about summary refs log tree commit diff
path: root/sysdeps/powerpc/powerpc64/dl-machine.h
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2022-01-22 11:48:50 +1030
committerAlan Modra <amodra@gmail.com>2022-04-10 08:33:06 +0930
commitd6efcc118e406a1cfeb309f835d7118df53419bb (patch)
tree31bbfdb82f662a47fece23a2e7f1324ea0c3ce6e /sysdeps/powerpc/powerpc64/dl-machine.h
parent30afd8c44d6a0a8b0eddbadecb02c9b9dad3facf (diff)
downloadglibc-d6efcc118e406a1cfeb309f835d7118df53419bb.tar.gz
glibc-d6efcc118e406a1cfeb309f835d7118df53419bb.tar.xz
glibc-d6efcc118e406a1cfeb309f835d7118df53419bb.zip
powerpc64: Use medium model toc accesses throughout
The PowerPC64 linker edits medium model toc-indirect code to toc-pointer
relative:
	addis r9,r2,tc_entry_for_var@toc@ha
	ld r9,tc_entry_for_var@toc@l(r9)
becomes
	addis r9,r2,(var-.TOC.)@ha
	addi r9,r9,(var-.TOC.)@l
when "var" is known to be local to the binary.  This isn't done for
small-model toc-indirect code, because "var" is almost guaranteed to
be too far away from .TOC. for a 16-bit signed offset.  And, because
the analysis of which .toc entry can be removed becomes much more
complicated in objects that mix code models, they aren't removed if
any small-model toc sequence appears in an object file.

Unfortunately, glibc's build of ld.so smashes the needed objects
together in a ld -r linking stage.  This means the GOT/TOC is left
with a whole lot of relative relocations which is untidy, but in
itself is not a serious problem.  However, static-pie on powerpc64
bombs due to a segfault caused by one of the small-model accesses
before _dl_relocate_static_pie.  (The very first one in rcrt1.o
passing start_addresses in r8 to __libc_start_main.)

So this patch makes all the toc/got accesses in assembly medium code
model, and a couple of functions hidden.  By itself this is not
enough to give us working static-pie, but it is useful in isolation to
enable better linker optimisation.

There's a serious problem in libgcc too.  libgcc ifuncs access the
AT_HWCAP words stored in the tcb with an offset from the thread
pointer (r13), but r13 isn't set at the time _dl_relocate_static_pie.
A followup patch will fix that.

Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
Diffstat (limited to 'sysdeps/powerpc/powerpc64/dl-machine.h')
-rw-r--r--sysdeps/powerpc/powerpc64/dl-machine.h12
1 files changed, 8 insertions, 4 deletions
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index 5da5de7a0a..6fab5cbe81 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -175,9 +175,12 @@ BODY_PREFIX "_dl_start_user:\n"						\
 /* the address of _start in r30.  */					\
 "	mr	30,3\n"							\
 /* &_dl_argc in 29, &_dl_argv in 27, and _dl_loaded in 28.  */		\
-"	ld	28,.LC__rtld_local@toc(2)\n"				\
-"	ld	29,.LC__dl_argc@toc(2)\n"				\
-"	ld	27,.LC__dl_argv@toc(2)\n"				\
+"	addis	28,2,.LC__rtld_local@toc@ha\n"				\
+"	ld	28,.LC__rtld_local@toc@l(28)\n"				\
+"	addis	29,2,.LC__dl_argc@toc@ha\n"				\
+"	ld	29,.LC__dl_argc@toc@l(29)\n"				\
+"	addis	27,2,.LC__dl_argv@toc@ha\n"				\
+"	ld	27,.LC__dl_argv@toc@l(27)\n"				\
 /* _dl_init (_dl_loaded, _dl_argc, _dl_argv, _dl_argv+_dl_argc+1).  */	\
 "	ld	3,0(28)\n"						\
 "	lwa	4,0(29)\n"						\
@@ -204,7 +207,8 @@ BODY_PREFIX "_dl_start_user:\n"						\
 "	addi	6,6,8\n"						\
 /* Pass a termination function pointer (in this case _dl_fini) in	\
    r7.  */								\
-"	ld	7,.LC__dl_fini@toc(2)\n"				\
+"	addis	7,2,.LC__dl_fini@toc@ha\n"				\
+"	ld	7,.LC__dl_fini@toc@l(7)\n"				\
 /* Pass the stack pointer in r1 (so far so good), pointing to a NULL	\
    value.  This lets our startup code distinguish between a program	\
    linked statically, which linux will call with argc on top of the	\