From: George Rimar Date: Wed, 14 Sep 2016 13:07:13 +0000 (+0000) Subject: [ELF] - Implemented --section-start, -Ttext, -Tdata, -Tbss options. X-Git-Tag: llvmorg-4.0.0-rc1~9824 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d73ef1738b133c3f264b590eb996991c2f13cb9f;p=platform%2Fupstream%2Fllvm.git [ELF] - Implemented --section-start, -Ttext, -Tdata, -Tbss options. --section-start=sectionname=org Locate a section in the output file at the absolute address given by org. You may use this option as many times as necessary to locate multiple sections in the command line. org must be a single hexadecimal integer; for compatibility with other linkers, you may omit the leading `0x' usually associated with hexadecimal values. Note: there should be no white space between sectionname, the equals sign (“<=>”), and org. -Tbss=org -Tdata=org -Ttext=org Same as --section-start, with .bss, .data or .text as the sectionname. Differential revision: https://reviews.llvm.org/D24294 llvm-svn: 281458 --- diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index b182b77..dfff5e7 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -65,6 +65,7 @@ struct VersionDefinition { struct Configuration { Symbol *EntrySym = nullptr; InputFile *FirstElf = nullptr; + llvm::StringMap SectionStartMap; llvm::StringRef DynamicLinker; llvm::StringRef Entry; llvm::StringRef Emulation; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 8f5f543c..9f1d91a 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -380,6 +380,33 @@ static StripPolicy getStripOption(opt::InputArgList &Args) { return StripPolicy::None; } +static uint64_t parseSectionAddress(StringRef S, opt::Arg *Arg) { + uint64_t VA = 0; + if (S.startswith("0x")) + S = S.drop_front(2); + if (S.getAsInteger(16, VA)) + error("invalid argument: " + stringize(Arg)); + return VA; +} + +static StringMap getSectionStartMap(opt::InputArgList &Args) { + StringMap Ret; + for (auto *Arg : Args.filtered(OPT_section_start)) { + StringRef Name; + StringRef Addr; + std::tie(Name, Addr) = StringRef(Arg->getValue()).split('='); + Ret[Name] = parseSectionAddress(Addr, Arg); + } + + if (auto *Arg = Args.getLastArg(OPT_Ttext)) + Ret[".text"] = parseSectionAddress(Arg->getValue(), Arg); + if (auto *Arg = Args.getLastArg(OPT_Tdata)) + Ret[".data"] = parseSectionAddress(Arg->getValue(), Arg); + if (auto *Arg = Args.getLastArg(OPT_Tbss)) + Ret[".bss"] = parseSectionAddress(Arg->getValue(), Arg); + return Ret; +} + // Initializes Config members by the command line options. void LinkerDriver::readConfigs(opt::InputArgList &Args) { for (auto *Arg : Args.filtered(OPT_L)) @@ -391,6 +418,8 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { if (!RPaths.empty()) Config->RPath = llvm::join(RPaths.begin(), RPaths.end(), ":"); + Config->SectionStartMap = getSectionStartMap(Args); + if (auto *Arg = Args.getLastArg(OPT_m)) { // Parse ELF{32,64}{LE,BE} and CPU type. StringRef S = Arg->getValue(); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index e90eb1a..274d2a2 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -27,6 +27,12 @@ def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"">, def O: Joined<["-"], "O">, HelpText<"Optimize output file size">; +def Tbss: J<"Tbss=">, HelpText<"Same as --section-start with .bss as the sectionname">; + +def Tdata: J<"Tdata=">, HelpText<"Same as --section-start with .data as the sectionname">; + +def Ttext: J<"Ttext=">, HelpText<"Same as --section-start with .text as the sectionname">; + def allow_multiple_definition: F<"allow-multiple-definition">, HelpText<"Allow multiple definitions">; @@ -147,6 +153,9 @@ def relocatable: F<"relocatable">, HelpText<"Create relocatable object file">; def script: S<"script">, HelpText<"Read linker script">; +def section_start: S<"section-start">, MetaVarName<"
">, + HelpText<"Set address of section">; + def shared: F<"shared">, HelpText<"Build a shared object">; def soname: J<"soname=">, HelpText<"Set DT_SONAME">; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index c728a73..2ebdfae 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1080,6 +1080,10 @@ template void Writer::assignAddresses() { if (Sec->PageAlign) Alignment = std::max(Alignment, Target->PageSize); + auto I = Config->SectionStartMap.find(Sec->getName()); + if (I != Config->SectionStartMap.end()) + VA = I->second; + // We only assign VAs to allocated sections. if (needsPtLoad(Sec)) { VA = alignTo(VA, Alignment); diff --git a/lld/test/ELF/sectionstart.s b/lld/test/ELF/sectionstart.s new file mode 100644 index 0000000..4329952 --- /dev/null +++ b/lld/test/ELF/sectionstart.s @@ -0,0 +1,57 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: ld.lld %t.o --section-start .text=0x100000 \ +# RUN: --section-start .data=0x110000 --section-start .bss=0x200000 -o %t +# RUN: llvm-objdump -section-headers %t | FileCheck %s + +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address Type +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 .text 00000001 0000000000100000 TEXT DATA +# CHECK-NEXT: 2 .data 00000004 0000000000110000 DATA +# CHECK-NEXT: 3 .bss 00000004 0000000000200000 BSS + +## The same, but dropped "0x" prefix. +# RUN: ld.lld %t.o --section-start .text=100000 \ +# RUN: --section-start .data=110000 --section-start .bss=0x200000 -o %t1 +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s + +## Use -Ttext, -Tdata, -Tbss as replacement for --section-start: +# RUN: ld.lld %t.o -Ttext=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 + +## Errors: +# RUN: not ld.lld %t.o --section-start .text100000 -o %t2 2>&1 \ +# RUN: | FileCheck -check-prefix=ERR1 %s +# ERR1: invalid argument: --section-start .text100000 + +# RUN: not ld.lld %t.o --section-start .text=1Q0000 -o %t3 2>&1 \ +# RUN: | FileCheck -check-prefix=ERR2 %s +# ERR2: invalid argument: --section-start .text=1Q0000 + +# RUN: not ld.lld %t.o -Ttext=1w0000 -o %t6 2>&1 \ +# RUN: | FileCheck -check-prefix=ERR3 %s +# ERR3: invalid argument: -Ttext=1w0000 + +# RUN: not ld.lld %t.o -Tbss=1w0000 -o %t6 2>&1 \ +# RUN: | FileCheck -check-prefix=ERR4 %s +# ERR4: invalid argument: -Tbss=1w0000 + +# RUN: not ld.lld %t.o -Tdata=1w0000 -o %t6 2>&1 \ +# RUN: | FileCheck -check-prefix=ERR5 %s +# ERR5: invalid argument: -Tdata=1w0000 + +.text +.globl _start +_start: + nop + +.data +.long 0 + +.bss +.zero 4