MC: Change object writers to use endian::Writer. NFCI.

Part of PR37466.

Differential Revision: https://reviews.llvm.org/D47040

llvm-svn: 332861
This commit is contained in:
Peter Collingbourne 2018-05-21 18:17:42 +00:00
parent 168d04d544
commit f17b149d8c
7 changed files with 382 additions and 371 deletions

View File

@ -116,11 +116,16 @@ class MachObjectWriter : public MCObjectWriter {
MachSymbolData *findSymbolData(const MCSymbol &Sym);
void writeWithPadding(StringRef Str, uint64_t Size);
public:
MachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
raw_pwrite_stream &OS, bool IsLittleEndian)
: MCObjectWriter(OS, IsLittleEndian),
TargetObjectWriter(std::move(MOTW)) {}
TargetObjectWriter(std::move(MOTW)),
W(OS, IsLittleEndian ? support::little : support::big) {}
support::endian::Writer W;
const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const;

View File

@ -160,10 +160,12 @@ class ELFObjectWriter : public MCObjectWriter {
bool ZLibStyle, unsigned Alignment);
public:
support::endian::Writer W;
ELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
raw_pwrite_stream &OS, bool IsLittleEndian)
: MCObjectWriter(OS, IsLittleEndian),
TargetObjectWriter(std::move(MOTW)) {}
: MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(std::move(MOTW)),
W(OS, IsLittleEndian ? support::little : support::big) {}
~ELFObjectWriter() override = default;
@ -175,16 +177,15 @@ public:
MCObjectWriter::reset();
}
void WriteWord(uint64_t W) {
void WriteWord(uint64_t Word) {
if (is64Bit())
write64(W);
W.write<uint64_t>(Word);
else
write32(W);
W.write<uint32_t>(Word);
}
template <typename T> void write(T Val) {
support::endian::write(getStream(), Val,
IsLittleEndian ? support::little : support::big);
W.write(Val);
}
void writeHeader(const MCAssembler &Asm);
@ -255,8 +256,8 @@ public:
} // end anonymous namespace
void ELFObjectWriter::align(unsigned Alignment) {
uint64_t Padding = OffsetToAlignment(getStream().tell(), Alignment);
WriteZeros(Padding);
uint64_t Padding = OffsetToAlignment(W.OS.tell(), Alignment);
W.OS.write_zeros(Padding);
}
unsigned ELFObjectWriter::addToSectionTable(const MCSectionELF *Sec) {
@ -325,47 +326,50 @@ void ELFObjectWriter::writeHeader(const MCAssembler &Asm) {
// emitWord method behaves differently for ELF32 and ELF64, writing
// 4 bytes in the former and 8 in the latter.
writeBytes(ELF::ElfMagic); // e_ident[EI_MAG0] to e_ident[EI_MAG3]
W.OS << ELF::ElfMagic; // e_ident[EI_MAG0] to e_ident[EI_MAG3]
write8(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS]
W.OS << char(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS]
// e_ident[EI_DATA]
write8(isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
W.OS << char(W.Endian == support::little ? ELF::ELFDATA2LSB
: ELF::ELFDATA2MSB);
write8(ELF::EV_CURRENT); // e_ident[EI_VERSION]
W.OS << char(ELF::EV_CURRENT); // e_ident[EI_VERSION]
// e_ident[EI_OSABI]
write8(TargetObjectWriter->getOSABI());
write8(0); // e_ident[EI_ABIVERSION]
W.OS << char(TargetObjectWriter->getOSABI());
W.OS << char(0); // e_ident[EI_ABIVERSION]
WriteZeros(ELF::EI_NIDENT - ELF::EI_PAD);
W.OS.write_zeros(ELF::EI_NIDENT - ELF::EI_PAD);
write16(ELF::ET_REL); // e_type
W.write<uint16_t>(ELF::ET_REL); // e_type
write16(TargetObjectWriter->getEMachine()); // e_machine = target
W.write<uint16_t>(TargetObjectWriter->getEMachine()); // e_machine = target
write32(ELF::EV_CURRENT); // e_version
W.write<uint32_t>(ELF::EV_CURRENT); // e_version
WriteWord(0); // e_entry, no entry point in .o file
WriteWord(0); // e_phoff, no program header for .o
WriteWord(0); // e_shoff = sec hdr table off in bytes
// e_flags = whatever the target wants
write32(Asm.getELFHeaderEFlags());
W.write<uint32_t>(Asm.getELFHeaderEFlags());
// e_ehsize = ELF header size
write16(is64Bit() ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr));
W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Ehdr)
: sizeof(ELF::Elf32_Ehdr));
write16(0); // e_phentsize = prog header entry size
write16(0); // e_phnum = # prog header entries = 0
W.write<uint16_t>(0); // e_phentsize = prog header entry size
W.write<uint16_t>(0); // e_phnum = # prog header entries = 0
// e_shentsize = Section header entry size
write16(is64Bit() ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr));
W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Shdr)
: sizeof(ELF::Elf32_Shdr));
// e_shnum = # of section header ents
write16(0);
W.write<uint16_t>(0);
// e_shstrndx = Section # of '.shstrtab'
assert(StringTableIndex < ELF::SHN_LORESERVE);
write16(StringTableIndex);
W.write<uint16_t>(StringTableIndex);
}
uint64_t ELFObjectWriter::SymbolValue(const MCSymbol &Sym,
@ -784,7 +788,7 @@ void ELFObjectWriter::computeSymbolTable(
SymbolTableIndex = addToSectionTable(SymtabSection);
align(SymtabSection->getAlignment());
uint64_t SecStart = getStream().tell();
uint64_t SecStart = W.OS.tell();
// The first entry is the undefined symbol entry.
Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);
@ -900,7 +904,7 @@ void ELFObjectWriter::computeSymbolTable(
assert(MSD.Symbol->getBinding() != ELF::STB_LOCAL);
}
uint64_t SecEnd = getStream().tell();
uint64_t SecEnd = W.OS.tell();
SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd);
ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes();
@ -910,12 +914,12 @@ void ELFObjectWriter::computeSymbolTable(
}
assert(SymtabShndxSectionIndex != 0);
SecStart = getStream().tell();
SecStart = W.OS.tell();
const MCSectionELF *SymtabShndxSection =
SectionTable[SymtabShndxSectionIndex - 1];
for (uint32_t Index : ShndxIndexes)
write(Index);
SecEnd = getStream().tell();
SecEnd = W.OS.tell();
SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd);
}
@ -976,8 +980,8 @@ bool ELFObjectWriter::maybeWriteCompression(
const StringRef Magic = "ZLIB";
if (Size <= Magic.size() + sizeof(Size) + CompressedContents.size())
return false;
write(ArrayRef<char>(Magic.begin(), Magic.size()));
writeBE64(Size);
W.OS << Magic;
support::endian::write(W.OS, Size, support::big);
return true;
}
@ -996,7 +1000,7 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
MAI->compressDebugSections() != DebugCompressionType::None;
if (!CompressionEnabled || !SectionName.startswith(".debug_") ||
SectionName == ".debug_frame") {
Asm.writeSectionData(getStream(), &Section, Layout);
Asm.writeSectionData(W.OS, &Section, Layout);
return;
}
@ -1013,14 +1017,14 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
StringRef(UncompressedData.data(), UncompressedData.size()),
CompressedContents)) {
consumeError(std::move(E));
getStream() << UncompressedData;
W.OS << UncompressedData;
return;
}
bool ZlibStyle = MAI->compressDebugSections() == DebugCompressionType::Z;
if (!maybeWriteCompression(UncompressedData.size(), CompressedContents,
ZlibStyle, Sec.getAlignment())) {
getStream() << UncompressedData;
W.OS << UncompressedData;
return;
}
@ -1030,7 +1034,7 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
else
// Add "z" prefix to section name. This is zlib-gnu style.
MC.renameELFSection(&Section, (".z" + SectionName.drop_front(1)).str());
getStream() << CompressedContents;
W.OS << CompressedContents;
}
void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type,
@ -1039,14 +1043,14 @@ void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type,
uint32_t Link, uint32_t Info,
uint64_t Alignment,
uint64_t EntrySize) {
write32(Name); // sh_name: index into string table
write32(Type); // sh_type
W.write<uint32_t>(Name); // sh_name: index into string table
W.write<uint32_t>(Type); // sh_type
WriteWord(Flags); // sh_flags
WriteWord(Address); // sh_addr
WriteWord(Offset); // sh_offset
WriteWord(Size); // sh_size
write32(Link); // sh_link
write32(Info); // sh_info
W.write<uint32_t>(Link); // sh_link
W.write<uint32_t>(Info); // sh_info
WriteWord(Alignment); // sh_addralign
WriteWord(EntrySize); // sh_entsize
}
@ -1116,7 +1120,7 @@ void ELFObjectWriter::writeRelocations(const MCAssembler &Asm,
const MCSectionELF *ELFObjectWriter::createStringTable(MCContext &Ctx) {
const MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1];
StrTabBuilder.write(getStream());
StrTabBuilder.write(W.OS);
return StrtabSection;
}
@ -1226,12 +1230,12 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm,
align(Section.getAlignment());
// Remember the offset into the file for this section.
uint64_t SecStart = getStream().tell();
uint64_t SecStart = W.OS.tell();
const MCSymbolELF *SignatureSymbol = Section.getGroup();
writeSectionData(Asm, Section, Layout);
uint64_t SecEnd = getStream().tell();
uint64_t SecEnd = W.OS.tell();
SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd);
MCSectionELF *RelSection = createRelocationSection(Ctx, Section);
@ -1263,7 +1267,7 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm,
align(Group->getAlignment());
// Remember the offset into the file for this section.
uint64_t SecStart = getStream().tell();
uint64_t SecStart = W.OS.tell();
const MCSymbol *SignatureSymbol = Group->getGroup();
assert(SignatureSymbol);
@ -1273,7 +1277,7 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm,
write(SecIndex);
}
uint64_t SecEnd = getStream().tell();
uint64_t SecEnd = W.OS.tell();
SectionOffsets[Group] = std::make_pair(SecStart, SecEnd);
}
@ -1284,54 +1288,52 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm,
align(RelSection->getAlignment());
// Remember the offset into the file for this section.
uint64_t SecStart = getStream().tell();
uint64_t SecStart = W.OS.tell();
writeRelocations(Asm,
cast<MCSectionELF>(*RelSection->getAssociatedSection()));
uint64_t SecEnd = getStream().tell();
uint64_t SecEnd = W.OS.tell();
SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd);
}
{
uint64_t SecStart = getStream().tell();
uint64_t SecStart = W.OS.tell();
const MCSectionELF *Sec = createStringTable(Ctx);
uint64_t SecEnd = getStream().tell();
uint64_t SecEnd = W.OS.tell();
SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd);
}
uint64_t NaturalAlignment = is64Bit() ? 8 : 4;
align(NaturalAlignment);
const uint64_t SectionHeaderOffset = getStream().tell();
const uint64_t SectionHeaderOffset = W.OS.tell();
// ... then the section header table ...
writeSectionHeader(Layout, SectionIndexMap, SectionOffsets);
uint16_t NumSections = (SectionTable.size() + 1 >= ELF::SHN_LORESERVE)
? (uint16_t)ELF::SHN_UNDEF
: SectionTable.size() + 1;
if (sys::IsLittleEndianHost != IsLittleEndian)
sys::swapByteOrder(NumSections);
uint16_t NumSections = support::endian::byte_swap<uint16_t>(
(SectionTable.size() + 1 >= ELF::SHN_LORESERVE) ? (uint16_t)ELF::SHN_UNDEF
: SectionTable.size() + 1,
W.Endian);
unsigned NumSectionsOffset;
auto &Stream = static_cast<raw_pwrite_stream &>(W.OS);
if (is64Bit()) {
uint64_t Val = SectionHeaderOffset;
if (sys::IsLittleEndianHost != IsLittleEndian)
sys::swapByteOrder(Val);
getStream().pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
offsetof(ELF::Elf64_Ehdr, e_shoff));
uint64_t Val =
support::endian::byte_swap<uint64_t>(SectionHeaderOffset, W.Endian);
Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
offsetof(ELF::Elf64_Ehdr, e_shoff));
NumSectionsOffset = offsetof(ELF::Elf64_Ehdr, e_shnum);
} else {
uint32_t Val = SectionHeaderOffset;
if (sys::IsLittleEndianHost != IsLittleEndian)
sys::swapByteOrder(Val);
getStream().pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
offsetof(ELF::Elf32_Ehdr, e_shoff));
uint32_t Val =
support::endian::byte_swap<uint32_t>(SectionHeaderOffset, W.Endian);
Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
offsetof(ELF::Elf32_Ehdr, e_shoff));
NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum);
}
getStream().pwrite(reinterpret_cast<char *>(&NumSections),
sizeof(NumSections), NumSectionsOffset);
Stream.pwrite(reinterpret_cast<char *>(&NumSections), sizeof(NumSections),
NumSectionsOffset);
}
bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(

View File

@ -36,7 +36,7 @@ void MCLOHDirective::emit_impl(raw_ostream &OutStream,
void MCLOHDirective::emit(MachObjectWriter &ObjWriter,
const MCAsmLayout &Layout) const {
raw_ostream &OutStream = ObjWriter.getStream();
raw_ostream &OutStream = ObjWriter.W.OS;
emit_impl(OutStream, ObjWriter, Layout);
}

View File

@ -141,24 +141,29 @@ void MachObjectWriter::writeHeader(MachO::HeaderFileType Type,
// struct mach_header (28 bytes) or
// struct mach_header_64 (32 bytes)
uint64_t Start = getStream().tell();
uint64_t Start = W.OS.tell();
(void) Start;
write32(is64Bit() ? MachO::MH_MAGIC_64 : MachO::MH_MAGIC);
W.write<uint32_t>(is64Bit() ? MachO::MH_MAGIC_64 : MachO::MH_MAGIC);
write32(TargetObjectWriter->getCPUType());
write32(TargetObjectWriter->getCPUSubtype());
W.write<uint32_t>(TargetObjectWriter->getCPUType());
W.write<uint32_t>(TargetObjectWriter->getCPUSubtype());
write32(Type);
write32(NumLoadCommands);
write32(LoadCommandsSize);
write32(Flags);
W.write<uint32_t>(Type);
W.write<uint32_t>(NumLoadCommands);
W.write<uint32_t>(LoadCommandsSize);
W.write<uint32_t>(Flags);
if (is64Bit())
write32(0); // reserved
W.write<uint32_t>(0); // reserved
assert(
getStream().tell() - Start ==
(is64Bit() ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header)));
assert(W.OS.tell() - Start == (is64Bit() ? sizeof(MachO::mach_header_64)
: sizeof(MachO::mach_header)));
}
void MachObjectWriter::writeWithPadding(StringRef Str, uint64_t Size) {
assert(Size >= Str.size());
W.OS << Str;
W.OS.write_zeros(Size - Str.size());
}
/// writeSegmentLoadCommand - Write a segment load command.
@ -172,38 +177,37 @@ void MachObjectWriter::writeSegmentLoadCommand(
// struct segment_command (56 bytes) or
// struct segment_command_64 (72 bytes)
uint64_t Start = getStream().tell();
uint64_t Start = W.OS.tell();
(void) Start;
unsigned SegmentLoadCommandSize =
is64Bit() ? sizeof(MachO::segment_command_64):
sizeof(MachO::segment_command);
write32(is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT);
write32(SegmentLoadCommandSize +
W.write<uint32_t>(is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT);
W.write<uint32_t>(SegmentLoadCommandSize +
NumSections * (is64Bit() ? sizeof(MachO::section_64) :
sizeof(MachO::section)));
assert(Name.size() <= 16);
writeBytes(Name, 16);
writeWithPadding(Name, 16);
if (is64Bit()) {
write64(VMAddr); // vmaddr
write64(VMSize); // vmsize
write64(SectionDataStartOffset); // file offset
write64(SectionDataSize); // file size
W.write<uint64_t>(VMAddr); // vmaddr
W.write<uint64_t>(VMSize); // vmsize
W.write<uint64_t>(SectionDataStartOffset); // file offset
W.write<uint64_t>(SectionDataSize); // file size
} else {
write32(VMAddr); // vmaddr
write32(VMSize); // vmsize
write32(SectionDataStartOffset); // file offset
write32(SectionDataSize); // file size
W.write<uint32_t>(VMAddr); // vmaddr
W.write<uint32_t>(VMSize); // vmsize
W.write<uint32_t>(SectionDataStartOffset); // file offset
W.write<uint32_t>(SectionDataSize); // file size
}
// maxprot
write32(MaxProt);
W.write<uint32_t>(MaxProt);
// initprot
write32(InitProt);
write32(NumSections);
write32(0); // flags
W.write<uint32_t>(InitProt);
W.write<uint32_t>(NumSections);
W.write<uint32_t>(0); // flags
assert(getStream().tell() - Start == SegmentLoadCommandSize);
assert(W.OS.tell() - Start == SegmentLoadCommandSize);
}
void MachObjectWriter::writeSection(const MCAsmLayout &Layout,
@ -223,31 +227,31 @@ void MachObjectWriter::writeSection(const MCAsmLayout &Layout,
// struct section (68 bytes) or
// struct section_64 (80 bytes)
uint64_t Start = getStream().tell();
uint64_t Start = W.OS.tell();
(void) Start;
writeBytes(Section.getSectionName(), 16);
writeBytes(Section.getSegmentName(), 16);
writeWithPadding(Section.getSectionName(), 16);
writeWithPadding(Section.getSegmentName(), 16);
if (is64Bit()) {
write64(VMAddr); // address
write64(SectionSize); // size
W.write<uint64_t>(VMAddr); // address
W.write<uint64_t>(SectionSize); // size
} else {
write32(VMAddr); // address
write32(SectionSize); // size
W.write<uint32_t>(VMAddr); // address
W.write<uint32_t>(SectionSize); // size
}
write32(FileOffset);
W.write<uint32_t>(FileOffset);
assert(isPowerOf2_32(Section.getAlignment()) && "Invalid alignment!");
write32(Log2_32(Section.getAlignment()));
write32(NumRelocations ? RelocationsStart : 0);
write32(NumRelocations);
write32(Flags);
write32(IndirectSymBase.lookup(&Sec)); // reserved1
write32(Section.getStubSize()); // reserved2
W.write<uint32_t>(Log2_32(Section.getAlignment()));
W.write<uint32_t>(NumRelocations ? RelocationsStart : 0);
W.write<uint32_t>(NumRelocations);
W.write<uint32_t>(Flags);
W.write<uint32_t>(IndirectSymBase.lookup(&Sec)); // reserved1
W.write<uint32_t>(Section.getStubSize()); // reserved2
if (is64Bit())
write32(0); // reserved3
W.write<uint32_t>(0); // reserved3
assert(getStream().tell() - Start ==
assert(W.OS.tell() - Start ==
(is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section)));
}
@ -257,17 +261,17 @@ void MachObjectWriter::writeSymtabLoadCommand(uint32_t SymbolOffset,
uint32_t StringTableSize) {
// struct symtab_command (24 bytes)
uint64_t Start = getStream().tell();
uint64_t Start = W.OS.tell();
(void) Start;
write32(MachO::LC_SYMTAB);
write32(sizeof(MachO::symtab_command));
write32(SymbolOffset);
write32(NumSymbols);
write32(StringTableOffset);
write32(StringTableSize);
W.write<uint32_t>(MachO::LC_SYMTAB);
W.write<uint32_t>(sizeof(MachO::symtab_command));
W.write<uint32_t>(SymbolOffset);
W.write<uint32_t>(NumSymbols);
W.write<uint32_t>(StringTableOffset);
W.write<uint32_t>(StringTableSize);
assert(getStream().tell() - Start == sizeof(MachO::symtab_command));
assert(W.OS.tell() - Start == sizeof(MachO::symtab_command));
}
void MachObjectWriter::writeDysymtabLoadCommand(uint32_t FirstLocalSymbol,
@ -280,31 +284,31 @@ void MachObjectWriter::writeDysymtabLoadCommand(uint32_t FirstLocalSymbol,
uint32_t NumIndirectSymbols) {
// struct dysymtab_command (80 bytes)
uint64_t Start = getStream().tell();
uint64_t Start = W.OS.tell();
(void) Start;
write32(MachO::LC_DYSYMTAB);
write32(sizeof(MachO::dysymtab_command));
write32(FirstLocalSymbol);
write32(NumLocalSymbols);
write32(FirstExternalSymbol);
write32(NumExternalSymbols);
write32(FirstUndefinedSymbol);
write32(NumUndefinedSymbols);
write32(0); // tocoff
write32(0); // ntoc
write32(0); // modtaboff
write32(0); // nmodtab
write32(0); // extrefsymoff
write32(0); // nextrefsyms
write32(IndirectSymbolOffset);
write32(NumIndirectSymbols);
write32(0); // extreloff
write32(0); // nextrel
write32(0); // locreloff
write32(0); // nlocrel
W.write<uint32_t>(MachO::LC_DYSYMTAB);
W.write<uint32_t>(sizeof(MachO::dysymtab_command));
W.write<uint32_t>(FirstLocalSymbol);
W.write<uint32_t>(NumLocalSymbols);
W.write<uint32_t>(FirstExternalSymbol);
W.write<uint32_t>(NumExternalSymbols);
W.write<uint32_t>(FirstUndefinedSymbol);
W.write<uint32_t>(NumUndefinedSymbols);
W.write<uint32_t>(0); // tocoff
W.write<uint32_t>(0); // ntoc
W.write<uint32_t>(0); // modtaboff
W.write<uint32_t>(0); // nmodtab
W.write<uint32_t>(0); // extrefsymoff
W.write<uint32_t>(0); // nextrefsyms
W.write<uint32_t>(IndirectSymbolOffset);
W.write<uint32_t>(NumIndirectSymbols);
W.write<uint32_t>(0); // extreloff
W.write<uint32_t>(0); // nextrel
W.write<uint32_t>(0); // locreloff
W.write<uint32_t>(0); // nlocrel
assert(getStream().tell() - Start == sizeof(MachO::dysymtab_command));
assert(W.OS.tell() - Start == sizeof(MachO::dysymtab_command));
}
MachObjectWriter::MachSymbolData *
@ -384,33 +388,33 @@ void MachObjectWriter::writeNlist(MachSymbolData &MSD,
// struct nlist (12 bytes)
write32(MSD.StringIndex);
write8(Type);
write8(SectionIndex);
W.write<uint32_t>(MSD.StringIndex);
W.OS << char(Type);
W.OS << char(SectionIndex);
// The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
// value.
bool EncodeAsAltEntry =
IsAlias && cast<MCSymbolMachO>(OrigSymbol).isAltEntry();
write16(cast<MCSymbolMachO>(Symbol)->getEncodedFlags(EncodeAsAltEntry));
W.write<uint16_t>(cast<MCSymbolMachO>(Symbol)->getEncodedFlags(EncodeAsAltEntry));
if (is64Bit())
write64(Address);
W.write<uint64_t>(Address);
else
write32(Address);
W.write<uint32_t>(Address);
}
void MachObjectWriter::writeLinkeditLoadCommand(uint32_t Type,
uint32_t DataOffset,
uint32_t DataSize) {
uint64_t Start = getStream().tell();
uint64_t Start = W.OS.tell();
(void) Start;
write32(Type);
write32(sizeof(MachO::linkedit_data_command));
write32(DataOffset);
write32(DataSize);
W.write<uint32_t>(Type);
W.write<uint32_t>(sizeof(MachO::linkedit_data_command));
W.write<uint32_t>(DataOffset);
W.write<uint32_t>(DataSize);
assert(getStream().tell() - Start == sizeof(MachO::linkedit_data_command));
assert(W.OS.tell() - Start == sizeof(MachO::linkedit_data_command));
}
static unsigned ComputeLinkerOptionsLoadCommandSize(
@ -426,23 +430,23 @@ void MachObjectWriter::writeLinkerOptionsLoadCommand(
const std::vector<std::string> &Options)
{
unsigned Size = ComputeLinkerOptionsLoadCommandSize(Options, is64Bit());
uint64_t Start = getStream().tell();
uint64_t Start = W.OS.tell();
(void) Start;
write32(MachO::LC_LINKER_OPTION);
write32(Size);
write32(Options.size());
W.write<uint32_t>(MachO::LC_LINKER_OPTION);
W.write<uint32_t>(Size);
W.write<uint32_t>(Options.size());
uint64_t BytesWritten = sizeof(MachO::linker_option_command);
for (const std::string &Option : Options) {
// Write each string, including the null byte.
writeBytes(Option, Option.size() + 1);
W.OS << Option << '\0';
BytesWritten += Option.size() + 1;
}
// Pad to a multiple of the pointer size.
writeBytes("", OffsetToAlignment(BytesWritten, is64Bit() ? 8 : 4));
W.OS.write_zeros(OffsetToAlignment(BytesWritten, is64Bit() ? 8 : 4));
assert(getStream().tell() - Start == Size);
assert(W.OS.tell() - Start == Size);
}
void MachObjectWriter::recordRelocation(MCAssembler &Asm,
@ -611,7 +615,7 @@ void MachObjectWriter::computeSymbolTable(
// Set the Index and the IsExtern bit.
unsigned Index = Rel.Sym->getIndex();
assert(isInt<24>(Index));
if (IsLittleEndian)
if (W.Endian == support::little)
Rel.MRE.r_word1 = (Rel.MRE.r_word1 & (~0U << 24)) | Index | (1 << 27);
else
Rel.MRE.r_word1 = (Rel.MRE.r_word1 & 0xff) | Index << 8 | (1 << 4);
@ -847,19 +851,19 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
(VersionInfo.Major << 16);
if (VersionInfo.EmitBuildVersion) {
// FIXME: Currently empty tools. Add clang version in the future.
write32(MachO::LC_BUILD_VERSION);
write32(sizeof(MachO::build_version_command));
write32(VersionInfo.TypeOrPlatform.Platform);
write32(EncodedVersion);
write32(0); // SDK version.
write32(0); // Empty tools list.
W.write<uint32_t>(MachO::LC_BUILD_VERSION);
W.write<uint32_t>(sizeof(MachO::build_version_command));
W.write<uint32_t>(VersionInfo.TypeOrPlatform.Platform);
W.write<uint32_t>(EncodedVersion);
W.write<uint32_t>(0); // SDK version.
W.write<uint32_t>(0); // Empty tools list.
} else {
MachO::LoadCommandType LCType
= getLCFromMCVM(VersionInfo.TypeOrPlatform.Type);
write32(LCType);
write32(sizeof(MachO::version_min_command));
write32(EncodedVersion);
write32(0); // reserved.
W.write<uint32_t>(LCType);
W.write<uint32_t>(sizeof(MachO::version_min_command));
W.write<uint32_t>(EncodedVersion);
W.write<uint32_t>(0); // reserved.
}
}
@ -919,14 +923,14 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
// Write the actual section data.
for (const MCSection &Sec : Asm) {
Asm.writeSectionData(getStream(), &Sec, Layout);
Asm.writeSectionData(W.OS, &Sec, Layout);
uint64_t Pad = getPaddingSize(&Sec, Layout);
WriteZeros(Pad);
W.OS.write_zeros(Pad);
}
// Write the extra padding.
WriteZeros(SectionDataPadding);
W.OS.write_zeros(SectionDataPadding);
// Write the relocation entries.
for (const MCSection &Sec : Asm) {
@ -934,8 +938,8 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
// (approximately, the exact algorithm is more complicated than this).
std::vector<RelAndSymbol> &Relocs = Relocations[&Sec];
for (const RelAndSymbol &Rel : make_range(Relocs.rbegin(), Relocs.rend())) {
write32(Rel.MRE.r_word0);
write32(Rel.MRE.r_word1);
W.write<uint32_t>(Rel.MRE.r_word0);
W.write<uint32_t>(Rel.MRE.r_word1);
}
}
@ -956,20 +960,20 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
<< ")"
<< " end: " << End << "(" << Data->End->getName() << ")"
<< " size: " << End - Start << "\n");
write32(Start);
write16(End - Start);
write16(Data->Kind);
W.write<uint32_t>(Start);
W.write<uint16_t>(End - Start);
W.write<uint16_t>(Data->Kind);
}
// Write out the loh commands, if there is one.
if (LOHSize) {
#ifndef NDEBUG
unsigned Start = getStream().tell();
unsigned Start = W.OS.tell();
#endif
Asm.getLOHContainer().emit(*this, Layout);
// Pad to a multiple of the pointer size.
writeBytes("", OffsetToAlignment(LOHRawSize, is64Bit() ? 8 : 4));
assert(getStream().tell() - Start == LOHSize);
W.OS.write_zeros(OffsetToAlignment(LOHRawSize, is64Bit() ? 8 : 4));
assert(W.OS.tell() - Start == LOHSize);
}
// Write the symbol table data, if used.
@ -988,12 +992,12 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
uint32_t Flags = MachO::INDIRECT_SYMBOL_LOCAL;
if (it->Symbol->isAbsolute())
Flags |= MachO::INDIRECT_SYMBOL_ABS;
write32(Flags);
W.write<uint32_t>(Flags);
continue;
}
}
write32(it->Symbol->getIndex());
W.write<uint32_t>(it->Symbol->getIndex());
}
// FIXME: Check that offsets match computed ones.
@ -1005,7 +1009,7 @@ void MachObjectWriter::writeObject(MCAssembler &Asm,
writeNlist(Entry, Layout);
// Write the string table.
StringTable.write(getStream());
StringTable.write(W.OS);
}
}

