llvm.org GIT mirror llvm / 7a9b28a
[llvm-readobj] Impl GNU style program headers print readelf -lW Differential Revision: http://reviews.llvm.org/D18372 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@264415 91177308-0d34-0410-b5e6-96231b3b80d8 Hemant Kulkarni 4 years ago
4 changed file(s) with 304 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
0 #Source :
1 #__thread int a = 1;
2 #__thread int b;
3 #
4 #int main () {
5 # b = 2;
6 # throw (a + b) ;
7 # return 0;
8 #}
9 # compiled as clang++ source.cpp
10 # and clang++ -m32 source.cpp
11
12 RUN: llvm-readobj -program-headers %p/Inputs/phdrs-elf.exe-i386 --elf-output-style=GNU \
13 RUN: | FileCheck %s -check-prefix ELF32
14 RUN: llvm-readobj -program-headers %p/Inputs/phdrs-elf.exe-x86_64 \
15 RUN: --elf-output-style=GNU | FileCheck %s -check-prefix ELF64
16
17 ELF32: Elf file type is EXEC (Executable file)
18 ELF32-NEXT: Entry point 0x8048460
19 ELF32-NEXT: There are 10 program headers, starting at offset 52
20
21 ELF32: Program Headers:
22 ELF32-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
23 ELF32-NEXT: PHDR 0x000034 0x08048034 0x08048034 0x00140 0x00140 R E 0x4
24 ELF32-NEXT: INTERP 0x000174 0x08048174 0x08048174 0x00013 0x00013 R 0x1
25 ELF32-NEXT: [Requesting program interpreter: /lib/ld-linux.so.2]
26 ELF32-NEXT: LOAD 0x000000 0x08048000 0x08048000 0x006d0 0x006d0 R E 0x1000
27 ELF32-NEXT: LOAD 0x000ef0 0x08049ef0 0x08049ef0 0x00128 0x00140 RW 0x1000
28 ELF32-NEXT: DYNAMIC 0x000f08 0x08049f08 0x08049f08 0x000e8 0x000e8 RW 0x4
29 ELF32-NEXT: NOTE 0x000188 0x08048188 0x08048188 0x00044 0x00044 R 0x4
30 ELF32-NEXT: TLS 0x000ef0 0x08049ef0 0x08049ef0 0x00004 0x00008 R 0x4
31 ELF32-NEXT: GNU_EH_FRAME 0x000640 0x08048640 0x08048640 0x0001c 0x0001c R 0x4
32 ELF32-NEXT: GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
33 ELF32-NEXT: GNU_RELRO 0x000ef0 0x08049ef0 0x08049ef0 0x00110 0x00110 R 0x1
34
35 ELF32: Section to Segment mapping:
36 ELF32-NEXT: Segment Sections...
37 ELF32-NEXT: 00
38 ELF32-NEXT: 01 .interp
39 ELF32-NEXT: 02 .interp .note.ABI-tag .note.gnu.build-id .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
40 ELF32-NEXT: 03 .tdata .ctors .dtors .jcr .dynamic .got .got.plt .data .bss
41 ELF32-NEXT: 04 .dynamic
42 ELF32-NEXT: 05 .note.ABI-tag .note.gnu.build-id
43 ELF32-NEXT: 06 .tdata .tbss
44 ELF32-NEXT: 07 .eh_frame_hdr
45 ELF32-NEXT: 08
46 ELF32-NEXT: 09 .tdata .ctors .dtors .jcr .dynamic .got
47
48 ELF64: Elf file type is EXEC (Executable file)
49 ELF64-NEXT: Entry point 0x400610
50 ELF64-NEXT: There are 10 program headers, starting at offset 64
51
52 ELF64: Program Headers:
53 ELF64-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
54 ELF64-NEXT: PHDR 0x000040 0x0000000000400040 0x0000000000400040 0x000230 0x000230 R E 0x8
55 ELF64-NEXT: INTERP 0x000270 0x0000000000400270 0x0000000000400270 0x00001c 0x00001c R 0x1
56 ELF64-NEXT: [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
57 ELF64-NEXT: LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x000924 0x000924 R E 0x200000
58 ELF64-NEXT: LOAD 0x000db4 0x0000000000600db4 0x0000000000600db4 0x000274 0x0002a4 RW 0x200000
59 ELF64-NEXT: DYNAMIC 0x000dd0 0x0000000000600dd0 0x0000000000600dd0 0x000210 0x000210 RW 0x8
60 ELF64-NEXT: NOTE 0x00028c 0x000000000040028c 0x000000000040028c 0x000044 0x000044 R 0x4
61 ELF64-NEXT: TLS 0x000db4 0x0000000000600db4 0x0000000000600db4 0x000004 0x000008 R 0x4
62 ELF64-NEXT: GNU_EH_FRAME 0x00083c 0x000000000040083c 0x000000000040083c 0x00002c 0x00002c R 0x4
63 ELF64-NEXT: GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x8
64 ELF64-NEXT: GNU_RELRO 0x000db4 0x0000000000600db4 0x0000000000600db4 0x00024c 0x00024c R 0x1
65
66 ELF64: Section to Segment mapping:
67 ELF64-NEXT: Segment Sections...
68 ELF64-NEXT: 00
69 ELF64-NEXT: 01 .interp
70 ELF64-NEXT: 02 .interp .note.ABI-tag .note.gnu.build-id .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
71 ELF64-NEXT: 03 .tdata .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
72 ELF64-NEXT: 04 .dynamic
73 ELF64-NEXT: 05 .note.ABI-tag .note.gnu.build-id
74 ELF64-NEXT: 06 .tdata .tbss
75 ELF64-NEXT: 07 .eh_frame_hdr
76 ELF64-NEXT: 08
77 ELF64-NEXT: 09 .tdata .init_array .fini_array .jcr .dynamic .got
278278 virtual void printSymbol(const ELFFile *Obj, const Elf_Sym *Symbol,
279279 const Elf_Sym *FirstSym, StringRef StrTable,
280280 bool IsDynamic) = 0;
281 virtual void printProgramHeaders(const ELFFile *Obj) = 0;
281282 const ELFDumper *dumper() const { return Dumper; }
282283 private:
283284 const ELFDumper *Dumper;
298299 void printDynamicRelocations(const ELFO *Obj) override;
299300 virtual void printSymtabMessage(const ELFO *Obj, StringRef Name,
300301 size_t Offset) override;
302 void printProgramHeaders(const ELFO *Obj) override;
301303
302304 private:
303305 struct Field {
328330 StringRef StrTable, bool IsDynamic) override;
329331 std::string getSymbolSectionNdx(const ELFO *Obj, const Elf_Sym *Symbol,
330332 const Elf_Sym *FirstSym);
333 bool checkTLSSections(const Elf_Phdr &Phdr, const Elf_Shdr &Sec);
334 bool checkoffsets(const Elf_Phdr &Phdr, const Elf_Shdr &Sec);
335 bool checkVMA(const Elf_Phdr &Phdr, const Elf_Shdr &Sec);
336 bool checkPTDynamic(const Elf_Phdr &Phdr, const Elf_Shdr &Sec);
331337 };
332338
333339 template class LLVMStyle : public DumpStyle {
344350 void printSymbols(const ELFO *Obj) override;
345351 void printDynamicSymbols(const ELFO *Obj) override;
346352 void printDynamicRelocations(const ELFO *Obj) override;
353 void printProgramHeaders(const ELFO *Obj) override;
347354
348355 private:
349356 void printRelocation(const ELFO *Obj, Elf_Rela Rel, const Elf_Shdr *SymTab);
10751082 }
10761083 }
10771084
1085 static std::string getElfPtType(unsigned Arch, unsigned Type) {
1086 switch (Type) {
1087 case ELF::PT_NULL:
1088 return "NULL";
1089 case ELF::PT_LOAD:
1090 return "LOAD";
1091 case ELF::PT_DYNAMIC:
1092 return "DYNAMIC";
1093 case ELF::PT_INTERP:
1094 return "INTERP";
1095 case ELF::PT_NOTE:
1096 return "NOTE";
1097 case ELF::PT_SHLIB:
1098 return "SHLIB";
1099 case ELF::PT_PHDR:
1100 return "PHDR";
1101 case ELF::PT_TLS:
1102 return "TLS";
1103 case ELF::PT_GNU_EH_FRAME:
1104 return "GNU_EH_FRAME";
1105 case ELF::PT_SUNW_UNWIND:
1106 return "SUNW_UNWIND";
1107 case ELF::PT_GNU_STACK:
1108 return "GNU_STACK";
1109 case ELF::PT_GNU_RELRO:
1110 return "GNU_RELRO";
1111 default:
1112 // All machine specific PT_* types
1113 switch (Arch) {
1114 case ELF::EM_AMDGPU:
1115 switch (Type) {
1116 LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM);
1117 LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_AGENT);
1118 LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_READONLY_AGENT);
1119 LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_CODE_AGENT);
1120 }
1121 return "";
1122 case ELF::EM_ARM:
1123 if (Type == ELF::PT_ARM_EXIDX)
1124 return "EXIDX";
1125 return "";
1126 case ELF::EM_MIPS:
1127 case ELF::EM_MIPS_RS3_LE:
1128 switch (Type) {
1129 case PT_MIPS_REGINFO:
1130 return "REGINFO";
1131 case PT_MIPS_RTPROC:
1132 return "RTPROC";
1133 case PT_MIPS_OPTIONS:
1134 return "OPTIONS";
1135 case PT_MIPS_ABIFLAGS:
1136 return "ABIFLAGS";
1137 }
1138 return "";
1139 }
1140 }
1141 return std::string(": ") + to_string(format_hex(Type, 1));
1142 }
1143
10781144 static const EnumEntry ElfSegmentFlags[] = {
10791145 LLVM_READOBJ_ENUM_ENT(ELF, PF_X),
10801146 LLVM_READOBJ_ENUM_ENT(ELF, PF_W),
13121378 ELFDumperStyle->printRelocations(Obj);
13131379 }
13141380
1381 template void ELFDumper::printProgramHeaders() {
1382 ELFDumperStyle->printProgramHeaders(Obj);
1383 }
1384
13151385 template void ELFDumper::printDynamicRelocations() {
13161386 ELFDumperStyle->printDynamicRelocations(Obj);
13171387 }
1318
13191388
13201389 template
13211390 void ELFDumper::printSymbols() {
13261395 void ELFDumper::printDynamicSymbols() {
13271396 ELFDumperStyle->printDynamicSymbols(Obj);
13281397 }
1329
13301398
13311399 #define LLVM_READOBJ_TYPE_CASE(name) \
13321400 case DT_##name: return #name
16411709 }
16421710 }
16431711
1644 template
1645 void ELFDumper::printProgramHeaders() {
1646 ListScope L(W, "ProgramHeaders");
1647
1648 for (const Elf_Phdr &Phdr : Obj->program_headers()) {
1649 DictScope P(W, "ProgramHeader");
1650 W.printHex("Type",
1651 getElfSegmentType(Obj->getHeader()->e_machine, Phdr.p_type),
1652 Phdr.p_type);
1653 W.printHex("Offset", Phdr.p_offset);
1654 W.printHex("VirtualAddress", Phdr.p_vaddr);
1655 W.printHex("PhysicalAddress", Phdr.p_paddr);
1656 W.printNumber("FileSize", Phdr.p_filesz);
1657 W.printNumber("MemSize", Phdr.p_memsz);
1658 W.printFlags("Flags", Phdr.p_flags, makeArrayRef(ElfSegmentFlags));
1659 W.printNumber("Alignment", Phdr.p_align);
1660 }
1661 }
16621712
16631713 template
16641714 void ELFDumper::printHashTable() {
26472697 this->dumper()->printSymbolsHelper(true);
26482698 }
26492699
2700 static inline std::string printPhdrFlags(unsigned Flag) {
2701 std::string Str;
2702 Str = (Flag & PF_R) ? "R" : " ";
2703 Str += (Flag & PF_W) ? "W" : " ";
2704 Str += (Flag & PF_X) ? "E" : " ";
2705 return Str;
2706 }
2707
2708 // SHF_TLS sections are only in PT_TLS, PT_LOAD or PT_GNU_RELRO
2709 // PT_TLS must only have SHF_TLS sections
2710 template
2711 bool GNUStyle::checkTLSSections(const Elf_Phdr &Phdr,
2712 const Elf_Shdr &Sec) {
2713 return (((Sec.sh_flags & ELF::SHF_TLS) &&
2714 ((Phdr.p_type == ELF::PT_TLS) || (Phdr.p_type == ELF::PT_LOAD) ||
2715 (Phdr.p_type == ELF::PT_GNU_RELRO))) ||
2716 (!(Sec.sh_flags & ELF::SHF_TLS) && Phdr.p_type != ELF::PT_TLS));
2717 }
2718
2719 // Non-SHT_NOBITS must have its offset inside the segment
2720 // Only non-zero section can be at end of segment
2721 template
2722 bool GNUStyle::checkoffsets(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) {
2723 if (Sec.sh_type == ELF::SHT_NOBITS)
2724 return true;
2725 bool IsSpecial =
2726 (Sec.sh_type == ELF::SHT_NOBITS) && ((Sec.sh_flags & ELF::SHF_TLS) != 0);
2727 // .tbss is special, it only has memory in PT_TLS and has NOBITS properties
2728 auto SectionSize =
2729 (IsSpecial && Phdr.p_type != ELF::PT_TLS) ? 0 : Sec.sh_size;
2730 if (Sec.sh_offset >= Phdr.p_offset)
2731 return ((Sec.sh_offset + SectionSize <= Phdr.p_filesz + Phdr.p_offset)
2732 /*only non-zero sized sections at end*/ &&
2733 (Sec.sh_offset + 1 <= Phdr.p_offset + Phdr.p_filesz));
2734 return false;
2735 }
2736
2737 // SHF_ALLOC must have VMA inside segment
2738 // Only non-zero section can be at end of segment
2739 template
2740 bool GNUStyle::checkVMA(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) {
2741 if (!(Sec.sh_flags & ELF::SHF_ALLOC))
2742 return true;
2743 bool IsSpecial =
2744 (Sec.sh_type == ELF::SHT_NOBITS) && ((Sec.sh_flags & ELF::SHF_TLS) != 0);
2745 // .tbss is special, it only has memory in PT_TLS and has NOBITS properties
2746 auto SectionSize =
2747 (IsSpecial && Phdr.p_type != ELF::PT_TLS) ? 0 : Sec.sh_size;
2748 if (Sec.sh_addr >= Phdr.p_vaddr)
2749 return ((Sec.sh_addr + SectionSize <= Phdr.p_vaddr + Phdr.p_memsz) &&
2750 (Sec.sh_addr + 1 <= Phdr.p_vaddr + Phdr.p_memsz));
2751 return false;
2752 }
2753
2754 // No section with zero size must be at start or end of PT_DYNAMIC
2755 template
2756 bool GNUStyle::checkPTDynamic(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) {
2757 if (Phdr.p_type != ELF::PT_DYNAMIC || Sec.sh_size != 0 || Phdr.p_memsz == 0)
2758 return true;
2759 // Is section within the phdr both based on offset and VMA ?
2760 return ((Sec.sh_type == ELF::SHT_NOBITS) ||
2761 (Sec.sh_offset > Phdr.p_offset &&
2762 Sec.sh_offset < Phdr.p_offset + Phdr.p_filesz)) &&
2763 (!(Sec.sh_flags & ELF::SHF_ALLOC) ||
2764 (Sec.sh_addr > Phdr.p_vaddr && Sec.sh_addr < Phdr.p_memsz));
2765 }
2766
2767 template
2768 void GNUStyle::printProgramHeaders(const ELFO *Obj) {
2769 int Bias = (ELFT::Is64Bits) ? 8 : 0;
2770 unsigned Width = (ELFT::Is64Bits) ? 18 : 10;
2771 unsigned SizeWidth = (ELFT::Is64Bits) ? 8 : 7;
2772 std::string Type, Offset, VMA, LMA, FileSz, MemSz, Flag, Align;
2773
2774 const Elf_Ehdr *Header = Obj->getHeader();
2775 Field Fields[8] = {2, 17, 26, 37 + Bias,
2776 48 + Bias, 56 + Bias, 64 + Bias, 68 + Bias};
2777 OS << "\nElf file type is "
2778 << printEnum(Header->e_type, makeArrayRef(ElfObjectFileType)) << "\n"
2779 << "Entry point " << format_hex(Header->e_entry, 1) << "\n"
2780 << "There are " << Header->e_phnum << " program headers,"
2781 << " starting at offset " << Header->e_phoff << "\n\n"
2782 << "Program Headers:\n";
2783 if (ELFT::Is64Bits)
2784 OS << " Type Offset VirtAddr PhysAddr "
2785 << " FileSiz MemSiz Flg Align\n";
2786 else
2787 OS << " Type Offset VirtAddr PhysAddr FileSiz "
2788 << "MemSiz Flg Align\n";
2789 for (const auto &Phdr : Obj->program_headers()) {
2790 Type = getElfPtType(Header->e_machine, Phdr.p_type);
2791 Offset = to_string(format_hex(Phdr.p_offset, 8));
2792 VMA = to_string(format_hex(Phdr.p_vaddr, Width));
2793 LMA = to_string(format_hex(Phdr.p_paddr, Width));
2794 FileSz = to_string(format_hex(Phdr.p_filesz, SizeWidth));
2795 MemSz = to_string(format_hex(Phdr.p_memsz, SizeWidth));
2796 Flag = printPhdrFlags(Phdr.p_flags);
2797 Align = to_string(format_hex(Phdr.p_align, 1));
2798 Fields[0].Str = Type;
2799 Fields[1].Str = Offset;
2800 Fields[2].Str = VMA;
2801 Fields[3].Str = LMA;
2802 Fields[4].Str = FileSz;
2803 Fields[5].Str = MemSz;
2804 Fields[6].Str = Flag;
2805 Fields[7].Str = Align;
2806 for (auto Field : Fields)
2807 printField(Field);
2808 if (Phdr.p_type == ELF::PT_INTERP) {
2809 OS << "\n [Requesting program interpreter: ";
2810 OS << reinterpret_cast(Obj->base()) + Phdr.p_offset << "]";
2811 }
2812 OS << "\n";
2813 }
2814 OS << "\n Section to Segment mapping:\n Segment Sections...\n";
2815 int Phnum = 0;
2816 for (const Elf_Phdr &Phdr : Obj->program_headers()) {
2817 std::string Sections;
2818 OS << format(" %2.2d ", Phnum++);
2819 for (const Elf_Shdr &Sec : Obj->sections()) {
2820 // Check if each section is in a segment and then print mapping.
2821 // readelf additionally makes sure it does not print zero sized sections
2822 // at end of segments and for PT_DYNAMIC both start and end of section
2823 // .tbss must only be shown in PT_TLS section.
2824 bool TbssInNonTLS = (Sec.sh_type == ELF::SHT_NOBITS) &&
2825 ((Sec.sh_flags & ELF::SHF_TLS) != 0) &&
2826 Phdr.p_type != ELF::PT_TLS;
2827 if (!TbssInNonTLS && checkTLSSections(Phdr, Sec) &&
2828 checkoffsets(Phdr, Sec) && checkVMA(Phdr, Sec) &&
2829 checkPTDynamic(Phdr, Sec) && (Sec.sh_type != ELF::SHT_NULL))
2830 Sections += unwrapOrError(Obj->getSectionName(&Sec)).str() + " ";
2831 }
2832 OS << Sections << "\n";
2833 OS.flush();
2834 }
2835 }
2836
26502837 template
26512838 void GNUStyle::printDynamicRelocations(const ELFO *Obj) {
26522839 OS << "GNU style dynamic relocations not implemented!\n";
29943181 << W.hex(Rel.r_addend) << "\n";
29953182 }
29963183 }
3184
3185 template
3186 void LLVMStyle::printProgramHeaders(const ELFO *Obj) {
3187 ListScope L(W, "ProgramHeaders");
3188
3189 for (const Elf_Phdr &Phdr : Obj->program_headers()) {
3190 DictScope P(W, "ProgramHeader");
3191 W.printHex("Type",
3192 getElfSegmentType(Obj->getHeader()->e_machine, Phdr.p_type),
3193 Phdr.p_type);
3194 W.printHex("Offset", Phdr.p_offset);
3195 W.printHex("VirtualAddress", Phdr.p_vaddr);
3196 W.printHex("PhysicalAddress", Phdr.p_paddr);
3197 W.printNumber("FileSize", Phdr.p_filesz);
3198 W.printNumber("MemSize", Phdr.p_memsz);
3199 W.printFlags("Flags", Phdr.p_flags, makeArrayRef(ElfSegmentFlags));
3200 W.printNumber("Alignment", Phdr.p_align);
3201 }
3202 }