[PATCH] D43468: [ELF] - Support "INSERT AFTER" statement.

Rafael Avila de Espindola via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 7 16:48:19 PST 2018


LGTM

George Rimar via Phabricator via llvm-commits
<llvm-commits at lists.llvm.org> writes:

> grimar updated this revision to Diff 136968.
> grimar added a comment.
>
> - Rebased.
> - Implemented test case as a script.
> - Adjusted code slightly.
>
>
> https://reviews.llvm.org/D43468
>
> Files:
>   ELF/Driver.cpp
>   ELF/LinkerScript.cpp
>   ELF/LinkerScript.h
>   ELF/ScriptParser.cpp
>   test/ELF/linkerscript/Inputs/insert-after.s
>   test/ELF/linkerscript/Inputs/insert-after.script
>   test/ELF/linkerscript/insert-after.test
>
> Index: test/ELF/linkerscript/insert-after.test
> ===================================================================
> --- test/ELF/linkerscript/insert-after.test
> +++ test/ELF/linkerscript/insert-after.test
> @@ -0,0 +1,29 @@
> +# REQUIRES: x86
> +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/insert-after.s -o %t1.o
> +
> +## Main linker script contains .text and .data sections. Here
> +## we check that can use INSERT AFTER to insert sections .foo.data
> +## and .foo.text at the right places.
> +
> +SECTIONS {
> +  .foo.data : { *(.foo.data) }
> +} INSERT AFTER .data;
> +
> +SECTIONS {
> +  .foo.text : { *(.foo.text) }
> +} INSERT AFTER .text;
> +
> +# RUN: ld.lld %t1.o -o %t1 --script %p/Inputs/insert-after.script --script %s
> +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
> +# CHECK:      Sections:
> +# CHECK-NEXT: Idx Name          Size      Address          Type
> +# CHECK-NEXT:   0               00000000 0000000000000000
> +# CHECK-NEXT:   1 .text         00000008 0000000000000000 TEXT DATA
> +# CHECK-NEXT:   2 .foo.text     00000008 0000000000000008 TEXT DATA
> +# CHECK-NEXT:   3 .data         00000008 0000000000000010 DATA
> +# CHECK-NEXT:   4 .foo.data     00000008 0000000000000018 DATA
> +
> +# RUN: not ld.lld %t1.o -o %t1 --script %s 2>&1 \
> +# RUN:   | FileCheck %s --check-prefix=ERR
> +# ERR-DAG: error: unable to INSERT AFTER .text: section not defined
> +# ERR-DAG: error: unable to INSERT AFTER .data: section not defined
> Index: test/ELF/linkerscript/Inputs/insert-after.script
> ===================================================================
> --- test/ELF/linkerscript/Inputs/insert-after.script
> +++ test/ELF/linkerscript/Inputs/insert-after.script
> @@ -0,0 +1,4 @@
> +SECTIONS {
> +  .text  : { *(.text.*) }
> +  .data  : { *(.data.*) }
> +}
> Index: test/ELF/linkerscript/Inputs/insert-after.s
> ===================================================================
> --- test/ELF/linkerscript/Inputs/insert-after.s
> +++ test/ELF/linkerscript/Inputs/insert-after.s
> @@ -0,0 +1,11 @@
> +.section .foo.text,"ax"
> +.quad 0
> +
> +.section .foo.data,"aw"
> +.quad 0
> +
> +.section .text.1,"ax"
> +.quad 0
> +
> +.section .data.1,"aw"
> +.quad 0
> Index: ELF/ScriptParser.cpp
> ===================================================================
> --- ELF/ScriptParser.cpp
> +++ ELF/ScriptParser.cpp
> @@ -436,6 +436,7 @@
>    Config->SingleRoRx = true;
>  
>    expect("{");
> +  std::vector<BaseCommand *> V;
>    while (!errorCount() && !consume("}")) {
>      StringRef Tok = next();
>      BaseCommand *Cmd = readProvideOrAssignment(Tok);
> @@ -445,8 +446,18 @@
>        else
>          Cmd = readOutputSectionDescription(Tok);
>      }
> -    Script->SectionCommands.push_back(Cmd);
> +    V.push_back(Cmd);
>    }
> +
> +  if (!atEOF() && consume("INSERT")) {
> +    consume("AFTER");
> +    std::vector<BaseCommand *> &Dest = Script->PendingInserts[next()];
> +    Dest.insert(Dest.end(), V.begin(), V.end());
> +    return;
> +  }
> +
> +  Script->SectionCommands.insert(Script->SectionCommands.end(), V.begin(),
> +                                 V.end());
>  }
>  
>  static int precedence(StringRef Op) {
> Index: ELF/LinkerScript.h
> ===================================================================
> --- ELF/LinkerScript.h
> +++ ELF/LinkerScript.h
> @@ -267,6 +267,9 @@
>    void processSectionCommands();
>    void declareSymbols();
>  
> +  // Used to handle INSERT AFTER statements.
> +  void processInsertCommands();
> +
>    // SECTIONS command list.
>    std::vector<BaseCommand *> SectionCommands;
>  
> @@ -285,6 +288,10 @@
>  
>    // A list of symbols referenced by the script.
>    std::vector<llvm::StringRef> ReferencedSymbols;
> +
> +  // Used to implement INSERT AFTER. Contains commands that needs
> +  // to be inserted into SECTIONS commands list.
> +  llvm::DenseMap<StringRef, std::vector<BaseCommand *>> PendingInserts;
>  };
>  
>  extern LinkerScript *Script;
> Index: ELF/LinkerScript.cpp
> ===================================================================
> --- ELF/LinkerScript.cpp
> +++ ELF/LinkerScript.cpp
> @@ -203,6 +203,25 @@
>    Cmd->Provide = false;
>  }
>  
> +// This method used to handle INSERT AFTER statement. Here we rebuild
> +// list of script commands to mix section inserted into.
> +void LinkerScript::processInsertCommands() {
> +  std::vector<BaseCommand *> V;
> +  for (BaseCommand *Base : SectionCommands) {
> +    V.push_back(Base);
> +    if (auto *Cmd = dyn_cast<OutputSection>(Base)) {
> +      std::vector<BaseCommand *> &InsertV = PendingInserts[Cmd->Name];
> +      V.insert(V.end(), InsertV.begin(), InsertV.end());
> +      InsertV.clear();
> +    }
> +  }
> +  for (std::pair<StringRef, std::vector<BaseCommand *>> &P : PendingInserts)
> +    if (!P.second.empty())
> +      error("unable to INSERT AFTER " + P.first + ": section not defined");
> +
> +  SectionCommands.swap(V);
> +}
> +
>  // Symbols defined in script should not be inlined by LTO. At the same time
>  // we don't know their final values until late stages of link. Here we scan
>  // over symbol assignment commands and create placeholder symbols if needed.
> Index: ELF/Driver.cpp
> ===================================================================
> --- ELF/Driver.cpp
> +++ ELF/Driver.cpp
> @@ -1081,6 +1081,10 @@
>    if (errorCount())
>      return;
>  
> +  // Now when we read all script files, we want to finalize order of linker
> +  // script commands, which can be not yet final because of INSERT commands.
> +  Script->processInsertCommands();
> +
>    // We want to declare linker script's symbols early,
>    // so that we can version them.
>    // They also might be exported if referenced by DSOs.
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list