[ELF] Allow output section data commands to take expressions

The current implementation of the output section data store commands
can only handle integer literals, but it should really handle arbitrary
expressions [1].  This commit fixes that.

[1] https://sourceware.org/binutils/docs-2.27/ld/Output-Section-Data.html#Output-Section-Data

Differential Revision: https://reviews.llvm.org/D27561

llvm-svn: 289152
This commit is contained in:
Meador Inge 2016-12-08 23:21:30 +00:00
parent b641aa3f14
commit 95c7d8d2a7
3 changed files with 51 additions and 12 deletions

View File

@ -852,7 +852,7 @@ void LinkerScript<ELFT>::writeDataBytes(StringRef Name, uint8_t *Buf) {
auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I].get());
for (const std::unique_ptr<BaseCommand> &Base : Cmd->Commands)
if (auto *Data = dyn_cast<BytesDataCommand>(Base.get()))
writeInt<ELFT>(Buf + Data->Offset, Data->Data, Data->Size);
writeInt<ELFT>(Buf + Data->Offset, Data->Expression(0), Data->Size);
}
template <class ELFT> bool LinkerScript<ELFT>::hasLMA(StringRef Name) {
@ -1688,13 +1688,7 @@ BytesDataCommand *ScriptParser::readBytesDataCommand(StringRef Tok) {
if (Size == -1)
return nullptr;
expect("(");
uint64_t Val = 0;
StringRef S = next();
if (!readInteger(S, Val))
setError("unexpected value: " + S);
expect(")");
return new BytesDataCommand(Val, Size);
return new BytesDataCommand(readParenExpr(), Size);
}
StringRef ScriptParser::readParenLiteral() {

View File

@ -168,12 +168,12 @@ struct AssertCommand : BaseCommand {
// Represents BYTE(), SHORT(), LONG(), or QUAD().
struct BytesDataCommand : BaseCommand {
BytesDataCommand(uint64_t Data, unsigned Size)
: BaseCommand(BytesDataKind), Data(Data), Size(Size) {}
BytesDataCommand(Expr E, unsigned Size)
: BaseCommand(BytesDataKind), Expression(E), Size(Size) {}
static bool classof(const BaseCommand *C);
uint64_t Data;
Expr Expression;
unsigned Offset;
unsigned Size;
};

View File

@ -12,14 +12,28 @@
# RUN: *(.foo.4) \
# RUN: QUAD(0x1122334455667788) \
# RUN: } \
# RUN: .bar : { \
# RUN: *(.bar.1) \
# RUN: BYTE(a + 1) \
# RUN: *(.bar.2) \
# RUN: SHORT(b) \
# RUN: *(.bar.3) \
# RUN: LONG(c + 2) \
# RUN: *(.bar.4) \
# RUN: QUAD(d) \
# RUN: } \
# RUN: }" > %t.script
# RUN: ld.lld -o %t --script %t.script %t.o
# RUN: ld.lld -o %t %t.o --script %t.script
# RUN: llvm-objdump -s %t | FileCheck %s
# CHECK: Contents of section .foo:
# CHECK-NEXT: ff11ff22 11ff4433 2211ff88 77665544
# CHECK-NEXT: 332211
# CHECK: Contents of section .bar:
# CHECK-NEXT: ff12ff22 11ff4633 2211ff88 77665544
# CHECK-NEXT: 332211
# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %tmips64be
# RUN: ld.lld --script %t.script %tmips64be -o %t2
# RUN: llvm-objdump -s %t2 | FileCheck %s --check-prefix=BE
@ -27,6 +41,25 @@
# BE-NEXT: ff11ff11 22ff1122 3344ff11 22334455
# BE-NEXT: 667788
# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %tmips64be
# RUN: ld.lld --script %t.script %tmips64be -o %t2
# RUN: llvm-objdump -s %t2 | FileCheck %s --check-prefix=BE
# BE: Contents of section .bar:
# BE-NEXT: ff12ff11 22ff1122 3346ff11 22334455
# BE-NEXT: 667788
.global a
a = 0x11
.global b
b = 0x1122
.global c
c = 0x11223344
.global d
d = 0x1122334455667788
.section .foo.1, "a"
.byte 0xFF
@ -38,3 +71,15 @@
.section .foo.4, "a"
.byte 0xFF
.section .bar.1, "a"
.byte 0xFF
.section .bar.2, "a"
.byte 0xFF
.section .bar.3, "a"
.byte 0xFF
.section .bar.4, "a"
.byte 0xFF