1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_LIBELFFILE_ELF_ELF_DEBUG_READER_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_LIBELFFILE_ELF_ELF_DEBUG_READER_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include "base/array_ref.h" 21*795d594fSAndroid Build Coastguard Worker #include "dwarf/headers.h" 22*795d594fSAndroid Build Coastguard Worker #include "elf/elf_utils.h" 23*795d594fSAndroid Build Coastguard Worker #include "xz_utils.h" 24*795d594fSAndroid Build Coastguard Worker 25*795d594fSAndroid Build Coastguard Worker #include <map> 26*795d594fSAndroid Build Coastguard Worker #include <string_view> 27*795d594fSAndroid Build Coastguard Worker 28*795d594fSAndroid Build Coastguard Worker namespace art { 29*795d594fSAndroid Build Coastguard Worker 30*795d594fSAndroid Build Coastguard Worker // Trivial ELF file reader. 31*795d594fSAndroid Build Coastguard Worker // 32*795d594fSAndroid Build Coastguard Worker // It is the bare minimum needed to read mini-debug-info symbols for unwinding. 33*795d594fSAndroid Build Coastguard Worker // We use it to merge JIT mini-debug-infos together or to prune them after GC. 34*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes> 35*795d594fSAndroid Build Coastguard Worker class ElfDebugReader { 36*795d594fSAndroid Build Coastguard Worker public: 37*795d594fSAndroid Build Coastguard Worker // Note that the input buffer might be misaligned. 38*795d594fSAndroid Build Coastguard Worker using Elf_Ehdr ALIGNED(1) = typename ElfTypes::Ehdr; 39*795d594fSAndroid Build Coastguard Worker using Elf_Phdr ALIGNED(1) = typename ElfTypes::Phdr; 40*795d594fSAndroid Build Coastguard Worker using Elf_Shdr ALIGNED(1) = typename ElfTypes::Shdr; 41*795d594fSAndroid Build Coastguard Worker using Elf_Sym ALIGNED(1) = typename ElfTypes::Sym; 42*795d594fSAndroid Build Coastguard Worker using Elf_Addr ALIGNED(1) = typename ElfTypes::Addr; 43*795d594fSAndroid Build Coastguard Worker 44*795d594fSAndroid Build Coastguard Worker // Call Frame Information. 45*795d594fSAndroid Build Coastguard Worker struct CFI { 46*795d594fSAndroid Build Coastguard Worker uint32_t length; // Length excluding the size of this field. 47*795d594fSAndroid Build Coastguard Worker int32_t cie_pointer; // Offset in the section or -1 for CIE. 48*795d594fSAndroid Build Coastguard Worker dataCFI49*795d594fSAndroid Build Coastguard Worker const uint8_t* data() const { return reinterpret_cast<const uint8_t*>(this); } sizeCFI50*795d594fSAndroid Build Coastguard Worker size_t size() const { return sizeof(uint32_t) + length; } 51*795d594fSAndroid Build Coastguard Worker } PACKED(1); 52*795d594fSAndroid Build Coastguard Worker 53*795d594fSAndroid Build Coastguard Worker // Common Information Entry. 54*795d594fSAndroid Build Coastguard Worker struct CIE : public CFI { 55*795d594fSAndroid Build Coastguard Worker } PACKED(1); 56*795d594fSAndroid Build Coastguard Worker 57*795d594fSAndroid Build Coastguard Worker // Frame Description Entry. 58*795d594fSAndroid Build Coastguard Worker struct FDE : public CFI { 59*795d594fSAndroid Build Coastguard Worker Elf_Addr sym_addr; 60*795d594fSAndroid Build Coastguard Worker Elf_Addr sym_size; 61*795d594fSAndroid Build Coastguard Worker } PACKED(1); 62*795d594fSAndroid Build Coastguard Worker ElfDebugReader(ArrayRef<const uint8_t> file)63*795d594fSAndroid Build Coastguard Worker explicit ElfDebugReader(ArrayRef<const uint8_t> file) : file_(file) { 64*795d594fSAndroid Build Coastguard Worker header_ = Read<Elf_Ehdr>(/*offset=*/ 0); 65*795d594fSAndroid Build Coastguard Worker CHECK_EQ(header_->e_ident[0], ELFMAG0); 66*795d594fSAndroid Build Coastguard Worker CHECK_EQ(header_->e_ident[1], ELFMAG1); 67*795d594fSAndroid Build Coastguard Worker CHECK_EQ(header_->e_ident[2], ELFMAG2); 68*795d594fSAndroid Build Coastguard Worker CHECK_EQ(header_->e_ident[3], ELFMAG3); 69*795d594fSAndroid Build Coastguard Worker CHECK_EQ(header_->e_ident[4], sizeof(Elf_Addr) / sizeof(uint32_t)); 70*795d594fSAndroid Build Coastguard Worker CHECK_EQ(header_->e_ehsize, sizeof(Elf_Ehdr)); 71*795d594fSAndroid Build Coastguard Worker 72*795d594fSAndroid Build Coastguard Worker // Find all ELF sections. 73*795d594fSAndroid Build Coastguard Worker CHECK_EQ(header_->e_shentsize, sizeof(Elf_Shdr)); 74*795d594fSAndroid Build Coastguard Worker sections_ = Read<Elf_Shdr>(header_->e_shoff, header_->e_shnum); 75*795d594fSAndroid Build Coastguard Worker for (const Elf_Shdr& section : sections_) { 76*795d594fSAndroid Build Coastguard Worker const char* name = Read<char>(sections_[header_->e_shstrndx].sh_offset + section.sh_name); 77*795d594fSAndroid Build Coastguard Worker section_map_[std::string_view(name)] = §ion; 78*795d594fSAndroid Build Coastguard Worker } 79*795d594fSAndroid Build Coastguard Worker 80*795d594fSAndroid Build Coastguard Worker // Decompressed embedded debug symbols, if any. 81*795d594fSAndroid Build Coastguard Worker const Elf_Shdr* gnu_debugdata = section_map_[".gnu_debugdata"]; 82*795d594fSAndroid Build Coastguard Worker if (gnu_debugdata != nullptr) { 83*795d594fSAndroid Build Coastguard Worker auto compressed = Read<uint8_t>(gnu_debugdata->sh_offset, gnu_debugdata->sh_size); 84*795d594fSAndroid Build Coastguard Worker XzDecompress(compressed, &decompressed_gnu_debugdata_); 85*795d594fSAndroid Build Coastguard Worker gnu_debugdata_reader_.reset(new ElfDebugReader(decompressed_gnu_debugdata_)); 86*795d594fSAndroid Build Coastguard Worker } 87*795d594fSAndroid Build Coastguard Worker } 88*795d594fSAndroid Build Coastguard Worker ElfDebugReader(const std::vector<uint8_t> & file)89*795d594fSAndroid Build Coastguard Worker explicit ElfDebugReader(const std::vector<uint8_t>& file) 90*795d594fSAndroid Build Coastguard Worker : ElfDebugReader(ArrayRef<const uint8_t>(file)) { 91*795d594fSAndroid Build Coastguard Worker } 92*795d594fSAndroid Build Coastguard Worker 93*795d594fSAndroid Build Coastguard Worker // Check that ELF signature is present at the start of the files, 94*795d594fSAndroid Build Coastguard Worker // and that the ELF bitness matches the ElfTypes template arguments. IsValidElfHeader(const std::vector<uint8_t> & data)95*795d594fSAndroid Build Coastguard Worker static bool IsValidElfHeader(const std::vector<uint8_t>& data) { 96*795d594fSAndroid Build Coastguard Worker static constexpr bool kIs64Bit = sizeof(Elf_Addr) == sizeof(uint64_t); 97*795d594fSAndroid Build Coastguard Worker static constexpr char kMagic[] = { 0x7f, 'E', 'L', 'F', kIs64Bit ? 2 : 1 }; 98*795d594fSAndroid Build Coastguard Worker return data.size() >= sizeof(kMagic) && memcmp(data.data(), kMagic, sizeof(kMagic)) == 0; 99*795d594fSAndroid Build Coastguard Worker } 100*795d594fSAndroid Build Coastguard Worker GetHeader()101*795d594fSAndroid Build Coastguard Worker const Elf_Ehdr* GetHeader() { return header_; } 102*795d594fSAndroid Build Coastguard Worker GetSections()103*795d594fSAndroid Build Coastguard Worker ArrayRef<Elf_Shdr> GetSections() { return sections_; } 104*795d594fSAndroid Build Coastguard Worker GetSection(const char * name)105*795d594fSAndroid Build Coastguard Worker const Elf_Shdr* GetSection(const char* name) { return section_map_[name]; } 106*795d594fSAndroid Build Coastguard Worker 107*795d594fSAndroid Build Coastguard Worker // Find the base address where the ELF file wants to be loaded. 108*795d594fSAndroid Build Coastguard Worker // This is generally zero (therefore always requiring relocation). GetLoadAddress()109*795d594fSAndroid Build Coastguard Worker Elf_Addr GetLoadAddress() { 110*795d594fSAndroid Build Coastguard Worker std::optional<Elf_Addr> addr; 111*795d594fSAndroid Build Coastguard Worker CHECK_EQ(header_->e_phentsize, sizeof(Elf_Phdr)); 112*795d594fSAndroid Build Coastguard Worker for (const Elf_Phdr& phdr : Read<Elf_Phdr>(header_->e_phoff, header_->e_phnum)) { 113*795d594fSAndroid Build Coastguard Worker if (phdr.p_type == PT_LOAD) { 114*795d594fSAndroid Build Coastguard Worker addr = addr.has_value() ? std::min(addr.value(), phdr.p_vaddr) : phdr.p_vaddr; 115*795d594fSAndroid Build Coastguard Worker } 116*795d594fSAndroid Build Coastguard Worker } 117*795d594fSAndroid Build Coastguard Worker CHECK(addr.has_value()); 118*795d594fSAndroid Build Coastguard Worker return addr.value(); 119*795d594fSAndroid Build Coastguard Worker } 120*795d594fSAndroid Build Coastguard Worker 121*795d594fSAndroid Build Coastguard Worker template <typename VisitSym> VisitFunctionSymbols(VisitSym && visit_sym)122*795d594fSAndroid Build Coastguard Worker void VisitFunctionSymbols(VisitSym&& visit_sym) { 123*795d594fSAndroid Build Coastguard Worker const Elf_Shdr* symtab = GetSection(".symtab"); 124*795d594fSAndroid Build Coastguard Worker const Elf_Shdr* strtab = GetSection(".strtab"); 125*795d594fSAndroid Build Coastguard Worker const Elf_Shdr* text = GetSection(".text"); 126*795d594fSAndroid Build Coastguard Worker if (symtab != nullptr && strtab != nullptr) { 127*795d594fSAndroid Build Coastguard Worker CHECK_EQ(symtab->sh_entsize, sizeof(Elf_Sym)); 128*795d594fSAndroid Build Coastguard Worker size_t count = symtab->sh_size / sizeof(Elf_Sym); 129*795d594fSAndroid Build Coastguard Worker for (const Elf_Sym& symbol : Read<Elf_Sym>(symtab->sh_offset, count)) { 130*795d594fSAndroid Build Coastguard Worker if (ELF_ST_TYPE(symbol.st_info) == STT_FUNC && 131*795d594fSAndroid Build Coastguard Worker symbol.st_shndx < sections_.size() && // Ignore ABS section. 132*795d594fSAndroid Build Coastguard Worker §ions_[symbol.st_shndx] == text) { 133*795d594fSAndroid Build Coastguard Worker visit_sym(symbol, Read<char>(strtab->sh_offset + symbol.st_name)); 134*795d594fSAndroid Build Coastguard Worker } 135*795d594fSAndroid Build Coastguard Worker } 136*795d594fSAndroid Build Coastguard Worker } 137*795d594fSAndroid Build Coastguard Worker if (gnu_debugdata_reader_ != nullptr) { 138*795d594fSAndroid Build Coastguard Worker gnu_debugdata_reader_->VisitFunctionSymbols(std::forward<VisitSym>(visit_sym)); 139*795d594fSAndroid Build Coastguard Worker } 140*795d594fSAndroid Build Coastguard Worker } 141*795d594fSAndroid Build Coastguard Worker 142*795d594fSAndroid Build Coastguard Worker template <typename VisitSym> VisitDynamicSymbols(VisitSym && visit_sym)143*795d594fSAndroid Build Coastguard Worker void VisitDynamicSymbols(VisitSym&& visit_sym) { 144*795d594fSAndroid Build Coastguard Worker const Elf_Shdr* dynsym = GetSection(".dynsym"); 145*795d594fSAndroid Build Coastguard Worker const Elf_Shdr* dynstr = GetSection(".dynstr"); 146*795d594fSAndroid Build Coastguard Worker if (dynsym != nullptr && dynstr != nullptr) { 147*795d594fSAndroid Build Coastguard Worker CHECK_EQ(dynsym->sh_entsize, sizeof(Elf_Sym)); 148*795d594fSAndroid Build Coastguard Worker size_t count = dynsym->sh_size / sizeof(Elf_Sym); 149*795d594fSAndroid Build Coastguard Worker for (const Elf_Sym& symbol : Read<Elf_Sym>(dynsym->sh_offset, count)) { 150*795d594fSAndroid Build Coastguard Worker visit_sym(symbol, Read<char>(dynstr->sh_offset + symbol.st_name)); 151*795d594fSAndroid Build Coastguard Worker } 152*795d594fSAndroid Build Coastguard Worker } 153*795d594fSAndroid Build Coastguard Worker } 154*795d594fSAndroid Build Coastguard Worker 155*795d594fSAndroid Build Coastguard Worker template <typename VisitCIE, typename VisitFDE> VisitDebugFrame(VisitCIE && visit_cie,VisitFDE && visit_fde)156*795d594fSAndroid Build Coastguard Worker void VisitDebugFrame(VisitCIE&& visit_cie, VisitFDE&& visit_fde) { 157*795d594fSAndroid Build Coastguard Worker const Elf_Shdr* debug_frame = GetSection(".debug_frame"); 158*795d594fSAndroid Build Coastguard Worker if (debug_frame != nullptr) { 159*795d594fSAndroid Build Coastguard Worker for (size_t offset = 0; offset < debug_frame->sh_size;) { 160*795d594fSAndroid Build Coastguard Worker const CFI* entry = Read<CFI>(debug_frame->sh_offset + offset); 161*795d594fSAndroid Build Coastguard Worker DCHECK_LE(entry->size(), debug_frame->sh_size - offset); 162*795d594fSAndroid Build Coastguard Worker if (entry->cie_pointer == -1) { 163*795d594fSAndroid Build Coastguard Worker visit_cie(Read<CIE>(debug_frame->sh_offset + offset)); 164*795d594fSAndroid Build Coastguard Worker } else { 165*795d594fSAndroid Build Coastguard Worker const FDE* fde = Read<FDE>(debug_frame->sh_offset + offset); 166*795d594fSAndroid Build Coastguard Worker visit_fde(fde, Read<CIE>(debug_frame->sh_offset + fde->cie_pointer)); 167*795d594fSAndroid Build Coastguard Worker } 168*795d594fSAndroid Build Coastguard Worker offset += entry->size(); 169*795d594fSAndroid Build Coastguard Worker } 170*795d594fSAndroid Build Coastguard Worker } 171*795d594fSAndroid Build Coastguard Worker if (gnu_debugdata_reader_ != nullptr) { 172*795d594fSAndroid Build Coastguard Worker gnu_debugdata_reader_->VisitDebugFrame(std::forward<VisitCIE>(visit_cie), 173*795d594fSAndroid Build Coastguard Worker std::forward<VisitFDE>(visit_fde)); 174*795d594fSAndroid Build Coastguard Worker } 175*795d594fSAndroid Build Coastguard Worker } 176*795d594fSAndroid Build Coastguard Worker 177*795d594fSAndroid Build Coastguard Worker private: 178*795d594fSAndroid Build Coastguard Worker template<typename T> Read(size_t offset)179*795d594fSAndroid Build Coastguard Worker const T* Read(size_t offset) { 180*795d594fSAndroid Build Coastguard Worker DCHECK_LE(offset + sizeof(T), file_.size()); 181*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const T*>(file_.data() + offset); 182*795d594fSAndroid Build Coastguard Worker } 183*795d594fSAndroid Build Coastguard Worker 184*795d594fSAndroid Build Coastguard Worker template<typename T> Read(size_t offset,size_t count)185*795d594fSAndroid Build Coastguard Worker ArrayRef<const T> Read(size_t offset, size_t count) { 186*795d594fSAndroid Build Coastguard Worker DCHECK_LE(offset + count * sizeof(T), file_.size()); 187*795d594fSAndroid Build Coastguard Worker return ArrayRef<const T>(Read<T>(offset), count); 188*795d594fSAndroid Build Coastguard Worker } 189*795d594fSAndroid Build Coastguard Worker 190*795d594fSAndroid Build Coastguard Worker ArrayRef<const uint8_t> const file_; 191*795d594fSAndroid Build Coastguard Worker const Elf_Ehdr* header_; 192*795d594fSAndroid Build Coastguard Worker ArrayRef<const Elf_Shdr> sections_; 193*795d594fSAndroid Build Coastguard Worker std::unordered_map<std::string_view, const Elf_Shdr*> section_map_; 194*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> decompressed_gnu_debugdata_; 195*795d594fSAndroid Build Coastguard Worker std::unique_ptr<ElfDebugReader> gnu_debugdata_reader_; 196*795d594fSAndroid Build Coastguard Worker 197*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ElfDebugReader); 198*795d594fSAndroid Build Coastguard Worker }; 199*795d594fSAndroid Build Coastguard Worker 200*795d594fSAndroid Build Coastguard Worker } // namespace art 201*795d594fSAndroid Build Coastguard Worker #endif // ART_LIBELFFILE_ELF_ELF_DEBUG_READER_H_ 202