mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-12 19:01:55 +00:00
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);
|
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
|
||||||
|
@ -121,6 +121,7 @@ struct PhdrsCommand {
|
|||||||
bool HasFilehdr;
|
bool HasFilehdr;
|
||||||
bool HasPhdrs;
|
bool HasPhdrs;
|
||||||
unsigned Flags;
|
unsigned Flags;
|
||||||
|
Expr LMAExpr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LinkerScriptBase {
|
class LinkerScriptBase {
|
||||||
|
@ -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.
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user