On 05/23/18 03:57 PM, 'Peter Collingbourne' via Generic System V Application Binary Interface wrote:
> Some existing tools that create object files (GNU objcopy, ld.bfd -r, ld.gold -r, ld.lld -r, but not llvm-objcopy at present) already set sh_link to 0 in this case for sections that they do not recognize, and I would propose that the generic ABI require this behaviour. We can do this, for example, by adding this language to the "Rules for Linking Unrecognized Sections":
I need to think about the rest of this a bit before commenting,
but the above immediately caught my eye. Setting sh_link to 0 for
sections you don't understand causes problems like this one,
that plagued Solaris for a couple of years until we got around to
root causing it and seeking upstream help:
https://sourceware.org/bugzilla/show_bug.cgi?id=19938
The gABI has rules that lets programs manipulate objects safely
without having to understand all their ABI-specific details. I wrote
this in the aftermath of the above bug, but they've been around since
the gABI was formed, and many utilities depend on it.
http://www.linker-aliens.org/blogs/ali/entry/how_to_strip_an_elf/
Please don't do that --- it will break a lot of things.
> A tool that modifies an object file must either update the SHT_ADDRSIG
> section (if it is safe to do so) or set the sh_link field to 0. A
> linker would then be able to ignore SHT_ADDRSIG sections whose
> sh_link is 0.
Even if the objection above wasn't a factor, I don't really follow how
an sh_link of 0 can be interpreted as meaning that the linker is
free to ignore the section. There's a circular problem here --- since
the section isn't understood, the meaning of its sh_link is also
not understood. If something like this ends up in the gABI, all the
gABI conforming ELF platforms will have to learn about the section.
- Ali
--
You received this message because you are subscribed to the Google Groups "Generic System V Application Binary Interface" group.
To unsubscribe from this group and stop receiving emails from it, send an email to generic-abi...@googlegroups.com.
To post to this group, send email to gener...@googlegroups.com.
Visit this group at https://groups.google.com/group/generic-abi.
For more options, visit https://groups.google.com/d/optout.
On 05/23/18 03:57 PM, 'Peter Collingbourne' via Generic System V Application Binary Interface wrote:
> I would like to propose an extension to the generic ABI that allows for object files to specify whether each symbol is address-significant. If a symbol is address-significant, it means that the program relies on whichever section the symbol resolves to having a distinct address from other sections referred to by address-significant symbols. This means for example that a linker cannot apply identical-code folding to merge two sections which are referred to by address-significant symbols.
As I said, I want to sleep on this a bit before getting into a
detailed discussion. However, I have a question to ask that would
help me in understanding what you're going for.
Would it work for you if we reversed the sense of this feature, so
that the default is not to merge untagged things, and then to tag
those that can be merged?
-----
I think that you're saying that gold has an optimization that
eliminates duplicate copies of code, by throwing out the duplicates
and having all those symbols reference the one remaining instance.
Gold has heuristics for knowing when this is safe, but sometimes
it's wrong and merges things that need to have unique addresses.
(I'll guess: Code that compares addresses to decide if 2 function
pointers reference the same thing needs those functions to be
"address significant"). It would be better if the compiler
labeled this stuff, and link-editors didn't guess about it.
I ask, because your feature sounds a lot like the existing SHF_MERGE
section flag, when combined with SHF_STRINGS, except that it has the
opposite sense (merging has to be requested rather than disabled). As
such, my first reaction to your proposal was to wonder why that existing
SHF_MERGE mechanism couldn't be used to handle this. Mergable functions
could be put in a .text section with SHF_MERGE|SHF_EXECINSTR, to identify
things that can be combined, and address-significant things would go into
a normal .text section that does not have these flags set. Naive
link-editors would not be affected by that, and would produce valid
results, just a bit larger than otherwise. New link-editors would
have the option of merging.
That's not a counter proposal yet --- I don't think I understand
what you're getting at well enough to know if it's a good idea, but
I mention it so that you'll understand why I asked the question above.
On 05/23/18 05:07 PM, 'Peter Collingbourne' via Generic System V Application Binary Interface wrote:
> The proposed rule would not break the sh_link for either of those, as long as they do not link to SHT_SYMTAB.
But why shouldn't they link to SHT_SYMTAB? That's a very big restriction.
Symbol tables are the most common targets of sh_link. The odds are better than
not that any new section type wants to reference a symbol table. We don't
want to preclude that.
> Sorry, when I said "linker" above I was referring to a linker that
> understands SHT_ADDRSIG.
OK, that helps. I guess that you are concerned about the
following scenario:
- You put a new gold in the world that understands this
feature.
- You get the compilers to use it.
- You can't ensure that the binutils or other packages on some
systems that see the results of these new features will be
SHT_ADDRSIG aware, so you might encounter objects that have
been corrupted by objcopy (to pick one possibility). You
don't want to error out in this case.
That's a real problem, but it's a temporary one, because the rest of the
tools will catch up fairly quickly. And while ignoring SHT_ADDRSIG in this
case might be fine, that might not be true for other new sections. I would
prefer to solve this without permanently complicating the gABI.
I'll suggest that this could be solved by having gold ignore SHT_ADDRSIG
sections with sh_link set to 0, for a respectful period of time (a year
or 2, or whatever), until the rest of the toolchain catches up, and then
later removing that implementation loophole from the code. There's no
reason to have the gABI require that --- it's just a temporary implementation
detail used to bootstrap a new feature.
If I'm understanding the above, a symbol is only address-insignificant
when:
- Its address isn't taken
- It does not emerge from the link-edit as a global symbol.
I could make it even harder on the compiler, by moving f1() and f2()
into yet another separately linked shared object. But then, I guess the
compiler would still decide that f1() and f2() are address significant,
based on the fact that they are exported as global symbols from a shared
object?
At least on Solaris, this last case is particularly opaque, because
it's the address of the PLT getting compared. f1() and f2() would not
compare as equal even if they really are one function body in their
shared object, because they'd each have a different PLT in the main
program, and therefore, g() would be passed 2 different addresses.
The rule about not emerging as a global symbol might not be necessary.
Tricky stuff...
On 05/23/18 15:57, 'Peter Collingbourne' via Generic System V Application Binary Interface wrote:
> The proposal is that we introduce a new section type, SHT_ADDRSIG. This section would contain a ULEB128-encoded sequence of symbol table indexes corresponding to address-significant symbols. If the section is not present in an object file, all symbols in the object file are treated as address significant. For compatibility with existing tools, the section would be marked with a flag SHF_EXCLUDE to ensure that it is dropped by linkers which do not recognize the section.
>
> Also, the section's sh_link field would be set to the section index of the .symtab section. Similarly to relocation sections, this encodes that the section references symbol table entries by index. A tool that modifies an object file must either update the SHT_ADDRSIG section (if it is safe to do so) or set the sh_link field to 0. A linker would then be able to ignore SHT_ADDRSIG sections whose sh_link is 0.
I've had a chance to think about this, and to discuss it with
my partner in ELF crime, Rod Evans. We're generally supportive
of the idea of giving compilers a way to tag reference symbols to
say that they must point at a unique address. We have some thoughts
about the specifics, while I'll list below. Think of this as more
grist for the mill.
I'm going to ignore the sh_link/sh_info discussion here, and
will close the loop on that separately.
-----
Excluding the part about sh_link of 0, having the sh_link for this
section point at the symbol table it corresponds to is clearly the
right thing.
-----
I'm puzzled about the SHF_EXCLUDE idea. Yes, it will let old
linkers ignore the section, but it also requires new linkers
to ignore it. Are you proposing that new linkers will recognize
an SHT_ADDRSIG, and ignore an SHF_EXCLUDE? That seems problematic.
-----
To summarize:
- Generally for doing something in this ADDRSIG area
- Not in love with the ULEB128 idea
- The idea of an array of symbol indexes is OK, but we'd
like you to consider the flags section idea --- it's
useful beyond just the problem you're trying to solve.
I'd like to hear some other voices --- any of this is a fairly
large change, and general agreement is needed. It's clearly a bit
early to standardize, but I think you're on a track that will
get you there.
Thanks for the opportunity to comment.
- Ali
Coming back around on the sh_link/sh_info aspect of this
discussion...
On 05/23/18 08:53 PM, 'Peter Collingbourne' via Generic System V Application Binary Interface wrote:
> That *might* work for this specific section, but the transition period could be much longer than a year or two (one feature that springs to mind is .gnu.linkonce, which was superseded by COMDAT in the early 2000's but is still supported by the GNU linkers and somewhat by lld, in part because glibc still uses it on i386). On the other hand, there also seem to be good reasons to adopt the rule that I've proposed.
That really only says that transitions can take a long time,
unless something or someone is able to apply some back pressure
on the issue to flush things out.
The problem with gnu.linkonce as an example is that COMDAT hasn't fully
superseded it. My understanding is that the dwarf sections are not
COMDATified, which means that even when comdat is used, there's
some linkonce handling required. That was discussed here in April:
https://groups.google.com/forum/#!topic/generic-abi/A-1rbP8hFCA
I hold out hope that linkonce will die a richly deserved death, as I
did (literally) a decade ago, but even now, it's not going to be soon.
I'm not really sure how much we need this though --- I sure hope we're not
going to be adding *too* many new sections that reference symbol tables.
This ought to be a fairly rare thing, and maybe something that can just
be handled case by case.
No matter, I'm content for this to be an implementation quirk.
I'd encourage you to stop using it the moment you can safely
remove its use.
- Ali
I like not making it mandatory because it allows people to implement
it as they find it useful, rather than having an external timeline
imposed on them by some other group. It's in the spirit of SHF_MERGE,
which provides an option, but not a requirement.
- Ali
--
Thanks Peter. I used SHF_EXCLUDE incorrectly in my proposal. As you point out,
we wouldn't want the semantics for SHF_EXCLUDE. What I actually wanted was a
flag to indicate whether any tools that rewrite the symbol table need to consume
and rewrite the symbol metadata section or whether a simple rule like "choose
the prevailing symbol" is appropriate. My idea was that we could have a section
with a common structure and a set of default rules:
1. If a symbol is stripped then strip the corresponding entry.2. Choose the metadata for the prevailing symbols when combining objects.
However, for section contents that are not handled correctly by these default rules we
would set a flag on the section which would indicate to the tools that they
are required to rewrite the section if they are editing the associated symbol
table. In this case e.g. "ld -r" would have to consume the attributes in the
input symbol attributes sections and create an appropriate symbol metadata
section that matches the .symtab in the output.
Your second set of objections about what to do regarding empty entries is
difficult. In fact I think it would be better to define such a section as a set
of index and payload pairs rather than a sparse array which would both reduce
the section size and sidestep those problems.
Having thought about your response it does seem that the different use cases
will not combine naturally. Therefore, I agree that it would be better to make a
separate proposal and keep the proposal here as minimal as possible to keep
SHT_ADDRSIG on track.
So getting back to SHT_ADDRSIG one of the objections seems to be the use of
ulebs. Is this really a reasonable objection?
What would the overhead be for
using a fixed width type for the symbol table indexes?
On 05/31/18 05:48 PM, 'Peter Collingbourne' via Generic System V Application Binary Interface wrote:
> My conclusion straight away from these numbers is that uncompressed SHT_SYMATTR is not an option if we can avoid it: the object file size overhead is simply too large. But compressed SHT_SYMATTR seems worth considering since the additional object file size cost is only 0.03%. The additional cost of words in SHT_ADDRSIG is only 0.02%, but that's a cost that doesn't really buy us much other than avoiding the use of a novel representation, and as I was saying elsewhere on the thread I'm not convinced that that's worth much.
To my eye, a cost of 0.03% says that these things have essentially
the same cost, and since I think avoiding the use of a novel representation
is actually a very big deal, this looks great to me. (I'll tackle the uleb
thing separately).
And don't forget that we get 31-bits of unused future symbol
attributes out of the deal, which seems a really nice bonus.
>
> My other concern for SHT_SYMATTR was the effect on link time. Keep in mind that at the end of the day the linker doesn't want to know which symbols are address-significant, it only needs to know which sections are address-significant. That means that the linker needs to do a second pass over the address-significant symbols once symbol resolution is done to mark sections as address-significant based on the symbol resolutions. This is straightforward if the representation is a list of indexes: we simply need to visit the symbol at each index in the list and mark its section as address-significant. But with SHT_SYMATTR we have to revisit every symbol in every object file after symbol resolution to copy the address-significant bit onto the section. And with compression we have to pay the cost of decompressing the sections as well.
Does this really have to be 2 passes?
Logically speaking, the symbol table and symattr combine to form
a single symbol table. You can think of it as adding an extra
field to Elf_Sym, only it's in a separate array. Get both
and pass them both to symbol resolution.
Now, during symbol resolution, when an ADDRSIG reference symbol
is resolved to a definition symbol, you transfer the ADDRSIG attribute
to the section. When symbol resolution is done, all the ADDRSIG
sections will be tagged.
>
> So I also implemented compressed SHT_SYMATTR in the linker and measured the effect on link time. The median wall-clock link time for 500 links of clang with --icf=safe was 0.97s with ulebs in SHT_ADDRSIG, or 0.98s with compressed SHT_SYMATTR. So the link time cost of SHT_SYMATTR is around 1%. That seems acceptable to me, but I'd like to get other opinions as well.
It seems OK to me too, but if that really involves a second pass on
the symbols, I bet you can squeeze it a bit more.
-cary
> It's true that address-significance can technically be considered a property
> of a reference, but that doesn't necessarily mean that we need to represent
> it in object files that way. A few points:
It's always a sound practice to have the representation a close fit to
the model. If something is a property of the reference, it should be
reflected in the relocation.
> 1) I'm not convinced that this approach would be simpler overall, because it
> would impose additional costs elsewhere:
>
> - it would mean updating every psABI to add the new FPTR relocations, as
> well as relocations that mean the opposite of FPTR (the latter being
> required because we would like a way to say that in C++, vtables and virtual
> function pointers are not address-significant, as well as a way of saying
> the same about compiler-generated data structures and similar constructs in
> other languages). That would mean adding significant redundancy to every
> psABI.
I don't see where you're getting this redundancy. The non-FPTR
relocations already exist.
> - because old linkers would not recognize the new relocations, the feature
> would be need to be behind a flag and off by default, so it would be less
> discoverable, at least to begin with
Not necessarily. Compilers are constantly relying on new features of
the assembler, linker, and other tools, and compiler distros will
include the tools that support those new features. We've added new
relocations to the x86 psABI (and others) several times without any
trouble.
> - linkers would need to recognize that all non-FPTR relocations in old
> object files are address-significant, so we'd need some sort of marker on
> new object files anyway (although I guess we could avoid this by redefining
> the existing relocations to be FPTR and having the new ones be non-FPTR).
That would be fine, although I'd also be fine with leaving the
existing guesswork in place for a time.
> - depending on how the linker is implemented, it could make things more
> complicated, because now it needs to read all relocations before running
> ICF. lld does not do this for example (if ICF is enabled, the first time it
> reads relocations might be *during* ICF).
I don't see a problem there. ICF can't function without reading the
relocations, but I don't see why it would need to have collected this
information before starting.
> 3) It's not clear that there would be a benefit in representing
> address-significance using relocations instead of a symbol property.
>
> In a traditional link (without --gc-sections) it normally wouldn't provide a
> benefit because each symbol in an object file would typically either be
> defined or have one or more relocations associated with it, so it wouldn't
> matter if the address-significance is expressed via the relocation or via
> the symbol. But let's assume that the user has --gc-sections enabled, since
> if they're using ICF they probably care a lot about binary size. In that
> case, we gain a benefit if a translation unit contains an
> address-significance that would have been optimized away by --gc-sections.
This is indeed one reason why it's better to let the relocations
describe the reference.
> Also keep in mind that even if a representation based on references turn out
> to be beneficial, we don't necessarily need to use relocations. We could
> always represent it with some sort of separate mapping from sections to the
> symbols that they make address-significant. That would address my concerns
> in 1 and 2.
That would be far worse in my estimation, especially considering the
lengths you've gone to upthread to add parallel symbol table sections,
or other sections that reference the symbol table. I'd like to keep
such complications out of the gABI -- one SHT_SYMTAB_SHNDX section is
one too many already.
Thanks,
Florian