[readtapi] Setup simple stubify support (#76075)

Stubify broadly takes either tbd files or binary dylibs and turns them
into tbd files. In future patches, stubify will also allow additional
information to be embedded into the final TBD output too.

Add Util APIs to TextAPI for common operations used by readtapi for now.
This commit is contained in:
Cyndy Ishida
2023-12-20 14:56:53 -08:00
committed by GitHub
parent 8773c9be3d
commit c6f29dbb59
16 changed files with 6022 additions and 85 deletions

View File

@@ -0,0 +1,34 @@
//===- llvm/TextAPI/Utils.h - TAPI Utils -----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Helper functionality used for Darwin specific operations.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TEXTAPI_UTILS_H
#define LLVM_TEXTAPI_UTILS_H
#include "llvm/ADT/Twine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#if !defined(PATH_MAX)
#define PATH_MAX 1024
#endif
namespace llvm::MachO {
using PathSeq = std::vector<std::string>;
/// Replace extension considering frameworks.
///
/// \param Path Location of file.
/// \param Extension File extension to update with.
void replace_extension(SmallVectorImpl<char> &Path, const Twine &Extension);
} // namespace llvm::MachO
#endif // LLVM_TEXTAPI_UTILS_H

View File

@@ -13,6 +13,7 @@ add_llvm_component_library(LLVMTextAPI
TextAPIError.cpp
TextStub.cpp
TextStubCommon.cpp
Utils.cpp
ADDITIONAL_HEADER_DIRS
"${LLVM_MAIN_INCLUDE_DIR}/llvm/TextAPI"

View File

@@ -0,0 +1,40 @@
//===- Utils.cpp ----------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Implements utility functions for TextAPI Darwin operations.
//
//===----------------------------------------------------------------------===//
#include "llvm/TextAPI/Utils.h"
using namespace llvm;
using namespace llvm::MachO;
void llvm::MachO::replace_extension(SmallVectorImpl<char> &Path,
const Twine &Extension) {
StringRef P(Path.begin(), Path.size());
auto ParentPath = sys::path::parent_path(P);
auto Filename = sys::path::filename(P);
if (!ParentPath.ends_with(Filename.str() + ".framework")) {
sys::path::replace_extension(Path, Extension);
return;
}
// Framework dylibs do not have a file extension, in those cases the new
// extension is appended. e.g. given Path: "Foo.framework/Foo" and Extension:
// "tbd", the result is "Foo.framework/Foo.tbd".
SmallString<8> Storage;
StringRef Ext = Extension.toStringRef(Storage);
// Append '.' if needed.
if (!Ext.empty() && Ext[0] != '.')
Path.push_back('.');
// Append extension.
Path.append(Ext.begin(), Ext.end());
}

View File

@@ -0,0 +1,328 @@
--- !mach-o
FileHeader:
magic: 0xFEEDFACF
cputype: 0x01000007
cpusubtype: 0x00000003
filetype: 0x00000006
ncmds: 13
sizeofcmds: 1128
flags: 0x00100004
reserved: 0x00000000
LoadCommands:
- cmd: LC_SEGMENT_64
cmdsize: 392
segname: __TEXT
vmaddr: 0
vmsize: 4096
fileoff: 0
filesize: 4096
maxprot: 7
initprot: 5
nsects: 4
flags: 0
Sections:
- sectname: __text
segname: __TEXT
addr: 0x0000000000000F60
size: 44
offset: 0x00000F60
align: 4
reloff: 0x00000000
nreloc: 0
flags: 0x80000400
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
content: 554889E54883EC10897DFCBF7A000000E817000000488B0D940000008B39037DFC8945F889F84883C4105DC3
- sectname: __stubs
segname: __TEXT
addr: 0x0000000000000F8C
size: 6
offset: 0x00000F8C
align: 1
reloff: 0x00000000
nreloc: 0
flags: 0x80000408
reserved1: 0x00000000
reserved2: 0x00000006
reserved3: 0x00000000
content: FF2586000000
- sectname: __stub_helper
segname: __TEXT
addr: 0x0000000000000F94
size: 26
offset: 0x00000F94
align: 2
reloff: 0x00000000
nreloc: 0
flags: 0x80000400
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
content: 4C8D1D6D0000004153FF255D000000906800000000E9E6FFFFFF
- sectname: __unwind_info
segname: __TEXT
addr: 0x0000000000000FB0
size: 72
offset: 0x00000FB0
align: 2
reloff: 0x00000000
nreloc: 0
flags: 0x00000000
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
content: 010000001C000000000000001C000000000000001C00000002000000600F000034000000340000008D0F00000000000034000000030000000C000100100001000000000000000001
- cmd: LC_SEGMENT_64
cmdsize: 312
segname: __DATA
vmaddr: 4096
vmsize: 4096
fileoff: 4096
filesize: 4096
maxprot: 7
initprot: 3
nsects: 3
flags: 0
Sections:
- sectname: __nl_symbol_ptr
segname: __DATA
addr: 0x0000000000001000
size: 16
offset: 0x00001000
align: 3
reloff: 0x00000000
nreloc: 0
flags: 0x00000006
reserved1: 0x00000001
reserved2: 0x00000000
reserved3: 0x00000000
content: '00000000000000000000000000000000'
- sectname: __got
segname: __DATA
addr: 0x0000000000001010
size: 8
offset: 0x00001010
align: 3
reloff: 0x00000000
nreloc: 0
flags: 0x00000006
reserved1: 0x00000003
reserved2: 0x00000000
reserved3: 0x00000000
content: '0000000000000000'
- sectname: __la_symbol_ptr
segname: __DATA
addr: 0x0000000000001018
size: 8
offset: 0x00001018
align: 3
reloff: 0x00000000
nreloc: 0
flags: 0x00000007
reserved1: 0x00000004
reserved2: 0x00000000
reserved3: 0x00000000
content: A40F000000000000
- cmd: LC_SEGMENT_64
cmdsize: 72
segname: __LINKEDIT
vmaddr: 8192
vmsize: 4096
fileoff: 8192
filesize: 220
maxprot: 7
initprot: 1
nsects: 0
flags: 0
- cmd: LC_ID_DYLIB
cmdsize: 40
dylib:
name: 24
timestamp: 1
current_version: 0
compatibility_version: 0
Content: foo.dylib
ZeroPadBytes: 7
- cmd: LC_DYLD_INFO_ONLY
cmdsize: 48
rebase_off: 8192
rebase_size: 8
bind_off: 8200
bind_size: 48
weak_bind_off: 0
weak_bind_size: 0
lazy_bind_off: 8248
lazy_bind_size: 16
export_off: 8264
export_size: 16
- cmd: LC_SYMTAB
cmdsize: 24
symoff: 8288
nsyms: 4
stroff: 8372
strsize: 40
- cmd: LC_DYSYMTAB
cmdsize: 80
ilocalsym: 0
nlocalsym: 0
iextdefsym: 0
nextdefsym: 1
iundefsym: 1
nundefsym: 3
tocoff: 0
ntoc: 0
modtaboff: 0
nmodtab: 0
extrefsymoff: 0
nextrefsyms: 0
indirectsymoff: 8352
nindirectsyms: 5
extreloff: 0
nextrel: 0
locreloff: 0
nlocrel: 0
- cmd: LC_UUID
cmdsize: 24
uuid: 24AE602E-6B89-37A8-9E38-39A436D25110
- cmd: LC_BUILD_VERSION
cmdsize: 32
platform: 1
minos: 658944
sdk: 658944
ntools: 1
Tools:
- tool: 3
version: 29491968
- cmd: LC_SOURCE_VERSION
cmdsize: 16
version: 0
- cmd: LC_LOAD_DYLIB
cmdsize: 56
dylib:
name: 24
timestamp: 2
current_version: 82115073
compatibility_version: 65536
Content: '/usr/lib/libSystem.B.dylib'
ZeroPadBytes: 6
- cmd: LC_FUNCTION_STARTS
cmdsize: 16
dataoff: 8280
datasize: 8
- cmd: LC_DATA_IN_CODE
cmdsize: 16
dataoff: 8288
datasize: 0
LinkEditData:
RebaseOpcodes:
- Opcode: REBASE_OPCODE_SET_TYPE_IMM
Imm: 1
- Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Imm: 1
ExtraData:
- 0x0000000000000018
- Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES
Imm: 1
- Opcode: REBASE_OPCODE_DONE
Imm: 0
BindOpcodes:
- Opcode: BIND_OPCODE_SET_DYLIB_SPECIAL_IMM
Imm: 14
Symbol: ''
- Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
Imm: 0
Symbol: _bar
- Opcode: BIND_OPCODE_SET_TYPE_IMM
Imm: 1
Symbol: ''
- Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Imm: 1
ULEBExtraData:
- 0x0000000000000010
Symbol: ''
- Opcode: BIND_OPCODE_DO_BIND
Imm: 0
Symbol: ''
- Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
Imm: 0
Symbol: dyld_stub_binder
- Opcode: BIND_OPCODE_ADD_ADDR_ULEB
Imm: 0
ULEBExtraData:
- 0xFFFFFFFFFFFFFFE8
Symbol: ''
- Opcode: BIND_OPCODE_DO_BIND
Imm: 0
Symbol: ''
- Opcode: BIND_OPCODE_DONE
Imm: 0
Symbol: ''
LazyBindOpcodes:
- Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Imm: 1
ULEBExtraData:
- 0x0000000000000018
Symbol: ''
- Opcode: BIND_OPCODE_SET_DYLIB_SPECIAL_IMM
Imm: 14
Symbol: ''
- Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
Imm: 0
Symbol: _putchar
- Opcode: BIND_OPCODE_DO_BIND
Imm: 0
Symbol: ''
- Opcode: BIND_OPCODE_DONE
Imm: 0
Symbol: ''
- Opcode: BIND_OPCODE_DONE
Imm: 0
Symbol: ''
ExportTrie:
TerminalSize: 0
NodeOffset: 0
Name: ''
Flags: 0x0000000000000000
Address: 0x0000000000000000
Other: 0x0000000000000000
ImportName: ''
Children:
- TerminalSize: 3
NodeOffset: 8
Name: _foo
Flags: 0x0000000000000000
Address: 0x0000000000000F60
Other: 0x0000000000000000
ImportName: ''
NameList:
- n_strx: 2
n_type: 0x0F
n_sect: 1
n_desc: 0
n_value: 3936
- n_strx: 7
n_type: 0x01
n_sect: 0
n_desc: 0
n_value: 0
- n_strx: 12
n_type: 0x01
n_sect: 0
n_desc: 0
n_value: 0
- n_strx: 21
n_type: 0x01
n_sect: 0
n_desc: 0
n_value: 0
StringTable:
- ' '
- _foo
- _bar
- _putchar
- dyld_stub_binder
- ''
- ''
...

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,228 @@
--- !mach-o
FileHeader:
magic: 0xFEEDFACF
cputype: 0x01000007
cpusubtype: 0x00000003
filetype: 0x00000006
ncmds: 13
sizeofcmds: 872
flags: 0x00900085
reserved: 0x00000000
LoadCommands:
- cmd: LC_SEGMENT_64
cmdsize: 152
segname: __TEXT
vmaddr: 0
vmsize: 16384
fileoff: 0
filesize: 16384
maxprot: 5
initprot: 5
nsects: 1
flags: 0
Sections:
- sectname: __text
segname: __TEXT
addr: 0x0000000000004000
size: 0
offset: 0x00004000
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x80000400
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
content: ''
- cmd: LC_SEGMENT_64
cmdsize: 232
segname: __DATA
vmaddr: 16384
vmsize: 16384
fileoff: 16384
filesize: 16384
maxprot: 3
initprot: 3
nsects: 2
flags: 0
Sections:
- sectname: __thread_vars
segname: __DATA
addr: 0x0000000000004000
size: 24
offset: 0x00004000
align: 3
reloff: 0x00000000
nreloc: 0
flags: 0x00000013
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
content: '000000000000000000000000000000000000000000000000'
- sectname: __thread_bss
segname: __DATA
addr: 0x0000000000004018
size: 1
offset: 0x00000000
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x00000012
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- cmd: LC_SEGMENT_64
cmdsize: 72
segname: __LINKEDIT
vmaddr: 32768
vmsize: 16384
fileoff: 32768
filesize: 184
maxprot: 1
initprot: 1
nsects: 0
flags: 0
- cmd: LC_ID_DYLIB
cmdsize: 104
dylib:
name: 24
timestamp: 1
current_version: 0
compatibility_version: 0
Content: '/System/Library/Frameworks/ThreadLocal.framework/ThreadLocal'
ZeroPadBytes: 2
- cmd: LC_DYLD_INFO_ONLY
cmdsize: 48
rebase_off: 0
rebase_size: 0
bind_off: 32768
bind_size: 24
weak_bind_off: 0
weak_bind_size: 0
lazy_bind_off: 0
lazy_bind_size: 0
export_off: 32792
export_size: 24
- cmd: LC_SYMTAB
cmdsize: 24
symoff: 32824
nsyms: 4
stroff: 32888
strsize: 64
- cmd: LC_DYSYMTAB
cmdsize: 80
ilocalsym: 0
nlocalsym: 1
iextdefsym: 1
nextdefsym: 1
iundefsym: 2
nundefsym: 2
tocoff: 0
ntoc: 0
modtaboff: 0
nmodtab: 0
extrefsymoff: 0
nextrefsyms: 0
indirectsymoff: 0
nindirectsyms: 0
extreloff: 0
nextrel: 0
locreloff: 0
nlocrel: 0
- cmd: LC_UUID
cmdsize: 24
uuid: E4FA1DB7-CD39-3568-B80D-BFAF224E5ADC
- cmd: LC_BUILD_VERSION
cmdsize: 32
platform: 1
minos: 720896
sdk: 720896
ntools: 1
Tools:
- tool: 3
version: 39913216
- cmd: LC_SOURCE_VERSION
cmdsize: 16
version: 0
- cmd: LC_LOAD_DYLIB
cmdsize: 56
dylib:
name: 24
timestamp: 2
current_version: 84672512
compatibility_version: 65536
Content: '/usr/lib/libSystem.B.dylib'
ZeroPadBytes: 6
- cmd: LC_FUNCTION_STARTS
cmdsize: 16
dataoff: 32816
datasize: 8
- cmd: LC_DATA_IN_CODE
cmdsize: 16
dataoff: 32824
datasize: 0
LinkEditData:
BindOpcodes:
- Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
Imm: 1
Symbol: ''
- Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
Imm: 0
Symbol: __tlv_bootstrap
- Opcode: BIND_OPCODE_SET_TYPE_IMM
Imm: 1
Symbol: ''
- Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Imm: 1
ULEBExtraData: [ 0x0000000000000000 ]
Symbol: ''
- Opcode: BIND_OPCODE_DO_BIND
Imm: 0
Symbol: ''
- Opcode: BIND_OPCODE_DONE
Imm: 0
Symbol: ''
ExportTrie:
TerminalSize: 0
NodeOffset: 0
Name: ''
Flags: 0x0000000000000000
Address: 0x0000000000000000
Other: 0x0000000000000000
ImportName: ''
Children:
- TerminalSize: 4
NodeOffset: 13
Name: _MySymbol
Flags: 0x0000000000000001
Address: 0x0000000000004000
Other: 0x0000000000000000
ImportName: ''
NameList:
- n_strx: 45
n_type: 0x0E
n_sect: 3
n_desc: 0
n_value: 16408
- n_strx: 2
n_type: 0x0F
n_sect: 2
n_desc: 0
n_value: 16384
- n_strx: 12
n_type: 0x01
n_sect: 0
n_desc: 256
n_value: 0
- n_strx: 28
n_type: 0x01
n_sect: 0
n_desc: 256
n_value: 0
StringTable:
- ' '
- _MySymbol
- __tlv_bootstrap
- dyld_stub_binder
- '_MySymbol$tlv$init'
...

View File

@@ -0,0 +1,372 @@
--- !fat-mach-o
FatHeader:
magic: 0xCAFEBABE
nfat_arch: 2
FatArchs:
- cputype: 0x0000000C
cpusubtype: 0x00000009
offset: 0x0000000000004000
size: 16424
align: 14
- cputype: 0x0100000C
cpusubtype: 0x00000000
offset: 0x000000000000C000
size: 16464
align: 14
Slices:
- !mach-o
FileHeader:
magic: 0xFEEDFACE
cputype: 0x0000000C
cpusubtype: 0x00000009
filetype: 0x00000006
ncmds: 13
sizeofcmds: 608
flags: 0x00100085
LoadCommands:
- cmd: LC_SEGMENT
cmdsize: 124
segname: __TEXT
vmaddr: 0
vmsize: 16384
fileoff: 0
filesize: 16384
maxprot: 5
initprot: 5
nsects: 1
flags: 0
Sections:
- sectname: __text
segname: __TEXT
addr: 0x0000000000004000
size: 0
offset: 0x00004000
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x80000400
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
content: ''
- cmd: LC_SEGMENT
cmdsize: 124
segname: __DATA
vmaddr: 16384
vmsize: 16384
fileoff: 0
filesize: 0
maxprot: 3
initprot: 3
nsects: 1
flags: 0
Sections:
- sectname: __common
segname: __DATA
addr: 0x0000000000004000
size: 4
offset: 0x00000000
align: 2
reloff: 0x00000000
nreloc: 0
flags: 0x00000001
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- cmd: LC_SEGMENT
cmdsize: 56
segname: __LINKEDIT
vmaddr: 32768
vmsize: 16384
fileoff: 16384
filesize: 40
maxprot: 1
initprot: 1
nsects: 0
flags: 0
- cmd: LC_ID_DYLIB
cmdsize: 44
dylib:
name: 24
timestamp: 1
current_version: 0
compatibility_version: 0
Content: '@rpath/libfoo.dylib'
ZeroPadBytes: 1
- cmd: LC_DYLD_INFO_ONLY
cmdsize: 48
rebase_off: 0
rebase_size: 0
bind_off: 0
bind_size: 0
weak_bind_off: 0
weak_bind_size: 0
lazy_bind_off: 0
lazy_bind_size: 0
export_off: 16384
export_size: 16
- cmd: LC_SYMTAB
cmdsize: 24
symoff: 16404
nsyms: 1
stroff: 16416
strsize: 8
- cmd: LC_DYSYMTAB
cmdsize: 80
ilocalsym: 0
nlocalsym: 0
iextdefsym: 0
nextdefsym: 1
iundefsym: 1
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
- cmd: LC_UUID
cmdsize: 24
uuid: 55BB3EB2-88FF-39A2-BAFB-C8695DC33D4B
- cmd: LC_VERSION_MIN_IPHONEOS
cmdsize: 16
version: 680803
sdk: 917504
- cmd: LC_SOURCE_VERSION
cmdsize: 16
version: 0
- cmd: LC_ENCRYPTION_INFO
cmdsize: 20
cryptoff: 16384
cryptsize: 0
cryptid: 0
- cmd: LC_FUNCTION_STARTS
cmdsize: 16
dataoff: 16400
datasize: 4
- cmd: LC_DATA_IN_CODE
cmdsize: 16
dataoff: 16404
datasize: 0
LinkEditData:
ExportTrie:
TerminalSize: 0
NodeOffset: 0
Name: ''
Flags: 0x0000000000000000
Address: 0x0000000000000000
Other: 0x0000000000000000
ImportName: ''
Children:
- TerminalSize: 4
NodeOffset: 8
Name: _foo
Flags: 0x0000000000000000
Address: 0x0000000000004000
Other: 0x0000000000000000
ImportName: ''
NameList:
- n_strx: 2
n_type: 0x0F
n_sect: 2
n_desc: 0
n_value: 16384
StringTable:
- ' '
- _foo
- ''
- !mach-o
FileHeader:
magic: 0xFEEDFACF
cputype: 0x0100000C
cpusubtype: 0x00000000
filetype: 0x00000006
ncmds: 14
sizeofcmds: 760
flags: 0x00100085
reserved: 0x00000000
LoadCommands:
- cmd: LC_SEGMENT_64
cmdsize: 152
segname: __TEXT
vmaddr: 0
vmsize: 16384
fileoff: 0
filesize: 16384
maxprot: 5
initprot: 5
nsects: 1
flags: 0
Sections:
- sectname: __text
segname: __TEXT
addr: 0x0000000000004000
size: 0
offset: 0x00004000
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x80000400
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
content: ''
- cmd: LC_SEGMENT_64
cmdsize: 152
segname: __DATA
vmaddr: 16384
vmsize: 16384
fileoff: 0
filesize: 0
maxprot: 3
initprot: 3
nsects: 1
flags: 0
Sections:
- sectname: __common
segname: __DATA
addr: 0x0000000000004000
size: 4
offset: 0x00000000
align: 2
reloff: 0x00000000
nreloc: 0
flags: 0x00000001
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- cmd: LC_SEGMENT_64
cmdsize: 72
segname: __LINKEDIT
vmaddr: 32768
vmsize: 16384
fileoff: 16384
filesize: 80
maxprot: 1
initprot: 1
nsects: 0
flags: 0
- cmd: LC_ID_DYLIB
cmdsize: 48
dylib:
name: 24
timestamp: 1
current_version: 0
compatibility_version: 0
Content: '@rpath/libfoo.dylib'
ZeroPadBytes: 5
- cmd: LC_DYLD_INFO_ONLY
cmdsize: 48
rebase_off: 0
rebase_size: 0
bind_off: 0
bind_size: 0
weak_bind_off: 0
weak_bind_size: 0
lazy_bind_off: 0
lazy_bind_size: 0
export_off: 16384
export_size: 16
- cmd: LC_SYMTAB
cmdsize: 24
symoff: 16408
nsyms: 2
stroff: 16440
strsize: 24
- 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
- cmd: LC_UUID
cmdsize: 24
uuid: 57F7A4EB-2EDE-3150-80B6-8D587A135790
- cmd: LC_BUILD_VERSION
cmdsize: 32
platform: 2
minos: 917504
sdk: 917504
ntools: 1
Tools:
- tool: 3
version: 39322368
- cmd: LC_SOURCE_VERSION
cmdsize: 16
version: 0
- cmd: LC_ENCRYPTION_INFO_64
cmdsize: 24
cryptoff: 16384
cryptsize: 0
cryptid: 0
pad: 0
- cmd: LC_LOAD_DYLIB
cmdsize: 56
dylib:
name: 24
timestamp: 2
current_version: 84017152
compatibility_version: 65536
Content: '/usr/lib/libSystem.B.dylib'
ZeroPadBytes: 6
- cmd: LC_FUNCTION_STARTS
cmdsize: 16
dataoff: 16400
datasize: 8
- cmd: LC_DATA_IN_CODE
cmdsize: 16
dataoff: 16408
datasize: 0
LinkEditData:
ExportTrie:
TerminalSize: 0
NodeOffset: 0
Name: ''
Flags: 0x0000000000000000
Address: 0x0000000000000000
Other: 0x0000000000000000
ImportName: ''
Children:
- TerminalSize: 4
NodeOffset: 8
Name: _foo
Flags: 0x0000000000000000
Address: 0x0000000000004000
Other: 0x0000000000000000
ImportName: ''
NameList:
- n_strx: 2
n_type: 0x0F
n_sect: 2
n_desc: 0
n_value: 16384
- n_strx: 7
n_type: 0x01
n_sect: 0
n_desc: 256
n_value: 0
StringTable:
- ' '
- _foo
- dyld_stub_binder
...

View File

@@ -1,7 +0,0 @@
; RUN: mkdir -p %t
; RUN: yaml2obj %S/Inputs/macho.yaml -o %t/macho.dylib
; RUN: not llvm-readtapi --compare %S/Inputs/v4A.tbd %t/macho.dylib 2>&1 | FileCheck %s
; CHECK: error: {{.*}}macho.dylib' unsupported file type
; CHECK-NOT: error:
; CHECK-NOT: warning:

View File

@@ -0,0 +1,41 @@
; RUN: rm -rf %t
; RUN: split-file %s %t
; RUN: mkdir -p %t
; RUN: yaml2obj %S/Inputs/macho.yaml -o %t/macho.dylib
; RUN: not llvm-readtapi --compare %t/macho.tbd %t/macho.dylib 2>&1 | FileCheck %s
; CHECK: macho.tbd
; CHECK-NEXT: macho.dylib
; CHECK: Current Version
; CHECK-NEXT: < 1.2
; CHECK-NEXT: > 1
; CHECK-NEXT: Compatibility Version
; CHECK-NEXT: < 3.1
; CHECK-NEXT: > 1
;--- macho.tbd
{
"main_library": {
"flags": [
{
"attributes": [
"not_app_extension_safe"
]
}
],
"current_versions":[{"version": "1.2"}],
"compatibility_versions":[{ "version": "3.1"}],
"install_names": [
{
"name": "macho-no-exports.dylib"
}
],
"target_info": [
{
"min_deployment": "10.10",
"target": "x86_64-macos"
}
]
},
"tapi_tbd_version": 5
}

View File

@@ -0,0 +1,7 @@
; RUN: rm -rf %t
; RUN: not llvm-readtapi -stubify %t/objc.dylib %t/flat_namespace.dylib %t/thread_local.dylib %t/fat.dylib --o tmp.tbd 2>&1 | FileCheck %s --allow-empty --check-prefix OUT
; RUN: not llvm-readtapi -stubify --o tmp.tbd 2>&1 | FileCheck %s --allow-empty --check-prefix IN
; OUT: error: cannot write multiple inputs into single output file
; IN: error: stubify requires at least one input file

View File

@@ -0,0 +1,158 @@
; RUN: rm -rf %t
; RUN: split-file %s %t
; RUN: yaml2obj %S/Inputs/flat_namespace.yaml -o %t/flat_namespace.dylib
; RUN: yaml2obj %S/Inputs/thread_local.yaml -o %t/thread_local.dylib
; RUN: yaml2obj %S/Inputs/universal.yaml -o %t/fat.dylib
; RUN: yaml2obj %S/Inputs/objc.yaml -o %t/objc.dylib
; RUN: llvm-readtapi -stubify %t/objc.dylib -o %t/new_objc.tbd 2>&1 | FileCheck %s --allow-empty
; RUN: llvm-readtapi -stubify %t/objc.dylib %t/flat_namespace.dylib %t/thread_local.dylib %t/fat.dylib -delete-input 2>&1 | FileCheck %s --allow-empty
; RUN: llvm-readtapi -compare %t/expected_flat.tbd %t/flat_namespace.tbd 2>&1 | FileCheck %s --allow-empty
; RUN: llvm-readtapi -compare %t/expected_tl.tbd %t/thread_local.tbd 2>&1 | FileCheck %s --allow-empty
; RUN: llvm-readtapi -compare %t/objc.tbd %t/expected_objc.tbd 2>&1 | FileCheck %s --allow-empty
; RUN: llvm-readtapi -compare %t/new_objc.tbd %t/expected_objc.tbd 2>&1 | FileCheck %s --allow-empty
; CHECK-NOT: error:
; CHECK-NOT: warning:
;--- expected_flat.tbd
{
"main_library": {
"compatibility_versions": [
{
"version": "0"
}
],
"current_versions": [
{
"version": "0"
}
],
"exported_symbols": [
{
"text": {
"global": [ "_foo" ]
}
}
],
"flags": [
{
"attributes": [
"flat_namespace",
"not_app_extension_safe"
]
}
],
"install_names": [
{
"name": "foo.dylib"
}
],
"target_info": [
{
"min_deployment": "10.14",
"target": "x86_64-macos"
}
],
"undefined_symbols": [
{
"data": {
"global": [ "dyld_stub_binder", "_bar", "_putchar" ]
}
}
]
},
"tapi_tbd_version": 5
}
;--- expected_tl.tbd
{
"main_library": {
"compatibility_versions": [
{
"version": "0"
}
],
"current_versions": [
{
"version": "0"
}
],
"exported_symbols": [
{
"data": {
"thread_local": [
"_MySymbol"
]
}
}
],
"flags": [
{
"attributes": [
"not_app_extension_safe"
]
}
],
"install_names": [
{
"name": "/System/Library/Frameworks/ThreadLocal.framework/ThreadLocal"
}
],
"target_info": [
{
"min_deployment": "11",
"target": "x86_64-macos"
}
]
},
"tapi_tbd_version": 5
}
;--- expected_objc.tbd
{
"main_library": {
"compatibility_versions": [
{
"version": "0"
}
],
"current_versions": [
{
"version": "0"
}
],
"exported_symbols": [
{
"data": {
"objc_class": [
"Suggestion"
],
"objc_ivar": [
"Suggestion._topChoice",
"Suggestion._other"
]
}
}
],
"flags": [
{
"attributes": [
"not_app_extension_safe"
]
}
],
"install_names": [
{
"name": "tmp.dylib"
}
],
"target_info": [
{
"min_deployment": "13",
"target": "arm64-macos"
}
]
},
"tapi_tbd_version": 5
}

View File

@@ -1,77 +1,34 @@
; RUN: rm -rf %t
; RUN: split-file %s %t
; RUN: llvm-readtapi %t/arm64.tbd 2>&1 | FileCheck %s
; RUN: mkdir -p %t
; RUN: yaml2obj %S/Inputs/macho.yaml -o %t/macho.dylib
; RUN: llvm-readtapi %t/macho.dylib -o %t/out.tbd 2>&1 | FileCheck %s --allow-empty
; RUN: llvm-readtapi -compare %t/out.tbd %t/expected.tbd 2>&1 | FileCheck %s --allow-empty
; CHECK-NOT: error
; CHECK-NOT: warning
; CHECK: {
; CHECK-NEXT: "main_library": {
; CHECK-NEXT: "allowable_clients": [
; CHECK-NEXT: {
; CHECK-NEXT: "clients": [
; CHECK-NEXT: "ClientAll"
; CHECK-NEXT: ]
; CHECK-NEXT: }
; CHECK-NEXT: ],
; CHECK-NEXT: "exported_symbols": [
; CHECK-NEXT: {
; CHECK-NEXT: "data": {
; CHECK-NEXT: "global": [
; CHECK-NEXT: "_sym1"
; CHECK-NEXT: ],
; CHECK-NEXT: "objc_class": [
; CHECK-NEXT: "_A"
; CHECK-NEXT: ],
; CHECK-NEXT: "objc_ivar": [
; CHECK-NEXT: "_A._ivar1"
; CHECK-NEXT: ],
; CHECK-NEXT: "thread_local": [
; CHECK-NEXT: "_tlv1"
; CHECK-NEXT: ],
; CHECK-NEXT: "weak": [
; CHECK-NEXT: "_weak1"
; CHECK-NEXT: ]
; CHECK-NEXT: }
; CHECK-NEXT: }
; CHECK-NEXT: ],
; CHECK-NEXT: "install_names": [
; CHECK-NEXT: {
; CHECK-NEXT: "name": "/usr/lib/libfat.dylib"
; CHECK-NEXT: }
; CHECK-NEXT: ],
; CHECK-NEXT: "reexported_libraries": [
; CHECK-NEXT: {
; CHECK-NEXT: "names": [
; CHECK-NEXT: "/usr/lib/liball.dylib"
; CHECK-NEXT: ]
; CHECK-NEXT: }
; CHECK-NEXT: ],
; CHECK-NEXT: "target_info": [
; CHECK-NEXT: {
; CHECK-NEXT: "target": "arm64-macos"
; CHECK-NEXT: }
; CHECK-NEXT: ]
; CHECK-NEXT: },
; CHECK-NEXT: "tapi_tbd_version": 5
; CHECK-NEXT: }
; CHECK-NOT: error
; CHECK-NOT: warning
;--- arm64.tbd
--- !tapi-tbd
tbd-version: 4
targets: [ arm64-macos ]
install-name: '/usr/lib/libfat.dylib'
allowable-clients:
- targets: [ arm64-macos ]
clients: [ ClientAll ]
reexported-libraries:
- targets: [ arm64-macos ]
libraries: [ '/usr/lib/liball.dylib' ]
exports:
- targets: [ arm64-macos ]
symbols: [ _sym1 ]
objc-classes: [ _A ]
objc-ivars: [ _A._ivar1 ]
weak-symbols: [ _weak1 ]
thread-local-symbols: [ _tlv1 ]
...
;--- expected.tbd
{
"main_library": {
"flags": [
{
"attributes": [
"not_app_extension_safe"
]
}
],
"install_names": [
{
"name": "macho-no-exports.dylib"
}
],
"target_info": [
{
"min_deployment": "10.10",
"target": "x86_64-macos"
}
]
},
"tapi_tbd_version": 5
}

View File

@@ -1,4 +1,5 @@
set(LLVM_LINK_COMPONENTS
BinaryFormat
Object
Support
Option

View File

@@ -15,6 +15,7 @@ def compare : FF<"compare", "compare tapi files for library differences">, Group
def merge : FF<"merge", "merge the input files that represent the same library">, Group<action_group>;
def extract: FF<"extract", "extract <architecture> from input file">, Group<action_group>;
def remove: FF<"remove", "remove <architecture> from input file">, Group<action_group>;
def stubify: FF<"stubify", "create a tapi file from a dynamic library or framework">, Group<action_group>;
//
// General Driver options
@@ -26,3 +27,8 @@ defm output: JS<"o", "write output to <file>","<file>">;
def compact: FF<"compact", "write compact tapi output file">;
defm filetype: JS<"filetype", "specify the output file type (tbd-v3, tbd-v4 or tbd-v5)","<value>">;
defm arch: JS<"arch", "specify the <architecture>", "<architecture>">;
//
// Stub options
//
def delete_input : FF<"delete-input", "delete and replace input file on success">;

View File

@@ -10,23 +10,32 @@
//
//===----------------------------------------------------------------------===//
#include "DiffEngine.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TextAPI/DylibReader.h"
#include "llvm/TextAPI/TextAPIError.h"
#include "llvm/TextAPI/TextAPIReader.h"
#include "llvm/TextAPI/TextAPIWriter.h"
#include "llvm/TextAPI/Utils.h"
#include <cstdlib>
using namespace llvm;
using namespace MachO;
using namespace object;
#if !defined(PATH_MAX)
#define PATH_MAX 1024
#endif
namespace {
using namespace llvm::opt;
enum ID {
@@ -56,10 +65,15 @@ public:
}
};
struct StubOptions {
bool DeleteInput = false;
};
struct Context {
std::vector<std::string> Inputs;
std::unique_ptr<llvm::raw_fd_stream> OutStream;
FileType WriteFT = FileType::TBD_V5;
StubOptions StubOpt;
bool Compact = false;
Architecture Arch = AK_unknown;
};
@@ -86,13 +100,35 @@ getInterfaceFile(const StringRef Filename, bool ResetBanner = true) {
MemoryBuffer::getFile(Filename);
if (BufferOrErr.getError())
ExitOnErr(errorCodeToError(BufferOrErr.getError()));
Expected<std::unique_ptr<InterfaceFile>> IF =
TextAPIReader::get((*BufferOrErr)->getMemBufferRef());
if (!IF)
ExitOnErr(IF.takeError());
auto Buffer = std::move(*BufferOrErr);
std::unique_ptr<InterfaceFile> IF;
switch (identify_magic(Buffer->getBuffer())) {
case file_magic::macho_dynamically_linked_shared_lib:
LLVM_FALLTHROUGH;
case file_magic::macho_dynamically_linked_shared_lib_stub:
LLVM_FALLTHROUGH;
case file_magic::macho_universal_binary: {
auto IFOrErr = DylibReader::get(Buffer->getMemBufferRef());
if (!IFOrErr)
ExitOnErr(IFOrErr.takeError());
IF = std::move(*IFOrErr);
break;
}
case file_magic::tapi_file: {
auto IFOrErr = TextAPIReader::get(Buffer->getMemBufferRef());
if (!IFOrErr)
ExitOnErr(IFOrErr.takeError());
IF = std::move(*IFOrErr);
break;
}
default:
reportError(Filename + ": unsupported file type");
}
if (ResetBanner)
ExitOnErr.setBanner(TOOLNAME + ": error: ");
return std::move(*IF);
return IF;
}
static bool handleCompareAction(const Context &Ctx) {
@@ -142,6 +178,30 @@ static bool handleMergeAction(const Context &Ctx) {
return handleWriteAction(Ctx, std::move(Out));
}
static bool handleStubifyAction(Context &Ctx) {
if (Ctx.Inputs.empty())
reportError("stubify requires at least one input file");
if ((Ctx.Inputs.size() > 1) && (Ctx.OutStream != nullptr))
reportError("cannot write multiple inputs into single output file");
for (StringRef FileName : Ctx.Inputs) {
auto IF = getInterfaceFile(FileName);
if (Ctx.StubOpt.DeleteInput) {
std::error_code EC;
SmallString<PATH_MAX> OutputLoc = FileName;
MachO::replace_extension(OutputLoc, ".tbd");
Ctx.OutStream = std::make_unique<llvm::raw_fd_stream>(OutputLoc, EC);
if (EC)
reportError("opening file '" + OutputLoc + ": " + EC.message());
if (auto Err = sys::fs::remove(FileName))
reportError("deleting file '" + FileName + ": " + EC.message());
}
handleWriteAction(Ctx, std::move(IF));
}
return EXIT_SUCCESS;
}
using IFOperation =
std::function<llvm::Expected<std::unique_ptr<InterfaceFile>>(
const llvm::MachO::InterfaceFile &, Architecture)>;
@@ -160,6 +220,10 @@ static bool handleSingleFileAction(const Context &Ctx, const StringRef Action,
return handleWriteAction(Ctx, std::move(*OutIF));
}
static void setStubOptions(opt::InputArgList &Args, StubOptions &Opt) {
Opt.DeleteInput = Args.hasArg(OPT_delete_input);
}
int main(int Argc, char **Argv) {
InitLLVM X(Argc, Argv);
BumpPtrAllocator A;
@@ -183,6 +247,7 @@ int main(int Argc, char **Argv) {
return EXIT_SUCCESS;
}
// TODO: Add support for picking up libraries from directory input.
for (opt::Arg *A : Args.filtered(OPT_INPUT))
Ctx.Inputs.push_back(A->getValue());
@@ -237,6 +302,9 @@ int main(int Argc, char **Argv) {
return handleSingleFileAction(Ctx, "extract", &InterfaceFile::extract);
case OPT_remove:
return handleSingleFileAction(Ctx, "remove", &InterfaceFile::remove);
case OPT_stubify:
setStubOptions(Args, Ctx.StubOpt);
return handleStubifyAction(Ctx);
}
return EXIT_SUCCESS;