1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2023 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 "dwarf_section.h"
17800b99b8Sopenharmony_ci#include <securec.h>
18800b99b8Sopenharmony_ci#include "dfx_log.h"
19800b99b8Sopenharmony_ci#include "dfx_trace_dlsym.h"
20800b99b8Sopenharmony_ci#include "dwarf_cfa_instructions.h"
21800b99b8Sopenharmony_ci
22800b99b8Sopenharmony_cinamespace OHOS {
23800b99b8Sopenharmony_cinamespace HiviewDFX {
24800b99b8Sopenharmony_cinamespace {
25800b99b8Sopenharmony_ci#undef LOG_DOMAIN
26800b99b8Sopenharmony_ci#undef LOG_TAG
27800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11
28800b99b8Sopenharmony_ci#define LOG_TAG "DfxDwarfSection"
29800b99b8Sopenharmony_ci}
30800b99b8Sopenharmony_ci
31800b99b8Sopenharmony_ciDwarfSection::DwarfSection(std::shared_ptr<DfxMemory> memory) : memory_(memory)
32800b99b8Sopenharmony_ci{
33800b99b8Sopenharmony_ci    (void)memset_s(&lastErrorData_, sizeof(UnwindErrorData), 0, sizeof(UnwindErrorData));
34800b99b8Sopenharmony_ci}
35800b99b8Sopenharmony_ci
36800b99b8Sopenharmony_cibool DwarfSection::LinearSearchEntry(uintptr_t pc, struct UnwindTableInfo uti, struct UnwindEntryInfo& uei)
37800b99b8Sopenharmony_ci{
38800b99b8Sopenharmony_ci    DFX_TRACE_SCOPED_DLSYM("DwarfSectionLinearSearchEntry");
39800b99b8Sopenharmony_ci    uintptr_t fdeCount = uti.tableLen;
40800b99b8Sopenharmony_ci    uintptr_t tableData = uti.tableData;
41800b99b8Sopenharmony_ci    DFXLOGU("LinearSearchEntry tableData:%{public}p, tableLen: %{public}u", (void*)tableData, (uint32_t)fdeCount);
42800b99b8Sopenharmony_ci    uintptr_t i = 0, ptr = tableData;
43800b99b8Sopenharmony_ci    FrameDescEntry fdeInfo;
44800b99b8Sopenharmony_ci    while (i++ < fdeCount && ptr < uti.endPc) {
45800b99b8Sopenharmony_ci        uintptr_t fdeAddr = ptr;
46800b99b8Sopenharmony_ci        if (GetCieOrFde(ptr, fdeInfo)) {
47800b99b8Sopenharmony_ci            if (pc >= fdeInfo.pcStart && pc < fdeInfo.pcEnd) {
48800b99b8Sopenharmony_ci                DFXLOGU("Fde entry addr: %{public}" PRIx64 "", (uint64_t)fdeAddr);
49800b99b8Sopenharmony_ci                uei.unwindInfo = (void *)(fdeAddr);
50800b99b8Sopenharmony_ci                uei.format = UNW_INFO_FORMAT_REMOTE_TABLE;
51800b99b8Sopenharmony_ci                return true;
52800b99b8Sopenharmony_ci            }
53800b99b8Sopenharmony_ci        } else {
54800b99b8Sopenharmony_ci            break;
55800b99b8Sopenharmony_ci        }
56800b99b8Sopenharmony_ci    }
57800b99b8Sopenharmony_ci    return false;
58800b99b8Sopenharmony_ci}
59800b99b8Sopenharmony_ci
60800b99b8Sopenharmony_cibool DwarfSection::SearchEntry(uintptr_t pc, struct UnwindTableInfo uti, struct UnwindEntryInfo& uei)
61800b99b8Sopenharmony_ci{
62800b99b8Sopenharmony_ci    DFX_TRACE_SCOPED_DLSYM("DwarfSectionSearchEntry");
63800b99b8Sopenharmony_ci    MAYBE_UNUSED auto segbase = uti.segbase;
64800b99b8Sopenharmony_ci    uintptr_t fdeCount = uti.tableLen;
65800b99b8Sopenharmony_ci    uintptr_t tableData = uti.tableData;
66800b99b8Sopenharmony_ci    DFXLOGU("SearchEntry pc: %{public}p segbase:%{public}p, tableData:%{public}p, tableLen: %{public}u",
67800b99b8Sopenharmony_ci        (void*)pc, (void*)segbase, (void*)tableData, (uint32_t)fdeCount);
68800b99b8Sopenharmony_ci
69800b99b8Sopenharmony_ci    // do binary search, encode is stored in symbol file, we have no means to find?
70800b99b8Sopenharmony_ci    // hard code for 1b DwarfEncoding
71800b99b8Sopenharmony_ci    uintptr_t ptr = 0;
72800b99b8Sopenharmony_ci    uintptr_t entry = 0;
73800b99b8Sopenharmony_ci    uintptr_t low = 0;
74800b99b8Sopenharmony_ci    uintptr_t high = fdeCount;
75800b99b8Sopenharmony_ci    DwarfTableEntry dwarfTableEntry;
76800b99b8Sopenharmony_ci    while (low < high) {
77800b99b8Sopenharmony_ci        uintptr_t cur = (low + high) / 2; // 2 : binary search divided parameter
78800b99b8Sopenharmony_ci        ptr = (uintptr_t) tableData + cur * sizeof(DwarfTableEntry);
79800b99b8Sopenharmony_ci        if (!memory_->ReadS32(ptr, &dwarfTableEntry.startPc, true)) {
80800b99b8Sopenharmony_ci            lastErrorData_.SetAddrAndCode(ptr, UNW_ERROR_INVALID_MEMORY);
81800b99b8Sopenharmony_ci            return false;
82800b99b8Sopenharmony_ci        }
83800b99b8Sopenharmony_ci        uintptr_t startPc = static_cast<uintptr_t>(dwarfTableEntry.startPc) + segbase;
84800b99b8Sopenharmony_ci        if (startPc == pc) {
85800b99b8Sopenharmony_ci            if (!memory_->ReadS32(ptr, &dwarfTableEntry.fdeOffset, true)) {
86800b99b8Sopenharmony_ci                lastErrorData_.SetAddrAndCode(ptr, UNW_ERROR_INVALID_MEMORY);
87800b99b8Sopenharmony_ci                return false;
88800b99b8Sopenharmony_ci            }
89800b99b8Sopenharmony_ci            entry = static_cast<uintptr_t>(dwarfTableEntry.fdeOffset) + segbase;
90800b99b8Sopenharmony_ci            break;
91800b99b8Sopenharmony_ci        } else if (pc < startPc) {
92800b99b8Sopenharmony_ci            high = cur;
93800b99b8Sopenharmony_ci        } else {
94800b99b8Sopenharmony_ci            low = cur + 1;
95800b99b8Sopenharmony_ci        }
96800b99b8Sopenharmony_ci    }
97800b99b8Sopenharmony_ci
98800b99b8Sopenharmony_ci    if (entry == 0) {
99800b99b8Sopenharmony_ci        if (high != 0) {
100800b99b8Sopenharmony_ci            ptr = static_cast<uintptr_t>(tableData) + (high - 1) * sizeof(DwarfTableEntry) + 4; // 4 : four bytes
101800b99b8Sopenharmony_ci            if (!memory_->ReadS32(ptr, &dwarfTableEntry.fdeOffset, true)) {
102800b99b8Sopenharmony_ci                lastErrorData_.SetAddrAndCode(ptr, UNW_ERROR_INVALID_MEMORY);
103800b99b8Sopenharmony_ci                return false;
104800b99b8Sopenharmony_ci            }
105800b99b8Sopenharmony_ci            entry = static_cast<uintptr_t>(dwarfTableEntry.fdeOffset) + segbase;
106800b99b8Sopenharmony_ci        } else {
107800b99b8Sopenharmony_ci            return false;
108800b99b8Sopenharmony_ci        }
109800b99b8Sopenharmony_ci    }
110800b99b8Sopenharmony_ci
111800b99b8Sopenharmony_ci    DFXLOGU("Fde entry addr: %{public}" PRIx64 "", (uint64_t)entry);
112800b99b8Sopenharmony_ci    uei.unwindInfo = (void *)(entry);
113800b99b8Sopenharmony_ci    uei.format = UNW_INFO_FORMAT_REMOTE_TABLE;
114800b99b8Sopenharmony_ci    return true;
115800b99b8Sopenharmony_ci}
116800b99b8Sopenharmony_ci
117800b99b8Sopenharmony_cibool DwarfSection::Step(uintptr_t pc, uintptr_t fdeAddr, std::shared_ptr<RegLocState> rs)
118800b99b8Sopenharmony_ci{
119800b99b8Sopenharmony_ci    DFX_TRACE_SCOPED_DLSYM("DwarfSectionStep");
120800b99b8Sopenharmony_ci    FrameDescEntry fdeInfo;
121800b99b8Sopenharmony_ci    if (!ParseFde(fdeAddr, fdeAddr, fdeInfo)) {
122800b99b8Sopenharmony_ci        DFXLOGE("Failed to parse fde?");
123800b99b8Sopenharmony_ci        lastErrorData_.SetAddrAndCode(fdeAddr, UNW_ERROR_DWARF_INVALID_FDE);
124800b99b8Sopenharmony_ci        return false;
125800b99b8Sopenharmony_ci    }
126800b99b8Sopenharmony_ci
127800b99b8Sopenharmony_ci    if (pc < fdeInfo.pcStart || pc >= fdeInfo.pcEnd) {
128800b99b8Sopenharmony_ci        DFXLOGU("pc: %{public}p, FDE start: %{public}p, end: %{public}p",
129800b99b8Sopenharmony_ci            (void*)pc, (void*)fdeInfo.pcStart, (void*)fdeInfo.pcEnd);
130800b99b8Sopenharmony_ci        return false;
131800b99b8Sopenharmony_ci    }
132800b99b8Sopenharmony_ci    DwarfCfaInstructions dwarfInstructions(memory_);
133800b99b8Sopenharmony_ci    if (!dwarfInstructions.Parse(pc, fdeInfo, *(rs.get()))) {
134800b99b8Sopenharmony_ci        DFXLOGE("Failed to parse dwarf instructions?");
135800b99b8Sopenharmony_ci        lastErrorData_.SetAddrAndCode(pc, UNW_ERROR_DWARF_INVALID_INSTR);
136800b99b8Sopenharmony_ci        return false;
137800b99b8Sopenharmony_ci    }
138800b99b8Sopenharmony_ci    return true;
139800b99b8Sopenharmony_ci}
140800b99b8Sopenharmony_ci
141800b99b8Sopenharmony_cibool DwarfSection::GetCieOrFde(uintptr_t &addr, FrameDescEntry &fdeInfo)
142800b99b8Sopenharmony_ci{
143800b99b8Sopenharmony_ci    uintptr_t ptr = addr;
144800b99b8Sopenharmony_ci    bool isCieEntry = false;
145800b99b8Sopenharmony_ci    ParseCieOrFdeHeader(ptr, fdeInfo, isCieEntry);
146800b99b8Sopenharmony_ci
147800b99b8Sopenharmony_ci    if (isCieEntry) {
148800b99b8Sopenharmony_ci        if (!ParseCie(addr, ptr, fdeInfo.cie)) {
149800b99b8Sopenharmony_ci            DFXLOGE("Failed to Parse CIE?");
150800b99b8Sopenharmony_ci            return false;
151800b99b8Sopenharmony_ci        }
152800b99b8Sopenharmony_ci        addr = fdeInfo.cie.instructionsEnd;
153800b99b8Sopenharmony_ci    } else {
154800b99b8Sopenharmony_ci        if (!ParseFde(addr, ptr, fdeInfo)) {
155800b99b8Sopenharmony_ci            DFXLOGE("Failed to Parse FDE?");
156800b99b8Sopenharmony_ci            return false;
157800b99b8Sopenharmony_ci        }
158800b99b8Sopenharmony_ci        addr = fdeInfo.instructionsEnd;
159800b99b8Sopenharmony_ci    }
160800b99b8Sopenharmony_ci    return true;
161800b99b8Sopenharmony_ci}
162800b99b8Sopenharmony_ci
163800b99b8Sopenharmony_civoid DwarfSection::ParseCieOrFdeHeader(uintptr_t& ptr, FrameDescEntry &fdeInfo, bool& isCieEntry)
164800b99b8Sopenharmony_ci{
165800b99b8Sopenharmony_ci    uint32_t value32 = 0;
166800b99b8Sopenharmony_ci    memory_->ReadU32(ptr, &value32, true);
167800b99b8Sopenharmony_ci    uintptr_t ciePtr = 0;
168800b99b8Sopenharmony_ci    uintptr_t instructionsEnd = 0;
169800b99b8Sopenharmony_ci    if (value32 == static_cast<uint32_t>(-1)) {
170800b99b8Sopenharmony_ci        uint64_t value64;
171800b99b8Sopenharmony_ci        memory_->ReadU64(ptr, &value64, true);
172800b99b8Sopenharmony_ci        instructionsEnd = ptr + value64;
173800b99b8Sopenharmony_ci
174800b99b8Sopenharmony_ci        memory_->ReadU64(ptr, &value64, true);
175800b99b8Sopenharmony_ci        ciePtr = static_cast<uintptr_t>(value64);
176800b99b8Sopenharmony_ci        if (ciePtr == cie64Value_) {
177800b99b8Sopenharmony_ci            isCieEntry = true;
178800b99b8Sopenharmony_ci            fdeInfo.cie.instructionsEnd = instructionsEnd;
179800b99b8Sopenharmony_ci            fdeInfo.cie.pointerEncoding = DW_EH_PE_sdata8;
180800b99b8Sopenharmony_ci        } else {
181800b99b8Sopenharmony_ci            fdeInfo.instructionsEnd = instructionsEnd;
182800b99b8Sopenharmony_ci            fdeInfo.cieAddr = static_cast<uintptr_t>(ptr - ciePtr);
183800b99b8Sopenharmony_ci        }
184800b99b8Sopenharmony_ci        ptr += sizeof(uint64_t);
185800b99b8Sopenharmony_ci    } else {
186800b99b8Sopenharmony_ci        instructionsEnd = ptr + value32;
187800b99b8Sopenharmony_ci        memory_->ReadU32(ptr, &value32, false);
188800b99b8Sopenharmony_ci        ciePtr = static_cast<uintptr_t>(value32);
189800b99b8Sopenharmony_ci        if (ciePtr == cie32Value_) {
190800b99b8Sopenharmony_ci            isCieEntry = true;
191800b99b8Sopenharmony_ci            fdeInfo.cie.instructionsEnd = instructionsEnd;
192800b99b8Sopenharmony_ci            fdeInfo.cie.pointerEncoding = DW_EH_PE_sdata4;
193800b99b8Sopenharmony_ci        } else {
194800b99b8Sopenharmony_ci            fdeInfo.instructionsEnd = instructionsEnd;
195800b99b8Sopenharmony_ci            fdeInfo.cieAddr = static_cast<uintptr_t>(ptr - ciePtr);
196800b99b8Sopenharmony_ci        }
197800b99b8Sopenharmony_ci        ptr += sizeof(uint32_t);
198800b99b8Sopenharmony_ci    }
199800b99b8Sopenharmony_ci}
200800b99b8Sopenharmony_ci
201800b99b8Sopenharmony_cibool DwarfSection::ParseFde(uintptr_t fdeAddr, uintptr_t fdePtr, FrameDescEntry &fdeInfo)
202800b99b8Sopenharmony_ci{
203800b99b8Sopenharmony_ci    DFXLOGU("fdeAddr: %{public}" PRIx64 "", (uint64_t)fdeAddr);
204800b99b8Sopenharmony_ci    if (!fdeEntries_.empty()) {
205800b99b8Sopenharmony_ci        auto iter = fdeEntries_.find(fdeAddr);
206800b99b8Sopenharmony_ci        if (iter != fdeEntries_.end()) {
207800b99b8Sopenharmony_ci            fdeInfo = iter->second;
208800b99b8Sopenharmony_ci            return true;
209800b99b8Sopenharmony_ci        }
210800b99b8Sopenharmony_ci    }
211800b99b8Sopenharmony_ci
212800b99b8Sopenharmony_ci    if (fdeAddr == fdePtr) {
213800b99b8Sopenharmony_ci        bool isCieEntry = false;
214800b99b8Sopenharmony_ci        ParseCieOrFdeHeader(fdePtr, fdeInfo, isCieEntry);
215800b99b8Sopenharmony_ci        if (isCieEntry) {
216800b99b8Sopenharmony_ci            DFXLOGE("ParseFde error, is Cie Entry?");
217800b99b8Sopenharmony_ci            return false;
218800b99b8Sopenharmony_ci        }
219800b99b8Sopenharmony_ci    }
220800b99b8Sopenharmony_ci    if (!FillInFde(fdePtr, fdeInfo)) {
221800b99b8Sopenharmony_ci        DFXLOGE("ParseFde error, failed to fill FDE?");
222800b99b8Sopenharmony_ci        fdeEntries_.erase(fdeAddr);
223800b99b8Sopenharmony_ci        return false;
224800b99b8Sopenharmony_ci    }
225800b99b8Sopenharmony_ci    fdeEntries_[fdeAddr] = fdeInfo;
226800b99b8Sopenharmony_ci    return true;
227800b99b8Sopenharmony_ci}
228800b99b8Sopenharmony_ci
229800b99b8Sopenharmony_cibool DwarfSection::FillInFde(uintptr_t ptr, FrameDescEntry &fdeInfo)
230800b99b8Sopenharmony_ci{
231800b99b8Sopenharmony_ci    if (!ParseCie(fdeInfo.cieAddr, fdeInfo.cieAddr, fdeInfo.cie)) {
232800b99b8Sopenharmony_ci        DFXLOGE("Failed to parse CIE?");
233800b99b8Sopenharmony_ci        return false;
234800b99b8Sopenharmony_ci    }
235800b99b8Sopenharmony_ci
236800b99b8Sopenharmony_ci    if (fdeInfo.cie.segmentSize != 0) {
237800b99b8Sopenharmony_ci        // Skip over the segment selector for now.
238800b99b8Sopenharmony_ci        ptr += fdeInfo.cie.segmentSize;
239800b99b8Sopenharmony_ci    }
240800b99b8Sopenharmony_ci    // Parse pc begin and range.
241800b99b8Sopenharmony_ci    DFXLOGU("pointerEncoding: %{public}02x", fdeInfo.cie.pointerEncoding);
242800b99b8Sopenharmony_ci    uintptr_t pcStart = memory_->ReadEncodedValue(ptr, fdeInfo.cie.pointerEncoding);
243800b99b8Sopenharmony_ci    uintptr_t pcRange = memory_->ReadEncodedValue(ptr, (fdeInfo.cie.pointerEncoding & 0x0F));
244800b99b8Sopenharmony_ci
245800b99b8Sopenharmony_ci    fdeInfo.lsda = 0;
246800b99b8Sopenharmony_ci    // Check for augmentation length.
247800b99b8Sopenharmony_ci    if (fdeInfo.cie.hasAugmentationData) {
248800b99b8Sopenharmony_ci        uintptr_t augLen = memory_->ReadUleb128(ptr);
249800b99b8Sopenharmony_ci        uintptr_t instructionsPtr = ptr + augLen;
250800b99b8Sopenharmony_ci        if (fdeInfo.cie.lsdaEncoding != DW_EH_PE_omit) {
251800b99b8Sopenharmony_ci            uintptr_t lsdaPtr = ptr;
252800b99b8Sopenharmony_ci            if (memory_->ReadEncodedValue(ptr, (fdeInfo.cie.lsdaEncoding & 0x0F)) != 0) {
253800b99b8Sopenharmony_ci                fdeInfo.lsda = memory_->ReadEncodedValue(lsdaPtr, fdeInfo.cie.lsdaEncoding);
254800b99b8Sopenharmony_ci            }
255800b99b8Sopenharmony_ci        }
256800b99b8Sopenharmony_ci        ptr = instructionsPtr;
257800b99b8Sopenharmony_ci    }
258800b99b8Sopenharmony_ci
259800b99b8Sopenharmony_ci    fdeInfo.instructionsOff = ptr;
260800b99b8Sopenharmony_ci    fdeInfo.pcStart = pcStart;
261800b99b8Sopenharmony_ci    fdeInfo.pcEnd = pcStart + pcRange;
262800b99b8Sopenharmony_ci    DFXLOGU("FDE pcStart: %{public}p, pcEnd: %{public}p", (void*)(fdeInfo.pcStart), (void*)(fdeInfo.pcEnd));
263800b99b8Sopenharmony_ci    return true;
264800b99b8Sopenharmony_ci}
265800b99b8Sopenharmony_ci
266800b99b8Sopenharmony_cibool DwarfSection::ParseCie(uintptr_t cieAddr, uintptr_t ciePtr, CommonInfoEntry &cieInfo)
267800b99b8Sopenharmony_ci{
268800b99b8Sopenharmony_ci    DFXLOGU("cieAddr: %{public}" PRIx64 "", (uint64_t)cieAddr);
269800b99b8Sopenharmony_ci    if (!cieEntries_.empty()) {
270800b99b8Sopenharmony_ci        auto iter = cieEntries_.find(cieAddr);
271800b99b8Sopenharmony_ci        if (iter != cieEntries_.end()) {
272800b99b8Sopenharmony_ci            cieInfo = iter->second;
273800b99b8Sopenharmony_ci            return true;
274800b99b8Sopenharmony_ci        }
275800b99b8Sopenharmony_ci    }
276800b99b8Sopenharmony_ci    if (cieAddr == ciePtr) {
277800b99b8Sopenharmony_ci        cieInfo.lsdaEncoding = DW_EH_PE_omit;
278800b99b8Sopenharmony_ci        bool isCieEntry = false;
279800b99b8Sopenharmony_ci        FrameDescEntry fdeInfo;
280800b99b8Sopenharmony_ci        ParseCieOrFdeHeader(ciePtr, fdeInfo, isCieEntry);
281800b99b8Sopenharmony_ci        if (!isCieEntry) {
282800b99b8Sopenharmony_ci            DFXLOGE("ParseCie error, is not Cie Entry?");
283800b99b8Sopenharmony_ci            return false;
284800b99b8Sopenharmony_ci        }
285800b99b8Sopenharmony_ci        cieInfo = fdeInfo.cie;
286800b99b8Sopenharmony_ci    }
287800b99b8Sopenharmony_ci    if (!FillInCie(ciePtr, cieInfo)) {
288800b99b8Sopenharmony_ci        DFXLOGE("ParseCie error, failed to fill Cie?");
289800b99b8Sopenharmony_ci        cieEntries_.erase(cieAddr);
290800b99b8Sopenharmony_ci        return false;
291800b99b8Sopenharmony_ci    }
292800b99b8Sopenharmony_ci    cieEntries_[cieAddr] = cieInfo;
293800b99b8Sopenharmony_ci    return true;
294800b99b8Sopenharmony_ci}
295800b99b8Sopenharmony_ci
296800b99b8Sopenharmony_cibool DwarfSection::FillInCie(uintptr_t ptr, CommonInfoEntry &cieInfo)
297800b99b8Sopenharmony_ci{
298800b99b8Sopenharmony_ci    uint8_t version;
299800b99b8Sopenharmony_ci    memory_->ReadU8(ptr, &version, true);
300800b99b8Sopenharmony_ci    DFXLOGU("Cie version: %{public}d", version);
301800b99b8Sopenharmony_ci    if (version != DW_EH_VERSION && version != 3 && version != 4 && version != 5) { // 3 4 5 : cie version
302800b99b8Sopenharmony_ci        DFXLOGE("Invalid cie version: %{public}d", version);
303800b99b8Sopenharmony_ci        lastErrorData_.SetAddrAndCode(ptr, UNW_ERROR_UNSUPPORTED_VERSION);
304800b99b8Sopenharmony_ci        return false;
305800b99b8Sopenharmony_ci    }
306800b99b8Sopenharmony_ci
307800b99b8Sopenharmony_ci    // save augmentation string
308800b99b8Sopenharmony_ci    uint8_t ch;
309800b99b8Sopenharmony_ci    std::vector<char> augStr;
310800b99b8Sopenharmony_ci    augStr.clear();
311800b99b8Sopenharmony_ci    while (true) {
312800b99b8Sopenharmony_ci        memory_->ReadU8(ptr, &ch, true);
313800b99b8Sopenharmony_ci        if (ch == '\0') {
314800b99b8Sopenharmony_ci            break;
315800b99b8Sopenharmony_ci        }
316800b99b8Sopenharmony_ci        augStr.push_back(ch);
317800b99b8Sopenharmony_ci    }
318800b99b8Sopenharmony_ci
319800b99b8Sopenharmony_ci    // Segment Size
320800b99b8Sopenharmony_ci    if (version == 4 || version == 5) { // 4 5 : cie version
321800b99b8Sopenharmony_ci        // Skip the Address Size field since we only use it for validation.
322800b99b8Sopenharmony_ci        ptr += 1;
323800b99b8Sopenharmony_ci        memory_->ReadU8(ptr, &cieInfo.segmentSize, true);
324800b99b8Sopenharmony_ci    } else {
325800b99b8Sopenharmony_ci        cieInfo.segmentSize = 0;
326800b99b8Sopenharmony_ci    }
327800b99b8Sopenharmony_ci
328800b99b8Sopenharmony_ci    // parse code alignment factor
329800b99b8Sopenharmony_ci    cieInfo.codeAlignFactor = (uint32_t)memory_->ReadUleb128(ptr);
330800b99b8Sopenharmony_ci    DFXLOGU("codeAlignFactor: %{public}d", cieInfo.codeAlignFactor);
331800b99b8Sopenharmony_ci
332800b99b8Sopenharmony_ci    // parse data alignment factor
333800b99b8Sopenharmony_ci    cieInfo.dataAlignFactor = (int32_t)memory_->ReadSleb128(ptr);
334800b99b8Sopenharmony_ci    DFXLOGU("dataAlignFactor: %{public}d", cieInfo.dataAlignFactor);
335800b99b8Sopenharmony_ci
336800b99b8Sopenharmony_ci    // parse return address register
337800b99b8Sopenharmony_ci    if (version == DW_EH_VERSION) {
338800b99b8Sopenharmony_ci        uint8_t val;
339800b99b8Sopenharmony_ci        memory_->ReadU8(ptr, &val, true);
340800b99b8Sopenharmony_ci        cieInfo.returnAddressRegister = static_cast<uintptr_t>(val);
341800b99b8Sopenharmony_ci    } else {
342800b99b8Sopenharmony_ci        cieInfo.returnAddressRegister = (uintptr_t)memory_->ReadUleb128(ptr);
343800b99b8Sopenharmony_ci    }
344800b99b8Sopenharmony_ci    DFXLOGU("returnAddressRegister: %{public}d", (int)cieInfo.returnAddressRegister);
345800b99b8Sopenharmony_ci
346800b99b8Sopenharmony_ci    // parse augmentation data based on augmentation string
347800b99b8Sopenharmony_ci    if (augStr.empty() || augStr[0] != 'z') {
348800b99b8Sopenharmony_ci        cieInfo.instructionsOff = ptr;
349800b99b8Sopenharmony_ci        return true;
350800b99b8Sopenharmony_ci    }
351800b99b8Sopenharmony_ci    cieInfo.hasAugmentationData = true;
352800b99b8Sopenharmony_ci    // parse augmentation data length
353800b99b8Sopenharmony_ci    MAYBE_UNUSED uintptr_t augSize = memory_->ReadUleb128(ptr);
354800b99b8Sopenharmony_ci    DFXLOGU("augSize: %{public}" PRIxPTR "", augSize);
355800b99b8Sopenharmony_ci    cieInfo.instructionsOff = ptr + augSize;
356800b99b8Sopenharmony_ci
357800b99b8Sopenharmony_ci    for (size_t i = 1; i < augStr.size(); ++i) {
358800b99b8Sopenharmony_ci        switch (augStr[i]) {
359800b99b8Sopenharmony_ci            case 'P':
360800b99b8Sopenharmony_ci                uint8_t personalityEncoding;
361800b99b8Sopenharmony_ci                memory_->ReadU8(ptr, &personalityEncoding, true);
362800b99b8Sopenharmony_ci                cieInfo.personality = memory_->ReadEncodedValue(ptr, personalityEncoding);
363800b99b8Sopenharmony_ci                break;
364800b99b8Sopenharmony_ci            case 'L':
365800b99b8Sopenharmony_ci                memory_->ReadU8(ptr, &cieInfo.lsdaEncoding, true);
366800b99b8Sopenharmony_ci                DFXLOGU("cieInfo.lsdaEncoding: %{public}x", cieInfo.lsdaEncoding);
367800b99b8Sopenharmony_ci                break;
368800b99b8Sopenharmony_ci            case 'R':
369800b99b8Sopenharmony_ci                memory_->ReadU8(ptr, &cieInfo.pointerEncoding, true);
370800b99b8Sopenharmony_ci                DFXLOGU("cieInfo.pointerEncoding: %{public}x", cieInfo.pointerEncoding);
371800b99b8Sopenharmony_ci                break;
372800b99b8Sopenharmony_ci            case 'S':
373800b99b8Sopenharmony_ci                cieInfo.isSignalFrame = true;
374800b99b8Sopenharmony_ci                break;
375800b99b8Sopenharmony_ci            default:
376800b99b8Sopenharmony_ci                break;
377800b99b8Sopenharmony_ci        }
378800b99b8Sopenharmony_ci    }
379800b99b8Sopenharmony_ci    return true;
380800b99b8Sopenharmony_ci}
381800b99b8Sopenharmony_ci}   // namespace HiviewDFX
382800b99b8Sopenharmony_ci}   // namespace OHOS