ld: Extend options for altering orphan handling behaviour.

Replace the options --warn-orphan and --no-warn-orphan with a single
option --orphan-handling=MODE, where mode can be place, warn, error, and
discard.

Mode 'place' is the default, and is the current behaviour, placing the
orphan section into a suitable output section.

Mode 'warn' is the same as '--warn-orphan'.  The orphan is also placed
using the same algorithm as for 'place'.

Mode 'error' is the same as '--warn-orphan' and '--fatal-warnings'.

Mode 'discard' assigns all output sections to the /DISCARD/ section.

ld/ChangeLog:

	* ld.h (enum orphan_handling_enum): New.
	(ld_config_type): Remove warn_orphan, add orphan_handling.
	* ldemul.c (ldemul_place_orphan): Remove warning about orphan
	sections.
	* ldlang.c (ldlang_place_orphan): New function.
	(lang_place_orphans): Call ldlang_place_orphan.
	* ldlex.h (enum option_values): Remove OPTION_WARN_ORPHAN and
	OPTION_NO_WARN_ORPHAN, add OPTION_ORPHAN_HANDLING.
	* lexsup.c (ld_options): Remove 'warn-orphan' and
	'no-warn-orphan', add 'orphan-handling'.
	(parse_args): Remove handling for OPTION_WARN_ORPHAN and
	OPTION_NO_WARN_ORPHAN, add handling for OPTION_ORPHAN_HANDLING.
	* NEWS: Replace text about --warn-orphan with --orphan-handling.
	* ld.texinfo (Options): Remove --warn-orphan entry and add
	entry on --orphan-handling.
	(Orphan Sections): Add reference to relevant command line options.

ld/testsuite/ChangeLog:

	* ld-elf/elf.exp: Switch to rely on run_dump_test.
	* ld-elf/orphan-5.l: Update expected output.
	* ld-elf/orphan-5.d: New file.
	* ld-elf/orphan-6.d: New file.
	* ld-elf/orphan-6.l: New file.
	* ld-elf/orphan-7.d: New file.
	* ld-elf/orphan-7.map: New file.
	* ld-elf/orphan-8.d: New file.
	* ld-elf/orphan-8.map: New file.
This commit is contained in:
Andrew Burgess 2015-07-28 19:20:37 +01:00
parent e65b52456b
commit c005eb9e34
18 changed files with 195 additions and 65 deletions

View file

@ -1,3 +1,22 @@
2015-07-28 Andrew Burgess <andrew.burgess@embecosm.com>
* ld.h (enum orphan_handling_enum): New.
(ld_config_type): Remove warn_orphan, add orphan_handling.
* ldemul.c (ldemul_place_orphan): Remove warning about orphan
sections.
* ldlang.c (ldlang_place_orphan): New function.
(lang_place_orphans): Call ldlang_place_orphan.
* ldlex.h (enum option_values): Remove OPTION_WARN_ORPHAN and
OPTION_NO_WARN_ORPHAN, add OPTION_ORPHAN_HANDLING.
* lexsup.c (ld_options): Remove 'warn-orphan' and
'no-warn-orphan', add 'orphan-handling'.
(parse_args): Remove handling for OPTION_WARN_ORPHAN and
OPTION_NO_WARN_ORPHAN, add handling for OPTION_ORPHAN_HANDLING.
* NEWS: Replace text about --warn-orphan with --orphan-handling.
* ld.texinfo (Options): Remove --warn-orphan entry and add
entry on --orphan-handling.
(Orphan Sections): Add reference to relevant command line options.
2015-09-03 Nick Clifton <nickc@redhat.com> 2015-09-03 Nick Clifton <nickc@redhat.com>
* ld.texinfo (--build-id): Fix typo. The COFF/PE build-id section * ld.texinfo (--build-id): Fix typo. The COFF/PE build-id section

View file

