summaryrefslogtreecommitdiffstats
path: root/lld/ELF
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF')
-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
4 files changed, 43 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);
OpenPOWER on IntegriCloud