Skip to content

Commit 8011fc1

Browse files
author
Esme-Yi
committed
[yaml2obj] Enable support for parsing 64-bit XCOFF.
Summary: Add support for yaml2obj to parse 64-bit XCOFF. Reviewed By: shchenz Differential Revision: https://reviews.llvm.org/D100375
1 parent 5839976 commit 8011fc1

File tree

3 files changed

+221
-47
lines changed

3 files changed

+221
-47
lines changed

llvm/include/llvm/BinaryFormat/XCOFF.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,12 @@ namespace XCOFF {
2828
constexpr size_t FileNamePadSize = 6;
2929
constexpr size_t NameSize = 8;
3030
constexpr size_t FileHeaderSize32 = 20;
31+
constexpr size_t FileHeaderSize64 = 24;
3132
constexpr size_t SectionHeaderSize32 = 40;
33+
constexpr size_t SectionHeaderSize64 = 72;
3234
constexpr size_t SymbolTableEntrySize = 18;
3335
constexpr size_t RelocationSerializationSize32 = 10;
36+
constexpr size_t RelocationSerializationSize64 = 14;
3437
constexpr uint16_t RelocOverflow = 65535;
3538
constexpr uint8_t AllocRegNo = 31;
3639

llvm/lib/ObjectYAML/XCOFFEmitter.cpp

Lines changed: 82 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,18 @@ static void writeName(StringRef StrName, support::endian::Writer W) {
7575
}
7676

7777
bool XCOFFWriter::nameShouldBeInStringTable(StringRef SymbolName) {
78-
return SymbolName.size() > XCOFF::NameSize;
78+
// For XCOFF64: The symbol name is always in the string table.
79+
return (SymbolName.size() > XCOFF::NameSize) || Is64Bit;
7980
}
8081

8182
bool XCOFFWriter::initRelocations(uint64_t &CurrentOffset) {
8283
for (uint16_t I = 0, E = InitSections.size(); I < E; ++I) {
8384
if (!InitSections[I].Relocations.empty()) {
8485
InitSections[I].NumberOfRelocations = InitSections[I].Relocations.size();
8586
InitSections[I].FileOffsetToRelocations = CurrentOffset;
86-
CurrentOffset += InitSections[I].NumberOfRelocations *
87-
XCOFF::RelocationSerializationSize32;
87+
uint64_t RelSize = Is64Bit ? XCOFF::RelocationSerializationSize64
88+
: XCOFF::RelocationSerializationSize32;
89+
CurrentOffset += InitSections[I].NumberOfRelocations * RelSize;
8890
if (CurrentOffset > MaxRawDataSize) {
8991
ErrHandler("maximum object size of" + Twine(MaxRawDataSize) +
9092
"exceeded when writing relocation data");
@@ -170,9 +172,12 @@ bool XCOFFWriter::initFileHeader(uint64_t CurrentOffset) {
170172

171173
bool XCOFFWriter::assignAddressesAndIndices() {
172174
Strings.clear();
173-
uint64_t CurrentOffset =
174-
XCOFF::FileHeaderSize32 /* TODO: + auxiliaryHeaderSize() */ +
175-
InitSections.size() * XCOFF::SectionHeaderSize32;
175+
uint64_t FileHdrSize =
176+
Is64Bit ? XCOFF::FileHeaderSize64 : XCOFF::FileHeaderSize32;
177+
uint64_t SecHdrSize =
178+
Is64Bit ? XCOFF::SectionHeaderSize64 : XCOFF::SectionHeaderSize32;
179+
uint64_t CurrentOffset = FileHdrSize /* TODO: + auxiliaryHeaderSize() */ +
180+
InitSections.size() * SecHdrSize;
176181

177182
// Calculate section header info.
178183
if (!initSectionHeader(CurrentOffset))
@@ -186,14 +191,25 @@ void XCOFFWriter::writeFileHeader() {
186191
W.write<uint16_t>(Obj.Header.NumberOfSections ? Obj.Header.NumberOfSections
187192
: InitFileHdr.NumberOfSections);
188193
W.write<int32_t>(Obj.Header.TimeStamp);
189-
W.write<uint32_t>(Obj.Header.SymbolTableOffset
190-
? Obj.Header.SymbolTableOffset
191-
: InitFileHdr.SymbolTableOffset);
192-
W.write<int32_t>(Obj.Header.NumberOfSymTableEntries
193-
? Obj.Header.NumberOfSymTableEntries
194-
: InitFileHdr.NumberOfSymTableEntries);
195-
W.write<uint16_t>(Obj.Header.AuxHeaderSize);
196-
W.write<uint16_t>(Obj.Header.Flags);
194+
if (Is64Bit) {
195+
W.write<uint64_t>(Obj.Header.SymbolTableOffset
196+
? Obj.Header.SymbolTableOffset
197+
: InitFileHdr.SymbolTableOffset);
198+
W.write<uint16_t>(Obj.Header.AuxHeaderSize);
199+
W.write<uint16_t>(Obj.Header.Flags);
200+
W.write<int32_t>(Obj.Header.NumberOfSymTableEntries
201+
? Obj.Header.NumberOfSymTableEntries
202+
: InitFileHdr.NumberOfSymTableEntries);
203+
} else {
204+
W.write<uint32_t>(Obj.Header.SymbolTableOffset
205+
? Obj.Header.SymbolTableOffset
206+
: InitFileHdr.SymbolTableOffset);
207+
W.write<int32_t>(Obj.Header.NumberOfSymTableEntries
208+
? Obj.Header.NumberOfSymTableEntries
209+
: InitFileHdr.NumberOfSymTableEntries);
210+
W.write<uint16_t>(Obj.Header.AuxHeaderSize);
211+
W.write<uint16_t>(Obj.Header.Flags);
212+
}
197213
}
198214

199215
void XCOFFWriter::writeSectionHeader() {
@@ -202,22 +218,40 @@ void XCOFFWriter::writeSectionHeader() {
202218
XCOFFYAML::Section DerivedSec = InitSections[I];
203219
writeName(YamlSec.SectionName, W);
204220
// Virtual address is the same as physical address.
205-
uint32_t SectionAddress =
221+
uint64_t SectionAddress =
206222
YamlSec.Address ? YamlSec.Address : DerivedSec.Address;
207-
W.write<uint32_t>(SectionAddress); // Physical address
208-
W.write<uint32_t>(SectionAddress); // Virtual address
209-
W.write<uint32_t>(YamlSec.Size ? YamlSec.Size : DerivedSec.Size);
210-
W.write<uint32_t>(YamlSec.FileOffsetToData ? YamlSec.FileOffsetToData
211-
: DerivedSec.FileOffsetToData);
212-
W.write<uint32_t>(YamlSec.FileOffsetToRelocations
213-
? YamlSec.FileOffsetToRelocations
214-
: DerivedSec.FileOffsetToRelocations);
215-
W.write<uint32_t>(YamlSec.FileOffsetToLineNumbers);
216-
W.write<uint16_t>(YamlSec.NumberOfRelocations
217-
? YamlSec.NumberOfRelocations
218-
: DerivedSec.NumberOfRelocations);
219-
W.write<uint16_t>(YamlSec.NumberOfLineNumbers);
220-
W.write<int32_t>(YamlSec.Flags);
223+
if (Is64Bit) {
224+
W.write<uint64_t>(SectionAddress); // Physical address
225+
W.write<uint64_t>(SectionAddress); // Virtual address
226+
W.write<uint64_t>(YamlSec.Size ? YamlSec.Size : DerivedSec.Size);
227+
W.write<uint64_t>(YamlSec.FileOffsetToData ? YamlSec.FileOffsetToData
228+
: DerivedSec.FileOffsetToData);
229+
W.write<uint64_t>(YamlSec.FileOffsetToRelocations
230+
? YamlSec.FileOffsetToRelocations
231+
: DerivedSec.FileOffsetToRelocations);
232+
W.write<uint64_t>(YamlSec.FileOffsetToLineNumbers);
233+
W.write<uint32_t>(YamlSec.NumberOfRelocations
234+
? YamlSec.NumberOfRelocations
235+
: DerivedSec.NumberOfRelocations);
236+
W.write<uint32_t>(YamlSec.NumberOfLineNumbers);
237+
W.write<int32_t>(YamlSec.Flags);
238+
W.OS.write_zeros(4);
239+
} else {
240+
W.write<uint32_t>(SectionAddress); // Physical address
241+
W.write<uint32_t>(SectionAddress); // Virtual address
242+
W.write<uint32_t>(YamlSec.Size ? YamlSec.Size : DerivedSec.Size);
243+
W.write<uint32_t>(YamlSec.FileOffsetToData ? YamlSec.FileOffsetToData
244+
: DerivedSec.FileOffsetToData);
245+
W.write<uint32_t>(YamlSec.FileOffsetToRelocations
246+
? YamlSec.FileOffsetToRelocations
247+
: DerivedSec.FileOffsetToRelocations);
248+
W.write<uint32_t>(YamlSec.FileOffsetToLineNumbers);
249+
W.write<uint16_t>(YamlSec.NumberOfRelocations
250+
? YamlSec.NumberOfRelocations
251+
: DerivedSec.NumberOfRelocations);
252+
W.write<uint16_t>(YamlSec.NumberOfLineNumbers);
253+
W.write<int32_t>(YamlSec.Flags);
254+
}
221255
}
222256
}
223257

@@ -232,8 +266,7 @@ bool XCOFFWriter::writeSectionData() {
232266
ErrHandler("redundant data was written before section data");
233267
return false;
234268
}
235-
if (PaddingSize > 0)
236-
W.OS.write_zeros(PaddingSize);
269+
W.OS.write_zeros(PaddingSize);
237270
YamlSec.SectionData.writeAsBinary(W.OS);
238271
}
239272
}
@@ -250,10 +283,12 @@ bool XCOFFWriter::writeRelocations() {
250283
ErrHandler("redundant data was written before relocations");
251284
return false;
252285
}
253-
if (PaddingSize > 0)
254-
W.OS.write_zeros(PaddingSize);
286+
W.OS.write_zeros(PaddingSize);
255287
for (const XCOFFYAML::Relocation &YamlRel : YamlSec.Relocations) {
256-
W.write<uint32_t>(YamlRel.VirtualAddress);
288+
if (Is64Bit)
289+
W.write<uint64_t>(YamlRel.VirtualAddress);
290+
else
291+
W.write<uint32_t>(YamlRel.VirtualAddress);
257292
W.write<uint32_t>(YamlRel.SymbolIndex);
258293
W.write<uint8_t>(YamlRel.Info);
259294
W.write<uint8_t>(YamlRel.Type);
@@ -270,18 +305,22 @@ bool XCOFFWriter::writeSymbols() {
270305
ErrHandler("redundant data was written before symbols");
271306
return false;
272307
}
273-
if (PaddingSize > 0)
274-
W.OS.write_zeros(PaddingSize);
308+
W.OS.write_zeros(PaddingSize);
275309
for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
276-
if (nameShouldBeInStringTable(YamlSym.SymbolName)) {
277-
// For XCOFF32: A value of 0 indicates that the symbol name is in the
278-
// string table.
279-
W.write<int32_t>(0);
310+
if (Is64Bit) {
311+
W.write<uint64_t>(YamlSym.Value);
280312
W.write<uint32_t>(Strings.getOffset(YamlSym.SymbolName));
281313
} else {
282-
writeName(YamlSym.SymbolName, W);
314+
if (nameShouldBeInStringTable(YamlSym.SymbolName)) {
315+
// For XCOFF32: A value of 0 indicates that the symbol name is in the
316+
// string table.
317+
W.write<int32_t>(0);
318+
W.write<uint32_t>(Strings.getOffset(YamlSym.SymbolName));
319+
} else {
320+
writeName(YamlSym.SymbolName, W);
321+
}
322+
W.write<uint32_t>(YamlSym.Value);
283323
}
284-
W.write<uint32_t>(YamlSym.Value);
285324
W.write<int16_t>(
286325
YamlSym.SectionName.size() ? SectionIndexMap[YamlSym.SectionName] : 0);
287326
W.write<uint16_t>(YamlSym.Type);
@@ -295,17 +334,13 @@ bool XCOFFWriter::writeSymbols() {
295334
// length of each auxiliary entry is the same as a symbol table entry (18
296335
// bytes). The format and quantity of auxiliary entries depend on the
297336
// storage class (n_sclass) and type (n_type) of the symbol table entry.
298-
W.OS.write_zeros(18);
337+
W.OS.write_zeros(XCOFF::SymbolTableEntrySize);
299338
}
300339
}
301340
return true;
302341
}
303342

304343
bool XCOFFWriter::writeXCOFF() {
305-
if (Is64Bit) {
306-
ErrHandler("only XCOFF32 is currently supported");
307-
return false;
308-
}
309344
if (!assignAddressesAndIndices())
310345
return false;
311346
StartOffset = W.OS.tell();
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# RUN: yaml2obj %s -o %t
2+
# RUN: llvm-readobj --headers --symbols %t | \
3+
# RUN: FileCheck %s --check-prefix=CHECK64
4+
5+
--- !XCOFF
6+
FileHeader:
7+
MagicNumber: 0x01F7
8+
Sections:
9+
- Name: .text
10+
Flags: [ STYP_TEXT ]
11+
- Name: .data
12+
Flags: [ STYP_DATA ]
13+
SectionData: "0000000000000FC0"
14+
- Name: .bss
15+
Flags: [ STYP_BSS ]
16+
Relocations:
17+
- Type: 0x02
18+
- Name: .debug
19+
Address: 0x0
20+
Size: 0x60
21+
Flags: [ STYP_DEBUG, STYP_DATA ]
22+
SectionData: 01110103
23+
Symbols:
24+
- Name: .file
25+
Section: N_DEBUG
26+
- Name: .undef
27+
- Name: .abs
28+
Section: N_ABS
29+
- Name: .text
30+
Value: 0x0
31+
Section: .text
32+
Type: 0x0
33+
StorageClass: C_HIDEXT
34+
35+
# CHECK64: AddressSize: 64bit
36+
# CHECK64-NEXT: FileHeader {
37+
# CHECK64-NEXT: Magic: 0x1F7
38+
# CHECK64-NEXT: NumberOfSections: 4
39+
# CHECK64-NEXT: TimeStamp: None (0x0)
40+
# CHECK64-NEXT: SymbolTableOffset: 0x152
41+
# CHECK64-NEXT: SymbolTableEntries: 4
42+
# CHECK64-NEXT: OptionalHeaderSize: 0x0
43+
# CHECK64-NEXT: Flags: 0x0
44+
# CHECK64-NEXT: }
45+
# CHECK64-NEXT: Sections [
46+
# CHECK64-NEXT: Section {
47+
# CHECK64-NEXT: Index: 1
48+
# CHECK64-NEXT: Name: .text
49+
# CHECK64-NEXT: PhysicalAddress: 0x0
50+
# CHECK64-NEXT: VirtualAddress: 0x0
51+
# CHECK64-NEXT: Size: 0x0
52+
# CHECK64-NEXT: RawDataOffset: 0x0
53+
# CHECK64-NEXT: RelocationPointer: 0x0
54+
# CHECK64-NEXT: LineNumberPointer: 0x0
55+
# CHECK64-NEXT: NumberOfRelocations: 0
56+
# CHECK64-NEXT: NumberOfLineNumbers: 0
57+
# CHECK64-NEXT: Type: STYP_TEXT (0x20)
58+
# CHECK64-NEXT: }
59+
# CHECK64-NEXT: Section {
60+
# CHECK64-NEXT: Index: 2
61+
# CHECK64-NEXT: Name: .data
62+
# CHECK64-NEXT: PhysicalAddress: 0x0
63+
# CHECK64-NEXT: VirtualAddress: 0x0
64+
# CHECK64-NEXT: Size: 0x8
65+
# CHECK64-NEXT: RawDataOffset: 0x138
66+
# CHECK64-NEXT: RelocationPointer: 0x0
67+
# CHECK64-NEXT: LineNumberPointer: 0x0
68+
# CHECK64-NEXT: NumberOfRelocations: 0
69+
# CHECK64-NEXT: NumberOfLineNumbers: 0
70+
# CHECK64-NEXT: Type: STYP_DATA (0x40)
71+
# CHECK64-NEXT: }
72+
# CHECK64-NEXT: Section {
73+
# CHECK64-NEXT: Index: 3
74+
# CHECK64-NEXT: Name: .bss
75+
# CHECK64-NEXT: PhysicalAddress: 0x8
76+
# CHECK64-NEXT: VirtualAddress: 0x8
77+
# CHECK64-NEXT: Size: 0x0
78+
# CHECK64-NEXT: RawDataOffset: 0x0
79+
# CHECK64-NEXT: RelocationPointer: 0x144
80+
# CHECK64-NEXT: LineNumberPointer: 0x0
81+
# CHECK64-NEXT: NumberOfRelocations: 1
82+
# CHECK64-NEXT: NumberOfLineNumbers: 0
83+
# CHECK64-NEXT: Type: STYP_BSS (0x80)
84+
# CHECK64-NEXT: }
85+
# CHECK64-NEXT: Section {
86+
# CHECK64-NEXT: Index: 4
87+
# CHECK64-NEXT: Name: .debug
88+
# CHECK64-NEXT: PhysicalAddress: 0x0
89+
# CHECK64-NEXT: VirtualAddress: 0x0
90+
# CHECK64-NEXT: Size: 0x60
91+
# CHECK64-NEXT: RawDataOffset: 0x140
92+
# CHECK64-NEXT: RelocationPointer: 0x0
93+
# CHECK64-NEXT: LineNumberPointer: 0x0
94+
# CHECK64-NEXT: NumberOfRelocations: 0
95+
# CHECK64-NEXT: NumberOfLineNumbers: 0
96+
# CHECK64-NEXT: Type: 0x2040
97+
# CHECK64-NEXT: }
98+
# CHECK64-NEXT: ]
99+
# CHECK64-NEXT: Symbols [
100+
# CHECK64-NEXT: Symbol {
101+
# CHECK64-NEXT: Index: 0
102+
# CHECK64-NEXT: Name: .file
103+
# CHECK64-NEXT: Value: 0x0
104+
# CHECK64-NEXT: Section: N_DEBUG
105+
# CHECK64-NEXT: Type: 0x0
106+
# CHECK64-NEXT: StorageClass: C_NULL (0x0)
107+
# CHECK64-NEXT: NumberOfAuxEntries: 0
108+
# CHECK64-NEXT: }
109+
# CHECK64-NEXT: Symbol {
110+
# CHECK64-NEXT: Index: 1
111+
# CHECK64-NEXT: Name: .undef
112+
# CHECK64-NEXT: Value: 0x0
113+
# CHECK64-NEXT: Section: N_UNDEF
114+
# CHECK64-NEXT: Type: 0x0
115+
# CHECK64-NEXT: StorageClass: C_NULL (0x0)
116+
# CHECK64-NEXT: NumberOfAuxEntries: 0
117+
# CHECK64-NEXT: }
118+
# CHECK64-NEXT: Symbol {
119+
# CHECK64-NEXT: Index: 2
120+
# CHECK64-NEXT: Name: .abs
121+
# CHECK64-NEXT: Value: 0x0
122+
# CHECK64-NEXT: Section: N_ABS
123+
# CHECK64-NEXT: Type: 0x0
124+
# CHECK64-NEXT: StorageClass: C_NULL (0x0)
125+
# CHECK64-NEXT: NumberOfAuxEntries: 0
126+
# CHECK64-NEXT: }
127+
# CHECK64-NEXT: Symbol {
128+
# CHECK64-NEXT: Index: 3
129+
# CHECK64-NEXT: Name: .text
130+
# CHECK64-NEXT: Value (RelocatableAddress): 0x0
131+
# CHECK64-NEXT: Section: .text
132+
# CHECK64-NEXT: Type: 0x0
133+
# CHECK64-NEXT: StorageClass: C_HIDEXT (0x6B)
134+
# CHECK64-NEXT: NumberOfAuxEntries: 0
135+
# CHECK64-NEXT: }
136+
# CHECK64-NEXT: ]

0 commit comments

Comments
 (0)