1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd. 3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License. 5800b99b8Sopenharmony_ci * You may obtain a copy of the License at 6800b99b8Sopenharmony_ci * 7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8800b99b8Sopenharmony_ci * 9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and 13800b99b8Sopenharmony_ci * limitations under the License. 14800b99b8Sopenharmony_ci */ 15800b99b8Sopenharmony_ci 16800b99b8Sopenharmony_ci#include "dfx_memory.h" 17800b99b8Sopenharmony_ci#include <algorithm> 18800b99b8Sopenharmony_ci#include <securec.h> 19800b99b8Sopenharmony_ci#if is_ohos && !is_mingw 20800b99b8Sopenharmony_ci#include <sys/uio.h> 21800b99b8Sopenharmony_ci#endif 22800b99b8Sopenharmony_ci#include "dfx_define.h" 23800b99b8Sopenharmony_ci#include "dfx_errors.h" 24800b99b8Sopenharmony_ci#include "dfx_log.h" 25800b99b8Sopenharmony_ci#include "dwarf_define.h" 26800b99b8Sopenharmony_ci 27800b99b8Sopenharmony_cinamespace OHOS { 28800b99b8Sopenharmony_cinamespace HiviewDFX { 29800b99b8Sopenharmony_cinamespace { 30800b99b8Sopenharmony_ci#undef LOG_DOMAIN 31800b99b8Sopenharmony_ci#undef LOG_TAG 32800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11 33800b99b8Sopenharmony_ci#define LOG_TAG "DfxMemory" 34800b99b8Sopenharmony_ci 35800b99b8Sopenharmony_cistatic const int SEVEN_BIT_OFFSET = 7; 36800b99b8Sopenharmony_cistatic const int TWO_BYTE_SIZE = 2; 37800b99b8Sopenharmony_cistatic const int FOUR_BYTE_SIZE = 4; 38800b99b8Sopenharmony_cistatic const int EIGHT_BYTE_SIZE = 8; 39800b99b8Sopenharmony_ci} 40800b99b8Sopenharmony_ci 41800b99b8Sopenharmony_cibool DfxMemory::ReadReg(int regIdx, uintptr_t *val) 42800b99b8Sopenharmony_ci{ 43800b99b8Sopenharmony_ci if (acc_ != nullptr && acc_->AccessReg(regIdx, val, ctx_) == UNW_ERROR_NONE) { 44800b99b8Sopenharmony_ci return true; 45800b99b8Sopenharmony_ci } 46800b99b8Sopenharmony_ci return false; 47800b99b8Sopenharmony_ci} 48800b99b8Sopenharmony_ci 49800b99b8Sopenharmony_cibool DfxMemory::ReadMem(uintptr_t addr, uintptr_t *val) 50800b99b8Sopenharmony_ci{ 51800b99b8Sopenharmony_ci if (acc_ != nullptr && acc_->AccessMem(addr, val, ctx_) == UNW_ERROR_NONE) { 52800b99b8Sopenharmony_ci return true; 53800b99b8Sopenharmony_ci } 54800b99b8Sopenharmony_ci return false; 55800b99b8Sopenharmony_ci} 56800b99b8Sopenharmony_ci 57800b99b8Sopenharmony_cisize_t DfxMemory::Read(uintptr_t& addr, void* val, size_t size, bool incre) 58800b99b8Sopenharmony_ci{ 59800b99b8Sopenharmony_ci uintptr_t tmpAddr = addr; 60800b99b8Sopenharmony_ci uint64_t maxSize; 61800b99b8Sopenharmony_ci if (val == nullptr || __builtin_add_overflow(tmpAddr, size, &maxSize)) { 62800b99b8Sopenharmony_ci DFXLOGE("val is nullptr or size(%{public}zu) overflow", size); 63800b99b8Sopenharmony_ci return 0; 64800b99b8Sopenharmony_ci } 65800b99b8Sopenharmony_ci size_t bytesRead = 0; 66800b99b8Sopenharmony_ci uintptr_t tmpVal; 67800b99b8Sopenharmony_ci if (alignAddr_ && (alignBytes_ != 0)) { 68800b99b8Sopenharmony_ci size_t alignBytes = tmpAddr & (static_cast<size_t>(alignBytes_) - 1); 69800b99b8Sopenharmony_ci if (alignBytes != 0) { 70800b99b8Sopenharmony_ci uintptr_t alignedAddr = tmpAddr & (~(static_cast<uintptr_t>(alignBytes_)) - 1); 71800b99b8Sopenharmony_ci DFXLOGU("alignBytes: %{public}zu, alignedAddr: %{public}" PRIx64 "", alignBytes, 72800b99b8Sopenharmony_ci static_cast<uint64_t>(alignedAddr)); 73800b99b8Sopenharmony_ci if (!ReadMem(alignedAddr, &tmpVal)) { 74800b99b8Sopenharmony_ci return bytesRead; 75800b99b8Sopenharmony_ci } 76800b99b8Sopenharmony_ci uintptr_t valp = static_cast<uintptr_t>(tmpVal); 77800b99b8Sopenharmony_ci size_t copyBytes = std::min(static_cast<size_t>(alignBytes_) - alignBytes, size); 78800b99b8Sopenharmony_ci if (memcpy_s(val, copyBytes, reinterpret_cast<uint8_t*>(&valp) + alignBytes, copyBytes) != 0) { 79800b99b8Sopenharmony_ci return bytesRead; 80800b99b8Sopenharmony_ci } 81800b99b8Sopenharmony_ci tmpAddr += copyBytes; 82800b99b8Sopenharmony_ci val = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(val) + copyBytes); 83800b99b8Sopenharmony_ci size -= copyBytes; 84800b99b8Sopenharmony_ci bytesRead += copyBytes; 85800b99b8Sopenharmony_ci } 86800b99b8Sopenharmony_ci } 87800b99b8Sopenharmony_ci for (size_t i = 0; i < size / sizeof(uintptr_t); i++) { 88800b99b8Sopenharmony_ci if (!ReadMem(tmpAddr, &tmpVal) || memcpy_s(val, sizeof(uintptr_t), &tmpVal, sizeof(uintptr_t)) != 0) { 89800b99b8Sopenharmony_ci return bytesRead; 90800b99b8Sopenharmony_ci } 91800b99b8Sopenharmony_ci val = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(val) + sizeof(uintptr_t)); 92800b99b8Sopenharmony_ci tmpAddr += sizeof(uintptr_t); 93800b99b8Sopenharmony_ci bytesRead += sizeof(uintptr_t); 94800b99b8Sopenharmony_ci } 95800b99b8Sopenharmony_ci size_t leftOver = size & (sizeof(uintptr_t) - 1); 96800b99b8Sopenharmony_ci if (leftOver) { 97800b99b8Sopenharmony_ci if (!ReadMem(tmpAddr, &tmpVal) || memcpy_s(val, leftOver, &tmpVal, leftOver) != 0) { 98800b99b8Sopenharmony_ci return bytesRead; 99800b99b8Sopenharmony_ci } 100800b99b8Sopenharmony_ci tmpAddr += leftOver; 101800b99b8Sopenharmony_ci bytesRead += leftOver; 102800b99b8Sopenharmony_ci } 103800b99b8Sopenharmony_ci if (incre) { 104800b99b8Sopenharmony_ci addr = tmpAddr; 105800b99b8Sopenharmony_ci } 106800b99b8Sopenharmony_ci return bytesRead; 107800b99b8Sopenharmony_ci} 108800b99b8Sopenharmony_ci 109800b99b8Sopenharmony_cibool DfxMemory::ReadU8(uintptr_t& addr, uint8_t *val, bool incre) 110800b99b8Sopenharmony_ci{ 111800b99b8Sopenharmony_ci if (Read(addr, val, sizeof(uint8_t), incre) == sizeof(uint8_t)) { 112800b99b8Sopenharmony_ci return true; 113800b99b8Sopenharmony_ci } 114800b99b8Sopenharmony_ci return false; 115800b99b8Sopenharmony_ci} 116800b99b8Sopenharmony_ci 117800b99b8Sopenharmony_cibool DfxMemory::ReadU16(uintptr_t& addr, uint16_t *val, bool incre) 118800b99b8Sopenharmony_ci{ 119800b99b8Sopenharmony_ci if (Read(addr, val, sizeof(uint16_t), incre) == sizeof(uint16_t)) { 120800b99b8Sopenharmony_ci return true; 121800b99b8Sopenharmony_ci } 122800b99b8Sopenharmony_ci return false; 123800b99b8Sopenharmony_ci} 124800b99b8Sopenharmony_ci 125800b99b8Sopenharmony_cibool DfxMemory::ReadU32(uintptr_t& addr, uint32_t *val, bool incre) 126800b99b8Sopenharmony_ci{ 127800b99b8Sopenharmony_ci if (Read(addr, val, sizeof(uint32_t), incre) == sizeof(uint32_t)) { 128800b99b8Sopenharmony_ci return true; 129800b99b8Sopenharmony_ci } 130800b99b8Sopenharmony_ci return false; 131800b99b8Sopenharmony_ci} 132800b99b8Sopenharmony_ci 133800b99b8Sopenharmony_cibool DfxMemory::ReadU64(uintptr_t& addr, uint64_t *val, bool incre) 134800b99b8Sopenharmony_ci{ 135800b99b8Sopenharmony_ci if (Read(addr, val, sizeof(uint64_t), incre) == sizeof(uint64_t)) { 136800b99b8Sopenharmony_ci return true; 137800b99b8Sopenharmony_ci } 138800b99b8Sopenharmony_ci return false; 139800b99b8Sopenharmony_ci} 140800b99b8Sopenharmony_ci 141800b99b8Sopenharmony_cibool DfxMemory::ReadUptr(uintptr_t& addr, uintptr_t *val, bool incre) 142800b99b8Sopenharmony_ci{ 143800b99b8Sopenharmony_ci if (Read(addr, val, sizeof(uintptr_t), incre) == sizeof(uintptr_t)) { 144800b99b8Sopenharmony_ci return true; 145800b99b8Sopenharmony_ci } 146800b99b8Sopenharmony_ci return false; 147800b99b8Sopenharmony_ci} 148800b99b8Sopenharmony_ci 149800b99b8Sopenharmony_cibool DfxMemory::ReadString(uintptr_t& addr, std::string* str, size_t maxSize, bool incre) 150800b99b8Sopenharmony_ci{ 151800b99b8Sopenharmony_ci if (str == nullptr) { 152800b99b8Sopenharmony_ci return false; 153800b99b8Sopenharmony_ci } 154800b99b8Sopenharmony_ci char buf[NAME_BUF_LEN]; 155800b99b8Sopenharmony_ci size_t size = 0; 156800b99b8Sopenharmony_ci uintptr_t ptr = addr; 157800b99b8Sopenharmony_ci for (size_t offset = 0; offset < maxSize; offset += size) { 158800b99b8Sopenharmony_ci size_t readn = std::min(sizeof(buf), maxSize - offset); 159800b99b8Sopenharmony_ci ptr = ptr + offset; 160800b99b8Sopenharmony_ci size = Read(ptr, buf, readn, false); 161800b99b8Sopenharmony_ci if (size == 0) { 162800b99b8Sopenharmony_ci return false; 163800b99b8Sopenharmony_ci } 164800b99b8Sopenharmony_ci size_t length = strnlen(buf, size); 165800b99b8Sopenharmony_ci if (length < size) { 166800b99b8Sopenharmony_ci if (offset == 0) { 167800b99b8Sopenharmony_ci str->assign(buf, length); 168800b99b8Sopenharmony_ci return true; 169800b99b8Sopenharmony_ci } else { 170800b99b8Sopenharmony_ci str->assign(offset + length, '\0'); 171800b99b8Sopenharmony_ci Read(addr, (void*)str->data(), str->size(), false); 172800b99b8Sopenharmony_ci return true; 173800b99b8Sopenharmony_ci } 174800b99b8Sopenharmony_ci } 175800b99b8Sopenharmony_ci } 176800b99b8Sopenharmony_ci if (incre && str != nullptr) { 177800b99b8Sopenharmony_ci addr += str->size(); 178800b99b8Sopenharmony_ci } 179800b99b8Sopenharmony_ci return false; 180800b99b8Sopenharmony_ci} 181800b99b8Sopenharmony_ci 182800b99b8Sopenharmony_cibool DfxMemory::ReadPrel31(uintptr_t& addr, uintptr_t *val) 183800b99b8Sopenharmony_ci{ 184800b99b8Sopenharmony_ci uintptr_t offset; 185800b99b8Sopenharmony_ci if (!ReadUptr(addr, &offset, false)) { 186800b99b8Sopenharmony_ci return false; 187800b99b8Sopenharmony_ci } 188800b99b8Sopenharmony_ci offset = static_cast<uintptr_t>(static_cast<int32_t>(offset << 1) >> 1); 189800b99b8Sopenharmony_ci *val = addr + offset; 190800b99b8Sopenharmony_ci return true; 191800b99b8Sopenharmony_ci} 192800b99b8Sopenharmony_ci 193800b99b8Sopenharmony_ciuint64_t DfxMemory::ReadUleb128(uintptr_t& addr) 194800b99b8Sopenharmony_ci{ 195800b99b8Sopenharmony_ci uint64_t val = 0; 196800b99b8Sopenharmony_ci uint64_t shift = 0; 197800b99b8Sopenharmony_ci uint8_t u8 = 0; 198800b99b8Sopenharmony_ci do { 199800b99b8Sopenharmony_ci if (!ReadU8(addr, &u8, true)) { 200800b99b8Sopenharmony_ci break; 201800b99b8Sopenharmony_ci } 202800b99b8Sopenharmony_ci 203800b99b8Sopenharmony_ci val |= static_cast<uint64_t>(u8 & 0x7f) << shift; 204800b99b8Sopenharmony_ci shift += SEVEN_BIT_OFFSET; 205800b99b8Sopenharmony_ci } while (u8 & 0x80); 206800b99b8Sopenharmony_ci return val; 207800b99b8Sopenharmony_ci} 208800b99b8Sopenharmony_ci 209800b99b8Sopenharmony_ciint64_t DfxMemory::ReadSleb128(uintptr_t& addr) 210800b99b8Sopenharmony_ci{ 211800b99b8Sopenharmony_ci uint64_t val = 0; 212800b99b8Sopenharmony_ci uint64_t shift = 0; 213800b99b8Sopenharmony_ci uint8_t byte = 0; 214800b99b8Sopenharmony_ci do { 215800b99b8Sopenharmony_ci if (!ReadU8(addr, &byte, true)) { 216800b99b8Sopenharmony_ci break; 217800b99b8Sopenharmony_ci } 218800b99b8Sopenharmony_ci 219800b99b8Sopenharmony_ci val |= static_cast<uint64_t>(byte & 0x7f) << shift; 220800b99b8Sopenharmony_ci shift += SEVEN_BIT_OFFSET; 221800b99b8Sopenharmony_ci } while (byte & 0x80); 222800b99b8Sopenharmony_ci 223800b99b8Sopenharmony_ci if ((byte & 0x40) != 0) { 224800b99b8Sopenharmony_ci val |= (-1ULL) << shift; 225800b99b8Sopenharmony_ci } 226800b99b8Sopenharmony_ci return static_cast<int64_t>(val); 227800b99b8Sopenharmony_ci} 228800b99b8Sopenharmony_ci 229800b99b8Sopenharmony_cisize_t DfxMemory::GetEncodedSize(uint8_t encoding) 230800b99b8Sopenharmony_ci{ 231800b99b8Sopenharmony_ci switch (encoding & 0x0f) { 232800b99b8Sopenharmony_ci case DW_EH_PE_absptr: 233800b99b8Sopenharmony_ci return sizeof(uintptr_t); 234800b99b8Sopenharmony_ci case DW_EH_PE_udata1: 235800b99b8Sopenharmony_ci case DW_EH_PE_sdata1: 236800b99b8Sopenharmony_ci return 1; 237800b99b8Sopenharmony_ci case DW_EH_PE_udata2: 238800b99b8Sopenharmony_ci case DW_EH_PE_sdata2: 239800b99b8Sopenharmony_ci return TWO_BYTE_SIZE; 240800b99b8Sopenharmony_ci case DW_EH_PE_udata4: 241800b99b8Sopenharmony_ci case DW_EH_PE_sdata4: 242800b99b8Sopenharmony_ci return FOUR_BYTE_SIZE; 243800b99b8Sopenharmony_ci case DW_EH_PE_udata8: 244800b99b8Sopenharmony_ci case DW_EH_PE_sdata8: 245800b99b8Sopenharmony_ci return EIGHT_BYTE_SIZE; 246800b99b8Sopenharmony_ci case DW_EH_PE_uleb128: 247800b99b8Sopenharmony_ci case DW_EH_PE_sleb128: 248800b99b8Sopenharmony_ci default: 249800b99b8Sopenharmony_ci return 0; 250800b99b8Sopenharmony_ci } 251800b99b8Sopenharmony_ci} 252800b99b8Sopenharmony_ci 253800b99b8Sopenharmony_ciuintptr_t DfxMemory::ReadEncodedValue(uintptr_t& addr, uint8_t encoding) 254800b99b8Sopenharmony_ci{ 255800b99b8Sopenharmony_ci uintptr_t startAddr = addr; 256800b99b8Sopenharmony_ci uintptr_t val = 0; 257800b99b8Sopenharmony_ci if (encoding == DW_EH_PE_omit) { 258800b99b8Sopenharmony_ci return val; 259800b99b8Sopenharmony_ci } else if (encoding == DW_EH_PE_aligned) { 260800b99b8Sopenharmony_ci if (__builtin_add_overflow(addr, sizeof(uintptr_t) - 1, &addr)) { 261800b99b8Sopenharmony_ci return val; 262800b99b8Sopenharmony_ci } 263800b99b8Sopenharmony_ci addr &= -sizeof(uintptr_t); 264800b99b8Sopenharmony_ci ReadUptr(addr, &val, true); 265800b99b8Sopenharmony_ci return val; 266800b99b8Sopenharmony_ci } 267800b99b8Sopenharmony_ci 268800b99b8Sopenharmony_ci switch (encoding & DW_EH_PE_FORMAT_MASK) { 269800b99b8Sopenharmony_ci case DW_EH_PE_absptr: 270800b99b8Sopenharmony_ci ReadUptr(addr, &val, true); 271800b99b8Sopenharmony_ci return val; 272800b99b8Sopenharmony_ci case DW_EH_PE_uleb128: 273800b99b8Sopenharmony_ci val = static_cast<uintptr_t>(ReadUleb128(addr)); 274800b99b8Sopenharmony_ci break; 275800b99b8Sopenharmony_ci case DW_EH_PE_sleb128: 276800b99b8Sopenharmony_ci val = static_cast<uintptr_t>(ReadSleb128(addr)); 277800b99b8Sopenharmony_ci break; 278800b99b8Sopenharmony_ci case DW_EH_PE_udata1: { 279800b99b8Sopenharmony_ci uint8_t tmp = 0; 280800b99b8Sopenharmony_ci ReadU8(addr, &tmp, true); 281800b99b8Sopenharmony_ci val = static_cast<uintptr_t>(tmp); 282800b99b8Sopenharmony_ci } 283800b99b8Sopenharmony_ci break; 284800b99b8Sopenharmony_ci case DW_EH_PE_sdata1: { 285800b99b8Sopenharmony_ci int8_t tmp = 0; 286800b99b8Sopenharmony_ci ReadS8(addr, &tmp, true); 287800b99b8Sopenharmony_ci val = static_cast<uintptr_t>(tmp); 288800b99b8Sopenharmony_ci } 289800b99b8Sopenharmony_ci break; 290800b99b8Sopenharmony_ci case DW_EH_PE_udata2: { 291800b99b8Sopenharmony_ci uint16_t tmp = 0; 292800b99b8Sopenharmony_ci ReadU16(addr, &tmp, true); 293800b99b8Sopenharmony_ci val = static_cast<uintptr_t>(tmp); 294800b99b8Sopenharmony_ci } 295800b99b8Sopenharmony_ci break; 296800b99b8Sopenharmony_ci case DW_EH_PE_sdata2: { 297800b99b8Sopenharmony_ci int16_t tmp = 0; 298800b99b8Sopenharmony_ci ReadS16(addr, &tmp, true); 299800b99b8Sopenharmony_ci val = static_cast<uintptr_t>(tmp); 300800b99b8Sopenharmony_ci } 301800b99b8Sopenharmony_ci break; 302800b99b8Sopenharmony_ci case DW_EH_PE_udata4: { 303800b99b8Sopenharmony_ci uint32_t tmp = 0; 304800b99b8Sopenharmony_ci ReadU32(addr, &tmp, true); 305800b99b8Sopenharmony_ci val = static_cast<uintptr_t>(tmp); 306800b99b8Sopenharmony_ci } 307800b99b8Sopenharmony_ci break; 308800b99b8Sopenharmony_ci case DW_EH_PE_sdata4: { 309800b99b8Sopenharmony_ci int32_t tmp = 0; 310800b99b8Sopenharmony_ci ReadS32(addr, &tmp, true); 311800b99b8Sopenharmony_ci val = static_cast<uintptr_t>(tmp); 312800b99b8Sopenharmony_ci } 313800b99b8Sopenharmony_ci break; 314800b99b8Sopenharmony_ci case DW_EH_PE_udata8: { 315800b99b8Sopenharmony_ci uint64_t tmp = 0; 316800b99b8Sopenharmony_ci ReadU64(addr, &tmp, true); 317800b99b8Sopenharmony_ci val = static_cast<uintptr_t>(tmp); 318800b99b8Sopenharmony_ci } 319800b99b8Sopenharmony_ci break; 320800b99b8Sopenharmony_ci case DW_EH_PE_sdata8: { 321800b99b8Sopenharmony_ci int64_t tmp = 0; 322800b99b8Sopenharmony_ci ReadS64(addr, &tmp, true); 323800b99b8Sopenharmony_ci val = static_cast<uintptr_t>(tmp); 324800b99b8Sopenharmony_ci } 325800b99b8Sopenharmony_ci break; 326800b99b8Sopenharmony_ci default: 327800b99b8Sopenharmony_ci DFXLOGW("Unexpected encoding format 0x%{public}x", encoding & DW_EH_PE_FORMAT_MASK); 328800b99b8Sopenharmony_ci break; 329800b99b8Sopenharmony_ci } 330800b99b8Sopenharmony_ci 331800b99b8Sopenharmony_ci switch (encoding & DW_EH_PE_APPL_MASK) { 332800b99b8Sopenharmony_ci case DW_EH_PE_pcrel: 333800b99b8Sopenharmony_ci val += startAddr; 334800b99b8Sopenharmony_ci break; 335800b99b8Sopenharmony_ci case DW_EH_PE_textrel: 336800b99b8Sopenharmony_ci DFXLOGE("XXX For now we don't support text-rel values"); 337800b99b8Sopenharmony_ci break; 338800b99b8Sopenharmony_ci case DW_EH_PE_datarel: 339800b99b8Sopenharmony_ci val += dataOffset_; 340800b99b8Sopenharmony_ci break; 341800b99b8Sopenharmony_ci case DW_EH_PE_funcrel: 342800b99b8Sopenharmony_ci val += funcOffset_; 343800b99b8Sopenharmony_ci break; 344800b99b8Sopenharmony_ci default: 345800b99b8Sopenharmony_ci break; 346800b99b8Sopenharmony_ci } 347800b99b8Sopenharmony_ci 348800b99b8Sopenharmony_ci if (encoding & DW_EH_PE_indirect) { 349800b99b8Sopenharmony_ci uintptr_t indirectAddr = val; 350800b99b8Sopenharmony_ci ReadUptr(indirectAddr, &val, true); 351800b99b8Sopenharmony_ci } 352800b99b8Sopenharmony_ci return val; 353800b99b8Sopenharmony_ci} 354800b99b8Sopenharmony_ci#if is_ohos && !is_mingw 355800b99b8Sopenharmony_cisize_t DfxMemory::ReadProcMemByPid(const pid_t pid, const uint64_t addr, void* data, size_t size) 356800b99b8Sopenharmony_ci{ 357800b99b8Sopenharmony_ci constexpr size_t maxSize = 64; 358800b99b8Sopenharmony_ci struct iovec RemoteIovs[maxSize]; 359800b99b8Sopenharmony_ci 360800b99b8Sopenharmony_ci uint64_t cur = addr; 361800b99b8Sopenharmony_ci size_t totalRead = 0; 362800b99b8Sopenharmony_ci struct iovec dataIov = { 363800b99b8Sopenharmony_ci .iov_base = &reinterpret_cast<uint8_t*>(data)[totalRead], 364800b99b8Sopenharmony_ci .iov_len = size, 365800b99b8Sopenharmony_ci }; 366800b99b8Sopenharmony_ci size_t iovecsIndex = 0; 367800b99b8Sopenharmony_ci while (size > 0) { 368800b99b8Sopenharmony_ci if (cur >= UINTPTR_MAX) { 369800b99b8Sopenharmony_ci return totalRead; 370800b99b8Sopenharmony_ci } 371800b99b8Sopenharmony_ci RemoteIovs[iovecsIndex].iov_base = reinterpret_cast<void*>(cur); 372800b99b8Sopenharmony_ci uintptr_t misalign = cur & static_cast<uint64_t>(getpagesize() - 1); 373800b99b8Sopenharmony_ci size_t iovLen = std::min(getpagesize() - misalign, size); 374800b99b8Sopenharmony_ci 375800b99b8Sopenharmony_ci size -= iovLen; 376800b99b8Sopenharmony_ci if (__builtin_add_overflow(cur, iovLen, &cur)) { 377800b99b8Sopenharmony_ci return totalRead; 378800b99b8Sopenharmony_ci } 379800b99b8Sopenharmony_ci 380800b99b8Sopenharmony_ci RemoteIovs[iovecsIndex].iov_len = iovLen; 381800b99b8Sopenharmony_ci ++iovecsIndex; 382800b99b8Sopenharmony_ci if (iovecsIndex >= maxSize || size <= 0) { 383800b99b8Sopenharmony_ci ssize_t count = process_vm_readv(pid, &dataIov, 1, RemoteIovs, iovecsIndex, 0); 384800b99b8Sopenharmony_ci if (count == -1) { 385800b99b8Sopenharmony_ci return totalRead; 386800b99b8Sopenharmony_ci } 387800b99b8Sopenharmony_ci totalRead += static_cast<size_t>(count); 388800b99b8Sopenharmony_ci if (iovecsIndex >= maxSize) { 389800b99b8Sopenharmony_ci iovecsIndex -= maxSize; 390800b99b8Sopenharmony_ci } 391800b99b8Sopenharmony_ci dataIov.iov_base = &reinterpret_cast<uint8_t*>(data)[totalRead]; 392800b99b8Sopenharmony_ci dataIov.iov_len = size; 393800b99b8Sopenharmony_ci } 394800b99b8Sopenharmony_ci } 395800b99b8Sopenharmony_ci 396800b99b8Sopenharmony_ci return totalRead; 397800b99b8Sopenharmony_ci} 398800b99b8Sopenharmony_ci#endif 399800b99b8Sopenharmony_ci} // namespace HiviewDFX 400800b99b8Sopenharmony_ci} // namespace OHOS 401