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; + 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,6 +248,7 @@ 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 &, @@ -265,6 +269,10 @@ const DwarfSectionEntry &DwarfEntry, uint32_t &CurrentAddressLocation); void writeSymbolTable(const MCAsmLayout &Layout); + void writeAuxSymbolDwarf(uint64_t, uint64_t); + void writeAuxSymbolCsect(uint64_t, uint8_t, uint8_t); + void writeSymbolBody(StringRef, uint64_t, int16_t, uint16_t, uint8_t, + uint8_t); void writeRelocations(); void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section); @@ -548,10 +556,10 @@ FixedValue = TOCEntryOffset; } - assert( - (TargetObjectWriter->is64Bit() || - Fixup.getOffset() <= UINT32_MAX - Layout.getFragmentOffset(Fragment)) && - "Fragment offset + fixup offset is overflowed in 32-bit mode."); + assert((TargetObjectWriter->is64Bit() || + Fixup.getOffset() <= + MaxRawDataSize - Layout.getFragmentOffset(Fragment)) && + "Fragment offset + fixup offset is overflowed in 32-bit mode."); uint32_t FixupOffsetInCsect = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); @@ -635,22 +643,19 @@ 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::writeSymbolBody(StringRef SymbolName, uint64_t Value, + int16_t SecIdx, uint16_t Type, + uint8_t StorageClass, uint8_t AuxCnt) { + writeSymbolName(SymbolName); // n_name, n_zeros, n_offset + W.write(Value); // n_value + W.write(SecIdx); // n_scnum // 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,111 +663,73 @@ // 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()); + W.write(Type); // n_type + W.write(StorageClass); // n_sclass // 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(AuxCnt); // n_numaux +} + +void XCOFFObjectWriter::writeAuxSymbolCsect(uint64_t SecLen, uint8_t Type, + uint8_t MapClass) { + W.write(Lo_32(SecLen)); // x_scnlen + W.write(0); // x_parmhash + W.write(0); // x_snhash + W.write(Type); // x_smtyp + W.write(MapClass); // x_smclas + W.write(0); // x_stab + W.write(0); // x_snstab +} + +void XCOFFObjectWriter::writeAuxSymbolDwarf(uint64_t SecLen, + uint64_t RelCnt = 0) { + W.write(SecLen); // x_scnlen + W.OS.write_zeros(4); // Reserved + W.write(RelCnt); // x_nreloc + W.OS.write_zeros(6); // Reserved +} + +void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel( + const Symbol &SymbolRef, const XCOFFSection &CSectionRef, + int16_t SectionIndex, uint64_t SymbolOffset) { + assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address && + "Symbol address overflowed."); + + writeSymbolBody(SymbolRef.getSymbolTableName(), + CSectionRef.Address + SymbolOffset, SectionIndex, 0, + SymbolRef.getStorageClass(), 1); + + writeAuxSymbolCsect(CSectionRef.SymbolTableIndex, XCOFF::XTY_LD, + CSectionRef.MCSec->getMappingClass()); } void XCOFFObjectWriter::writeSymbolTableEntryForDwarfSection( 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); + writeSymbolBody(DwarfSectionRef.getSymbolTableName(), 0, SectionIndex, 0, + XCOFF::C_DWARF, 1); + + writeAuxSymbolDwarf(DwarfSectionRef.Size); } void XCOFFObjectWriter::writeSymbolTableEntryForControlSection( 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); + writeSymbolBody(CSectionRef.getSymbolTableName(), CSectionRef.Address, + SectionIndex, 0, StorageClass, 1); + + writeAuxSymbolCsect(CSectionRef.Size, getEncodedType(CSectionRef.MCSec), + CSectionRef.MCSec->getMappingClass()); } void XCOFFObjectWriter::writeFileHeader() { - // Magic. - W.write(0x01df); - // Number of sections. - 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(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(is64Bit() ? XCOFF::XCOFF64 : XCOFF::XCOFF32); + W.write(SectionCount); // f_nscns + W.write(0); // f_timdat + W.write(SymbolTableOffset); // f_symptr + W.write(SymbolTableEntryCount); // f_nsyms + W.write(0); // f_opthdr + W.write(0); // f_flags } void XCOFFObjectWriter::writeSectionHeaderTable() { @@ -779,26 +746,21 @@ // are the same. // We use 0 for DWARF sections' Physical and Virtual Addresses. if (!IsDwarf) { - W.write(Sec->Address); + W.write(Sec->Address); // s_paddr = s_vaddr W.write(Sec->Address); } else { W.write(0); W.write(0); } - W.write(Sec->Size); - W.write(Sec->FileOffsetToData); - W.write(Sec->FileOffsetToRelocations); - - // Line number pointer. Not supported yet. - W.write(0); - - W.write(Sec->RelocationCount); - - // Line number counts. Not supported yet. - W.write(0); + W.write(Sec->Size); // s_size + W.write(Sec->FileOffsetToData); // s_scnptr + W.write(Sec->FileOffsetToRelocations); // s_relptr + W.write(0); // s_lnnoptr. Not supported yet. - W.write(Sec->Flags); + W.write(Sec->RelocationCount); // s_nreloc + W.write(0); // s_nlnno. Not supported yet. + W.write(Sec->Flags); // s_flags return true; }; @@ -848,27 +810,12 @@ 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`. + // 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); + writeSymbolBody(StringRef(".file"), 0, XCOFF::ReservedSectionNum::N_DEBUG, 0, + XCOFF::C_FILE, 0); for (const auto &Csect : UndefinedCsects) { writeSymbolTableEntryForControlSection(Csect, @@ -942,7 +889,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 +1029,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 +1038,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 +1047,7 @@ // Make sure RawPointer is aligned. RawPointer = alignTo(RawPointer, DefaultSectionAlign); - assert(RawPointer <= UINT32_MAX && + assert(RawPointer <= MaxRawDataSize && "Section raw data overflowed this object file."); }