From eaeafb2b4ff8015dbad2bd4f3d06b9b8672856cb Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Fri, 2 Sep 2016 21:54:35 +0000 Subject: [PATCH] [ELF] PR30221 - linker script expression parser does not accept '~' The patch adds support for both '-' and '~' unary expressions. Also it brings support for signed numbers is expressions. https://llvm.org/bugs/show_bug.cgi?id=30221 Differential revision: https://reviews.llvm.org/D24128 llvm-svn: 280546 --- lld/ELF/LinkerScript.cpp | 15 ++++++++++++++ lld/test/ELF/linkerscript/locationcounter.s | 20 +++++++++++++++++++ lld/test/ELF/linkerscript/symbol-assignexpr.s | 16 +++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 6085b19b6789..3d3b3d6e59f8 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -1231,6 +1231,12 @@ uint64_t static getConstant(StringRef S) { // and decimal numbers. Decimal numbers may have "K" (kilo) or // "M" (mega) prefixes. static bool readInteger(StringRef Tok, uint64_t &Result) { + if (Tok.startswith("-")) { + if (!readInteger(Tok.substr(1), Result)) + return false; + Result = -Result; + return true; + } if (Tok.startswith_lower("0x")) return !Tok.substr(2).getAsInteger(16, Result); if (Tok.endswith_lower("H")) @@ -1256,6 +1262,15 @@ Expr ScriptParser::readPrimary() { StringRef Tok = next(); + if (Tok == "~") { + Expr E = readPrimary(); + return [=](uint64_t Dot) { return ~E(Dot); }; + } + if (Tok == "-") { + Expr E = readPrimary(); + return [=](uint64_t Dot) { return -E(Dot); }; + } + // Built-in functions are parsed here. // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html. if (Tok == "ADDR") { diff --git a/lld/test/ELF/linkerscript/locationcounter.s b/lld/test/ELF/linkerscript/locationcounter.s index 94af0ce3840a..4e17da42e1f6 100644 --- a/lld/test/ELF/linkerscript/locationcounter.s +++ b/lld/test/ELF/linkerscript/locationcounter.s @@ -40,6 +40,8 @@ # RUN: . = 0x27000; \ # RUN: . += 0x1000; \ # RUN: .plusassign : { *(.plusassign) } \ +# RUN: . = ((. + 0x1fff) & ~(0x1000 + -1)); \ +# RUN: .unary : { *(.unary) } \ # RUN: }" > %t.script # RUN: ld.lld %t --script %t.script -o %t2 # RUN: llvm-readobj -s %t2 | FileCheck %s @@ -314,6 +316,21 @@ # CHECK-NEXT: AddressAlignment: # CHECK-NEXT: EntrySize: # CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: +# CHECK-NEXT: Name: .unary +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x2A000 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: } ## Mailformed number error. # RUN: echo "SECTIONS { \ @@ -420,3 +437,6 @@ nop .section .plusassign, "a" .quad 0 + +.section .unary, "a" +.quad 0 diff --git a/lld/test/ELF/linkerscript/symbol-assignexpr.s b/lld/test/ELF/linkerscript/symbol-assignexpr.s index 80c4e89424e4..6e256e6a5e8c 100644 --- a/lld/test/ELF/linkerscript/symbol-assignexpr.s +++ b/lld/test/ELF/linkerscript/symbol-assignexpr.s @@ -5,6 +5,14 @@ # RUN: symbol = CONSTANT(MAXPAGESIZE); \ # RUN: symbol2 = symbol + 0x1234; \ # RUN: symbol3 = symbol2; \ +# RUN: symbol4 = symbol + -4; \ +# RUN: symbol5 = symbol - ~ 0xfffb; \ +# RUN: symbol6 = symbol - ~(0xfff0 + 0xb); \ +# RUN: symbol7 = symbol - ~ 0xfffb + 4; \ +# RUN: symbol8 = ~ 0xffff + 4; \ +# RUN: symbol9 = - 4; \ +# RUN: symbol10 = 0xfedcba9876543210; \ +# RUN: symbol11 = ((0x28000 + 0x1fff) & ~(0x1000 + -1)); \ # RUN: }" > %t.script # RUN: ld.lld -o %t1 --script %t.script %t # RUN: llvm-objdump -t %t1 | FileCheck %s @@ -16,6 +24,14 @@ # CHECK-NEXT: 0000000000200000 *ABS* 00000000 symbol # CHECK-NEXT: 0000000000201234 *ABS* 00000000 symbol2 # CHECK-NEXT: 0000000000201234 *ABS* 00000000 symbol3 +# CHECK-NEXT: 00000000001ffffc *ABS* 00000000 symbol4 +# CHECK-NEXT: 000000000020fffc *ABS* 00000000 symbol5 +# CHECK-NEXT: 000000000020fffc *ABS* 00000000 symbol6 +# CHECK-NEXT: 0000000000210000 *ABS* 00000000 symbol7 +# CHECK-NEXT: ffffffffffff0004 *ABS* 00000000 symbol8 +# CHECK-NEXT: fffffffffffffffc *ABS* 00000000 symbol9 +# CHECK-NEXT: fedcba9876543210 *ABS* 00000000 symbol10 +# CHECK-NEXT: 0000000000029000 *ABS* 00000000 symbol11 # RUN: echo "SECTIONS { \ # RUN: symbol2 = symbol; \