diff options
author | Ulrich Drepper <drepper@redhat.com> | 1997-09-27 00:21:42 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 1997-09-27 00:21:42 +0000 |
commit | a2b08ee54130cf3a74655856e6ca6c29874a9df2 (patch) | |
tree | 71e7d867304f432bc57043e0c54a5cf101835651 /sysdeps | |
parent | 650425ceb40e840b2123b6c8cc65389589f41218 (diff) | |
download | glibc-a2b08ee54130cf3a74655856e6ca6c29874a9df2.tar.gz glibc-a2b08ee54130cf3a74655856e6ca6c29874a9df2.tar.xz glibc-a2b08ee54130cf3a74655856e6ca6c29874a9df2.zip |
Update. cvs/libc-ud-970926
1997-09-27 01:14 Ulrich Drepper <drepper@cygnus.com> * Makeconfig (extra-objs): Depend in before-compile. * configure.in: Locate Perl and substitute with complete path. * config.make.in: Add PERL for substitution. * elf/Makefile (routines): Add dl-addr. * elf/dladdr.c: Move the real code into ... * elf/dl-addr.c: New file. * elf/link.h: Add prototype for _dl_addr. * elf/dladdr.c (dladdr): Change address argument to be const. * elf/dlfcn.h: Likewise. * locale/C_name.c: Add _nl_POSIX_name. * locale/localeinfo.h: Add declaration of _nl_POSIX_name. * locale/findlocale.c (_nl_find_locale): Use _nl_POSIX_name. (_nl_remove_locale): Free name of data set. * locale/setlocale.c (clever_copy): Remove. (new_composite_name): Use _nl_C_name and _nl_POSIX_name in compare. (setname): Only remove old name when it is for category LC_ALL. Change malloc, free, realloc, and memalign hooks for glibc to take another parameter indicating the location of the caller. * malloc/malloc.c: Change hook functions and variables. * malloc/malloc.h: Likewise. * malloc/mcheck.c: Likewise. Make sure later hooked function also get the original caller address. * malloc/mtrace.c: Likewise. (tr_where): If no information in _mtrace_file is given use the information about the caller. * malloc/Makefile (distribute): Replace mtrace.awk by mtrace.pl. Add rules to install mtrace.pl after rewriting. * malloc/mtrace.pl: New file. Based on the old AWK script but with extended functionality. * malloc/mtrace.awk: Removed. * po/fr.po: New version. * string/Makefile: Do use builtins for tester.c and inl-tester.c. * string/tester.c: Rewrite. Split in many small functions to not exceed gcc's limits. * sysdeps/unix/sysv/linux/syscalls.list: Add prctl. 1997-09-25 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> * string/bits/string2.h (__stpcpy_small): Don't use casts as lvalues. 1997-09-26 Andreas Jaeger <aj@arthur.rhein-neckar.de> * manual/time.texi (Formatting Date and Time): Clarify explanation of strftime flags a bit. Suggested by Robert Bihlmeyer <robbe@orcus.priv.at>. 1997-09-25 00:13 David S. Miller <davem@tanya.rutgers.edu> * sysdeps/libm-ieee754/s_exp2f.c: Protect _GNU_SOURCE definition. Fix typo, it is FLT_MANT_DIG. 1997-09-24 18:52 H.J. Lu <hjl@gnu.ai.mit.edu> * math/atest-exp2.c: Include <stdlib/gmp.h> instead of <gmp.h>. 1997-08-27 08:10 H.J. Lu <hjl@gnu.ai.mit.edu> * libio/libio.h, libio/libioP.h: Support libio in libstdc++. * libio/libio.h (_IO_peekc): Defined as _IO_peekc_unlocked if _IO_MTSAFE_IO is undefined. 1997-09-24 23:27 Richard Henderson <rth@cygnus.com> * elf/dl-runtime.c (fixup): Don't go through elf_machine_relplt, but lookup the value of the target symbol ourselves and call the new elf_machine_fixup_plt. This kills the ELF_FIXUP_RETURN_VALUE hack. (profile_fixup): Likewise, but don't fix up the plt. * elf/rtld.c (_dl_main): ELF_MACHINE_RELOC_NOPLT renamed _JMP_SLOT. * sysdeps/alpha/dl-machine.h (ELF_MACHINE_RELOC_NOPLT): Renamed. (elf_alpha_fix_plt): Renamed elf_machine_fixup_plt. * sysdeps/i386/dl-machine.h (elf_machine_relplt): Killed. (ELF_MACHINE_JMP_SLOT): Renamed. (elf_machine_fixup_plt): New function. * sysdeps/m68k/dl-machine.h: Likewise. * sysdeps/powerpc/dl-machine.h: Likewise. (elf_machine_rela): Moved JMP_SLOT fixup out to elf_machine_fixup_plt. * sysdeps/sparc/sparc32/dl-machine.h: Likewise. * sysdeps/sparc/sparc64/dl-machine.h: Likewise. * sysdeps/stub/dl-machine.h: Update, sorta. * sysdeps/alpha/dl-machine.h (elf_machine_runtime_setup): Do profiling. (TRAMPOLINE_TEMPLATE): From the carcas of _RUNTIME_TRAMPOLINE, do both normal and profile code. (elf_machine_rela): Handle r_addend for .got and .plt too.
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/alpha/dl-machine.h | 85 | ||||
-rw-r--r-- | sysdeps/i386/dl-machine.h | 13 | ||||
-rw-r--r-- | sysdeps/libm-ieee754/s_exp2f.c | 6 | ||||
-rw-r--r-- | sysdeps/m68k/dl-machine.h | 13 | ||||
-rw-r--r-- | sysdeps/powerpc/dl-machine.h | 134 | ||||
-rw-r--r-- | sysdeps/sparc/sparc32/dl-machine.h | 44 | ||||
-rw-r--r-- | sysdeps/sparc/sparc64/dl-machine.h | 44 | ||||
-rw-r--r-- | sysdeps/stub/dl-machine.h | 17 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/syscalls.list | 1 |
9 files changed, 194 insertions, 163 deletions
diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h index e0ba67b48b..d3eb242c04 100644 --- a/sysdeps/alpha/dl-machine.h +++ b/sysdeps/alpha/dl-machine.h @@ -91,6 +91,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) { Elf64_Addr plt; extern void _dl_runtime_resolve (void); + extern void _dl_runtime_profile (void); if (l->l_info[DT_JMPREL] && lazy) { @@ -100,7 +101,14 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) plt = l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr; /* This function will be called to perform the relocation. */ - *(Elf64_Addr *)(plt + 16) = (Elf64_Addr) &_dl_runtime_resolve; + if (!profile) + *(Elf64_Addr *)(plt + 16) = (Elf64_Addr) &_dl_runtime_resolve; + else + { + *(Elf64_Addr *)(plt + 16) = (Elf64_Addr) &_dl_runtime_profile; + /* Say that we really want profiling and the timers are started. */ + _dl_profile_map = l; + } /* Identify this shared object */ *(Elf64_Addr *)(plt + 24) = (Elf64_Addr) l; @@ -115,11 +123,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) /* This code is used in dl-runtime.c to call the `fixup' function and then redirect to the address it returns. */ -#define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ( \ -"/* Trampoline for _dl_runtime_resolver */ - .globl _dl_runtime_resolve - .ent _dl_runtime_resolve -_dl_runtime_resolve: +#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name, IMB) asm ( "\ + .globl " #tramp_name " + .ent " #tramp_name " +" #tramp_name ": lda $sp, -168($sp) .frame $sp, 168, $26 /* Preserve all registers that C normally doesn't. */ @@ -146,18 +153,20 @@ _dl_runtime_resolve: stq $29, 160($sp) .mask 0x27ff01ff, -168 /* Set up our $gp */ - br $gp, 0f -0: ldgp $gp, 0($gp) + br $gp, .+4 + ldgp $gp, 0($gp) .prologue 1 - /* Set up the arguments for _dl_runtime_resolve. */ + /* Set up the arguments for fixup: */ /* $16 = link_map out of plt0 */ /* $17 = offset of reloc entry = ($28 - $27 - 20) /12 * 24 */ + /* $18 = return address */ subq $28, $27, $17 ldq $16, 8($27) subq $17, 20, $17 + mov $26, $18 addq $17, $17, $17 /* Do the fixup */ - bsr $26, fixup..ng + bsr $26, " #fixup_name "..ng /* Move the destination address into position. */ mov $0, $27 /* Restore program registers. */ @@ -183,14 +192,21 @@ _dl_runtime_resolve: ldq $25, 152($sp) ldq $29, 160($sp) /* Flush the Icache after having modified the .plt code. */ - imb + " #IMB " /* Clean up and turn control to the destination */ lda $sp, 168($sp) jmp $31, ($27) - .end _dl_runtime_resolve"); + .end " #tramp_name) -/* The PLT uses Elf64_Rela relocs. */ -#define elf_machine_relplt elf_machine_rela +#ifndef PROF +#define ELF_MACHINE_RUNTIME_TRAMPOLINE \ + TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup, imb); \ + TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup, #nop); +#else +#define ELF_MACHINE_RUNTIME_TRAMPOLINE \ + TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup); \ + strong_alias (_dl_runtime_resolve, _dl_runtime_profile); +#endif /* Initial entry point code for the dynamic linker. The C function `_dl_start' is the real entry point; @@ -255,37 +271,31 @@ _dl_start_user: #define elf_machine_lookup_noexec_p(type) (0) /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ -#define ELF_MACHINE_RELOC_NOPLT R_ALPHA_JMP_SLOT +#define ELF_MACHINE_JMP_SLOT R_ALPHA_JMP_SLOT /* The alpha never uses Elf64_Rel relocations. */ #define ELF_MACHINE_NO_REL 1 -#endif /* !dl_machine_h */ - -#ifdef RESOLVE - /* Fix up the instructions of a PLT entry to invoke the function rather than the dynamic linker. */ static inline void -elf_alpha_fix_plt(struct link_map *l, - const Elf64_Rela *reloc, - Elf64_Addr got_addr, - Elf64_Addr value) +elf_machine_fixup_plt(struct link_map *l, const Elf64_Rela *reloc, + Elf64_Addr *got_addr, Elf64_Addr value) { const Elf64_Rela *rela_plt; Elf64_Word *plte; long edisp; + /* Store the value we are going to load. */ + *got_addr = value; + /* Recover the PLT entry address by calculating reloc's index into the .rela.plt, and finding that entry in the .plt. */ - rela_plt = (void *)(l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr); - plte = (void *)(l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr + 32); plte += 3 * (reloc - rela_plt); /* Find the displacement from the plt entry to the function. */ - edisp = (long)(value - (Elf64_Addr)&plte[3]) / 4; if (edisp >= -0x100000 && edisp < 0x100000) @@ -299,7 +309,7 @@ elf_alpha_fix_plt(struct link_map *l, lo = (short)hi; hi = (hi - lo) >> 16; - /* Emit "lda $27,L($27)" */ + /* Emit "lda $27,lo($27)" */ plte[1] = 0x237b0000 | (lo & 0xffff); /* Emit "br $31,function" */ @@ -309,7 +319,7 @@ elf_alpha_fix_plt(struct link_map *l, committed to memory before the first is overwritten. */ __asm__ __volatile__("wmb" : : : "memory"); - /* Emit "ldah $27,H($27)" */ + /* Emit "ldah $27,hi($27)" */ plte[0] = 0x277b0000 | (hi & 0xffff); } else @@ -319,11 +329,11 @@ elf_alpha_fix_plt(struct link_map *l, into the cache. */ int hi, lo; - hi = got_addr - (Elf64_Addr)&plte[0]; + hi = (Elf64_Addr)got_addr - (Elf64_Addr)&plte[0]; lo = (short)hi; hi = (hi - lo) >> 16; - /* Emit "ldq $27,L($27)" */ + /* Emit "ldq $27,lo($27)" */ plte[1] = 0xa77b0000 | (lo & 0xffff); /* Emit "jmp $31,($27)" */ @@ -333,7 +343,7 @@ elf_alpha_fix_plt(struct link_map *l, committed to memory before the first is overwritten. */ __asm__ __volatile__("wmb" : : : "memory"); - /* Emit "ldah $27,H($27)" */ + /* Emit "ldah $27,hi($27)" */ plte[0] = 0x277b0000 | (hi & 0xffff); } @@ -343,6 +353,10 @@ elf_alpha_fix_plt(struct link_map *l, hasn't made it into Icache yet, so there's nothing to clean up. */ } +#endif /* !dl_machine_h */ + +#ifdef RESOLVE + /* Perform the relocation specified by RELOC and SYM (which is fully resolved). MAP is the object containing the reloc. */ static inline void @@ -382,14 +396,12 @@ elf_machine_rela (struct link_map *map, loadbase = RESOLVE (&sym, version, r_type); sym_value = sym ? loadbase + sym->st_value : 0; + sym_value += reloc->r_addend; if (r_type == R_ALPHA_GLOB_DAT) *reloc_addr = sym_value; else if (r_type == R_ALPHA_JMP_SLOT) - { - *reloc_addr = sym_value; - elf_alpha_fix_plt (map, reloc, (Elf64_Addr) reloc_addr, sym_value); - } + elf_machine_fixup_plt (map, reloc, reloc_addr, sym_value); else if (r_type == R_ALPHA_REFQUAD) { sym_value += *reloc_addr; @@ -405,10 +417,9 @@ elf_machine_rela (struct link_map *map, = (void *)(map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr); sym_value -= map->l_addr; sym_value -= dlsymtab[ELF64_R_SYM(reloc->r_info)].st_value; + sym_value -= reloc->r_addend; } - else #endif - sym_value += reloc->r_addend; *reloc_addr = sym_value; } else diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h index 041643ef5a..0ac67c05d9 100644 --- a/sysdeps/i386/dl-machine.h +++ b/sysdeps/i386/dl-machine.h @@ -185,15 +185,11 @@ _dl_runtime_profile: .previous "); #endif -/* The PLT uses Elf32_Rel relocs. */ -#define elf_machine_relplt elf_machine_rel /* Mask identifying addresses reserved for the user program, where the dynamic linker should not map anything. */ #define ELF_MACHINE_USER_ADDRESS_MASK 0xf8000000UL - - /* Initial entry point code for the dynamic linker. The C function `_dl_start' is the real entry point; its return value is the user program's entry point. */ @@ -265,7 +261,7 @@ _dl_start_user:\n\ #define elf_machine_lookup_noplt_p(type) ((type) == R_386_JMP_SLOT) /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ -#define ELF_MACHINE_RELOC_NOPLT R_386_JMP_SLOT +#define ELF_MACHINE_JMP_SLOT R_386_JMP_SLOT /* The i386 never uses Elf32_Rela relocations. */ #define ELF_MACHINE_NO_RELA 1 @@ -287,6 +283,13 @@ dl_platform_init (void) _dl_platform = NULL; } +static inline void +elf_machine_fixup_plt (struct link_map *map, const Elf32_Rel *reloc, + Elf32_Addr *reloc_addr, Elf32_Addr value) +{ + *reloc_addr = value; +} + #endif /* !dl_machine_h */ #ifdef RESOLVE diff --git a/sysdeps/libm-ieee754/s_exp2f.c b/sysdeps/libm-ieee754/s_exp2f.c index e50ac77792..92c1f16c5a 100644 --- a/sysdeps/libm-ieee754/s_exp2f.c +++ b/sysdeps/libm-ieee754/s_exp2f.c @@ -25,7 +25,9 @@ It has been slightly modified to compute 2^x instead of e^x, and for single-precision. */ -#define _GNU_SOURCE +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif #include <float.h> #include <ieee754.h> #include <math.h> @@ -116,7 +118,7 @@ __ieee754_exp2f (float x) else if (isgreaterequal (x, (float) FLT_MAX_EXP)) return huge * huge; /* And underflow (including -inf). */ - else if (isless (x, (float) (FLT_MIN_EXP - FLT_MANT_DIF))) + else if (isless (x, (float) (FLT_MIN_EXP - FLT_MANT_DIG))) return TWOM100 * TWOM100; /* Maybe the result needs to be a denormalised number... */ else if (!isnan (x)) diff --git a/sysdeps/m68k/dl-machine.h b/sysdeps/m68k/dl-machine.h index 44eefb20f5..cc0fb56189 100644 --- a/sysdeps/m68k/dl-machine.h +++ b/sysdeps/m68k/dl-machine.h @@ -135,8 +135,6 @@ asm (TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup) \ ".set _dl_runtime_profile, _dl_runtime_resolve"); #endif #define ELF_MACHINE_RUNTIME_FIXUP_ARGS long int save_a0, long int save_a1 -/* The PLT uses Elf32_Rela relocs. */ -#define elf_machine_relplt elf_machine_rela /* Mask identifying addresses reserved for the user program, @@ -216,11 +214,18 @@ _dl_start_user: #define elf_machine_lookup_noplt_p(type) ((type) == R_68K_JMP_SLOT) /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ -#define ELF_MACHINE_RELOC_NOPLT R_68K_JMP_SLOT +#define ELF_MACHINE_JMP_SLOT R_68K_JMP_SLOT /* The m68k never uses Elf32_Rel relocations. */ #define ELF_MACHINE_NO_REL 1 +static inline void +elf_machine_fixup_plt (struct link_map *map, const Elf32_Rela *reloc, + Elf32_Addr *reloc_addr, Elf32_Addr value) +{ + *reloc_addr = value + reloc->r_addend; +} + #endif /* !dl_machine_h */ #ifdef RESOLVE @@ -267,7 +272,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, break; case R_68K_GLOB_DAT: case R_68K_JMP_SLOT: - *reloc_addr = value; + *reloc_addr = value + reloc->r_addend; break; case R_68K_8: *(char *) reloc_addr = value + reloc->r_addend; diff --git a/sysdeps/powerpc/dl-machine.h b/sysdeps/powerpc/dl-machine.h index 70a3f20b31..beabc1d4ff 100644 --- a/sysdeps/powerpc/dl-machine.h +++ b/sysdeps/powerpc/dl-machine.h @@ -197,8 +197,7 @@ _dl_runtime_resolve: # ...unwind the stack frame, and jump to the PLT entry we updated. addi 1,1,48 bctr -0: - .size _dl_runtime_resolve,0b-_dl_runtime_resolve + .size _dl_runtime_resolve,.-_dl_runtime_resolve .align 2 .globl _dl_prof_resolve @@ -395,10 +394,6 @@ static ElfW(Addr) _dl_preferred_address = 1 _dl_preferred_address = mapstart; \ } ) -/* We require the address of the PLT entry returned from fixup, not - the first word of the PLT entry. */ -#define ELF_FIXUP_RETURN_VALUE(map, result) ((Elf32_Addr) &(result)) - /* Nonzero iff TYPE should not be allowed to resolve to one of the main executable's symbols, as for a COPY reloc. */ #define elf_machine_lookup_noexec_p(type) ((type) == R_PPC_COPY) @@ -413,7 +408,7 @@ static ElfW(Addr) _dl_preferred_address = 1 (type) == R_PPC_JMP_SLOT) /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ -#define ELF_MACHINE_RELOC_NOPLT R_PPC_JMP_SLOT +#define ELF_MACHINE_JMP_SLOT R_PPC_JMP_SLOT /* Nonzero iff TYPE describes relocation of a PLT entry, so PLT entries should not be allowed to define the value. */ @@ -554,6 +549,70 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc) /* elf_machine_runtime_setup handles this. */ } +static inline void +elf_machine_fixup_plt(struct link_map *map, const Elf32_Rela *reloc, + Elf32_Addr *reloc_addr, Elf32_Addr finaladdr) +{ + Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr; + if (delta << 6 >> 6 == delta) + *reloc_addr = OPCODE_B (delta); + else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000) + *reloc_addr = OPCODE_BA (finaladdr); + else + { + Elf32_Word *plt; + Elf32_Word index; + + plt = (Elf32_Word *)((char *)map->l_addr + + map->l_info[DT_PLTGOT]->d_un.d_val); + index = (reloc_addr - plt - PLT_INITIAL_ENTRY_WORDS)/2; + if (index >= PLT_DOUBLE_SIZE) + { + /* Slots greater than or equal to 2^13 have 4 words available + instead of two. */ + /* FIXME: There are some possible race conditions in this code, + when called from 'fixup'. + + 1) Suppose that a lazy PLT entry is executing, a context switch + between threads (or a signal) occurs, and the new thread or + signal handler calls the same lazy PLT entry. Then the PLT entry + would be changed while it's being run, which will cause a segfault + (almost always). + + 2) Suppose the reverse: that a lazy PLT entry is being updated, + a context switch occurs, and the new code calls the lazy PLT + entry that is being updated. Then the half-fixed PLT entry will + be executed, which will also almost always cause a segfault. + + These problems don't happen with the 2-word entries, because + only one of the two instructions are changed when a lazy entry + is retargeted at the actual PLT entry; the li instruction stays + the same (we have to update it anyway, because we might not be + updating a lazy PLT entry). */ + + reloc_addr[0] = OPCODE_LI (11, finaladdr); + reloc_addr[1] = OPCODE_ADDIS (11, 11, finaladdr + 0x8000 >> 16); + reloc_addr[2] = OPCODE_MTCTR (11); + reloc_addr[3] = OPCODE_BCTR (); + } + else + { + Elf32_Word num_plt_entries; + + num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val + / sizeof(Elf32_Rela)); + + plt[index+PLT_DATA_START_WORDS (num_plt_entries)] = finaladdr; + reloc_addr[0] = OPCODE_LI (11, index*4); + reloc_addr[1] = OPCODE_B (-(4*(index*2 + + 1 + - PLT_LONGBRANCH_ENTRY_WORDS + + PLT_INITIAL_ENTRY_WORDS))); + } + } + MODIFIED_CODE (reloc_addr); +} + #endif /* dl_machine_h */ #ifdef RESOLVE @@ -674,66 +733,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, } else if (rinfo == R_PPC_JMP_SLOT) { - Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr; - if (delta << 6 >> 6 == delta) - *reloc_addr = OPCODE_B (delta); - else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000) - *reloc_addr = OPCODE_BA (finaladdr); - else - { - Elf32_Word *plt; - Elf32_Word index; - - plt = (Elf32_Word *)((char *)map->l_addr - + map->l_info[DT_PLTGOT]->d_un.d_val); - index = (reloc_addr - plt - PLT_INITIAL_ENTRY_WORDS)/2; - if (index >= PLT_DOUBLE_SIZE) - { - /* Slots greater than or equal to 2^13 have 4 words available - instead of two. */ - /* FIXME: There are some possible race conditions in this code, - when called from 'fixup'. - - 1) Suppose that a lazy PLT entry is executing, a - context switch between threads (or a signal) occurs, - and the new thread or signal handler calls the same - lazy PLT entry. Then the PLT entry would be changed - while it's being run, which will cause a segfault - (almost always). - - 2) Suppose the reverse: that a lazy PLT entry is - being updated, a context switch occurs, and the new - code calls the lazy PLT entry that is being updated. - Then the half-fixed PLT entry will be executed, which - will also almost always cause a segfault. - - These problems don't happen with the 2-word entries, because - only one of the two instructions are changed when a lazy - entry is retargeted at the actual PLT entry; the li - instruction stays the same (we have to update it anyway, - because we might not be updating a lazy PLT entry). */ - reloc_addr[0] = OPCODE_LI (11, finaladdr); - reloc_addr[1] = OPCODE_ADDIS (11, 11, finaladdr + 0x8000 >> 16); - reloc_addr[2] = OPCODE_MTCTR (11); - reloc_addr[3] = OPCODE_BCTR (); - } - else - { - Elf32_Word num_plt_entries; - - num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val - / sizeof(Elf32_Rela)); - - plt[index+PLT_DATA_START_WORDS (num_plt_entries)] = finaladdr; - reloc_addr[0] = OPCODE_LI (11, index*4); - reloc_addr[1] = - OPCODE_B (-(4*(index*2 - + 1 - - PLT_LONGBRANCH_ENTRY_WORDS - + PLT_INITIAL_ENTRY_WORDS))); - } - } - MODIFIED_CODE (reloc_addr); + elf_machine_fixup_plt (map, reloc, reloc_addr, finalvalue); } else { diff --git a/sysdeps/sparc/sparc32/dl-machine.h b/sysdeps/sparc/sparc32/dl-machine.h index b80c126487..288a140245 100644 --- a/sysdeps/sparc/sparc32/dl-machine.h +++ b/sysdeps/sparc/sparc32/dl-machine.h @@ -126,13 +126,6 @@ _dl_runtime_resolve: restore .size _dl_runtime_resolve, . - _dl_runtime_resolve"); -/* The address of the JMP_SLOT reloc is the .plt entry, thus we don't - dereference the reloc's addr to get the final destination. Ideally - there would be a generic way to return the value of the symbol from - elf_machine_relplt, but as it is, the address of the .plt entry is - good enough. */ -#define ELF_FIXUP_RETURN_VALUE(map, result) ((Elf32_Addr) &(result)) - /* Nonzero iff TYPE should not be allowed to resolve to one of the main executable's symbols, as for a COPY reloc. */ #define elf_machine_lookup_noexec_p(type) ((type) == R_SPARC_COPY) @@ -142,7 +135,7 @@ _dl_runtime_resolve: #define elf_machine_lookup_noplt_p(type) ((type) == R_SPARC_JMP_SLOT) /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ -#define ELF_MACHINE_RELOC_NOPLT R_SPARC_JMP_SLOT +#define ELF_MACHINE_JMP_SLOT R_SPARC_JMP_SLOT /* The SPARC never uses Elf32_Rel relocations. */ #define ELF_MACHINE_NO_REL 1 @@ -150,9 +143,6 @@ _dl_runtime_resolve: /* The SPARC overlaps DT_RELA and DT_PLTREL. */ #define ELF_MACHINE_PLTREL_OVERLAP 1 -/* The PLT uses Elf32_Rela relocs. */ -#define elf_machine_relplt elf_machine_rela - /* Initial entry point code for the dynamic linker. The C function `_dl_start' is the real entry point; its return value is the user program's entry point. */ @@ -246,7 +236,30 @@ _dl_start_user: .size _dl_start_user,.-_dl_start_user .previous"); +static inline void +elf_machine_fixup_plt (struct link_map *map, const Elf32_Rela *reloc, + Elf32_Addr *reloc_addr, Elf32_Addr value) +{ + /* For thread safety, write the instructions from the bottom and + flush before we overwrite the critical "b,a". This of course + need not be done during bootstrapping, since there are no threads. + But we also can't tell if we _can_ use flush, so don't. */ + + reloc_addr[2] = OPCODE_JMP_G1 | (value & 0x3ff); +#ifndef RTLD_BOOTSTRAP + if (_dl_hwcap & HWCAP_SPARC_FLUSH) + __asm __volatile ("flush %0+8" : : "r"(reloc_addr)); +#endif + + reloc_addr[1] = OPCODE_SETHI_G1 | (value >> 10); +#ifndef RTLD_BOOTSTRAP + if (_dl_hwcap & HWCAP_SPARC_FLUSH) + __asm __volatile ("flush %0+4" : : "r"(reloc_addr)); +#endif +} + #ifdef RESOLVE + /* Perform the relocation specified by RELOC and SYM (which is fully resolved). MAP is the object containing the reloc. */ @@ -305,14 +318,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, *reloc_addr = value; break; case R_SPARC_JMP_SLOT: - /* For thread safety, write the instructions from the bottom and - flush before we overwrite the critical "b,a". */ - reloc_addr[2] = OPCODE_JMP_G1 | (value & 0x3ff); - if (_dl_hwcap & HWCAP_SPARC_FLUSH) - __asm __volatile ("flush %0+8" : : "r"(reloc_addr)); - reloc_addr[1] = OPCODE_SETHI_G1 | (value >> 10); - if (_dl_hwcap & HWCAP_SPARC_FLUSH) - __asm __volatile ("flush %0+4" : : "r"(reloc_addr)); + elf_machine_fixup_plt(map, reloc, reloc_addr, value); break; case R_SPARC_8: *(char *) reloc_addr = value; diff --git a/sysdeps/sparc/sparc64/dl-machine.h b/sysdeps/sparc/sparc64/dl-machine.h index e302f4a1fe..226623152d 100644 --- a/sysdeps/sparc/sparc64/dl-machine.h +++ b/sysdeps/sparc/sparc64/dl-machine.h @@ -67,7 +67,26 @@ elf_machine_load_address (void) return pc - *(Elf64_Addr *)(elf_pic_register + la); } +static inline void +elf_machine_fixup_plt(struct link_map *map, const Elf64_Rela *reloc, + Elf64_Addr *reloc_addr, Elf64_Addr value) +{ + Elf64_Dyn *pltfmt = map->l_info[DT_SPARC(PLTFMT)]; + switch (pltfmt ? pltfmt->d_un.d_val : 0) + { + case 1: /* .got.plt with absolute addresses */ + *reloc_addr = value; + break; + case 2: /* .got.plt with got-relative addresses */ + *reloc_addr = value - (map->l_info[DT_PLTGOT]->d_un.d_ptr + map->l_addr); + break; + default: + assert (! "unexpected .plt format type"); + } +} + #ifdef RESOLVE + /* Perform the relocation specified by RELOC and SYM (which is fully resolved). MAP is the object containing the reloc. */ @@ -160,21 +179,7 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, break; case R_SPARC_JMP_SLOT: - { - Elf64_Dyn *pltfmt = map->l_info[DT_SPARC(PLTFMT)]; - switch (pltfmt ? pltfmt->d_un.d_val : 0) - { - case 1: /* .got.plt with absolute addresses */ - *reloc_addr = value; - break; - case 2: /* .got.plt with got-relative addresses */ - *reloc_addr = value - (map->l_info[DT_PLTGOT]->d_un.d_ptr - + map->l_addr); - break; - default: - assert (! "unexpected .plt format type"); - } - } + elf_machine_fixup_plt(map, reloc, reloc_addr, value); break; case R_SPARC_NONE: /* Alright, Wilbur. */ @@ -212,7 +217,7 @@ elf_machine_lazy_rel (struct link_map *map, const Elf64_Rela *reloc) #define elf_machine_lookup_noplt_p(type) ((type) == R_SPARC_JMP_SLOT) /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ -#define ELF_MACHINE_RELOC_NOPLT R_SPARC_JMP_SLOT +#define ELF_MACHINE_JMP_SLOT R_SPARC_JMP_SLOT /* The SPARC never uses Elf64_Rel relocations. */ #define ELF_MACHINE_NO_REL 1 @@ -220,13 +225,6 @@ elf_machine_lazy_rel (struct link_map *map, const Elf64_Rela *reloc) /* The SPARC overlaps DT_RELA and DT_PLTREL. */ #define ELF_MACHINE_PLTREL_OVERLAP 1 -/* The return value from dl-runtime's fixup, if it should be special. */ -#define ELF_FIXUP_RETURN_VALUE(map, result) \ - ((map)->l_info[DT_SPARC(PLTFMT)] \ - && (map)->l_info[DT_SPARC(PLTFMT)]->d_un.d_val == 2 \ - ? (result) + (map)->l_info[DT_PLTGOT]->d_un.d_ptr + (map)->l_addr \ - : (result)) - /* Set up the loaded object described by L so its unrelocated PLT entries will jump to the on-demand fixup code in dl-runtime.c. */ diff --git a/sysdeps/stub/dl-machine.h b/sysdeps/stub/dl-machine.h index 239d0b0e9f..f787df3500 100644 --- a/sysdeps/stub/dl-machine.h +++ b/sysdeps/stub/dl-machine.h @@ -1,5 +1,5 @@ /* Machine-dependent ELF dynamic relocation inline functions. Stub version. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -51,9 +51,14 @@ elf_machine_load_address (void) #error "Where am I?" } -/* This can modify DYNAMIC_INFO to avoid relocating code in - the functions above if they are doing bizarre magic. */ -#define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) /* nothing */ +/* Fixup a PLT entry to bounce directly to the function at VALUE. */ + +static inline void +elf_machine_fixup_plt (struct link_map *map, const Elf32_Rel *reloc, + Elf32_Addr *reloc_addr, Elf32_Addr value) +{ + *reloc_addr = value; +} /* Perform the relocation specified by RELOC and SYM (which is fully resolved). LOADADDR is the load address of the object; INFO is an array indexed @@ -82,7 +87,7 @@ elf_machine_rel (Elf32_Addr loadaddr, Elf32_Dyn *info[DT_NUM], } -static inline void +static inline Elf32_Addr elf_machine_rela (Elf32_Addr loadaddr, Elf32_Dyn *info[DT_NUM], const Elf32_Rel *reloc, const Elf32_Sym *sym, Elf32_Addr (*resolve) (const Elf32_Sym **ref, @@ -107,7 +112,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy) { extern void _dl_runtime_resolve (Elf32_Word); - if (lazy) + if (lazy) { /* The GOT entries for functions in the PLT have not yet been filled in. Their initial contents will arrange when called to push an diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list index a3b0eef691..d5c486d7d0 100644 --- a/sysdeps/unix/sysv/linux/syscalls.list +++ b/sysdeps/unix/sysv/linux/syscalls.list @@ -32,6 +32,7 @@ nfsservctl EXTRA nfsservctl 3 nfsservctl pause - pause 0 __libc_pause pause personality init-first personality 1 __personality personality pipe - pipe 1 __pipe pipe +prctl EXTRA prctl 5 query_module EXTRA query_module 5 query_module quotactl EXTRA quotactl 4 quotactl s_getdents EXTRA getdents 3 __getdents |