@ -6,7 +6,11 @@
* New command line option for ELF targets to compress DWARF debug * New command line option for ELF targets to compress DWARF debug
sections, --compress-debug-sections=[none|zlib|zlib-gnu|zlib-gabi]. sections, --compress-debug-sections=[none|zlib|zlib-gnu|zlib-gabi].
* Add --warn-orphan option to report orphan sections. * New command line option, --orphan-handling=[place|warn|error|discard], to
adjust how orphan sections are handled. The default is 'place' which gives
the current behaviour, 'warn' and 'error' issue a warning or error
respectively when orphan sections are found, and 'discard' will discard all
orphan sections.
* Add support for LLVM plugin. * Add support for LLVM plugin.

23
ld/ld.h
View file

@ -207,6 +207,25 @@ extern args_type command_line;
typedef int token_code_type; typedef int token_code_type;
/* Different ways we can handle orphan sections. */
enum orphan_handling_enum {
/* The classic strategy, find a suitable section to place the orphan
into. */
orphan_handling_place = 0,
/* Discard any orphan sections as though they were assign to the section
/DISCARD/. */
orphan_handling_discard,
/* Find somewhere to place the orphan section, as with
ORPHAN_HANDLING_PLACE, but also issue a warning. */
orphan_handling_warn,
/* Issue a fatal error if any orphan sections are found. */
orphan_handling_error,
};
typedef struct { typedef struct {
bfd_boolean magic_demand_paged; bfd_boolean magic_demand_paged;
bfd_boolean make_executable; bfd_boolean make_executable;
@ -229,8 +248,8 @@ typedef struct {
/* If TRUE, only warn once about a particular undefined symbol. */ /* If TRUE, only warn once about a particular undefined symbol. */
bfd_boolean warn_once; bfd_boolean warn_once;
/* If TRUE, issue warning messages when orphan sections are encountered. */ /* How should we deal with orphan sections. */
bfd_boolean warn_orphan; enum orphan_handling_enum orphan_handling;
/* If TRUE, warn if multiple global-pointers are needed (Alpha /* If TRUE, warn if multiple global-pointers are needed (Alpha
only). */ only). */

View file

@ -1001,6 +1001,35 @@ with @samp{-Ur}; once the constructor table has been built, it cannot
be added to. Use @samp{-Ur} only for the last partial link, and be added to. Use @samp{-Ur} only for the last partial link, and
@samp{-r} for the others. @samp{-r} for the others.
@kindex --orphan-handling=@var{MODE}
@cindex orphan sections
@cindex sections, orphan
@item --orphan-handling=@var{MODE}
Control how orphan sections are handled. An orphan section is one not
specifically mentioned in a linker script. @xref{Orphan Sections}.
@var{MODE} can have any of the following values:
@table @code
@item place
Orphan sections are placed into a suitable output section following
the strategy described in @ref{Orphan Sections}. The option
@samp{--unique} also effects how sections are placed.
@item discard
All orphan sections are discarded, by placing them in the
@samp{/DISCARD/} section (@pxref{Output Section Discarding}).
@item warn
The linker will place the orphan section as for @code{place} and also
issue a warning.
@item error
The linker will exit with an error if any orphan section is found.
@end table
The default if @samp{--orphan-handling} is not given is @code{place}.
@kindex --unique[=@var{SECTION}] @kindex --unique[=@var{SECTION}]
@item --unique[=@var{SECTION}] @item --unique[=@var{SECTION}]
Creates a separate output section for every input section matching Creates a separate output section for every input section matching
@ -2105,17 +2134,6 @@ option causes a warning to be issued whenever this case occurs.
Only warn once for each undefined symbol, rather than once per module Only warn once for each undefined symbol, rather than once per module
which refers to it. which refers to it.
@kindex --warn-orphan
@kindex --no-warn-orphan
@cindex warnings, on orphan sections
@cindex orphan sections, warnings on
@item --warn-orphan
The @option{--warn-orphan} option tells the linker to generate a
warning message whenever it has to place an orphan section into the
output file. @xref{Orphan Sections}. The @option{--no-warn-orphan}
option restores the default behaviour of just silently placing these
sections.
@kindex --warn-section-align @kindex --warn-section-align
@cindex warnings, on section alignment @cindex warnings, on section alignment
@cindex section alignment, warnings on @cindex section alignment, warnings on
@ -5569,6 +5587,10 @@ at the end of the file.
For ELF targets, the attribute of the section includes section type as For ELF targets, the attribute of the section includes section type as
well as section flag. well as section flag.
The command line options @samp{--orphan-handling} and @samp{--unique}
(@pxref{Options,,Command Line Options}) can be used to control which
output sections an orphan is placed in.
If an orphaned section's name is representable as a C identifier then If an orphaned section's name is representable as a C identifier then
the linker will automatically @pxref{PROVIDE} two symbols: the linker will automatically @pxref{PROVIDE} two symbols:
__start_SECNAME and __stop_SECNAME, where SECNAME is the name of the __start_SECNAME and __stop_SECNAME, where SECNAME is the name of the

View file

@ -120,10 +120,6 @@ ldemul_open_dynamic_archive (const char *arch, search_dirs_type *search,
lang_output_section_statement_type * lang_output_section_statement_type *
ldemul_place_orphan (asection *s, const char *name, int constraint) ldemul_place_orphan (asection *s, const char *name, int constraint)
{ {
if (config.warn_orphan)
einfo (_("%P: Warning: input section '%s' from file '%B' is not mentioned in linker script\n"),
name, s->owner);
if (ld_emulation->place_orphan) if (ld_emulation->place_orphan)
return (*ld_emulation->place_orphan) (s, name, constraint); return (*ld_emulation->place_orphan) (s, name, constraint);
return NULL; return NULL;

View file

@ -6102,6 +6102,55 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info)
return TRUE; return TRUE;
} }
/* Handle a single orphan section S, placing the orphan into an appropriate
output section. The effects of the --orphan-handling command line
option are handled here. */
static void
ldlang_place_orphan (asection *s)
{
if (config.orphan_handling == orphan_handling_discard)
{
lang_output_section_statement_type *os;
os = lang_output_section_statement_lookup (DISCARD_SECTION_NAME, 0,
TRUE);
if (os->addr_tree == NULL
&& (bfd_link_relocatable (&link_info)
|| (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
os->addr_tree = exp_intop (0);
lang_add_section (&os->children, s, NULL, os);
}
else
{
lang_output_section_statement_type *os;
const char *name = s->name;
int constraint = 0;
if (config.orphan_handling == orphan_handling_error)
einfo ("%X%P: error: unplaced orphan section `%A' from `%B'.\n",
s, s->owner);
if (config.unique_orphan_sections || unique_section_p (s, NULL))
constraint = SPECIAL;
os = ldemul_place_orphan (s, name, constraint);
if (os == NULL)
{
os = lang_output_section_statement_lookup (name, constraint, TRUE);
if (os->addr_tree == NULL
&& (bfd_link_relocatable (&link_info)
|| (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
os->addr_tree = exp_intop (0);
lang_add_section (&os->children, s, NULL, os);
}
if (config.orphan_handling == orphan_handling_warn)
einfo ("%P: warning: orphan section `%A' from `%B' being "
"placed in section `%s'.\n",
s, s->owner, os->name);
}
}
/* Run through the input files and ensure that every input section has /* Run through the input files and ensure that every input section has
somewhere to go. If one is found without a destination then create somewhere to go. If one is found without a destination then create
an input request and place it into the statement tree. */ an input request and place it into the statement tree. */
@ -6141,27 +6190,7 @@ lang_place_orphans (void)
} }
} }
else else
{ ldlang_place_orphan (s);
const char *name = s->name;
int constraint = 0;
if (config.unique_orphan_sections
|| unique_section_p (s, NULL))
constraint = SPECIAL;
if (!ldemul_place_orphan (s, name, constraint))
{
lang_output_section_statement_type *os;
os = lang_output_section_statement_lookup (name,
constraint,
TRUE);
if (os->addr_tree == NULL
&& (bfd_link_relocatable (&link_info)
|| (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
os->addr_tree = exp_intop (0);
lang_add_section (&os->children, s, NULL, os);
}
}
} }
} }
} }

View file

@ -85,8 +85,6 @@ enum option_values
OPTION_NO_WARN_FATAL, OPTION_NO_WARN_FATAL,
OPTION_WARN_MULTIPLE_GP, OPTION_WARN_MULTIPLE_GP,
OPTION_WARN_ONCE, OPTION_WARN_ONCE,
OPTION_WARN_ORPHAN,
OPTION_NO_WARN_ORPHAN,
OPTION_WARN_SECTION_ALIGN, OPTION_WARN_SECTION_ALIGN,
OPTION_SPLIT_BY_RELOC, OPTION_SPLIT_BY_RELOC,
OPTION_SPLIT_BY_FILE , OPTION_SPLIT_BY_FILE ,
@ -144,6 +142,7 @@ enum option_values
OPTION_POP_STATE, OPTION_POP_STATE,
OPTION_PRINT_MEMORY_USAGE, OPTION_PRINT_MEMORY_USAGE,
OPTION_REQUIRE_DEFINED_SYMBOL, OPTION_REQUIRE_DEFINED_SYMBOL,
OPTION_ORPHAN_HANDLING,
}; };
/* The initial parser states. */ /* The initial parser states. */

