Skip to content

Commit b5913e6

Browse files
author
Alexander Shaposhnikov
committed
Introduce llvm-install-name-tool
This diff adds a new "driver" for llvm-objcopy which is supposed to emulate the behavior of install-name-tool. Differential revision: https://reviews.llvm.org/D69146 Test plan: make check-all
1 parent 2293b3f commit b5913e6

File tree

13 files changed

+382
-8
lines changed

13 files changed

+382
-8
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
--- !mach-o
2+
FileHeader:
3+
magic: 0xFEEDFACE
4+
cputype: 0x00000007
5+
cpusubtype: 0x00000003
6+
filetype: 0x00000001
7+
ncmds: 4
8+
sizeofcmds: 312
9+
flags: 0x00002000
10+
LoadCommands:
11+
- cmd: LC_SEGMENT
12+
cmdsize: 192
13+
segname: ''
14+
vmaddr: 0
15+
vmsize: 72
16+
fileoff: 340
17+
filesize: 72
18+
maxprot: 7
19+
initprot: 7
20+
nsects: 2
21+
flags: 0
22+
Sections:
23+
- sectname: __text
24+
segname: __TEXT
25+
addr: 0x0000000000000000
26+
size: 18
27+
offset: 0x00000154
28+
align: 4
29+
reloff: 0x00000000
30+
nreloc: 0
31+
flags: 0x80000400
32+
reserved1: 0x00000000
33+
reserved2: 0x00000000
34+
reserved3: 0x00000000
35+
- sectname: __eh_frame
36+
segname: __TEXT
37+
addr: 0x0000000000000014
38+
size: 52
39+
offset: 0x00000168
40+
align: 2
41+
reloff: 0x00000000
42+
nreloc: 0
43+
flags: 0x6800000B
44+
reserved1: 0x00000000
45+
reserved2: 0x00000000
46+
reserved3: 0x00000000
47+
- cmd: LC_VERSION_MIN_MACOSX
48+
cmdsize: 16
49+
version: 656384
50+
sdk: 0
51+
- cmd: LC_SYMTAB
52+
cmdsize: 24
53+
symoff: 412
54+
nsyms: 1
55+
stroff: 424
56+
strsize: 8
57+
- cmd: LC_DYSYMTAB
58+
cmdsize: 80
59+
ilocalsym: 0
60+
nlocalsym: 0
61+
iextdefsym: 0
62+
nextdefsym: 1
63+
iundefsym: 1
64+
nundefsym: 0
65+
tocoff: 0
66+
ntoc: 0
67+
modtaboff: 0
68+
nmodtab: 0
69+
extrefsymoff: 0
70+
nextrefsyms: 0
71+
indirectsymoff: 0
72+
nindirectsyms: 0
73+
extreloff: 0
74+
nextrel: 0
75+
locreloff: 0
76+
nlocrel: 0
77+
LinkEditData:
78+
NameList:
79+
- n_strx: 1
80+
n_type: 0x0F
81+
n_sect: 1
82+
n_desc: 0
83+
n_value: 0
84+
StringTable:
85+
- ''
86+
- _main
87+
- ''
88+
...
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
--- !mach-o
2+
FileHeader:
3+
magic: 0xFEEDFACF
4+
cputype: 0x01000007
5+
cpusubtype: 0x00000003
6+
filetype: 0x00000001
7+
ncmds: 4
8+
sizeofcmds: 352
9+
flags: 0x00002000
10+
reserved: 0x00000000
11+
LoadCommands:
12+
- cmd: LC_SEGMENT_64
13+
cmdsize: 232
14+
segname: ''
15+
vmaddr: 0
16+
vmsize: 80
17+
fileoff: 384
18+
filesize: 80
19+
maxprot: 7
20+
initprot: 7
21+
nsects: 2
22+
flags: 0
23+
Sections:
24+
- sectname: __text
25+
segname: __TEXT
26+
addr: 0x0000000000000000
27+
size: 15
28+
offset: 0x00000180
29+
align: 4
30+
reloff: 0x00000000
31+
nreloc: 0
32+
flags: 0x80000400
33+
reserved1: 0x00000000
34+
reserved2: 0x00000000
35+
reserved3: 0x00000000
36+
- sectname: __eh_frame
37+
segname: __TEXT
38+
addr: 0x0000000000000010
39+
size: 64
40+
offset: 0x00000190
41+
align: 3
42+
reloff: 0x00000000
43+
nreloc: 0
44+
flags: 0x6800000B
45+
reserved1: 0x00000000
46+
reserved2: 0x00000000
47+
reserved3: 0x00000000
48+
- cmd: LC_VERSION_MIN_MACOSX
49+
cmdsize: 16
50+
version: 656384
51+
sdk: 0
52+
- cmd: LC_SYMTAB
53+
cmdsize: 24
54+
symoff: 464
55+
nsyms: 1
56+
stroff: 480
57+
strsize: 8
58+
- cmd: LC_DYSYMTAB
59+
cmdsize: 80
60+
ilocalsym: 0
61+
nlocalsym: 0
62+
iextdefsym: 0
63+
nextdefsym: 1
64+
iundefsym: 1
65+
nundefsym: 0
66+
tocoff: 0
67+
ntoc: 0
68+
modtaboff: 0
69+
nmodtab: 0
70+
extrefsymoff: 0
71+
nextrefsyms: 0
72+
indirectsymoff: 0
73+
nindirectsyms: 0
74+
extreloff: 0
75+
nextrel: 0
76+
locreloff: 0
77+
nlocrel: 0
78+
LinkEditData:
79+
NameList:
80+
- n_strx: 1
81+
n_type: 0x0F
82+
n_sect: 1
83+
n_desc: 0
84+
n_value: 0
85+
StringTable:
86+
- ''
87+
- _main
88+
- ''
89+
...
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
## This test checks adding a new LC_RPATH load command to a MachO binary.
2+
3+
# RUN: yaml2obj %p/Inputs/i386.yaml > %t.i386
4+
# RUN: llvm-install-name-tool -add_rpath @executable_path/. %t.i386
5+
# RUN: llvm-objdump -p %t.i386 | FileCheck --check-prefix=NEW-RPATH %s
6+
7+
# RUN: yaml2obj %p/Inputs/x86_64.yaml > %t.x86_64
8+
# RUN: llvm-install-name-tool -add_rpath @executable_path/. %t.x86_64
9+
# RUN: llvm-objdump -p %t.x86_64 | FileCheck --check-prefix=NEW-RPATH %s
10+
11+
# NEW-RPATH: cmd LC_RPATH
12+
# NEW-RPATH-NEXT: cmdsize
13+
# NEW-RPATH-NEXT: @executable_path/.
14+
15+
# RUN: not llvm-install-name-tool -add_rpath @executable_path/. %t.i386 2>&1 \
16+
# RUN: | FileCheck --check-prefix=DUPLICATE-RPATH %s
17+
18+
# DUPLICATE-RPATH: duplicate load command
19+
20+
# RUN: not llvm-install-name-tool -add_rpath @executable_path/. 2>&1 \
21+
# RUN: | FileCheck --check-prefix=NO-INPUT %s
22+
23+
# NO-INPUT: no input file specified
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# RUN: llvm-install-name-tool -h | FileCheck --check-prefix=INSTALL-NAME-TOOL-USAGE %s
2+
# RUN: llvm-install-name-tool --help | FileCheck --check-prefix=INSTALL-NAME-TOOL-USAGE %s
3+
# RUN: not llvm-install-name-tool 2>&1 | FileCheck --check-prefix=INSTALL-NAME-TOOL-USAGE %s
4+
# RUN: not llvm-install-name-tool -abcabc 2>&1 | FileCheck --check-prefix=UNKNOWN-ARG %s
5+
# RUN: not llvm-install-name-tool --abcabc 2>&1 | FileCheck --check-prefix=UNKNOWN-ARG %s
6+
7+
# INSTALL-NAME-TOOL-USAGE: USAGE: llvm-install-name-tool
8+
# INSTALL-NAME-TOOL-USAGE: @FILE
9+
10+
# UNKNOWN-ARG: unknown argument '{{-+}}abcabc'
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# RUN: llvm-install-name-tool --version | FileCheck %s
2+
# CHECK: {{ version }}

