forked from OSchip/llvm-project
[dsymutil] Add flag to force a static variable to keep its enclosing function
Add a flag to change dsymutil's behavior and force a static variable to keep its enclosing function. The test shows a situation where that could be useful. I'm not convinced this behavior makes sense as a default, which is why it's behind a flag. rdar://74918374 Differential revision: https://reviews.llvm.org/D101337
This commit is contained in:
parent
8a4ee3b39c
commit
625bd94c6d
|
@ -50,6 +50,11 @@ OPTIONS
|
||||||
|
|
||||||
Print this help output.
|
Print this help output.
|
||||||
|
|
||||||
|
.. option:: --keep-function-for-static
|
||||||
|
|
||||||
|
Make a static variable keep the enclosing function even if it would have been
|
||||||
|
omitted otherwise.
|
||||||
|
|
||||||
.. option:: --minimize, -z
|
.. option:: --minimize, -z
|
||||||
|
|
||||||
When used when creating a dSYM file, this option will suppress the emission of
|
When used when creating a dSYM file, this option will suppress the emission of
|
||||||
|
|
|
@ -281,6 +281,11 @@ public:
|
||||||
/// update existing DWARF info(for the linked binary).
|
/// update existing DWARF info(for the linked binary).
|
||||||
void setUpdate(bool Update) { Options.Update = Update; }
|
void setUpdate(bool Update) { Options.Update = Update; }
|
||||||
|
|
||||||
|
/// Set whether to keep the enclosing function for a static variable.
|
||||||
|
void setKeepFunctionForStatic(bool KeepFunctionForStatic) {
|
||||||
|
Options.KeepFunctionForStatic = KeepFunctionForStatic;
|
||||||
|
}
|
||||||
|
|
||||||
/// Use specified number of threads for parallel files linking.
|
/// Use specified number of threads for parallel files linking.
|
||||||
void setNumThreads(unsigned NumThreads) { Options.Threads = NumThreads; }
|
void setNumThreads(unsigned NumThreads) { Options.Threads = NumThreads; }
|
||||||
|
|
||||||
|
@ -782,6 +787,10 @@ private:
|
||||||
/// Update
|
/// Update
|
||||||
bool Update = false;
|
bool Update = false;
|
||||||
|
|
||||||
|
/// Whether we want a static variable to force us to keep its enclosing
|
||||||
|
/// function.
|
||||||
|
bool KeepFunctionForStatic = false;
|
||||||
|
|
||||||
/// Number of threads.
|
/// Number of threads.
|
||||||
unsigned Threads = 1;
|
unsigned Threads = 1;
|
||||||
|
|
||||||
|
|
|
@ -434,13 +434,15 @@ unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr,
|
||||||
return Flags | TF_Keep;
|
return Flags | TF_Keep;
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if there is a relocation to a valid debug map entry inside
|
// See if there is a relocation to a valid debug map entry inside this
|
||||||
// this variable's location. The order is important here. We want to
|
// variable's location. The order is important here. We want to always check
|
||||||
// always check if the variable has a valid relocation, so that the
|
// if the variable has a valid relocation, so that the DIEInfo is filled.
|
||||||
// DIEInfo is filled. However, we don't want a static variable in a
|
// However, we don't want a static variable in a function to force us to keep
|
||||||
// function to force us to keep the enclosing function.
|
// the enclosing function, unless requested explicitly.
|
||||||
if (!RelocMgr.hasLiveMemoryLocation(DIE, MyInfo) ||
|
const bool HasLiveMemoryLocation =
|
||||||
(Flags & TF_InFunctionScope))
|
RelocMgr.hasLiveMemoryLocation(DIE, MyInfo);
|
||||||
|
if (!HasLiveMemoryLocation || ((Flags & TF_InFunctionScope) &&
|
||||||
|
!LLVM_UNLIKELY(Options.KeepFunctionForStatic)))
|
||||||
return Flags;
|
return Flags;
|
||||||
|
|
||||||
if (Options.Verbose) {
|
if (Options.Verbose) {
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,36 @@
|
||||||
|
$ cat main.cpp
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static void Foo(void)
|
||||||
|
{
|
||||||
|
typedef struct {
|
||||||
|
int x1;
|
||||||
|
int x2;
|
||||||
|
} FOO_VAR_TYPE;
|
||||||
|
static FOO_VAR_TYPE MyDummyVar __attribute__((aligned(4), used, section("TAD_VIRTUAL, TAD_DUMMY_DATA"), nocommon));
|
||||||
|
printf("Foo called");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Foo();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ clang++ -O2 -g main.cpp -c -o main.o
|
||||||
|
$ clang++ main.o -o main.out
|
||||||
|
|
||||||
|
RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/keep_func/main.out -o %t.omit.dSYM
|
||||||
|
RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/keep_func/main.out -o %t.keep.dSYM -keep-function-for-static
|
||||||
|
RUN: llvm-dwarfdump %t.omit.dSYM | FileCheck %s --check-prefix OMIT
|
||||||
|
RUN: llvm-dwarfdump %t.keep.dSYM | FileCheck %s --check-prefix KEEP
|
||||||
|
|
||||||
|
KEEP: DW_AT_name ("MyDummyVar")
|
||||||
|
KEEP: DW_AT_name ("FOO_VAR_TYPE")
|
||||||
|
KEEP: DW_AT_name ("x1")
|
||||||
|
KEEP: DW_AT_name ("x2")
|
||||||
|
|
||||||
|
OMIT-NOT: DW_AT_name ("MyDummyVar")
|
||||||
|
OMIT-NOT: DW_AT_name ("FOO_VAR_TYPE")
|
||||||
|
OMIT-NOT: DW_AT_name ("x1")
|
||||||
|
OMIT-NOT: DW_AT_name ("x2")
|
|
@ -11,6 +11,7 @@ CHECK: -dump-debug-map
|
||||||
CHECK: -flat
|
CHECK: -flat
|
||||||
CHECK: -gen-reproducer
|
CHECK: -gen-reproducer
|
||||||
CHECK: -help
|
CHECK: -help
|
||||||
|
CHECK: -keep-function-for-static
|
||||||
CHECK: -no-odr
|
CHECK: -no-odr
|
||||||
CHECK: -no-output
|
CHECK: -no-output
|
||||||
CHECK: -no-swiftmodule-timestamp
|
CHECK: -no-swiftmodule-timestamp
|
||||||
|
|
|
@ -325,6 +325,7 @@ bool DwarfLinkerForBinary::link(const DebugMap &Map) {
|
||||||
GeneralLinker.setNumThreads(Options.Threads);
|
GeneralLinker.setNumThreads(Options.Threads);
|
||||||
GeneralLinker.setAccelTableKind(Options.TheAccelTableKind);
|
GeneralLinker.setAccelTableKind(Options.TheAccelTableKind);
|
||||||
GeneralLinker.setPrependPath(Options.PrependPath);
|
GeneralLinker.setPrependPath(Options.PrependPath);
|
||||||
|
GeneralLinker.setKeepFunctionForStatic(Options.KeepFunctionForStatic);
|
||||||
if (Options.Translator)
|
if (Options.Translator)
|
||||||
GeneralLinker.setStringsTranslator(TranslationLambda);
|
GeneralLinker.setStringsTranslator(TranslationLambda);
|
||||||
GeneralLinker.setWarningHandler(
|
GeneralLinker.setWarningHandler(
|
||||||
|
|
|
@ -42,6 +42,10 @@ struct LinkOptions {
|
||||||
/// Do not check swiftmodule timestamp
|
/// Do not check swiftmodule timestamp
|
||||||
bool NoTimestamp = false;
|
bool NoTimestamp = false;
|
||||||
|
|
||||||
|
/// Whether we want a static variable to force us to keep its enclosing
|
||||||
|
/// function.
|
||||||
|
bool KeepFunctionForStatic = false;
|
||||||
|
|
||||||
/// Number of threads.
|
/// Number of threads.
|
||||||
unsigned Threads = 1;
|
unsigned Threads = 1;
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,10 @@ def verbose: F<"verbose">,
|
||||||
HelpText<"Enable verbose mode.">,
|
HelpText<"Enable verbose mode.">,
|
||||||
Group<grp_general>;
|
Group<grp_general>;
|
||||||
|
|
||||||
|
def keep_func_for_static: F<"keep-function-for-static">,
|
||||||
|
HelpText<"Make a static variable keep the enclosing function even if it would have been omitted otherwise.">,
|
||||||
|
Group<grp_general>;
|
||||||
|
|
||||||
def statistics: F<"statistics">,
|
def statistics: F<"statistics">,
|
||||||
HelpText<"Print statistics about the contribution of each object file to "
|
HelpText<"Print statistics about the contribution of each object file to "
|
||||||
"the linked debug info. This prints a table after linking with the "
|
"the linked debug info. This prints a table after linking with the "
|
||||||
|
|
|
@ -91,6 +91,7 @@ struct DsymutilOptions {
|
||||||
bool InputIsYAMLDebugMap = false;
|
bool InputIsYAMLDebugMap = false;
|
||||||
bool PaperTrailWarnings = false;
|
bool PaperTrailWarnings = false;
|
||||||
bool Verify = false;
|
bool Verify = false;
|
||||||
|
bool ForceKeepFunctionForStatic = false;
|
||||||
std::string SymbolMap;
|
std::string SymbolMap;
|
||||||
std::string OutputFile;
|
std::string OutputFile;
|
||||||
std::string Toolchain;
|
std::string Toolchain;
|
||||||
|
@ -230,6 +231,8 @@ static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
|
||||||
Options.LinkOpts.Update = Args.hasArg(OPT_update);
|
Options.LinkOpts.Update = Args.hasArg(OPT_update);
|
||||||
Options.LinkOpts.Verbose = Args.hasArg(OPT_verbose);
|
Options.LinkOpts.Verbose = Args.hasArg(OPT_verbose);
|
||||||
Options.LinkOpts.Statistics = Args.hasArg(OPT_statistics);
|
Options.LinkOpts.Statistics = Args.hasArg(OPT_statistics);
|
||||||
|
Options.LinkOpts.KeepFunctionForStatic =
|
||||||
|
Args.hasArg(OPT_keep_func_for_static);
|
||||||
|
|
||||||
if (opt::Arg *ReproducerPath = Args.getLastArg(OPT_use_reproducer)) {
|
if (opt::Arg *ReproducerPath = Args.getLastArg(OPT_use_reproducer)) {
|
||||||
Options.ReproMode = ReproducerMode::Use;
|
Options.ReproMode = ReproducerMode::Use;
|
||||||
|
|
Loading…
Reference in New Issue