Add option '-fvisibility=<hidden|default>' able to hide symbols not marked as 'export' on non-Windows targets. Resolves #2431 (#2894)

This commit is contained in:
Andrey Penechko 2018-11-09 21:55:57 +02:00 committed by Martin Kinkelin
parent 41e2ed034f
commit 7bcd6d34dd
8 changed files with 90 additions and 0 deletions

View file

@ -81,6 +81,13 @@ static cl::opt<bool, true>
createSharedLib("shared", cl::desc("Create shared library (DLL)"), createSharedLib("shared", cl::desc("Create shared library (DLL)"),
cl::ZeroOrMore, cl::location(global.params.dll)); cl::ZeroOrMore, cl::location(global.params.dll));
cl::opt<ubyte> defaultToHiddenVisibility(
"fvisibility", cl::ZeroOrMore,
cl::desc("Default visibility of symbols (not relevant for Windows)"),
clEnumValues(clEnumValN(0, "default", "Export all symbols"),
clEnumValN(1, "hidden",
"Only export symbols marked with 'export'")));
static cl::opt<bool, true> verbose("v", cl::desc("Verbose"), cl::ZeroOrMore, static cl::opt<bool, true> verbose("v", cl::desc("Verbose"), cl::ZeroOrMore,
cl::location(global.params.verbose)); cl::location(global.params.verbose));

View file

@ -77,6 +77,7 @@ extern cl::opt<std::string> mABI;
extern FloatABI::Type floatABI; extern FloatABI::Type floatABI;
extern cl::opt<bool> linkonceTemplates; extern cl::opt<bool> linkonceTemplates;
extern cl::opt<bool> disableLinkerStripDead; extern cl::opt<bool> disableLinkerStripDead;
extern cl::opt<ubyte> defaultToHiddenVisibility;
// Math options // Math options
extern bool fFastMath; extern bool fFastMath;

View file

@ -17,6 +17,7 @@
#include "dmd/nspace.h" #include "dmd/nspace.h"
#include "dmd/root/rmem.h" #include "dmd/root/rmem.h"
#include "dmd/template.h" #include "dmd/template.h"
#include "driver/cl_options.h"
#include "gen/classes.h" #include "gen/classes.h"
#include "gen/functions.h" #include "gen/functions.h"
#include "gen/irstate.h" #include "gen/irstate.h"
@ -308,6 +309,11 @@ public:
gvar->setDLLStorageClass(LLGlobalValue::DLLExportStorageClass); gvar->setDLLStorageClass(LLGlobalValue::DLLExportStorageClass);
} }
// Hide non-exported symbols
if (opts::defaultToHiddenVisibility && !decl->isExport()) {
gvar->setVisibility(LLGlobalValue::HiddenVisibility);
}
// Also set up the debug info. // Also set up the debug info.
irs->DBuilder.EmitGlobalVariable(gvar, decl); irs->DBuilder.EmitGlobalVariable(gvar, decl);
} }

View file

@ -574,6 +574,13 @@ void DtoDeclareFunction(FuncDeclaration *fdecl) {
: LLGlobalValue::DLLExportStorageClass); : LLGlobalValue::DLLExportStorageClass);
} }
// Hide non-exported symbols
if (opts::defaultToHiddenVisibility &&
!fdecl->isImportedSymbol() &&
!fdecl->isExport()) {
func->setVisibility(LLGlobalValue::HiddenVisibility);
}
IF_LOG Logger::cout() << "func = " << *func << std::endl; IF_LOG Logger::cout() << "func = " << *func << std::endl;
// add func to IRFunc // add func to IRFunc

View file

@ -0,0 +1,26 @@
// Test that passing -fvisibility=hidden hides all unexported symbols
// UNSUPPORTED: Windows
// RUN: ldc2 %s -betterC -shared -fvisibility=hidden -of=lib%t.so
// RUN: nm -g lib%t.so | FileCheck %s
// CHECK: test__exportedFunDef
// CHECK: test__exportedVarDef
// CHECK-NOT: test__nonExportedFunDecl
// CHECK-NOT: test__nonExportedFunDef
// CHECK-NOT: test__nonExportedVarDecl
// CHECK-NOT: test__nonExportedVarDef
extern(C) export int test__exportedFunDef() { return 42; }
extern(C) int test__nonExportedFunDef() { return 101; }
extern(C) export int test__exportedFunDecl();
extern(C) int test__nonExportedFunDecl();
extern(C) export int test__exportedVarDef;
extern(C) int test__nonExportedVarDef;
extern(C) extern export int test__exportedVarDecl;
extern(C) extern int test__nonExportedVarDecl;

View file

@ -0,0 +1,26 @@
// Test that compiling with -fvisibility=default exports all symbols on non-Windows targets
// UNSUPPORTED: Windows
// RUN: ldc2 %s -betterC -shared -fvisibility=default -of=lib%t.so
// RUN: nm -g lib%t.so | FileCheck %s
// CHECK: test__exportedFunDef
// CHECK: test__exportedVarDef
// CHECK-NOT: test__nonExportedFunDecl
// CHECK: test__nonExportedFunDef
// CHECK-NOT: test__nonExportedVarDecl
// CHECK: test__nonExportedVarDef
extern(C) export int test__exportedFunDef() { return 42; }
extern(C) int test__nonExportedFunDef() { return 101; }
extern(C) export int test__exportedFunDecl();
extern(C) int test__nonExportedFunDecl();
extern(C) export int test__exportedVarDef;
extern(C) int test__nonExportedVarDef;
extern(C) extern export int test__exportedVarDecl;
extern(C) extern int test__nonExportedVarDecl;

View file

@ -0,0 +1,15 @@
// Test that -fvisibility=hidden works with thin LTO
// REQUIRES: LTO
// RUN: ldc2 %S/inputs/export_marked_symbols_thin_lto_lib.d -c -fvisibility=hidden -flto=thin -of=%t1%obj
// RUN: ldc2 %s -I%S/inputs -c -flto=thin -of=%t2%obj
// RUN: ldc2 %t1%obj %t2%obj -flto=thin
import export_marked_symbols_thin_lto_lib;
void main()
{
exportedFoo();
normalFoo();
}

View file

@ -0,0 +1,2 @@
export void exportedFoo() {}
void normalFoo() {} // hidden visibility