diff --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp --- a/llvm/lib/MC/XCOFFObjectWriter.cpp +++ b/llvm/lib/MC/XCOFFObjectWriter.cpp @@ -198,6 +198,9 @@ std::unique_ptr 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. @@ -245,14 +248,19 @@ uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override; + bool is64Bit() const { return TargetObjectWriter->is64Bit(); } static 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); @@ -265,6 +273,14 @@ const DwarfSectionEntry &DwarfEntry, uint32_t &CurrentAddressLocation); void writeSymbolTable(const MCAsmLayout &Layout); + void writeSymbolAuxDwarfEntry(uint32_t LengthOfSectionPortion, + uint32_t NumberOfRelocEnt = 0); + void writeSymbolAuxCsectEntry(uint32_t SectionOrLength, + uint8_t SymbolAlignmentAndType, + uint8_t StorageMappingClass); + void writeSymbolEntry(StringRef SymbolName, uint32_t Value, + int16_t SectionNumber, uint16_t SymbolType, + uint8_t StorageClass, uint8_t NumberOfAuxEntries = 1); void writeRelocations(); void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section); @@ -397,7 +413,7 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) { - if (TargetObjectWriter->is64Bit()) + if (is64Bit()) report_fatal_error("64-bit XCOFF object files are not supported yet."); for (const auto &S : Asm) { @@ -548,10 +564,9 @@ 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(); @@ -591,6 +606,7 @@ void XCOFFObjectWriter::writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout) { + assert(!is64Bit() && "Writing 64-bit sections is not yet supported."); uint32_t CurrentAddressLocation = 0; for (const auto *Section : Sections) writeSectionForControlSectionEntry(Asm, Layout, *Section, @@ -608,7 +624,7 @@ if (Asm.isIncrementalLinkerCompatible()) report_fatal_error("Incremental linking not supported for XCOFF."); - if (TargetObjectWriter->is64Bit()) + if (is64Bit()) report_fatal_error("64-bit XCOFF object files are not supported yet."); finalizeSectionInfo(); @@ -635,22 +651,21 @@ W.write(0); W.write(Strings.getOffset(SymbolName)); } else { - char Name[XCOFF::NameSize+1]; + char Name[XCOFF::NameSize + 1]; std::strncpy(Name, SymbolName.data(), XCOFF::NameSize); ArrayRef 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(CSectionRef.Address + SymbolOffset); - W.write(SectionIndex); +void XCOFFObjectWriter::writeSymbolEntry(StringRef SymbolName, uint32_t Value, + int16_t SectionNumber, + uint16_t SymbolType, + uint8_t StorageClass, + uint8_t NumberOfAuxEntries) { + writeSymbolName(SymbolName); // n_name, n_zeros, n_offset + W.write(Value); + W.write(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 @@ -658,114 +673,78 @@ // 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(0); - W.write(SymbolRef.getStorageClass()); - // Always 1 aux entry for now. - W.write(1); - - // Now output the auxiliary entry. - W.write(CSectionRef.SymbolTableIndex); - // Parameter typecheck hash. Not supported. - W.write(0); - // Typecheck section number. Not supported. - W.write(0); - // Symbol type: Label - W.write(XCOFF::XTY_LD); - // Storage mapping class. - W.write(CSectionRef.MCSec->getMappingClass()); - // Reserved (x_stab). - W.write(0); - // Reserved (x_snstab). - W.write(0); + W.write(SymbolType); + W.write(StorageClass); + W.write(NumberOfAuxEntries); +} + +void XCOFFObjectWriter::writeSymbolAuxCsectEntry(uint32_t SectionOrLength, + uint8_t SymbolAlignmentAndType, + uint8_t StorageMappingClass) { + W.write(SectionOrLength); + W.write(0); // x_parmhash + W.write(0); // x_snhash + W.write(SymbolAlignmentAndType); + W.write(StorageMappingClass); + W.write(0); // x_stab + W.write(0); // x_snstab +} + +void XCOFFObjectWriter::writeSymbolAuxDwarfEntry( + uint32_t LengthOfSectionPortion, uint32_t NumberOfRelocEnt) { + W.write(LengthOfSectionPortion); + W.OS.write_zeros(4); // Reserved + W.write(NumberOfRelocEnt); + W.OS.write_zeros(6); // Reserved +} + +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, + /* SymbolType */ 0, 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(0); - // n_scnum - W.write(SectionIndex); - // n_type - W.write(0); - // n_sclass - W.write(XCOFF::C_DWARF); - // Always 1 aux entry for now. - W.write(1); - - // Now output the auxiliary entry. - // x_scnlen - W.write(DwarfSectionRef.Size); - // Reserved - W.write(0); - // x_nreloc. Set to 0 for now. - W.write(0); - // Reserved - W.write(0); - // Reserved - W.write(0); + writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), /* Value */ 0, + SectionIndex, /* SymbolType */ 0, XCOFF::C_DWARF); + + 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(CSectionRef.Address); - // n_scnum - W.write(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(0); - // n_sclass - W.write(StorageClass); - // Always 1 aux entry for now. - W.write(1); - - // Now output the auxiliary entry. - W.write(CSectionRef.Size); - // Parameter typecheck hash. Not supported. - W.write(0); - // Typecheck section number. Not supported. - W.write(0); - // Symbol type. - W.write(getEncodedType(CSectionRef.MCSec)); - // Storage mapping class. - W.write(CSectionRef.MCSec->getMappingClass()); - // Reserved (x_stab). - W.write(0); - // Reserved (x_snstab). - W.write(0); + writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address, + SectionIndex, /* SymbolType */ 0, StorageClass); + + writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec), + CSectionRef.MCSec->getMappingClass()); } void XCOFFObjectWriter::writeFileHeader() { - // Magic. - W.write(0x01df); - // Number of sections. + assert(!is64Bit() && "Writing 64-bit file header is not yet supported."); + W.write(XCOFF::XCOFF32); W.write(SectionCount); - // Timestamp field. For reproducible output we write a 0, which represents no - // timestamp. - W.write(0); - // Byte Offset to the start of the symbol table. + W.write(0); // f_timdat W.write(SymbolTableOffset); - // Number of entries in the symbol table. W.write(SymbolTableEntryCount); - // Size of the optional header. - W.write(0); - // Flags. - W.write(0); + W.write(0); // f_opthdr + W.write(0); // f_flags } void XCOFFObjectWriter::writeSectionHeaderTable() { + assert(!is64Bit() && "Writing 64-bit section headers is not yet supported."); auto writeSectionHeader = [&](const SectionEntry *Sec, bool IsDwarf) { // Nothing to write for this Section. if (Sec->Index == SectionEntry::UninitializedIndex) @@ -778,26 +757,16 @@ // 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(Sec->Address); - W.write(Sec->Address); - } else { - W.write(0); - W.write(0); - } + W.write(IsDwarf ? 0 : Sec->Address); // s_paddr = s_vaddr + W.write(IsDwarf ? 0 : Sec->Address); W.write(Sec->Size); W.write(Sec->FileOffsetToData); W.write(Sec->FileOffsetToRelocations); - - // Line number pointer. Not supported yet. - W.write(0); + W.write(0); // s_lnnoptr. Not supported yet. W.write(Sec->RelocationCount); - - // Line number counts. Not supported yet. - W.write(0); - + W.write(0); // s_nlnno. Not supported yet. W.write(Sec->Flags); return true; @@ -811,6 +780,7 @@ void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section) { + assert(!is64Bit() && "Writing 64-bit relocation is not yet supported."); if (Section.MCSec->isCsect()) W.write(Section.Address + Reloc.FixupOffsetInCsect); else { @@ -846,34 +816,20 @@ } void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) { + assert(!is64Bit() && "Writing 64-bit symbol table is not yet supported."); // 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(0); - // n_scnum. N_DEBUG is a reserved section number for indicating a special - // symbolic debugging symbol. - W.write(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(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(XCOFF::C_FILE); - // n_numaux. No aux entry for now. - W.write(0); + // The n_name of a C_FILE symbol is the source file's name when no auxiliary + // entries are present. The source file's name 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 file's name. + writeSymbolEntry(".file", /* Type */ 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) { @@ -888,19 +844,19 @@ 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() { @@ -942,7 +898,7 @@ const uint32_t RelocationSizeInSec = Sec->RelocationCount * XCOFF::RelocationSerializationSize32; RawPointer += RelocationSizeInSec; - if (RawPointer > UINT32_MAX) + if (RawPointer > MaxRawDataSize) report_fatal_error("Relocation data overflowed this object file."); return true; @@ -1082,7 +1038,7 @@ Sec->FileOffsetToData = RawPointer; RawPointer += Sec->Size; - if (RawPointer > UINT32_MAX) + if (RawPointer > MaxRawDataSize) report_fatal_error("Section raw data overflowed this object file."); } @@ -1091,7 +1047,7 @@ // 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()); + alignTo(RawPointer, DwarfSection.DwarfSect->MCSec->getAlignment()); DwarfSection.FileOffsetToData = RawPointer; // Some section entries, like DWARF section size is not aligned, so @@ -1100,7 +1056,7 @@ // Make sure RawPointer is aligned. RawPointer = alignTo(RawPointer, DefaultSectionAlign); - assert(RawPointer <= UINT32_MAX && + assert(RawPointer <= MaxRawDataSize && "Section raw data overflowed this object file."); }