X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FMachObjectWriter.cpp;h=8234affc54da853de3aab5e6e0a245d965804c02;hb=6079f00035e029f12e4be0281aa2cbfbb4817141;hp=2778ed386da54f2dc146fb6631782d02ed81ba2d;hpb=c5252da873d547a19069eaf9030fec203f128f66;p=oota-llvm.git diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index 2778ed386da..8234affc54d 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -10,23 +10,31 @@ #include "llvm/MC/MCMachObjectWriter.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" -#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/MC/MCMachOSymbolFlags.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCMachOSymbolFlags.h" #include "llvm/MC/MCValue.h" -#include "llvm/Object/MachOFormat.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" - +#include "llvm/Support/MachO.h" #include using namespace llvm; -using namespace llvm::object; + +void MachObjectWriter::reset() { + Relocations.clear(); + IndirectSymBase.clear(); + StringTable.clear(); + LocalSymbolData.clear(); + ExternalSymbolData.clear(); + UndefinedSymbolData.clear(); + MCObjectWriter::reset(); +} bool MachObjectWriter:: doesSymbolRequireExternRelocation(const MCSymbolData *SD) { @@ -119,7 +127,7 @@ void MachObjectWriter::WriteHeader(unsigned NumLoadCommands, uint32_t Flags = 0; if (SubsectionsViaSymbols) - Flags |= macho::HF_SubsectionsViaSymbols; + Flags |= MachO::MH_SUBSECTIONS_VIA_SYMBOLS; // struct mach_header (28 bytes) or // struct mach_header_64 (32 bytes) @@ -127,12 +135,12 @@ void MachObjectWriter::WriteHeader(unsigned NumLoadCommands, uint64_t Start = OS.tell(); (void) Start; - Write32(is64Bit() ? macho::HM_Object64 : macho::HM_Object32); + Write32(is64Bit() ? MachO::MH_MAGIC_64 : MachO::MH_MAGIC); Write32(TargetObjectWriter->getCPUType()); Write32(TargetObjectWriter->getCPUSubtype()); - Write32(macho::HFT_Object); + Write32(MachO::MH_OBJECT); Write32(NumLoadCommands); Write32(LoadCommandsSize); Write32(Flags); @@ -140,7 +148,7 @@ void MachObjectWriter::WriteHeader(unsigned NumLoadCommands, Write32(0); // reserved assert(OS.tell() - Start == - (is64Bit() ? macho::Header64Size : macho::Header32Size)); + (is64Bit()?sizeof(MachO::mach_header_64): sizeof(MachO::mach_header))); } /// WriteSegmentLoadCommand - Write a segment load command. @@ -158,12 +166,12 @@ void MachObjectWriter::WriteSegmentLoadCommand(unsigned NumSections, (void) Start; unsigned SegmentLoadCommandSize = - is64Bit() ? macho::SegmentLoadCommand64Size: - macho::SegmentLoadCommand32Size; - Write32(is64Bit() ? macho::LCT_Segment64 : macho::LCT_Segment); + is64Bit() ? sizeof(MachO::segment_command_64): + sizeof(MachO::segment_command); + Write32(is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT); Write32(SegmentLoadCommandSize + - NumSections * (is64Bit() ? macho::Section64Size : - macho::Section32Size)); + NumSections * (is64Bit() ? sizeof(MachO::section_64) : + sizeof(MachO::section))); WriteBytes("", 16); if (is64Bit()) { @@ -177,8 +185,10 @@ void MachObjectWriter::WriteSegmentLoadCommand(unsigned NumSections, Write32(SectionDataStartOffset); // file offset Write32(SectionDataSize); // file size } - Write32(0x7); // maxprot - Write32(0x7); // initprot + // maxprot + Write32(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE); + // initprot + Write32(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE); Write32(NumSections); Write32(0); // flags @@ -231,8 +241,8 @@ void MachObjectWriter::WriteSection(const MCAssembler &Asm, if (is64Bit()) Write32(0); // reserved3 - assert(OS.tell() - Start == (is64Bit() ? macho::Section64Size : - macho::Section32Size)); + assert(OS.tell() - Start == (is64Bit() ? sizeof(MachO::section_64) : + sizeof(MachO::section))); } void MachObjectWriter::WriteSymtabLoadCommand(uint32_t SymbolOffset, @@ -244,14 +254,14 @@ void MachObjectWriter::WriteSymtabLoadCommand(uint32_t SymbolOffset, uint64_t Start = OS.tell(); (void) Start; - Write32(macho::LCT_Symtab); - Write32(macho::SymtabLoadCommandSize); + Write32(MachO::LC_SYMTAB); + Write32(sizeof(MachO::symtab_command)); Write32(SymbolOffset); Write32(NumSymbols); Write32(StringTableOffset); Write32(StringTableSize); - assert(OS.tell() - Start == macho::SymtabLoadCommandSize); + assert(OS.tell() - Start == sizeof(MachO::symtab_command)); } void MachObjectWriter::WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, @@ -267,8 +277,8 @@ void MachObjectWriter::WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, uint64_t Start = OS.tell(); (void) Start; - Write32(macho::LCT_Dysymtab); - Write32(macho::DysymtabLoadCommandSize); + Write32(MachO::LC_DYSYMTAB); + Write32(sizeof(MachO::dysymtab_command)); Write32(FirstLocalSymbol); Write32(NumLocalSymbols); Write32(FirstExternalSymbol); @@ -288,7 +298,7 @@ void MachObjectWriter::WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, Write32(0); // locreloff Write32(0); // nlocrel - assert(OS.tell() - Start == macho::DysymtabLoadCommandSize); + assert(OS.tell() - Start == sizeof(MachO::dysymtab_command)); } void MachObjectWriter::WriteNlist(MachSymbolData &MSD, @@ -303,20 +313,20 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD, // // FIXME: Are the prebound or indirect fields possible here? if (Symbol.isUndefined()) - Type = macho::STT_Undefined; + Type = MachO::N_UNDF; else if (Symbol.isAbsolute()) - Type = macho::STT_Absolute; + Type = MachO::N_ABS; else - Type = macho::STT_Section; + Type = MachO::N_SECT; // FIXME: Set STAB bits. if (Data.isPrivateExtern()) - Type |= macho::STF_PrivateExtern; + Type |= MachO::N_PEXT; // Set external bit. if (Data.isExternal() || Symbol.isUndefined()) - Type |= macho::STF_External; + Type |= MachO::N_EXT; // Compute the symbol address. if (Symbol.isDefined()) { @@ -332,7 +342,8 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD, assert((1U << Log2Size) == Align && "Invalid 'common' alignment!"); if (Log2Size > 15) report_fatal_error("invalid 'common' alignment '" + - Twine(Align) + "'"); + Twine(Align) + "' for '" + Symbol.getName() + "'", + false); // FIXME: Keep this mask with the SymbolFlags enumeration. Flags = (Flags & 0xF0FF) | (Log2Size << 8); } @@ -360,11 +371,44 @@ void MachObjectWriter::WriteLinkeditLoadCommand(uint32_t Type, (void) Start; Write32(Type); - Write32(macho::LinkeditLoadCommandSize); + Write32(sizeof(MachO::linkedit_data_command)); Write32(DataOffset); Write32(DataSize); - assert(OS.tell() - Start == macho::LinkeditLoadCommandSize); + assert(OS.tell() - Start == sizeof(MachO::linkedit_data_command)); +} + +static unsigned ComputeLinkerOptionsLoadCommandSize( + const std::vector &Options, bool is64Bit) +{ + unsigned Size = sizeof(MachO::linker_options_command); + for (unsigned i = 0, e = Options.size(); i != e; ++i) + Size += Options[i].size() + 1; + return RoundUpToAlignment(Size, is64Bit ? 8 : 4); +} + +void MachObjectWriter::WriteLinkerOptionsLoadCommand( + const std::vector &Options) +{ + unsigned Size = ComputeLinkerOptionsLoadCommandSize(Options, is64Bit()); + uint64_t Start = OS.tell(); + (void) Start; + + Write32(MachO::LC_LINKER_OPTIONS); + Write32(Size); + Write32(Options.size()); + uint64_t BytesWritten = sizeof(MachO::linker_options_command); + for (unsigned i = 0, e = Options.size(); i != e; ++i) { + // Write each string, including the null byte. + const std::string &Option = Options[i]; + WriteBytes(Option.c_str(), Option.size() + 1); + BytesWritten += Option.size() + 1; + } + + // Pad to a multiple of the pointer size. + WriteBytes("", OffsetToAlignment(BytesWritten, is64Bit() ? 8 : 4)); + + assert(OS.tell() - Start == Size); } @@ -386,6 +430,22 @@ void MachObjectWriter::BindIndirectSymbols(MCAssembler &Asm) { // // FIXME: Revisit this when the dust settles. + // Report errors for use of .indirect_symbol not in a symbol pointer section + // or stub section. + for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), + ie = Asm.indirect_symbol_end(); it != ie; ++it) { + const MCSectionMachO &Section = + cast(it->SectionData->getSection()); + + if (Section.getType() != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS && + Section.getType() != MCSectionMachO::S_LAZY_SYMBOL_POINTERS && + Section.getType() != MCSectionMachO::S_SYMBOL_STUBS) { + MCSymbol &Symbol = *it->Symbol; + report_fatal_error("indirect symbol '" + Symbol.getName() + + "' not in a symbol pointer or stub section"); + } + } + // Bind non lazy symbol pointers first. unsigned IndirectIndex = 0; for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), @@ -681,29 +741,38 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, // section headers) and the symbol table. unsigned NumLoadCommands = 1; uint64_t LoadCommandsSize = is64Bit() ? - macho::SegmentLoadCommand64Size + NumSections * macho::Section64Size : - macho::SegmentLoadCommand32Size + NumSections * macho::Section32Size; + sizeof(MachO::segment_command_64) + NumSections * sizeof(MachO::section_64): + sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section); + + // Add the data-in-code load command size, if used. + unsigned NumDataRegions = Asm.getDataRegions().size(); + if (NumDataRegions) { + ++NumLoadCommands; + LoadCommandsSize += sizeof(MachO::linkedit_data_command); + } // Add the symbol table load command sizes, if used. unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() + UndefinedSymbolData.size(); if (NumSymbols) { NumLoadCommands += 2; - LoadCommandsSize += (macho::SymtabLoadCommandSize + - macho::DysymtabLoadCommandSize); + LoadCommandsSize += (sizeof(MachO::symtab_command) + + sizeof(MachO::dysymtab_command)); } - // Add the data-in-code load command size, if used. - unsigned NumDataRegions = Asm.getDataRegions().size(); - if (NumDataRegions) { + // Add the linker option load commands sizes. + const std::vector > &LinkerOptions = + Asm.getLinkerOptions(); + for (unsigned i = 0, e = LinkerOptions.size(); i != e; ++i) { ++NumLoadCommands; - LoadCommandsSize += macho::LinkeditLoadCommandSize; + LoadCommandsSize += ComputeLinkerOptionsLoadCommandSize(LinkerOptions[i], + is64Bit()); } - + // Compute the total size of the section data, as well as its file size and vm // size. - uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size : - macho::Header32Size) + LoadCommandsSize; + uint64_t SectionDataStart = (is64Bit() ? sizeof(MachO::mach_header_64) : + sizeof(MachO::mach_header)) + LoadCommandsSize; uint64_t SectionDataSize = 0; uint64_t SectionDataFileSize = 0; uint64_t VMSize = 0; @@ -740,11 +809,11 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize; for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { - std::vector &Relocs = Relocations[it]; + std::vector &Relocs = Relocations[it]; unsigned NumRelocs = Relocs.size(); uint64_t SectionStart = SectionDataStart + getSectionAddress(it); WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs); - RelocTableEnd += NumRelocs * macho::RelocationInfoSize; + RelocTableEnd += NumRelocs * sizeof(MachO::any_relocation_info); } // Write the data-in-code load command, if used. @@ -752,7 +821,7 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, if (NumDataRegions) { uint64_t DataRegionsOffset = RelocTableEnd; uint64_t DataRegionsSize = NumDataRegions * 8; - WriteLinkeditLoadCommand(macho::LCT_DataInCode, DataRegionsOffset, + WriteLinkeditLoadCommand(MachO::LC_DATA_IN_CODE, DataRegionsOffset, DataRegionsSize); } @@ -779,8 +848,9 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, // The string table is written after symbol table. uint64_t StringTableOffset = - SymbolTableOffset + NumSymTabSymbols * (is64Bit() ? macho::Nlist64Size : - macho::Nlist32Size); + SymbolTableOffset + NumSymTabSymbols * (is64Bit() ? + sizeof(MachO::nlist_64) : + sizeof(MachO::nlist)); WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols, StringTableOffset, StringTable.size()); @@ -790,6 +860,11 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, IndirectSymbolOffset, NumIndirectSymbols); } + // Write the linker options load commands. + for (unsigned i = 0, e = LinkerOptions.size(); i != e; ++i) { + WriteLinkerOptionsLoadCommand(LinkerOptions[i]); + } + // Write the actual section data. for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { @@ -808,10 +883,10 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, ie = Asm.end(); it != ie; ++it) { // Write the section relocation entries, in reverse order to match 'as' // (approximately, the exact algorithm is more complicated than this). - std::vector &Relocs = Relocations[it]; + std::vector &Relocs = Relocations[it]; for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { - Write32(Relocs[e - i - 1].Word0); - Write32(Relocs[e - i - 1].Word1); + Write32(Relocs[e - i - 1].r_word0); + Write32(Relocs[e - i - 1].r_word1); } } @@ -820,8 +895,12 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, it = Asm.data_region_begin(), ie = Asm.data_region_end(); it != ie; ++it) { const DataRegionData *Data = &(*it); - uint64_t Start = getSymbolAddress(&Layout.getAssembler().getSymbolData(*Data->Start), Layout); - uint64_t End = getSymbolAddress(&Layout.getAssembler().getSymbolData(*Data->End), Layout); + uint64_t Start = + getSymbolAddress(&Layout.getAssembler().getSymbolData(*Data->Start), + Layout); + uint64_t End = + getSymbolAddress(&Layout.getAssembler().getSymbolData(*Data->End), + Layout); DEBUG(dbgs() << "data in code region-- kind: " << Data->Kind << " start: " << Start << "(" << Data->Start->getName() << ")" << " end: " << End << "(" << Data->End->getName() << ")" @@ -846,9 +925,9 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, // If this symbol is defined and internal, mark it as such. if (it->Symbol->isDefined() && !Asm.getSymbolData(*it->Symbol).isExternal()) { - uint32_t Flags = macho::ISF_Local; + uint32_t Flags = MachO::INDIRECT_SYMBOL_LOCAL; if (it->Symbol->isAbsolute()) - Flags |= macho::ISF_Absolute; + Flags |= MachO::INDIRECT_SYMBOL_ABS; Write32(Flags); continue; }