diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 48e29111edb9..e93f138324f1 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -59,11 +59,23 @@ uint64_t ExprValue::getValue() const { return Val; } -static ExprValue add(ExprValue A, ExprValue B) { +uint64_t ExprValue::getSecAddr() const { + if (Sec) + return Sec->getOffset(0) + Sec->getOutputSection()->Addr; + return 0; +} + +// Some operations only support one non absolute value. Move the +// absolute one to the right hand side for convenience. +static void moveAbsRight(ExprValue &A, ExprValue &B) { if (A.isAbsolute()) std::swap(A, B); if (!B.isAbsolute()) error("At least one side of the expression must be absolute"); +} + +static ExprValue add(ExprValue A, ExprValue B) { + moveAbsRight(A, B); return {A.Sec, A.ForceAbsolute, A.Val + B.getValue()}; } static ExprValue sub(ExprValue A, ExprValue B) { @@ -103,10 +115,14 @@ static ExprValue notEqual(ExprValue A, ExprValue B) { return A.getValue() != B.getValue(); } static ExprValue bitAnd(ExprValue A, ExprValue B) { - return A.getValue() & B.getValue(); + moveAbsRight(A, B); + return {A.Sec, A.ForceAbsolute, + (A.getValue() & B.getValue()) - A.getSecAddr()}; } static ExprValue bitOr(ExprValue A, ExprValue B) { - return A.getValue() | B.getValue(); + moveAbsRight(A, B); + return {A.Sec, A.ForceAbsolute, + (A.getValue() | B.getValue()) - A.getSecAddr()}; } static ExprValue bitNot(ExprValue A) { return ~A.getValue(); } static ExprValue minus(ExprValue A) { return -A.getValue(); } diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 1dc2e049df49..ee08b272098b 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -49,6 +49,7 @@ struct ExprValue { ExprValue(uint64_t Val) : ExprValue(nullptr, Val) {} bool isAbsolute() const { return ForceAbsolute || Sec == nullptr; } uint64_t getValue() const; + uint64_t getSecAddr() const; }; // This represents an expression in the linker script. diff --git a/lld/test/ELF/linkerscript/expr-sections.s b/lld/test/ELF/linkerscript/expr-sections.s index 74b9393db85a..eb60009cd971 100644 --- a/lld/test/ELF/linkerscript/expr-sections.s +++ b/lld/test/ELF/linkerscript/expr-sections.s @@ -1,35 +1,22 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o -# RUN: echo "SECTIONS { foo = ADDR(.text) + 1; bar = 1 + ADDR(.text); };" > %t.script +# RUN: echo "SECTIONS { \ +# RUN: . = . + 4; \ +# RUN: .text : { \ +# RUN: *(.text) \ +# RUN: foo1 = ADDR(.text) + 1; bar1 = 1 + ADDR(.text); \ +# RUN: foo2 = ADDR(.text) & 1; bar2 = 1 & ADDR(.text); \ +# RUN: foo3 = ADDR(.text) | 1; bar3 = 1 | ADDR(.text); \ +# RUN: } \ +# RUN: };" > %t.script # RUN: ld.lld -o %t.so --script %t.script %t.o -shared -# RUN: llvm-readobj -t -s %t.so | FileCheck %s +# RUN: llvm-objdump -t -h %t.so | FileCheck %s -# CHECK: Section { -# CHECK: Index: -# CHECK: Name: .text -# CHECK-NEXT: Type: -# CHECK-NEXT: Flags [ -# CHECK-NEXT: SHF_ALLOC -# CHECK-NEXT: SHF_EXECINSTR -# CHECK-NEXT: ] -# CHECK-NEXT: Address: 0x0 +# CHECK: 1 .text 00000000 0000000000000004 TEXT DATA -# CHECK: Symbol { -# CHECK: Name: foo -# CHECK-NEXT: Value: 0x1 -# CHECK-NEXT: Size: 0 -# CHECK-NEXT: Binding: Global -# CHECK-NEXT: Type: None -# CHECK-NEXT: Other: 0 -# CHECK-NEXT: Section: .text -# CHECK-NEXT: } - -# CHECK: Symbol { -# CHECK: Name: bar -# CHECK-NEXT: Value: 0x1 -# CHECK-NEXT: Size: 0 -# CHECK-NEXT: Binding: Global -# CHECK-NEXT: Type: None -# CHECK-NEXT: Other: 0 -# CHECK-NEXT: Section: .text -# CHECK-NEXT: } +# CHECK: 0000000000000005 .text 00000000 foo1 +# CHECK: 0000000000000005 .text 00000000 bar1 +# CHECK: 0000000000000000 .text 00000000 foo2 +# CHECK: 0000000000000000 .text 00000000 bar2 +# CHECK: 0000000000000005 .text 00000000 foo3 +# CHECK: 0000000000000005 .text 00000000 bar3