View File

@ -196,6 +196,8 @@ raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
#endif
class WasmObjectWriter : public MCObjectWriter {
support::endian::Writer W;
/// The target specific Wasm writer instance.
std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
@ -250,7 +252,7 @@ class WasmObjectWriter : public MCObjectWriter {
public:
WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
raw_pwrite_stream &OS)
: MCObjectWriter(OS, /*IsLittleEndian=*/true),
: MCObjectWriter(OS, /*IsLittleEndian=*/true), W(OS, support::little),
TargetObjectWriter(std::move(MOTW)) {}
~WasmObjectWriter() override;
@ -286,12 +288,12 @@ private:
void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
void writeString(const StringRef Str) {
encodeULEB128(Str.size(), getStream());
writeBytes(Str);
encodeULEB128(Str.size(), W.OS);
W.OS << Str;
}
void writeValueType(wasm::ValType Ty) {
write8(static_cast<uint8_t>(Ty));
W.OS << static_cast<char>(Ty);
}
void writeTypeSection(ArrayRef<WasmFunctionType> FunctionTypes);
@ -333,17 +335,17 @@ WasmObjectWriter::~WasmObjectWriter() {}
void WasmObjectWriter::startSection(SectionBookkeeping &Section,
unsigned SectionId) {
LLVM_DEBUG(dbgs() << "startSection " << SectionId << "\n");
write8(SectionId);
W.OS << char(SectionId);
Section.SizeOffset = getStream().tell();
Section.SizeOffset = W.OS.tell();
// The section size. We don't know the size yet, so reserve enough space
// for any 32-bit value; we'll patch it later.
encodeULEB128(UINT32_MAX, getStream());
encodeULEB128(UINT32_MAX, W.OS);
// The position where the section starts, for measuring its size.
Section.ContentsOffset = getStream().tell();
Section.PayloadOffset = getStream().tell();
Section.ContentsOffset = W.OS.tell();
Section.PayloadOffset = W.OS.tell();
Section.Index = SectionCount++;
}
@ -353,19 +355,19 @@ void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
startSection(Section, wasm::WASM_SEC_CUSTOM);
// The position where the section header ends, for measuring its size.
Section.PayloadOffset = getStream().tell();
Section.PayloadOffset = W.OS.tell();
// Custom sections in wasm also have a string identifier.
writeString(Name);
// The position where the custom section starts.
Section.ContentsOffset = getStream().tell();
Section.ContentsOffset = W.OS.tell();
}
// Now that the section is complete and we know how big it is, patch up the
// section size field at the start of the section.
void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
uint64_t Size = getStream().tell() - Section.PayloadOffset;
uint64_t Size = W.OS.tell() - Section.PayloadOffset;
if (uint32_t(Size) != Size)
report_fatal_error("section size does not fit in a uint32_t");
@ -376,13 +378,14 @@ void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
uint8_t Buffer[16];
unsigned SizeLen = encodeULEB128(Size, Buffer, 5);
assert(SizeLen == 5);
getStream().pwrite((char *)Buffer, SizeLen, Section.SizeOffset);
static_cast<raw_pwrite_stream &>(W.OS).pwrite((char *)Buffer, SizeLen,
Section.SizeOffset);
}
// Emit the Wasm header.
void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {
writeBytes(StringRef(wasm::WasmMagic, sizeof(wasm::WasmMagic)));
writeLE32(wasm::WasmVersion);
W.OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
W.write<uint32_t>(wasm::WasmVersion);
}
void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
@ -662,7 +665,7 @@ WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) {
// directly.
void WasmObjectWriter::applyRelocations(
ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset) {
raw_pwrite_stream &Stream = getStream();
auto &Stream = static_cast<raw_pwrite_stream &>(W.OS);
for (const WasmRelocationEntry &RelEntry : Relocations) {
uint64_t Offset = ContentsOffset +
RelEntry.FixupSection->getSectionOffset() +
@ -702,14 +705,14 @@ void WasmObjectWriter::writeTypeSection(
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_TYPE);
encodeULEB128(FunctionTypes.size(), getStream());
encodeULEB128(FunctionTypes.size(), W.OS);
for (const WasmFunctionType &FuncTy : FunctionTypes) {
write8(wasm::WASM_TYPE_FUNC);
encodeULEB128(FuncTy.Params.size(), getStream());
W.OS << char(wasm::WASM_TYPE_FUNC);
encodeULEB128(FuncTy.Params.size(), W.OS);
for (wasm::ValType Ty : FuncTy.Params)
writeValueType(Ty);
encodeULEB128(FuncTy.Returns.size(), getStream());
encodeULEB128(FuncTy.Returns.size(), W.OS);
for (wasm::ValType Ty : FuncTy.Returns)
writeValueType(Ty);
}
@ -728,28 +731,28 @@ void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_IMPORT);
encodeULEB128(Imports.size(), getStream());
encodeULEB128(Imports.size(), W.OS);
for (const wasm::WasmImport &Import : Imports) {
writeString(Import.Module);
writeString(Import.Field);
write8(Import.Kind);
W.OS << char(Import.Kind);
switch (Import.Kind) {
case wasm::WASM_EXTERNAL_FUNCTION:
encodeULEB128(Import.SigIndex, getStream());
encodeULEB128(Import.SigIndex, W.OS);
break;
case wasm::WASM_EXTERNAL_GLOBAL:
write8(Import.Global.Type);
write8(Import.Global.Mutable ? 1 : 0);
W.OS << char(Import.Global.Type);
W.OS << char(Import.Global.Mutable ? 1 : 0);
break;
case wasm::WASM_EXTERNAL_MEMORY:
encodeULEB128(0, getStream()); // flags
encodeULEB128(NumPages, getStream()); // initial
encodeULEB128(0, W.OS); // flags
encodeULEB128(NumPages, W.OS); // initial
break;
case wasm::WASM_EXTERNAL_TABLE:
write8(Import.Table.ElemType);
encodeULEB128(0, getStream()); // flags
encodeULEB128(NumElements, getStream()); // initial
W.OS << char(Import.Table.ElemType);
encodeULEB128(0, W.OS); // flags
encodeULEB128(NumElements, W.OS); // initial
break;
default:
llvm_unreachable("unsupported import kind");
@ -766,9 +769,9 @@ void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_FUNCTION);
encodeULEB128(Functions.size(), getStream());
encodeULEB128(Functions.size(), W.OS);
for (const WasmFunction &Func : Functions)
encodeULEB128(Func.Type, getStream());
encodeULEB128(Func.Type, W.OS);
endSection(Section);
}
@ -780,14 +783,14 @@ void WasmObjectWriter::writeGlobalSection() {
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_GLOBAL);
encodeULEB128(Globals.size(), getStream());
encodeULEB128(Globals.size(), W.OS);
for (const WasmGlobal &Global : Globals) {
writeValueType(static_cast<wasm::ValType>(Global.Type.Type));
write8(Global.Type.Mutable);
W.OS << char(Global.Type.Mutable);
write8(wasm::WASM_OPCODE_I32_CONST);
encodeSLEB128(Global.InitialValue, getStream());
write8(wasm::WASM_OPCODE_END);
W.OS << char(wasm::WASM_OPCODE_I32_CONST);
encodeSLEB128(Global.InitialValue, W.OS);
W.OS << char(wasm::WASM_OPCODE_END);
}
endSection(Section);
@ -800,11 +803,11 @@ void WasmObjectWriter::writeExportSection(ArrayRef<wasm::WasmExport> Exports) {
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_EXPORT);
encodeULEB128(Exports.size(), getStream());
encodeULEB128(Exports.size(), W.OS);
for (const wasm::WasmExport &Export : Exports) {
writeString(Export.Name);
write8(Export.Kind);
encodeULEB128(Export.Index, getStream());
W.OS << char(Export.Kind);
encodeULEB128(Export.Index, W.OS);
}
endSection(Section);
@ -817,17 +820,17 @@ void WasmObjectWriter::writeElemSection(ArrayRef<uint32_t> TableElems) {
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_ELEM);
encodeULEB128(1, getStream()); // number of "segments"
encodeULEB128(0, getStream()); // the table index
encodeULEB128(1, W.OS); // number of "segments"
encodeULEB128(0, W.OS); // the table index
// init expr for starting offset
write8(wasm::WASM_OPCODE_I32_CONST);
encodeSLEB128(kInitialTableOffset, getStream());
write8(wasm::WASM_OPCODE_END);
W.OS << char(wasm::WASM_OPCODE_I32_CONST);
encodeSLEB128(kInitialTableOffset, W.OS);
W.OS << char(wasm::WASM_OPCODE_END);
encodeULEB128(TableElems.size(), getStream());
encodeULEB128(TableElems.size(), W.OS);
for (uint32_t Elem : TableElems)
encodeULEB128(Elem, getStream());
encodeULEB128(Elem, W.OS);
endSection(Section);
}
@ -842,7 +845,7 @@ void WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
startSection(Section, wasm::WASM_SEC_CODE);
CodeSectionIndex = Section.Index;
encodeULEB128(Functions.size(), getStream());
encodeULEB128(Functions.size(), W.OS);
for (const WasmFunction &Func : Functions) {
auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection());
@ -851,9 +854,9 @@ void WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
report_fatal_error(".size expression must be evaluatable");
encodeULEB128(Size, getStream());
FuncSection.setSectionOffset(getStream().tell() - Section.ContentsOffset);
Asm.writeSectionData(getStream(), &FuncSection, Layout);
encodeULEB128(Size, W.OS);
FuncSection.setSectionOffset(W.OS.tell() - Section.ContentsOffset);
Asm.writeSectionData(W.OS, &FuncSection, Layout);
}
// Apply fixups.
@ -870,16 +873,16 @@ void WasmObjectWriter::writeDataSection() {
startSection(Section, wasm::WASM_SEC_DATA);
DataSectionIndex = Section.Index;
encodeULEB128(DataSegments.size(), getStream()); // count
encodeULEB128(DataSegments.size(), W.OS); // count
for (const WasmDataSegment &Segment : DataSegments) {
encodeULEB128(0, getStream()); // memory index
write8(wasm::WASM_OPCODE_I32_CONST);
encodeSLEB128(Segment.Offset, getStream()); // offset
write8(wasm::WASM_OPCODE_END);
encodeULEB128(Segment.Data.size(), getStream()); // size
Segment.Section->setSectionOffset(getStream().tell() - Section.ContentsOffset);
writeBytes(Segment.Data); // data
encodeULEB128(0, W.OS); // memory index
W.OS << char(wasm::WASM_OPCODE_I32_CONST);
encodeSLEB128(Segment.Offset, W.OS); // offset
W.OS << char(wasm::WASM_OPCODE_END);
encodeULEB128(Segment.Data.size(), W.OS); // size
Segment.Section->setSectionOffset(W.OS.tell() - Section.ContentsOffset);
W.OS << Segment.Data; // data
}
// Apply fixups.
@ -900,20 +903,18 @@ void WasmObjectWriter::writeRelocSection(
SectionBookkeeping Section;
startCustomSection(Section, std::string("reloc.") + Name.str());
raw_pwrite_stream &Stream = getStream();
encodeULEB128(SectionIndex, Stream);
encodeULEB128(Relocations.size(), Stream);
encodeULEB128(SectionIndex, W.OS);
encodeULEB128(Relocations.size(), W.OS);
for (const WasmRelocationEntry& RelEntry : Relocations) {
uint64_t Offset = RelEntry.Offset +
RelEntry.FixupSection->getSectionOffset();
uint32_t Index = getRelocationIndexValue(RelEntry);
write8(RelEntry.Type);
encodeULEB128(Offset, Stream);
encodeULEB128(Index, Stream);
W.OS << char(RelEntry.Type);
encodeULEB128(Offset, W.OS);
encodeULEB128(Index, W.OS);
if (RelEntry.hasAddend())
encodeSLEB128(RelEntry.Addend, Stream);
encodeSLEB128(RelEntry.Addend, W.OS);
}
endSection(Section);
@ -932,34 +933,34 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats) {
SectionBookkeeping Section;
startCustomSection(Section, "linking");
encodeULEB128(wasm::WasmMetadataVersion, getStream());
encodeULEB128(wasm::WasmMetadataVersion, W.OS);
SectionBookkeeping SubSection;
if (SymbolInfos.size() != 0) {
startSection(SubSection, wasm::WASM_SYMBOL_TABLE);
encodeULEB128(SymbolInfos.size(), getStream());
encodeULEB128(SymbolInfos.size(), W.OS);
for (const wasm::WasmSymbolInfo &Sym : SymbolInfos) {
encodeULEB128(Sym.Kind, getStream());
encodeULEB128(Sym.Flags, getStream());
encodeULEB128(Sym.Kind, W.OS);
encodeULEB128(Sym.Flags, W.OS);
switch (Sym.Kind) {
case wasm::WASM_SYMBOL_TYPE_FUNCTION:
case wasm::WASM_SYMBOL_TYPE_GLOBAL:
encodeULEB128(Sym.ElementIndex, getStream());
encodeULEB128(Sym.ElementIndex, W.OS);
if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0)
writeString(Sym.Name);
break;
case wasm::WASM_SYMBOL_TYPE_DATA:
writeString(Sym.Name);
if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
encodeULEB128(Sym.DataRef.Segment, getStream());
encodeULEB128(Sym.DataRef.Offset, getStream());
encodeULEB128(Sym.DataRef.Size, getStream());
encodeULEB128(Sym.DataRef.Segment, W.OS);
encodeULEB128(Sym.DataRef.Offset, W.OS);
encodeULEB128(Sym.DataRef.Size, W.OS);
}
break;
case wasm::WASM_SYMBOL_TYPE_SECTION: {
const uint32_t SectionIndex =
CustomSections[Sym.ElementIndex].OutputIndex;
encodeULEB128(SectionIndex, getStream());
encodeULEB128(SectionIndex, W.OS);
break;
}
default:
@ -971,35 +972,35 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
if (DataSegments.size()) {
startSection(SubSection, wasm::WASM_SEGMENT_INFO);
encodeULEB128(DataSegments.size(), getStream());
encodeULEB128(DataSegments.size(), W.OS);
for (const WasmDataSegment &Segment : DataSegments) {
writeString(Segment.Name);
encodeULEB128(Segment.Alignment, getStream());
encodeULEB128(Segment.Flags, getStream());
encodeULEB128(Segment.Alignment, W.OS);
encodeULEB128(Segment.Flags, W.OS);
}
endSection(SubSection);
}
if (!InitFuncs.empty()) {
startSection(SubSection, wasm::WASM_INIT_FUNCS);
encodeULEB128(InitFuncs.size(), getStream());
encodeULEB128(InitFuncs.size(), W.OS);
for (auto &StartFunc : InitFuncs) {
encodeULEB128(StartFunc.first, getStream()); // priority
encodeULEB128(StartFunc.second, getStream()); // function index
encodeULEB128(StartFunc.first, W.OS); // priority
encodeULEB128(StartFunc.second, W.OS); // function index
}
endSection(SubSection);
}
if (Comdats.size()) {
startSection(SubSection, wasm::WASM_COMDAT_INFO);
encodeULEB128(Comdats.size(), getStream());
encodeULEB128(Comdats.size(), W.OS);
for (const auto &C : Comdats) {
writeString(C.first);
encodeULEB128(0, getStream()); // flags for future use
encodeULEB128(C.second.size(), getStream());
encodeULEB128(0, W.OS); // flags for future use
encodeULEB128(C.second.size(), W.OS);
for (const WasmComdatEntry &Entry : C.second) {
encodeULEB128(Entry.Kind, getStream());
encodeULEB128(Entry.Index, getStream());
encodeULEB128(Entry.Kind, W.OS);
encodeULEB128(Entry.Index, W.OS);
}
}
endSection(SubSection);
@ -1015,8 +1016,8 @@ void WasmObjectWriter::writeCustomSections(const MCAssembler &Asm,
auto *Sec = CustomSection.Section;
startCustomSection(Section, CustomSection.Name);
Sec->setSectionOffset(getStream().tell() - Section.ContentsOffset);
Asm.writeSectionData(getStream(), Sec, Layout);
Sec->setSectionOffset(W.OS.tell() - Section.ContentsOffset);
Asm.writeSectionData(W.OS, Sec, Layout);
CustomSection.OutputContentsOffset = Section.ContentsOffset;
CustomSection.OutputIndex = Section.Index;

View File

@ -125,6 +125,8 @@ public:
class WinCOFFObjectWriter : public MCObjectWriter {
public:
support::endian::Writer W;
using symbols = std::vector<std::unique_ptr<COFFSymbol>>;
using sections = std::vector<std::unique_ptr<COFFSection>>;
@ -225,7 +227,8 @@ void COFFSymbol::set_name_offset(uint32_t Offset) {
WinCOFFObjectWriter::WinCOFFObjectWriter(
std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
: MCObjectWriter(OS, true), TargetObjectWriter(std::move(MOTW)) {
: MCObjectWriter(OS, true), W(OS, support::little),
TargetObjectWriter(std::move(MOTW)) {
Header.Machine = TargetObjectWriter->getMachine();
}
@ -472,40 +475,40 @@ bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
void WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) {
if (UseBigObj) {
writeLE16(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
writeLE16(0xFFFF);
writeLE16(COFF::BigObjHeader::MinBigObjectVersion);
writeLE16(Header.Machine);
writeLE32(Header.TimeDateStamp);
writeBytes(StringRef(COFF::BigObjMagic, sizeof(COFF::BigObjMagic)));
writeLE32(0);
writeLE32(0);
writeLE32(0);
writeLE32(0);
writeLE32(Header.NumberOfSections);
writeLE32(Header.PointerToSymbolTable);
writeLE32(Header.NumberOfSymbols);
W.write<uint16_t>(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
W.write<uint16_t>(0xFFFF);
W.write<uint16_t>(COFF::BigObjHeader::MinBigObjectVersion);
W.write<uint16_t>(Header.Machine);
W.write<uint32_t>(Header.TimeDateStamp);
W.OS.write(COFF::BigObjMagic, sizeof(COFF::BigObjMagic));
W.write<uint32_t>(0);
W.write<uint32_t>(0);
W.write<uint32_t>(0);
W.write<uint32_t>(0);
W.write<uint32_t>(Header.NumberOfSections);
W.write<uint32_t>(Header.PointerToSymbolTable);
W.write<uint32_t>(Header.NumberOfSymbols);
} else {
writeLE16(Header.Machine);
writeLE16(static_cast<int16_t>(Header.NumberOfSections));
writeLE32(Header.TimeDateStamp);
writeLE32(Header.PointerToSymbolTable);
writeLE32(Header.NumberOfSymbols);
writeLE16(Header.SizeOfOptionalHeader);
writeLE16(Header.Characteristics);
W.write<uint16_t>(Header.Machine);
W.write<uint16_t>(static_cast<int16_t>(Header.NumberOfSections));
W.write<uint32_t>(Header.TimeDateStamp);
W.write<uint32_t>(Header.PointerToSymbolTable);
W.write<uint32_t>(Header.NumberOfSymbols);
W.write<uint16_t>(Header.SizeOfOptionalHeader);
W.write<uint16_t>(Header.Characteristics);
}
}
void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) {
writeBytes(StringRef(S.Data.Name, COFF::NameSize));
writeLE32(S.Data.Value);
W.OS.write(S.Data.Name, COFF::NameSize);
W.write<uint32_t>(S.Data.Value);
if (UseBigObj)
writeLE32(S.Data.SectionNumber);
W.write<uint32_t>(S.Data.SectionNumber);
else
writeLE16(static_cast<int16_t>(S.Data.SectionNumber));
writeLE16(S.Data.Type);
write8(S.Data.StorageClass);
write8(S.Data.NumberOfAuxSymbols);
W.write<uint16_t>(static_cast<int16_t>(S.Data.SectionNumber));
W.write<uint16_t>(S.Data.Type);
W.OS << char(S.Data.StorageClass);
W.OS << char(S.Data.NumberOfAuxSymbols);
WriteAuxiliarySymbols(S.Aux);
}
@ -514,46 +517,45 @@ void WinCOFFObjectWriter::WriteAuxiliarySymbols(
for (const AuxSymbol &i : S) {
switch (i.AuxType) {
case ATFunctionDefinition:
writeLE32(i.Aux.FunctionDefinition.TagIndex);
writeLE32(i.Aux.FunctionDefinition.TotalSize);
writeLE32(i.Aux.FunctionDefinition.PointerToLinenumber);
writeLE32(i.Aux.FunctionDefinition.PointerToNextFunction);
WriteZeros(sizeof(i.Aux.FunctionDefinition.unused));
W.write<uint32_t>(i.Aux.FunctionDefinition.TagIndex);
W.write<uint32_t>(i.Aux.FunctionDefinition.TotalSize);
W.write<uint32_t>(i.Aux.FunctionDefinition.PointerToLinenumber);
W.write<uint32_t>(i.Aux.FunctionDefinition.PointerToNextFunction);
W.OS.write_zeros(sizeof(i.Aux.FunctionDefinition.unused));
if (UseBigObj)
WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
break;
case ATbfAndefSymbol:
WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused1));
writeLE16(i.Aux.bfAndefSymbol.Linenumber);
WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused2));
writeLE32(i.Aux.bfAndefSymbol.PointerToNextFunction);
WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused3));
W.OS.write_zeros(sizeof(i.Aux.bfAndefSymbol.unused1));
W.write<uint16_t>(i.Aux.bfAndefSymbol.Linenumber);
W.OS.write_zeros(sizeof(i.Aux.bfAndefSymbol.unused2));
W.write<uint32_t>(i.Aux.bfAndefSymbol.PointerToNextFunction);
W.OS.write_zeros(sizeof(i.Aux.bfAndefSymbol.unused3));
if (UseBigObj)
WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
break;
case ATWeakExternal:
writeLE32(i.Aux.WeakExternal.TagIndex);
writeLE32(i.Aux.WeakExternal.Characteristics);
WriteZeros(sizeof(i.Aux.WeakExternal.unused));
W.write<uint32_t>(i.Aux.WeakExternal.TagIndex);
W.write<uint32_t>(i.Aux.WeakExternal.Characteristics);
W.OS.write_zeros(sizeof(i.Aux.WeakExternal.unused));
if (UseBigObj)
WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
break;
case ATFile:
writeBytes(
StringRef(reinterpret_cast<const char *>(&i.Aux),
UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size));
W.OS.write(reinterpret_cast<const char *>(&i.Aux),
UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size);
break;
case ATSectionDefinition:
writeLE32(i.Aux.SectionDefinition.Length);
writeLE16(i.Aux.SectionDefinition.NumberOfRelocations);
writeLE16(i.Aux.SectionDefinition.NumberOfLinenumbers);
writeLE32(i.Aux.SectionDefinition.CheckSum);
writeLE16(static_cast<int16_t>(i.Aux.SectionDefinition.Number));
write8(i.Aux.SectionDefinition.Selection);
WriteZeros(sizeof(i.Aux.SectionDefinition.unused));
writeLE16(static_cast<int16_t>(i.Aux.SectionDefinition.Number >> 16));
W.write<uint32_t>(i.Aux.SectionDefinition.Length);
W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfRelocations);
W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfLinenumbers);
W.write<uint32_t>(i.Aux.SectionDefinition.CheckSum);
W.write<uint16_t>(static_cast<int16_t>(i.Aux.SectionDefinition.Number));
W.OS << char(i.Aux.SectionDefinition.Selection);
W.OS.write_zeros(sizeof(i.Aux.SectionDefinition.unused));
W.write<uint16_t>(static_cast<int16_t>(i.Aux.SectionDefinition.Number >> 16));
if (UseBigObj)
WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
break;
}
}
@ -579,23 +581,23 @@ void WinCOFFObjectWriter::writeSectionHeaders() {
COFF::section &S = Section->Header;
if (Section->Relocations.size() >= 0xffff)
S.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL;
writeBytes(StringRef(S.Name, COFF::NameSize));
writeLE32(S.VirtualSize);
writeLE32(S.VirtualAddress);
writeLE32(S.SizeOfRawData);
writeLE32(S.PointerToRawData);
writeLE32(S.PointerToRelocations);
writeLE32(S.PointerToLineNumbers);
writeLE16(S.NumberOfRelocations);
writeLE16(S.NumberOfLineNumbers);
writeLE32(S.Characteristics);
W.OS.write(S.Name, COFF::NameSize);
W.write<uint32_t>(S.VirtualSize);
W.write<uint32_t>(S.VirtualAddress);
W.write<uint32_t>(S.SizeOfRawData);
W.write<uint32_t>(S.PointerToRawData);
W.write<uint32_t>(S.PointerToRelocations);
W.write<uint32_t>(S.PointerToLineNumbers);
W.write<uint16_t>(S.NumberOfRelocations);
W.write<uint16_t>(S.NumberOfLineNumbers);
W.write<uint32_t>(S.Characteristics);
}
}
void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) {
writeLE32(R.VirtualAddress);
writeLE32(R.SymbolTableIndex);
writeLE16(R.Type);
W.write<uint32_t>(R.VirtualAddress);
W.write<uint32_t>(R.SymbolTableIndex);
W.write<uint16_t>(R.Type);
}
// Write MCSec's contents. What this function does is essentially
@ -611,7 +613,7 @@ uint32_t WinCOFFObjectWriter::writeSectionContents(MCAssembler &Asm,
Asm.writeSectionData(VecOS, &MCSec, Layout);
// Write the section contents to the object file.
getStream() << Buf;
W.OS << Buf;
// Calculate our CRC with an initial value of '0', this is not how
// JamCRC is specified but it aligns with the expected output.
@ -629,13 +631,13 @@ void WinCOFFObjectWriter::writeSection(MCAssembler &Asm,
// Write the section contents.
if (Sec.Header.PointerToRawData != 0) {
assert(getStream().tell() <= Sec.Header.PointerToRawData &&
assert(W.OS.tell() <= Sec.Header.PointerToRawData &&
"Section::PointerToRawData is insane!");
unsigned PaddingSize = Sec.Header.PointerToRawData - getStream().tell();
unsigned PaddingSize = Sec.Header.PointerToRawData - W.OS.tell();
assert(PaddingSize < 4 &&
"Should only need at most three bytes of padding!");
WriteZeros(PaddingSize);
W.OS.write_zeros(PaddingSize);
uint32_t CRC = writeSectionContents(Asm, Layout, MCSec);
@ -654,7 +656,7 @@ void WinCOFFObjectWriter::writeSection(MCAssembler &Asm,
return;
}
assert(getStream().tell() == Sec.Header.PointerToRelocations &&
assert(W.OS.tell() == Sec.Header.PointerToRelocations &&
"Section::PointerToRelocations is insane!");
if (Sec.Relocations.size() >= 0xffff) {
@ -900,7 +902,7 @@ void WinCOFFObjectWriter::assignSectionNumbers() {
// Assign file offsets to COFF object file structures.
void WinCOFFObjectWriter::assignFileOffsets(MCAssembler &Asm,
const MCAsmLayout &Layout) {
unsigned Offset = getInitialOffset();
unsigned Offset = W.OS.tell();
Offset += UseBigObj ? COFF::Header32Size : COFF::Header16Size;
Offset += COFF::SectionSize * Header.NumberOfSections;
@ -1058,7 +1060,7 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
for (; I != IE && J != JE; ++I, ++J)
writeSection(Asm, Layout, **I, *J);
assert(getStream().tell() == Header.PointerToSymbolTable &&
assert(W.OS.tell() == Header.PointerToSymbolTable &&
"Header::PointerToSymbolTable is insane!");
// Write a symbol table.
@ -1067,7 +1069,7 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
WriteSymbol(*Symbol);
// Write a string table, which completes the entire COFF file.
Strings.write(getStream());
Strings.write(W.OS);
}
MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_)

View File

@ -225,7 +225,7 @@ getSection(const object::MachOObjectFile &Obj,
template <typename SegmentTy>
static void transferSegmentAndSections(
const object::MachOObjectFile::LoadCommandInfo &LCI, SegmentTy Segment,
const object::MachOObjectFile &Obj, MCObjectWriter &Writer,
const object::MachOObjectFile &Obj, MachObjectWriter &Writer,
uint64_t LinkeditOffset, uint64_t LinkeditSize, uint64_t DwarfSegmentSize,
uint64_t &GapForDwarf, uint64_t &EndAddress) {
if (StringRef("__DWARF") == Segment.segname)
@ -255,14 +255,13 @@ static void transferSegmentAndSections(
unsigned nsects = Segment.nsects;
if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
MachO::swapStruct(Segment);
Writer.writeBytes(
StringRef(reinterpret_cast<char *>(&Segment), sizeof(Segment)));
Writer.W.OS.write(reinterpret_cast<char *>(&Segment), sizeof(Segment));
for (unsigned i = 0; i < nsects; ++i) {
auto Sect = getSection(Obj, Segment, LCI, i);
Sect.offset = Sect.reloff = Sect.nreloc = 0;
if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
MachO::swapStruct(Sect);
Writer.writeBytes(StringRef(reinterpret_cast<char *>(&Sect), sizeof(Sect)));
Writer.W.OS.write(reinterpret_cast<char *>(&Sect), sizeof(Sect));
}
}
@ -429,10 +428,9 @@ bool generateDsymCompanion(const DebugMap &DM, MCStreamer &MS,
// Write the load commands.
assert(OutFile.tell() == HeaderSize);
if (UUIDCmd.cmd != 0) {
Writer.write32(UUIDCmd.cmd);
Writer.write32(UUIDCmd.cmdsize);
Writer.writeBytes(
StringRef(reinterpret_cast<const char *>(UUIDCmd.uuid), 16));
Writer.W.write<uint32_t>(UUIDCmd.cmd);
Writer.W.write<uint32_t>(UUIDCmd.cmdsize);
OutFile.write(reinterpret_cast<const char *>(UUIDCmd.uuid), 16);
assert(OutFile.tell() == HeaderSize + sizeof(UUIDCmd));
}
@ -479,12 +477,12 @@ bool generateDsymCompanion(const DebugMap &DM, MCStreamer &MS,
NumDwarfSections, Layout, Writer);
assert(OutFile.tell() == LoadCommandSize + HeaderSize);
Writer.WriteZeros(SymtabStart - (LoadCommandSize + HeaderSize));
OutFile.write_zeros(SymtabStart - (LoadCommandSize + HeaderSize));
assert(OutFile.tell() == SymtabStart);
// Transfer symbols.
if (ShouldEmitSymtab) {
Writer.writeBytes(NewSymtab.str());
OutFile << NewSymtab.str();
assert(OutFile.tell() == StringStart);
// Transfer string table.
@ -492,21 +490,20 @@ bool generateDsymCompanion(const DebugMap &DM, MCStreamer &MS,
// dsymutil-classic starts the reconstructed string table with 2 of these.
// Reproduce that behavior for now (there is corresponding code in
// transferSymbol).
Writer.WriteZeros(1);
OutFile << '\0';
std::vector<DwarfStringPoolEntryRef> Strings = NewStrings.getEntries();
for (auto EntryRef : Strings) {
if (EntryRef.getIndex() == -1U)
break;
StringRef ZeroTerminated(EntryRef.getString().data(),
EntryRef.getString().size() + 1);
Writer.writeBytes(ZeroTerminated);
OutFile.write(EntryRef.getString().data(),
EntryRef.getString().size() + 1);
}
}
assert(OutFile.tell() == StringStart + NewStringsSize);
// Pad till the Dwarf segment start.
Writer.WriteZeros(DwarfSegmentStart - (StringStart + NewStringsSize));
OutFile.write_zeros(DwarfSegmentStart - (StringStart + NewStringsSize));
assert(OutFile.tell() == DwarfSegmentStart);
// Emit the Dwarf sections contents.
@ -515,7 +512,7 @@ bool generateDsymCompanion(const DebugMap &DM, MCStreamer &MS,
continue;
uint64_t Pos = OutFile.tell();
Writer.WriteZeros(alignTo(Pos, Sec.getAlignment()) - Pos);
OutFile.write_zeros(alignTo(Pos, Sec.getAlignment()) - Pos);
MCAsm.writeSectionData(OutFile, &Sec, Layout);
}