virtual ~ExceptionSectionEntry() = default;
};
+struct CInfoSymInfo {
+ // Name of the C_INFO symbol associated with the section
+ std::string Name;
+ std::string Metadata;
+ // Offset into the start of the metadata in the section
+ uint64_t Offset;
+
+ CInfoSymInfo(std::string Name, std::string Metadata)
+ : Name(Name), Metadata(Metadata) {}
+ // Metadata needs to be padded out to an even word size.
+ uint32_t paddingSize() const {
+ return alignTo(Metadata.size(), sizeof(uint32_t)) - Metadata.size();
+ };
+
+ // Total size of the entry, including the 4 byte length
+ uint32_t size() const {
+ return Metadata.size() + paddingSize() + sizeof(uint32_t);
+ };
+};
+
+struct CInfoSymSectionEntry : public SectionEntry {
+ std::unique_ptr<CInfoSymInfo> Entry;
+
+ CInfoSymSectionEntry(StringRef N, int32_t Flags) : SectionEntry(N, Flags) {}
+ virtual ~CInfoSymSectionEntry() = default;
+ void addEntry(std::unique_ptr<CInfoSymInfo> NewEntry) {
+ Entry = std::move(NewEntry);
+ Entry->Offset = sizeof(uint32_t);
+ Size += Entry->size();
+ }
+ void reset() override {
+ SectionEntry::reset();
+ Entry.reset();
+ }
+};
+
class XCOFFObjectWriter : public MCObjectWriter {
uint32_t SymbolTableEntryCount = 0;
std::vector<SectionEntry> OverflowSections;
ExceptionSectionEntry ExceptionSection;
+ CInfoSymSectionEntry CInfoSymSection;
CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
void writeSectionForExceptionSectionEntry(
const MCAssembler &Asm, const MCAsmLayout &Layout,
ExceptionSectionEntry &ExceptionEntry, uint64_t &CurrentAddressLocation);
+ void writeSectionForCInfoSymSectionEntry(const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ CInfoSymSectionEntry &CInfoSymEntry,
+ uint64_t &CurrentAddressLocation);
void writeSymbolTable(const MCAsmLayout &Layout);
void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion,
uint64_t NumberOfRelocEnt = 0);
unsigned getExceptionSectionSize();
unsigned getExceptionOffset(const MCSymbol *Symbol);
+ void addCInfoSymEntry(StringRef Name, StringRef Metadata) override;
size_t auxiliaryHeaderSize() const {
// 64-bit object files have no auxiliary header.
return HasVisibility && !is64Bit() ? XCOFF::AuxFileHeaderSizeShort : 0;
CsectGroups{&TDataCsects}),
TBSS(".tbss", XCOFF::STYP_TBSS, /* IsVirtual */ true,
CsectGroups{&TBSSCsects}),
- ExceptionSection(".except", XCOFF::STYP_EXCEPT) {}
+ ExceptionSection(".except", XCOFF::STYP_EXCEPT),
+ CInfoSymSection(".info", XCOFF::STYP_INFO) {}
void XCOFFObjectWriter::reset() {
// Clear the mappings we created.
for (auto &OverflowSec : OverflowSections)
OverflowSec.reset();
ExceptionSection.reset();
+ CInfoSymSection.reset();
// Reset states in XCOFFObjectWriter.
SymbolTableEntryCount = 0;
Strings.add(XSym->getSymbolTableName());
}
+ std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymSection.Entry;
+ if (CISI && nameShouldBeInStringTable(CISI->Name))
+ Strings.add(CISI->Name);
+
FileNames = Asm.getFileNames();
// Emit ".file" as the source file name when there is no file name.
if (FileNames.empty())
CurrentAddressLocation);
writeSectionForExceptionSectionEntry(Asm, Layout, ExceptionSection,
CurrentAddressLocation);
+ writeSectionForCInfoSymSectionEntry(Asm, Layout, CInfoSymSection,
+ CurrentAddressLocation);
}
uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
writeSectionHeader(&OverflowSec);
if (hasExceptionSection())
writeSectionHeader(&ExceptionSection);
+ if (CInfoSymSection.Entry)
+ writeSectionHeader(&CInfoSymSection);
}
void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
/*NumberOfAuxEntries=*/0);
}
+ if (CInfoSymSection.Entry)
+ writeSymbolEntry(CInfoSymSection.Entry->Name, CInfoSymSection.Entry->Offset,
+ CInfoSymSection.Index,
+ /*SymbolType=*/0, XCOFF::C_INFO,
+ /*NumberOfAuxEntries=*/0);
+
for (const auto &Csect : UndefinedCsects) {
writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF,
Csect.MCSec->getStorageClass());
if (hasExceptionSection())
RawPointer = ExceptionSection.advanceFileOffset(MaxRawDataSize, RawPointer);
+ if (CInfoSymSection.Entry)
+ RawPointer = CInfoSymSection.advanceFileOffset(MaxRawDataSize, RawPointer);
+
for (auto *Sec : Sections) {
if (Sec->Index != SectionEntry::UninitializedIndex)
calcOffsetToRelocations(Sec, RawPointer);
: XCOFF::ExceptionSectionEntrySize32);
}
+void XCOFFObjectWriter::addCInfoSymEntry(StringRef Name, StringRef Metadata) {
+ assert(!CInfoSymSection.Entry && "Multiple entries are not supported");
+ CInfoSymSection.addEntry(
+ std::make_unique<CInfoSymInfo>(Name.str(), Metadata.str()));
+}
+
void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
// The symbol table starts with all the C_FILE symbols.
uint32_t SymbolTableIndex = FileNames.size();
+ if (CInfoSymSection.Entry)
+ SymbolTableIndex++;
+
// Calculate indices for undefined symbols.
for (auto &Csect : UndefinedCsects) {
Csect.Size = 0;
Address = alignTo(Address, DefaultSectionAlign);
}
+ if (CInfoSymSection.Entry) {
+ CInfoSymSection.Index = SectionIndex++;
+ SectionCount++;
+ CInfoSymSection.Address = 0;
+ Address += CInfoSymSection.Size;
+ Address = alignTo(Address, DefaultSectionAlign);
+ }
+
SymbolTableEntryCount = SymbolTableIndex;
}
CurrentAddressLocation += getExceptionSectionSize();
}
+void XCOFFObjectWriter::writeSectionForCInfoSymSectionEntry(
+ const MCAssembler &Asm, const MCAsmLayout &Layout,
+ CInfoSymSectionEntry &CInfoSymEntry, uint64_t &CurrentAddressLocation) {
+ if (!CInfoSymSection.Entry)
+ return;
+
+ constexpr int WordSize = sizeof(uint32_t);
+ std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymEntry.Entry;
+ const std::string &Metadata = CISI->Metadata;
+
+ // Emit the 4-byte length of the metadata.
+ W.write<uint32_t>(Metadata.size());
+
+ if (Metadata.size() == 0)
+ return;
+
+ // Write out the payload one word at a time.
+ size_t Index = 0;
+ while (Index + WordSize <= Metadata.size()) {
+ uint32_t NextWord =
+ llvm::support::endian::read32be(Metadata.data() + Index);
+ W.write<uint32_t>(NextWord);
+ Index += WordSize;
+ }
+
+ // If there is padding, we have at least one byte of payload left to emit.
+ if (CISI->paddingSize()) {
+ std::array<uint8_t, WordSize> LastWord = {0};
+ ::memcpy(LastWord.data(), Metadata.data() + Index, Metadata.size() - Index);
+ W.write<uint32_t>(llvm::support::endian::read32be(LastWord.data()));
+ }
+
+ CurrentAddressLocation += CISI->size();
+}
+
// Takes the log base 2 of the alignment and shifts the result into the 5 most
// significant bits of a byte, then or's in the csect type into the least
// significant 3 bits.
; RUN: llc -mtriple powerpc64-ibm-aix-xcoff < %s | \
; RUN: FileCheck --check-prefix=ASM %s
-; RUN: not --crash llc -mtriple powerpc-ibm-aix-xcoff -filetype=obj < %s 2>&1 | \
+; RUN: llc -mtriple powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s
+; RUN: llvm-objdump --full-contents --section=.info %t.o | \
; RUN: FileCheck --check-prefix=OBJ %s
-; RUN: not --crash llc -mtriple powerpc64-ibm-aix-xcoff -filetype=obj < %s 2>&1 | \
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -filetype=obj -o %t.o < %s
+; RUN: llvm-objdump --full-contents --section=.info %t.o | \
; RUN: FileCheck --check-prefix=OBJ %s
; Verify that llvm.commandline metadata is emitted to .info sections and that the
; metadata is padded if necessary.
-; OBJ: LLVM ERROR: emitXCOFFCInfoSym is not implemented yet on object generation path
-
; ASM: .info ".GCC.command.line", 0x0000003a,
; ASM: .info , 0x40282329, 0x6f707420, 0x636c616e, 0x67202d63, 0x6f6d6d61, 0x6e64202d
; ASM: .info , 0x6c696e65, 0x0a004028, 0x23296f70, 0x7420736f, 0x6d657468, 0x696e6720
; ASM: .info , 0x656c7365, 0x20313233, 0x0a000000
+; OBJ: Contents of section .info:
+; OBJ: 0000 0000003a 40282329 6f707420 636c616e ...:@(#)opt clan
+; OBJ: 0010 67202d63 6f6d6d61 6e64202d 6c696e65 g -command -line
+; OBJ: 0020 0a004028 23296f70 7420736f 6d657468 ..@(#)opt someth
+; OBJ: 0030 696e6720 656c7365 20313233 0a000000 ing else 123....
+
!llvm.commandline = !{!0, !1}
!0 = !{!"clang -command -line"}
!1 = !{!"something else 123"}