View file

@ -492,10 +492,6 @@ static const struct ld_option ld_options[] =
'\0', NULL, N_("Warn if the multiple GP values are used"), TWO_DASHES }, '\0', NULL, N_("Warn if the multiple GP values are used"), TWO_DASHES },
{ {"warn-once", no_argument, NULL, OPTION_WARN_ONCE}, { {"warn-once", no_argument, NULL, OPTION_WARN_ONCE},
'\0', NULL, N_("Warn only once per undefined symbol"), TWO_DASHES }, '\0', NULL, N_("Warn only once per undefined symbol"), TWO_DASHES },
{ {"warn-orphan", no_argument, NULL, OPTION_WARN_ORPHAN},
'\0', NULL, N_("Warn if any orphan sections are encountered"), TWO_DASHES },
{ {"no-warn-orphan", no_argument, NULL, OPTION_NO_WARN_ORPHAN},
'\0', NULL, N_("Do not warn if orphan sections are encountered (default)"), TWO_DASHES },
{ {"warn-section-align", no_argument, NULL, OPTION_WARN_SECTION_ALIGN}, { {"warn-section-align", no_argument, NULL, OPTION_WARN_SECTION_ALIGN},
'\0', NULL, N_("Warn if start of section changes due to alignment"), '\0', NULL, N_("Warn if start of section changes due to alignment"),
TWO_DASHES }, TWO_DASHES },
@ -528,6 +524,9 @@ static const struct ld_option ld_options[] =
TWO_DASHES }, TWO_DASHES },
{ {"print-memory-usage", no_argument, NULL, OPTION_PRINT_MEMORY_USAGE}, { {"print-memory-usage", no_argument, NULL, OPTION_PRINT_MEMORY_USAGE},
'\0', NULL, N_("Report target memory usage"), TWO_DASHES }, '\0', NULL, N_("Report target memory usage"), TWO_DASHES },
{ {"orphan-handling", required_argument, NULL, OPTION_ORPHAN_HANDLING},
'\0', N_("=MODE"), N_("Control how orphan sections are handled."),
TWO_DASHES },
}; };
#define OPTION_COUNT ARRAY_SIZE (ld_options) #define OPTION_COUNT ARRAY_SIZE (ld_options)
@ -1375,12 +1374,6 @@ parse_args (unsigned argc, char **argv)
case OPTION_WARN_ONCE: case OPTION_WARN_ONCE:
config.warn_once = TRUE; config.warn_once = TRUE;
break; break;
case OPTION_WARN_ORPHAN:
config.warn_orphan = TRUE;
break;
case OPTION_NO_WARN_ORPHAN:
config.warn_orphan = FALSE;
break;
case OPTION_WARN_SECTION_ALIGN: case OPTION_WARN_SECTION_ALIGN:
config.warn_section_align = TRUE; config.warn_section_align = TRUE;
break; break;
@ -1515,6 +1508,20 @@ parse_args (unsigned argc, char **argv)
case OPTION_PRINT_MEMORY_USAGE: case OPTION_PRINT_MEMORY_USAGE:
command_line.print_memory_usage = TRUE; command_line.print_memory_usage = TRUE;
break; break;
case OPTION_ORPHAN_HANDLING:
if (strcasecmp (optarg, "place") == 0)
config.orphan_handling = orphan_handling_place;
else if (strcasecmp (optarg, "warn") == 0)
config.orphan_handling = orphan_handling_warn;
else if (strcasecmp (optarg, "error") == 0)
config.orphan_handling = orphan_handling_error;
else if (strcasecmp (optarg, "discard") == 0)
config.orphan_handling = orphan_handling_discard;
else
einfo (_("%P%F: invalid argument to option"
" \"--orphan-handling\"\n"));
break;
} }
} }

