• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "dfx_elf_parser.h"
17 
18 #include <algorithm>
19 #include <cstdlib>
20 #include <securec.h>
21 #include <string>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include <utility>
25 
26 #include "dfx_define.h"
27 #include "dfx_log.h"
28 #include "dfx_util.h"
29 
30 #ifndef PAGE_SIZE
31 #define PAGE_SIZE 4096
32 #endif
33 
34 // workaround for non mingw build
35 #ifndef EM_LOONGARCH
36 #define EM_LOONGARCH	258 // LOONGARCH
37 #endif
38 
39 namespace OHOS {
40 namespace HiviewDFX {
41 namespace {
42 #undef LOG_DOMAIN
43 #undef LOG_TAG
44 #define LOG_DOMAIN 0xD002D11
45 #define LOG_TAG "DfxElfParser"
46 }
47 
Read(uintptr_t pos,void * buf,size_t size)48 bool ElfParser::Read(uintptr_t pos, void *buf, size_t size)
49 {
50     if (mmap_->Read(pos, buf, size) == size) {
51         return true;
52     }
53     return false;
54 }
55 
MmapSize()56 size_t ElfParser::MmapSize()
57 {
58     return mmap_->Size();
59 }
60 
GetElfSize()61 uint64_t ElfParser::GetElfSize()
62 {
63     return elfSize_;
64 }
65 
66 template <typename EhdrType, typename PhdrType, typename ShdrType>
ParseAllHeaders()67 bool ElfParser::ParseAllHeaders()
68 {
69     EhdrType ehdr;
70     if (!Read(0, &ehdr, sizeof(ehdr))) {
71         return false;
72     }
73 
74     if (!ParseElfHeaders<EhdrType>(ehdr)) {
75         DFXLOGW("[%{public}d]: ParseElfHeaders failed", __LINE__);
76         return false;
77     }
78 
79     if (!ParseProgramHeaders<EhdrType, PhdrType>(ehdr)) {
80         DFXLOGW("[%{public}d]: ParseProgramHeaders failed", __LINE__);
81         return false;
82     }
83 
84     if (!ParseSectionHeaders<EhdrType, ShdrType>(ehdr)) {
85         DFXLOGW("ParseSectionHeaders failed");
86         return false;
87     }
88     return true;
89 }
90 
91 template <typename EhdrType>
ParseElfHeaders(const EhdrType & ehdr)92 bool ElfParser::ParseElfHeaders(const EhdrType& ehdr)
93 {
94     if (ehdr.e_shnum == 0) {
95         return false;
96     }
97 
98     auto machine = ehdr.e_machine;
99     if (machine == EM_ARM) {
100         archType_ = ARCH_ARM;
101     } else if (machine == EM_386) {
102         archType_ = ARCH_X86;
103     } else if (machine == EM_AARCH64) {
104         archType_ = ARCH_ARM64;
105     } else if (machine == EM_RISCV) {
106         archType_ = ARCH_RISCV64;
107     } else if (machine == EM_X86_64) {
108         archType_ = ARCH_X86_64;
109     } else if (machine == EM_LOONGARCH) {
110         archType_ = ARCH_LOONGARCH;
111     } else {
112         DFXLOGW("Failed the machine = %{public}d", machine);
113     }
114     elfSize_ = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum;
115     return true;
116 }
117 
118 template <typename EhdrType, typename PhdrType>
ParseProgramHeaders(const EhdrType & ehdr)119 bool ElfParser::ParseProgramHeaders(const EhdrType& ehdr)
120 {
121     uint64_t offset = ehdr.e_phoff;
122     bool firstLoadHeader = true;
123     for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
124         PhdrType phdr;
125         if (!Read((uintptr_t)offset, &phdr, sizeof(phdr))) {
126             return false;
127         }
128 
129         switch (phdr.p_type) {
130             case PT_LOAD: {
131                 ElfLoadInfo loadInfo;
132                 loadInfo.offset = phdr.p_offset;
133                 loadInfo.tableVaddr = phdr.p_vaddr;
134                 loadInfo.tableSize = static_cast<size_t>(phdr.p_memsz);
135                 loadInfo.align = phdr.p_align;
136                 if (loadInfo.align == 0) {
137                     continue;
138                 }
139                 uint64_t len = loadInfo.tableSize + (loadInfo.tableVaddr & (loadInfo.align - 1));
140                 loadInfo.mmapLen = len - (len & (loadInfo.align - 1)) + loadInfo.align;
141                 ptLoads_[phdr.p_offset] = loadInfo;
142                 if ((phdr.p_flags & PF_X) == 0) {
143                     continue;
144                 }
145                 // Only set the load bias from the first executable load header.
146                 if (firstLoadHeader) {
147                     loadBias_ = static_cast<int64_t>(static_cast<uint64_t>(phdr.p_vaddr) - phdr.p_offset);
148                 }
149                 firstLoadHeader = false;
150 
151                 if (static_cast<uint64_t>(phdr.p_vaddr) < static_cast<uint64_t>(startVaddr_)) {
152                     startVaddr_ = static_cast<uint64_t>(phdr.p_vaddr);
153                     startOffset_ = static_cast<uint64_t>(phdr.p_offset);
154                 }
155                 if (static_cast<uint64_t>(phdr.p_vaddr + phdr.p_memsz) > static_cast<uint64_t>(endVaddr_)) {
156                     endVaddr_ = static_cast<uint64_t>(phdr.p_vaddr + phdr.p_memsz);
157                 }
158                 DFXLOGU("Elf startVaddr: %{public}" PRIx64 ", endVaddr: %{public}" PRIx64 "",
159                     startVaddr_, endVaddr_);
160                 break;
161             }
162             case PT_DYNAMIC: {
163                 dynamicOffset_ = phdr.p_offset;
164                 break;
165             }
166             default:
167                 break;
168         }
169     }
170     return true;
171 }
172 
GetGnuDebugDataHdr() const173 const GnuDebugDataHdr& ElfParser::GetGnuDebugDataHdr() const
174 {
175     return gnuDebugDataHdr_;
176 }
177 
178 template <typename EhdrType, typename ShdrType>
ExtractSectionHeadersInfo(const EhdrType & ehdr,ShdrType & shdr)179 bool ElfParser::ExtractSectionHeadersInfo(const EhdrType& ehdr, ShdrType& shdr)
180 {
181     uint64_t offset = ehdr.e_shoff;
182     offset += ehdr.e_shentsize;
183     for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
184         if (i == ehdr.e_shstrndx) {
185             continue;
186         }
187         if (!Read((uintptr_t)offset, &shdr, sizeof(shdr))) {
188             return false;
189         }
190 
191         std::string secName;
192         if (!GetSectionNameByIndex(secName, shdr.sh_name)) {
193             DFXLOGE("Failed to get section name");
194             continue;
195         }
196 
197         if (shdr.sh_size != 0 && secName == GNU_DEBUGDATA) {
198             gnuDebugDataHdr_.address = reinterpret_cast<uintptr_t>(shdr.sh_offset +
199                 static_cast<uint8_t *>(mmap_->Get()));
200             gnuDebugDataHdr_.size = static_cast<uintptr_t>(shdr.sh_size);
201         }
202 
203         ShdrInfo shdrInfo;
204         shdrInfo.addr = static_cast<uint64_t>(shdr.sh_addr);
205         shdrInfo.entSize = static_cast<uint64_t>(shdr.sh_entsize);
206         shdrInfo.size = static_cast<uint64_t>(shdr.sh_size);
207         shdrInfo.offset = static_cast<uint64_t>(shdr.sh_offset);
208         shdrInfoPairs_.emplace(std::make_pair(i, secName), shdrInfo);
209 
210         if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
211             if (shdr.sh_link >= ehdr.e_shnum) {
212                 continue;
213             }
214             ElfShdr elfShdr;
215             elfShdr.name = static_cast<uint32_t>(shdr.sh_name);
216             elfShdr.type = static_cast<uint32_t>(shdr.sh_type);
217             elfShdr.flags = static_cast<uint64_t>(shdr.sh_flags);
218             elfShdr.addr = static_cast<uint64_t>(shdr.sh_addr);
219             elfShdr.offset = static_cast<uint64_t>(shdr.sh_offset);
220             elfShdr.size = static_cast<uint64_t>(shdr.sh_size);
221             elfShdr.link = static_cast<uint32_t>(shdr.sh_link);
222             elfShdr.info = static_cast<uint32_t>(shdr.sh_info);
223             elfShdr.addrAlign = static_cast<uint64_t>(shdr.sh_addralign);
224             elfShdr.entSize = static_cast<uint64_t>(shdr.sh_entsize);
225             symShdrs_.emplace_back(elfShdr);
226         }
227     }
228     return true;
229 }
230 
231 template <typename EhdrType, typename ShdrType>
ParseSectionHeaders(const EhdrType & ehdr)232 bool ElfParser::ParseSectionHeaders(const EhdrType& ehdr)
233 {
234     ShdrType shdr;
235     //section header string table index. include section header table with section name string table.
236     if (ehdr.e_shstrndx < ehdr.e_shnum) {
237         uint64_t secOffset = 0;
238         uint64_t secSize = 0;
239         uint64_t shNdxOffset = ehdr.e_shoff + ehdr.e_shstrndx * ehdr.e_shentsize;
240         if (!Read(static_cast<uintptr_t>(shNdxOffset), &shdr, sizeof(shdr))) {
241             DFXLOGE("Read section header string table failed");
242             return false;
243         }
244         secOffset = shdr.sh_offset;
245         secSize = shdr.sh_size;
246         if (!ParseStrTab(sectionNames_, secOffset, secSize)) {
247             return false;
248         }
249     } else {
250         DFXLOGE("e_shstrndx(%{public}u) cannot greater than or equal e_shnum(%{public}u)",
251             ehdr.e_shstrndx, ehdr.e_shnum);
252         return false;
253     }
254 
255     if (!ExtractSectionHeadersInfo(ehdr, shdr)) {
256         return false;
257     }
258 
259     return true;
260 }
261 
262 template <typename DynType>
ParseElfDynamic()263 bool ElfParser::ParseElfDynamic()
264 {
265     if (dynamicOffset_ == 0 || mmap_->Get() == nullptr) {
266         return false;
267     }
268 
269     DynType* dyn = reinterpret_cast<DynType *>(dynamicOffset_ + static_cast<char *>(mmap_->Get()));
270     if (dyn == nullptr) {
271         return false;
272     }
273     for (; dyn->d_tag != DT_NULL; ++dyn) {
274         if (dyn->d_tag == DT_PLTGOT) {
275             // Assume that _DYNAMIC is writable and GLIBC has relocated it (true for x86 at least).
276             dtPltGotAddr_ = dyn->d_un.d_ptr;
277             break;
278         } else if (dyn->d_tag == DT_STRTAB) {
279             dtStrtabAddr_ = dyn->d_un.d_ptr;
280         } else if (dyn->d_tag == DT_STRSZ) {
281             dtStrtabSize_ = dyn->d_un.d_val;
282         } else if (dyn->d_tag == DT_SONAME) {
283             dtSonameOffset_ = dyn->d_un.d_val;
284         }
285     }
286     return true;
287 }
288 
289 template <typename DynType>
ParseElfName()290 bool ElfParser::ParseElfName()
291 {
292     if (!ParseElfDynamic<DynType>()) {
293         return false;
294     }
295     ShdrInfo shdrInfo;
296     if (!GetSectionInfo(shdrInfo, DYNSTR)) {
297         return false;
298     }
299     uintptr_t sonameOffset = shdrInfo.offset + dtSonameOffset_;
300     uint64_t sonameOffsetMax = shdrInfo.offset + dtStrtabSize_;
301     size_t maxStrSize = static_cast<size_t>(sonameOffsetMax - sonameOffset);
302     mmap_->ReadString(sonameOffset, &soname_, maxStrSize);
303     DFXLOGU("parse current elf file soname is %{public}s.", soname_.c_str());
304     return true;
305 }
306 
307 template <typename SymType>
IsFunc(const SymType sym)308 bool ElfParser::IsFunc(const SymType sym)
309 {
310     return ((sym.st_shndx != SHN_UNDEF) &&
311         (ELF32_ST_TYPE(sym.st_info) == STT_FUNC || ELF32_ST_TYPE(sym.st_info) == STT_GNU_IFUNC));
312 }
313 
314 template <typename SymType>
ParseFuncSymbols()315 bool ElfParser::ParseFuncSymbols()
316 {
317     if (symShdrs_.empty()) {
318         return false;
319     }
320 
321     funcSymbols_.clear();
322     for (const auto& iter : symShdrs_) {
323         const auto& shdr = iter;
324         ParseFuncSymbols<SymType>(shdr);
325     }
326     return (funcSymbols_.size() > 0);
327 }
328 
329 template <typename SymType>
ReadSymType(const ElfShdr & shdr,const uint32_t idx,SymType & sym)330 bool ElfParser::ReadSymType(const ElfShdr& shdr, const uint32_t idx, SymType& sym)
331 {
332     uintptr_t offset = static_cast<uintptr_t>(shdr.offset + idx * shdr.entSize);
333     if (!Read(offset, &sym, sizeof(sym))) {
334         return false;
335     }
336     if (sym.st_value == 0 || sym.st_size == 0) {
337         return false;
338     }
339     return true;
340 }
341 
342 template <typename SymType>
ParseFuncSymbols(const ElfShdr & shdr)343 bool ElfParser::ParseFuncSymbols(const ElfShdr& shdr)
344 {
345     ShdrInfo linkShdrInfo;
346     if (!GetSectionInfo(linkShdrInfo, shdr.link)) {
347         return false;
348     }
349 
350     uint32_t count = static_cast<uint32_t>((shdr.entSize != 0) ? (shdr.size / shdr.entSize) : 0);
351     for (uint32_t idx = 0; idx < count; ++idx) {
352         SymType sym;
353         if (!ReadSymType(shdr, idx, sym)) {
354             continue;
355         }
356         ElfSymbol elfSymbol;
357         if (!ParseFuncSymbolName(linkShdrInfo, sym, elfSymbol.nameStr)) {
358             continue;
359         }
360         elfSymbol.value = static_cast<uint64_t>(sym.st_value);
361         elfSymbol.size = static_cast<uint64_t>(sym.st_size);
362         elfSymbol.name = static_cast<uint32_t>(sym.st_name);
363         funcSymbols_.emplace(elfSymbol);
364     }
365     DFXLOGU("elfSymbols.size: %{public}" PRIuPTR "", funcSymbols_.size());
366     return true;
367 }
368 
369 template <typename SymType>
ParseFuncSymbolName(const ShdrInfo & linkShdr,SymType sym,std::string & nameStr)370 bool ElfParser::ParseFuncSymbolName(const ShdrInfo& linkShdr, SymType sym, std::string& nameStr)
371 {
372     if (!IsFunc(sym) || (static_cast<uint64_t>(sym.st_name) >= linkShdr.size) || mmap_->Get() == nullptr) {
373         return false;
374     }
375     uintptr_t nameOffset = static_cast<uintptr_t>(linkShdr.offset + sym.st_name);
376     nameStr = std::string(static_cast<char*>(mmap_->Get()) + nameOffset);
377     return true;
378 }
379 
380 template <typename SymType>
ParseFuncSymbolByAddr(uint64_t addr,ElfSymbol & elfSymbol)381 bool ElfParser::ParseFuncSymbolByAddr(uint64_t addr, ElfSymbol& elfSymbol)
382 {
383     if (symShdrs_.empty()) {
384         return false;
385     }
386 
387     for (const auto& shdr : symShdrs_) {
388         ShdrInfo linkShdrInfo;
389         if (!GetSectionInfo(linkShdrInfo, shdr.link)) {
390             return false;
391         }
392 
393         uint32_t count = static_cast<uint32_t>((shdr.entSize != 0) ? (shdr.size / shdr.entSize) : 0);
394         for (uint32_t idx = 0; idx < count; ++idx) {
395             SymType sym;
396             if (!ReadSymType(shdr, idx, sym)) {
397                 continue;
398             }
399 
400             if ((sym.st_value <= addr) && (addr < (sym.st_value + sym.st_size)) &&
401                 ParseFuncSymbolName(linkShdrInfo, sym, elfSymbol.nameStr)) {
402                 elfSymbol.value = static_cast<uint64_t>(sym.st_value);
403                 elfSymbol.size = static_cast<uint64_t>(sym.st_size);
404                 elfSymbol.name = static_cast<uint32_t>(sym.st_name);
405                 DFXLOGU("Parse elf symbol nameStr: %{public}s", elfSymbol.nameStr.c_str());
406                 return true;
407             }
408         }
409     }
410     return false;
411 }
412 
GetSectionNameByIndex(std::string & nameStr,const uint32_t name)413 bool ElfParser::GetSectionNameByIndex(std::string& nameStr, const uint32_t name)
414 {
415     if (sectionNames_.empty() || name >= sectionNames_.size()) {
416         DFXLOGE("name index(%{public}u) out of range, size: %{public}" PRIuPTR "", name, sectionNames_.size());
417         return false;
418     }
419 
420     size_t endIndex = sectionNames_.find('\0', name);
421     if (endIndex != std::string::npos) {
422         nameStr = sectionNames_.substr(name, endIndex - name);
423         return true;
424     }
425     return false;
426 }
427 
ParseStrTab(std::string & nameStr,const uint64_t offset,const uint64_t size)428 bool ElfParser::ParseStrTab(std::string& nameStr, const uint64_t offset, const uint64_t size)
429 {
430     if (size > MmapSize()) {
431         DFXLOGE("size(%{public}" PRIu64 ") is too large.", size);
432         return false;
433     }
434     std::vector<char> namesBuf(size, 0);
435     if (!Read((uintptr_t)offset, namesBuf.data(), size)) {
436         DFXLOGE("Read failed");
437         return false;
438     }
439     nameStr = std::string(namesBuf.begin(), namesBuf.begin() + size);
440     return true;
441 }
442 
GetSectionInfo(ShdrInfo & shdr,const uint32_t idx)443 bool ElfParser::GetSectionInfo(ShdrInfo& shdr, const uint32_t idx)
444 {
445     for (const auto& iter: shdrInfoPairs_) {
446         auto tmpPair = iter.first;
447         if (tmpPair.first == idx) {
448             shdr = iter.second;
449             return true;
450         }
451     }
452     return false;
453 }
454 
GetSectionInfo(ShdrInfo & shdr,const std::string & secName)455 bool ElfParser::GetSectionInfo(ShdrInfo& shdr, const std::string& secName)
456 {
457     for (const auto& iter: shdrInfoPairs_) {
458         auto tmpPair = iter.first;
459         if (tmpPair.second == secName) {
460             shdr = iter.second;
461             return true;
462         }
463     }
464     return false;
465 }
466 
GetSectionData(unsigned char * buf,uint64_t size,std::string secName)467 bool ElfParser::GetSectionData(unsigned char* buf, uint64_t size, std::string secName)
468 {
469     ShdrInfo shdr;
470     if (GetSectionInfo(shdr, secName)) {
471         if (Read(shdr.offset, buf, size)) {
472             return true;
473         }
474     } else {
475         DFXLOGE("Failed to get data from secName %{public}s", secName.c_str());
476     }
477     return false;
478 }
479 
GetBuildId()480 std::string ElfParser::GetBuildId()
481 {
482     ShdrInfo shdr;
483     std::string buildId = "";
484     if ((GetSectionInfo(shdr, NOTE_GNU_BUILD_ID) || GetSectionInfo(shdr, NOTES)) && mmap_->Get() != nullptr) {
485         std::string buildIdHex = ParseHexBuildId((uint64_t)((char *)mmap_->Get() + shdr.offset), shdr.size);
486         if (!buildIdHex.empty()) {
487             buildId = ToReadableBuildId(buildIdHex);
488             DFXLOGU("Elf buildId: %{public}s", buildId.c_str());
489         }
490     }
491     return buildId;
492 }
493 
ParseHexBuildId(uint64_t noteAddr,uint64_t noteSize)494 std::string ElfParser::ParseHexBuildId(uint64_t noteAddr, uint64_t noteSize)
495 {
496     uint64_t tmp;
497     if (__builtin_add_overflow(noteAddr, noteSize, &tmp)) {
498         DFXLOGE("noteAddr overflow");
499         return "";
500     }
501     uint64_t offset = 0;
502     while (offset < noteSize) {
503         ElfW(Nhdr) nhdr;
504         if (noteSize - offset < sizeof(nhdr)) {
505             return "";
506         }
507         uint64_t ptr = noteAddr + offset;
508         if (memcpy_s(&nhdr, sizeof(nhdr), reinterpret_cast<void*>(ptr), sizeof(nhdr)) != 0) {
509             DFXLOGE("memcpy_s nhdr failed");
510             return "";
511         }
512         offset += sizeof(nhdr);
513         if (noteSize - offset < nhdr.n_namesz) {
514             return "";
515         }
516         if (nhdr.n_namesz > 0) {
517             std::string name(nhdr.n_namesz, '\0');
518             ptr = noteAddr + offset;
519             if (memcpy_s(&(name[0]), name.size(), reinterpret_cast<void*>(ptr), nhdr.n_namesz) != 0) {
520                 DFXLOGE("memcpy_s note name failed");
521                 return "";
522             }
523             // Trim trailing \0 as GNU is stored as a C string in the ELF file.
524             if (name.size() != 0 && name.back() == '\0') {
525                 name.resize(name.size() - 1);
526             }
527             // Align nhdr.n_namesz to next power multiple of 4. See man 5 elf.
528             offset += (nhdr.n_namesz + 3) & ~3; // 3 : Align the offset to a 4-byte boundary
529             if (name != "GNU" || nhdr.n_type != NT_GNU_BUILD_ID) {
530                 offset += (nhdr.n_descsz + 3) & ~3; // 3 : Align the offset to a 4-byte boundary
531                 continue;
532             }
533             if (noteSize - offset < nhdr.n_descsz || nhdr.n_descsz == 0) {
534                 return "";
535             }
536             std::string buildIdRaw(nhdr.n_descsz, '\0');
537             ptr = noteAddr + offset;
538             if (memcpy_s(&buildIdRaw[0], buildIdRaw.size(), reinterpret_cast<void*>(ptr), nhdr.n_descsz) != 0) {
539                 return "";
540             }
541             return buildIdRaw;
542         }
543         // Align hdr.n_descsz to next power multiple of 4. See man 5 elf.
544         offset += (nhdr.n_descsz + 3) & ~3; // 3 : Align the offset to a 4-byte boundary
545     }
546     return "";
547 }
548 
ToReadableBuildId(const std::string & buildIdHex)549 std::string ElfParser::ToReadableBuildId(const std::string& buildIdHex)
550 {
551     if (buildIdHex.empty()) {
552         return "";
553     }
554     const char hexTable[] = "0123456789abcdef";
555     const int hexLength = 16;
556     const int hexExpandParam = 2;
557     const size_t len = buildIdHex.length();
558     std::string buildId(len * hexExpandParam, '\0');
559 
560     for (size_t i = 0; i < len; i++) {
561         unsigned int n = buildIdHex[i];
562         buildId[i * hexExpandParam] = hexTable[(n >> 4) % hexLength]; // 4 : higher 4 bit of uint8
563         buildId[i * hexExpandParam + 1] = hexTable[n % hexLength];
564     }
565     return buildId;
566 }
567 
InitHeaders()568 bool ElfParser32::InitHeaders()
569 {
570     return ParseAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>();
571 }
572 
InitHeaders()573 bool ElfParser64::InitHeaders()
574 {
575     return ParseAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>();
576 }
577 
GetElfName()578 std::string ElfParser32::GetElfName()
579 {
580     if (soname_ == "") {
581         ParseElfName<Elf32_Dyn>();
582     }
583     return soname_;
584 }
585 
GetElfName()586 std::string ElfParser64::GetElfName()
587 {
588     if (soname_ == "") {
589         ParseElfName<Elf64_Dyn>();
590     }
591     return soname_;
592 }
593 
GetGlobalPointer()594 uintptr_t ElfParser32::GetGlobalPointer()
595 {
596     if (dtPltGotAddr_ == 0) {
597         ParseElfDynamic<Elf32_Dyn>();
598     }
599     return dtPltGotAddr_;
600 }
601 
GetGlobalPointer()602 uintptr_t ElfParser64::GetGlobalPointer()
603 {
604     if (dtPltGotAddr_ == 0) {
605         ParseElfDynamic<Elf64_Dyn>();
606     }
607     return dtPltGotAddr_;
608 }
609 
GetFuncSymbols()610 const std::set<ElfSymbol>& ElfParser32::GetFuncSymbols()
611 {
612     ParseFuncSymbols<Elf32_Sym>();
613     return funcSymbols_;
614 }
615 
GetFuncSymbols()616 const std::set<ElfSymbol>& ElfParser64::GetFuncSymbols()
617 {
618     ParseFuncSymbols<Elf64_Sym>();
619     return funcSymbols_;
620 }
621 
GetFuncSymbolByAddr(uint64_t addr,ElfSymbol & elfSymbol)622 bool ElfParser32::GetFuncSymbolByAddr(uint64_t addr, ElfSymbol& elfSymbol)
623 {
624     return ParseFuncSymbolByAddr<Elf32_Sym>(addr, elfSymbol);
625 }
626 
GetFuncSymbolByAddr(uint64_t addr,ElfSymbol & elfSymbol)627 bool ElfParser64::GetFuncSymbolByAddr(uint64_t addr, ElfSymbol& elfSymbol)
628 {
629     return ParseFuncSymbolByAddr<Elf64_Sym>(addr, elfSymbol);
630 }
631 } // namespace HiviewDFX
632 } // namespace OHOS
633