From 343580097d9e0d5da24c7e2e7747f9e1032add57 Mon Sep 17 00:00:00 2001 From: George Rimar Date: Mon, 14 Mar 2016 09:19:30 +0000 Subject: [PATCH] [ELF] implement --warn-common/--no-warn-common -warn-common Warn when a common symbol is combined with another common symbol or with a symbol definition. Unix linkers allow this somewhat sloppy practice, but linkers on some other operating systems do not. This option allows you to find potential problems from combining global symbols. Differential revision: http://reviews.llvm.org/D17998 llvm-svn: 263413 --- lld/ELF/Config.h | 1 + lld/ELF/Driver.cpp | 1 + lld/ELF/Options.td | 5 ++++- lld/ELF/Symbols.cpp | 4 ++++ lld/test/ELF/Inputs/warn-common.s | 2 ++ lld/test/ELF/Inputs/warn-common2.s | 8 ++++++++ lld/test/ELF/warn-common.s | 25 +++++++++++++++++++++++++ 7 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 lld/test/ELF/Inputs/warn-common.s create mode 100644 lld/test/ELF/Inputs/warn-common2.s create mode 100644 lld/test/ELF/warn-common.s diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index fa31b40ca9ae..f1a90f2070e1 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -78,6 +78,7 @@ struct Configuration { bool SysvHash = true; bool Threads; bool Verbose; + bool WarnCommon; bool ZExecStack; bool ZNodelete; bool ZNow; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 22c61450e3f6..f5eecb4148a2 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -244,6 +244,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { Config->StripAll = Args.hasArg(OPT_strip_all); Config->Threads = Args.hasArg(OPT_threads); Config->Verbose = Args.hasArg(OPT_verbose); + Config->WarnCommon = Args.hasArg(OPT_warn_common); Config->DynamicLinker = getString(Args, OPT_dynamic_linker); Config->Entry = getString(Args, OPT_entry); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 6b47106c5b69..741013fef150 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -131,6 +131,9 @@ def verbose : Flag<["--"], "verbose">; def version : Flag<["--", "-"], "version">, HelpText<"Display the version number">; +def warn_common : Flag<["--", "-"], "warn-common">, + HelpText<"Warn about duplicate common symbols">; + def whole_archive : Flag<["--", "-"], "whole-archive">, HelpText<"Force load of all members in a static library">; @@ -178,9 +181,9 @@ def start_group_paren: Flag<["-"], "(">; def fatal_warnings : Flag<["--"], "fatal-warnings">; def no_add_needed : Flag<["--"], "no-add-needed">; def no_fatal_warnings : Flag<["--"], "no-fatal-warnings">; +def no_warn_common : Flag<["--", "-"], "no-warn-common">; def no_warn_mismatch : Flag<["--"], "no-warn-mismatch">; def version_script : Separate<["--"], "version-script">; -def warn_common : Flag<["--"], "warn-common">; def warn_shared_textrel : Flag<["--"], "warn-shared-textrel">; def G : Separate<["-"], "G">; diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 53b9660411b7..78662ee47981 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -159,6 +159,8 @@ static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { } static int compareCommons(DefinedCommon *A, DefinedCommon *B) { + if (Config->WarnCommon) + warning("multiple common of " + A->getName()); A->Alignment = B->Alignment = std::max(A->Alignment, B->Alignment); if (A->Size < B->Size) return -1; @@ -199,6 +201,8 @@ template int SymbolBody::compare(SymbolBody *Other) { if (isCommon() && Other->isCommon()) return compareCommons(cast(this), cast(Other)); + if (Config->WarnCommon) + warning("common " + this->getName() + " is overridden"); return isCommon() ? -1 : 1; } diff --git a/lld/test/ELF/Inputs/warn-common.s b/lld/test/ELF/Inputs/warn-common.s new file mode 100644 index 000000000000..fc4509ba70c7 --- /dev/null +++ b/lld/test/ELF/Inputs/warn-common.s @@ -0,0 +1,2 @@ +.type arr,@object +.comm arr,8,4 diff --git a/lld/test/ELF/Inputs/warn-common2.s b/lld/test/ELF/Inputs/warn-common2.s new file mode 100644 index 000000000000..976c5becb09f --- /dev/null +++ b/lld/test/ELF/Inputs/warn-common2.s @@ -0,0 +1,8 @@ +.type arr,@object +.data +.globl arr +.p2align 2 +arr: + .long 1 + .long 0 + .size arr, 8 diff --git a/lld/test/ELF/warn-common.s b/lld/test/ELF/warn-common.s new file mode 100644 index 000000000000..783a9ab77b56 --- /dev/null +++ b/lld/test/ELF/warn-common.s @@ -0,0 +1,25 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/warn-common.s -o %t2.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/warn-common2.s -o %t3.o + +## Report multiple commons if warn-common is specified +# RUN: ld.lld --warn-common %t1.o %t2.o -o %t.out 2>&1 | FileCheck %s --check-prefix=WARN +# WARN: multiple common of arr + +## no-warn-common is ignored +# RUN: ld.lld --no-warn-common %t1.o %t2.o -o %t.out +# RUN: llvm-readobj %t.out > /dev/null + +## Report if common is overridden +# RUN: ld.lld --warn-common %t1.o %t3.o -o %t.out 2>&1 | FileCheck %s --check-prefix=OVER +# OVER: common arr is overridden + +## Report if common is overridden, but in different order +# RUN: ld.lld --warn-common %t3.o %t1.o -o %t.out 2>&1 | FileCheck %s --check-prefix=OVER + +.globl _start +_start: + +.type arr,@object +.comm arr,4,4