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