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