X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FObject%2FELFObjectFile.cpp;h=a6c4c257d0e55e13ebac1646dcb9b47185dccc8b;hb=b0436a73054fe676b216a0cf872d1fc433125c62;hp=e427bedb982da71b77a2f88f149e247805e467c8;hpb=4344b1ef9b3721a5ebc2e024f753772a1e4ddd92;p=oota-llvm.git diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index e427bedb982..a6c4c257d0e 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -296,6 +296,7 @@ class ELFObjectFile : public ObjectFile { const Elf_Shdr *dot_strtab_sec; // Symbol header string table. Sections_t SymbolTableSections; IndexMap_t SymbolTableSectionsIndexMap; + DenseMap ExtendedSymbolTable; /// @brief Map sections to an array of relocation sections that reference /// them sorted by section index. @@ -314,29 +315,34 @@ class ELFObjectFile : public ObjectFile { const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; const Elf_Sym *getSymbol(DataRefImpl Symb) const; const Elf_Shdr *getSection(DataRefImpl index) const; - const Elf_Shdr *getSection(uint16_t index) const; + const Elf_Shdr *getSection(uint32_t index) const; const Elf_Rel *getRel(DataRefImpl Rel) const; const Elf_Rela *getRela(DataRefImpl Rela) const; - const char *getString(uint16_t section, uint32_t offset) const; + const char *getString(uint32_t section, uint32_t offset) const; const char *getString(const Elf_Shdr *section, uint32_t offset) const; error_code getSymbolName(const Elf_Sym *Symb, StringRef &Res) const; protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; - virtual error_code getSymbolOffset(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; virtual error_code isSymbolGlobal(DataRefImpl Symb, bool &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::SymbolType &Res) const; + virtual error_code isSymbolWeak(DataRefImpl Symb, bool &Res) const; + virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; + virtual error_code isSymbolAbsolute(DataRefImpl Symb, bool &Res) const; + virtual error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const; virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; @@ -349,10 +355,12 @@ protected: RelocationRef &Res) const; virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const; virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const; virtual error_code getRelocationType(DataRefImpl Rel, - uint32_t &Res) const; + uint64_t &Res) const; virtual error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const; virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, @@ -370,6 +378,16 @@ public: virtual uint8_t getBytesInAddress() const; virtual StringRef getFileFormatName() const; virtual unsigned getArch() const; + + uint64_t getNumSections() const; + uint64_t getStringTableIndex() const; + ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; + const Elf_Shdr *getSection(const Elf_Sym *symb) const; + + static inline bool classof(const Binary *v) { + return v->getType() == isELF; + } + static inline bool classof(const ELFObjectFile *v) { return true; } }; } // end namespace @@ -421,18 +439,37 @@ error_code ELFObjectFile ::getSymbolName(DataRefImpl Symb, StringRef &Result) const { validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); + const Elf_Sym *symb = getSymbol(Symb); return getSymbolName(symb, Result); } +template +ELF::Elf64_Word ELFObjectFile + ::getSymbolTableIndex(const Elf_Sym *symb) const { + if (symb->st_shndx == ELF::SHN_XINDEX) + return ExtendedSymbolTable.lookup(symb); + return symb->st_shndx; +} + +template +const typename ELFObjectFile::Elf_Shdr * +ELFObjectFile + ::getSection(const Elf_Sym *symb) const { + if (symb->st_shndx == ELF::SHN_XINDEX) + return getSection(ExtendedSymbolTable.lookup(symb)); + if (symb->st_shndx >= ELF::SHN_LORESERVE) + return 0; + return getSection(symb->st_shndx); +} + template error_code ELFObjectFile - ::getSymbolOffset(DataRefImpl Symb, - uint64_t &Result) const { + ::getSymbolFileOffset(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section; - switch (symb->st_shndx) { + switch (getSymbolTableIndex(symb)) { case ELF::SHN_COMMON: // Undefined symbols have no address yet. case ELF::SHN_UNDEF: @@ -441,7 +478,7 @@ error_code ELFObjectFile case ELF::SHN_ABS: Result = symb->st_value; return object_error::success; - default: Section = getSection(symb->st_shndx); + default: Section = getSection(symb); } switch (symb->getType()) { @@ -451,7 +488,8 @@ error_code ELFObjectFile case ELF::STT_FUNC: case ELF::STT_OBJECT: case ELF::STT_NOTYPE: - Result = symb->st_value; + Result = symb->st_value + + (Section ? Section->sh_offset - Section->sh_addr : 0); return object_error::success; default: Result = UnknownAddressOrSize; @@ -466,29 +504,26 @@ error_code ELFObjectFile validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section; - switch (symb->st_shndx) { - case ELF::SHN_COMMON: // Fall through. + switch (getSymbolTableIndex(symb)) { + case ELF::SHN_COMMON: // Undefined symbols have no address yet. case ELF::SHN_UNDEF: Result = UnknownAddressOrSize; return object_error::success; case ELF::SHN_ABS: - Result = reinterpret_cast(base()+symb->st_value); + Result = symb->st_value; return object_error::success; - default: Section = getSection(symb->st_shndx); + default: Section = getSection(symb); } - const uint8_t* addr = base(); - if (Section) - addr += Section->sh_offset; + switch (symb->getType()) { case ELF::STT_SECTION: - Result = reinterpret_cast(addr); + Result = Section ? Section->sh_addr : UnknownAddressOrSize; return object_error::success; - case ELF::STT_FUNC: // Fall through. - case ELF::STT_OBJECT: // Fall through. + case ELF::STT_FUNC: + case ELF::STT_OBJECT: case ELF::STT_NOTYPE: - addr += symb->st_value; - Result = reinterpret_cast(addr); + Result = symb->st_value; return object_error::success; default: Result = UnknownAddressOrSize; @@ -514,7 +549,7 @@ error_code ELFObjectFile char &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section = getSection(symb->st_shndx); + const Elf_Shdr *Section = getSection(symb); char ret = '?'; @@ -537,7 +572,7 @@ error_code ELFObjectFile } } - switch (symb->st_shndx) { + switch (getSymbolTableIndex(symb)) { case ELF::SHN_UNDEF: if (ret == '?') ret = 'U'; @@ -549,7 +584,7 @@ error_code ELFObjectFile switch (symb->getBinding()) { case ELF::STB_GLOBAL: ret = ::toupper(ret); break; case ELF::STB_WEAK: - if (symb->st_shndx == ELF::SHN_UNDEF) + if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) ret = 'w'; else if (symb->getType() == ELF::STT_OBJECT) @@ -576,16 +611,22 @@ error_code ELFObjectFile template error_code ELFObjectFile ::getSymbolType(DataRefImpl Symb, - SymbolRef::SymbolType &Result) const { + SymbolRef::Type &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); - if (symb->st_shndx == ELF::SHN_UNDEF) { + if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) { Result = SymbolRef::ST_External; return object_error::success; } switch (symb->getType()) { + case ELF::STT_SECTION: + Result = SymbolRef::ST_Debug; + break; + case ELF::STT_FILE: + Result = SymbolRef::ST_File; + break; case ELF::STT_FUNC: Result = SymbolRef::ST_Function; break; @@ -610,6 +651,43 @@ error_code ELFObjectFile return object_error::success; } +template +error_code ELFObjectFile + ::isSymbolWeak(DataRefImpl Symb, + bool &Result) const { + validateSymbol(Symb); + const Elf_Sym *symb = getSymbol(Symb); + + Result = symb->getBinding() == ELF::STB_WEAK; + return object_error::success; +} + +template +error_code ELFObjectFile + ::isSymbolAbsolute(DataRefImpl Symb, bool &Res) const { + validateSymbol(Symb); + const Elf_Sym *symb = getSymbol(Symb); + Res = symb->st_shndx == ELF::SHN_ABS; + return object_error::success; +} + +template +error_code ELFObjectFile + ::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { + validateSymbol(Symb); + const Elf_Sym *symb = getSymbol(Symb); + const Elf_Shdr *sec = getSection(symb); + if (!sec) + Res = end_sections(); + else { + DataRefImpl Sec; + Sec.p = reinterpret_cast(sec); + Res = section_iterator(SectionRef(Sec, this)); + } + return object_error::success; +} + template error_code ELFObjectFile ::isSymbolInternal(DataRefImpl Symb, @@ -671,6 +749,15 @@ error_code ELFObjectFile return object_error::success; } +template +error_code ELFObjectFile + ::getSectionAlignment(DataRefImpl Sec, + uint64_t &Result) const { + const Elf_Shdr *sec = reinterpret_cast(Sec.p); + Result = sec->sh_addralign; + return object_error::success; +} + template error_code ELFObjectFile ::isSectionText(DataRefImpl Sec, @@ -727,7 +814,7 @@ relocation_iterator ELFObjectFile const Elf_Shdr *sec = reinterpret_cast(Sec.p); typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); if (sec != 0 && ittr != SectionRelocMap.end()) { - RelData.w.a = getSection(ittr->second[0])->sh_link; + RelData.w.a = getSection(ittr->second[0])->sh_info; RelData.w.b = ittr->second[0]; RelData.w.c = 0; } @@ -745,7 +832,7 @@ relocation_iterator ELFObjectFile // Get the index of the last relocation section for this section. std::size_t relocsecindex = ittr->second[ittr->second.size() - 1]; const Elf_Shdr *relocsec = getSection(relocsecindex); - RelData.w.a = relocsec->sh_link; + RelData.w.a = relocsec->sh_info; RelData.w.b = relocsecindex; RelData.w.c = relocsec->sh_size / relocsec->sh_entsize; } @@ -762,7 +849,7 @@ error_code ELFObjectFile if (Rel.w.c >= (relocsec->sh_size / relocsec->sh_entsize)) { // We have reached the end of the relocations for this section. See if there // is another relocation section. - typename RelocMap_t::mapped_type &relocseclist = + typename RelocMap_t::mapped_type relocseclist = SectionRelocMap.lookup(getSection(Rel.w.a)); // Do a binary search for the current reloc section index (which must be @@ -833,10 +920,33 @@ error_code ELFObjectFile return object_error::success; } +template +error_code ELFObjectFile + ::getRelocationOffset(DataRefImpl Rel, + uint64_t &Result) const { + uint64_t offset; + const Elf_Shdr *sec = getSection(Rel.w.b); + switch (sec->sh_type) { + default : + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL : { + offset = getRel(Rel)->r_offset; + break; + } + case ELF::SHT_RELA : { + offset = getRela(Rel)->r_offset; + break; + } + } + + Result = offset - sec->sh_addr; + return object_error::success; +} + template error_code ELFObjectFile ::getRelocationType(DataRefImpl Rel, - uint32_t &Result) const { + uint64_t &Result) const { const Elf_Shdr *sec = getSection(Rel.w.b); switch (sec->sh_type) { default : @@ -1057,22 +1167,29 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object SectionHeaderTable = reinterpret_cast(base() + Header->e_shoff); - uint32_t SectionTableSize = Header->e_shnum * Header->e_shentsize; + uint64_t SectionTableSize = getNumSections() * Header->e_shentsize; if (!( (const uint8_t *)SectionHeaderTable + SectionTableSize <= base() + Data->getBufferSize())) // FIXME: Proper error handling. report_fatal_error("Section table goes past end of file!"); - // To find the symbol tables we walk the section table to find SHT_STMTAB. + // To find the symbol tables we walk the section table to find SHT_SYMTAB. + const Elf_Shdr* SymbolTableSectionHeaderIndex = 0; const Elf_Shdr* sh = reinterpret_cast(SectionHeaderTable); - for (unsigned i = 0; i < Header->e_shnum; ++i) { + for (uint64_t i = 0, e = getNumSections(); i != e; ++i) { + if (sh->sh_type == ELF::SHT_SYMTAB_SHNDX) { + if (SymbolTableSectionHeaderIndex) + // FIXME: Proper error handling. + report_fatal_error("More than one .symtab_shndx!"); + SymbolTableSectionHeaderIndex = sh; + } if (sh->sh_type == ELF::SHT_SYMTAB) { SymbolTableSectionsIndexMap[i] = SymbolTableSections.size(); SymbolTableSections.push_back(sh); } if (sh->sh_type == ELF::SHT_REL || sh->sh_type == ELF::SHT_RELA) { - SectionRelocMap[getSection(sh->sh_link)].push_back(i); + SectionRelocMap[getSection(sh->sh_info)].push_back(i); } ++sh; } @@ -1084,7 +1201,7 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object } // Get string table sections. - dot_shstrtab_sec = getSection(Header->e_shstrndx); + dot_shstrtab_sec = getSection(getStringTableIndex()); if (dot_shstrtab_sec) { // Verify that the last byte in the string table in a null. if (((const char*)base() + dot_shstrtab_sec->sh_offset) @@ -1095,7 +1212,7 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object // Merge this into the above loop. for (const char *i = reinterpret_cast(SectionHeaderTable), - *e = i + Header->e_shnum * Header->e_shentsize; + *e = i + getNumSections() * Header->e_shentsize; i != e; i += Header->e_shentsize) { const Elf_Shdr *sh = reinterpret_cast(i); if (sh->sh_type == ELF::SHT_STRTAB) { @@ -1112,6 +1229,21 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object } } } + + // Build symbol name side-mapping if there is one. + if (SymbolTableSectionHeaderIndex) { + const Elf_Word *ShndxTable = reinterpret_cast(base() + + SymbolTableSectionHeaderIndex->sh_offset); + error_code ec; + for (symbol_iterator si = begin_symbols(), + se = end_symbols(); si != se; si.increment(ec)) { + if (ec) + report_fatal_error("Fewer extended symbol table entries than symbols!"); + if (*ShndxTable != ELF::SHN_UNDEF) + ExtendedSymbolTable[getSymbol(si->getRawDataRefImpl())] = *ShndxTable; + ++ShndxTable; + } + } } template @@ -1155,7 +1287,7 @@ section_iterator ELFObjectFile memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(base() + Header->e_shoff - + (Header->e_shentsize * Header->e_shnum)); + + (Header->e_shentsize*getNumSections())); return section_iterator(SectionRef(ret, this)); } @@ -1208,6 +1340,25 @@ unsigned ELFObjectFile::getArch() const { } } +template +uint64_t ELFObjectFile::getNumSections() const { + if (Header->e_shnum == ELF::SHN_UNDEF) + return SectionHeaderTable->sh_size; + return Header->e_shnum; +} + +template +uint64_t +ELFObjectFile::getStringTableIndex() const { + if (Header->e_shnum == ELF::SHN_UNDEF) { + if (Header->e_shstrndx == ELF::SHN_HIRESERVE) + return SectionHeaderTable->sh_link; + if (Header->e_shstrndx >= getNumSections()) + return 0; + } + return Header->e_shstrndx; +} + template template @@ -1258,10 +1409,10 @@ ELFObjectFile::getSection(DataRefImpl Symb) const { template const typename ELFObjectFile::Elf_Shdr * -ELFObjectFile::getSection(uint16_t index) const { - if (index == 0 || index >= ELF::SHN_LORESERVE) +ELFObjectFile::getSection(uint32_t index) const { + if (index == 0) return 0; - if (!SectionHeaderTable || index >= Header->e_shnum) + if (!SectionHeaderTable || index >= getNumSections()) // FIXME: Proper error handling. report_fatal_error("Invalid section index!"); @@ -1272,7 +1423,7 @@ ELFObjectFile::getSection(uint16_t index) const { template const char *ELFObjectFile - ::getString(uint16_t section, + ::getString(uint32_t section, ELF::Elf32_Word offset) const { return getString(getSection(section), offset); } @@ -1293,7 +1444,7 @@ error_code ELFObjectFile ::getSymbolName(const Elf_Sym *symb, StringRef &Result) const { if (symb->st_name == 0) { - const Elf_Shdr *section = getSection(symb->st_shndx); + const Elf_Shdr *section = getSection(symb); if (!section) Result = ""; else