Skip to content

Commit e3033a2

Browse files
committed
[lld-macho] Add flag --keep-icf-stabs to LLD for MachO
1 parent 3ca428c commit e3033a2

File tree

5 files changed

+42
-5
lines changed

5 files changed

+42
-5
lines changed

lld/MachO/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ struct Configuration {
193193
UndefinedSymbolTreatment undefinedSymbolTreatment =
194194
UndefinedSymbolTreatment::error;
195195
ICFLevel icfLevel = ICFLevel::none;
196+
bool keepICFStabs = false;
196197
ObjCStubsMode objcStubsMode = ObjCStubsMode::fast;
197198
llvm::MachO::HeaderFileType outputType;
198199
std::vector<llvm::StringRef> systemLibraryRoots;

lld/MachO/Driver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,6 +1648,7 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
16481648
config->emitChainedFixups || args.hasArg(OPT_init_offsets);
16491649
config->emitRelativeMethodLists = shouldEmitRelativeMethodLists(args);
16501650
config->icfLevel = getICFLevel(args);
1651+
config->keepICFStabs = args.hasArg(OPT_keep_icf_stabs);
16511652
config->dedupStrings =
16521653
args.hasFlag(OPT_deduplicate_strings, OPT_no_deduplicate_strings, true);
16531654
config->deadStripDuplicates = args.hasArg(OPT_dead_strip_duplicates);

lld/MachO/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ def icf_eq: Joined<["--"], "icf=">,
8585
HelpText<"Set level for identical code folding (default: none)">,
8686
MetaVarName<"[none,safe,all]">,
8787
Group<grp_lld>;
88+
def keep_icf_stabs: Joined<["--"], "keep-icf-stabs">,
89+
HelpText<"For symbols that were folded by ICF - retain them as stabs entries">,
90+
Group<grp_lld>;
8891
def lto_O: Joined<["--"], "lto-O">,
8992
HelpText<"Set optimization level for LTO (default: 2)">,
9093
MetaVarName<"<opt-level>">,

lld/MachO/SyntheticSections.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,15 +1220,18 @@ void SymtabSection::emitStabs() {
12201220
continue;
12211221

12221222
// Constant-folded symbols go in the executable's symbol table, but don't
1223-
// get a stabs entry.
1224-
if (defined->wasIdenticalCodeFolded)
1223+
// get a stabs entry unless --keep-icf-stabs flag is specified
1224+
if (!config->keepICFStabs && defined->wasIdenticalCodeFolded)
12251225
continue;
12261226

12271227
ObjFile *file = defined->getObjectFile();
12281228
if (!file || !file->compileUnit)
12291229
continue;
12301230

1231-
symbolsNeedingStabs.emplace_back(defined, defined->isec()->getFile()->id);
1231+
// We use 'originalIsec' to get the file id of the symbol since 'isec()'
1232+
// might point to the merged ICF symbol's file
1233+
symbolsNeedingStabs.emplace_back(defined,
1234+
defined->originalIsec->getFile()->id);
12321235
}
12331236
}
12341237

@@ -1243,7 +1246,9 @@ void SymtabSection::emitStabs() {
12431246
InputFile *lastFile = nullptr;
12441247
for (SortingPair &pair : symbolsNeedingStabs) {
12451248
Defined *defined = pair.first;
1246-
InputSection *isec = defined->isec();
1249+
// We use 'originalIsec' of the symbol since we care about the actual origin
1250+
// of the symbol, not the canonical location returned by `isec()`.
1251+
InputSection *isec = defined->originalIsec;
12471252
ObjFile *file = cast<ObjFile>(isec->getFile());
12481253

12491254
if (lastFile == nullptr || lastFile != file) {
@@ -1256,7 +1261,7 @@ void SymtabSection::emitStabs() {
12561261
}
12571262

12581263
StabsEntry symStab;
1259-
symStab.sect = defined->isec()->parent->index;
1264+
symStab.sect = isec->parent->index;
12601265
symStab.strx = stringTableSection.addString(defined->getName());
12611266
symStab.value = defined->getVA();
12621267

lld/test/MachO/stabs-icf.s

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
# RUN: %lld -lSystem --icf=all %t.o -o %t
55
# RUN: dsymutil -s %t | FileCheck %s -DDIR=%t -DSRC_PATH=%t.o
66

7+
# RUN: %lld -lSystem --icf=all %t.o -o %t_icf_stabs --keep-icf-stabs
8+
# RUN: dsymutil -s %t_icf_stabs | FileCheck %s -DDIR=%t_icf_stabs -DSRC_PATH=%t.o --check-prefixes=ICF_STABS
9+
710
## This should include no N_FUN entry for _baz (which is ICF'd into _bar),
811
## but it does include a SECT EXT entry.
912
## NOTE: We do not omit the N_FUN entry for _bar even though it is of size zero.
@@ -27,6 +30,30 @@
2730
# CHECK-DAG: ( {{.*}}) {{[0-9]+}} 0100 0000000000000000 'dyld_stub_binder'
2831
# CHECK-EMPTY:
2932

33+
34+
# ICF_STABS: (N_SO ) 00 0000 0000000000000000 '/tmp{{[/\\]}}test.cpp'
35+
# ICF_STABS-NEXT: (N_OSO ) 03 0001 {{.*}} '[[SRC_PATH]]'
36+
# ICF_STABS-NEXT: (N_FUN ) 01 0000 [[#%.16x,MAIN:]] '_main'
37+
# ICF_STABS-NEXT: (N_FUN ) 00 0000 000000000000000b{{$}}
38+
# ICF_STABS-NEXT: (N_FUN ) 01 0000 [[#%.16x,BAR:]] '_bar'
39+
# ICF_STABS-NEXT: (N_FUN ) 00 0000 0000000000000000{{$}}
40+
# ICF_STABS-NEXT: (N_FUN ) 01 0000 [[#BAR]] '_bar2'
41+
# ICF_STABS-NEXT: (N_FUN ) 00 0000 0000000000000001{{$}}
42+
# ICF_STABS-NEXT: (N_FUN ) 01 0000 [[#BAR]] '_baz'
43+
# ICF_STABS-NEXT: (N_FUN ) 00 0000 0000000000000000{{$}}
44+
# ICF_STABS-NEXT: (N_FUN ) 01 0000 [[#BAR]] '_baz2'
45+
# ICF_STABS-NEXT: (N_FUN ) 00 0000 0000000000000001{{$}}
46+
# ICF_STABS-NEXT: (N_SO ) 01 0000 0000000000000000{{$}}
47+
# ICF_STABS-DAG: ( SECT EXT) 01 0000 [[#MAIN]] '_main'
48+
# ICF_STABS-DAG: ( SECT EXT) 01 0000 [[#BAR]] '_bar'
49+
# ICF_STABS-DAG: ( SECT EXT) 01 0000 [[#BAR]] '_bar2'
50+
# ICF_STABS-DAG: ( SECT EXT) 01 0000 [[#BAR]] '_baz'
51+
# ICF_STABS-DAG: ( SECT EXT) 01 0000 [[#BAR]] '_baz2'
52+
# ICF_STABS-DAG: ( {{.*}}) {{[0-9]+}} 0010 {{[0-9a-f]+}} '__mh_execute_header'
53+
# ICF_STABS-DAG: ( {{.*}}) {{[0-9]+}} 0100 0000000000000000 'dyld_stub_binder'
54+
# ICF_STABS-EMPTY:
55+
56+
3057
.text
3158
.globl _bar, _bar2, _baz, _baz2, _main
3259

0 commit comments

Comments
 (0)