summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorge Rimar <grimar@accesssoftek.com>2016-09-14 13:07:13 +0000
committerGeorge Rimar <grimar@accesssoftek.com>2016-09-14 13:07:13 +0000
commitd73ef1738b133c3f264b590eb996991c2f13cb9f (patch)
treeb0b9f25f2715d8abf23fce861106c9bef07823f0
parentac73ea34a474f578edde75ef4aaa243c8d2847d0 (diff)
downloadbcm5719-llvm-d73ef1738b133c3f264b590eb996991c2f13cb9f.tar.gz
bcm5719-llvm-d73ef1738b133c3f264b590eb996991c2f13cb9f.zip
[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
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/Driver.cpp29
-rw-r--r--lld/ELF/Options.td9
-rw-r--r--lld/ELF/Writer.cpp4
-rw-r--r--lld/test/ELF/sectionstart.s57
5 files changed, 100 insertions, 0 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index b182b77b0c1..dfff5e78e63 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<uint64_t> SectionStartMap;
llvm::StringRef DynamicLinker;
llvm::StringRef Entry;
llvm::StringRef Emulation;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 8f5f543c7e4..9f1d91a93e6 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<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::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 e90eb1afaf7..274d2a27b4e 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -27,6 +27,12 @@ def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,
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<"<address>">,
+ 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 c728a7391b1..2ebdfaed41c 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1080,6 +1080,10 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
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);
diff --git a/lld/test/ELF/sectionstart.s b/lld/test/ELF/sectionstart.s
new file mode 100644
index 00000000000..4329952ab21
--- /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
OpenPOWER on IntegriCloud