ld tests about protected visibility

Michael Matz matz@suse.de
Thu Nov 25 16:40:15 GMT 2021
Hello,

On Thu, 25 Nov 2021, CHIGOT, CLEMENT wrote:

> >So, yes, removing .protected from main.c should have the effect you see;
> >but as said, it's not an interesting test as no protected visibility would
> >be involved anymore, just normal default ELF lookup rules.
> 
> Ok, I understand a bit more. I just find it really weird that the test has
> the same result whether or not ".protected" is there. Because, that means
> that if protected for whatever reasons stops working and is kind of ignored
> by the linker, it won't be detected right ?

Not by _this_ test, correct.  But that is not the point of this test.  
Simply testing that the .protected directive cause the symbols to be of 
PROTECTED visibility is the point of other tests (define.s and 
protected0.d in this directory).  _This_ test checks if references from 
the shared library are resolved to the protected symbol in the executable, 
no matter if the shared lib does or does not contain its own definition of 
the symbol.  I.e. it tests that the presence of protected in the 
executable doesn't accidentally lead to that symbol not being used by the 
shared lib anymore.  See below for the other direction.

> >In case it helps: protected symbols are conceptually fairly simple: a
> >protected symbol in component (exe or shared lib) A is visible from other
> >components B (i.e. it's exported).  References to that symbol from within
> >component A are resolved to the symbol in component A, no matter if other
> >components also define that symbol (this is in difference to normal ELF
> >lookup rules, which state that the first symbol found in a global breadth
> >first search of all components is the one that all references resolve to).
> 
> So if I understand correctly, if ".protected" is removed from our testcase and
> vp.so is still exporting shared_data, thus, linking with vp.so before mainnp.o
> would mean that the data_shared referenced in mainnp.o would be the one
> within the shared lib and not the one from the main (because vp.so is
> included before mainnp.o) ?

No.  There are runtime and link editing time resolving steps.  In this 
case we are interested in the effect of both, and for that the order of 
the cmdline arguments to ld don't matter here: shared libraries (like 
vp.so) implicitely loaded by executables (vp, link-edited from mainnp.o) 
always come after the executable in symbol lookups.  So, if both lib and 
exe contain global defines then the only one found by lookups from any 
component would be the one in the exe.

But, a similar case can be constructed where there's a difference in 
behaviour when protected is or isn't used: the executable defines a GLOBAL 
'foobar', the shared library defines a PROTECTED foobar (i.e. opposite of 
the tests related to "shared_data").  Now references from within the 
executable would be resolved to the exe-foobar (by normal lookup rules), 
and references from within the shared lib would resolve to lib-foobar (by 
protected lookup rules).

This latter scenario is tested by the 'visibility_var' variables with 
certain defines.

If the lib would define a GLOBAL foobar, then references from within the 
lib would also resolve to exe-foobar.  (In effect lib-foobar would be 
globally shadowed by exe-foobar).

> While with ".protected" whatever the order is, "data_shared" references 
> in mainnp.o would always target the one defined in mainnp.o ?

This is correct, though.  No matter into which component mainnp.o would be 
link-edited (shared lib or exe) references from it to "data_shared" would 
always resolve locally in that component.


Ciao,
Michael.


More information about the Binutils mailing list