Linker script: implement AT [ (address) ] for PHDR

Differential revision: https://reviews.llvm.org/D24340

llvm-svn: 281024
This commit is contained in:
Eugene Leviant 2016-09-09 09:46:16 +00:00
parent d63d8a7c05
commit 56b21c869e
5 changed files with 44 additions and 6 deletions

View File

@ -463,6 +463,11 @@ std::vector<PhdrEntry<ELFT>> LinkerScript<ELFT>::createPhdrs() {
Phdr.add(Out<ELFT>::ElfHeader); Phdr.add(Out<ELFT>::ElfHeader);
if (Cmd.HasPhdrs) if (Cmd.HasPhdrs)
Phdr.add(Out<ELFT>::ProgramHeaders); Phdr.add(Out<ELFT>::ProgramHeaders);
if (Cmd.LMAExpr) {
Phdr.H.p_paddr = Cmd.LMAExpr(0);
Phdr.HasLMA = true;
}
} }
// Add output sections to program headers. // Add output sections to program headers.
@ -860,7 +865,8 @@ void ScriptParser::readPhdrs() {
expect("{"); expect("{");
while (!Error && !skip("}")) { while (!Error && !skip("}")) {
StringRef Tok = next(); StringRef Tok = next();
Opt.PhdrsCommands.push_back({Tok, PT_NULL, false, false, UINT_MAX}); Opt.PhdrsCommands.push_back(
{Tok, PT_NULL, false, false, UINT_MAX, nullptr});
PhdrsCommand &PhdrCmd = Opt.PhdrsCommands.back(); PhdrsCommand &PhdrCmd = Opt.PhdrsCommands.back();
PhdrCmd.Type = readPhdrType(); PhdrCmd.Type = readPhdrType();
@ -872,6 +878,8 @@ void ScriptParser::readPhdrs() {
PhdrCmd.HasFilehdr = true; PhdrCmd.HasFilehdr = true;
else if (Tok == "PHDRS") else if (Tok == "PHDRS")
PhdrCmd.HasPhdrs = true; PhdrCmd.HasPhdrs = true;
else if (Tok == "AT")
PhdrCmd.LMAExpr = readParenExpr();
else if (Tok == "FLAGS") { else if (Tok == "FLAGS") {
expect("("); expect("(");
// Passing 0 for the value of dot is a bit of a hack. It means that // Passing 0 for the value of dot is a bit of a hack. It means that

View File

@ -121,6 +121,7 @@ struct PhdrsCommand {
bool HasFilehdr; bool HasFilehdr;
bool HasPhdrs; bool HasPhdrs;
unsigned Flags; unsigned Flags;
Expr LMAExpr;
}; };
class LinkerScriptBase { class LinkerScriptBase {

View File

@ -1168,10 +1168,14 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() {
else if (H.p_type == PT_GNU_RELRO) else if (H.p_type == PT_GNU_RELRO)
H.p_align = 1; H.p_align = 1;
H.p_paddr = H.p_vaddr; if (!P.HasLMA) {
if (H.p_type == PT_LOAD && First) // The p_paddr field can be set using linker script AT command.
if (Expr LmaExpr = Script<ELFT>::X->getLma(First->getName())) // By default, it is the same value as p_vaddr.
H.p_paddr = LmaExpr(H.p_vaddr); H.p_paddr = H.p_vaddr;
if (H.p_type == PT_LOAD && First)
if (Expr LmaExpr = Script<ELFT>::X->getLma(First->getName()))
H.p_paddr = LmaExpr(H.p_vaddr);
}
// The TLS pointer goes after PT_TLS. At least glibc will align it, // The TLS pointer goes after PT_TLS. At least glibc will align it,
// so round up the size to make sure the offsets are correct. // so round up the size to make sure the offsets are correct.

View File

@ -38,6 +38,7 @@ struct PhdrEntry {
typename ELFT::Phdr H = {}; typename ELFT::Phdr H = {};
OutputSectionBase<ELFT> *First = nullptr; OutputSectionBase<ELFT> *First = nullptr;
OutputSectionBase<ELFT> *Last = nullptr; OutputSectionBase<ELFT> *Last = nullptr;
bool HasLMA = false;
}; };
template <class ELFT> template <class ELFT>

View File

@ -6,9 +6,19 @@
# RUN: .text : {*(.text*)} :all \ # RUN: .text : {*(.text*)} :all \
# RUN: .foo : {*(.foo.*)} :all \ # RUN: .foo : {*(.foo.*)} :all \
# RUN: .data : {*(.data.*)} :all}" > %t.script # RUN: .data : {*(.data.*)} :all}" > %t.script
# RUN: ld.lld -o %t1 --script %t.script %t # RUN: ld.lld -o %t1 --script %t.script %t
# RUN: llvm-readobj -program-headers %t1 | FileCheck %s # RUN: llvm-readobj -program-headers %t1 | FileCheck %s
## Check the AT(expr)
# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS AT(0x500 + 0x500) ;} \
# RUN: SECTIONS { \
# RUN: . = 0x10000200; \
# RUN: .text : {*(.text*)} :all \
# RUN: .foo : {*(.foo.*)} :all \
# RUN: .data : {*(.data.*)} :all}" > %t.script
# RUN: ld.lld -o %t1 --script %t.script %t
# RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=AT %s
# CHECK: ProgramHeaders [ # CHECK: ProgramHeaders [
# CHECK-NEXT: ProgramHeader { # CHECK-NEXT: ProgramHeader {
# CHECK-NEXT: Type: PT_LOAD (0x1) # CHECK-NEXT: Type: PT_LOAD (0x1)
@ -23,6 +33,20 @@
# CHECK-NEXT: PF_X (0x1) # CHECK-NEXT: PF_X (0x1)
# CHECK-NEXT: ] # CHECK-NEXT: ]
# AT: ProgramHeaders [
# AT-NEXT: ProgramHeader {
# AT-NEXT: Type: PT_LOAD (0x1)
# AT-NEXT: Offset: 0x0
# AT-NEXT: VirtualAddress: 0x10000000
# AT-NEXT: PhysicalAddress: 0xA00
# AT-NEXT: FileSize: 521
# AT-NEXT: MemSize: 521
# AT-NEXT: Flags [ (0x7)
# AT-NEXT: PF_R (0x4)
# AT-NEXT: PF_W (0x2)
# AT-NEXT: PF_X (0x1)
# AT-NEXT: ]
.global _start .global _start
_start: _start:
nop nop