Skip to content

Commit eb04da3

Browse files
committed
[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 llvm-svn: 308520
1 parent 38b0f4a commit eb04da3

File tree

5 files changed

+270
-5
lines changed

5 files changed

+270
-5
lines changed

llvm/include/llvm/ObjectYAML/ELFYAML.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ namespace ELFYAML {
3737
// In the future, these would probably be better suited by C++11 enum
3838
// class's with appropriate fixed underlying type.
3939
LLVM_YAML_STRONG_TYPEDEF(uint16_t, ELF_ET)
40+
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_PT)
4041
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_EM)
4142
LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFCLASS)
4243
LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFDATA)
4344
LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI)
4445
// Just use 64, since it can hold 32-bit values too.
4546
LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF)
47+
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_PF)
4648
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT)
4749
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL)
4850
LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_RSS)
@@ -71,6 +73,18 @@ struct FileHeader {
7173
llvm::yaml::Hex64 Entry;
7274
};
7375

76+
struct SectionName {
77+
StringRef Section;
78+
};
79+
80+
struct ProgramHeader {
81+
ELF_PT Type;
82+
ELF_PF Flags;
83+
llvm::yaml::Hex64 VAddr;
84+
llvm::yaml::Hex64 PAddr;
85+
std::vector<SectionName> Sections;
86+
};
87+
7488
struct Symbol {
7589
StringRef Name;
7690
ELF_STT Type;
@@ -183,6 +197,7 @@ struct MipsABIFlags : Section {
183197

184198
struct Object {
185199
FileHeader Header;
200+
std::vector<ProgramHeader> ProgramHeaders;
186201
std::vector<std::unique_ptr<Section>> Sections;
187202
// Although in reality the symbols reside in a section, it is a lot
188203
// cleaner and nicer if we read them from the YAML as a separate
@@ -194,10 +209,12 @@ struct Object {
194209
} // end namespace ELFYAML
195210
} // end namespace llvm
196211

212+
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader)
197213
LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Section>)
198214
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol)
199215
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation)
200216
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionOrType)
217+
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionName)
201218

