forked from OSchip/llvm-project
Linker script: implement AT [ (address) ] for PHDR
Differential revision: https://reviews.llvm.org/D24340 llvm-svn: 281024
This commit is contained in:
parent
d63d8a7c05
commit
56b21c869e
|
@ -463,6 +463,11 @@ std::vector<PhdrEntry<ELFT>> LinkerScript<ELFT>::createPhdrs() {
|
|||
Phdr.add(Out<ELFT>::ElfHeader);
|
||||
if (Cmd.HasPhdrs)
|
||||
Phdr.add(Out<ELFT>::ProgramHeaders);
|
||||
|
||||
if (Cmd.LMAExpr) {
|
||||
Phdr.H.p_paddr = Cmd.LMAExpr(0);
|
||||
Phdr.HasLMA = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Add output sections to program headers.
|
||||
|
@ -860,7 +865,8 @@ void ScriptParser::readPhdrs() {
|
|||
expect("{");
|
||||
while (!Error && !skip("}")) {
|
||||
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();
|
||||
|
||||
PhdrCmd.Type = readPhdrType();
|
||||
|
@ -872,6 +878,8 @@ void ScriptParser::readPhdrs() {
|
|||
PhdrCmd.HasFilehdr = true;
|
||||
else if (Tok == "PHDRS")
|
||||
PhdrCmd.HasPhdrs = true;
|
||||
else if (Tok == "AT")
|
||||
PhdrCmd.LMAExpr = readParenExpr();
|
||||
else if (Tok == "FLAGS") {
|
||||
expect("(");
|
||||
// Passing 0 for the value of dot is a bit of a hack. It means that
|
||||
|
|
|
@ -121,6 +121,7 @@ struct PhdrsCommand {
|
|||
bool HasFilehdr;
|
||||
bool HasPhdrs;
|
||||
unsigned Flags;
|
||||
Expr LMAExpr;
|
||||
};
|
||||
|
||||
class LinkerScriptBase {
|
||||
|
|
|
@ -1168,10 +1168,14 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() {
|
|||
else if (H.p_type == PT_GNU_RELRO)
|
||||
H.p_align = 1;
|
||||
|
||||
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);
|
||||
if (!P.HasLMA) {
|
||||
// The p_paddr field can be set using linker script AT command.
|
||||
// By default, it is the same value as 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,
|
||||
// so round up the size to make sure the offsets are correct.
|
||||
|
|
|
@ -38,6 +38,7 @@ struct PhdrEntry {
|
|||
typename ELFT::Phdr H = {};
|
||||
OutputSectionBase<ELFT> *First = nullptr;
|
||||
OutputSectionBase<ELFT> *Last = nullptr;
|
||||
bool HasLMA = false;
|
||||
};
|
||||
|
||||
template <class ELFT>
|
||||
|
|
|
@ -6,9 +6,19 @@
|
|||
# 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 %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-NEXT: ProgramHeader {
|
||||
# CHECK-NEXT: Type: PT_LOAD (0x1)
|
||||
|
@ -23,6 +33,20 @@
|
|||
# CHECK-NEXT: PF_X (0x1)
|
||||
# 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
|
||||
_start:
|
||||
nop
|
||||
|
|
Loading…
Reference in New Issue