From a94c33942373cb504b6e64c95415165907a89d34 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Fri, 18 Jan 2013 01:26:07 +0000 Subject: [MC/Mach-O] Add support for linker options in Mach-O files. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172779 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MachObjectWriter.cpp | 56 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 5 deletions(-) (limited to 'lib/MC/MachObjectWriter.cpp') diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index 0098bead45..d13c178a9c 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -376,6 +376,39 @@ void MachObjectWriter::WriteLinkeditLoadCommand(uint32_t Type, assert(OS.tell() - Start == macho::LinkeditLoadCommandSize); } +static unsigned ComputeLinkerOptionsLoadCommandSize( + const std::vector &Options) +{ + unsigned Size = sizeof(macho::LinkerOptionsLoadCommand); + for (unsigned i = 0, e = Options.size(); i != e; ++i) + Size += Options[i].size() + 1; + return RoundUpToAlignment(Size, 4); +} + +void MachObjectWriter::WriteLinkerOptionsLoadCommand( + const std::vector &Options) +{ + unsigned Size = ComputeLinkerOptionsLoadCommandSize(Options); + uint64_t Start = OS.tell(); + (void) Start; + + Write32(macho::LCT_LinkerOptions); + Write32(Size); + Write32(Options.size()); + uint64_t BytesWritten = 0; + 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 4. + WriteBytes("", OffsetToAlignment(BytesWritten, 4)); + + assert(OS.tell() - Start == Size); +} + void MachObjectWriter::RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, @@ -693,6 +726,13 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, macho::SegmentLoadCommand64Size + NumSections * macho::Section64Size : macho::SegmentLoadCommand32Size + NumSections * macho::Section32Size; + // Add the data-in-code load command size, if used. + unsigned NumDataRegions = Asm.getDataRegions().size(); + if (NumDataRegions) { + ++NumLoadCommands; + LoadCommandsSize += macho::LinkeditLoadCommandSize; + } + // Add the symbol table load command sizes, if used. unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() + UndefinedSymbolData.size(); @@ -702,13 +742,14 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, macho::DysymtabLoadCommandSize); } - // 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]); } - + // Compute the total size of the section data, as well as its file size and vm // size. uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size : @@ -799,6 +840,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) { -- cgit v1.2.3-18-g5258