[lld] r277165 - [ELF] - Linkerscript: implemented SIZEOF(section)

Sean Silva via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 30 20:01:02 PDT 2016


What happens for something like:

```
SECTIONS {
  .aaa : {
    *(.aaa);
    . = . + SIZEOF(.aaa);
  }
}
```

Can you add a test case? (or modify the existing one)


-- Sean Silva



On Fri, Jul 29, 2016 at 9:18 AM, George Rimar via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: grimar
> Date: Fri Jul 29 11:18:47 2016
> New Revision: 277165
>
> URL: http://llvm.org/viewvc/llvm-project?rev=277165&view=rev
> Log:
> [ELF] - Linkerscript: implemented SIZEOF(section)
>
> SIZEOF(section)
> Return the size in bytes of the named section, if that section has been
> allocated.
>
> SIZEOF(section) often used in scripts. Few examples from the wild:
>
> https://github.com/chipKIT32/pic32-Arduino-USB-Bootloader-original/blob/master/boot-linkerscript.ld
>
> https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/gba_cart.ld
>
> Patch implements it.
>
> Differential revision: https://reviews.llvm.org/D22915
>
> Added:
>     lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.s
> Modified:
>     lld/trunk/ELF/LinkerScript.cpp
>     lld/trunk/ELF/LinkerScript.h
>     lld/trunk/ELF/Writer.cpp
>
> Modified: lld/trunk/ELF/LinkerScript.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=277165&r1=277164&r2=277165&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/LinkerScript.cpp (original)
> +++ lld/trunk/ELF/LinkerScript.cpp Fri Jul 29 11:18:47 2016
> @@ -138,9 +138,10 @@ static bool compareByName(InputSectionBa
>  }
>
>  template <class ELFT>
> -std::vector<OutputSectionBase<ELFT> *>
> -LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
> -  std::vector<OutputSectionBase<ELFT> *> Ret;
> +void LinkerScript<ELFT>::createSections(
> +    std::vector<OutputSectionBase<ELFT> *> *Out,
> +    OutputSectionFactory<ELFT> &Factory) {
> +  OutputSections = Out;
>
>    for (auto &P : getSectionMap()) {
>      std::vector<InputSectionBase<ELFT> *> Sections;
> @@ -157,7 +158,7 @@ LinkerScript<ELFT>::createSections(Outpu
>      if (I->Sort)
>        std::stable_sort(Sections.begin(), Sections.end(),
> compareByName<ELFT>);
>      for (InputSectionBase<ELFT> *S : Sections)
> -      addSection(Factory, Ret, S, OutputName);
> +      addSection(Factory, *Out, S, OutputName);
>    }
>
>    // Add all other input sections, which are not listed in script.
> @@ -165,17 +166,15 @@ LinkerScript<ELFT>::createSections(Outpu
>         Symtab<ELFT>::X->getObjectFiles())
>      for (InputSectionBase<ELFT> *S : F->getSections())
>        if (!isDiscarded(S) && !S->OutSec)
> -        addSection(Factory, Ret, S, getOutputSectionName(S));
> +        addSection(Factory, *Out, S, getOutputSectionName(S));
>
>    // Remove from the output all the sections which did not meet
>    // the optional constraints.
> -  return filter(Ret);
> +  filter();
>  }
>
>  // Process ONLY_IF_RO and ONLY_IF_RW.
> -template <class ELFT>
> -std::vector<OutputSectionBase<ELFT> *>
> -LinkerScript<ELFT>::filter(std::vector<OutputSectionBase<ELFT> *>
> &Sections) {
> +template <class ELFT> void LinkerScript<ELFT>::filter() {
>    // In this loop, we remove output sections if they don't satisfy
>    // requested properties.
>    for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
> @@ -186,10 +185,10 @@ LinkerScript<ELFT>::filter(std::vector<O
>      if (Cmd->Constraint == ConstraintKind::NoConstraint)
>        continue;
>
> -    auto It = llvm::find_if(Sections, [&](OutputSectionBase<ELFT> *S) {
> +    auto It = llvm::find_if(*OutputSections, [&](OutputSectionBase<ELFT>
> *S) {
>        return S->getName() == Cmd->Name;
>      });
> -    if (It == Sections.end())
> +    if (It == OutputSections->end())
>        continue;
>
>      OutputSectionBase<ELFT> *Sec = *It;
> @@ -198,9 +197,8 @@ LinkerScript<ELFT>::filter(std::vector<O
>      bool RW = (Cmd->Constraint == ConstraintKind::ReadWrite);
>
>      if ((RO && Writable) || (RW && !Writable))
> -      Sections.erase(It);
> +      OutputSections->erase(It);
>    }
> -  return Sections;
>  }
>
>  template <class ELFT>
> @@ -396,6 +394,15 @@ template <class ELFT> bool LinkerScript<
>    return !Opt.PhdrsCommands.empty();
>  }
>
> +template <class ELFT>
> +typename ELFT::uint LinkerScript<ELFT>::getOutputSectionSize(StringRef
> Name) {
> +  for (OutputSectionBase<ELFT> *Sec : *OutputSections)
> +    if (Sec->getName() == Name)
> +      return Sec->getSize();
> +  error("undefined section " + Name);
> +  return 0;
> +}
> +
>  // Returns indices of ELF headers containing specific section, identified
>  // by Name. Each index is a zero based number of ELF header listed within
>  // PHDRS {} script block.
> @@ -838,6 +845,22 @@ static uint64_t getSymbolValue(StringRef
>    return 0;
>  }
>
> +static uint64_t getSectionSize(StringRef Name) {
> +  switch (Config->EKind) {
> +  case ELF32LEKind:
> +    return Script<ELF32LE>::X->getOutputSectionSize(Name);
> +  case ELF32BEKind:
> +    return Script<ELF32BE>::X->getOutputSectionSize(Name);
> +  case ELF64LEKind:
> +    return Script<ELF64LE>::X->getOutputSectionSize(Name);
> +  case ELF64BEKind:
> +    return Script<ELF64BE>::X->getOutputSectionSize(Name);
> +  default:
> +    llvm_unreachable("unsupported target");
> +  }
> +  return 0;
> +}
> +
>  SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
>    StringRef Op = next();
>    assert(Op == "=" || Op == "+=");
> @@ -946,6 +969,12 @@ Expr ScriptParser::readPrimary() {
>      expect(")");
>      return [](uint64_t Dot) { return alignTo(Dot, Target->PageSize); };
>    }
> +  if (Tok == "SIZEOF") {
> +    expect("(");
> +    StringRef Name = next();
> +    expect(")");
> +    return [=](uint64_t Dot) { return getSectionSize(Name); };
> +  }
>
>    // Parse a symbol name or a number literal.
>    uint64_t V = 0;
>
> Modified: lld/trunk/ELF/LinkerScript.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=277165&r1=277164&r2=277165&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/LinkerScript.h (original)
> +++ lld/trunk/ELF/LinkerScript.h Fri Jul 29 11:18:47 2016
> @@ -128,8 +128,8 @@ template <class ELFT> class LinkerScript
>    typedef typename ELFT::uint uintX_t;
>
>  public:
> -  std::vector<OutputSectionBase<ELFT> *>
> -  createSections(OutputSectionFactory<ELFT> &Factory);
> +  void createSections(std::vector<OutputSectionBase<ELFT> *> *Out,
> +                      OutputSectionFactory<ELFT> &Factory);
>
>    std::vector<PhdrEntry<ELFT>>
>    createPhdrs(ArrayRef<OutputSectionBase<ELFT> *> S);
> @@ -140,6 +140,7 @@ public:
>    int compareSections(StringRef A, StringRef B);
>    void addScriptedSymbols();
>    bool hasPhdrsCommands();
> +  uintX_t getOutputSectionSize(StringRef Name);
>
>  private:
>    std::vector<std::pair<StringRef, const InputSectionDescription *>>
> @@ -151,13 +152,13 @@ private:
>    // "ScriptConfig" is a bit too long, so define a short name for it.
>    ScriptConfiguration &Opt = *ScriptConfig;
>
> -  std::vector<OutputSectionBase<ELFT> *>
> -  filter(std::vector<OutputSectionBase<ELFT> *> &Sections);
> +  void filter();
>
>    int getSectionIndex(StringRef Name);
>    std::vector<size_t> getPhdrIndices(StringRef SectionName);
>    size_t getPhdrIndex(StringRef PhdrName);
>
> +  std::vector<OutputSectionBase<ELFT> *> *OutputSections;
>    uintX_t Dot;
>  };
>
>
> Modified: lld/trunk/ELF/Writer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=277165&r1=277164&r2=277165&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/Writer.cpp (original)
> +++ lld/trunk/ELF/Writer.cpp Fri Jul 29 11:18:47 2016
> @@ -48,7 +48,7 @@ private:
>
>    void copyLocalSymbols();
>    void addReservedSymbols();
> -  std::vector<OutputSectionBase<ELFT> *> createSections();
> +  void createSections();
>    void forEachRelSec(
>        std::function<void(InputSectionBase<ELFT> &, const typename
> ELFT::Shdr &)>
>            Fn);
> @@ -233,9 +233,11 @@ template <class ELFT> void Writer<ELFT>:
>    CommonInputSection<ELFT> Common(getCommonSymbols<ELFT>());
>    CommonInputSection<ELFT>::X = &Common;
>
> -  OutputSections = ScriptConfig->HasContents
> -                       ? Script<ELFT>::X->createSections(Factory)
> -                       : createSections();
> +  if (ScriptConfig->HasContents)
> +    Script<ELFT>::X->createSections(&OutputSections, Factory);
> +  else
> +    createSections();
> +
>    finalizeSections();
>    if (HasError)
>      return;
> @@ -635,10 +637,7 @@ void Writer<ELFT>::forEachRelSec(
>    }
>  }
>
> -template <class ELFT>
> -std::vector<OutputSectionBase<ELFT> *> Writer<ELFT>::createSections() {
> -  std::vector<OutputSectionBase<ELFT> *> Result;
> -
> +template <class ELFT> void Writer<ELFT>::createSections() {
>    for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
>         Symtab.getObjectFiles()) {
>      for (InputSectionBase<ELFT> *C : F->getSections()) {
> @@ -650,11 +649,10 @@ std::vector<OutputSectionBase<ELFT> *> W
>        bool IsNew;
>        std::tie(Sec, IsNew) = Factory.create(C, getOutputSectionName(C));
>        if (IsNew)
> -        Result.push_back(Sec);
> +        OutputSections.push_back(Sec);
>        Sec->addSection(C);
>      }
>    }
> -  return Result;
>  }
>
>  // Create output section objects and add them to OutputSections.
>
> Added: lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.s?rev=277165&view=auto
>
> ==============================================================================
> --- lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.s (added)
> +++ lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.s Fri Jul 29
> 11:18:47 2016
> @@ -0,0 +1,53 @@
> +# REQUIRES: x86
> +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
> +
> +# RUN: echo "SECTIONS { \
> +# RUN:   .aaa         : { *(.aaa) } \
> +# RUN:   .bbb         : { *(.bbb) } \
> +# RUN:   .ccc         : { *(.ccc) } \
> +# RUN:   _aaa = SIZEOF(.aaa); \
> +# RUN:   _bbb = SIZEOF(.bbb); \
> +# RUN:   _ccc = SIZEOF(.ccc); \
> +# RUN: }" > %t.script
> +# RUN: ld.lld -o %t1 --script %t.script %t
> +# RUN: llvm-objdump -t -section-headers %t1 | FileCheck %s
> +# CHECK:      Sections:
> +# CHECK-NEXT:  Idx Name          Size      Address          Type
> +# CHECK-NEXT:    0               00000000 0000000000000000
> +# CHECK-NEXT:    1 .aaa          00000008 0000000000000120 DATA
> +# CHECK-NEXT:    2 .bbb          00000010 0000000000000128 DATA
> +# CHECK-NEXT:    3 .ccc          00000018 0000000000000138 DATA
> +# CHECK:      SYMBOL TABLE:
> +# CHECK-NEXT:  0000000000000000 *UND* 00000000
> +# CHECK-NEXT:  0000000000000150 .text 00000000 _start
> +# CHECK-NEXT:  0000000000000008 *ABS* 00000000 _aaa
> +# CHECK-NEXT:  0000000000000010 *ABS* 00000000 _bbb
> +# CHECK-NEXT:  0000000000000018 *ABS* 00000000 _ccc
> +
> +## Check that we error out if trying to get size of
> +## section that does not exist.
> +# RUN: echo "SECTIONS { \
> +# RUN:   .aaa         : { *(.aaa) } \
> +# RUN:   .bbb         : { *(.bbb) } \
> +# RUN:   .ccc         : { *(.ccc) } \
> +# RUN:   _aaa = SIZEOF(.foo); \
> +# RUN: }" > %t.script
> +# RUN: not ld.lld -o %t1 --script %t.script %t 2>&1 \
> +# RUN:  | FileCheck -check-prefix=ERR %s
> +# ERR: undefined section .foo
> +
> +.global _start
> +_start:
> + nop
> +
> +.section .aaa,"a"
> + .quad 0
> +
> +.section .bbb,"a"
> + .quad 0
> + .quad 0
> +
> +.section .ccc,"a"
> + .quad 0
> + .quad 0
> + .quad 0
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160730/34a7ed7e/attachment.html>


More information about the llvm-commits mailing list