diff options
Diffstat (limited to 'lld/ELF')
| -rw-r--r-- | lld/ELF/Config.h | 1 | ||||
| -rw-r--r-- | lld/ELF/Driver.cpp | 29 | ||||
| -rw-r--r-- | lld/ELF/Options.td | 9 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 4 |
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); |

