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