llvm/tools/llvm-objcopy/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ set(LLVM_TARGET_DEFINITIONS ObjcopyOpts.td)
99
tablegen(LLVM ObjcopyOpts.inc -gen-opt-parser-defs)
1010
add_public_tablegen_target(ObjcopyOptsTableGen)
1111

12+
set(LLVM_TARGET_DEFINITIONS InstallNameToolOpts.td)
13+
tablegen(LLVM InstallNameToolOpts.inc -gen-opt-parser-defs)
14+
add_public_tablegen_target(InstallNameToolOptsTableGen)
15+
1216
set(LLVM_TARGET_DEFINITIONS StripOpts.td)
1317
tablegen(LLVM StripOpts.inc -gen-opt-parser-defs)
1418
add_public_tablegen_target(StripOptsTableGen)
@@ -31,9 +35,11 @@ add_llvm_tool(llvm-objcopy
3135
MachO/Object.cpp
3236
DEPENDS
3337
ObjcopyOptsTableGen
38+
InstallNameToolOptsTableGen
3439
StripOptsTableGen
3540
)
3641

42+
add_llvm_tool_symlink(llvm-install-name-tool llvm-objcopy)
3743
add_llvm_tool_symlink(llvm-strip llvm-objcopy)
3844

3945
if(LLVM_INSTALL_BINUTILS_SYMLINKS)

