Add support for export_dynamic cmdline option and behaviour.

This option matches the behaviour of ld64, that is it prevents globals
from being dead stripped in executables and dylibs.

Reviewed by Lang Hames

Differential Revision: http://reviews.llvm.org/D16026

llvm-svn: 258554
This commit is contained in:
Pete Cooper
2016-01-22 21:13:24 +00:00
parent 7849ad0f72
commit 351164504a
6 changed files with 69 additions and 4 deletions

View File

@@ -84,7 +84,8 @@ public:
/// Initializes the context to sane default values given the specified output
/// file type, arch, os, and minimum os version. This should be called before
/// other setXXX() methods.
void configure(HeaderFileType type, Arch arch, OS os, uint32_t minOSVersion);
void configure(HeaderFileType type, Arch arch, OS os, uint32_t minOSVersion,
bool exportDynamicSymbols);
void addPasses(PassManager &pm) override;
bool validateImpl(raw_ostream &diagnostics) override;

View File

@@ -385,9 +385,16 @@ bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
// No min-os version on command line, check environment variables
}
// Handle export_dynamic
// FIXME: Should we warn when this applies to something other than a static
// executable or dylib? Those are the only cases where this has an effect.
// Note, this has to come before ctx.configure() so that we get the correct
// value for _globalsAreDeadStripRoots.
bool exportDynamicSymbols = parsedArgs.hasArg(OPT_export_dynamic);
// Now that there's enough information parsed in, let the linking context
// set up default values.
ctx.configure(fileType, arch, os, minOSVersion);
ctx.configure(fileType, arch, os, minOSVersion, exportDynamicSymbols);
// Handle -e xxx
if (llvm::opt::Arg *entry = parsedArgs.getLastArg(OPT_entry))

View File

@@ -84,6 +84,9 @@ def stack_size : Separate<["-"], "stack_size">,
HelpText<"Specifies the maximum stack size for the main thread in a program. "
"Must be a page-size multiple. (default=8Mb)">,
Group<grp_main>;
def export_dynamic : Flag<["-"], "export_dynamic">,
HelpText<"Preserves all global symbols in main executables during LTO">,
Group<grp_main>;
// dylib executable options
def grp_dylib : OptionGroup<"opts">, HelpText<"DYLIB EXECUTABLE OPTIONS">;

View File

@@ -155,7 +155,8 @@ MachOLinkingContext::MachOLinkingContext()
MachOLinkingContext::~MachOLinkingContext() {}
void MachOLinkingContext::configure(HeaderFileType type, Arch arch, OS os,
uint32_t minOSVersion) {
uint32_t minOSVersion,
bool exportDynamicSymbols) {
_outputMachOType = type;
_arch = arch;
_os = os;
@@ -218,9 +219,10 @@ void MachOLinkingContext::configure(HeaderFileType type, Arch arch, OS os,
case OS::unknown:
break;
}
setGlobalsAreDeadStripRoots(exportDynamicSymbols);
break;
case llvm::MachO::MH_DYLIB:
setGlobalsAreDeadStripRoots(true);
setGlobalsAreDeadStripRoots(exportDynamicSymbols);
break;
case llvm::MachO::MH_BUNDLE:
break;

View File

@@ -0,0 +1,27 @@
# RUN: lld -flavor darwin -arch x86_64 -dead_strip -export_dynamic %s -dylib %p/Inputs/libSystem.yaml -o %t.dylib -print_atoms | FileCheck -check-prefix=CHECK1 %s
# RUN: lld -flavor darwin -arch x86_64 -export_dynamic -dead_strip %s -dylib %p/Inputs/libSystem.yaml -o %t.dylib -print_atoms | FileCheck -check-prefix=CHECK1 %s
# RUN: lld -flavor darwin -arch x86_64 -dead_strip %s -dylib %p/Inputs/libSystem.yaml -o %t2.dylib -print_atoms | FileCheck -check-prefix=CHECK2 %s
#
# Test that -export_dynamic -dead-strip from removing globals.
#
---
defined-atoms:
- name: def
scope: global
dead-strip: never
- name: dead
scope: global
shared-library-atoms:
- name: dyld_stub_binder
load-name: /usr/lib/libSystem.B.dylib
type: unknown
...
# CHECK1: name: def
# CHECK1: name: dead
# CHECK2: name: def
# CHECK2-NOT: name: dead

View File

@@ -84,9 +84,34 @@ TEST_F(DarwinLdParserTest, DeadStripRootsExe) {
TEST_F(DarwinLdParserTest, DeadStripRootsDylib) {
EXPECT_TRUE(parse("ld", "-arch", "x86_64", "-dylib", "-dead_strip", "foo.o",
nullptr));
EXPECT_FALSE(_ctx.globalsAreDeadStripRoots());
}
TEST_F(DarwinLdParserTest, DeadStripRootsRelocatable) {
EXPECT_TRUE(parse("ld", "-arch", "x86_64", "-r", "-dead_strip", "foo.o",
nullptr));
EXPECT_FALSE(_ctx.globalsAreDeadStripRoots());
}
TEST_F(DarwinLdParserTest, DeadStripRootsExportDynamicExe) {
EXPECT_TRUE(parse("ld", "-arch", "x86_64", "-dead_strip",
"-export_dynamic", "foo.o", nullptr));
EXPECT_TRUE(_ctx.globalsAreDeadStripRoots());
}
TEST_F(DarwinLdParserTest, DeadStripRootsExportDynamicDylib) {
EXPECT_TRUE(parse("ld", "-arch", "x86_64", "-dylib", "-dead_strip",
"-export_dynamic", "foo.o",
nullptr));
EXPECT_TRUE(_ctx.globalsAreDeadStripRoots());
}
TEST_F(DarwinLdParserTest, DeadStripRootsExportDynamicRelocatable) {
EXPECT_TRUE(parse("ld", "-arch", "x86_64", "-r", "-dead_strip",
"-export_dynamic", "foo.o", nullptr));
EXPECT_FALSE(_ctx.globalsAreDeadStripRoots());
}
TEST_F(DarwinLdParserTest, Arch) {
EXPECT_TRUE(parse("ld", "-arch", "x86_64", "foo.o", nullptr));
EXPECT_EQ(MachOLinkingContext::arch_x86_64, _ctx.arch());