forked from OSchip/llvm-project
[llvm-libtool-darwin] Add support for -arch_only
Add support for -arch_only option for llvm-libtool-darwin. This diff also adds support for accepting universal files as input and flattening them to create the required static library. Supports input universal files contaning both Mach-O object files or archives. Differences from cctools' libtool: - `-arch_only` can be specified multiple times - archives containing universal files are considered invalid (libtool allows such archives) Reviewed by jhenderson, smeenai Differential Revision: https://reviews.llvm.org/D84770
This commit is contained in:
parent
05169af5ce
commit
bd2853f799
|
@ -21,6 +21,26 @@ OPTIONS
|
|||
--------
|
||||
:program:`llvm-libtool-darwin` supports the following options:
|
||||
|
||||
.. option:: -arch_only <architecture>
|
||||
|
||||
Build a static library only for the specified `<architecture>` and ignore all
|
||||
other architectures in the files.
|
||||
|
||||
.. option:: -color
|
||||
|
||||
Use colors in output.
|
||||
|
||||
.. option:: -D
|
||||
|
||||
Use zero for timestamps and UIDs/GIDs. This is set by default.
|
||||
|
||||
.. option:: -filelist <listfile[,dirname]>
|
||||
|
||||
Read input file names from `<listfile>`. File names are specified in `<listfile>`
|
||||
one per line, separated only by newlines. Whitespace on a line is assumed
|
||||
to be part of the filename. If the directory name, `dirname`, is also
|
||||
specified then it is prepended to each file name in the `<listfile>`.
|
||||
|
||||
.. option:: -h, -help
|
||||
|
||||
Show help and usage for this command.
|
||||
|
@ -30,36 +50,21 @@ OPTIONS
|
|||
Show help and usage for this command without grouping the options
|
||||
into categories.
|
||||
|
||||
.. option:: -color
|
||||
|
||||
Use colors in output.
|
||||
|
||||
.. option:: -version
|
||||
|
||||
Display the version of this program.
|
||||
|
||||
.. option:: -D
|
||||
|
||||
Use zero for timestamps and UIDs/GIDs. This is set by default.
|
||||
|
||||
.. option:: -U
|
||||
|
||||
Use actual timestamps and UIDs/GIDs.
|
||||
|
||||
.. option:: -o <filename>
|
||||
|
||||
Specify the output file name. Must be specified exactly once.
|
||||
|
||||
.. option:: -static
|
||||
|
||||
Produces a static library from the input files.
|
||||
Produces a static library from the input files.
|
||||
|
||||
.. option:: -filelist <listfile[,dirname]>
|
||||
.. option:: -U
|
||||
|
||||
Read input file names from `<listfile>`. File names are specified in `<listfile>`
|
||||
one per line, separated only by newlines. Whitespace on a line is assumed
|
||||
to be part of the filename. If the directory name, `dirname`, is also
|
||||
specified then it is prepended to each file name in the `<listfile>`.
|
||||
Use actual timestamps and UIDs/GIDs.
|
||||
|
||||
.. option:: -version
|
||||
|
||||
Display the version of this program.
|
||||
|
||||
EXIT STATUS
|
||||
-----------
|
||||
|
|
|
@ -0,0 +1,269 @@
|
|||
## This test checks that the CPU subtype matching logic is handled correctly.
|
||||
|
||||
# RUN: yaml2obj %s --docnum=1 -o %t.armv6
|
||||
# RUN: yaml2obj %s --docnum=2 -o %t.armv7
|
||||
|
||||
# RUN: llvm-libtool-darwin -static -o %t.lib %t.armv6 %t.armv7 -arch_only armv7
|
||||
|
||||
## Check that only armv7 binary is present:
|
||||
# RUN: llvm-ar t %t.lib | \
|
||||
# RUN: FileCheck %s --check-prefix=ARM-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
|
||||
|
||||
# ARM-NAMES: [[PREFIX]].armv7
|
||||
|
||||
## Check that only armv7 symbol is present:
|
||||
# RUN: llvm-nm --print-armap %t.lib | \
|
||||
# RUN: FileCheck %s --check-prefix=ARM-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
|
||||
|
||||
# ARM-SYMBOLS: Archive map
|
||||
# ARM-SYMBOLS-NEXT: _armv7 in [[PREFIX]].armv7
|
||||
# ARM-SYMBOLS-EMPTY:
|
||||
|
||||
## armv6.yaml
|
||||
## CPUTYPE: CPU_TYPE_ARM
|
||||
## CPUSUBTYPE: CPU_SUBTYPE_ARM_V6
|
||||
--- !mach-o
|
||||
FileHeader:
|
||||
magic: 0xFEEDFACE
|
||||
cputype: 0x0000000C
|
||||
cpusubtype: 0x00000006
|
||||
filetype: 0x00000001
|
||||
ncmds: 2
|
||||
sizeofcmds: 148
|
||||
flags: 0x00002000
|
||||
LoadCommands:
|
||||
- cmd: LC_SEGMENT
|
||||
cmdsize: 124
|
||||
segname: ''
|
||||
vmaddr: 0
|
||||
vmsize: 24
|
||||
fileoff: 296
|
||||
filesize: 24
|
||||
maxprot: 7
|
||||
initprot: 7
|
||||
nsects: 1
|
||||
flags: 0
|
||||
Sections:
|
||||
- sectname: __text
|
||||
segname: __TEXT
|
||||
addr: 0x0000000000000000
|
||||
size: 24
|
||||
offset: 0x00000128
|
||||
align: 2
|
||||
reloff: 0x00000000
|
||||
nreloc: 0
|
||||
flags: 0x80000400
|
||||
reserved1: 0x00000000
|
||||
reserved2: 0x00000000
|
||||
reserved3: 0x00000000
|
||||
content: 04D04DE208009FE500008DE504D08DE21EFF2FE100000000
|
||||
- cmd: LC_SYMTAB
|
||||
cmdsize: 24
|
||||
symoff: 328
|
||||
nsyms: 1
|
||||
stroff: 340
|
||||
strsize: 8
|
||||
LinkEditData:
|
||||
NameList:
|
||||
- n_strx: 1
|
||||
n_type: 0x0F
|
||||
n_sect: 1
|
||||
n_desc: 0
|
||||
n_value: 0
|
||||
StringTable:
|
||||
- ''
|
||||
- _armv6
|
||||
- ''
|
||||
...
|
||||
|
||||
## armv7.yaml
|
||||
## CPUTYPE: CPU_TYPE_ARM
|
||||
## CPUSUBTYPE: CPU_SUBTYPE_ARM_V7
|
||||
--- !mach-o
|
||||
FileHeader:
|
||||
magic: 0xFEEDFACE
|
||||
cputype: 0x0000000C
|
||||
cpusubtype: 0x00000009
|
||||
filetype: 0x00000001
|
||||
ncmds: 2
|
||||
sizeofcmds: 148
|
||||
flags: 0x00002000
|
||||
LoadCommands:
|
||||
- cmd: LC_SEGMENT
|
||||
cmdsize: 124
|
||||
segname: ''
|
||||
vmaddr: 0
|
||||
vmsize: 10
|
||||
fileoff: 280
|
||||
filesize: 10
|
||||
maxprot: 7
|
||||
initprot: 7
|
||||
nsects: 1
|
||||
flags: 0
|
||||
Sections:
|
||||
- sectname: __text
|
||||
segname: __TEXT
|
||||
addr: 0x0000000000000000
|
||||
size: 10
|
||||
offset: 0x00000118
|
||||
align: 1
|
||||
reloff: 0x00000000
|
||||
nreloc: 0
|
||||
flags: 0x80000400
|
||||
reserved1: 0x00000000
|
||||
reserved2: 0x00000000
|
||||
reserved3: 0x00000000
|
||||
content: 81B00020009001B07047
|
||||
- cmd: LC_SYMTAB
|
||||
cmdsize: 24
|
||||
symoff: 292
|
||||
nsyms: 1
|
||||
stroff: 304
|
||||
strsize: 8
|
||||
LinkEditData:
|
||||
NameList:
|
||||
- n_strx: 1
|
||||
n_type: 0x0F
|
||||
n_sect: 1
|
||||
n_desc: 8
|
||||
n_value: 0
|
||||
StringTable:
|
||||
- ''
|
||||
- _armv7
|
||||
- ''
|
||||
...
|
||||
|
||||
# RUN: yaml2obj %s --docnum=3 -o %t.x86_64
|
||||
# RUN: yaml2obj %s --docnum=4 -o %t.x86_64_h
|
||||
|
||||
# RUN: llvm-libtool-darwin -static -o %t.lib %t.x86_64 %t.x86_64_h -arch_only x86_64
|
||||
|
||||
## Check that only x86_64 binary is present:
|
||||
# RUN: llvm-ar t %t.lib | \
|
||||
# RUN: FileCheck %s --check-prefix=X86-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
|
||||
|
||||
# X86-NAMES: [[PREFIX]].x86_64
|
||||
|
||||
## Check that only x86_64 symbol is present:
|
||||
# RUN: llvm-nm --print-armap %t.lib | \
|
||||
# RUN: FileCheck %s --check-prefix=X86-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
|
||||
|
||||
# X86-SYMBOLS: Archive map
|
||||
# X86-SYMBOLS-NEXT: _x86_64 in [[PREFIX]].x86_64
|
||||
# X86-SYMBOLS-EMPTY:
|
||||
|
||||
## x86_64.yaml
|
||||
## CPUTYPE: CPU_TYPE_X86_64
|
||||
## CPUSUBTYPE: CPU_SUBTYPE_X86_64_ALL
|
||||
--- !mach-o
|
||||
FileHeader:
|
||||
magic: 0xFEEDFACF
|
||||
cputype: 0x01000007
|
||||
cpusubtype: 0x00000003
|
||||
filetype: 0x00000001
|
||||
ncmds: 2
|
||||
sizeofcmds: 176
|
||||
flags: 0x00002000
|
||||
reserved: 0x00000000
|
||||
LoadCommands:
|
||||
- cmd: LC_SEGMENT_64
|
||||
cmdsize: 152
|
||||
segname: ''
|
||||
vmaddr: 0
|
||||
vmsize: 15
|
||||
fileoff: 312
|
||||
filesize: 15
|
||||
maxprot: 7
|
||||
initprot: 7
|
||||
nsects: 1
|
||||
flags: 0
|
||||
Sections:
|
||||
- sectname: __text
|
||||
segname: __TEXT
|
||||
addr: 0x0000000000000000
|
||||
size: 15
|
||||
offset: 0x00000138
|
||||
align: 4
|
||||
reloff: 0x00000000
|
||||
nreloc: 0
|
||||
flags: 0x80000400
|
||||
reserved1: 0x00000000
|
||||
reserved2: 0x00000000
|
||||
reserved3: 0x00000000
|
||||
content: 554889E531C0C745FC000000005DC3
|
||||
- cmd: LC_SYMTAB
|
||||
cmdsize: 24
|
||||
symoff: 328
|
||||
nsyms: 1
|
||||
stroff: 344
|
||||
strsize: 8
|
||||
LinkEditData:
|
||||
NameList:
|
||||
- n_strx: 1
|
||||
n_type: 0x0F
|
||||
n_sect: 1
|
||||
n_desc: 0
|
||||
n_value: 0
|
||||
StringTable:
|
||||
- ''
|
||||
- _x86_64
|
||||
- ''
|
||||
...
|
||||
|
||||
## x86_64h.yaml
|
||||
## CPUTYPE: CPU_TYPE_X86_64
|
||||
## CPUSUBTYPE: CPU_SUBTYPE_X86_64_H
|
||||
--- !mach-o
|
||||
FileHeader:
|
||||
magic: 0xFEEDFACF
|
||||
cputype: 0x01000007
|
||||
cpusubtype: 0x00000008
|
||||
filetype: 0x00000001
|
||||
ncmds: 2
|
||||
sizeofcmds: 176
|
||||
flags: 0x00002000
|
||||
reserved: 0x00000000
|
||||
LoadCommands:
|
||||
- cmd: LC_SEGMENT_64
|
||||
cmdsize: 152
|
||||
segname: ''
|
||||
vmaddr: 0
|
||||
vmsize: 15
|
||||
fileoff: 312
|
||||
filesize: 15
|
||||
maxprot: 7
|
||||
initprot: 7
|
||||
nsects: 1
|
||||
flags: 0
|
||||
Sections:
|
||||
- sectname: __text
|
||||
segname: __TEXT
|
||||
addr: 0x0000000000000000
|
||||
size: 15
|
||||
offset: 0x00000138
|
||||
align: 4
|
||||
reloff: 0x00000000
|
||||
nreloc: 0
|
||||
flags: 0x80000400
|
||||
reserved1: 0x00000000
|
||||
reserved2: 0x00000000
|
||||
reserved3: 0x00000000
|
||||
content: 554889E531C0C745FC000000005DC3
|
||||
- cmd: LC_SYMTAB
|
||||
cmdsize: 24
|
||||
symoff: 328
|
||||
nsyms: 1
|
||||
stroff: 344
|
||||
strsize: 8
|
||||
LinkEditData:
|
||||
NameList:
|
||||
- n_strx: 1
|
||||
n_type: 0x0F
|
||||
n_sect: 1
|
||||
n_desc: 0
|
||||
n_value: 0
|
||||
StringTable:
|
||||
- ''
|
||||
- _x86_64_h
|
||||
- ''
|
||||
...
|
|
@ -0,0 +1,240 @@
|
|||
## This test checks that a universal file is flattened correctly.
|
||||
|
||||
# RUN: yaml2obj %s -o %t-universal.o
|
||||
# RUN: yaml2obj %S/Inputs/input1.yaml -o %t-input1.o
|
||||
# RUN: yaml2obj %S/Inputs/input2.yaml -o %t-input2.o
|
||||
|
||||
# RUN: llvm-libtool-darwin -static -o %t.lib %t-universal.o -arch_only arm64
|
||||
|
||||
## Check that the binary is present:
|
||||
# RUN: llvm-ar t %t.lib | \
|
||||
# RUN: FileCheck %s --check-prefix=CHECK-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
|
||||
|
||||
# CHECK-NAMES: [[PREFIX]]-universal.o
|
||||
|
||||
## Check that symbols are present:
|
||||
# RUN: llvm-nm --print-armap %t.lib | \
|
||||
# RUN: FileCheck %s --check-prefix=CHECK-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
|
||||
|
||||
# CHECK-SYMBOLS: Archive map
|
||||
# CHECK-SYMBOLS-NEXT: _arm64 in [[PREFIX]]-universal.o
|
||||
# CHECK-SYMBOLS-EMPTY:
|
||||
|
||||
## Check that the output archive is in Darwin format:
|
||||
# RUN: llvm-objdump --macho --archive-headers %t.lib | \
|
||||
# RUN: FileCheck %s --check-prefix=FORMAT -DPREFIX=%basename_t.tmp -DARCHIVE=%t.lib
|
||||
|
||||
# FORMAT: Archive : [[ARCHIVE]]
|
||||
# FORMAT-NEXT: __.SYMDEF
|
||||
# FORMAT-NEXT: [[PREFIX]]-universal.o
|
||||
# FORMAT-NOT: {{.}}
|
||||
|
||||
## Passing both a universal file and an object file:
|
||||
# RUN: llvm-libtool-darwin -static -o %t.lib %t-universal.o %t-input1.o -arch_only x86_64
|
||||
# RUN: llvm-ar t %t.lib | \
|
||||
# RUN: FileCheck %s --check-prefix=BOTH-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
|
||||
# RUN: llvm-nm --print-armap %t.lib | \
|
||||
# RUN: FileCheck %s --check-prefix=BOTH-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
|
||||
|
||||
# BOTH-NAMES: [[PREFIX]]-universal.o
|
||||
# BOTH-NAMES-NEXT: [[PREFIX]]-input1.o
|
||||
|
||||
# BOTH-SYMBOLS: Archive map
|
||||
# BOTH-SYMBOLS-NEXT: _x86_64 in [[PREFIX]]-universal.o
|
||||
# BOTH-SYMBOLS-NEXT: _symbol1 in [[PREFIX]]-input1.o
|
||||
# BOTH-SYMBOLS-EMPTY:
|
||||
|
||||
## Passing both a universal file and an object file but filtering out the object file:
|
||||
# RUN: llvm-libtool-darwin -static -o %t.lib %t-universal.o %t-input1.o -arch_only arm64
|
||||
# RUN: llvm-ar t %t.lib | \
|
||||
# RUN: FileCheck %s --check-prefix=CHECK-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
|
||||
# RUN: llvm-nm --print-armap %t.lib | \
|
||||
# RUN: FileCheck %s --check-prefix=CHECK-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
|
||||
|
||||
## Universal file containing an archive:
|
||||
# RUN: rm -f %t.ar
|
||||
# RUN: llvm-ar cr %t.ar %t-input1.o %t-input2.o
|
||||
# RUN: llvm-lipo %t.ar -create -output %t-fat-with-archive.o
|
||||
# RUN: llvm-libtool-darwin -static -o %t.lib %t-fat-with-archive.o -arch_only x86_64
|
||||
# RUN: llvm-ar t %t.lib | \
|
||||
# RUN: FileCheck %s --check-prefix=ARCHIVE-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
|
||||
# RUN: llvm-nm --print-armap %t.lib | \
|
||||
# RUN: FileCheck %s --check-prefix=ARCHIVE-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
|
||||
|
||||
# ARCHIVE-NAMES: [[PREFIX]]-input1.o
|
||||
# ARCHIVE-NAMES-NEXT: [[PREFIX]]-input2.o
|
||||
|
||||
# ARCHIVE-SYMBOLS: Archive map
|
||||
# ARCHIVE-SYMBOLS-NEXT: _symbol1 in [[PREFIX]]-input1.o
|
||||
# ARCHIVE-SYMBOLS-NEXT: _symbol2 in [[PREFIX]]-input2.o
|
||||
# ARCHIVE-SYMBOLS-EMPTY:
|
||||
|
||||
## Allow arch_only to be specified more than once (pick the last one):
|
||||
# RUN: llvm-libtool-darwin -static -o %t.lib %t-universal.o -arch_only arm64 -arch_only x86_64
|
||||
# RUN: llvm-ar t %t.lib | \
|
||||
# RUN: FileCheck %s --check-prefix=DOUBLE-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
|
||||
# RUN: llvm-nm --print-armap %t.lib | \
|
||||
# RUN: FileCheck %s --check-prefix=DOUBLE-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
|
||||
|
||||
# DOUBLE-NAMES: [[PREFIX]]-universal.o
|
||||
|
||||
# DOUBLE-SYMBOLS: Archive map
|
||||
# DOUBLE-SYMBOLS-NEXT: _x86_64 in [[PREFIX]]-universal.o
|
||||
# DOUBLE-SYMBOLS-EMPTY:
|
||||
|
||||
## Invalid architecture:
|
||||
# RUN: not llvm-libtool-darwin -static -o %t.lib %t-universal.o -arch_only arch101 2>&1 | \
|
||||
# RUN: FileCheck %s --check-prefix=INVALID-ARCH
|
||||
|
||||
# INVALID-ARCH: invalid architecture 'arch101': valid architecture names are
|
||||
|
||||
## Empty architecture:
|
||||
# RUN: not llvm-libtool-darwin -static -o %t.lib %t-universal.o -arch_only "" 2>&1 | \
|
||||
# RUN: FileCheck %s --check-prefix=EMPTY-ARCH
|
||||
|
||||
# EMPTY-ARCH: invalid architecture '': valid architecture names are
|
||||
|
||||
## Missing architecture:
|
||||
# RUN: not llvm-libtool-darwin -static -o %t.lib %t-universal.o -arch_only ppc 2>&1 | \
|
||||
# RUN: FileCheck %s --check-prefix=MISSING-ARCH
|
||||
|
||||
# MISSING-ARCH: error: no library created (no object files in input files matching -arch_only ppc)
|
||||
|
||||
## arch_only missing argument:
|
||||
# RUN: not llvm-libtool-darwin -static -o %t.lib %t-universal.o -arch_only 2>&1 | \
|
||||
# RUN: FileCheck %s --check-prefix=REQUIRE-ARCH
|
||||
|
||||
# REQUIRE-ARCH: for the --arch_only option: requires a value!
|
||||
|
||||
## x86_64-arm64-universal.yaml
|
||||
--- !fat-mach-o
|
||||
FatHeader:
|
||||
magic: 0xCAFEBABE
|
||||
nfat_arch: 2
|
||||
FatArchs:
|
||||
- cputype: 0x01000007
|
||||
cpusubtype: 0x00000003
|
||||
offset: 0x0000000000001000
|
||||
size: 352
|
||||
align: 12
|
||||
- cputype: 0x0100000C
|
||||
cpusubtype: 0x00000000
|
||||
offset: 0x0000000000004000
|
||||
size: 384
|
||||
align: 14
|
||||
Slices:
|
||||
- !mach-o
|
||||
FileHeader:
|
||||
magic: 0xFEEDFACF
|
||||
cputype: 0x01000007
|
||||
cpusubtype: 0x00000003
|
||||
filetype: 0x00000001
|
||||
ncmds: 2
|
||||
sizeofcmds: 176
|
||||
flags: 0x00002000
|
||||
reserved: 0x00000000
|
||||
LoadCommands:
|
||||
- cmd: LC_SEGMENT_64
|
||||
cmdsize: 152
|
||||
segname: ''
|
||||
vmaddr: 0
|
||||
vmsize: 15
|
||||
fileoff: 312
|
||||
filesize: 15
|
||||
maxprot: 7
|
||||
initprot: 7
|
||||
nsects: 1
|
||||
flags: 0
|
||||
Sections:
|
||||
- sectname: __text
|
||||
segname: __TEXT
|
||||
addr: 0x0000000000000000
|
||||
size: 15
|
||||
offset: 0x00000138
|
||||
align: 4
|
||||
reloff: 0x00000000
|
||||
nreloc: 0
|
||||
flags: 0x80000400
|
||||
reserved1: 0x00000000
|
||||
reserved2: 0x00000000
|
||||
reserved3: 0x00000000
|
||||
content: 554889E531C0C745FC000000005DC3
|
||||
- cmd: LC_SYMTAB
|
||||
cmdsize: 24
|
||||
symoff: 328
|
||||
nsyms: 1
|
||||
stroff: 344
|
||||
strsize: 8
|
||||
LinkEditData:
|
||||
NameList:
|
||||
- n_strx: 1
|
||||
n_type: 0x0F
|
||||
n_sect: 1
|
||||
n_desc: 0
|
||||
n_value: 0
|
||||
StringTable:
|
||||
- ''
|
||||
- _x86_64
|
||||
- ''
|
||||
- !mach-o
|
||||
FileHeader:
|
||||
magic: 0xFEEDFACF
|
||||
cputype: 0x0100000C
|
||||
cpusubtype: 0x00000000
|
||||
filetype: 0x00000001
|
||||
ncmds: 2
|
||||
sizeofcmds: 176
|
||||
flags: 0x00002000
|
||||
reserved: 0x00000000
|
||||
LoadCommands:
|
||||
- cmd: LC_SEGMENT_64
|
||||
cmdsize: 152
|
||||
segname: ''
|
||||
vmaddr: 0
|
||||
vmsize: 24
|
||||
fileoff: 312
|
||||
filesize: 24
|
||||
maxprot: 7
|
||||
initprot: 7
|
||||
nsects: 1
|
||||
flags: 0
|
||||
Sections:
|
||||
- sectname: __text
|
||||
segname: __TEXT
|
||||
addr: 0x0000000000000000
|
||||
size: 24
|
||||
offset: 0x00000138
|
||||
align: 2
|
||||
reloff: 0x00000000
|
||||
nreloc: 0
|
||||
flags: 0x80000400
|
||||
reserved1: 0x00000000
|
||||
reserved2: 0x00000000
|
||||
reserved3: 0x00000000
|
||||
content: FF4300D1FF0F00B908008052E00308AAFF430091C0035FD6
|
||||
- cmd: LC_SYMTAB
|
||||
cmdsize: 24
|
||||
symoff: 336
|
||||
nsyms: 2
|
||||
stroff: 368
|
||||
strsize: 16
|
||||
LinkEditData:
|
||||
NameList:
|
||||
- n_strx: 7
|
||||
n_type: 0x0E
|
||||
n_sect: 1
|
||||
n_desc: 0
|
||||
n_value: 0
|
||||
- n_strx: 1
|
||||
n_type: 0x0F
|
||||
n_sect: 1
|
||||
n_desc: 0
|
||||
n_value: 0
|
||||
StringTable:
|
||||
- ''
|
||||
- _arm64
|
||||
- ltmp0
|
||||
- ''
|
||||
- ''
|
||||
- ''
|
||||
...
|
|
@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS
|
|||
BinaryFormat
|
||||
Object
|
||||
Support
|
||||
TextAPI
|
||||
)
|
||||
|
||||
add_llvm_tool(llvm-libtool-darwin
|
||||
|
|
|
@ -17,4 +17,4 @@
|
|||
type = Tool
|
||||
name = llvm-libtool-darwin
|
||||
parent = Tools
|
||||
required_libraries = BinaryFormat Object Support
|
||||
required_libraries = BinaryFormat Object Support TextAPI
|
||||
|
|
|
@ -13,11 +13,13 @@
|
|||
#include "llvm/BinaryFormat/Magic.h"
|
||||
#include "llvm/Object/ArchiveWriter.h"
|
||||
#include "llvm/Object/MachO.h"
|
||||
#include "llvm/Object/MachOUniversal.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/InitLLVM.h"
|
||||
#include "llvm/Support/LineIterator.h"
|
||||
#include "llvm/Support/WithColor.h"
|
||||
#include "llvm/TextAPI/MachO/Architecture.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
|
@ -33,6 +35,10 @@ static cl::list<std::string> InputFiles(cl::Positional,
|
|||
cl::ZeroOrMore,
|
||||
cl::cat(LibtoolCategory));
|
||||
|
||||
static cl::opt<std::string> ArchType(
|
||||
"arch_only", cl::desc("Specify architecture type for output library"),
|
||||
cl::value_desc("arch_type"), cl::ZeroOrMore, cl::cat(LibtoolCategory));
|
||||
|
||||
enum class Operation { Static };
|
||||
|
||||
static cl::opt<Operation> LibraryOperation(
|
||||
|
@ -92,7 +98,51 @@ static Error processFileList() {
|
|||
return Error::success();
|
||||
}
|
||||
|
||||
static Error verifyMachOObject(const NewArchiveMember &Member) {
|
||||
static Error validateArchitectureName(StringRef ArchitectureName) {
|
||||
if (!MachOObjectFile::isValidArch(ArchitectureName)) {
|
||||
std::string Buf;
|
||||
raw_string_ostream OS(Buf);
|
||||
for (StringRef Arch : MachOObjectFile::getValidArchs())
|
||||
OS << Arch << " ";
|
||||
|
||||
return createStringError(
|
||||
std::errc::invalid_argument,
|
||||
"invalid architecture '%s': valid architecture names are %s",
|
||||
ArchitectureName.str().c_str(), OS.str().c_str());
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
// Check that a file's architecture [FileCPUType, FileCPUSubtype]
|
||||
// matches the architecture specified under -arch_only flag.
|
||||
static bool acceptFileArch(uint32_t FileCPUType, uint32_t FileCPUSubtype) {
|
||||
uint32_t ArchCPUType, ArchCPUSubtype;
|
||||
std::tie(ArchCPUType, ArchCPUSubtype) = MachO::getCPUTypeFromArchitecture(
|
||||
MachO::getArchitectureFromName(ArchType));
|
||||
|
||||
if (ArchCPUType != FileCPUType)
|
||||
return false;
|
||||
|
||||
switch (ArchCPUType) {
|
||||
case MachO::CPU_TYPE_ARM:
|
||||
case MachO::CPU_TYPE_ARM64_32:
|
||||
case MachO::CPU_TYPE_X86_64:
|
||||
return ArchCPUSubtype == FileCPUSubtype;
|
||||
|
||||
case MachO::CPU_TYPE_ARM64:
|
||||
if (ArchCPUSubtype == MachO::CPU_SUBTYPE_ARM64_ALL)
|
||||
return FileCPUSubtype == MachO::CPU_SUBTYPE_ARM64_ALL ||
|
||||
FileCPUSubtype == MachO::CPU_SUBTYPE_ARM64_V8;
|
||||
else
|
||||
return ArchCPUSubtype == FileCPUSubtype;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static Error verifyAndAddMachOObject(std::vector<NewArchiveMember> &Members,
|
||||
NewArchiveMember Member) {
|
||||
auto MBRef = Member.Buf->getMemBufferRef();
|
||||
Expected<std::unique_ptr<object::ObjectFile>> ObjOrErr =
|
||||
object::ObjectFile::createObjectFile(MBRef);
|
||||
|
@ -107,6 +157,18 @@ static Error verifyMachOObject(const NewArchiveMember &Member) {
|
|||
"'%s': format not supported",
|
||||
Member.MemberName.data());
|
||||
|
||||
auto *O = dyn_cast<MachOObjectFile>(ObjOrErr->get());
|
||||
uint32_t FileCPUType, FileCPUSubtype;
|
||||
std::tie(FileCPUType, FileCPUSubtype) = MachO::getCPUTypeFromArchitecture(
|
||||
MachO::getArchitectureFromName(O->getArchTriple().getArchName()));
|
||||
|
||||
// If -arch_only is specified then skip this file if it doesn't match
|
||||
// the architecture specified.
|
||||
if (!ArchType.empty() && !acceptFileArch(FileCPUType, FileCPUSubtype)) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Members.push_back(std::move(Member));
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
|
@ -117,18 +179,94 @@ static Error addChildMember(std::vector<NewArchiveMember> &Members,
|
|||
if (!NMOrErr)
|
||||
return NMOrErr.takeError();
|
||||
|
||||
// Verify that Member is a Mach-O object file.
|
||||
if (Error E = verifyMachOObject(*NMOrErr))
|
||||
if (Error E = verifyAndAddMachOObject(Members, std::move(*NMOrErr)))
|
||||
return E;
|
||||
|
||||
Members.push_back(std::move(*NMOrErr));
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static Error processArchive(std::vector<NewArchiveMember> &Members,
|
||||
object::Archive &Lib, StringRef FileName,
|
||||
const Config &C) {
|
||||
Error Err = Error::success();
|
||||
for (const object::Archive::Child &Child : Lib.children(Err))
|
||||
if (Error E = addChildMember(Members, Child, C))
|
||||
return createFileError(FileName, std::move(E));
|
||||
if (Err)
|
||||
return createFileError(FileName, std::move(Err));
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static Error
|
||||
addMember(std::vector<NewArchiveMember> &Members, StringRef FileName,
|
||||
std::vector<std::unique_ptr<MemoryBuffer>> &ArchiveBuffers,
|
||||
const Config &C) {
|
||||
addArchiveMembers(std::vector<NewArchiveMember> &Members,
|
||||
std::vector<std::unique_ptr<MemoryBuffer>> &ArchiveBuffers,
|
||||
NewArchiveMember NM, StringRef FileName, const Config &C) {
|
||||
Expected<std::unique_ptr<Archive>> LibOrErr =
|
||||
object::Archive::create(NM.Buf->getMemBufferRef());
|
||||
if (!LibOrErr)
|
||||
return createFileError(FileName, LibOrErr.takeError());
|
||||
|
||||
if (Error E = processArchive(Members, **LibOrErr, FileName, C))
|
||||
return E;
|
||||
|
||||
// Update vector ArchiveBuffers with the MemoryBuffers to transfer
|
||||
// ownership.
|
||||
ArchiveBuffers.push_back(std::move(NM.Buf));
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static Error addUniversalMembers(
|
||||
std::vector<NewArchiveMember> &Members,
|
||||
std::vector<std::unique_ptr<MemoryBuffer>> &UniversalBuffers,
|
||||
NewArchiveMember NM, StringRef FileName, const Config &C) {
|
||||
Expected<std::unique_ptr<MachOUniversalBinary>> BinaryOrErr =
|
||||
MachOUniversalBinary::create(NM.Buf->getMemBufferRef());
|
||||
if (!BinaryOrErr)
|
||||
return createFileError(FileName, BinaryOrErr.takeError());
|
||||
|
||||
auto *UO = BinaryOrErr->get();
|
||||
for (const MachOUniversalBinary::ObjectForArch &O : UO->objects()) {
|
||||
|
||||
Expected<std::unique_ptr<MachOObjectFile>> MachOObjOrErr =
|
||||
O.getAsObjectFile();
|
||||
if (MachOObjOrErr) {
|
||||
NewArchiveMember NewMember =
|
||||
NewArchiveMember(MachOObjOrErr->get()->getMemoryBufferRef());
|
||||
NewMember.MemberName = sys::path::filename(NewMember.MemberName);
|
||||
|
||||
if (Error E = verifyAndAddMachOObject(Members, std::move(NewMember)))
|
||||
return E;
|
||||
continue;
|
||||
}
|
||||
|
||||
Expected<std::unique_ptr<Archive>> ArchiveOrError = O.getAsArchive();
|
||||
if (ArchiveOrError) {
|
||||
// A universal file member can either be a MachOObjectFile or an Archive.
|
||||
// In case we can successfully cast the member as an Archive, it is safe
|
||||
// to throw away the error generated due to casting the object as a
|
||||
// MachOObjectFile.
|
||||
consumeError(MachOObjOrErr.takeError());
|
||||
|
||||
if (Error E = processArchive(Members, **ArchiveOrError, FileName, C))
|
||||
return E;
|
||||
continue;
|
||||
}
|
||||
|
||||
Error CombinedError =
|
||||
joinErrors(ArchiveOrError.takeError(), MachOObjOrErr.takeError());
|
||||
return createFileError(FileName, std::move(CombinedError));
|
||||
}
|
||||
|
||||
// Update vector UniversalBuffers with the MemoryBuffers to transfer
|
||||
// ownership.
|
||||
UniversalBuffers.push_back(std::move(NM.Buf));
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static Error addMember(std::vector<NewArchiveMember> &Members,
|
||||
std::vector<std::unique_ptr<MemoryBuffer>> &FileBuffers,
|
||||
StringRef FileName, const Config &C) {
|
||||
Expected<NewArchiveMember> NMOrErr =
|
||||
NewArchiveMember::getFile(FileName, C.Deterministic);
|
||||
if (!NMOrErr)
|
||||
|
@ -137,43 +275,36 @@ addMember(std::vector<NewArchiveMember> &Members, StringRef FileName,
|
|||
// For regular archives, use the basename of the object path for the member
|
||||
// name.
|
||||
NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName);
|
||||
file_magic Magic = identify_magic(NMOrErr->Buf->getBuffer());
|
||||
|
||||
// Flatten archives.
|
||||
if (identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {
|
||||
Expected<std::unique_ptr<Archive>> LibOrErr =
|
||||
object::Archive::create(NMOrErr->Buf->getMemBufferRef());
|
||||
if (!LibOrErr)
|
||||
return createFileError(FileName, LibOrErr.takeError());
|
||||
object::Archive &Lib = **LibOrErr;
|
||||
if (Magic == file_magic::archive)
|
||||
return addArchiveMembers(Members, FileBuffers, std::move(*NMOrErr),
|
||||
FileName, C);
|
||||
|
||||
Error Err = Error::success();
|
||||
for (const object::Archive::Child &Child : Lib.children(Err))
|
||||
if (Error E = addChildMember(Members, Child, C))
|
||||
return createFileError(FileName, std::move(E));
|
||||
if (Err)
|
||||
return createFileError(FileName, std::move(Err));
|
||||
// Flatten universal files.
|
||||
if (Magic == file_magic::macho_universal_binary)
|
||||
return addUniversalMembers(Members, FileBuffers, std::move(*NMOrErr),
|
||||
FileName, C);
|
||||
|
||||
// Update vector ArchiveBuffers with the MemoryBuffers to transfer
|
||||
// ownership.
|
||||
ArchiveBuffers.push_back(std::move(NMOrErr->Buf));
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
// Verify that Member is a Mach-O object file.
|
||||
if (Error E = verifyMachOObject(*NMOrErr))
|
||||
if (Error E = verifyAndAddMachOObject(Members, std::move(*NMOrErr)))
|
||||
return E;
|
||||
|
||||
Members.push_back(std::move(*NMOrErr));
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static Error createStaticLibrary(const Config &C) {
|
||||
std::vector<NewArchiveMember> NewMembers;
|
||||
std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers;
|
||||
for (StringRef Member : InputFiles)
|
||||
if (Error E = addMember(NewMembers, Member, ArchiveBuffers, C))
|
||||
std::vector<std::unique_ptr<MemoryBuffer>> FileBuffers;
|
||||
for (StringRef FileName : InputFiles)
|
||||
if (Error E = addMember(NewMembers, FileBuffers, FileName, C))
|
||||
return E;
|
||||
|
||||
if (NewMembers.empty() && !ArchType.empty())
|
||||
return createStringError(std::errc::invalid_argument,
|
||||
"no library created (no object files in input "
|
||||
"files matching -arch_only %s)",
|
||||
ArchType.c_str());
|
||||
|
||||
if (Error E =
|
||||
writeArchive(OutputFile, NewMembers,
|
||||
/*WriteSymtab=*/true,
|
||||
|
@ -201,6 +332,10 @@ static Expected<Config> parseCommandLine(int Argc, char **Argv) {
|
|||
return createStringError(std::errc::invalid_argument,
|
||||
"no input files specified");
|
||||
|
||||
if (ArchType.getNumOccurrences())
|
||||
if (Error E = validateArchitectureName(ArchType))
|
||||
return std::move(E);
|
||||
|
||||
return C;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue