llvm.org GIT mirror llvm / e7726ca
[yaml2obj][ELF] Add support for program headers This change adds basic support for program headers. I need to do some testing which requires generating program headers but I can't use ld.lld or clang to produce programs that have headers. I'd also like to test some strange things that those programs may never produce. Patch by Jake Ehrlich Differential Revision: https://reviews.llvm.org/D35276 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@308520 91177308-0d34-0410-b5e6-96231b3b80d8 Petr Hosek 2 years ago
5 changed file(s) with 270 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
3636 // In the future, these would probably be better suited by C++11 enum
3737 // class's with appropriate fixed underlying type.
3838 LLVM_YAML_STRONG_TYPEDEF(uint16_t, ELF_ET)
39 LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_PT)
3940 LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_EM)
4041 LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFCLASS)
4142 LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFDATA)
4243 LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI)
4344 // Just use 64, since it can hold 32-bit values too.
4445 LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF)
46 LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_PF)
4547 LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT)
4648 LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL)
4749 LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_RSS)
6870 ELF_EM Machine;
6971 ELF_EF Flags;
7072 llvm::yaml::Hex64 Entry;
73 };
74
75 struct SectionName {
76 StringRef Section;
77 };
78
79 struct ProgramHeader {
80 ELF_PT Type;
81 ELF_PF Flags;
82 llvm::yaml::Hex64 VAddr;
83 llvm::yaml::Hex64 PAddr;
84 std::vector Sections;
7185 };
7286
7387 struct Symbol {
182196
183197 struct Object {
184198 FileHeader Header;
199 std::vector ProgramHeaders;
185200 std::vector> Sections;
186201 // Although in reality the symbols reside in a section, it is a lot
187202 // cleaner and nicer if we read them from the YAML as a separate
193208 } // end namespace ELFYAML
194209 } // end namespace llvm
195210
211 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader)
196212 LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr)
197213 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol)
198214 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation)
199215 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionOrType)
216 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionName)
200217
201218 namespace llvm {
202219 namespace yaml {
206223 static void enumeration(IO &IO, ELFYAML::ELF_ET &Value);
207224 };
208225
226 template <> struct ScalarEnumerationTraits {
227 static void enumeration(IO &IO, ELFYAML::ELF_PT &Value);
228 };
229
209230 template <>
210231 struct ScalarEnumerationTraits {
211232 static void enumeration(IO &IO, ELFYAML::ELF_EM &Value);
231252 static void bitset(IO &IO, ELFYAML::ELF_EF &Value);
232253 };
233254
255 template <> struct ScalarBitSetTraits {
256 static void bitset(IO &IO, ELFYAML::ELF_PF &Value);
257 };
258
234259 template <>
235260 struct ScalarEnumerationTraits {
236261 static void enumeration(IO &IO, ELFYAML::ELF_SHT &Value);
299324 template <>
300325 struct MappingTraits {
301326 static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr);
327 };
328
329 template <> struct MappingTraits {
330 static void mapping(IO &IO, ELFYAML::ProgramHeader &FileHdr);
302331 };
303332
304333 template <>
330359 static void mapping(IO &IO, ELFYAML::SectionOrType §ionOrType);
331360 };
332361
362 template <> struct MappingTraits {
363 static void mapping(IO &IO, ELFYAML::SectionName §ionName);
364 };
365
333366 } // end namespace yaml
334367 } // end namespace llvm
335368
3636 ECase(ET_CORE);
3737 #undef ECase
3838 IO.enumFallback(Value);
39 }
40
41 void ScalarEnumerationTraits::enumeration(
42 IO &IO, ELFYAML::ELF_PT &Value) {
43 #define ECase(X) IO.enumCase(Value, #X, ELF::X)
44 ECase(PT_NULL);
45 ECase(PT_LOAD);
46 ECase(PT_DYNAMIC);
47 ECase(PT_INTERP);
48 ECase(PT_NOTE);
49 ECase(PT_SHLIB);
50 ECase(PT_PHDR);
51 ECase(PT_TLS);
52 #undef ECase
53 IO.enumFallback(Value);
3954 }
4055
4156 void ScalarEnumerationTraits::enumeration(
411426 #undef ECase
412427 }
413428
429 void ScalarBitSetTraits::bitset(IO &IO,
430 ELFYAML::ELF_PF &Value) {
431 #define BCase(X) IO.bitSetCase(Value, #X, ELF::X)
432 BCase(PF_X);
433 BCase(PF_W);
434 BCase(PF_R);
435 }
436
414437 void ScalarBitSetTraits::bitset(IO &IO,
415438 ELFYAML::ELF_SHF &Value) {
416439 const auto *Object = static_cast(IO.getContext());
648671 IO.mapOptional("Entry", FileHdr.Entry, Hex64(0));
649672 }
650673
674 void MappingTraits::mapping(
675 IO &IO, ELFYAML::ProgramHeader &Phdr) {
676 IO.mapRequired("Type", Phdr.Type);
677 IO.mapOptional("Flags", Phdr.Flags, ELFYAML::ELF_PF(0));
678 IO.mapOptional("Sections", Phdr.Sections);
679 IO.mapOptional("VAddr", Phdr.VAddr, Hex64(0));
680 IO.mapOptional("PAddr", Phdr.PAddr, Hex64(0));
681 }
682
651683 namespace {
652684
653685 struct NormalizedOther {
717749 void MappingTraits::mapping(
718750 IO &IO, ELFYAML::SectionOrType §ionOrType) {
719751 IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType);
752 }
753
754 void MappingTraits::mapping(
755 IO &IO, ELFYAML::SectionName §ionName) {
756 IO.mapRequired("Section", sectionName.Section);
720757 }
721758
722759 static void sectionMapping(IO &IO, ELFYAML::MipsABIFlags &Section) {
836873 IO.setContext(&Object);
837874 IO.mapTag("!ELF", true);
838875 IO.mapRequired("FileHeader", Object.Header);
876 IO.mapOptional("ProgramHeaders", Object.ProgramHeaders);
839877 IO.mapOptional("Sections", Object.Sections);
840878 IO.mapOptional("Symbols", Object.Symbols);
841879 IO.setContext(nullptr);
0 # RUN: yaml2obj %s -o %t
1 # RUN: llvm-readobj -program-headers %t | FileCheck %s
2
3 !ELF
4 FileHeader:
5 Class: ELFCLASS64
6 Data: ELFDATA2LSB
7 Type: ET_EXEC
8 Machine: EM_X86_64
9 Sections:
10 - Name: .data
11 Type: SHT_PROGBITS
12 Flags: [ SHF_ALLOC ]
13 Content: "00000000"
14 - Name: .after
15 Type: SHT_NOBITS
16 Flags: [ SHF_ALLOC ]
17 Size: 64
18 ProgramHeaders:
19 - Type: PT_LOAD
20 Flags: [ PF_R ]
21 Sections:
22 - Section: .data
23 - Section: .after
24
25 #CHECK: ProgramHeaders [
26 #CHECK-NEXT: ProgramHeader {
27 #CHECK-NEXT: Type: PT_LOAD
28 #CHECK-NEXT: Offset:
29 #CHECK-NEXT: VirtualAddress:
30 #CHECK-NEXT: PhysicalAddress:
31 #CHECK-NEXT: FileSize: 4
32 #CHECK-NEXT: MemSize: 68
33 #CHECK-NEXT: Flags [
34 #CHECK-NEXT: PF_R
35 #CHECK-NEXT: ]
36 #CHECK-NEXT: Alignment:
37 #CHECK-NEXT: }
38 #CHECK-NEXT:]
0 # RUN: yaml2obj %s -o %t
1 # RUN: llvm-readobj -program-headers %t | FileCheck %s
2
3 !ELF
4 FileHeader:
5 Class: ELFCLASS64
6 Data: ELFDATA2LSB
7 Type: ET_EXEC
8 Machine: EM_X86_64
9 Sections:
10 - Name: .text
11 Type: SHT_PROGBITS
12 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
13 AddressAlign: 0x0000000000001000
14 Content: "00000000"
15 - Name: .init
16 Type: SHT_PROGBITS
17 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
18 Content: "00000000"
19 AddressAlign: 0x0000000000000010
20 - Name: .data
21 Type: SHT_PROGBITS
22 Flags: [ SHF_ALLOC ]
23 Content: "00000000"
24 AddressAlign: 0x0000000000001000
25 ProgramHeaders:
26 - Type: PT_LOAD
27 Flags: [ PF_X, PF_R ]
28 VAddr: 0xAAAA1000
29 PAddr: 0xFFFF1000
30 Sections:
31 - Section: .text
32 - Section: .init
33 - Type: PT_LOAD
34 Flags: [ PF_R ]
35 VAddr: 0xAAAA2000
36 PAddr: 0xFFFF2000
37 Sections:
38 - Section: .data
39
40 #CHECK: ProgramHeaders [
41 #CHECK-NEXT: ProgramHeader {
42 #CHECK-NEXT: Type: PT_LOAD
43 #CHECK-NEXT: Offset: 0x1000
44 #CHECK-NEXT: VirtualAddress: 0xAAAA1000
45 #CHECK-NEXT: PhysicalAddress: 0xFFFF1000
46 #CHECK-NEXT: FileSize: 20
47 #CHECK-NEXT: MemSize: 20
48 #CHECK-NEXT: Flags [
49 #CHECK-NEXT: PF_R
50 #CHECK-NEXT: PF_X
51 #CHECK-NEXT: ]
52 #CHECK-NEXT: Alignment: 4096
53 #CHECK-NEXT: }
54 #CHECK-NEXT: ProgramHeader {
55 #CHECK-NEXT: Type: PT_LOAD
56 #CHECK-NEXT: Offset: 0x2000
57 #CHECK-NEXT: VirtualAddress: 0xAAAA2000
58 #CHECK-NEXT: PhysicalAddress: 0xFFFF2000
59 #CHECK-NEXT: FileSize: 4
60 #CHECK-NEXT: MemSize: 4
61 #CHECK-NEXT: Flags [
62 #CHECK-NEXT: PF_R
63 #CHECK-NEXT: ]
64 #CHECK-NEXT: Alignment: 4096
65 #CHECK-NEXT: }
66 #CHECK-NEXT:]
9898 template
9999 class ELFState {
100100 typedef typename object::ELFFile::Elf_Ehdr Elf_Ehdr;
101 typedef typename object::ELFFile::Elf_Phdr Elf_Phdr;
101102 typedef typename object::ELFFile::Elf_Shdr Elf_Shdr;
102103 typedef typename object::ELFFile::Elf_Sym Elf_Sym;
103104 typedef typename object::ELFFile::Elf_Rel Elf_Rel;
117118 bool buildSymbolIndex(std::size_t &StartIndex,
118119 const std::vector &Symbols);
119120 void initELFHeader(Elf_Ehdr &Header);
121 void initProgramHeaders(std::vector &PHeaders);
120122 bool initSectionHeaders(std::vector &SHeaders,
121123 ContiguousBlobAccumulator &CBA);
122124 void initSymtabSectionHeader(Elf_Shdr &SHeader,
124126 void initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
125127 StringTableBuilder &STB,
126128 ContiguousBlobAccumulator &CBA);
129 void setProgramHeaderLayout(std::vector &PHeaders,
130 std::vector &SHeaders);
127131 void addSymbols(const std::vector &Symbols,
128132 std::vector &Syms, unsigned SymbolBinding);
129133 void writeSectionContent(Elf_Shdr &SHeader,
172176 Header.e_machine = Doc.Header.Machine;
173177 Header.e_version = EV_CURRENT;
174178 Header.e_entry = Doc.Header.Entry;
179 Header.e_phoff = sizeof(Header);
175180 Header.e_flags = Doc.Header.Flags;
176181 Header.e_ehsize = sizeof(Elf_Ehdr);
182 Header.e_phentsize = sizeof(Elf_Phdr);
183 Header.e_phnum = Doc.ProgramHeaders.size();
177184 Header.e_shentsize = sizeof(Elf_Shdr);
178 // Immediately following the ELF header.
179 Header.e_shoff = sizeof(Header);
185 // Immediately following the ELF header and program headers.
186 Header.e_shoff =
187 sizeof(Header) + sizeof(Elf_Phdr) * Doc.ProgramHeaders.size();
180188 Header.e_shnum = getSectionCount();
181189 Header.e_shstrndx = getDotShStrTabSecNo();
190 }
191
192 template
193 void ELFState::initProgramHeaders(std::vector &PHeaders) {
194 for (const auto &YamlPhdr : Doc.ProgramHeaders) {
195 Elf_Phdr Phdr;
196 Phdr.p_type = YamlPhdr.Type;
197 Phdr.p_flags = YamlPhdr.Flags;
198 Phdr.p_vaddr = YamlPhdr.VAddr;
199 Phdr.p_paddr = YamlPhdr.PAddr;
200 PHeaders.push_back(Phdr);
201 }
182202 }
183203
184204 template
310330 }
311331
312332 template
333 void ELFState::setProgramHeaderLayout(std::vector &PHeaders,
334 std::vector &SHeaders) {
335 uint32_t PhdrIdx = 0;
336 for (auto &YamlPhdr : Doc.ProgramHeaders) {
337 auto &PHeader = PHeaders[PhdrIdx++];
338
339 if (YamlPhdr.Sections.size())
340 PHeader.p_offset = UINT32_MAX;
341 else
342 PHeader.p_offset = 0;
343
344 // Find the minimum offset for the program header.
345 for (auto SecName : YamlPhdr.Sections) {
346 uint32_t Index = 0;
347 SN2I.lookup(SecName.Section, Index);
348 const auto &SHeader = SHeaders[Index];
349 PHeader.p_offset = std::min(PHeader.p_offset, SHeader.sh_offset);
350 }
351
352 // Find the maximum offset of the end of a section in order to set p_filesz.
353 PHeader.p_filesz = 0;
354 for (auto SecName : YamlPhdr.Sections) {
355 uint32_t Index = 0;
356 SN2I.lookup(SecName.Section, Index);
357 const auto &SHeader = SHeaders[Index];
358 uint64_t EndOfSection;
359 if (SHeader.sh_type == llvm::ELF::SHT_NOBITS)
360 EndOfSection = SHeader.sh_offset;
361 else
362 EndOfSection = SHeader.sh_offset + SHeader.sh_size;
363 uint64_t EndOfSegment = PHeader.p_offset + PHeader.p_filesz;
364 EndOfSegment = std::max(EndOfSegment, EndOfSection);
365 PHeader.p_filesz = EndOfSegment - PHeader.p_offset;
366 }
367
368 // Find the memory size by adding the size of sections at the end of the
369 // segment. These should be empty (size of zero) and NOBITS sections.
370 PHeader.p_memsz = PHeader.p_filesz;
371 for (auto SecName : YamlPhdr.Sections) {
372 uint32_t Index = 0;
373 SN2I.lookup(SecName.Section, Index);
374 const auto &SHeader = SHeaders[Index];
375 if (SHeader.sh_offset == PHeader.p_offset + PHeader.p_filesz)
376 PHeader.p_memsz += SHeader.sh_size;
377 }
378
379 // Set the alignment of the segment to be the same as the maximum alignment
380 // of the the sections with the same offset so that by default the segment
381 // has a valid and sensible alignment.
382 PHeader.p_align = 1;
383 for (auto SecName : YamlPhdr.Sections) {
384 uint32_t Index = 0;
385 SN2I.lookup(SecName.Section, Index);
386 const auto &SHeader = SHeaders[Index];
387 if (SHeader.sh_offset == PHeader.p_offset)
388 PHeader.p_align = std::max(PHeader.p_align, SHeader.sh_addralign);
389 }
390 }
391 }
392
393 template
313394 void ELFState::addSymbols(const std::vector &Symbols,
314395 std::vector &Syms,
315396 unsigned SymbolBinding) {
507588 State.initELFHeader(Header);
508589
509590 // TODO: Flesh out section header support.
510 // TODO: Program headers.
591
592 std::vector PHeaders;
593 State.initProgramHeaders(PHeaders);
511594
512595 // XXX: This offset is tightly coupled with the order that we write
513596 // things to `OS`.
514 const size_t SectionContentBeginOffset =
515 Header.e_ehsize + Header.e_shentsize * Header.e_shnum;
597 const size_t SectionContentBeginOffset = Header.e_ehsize +
598 Header.e_phentsize * Header.e_phnum +
599 Header.e_shentsize * Header.e_shnum;
516600 ContiguousBlobAccumulator CBA(SectionContentBeginOffset);
517601
518602 // Doc might not contain .symtab, .strtab and .shstrtab sections,
542626 CBA);
543627 SHeaders.push_back(ShStrTabSHeader);
544628
629 // Now we can decide segment offsets
630 State.setProgramHeaderLayout(PHeaders, SHeaders);
631
545632 OS.write((const char *)&Header, sizeof(Header));
633 writeArrayData(OS, makeArrayRef(PHeaders));
546634 writeArrayData(OS, makeArrayRef(SHeaders));
547635 CBA.writeBlobToStream(OS);
548636 return 0;