llvm.org GIT mirror llvm / c22eb2b
Don't iterate over the program headers in the constructor of ELFFile. Not every program needs this information. In particular, it is necessary and sufficient for a static linker to scan the section table. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242833 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Espindola 4 years ago
2 changed file(s) with 174 addition(s) and 190 deletion(s). Raw diff Collapse all Expand all
156156
157157 typedef iterator_range Elf_Sym_Range;
158158
159 const uint8_t *base() const {
160 return reinterpret_cast(Buf.data());
161 }
162
159163 private:
160164 typedef SmallVector Sections_t;
161165 typedef DenseMap IndexMap_t;
162166
163167 StringRef Buf;
164
165 const uint8_t *base() const {
166 return reinterpret_cast(Buf.data());
167 }
168168
169169 const Elf_Ehdr *Header;
170170 const Elf_Shdr *SectionHeaderTable = nullptr;
172172 StringRef DotStrtab; // Symbol header string table.
173173 const Elf_Shdr *dot_symtab_sec = nullptr; // Symbol table section.
174174 const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section.
175 const Elf_Hash *HashTable = nullptr;
176175
177176 const Elf_Shdr *SymbolTableSectionHeaderIndex = nullptr;
178177 DenseMap ExtendedSymbolTable;
180179 const Elf_Shdr *dot_gnu_version_sec = nullptr; // .gnu.version
181180 const Elf_Shdr *dot_gnu_version_r_sec = nullptr; // .gnu.version_r
182181 const Elf_Shdr *dot_gnu_version_d_sec = nullptr; // .gnu.version_d
183
184 /// \brief Represents a region described by entries in the .dynamic table.
185 struct DynRegionInfo {
186 DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {}
187 /// \brief Address in current address space.
188 const void *Addr;
189 /// \brief Size in bytes of the region.
190 uintX_t Size;
191 /// \brief Size of each entity in the region.
192 uintX_t EntSize;
193 };
194
195 DynRegionInfo DynamicRegion;
196 DynRegionInfo DynStrRegion;
197 DynRegionInfo DynRelaRegion;
198
199 // SONAME entry in dynamic string table
200 StringRef DTSoname;
201182
202183 // Records for each version index the corresponding Verdef or Vernaux entry.
203184 // This is filled the first time LoadVersionMap() is called.
225206 void LoadVersionNeeds(const Elf_Shdr *ec) const;
226207 void LoadVersionMap() const;
227208
228 void scanDynamicTable();
229
230209 public:
231210 template
232211 const T *getEntry(uint32_t Section, uint32_t Entry) const;
235214
236215 const Elf_Shdr *getDotSymtabSec() const { return dot_symtab_sec; }
237216 const Elf_Shdr *getDotDynSymSec() const { return DotDynSymSec; }
238 const Elf_Hash *getHashTable() const { return HashTable; }
239 StringRef getDynamicStringTable() const {
240 return StringRef((const char *)DynStrRegion.Addr, DynStrRegion.Size);
241 }
242217
243218 ErrorOr getStringTable(const Elf_Shdr *Section) const;
244219 ErrorOr getStringTableForSymtab(const Elf_Shdr &Section) const;
245220
246 const char *getDynamicString(uintX_t Offset) const;
247 ErrorOr getSymbolVersion(const Elf_Sym *Symb,
221 ErrorOr getSymbolVersion(StringRef StrTab, const Elf_Sym *Symb,
248222 bool &IsDefault) const;
249223 void VerifyStrTab(const Elf_Shdr *sh) const;
250224
280254 const Elf_Sym *symbol_end() const;
281255 Elf_Sym_Range symbols() const {
282256 return make_range(symbol_begin(), symbol_end());
283 }
284
285 const Elf_Dyn *dynamic_table_begin() const;
286 const Elf_Dyn *dynamic_table_end() const;
287 Elf_Dyn_Range dynamic_table() const {
288 return make_range(dynamic_table_begin(), dynamic_table_end());
289257 }
290258
291259 const Elf_Sym *dynamic_symbol_begin() const {
307275 return make_range(dynamic_symbol_begin(), dynamic_symbol_end());
308276 }
309277
310 const Elf_Rela *dyn_rela_begin() const {
311 if (DynRelaRegion.Size && DynRelaRegion.EntSize != sizeof(Elf_Rela))
312 report_fatal_error("Invalid relocation entry size");
313 return reinterpret_cast(DynRelaRegion.Addr);
314 }
315
316 const Elf_Rela *dyn_rela_end() const {
317 uint64_t Size = DynRelaRegion.Size;
318 if (Size % sizeof(Elf_Rela))
319 report_fatal_error("Invalid relocation table size");
320 return dyn_rela_begin() + Size / sizeof(Elf_Rela);
321 }
322
323278 typedef iterator_range Elf_Rela_Range;
324
325 Elf_Rela_Range dyn_relas() const {
326 return make_range(dyn_rela_begin(), dyn_rela_end());
327 }
328279
329280 const Elf_Rela *rela_begin(const Elf_Shdr *sec) const {
330281 if (sec->sh_entsize != sizeof(Elf_Rela))
388339
389340 ErrorOr getSectionName(const Elf_Shdr *Section) const;
390341 ErrorOr > getSectionContents(const Elf_Shdr *Sec) const;
391 StringRef getLoadName() const;
392342 };
393343
394344 typedef ELFFile> ELF32LEFile;
595545
596546 Header = reinterpret_cast(base());
597547
598 if (Header->e_shoff == 0) {
599 scanDynamicTable();
548 if (Header->e_shoff == 0)
600549 return;
601 }
602550
603551 const uint64_t SectionTableOffset = Header->e_shoff;
604552
623571
624572 for (const Elf_Shdr &Sec : sections()) {
625573 switch (Sec.sh_type) {
626 case ELF::SHT_HASH:
627 if (HashTable) {
628 EC = object_error::parse_failed;
629 return;
630 }
631 HashTable = reinterpret_cast(base() + Sec.sh_offset);
632 break;
633574 case ELF::SHT_SYMTAB_SHNDX:
634575 if (SymbolTableSectionHeaderIndex) {
635576 // More than one .symtab_shndx!
707648 }
708649 }
709650
710 scanDynamicTable();
711
712651 EC = std::error_code();
713652 }
714653
715654 template
716655 static bool compareAddr(uint64_t VAddr, const Elf_Phdr_Impl *Phdr) {
717656 return VAddr < Phdr->p_vaddr;
718 }
719
720 template void ELFFile::scanDynamicTable() {
721 SmallVector LoadSegments;
722 for (const Elf_Phdr &Phdr : program_headers()) {
723 if (Phdr.p_type == ELF::PT_DYNAMIC) {
724 DynamicRegion.Addr = base() + Phdr.p_offset;
725 DynamicRegion.Size = Phdr.p_filesz;
726 continue;
727 }
728 if (Phdr.p_type != ELF::PT_LOAD || Phdr.p_filesz == 0)
729 continue;
730 LoadSegments.push_back(&Phdr);
731 }
732
733 auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * {
734 const Elf_Phdr **I = std::upper_bound(
735 LoadSegments.begin(), LoadSegments.end(), VAddr, compareAddr);
736 if (I == LoadSegments.begin())
737 report_fatal_error("Virtual address is not in any segment");
738 --I;
739 const Elf_Phdr &Phdr = **I;
740 uint64_t Delta = VAddr - Phdr.p_vaddr;
741 if (Delta >= Phdr.p_filesz)
742 report_fatal_error("Virtual address is not in any segment");
743 return this->base() + Phdr.p_offset + Delta;
744 };
745
746 uint64_t SONameOffset = 0;
747 for (const Elf_Dyn &Dyn : dynamic_table()) {
748 switch (Dyn.d_tag) {
749 case ELF::DT_HASH:
750 if (HashTable)
751 continue;
752 HashTable =
753 reinterpret_cast(toMappedAddr(Dyn.getPtr()));
754 break;
755 case ELF::DT_STRTAB:
756 if (!DynStrRegion.Addr)
757 DynStrRegion.Addr = toMappedAddr(Dyn.getPtr());
758 break;
759 case ELF::DT_STRSZ:
760 if (!DynStrRegion.Size)
761 DynStrRegion.Size = Dyn.getVal();
762 break;
763 case ELF::DT_RELA:
764 if (!DynRelaRegion.Addr)
765 DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr());
766 break;
767 case ELF::DT_RELASZ:
768 DynRelaRegion.Size = Dyn.getVal();
769 break;
770 case ELF::DT_RELAENT:
771 DynRelaRegion.EntSize = Dyn.getVal();
772 break;
773 case ELF::DT_SONAME:
774 SONameOffset = Dyn.getVal();
775 break;
776 }
777 }
778 if (SONameOffset)
779 DTSoname = getDynamicString(SONameOffset);
780657 }
781658
782659 template
807684 return nullptr;
808685 return reinterpret_cast(base() + dot_symtab_sec->sh_offset +
809686 dot_symtab_sec->sh_size);
810 }
811
812 template
813 const typename ELFFile::Elf_Dyn *
814 ELFFile::dynamic_table_begin() const {
815 return reinterpret_cast(DynamicRegion.Addr);
816 }
817
818 template
819 const typename ELFFile::Elf_Dyn *
820 ELFFile::dynamic_table_end() const {
821 uint64_t Size = DynamicRegion.Size;
822 if (Size % sizeof(Elf_Dyn))
823 report_fatal_error("Invalid dynamic table size");
824
825 return dynamic_table_begin() + Size / sizeof(Elf_Dyn);
826 }
827
828 template
829 StringRef ELFFile::getLoadName() const {
830 return DTSoname;
831687 }
832688
833689 template
886742 }
887743
888744 template
889 const char *ELFFile::getDynamicString(uintX_t Offset) const {
890 if (Offset >= DynStrRegion.Size)
891 return nullptr;
892 return (const char *)DynStrRegion.Addr + Offset;
893 }
894
895 template
896745 ErrorOr
897746 ELFFile::getSectionName(const Elf_Shdr *Section) const {
898747 uint32_t Offset = Section->sh_name;
902751 }
903752
904753 template
905 ErrorOr ELFFile::getSymbolVersion(const Elf_Sym *symb,
754 ErrorOr ELFFile::getSymbolVersion(StringRef StrTab,
755 const Elf_Sym *symb,
906756 bool &IsDefault) const {
907757 // This is a dynamic symbol. Look in the GNU symbol version table.
908758 if (!dot_gnu_version_sec) {
950800 IsDefault = false;
951801 }
952802
953 if (name_offset >= DynStrRegion.Size)
803 if (name_offset >= StrTab.size())
954804 return object_error::parse_failed;
955 return StringRef(getDynamicString(name_offset));
805 return StringRef(StrTab.data() + name_offset);
956806 }
957807
958808 /// This function returns the hash value for a symbol in the .dynsym section
4141 template
4242 class ELFDumper : public ObjDumper {
4343 public:
44 ELFDumper(const ELFFile *Obj, StreamWriter &Writer)
45 : ObjDumper(Writer), Obj(Obj) {}
44 ELFDumper(const ELFFile *Obj, StreamWriter &Writer);
4645
4746 void printFileHeaders() override;
4847 void printSections() override;
6968 typedef ELFFile ELFO;
7069 typedef typename ELFO::Elf_Shdr Elf_Shdr;
7170 typedef typename ELFO::Elf_Sym Elf_Sym;
71 typedef typename ELFO::Elf_Dyn Elf_Dyn;
72 typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range;
73 typedef typename ELFO::Elf_Rela Elf_Rela;
74 typedef typename ELFO::Elf_Rela_Range Elf_Rela_Range;
75 typedef typename ELFO::Elf_Phdr Elf_Phdr;
76 typedef typename ELFO::Elf_Hash Elf_Hash;
77 typedef typename ELFO::uintX_t uintX_t;
78
79 /// \brief Represents a region described by entries in the .dynamic table.
80 struct DynRegionInfo {
81 DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {}
82 /// \brief Address in current address space.
83 const void *Addr;
84 /// \brief Size in bytes of the region.
85 uintX_t Size;
86 /// \brief Size of each entity in the region.
87 uintX_t EntSize;
88 };
7289
7390 void printSymbol(const Elf_Sym *Symbol, StringRef StrTable, bool IsDynamic);
7491
7693 void printRelocation(const Elf_Shdr *Sec, typename ELFO::Elf_Rela Rel);
7794 void printValue(uint64_t Type, uint64_t Value);
7895
96 const Elf_Rela *dyn_rela_begin() const;
97 const Elf_Rela *dyn_rela_end() const;
98 Elf_Rela_Range dyn_relas() const;
99 StringRef getDynamicString(uint64_t Offset) const;
100 const Elf_Dyn *dynamic_table_begin() const;
101 const Elf_Dyn *dynamic_table_end() const;
102 Elf_Dyn_Range dynamic_table() const {
103 return make_range(dynamic_table_begin(), dynamic_table_end());
104 }
105
79106 const ELFO *Obj;
107 DynRegionInfo DynRelaRegion;
108 DynRegionInfo DynamicRegion;
109 StringRef DynamicStringTable;
110 StringRef SOName;
111 const Elf_Hash *HashTable = nullptr;
80112 };
81113
82114 template T errorOrDefault(ErrorOr Val, T Default = T()) {
134166 std::string FullSymbolName(SymbolName);
135167
136168 bool IsDefault;
137 ErrorOr Version = Obj.getSymbolVersion(&*Symbol, IsDefault);
169 ErrorOr Version =
170 Obj.getSymbolVersion(StrTable, &*Symbol, IsDefault);
138171 if (Version) {
139172 FullSymbolName += (IsDefault ? "@@" : "@");
140173 FullSymbolName += *Version;
565598 LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R6)
566599 };
567600
601 template
602 ELFDumper::ELFDumper(const ELFFile *Obj, StreamWriter &Writer)
603 : ObjDumper(Writer), Obj(Obj) {
604
605 SmallVector LoadSegments;
606 for (const Elf_Phdr &Phdr : Obj->program_headers()) {
607 if (Phdr.p_type == ELF::PT_DYNAMIC) {
608 DynamicRegion.Addr = Obj->base() + Phdr.p_offset;
609 uint64_t Size = Phdr.p_filesz;
610 if (Size % sizeof(Elf_Dyn))
611 report_fatal_error("Invalid dynamic table size");
612 DynamicRegion.Size = Phdr.p_filesz;
613 continue;
614 }
615 if (Phdr.p_type != ELF::PT_LOAD || Phdr.p_filesz == 0)
616 continue;
617 LoadSegments.push_back(&Phdr);
618 }
619
620 auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * {
621 const Elf_Phdr **I = std::upper_bound(
622 LoadSegments.begin(), LoadSegments.end(), VAddr, compareAddr);
623 if (I == LoadSegments.begin())
624 report_fatal_error("Virtual address is not in any segment");
625 --I;
626 const Elf_Phdr &Phdr = **I;
627 uint64_t Delta = VAddr - Phdr.p_vaddr;
628 if (Delta >= Phdr.p_filesz)
629 report_fatal_error("Virtual address is not in any segment");
630 return Obj->base() + Phdr.p_offset + Delta;
631 };
632
633 uint64_t SONameOffset = 0;
634 const char *StringTableBegin = nullptr;
635 uint64_t StringTableSize = 0;
636 for (const Elf_Dyn &Dyn : dynamic_table()) {
637 switch (Dyn.d_tag) {
638 case ELF::DT_HASH:
639 HashTable =
640 reinterpret_cast(toMappedAddr(Dyn.getPtr()));
641 break;
642 case ELF::DT_RELA:
643 DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr());
644 break;
645 case ELF::DT_RELASZ:
646 DynRelaRegion.Size = Dyn.getVal();
647 break;
648 case ELF::DT_RELAENT:
649 DynRelaRegion.EntSize = Dyn.getVal();
650 break;
651 case ELF::DT_SONAME:
652 SONameOffset = Dyn.getVal();
653 break;
654 case ELF::DT_STRTAB:
655 StringTableBegin = (const char *)toMappedAddr(Dyn.getPtr());
656 break;
657 case ELF::DT_STRSZ:
658 StringTableSize = Dyn.getVal();
659 break;
660 }
661 }
662 if (StringTableBegin)
663 DynamicStringTable = StringRef(StringTableBegin, StringTableSize);
664 if (SONameOffset)
665 SOName = getDynamicString(SONameOffset);
666 }
667
668 template
669 const typename ELFDumper::Elf_Rela *
670 ELFDumper::dyn_rela_begin() const {
671 if (DynRelaRegion.Size && DynRelaRegion.EntSize != sizeof(Elf_Rela))
672 report_fatal_error("Invalid relocation entry size");
673 return reinterpret_cast(DynRelaRegion.Addr);
674 }
675
676 template
677 const typename ELFDumper::Elf_Rela *
678 ELFDumper::dyn_rela_end() const {
679 uint64_t Size = DynRelaRegion.Size;
680 if (Size % sizeof(Elf_Rela))
681 report_fatal_error("Invalid relocation table size");
682 return dyn_rela_begin() + Size / sizeof(Elf_Rela);
683 }
684
685 template
686 typename ELFDumper::Elf_Rela_Range ELFDumper::dyn_relas() const {
687 return make_range(dyn_rela_begin(), dyn_rela_end());
688 }
689
690 template
691 const typename ELFDumper::Elf_Dyn *
692 ELFDumper::dynamic_table_begin() const {
693 return reinterpret_cast(DynamicRegion.Addr);
694 }
695
696 template
697 const typename ELFDumper::Elf_Dyn *
698 ELFDumper::dynamic_table_end() const {
699 uint64_t Size = DynamicRegion.Size;
700 return dynamic_table_begin() + Size / sizeof(Elf_Dyn);
701 }
702
568703 template
569704 void ELFDumper::printFileHeaders() {
570705 const typename ELFO::Elf_Ehdr *Header = Obj->getHeader();
694829 void ELFDumper::printDynamicRelocations() {
695830 W.startLine() << "Dynamic Relocations {\n";
696831 W.indent();
697 StringRef StringTable = Obj->getDynamicStringTable();
698 for (const typename ELFO::Elf_Rela &Rel : Obj->dyn_relas()) {
832 for (const typename ELFO::Elf_Rela &Rel : dyn_relas()) {
699833 SmallString<32> RelocName;
700834 Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
701835 StringRef SymbolName;
702836 uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL());
703837 const typename ELFO::Elf_Sym *Sym = Obj->dynamic_symbol_begin() + SymIndex;
704 SymbolName = errorOrDefault(Sym->getName(StringTable));
838 SymbolName = errorOrDefault(Sym->getName(DynamicStringTable));
705839 if (opts::ExpandRelocs) {
706840 DictScope Group(W, "Relocation");
707841 W.printHex("Offset", Rel.r_offset);
9591093 }
9601094
9611095 template
962 static const char *getDynamicString(const ELFFile &O, uint64_t Value) {
963 const char *Ret = O.getDynamicString(Value);
964 if (!Ret)
1096 StringRef ELFDumper::getDynamicString(uint64_t Value) const {
1097 if (Value >= DynamicStringTable.size())
9651098 reportError("Invalid dynamic string table reference");
966 return Ret;
1099 return StringRef(DynamicStringTable.data() + Value);
9671100 }
9681101
9691102 template
10241157 OS << Value << " (bytes)";
10251158 break;
10261159 case DT_NEEDED:
1027 OS << "SharedLibrary (" << getDynamicString(*Obj, Value) << ")";
1160 OS << "SharedLibrary (" << getDynamicString(Value) << ")";
10281161 break;
10291162 case DT_SONAME:
1030 OS << "LibrarySoname (" << getDynamicString(*Obj, Value) << ")";
1163 OS << "LibrarySoname (" << getDynamicString(Value) << ")";
10311164 break;
10321165 case DT_RPATH:
10331166 case DT_RUNPATH:
1034 OS << getDynamicString(*Obj, Value);
1167 OS << getDynamicString(Value);
10351168 break;
10361169 case DT_MIPS_FLAGS:
10371170 printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS);
10661199
10671200 template
10681201 void ELFDumper::printDynamicTable() {
1069 auto I = Obj->dynamic_table_begin();
1070 auto E = Obj->dynamic_table_end();
1202 auto I = dynamic_table_begin();
1203 auto E = dynamic_table_end();
10711204
10721205 if (I == E)
10731206 return;
11121245 typedef std::vector LibsTy;
11131246 LibsTy Libs;
11141247
1115 for (const auto &Entry : Obj->dynamic_table())
1248 for (const auto &Entry : dynamic_table())
11161249 if (Entry.d_tag == ELF::DT_NEEDED)
1117 Libs.push_back(getDynamicString(*Obj, Entry.d_un.d_val));
1250 Libs.push_back(getDynamicString(Entry.d_un.d_val));
11181251
11191252 std::stable_sort(Libs.begin(), Libs.end());
11201253
11451278 template
11461279 void ELFDumper::printHashTable() {
11471280 DictScope D(W, "HashTable");
1148 auto HT = Obj->getHashTable();
1149 if (!HT)
1150 return;
1151 W.printNumber("Num Buckets", HT->nbucket);
1152 W.printNumber("Num Chains", HT->nchain);
1153 W.printList("Buckets", HT->buckets());
1154 W.printList("Chains", HT->chains());
1281 if (!HashTable)
1282 return;
1283 W.printNumber("Num Buckets", HashTable->nbucket);
1284 W.printNumber("Num Chains", HashTable->nchain);
1285 W.printList("Buckets", HashTable->buckets());
1286 W.printList("Chains", HashTable->chains());
11551287 }
11561288
11571289 template void ELFDumper::printLoadName() {
1158 outs() << "LoadName: " << Obj->getLoadName() << '\n';
1290 outs() << "LoadName: " << SOName << '\n';
11591291 }
11601292
11611293 template
12001332 typedef object::ELFFile ObjectFile;
12011333 typedef typename ObjectFile::Elf_Shdr Elf_Shdr;
12021334 typedef typename ObjectFile::Elf_Sym Elf_Sym;
1203
1204 MipsGOTParser(const ObjectFile *Obj, StreamWriter &W);
1335 typedef typename ObjectFile::Elf_Dyn_Range Elf_Dyn_Range;
1336
1337 MipsGOTParser(const ObjectFile *Obj, Elf_Dyn_Range DynTable, StreamWriter &W);
12051338
12061339 void parseGOT();
12071340 void parsePLT();
12341367 }
12351368
12361369 template
1237 MipsGOTParser::MipsGOTParser(const ObjectFile *Obj, StreamWriter &W)
1370 MipsGOTParser::MipsGOTParser(const ObjectFile *Obj,
1371 Elf_Dyn_Range DynTable, StreamWriter &W)
12381372 : Obj(Obj), W(W) {
1239 for (const auto &Entry : Obj->dynamic_table()) {
1373 for (const auto &Entry : DynTable) {
12401374 switch (Entry.getTag()) {
12411375 case ELF::DT_PLTGOT:
12421376 DtPltGot = Entry.getVal();
15021636 return;
15031637 }
15041638
1505 MipsGOTParser GOTParser(Obj, W);
1639 MipsGOTParser GOTParser(Obj, dynamic_table(), W);
15061640 GOTParser.parseGOT();
15071641 GOTParser.parsePLT();
15081642 }