diff options
Diffstat (limited to 'sysdeps/hppa/dl-machine.h')
-rw-r--r-- | sysdeps/hppa/dl-machine.h | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/sysdeps/hppa/dl-machine.h b/sysdeps/hppa/dl-machine.h index 9e98366ea3..8ecff97706 100644 --- a/sysdeps/hppa/dl-machine.h +++ b/sysdeps/hppa/dl-machine.h @@ -48,6 +48,14 @@ #define GOT_FROM_PLT_STUB (4*4) #define PLT_ENTRY_SIZE (2*4) +/* The gp slot in the function descriptor contains the relocation offset + before resolution. To distinguish between a resolved gp value and an + unresolved relocation offset we set an unused bit in the relocation + offset. This would allow us to do a synchronzied two word update + using this bit (interlocked update), but instead of waiting for the + update we simply recompute the gp value given that we know the ip. */ +#define PA_GP_RELOC 1 + /* Initialize the function descriptor table before relocations */ static inline void __hppa_init_bootstrap_fdesc_table (struct link_map *map) @@ -117,10 +125,28 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t t, volatile Elf32_Addr *rfdesc = reloc_addr; /* map is the link_map for the caller, t is the link_map for the object being called */ - rfdesc[1] = value.gp; - /* Need to ensure that the gp is visible before the code - entry point is updated */ - rfdesc[0] = value.ip; + + /* We would like the function descriptor to be double word aligned. This + helps performance (ip and gp then reside on the same cache line) and + we can update the pair atomically with a single store. The linker + now ensures this alignment but we still have to handle old code. */ + if ((unsigned int)reloc_addr & 7) + { + /* Need to ensure that the gp is visible before the code + entry point is updated */ + rfdesc[1] = value.gp; + atomic_full_barrier(); + rfdesc[0] = value.ip; + } + else + { + /* Update pair atomically with floating point store. */ + union { ElfW(Word) v[2]; double d; } u; + + u.v[0] = value.ip; + u.v[1] = value.gp; + *(volatile double *)rfdesc = u.d; + } return value; } @@ -265,7 +291,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) here. The trampoline code will load the proper LTP and pass the reloc offset to the fixup function. */ - fptr->gp = iplt - jmprel; + fptr->gp = (iplt - jmprel) | PA_GP_RELOC; } /* r_sym != 0 */ else { |