[ELF] PR30221 - linker script expression parser does not accept '~'
authorSimon Atanasyan <simon@atanasyan.com>
Fri, 2 Sep 2016 21:54:35 +0000 (21:54 +0000)
committerSimon Atanasyan <simon@atanasyan.com>
Fri, 2 Sep 2016 21:54:35 +0000 (21:54 +0000)
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
lld/test/ELF/linkerscript/locationcounter.s
lld/test/ELF/linkerscript/symbol-assignexpr.s

index 6085b19..3d3b3d6 100644 (file)
@@ -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") {
index 94af0ce..4e17da4 100644 (file)
@@ -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
 # 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
index 80c4e89..6e256e6 100644 (file)
@@ -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
 # 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; \