llvm/tools/llvm-objcopy/CopyConfig.cpp

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,44 @@ class ObjcopyOptTable : public opt::OptTable {
6363
ObjcopyOptTable() : OptTable(ObjcopyInfoTable) {}
6464
};
6565

66+
enum InstallNameToolID {
67+
INSTALL_NAME_TOOL_INVALID = 0, // This is not an option ID.
68+
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
69+
HELPTEXT, METAVAR, VALUES) \
70+
INSTALL_NAME_TOOL_##ID,
71+
#include "InstallNameToolOpts.inc"
72+
#undef OPTION
73+
};
74+
75+
#define PREFIX(NAME, VALUE) \
76+
const char *const INSTALL_NAME_TOOL_##NAME[] = VALUE;
77+
#include "InstallNameToolOpts.inc"
78+
#undef PREFIX
79+
80+
static const opt::OptTable::Info InstallNameToolInfoTable[] = {
81+
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
82+
HELPTEXT, METAVAR, VALUES) \
83+
{INSTALL_NAME_TOOL_##PREFIX, \
84+
NAME, \
85+
HELPTEXT, \
86+
METAVAR, \
87+
INSTALL_NAME_TOOL_##ID, \
88+
opt::Option::KIND##Class, \
89+
PARAM, \
90+
FLAGS, \
91+
INSTALL_NAME_TOOL_##GROUP, \
92+
INSTALL_NAME_TOOL_##ALIAS, \
93+
ALIASARGS, \
94+
VALUES},
95+
#include "InstallNameToolOpts.inc"
96+
#undef OPTION
97+
};
98+
99+
class InstallNameToolOptTable : public opt::OptTable {
100+
public:
101+
InstallNameToolOptTable() : OptTable(InstallNameToolInfoTable) {}
102+
};
103+
66104
enum StripID {
67105
STRIP_INVALID = 0, // This is not an option ID.
68106
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
@@ -752,6 +790,57 @@ parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
752790
return std::move(DC);
753791
}
754792

