[2/2] bfd/elfnn-aarch64.c: set DF_STATIC_TLS when emitting IE relocs

Message ID 20140701001808.GB9511@redacted.bos.redhat.com
State New
Headers show

Commit Message

Kyle McMartin July 1, 2014, 12:18 a.m.
For consistency with other architectures, set DF_STATIC_TLS in
shared libraries which will consume static TLS slots when loaded.
Fixes the tls-flag-static_tls test added in 1/2.
                                      
bfd/ChangeLog:

2014-06-30  Kyle McMartin <kyle@redhat.com>

	* elfnn-aarch64.c (elfNN_aarch64_check_relocs): Set DF_STATIC_TLS
	when emitting initial-exec relocs and not linking an executable.

Comments

Marcus Shawcroft July 1, 2014, 9:02 a.m. | #1
On 01/07/14 01:18, Kyle McMartin wrote:
> For consistency with other architectures, set DF_STATIC_TLS in
> shared libraries which will consume static TLS slots when loaded.
> Fixes the tls-flag-static_tls test added in 1/2.
>
> bfd/ChangeLog:
>
> 2014-06-30  Kyle McMartin <kyle@redhat.com>
>
> 	* elfnn-aarch64.c (elfNN_aarch64_check_relocs): Set DF_STATIC_TLS
> 	when emitting initial-exec relocs and not linking an executable.
>
> --- a/bfd/elfnn-aarch64.c
> +++ b/bfd/elfnn-aarch64.c
> @@ -5233,6 +5233,9 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
>
>   	    got_type = aarch64_reloc_got_type (bfd_r_type);
>
> +	    if (!info->executable && (got_type & GOT_TLS_IE))
> +	      info->flags |= DF_STATIC_TLS;
> +
>   	    if (h)
>   	      {
>   		h->got.refcount += 1;
>

Shouldn't this be:

if (info->shared && ...

.. with the effect of including PIE rather than excluding PIE ?

/Marcus
Kyle McMartin July 1, 2014, 2:14 p.m. | #2
On Tue, Jul 01, 2014 at 10:02:48AM +0100, Marcus Shawcroft wrote:
> 
> Shouldn't this be:
> 
> if (info->shared && ...
> 
> .. with the effect of including PIE rather than excluding PIE ?
> 

hrm, i think the theory is that PIE will relax to LE anyway? it doesn't
look like it currently would on aarch64 though, i'll look into that...

it seems to be about half and half who tests what:
i386, x86_64, ppc all set if !info->executable
sparc, mips, alpha all set if info->shared

--kyle
Alan Modra July 1, 2014, 3:42 p.m. | #3
On Tue, Jul 01, 2014 at 10:14:28AM -0400, Kyle McMartin wrote:
> it seems to be about half and half who tests what:
> i386, x86_64, ppc all set if !info->executable
> sparc, mips, alpha all set if info->shared

DF_STATIC_TLS is a flag that says the object is using thread pointer
relative addressing of TLS.  ie. the thread local storage for that
object must be laid out at program startup, which means the object
can't be dlopen'd (*).  So DF_STATIC_TLS is a flag for objects that
might be dlopen'd.  Hmm, and since we can actually dlopen any ET_DYN
including PIEs it would seem that info->shared is the correct test.

*) Except that glibc allocates some extra thread local storage,
and therefore can dynamically load shared libraries with static tls.
Kyle McMartin July 1, 2014, 4:19 p.m. | #4
On Wed, Jul 02, 2014 at 01:12:05AM +0930, Alan Modra wrote:
> On Tue, Jul 01, 2014 at 10:14:28AM -0400, Kyle McMartin wrote:
> > it seems to be about half and half who tests what:
> > i386, x86_64, ppc all set if !info->executable
> > sparc, mips, alpha all set if info->shared
> 
> DF_STATIC_TLS is a flag that says the object is using thread pointer
> relative addressing of TLS.  ie. the thread local storage for that
> object must be laid out at program startup, which means the object
> can't be dlopen'd (*).  So DF_STATIC_TLS is a flag for objects that
> might be dlopen'd.  Hmm, and since we can actually dlopen any ET_DYN
> including PIEs it would seem that info->shared is the correct test.
> 

Indeed... the specific problem I'm trying to solve is to have an easy
way to know a priori whether any static TLS relocs are present, so that
libc can choose to do the right thing for all cases. The problem right
now is, as it stands, glibc will allocate static TLS to optimize TLS
descriptor accesses, which consumes all the "reserved" static TLS space
for dlopen-ing TP relative libraries, which means any attempt to dlopen
a library which actually needs space fails. If we have this flag set,
then I can know if the link map comes from dlopen'd library (always use
dynamic TLS desc unless DF_STATIC_TLS is present) or if it was known at
ld time, in which case we have reserved space anyway. (And I can then do
it without two passes through the dyn relocs.)

I'm happy changing this, and testing changing it for places where it's
predicated on !info->executable as well, if you'd like. Mostly I just
want this to be consistent across platforms.

(I'm working on some other cleanups for the relaxation code too, but
 that's a side issue.)

> *) Except that glibc allocates some extra thread local storage,
> and therefore can dynamically load shared libraries with static tls.
> 

regards, Kyle

Patch hide | download patch | download mbox

--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -5233,6 +5233,9 @@  elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
 	    got_type = aarch64_reloc_got_type (bfd_r_type);
 
+	    if (!info->executable && (got_type & GOT_TLS_IE))
+	      info->flags |= DF_STATIC_TLS;
+
 	    if (h)
 	      {
 		h->got.refcount += 1;