This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
PATCH: [BZ #14538] Use the first element of GOT for ld.so addresses
- From: "H.J. Lu" <hongjiu dot lu at intel dot com>
- To: GNU C Library <libc-alpha at sourceware dot org>
- Date: Sat, 1 Sep 2012 05:46:13 -0700
- Subject: PATCH: [BZ #14538] Use the first element of GOT for ld.so addresses
- Reply-to: "H.J. Lu" <hjl dot tools at gmail dot com>
Hi,
We can use IP-relative relocations to get the runtime and link-time
addresses of _DYNAMIC, which leads to smaller code size and data size.
The new code
movq _DYNAMIC(%rip), %rax
movq %rdx, start_time(%rip)
leaq _DYNAMIC(%rip), %rdx
movq %rdx, %r13
subq _GLOBAL_OFFSET_TABLE_(%rip), %r13
testq %rax, %rax
movq %rdx, 2472+_rtld_local(%rip)
movq %r13, 2456+_rtld_local(%rip)
je .L993
vs the old code
lea _dl_start(%rip), %r13
sub 1f(%rip), %r13
.section .data.rel.ro
1: .quad _dl_start
.previous
movq %rdx, start_time(%rip)
movq %r13, %rdx
addq _DYNAMIC@GOTPCREL(%rip), %rdx
movq %r13, 2456+_rtld_local(%rip)
movq (%rdx), %rax
movq %rdx, 2472+_rtld_local(%rip)
testq %rax, %rax
je .L994
Tested on x86-64 and x32. On x86-64, the new ld.so:
text data bss dec hex filename
133655 5108 456 139219 21fd3 ./build-x86_64-linux/elf/ld.so
vs. the old ld.so:
text data bss dec hex filename
133719 5148 456 139323 2203b ./build-x86_64-linux.2/elf/ld.so
On x32, the new ld.so:
text data bss dec hex filename
131677 2960 308 134945 20f21 ./build-x86_64-linux/elf/ld.so
vs. the old ld.so:
text data bss dec hex filename
131701 3000 308 135009 20f61 ./build-x86_64-linux.1/elf/ld.so
OK to install?
Thanks.
H.J.
--
[BZ #14538]
* sysdeps/x86_64/dl-machine.h (elf_machine_dynamic): Use the
first element of the GOT.
(elf_machine_load_address): Return the difference between
the runtime address of _DYNAMIC and elf_machine_dynamic ().
---
ChangeLog | 8 ++++++++
sysdeps/x86_64/dl-machine.h | 40 ++++++++--------------------------------
2 files changed, 16 insertions(+), 32 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index bd896ba..9ceadf1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2012-09-01 H.J. Lu <hongjiu.lu@intel.com>
+
+ [BZ #14538]
+ * sysdeps/x86_64/dl-machine.h (elf_machine_dynamic): Use the
+ first element of the GOT.
+ (elf_machine_load_address): Return the difference between
+ the runtime address of _DYNAMIC and elf_machine_dynamic ().
+
2012-08-29 H.J. Lu <hongjiu.lu@intel.com>
[BZ #14476]
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
index 9c27ecf..d2654aa 100644
--- a/sysdeps/x86_64/dl-machine.h
+++ b/sysdeps/x86_64/dl-machine.h
@@ -41,13 +41,9 @@ elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
static inline ElfW(Addr) __attribute__ ((unused))
elf_machine_dynamic (void)
{
- ElfW(Addr) addr;
-
- /* This works because we have our GOT address available in the small PIC
- model. */
- addr = (ElfW(Addr)) &_DYNAMIC;
-
- return addr;
+ /* This produces an IP-relative reloc which is resolved at link time. */
+ extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden;
+ return _GLOBAL_OFFSET_TABLE_[0];
}
@@ -55,31 +51,11 @@ elf_machine_dynamic (void)
static inline ElfW(Addr) __attribute__ ((unused))
elf_machine_load_address (void)
{
- ElfW(Addr) addr;
-
- /* The easy way is just the same as on x86:
- leaq _dl_start, %0
- leaq _dl_start(%%rip), %1
- subq %0, %1
- but this does not work with binutils since we then have
- a R_X86_64_32S relocation in a shared lib.
-
- Instead we store the address of _dl_start in the data section
- and compare it with the current value that we can get via
- an RIP relative addressing mode. Note that this is the address
- of _dl_start before any relocation performed at runtime. In case
- the binary is prelinked the resulting "address" is actually a
- load offset which is zero if the binary was loaded at the address
- it is prelinked for. */
-
- asm ("lea _dl_start(%%rip), %0\n\t"
- "sub 1f(%%rip), %0\n\t"
- ".section\t.data.rel.ro\n"
- "1:\t" ASM_ADDR " _dl_start\n\t"
- ".previous\n\t"
- : "=r" (addr) : : "cc");
-
- return addr;
+ /* Compute the difference between the runtime address of _DYNAMIC as seen
+ by an IP-relative reference, and the link-time address found in the
+ special unrelocated first GOT entry. */
+ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
+ return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic ();
}
/* Set up the loaded object described by L so its unrelocated PLT
--
1.7.11.4