This is an archive of the discontinued LLVM Phabricator instance.

[ELF] Linkerscript: eliminate LayoutInputSection
ClosedPublic

Authored by evgeny777 on Aug 22 2016, 6:57 AM.

Details

Reviewers
ruiu
rafael
Summary

Current implementation of LayoutInputSection relies on LLVM-style casting to InputSection<ELFT>, which is not a base class for it. The following statements will be successfully compiled and executed:

InputSection<ELFT> *I = ...;
LayoutInputSection<ELFT> *L = cast<LayoutInputSection<ELFT>>(I);

And the following one cannot compile:

LayoutInputSection<ELFT> *L = static_cast<LayoutInputSection<ELFT> *>(I);

This patch eliminates LayoutInputSection by saving pointer to preceding input section in SymbolAssignment class.

Diff Detail

Event Timeline

evgeny777 updated this revision to Diff 68855.Aug 22 2016, 6:57 AM
evgeny777 retitled this revision from to [ELF] Linkerscript: eliminate LayoutInputSection.
evgeny777 updated this object.
evgeny777 added a reviewer: ruiu.
evgeny777 set the repository for this revision to rL LLVM.
evgeny777 added a project: lld.
evgeny777 added subscribers: grimar, ikudrin, llvm-commits.
grimar added inline comments.Aug 22 2016, 7:57 AM
ELF/LinkerScript.cpp
341

I would reorder conditions to avoid nesting and ++ItCmd in multiple places:

auto AddSuccessors = [&](InputSectionData *D) {
  for (; I != Cmd->Commands.end(); ++I) {
    auto *AssignCmd = dyn_cast<SymbolAssignment>(I->get());
    if (!AssignCmd)
      continue;
    if (D != AssignCmd->GoesAfter)
      break;

    uintX_t Value = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA();
    if (AssignCmd->Name == ".") {
      // Update to location counter means update to section size.
      Off = Value;
      Sec->setSize(Off);
      continue;
    }

    if (DefinedSynthetic<ELFT> *Sym =
            cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) {
      Sym->Section = OutSec;
      Sym->Value = Value;
    }
  }
};
348

Asignment in argument ? May be better separate it ?

Off = Value;
Sec->setSize(Value);
ruiu added inline comments.Aug 29 2016, 5:28 PM
ELF/InputSection.h
34–37

Move this after public section.

46–48

Seems Compressed is also used by the garbage collector.

58–59

Now the "Base" class has a base class? I seems to me that it's too object-oriented-ish, but let's see how it works.

ELF/LinkerScript.cpp
212–213

reinterpret_cast<OutputSectionBase<ELFT> *>(-1ULL)?

338

It needs a comment.

evgeny777 added inline comments.Aug 30 2016, 3:35 AM
ELF/InputSection.h
58–59

Unfortunately SymbolAssignment is not (and shouldn't be) template class.
Also I think that moving data which doesn't depend on template parameter ELFT to the base non-template class should slightly reduce image size.

evgeny777 updated this revision to Diff 69663.Aug 30 2016, 4:01 AM
evgeny777 removed rL LLVM as the repository for this revision.

Addressed review comments + simplified InputSectionData.

rafael added inline comments.
ELF/LinkerScript.cpp
353

Is this correctly handling the case of

. = . + 4
foo = .

That is, the virtual address of a symbol is not immediately after a inputsection?

Yeah. See lines 294-295 in LinkerScript.cpp. Also, please take a look at linkerscript-symbols-synthetic.s

rafael accepted this revision.Aug 30 2016, 7:18 AM
rafael added a reviewer: rafael.

LGTM.

I think the code can be simplified further (I am experimenting with it), but this is a step in the right direction.

Thanks!

ELF/InputSection.h
46

Move the "Usef for garbage collection" comment to the same line as Live or add a newline after it.

This revision is now accepted and ready to land.Aug 30 2016, 7:18 AM
ruiu added inline comments.Aug 30 2016, 1:02 PM
ELF/InputSection.h
33

Please write a comment for this class. It should describe why we need this class (because we want to have a base class which is not a template class).

46

Yup. That's what I meant.

ELF/LinkerScript.cpp
209

Needs a comment. What are you trying to do with this loop?

318

Thank you for the comment. I think I now understand what it does.

evgeny777 updated this revision to Diff 69821.Aug 31 2016, 3:24 AM
evgeny777 edited edge metadata.

Rebased and addressed review comments

ruiu accepted this revision.Aug 31 2016, 8:04 AM
ruiu edited edge metadata.

LGTM with this change.

ELF/LinkerScript.cpp
214–217

Setting -1 to the pointer to record whether an input section is added or not is an unintended use of the pointer and pretty confusing. Please use a DenseSet to uniquefy.

evgeny777 added inline comments.Aug 31 2016, 8:27 AM
ELF/LinkerScript.cpp
214–217

This will cause growth of memory consumption and slightly slow down things. May be using some fake output section is better?

OutputSectionBase<ELFT> FakeSec;
for (InputSectionBase<ELFT> *S : V)
      if (!S->OutSec) {
         Ret.push_back(S);
         S->OutSec = &FakeSec;
      }
ruiu added inline comments.Aug 31 2016, 9:05 AM
ELF/LinkerScript.cpp
214–217

That also has a prolonged side effect -- the assigned pointers will be visible from outside after returning from this function even though they are not valid pointers. That confuses readers as to why we needed to assign pointers. I was actually wondering. I don't think this is a performance critical path (linker scripts are not that fast anyways). So I'd use a map.

evgeny777 closed this revision.Sep 1 2016, 4:44 AM