From 4dc2fb123dcfe9a97ad6f3a1135053b74efd0bc9 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 19 Nov 2019 14:16:04 -0800 Subject: [PATCH] [ELF] Error if -Ttext-segment is specified In GNU ld, -Ttext sets the address of the .text section and -Ttext-segment sets the address of the text segment (RX). gold only supports the -Ttext-segment semantic and treats -Ttext as an alias for -Ttext-segment. lld only supports the -Ttext semantic and treats -Ttext-segment as an alias for -Ttext. The text segment will be assigned to an address less than the specified -Ttext-segment value. This patch drops the -Ttext-segment alias. The text segment is traditionally the first segment. Users who specify -Ttext-segment may actually want to specify --image-base, the lld way to express this. Unfortunately currently this is supported by GNU ld's COFF port but not by its ELF port. gold does not support this option. With -z separate-code, the behavior of GNU ld -Ttext-segment is weird (see https://sourceware.org/bugzilla/show_bug.cgi?id=25207) rL289827 introduced the alias for linking qemu's non-pie user mode binaries. As explained previously, this actually assigns the text segment to an address less than 0x60000000. I feel that a better fix is on the qemu side: https://lists.nongnu.org/archive/html/qemu-devel/2019-11/msg02480.html Reviewed By: grimar, ruiu Differential Revision: https://reviews.llvm.org/D70468 --- lld/ELF/Driver.cpp | 8 ++++++++ lld/ELF/Options.td | 5 +++-- lld/test/ELF/sectionstart.s | 6 ------ lld/test/ELF/ttext-segment.s | 8 ++++++++ 4 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 lld/test/ELF/ttext-segment.s diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index f7ce735..ca1a9ed 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1012,6 +1012,14 @@ static void readConfigs(opt::InputArgList &args) { if (config->splitStackAdjustSize < 0) error("--split-stack-adjust-size: size must be >= 0"); + // The text segment is traditionally the first segment, whose address equals + // the base address. However, lld places the R PT_LOAD first. -Ttext-segment + // is an old-fashioned option that does not play well with lld's layout. + // Suggest --image-base as a likely alternative. + if (args.hasArg(OPT_Ttext_segment)) + error("-Ttext-segment is not supported. Use --image-base if you " + "intend to set the base address"); + // Parse ELF{32,64}{LE,BE} and CPU type. if (auto *arg = args.getLastArg(OPT_m)) { StringRef s = arg->getValue(); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index c6773d0..101fc43 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -59,6 +59,8 @@ defm Tdata: Eq<"Tdata", "Same as --section-start with .data as the sectionname"> defm Ttext: Eq<"Ttext", "Same as --section-start with .text as the sectionname">; +def Ttext_segment: Separate<["-", "--"], "Ttext-segment">; + defm allow_multiple_definition: B<"allow-multiple-definition", "Allow multiple definitions", "Do not allow multiple definitions (default)">; @@ -462,9 +464,8 @@ def: Flag<["-"], "(">, Alias, HelpText<"Alias for --start-group">; def: Flag<["-"], "s">, Alias, HelpText<"Alias for --strip-all">; def: Flag<["-"], "S">, Alias, HelpText<"Alias for --strip-debug">; def: Flag<["-"], "t">, Alias, HelpText<"Alias for --trace">; +def: Joined<["-", "--"], "Ttext-segment=">, Alias; def: JoinedOrSeparate<["-"], "y">, Alias, HelpText<"Alias for --trace-symbol">; -def: Separate<["-", "--"], "Ttext-segment">, Alias, HelpText<"Alias for --Ttext">; -def: Joined<["-", "--"], "Ttext-segment=">, Alias, HelpText<"Alias for --Ttext">; def: JoinedOrSeparate<["-"], "u">, Alias, HelpText<"Alias for --undefined">; def: Flag<["-"], "V">, Alias, HelpText<"Alias for --version">; diff --git a/lld/test/ELF/sectionstart.s b/lld/test/ELF/sectionstart.s index 771d28e..f404a92 100644 --- a/lld/test/ELF/sectionstart.s +++ b/lld/test/ELF/sectionstart.s @@ -20,12 +20,6 @@ # RUN: ld.lld %t.o -Ttext=0x100000 -Tdata=0x110000 -Tbss=0x200000 -o %t4 # RUN: llvm-objdump -section-headers %t4 | FileCheck %s -## Check Ttext-segment X and Ttext-segment=X forms. -# RUN: ld.lld %t.o -Ttext-segment=0x100000 -Tdata=0x110000 -Tbss=0x200000 -o %t4 -# RUN: llvm-objdump -section-headers %t4 | FileCheck %s -# RUN: ld.lld %t.o -Ttext-segment 0x100000 -Tdata=0x110000 -Tbss=0x200000 -o %t4 -# RUN: llvm-objdump -section-headers %t4 | FileCheck %s - ## The same, but dropped "0x" prefix. # RUN: ld.lld %t.o -Ttext=100000 -Tdata=110000 -Tbss=200000 -o %t5 # RUN: llvm-objdump -section-headers %t5 | FileCheck %s diff --git a/lld/test/ELF/ttext-segment.s b/lld/test/ELF/ttext-segment.s new file mode 100644 index 0000000..4d7d690 --- /dev/null +++ b/lld/test/ELF/ttext-segment.s @@ -0,0 +1,8 @@ +# REQUIRES: x86 +## Check that we emit an error for -Ttext-segment. + +# RUN: llvm-mc -filetype=obj -triple=x86_64 /dev/null -o %t.o +# RUN: not ld.lld %t.o -Ttext-segment=0x100000 -o /dev/null 2>&1 | FileCheck %s +# RUN: not ld.lld %t.o -Ttext-segment 0x100000 -o /dev/null 2>&1 | FileCheck %s + +# CHECK: error: -Ttext-segment is not supported. Use --image-base if you intend to set the base address -- 2.7.4