202219
namespace llvm {
203220
namespace yaml {
@@ -207,6 +224,10 @@ struct ScalarEnumerationTraits<ELFYAML::ELF_ET> {
207224
static void enumeration(IO &IO, ELFYAML::ELF_ET &Value);
208225
};
209226

227+
template <> struct ScalarEnumerationTraits<ELFYAML::ELF_PT> {
228+
static void enumeration(IO &IO, ELFYAML::ELF_PT &Value);
229+
};
230+
210231
template <>
211232
struct ScalarEnumerationTraits<ELFYAML::ELF_EM> {
212233
static void enumeration(IO &IO, ELFYAML::ELF_EM &Value);
@@ -232,6 +253,10 @@ struct ScalarBitSetTraits<ELFYAML::ELF_EF> {
232253
static void bitset(IO &IO, ELFYAML::ELF_EF &Value);
233254
};
234255

256+
template <> struct ScalarBitSetTraits<ELFYAML::ELF_PF> {
257+
static void bitset(IO &IO, ELFYAML::ELF_PF &Value);
258+
};
259+
235260
template <>
236261
struct ScalarEnumerationTraits<ELFYAML::ELF_SHT> {
237262
static void enumeration(IO &IO, ELFYAML::ELF_SHT &Value);
@@ -302,6 +327,10 @@ struct MappingTraits<ELFYAML::FileHeader> {
302327
static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr);
303328
};
304329

330+
template <> struct MappingTraits<ELFYAML::ProgramHeader> {
331+
static void mapping(IO &IO, ELFYAML::ProgramHeader &FileHdr);
332+
};
333+
305334
template <>
306335
struct MappingTraits<ELFYAML::Symbol> {
307336
static void mapping(IO &IO, ELFYAML::Symbol &Symbol);
@@ -331,6 +360,10 @@ template <> struct MappingTraits<ELFYAML::SectionOrType> {
331360
static void mapping(IO &IO, ELFYAML::SectionOrType &sectionOrType);
332361
};
333362

363+
template <> struct MappingTraits<ELFYAML::SectionName> {
364+
static void mapping(IO &IO, ELFYAML::SectionName &sectionName);
365+
};
366+
334367
} // end namespace yaml
335368
} // end namespace llvm
336369

llvm/lib/ObjectYAML/ELFYAML.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,21 @@ void ScalarEnumerationTraits<ELFYAML::ELF_ET>::enumeration(
3939
IO.enumFallback<Hex16>(Value);
4040
}
4141

42+
void ScalarEnumerationTraits<ELFYAML::ELF_PT>::enumeration(
43+
IO &IO, ELFYAML::ELF_PT &Value) {
44+
#define ECase(X) IO.enumCase(Value, #X, ELF::X)
45+
ECase(PT_NULL);
46+
ECase(PT_LOAD);
47+
ECase(PT_DYNAMIC);
48+
ECase(PT_INTERP);
49+
ECase(PT_NOTE);
50+
ECase(PT_SHLIB);
51+
ECase(PT_PHDR);
52+
ECase(PT_TLS);
53+
#undef ECase
54+
IO.enumFallback<Hex32>(Value);
55+
}
56+
4257
void ScalarEnumerationTraits<ELFYAML::ELF_EM>::enumeration(
4358
IO &IO, ELFYAML::ELF_EM &Value) {
4459
#define ECase(X) IO.enumCase(Value, #X, ELF::X)
@@ -412,6 +427,14 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration(
412427
#undef ECase
413428
}
414429

430+
void ScalarBitSetTraits<ELFYAML::ELF_PF>::bitset(IO &IO,
431+
ELFYAML::ELF_PF &Value) {
432+
#define BCase(X) IO.bitSetCase(Value, #X, ELF::X)
433+
BCase(PF_X);
434+
BCase(PF_W);
435+
BCase(PF_R);
436+
}
437+
415438
void ScalarBitSetTraits<ELFYAML::ELF_SHF>::bitset(IO &IO,
416439
ELFYAML::ELF_SHF &Value) {
417440
const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext());
@@ -649,6 +672,15 @@ void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO,
649672
IO.mapOptional("Entry", FileHdr.Entry, Hex64(0));
650673
}
651674

675+
void MappingTraits<ELFYAML::ProgramHeader>::mapping(
676+
IO &IO, ELFYAML::ProgramHeader &Phdr) {
677+
IO.mapRequired("Type", Phdr.Type);
678+
IO.mapOptional("Flags", Phdr.Flags, ELFYAML::ELF_PF(0));
679+
IO.mapOptional("Sections", Phdr.Sections);
680+
IO.mapOptional("VAddr", Phdr.VAddr, Hex64(0));
681+
IO.mapOptional("PAddr", Phdr.PAddr, Hex64(0));
682+
}
683+
652684
namespace {
653685

654686
struct NormalizedOther {
@@ -720,6 +752,11 @@ void MappingTraits<ELFYAML::SectionOrType>::mapping(
720752
IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType);
721753
}
722754

755+
void MappingTraits<ELFYAML::SectionName>::mapping(
756+
IO &IO, ELFYAML::SectionName &sectionName) {
757+
IO.mapRequired("Section", sectionName.Section);
758+
}
759+
723760
static void sectionMapping(IO &IO, ELFYAML::MipsABIFlags &Section) {
724761
commonSectionMapping(IO, Section);
725762
IO.mapOptional("Version", Section.Version, Hex16(0));
@@ -837,6 +874,7 @@ void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {
837874
IO.setContext(&Object);
838875
IO.mapTag("!ELF", true);
839876
IO.mapRequired("FileHeader", Object.Header);
877+
IO.mapOptional("ProgramHeaders", Object.ProgramHeaders);
840878
IO.mapOptional("Sections", Object.Sections);
841879
IO.mapOptional("Symbols", Object.Symbols);
842880
IO.setContext(nullptr);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# RUN: yaml2obj %s -o %t
2+
# RUN: llvm-readobj -program-headers %t | FileCheck %s
3+
4+
!ELF
5+
FileHeader:
6+
Class: ELFCLASS64
7+
Data: ELFDATA2LSB
8+
Type: ET_EXEC
9+
Machine: EM_X86_64
10+
Sections:
11+
- Name: .data
12+
Type: SHT_PROGBITS
13+
Flags: [ SHF_ALLOC ]
14+
Content: "00000000"
15+
- Name: .after
16+
Type: SHT_NOBITS
17+
Flags: [ SHF_ALLOC ]
18+
Size: 64
19+
ProgramHeaders:
20+
- Type: PT_LOAD
21+
Flags: [ PF_R ]
22+
Sections:
23+
- Section: .data
24+
- Section: .after
25+
26+
#CHECK: ProgramHeaders [
27+
#CHECK-NEXT: ProgramHeader {
28+
#CHECK-NEXT: Type: PT_LOAD
29+
#CHECK-NEXT: Offset:
30+
#CHECK-NEXT: VirtualAddress:
31+
#CHECK-NEXT: PhysicalAddress:
32+
#CHECK-NEXT: FileSize: 4
33+
#CHECK-NEXT: MemSize: 68
34+
#CHECK-NEXT: Flags [
35+
#CHECK-NEXT: PF_R
36+
#CHECK-NEXT: ]
37+
#CHECK-NEXT: Alignment:
38+
#CHECK-NEXT: }
39+
#CHECK-NEXT:]
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# RUN: yaml2obj %s -o %t
2+
# RUN: llvm-readobj -program-headers %t | FileCheck %s
3+
4+
!ELF
5+
FileHeader:
6+
Class: ELFCLASS64
7+
Data: ELFDATA2LSB
8+
Type: ET_EXEC
9+
Machine: EM_X86_64
10+
Sections:
11+
- Name: .text
12+
Type: SHT_PROGBITS
13+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
14+
AddressAlign: 0x0000000000001000
15+
Content: "00000000"
16+
- Name: .init
17+
Type: SHT_PROGBITS
18+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
19+
Content: "00000000"
20+
AddressAlign: 0x0000000000000010
21+
- Name: .data
22+
Type: SHT_PROGBITS
23+
Flags: [ SHF_ALLOC ]
24+
Content: "00000000"
25+
AddressAlign: 0x0000000000001000
26+
ProgramHeaders:
27+
- Type: PT_LOAD
28+
Flags: [ PF_X, PF_R ]
29+
VAddr: 0xAAAA1000
30+
PAddr: 0xFFFF1000
31+
Sections:
32+
- Section: .text
33+
- Section: .init
34+
- Type: PT_LOAD
35+
Flags: [ PF_R ]
36+
VAddr: 0xAAAA2000
37+
PAddr: 0xFFFF2000
38+
Sections:
39+
- Section: .data
40+
41+
#CHECK: ProgramHeaders [
42+
#CHECK-NEXT: ProgramHeader {
43+
#CHECK-NEXT: Type: PT_LOAD
44+
#CHECK-NEXT: Offset: 0x1000
45+
#CHECK-NEXT: VirtualAddress: 0xAAAA1000
46+
#CHECK-NEXT: PhysicalAddress: 0xFFFF1000
47+
#CHECK-NEXT: FileSize: 20
48+
#CHECK-NEXT: MemSize: 20
49+
#CHECK-NEXT: Flags [
50+
#CHECK-NEXT: PF_R
51+
#CHECK-NEXT: PF_X
52+
#CHECK-NEXT: ]
53+
#CHECK-NEXT: Alignment: 4096
54+
#CHECK-NEXT: }
55+
#CHECK-NEXT: ProgramHeader {
56+
#CHECK-NEXT: Type: PT_LOAD
57+
#CHECK-NEXT: Offset: 0x2000
58+
#CHECK-NEXT: VirtualAddress: 0xAAAA2000
59+
#CHECK-NEXT: PhysicalAddress: 0xFFFF2000
60+
#CHECK-NEXT: FileSize: 4
61+
#CHECK-NEXT: MemSize: 4
62+
#CHECK-NEXT: Flags [
63+
#CHECK-NEXT: PF_R
64+
#CHECK-NEXT: ]
65+
#CHECK-NEXT: Alignment: 4096
66+
#CHECK-NEXT: }
67+
#CHECK-NEXT:]

0 commit comments

Comments
 (0)