• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
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 #ifndef ELF_FILE_H_
17 #define ELF_FILE_H_
18 #include <cassert>
19 #include <cstring>
20 #include <fstream>
21 #include <functional>
22 #include <iomanip>
23 #include <iostream>
24 #include <string>
25 #include <unordered_map>
26 #include <vector>
27 
28 #include <elf.h>
29 
30 #include <fcntl.h>
31 #include <stdint.h>
32 #include <strings.h>
33 #include <sys/mman.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <unistd.h>
37 
38 #include "hhlog.h"
39 #include "utilities.h"
40 
41 namespace OHOS {
42 namespace Developtools {
43 namespace Hiebpf {
44 using namespace std::string_literals;
45 
46 constexpr std::size_t ehdr32Size {52};
47 constexpr std::size_t ehdr64Size {64};
48 constexpr std::size_t shdr32Size {40};
49 constexpr std::size_t shdr64Size {64};
50 constexpr std::size_t phdr32Size {32};
51 constexpr std::size_t phdr64Size {56};
52 constexpr std::size_t symEnt32Size {16};
53 constexpr std::size_t symEnt64Size {24};
54 
55 class ElfHeader {
56 public:
57     static std::unique_ptr<ElfHeader> MakeUnique(unsigned char * const ehdrBuf,
58                                                  const std::size_t bufSize);
59     bool Init(unsigned char * const ehdrBuf, const std::size_t bufSize);
60 
61     unsigned char ehdrIdent_[EI_NIDENT];
62     uint16_t type_;
63     uint16_t machine_;
64     uint16_t ehdrSize_;
65     uint16_t phdrEntSize_;
66     uint16_t phdrNumEnts_;
67     uint16_t shdrEntSize_;
68     uint16_t shdrNumEnts_;
69     uint16_t shdrStrTabIdx_;
70     uint32_t elfVersion_;
71     uint32_t ehdrFlags_;
72     uint64_t prgEntryVaddr_;
73     uint64_t phdrOffset_;
74     uint64_t shdrOffset_;
75 
76 private:
77     explicit ElfHeader() = default;
78     bool ParseElf32Header(unsigned char * const ehdrBuf, const std::size_t bufSize);
79     bool ParseElf64Header(unsigned char * const ehdrBuf, const std::size_t bufSize);
80 };
81 
82 class ProgramHeader {
83 public:
84     static std::unique_ptr<ProgramHeader> MakeUnique(char * const phdrBuf, const size_t bufSize);
Init(char * const phdrBuf,const size_t bufSize)85     inline bool Init(char * const phdrBuf, const size_t bufSize)
86     {
87         if (bufSize == phdr32Size and ParsePrgHeader32(phdrBuf)) {
88             return true;
89         }
90         if (bufSize == phdr64Size and ParsePrgHeader64(phdrBuf)) {
91             return true;
92         }
93         HHLOGE(true, "parse program header failed, program header buffer dumped");
94         return false;
95     }
96 
97     uint32_t type_;
98     uint32_t flags_;
99     uint64_t offset_;
100     uint64_t vaddr_;
101     uint64_t paddr_;
102     uint64_t fileSize_;
103     uint64_t memSize_;
104     uint64_t secAlign_;
105 
106 private:
107     explicit ProgramHeader() = default;
108     bool ParsePrgHeader32(char * const phdrBuf);
109     bool ParsePrgHeader64(char * const phdrBuf);
110 };
111 
112 class SectionHeader {
113 public:
114     static std::unique_ptr<SectionHeader> MakeUnique(char * const shdrBuf, const size_t bufSize,
115                                                      const size_t index);
116 
Init(char * const shdrBuf,const size_t bufSize,const size_t index)117     inline bool Init(char * const shdrBuf, const size_t bufSize, const size_t index)
118     {
119         secIndex_ = index;
120         if (bufSize == shdr32Size and ParseSecHeader32(shdrBuf)) {
121             return true;
122         }
123         if (bufSize == shdr64Size and ParseSecHeader64(shdrBuf)) {
124             return true;
125         }
126         HHLOGE(true, "parse section header failed, section header buffer dumped");
127         return false;
128     }
129 
130     uint32_t nameIndex_;
131     uint32_t link_;
132     uint32_t info_;
133     uint64_t secFlags_;
134     uint64_t secVaddr_;
135     uint64_t fileOffset_;
136     uint64_t secSize_;
137     uint64_t secAddrAlign_;
138     uint64_t secEntrySize_;
139     uint64_t secType_;
140     uint32_t secIndex_;
141     std::string secTypeName_;
142 
143 private:
144     explicit SectionHeader() = default;
145     bool ParseSecHeader32(char * const shdrBuf);
146     bool ParseSecHeader64(char * const shdrBuf);
147 };
148 
149 class ElfFile {
150 public:
151     ~ElfFile();
152     static std::unique_ptr<ElfFile> MakeUnique(const std::string &filename);
153     bool ParseFile();
154     std::string GetSectionName(const uint32_t startIndex);
155 
IsOpened()156     inline bool IsOpened() const
157     {
158         return fd_ != -1;
159     }
160 
GetStrPtr(uint32_t sh_link,uint32_t st_name)161     inline const char *GetStrPtr(uint32_t sh_link, uint32_t st_name)
162     {
163         for (const auto &shdrsItem : shdrs_) {
164             if (shdrsItem.second->secIndex_ == sh_link) {
165                 if (mmap_ != MMAP_FAILED) {
166                     char *elfFileBegin = (char *)mmap_;
167                     return elfFileBegin + shdrsItem.second->fileOffset_ + st_name;
168                 }
169             }
170         }
171         HHLOGE(true, "string not found sh_link %u st_name %d", sh_link, st_name);
172         return nullptr;
173     }
174 
GetSectionData(uint32_t shIndex)175     inline const unsigned char *GetSectionData(uint32_t shIndex)
176     {
177         for (const auto &shdrsItem : shdrs_) {
178             if (shdrsItem.second->secIndex_ == shIndex) {
179                 if (mmap_ != MMAP_FAILED) {
180                     const unsigned char *elfFileBegin = (const unsigned char *)mmap_;
181                     return elfFileBegin + shdrsItem.second->fileOffset_;
182                 }
183             }
184         }
185         HHLOGE(true, "string not found shIndex %u ", shIndex);
186         return nullptr;
187     }
188 
189     using SecHeaderTableType = std::unordered_map<std::string, std::unique_ptr<SectionHeader>>;
190     using PrgHeaderTableType = std::vector<std::unique_ptr<ProgramHeader>>;
191     int fd_ {-1};
192     std::unique_ptr<ElfHeader> ehdr_ {nullptr};
193     SecHeaderTableType shdrs_ {};
194     PrgHeaderTableType phdrs_ {};
195     std::string secNamesStr_ {};
196 
197 private:
ReadFile(void * buf,size_t count)198     ssize_t ReadFile(void *buf, size_t count)
199     {
200         return read(fd_, buf, count);
201     };
202     explicit ElfFile(const std::string &filename);
203 
204     bool ParseElfHeader();
205     bool ParsePrgHeaders();
206     bool ParseSecNamesStr();
207     bool ParseSecHeaders();
208 
209     void *mmap_ = MMAP_FAILED;
210     uint64_t mmapSize_ = 0;
211 };
212 } // namespace Hiebpf
213 } // namespace Developtools
214 } // namespace OHOS
215 #endif // ELF_FILE_H_
216