* sysdeps/x86_64/dl-machine.h (elf_machine_rela): Add branch

prediction.  A few size optimizations.
This commit is contained in:
Ulrich Drepper 2009-03-12 06:31:25 +00:00
parent 30991b8bd9
commit e7f110cdbd
3 changed files with 63 additions and 57 deletions

View File

@ -1,3 +1,8 @@
2009-03-11 Ulrich Drepper <drepper@redhat.com>
* sysdeps/x86_64/dl-machine.h (elf_machine_rela): Add branch
prediction. A few size optimizations.
2009-03-10 Ulrich Drepper <drepper@redhat.com> 2009-03-10 Ulrich Drepper <drepper@redhat.com>
* time/tzset.c: Optimize a bit for size. * time/tzset.c: Optimize a bit for size.

View File

@ -0,0 +1 @@
powerpc/powerpc32/power5/fpu

View File

@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation inline functions. x86-64 version. /* Machine-dependent ELF dynamic relocation inline functions. x86-64 version.
Copyright (C) 2001-2005, 2006 Free Software Foundation, Inc. Copyright (C) 2001-2005, 2006, 2008, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Andreas Jaeger <aj@suse.de>. Contributed by Andreas Jaeger <aj@suse.de>.
@ -266,40 +266,45 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
Elf64_Addr *const reloc_addr = reloc_addr_arg; Elf64_Addr *const reloc_addr = reloc_addr_arg;
const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info); const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info);
#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC # if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
if (__builtin_expect (r_type == R_X86_64_RELATIVE, 0)) if (__builtin_expect (r_type == R_X86_64_RELATIVE, 0))
{ {
# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC # if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
/* This is defined in rtld.c, but nowhere in the static libc.a; /* This is defined in rtld.c, but nowhere in the static libc.a;
make the reference weak so static programs can still link. make the reference weak so static programs can still link.
This declaration cannot be done when compiling rtld.c This declaration cannot be done when compiling rtld.c
(i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the
common defn for _dl_rtld_map, which is incompatible with a common defn for _dl_rtld_map, which is incompatible with a
weak decl in the same file. */ weak decl in the same file. */
# ifndef SHARED # ifndef SHARED
weak_extern (GL(dl_rtld_map)); weak_extern (GL(dl_rtld_map));
# endif # endif
if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */ if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */
# endif # endif
*reloc_addr = map->l_addr + reloc->r_addend; *reloc_addr = map->l_addr + reloc->r_addend;
} }
else else
#endif # endif
if (__builtin_expect (r_type == R_X86_64_NONE, 0)) if (__builtin_expect (r_type == R_X86_64_NONE, 0))
return; return;
else else
{ {
#ifndef RTLD_BOOTSTRAP # ifndef RTLD_BOOTSTRAP
const Elf64_Sym *const refsym = sym; const Elf64_Sym *const refsym = sym;
#endif # endif
struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
Elf64_Addr value = (sym == NULL ? 0 Elf64_Addr value = (sym == NULL ? 0
: (Elf64_Addr) sym_map->l_addr + sym->st_value); : (Elf64_Addr) sym_map->l_addr + sym->st_value);
#if defined RTLD_BOOTSTRAP && !USE___THREAD if (sym != NULL
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
0))
value = ((Elf64_Addr (*) (void)) value) ();
# if defined RTLD_BOOTSTRAP && !USE___THREAD
assert (r_type == R_X86_64_GLOB_DAT || r_type == R_X86_64_JUMP_SLOT); assert (r_type == R_X86_64_GLOB_DAT || r_type == R_X86_64_JUMP_SLOT);
*reloc_addr = value + reloc->r_addend; *reloc_addr = value + reloc->r_addend;
#else # else
switch (r_type) switch (r_type)
{ {
case R_X86_64_GLOB_DAT: case R_X86_64_GLOB_DAT:
@ -307,47 +312,47 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
*reloc_addr = value + reloc->r_addend; *reloc_addr = value + reloc->r_addend;
break; break;
#ifndef RESOLVE_CONFLICT_FIND_MAP # ifndef RESOLVE_CONFLICT_FIND_MAP
case R_X86_64_DTPMOD64: case R_X86_64_DTPMOD64:
# ifdef RTLD_BOOTSTRAP # ifdef RTLD_BOOTSTRAP
/* During startup the dynamic linker is always the module /* During startup the dynamic linker is always the module
with index 1. with index 1.
XXX If this relocation is necessary move before RESOLVE XXX If this relocation is necessary move before RESOLVE
call. */ call. */
*reloc_addr = 1; *reloc_addr = 1;
# else # else
/* Get the information from the link map returned by the /* Get the information from the link map returned by the
resolve function. */ resolve function. */
if (sym_map != NULL) if (sym_map != NULL)
*reloc_addr = sym_map->l_tls_modid; *reloc_addr = sym_map->l_tls_modid;
# endif # endif
break; break;
case R_X86_64_DTPOFF64: case R_X86_64_DTPOFF64:
# ifndef RTLD_BOOTSTRAP # ifndef RTLD_BOOTSTRAP
/* During relocation all TLS symbols are defined and used. /* During relocation all TLS symbols are defined and used.
Therefore the offset is already correct. */ Therefore the offset is already correct. */
if (sym != NULL) if (sym != NULL)
*reloc_addr = sym->st_value + reloc->r_addend; *reloc_addr = sym->st_value + reloc->r_addend;
# endif # endif
break; break;
case R_X86_64_TLSDESC: case R_X86_64_TLSDESC:
{ {
struct tlsdesc volatile *td = struct tlsdesc volatile *td =
(struct tlsdesc volatile *)reloc_addr; (struct tlsdesc volatile *)reloc_addr;
# ifndef RTLD_BOOTSTRAP # ifndef RTLD_BOOTSTRAP
if (! sym) if (! sym)
{ {
td->arg = (void*)reloc->r_addend; td->arg = (void*)reloc->r_addend;
td->entry = _dl_tlsdesc_undefweak; td->entry = _dl_tlsdesc_undefweak;
} }
else else
# endif # endif
{ {
# ifndef RTLD_BOOTSTRAP # ifndef RTLD_BOOTSTRAP
# ifndef SHARED # ifndef SHARED
CHECK_STATIC_TLS (map, sym_map); CHECK_STATIC_TLS (map, sym_map);
# else # else
if (!TRY_STATIC_TLS (map, sym_map)) if (!TRY_STATIC_TLS (map, sym_map))
{ {
td->arg = _dl_make_tlsdesc_dynamic td->arg = _dl_make_tlsdesc_dynamic
@ -355,8 +360,8 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
td->entry = _dl_tlsdesc_dynamic; td->entry = _dl_tlsdesc_dynamic;
} }
else else
# endif
# endif # endif
# endif
{ {
td->arg = (void*)(sym->st_value - sym_map->l_tls_offset td->arg = (void*)(sym->st_value - sym_map->l_tls_offset
+ reloc->r_addend); + reloc->r_addend);
@ -367,13 +372,13 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
} }
case R_X86_64_TPOFF64: case R_X86_64_TPOFF64:
/* The offset is negative, forward from the thread pointer. */ /* The offset is negative, forward from the thread pointer. */
# ifndef RTLD_BOOTSTRAP # ifndef RTLD_BOOTSTRAP
if (sym != NULL) if (sym != NULL)
# endif # endif
{ {
# ifndef RTLD_BOOTSTRAP # ifndef RTLD_BOOTSTRAP
CHECK_STATIC_TLS (map, sym_map); CHECK_STATIC_TLS (map, sym_map);
# endif # endif
/* We know the offset of the object the symbol is contained in. /* We know the offset of the object the symbol is contained in.
It is a negative value which will be added to the It is a negative value which will be added to the
thread pointer. */ thread pointer. */
@ -381,42 +386,41 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
- sym_map->l_tls_offset); - sym_map->l_tls_offset);
} }
break; break;
#endif # endif
#ifndef RTLD_BOOTSTRAP # ifndef RTLD_BOOTSTRAP
case R_X86_64_64: case R_X86_64_64:
*reloc_addr = value + reloc->r_addend; *reloc_addr = value + reloc->r_addend;
break; break;
case R_X86_64_32: case R_X86_64_32:
*(unsigned int *) reloc_addr = value + reloc->r_addend; value += reloc->r_addend;
if (value + reloc->r_addend > UINT_MAX) *(unsigned int *) reloc_addr = value;
const char *fmt;
if (__builtin_expect (value > UINT_MAX, 0))
{ {
const char *strtab; const char *strtab;
fmt = "\
%s: Symbol `%s' causes overflow in R_X86_64_32 relocation\n";
print_err:
strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]); strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
_dl_error_printf ("\ _dl_error_printf (fmt,
%s: Symbol `%s' causes overflow in R_X86_64_32 relocation\n",
rtld_progname ?: "<program name unknown>", rtld_progname ?: "<program name unknown>",
strtab + refsym->st_name); strtab + refsym->st_name);
} }
break; break;
# ifndef RESOLVE_CONFLICT_FIND_MAP # ifndef RESOLVE_CONFLICT_FIND_MAP
/* Not needed for dl-conflict.c. */ /* Not needed for dl-conflict.c. */
case R_X86_64_PC32: case R_X86_64_PC32:
*(unsigned int *) reloc_addr = value + reloc->r_addend value += reloc->r_addend - (Elf64_Addr) reloc_addr;
- (Elf64_Addr) reloc_addr; *(unsigned int *) reloc_addr = value;
if (value + reloc->r_addend - (Elf64_Addr) reloc_addr if (__builtin_expect (value != (unsigned int) value, 0))
!= (int)(value + reloc->r_addend - (Elf64_Addr) reloc_addr))
{ {
const char *strtab; fmt = "\
%s: Symbol `%s' causes overflow in R_X86_64_PC32 relocation\n";
strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]); goto print_err;
_dl_error_printf ("\
%s: Symbol `%s' causes overflow in R_X86_64_PC32 relocation\n",
rtld_progname ?: "<program name unknown>",
strtab + refsym->st_name);
} }
break; break;
case R_X86_64_COPY: case R_X86_64_COPY:
@ -424,26 +428,22 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
/* This can happen in trace mode if an object could not be /* This can happen in trace mode if an object could not be
found. */ found. */
break; break;
memcpy (reloc_addr_arg, (void *) value,
MIN (sym->st_size, refsym->st_size));
if (__builtin_expect (sym->st_size > refsym->st_size, 0) if (__builtin_expect (sym->st_size > refsym->st_size, 0)
|| (__builtin_expect (sym->st_size < refsym->st_size, 0) || (__builtin_expect (sym->st_size < refsym->st_size, 0)
&& GLRO(dl_verbose))) && GLRO(dl_verbose)))
{ {
const char *strtab; fmt = "\
%s: Symbol `%s' has different size in shared object, consider re-linking\n";
strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]); goto print_err;
_dl_error_printf ("\
%s: Symbol `%s' has different size in shared object, consider re-linking\n",
rtld_progname ?: "<program name unknown>",
strtab + refsym->st_name);
} }
memcpy (reloc_addr_arg, (void *) value,
MIN (sym->st_size, refsym->st_size));
break; break;
# endif # endif
default: default:
_dl_reloc_bad_type (map, r_type, 0); _dl_reloc_bad_type (map, r_type, 0);
break; break;
#endif # endif
} }
#endif #endif
} }