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