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