Skip to content

Commit 22086fe

Browse files
rachitmehtparth-07
authored andcommitted
Warn under -Wlinker-script when multiple entry points are specified
Add EntryCmdWarn.test covering rules and warning behaviour. Document entry point precedence and the new warning in linker_script.rst, linker_faq.rst, and diagnostic_reports.rst. Resolves #1538 Signed-off-by: Rachit Mehta <rachmeht@qti.qualcomm.com>
1 parent 2e2bfbd commit 22086fe

8 files changed

Lines changed: 75 additions & 4 deletions

File tree

docs/userguide/documentation/diagnostic_reports.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ General Warning Flags
8585
* - ``-Werror``
8686
- Treats all warnings as errors, halting the link process.
8787
* - ``-Wlinker-script``
88-
- Enables warnings specific to linker script issues, such as malformed directives, deprecated syntax, or unsupported constructs.
88+
- Enables warnings specific to linker script issues, such as malformed directives, deprecated syntax, unsupported constructs or specifying multiple entry points.
8989
* - ``-Wlinker-script-memory``
9090
- Focuses on memory region definitions in linker scripts, such as overlaps or undefined regions.
9191
* - ``-Wwhole-archive``

docs/userguide/documentation/linker_faq.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ Multiple ways to provide entry point to linker
344344
* Initialising the value of linker symbol "start"
345345
* Specifying the start address for the first input section in linker script
346346
(eg: .text : AT(0))
347+
* When multiple -e options are given, the last one takes effect.
347348
348349
How to obtain a non-executable stack
349350
--------------------------------------

docs/userguide/documentation/linker_script.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,8 @@ Syntax :- ``ENTRY(symbol)``
474474
point.
475475
- The entry point is the first instruction that is executed after a
476476
program is loaded.
477+
- When multiple ENTRY() commands appear (in one script or across
478+
several -T scripts), the last one takes effect.
477479
- This command is equivalent to the linker command-line option
478480
:option:`-e`.
479481

include/eld/Diagnostics/DiagLDScript.inc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ DIAG(assert_failed, DiagnosticEngine::Error, "Assertion failed %0")
3939
DIAG(error_printcmd, DiagnosticEngine::Error, "%0: PRINT: %1")
4040
DIAG(linker_script_uses_phdrs_no_sections, DiagnosticEngine::Error,
4141
"Linker Script is using PHDR's but not using SECTIONS command")
42+
DIAG(warn_multiple_entry, DiagnosticEngine::Warning,
43+
"multiple entry points specified; the last one takes effect")
4244
DIAG(cannot_set_at_address, DiagnosticEngine::Error,
4345
"Address for section %0 specified with AT cannot be set, as there is a "
4446
"dependency issue, check the map file for more analysis")

lib/LinkerWrapper/GnuLdDriver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ bool GnuLdDriver::processOptions(llvm::opt::InputArgList &Args) {
719719
T::fatal_internal_errors, T::no_fatal_internal_errors, /*default=*/false);
720720
Config.options().setFatalInternalErrors(enableFatalInternalErrors);
721721

