LLVM  14.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 // 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;
81  uint32_t Size;
82 
85  StringRef getSymbolTableName() const { return MCSec->getSymbolTableName(); }
86  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.
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 =
121 
122  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 
130  virtual void reset() {
131  Address = 0;
132  Size = 0;
133  FileOffsetToData = 0;
134  FileOffsetToRelocations = 0;
135  RelocationCount = 0;
136  Index = UninitializedIndex;
137  }
138 
139  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 
154  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 
161  void reset() override {
162  SectionEntry::reset();
163  // Clear any csects we have stored.
164  for (auto *Group : Groups)
165  Group->clear();
166  }
167 
168  virtual ~CsectSectionEntry() {}
169 };
170 
171 struct DwarfSectionEntry : public SectionEntry {
172  // For DWARF section entry.
173  std::unique_ptr<XCOFFSection> DwarfSect;
174 
175  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 
186  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 
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.
204 
205  // Maps the MCSymbol representation to its corrresponding symbol table index.
206  // Needed for relocation.
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,
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
282  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.
287  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 
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 
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 
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 
391 static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) {
392  if (XSym->isDefined())
393  return cast<MCSectionXCOFF>(XSym->getFragment()->getParent());
394  return XSym->getRepresentedCsect();
395 }
396 
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 
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);
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();
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 ||
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)
575  "relocation for paired relocatable term is not yet supported");
576 
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 
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 
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 
628 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
629  return SymbolName.size() > XCOFF::NameSize;
630 }
631 
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);
640  W.write(NameRef);
641  }
642 }
643 
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 
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 
711 void XCOFFObjectWriter::writeSymbolTableEntryForControlSection(
712  const XCOFFSection &CSectionRef, int16_t SectionIndex,
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 
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 
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 
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 
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 
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,
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 
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)
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 
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 
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 
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.
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>
1201 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
1202  raw_pwrite_stream &OS) {
1203  return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS);
1204 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
alignTo
static int alignTo(int Num, int PowOf2)
Definition: AArch64LoadStoreOptimizer.cpp:1218
llvm::MCSectionXCOFF::getCSectType
XCOFF::SymbolType getCSectType() const
Definition: MCSectionXCOFF.h:98
llvm::XCOFF::XTY_ER
@ XTY_ER
External reference.
Definition: XCOFF.h:197
MathExtras.h
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::MCSymbol
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
llvm::XCOFF::C_DWARF
@ C_DWARF
Definition: XCOFF.h:142
llvm::MCSectionXCOFF
Definition: MCSectionXCOFF.h:32
llvm::MCAsmBackend::getFixupKindInfo
virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
Definition: MCAsmBackend.cpp:74
llvm::XCOFF::XTY_LD
@ XTY_LD
Label definition. Defines an entry point to an initialized csect.
Definition: XCOFF.h:199
llvm::MCSymbol::isExternal
bool isExternal() const
Definition: MCSymbol.h:401
llvm::XCOFF::XMC_TD
@ XMC_TD
Scalar data item in the TOC.
Definition: XCOFF.h:76
llvm::MCSymbolXCOFF::getSymbolTableName
StringRef getSymbolTableName() const
Definition: MCSymbolXCOFF.h:61
llvm::XCOFF::STYP_BSS
@ STYP_BSS
Definition: XCOFF.h:95
llvm::XCOFF::XMC_TE
@ XMC_TE
Symbol mapped at the end of TOC.
Definition: XCOFF.h:84
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:137
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::RISCVFenceField::W
@ W
Definition: RISCVBaseInfo.h:208
llvm::XCOFF::C_FILE
@ C_FILE
Definition: XCOFF.h:128
llvm::XCOFF::SectionHeaderSize32
constexpr size_t SectionHeaderSize32
Definition: XCOFF.h:34
llvm::XCOFF::XMC_PR
@ XMC_PR
Program Code.
Definition: XCOFF.h:61
Error.h
MCAssembler.h
llvm::MCSectionXCOFF::isCsect
bool isCsect() const
Definition: MCSectionXCOFF.h:111
llvm::COFF::NameSize
@ NameSize
Definition: COFF.h:58
llvm::MCSymbol::getFragment
MCFragment * getFragment(bool SetUsed=true) const
Definition: MCSymbol.h:392
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::MCSymbol::isDefined
bool isDefined() const
isDefined - Check if this symbol is defined (i.e., it has an address).
Definition: MCSymbol.h:243
Groups
static const X86InstrFMA3Group Groups[]
Definition: X86InstrFMA3Info.cpp:73
llvm::XCOFF::XMC_TC
@ XMC_TC
General TOC item.
Definition: XCOFF.h:75
llvm::MCFragment::getParent
MCSection * getParent() const
Definition: MCFragment.h:96
MCFixupKindInfo.h
llvm::isPowerOf2_32
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition: MathExtras.h:491
llvm::support::endian::Writer
Adapter to write values to a stream in a particular byte order.
Definition: EndianStream.h:52
llvm::MCSymbolXCOFF::getRepresentedCsect
MCSectionXCOFF * getRepresentedCsect() const
Definition: MCSymbolXCOFF.cpp:13
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::XCOFF::STYP_DWARF
@ STYP_DWARF
Definition: XCOFF.h:92
llvm::createXCOFFObjectWriter
std::unique_ptr< MCObjectWriter > createXCOFFObjectWriter(std::unique_ptr< MCXCOFFObjectTargetWriter > MOTW, raw_pwrite_stream &OS)
Definition: XCOFFObjectWriter.cpp:1201
llvm::ARMBuildAttrs::Section
@ Section
Legacy Tags.
Definition: ARMBuildAttributes.h:82
XCOFF.h
llvm::MCFragment
Definition: MCFragment.h:31
llvm::all_of
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:1600
StringTableBuilder.h
llvm::MCAsmBackend
Generic interface to target specific assembler backends.
Definition: MCAsmBackend.h:36
llvm::XCOFF::XMC_RO
@ XMC_RO
Read Only Constant.
Definition: XCOFF.h:62
MCAsmBackend.h
llvm::XCOFF::R_TLS
@ R_TLS
General-dynamic reference to TLS symbol.
Definition: XCOFF.h:263
StorageClass
COFF::SymbolStorageClass StorageClass
Definition: COFFYAML.cpp:357
llvm::XCOFF::R_POS
@ R_POS
Positive relocation. Provides the address of the referenced symbol.
Definition: XCOFF.h:217
false
Definition: StackSlotColoring.cpp:142
llvm::Log2_32
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:596
llvm::SectionEntry::SectionEntry
SectionEntry(StringRef name, uint8_t *address, size_t size, size_t allocationSize, uintptr_t objAddress)
Definition: RuntimeDyldImpl.h:74
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:143
llvm::MCSectionXCOFF::getMappingClass
XCOFF::StorageMappingClass getMappingClass() const
Definition: MCSectionXCOFF.h:91
llvm::XCOFF::XTY_SD
@ XTY_SD
Csect definition for initialized storage.
Definition: XCOFF.h:198
llvm::XCOFF::N_DEBUG
@ N_DEBUG
Definition: XCOFF.h:42
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
MCSectionXCOFF.h
llvm::MCSymbolXCOFF::getStorageClass
XCOFF::StorageClass getStorageClass() const
Definition: MCSymbolXCOFF.h:41
llvm::MCFixupKindInfo::Flags
unsigned Flags
Flags describing additional information on this fixup kind.
Definition: MCFixupKindInfo.h:45
llvm::XCOFF::R_NEG
@ R_NEG
Negative relocation. Provides the negative of the address of the referenced symbol.
Definition: XCOFF.h:222
llvm::XCOFF::NameSize
constexpr size_t NameSize
Definition: XCOFF.h:29
llvm::XCOFF::STYP_TDATA
@ STYP_TDATA
Definition: XCOFF.h:98
llvm::XCOFF::StorageClass
StorageClass
Definition: XCOFF.h:126
writeSymbolTable
static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind, bool Deterministic, ArrayRef< MemberData > Members, StringRef StringTable)
Definition: ArchiveWriter.cpp:325
llvm::MCAssembler
Definition: MCAssembler.h:60
llvm::DenseMapBase< DenseMap< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::clear
void clear()
Definition: DenseMap.h:111
Index
uint32_t Index
Definition: ELFObjHandler.cpp:84
uint64_t
llvm::raw_pwrite_stream
An abstract base class for streams implementations that also support a pwrite operation.
Definition: raw_ostream.h:417
llvm::XCOFF::XTY_CM
@ XTY_CM
Common csect definition. For uninitialized storage.
Definition: XCOFF.h:201
s
multiplies can be turned into SHL s
Definition: README.txt:370
llvm::XCOFF::XMC_TL
@ XMC_TL
Initialized thread-local variable.
Definition: XCOFF.h:82
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::DenseMap
Definition: DenseMap.h:714
MCSymbolXCOFF.h
MCXCOFFObjectWriter.h
llvm::SectionEntry
SectionEntry - represents a section emitted into memory by the dynamic linker.
Definition: RuntimeDyldImpl.h:45
llvm::HighlightColor::Address
@ Address
llvm::DenseMapBase< DenseMap< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::find
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:150
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1658
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
llvm::ArrayRef< char >
llvm::MCSection::getAlignment
unsigned getAlignment() const
Definition: MCSection.h:138
Fixup
PowerPC TLS Dynamic Call Fixup
Definition: PPCTLSDynamicCall.cpp:233
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
uint32_t
MCFixup.h
llvm::MCObjectWriter
Defines the object file and target independent interfaces used by the assembler backend to write nati...
Definition: MCObjectWriter.h:33
llvm::XCOFF::SectionTypeFlags
SectionTypeFlags
Definition: XCOFF.h:90
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::XCOFF::R_TOC
@ R_TOC
Relative to the TOC relocation. Provides a displacement that is the difference between the address of...
Definition: XCOFF.h:228
llvm::XCOFF::FileHeaderSize32
constexpr size_t FileHeaderSize32
Definition: XCOFF.h:30
llvm::MCAsmLayout::getFragmentOffset
uint64_t getFragmentOffset(const MCFragment *F) const
Get the offset of the given fragment inside its containing section.
Definition: MCFragment.cpp:96
MCAsmLayout.h
llvm::MCSection::getName
StringRef getName() const
Definition: MCSection.h:122
llvm::XCOFF::N_UNDEF
@ N_UNDEF
Definition: XCOFF.h:42
llvm::MCSectionXCOFF::isDwarfSect
bool isDwarfSect() const
Definition: MCSectionXCOFF.h:112
llvm::isInt< 16 >
constexpr bool isInt< 16 >(int64_t x)
Definition: MathExtras.h:370
MCObjectWriter.h
llvm::AMDGPU::HSAMD::Kernel::Key::SymbolName
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
Definition: AMDGPUMetadata.h:381
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
std
Definition: BitVector.h:838
EndianStream.h
uint16_t
llvm::MCAsmLayout
Encapsulates the layout of an assembly file at a particular point in time.
Definition: MCAsmLayout.h:28
llvm::DenseMapBase< DenseMap< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::end
iterator end()
Definition: DenseMap.h:83
llvm::XCOFF::XMC_TC0
@ XMC_TC0
TOC Anchor for TOC Addressability.
Definition: XCOFF.h:74
llvm::MCAsmLayout::getSymbolOffset
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:152
llvm::StringTableBuilder
Utility for building string tables with deduplicated suffixes.
Definition: StringTableBuilder.h:23
MCValue.h
llvm::XCOFF::XMC_DS
@ XMC_DS
Descriptor csect.
Definition: XCOFF.h:77
llvm::ARMBuildAttrs::Symbol
@ Symbol
Definition: ARMBuildAttributes.h:83
llvm::XCOFF::STYP_DATA
@ STYP_DATA
Definition: XCOFF.h:94
llvm::MCSymbolXCOFF
Definition: MCSymbolXCOFF.h:20
llvm::XCOFF::STYP_TEXT
@ STYP_TEXT
Definition: XCOFF.h:93
llvm::XCOFF::XMC_RW
@ XMC_RW
Read Write Data.
Definition: XCOFF.h:73
N
#define N
llvm::MCSectionXCOFF::getQualNameSymbol
MCSymbolXCOFF * getQualNameSymbol() const
Definition: MCSectionXCOFF.h:102
support
Reimplement select in terms of SEL *We would really like to support but we need to prove that the add doesn t need to overflow between the two bit chunks *Implement pre post increment support(e.g. PR935) *Implement smarter const ant generation for binops with large immediates. A few ARMv6T2 ops should be pattern matched
Definition: README.txt:10
llvm::XCOFF::R_TOCL
@ R_TOCL
Relative to TOC lower. Specifies the low-order 16 bits of a large code model TOC-relative relocation.
Definition: XCOFF.h:273
llvm::msgpack::Type
Type
MessagePack types as defined in the standard, with the exception of Integer being divided into a sign...
Definition: MsgPackReader.h:49
llvm::HexStyle::Asm
@ Asm
0ffh
Definition: MCInstPrinter.h:34
llvm::MCValue
This represents an "assembler immediate".
Definition: MCValue.h:37
llvm::XCOFF::RelocationSerializationSize32
constexpr size_t RelocationSerializationSize32
Definition: XCOFF.h:37
llvm::MCSectionXCOFF::getSymbolTableName
StringRef getSymbolTableName() const
Definition: MCSectionXCOFF.h:109
llvm::XCOFF::STYP_TBSS
@ STYP_TBSS
Definition: XCOFF.h:99
llvm::MCAsmLayout::getSectionAddressSize
uint64_t getSectionAddressSize(const MCSection *Sec) const
Get the address space size of the given section, as it effects layout.
Definition: MCFragment.cpp:198
Mod
Module * Mod
Definition: PassBuilderBindings.cpp:54
llvm::MCSectionXCOFF::getDwarfSubtypeFlags
Optional< XCOFF::DwarfSectionSubtypeFlags > getDwarfSubtypeFlags() const
Definition: MCSectionXCOFF.h:113
llvm::XCOFF::XMC_UL
@ XMC_UL
Uninitialized thread-local variable.
Definition: XCOFF.h:83
llvm::MCFixup
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:71
llvm::XCOFF::RelocOverflow
constexpr uint16_t RelocOverflow
Definition: XCOFF.h:39
llvm::XCOFF::R_TLSM
@ R_TLSM
Module reference to TLS. Provides a handle for the module containing the referenced symbol.
Definition: XCOFF.h:267
llvm::Optional::getValue
constexpr const T & getValue() const LLVM_LVALUE_FUNCTION
Definition: Optional.h:282
llvm::support::big
@ big
Definition: Endian.h:27
llvm::XCOFF::XMC_BS
@ XMC_BS
BSS class (uninitialized static internal)
Definition: XCOFF.h:79