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