LLVM  12.0.0git
XCOFFObjectWriter.cpp
Go to the documentation of this file.
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 
14 #include "llvm/MC/MCAsmBackend.h"
15 #include "llvm/MC/MCAsmLayout.h"
16 #include "llvm/MC/MCAssembler.h"
17 #include "llvm/MC/MCFixup.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"
26 #include "llvm/Support/Error.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 
68  XCOFF::StorageClass getStorageClass() const {
69  return MCSym->getStorageClass();
70  }
71  StringRef getSymbolTableName() const { return MCSym->getSymbolTableName(); }
72  Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {}
73 };
74 
75 // Wrapper for an MCSectionXCOFF.
76 struct ControlSection {
77  const MCSectionXCOFF *const MCCsect;
78  uint32_t SymbolTableIndex;
80  uint32_t Size;
81 
84  StringRef getSymbolTableName() const { return MCCsect->getSymbolTableName(); }
85  ControlSection(const MCSectionXCOFF *MCSec)
86  : MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
87 };
88 
89 // Type to be used for a container representing a set of csects with
90 // (approximately) the same storage mapping class. For example all the csects
91 // with a storage mapping class of `xmc_pr` will get placed into the same
92 // container.
93 using CsectGroup = std::deque<ControlSection>;
94 using CsectGroups = std::deque<CsectGroup *>;
95 
96 // Represents the data related to a section excluding the csects that make up
97 // the raw data of the section. The csects are stored separately as not all
98 // sections contain csects, and some sections contain csects which are better
99 // stored separately, e.g. the .data section containing read-write, descriptor,
100 // TOCBase and TOC-entry csects.
101 struct Section {
102  char Name[XCOFF::NameSize];
103  // The physical/virtual address of the section. For an object file
104  // these values are equivalent.
106  uint32_t Size;
107  uint32_t FileOffsetToData;
108  uint32_t FileOffsetToRelocations;
109  uint32_t RelocationCount;
110  int32_t Flags;
111 
112  int16_t Index;
113 
114  // Virtual sections do not need storage allocated in the object file.
115  const bool IsVirtual;
116 
117  // XCOFF has special section numbers for symbols:
118  // -2 Specifies N_DEBUG, a special symbolic debugging symbol.
119  // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
120  // relocatable.
121  // 0 Specifies N_UNDEF, an undefined external symbol.
122  // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
123  // hasn't been initialized.
124  static constexpr int16_t UninitializedIndex =
126 
127  CsectGroups Groups;
128 
129  void reset() {
130  Address = 0;
131  Size = 0;
132  FileOffsetToData = 0;
133  FileOffsetToRelocations = 0;
134  RelocationCount = 0;
135  Index = UninitializedIndex;
136  // Clear any csects we have stored.
137  for (auto *Group : Groups)
138  Group->clear();
139  }
140 
141  Section(const char *N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
142  CsectGroups Groups)
143  : Address(0), Size(0), FileOffsetToData(0), FileOffsetToRelocations(0),
144  RelocationCount(0), Flags(Flags), Index(UninitializedIndex),
145  IsVirtual(IsVirtual), Groups(Groups) {
146  strncpy(Name, N, XCOFF::NameSize);
147  }
148 };
149 
150 class XCOFFObjectWriter : public MCObjectWriter {
151 
152  uint32_t SymbolTableEntryCount = 0;
153  uint32_t SymbolTableOffset = 0;
154  uint16_t SectionCount = 0;
155  uint32_t RelocationEntryOffset = 0;
156 
158  std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
159  StringTableBuilder Strings;
160 
161  // Maps the MCSection representation to its corresponding ControlSection
162  // wrapper. Needed for finding the ControlSection to insert an MCSymbol into
163  // from its containing MCSectionXCOFF.
165 
166  // Maps the MCSymbol representation to its corrresponding symbol table index.
167  // Needed for relocation.
169 
170  // CsectGroups. These store the csects which make up different parts of
171  // the sections. Should have one for each set of csects that get mapped into
172  // the same section and get handled in a 'similar' way.
173  CsectGroup UndefinedCsects;
174  CsectGroup ProgramCodeCsects;
175  CsectGroup ReadOnlyCsects;
176  CsectGroup DataCsects;
177  CsectGroup FuncDSCsects;
178  CsectGroup TOCCsects;
179  CsectGroup BSSCsects;
180 
181  // The Predefined sections.
182  Section Text;
183  Section Data;
184  Section BSS;
185 
186  // All the XCOFF sections, in the order they will appear in the section header
187  // table.
188  std::array<Section *const, 3> Sections{{&Text, &Data, &BSS}};
189 
190  CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
191 
192  virtual void reset() override;
193 
194  void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override;
195 
196  void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *,
197  const MCFixup &, MCValue, uint64_t &) override;
198 
199  uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override;
200 
201  static bool nameShouldBeInStringTable(const StringRef &);
202  void writeSymbolName(const StringRef &);
203  void writeSymbolTableEntryForCsectMemberLabel(const Symbol &,
204  const ControlSection &, int16_t,
205  uint64_t);
206  void writeSymbolTableEntryForControlSection(const ControlSection &, int16_t,
208  void writeFileHeader();
209  void writeSectionHeaderTable();
210  void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
211  void writeSymbolTable(const MCAsmLayout &Layout);
212  void writeRelocations();
213  void writeRelocation(XCOFFRelocation Reloc, const ControlSection &CSection);
214 
215  // Called after all the csects and symbols have been processed by
216  // `executePostLayoutBinding`, this function handles building up the majority
217  // of the structures in the object file representation. Namely:
218  // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
219  // sizes.
220  // *) Assigns symbol table indices.
221  // *) Builds up the section header table by adding any non-empty sections to
222  // `Sections`.
223  void assignAddressesAndIndices(const MCAsmLayout &);
224  void finalizeSectionInfo();
225 
226  bool
227  needsAuxiliaryHeader() const { /* TODO aux header support not implemented. */
228  return false;
229  }
230 
231  // Returns the size of the auxiliary header to be written to the object file.
232  size_t auxiliaryHeaderSize() const {
233  assert(!needsAuxiliaryHeader() &&
234  "Auxiliary header support not implemented.");
235  return 0;
236  }
237 
238 public:
239  XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
240  raw_pwrite_stream &OS);
241 };
242 
243 XCOFFObjectWriter::XCOFFObjectWriter(
244  std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
245  : W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
246  Strings(StringTableBuilder::XCOFF),
247  Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false,
248  CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
249  Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false,
250  CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
251  BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true,
252  CsectGroups{&BSSCsects}) {}
253 
254 void XCOFFObjectWriter::reset() {
255  // Clear the mappings we created.
256  SymbolIndexMap.clear();
257  SectionMap.clear();
258 
259  UndefinedCsects.clear();
260  // Reset any sections we have written to, and empty the section header table.
261  for (auto *Sec : Sections)
262  Sec->reset();
263 
264  // Reset states in XCOFFObjectWriter.
265  SymbolTableEntryCount = 0;
266  SymbolTableOffset = 0;
267  SectionCount = 0;
268  RelocationEntryOffset = 0;
269  Strings.clear();
270 
272 }
273 
274 CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
275  switch (MCSec->getMappingClass()) {
276  case XCOFF::XMC_PR:
277  assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
278  "Only an initialized csect can contain program code.");
279  return ProgramCodeCsects;
280  case XCOFF::XMC_RO:
281  assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
282  "Only an initialized csect can contain read only data.");
283  return ReadOnlyCsects;
284  case XCOFF::XMC_RW:
285  if (XCOFF::XTY_CM == MCSec->getCSectType())
286  return BSSCsects;
287 
288  if (XCOFF::XTY_SD == MCSec->getCSectType())
289  return DataCsects;
290 
291  report_fatal_error("Unhandled mapping of read-write csect to section.");
292  case XCOFF::XMC_DS:
293  return FuncDSCsects;
294  case XCOFF::XMC_BS:
295  assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
296  "Mapping invalid csect. CSECT with bss storage class must be "
297  "common type.");
298  return BSSCsects;
299  case XCOFF::XMC_TC0:
300  assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
301  "Only an initialized csect can contain TOC-base.");
302  assert(TOCCsects.empty() &&
303  "We should have only one TOC-base, and it should be the first csect "
304  "in this CsectGroup.");
305  return TOCCsects;
306  case XCOFF::XMC_TC:
307  assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
308  "Only an initialized csect can contain TC entry.");
309  assert(!TOCCsects.empty() &&
310  "We should at least have a TOC-base in this CsectGroup.");
311  return TOCCsects;
312  default:
313  report_fatal_error("Unhandled mapping of csect to section.");
314  }
315 }
316 
317 static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) {
318  if (XSym->isDefined())
319  return cast<MCSectionXCOFF>(XSym->getFragment()->getParent());
320  return XSym->getRepresentedCsect();
321 }
322 
323 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
324  const MCAsmLayout &Layout) {
325  if (TargetObjectWriter->is64Bit())
326  report_fatal_error("64-bit XCOFF object files are not supported yet.");
327 
328  for (const auto &S : Asm) {
329  const auto *MCSec = cast<const MCSectionXCOFF>(&S);
330  assert(SectionMap.find(MCSec) == SectionMap.end() &&
331  "Cannot add a csect twice.");
332  assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
333  "An undefined csect should not get registered.");
334 
335  // If the name does not fit in the storage provided in the symbol table
336  // entry, add it to the string table.
337  if (nameShouldBeInStringTable(MCSec->getSymbolTableName()))
338  Strings.add(MCSec->getSymbolTableName());
339 
340  CsectGroup &Group = getCsectGroup(MCSec);
341  Group.emplace_back(MCSec);
342  SectionMap[MCSec] = &Group.back();
343  }
344 
345  for (const MCSymbol &S : Asm.symbols()) {
346  // Nothing to do for temporary symbols.
347  if (S.isTemporary())
348  continue;
349 
350  const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
351  const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym);
352 
353  if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) {
354  // Handle undefined symbol.
355  UndefinedCsects.emplace_back(ContainingCsect);
356  SectionMap[ContainingCsect] = &UndefinedCsects.back();
357  if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName()))
358  Strings.add(ContainingCsect->getSymbolTableName());
359  continue;
360  }
361 
362  // If the symbol is the csect itself, we don't need to put the symbol
363  // into csect's Syms.
364  if (XSym == ContainingCsect->getQualNameSymbol())
365  continue;
366 
367  // Only put a label into the symbol table when it is an external label.
368  if (!XSym->isExternal())
369  continue;
370 
371  assert(SectionMap.find(ContainingCsect) != SectionMap.end() &&
372  "Expected containing csect to exist in map");
373  // Lookup the containing csect and add the symbol to it.
374  SectionMap[ContainingCsect]->Syms.emplace_back(XSym);
375 
376  // If the name does not fit in the storage provided in the symbol table
377  // entry, add it to the string table.
378  if (nameShouldBeInStringTable(XSym->getSymbolTableName()))
379  Strings.add(XSym->getSymbolTableName());
380  }
381 
382  Strings.finalize();
383  assignAddressesAndIndices(Layout);
384 }
385 
386 void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
387  const MCAsmLayout &Layout,
388  const MCFragment *Fragment,
389  const MCFixup &Fixup, MCValue Target,
390  uint64_t &FixedValue) {
391  auto getIndex = [this](const MCSymbol *Sym,
392  const MCSectionXCOFF *ContainingCsect) {
393  // If we could not find the symbol directly in SymbolIndexMap, this symbol
394  // could either be a temporary symbol or an undefined symbol. In this case,
395  // we would need to have the relocation reference its csect instead.
396  return SymbolIndexMap.find(Sym) != SymbolIndexMap.end()
397  ? SymbolIndexMap[Sym]
398  : SymbolIndexMap[ContainingCsect->getQualNameSymbol()];
399  };
400 
401  auto getVirtualAddress = [this,
402  &Layout](const MCSymbol *Sym,
403  const MCSectionXCOFF *ContainingCsect) {
404  // If Sym is a csect, return csect's address.
405  // If Sym is a label, return csect's address + label's offset from the csect.
406  return SectionMap[ContainingCsect]->Address +
407  (Sym->isDefined() ? Layout.getSymbolOffset(*Sym) : 0);
408  };
409 
410  const MCSymbol *const SymA = &Target.getSymA()->getSymbol();
411 
412  MCAsmBackend &Backend = Asm.getBackend();
413  bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
415 
416  uint8_t Type;
417  uint8_t SignAndSize;
418  std::tie(Type, SignAndSize) =
419  TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel);
420 
421  const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
422  assert(SectionMap.find(SymASec) != SectionMap.end() &&
423  "Expected containing csect to exist in map.");
424 
425  const uint32_t Index = getIndex(SymA, SymASec);
426  if (Type == XCOFF::RelocationType::R_POS)
427  // The FixedValue should be symbol's virtual address in this object file
428  // plus any constant value that we might get.
429  FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();
430  else if (Type == XCOFF::RelocationType::R_TOC)
431  // The FixedValue should be the TC entry offset from TOC-base.
432  FixedValue = SectionMap[SymASec]->Address - TOCCsects.front().Address;
433 
434  assert(
435  (TargetObjectWriter->is64Bit() ||
436  Fixup.getOffset() <= UINT32_MAX - Layout.getFragmentOffset(Fragment)) &&
437  "Fragment offset + fixup offset is overflowed in 32-bit mode.");
438  uint32_t FixupOffsetInCsect =
439  Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
440 
441  XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type};
442  MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent());
443  assert(SectionMap.find(RelocationSec) != SectionMap.end() &&
444  "Expected containing csect to exist in map.");
445  SectionMap[RelocationSec]->Relocations.push_back(Reloc);
446 
447  if (!Target.getSymB())
448  return;
449 
450  const MCSymbol *const SymB = &Target.getSymB()->getSymbol();
451  if (SymA == SymB)
452  report_fatal_error("relocation for opposite term is not yet supported");
453 
454  const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
455  assert(SectionMap.find(SymBSec) != SectionMap.end() &&
456  "Expected containing csect to exist in map.");
457  if (SymASec == SymBSec)
459  "relocation for paired relocatable term is not yet supported");
460 
462  "SymA must be R_POS here if it's not opposite term or paired "
463  "relocatable term.");
464  const uint32_t IndexB = getIndex(SymB, SymBSec);
465  // SymB must be R_NEG here, given the general form of Target(MCValue) is
466  // "SymbolA - SymbolB + imm64".
467  const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
468  XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
469  SectionMap[RelocationSec]->Relocations.push_back(RelocB);
470  // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
471  // now we just need to fold "- SymbolB" here.
472  FixedValue -= getVirtualAddress(SymB, SymBSec);
473 }
474 
475 void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
476  const MCAsmLayout &Layout) {
477  uint32_t CurrentAddressLocation = 0;
478  for (const auto *Section : Sections) {
479  // Nothing to write for this Section.
480  if (Section->Index == Section::UninitializedIndex || Section->IsVirtual)
481  continue;
482 
483  // There could be a gap (without corresponding zero padding) between
484  // sections.
485  assert(CurrentAddressLocation <= Section->Address &&
486  "CurrentAddressLocation should be less than or equal to section "
487  "address.");
488 
489  CurrentAddressLocation = Section->Address;
490 
491  for (const auto *Group : Section->Groups) {
492  for (const auto &Csect : *Group) {
493  if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
494  W.OS.write_zeros(PaddingSize);
495  if (Csect.Size)
496  Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
497  CurrentAddressLocation = Csect.Address + Csect.Size;
498  }
499  }
500 
501  // The size of the tail padding in a section is the end virtual address of
502  // the current section minus the the end virtual address of the last csect
503  // in that section.
504  if (uint32_t PaddingSize =
505  Section->Address + Section->Size - CurrentAddressLocation) {
506  W.OS.write_zeros(PaddingSize);
507  CurrentAddressLocation += PaddingSize;
508  }
509  }
510 }
511 
512 uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
513  const MCAsmLayout &Layout) {
514  // We always emit a timestamp of 0 for reproducibility, so ensure incremental
515  // linking is not enabled, in case, like with Windows COFF, such a timestamp
516  // is incompatible with incremental linking of XCOFF.
518  report_fatal_error("Incremental linking not supported for XCOFF.");
519 
520  if (TargetObjectWriter->is64Bit())
521  report_fatal_error("64-bit XCOFF object files are not supported yet.");
522 
523  finalizeSectionInfo();
524  uint64_t StartOffset = W.OS.tell();
525 
526  writeFileHeader();
527  writeSectionHeaderTable();
528  writeSections(Asm, Layout);
529  writeRelocations();
530 
531  writeSymbolTable(Layout);
532  // Write the string table.
533  Strings.write(W.OS);
534 
535  return W.OS.tell() - StartOffset;
536 }
537 
538 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
539  return SymbolName.size() > XCOFF::NameSize;
540 }
541 
542 void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) {
543  if (nameShouldBeInStringTable(SymbolName)) {
544  W.write<int32_t>(0);
545  W.write<uint32_t>(Strings.getOffset(SymbolName));
546  } else {
547  char Name[XCOFF::NameSize+1];
548  std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
549  ArrayRef<char> NameRef(Name, XCOFF::NameSize);
550  W.write(NameRef);
551  }
552 }
553 
554 void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel(
555  const Symbol &SymbolRef, const ControlSection &CSectionRef,
556  int16_t SectionIndex, uint64_t SymbolOffset) {
557  // Name or Zeros and string table offset
558  writeSymbolName(SymbolRef.getSymbolTableName());
559  assert(SymbolOffset <= UINT32_MAX - CSectionRef.Address &&
560  "Symbol address overflows.");
561  W.write<uint32_t>(CSectionRef.Address + SymbolOffset);
562  W.write<int16_t>(SectionIndex);
563  // Basic/Derived type. See the description of the n_type field for symbol
564  // table entries for a detailed description. Since we don't yet support
565  // visibility, and all other bits are either optionally set or reserved, this
566  // is always zero.
567  // TODO FIXME How to assert a symbol's visibilty is default?
568  // TODO Set the function indicator (bit 10, 0x0020) for functions
569  // when debugging is enabled.
570  W.write<uint16_t>(0);
571  W.write<uint8_t>(SymbolRef.getStorageClass());
572  // Always 1 aux entry for now.
573  W.write<uint8_t>(1);
574 
575  // Now output the auxiliary entry.
576  W.write<uint32_t>(CSectionRef.SymbolTableIndex);
577  // Parameter typecheck hash. Not supported.
578  W.write<uint32_t>(0);
579  // Typecheck section number. Not supported.
580  W.write<uint16_t>(0);
581  // Symbol type: Label
582  W.write<uint8_t>(XCOFF::XTY_LD);
583  // Storage mapping class.
584  W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass());
585  // Reserved (x_stab).
586  W.write<uint32_t>(0);
587  // Reserved (x_snstab).
588  W.write<uint16_t>(0);
589 }
590 
591 void XCOFFObjectWriter::writeSymbolTableEntryForControlSection(
592  const ControlSection &CSectionRef, int16_t SectionIndex,
594  // n_name, n_zeros, n_offset
595  writeSymbolName(CSectionRef.getSymbolTableName());
596  // n_value
597  W.write<uint32_t>(CSectionRef.Address);
598  // n_scnum
599  W.write<int16_t>(SectionIndex);
600  // Basic/Derived type. See the description of the n_type field for symbol
601  // table entries for a detailed description. Since we don't yet support
602  // visibility, and all other bits are either optionally set or reserved, this
603  // is always zero.
604  // TODO FIXME How to assert a symbol's visibilty is default?
605  // TODO Set the function indicator (bit 10, 0x0020) for functions
606  // when debugging is enabled.
607  W.write<uint16_t>(0);
608  // n_sclass
609  W.write<uint8_t>(StorageClass);
610  // Always 1 aux entry for now.
611  W.write<uint8_t>(1);
612 
613  // Now output the auxiliary entry.
614  W.write<uint32_t>(CSectionRef.Size);
615  // Parameter typecheck hash. Not supported.
616  W.write<uint32_t>(0);
617  // Typecheck section number. Not supported.
618  W.write<uint16_t>(0);
619  // Symbol type.
620  W.write<uint8_t>(getEncodedType(CSectionRef.MCCsect));
621  // Storage mapping class.
622  W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass());
623  // Reserved (x_stab).
624  W.write<uint32_t>(0);
625  // Reserved (x_snstab).
626  W.write<uint16_t>(0);
627 }
628 
629 void XCOFFObjectWriter::writeFileHeader() {
630  // Magic.
631  W.write<uint16_t>(0x01df);
632  // Number of sections.
633  W.write<uint16_t>(SectionCount);
634  // Timestamp field. For reproducible output we write a 0, which represents no
635  // timestamp.
636  W.write<int32_t>(0);
637  // Byte Offset to the start of the symbol table.
638  W.write<uint32_t>(SymbolTableOffset);
639  // Number of entries in the symbol table.
640  W.write<int32_t>(SymbolTableEntryCount);
641  // Size of the optional header.
642  W.write<uint16_t>(0);
643  // Flags.
644  W.write<uint16_t>(0);
645 }
646 
647 void XCOFFObjectWriter::writeSectionHeaderTable() {
648  for (const auto *Sec : Sections) {
649  // Nothing to write for this Section.
650  if (Sec->Index == Section::UninitializedIndex)
651  continue;
652 
653  // Write Name.
654  ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
655  W.write(NameRef);
656 
657  // Write the Physical Address and Virtual Address. In an object file these
658  // are the same.
659  W.write<uint32_t>(Sec->Address);
660  W.write<uint32_t>(Sec->Address);
661 
662  W.write<uint32_t>(Sec->Size);
663  W.write<uint32_t>(Sec->FileOffsetToData);
664  W.write<uint32_t>(Sec->FileOffsetToRelocations);
665 
666  // Line number pointer. Not supported yet.
667  W.write<uint32_t>(0);
668 
669  W.write<uint16_t>(Sec->RelocationCount);
670 
671  // Line number counts. Not supported yet.
672  W.write<uint16_t>(0);
673 
674  W.write<int32_t>(Sec->Flags);
675  }
676 }
677 
678 void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
679  const ControlSection &CSection) {
680  W.write<uint32_t>(CSection.Address + Reloc.FixupOffsetInCsect);
681  W.write<uint32_t>(Reloc.SymbolTableIndex);
682  W.write<uint8_t>(Reloc.SignAndSize);
683  W.write<uint8_t>(Reloc.Type);
684 }
685 
686 void XCOFFObjectWriter::writeRelocations() {
687  for (const auto *Section : Sections) {
688  if (Section->Index == Section::UninitializedIndex)
689  // Nothing to write for this Section.
690  continue;
691 
692  for (const auto *Group : Section->Groups) {
693  if (Group->empty())
694  continue;
695 
696  for (const auto &Csect : *Group) {
697  for (const auto Reloc : Csect.Relocations)
698  writeRelocation(Reloc, Csect);
699  }
700  }
701  }
702 }
703 
705  for (const auto &Csect : UndefinedCsects) {
706  writeSymbolTableEntryForControlSection(
707  Csect, XCOFF::ReservedSectionNum::N_UNDEF, Csect.MCCsect->getStorageClass());
708  }
709 
710  for (const auto *Section : Sections) {
711  if (Section->Index == Section::UninitializedIndex)
712  // Nothing to write for this Section.
713  continue;
714 
715  for (const auto *Group : Section->Groups) {
716  if (Group->empty())
717  continue;
718 
719  const int16_t SectionIndex = Section->Index;
720  for (const auto &Csect : *Group) {
721  // Write out the control section first and then each symbol in it.
722  writeSymbolTableEntryForControlSection(
723  Csect, SectionIndex, Csect.MCCsect->getStorageClass());
724 
725  for (const auto &Sym : Csect.Syms)
726  writeSymbolTableEntryForCsectMemberLabel(
727  Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym)));
728  }
729  }
730  }
731 }
732 
733 void XCOFFObjectWriter::finalizeSectionInfo() {
734  for (auto *Section : Sections) {
735  if (Section->Index == Section::UninitializedIndex)
736  // Nothing to record for this Section.
737  continue;
738 
739  for (const auto *Group : Section->Groups) {
740  if (Group->empty())
741  continue;
742 
743  for (auto &Csect : *Group) {
744  const size_t CsectRelocCount = Csect.Relocations.size();
745  if (CsectRelocCount >= XCOFF::RelocOverflow ||
746  Section->RelocationCount >= XCOFF::RelocOverflow - CsectRelocCount)
748  "relocation entries overflowed; overflow section is "
749  "not implemented yet");
750 
751  Section->RelocationCount += CsectRelocCount;
752  }
753  }
754  }
755 
756  // Calculate the file offset to the relocation entries.
757  uint64_t RawPointer = RelocationEntryOffset;
758  for (auto Sec : Sections) {
759  if (Sec->Index == Section::UninitializedIndex || !Sec->RelocationCount)
760  continue;
761 
762  Sec->FileOffsetToRelocations = RawPointer;
763  const uint32_t RelocationSizeInSec =
764  Sec->RelocationCount * XCOFF::RelocationSerializationSize32;
765  RawPointer += RelocationSizeInSec;
766  if (RawPointer > UINT32_MAX)
767  report_fatal_error("Relocation data overflowed this object file.");
768  }
769 
770  // TODO Error check that the number of symbol table entries fits in 32-bits
771  // signed ...
772  if (SymbolTableEntryCount)
773  SymbolTableOffset = RawPointer;
774 }
775 
776 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
777  // The first symbol table entry is for the file name. We are not emitting it
778  // yet, so start at index 0.
779  uint32_t SymbolTableIndex = 0;
780 
781  // Calculate indices for undefined symbols.
782  for (auto &Csect : UndefinedCsects) {
783  Csect.Size = 0;
784  Csect.Address = 0;
785  Csect.SymbolTableIndex = SymbolTableIndex;
786  SymbolIndexMap[Csect.MCCsect->getQualNameSymbol()] = Csect.SymbolTableIndex;
787  // 1 main and 1 auxiliary symbol table entry for each contained symbol.
788  SymbolTableIndex += 2;
789  }
790 
791  // The address corrresponds to the address of sections and symbols in the
792  // object file. We place the shared address 0 immediately after the
793  // section header table.
794  uint32_t Address = 0;
795  // Section indices are 1-based in XCOFF.
796  int32_t SectionIndex = 1;
797 
798  for (auto *Section : Sections) {
799  const bool IsEmpty =
800  llvm::all_of(Section->Groups,
801  [](const CsectGroup *Group) { return Group->empty(); });
802  if (IsEmpty)
803  continue;
804 
805  if (SectionIndex > MaxSectionIndex)
806  report_fatal_error("Section index overflow!");
807  Section->Index = SectionIndex++;
808  SectionCount++;
809 
810  bool SectionAddressSet = false;
811  for (auto *Group : Section->Groups) {
812  if (Group->empty())
813  continue;
814 
815  for (auto &Csect : *Group) {
816  const MCSectionXCOFF *MCSec = Csect.MCCsect;
817  Csect.Address = alignTo(Address, MCSec->getAlignment());
818  Csect.Size = Layout.getSectionAddressSize(MCSec);
819  Address = Csect.Address + Csect.Size;
820  Csect.SymbolTableIndex = SymbolTableIndex;
821  SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
822  // 1 main and 1 auxiliary symbol table entry for the csect.
823  SymbolTableIndex += 2;
824 
825  for (auto &Sym : Csect.Syms) {
826  Sym.SymbolTableIndex = SymbolTableIndex;
827  SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex;
828  // 1 main and 1 auxiliary symbol table entry for each contained
829  // symbol.
830  SymbolTableIndex += 2;
831  }
832  }
833 
834  if (!SectionAddressSet) {
835  Section->Address = Group->front().Address;
836  SectionAddressSet = true;
837  }
838  }
839 
840  // Make sure the address of the next section aligned to
841  // DefaultSectionAlign.
842  Address = alignTo(Address, DefaultSectionAlign);
843  Section->Size = Address - Section->Address;
844  }
845 
846  SymbolTableEntryCount = SymbolTableIndex;
847 
848  // Calculate the RawPointer value for each section.
849  uint64_t RawPointer = sizeof(XCOFF::FileHeader32) + auxiliaryHeaderSize() +
850  SectionCount * sizeof(XCOFF::SectionHeader32);
851  for (auto *Sec : Sections) {
852  if (Sec->Index == Section::UninitializedIndex || Sec->IsVirtual)
853  continue;
854 
855  Sec->FileOffsetToData = RawPointer;
856  RawPointer += Sec->Size;
857  if (RawPointer > UINT32_MAX)
858  report_fatal_error("Section raw data overflowed this object file.");
859  }
860 
861  RelocationEntryOffset = RawPointer;
862 }
863 
864 // Takes the log base 2 of the alignment and shifts the result into the 5 most
865 // significant bits of a byte, then or's in the csect type into the least
866 // significant 3 bits.
867 uint8_t getEncodedType(const MCSectionXCOFF *Sec) {
868  unsigned Align = Sec->getAlignment();
869  assert(isPowerOf2_32(Align) && "Alignment must be a power of 2.");
870  unsigned Log2Align = Log2_32(Align);
871  // Result is a number in the range [0, 31] which fits in the 5 least
872  // significant bits. Shift this value into the 5 most significant bits, and
873  // bitwise-or in the csect type.
874  uint8_t EncodedAlign = Log2Align << 3;
875  return EncodedAlign | Sec->getCSectType();
876 }
877 
878 } // end anonymous namespace
879 
880 std::unique_ptr<MCObjectWriter>
881 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
882  raw_pwrite_stream &OS) {
883  return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS);
884 }
Negative relocation. Provides the negative of the address of the referenced symbol.
Definition: XCOFF.h:199
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
This class represents lattice values for constants.
Definition: AllocatorList.h:23
This represents an "assembler immediate".
Definition: MCValue.h:37
uint64_t getSectionAddressSize(const MCSection *Sec) const
Get the address space size of the given section, as it effects layout.
Definition: MCFragment.cpp:194
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
TOC Anchor for TOC Addressability.
Definition: XCOFF.h:51
raw_ostream & write_zeros(unsigned NumZeros)
write_zeros - Insert &#39;NumZeros&#39; nulls.
virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1491
Read Write Data.
Definition: XCOFF.h:50
COFF::SymbolStorageClass StorageClass
Definition: COFFYAML.cpp:356
Defines the object file and target independent interfaces used by the assembler backend to write nati...
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:82
unsigned getAlignment() const
Definition: MCSection.h:131
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...
int64_t getConstant() const
Definition: MCValue.h:44
const MCSymbolRefExpr * getSymB() const
Definition: MCValue.h:46
Definition: BitVector.h:959
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
Encapsulates the layout of an assembly file at a particular point in time.
Definition: MCAsmLayout.h:28
StringRef getSymbolTableName() const
MCSymbolXCOFF * getQualNameSymbol() const
void write(raw_ostream &OS) const
StorageClass
Definition: XCOFF.h:103
Utility for building string tables with deduplicated suffixes.
size_t add(CachedHashStringRef S)
Add a string to the builder.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:32
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:160
StringRef getSymbolTableName() const
Definition: MCSymbolXCOFF.h:65
MCSectionXCOFF * getRepresentedCsect() const
Program Code.
Definition: XCOFF.h:38
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition: MathExtras.h:492
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
External reference.
Definition: XCOFF.h:174
virtual void reset()
lifetime management
bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const
Get the offset of the given symbol, as computed in the current layout.
Definition: MCFragment.cpp:148
const MCSymbolRefExpr * getSymA() const
Definition: MCValue.h:45
General TOC item.
Definition: XCOFF.h:52
uint32_t getOffset() const
Definition: MCFixup.h:135
SectionTypeFlags
Definition: XCOFF.h:67
void writeSectionData(raw_ostream &OS, const MCSection *Section, const MCAsmLayout &Layout) const
Emit the section contents to OS.
void finalize()
Analyze the strings and build the final table.
bool isExternal() const
Definition: MCSymbol.h:397
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
std::unique_ptr< MCObjectWriter > createXCOFFObjectWriter(std::unique_ptr< MCXCOFFObjectTargetWriter > MOTW, raw_pwrite_stream &OS)
Common csect definition. For uninitialized storage.
Definition: XCOFF.h:178
uint64_t getFragmentOffset(const MCFragment *F) const
Get the offset of the given fragment inside its containing section.
Definition: MCFragment.cpp:96
XCOFF::SymbolType getCSectType() const
static const X86InstrFMA3Group Groups[]
constexpr size_t NameSize
Definition: XCOFF.h:27
BSS class (uninitialized static internal)
Definition: XCOFF.h:56
size_t getOffset(CachedHashStringRef S) const
Get the offest of a string in the string table.
void write(ArrayRef< value_type > Val)
Definition: EndianStream.h:55
MCAsmBackend & getBackend() const
Definition: MCAssembler.h:292
const MCSymbol & getSymbol() const
Definition: MCExpr.h:397
MCFragment * getFragment(bool SetUsed=true) const
Definition: MCSymbol.h:388
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:883
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition: MathExtras.h:597
bool isDefined() const
isDefined - Check if this symbol is defined (i.e., it has an address).
Definition: MCSymbol.h:241
Target - Wrapper for Target specific information.
MCSection * getParent() const
Definition: MCFragment.h:90
Read Only Constant.
Definition: XCOFF.h:39
Adapter to write values to a stream in a particular byte order.
Definition: EndianStream.h:51
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:158
static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind, bool Deterministic, ArrayRef< MemberData > Members, StringRef StringTable)
XCOFF::StorageMappingClass getMappingClass() const
Positive relocation. Provides the address of the referenced symbol.
Definition: XCOFF.h:194
#define N
constexpr uint16_t RelocOverflow
Definition: XCOFF.h:30
uint32_t Size
Definition: Profile.cpp:46
constexpr size_t RelocationSerializationSize32
Definition: XCOFF.h:29
Relative to the TOC relocation. Provides a displacement that is the difference between the address of...
Definition: XCOFF.h:205
An abstract base class for streams implementations that also support a pwrite operation.
Definition: raw_ostream.h:383
LLVM_NODISCARD const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:152
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isIncrementalLinkerCompatible() const
Definition: MCAssembler.h:313
XCOFF::StorageClass getStorageClass() const
Definition: MCSymbolXCOFF.h:43
Generic interface to target specific assembler backends.
Definition: MCAsmBackend.h:36
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:118
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
Csect definition for initialized storage.
Definition: XCOFF.h:175
MCFixupKind getKind() const
Definition: MCFixup.h:131
Descriptor csect.
Definition: XCOFF.h:54
Label definition. Defines an entry point to an initialized csect.
Definition: XCOFF.h:176