Add a "-O 0" option to the linker for a faster, but less effective link.

This commit is contained in:
Nick Clifton 2026-04-13 09:32:09 +01:00
parent 3a4ee1b517
commit 4fe7dd9a10
8 changed files with 69 additions and 10 deletions

View file

@ -551,10 +551,15 @@ struct bfd_link_info
an executable stack. */
unsigned int default_execstack : 1;
/* TRUE if we want to produced optimized output files. This might
/* TRUE if we want to produce optimized output files. This might
need much more time and therefore must be explicitly selected. */
unsigned int optimize: 1;
/* TRUE if we want to skip optional steps during linking. This can
include section merging for example. This is effectively the opposite
of the 'optimize' field, and both should not be TRUE at the same time. */
unsigned int skip_optional: 1;
/* TRUE if user should be informed of removed unreferenced sections. */
unsigned int print_gc_sections: 1;

View file

@ -1,5 +1,10 @@
-*- text -*-
* Add a linker optimization level of zero. Using "-O 0" on the linker command
line will stop it from combining the contents of mergeable sections. This
can significantly speed up the link process at the cost of producing larger
binaries.
Changes in 2.47:
* Add linker support for --start-lib/--end-lib options and LIB linker script

View file

@ -1043,6 +1043,16 @@ the linker may make more use of this option. Also currently there is
no difference in the linker's behaviour for different non-zero values
of this option. Again this may change with future releases.
If @var{level} is zero or the string @samp{fast} then @command{ld}
instead skips operations that are optional, resulting in a faster link
but producing slower, larger binaries. Currently the only operation
that is skipped is the combining of mergeable sections, but this may
change in the future.
If @var{level} is the string @samp{default} or just the @samp{-}
character then the linker's default behaviour of neither optimizing
nor skipping operations is selected.
@kindex -plugin @var{name}
@item -plugin @var{name}
Involve a plugin in the linking process. The @var{name} parameter is

View file

@ -8820,16 +8820,19 @@ lang_process (void)
{
asection *found;
ld_start_phase (PHASE_MERGE);
if (! link_info.skip_optional)
{
ld_start_phase (PHASE_MERGE);
/* Merge SEC_MERGE sections. This has to be done after GC of
sections, so that GCed sections are not merged, but before
assigning dynamic symbols, since removing whole input sections
is hard then. */
if (!bfd_merge_sections (link_info.output_bfd, &link_info))
fatal (_("%P: bfd_merge_sections failed: %E\n"));
/* Merge SEC_MERGE sections. This has to be done after GC of
sections, so that GCed sections are not merged, but before
assigning dynamic symbols, since removing whole input sections
is hard then. */
if (!bfd_merge_sections (link_info.output_bfd, &link_info))
fatal (_("%P: bfd_merge_sections failed: %E\n"));
ld_stop_phase (PHASE_MERGE);
ld_stop_phase (PHASE_MERGE);
}
/* Look for a text section and set the readonly attribute in it. */
found = bfd_get_section_by_name (link_info.output_bfd, ".text");

View file

@ -177,7 +177,7 @@ static const struct ld_option ld_options[] =
{ {"output", required_argument, NULL, 'o'},
'o', N_("FILE"), N_("Set output file name"), EXACTLY_TWO_DASHES },
{ {NULL, required_argument, NULL, '\0'},
'O', NULL, N_("Optimize output file"), ONE_DASH },
'O', N_("LEVEL"), N_("Optimize output file"), ONE_DASH },
{ {"out-implib", required_argument, NULL, OPTION_OUT_IMPLIB},
'\0', N_("FILE"), N_("Generate import library"), TWO_DASHES },
{ {"plugin", required_argument, NULL, OPTION_PLUGIN},
@ -1211,6 +1211,24 @@ parse_args (unsigned argc, char **argv)
/* Enable optimizations of output files. */
link_info.optimize = strtoul (optarg, NULL, 0) != 0;
if (link_info.optimize == 0)
{
/* "-O -" or "-O default" means restore the linker's default behaviour. */
if ((optarg[0] == '-' && optarg[1] == 0) || strcmp (optarg, "default") == 0)
{
link_info.optimize = link_info.skip_optional = 0;
}
/* "-O 0" or "-O fast" means disable optimizations and skip optional features. */
else if ((optarg[0] == '0' && optarg[1] == 0) || strcmp (optarg, "fast") == 0)
{
link_info.optimize = 0;
link_info.skip_optional = 1;
}
else
fatal (_("%P: -O requires a numerical argument or '-' or 'fast' or 'default'"));
}
else
link_info.skip_optional = 0;
break;
case 'o':
lang_add_output (optarg, 0);

View file

@ -0,0 +1,4 @@
.section .rodata.str,"aMS","progbits",1
.global .merge1
.merge1:
.asciz "abc"

View file

@ -0,0 +1,4 @@
.section .rodata.str,"aMS","progbits",1
.global .merge2
.merge2:
.asciz "abc"

View file

@ -0,0 +1,10 @@
# Checks to see that linking with "-O 0" does not merge strings.
# The various other -O options are there just to make sure that the parser handles them.
#source: merge5.a.s
#source: merge5.b.s
#ld: -T merge.ld -O 2 -O - -O 99 -O default -O fast -O 0
#nm: -s
0+1100 R .merge1
0+1104 R .merge2
#pass