This is an archive of the discontinued LLVM Phabricator instance.

[ELF] - Add support for access to most of synthetic sections from linkerscript.
ClosedPublic

Authored by grimar on Nov 23 2016, 5:04 AM.

Details

Summary

This is important for FreeBSD EFI bootloaders one of which has next script:

  .sdata        : {
    *(.got.plt .got)
...
  }

So it wants to place got.plt and got into single section of name .sdata.
That was not supported before as there was no way to get access to
synthetic sections from script.

To do that we need to add them early to Symtab<ELFT>::X->Sections.
That involves next problems:

  1. Not all sections are required in output finally. For example we do not need

to emit got content when it has no entries. Patch solves that in next way:
after script do its job of layouting, removeUnusedSynthetics() is called.
Main intention to check the condition for each synthetic and remove it from output
if it is not needed.

  1. Adding sections early involves possible change in ordering. That is why this patch

does not do support for all sections at ones. Otherwise too many tests fill fail (up to 150).
It still breaks order for .eh_frame, that is why few relative testcases were fixes.
I believe that is not a problem.

If we land this - we might be able to add all rest sections in next patches
and get rid off addPredefinedSections() fully I think.

Diff Detail

Repository
rL LLVM

Event Timeline

grimar updated this revision to Diff 79053.Nov 23 2016, 5:04 AM
grimar retitled this revision from to [ELF] - Add support for access to most of synthetic sections from linkerscript..
grimar updated this object.
grimar added reviewers: ruiu, rafael, evgeny777.
grimar added subscribers: llvm-commits, grimar, davide, emaste.
evgeny777 added inline comments.Nov 23 2016, 5:31 AM
ELF/Writer.cpp
230 ↗(On Diff #79053)

This looks better

auto add = [](InputSection<ELFT> *IS) {
  Symtab<ELFT>::X->Sections.push_back(IS);
  return IS;
};
255 ↗(On Diff #79053)
In<ELFT>::Interp = add(createInterpSection<ELFT>());
723 ↗(On Diff #79053)

Why are you checking IS for nullptr?

883 ↗(On Diff #79053)

Why are you checking for null?

889 ↗(On Diff #79053)

Looks like you're removing all sections starting from unused synthetic till the end of the input section array. May be you actually wanted to use std::remove() ?

grimar updated this revision to Diff 79067.Nov 23 2016, 6:43 AM
  • Addressed review comments.
ELF/Writer.cpp
230 ↗(On Diff #79053)

Unfortunately this will not work. You can not assign base class pointer to derived.
I applied the idea of your suggestion though.

723 ↗(On Diff #79053)

Forgot to remove after experiments, thanks.

883 ↗(On Diff #79053)

Because Symtab<ELFT>::X->Sections contains all sections, not only synthetic.
And that works like optimization.

I am iterating from the end to start and stop doing that when met non-synthetic section,
which will be null after cast.

889 ↗(On Diff #79053)

It is a mistake definetely. Wanted to use std::erase(Iterator) form, like below.

grimar updated this revision to Diff 79102.Nov 23 2016, 9:02 AM
  • Fixed compilation error under FreeBSD.
ruiu added inline comments.Nov 23 2016, 11:42 AM
ELF/SyntheticSections.h
35 ↗(On Diff #79102)

isPresent sound a bit odd to me, because as soon as you instantiate objects, they are present. How about empty?

ELF/Writer.cpp
878 ↗(On Diff #79102)

removeUnusedSyntheticSections because we have other synthetic things such as synthetic symbols.

881–882 ↗(On Diff #79102)

Use llvm::reverse.

230 ↗(On Diff #79053)

It seems unnecessarily complicated. I'd just remove this function and inline it.

255 ↗(On Diff #79053)

For example, I'd write

In<ELFT>::Interp = createInterpSection<EFLT>();
Symtab<ELFT>::X->Sections.push_back(In<ELFT>::Interp);
grimar updated this revision to Diff 79202.Nov 24 2016, 2:28 AM
  • Addressed review comments.
grimar added inline comments.Nov 24 2016, 2:29 AM
ELF/SyntheticSections.h
35 ↗(On Diff #79102)

Done.

ELF/Writer.cpp
878 ↗(On Diff #79102)

Done.

881–882 ↗(On Diff #79102)

Done.

230 ↗(On Diff #79053)

I did that though I find this a bit bulky code. I think we may want to refactor it in this way separatelly.

ruiu added inline comments.Nov 24 2016, 9:05 AM
ELF/SyntheticSections.h
35 ↗(On Diff #79102)

Well, empty should return true if it is empty. Your functions return true if it is not empty.

grimar updated this revision to Diff 79242.Nov 24 2016, 9:35 AM
  • Addressed review comments.
  • Removed 2 excessive checks.
ruiu added inline comments.Nov 24 2016, 9:45 AM
ELF/SyntheticSections.cpp
1589–1590 ↗(On Diff #79242)

I don't understand these conditions. Is this the same as the code below?

if (!In<ELFT>::Verdef)
  return true;
return In<ELFT>::VerNeed->empty();
grimar added inline comments.Nov 24 2016, 9:55 AM
ELF/SyntheticSections.cpp
1589–1590 ↗(On Diff #79242)

It is the same as:

template <class ELFT> bool VersionTableSection<ELFT>::empty() const {
  return !In<ELFT>::VerDef && In<ELFT>::VerNeed->empty();
}
ruiu added inline comments.Nov 24 2016, 9:57 AM
ELF/SyntheticSections.cpp
1589–1590 ↗(On Diff #79242)

So, you meant VersionTable is empty if

  • we have a VerDef section,
  • and VerNeed is empty.

But why?

grimar added inline comments.Nov 24 2016, 10:00 AM
ELF/SyntheticSections.cpp
1589–1590 ↗(On Diff #79242)

Mmm, no, it is empty if

  • we do not have Verdef
  • and VerNeed is empty.
ruiu added inline comments.Nov 24 2016, 10:02 AM
ELF/SyntheticSections.cpp
1589–1590 ↗(On Diff #79242)

Then

if (In<ELFT>::VerDef == nullptr)
  return true;
return In<ELFT>::VerNeed->empty();

This is the same code as I wrote in the first comment.

grimar added inline comments.Nov 24 2016, 10:04 AM
ELF/SyntheticSections.cpp
1589–1590 ↗(On Diff #79242)

No, because your code will return empty if we do not have Verdef but have entries in VerNeed

ruiu added inline comments.Nov 24 2016, 10:06 AM
ELF/SyntheticSections.cpp
1589–1590 ↗(On Diff #79242)

I don't know what you are doing here is right, I need to take a look at the original code. Anyways, can you rewrite this code so that it is easy to understand?

grimar added inline comments.Nov 24 2016, 10:13 AM
ELF/SyntheticSections.cpp
1589–1590 ↗(On Diff #79242)

Sure. Just what would you prefer:

template <class ELFT> bool VersionTableSection<ELFT>::empty() const {
  if (!In<ELFT>::VerDef)
    return In<ELFT>::VerNeed->empty();
  return false;
}

or

template <class ELFT> bool VersionTableSection<ELFT>::empty() const {
  return !In<ELFT>::VerDef && In<ELFT>::VerNeed->empty();
}
grimar added inline comments.Nov 24 2016, 10:25 AM
ELF/SyntheticSections.cpp
1589–1590 ↗(On Diff #79242)

I think I know what confused you.
You wrote:

if (!In<ELFT>::Verdef)
  return true;

but this is not the same as

if (!In<ELFT>::Verdef->empty())
  return true;
grimar added inline comments.Nov 24 2016, 1:31 PM
ELF/SyntheticSections.cpp
1589–1590 ↗(On Diff #79242)

Yes, sure. That where I took the condition from initially.

ruiu accepted this revision.Nov 24 2016, 3:08 PM
ruiu edited edge metadata.

LGTM

ELF/SyntheticSections.cpp
1589–1590 ↗(On Diff #79242)

OK, then this is consistent. Please replace it with the one line code.

This revision is now accepted and ready to land.Nov 24 2016, 3:08 PM
This revision was automatically updated to reflect the committed changes.