View file

@ -1,3 +1,15 @@
2015-07-28 Andrew Burgess <andrew.burgess@embecosm.com>
* ld-elf/elf.exp: Switch to rely on run_dump_test.
* ld-elf/orphan-5.l: Update expected output.
* ld-elf/orphan-5.d: New file.
* ld-elf/orphan-6.d: New file.
* ld-elf/orphan-6.l: New file.
* ld-elf/orphan-7.d: New file.
* ld-elf/orphan-7.map: New file.
* ld-elf/orphan-8.d: New file.
* ld-elf/orphan-8.map: New file.
2015-09-03 H.J. Lu <hongjiu.lu@intel.com> 2015-09-03 H.J. Lu <hongjiu.lu@intel.com>
* ld-ifunc/ifunc-21-i386.s: Add tests for call, jmp, add, test. * ld-ifunc/ifunc-21-i386.s: Add tests for call, jmp, add, test.

View file

@ -124,18 +124,6 @@ foreach t $test_list {
run_dump_test [file rootname $t] run_dump_test [file rootname $t]
} }
# Check that the --warn-orphan option works correctly.
run_ld_link_tests {
{"Report orphan sections"
"--script orphan.ld --warn-orphan"
""
""
{orphan.s}
{ { ld "orphan-5.l" } }
"orphan"
}
}
if { [istarget *-*-linux*] if { [istarget *-*-linux*]
|| [istarget *-*-nacl*] || [istarget *-*-nacl*]
|| [istarget *-*-gnu*] } { || [istarget *-*-gnu*] } {

View file

@ -0,0 +1,4 @@
#name: Report warning for orphan sections
#ld: --script orphan.ld --orphan-handling=warn
#source: orphan.s
#warning_output: orphan-5.l

View file

@ -1,5 +1,5 @@
#... #...
.*Warning: input section '.notbad' from file 'tmpdir/orphan.o' is not mentioned in linker script .*warning: orphan section `\.notbad' from `tmpdir/orphan\.o' being placed in section `\.notbad'\.
#... #...
.*Warning: input section '.note.bar' from file 'tmpdir/orphan.o' is not mentioned in linker script .*warning: orphan section `\.note\.bar' from `tmpdir/orphan\.o' being placed in section `\.note\.bar'\.
#... #...

View file

@ -0,0 +1,4 @@
#name: Report error for orphan sections
#ld: --script orphan.ld --orphan-handling=error
#source: orphan.s
#error_output: orphan-6.l

View file

@ -0,0 +1,5 @@
#...
.*error: unplaced orphan section `\.notbad' from `tmpdir/orphan\.o'\.
#...
.*error: unplaced orphan section `\.note\.bar' from `tmpdir/orphan\.o'\.
#...

View file

@ -0,0 +1,4 @@
#name: Discard orphan sections
#ld: --script orphan.ld --orphan-handling=discard
#source: orphan.s
#map: orphan-7.map

View file

@ -0,0 +1,7 @@
Discarded input sections
\.notbad 0x0+ 0x4 tmpdir/.*\.o
\.note\.bar 0x0+ 0x4 tmpdir/.*\.o
#...

View file

@ -0,0 +1,4 @@
#name: Place orphan sections
#ld: --script orphan.ld --orphan-handling=place
#source: orphan.s
#map: orphan-8.map

View file

@ -0,0 +1,7 @@
#...
.notbad 0x0000000000000004 0x4
.notbad 0x0000000000000004 0x4 tmpdir/dump0.o
#...
.note.bar 0x0000000000000010 0x4
.note.bar 0x0000000000000010 0x4 tmpdir/dump0.o
#...