mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 07:06:38 +00:00
[lld-macho] Add flag --keep-icf-stabs to LLD for MachO (#93137)
This change adds the `--keep-icf-stabs` which, when specified, preserves symbols that were folded by ICF in the binary's stabs entries. This allows `dsymutil` to process debug information for the folded symbols.
This commit is contained in:
parent
9ca2d60213
commit
5eea4f4425
@ -193,6 +193,7 @@ struct Configuration {
|
||||
UndefinedSymbolTreatment undefinedSymbolTreatment =
|
||||
UndefinedSymbolTreatment::error;
|
||||
ICFLevel icfLevel = ICFLevel::none;
|
||||
bool keepICFStabs = false;
|
||||
ObjCStubsMode objcStubsMode = ObjCStubsMode::fast;
|
||||
llvm::MachO::HeaderFileType outputType;
|
||||
std::vector<llvm::StringRef> systemLibraryRoots;
|
||||
|
@ -1648,6 +1648,7 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
|
||||
config->emitChainedFixups || args.hasArg(OPT_init_offsets);
|
||||
config->emitRelativeMethodLists = shouldEmitRelativeMethodLists(args);
|
||||
config->icfLevel = getICFLevel(args);
|
||||
config->keepICFStabs = args.hasArg(OPT_keep_icf_stabs);
|
||||
config->dedupStrings =
|
||||
args.hasFlag(OPT_deduplicate_strings, OPT_no_deduplicate_strings, true);
|
||||
config->deadStripDuplicates = args.hasArg(OPT_dead_strip_duplicates);
|
||||
|
@ -85,6 +85,9 @@ def icf_eq: Joined<["--"], "icf=">,
|
||||
HelpText<"Set level for identical code folding (default: none)">,
|
||||
MetaVarName<"[none,safe,all]">,
|
||||
Group<grp_lld>;
|
||||
def keep_icf_stabs: Joined<["--"], "keep-icf-stabs">,
|
||||
HelpText<"Generate STABS entries for symbols folded by ICF. These entries can then be used by dsymutil to discover the address range where folded symbols are located.">,
|
||||
Group<grp_lld>;
|
||||
def lto_O: Joined<["--"], "lto-O">,
|
||||
HelpText<"Set optimization level for LTO (default: 2)">,
|
||||
MetaVarName<"<opt-level>">,
|
||||
|
@ -1220,15 +1220,18 @@ void SymtabSection::emitStabs() {
|
||||
continue;
|
||||
|
||||
// Constant-folded symbols go in the executable's symbol table, but don't
|
||||
// get a stabs entry.
|
||||
if (defined->wasIdenticalCodeFolded)
|
||||
// get a stabs entry unless --keep-icf-stabs flag is specified
|
||||
if (!config->keepICFStabs && defined->wasIdenticalCodeFolded)
|
||||
continue;
|
||||
|
||||
ObjFile *file = defined->getObjectFile();
|
||||
if (!file || !file->compileUnit)
|
||||
continue;
|
||||
|
||||
symbolsNeedingStabs.emplace_back(defined, defined->isec()->getFile()->id);
|
||||
// We use 'originalIsec' to get the file id of the symbol since 'isec()'
|
||||
// might point to the merged ICF symbol's file
|
||||
symbolsNeedingStabs.emplace_back(defined,
|
||||
defined->originalIsec->getFile()->id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1243,7 +1246,9 @@ void SymtabSection::emitStabs() {
|
||||
InputFile *lastFile = nullptr;
|
||||
for (SortingPair &pair : symbolsNeedingStabs) {
|
||||
Defined *defined = pair.first;
|
||||
InputSection *isec = defined->isec();
|
||||
// We use 'originalIsec' of the symbol since we care about the actual origin
|
||||
// of the symbol, not the canonical location returned by `isec()`.
|
||||
InputSection *isec = defined->originalIsec;
|
||||
ObjFile *file = cast<ObjFile>(isec->getFile());
|
||||
|
||||
if (lastFile == nullptr || lastFile != file) {
|
||||
@ -1256,7 +1261,7 @@ void SymtabSection::emitStabs() {
|
||||
}
|
||||
|
||||
StabsEntry symStab;
|
||||
symStab.sect = defined->isec()->parent->index;
|
||||
symStab.sect = isec->parent->index;
|
||||
symStab.strx = stringTableSection.addString(defined->getName());
|
||||
symStab.value = defined->getVA();
|
||||
|
||||
|
@ -4,6 +4,9 @@
|
||||
# RUN: %lld -lSystem --icf=all %t.o -o %t
|
||||
# RUN: dsymutil -s %t | FileCheck %s -DDIR=%t -DSRC_PATH=%t.o
|
||||
|
||||
# RUN: %lld -lSystem --icf=all %t.o -o %t_icf_stabs --keep-icf-stabs
|
||||
# RUN: dsymutil -s %t_icf_stabs | FileCheck %s -DDIR=%t_icf_stabs -DSRC_PATH=%t.o --check-prefixes=ICF_STABS
|
||||
|
||||
## This should include no N_FUN entry for _baz (which is ICF'd into _bar),
|
||||
## but it does include a SECT EXT entry.
|
||||
## NOTE: We do not omit the N_FUN entry for _bar even though it is of size zero.
|
||||
@ -27,6 +30,30 @@
|
||||
# CHECK-DAG: ( {{.*}}) {{[0-9]+}} 0100 0000000000000000 'dyld_stub_binder'
|
||||
# CHECK-EMPTY:
|
||||
|
||||
|
||||
# ICF_STABS: (N_SO ) 00 0000 0000000000000000 '/tmp{{[/\\]}}test.cpp'
|
||||
# ICF_STABS-NEXT: (N_OSO ) 03 0001 {{.*}} '[[SRC_PATH]]'
|
||||
# ICF_STABS-NEXT: (N_FUN ) 01 0000 [[#%.16x,MAIN:]] '_main'
|
||||
# ICF_STABS-NEXT: (N_FUN ) 00 0000 000000000000000b{{$}}
|
||||
# ICF_STABS-NEXT: (N_FUN ) 01 0000 [[#%.16x,BAR:]] '_bar'
|
||||
# ICF_STABS-NEXT: (N_FUN ) 00 0000 0000000000000000{{$}}
|
||||
# ICF_STABS-NEXT: (N_FUN ) 01 0000 [[#BAR]] '_bar2'
|
||||
# ICF_STABS-NEXT: (N_FUN ) 00 0000 0000000000000001{{$}}
|
||||
# ICF_STABS-NEXT: (N_FUN ) 01 0000 [[#BAR]] '_baz'
|
||||
# ICF_STABS-NEXT: (N_FUN ) 00 0000 0000000000000000{{$}}
|
||||
# ICF_STABS-NEXT: (N_FUN ) 01 0000 [[#BAR]] '_baz2'
|
||||
# ICF_STABS-NEXT: (N_FUN ) 00 0000 0000000000000001{{$}}
|
||||
# ICF_STABS-NEXT: (N_SO ) 01 0000 0000000000000000{{$}}
|
||||
# ICF_STABS-DAG: ( SECT EXT) 01 0000 [[#MAIN]] '_main'
|
||||
# ICF_STABS-DAG: ( SECT EXT) 01 0000 [[#BAR]] '_bar'
|
||||
# ICF_STABS-DAG: ( SECT EXT) 01 0000 [[#BAR]] '_bar2'
|
||||
# ICF_STABS-DAG: ( SECT EXT) 01 0000 [[#BAR]] '_baz'
|
||||
# ICF_STABS-DAG: ( SECT EXT) 01 0000 [[#BAR]] '_baz2'
|
||||
# ICF_STABS-DAG: ( {{.*}}) {{[0-9]+}} 0010 {{[0-9a-f]+}} '__mh_execute_header'
|
||||
# ICF_STABS-DAG: ( {{.*}}) {{[0-9]+}} 0100 0000000000000000 'dyld_stub_binder'
|
||||
# ICF_STABS-EMPTY:
|
||||
|
||||
|
||||
.text
|
||||
.globl _bar, _bar2, _baz, _baz2, _main
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user