793+
// ParseInstallNameToolOptions returns the config and sets the input arguments.
794+
// If a help flag is set then ParseInstallNameToolOptions will print the help
795+
// messege and exit.
796+
Expected<DriverConfig>
797+
parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
798+
DriverConfig DC;
799+
CopyConfig Config;
800+
InstallNameToolOptTable T;
801+
unsigned MissingArgumentIndex, MissingArgumentCount;
802+
llvm::opt::InputArgList InputArgs =
803+
T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
804+
805+
if (InputArgs.size() == 0) {
806+
printHelp(T, errs(), "llvm-install-name-tool");
807+
exit(1);
808+
}
809+
810+
if (InputArgs.hasArg(INSTALL_NAME_TOOL_help)) {
811+
printHelp(T, outs(), "llvm-install-name-tool");
812+
exit(0);
813+
}
814+
815+
if (InputArgs.hasArg(INSTALL_NAME_TOOL_version)) {
816+
outs() << "llvm-install-name-tool, compatible with cctools "
817+
"install_name_tool\n";
818+
cl::PrintVersionMessage();
819+
exit(0);
820+
}
821+
822+
for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath))
823+
Config.RPathToAdd.push_back(Arg->getValue());
824+
825+
SmallVector<StringRef, 2> Positional;
826+
for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN))
827+
return createStringError(errc::invalid_argument, "unknown argument '%s'",
828+
Arg->getAsString(InputArgs).c_str());
829+
for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT))
830+
Positional.push_back(Arg->getValue());
831+
if (Positional.empty())
832+
return createStringError(errc::invalid_argument, "no input file specified");
833+
if (Positional.size() > 1)
834+
return createStringError(
835+
errc::invalid_argument,
836+
"llvm-install-name-tool expects a single input file");
837+
Config.InputFilename = Positional[0];
838+
Config.OutputFilename = Positional[0];
839+
840+
DC.CopyConfigs.push_back(std::move(Config));
841+
return std::move(DC);
842+
}
843+
755844
// ParseStripOptions returns the config and sets the input arguments. If a
756845
// help flag is set then ParseStripOptions will print the help messege and
757846
// exit.

llvm/tools/llvm-objcopy/CopyConfig.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ struct CopyConfig {
175175
std::vector<StringRef> AddSection;
176176
std::vector<StringRef> DumpSection;
177177
std::vector<StringRef> SymbolsToAdd;
178+
std::vector<StringRef> RPathToAdd;
178179

179180
// Section matchers
180181
NameMatcher KeepSection;
@@ -251,14 +252,19 @@ Expected<DriverConfig>
251252
parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
252253
llvm::function_ref<Error(Error)> ErrorCallback);
253254

255+
// ParseInstallNameToolOptions returns the config and sets the input arguments.
256+
// If a help flag is set then ParseInstallNameToolOptions will print the help
257+
// messege and exit.
258+
Expected<DriverConfig>
259+
parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr);
260+
254261
// ParseStripOptions returns the config and sets the input arguments. If a
255262
// help flag is set then ParseStripOptions will print the help messege and
256263
// exit. ErrorCallback is used to handle recoverable errors. An Error returned
257264
// by the callback aborts the parsing and is then returned by this function.
258265
Expected<DriverConfig>
259266
parseStripOptions(ArrayRef<const char *> ArgsArr,
260267
llvm::function_ref<Error(Error)> ErrorCallback);
261-
262268
} // namespace objcopy
263269
} // namespace llvm
264270

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===-- InstallNameToolOpts.td - llvm-install-name-tool options --------*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file describes the command line options of llvm-install-name.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
include "llvm/Option/OptParser.td"
14+
15+
def help : Flag<["--"], "help">;
16+
def h : Flag<["-"], "h">, Alias<help>;
17+
18+
def add_rpath : Option<["-", "--"], "add_rpath", KIND_SEPARATE>,
19+
HelpText<"Add new rpath">;
20+
21+
def version : Flag<["--"], "version">,
22+
HelpText<"Print the version and exit.">;

0 commit comments

Comments
 (0)