1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2023-2024 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 "elf_imitate.h"
17800b99b8Sopenharmony_ci
18800b99b8Sopenharmony_ci#include <cstdlib>
19800b99b8Sopenharmony_ci#include <securec.h>
20800b99b8Sopenharmony_ci#include <string>
21800b99b8Sopenharmony_ci#include <sys/mman.h>
22800b99b8Sopenharmony_ci#include <sys/types.h>
23800b99b8Sopenharmony_ci#include <unistd.h>
24800b99b8Sopenharmony_ci#include <utility>
25800b99b8Sopenharmony_ci#include "dfx_define.h"
26800b99b8Sopenharmony_ci#include "dfx_log.h"
27800b99b8Sopenharmony_ci#include "dfx_util.h"
28800b99b8Sopenharmony_ci#include <iostream>
29800b99b8Sopenharmony_ci
30800b99b8Sopenharmony_ci#ifndef PAGE_SIZE
31800b99b8Sopenharmony_ci#define PAGE_SIZE 4096
32800b99b8Sopenharmony_ci#endif
33800b99b8Sopenharmony_ci
34800b99b8Sopenharmony_cinamespace {
35800b99b8Sopenharmony_ciconst std::string EHDR_32 {"/data/test/resource/testdata/ehdr_from_readelf_32"};
36800b99b8Sopenharmony_ciconst std::string EHDR_64 {"/data/test/resource/testdata/ehdr_from_readelf_64"};
37800b99b8Sopenharmony_ciconst std::string SHDRS_32 {"/data/test/resource/testdata/shdrs_from_readelf_32"};
38800b99b8Sopenharmony_ciconst std::string SHDRS_64 {"/data/test/resource/testdata/shdrs_from_readelf_64"};
39800b99b8Sopenharmony_ciconst std::string PHDRS_32 {"/data/test/resource/testdata/phdrs_from_readelf_32"};
40800b99b8Sopenharmony_ciconst std::string PHDRS_64 {"/data/test/resource/testdata/phdrs_from_readelf_64"};
41800b99b8Sopenharmony_ciconst std::string SYMS_32 {"/data/test/resource/testdata/syms_from_readelf_32"};
42800b99b8Sopenharmony_ciconst std::string SYMS_64 {"/data/test/resource/testdata/syms_from_readelf_64"};
43800b99b8Sopenharmony_ci} // namespace
44800b99b8Sopenharmony_cinamespace OHOS {
45800b99b8Sopenharmony_cinamespace HiviewDFX {
46800b99b8Sopenharmony_ciElfImitate::~ElfImitate()
47800b99b8Sopenharmony_ci{
48800b99b8Sopenharmony_ci    if (ehdrFP_ != nullptr) {
49800b99b8Sopenharmony_ci        fclose(ehdrFP_);
50800b99b8Sopenharmony_ci        ehdrFP_ = nullptr;
51800b99b8Sopenharmony_ci    }
52800b99b8Sopenharmony_ci    if (shdrFP_ != nullptr) {
53800b99b8Sopenharmony_ci        fclose(shdrFP_);
54800b99b8Sopenharmony_ci        shdrFP_ = nullptr;
55800b99b8Sopenharmony_ci    }
56800b99b8Sopenharmony_ci    if (phdrFP_ != nullptr) {
57800b99b8Sopenharmony_ci        fclose(phdrFP_);
58800b99b8Sopenharmony_ci        phdrFP_ = nullptr;
59800b99b8Sopenharmony_ci    }
60800b99b8Sopenharmony_ci    if (symTabFP_ != nullptr) {
61800b99b8Sopenharmony_ci        fclose(symTabFP_);
62800b99b8Sopenharmony_ci        symTabFP_ = nullptr;
63800b99b8Sopenharmony_ci    }
64800b99b8Sopenharmony_ci}
65800b99b8Sopenharmony_ci
66800b99b8Sopenharmony_cistatic const std::string GetNextLine(FILE *fp, int *status)
67800b99b8Sopenharmony_ci{
68800b99b8Sopenharmony_ci    constexpr int bufSize {128};
69800b99b8Sopenharmony_ci    char buf[bufSize] = {0};
70800b99b8Sopenharmony_ci    if (fgets(buf, bufSize, fp) == nullptr) {
71800b99b8Sopenharmony_ci        DFXLOGE("fgets() failed");
72800b99b8Sopenharmony_ci        *status = -1;
73800b99b8Sopenharmony_ci        return "";
74800b99b8Sopenharmony_ci    }
75800b99b8Sopenharmony_ci    *status = 0;
76800b99b8Sopenharmony_ci    std::string res {buf};
77800b99b8Sopenharmony_ci    if (res.back() == '\n') {
78800b99b8Sopenharmony_ci        res.pop_back();
79800b99b8Sopenharmony_ci    }
80800b99b8Sopenharmony_ci    return res;
81800b99b8Sopenharmony_ci}
82800b99b8Sopenharmony_cistd::vector<std::string> ElfImitate::StringSplit(std::string src, const std::string split)
83800b99b8Sopenharmony_ci{
84800b99b8Sopenharmony_ci    std::vector<std::string> result;
85800b99b8Sopenharmony_ci
86800b99b8Sopenharmony_ci    if (!split.empty()) {
87800b99b8Sopenharmony_ci        size_t pos = 0;
88800b99b8Sopenharmony_ci        while ((pos = src.find(split)) != std::string::npos) {
89800b99b8Sopenharmony_ci            // split
90800b99b8Sopenharmony_ci            std::string token = src.substr(0, pos);
91800b99b8Sopenharmony_ci            if (!token.empty()) {
92800b99b8Sopenharmony_ci                result.push_back(token);
93800b99b8Sopenharmony_ci            }
94800b99b8Sopenharmony_ci            src.erase(0, pos + split.length());
95800b99b8Sopenharmony_ci        }
96800b99b8Sopenharmony_ci    }
97800b99b8Sopenharmony_ci
98800b99b8Sopenharmony_ci    if (!src.empty()) {
99800b99b8Sopenharmony_ci        result.push_back(src);
100800b99b8Sopenharmony_ci    }
101800b99b8Sopenharmony_ci    return result;
102800b99b8Sopenharmony_ci}
103800b99b8Sopenharmony_ci
104800b99b8Sopenharmony_cibool ElfImitate::ParseAllHeaders(ElfFileType fileType)
105800b99b8Sopenharmony_ci{
106800b99b8Sopenharmony_ci    if (fileType == ElfFileType::ELF32) {
107800b99b8Sopenharmony_ci        ehdrFP_ = std::fopen(EHDR_32.c_str(), "rb");
108800b99b8Sopenharmony_ci        if (ehdrFP_ == nullptr) {
109800b99b8Sopenharmony_ci            DFXLOGE("fopen(EHDR_32, \"r\") failed");
110800b99b8Sopenharmony_ci        }
111800b99b8Sopenharmony_ci        shdrFP_ = fopen(SHDRS_32.c_str(), "rb");
112800b99b8Sopenharmony_ci        if (shdrFP_ == nullptr) {
113800b99b8Sopenharmony_ci            DFXLOGE("fopen(SHDRS_32, \"r\") failed");
114800b99b8Sopenharmony_ci        }
115800b99b8Sopenharmony_ci        phdrFP_ = fopen(PHDRS_32.c_str(), "rb");
116800b99b8Sopenharmony_ci        if (phdrFP_ == nullptr) {
117800b99b8Sopenharmony_ci            DFXLOGE("fopen(PHDRS_32, \"r\") failed");
118800b99b8Sopenharmony_ci        }
119800b99b8Sopenharmony_ci        symTabFP_ = fopen(SYMS_32.c_str(), "rb");
120800b99b8Sopenharmony_ci        if (symTabFP_ == nullptr) {
121800b99b8Sopenharmony_ci            DFXLOGE("fopen(SYMS_32, \"r\") failed");
122800b99b8Sopenharmony_ci        }
123800b99b8Sopenharmony_ci    } else if (fileType == ElfFileType::ELF64) {
124800b99b8Sopenharmony_ci        ehdrFP_ = fopen(EHDR_64.c_str(), "rb");
125800b99b8Sopenharmony_ci        if (ehdrFP_ == nullptr) {
126800b99b8Sopenharmony_ci            DFXLOGE("fopen(EHDR_64, \"r\") failed");
127800b99b8Sopenharmony_ci        }
128800b99b8Sopenharmony_ci        shdrFP_ = fopen(SHDRS_64.c_str(), "rb");
129800b99b8Sopenharmony_ci        if (shdrFP_ == nullptr) {
130800b99b8Sopenharmony_ci            DFXLOGE("fopen(SHDRS_64, \"r\") failed");
131800b99b8Sopenharmony_ci        }
132800b99b8Sopenharmony_ci        phdrFP_ = fopen(PHDRS_64.c_str(), "rb");
133800b99b8Sopenharmony_ci        if (phdrFP_ == nullptr) {
134800b99b8Sopenharmony_ci            DFXLOGE("fopen(PHDRS_64, \"r\") failed");
135800b99b8Sopenharmony_ci        }
136800b99b8Sopenharmony_ci        symTabFP_ = fopen(SYMS_64.c_str(), "rb");
137800b99b8Sopenharmony_ci        if (symTabFP_ == nullptr) {
138800b99b8Sopenharmony_ci            DFXLOGE("fopen(SYMS_64, \"r\") failed");
139800b99b8Sopenharmony_ci        }
140800b99b8Sopenharmony_ci    }
141800b99b8Sopenharmony_ci    if (!ParseElfHeaders()) {
142800b99b8Sopenharmony_ci        DFXLOGW("ParseElfHeaders failed");
143800b99b8Sopenharmony_ci        return false;
144800b99b8Sopenharmony_ci    }
145800b99b8Sopenharmony_ci
146800b99b8Sopenharmony_ci    if (!ParseProgramHeaders(fileType)) {
147800b99b8Sopenharmony_ci        DFXLOGW("ParseProgramHeaders failed");
148800b99b8Sopenharmony_ci        return false;
149800b99b8Sopenharmony_ci    }
150800b99b8Sopenharmony_ci
151800b99b8Sopenharmony_ci    if (!ParseSectionHeaders(fileType)) {
152800b99b8Sopenharmony_ci        DFXLOGW("ReadSectionHeaders failed");
153800b99b8Sopenharmony_ci        return false;
154800b99b8Sopenharmony_ci    }
155800b99b8Sopenharmony_ci    if (!ParseElfSymbols()) {
156800b99b8Sopenharmony_ci        DFXLOGW("ParseElfSymbols failed");
157800b99b8Sopenharmony_ci        return false;
158800b99b8Sopenharmony_ci    }
159800b99b8Sopenharmony_ci    return true;
160800b99b8Sopenharmony_ci}
161800b99b8Sopenharmony_ci
162800b99b8Sopenharmony_cibool ElfImitate::ParseElfHeaders()
163800b99b8Sopenharmony_ci{
164800b99b8Sopenharmony_ci    if (ehdrFP_ == nullptr) {
165800b99b8Sopenharmony_ci        DFXLOGE("param is null");
166800b99b8Sopenharmony_ci        return false;
167800b99b8Sopenharmony_ci    }
168800b99b8Sopenharmony_ci    int status {0};
169800b99b8Sopenharmony_ci    // drop header line
170800b99b8Sopenharmony_ci    GetNextLine(ehdrFP_, &status);
171800b99b8Sopenharmony_ci    if (!GetMagic(ehdrFP_)) {
172800b99b8Sopenharmony_ci        DFXLOGE("ElfImitate::InitMagic(ehdrFP_) failed:");
173800b99b8Sopenharmony_ci        return false;
174800b99b8Sopenharmony_ci    }
175800b99b8Sopenharmony_ci    if (!GetClass(ehdrFP_)) {
176800b99b8Sopenharmony_ci        DFXLOGE("ElfImitate::InitClass(ehdrFP_) failed:");
177800b99b8Sopenharmony_ci        return false;
178800b99b8Sopenharmony_ci    }
179800b99b8Sopenharmony_ci    constexpr int numSkip {6};
180800b99b8Sopenharmony_ci    // drop unused 6 lines
181800b99b8Sopenharmony_ci    for (int count = 0; count < numSkip; ++count) {
182800b99b8Sopenharmony_ci        GetNextLine(ehdrFP_, &status);
183800b99b8Sopenharmony_ci    }
184800b99b8Sopenharmony_ci    if (!GetMachine(ehdrFP_)) {
185800b99b8Sopenharmony_ci        DFXLOGE("ElfImitate::InitMachine(ehdrFP_) failed:");
186800b99b8Sopenharmony_ci    }
187800b99b8Sopenharmony_ci
188800b99b8Sopenharmony_ci    if (machine_ == "ARM") {
189800b99b8Sopenharmony_ci        archType_ = ARCH_ARM;
190800b99b8Sopenharmony_ci    } else if (machine_ == "80386") {
191800b99b8Sopenharmony_ci        archType_ = ARCH_X86;
192800b99b8Sopenharmony_ci    } else if (machine_ == "AARCH64") {
193800b99b8Sopenharmony_ci        archType_ = ARCH_ARM64;
194800b99b8Sopenharmony_ci    } else if (machine_ == "X86-64") {
195800b99b8Sopenharmony_ci        archType_ = ARCH_X86_64;
196800b99b8Sopenharmony_ci    } else {
197800b99b8Sopenharmony_ci        DFXLOGW("Failed the machine = %{public}s", machine_.c_str());
198800b99b8Sopenharmony_ci    }
199800b99b8Sopenharmony_ci
200800b99b8Sopenharmony_ci    if (!GetEntryAddr(ehdrFP_)) {
201800b99b8Sopenharmony_ci        DFXLOGE("ElfImitate::InitEntryAddr(ehdrFP_) failed:");
202800b99b8Sopenharmony_ci        return false;
203800b99b8Sopenharmony_ci    }
204800b99b8Sopenharmony_ci    if (!GetPrgOffset(ehdrFP_)) {
205800b99b8Sopenharmony_ci        DFXLOGE("ElfImitate::InitPrgOffset(ehdrFP_) failed:");
206800b99b8Sopenharmony_ci        return false;
207800b99b8Sopenharmony_ci    }
208800b99b8Sopenharmony_ci    if (!GetSecOffset(ehdrFP_)) {
209800b99b8Sopenharmony_ci        DFXLOGE("ElfImitate::InitSecOffset(ehdrFP_) failed:");
210800b99b8Sopenharmony_ci        return false;
211800b99b8Sopenharmony_ci    }
212800b99b8Sopenharmony_ci    if (!GetFlag(ehdrFP_)) {
213800b99b8Sopenharmony_ci        DFXLOGE("ElfImitate::InitFlag(ehdrFP_) failed:");
214800b99b8Sopenharmony_ci        return false;
215800b99b8Sopenharmony_ci    }
216800b99b8Sopenharmony_ci    if (!GetEhdrSize(ehdrFP_)) {
217800b99b8Sopenharmony_ci        DFXLOGE("ElfImitate::InitEhdrSize(ehdrFP_) failed:");
218800b99b8Sopenharmony_ci        return false;
219800b99b8Sopenharmony_ci    }
220800b99b8Sopenharmony_ci    if (!GetPhdrSize(ehdrFP_)) {
221800b99b8Sopenharmony_ci        DFXLOGE("ElfImitate::InitPhdrSize(ehdrFP_) failed:");
222800b99b8Sopenharmony_ci        return false;
223800b99b8Sopenharmony_ci    }
224800b99b8Sopenharmony_ci    if (!GetNumPhdrs(ehdrFP_)) {
225800b99b8Sopenharmony_ci        DFXLOGE("ElfImitate::InitNumPhdrs(ehdrFP_) failed:");
226800b99b8Sopenharmony_ci        return false;
227800b99b8Sopenharmony_ci    }
228800b99b8Sopenharmony_ci    if (!GetShdrSize(ehdrFP_)) {
229800b99b8Sopenharmony_ci        DFXLOGE("ElfImitate::InitShdrSize(ehdrFP_) failed:");
230800b99b8Sopenharmony_ci        return false;
231800b99b8Sopenharmony_ci    }
232800b99b8Sopenharmony_ci    if (!GetNumShdrs(ehdrFP_)) {
233800b99b8Sopenharmony_ci        DFXLOGE("ElfImitate::InitNumShdrs(ehdrFP_) failed:");
234800b99b8Sopenharmony_ci        return false;
235800b99b8Sopenharmony_ci    }
236800b99b8Sopenharmony_ci    if (!GetShdrStrTabIdx(ehdrFP_)) {
237800b99b8Sopenharmony_ci        DFXLOGE("ElfImitate::InitShdrStrTabIdx(ehdrFP_) failed:");
238800b99b8Sopenharmony_ci        return false;
239800b99b8Sopenharmony_ci    }
240800b99b8Sopenharmony_ci    elfSize_ = shdrOffset_ + shdrEntSize_ * shdrNumEnts_;
241800b99b8Sopenharmony_ci    return true;
242800b99b8Sopenharmony_ci}
243800b99b8Sopenharmony_cibool ElfImitate::GetMagic(FILE * const fp)
244800b99b8Sopenharmony_ci{
245800b99b8Sopenharmony_ci    if (fp == nullptr) {
246800b99b8Sopenharmony_ci        DFXLOGE("param is null");
247800b99b8Sopenharmony_ci        return false;
248800b99b8Sopenharmony_ci    }
249800b99b8Sopenharmony_ci    int status {0};
250800b99b8Sopenharmony_ci    std::string magicLine = GetNextLine(fp, &status);
251800b99b8Sopenharmony_ci    if (status == -1) {
252800b99b8Sopenharmony_ci        DFXLOGE("early end");
253800b99b8Sopenharmony_ci        return false;
254800b99b8Sopenharmony_ci    }
255800b99b8Sopenharmony_ci    auto tmp = StringSplit(magicLine, " ");
256800b99b8Sopenharmony_ci    std::vector<std::string> strVec {tmp.begin() + 1, tmp.end()};
257800b99b8Sopenharmony_ci    if (strVec.size() != EI_NIDENT) {
258800b99b8Sopenharmony_ci        DFXLOGE("line format incorrect:");
259800b99b8Sopenharmony_ci        DFXLOGE("    line = %{public}s", magicLine.c_str());
260800b99b8Sopenharmony_ci        return false;
261800b99b8Sopenharmony_ci    }
262800b99b8Sopenharmony_ci    for (std::size_t count = 0; count < strVec.size(); ++count) {
263800b99b8Sopenharmony_ci        std::string valStr = strVec[count];
264800b99b8Sopenharmony_ci        constexpr int base {16};
265800b99b8Sopenharmony_ci        ehdrIdent_[count] = static_cast<unsigned char>(std::stoul(valStr, nullptr, base));
266800b99b8Sopenharmony_ci    }
267800b99b8Sopenharmony_ci    return true;
268800b99b8Sopenharmony_ci}
269800b99b8Sopenharmony_ci
270800b99b8Sopenharmony_cibool ElfImitate::GetClass(FILE * const fp)
271800b99b8Sopenharmony_ci{
272800b99b8Sopenharmony_ci    if (fp == nullptr) {
273800b99b8Sopenharmony_ci        DFXLOGE("param is null");
274800b99b8Sopenharmony_ci        return false;
275800b99b8Sopenharmony_ci    }
276800b99b8Sopenharmony_ci    int status {0};
277800b99b8Sopenharmony_ci    std::string classLine = GetNextLine(fp, &status);
278800b99b8Sopenharmony_ci    if (status == -1) {
279800b99b8Sopenharmony_ci        DFXLOGE("early end");
280800b99b8Sopenharmony_ci        return false;
281800b99b8Sopenharmony_ci    }
282800b99b8Sopenharmony_ci    auto strVec = StringSplit(classLine, " ");
283800b99b8Sopenharmony_ci    constexpr int len {2};
284800b99b8Sopenharmony_ci    if (strVec.size() != len) {
285800b99b8Sopenharmony_ci        DFXLOGE("line format incorrect:");
286800b99b8Sopenharmony_ci        DFXLOGE("    line = %{public}s", classLine.c_str());
287800b99b8Sopenharmony_ci        return false;
288800b99b8Sopenharmony_ci    }
289800b99b8Sopenharmony_ci    if (strVec.back() == "ELF32") {
290800b99b8Sopenharmony_ci        classType_ = ELFCLASS32;
291800b99b8Sopenharmony_ci    } else if (strVec.back() == "ELF64") {
292800b99b8Sopenharmony_ci        classType_ = ELFCLASS64;
293800b99b8Sopenharmony_ci    }
294800b99b8Sopenharmony_ci    return true;
295800b99b8Sopenharmony_ci}
296800b99b8Sopenharmony_ci
297800b99b8Sopenharmony_cibool ElfImitate::GetMachine(FILE * const fp)
298800b99b8Sopenharmony_ci{
299800b99b8Sopenharmony_ci    int status {0};
300800b99b8Sopenharmony_ci    std::string machineLine = GetNextLine(fp, &status);
301800b99b8Sopenharmony_ci    if (status == -1) {
302800b99b8Sopenharmony_ci        DFXLOGE("early end");
303800b99b8Sopenharmony_ci        return false;
304800b99b8Sopenharmony_ci    }
305800b99b8Sopenharmony_ci    auto strVec = StringSplit(machineLine, " ");
306800b99b8Sopenharmony_ci    constexpr int len {2};
307800b99b8Sopenharmony_ci    if (strVec.size() != len) {
308800b99b8Sopenharmony_ci        DFXLOGE("line format incorrect:");
309800b99b8Sopenharmony_ci        DFXLOGE("    line = %{public}s", machineLine.c_str());
310800b99b8Sopenharmony_ci        return false;
311800b99b8Sopenharmony_ci    }
312800b99b8Sopenharmony_ci    machine_ = strVec.back();
313800b99b8Sopenharmony_ci    return true;
314800b99b8Sopenharmony_ci}
315800b99b8Sopenharmony_cibool ElfImitate::GetEntryAddr(FILE * const fp)
316800b99b8Sopenharmony_ci{
317800b99b8Sopenharmony_ci    int status {0};
318800b99b8Sopenharmony_ci    std::string entryLine = GetNextLine(fp, &status);
319800b99b8Sopenharmony_ci    if (status == -1) {
320800b99b8Sopenharmony_ci        DFXLOGE("early end");
321800b99b8Sopenharmony_ci        return false;
322800b99b8Sopenharmony_ci    }
323800b99b8Sopenharmony_ci    auto strVec = StringSplit(entryLine, " ");
324800b99b8Sopenharmony_ci    constexpr int len {2};
325800b99b8Sopenharmony_ci    if (strVec.size() != len) {
326800b99b8Sopenharmony_ci        DFXLOGE("line format incorrect:");
327800b99b8Sopenharmony_ci        DFXLOGE("    line = %{public}s", entryLine.c_str());
328800b99b8Sopenharmony_ci        return false;
329800b99b8Sopenharmony_ci    }
330800b99b8Sopenharmony_ci    std::string entryStr = strVec.back();
331800b99b8Sopenharmony_ci    constexpr int base {16};
332800b99b8Sopenharmony_ci    prgEntryVaddr_ = static_cast<uint64_t>(std::stoull(entryStr, nullptr, base));
333800b99b8Sopenharmony_ci    return true;
334800b99b8Sopenharmony_ci}
335800b99b8Sopenharmony_ci
336800b99b8Sopenharmony_cibool ElfImitate::GetPrgOffset(FILE * const fp)
337800b99b8Sopenharmony_ci{
338800b99b8Sopenharmony_ci    int status {0};
339800b99b8Sopenharmony_ci    std::string line = GetNextLine(fp, &status);
340800b99b8Sopenharmony_ci    if (status == -1) {
341800b99b8Sopenharmony_ci        DFXLOGE("early end");
342800b99b8Sopenharmony_ci        return false;
343800b99b8Sopenharmony_ci    }
344800b99b8Sopenharmony_ci    auto strVec = StringSplit(line, " ");
345800b99b8Sopenharmony_ci    constexpr int len {5};
346800b99b8Sopenharmony_ci    if (strVec.size() != len) {
347800b99b8Sopenharmony_ci        DFXLOGE("line format incorrect:");
348800b99b8Sopenharmony_ci        DFXLOGE("    line = %{public}s", line.c_str());
349800b99b8Sopenharmony_ci        return false;
350800b99b8Sopenharmony_ci    }
351800b99b8Sopenharmony_ci    constexpr int valIndex {1};
352800b99b8Sopenharmony_ci    std::string valStr = strVec[valIndex];
353800b99b8Sopenharmony_ci    phdrOffset_ = static_cast<uint64_t>(std::stoull(valStr));
354800b99b8Sopenharmony_ci    return true;
355800b99b8Sopenharmony_ci}
356800b99b8Sopenharmony_ci
357800b99b8Sopenharmony_cibool ElfImitate::GetSecOffset(FILE * const fp)
358800b99b8Sopenharmony_ci{
359800b99b8Sopenharmony_ci    int status {0};
360800b99b8Sopenharmony_ci    std::string line = GetNextLine(fp, &status);
361800b99b8Sopenharmony_ci    if (status == -1) {
362800b99b8Sopenharmony_ci        DFXLOGE("early end");
363800b99b8Sopenharmony_ci        return false;
364800b99b8Sopenharmony_ci    }
365800b99b8Sopenharmony_ci    auto strVec = StringSplit(line, " ");
366800b99b8Sopenharmony_ci    constexpr int len {8};
367800b99b8Sopenharmony_ci    if (strVec.size() != len) {
368800b99b8Sopenharmony_ci        DFXLOGE("line format incorrect:");
369800b99b8Sopenharmony_ci        DFXLOGE("    line = %{public}s", line.c_str());
370800b99b8Sopenharmony_ci        return false;
371800b99b8Sopenharmony_ci    }
372800b99b8Sopenharmony_ci    constexpr int valIndex {4};
373800b99b8Sopenharmony_ci    std::string valStr = strVec[valIndex];
374800b99b8Sopenharmony_ci    shdrOffset_ = static_cast<uint64_t>(std::stoull(valStr));
375800b99b8Sopenharmony_ci    return true;
376800b99b8Sopenharmony_ci}
377800b99b8Sopenharmony_ci
378800b99b8Sopenharmony_cibool ElfImitate::GetFlag(FILE * const fp)
379800b99b8Sopenharmony_ci{
380800b99b8Sopenharmony_ci    int status {0};
381800b99b8Sopenharmony_ci    std::string line = GetNextLine(fp, &status);
382800b99b8Sopenharmony_ci    if (status == -1) {
383800b99b8Sopenharmony_ci        DFXLOGE("early end");
384800b99b8Sopenharmony_ci        return false;
385800b99b8Sopenharmony_ci    }
386800b99b8Sopenharmony_ci    auto strVec = StringSplit(line, " ");
387800b99b8Sopenharmony_ci    constexpr int len {2};
388800b99b8Sopenharmony_ci    if (strVec.size() != len) {
389800b99b8Sopenharmony_ci        DFXLOGE("line format incorrect:");
390800b99b8Sopenharmony_ci        DFXLOGE("    line = %{public}s", line.c_str());
391800b99b8Sopenharmony_ci        return false;
392800b99b8Sopenharmony_ci    }
393800b99b8Sopenharmony_ci    constexpr int valIndex {1};
394800b99b8Sopenharmony_ci    std::string valStr = strVec[valIndex];
395800b99b8Sopenharmony_ci    ehdrFlags_ = static_cast<uint32_t>(std::stoul(valStr));
396800b99b8Sopenharmony_ci    return true;
397800b99b8Sopenharmony_ci}
398800b99b8Sopenharmony_ci
399800b99b8Sopenharmony_cibool ElfImitate::GetEhdrSize(FILE * const fp)
400800b99b8Sopenharmony_ci{
401800b99b8Sopenharmony_ci    int status {0};
402800b99b8Sopenharmony_ci    std::string line = GetNextLine(fp, &status);
403800b99b8Sopenharmony_ci    if (status == -1) {
404800b99b8Sopenharmony_ci        DFXLOGE("early end");
405800b99b8Sopenharmony_ci        return false;
406800b99b8Sopenharmony_ci    }
407800b99b8Sopenharmony_ci    auto strVec = StringSplit(line, " ");
408800b99b8Sopenharmony_ci    constexpr int len {6};
409800b99b8Sopenharmony_ci    if (strVec.size() != len) {
410800b99b8Sopenharmony_ci        DFXLOGE("line format incorrect:");
411800b99b8Sopenharmony_ci        DFXLOGE("    line = %{public}s", line.c_str());
412800b99b8Sopenharmony_ci        return false;
413800b99b8Sopenharmony_ci    }
414800b99b8Sopenharmony_ci    constexpr int valIndex {4};
415800b99b8Sopenharmony_ci    std::string valStr = strVec[valIndex];
416800b99b8Sopenharmony_ci    ehdrSize_ = static_cast<uint16_t>(std::stoull(valStr));
417800b99b8Sopenharmony_ci    return true;
418800b99b8Sopenharmony_ci}
419800b99b8Sopenharmony_ci
420800b99b8Sopenharmony_cibool ElfImitate::GetPhdrSize(FILE * const fp)
421800b99b8Sopenharmony_ci{
422800b99b8Sopenharmony_ci    int status {0};
423800b99b8Sopenharmony_ci    std::string line = GetNextLine(fp, &status);
424800b99b8Sopenharmony_ci    if (status == -1) {
425800b99b8Sopenharmony_ci        DFXLOGE("early end");
426800b99b8Sopenharmony_ci        return false;
427800b99b8Sopenharmony_ci    }
428800b99b8Sopenharmony_ci    auto strVec = StringSplit(line, " ");
429800b99b8Sopenharmony_ci    constexpr int len {6};
430800b99b8Sopenharmony_ci    if (strVec.size() != len) {
431800b99b8Sopenharmony_ci        DFXLOGE("line format incorrect:");
432800b99b8Sopenharmony_ci        DFXLOGE("    line = %{public}s", line.c_str());
433800b99b8Sopenharmony_ci        return false;
434800b99b8Sopenharmony_ci    }
435800b99b8Sopenharmony_ci    constexpr int valIndex {4};
436800b99b8Sopenharmony_ci    std::string valStr = strVec[valIndex];
437800b99b8Sopenharmony_ci    phdrEntSize_ = static_cast<uint16_t>(std::stoull(valStr));
438800b99b8Sopenharmony_ci    return true;
439800b99b8Sopenharmony_ci}
440800b99b8Sopenharmony_ci
441800b99b8Sopenharmony_cibool ElfImitate::GetNumPhdrs(FILE * const fp)
442800b99b8Sopenharmony_ci{
443800b99b8Sopenharmony_ci    int status {0};
444800b99b8Sopenharmony_ci    std::string line = GetNextLine(fp, &status);
445800b99b8Sopenharmony_ci    if (status == -1) {
446800b99b8Sopenharmony_ci        DFXLOGE("early end");
447800b99b8Sopenharmony_ci        return false;
448800b99b8Sopenharmony_ci    }
449800b99b8Sopenharmony_ci    auto strVec = StringSplit(line, " ");
450800b99b8Sopenharmony_ci    constexpr int len {5};
451800b99b8Sopenharmony_ci    if (strVec.size() != len) {
452800b99b8Sopenharmony_ci        DFXLOGE("line format incorrect:");
453800b99b8Sopenharmony_ci        DFXLOGE("    line = %{public}s", line.c_str());
454800b99b8Sopenharmony_ci        return false;
455800b99b8Sopenharmony_ci    }
456800b99b8Sopenharmony_ci    constexpr int valIndex {4};
457800b99b8Sopenharmony_ci    std::string valStr = strVec[valIndex];
458800b99b8Sopenharmony_ci    phdrNumEnts_ = static_cast<uint16_t>(std::stoull(valStr));
459800b99b8Sopenharmony_ci    return true;
460800b99b8Sopenharmony_ci}
461800b99b8Sopenharmony_ci
462800b99b8Sopenharmony_cibool ElfImitate::GetShdrSize(FILE * const fp)
463800b99b8Sopenharmony_ci{
464800b99b8Sopenharmony_ci    int status {0};
465800b99b8Sopenharmony_ci    std::string line = GetNextLine(fp, &status);
466800b99b8Sopenharmony_ci    if (status == -1) {
467800b99b8Sopenharmony_ci        DFXLOGE("early end");
468800b99b8Sopenharmony_ci        return false;
469800b99b8Sopenharmony_ci    }
470800b99b8Sopenharmony_ci    auto strVec = StringSplit(line, " ");
471800b99b8Sopenharmony_ci    constexpr int len {6};
472800b99b8Sopenharmony_ci    if (strVec.size() != len) {
473800b99b8Sopenharmony_ci        DFXLOGE("line format incorrect:");
474800b99b8Sopenharmony_ci        DFXLOGE("    line = %{public}s", line.c_str());
475800b99b8Sopenharmony_ci        return false;
476800b99b8Sopenharmony_ci    }
477800b99b8Sopenharmony_ci    constexpr int valIndex {4};
478800b99b8Sopenharmony_ci    std::string valStr = strVec[valIndex];
479800b99b8Sopenharmony_ci    shdrEntSize_ = static_cast<uint16_t>(std::stoull(valStr));
480800b99b8Sopenharmony_ci    return true;
481800b99b8Sopenharmony_ci}
482800b99b8Sopenharmony_ci
483800b99b8Sopenharmony_cibool ElfImitate::GetNumShdrs(FILE * const fp)
484800b99b8Sopenharmony_ci{
485800b99b8Sopenharmony_ci    int status {0};
486800b99b8Sopenharmony_ci    std::string line = GetNextLine(fp, &status);
487800b99b8Sopenharmony_ci    if (status == -1) {
488800b99b8Sopenharmony_ci        DFXLOGE("early end");
489800b99b8Sopenharmony_ci        return false;
490800b99b8Sopenharmony_ci    }
491800b99b8Sopenharmony_ci    auto strVec = StringSplit(line, " ");
492800b99b8Sopenharmony_ci    constexpr int len {5};
493800b99b8Sopenharmony_ci    if (strVec.size() != len) {
494800b99b8Sopenharmony_ci        DFXLOGE("line format incorrect:");
495800b99b8Sopenharmony_ci        DFXLOGE("    line = %{public}s", line.c_str());
496800b99b8Sopenharmony_ci        return false;
497800b99b8Sopenharmony_ci    }
498800b99b8Sopenharmony_ci    constexpr int valIndex {4};
499800b99b8Sopenharmony_ci    std::string valStr = strVec[valIndex];
500800b99b8Sopenharmony_ci    shdrNumEnts_ = static_cast<uint16_t>(std::stoull(valStr));
501800b99b8Sopenharmony_ci    return true;
502800b99b8Sopenharmony_ci}
503800b99b8Sopenharmony_ci
504800b99b8Sopenharmony_cibool ElfImitate::GetShdrStrTabIdx(FILE * const fp)
505800b99b8Sopenharmony_ci{
506800b99b8Sopenharmony_ci    int status {0};
507800b99b8Sopenharmony_ci    std::string line = GetNextLine(fp, &status);
508800b99b8Sopenharmony_ci    if (status == -1) {
509800b99b8Sopenharmony_ci        DFXLOGE("early end");
510800b99b8Sopenharmony_ci        return false;
511800b99b8Sopenharmony_ci    }
512800b99b8Sopenharmony_ci    auto strVec = StringSplit(line, " ");
513800b99b8Sopenharmony_ci    constexpr int len {6};
514800b99b8Sopenharmony_ci    if (strVec.size() != len) {
515800b99b8Sopenharmony_ci        DFXLOGE("line format incorrect:");
516800b99b8Sopenharmony_ci        DFXLOGE("    line = %{public}s", line.c_str());
517800b99b8Sopenharmony_ci        return false;
518800b99b8Sopenharmony_ci    }
519800b99b8Sopenharmony_ci    constexpr int valIndex {5};
520800b99b8Sopenharmony_ci    std::string valStr = strVec[valIndex];
521800b99b8Sopenharmony_ci    shdrStrTabIdx_ = static_cast<uint16_t>(std::stoull(valStr));
522800b99b8Sopenharmony_ci    return true;
523800b99b8Sopenharmony_ci}
524800b99b8Sopenharmony_ci
525800b99b8Sopenharmony_cibool ElfImitate::ParseProgramHeaders(ElfFileType fileType)
526800b99b8Sopenharmony_ci{
527800b99b8Sopenharmony_ci    bool firstLoadHeader = true;
528800b99b8Sopenharmony_ci    while (true) {
529800b99b8Sopenharmony_ci        std::string line {};
530800b99b8Sopenharmony_ci        line = GetNextPhdrLine();
531800b99b8Sopenharmony_ci        if (line.empty()) {
532800b99b8Sopenharmony_ci            break;
533800b99b8Sopenharmony_ci            DFXLOGI("no more program lines");
534800b99b8Sopenharmony_ci        }
535800b99b8Sopenharmony_ci        if (fileType == ElfFileType::ELF64) {
536800b99b8Sopenharmony_ci            int status = 0;
537800b99b8Sopenharmony_ci            std::string lineAppend = GetNextLine(phdrFP_, &status);
538800b99b8Sopenharmony_ci            if (status == -1) {
539800b99b8Sopenharmony_ci                DFXLOGE("GetNextLine(phdrFP_, &status) error:");
540800b99b8Sopenharmony_ci                break;
541800b99b8Sopenharmony_ci            }
542800b99b8Sopenharmony_ci            if (lineAppend.empty()) {
543800b99b8Sopenharmony_ci                break;
544800b99b8Sopenharmony_ci                DFXLOGI("no more program lines");
545800b99b8Sopenharmony_ci            }
546800b99b8Sopenharmony_ci            line += lineAppend;
547800b99b8Sopenharmony_ci        }
548800b99b8Sopenharmony_ci
549800b99b8Sopenharmony_ci        auto strVec = StringSplit(line, " ");
550800b99b8Sopenharmony_ci        std::string type = strVec[0];
551800b99b8Sopenharmony_ci        int base = 16; // 16:HEX
552800b99b8Sopenharmony_ci        uint64_t offset =  std::stoull(strVec[INDEX_I1], nullptr, base);
553800b99b8Sopenharmony_ci        uint64_t vAddr = std::stoull(strVec[INDEX_I2], nullptr, base);
554800b99b8Sopenharmony_ci        uint64_t memSize = std::stoull(strVec[INDEX_I5], nullptr, base);
555800b99b8Sopenharmony_ci        std::string flg = strVec[INDEX_I6];
556800b99b8Sopenharmony_ci        if (!std::all_of(strVec[INDEX_I7].begin(), strVec[INDEX_I7].end(), ::isdigit)) {
557800b99b8Sopenharmony_ci            flg += strVec[INDEX_I7];
558800b99b8Sopenharmony_ci        }
559800b99b8Sopenharmony_ci        if (type == "LOAD") {
560800b99b8Sopenharmony_ci            if (flg.find("E") == std::string::npos) {
561800b99b8Sopenharmony_ci                continue;
562800b99b8Sopenharmony_ci            }
563800b99b8Sopenharmony_ci            ptLoads_[offset] = ElfLoadInfo{offset, vAddr, static_cast<size_t>(memSize)};
564800b99b8Sopenharmony_ci
565800b99b8Sopenharmony_ci            // Only set the load bias from the first executable load header.
566800b99b8Sopenharmony_ci            if (firstLoadHeader) {
567800b99b8Sopenharmony_ci                loadBias_ = static_cast<int64_t>(static_cast<uint64_t>(vAddr) - offset);
568800b99b8Sopenharmony_ci            }
569800b99b8Sopenharmony_ci            firstLoadHeader = false;
570800b99b8Sopenharmony_ci
571800b99b8Sopenharmony_ci            if (vAddr < startVaddr_) {
572800b99b8Sopenharmony_ci                startVaddr_ = vAddr;
573800b99b8Sopenharmony_ci            }
574800b99b8Sopenharmony_ci            if (vAddr + memSize > endVaddr_) {
575800b99b8Sopenharmony_ci                endVaddr_ = vAddr + memSize;
576800b99b8Sopenharmony_ci            }
577800b99b8Sopenharmony_ci        }
578800b99b8Sopenharmony_ci    }
579800b99b8Sopenharmony_ci    return true;
580800b99b8Sopenharmony_ci}
581800b99b8Sopenharmony_cibool ElfImitate::ParseSectionHeaders(ElfFileType fileType)
582800b99b8Sopenharmony_ci{
583800b99b8Sopenharmony_ci    std::string line {};
584800b99b8Sopenharmony_ci    int status = 0;
585800b99b8Sopenharmony_ci    (void)GetNextShdrLine(); //skip index 0 section header
586800b99b8Sopenharmony_ci    (void)GetNextLine(shdrFP_, &status);
587800b99b8Sopenharmony_ci    while (true) {
588800b99b8Sopenharmony_ci        status = 0;
589800b99b8Sopenharmony_ci        line = GetNextShdrLine();
590800b99b8Sopenharmony_ci        if (line.empty()) {
591800b99b8Sopenharmony_ci            break;
592800b99b8Sopenharmony_ci            DFXLOGI("no more section lines");
593800b99b8Sopenharmony_ci        }
594800b99b8Sopenharmony_ci        if (fileType == ElfFileType::ELF64) {
595800b99b8Sopenharmony_ci            std::string lineAppend = GetNextLine(shdrFP_, &status);
596800b99b8Sopenharmony_ci            if (lineAppend.empty()) {
597800b99b8Sopenharmony_ci                break;
598800b99b8Sopenharmony_ci                DFXLOGI("no more section lines");
599800b99b8Sopenharmony_ci            }
600800b99b8Sopenharmony_ci            line += lineAppend;
601800b99b8Sopenharmony_ci        }
602800b99b8Sopenharmony_ci
603800b99b8Sopenharmony_ci        auto secIndex = GetSecIndex(line);
604800b99b8Sopenharmony_ci
605800b99b8Sopenharmony_ci        auto pos = line.find("]");
606800b99b8Sopenharmony_ci        if (pos == std::string::npos) {
607800b99b8Sopenharmony_ci            DFXLOGI("incorrect section line: %{public}s", line.c_str());
608800b99b8Sopenharmony_ci            return false;
609800b99b8Sopenharmony_ci        }
610800b99b8Sopenharmony_ci        ++pos;
611800b99b8Sopenharmony_ci        std::string tmpLine = line.substr(pos, line.length() - pos);
612800b99b8Sopenharmony_ci        auto strVec = StringSplit(tmpLine, " ");
613800b99b8Sopenharmony_ci        for (size_t i = 0; i < strVec.size(); ++i) {}
614800b99b8Sopenharmony_ci
615800b99b8Sopenharmony_ci        constexpr int base {16};
616800b99b8Sopenharmony_ci        std::string secName = strVec[0];
617800b99b8Sopenharmony_ci        std::string secType = strVec[1];
618800b99b8Sopenharmony_ci        uint64_t secAddr = std::stoull(strVec[2], nullptr, base);
619800b99b8Sopenharmony_ci        uint64_t secOffset = std::stoull(strVec[3], nullptr, base);
620800b99b8Sopenharmony_ci        uint64_t secSize = std::stoull(strVec[4], nullptr, base);
621800b99b8Sopenharmony_ci        uint64_t secEntSize = std::stoull(strVec[5], nullptr, base);
622800b99b8Sopenharmony_ci        uint64_t secLink = std::stoull(strVec[strVec.size() - 3], nullptr, base);
623800b99b8Sopenharmony_ci        uint64_t secInfo = std::stoull(strVec[strVec.size() - 2], nullptr, base);
624800b99b8Sopenharmony_ci        uint64_t secAddrAlign = std::stoull(strVec[strVec.size() - 1], nullptr, base);
625800b99b8Sopenharmony_ci
626800b99b8Sopenharmony_ci        ShdrInfo shdrInfo;
627800b99b8Sopenharmony_ci        shdrInfo.addr = secAddr;
628800b99b8Sopenharmony_ci        shdrInfo.offset = secOffset;
629800b99b8Sopenharmony_ci        shdrInfo.size = secSize;
630800b99b8Sopenharmony_ci        shdrInfoPairs_.emplace(std::make_pair(secIndex, secName), shdrInfo);
631800b99b8Sopenharmony_ci
632800b99b8Sopenharmony_ci        if (secType == "SYMTAB" || secType == "DYNSYM") {
633800b99b8Sopenharmony_ci            ElfShdr elfShdr;
634800b99b8Sopenharmony_ci            elfShdr.name = static_cast<uint32_t>(secIndex);
635800b99b8Sopenharmony_ci            if (secType == "SYMTAB") {
636800b99b8Sopenharmony_ci                elfShdr.type = static_cast<uint32_t>(SHT_SYMTAB);
637800b99b8Sopenharmony_ci            } else {
638800b99b8Sopenharmony_ci                elfShdr.type = static_cast<uint32_t>(SHT_DYNSYM);
639800b99b8Sopenharmony_ci            }
640800b99b8Sopenharmony_ci
641800b99b8Sopenharmony_ci            elfShdr.addr = secAddr;
642800b99b8Sopenharmony_ci            elfShdr.offset = secOffset;
643800b99b8Sopenharmony_ci            elfShdr.size = secSize;
644800b99b8Sopenharmony_ci            elfShdr.link = static_cast<uint32_t>(secLink);
645800b99b8Sopenharmony_ci            elfShdr.info = static_cast<uint32_t>(secInfo);
646800b99b8Sopenharmony_ci            elfShdr.addrAlign = secAddrAlign;
647800b99b8Sopenharmony_ci            elfShdr.entSize = secEntSize;
648800b99b8Sopenharmony_ci            symShdrs_.emplace(secName, elfShdr);
649800b99b8Sopenharmony_ci        }
650800b99b8Sopenharmony_ci    }
651800b99b8Sopenharmony_ci    return true;
652800b99b8Sopenharmony_ci}
653800b99b8Sopenharmony_ciconst std::string ElfImitate::GetNextPhdrLine()
654800b99b8Sopenharmony_ci{
655800b99b8Sopenharmony_ci    const std::string effectFlag {"0x00"};
656800b99b8Sopenharmony_ci    std::string line {};
657800b99b8Sopenharmony_ci    int status {0};
658800b99b8Sopenharmony_ci    while (true) {
659800b99b8Sopenharmony_ci        line = GetNextLine(phdrFP_, &status);
660800b99b8Sopenharmony_ci        if (status == -1) {
661800b99b8Sopenharmony_ci            DFXLOGE("GetNextLine(phdrFP_, &status) error:");
662800b99b8Sopenharmony_ci            line = "";
663800b99b8Sopenharmony_ci            break;
664800b99b8Sopenharmony_ci        }
665800b99b8Sopenharmony_ci        if (line.find(effectFlag) != std::string::npos) {
666800b99b8Sopenharmony_ci            DFXLOGE("effective program header line: %{public}s", line.c_str());
667800b99b8Sopenharmony_ci            break;
668800b99b8Sopenharmony_ci        }
669800b99b8Sopenharmony_ci    }
670800b99b8Sopenharmony_ci    return line;
671800b99b8Sopenharmony_ci}
672800b99b8Sopenharmony_ci
673800b99b8Sopenharmony_ciconst std::string ElfImitate::GetNextShdrLine()
674800b99b8Sopenharmony_ci{
675800b99b8Sopenharmony_ci    const std::string effectFlag {"]"};
676800b99b8Sopenharmony_ci    std::string line {};
677800b99b8Sopenharmony_ci    int status {0};
678800b99b8Sopenharmony_ci    while (true) {
679800b99b8Sopenharmony_ci        line = GetNextLine(shdrFP_, &status);
680800b99b8Sopenharmony_ci        if (status == -1) {
681800b99b8Sopenharmony_ci            DFXLOGE("GetNextLine(phdrFP_, &status) error:");
682800b99b8Sopenharmony_ci            line = "";
683800b99b8Sopenharmony_ci            break;
684800b99b8Sopenharmony_ci        }
685800b99b8Sopenharmony_ci        auto pos = line.find(effectFlag);
686800b99b8Sopenharmony_ci        if ((pos != std::string::npos) and isdigit(line.at(pos - 1))) {
687800b99b8Sopenharmony_ci            DFXLOGE("effective section header line: %{public}s", line.c_str());
688800b99b8Sopenharmony_ci            break;
689800b99b8Sopenharmony_ci        }
690800b99b8Sopenharmony_ci    }
691800b99b8Sopenharmony_ci    return line;
692800b99b8Sopenharmony_ci}
693800b99b8Sopenharmony_ciint64_t ElfImitate::GetSecIndex(const std::string &line)
694800b99b8Sopenharmony_ci{
695800b99b8Sopenharmony_ci    int64_t res {-1};
696800b99b8Sopenharmony_ci    auto pos = line.find("[");
697800b99b8Sopenharmony_ci    if (pos == std::string::npos) {
698800b99b8Sopenharmony_ci        DFXLOGI("no section index found: %{public}s", line.c_str());
699800b99b8Sopenharmony_ci        return res;
700800b99b8Sopenharmony_ci    }
701800b99b8Sopenharmony_ci    constexpr int len {4};
702800b99b8Sopenharmony_ci    std::string str = line.substr(pos, len);
703800b99b8Sopenharmony_ci    if (str.length() != len) {
704800b99b8Sopenharmony_ci        DFXLOGI("section index form incorrect: %{public}s", str.c_str());
705800b99b8Sopenharmony_ci        return res;
706800b99b8Sopenharmony_ci    }
707800b99b8Sopenharmony_ci    // section index is of the form "[xx]"
708800b99b8Sopenharmony_ci    constexpr int firstDigit {1};
709800b99b8Sopenharmony_ci    constexpr int numDigits {2};
710800b99b8Sopenharmony_ci    str = str.substr(firstDigit, numDigits);
711800b99b8Sopenharmony_ci    if (str[0] == ' ') {
712800b99b8Sopenharmony_ci        // str = [ x], transform it to [xx]
713800b99b8Sopenharmony_ci        str[0] = '0';
714800b99b8Sopenharmony_ci    }
715800b99b8Sopenharmony_ci    if (!str.empty() && std::all_of(str.begin(), str.end(), ::isdigit)) {
716800b99b8Sopenharmony_ci        res = std::stoll(str);
717800b99b8Sopenharmony_ci    } else {
718800b99b8Sopenharmony_ci        DFXLOGI("not digits: %{public}s", str.c_str());
719800b99b8Sopenharmony_ci    }
720800b99b8Sopenharmony_ci    return res;
721800b99b8Sopenharmony_ci}
722800b99b8Sopenharmony_ci
723800b99b8Sopenharmony_cibool ElfImitate::ParseElfSymbols()
724800b99b8Sopenharmony_ci{
725800b99b8Sopenharmony_ci    std::unordered_map <std::string, uint8_t> typeMap = {
726800b99b8Sopenharmony_ci        {"OBJECT", STT_OBJECT}, {"FUNC", STT_FUNC}, {"SECTION", STT_SECTION}, {"FILE", STT_FILE},
727800b99b8Sopenharmony_ci        {"COMMON", STT_COMMON}, {"TLS", STT_TLS}, {"NUM", STT_NUM}, {"LOOS", STT_LOOS},
728800b99b8Sopenharmony_ci        {"GNU_IFUNC", STT_GNU_IFUNC}, {"HIOS", STT_HIOS}, {"LOPROC", STT_LOPROC}, {"HIPROC", STT_HIPROC},
729800b99b8Sopenharmony_ci    };
730800b99b8Sopenharmony_ci    std::unordered_map <std::string, uint8_t> bindMap = {
731800b99b8Sopenharmony_ci        {"LOCAL", STB_LOCAL}, {"GLOBAL", STB_GLOBAL}, {"WEAK", STB_WEAK}, {"NUM", STB_NUM}, {"LOOS", STB_LOOS},
732800b99b8Sopenharmony_ci        {"GNU_UNIQUE", STB_GNU_UNIQUE}, {"HIOS", STB_HIOS}, {"LOPROC", STB_LOPROC}, {"HIPROC", STB_HIPROC}
733800b99b8Sopenharmony_ci    };
734800b99b8Sopenharmony_ci    std::unordered_map <std::string, uint8_t> vsMap = {
735800b99b8Sopenharmony_ci        {"DEFAULT", STV_DEFAULT}, {"INTERNAL", STV_INTERNAL}, {"HIDDEN", STV_HIDDEN}, {"PROTECTED", STV_PROTECTED},
736800b99b8Sopenharmony_ci    };
737800b99b8Sopenharmony_ci    while (true) {
738800b99b8Sopenharmony_ci        std::string line {};
739800b99b8Sopenharmony_ci        line = GetNextSymLine();
740800b99b8Sopenharmony_ci        if (line.empty()) {
741800b99b8Sopenharmony_ci            DFXLOGI("no more symbol lines");
742800b99b8Sopenharmony_ci            break;
743800b99b8Sopenharmony_ci        }
744800b99b8Sopenharmony_ci        auto strVec = StringSplit(line, " ");
745800b99b8Sopenharmony_ci        ElfSymbol elfSymbol;
746800b99b8Sopenharmony_ci        constexpr int base {16}; // 16:HEX
747800b99b8Sopenharmony_ci        elfSymbol.name = std::stoul(strVec[INDEX_I0].substr(0, strVec[INDEX_I0].size() -1));
748800b99b8Sopenharmony_ci        elfSymbol.value = std::stoull(strVec[INDEX_I1], nullptr, base);
749800b99b8Sopenharmony_ci        elfSymbol.size = std::stoull(strVec[INDEX_I2]);
750800b99b8Sopenharmony_ci        elfSymbol.info = ELF32_ST_INFO(bindMap[strVec[INDEX_I4]], typeMap[strVec[INDEX_I3]]);
751800b99b8Sopenharmony_ci        elfSymbol.other = vsMap["strVec[INDEX_I5]"];
752800b99b8Sopenharmony_ci        if (strVec[INDEX_I6] == "UND") {
753800b99b8Sopenharmony_ci            elfSymbol.shndx = SHN_UNDEF;
754800b99b8Sopenharmony_ci        } else if (strVec[INDEX_I6] == "ABS") {
755800b99b8Sopenharmony_ci            elfSymbol.shndx = SHN_ABS;
756800b99b8Sopenharmony_ci        } else {
757800b99b8Sopenharmony_ci            elfSymbol.shndx = static_cast<uint16_t>(std::stoul(strVec[INDEX_I6]));
758800b99b8Sopenharmony_ci        }
759800b99b8Sopenharmony_ci        elfSymbols_.push_back(elfSymbol);
760800b99b8Sopenharmony_ci    }
761800b99b8Sopenharmony_ci    return true;
762800b99b8Sopenharmony_ci}
763800b99b8Sopenharmony_ciconst std::string ElfImitate::GetNextSymLine()
764800b99b8Sopenharmony_ci{
765800b99b8Sopenharmony_ci    const std::string effectFlag {":"};
766800b99b8Sopenharmony_ci    std::string line {};
767800b99b8Sopenharmony_ci    int status {0};
768800b99b8Sopenharmony_ci    while (true) {
769800b99b8Sopenharmony_ci        line = GetNextLine(symTabFP_, &status);
770800b99b8Sopenharmony_ci        if (status == -1) {
771800b99b8Sopenharmony_ci            DFXLOGI("GetNextLine(phdrFP_, &status) error:");
772800b99b8Sopenharmony_ci            line = "";
773800b99b8Sopenharmony_ci            break;
774800b99b8Sopenharmony_ci        }
775800b99b8Sopenharmony_ci        auto pos = line.find(effectFlag);
776800b99b8Sopenharmony_ci        if ((pos != std::string::npos) and isdigit(line.at(pos - 1))) {
777800b99b8Sopenharmony_ci            DFXLOGI("effective symbol line: %{public}s", line.c_str());
778800b99b8Sopenharmony_ci            break;
779800b99b8Sopenharmony_ci        }
780800b99b8Sopenharmony_ci    }
781800b99b8Sopenharmony_ci    return line;
782800b99b8Sopenharmony_ci}
783800b99b8Sopenharmony_ci
784800b99b8Sopenharmony_cibool ElfImitate::GetSectionInfo(ShdrInfo& shdr, const std::string secName)
785800b99b8Sopenharmony_ci{
786800b99b8Sopenharmony_ci    for (const auto &iter: shdrInfoPairs_) {
787800b99b8Sopenharmony_ci        auto tmpPair = iter.first;
788800b99b8Sopenharmony_ci        if (tmpPair.second == secName) {
789800b99b8Sopenharmony_ci            shdr = iter.second;
790800b99b8Sopenharmony_ci            return true;
791800b99b8Sopenharmony_ci        }
792800b99b8Sopenharmony_ci    }
793800b99b8Sopenharmony_ci    return false;
794800b99b8Sopenharmony_ci}
795800b99b8Sopenharmony_ci
796800b99b8Sopenharmony_ciconst std::vector<ElfSymbol>& ElfImitate::GetElfSymbols()
797800b99b8Sopenharmony_ci{
798800b99b8Sopenharmony_ci    if (elfSymbols_.empty()) {
799800b99b8Sopenharmony_ci        ParseElfSymbols();
800800b99b8Sopenharmony_ci    }
801800b99b8Sopenharmony_ci    return elfSymbols_;
802800b99b8Sopenharmony_ci}
803800b99b8Sopenharmony_ciuint64_t ElfImitate::GetLoadBase(uint64_t mapStart, uint64_t mapOffset)
804800b99b8Sopenharmony_ci{
805800b99b8Sopenharmony_ci    loadBase_ = mapStart - mapOffset - GetLoadBias();
806800b99b8Sopenharmony_ci
807800b99b8Sopenharmony_ci    return loadBase_;
808800b99b8Sopenharmony_ci}
809800b99b8Sopenharmony_ci
810800b99b8Sopenharmony_ciuint64_t ElfImitate::GetStartPc()
811800b99b8Sopenharmony_ci{
812800b99b8Sopenharmony_ci    auto startVaddr = GetStartVaddr();
813800b99b8Sopenharmony_ci    startPc_ = startVaddr + loadBase_;
814800b99b8Sopenharmony_ci    return startPc_;
815800b99b8Sopenharmony_ci}
816800b99b8Sopenharmony_ci
817800b99b8Sopenharmony_ciuint64_t ElfImitate::GetEndPc()
818800b99b8Sopenharmony_ci{
819800b99b8Sopenharmony_ci    auto endVaddr = GetEndVaddr();
820800b99b8Sopenharmony_ci    endPc_ = endVaddr + loadBase_;
821800b99b8Sopenharmony_ci    return endPc_;
822800b99b8Sopenharmony_ci}
823800b99b8Sopenharmony_ci
824800b99b8Sopenharmony_ciuint64_t ElfImitate::GetRelPc(uint64_t pc, uint64_t mapStart, uint64_t mapOffset)
825800b99b8Sopenharmony_ci{
826800b99b8Sopenharmony_ci    return (pc - GetLoadBase(mapStart, mapOffset));
827800b99b8Sopenharmony_ci}
828800b99b8Sopenharmony_ci
829800b99b8Sopenharmony_cibool ElfImitate::IsFunc(const ElfSymbol symbol)
830800b99b8Sopenharmony_ci{
831800b99b8Sopenharmony_ci    return ((symbol.shndx != SHN_UNDEF) &&
832800b99b8Sopenharmony_ci        (ELF32_ST_TYPE(symbol.info) == STT_FUNC || ELF32_ST_TYPE(symbol.info) == STT_GNU_IFUNC));
833800b99b8Sopenharmony_ci}
834800b99b8Sopenharmony_ci
835800b99b8Sopenharmony_cibool ElfImitate::ParseSymbols(std::vector<DfxSymbol>& symbols, const std::string& filePath)
836800b99b8Sopenharmony_ci{
837800b99b8Sopenharmony_ci    std::vector<ElfSymbol> elfSymbols = GetElfSymbols();
838800b99b8Sopenharmony_ci    for (auto elfSymbol : elfSymbols) {
839800b99b8Sopenharmony_ci        if (IsFunc(elfSymbol)) {
840800b99b8Sopenharmony_ci            if (elfSymbol.value == 0 || elfSymbol.size == 0) {
841800b99b8Sopenharmony_ci                continue;
842800b99b8Sopenharmony_ci            }
843800b99b8Sopenharmony_ci            std::string nameStr = "";
844800b99b8Sopenharmony_ci            symbols.emplace_back(elfSymbol.value, elfSymbol.size,
845800b99b8Sopenharmony_ci                                 nameStr, DfxSymbols::Demangle(nameStr), filePath);
846800b99b8Sopenharmony_ci        } else {
847800b99b8Sopenharmony_ci            continue;
848800b99b8Sopenharmony_ci        }
849800b99b8Sopenharmony_ci    }
850800b99b8Sopenharmony_ci    auto comp = [](DfxSymbol a, DfxSymbol b) { return a.funcVaddr_ < b.funcVaddr_; };
851800b99b8Sopenharmony_ci    std::sort(symbols.begin(), symbols.end(), comp);
852800b99b8Sopenharmony_ci    auto pred = [](DfxSymbol a, DfxSymbol b) { return a.funcVaddr_ == b.funcVaddr_; };
853800b99b8Sopenharmony_ci    symbols.erase(std::unique(symbols.begin(), symbols.end(), pred), symbols.end());
854800b99b8Sopenharmony_ci    symbols.shrink_to_fit();
855800b99b8Sopenharmony_ci    return true;
856800b99b8Sopenharmony_ci}
857800b99b8Sopenharmony_ci
858800b99b8Sopenharmony_cibool ElfImitate::AddSymbolsByPlt(std::vector<DfxSymbol>& symbols, const std::string& filePath)
859800b99b8Sopenharmony_ci{
860800b99b8Sopenharmony_ci    ShdrInfo shdr;
861800b99b8Sopenharmony_ci    GetSectionInfo(shdr, PLT);
862800b99b8Sopenharmony_ci    symbols.emplace_back(shdr.addr, shdr.size, PLT, filePath);
863800b99b8Sopenharmony_ci    return true;
864800b99b8Sopenharmony_ci}
865800b99b8Sopenharmony_ci
866800b99b8Sopenharmony_cibool ElfImitate::GetFuncNameAndOffset(uint64_t pc, std::string& funcName, uint64_t& start, uint64_t& end)
867800b99b8Sopenharmony_ci{
868800b99b8Sopenharmony_ci    std::vector<DfxSymbol> symbols;
869800b99b8Sopenharmony_ci    if (!ParseSymbols(symbols, "")) {
870800b99b8Sopenharmony_ci        return false;
871800b99b8Sopenharmony_ci    }
872800b99b8Sopenharmony_ci
873800b99b8Sopenharmony_ci    for (const auto& symbol : symbols) {
874800b99b8Sopenharmony_ci        if (symbol.Contain(pc)) {
875800b99b8Sopenharmony_ci            funcName = symbol.demangle_;
876800b99b8Sopenharmony_ci            start = symbol.funcVaddr_;
877800b99b8Sopenharmony_ci            end = symbol.funcVaddr_ + symbol.size_;
878800b99b8Sopenharmony_ci            return true;
879800b99b8Sopenharmony_ci        }
880800b99b8Sopenharmony_ci    }
881800b99b8Sopenharmony_ci    return false;
882800b99b8Sopenharmony_ci}
883800b99b8Sopenharmony_ci} // namespace HiviewDFX
884800b99b8Sopenharmony_ci} // namespace OHOS