Skip to content

Commit 22e6648

Browse files
committed
[lld-macho] Implement -headerpad
Tools like `install_name_tool` and `codesign` may modify the Mach-O header and increase its size. The linker has to provide padding to make this possible. This diff does that, plus sets its default value to 32 bytes (which is what ld64 does). Unlike ld64, however, we lay out our sections *exactly* `-headerpad` bytes from the header, whereas ld64 just treats the padding requirement as a lower bound. ld64 actually starts laying out the non-header sections in the __TEXT segment from the end of the (page-aligned) segment rather than the front, so its binaries typically have more than `-headerpad` bytes of actual padding. We should consider implementing the same alignment behavior. Reviewed By: #lld-macho, compnerd Differential Revision: https://reviews.llvm.org/D84714
1 parent 3587de2 commit 22e6648

File tree

9 files changed

+56
-8
lines changed

9 files changed

+56
-8
lines changed

lld/Common/Args.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,31 @@ CodeGenOpt::Level lld::args::getCGOptLevel(int optLevelLTO) {
2626
return CodeGenOpt::Default;
2727
}
2828

29-
int64_t lld::args::getInteger(opt::InputArgList &args, unsigned key,
30-
int64_t Default) {
29+
static int64_t getInteger(opt::InputArgList &args, unsigned key,
30+
int64_t Default, unsigned base) {
3131
auto *a = args.getLastArg(key);
3232
if (!a)
3333
return Default;
3434

3535
int64_t v;
36-
if (to_integer(a->getValue(), v, 10))
36+
if (to_integer(a->getValue(), v, base))
3737
return v;
3838

3939
StringRef spelling = args.getArgString(a->getIndex());
4040
error(spelling + ": number expected, but got '" + a->getValue() + "'");
4141
return 0;
4242
}
4343

44+
int64_t lld::args::getInteger(opt::InputArgList &args, unsigned key,
45+
int64_t Default) {
46+
return ::getInteger(args, key, Default, 10);
47+
}
48+
49+
int64_t lld::args::getHex(opt::InputArgList &args, unsigned key,
50+
int64_t Default) {
51+
return ::getInteger(args, key, Default, 16);
52+
}
53+
4454
std::vector<StringRef> lld::args::getStrings(opt::InputArgList &args, int id) {
4555
std::vector<StringRef> v;
4656
for (auto *arg : args.filtered(id))

lld/MachO/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ struct SymbolPriorityEntry;
2525
struct Configuration {
2626
Symbol *entry;
2727
bool hasReexports = false;
28+
uint32_t headerPad;
2829
llvm::StringRef installName;
2930
llvm::StringRef outputFile;
3031
llvm::MachO::Architecture arch;

lld/MachO/Driver.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
396396
config->outputFile = args.getLastArgValue(OPT_o, "a.out");
397397
config->installName =
398398
args.getLastArgValue(OPT_install_name, config->outputFile);
399+
config->headerPad = args::getHex(args, OPT_headerpad, 32);
399400
getLibrarySearchPaths(config->librarySearchPaths, args);
400401
getFrameworkSearchPaths(config->frameworkSearchPaths, args);
401402
config->outputType = args.hasArg(OPT_dylib) ? MH_DYLIB : MH_EXECUTE;
@@ -450,6 +451,7 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
450451
case OPT_e:
451452
case OPT_F:
452453
case OPT_L:
454+
case OPT_headerpad:
453455
case OPT_install_name:
454456
case OPT_Z:
455457
case OPT_arch:

lld/MachO/Options.td

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,6 @@ def umbrella : Separate<["-"], "umbrella">,
693693
def headerpad : Separate<["-"], "headerpad">,
694694
MetaVarName<"<size>">,
695695
HelpText<"Allocate hex <size> extra space for future expansion of the load commands via install_name_tool">,
696-
Flags<[HelpHidden]>,
697696
Group<grp_rare>;
698697
def headerpad_max_install_names : Flag<["-"], "headerpad_max_install_names">,
699698
HelpText<"Allocate extra space so all load-command paths can expand to MAXPATHLEN via install_name_tool">,

lld/MachO/SyntheticSections.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void MachHeaderSection::addLoadCommand(LoadCommand *lc) {
4747
}
4848

4949
uint64_t MachHeaderSection::getSize() const {
50-
return sizeof(MachO::mach_header_64) + sizeOfCmds;
50+
return sizeof(MachO::mach_header_64) + sizeOfCmds + config->headerPad;
5151
}
5252

5353
void MachHeaderSection::writeTo(uint8_t *buf) const {

lld/include/lld/Common/Args.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ llvm::CodeGenOpt::Level getCGOptLevel(int optLevelLTO);
2828
int64_t getInteger(llvm::opt::InputArgList &args, unsigned key,
2929
int64_t Default);
3030

31+
int64_t getHex(llvm::opt::InputArgList &args, unsigned key, int64_t Default);
32+
3133
std::vector<StringRef> getStrings(llvm::opt::InputArgList &args, int id);
3234

3335
uint64_t getZOptionValue(llvm::opt::InputArgList &args, int id, StringRef key,

lld/test/MachO/headerpad.s

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# REQUIRES: x86
2+
3+
## NOTE: Here we check that the first non-header section -- __text -- appears
4+
## *exactly* `-headerpad` bytes from the end of the header. ld64 actually
5+
## starts laying out the non-header sections in the __TEXT segment from the end
6+
## of the (page-aligned) segment rather than the front, so its binaries
7+
## typically have more than `-headerpad` bytes of actual padding. `-headerpad`
8+
## just enforces a lower bound. We should consider implementing the same
9+
## alignment behavior.
10+
11+
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
12+
# RUN: lld -flavor darwinnew -o %t %t.o -headerpad 0
13+
# RUN: llvm-objdump --macho --all-headers %t | FileCheck %s --check-prefix=PAD0
14+
# PAD0: magic cputype cpusubtype caps filetype ncmds sizeofcmds
15+
# PAD0-NEXT: MH_MAGIC_64 X86_64 ALL LIB64 EXECUTE 8 [[#%u, CMDSIZE:]] {{.*}}
16+
# PAD0: sectname __text
17+
# PAD0-NEXT: segname __TEXT
18+
# PAD0-NEXT: addr
19+
# PAD0-NEXT: size
20+
# PAD0-NEXT: offset [[#%u, CMDSIZE + 32]]
21+
22+
# RUN: lld -flavor darwinnew -o %t %t.o -headerpad 11
23+
# RUN: llvm-objdump --macho --all-headers %t | FileCheck %s --check-prefix=PAD11
24+
# PAD11: magic cputype cpusubtype caps filetype ncmds sizeofcmds
25+
# PAD11-NEXT: MH_MAGIC_64 X86_64 ALL LIB64 EXECUTE 8 [[#%u, CMDSIZE:]] {{.*}}
26+
# PAD11: sectname __text
27+
# PAD11-NEXT: segname __TEXT
28+
# PAD11-NEXT: addr
29+
# PAD11-NEXT: size
30+
# PAD11-NEXT: offset [[#%u, CMDSIZE + 32 + 0x11]]
31+
32+
.globl _main
33+
_main:
34+
ret

lld/test/MachO/local-got.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212
## address offset and the contents at that address very similarly, so am using
1313
## --match-full-lines to make sure we match on the right thing.
1414
# CHECK: Contents of section __cstring:
15-
# CHECK-NEXT: 1000003cc {{.*}}
15+
# CHECK-NEXT: 1000003ec {{.*}}
1616

1717
## 1st 8 bytes refer to the start of __cstring + 0xe, 2nd 8 bytes refer to the
1818
## start of __cstring
1919
# CHECK: Contents of section __got:
20-
# CHECK-NEXT: [[#%X,ADDR:]] da030000 01000000 cc030000 01000000 {{.*}}
20+
# CHECK-NEXT: [[#%X,ADDR:]] fa030000 01000000 ec030000 01000000 {{.*}}
2121
# CHECK-NEXT: [[#ADDR + 16]] 00000000 00000000 {{.*}}
2222

2323
## Check that a non-locally-defined symbol is still bound at the correct offset:

lld/test/MachO/relocations.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
# RUN: llvm-objdump --section=__const --full-contents -d %t | FileCheck %s --check-prefix=NONPCREL
2323
# NONPCREL: Contents of section __const:
24-
# NONPCREL-NEXT: 100001000 b0030000 01000000 b0030000 01000000
24+
# NONPCREL-NEXT: 100001000 d0030000 01000000 d0030000 01000000
2525

2626
.section __TEXT,__text
2727
.globl _main, _f

0 commit comments

Comments
 (0)