[llvm] r352944 - [llvm-objcopy] Add ability to copy MachO object files
Alexander Shaposhnikov via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 1 16:38:07 PST 2019
Author: alexshap
Date: Fri Feb 1 16:38:07 2019
New Revision: 352944
URL: http://llvm.org/viewvc/llvm-project?rev=352944&view=rev
Log:
[llvm-objcopy] Add ability to copy MachO object files
This diff implements first bits for copying (without modification) MachO object files.
Test plan: make check-all
Differential revision: https://reviews.llvm.org/D54674
Added:
llvm/trunk/test/tools/llvm-objcopy/MachO/
llvm/trunk/test/tools/llvm-objcopy/MachO/Inputs/
llvm/trunk/test/tools/llvm-objcopy/MachO/Inputs/macho.32.s
llvm/trunk/test/tools/llvm-objcopy/MachO/Inputs/macho.64.s
llvm/trunk/test/tools/llvm-objcopy/MachO/basic-big-endian-32-copy.test
llvm/trunk/test/tools/llvm-objcopy/MachO/basic-big-endian-64-copy.test
llvm/trunk/test/tools/llvm-objcopy/MachO/basic-little-endian-32-copy.test
llvm/trunk/test/tools/llvm-objcopy/MachO/basic-little-endian-64-copy.test
llvm/trunk/test/tools/llvm-objcopy/MachO/real-world-input-copy.test
llvm/trunk/tools/llvm-objcopy/MachO/
llvm/trunk/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
llvm/trunk/tools/llvm-objcopy/MachO/MachOObjcopy.h
llvm/trunk/tools/llvm-objcopy/MachO/MachOReader.cpp
llvm/trunk/tools/llvm-objcopy/MachO/MachOReader.h
llvm/trunk/tools/llvm-objcopy/MachO/MachOWriter.cpp
llvm/trunk/tools/llvm-objcopy/MachO/MachOWriter.h
llvm/trunk/tools/llvm-objcopy/MachO/Object.h
Modified:
llvm/trunk/tools/llvm-objcopy/CMakeLists.txt
llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp
Added: llvm/trunk/test/tools/llvm-objcopy/MachO/Inputs/macho.32.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/MachO/Inputs/macho.32.s?rev=352944&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/MachO/Inputs/macho.32.s (added)
+++ llvm/trunk/test/tools/llvm-objcopy/MachO/Inputs/macho.32.s Fri Feb 1 16:38:07 2019
@@ -0,0 +1,54 @@
+ .section __TEXT,__text,regular,pure_instructions
+ .build_version macos, 10, 14
+ .globl __Z1fi ## -- Begin function _Z1fi
+ .p2align 4, 0x90
+__Z1fi: ## @_Z1fi
+ .cfi_startproc
+## %bb.0:
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset %ebp, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register %ebp
+ pushl %eax
+ calll L0$pb
+L0$pb:
+ popl %eax
+ movl 8(%ebp), %ecx
+ movl _x-L0$pb(%eax), %eax
+ addl 8(%ebp), %eax
+ movl %ecx, -4(%ebp) ## 4-byte Spill
+ addl $4, %esp
+ popl %ebp
+ retl
+ .cfi_endproc
+ ## -- End function
+ .globl _main ## -- Begin function main
+ .p2align 4, 0x90
+_main: ## @main
+ .cfi_startproc
+## %bb.0:
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset %ebp, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register %ebp
+ subl $24, %esp
+ movl $2, %eax
+ movl $0, -4(%ebp)
+ movl $2, (%esp)
+ movl %eax, -8(%ebp) ## 4-byte Spill
+ calll __Z1fi
+ addl $24, %esp
+ popl %ebp
+ retl
+ .cfi_endproc
+ ## -- End function
+ .section __DATA,__data
+ .globl _x ## @x
+ .p2align 2
+_x:
+ .long 1 ## 0x1
+
+
+.subsections_via_symbols
Added: llvm/trunk/test/tools/llvm-objcopy/MachO/Inputs/macho.64.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/MachO/Inputs/macho.64.s?rev=352944&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/MachO/Inputs/macho.64.s (added)
+++ llvm/trunk/test/tools/llvm-objcopy/MachO/Inputs/macho.64.s Fri Feb 1 16:38:07 2019
@@ -0,0 +1,47 @@
+ .section __TEXT,__text,regular,pure_instructions
+ .build_version macos, 10, 14
+ .globl __Z1fi ## -- Begin function _Z1fi
+ .p2align 4, 0x90
+__Z1fi: ## @_Z1fi
+ .cfi_startproc
+## %bb.0:
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl %edi, -4(%rbp)
+ movl _x(%rip), %edi
+ addl -4(%rbp), %edi
+ movl %edi, %eax
+ popq %rbp
+ retq
+ .cfi_endproc
+ ## -- End function
+ .globl _main ## -- Begin function main
+ .p2align 4, 0x90
+_main: ## @main
+ .cfi_startproc
+## %bb.0:
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ subq $16, %rsp
+ movl $2, %edi
+ movl $0, -4(%rbp)
+ callq __Z1fi
+ addq $16, %rsp
+ popq %rbp
+ retq
+ .cfi_endproc
+ ## -- End function
+ .section __DATA,__data
+ .globl _x ## @x
+ .p2align 2
+_x:
+ .long 1 ## 0x1
+
+
+.subsections_via_symbols
Added: llvm/trunk/test/tools/llvm-objcopy/MachO/basic-big-endian-32-copy.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/MachO/basic-big-endian-32-copy.test?rev=352944&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/MachO/basic-big-endian-32-copy.test (added)
+++ llvm/trunk/test/tools/llvm-objcopy/MachO/basic-big-endian-32-copy.test Fri Feb 1 16:38:07 2019
@@ -0,0 +1,112 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objcopy %t %t2
+# RUN: cmp %t %t2
+
+--- !mach-o
+IsLittleEndian: false
+FileHeader:
+ magic: 0xFEEDFACE
+ cputype: 0x00000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 4
+ sizeofcmds: 380
+ flags: 0x00002000
+LoadCommands:
+ - cmd: LC_SEGMENT
+ cmdsize: 260
+ segname: ''
+ vmaddr: 0
+ vmsize: 184
+ fileoff: 408
+ filesize: 184
+ maxprot: 7
+ initprot: 7
+ nsects: 3
+ flags: 0
+ Sections:
+ - sectname: __text
+ segname: __TEXT
+ addr: 0x0000000000000000
+ size: 61
+ offset: 0x00000198
+ align: 4
+ reloff: 0x00000250
+ nreloc: 1
+ flags: 0x80000400
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __compact_unwind
+ segname: __LD
+ addr: 0x0000000000000040
+ size: 40
+ offset: 0x000001D8
+ align: 2
+ reloff: 0x00000258
+ nreloc: 2
+ flags: 0x02000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __eh_frame
+ segname: __TEXT
+ addr: 0x0000000000000068
+ size: 80
+ offset: 0x00000200
+ align: 2
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x6800000B
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - cmd: LC_VERSION_MIN_MACOSX
+ cmdsize: 16
+ version: 658688
+ sdk: 0
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 616
+ nsyms: 2
+ stroff: 640
+ strsize: 16
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+ nlocalsym: 0
+ iextdefsym: 0
+ nextdefsym: 2
+ iundefsym: 2
+ nundefsym: 0
+ tocoff: 0
+ ntoc: 0
+ modtaboff: 0
+ nmodtab: 0
+ extrefsymoff: 0
+ nextrefsyms: 0
+ indirectsymoff: 0
+ nindirectsyms: 0
+ extreloff: 0
+ nextrel: 0
+ locreloff: 0
+ nlocrel: 0
+LinkEditData:
+ NameList:
+ - n_strx: 1
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 0
+ - n_strx: 8
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 32
+ StringTable:
+ - ''
+ - __Z1fv
+ - _main
+ - ''
+ - ''
+...
Added: llvm/trunk/test/tools/llvm-objcopy/MachO/basic-big-endian-64-copy.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/MachO/basic-big-endian-64-copy.test?rev=352944&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/MachO/basic-big-endian-64-copy.test (added)
+++ llvm/trunk/test/tools/llvm-objcopy/MachO/basic-big-endian-64-copy.test Fri Feb 1 16:38:07 2019
@@ -0,0 +1,124 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objcopy %t %t2
+# RUN: cmp %t %t2
+
+--- !mach-o
+IsLittleEndian: false
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 4
+ sizeofcmds: 512
+ flags: 0x00002000
+ reserved: 0x00000000
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 392
+ segname: ''
+ vmaddr: 0
+ vmsize: 240
+ fileoff: 544
+ filesize: 240
+ maxprot: 7
+ initprot: 7
+ nsects: 4
+ flags: 0
+ Sections:
+ - sectname: __text
+ segname: __TEXT
+ addr: 0x0000000000000000
+ size: 93
+ offset: 0x00000220
+ align: 4
+ reloff: 0x00000310
+ nreloc: 3
+ flags: 0x80000400
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __cstring
+ segname: __TEXT
+ addr: 0x000000000000005D
+ size: 48
+ offset: 0x0000027D
+ align: 0
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x00000002
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __compact_unwind
+ segname: __LD
+ addr: 0x0000000000000090
+ size: 32
+ offset: 0x000002B0
+ align: 3
+ reloff: 0x00000328
+ nreloc: 1
+ flags: 0x02000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __eh_frame
+ segname: __TEXT
+ addr: 0x00000000000000B0
+ size: 64
+ offset: 0x000002D0
+ align: 3
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x6800000B
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - cmd: LC_VERSION_MIN_MACOSX
+ cmdsize: 16
+ version: 658432
+ sdk: 0
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 816
+ nsyms: 2
+ stroff: 848
+ strsize: 36
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+ nlocalsym: 0
+ iextdefsym: 0
+ nextdefsym: 1
+ iundefsym: 1
+ nundefsym: 1
+ tocoff: 0
+ ntoc: 0
+ modtaboff: 0
+ nmodtab: 0
+ extrefsymoff: 0
+ nextrefsyms: 0
+ indirectsymoff: 0
+ nindirectsyms: 0
+ extreloff: 0
+ nextrel: 0
+ locreloff: 0
+ nlocrel: 0
+LinkEditData:
+ NameList:
+ - n_strx: 24
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 0
+ - n_strx: 1
+ n_type: 0x01
+ n_sect: 0
+ n_desc: 0
+ n_value: 0
+ StringTable:
+ - ''
+ - _compilerrt_abort_impl
+ - ___absvdi2
+ - ''
+...
Added: llvm/trunk/test/tools/llvm-objcopy/MachO/basic-little-endian-32-copy.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/MachO/basic-little-endian-32-copy.test?rev=352944&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/MachO/basic-little-endian-32-copy.test (added)
+++ llvm/trunk/test/tools/llvm-objcopy/MachO/basic-little-endian-32-copy.test Fri Feb 1 16:38:07 2019
@@ -0,0 +1,112 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objcopy %t %t2
+# RUN: cmp %t %t2
+
+--- !mach-o
+IsLittleEndian: true
+FileHeader:
+ magic: 0xFEEDFACE
+ cputype: 0x00000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 4
+ sizeofcmds: 380
+ flags: 0x00002000
+LoadCommands:
+ - cmd: LC_SEGMENT
+ cmdsize: 260
+ segname: ''
+ vmaddr: 0
+ vmsize: 184
+ fileoff: 408
+ filesize: 184
+ maxprot: 7
+ initprot: 7
+ nsects: 3
+ flags: 0
+ Sections:
+ - sectname: __text
+ segname: __TEXT
+ addr: 0x0000000000000000
+ size: 61
+ offset: 0x00000198
+ align: 4
+ reloff: 0x00000250
+ nreloc: 1
+ flags: 0x80000400
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __compact_unwind
+ segname: __LD
+ addr: 0x0000000000000040
+ size: 40
+ offset: 0x000001D8
+ align: 2
+ reloff: 0x00000258
+ nreloc: 2
+ flags: 0x02000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __eh_frame
+ segname: __TEXT
+ addr: 0x0000000000000068
+ size: 80
+ offset: 0x00000200
+ align: 2
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x6800000B
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - cmd: LC_VERSION_MIN_MACOSX
+ cmdsize: 16
+ version: 658688
+ sdk: 0
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 616
+ nsyms: 2
+ stroff: 640
+ strsize: 16
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+ nlocalsym: 0
+ iextdefsym: 0
+ nextdefsym: 2
+ iundefsym: 2
+ nundefsym: 0
+ tocoff: 0
+ ntoc: 0
+ modtaboff: 0
+ nmodtab: 0
+ extrefsymoff: 0
+ nextrefsyms: 0
+ indirectsymoff: 0
+ nindirectsyms: 0
+ extreloff: 0
+ nextrel: 0
+ locreloff: 0
+ nlocrel: 0
+LinkEditData:
+ NameList:
+ - n_strx: 1
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 0
+ - n_strx: 8
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 32
+ StringTable:
+ - ''
+ - __Z1fv
+ - _main
+ - ''
+ - ''
+...
Added: llvm/trunk/test/tools/llvm-objcopy/MachO/basic-little-endian-64-copy.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/MachO/basic-little-endian-64-copy.test?rev=352944&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/MachO/basic-little-endian-64-copy.test (added)
+++ llvm/trunk/test/tools/llvm-objcopy/MachO/basic-little-endian-64-copy.test Fri Feb 1 16:38:07 2019
@@ -0,0 +1,124 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objcopy %t %t2
+# RUN: cmp %t %t2
+
+--- !mach-o
+IsLittleEndian: true
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 4
+ sizeofcmds: 512
+ flags: 0x00002000
+ reserved: 0x00000000
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 392
+ segname: ''
+ vmaddr: 0
+ vmsize: 240
+ fileoff: 544
+ filesize: 240
+ maxprot: 7
+ initprot: 7
+ nsects: 4
+ flags: 0
+ Sections:
+ - sectname: __text
+ segname: __TEXT
+ addr: 0x0000000000000000
+ size: 93
+ offset: 0x00000220
+ align: 4
+ reloff: 0x00000310
+ nreloc: 3
+ flags: 0x80000400
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __cstring
+ segname: __TEXT
+ addr: 0x000000000000005D
+ size: 48
+ offset: 0x0000027D
+ align: 0
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x00000002
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __compact_unwind
+ segname: __LD
+ addr: 0x0000000000000090
+ size: 32
+ offset: 0x000002B0
+ align: 3
+ reloff: 0x00000328
+ nreloc: 1
+ flags: 0x02000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __eh_frame
+ segname: __TEXT
+ addr: 0x00000000000000B0
+ size: 64
+ offset: 0x000002D0
+ align: 3
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x6800000B
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - cmd: LC_VERSION_MIN_MACOSX
+ cmdsize: 16
+ version: 658432
+ sdk: 0
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 816
+ nsyms: 2
+ stroff: 848
+ strsize: 36
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+ nlocalsym: 0
+ iextdefsym: 0
+ nextdefsym: 1
+ iundefsym: 1
+ nundefsym: 1
+ tocoff: 0
+ ntoc: 0
+ modtaboff: 0
+ nmodtab: 0
+ extrefsymoff: 0
+ nextrefsyms: 0
+ indirectsymoff: 0
+ nindirectsyms: 0
+ extreloff: 0
+ nextrel: 0
+ locreloff: 0
+ nlocrel: 0
+LinkEditData:
+ NameList:
+ - n_strx: 24
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 0
+ - n_strx: 1
+ n_type: 0x01
+ n_sect: 0
+ n_desc: 0
+ n_value: 0
+ StringTable:
+ - ''
+ - _compilerrt_abort_impl
+ - ___absvdi2
+ - ''
+...
Added: llvm/trunk/test/tools/llvm-objcopy/MachO/real-world-input-copy.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/MachO/real-world-input-copy.test?rev=352944&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/MachO/real-world-input-copy.test (added)
+++ llvm/trunk/test/tools/llvm-objcopy/MachO/real-world-input-copy.test Fri Feb 1 16:38:07 2019
@@ -0,0 +1,7 @@
+# RUN: llvm-mc -assemble -triple i386-apple-macosx10.14.0 -filetype=obj %p/Inputs/macho.32.s -o %t.32.o
+# RUN: llvm-objcopy %t.32.o %t.32.copy.o
+# RUN: cmp %t.32.o %t.32.copy.o
+
+# RUN: llvm-mc -assemble -triple x86_64-apple-macosx10.14.0 -filetype=obj %p/Inputs/macho.64.s -o %t.64.o
+# RUN: llvm-objcopy %t.64.o %t.64.copy.o
+# RUN: cmp %t.64.o %t.64.copy.o
Modified: llvm/trunk/tools/llvm-objcopy/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/CMakeLists.txt?rev=352944&r1=352943&r2=352944&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-objcopy/CMakeLists.txt Fri Feb 1 16:38:07 2019
@@ -23,6 +23,9 @@ add_llvm_tool(llvm-objcopy
COFF/Writer.cpp
ELF/ELFObjcopy.cpp
ELF/Object.cpp
+ MachO/MachOObjcopy.cpp
+ MachO/MachOReader.cpp
+ MachO/MachOWriter.cpp
DEPENDS
ObjcopyOptsTableGen
StripOptsTableGen
Added: llvm/trunk/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/MachO/MachOObjcopy.cpp?rev=352944&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/MachO/MachOObjcopy.cpp (added)
+++ llvm/trunk/tools/llvm-objcopy/MachO/MachOObjcopy.cpp Fri Feb 1 16:38:07 2019
@@ -0,0 +1,32 @@
+//===- MachOObjcopy.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MachOObjcopy.h"
+#include "../CopyConfig.h"
+#include "../llvm-objcopy.h"
+#include "MachOReader.h"
+#include "MachOWriter.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace objcopy {
+namespace macho {
+
+Error executeObjcopyOnBinary(const CopyConfig &Config,
+ object::MachOObjectFile &In, Buffer &Out) {
+ MachOReader Reader(In);
+ std::unique_ptr<Object> O = Reader.create();
+ assert(O && "Unable to deserialize MachO object");
+ MachOWriter Writer(*O, In.is64Bit(), In.isLittleEndian(), Out);
+ return Writer.write();
+}
+
+} // end namespace macho
+} // end namespace objcopy
+} // end namespace llvm
Added: llvm/trunk/tools/llvm-objcopy/MachO/MachOObjcopy.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/MachO/MachOObjcopy.h?rev=352944&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/MachO/MachOObjcopy.h (added)
+++ llvm/trunk/tools/llvm-objcopy/MachO/MachOObjcopy.h Fri Feb 1 16:38:07 2019
@@ -0,0 +1,32 @@
+//===- MachOObjcopy.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_OBJCOPY_MACHOOBJCOPY_H
+#define LLVM_TOOLS_OBJCOPY_MACHOOBJCOPY_H
+
+namespace llvm {
+class Error;
+
+namespace object {
+class MachOObjectFile;
+class MachOUniversalBinary;
+} // end namespace object
+
+namespace objcopy {
+struct CopyConfig;
+class Buffer;
+
+namespace macho {
+Error executeObjcopyOnBinary(const CopyConfig &Config,
+ object::MachOObjectFile &In, Buffer &Out);
+} // end namespace macho
+} // end namespace objcopy
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_OBJCOPY_MACHOOBJCOPY_H
Added: llvm/trunk/tools/llvm-objcopy/MachO/MachOReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/MachO/MachOReader.cpp?rev=352944&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/MachO/MachOReader.cpp (added)
+++ llvm/trunk/tools/llvm-objcopy/MachO/MachOReader.cpp Fri Feb 1 16:38:07 2019
@@ -0,0 +1,225 @@
+//===- MachOReader.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MachOReader.h"
+#include "../llvm-objcopy.h"
+#include "Object.h"
+#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/Object/MachO.h"
+#include <memory>
+
+namespace llvm {
+namespace objcopy {
+namespace macho {
+
+void MachOReader::readHeader(Object &O) const {
+ O.Header.Magic = MachOObj.getHeader().magic;
+ O.Header.CPUType = MachOObj.getHeader().cputype;
+ O.Header.CPUSubType = MachOObj.getHeader().cpusubtype;
+ O.Header.FileType = MachOObj.getHeader().filetype;
+ O.Header.NCmds = MachOObj.getHeader().ncmds;
+ O.Header.SizeOfCmds = MachOObj.getHeader().sizeofcmds;
+ O.Header.Flags = MachOObj.getHeader().flags;
+}
+
+template <typename SectionType>
+Section constructSectionCommon(SectionType Sec) {
+ Section S;
+ memcpy(S.Sectname, Sec.sectname, sizeof(Sec.sectname));
+ memcpy(S.Segname, Sec.segname, sizeof(Sec.segname));
+ S.Addr = Sec.addr;
+ S.Size = Sec.size;
+ S.Offset = Sec.offset;
+ S.Align = Sec.align;
+ S.RelOff = Sec.reloff;
+ S.NReloc = Sec.nreloc;
+ S.Flags = Sec.flags;
+ S.Reserved1 = Sec.reserved1;
+ S.Reserved2 = Sec.reserved2;
+ S.Reserved3 = 0;
+ return S;
+}
+
+template <typename SectionType> Section constructSection(SectionType Sec);
+
+template <> Section constructSection(MachO::section Sec) {
+ return constructSectionCommon(Sec);
+}
+
+template <> Section constructSection(MachO::section_64 Sec) {
+ Section S = constructSectionCommon(Sec);
+ S.Reserved3 = Sec.reserved3;
+ return S;
+}
+
+// TODO: get rid of reportError and make MachOReader return Expected<> instead.
+template <typename SectionType, typename SegmentType>
+std::vector<Section>
+extractSections(const object::MachOObjectFile::LoadCommandInfo &LoadCmd,
+ const object::MachOObjectFile &MachOObj,
+ size_t &NextSectionIndex) {
+ auto End = LoadCmd.Ptr + LoadCmd.C.cmdsize;
+ const SectionType *Curr =
+ reinterpret_cast<const SectionType *>(LoadCmd.Ptr + sizeof(SegmentType));
+ std::vector<Section> Sections;
+ for (; reinterpret_cast<const void *>(Curr) < End; Curr++) {
+ if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) {
+ SectionType Sec;
+ memcpy((void *)&Sec, Curr, sizeof(SectionType));
+ MachO::swapStruct(Sec);
+ Sections.push_back(constructSection(Sec));
+ } else {
+ Sections.push_back(constructSection(*Curr));
+ }
+
+ Section &S = Sections.back();
+
+ StringRef SectName(S.Sectname);
+ Expected<object::SectionRef> SecRef =
+ MachOObj.getSection(NextSectionIndex++);
+ if (!SecRef)
+ reportError(MachOObj.getFileName(), SecRef.takeError());
+
+ StringRef Content;
+ if (auto EC =
+ MachOObj.getSectionContents(SecRef->getRawDataRefImpl(), Content))
+ reportError(MachOObj.getFileName(), std::move(EC));
+ S.Content = Content;
+
+ S.Relocations.reserve(S.NReloc);
+ for (auto RI = MachOObj.section_rel_begin(SecRef->getRawDataRefImpl()),
+ RE = MachOObj.section_rel_end(SecRef->getRawDataRefImpl());
+ RI != RE; ++RI)
+ S.Relocations.push_back(MachOObj.getRelocation(RI->getRawDataRefImpl()));
+ assert(S.NReloc == S.Relocations.size() &&
+ "Incorrect number of relocations");
+ }
+ return Sections;
+}
+
+void MachOReader::readLoadCommands(Object &O) const {
+ // For MachO sections indices start from 1.
+ size_t NextSectionIndex = 1;
+ for (auto LoadCmd : MachOObj.load_commands()) {
+ LoadCommand LC;
+ switch (LoadCmd.C.cmd) {
+ case MachO::LC_SEGMENT:
+ LC.Sections = extractSections<MachO::section, MachO::segment_command>(
+ LoadCmd, MachOObj, NextSectionIndex);
+ break;
+ case MachO::LC_SEGMENT_64:
+ LC.Sections =
+ extractSections<MachO::section_64, MachO::segment_command_64>(
+ LoadCmd, MachOObj, NextSectionIndex);
+ break;
+ case MachO::LC_SYMTAB:
+ O.SymTabCommandIndex = O.LoadCommands.size();
+ break;
+ case MachO::LC_DYLD_INFO:
+ case MachO::LC_DYLD_INFO_ONLY:
+ O.DyLdInfoCommandIndex = O.LoadCommands.size();
+ break;
+ }
+#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
+ case MachO::LCName: \
+ memcpy((void *)&(LC.MachOLoadCommand.LCStruct##_data), LoadCmd.Ptr, \
+ sizeof(MachO::LCStruct)); \
+ if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) \
+ MachO::swapStruct(LC.MachOLoadCommand.LCStruct##_data); \
+ LC.Payload = ArrayRef<uint8_t>( \
+ reinterpret_cast<uint8_t *>(const_cast<char *>(LoadCmd.Ptr)) + \
+ sizeof(MachO::LCStruct), \
+ LoadCmd.C.cmdsize - sizeof(MachO::LCStruct)); \
+ break;
+
+ switch (LoadCmd.C.cmd) {
+ default:
+ memcpy((void *)&(LC.MachOLoadCommand.load_command_data), LoadCmd.Ptr,
+ sizeof(MachO::load_command));
+ if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost)
+ MachO::swapStruct(LC.MachOLoadCommand.load_command_data);
+ LC.Payload = ArrayRef<uint8_t>(
+ reinterpret_cast<uint8_t *>(const_cast<char *>(LoadCmd.Ptr)) +
+ sizeof(MachO::load_command),
+ LoadCmd.C.cmdsize - sizeof(MachO::load_command));
+ break;
+#include "llvm/BinaryFormat/MachO.def"
+ }
+ O.LoadCommands.push_back(std::move(LC));
+ }
+}
+
+template <typename nlist_t> NListEntry constructNameList(const nlist_t &nlist) {
+ NListEntry NL;
+ NL.n_strx = nlist.n_strx;
+ NL.n_type = nlist.n_type;
+ NL.n_sect = nlist.n_sect;
+ NL.n_desc = nlist.n_desc;
+ NL.n_value = nlist.n_value;
+ return NL;
+}
+
+void MachOReader::readSymbolTable(Object &O) const {
+ for (auto Symbol : MachOObj.symbols()) {
+ NListEntry NLE =
+ MachOObj.is64Bit()
+ ? constructNameList<MachO::nlist_64>(
+ MachOObj.getSymbol64TableEntry(Symbol.getRawDataRefImpl()))
+ : constructNameList<MachO::nlist>(
+ MachOObj.getSymbolTableEntry(Symbol.getRawDataRefImpl()));
+ O.SymTable.NameList.push_back(NLE);
+ }
+};
+
+void MachOReader::readStringTable(Object &O) const {
+ StringRef Data = MachOObj.getStringTableData();
+ SmallVector<StringRef, 10> Strs;
+ Data.split(Strs, '\0');
+ O.StrTable.Strings.reserve(Strs.size());
+ for (auto S : Strs)
+ O.StrTable.Strings.push_back(S.str());
+};
+
+void MachOReader::readRebaseInfo(Object &O) const {
+ O.Rebases.Opcodes = MachOObj.getDyldInfoRebaseOpcodes();
+}
+
+void MachOReader::readBindInfo(Object &O) const {
+ O.Binds.Opcodes = MachOObj.getDyldInfoBindOpcodes();
+}
+
+void MachOReader::readWeakBindInfo(Object &O) const {
+ O.WeakBinds.Opcodes = MachOObj.getDyldInfoWeakBindOpcodes();
+}
+
+void MachOReader::readLazyBindInfo(Object &O) const {
+ O.LazyBinds.Opcodes = MachOObj.getDyldInfoLazyBindOpcodes();
+}
+
+void MachOReader::readExportInfo(Object &O) const {
+ O.Exports.Trie = MachOObj.getDyldInfoExportsTrie();
+}
+
+std::unique_ptr<Object> MachOReader::create() const {
+ auto Obj = llvm::make_unique<Object>();
+ readHeader(*Obj);
+ readLoadCommands(*Obj);
+ readSymbolTable(*Obj);
+ readStringTable(*Obj);
+ readRebaseInfo(*Obj);
+ readBindInfo(*Obj);
+ readWeakBindInfo(*Obj);
+ readLazyBindInfo(*Obj);
+ readExportInfo(*Obj);
+ return Obj;
+}
+
+} // end namespace macho
+} // end namespace objcopy
+} // end namespace llvm
Added: llvm/trunk/tools/llvm-objcopy/MachO/MachOReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/MachO/MachOReader.h?rev=352944&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/MachO/MachOReader.h (added)
+++ llvm/trunk/tools/llvm-objcopy/MachO/MachOReader.h Fri Feb 1 16:38:07 2019
@@ -0,0 +1,49 @@
+//===- MachOReader.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MachOObjcopy.h"
+#include "Object.h"
+#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/Object/MachO.h"
+#include <memory>
+
+namespace llvm {
+namespace objcopy {
+namespace macho {
+
+// The hierarchy of readers is responsible for parsing different inputs:
+// raw binaries and regular MachO object files.
+class Reader {
+public:
+ virtual ~Reader(){};
+ virtual std::unique_ptr<Object> create() const = 0;
+};
+
+class MachOReader : public Reader {
+ const object::MachOObjectFile &MachOObj;
+
+ void readHeader(Object &O) const;
+ void readLoadCommands(Object &O) const;
+ void readSymbolTable(Object &O) const;
+ void readStringTable(Object &O) const;
+ void readRebaseInfo(Object &O) const;
+ void readBindInfo(Object &O) const;
+ void readWeakBindInfo(Object &O) const;
+ void readLazyBindInfo(Object &O) const;
+ void readExportInfo(Object &O) const;
+
+public:
+ explicit MachOReader(const object::MachOObjectFile &Obj) : MachOObj(Obj) {}
+
+ std::unique_ptr<Object> create() const override;
+};
+
+} // end namespace macho
+} // end namespace objcopy
+} // end namespace llvm
Added: llvm/trunk/tools/llvm-objcopy/MachO/MachOWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/MachO/MachOWriter.cpp?rev=352944&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/MachO/MachOWriter.cpp (added)
+++ llvm/trunk/tools/llvm-objcopy/MachO/MachOWriter.cpp Fri Feb 1 16:38:07 2019
@@ -0,0 +1,353 @@
+//===- MachOWriter.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MachOWriter.h"
+#include "../llvm-objcopy.h"
+#include "Object.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/Object/MachO.h"
+#include <memory>
+
+namespace llvm {
+namespace objcopy {
+namespace macho {
+
+size_t MachOWriter::headerSize() const {
+ return Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
+}
+
+size_t MachOWriter::loadCommandsSize() const { return O.Header.SizeOfCmds; }
+
+size_t MachOWriter::symTableSize() const {
+ return O.SymTable.NameList.size() *
+ (Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist));
+}
+
+size_t MachOWriter::strTableSize() const {
+ size_t S = 0;
+ for (const auto &Str : O.StrTable.Strings)
+ S += Str.size();
+ S += (O.StrTable.Strings.empty() ? 0 : O.StrTable.Strings.size() - 1);
+ return S;
+}
+
+size_t MachOWriter::totalSize() const {
+ // Going from tail to head and looking for an appropriate "anchor" to
+ // calculate the total size assuming that all the offsets are either valid
+ // ("true") or 0 (0 indicates that the corresponding part is missing).
+
+ SmallVector<size_t, 7> Ends;
+ if (O.SymTabCommandIndex) {
+ const MachO::symtab_command &SymTabCommand =
+ O.LoadCommands[*O.SymTabCommandIndex]
+ .MachOLoadCommand.symtab_command_data;
+ if (SymTabCommand.symoff) {
+ assert((SymTabCommand.nsyms == O.SymTable.NameList.size()) &&
+ "Incorrect number of symbols");
+ Ends.push_back(SymTabCommand.symoff + symTableSize());
+ }
+ if (SymTabCommand.stroff) {
+ assert((SymTabCommand.strsize == strTableSize()) &&
+ "Incorrect string table size");
+ Ends.push_back(SymTabCommand.stroff + SymTabCommand.strsize);
+ }
+ }
+ if (O.DyLdInfoCommandIndex) {
+ const MachO::dyld_info_command &DyLdInfoCommand =
+ O.LoadCommands[*O.DyLdInfoCommandIndex]
+ .MachOLoadCommand.dyld_info_command_data;
+ if (DyLdInfoCommand.rebase_off) {
+ assert((DyLdInfoCommand.rebase_size == O.Rebases.Opcodes.size()) &&
+ "Incorrect rebase opcodes size");
+ Ends.push_back(DyLdInfoCommand.rebase_off + DyLdInfoCommand.rebase_size);
+ }
+ if (DyLdInfoCommand.bind_off) {
+ assert((DyLdInfoCommand.bind_size == O.Binds.Opcodes.size()) &&
+ "Incorrect bind opcodes size");
+ Ends.push_back(DyLdInfoCommand.bind_off + DyLdInfoCommand.bind_size);
+ }
+ if (DyLdInfoCommand.weak_bind_off) {
+ assert((DyLdInfoCommand.weak_bind_size == O.WeakBinds.Opcodes.size()) &&
+ "Incorrect weak bind opcodes size");
+ Ends.push_back(DyLdInfoCommand.weak_bind_off +
+ DyLdInfoCommand.weak_bind_size);
+ }
+ if (DyLdInfoCommand.lazy_bind_off) {
+ assert((DyLdInfoCommand.lazy_bind_size == O.LazyBinds.Opcodes.size()) &&
+ "Incorrect lazy bind opcodes size");
+ Ends.push_back(DyLdInfoCommand.lazy_bind_off +
+ DyLdInfoCommand.lazy_bind_size);
+ }
+ if (DyLdInfoCommand.export_off) {
+ assert((DyLdInfoCommand.export_size == O.Exports.Trie.size()) &&
+ "Incorrect trie size");
+ Ends.push_back(DyLdInfoCommand.export_off + DyLdInfoCommand.export_size);
+ }
+ }
+
+ // Otherwise, use the last section / reloction.
+ for (const auto &LC : O.LoadCommands)
+ for (const auto &S : LC.Sections) {
+ Ends.push_back(S.Offset + S.Size);
+ if (S.RelOff)
+ Ends.push_back(S.RelOff +
+ S.NReloc * sizeof(MachO::any_relocation_info));
+ }
+
+ if (!Ends.empty())
+ return *std::max_element(Ends.begin(), Ends.end());
+
+ // Otherwise, we have only Mach header and load commands.
+ return headerSize() + loadCommandsSize();
+}
+
+void MachOWriter::writeHeader() {
+ MachO::mach_header_64 Header;
+
+ Header.magic = O.Header.Magic;
+ Header.cputype = O.Header.CPUType;
+ Header.cpusubtype = O.Header.CPUSubType;
+ Header.filetype = O.Header.FileType;
+ Header.ncmds = O.Header.NCmds;
+ Header.sizeofcmds = O.Header.SizeOfCmds;
+ Header.flags = O.Header.Flags;
+ Header.reserved = O.Header.Reserved;
+
+ if (IsLittleEndian != sys::IsLittleEndianHost)
+ MachO::swapStruct(Header);
+
+ auto HeaderSize =
+ Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
+ memcpy(B.getBufferStart(), &Header, HeaderSize);
+}
+
+void MachOWriter::writeLoadCommands() {
+ uint8_t *Begin = B.getBufferStart() + headerSize();
+ MachO::macho_load_command MLC;
+ for (const auto &LC : O.LoadCommands) {
+#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
+ case MachO::LCName: \
+ assert(sizeof(MachO::LCStruct) + LC.Payload.size() == \
+ LC.MachOLoadCommand.load_command_data.cmdsize); \
+ MLC = LC.MachOLoadCommand; \
+ if (IsLittleEndian != sys::IsLittleEndianHost) \
+ MachO::swapStruct(MLC.LCStruct##_data); \
+ memcpy(Begin, &MLC.LCStruct##_data, sizeof(MachO::LCStruct)); \
+ Begin += sizeof(MachO::LCStruct); \
+ memcpy(Begin, LC.Payload.data(), LC.Payload.size()); \
+ Begin += LC.Payload.size(); \
+ break;
+
+ switch (LC.MachOLoadCommand.load_command_data.cmd) {
+ default:
+ assert(sizeof(MachO::load_command) + LC.Payload.size() ==
+ LC.MachOLoadCommand.load_command_data.cmdsize);
+ MLC = LC.MachOLoadCommand;
+ if (IsLittleEndian != sys::IsLittleEndianHost)
+ MachO::swapStruct(MLC.load_command_data);
+ memcpy(Begin, &MLC.load_command_data, sizeof(MachO::load_command));
+ Begin += sizeof(MachO::load_command);
+ memcpy(Begin, LC.Payload.data(), LC.Payload.size());
+ Begin += LC.Payload.size();
+ break;
+#include "llvm/BinaryFormat/MachO.def"
+ }
+ }
+}
+
+void MachOWriter::writeSections() {
+ for (const auto &LC : O.LoadCommands)
+ for (const auto &Sec : LC.Sections) {
+ assert(Sec.Offset && "Section offset can not be zero");
+ assert((Sec.Size == Sec.Content.size()) && "Incorrect section size");
+ memcpy(B.getBufferStart() + Sec.Offset, Sec.Content.data(),
+ Sec.Content.size());
+ for (size_t Index = 0; Index < Sec.Relocations.size(); ++Index) {
+ MachO::any_relocation_info R = Sec.Relocations[Index];
+ if (IsLittleEndian != sys::IsLittleEndianHost)
+ MachO::swapStruct(R);
+ memcpy(B.getBufferStart() + Sec.RelOff +
+ Index * sizeof(MachO::any_relocation_info),
+ &R, sizeof(R));
+ }
+ }
+}
+
+template <typename NListType>
+void writeNListEntry(const NListEntry &NLE, bool IsLittleEndian, char *&Out) {
+ NListType ListEntry;
+ ListEntry.n_strx = NLE.n_strx;
+ ListEntry.n_type = NLE.n_type;
+ ListEntry.n_sect = NLE.n_sect;
+ ListEntry.n_desc = NLE.n_desc;
+ ListEntry.n_value = NLE.n_value;
+
+ if (IsLittleEndian != sys::IsLittleEndianHost)
+ MachO::swapStruct(ListEntry);
+ memcpy(Out, reinterpret_cast<const char *>(&ListEntry), sizeof(NListType));
+ Out += sizeof(NListType);
+}
+
+void MachOWriter::writeSymbolTable() {
+ if (!O.SymTabCommandIndex)
+ return;
+ const MachO::symtab_command &SymTabCommand =
+ O.LoadCommands[*O.SymTabCommandIndex]
+ .MachOLoadCommand.symtab_command_data;
+ assert((SymTabCommand.nsyms == O.SymTable.NameList.size()) &&
+ "Incorrect number of symbols");
+ char *Out = (char *)B.getBufferStart() + SymTabCommand.symoff;
+ for (auto NLE : O.SymTable.NameList) {
+ if (Is64Bit)
+ writeNListEntry<MachO::nlist_64>(NLE, IsLittleEndian, Out);
+ else
+ writeNListEntry<MachO::nlist>(NLE, IsLittleEndian, Out);
+ }
+}
+
+void MachOWriter::writeStringTable() {
+ if (!O.SymTabCommandIndex)
+ return;
+ const MachO::symtab_command &SymTabCommand =
+ O.LoadCommands[*O.SymTabCommandIndex]
+ .MachOLoadCommand.symtab_command_data;
+ char *Out = (char *)B.getBufferStart() + SymTabCommand.stroff;
+ assert((SymTabCommand.strsize == strTableSize()) &&
+ "Incorrect string table size");
+ for (size_t Index = 0; Index < O.StrTable.Strings.size(); ++Index) {
+ memcpy(Out, O.StrTable.Strings[Index].data(),
+ O.StrTable.Strings[Index].size());
+ Out += O.StrTable.Strings[Index].size();
+ if (Index + 1 != O.StrTable.Strings.size()) {
+ memcpy(Out, "\0", 1);
+ Out += 1;
+ }
+ }
+}
+
+void MachOWriter::writeRebaseInfo() {
+ if (!O.DyLdInfoCommandIndex)
+ return;
+ const MachO::dyld_info_command &DyLdInfoCommand =
+ O.LoadCommands[*O.DyLdInfoCommandIndex]
+ .MachOLoadCommand.dyld_info_command_data;
+ char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.rebase_off;
+ assert((DyLdInfoCommand.rebase_size == O.Rebases.Opcodes.size()) &&
+ "Incorrect rebase opcodes size");
+ memcpy(Out, O.Rebases.Opcodes.data(), O.Rebases.Opcodes.size());
+}
+
+void MachOWriter::writeBindInfo() {
+ if (!O.DyLdInfoCommandIndex)
+ return;
+ const MachO::dyld_info_command &DyLdInfoCommand =
+ O.LoadCommands[*O.DyLdInfoCommandIndex]
+ .MachOLoadCommand.dyld_info_command_data;
+ char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.bind_off;
+ assert((DyLdInfoCommand.bind_size == O.Binds.Opcodes.size()) &&
+ "Incorrect bind opcodes size");
+ memcpy(Out, O.Binds.Opcodes.data(), O.Binds.Opcodes.size());
+}
+
+void MachOWriter::writeWeakBindInfo() {
+ if (!O.DyLdInfoCommandIndex)
+ return;
+ const MachO::dyld_info_command &DyLdInfoCommand =
+ O.LoadCommands[*O.DyLdInfoCommandIndex]
+ .MachOLoadCommand.dyld_info_command_data;
+ char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.weak_bind_off;
+ assert((DyLdInfoCommand.weak_bind_size == O.WeakBinds.Opcodes.size()) &&
+ "Incorrect weak bind opcodes size");
+ memcpy(Out, O.WeakBinds.Opcodes.data(), O.WeakBinds.Opcodes.size());
+}
+
+void MachOWriter::writeLazyBindInfo() {
+ if (!O.DyLdInfoCommandIndex)
+ return;
+ const MachO::dyld_info_command &DyLdInfoCommand =
+ O.LoadCommands[*O.DyLdInfoCommandIndex]
+ .MachOLoadCommand.dyld_info_command_data;
+ char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.lazy_bind_off;
+ assert((DyLdInfoCommand.lazy_bind_size == O.LazyBinds.Opcodes.size()) &&
+ "Incorrect lazy bind opcodes size");
+ memcpy(Out, O.LazyBinds.Opcodes.data(), O.LazyBinds.Opcodes.size());
+}
+
+void MachOWriter::writeExportInfo() {
+ if (!O.DyLdInfoCommandIndex)
+ return;
+ const MachO::dyld_info_command &DyLdInfoCommand =
+ O.LoadCommands[*O.DyLdInfoCommandIndex]
+ .MachOLoadCommand.dyld_info_command_data;
+ char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.export_off;
+ assert((DyLdInfoCommand.export_size == O.Exports.Trie.size()) &&
+ "Incorrect export trie size");
+ memcpy(Out, O.Exports.Trie.data(), O.Exports.Trie.size());
+}
+
+void MachOWriter::writeTail() {
+ typedef void (MachOWriter::*WriteHandlerType)(void);
+ typedef std::pair<uint64_t, WriteHandlerType> WriteOperation;
+ SmallVector<WriteOperation, 7> Queue;
+
+ if (O.SymTabCommandIndex) {
+ const MachO::symtab_command &SymTabCommand =
+ O.LoadCommands[*O.SymTabCommandIndex]
+ .MachOLoadCommand.symtab_command_data;
+ if (SymTabCommand.symoff)
+ Queue.push_back({SymTabCommand.symoff, &MachOWriter::writeSymbolTable});
+ if (SymTabCommand.stroff)
+ Queue.push_back({SymTabCommand.stroff, &MachOWriter::writeStringTable});
+ }
+
+ if (O.DyLdInfoCommandIndex) {
+ const MachO::dyld_info_command &DyLdInfoCommand =
+ O.LoadCommands[*O.DyLdInfoCommandIndex]
+ .MachOLoadCommand.dyld_info_command_data;
+ if (DyLdInfoCommand.rebase_off)
+ Queue.push_back(
+ {DyLdInfoCommand.rebase_off, &MachOWriter::writeRebaseInfo});
+ if (DyLdInfoCommand.bind_off)
+ Queue.push_back({DyLdInfoCommand.bind_off, &MachOWriter::writeBindInfo});
+ if (DyLdInfoCommand.weak_bind_off)
+ Queue.push_back(
+ {DyLdInfoCommand.weak_bind_off, &MachOWriter::writeWeakBindInfo});
+ if (DyLdInfoCommand.lazy_bind_off)
+ Queue.push_back(
+ {DyLdInfoCommand.lazy_bind_off, &MachOWriter::writeLazyBindInfo});
+ if (DyLdInfoCommand.export_off)
+ Queue.push_back(
+ {DyLdInfoCommand.export_off, &MachOWriter::writeExportInfo});
+ }
+
+ llvm::sort(Queue, [](const WriteOperation &LHS, const WriteOperation &RHS) {
+ return LHS.first < RHS.first;
+ });
+
+ for (auto WriteOp : Queue)
+ (this->*WriteOp.second)();
+}
+
+Error MachOWriter::write() {
+ if (Error E = B.allocate(totalSize()))
+ return E;
+ memset(B.getBufferStart(), 0, totalSize());
+ writeHeader();
+ writeLoadCommands();
+ writeSections();
+ writeTail();
+ if (auto E = B.commit())
+ return E;
+ return Error::success();
+}
+
+} // end namespace macho
+} // end namespace objcopy
+} // end namespace llvm
Added: llvm/trunk/tools/llvm-objcopy/MachO/MachOWriter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/MachO/MachOWriter.h?rev=352944&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/MachO/MachOWriter.h (added)
+++ llvm/trunk/tools/llvm-objcopy/MachO/MachOWriter.h Fri Feb 1 16:38:07 2019
@@ -0,0 +1,55 @@
+//===- MachOWriter.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../Buffer.h"
+#include "MachOObjcopy.h"
+#include "Object.h"
+#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/Object/MachO.h"
+
+namespace llvm {
+class Error;
+
+namespace objcopy {
+namespace macho {
+
+class MachOWriter {
+ Object &O;
+ bool Is64Bit;
+ bool IsLittleEndian;
+ Buffer &B;
+
+ size_t headerSize() const;
+ size_t loadCommandsSize() const;
+ size_t symTableSize() const;
+ size_t strTableSize() const;
+
+ void writeHeader();
+ void writeLoadCommands();
+ void writeSections();
+ void writeSymbolTable();
+ void writeStringTable();
+ void writeRebaseInfo();
+ void writeBindInfo();
+ void writeWeakBindInfo();
+ void writeLazyBindInfo();
+ void writeExportInfo();
+ void writeTail();
+
+public:
+ MachOWriter(Object &O, bool Is64Bit, bool IsLittleEndian, Buffer &B)
+ : O(O), Is64Bit(Is64Bit), IsLittleEndian(IsLittleEndian), B(B) {}
+
+ size_t totalSize() const;
+ Error write();
+};
+
+} // end namespace macho
+} // end namespace objcopy
+} // end namespace llvm
Added: llvm/trunk/tools/llvm-objcopy/MachO/Object.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/MachO/Object.h?rev=352944&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/MachO/Object.h (added)
+++ llvm/trunk/tools/llvm-objcopy/MachO/Object.h Fri Feb 1 16:38:07 2019
@@ -0,0 +1,209 @@
+//===- Object.h - Mach-O object file model ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJCOPY_MACHO_OBJECT_H
+#define LLVM_OBJCOPY_MACHO_OBJECT_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/ObjectYAML/DWARFYAML.h"
+#include "llvm/Support/YAMLTraits.h"
+#include <cstdint>
+#include <string>
+#include <vector>
+
+namespace llvm {
+namespace objcopy {
+namespace macho {
+
+struct MachHeader {
+ uint32_t Magic;
+ uint32_t CPUType;
+ uint32_t CPUSubType;
+ uint32_t FileType;
+ uint32_t NCmds;
+ uint32_t SizeOfCmds;
+ uint32_t Flags;
+ uint32_t Reserved = 0;
+};
+
+struct Section {
+ char Sectname[16];
+ char Segname[16];
+ uint64_t Addr;
+ uint64_t Size;
+ uint32_t Offset;
+ uint32_t Align;
+ uint32_t RelOff;
+ uint32_t NReloc;
+ uint32_t Flags;
+ uint32_t Reserved1;
+ uint32_t Reserved2;
+ uint32_t Reserved3;
+
+ StringRef Content;
+ std::vector<MachO::any_relocation_info> Relocations;
+};
+
+struct LoadCommand {
+ // The type MachO::macho_load_command is defined in llvm/BinaryFormat/MachO.h
+ // and it is a union of all the structs corresponding to various load
+ // commands.
+ MachO::macho_load_command MachOLoadCommand;
+
+ // The raw content of the payload of the load command (located right after the
+ // corresponding struct). In some cases it is either empty or can be
+ // copied-over without digging into its structure.
+ ArrayRef<uint8_t> Payload;
+
+ // Some load commands can contain (inside the payload) an array of sections,
+ // though the contents of the sections are stored separately. The struct
+ // Section describes only sections' metadata and where to find the
+ // corresponding content inside the binary.
+ std::vector<Section> Sections;
+};
+
+struct NListEntry {
+ uint32_t n_strx;
+ uint8_t n_type;
+ uint8_t n_sect;
+ uint16_t n_desc;
+ uint64_t n_value;
+};
+
+/// The location of the symbol table inside the binary is described by LC_SYMTAB
+/// load command.
+struct SymbolTable {
+ std::vector<NListEntry> NameList;
+};
+
+/// The location of the string table inside the binary is described by LC_SYMTAB
+/// load command.
+struct StringTable {
+ std::vector<std::string> Strings;
+};
+
+/// The location of the rebase info inside the binary is described by
+/// LC_DYLD_INFO load command. Dyld rebases an image whenever dyld loads it at
+/// an address different from its preferred address. The rebase information is
+/// a stream of byte sized opcodes whose symbolic names start with
+/// REBASE_OPCODE_. Conceptually the rebase information is a table of tuples:
+/// <seg-index, seg-offset, type>
+/// The opcodes are a compressed way to encode the table by only
+/// encoding when a column changes. In addition simple patterns
+/// like "every n'th offset for m times" can be encoded in a few
+/// bytes.
+struct RebaseInfo {
+ // At the moment we do not parse this info (and it is simply copied over),
+ // but the proper support will be added later.
+ ArrayRef<uint8_t> Opcodes;
+};
+
+/// The location of the bind info inside the binary is described by
+/// LC_DYLD_INFO load command. Dyld binds an image during the loading process,
+/// if the image requires any pointers to be initialized to symbols in other
+/// images. The bind information is a stream of byte sized opcodes whose
+/// symbolic names start with BIND_OPCODE_. Conceptually the bind information is
+/// a table of tuples: <seg-index, seg-offset, type, symbol-library-ordinal,
+/// symbol-name, addend> The opcodes are a compressed way to encode the table by
+/// only encoding when a column changes. In addition simple patterns like for
+/// runs of pointers initialized to the same value can be encoded in a few
+/// bytes.
+struct BindInfo {
+ // At the moment we do not parse this info (and it is simply copied over),
+ // but the proper support will be added later.
+ ArrayRef<uint8_t> Opcodes;
+};
+
+/// The location of the weak bind info inside the binary is described by
+/// LC_DYLD_INFO load command. Some C++ programs require dyld to unique symbols
+/// so that all images in the process use the same copy of some code/data. This
+/// step is done after binding. The content of the weak_bind info is an opcode
+/// stream like the bind_info. But it is sorted alphabetically by symbol name.
+/// This enable dyld to walk all images with weak binding information in order
+/// and look for collisions. If there are no collisions, dyld does no updating.
+/// That means that some fixups are also encoded in the bind_info. For
+/// instance, all calls to "operator new" are first bound to libstdc++.dylib
+/// using the information in bind_info. Then if some image overrides operator
+/// new that is detected when the weak_bind information is processed and the
+/// call to operator new is then rebound.
+struct WeakBindInfo {
+ // At the moment we do not parse this info (and it is simply copied over),
+ // but the proper support will be added later.
+ ArrayRef<uint8_t> Opcodes;
+};
+
+/// The location of the lazy bind info inside the binary is described by
+/// LC_DYLD_INFO load command. Some uses of external symbols do not need to be
+/// bound immediately. Instead they can be lazily bound on first use. The
+/// lazy_bind contains a stream of BIND opcodes to bind all lazy symbols. Normal
+/// use is that dyld ignores the lazy_bind section when loading an image.
+/// Instead the static linker arranged for the lazy pointer to initially point
+/// to a helper function which pushes the offset into the lazy_bind area for the
+/// symbol needing to be bound, then jumps to dyld which simply adds the offset
+/// to lazy_bind_off to get the information on what to bind.
+struct LazyBindInfo {
+ ArrayRef<uint8_t> Opcodes;
+};
+
+/// The location of the export info inside the binary is described by
+/// LC_DYLD_INFO load command. The symbols exported by a dylib are encoded in a
+/// trie. This is a compact representation that factors out common prefixes. It
+/// also reduces LINKEDIT pages in RAM because it encodes all information (name,
+/// address, flags) in one small, contiguous range. The export area is a stream
+/// of nodes. The first node sequentially is the start node for the trie. Nodes
+/// for a symbol start with a uleb128 that is the length of the exported symbol
+/// information for the string so far. If there is no exported symbol, the node
+/// starts with a zero byte. If there is exported info, it follows the length.
+/// First is a uleb128 containing flags. Normally, it is followed by
+/// a uleb128 encoded offset which is location of the content named
+/// by the symbol from the mach_header for the image. If the flags
+/// is EXPORT_SYMBOL_FLAGS_REEXPORT, then following the flags is
+/// a uleb128 encoded library ordinal, then a zero terminated
+/// UTF8 string. If the string is zero length, then the symbol
+/// is re-export from the specified dylib with the same name.
+/// If the flags is EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER, then following
+/// the flags is two uleb128s: the stub offset and the resolver offset.
+/// The stub is used by non-lazy pointers. The resolver is used
+/// by lazy pointers and must be called to get the actual address to use.
+/// After the optional exported symbol information is a byte of
+/// how many edges (0-255) that this node has leaving it,
+/// followed by each edge.
+/// Each edge is a zero terminated UTF8 of the addition chars
+/// in the symbol, followed by a uleb128 offset for the node that
+/// edge points to.
+struct ExportInfo {
+ ArrayRef<uint8_t> Trie;
+};
+
+struct Object {
+ MachHeader Header;
+ std::vector<LoadCommand> LoadCommands;
+
+ SymbolTable SymTable;
+ StringTable StrTable;
+
+ RebaseInfo Rebases;
+ BindInfo Binds;
+ WeakBindInfo WeakBinds;
+ LazyBindInfo LazyBinds;
+ ExportInfo Exports;
+
+ /// The index of LC_SYMTAB load command if present.
+ Optional<size_t> SymTabCommandIndex;
+ /// The index of LC_DYLD_INFO or LC_DYLD_INFO_ONLY load command if present.
+ Optional<size_t> DyLdInfoCommandIndex;
+};
+
+} // end namespace macho
+} // end namespace objcopy
+} // end namespace llvm
+
+#endif // LLVM_OBJCOPY_MACHO_OBJECT_H
Modified: llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp?rev=352944&r1=352943&r2=352944&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp (original)
+++ llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp Fri Feb 1 16:38:07 2019
@@ -11,6 +11,7 @@
#include "COFF/COFFObjcopy.h"
#include "CopyConfig.h"
#include "ELF/ELFObjcopy.h"
+#include "MachO/MachOObjcopy.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
@@ -23,6 +24,7 @@
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/ELFTypes.h"
#include "llvm/Object/Error.h"
+#include "llvm/Object/MachO.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
@@ -142,6 +144,8 @@ static Error executeObjcopyOnBinary(cons
return elf::executeObjcopyOnBinary(Config, *ELFBinary, Out);
else if (auto *COFFBinary = dyn_cast<object::COFFObjectFile>(&In))
return coff::executeObjcopyOnBinary(Config, *COFFBinary, Out);
+ else if (auto *MachOBinary = dyn_cast<object::MachOObjectFile>(&In))
+ return macho::executeObjcopyOnBinary(Config, *MachOBinary, Out);
else
return createStringError(object_error::invalid_file_type,
"Unsupported object file format");
More information about the llvm-commits
mailing list