summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Hosek <phosek@chromium.org>2016-07-12 19:37:53 +0000
committerPetr Hosek <phosek@chromium.org>2016-07-12 19:37:53 +0000
commitd7bd2389ceb2c2772d0d74cb092571a84aab3584 (patch)
tree33a9ec32b3e1da200723f1b6e357e56961463826
parent9330b7843170d0ca073f47ca096526e4076d26cd (diff)
downloadbcm5719-llvm-d7bd2389ceb2c2772d0d74cb092571a84aab3584.tar.gz
bcm5719-llvm-d7bd2389ceb2c2772d0d74cb092571a84aab3584.zip
[ELF] Support for setting the base address
The -image-base option allows for overriding the base address. Differential Revision: http://reviews.llvm.org/D22116 llvm-svn: 275206
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/Driver.cpp10
-rw-r--r--lld/ELF/Options.td2
-rw-r--r--lld/ELF/Writer.cpp4
-rw-r--r--lld/test/ELF/ttext-segment.s60
5 files changed, 75 insertions, 2 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index abfdc43b74c..8a8cc04b760 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -117,6 +117,7 @@ struct Configuration {
ELFKind EKind = ELFNoneKind;
uint16_t EMachine = llvm::ELF::EM_NONE;
uint64_t EntryAddr = -1;
+ uint64_t VAStart;
unsigned LtoJobs;
unsigned LtoO;
unsigned Optimize;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 21357fb8654..fd783ccd6b1 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -532,6 +532,16 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
Config->EntrySym = Symtab.addUndefined(S);
}
+ if (auto *Arg = Args.getLastArg(OPT_image_base)) {
+ StringRef S = Arg->getValue();
+ if (S.getAsInteger(0, Config->VAStart))
+ error(Arg->getSpelling() + ": number expected, but got " + S);
+ else if ((Config->VAStart % Target->PageSize) != 0)
+ warning(Arg->getSpelling() + ": address isn't multiple of page size");
+ } else {
+ Config->VAStart = Target->getVAStart();
+ }
+
for (std::unique_ptr<InputFile> &F : Files)
Symtab.addFile(std::move(F));
if (HasError)
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 4d291966380..010f37687f0 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -79,6 +79,8 @@ def help: F<"help">, HelpText<"Print option help">;
def icf: F<"icf=all">, HelpText<"Enable identical code folding">;
+def image_base : J<"image-base=">, HelpText<"Set the base address">;
+
def gc_sections: F<"gc-sections">,
HelpText<"Enable garbage collection of unused sections">;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 17b10259d8f..1f03df53027 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1022,7 +1022,7 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
// sections. These are special, we do not include them into output sections
// list, but have them to simplify the code.
template <class ELFT> void Writer<ELFT>::fixHeaders() {
- uintX_t BaseVA = ScriptConfig->DoLayout ? 0 : Target->getVAStart();
+ uintX_t BaseVA = ScriptConfig->DoLayout ? 0 : Config->VAStart;
Out<ELFT>::ElfHeader->setVA(BaseVA);
uintX_t Off = Out<ELFT>::ElfHeader->getSize();
Out<ELFT>::ProgramHeaders->setVA(Off + BaseVA);
@@ -1030,7 +1030,7 @@ template <class ELFT> void Writer<ELFT>::fixHeaders() {
// Assign VAs (addresses at run-time) to output sections.
template <class ELFT> void Writer<ELFT>::assignAddresses() {
- uintX_t VA = Target->getVAStart() + Out<ELFT>::ElfHeader->getSize() +
+ uintX_t VA = Config->VAStart + Out<ELFT>::ElfHeader->getSize() +
Out<ELFT>::ProgramHeaders->getSize();
uintX_t ThreadBssOffset = 0;
diff --git a/lld/test/ELF/ttext-segment.s b/lld/test/ELF/ttext-segment.s
new file mode 100644
index 00000000000..0be5059dcad
--- /dev/null
+++ b/lld/test/ELF/ttext-segment.s
@@ -0,0 +1,60 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld -image-base=0x1000000 %t -o %t1
+# RUN: llvm-readobj -program-headers %t1 | FileCheck %s
+
+.global _start
+_start:
+ nop
+
+# CHECK: ProgramHeaders [
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_PHDR (0x6)
+# CHECK-NEXT: Offset: 0x40
+# CHECK-NEXT: VirtualAddress: 0x1000040
+# CHECK-NEXT: PhysicalAddress: 0x1000040
+# CHECK-NEXT: FileSize: 224
+# CHECK-NEXT: MemSize: 224
+# CHECK-NEXT: Flags [ (0x4)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 8
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD (0x1)
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: VirtualAddress: 0x1000000
+# CHECK-NEXT: PhysicalAddress: 0x1000000
+# CHECK-NEXT: FileSize: 288
+# CHECK-NEXT: MemSize: 288
+# CHECK-NEXT: Flags [ (0x4)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 4096
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD (0x1)
+# CHECK-NEXT: Offset: 0x1000
+# CHECK-NEXT: VirtualAddress: 0x1001000
+# CHECK-NEXT: PhysicalAddress: 0x1001000
+# CHECK-NEXT: FileSize: 1
+# CHECK-NEXT: MemSize: 1
+# CHECK-NEXT: Flags [ (0x5)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: PF_X (0x1)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 4096
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_GNU_STACK (0x6474E551)
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: FileSize: 0
+# CHECK-NEXT: MemSize: 0
+# CHECK-NEXT: Flags [ (0x6)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: PF_W (0x2)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 0
+# CHECK-NEXT: }
OpenPOWER on IntegriCloud