[lld] r281458 - [ELF] - Implemented --section-start, -Ttext, -Tdata, -Tbss options.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 14 06:07:13 PDT 2016


Author: grimar
Date: Wed Sep 14 08:07:13 2016
New Revision: 281458

URL: http://llvm.org/viewvc/llvm-project?rev=281458&view=rev
Log:
[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

Added:
    lld/trunk/test/ELF/sectionstart.s
Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/Options.td
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=281458&r1=281457&r2=281458&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Wed Sep 14 08:07:13 2016
@@ -65,6 +65,7 @@ struct VersionDefinition {
 struct Configuration {
   Symbol *EntrySym = nullptr;
   InputFile *FirstElf = nullptr;
+  llvm::StringMap<uint64_t> SectionStartMap;
   llvm::StringRef DynamicLinker;
   llvm::StringRef Entry;
   llvm::StringRef Emulation;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=281458&r1=281457&r2=281458&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Wed Sep 14 08:07:13 2016
@@ -380,6 +380,33 @@ static StripPolicy getStripOption(opt::I
   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<uint64_t> getSectionStartMap(opt::InputArgList &Args) {
+  StringMap<uint64_t> 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::Inpu
   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();

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=281458&r1=281457&r2=281458&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Wed Sep 14 08:07:13 2016
@@ -27,6 +27,12 @@ def L: JoinedOrSeparate<["-"], "L">, Met
 
 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">, HelpT
 
 def script: S<"script">, HelpText<"Read linker script">;
 
+def section_start: S<"section-start">, MetaVarName<"<address>">,
+  HelpText<"Set address of section">;
+
 def shared: F<"shared">, HelpText<"Build a shared object">;
 
 def soname: J<"soname=">, HelpText<"Set DT_SONAME">;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=281458&r1=281457&r2=281458&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Sep 14 08:07:13 2016
@@ -1080,6 +1080,10 @@ template <class ELFT> void Writer<ELFT>:
     if (Sec->PageAlign)
       Alignment = std::max<uintX_t>(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);

Added: lld/trunk/test/ELF/sectionstart.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/sectionstart.s?rev=281458&view=auto
==============================================================================
--- lld/trunk/test/ELF/sectionstart.s (added)
+++ lld/trunk/test/ELF/sectionstart.s Wed Sep 14 08:07:13 2016
@@ -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




More information about the llvm-commits mailing list