1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2021-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 "dfx_elf_parser.h" 17800b99b8Sopenharmony_ci 18800b99b8Sopenharmony_ci#include <algorithm> 19800b99b8Sopenharmony_ci#include <cstdlib> 20800b99b8Sopenharmony_ci#include <securec.h> 21800b99b8Sopenharmony_ci#include <string> 22800b99b8Sopenharmony_ci#include <sys/types.h> 23800b99b8Sopenharmony_ci#include <unistd.h> 24800b99b8Sopenharmony_ci#include <utility> 25800b99b8Sopenharmony_ci 26800b99b8Sopenharmony_ci#include "dfx_define.h" 27800b99b8Sopenharmony_ci#include "dfx_log.h" 28800b99b8Sopenharmony_ci#include "dfx_util.h" 29800b99b8Sopenharmony_ci 30800b99b8Sopenharmony_ci#ifndef PAGE_SIZE 31800b99b8Sopenharmony_ci#define PAGE_SIZE 4096 32800b99b8Sopenharmony_ci#endif 33800b99b8Sopenharmony_ci 34800b99b8Sopenharmony_cinamespace OHOS { 35800b99b8Sopenharmony_cinamespace HiviewDFX { 36800b99b8Sopenharmony_cinamespace { 37800b99b8Sopenharmony_ci#undef LOG_DOMAIN 38800b99b8Sopenharmony_ci#undef LOG_TAG 39800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11 40800b99b8Sopenharmony_ci#define LOG_TAG "DfxElfParser" 41800b99b8Sopenharmony_ci} 42800b99b8Sopenharmony_ci 43800b99b8Sopenharmony_cibool ElfParser::Read(uintptr_t pos, void *buf, size_t size) 44800b99b8Sopenharmony_ci{ 45800b99b8Sopenharmony_ci if (mmap_->Read(pos, buf, size) == size) { 46800b99b8Sopenharmony_ci return true; 47800b99b8Sopenharmony_ci } 48800b99b8Sopenharmony_ci return false; 49800b99b8Sopenharmony_ci} 50800b99b8Sopenharmony_ci 51800b99b8Sopenharmony_cisize_t ElfParser::MmapSize() 52800b99b8Sopenharmony_ci{ 53800b99b8Sopenharmony_ci return mmap_->Size(); 54800b99b8Sopenharmony_ci} 55800b99b8Sopenharmony_ci 56800b99b8Sopenharmony_ciuint64_t ElfParser::GetElfSize() 57800b99b8Sopenharmony_ci{ 58800b99b8Sopenharmony_ci return elfSize_; 59800b99b8Sopenharmony_ci} 60800b99b8Sopenharmony_ci 61800b99b8Sopenharmony_citemplate <typename EhdrType, typename PhdrType, typename ShdrType> 62800b99b8Sopenharmony_cibool ElfParser::ParseAllHeaders() 63800b99b8Sopenharmony_ci{ 64800b99b8Sopenharmony_ci EhdrType ehdr; 65800b99b8Sopenharmony_ci if (!Read(0, &ehdr, sizeof(ehdr))) { 66800b99b8Sopenharmony_ci return false; 67800b99b8Sopenharmony_ci } 68800b99b8Sopenharmony_ci 69800b99b8Sopenharmony_ci if (!ParseElfHeaders<EhdrType>(ehdr)) { 70800b99b8Sopenharmony_ci DFXLOGW("[%{public}d]: ParseElfHeaders failed", __LINE__); 71800b99b8Sopenharmony_ci return false; 72800b99b8Sopenharmony_ci } 73800b99b8Sopenharmony_ci 74800b99b8Sopenharmony_ci if (!ParseProgramHeaders<EhdrType, PhdrType>(ehdr)) { 75800b99b8Sopenharmony_ci DFXLOGW("[%{public}d]: ParseProgramHeaders failed", __LINE__); 76800b99b8Sopenharmony_ci return false; 77800b99b8Sopenharmony_ci } 78800b99b8Sopenharmony_ci 79800b99b8Sopenharmony_ci if (!ParseSectionHeaders<EhdrType, ShdrType>(ehdr)) { 80800b99b8Sopenharmony_ci DFXLOGW("ParseSectionHeaders failed"); 81800b99b8Sopenharmony_ci return false; 82800b99b8Sopenharmony_ci } 83800b99b8Sopenharmony_ci return true; 84800b99b8Sopenharmony_ci} 85800b99b8Sopenharmony_ci 86800b99b8Sopenharmony_citemplate <typename EhdrType> 87800b99b8Sopenharmony_cibool ElfParser::ParseElfHeaders(const EhdrType& ehdr) 88800b99b8Sopenharmony_ci{ 89800b99b8Sopenharmony_ci if (ehdr.e_shnum == 0) { 90800b99b8Sopenharmony_ci return false; 91800b99b8Sopenharmony_ci } 92800b99b8Sopenharmony_ci 93800b99b8Sopenharmony_ci auto machine = ehdr.e_machine; 94800b99b8Sopenharmony_ci if (machine == EM_ARM) { 95800b99b8Sopenharmony_ci archType_ = ARCH_ARM; 96800b99b8Sopenharmony_ci } else if (machine == EM_386) { 97800b99b8Sopenharmony_ci archType_ = ARCH_X86; 98800b99b8Sopenharmony_ci } else if (machine == EM_AARCH64) { 99800b99b8Sopenharmony_ci archType_ = ARCH_ARM64; 100800b99b8Sopenharmony_ci } else if (machine == EM_RISCV) { 101800b99b8Sopenharmony_ci archType_ = ARCH_RISCV64; 102800b99b8Sopenharmony_ci } else if (machine == EM_X86_64) { 103800b99b8Sopenharmony_ci archType_ = ARCH_X86_64; 104800b99b8Sopenharmony_ci } else { 105800b99b8Sopenharmony_ci DFXLOGW("Failed the machine = %{public}d", machine); 106800b99b8Sopenharmony_ci } 107800b99b8Sopenharmony_ci elfSize_ = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum; 108800b99b8Sopenharmony_ci return true; 109800b99b8Sopenharmony_ci} 110800b99b8Sopenharmony_ci 111800b99b8Sopenharmony_citemplate <typename EhdrType, typename PhdrType> 112800b99b8Sopenharmony_cibool ElfParser::ParseProgramHeaders(const EhdrType& ehdr) 113800b99b8Sopenharmony_ci{ 114800b99b8Sopenharmony_ci uint64_t offset = ehdr.e_phoff; 115800b99b8Sopenharmony_ci bool firstLoadHeader = true; 116800b99b8Sopenharmony_ci for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) { 117800b99b8Sopenharmony_ci PhdrType phdr; 118800b99b8Sopenharmony_ci if (!Read((uintptr_t)offset, &phdr, sizeof(phdr))) { 119800b99b8Sopenharmony_ci return false; 120800b99b8Sopenharmony_ci } 121800b99b8Sopenharmony_ci 122800b99b8Sopenharmony_ci switch (phdr.p_type) { 123800b99b8Sopenharmony_ci case PT_LOAD: { 124800b99b8Sopenharmony_ci ElfLoadInfo loadInfo; 125800b99b8Sopenharmony_ci loadInfo.offset = phdr.p_offset; 126800b99b8Sopenharmony_ci loadInfo.tableVaddr = phdr.p_vaddr; 127800b99b8Sopenharmony_ci loadInfo.tableSize = static_cast<size_t>(phdr.p_memsz); 128800b99b8Sopenharmony_ci loadInfo.align = phdr.p_align; 129800b99b8Sopenharmony_ci if (loadInfo.align == 0) { 130800b99b8Sopenharmony_ci continue; 131800b99b8Sopenharmony_ci } 132800b99b8Sopenharmony_ci uint64_t len = loadInfo.tableSize + (loadInfo.tableVaddr & (loadInfo.align - 1)); 133800b99b8Sopenharmony_ci loadInfo.mmapLen = len - (len & (loadInfo.align - 1)) + loadInfo.align; 134800b99b8Sopenharmony_ci ptLoads_[phdr.p_offset] = loadInfo; 135800b99b8Sopenharmony_ci if ((phdr.p_flags & PF_X) == 0) { 136800b99b8Sopenharmony_ci continue; 137800b99b8Sopenharmony_ci } 138800b99b8Sopenharmony_ci // Only set the load bias from the first executable load header. 139800b99b8Sopenharmony_ci if (firstLoadHeader) { 140800b99b8Sopenharmony_ci loadBias_ = static_cast<int64_t>(static_cast<uint64_t>(phdr.p_vaddr) - phdr.p_offset); 141800b99b8Sopenharmony_ci } 142800b99b8Sopenharmony_ci firstLoadHeader = false; 143800b99b8Sopenharmony_ci 144800b99b8Sopenharmony_ci if (static_cast<uint64_t>(phdr.p_vaddr) < static_cast<uint64_t>(startVaddr_)) { 145800b99b8Sopenharmony_ci startVaddr_ = static_cast<uint64_t>(phdr.p_vaddr); 146800b99b8Sopenharmony_ci startOffset_ = static_cast<uint64_t>(phdr.p_offset); 147800b99b8Sopenharmony_ci } 148800b99b8Sopenharmony_ci if (static_cast<uint64_t>(phdr.p_vaddr + phdr.p_memsz) > static_cast<uint64_t>(endVaddr_)) { 149800b99b8Sopenharmony_ci endVaddr_ = static_cast<uint64_t>(phdr.p_vaddr + phdr.p_memsz); 150800b99b8Sopenharmony_ci } 151800b99b8Sopenharmony_ci DFXLOGU("Elf startVaddr: %{public}" PRIx64 ", endVaddr: %{public}" PRIx64 "", 152800b99b8Sopenharmony_ci startVaddr_, endVaddr_); 153800b99b8Sopenharmony_ci break; 154800b99b8Sopenharmony_ci } 155800b99b8Sopenharmony_ci case PT_DYNAMIC: { 156800b99b8Sopenharmony_ci dynamicOffset_ = phdr.p_offset; 157800b99b8Sopenharmony_ci break; 158800b99b8Sopenharmony_ci } 159800b99b8Sopenharmony_ci default: 160800b99b8Sopenharmony_ci break; 161800b99b8Sopenharmony_ci } 162800b99b8Sopenharmony_ci } 163800b99b8Sopenharmony_ci return true; 164800b99b8Sopenharmony_ci} 165800b99b8Sopenharmony_ci 166800b99b8Sopenharmony_cistd::shared_ptr<MiniDebugInfo> ElfParser::GetMiniDebugInfo() 167800b99b8Sopenharmony_ci{ 168800b99b8Sopenharmony_ci return minidebugInfo_; 169800b99b8Sopenharmony_ci} 170800b99b8Sopenharmony_ci 171800b99b8Sopenharmony_citemplate <typename EhdrType, typename ShdrType> 172800b99b8Sopenharmony_cibool ElfParser::ParseSectionHeaders(const EhdrType& ehdr) 173800b99b8Sopenharmony_ci{ 174800b99b8Sopenharmony_ci uint64_t offset = ehdr.e_shoff; 175800b99b8Sopenharmony_ci 176800b99b8Sopenharmony_ci ShdrType shdr; 177800b99b8Sopenharmony_ci //section header string table index. include section header table with section name string table. 178800b99b8Sopenharmony_ci if (ehdr.e_shstrndx < ehdr.e_shnum) { 179800b99b8Sopenharmony_ci uint64_t secOffset = 0; 180800b99b8Sopenharmony_ci uint64_t secSize = 0; 181800b99b8Sopenharmony_ci uint64_t shNdxOffset = offset + ehdr.e_shstrndx * ehdr.e_shentsize; 182800b99b8Sopenharmony_ci if (!Read((uintptr_t)shNdxOffset, &shdr, sizeof(shdr))) { 183800b99b8Sopenharmony_ci DFXLOGE("Read section header string table failed"); 184800b99b8Sopenharmony_ci return false; 185800b99b8Sopenharmony_ci } 186800b99b8Sopenharmony_ci secOffset = shdr.sh_offset; 187800b99b8Sopenharmony_ci secSize = shdr.sh_size; 188800b99b8Sopenharmony_ci if (!ParseStrTab(sectionNames_, secOffset, secSize)) { 189800b99b8Sopenharmony_ci return false; 190800b99b8Sopenharmony_ci } 191800b99b8Sopenharmony_ci } else { 192800b99b8Sopenharmony_ci DFXLOGE("e_shstrndx(%{public}u) cannot greater than or equal e_shnum(%{public}u)", 193800b99b8Sopenharmony_ci ehdr.e_shstrndx, ehdr.e_shnum); 194800b99b8Sopenharmony_ci return false; 195800b99b8Sopenharmony_ci } 196800b99b8Sopenharmony_ci 197800b99b8Sopenharmony_ci offset += ehdr.e_shentsize; 198800b99b8Sopenharmony_ci for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) { 199800b99b8Sopenharmony_ci if (i == ehdr.e_shstrndx) { 200800b99b8Sopenharmony_ci continue; 201800b99b8Sopenharmony_ci } 202800b99b8Sopenharmony_ci if (!Read((uintptr_t)offset, &shdr, sizeof(shdr))) { 203800b99b8Sopenharmony_ci return false; 204800b99b8Sopenharmony_ci } 205800b99b8Sopenharmony_ci 206800b99b8Sopenharmony_ci std::string secName; 207800b99b8Sopenharmony_ci if (!GetSectionNameByIndex(secName, shdr.sh_name)) { 208800b99b8Sopenharmony_ci DFXLOGE("Failed to get section name"); 209800b99b8Sopenharmony_ci continue; 210800b99b8Sopenharmony_ci } 211800b99b8Sopenharmony_ci 212800b99b8Sopenharmony_ci if (shdr.sh_size != 0 && secName == GNU_DEBUGDATA) { 213800b99b8Sopenharmony_ci minidebugInfo_ = std::make_shared<MiniDebugInfo>(); 214800b99b8Sopenharmony_ci minidebugInfo_->offset = static_cast<uint64_t>(shdr.sh_offset); 215800b99b8Sopenharmony_ci minidebugInfo_->size = static_cast<uintptr_t>(shdr.sh_size); 216800b99b8Sopenharmony_ci } 217800b99b8Sopenharmony_ci 218800b99b8Sopenharmony_ci ShdrInfo shdrInfo; 219800b99b8Sopenharmony_ci shdrInfo.addr = static_cast<uint64_t>(shdr.sh_addr); 220800b99b8Sopenharmony_ci shdrInfo.entSize = static_cast<uint64_t>(shdr.sh_entsize); 221800b99b8Sopenharmony_ci shdrInfo.size = static_cast<uint64_t>(shdr.sh_size); 222800b99b8Sopenharmony_ci shdrInfo.offset = static_cast<uint64_t>(shdr.sh_offset); 223800b99b8Sopenharmony_ci shdrInfoPairs_.emplace(std::make_pair(i, secName), shdrInfo); 224800b99b8Sopenharmony_ci 225800b99b8Sopenharmony_ci if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { 226800b99b8Sopenharmony_ci if (shdr.sh_link >= ehdr.e_shnum) { 227800b99b8Sopenharmony_ci continue; 228800b99b8Sopenharmony_ci } 229800b99b8Sopenharmony_ci ElfShdr elfShdr; 230800b99b8Sopenharmony_ci elfShdr.name = static_cast<uint32_t>(shdr.sh_name); 231800b99b8Sopenharmony_ci elfShdr.type = static_cast<uint32_t>(shdr.sh_type); 232800b99b8Sopenharmony_ci elfShdr.flags = static_cast<uint64_t>(shdr.sh_flags); 233800b99b8Sopenharmony_ci elfShdr.addr = static_cast<uint64_t>(shdr.sh_addr); 234800b99b8Sopenharmony_ci elfShdr.offset = static_cast<uint64_t>(shdr.sh_offset); 235800b99b8Sopenharmony_ci elfShdr.size = static_cast<uint64_t>(shdr.sh_size); 236800b99b8Sopenharmony_ci elfShdr.link = static_cast<uint32_t>(shdr.sh_link); 237800b99b8Sopenharmony_ci elfShdr.info = static_cast<uint32_t>(shdr.sh_info); 238800b99b8Sopenharmony_ci elfShdr.addrAlign = static_cast<uint64_t>(shdr.sh_addralign); 239800b99b8Sopenharmony_ci elfShdr.entSize = static_cast<uint64_t>(shdr.sh_entsize); 240800b99b8Sopenharmony_ci symShdrs_.emplace_back(elfShdr); 241800b99b8Sopenharmony_ci } 242800b99b8Sopenharmony_ci } 243800b99b8Sopenharmony_ci return true; 244800b99b8Sopenharmony_ci} 245800b99b8Sopenharmony_ci 246800b99b8Sopenharmony_citemplate <typename DynType> 247800b99b8Sopenharmony_cibool ElfParser::ParseElfDynamic() 248800b99b8Sopenharmony_ci{ 249800b99b8Sopenharmony_ci if (dynamicOffset_ == 0 || mmap_->Get() == nullptr) { 250800b99b8Sopenharmony_ci return false; 251800b99b8Sopenharmony_ci } 252800b99b8Sopenharmony_ci 253800b99b8Sopenharmony_ci DynType *dyn = (DynType *)(dynamicOffset_ + static_cast<char*>(mmap_->Get())); 254800b99b8Sopenharmony_ci if (dyn == nullptr) { 255800b99b8Sopenharmony_ci return false; 256800b99b8Sopenharmony_ci } 257800b99b8Sopenharmony_ci for (; dyn->d_tag != DT_NULL; ++dyn) { 258800b99b8Sopenharmony_ci if (dyn->d_tag == DT_PLTGOT) { 259800b99b8Sopenharmony_ci // Assume that _DYNAMIC is writable and GLIBC has relocated it (true for x86 at least). 260800b99b8Sopenharmony_ci dtPltGotAddr_ = dyn->d_un.d_ptr; 261800b99b8Sopenharmony_ci break; 262800b99b8Sopenharmony_ci } else if (dyn->d_tag == DT_STRTAB) { 263800b99b8Sopenharmony_ci dtStrtabAddr_ = dyn->d_un.d_ptr; 264800b99b8Sopenharmony_ci } else if (dyn->d_tag == DT_STRSZ) { 265800b99b8Sopenharmony_ci dtStrtabSize_ = dyn->d_un.d_val; 266800b99b8Sopenharmony_ci } else if (dyn->d_tag == DT_SONAME) { 267800b99b8Sopenharmony_ci dtSonameOffset_ = dyn->d_un.d_val; 268800b99b8Sopenharmony_ci } 269800b99b8Sopenharmony_ci } 270800b99b8Sopenharmony_ci return true; 271800b99b8Sopenharmony_ci} 272800b99b8Sopenharmony_ci 273800b99b8Sopenharmony_citemplate <typename DynType> 274800b99b8Sopenharmony_cibool ElfParser::ParseElfName() 275800b99b8Sopenharmony_ci{ 276800b99b8Sopenharmony_ci if (!ParseElfDynamic<DynType>()) { 277800b99b8Sopenharmony_ci return false; 278800b99b8Sopenharmony_ci } 279800b99b8Sopenharmony_ci ShdrInfo shdrInfo; 280800b99b8Sopenharmony_ci if (!GetSectionInfo(shdrInfo, DYNSTR)) { 281800b99b8Sopenharmony_ci return false; 282800b99b8Sopenharmony_ci } 283800b99b8Sopenharmony_ci uintptr_t sonameOffset = shdrInfo.offset + dtSonameOffset_; 284800b99b8Sopenharmony_ci uint64_t sonameOffsetMax = shdrInfo.offset + dtStrtabSize_; 285800b99b8Sopenharmony_ci size_t maxStrSize = static_cast<size_t>(sonameOffsetMax - sonameOffset); 286800b99b8Sopenharmony_ci mmap_->ReadString(sonameOffset, &soname_, maxStrSize); 287800b99b8Sopenharmony_ci DFXLOGU("parse current elf file soname is %{public}s.", soname_.c_str()); 288800b99b8Sopenharmony_ci return true; 289800b99b8Sopenharmony_ci} 290800b99b8Sopenharmony_ci 291800b99b8Sopenharmony_citemplate <typename SymType> 292800b99b8Sopenharmony_cibool ElfParser::IsFunc(const SymType sym) 293800b99b8Sopenharmony_ci{ 294800b99b8Sopenharmony_ci return ((sym.st_shndx != SHN_UNDEF) && 295800b99b8Sopenharmony_ci (ELF32_ST_TYPE(sym.st_info) == STT_FUNC || ELF32_ST_TYPE(sym.st_info) == STT_GNU_IFUNC)); 296800b99b8Sopenharmony_ci} 297800b99b8Sopenharmony_ci 298800b99b8Sopenharmony_citemplate <typename SymType> 299800b99b8Sopenharmony_cibool ElfParser::ParseElfSymbols(bool isFunc) 300800b99b8Sopenharmony_ci{ 301800b99b8Sopenharmony_ci if (symShdrs_.empty()) { 302800b99b8Sopenharmony_ci return false; 303800b99b8Sopenharmony_ci } 304800b99b8Sopenharmony_ci 305800b99b8Sopenharmony_ci elfSymbols_.clear(); 306800b99b8Sopenharmony_ci for (const auto &iter : symShdrs_) { 307800b99b8Sopenharmony_ci const auto &shdr = iter; 308800b99b8Sopenharmony_ci ParseElfSymbols<SymType>(shdr, isFunc); 309800b99b8Sopenharmony_ci } 310800b99b8Sopenharmony_ci return (elfSymbols_.size() > 0); 311800b99b8Sopenharmony_ci} 312800b99b8Sopenharmony_ci 313800b99b8Sopenharmony_citemplate <typename SymType> 314800b99b8Sopenharmony_cibool ElfParser::ParseElfSymbols(ElfShdr shdr, bool isFunc) 315800b99b8Sopenharmony_ci{ 316800b99b8Sopenharmony_ci ShdrInfo linkShdrInfo; 317800b99b8Sopenharmony_ci if (!GetSectionInfo(linkShdrInfo, shdr.link)) { 318800b99b8Sopenharmony_ci return false; 319800b99b8Sopenharmony_ci } 320800b99b8Sopenharmony_ci 321800b99b8Sopenharmony_ci uint32_t count = static_cast<uint32_t>((shdr.entSize != 0) ? (shdr.size / shdr.entSize) : 0); 322800b99b8Sopenharmony_ci for (uint32_t idx = 0; idx < count; ++idx) { 323800b99b8Sopenharmony_ci uintptr_t offset = static_cast<uintptr_t>(shdr.offset + idx * shdr.entSize); 324800b99b8Sopenharmony_ci SymType sym; 325800b99b8Sopenharmony_ci if (!Read(offset, &sym, sizeof(sym))) { 326800b99b8Sopenharmony_ci continue; 327800b99b8Sopenharmony_ci } 328800b99b8Sopenharmony_ci if (sym.st_value == 0 || sym.st_size == 0) { 329800b99b8Sopenharmony_ci continue; 330800b99b8Sopenharmony_ci } 331800b99b8Sopenharmony_ci ElfSymbol elfSymbol; 332800b99b8Sopenharmony_ci if (isFunc && (!ParseElfSymbolName(linkShdrInfo, sym, elfSymbol.nameStr))) { 333800b99b8Sopenharmony_ci continue; 334800b99b8Sopenharmony_ci } 335800b99b8Sopenharmony_ci elfSymbol.value = static_cast<uint64_t>(sym.st_value); 336800b99b8Sopenharmony_ci elfSymbol.size = static_cast<uint64_t>(sym.st_size); 337800b99b8Sopenharmony_ci elfSymbol.name = static_cast<uint32_t>(sym.st_name); 338800b99b8Sopenharmony_ci elfSymbols_.emplace_back(elfSymbol); 339800b99b8Sopenharmony_ci } 340800b99b8Sopenharmony_ci DFXLOGU("elfSymbols.size: %{public}" PRIuPTR "", elfSymbols_.size()); 341800b99b8Sopenharmony_ci return true; 342800b99b8Sopenharmony_ci} 343800b99b8Sopenharmony_ci 344800b99b8Sopenharmony_citemplate <typename SymType> 345800b99b8Sopenharmony_cibool ElfParser::ParseElfSymbolName(ShdrInfo linkShdr, SymType sym, std::string& nameStr) 346800b99b8Sopenharmony_ci{ 347800b99b8Sopenharmony_ci if (!IsFunc(sym) || (static_cast<uint64_t>(sym.st_name) >= linkShdr.size) || mmap_->Get() == nullptr) { 348800b99b8Sopenharmony_ci return false; 349800b99b8Sopenharmony_ci } 350800b99b8Sopenharmony_ci uintptr_t nameOffset = static_cast<uintptr_t>(linkShdr.offset + sym.st_name); 351800b99b8Sopenharmony_ci nameStr = std::string(static_cast<char*>(mmap_->Get()) + nameOffset); 352800b99b8Sopenharmony_ci return true; 353800b99b8Sopenharmony_ci} 354800b99b8Sopenharmony_ci 355800b99b8Sopenharmony_citemplate <typename SymType> 356800b99b8Sopenharmony_cibool ElfParser::ParseElfSymbolByAddr(uint64_t addr, ElfSymbol& elfSymbol) 357800b99b8Sopenharmony_ci{ 358800b99b8Sopenharmony_ci if (symShdrs_.empty()) { 359800b99b8Sopenharmony_ci return false; 360800b99b8Sopenharmony_ci } 361800b99b8Sopenharmony_ci 362800b99b8Sopenharmony_ci for (const auto &shdr : symShdrs_) { 363800b99b8Sopenharmony_ci ShdrInfo linkShdrInfo; 364800b99b8Sopenharmony_ci if (!GetSectionInfo(linkShdrInfo, shdr.link)) { 365800b99b8Sopenharmony_ci return false; 366800b99b8Sopenharmony_ci } 367800b99b8Sopenharmony_ci 368800b99b8Sopenharmony_ci uint32_t count = static_cast<uint32_t>((shdr.entSize != 0) ? (shdr.size / shdr.entSize) : 0); 369800b99b8Sopenharmony_ci for (uint32_t idx = 0; idx < count; ++idx) { 370800b99b8Sopenharmony_ci uintptr_t offset = static_cast<uintptr_t>(shdr.offset + idx * shdr.entSize); 371800b99b8Sopenharmony_ci SymType sym; 372800b99b8Sopenharmony_ci if (!Read(offset, &sym, sizeof(sym))) { // todo inplace search 373800b99b8Sopenharmony_ci continue; 374800b99b8Sopenharmony_ci } 375800b99b8Sopenharmony_ci if (sym.st_value == 0 || sym.st_size == 0) { 376800b99b8Sopenharmony_ci continue; 377800b99b8Sopenharmony_ci } 378800b99b8Sopenharmony_ci 379800b99b8Sopenharmony_ci if ((sym.st_value <= addr) && (addr < (sym.st_value + sym.st_size)) && 380800b99b8Sopenharmony_ci ParseElfSymbolName(linkShdrInfo, sym, elfSymbol.nameStr)) { 381800b99b8Sopenharmony_ci elfSymbol.value = static_cast<uint64_t>(sym.st_value); 382800b99b8Sopenharmony_ci elfSymbol.size = static_cast<uint64_t>(sym.st_size); 383800b99b8Sopenharmony_ci elfSymbol.name = static_cast<uint32_t>(sym.st_name); 384800b99b8Sopenharmony_ci DFXLOGU("Parse elf symbol nameStr: %{public}s", elfSymbol.nameStr.c_str()); 385800b99b8Sopenharmony_ci return true; 386800b99b8Sopenharmony_ci } 387800b99b8Sopenharmony_ci } 388800b99b8Sopenharmony_ci } 389800b99b8Sopenharmony_ci return false; 390800b99b8Sopenharmony_ci} 391800b99b8Sopenharmony_ci 392800b99b8Sopenharmony_cibool ElfParser::GetSectionNameByIndex(std::string& nameStr, const uint32_t name) 393800b99b8Sopenharmony_ci{ 394800b99b8Sopenharmony_ci if (sectionNames_.empty() || name >= sectionNames_.size()) { 395800b99b8Sopenharmony_ci DFXLOGE("name index(%{public}u) out of range, size: %{public}" PRIuPTR "", name, sectionNames_.size()); 396800b99b8Sopenharmony_ci return false; 397800b99b8Sopenharmony_ci } 398800b99b8Sopenharmony_ci 399800b99b8Sopenharmony_ci size_t endIndex = sectionNames_.find('\0', name); 400800b99b8Sopenharmony_ci if (endIndex != std::string::npos) { 401800b99b8Sopenharmony_ci nameStr = sectionNames_.substr(name, endIndex - name); 402800b99b8Sopenharmony_ci return true; 403800b99b8Sopenharmony_ci } 404800b99b8Sopenharmony_ci return false; 405800b99b8Sopenharmony_ci} 406800b99b8Sopenharmony_ci 407800b99b8Sopenharmony_cibool ElfParser::ParseStrTab(std::string& nameStr, const uint64_t offset, const uint64_t size) 408800b99b8Sopenharmony_ci{ 409800b99b8Sopenharmony_ci if (size > MmapSize()) { 410800b99b8Sopenharmony_ci DFXLOGE("size(%{public}" PRIu64 ") is too large.", size); 411800b99b8Sopenharmony_ci return false; 412800b99b8Sopenharmony_ci } 413800b99b8Sopenharmony_ci char *namesBuf = new char[size]; 414800b99b8Sopenharmony_ci if (namesBuf == nullptr) { 415800b99b8Sopenharmony_ci DFXLOGE("New failed"); 416800b99b8Sopenharmony_ci return false; 417800b99b8Sopenharmony_ci } 418800b99b8Sopenharmony_ci (void)memset_s(namesBuf, size, '\0', size); 419800b99b8Sopenharmony_ci if (!Read((uintptr_t)offset, namesBuf, size)) { 420800b99b8Sopenharmony_ci DFXLOGE("Read failed"); 421800b99b8Sopenharmony_ci delete[] namesBuf; 422800b99b8Sopenharmony_ci namesBuf = nullptr; 423800b99b8Sopenharmony_ci return false; 424800b99b8Sopenharmony_ci } 425800b99b8Sopenharmony_ci nameStr = std::string(namesBuf, namesBuf + size); 426800b99b8Sopenharmony_ci delete[] namesBuf; 427800b99b8Sopenharmony_ci namesBuf = nullptr; 428800b99b8Sopenharmony_ci return true; 429800b99b8Sopenharmony_ci} 430800b99b8Sopenharmony_ci 431800b99b8Sopenharmony_cibool ElfParser::GetSectionInfo(ShdrInfo& shdr, const uint32_t idx) 432800b99b8Sopenharmony_ci{ 433800b99b8Sopenharmony_ci for (const auto &iter: shdrInfoPairs_) { 434800b99b8Sopenharmony_ci auto tmpPair = iter.first; 435800b99b8Sopenharmony_ci if (tmpPair.first == idx) { 436800b99b8Sopenharmony_ci shdr = iter.second; 437800b99b8Sopenharmony_ci return true; 438800b99b8Sopenharmony_ci } 439800b99b8Sopenharmony_ci } 440800b99b8Sopenharmony_ci return false; 441800b99b8Sopenharmony_ci} 442800b99b8Sopenharmony_ci 443800b99b8Sopenharmony_cibool ElfParser::GetSectionInfo(ShdrInfo& shdr, const std::string& secName) 444800b99b8Sopenharmony_ci{ 445800b99b8Sopenharmony_ci for (const auto &iter: shdrInfoPairs_) { 446800b99b8Sopenharmony_ci auto tmpPair = iter.first; 447800b99b8Sopenharmony_ci if (tmpPair.second == secName) { 448800b99b8Sopenharmony_ci shdr = iter.second; 449800b99b8Sopenharmony_ci return true; 450800b99b8Sopenharmony_ci } 451800b99b8Sopenharmony_ci } 452800b99b8Sopenharmony_ci return false; 453800b99b8Sopenharmony_ci} 454800b99b8Sopenharmony_ci 455800b99b8Sopenharmony_cibool ElfParser::GetSectionData(unsigned char *buf, uint64_t size, std::string secName) 456800b99b8Sopenharmony_ci{ 457800b99b8Sopenharmony_ci ShdrInfo shdr; 458800b99b8Sopenharmony_ci if (GetSectionInfo(shdr, secName)) { 459800b99b8Sopenharmony_ci if (Read(shdr.offset, buf, size)) { 460800b99b8Sopenharmony_ci return true; 461800b99b8Sopenharmony_ci } 462800b99b8Sopenharmony_ci } else { 463800b99b8Sopenharmony_ci DFXLOGE("Failed to get data from secName %{public}s", secName.c_str()); 464800b99b8Sopenharmony_ci } 465800b99b8Sopenharmony_ci return false; 466800b99b8Sopenharmony_ci} 467800b99b8Sopenharmony_ci 468800b99b8Sopenharmony_cibool ElfParser32::InitHeaders() 469800b99b8Sopenharmony_ci{ 470800b99b8Sopenharmony_ci return ParseAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(); 471800b99b8Sopenharmony_ci} 472800b99b8Sopenharmony_ci 473800b99b8Sopenharmony_cibool ElfParser64::InitHeaders() 474800b99b8Sopenharmony_ci{ 475800b99b8Sopenharmony_ci return ParseAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(); 476800b99b8Sopenharmony_ci} 477800b99b8Sopenharmony_ci 478800b99b8Sopenharmony_cistd::string ElfParser32::GetElfName() 479800b99b8Sopenharmony_ci{ 480800b99b8Sopenharmony_ci if (soname_ == "") { 481800b99b8Sopenharmony_ci ParseElfName<Elf32_Dyn>(); 482800b99b8Sopenharmony_ci } 483800b99b8Sopenharmony_ci return soname_; 484800b99b8Sopenharmony_ci} 485800b99b8Sopenharmony_ci 486800b99b8Sopenharmony_cistd::string ElfParser64::GetElfName() 487800b99b8Sopenharmony_ci{ 488800b99b8Sopenharmony_ci if (soname_ == "") { 489800b99b8Sopenharmony_ci ParseElfName<Elf64_Dyn>(); 490800b99b8Sopenharmony_ci } 491800b99b8Sopenharmony_ci return soname_; 492800b99b8Sopenharmony_ci} 493800b99b8Sopenharmony_ci 494800b99b8Sopenharmony_ciuintptr_t ElfParser32::GetGlobalPointer() 495800b99b8Sopenharmony_ci{ 496800b99b8Sopenharmony_ci if (dtPltGotAddr_ == 0) { 497800b99b8Sopenharmony_ci ParseElfDynamic<Elf32_Dyn>(); 498800b99b8Sopenharmony_ci } 499800b99b8Sopenharmony_ci return dtPltGotAddr_; 500800b99b8Sopenharmony_ci} 501800b99b8Sopenharmony_ci 502800b99b8Sopenharmony_ciuintptr_t ElfParser64::GetGlobalPointer() 503800b99b8Sopenharmony_ci{ 504800b99b8Sopenharmony_ci if (dtPltGotAddr_ == 0) { 505800b99b8Sopenharmony_ci ParseElfDynamic<Elf64_Dyn>(); 506800b99b8Sopenharmony_ci } 507800b99b8Sopenharmony_ci return dtPltGotAddr_; 508800b99b8Sopenharmony_ci} 509800b99b8Sopenharmony_ci 510800b99b8Sopenharmony_ciconst std::vector<ElfSymbol>& ElfParser32::GetElfSymbols(bool isFunc) 511800b99b8Sopenharmony_ci{ 512800b99b8Sopenharmony_ci ParseElfSymbols<Elf32_Sym>(isFunc); 513800b99b8Sopenharmony_ci return elfSymbols_; 514800b99b8Sopenharmony_ci} 515800b99b8Sopenharmony_ci 516800b99b8Sopenharmony_ciconst std::vector<ElfSymbol>& ElfParser64::GetElfSymbols(bool isFunc) 517800b99b8Sopenharmony_ci{ 518800b99b8Sopenharmony_ci ParseElfSymbols<Elf64_Sym>(isFunc); 519800b99b8Sopenharmony_ci return elfSymbols_; 520800b99b8Sopenharmony_ci} 521800b99b8Sopenharmony_ci 522800b99b8Sopenharmony_cibool ElfParser32::GetElfSymbolByAddr(uint64_t addr, ElfSymbol& elfSymbol) 523800b99b8Sopenharmony_ci{ 524800b99b8Sopenharmony_ci return ParseElfSymbolByAddr<Elf32_Sym>(addr, elfSymbol); 525800b99b8Sopenharmony_ci} 526800b99b8Sopenharmony_ci 527800b99b8Sopenharmony_cibool ElfParser64::GetElfSymbolByAddr(uint64_t addr, ElfSymbol& elfSymbol) 528800b99b8Sopenharmony_ci{ 529800b99b8Sopenharmony_ci return ParseElfSymbolByAddr<Elf64_Sym>(addr, elfSymbol); 530800b99b8Sopenharmony_ci} 531800b99b8Sopenharmony_ci} // namespace HiviewDFX 532800b99b8Sopenharmony_ci} // namespace OHOS 533