722-
// set up entry point from -e
722+
// set up entry point from -e;
723723
if (llvm::opt::Arg *arg = Args.getLastArg(T::entrypoint)) {
724724
Config.options().setEntry(arg->getValue());
725725
Config.options().setEntryFromCmdLine();

lib/Script/EntryCmd.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ void EntryCmd::dump(llvm::raw_ostream &Outs) const {
3333

3434
eld::Expected<void> EntryCmd::activate(Module &CurModule) {
3535
GeneralOptions &Options = CurModule.getConfig().options();
36-
if (!EntrySymbol.empty() && !Options.isEntryFromCmdLine())
37-
Options.setEntry(EntrySymbol);
36+
if (!EntrySymbol.empty()) {
37+
if (Options.hasEntry() && CurModule.getConfig().showLinkerScriptWarnings())
38+
CurModule.getConfig().raise(Diag::warn_multiple_entry);
39+
if (!Options.isEntryFromCmdLine())
40+
Options.setEntry(EntrySymbol);
41+
}
3842
return eld::Expected<void>();
3943
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#---EntryCmdWarn.test-------------------- Executable,LS ----------------------#
2+
#BEGIN_COMMENT
3+
# Tests that -Wlinker-script emits a warning when multiple entry points are
4+
# specified, and that the warning is suppressed without -Wlinker-script.
5+
#
6+
# Warning cases:
7+
# Case 1: Two ENTRY() in one script -- warns once with -Wlinker-script.
8+
# Case 2: -e combined with a single script ENTRY() -- warns with -Wlinker-script.
9+
# Case 3: Multiple -e on command line -- warns once with -Wlinker-script.
10+
# Case 4: Cross-script two ENTRY() -- warns with -Wlinker-script.
11+
# Case 5: Single ENTRY(), no -e -- no warning even with -Wlinker-script.
12+
# Case 6: Two ENTRY() without -Wlinker-script -- no warning.
13+
# Case 7: Three ENTRY() in one script -- warns once per overriding ENTRY().
14+
#END_COMMENT
15+
#START_TEST
16+
RUN: %clang %clangopts -c %p/Inputs/1.c -o %t1.o -ffunction-sections
17+
18+
# Case 1: Two ENTRY() in one script -- exactly one warning.
19+
RUN: %link %linkopts %t1.o -T %p/Inputs/two_entries.t -Wlinker-script -o %t.warn1.out 2>&1 | \
20+
RUN: %filecheck %s --check-prefix=WARN1
21+
#WARN1-COUNT-1: Warning: multiple entry points specified; the last one takes effect
22+
#WARN1-NOT: Warning: multiple entry points specified; the last one takes effect
23+
24+
# Case 2: -e combined with a single script ENTRY() -- warn.
25+
RUN: %link %linkopts %t1.o -T %p/Inputs/script.t -e bar -Wlinker-script -o %t.warn2.out 2>&1 | \
26+
RUN: %filecheck %s --check-prefix=WARN
27+
#WARN: Warning: multiple entry points specified; the last one takes effect
28+
29+
# Case 3: Multiple -e on command line -- exactly one warning.
30+
RUN: %link %linkopts %t1.o -T %p/Inputs/script.t -e foo -e bar -Wlinker-script -o %t.warn3.out 2>&1 | \
31+
RUN: %filecheck %s --check-prefix=WARN3
32+
#WARN3-COUNT-1: Warning: multiple entry points specified; the last one takes effect
33+
#WARN3-NOT: Warning: multiple entry points specified; the last one takes effect
34+
35+
# Case 4: Two ENTRY() across two scripts -- warn.
36+
RUN: %link %linkopts %t1.o -T %p/Inputs/entry_bar.t -T %p/Inputs/entry_foo.t -Wlinker-script -o %t.warn4.out 2>&1 | \
37+
RUN: %filecheck %s --check-prefix=WARN
38+
39+
# Case 5: Single ENTRY(), no -e -- no warning even with -Wlinker-script.
40+
RUN: %link %linkopts %t1.o -T %p/Inputs/script.t -Wlinker-script -o %t.nowarn1.out 2>&1 | \
41+
RUN: %filecheck %s --allow-empty --check-prefix=NOWARN
42+
#NOWARN-NOT: multiple entry points
43+
44+
# Case 6: Two ENTRY() without -Wlinker-script -- no warning.
45+
RUN: %link %linkopts %t1.o -T %p/Inputs/two_entries.t -o %t.nowarn2.out 2>&1 | \
46+
RUN: %filecheck %s --allow-empty --check-prefix=NOWARN
47+
48+
# Case 7: Three ENTRY() in one script -- one warning per overriding ENTRY() (two total).
49+
RUN: %link %linkopts %t1.o -T %p/Inputs/three_entries.t -Wlinker-script -o %t.warn7.out 2>&1 | \
50+
RUN: %filecheck %s --check-prefix=WARN7
51+
#WARN7-COUNT-2: Warning: multiple entry points specified; the last one takes effect
52+
#WARN7-NOT: Warning: multiple entry points specified; the last one takes effect
53+
#END_TEST
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
ENTRY(bar)
2+
ENTRY(foo)
3+
ENTRY(bar)
4+
SECTIONS {
5+
. = 0x1000;
6+
.bar : { *(.text.bar) }
7+
. = 0x2000;
8+
.foo : { *(.text.foo) }
9+
}

0 commit comments

Comments
 (0)