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.
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();
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
bool HasFilehdr;
bool HasPhdrs;
unsigned Flags;
+ Expr LMAExpr;
};
class LinkerScriptBase {
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.
typename ELFT::Phdr H = {};
OutputSectionBase<ELFT> *First = nullptr;
OutputSectionBase<ELFT> *Last = nullptr;
+ bool HasLMA = false;
};
template <class ELFT>
# 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)
# 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