ld/ELF: Add --image-base command line option to the ELF linker

LLD has dropped the option -Ttext-segment for specifying image base
addresses, instead forcing the use of the --image-base option for both
ELF and PE targets. As it stands, GNU LD and LLVM LLD are incompatible,
having two different options for the same functionality.

This patch enables the use of --image-base on ELF targets, advancing
consistency and compatibility.

See: https://reviews.llvm.org/D70468
     https://maskray.me/blog/2020-11-15-explain-gnu-linker-options#address-related
     https://sourceware.org/bugzilla/show_bug.cgi?id=25207

Moreover, a new test has been added to ensure -z separate-code behaviour
when used with -Ttext-segment stays the same. When this combination is
used, -Ttext-segment sets the address of the first segment (R), not the
text segment (RX), and like with -z noseparate-code, no segments lesser
than the specified address are created. If this behaviour was to change,
the first (R) segment of the ELF file would begin in a lesser address
than the specified text (RX) segment, breaking traditional use of this
option for specifying image base address.
This commit is contained in:
Hakan Candar 2024-10-28 11:01:59 +00:00 committed by Alan Modra
parent 80ac478511
commit f4e363cae2
9 changed files with 47 additions and 16 deletions

View File

@ -2,6 +2,9 @@
Changes in 2.44:
* Add --image-base=<ADDR> option to the ELF linker to behave the same
as -Ttext-segment for compatibility with LLD.
* Add a "--build-id=xx" option, if built with the xxhash library. This
produces a 128-bit hash, 2-4x faster than md5 or sha1.

View File

@ -82,7 +82,6 @@ gld${EMULATION_NAME}_add_options
{"dll", no_argument, NULL, OPTION_DLL},
{"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT},
{"heap", required_argument, NULL, OPTION_HEAP},
{"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
{"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION},
{"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION},
{"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION},

View File

@ -251,7 +251,6 @@ gld${EMULATION_NAME}_add_options
{"dll", no_argument, NULL, OPTION_DLL},
{"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT},
{"heap", required_argument, NULL, OPTION_HEAP},
{"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
{"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION},
{"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION},
{"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION},

View File

@ -261,7 +261,6 @@ gld${EMULATION_NAME}_add_options
{"dll", no_argument, NULL, OPTION_DLL},
{"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT},
{"heap", required_argument, NULL, OPTION_HEAP},
{"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
{"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION},
{"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION},
{"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION},

View File

@ -2732,6 +2732,19 @@ for compatibility with other linkers, you may omit the leading
should be no white space between @var{sectionname}, the equals
sign (``@key{=}''), and @var{org}.
@kindex --image-base=@var{org}
@item --image-base=@var{org}
@cindex image base address, cmd line
When using ELF, same as @option{-Ttext-segment}, with both options effectively
setting the base address of the ELF executable.
When using PE, use @var{value} as the base address of your program or dll.
This is the lowest memory location that will be used when your program or
dll is loaded. To reduce the need to relocate and improve performance of
your dlls, each should have a unique base address and not overlap any
other dlls. The default is 0x400000 for executables, and 0x10000000
for dlls.
@kindex -Tbss=@var{org}
@kindex -Tdata=@var{org}
@kindex -Ttext=@var{org}
@ -2746,7 +2759,7 @@ Same as @option{--section-start}, with @code{.bss}, @code{.data} or
@item -Ttext-segment=@var{org}
@cindex text segment origin, cmd line
When creating an ELF executable, it will set the address of the first
byte of the text segment. Note that when @option{-pie} is used with
byte of the first segment. Note that when @option{-pie} is used with
@option{-Ttext-segment=@var{org}}, the output executable is marked
ET_EXEC so that the address of the first byte of the text segment will
be guaranteed to be @var{org} at run time.
@ -3392,17 +3405,6 @@ to be used as heap for this program. The default is 1MB reserved, 4K
committed.
[This option is specific to the i386 PE targeted port of the linker]
@cindex image base
@kindex --image-base
@item --image-base @var{value}
Use @var{value} as the base address of your program or dll. This is
the lowest memory location that will be used when your program or dll
is loaded. To reduce the need to relocate and improve performance of
your dlls, each should have a unique base address and not overlap any
other dlls. The default is 0x400000 for executables, and 0x10000000
for dlls.
[This option is specific to the i386 PE targeted port of the linker]
@kindex --kill-at
@item --kill-at
If given, the stdcall suffixes (@@@var{nn}) will be stripped from

View File

@ -67,6 +67,7 @@ enum option_values
OPTION_SYMBOLIC,
OPTION_SYMBOLIC_FUNCTIONS,
OPTION_TASK_LINK,
OPTION_IMAGE_BASE,
OPTION_TBSS,
OPTION_TDATA,
OPTION_TTEXT,
@ -325,7 +326,6 @@ enum option_values
/* Used by emultempl/pe.em, emultempl/pep.em and emultempl/beos.em. */
OPTION_DLL,
OPTION_FILE_ALIGNMENT,
OPTION_IMAGE_BASE,
OPTION_MAJOR_IMAGE_VERSION,
OPTION_MAJOR_OS_VERSION,
OPTION_MAJOR_SUBSYSTEM_VERSION,

View File

@ -510,6 +510,8 @@ static const struct ld_option ld_options[] =
{ {"section-start", required_argument, NULL, OPTION_SECTION_START},
'\0', N_("SECTION=ADDRESS"), N_("Set address of named section"),
TWO_DASHES },
{ {"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
'\0', N_("ADDRESS"), N_("Set image base address"), TWO_DASHES },
{ {"Tbss", required_argument, NULL, OPTION_TBSS},
'\0', N_("ADDRESS"), N_("Set address of .bss section"), ONE_DASH },
{ {"Tdata", required_argument, NULL, OPTION_TDATA},
@ -1477,6 +1479,9 @@ parse_args (unsigned argc, char **argv)
case OPTION_TTEXT:
set_segment_start (".text", optarg);
break;
case OPTION_IMAGE_BASE:
/* Unless PE, --image-base and -Ttext-segment behavior is the same
PE-specific functionality is implemented in emultempl/{pe, pep, beos}.em */
case OPTION_TTEXT_SEGMENT:
set_segment_start (".text-segment", optarg);
break;

View File

@ -0,0 +1,11 @@
#source: pr25207.s
#ld: -z separate-code -Ttext-segment=0x120000 -z max-page-size=0x10000
#readelf: -l --wide
#target: *-*-linux* *-*-gnu* arm*-*-uclinuxfdpiceabi
# changing -Ttext-segment behaviour will break --image-base (pr25207)
# -Ttext-segment=<ADDR> should set the first segment address,
# not necessarily the first executable segment.
#...
LOAD +0x0+ 0x0*120000 0x0*120000 0x[0-9a-f]+ 0x[0-9a-f]+ R .*
#pass

View File

@ -0,0 +1,13 @@
.section .text, "ax"
.globl main
.globl start
.globl _start
.globl __start
main:
start:
_start:
__start:
.byte 0
.section .rodata
.byte 0