From 30835ea47a17f1a147bcda2d851e7c90bbbbfc18 Mon Sep 17 00:00:00 2001 From: George Rimar Date: Thu, 28 Jul 2016 21:08:56 +0000 Subject: [PATCH] [ELF] - Linkerscript: implemented += operator. Sometimes += is used to move the location counter. Example from the wild is: .dbg_excpt _DBG_EXCPT_ADDR (NOLOAD) : { . += (DEFINED (_DEBUGGER) ? 0x8 : 0x0); https://github.com/chipKIT32/pic32-Arduino-USB-Bootloader-original/blob/master/boot-linkerscript.ld Patch implements it and opens way for others type of assignments (-= *= etc), though I think only += is actual to support. Differential revision: https://reviews.llvm.org/D22916 llvm-svn: 277035 --- lld/ELF/LinkerScript.cpp | 39 ++++++++++--------- .../linkerscript-locationcounter.s | 21 ++++++++++ 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 86421536fadf..339c06dde66f 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -643,7 +643,7 @@ void ScriptParser::readSections() { expect("{"); while (!Error && !skip("}")) { StringRef Tok = next(); - if (peek() == "=") { + if (peek() == "=" || peek() == "+=") { readAssignment(Tok); expect(";"); } else if (Tok == "PROVIDE") { @@ -777,19 +777,10 @@ void ScriptParser::readProvide(bool Hidden) { expect(";"); } -SymbolAssignment *ScriptParser::readAssignment(StringRef Name) { - expect("="); - Expr E = readExpr(); - auto *Cmd = new SymbolAssignment(Name, E); - Opt.Commands.emplace_back(Cmd); - return Cmd; -} +static uint64_t getSymbolValue(StringRef S, uint64_t Dot) { + if (S == ".") + return Dot; -// This is an operator-precedence parser to parse a linker -// script expression. -Expr ScriptParser::readExpr() { return readExpr1(readPrimary(), 0); } - -static uint64_t getSymbolValue(StringRef S) { switch (Config->EKind) { case ELF32LEKind: if (SymbolBody *B = Symtab::X->find(S)) @@ -814,6 +805,21 @@ static uint64_t getSymbolValue(StringRef S) { return 0; } +SymbolAssignment *ScriptParser::readAssignment(StringRef Name) { + StringRef Op = next(); + assert(Op == "=" || Op == "+="); + Expr E = readExpr(); + if (Op == "+=") + E = [=](uint64_t Dot) { return getSymbolValue(Name, Dot) + E(Dot); }; + auto *Cmd = new SymbolAssignment(Name, E); + Opt.Commands.emplace_back(Cmd); + return Cmd; +} + +// This is an operator-precedence parser to parse a linker +// script expression. +Expr ScriptParser::readExpr() { return readExpr1(readPrimary(), 0); } + // This is a part of the operator-precedence parser. This function // assumes that the remaining token stream starts with an operator. Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) { @@ -853,9 +859,6 @@ uint64_t static getConstant(StringRef S) { Expr ScriptParser::readPrimary() { StringRef Tok = next(); - if (Tok == ".") - return [](uint64_t Dot) { return Dot; }; - if (Tok == "(") { Expr E = readExpr(); expect(")"); @@ -914,9 +917,9 @@ Expr ScriptParser::readPrimary() { // Parse a symbol name or a number literal. uint64_t V = 0; if (Tok.getAsInteger(0, V)) { - if (!isValidCIdentifier(Tok)) + if (Tok != "." && !isValidCIdentifier(Tok)) setError("malformed number: " + Tok); - return [=](uint64_t Dot) { return getSymbolValue(Tok); }; + return [=](uint64_t Dot) { return getSymbolValue(Tok, Dot); }; } return [=](uint64_t Dot) { return V; }; } diff --git a/lld/test/ELF/linkerscript/linkerscript-locationcounter.s b/lld/test/ELF/linkerscript/linkerscript-locationcounter.s index ac31ca48412d..f70e78d87294 100644 --- a/lld/test/ELF/linkerscript/linkerscript-locationcounter.s +++ b/lld/test/ELF/linkerscript/linkerscript-locationcounter.s @@ -37,6 +37,9 @@ # RUN: . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); \ # RUN: .datasegmentalign : { *(.datasegmentalign) } \ # RUN: . = DATA_SEGMENT_END (.); \ +# RUN: . = 0x27000; \ +# RUN: . += 0x1000; \ +# RUN: .plusassign : { *(.plusassign) } \ # RUN: }" > %t.script # RUN: ld.lld %t --script %t.script -o %t2 # RUN: llvm-readobj -s %t2 | FileCheck %s @@ -296,6 +299,21 @@ # CHECK-NEXT: AddressAlignment: # CHECK-NEXT: EntrySize: # CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: +# CHECK-NEXT: Name: .plusassign +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x28000 +# 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 { \ @@ -399,3 +417,6 @@ nop .section .datasegmentalign, "a" .quad 0 + +.section .plusassign, "a" +.quad 0