aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/XCOFFObjectWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC/XCOFFObjectWriter.cpp')
-rw-r--r--llvm/lib/MC/XCOFFObjectWriter.cpp474
1 files changed, 253 insertions, 221 deletions
diff --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp
index 177253d7a9d7..977e77bf67fd 100644
--- a/llvm/lib/MC/XCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/XCOFFObjectWriter.cpp
@@ -22,8 +22,9 @@
#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCXCOFFObjectWriter.h"
#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/EndianStream.h"
-#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <deque>
@@ -65,6 +66,10 @@ struct Symbol {
const MCSymbolXCOFF *const MCSym;
uint32_t SymbolTableIndex;
+ XCOFF::VisibilityType getVisibilityType() const {
+ return MCSym->getVisibilityType();
+ }
+
XCOFF::StorageClass getStorageClass() const {
return MCSym->getStorageClass();
}
@@ -77,12 +82,15 @@ struct Symbol {
struct XCOFFSection {
const MCSectionXCOFF *const MCSec;
uint32_t SymbolTableIndex;
- uint32_t Address;
- uint32_t Size;
+ uint64_t Address;
+ uint64_t Size;
SmallVector<Symbol, 1> Syms;
SmallVector<XCOFFRelocation, 1> Relocations;
StringRef getSymbolTableName() const { return MCSec->getSymbolTableName(); }
+ XCOFF::VisibilityType getVisibilityType() const {
+ return MCSec->getVisibilityType();
+ }
XCOFFSection(const MCSectionXCOFF *MCSec)
: MCSec(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
};
@@ -100,10 +108,10 @@ struct SectionEntry {
char Name[XCOFF::NameSize];
// The physical/virtual address of the section. For an object file
// these values are equivalent.
- uint32_t Address;
- uint32_t Size;
- uint32_t FileOffsetToData;
- uint32_t FileOffsetToRelocations;
+ uint64_t Address;
+ uint64_t Size;
+ uint64_t FileOffsetToData;
+ uint64_t FileOffsetToRelocations;
uint32_t RelocationCount;
int32_t Flags;
@@ -136,7 +144,7 @@ struct SectionEntry {
Index = UninitializedIndex;
}
- virtual ~SectionEntry() {}
+ virtual ~SectionEntry() = default;
};
// Represents the data related to a section excluding the csects that make up
@@ -165,16 +173,21 @@ struct CsectSectionEntry : public SectionEntry {
Group->clear();
}
- virtual ~CsectSectionEntry() {}
+ virtual ~CsectSectionEntry() = default;
};
struct DwarfSectionEntry : public SectionEntry {
// For DWARF section entry.
std::unique_ptr<XCOFFSection> DwarfSect;
+ // For DWARF section, we must use real size in the section header. MemorySize
+ // is for the size the DWARF section occupies including paddings.
+ uint32_t MemorySize;
+
DwarfSectionEntry(StringRef N, int32_t Flags,
std::unique_ptr<XCOFFSection> Sect)
- : SectionEntry(N, Flags | XCOFF::STYP_DWARF), DwarfSect(std::move(Sect)) {
+ : SectionEntry(N, Flags | XCOFF::STYP_DWARF), DwarfSect(std::move(Sect)),
+ MemorySize(0) {
assert(DwarfSect->MCSec->isDwarfSect() &&
"This should be a DWARF section!");
assert(N.size() <= XCOFF::NameSize && "section name too long");
@@ -183,20 +196,24 @@ struct DwarfSectionEntry : public SectionEntry {
DwarfSectionEntry(DwarfSectionEntry &&s) = default;
- virtual ~DwarfSectionEntry() {}
+ virtual ~DwarfSectionEntry() = default;
};
class XCOFFObjectWriter : public MCObjectWriter {
uint32_t SymbolTableEntryCount = 0;
- uint32_t SymbolTableOffset = 0;
+ uint64_t SymbolTableOffset = 0;
uint16_t SectionCount = 0;
- uint32_t RelocationEntryOffset = 0;
+ uint64_t RelocationEntryOffset = 0;
+ std::vector<std::pair<std::string, size_t>> FileNames;
support::endian::Writer W;
std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
StringTableBuilder Strings;
+ const uint64_t MaxRawDataSize =
+ TargetObjectWriter->is64Bit() ? UINT64_MAX : UINT32_MAX;
+
// Maps the MCSection representation to its corresponding XCOFFSection
// wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into
// from its containing MCSectionXCOFF.
@@ -244,26 +261,39 @@ class XCOFFObjectWriter : public MCObjectWriter {
uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override;
- static bool nameShouldBeInStringTable(const StringRef &);
+ bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
+ bool nameShouldBeInStringTable(const StringRef &);
void writeSymbolName(const StringRef &);
- void writeSymbolTableEntryForCsectMemberLabel(const Symbol &,
- const XCOFFSection &, int16_t,
- uint64_t);
- void writeSymbolTableEntryForControlSection(const XCOFFSection &, int16_t,
- XCOFF::StorageClass);
- void writeSymbolTableEntryForDwarfSection(const XCOFFSection &, int16_t);
+
+ void writeSymbolEntryForCsectMemberLabel(const Symbol &SymbolRef,
+ const XCOFFSection &CSectionRef,
+ int16_t SectionIndex,
+ uint64_t SymbolOffset);
+ void writeSymbolEntryForControlSection(const XCOFFSection &CSectionRef,
+ int16_t SectionIndex,
+ XCOFF::StorageClass StorageClass);
+ void writeSymbolEntryForDwarfSection(const XCOFFSection &DwarfSectionRef,
+ int16_t SectionIndex);
void writeFileHeader();
void writeSectionHeaderTable();
void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
void writeSectionForControlSectionEntry(const MCAssembler &Asm,
const MCAsmLayout &Layout,
const CsectSectionEntry &CsectEntry,
- uint32_t &CurrentAddressLocation);
+ uint64_t &CurrentAddressLocation);
void writeSectionForDwarfSectionEntry(const MCAssembler &Asm,
const MCAsmLayout &Layout,
const DwarfSectionEntry &DwarfEntry,
- uint32_t &CurrentAddressLocation);
+ uint64_t &CurrentAddressLocation);
void writeSymbolTable(const MCAsmLayout &Layout);
+ void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion,
+ uint64_t NumberOfRelocEnt = 0);
+ void writeSymbolAuxCsectEntry(uint64_t SectionOrLength,
+ uint8_t SymbolAlignmentAndType,
+ uint8_t StorageMappingClass);
+ void writeSymbolEntry(StringRef SymbolName, uint64_t Value,
+ int16_t SectionNumber, uint16_t SymbolType,
+ uint8_t StorageClass, uint8_t NumberOfAuxEntries = 1);
void writeRelocations();
void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section);
@@ -278,10 +308,8 @@ class XCOFFObjectWriter : public MCObjectWriter {
void assignAddressesAndIndices(const MCAsmLayout &);
void finalizeSectionInfo();
- bool
- needsAuxiliaryHeader() const { /* TODO aux header support not implemented. */
- return false;
- }
+ // TODO aux header support not implemented.
+ bool needsAuxiliaryHeader() const { return false; }
// Returns the size of the auxiliary header to be written to the object file.
size_t auxiliaryHeaderSize() const {
@@ -293,6 +321,10 @@ class XCOFFObjectWriter : public MCObjectWriter {
public:
XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
raw_pwrite_stream &OS);
+
+ void writeWord(uint64_t Word) {
+ is64Bit() ? W.write<uint64_t>(Word) : W.write<uint32_t>(Word);
+ }
};
XCOFFObjectWriter::XCOFFObjectWriter(
@@ -396,9 +428,6 @@ static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) {
void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) {
- if (TargetObjectWriter->is64Bit())
- report_fatal_error("64-bit XCOFF object files are not supported yet.");
-
for (const auto &S : Asm) {
const auto *MCSec = cast<const MCSectionXCOFF>(&S);
assert(SectionMap.find(MCSec) == SectionMap.end() &&
@@ -424,7 +453,7 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
SectionMap[MCSec] = DwarfSec.get();
DwarfSectionEntry SecEntry(MCSec->getName(),
- MCSec->getDwarfSubtypeFlags().getValue(),
+ *MCSec->getDwarfSubtypeFlags(),
std::move(DwarfSec));
DwarfSections.push_back(std::move(SecEntry));
} else
@@ -470,6 +499,15 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
Strings.add(XSym->getSymbolTableName());
}
+ FileNames = Asm.getFileNames();
+ // Emit ".file" as the source file name when there is no file name.
+ if (FileNames.empty())
+ FileNames.emplace_back(".file", 0);
+ for (const std::pair<std::string, size_t> &F : FileNames) {
+ if (nameShouldBeInStringTable(F.first))
+ Strings.add(F.first);
+ }
+
Strings.finalize();
assignAddressesAndIndices(Layout);
}
@@ -547,10 +585,9 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
FixedValue = TOCEntryOffset;
}
- assert(
- (TargetObjectWriter->is64Bit() ||
- Fixup.getOffset() <= UINT32_MAX - Layout.getFragmentOffset(Fragment)) &&
- "Fragment offset + fixup offset is overflowed in 32-bit mode.");
+ assert((Fixup.getOffset() <=
+ MaxRawDataSize - Layout.getFragmentOffset(Fragment)) &&
+ "Fragment offset + fixup offset is overflowed.");
uint32_t FixupOffsetInCsect =
Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
@@ -590,7 +627,7 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
const MCAsmLayout &Layout) {
- uint32_t CurrentAddressLocation = 0;
+ uint64_t CurrentAddressLocation = 0;
for (const auto *Section : Sections)
writeSectionForControlSectionEntry(Asm, Layout, *Section,
CurrentAddressLocation);
@@ -607,9 +644,6 @@ uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
if (Asm.isIncrementalLinkerCompatible())
report_fatal_error("Incremental linking not supported for XCOFF.");
- if (TargetObjectWriter->is64Bit())
- report_fatal_error("64-bit XCOFF object files are not supported yet.");
-
finalizeSectionInfo();
uint64_t StartOffset = W.OS.tell();
@@ -617,7 +651,6 @@ uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
writeSectionHeaderTable();
writeSections(Asm, Layout);
writeRelocations();
-
writeSymbolTable(Layout);
// Write the string table.
Strings.write(W.OS);
@@ -626,142 +659,130 @@ uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
}
bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
- return SymbolName.size() > XCOFF::NameSize;
+ return SymbolName.size() > XCOFF::NameSize || is64Bit();
}
void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) {
+ // Magic, Offset or SymbolName.
if (nameShouldBeInStringTable(SymbolName)) {
W.write<int32_t>(0);
W.write<uint32_t>(Strings.getOffset(SymbolName));
} else {
- char Name[XCOFF::NameSize+1];
+ char Name[XCOFF::NameSize + 1];
std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
ArrayRef<char> NameRef(Name, XCOFF::NameSize);
W.write(NameRef);
}
}
-void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel(
- const Symbol &SymbolRef, const XCOFFSection &CSectionRef,
- int16_t SectionIndex, uint64_t SymbolOffset) {
- // Name or Zeros and string table offset
- writeSymbolName(SymbolRef.getSymbolTableName());
- assert(SymbolOffset <= UINT32_MAX - CSectionRef.Address &&
- "Symbol address overflows.");
- W.write<uint32_t>(CSectionRef.Address + SymbolOffset);
- W.write<int16_t>(SectionIndex);
+void XCOFFObjectWriter::writeSymbolEntry(StringRef SymbolName, uint64_t Value,
+ int16_t SectionNumber,
+ uint16_t SymbolType,
+ uint8_t StorageClass,
+ uint8_t NumberOfAuxEntries) {
+ if (is64Bit()) {
+ W.write<uint64_t>(Value);
+ W.write<uint32_t>(Strings.getOffset(SymbolName));
+ } else {
+ writeSymbolName(SymbolName);
+ W.write<uint32_t>(Value);
+ }
+ W.write<int16_t>(SectionNumber);
// Basic/Derived type. See the description of the n_type field for symbol
// table entries for a detailed description. Since we don't yet support
// visibility, and all other bits are either optionally set or reserved, this
// is always zero.
- // TODO FIXME How to assert a symbol's visibilty is default?
+ if (SymbolType != 0)
+ report_fatal_error("Emitting non-zero visibilities is not supported yet.");
// TODO Set the function indicator (bit 10, 0x0020) for functions
// when debugging is enabled.
- W.write<uint16_t>(0);
- W.write<uint8_t>(SymbolRef.getStorageClass());
- // Always 1 aux entry for now.
- W.write<uint8_t>(1);
+ W.write<uint16_t>(SymbolType);
+ W.write<uint8_t>(StorageClass);
+ W.write<uint8_t>(NumberOfAuxEntries);
+}
+
+void XCOFFObjectWriter::writeSymbolAuxCsectEntry(uint64_t SectionOrLength,
+ uint8_t SymbolAlignmentAndType,
+ uint8_t StorageMappingClass) {
+ W.write<uint32_t>(is64Bit() ? Lo_32(SectionOrLength) : SectionOrLength);
+ W.write<uint32_t>(0); // ParameterHashIndex
+ W.write<uint16_t>(0); // TypeChkSectNum
+ W.write<uint8_t>(SymbolAlignmentAndType);
+ W.write<uint8_t>(StorageMappingClass);
+ if (is64Bit()) {
+ W.write<uint32_t>(Hi_32(SectionOrLength));
+ W.OS.write_zeros(1); // Reserved
+ W.write<uint8_t>(XCOFF::AUX_CSECT);
+ } else {
+ W.write<uint32_t>(0); // StabInfoIndex
+ W.write<uint16_t>(0); // StabSectNum
+ }
+}
+
+void XCOFFObjectWriter::writeSymbolAuxDwarfEntry(
+ uint64_t LengthOfSectionPortion, uint64_t NumberOfRelocEnt) {
+ writeWord(LengthOfSectionPortion);
+ if (!is64Bit())
+ W.OS.write_zeros(4); // Reserved
+ writeWord(NumberOfRelocEnt);
+ if (is64Bit()) {
+ W.OS.write_zeros(1); // Reserved
+ W.write<uint8_t>(XCOFF::AUX_SECT);
+ } else {
+ W.OS.write_zeros(6); // Reserved
+ }
+}
- // Now output the auxiliary entry.
- W.write<uint32_t>(CSectionRef.SymbolTableIndex);
- // Parameter typecheck hash. Not supported.
- W.write<uint32_t>(0);
- // Typecheck section number. Not supported.
- W.write<uint16_t>(0);
- // Symbol type: Label
- W.write<uint8_t>(XCOFF::XTY_LD);
- // Storage mapping class.
- W.write<uint8_t>(CSectionRef.MCSec->getMappingClass());
- // Reserved (x_stab).
- W.write<uint32_t>(0);
- // Reserved (x_snstab).
- W.write<uint16_t>(0);
+void XCOFFObjectWriter::writeSymbolEntryForCsectMemberLabel(
+ const Symbol &SymbolRef, const XCOFFSection &CSectionRef,
+ int16_t SectionIndex, uint64_t SymbolOffset) {
+ assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address &&
+ "Symbol address overflowed.");
+
+ writeSymbolEntry(SymbolRef.getSymbolTableName(),
+ CSectionRef.Address + SymbolOffset, SectionIndex,
+ SymbolRef.getVisibilityType(), SymbolRef.getStorageClass());
+
+ writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex, XCOFF::XTY_LD,
+ CSectionRef.MCSec->getMappingClass());
}
-void XCOFFObjectWriter::writeSymbolTableEntryForDwarfSection(
+void XCOFFObjectWriter::writeSymbolEntryForDwarfSection(
const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) {
assert(DwarfSectionRef.MCSec->isDwarfSect() && "Not a DWARF section!");
- // n_name, n_zeros, n_offset
- writeSymbolName(DwarfSectionRef.getSymbolTableName());
- // n_value
- W.write<uint32_t>(0);
- // n_scnum
- W.write<int16_t>(SectionIndex);
- // n_type
- W.write<uint16_t>(0);
- // n_sclass
- W.write<uint8_t>(XCOFF::C_DWARF);
- // Always 1 aux entry for now.
- W.write<uint8_t>(1);
+ writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), /*Value=*/0,
+ SectionIndex, /*SymbolType=*/0, XCOFF::C_DWARF);
- // Now output the auxiliary entry.
- // x_scnlen
- W.write<uint32_t>(DwarfSectionRef.Size);
- // Reserved
- W.write<uint32_t>(0);
- // x_nreloc. Set to 0 for now.
- W.write<uint32_t>(0);
- // Reserved
- W.write<uint32_t>(0);
- // Reserved
- W.write<uint16_t>(0);
+ writeSymbolAuxDwarfEntry(DwarfSectionRef.Size);
}
-void XCOFFObjectWriter::writeSymbolTableEntryForControlSection(
+void XCOFFObjectWriter::writeSymbolEntryForControlSection(
const XCOFFSection &CSectionRef, int16_t SectionIndex,
XCOFF::StorageClass StorageClass) {
- // n_name, n_zeros, n_offset
- writeSymbolName(CSectionRef.getSymbolTableName());
- // n_value
- W.write<uint32_t>(CSectionRef.Address);
- // n_scnum
- W.write<int16_t>(SectionIndex);
- // Basic/Derived type. See the description of the n_type field for symbol
- // table entries for a detailed description. Since we don't yet support
- // visibility, and all other bits are either optionally set or reserved, this
- // is always zero.
- // TODO FIXME How to assert a symbol's visibilty is default?
- // TODO Set the function indicator (bit 10, 0x0020) for functions
- // when debugging is enabled.
- W.write<uint16_t>(0);
- // n_sclass
- W.write<uint8_t>(StorageClass);
- // Always 1 aux entry for now.
- W.write<uint8_t>(1);
+ writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address,
+ SectionIndex, CSectionRef.getVisibilityType(), StorageClass);
- // Now output the auxiliary entry.
- W.write<uint32_t>(CSectionRef.Size);
- // Parameter typecheck hash. Not supported.
- W.write<uint32_t>(0);
- // Typecheck section number. Not supported.
- W.write<uint16_t>(0);
- // Symbol type.
- W.write<uint8_t>(getEncodedType(CSectionRef.MCSec));
- // Storage mapping class.
- W.write<uint8_t>(CSectionRef.MCSec->getMappingClass());
- // Reserved (x_stab).
- W.write<uint32_t>(0);
- // Reserved (x_snstab).
- W.write<uint16_t>(0);
+ writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec),
+ CSectionRef.MCSec->getMappingClass());
}
void XCOFFObjectWriter::writeFileHeader() {
- // Magic.
- W.write<uint16_t>(0x01df);
- // Number of sections.
+ W.write<uint16_t>(is64Bit() ? XCOFF::XCOFF64 : XCOFF::XCOFF32);
W.write<uint16_t>(SectionCount);
- // Timestamp field. For reproducible output we write a 0, which represents no
- // timestamp.
- W.write<int32_t>(0);
- // Byte Offset to the start of the symbol table.
- W.write<uint32_t>(SymbolTableOffset);
- // Number of entries in the symbol table.
- W.write<int32_t>(SymbolTableEntryCount);
- // Size of the optional header.
- W.write<uint16_t>(0);
- // Flags.
- W.write<uint16_t>(0);
+ W.write<int32_t>(0); // TimeStamp
+ writeWord(SymbolTableOffset);
+ if (is64Bit()) {
+ W.write<uint16_t>(0); // AuxHeaderSize. No optional header for an object
+ // file that is not to be loaded.
+ W.write<uint16_t>(0); // Flags
+ W.write<int32_t>(SymbolTableEntryCount);
+ } else {
+ W.write<int32_t>(SymbolTableEntryCount);
+ W.write<uint16_t>(0); // AuxHeaderSize. No optional header for an object
+ // file that is not to be loaded.
+ W.write<uint16_t>(0); // Flags
+ }
}
void XCOFFObjectWriter::writeSectionHeaderTable() {
@@ -777,27 +798,24 @@ void XCOFFObjectWriter::writeSectionHeaderTable() {
// Write the Physical Address and Virtual Address. In an object file these
// are the same.
// We use 0 for DWARF sections' Physical and Virtual Addresses.
- if (!IsDwarf) {
- W.write<uint32_t>(Sec->Address);
- W.write<uint32_t>(Sec->Address);
- } else {
- W.write<uint32_t>(0);
- W.write<uint32_t>(0);
- }
+ writeWord(IsDwarf ? 0 : Sec->Address);
+ writeWord(IsDwarf ? 0 : Sec->Address);
- W.write<uint32_t>(Sec->Size);
- W.write<uint32_t>(Sec->FileOffsetToData);
- W.write<uint32_t>(Sec->FileOffsetToRelocations);
+ writeWord(Sec->Size);
+ writeWord(Sec->FileOffsetToData);
+ writeWord(Sec->FileOffsetToRelocations);
+ writeWord(0); // FileOffsetToLineNumberInfo. Not supported yet.
- // Line number pointer. Not supported yet.
- W.write<uint32_t>(0);
-
- W.write<uint16_t>(Sec->RelocationCount);
-
- // Line number counts. Not supported yet.
- W.write<uint16_t>(0);
-
- W.write<int32_t>(Sec->Flags);
+ if (is64Bit()) {
+ W.write<uint32_t>(Sec->RelocationCount);
+ W.write<uint32_t>(0); // NumberOfLineNumbers. Not supported yet.
+ W.write<int32_t>(Sec->Flags);
+ W.OS.write_zeros(4);
+ } else {
+ W.write<uint16_t>(Sec->RelocationCount);
+ W.write<uint16_t>(0); // NumberOfLineNumbers. Not supported yet.
+ W.write<int32_t>(Sec->Flags);
+ }
return true;
};
@@ -811,11 +829,11 @@ void XCOFFObjectWriter::writeSectionHeaderTable() {
void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
const XCOFFSection &Section) {
if (Section.MCSec->isCsect())
- W.write<uint32_t>(Section.Address + Reloc.FixupOffsetInCsect);
+ writeWord(Section.Address + Reloc.FixupOffsetInCsect);
else {
// DWARF sections' address is set to 0.
assert(Section.MCSec->isDwarfSect() && "unsupport section type!");
- W.write<uint32_t>(Reloc.FixupOffsetInCsect);
+ writeWord(Reloc.FixupOffsetInCsect);
}
W.write<uint32_t>(Reloc.SymbolTableIndex);
W.write<uint8_t>(Reloc.SignAndSize);
@@ -845,34 +863,18 @@ void XCOFFObjectWriter::writeRelocations() {
}
void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
- // Write symbol 0 as C_FILE.
- // FIXME: support 64-bit C_FILE symbol.
- //
- // n_name. The n_name of a C_FILE symbol is the source filename when no
- // auxiliary entries are present. The source filename is alternatively
- // provided by an auxiliary entry, in which case the n_name of the C_FILE
- // symbol is `.file`.
- // FIXME: add the real source filename.
- writeSymbolName(".file");
- // n_value. The n_value of a C_FILE symbol is its symbol table index.
- W.write<uint32_t>(0);
- // n_scnum. N_DEBUG is a reserved section number for indicating a special
- // symbolic debugging symbol.
- W.write<int16_t>(XCOFF::ReservedSectionNum::N_DEBUG);
- // n_type. The n_type field of a C_FILE symbol encodes the source language and
- // CPU version info; zero indicates no info.
- W.write<uint16_t>(0);
- // n_sclass. The C_FILE symbol provides source file-name information,
- // source-language ID and CPU-version ID information and some other optional
- // infos.
- W.write<uint8_t>(XCOFF::C_FILE);
- // n_numaux. No aux entry for now.
- W.write<uint8_t>(0);
+ // Write C_FILE symbols.
+ // The n_name of a C_FILE symbol is the source file's name when no auxiliary
+ // entries are present.
+ for (const std::pair<std::string, size_t> &F : FileNames) {
+ writeSymbolEntry(F.first, /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG,
+ /*SymbolType=*/0, XCOFF::C_FILE,
+ /*NumberOfAuxEntries=*/0);
+ }
for (const auto &Csect : UndefinedCsects) {
- writeSymbolTableEntryForControlSection(Csect,
- XCOFF::ReservedSectionNum::N_UNDEF,
- Csect.MCSec->getStorageClass());
+ writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF,
+ Csect.MCSec->getStorageClass());
}
for (const auto *Section : Sections) {
@@ -887,19 +889,19 @@ void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
const int16_t SectionIndex = Section->Index;
for (const auto &Csect : *Group) {
// Write out the control section first and then each symbol in it.
- writeSymbolTableEntryForControlSection(Csect, SectionIndex,
- Csect.MCSec->getStorageClass());
+ writeSymbolEntryForControlSection(Csect, SectionIndex,
+ Csect.MCSec->getStorageClass());
for (const auto &Sym : Csect.Syms)
- writeSymbolTableEntryForCsectMemberLabel(
+ writeSymbolEntryForCsectMemberLabel(
Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym)));
}
}
}
for (const auto &DwarfSection : DwarfSections)
- writeSymbolTableEntryForDwarfSection(*DwarfSection.DwarfSect,
- DwarfSection.Index);
+ writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect,
+ DwarfSection.Index);
}
void XCOFFObjectWriter::finalizeSectionInfo() {
@@ -914,8 +916,10 @@ void XCOFFObjectWriter::finalizeSectionInfo() {
for (auto &Csect : *Group) {
const size_t CsectRelocCount = Csect.Relocations.size();
- if (CsectRelocCount >= XCOFF::RelocOverflow ||
- Section->RelocationCount >= XCOFF::RelocOverflow - CsectRelocCount)
+ // An XCOFF64 file may not contain an overflow section header.
+ if (!is64Bit() && (CsectRelocCount >= XCOFF::RelocOverflow ||
+ Section->RelocationCount >=
+ XCOFF::RelocOverflow - CsectRelocCount))
report_fatal_error(
"relocation entries overflowed; overflow section is "
"not implemented yet");
@@ -938,10 +942,12 @@ void XCOFFObjectWriter::finalizeSectionInfo() {
return false;
Sec->FileOffsetToRelocations = RawPointer;
- const uint32_t RelocationSizeInSec =
- Sec->RelocationCount * XCOFF::RelocationSerializationSize32;
+ const uint64_t RelocationSizeInSec =
+ Sec->RelocationCount * (is64Bit()
+ ? XCOFF::RelocationSerializationSize64
+ : XCOFF::RelocationSerializationSize32);
RawPointer += RelocationSizeInSec;
- if (RawPointer > UINT32_MAX)
+ if (RawPointer > MaxRawDataSize)
report_fatal_error("Relocation data overflowed this object file.");
return true;
@@ -960,8 +966,8 @@ void XCOFFObjectWriter::finalizeSectionInfo() {
}
void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
- // The first symbol table entry (at index 0) is for the file name.
- uint32_t SymbolTableIndex = 1;
+ // The symbol table starts with all the C_FILE symbols.
+ uint32_t SymbolTableIndex = FileNames.size();
// Calculate indices for undefined symbols.
for (auto &Csect : UndefinedCsects) {
@@ -976,10 +982,11 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
// The address corrresponds to the address of sections and symbols in the
// object file. We place the shared address 0 immediately after the
// section header table.
- uint32_t Address = 0;
+ uint64_t Address = 0;
// Section indices are 1-based in XCOFF.
int32_t SectionIndex = 1;
bool HasTDataSection = false;
+ uint32_t PaddingsBeforeDwarf = 0;
for (auto *Section : Sections) {
const bool IsEmpty =
@@ -1039,6 +1046,19 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
Section->Size = Address - Section->Address;
}
+ // Start to generate DWARF sections. Sections other than DWARF section use
+ // DefaultSectionAlign as the default alignment, while DWARF sections have
+ // their own alignments. If these two alignments are not the same, we need
+ // some paddings here and record the paddings bytes for FileOffsetToData
+ // calculation.
+ if (!DwarfSections.empty())
+ PaddingsBeforeDwarf =
+ alignTo(Address,
+ (*DwarfSections.begin()).DwarfSect->MCSec->getAlignment()) -
+ Address;
+
+ DwarfSectionEntry *LastDwarfSection = nullptr;
+
for (auto &DwarfSection : DwarfSections) {
assert((SectionIndex <= MaxSectionIndex) && "Section index overflow!");
@@ -1066,40 +1086,52 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
// For DWARF section, we must use the real size which may be not aligned.
DwarfSection.Size = DwarfSect.Size = Layout.getSectionAddressSize(MCSec);
- // Make the Address align to default alignment for follow section.
- Address = alignTo(DwarfSect.Address + DwarfSect.Size, DefaultSectionAlign);
+ Address = DwarfSection.Address + DwarfSection.Size;
+
+ if (LastDwarfSection)
+ LastDwarfSection->MemorySize =
+ DwarfSection.Address - LastDwarfSection->Address;
+ LastDwarfSection = &DwarfSection;
+ }
+ if (LastDwarfSection) {
+ // Make the final DWARF section address align to the default section
+ // alignment for follow contents.
+ Address = alignTo(LastDwarfSection->Address + LastDwarfSection->Size,
+ DefaultSectionAlign);
+ LastDwarfSection->MemorySize = Address - LastDwarfSection->Address;
}
SymbolTableEntryCount = SymbolTableIndex;
// Calculate the RawPointer value for each section.
- uint64_t RawPointer = XCOFF::FileHeaderSize32 + auxiliaryHeaderSize() +
- SectionCount * XCOFF::SectionHeaderSize32;
+ uint64_t RawPointer =
+ (is64Bit() ? (XCOFF::FileHeaderSize64 +
+ SectionCount * XCOFF::SectionHeaderSize64)
+ : (XCOFF::FileHeaderSize32 +
+ SectionCount * XCOFF::SectionHeaderSize32)) +
+ auxiliaryHeaderSize();
+
for (auto *Sec : Sections) {
if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual)
continue;
Sec->FileOffsetToData = RawPointer;
RawPointer += Sec->Size;
- if (RawPointer > UINT32_MAX)
+ if (RawPointer > MaxRawDataSize)
report_fatal_error("Section raw data overflowed this object file.");
}
- for (auto &DwarfSection : DwarfSections) {
- // Address of csect sections are always aligned to DefaultSectionAlign, but
- // address of DWARF section are aligned to Section alignment which may be
- // bigger than DefaultSectionAlign, need to execlude the padding bits.
- RawPointer =
- alignTo(RawPointer, DwarfSection.DwarfSect->MCSec->getAlignment());
+ // Increase the raw pointer for the padding bytes between csect sections and
+ // DWARF sections.
+ if (!DwarfSections.empty())
+ RawPointer += PaddingsBeforeDwarf;
+ for (auto &DwarfSection : DwarfSections) {
DwarfSection.FileOffsetToData = RawPointer;
- // Some section entries, like DWARF section size is not aligned, so
- // RawPointer may be not aligned.
- RawPointer += DwarfSection.Size;
- // Make sure RawPointer is aligned.
- RawPointer = alignTo(RawPointer, DefaultSectionAlign);
- assert(RawPointer <= UINT32_MAX &&
+ RawPointer += DwarfSection.MemorySize;
+
+ assert(RawPointer <= MaxRawDataSize &&
"Section raw data overflowed this object file.");
}
@@ -1108,7 +1140,7 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
void XCOFFObjectWriter::writeSectionForControlSectionEntry(
const MCAssembler &Asm, const MCAsmLayout &Layout,
- const CsectSectionEntry &CsectEntry, uint32_t &CurrentAddressLocation) {
+ const CsectSectionEntry &CsectEntry, uint64_t &CurrentAddressLocation) {
// Nothing to write for this Section.
if (CsectEntry.Index == SectionEntry::UninitializedIndex)
return;
@@ -1146,7 +1178,7 @@ void XCOFFObjectWriter::writeSectionForControlSectionEntry(
// The size of the tail padding in a section is the end virtual address of
// the current section minus the the end virtual address of the last csect
// in that section.
- if (uint32_t PaddingSize =
+ if (uint64_t PaddingSize =
CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) {
W.OS.write_zeros(PaddingSize);
CurrentAddressLocation += PaddingSize;
@@ -1155,7 +1187,7 @@ void XCOFFObjectWriter::writeSectionForControlSectionEntry(
void XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
const MCAssembler &Asm, const MCAsmLayout &Layout,
- const DwarfSectionEntry &DwarfEntry, uint32_t &CurrentAddressLocation) {
+ const DwarfSectionEntry &DwarfEntry, uint64_t &CurrentAddressLocation) {
// There could be a gap (without corresponding zero padding) between
// sections. For example DWARF section alignment is bigger than
// DefaultSectionAlign.
@@ -1163,7 +1195,7 @@ void XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
"CurrentAddressLocation should be less than or equal to section "
"address.");
- if (uint32_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation)
+ if (uint64_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation)
W.OS.write_zeros(PaddingSize);
if (DwarfEntry.Size)