1 //===-- lib/MC/XCOFFObjectWriter.cpp - XCOFF file writer ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements XCOFF object file writer information.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/BinaryFormat/XCOFF.h"
14 #include "llvm/MC/MCAsmBackend.h"
15 #include "llvm/MC/MCAsmLayout.h"
16 #include "llvm/MC/MCAssembler.h"
17 #include "llvm/MC/MCFixup.h"
18 #include "llvm/MC/MCFixupKindInfo.h"
19 #include "llvm/MC/MCObjectWriter.h"
20 #include "llvm/MC/MCSectionXCOFF.h"
21 #include "llvm/MC/MCSymbolXCOFF.h"
22 #include "llvm/MC/MCValue.h"
23 #include "llvm/MC/MCXCOFFObjectWriter.h"
24 #include "llvm/MC/StringTableBuilder.h"
25 #include "llvm/Support/Casting.h"
26 #include "llvm/Support/EndianStream.h"
27 #include "llvm/Support/ErrorHandling.h"
28 #include "llvm/Support/MathExtras.h"
29
30 #include <deque>
31
32 using namespace llvm;
33
34 // An XCOFF object file has a limited set of predefined sections. The most
35 // important ones for us (right now) are:
36 // .text --> contains program code and read-only data.
37 // .data --> contains initialized data, function descriptors, and the TOC.
38 // .bss --> contains uninitialized data.
39 // Each of these sections is composed of 'Control Sections'. A Control Section
40 // is more commonly referred to as a csect. A csect is an indivisible unit of
41 // code or data, and acts as a container for symbols. A csect is mapped
42 // into a section based on its storage-mapping class, with the exception of
43 // XMC_RW which gets mapped to either .data or .bss based on whether it's
44 // explicitly initialized or not.
45 //
46 // We don't represent the sections in the MC layer as there is nothing
47 // interesting about them at at that level: they carry information that is
48 // only relevant to the ObjectWriter, so we materialize them in this class.
49 namespace {
50
51 constexpr unsigned DefaultSectionAlign = 4;
52 constexpr int16_t MaxSectionIndex = INT16_MAX;
53
54 // Packs the csect's alignment and type into a byte.
55 uint8_t getEncodedType(const MCSectionXCOFF *);
56
57 struct XCOFFRelocation {
58 uint32_t SymbolTableIndex;
59 uint32_t FixupOffsetInCsect;
60 uint8_t SignAndSize;
61 uint8_t Type;
62 };
63
64 // Wrapper around an MCSymbolXCOFF.
65 struct Symbol {
66 const MCSymbolXCOFF *const MCSym;
67 uint32_t SymbolTableIndex;
68
getVisibilityType__anondfe4bda90111::Symbol69 XCOFF::VisibilityType getVisibilityType() const {
70 return MCSym->getVisibilityType();
71 }
72
getStorageClass__anondfe4bda90111::Symbol73 XCOFF::StorageClass getStorageClass() const {
74 return MCSym->getStorageClass();
75 }
getSymbolTableName__anondfe4bda90111::Symbol76 StringRef getSymbolTableName() const { return MCSym->getSymbolTableName(); }
Symbol__anondfe4bda90111::Symbol77 Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {}
78 };
79
80 // Wrapper for an MCSectionXCOFF.
81 // It can be a Csect or debug section or DWARF section and so on.
82 struct XCOFFSection {
83 const MCSectionXCOFF *const MCSec;
84 uint32_t SymbolTableIndex;
85 uint64_t Address;
86 uint64_t Size;
87
88 SmallVector<Symbol, 1> Syms;
89 SmallVector<XCOFFRelocation, 1> Relocations;
getSymbolTableName__anondfe4bda90111::XCOFFSection90 StringRef getSymbolTableName() const { return MCSec->getSymbolTableName(); }
getVisibilityType__anondfe4bda90111::XCOFFSection91 XCOFF::VisibilityType getVisibilityType() const {
92 return MCSec->getVisibilityType();
93 }
XCOFFSection__anondfe4bda90111::XCOFFSection94 XCOFFSection(const MCSectionXCOFF *MCSec)
95 : MCSec(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
96 };
97
98 // Type to be used for a container representing a set of csects with
99 // (approximately) the same storage mapping class. For example all the csects
100 // with a storage mapping class of `xmc_pr` will get placed into the same
101 // container.
102 using CsectGroup = std::deque<XCOFFSection>;
103 using CsectGroups = std::deque<CsectGroup *>;
104
105 // The basic section entry defination. This Section represents a section entry
106 // in XCOFF section header table.
107 struct SectionEntry {
108 char Name[XCOFF::NameSize];
109 // The physical/virtual address of the section. For an object file
110 // these values are equivalent.
111 uint64_t Address;
112 uint64_t Size;
113 uint64_t FileOffsetToData;
114 uint64_t FileOffsetToRelocations;
115 uint32_t RelocationCount;
116 int32_t Flags;
117
118 int16_t Index;
119
120 // XCOFF has special section numbers for symbols:
121 // -2 Specifies N_DEBUG, a special symbolic debugging symbol.
122 // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
123 // relocatable.
124 // 0 Specifies N_UNDEF, an undefined external symbol.
125 // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
126 // hasn't been initialized.
127 static constexpr int16_t UninitializedIndex =
128 XCOFF::ReservedSectionNum::N_DEBUG - 1;
129
SectionEntry__anondfe4bda90111::SectionEntry130 SectionEntry(StringRef N, int32_t Flags)
131 : Name(), Address(0), Size(0), FileOffsetToData(0),
132 FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags),
133 Index(UninitializedIndex) {
134 assert(N.size() <= XCOFF::NameSize && "section name too long");
135 memcpy(Name, N.data(), N.size());
136 }
137
reset__anondfe4bda90111::SectionEntry138 virtual void reset() {
139 Address = 0;
140 Size = 0;
141 FileOffsetToData = 0;
142 FileOffsetToRelocations = 0;
143 RelocationCount = 0;
144 Index = UninitializedIndex;
145 }
146
147 virtual ~SectionEntry() = default;
148 };
149
150 // Represents the data related to a section excluding the csects that make up
151 // the raw data of the section. The csects are stored separately as not all
152 // sections contain csects, and some sections contain csects which are better
153 // stored separately, e.g. the .data section containing read-write, descriptor,
154 // TOCBase and TOC-entry csects.
155 struct CsectSectionEntry : public SectionEntry {
156 // Virtual sections do not need storage allocated in the object file.
157 const bool IsVirtual;
158
159 // This is a section containing csect groups.
160 CsectGroups Groups;
161
CsectSectionEntry__anondfe4bda90111::CsectSectionEntry162 CsectSectionEntry(StringRef N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
163 CsectGroups Groups)
164 : SectionEntry(N, Flags), IsVirtual(IsVirtual), Groups(Groups) {
165 assert(N.size() <= XCOFF::NameSize && "section name too long");
166 memcpy(Name, N.data(), N.size());
167 }
168
reset__anondfe4bda90111::CsectSectionEntry169 void reset() override {
170 SectionEntry::reset();
171 // Clear any csects we have stored.
172 for (auto *Group : Groups)
173 Group->clear();
174 }
175
176 virtual ~CsectSectionEntry() = default;
177 };
178
179 struct DwarfSectionEntry : public SectionEntry {
180 // For DWARF section entry.
181 std::unique_ptr<XCOFFSection> DwarfSect;
182
183 // For DWARF section, we must use real size in the section header. MemorySize
184 // is for the size the DWARF section occupies including paddings.
185 uint32_t MemorySize;
186
DwarfSectionEntry__anondfe4bda90111::DwarfSectionEntry187 DwarfSectionEntry(StringRef N, int32_t Flags,
188 std::unique_ptr<XCOFFSection> Sect)
189 : SectionEntry(N, Flags | XCOFF::STYP_DWARF), DwarfSect(std::move(Sect)),
190 MemorySize(0) {
191 assert(DwarfSect->MCSec->isDwarfSect() &&
192 "This should be a DWARF section!");
193 assert(N.size() <= XCOFF::NameSize && "section name too long");
194 memcpy(Name, N.data(), N.size());
195 }
196
197 DwarfSectionEntry(DwarfSectionEntry &&s) = default;
198
199 virtual ~DwarfSectionEntry() = default;
200 };
201
202 class XCOFFObjectWriter : public MCObjectWriter {
203
204 uint32_t SymbolTableEntryCount = 0;
205 uint64_t SymbolTableOffset = 0;
206 uint16_t SectionCount = 0;
207 uint64_t RelocationEntryOffset = 0;
208 std::vector<std::pair<std::string, size_t>> FileNames;
209 bool HasVisibility = false;
210
211 support::endian::Writer W;
212 std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
213 StringTableBuilder Strings;
214
215 const uint64_t MaxRawDataSize =
216 TargetObjectWriter->is64Bit() ? UINT64_MAX : UINT32_MAX;
217
218 // Maps the MCSection representation to its corresponding XCOFFSection
219 // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into
220 // from its containing MCSectionXCOFF.
221 DenseMap<const MCSectionXCOFF *, XCOFFSection *> SectionMap;
222
223 // Maps the MCSymbol representation to its corrresponding symbol table index.
224 // Needed for relocation.
225 DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap;
226
227 // CsectGroups. These store the csects which make up different parts of
228 // the sections. Should have one for each set of csects that get mapped into
229 // the same section and get handled in a 'similar' way.
230 CsectGroup UndefinedCsects;
231 CsectGroup ProgramCodeCsects;
232 CsectGroup ReadOnlyCsects;
233 CsectGroup DataCsects;
234 CsectGroup FuncDSCsects;
235 CsectGroup TOCCsects;
236 CsectGroup BSSCsects;
237 CsectGroup TDataCsects;
238 CsectGroup TBSSCsects;
239
240 // The Predefined sections.
241 CsectSectionEntry Text;
242 CsectSectionEntry Data;
243 CsectSectionEntry BSS;
244 CsectSectionEntry TData;
245 CsectSectionEntry TBSS;
246
247 // All the XCOFF sections, in the order they will appear in the section header
248 // table.
249 std::array<CsectSectionEntry *const, 5> Sections{
250 {&Text, &Data, &BSS, &TData, &TBSS}};
251
252 std::vector<DwarfSectionEntry> DwarfSections;
253
254 CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
255
256 void reset() override;
257
258 void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override;
259
260 void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *,
261 const MCFixup &, MCValue, uint64_t &) override;
262
263 uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override;
264
is64Bit() const265 bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
266 bool nameShouldBeInStringTable(const StringRef &);
267 void writeSymbolName(const StringRef &);
268
269 void writeSymbolEntryForCsectMemberLabel(const Symbol &SymbolRef,
270 const XCOFFSection &CSectionRef,
271 int16_t SectionIndex,
272 uint64_t SymbolOffset);
273 void writeSymbolEntryForControlSection(const XCOFFSection &CSectionRef,
274 int16_t SectionIndex,
275 XCOFF::StorageClass StorageClass);
276 void writeSymbolEntryForDwarfSection(const XCOFFSection &DwarfSectionRef,
277 int16_t SectionIndex);
278 void writeFileHeader();
279 void writeAuxFileHeader();
280 void writeSectionHeaderTable();
281 void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
282 void writeSectionForControlSectionEntry(const MCAssembler &Asm,
283 const MCAsmLayout &Layout,
284 const CsectSectionEntry &CsectEntry,
285 uint64_t &CurrentAddressLocation);
286 void writeSectionForDwarfSectionEntry(const MCAssembler &Asm,
287 const MCAsmLayout &Layout,
288 const DwarfSectionEntry &DwarfEntry,
289 uint64_t &CurrentAddressLocation);
290 void writeSymbolTable(const MCAsmLayout &Layout);
291 void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion,
292 uint64_t NumberOfRelocEnt = 0);
293 void writeSymbolAuxCsectEntry(uint64_t SectionOrLength,
294 uint8_t SymbolAlignmentAndType,
295 uint8_t StorageMappingClass);
296 void writeSymbolEntry(StringRef SymbolName, uint64_t Value,
297 int16_t SectionNumber, uint16_t SymbolType,
298 uint8_t StorageClass, uint8_t NumberOfAuxEntries = 1);
299 void writeRelocations();
300 void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section);
301
302 // Called after all the csects and symbols have been processed by
303 // `executePostLayoutBinding`, this function handles building up the majority
304 // of the structures in the object file representation. Namely:
305 // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
306 // sizes.
307 // *) Assigns symbol table indices.
308 // *) Builds up the section header table by adding any non-empty sections to
309 // `Sections`.
310 void assignAddressesAndIndices(const MCAsmLayout &);
311 void finalizeSectionInfo();
312
auxiliaryHeaderSize() const313 size_t auxiliaryHeaderSize() const {
314 // 64-bit object files have no auxiliary header.
315 return HasVisibility && !is64Bit() ? XCOFF::AuxFileHeaderSizeShort : 0;
316 }
317
318 public:
319 XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
320 raw_pwrite_stream &OS);
321
writeWord(uint64_t Word)322 void writeWord(uint64_t Word) {
323 is64Bit() ? W.write<uint64_t>(Word) : W.write<uint32_t>(Word);
324 }
325 };
326
XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,raw_pwrite_stream & OS)327 XCOFFObjectWriter::XCOFFObjectWriter(
328 std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
329 : W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
330 Strings(StringTableBuilder::XCOFF),
331 Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false,
332 CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
333 Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false,
334 CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
335 BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true,
336 CsectGroups{&BSSCsects}),
337 TData(".tdata", XCOFF::STYP_TDATA, /* IsVirtual */ false,
338 CsectGroups{&TDataCsects}),
339 TBSS(".tbss", XCOFF::STYP_TBSS, /* IsVirtual */ true,
340 CsectGroups{&TBSSCsects}) {}
341
reset()342 void XCOFFObjectWriter::reset() {
343 // Clear the mappings we created.
344 SymbolIndexMap.clear();
345 SectionMap.clear();
346
347 UndefinedCsects.clear();
348 // Reset any sections we have written to, and empty the section header table.
349 for (auto *Sec : Sections)
350 Sec->reset();
351 for (auto &DwarfSec : DwarfSections)
352 DwarfSec.reset();
353
354 // Reset states in XCOFFObjectWriter.
355 SymbolTableEntryCount = 0;
356 SymbolTableOffset = 0;
357 SectionCount = 0;
358 RelocationEntryOffset = 0;
359 Strings.clear();
360
361 MCObjectWriter::reset();
362 }
363
getCsectGroup(const MCSectionXCOFF * MCSec)364 CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
365 switch (MCSec->getMappingClass()) {
366 case XCOFF::XMC_PR:
367 assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
368 "Only an initialized csect can contain program code.");
369 return ProgramCodeCsects;
370 case XCOFF::XMC_RO:
371 assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
372 "Only an initialized csect can contain read only data.");
373 return ReadOnlyCsects;
374 case XCOFF::XMC_RW:
375 if (XCOFF::XTY_CM == MCSec->getCSectType())
376 return BSSCsects;
377
378 if (XCOFF::XTY_SD == MCSec->getCSectType())
379 return DataCsects;
380
381 report_fatal_error("Unhandled mapping of read-write csect to section.");
382 case XCOFF::XMC_DS:
383 return FuncDSCsects;
384 case XCOFF::XMC_BS:
385 assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
386 "Mapping invalid csect. CSECT with bss storage class must be "
387 "common type.");
388 return BSSCsects;
389 case XCOFF::XMC_TL:
390 assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
391 "Mapping invalid csect. CSECT with tdata storage class must be "
392 "an initialized csect.");
393 return TDataCsects;
394 case XCOFF::XMC_UL:
395 assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
396 "Mapping invalid csect. CSECT with tbss storage class must be "
397 "an uninitialized csect.");
398 return TBSSCsects;
399 case XCOFF::XMC_TC0:
400 assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
401 "Only an initialized csect can contain TOC-base.");
402 assert(TOCCsects.empty() &&
403 "We should have only one TOC-base, and it should be the first csect "
404 "in this CsectGroup.");
405 return TOCCsects;
406 case XCOFF::XMC_TC:
407 case XCOFF::XMC_TE:
408 assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
409 "Only an initialized csect can contain TC entry.");
410 assert(!TOCCsects.empty() &&
411 "We should at least have a TOC-base in this CsectGroup.");
412 return TOCCsects;
413 case XCOFF::XMC_TD:
414 report_fatal_error("toc-data not yet supported when writing object files.");
415 default:
416 report_fatal_error("Unhandled mapping of csect to section.");
417 }
418 }
419
getContainingCsect(const MCSymbolXCOFF * XSym)420 static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) {
421 if (XSym->isDefined())
422 return cast<MCSectionXCOFF>(XSym->getFragment()->getParent());
423 return XSym->getRepresentedCsect();
424 }
425
executePostLayoutBinding(MCAssembler & Asm,const MCAsmLayout & Layout)426 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
427 const MCAsmLayout &Layout) {
428 for (const auto &S : Asm) {
429 const auto *MCSec = cast<const MCSectionXCOFF>(&S);
430 assert(SectionMap.find(MCSec) == SectionMap.end() &&
431 "Cannot add a section twice.");
432
433 // If the name does not fit in the storage provided in the symbol table
434 // entry, add it to the string table.
435 if (nameShouldBeInStringTable(MCSec->getSymbolTableName()))
436 Strings.add(MCSec->getSymbolTableName());
437 if (MCSec->isCsect()) {
438 // A new control section. Its CsectSectionEntry should already be staticly
439 // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of
440 // the CsectSectionEntry.
441 assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
442 "An undefined csect should not get registered.");
443 CsectGroup &Group = getCsectGroup(MCSec);
444 Group.emplace_back(MCSec);
445 SectionMap[MCSec] = &Group.back();
446 } else if (MCSec->isDwarfSect()) {
447 // A new DwarfSectionEntry.
448 std::unique_ptr<XCOFFSection> DwarfSec =
449 std::make_unique<XCOFFSection>(MCSec);
450 SectionMap[MCSec] = DwarfSec.get();
451
452 DwarfSectionEntry SecEntry(MCSec->getName(),
453 *MCSec->getDwarfSubtypeFlags(),
454 std::move(DwarfSec));
455 DwarfSections.push_back(std::move(SecEntry));
456 } else
457 llvm_unreachable("unsupport section type!");
458 }
459
460 for (const MCSymbol &S : Asm.symbols()) {
461 // Nothing to do for temporary symbols.
462 if (S.isTemporary())
463 continue;
464
465 const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
466 const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym);
467
468 if (XSym->getVisibilityType() != XCOFF::SYM_V_UNSPECIFIED)
469 HasVisibility = true;
470
471 if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) {
472 // Handle undefined symbol.
473 UndefinedCsects.emplace_back(ContainingCsect);
474 SectionMap[ContainingCsect] = &UndefinedCsects.back();
475 if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName()))
476 Strings.add(ContainingCsect->getSymbolTableName());
477 continue;
478 }
479
480 // If the symbol is the csect itself, we don't need to put the symbol
481 // into csect's Syms.
482 if (XSym == ContainingCsect->getQualNameSymbol())
483 continue;
484
485 // Only put a label into the symbol table when it is an external label.
486 if (!XSym->isExternal())
487 continue;
488
489 assert(SectionMap.find(ContainingCsect) != SectionMap.end() &&
490 "Expected containing csect to exist in map");
491 XCOFFSection *Csect = SectionMap[ContainingCsect];
492 // Lookup the containing csect and add the symbol to it.
493 assert(Csect->MCSec->isCsect() && "only csect is supported now!");
494 Csect->Syms.emplace_back(XSym);
495
496 // If the name does not fit in the storage provided in the symbol table
497 // entry, add it to the string table.
498 if (nameShouldBeInStringTable(XSym->getSymbolTableName()))
499 Strings.add(XSym->getSymbolTableName());
500 }
501
502 FileNames = Asm.getFileNames();
503 // Emit ".file" as the source file name when there is no file name.
504 if (FileNames.empty())
505 FileNames.emplace_back(".file", 0);
506 for (const std::pair<std::string, size_t> &F : FileNames) {
507 if (nameShouldBeInStringTable(F.first))
508 Strings.add(F.first);
509 }
510
511 Strings.finalize();
512 assignAddressesAndIndices(Layout);
513 }
514
recordRelocation(MCAssembler & Asm,const MCAsmLayout & Layout,const MCFragment * Fragment,const MCFixup & Fixup,MCValue Target,uint64_t & FixedValue)515 void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
516 const MCAsmLayout &Layout,
517 const MCFragment *Fragment,
518 const MCFixup &Fixup, MCValue Target,
519 uint64_t &FixedValue) {
520 auto getIndex = [this](const MCSymbol *Sym,
521 const MCSectionXCOFF *ContainingCsect) {
522 // If we could not find the symbol directly in SymbolIndexMap, this symbol
523 // could either be a temporary symbol or an undefined symbol. In this case,
524 // we would need to have the relocation reference its csect instead.
525 return SymbolIndexMap.find(Sym) != SymbolIndexMap.end()
526 ? SymbolIndexMap[Sym]
527 : SymbolIndexMap[ContainingCsect->getQualNameSymbol()];
528 };
529
530 auto getVirtualAddress =
531 [this, &Layout](const MCSymbol *Sym,
532 const MCSectionXCOFF *ContainingSect) -> uint64_t {
533 // A DWARF section.
534 if (ContainingSect->isDwarfSect())
535 return Layout.getSymbolOffset(*Sym);
536
537 // A csect.
538 if (!Sym->isDefined())
539 return SectionMap[ContainingSect]->Address;
540
541 // A label.
542 assert(Sym->isDefined() && "not a valid object that has address!");
543 return SectionMap[ContainingSect]->Address + Layout.getSymbolOffset(*Sym);
544 };
545
546 const MCSymbol *const SymA = &Target.getSymA()->getSymbol();
547
548 MCAsmBackend &Backend = Asm.getBackend();
549 bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
550 MCFixupKindInfo::FKF_IsPCRel;
551
552 uint8_t Type;
553 uint8_t SignAndSize;
554 std::tie(Type, SignAndSize) =
555 TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel);
556
557 const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
558
559 if (SymASec->isCsect() && SymASec->getMappingClass() == XCOFF::XMC_TD)
560 report_fatal_error("toc-data not yet supported when writing object files.");
561
562 assert(SectionMap.find(SymASec) != SectionMap.end() &&
563 "Expected containing csect to exist in map.");
564
565 const uint32_t Index = getIndex(SymA, SymASec);
566 if (Type == XCOFF::RelocationType::R_POS ||
567 Type == XCOFF::RelocationType::R_TLS)
568 // The FixedValue should be symbol's virtual address in this object file
569 // plus any constant value that we might get.
570 FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();
571 else if (Type == XCOFF::RelocationType::R_TLSM)
572 // The FixedValue should always be zero since the region handle is only
573 // known at load time.
574 FixedValue = 0;
575 else if (Type == XCOFF::RelocationType::R_TOC ||
576 Type == XCOFF::RelocationType::R_TOCL) {
577 // The FixedValue should be the TOC entry offset from the TOC-base plus any
578 // constant offset value.
579 const int64_t TOCEntryOffset = SectionMap[SymASec]->Address -
580 TOCCsects.front().Address +
581 Target.getConstant();
582 if (Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset))
583 report_fatal_error("TOCEntryOffset overflows in small code model mode");
584
585 FixedValue = TOCEntryOffset;
586 }
587
588 assert((Fixup.getOffset() <=
589 MaxRawDataSize - Layout.getFragmentOffset(Fragment)) &&
590 "Fragment offset + fixup offset is overflowed.");
591 uint32_t FixupOffsetInCsect =
592 Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
593
594 XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type};
595 MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent());
596 assert(SectionMap.find(RelocationSec) != SectionMap.end() &&
597 "Expected containing csect to exist in map.");
598 SectionMap[RelocationSec]->Relocations.push_back(Reloc);
599
600 if (!Target.getSymB())
601 return;
602
603 const MCSymbol *const SymB = &Target.getSymB()->getSymbol();
604 if (SymA == SymB)
605 report_fatal_error("relocation for opposite term is not yet supported");
606
607 const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
608 assert(SectionMap.find(SymBSec) != SectionMap.end() &&
609 "Expected containing csect to exist in map.");
610 if (SymASec == SymBSec)
611 report_fatal_error(
612 "relocation for paired relocatable term is not yet supported");
613
614 assert(Type == XCOFF::RelocationType::R_POS &&
615 "SymA must be R_POS here if it's not opposite term or paired "
616 "relocatable term.");
617 const uint32_t IndexB = getIndex(SymB, SymBSec);
618 // SymB must be R_NEG here, given the general form of Target(MCValue) is
619 // "SymbolA - SymbolB + imm64".
620 const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
621 XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
622 SectionMap[RelocationSec]->Relocations.push_back(RelocB);
623 // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
624 // now we just need to fold "- SymbolB" here.
625 FixedValue -= getVirtualAddress(SymB, SymBSec);
626 }
627
writeSections(const MCAssembler & Asm,const MCAsmLayout & Layout)628 void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
629 const MCAsmLayout &Layout) {
630 uint64_t CurrentAddressLocation = 0;
631 for (const auto *Section : Sections)
632 writeSectionForControlSectionEntry(Asm, Layout, *Section,
633 CurrentAddressLocation);
634 for (const auto &DwarfSection : DwarfSections)
635 writeSectionForDwarfSectionEntry(Asm, Layout, DwarfSection,
636 CurrentAddressLocation);
637 }
638
writeObject(MCAssembler & Asm,const MCAsmLayout & Layout)639 uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
640 const MCAsmLayout &Layout) {
641 // We always emit a timestamp of 0 for reproducibility, so ensure incremental
642 // linking is not enabled, in case, like with Windows COFF, such a timestamp
643 // is incompatible with incremental linking of XCOFF.
644 if (Asm.isIncrementalLinkerCompatible())
645 report_fatal_error("Incremental linking not supported for XCOFF.");
646
647 finalizeSectionInfo();
648 uint64_t StartOffset = W.OS.tell();
649
650 writeFileHeader();
651 writeAuxFileHeader();
652 writeSectionHeaderTable();
653 writeSections(Asm, Layout);
654 writeRelocations();
655 writeSymbolTable(Layout);
656 // Write the string table.
657 Strings.write(W.OS);
658
659 return W.OS.tell() - StartOffset;
660 }
661
nameShouldBeInStringTable(const StringRef & SymbolName)662 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
663 return SymbolName.size() > XCOFF::NameSize || is64Bit();
664 }
665
writeSymbolName(const StringRef & SymbolName)666 void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) {
667 // Magic, Offset or SymbolName.
668 if (nameShouldBeInStringTable(SymbolName)) {
669 W.write<int32_t>(0);
670 W.write<uint32_t>(Strings.getOffset(SymbolName));
671 } else {
672 char Name[XCOFF::NameSize + 1];
673 std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
674 ArrayRef<char> NameRef(Name, XCOFF::NameSize);
675 W.write(NameRef);
676 }
677 }
678
writeSymbolEntry(StringRef SymbolName,uint64_t Value,int16_t SectionNumber,uint16_t SymbolType,uint8_t StorageClass,uint8_t NumberOfAuxEntries)679 void XCOFFObjectWriter::writeSymbolEntry(StringRef SymbolName, uint64_t Value,
680 int16_t SectionNumber,
681 uint16_t SymbolType,
682 uint8_t StorageClass,
683 uint8_t NumberOfAuxEntries) {
684 if (is64Bit()) {
685 W.write<uint64_t>(Value);
686 W.write<uint32_t>(Strings.getOffset(SymbolName));
687 } else {
688 writeSymbolName(SymbolName);
689 W.write<uint32_t>(Value);
690 }
691 W.write<int16_t>(SectionNumber);
692 // TODO Set the function indicator (bit 10, 0x0020) for functions
693 // when debugging is enabled.
694 W.write<uint16_t>(SymbolType);
695 W.write<uint8_t>(StorageClass);
696 W.write<uint8_t>(NumberOfAuxEntries);
697 }
698
writeSymbolAuxCsectEntry(uint64_t SectionOrLength,uint8_t SymbolAlignmentAndType,uint8_t StorageMappingClass)699 void XCOFFObjectWriter::writeSymbolAuxCsectEntry(uint64_t SectionOrLength,
700 uint8_t SymbolAlignmentAndType,
701 uint8_t StorageMappingClass) {
702 W.write<uint32_t>(is64Bit() ? Lo_32(SectionOrLength) : SectionOrLength);
703 W.write<uint32_t>(0); // ParameterHashIndex
704 W.write<uint16_t>(0); // TypeChkSectNum
705 W.write<uint8_t>(SymbolAlignmentAndType);
706 W.write<uint8_t>(StorageMappingClass);
707 if (is64Bit()) {
708 W.write<uint32_t>(Hi_32(SectionOrLength));
709 W.OS.write_zeros(1); // Reserved
710 W.write<uint8_t>(XCOFF::AUX_CSECT);
711 } else {
712 W.write<uint32_t>(0); // StabInfoIndex
713 W.write<uint16_t>(0); // StabSectNum
714 }
715 }
716
writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion,uint64_t NumberOfRelocEnt)717 void XCOFFObjectWriter::writeSymbolAuxDwarfEntry(
718 uint64_t LengthOfSectionPortion, uint64_t NumberOfRelocEnt) {
719 writeWord(LengthOfSectionPortion);
720 if (!is64Bit())
721 W.OS.write_zeros(4); // Reserved
722 writeWord(NumberOfRelocEnt);
723 if (is64Bit()) {
724 W.OS.write_zeros(1); // Reserved
725 W.write<uint8_t>(XCOFF::AUX_SECT);
726 } else {
727 W.OS.write_zeros(6); // Reserved
728 }
729 }
730
writeSymbolEntryForCsectMemberLabel(const Symbol & SymbolRef,const XCOFFSection & CSectionRef,int16_t SectionIndex,uint64_t SymbolOffset)731 void XCOFFObjectWriter::writeSymbolEntryForCsectMemberLabel(
732 const Symbol &SymbolRef, const XCOFFSection &CSectionRef,
733 int16_t SectionIndex, uint64_t SymbolOffset) {
734 assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address &&
735 "Symbol address overflowed.");
736
737 writeSymbolEntry(SymbolRef.getSymbolTableName(),
738 CSectionRef.Address + SymbolOffset, SectionIndex,
739 SymbolRef.getVisibilityType(), SymbolRef.getStorageClass());
740
741 writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex, XCOFF::XTY_LD,
742 CSectionRef.MCSec->getMappingClass());
743 }
744
writeSymbolEntryForDwarfSection(const XCOFFSection & DwarfSectionRef,int16_t SectionIndex)745 void XCOFFObjectWriter::writeSymbolEntryForDwarfSection(
746 const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) {
747 assert(DwarfSectionRef.MCSec->isDwarfSect() && "Not a DWARF section!");
748
749 writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), /*Value=*/0,
750 SectionIndex, /*SymbolType=*/0, XCOFF::C_DWARF);
751
752 writeSymbolAuxDwarfEntry(DwarfSectionRef.Size);
753 }
754
writeSymbolEntryForControlSection(const XCOFFSection & CSectionRef,int16_t SectionIndex,XCOFF::StorageClass StorageClass)755 void XCOFFObjectWriter::writeSymbolEntryForControlSection(
756 const XCOFFSection &CSectionRef, int16_t SectionIndex,
757 XCOFF::StorageClass StorageClass) {
758 writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address,
759 SectionIndex, CSectionRef.getVisibilityType(), StorageClass);
760
761 writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec),
762 CSectionRef.MCSec->getMappingClass());
763 }
764
writeFileHeader()765 void XCOFFObjectWriter::writeFileHeader() {
766 W.write<uint16_t>(is64Bit() ? XCOFF::XCOFF64 : XCOFF::XCOFF32);
767 W.write<uint16_t>(SectionCount);
768 W.write<int32_t>(0); // TimeStamp
769 writeWord(SymbolTableOffset);
770 if (is64Bit()) {
771 W.write<uint16_t>(auxiliaryHeaderSize());
772 W.write<uint16_t>(0); // Flags
773 W.write<int32_t>(SymbolTableEntryCount);
774 } else {
775 W.write<int32_t>(SymbolTableEntryCount);
776 W.write<uint16_t>(auxiliaryHeaderSize());
777 W.write<uint16_t>(0); // Flags
778 }
779 }
780
writeAuxFileHeader()781 void XCOFFObjectWriter::writeAuxFileHeader() {
782 if (!auxiliaryHeaderSize())
783 return;
784 W.write<uint16_t>(0); // Magic
785 W.write<uint16_t>(
786 XCOFF::NEW_XCOFF_INTERPRET); // Version. The new interpretation of the
787 // n_type field in the symbol table entry is
788 // used in XCOFF32.
789 W.write<uint32_t>(Sections[0]->Size); // TextSize
790 W.write<uint32_t>(Sections[1]->Size); // InitDataSize
791 W.write<uint32_t>(Sections[2]->Size); // BssDataSize
792 W.write<uint32_t>(0); // EntryPointAddr
793 W.write<uint32_t>(Sections[0]->Address); // TextStartAddr
794 W.write<uint32_t>(Sections[1]->Address); // DataStartAddr
795 }
796
writeSectionHeaderTable()797 void XCOFFObjectWriter::writeSectionHeaderTable() {
798 auto writeSectionHeader = [&](const SectionEntry *Sec, bool IsDwarf) {
799 // Nothing to write for this Section.
800 if (Sec->Index == SectionEntry::UninitializedIndex)
801 return false;
802
803 // Write Name.
804 ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
805 W.write(NameRef);
806
807 // Write the Physical Address and Virtual Address. In an object file these
808 // are the same.
809 // We use 0 for DWARF sections' Physical and Virtual Addresses.
810 writeWord(IsDwarf ? 0 : Sec->Address);
811 writeWord(IsDwarf ? 0 : Sec->Address);
812
813 writeWord(Sec->Size);
814 writeWord(Sec->FileOffsetToData);
815 writeWord(Sec->FileOffsetToRelocations);
816 writeWord(0); // FileOffsetToLineNumberInfo. Not supported yet.
817
818 if (is64Bit()) {
819 W.write<uint32_t>(Sec->RelocationCount);
820 W.write<uint32_t>(0); // NumberOfLineNumbers. Not supported yet.
821 W.write<int32_t>(Sec->Flags);
822 W.OS.write_zeros(4);
823 } else {
824 W.write<uint16_t>(Sec->RelocationCount);
825 W.write<uint16_t>(0); // NumberOfLineNumbers. Not supported yet.
826 W.write<int32_t>(Sec->Flags);
827 }
828
829 return true;
830 };
831
832 for (const auto *CsectSec : Sections)
833 writeSectionHeader(CsectSec, /* IsDwarf */ false);
834 for (const auto &DwarfSec : DwarfSections)
835 writeSectionHeader(&DwarfSec, /* IsDwarf */ true);
836 }
837
writeRelocation(XCOFFRelocation Reloc,const XCOFFSection & Section)838 void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
839 const XCOFFSection &Section) {
840 if (Section.MCSec->isCsect())
841 writeWord(Section.Address + Reloc.FixupOffsetInCsect);
842 else {
843 // DWARF sections' address is set to 0.
844 assert(Section.MCSec->isDwarfSect() && "unsupport section type!");
845 writeWord(Reloc.FixupOffsetInCsect);
846 }
847 W.write<uint32_t>(Reloc.SymbolTableIndex);
848 W.write<uint8_t>(Reloc.SignAndSize);
849 W.write<uint8_t>(Reloc.Type);
850 }
851
writeRelocations()852 void XCOFFObjectWriter::writeRelocations() {
853 for (const auto *Section : Sections) {
854 if (Section->Index == SectionEntry::UninitializedIndex)
855 // Nothing to write for this Section.
856 continue;
857
858 for (const auto *Group : Section->Groups) {
859 if (Group->empty())
860 continue;
861
862 for (const auto &Csect : *Group) {
863 for (const auto Reloc : Csect.Relocations)
864 writeRelocation(Reloc, Csect);
865 }
866 }
867 }
868
869 for (const auto &DwarfSection : DwarfSections)
870 for (const auto &Reloc : DwarfSection.DwarfSect->Relocations)
871 writeRelocation(Reloc, *DwarfSection.DwarfSect);
872 }
873
writeSymbolTable(const MCAsmLayout & Layout)874 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
875 // Write C_FILE symbols.
876 // The n_name of a C_FILE symbol is the source file's name when no auxiliary
877 // entries are present.
878 for (const std::pair<std::string, size_t> &F : FileNames) {
879 writeSymbolEntry(F.first, /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG,
880 /*SymbolType=*/0, XCOFF::C_FILE,
881 /*NumberOfAuxEntries=*/0);
882 }
883
884 for (const auto &Csect : UndefinedCsects) {
885 writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF,
886 Csect.MCSec->getStorageClass());
887 }
888
889 for (const auto *Section : Sections) {
890 if (Section->Index == SectionEntry::UninitializedIndex)
891 // Nothing to write for this Section.
892 continue;
893
894 for (const auto *Group : Section->Groups) {
895 if (Group->empty())
896 continue;
897
898 const int16_t SectionIndex = Section->Index;
899 for (const auto &Csect : *Group) {
900 // Write out the control section first and then each symbol in it.
901 writeSymbolEntryForControlSection(Csect, SectionIndex,
902 Csect.MCSec->getStorageClass());
903
904 for (const auto &Sym : Csect.Syms)
905 writeSymbolEntryForCsectMemberLabel(
906 Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym)));
907 }
908 }
909 }
910
911 for (const auto &DwarfSection : DwarfSections)
912 writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect,
913 DwarfSection.Index);
914 }
915
finalizeSectionInfo()916 void XCOFFObjectWriter::finalizeSectionInfo() {
917 for (auto *Section : Sections) {
918 if (Section->Index == SectionEntry::UninitializedIndex)
919 // Nothing to record for this Section.
920 continue;
921
922 for (const auto *Group : Section->Groups) {
923 if (Group->empty())
924 continue;
925
926 for (auto &Csect : *Group) {
927 const size_t CsectRelocCount = Csect.Relocations.size();
928 // An XCOFF64 file may not contain an overflow section header.
929 if (!is64Bit() && (CsectRelocCount >= XCOFF::RelocOverflow ||
930 Section->RelocationCount >=
931 XCOFF::RelocOverflow - CsectRelocCount))
932 report_fatal_error(
933 "relocation entries overflowed; overflow section is "
934 "not implemented yet");
935
936 Section->RelocationCount += CsectRelocCount;
937 }
938 }
939 }
940
941 for (auto &DwarfSection : DwarfSections)
942 DwarfSection.RelocationCount = DwarfSection.DwarfSect->Relocations.size();
943
944 // Calculate the file offset to the relocation entries.
945 uint64_t RawPointer = RelocationEntryOffset;
946 auto calcOffsetToRelocations = [&](SectionEntry *Sec, bool IsDwarf) {
947 if (!IsDwarf && Sec->Index == SectionEntry::UninitializedIndex)
948 return false;
949
950 if (!Sec->RelocationCount)
951 return false;
952
953 Sec->FileOffsetToRelocations = RawPointer;
954 const uint64_t RelocationSizeInSec =
955 Sec->RelocationCount * (is64Bit()
956 ? XCOFF::RelocationSerializationSize64
957 : XCOFF::RelocationSerializationSize32);
958 RawPointer += RelocationSizeInSec;
959 if (RawPointer > MaxRawDataSize)
960 report_fatal_error("Relocation data overflowed this object file.");
961
962 return true;
963 };
964
965 for (auto *Sec : Sections)
966 calcOffsetToRelocations(Sec, /* IsDwarf */ false);
967
968 for (auto &DwarfSec : DwarfSections)
969 calcOffsetToRelocations(&DwarfSec, /* IsDwarf */ true);
970
971 // TODO Error check that the number of symbol table entries fits in 32-bits
972 // signed ...
973 if (SymbolTableEntryCount)
974 SymbolTableOffset = RawPointer;
975 }
976
assignAddressesAndIndices(const MCAsmLayout & Layout)977 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
978 // The symbol table starts with all the C_FILE symbols.
979 uint32_t SymbolTableIndex = FileNames.size();
980
981 // Calculate indices for undefined symbols.
982 for (auto &Csect : UndefinedCsects) {
983 Csect.Size = 0;
984 Csect.Address = 0;
985 Csect.SymbolTableIndex = SymbolTableIndex;
986 SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
987 // 1 main and 1 auxiliary symbol table entry for each contained symbol.
988 SymbolTableIndex += 2;
989 }
990
991 // The address corrresponds to the address of sections and symbols in the
992 // object file. We place the shared address 0 immediately after the
993 // section header table.
994 uint64_t Address = 0;
995 // Section indices are 1-based in XCOFF.
996 int32_t SectionIndex = 1;
997 bool HasTDataSection = false;
998 uint32_t PaddingsBeforeDwarf = 0;
999
1000 for (auto *Section : Sections) {
1001 const bool IsEmpty =
1002 llvm::all_of(Section->Groups,
1003 [](const CsectGroup *Group) { return Group->empty(); });
1004 if (IsEmpty)
1005 continue;
1006
1007 if (SectionIndex > MaxSectionIndex)
1008 report_fatal_error("Section index overflow!");
1009 Section->Index = SectionIndex++;
1010 SectionCount++;
1011
1012 bool SectionAddressSet = false;
1013 // Reset the starting address to 0 for TData section.
1014 if (Section->Flags == XCOFF::STYP_TDATA) {
1015 Address = 0;
1016 HasTDataSection = true;
1017 }
1018 // Reset the starting address to 0 for TBSS section if the object file does
1019 // not contain TData Section.
1020 if ((Section->Flags == XCOFF::STYP_TBSS) && !HasTDataSection)
1021 Address = 0;
1022
1023 for (auto *Group : Section->Groups) {
1024 if (Group->empty())
1025 continue;
1026
1027 for (auto &Csect : *Group) {
1028 const MCSectionXCOFF *MCSec = Csect.MCSec;
1029 Csect.Address = alignTo(Address, MCSec->getAlignment());
1030 Csect.Size = Layout.getSectionAddressSize(MCSec);
1031 Address = Csect.Address + Csect.Size;
1032 Csect.SymbolTableIndex = SymbolTableIndex;
1033 SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
1034 // 1 main and 1 auxiliary symbol table entry for the csect.
1035 SymbolTableIndex += 2;
1036
1037 for (auto &Sym : Csect.Syms) {
1038 Sym.SymbolTableIndex = SymbolTableIndex;
1039 SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex;
1040 // 1 main and 1 auxiliary symbol table entry for each contained
1041 // symbol.
1042 SymbolTableIndex += 2;
1043 }
1044 }
1045
1046 if (!SectionAddressSet) {
1047 Section->Address = Group->front().Address;
1048 SectionAddressSet = true;
1049 }
1050 }
1051
1052 // Make sure the address of the next section aligned to
1053 // DefaultSectionAlign.
1054 Address = alignTo(Address, DefaultSectionAlign);
1055 Section->Size = Address - Section->Address;
1056 }
1057
1058 // Start to generate DWARF sections. Sections other than DWARF section use
1059 // DefaultSectionAlign as the default alignment, while DWARF sections have
1060 // their own alignments. If these two alignments are not the same, we need
1061 // some paddings here and record the paddings bytes for FileOffsetToData
1062 // calculation.
1063 if (!DwarfSections.empty())
1064 PaddingsBeforeDwarf =
1065 alignTo(Address,
1066 (*DwarfSections.begin()).DwarfSect->MCSec->getAlignment()) -
1067 Address;
1068
1069 DwarfSectionEntry *LastDwarfSection = nullptr;
1070
1071 for (auto &DwarfSection : DwarfSections) {
1072 assert((SectionIndex <= MaxSectionIndex) && "Section index overflow!");
1073
1074 XCOFFSection &DwarfSect = *DwarfSection.DwarfSect;
1075 const MCSectionXCOFF *MCSec = DwarfSect.MCSec;
1076
1077 // Section index.
1078 DwarfSection.Index = SectionIndex++;
1079 SectionCount++;
1080
1081 // Symbol index.
1082 DwarfSect.SymbolTableIndex = SymbolTableIndex;
1083 SymbolIndexMap[MCSec->getQualNameSymbol()] = DwarfSect.SymbolTableIndex;
1084 // 1 main and 1 auxiliary symbol table entry for the csect.
1085 SymbolTableIndex += 2;
1086
1087 // Section address. Make it align to section alignment.
1088 // We use address 0 for DWARF sections' Physical and Virtual Addresses.
1089 // This address is used to tell where is the section in the final object.
1090 // See writeSectionForDwarfSectionEntry().
1091 DwarfSection.Address = DwarfSect.Address =
1092 alignTo(Address, MCSec->getAlignment());
1093
1094 // Section size.
1095 // For DWARF section, we must use the real size which may be not aligned.
1096 DwarfSection.Size = DwarfSect.Size = Layout.getSectionAddressSize(MCSec);
1097
1098 Address = DwarfSection.Address + DwarfSection.Size;
1099
1100 if (LastDwarfSection)
1101 LastDwarfSection->MemorySize =
1102 DwarfSection.Address - LastDwarfSection->Address;
1103 LastDwarfSection = &DwarfSection;
1104 }
1105 if (LastDwarfSection) {
1106 // Make the final DWARF section address align to the default section
1107 // alignment for follow contents.
1108 Address = alignTo(LastDwarfSection->Address + LastDwarfSection->Size,
1109 DefaultSectionAlign);
1110 LastDwarfSection->MemorySize = Address - LastDwarfSection->Address;
1111 }
1112
1113 SymbolTableEntryCount = SymbolTableIndex;
1114
1115 // Calculate the RawPointer value for each section.
1116 uint64_t RawPointer =
1117 (is64Bit() ? (XCOFF::FileHeaderSize64 +
1118 SectionCount * XCOFF::SectionHeaderSize64)
1119 : (XCOFF::FileHeaderSize32 +
1120 SectionCount * XCOFF::SectionHeaderSize32)) +
1121 auxiliaryHeaderSize();
1122
1123 for (auto *Sec : Sections) {
1124 if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual)
1125 continue;
1126
1127 Sec->FileOffsetToData = RawPointer;
1128 RawPointer += Sec->Size;
1129 if (RawPointer > MaxRawDataSize)
1130 report_fatal_error("Section raw data overflowed this object file.");
1131 }
1132
1133 // Increase the raw pointer for the padding bytes between csect sections and
1134 // DWARF sections.
1135 if (!DwarfSections.empty())
1136 RawPointer += PaddingsBeforeDwarf;
1137
1138 for (auto &DwarfSection : DwarfSections) {
1139 DwarfSection.FileOffsetToData = RawPointer;
1140
1141 RawPointer += DwarfSection.MemorySize;
1142
1143 assert(RawPointer <= MaxRawDataSize &&
1144 "Section raw data overflowed this object file.");
1145 }
1146
1147 RelocationEntryOffset = RawPointer;
1148 }
1149
writeSectionForControlSectionEntry(const MCAssembler & Asm,const MCAsmLayout & Layout,const CsectSectionEntry & CsectEntry,uint64_t & CurrentAddressLocation)1150 void XCOFFObjectWriter::writeSectionForControlSectionEntry(
1151 const MCAssembler &Asm, const MCAsmLayout &Layout,
1152 const CsectSectionEntry &CsectEntry, uint64_t &CurrentAddressLocation) {
1153 // Nothing to write for this Section.
1154 if (CsectEntry.Index == SectionEntry::UninitializedIndex)
1155 return;
1156
1157 // There could be a gap (without corresponding zero padding) between
1158 // sections.
1159 // There could be a gap (without corresponding zero padding) between
1160 // sections.
1161 assert(((CurrentAddressLocation <= CsectEntry.Address) ||
1162 (CsectEntry.Flags == XCOFF::STYP_TDATA) ||
1163 (CsectEntry.Flags == XCOFF::STYP_TBSS)) &&
1164 "CurrentAddressLocation should be less than or equal to section "
1165 "address if the section is not TData or TBSS.");
1166
1167 CurrentAddressLocation = CsectEntry.Address;
1168
1169 // For virtual sections, nothing to write. But need to increase
1170 // CurrentAddressLocation for later sections like DWARF section has a correct
1171 // writing location.
1172 if (CsectEntry.IsVirtual) {
1173 CurrentAddressLocation += CsectEntry.Size;
1174 return;
1175 }
1176
1177 for (const auto &Group : CsectEntry.Groups) {
1178 for (const auto &Csect : *Group) {
1179 if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
1180 W.OS.write_zeros(PaddingSize);
1181 if (Csect.Size)
1182 Asm.writeSectionData(W.OS, Csect.MCSec, Layout);
1183 CurrentAddressLocation = Csect.Address + Csect.Size;
1184 }
1185 }
1186
1187 // The size of the tail padding in a section is the end virtual address of
1188 // the current section minus the the end virtual address of the last csect
1189 // in that section.
1190 if (uint64_t PaddingSize =
1191 CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) {
1192 W.OS.write_zeros(PaddingSize);
1193 CurrentAddressLocation += PaddingSize;
1194 }
1195 }
1196
writeSectionForDwarfSectionEntry(const MCAssembler & Asm,const MCAsmLayout & Layout,const DwarfSectionEntry & DwarfEntry,uint64_t & CurrentAddressLocation)1197 void XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
1198 const MCAssembler &Asm, const MCAsmLayout &Layout,
1199 const DwarfSectionEntry &DwarfEntry, uint64_t &CurrentAddressLocation) {
1200 // There could be a gap (without corresponding zero padding) between
1201 // sections. For example DWARF section alignment is bigger than
1202 // DefaultSectionAlign.
1203 assert(CurrentAddressLocation <= DwarfEntry.Address &&
1204 "CurrentAddressLocation should be less than or equal to section "
1205 "address.");
1206
1207 if (uint64_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation)
1208 W.OS.write_zeros(PaddingSize);
1209
1210 if (DwarfEntry.Size)
1211 Asm.writeSectionData(W.OS, DwarfEntry.DwarfSect->MCSec, Layout);
1212
1213 CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size;
1214
1215 // DWARF section size is not aligned to DefaultSectionAlign.
1216 // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign.
1217 uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign;
1218 uint32_t TailPaddingSize = Mod ? DefaultSectionAlign - Mod : 0;
1219 if (TailPaddingSize)
1220 W.OS.write_zeros(TailPaddingSize);
1221
1222 CurrentAddressLocation += TailPaddingSize;
1223 }
1224
1225 // Takes the log base 2 of the alignment and shifts the result into the 5 most
1226 // significant bits of a byte, then or's in the csect type into the least
1227 // significant 3 bits.
getEncodedType(const MCSectionXCOFF * Sec)1228 uint8_t getEncodedType(const MCSectionXCOFF *Sec) {
1229 unsigned Align = Sec->getAlignment();
1230 assert(isPowerOf2_32(Align) && "Alignment must be a power of 2.");
1231 unsigned Log2Align = Log2_32(Align);
1232 // Result is a number in the range [0, 31] which fits in the 5 least
1233 // significant bits. Shift this value into the 5 most significant bits, and
1234 // bitwise-or in the csect type.
1235 uint8_t EncodedAlign = Log2Align << 3;
1236 return EncodedAlign | Sec->getCSectType();
1237 }
1238
1239 } // end anonymous namespace
1240
1241 std::unique_ptr<MCObjectWriter>
createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,raw_pwrite_stream & OS)1242 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
1243 raw_pwrite_stream &OS) {
1244 return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS);
1245 }
1246