summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2005-02-08 10:05:09 +0000
committerJakub Jelinek <jakub@redhat.com>2005-02-08 10:05:09 +0000
commitd585b66fa4d11059948f466c9080a6826932358d (patch)
tree8b06692920852c297635b46a7d616c3066f95fac
parente7cbcee4982d8caa809a91c9cfef5fda67445f0a (diff)
Updated to fedora-glibc-20050208T0948cvs/fedora-glibc-2_3_4-6
-rw-r--r--ChangeLog734
-rw-r--r--Makeconfig19
-rw-r--r--catgets/gencat.c4
-rwxr-xr-xconfigure8
-rw-r--r--configure.in8
-rw-r--r--csu/elf-init.c7
-rw-r--r--csu/version.c2
-rwxr-xr-xdebug/catchsegv.sh2
-rw-r--r--debug/chk_fail.c8
-rwxr-xr-xdebug/xtrace.sh4
-rw-r--r--dirent/tst-seekdir.c28
-rw-r--r--dlfcn/Makefile8
-rw-r--r--dlfcn/dlclose.c3
-rw-r--r--dlfcn/dlfcn.c33
-rw-r--r--dlfcn/dlmopen.c7
-rw-r--r--dlfcn/dlopen.c15
-rw-r--r--dlfcn/dlopenold.c8
-rw-r--r--elf/Makefile31
-rw-r--r--elf/Versions2
-rw-r--r--elf/dl-close.c115
-rw-r--r--elf/dl-debug.c25
-rw-r--r--elf/dl-fini.c94
-rw-r--r--elf/dl-init.c12
-rw-r--r--elf/dl-libc.c14
-rw-r--r--elf/dl-load.c181
-rw-r--r--elf/dl-object.c24
-rw-r--r--elf/dl-open.c238
-rw-r--r--elf/dl-reloc.c65
-rw-r--r--elf/dl-runtime.c285
-rw-r--r--elf/dl-sym.c59
-rw-r--r--elf/dynamic-link.h6
-rw-r--r--elf/ldconfig.c4
-rw-r--r--elf/ldd.bash.in4
-rw-r--r--elf/link.h69
-rw-r--r--elf/rtld.c549
-rw-r--r--elf/sprof.c4
-rw-r--r--elf/tst-align2.c157
-rw-r--r--elf/tst-alignmod2.c60
-rw-r--r--elf/tst-audit1.c1
-rw-r--r--elf/tst-auditmod1.c190
-rw-r--r--fedora/branch.mk4
-rw-r--r--fedora/glibc.spec.in31
-rw-r--r--grp/putgrent.c11
-rw-r--r--hurd/sigunwind.c4
-rw-r--r--iconv/iconv_prog.c16
-rw-r--r--iconv/iconvconfig.c4
-rw-r--r--iconv/strtab.c4
-rw-r--r--iconvdata/jis0208.h20
-rw-r--r--include/dlfcn.h27
-rw-r--r--include/link.h76
-rw-r--r--libio/fmemopen.c1
-rw-r--r--libio/iofopncook.c2
-rw-r--r--libio/stdio.h4
-rw-r--r--linuxthreads/ChangeLog23
-rw-r--r--linuxthreads/Makefile4
-rw-r--r--linuxthreads/pthread.c3
-rw-r--r--linuxthreads/specific.c14
-rw-r--r--linuxthreads/sysdeps/alpha/tls.h9
-rw-r--r--linuxthreads/sysdeps/i386/tls.h9
-rw-r--r--linuxthreads/sysdeps/ia64/tls.h9
-rw-r--r--linuxthreads/sysdeps/powerpc/tls.h15
-rw-r--r--linuxthreads/sysdeps/s390/tls.h9
-rw-r--r--linuxthreads/sysdeps/sh/tls.h9
-rw-r--r--linuxthreads/sysdeps/sparc/tls.h9
-rw-r--r--linuxthreads/sysdeps/x86_64/tls.h9
-rw-r--r--linuxthreads/tst-tsd1.c118
-rw-r--r--linuxthreads_db/ChangeLog4
-rw-r--r--linuxthreads_db/td_thr_tlsbase.c6
-rw-r--r--locale/programs/locale.c4
-rw-r--r--locale/programs/localedef.c4
-rw-r--r--malloc/malloc.c8
-rw-r--r--malloc/malloc.h141
-rwxr-xr-xmalloc/memusage.sh4
-rw-r--r--malloc/mtrace.pl2
-rw-r--r--manual/.cvsignore2
-rw-r--r--manual/memory.texi2
-rw-r--r--manual/string.texi4
-rw-r--r--manual/users.texi3
-rw-r--r--math/math_private.h14
-rw-r--r--misc/sys/cdefs.h13
-rw-r--r--nptl/ChangeLog39
-rw-r--r--nptl/allocatestack.c3
-rw-r--r--nptl/sysdeps/alpha/tls.h9
-rw-r--r--nptl/sysdeps/generic/lowlevellock.h2
-rw-r--r--nptl/sysdeps/i386/tls.h7
-rw-r--r--nptl/sysdeps/ia64/tls.h9
-rw-r--r--nptl/sysdeps/powerpc/tls.h9
-rw-r--r--nptl/sysdeps/pthread/pthread.h4
-rw-r--r--nptl/sysdeps/s390/tls.h9
-rw-r--r--nptl/sysdeps/sh/tls.h9
-rw-r--r--nptl/sysdeps/sparc/tls.h9
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S11
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S11
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S11
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S11
-rw-r--r--nptl/sysdeps/x86_64/tls.h9
-rw-r--r--nscd/Makefile6
-rw-r--r--nscd/connections.c7
-rw-r--r--nscd/nscd.c7
-rw-r--r--nscd/nscd.init10
-rw-r--r--nscd/nscd_getai.c11
-rw-r--r--nscd/nscd_helper.c7
-rw-r--r--nscd/nscd_initgroups.c14
-rw-r--r--nscd/nscd_nischeck.c4
-rw-r--r--nss/getent.c4
-rw-r--r--posix/Makefile13
-rw-r--r--posix/bug-regex19.c22
-rw-r--r--posix/execl.c50
-rw-r--r--posix/execle.c53
-rw-r--r--posix/execlp.c50
-rw-r--r--posix/execvp.c98
-rw-r--r--posix/getconf.c4
-rw-r--r--posix/regcomp.c970
-rw-r--r--posix/regex_internal.c72
-rw-r--r--posix/regex_internal.h33
-rw-r--r--posix/regexec.c50
-rw-r--r--posix/rxspencer/tests9
-rw-r--r--posix/tst-rxspencer.c20
-rw-r--r--posix/unistd.h2
-rw-r--r--pwd/putpwent.c26
-rw-r--r--shadow/sgetspent_r.c6
-rw-r--r--stdio-common/tst-fmemopen2.c1
-rw-r--r--stdlib/Makefile1
-rw-r--r--stdlib/fmtmsg.c25
-rw-r--r--stdlib/stdlib.h2
-rw-r--r--stdlib/tst-fmtmsg.c32
-rw-r--r--sunrpc/openchild.c2
-rw-r--r--sunrpc/rpc_main.c6
-rw-r--r--sunrpc/svc_tcp.c2
-rw-r--r--sunrpc/svc_unix.c2
-rw-r--r--sysdeps/alpha/bits/link.h69
-rw-r--r--sysdeps/alpha/dl-machine.h168
-rw-r--r--sysdeps/alpha/dl-trampoline.S361
-rw-r--r--sysdeps/alpha/fpu/bits/mathinline.h17
-rw-r--r--sysdeps/alpha/libc-tls.c2
-rw-r--r--sysdeps/arm/bits/link.h4
-rw-r--r--sysdeps/arm/bits/linkmap.h4
-rw-r--r--sysdeps/generic/bits/link.h5
-rw-r--r--sysdeps/generic/bits/linkmap.h4
-rw-r--r--sysdeps/generic/dl-fptr.h2
-rw-r--r--sysdeps/generic/dl-lookupcfg.h25
-rw-r--r--sysdeps/generic/dl-tls.c411
-rw-r--r--sysdeps/generic/dl-trampoline.c1
-rw-r--r--sysdeps/generic/ldsodefs.h198
-rw-r--r--sysdeps/generic/libc-start.c24
-rw-r--r--sysdeps/generic/libc-tls.c11
-rw-r--r--sysdeps/generic/syslog.c (renamed from misc/syslog.c)19
-rw-r--r--sysdeps/generic/unsecvars.h17
-rw-r--r--sysdeps/generic/wordexp.c60
-rw-r--r--sysdeps/hppa/bits/link.h6
-rw-r--r--sysdeps/hppa/bits/linkmap.h6
-rw-r--r--sysdeps/hppa/dl-lookupcfg.h6
-rw-r--r--sysdeps/i386/Makefile4
-rw-r--r--sysdeps/i386/bits/link.h65
-rw-r--r--sysdeps/i386/bits/linkmap.h5
-rw-r--r--sysdeps/i386/dl-machine.h149
-rw-r--r--sysdeps/i386/dl-trampoline.S182
-rw-r--r--sysdeps/ia64/bits/link.h68
-rw-r--r--sysdeps/ia64/bits/linkmap.h5
-rw-r--r--sysdeps/ia64/dl-lookupcfg.h19
-rw-r--r--sysdeps/ia64/dl-machine.h159
-rw-r--r--sysdeps/ia64/dl-trampoline.S537
-rw-r--r--sysdeps/ia64/fpu/e_logl.c1
-rw-r--r--sysdeps/ia64/libc-tls.c2
-rw-r--r--sysdeps/linkmap.h4
-rw-r--r--sysdeps/m68k/bits/link.h58
-rw-r--r--sysdeps/m68k/dl-machine.h49
-rw-r--r--sysdeps/m68k/dl-trampoline.S129
-rw-r--r--sysdeps/mach/hurd/tls.h9
-rw-r--r--sysdeps/powerpc/powerpc32/bits/link.h62
-rw-r--r--sysdeps/powerpc/powerpc32/dl-machine.c5
-rw-r--r--sysdeps/powerpc/powerpc32/dl-machine.h175
-rw-r--r--sysdeps/powerpc/powerpc32/dl-trampoline.S174
-rw-r--r--sysdeps/powerpc/powerpc64/bits/link.h109
-rw-r--r--sysdeps/powerpc/powerpc64/dl-lookupcfg.h22
-rw-r--r--sysdeps/powerpc/powerpc64/dl-machine.h96
-rw-r--r--sysdeps/powerpc/powerpc64/dl-trampoline.S196
-rw-r--r--sysdeps/powerpc/tst-stack-align.h47
-rw-r--r--sysdeps/s390/bits/link.h120
-rw-r--r--sysdeps/s390/bits/linkmap.h13
-rw-r--r--sysdeps/s390/bits/string.h14
-rw-r--r--sysdeps/s390/s390-32/dl-machine.h151
-rw-r--r--sysdeps/s390/s390-32/dl-trampoline.S133
-rw-r--r--sysdeps/s390/s390-64/dl-machine.h137
-rw-r--r--sysdeps/s390/s390-64/dl-trampoline.S126
-rw-r--r--sysdeps/sh/bits/link.h75
-rw-r--r--sysdeps/sh/bits/linkmap.h5
-rw-r--r--sysdeps/sh/dl-machine.h297
-rw-r--r--sysdeps/sh/dl-trampoline.S431
-rw-r--r--sysdeps/sh/sh4/Versions5
-rw-r--r--sysdeps/sh/sh4/dl-machine.h2
-rw-r--r--sysdeps/sh/sh4/dl-trampoline.S2
-rw-r--r--sysdeps/unix/i386/sysdep.S12
-rw-r--r--sysdeps/unix/rewinddir.c3
-rw-r--r--sysdeps/unix/sysv/linux/alpha/oldglob.c3
-rw-r--r--sysdeps/unix/sysv/linux/dl-execstack.c26
-rw-r--r--sysdeps/unix/sysv/linux/futimes.c66
-rw-r--r--sysdeps/unix/sysv/linux/i386/sysdep.h37
-rw-r--r--sysdeps/unix/sysv/linux/init-first.c1
-rw-r--r--sysdeps/unix/sysv/linux/kernel-features.h7
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S10
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/swapcontext.S10
-rw-r--r--sysdeps/unix/sysv/linux/syslog.c10
-rw-r--r--sysdeps/x86_64/bits/link.h125
-rw-r--r--sysdeps/x86_64/bits/linkmap.h14
-rw-r--r--sysdeps/x86_64/dl-machine.h157
-rw-r--r--sysdeps/x86_64/dl-trampoline.S188
-rw-r--r--time/strptime_l.c12
-rw-r--r--time/tst-strptime.c22
-rw-r--r--timezone/asia135
-rw-r--r--timezone/backward20
-rw-r--r--timezone/europe18
-rw-r--r--timezone/leapseconds11
-rw-r--r--timezone/northamerica39
-rw-r--r--timezone/private.h13
-rw-r--r--timezone/southamerica17
-rw-r--r--timezone/tzfile.h17
-rw-r--r--timezone/zdump.c377
-rw-r--r--timezone/zic.c89
219 files changed, 8747 insertions, 3479 deletions
diff --git a/ChangeLog b/ChangeLog
index ab874d8fed..ba9d876327 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,736 @@
+2005-02-07 Richard Henderson <rth@redhat.com>
+
+ * iconvdata/jis0208.h (struct jisx0208_ucs_idx): Move before use.
+
+2005-02-08 Kaz Kojima <kkojima@rr.iij4u.or.jp>
+
+ * sysdeps/sh/dl-machine.h (elf_machine_rela): Remove code using
+ RESOLVE.
+
+2005-02-07 Ulrich Drepper <drepper@redhat.com>
+
+ * elf/dl-load.c (_dl_map_object_from_fd): Makre sure registers are
+ set correctly.
+
+2005-01-07 Richard Henderson <rth@redhat.com>
+
+ * math/math_private.h (__copysign): Define as builtin for gcc 4.
+ (__copysignf, __copysignl): Likewise.
+ * sysdeps/alpha/fpu/bits/mathinline.h (copysign): Don't define
+ for gcc 4.0.
+ (copysignf, copysignl, fabsf, fabs): Likewise.
+ (__copysign, __copysignf, __copysignl): Remove.
+ (__fabs, __fabsf): Remove.
+
+2005-01-07 Jakub Jelinek <jakub@redhat.com>
+
+ * elf/dl-load.c (open_path): If rtld_search_dirs is in RELRO segment,
+ avoid writing to it if none of the standard search directories exist.
+
+2005-02-07 Steven Munroe <sjmunroe@us.ibm.com>
+
+ [BZ #700]
+ * sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S
+ (__novec_setcontext, __setcontext): Fix typo so CCR is restored.
+ Load MSR as a doubleword.
+ * sysdeps/unix/sysv/linux/powerpc/powerpc64/swapcontext.S
+ (__novec_swapcontext, __swapcontext): Likewise.
+
+2005-02-07 Ulrich Drepper <drepper@redhat.com>
+
+ * iconv/iconv_prog.c (main): Provide more help in case on an error.
+
+ * sysdeps/unix/sysv/linux/i386/sysdep.h (check_consistency): Define.
+
+2005-02-07 Jakub Jelinek <jakub@redhat.com>
+
+ * nscd/nscd.c (termination_handler): Avoid segfault if some database
+ is not enabled.
+
+ * nscd/nscd_getai.c (__nscd_getai): If ai_resp->found == -1, set
+ __nss_not_use_nscd_hosts and return -1.
+ * nscd/nscd_initgroups.c (__nscd_getgrouplist): If
+ initgr_resp->found == -1, set __nss_not_use_nscd_group and return -1.
+ Avoid leaking sockets.
+
+2005-01-28 Andreas Schwab <schwab@suse.de>
+ H.J. Lu <hongjiu.lu@intel.com>
+
+ [BZ #677]
+ * elf/dl-runtime.c (fixup): Change return type to
+ DL_FIXUP_VALUE_TYPE. Use DL_FIXUP_VALUE_TYPE,
+ DL_FIXUP_MAKE_VALUE and DL_FIXUP_VALUE_CODE_ADDR for relocation
+ values. Use DL_FIXUP_VALUE_ADDR and DL_FIXUP_ADDR_VALUE to
+ store and retrieve relocation values.
+ (profile_fixup): Likewise.
+ * include/link.h (link_map): Use DL_FIXUP_VALUE_TYPE for
+ l_reloc_result.
+ * sysdeps/generic/dl-fptr.h (link_map): Forward declaration.
+ * sysdeps/generic/dl-lookupcfg.h (DL_FIXUP_VALUE_TYPE): New.
+ (DL_FIXUP_MAKE_VALUE): Likewise.
+ (DL_FIXUP_VALUE_CODE_ADDR): Likewise.
+ (DL_FIXUP_VALUE_ADDR): Likewise.
+ (DL_FIXUP_ADDR_VALUE): Likewise.
+ * sysdeps/ia64/dl-lookupcfg.h: Include <dl-fptr.h> for "struct fdesc".
+ (DL_FIXUP_VALUE_TYPE): New.
+ (DL_FIXUP_MAKE_VALUE): Likewise.
+ (DL_FIXUP_VALUE_CODE_ADDR): Likewise.
+ (DL_FIXUP_VALUE_ADDR): Likewise.
+ (DL_FIXUP_ADDR_VALUE): Likewise.
+ * sysdeps/ia64/dl-machine.h (elf_machine_profile_fixup_plt): Removed.
+ (elf_machine_profile_plt): Removed.
+ (elf_machine_fixup_plt): Change return type and type of value
+ parameter to struct fdesc.
+ (elf_machine_plt_value): Likewise.
+ (elf_machine_rela): Use DL_FIXUP_MAKE_VALUE to construct
+ argument for elf_machine_fixup_plt.
+
+2005-02-07 Jakub Jelinek <jakub@redhat.com>
+
+ * nscd/nscd.init (reload): Print Reloading nscd: before and a newline
+ after the status string printed by killproc.
+
+2004-11-18 Alexandre Oliva <aoliva@redhat.com>
+
+ * manual/.cvsignore: Add dir-add.texi.
+
+2005-02-06 Richard Henderson <rth@redhat.com>
+
+ * sysdeps/alpha/dl-machine.h (elf_machine_rela): Use RESOLVE_MAP
+ all the time.
+
+2004-11-03 Marcus Brinkmann <marcus@gnu.org>
+
+ * configure.in (sysnames): Append sysdeps/generic for each add-on.
+ * configure: Regenerated.
+
+2005-02-02 Alfred M. Szmidt <ams@gnu.org>
+
+ * sysdeps/mach/hurd/tls.h: Include <stdbool.h>
+ (dtv_t): Change pointer type to be a struct which also contains
+ information whether the memory pointed to is static TLS or not.
+
+ * sysdeps/generic/syslog.c (send_flags) [!send_flags]: Define it.
+
+ * shadow/sgetspent_r.c (FALSE): Macro renamed to ...
+ (FALSEP): ... this. Updated all references.
+
+ * libio/fmemopen.c: Include <stdint.h>.
+
+2005-01-30 Ulrich Drepper <drepper@redhat.com>
+
+ * nscd/nscd_helper.c (get_mapping): Use MSG_NOSIGNAL if available.
+ * nscd/connections.c (send_ro_fd): Likewise.
+
+2005-01-28 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elf/tst-auditmod1.c: Add ia64 entries.
+ * sysdeps/generic/ldsodefs.h (La_ia64_regs): New.
+ (La_ia64_retval): New.
+ (audit_ifaces): Add ia64 entries.
+ * sysdeps/ia64/bits/link.h: New file.
+ * sysdeps/ia64/dl-machine.h (elf_machine_runtime_setup): Test
+ for dl_profile non-null.
+ (ARCH_LA_PLTENTER): New.
+ (ARCH_LA_PLTEXIT): New.
+ * sysdeps/ia64/dl-trampoline.S (_dl_runtime_resolve): Allocate
+ only 2 output registers. Allocate stack to save/restore
+ 8 incoming fp registers. Call _dl_fixup instead of fixup.
+ (_dl_runtime_profile): Rewrite.
+
+2005-01-28 Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+ * sysdeps/s390/bits/link.h: New file.
+ * sysdeps/s390/s390-32/dl-trampoline.S: New file.
+ * sysdeps/s390/s390-64/dl-trampoline.S: New file.
+ * sysdeps/s390/s390-32/dl-machine.h: Move PLT trampolines to
+ dl-trampoline.S. Use RESOLVE_MAP instead of RESOLVE to protect
+ relocation code.
+ (elf_machine_runtime_setup): Test for dl_profile non-null.
+ (elf_machine_rela): Remove code using RESOLVE.
+ (ARCH_LA_PLTENTER, ARCH_LA_PLTEXIT): New.
+ * sysdeps/s390/s390-64/dl-machine.h: Likewise.
+ * sysdeps/generic/ldsodefs.h (La_s390_32_regs, La_s390_32_retval,
+ La_s390_64_regs, La_s390_64_retval): New.
+ * elf/tst-auditmod1.c: Add s390 entries.
+
+ * sysdeps/s390/bits/string.h (strlen, strncpy, strcat, strncat,
+ strncat, memchr, strcmp): Add missing memory clobber.
+
+2005-01-27 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/unix/sysv/linux/alpha/oldglob.c (__old_globfree): Also
+ copy gl_offs. Patch by Sergey Tikhonov <tsv@solvo.ru>.
+
+2005-01-27 Paolo Bonzini <bonzini@gnu.org>
+
+ [BZ #558]
+ * posix/regcomp.c (calc_inveclosure): Return reg_errcode_t.
+ Initialize the node sets in dfa->inveclosures.
+ (analyze): Initialize inveclosures only if it is needed.
+ Check errors from calc_inveclosure.
+ * posix/regex_internal.c (re_dfa_add_node): Do not initialize
+ the inveclosure node set.
+ * posix/regexec.c (re_search_internal): If nmatch includes unused
+ subexpressions, reset them to { rm_so: -1, rm_eo: -1 } here.
+
+ * posix/regcomp.c (parse_bracket_exp) [!RE_ENABLE_I18N]:
+ Do build a SIMPLE_BRACKET token.
+
+ * posix/regexec.c (transit_state_mb): Do not examine nodes
+ where ACCEPT_MB is not set.
+
+2005-01-27 Jakub Jelinek <jakub@redhat.com>
+
+ * stdlib/tst-fmtmsg.c: Include stdlib.h.
+ * stdio-common/tst-fmemopen2.c: Include string.h.
+ * posix/execvp.c: Include stdbool.h.
+
+2004-12-13 Paolo Bonzini <bonzini@gnu.org>
+
+ Separate parsing and creation of the NFA. Avoided recursion on
+ the (very unbalanced) parse tree.
+ [BZ #611]
+ * posix/regcomp.c (struct subexp_optimize, analyze_tree, calc_epsdest,
+ re_dfa_add_tree_node, mark_opt_subexp_iter): Removed.
+ (optimize_subexps, duplicate_tree, calc_first, calc_next,
+ mark_opt_subexp): Rewritten.
+ (preorder, postorder, lower_subexps, lower_subexp, link_nfa_nodes,
+ create_token_tree, free_tree, free_token): New.
+ (analyze): Accept a regex_t *. Invoke the passes via the preorder and
+ postorder generic visitors. Do not initialize the fields in the
+ re_dfa_t that represent the transitions.
+ (free_dfa_content): Use free_token.
+ (re_compile_internal): Analyze before UTF-8 optimizations. Do not
+ include optimization of subexpressions.
+ (create_initial_state): Fetch the DFA node index from the first node's
+ bin_tree_t *.
+ (optimize_utf8): Abort on unexpected nodes, including OP_DUP_QUESTION.
+ Return on COMPLEX_BRACKET.
+ (duplicate_node_closure): Fix comment.
+ (duplicate_node): Do not initialize the fields in the
+ re_dfa_t that represent the transitions.
+ (calc_eclosure, calc_inveclosure): Do not handle OP_DELETED_SUBEXP.
+ (create_tree): Remove final argument. All callers adjusted. Rewritten
+ to use create_token_tree.
+ (parse_reg_exp, parse_branch, parse_expression, parse_bracket_exp,
+ build_charclass_op): Use create_tree or create_token_tree instead
+ of re_dfa_add_tree_node.
+ (parse_dup_op): Likewise. Also free the tree using free_tree for
+ "<re>{0}", and lower OP_DUP_QUESTION to OP_ALT: "a?" is equivalent
+ to "a|". Adjust invocation of mark_opt_subexp.
+ (parse_sub_exp): Create a single SUBEXP node.
+ * posix/regex_internal.c (re_dfa_add_node): Remove last parameter,
+ always perform as if it was 1. Do not initialize OPT_SUBEXP and
+ DUPLICATED, and initialize the DFA fields representing the transitions.
+ * posix/regex_internal.h (re_dfa_add_node): Adjust prototype.
+ (re_token_type_t): Move OP_DUP_PLUS and OP_DUP_QUESTION to the tokens
+ section. Add a tree-only code SUBEXP. Remove OP_DELETED_SUBEXP.
+ (bin_tree_t): Include a full re_token_t for TOKEN. Turn FIRST and
+ NEXT into pointers to trees. Remove ECLOSURE.
+
+2004-12-28 Paolo Bonzini <bonzini@gnu.org >
+
+ [BZ #605]
+ * posix/regcomp.c (parse_bracket_exp): Do not modify DFA nodes
+ that were already created.
+ * posix/regex_internal.c (re_dfa_add_node): Set accept_mb field
+ in the token if needed.
+ (create_ci_newstate, create_cd_newstate): Set accept_mb field
+ from the tokens' field.
+ * posix/regex_internal.h (re_token_t): Add accept_mb field.
+ (ACCEPT_MB_NODE): Removed.
+ * posix/regexec.c (proceed_next_node, transit_states_mb,
+ build_sifted_states, check_arrival_add_next_nodes): Use
+ accept_mb instead of ACCEPT_MB_NODE.
+
+2005-01-26 Ulrich Drepper <drepper@redhat.com>
+
+ * debug/chk_fail.c (__chk_fail): Print program name in final message.
+
+ * sysdeps/unix/sysv/linux/kernel-features.h: Found reference to
+ MSG_NOSIGNAL being in 2.2 kernels.
+
+2005-01-26 Jakub Jelinek <jakub@redhat.com>
+
+ * sysdeps/unix/sysv/linux/i386/sysdep.h
+ (SYSCALL_ERROR_HANDLER_TLS_STORE): Remove unnecessary 0 imm.
+
+ [BZ #693]
+ * posix/regex_internal.h (DUMMY_CONSTRAINT): Rename to...
+ (WORD_DELIM_CONSTRAINT): ...this.
+ (NOT_WORD_DELIM_CONSTRAINT): Define.
+ (re_context_type): Add INSIDE_NOTWORD and NOT_WORD_DELIM,
+ change WORD_DELIM to use WORD_DELIM_CONSTRAINT.
+ * posix/regcomp.c (peek_token): For \B create NOT_WORD_DELIM
+ anchor instead of INSIDE_WORD.
+ (parse_expression): Handle NOT_WORD_DELIM constraint.
+ * posix/bug-regex19.c (tests): Adjust tests that relied on \B
+ being inside word instead of not word delim.
+ * posix/tst-rxspencer.c (mb_frob_pattern): Don't frob escaped
+ characters.
+ * posix/rxspencer/tests: Add some new tests.
+
+2005-01-14 GOTO Masanori <gotom@debian.or.jp>
+
+ * sunrpc/rpc_main.c (s_output): Generate #include <rpc/pmap_clnt.h>
+ irrespective of Cflag.
+
+ * manual/memory.texi (sbrk): Fix definition.
+ * manual/string.texi (strcasestr): Fix example typo.
+
+2005-01-25 Roland McGrath <roland@redhat.com>
+
+ * sysdeps/generic/syslog.c [NO_SIGPIPE]: Protect sigpipe_handler decl.
+
+2005-01-23 Roland McGrath <roland@redhat.com>
+
+ * sysdeps/i386/Makefile (defines): If -mno-tls-direct-seg-refs appears
+ in $(CFLAGS), add -DNO_TLS_DIRECT_SEG_REFS.
+ * sysdeps/unix/sysv/linux/i386/sysdep.h [USE___THREAD]
+ (SYSCALL_ERROR_HANDLER) [NO_TLS_DIRECT_SEG_REFS]: Load thread pointer
+ from %gs:0 and add to that value, rather that direct %gs:OFFSET access.
+ * sysdeps/unix/i386/sysdep.S [NO_TLS_DIRECT_SEG_REFS]: Likewise.
+
+2005-01-25 Jakub Jelinek <jakub@redhat.com>
+
+ * stdlib/fmtmsg.c (addseverity): Remove new_string variable.
+ (free_mem): Don't free string.
+ * stdlib/tst-fmtmsg.c: Include string.h.
+ (main): Add some more tests.
+
+2005-01-25 Andreas Schwab <schwab@suse.de>
+
+ * timezone/asia: Update from tzdata2005c.
+ * timezone/backward: Likewise.
+ * timezone/leapseconds: Likewise.
+ * timezone/northamerica: Likewise.
+ * timezone/southamerica: Likewise.
+
+ * timezone/private.h: Update from tzcode2005c.
+ * timezone/tzfile.h: Likewise.
+ * timezone/zdump.c: Likewise.
+ * timezone/zic.c: Likewise.
+
+2005-01-25 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/i386/dl-machine.h (elf_machine_rel): Remove code using
+ RESOLVE.
+ * sysdeps/x86_64/dl-machine.h (elf_machine_rela): Remove code
+ using RESOLVE.
+ * elf/rtld.c (_dl_start): Remove RESOLVE definition.
+
+2005-01-25 Alan Modra <amodra@bigpond.net.au>
+
+ * sysdeps/powerpc/powerpc32/dl-machine.h (elf_machine_rela): Test
+ sym_map, not sym, against zero.
+
+2005-01-24 Ulrich Drepper <drepper@redhat.com>
+
+ * misc/syslog.c: Moved to...
+ * sysdeps/generic/syslog.c: ...here.
+ [NO_SIGIPE]: Don't install SIGPIPE handler.
+ * sysdeps/unix/sysv/linux/syslog.c: New file.
+ * sysdeps/unix/sysv/linux/kernel-features.h: Define
+ __ASSUME_MSG_NOSIGNAL.
+
+2005-01-22 Richard Henderson <rth@redhat.com>
+
+ * sysdeps/alpha/dl-trampoline.S: New file.
+ * sysdeps/alpha/dl-machine.h: Move PLT trampolines there.
+ Use RESOLVE_MAP instead of RESOLVE to protect relocation code.
+ (elf_machine_runtime_setup): Test for dl_profile non-null.
+ (ARCH_LA_PLTENTER, ARCH_LA_PLTEXIT): New.
+ * sysdeps/alpha/bits/link.h: New file.
+ * sysdeps/generic/ldsodefs.h (La_alpha_regs, La_alpha_retval): New.
+ (struct audit_ifaces): Add alpha entries.
+ * elf/tst-auditmod1.c: Add alpha entries.
+
+2005-01-22 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/ia64/dl-machine.h: Remove PLT trampolines here.
+ * sysdeps/ia64/dl-trampoline.S: New file.
+
+ * sysdeps/x86_64/bits/link.h: Use namespace-safe identifiers in
+ La_x86_64_xmm definition.
+
+ * posix/Makefile: Use CFLAGS-*.os instead of CFLAGS-*.c for frame
+ pointer option.
+ * stdlib/Makefile (CFLAGS-system.os): Use this instead of
+ CFLAGS-system.c for frame pointer option.
+
+2005-01-21 Roland McGrath <roland@redhat.com>
+
+ * elf/dl-runtime.c (_dl_profile_fixup): Remove const from REGS.
+ * sysdeps/i386/dl-machine.h: Update decl.
+
+2005-01-21 Jakub Jelinek <jakub@redhat.com>
+
+ * elf/Makefile: Add rules to build and run tst-align2.
+ * elf/tst-align2.c: New test.
+ * elf/tst-alignmod2.c: New file.
+ * sysdeps/powerpc/tst-stack-align.h: New file.
+ * sysdeps/i386/dl-machine.h (RTLD_START): Align stack and clear frame
+ pointer before calling _dl_init.
+ * sysdeps/x86_64/dl-machine.h (RTLD_START): Likewise.
+
+2005-01-20 Ulrich Drepper <drepper@redhat.com>
+
+ * posix/execl.c: Do not allocate potentially large buffers on the
+ stack.
+ * posix/execle.c: Likewise.
+ * posix/execlp.c: Likewise.
+ * posix/execlp.c: Likewise.
+ (script_execute): Removed.
+ (allocate_scripts_argv): New function. Called at most once to
+ allocate memory, not every time a script is run. Adjust caller.
+
+ * sysdeps/generic/wordexp.c (exec_comm): Add a few
+ TEMP_FAILURE_RETRY. Reorganize code to avoid multiple calls to
+ exec_comm_child.
+ (exec_comm_child): Can now be inlined.
+
+ * posix/Makefile: Add -fomit-frame-pointer for a few more files.
+ * stdlib/Makefile: Likewise.
+
+2005-01-19 Roland McGrath <roland@redhat.com>
+
+ [BZ #681]
+ * sunrpc/openchild.c (_openchild): Use NULL instead of 0 for trailing
+ argument to execlp.
+ Reported by Marcus Meissner <meissner@suse.de>.
+
+2005-01-19 Jakub Jelinek <jakub@redhat.com>
+
+ * hurd/sigunwind.c (_hurdsig_longjmp_from_handler): Fix a typo
+ in assert.
+ * iconv/strtab.c (strtabfinalize): Likewise.
+
+ * libio/iofopncook.c (_IO_cookie_seekoff): Add prototype.
+
+2005-01-17 Roland McGrath <roland@redhat.com>
+
+ * nscd/Makefile (LDLIBS-nscd): New variable.
+ ($(objpfx)nscd): Use that instead of selinux-LIBS.
+
+ * Makeconfig (link-extra-libs): Define just as $(LDLIBS-$(@F)).
+ (link-extra-libs-static): Define to $(link-extra-libs).
+ (link-extra-libs-bounded): Likewise.
+
+2005-01-17 Ulrich Drepper <drepper@redhat.com>
+
+ * include/link.h: Remove stray definition of pltenter.
+
+2005-01-16 GOTO Masanori <gotom@debian.or.jp>
+
+ * sysdeps/unix/rewinddir.c: Reset filepos.
+ * dirent/tst-seekdir.c: Check telldir value after calling rewinddir.
+
+2005-01-15 Ulrich Drepper <drepper@redhat.com>
+
+ * elf/tst-auditmod1.c: Reduce duplication.
+
+2005-01-16 Andreas Schwab <schwab@suse.de>
+
+ * sysdeps/m68k/dl-machine.h: Remove trampoline code. Define
+ ARCH_LA_PLTENTER and ARCH_LA_PLTEXIT.
+ (elf_machine_runtime_setup): If profile != 0 does not anymore mean
+ GLRO(dl_profile) != NULL.
+ * sysdeps/m68k/dl-trampoline.S: New file.
+ * sysdeps/m68k/bits/link.h: New file.
+ * sysdeps/generic/ldsodefs.h (struct audit_ifaces): Add m68k
+ variants.
+ * elf/tst-auditmod1.c: Add m68k support.
+
+2005-01-14 Ulrich Drepper <drepper@redhat.com>
+
+ * posix/regcomp.c [!_LIBC] (init_dfa): Fix determining of relevant
+ LC_* variable. Patch by Aharon Robbins <arnold@skeeve.com>.
+
+ * stdlib/fmtmsg.c (internal_addseverity): Remove incorrect free call.
+ * stdlib/tst-fmtmsg.c (main): Add another addseverity test.
+
+2005-01-12 Ulrich Drepper <drepper@redhat.com>
+
+ * elf/dl-load.c (_dl_map_object_from_fd): We don't have to allow
+ callers from libc anymore.
+
+ * elf/dl-open.c (dl_open_worker): Pass __RTLD_AUDIT flag from caller
+ to _dl_map_object_deps.
+ * elf/dl-load.c (_dl_map_object_from_fd): Don't change memory
+ protections when loading auditing modules.
+
+ * dlfcn/dlopen.c (dlopen_doit): Catch invalid mode arguments and fail.
+
+ * posix/getconf.c: Update copyright year.
+ * nss/getent.c: Likewise.
+ * nscd/nscd_nischeck.c: Likewise.
+ * iconv/iconvconfig.c: Likewise.
+ * iconv/iconv_prog.c: Likewise.
+ * elf/ldconfig.c: Likewise.
+ * catgets/gencat.c: Likewise.
+ * csu/version.c: Likewise.
+ * elf/ldd.bash.in: Likewise.
+ * elf/sprof.c (print_version): Likewise.
+ * locale/programs/locale.c: Likewise.
+ * locale/programs/localedef.c: Likewise.
+ * nscd/nscd.c (print_version): Likewise.
+ * debug/xtrace.sh: Likewise.
+ * malloc/memusage.sh: Likewise.
+ * malloc/mtrace.pl: Likewise.
+ * debug/catchsegv.sh: Likewise.
+
+2005-01-11 Thorsten Kukuk <kukuk@suse.de>
+
+ * sunrpc/svc_tcp.c (svctcp_create): Call listen with SOMAXCONN
+ as backlog.
+ * sunrpc/svc_unix.c (svcunix_create): Likewise.
+
+ * grp/putgrent.c (putgrent): Don't write 0 as group
+ ID if groupname starts with + or -.
+ * pwd/putpwent.c (putpwent): Don't write 0 as user or
+ group ID if user name starts with + or -.
+
+2005-01-09 Kaz Kojima <kkojima@rr.iij4u.or.jp>
+
+ * sysdeps/generic/ldsodefs.h (struct audit_ifaces): Add sh variants.
+ * sysdeps/elf/tst-auditmod1.c: Add sh support.
+ * sysdeps/sh/bits/link.h: New.
+ * sysdeps/sh/dl-machine.h: Remove trampoline code here. Define
+ ARCH_LA_PLTENTER and ARCH_LA_PLTEXIT. Remove obsolete comments.
+ (RTLD_START): Define __fpscr_values.
+ * sysdeps/sh/dl-trampoline.S: New file.
+ * sysdeps/sh/sh4/dl-trampoline.S: New file.
+ * sysdeps/sh/sh4/Versions [ld]: Add __fpscr_values.
+ * sysdeps/sh/sh4/dl-machine.h: Remove.
+
+2005-01-10 Jakub Jelinek <jakub@redhat.com>
+
+ * time/tst-strptime.c (day_tests): Add 2 new tests.
+ (test_tm, main): Issue an error instead of segfaulting if
+ strptime returns NULL.
+
+2005-01-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/alpha/libc-tls.c (__tls_get_addr): Updated for dtv_t union.
+ * sysdeps/ia64/libc-tls.c (__tls_get_addr): Likewise.
+
+2005-01-11 Ulrich Drepper <drepper@redhat.com>
+
+ * malloc/malloc.h: Remove no-glibc support.
+
+2005-01-12 GOTO Masanori <gotom@debian.or.jp>
+
+ [BZ #650]
+ * malloc/malloc.h: Always include features.h.
+
+2005-01-10 Roland McGrath <roland@redhat.com>
+
+ * sysdeps/ia64/fpu/e_logl.c: File removed.
+
+ * dlfcn/dlfcn.c (init): Fix typo in attribute decl.
+
+2005-01-10 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/generic/dl-tls.c (_dl_next_tls_modid): Fix assertion and
+ recognition of last entry.
+
+2005-01-09 Ulrich Drepper <drepper@redhat.com>
+
+ * elf/dl-runtime.c: Include <sys/param.h>.
+
+ * elf/Makefile (headers): Add bits/link.h.
+
+2005-01-09 Andreas Schwab <schwab@suse.de>
+
+ * elf/rtld.c (dl_main): Create main_map with __RTLD_OPENEXEC.
+
+2005-01-09 Andreas Jaeger <aj@suse.de>
+
+ * time/strptime_l.c (__strptime_internal): Add braces to avoid
+ warning.
+
+ * sysdeps/x86_64/bits/link.h: Use vector_size for GCC 4.0.
+
+ * elf/rtld.c (dl_main): Call _dl_add_to_slotinfo only if USE_TLS.
+
+2005-01-08 Jakub Jelinek <jakub@redhat.com>
+
+ * elf/Makefile (generated): Add tst-pie1{,.out,.o}.
+
+2005-01-09 Ulrich Drepper <drepper@redhat.com>
+
+ * elf/dl-fini.c (_dl_fini): Call destructors of audit DSOs after
+ those of all the regular objects.
+
+ * elf/dl-debug.c (_dl_debug_initialize): Take extra parameter and
+ use it to select the r_debug structure for that namespace.
+ * elf/dl-close.c (_dl_close): Adjust call to _dl_debug_initialize.
+ * elf/dl-load.c (_dl_map_object_from_fd): Likewise.
+ * elf/dl-open.c (_dl_open): Likewise.
+ * elf/rtld.c (dl_main): Likewise.
+ * sysdeps/generic/ldsodefs.h (struct link_namespaces): Add _ns_debug
+ member.
+ (_dl_debug_initialize): Add new parameter in declaration.
+
+ * elf/dl-close.c (_dl_close): Make sure auditing callbacks are not
+ called for the auditing objects themselves.
+ * elf/dl-load.c (_dl_map_object_from_fd): Likewise.
+
+2005-01-07 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/powerpc/powerpc64/dl-machine.h
+ (elf_machine_runtime_setup): If profile != 0 does not anymore mean
+ GLRO(dl_profile) != NULL.
+ * sysdeps/powerpc/powerpc64/bits/link.h (struct la_ppc64_regs): Add
+ padding.
+ * sysdeps/powerpc/powerpc64/dl-trampoline.S: (_dl_profile_resolve):
+ Extend _dl_prof_resolve to add pass extra parameters to
+ _dl_profile_fixup and set up structure with register content.
+
+ * sysdeps/powerpc/powerpc32/dl-machine.c (__elf_machine_runtime_setup):
+ If profile != 0 does not anymore mean GLRO(dl_profile) != NULL.
+ * sysdeps/powerpc/powerpc32/dl-trampoline.S (_dl_prof_resolve):
+ Extend _dl_prof_resolve to add pass extra parameters to
+ _dl_profile_fixup and set up structure with register content.
+ * sysdeps/powerpc/powerpc32/bits/link.h: Fix types of some fields in
+ the register and result structures.
+ * sysdeps/powerpc/powerpc64/bits/link.h: Fix types of some fields
+ in the 32-bit register and result structures.
+
+ * sysdeps/powerpc/powerpc64/dl-trampoline.S: Use register names.
+
+ * sysdeps/powerpc/powerpc32/dl-trampoline.S: New file.
+ * sysdeps/powerpc/powerpc32/dl-machine.h: Remove trampoline code here.
+ Define ARCH_LA_PLTENTER and ARCH_LA_PLTEXIT.
+ * sysdeps/generic/ldsodefs.h (struct audit_ifaces): Add ppc32 variants.
+ * elf/tst-auditmod1.c: Add ppc32 support.
+ * sysdeps/powerpc/powerpc32/bits/link.h: New file.
+ * sysdeps/powerpc/powerpc64/bits/link.h: Add ppc32 definitions.
+
+ * malloc/malloc.c (malloc_printerr): Print program name as part of
+ error message.
+
+ * misc/sys/cdefs.h (__attribute_warn_unused_result__): Define.
+ * stdlib/stdlib.h: Make realloc with
+ __attribute_warn_unused_result__ instead of __wur.
+ * malloc/malloc.h: Add __wur and __attribute_warn_unused_result__
+ markers as in <stdlib.h>.
+
+ * libio/stdio.h: Remove __wur from rename and remove.
+ * posix/unistd.h: Remove __wur from dup2.
+
+2005-01-03 Andreas Jaeger <aj@suse.de>
+
+ * elf/Makefile (tests): Revert patch from 2005-01-03.
+
+2005-01-07 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/unix/sysv/linux/init-first.c (__libc_init_first): Don't
+ make __libc_init_first hidden.
+
+ * elf/rtld.c [!DONT_USE_BOOTSTRAP_MAP] (_dl_start_final): Initialize
+ l_relocated of rtld map.
+ * sysdeps/powerpc/powerpc64/dl-trampoline.S: New file.
+ * sysdeps/powerpc/powerpc64/dl-machine.h: Remove trampoline code here.
+ Define ARCH_LA_PLTENTER and ARCH_LA_PLTEXIT.
+ * sysdeps/generic/ldsodefs.h (struct audit_ifaces): Add ppc64 variants.
+ * elf/tst-auditmod1.c: Add ppc64 support.
+ * sysdeps/powerpc/powerpc64/bits/link.h: New file.
+
+2005-01-06 Roland McGrath <roland@redhat.com>
+
+ [BZ #633]
+ * sysdeps/unix/sysv/linux/futimes.c (__futimes): Catch errno values
+ indicating file-name lookup errors, and return ENOSYS or EBADF instead.
+
2005-01-06 Ulrich Drepper <drepper@redhat.com>
+ * csu/elf-init.c (__libc_csu_fini): Don't do anything here.
+ * sysdeps/generic/libc-start.c: Don't register program destructor here.
+
+ * dlfcn/Makefile: Add rules to build dlfcn.c.
+ (LDFLAGS-dl.so): Removed.
+ * dlfcn/dlclose.c: _dl_close is now in ld.so, use function pointer
+ table.
+ * dlfcn/dlmopen.c: Likewise for _dl_open.
+ * dlfcn/dlopen.c: Likewise.
+ * dlfcn/dlopenold.c: Likewise.
+ * elf/dl-libc.c: Likewise for _dl_open and _dl_close.
+ * elf/Makefile (routines): Remove dl-open and dl-close.
+ (dl-routines): Add dl-open, dl-close, and dl-trampoline.
+ Add rules to build and run tst-audit1.
+ * elf/tst-audit1.c: New file.
+ * elf/tst-auditmod1.c: New file.
+ * elf/Versions [libc]: Remove _dl_open and _dl_close.
+ * elf/dl-close.c: Change for use inside ld.so instead of libc.so.
+ * elf/dl-open.c: Likewise.
+ * elf/dl-debug.c (_dl_debug_initialize): Allow reinitialization,
+ signaled by nonzero parameter.
+ * elf/dl-init.c: Fix use of r_state.
+ * elf/dl-load.c: Likewise.
+
+ * elf/dl-close.c: Add auditing checkpoints.
+ * elf/dl-open.c: Likewise.
+ * elf/dl-fini.c: Likewise.
+ * elf/dl-load.c: Likewise.
+ * elf/dl-sym.c: Likewise.
+ * sysdeps/generic/libc-start.c: Likewise.
+ * elf/dl-object.c: Allocate memory for auditing information.
+ * elf/dl-reloc.c: Remove RESOLV. We now always need the map.
+ Correctly initialize slotinfo.
+ * elf/dynamic-link.h: Adjust after removal of RESOLV.
+ * sysdeps/hppa/dl-lookupcfg.h: Likewise.
+ * sysdeps/ia64/dl-lookupcfg.h: Likewise.
+ * sysdeps/powerpc/powerpc64/dl-lookupcfg.h: Removed.
+ * elf/dl-runtime.c (_dl_fixup): Little cleanup.
+ (_dl_profile_fixup): New parameters to point to register struct and
+ variable for frame size.
+ Add auditing checkpoints.
+ (_dl_call_pltexit): New function.
+ Don't define trampoline code here.
+ * elf/rtld.c: Recognize LD_AUDIT. Load modules on startup.
+ Remove all the functions from _rtld_global_ro which only _dl_open
+ and _dl_close needed.
+ Add auditing checkpoints.
+ * elf/link.h: Define symbols for auditing interfaces.
+ * include/link.h: Likewise.
+ * include/dlfcn.h: Define __RTLD_AUDIT.
+ Remove prototypes for _dl_open and _dl_close.
+ Adjust access to argc and argv in libdl.
+ * dlfcn/dlfcn.c: New file.
+ * sysdeps/generic/dl-lookupcfg.h: Remove all content now that RESOLVE
+ is gone.
+ * sysdeps/generic/ldsodefs.h: Add definitions for auditing interfaces.
+ * sysdeps/generic/unsecvars.h: Add LD_AUDIT.
+ * sysdeps/i386/dl-machine.h: Remove trampoline code here.
+ Adjust for removal of RESOLVE.
+ * sysdeps/x86_64/dl-machine.h: Likewise.
+ * sysdeps/generic/dl-trampoline.c: New file.
+ * sysdeps/i386/dl-trampoline.c: New file.
+ * sysdeps/x86_64/dl-trampoline.c: New file.
+
+ * sysdeps/generic/dl-tls.c: Cleanups. Fixup for dtv_t change.
+ Fix updating of DTV.
+ * sysdeps/generic/libc-tls.c: Likewise.
+
+ * sysdeps/arm/bits/link.h: Renamed to ...
+ * sysdeps/arm/bits/linkmap.h: ...this.
+ * sysdeps/generic/bits/link.h: Renamed to...
+ * sysdeps/generic/bits/linkmap.h: ...this.
+ * sysdeps/hppa/bits/link.h: Renamed to...
+ * sysdeps/hppa/bits/linkmap.h: ...this.
+ * sysdeps/i386/bits/link.h: Renamed to...
+ * sysdeps/i386/bits/linkmap.h: ...this.
+ * sysdeps/ia64/bits/link.h: Renamed to...
+ * sysdeps/ia64/bits/linkmap.h: ...this.
+ * sysdeps/s390/bits/link.h: Renamed to...
+ * sysdeps/s390/bits/linkmap.h: ...this.
+ * sysdeps/sh/bits/link.h: Renamed to...
+ * sysdeps/sh/bits/linkmap.h: ...this.
+ * sysdeps/x86_64/bits/link.h: Renamed to...
+ * sysdeps/x86_64/bits/linkmap.h: ...this.
+
* posix/unistd.h: Declare ftruncate for POSIX 2003. [BZ #640]
2004-12-22 Steven Munroe <sjmunroe@us.ibm.com>
@@ -339,9 +1070,6 @@
2005-01-05 Ulrich Drepper <drepper@redhat.com>
- * libio/fmemopen.c (fmemopen_seek): SEEK_END should count from
- maximum used address, not maximum buffer position.
-
* libio/iofopncook.c (_IO_cookie_seekoff): Define. Mark offset as
invalid to disable optimizations in fileops which won't work here.
(_IO_cookie_jumps): Use it.
diff --git a/Makeconfig b/Makeconfig
index d267e5af21..5ecda01169 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -1,4 +1,4 @@
-# Copyright (C) 1991-2003, 2004 Free Software Foundation, Inc.
+# Copyright (C) 1991-2003, 2004, 2005 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
@@ -480,32 +480,21 @@ default-rpath = $(libdir)
endif
ifndef link-extra-libs
-ifeq (yes,$(build-shared))
-ifneq ($(common-objpfx),$(objpfx))
-link-extra-libs = $(foreach lib,$(LDLIBS-$(@F)),\
- $(wildcard $(common-objpfx)$(lib).so$($(notdir $(lib)).so-version) \
- $(objpfx)$(lib).so$($(notdir $(lib)).so-version)))
-else
-link-extra-libs = $(foreach lib,$(LDLIBS-$(@F)),$(common-objpfx)$(lib).so$($(notdir $(lib)).so-version))
-endif
-else
-link-extra-libs = $(foreach lib,$(LDLIBS-$(@F)),$(common-objpfx)$(lib).a)
-endif
+link-extra-libs = $(LDLIBS-$(@F))
+link-extra-libs-static = $(link-extra-libs)
+link-extra-libs-bounded = $(link-extra-libs)
endif
# The static libraries.
ifeq (yes,$(build-static))
link-libc-static = $(common-objpfx)libc.a $(static-gnulib) $(common-objpfx)libc.a
-link-extra-libs-static = $(foreach lib,$(LDLIBS-$(@F)),$(common-objpfx)$(lib).a)
else
ifeq (yes,$(build-shared))
# We can try to link the programs with lib*_pic.a...
link-libc-static = $(static-gnulib) $(common-objpfx)libc_pic.a
-link-extra-libs-static = $(link-extra-libs)
endif
endif
link-libc-bounded = $(common-objpfx)libc_b.a $(gnulib) $(common-objpfx)libc_b.a
-link-extra-libs-bounded = $(foreach lib,$(LDLIBS-$(@F:%-bp=%)),$(common-objpfx)$(lib)_b.a)
ifndef gnulib
ifneq ($(have-cc-with-libunwind),yes)
diff --git a/catgets/gencat.c b/catgets/gencat.c
index 2f6c81dc1d..39938097d3 100644
--- a/catgets/gencat.c
+++ b/catgets/gencat.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1996.
@@ -248,7 +248,7 @@ print_version (FILE *stream, struct argp_state *state)
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
+"), "2005");
fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
}
diff --git a/configure b/configure
index e10f4b9836..1e9e50c491 100755
--- a/configure
+++ b/configure
@@ -2093,6 +2093,14 @@ for d in $add_ons_pfx ''; do
done
done
done
+ if test -n "$d"; then
+ try="${d}sysdeps/generic"
+ test -n "$enable_debug_configure" &&
+ echo "$0 DEBUG: try $try" >&2
+ if test -d $srcdir/$try; then
+ sysnames="$sysnames $try"
+ fi
+ fi
done
IFS="$ac_save_ifs"
diff --git a/configure.in b/configure.in
index 4ad54cfefd..11f78b0ec3 100644
--- a/configure.in
+++ b/configure.in
@@ -593,6 +593,14 @@ for d in $add_ons_pfx ''; do
done
done
done
+ if test -n "$d"; then
+ try="${d}sysdeps/generic"
+ test -n "$enable_debug_configure" &&
+ echo "$0 DEBUG: try $try" >&2
+ if test -d $srcdir/$try; then
+ sysnames="$sysnames $try"
+ fi
+ fi
done
IFS="$ac_save_ifs"
diff --git a/csu/elf-init.c b/csu/elf-init.c
index c538627dfd..dbd2a91cb7 100644
--- a/csu/elf-init.c
+++ b/csu/elf-init.c
@@ -1,5 +1,5 @@
/* Startup support for ELF initializers/finalizers in the main executable.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 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
@@ -104,9 +104,13 @@ __libc_csu_init (void)
#endif
}
+/* This function should not be used anymore. We run the executable's
+ destructor now just like any other. We cannot remove the function,
+ though. */
void
__libc_csu_fini (void)
{
+#if 0
#ifdef HAVE_INITFINI_ARRAY
size_t i = __fini_array_end - __fini_array_start;
while (i-- > 0)
@@ -114,4 +118,5 @@ __libc_csu_fini (void)
#endif
_fini ();
+#endif
}
diff --git a/csu/version.c b/csu/version.c
index 1104fa9137..606246a6e1 100644
--- a/csu/version.c
+++ b/csu/version.c
@@ -25,7 +25,7 @@ static const char __libc_version[] = VERSION;
static const char banner[] =
"GNU C Library "RELEASE" release version "VERSION", by Roland McGrath et al.\n\
-Copyright (C) 2004 Free Software Foundation, Inc.\n\
+Copyright (C) 2005 Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions.\n\
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\
PARTICULAR PURPOSE.\n\
diff --git a/debug/catchsegv.sh b/debug/catchsegv.sh
index 14556f712a..f7e79bce42 100755
--- a/debug/catchsegv.sh
+++ b/debug/catchsegv.sh
@@ -39,7 +39,7 @@ if test $# -eq 0; then
;;
--v | --ve | --ver | --vers | --versi | --versio | --version)
echo 'catchsegv (GNU libc) @VERSION@'
- echo 'Copyright (C) 2004 Free Software Foundation, Inc.
+ echo 'Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Ulrich Drepper.'
diff --git a/debug/chk_fail.c b/debug/chk_fail.c
index dc1c3d70b6..29df08b9ca 100644
--- a/debug/chk_fail.c
+++ b/debug/chk_fail.c
@@ -1,5 +1,4 @@
-
-/* Copyright (C) 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2005 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
@@ -21,10 +20,13 @@
#include <stdlib.h>
+extern char **__libc_argv attribute_hidden;
+
void
__attribute__ ((noreturn))
__chk_fail (void)
{
- __libc_fatal ("*** buffer overflow detected ***\n");
+ __libc_message (1, "*** buffer overflow detected ***: %s terminated\n",
+ __libc_argv[0] ?: "<unknown>");
}
libc_hidden_def (__chk_fail)
diff --git a/debug/xtrace.sh b/debug/xtrace.sh
index 4ce8888490..811d6ba9a6 100755
--- a/debug/xtrace.sh
+++ b/debug/xtrace.sh
@@ -1,5 +1,5 @@
#! @BASH@
-# Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+# Copyright (C) 1999, 2001-2004, 2005 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# Contributed by Ulrich Drepper <drepper@gnu.org>, 1999.
@@ -64,7 +64,7 @@ do_version() {
printf $"Copyright (C) %s Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-" "2004"
+" "2005"
printf $"Written by %s.
" "Ulrich Drepper"
exit 0
diff --git a/dirent/tst-seekdir.c b/dirent/tst-seekdir.c
index b833c30705..43808fecb5 100644
--- a/dirent/tst-seekdir.c
+++ b/dirent/tst-seekdir.c
@@ -11,8 +11,23 @@ main (int argc, char *argv[])
int i = 0;
int result = 0;
struct dirent *dp;
+ long int save0;
+ long int rewind;
dirp = opendir (".");
+ if (dirp == NULL)
+ {
+ printf ("opendir failed: %m\n");
+ return 1;
+ }
+
+ save0 = telldir (dirp);
+ if (save0 == -1)
+ {
+ printf ("telldir failed: %m\n");
+ result = 1;
+ }
+
for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp))
{
/* save position 3 (after fourth entry) */
@@ -44,6 +59,19 @@ main (int argc, char *argv[])
for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp))
printf ("%s\n", dp->d_name);
+ /* Check rewinddir */
+ rewinddir (dirp);
+ rewind = telldir (dirp);
+ if (rewind == -1)
+ {
+ printf ("telldir failed: %m\n");
+ result = 1;
+ }
+ else if (save0 != rewind)
+ {
+ printf ("rewinddir didn't reset directory stream\n");
+ result = 1;
+ }
closedir (dirp);
return result;
diff --git a/dlfcn/Makefile b/dlfcn/Makefile
index ed20ae5ccd..7b538fed2b 100644
--- a/dlfcn/Makefile
+++ b/dlfcn/Makefile
@@ -20,8 +20,8 @@ subdir := dlfcn
headers := bits/dlfcn.h dlfcn.h
extra-libs := libdl
libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr dladdr1 dlinfo \
- dlmopen
-routines := $(patsubst %,s%,$(libdl-routines))
+ dlmopen dlfcn
+routines := $(patsubst %,s%,$(filter-out dlfcn,$(libdl-routines)))
elide-routines.os := $(routines)
distribute := dlopenold.c glreflib1.c glreflib2.c failtestmod.c \
defaultmod1.c defaultmod2.c errmsg1mod.c modatexit.c \
@@ -34,7 +34,7 @@ include ../Makeconfig
ifeq ($(versioning),yes)
libdl-routines += dlopenold
-libdl-shared-only-routines := dlopenold
+libdl-shared-only-routines := dlopenold dlfcn
endif
ifeq (yes,$(build-shared))
@@ -65,8 +65,6 @@ generated := $(modules-names:=.so)
include ../Rules
-LDFLAGS-dl.so = -Wl,-dynamic-linker,$(slibdir)/$(rtld-installed-name)
-
test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
$(test-modules): $(objpfx)%.so: $(objpfx)%.os $(common-objpfx)shlib.lds
$(build-module)
diff --git a/dlfcn/dlclose.c b/dlfcn/dlclose.c
index 3ddedcffbe..5a344f31ca 100644
--- a/dlfcn/dlclose.c
+++ b/dlfcn/dlclose.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#include <dlfcn.h>
+#include <ldsodefs.h>
#if !defined SHARED && defined IS_IN_libdl
@@ -33,7 +34,7 @@ dlclose (void *handle)
static void
dlclose_doit (void *handle)
{
- _dl_close (handle);
+ GLRO(dl_close) (handle);
}
int
diff --git a/dlfcn/dlfcn.c b/dlfcn/dlfcn.c
new file mode 100644
index 0000000000..9c0a84afb8
--- /dev/null
+++ b/dlfcn/dlfcn.c
@@ -0,0 +1,33 @@
+/* Load a shared object at run time.
+ Copyright (C) 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <dlfcn.h>
+
+
+int __dlfcn_argc attribute_hidden;
+char **__dlfcn_argv attribute_hidden;
+
+
+void
+__attribute__ ((constructor))
+init (int argc, char *argv[])
+{
+ __dlfcn_argc = argc;
+ __dlfcn_argv = argv;
+}
diff --git a/dlfcn/dlmopen.c b/dlfcn/dlmopen.c
index 5fd6543655..0a6d47ea2e 100644
--- a/dlfcn/dlmopen.c
+++ b/dlfcn/dlmopen.c
@@ -21,6 +21,7 @@
#include <errno.h>
#include <libintl.h>
#include <stddef.h>
+#include <unistd.h>
#include <ldsodefs.h>
#if !defined SHARED && defined IS_IN_libdl
@@ -61,8 +62,10 @@ dlmopen_doit (void *a)
# endif
GLRO(dl_signal_error) (EINVAL, NULL, NULL, N_("invalid namespace"));
- args->new = _dl_open (args->file ?: "", args->mode | __RTLD_DLOPEN,
- args->caller, args->nsid);
+ args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN,
+ args->caller,
+ args->nsid, __dlfcn_argc, __dlfcn_argv,
+ __environ);
}
diff --git a/dlfcn/dlopen.c b/dlfcn/dlopen.c
index 6381ffc9b1..bffb512aa3 100644
--- a/dlfcn/dlopen.c
+++ b/dlfcn/dlopen.c
@@ -1,5 +1,5 @@
/* Load a shared object at run time.
- Copyright (C) 1995,96,97,98,99,2000,2003,2004 Free Software Foundation, Inc.
+ Copyright (C) 1995-2000,2003,2004,2005 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
@@ -18,7 +18,10 @@
02111-1307 USA. */
#include <dlfcn.h>
+#include <libintl.h>
#include <stddef.h>
+#include <unistd.h>
+#include <ldsodefs.h>
#if !defined SHARED && defined IS_IN_libdl
@@ -56,8 +59,14 @@ dlopen_doit (void *a)
{
struct dlopen_args *args = (struct dlopen_args *) a;
- args->new = _dl_open (args->file ?: "", args->mode | __RTLD_DLOPEN,
- args->caller, args->file == NULL ? LM_ID_BASE : NS);
+ if (args->mode & ~(RTLD_BINDING_MASK | RTLD_NOLOAD | RTLD_DEEPBIND
+ | RTLD_GLOBAL | RTLD_LOCAL | RTLD_NODELETE))
+ GLRO(dl_signal_error) (0, NULL, NULL, _("invalid mode parameter"));
+
+ args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN,
+ args->caller,
+ args->file == NULL ? LM_ID_BASE : NS,
+ __dlfcn_argc, __dlfcn_argv, __environ);
}
diff --git a/dlfcn/dlopenold.c b/dlfcn/dlopenold.c
index 148716cdb0..8dae1c40ce 100644
--- a/dlfcn/dlopenold.c
+++ b/dlfcn/dlopenold.c
@@ -19,6 +19,8 @@
#include <dlfcn.h>
#include <stddef.h>
+#include <unistd.h>
+#include <ldsodefs.h>
/* This file is for compatibility with glibc 2.0. Compile it only if
versioning is used. */
@@ -50,8 +52,10 @@ dlopen_doit (void *a)
{
struct dlopen_args *args = (struct dlopen_args *) a;
- args->new = _dl_open (args->file ?: "", args->mode | __RTLD_DLOPEN,
- args->caller, args->file == NULL ? LM_ID_BASE : NS);
+ args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN,
+ args->caller,
+ args->file == NULL ? LM_ID_BASE : NS,
+ __dlfcn_argc, __dlfcn_argv, __environ);
}
extern void *__dlopen_nocheck (const char *file, int mode);
diff --git a/elf/Makefile b/elf/Makefile
index 87172d367d..47e6ea4d58 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -20,8 +20,8 @@
subdir := elf
-headers = elf.h bits/elfclass.h link.h
-routines = $(dl-routines) dl-open dl-close dl-support dl-iteratephdr \
+headers = elf.h bits/elfclass.h link.h bits/link.h
+routines = $(dl-routines) dl-support dl-iteratephdr \
dl-addr enbl-secure dl-profstub \
dl-origin dl-libc dl-sym dl-tsd
@@ -30,7 +30,7 @@ routines = $(dl-routines) dl-open dl-close dl-support dl-iteratephdr \
dl-routines = $(addprefix dl-,load cache lookup object reloc deps \
runtime error init fini debug misc \
version profile conflict tls origin \
- execstack caller)
+ execstack caller open close trampoline)
all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
# But they are absent from the shared libc, because that code is in ld.so.
elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin
@@ -72,7 +72,7 @@ distribute := rtld-Rules \
tst-tlsmod1.c tst-tlsmod2.c tst-tlsmod3.c tst-tlsmod4.c \
tst-tlsmod5.c tst-tlsmod6.c tst-tlsmod7.c tst-tlsmod8.c \
tst-tlsmod9.c tst-tlsmod10.c tst-tlsmod11.c \
- tst-tlsmod12.c tst-tls10.h tst-alignmod.c \
+ tst-tlsmod12.c tst-tls10.h tst-alignmod.c tst-alignmod2.c \
circlemod1.c circlemod1a.c circlemod2.c circlemod2a.c \
circlemod3.c circlemod3a.c nodlopenmod2.c \
tls-macros.h \
@@ -83,7 +83,8 @@ distribute := rtld-Rules \
tst-array2dep.c tst-piemod1.c \
tst-execstack-mod.c tst-dlmodcount.c \
check-textrel.c dl-sysdep.h test-dlopenrpathmod.c \
- tst-deep1mod1.c tst-deep1mod2.c tst-deep1mod3.c
+ tst-deep1mod1.c tst-deep1mod2.c tst-deep1mod3.c \
+ tst-auditmod1.c
CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables
@@ -153,8 +154,9 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \
circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \
tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-align \
- $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \
- tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3
+ tst-align2 $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \
+ tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
+ tst-audit1
# reldep9
test-srcs = tst-pathopt
tests-vis-yes = vismain
@@ -163,7 +165,7 @@ tests-nodlopen-yes = nodlopen nodlopen2
tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog
endif
ifeq (yesyes,$(have-fpie)$(build-shared))
-tests += tst-pie1
+tests: $(objpfx)tst-pie1.out
endif
modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
testobj1_1 failobj constload2 constload3 unloadmod \
@@ -186,9 +188,10 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
circlemod3 circlemod3a \
reldep8mod1 reldep8mod2 reldep8mod3 \
reldep9mod1 reldep9mod2 reldep9mod3 \
- tst-alignmod $(modules-execstack-$(have-z-execstack)) \
+ tst-alignmod tst-alignmod2 \
+ $(modules-execstack-$(have-z-execstack)) \
tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 \
- tst-dlmopen1mod
+ tst-dlmopen1mod tst-auditmod1
ifeq (yes,$(have-initfini-array))
modules-names += tst-array2dep
endif
@@ -668,9 +671,12 @@ $(objpfx)tst-tls14: $(objpfx)tst-tlsmod14a.so $(libdl)
$(objpfx)tst-tls14.out:$(objpfx)tst-tlsmod14b.so
CFLAGS-tst-align.c = $(stack-align-test-flags)
+CFLAGS-tst-align2.c = $(stack-align-test-flags)
CFLAGS-tst-alignmod.c = $(stack-align-test-flags)
+CFLAGS-tst-alignmod2.c = $(stack-align-test-flags)
$(objpfx)tst-align: $(libdl)
$(objpfx)tst-align.out: $(objpfx)tst-alignmod.so
+$(objpfx)tst-align2: $(objpfx)tst-alignmod2.so
ifdef libdl
$(objpfx)tst-tls9-static: $(common-objpfx)dlfcn/libdl.a
@@ -732,6 +738,8 @@ $(objpfx)tst-pie1: $(objpfx)tst-pie1.o $(objpfx)tst-piemod1.so
-L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link) \
-o $@ $(objpfx)tst-pie1.o $(objpfx)tst-piemod1.so \
$(common-objpfx)libc_nonshared.a
+
+generated += tst-pie1 tst-pie1.out tst-pie1.o
endif
check-textrel-CFLAGS = -O -Wall -D_XOPEN_SOURCE=600 -D_BSD_SOURCE
@@ -773,3 +781,6 @@ $(objpfx)tst-dlmopen2.out: $(objpfx)tst-dlmopen1mod.so
$(objpfx)tst-dlmopen3: $(libdl)
$(objpfx)tst-dlmopen3.out: $(objpfx)tst-dlmopen1mod.so
+
+$(objpfx)tst-audit1.out: $(objpfx)tst-auditmod1.so
+tst-audit1-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
diff --git a/elf/Versions b/elf/Versions
index e24b2de04c..aaacf3e4ea 100644
--- a/elf/Versions
+++ b/elf/Versions
@@ -19,7 +19,7 @@ libc {
%endif
GLIBC_PRIVATE {
# functions used in other libraries
- _dl_open; _dl_close; _dl_addr;
+ _dl_addr;
_dl_sym; _dl_vsym;
_dl_open_hook;
__libc_dlopen_mode; __libc_dlsym; __libc_dlclose;
diff --git a/elf/dl-close.c b/elf/dl-close.c
index c823b17642..eb5e805dd4 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -1,5 +1,5 @@
/* Close a shared object opened by `_dl_open'.
- Copyright (C) 1996-2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1996-2002, 2003, 2004, 2005 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
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <bits/libc-lock.h>
#include <ldsodefs.h>
#include <sys/types.h>
@@ -99,7 +100,6 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
void
-internal_function
_dl_close (void *_map)
{
struct reldep_list
@@ -112,6 +112,7 @@ _dl_close (void *_map)
} *reldeps = NULL;
struct link_map **list;
struct link_map *map = _map;
+ Lmid_t ns = map->l_ns;
unsigned int i;
unsigned int *new_opencount;
#ifdef USE_TLS
@@ -139,8 +140,8 @@ _dl_close (void *_map)
{
/* There are still references to this object. Do nothing more. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
- GLRO(dl_debug_printf) ("\nclosing file=%s; opencount == %u\n",
- map->l_name, map->l_opencount);
+ _dl_debug_printf ("\nclosing file=%s; opencount == %u\n",
+ map->l_name, map->l_opencount);
/* Decrement the object's reference counter, not the dependencies'. */
--map->l_opencount;
@@ -265,16 +266,23 @@ _dl_close (void *_map)
assert (new_opencount[0] == 0);
/* Call all termination functions at once. */
+#ifdef SHARED
+ bool do_audit = GLRO(dl_naudit) > 0 && !GL(dl_ns)[ns]._ns_loaded->l_auditing;
+#endif
for (i = 0; list[i] != NULL; ++i)
{
struct link_map *imap = list[i];
+
+ /* All elements must be in the same namespace. */
+ assert (imap->l_ns == ns);
+
if (new_opencount[i] == 0 && imap->l_type == lt_loaded
&& (imap->l_flags_1 & DF_1_NODELETE) == 0)
{
/* When debugging print a message first. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
- GLRO(dl_debug_printf) ("\ncalling fini: %s [%lu]\n\n",
- imap->l_name, imap->l_ns);
+ _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
+ imap->l_name, ns);
/* Call its termination function. Do not do it for
half-cooked objects. */
@@ -299,6 +307,22 @@ _dl_close (void *_map)
+ imap->l_info[DT_FINI]->d_un.d_ptr))) ();
}
+#ifdef SHARED
+ /* Auditing checkpoint: we have a new object. */
+ if (__builtin_expect (do_audit, 0))
+ {
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->objclose != NULL)
+ /* Return value is ignored. */
+ (void) afct->objclose (&imap->l_audit[cnt].cookie);
+
+ afct = afct->next;
+ }
+ }
+#endif
+
/* This object must not be used anymore. We must remove the
reference from the scope. */
unsigned int j;
@@ -365,9 +389,30 @@ _dl_close (void *_map)
assert (imap->l_type == lt_loaded || imap->l_opencount > 0);
}
+#ifdef SHARED
+ /* Auditing checkpoint: we will start deleting objects. */
+ if (__builtin_expect (do_audit, 0))
+ {
+ struct link_map *head = GL(dl_ns)[ns]._ns_loaded;
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ /* Do not call the functions for any auditing object. */
+ if (head->l_auditing == 0)
+ {
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->activity != NULL)
+ afct->activity (&head->l_audit[cnt].cookie, LA_ACT_DELETE);
+
+ afct = afct->next;
+ }
+ }
+ }
+#endif
+
/* Notify the debugger we are about to remove some loaded objects. */
- _r_debug.r_state = RT_DELETE;
- GLRO(dl_debug_state) ();
+ struct r_debug *r = _dl_debug_initialize (0, ns);
+ r->r_state = RT_DELETE;
+ _dl_debug_state ();
#ifdef USE_TLS
size_t tls_free_start;
@@ -389,21 +434,19 @@ _dl_close (void *_map)
if (__builtin_expect (imap->l_global, 0))
{
/* This object is in the global scope list. Remove it. */
- unsigned int cnt
- = GL(dl_ns)[imap->l_ns]._ns_main_searchlist->r_nlist;
+ unsigned int cnt = GL(dl_ns)[ns]._ns_main_searchlist->r_nlist;
do
--cnt;
- while (GL(dl_ns)[imap->l_ns]._ns_main_searchlist->r_list[cnt]
- != imap);
+ while (GL(dl_ns)[ns]._ns_main_searchlist->r_list[cnt] != imap);
/* The object was already correctly registered. */
while (++cnt
- < GL(dl_ns)[imap->l_ns]._ns_main_searchlist->r_nlist)
- GL(dl_ns)[imap->l_ns]._ns_main_searchlist->r_list[cnt - 1]
- = GL(dl_ns)[imap->l_ns]._ns_main_searchlist->r_list[cnt];
+ < GL(dl_ns)[ns]._ns_main_searchlist->r_nlist)
+ GL(dl_ns)[ns]._ns_main_searchlist->r_list[cnt - 1]
+ = GL(dl_ns)[ns]._ns_main_searchlist->r_list[cnt];
- --GL(dl_ns)[imap->l_ns]._ns_main_searchlist->r_nlist;
+ --GL(dl_ns)[ns]._ns_main_searchlist->r_nlist;
}
#ifdef USE_TLS
@@ -412,9 +455,10 @@ _dl_close (void *_map)
{
any_tls = true;
- if (! remove_slotinfo (imap->l_tls_modid,
- GL(dl_tls_dtv_slotinfo_list), 0,
- imap->l_init_called))
+ if (GL(dl_tls_dtv_slotinfo_list) != NULL
+ && ! remove_slotinfo (imap->l_tls_modid,
+ GL(dl_tls_dtv_slotinfo_list), 0,
+ imap->l_init_called))
/* All dynamically loaded modules with TLS are unloaded. */
GL(dl_tls_max_dtv_idx) = GL(dl_tls_static_nelem);
@@ -499,12 +543,12 @@ _dl_close (void *_map)
else
{
#ifdef SHARED
- assert (imap->l_ns != LM_ID_BASE);
+ assert (ns != LM_ID_BASE);
#endif
- GL(dl_ns)[imap->l_ns]._ns_loaded = imap->l_next;
+ GL(dl_ns)[ns]._ns_loaded = imap->l_next;
}
- --GL(dl_ns)[imap->l_ns]._ns_nloaded;
+ --GL(dl_ns)[ns]._ns_nloaded;
if (imap->l_next != NULL)
imap->l_next->l_prev = imap->l_prev;
@@ -579,16 +623,36 @@ _dl_close (void *_map)
if (any_tls)
{
if (__builtin_expect (++GL(dl_tls_generation) == 0, 0))
- __libc_fatal (_("TLS generation counter wrapped! Please report as described in <http://www.gnu.org/software/libc/bugs.html>."));
+ _dl_fatal_printf ("TLS generation counter wrapped! Please report as described in <http://www.gnu.org/software/libc/bugs.html>.\n");
if (tls_free_end == GL(dl_tls_static_used))
GL(dl_tls_static_used) = tls_free_start;
}
#endif
+#ifdef SHARED
+ /* Auditing checkpoint: we have deleted all objects. */
+ if (__builtin_expect (do_audit, 0))
+ {
+ struct link_map *head = GL(dl_ns)[ns]._ns_loaded;
+ /* Do not call the functions for any auditing object. */
+ if (head->l_auditing == 0)
+ {
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->activity != NULL)
+ afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT);
+
+ afct = afct->next;
+ }
+ }
+ }
+#endif
+
/* Notify the debugger those objects are finalized and gone. */
- _r_debug.r_state = RT_CONSISTENT;
- GLRO(dl_debug_state) ();
+ r->r_state = RT_CONSISTENT;
+ _dl_debug_state ();
/* Now we can perhaps also remove the modules for which we had
dependencies because of symbol lookup. */
@@ -612,7 +676,6 @@ _dl_close (void *_map)
/* Release the lock. */
__rtld_lock_unlock_recursive (GL(dl_load_lock));
}
-libc_hidden_def (_dl_close)
#ifdef USE_TLS
diff --git a/elf/dl-debug.c b/elf/dl-debug.c
index bd6ee69189..bc7d793435 100644
--- a/elf/dl-debug.c
+++ b/elf/dl-debug.c
@@ -1,5 +1,5 @@
/* Communicate dynamic linker state to the debugger at runtime.
- Copyright (C) 1996, 1998, 2000, 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1998,2000,2002,2004,2005 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
@@ -32,20 +32,25 @@ struct r_debug _r_debug;
struct r_debug *
internal_function
-_dl_debug_initialize (ElfW(Addr) ldbase)
+_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
{
- if (_r_debug.r_brk == 0)
+ struct r_debug *r;
+
+ if (ns == LM_ID_BASE)
+ r = &_r_debug;
+ else
+ r = &GL(dl_ns)[ns]._ns_debug;
+
+ if (r->r_brk == 0 || ldbase != 0)
{
/* Tell the debugger where to find the map of loaded objects. */
- _r_debug.r_version = 1 /* R_DEBUG_VERSION XXX */;
- _r_debug.r_ldbase = ldbase;
- // XXX This is problematic. It means we cannot tell the debugger
- // XXX about namespaces other than the main one.
- _r_debug.r_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
- _r_debug.r_brk = (ElfW(Addr)) &_dl_debug_state;
+ r->r_version = 1 /* R_DEBUG_VERSION XXX */;
+ r->r_ldbase = ldbase ?: _r_debug.r_ldbase;
+ r->r_map = GL(dl_ns)[ns]._ns_loaded;
+ r->r_brk = (ElfW(Addr)) &_dl_debug_state;
}
- return &_r_debug;
+ return r;
}
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index f43f4a00ed..b3282089a9 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -1,5 +1,5 @@
/* Call the termination functions of loaded shared objects.
- Copyright (C) 1995,96,1998-2002,2004 Free Software Foundation, Inc.
+ Copyright (C) 1995,96,1998-2002,2004, 2005 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
@@ -48,12 +48,25 @@ _dl_fini (void)
/* We run the destructors of the main namespaces last. As for the
other namespaces, we pick run the destructors in them in reverse
order of the namespace ID. */
+#ifdef SHARED
+ int do_audit = 0;
+ again:
+#endif
for (Lmid_t cnt = DL_NNS - 1; cnt >= 0; --cnt)
{
/* Protect against concurrent loads and unloads. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
+ unsigned int nmaps = 0;
unsigned int nloaded = GL(dl_ns)[cnt]._ns_nloaded;
+ /* No need to do anything for empty namespaces or those used for
+ auditing DSOs. */
+ if (nloaded == 0
+#ifdef SHARED
+ || GL(dl_ns)[cnt]._ns_loaded->l_auditing != do_audit
+#endif
+ )
+ goto out;
/* XXX Could it be (in static binaries) that there is no object
loaded? */
@@ -76,6 +89,7 @@ _dl_fini (void)
unsigned int i;
struct link_map *l;
+ assert (nloaded != 0 || GL(dl_ns)[cnt]._ns_loaded == NULL);
for (l = GL(dl_ns)[cnt]._ns_loaded, i = 0; l != NULL; l = l->l_next)
/* Do not handle ld.so in secondary namespaces. */
if (l == l->l_real)
@@ -90,7 +104,7 @@ _dl_fini (void)
}
assert (cnt != LM_ID_BASE || i == nloaded);
assert (cnt == LM_ID_BASE || i == nloaded || i == nloaded - 1);
- unsigned int nmaps = i;
+ nmaps = i;
if (nmaps != 0)
{
@@ -163,6 +177,7 @@ _dl_fini (void)
high and will be decremented in this loop. So we release the
lock so that some code which might be called from a destructor
can directly or indirectly access the lock. */
+ out:
__rtld_lock_unlock_recursive (GL(dl_load_lock));
/* 'maps' now contains the objects in the right order. Now call the
@@ -176,38 +191,49 @@ _dl_fini (void)
/* Make sure nothing happens if we are called twice. */
l->l_init_called = 0;
- /* Don't call the destructors for objects we are not
- supposed to. */
- if (l->l_name[0] == '\0' && l->l_type == lt_executable)
- continue;
-
/* Is there a destructor function? */
- if (l->l_info[DT_FINI_ARRAY] == NULL
- && l->l_info[DT_FINI] == NULL)
- continue;
-
- /* When debugging print a message first. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS,
- 0))
- _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
- l->l_name[0] ? l->l_name : rtld_progname,
- cnt);
-
- /* First see whether an array is given. */
- if (l->l_info[DT_FINI_ARRAY] != NULL)
+ if (l->l_info[DT_FINI_ARRAY] != NULL
+ || l->l_info[DT_FINI] != NULL)
{
- ElfW(Addr) *array =
- (ElfW(Addr) *) (l->l_addr
- + l->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
- unsigned int i = (l->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
- / sizeof (ElfW(Addr)));
- while (i-- > 0)
- ((fini_t) array[i]) ();
+ /* When debugging print a message first. */
+ if (__builtin_expect (GLRO(dl_debug_mask)
+ & DL_DEBUG_IMPCALLS, 0))
+ _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
+ l->l_name[0] ? l->l_name : rtld_progname,
+ cnt);
+
+ /* First see whether an array is given. */
+ if (l->l_info[DT_FINI_ARRAY] != NULL)
+ {
+ ElfW(Addr) *array =
+ (ElfW(Addr) *) (l->l_addr
+ + l->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
+ unsigned int i = (l->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
+ / sizeof (ElfW(Addr)));
+ while (i-- > 0)
+ ((fini_t) array[i]) ();
+ }
+
+ /* Next try the old-style destructor. */
+ if (l->l_info[DT_FINI] != NULL)
+ ((fini_t) DL_DT_FINI_ADDRESS (l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) ();
}
- /* Next try the old-style destructor. */
- if (l->l_info[DT_FINI] != NULL)
- ((fini_t) DL_DT_FINI_ADDRESS (l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) ();
+#ifdef SHARED
+ /* Auditing checkpoint: another object closed. */
+ if (!do_audit && __builtin_expect (GLRO(dl_naudit) > 0, 0))
+ {
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->objclose != NULL)
+ /* Return value is ignored. */
+ (void) afct->objclose (&l->l_audit[cnt].cookie);
+
+ afct = afct->next;
+ }
+ }
+#endif
}
/* Correct the previous increment. */
@@ -215,6 +241,14 @@ _dl_fini (void)
}
}
+#ifdef SHARED
+ if (! do_audit && GLRO(dl_naudit) > 0)
+ {
+ do_audit = 1;
+ goto again;
+ }
+#endif
+
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS, 0))
_dl_debug_printf ("\nruntime linker statistics:\n"
" final number of relocations: %lu\n"
diff --git a/elf/dl-init.c b/elf/dl-init.c
index e700dffb3a..e7b67570fd 100644
--- a/elf/dl-init.c
+++ b/elf/dl-init.c
@@ -93,7 +93,6 @@ _dl_init (struct link_map *main_map, int argc, char **argv, char **env)
{
ElfW(Dyn) *preinit_array = main_map->l_info[DT_PREINIT_ARRAY];
ElfW(Dyn) *preinit_array_size = main_map->l_info[DT_PREINIT_ARRAYSZ];
- struct r_debug *r;
unsigned int i;
if (__builtin_expect (GL(dl_initfirst) != NULL, 0))
@@ -120,13 +119,6 @@ _dl_init (struct link_map *main_map, int argc, char **argv, char **env)
((init_t) addrs[cnt]) (argc, argv, env);
}
- /* Notify the debugger we have added some objects. We need to call
- _dl_debug_initialize in a static program in case dynamic linking has
- not been used before. */
- r = _dl_debug_initialize (0);
- r->r_state = RT_ADD;
- _dl_debug_state ();
-
/* Stupid users forced the ELF specification to be changed. It now
says that the dynamic loader is responsible for determining the
order in which the constructors have to run. The constructors
@@ -141,10 +133,6 @@ _dl_init (struct link_map *main_map, int argc, char **argv, char **env)
while (i-- > 0)
call_init (main_map->l_initfini[i], argc, argv, env);
- /* Notify the debugger all new objects are now ready to go. */
- r->r_state = RT_CONSISTENT;
- _dl_debug_state ();
-
#ifndef HAVE_INLINED_SYSCALLS
/* Finished starting up. */
INTUSE(_dl_starting_up) = 0;
diff --git a/elf/dl-libc.c b/elf/dl-libc.c
index 8a3f542e01..5e76069139 100644
--- a/elf/dl-libc.c
+++ b/elf/dl-libc.c
@@ -22,6 +22,11 @@
#include <stdlib.h>
#include <ldsodefs.h>
+extern int __libc_argc attribute_hidden;
+extern char **__libc_argv attribute_hidden;
+
+extern char **__environ;
+
/* The purpose of this file is to provide wrappers around the dynamic
linker error mechanism (similar to dlopen() et al in libdl) which
are usable from within libc. Generally we want to throw away the
@@ -77,7 +82,8 @@ do_dlopen (void *ptr)
{
struct do_dlopen_args *args = (struct do_dlopen_args *) ptr;
/* Open and relocate the shared object. */
- args->map = _dl_open (args->name, args->mode, NULL, __LM_ID_CALLER);
+ args->map = GLRO(dl_open) (args->name, args->mode, NULL, __LM_ID_CALLER,
+ __libc_argc, __libc_argv, __environ);
}
static void
@@ -93,7 +99,7 @@ do_dlsym (void *ptr)
static void
do_dlclose (void *ptr)
{
- _dl_close ((struct link_map *) ptr);
+ GLRO(dl_close) ((struct link_map *) ptr);
}
/* This code is to support __libc_dlopen from __libc_dlopen'ed shared
@@ -109,7 +115,7 @@ struct dl_open_hook
#ifdef SHARED
extern struct dl_open_hook *_dl_open_hook;
libc_hidden_proto (_dl_open_hook);
-struct dl_open_hook *_dl_open_hook __attribute__((nocommon));
+struct dl_open_hook *_dl_open_hook __attribute__ ((nocommon));
libc_hidden_data_def (_dl_open_hook);
#else
static void
@@ -119,7 +125,7 @@ do_dlsym_private (void *ptr)
struct r_found_version vers;
vers.name = "GLIBC_PRIVATE";
vers.hidden = 1;
- /* vers.hash = _dl_elf_hash (version); */
+ /* vers.hash = _dl_elf_hash (vers.name); */
vers.hash = 0x0963cf85;
vers.filename = NULL;
diff --git a/elf/dl-load.c b/elf/dl-load.c
index eb1a7919fb..f307dada2e 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1,5 +1,5 @@
/* Map in a shared object's segments from the file.
- Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1995-2002, 2003, 2004, 2005 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
@@ -36,6 +36,7 @@
#include <dl-osinfo.h>
#include <stackinfo.h>
#include <caller.h>
+#include <sysdep.h>
#include <dl-dst.h>
@@ -105,13 +106,11 @@ ELF_PREFERRED_ADDRESS_DATA;
int __stack_prot attribute_hidden attribute_relro
- = (PROT_READ|PROT_WRITE
#if _STACK_GROWS_DOWN && defined PROT_GROWSDOWN
- |PROT_GROWSDOWN
+ = PROT_GROWSDOWN;
#elif _STACK_GROWS_UP && defined PROT_GROWSUP
- |PROT_GROWSUP
+ = PROT_GROWSUP;
#endif
- );
/* Type for the buffer we put the ELF header and hopefully the program
@@ -827,6 +826,8 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
/* Initialize to keep the compiler happy. */
const char *errstring = NULL;
int errval = 0;
+ struct r_debug *r = _dl_debug_initialize (0, nsid);
+ bool make_consistent = false;
/* Get file information. */
if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st) < 0, 0))
@@ -835,6 +836,12 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
call_lose_errno:
errval = errno;
call_lose:
+ if (make_consistent)
+ {
+ r->r_state = RT_CONSISTENT;
+ _dl_debug_state ();
+ }
+
lose (errval, fd, name, realname, l, errstring);
}
@@ -905,6 +912,39 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
}
#endif
+ /* Signal that we are going to add new objects. */
+ if (r->r_state == RT_CONSISTENT)
+ {
+#ifdef SHARED
+ /* Auditing checkpoint: we are going to add new objects. */
+ if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+ {
+ struct link_map *head = GL(dl_ns)[nsid]._ns_loaded;
+ /* Do not call the functions for any auditing object. */
+ if (head->l_auditing == 0)
+ {
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->activity != NULL)
+ afct->activity (&head->l_audit[cnt].cookie, LA_ACT_ADD);
+
+ afct = afct->next;
+ }
+ }
+ }
+#endif
+
+ /* Notify the debugger we have added some objects. We need to
+ call _dl_debug_initialize in a static program in case dynamic
+ linking has not been used before. */
+ r->r_state = RT_ADD;
+ _dl_debug_state ();
+ make_consistent = true;
+ }
+ else
+ assert (r->r_state == RT_ADD);
+
/* Enter the new object in the list of loaded objects. */
l = _dl_new_object (realname, name, l_type, loader, mode, nsid);
if (__builtin_expect (l == NULL, 0))
@@ -1044,7 +1084,7 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
}
# ifdef SHARED
- if (l->l_prev == NULL)
+ if (l->l_prev == NULL || (mode && __RTLD_AUDIT) != 0)
/* We are loading the executable itself when the dynamic linker
was executed directly. The setup will happen later. */
break;
@@ -1318,21 +1358,25 @@ cannot allocate TLS data structures for initial thread");
protection of the variable which contains the flags used in
the mprotect calls. */
#ifdef HAVE_Z_RELRO
- if (mode & __RTLD_DLOPEN)
+ if ((mode & (__RTLD_DLOPEN | __RTLD_AUDIT)) == __RTLD_DLOPEN)
{
uintptr_t p = ((uintptr_t) &__stack_prot) & ~(GLRO(dl_pagesize) - 1);
size_t s = (uintptr_t) &__stack_prot - p + sizeof (int);
__mprotect ((void *) p, s, PROT_READ|PROT_WRITE);
if (__builtin_expect (__check_caller (RETURN_ADDRESS (0),
- allow_ldso|allow_libc) == 0,
+ allow_ldso) == 0,
0))
- __stack_prot |= PROT_EXEC;
+ __stack_prot |= PROT_READ|PROT_WRITE|PROT_EXEC;
__mprotect ((void *) p, s, PROT_READ);
}
else
#endif
- __stack_prot |= PROT_EXEC;
+ __stack_prot |= PROT_READ|PROT_WRITE|PROT_EXEC;
+
+#ifdef check_consistency
+ check_consistency ();
+#endif
errval = (*GL(dl_make_stack_executable_hook)) (stack_endp);
if (errval)
@@ -1424,6 +1468,27 @@ cannot enable executable stack as shared object requires");
add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_SONAME]->d_un.d_val));
+#ifdef SHARED
+ /* Auditing checkpoint: we have a new object. */
+ if (__builtin_expect (GLRO(dl_naudit) > 0, 0)
+ && !GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing)
+ {
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->objopen != NULL)
+ {
+ l->l_audit[cnt].bindflags
+ = afct->objopen (l, nsid, &l->l_audit[cnt].cookie);
+
+ l->l_audit_any_plt |= l->l_audit[cnt].bindflags != 0;
+ }
+
+ afct = afct->next;
+ }
+ }
+#endif
+
return l;
}
@@ -1471,7 +1536,8 @@ print_search_path (struct r_search_path_elem **list,
this could mean there is something wrong in the installation and the
user might want to know about this. */
static int
-open_verify (const char *name, struct filebuf *fbp)
+open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
+ int whatcode)
{
/* This is the expected ELF header. */
#define ELF32_CLASS ELFCLASS32
@@ -1500,13 +1566,34 @@ open_verify (const char *name, struct filebuf *fbp)
ElfW(Word) type;
char vendor[4];
} expected_note = { 4, 16, 1, "GNU" };
- int fd;
/* Initialize it to make the compiler happy. */
const char *errstring = NULL;
int errval = 0;
+#ifdef SHARED
+ /* Give the auditing libraries a chance. */
+ if (__builtin_expect (GLRO(dl_naudit) > 0, 0) && whatcode != 0
+ && loader->l_auditing == 0)
+ {
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->objsearch != NULL)
+ {
+ name = afct->objsearch (name, &loader->l_audit[cnt].cookie,
+ whatcode);
+ if (name == NULL)
+ /* Ignore the path. */
+ return -1;
+ }
+
+ afct = afct->next;
+ }
+ }
+#endif
+
/* Open the file. We always open files read-only. */
- fd = __open (name, O_RDONLY);
+ int fd = __open (name, O_RDONLY);
if (fd != -1)
{
ElfW(Ehdr) *ehdr;
@@ -1664,7 +1751,7 @@ open_verify (const char *name, struct filebuf *fbp)
static int
open_path (const char *name, size_t namelen, int preloaded,
struct r_search_path_struct *sps, char **realname,
- struct filebuf *fbp)
+ struct filebuf *fbp, struct link_map *loader, int whatcode)
{
struct r_search_path_elem **dirs = sps->dirs;
char *buf;
@@ -1708,12 +1795,16 @@ open_path (const char *name, size_t namelen, int preloaded,
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
_dl_debug_printf (" trying file=%s\n", buf);
- fd = open_verify (buf, fbp);
+ fd = open_verify (buf, fbp, loader, whatcode);
if (this_dir->status[cnt] == unknown)
{
if (fd != -1)
this_dir->status[cnt] = existing;
- else
+ /* Do not update the directory information when loading
+ auditing code. We must try to disturb the program as
+ little as possible. */
+ else if (loader == NULL
+ || GL(dl_ns)[loader->l_ns]._ns_loaded->l_audit == 0)
{
/* We failed to open machine dependent library. Let's
test whether there is any directory at all. */
@@ -1731,7 +1822,7 @@ open_path (const char *name, size_t namelen, int preloaded,
}
/* Remember whether we found any existing directory. */
- here_any |= this_dir->status[cnt] == existing;
+ here_any |= this_dir->status[cnt] != nonexisting;
if (fd != -1 && __builtin_expect (preloaded, 0)
&& INTUSE(__libc_enable_secure))
@@ -1788,7 +1879,12 @@ open_path (const char *name, size_t namelen, int preloaded,
must not be freed using the general free() in libc. */
if (sps->malloced)
free (sps->dirs);
- sps->dirs = (void *) -1;
+#ifdef HAVE_Z_RELRO
+ /* rtld_search_dirs is attribute_relro, therefore avoid writing
+ into it. */
+ if (sps != &rtld_search_dirs)
+#endif
+ sps->dirs = (void *) -1;
}
return -1;
@@ -1847,6 +1943,32 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
loader->l_name[0]
? loader->l_name : rtld_progname, loader->l_ns);
+#ifdef SHARED
+ /* Give the auditing libraries a chance to change the name before we
+ try anything. */
+ if (__builtin_expect (GLRO(dl_naudit) > 0, 0)
+ && (loader == NULL || loader->l_auditing == 0))
+ {
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->objsearch != NULL)
+ {
+ name = afct->objsearch (name, &loader->l_audit[cnt].cookie,
+ LA_SER_ORIG);
+ if (name == NULL)
+ {
+ /* Do not try anything further. */
+ fd = -1;
+ goto no_file;
+ }
+ }
+
+ afct = afct->next;
+ }
+ }
+#endif
+
if (strchr (name, '/') == NULL)
{
/* Search for NAME in several places. */
@@ -1867,7 +1989,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
for (l = loader; fd == -1 && l; l = l->l_loader)
if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs,
- &realname, &fb);
+ &realname, &fb, loader, LA_SER_RUNPATH);
/* If dynamically linked, try the DT_RPATH of the executable
itself. NB: we do this for lookups in any namespace. */
@@ -1877,21 +1999,24 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
if (l && l->l_type != lt_loaded && l != loader
&& cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs,
- &realname, &fb);
+ &realname, &fb, loader ?: l, LA_SER_RUNPATH);
}
}
/* Try the LD_LIBRARY_PATH environment variable. */
if (fd == -1 && env_path_list.dirs != (void *) -1)
fd = open_path (name, namelen, preloaded, &env_path_list,
- &realname, &fb);
+ &realname, &fb,
+ loader ?: GL(dl_ns)[LM_ID_BASE]._ns_loaded,
+ LA_SER_LIBPATH);
/* Look at the RUNPATH information for this binary. */
if (fd == -1 && loader != NULL
&& cache_rpath (loader, &loader->l_runpath_dirs,
DT_RUNPATH, "RUNPATH"))
fd = open_path (name, namelen, preloaded,
- &loader->l_runpath_dirs, &realname, &fb);
+ &loader->l_runpath_dirs, &realname, &fb, loader,
+ LA_SER_RUNPATH);
if (fd == -1
&& (__builtin_expect (! preloaded, 1)
@@ -1939,7 +2064,9 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
if (cached != NULL)
{
- fd = open_verify (cached, &fb);
+ fd = open_verify (cached,
+ &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
+ LA_SER_CONFIG);
if (__builtin_expect (fd != -1, 1))
{
realname = local_strdup (cached);
@@ -1959,7 +2086,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
|| __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1))
&& rtld_search_dirs.dirs != (void *) -1)
fd = open_path (name, namelen, preloaded, &rtld_search_dirs,
- &realname, &fb);
+ &realname, &fb, l, LA_SER_DEFAULT);
/* Add another newline when we are tracing the library loading. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
@@ -1975,12 +2102,16 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
fd = -1;
else
{
- fd = open_verify (realname, &fb);
+ fd = open_verify (realname, &fb,
+ loader ?: GL(dl_ns)[nsid]._ns_loaded, 0);
if (__builtin_expect (fd, 0) == -1)
free (realname);
}
}
+#ifdef SHARED
+ no_file:
+#endif
/* In case the LOADER information has only been provided to get to
the appropriate RUNPATH/RPATH information we do not need it
anymore. */
diff --git a/elf/dl-object.c b/elf/dl-object.c
index b46ebdc33f..86f7a8e4d9 100644
--- a/elf/dl-object.c
+++ b/elf/dl-object.c
@@ -39,14 +39,24 @@ _dl_new_object (char *realname, const char *libname, int type,
size_t libname_len = strlen (libname) + 1;
struct link_map *new;
struct libname_list *newname;
+#ifdef SHARED
+ /* We create the map for the executable before we know whether we have
+ auditing libraries and if yes, how many. Assume the worst. */
+ unsigned int naudit = GLRO(dl_naudit) ?: ((mode & __RTLD_OPENEXEC)
+ ? DL_NNS : 0);
+ size_t audit_space = naudit * sizeof (new->l_audit[0]);
+#else
+# define audit_space 0
+#endif
- new = (struct link_map *) calloc (sizeof (*new) + sizeof (*newname)
- + libname_len, 1);
+ new = (struct link_map *) calloc (sizeof (*new) + audit_space
+ + sizeof (*newname) + libname_len, 1);
if (new == NULL)
return NULL;
new->l_real = new;
- new->l_libname = newname = (struct libname_list *) (new + 1);
+ new->l_libname = newname = (struct libname_list *) ((char *) (new + 1)
+ + audit_space);
newname->name = (char *) memcpy (newname + 1, libname, libname_len);
/* newname->next = NULL; We use calloc therefore not necessary. */
newname->dont_free = 1;
@@ -59,6 +69,14 @@ _dl_new_object (char *realname, const char *libname, int type,
#endif
new->l_ns = nsid;
+#ifdef SHARED
+ for (unsigned int cnt = 0; cnt < naudit; ++cnt)
+ {
+ new->l_audit[cnt].cookie = (uintptr_t) new;
+ /* new->l_audit[cnt].bindflags = 0; */
+ }
+#endif
+
/* new->l_global = 0; We use calloc therefore not necessary. */
/* Use the 'l_scope_mem' array by default for the the 'l_scope'
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 7e890ad7f7..4de20720ed 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -1,5 +1,5 @@
/* Load a shared object at runtime, relocate it, and run its initializer.
- Copyright (C) 1996-2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1996-2004, 2005 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
@@ -49,11 +49,6 @@ weak_extern (BP_SYM (_dl_sysdep_start))
extern int __libc_multiple_libcs; /* Defined in init-first.c. */
-extern int __libc_argc attribute_hidden;
-extern char **__libc_argv attribute_hidden;
-
-extern char **__environ;
-
/* Undefine the following for debugging. */
/* #define SCOPE_DEBUG 1 */
#ifdef SCOPE_DEBUG
@@ -74,6 +69,10 @@ struct dl_open_args
struct link_map *map;
/* Namespace ID. */
Lmid_t nsid;
+ /* Original parameters to the program and the current environment. */
+ int argc;
+ char **argv;
+ char **env;
};
@@ -115,8 +114,8 @@ add_to_global (struct link_map *new)
{
GL(dl_ns)[new->l_ns]._ns_global_scope_alloc = 0;
nomem:
- GLRO(dl_signal_error) (ENOMEM, new->l_libname->name, NULL,
- N_("cannot extend global scope"));
+ _dl_signal_error (ENOMEM, new->l_libname->name, NULL,
+ N_("cannot extend global scope"));
return 1;
}
@@ -171,13 +170,14 @@ dl_open_worker (void *a)
int lazy;
unsigned int i;
#ifdef USE_TLS
- bool any_tls;
+ bool any_tls = false;
#endif
struct link_map *call_map = NULL;
/* Check whether _dl_open() has been called from a valid DSO. */
- if (__check_caller (args->caller_dl_open, allow_libc|allow_libdl) != 0)
- GLRO(dl_signal_error) (0, "dlopen", NULL, N_("invalid caller"));
+ if (__check_caller (args->caller_dl_open,
+ allow_libc|allow_libdl|allow_ldso) != 0)
+ _dl_signal_error (0, "dlopen", NULL, N_("invalid caller"));
/* Determine the caller's map if necessary. This is needed in case
we have a DST, when we don't know the namespace ID we have to put
@@ -218,6 +218,8 @@ dl_open_worker (void *a)
}
}
+ assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
+
/* Maybe we have to expand a DST. */
if (__builtin_expect (dst != NULL, 0))
{
@@ -226,10 +228,10 @@ dl_open_worker (void *a)
char *new_file;
/* DSTs must not appear in SUID/SGID programs. */
- if (__libc_enable_secure)
+ if (INTUSE(__libc_enable_secure))
/* This is an error. */
- GLRO(dl_signal_error) (0, "dlopen", NULL,
- N_("DST not allowed in SUID/SGID programs"));
+ _dl_signal_error (0, "dlopen", NULL,
+ N_("DST not allowed in SUID/SGID programs"));
/* Determine how much space we need. We have to allocate the
@@ -244,8 +246,8 @@ dl_open_worker (void *a)
/* If the substitution failed don't try to load. */
if (*new_file == '\0')
- GLRO(dl_signal_error) (0, "dlopen", NULL,
- N_("empty dynamic string token substitution"));
+ _dl_signal_error (0, "dlopen", NULL,
+ N_("empty dynamic string token substitution"));
/* Now we have a new file name. */
file = new_file;
@@ -256,8 +258,8 @@ dl_open_worker (void *a)
}
/* Load the named object. */
- args->map = new = GLRO(dl_map_object) (call_map, file, 0, lt_loaded, 0,
- mode | __RTLD_CALLMAP, args->nsid);
+ args->map = new = _dl_map_object (call_map, file, 0, lt_loaded, 0,
+ mode | __RTLD_CALLMAP, args->nsid);
/* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
set and the object is not already loaded. */
@@ -279,8 +281,8 @@ dl_open_worker (void *a)
{
/* Let the user know about the opencount. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
- GLRO(dl_debug_printf) ("opening file=%s [%lu]; opencount=%u\n\n",
- new->l_name, new->l_ns, new->l_opencount);
+ _dl_debug_printf ("opening file=%s [%lu]; opencount=%u\n\n",
+ new->l_name, new->l_ns, new->l_opencount);
/* If the user requested the object to be in the global namespace
but it is not so far, add it now. */
@@ -296,23 +298,50 @@ dl_open_worker (void *a)
/* Increment just the reference counter of the object. */
++new->l_opencount;
+ assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
+
return;
}
/* Load that object's dependencies. */
- GLRO(dl_map_object_deps) (new, NULL, 0, 0,
- mode & (__RTLD_DLOPEN | RTLD_DEEPBIND));
+ _dl_map_object_deps (new, NULL, 0, 0,
+ mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT));
/* So far, so good. Now check the versions. */
for (i = 0; i < new->l_searchlist.r_nlist; ++i)
if (new->l_searchlist.r_list[i]->l_real->l_versions == NULL)
- (void) GLRO(dl_check_map_versions) (new->l_searchlist.r_list[i]->l_real,
- 0, 0);
+ (void) _dl_check_map_versions (new->l_searchlist.r_list[i]->l_real,
+ 0, 0);
#ifdef SCOPE_DEBUG
show_scope (new);
#endif
+#ifdef SHARED
+ /* Auditing checkpoint: we have added all objects. */
+ if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+ {
+ struct link_map *head = GL(dl_ns)[new->l_ns]._ns_loaded;
+ /* Do not call the functions for any auditing object. */
+ if (head->l_auditing == 0)
+ {
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->activity != NULL)
+ afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT);
+
+ afct = afct->next;
+ }
+ }
+ }
+#endif
+
+ /* Notify the debugger all new objects are now ready to go. */
+ struct r_debug *r = _dl_debug_initialize (0, args->nsid);
+ r->r_state = RT_CONSISTENT;
+ _dl_debug_state ();
+
/* Only do lazy relocation if `LD_BIND_NOW' is not set. */
lazy = (mode & RTLD_BINDING_MASK) == RTLD_LAZY && GLRO(dl_lazy);
@@ -336,12 +365,12 @@ dl_open_worker (void *a)
start the profiling. */
struct link_map *old_profile_map = GL(dl_profile_map);
- GLRO(dl_relocate_object) (l, l->l_scope, 1, 1);
+ _dl_relocate_object (l, l->l_scope, 1, 1);
if (old_profile_map == NULL && GL(dl_profile_map) != NULL)
{
/* We must prepare the profiling. */
- GLRO(dl_start_profile) ();
+ _dl_start_profile ();
/* Prevent unloading the object. */
GL(dl_profile_map)->l_flags_1 |= DF_1_NODELETE;
@@ -349,7 +378,7 @@ dl_open_worker (void *a)
}
else
#endif
- GLRO(dl_relocate_object) (l, l->l_scope, lazy, 0);
+ _dl_relocate_object (l, l->l_scope, lazy, 0);
}
if (l == new)
@@ -357,22 +386,6 @@ dl_open_worker (void *a)
l = l->l_prev;
}
-#ifdef USE_TLS
- /* Do static TLS initialization now if it has been delayed because
- the TLS template might not be fully relocated at _dl_allocate_static_tls
- time. */
- for (l = new; l; l = l->l_next)
- if (l->l_need_tls_init)
- {
- l->l_need_tls_init = 0;
- GL(dl_init_static_tls) (l);
- }
-
- /* We normally don't bump the TLS generation counter. There must be
- actually a need to do this. */
- any_tls = false;
-#endif
-
/* Increment the open count for all dependencies. If the file is
not loaded as a dependency here add the search list of the newly
loaded object to the scope. */
@@ -412,8 +425,8 @@ dl_open_worker (void *a)
newp = (struct r_scope_elem **)
malloc (new_size * sizeof (struct r_scope_elem *));
if (newp == NULL)
- GLRO(dl_signal_error) (ENOMEM, "dlopen", NULL,
- N_("cannot create scope list"));
+ _dl_signal_error (ENOMEM, "dlopen", NULL,
+ N_("cannot create scope list"));
imap->l_scope = memcpy (newp, imap->l_scope,
cnt * sizeof (imap->l_scope[0]));
}
@@ -423,8 +436,8 @@ dl_open_worker (void *a)
realloc (imap->l_scope,
new_size * sizeof (struct r_scope_elem *));
if (newp == NULL)
- GLRO(dl_signal_error) (ENOMEM, "dlopen", NULL,
- N_("cannot create scope list"));
+ _dl_signal_error (ENOMEM, "dlopen", NULL,
+ N_("cannot create scope list"));
imap->l_scope = newp;
}
@@ -441,76 +454,35 @@ dl_open_worker (void *a)
> 0, 0))
{
/* Now that we know the object is loaded successfully add
- modules containing TLS data to the dtv info table. We
+ modules containing TLS data to the slot info table. We
might have to increase its size. */
- struct dtv_slotinfo_list *listp;
- struct dtv_slotinfo_list *prevp;
- size_t idx = new->l_searchlist.r_list[i]->l_tls_modid;
-
- assert (new->l_searchlist.r_list[i]->l_type == lt_loaded);
+ _dl_add_to_slotinfo (new->l_searchlist.r_list[i]);
- /* Find the place in the dtv slotinfo list. */
- listp = GL(dl_tls_dtv_slotinfo_list);
- prevp = NULL; /* Needed to shut up gcc. */
- do
+ if (new->l_searchlist.r_list[i]->l_need_tls_init)
{
- /* Does it fit in the array of this list element? */
- if (idx < listp->len)
- break;
- idx -= listp->len;
- prevp = listp;
- listp = listp->next;
+ new->l_searchlist.r_list[i]->l_need_tls_init = 0;
+# ifdef SHARED
+ /* Update the slot information data for at least the
+ generation of the DSO we are allocating data for. */
+ _dl_update_slotinfo (new->l_searchlist.r_list[i]->l_tls_modid);
+# endif
+
+ GL(dl_init_static_tls) (new->l_searchlist.r_list[i]);
+ assert (new->l_searchlist.r_list[i]->l_need_tls_init == 0);
}
- while (listp != NULL);
-
- if (listp == NULL)
- {
- /* When we come here it means we have to add a new element
- to the slotinfo list. And the new module must be in
- the first slot. */
- assert (idx == 0);
-
- listp = prevp->next = (struct dtv_slotinfo_list *)
- malloc (sizeof (struct dtv_slotinfo_list)
- + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
- if (listp == NULL)
- {
- /* We ran out of memory. We will simply fail this
- call but don't undo anything we did so far. The
- application will crash or be terminated anyway very
- soon. */
-
- /* We have to do this since some entries in the dtv
- slotinfo array might already point to this
- generation. */
- ++GL(dl_tls_generation);
-
- GLRO(dl_signal_error) (ENOMEM, "dlopen", NULL, N_("\
-cannot create TLS data structures"));
- }
-
- listp->len = TLS_SLOTINFO_SURPLUS;
- listp->next = NULL;
- memset (listp->slotinfo, '\0',
- TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
- }
-
- /* Add the information into the slotinfo data structure. */
- listp->slotinfo[idx].map = new->l_searchlist.r_list[i];
- listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
/* We have to bump the generation counter. */
any_tls = true;
}
/* Bump the generation number if necessary. */
- if (any_tls)
- if (__builtin_expect (++GL(dl_tls_generation) == 0, 0))
- __libc_fatal (_("TLS generation counter wrapped! Please report this."));
+ if (any_tls && __builtin_expect (++GL(dl_tls_generation) == 0, 0))
+ _dl_fatal_printf (N_("\
+TLS generation counter wrapped! Please report this."));
#endif
/* Run the initializer functions of new objects. */
- GLRO(dl_init) (new, __libc_argc, __libc_argv, __environ);
+ _dl_init (new, args->argc, args->argv, args->env);
/* Now we can make the new map available in the global scope. */
if (mode & RTLD_GLOBAL)
@@ -532,14 +504,14 @@ cannot create TLS data structures"));
/* Let the user know about the opencount. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
- GLRO(dl_debug_printf) ("opening file=%s [%lu]; opencount=%u\n\n",
- new->l_name, new->l_ns, new->l_opencount);
+ _dl_debug_printf ("opening file=%s [%lu]; opencount=%u\n\n",
+ new->l_name, new->l_ns, new->l_opencount);
}
void *
-internal_function
-_dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid)
+_dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
+ int argc, char *argv[], char *env[])
{
struct dl_open_args args;
const char *objname;
@@ -548,8 +520,7 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid)
if ((mode & RTLD_BINDING_MASK) == 0)
/* One of the flags must be set. */
- GLRO(dl_signal_error) (EINVAL, file, NULL,
- N_("invalid mode for dlopen()"));
+ _dl_signal_error (EINVAL, file, NULL, N_("invalid mode for dlopen()"));
/* Make sure we are alone. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
@@ -566,16 +537,20 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid)
/* No more namespace available. */
__rtld_lock_unlock_recursive (GL(dl_load_lock));
- GLRO(dl_signal_error) (EINVAL, file, NULL, N_("\
+ _dl_signal_error (EINVAL, file, NULL, N_("\
no more namespaces available for dlmopen()"));
}
+
+ _dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;
}
/* Never allow loading a DSO in a namespace which is empty. Such
- direct placements is only causing problems. */
+ direct placements is only causing problems. Also don't allow
+ loading into a namespace used for auditing. */
else if (nsid != LM_ID_BASE && nsid != __LM_ID_CALLER
- && GL(dl_ns)[nsid]._ns_nloaded == 0)
- GLRO(dl_signal_error) (EINVAL, file, NULL,
- N_("invalid target namespace in dlmopen()"));
+ && (GL(dl_ns)[nsid]._ns_nloaded == 0
+ || GL(dl_ns)[nsid]._ns_loaded->l_auditing))
+ _dl_signal_error (EINVAL, file, NULL,
+ N_("invalid target namespace in dlmopen()"));
args.file = file;
args.mode = mode;
@@ -583,11 +558,14 @@ no more namespaces available for dlmopen()"));
args.caller_dl_open = RETURN_ADDRESS (0);
args.map = NULL;
args.nsid = nsid;
- errcode = GLRO(dl_catch_error) (&objname, &errstring, dl_open_worker, &args);
+ args.argc = argc;
+ args.argv = argv;
+ args.env = env;
+ errcode = _dl_catch_error (&objname, &errstring, dl_open_worker, &args);
#ifndef MAP_COPY
/* We must munmap() the cache file. */
- GLRO(dl_unload_cache) ();
+ _dl_unload_cache ();
#endif
/* Release the lock. */
@@ -603,21 +581,22 @@ no more namespaces available for dlmopen()"));
state if relocation failed, for example. */
if (args.map)
{
- unsigned int i;
-
/* Increment open counters for all objects since this
sometimes has not happened yet. */
if (args.map->l_searchlist.r_list[0]->l_opencount == 0)
- for (i = 0; i < args.map->l_searchlist.r_nlist; ++i)
+ for (unsigned int i = 0; i < args.map->l_searchlist.r_nlist; ++i)
++args.map->l_searchlist.r_list[i]->l_opencount;
#ifdef USE_TLS
- /* Maybe some of the modules which were loaded uses TLS.
+ /* Maybe some of the modules which were loaded use TLS.
Since it will be removed in the following _dl_close call
- we have to mark the dtv array as having gaps to fill
- the holes. This is a pessimistic assumption which won't
- hurt if not true. */
- GL(dl_tls_dtv_gaps) = true;
+ we have to mark the dtv array as having gaps to fill the
+ holes. This is a pessimistic assumption which won't hurt
+ if not true. There is no need to do this when we are
+ loading the auditing DSOs since TLS has not yet been set
+ up. */
+ if ((mode & __RTLD_AUDIT) == 0)
+ GL(dl_tls_dtv_gaps) = true;
#endif
_dl_close (args.map);
@@ -639,20 +618,23 @@ no more namespaces available for dlmopen()"));
memcpy (local_errstring, errstring, len_errstring);
}
- if (errstring != _dl_out_of_memory)
+ if (errstring != INTUSE(_dl_out_of_memory))
free ((char *) errstring);
+ assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
+
/* Reraise the error. */
- GLRO(dl_signal_error) (errcode, objname, NULL, local_errstring);
+ _dl_signal_error (errcode, objname, NULL, local_errstring);
}
+ assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
+
#ifndef SHARED
DL_STATIC_INIT (args.map);
#endif
return args.map;
}
-libc_hidden_def (_dl_open)
#ifdef SCOPE_DEBUG
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 4004316c5a..b680683198 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -48,8 +48,6 @@ void
internal_function __attribute_noinline__
_dl_allocate_static_tls (struct link_map *map)
{
- size_t offset;
-
/* If the alignment requirements are too high fail. */
if (map->l_tls_align > GL(dl_tls_static_align))
{
@@ -71,15 +69,15 @@ cannot allocate memory in static TLS block"));
n = (freebytes - blsize) / map->l_tls_align;
- offset = GL(dl_tls_static_used) + (freebytes - n * map->l_tls_align
- - map->l_tls_firstbyte_offset);
+ size_t offset = GL(dl_tls_static_used) + (freebytes - n * map->l_tls_align
+ - map->l_tls_firstbyte_offset);
map->l_tls_offset = GL(dl_tls_static_used) = offset;
# elif TLS_DTV_AT_TP
size_t used;
size_t check;
- offset = roundup (GL(dl_tls_static_used), map->l_tls_align);
+ size_t offset = roundup (GL(dl_tls_static_used), map->l_tls_align);
used = offset + map->l_tls_blocksize;
check = used;
/* dl_tls_static_used includes the TCB at the beginning. */
@@ -93,8 +91,20 @@ cannot allocate memory in static TLS block"));
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
# endif
- if (map->l_relocated)
- GL(dl_init_static_tls) (map);
+ /* If the object is not yet relocated we cannot initialize the
+ static TLS region. Delay it. */
+ if (map->l_real->l_relocated)
+ {
+#ifdef SHARED
+ if (__builtin_expect (THREAD_DTV()[0].counter != GL(dl_tls_generation),
+ 0))
+ /* Update the slot information data for at least the generation of
+ the DSO we are allocating data for. */
+ (void) _dl_update_slotinfo (map->l_tls_modid);
+#endif
+
+ GL(dl_init_static_tls) (map);
+ }
else
map->l_need_tls_init = 1;
}
@@ -114,7 +124,8 @@ _dl_nothread_init_static_tls (struct link_map *map)
# endif
/* Fill in the DTV slot so that a later LD/GD access will find it. */
- THREAD_DTV ()[map->l_tls_modid].pointer = dest;
+ THREAD_DTV ()[map->l_tls_modid].pointer.val = dest;
+ THREAD_DTV ()[map->l_tls_modid].pointer.is_static = true;
/* Initialize the memory. */
memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
@@ -137,11 +148,17 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
/* Initialize it to make the compiler happy. */
const char *errstring = NULL;
+#ifdef SHARED
+ /* If we are auditing, install the same handlers we need for profiling. */
+ consider_profiling |= GLRO(dl_audit) != NULL;
+#endif
+
if (l->l_relocated)
return;
/* If DT_BIND_NOW is set relocate all references in this object. We
do not do this if we are profiling, of course. */
+ // XXX Correct for auditing?
if (!consider_profiling
&& __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0))
lazy = 0;
@@ -225,29 +242,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
l->l_lookup_cache.ret = (*ref); \
l->l_lookup_cache.value = _lr; })) \
: l)
-#define RESOLVE(ref, version, r_type) \
- (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
- ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \
- && elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \
- ? (bump_num_cache_relocations (), \
- (*ref) = l->l_lookup_cache.ret, \
- l->l_lookup_cache.value) \
- : ({ lookup_t _lr; \
- int _tc = elf_machine_type_class (r_type); \
- l->l_lookup_cache.type_class = _tc; \
- l->l_lookup_cache.sym = (*ref); \
- const struct r_found_version *v = NULL; \
- int flags = DL_LOOKUP_ADD_DEPENDENCY; \
- if ((version) != NULL && (version)->hash != 0) \
- { \
- v = (version); \
- flags = 0; \
- } \
- _lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref), \
- scope, v, _tc, flags, NULL); \
- l->l_lookup_cache.ret = (*ref); \
- l->l_lookup_cache.value = _lr; })) \
- : l->l_addr)
/* This macro is used as a callback from elf_machine_rel{a,} when a
static TLS reloc is about to be performed. Since (in dl-load.c) we
@@ -276,20 +270,19 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
will be NULL. */
if (l->l_info[DT_PLTRELSZ] == NULL)
{
- errstring = N_("%s: profiler found no PLTREL in object %s\n");
+ errstring = N_("%s: no PLTREL found in object %s\n");
fatal:
_dl_fatal_printf (errstring,
rtld_progname ?: "<program name unknown>",
l->l_name);
}
- l->l_reloc_result =
- (ElfW(Addr) *) calloc (sizeof (ElfW(Addr)),
- l->l_info[DT_PLTRELSZ]->d_un.d_val);
+ l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]),
+ l->l_info[DT_PLTRELSZ]->d_un.d_val);
if (l->l_reloc_result == NULL)
{
errstring = N_("\
-%s: profiler out of memory shadowing PLTREL of %s\n");
+%s: out of memory to store relocation results for %s\n");
goto fatal;
}
}
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index a0aecda2e8..f92cbe26bd 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -1,5 +1,5 @@
/* On-demand PLT fixup for shared objects.
- Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1995-2002,2003,2004,2005 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
@@ -22,6 +22,7 @@
#include <alloca.h>
#include <stdlib.h>
#include <unistd.h>
+#include <sys/param.h>
#include <ldsodefs.h>
#include "dynamic-link.h"
@@ -51,15 +52,15 @@
function. */
#ifndef ELF_MACHINE_NO_PLT
-static ElfW(Addr)
-__attribute ((used, noinline)) ARCH_FIXUP_ATTRIBUTE
-fixup (
+DL_FIXUP_VALUE_TYPE
+__attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
+_dl_fixup (
# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
- ELF_MACHINE_RUNTIME_FIXUP_ARGS,
+ ELF_MACHINE_RUNTIME_FIXUP_ARGS,
# endif
- /* GKM FIXME: Fix trampoline to pass bounds so we can do
- without the `__unbounded' qualifier. */
- struct link_map *__unbounded l, ElfW(Word) reloc_offset)
+ /* GKM FIXME: Fix trampoline to pass bounds so we can do
+ without the `__unbounded' qualifier. */
+ struct link_map *__unbounded l, ElfW(Word) reloc_offset)
{
const ElfW(Sym) *const symtab
= (const void *) D_PTR (l, l_info[DT_SYMTAB]);
@@ -70,7 +71,7 @@ fixup (
const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
lookup_t result;
- ElfW(Addr) value;
+ DL_FIXUP_VALUE_TYPE value;
/* Sanity check that we're really looking at a PLT relocation. */
assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
@@ -80,8 +81,6 @@ fixup (
if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
{
const struct r_found_version *version = NULL;
- // XXX Why exactly do we have the differentiation of the flags here?
- int flags = DL_LOOKUP_ADD_DEPENDENCY;
if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
{
@@ -91,8 +90,6 @@ fixup (
version = &l->l_versions[ndx];
if (version->hash == 0)
version = NULL;
- else
- flags = 0;
}
result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
@@ -102,16 +99,16 @@ fixup (
/* Currently result contains the base load address (or link map)
of the object that defines sym. Now add in the symbol
offset. */
- value = (sym ? LOOKUP_VALUE_ADDRESS (result) + sym->st_value : 0);
+ value = DL_FIXUP_MAKE_VALUE (result,
+ sym ? LOOKUP_VALUE_ADDRESS (result)
+ + sym->st_value : 0);
}
else
{
/* We already found the symbol. The module (and therefore its load
address) is also known. */
- value = l->l_addr + sym->st_value;
-#ifdef DL_LOOKUP_RETURNS_MAP
+ value = DL_FIXUP_MAKE_VALUE (l, l->l_addr + sym->st_value);
result = l;
-#endif
}
/* And now perhaps the relocation addend. */
@@ -127,45 +124,45 @@ fixup (
#if !defined PROF && !defined ELF_MACHINE_NO_PLT && !__BOUNDED_POINTERS__
-static ElfW(Addr)
-__attribute ((used, noinline)) ARCH_FIXUP_ATTRIBUTE
-profile_fixup (
+DL_FIXUP_VALUE_TYPE
+__attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
+_dl_profile_fixup (
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
- ELF_MACHINE_RUNTIME_FIXUP_ARGS,
+ ELF_MACHINE_RUNTIME_FIXUP_ARGS,
#endif
- struct link_map *l, ElfW(Word) reloc_offset, ElfW(Addr) retaddr)
+ struct link_map *l, ElfW(Word) reloc_offset,
+ ElfW(Addr) retaddr, void *regs, long int *framesizep)
{
void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = INTUSE(_dl_mcount);
- ElfW(Addr) *resultp;
- lookup_t result;
- ElfW(Addr) value;
/* This is the address in the array where we store the result of previous
relocations. */
- resultp = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
+ struct reloc_result *reloc_result
+ = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
+ DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr;
- value = *resultp;
- if (value == 0)
+ DL_FIXUP_VALUE_TYPE value = *resultp;
+ if (DL_FIXUP_VALUE_CODE_ADDR (value) == 0)
{
/* This is the first time we have to relocate this object. */
const ElfW(Sym) *const symtab
= (const void *) D_PTR (l, l_info[DT_SYMTAB]);
- const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
+ const char *strtab = (const char *) D_PTR (l, l_info[DT_STRTAB]);
const PLTREL *const reloc
= (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
- const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
+ const ElfW(Sym) *refsym = &symtab[ELFW(R_SYM) (reloc->r_info)];
+ const ElfW(Sym) *defsym = refsym;
+ lookup_t result;
/* Sanity check that we're really looking at a PLT relocation. */
assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
/* Look up the target symbol. If the symbol is marked STV_PROTECTED
don't look in the global scope. */
- if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
+ if (__builtin_expect (ELFW(ST_VISIBILITY) (refsym->st_other), 0) == 0)
{
const struct r_found_version *version = NULL;
- // XXX Why exactly do we have the differentiation of the flags here?
- int flags = DL_LOOKUP_ADD_DEPENDENCY;
if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
{
@@ -175,11 +172,9 @@ profile_fixup (
version = &l->l_versions[ndx];
if (version->hash == 0)
version = NULL;
- else
- flags = 0;
}
- result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
+ result = _dl_lookup_symbol_x (strtab + refsym->st_name, l, &defsym,
l->l_scope, version,
ELF_RTYPE_CLASS_PLT,
DL_LOOKUP_ADD_DEPENDENCY, NULL);
@@ -187,26 +182,188 @@ profile_fixup (
/* Currently result contains the base load address (or link map)
of the object that defines sym. Now add in the symbol
offset. */
- value = (sym ? LOOKUP_VALUE_ADDRESS (result) + sym->st_value : 0);
+ value = DL_FIXUP_MAKE_VALUE (result,
+ defsym != NULL
+ ? LOOKUP_VALUE_ADDRESS (result)
+ + defsym->st_value : 0);
}
else
{
/* We already found the symbol. The module (and therefore its load
address) is also known. */
- value = l->l_addr + sym->st_value;
-#ifdef DL_LOOKUP_RETURNS_MAP
+ value = DL_FIXUP_MAKE_VALUE (l, l->l_addr + refsym->st_value);
result = l;
-#endif
}
/* And now perhaps the relocation addend. */
value = elf_machine_plt_value (l, reloc, value);
+#ifdef SHARED
+ /* Auditing checkpoint: we have a new binding. Provide the
+ auditing libraries the possibility to change the value and
+ tell us whether further auditing is wanted. */
+ if (defsym != NULL && GLRO(dl_naudit) > 0)
+ {
+ reloc_result->bound = result;
+ /* Compute index of the symbol entry in the symbol table of
+ the DSO with the definition. */
+ reloc_result->boundndx = (defsym
+ - (ElfW(Sym) *) D_PTR (result,
+ l_info[DT_SYMTAB]));
+
+ /* Determine whether any of the two participating DSOs is
+ interested in auditing. */
+ if ((l->l_audit_any_plt | result->l_audit_any_plt) != 0)
+ {
+ unsigned int altvalue = 0;
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ /* Synthesize a symbol record where the st_value field is
+ the result. */
+ ElfW(Sym) sym = *defsym;
+ sym.st_value = DL_FIXUP_VALUE_ADDR (value);
+
+ /* Keep track whether there is any interest in tracing
+ the call in the lower two bits. */
+ assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8);
+ assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3);
+ reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT;
+
+ const char *strtab2 = (const void *) D_PTR (result,
+ l_info[DT_STRTAB]);
+
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ /* XXX Check whether both DSOs must request action or
+ only one */
+ if ((l->l_audit[cnt].bindflags & LA_FLG_BINDFROM) != 0
+ && (result->l_audit[cnt].bindflags & LA_FLG_BINDTO) != 0)
+ {
+ unsigned int flags = altvalue;
+ if (afct->symbind != NULL)
+ {
+ uintptr_t new_value
+ = afct->symbind (&sym, reloc_result->boundndx,
+ &l->l_audit[cnt].cookie,
+ &result->l_audit[cnt].cookie,
+ &flags,
+ strtab2 + defsym->st_name);
+ if (new_value != (uintptr_t) sym.st_value)
+ {
+ altvalue = LA_SYMB_ALTVALUE;
+ sym.st_value = new_value;
+ }
+ }
+
+ /* Remember the results for every audit library and
+ store a summary in the first two bits. */
+ reloc_result->enterexit
+ &= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT);
+ reloc_result->enterexit
+ |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
+ << ((cnt + 1) * 2));
+ }
+ else
+ /* If the bind flags say this auditor is not interested,
+ set the bits manually. */
+ reloc_result->enterexit
+ |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)
+ << ((cnt + 1) * 2));
+
+ afct = afct->next;
+ }
+
+ reloc_result->flags = altvalue;
+ value = DL_FIXUP_ADDR_VALUE (sym.st_value);
+ }
+ else
+ /* Set all bits since this symbol binding is not interesting. */
+ reloc_result->enterexit = (1u << DL_NNS) - 1;
+ }
+#endif
+
/* Store the result for later runs. */
if (__builtin_expect (! GLRO(dl_bind_not), 1))
*resultp = value;
}
- (*mcount_fct) (retaddr, value);
+ /* By default we do not call the pltexit function. */
+ long int framesize = -1;
+
+#ifdef SHARED
+ /* Auditing checkpoint: report the PLT entering and allow the
+ auditors to change the value. */
+ if (DL_FIXUP_VALUE_CODE_ADDR (value) != 0 && GLRO(dl_naudit) > 0
+ /* Don't do anything if no auditor wants to intercept this call. */
+ && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0)
+ {
+ ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
+ l_info[DT_SYMTAB])
+ + reloc_result->boundndx);
+
+ /* Set up the sym parameter. */
+ ElfW(Sym) sym = *defsym;
+ sym.st_value = DL_FIXUP_VALUE_ADDR (value);
+
+ /* Get the symbol name. */
+ const char *strtab = (const void *) D_PTR (reloc_result->bound,
+ l_info[DT_STRTAB]);
+ const char *symname = strtab + sym.st_name;
+
+ /* Keep track of overwritten addresses. */
+ unsigned int altvalue = reloc_result->flags;
+
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->ARCH_LA_PLTENTER != NULL
+ && (reloc_result->enterexit
+ & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0)
+ {
+ unsigned int flags = altvalue;
+ long int new_framesize = -1;
+ uintptr_t new_value
+ = afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx,
+ &l->l_audit[cnt].cookie,
+ &reloc_result->bound->l_audit[cnt].cookie,
+ regs, &flags, symname,
+ &new_framesize);
+ if (new_value != (uintptr_t) sym.st_value)
+ {
+ altvalue = LA_SYMB_ALTVALUE;
+ sym.st_value = new_value;
+ }
+
+ /* Remember the results for every audit library and
+ store a summary in the first two bits. */
+ reloc_result->enterexit
+ |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
+ << (2 * (cnt + 1)));
+
+ if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT
+ << (2 * (cnt + 1))))
+ == 0 && new_framesize != -1 && framesize != -2)
+ {
+ /* If this is the first call providing information,
+ use it. */
+ if (framesize == -1)
+ framesize = new_framesize;
+ /* If two pltenter calls provide conflicting information,
+ use the larger value. */
+ else if (new_framesize != framesize)
+ framesize = MAX (new_framesize, framesize);
+ }
+ }
+
+ afct = afct->next;
+ }
+
+ value = DL_FIXUP_ADDR_VALUE (sym.st_value);
+ }
+#endif
+
+ /* Store the frame size information. */
+ *framesizep = framesize;
+
+ (*mcount_fct) (retaddr, DL_FIXUP_VALUE_CODE_ADDR (value));
return value;
}
@@ -214,9 +371,45 @@ profile_fixup (
#endif /* PROF && ELF_MACHINE_NO_PLT */
-/* This macro is defined in dl-machine.h to define the entry point called
- by the PLT. The `fixup' function above does the real work, but a little
- more twiddling is needed to get the stack right and jump to the address
- finally resolved. */
+#include <stdio.h>
+void
+ARCH_FIXUP_ATTRIBUTE
+_dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_offset,
+ const void *inregs, void *outregs)
+{
+#ifdef SHARED
+ /* This is the address in the array where we store the result of previous
+ relocations. */
+ // XXX Maybe the bound information must be stored on the stack since
+ // XXX with bind_not a new value could have been stored in the meantime.
+ struct reloc_result *reloc_result
+ = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
+ ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
+ l_info[DT_SYMTAB])
+ + reloc_result->boundndx);
+
+ /* Set up the sym parameter. */
+ ElfW(Sym) sym = *defsym;
+
+ /* Get the symbol name. */
+ const char *strtab = (const void *) D_PTR (reloc_result->bound,
+ l_info[DT_STRTAB]);
+ const char *symname = strtab + sym.st_name;
+
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->ARCH_LA_PLTEXIT != NULL
+ && (reloc_result->enterexit
+ & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0)
+ {
+ afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx,
+ &l->l_audit[cnt].cookie,
+ &reloc_result->bound->l_audit[cnt].cookie,
+ inregs, outregs, symname);
+ }
-ELF_MACHINE_RUNTIME_TRAMPOLINE
+ afct = afct->next;
+ }
+#endif
+}
diff --git a/elf/dl-sym.c b/elf/dl-sym.c
index ba00ef56f4..ca83daf21d 100644
--- a/elf/dl-sym.c
+++ b/elf/dl-sym.c
@@ -116,14 +116,69 @@ RTLD_NEXT used in code not dynamically loaded"));
if (ref != NULL)
{
+ void *value;
+
#if defined USE_TLS && defined SHARED
if (ELFW(ST_TYPE) (ref->st_info) == STT_TLS)
/* The found symbol is a thread-local storage variable.
Return the address for to the current thread. */
- return _dl_tls_symaddr (result, ref);
+ value = _dl_tls_symaddr (result, ref);
+ else
+#endif
+ value = DL_SYMBOL_ADDRESS (result, ref);
+
+#ifdef SHARED
+ /* Auditing checkpoint: we have a new binding. Provide the
+ auditing libraries the possibility to change the value and
+ tell us whether further auditing is wanted. */
+ if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+ {
+ const char *strtab = (const char *) D_PTR (result,
+ l_info[DT_STRTAB]);
+ /* Compute index of the symbol entry in the symbol table of
+ the DSO with the definition. */
+ unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result,
+ l_info[DT_SYMTAB]));
+
+ if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0)
+ {
+ unsigned int altvalue = 0;
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ /* Synthesize a symbol record where the st_value field is
+ the result. */
+ ElfW(Sym) sym = *ref;
+ sym.st_value = (ElfW(Addr)) value;
+
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->symbind != NULL
+ && ((match->l_audit[cnt].bindflags & LA_FLG_BINDFROM)
+ != 0
+ || ((result->l_audit[cnt].bindflags & LA_FLG_BINDTO)
+ != 0)))
+ {
+ unsigned int flags = altvalue | LA_SYMB_DLSYM;
+ uintptr_t new_value
+ = afct->symbind (&sym, ndx,
+ &match->l_audit[cnt].cookie,
+ &result->l_audit[cnt].cookie,
+ &flags, strtab + ref->st_name);
+ if (new_value != (uintptr_t) sym.st_value)
+ {
+ altvalue = LA_SYMB_ALTVALUE;
+ sym.st_value = new_value;
+ }
+ }
+
+ afct = afct->next;
+ }
+
+ value = (void *) sym.st_value;
+ }
+ }
#endif
- return DL_SYMBOL_ADDRESS (result, ref);
+ return value;
}
return NULL;
diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
index f9559dc59c..5118144174 100644
--- a/elf/dynamic-link.h
+++ b/elf/dynamic-link.h
@@ -20,7 +20,7 @@
#include <elf.h>
#include <assert.h>
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
/* We pass reloc_addr as a pointer to void, as opposed to a pointer to
ElfW(Addr), because not all architectures can assume that the
relocated address is properly aligned, whereas the compiler is
@@ -64,7 +64,7 @@ elf_machine_lazy_rel (struct link_map *map,
/* Read the dynamic section at DYN and fill in INFO with indices DT_*. */
-#ifndef RESOLVE
+#ifndef RESOLVE_MAP
static
#else
auto
@@ -199,7 +199,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
#endif
}
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
# ifdef RTLD_BOOTSTRAP
# define ELF_DURING_STARTUP (1)
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
index f8504fb95e..70f3a8f402 100644
--- a/elf/ldconfig.c
+++ b/elf/ldconfig.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Jaeger <aj@suse.de>, 1999.
@@ -279,7 +279,7 @@ print_version (FILE *stream, struct argp_state *state)
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
+"), "2005");
fprintf (stream, gettext ("Written by %s.\n"),
"Andreas Jaeger");
}
diff --git a/elf/ldd.bash.in b/elf/ldd.bash.in
index 4d7c33c728..4587efd1cb 100644
--- a/elf/ldd.bash.in
+++ b/elf/ldd.bash.in
@@ -1,5 +1,5 @@
#! @BASH@
-# Copyright (C) 1996-2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+# Copyright (C) 1996-2004, 2005 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
@@ -39,7 +39,7 @@ while test $# -gt 0; do
printf $"Copyright (C) %s Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-" "2004"
+" "2005"
printf $"Written by %s and %s.
" "Roland McGrath" "Ulrich Drepper"
exit 0
diff --git a/elf/link.h b/elf/link.h
index 6d5ad9d98c..fdda019cbe 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -1,6 +1,6 @@
/* Data structure for communication from the run-time dynamic linker for
loaded ELF shared objects.
- Copyright (C) 1995-1999, 2000, 2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1995-2001, 2004, 2005 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
@@ -33,6 +33,7 @@
#define _ElfW_1(e,w,t) e##w##t
#include <bits/elfclass.h> /* Defines __ELF_NATIVE_CLASS. */
+#include <bits/link.h>
/* Rendezvous structure used by the run-time dynamic linker to communicate
details of shared object loading to the debugger. If the executable's
@@ -94,6 +95,47 @@ struct link_map
#ifdef __USE_GNU
+/* Version numbers for la_version handshake interface. */
+#define LAV_CURRENT 1
+
+/* Activity types signaled through la_activity. */
+enum
+ {
+ LA_ACT_CONSISTENT, /* Link map consistent again. */
+ LA_ACT_ADD, /* New object will be added. */
+ LA_ACT_DELETE /* Objects will be removed. */
+ };
+
+/* Values representing origin of name for dynamic loading. */
+enum
+ {
+ LA_SER_ORIG = 0x01, /* Original name. */
+ LA_SER_LIBPATH = 0x02, /* Directory from LD_LIBRARY_PATH. */
+ LA_SER_RUNPATH = 0x04, /* Directory from RPATH/RUNPATH. */
+ LA_SER_CONFIG = 0x08, /* Found through ldconfig. */
+ LA_SER_DEFAULT = 0x40, /* Default directory. */
+ LA_SER_SECURE = 0x80 /* Unused. */
+ };
+
+/* Values for la_objopen return value. */
+enum
+ {
+ LA_FLG_BINDTO = 0x01, /* Audit symbols bound to this object. */
+ LA_FLG_BINDFROM = 0x02 /* Audit symbols bound from this object. */
+ };
+
+/* Values for la_symbind flags parameter. */
+enum
+ {
+ LA_SYMB_NOPLTENTER = 0x01, /* la_pltenter will not be called. */
+ LA_SYMB_NOPLTEXIT = 0x02, /* la_pltexit will not be called. */
+ LA_SYMB_STRUCTCALL = 0x04, /* Return value is a structure. */
+ LA_SYMB_DLSYM = 0x08, /* Binding due to dlsym call. */
+ LA_SYMB_ALTVALUE = 0x10 /* Value has been changed by a previous
+ la_symbind call. */
+ };
+
+
struct dl_phdr_info
{
ElfW(Addr) dlpi_addr;
@@ -114,9 +156,28 @@ struct dl_phdr_info
__BEGIN_DECLS
-extern int dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
- size_t size, void *data),
- void *data);
+extern int dl_iterate_phdr (int (*__callback) (struct dl_phdr_info *,
+ size_t, void *),
+ void *__data);
+
+
+/* Prototypes for the ld.so auditing interfaces. These are not
+ defined anywhere in ld.so but instead have to be provided by the
+ auditing DSO. */
+extern unsigned int la_version (unsigned int __version);
+extern void la_activity (uintptr_t *__cookie, unsigned int __flag);
+extern char *la_objsearch (const char *__name, uintptr_t *__cookie,
+ unsigned int __flag);
+extern unsigned int la_objopen (struct link_map *__map, Lmid_t __lmid,
+ uintptr_t *__cookie);
+extern void la_preinit (uintptr_t *__cookie);
+extern uintptr_t la_symbind32 (Elf32_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook, uintptr_t *__defcook,
+ unsigned int *__flags, const char *__symname);
+extern uintptr_t la_symbind64 (Elf64_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook, uintptr_t *__defcook,
+ unsigned int *__flags, const char *__symname);
+extern unsigned int la_objclose (uintptr_t *__cookie);
__END_DECLS
diff --git a/elf/rtld.c b/elf/rtld.c
index 3835a207ec..9fda5b8122 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -79,6 +79,13 @@ INTDEF(_dl_argv)
/* Nonzero if we were run directly. */
unsigned int _dl_skip_args attribute_relro attribute_hidden;
+/* List of auditing DSOs. */
+static struct audit_list
+{
+ const char *name;
+ struct audit_list *next;
+} *audit_list;
+
#ifndef HAVE_INLINED_SYSCALLS
/* Set nonzero during loading and initialization of executable and
libraries, cleared before the executable's entry point runs. This
@@ -126,25 +133,14 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
._dl_fpu_control = _FPU_DEFAULT,
/* Function pointers. */
- ._dl_get_origin = _dl_get_origin,
- ._dl_dst_count = _dl_dst_count,
- ._dl_dst_substitute = _dl_dst_substitute,
- ._dl_map_object = _dl_map_object,
- ._dl_map_object_deps = _dl_map_object_deps,
- ._dl_relocate_object = _dl_relocate_object,
- ._dl_check_map_versions = _dl_check_map_versions,
- ._dl_init = _dl_init,
- ._dl_debug_state = _dl_debug_state,
-#ifndef MAP_COPY
- ._dl_unload_cache = _dl_unload_cache,
-#endif
._dl_debug_printf = _dl_debug_printf,
._dl_catch_error = _dl_catch_error,
._dl_signal_error = _dl_signal_error,
- ._dl_start_profile = _dl_start_profile,
._dl_mcount = _dl_mcount_internal,
._dl_lookup_symbol_x = _dl_lookup_symbol_x,
- ._dl_check_caller = _dl_check_caller
+ ._dl_check_caller = _dl_check_caller,
+ ._dl_open = _dl_open,
+ ._dl_close = _dl_close
};
/* If we would use strong_alias here the compiler would see a
non-hidden definition. This would undo the effect of the previous
@@ -267,6 +263,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
memcpy (GL(dl_rtld_map).l_info, info->l.l_info,
sizeof GL(dl_rtld_map).l_info);
GL(dl_rtld_map).l_mach = info->l.l_mach;
+ GL(dl_rtld_map).l_relocated = 1;
#endif
_dl_setup_hash (&GL(dl_rtld_map));
GL(dl_rtld_map).l_real = &GL(dl_rtld_map);
@@ -348,8 +345,6 @@ _dl_start (void *arg)
#define RTLD_BOOTSTRAP
#define RESOLVE_MAP(sym, version, flags) \
((*(sym))->st_shndx == SHN_UNDEF ? 0 : &bootstrap_map)
-#define RESOLVE(sym, version, flags) \
- ((*(sym))->st_shndx == SHN_UNDEF ? 0 : bootstrap_map.l_addr)
#include "dynamic-link.h"
if (HP_TIMING_INLINE && HP_TIMING_AVAIL)
@@ -472,7 +467,7 @@ _dl_start (void *arg)
while (remaining-- > 0)
*p++ = '\0';
}
-#endif
+# endif
/* Install the pointer to the dtv. */
@@ -514,6 +509,7 @@ _dl_start (void *arg)
data access using the global offset table. */
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0);
+ bootstrap_map.l_relocated = 1;
}
/* Please note that we don't allow profiling of this object and
@@ -566,6 +562,19 @@ struct map_args
struct link_map *map;
};
+struct dlmopen_args
+{
+ const char *fname;
+ struct link_map *map;
+};
+
+struct lookup_args
+{
+ const char *name;
+ struct link_map *map;
+ void *result;
+};
+
/* Arguments to version_check_doit. */
struct version_check_args
{
@@ -591,6 +600,28 @@ map_doit (void *a)
}
static void
+dlmopen_doit (void *a)
+{
+ struct dlmopen_args *args = (struct dlmopen_args *) a;
+ args->map = _dl_open (args->fname, RTLD_LAZY | __RTLD_DLOPEN | __RTLD_AUDIT,
+ dl_main, LM_ID_NEWLM, _dl_argc, INTUSE(_dl_argv),
+ __environ);
+}
+
+static void
+lookup_doit (void *a)
+{
+ struct lookup_args *args = (struct lookup_args *) a;
+ const ElfW(Sym) *ref = NULL;
+ args->result = NULL;
+ lookup_t l = _dl_lookup_symbol_x (args->name, args->map, &ref,
+ args->map->l_local_scope, NULL, 0,
+ DL_LOOKUP_RETURN_NEWEST, NULL);
+ if (ref != NULL)
+ args->result = DL_SYMBOL_ADDRESS (l, ref);
+}
+
+static void
version_check_doit (void *a)
{
struct version_check_args *args = (struct version_check_args *) a;
@@ -648,6 +679,80 @@ match_version (const char *string, struct link_map *map)
return 0;
}
+#ifdef USE_TLS
+static bool tls_init_tp_called;
+
+static void *
+init_tls (void)
+{
+ /* Number of elements in the static TLS block. */
+ GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
+
+ /* Do not do this twice. The audit interface might have required
+ the DTV interfaces to be set up early. */
+ if (GL(dl_initial_dtv) != NULL)
+ return NULL;
+
+ /* Allocate the array which contains the information about the
+ dtv slots. We allocate a few entries more than needed to
+ avoid the need for reallocation. */
+ size_t nelem = GL(dl_tls_max_dtv_idx) + 1 + TLS_SLOTINFO_SURPLUS;
+
+ /* Allocate. */
+ GL(dl_tls_dtv_slotinfo_list) = (struct dtv_slotinfo_list *)
+ calloc (sizeof (struct dtv_slotinfo_list)
+ + nelem * sizeof (struct dtv_slotinfo), 1);
+ /* No need to check the return value. If memory allocation failed
+ the program would have been terminated. */
+
+ struct dtv_slotinfo *slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo;
+ GL(dl_tls_dtv_slotinfo_list)->len = nelem;
+ GL(dl_tls_dtv_slotinfo_list)->next = NULL;
+
+ /* Fill in the information from the loaded modules. No namespace
+ but the base one can be filled at this time. */
+ assert (GL(dl_ns)[LM_ID_BASE + 1]._ns_loaded == NULL);
+ int i = 0;
+ for (struct link_map *l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; l != NULL;
+ l = l->l_next)
+ if (l->l_tls_blocksize != 0)
+ {
+ /* This is a module with TLS data. Store the map reference.
+ The generation counter is zero. */
+ slotinfo[i].map = l;
+ /* slotinfo[i].gen = 0; */
+ ++i;
+ }
+ assert (i == GL(dl_tls_max_dtv_idx));
+
+ /* Compute the TLS offsets for the various blocks. */
+ _dl_determine_tlsoffset ();
+
+ /* Construct the static TLS block and the dtv for the initial
+ thread. For some platforms this will include allocating memory
+ for the thread descriptor. The memory for the TLS block will
+ never be freed. It should be allocated accordingly. The dtv
+ array can be changed if dynamic loading requires it. */
+ void *tcbp = _dl_allocate_tls_storage ();
+ if (tcbp == NULL)
+ _dl_fatal_printf ("\
+cannot allocate TLS data structures for initial thread");
+
+ /* Store for detection of the special case by __tls_get_addr
+ so it knows not to pass this dtv to the normal realloc. */
+ GL(dl_initial_dtv) = GET_DTV (tcbp);
+
+ /* And finally install it for the main thread. If ld.so itself uses
+ TLS we know the thread pointer was initialized earlier. */
+ const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD);
+ if (__builtin_expect (lossage != NULL, 0))
+ _dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage);
+ tls_init_tp_called = true;
+
+ return tcbp;
+}
+#endif
+
#ifdef _LIBC_REENTRANT
/* _dl_error_catch_tsd points to this for the single-threaded case.
It's reset by the thread library for multithreaded programs. */
@@ -702,7 +807,7 @@ dl_main (const ElfW(Phdr) *phdr,
hp_timing_t diff;
#endif
#ifdef USE_TLS
- void *tcbp;
+ void *tcbp = NULL;
#endif
#ifdef _LIBC_REENTRANT
@@ -826,6 +931,7 @@ of this helper program; chances are you did not intend to run this program.\n\
objects. */
_dl_init_paths (library_path);
+
/* The initialization of _dl_stack_flags done below assumes the
executable's PT_GNU_STACK may have been honored by the kernel, and
so a PT_GNU_STACK with PF_X set means the stack started out with
@@ -887,10 +993,10 @@ of this helper program; chances are you did not intend to run this program.\n\
{
/* Create a link_map for the executable itself.
This will be what dlopen on "" returns. */
- _dl_new_object ((char *) "", "", lt_executable, NULL, 0, LM_ID_BASE);
- main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
- if (main_map == NULL)
- _dl_fatal_printf ("cannot allocate memory for link map\n");
+ main_map = _dl_new_object ((char *) "", "", lt_executable, NULL,
+ __RTLD_OPENEXEC, LM_ID_BASE);
+ assert (main_map != NULL);
+ assert (main_map == GL(dl_ns)[LM_ID_BASE]._ns_loaded);
main_map->l_phdr = phdr;
main_map->l_phnum = phnum;
main_map->l_entry = *user_entry;
@@ -991,8 +1097,9 @@ of this helper program; chances are you did not intend to run this program.\n\
main_map->l_text_end = allocend;
}
break;
-#ifdef USE_TLS
+
case PT_TLS:
+#ifdef USE_TLS
if (ph->p_memsz > 0)
{
/* Note that in the case the dynamic linker we duplicate work
@@ -1012,8 +1119,12 @@ of this helper program; chances are you did not intend to run this program.\n\
/* This image gets the ID one. */
GL(dl_tls_max_dtv_idx) = main_map->l_tls_modid = 1;
}
- break;
+#else
+ _dl_fatal_printf ("\
+ld.so does not support TLS, but program uses it!\n");
#endif
+ break;
+
case PT_GNU_STACK:
GL(dl_stack_flags) = ph->p_flags;
break;
@@ -1045,6 +1156,26 @@ of this helper program; chances are you did not intend to run this program.\n\
else
assert (GL(dl_rtld_map).l_libname); /* How else did we get here? */
+ /* If the current libname is different from the SONAME, add the
+ latter as well. */
+ if (GL(dl_rtld_map).l_info[DT_SONAME] != NULL
+ && strcmp (GL(dl_rtld_map).l_libname->name,
+ (const char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB])
+ + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_val) != 0)
+ {
+ static struct libname_list newname;
+ newname.name = ((char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB])
+ + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_ptr);
+ newname.next = NULL;
+ newname.dont_free = 1;
+
+ assert (GL(dl_rtld_map).l_libname->next == NULL);
+ GL(dl_rtld_map).l_libname->next = &newname;
+ }
+ /* The ld.so must be relocated since otherwise loading audit modules
+ will fail since they reuse the very same ld.so. */
+ assert (GL(dl_rtld_map).l_relocated);
+
if (! rtld_is_main)
{
/* Extract the contents of the dynamic section for easy access. */
@@ -1074,6 +1205,11 @@ of this helper program; chances are you did not intend to run this program.\n\
objects. */
_dl_init_paths (library_path);
+ /* Initialize _r_debug. */
+ struct r_debug *r = _dl_debug_initialize (GL(dl_rtld_map).l_addr,
+ LM_ID_BASE);
+ r->r_state = RT_CONSISTENT;
+
/* Put the link_map for ourselves on the chain so it can be found by
name. Note that at this point the global chain of link maps contains
exactly one element, which is pointed to by dl_loaded. */
@@ -1148,6 +1284,7 @@ of this helper program; chances are you did not intend to run this program.\n\
GL(dl_rtld_map).l_phdr = rtld_phdr;
GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum;
+
/* PT_GNU_RELRO is usually the last phdr. */
size_t cnt = rtld_ehdr->e_phnum;
while (cnt-- > 0)
@@ -1158,6 +1295,204 @@ of this helper program; chances are you did not intend to run this program.\n\
break;
}
+#ifdef USE_TLS
+ /* Add the dynamic linker to the TLS list if it also uses TLS. */
+ if (GL(dl_rtld_map).l_tls_blocksize != 0)
+ /* Assign a module ID. Do this before loading any audit modules. */
+ GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
+#endif
+
+ /* If we have auditing DSOs to load, do it now. */
+ if (__builtin_expect (audit_list != NULL, 0))
+ {
+ /* Iterate over all entries in the list. The order is important. */
+ struct audit_ifaces *last_audit = NULL;
+ struct audit_list *al = audit_list->next;
+ do
+ {
+#ifdef USE_TLS
+ int tls_idx = GL(dl_tls_max_dtv_idx);
+
+ /* Now it is time to determine the layout of the static TLS
+ block and allocate it for the initial thread. Note that we
+ always allocate the static block, we never defer it even if
+ no DF_STATIC_TLS bit is set. The reason is that we know
+ glibc will use the static model. */
+# ifndef TLS_INIT_TP_EXPENSIVE
+# define TLS_INIT_TP_EXPENSIVE 0
+# endif
+
+ /* Since we start using the auditing DSOs right away we need to
+ initialize the data structures now. */
+ if (!TLS_INIT_TP_EXPENSIVE)
+ tcbp = init_tls ();
+#endif
+ struct dlmopen_args dlmargs;
+ dlmargs.fname = al->name;
+ dlmargs.map = NULL;
+
+ const char *objname;
+ const char *err_str = NULL;
+ (void) _dl_catch_error (&objname, &err_str, dlmopen_doit, &dlmargs);
+ if (__builtin_expect (err_str != NULL, 0))
+ {
+ not_loaded:
+ _dl_error_printf ("\
+ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
+ al->name, err_str);
+ free ((char *) err_str);
+ }
+ else
+ {
+ struct lookup_args largs;
+ largs.name = "la_version";
+ largs.map = dlmargs.map;
+
+ /* Check whether the interface version matches. */
+ (void) _dl_catch_error (&objname, &err_str, lookup_doit, &largs);
+
+ unsigned int (*laversion) (unsigned int);
+ unsigned int lav;
+ if (err_str == NULL
+ && (laversion = largs.result) != NULL
+ && (lav = laversion (LAV_CURRENT)) > 0
+ && lav <= LAV_CURRENT)
+ {
+ /* Allocate structure for the callback function pointers.
+ This call can never fail. */
+ union
+ {
+ struct audit_ifaces ifaces;
+#define naudit_ifaces 8
+ void (*fptr[naudit_ifaces]) (void);
+ } *newp = malloc (sizeof (*newp));
+
+ /* Names of the auditing interfaces. All in one
+ long string. */
+ static const char audit_iface_names[] =
+ "la_activity\0"
+ "la_objsearch\0"
+ "la_objopen\0"
+ "la_preinit\0"
+#if __ELF_NATIVE_CLASS == 32
+ "la_symbind32\0"
+#elif __ELF_NATIVE_CLASS == 64
+ "la_symbind64\0"
+#else
+# error "__ELF_NATIVE_CLASS must be defined"
+#endif
+#define STRING(s) __STRING (s)
+ "la_" STRING (ARCH_LA_PLTENTER) "\0"
+ "la_" STRING (ARCH_LA_PLTEXIT) "\0"
+ "la_objclose\0";
+ unsigned int cnt = 0;
+ const char *cp = audit_iface_names;
+ do
+ {
+ largs.name = cp;
+ (void) _dl_catch_error (&objname, &err_str, lookup_doit,
+ &largs);
+
+ /* Store the pointer. */
+ if (err_str == NULL && largs.result != NULL)
+ {
+ newp->fptr[cnt] = largs.result;
+
+ /* The dynamic linker link map is statically
+ allocated, initialize the data now. */
+ GL(dl_rtld_map).l_audit[cnt].cookie
+ = (intptr_t) &GL(dl_rtld_map);
+ }
+ else
+ newp->fptr[cnt] = NULL;
+ ++cnt;
+
+ cp = (char *) rawmemchr (cp, '\0') + 1;
+ }
+ while (*cp != '\0');
+ assert (cnt == naudit_ifaces);
+
+ /* Now append the new auditing interface to the list. */
+ newp->ifaces.next = NULL;
+ if (last_audit == NULL)
+ last_audit = GLRO(dl_audit) = &newp->ifaces;
+ else
+ last_audit = last_audit->next = &newp->ifaces;
+ ++GLRO(dl_naudit);
+
+ /* Mark the DSO as being used for auditing. */
+ dlmargs.map->l_auditing = 1;
+ }
+ else
+ {
+ /* We cannot use the DSO, it does not have the
+ appropriate interfaces or it expects something
+ more recent. */
+#ifndef NDEBUG
+ Lmid_t ns = dlmargs.map->l_ns;
+#endif
+ _dl_close (dlmargs.map);
+
+ /* Make sure the namespace has been cleared entirely. */
+ assert (GL(dl_ns)[ns]._ns_loaded == NULL);
+ assert (GL(dl_ns)[ns]._ns_nloaded == 0);
+
+#ifdef USE_TLS
+ GL(dl_tls_max_dtv_idx) = tls_idx;
+#endif
+ goto not_loaded;
+ }
+ }
+
+ al = al->next;
+ }
+ while (al != audit_list->next);
+
+ /* If we have any auditing modules, announce that we already
+ have two objects loaded. */
+ if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+ {
+ struct link_map *ls[2] = { main_map, &GL(dl_rtld_map) };
+
+ for (unsigned int outer = 0; outer < 2; ++outer)
+ {
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->objopen != NULL)
+ {
+ ls[outer]->l_audit[cnt].bindflags
+ = afct->objopen (ls[outer], LM_ID_BASE,
+ &ls[outer]->l_audit[cnt].cookie);
+
+ ls[outer]->l_audit_any_plt
+ |= ls[outer]->l_audit[cnt].bindflags != 0;
+ }
+
+ afct = afct->next;
+ }
+ }
+ }
+ }
+
+ /* We start adding objects. */
+ r->r_state = RT_ADD;
+ _dl_debug_state ();
+
+ /* Auditing checkpoint: we are ready to signal that the initial map
+ is being constructed. */
+ if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+ {
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->activity != NULL)
+ afct->activity (&main_map->l_audit[cnt].cookie, LA_ACT_ADD);
+
+ afct = afct->next;
+ }
+ }
+
/* We have two ways to specify objects to preload: via environment
variable and via the file /etc/ld.so.preload. The latter can also
be used when security is enabled. */
@@ -1418,6 +1753,9 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
&& ph->p_vaddr + ph->p_memsz >= l->l_text_end)
l->l_text_end = ph->p_vaddr + ph->p_memsz;
}
+ else
+ /* There must be no TLS segment. */
+ assert (ph->p_type != PT_TLS);
}
l->l_map_start = (ElfW(Addr)) GLRO(dl_sysinfo_dso);
l->l_addr = l->l_map_start - l->l_addr;
@@ -1533,20 +1871,6 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
}
#ifdef USE_TLS
- /* Now it is time to determine the layout of the static TLS block
- and allocate it for the initial thread. Note that we always
- allocate the static block, we never defer it even if no
- DF_STATIC_TLS bit is set. The reason is that we know glibc will
- use the static model. First add the dynamic linker to the list
- if it also uses TLS. */
- if (GL(dl_rtld_map).l_tls_blocksize != 0)
- /* Assign a module ID. */
- GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
-
-# ifndef TLS_INIT_TP_EXPENSIVE
-# define TLS_INIT_TP_EXPENSIVE 0
-# endif
-
/* We do not initialize any of the TLS functionality unless any of the
initial modules uses TLS. This makes dynamic loading of modules with
TLS impossible, but to support it requires either eagerly doing setup
@@ -1554,57 +1878,9 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever
used. Trying to do it lazily is too hairy to try when there could be
multiple threads (from a non-TLS-using libpthread). */
- if (!TLS_INIT_TP_EXPENSIVE || GL(dl_tls_max_dtv_idx) > 0)
- {
- struct link_map *l;
- size_t nelem;
- struct dtv_slotinfo *slotinfo;
-
- /* Number of elements in the static TLS block. */
- GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
-
- /* Allocate the array which contains the information about the
- dtv slots. We allocate a few entries more than needed to
- avoid the need for reallocation. */
- nelem = GL(dl_tls_max_dtv_idx) + 1 + TLS_SLOTINFO_SURPLUS;
-
- /* Allocate. */
- GL(dl_tls_dtv_slotinfo_list) = (struct dtv_slotinfo_list *)
- malloc (sizeof (struct dtv_slotinfo_list)
- + nelem * sizeof (struct dtv_slotinfo));
- /* No need to check the return value. If memory allocation failed
- the program would have been terminated. */
-
- slotinfo = memset (GL(dl_tls_dtv_slotinfo_list)->slotinfo, '\0',
- nelem * sizeof (struct dtv_slotinfo));
- GL(dl_tls_dtv_slotinfo_list)->len = nelem;
- GL(dl_tls_dtv_slotinfo_list)->next = NULL;
-
- /* Fill in the information from the loaded modules. */
- for (l = main_map, i = 0; l != NULL; l = l->l_next)
- if (l->l_tls_blocksize != 0)
- /* This is a module with TLS data. Store the map reference.
- The generation counter is zero. */
- slotinfo[++i].map = l;
- assert (i == GL(dl_tls_max_dtv_idx));
-
- /* Compute the TLS offsets for the various blocks. */
- _dl_determine_tlsoffset ();
-
- /* Construct the static TLS block and the dtv for the initial
- thread. For some platforms this will include allocating memory
- for the thread descriptor. The memory for the TLS block will
- never be freed. It should be allocated accordingly. The dtv
- array can be changed if dynamic loading requires it. */
- tcbp = _dl_allocate_tls_storage ();
- if (tcbp == NULL)
- _dl_fatal_printf ("\
-cannot allocate TLS data structures for initial thread");
-
- /* Store for detection of the special case by __tls_get_addr
- so it knows not to pass this dtv to the normal realloc. */
- GL(dl_initial_dtv) = GET_DTV (tcbp);
- }
+ bool was_tls_init_tp_called = tls_init_tp_called;
+ if (tcbp == NULL && (!TLS_INIT_TP_EXPENSIVE || GL(dl_tls_max_dtv_idx) > 0))
+ tcbp = init_tls ();
#endif
if (__builtin_expect (mode, normal) != normal)
@@ -1885,8 +2161,6 @@ cannot allocate TLS data structures for initial thread");
}
- /* Initialize _r_debug. */
- struct r_debug *r = _dl_debug_initialize (GL(dl_rtld_map).l_addr);
{
struct link_map *l = main_map;
@@ -1921,8 +2195,6 @@ cannot allocate TLS data structures for initial thread");
if (prelinked)
{
- struct link_map *l;
-
if (main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL)
{
ElfW(Rela) *conflict, *conflictend;
@@ -1945,11 +2217,17 @@ cannot allocate TLS data structures for initial thread");
/* Mark all the objects so we know they have been already relocated. */
- for (l = main_map; l != NULL; l = l->l_next)
+ for (struct link_map *l = main_map; l != NULL; l = l->l_next)
{
l->l_relocated = 1;
if (l->l_relro_size)
_dl_protect_relro (l);
+
+#ifdef USE_TLS
+ /* Add object to slot information data if necessasy. */
+ if (l->l_tls_blocksize != 0 && tls_init_tp_called)
+ _dl_add_to_slotinfo (l);
+#endif
}
_dl_sysdep_start_cleanup ();
@@ -1965,7 +2243,6 @@ cannot allocate TLS data structures for initial thread");
the dynamic linker out of order because it has no copy relocs (we
know that because it is self-contained). */
- struct link_map *l;
int consider_profiling = GLRO(dl_profile) != NULL;
#ifndef HP_TIMING_NONAVAIL
hp_timing_t start;
@@ -1976,7 +2253,7 @@ cannot allocate TLS data structures for initial thread");
/* If we are profiling we also must do lazy reloaction. */
GLRO(dl_lazy) |= consider_profiling;
- l = main_map;
+ struct link_map *l = main_map;
while (l->l_next)
l = l->l_next;
@@ -1998,6 +2275,12 @@ cannot allocate TLS data structures for initial thread");
_dl_relocate_object (l, l->l_scope, GLRO(dl_lazy),
consider_profiling);
+#ifdef USE_TLS
+ /* Add object to slot information data if necessasy. */
+ if (l->l_tls_blocksize != 0 && tls_init_tp_called)
+ _dl_add_to_slotinfo (l);
+#endif
+
l = l->l_prev;
}
while (l);
@@ -2025,6 +2308,8 @@ cannot allocate TLS data structures for initial thread");
/* There was an explicit ref to the dynamic linker as a shared lib.
Re-relocate ourselves with user-controlled symbol definitions. */
HP_TIMING_NOW (start);
+ /* Mark the link map as not yet relocated again. */
+ GL(dl_rtld_map).l_relocated = 0;
_dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0);
HP_TIMING_NOW (stop);
HP_TIMING_DIFF (add, start, stop);
@@ -2039,6 +2324,9 @@ cannot allocate TLS data structures for initial thread");
#ifdef USE_TLS
if (GL(dl_tls_max_dtv_idx) > 0 || USE___THREAD || !TLS_INIT_TP_EXPENSIVE)
{
+ if (!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0)
+ ++GL(dl_tls_generation);
+
/* Now that we have completed relocation, the initializer data
for the TLS blocks has its final values and we can copy them
into the main thread's TLS area, which we allocated above. */
@@ -2046,16 +2334,42 @@ cannot allocate TLS data structures for initial thread");
/* And finally install it for the main thread. If ld.so itself uses
TLS we know the thread pointer was initialized earlier. */
- const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD);
- if (__builtin_expect (lossage != NULL, 0))
- _dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage);
+ if (! tls_init_tp_called)
+ {
+ const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD);
+ if (__builtin_expect (lossage != NULL, 0))
+ _dl_fatal_printf ("cannot set up thread-local storage: %s\n",
+ lossage);
+ }
}
else
#endif
NONTLS_INIT_TP;
- /* Notify the debugger that all objects are now mapped in. */
- r->r_state = RT_ADD;
+#ifdef SHARED
+ /* Auditing checkpoint: we have added all objects. */
+ if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+ {
+ struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+ /* Do not call the functions for any auditing object. */
+ if (head->l_auditing == 0)
+ {
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->activity != NULL)
+ afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT);
+
+ afct = afct->next;
+ }
+ }
+ }
+#endif
+
+ /* Notify the debugger all new objects are now ready to go. We must re-get
+ the address since by now the variable might be in another object. */
+ r = _dl_debug_initialize (0, LM_ID_BASE);
+ r->r_state = RT_CONSISTENT;
_dl_debug_state ();
#ifndef MAP_COPY
@@ -2187,6 +2501,32 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n");
}
}
+static void
+process_dl_audit (char *str)
+{
+ /* The parameter is a colon separated list of DSO names. */
+ char *p;
+
+ while ((p = (strsep) (&str, ":")) != NULL)
+ if (p[0] != '\0'
+ && (__builtin_expect (! INTUSE(__libc_enable_secure), 1)
+ || strchr (p, '/') == NULL))
+ {
+ /* This is using the local malloc, not the system malloc. The
+ memory can never be freed. */
+ struct audit_list *newp = malloc (sizeof (*newp));
+ newp->name = p;
+
+ if (audit_list == NULL)
+ audit_list = newp->next = newp;
+ else
+ {
+ newp->next = audit_list->next;
+ audit_list = audit_list->next = newp;
+ }
+ }
+}
+
/* Process all environments variables the dynamic linker must recognize.
Since all of them start with `LD_' we are a bit smarter while finding
all the entries. */
@@ -2229,7 +2569,12 @@ process_envvars (enum mode *modep)
case 5:
/* Debugging of the dynamic linker? */
if (memcmp (envline, "DEBUG", 5) == 0)
- process_dl_debug (&envline[6]);
+ {
+ process_dl_debug (&envline[6]);
+ break;
+ }
+ if (memcmp (envline, "AUDIT", 5) == 0)
+ process_dl_audit (&envline[6]);
break;
case 7:
diff --git a/elf/sprof.c b/elf/sprof.c
index afe3955ad8..9567e4689f 100644
--- a/elf/sprof.c
+++ b/elf/sprof.c
@@ -1,5 +1,5 @@
/* Read and display shared object profiling data.
- Copyright (C) 1997-2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1997-2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -357,7 +357,7 @@ Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
"),
- "2004");
+ "2005");
fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
}
diff --git a/elf/tst-align2.c b/elf/tst-align2.c
new file mode 100644
index 0000000000..4fc0330e39
--- /dev/null
+++ b/elf/tst-align2.c
@@ -0,0 +1,157 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2005.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <tst-stack-align.h>
+#include <unistd.h>
+
+static int res, fds[2], result;
+static bool test_destructors;
+
+extern void in_dso (int *, bool *, int *);
+
+static void __attribute__ ((constructor)) con (void)
+{
+ res = TEST_STACK_ALIGN () ? -1 : 1;
+}
+
+static void __attribute__ ((destructor)) des (void)
+{
+ if (!test_destructors)
+ return;
+
+ char c = TEST_STACK_ALIGN () ? 'B' : 'A';
+ write (fds[1], &c, 1);
+}
+
+static int
+do_test (void)
+{
+ if (!res)
+ {
+ puts ("binary's constructor has not been run");
+ result = 1;
+ }
+ else if (res != 1)
+ {
+ puts ("binary's constructor has been run without sufficient alignment");
+ result = 1;
+ }
+
+ if (TEST_STACK_ALIGN ())
+ {
+ puts ("insufficient stack alignment in do_test");
+ result = 1;
+ }
+
+ in_dso (&result, &test_destructors, &fds[1]);
+
+ if (pipe (fds) < 0)
+ {
+ printf ("couldn't create pipe: %m\n");
+ return 1;
+ }
+
+ pid_t pid = fork ();
+ if (pid < 0)
+ {
+ printf ("fork failed: %m\n");
+ return 1;
+ }
+
+ if (!pid)
+ {
+ close (fds[0]);
+ test_destructors = true;
+ exit (0);
+ }
+
+ close (fds[1]);
+
+ unsigned char c;
+ ssize_t len;
+ int des_seen = 0, dso_des_seen = 0;
+ while ((len = TEMP_FAILURE_RETRY (read (fds[0], &c, 1))) > 0)
+ {
+ switch (c)
+ {
+ case 'B':
+ puts ("insufficient alignment in binary's destructor");
+ result = 1;
+ /* FALLTHROUGH */
+ case 'A':
+ des_seen++;
+ break;
+ case 'D':
+ puts ("insufficient alignment in DSO destructor");
+ result = 1;
+ /* FALLTHROUGH */
+ case 'C':
+ dso_des_seen++;
+ break;
+ default:
+ printf ("unexpected character %x read from pipe", c);
+ result = 1;
+ break;
+ }
+ }
+
+ close (fds[0]);
+
+ if (des_seen != 1)
+ {
+ printf ("binary destructor run %d times instead of once\n", des_seen);
+ result = 1;
+ }
+
+ if (dso_des_seen != 1)
+ {
+ printf ("DSO destructor run %d times instead of once\n", dso_des_seen);
+ result = 1;
+ }
+
+ int status;
+ pid_t termpid;
+ termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
+ if (termpid == -1)
+ {
+ printf ("waitpid failed: %m\n");
+ result = 1;
+ }
+ else if (termpid != pid)
+ {
+ printf ("waitpid returned %ld != %ld\n",
+ (long int) termpid, (long int) pid);
+ result = 1;
+ }
+ else if (!WIFEXITED (status) || WEXITSTATUS (status))
+ {
+ puts ("child hasn't exited with exit status 0");
+ result = 1;
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-alignmod2.c b/elf/tst-alignmod2.c
new file mode 100644
index 0000000000..21dcc535c0
--- /dev/null
+++ b/elf/tst-alignmod2.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <tst-stack-align.h>
+#include <unistd.h>
+
+static int res, *fdp;
+static bool *test_destructorsp;
+
+static void __attribute__((constructor))
+con (void)
+{
+ res = TEST_STACK_ALIGN () ? -1 : 1;
+}
+
+void
+in_dso (int *result, bool *test_destructors, int *fd)
+{
+ if (!res)
+ {
+ puts ("constructor has not been run");
+ *result = 1;
+ }
+ else if (res != 1)
+ {
+ puts ("constructor has been run without sufficient alignment");
+ *result = 1;
+ }
+
+ test_destructorsp = test_destructors;
+ fdp = fd;
+}
+
+static void __attribute__((destructor))
+des (void)
+{
+ if (!test_destructorsp || !*test_destructorsp)
+ return;
+
+ char c = TEST_STACK_ALIGN () ? 'D' : 'C';
+ write (*fdp, &c, 1);
+}
diff --git a/elf/tst-audit1.c b/elf/tst-audit1.c
new file mode 100644
index 0000000000..63656b4ee9
--- /dev/null
+++ b/elf/tst-audit1.c
@@ -0,0 +1 @@
+#include "../io/pwd.c"
diff --git a/elf/tst-auditmod1.c b/elf/tst-auditmod1.c
new file mode 100644
index 0000000000..9b07588288
--- /dev/null
+++ b/elf/tst-auditmod1.c
@@ -0,0 +1,190 @@
+#include <dlfcn.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <bits/wordsize.h>
+#include <gnu/lib-names.h>
+
+
+unsigned int
+la_version (unsigned int v)
+{
+ setlinebuf (stdout);
+
+ printf ("version: %u\n", v);
+
+ char buf[20];
+ sprintf (buf, "%u", v);
+
+ return v;
+}
+
+void
+la_activity (uintptr_t *cookie, unsigned int flag)
+{
+ if (flag == LA_ACT_CONSISTENT)
+ printf ("activity: consistent\n");
+ else if (flag == LA_ACT_ADD)
+ printf ("activity: add\n");
+ else if (flag == LA_ACT_DELETE)
+ printf ("activity: delete\n");
+ else
+ printf ("activity: unknown activity %u\n", flag);
+}
+
+char *
+la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag)
+{
+ char buf[100];
+ const char *flagstr;
+ if (flag == LA_SER_ORIG)
+ flagstr = "LA_SET_ORIG";
+ else if (flag == LA_SER_LIBPATH)
+ flagstr = "LA_SER_LIBPATH";
+ else if (flag == LA_SER_RUNPATH)
+ flagstr = "LA_SER_RUNPATH";
+ else if (flag == LA_SER_CONFIG)
+ flagstr = "LA_SER_CONFIG";
+ else if (flag == LA_SER_DEFAULT)
+ flagstr = "LA_SER_DEFAULT";
+ else if (flag == LA_SER_SECURE)
+ flagstr = "LA_SER_SECURE";
+ else
+ {
+ sprintf (buf, "unknown flag %d", flag);
+ flagstr = buf;
+ }
+ printf ("objsearch: %s, %s\n", name, flagstr);
+
+ return (char *) name;
+}
+
+unsigned int
+la_objopen (struct link_map *l, Lmid_t lmid, uintptr_t *cookie)
+{
+ printf ("objopen: %ld, %s\n", lmid, l->l_name);
+
+ return 3;
+}
+
+void
+la_preinit (uintptr_t *cookie)
+{
+ printf ("preinit\n");
+}
+
+unsigned int
+la_objclose (uintptr_t *cookie)
+{
+ printf ("objclose\n");
+ return 0;
+}
+
+uintptr_t
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, unsigned int *flags, const char *symname)
+{
+ printf ("symbind32: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
+ symname, (long int) sym->st_value, ndx, *flags);
+
+ return sym->st_value;
+}
+
+uintptr_t
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, unsigned int *flags, const char *symname)
+{
+ printf ("symbind64: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
+ symname, (long int) sym->st_value, ndx, *flags);
+
+ return sym->st_value;
+}
+
+#ifdef __i386__
+# define pltenter la_i86_gnu_pltenter
+# define pltexit la_i86_gnu_pltexit
+# define La_regs La_i86_regs
+# define La_retval La_i86_retval
+# define int_retval lrv_eax
+#elif defined __x86_64__
+# define pltenter la_x86_64_gnu_pltenter
+# define pltexit la_x86_64_gnu_pltexit
+# define La_regs La_x86_64_regs
+# define La_retval La_x86_64_retval
+# define int_retval lrv_rax
+#elif defined __powerpc__ && __WORDSIZE == 32
+# define pltenter la_ppc32_gnu_pltenter
+# define pltexit la_ppc32_gnu_pltexit
+# define La_regs La_ppc32_regs
+# define La_retval La_ppc32_retval
+# define int_retval lrv_r3
+#elif defined __powerpc__ && __WORDSIZE == 64
+# define pltenter la_ppc64_gnu_pltenter
+# define pltexit la_ppc64_gnu_pltexit
+# define La_regs La_ppc64_regs
+# define La_retval La_ppc64_retval
+# define int_retval lrv_r3
+#elif defined __sh__
+# define pltenter la_sh_gnu_pltenter
+# define pltexit la_sh_gnu_pltexit
+# define La_regs La_sh_regs
+# define La_retval La_sh_retval
+# define int_retval lrv_r0
+#elif defined __mc68000__
+# define pltenter la_m68k_gnu_pltenter
+# define pltexit la_m68k_gnu_pltexit
+# define La_regs La_m68k_regs
+# define La_retval La_m68k_retval
+# define int_retval lrv_d0
+#elif defined __alpha__
+# define pltenter la_alpha_gnu_pltenter
+# define pltexit la_alpha_gnu_pltexit
+# define La_regs La_alpha_regs
+# define La_retval La_alpha_retval
+# define int_retval lrv_r0
+#elif defined __s390__ && __WORDSIZE == 32
+# define pltenter la_s390_32_gnu_pltenter
+# define pltexit la_s390_32_gnu_pltexit
+# define La_regs La_s390_32_regs
+# define La_retval La_s390_32_retval
+# define int_retval lrv_r2
+#elif defined __s390__ && __WORDSIZE == 64
+# define pltenter la_s390_64_gnu_pltenter
+# define pltexit la_s390_64_gnu_pltexit
+# define La_regs La_s390_64_regs
+# define La_retval La_s390_64_retval
+# define int_retval lrv_r2
+#elif defined __ia64__
+# define pltenter la_ia64_gnu_pltenter
+# define pltexit la_ia64_gnu_pltexit
+# define La_regs La_ia64_regs
+# define La_retval La_ia64_retval
+# define int_retval lrv_r8
+#else
+# error "architecture specific code needed"
+#endif
+
+
+ElfW(Addr)
+pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, La_regs *regs, unsigned int *flags,
+ const char *symname, long int *framesizep)
+{
+ printf ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
+ symname, (long int) sym->st_value, ndx, *flags);
+
+ return sym->st_value;
+}
+
+unsigned int
+pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, const La_regs *inregs, La_retval *outregs,
+ const char *symname)
+{
+ printf ("pltexit: symname=%s, st_value=%#lx, ndx=%u, retval=%tu\n",
+ symname, (long int) sym->st_value, ndx, outregs->int_retval);
+
+ return 0;
+}
diff --git a/fedora/branch.mk b/fedora/branch.mk
index 4c1e1f0f5c..96a37d0f31 100644
--- a/fedora/branch.mk
+++ b/fedora/branch.mk
@@ -1,5 +1,5 @@
# This file is updated automatically by Makefile.
glibc-branch := fedora
glibc-base := HEAD
-fedora-sync-date := 2005-01-06 22:03 UTC
-fedora-sync-tag := fedora-glibc-20050106T2203
+fedora-sync-date := 2005-02-08 09:48 UTC
+fedora-sync-tag := fedora-glibc-20050208T0948
diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in
index d063010b1f..f508a0dae2 100644
--- a/fedora/glibc.spec.in
+++ b/fedora/glibc.spec.in
@@ -1,4 +1,4 @@
-%define glibcrelease 5
+%define glibcrelease 6
%define auxarches i586 i686 athlon sparcv9 alphaev6
%define prelinkarches noarch
%define nptlarches i386 i686 athlon x86_64 ia64 s390 s390x sparcv9 ppc ppc64
@@ -1270,6 +1270,33 @@ rm -f *.filelist*
%endif
%changelog
+* Tue Feb 8 2005 Jakub Jelinek <jakub@redhat.com> 2.3.4-6
+- update from CVS
+ - ld.so auditing
+ - fix segfault if chrooted app attempts to dlopen a library
+ and no standard library directory exists at all (#147067, #144303)
+ - fix initgroups when nscd is running, but has group caching disabled
+ (#146588)
+ - fix pthread_key_{create,destroy} in LinuxThreads when pthread_create
+ has not been called yet (#146710)
+ - fix ppc64 swapcontext and setcontext (#146736, BZ#700)
+ - service nscd cosmetic fixes (#146776)
+ - fix IA-32 and x86-64 stack alignment in DSO constructors (#145689)
+ - fix zdump -v segfaults on x86-64 (#146210)
+ - avoid calling sigaction (SIGPIPE, ...) inside syslog (#146021, IT#56686)
+ - fix errno values for futimes (BZ#633)
+ - unconditionally include <features.h> in malloc.h (BZ#650)
+ - change regex \B handling to match old GNU regex as well as perl/grep's dfa
+ (from empty string inside of word to empty string not at a word boundary,
+ BZ#693)
+ - slightly optimize i686 TLS accesses, use direct TLS %gs access in sem_*
+ and allow building -mno-tls-direct-seg-refs glibc that is free of direct TLS
+ %gs access with negative offsets
+ - fix addseverity
+ - fix fmemopen
+ - fix rewinddir
+ - increase svc{tcp,unix}_create listen backlog
+
* Thu Jan 6 2005 Jakub Jelinek <jakub@redhat.com> 2.3.4-5
- update from CVS
- add some warn_unused_result marking
@@ -1279,7 +1306,7 @@ rm -f *.filelist*
* Thu Jan 6 2005 Jakub Jelinek <jakub@redhat.com> 2.3.4-4
- update from CVS
- fix IA-32 stack alignment for LinuxThreads thread functions
- and functions passed to clone(2) directly
+ and functions passed to clone(2) directly
- fix ecvt{,_r} on denormals (#143279)
- fix __tls_get_addr typo
- fix rounding in IA-64 alarm (#143710)
diff --git a/grp/putgrent.c b/grp/putgrent.c
index cb9b6b1f79..382d6a4daa 100644
--- a/grp/putgrent.c
+++ b/grp/putgrent.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 92, 96, 98, 99, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1991,92,96,98,99,2000,2005 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
@@ -44,8 +44,13 @@ putgrent (gr, stream)
flockfile (stream);
- retval = fprintf (stream, "%s:%s:%u:",
- gr->gr_name, _S (gr->gr_passwd), gr->gr_gid);
+ if (gr->gr_name[0] == '+' || gr->gr_name[0] == '-')
+ retval = fprintf (stream, "%s:%s::",
+ gr->gr_name, _S (gr->gr_passwd));
+ else
+ retval = fprintf (stream, "%s:%s:%lu:",
+ gr->gr_name, _S (gr->gr_passwd),
+ (unsigned long int) gr->gr_gid);
if (__builtin_expect (retval, 0) < 0)
{
funlockfile (stream);
diff --git a/hurd/sigunwind.c b/hurd/sigunwind.c
index 450a385a2a..1c6489b3b3 100644
--- a/hurd/sigunwind.c
+++ b/hurd/sigunwind.c
@@ -1,5 +1,5 @@
/* longjmp cleanup function for unwinding past signal handlers.
- Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998, 2005 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
@@ -111,7 +111,7 @@ _hurdsig_longjmp_from_handler (void *data, jmp_buf env, int val)
link = (void *) &scp[1];
assert (! link->resource.next && ! link->resource.prevp);
assert (link->thread.next == ss->active_resources);
- assert (link->thread.prevp = &ss->active_resources);
+ assert (link->thread.prevp == &ss->active_resources);
if (link->thread.next)
link->thread.next->thread.prevp = &link->thread.next;
ss->active_resources = link;
diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c
index 86852857a3..5b3d35ecaa 100644
--- a/iconv/iconv_prog.c
+++ b/iconv/iconv_prog.c
@@ -1,5 +1,5 @@
/* Convert text in given files from the specified from-set to the to-set.
- Copyright (C) 1998-2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1998-2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@@ -239,26 +239,30 @@ main (int argc, char *argv[])
if (from_wrong)
{
if (to_wrong)
- error (EXIT_FAILURE, 0,
+ error (0, 0,
_("\
conversion from `%s' and to `%s' are not supported"),
from_pretty, to_pretty);
else
- error (EXIT_FAILURE, 0,
+ error (0, 0,
_("conversion from `%s' is not supported"),
from_pretty);
}
else
{
if (to_wrong)
- error (EXIT_FAILURE, 0,
+ error (0, 0,
_("conversion to `%s' is not supported"),
to_pretty);
else
- error (EXIT_FAILURE, 0,
+ error (0, 0,
_("conversion from `%s' to `%s' is not supported"),
from_pretty, to_pretty);
}
+
+ argp_help (&argp, stderr, ARGP_HELP_SEE,
+ program_invocation_short_name);
+ exit (1);
}
else
error (EXIT_FAILURE, errno,
@@ -424,7 +428,7 @@ print_version (FILE *stream, struct argp_state *state)
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
+"), "2005");
fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
}
diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c
index 0ed210b794..8c56d29bb0 100644
--- a/iconv/iconvconfig.c
+++ b/iconv/iconvconfig.c
@@ -1,5 +1,5 @@
/* Generate fastloading iconv module configuration files.
- Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2000-2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
@@ -397,7 +397,7 @@ print_version (FILE *stream, struct argp_state *state)
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
+"), "2005");
fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
}
diff --git a/iconv/strtab.c b/iconv/strtab.c
index e6feb2cf24..4a8f29a675 100644
--- a/iconv/strtab.c
+++ b/iconv/strtab.c
@@ -1,5 +1,5 @@
/* C string table handling.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2005 Free Software Foundation, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
This program is free software; you can redistribute it and/or modify
@@ -326,7 +326,7 @@ strtabfinalize (struct Strtab *st, size_t *size)
copylen = 1;
copystrings (st->root, &endp, &copylen);
assert (copylen == st->total + 1);
- assert (endp = retval + st->total + 1);
+ assert (endp == retval + st->total + 1);
*size = copylen;
return retval;
diff --git a/iconvdata/jis0208.h b/iconvdata/jis0208.h
index 9dea38973c..8255bafc62 100644
--- a/iconvdata/jis0208.h
+++ b/iconvdata/jis0208.h
@@ -1,5 +1,5 @@
/* Access functions for JISX0208 conversion.
- Copyright (C) 1997, 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1997,1998,1999,2000,2003,2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -24,15 +24,6 @@
#include <gconv.h>
#include <stdint.h>
-/* Conversion table. */
-extern const uint16_t __jis0208_to_ucs[];
-
-extern const char __jisx0208_from_ucs4_lat1[256][2];
-extern const char __jisx0208_from_ucs4_greek[0xc1][2];
-extern const struct jisx0208_ucs_idx __jisx0208_from_ucs_idx[];
-extern const char __jisx0208_from_ucs_tab[][2];
-
-
/* Struct for table with indeces in UCS mapping table. */
struct jisx0208_ucs_idx
{
@@ -42,6 +33,15 @@ struct jisx0208_ucs_idx
};
+/* Conversion table. */
+extern const uint16_t __jis0208_to_ucs[];
+
+extern const char __jisx0208_from_ucs4_lat1[256][2];
+extern const char __jisx0208_from_ucs4_greek[0xc1][2];
+extern const struct jisx0208_ucs_idx __jisx0208_from_ucs_idx[];
+extern const char __jisx0208_from_ucs_tab[][2];
+
+
static inline uint32_t
__attribute ((always_inline))
jisx0208_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset)
diff --git a/include/dlfcn.h b/include/dlfcn.h
index bfa1b9041b..460c037ed1 100644
--- a/include/dlfcn.h
+++ b/include/dlfcn.h
@@ -7,9 +7,24 @@
#define __RTLD_SPROF 0x40000000
#define __RTLD_OPENEXEC 0x20000000
#define __RTLD_CALLMAP 0x10000000
+#define __RTLD_AUDIT 0x08000000
#define __LM_ID_CALLER -2
+#ifdef SHARED
+/* Locally stored program arguments. */
+extern int __dlfcn_argc attribute_hidden;
+extern char **__dlfcn_argv attribute_hidden;
+#else
+/* These variables are defined and initialized in the startup code. */
+extern int __libc_argc attribute_hidden;
+extern char **__libc_argv attribute_hidden;
+
+# define __dlfcn_argc __libc_argc
+# define __dlfcn_argv __libc_argv
+#endif
+
+
/* Now define the internal interfaces. */
#define __libc_dlopen(name) \
@@ -29,18 +44,8 @@ extern int _dl_addr (const void *address, Dl_info *info,
libc_hidden_proto (_dl_addr)
#endif
-/* Open the shared object NAME, relocate it, and run its initializer if it
- hasn't already been run. MODE is as for `dlopen' (see <dlfcn.h>). If
- the object is already opened, returns its existing map. */
-extern void *_dl_open (const char *name, int mode, const void *caller,
- Lmid_t nsid)
- internal_function;
-libc_hidden_proto (_dl_open)
-
/* Close an object previously opened by _dl_open. */
-extern void _dl_close (void *map)
- internal_function;
-libc_hidden_proto (_dl_close)
+extern void _dl_close (void *map) attribute_hidden;
/* Look up NAME in shared object HANDLE (which may be RTLD_DEFAULT or
RTLD_NEXT). WHO is the calling function, for RTLD_NEXT. Returns
diff --git a/include/link.h b/include/link.h
index 3078b72a87..965419126d 100644
--- a/include/link.h
+++ b/include/link.h
@@ -1,6 +1,6 @@
/* Data structure for communication from the run-time dynamic linker for
loaded ELF shared objects.
- Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1995-2002, 2003, 2004, 2005 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
@@ -34,6 +34,7 @@
#include <bits/elfclass.h> /* Defines __ELF_NATIVE_CLASS. */
#include <bits/link.h>
+#include <bits/linkmap.h>
#include <dl-lookupcfg.h>
#include <tls.h> /* Defines USE_TLS. */
@@ -199,6 +200,10 @@ struct link_map
should be called on this link map
when relocation finishes. */
unsigned int l_used:1; /* Nonzero if the DSO is used. */
+ unsigned int l_auditing:1; /* Nonzero if the DSO is used in auditing. */
+ unsigned int l_audit_any_plt:1; /* Nonzero if at least one audit module
+ is interested in the PLT interception.*/
+
/* Array with version names. */
unsigned int l_nversions;
struct r_found_version *l_versions;
@@ -207,7 +212,14 @@ struct link_map
struct r_search_path_struct l_rpath_dirs;
/* Collected results of relocation while profiling. */
- ElfW(Addr) *l_reloc_result;
+ struct reloc_result
+ {
+ DL_FIXUP_VALUE_TYPE addr;
+ struct link_map *bound;
+ unsigned int boundndx;
+ uint32_t enterexit;
+ unsigned int flags;
+ } *l_reloc_result;
/* Pointer to the version information if available. */
ElfW(Versym) *l_versyms;
@@ -263,11 +275,7 @@ struct link_map
{
const ElfW(Sym) *sym;
int type_class;
-#ifdef DL_LOOKUP_RETURNS_MAP
struct link_map *value;
-#else
- ElfW(Addr) value;
-#endif
const ElfW(Sym) *ret;
} l_lookup_cache;
@@ -297,8 +305,64 @@ struct link_map
done. */
ElfW(Addr) l_relro_addr;
size_t l_relro_size;
+
+ /* Audit information. This array apparent must be the last in the
+ structure. Never add something after it. */
+ struct auditstate
+ {
+ uintptr_t cookie;
+ unsigned int bindflags;
+ } l_audit[0];
+ };
+
+/* Version numbers for la_version handshake interface. */
+#define LAV_CURRENT 1
+
+/* Activity types signaled through la_activity. */
+enum
+ {
+ LA_ACT_CONSISTENT,
+ LA_ACT_ADD,
+ LA_ACT_DELETE
+ };
+
+/* Values representing origin of name for dynamic loading. */
+enum
+ {
+ LA_SER_ORIG = 0x01, /* Original name. */
+ LA_SER_LIBPATH = 0x02, /* Directory from LD_LIBRARY_PATH. */
+ LA_SER_RUNPATH = 0x04, /* Directory from RPATH/RUNPATH. */
+ LA_SER_CONFIG = 0x08, /* Found through ldconfig. */
+ LA_SER_DEFAULT = 0x40, /* Default directory. */
+ LA_SER_SECURE = 0x80 /* Unused. */
+ };
+
+/* Values for la_objopen return value. */
+enum
+ {
+ LA_FLG_BINDTO = 0x01, /* Audit symbols bound to this object. */
+ LA_FLG_BINDFROM = 0x02 /* Audit symbols bound from this object. */
};
+/* Values for la_symbind flags parameter. */
+enum
+ {
+ LA_SYMB_NOPLTENTER = 0x01, /* la_pltenter will not be called. */
+ LA_SYMB_NOPLTEXIT = 0x02, /* la_pltexit will not be called. */
+ LA_SYMB_STRUCTCALL = 0x04, /* Return value is a structure. */
+ LA_SYMB_DLSYM = 0x08, /* Binding due to dlsym call. */
+ LA_SYMB_ALTVALUE = 0x10 /* Value has been changed by a previous
+ la_symbind call. */
+ };
+
+#if __ELF_NATIVE_CLASS == 32
+# define symbind symbind32
+#elif __ELF_NATIVE_CLASS == 64
+# define symbind symbind64
+#else
+# error "__ELF_NATIVE_CLASS must be defined"
+#endif
+
struct dl_phdr_info
{
ElfW(Addr) dlpi_addr;
diff --git a/libio/fmemopen.c b/libio/fmemopen.c
index 51e849e846..7c8769a130 100644
--- a/libio/fmemopen.c
+++ b/libio/fmemopen.c
@@ -71,6 +71,7 @@
#include <libio.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include "libioP.h"
diff --git a/libio/iofopncook.c b/libio/iofopncook.c
index eba3d435dc..9c5503d1f2 100644
--- a/libio/iofopncook.c
+++ b/libio/iofopncook.c
@@ -37,6 +37,8 @@ static _IO_ssize_t _IO_cookie_read (register _IO_FILE* fp, void* buf,
static _IO_ssize_t _IO_cookie_write (register _IO_FILE* fp,
const void* buf, _IO_ssize_t size);
static _IO_off64_t _IO_cookie_seek (_IO_FILE *fp, _IO_off64_t offset, int dir);
+static _IO_off64_t _IO_cookie_seekoff (_IO_FILE *fp, _IO_off64_t offset,
+ int dir, int mode);
static int _IO_cookie_close (_IO_FILE* fp);
static _IO_ssize_t
diff --git a/libio/stdio.h b/libio/stdio.h
index 9b529dd839..ac42b3e2ac 100644
--- a/libio/stdio.h
+++ b/libio/stdio.h
@@ -151,9 +151,9 @@ extern struct _IO_FILE *stderr; /* Standard error output stream. */
__BEGIN_NAMESPACE_STD
/* Remove file FILENAME. */
-extern int remove (__const char *__filename) __THROW __wur;
+extern int remove (__const char *__filename) __THROW;
/* Rename file OLD to NEW. */
-extern int rename (__const char *__old, __const char *__new) __THROW __wur;
+extern int rename (__const char *__old, __const char *__new) __THROW;
__END_NAMESPACE_STD
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index ff1b7fea93..329f2d8b12 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -1,3 +1,26 @@
+2005-02-07 Jakub Jelinek <jakub@redhat.com>
+
+ * specific.c (pthread_key_delete): If pthread_create has not been
+ called yet, clear p_specific for the current thread.
+ * Makefile (tests): Add tst-tsd1.
+ * tst-tsd1.c: New test.
+
+2005-01-08 Andreas Jaeger <aj@suse.de>
+
+ * pthread.c (init_one_static_tls): Adjust initialization of DTV
+ entry for static tls deallocation fix.
+
+ * sysdeps/alpha/tls.h (dtv_t): Change pointer type to be struct which
+ also contains information whether the memory pointed to is static
+ TLS or not, include <stdbool.h>.
+ * sysdeps/i386/tls.h: Likewise.
+ * sysdeps/ia64/tls.h: Likewise.
+ * sysdeps/powerpc/tls.h: Likewise.
+ * sysdeps/s390/tls.h: Likewise.
+ * sysdeps/sh/tls.h: Likewise.
+ * sysdeps/sparc/tls.h: Likewise.
+ * sysdeps/x86_64/tls.h: Likewise.
+
2004-12-21 Jakub Jelinek <jakub@redhat.com>
* Makefile (tests): Add tst-align.
diff --git a/linuxthreads/Makefile b/linuxthreads/Makefile
index d9bf476c7e..c2b548b38b 100644
--- a/linuxthreads/Makefile
+++ b/linuxthreads/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1996-2003, 2004 Free Software Foundation, Inc.
+# Copyright (C) 1996-2003, 2004, 2005 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
@@ -111,7 +111,7 @@ tests = ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 ex9 $(librt-tests) ex12 ex13 joinrace \
ex17 ex18 tst-cancel tst-context bug-sleep \
tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel4 tst-cancel5 \
tst-cancel6 tst-cancel7 tst-cancel8 tst-popen tst-popen2 tst-attr1 \
- tst-stack1 tst-align
+ tst-stack1 tst-align tst-tsd1
test-srcs = tst-signal
# These tests are linked with libc before libpthread
tests-reverse += tst-cancel5
diff --git a/linuxthreads/pthread.c b/linuxthreads/pthread.c
index 24f0eb02b0..39863f2b54 100644
--- a/linuxthreads/pthread.c
+++ b/linuxthreads/pthread.c
@@ -482,7 +482,8 @@ init_one_static_tls (pthread_descr descr, struct link_map *map)
# endif
/* Fill in the DTV slot so that a later LD/GD access will find it. */
- dtv[map->l_tls_modid].pointer = dest;
+ dtv[map->l_tls_modid].pointer.val = dest;
+ dtv[map->l_tls_modid].pointer.is_static = true;
/* Initialize the memory. */
memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
diff --git a/linuxthreads/specific.c b/linuxthreads/specific.c
index f54fabaeb9..92eec3d99a 100644
--- a/linuxthreads/specific.c
+++ b/linuxthreads/specific.c
@@ -104,15 +104,16 @@ int pthread_key_delete(pthread_key_t key)
that if the key is reallocated later by pthread_key_create, its
associated values will be NULL in all threads.
- Do nothing if no threads have been created yet. */
+ If no threads have been created yet, clear it just in the
+ current thread. */
+ struct pthread_key_delete_helper_args args;
+ args.idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
+ args.idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
if (__pthread_manager_request != -1)
{
- struct pthread_key_delete_helper_args args;
struct pthread_request request;
- args.idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
- args.idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
args.self = 0;
request.req_thread = self;
@@ -124,6 +125,11 @@ int pthread_key_delete(pthread_key_t key)
(char *) &request, sizeof(request)));
suspend(self);
}
+ else
+ {
+ if (self->p_specific[args.idx1st] != NULL)
+ self->p_specific[args.idx1st][args.idx2nd] = NULL;
+ }
pthread_mutex_unlock(&pthread_keys_mutex);
return 0;
diff --git a/linuxthreads/sysdeps/alpha/tls.h b/linuxthreads/sysdeps/alpha/tls.h
index 9e15318b79..1eabf5b890 100644
--- a/linuxthreads/sysdeps/alpha/tls.h
+++ b/linuxthreads/sysdeps/alpha/tls.h
@@ -1,5 +1,5 @@
/* Definitions for thread-local data handling. linuxthreads/Alpha version.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2005 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
@@ -23,13 +23,18 @@
#ifndef __ASSEMBLER__
# include <pt-machine.h>
+# include <stdbool.h>
# include <stddef.h>
/* Type for the dtv. */
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
diff --git a/linuxthreads/sysdeps/i386/tls.h b/linuxthreads/sysdeps/i386/tls.h
index d296340ad8..f5d555baec 100644
--- a/linuxthreads/sysdeps/i386/tls.h
+++ b/linuxthreads/sysdeps/i386/tls.h
@@ -1,5 +1,5 @@
/* Definition for thread-local data handling. linuxthreads/i386 version.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 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
@@ -24,6 +24,7 @@
# include <pt-machine.h>
#ifndef __ASSEMBLER__
+# include <stdbool.h>
# include <stddef.h>
# include <stdint.h>
@@ -31,7 +32,11 @@
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
diff --git a/linuxthreads/sysdeps/ia64/tls.h b/linuxthreads/sysdeps/ia64/tls.h
index 6bdf819d8d..fe8fcd15f8 100644
--- a/linuxthreads/sysdeps/ia64/tls.h
+++ b/linuxthreads/sysdeps/ia64/tls.h
@@ -1,5 +1,5 @@
/* Definitions for thread-local data handling. linuxthreads/IA-64 version.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 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
@@ -24,13 +24,18 @@
# include <dl-sysdep.h>
# include <pt-machine.h>
+# include <stdbool.h>
# include <stddef.h>
/* Type for the dtv. */
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
#else /* __ASSEMBLER__ */
diff --git a/linuxthreads/sysdeps/powerpc/tls.h b/linuxthreads/sysdeps/powerpc/tls.h
index fda953976e..35472081d6 100644
--- a/linuxthreads/sysdeps/powerpc/tls.h
+++ b/linuxthreads/sysdeps/powerpc/tls.h
@@ -1,5 +1,5 @@
/* Definitions for thread-local data handling. linuxthreads/PPC version.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005 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
@@ -23,13 +23,18 @@
#ifndef __ASSEMBLER__
# include <pt-machine.h>
+# include <stdbool.h>
# include <stddef.h>
/* Type for the dtv. */
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
#else /* __ASSEMBLER__ */
@@ -107,9 +112,9 @@ typedef struct
/* Code to initially initialize the thread pointer. This might need
special attention since 'errno' is not yet available and if the
operation can cause a failure 'errno' must not be touched.
-
- The global register variable is declared in pt-machine.h with the
- wrong type, so we need some extra casts to get the desired result.
+
+ The global register variable is declared in pt-machine.h with the
+ wrong type, so we need some extra casts to get the desired result.
This avoids a lvalue cast that gcc-3.4 does not like. */
# define TLS_INIT_TP(TCBP, SECONDCALL) \
(__thread_self = (struct _pthread_descr_struct *) \
diff --git a/linuxthreads/sysdeps/s390/tls.h b/linuxthreads/sysdeps/s390/tls.h
index f420195bd2..00a4df9382 100644
--- a/linuxthreads/sysdeps/s390/tls.h
+++ b/linuxthreads/sysdeps/s390/tls.h
@@ -1,5 +1,5 @@
/* Definitions for thread-local data handling. linuxthreads/s390 version.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2005 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
@@ -23,13 +23,18 @@
#ifndef __ASSEMBLER__
# include <pt-machine.h>
+# include <stdbool.h>
# include <stddef.h>
/* Type for the dtv. */
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
typedef struct
diff --git a/linuxthreads/sysdeps/sh/tls.h b/linuxthreads/sysdeps/sh/tls.h
index bc9d44fa85..fbc6f01151 100644
--- a/linuxthreads/sysdeps/sh/tls.h
+++ b/linuxthreads/sysdeps/sh/tls.h
@@ -1,5 +1,5 @@
/* Definition for thread-local data handling. linuxthreads/SH version.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2005 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
@@ -24,6 +24,7 @@
# include <pt-machine.h>
#ifndef __ASSEMBLER__
+# include <stdbool.h>
# include <stddef.h>
# include <stdint.h>
@@ -31,7 +32,11 @@
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
#else /* __ASSEMBLER__ */
diff --git a/linuxthreads/sysdeps/sparc/tls.h b/linuxthreads/sysdeps/sparc/tls.h
index 5053824058..3e550fa7c7 100644
--- a/linuxthreads/sysdeps/sparc/tls.h
+++ b/linuxthreads/sysdeps/sparc/tls.h
@@ -1,5 +1,5 @@
/* Definitions for thread-local data handling. linuxthreads/sparc version.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2005 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
@@ -23,13 +23,18 @@
#ifndef __ASSEMBLER__
# include <pt-machine.h>
+# include <stdbool.h>
# include <stddef.h>
/* Type for the dtv. */
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
typedef struct
diff --git a/linuxthreads/sysdeps/x86_64/tls.h b/linuxthreads/sysdeps/x86_64/tls.h
index d979bbd896..67d80b28d9 100644
--- a/linuxthreads/sysdeps/x86_64/tls.h
+++ b/linuxthreads/sysdeps/x86_64/tls.h
@@ -1,5 +1,5 @@
/* Definitions for thread-local data handling. linuxthreads/x86-64 version.
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2005 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
@@ -23,13 +23,18 @@
#ifndef __ASSEMBLER__
# include <pt-machine.h>
+# include <stdbool.h>
# include <stddef.h>
/* Type for the dtv. */
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
diff --git a/linuxthreads/tst-tsd1.c b/linuxthreads/tst-tsd1.c
new file mode 100644
index 0000000000..ba7973f1c4
--- /dev/null
+++ b/linuxthreads/tst-tsd1.c
@@ -0,0 +1,118 @@
+/* Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+
+
+static int
+do_test (void)
+{
+ pthread_key_t key1;
+ pthread_key_t key2;
+ void *value;
+ int result = 0;
+ int err;
+
+ err = pthread_key_create (&key1, NULL);
+ if (err != 0)
+ {
+ printf ("1st key_create failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ /* Initial value must be NULL. */
+ value = pthread_getspecific (key1);
+ if (value != NULL)
+ {
+ puts ("1st getspecific != NULL");
+ result = 1;
+ }
+
+ err = pthread_setspecific (key1, (void *) -2l);
+ if (err != 0)
+ {
+ printf ("1st setspecific failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ value = pthread_getspecific (key1);
+ if (value == NULL)
+ {
+ puts ("2nd getspecific == NULL\n");
+ result = 1;
+ }
+ else if (value != (void *) -2l)
+ {
+ puts ("2nd getspecific != -2l\n");
+ result = 1;
+ }
+
+ err = pthread_setspecific (key1, (void *) -3l);
+ if (err != 0)
+ {
+ printf ("2nd setspecific failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ value = pthread_getspecific (key1);
+ if (value == NULL)
+ {
+ puts ("3rd getspecific == NULL\n");
+ result = 1;
+ }
+ else if (value != (void *) -3l)
+ {
+ puts ("3rd getspecific != -2l\n");
+ result = 1;
+ }
+
+ err = pthread_key_delete (key1);
+ if (err != 0)
+ {
+ printf ("key_delete failed: %s\n", strerror (err));
+ result = 1;
+ }
+
+
+ err = pthread_key_create (&key2, NULL);
+ if (err != 0)
+ {
+ printf ("2nd key_create failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ if (key1 != key2)
+ puts ("key1 != key2; no more tests performed");
+ else
+ {
+ value = pthread_getspecific (key2);
+ if (value != NULL)
+ {
+ puts ("4th getspecific != NULL");
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/linuxthreads_db/ChangeLog b/linuxthreads_db/ChangeLog
index 338bf8207f..4bda6fb47a 100644
--- a/linuxthreads_db/ChangeLog
+++ b/linuxthreads_db/ChangeLog
@@ -1,3 +1,7 @@
+2005-01-09 Andreas Jaeger <aj@suse.de>
+
+ * td_thr_tlsbase.c (td_thr_tlsbase): Adjust for dtv change.
+
2004-05-01 Jakub Jelinek <jakub@redhat.com>
* thread_dbP.h (LOG): Use write instead of __libc_write.
diff --git a/linuxthreads_db/td_thr_tlsbase.c b/linuxthreads_db/td_thr_tlsbase.c
index 081e8d0e70..5a7e31b9e1 100644
--- a/linuxthreads_db/td_thr_tlsbase.c
+++ b/linuxthreads_db/td_thr_tlsbase.c
@@ -1,5 +1,5 @@
/* Locate TLS data for a thread.
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005 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
@@ -59,10 +59,10 @@ td_thr_tlsbase (const td_thrhandle_t *th,
/* It could be that the memory for this module is not allocated for
the given thread. */
- if (pdtv.pointer == TLS_DTV_UNALLOCATED)
+ if (pdtv.pointer.val == TLS_DTV_UNALLOCATED)
return TD_TLSDEFER;
- *base = (char *) pdtv.pointer;
+ *base = (char *) pdtv.pointer.val;
return TD_OK;
#else
diff --git a/locale/programs/locale.c b/locale/programs/locale.c
index adf9944578..d64bb0b560 100644
--- a/locale/programs/locale.c
+++ b/locale/programs/locale.c
@@ -1,5 +1,5 @@
/* Implementation of the locale program according to POSIX 9945-2.
- Copyright (C) 1995-1997, 1999-2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1995-1997, 1999-2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1995.
@@ -277,7 +277,7 @@ print_version (FILE *stream, struct argp_state *state)
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
+"), "2005");
fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
}
diff --git a/locale/programs/localedef.c b/locale/programs/localedef.c
index 28cb7b316e..326113c175 100644
--- a/locale/programs/localedef.c
+++ b/locale/programs/localedef.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1995-2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1995.
@@ -389,7 +389,7 @@ print_version (FILE *stream, struct argp_state *state)
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
+"), "2005");
fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
}
diff --git a/malloc/malloc.c b/malloc/malloc.c
index e3ccbde7b5..4d2169bf78 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1,5 +1,5 @@
/* Malloc implementation for multiple threads without lock contention.
- Copyright (C) 1996-2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1996-2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Wolfram Gloger <wg@malloc.de>
and Doug Lea <dl@cs.oswego.edu>, 2001.
@@ -5508,6 +5508,8 @@ int mALLOPt(param_number, value) int param_number; int value;
/* Helper code. */
+extern char **__libc_argv attribute_hidden;
+
static void
malloc_printerr(int action, const char *str, void *ptr)
{
@@ -5522,8 +5524,8 @@ malloc_printerr(int action, const char *str, void *ptr)
__libc_message (action & 2,
action & 4
- ? "%s\n" : "*** glibc detected *** %s: 0x%s ***\n",
- str, cp);
+ ? "%s\n" : "*** glibc detected *** %s: %s: 0x%s ***\n",
+ __libc_argv[0] ?: "<unknown>", str, cp);
}
else if (action & 2)
abort ();
diff --git a/malloc/malloc.h b/malloc/malloc.h
index 753539e7b0..0f99e837c3 100644
--- a/malloc/malloc.h
+++ b/malloc/malloc.h
@@ -1,5 +1,5 @@
/* Prototypes and definition for malloc implementation.
- Copyright (C) 1996,97,99,2000,2002,2003,2004 Free Software Foundation, Inc.
+ Copyright (C) 1996,97,99,2000,2002-2004,2005 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
@@ -20,59 +20,16 @@
#ifndef _MALLOC_H
#define _MALLOC_H 1
-#ifdef _LIBC
#include <features.h>
-#endif
-
-/*
- $Id$
- `ptmalloc2', a malloc implementation for multiple threads without
- lock contention, by Wolfram Gloger <wg@malloc.de>.
-
- VERSION 2.7.0
-
- This work is mainly derived from malloc-2.7.0 by Doug Lea
- <dl@cs.oswego.edu>, which is available from:
-
- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
-
- This trimmed-down header file only provides function prototypes and
- the exported data structures. For more detailed function
- descriptions and compile-time options, see the source file
- `malloc.c'.
-*/
-
-#if defined(__STDC__) || defined (__cplusplus)
-# include <stddef.h>
+#include <stddef.h>
# define __malloc_ptr_t void *
-#else
-# undef size_t
-# define size_t unsigned int
-# undef ptrdiff_t
-# define ptrdiff_t int
-# define __malloc_ptr_t char *
-#endif
-#ifdef _LIBC
/* Used by GNU libc internals. */
-# define __malloc_size_t size_t
-# define __malloc_ptrdiff_t ptrdiff_t
-#elif !defined __attribute_malloc__
-# define __attribute_malloc__
-#endif
+#define __malloc_size_t size_t
+#define __malloc_ptrdiff_t ptrdiff_t
#ifdef __GNUC__
-/* GCC can always grok prototypes. For C++ programs we add throw()
- to help it optimize the function calls. But this works only with
- gcc 2.8.x and egcs. */
-# ifndef __THROW
-# if defined __cplusplus && (__GNUC__ >= 3 || __GNUC_MINOR__ >= 8)
-# define __THROW throw ()
-# else
-# define __THROW
-# endif
-# endif
# define __MALLOC_P(args) args __THROW
/* This macro will be used for functions which might take C++ callback
functions. */
@@ -80,78 +37,51 @@
#else /* Not GCC. */
-# define __THROW
-
-# if (defined __STDC__ && __STDC__) || defined __cplusplus
-
-# define __MALLOC_P(args) args
-# define __MALLOC_PMT(args) args
-
-# ifndef __const
-# define __const const
-# endif
-
-# else /* Not ANSI C or C++. */
-
-# define __MALLOC_P(args) () /* No prototypes. */
-# define __MALLOC_PMT(args) ()
-
-# ifndef __const
-# define __const
-# endif
-
-# endif /* ANSI C or C++. */
+# define __MALLOC_P(args) args
+# define __MALLOC_PMT(args) args
#endif /* GCC. */
-#ifndef NULL
-# ifdef __cplusplus
-# define NULL 0
-# else
-# define NULL ((__malloc_ptr_t) 0)
-# endif
-#endif
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
/* Allocate SIZE bytes of memory. */
-extern __malloc_ptr_t malloc __MALLOC_P ((size_t __size)) __attribute_malloc__;
+extern void *malloc __MALLOC_P ((size_t __size)) __attribute_malloc__ __wur;
/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
-extern __malloc_ptr_t calloc __MALLOC_P ((size_t __nmemb, size_t __size))
- __attribute_malloc__;
+extern void *calloc __MALLOC_P ((size_t __nmemb, size_t __size))
+ __attribute_malloc__ __wur;
/* Re-allocate the previously allocated block in __ptr, making the new
block SIZE bytes long. */
-extern __malloc_ptr_t realloc __MALLOC_P ((__malloc_ptr_t __ptr,
- size_t __size))
- __attribute_malloc__;
+extern void *realloc __MALLOC_P ((void *__ptr, size_t __size))
+ __attribute_malloc__ __attribute_warn_unused_result__;
/* Free a block allocated by `malloc', `realloc' or `calloc'. */
-extern void free __MALLOC_P ((__malloc_ptr_t __ptr));
+extern void free __MALLOC_P ((void *__ptr));
/* Free a block allocated by `calloc'. */
-extern void cfree __MALLOC_P ((__malloc_ptr_t __ptr));
+extern void cfree __MALLOC_P ((void *__ptr));
/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
-extern __malloc_ptr_t memalign __MALLOC_P ((size_t __alignment, size_t __size));
+extern void *memalign __MALLOC_P ((size_t __alignment, size_t __size))
+ __attribute_malloc__ __wur;
/* Allocate SIZE bytes on a page boundary. */
-extern __malloc_ptr_t valloc __MALLOC_P ((size_t __size)) __attribute_malloc__;
+extern void *valloc __MALLOC_P ((size_t __size))
+ __attribute_malloc__ __wur;
/* Equivalent to valloc(minimum-page-that-holds(n)), that is, round up
__size to nearest pagesize. */
-extern __malloc_ptr_t pvalloc __MALLOC_P ((size_t __size))
- __attribute_malloc__;
+extern void * pvalloc __MALLOC_P ((size_t __size))
+ __attribute_malloc__ __wur;
/* Underlying allocation function; successive calls should return
contiguous pieces of memory. */
-extern __malloc_ptr_t (*__morecore) __MALLOC_PMT ((ptrdiff_t __size));
+extern void *(*__morecore) __MALLOC_PMT ((ptrdiff_t __size));
/* Default value of `__morecore'. */
-extern __malloc_ptr_t __default_morecore __MALLOC_P ((ptrdiff_t __size))
+extern void *__default_morecore __MALLOC_P ((ptrdiff_t __size))
__attribute_malloc__;
/* SVID2/XPG mallinfo structure */
@@ -202,41 +132,38 @@ extern int malloc_trim __MALLOC_P ((size_t __pad));
/* Report the number of usable allocated bytes associated with allocated
chunk __ptr. */
-extern size_t malloc_usable_size __MALLOC_P ((__malloc_ptr_t __ptr));
+extern size_t malloc_usable_size __MALLOC_P ((void *__ptr));
/* Prints brief summary statistics on stderr. */
extern void malloc_stats __MALLOC_P ((void));
/* Record the state of all malloc variables in an opaque data structure. */
-extern __malloc_ptr_t malloc_get_state __MALLOC_P ((void));
+extern void *malloc_get_state __MALLOC_P ((void));
/* Restore the state of all malloc variables from data obtained with
malloc_get_state(). */
-extern int malloc_set_state __MALLOC_P ((__malloc_ptr_t __ptr));
+extern int malloc_set_state __MALLOC_P ((void *__ptr));
/* Called once when malloc is initialized; redefining this variable in
the application provides the preferred way to set up the hook
pointers. */
extern void (*__malloc_initialize_hook) __MALLOC_PMT ((void));
/* Hooks for debugging and user-defined versions. */
-extern void (*__free_hook) __MALLOC_PMT ((__malloc_ptr_t __ptr,
+extern void (*__free_hook) __MALLOC_PMT ((void *__ptr,
__const __malloc_ptr_t));
-extern __malloc_ptr_t (*__malloc_hook) __MALLOC_PMT ((size_t __size,
- __const __malloc_ptr_t));
-extern __malloc_ptr_t (*__realloc_hook) __MALLOC_PMT ((__malloc_ptr_t __ptr,
- size_t __size,
- __const __malloc_ptr_t));
-extern __malloc_ptr_t (*__memalign_hook) __MALLOC_PMT ((size_t __alignment,
- size_t __size,
- __const __malloc_ptr_t));
+extern void *(*__malloc_hook) __MALLOC_PMT ((size_t __size,
+ __const __malloc_ptr_t));
+extern void *(*__realloc_hook) __MALLOC_PMT ((void *__ptr, size_t __size,
+ __const __malloc_ptr_t));
+extern void *(*__memalign_hook) __MALLOC_PMT ((size_t __alignment,
+ size_t __size,
+ __const __malloc_ptr_t));
extern void (*__after_morecore_hook) __MALLOC_PMT ((void));
/* Activate a standard set of debugging hooks. */
extern void __malloc_check_init __MALLOC_P ((void));
-#ifdef __cplusplus
-} /* end of extern "C" */
-#endif
+__END_DECLS
#endif /* malloc.h */
diff --git a/malloc/memusage.sh b/malloc/memusage.sh
index be8f755a20..b2e08c6039 100755
--- a/malloc/memusage.sh
+++ b/malloc/memusage.sh
@@ -1,5 +1,5 @@
#! @BASH@
-# Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+# Copyright (C) 1999-2004, 2005 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# Contributed by Ulrich Drepper <drepper@gnu.org>, 1999.
@@ -71,7 +71,7 @@ do_version() {
printf $"Copyright (C) %s Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-" "2004"
+" "2005"
printf $"Written by %s.
" "Ulrich Drepper"
exit 0
diff --git a/malloc/mtrace.pl b/malloc/mtrace.pl
index 1640fa652d..0036f33f59 100644
--- a/malloc/mtrace.pl
+++ b/malloc/mtrace.pl
@@ -45,7 +45,7 @@ arglist: while (@ARGV) {
$ARGV[0] eq "--vers" || $ARGV[0] eq "--versi" ||
$ARGV[0] eq "--versio" || $ARGV[0] eq "--version") {
print "mtrace (GNU $PACKAGE) $VERSION\n";
- print "Copyright (C) 2004 Free Software Foundation, Inc.\n";
+ print "Copyright (C) 2005 Free Software Foundation, Inc.\n";
print "This is free software; see the source for copying conditions. There is NO\n";
print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
print "Written by Ulrich Drepper <drepper\@gnu.org>\n";
diff --git a/manual/.cvsignore b/manual/.cvsignore
index f1254e92d3..54abbbb5a4 100644
--- a/manual/.cvsignore
+++ b/manual/.cvsignore
@@ -9,6 +9,6 @@ glibc-*
*.cp *.cps *.fn *.fns *.vr *.vrs *.tp *.tps *.ky *.kys *.pg *.pgs
texis top-menu.texi chapters.texi summary.texi stamp-*
-distinfo dir-add.texinfo
+distinfo dir-add.texinfo dir-add.texi
libm-err.texi
diff --git a/manual/memory.texi b/manual/memory.texi
index 91abb7f5d4..ee2cd75c44 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -2384,7 +2384,7 @@ exceed the process' data storage limit.
@comment unistd.h
@comment BSD
-@deftypefun int sbrk (ptrdiff_t @var{delta})
+@deftypefun void *sbrk (ptrdiff_t @var{delta})
This function is the same as @code{brk} except that you specify the new
end of the data segment as an offset @var{delta} from the current end
and on success the return value is the address of the resulting end of
diff --git a/manual/string.texi b/manual/string.texi
index 21ab71461a..d9de12996e 100644
--- a/manual/string.texi
+++ b/manual/string.texi
@@ -1781,9 +1781,9 @@ uppercase and lowercase characters are related.
For example,
@smallexample
-strstr ("hello, world", "L")
+strcasestr ("hello, world", "L")
@result{} "llo, world"
-strstr ("hello, World", "wo")
+strcasestr ("hello, World", "wo")
@result{} "World"
@end smallexample
@end deftypefun
diff --git a/manual/users.texi b/manual/users.texi
index 20deeabdd2..b52ee44439 100644
--- a/manual/users.texi
+++ b/manual/users.texi
@@ -1690,6 +1690,9 @@ extended information about users, adding an entry using this function
would inevitably leave out much of the important information.
@c Then how are programmers to modify the password file? -zw
+The group and user ID fields are left empty if the group or user name
+starts with a - or +.
+
The function @code{putpwent} is declared in @file{pwd.h}.
@end deftypefun
diff --git a/math/math_private.h b/math/math_private.h
index f545841df0..a6a85d3b1e 100644
--- a/math/math_private.h
+++ b/math/math_private.h
@@ -192,6 +192,10 @@ extern int __kernel_rem_pio2 (double*,double*,int,int,int, const int32_t*);
/* internal functions. */
extern double __copysign (double x, double __y);
+#if __GNUC_PREREQ (4, 0)
+extern inline double __copysign (double x, double y)
+{ return __builtin_copysign (x, y); }
+#endif
/* ieee style elementary float functions */
extern float __ieee754_sqrtf (float);
@@ -235,6 +239,10 @@ extern int __kernel_rem_pio2f (float*,float*,int,int,int, const int32_t*);
/* internal functions. */
extern float __copysignf (float x, float __y);
+#if __GNUC_PREREQ (4, 0)
+extern inline float __copysignf (float x, float y)
+{ return __builtin_copysignf (x, y); }
+#endif
/* ieee style elementary long double functions */
extern long double __ieee754_sqrtl (long double);
@@ -298,6 +306,12 @@ extern long double fabsl (long double x);
extern void __sincosl (long double, long double *, long double *);
extern long double __logbl (long double x);
extern long double __significandl (long double x);
+
+#if __GNUC_PREREQ (4, 0)
+extern inline long double __copysignl (long double x, long double y)
+{ return __builtin_copysignl (x, y); }
+#endif
+
#endif
/* Prototypes for functions of the IBM Accurate Mathematical Library. */
diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
index 6ac21013cc..8d529bfadc 100644
--- a/misc/sys/cdefs.h
+++ b/misc/sys/cdefs.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992-2001, 2002, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2001, 2002, 2004, 2005 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
@@ -257,9 +257,16 @@
/* If fortification mode, we warn about unused results of certain
function calls which can lead to problems. */
-#if __GNUC_PREREQ (3,4) && __USE_FORTIFY_LEVEL > 0
-# define __wur __attribute__ ((__warn_unused_result__))
+#if __GNUC_PREREQ (3,4)
+# define __attribute_warn_unused_result__ \
+ __attribute__ ((__warn_unused_result__))
+# if __USE_FORTIFY_LEVEL > 0
+# define __wur __attribute_warn_unused_result__
+# endif
#else
+# define __attribute_warn_unused_result__ /* empty */
+#endif
+#ifndef __wur
# define __wur /* Ignore */
#endif
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index ec4d10b7ad..f372bde30e 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,40 @@
+2005-02-07 Richard Henderson <rth@redhat.com>
+
+ * sysdeps/pthread/pthread.h (__sigsetjmp): Use pointer as first
+ argument.
+
+2004-11-03 Marcus Brinkmann <marcus@gnu.org>
+
+ * sysdeps/generic/lowlevellock.h (__generic_mutex_unlock): Fix
+ order of arguments in invocation of atomic_add_zero.
+
+2005-01-26 Jakub Jelinek <jakub@redhat.com>
+
+ * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S (__new_sem_trywait):
+ Use direct %gs segment access or, if NO_TLS_DIRECT_SEG_REFS,
+ at least gotntpoff relocation and addition.
+ * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait):
+ Likewise.
+ * sysdeps/unix/sysv/linux/i386/i486/sem_post.S (__new_sem_post):
+ Likewise.
+ * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S (__new_sem_wait):
+ Likewise.
+
+2005-01-06 Ulrich Drepper <drepper@redhat.com>
+
+ * allocatestack.c (init_one_static_tls): Adjust initialization of DTV
+ entry for static tls deallocation fix.
+ * sysdeps/alpha/tls.h (dtv_t): Change pointer type to be struct which
+ also contains information whether the memory pointed to is static
+ TLS or not.
+ * sysdeps/i386/tls.h: Likewise.
+ * sysdeps/ia64/tls.h: Likewise.
+ * sysdeps/powerpc/tls.h: Likewise.
+ * sysdeps/s390/tls.h: Likewise.
+ * sysdeps/sh/tls.h: Likewise.
+ * sysdeps/sparc/tls.h: Likewise.
+ * sysdeps/x86_64/tls.h: Likewise.
+
2004-12-27 Ulrich Drepper <drepper@redhat.com>
* init.c (__pthread_initialize_minimal_internal): Use __sigemptyset.
@@ -69,7 +106,7 @@
* sysdeps/pthread/posix-timer.h (__timer_signal_thread_pclk,
__timer_signal_thread_tclk): Remove.
* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Removed.
- * sysdeps/unix/sysv/linux/ia64/bits/posix_>opt.h: Removed.
+ * sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Removed.
* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Removed.
2004-12-07 Jakub Jelinek <jakub@redhat.com>
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index 8875209a11..fcb6c6e475 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -920,7 +920,8 @@ init_one_static_tls (struct pthread *curp, struct link_map *map)
# endif
/* Fill in the DTV slot so that a later LD/GD access will find it. */
- dtv[map->l_tls_modid].pointer = dest;
+ dtv[map->l_tls_modid].pointer.val = dest;
+ dtv[map->l_tls_modid].pointer.is_static = true;
/* Initialize the memory. */
memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
diff --git a/nptl/sysdeps/alpha/tls.h b/nptl/sysdeps/alpha/tls.h
index bc6630953f..fa3c832a68 100644
--- a/nptl/sysdeps/alpha/tls.h
+++ b/nptl/sysdeps/alpha/tls.h
@@ -1,5 +1,5 @@
/* Definition for thread-local data handling. NPTL/Alpha version.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005 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
@@ -23,6 +23,7 @@
# include <dl-sysdep.h>
#ifndef __ASSEMBLER__
+# include <stdbool.h>
# include <stddef.h>
# include <stdint.h>
@@ -30,7 +31,11 @@
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
#else /* __ASSEMBLER__ */
diff --git a/nptl/sysdeps/generic/lowlevellock.h b/nptl/sysdeps/generic/lowlevellock.h
index 9cffca83e6..7f95daadad 100644
--- a/nptl/sysdeps/generic/lowlevellock.h
+++ b/nptl/sysdeps/generic/lowlevellock.h
@@ -76,7 +76,7 @@ __generic_mutex_unlock (int *mutex)
/* Adding 0x80000000 to the counter results in 0 if and only if
there are not other interested threads - we can return (this is
the fastpath). */
- if (atomic_add_zero (0x80000000, mutex))
+ if (atomic_add_zero (mutex, 0x80000000))
return;
/* There are other threads waiting for this mutex, wake one of them
diff --git a/nptl/sysdeps/i386/tls.h b/nptl/sysdeps/i386/tls.h
index 945a4c71d6..e243f8b2cf 100644
--- a/nptl/sysdeps/i386/tls.h
+++ b/nptl/sysdeps/i386/tls.h
@@ -22,6 +22,7 @@
#include <dl-sysdep.h>
#ifndef __ASSEMBLER__
+# include <stdbool.h>
# include <stddef.h>
# include <stdint.h>
# include <stdlib.h>
@@ -32,7 +33,11 @@
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
diff --git a/nptl/sysdeps/ia64/tls.h b/nptl/sysdeps/ia64/tls.h
index 4591a415c0..a435f966ca 100644
--- a/nptl/sysdeps/ia64/tls.h
+++ b/nptl/sysdeps/ia64/tls.h
@@ -1,5 +1,5 @@
/* Definition for thread-local data handling. nptl/IA-64 version.
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005 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
@@ -22,6 +22,7 @@
#include <dl-sysdep.h>
#ifndef __ASSEMBLER__
+# include <stdbool.h>
# include <stddef.h>
# include <stdint.h>
# include <stdlib.h>
@@ -32,7 +33,11 @@
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
diff --git a/nptl/sysdeps/powerpc/tls.h b/nptl/sysdeps/powerpc/tls.h
index ce7f5bd53d..a7f69074e9 100644
--- a/nptl/sysdeps/powerpc/tls.h
+++ b/nptl/sysdeps/powerpc/tls.h
@@ -1,5 +1,5 @@
/* Definition for thread-local data handling. NPTL/PowerPC version.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005 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
@@ -23,6 +23,7 @@
# include <dl-sysdep.h>
#ifndef __ASSEMBLER__
+# include <stdbool.h>
# include <stddef.h>
# include <stdint.h>
@@ -30,7 +31,11 @@
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
#else /* __ASSEMBLER__ */
diff --git a/nptl/sysdeps/pthread/pthread.h b/nptl/sysdeps/pthread/pthread.h
index 5046a6976b..57024e1e84 100644
--- a/nptl/sysdeps/pthread/pthread.h
+++ b/nptl/sysdeps/pthread/pthread.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 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
@@ -661,7 +661,7 @@ extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf)
/* Function used in the macros. */
struct __jmp_buf_tag;
-extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __THROW;
+extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __THROW;
/* Mutex handling. */
diff --git a/nptl/sysdeps/s390/tls.h b/nptl/sysdeps/s390/tls.h
index c9b991df32..e93f3d080c 100644
--- a/nptl/sysdeps/s390/tls.h
+++ b/nptl/sysdeps/s390/tls.h
@@ -1,5 +1,5 @@
/* Definition for thread-local data handling. NPTL/s390 version.
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005 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
@@ -22,6 +22,7 @@
#include <dl-sysdep.h>
#ifndef __ASSEMBLER__
+# include <stdbool.h>
# include <stddef.h>
# include <stdint.h>
# include <stdlib.h>
@@ -32,7 +33,11 @@
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
diff --git a/nptl/sysdeps/sh/tls.h b/nptl/sysdeps/sh/tls.h
index db490ab7ee..e883bae993 100644
--- a/nptl/sysdeps/sh/tls.h
+++ b/nptl/sysdeps/sh/tls.h
@@ -1,5 +1,5 @@
/* Definition for thread-local data handling. NPTL/SH version.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005 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
@@ -23,6 +23,7 @@
# include <dl-sysdep.h>
#ifndef __ASSEMBLER__
+# include <stdbool.h>
# include <stddef.h>
# include <stdint.h>
@@ -30,7 +31,11 @@
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
typedef struct
diff --git a/nptl/sysdeps/sparc/tls.h b/nptl/sysdeps/sparc/tls.h
index 8980f9fc0c..8f54a0bb23 100644
--- a/nptl/sysdeps/sparc/tls.h
+++ b/nptl/sysdeps/sparc/tls.h
@@ -1,5 +1,5 @@
/* Definitions for thread-local data handling. NPTL/sparc version.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005 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
@@ -22,6 +22,7 @@
#include <dl-sysdep.h>
#ifndef __ASSEMBLER__
+# include <stdbool.h>
# include <stddef.h>
# include <stdint.h>
# include <stdlib.h>
@@ -31,7 +32,11 @@
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
typedef struct
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S
index 3d67329bd1..71e96d2228 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -65,9 +65,14 @@ __new_sem_post:
#endif
addl $_GLOBAL_OFFSET_TABLE_, %ebx
#if USE___THREAD
- movl %gs:0, %edx
- subl errno@gottpoff(%ebx), %edx
+# ifdef NO_TLS_DIRECT_SEG_REFS
+ movl errno@gotntpoff(%ebx), %edx
+ addl %gs:0, %edx
movl $EINVAL, (%edx)
+# else
+ movl errno@gotntpoff(%ebx), %edx
+ movl $EINVAL, %gs:(%edx)
+# endif
#else
call __errno_location@plt
movl $EINVAL, (%eax)
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S
index 5b24476936..318b53a873 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -158,9 +158,14 @@ sem_timedwait:
#endif
addl $_GLOBAL_OFFSET_TABLE_, %ebx
#if USE___THREAD
- movl %gs:0, %edx
- subl errno@gottpoff(%ebx), %edx
+# ifdef NO_TLS_DIRECT_SEG_REFS
+ movl errno@gotntpoff(%ebx), %edx
+ addl %gs:0, %edx
movl %esi, (%edx)
+# else
+ movl errno@gotntpoff(%ebx), %edx
+ movl %esi, %gs:(%edx)
+# endif
#else
call __errno_location@plt
movl %esi, (%eax)
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S
index a7c405d95f..d36a1088fb 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -55,9 +55,14 @@ __new_sem_trywait:
#endif
addl $_GLOBAL_OFFSET_TABLE_, %ecx
#if USE___THREAD
- movl %gs:0, %edx
- subl errno@gottpoff(%ecx), %edx
+# ifdef NO_TLS_DIRECT_SEG_REFS
+ movl errno@gotntpoff(%ecx), %edx
+ addl %gs:0, %edx
movl $EAGAIN, (%edx)
+# else
+ movl errno@gotntpoff(%ecx), %edx
+ movl $EAGAIN, %gs:(%edx)
+# endif
#else
call __errno_location@plt
movl $EAGAIN, (%eax)
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S
index b7674dc3ba..1605b69b69 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -102,9 +102,14 @@ __new_sem_wait:
#endif
addl $_GLOBAL_OFFSET_TABLE_, %ebx
#if USE___THREAD
- movl %gs:0, %edx
- subl errno@gottpoff(%ebx), %edx
+# ifdef NO_TLS_DIRECT_SEG_REFS
+ movl errno@gotntpoff(%ebx), %edx
+ addl %gs:0, %edx
movl %esi, (%edx)
+# else
+ movl errno@gotntpoff(%ebx), %edx
+ movl %esi, %gs:(%edx)
+# endif
#else
call __errno_location@plt
movl %esi, (%eax)
diff --git a/nptl/sysdeps/x86_64/tls.h b/nptl/sysdeps/x86_64/tls.h
index 3d6111f4e3..12da9dc81f 100644
--- a/nptl/sysdeps/x86_64/tls.h
+++ b/nptl/sysdeps/x86_64/tls.h
@@ -1,5 +1,5 @@
/* Definition for thread-local data handling. nptl/x86_64 version.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004 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
@@ -22,6 +22,7 @@
#include <asm/prctl.h> /* For ARCH_SET_FS. */
#ifndef __ASSEMBLER__
+# include <stdbool.h>
# include <stddef.h>
# include <stdint.h>
# include <stdlib.h>
@@ -31,7 +32,11 @@
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
diff --git a/nscd/Makefile b/nscd/Makefile
index 70a35198c2..9c32c68681 100644
--- a/nscd/Makefile
+++ b/nscd/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1998, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
+# Copyright (C) 1998,2000,2002,2003,2004,2005 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
@@ -56,6 +56,8 @@ nscd-modules += selinux
selinux-LIBS := -lselinux
endif
+LDLIBS-nscd = $(selinux-LIBS)
+
distribute := nscd.h nscd-client.h dbg_log.h \
$(addsuffix .c, $(filter-out xmalloc, $(nscd-modules))) \
nscd_nischeck.c nscd.conf nscd.init nscd_proto.h \
@@ -110,7 +112,7 @@ $(objpfx)nscd: $(addprefix $(objpfx),$(nscd-modules:=.o))
$(extra-B-$(@F:lib%.so=%).so) $(load-map-file) \
$(LDFLAGS) $(LDFLAGS-$(@F)) \
-L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link) \
- -o $@ $^ $(selinux-LIBS) $(common-objpfx)libc_nonshared.a
+ -o $@ $^ $(LDLIBS-nscd) $(common-objpfx)libc_nonshared.a
endif
# This makes sure -DNOT_IN_libc is passed for all these modules.
diff --git a/nscd/connections.c b/nscd/connections.c
index aa760e0252..fe4989d6ef 100644
--- a/nscd/connections.c
+++ b/nscd/connections.c
@@ -1,5 +1,5 @@
/* Inner loops of cache daemon.
- Copyright (C) 1998-2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1998-2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@@ -605,7 +605,10 @@ send_ro_fd (struct database_dyn *db, char *key, int fd)
/* Send the control message. We repeat when we are interrupted but
everything else is ignored. */
- (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, 0));
+#ifndef MSG_NOSIGNAL
+# define MSG_NOSIGNAL 0
+#endif
+ (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, MSG_NOSIGNAL));
if (__builtin_expect (debug_level > 0, 0))
dbg_log (_("provide access to FD %d, for %s"), db->ro_fd, key);
diff --git a/nscd/nscd.c b/nscd/nscd.c
index 5cca127f91..3ae401f1f7 100644
--- a/nscd/nscd.c
+++ b/nscd/nscd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 1998-2003, 2004 Free Software Foundation, Inc.
+/* Copyright (c) 1998-2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
@@ -403,7 +403,7 @@ print_version (FILE *stream, struct argp_state *state)
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
+"), "2005");
fprintf (stream, gettext ("Written by %s.\n"),
"Thorsten Kukuk and Ulrich Drepper");
}
@@ -450,6 +450,9 @@ termination_handler (int signum)
/* Synchronize memory. */
for (int cnt = 0; cnt < lastdb; ++cnt)
{
+ if (!dbs[cnt].enabled)
+ continue;
+
/* Make sure nobody keeps using the database. */
dbs[cnt].head->timestamp = 0;
diff --git a/nscd/nscd.init b/nscd/nscd.init
index d5c1cb9ae3..23e20c3a82 100644
--- a/nscd/nscd.init
+++ b/nscd/nscd.init
@@ -88,9 +88,9 @@ case "$1" in
RETVAL=$?
;;
status)
- status nscd
+ status nscd
RETVAL=$?
- ;;
+ ;;
restart)
restart
RETVAL=$?
@@ -100,9 +100,11 @@ case "$1" in
RETVAL=$?
;;
reload)
- killproc /usr/sbin/nscd -HUP
+ echo -n $"Reloading $prog: "
+ killproc /usr/sbin/nscd -HUP
RETVAL=$?
- ;;
+ echo
+ ;;
*)
echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}"
RETVAL=1
diff --git a/nscd/nscd_getai.c b/nscd/nscd_getai.c
index 24b374b0dc..866f7b2a5f 100644
--- a/nscd/nscd_getai.c
+++ b/nscd/nscd_getai.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
@@ -78,7 +78,7 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop)
sizeof (ai_resp_mem));
if (sock == -1)
{
- /* nscd not running or wrong version or hosts caching disabled. */
+ /* nscd not running or wrong version. */
__nss_not_use_nscd_hosts = 1;
goto out;
}
@@ -151,6 +151,13 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop)
}
else
{
+ if (__builtin_expect (ai_resp->found == -1, 0))
+ {
+ /* The daemon does not cache this database. */
+ __nss_not_use_nscd_hosts = 1;
+ goto out_close;
+ }
+
/* Store the error number. */
*h_errnop = ai_resp->error;
diff --git a/nscd/nscd_helper.c b/nscd/nscd_helper.c
index 0e16cb8aeb..ea4fb968db 100644
--- a/nscd/nscd_helper.c
+++ b/nscd/nscd_helper.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@@ -138,7 +138,10 @@ get_mapping (request_type type, const char *key,
/* Failure or timeout. */
goto out_close2;
- if (TEMP_FAILURE_RETRY (__recvmsg (sock, &msg, 0)) != keylen)
+#ifndef MSG_NOSIGNAL
+# define MSG_NOSIGNAL 0
+#endif
+ if (TEMP_FAILURE_RETRY (__recvmsg (sock, &msg, MSG_NOSIGNAL)) != keylen)
goto out_close2;
mapfd = *(int *) CMSG_DATA (cmsg);
diff --git a/nscd/nscd_initgroups.c b/nscd/nscd_initgroups.c
index 2ea9e7f862..daddf2e164 100644
--- a/nscd/nscd_initgroups.c
+++ b/nscd/nscd_initgroups.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
@@ -75,7 +75,7 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size,
sizeof (initgr_resp_mem));
if (sock == -1)
{
- /* nscd not running or wrong version or hosts caching disabled. */
+ /* nscd not running or wrong version. */
__nss_not_use_nscd_group = 1;
goto out;
}
@@ -101,7 +101,7 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size,
(initgr_resp->ngrps + 1) * sizeof (gid_t));
if (newp == NULL)
/* We cannot increase the buffer size. */
- goto out;
+ goto out_close;
*groupsp = newp;
*size = initgr_resp->ngrps + 1;
@@ -125,6 +125,13 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size,
}
else
{
+ if (__builtin_expect (initgr_resp->found == -1, 0))
+ {
+ /* The daemon does not cache this database. */
+ __nss_not_use_nscd_group = 1;
+ goto out_close;
+ }
+
/* No group found yet. */
retval = 0;
@@ -143,6 +150,7 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size,
(*groupsp)[retval++] = group;
}
+ out_close:
if (sock != -1)
close_not_cancel_no_status (sock);
out:
diff --git a/nscd/nscd_nischeck.c b/nscd/nscd_nischeck.c
index a6817cf79e..20f7bb0620 100644
--- a/nscd/nscd_nischeck.c
+++ b/nscd/nscd_nischeck.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 1999, 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (c) 1999, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@suse.de>, 1999.
@@ -91,6 +91,6 @@ print_version (FILE *stream, struct argp_state *state)
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
+"), "2005");
fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk");
}
diff --git a/nss/getent.c b/nss/getent.c
index c0a273241f..0aea5eed2a 100644
--- a/nss/getent.c
+++ b/nss/getent.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 1998-2003, 2004 Free Software Foundation, Inc.
+/* Copyright (c) 1998-2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
@@ -83,7 +83,7 @@ print_version (FILE *stream, struct argp_state *state)
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
+"), "2005");
fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk");
}
diff --git a/posix/Makefile b/posix/Makefile
index 149283c65d..3af9e6681d 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1991-1999, 2000-2003, 2004 Free Software Foundation, Inc.
+# Copyright (C) 1991-1999, 2000-2003, 2004, 2005 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
@@ -140,16 +140,27 @@ CFLAGS-waitid.c = -fexceptions
CFLAGS-waitpid.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-getopt.c = -fexceptions
CFLAGS-wordexp.c = -fexceptions
+CFLAGS-wordexp.os = -fomit-frame-pointer
CFLAGS-sysconf.c = -fexceptions -DGETCONF_DIR='"$(libexecdir)/getconf"'
CFLAGS-pathconf.c = -fexceptions
CFLAGS-fpathconf.c = -fexceptions
CFLAGS-spawn.c = -fexceptions
+CFLAGS-spawn.os = -fomit-frame-pointer
CFLAGS-spawnp.c = -fexceptions
+CFLAGS-spawnp.os = -fomit-frame-pointer
CFLAGS-spawni.c = -fexceptions
+CFLAGS-spawni.os = -fomit-frame-pointer
CFLAGS-pause.c = -fexceptions
CFLAGS-glob.c = $(uses-callbacks) -fexceptions
CFLAGS-glob64.c = $(uses-callbacks) -fexceptions
CFLAGS-getconf.c = -DGETCONF_DIR='"$(libexecdir)/getconf"'
+CFLAGS-execve.os = -fomit-frame-pointer
+CFLAGS-fexecve.os = -fomit-frame-pointer
+CFLAGS-execv.os = -fomit-frame-pointer
+CFLAGS-execle.os = -fomit-frame-pointer
+CFLAGS-execl.os = -fomit-frame-pointer
+CFLAGS-execvp.os = -fomit-frame-pointer
+CFLAGS-execlp.os = -fomit-frame-pointer
tstgetopt-ARGS = -a -b -cfoobar --required foobar --optional=bazbug \
--none random --col --color --colour
diff --git a/posix/bug-regex19.c b/posix/bug-regex19.c
index 4000b19b4d..3a173a6ca0 100644
--- a/posix/bug-regex19.c
+++ b/posix/bug-regex19.c
@@ -1,5 +1,5 @@
/* Regular expression tests.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@@ -170,22 +170,22 @@ static struct test_s
{ERE, "[^k]\\B[^k]", "kBk", 0, -1},
{ERE, "[^C]\\B[^C]", "CCCABA", 0, 3},
{ERE, "[^C]\\B[^C]", "CBC", 0, -1},
- {ERE, ".(\\b|\\B).", "=~AB", 0, 1},
+ {ERE, ".(\\b|\\B).", "=~AB", 0, 0},
{ERE, ".(\\b|\\B).", "A=C", 0, 0},
{ERE, ".(\\b|\\B).", "ABC", 0, 0},
- {ERE, ".(\\b|\\B).", "=~\\!", 0, -1},
- {ERE, "[^k](\\b|\\B)[^k]", "=~AB", 0, 1},
+ {ERE, ".(\\b|\\B).", "=~\\!", 0, 0},
+ {ERE, "[^k](\\b|\\B)[^k]", "=~AB", 0, 0},
{ERE, "[^k](\\b|\\B)[^k]", "A=C", 0, 0},
{ERE, "[^k](\\b|\\B)[^k]", "ABC", 0, 0},
- {ERE, "[^k](\\b|\\B)[^k]", "=~kBD", 0, 3},
- {ERE, "[^k](\\b|\\B)[^k]", "=~\\!", 0, -1},
- {ERE, "[^k](\\b|\\B)[^k]", "=~kB", 0, -1},
- {ERE, "[^C](\\b|\\B)[^C]", "=~AB", 0, 1},
+ {ERE, "[^k](\\b|\\B)[^k]", "=~kBD", 0, 0},
+ {ERE, "[^k](\\b|\\B)[^k]", "=~\\!", 0, 0},
+ {ERE, "[^k](\\b|\\B)[^k]", "=~kB", 0, 0},
+ {ERE, "[^C](\\b|\\B)[^C]", "=~AB", 0, 0},
{ERE, "[^C](\\b|\\B)[^C]", "A=C", 0, 0},
{ERE, "[^C](\\b|\\B)[^C]", "ABC", 0, 0},
- {ERE, "[^C](\\b|\\B)[^C]", "=~CBD", 0, 3},
- {ERE, "[^C](\\b|\\B)[^C]", "=~\\!", 0, -1},
- {ERE, "[^C](\\b|\\B)[^C]", "=~CB", 0, -1},
+ {ERE, "[^C](\\b|\\B)[^C]", "=~CBD", 0, 0},
+ {ERE, "[^C](\\b|\\B)[^C]", "=~\\!", 0, 0},
+ {ERE, "[^C](\\b|\\B)[^C]", "=~CB", 0, 0},
{ERE, "\\b([A]|[!]|.B)", "A=AC", 0, 0},
{ERE, "\\b([A]|[!]|.B)", "=AC", 0, 1},
{ERE, "\\b([A]|[!]|.B)", "!AC", 0, 1},
diff --git a/posix/execl.c b/posix/execl.c
index 62fd45db58..12b59f9de3 100644
--- a/posix/execl.c
+++ b/posix/execl.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991,92,94,97,98,99,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1991,92,94,97,98,99,2002,2005 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
@@ -16,10 +16,10 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-#include <alloca.h>
#include <unistd.h>
#include <stdarg.h>
#include <stddef.h>
+#include <stdlib.h>
#include <string.h>
#include <stackinfo.h>
@@ -33,46 +33,44 @@
int
execl (const char *path, const char *arg, ...)
{
- size_t argv_max = 1024;
- const char **argv = alloca (argv_max * sizeof (const char *));
- unsigned int i;
+#define INITIAL_ARGV_MAX 1024
+ size_t argv_max = INITIAL_ARGV_MAX;
+ const char *initial_argv[INITIAL_ARGV_MAX];
+ const char **argv = initial_argv;
va_list args;
argv[0] = arg;
va_start (args, arg);
- i = 0;
+ unsigned int i = 0;
while (argv[i++] != NULL)
{
if (i == argv_max)
{
- const char **nptr = alloca ((argv_max *= 2) * sizeof (const char *));
-
-#ifndef _STACK_GROWS_UP
- if ((char *) nptr + argv_max == (char *) argv)
+ argv_max *= 2;
+ const char **nptr = realloc (argv == initial_argv ? NULL : argv,
+ argv_max * sizeof (const char *));
+ if (nptr == NULL)
{
- /* Stack grows down. */
- argv = (const char **) memcpy (nptr, argv,
- i * sizeof (const char *));
- argv_max += i;
+ if (argv != initial_argv)
+ free (argv);
+ return -1;
}
- else
-#endif
-#ifndef _STACK_GROWS_DOWN
- if ((char *) argv + i == (char *) nptr)
- /* Stack grows up. */
- argv_max += i;
- else
-#endif
- /* We have a hole in the stack. */
- argv = (const char **) memcpy (nptr, argv,
- i * sizeof (const char *));
+ if (argv == initial_argv)
+ /* We have to copy the already filled-in data ourselves. */
+ memcpy (nptr, argv, i * sizeof (const char *));
+
+ argv = nptr;
}
argv[i] = va_arg (args, const char *);
}
va_end (args);
- return __execve (path, (char *const *) argv, __environ);
+ int ret = __execve (path, (char *const *) argv, __environ);
+ if (argv != initial_argv)
+ free (argv);
+
+ return ret;
}
libc_hidden_def (execl)
diff --git a/posix/execle.c b/posix/execle.c
index 2199ebeb74..70522ad2e5 100644
--- a/posix/execle.c
+++ b/posix/execle.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991,97,98,99,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1991,97,98,99,2002,2005 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
@@ -16,10 +16,10 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-#include <alloca.h>
#include <unistd.h>
#include <stdarg.h>
#include <stddef.h>
+#include <stdlib.h>
#include <string.h>
#include <stackinfo.h>
@@ -29,48 +29,45 @@
int
execle (const char *path, const char *arg, ...)
{
- size_t argv_max = 1024;
- const char **argv = alloca (argv_max * sizeof (const char *));
- const char *const *envp;
- unsigned int i;
+#define INITIAL_ARGV_MAX 1024
+ size_t argv_max = INITIAL_ARGV_MAX;
+ const char *initial_argv[INITIAL_ARGV_MAX];
+ const char **argv = initial_argv;
va_list args;
argv[0] = arg;
va_start (args, arg);
- i = 0;
+ unsigned int i = 0;
while (argv[i++] != NULL)
{
if (i == argv_max)
{
- const char **nptr = alloca ((argv_max *= 2) * sizeof (const char *));
-
-#ifndef _STACK_GROWS_UP
- if ((char *) nptr + argv_max == (char *) argv)
+ argv_max *= 2;
+ const char **nptr = realloc (argv == initial_argv ? NULL : argv,
+ argv_max * sizeof (const char *));
+ if (nptr == NULL)
{
- /* Stack grows down. */
- argv = (const char **) memcpy (nptr, argv,
- i * sizeof (const char *));
- argv_max += i;
+ if (argv != initial_argv)
+ free (argv);
+ return -1;
}
- else
-#endif
-#ifndef _STACK_GROWS_DOWN
- if ((char *) argv + i == (char *) nptr)
- /* Stack grows up. */
- argv_max += i;
- else
-#endif
- /* We have a hole in the stack. */
- argv = (const char **) memcpy (nptr, argv,
- i * sizeof (const char *));
+ if (argv == initial_argv)
+ /* We have to copy the already filled-in data ourselves. */
+ memcpy (nptr, argv, i * sizeof (const char *));
+
+ argv = nptr;
}
argv[i] = va_arg (args, const char *);
}
- envp = va_arg (args, const char *const *);
+ const char *const *envp = va_arg (args, const char *const *);
va_end (args);
- return __execve (path, (char *const *) argv, (char *const *) envp);
+ int ret = __execve (path, (char *const *) argv, (char *const *) envp);
+ if (argv != initial_argv)
+ free (argv);
+
+ return ret;
}
libc_hidden_def (execle)
diff --git a/posix/execlp.c b/posix/execlp.c
index ba8fc74c90..66996a9367 100644
--- a/posix/execlp.c
+++ b/posix/execlp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991,93,96,97,98,99,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1991,93,96,97,98,99,2002,2005 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
@@ -16,10 +16,10 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-#include <alloca.h>
#include <unistd.h>
#include <stdarg.h>
#include <stddef.h>
+#include <stdlib.h>
#include <string.h>
#include <stackinfo.h>
@@ -30,46 +30,44 @@
int
execlp (const char *file, const char *arg, ...)
{
- size_t argv_max = 1024;
- const char **argv = alloca (argv_max * sizeof (const char *));
- unsigned int i;
+#define INITIAL_ARGV_MAX 1024
+ size_t argv_max = INITIAL_ARGV_MAX;
+ const char *initial_argv[INITIAL_ARGV_MAX];
+ const char **argv = initial_argv;
va_list args;
argv[0] = arg;
va_start (args, arg);
- i = 0;
+ unsigned int i = 0;
while (argv[i++] != NULL)
{
if (i == argv_max)
{
- const char **nptr = alloca ((argv_max *= 2) * sizeof (const char *));
-
-#ifndef _STACK_GROWS_UP
- if ((char *) nptr + argv_max == (char *) argv)
+ argv_max *= 2;
+ const char **nptr = realloc (argv == initial_argv ? NULL : argv,
+ argv_max * sizeof (const char *));
+ if (nptr == NULL)
{
- /* Stack grows down. */
- argv = (const char **) memcpy (nptr, argv,
- i * sizeof (const char *));
- argv_max += i;
+ if (argv != initial_argv)
+ free (argv);
+ return -1;
}
- else
-#endif
-#ifndef _STACK_GROWS_DOWN
- if ((char *) argv + i == (char *) nptr)
- /* Stack grows up. */
- argv_max += i;
- else
-#endif
- /* We have a hole in the stack. */
- argv = (const char **) memcpy (nptr, argv,
- i * sizeof (const char *));
+ if (argv == initial_argv)
+ /* We have to copy the already filled-in data ourselves. */
+ memcpy (nptr, argv, i * sizeof (const char *));
+
+ argv = nptr;
}
argv[i] = va_arg (args, const char *);
}
va_end (args);
- return execvp (file, (char *const *) argv);
+ int ret = execvp (file, (char *const *) argv);
+ if (argv != initial_argv)
+ free (argv);
+
+ return ret;
}
libc_hidden_def (execlp)
diff --git a/posix/execvp.c b/posix/execvp.c
index d6f60c02e7..9ccfd7fc22 100644
--- a/posix/execvp.c
+++ b/posix/execvp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991,92,1995-99,2002,2004 Free Software Foundation, Inc.
+/* Copyright (C) 1991,92,1995-99,2002,2004,2005 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
@@ -18,6 +18,7 @@
#include <unistd.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
@@ -26,9 +27,9 @@
/* The file is accessible but it is not an executable file. Invoke
the shell to interpret it as a script. */
-static void
+static char **
internal_function
-script_execute (const char *file, char *const argv[])
+allocate_scripts_argv (const char *file, char *const argv[])
{
/* Count the arguments. */
int argc = 0;
@@ -36,19 +37,19 @@ script_execute (const char *file, char *const argv[])
;
/* Construct an argument list for the shell. */
- {
- char *new_argv[argc + 1];
- new_argv[0] = (char *) _PATH_BSHELL;
- new_argv[1] = (char *) file;
- while (argc > 1)
- {
- new_argv[argc] = argv[argc - 1];
- --argc;
- }
-
- /* Execute the shell. */
- __execve (new_argv[0], new_argv, __environ);
- }
+ char **new_argv = (char **) malloc ((argc + 1) * sizeof (char *));
+ if (new_argv != NULL)
+ {
+ new_argv[0] = (char *) _PATH_BSHELL;
+ new_argv[1] = (char *) file;
+ while (argc > 1)
+ {
+ new_argv[argc] = argv[argc - 1];
+ --argc;
+ }
+ }
+
+ return new_argv;
}
@@ -66,42 +67,58 @@ execvp (file, argv)
return -1;
}
+ char **script_argv = NULL;
+
if (strchr (file, '/') != NULL)
{
/* Don't search when it contains a slash. */
__execve (file, argv, __environ);
if (errno == ENOEXEC)
- script_execute (file, argv);
+ {
+ script_argv = allocate_scripts_argv (file, argv);
+ if (script_argv != NULL)
+ {
+ __execve (script_argv[0], script_argv, __environ);
+
+ free (script_argv);
+ }
+ }
}
else
{
- int got_eacces = 0;
- char *path, *p, *name;
- size_t len;
- size_t pathlen;
-
- path = getenv ("PATH");
+ char *path = getenv ("PATH");
+ bool path_malloc = false;
if (path == NULL)
{
/* There is no `PATH' in the environment.
The default search path is the current directory
followed by the path `confstr' returns for `_CS_PATH'. */
- len = confstr (_CS_PATH, (char *) NULL, 0);
- path = (char *) __alloca (1 + len);
+ size_t len = confstr (_CS_PATH, (char *) NULL, 0);
+ path = (char *) malloc (1 + len);
+ if (path == NULL)
+ return -1;
path[0] = ':';
(void) confstr (_CS_PATH, path + 1, len);
+ path_malloc = true;
}
- len = strlen (file) + 1;
- pathlen = strlen (path);
- name = __alloca (pathlen + len + 1);
+ size_t len = strlen (file) + 1;
+ size_t pathlen = strlen (path);
+ char *name = malloc (pathlen + len + 1);
+ if (name == NULL)
+ {
+ if (path_malloc)
+ free (path);
+ return -1;
+ }
/* Copy the file name at the top. */
name = (char *) memcpy (name + pathlen + 1, file, len);
/* And add the slash. */
*--name = '/';
- p = path;
+ bool got_eacces = false;
+ char *p = path;
do
{
char *startp;
@@ -120,7 +137,21 @@ execvp (file, argv)
__execve (startp, argv, __environ);
if (errno == ENOEXEC)
- script_execute (startp, argv);
+ {
+ if (script_argv == NULL)
+ {
+ script_argv = allocate_scripts_argv (file, argv);
+ if (script_argv == NULL)
+ {
+ /* A possible EACCES error is not as important as
+ the ENOMEM. */
+ got_eacces = false;
+ break;
+ }
+ }
+
+ __execve (script_argv[0], script_argv, __environ);
+ }
switch (errno)
{
@@ -128,7 +159,7 @@ execvp (file, argv)
/* Record the we got a `Permission denied' error. If we end
up finding no executable we can use, we want to diagnose
that we did find one but were denied access. */
- got_eacces = 1;
+ got_eacces = true;
case ENOENT:
case ESTALE:
case ENOTDIR:
@@ -156,6 +187,11 @@ execvp (file, argv)
/* At least one failure was due to permissions, so report that
error. */
__set_errno (EACCES);
+
+ free (script_argv);
+ free (name);
+ if (path_malloc)
+ free (path);
}
/* Return the error from the last attempt (probably ENOENT). */
diff --git a/posix/getconf.c b/posix/getconf.c
index 4ce4f8e413..0cc0c0d7b5 100644
--- a/posix/getconf.c
+++ b/posix/getconf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 92, 1995-2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 1995-2003, 2004, 2005 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
@@ -964,7 +964,7 @@ main (int argc, char *argv[])
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
+"), "2005");
fprintf (stderr, gettext ("Written by %s.\n"), "Roland McGrath");
return 0;
}
diff --git a/posix/regcomp.c b/posix/regcomp.c
index 5de5bf725a..1a5f7952c3 100644
--- a/posix/regcomp.c
+++ b/posix/regcomp.c
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -33,19 +33,21 @@ static reg_errcode_t create_initial_state (re_dfa_t *dfa);
#ifdef RE_ENABLE_I18N
static void optimize_utf8 (re_dfa_t *dfa);
#endif
-struct subexp_optimize
-{
- re_dfa_t *dfa;
- re_token_t *nodes;
- int no_sub, re_nsub;
-};
-static bin_tree_t *optimize_subexps (struct subexp_optimize *so,
- bin_tree_t *node, int sidx, int depth);
-static reg_errcode_t analyze (re_dfa_t *dfa);
-static reg_errcode_t analyze_tree (re_dfa_t *dfa, bin_tree_t *node);
-static void calc_first (re_dfa_t *dfa, bin_tree_t *node);
-static void calc_next (re_dfa_t *dfa, bin_tree_t *node);
-static void calc_epsdest (re_dfa_t *dfa, bin_tree_t *node);
+static reg_errcode_t analyze (regex_t *preg);
+static reg_errcode_t create_initial_state (re_dfa_t *dfa);
+static reg_errcode_t preorder (bin_tree_t *root,
+ reg_errcode_t (fn (void *, bin_tree_t *)),
+ void *extra);
+static reg_errcode_t postorder (bin_tree_t *root,
+ reg_errcode_t (fn (void *, bin_tree_t *)),
+ void *extra);
+static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node);
+static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node);
+static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg,
+ bin_tree_t *node);
+static reg_errcode_t calc_first (void *extra, bin_tree_t *node);
+static reg_errcode_t calc_next (void *extra, bin_tree_t *node);
+static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node);
static reg_errcode_t duplicate_node_closure (re_dfa_t *dfa, int top_org_node,
int top_clone_node, int root_node,
unsigned int constraint);
@@ -56,7 +58,7 @@ static int search_duplicated_node (re_dfa_t *dfa, int org_node,
static reg_errcode_t calc_eclosure (re_dfa_t *dfa);
static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa,
int node, int root);
-static void calc_inveclosure (re_dfa_t *dfa);
+static reg_errcode_t calc_inveclosure (re_dfa_t *dfa);
static int fetch_number (re_string_t *input, re_token_t *token,
reg_syntax_t syntax);
static void fetch_token (re_token_t *result, re_string_t *input,
@@ -138,14 +140,14 @@ static bin_tree_t *build_charclass_op (re_dfa_t *dfa,
int non_match, reg_errcode_t *err);
static bin_tree_t *create_tree (re_dfa_t *dfa,
bin_tree_t *left, bin_tree_t *right,
- re_token_type_t type, int index);
-static bin_tree_t *re_dfa_add_tree_node (re_dfa_t *dfa,
- bin_tree_t *left, bin_tree_t *right,
- const re_token_t *token)
- __attribute ((noinline));
+ re_token_type_t type);
+static bin_tree_t *create_token_tree (re_dfa_t *dfa,
+ bin_tree_t *left, bin_tree_t *right,
+ const re_token_t *token);
static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa);
-static void mark_opt_subexp (const bin_tree_t *src, re_dfa_t *dfa);
-static void mark_opt_subexp_iter (const bin_tree_t *src, re_dfa_t *dfa, int idx);
+static void free_token (re_token_t *node);
+static reg_errcode_t free_tree (void *extra, bin_tree_t *node);
+static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node);
/* This table gives an error message for each of the error codes listed
in regex.h. Obviously the order here has to be same as there.
@@ -598,16 +600,7 @@ free_dfa_content (re_dfa_t *dfa)
if (dfa->nodes)
for (i = 0; i < dfa->nodes_len; ++i)
- {
- re_token_t *node = dfa->nodes + i;
-#ifdef RE_ENABLE_I18N
- if (node->type == COMPLEX_BRACKET && node->duplicated == 0)
- free_charset (node->opr.mbcset);
- else
-#endif /* RE_ENABLE_I18N */
- if (node->type == SIMPLE_BRACKET && node->duplicated == 0)
- re_free (node->opr.sbcset);
- }
+ free_token (dfa->nodes + i);
re_free (dfa->nexts);
for (i = 0; i < dfa->nodes_len; ++i)
{
@@ -811,29 +804,17 @@ re_compile_internal (preg, pattern, length, syntax)
if (BE (dfa->str_tree == NULL, 0))
goto re_compile_internal_free_return;
+ /* Analyze the tree and create the nfa. */
+ err = analyze (preg);
+ if (BE (err != REG_NOERROR, 0))
+ goto re_compile_internal_free_return;
+
#ifdef RE_ENABLE_I18N
/* If possible, do searching in single byte encoding to speed things up. */
if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL)
optimize_utf8 (dfa);
#endif
- if (preg->re_nsub > 0)
- {
- struct subexp_optimize so;
-
- so.dfa = dfa;
- so.nodes = dfa->nodes;
- so.no_sub = preg->no_sub;
- so.re_nsub = preg->re_nsub;
- dfa->str_tree = optimize_subexps (&so, dfa->str_tree, -1, 0);
- }
-
- /* Analyze the tree and collect information which is necessary to
- create the dfa. */
- err = analyze (dfa);
- if (BE (err != REG_NOERROR, 0))
- goto re_compile_internal_free_return;
-
/* Then create the initial state of the dfa. */
err = create_initial_state (dfa);
@@ -894,9 +875,9 @@ init_dfa (dfa, pat_len)
codeset_name = nl_langinfo (CODESET);
# else
codeset_name = getenv ("LC_ALL");
- if (codeset_name == NULL || codeset[0] == '\0')
+ if (codeset_name == NULL || codeset_name[0] == '\0')
codeset_name = getenv ("LC_CTYPE");
- if (codeset_name == NULL || codeset[0] == '\0')
+ if (codeset_name == NULL || codeset_name[0] == '\0')
codeset_name = getenv ("LANG");
if (codeset_name == NULL)
codeset_name = "";
@@ -998,7 +979,7 @@ create_initial_state (dfa)
/* Initial states have the epsilon closure of the node which is
the first node of the regular expression. */
- first = dfa->str_tree->first;
+ first = dfa->str_tree->first->node_idx;
dfa->init_node = first;
err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first);
if (BE (err != REG_NOERROR, 0))
@@ -1104,10 +1085,11 @@ optimize_utf8 (dfa)
case OP_ALT:
case END_OF_RE:
case OP_DUP_ASTERISK:
- case OP_DUP_QUESTION:
case OP_OPEN_SUBEXP:
case OP_CLOSE_SUBEXP:
break;
+ case COMPLEX_BRACKET:
+ return;
case SIMPLE_BRACKET:
/* Just double check. */
for (i = 0x80 / UINT_BITS; i < BITSET_UINTS; ++i)
@@ -1115,7 +1097,7 @@ optimize_utf8 (dfa)
return;
break;
default:
- return;
+ abort ();
}
if (mb_chars || has_period)
@@ -1135,90 +1117,14 @@ optimize_utf8 (dfa)
}
#endif
-static bin_tree_t *
-optimize_subexps (so, node, sidx, depth)
- struct subexp_optimize *so;
- bin_tree_t *node;
- int sidx, depth;
-{
- int idx, new_depth, new_sidx;
- bin_tree_t *ret;
- if (node == NULL)
- return NULL;
-
- new_depth = 0;
- new_sidx = sidx;
- if ((depth & 1) && node->type == CONCAT
- && node->right && node->right->type == 0
- && so->nodes[idx = node->right->node_idx].type == OP_CLOSE_SUBEXP)
- {
- new_depth = depth + 1;
- if (new_depth == 2
- || (so->nodes[idx].opr.idx < 8 * sizeof (so->dfa->used_bkref_map)
- && so->dfa->used_bkref_map & (1 << so->nodes[idx].opr.idx)))
- new_sidx = so->nodes[idx].opr.idx;
- }
- node->left = optimize_subexps (so, node->left, new_sidx, new_depth);
- new_depth = (depth & 1) == 0 && node->type == CONCAT
- && node->left && node->left->type == 0
- && so->nodes[node->left->node_idx].type == OP_OPEN_SUBEXP
- ? depth + 1 : 0;
- node->right = optimize_subexps (so, node->right, sidx, new_depth);
-
- if (node->type != CONCAT)
- return node;
- if ((depth & 1) == 0
- && node->left
- && node->left->type == 0
- && so->nodes[idx = node->left->node_idx].type == OP_OPEN_SUBEXP)
- ret = node->right;
- else if ((depth & 1)
- && node->right
- && node->right->type == 0
- && so->nodes[idx = node->right->node_idx].type == OP_CLOSE_SUBEXP)
- ret = node->left;
- else
- return node;
-
- if (so->nodes[idx].opr.idx < 8 * sizeof (so->dfa->used_bkref_map)
- && so->dfa->used_bkref_map & (1 << so->nodes[idx].opr.idx))
- return node;
-
- if (!so->no_sub)
- {
- int i;
-
- if (depth < 2)
- return node;
-
- if (so->dfa->subexp_map == NULL)
- {
- so->dfa->subexp_map = re_malloc (int, so->re_nsub);
- if (so->dfa->subexp_map == NULL)
- return node;
-
- for (i = 0; i < so->re_nsub; i++)
- so->dfa->subexp_map[i] = i;
- }
-
- i = so->nodes[idx].opr.idx;
- assert (sidx < i);
- so->dfa->subexp_map[i] = sidx;
- }
-
- so->nodes[idx].type = OP_DELETED_SUBEXP;
- ret->parent = node->parent;
- return ret;
-}
-
/* Analyze the structure tree, and calculate "first", "next", "edest",
"eclosure", and "inveclosure". */
static reg_errcode_t
-analyze (dfa)
- re_dfa_t *dfa;
+analyze (preg)
+ regex_t *preg;
{
- int i;
+ re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
reg_errcode_t ret;
/* Allocate arrays. */
@@ -1226,225 +1132,321 @@ analyze (dfa)
dfa->org_indices = re_malloc (int, dfa->nodes_alloc);
dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc);
dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc);
- dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_alloc);
if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL
- || dfa->eclosures == NULL || dfa->inveclosures == NULL, 0))
+ || dfa->eclosures == NULL, 0))
return REG_ESPACE;
- /* Initialize them. */
- for (i = 0; i < dfa->nodes_len; ++i)
+
+ dfa->subexp_map = re_malloc (int, preg->re_nsub);
+ if (dfa->subexp_map != NULL)
{
- dfa->nexts[i] = -1;
- re_node_set_init_empty (dfa->edests + i);
- re_node_set_init_empty (dfa->eclosures + i);
- re_node_set_init_empty (dfa->inveclosures + i);
+ int i;
+ for (i = 0; i < preg->re_nsub; i++)
+ dfa->subexp_map[i] = i;
+ preorder (dfa->str_tree, optimize_subexps, dfa);
+ for (i = 0; i < preg->re_nsub; i++)
+ if (dfa->subexp_map[i] != i)
+ break;
+ if (i == preg->re_nsub)
+ {
+ free (dfa->subexp_map);
+ dfa->subexp_map = NULL;
+ }
}
- ret = analyze_tree (dfa, dfa->str_tree);
- if (BE (ret == REG_NOERROR, 1))
+ ret = postorder (dfa->str_tree, lower_subexps, preg);
+ if (BE (ret != REG_NOERROR, 0))
+ return ret;
+ ret = postorder (dfa->str_tree, calc_first, dfa);
+ if (BE (ret != REG_NOERROR, 0))
+ return ret;
+ preorder (dfa->str_tree, calc_next, dfa);
+ ret = preorder (dfa->str_tree, link_nfa_nodes, dfa);
+ if (BE (ret != REG_NOERROR, 0))
+ return ret;
+ ret = calc_eclosure (dfa);
+ if (BE (ret != REG_NOERROR, 0))
+ return ret;
+
+ /* We only need this during the prune_impossible_nodes pass in regexec.c;
+ skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */
+ if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match)
+ || dfa->nbackref)
{
- ret = calc_eclosure (dfa);
- if (ret == REG_NOERROR)
- calc_inveclosure (dfa);
+ dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len);
+ if (BE (dfa->inveclosures == NULL, 0))
+ return REG_ESPACE;
+ ret = calc_inveclosure (dfa);
}
+
return ret;
}
-/* Helper functions for analyze.
- This function calculate "first", "next", and "edest" for the subtree
- whose root is NODE. */
+/* Our parse trees are very unbalanced, so we cannot use a stack to
+ implement parse tree visits. Instead, we use parent pointers and
+ some hairy code in these two functions. */
+static reg_errcode_t
+postorder (root, fn, extra)
+ bin_tree_t *root;
+ reg_errcode_t (fn (void *, bin_tree_t *));
+ void *extra;
+{
+ bin_tree_t *node, *prev;
+
+ for (node = root; ; )
+ {
+ /* Descend down the tree, preferably to the left (or to the right
+ if that's the only child). */
+ while (node->left || node->right)
+ if (node->left)
+ node = node->left;
+ else
+ node = node->right;
+
+ do
+ {
+ reg_errcode_t err = fn (extra, node);
+ if (BE (err != REG_NOERROR, 0))
+ return err;
+ if (node->parent == NULL)
+ return REG_NOERROR;
+ prev = node;
+ node = node->parent;
+ }
+ /* Go up while we have a node that is reached from the right. */
+ while (node->right == prev || node->right == NULL);
+ node = node->right;
+ }
+}
static reg_errcode_t
-analyze_tree (dfa, node)
- re_dfa_t *dfa;
+preorder (root, fn, extra)
+ bin_tree_t *root;
+ reg_errcode_t (fn (void *, bin_tree_t *));
+ void *extra;
+{
+ bin_tree_t *node;
+
+ for (node = root; ; )
+ {
+ reg_errcode_t err = fn (extra, node);
+ if (BE (err != REG_NOERROR, 0))
+ return err;
+
+ /* Go to the left node, or up and to the right. */
+ if (node->left)
+ node = node->left;
+ else
+ {
+ bin_tree_t *prev = NULL;
+ while (node->right == prev || node->right == NULL)
+ {
+ prev = node;
+ node = node->parent;
+ if (!node)
+ return REG_NOERROR;
+ }
+ node = node->right;
+ }
+ }
+}
+
+/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell
+ re_search_internal to map the inner one's opr.idx to this one's. Adjust
+ backreferences as well. Requires a preorder visit. */
+static reg_errcode_t
+optimize_subexps (extra, node)
+ void *extra;
bin_tree_t *node;
{
- reg_errcode_t ret;
- if (node->first == -1)
- calc_first (dfa, node);
- if (node->next == -1)
- calc_next (dfa, node);
- calc_epsdest (dfa, node);
+ re_dfa_t *dfa = (re_dfa_t *) extra;
- /* Calculate "first" etc. for the left child. */
- if (node->left != NULL)
+ if (node->token.type == OP_BACK_REF && dfa->subexp_map)
{
- ret = analyze_tree (dfa, node->left);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
+ int idx = node->token.opr.idx;
+ node->token.opr.idx = dfa->subexp_map[idx];
+ dfa->used_bkref_map |= 1 << node->token.opr.idx;
}
- /* Calculate "first" etc. for the right child. */
- if (node->right != NULL)
+
+ else if (node->token.type == SUBEXP
+ && node->left && node->left->token.type == SUBEXP)
{
- ret = analyze_tree (dfa, node->right);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
+ int other_idx = node->left->token.opr.idx;
+
+ node->left = node->left->left;
+ if (node->left)
+ node->left->parent = node;
+
+ dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx];
+ if (other_idx < 8 * sizeof (dfa->used_bkref_map))
+ dfa->used_bkref_map &= ~(1 << other_idx);
}
+
return REG_NOERROR;
}
-/* Calculate "first" for the node NODE. */
-static void
-calc_first (dfa, node)
- re_dfa_t *dfa;
+/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation
+ of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */
+static reg_errcode_t
+lower_subexps (extra, node)
+ void *extra;
bin_tree_t *node;
{
- int idx, type;
- idx = node->node_idx;
- type = (node->type == 0) ? dfa->nodes[idx].type : node->type;
+ regex_t *preg = (regex_t *) extra;
+ reg_errcode_t err = REG_NOERROR;
- switch (type)
+ if (node->left && node->left->token.type == SUBEXP)
{
-#ifdef DEBUG
- case OP_OPEN_BRACKET:
- case OP_CLOSE_BRACKET:
- case OP_OPEN_DUP_NUM:
- case OP_CLOSE_DUP_NUM:
- case OP_DUP_PLUS:
- case OP_NON_MATCH_LIST:
- case OP_OPEN_COLL_ELEM:
- case OP_CLOSE_COLL_ELEM:
- case OP_OPEN_EQUIV_CLASS:
- case OP_CLOSE_EQUIV_CLASS:
- case OP_OPEN_CHAR_CLASS:
- case OP_CLOSE_CHAR_CLASS:
- /* These must not appear here. */
- assert (0);
-#endif
- case END_OF_RE:
- case CHARACTER:
- case OP_PERIOD:
- case OP_DUP_ASTERISK:
- case OP_DUP_QUESTION:
-#ifdef RE_ENABLE_I18N
- case OP_UTF8_PERIOD:
- case COMPLEX_BRACKET:
-#endif /* RE_ENABLE_I18N */
- case SIMPLE_BRACKET:
- case OP_BACK_REF:
- case ANCHOR:
- case OP_OPEN_SUBEXP:
- case OP_CLOSE_SUBEXP:
- node->first = idx;
- break;
- case OP_ALT:
- node->first = idx;
- break;
- /* else fall through */
- default:
-#ifdef DEBUG
- assert (node->left != NULL);
-#endif
- if (node->left->first == -1)
- calc_first (dfa, node->left);
- node->first = node->left->first;
- break;
+ node->left = lower_subexp (&err, preg, node->left);
+ if (node->left)
+ node->left->parent = node;
+ }
+ if (node->right && node->right->token.type == SUBEXP)
+ {
+ node->right = lower_subexp (&err, preg, node->right);
+ if (node->right)
+ node->right->parent = node;
}
-}
-/* Calculate "next" for the node NODE. */
+ return err;
+}
-static void
-calc_next (dfa, node)
- re_dfa_t *dfa;
+static bin_tree_t *
+lower_subexp (err, preg, node)
+ reg_errcode_t *err;
+ regex_t *preg;
bin_tree_t *node;
{
- int idx, type;
- bin_tree_t *parent = node->parent;
- if (parent == NULL)
+ re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
+ bin_tree_t *body = node->left;
+ bin_tree_t *op, *cls, *tree1, *tree;
+
+ if (preg->no_sub
+ && (node->token.opr.idx >= 8 * sizeof (dfa->used_bkref_map)
+ || !(dfa->used_bkref_map & (1 << node->token.opr.idx))))
+ return node->left;
+
+ /* Convert the SUBEXP node to the concatenation of an
+ OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */
+ op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP);
+ cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP);
+ tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls;
+ tree = create_tree (dfa, op, tree1, CONCAT);
+ if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0))
{
- node->next = -1;
- idx = node->node_idx;
- if (node->type == 0)
- dfa->nexts[idx] = node->next;
- return;
+ *err = REG_ESPACE;
+ return NULL;
}
- idx = parent->node_idx;
- type = (parent->type == 0) ? dfa->nodes[idx].type : parent->type;
+ op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx;
+ op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp;
+ return tree;
+}
- switch (type)
+/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton
+ nodes. Requires a postorder visit. */
+static reg_errcode_t
+calc_first (extra, node)
+ void *extra;
+ bin_tree_t *node;
+{
+ re_dfa_t *dfa = (re_dfa_t *) extra;
+ if (node->token.type == CONCAT)
+ {
+ node->first = node->left->first;
+ node->node_idx = node->left->node_idx;
+ }
+ else
+ {
+ node->first = node;
+ node->node_idx = re_dfa_add_node (dfa, node->token);
+ if (BE (node->node_idx == -1, 0))
+ return REG_ESPACE;
+ }
+ return REG_NOERROR;
+}
+
+/* Pass 2: compute NEXT on the tree. Preorder visit. */
+static reg_errcode_t
+calc_next (extra, node)
+ void *extra;
+ bin_tree_t *node;
+{
+ switch (node->token.type)
{
case OP_DUP_ASTERISK:
- node->next = idx;
+ node->left->next = node;
break;
case CONCAT:
- if (parent->left == node)
- {
- if (parent->right->first == -1)
- calc_first (dfa, parent->right);
- node->next = parent->right->first;
- break;
- }
- /* else fall through */
+ node->left->next = node->right->first;
+ node->right->next = node->next;
+ break;
default:
- if (parent->next == -1)
- calc_next (dfa, parent);
- node->next = parent->next;
+ if (node->left)
+ node->left->next = node->next;
+ if (node->right)
+ node->right->next = node->next;
break;
}
- idx = node->node_idx;
- if (node->type == 0)
- dfa->nexts[idx] = node->next;
+ return REG_NOERROR;
}
-/* Calculate "edest" for the node NODE. */
-
-static void
-calc_epsdest (dfa, node)
- re_dfa_t *dfa;
+/* Pass 3: link all DFA nodes to their NEXT node (any order will do). */
+static reg_errcode_t
+link_nfa_nodes (extra, node)
+ void *extra;
bin_tree_t *node;
{
- int idx;
- idx = node->node_idx;
- if (node->type == 0)
+ re_dfa_t *dfa = (re_dfa_t *) extra;
+ int idx = node->node_idx;
+ reg_errcode_t err = REG_NOERROR;
+
+ switch (node->token.type)
{
- if (dfa->nodes[idx].type == OP_DUP_ASTERISK
- || dfa->nodes[idx].type == OP_DUP_QUESTION)
- {
- if (node->left->first == -1)
- calc_first (dfa, node->left);
- if (node->next == -1)
- calc_next (dfa, node);
- re_node_set_init_2 (dfa->edests + idx, node->left->first,
- node->next);
- }
- else if (dfa->nodes[idx].type == OP_ALT)
- {
- int left, right;
- if (node->left != NULL)
- {
- if (node->left->first == -1)
- calc_first (dfa, node->left);
- left = node->left->first;
- }
- else
- {
- if (node->next == -1)
- calc_next (dfa, node);
- left = node->next;
- }
- if (node->right != NULL)
- {
- if (node->right->first == -1)
- calc_first (dfa, node->right);
- right = node->right->first;
- }
- else
- {
- if (node->next == -1)
- calc_next (dfa, node);
- right = node->next;
- }
- re_node_set_init_2 (dfa->edests + idx, left, right);
- }
- else if (dfa->nodes[idx].type == ANCHOR
- || dfa->nodes[idx].type == OP_OPEN_SUBEXP
- || dfa->nodes[idx].type == OP_CLOSE_SUBEXP
- || dfa->nodes[idx].type == OP_BACK_REF)
- re_node_set_init_1 (dfa->edests + idx, node->next);
- else
- assert (!IS_EPSILON_NODE (dfa->nodes[idx].type));
+ case CONCAT:
+ break;
+
+ case END_OF_RE:
+ assert (node->next == NULL);
+ break;
+
+ case OP_DUP_ASTERISK:
+ case OP_ALT:
+ {
+ int left, right;
+ dfa->has_plural_match = 1;
+ if (node->left != NULL)
+ left = node->left->first->node_idx;
+ else
+ left = node->next->node_idx;
+ if (node->right != NULL)
+ right = node->right->first->node_idx;
+ else
+ right = node->next->node_idx;
+ assert (left > -1);
+ assert (right > -1);
+ err = re_node_set_init_2 (dfa->edests + idx, left, right);
+ }
+ break;
+
+ case ANCHOR:
+ case OP_OPEN_SUBEXP:
+ case OP_CLOSE_SUBEXP:
+ err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx);
+ break;
+
+ case OP_BACK_REF:
+ dfa->nexts[idx] = node->next->node_idx;
+ if (node->token.type == OP_BACK_REF)
+ re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]);
+ break;
+
+ default:
+ assert (!IS_EPSILON_NODE (node->token.type));
+ dfa->nexts[idx] = node->next->node_idx;
+ break;
}
+
+ return err;
}
/* Duplicate the epsilon closure of the node ROOT_NODE.
@@ -1520,7 +1522,7 @@ duplicate_node_closure (dfa, top_org_node, top_clone_node, root_node,
else /* dfa->edests[org_node].nelem == 2 */
{
/* In case of the node can epsilon-transit, and it has two
- destinations. E.g. '|', '*', '+', '?'. */
+ destinations. In the bin_tree_t and DFA, that's '|' and '*'. */
org_dest = dfa->edests[org_node].elems[0];
re_node_set_empty (dfa->edests + clone_node);
/* Search for a duplicated node which satisfies the constraint. */
@@ -1591,16 +1593,13 @@ duplicate_node (new_idx, dfa, org_idx, constraint)
int *new_idx, org_idx;
unsigned int constraint;
{
- int dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx], 1);
+ int dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]);
if (BE (dup_idx == -1, 0))
return REG_ESPACE;
dfa->nodes[dup_idx].constraint = constraint;
if (dfa->nodes[org_idx].type == ANCHOR)
dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type;
dfa->nodes[dup_idx].duplicated = 1;
- re_node_set_init_empty (dfa->edests + dup_idx);
- re_node_set_init_empty (dfa->eclosures + dup_idx);
- re_node_set_init_empty (dfa->inveclosures + dup_idx);
/* Store the index of the original node. */
dfa->org_indices[dup_idx] = org_idx;
@@ -1608,21 +1607,26 @@ duplicate_node (new_idx, dfa, org_idx, constraint)
return REG_NOERROR;
}
-static void
+static reg_errcode_t
calc_inveclosure (dfa)
re_dfa_t *dfa;
{
- int src, idx, dest;
+ int src, idx, ret;
+ for (idx = 0; idx < dfa->nodes_len; ++idx)
+ re_node_set_init_empty (dfa->inveclosures + idx);
+
for (src = 0; src < dfa->nodes_len; ++src)
{
- if (dfa->nodes[src].type == OP_DELETED_SUBEXP)
- continue;
+ int *elems = dfa->eclosures[src].elems;
for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx)
{
- dest = dfa->eclosures[src].elems[idx];
- re_node_set_insert_last (dfa->inveclosures + dest, src);
+ ret = re_node_set_insert_last (dfa->inveclosures + elems[idx], src);
+ if (BE (ret == -1, 0))
+ return REG_ESPACE;
}
}
+
+ return REG_NOERROR;
}
/* Calculate "eclosure" for all the node in DFA. */
@@ -1652,8 +1656,6 @@ calc_eclosure (dfa)
#ifdef DEBUG
assert (dfa->eclosures[node_idx].nelem != -1);
#endif
- if (dfa->nodes[node_idx].type == OP_DELETED_SUBEXP)
- continue;
/* If we have already calculated, skip it. */
if (dfa->eclosures[node_idx].nelem != 0)
@@ -1859,7 +1861,7 @@ peek_token (token, input, syntax)
if (!(syntax & RE_NO_GNU_OPS))
{
token->type = ANCHOR;
- token->opr.ctx_type = INSIDE_WORD;
+ token->opr.ctx_type = NOT_WORD_DELIM;
}
break;
case 'w':
@@ -2124,9 +2126,9 @@ parse (regexp, preg, syntax, err)
tree = parse_reg_exp (regexp, preg, &current_token, syntax, 0, err);
if (BE (*err != REG_NOERROR && tree == NULL, 0))
return NULL;
- eor = re_dfa_add_tree_node (dfa, NULL, NULL, &current_token);
+ eor = create_tree (dfa, NULL, NULL, END_OF_RE);
if (tree != NULL)
- root = create_tree (dfa, tree, eor, CONCAT, 0);
+ root = create_tree (dfa, tree, eor, CONCAT);
else
root = eor;
if (BE (eor == NULL || root == NULL, 0))
@@ -2163,7 +2165,6 @@ parse_reg_exp (regexp, preg, token, syntax, nest, err)
while (token->type == OP_ALT)
{
- re_token_t alt_token = *token;
fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
if (token->type != OP_ALT && token->type != END_OF_RE
&& (nest == 0 || token->type != OP_CLOSE_SUBEXP))
@@ -2174,13 +2175,12 @@ parse_reg_exp (regexp, preg, token, syntax, nest, err)
}
else
branch = NULL;
- tree = re_dfa_add_tree_node (dfa, tree, branch, &alt_token);
+ tree = create_tree (dfa, tree, branch, OP_ALT);
if (BE (tree == NULL, 0))
{
*err = REG_ESPACE;
return NULL;
}
- dfa->has_plural_match = 1;
}
return tree;
}
@@ -2219,7 +2219,7 @@ parse_branch (regexp, preg, token, syntax, nest, err)
}
if (tree != NULL && exp != NULL)
{
- tree = create_tree (dfa, tree, exp, CONCAT, 0);
+ tree = create_tree (dfa, tree, exp, CONCAT);
if (tree == NULL)
{
*err = REG_ESPACE;
@@ -2253,7 +2253,7 @@ parse_expression (regexp, preg, token, syntax, nest, err)
switch (token->type)
{
case CHARACTER:
- tree = re_dfa_add_tree_node (dfa, NULL, NULL, token);
+ tree = create_token_tree (dfa, NULL, NULL, token);
if (BE (tree == NULL, 0))
{
*err = REG_ESPACE;
@@ -2267,8 +2267,8 @@ parse_expression (regexp, preg, token, syntax, nest, err)
{
bin_tree_t *mbc_remain;
fetch_token (token, regexp, syntax);
- mbc_remain = re_dfa_add_tree_node (dfa, NULL, NULL, token);
- tree = create_tree (dfa, tree, mbc_remain, CONCAT, 0);
+ mbc_remain = create_token_tree (dfa, NULL, NULL, token);
+ tree = create_tree (dfa, tree, mbc_remain, CONCAT);
if (BE (mbc_remain == NULL || tree == NULL, 0))
{
*err = REG_ESPACE;
@@ -2295,7 +2295,7 @@ parse_expression (regexp, preg, token, syntax, nest, err)
return NULL;
}
dfa->used_bkref_map |= 1 << token->opr.idx;
- tree = re_dfa_add_tree_node (dfa, NULL, NULL, token);
+ tree = create_token_tree (dfa, NULL, NULL, token);
if (BE (tree == NULL, 0))
{
*err = REG_ESPACE;
@@ -2340,7 +2340,7 @@ parse_expression (regexp, preg, token, syntax, nest, err)
token->type = CHARACTER;
/* mb_partial and word_char bits should be initialized already
by peek_token. */
- tree = re_dfa_add_tree_node (dfa, NULL, NULL, token);
+ tree = create_token_tree (dfa, NULL, NULL, token);
if (BE (tree == NULL, 0))
{
*err = REG_ESPACE;
@@ -2349,18 +2349,27 @@ parse_expression (regexp, preg, token, syntax, nest, err)
break;
case ANCHOR:
if ((token->opr.ctx_type
- & (WORD_DELIM | INSIDE_WORD | WORD_FIRST | WORD_LAST))
+ & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST))
&& dfa->word_ops_used == 0)
init_word_char (dfa);
- if (token->opr.ctx_type == WORD_DELIM)
+ if (token->opr.ctx_type == WORD_DELIM
+ || token->opr.ctx_type == NOT_WORD_DELIM)
{
bin_tree_t *tree_first, *tree_last;
- token->opr.ctx_type = WORD_FIRST;
- tree_first = re_dfa_add_tree_node (dfa, NULL, NULL, token);
- token->opr.ctx_type = WORD_LAST;
- tree_last = re_dfa_add_tree_node (dfa, NULL, NULL, token);
- token->type = OP_ALT;
- tree = re_dfa_add_tree_node (dfa, tree_first, tree_last, token);
+ if (token->opr.ctx_type == WORD_DELIM)
+ {
+ token->opr.ctx_type = WORD_FIRST;
+ tree_first = create_token_tree (dfa, NULL, NULL, token);
+ token->opr.ctx_type = WORD_LAST;
+ }
+ else
+ {
+ token->opr.ctx_type = INSIDE_WORD;
+ tree_first = create_token_tree (dfa, NULL, NULL, token);
+ token->opr.ctx_type = INSIDE_NOTWORD;
+ }
+ tree_last = create_token_tree (dfa, NULL, NULL, token);
+ tree = create_tree (dfa, tree_first, tree_last, OP_ALT);
if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0))
{
*err = REG_ESPACE;
@@ -2369,7 +2378,7 @@ parse_expression (regexp, preg, token, syntax, nest, err)
}
else
{
- tree = re_dfa_add_tree_node (dfa, NULL, NULL, token);
+ tree = create_token_tree (dfa, NULL, NULL, token);
if (BE (tree == NULL, 0))
{
*err = REG_ESPACE;
@@ -2383,7 +2392,7 @@ parse_expression (regexp, preg, token, syntax, nest, err)
fetch_token (token, regexp, syntax);
return tree;
case OP_PERIOD:
- tree = re_dfa_add_tree_node (dfa, NULL, NULL, token);
+ tree = create_token_tree (dfa, NULL, NULL, token);
if (BE (tree == NULL, 0))
{
*err = REG_ESPACE;
@@ -2439,7 +2448,6 @@ parse_expression (regexp, preg, token, syntax, nest, err)
*err = REG_BADRPT;
return NULL;
}
- dfa->has_plural_match = 1;
}
return tree;
@@ -2462,17 +2470,10 @@ parse_sub_exp (regexp, preg, token, syntax, nest, err)
reg_errcode_t *err;
{
re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- bin_tree_t *tree, *left_par, *right_par;
+ bin_tree_t *tree;
size_t cur_nsub;
cur_nsub = preg->re_nsub++;
- left_par = re_dfa_add_tree_node (dfa, NULL, NULL, token);
- if (BE (left_par == NULL, 0))
- {
- *err = REG_ESPACE;
- return NULL;
- }
- dfa->nodes[left_par->node_idx].opr.idx = cur_nsub;
fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
/* The subexpression may be a null string. */
@@ -2481,26 +2482,20 @@ parse_sub_exp (regexp, preg, token, syntax, nest, err)
else
{
tree = parse_reg_exp (regexp, preg, token, syntax, nest, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
+ if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0))
+ *err = REG_EPAREN;
+ if (BE (*err != REG_NOERROR, 0))
return NULL;
}
- if (BE (token->type != OP_CLOSE_SUBEXP, 0))
- {
- *err = REG_EPAREN;
- return NULL;
- }
- right_par = re_dfa_add_tree_node (dfa, NULL, NULL, token);
dfa->completed_bkref_map |= 1 << cur_nsub;
- tree = ((tree == NULL) ? right_par
- : create_tree (dfa, tree, right_par, CONCAT, 0));
- tree = create_tree (dfa, left_par, tree, CONCAT, 0);
- if (BE (right_par == NULL || tree == NULL, 0))
+
+ tree = create_tree (dfa, tree, NULL, SUBEXP);
+ if (BE (tree == NULL, 0))
{
*err = REG_ESPACE;
return NULL;
}
- dfa->nodes[right_par->node_idx].opr.idx = cur_nsub;
-
+ tree->token.opr.idx = cur_nsub;
return tree;
}
@@ -2515,7 +2510,6 @@ parse_dup_op (elem, regexp, dfa, token, syntax, err)
reg_syntax_t syntax;
reg_errcode_t *err;
{
- re_token_t dup_token;
bin_tree_t *tree = NULL, *old_tree = NULL;
int i, start, end, start_idx = re_string_cur_idx (regexp);
re_token_t start_token = *token;
@@ -2578,9 +2572,13 @@ parse_dup_op (elem, regexp, dfa, token, syntax, err)
fetch_token (token, regexp, syntax);
- /* Treat "<re>{0}*" etc. as "<re>{0}". */
- if (BE (elem == NULL || (start == 0 && end == 0), 0))
+ if (BE (elem == NULL, 0))
return NULL;
+ if (BE (start == 0 && end == 0, 0))
+ {
+ postorder (elem, free_tree, NULL);
+ return NULL;
+ }
/* Extract "<re>{n,m}" to "<re><re>...<re><re>{0,<m-n>}". */
if (BE (start > 0, 0))
@@ -2589,7 +2587,7 @@ parse_dup_op (elem, regexp, dfa, token, syntax, err)
for (i = 2; i <= start; ++i)
{
elem = duplicate_tree (elem, dfa);
- tree = create_tree (dfa, tree, elem, CONCAT, 0);
+ tree = create_tree (dfa, tree, elem, CONCAT);
if (BE (elem == NULL || tree == NULL, 0))
goto parse_dup_op_espace;
}
@@ -2604,9 +2602,10 @@ parse_dup_op (elem, regexp, dfa, token, syntax, err)
else
old_tree = NULL;
- mark_opt_subexp (elem, dfa);
- dup_token.type = (end == -1 ? OP_DUP_ASTERISK : OP_DUP_QUESTION);
- tree = re_dfa_add_tree_node (dfa, elem, NULL, &dup_token);
+ if (elem->token.type == SUBEXP)
+ postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx);
+
+ tree = create_tree (dfa, elem, NULL, (end == -1 ? OP_DUP_ASTERISK : OP_ALT));
if (BE (tree == NULL, 0))
goto parse_dup_op_espace;
@@ -2616,17 +2615,17 @@ parse_dup_op (elem, regexp, dfa, token, syntax, err)
for (i = start + 2; i <= end; ++i)
{
elem = duplicate_tree (elem, dfa);
- tree = create_tree (dfa, tree, elem, CONCAT, 0);
+ tree = create_tree (dfa, tree, elem, CONCAT);
if (BE (elem == NULL || tree == NULL, 0))
goto parse_dup_op_espace;
- tree = re_dfa_add_tree_node (dfa, tree, NULL, &dup_token);
+ tree = create_tree (dfa, tree, NULL, OP_ALT);
if (BE (tree == NULL, 0))
goto parse_dup_op_espace;
}
if (old_tree)
- tree = create_tree (dfa, old_tree, tree, CONCAT, 0);
+ tree = create_tree (dfa, old_tree, tree, CONCAT);
return tree;
@@ -3282,57 +3281,59 @@ parse_bracket_exp (regexp, dfa, token, syntax, err)
/* Ensure only single byte characters are set. */
if (dfa->mb_cur_max > 1)
bitset_mask (sbcset, dfa->sb_char);
-#endif /* RE_ENABLE_I18N */
- /* Build a tree for simple bracket. */
- br_token.type = SIMPLE_BRACKET;
- br_token.opr.sbcset = sbcset;
- work_tree = re_dfa_add_tree_node (dfa, NULL, NULL, &br_token);
- if (BE (work_tree == NULL, 0))
- goto parse_bracket_exp_espace;
-
-#ifdef RE_ENABLE_I18N
if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes
|| mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes
|| mbcset->non_match)))
{
- re_token_t alt_token;
bin_tree_t *mbc_tree;
int sbc_idx;
/* Build a tree for complex bracket. */
dfa->has_mb_node = 1;
+ br_token.type = COMPLEX_BRACKET;
+ br_token.opr.mbcset = mbcset;
+ mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+ if (BE (mbc_tree == NULL, 0))
+ goto parse_bracket_exp_espace;
for (sbc_idx = 0; sbc_idx < BITSET_UINTS; ++sbc_idx)
if (sbcset[sbc_idx])
break;
/* If there are no bits set in sbcset, there is no point
of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */
- if (sbc_idx == BITSET_UINTS)
+ if (sbc_idx < BITSET_UINTS)
+ {
+ /* Build a tree for simple bracket. */
+ br_token.type = SIMPLE_BRACKET;
+ br_token.opr.sbcset = sbcset;
+ work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+ if (BE (work_tree == NULL, 0))
+ goto parse_bracket_exp_espace;
+
+ /* Then join them by ALT node. */
+ work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT);
+ if (BE (work_tree == NULL, 0))
+ goto parse_bracket_exp_espace;
+ }
+ else
{
re_free (sbcset);
- dfa->nodes[work_tree->node_idx].type = COMPLEX_BRACKET;
- dfa->nodes[work_tree->node_idx].opr.mbcset = mbcset;
- return work_tree;
+ work_tree = mbc_tree;
}
- br_token.type = COMPLEX_BRACKET;
- br_token.opr.mbcset = mbcset;
- mbc_tree = re_dfa_add_tree_node (dfa, NULL, NULL, &br_token);
- if (BE (mbc_tree == NULL, 0))
- goto parse_bracket_exp_espace;
- /* Then join them by ALT node. */
- alt_token.type = OP_ALT;
- dfa->has_plural_match = 1;
- work_tree = re_dfa_add_tree_node (dfa, work_tree, mbc_tree, &alt_token);
- if (BE (mbc_tree != NULL, 1))
- return work_tree;
}
else
+#endif /* not RE_ENABLE_I18N */
{
+#ifdef RE_ENABLE_I18N
free_charset (mbcset);
- return work_tree;
+#endif
+ /* Build a tree for simple bracket. */
+ br_token.type = SIMPLE_BRACKET;
+ br_token.opr.sbcset = sbcset;
+ work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+ if (BE (work_tree == NULL, 0))
+ goto parse_bracket_exp_espace;
}
-#else /* not RE_ENABLE_I18N */
return work_tree;
-#endif /* not RE_ENABLE_I18N */
parse_bracket_exp_espace:
*err = REG_ESPACE;
@@ -3693,26 +3694,23 @@ build_charclass_op (dfa, trans, class_name, extra, non_match, err)
/* Build a tree for simple bracket. */
br_token.type = SIMPLE_BRACKET;
br_token.opr.sbcset = sbcset;
- tree = re_dfa_add_tree_node (dfa, NULL, NULL, &br_token);
+ tree = create_token_tree (dfa, NULL, NULL, &br_token);
if (BE (tree == NULL, 0))
goto build_word_op_espace;
#ifdef RE_ENABLE_I18N
if (dfa->mb_cur_max > 1)
{
- re_token_t alt_token;
bin_tree_t *mbc_tree;
/* Build a tree for complex bracket. */
br_token.type = COMPLEX_BRACKET;
br_token.opr.mbcset = mbcset;
dfa->has_mb_node = 1;
- mbc_tree = re_dfa_add_tree_node (dfa, NULL, NULL, &br_token);
+ mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
if (BE (mbc_tree == NULL, 0))
goto build_word_op_espace;
/* Then join them by ALT node. */
- alt_token.type = OP_ALT;
- dfa->has_plural_match = 1;
- tree = re_dfa_add_tree_node (dfa, tree, mbc_tree, &alt_token);
+ tree = create_tree (dfa, tree, mbc_tree, OP_ALT);
if (BE (mbc_tree != NULL, 1))
return tree;
}
@@ -3783,12 +3781,23 @@ free_charset (re_charset_t *cset)
/* Create a tree node. */
static bin_tree_t *
-create_tree (dfa, left, right, type, index)
+create_tree (dfa, left, right, type)
re_dfa_t *dfa;
bin_tree_t *left;
bin_tree_t *right;
re_token_type_t type;
- int index;
+{
+ re_token_t t;
+ t.type = type;
+ return create_token_tree (dfa, left, right, &t);
+}
+
+static bin_tree_t *
+create_token_tree (dfa, left, right, token)
+ re_dfa_t *dfa;
+ bin_tree_t *left;
+ bin_tree_t *right;
+ const re_token_t *token;
{
bin_tree_t *tree;
if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0))
@@ -3806,11 +3815,12 @@ create_tree (dfa, left, right, type, index)
tree->parent = NULL;
tree->left = left;
tree->right = right;
- tree->type = type;
- tree->node_idx = index;
- tree->first = -1;
- tree->next = -1;
- re_node_set_init_empty (&tree->eclosure);
+ tree->token = *token;
+ tree->token.duplicated = 0;
+ tree->token.opt_subexp = 0;
+ tree->first = NULL;
+ tree->next = NULL;
+ tree->node_idx = -1;
if (left != NULL)
left->parent = tree;
@@ -3819,103 +3829,89 @@ create_tree (dfa, left, right, type, index)
return tree;
}
-/* Create both a DFA node and a tree for it. */
+/* Mark the tree SRC as an optional subexpression.
+ To be called from preorder or postorder. */
-static bin_tree_t *
-re_dfa_add_tree_node (dfa, left, right, token)
- re_dfa_t *dfa;
- bin_tree_t *left;
- bin_tree_t *right;
- const re_token_t *token;
+static reg_errcode_t
+mark_opt_subexp (extra, node)
+ void *extra;
+ bin_tree_t *node;
{
- int new_idx = re_dfa_add_node (dfa, *token, 0);
+ int idx = (int) (long) extra;
+ if (node->token.type == SUBEXP && node->token.opr.idx == idx)
+ node->token.opt_subexp = 1;
- if (new_idx == -1)
- return NULL;
-
- return create_tree (dfa, left, right, 0, new_idx);
+ return REG_NOERROR;
}
-/* Mark the tree SRC as an optional subexpression. */
+/* Free the allocated memory inside NODE. */
static void
-mark_opt_subexp (src, dfa)
- const bin_tree_t *src;
- re_dfa_t *dfa;
+free_token (re_token_t *node)
{
- /* Pass an OPT_SUBEXP_IDX which is != 1 if the duplicated tree is
- a subexpression. */
- if (src->type == CONCAT
- && src->left->type == NON_TYPE
- && dfa->nodes[src->left->node_idx].type == OP_OPEN_SUBEXP)
- mark_opt_subexp_iter (src, dfa, dfa->nodes[src->left->node_idx].opr.idx);
+#ifdef RE_ENABLE_I18N
+ if (node->type == COMPLEX_BRACKET && node->duplicated == 0)
+ free_charset (node->opr.mbcset);
+ else
+#endif /* RE_ENABLE_I18N */
+ if (node->type == SIMPLE_BRACKET && node->duplicated == 0)
+ re_free (node->opr.sbcset);
}
+/* Worker function for tree walking. Free the allocated memory inside NODE
+ and its children. */
-/* Recursive tree walker for mark_opt_subexp. */
-
-static void
-mark_opt_subexp_iter (src, dfa, idx)
- const bin_tree_t *src;
- re_dfa_t *dfa;
- int idx;
+static reg_errcode_t
+free_tree (void *extra, bin_tree_t *node)
{
- int node_idx;
-
- if (src->type == NON_TYPE)
- {
- node_idx = src->node_idx;
- if ((dfa->nodes[node_idx].type == OP_OPEN_SUBEXP
- || dfa->nodes[node_idx].type == OP_CLOSE_SUBEXP)
- && dfa->nodes[node_idx].opr.idx == idx)
- dfa->nodes[node_idx].opt_subexp = 1;
- }
-
- if (src->left != NULL)
- mark_opt_subexp_iter (src->left, dfa, idx);
-
- if (src->right != NULL)
- mark_opt_subexp_iter (src->right, dfa, idx);
+ free_token (&node->token);
+ return REG_NOERROR;
}
-/* Duplicate the node SRC, and return new node. */
+/* Duplicate the node SRC, and return new node. This is a preorder
+ visit similar to the one implemented by the generic visitor, but
+ we need more infrastructure to maintain two parallel trees --- so,
+ it's easier to duplicate. */
static bin_tree_t *
-duplicate_tree (src, dfa)
- const bin_tree_t *src;
+duplicate_tree (root, dfa)
+ const bin_tree_t *root;
re_dfa_t *dfa;
{
- bin_tree_t *left = NULL, *right = NULL, *new_tree;
- int new_node_idx;
- /* Since node indies must be according to Post-order of the tree,
- we must duplicate the left at first. */
- if (src->left != NULL)
- {
- left = duplicate_tree (src->left, dfa);
- if (left == NULL)
- return NULL;
- }
+ const bin_tree_t *node;
+ bin_tree_t *dup_root;
+ bin_tree_t **p_new = &dup_root, *dup_node = root->parent;
- /* Secondaly, duplicate the right. */
- if (src->right != NULL)
+ for (node = root; ; )
{
- right = duplicate_tree (src->right, dfa);
- if (right == NULL)
+ /* Create a new tree and link it back to the current parent. */
+ *p_new = create_token_tree (dfa, NULL, NULL, &node->token);
+ if (*p_new == NULL)
return NULL;
- }
+ (*p_new)->parent = dup_node;
+ (*p_new)->token.duplicated = 1;
+ dup_node = *p_new;
- /* At last, duplicate itself. */
- if (src->type == NON_TYPE)
- {
- new_node_idx = re_dfa_add_node (dfa, dfa->nodes[src->node_idx], 0);
- dfa->nodes[new_node_idx].duplicated = 1;
- if (BE (new_node_idx == -1, 0))
- return NULL;
+ /* Go to the left node, or up and to the right. */
+ if (node->left)
+ {
+ node = node->left;
+ p_new = &dup_node->left;
+ }
+ else
+ {
+ const bin_tree_t *prev = NULL;
+ while (node->right == prev || node->right == NULL)
+ {
+ prev = node;
+ node = node->parent;
+ dup_node = dup_node->parent;
+ if (!node)
+ return dup_root;
+ }
+ node = node->right;
+ p_new = &dup_node->right;
+ }
}
- else
- new_node_idx = src->type;
-
- new_tree = create_tree (dfa, left, right, src->type, new_node_idx);
- return new_tree;
}
diff --git a/posix/regex_internal.c b/posix/regex_internal.c
index f15cb575eb..c3295a851c 100644
--- a/posix/regex_internal.c
+++ b/posix/regex_internal.c
@@ -1330,47 +1330,44 @@ re_node_set_remove_at (set, idx)
Or return -1, if an error will be occured. */
static int
-re_dfa_add_node (dfa, token, mode)
+re_dfa_add_node (dfa, token)
re_dfa_t *dfa;
re_token_t token;
- int mode;
{
+ int type = token.type;
if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0))
{
int new_nodes_alloc = dfa->nodes_alloc * 2;
+ int *new_nexts, *new_indices;
+ re_node_set *new_edests, *new_eclosures;
+
re_token_t *new_array = re_realloc (dfa->nodes, re_token_t,
new_nodes_alloc);
if (BE (new_array == NULL, 0))
return -1;
dfa->nodes = new_array;
- if (mode)
- {
- int *new_nexts, *new_indices;
- re_node_set *new_edests, *new_eclosures, *new_inveclosures;
-
- new_nexts = re_realloc (dfa->nexts, int, new_nodes_alloc);
- new_indices = re_realloc (dfa->org_indices, int, new_nodes_alloc);
- new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc);
- new_eclosures = re_realloc (dfa->eclosures, re_node_set,
- new_nodes_alloc);
- new_inveclosures = re_realloc (dfa->inveclosures, re_node_set,
- new_nodes_alloc);
- if (BE (new_nexts == NULL || new_indices == NULL
- || new_edests == NULL || new_eclosures == NULL
- || new_inveclosures == NULL, 0))
- return -1;
- dfa->nexts = new_nexts;
- dfa->org_indices = new_indices;
- dfa->edests = new_edests;
- dfa->eclosures = new_eclosures;
- dfa->inveclosures = new_inveclosures;
- }
+ new_nexts = re_realloc (dfa->nexts, int, new_nodes_alloc);
+ new_indices = re_realloc (dfa->org_indices, int, new_nodes_alloc);
+ new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc);
+ new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc);
+ if (BE (new_nexts == NULL || new_indices == NULL
+ || new_edests == NULL || new_eclosures == NULL, 0))
+ return -1;
+ dfa->nexts = new_nexts;
+ dfa->org_indices = new_indices;
+ dfa->edests = new_edests;
+ dfa->eclosures = new_eclosures;
dfa->nodes_alloc = new_nodes_alloc;
}
dfa->nodes[dfa->nodes_len] = token;
- dfa->nodes[dfa->nodes_len].opt_subexp = 0;
- dfa->nodes[dfa->nodes_len].duplicated = 0;
dfa->nodes[dfa->nodes_len].constraint = 0;
+#ifdef RE_ENABLE_I18N
+ dfa->nodes[dfa->nodes_len].accept_mb =
+ (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET;
+#endif
+ dfa->nexts[dfa->nodes_len] = -1;
+ re_node_set_init_empty (dfa->edests + dfa->nodes_len);
+ re_node_set_init_empty (dfa->eclosures + dfa->nodes_len);
return dfa->nodes_len++;
}
@@ -1551,16 +1548,13 @@ create_ci_newstate (dfa, nodes, hash)
re_token_type_t type = node->type;
if (type == CHARACTER && !node->constraint)
continue;
+#ifdef RE_ENABLE_I18N
+ newstate->accept_mb |= node->accept_mb;
+#endif /* RE_ENABLE_I18N */
/* If the state has the halt node, the state is a halt state. */
- else if (type == END_OF_RE)
+ if (type == END_OF_RE)
newstate->halt = 1;
-#ifdef RE_ENABLE_I18N
- else if (type == COMPLEX_BRACKET
- || type == OP_UTF8_PERIOD
- || (type == OP_PERIOD && dfa->mb_cur_max > 1))
- newstate->accept_mb = 1;
-#endif /* RE_ENABLE_I18N */
else if (type == OP_BACK_REF)
newstate->has_backref = 1;
else if (type == ANCHOR || node->constraint)
@@ -1611,15 +1605,13 @@ create_cd_newstate (dfa, nodes, context, hash)
if (type == CHARACTER && !constraint)
continue;
- /* If the state has the halt node, the state is a halt state. */
- else if (type == END_OF_RE)
- newstate->halt = 1;
#ifdef RE_ENABLE_I18N
- else if (type == COMPLEX_BRACKET
- || type == OP_UTF8_PERIOD
- || (type == OP_PERIOD && dfa->mb_cur_max > 1))
- newstate->accept_mb = 1;
+ newstate->accept_mb |= node->accept_mb;
#endif /* RE_ENABLE_I18N */
+
+ /* If the state has the halt node, the state is a halt state. */
+ if (type == END_OF_RE)
+ newstate->halt = 1;
else if (type == OP_BACK_REF)
newstate->has_backref = 1;
else if (type == ANCHOR)
diff --git a/posix/regex_internal.h b/posix/regex_internal.h
index 23765c970e..f065cf449d 100644
--- a/posix/regex_internal.h
+++ b/posix/regex_internal.h
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -143,18 +143,21 @@ static inline void bitset_mask (bitset dest, const bitset src);
#define NEXT_NEWLINE_CONSTRAINT 0x0020
#define PREV_BEGBUF_CONSTRAINT 0x0040
#define NEXT_ENDBUF_CONSTRAINT 0x0080
-#define DUMMY_CONSTRAINT 0x0100
+#define WORD_DELIM_CONSTRAINT 0x0100
+#define NOT_WORD_DELIM_CONSTRAINT 0x0200
typedef enum
{
INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
+ INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
LINE_FIRST = PREV_NEWLINE_CONSTRAINT,
LINE_LAST = NEXT_NEWLINE_CONSTRAINT,
BUF_FIRST = PREV_BEGBUF_CONSTRAINT,
BUF_LAST = NEXT_ENDBUF_CONSTRAINT,
- WORD_DELIM = DUMMY_CONSTRAINT
+ WORD_DELIM = WORD_DELIM_CONSTRAINT,
+ NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT
} re_context_type;
typedef struct
@@ -186,16 +189,16 @@ typedef enum
OP_CLOSE_SUBEXP = EPSILON_BIT | 1,
OP_ALT = EPSILON_BIT | 2,
OP_DUP_ASTERISK = EPSILON_BIT | 3,
- OP_DUP_PLUS = EPSILON_BIT | 4,
- OP_DUP_QUESTION = EPSILON_BIT | 5,
- ANCHOR = EPSILON_BIT | 6,
- OP_DELETED_SUBEXP = EPSILON_BIT | 7,
+ ANCHOR = EPSILON_BIT | 4,
/* Tree type, these are used only by tree. */
CONCAT = 16,
+ SUBEXP = 17,
/* Token type, these are used only by token. */
- OP_OPEN_BRACKET = 17,
+ OP_DUP_PLUS = 18,
+ OP_DUP_QUESTION,
+ OP_OPEN_BRACKET,
OP_CLOSE_BRACKET,
OP_CHARSET_RANGE,
OP_OPEN_DUP_NUM,
@@ -284,6 +287,7 @@ typedef struct
unsigned int duplicated : 1;
unsigned int opt_subexp : 1;
#ifdef RE_ENABLE_I18N
+ unsigned int accept_mb : 1;
/* These 2 bits can be moved into the union if needed (e.g. if running out
of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */
unsigned int mb_partial : 1;
@@ -292,8 +296,6 @@ typedef struct
} re_token_t;
#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT)
-#define ACCEPT_MB_NODE(type) \
- ((type) >= OP_PERIOD && (type) <= OP_UTF8_PERIOD)
struct re_string_t
{
@@ -429,15 +431,14 @@ struct bin_tree_t
struct bin_tree_t *parent;
struct bin_tree_t *left;
struct bin_tree_t *right;
+ struct bin_tree_t *first;
+ struct bin_tree_t *next;
+
+ re_token_t token;
/* `node_idx' is the index in dfa->nodes, if `type' == 0.
Otherwise `type' indicate the type of this node. */
- re_token_type_t type;
int node_idx;
-
- int first;
- int next;
- re_node_set eclosure;
};
typedef struct bin_tree_t bin_tree_t;
@@ -677,7 +678,7 @@ static void re_node_set_remove_at (re_node_set *set, int idx) internal_function;
(re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
#define re_node_set_empty(p) ((p)->nelem = 0)
#define re_node_set_free(set) re_free ((set)->elems)
-static int re_dfa_add_node (re_dfa_t *dfa, re_token_t token, int mode) internal_function;
+static int re_dfa_add_node (re_dfa_t *dfa, re_token_t token) internal_function;
static re_dfastate_t *re_acquire_state (reg_errcode_t *err, re_dfa_t *dfa,
const re_node_set *nodes) internal_function;
static re_dfastate_t *re_acquire_state_context (reg_errcode_t *err,
diff --git a/posix/regexec.c b/posix/regexec.c
index 1b21b699e9..636396e6f7 100644
--- a/posix/regexec.c
+++ b/posix/regexec.c
@@ -605,6 +605,7 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
int left_lim, right_lim, incr;
int fl_longest_match, match_first, match_kind, match_last = -1;
+ int extra_nmatch;
int sb, ch;
#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
re_match_context_t mctx = { .dfa = dfa };
@@ -620,6 +621,9 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
mctx.dfa = dfa;
#endif
+ extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0;
+ nmatch -= extra_nmatch;
+
/* Check if the DFA haven't been compiled. */
if (BE (preg->used == 0 || dfa->init_state == NULL
|| dfa->init_state_word == NULL || dfa->init_state_nl == NULL
@@ -882,11 +886,14 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
pmatch[reg_idx].rm_so += match_first;
pmatch[reg_idx].rm_eo += match_first;
}
+ for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx)
+ {
+ pmatch[nmatch + reg_idx].rm_so = -1;
+ pmatch[nmatch + reg_idx].rm_eo = -1;
+ }
if (dfa->subexp_map)
- for (reg_idx = 0;
- reg_idx + 1 < nmatch && reg_idx < preg->re_nsub;
- reg_idx++)
+ for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++)
if (dfa->subexp_map[reg_idx] != reg_idx)
{
pmatch[reg_idx + 1].rm_so
@@ -1262,7 +1269,7 @@ proceed_next_node (mctx, nregs, regs, pidx, node, eps_via_nodes, fs)
re_token_type_t type = dfa->nodes[node].type;
#ifdef RE_ENABLE_I18N
- if (ACCEPT_MB_NODE (type))
+ if (dfa->nodes[node].accept_mb)
naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx);
else
#endif /* RE_ENABLE_I18N */
@@ -1371,7 +1378,7 @@ set_regs (preg, mctx, nmatch, pmatch, fl_backtrack)
int fl_backtrack;
{
re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- int idx, cur_node, real_nmatch;
+ int idx, cur_node;
re_node_set eps_via_nodes;
struct re_fail_stack_t *fs;
struct re_fail_stack_t fs_body = { 0, 2, NULL };
@@ -1392,15 +1399,14 @@ set_regs (preg, mctx, nmatch, pmatch, fl_backtrack)
fs = NULL;
cur_node = dfa->init_node;
- real_nmatch = (nmatch <= preg->re_nsub) ? nmatch : preg->re_nsub + 1;
re_node_set_init_empty (&eps_via_nodes);
- prev_idx_match = (regmatch_t *) alloca (sizeof (regmatch_t) * real_nmatch);
- memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * real_nmatch);
+ prev_idx_match = (regmatch_t *) alloca (sizeof (regmatch_t) * nmatch);
+ memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;)
{
- update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, real_nmatch);
+ update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch);
if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
{
@@ -1624,15 +1630,13 @@ build_sifted_states (mctx, sctx, str_idx, cur_dest)
int naccepted = 0;
int ret;
-#if defined DEBUG || defined RE_ENABLE_I18N
- re_token_type_t type = dfa->nodes[prev_node].type;
-#endif
#ifdef DEBUG
+ re_token_type_t type = dfa->nodes[prev_node].type;
assert (!IS_EPSILON_NODE (type));
#endif
#ifdef RE_ENABLE_I18N
/* If the node may accept `multi byte'. */
- if (ACCEPT_MB_NODE (type))
+ if (dfa->nodes[prev_node].accept_mb)
naccepted = sift_states_iter_mb (mctx, sctx, prev_node,
str_idx, sctx->last_str_idx);
#endif /* RE_ENABLE_I18N */
@@ -2471,10 +2475,13 @@ transit_state_mb (mctx, pstate)
{
re_node_set dest_nodes, *new_nodes;
int cur_node_idx = pstate->nodes.elems[i];
- int naccepted = 0, dest_idx;
+ int naccepted, dest_idx;
unsigned int context;
re_dfastate_t *dest_state;
+ if (!dfa->nodes[cur_node_idx].accept_mb)
+ continue;
+
if (dfa->nodes[cur_node_idx].constraint)
{
context = re_string_context_at (&mctx->input,
@@ -2486,9 +2493,8 @@ transit_state_mb (mctx, pstate)
}
/* How many bytes the node can accept? */
- if (ACCEPT_MB_NODE (dfa->nodes[cur_node_idx].type))
- naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input,
- re_string_cur_idx (&mctx->input));
+ naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input,
+ re_string_cur_idx (&mctx->input));
if (naccepted == 0)
continue;
@@ -2502,9 +2508,7 @@ transit_state_mb (mctx, pstate)
#ifdef DEBUG
assert (dfa->nexts[cur_node_idx] != -1);
#endif
- /* `cur_node_idx' may point the entity of the OP_CONTEXT_NODE,
- then we use pstate->nodes.elems[i] instead. */
- new_nodes = dfa->eclosures + dfa->nexts[pstate->nodes.elems[i]];
+ new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx];
dest_state = mctx->state_log[dest_idx];
if (dest_state == NULL)
@@ -3020,15 +3024,13 @@ check_arrival_add_next_nodes (mctx, str_idx, cur_nodes, next_nodes)
{
int naccepted = 0;
int cur_node = cur_nodes->elems[cur_idx];
-#if defined DEBUG || defined RE_ENABLE_I18N
- re_token_type_t type = dfa->nodes[cur_node].type;
-#endif
#ifdef DEBUG
+ re_token_type_t type = dfa->nodes[cur_node].type;
assert (!IS_EPSILON_NODE (type));
#endif
#ifdef RE_ENABLE_I18N
/* If the node may accept `multi byte'. */
- if (ACCEPT_MB_NODE (type))
+ if (dfa->nodes[cur_node].accept_mb)
{
naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input,
str_idx);
diff --git a/posix/rxspencer/tests b/posix/rxspencer/tests
index a724252d8c..a8b6e4baa8 100644
--- a/posix/rxspencer/tests
+++ b/posix/rxspencer/tests
@@ -526,3 +526,12 @@ a((b+|((c)*)))+d - abcd abcd c,c,c,c
(((\b))){0} - x @x -,-,-
a(((.*)))b((\2)){0}c - abc abc @bc,@bc,@bc,-,-
a(((.*)))b((\1)){0}c - axbc axbc x,x,x,-,-
+
+\b & SaT @aT
+\b & aT @aT
+a.*\b & abT ab
+\b & STSS
+\B & abc @bc
+\B & aSbTc
+\B & SaT @SaT
+\B & aSTSb @TSb
diff --git a/posix/tst-rxspencer.c b/posix/tst-rxspencer.c
index cb40421797..a68bab2de9 100644
--- a/posix/tst-rxspencer.c
+++ b/posix/tst-rxspencer.c
@@ -1,5 +1,5 @@
/* Regular expression tests.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@@ -127,14 +127,15 @@ mb_frob_string (const char *str, const char *letters)
}
/* Like mb_frob_string, but don't replace anything between
- [: and :], [. and .] or [= and =]. */
+ [: and :], [. and .] or [= and =] or characters escaped
+ with a backslash. */
static char *
mb_frob_pattern (const char *str, const char *letters)
{
char *ret, *dst;
const char *src;
- int in_class = 0;
+ int in_class = 0, escaped = 0;
if (str == NULL)
return NULL;
@@ -144,7 +145,18 @@ mb_frob_pattern (const char *str, const char *letters)
return NULL;
for (src = str, dst = ret; *src; ++src)
- if (!in_class && strchr (letters, *src))
+ if (*src == '\\')
+ {
+ escaped ^= 1;
+ *dst++ = *src;
+ }
+ else if (escaped)
+ {
+ escaped = 0;
+ *dst++ = *src;
+ continue;
+ }
+ else if (!in_class && strchr (letters, *src))
dst = mb_replace (dst, *src);
else
{
diff --git a/posix/unistd.h b/posix/unistd.h
index 06c8ca7c21..744c10c50b 100644
--- a/posix/unistd.h
+++ b/posix/unistd.h
@@ -468,7 +468,7 @@ extern char *getwd (char *__buf)
extern int dup (int __fd) __THROW __wur;
/* Duplicate FD to FD2, closing FD2 and making it open on the same file. */
-extern int dup2 (int __fd, int __fd2) __THROW __wur;
+extern int dup2 (int __fd, int __fd2) __THROW;
/* NULL-terminated array of "NAME=VALUE" environment variables. */
extern char **__environ;
diff --git a/pwd/putpwent.c b/pwd/putpwent.c
index 8b7767bd4a..a1041ec1c2 100644
--- a/pwd/putpwent.c
+++ b/pwd/putpwent.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1991,1992,1996,1997,1998,2005 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
@@ -20,7 +20,7 @@
#include <stdio.h>
#include <pwd.h>
-#define _S(x) x ? x : ""
+#define _S(x) x ?: ""
/* Write an entry to the given stream.
This must know the format of the password file. */
@@ -35,11 +35,21 @@ putpwent (p, stream)
return -1;
}
- if (fprintf (stream, "%s:%s:%lu:%lu:%s:%s:%s\n",
- p->pw_name, _S (p->pw_passwd),
- (unsigned long int) p->pw_uid, (unsigned long int) p->pw_gid,
- _S (p->pw_gecos), _S (p->pw_dir), _S (p->pw_shell)) < 0)
- return -1;
-
+ if (p->pw_name[0] == '+' || p->pw_name[0] == '-')
+ {
+ if (fprintf (stream, "%s:%s:::%s:%s:%s\n",
+ p->pw_name, _S (p->pw_passwd),
+ _S (p->pw_gecos), _S (p->pw_dir), _S (p->pw_shell)) < 0)
+ return -1;
+ }
+ else
+ {
+ if (fprintf (stream, "%s:%s:%lu:%lu:%s:%s:%s\n",
+ p->pw_name, _S (p->pw_passwd),
+ (unsigned long int) p->pw_uid,
+ (unsigned long int) p->pw_gid,
+ _S (p->pw_gecos), _S (p->pw_dir), _S (p->pw_shell)) < 0)
+ return -1;
+ }
return 0;
}
diff --git a/shadow/sgetspent_r.c b/shadow/sgetspent_r.c
index 01d22876ba..2ed350a1ad 100644
--- a/shadow/sgetspent_r.c
+++ b/shadow/sgetspent_r.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 2005 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
@@ -30,7 +30,7 @@
struct spent_data {};
/* Predicate which always returns false, needed below. */
-#define FALSE(arg) 0
+#define FALSEP(arg) 0
#include <nss/nss_files/files-parse.c>
@@ -77,7 +77,7 @@ LINE_PARSER
INT_FIELD_MAYBE_NULL (result->sp_expire, ISCOLON, 0, 10, (long int),
(long int) -1);
if (*line != '\0')
- INT_FIELD_MAYBE_NULL (result->sp_flag, FALSE, 0, 10,
+ INT_FIELD_MAYBE_NULL (result->sp_flag, FALSEP, 0, 10,
(unsigned long int), ~0ul)
else
result->sp_flag = ~0ul;
diff --git a/stdio-common/tst-fmemopen2.c b/stdio-common/tst-fmemopen2.c
index 6a0ee836a2..bcb136e8c1 100644
--- a/stdio-common/tst-fmemopen2.c
+++ b/stdio-common/tst-fmemopen2.c
@@ -1,5 +1,6 @@
#include <assert.h>
#include <stdio.h>
+#include <string.h>
#include <sys/types.h>
diff --git a/stdlib/Makefile b/stdlib/Makefile
index b766fb8656..a0c0e71704 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -92,6 +92,7 @@ CFLAGS-bsearch.c = $(uses-callbacks)
CFLAGS-msort.c = $(uses-callbacks)
CFLAGS-qsort.c = $(uses-callbacks)
CFLAGS-system.c = -fexceptions
+CFLAGS-system.os = -fomit-frame-pointer
CFLAGS-fmtmsg.c = -fexceptions
ifneq (,$(filter %REENTRANT, $(defines)))
diff --git a/stdlib/fmtmsg.c b/stdlib/fmtmsg.c
index 2ab97b7d90..b5d7436956 100644
--- a/stdlib/fmtmsg.c
+++ b/stdlib/fmtmsg.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997,1999,2000,2001,2002,2003 Free Software Foundation, Inc.
+/* Copyright (C) 1997,1999,2000-2003,2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -316,7 +316,7 @@ internal_addseverity (int severity, const char *string)
int result = MM_OK;
/* First see if there is already a record for the severity level. */
- for (runp = severity_list, lastp = NULL; runp != NULL; runp = runp-> next)
+ for (runp = severity_list, lastp = NULL; runp != NULL; runp = runp->next)
if (runp->severity == severity)
break;
else
@@ -324,9 +324,6 @@ internal_addseverity (int severity, const char *string)
if (runp != NULL)
{
- /* Release old string. */
- free ((char *) runp->string);
-
if (string != NULL)
/* Change the string. */
runp->string = string;
@@ -367,34 +364,17 @@ int
addseverity (int severity, const char *string)
{
int result;
- const char *new_string;
/* Prevent illegal SEVERITY values. */
if (severity <= MM_INFO)
return MM_NOTOK;
- if (string == NULL)
- /* We want to remove the severity class. */
- new_string = NULL;
- else
- {
- new_string = __strdup (string);
-
- if (new_string == NULL)
- /* Allocation failed or illegal value. */
- return MM_NOTOK;
- }
-
/* Protect the global data. */
__libc_lock_lock (lock);
/* Do the real work. */
result = internal_addseverity (severity, string);
- if (result != MM_OK)
- /* Free the allocated string. */
- free ((char *) new_string);
-
/* Release the lock. */
__libc_lock_unlock (lock);
@@ -411,7 +391,6 @@ libc_freeres_fn (free_mem)
{
/* This is data we have to release. */
struct severity_info *here = runp;
- free ((char *) runp->string);
runp = runp->next;
free (here);
}
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index e1d60d7619..4a1571e7db 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -596,7 +596,7 @@ __BEGIN_NAMESPACE_STD
/* Re-allocate the previously allocated block
in PTR, making the new block SIZE bytes long. */
extern void *realloc (void *__ptr, size_t __size)
- __THROW __attribute_malloc__ __wur;
+ __THROW __attribute_malloc__ __attribute_warn_unused_result__;
/* Free a block allocated by `malloc', `realloc' or `calloc'. */
extern void free (void *__ptr) __THROW;
__END_NAMESPACE_STD
diff --git a/stdlib/tst-fmtmsg.c b/stdlib/tst-fmtmsg.c
index d5369bda62..c3748d64d5 100644
--- a/stdlib/tst-fmtmsg.c
+++ b/stdlib/tst-fmtmsg.c
@@ -1,6 +1,8 @@
#include <fmtmsg.h>
#include <mcheck.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#define MM_TEST 10
@@ -12,11 +14,13 @@ main (void)
mtrace ();
- if (addseverity (MM_TEST, "TEST") != MM_OK)
+ char TEST[] = "ABCD";
+ if (addseverity (MM_TEST, TEST) != MM_OK)
{
puts ("addseverity failed");
result = 1;
}
+ strcpy (TEST, "TEST");
if (fmtmsg (MM_PRINT, "GLIBC:tst-fmtmsg", MM_HALT, "halt",
"should print message for MM_HALT", "GLIBC:tst-fmtmsg:1")
@@ -48,5 +52,31 @@ main (void)
!= MM_OK)
result = 1;
+ if (addseverity (MM_TEST, NULL) != MM_OK)
+ {
+ puts ("second addseverity failed");
+ result = 1;
+ }
+
+ if (addseverity (MM_TEST, NULL) != MM_NOTOK)
+ {
+ puts ("third addseverity unexpectedly succeeded");
+ result = 1;
+ }
+
+ char *p = strdup ("TEST2");
+ if (addseverity (MM_TEST, p) != MM_OK)
+ {
+ puts ("fourth addseverity failed");
+ result = 1;
+ }
+ if (addseverity (MM_TEST, "TEST3") != MM_OK)
+ {
+ puts ("fifth addseverity failed");
+ result = 1;
+ }
+
+ free (p);
+
return result;
}
diff --git a/sunrpc/openchild.c b/sunrpc/openchild.c
index 16f6a34e7a..29ddfa6b75 100644
--- a/sunrpc/openchild.c
+++ b/sunrpc/openchild.c
@@ -81,7 +81,7 @@ _openchild (const char *command, FILE ** fto, FILE ** ffrom)
for (i = _rpc_dtablesize () - 1; i >= 3; i--)
__close (i);
fflush (stderr);
- execlp (command, command, 0);
+ execlp (command, command, NULL);
perror ("exec");
_exit (~0);
diff --git a/sunrpc/rpc_main.c b/sunrpc/rpc_main.c
index fee83514d1..acc0132603 100644
--- a/sunrpc/rpc_main.c
+++ b/sunrpc/rpc_main.c
@@ -695,11 +695,9 @@ s_output (int argc, const char *argv[], const char *infile, const char *define,
fprintf (fout, "#include <stdio.h>\n");
fprintf (fout, "#include <stdlib.h>\n");
+ fprintf (fout, "#include <rpc/pmap_clnt.h>\n");
if (Cflag)
- {
- fprintf (fout, "#include <rpc/pmap_clnt.h>\n");
- fprintf (fout, "#include <string.h>\n");
- }
+ fprintf (fout, "#include <string.h>\n");
if (strcmp (svcclosetime, "-1") == 0)
indefinitewait = 1;
else if (strcmp (svcclosetime, "0") == 0)
diff --git a/sunrpc/svc_tcp.c b/sunrpc/svc_tcp.c
index 4decfa4fd0..873d39d52a 100644
--- a/sunrpc/svc_tcp.c
+++ b/sunrpc/svc_tcp.c
@@ -165,7 +165,7 @@ svctcp_create (int sock, u_int sendsize, u_int recvsize)
(void) __bind (sock, (struct sockaddr *) &addr, len);
}
if ((__getsockname (sock, (struct sockaddr *) &addr, &len) != 0) ||
- (__listen (sock, 2) != 0))
+ (__listen (sock, SOMAXCONN) != 0))
{
perror (_("svc_tcp.c - cannot getsockname or listen"));
if (madesock)
diff --git a/sunrpc/svc_unix.c b/sunrpc/svc_unix.c
index cfbc63866b..d95e884434 100644
--- a/sunrpc/svc_unix.c
+++ b/sunrpc/svc_unix.c
@@ -161,7 +161,7 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path)
__bind (sock, (struct sockaddr *) &addr, len);
if (__getsockname (sock, (struct sockaddr *) &addr, &len) != 0
- || __listen (sock, 2) != 0)
+ || __listen (sock, SOMAXCONN) != 0)
{
perror (_("svc_unix.c - cannot getsockname or listen"));
if (madesock)
diff --git a/sysdeps/alpha/bits/link.h b/sysdeps/alpha/bits/link.h
new file mode 100644
index 0000000000..429faff432
--- /dev/null
+++ b/sysdeps/alpha/bits/link.h
@@ -0,0 +1,69 @@
+/* Copyright (C) 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+/* Registers for entry into PLT on Alpha. */
+typedef struct La_alpha_regs
+{
+ uint64_t lr_r26;
+ uint64_t lr_sp;
+ uint64_t lr_r16;
+ uint64_t lr_r17;
+ uint64_t lr_r18;
+ uint64_t lr_r19;
+ uint64_t lr_r20;
+ uint64_t lr_r21;
+ double lr_f16;
+ double lr_f17;
+ double lr_f18;
+ double lr_f19;
+ double lr_f20;
+ double lr_f21;
+} La_alpha_regs;
+
+/* Return values for calls from PLT on Alpha. */
+typedef struct La_alpha_retval
+{
+ uint64_t lrv_r0;
+ uint64_t lrv_r1;
+ double lrv_f0;
+ double lrv_f1;
+} La_alpha_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf64_Addr la_alpha_gnu_pltenter (Elf64_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ La_alpha_regs *__regs,
+ unsigned int *__flags,
+ const char *__symname,
+ long int *__framesizep);
+extern unsigned int la_alpha_gnu_pltexit (Elf64_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ const La_alpha_regs *__inregs,
+ La_alpha_retval *__outregs,
+ const char *symname);
+
+__END_DECLS
diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h
index 780a3a57fd..4166e8c498 100644
--- a/sysdeps/alpha/dl-machine.h
+++ b/sysdeps/alpha/dl-machine.h
@@ -108,19 +108,20 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
plt = D_PTR (l, l_info[DT_PLTGOT]);
/* This function will be called to perform the relocation. */
- if (!profile)
- *(Elf64_Addr *)(plt + 16) = (Elf64_Addr) &_dl_runtime_resolve;
- else
+ if (__builtin_expect (profile, 0))
{
*(Elf64_Addr *)(plt + 16) = (Elf64_Addr) &_dl_runtime_profile;
- if (_dl_name_match_p (GLRO(dl_profile), l))
+ if (GLRO(dl_profile) != NULL
+ && _dl_name_match_p (GLRO(dl_profile), l))
{
/* This is the object we are looking for. Say that we really
want profiling and the timers are started. */
GL(dl_profile_map) = l;
}
}
+ else
+ *(Elf64_Addr *)(plt + 16) = (Elf64_Addr) &_dl_runtime_resolve;
/* Identify this shared object */
*(Elf64_Addr *)(plt + 24) = (Elf64_Addr) l;
@@ -156,143 +157,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
return lazy;
}
-/* This code is used in dl-runtime.c to call the `fixup' function
- and then redirect to the address it returns. */
-#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name, IMB) \
- extern void tramp_name (void); \
- asm ( "\
- .globl " #tramp_name " \n\
- .ent " #tramp_name " \n\
-" #tramp_name ": \n\
- lda $sp, -44*8($sp) \n\
- .frame $sp, 44*8, $26 \n\
- /* Preserve all integer registers that C normally \n\
- doesn't. */ \n\
- stq $26, 0*8($sp) \n\
- stq $0, 1*8($sp) \n\
- stq $1, 2*8($sp) \n\
- stq $2, 3*8($sp) \n\
- stq $3, 4*8($sp) \n\
- stq $4, 5*8($sp) \n\
- stq $5, 6*8($sp) \n\
- stq $6, 7*8($sp) \n\
- stq $7, 8*8($sp) \n\
- stq $8, 9*8($sp) \n\
- stq $16, 10*8($sp) \n\
- stq $17, 11*8($sp) \n\
- stq $18, 12*8($sp) \n\
- stq $19, 13*8($sp) \n\
- stq $20, 14*8($sp) \n\
- stq $21, 15*8($sp) \n\
- stq $22, 16*8($sp) \n\
- stq $23, 17*8($sp) \n\
- stq $24, 18*8($sp) \n\
- stq $25, 19*8($sp) \n\
- stq $29, 20*8($sp) \n\
- stt $f0, 21*8($sp) \n\
- stt $f1, 22*8($sp) \n\
- stt $f10, 23*8($sp) \n\
- stt $f11, 24*8($sp) \n\
- stt $f12, 25*8($sp) \n\
- stt $f13, 26*8($sp) \n\
- stt $f14, 27*8($sp) \n\
- stt $f15, 28*8($sp) \n\
- stt $f16, 29*8($sp) \n\
- stt $f17, 30*8($sp) \n\
- stt $f18, 31*8($sp) \n\
- stt $f19, 32*8($sp) \n\
- stt $f20, 33*8($sp) \n\
- stt $f21, 34*8($sp) \n\
- stt $f22, 35*8($sp) \n\
- stt $f23, 36*8($sp) \n\
- stt $f24, 37*8($sp) \n\
- stt $f25, 38*8($sp) \n\
- stt $f26, 39*8($sp) \n\
- stt $f27, 40*8($sp) \n\
- stt $f28, 41*8($sp) \n\
- stt $f29, 42*8($sp) \n\
- stt $f30, 43*8($sp) \n\
- .mask 0x27ff01ff, -44*8 \n\
- .fmask 0xfffffc03, -(44-21)*8 \n\
- /* Set up our $gp */ \n\
- br $gp, .+4 \n\
- ldgp $gp, 0($gp) \n\
- .prologue 0 \n\
- /* Set up the arguments for fixup: */ \n\
- /* $16 = link_map out of plt0 */ \n\
- /* $17 = offset of reloc entry = ($28 - $27 - 20) /12 * 24 */\n\
- /* $18 = return address */ \n\
- subq $28, $27, $17 \n\
- ldq $16, 8($27) \n\
- subq $17, 20, $17 \n\
- mov $26, $18 \n\
- addq $17, $17, $17 \n\
- /* Do the fixup */ \n\
- bsr $26, " #fixup_name " !samegp \n\
- /* Move the destination address into position. */ \n\
- mov $0, $27 \n\
- /* Restore program registers. */ \n\
- ldq $26, 0*8($sp) \n\
- ldq $0, 1*8($sp) \n\
- ldq $1, 2*8($sp) \n\
- ldq $2, 3*8($sp) \n\
- ldq $3, 4*8($sp) \n\
- ldq $4, 5*8($sp) \n\
- ldq $5, 6*8($sp) \n\
- ldq $6, 7*8($sp) \n\
- ldq $7, 8*8($sp) \n\
- ldq $8, 9*8($sp) \n\
- ldq $16, 10*8($sp) \n\
- ldq $17, 11*8($sp) \n\
- ldq $18, 12*8($sp) \n\
- ldq $19, 13*8($sp) \n\
- ldq $20, 14*8($sp) \n\
- ldq $21, 15*8($sp) \n\
- ldq $22, 16*8($sp) \n\
- ldq $23, 17*8($sp) \n\
- ldq $24, 18*8($sp) \n\
- ldq $25, 19*8($sp) \n\
- ldq $29, 20*8($sp) \n\
- ldt $f0, 21*8($sp) \n\
- ldt $f1, 22*8($sp) \n\
- ldt $f10, 23*8($sp) \n\
- ldt $f11, 24*8($sp) \n\
- ldt $f12, 25*8($sp) \n\
- ldt $f13, 26*8($sp) \n\
- ldt $f14, 27*8($sp) \n\
- ldt $f15, 28*8($sp) \n\
- ldt $f16, 29*8($sp) \n\
- ldt $f17, 30*8($sp) \n\
- ldt $f18, 31*8($sp) \n\
- ldt $f19, 32*8($sp) \n\
- ldt $f20, 33*8($sp) \n\
- ldt $f21, 34*8($sp) \n\
- ldt $f22, 35*8($sp) \n\
- ldt $f23, 36*8($sp) \n\
- ldt $f24, 37*8($sp) \n\
- ldt $f25, 38*8($sp) \n\
- ldt $f26, 39*8($sp) \n\
- ldt $f27, 40*8($sp) \n\
- ldt $f28, 41*8($sp) \n\
- ldt $f29, 42*8($sp) \n\
- ldt $f30, 43*8($sp) \n\
- /* Flush the Icache after having modified the .plt code. */\n\
- " #IMB " \n\
- /* Clean up and turn control to the destination */ \n\
- lda $sp, 44*8($sp) \n\
- jmp $31, ($27) \n\
- .end " #tramp_name)
-
-#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, imb); \
- 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;
its return value is the user program's entry point. */
@@ -501,9 +365,13 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
return value + reloc->r_addend;
}
+/* Names of the architecture-specific auditing callback functions. */
+#define ARCH_LA_PLTENTER alpha_gnu_pltenter
+#define ARCH_LA_PLTEXIT alpha_gnu_pltexit
+
#endif /* !dl_machine_h */
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
MAP is the object containing the reloc. */
@@ -555,26 +423,16 @@ elf_machine_rela (struct link_map *map,
return;
else
{
+ struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
Elf64_Addr sym_value;
Elf64_Addr sym_raw_value;
-#if defined USE_TLS && !defined RTLD_BOOTSTRAP
- struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
sym_raw_value = sym_value = reloc->r_addend;
- if (sym)
+ if (sym_map)
{
sym_raw_value += sym->st_value;
sym_value = sym_raw_value + sym_map->l_addr;
}
-#else
- Elf64_Addr loadbase = RESOLVE (&sym, version, r_type);
- sym_raw_value = sym_value = reloc->r_addend;
- if (sym)
- {
- sym_raw_value += sym->st_value;
- sym_value = sym_raw_value + loadbase;
- }
-#endif
if (r_type == R_ALPHA_GLOB_DAT)
*reloc_addr = sym_value;
@@ -680,4 +538,4 @@ elf_machine_lazy_rel (struct link_map *map,
_dl_reloc_bad_type (map, r_type, 1);
}
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/alpha/dl-trampoline.S b/sysdeps/alpha/dl-trampoline.S
new file mode 100644
index 0000000000..42350836ef
--- /dev/null
+++ b/sysdeps/alpha/dl-trampoline.S
@@ -0,0 +1,361 @@
+/* PLT trampolines. Alpha version.
+ Copyright (C) 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+
+ .set noat
+
+ .globl _dl_runtime_resolve
+ .ent _dl_runtime_resolve
+
+#undef FRAMESIZE
+#define FRAMESIZE 44*8
+
+_dl_runtime_resolve:
+ lda $30, -FRAMESIZE($30)
+ .frame $30, FRAMESIZE, $26
+ /* Preserve all registers that C normally doesn't. */
+ stq $26, 0*8($30)
+ stq $0, 1*8($30)
+ stq $1, 2*8($30)
+ stq $2, 3*8($30)
+ stq $3, 4*8($30)
+ stq $4, 5*8($30)
+ stq $5, 6*8($30)
+ stq $6, 7*8($30)
+ stq $7, 8*8($30)
+ stq $8, 9*8($30)
+ stq $16, 10*8($30)
+ stq $17, 11*8($30)
+ stq $18, 12*8($30)
+ stq $19, 13*8($30)
+ stq $20, 14*8($30)
+ stq $21, 15*8($30)
+ stq $22, 16*8($30)
+ stq $23, 17*8($30)
+ stq $24, 18*8($30)
+ stq $25, 19*8($30)
+ stq $29, 20*8($30)
+ stt $f0, 21*8($30)
+ stt $f1, 22*8($30)
+ stt $f10, 23*8($30)
+ stt $f11, 24*8($30)
+ stt $f12, 25*8($30)
+ stt $f13, 26*8($30)
+ stt $f14, 27*8($30)
+ stt $f15, 28*8($30)
+ stt $f16, 29*8($30)
+ stt $f17, 30*8($30)
+ stt $f18, 31*8($30)
+ stt $f19, 32*8($30)
+ stt $f20, 33*8($30)
+ stt $f21, 34*8($30)
+ stt $f22, 35*8($30)
+ stt $f23, 36*8($30)
+ stt $f24, 37*8($30)
+ stt $f25, 38*8($30)
+ stt $f26, 39*8($30)
+ stt $f27, 40*8($30)
+ stt $f28, 41*8($30)
+ stt $f29, 42*8($30)
+ stt $f30, 43*8($30)
+ .mask 0x27ff01ff, -FRAMESIZE
+ .fmask 0xfffffc03, -FRAMESIZE+21*8
+ /* Set up our GP. */
+ br $29, .+4
+ ldgp $29, 0($29)
+ .prologue 0
+ /* Set up the arguments for _dl_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
+ bsr $26, _dl_fixup !samegp
+
+ /* Move the destination address into position. */
+ mov $0, $27
+ /* Restore program registers. */
+ ldq $26, 0*8($30)
+ ldq $0, 1*8($30)
+ ldq $1, 2*8($30)
+ ldq $2, 3*8($30)
+ ldq $3, 4*8($30)
+ ldq $4, 5*8($30)
+ ldq $5, 6*8($30)
+ ldq $6, 7*8($30)
+ ldq $7, 8*8($30)
+ ldq $8, 9*8($30)
+ ldq $16, 10*8($30)
+ ldq $17, 11*8($30)
+ ldq $18, 12*8($30)
+ ldq $19, 13*8($30)
+ ldq $20, 14*8($30)
+ ldq $21, 15*8($30)
+ ldq $22, 16*8($30)
+ ldq $23, 17*8($30)
+ ldq $24, 18*8($30)
+ ldq $25, 19*8($30)
+ ldq $29, 20*8($30)
+ ldt $f0, 21*8($30)
+ ldt $f1, 22*8($30)
+ ldt $f10, 23*8($30)
+ ldt $f11, 24*8($30)
+ ldt $f12, 25*8($30)
+ ldt $f13, 26*8($30)
+ ldt $f14, 27*8($30)
+ ldt $f15, 28*8($30)
+ ldt $f16, 29*8($30)
+ ldt $f17, 30*8($30)
+ ldt $f18, 31*8($30)
+ ldt $f19, 32*8($30)
+ ldt $f20, 33*8($30)
+ ldt $f21, 34*8($30)
+ ldt $f22, 35*8($30)
+ ldt $f23, 36*8($30)
+ ldt $f24, 37*8($30)
+ ldt $f25, 38*8($30)
+ ldt $f26, 39*8($30)
+ ldt $f27, 40*8($30)
+ ldt $f28, 41*8($30)
+ ldt $f29, 42*8($30)
+ ldt $f30, 43*8($30)
+ /* Flush the Icache after having modified the .plt code. */
+ imb
+ /* Clean up and turn control to the destination */
+ lda $30, FRAMESIZE($30)
+ jmp $31, ($27)
+
+ .end _dl_runtime_resolve
+
+ .globl _dl_runtime_profile
+ .usepv _dl_runtime_profile, no
+ .type _dl_runtime_profile, @function
+
+ /* We save the registers in a different order than desired by
+ .mask/.fmask, so we have to use explicit cfi directives. */
+ cfi_startproc
+
+.macro savei regno, offset
+ stq $\regno, \offset($30)
+ cfi_rel_offset(\regno, \offset)
+.endm
+
+.macro savef regno, offset
+ stt $f\regno, \offset($30)
+ cfi_rel_offset(\regno+32, \offset)
+.endm
+
+#undef FRAMESIZE
+#define FRAMESIZE 50*8
+
+_dl_runtime_profile:
+ lda $30, -FRAMESIZE($30)
+ cfi_adjust_cfa_offset (FRAMESIZE)
+
+ /* Preserve all argument registers. This also constructs the
+ La_alpha_regs structure. */
+ savei 26, 0*8
+ savei 16, 2*8
+ savei 17, 3*8
+ savei 18, 4*8
+ savei 19, 5*8
+ savei 20, 6*8
+ savei 21, 7*8
+ lda $16, FRAMESIZE($30)
+ savef 16, 8*8
+ savef 17, 9*8
+ savef 18, 10*8
+ savef 19, 11*8
+ savef 20, 12*8
+ savef 21, 13*8
+ stq $16, 1*8($30)
+
+ /* Preserve all registers that C normally doesn't. */
+ savei 0, 14*8
+ savei 1, 15*8
+ savei 2, 16*8
+ savei 3, 17*8
+ savei 4, 18*8
+ savei 5, 19*8
+ savei 6, 20*8
+ savei 7, 21*8
+ savei 8, 22*8
+ savei 22, 23*8
+ savei 23, 24*8
+ savei 24, 25*8
+ savei 25, 26*8
+ savei 29, 27*8
+ savef 0, 28*8
+ savef 1, 29*8
+ savef 10, 30*8
+ savef 11, 31*8
+ savef 12, 32*8
+ savef 13, 33*8
+ savef 14, 34*8
+ savef 15, 35*8
+ savef 22, 36*8
+ savef 23, 37*8
+ savef 24, 38*8
+ savef 25, 39*8
+ savef 26, 40*8
+ savef 27, 41*8
+ savef 28, 42*8
+ savef 29, 43*8
+ savef 30, 44*8
+
+ /* Set up our GP. */
+ br $29, .+4
+ ldgp $29, 0($29)
+
+ /* Set up the arguments for _dl_profile_fixup:
+ $16 = link_map out of plt0
+ $17 = offset of reloc entry = ($28 - $27 - 20) /12 * 24
+ $18 = return address
+ $19 = La_alpha_regs address
+ $20 = framesize address
+ */
+ subq $28, $27, $17
+ ldq $16, 8($27)
+ subq $17, 20, $17
+ mov $26, $18
+ addq $17, $17, $17
+ lda $19, 0($30)
+ lda $20, 45*8($30)
+ stq $16, 48*8($30)
+ stq $17, 49*8($30)
+
+ bsr $26, _dl_profile_fixup !samegp
+
+ /* Discover if we're wrapping this call. */
+ ldq $18, 45*8($30)
+ bge $18, 1f
+
+ /* Move the destination address into position. */
+ mov $0, $27
+ /* Restore program registers. */
+ ldq $26, 0*8($30)
+ ldq $16, 2*8($30)
+ ldq $17, 3*8($30)
+ ldq $18, 4*8($30)
+ ldq $19, 5*8($30)
+ ldq $20, 6*8($30)
+ ldq $21, 7*8($30)
+ ldt $f16, 8*8($30)
+ ldt $f17, 9*8($30)
+ ldt $f18, 10*8($30)
+ ldt $f19, 11*8($30)
+ ldt $f20, 12*8($30)
+ ldt $f21, 13*8($30)
+ ldq $0, 14*8($30)
+ ldq $1, 15*8($30)
+ ldq $2, 16*8($30)
+ ldq $3, 17*8($30)
+ ldq $4, 18*8($30)
+ ldq $5, 19*8($30)
+ ldq $6, 20*8($30)
+ ldq $7, 21*8($30)
+ ldq $8, 22*8($30)
+ ldq $22, 23*8($30)
+ ldq $23, 24*8($30)
+ ldq $24, 25*8($30)
+ ldq $25, 26*8($30)
+ ldq $29, 27*8($30)
+ ldt $f0, 28*8($30)
+ ldt $f1, 29*8($30)
+ ldt $f10, 30*8($30)
+ ldt $f11, 31*8($30)
+ ldt $f12, 32*8($30)
+ ldt $f13, 33*8($30)
+ ldt $f14, 34*8($30)
+ ldt $f15, 35*8($30)
+ ldt $f22, 36*8($30)
+ ldt $f23, 37*8($30)
+ ldt $f24, 38*8($30)
+ ldt $f25, 39*8($30)
+ ldt $f26, 40*8($30)
+ ldt $f27, 41*8($30)
+ ldt $f28, 42*8($30)
+ ldt $f29, 43*8($30)
+ ldt $f30, 44*8($30)
+
+ /* Clean up and turn control to the destination. */
+ lda $30, FRAMESIZE($30)
+ jmp $31, ($27)
+
+1:
+ /* Create a frame pointer and allocate a new argument frame. */
+ savei 15, 45*8
+ mov $30, $15
+ cfi_def_cfa_register (15)
+ addq $18, 15, $18
+ bic $18, 15, $18
+ subq $30, $18, $30
+
+ /* Save the call destination around memcpy. */
+ stq $0, 46*8($30)
+
+ /* Copy the stack arguments into place. */
+ lda $16, 0($30)
+ lda $17, FRAMESIZE($15)
+ jsr $26, memcpy
+ ldgp $29, 0($26)
+
+ /* Reload the argument registers. */
+ ldq $27, 46*8($30)
+ ldq $16, 2*8($15)
+ ldq $17, 3*8($15)
+ ldq $18, 4*8($15)
+ ldq $19, 5*8($15)
+ ldq $20, 6*8($15)
+ ldq $21, 7*8($15)
+ ldt $f16, 8*8($15)
+ ldt $f17, 9*8($15)
+ ldt $f18, 10*8($15)
+ ldt $f19, 11*8($15)
+ ldt $f20, 12*8($15)
+ ldt $f21, 13*8($15)
+
+ jsr $26, ($27), 0
+ ldgp $29, 0($26)
+
+ /* Set up for call to _dl_call_pltexit. */
+ ldq $16, 48($15)
+ ldq $17, 49($15)
+ stq $0, 46*8($15)
+ lda $18, 0($15)
+ stq $1, 47*8($15)
+ lda $19, 46*8($15)
+ stt $f0, 48*8($15)
+ stt $f1, 49*8($15)
+ bsr $26, _dl_call_pltexit !samegp
+
+ mov $15, $30
+ cfi_def_cfa_register (30)
+ ldq $26, 0($30)
+ ldq $15, 45*8($30)
+ lda $30, FRAMESIZE($30)
+ ret
+
+ cfi_endproc
+ .size _dl_runtime_profile, .-_dl_runtime_profile
diff --git a/sysdeps/alpha/fpu/bits/mathinline.h b/sysdeps/alpha/fpu/bits/mathinline.h
index 187bd42f33..87d40058c3 100644
--- a/sysdeps/alpha/fpu/bits/mathinline.h
+++ b/sysdeps/alpha/fpu/bits/mathinline.h
@@ -46,7 +46,8 @@
#if (!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
&& defined __OPTIMIZE__
-#define __inline_copysign(NAME, TYPE) \
+#if !__GNUC_PREREQ (4, 0)
+# define __inline_copysign(NAME, TYPE) \
__MATH_INLINE TYPE \
__NTH (NAME (TYPE __x, TYPE __y)) \
{ \
@@ -60,19 +61,11 @@ __inline_copysign (copysignf, float)
__inline_copysign (__copysign, double)
__inline_copysign (copysign, double)
-#undef __MATH_INLINE_copysign
+# undef __inline_copysign
+#endif
-#if __GNUC_PREREQ (2, 8)
-__MATH_INLINE float
-__NTH (__fabsf (float __x)) { return __builtin_fabsf (__x); }
-__MATH_INLINE float
-__NTH (fabsf (float __x)) { return __builtin_fabsf (__x); }
-__MATH_INLINE double
-__NTH (__fabs (double __x)) { return __builtin_fabs (__x); }
-__MATH_INLINE double
-__NTH (fabs (double __x)) { return __builtin_fabs (__x); }
-#else
+#if !__GNUC_PREREQ (2, 8)
# define __inline_fabs(NAME, TYPE) \
__MATH_INLINE TYPE \
__NTH (NAME (TYPE __x)) \
diff --git a/sysdeps/alpha/libc-tls.c b/sysdeps/alpha/libc-tls.c
index 434d5d9313..a3b68e928f 100644
--- a/sysdeps/alpha/libc-tls.c
+++ b/sysdeps/alpha/libc-tls.c
@@ -31,7 +31,7 @@ void *
__tls_get_addr (tls_index *ti)
{
dtv_t *dtv = THREAD_DTV ();
- return (char *) dtv[1].pointer + ti->ti_offset;
+ return (char *) dtv[1].pointer.val + ti->ti_offset;
}
#endif
diff --git a/sysdeps/arm/bits/link.h b/sysdeps/arm/bits/link.h
index 648976d7d2..e69de29bb2 100644
--- a/sysdeps/arm/bits/link.h
+++ b/sysdeps/arm/bits/link.h
@@ -1,4 +0,0 @@
-struct link_map_machine
- {
- Elf32_Addr plt; /* Address of .plt */
- };
diff --git a/sysdeps/arm/bits/linkmap.h b/sysdeps/arm/bits/linkmap.h
new file mode 100644
index 0000000000..648976d7d2
--- /dev/null
+++ b/sysdeps/arm/bits/linkmap.h
@@ -0,0 +1,4 @@
+struct link_map_machine
+ {
+ Elf32_Addr plt; /* Address of .plt */
+ };
diff --git a/sysdeps/generic/bits/link.h b/sysdeps/generic/bits/link.h
index 470b4d3e5f..6b4f811c25 100644
--- a/sysdeps/generic/bits/link.h
+++ b/sysdeps/generic/bits/link.h
@@ -1,4 +1 @@
-struct link_map_machine
- {
- /* empty by default */
- };
+#error "Architecture-specific definition needed."
diff --git a/sysdeps/generic/bits/linkmap.h b/sysdeps/generic/bits/linkmap.h
new file mode 100644
index 0000000000..470b4d3e5f
--- /dev/null
+++ b/sysdeps/generic/bits/linkmap.h
@@ -0,0 +1,4 @@
+struct link_map_machine
+ {
+ /* empty by default */
+ };
diff --git a/sysdeps/generic/dl-fptr.h b/sysdeps/generic/dl-fptr.h
index 8156981e6e..d47fb7b635 100644
--- a/sysdeps/generic/dl-fptr.h
+++ b/sysdeps/generic/dl-fptr.h
@@ -36,6 +36,8 @@ struct fdesc_table
struct fdesc fdesc[0];
};
+struct link_map;
+
extern ElfW(Addr) _dl_boot_fptr_table [];
extern ElfW(Addr) _dl_make_fptr (struct link_map *, const ElfW(Sym) *,
diff --git a/sysdeps/generic/dl-lookupcfg.h b/sysdeps/generic/dl-lookupcfg.h
index f48cb0a844..2b29989600 100644
--- a/sysdeps/generic/dl-lookupcfg.h
+++ b/sysdeps/generic/dl-lookupcfg.h
@@ -1,5 +1,5 @@
/* Configuration of lookup functions.
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004 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
@@ -17,16 +17,13 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-/* Some platforms need more information from the symbol lookup function
- than just the address. But this is not generally the case.
-
- However, because of how _dl_sym and _dl_tls_symaddr are written, every
- platform needs it when we support TLS. */
-
-#include <tls.h> /* Defines USE_TLS (or doesn't). */
-
-#ifdef USE_TLS
-# define DL_LOOKUP_RETURNS_MAP
-#else
-# undef DL_LOOKUP_RETURNS_MAP
-#endif
+/* The type of the return value of fixup/profile_fixup. */
+#define DL_FIXUP_VALUE_TYPE ElfW(Addr)
+/* Construct a value of type DL_FIXUP_VALUE_TYPE from a code address
+ and a link map. */
+#define DL_FIXUP_MAKE_VALUE(map, addr) (addr)
+/* Extract the code address from a value of type DL_FIXUP_MAKE_VALUE.
+ */
+#define DL_FIXUP_VALUE_CODE_ADDR(value) (value)
+#define DL_FIXUP_VALUE_ADDR(value) (value)
+#define DL_FIXUP_ADDR_VALUE(addr) (addr)
diff --git a/sysdeps/generic/dl-tls.c b/sysdeps/generic/dl-tls.c
index 2282dda9cc..099742ceff 100644
--- a/sysdeps/generic/dl-tls.c
+++ b/sysdeps/generic/dl-tls.c
@@ -1,5 +1,5 @@
/* Thread-local storage handling in the ELF dynamic linker. Generic version.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 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
@@ -18,6 +18,8 @@
02111-1307 USA. */
#include <assert.h>
+#include <errno.h>
+#include <libintl.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
@@ -65,7 +67,10 @@ _dl_next_tls_modid (void)
/* Note that this branch will never be executed during program
start since there are no gaps at that time. Therefore it
does not matter that the dl_tls_dtv_slotinfo is not allocated
- yet when the function is called for the first times. */
+ yet when the function is called for the first times.
+
+ NB: the offset +1 is due to the fact that DTV[0] is used
+ for something else. */
result = GL(dl_tls_static_nelem) + 1;
/* If the following would not be true we mustn't have assumed
there is a gap. */
@@ -88,11 +93,11 @@ _dl_next_tls_modid (void)
}
while ((runp = runp->next) != NULL);
- if (result >= GL(dl_tls_max_dtv_idx))
+ if (result > GL(dl_tls_max_dtv_idx))
{
/* The new index must indeed be exactly one higher than the
previous high. */
- assert (result == GL(dl_tls_max_dtv_idx));
+ assert (result == GL(dl_tls_max_dtv_idx) + 1);
/* There is no gap anymore. */
GL(dl_tls_dtv_gaps) = false;
@@ -116,10 +121,9 @@ void
internal_function
_dl_determine_tlsoffset (void)
{
- struct dtv_slotinfo *slotinfo;
size_t max_align = TLS_TCB_ALIGN;
- size_t offset, freetop = 0, freebottom = 0;
- size_t cnt;
+ size_t freetop = 0;
+ size_t freebottom = 0;
/* The first element of the dtv slot info list is allocated. */
assert (GL(dl_tls_dtv_slotinfo_list) != NULL);
@@ -127,7 +131,7 @@ _dl_determine_tlsoffset (void)
dl_tls_dtv_slotinfo_list list. */
assert (GL(dl_tls_dtv_slotinfo_list)->next == NULL);
- slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo;
+ struct dtv_slotinfo *slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo;
/* Determining the offset of the various parts of the static TLS
block has several dependencies. In addition we have to work
@@ -159,9 +163,9 @@ _dl_determine_tlsoffset (void)
# if TLS_TCB_AT_TP
/* We simply start with zero. */
- offset = 0;
+ size_t offset = 0;
- for (cnt = 1; slotinfo[cnt].map != NULL; ++cnt)
+ for (size_t cnt = 0; slotinfo[cnt].map != NULL; ++cnt)
{
assert (cnt < GL(dl_tls_dtv_slotinfo_list)->len);
@@ -206,9 +210,9 @@ _dl_determine_tlsoffset (void)
+ TLS_TCB_SIZE);
# elif TLS_DTV_AT_TP
/* The TLS blocks start right after the TCB. */
- offset = TLS_TCB_SIZE;
+ size_t offset = TLS_TCB_SIZE;
- for (cnt = 1; slotinfo[cnt].map != NULL; ++cnt)
+ for (size_t cnt = 0; slotinfo[cnt].map != NULL; ++cnt)
{
assert (cnt < GL(dl_tls_dtv_slotinfo_list)->len);
@@ -225,8 +229,8 @@ _dl_determine_tlsoffset (void)
if (off + slotinfo[cnt].map->l_tls_blocksize - firstbyte <= freetop)
{
slotinfo[cnt].map->l_tls_offset = off - firstbyte;
- freebottom = off + slotinfo[cnt].map->l_tls_blocksize
- - firstbyte;
+ freebottom = (off + slotinfo[cnt].map->l_tls_blocksize
+ - firstbyte);
continue;
}
}
@@ -357,14 +361,14 @@ _dl_allocate_tls_storage (void)
/* Clear the TCB data structure. We can't ask the caller (i.e.
libpthread) to do it, because we will initialize the DTV et al. */
- memset (result, 0, TLS_TCB_SIZE);
+ memset (result, '\0', TLS_TCB_SIZE);
# elif TLS_DTV_AT_TP
result = (char *) result + size - GL(dl_tls_static_size);
/* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before it.
We can't ask the caller (i.e. libpthread) to do it, because we will
initialize the DTV et al. */
- memset ((char *) result - TLS_PRE_TCB_SIZE, 0,
+ memset ((char *) result - TLS_PRE_TCB_SIZE, '\0',
TLS_PRE_TCB_SIZE + TLS_TCB_SIZE);
# endif
@@ -388,10 +392,11 @@ _dl_allocate_tls_init (void *result)
dtv_t *dtv = GET_DTV (result);
struct dtv_slotinfo_list *listp;
size_t total = 0;
+ size_t maxgen = 0;
- /* We have to look prepare the dtv for all currently loaded
- modules using TLS. For those which are dynamically loaded we
- add the values indicating deferred allocation. */
+ /* We have to prepare the dtv for all currently loaded modules using
+ TLS. For those which are dynamically loaded we add the values
+ indicating deferred allocation. */
listp = GL(dl_tls_dtv_slotinfo_list);
while (1)
{
@@ -411,11 +416,16 @@ _dl_allocate_tls_init (void *result)
/* Unused entry. */
continue;
+ /* Keep track of the maximum generation number. This might
+ not be the generation counter. */
+ maxgen = MAX (maxgen, listp->slotinfo[cnt].gen);
+
if (map->l_tls_offset == NO_TLS_OFFSET)
{
/* For dynamically loaded modules we simply store
the value indicating deferred allocation. */
- dtv[map->l_tls_modid].pointer = TLS_DTV_UNALLOCATED;
+ dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
+ dtv[map->l_tls_modid].pointer.is_static = false;
continue;
}
@@ -431,7 +441,8 @@ _dl_allocate_tls_init (void *result)
# endif
/* Copy the initialization image and clear the BSS part. */
- dtv[map->l_tls_modid].pointer = dest;
+ dtv[map->l_tls_modid].pointer.val = dest;
+ dtv[map->l_tls_modid].pointer.is_static = true;
memset (__mempcpy (dest, map->l_tls_initimage,
map->l_tls_initimage_size), '\0',
map->l_tls_blocksize - map->l_tls_initimage_size);
@@ -445,6 +456,9 @@ _dl_allocate_tls_init (void *result)
assert (listp != NULL);
}
+ /* The DTV version is up-to-date now. */
+ dtv[0].counter = maxgen;
+
return result;
}
rtld_hidden_def (_dl_allocate_tls_init)
@@ -466,6 +480,12 @@ _dl_deallocate_tls (void *tcb, bool dealloc_tcb)
{
dtv_t *dtv = GET_DTV (tcb);
+ /* We need to free the memory allocated for non-static TLS. */
+ for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
+ if (! dtv[1 + cnt].pointer.is_static
+ && dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED)
+ free (dtv[1 + cnt].pointer.val);
+
/* The array starts with dtv[-1]. */
#ifdef SHARED
if (dtv != GL(dl_initial_dtv))
@@ -524,166 +544,172 @@ allocate_and_init (struct link_map *map)
}
-/* The generic dynamic and local dynamic model cannot be used in
- statically linked applications. */
-void *
-__tls_get_addr (GET_ADDR_ARGS)
+struct link_map *
+_dl_update_slotinfo (unsigned long int req_modid)
{
- dtv_t *dtv = THREAD_DTV ();
struct link_map *the_map = NULL;
- void *p;
+ dtv_t *dtv = THREAD_DTV ();
- if (__builtin_expect (dtv[0].counter != GL(dl_tls_generation), 0))
+ /* The global dl_tls_dtv_slotinfo array contains for each module
+ index the generation counter current when the entry was created.
+ This array never shrinks so that all module indices which were
+ valid at some time can be used to access it. Before the first
+ use of a new module index in this function the array was extended
+ appropriately. Access also does not have to be guarded against
+ modifications of the array. It is assumed that pointer-size
+ values can be read atomically even in SMP environments. It is
+ possible that other threads at the same time dynamically load
+ code and therefore add to the slotinfo list. This is a problem
+ since we must not pick up any information about incomplete work.
+ The solution to this is to ignore all dtv slots which were
+ created after the one we are currently interested. We know that
+ dynamic loading for this module is completed and this is the last
+ load operation we know finished. */
+ unsigned long int idx = req_modid;
+ struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
+
+ while (idx >= listp->len)
{
- struct dtv_slotinfo_list *listp;
- size_t idx;
-
- /* The global dl_tls_dtv_slotinfo array contains for each module
- index the generation counter current when the entry was
- created. This array never shrinks so that all module indices
- which were valid at some time can be used to access it.
- Before the first use of a new module index in this function
- the array was extended appropriately. Access also does not
- have to be guarded against modifications of the array. It is
- assumed that pointer-size values can be read atomically even
- in SMP environments. It is possible that other threads at
- the same time dynamically load code and therefore add to the
- slotinfo list. This is a problem since we must not pick up
- any information about incomplete work. The solution to this
- is to ignore all dtv slots which were created after the one
- we are currently interested. We know that dynamic loading
- for this module is completed and this is the last load
- operation we know finished. */
- idx = GET_ADDR_MODULE;
- listp = GL(dl_tls_dtv_slotinfo_list);
- while (idx >= listp->len)
- {
- idx -= listp->len;
- listp = listp->next;
- }
+ idx -= listp->len;
+ listp = listp->next;
+ }
- if (dtv[0].counter < listp->slotinfo[idx].gen)
+ if (dtv[0].counter < listp->slotinfo[idx].gen)
+ {
+ /* The generation counter for the slot is higher than what the
+ current dtv implements. We have to update the whole dtv but
+ only those entries with a generation counter <= the one for
+ the entry we need. */
+ size_t new_gen = listp->slotinfo[idx].gen;
+ size_t total = 0;
+
+ /* We have to look through the entire dtv slotinfo list. */
+ listp = GL(dl_tls_dtv_slotinfo_list);
+ do
{
- /* The generation counter for the slot is higher than what
- the current dtv implements. We have to update the whole
- dtv but only those entries with a generation counter <=
- the one for the entry we need. */
- size_t new_gen = listp->slotinfo[idx].gen;
- size_t total = 0;
-
- /* We have to look through the entire dtv slotinfo list. */
- listp = GL(dl_tls_dtv_slotinfo_list);
- do
+ for (size_t cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt)
{
- size_t cnt;
-
- for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt)
+ size_t gen = listp->slotinfo[cnt].gen;
+
+ if (gen > new_gen)
+ /* This is a slot for a generation younger than the
+ one we are handling now. It might be incompletely
+ set up so ignore it. */
+ continue;
+
+ /* If the entry is older than the current dtv layout we
+ know we don't have to handle it. */
+ if (gen <= dtv[0].counter)
+ continue;
+
+ /* If there is no map this means the entry is empty. */
+ struct link_map *map = listp->slotinfo[cnt].map;
+ if (map == NULL)
{
- size_t gen = listp->slotinfo[cnt].gen;
- struct link_map *map;
- size_t modid;
-
- if (gen > new_gen)
- /* This is a slot for a generation younger than
- the one we are handling now. It might be
- incompletely set up so ignore it. */
- continue;
-
- /* If the entry is older than the current dtv layout
- we know we don't have to handle it. */
- if (gen <= dtv[0].counter)
- continue;
-
- /* If there is no map this means the entry is empty. */
- map = listp->slotinfo[cnt].map;
- if (map == NULL)
+ /* If this modid was used at some point the memory
+ might still be allocated. */
+ if (! dtv[total + cnt].pointer.is_static
+ && dtv[total + cnt].pointer.val != TLS_DTV_UNALLOCATED)
{
- /* If this modid was used at some point the memory
- might still be allocated. */
- if (dtv[total + cnt].pointer != TLS_DTV_UNALLOCATED)
- {
- free (dtv[total + cnt].pointer);
- dtv[total + cnt].pointer = TLS_DTV_UNALLOCATED;
- }
-
- continue;
+ free (dtv[total + cnt].pointer.val);
+ dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
}
- /* Check whether the current dtv array is large enough. */
- modid = map->l_tls_modid;
- assert (total + cnt == modid);
- if (dtv[-1].counter < modid)
+ continue;
+ }
+
+ /* Check whether the current dtv array is large enough. */
+ size_t modid = map->l_tls_modid;
+ assert (total + cnt == modid);
+ if (dtv[-1].counter < modid)
+ {
+ /* Reallocate the dtv. */
+ dtv_t *newp;
+ size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
+ size_t oldsize = dtv[-1].counter;
+
+ assert (map->l_tls_modid <= newsize);
+
+ if (dtv == GL(dl_initial_dtv))
{
- /* Reallocate the dtv. */
- dtv_t *newp;
- size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
- size_t oldsize = dtv[-1].counter;
-
- assert (map->l_tls_modid <= newsize);
-
- if (dtv == GL(dl_initial_dtv))
- {
- /* This is the initial dtv that was allocated
- during rtld startup using the dl-minimal.c
- malloc instead of the real malloc. We can't
- free it, we have to abandon the old storage. */
-
- newp = malloc ((2 + newsize) * sizeof (dtv_t));
- if (newp == NULL)
- oom ();
- memcpy (newp, &dtv[-1], oldsize * sizeof (dtv_t));
- }
- else
- {
- newp = realloc (&dtv[-1],
- (2 + newsize) * sizeof (dtv_t));
- if (newp == NULL)
- oom ();
- }
-
- newp[0].counter = newsize;
-
- /* Clear the newly allocated part. */
- memset (newp + 2 + oldsize, '\0',
- (newsize - oldsize) * sizeof (dtv_t));
-
- /* Point dtv to the generation counter. */
- dtv = &newp[1];
-
- /* Install this new dtv in the thread data
- structures. */
- INSTALL_NEW_DTV (dtv);
+ /* This is the initial dtv that was allocated
+ during rtld startup using the dl-minimal.c
+ malloc instead of the real malloc. We can't
+ free it, we have to abandon the old storage. */
+
+ newp = malloc ((2 + newsize) * sizeof (dtv_t));
+ if (newp == NULL)
+ oom ();
+ memcpy (newp, &dtv[-1], oldsize * sizeof (dtv_t));
}
+ else
+ {
+ newp = realloc (&dtv[-1],
+ (2 + newsize) * sizeof (dtv_t));
+ if (newp == NULL)
+ oom ();
+ }
+
+ newp[0].counter = newsize;
+
+ /* Clear the newly allocated part. */
+ memset (newp + 2 + oldsize, '\0',
+ (newsize - oldsize) * sizeof (dtv_t));
- /* If there is currently memory allocate for this
- dtv entry free it. */
- /* XXX Ideally we will at some point create a memory
- pool. */
- if (dtv[modid].pointer != TLS_DTV_UNALLOCATED)
- /* Note that free is called for NULL is well. We
- deallocate even if it is this dtv entry we are
- supposed to load. The reason is that we call
- memalign and not malloc. */
- free (dtv[modid].pointer);
-
- /* This module is loaded dynamically- We defer
- memory allocation. */
- dtv[modid].pointer = TLS_DTV_UNALLOCATED;
-
- if (modid == GET_ADDR_MODULE)
- the_map = map;
+ /* Point dtv to the generation counter. */
+ dtv = &newp[1];
+
+ /* Install this new dtv in the thread data
+ structures. */
+ INSTALL_NEW_DTV (dtv);
}
- total += listp->len;
+ /* If there is currently memory allocate for this
+ dtv entry free it. */
+ /* XXX Ideally we will at some point create a memory
+ pool. */
+ if (! dtv[modid].pointer.is_static
+ && dtv[modid].pointer.val != TLS_DTV_UNALLOCATED)
+ /* Note that free is called for NULL is well. We
+ deallocate even if it is this dtv entry we are
+ supposed to load. The reason is that we call
+ memalign and not malloc. */
+ free (dtv[modid].pointer.val);
+
+ /* This module is loaded dynamically- We defer memory
+ allocation. */
+ dtv[modid].pointer.is_static = false;
+ dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
+
+ if (modid == req_modid)
+ the_map = map;
}
- while ((listp = listp->next) != NULL);
- /* This will be the new maximum generation counter. */
- dtv[0].counter = new_gen;
+ total += listp->len;
}
+ while ((listp = listp->next) != NULL);
+
+ /* This will be the new maximum generation counter. */
+ dtv[0].counter = new_gen;
}
- p = dtv[GET_ADDR_MODULE].pointer;
+ return the_map;
+}
+
+
+/* The generic dynamic and local dynamic model cannot be used in
+ statically linked applications. */
+void *
+__tls_get_addr (GET_ADDR_ARGS)
+{
+ dtv_t *dtv = THREAD_DTV ();
+ struct link_map *the_map = NULL;
+ void *p;
+
+ if (__builtin_expect (dtv[0].counter != GL(dl_tls_generation), 0))
+ the_map = _dl_update_slotinfo (GET_ADDR_MODULE);
+
+ p = dtv[GET_ADDR_MODULE].pointer.val;
if (__builtin_expect (p == TLS_DTV_UNALLOCATED, 0))
{
@@ -703,11 +729,74 @@ __tls_get_addr (GET_ADDR_ARGS)
the_map = listp->slotinfo[idx].map;
}
- p = dtv[GET_ADDR_MODULE].pointer = allocate_and_init (the_map);
+ p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map);
+ dtv[GET_ADDR_MODULE].pointer.is_static = false;
}
return (char *) p + GET_ADDR_OFFSET;
}
# endif
+
+
+void
+_dl_add_to_slotinfo (struct link_map *l)
+{
+ /* Now that we know the object is loaded successfully add
+ modules containing TLS data to the dtv info table. We
+ might have to increase its size. */
+ struct dtv_slotinfo_list *listp;
+ struct dtv_slotinfo_list *prevp;
+ size_t idx = l->l_tls_modid;
+
+ /* Find the place in the dtv slotinfo list. */
+ listp = GL(dl_tls_dtv_slotinfo_list);
+ prevp = NULL; /* Needed to shut up gcc. */
+ do
+ {
+ /* Does it fit in the array of this list element? */
+ if (idx < listp->len)
+ break;
+ idx -= listp->len;
+ prevp = listp;
+ listp = listp->next;
+ }
+ while (listp != NULL);
+
+ if (listp == NULL)
+ {
+ /* When we come here it means we have to add a new element
+ to the slotinfo list. And the new module must be in
+ the first slot. */
+ assert (idx == 0);
+
+ listp = prevp->next = (struct dtv_slotinfo_list *)
+ malloc (sizeof (struct dtv_slotinfo_list)
+ + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
+ if (listp == NULL)
+ {
+ /* We ran out of memory. We will simply fail this
+ call but don't undo anything we did so far. The
+ application will crash or be terminated anyway very
+ soon. */
+
+ /* We have to do this since some entries in the dtv
+ slotinfo array might already point to this
+ generation. */
+ ++GL(dl_tls_generation);
+
+ _dl_signal_error (ENOMEM, "dlopen", NULL, N_("\
+cannot create TLS data structures"));
+ }
+
+ listp->len = TLS_SLOTINFO_SURPLUS;
+ listp->next = NULL;
+ memset (listp->slotinfo, '\0',
+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
+ }
+
+ /* Add the information into the slotinfo data structure. */
+ listp->slotinfo[idx].map = l;
+ listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
+}
#endif /* use TLS */
diff --git a/sysdeps/generic/dl-trampoline.c b/sysdeps/generic/dl-trampoline.c
new file mode 100644
index 0000000000..3ca89f3879
--- /dev/null
+++ b/sysdeps/generic/dl-trampoline.c
@@ -0,0 +1 @@
+#error "Architecture specific PLT trampolines must be defined."
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index ec68e1a565..08039e18ca 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1,5 +1,5 @@
/* Run-time dynamic linker data structures for loaded ELF shared objects.
- Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1995-2003, 2004, 2005 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
@@ -52,23 +52,15 @@ __BEGIN_DECLS
most architectures the entry is already relocated - but for some not
and we need to relocate at access time. */
#ifdef DL_RO_DYN_SECTION
-# define D_PTR(map,i) (map->i->d_un.d_ptr + map->l_addr)
+# define D_PTR(map, i) ((map)->i->d_un.d_ptr + (map)->l_addr)
#else
-# define D_PTR(map,i) map->i->d_un.d_ptr
+# define D_PTR(map, i) (map)->i->d_un.d_ptr
#endif
-/* On some platforms more information than just the address of the symbol
- is needed from the lookup functions. In this case we return the whole
- link map. */
-#ifdef DL_LOOKUP_RETURNS_MAP
+/* Result of the lookup functions and how to retrieve the base address. */
typedef struct link_map *lookup_t;
# define LOOKUP_VALUE(map) map
-# define LOOKUP_VALUE_ADDRESS(map) (map ? map->l_addr : 0)
-#else
-typedef ElfW(Addr) lookup_t;
-# define LOOKUP_VALUE(map) map->l_addr
-# define LOOKUP_VALUE_ADDRESS(address) address
-#endif
+# define LOOKUP_VALUE_ADDRESS(map) ((map) ? (map)->l_addr : 0)
/* on some architectures a pointer to a function is not just a pointer
to the actual code of the function but rather an architecture
@@ -182,6 +174,133 @@ enum allowmask
};
+/* Type for list of auditing interfaces. */
+struct La_i86_regs;
+struct La_i86_retval;
+struct La_x86_64_regs;
+struct La_x86_64_retval;
+struct La_ppc32_regs;
+struct La_ppc32_retval;
+struct La_ppc64_regs;
+struct La_ppc64_retval;
+struct La_sh_regs;
+struct La_sh_retval;
+struct La_m68k_regs;
+struct La_m68k_retval;
+struct La_alpha_regs;
+struct La_alpha_retval;
+struct La_s390_32_regs;
+struct La_s390_32_retval;
+struct La_s390_64_regs;
+struct La_s390_64_retval;
+struct La_ia64_regs;
+struct La_ia64_retval;
+
+struct audit_ifaces
+{
+ void (*activity) (uintptr_t *, unsigned int);
+ char *(*objsearch) (const char *, uintptr_t *, unsigned int);
+ unsigned int (*objopen) (struct link_map *, Lmid_t, uintptr_t *);
+ void (*preinit) (uintptr_t *);
+ union
+ {
+ uintptr_t (*symbind32) (Elf32_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, unsigned int *, const char *);
+ uintptr_t (*symbind64) (Elf64_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, unsigned int *, const char *);
+ };
+ union
+ {
+ Elf32_Addr (*i86_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, struct La_i86_regs *,
+ unsigned int *, const char *name,
+ long int *framesizep);
+ Elf64_Addr (*x86_64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, struct La_x86_64_regs *,
+ unsigned int *, const char *name,
+ long int *framesizep);
+ Elf32_Addr (*ppc32_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, struct La_ppc32_regs *,
+ unsigned int *, const char *name,
+ long int *framesizep);
+ Elf64_Addr (*ppc64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, struct La_ppc64_regs *,
+ unsigned int *, const char *name,
+ long int *framesizep);
+ uintptr_t (*sh_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, const struct La_sh_regs *,
+ unsigned int *, const char *name,
+ long int *framesizep);
+ Elf32_Addr (*m68k_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, struct La_m68k_regs *,
+ unsigned int *, const char *name,
+ long int *framesizep);
+ Elf64_Addr (*alpha_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, struct La_alpha_regs *,
+ unsigned int *, const char *name,
+ long int *framesizep);
+ Elf32_Addr (*s390_32_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, struct La_s390_32_regs *,
+ unsigned int *, const char *name,
+ long int *framesizep);
+ Elf64_Addr (*s390_64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, struct La_s390_64_regs *,
+ unsigned int *, const char *name,
+ long int *framesizep);
+ Elf64_Addr (*ia64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, struct La_ia64_regs *,
+ unsigned int *, const char *name,
+ long int *framesizep);
+ };
+ union
+ {
+ unsigned int (*i86_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, const struct La_i86_regs *,
+ struct La_i86_retval *, const char *);
+ unsigned int (*x86_64_gnu_pltexit) (Elf64_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *,
+ const struct La_x86_64_regs *,
+ struct La_x86_64_retval *,
+ const char *);
+ unsigned int (*ppc32_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *,
+ const struct La_ppc32_regs *,
+ struct La_ppc32_retval *, const char *);
+ unsigned int (*ppc64_gnu_pltexit) (Elf64_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *,
+ const struct La_ppc64_regs *,
+ struct La_ppc64_retval *, const char *);
+ unsigned int (*sh_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, const struct La_sh_regs *,
+ struct La_sh_retval *, const char *);
+ unsigned int (*m68k_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, const struct La_m68k_regs *,
+ struct La_m68k_retval *, const char *);
+ unsigned int (*alpha_gnu_pltexit) (Elf64_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *,
+ const struct La_alpha_regs *,
+ struct La_alpha_retval *, const char *);
+ unsigned int (*s390_32_gnu_pltexit) (Elf32_Sym *, unsigned int,
+ uintptr_t *, uintptr_t *,
+ const struct La_s390_32_regs *,
+ struct La_s390_32_retval *,
+ const char *);
+ unsigned int (*s390_64_gnu_pltexit) (Elf64_Sym *, unsigned int,
+ uintptr_t *, uintptr_t *,
+ const struct La_s390_64_regs *,
+ struct La_s390_64_retval *,
+ const char *);
+ unsigned int (*ia64_gnu_pltexit) (Elf64_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *,
+ const struct La_ia64_regs *,
+ struct La_ia64_retval *, const char *);
+ };
+ unsigned int (*objclose) (uintptr_t *);
+
+ struct audit_ifaces *next;
+};
+
+
/* Test whether given NAME matches any of the names of the given object. */
extern int _dl_name_match_p (const char *__name, struct link_map *__map)
internal_function;
@@ -224,7 +343,7 @@ struct rtld_global
#endif
EXTERN struct link_namespaces
{
- /* And a pointer to the map for the main map. */
+ /* A pointer to the map for the main map. */
struct link_map *_ns_loaded;
/* Number of object in the _dl_loaded list. */
unsigned int _ns_nloaded;
@@ -236,6 +355,8 @@ struct rtld_global
allocated by rtld. Later it keeps the size of the map. It might be
reset if in _dl_close if the last global object is removed. */
size_t _ns_global_scope_alloc;
+ /* Keep track of changes to each namespace' list. */
+ struct r_debug _ns_debug;
} _dl_ns[DL_NNS];
/* During the program run we must not modify the global data of
@@ -277,8 +398,12 @@ struct rtld_global
EXTERN void **(*_dl_error_catch_tsd) (void) __attribute__ ((const));
#endif
- /* Structure describing the dynamic linker itself. */
+ /* Structure describing the dynamic linker itself. We need to
+ reserve memory for the data the audit libraries need. */
EXTERN struct link_map _dl_rtld_map;
+#ifdef SHARED
+ struct auditstate audit_data[DL_NNS];
+#endif
#if defined SHARED && defined _LIBC_REENTRANT \
&& defined __rtld_lock_default_lock_recursive
@@ -311,6 +436,7 @@ struct rtld_global
struct dtv_slotinfo
{
size_t gen;
+ bool is_static;
struct link_map *map;
} slotinfo[0];
} *_dl_tls_dtv_slotinfo_list;
@@ -483,32 +609,12 @@ struct rtld_global_ro
call the function instead of going through the PLT. The result
is that we can avoid exporting the functions and we do not jump
PLT relocations in libc.so. */
- const char *(*_dl_get_origin) (void);
- size_t (*_dl_dst_count) (const char *, int);
- char *(*_dl_dst_substitute) (struct link_map *, const char *, char *, int);
- struct link_map *(internal_function *_dl_map_object) (struct link_map *,
- const char *, int,
- int, int, int, Lmid_t);
- void (internal_function *_dl_map_object_deps) (struct link_map *,
- struct link_map **,
- unsigned int, int, int);
- void (*_dl_relocate_object) (struct link_map *, struct r_scope_elem *[],
- int, int);
- int (internal_function *_dl_check_map_versions) (struct link_map *, int,
- int);
- void (internal_function *_dl_init) (struct link_map *, int, char **,
- char **);
- void (*_dl_debug_state) (void);
-#ifndef MAP_COPY
- void (*_dl_unload_cache) (void);
-#endif
void (*_dl_debug_printf) (const char *, ...)
__attribute__ ((__format__ (__printf__, 1, 2)));
int (internal_function *_dl_catch_error) (const char **, const char **,
void (*) (void *), void *);
void (internal_function *_dl_signal_error) (int, const char *, const char *,
const char *);
- void (internal_function *_dl_start_profile) (void);
void (*_dl_mcount) (ElfW(Addr) frompc, ElfW(Addr) selfpc);
lookup_t (internal_function *_dl_lookup_symbol_x) (const char *,
struct link_map *,
@@ -518,7 +624,13 @@ struct rtld_global_ro
int, int,
struct link_map *);
int (*_dl_check_caller) (const void *, enum allowmask);
+ void *(*_dl_open) (const char *file, int mode, const void *caller_dlopen,
+ Lmid_t nsid, int argc, char *argv[], char *env[]);
+ void (*_dl_close) (void *map);
+ /* List of auditing interfaces. */
+ struct audit_ifaces *_dl_audit;
+ unsigned int _dl_naudit;
};
# define __rtld_global_attribute__
# ifdef IS_IN_rtld
@@ -793,7 +905,7 @@ rtld_hidden_proto (_dl_debug_state)
/* Initialize `struct r_debug' if it has not already been done. The
argument is the run-time load address of the dynamic linker, to be put
in the `r_ldbase' member. Returns the address of the structure. */
-extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase)
+extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
internal_function;
/* Initialize the basic data structure for the search paths. */
@@ -911,6 +1023,20 @@ extern char *_dl_dst_substitute (struct link_map *l, const char *name,
extern int _dl_check_caller (const void *caller, enum allowmask mask)
attribute_hidden;
+/* Open the shared object NAME, relocate it, and run its initializer if it
+ hasn't already been run. MODE is as for `dlopen' (see <dlfcn.h>). If
+ the object is already opened, returns its existing map. */
+extern void *_dl_open (const char *name, int mode, const void *caller,
+ Lmid_t nsid, int argc, char *argv[], char *env[])
+ attribute_hidden;
+
+/* Add module to slot information data. */
+extern void _dl_add_to_slotinfo (struct link_map *l) attribute_hidden;
+
+/* Update slot information data for at least the generation of the
+ module with the given index. */
+extern struct link_map *_dl_update_slotinfo (unsigned long int req_modid);
+
__END_DECLS
#endif /* ldsodefs.h */
diff --git a/sysdeps/generic/libc-start.c b/sysdeps/generic/libc-start.c
index ad5ebe0911..5bb8a9b352 100644
--- a/sysdeps/generic/libc-start.c
+++ b/sysdeps/generic/libc-start.c
@@ -80,6 +80,10 @@ STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
void *__unbounded stack_end)
__attribute__ ((noreturn));
+
+/* Note: the fini parameter is ignored here. It used to be registered
+ with __cxa_atexit. This had the disadvantage that finalizers were
+ called in more than one place. */
STATIC int
LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
int argc, char *__unbounded *__unbounded ubp_av,
@@ -158,10 +162,6 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
__libc_init_first (argc, argv, __environ);
#endif
- /* Register the destructor of the program, if any. */
- if (fini)
- __cxa_atexit ((void (*) (void *)) fini, NULL, NULL);
-
#ifndef SHARED
/* Some security at this point. Prevent starting a SUID binary where
the standard file descriptors are not opened. We have to do this
@@ -184,6 +184,22 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
);
#ifdef SHARED
+ /* Auditing checkpoint: we have a new object. */
+ if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+ {
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->preinit != NULL)
+ afct->preinit (&head->l_audit[cnt].cookie);
+
+ afct = afct->next;
+ }
+ }
+#endif
+
+#ifdef SHARED
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
#endif
diff --git a/sysdeps/generic/libc-tls.c b/sysdeps/generic/libc-tls.c
index b5ecc36436..b88ede06a2 100644
--- a/sysdeps/generic/libc-tls.c
+++ b/sysdeps/generic/libc-tls.c
@@ -1,5 +1,5 @@
/* Initialization code for TLS in statically linked application.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004 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
@@ -178,17 +178,18 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
/* Initialize the TLS block. */
# if TLS_TCB_AT_TP
- static_dtv[2].pointer = ((char *) tlsblock + tcb_offset
- - roundup (memsz, align ?: 1));
+ static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset
+ - roundup (memsz, align ?: 1));
static_map.l_tls_offset = roundup (memsz, align ?: 1);
# elif TLS_DTV_AT_TP
- static_dtv[2].pointer = (char *) tlsblock + tcb_offset;
+ static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset;
static_map.l_tls_offset = tcb_offset;
# else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
# endif
+ static_dtv[2].pointer.is_static = true;
/* sbrk gives us zero'd memory, so we don't need to clear the remainder. */
- memcpy (static_dtv[2].pointer, initimage, filesz);
+ memcpy (static_dtv[2].pointer.val, initimage, filesz);
/* Install the pointer to the dtv. */
diff --git a/misc/syslog.c b/sysdeps/generic/syslog.c
index 6916356da7..9c8f422aad 100644
--- a/misc/syslog.c
+++ b/sysdeps/generic/syslog.c
@@ -73,8 +73,13 @@ __libc_lock_define_initialized (static, syslog_lock)
static void openlog_internal(const char *, int, int) internal_function;
static void closelog_internal(void);
+#ifndef NO_SIGPIPE
static void sigpipe_handler (int);
+#endif
+#ifndef send_flags
+# define send_flags 0
+#endif
struct cleanup_arg
{
@@ -85,11 +90,13 @@ struct cleanup_arg
static void
cancel_handler (void *ptr)
{
+#ifndef NO_SIGPIPE
/* Restore the old signal handler. */
struct cleanup_arg *clarg = (struct cleanup_arg *) ptr;
if (clarg != NULL && clarg->oldaction != NULL)
__sigaction (SIGPIPE, clarg->oldaction, NULL);
+#endif
/* Free the lock. */
__libc_lock_unlock (syslog_lock);
@@ -135,8 +142,10 @@ vsyslog(pri, fmt, ap)
char *buf = 0;
size_t bufsize = 0;
size_t prioff, msgoff;
+#ifndef NO_SIGPIPE
struct sigaction action, oldaction;
int sigpipe;
+#endif
int saved_errno = errno;
char failbuf[3 * sizeof (pid_t) + sizeof "out of memory []"];
@@ -247,6 +256,7 @@ vsyslog(pri, fmt, ap)
__libc_cleanup_push (cancel_handler, &clarg);
__libc_lock_lock (syslog_lock);
+#ifndef NO_SIGPIPE
/* Prepare for a broken connection. */
memset (&action, 0, sizeof (action));
action.sa_handler = sigpipe_handler;
@@ -254,6 +264,7 @@ vsyslog(pri, fmt, ap)
sigpipe = __sigaction (SIGPIPE, &action, &oldaction);
if (sigpipe == 0)
clarg.oldaction = &oldaction;
+#endif
/* Get connected, output the message to the local logger. */
if (!connected)
@@ -264,7 +275,7 @@ vsyslog(pri, fmt, ap)
if (LogType == SOCK_STREAM)
++bufsize;
- if (!connected || __send(LogFile, buf, bufsize, 0) < 0)
+ if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0)
{
if (connected)
{
@@ -274,7 +285,7 @@ vsyslog(pri, fmt, ap)
openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);
}
- if (!connected || __send(LogFile, buf, bufsize, 0) < 0)
+ if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0)
{
closelog_internal (); /* attempt re-open next time */
/*
@@ -292,8 +303,10 @@ vsyslog(pri, fmt, ap)
}
}
+#ifndef NO_SIGPIPE
if (sigpipe == 0)
__sigaction (SIGPIPE, &oldaction, (struct sigaction *) NULL);
+#endif
/* End of critical section. */
__libc_cleanup_pop (0);
@@ -368,11 +381,13 @@ openlog (const char *ident, int logstat, int logfac)
__libc_cleanup_pop (1);
}
+#ifndef NO_SIGPIPE
static void
sigpipe_handler (int signo)
{
closelog_internal ();
}
+#endif
static void
closelog_internal()
diff --git a/sysdeps/generic/unsecvars.h b/sysdeps/generic/unsecvars.h
index eb77b260d8..a7378b742f 100644
--- a/sysdeps/generic/unsecvars.h
+++ b/sysdeps/generic/unsecvars.h
@@ -2,18 +2,19 @@
all stuffed in a single string which means they have to be terminated
with a '\0' explicitly. */
#define UNSECURE_ENVVARS \
- "LD_PRELOAD\0" \
- "LD_LIBRARY_PATH\0" \
- "LD_ORIGIN_PATH\0" \
+ "GCONV_PATH\0" \
+ "GETCONF_DIR\0" \
+ "HOSTALIASES\0" \
+ "LD_AUDIT\0" \
"LD_DEBUG\0" \
"LD_DEBUG_OUTPUT\0" \
- "LD_PROFILE\0" \
- "LD_USE_LOAD_BIAS\0" \
"LD_DYNAMIC_WEAK\0" \
+ "LD_LIBRARY_PATH\0" \
+ "LD_ORIGIN_PATH\0" \
+ "LD_PRELOAD\0" \
+ "LD_PROFILE\0" \
"LD_SHOW_AUXV\0" \
- "GCONV_PATH\0" \
- "GETCONF_DIR\0" \
- "HOSTALIASES\0" \
+ "LD_USE_LOAD_BIAS\0" \
"LOCALDOMAIN\0" \
"LOCPATH\0" \
"MALLOC_TRACE\0" \
diff --git a/sysdeps/generic/wordexp.c b/sysdeps/generic/wordexp.c
index 3e37d6449c..c3d382fb95 100644
--- a/sysdeps/generic/wordexp.c
+++ b/sysdeps/generic/wordexp.c
@@ -1,5 +1,5 @@
/* POSIX.2 wordexp implementation.
- Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1997-2002, 2003, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Tim Waugh <tim@cyberelk.demon.co.uk>.
@@ -810,7 +810,7 @@ parse_arith (char **word, size_t *word_length, size_t *max_length,
/* Function called by child process in exec_comm() */
static void
-internal_function
+internal_function __attribute__ ((always_inline))
exec_comm_child (char *comm, int *fildes, int showerr, int noexec)
{
const char *args[4] = { _PATH_BSHELL, "-c", comm, NULL };
@@ -868,13 +868,14 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
const char *ifs_white)
{
int fildes[2];
- int bufsize = 128;
+#define bufsize 128
int buflen;
int i;
int status = 0;
size_t maxnewlines = 0;
- char *buffer;
+ char buffer[bufsize];
pid_t pid;
+ int noexec = 0;
/* Don't fork() unless necessary */
if (!comm || !*comm)
@@ -884,32 +885,42 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
/* Bad */
return WRDE_NOSPACE;
+ again:
if ((pid = __fork ()) < 0)
{
/* Bad */
- __close (fildes[0]);
- __close (fildes[1]);
+ if (fildes[0] != -1)
+ __close (fildes[0]);
+ if (fildes[1] != -1)
+ __close (fildes[1]);
return WRDE_NOSPACE;
}
if (pid == 0)
- exec_comm_child (comm, fildes, flags & WRDE_SHOWERR, 0);
+ exec_comm_child (comm, fildes, noexec ? 0 : flags & WRDE_SHOWERR, noexec);
/* Parent */
+ /* If we are just testing the syntax, only wait. */
+ if (noexec)
+ return (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) == pid
+ && status != 0) ? WRDE_SYNTAX : 0;
+
__close (fildes[1]);
- buffer = __alloca (bufsize);
+ fildes[1] = -1;
if (!pwordexp)
/* Quoted - no field splitting */
{
while (1)
{
- if ((buflen = __read (fildes[0], buffer, bufsize)) < 1)
+ if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer,
+ bufsize))) < 1)
{
- if (__waitpid (pid, &status, WNOHANG) == 0)
+ if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, WNOHANG)) == 0)
continue;
- if ((buflen = __read (fildes[0], buffer, bufsize)) < 1)
+ if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer,
+ bufsize))) < 1)
break;
}
@@ -933,11 +944,13 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
while (1)
{
- if ((buflen = __read (fildes[0], buffer, bufsize)) < 1)
+ if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer,
+ bufsize))) < 1)
{
- if (__waitpid (pid, &status, WNOHANG) == 0)
+ if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, WNOHANG)) == 0)
continue;
- if ((buflen = __read (fildes[0], buffer, bufsize)) < 1)
+ if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer,
+ bufsize))) < 1)
break;
}
@@ -1053,31 +1066,20 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
}
__close (fildes[0]);
+ fildes[0] = -1;
/* Check for syntax error (re-execute but with "-n" flag) */
if (buflen < 1 && status != 0)
{
- if ((pid = __fork ()) < 0)
- {
- /* Bad */
- return WRDE_NOSPACE;
- }
-
- if (pid == 0)
- {
- fildes[0] = fildes[1] = -1;
- exec_comm_child (comm, fildes, 0, 1);
- }
-
- if (__waitpid (pid, &status, 0) == pid && status != 0)
- return WRDE_SYNTAX;
+ noexec = 1;
+ goto again;
}
return 0;
no_space:
__kill (pid, SIGKILL);
- __waitpid (pid, NULL, 0);
+ TEMP_FAILURE_RETRY (__waitpid (pid, NULL, 0));
__close (fildes[0]);
return WRDE_NOSPACE;
}
diff --git a/sysdeps/hppa/bits/link.h b/sysdeps/hppa/bits/link.h
index 54842b2299..e69de29bb2 100644
--- a/sysdeps/hppa/bits/link.h
+++ b/sysdeps/hppa/bits/link.h
@@ -1,6 +0,0 @@
-/* Used to store the function descriptor table */
-struct link_map_machine
- {
- size_t fptr_table_len;
- ElfW(Addr) *fptr_table;
- };
diff --git a/sysdeps/hppa/bits/linkmap.h b/sysdeps/hppa/bits/linkmap.h
new file mode 100644
index 0000000000..54842b2299
--- /dev/null
+++ b/sysdeps/hppa/bits/linkmap.h
@@ -0,0 +1,6 @@
+/* Used to store the function descriptor table */
+struct link_map_machine
+ {
+ size_t fptr_table_len;
+ ElfW(Addr) *fptr_table;
+ };
diff --git a/sysdeps/hppa/dl-lookupcfg.h b/sysdeps/hppa/dl-lookupcfg.h
index d393b3e427..84436e7c56 100644
--- a/sysdeps/hppa/dl-lookupcfg.h
+++ b/sysdeps/hppa/dl-lookupcfg.h
@@ -1,5 +1,5 @@
/* Configuration of lookup functions.
- Copyright (C) 2000 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2004 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
@@ -17,9 +17,6 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-/* Like IA-64, PA-RISC needs more information from the symbol lookup
- function than just the address. */
-#define DL_LOOKUP_RETURNS_MAP
#define ELF_FUNCTION_PTR_IS_SPECIAL
#define DL_UNMAP_IS_SPECIAL
@@ -66,4 +63,3 @@ void _dl_unmap (struct link_map *map);
((Elf32_Addr)(addr) & 2 ? (addr) : DL_AUTO_FUNCTION_ADDRESS (map, addr))
#define DL_DT_FINI_ADDRESS(map, addr) \
((Elf32_Addr)(addr) & 2 ? (addr) : DL_AUTO_FUNCTION_ADDRESS (map, addr))
-
diff --git a/sysdeps/i386/Makefile b/sysdeps/i386/Makefile
index 52faaa3109..ece94f3610 100644
--- a/sysdeps/i386/Makefile
+++ b/sysdeps/i386/Makefile
@@ -61,3 +61,7 @@ CFLAGS-dlopenold.c += -mpreferred-stack-boundary=4
CFLAGS-dlclose.c += -mpreferred-stack-boundary=4
CFLAGS-dlerror.c += -mpreferred-stack-boundary=4
endif
+
+ifneq (,$(filter -mno-tls-direct-seg-refs,$(CFLAGS)))
+defines += -DNO_TLS_DIRECT_SEG_REFS
+endif
diff --git a/sysdeps/i386/bits/link.h b/sysdeps/i386/bits/link.h
index 3be9b7eae8..985d040413 100644
--- a/sysdeps/i386/bits/link.h
+++ b/sysdeps/i386/bits/link.h
@@ -1,5 +1,60 @@
-struct link_map_machine
- {
- Elf32_Addr plt; /* Address of .plt + 0x16 */
- Elf32_Addr gotplt; /* Address of .got + 0x0c */
- };
+/* Copyright (C) 2004, 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+/* Registers for entry into PLT on IA-32. */
+typedef struct La_i86_regs
+{
+ uint32_t lr_edx;
+ uint32_t lr_ecx;
+ uint32_t lr_eax;
+ uint32_t lr_ebp;
+ uint32_t lr_esp;
+} La_i86_regs;
+
+/* Return values for calls from PLT on IA-32. */
+typedef struct La_i86_retval
+{
+ uint32_t lrv_eax;
+ uint32_t lrv_edx;
+ long double lrv_st0;
+ long double lrv_st1;
+} La_i86_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_i86_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ La_i86_regs *__regs,
+ unsigned int *__flags,
+ const char *__symname,
+ long int *__framesizep);
+extern unsigned int la_i86_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ const La_i86_regs *__inregs,
+ La_i86_retval *__outregs,
+ const char *symname);
+
+__END_DECLS
diff --git a/sysdeps/i386/bits/linkmap.h b/sysdeps/i386/bits/linkmap.h
new file mode 100644
index 0000000000..3be9b7eae8
--- /dev/null
+++ b/sysdeps/i386/bits/linkmap.h
@@ -0,0 +1,5 @@
+struct link_map_machine
+ {
+ Elf32_Addr plt; /* Address of .plt + 0x16 */
+ Elf32_Addr gotplt; /* Address of .got + 0x0c */
+ };
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index c48d9d325e..78c083f6ab 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation inline functions. i386 version.
- Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1995-2002, 2003, 2004, 2005 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
@@ -129,7 +129,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
got[2] = (Elf32_Addr) &_dl_runtime_profile;
- if (_dl_name_match_p (GLRO(dl_profile), l))
+ if (GLRO(dl_profile) != NULL
+ && _dl_name_match_p (GLRO(dl_profile), l))
/* This is the object we are looking for. Say that we really
want profiling and the timers are started. */
GL(dl_profile_map) = l;
@@ -154,112 +155,18 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
destroys the passed register information. */
/* GKM FIXME: Fix trampoline to pass bounds so we can do
without the `__unbounded' qualifier. */
-#define ARCH_FIXUP_ATTRIBUTE __attribute__ ((regparm (3), unused))
+#define ARCH_FIXUP_ATTRIBUTE __attribute__ ((regparm (3), stdcall, unused))
-static ElfW(Addr) fixup (struct link_map *__unbounded l,
- ElfW(Word) reloc_offset)
+extern ElfW(Addr) _dl_fixup (struct link_map *__unbounded l,
+ ElfW(Word) reloc_offset)
ARCH_FIXUP_ATTRIBUTE;
-static ElfW(Addr) profile_fixup (struct link_map *l, ElfW(Word) reloc_offset,
- ElfW(Addr) retaddr)
+extern ElfW(Addr) _dl_profile_fixup (struct link_map *l,
+ ElfW(Word) reloc_offset,
+ ElfW(Addr) retaddr, void *regs,
+ long int *framesizep)
ARCH_FIXUP_ATTRIBUTE;
# endif
-/* This code is used in dl-runtime.c to call the `fixup' function
- and then redirect to the address it returns. */
-# if !defined PROF && !__BOUNDED_POINTERS__
-# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
- .text\n\
- .globl _dl_runtime_resolve\n\
- .type _dl_runtime_resolve, @function\n\
- " CFI_STARTPROC "\n\
- .align 16\n\
-_dl_runtime_resolve:\n\
- " CFI_ADJUST_CFA_OFFSET (8) "\n\
- pushl %eax # Preserve registers otherwise clobbered.\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- pushl %ecx\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- pushl %edx\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- movl 16(%esp), %edx # Copy args pushed by PLT in register. Note\n\
- movl 12(%esp), %eax # that `fixup' takes its parameters in regs.\n\
- call fixup # Call resolver.\n\
- popl %edx # Get register content back.\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- popl %ecx\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- xchgl %eax, (%esp) # Get %eax contents end store function address.\n\
- ret $8 # Jump to function address.\n\
- " CFI_ENDPROC "\n\
- .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-\n\
- .globl _dl_runtime_profile\n\
- .type _dl_runtime_profile, @function\n\
- " CFI_STARTPROC "\n\
- .align 16\n\
-_dl_runtime_profile:\n\
- " CFI_ADJUST_CFA_OFFSET (8) "\n\
- pushl %eax # Preserve registers otherwise clobbered.\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- pushl %ecx\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- pushl %edx\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- movl 20(%esp), %ecx # Load return address\n\
- movl 16(%esp), %edx # Copy args pushed by PLT in register. Note\n\
- movl 12(%esp), %eax # that `fixup' takes its parameters in regs.\n\
- call profile_fixup # Call resolver.\n\
- popl %edx # Get register content back.\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- popl %ecx\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- xchgl %eax, (%esp) # Get %eax contents end store function address.\n\
- ret $8 # Jump to function address.\n\
- " CFI_ENDPROC "\n\
- .size _dl_runtime_profile, .-_dl_runtime_profile\n\
- .previous\n\
-");
-# else
-# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\
- .text\n\
- .globl _dl_runtime_resolve\n\
- .globl _dl_runtime_profile\n\
- .type _dl_runtime_resolve, @function\n\
- .type _dl_runtime_profile, @function\n\
- " CFI_STARTPROC "\n\
- .align 16\n\
-_dl_runtime_resolve:\n\
-_dl_runtime_profile:\n\
- " CFI_ADJUST_CFA_OFFSET (8) "\n\
- pushl %eax # Preserve registers otherwise clobbered.\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- pushl %ecx\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- pushl %edx\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- movl 16(%esp), %edx # Push the arguments for `fixup'\n\
- movl 12(%esp), %eax\n\
- pushl %edx\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- pushl %eax\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- call fixup # Call resolver.\n\
- popl %edx # Pop the parameters\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- popl %ecx\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- popl %edx # Get register content back.\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- popl %ecx\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- xchgl %eax, (%esp) # Get %eax contents end store function address.\n\
- ret $8 # Jump to function address.\n\
- " CFI_ENDPROC "\n\
- .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
- .size _dl_runtime_profile, .-_dl_runtime_profile\n\
- .previous\n\
-");
-# endif
#endif
/* Mask identifying addresses reserved for the user program,
@@ -308,11 +215,21 @@ _dl_start_user:\n\
movl _rtld_local@GOTOFF(%ebx), %eax\n\
leal 8(%esp,%edx,4), %esi\n\
leal 4(%esp), %ecx\n\
+ movl %esp, %ebp\n\
+ # Make sure _dl_init is run with 16 byte aligned stack.\n\
+ andl $-16, %esp\n\
+ pushl %eax\n\
+ pushl %eax\n\
+ pushl %ebp\n\
pushl %esi\n\
+ # Clear %ebp, so that even constructors have terminated backchain.\n\
+ xorl %ebp, %ebp\n\
# Call the function to run the initializers.\n\
call _dl_init_internal@PLT\n\
# Pass our finalizer function to the user in %edx, as per ELF ABI.\n\
leal _dl_fini@GOTOFF(%ebx), %edx\n\
+ # Restore %esp _start expects.\n\
+ movl (%esp), %esp\n\
# Jump to the user's entry point.\n\
jmp *%edi\n\
.previous\n\
@@ -375,9 +292,14 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc,
return value;
}
+
+/* Names of the architecture-specific auditing callback functions. */
+#define ARCH_LA_PLTENTER i86_gnu_pltenter
+#define ARCH_LA_PLTEXIT i86_gnu_pltexit
+
#endif /* !dl_machine_h */
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
/* The i386 never uses Elf32_Rela relocations for the dynamic linker.
Prelinked libraries may use Elf32_Rela though. */
@@ -422,17 +344,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
#endif /* !RTLD_BOOTSTRAP and have no -z combreloc */
{
const Elf32_Sym *const refsym = sym;
-#if defined USE_TLS && !defined RTLD_BOOTSTRAP
struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
- Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
-#else
- Elf32_Addr value = RESOLVE (&sym, version, r_type);
-
-# ifndef RTLD_BOOTSTRAP
- if (sym != NULL)
-# endif
- value += sym->st_value;
-#endif /* use TLS and !RTLD_BOOTSTRAP */
+ Elf32_Addr value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
switch (r_type)
{
@@ -549,14 +462,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
# ifndef RESOLVE_CONFLICT_FIND_MAP
const Elf32_Sym *const refsym = sym;
# endif
-# ifdef USE_TLS
struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
-# else
- Elf32_Addr value = RESOLVE (&sym, version, r_type);
- if (sym != NULL)
- value += sym->st_value;
-# endif
switch (ELF32_R_TYPE (reloc->r_info))
{
@@ -692,4 +599,4 @@ elf_machine_lazy_rela (struct link_map *map,
#endif /* !RTLD_BOOTSTRAP */
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/i386/dl-trampoline.S b/sysdeps/i386/dl-trampoline.S
new file mode 100644
index 0000000000..80dd300e86
--- /dev/null
+++ b/sysdeps/i386/dl-trampoline.S
@@ -0,0 +1,182 @@
+/* PLT trampolines. i386 version.
+ Copyright (C) 2004, 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+
+ .text
+ .globl _dl_runtime_resolve
+ .type _dl_runtime_resolve, @function
+ cfi_startproc
+ .align 16
+_dl_runtime_resolve:
+ cfi_adjust_cfa_offset (8)
+ pushl %eax # Preserve registers otherwise clobbered.
+ cfi_adjust_cfa_offset (4)
+ pushl %ecx
+ cfi_adjust_cfa_offset (4)
+ pushl %edx
+ cfi_adjust_cfa_offset (4)
+ movl 16(%esp), %edx # Copy args pushed by PLT in register. Note
+ movl 12(%esp), %eax # that `fixup' takes its parameters in regs.
+ call _dl_fixup # Call resolver.
+ popl %edx # Get register content back.
+ cfi_adjust_cfa_offset (-4)
+ popl %ecx
+ cfi_adjust_cfa_offset (-4)
+ xchgl %eax, (%esp) # Get %eax contents end store function address.
+ ret $8 # Jump to function address.
+ cfi_endproc
+ .size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+
+ .globl _dl_runtime_profile
+ .type _dl_runtime_profile, @function
+ cfi_startproc
+ .align 16
+_dl_runtime_profile:
+ cfi_adjust_cfa_offset (8)
+ pushl %esp
+ cfi_adjust_cfa_offset (4)
+ addl $8, (%esp) # Account for the pushed PLT data
+ pushl %ebp
+ cfi_adjust_cfa_offset (4)
+ pushl %eax # Preserve registers otherwise clobbered.
+ cfi_adjust_cfa_offset (4)
+ pushl %ecx
+ cfi_adjust_cfa_offset (4)
+ pushl %edx
+ cfi_adjust_cfa_offset (4)
+ movl %esp, %ecx
+ subl $8, %esp
+ cfi_adjust_cfa_offset (8)
+ movl $-1, 4(%esp)
+ leal 4(%esp), %edx
+ movl %edx, (%esp)
+ pushl %ecx # Address of the register structure
+ cfi_adjust_cfa_offset (4)
+ movl 40(%esp), %ecx # Load return address
+ movl 36(%esp), %edx # Copy args pushed by PLT in register. Note
+ movl 32(%esp), %eax # that `fixup' takes its parameters in regs.
+ call _dl_profile_fixup # Call resolver.
+ cfi_adjust_cfa_offset (-8)
+ movl (%esp), %edx
+ testl %edx, %edx
+ jns 1f
+ popl %edx
+ cfi_adjust_cfa_offset (-4)
+ popl %edx # Get register content back.
+ cfi_adjust_cfa_offset (-4)
+ popl %ecx
+ cfi_adjust_cfa_offset (-4)
+ xchgl %eax, (%esp) # Get %eax contents end store function address.
+ ret $16 # Jump to function address.
+
+ /*
+ +32 return address
+ +28 PLT1
+ +24 PLT2
+ +20 %esp
+ +16 %ebp
+ +12 %eax
+ +8 %ecx
+ +4 %edx
+ %esp free
+ */
+ cfi_adjust_cfa_offset (12)
+1: movl %ebx, (%esp)
+ cfi_rel_offset (3, 0)
+ movl %edx, %ebx # This is the frame buffer size
+ pushl %edi
+ cfi_adjust_cfa_offset (4)
+ cfi_rel_offset (7, 0)
+ pushl %esi
+ cfi_adjust_cfa_offset (4)
+ cfi_rel_offset (6, 0)
+ leal 44(%esp), %esi
+ movl %ebx, %ecx
+ movl %esp, %edi
+ subl %ebx, %edi
+ andl $0xfffffff0, %edi # Align stack
+ movl %esp, %ebx
+ cfi_def_cfa_register (3)
+ movl %edi, %esp
+ shrl $2, %ecx
+ rep
+ movsl
+ movl (%edi), %esi
+ cfi_restore (6)
+ movl 4(%edi), %edi
+ cfi_restore (7)
+ /*
+ %ebx+40 return address
+ %ebx+36 PLT1
+ %ebx+32 PLT2
+ %ebx+28 %esp
+ %ebx+24 %ebp
+ %ebx+20 %eax
+ %ebx+16 %ecx
+ %ebx+12 %edx
+ %ebx+8 %ebx
+ %ebx+4 free
+ %ebx free
+ %esp copied stack frame
+ */
+ movl %eax, (%ebx)
+ movl 12(%ebx), %edx
+ movl 16(%ebx), %ecx
+ movl 20(%ebx), %eax
+ call *(%ebx)
+ movl %ebx, %esp
+ cfi_def_cfa_register (4)
+ movl 8(%esp), %ebx
+ cfi_restore (3)
+ /*
+ +40 return address
+ +36 PLT1
+ +32 PLT2
+ +28 %esp
+ +24 %ebp
+ +20 %eax
+ +16 %ecx
+ +12 %edx
+ +8 free
+ +4 free
+ %esp free
+ */
+ subl $20, %esp
+ cfi_adjust_cfa_offset (20)
+ movl %eax, (%esp)
+ movl %edx, 4(%esp)
+ fstpt 8(%esp)
+ fstpt 20(%esp)
+ pushl %esp
+ cfi_adjust_cfa_offset (4)
+ leal 36(%esp), %ecx
+ movl 56(%esp), %eax
+ movl 60(%esp), %edx
+ call _dl_call_pltexit
+ movl (%esp), %eax
+ movl 4(%esp), %edx
+ fldt 20(%esp)
+ fldt 8(%esp)
+ addl $60, %esp
+ cfi_adjust_cfa_offset (-60)
+ ret
+ cfi_endproc
+ .size _dl_runtime_profile, .-_dl_runtime_profile
diff --git a/sysdeps/ia64/bits/link.h b/sysdeps/ia64/bits/link.h
index 7f8b0550d9..f751c23fd1 100644
--- a/sysdeps/ia64/bits/link.h
+++ b/sysdeps/ia64/bits/link.h
@@ -1,5 +1,63 @@
-struct link_map_machine
- {
- size_t fptr_table_len;
- Elf64_Addr *fptr_table;
- };
+/* Copyright (C) 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+/* Registers for entry into PLT on ia64. */
+typedef struct La_ia64_regs
+{
+ uint64_t lr_r8;
+ uint64_t lr_r9;
+ uint64_t lr_r10;
+ uint64_t lr_r11;
+ uint64_t lr_gr [8];
+ long double lr_fr [8];
+ uint64_t lr_unat;
+ uint64_t lr_sp;
+} La_ia64_regs;
+
+/* Return values for calls from PLT on ia64. */
+typedef struct La_ia64_retval
+{
+ uint64_t lrv_r8;
+ uint64_t lrv_r9;
+ uint64_t lrv_r10;
+ uint64_t lrv_r11;
+ long double lr_fr [8];
+} La_ia64_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf64_Addr la_ia64_gnu_pltenter (Elf64_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ La_ia64_regs *__regs,
+ unsigned int *__flags,
+ const char *__symname,
+ long int *__framesizep);
+extern unsigned int la_ia64_gnu_pltexit (Elf64_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ const La_ia64_regs *__inregs,
+ La_ia64_retval *__outregs,
+ const char *symname);
+
+__END_DECLS
diff --git a/sysdeps/ia64/bits/linkmap.h b/sysdeps/ia64/bits/linkmap.h
new file mode 100644
index 0000000000..7f8b0550d9
--- /dev/null
+++ b/sysdeps/ia64/bits/linkmap.h
@@ -0,0 +1,5 @@
+struct link_map_machine
+ {
+ size_t fptr_table_len;
+ Elf64_Addr *fptr_table;
+ };
diff --git a/sysdeps/ia64/dl-lookupcfg.h b/sysdeps/ia64/dl-lookupcfg.h
index 0ae3dd68ba..b50030ebd2 100644
--- a/sysdeps/ia64/dl-lookupcfg.h
+++ b/sysdeps/ia64/dl-lookupcfg.h
@@ -1,5 +1,5 @@
/* Configuration of lookup functions.
- Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2003, 2004 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
@@ -17,12 +17,11 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-/* The ia64 need more information from the symbol lookup function
- than just the address. */
-#define DL_LOOKUP_RETURNS_MAP
#define ELF_FUNCTION_PTR_IS_SPECIAL
#define DL_UNMAP_IS_SPECIAL
+#include <dl-fptr.h>
+
/* We do not support copy relocations for IA-64. */
#define DL_NO_COPY_RELOCS
@@ -59,3 +58,15 @@ extern void _dl_unmap (struct link_map *map);
#define DL_DT_INIT_ADDRESS(map, addr) DL_AUTO_FUNCTION_ADDRESS (map, addr)
#define DL_DT_FINI_ADDRESS(map, addr) DL_AUTO_FUNCTION_ADDRESS (map, addr)
+/* The type of the return value of fixup/profile_fixup. */
+#define DL_FIXUP_VALUE_TYPE struct fdesc
+/* Construct a value of type DL_FIXUP_VALUE_TYPE from a code address
+ and a link map. */
+#define DL_FIXUP_MAKE_VALUE(map, addr) \
+ ((struct fdesc) { (addr), (map)->l_info[DT_PLTGOT]->d_un.d_ptr })
+/* Extract the code address from a value of type DL_FIXUP_MAKE_VALUE.
+ */
+#define DL_FIXUP_VALUE_CODE_ADDR(value) (value).ip
+
+#define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value))
+#define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr))
diff --git a/sysdeps/ia64/dl-machine.h b/sysdeps/ia64/dl-machine.h
index 3108047869..55349690e3 100644
--- a/sysdeps/ia64/dl-machine.h
+++ b/sysdeps/ia64/dl-machine.h
@@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation inline functions. IA-64 version.
- Copyright (C) 1995-1997, 2000-2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1995-1997, 2000-2004, 2005 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
@@ -123,7 +123,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
doit = (Elf64_Addr) ((struct fdesc *) &_dl_runtime_resolve)->ip;
else
{
- if (_dl_name_match_p (GLRO(dl_profile), l))
+ if (GLRO(dl_profile) != NULL
+ && _dl_name_match_p (GLRO(dl_profile), l))
{
/* This is the object we are looking for. Say that we really
want profiling and the timers are started. */
@@ -139,133 +140,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
return lazy;
}
-
-/*
- This code is used in dl-runtime.c to call the `fixup' function
- and then redirect to the address it returns. `fixup()' takes two
- arguments, however profile_fixup() takes three.
-
- The ABI specifies that we will never see more than 8 input
- registers to a function call, thus it is safe to simply allocate
- those, and simpler than playing stack games.
- - 12/09/99 Jes
- */
-#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name) \
- extern void tramp_name (void); \
- asm ( \
-" .global " #tramp_name "#\n" \
-" .proc " #tramp_name "#\n" \
-#tramp_name ":\n" \
-" { .mmi\n" \
-" .prologue\n" \
-" .save ar.pfs, r40\n" \
-" alloc loc0 = ar.pfs, 8, 6, 3, 0\n" \
-" adds r2 = -144, r12\n" \
-" adds r3 = -128, r12\n" \
-" }\n" \
-" { .mii\n" \
-" .fframe 160\n" \
-" adds r12 = -160, r12\n" \
-" .save rp, r41\n" \
-" mov loc1 = b0\n" \
-" .body\n" \
-" mov out2 = b0 /* needed by fixup_profile */\n" \
-" ;;\n" \
-" }\n" \
-" { .mfb\n" \
-" mov loc2 = r8 /* preserve struct value register */\n" \
-" nop.f 0\n" \
-" nop.b 0\n" \
-" }\n" \
-" { .mii\n" \
-" mov loc3 = r9 /* preserve language specific register */\n" \
-" mov loc4 = r10 /* preserve language specific register */\n" \
-" mov loc5 = r11 /* preserve language specific register */\n" \
-" }\n" \
-" { .mmi\n" \
-" stf.spill [r2] = f8, 32\n" \
-" stf.spill [r3] = f9, 32\n" \
-" mov out0 = r16\n" \
-" ;;\n" \
-" }\n" \
-" { .mmi\n" \
-" stf.spill [r2] = f10, 32\n" \
-" stf.spill [r3] = f11, 32\n" \
-" shl out1 = r15, 4\n" \
-" ;;\n" \
-" }\n" \
-" { .mmi\n" \
-" stf.spill [r2] = f12, 32\n" \
-" stf.spill [r3] = f13, 32\n" \
-" shladd out1 = r15, 3, out1\n" \
-" ;;\n" \
-" }\n" \
-" { .mmb\n" \
-" stf.spill [r2] = f14\n" \
-" stf.spill [r3] = f15\n" \
-" br.call.sptk.many b0 = " #fixup_name "#\n" \
-" }\n" \
-" { .mii\n" \
-" ld8 r9 = [ret0], 8\n" \
-" adds r2 = 16, r12\n" \
-" adds r3 = 32, r12\n" \
-" ;;\n" \
-" }\n" \
-" { .mmi\n" \
-" ldf.fill f8 = [r2], 32\n" \
-" ldf.fill f9 = [r3], 32\n" \
-" mov b0 = loc1\n" \
-" ;;\n" \
-" }\n" \
-" { .mmi\n" \
-" ldf.fill f10 = [r2], 32\n" \
-" ldf.fill f11 = [r3], 32\n" \
-" mov b6 = r9\n" \
-" ;;\n" \
-" }\n" \
-" { .mmi\n" \
-" ldf.fill f12 = [r2], 32\n" \
-" ldf.fill f13 = [r3], 32\n" \
-" mov ar.pfs = loc0\n" \
-" ;;\n" \
-" }\n" \
-" { .mmi\n" \
-" ldf.fill f14 = [r2], 32\n" \
-" ldf.fill f15 = [r3], 32\n" \
-" .restore sp /* pop the unwind frame state */\n" \
-" adds r12 = 160, r12\n" \
-" ;;\n" \
-" }\n" \
-" { .mii\n" \
-" mov r9 = loc3 /* restore language specific register */\n" \
-" mov r10 = loc4 /* restore language specific register */\n" \
-" mov r11 = loc5 /* restore language specific register */\n" \
-" }\n" \
-" { .mii\n" \
-" ld8 gp = [ret0]\n" \
-" mov r8 = loc2 /* restore struct value register */\n" \
-" ;;\n" \
-" }\n" \
-" /* An alloc is needed for the break system call to work.\n" \
-" We don't care about the old value of the pfs register. */\n" \
-" { .mmb\n" \
-" .prologue\n" \
-" .body\n" \
-" alloc r2 = ar.pfs, 0, 0, 8, 0\n" \
-" br.sptk.many b6\n" \
-" ;;\n" \
-" }\n" \
-" .endp " #tramp_name "#\n");
-
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
- TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup); \
- TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup);
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
- TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup); \
- strong_alias (_dl_runtime_resolve, _dl_runtime_profile);
-#endif
+/* Names of the architecture-specific auditing callback functions. */
+#define ARCH_LA_PLTENTER ia64_gnu_pltenter
+#define ARCH_LA_PLTEXIT ia64_gnu_pltexit
/* Undo the adds out0 = 16, sp below to get at the value we want in
__libc_stack_end. */
@@ -454,34 +331,29 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
#define ELF_MACHINE_START_ADDRESS(map, start) \
DL_STATIC_FUNCTION_ADDRESS (map, start)
-#define elf_machine_profile_fixup_plt(l, reloc, rel_addr, value) \
- elf_machine_fixup_plt (l, reloc, rel_addr, value)
-
-#define elf_machine_profile_plt(reloc_addr) ((Elf64_Addr) (reloc_addr))
-
/* Fixup a PLT entry to bounce directly to the function at VALUE. */
-static inline Elf64_Addr __attribute__ ((always_inline))
+static inline struct fdesc __attribute__ ((always_inline))
elf_machine_fixup_plt (struct link_map *l, lookup_t t,
const Elf64_Rela *reloc,
- Elf64_Addr *reloc_addr, Elf64_Addr value)
+ Elf64_Addr *reloc_addr, struct fdesc value)
{
/* l is the link_map for the caller, t is the link_map for the object
* being called */
/* got has already been relocated in elf_get_dynamic_info() */
- reloc_addr[1] = t->l_info[DT_PLTGOT]->d_un.d_ptr;
+ reloc_addr[1] = value.gp;
/* we need a "release" here to ensure that the gp is visible before
the code entry point is updated: */
- ((volatile Elf64_Addr *) reloc_addr)[0] = value;
- return (Elf64_Addr) reloc_addr;
+ ((volatile Elf64_Addr *) reloc_addr)[0] = value.ip;
+ return value;
}
/* Return the final value of a plt relocation. */
-static inline Elf64_Addr
+static inline struct fdesc
elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
- Elf64_Addr value)
+ struct fdesc value)
{
/* No need to handle rel vs rela since IA64 is rela only */
- return value + reloc->r_addend;
+ return (struct fdesc) { value.ip + reloc->r_addend, value.gp };
}
#endif /* !dl_machine_h */
@@ -552,7 +424,8 @@ elf_machine_rela (struct link_map *map,
;/* No adjustment. */
else if (r_type == R_IA64_IPLTLSB)
{
- elf_machine_fixup_plt (NULL, sym_map, reloc, reloc_addr, value);
+ elf_machine_fixup_plt (NULL, NULL, reloc, reloc_addr,
+ DL_FIXUP_MAKE_VALUE (sym_map, value));
return;
}
else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_FPTR64LSB))
diff --git a/sysdeps/ia64/dl-trampoline.S b/sysdeps/ia64/dl-trampoline.S
new file mode 100644
index 0000000000..b7969a6cf0
--- /dev/null
+++ b/sysdeps/ia64/dl-trampoline.S
@@ -0,0 +1,537 @@
+/* PLT trampolines. ia64 version.
+ Copyright (C) 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+#undef ret
+
+/*
+ This code is used in dl-runtime.c to call the `_dl_fixup' function
+ and then redirect to the address it returns. `_dl_fixup()' takes two
+ arguments, however _dl_profile_fixup() takes five.
+
+ The ABI specifies that we will never see more than 8 input
+ registers to a function call, thus it is safe to simply allocate
+ those, and simpler than playing stack games. */
+
+/* Used to save and restore 8 incoming fp registers */
+#define RESOLVE_FRAME_SIZE (16*8)
+
+ENTRY(_dl_runtime_resolve)
+ { .mmi
+ .prologue
+ .save ar.pfs, r40
+ alloc loc0 = ar.pfs, 8, 6, 2, 0
+ /* Use the 16 byte scratch area. r2 will start at f8 and
+ r3 will start at f9. */
+ adds r2 = -(RESOLVE_FRAME_SIZE - 16), r12
+ adds r3 = -(RESOLVE_FRAME_SIZE - 32), r12
+ }
+ { .mii
+ .fframe RESOLVE_FRAME_SIZE
+ adds r12 = -RESOLVE_FRAME_SIZE, r12
+ .save rp, loc1
+ mov loc1 = b0
+ .body
+ mov loc2 = r8 /* preserve struct value register */
+ ;;
+ }
+ { .mii
+ mov loc3 = r9 /* preserve language specific register */
+ mov loc4 = r10 /* preserve language specific register */
+ mov loc5 = r11 /* preserve language specific register */
+ }
+ { .mmi
+ stf.spill [r2] = f8, 32
+ stf.spill [r3] = f9, 32
+ mov out0 = r16
+ ;;
+ }
+ { .mmi
+ stf.spill [r2] = f10, 32
+ stf.spill [r3] = f11, 32
+ shl out1 = r15, 4
+ ;;
+ }
+ { .mmi
+ stf.spill [r2] = f12, 32
+ stf.spill [r3] = f13, 32
+ /* Relocation record is 24 byte. */
+ shladd out1 = r15, 3, out1
+ ;;
+ }
+ { .mmb
+ stf.spill [r2] = f14
+ stf.spill [r3] = f15
+ br.call.sptk.many b0 = _dl_fixup
+ }
+ { .mii
+ /* Skip the 16byte scratch area. */
+ adds r2 = 16, r12
+ adds r3 = 32, r12
+ mov b6 = ret0
+ ;;
+ }
+ { .mmi
+ ldf.fill f8 = [r2], 32
+ ldf.fill f9 = [r3], 32
+ mov b0 = loc1
+ ;;
+ }
+ { .mmi
+ ldf.fill f10 = [r2], 32
+ ldf.fill f11 = [r3], 32
+ mov gp = ret1
+ ;;
+ }
+ { .mmi
+ ldf.fill f12 = [r2], 32
+ ldf.fill f13 = [r3], 32
+ mov ar.pfs = loc0
+ ;;
+ }
+ { .mmi
+ ldf.fill f14 = [r2], 32
+ ldf.fill f15 = [r3], 32
+ .restore sp /* pop the unwind frame state */
+ adds r12 = RESOLVE_FRAME_SIZE, r12
+ ;;
+ }
+ { .mii
+ mov r9 = loc3 /* restore language specific register */
+ mov r10 = loc4 /* restore language specific register */
+ mov r11 = loc5 /* restore language specific register */
+ }
+ { .mii
+ mov r8 = loc2 /* restore struct value register */
+ ;;
+ }
+ /* An alloc is needed for the break system call to work.
+ We don't care about the old value of the pfs register. */
+ { .mmb
+ .prologue
+ .body
+ alloc r2 = ar.pfs, 0, 0, 8, 0
+ br.sptk.many b6
+ ;;
+ }
+END(_dl_runtime_resolve)
+
+
+/* The fourth argument to _dl_profile_fixup and the third one to
+ _dl_call_pltexit are a pointer to La_ia64_regs:
+
+ 8byte r8
+ 8byte r9
+ 8byte r10
+ 8byte r11
+ 8byte in0
+ 8byte in1
+ 8byte in2
+ 8byte in3
+ 8byte in4
+ 8byte in5
+ 8byte in6
+ 8byte in7
+ 16byte f8
+ 16byte f9
+ 16byte f10
+ 16byte f11
+ 16byte f12
+ 16byte f13
+ 16byte f14
+ 16byte f15
+ 8byte ar.unat
+ 8byte sp
+
+ The fifth argument to _dl_profile_fixup is a pointer to long int.
+ The fourth argument to _dl_call_pltexit is a pointer to
+ La_ia64_retval:
+
+ 8byte r8
+ 8byte r9
+ 8byte r10
+ 8byte r11
+ 16byte f8
+ 16byte f9
+ 16byte f10
+ 16byte f11
+ 16byte f12
+ 16byte f13
+ 16byte f14
+ 16byte f15
+
+ Since stack has to be 16 byte aligned, the stack allocation is in
+ 16byte increment. Before calling _dl_profile_fixup, the stack will
+ look like
+
+ psp new frame_size
+ +16 La_ia64_regs
+ sp scratch
+
+ */
+
+#define PLTENTER_FRAME_SIZE (4*8 + 8*8 + 8*16 + 2*8 + 16)
+#define PLTEXIT_FRAME_SIZE (PLTENTER_FRAME_SIZE + 4*8 + 8*16)
+
+ENTRY(_dl_runtime_profile)
+ { .mii
+ .prologue
+ .save ar.pfs, r40
+ alloc loc0 = ar.pfs, 8, 12, 8, 0
+ .vframe loc10
+ mov loc10 = r12
+ .save rp, loc1
+ mov loc1 = b0
+ }
+ { .mii
+ .save ar.unat, r17
+ mov r17 = ar.unat
+ .save ar.lc, loc6
+ mov loc6 = ar.lc
+ mov loc11 = gp
+ }
+ { .mii
+ .body
+ /* There is a 16 byte scratch area. r2 will start at r8 and
+ r3 will start at r9 for La_ia64_regs. */
+ adds r2 = -(PLTENTER_FRAME_SIZE - 16), r12
+ adds r3 = -(PLTENTER_FRAME_SIZE - 24), r12
+ adds r12 = -PLTENTER_FRAME_SIZE, r12
+ ;;
+ }
+ { .mmi
+ st8 [r2] = r8, 16;
+ st8 [r3] = r9, 16;
+ mov out2 = b0 /* needed by _dl_fixup_profile */
+ ;;
+ }
+ { .mmi
+ st8 [r2] = r10, 16;
+ st8 [r3] = r11, 16;
+ adds out3 = 16, r12 /* pointer to La_ia64_regs */
+ ;;
+ }
+ { .mmi
+ .mem.offset 0, 0
+ st8.spill [r2] = in0, 16
+ .mem.offset 8, 0
+ st8.spill [r3] = in1, 16
+ mov out4 = loc10 /* pointer to new frame size */
+ ;;
+ }
+ { .mmi
+ .mem.offset 0, 0
+ st8.spill [r2] = in2, 16
+ .mem.offset 8, 0
+ st8.spill [r3] = in3, 16
+ mov loc2 = r8 /* preserve struct value register */
+ ;;
+ }
+ { .mmi
+ .mem.offset 0, 0
+ st8.spill [r2] = in4, 16
+ .mem.offset 8, 0
+ st8.spill [r3] = in5, 16
+ mov loc3 = r9 /* preserve language specific register */
+ ;;
+ }
+ { .mmi
+ .mem.offset 0, 0
+ st8 [r2] = in6, 16
+ .mem.offset 8, 0
+ st8 [r3] = in7, 24 /* adjust for f9 */
+ mov loc4 = r10 /* preserve language specific register */
+ ;;
+ }
+ { .mii
+ mov r18 = ar.unat /* save it in La_ia64_regs */
+ mov loc7 = out3 /* save it for _dl_call_pltexit */
+ mov loc5 = r11 /* preserve language specific register */
+ }
+ { .mmi
+ stf.spill [r2] = f8, 32
+ stf.spill [r3] = f9, 32
+ mov out0 = r16 /* needed by _dl_fixup_profile */
+ ;;
+ }
+ { .mii
+ mov ar.unat = r17 /* restore it for function call */
+ mov loc8 = r16 /* save it for _dl_call_pltexit */
+ nop.i 0x0
+ }
+ { .mmi
+ stf.spill [r2] = f10, 32
+ stf.spill [r3] = f11, 32
+ shl out1 = r15, 4
+ ;;
+ }
+ { .mmi
+ stf.spill [r2] = f12, 32
+ stf.spill [r3] = f13, 32
+ /* Relocation record is 24 byte. */
+ shladd out1 = r15, 3, out1
+ ;;
+ }
+ { .mmi
+ stf.spill [r2] = f14, 32
+ stf.spill [r3] = f15, 24
+ mov loc9 = out1 /* save it for _dl_call_pltexit */
+ ;;
+ }
+ { .mmb
+ st8 [r2] = r18 /* store ar.unat */
+ st8 [r3] = loc10 /* store sp */
+ br.call.sptk.many b0 = _dl_profile_fixup
+ }
+ { .mii
+ /* Skip the 16byte scratch area, 4 language specific GRs and
+ 8 incoming GRs to restore incoming fp registers. */
+ adds r2 = (4*8 + 8*8 + 16), r12
+ adds r3 = (4*8 + 8*8 + 32), r12
+ mov b6 = ret0
+ ;;
+ }
+ { .mmi
+ ldf.fill f8 = [r2], 32
+ ldf.fill f9 = [r3], 32
+ mov gp = ret1
+ ;;
+ }
+ { .mmi
+ ldf.fill f10 = [r2], 32
+ ldf.fill f11 = [r3], 32
+ mov r8 = loc2 /* restore struct value register */
+ ;;
+ }
+ { .mmi
+ ldf.fill f12 = [r2], 32
+ ldf.fill f13 = [r3], 32
+ mov r9 = loc3 /* restore language specific register */
+ ;;
+ }
+ { .mmi
+ ldf.fill f14 = [r2], 32
+ ldf.fill f15 = [r3], 32
+ mov r10 = loc4 /* restore language specific register */
+ ;;
+ }
+ { .mii
+ ld8 r15 = [loc10] /* load the new frame size */
+ mov r11 = loc5 /* restore language specific register */
+ ;;
+ cmp.eq p6, p7 = -1, r15
+ ;;
+ }
+ { .mii
+(p7) cmp.eq p8, p9 = 0, r15
+(p6) mov b0 = loc1
+(p6) mov ar.lc = loc6
+ }
+ { .mib
+ nop.m 0x0
+(p6) mov ar.pfs = loc0
+(p6) br.cond.dptk.many .Lresolved
+ ;;
+ }
+
+ /* At this point, the stack looks like
+
+ +psp free
+ +16 La_ia64_regs
+ sp scratch
+
+ We need to keep the current stack and call the resolved
+ function by copying the r15 byte from sp + PLTENTER_FRAME_SIZE
+ + 16 (scratch area) to sp + 16 (scratch area). Since stack
+ has to be 16byte aligned, we around r15 up to 16byte. */
+
+ { .mbb
+(p9) adds r15 = 15, r15
+(p8) br.cond.dptk.many .Lno_new_frame
+ nop.b 0x0
+ ;;
+ }
+ { .mmi
+ and r15 = -16, r15
+ ;;
+ /* We don't copy the 16byte scatch area. Prepare r16/r17 as
+ destination. */
+ sub r16 = r12, r15
+ sub r17 = r12, r15
+ ;;
+ }
+ { .mii
+ adds r16 = 16, r16
+ adds r17 = 24, r17
+ sub r12 = r12, r15 /* Adjust stack */
+ ;;
+ }
+ { .mii
+ nop.m 0x0
+ shr r15 = r15, 4
+ ;;
+ adds r15 = -1, r15
+ ;;
+ }
+ { .mii
+ /* Skip the 16byte scatch area. Prepare r2/r3 as source. */
+ adds r2 = 16, loc10
+ adds r3 = 24, loc10
+ mov ar.lc = r15
+ ;;
+ }
+.Lcopy:
+ { .mmi
+ ld8 r18 = [r2], 16
+ ld8 r19 = [r3], 16
+ nop.i 0x0
+ ;;
+ }
+ { .mmb
+ st8 [r16] = r18, 16
+ st8 [r17] = r19, 16
+ br.cloop.sptk.few .Lcopy
+ }
+.Lno_new_frame:
+ { .mii
+ mov out0 = in0
+ mov out1 = in1
+ mov out2 = in2
+ }
+ { .mii
+ mov out3 = in3
+ mov out4 = in4
+ mov out5 = in5
+ }
+ { .mib
+ mov out6 = in6
+ mov out7 = in7
+ /* Call the resolved function */
+ br.call.sptk.many b0 = b6
+ }
+ { .mii
+ /* Prepare stack for _dl_call_pltexit. Loc10 has the original
+ stack pointer. */
+ adds r12 = -PLTEXIT_FRAME_SIZE, loc10
+ adds r2 = -(PLTEXIT_FRAME_SIZE - 16), loc10
+ adds r3 = -(PLTEXIT_FRAME_SIZE - 24), loc10
+ ;;
+ }
+ { .mmi
+ /* Load all possible return values into buffer. */
+ st8 [r2] = r8, 16
+ st8 [r3] = r9, 16
+ mov out0 = loc8
+ ;;
+ }
+ { .mmi
+ st8 [r2] = r10, 16
+ st8 [r3] = r11, 24
+ mov out1 = loc9
+ ;;
+ }
+ { .mmi
+ stf.spill [r2] = f8, 32
+ stf.spill [r3] = f9, 32
+ mov out2 = loc7 /* Pointer to La_ia64_regs */
+ ;;
+ }
+ { .mmi
+ stf.spill [r2] = f10, 32
+ stf.spill [r3] = f11, 32
+ adds out3 = 16, r12 /* Pointer to La_ia64_retval */
+ ;;
+ }
+ { .mmi
+ stf.spill [r2] = f12, 32
+ stf.spill [r3] = f13, 32
+ /* We need to restore gp for _dl_call_pltexit. */
+ mov gp = loc11
+ ;;
+ }
+ { .mmb
+ stf.spill [r2] = f14
+ stf.spill [r3] = f15
+ br.call.sptk.many b0 = _dl_call_pltexit
+ }
+ { .mmi
+ /* Load all the non-floating and floating return values. Skip
+ the 16byte scratch area. */
+ adds r2 = 16, r12
+ adds r3 = 24, r12
+ nop.i 0x0
+ ;;
+ }
+ { .mmi
+ ld8 r8 = [r2], 16
+ ld8 r9 = [r3], 16
+ nop.i 0x0
+ ;;
+ }
+ { .mmi
+ ld8 r10 = [r2], 16
+ ld8 r11 = [r3], 24
+ nop.i 0x0
+ ;;
+ }
+ { .mmi
+ ldf.fill f8 = [r2], 32
+ ldf.fill f9 = [r3], 32
+ mov ar.lc = loc6
+ ;;
+ }
+ { .mmi
+ ldf.fill f10 = [r2], 32
+ ldf.fill f11 = [r3], 32
+ mov ar.pfs = loc0
+ ;;
+ }
+ { .mmi
+ ldf.fill f12 = [r2], 32
+ ldf.fill f13 = [r3], 32
+ mov b0 = loc1
+ ;;
+ }
+ { .mmi
+ ldf.fill f14 = [r2]
+ ldf.fill f15 = [r3]
+ /* We know that the previous stack pointer, loc10, isn't 0.
+ We use it to reload p7. */
+ cmp.ne p7, p0 = 0, loc10
+ ;;
+ }
+.Lresolved:
+ { .mmb
+ .restore sp
+ mov r12 = loc10
+(p7) br.ret.sptk.many b0
+ ;;
+ }
+ /* An alloc is needed for the break system call to work. We
+ don't care about the old value of the pfs register. After
+ this alloc, we can't use any rotating registers. Otherwise
+ assembler won't be happy. This has to be at the end. */
+ { .mmb
+ .prologue
+ .body
+ alloc r2 = ar.pfs, 0, 0, 8, 0
+ br.sptk.many b6
+ ;;
+ }
+END(_dl_runtime_profile)
diff --git a/sysdeps/ia64/fpu/e_logl.c b/sysdeps/ia64/fpu/e_logl.c
deleted file mode 100644
index 41254ae60a..0000000000
--- a/sysdeps/ia64/fpu/e_logl.c
+++ /dev/null
@@ -1 +0,0 @@
-/* Not needed. */
diff --git a/sysdeps/ia64/libc-tls.c b/sysdeps/ia64/libc-tls.c
index f1df4cd12e..3a6b8e5532 100644
--- a/sysdeps/ia64/libc-tls.c
+++ b/sysdeps/ia64/libc-tls.c
@@ -30,7 +30,7 @@ void *
__tls_get_addr (size_t m, size_t offset)
{
dtv_t *dtv = THREAD_DTV ();
- return (char *) dtv[1].pointer + offset;
+ return (char *) dtv[1].pointer.val + offset;
}
#endif
diff --git a/sysdeps/linkmap.h b/sysdeps/linkmap.h
new file mode 100644
index 0000000000..470b4d3e5f
--- /dev/null
+++ b/sysdeps/linkmap.h
@@ -0,0 +1,4 @@
+struct link_map_machine
+ {
+ /* empty by default */
+ };
diff --git a/sysdeps/m68k/bits/link.h b/sysdeps/m68k/bits/link.h
new file mode 100644
index 0000000000..9d0a94592f
--- /dev/null
+++ b/sysdeps/m68k/bits/link.h
@@ -0,0 +1,58 @@
+/* Copyright (C) 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+/* Registers for entry into PLT on M68K. */
+typedef struct La_m68k_regs
+{
+ uint32_t lr_a0;
+ uint32_t lr_a1;
+ uint32_t lr_sp;
+} La_m68k_regs;
+
+/* Return values for calls from PLT on M68K. */
+typedef struct La_m68k_retval
+{
+ uint32_t lrv_d0;
+ uint32_t lrv_d1;
+ uint32_t lrv_a0;
+ long double lrv_fp0;
+} La_m68k_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_m68k_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ La_m68k_regs *__regs,
+ unsigned int *__flags,
+ const char *__symname,
+ long int *__framesizep);
+extern unsigned int la_m68k_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ const La_m68k_regs *__inregs,
+ La_m68k_retval *__outregs,
+ const char *symname);
+
+__END_DECLS
diff --git a/sysdeps/m68k/dl-machine.h b/sysdeps/m68k/dl-machine.h
index 146c5866a9..89d7106365 100644
--- a/sysdeps/m68k/dl-machine.h
+++ b/sysdeps/m68k/dl-machine.h
@@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation inline functions. m68k version.
- Copyright (C) 1996-2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1996-2001, 2002, 2003, 2004, 2005 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
@@ -85,7 +85,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
got[2] = (Elf32_Addr) &_dl_runtime_profile;
- if (_dl_name_match_p (GLRO(dl_profile), l))
+ if (GLRO(dl_profile) != NULL
+ && _dl_name_match_p (GLRO(dl_profile), l))
{
/* This is the object we are looking for. Say that we really
want profiling and the timers are started. */
@@ -101,36 +102,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
return lazy;
}
-/* This code is used in dl-runtime.c to call the `fixup' function
- and then redirect to the address it returns. */
-#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name) \
-"| Trampoline for " #fixup_name "\n\
- .globl " #tramp_name "\n\
- .type " #tramp_name ", @function\n\
-" #tramp_name ":\n\
- | Save %a0 (struct return address) and %a1.\n\
- move.l %a0, -(%sp)\n\
- move.l %a1, -(%sp)\n\
- | Call the real address resolver.\n\
- jbsr " #fixup_name "\n\
- | Restore register %a0 and %a1.\n\
- move.l (%sp)+, %a1\n\
- move.l (%sp)+, %a0\n\
- | Pop parameters\n\
- addq.l #8, %sp\n\
- | Call real function.\n\
- jmp (%d0)\n\
- .size " #tramp_name ", . - " #tramp_name "\n"
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
-asm (TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup) \
- TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup));
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
-asm (TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup) \
- ".globl _dl_runtime_profile\n" \
- ".set _dl_runtime_profile, _dl_runtime_resolve");
-#endif
#define ELF_MACHINE_RUNTIME_FIXUP_ARGS long int save_a0, long int save_a1
@@ -216,9 +187,13 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
return value;
}
+/* Names of the architecture-specific auditing callback functions. */
+#define ARCH_LA_PLTENTER m68k_gnu_pltenter
+#define ARCH_LA_PLTEXIT m68k_gnu_pltexit
+
#endif /* !dl_machine_h */
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
MAP is the object containing the reloc. */
@@ -236,9 +211,15 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
else
{
const Elf32_Sym *const refsym = sym;
+#ifndef RTLD_BOOTSTRAP
+ struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+ Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
+#else
Elf32_Addr value = RESOLVE (&sym, version, r_type);
+
if (sym)
value += sym->st_value;
+#endif /* !RTLD_BOOTSTRAP */
switch (r_type)
{
@@ -313,4 +294,4 @@ elf_machine_lazy_rel (struct link_map *map,
_dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 1);
}
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/m68k/dl-trampoline.S b/sysdeps/m68k/dl-trampoline.S
new file mode 100644
index 0000000000..8791280371
--- /dev/null
+++ b/sysdeps/m68k/dl-trampoline.S
@@ -0,0 +1,129 @@
+/* PLT trampolines. m68k version.
+ Copyright (C) 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+
+ .text
+ .globl _dl_runtime_resolve
+ .type _dl_runtime_resolve, @function
+_dl_runtime_resolve:
+ | Save %a0 (struct return address) and %a1.
+ move.l %a0, -(%sp)
+ move.l %a1, -(%sp)
+ | Call the real address resolver.
+ jbsr _dl_fixup
+ | Restore register %a0 and %a1.
+ move.l (%sp)+, %a1
+ move.l (%sp)+, %a0
+ | Pop parameters
+ addq.l #8, %sp
+ | Call real function.
+ jmp (%d0)
+ .size _dl_runtime_resolve, . - _dl_runtime_resolve
+
+ .text
+ .globl _dl_runtime_profile
+ .type _dl_runtime_profile, @function
+_dl_runtime_profile:
+ pea 8(%sp)
+ move.l %a1, -(%sp)
+ move.l %a0, -(%sp)
+ pea -1.w
+ | Push parameters for _dl_profile_fixup
+ pea (%sp)
+ pea 8(%sp)
+ move.l 32(%sp), -(%sp)
+ move.l 32(%sp), -(%sp)
+ move.l 32(%sp), -(%sp)
+ subq.l #8, %sp
+ | Call the real address resolver.
+ jbsr _dl_profile_fixup
+ | Pop parameters
+ lea 28(%sp), %sp
+ move.l (%sp), %d1
+ jpl 1f
+ addq.l #4, %sp
+ | Restore register %a0 and %a1.
+ move.l (%sp)+, %a0
+ move.l (%sp)+, %a1
+ lea 12(%sp), %sp
+ | Call real function.
+ jmp (%d0)
+
+ /*
+ +24 return address
+ +20 PLT1
+ +16 PLT2
+ +12 %sp
+ +8 %a1
+ +4 %a0
+ %sp free
+ */
+1: move.l %a2, (%sp)
+ move.l %sp, %a2
+ move.l %sp, %a0
+ lea 28(%sp), %a1
+ | Round framesize up to even
+ addq.l #1, %d1
+ lsr #1, %d1
+ sub.l %d1, %a0
+ sub.l %d1, %a0
+ move.l %a0, %sp
+ jra 2f
+1: move.w (%a1)+, (%a0)+
+2: dbra %d1,1b
+ /*
+ %a2+24 return address
+ %a2+20 PLT1
+ %a2+16 PLT2
+ %a2+12 %sp
+ %a2+8 %a1
+ %a2+4 %a0
+ %a2 %a2
+ %sp copied stack frame
+ */
+
+ move.l 4(%a2), %a0
+ move.l 8(%a2), %a1
+ jsr (%d0)
+ move.l %a2, %sp
+ move.l (%sp)+, %a2
+ /*
+ +20 return address
+ +16 PLT1
+ +12 PLT2
+ +8 %sp
+ +4 %a1
+ %sp %a0
+ */
+ fmove.x %fp0, -(%sp)
+ move.l %d1, -(%sp)
+ move.l %d0, -(%sp)
+ pea (%sp)
+ pea 20(%sp)
+ move.l 40(%sp), -(%sp)
+ move.l 40(%sp), -(%sp)
+ jbsr _dl_call_pltexit
+ lea 16(%sp), %sp
+ move.l (%sp)+, %d0
+ move.l (%sp)+, %d1
+ fmove.x (%sp)+, %fp0
+ lea 20(%sp), %sp
+ rts
+ .size _dl_runtime_profile, . - _dl_runtime_profile
diff --git a/sysdeps/mach/hurd/tls.h b/sysdeps/mach/hurd/tls.h
index bc15b4dab6..cce42ef374 100644
--- a/sysdeps/mach/hurd/tls.h
+++ b/sysdeps/mach/hurd/tls.h
@@ -1,5 +1,5 @@
/* Definitions for thread-local data handling. Hurd version.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005 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
@@ -23,6 +23,7 @@
#if defined HAVE_TLS_SUPPORT && !defined ASSEMBLER
# include <stddef.h>
+# include <stdbool.h>
# include <mach/mig_errors.h>
# include <mach.h>
@@ -31,7 +32,11 @@
typedef union dtv
{
size_t counter;
- void *pointer;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
} dtv_t;
diff --git a/sysdeps/powerpc/powerpc32/bits/link.h b/sysdeps/powerpc/powerpc32/bits/link.h
new file mode 100644
index 0000000000..7f44087120
--- /dev/null
+++ b/sysdeps/powerpc/powerpc32/bits/link.h
@@ -0,0 +1,62 @@
+/* Copyright (C) 2004, 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+/* Registers for entry into PLT on PPC32. */
+typedef struct La_ppc32_regs
+{
+ uint32_t lr_reg[8];
+ double lr_fp[8];
+ uint32_t lr_vreg[12][4];
+ uint32_t lr_r1;
+ uint32_t lr_lr;
+} La_ppc32_regs;
+
+/* Return values for calls from PLT on PPC32. */
+typedef struct La_ppc32_retval
+{
+ uint32_t lrv_r3;
+ uint32_t lrv_r4;
+ double lrv_fp[8];
+ uint32_t lrv_v2[4];
+} La_ppc32_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_ppc32_gnu_pltenter (Elf32_Sym *__sym,
+ unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ La_ppc32_regs *__regs,
+ unsigned int *__flags,
+ const char *__symname,
+ long int *__framesizep);
+extern unsigned int la_ppc32_gnu_pltexit (Elf32_Sym *__sym,
+ unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ const La_ppc32_regs *__inregs,
+ La_ppc32_retval *__outregs,
+ const char *symname);
+
+__END_DECLS
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.c b/sysdeps/powerpc/powerpc32/dl-machine.c
index 06960716b9..4120a02382 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.c
+++ b/sysdeps/powerpc/powerpc32/dl-machine.c
@@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation functions. PowerPC version.
- Copyright (C) 1995-2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1995-2003, 2004, 2005 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
@@ -242,7 +242,8 @@ __elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
: _dl_runtime_resolve);
Elf32_Word offset;
- if (profile && _dl_name_match_p (GLRO(dl_profile), map))
+ if (profile && GLRO(dl_profile) != NULL
+ && _dl_name_match_p (GLRO(dl_profile), map))
/* This is the object we are looking for. Say that we really
want profiling and the timers are started. */
GL(dl_profile_map) = map;
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h
index a8c1e3e490..de3b9e923a 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.h
+++ b/sysdeps/powerpc/powerpc32/dl-machine.h
@@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation inline functions. PowerPC version.
- Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1995-2002, 2003, 2005 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
@@ -100,160 +100,6 @@ elf_machine_load_address (void)
/* The PLT uses Elf32_Rela relocs. */
#define elf_machine_relplt elf_machine_rela
-/* This code is used in dl-runtime.c to call the `fixup' function
- and then redirect to the address it returns. It is called
- from code built in the PLT by elf_machine_runtime_setup. */
-#if !defined PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\
- .section \".text\" \n\
- .align 2 \n\
- .globl _dl_runtime_resolve \n\
- .type _dl_runtime_resolve,@function \n\
-_dl_runtime_resolve: \n\
- # We need to save the registers used to pass parameters, and register 0,\n\
- # which is used by _mcount; the registers are saved in a stack frame.\n\
- stwu 1,-64(1) \n\
- stw 0,12(1) \n\
- stw 3,16(1) \n\
- stw 4,20(1) \n\
- # The code that calls this has put parameters for `fixup' in r12 and r11.\n\
- mr 3,12 \n\
- stw 5,24(1) \n\
- mr 4,11 \n\
- stw 6,28(1) \n\
- mflr 0 \n\
- # We also need to save some of the condition register fields.\n\
- stw 7,32(1) \n\
- stw 0,48(1) \n\
- stw 8,36(1) \n\
- mfcr 0 \n\
- stw 9,40(1) \n\
- stw 10,44(1) \n\
- stw 0,8(1) \n\
- bl fixup@local \n\
- # 'fixup' returns the address we want to branch to.\n\
- mtctr 3 \n\
- # Put the registers back...\n\
- lwz 0,48(1) \n\
- lwz 10,44(1) \n\
- lwz 9,40(1) \n\
- mtlr 0 \n\
- lwz 8,36(1) \n\
- lwz 0,8(1) \n\
- lwz 7,32(1) \n\
- lwz 6,28(1) \n\
- mtcrf 0xFF,0 \n\
- lwz 5,24(1) \n\
- lwz 4,20(1) \n\
- lwz 3,16(1) \n\
- lwz 0,12(1) \n\
- # ...unwind the stack frame, and jump to the PLT entry we updated.\n\
- addi 1,1,64 \n\
- bctr \n\
- .size _dl_runtime_resolve,.-_dl_runtime_resolve \n\
- \n\
- .align 2 \n\
- .globl _dl_prof_resolve \n\
- .type _dl_prof_resolve,@function \n\
-_dl_prof_resolve: \n\
- # We need to save the registers used to pass parameters, and register 0,\n\
- # which is used by _mcount; the registers are saved in a stack frame.\n\
- stwu 1,-64(1) \n\
- stw 0,12(1) \n\
- stw 3,16(1) \n\
- stw 4,20(1) \n\
- # The code that calls this has put parameters for `fixup' in r12 and r11.\n\
- mr 3,12 \n\
- stw 5,24(1) \n\
- mr 4,11 \n\
- stw 6,28(1) \n\
- mflr 5 \n\
- # We also need to save some of the condition register fields.\n\
- stw 7,32(1) \n\
- stw 5,48(1) \n\
- stw 8,36(1) \n\
- mfcr 0 \n\
- stw 9,40(1) \n\
- stw 10,44(1) \n\
- stw 0,8(1) \n\
- bl profile_fixup@local \n\
- # 'fixup' returns the address we want to branch to.\n\
- mtctr 3 \n\
- # Put the registers back...\n\
- lwz 0,48(1) \n\
- lwz 10,44(1) \n\
- lwz 9,40(1) \n\
- mtlr 0 \n\
- lwz 8,36(1) \n\
- lwz 0,8(1) \n\
- lwz 7,32(1) \n\
- lwz 6,28(1) \n\
- mtcrf 0xFF,0 \n\
- lwz 5,24(1) \n\
- lwz 4,20(1) \n\
- lwz 3,16(1) \n\
- lwz 0,12(1) \n\
- # ...unwind the stack frame, and jump to the PLT entry we updated.\n\
- addi 1,1,64 \n\
- bctr \n\
- .size _dl_prof_resolve,.-_dl_prof_resolve \n\
- # Undo '.section text'.\n\
- .previous \n\
-");
-#else
-# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\
- .section \".text\" \n\
- .align 2 \n\
- .globl _dl_runtime_resolve \n\
- .globl _dl_prof_resolve \n\
- .type _dl_runtime_resolve,@function \n\
- .type _dl_prof_resolve,@function \n\
-_dl_runtime_resolve: \n\
-_dl_prof_resolve: \n\
- # We need to save the registers used to pass parameters, and register 0,\n\
- # which is used by _mcount; the registers are saved in a stack frame.\n\
- stwu 1,-64(1) \n\
- stw 0,12(1) \n\
- stw 3,16(1) \n\
- stw 4,20(1) \n\
- # The code that calls this has put parameters for `fixup' in r12 and r11.\n\
- mr 3,12 \n\
- stw 5,24(1) \n\
- mr 4,11 \n\
- stw 6,28(1) \n\
- mflr 0 \n\
- # We also need to save some of the condition register fields.\n\
- stw 7,32(1) \n\
- stw 0,48(1) \n\
- stw 8,36(1) \n\
- mfcr 0 \n\
- stw 9,40(1) \n\
- stw 10,44(1) \n\
- stw 0,8(1) \n\
- bl fixup@local \n\
- # 'fixup' returns the address we want to branch to.\n\
- mtctr 3 \n\
- # Put the registers back...\n\
- lwz 0,48(1) \n\
- lwz 10,44(1) \n\
- lwz 9,40(1) \n\
- mtlr 0 \n\
- lwz 8,36(1) \n\
- lwz 0,8(1) \n\
- lwz 7,32(1) \n\
- lwz 6,28(1) \n\
- mtcrf 0xFF,0 \n\
- lwz 5,24(1) \n\
- lwz 4,20(1) \n\
- lwz 3,16(1) \n\
- lwz 0,12(1) \n\
- # ...unwind the stack frame, and jump to the PLT entry we updated.\n\
- addi 1,1,64 \n\
- bctr \n\
- .size _dl_runtime_resolve,.-_dl_runtime_resolve \n\
-");
-#endif
-
/* Mask identifying addresses reserved for the user program,
where the dynamic linker should not map anything. */
#define ELF_MACHINE_USER_ADDRESS_MASK 0xf0000000UL
@@ -328,9 +174,14 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
return value + reloc->r_addend;
}
+
+/* Names of the architecture-specific auditing callback functions. */
+#define ARCH_LA_PLTENTER ppc32_gnu_pltenter
+#define ARCH_LA_PLTEXIT ppc32_gnu_pltexit
+
#endif /* dl_machine_h */
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
/* Do the actual processing of a reloc, once its target address
has been determined. */
@@ -381,16 +232,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
value = map->l_addr;
else
{
-# if defined USE_TLS && !defined RTLD_BOOTSTRAP
sym_map = RESOLVE_MAP (&sym, version, r_type);
- value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
-# else
- value = RESOLVE (&sym, version, r_type);
-# ifndef RTLD_BOOTSTRAP
- if (sym != NULL)
-# endif
- value += sym->st_value;
-# endif
+ value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
}
value += reloc->r_addend;
#else
@@ -474,4 +317,4 @@ elf_machine_lazy_rel (struct link_map *map,
DT_RELA table. */
#define ELF_MACHINE_PLTREL_OVERLAP 1
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/powerpc/powerpc32/dl-trampoline.S b/sysdeps/powerpc/powerpc32/dl-trampoline.S
new file mode 100644
index 0000000000..ea5ce7b45a
--- /dev/null
+++ b/sysdeps/powerpc/powerpc32/dl-trampoline.S
@@ -0,0 +1,174 @@
+/* PLT trampolines. PPC32 version.
+ Copyright (C) 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+
+ .section ".text"
+ .align 2
+ .globl _dl_runtime_resolve
+ .type _dl_runtime_resolve,@function
+_dl_runtime_resolve:
+ # We need to save the registers used to pass parameters, and register 0,
+ # which is used by _mcount; the registers are saved in a stack frame.
+ stwu r1,-64(r1)
+ stw r0,12(r1)
+ stw r3,16(r1)
+ stw r4,20(r1)
+ # The code that calls this has put parameters for `fixup' in r12 and r11.
+ mr r3,r12
+ stw r5,24(r1)
+ mr r4,r11
+ stw r6,28(r1)
+ mflr r0
+ # We also need to save some of the condition register fields
+ stw r7,32(r1)
+ stw r0,48(r1)
+ stw r8,36(r1)
+ mfcr r0
+ stw r9,40(r1)
+ stw r10,44(r1)
+ stw r0,8(r1)
+ bl _dl_fixup@local
+ # 'fixup' returns the address we want to branch to.
+ mtctr r3
+ # Put the registers back...
+ lwz r0,48(r1)
+ lwz r10,44(r1)
+ lwz r9,40(r1)
+ mtlr r0
+ lwz r8,36(r1)
+ lwz r0,8(r1)
+ lwz r7,32(r1)
+ lwz r6,28(r1)
+ mtcrf 0xFF,r0
+ lwz r5,24(r1)
+ lwz r4,20(r1)
+ lwz r3,16(r1)
+ lwz r0,12(r1)
+ # ...unwind the stack frame, and jump to the PLT entry we updated.
+ addi r1,r1,64
+ bctr
+ .size _dl_runtime_resolve,.-_dl_runtime_resolve
+
+ .align 2
+ .globl _dl_prof_resolve
+ .type _dl_prof_resolve,@function
+_dl_prof_resolve:
+ # We need to save the registers used to pass parameters, and register 0,
+ # which is used by _mcount; the registers are saved in a stack frame.
+ stwu r1,-320(r1)
+ /* Stack layout:
+
+ +312 stackframe
+ +308 lr
+ +304 r1
+ +288 v12
+ +272 v11
+ +256 v10
+ +240 v9
+ +224 v8
+ +208 v7
+ +192 v6
+ +176 v5
+ +160 v4
+ +144 v3
+ +128 v2
+ +112 v1
+ +104 fp8
+ +96 fp7
+ +88 fp6
+ +80 fp5
+ +72 fp4
+ +64 fp3
+ +56 fp2
+ +48 fp1
+ +44 r10
+ +40 r9
+ +36 r8
+ +32 r7
+ +28 r6
+ +24 r5
+ +20 r4
+ +16 r3
+ +12 r0
+ +8 cr
+ r1 link
+ */
+ stw r0,12(r1)
+ stw r3,16(r1)
+ stw r4,20(r1)
+ # The code that calls this has put parameters for `fixup' in r12 and r11.
+ mr r3,r12
+ stw r5,24(r1)
+ mr r4,r11
+ stw r6,28(r1)
+ mflr r5
+ # We also need to save some of the condition register fields.
+ stw r7,32(r1)
+ stw r5,308(r1)
+ stw r8,36(r1)
+ mfcr r0
+ stw r9,40(r1)
+ stw r10,44(r1)
+ stw r0,8(r1)
+ # Save the floating point registers
+ stfd fp1,48(r1)
+ stfd fp2,56(r1)
+ stfd fp3,64(r1)
+ stfd fp4,72(r1)
+ stfd fp5,80(r1)
+ stfd fp6,88(r1)
+ stfd fp7,96(r1)
+ stfd fp8,104(r1)
+ # XXX TODO: store vmx registers
+ # Load the extra parameters.
+ addi r6,r1,16
+ addi r7,r1,312
+ li r0,-1
+ stw r0,0(r7)
+ bl _dl_profile_fixup@local
+ # 'fixup' returns the address we want to branch to.
+ mtctr r3
+ # Put the registers back...
+ lwz r0,308(r1)
+ lwz r10,44(r1)
+ lwz r9,40(r1)
+ mtlr r0
+ lwz r8,36(r1)
+ lwz r0,8(r1)
+ lwz r7,32(r1)
+ lwz r6,28(r1)
+ mtcrf 0xFF,r0
+ lwz r5,24(r1)
+ lwz r4,20(r1)
+ lwz r3,16(r1)
+ lwz r0,12(r1)
+ # Load the floating point registers.
+ lfd fp1,48(r1)
+ lfd fp2,56(r1)
+ lfd fp3,64(r1)
+ lfd fp4,72(r1)
+ lfd fp5,80(r1)
+ lfd fp6,88(r1)
+ lfd fp7,96(r1)
+ lfd fp8,104(r1)
+ # ...unwind the stack frame, and jump to the PLT entry we updated.
+ addi r1,r1,320
+ bctr
+ .size _dl_prof_resolve,.-_dl_prof_resolve
diff --git a/sysdeps/powerpc/powerpc64/bits/link.h b/sysdeps/powerpc/powerpc64/bits/link.h
new file mode 100644
index 0000000000..863336241a
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/bits/link.h
@@ -0,0 +1,109 @@
+/* Copyright (C) 2004, 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+#if __ELF_NATIVE_CLASS == 32
+
+/* Registers for entry into PLT on PPC32. */
+typedef struct La_ppc32_regs
+{
+ uint32_t lr_reg[8];
+ double lr_fp[8];
+ uint32_t lr_vreg[12][4];
+ uint32_t lr_r1;
+ uint32_t lr_lr;
+} La_ppc32_regs;
+
+/* Return values for calls from PLT on PPC32. */
+typedef struct La_ppc32_retval
+{
+ uint32_t lrv_r3;
+ uint32_t lrv_r4;
+ double lrv_fp[8];
+ uint32_t lrv_v2[4];
+} La_ppc32_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_ppc32_gnu_pltenter (Elf32_Sym *__sym,
+ unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ La_ppc32_regs *__regs,
+ unsigned int *__flags,
+ const char *__symname,
+ long int *__framesizep);
+extern unsigned int la_ppc32_gnu_pltexit (Elf32_Sym *__sym,
+ unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ const La_ppc32_regs *__inregs,
+ La_ppc32_retval *__outregs,
+ const char *symname);
+
+__END_DECLS
+
+#else
+
+/* Registers for entry into PLT on PPC64. */
+typedef struct La_ppc64_regs
+{
+ uint64_t lr_reg[8];
+ double lr_fp[13];
+ uint64_t __padding;
+ uint32_t lr_vreg[12][4];
+ uint64_t lr_r1;
+ uint64_t lr_lr;
+} La_ppc64_regs;
+
+/* Return values for calls from PLT on PPC64. */
+typedef struct La_ppc64_retval
+{
+ uint64_t lrv_r3;
+ uint64_t lrv_r4;
+ double lrv_fp[8];
+ uint32_t lrv_v2[4];
+} La_ppc64_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf64_Addr la_ppc64_gnu_pltenter (Elf64_Sym *__sym,
+ unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ La_ppc64_regs *__regs,
+ unsigned int *__flags,
+ const char *__symname,
+ long int *__framesizep);
+extern unsigned int la_ppc64_gnu_pltexit (Elf64_Sym *__sym,
+ unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ const La_ppc64_regs *__inregs,
+ La_ppc64_retval *__outregs,
+ const char *symname);
+
+__END_DECLS
+
+#endif
diff --git a/sysdeps/powerpc/powerpc64/dl-lookupcfg.h b/sysdeps/powerpc/powerpc64/dl-lookupcfg.h
index e502941015..e69de29bb2 100644
--- a/sysdeps/powerpc/powerpc64/dl-lookupcfg.h
+++ b/sysdeps/powerpc/powerpc64/dl-lookupcfg.h
@@ -1,22 +0,0 @@
-/* Configuration of lookup functions. PowerPC64 version.
- Copyright (C) 2002 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
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-/* Return the symbol map from the symbol lookup function. */
-
-#define DL_LOOKUP_RETURNS_MAP 1
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index 3fcf77df71..5ddc22e3c9 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -1,6 +1,6 @@
/* Machine-dependent ELF dynamic relocation inline functions.
PowerPC64 version.
- Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -107,92 +107,6 @@ elf_machine_dynamic (void)
/* The PLT uses Elf64_Rela relocs. */
#define elf_machine_relplt elf_machine_rela
-/* This code gets called via a .glink stub which loads PLT0. It is
- used in dl-runtime.c to call the `fixup' function and then redirect
- to the address `fixup' returns.
-
- Enter with r0 = plt reloc index,
- r2 = ld.so tocbase,
- r11 = ld.so link map. */
-
-#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name) \
- asm (".section \".text\"\n" \
-" .align 2\n" \
-" .type " BODY_PREFIX #tramp_name ",@function\n" \
-" .section \".opd\",\"aw\"\n" \
-" .align 3\n" \
-" .globl " #tramp_name "\n" \
-" " ENTRY_2(tramp_name) "\n" \
-#tramp_name ":\n" \
-" " OPD_ENT(tramp_name) "\n" \
-" .previous\n" \
-BODY_PREFIX #tramp_name ":\n" \
-/* We need to save the registers used to pass parameters, ie. r3 thru \
- r10; the registers are saved in a stack frame. */ \
-" stdu 1,-128(1)\n" \
-" std 3,48(1)\n" \
-" mr 3,11\n" \
-" std 4,56(1)\n" \
-" sldi 4,0,1\n" \
-" std 5,64(1)\n" \
-" add 4,4,0\n" \
-" std 6,72(1)\n" \
-" sldi 4,4,3\n" \
-" std 7,80(1)\n" \
-" mflr 0\n" \
-" std 8,88(1)\n" \
-/* Store the LR in the LR Save area of the previous frame. */ \
-" std 0,128+16(1)\n" \
-" mfcr 0\n" \
-" std 9,96(1)\n" \
-" std 10,104(1)\n" \
-/* I'm almost certain we don't have to save cr... be safe. */ \
-" std 0,8(1)\n" \
-" bl " DOT_PREFIX #fixup_name "\n" \
-/* Put the registers back. */ \
-" ld 0,128+16(1)\n" \
-" ld 10,104(1)\n" \
-" ld 9,96(1)\n" \
-" ld 8,88(1)\n" \
-" ld 7,80(1)\n" \
-" mtlr 0\n" \
-" ld 0,8(1)\n" \
-" ld 6,72(1)\n" \
-" ld 5,64(1)\n" \
-" ld 4,56(1)\n" \
-" mtcrf 0xFF,0\n" \
-/* Load the target address, toc and static chain reg from the function \
- descriptor returned by fixup. */ \
-" ld 0,0(3)\n" \
-" ld 2,8(3)\n" \
-" mtctr 0\n" \
-" ld 11,16(3)\n" \
-" ld 3,48(1)\n" \
-/* Unwind the stack frame, and jump. */ \
-" addi 1,1,128\n" \
-" bctr\n" \
-".LT_" #tramp_name ":\n" \
-" .long 0\n" \
-" .byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\n" \
-" .long .LT_" #tramp_name "-" BODY_PREFIX #tramp_name "\n" \
-" .short .LT_" #tramp_name "_name_end-.LT_" #tramp_name "_name_start\n" \
-".LT_" #tramp_name "_name_start:\n" \
-" .ascii \"" #tramp_name "\"\n" \
-".LT_" #tramp_name "_name_end:\n" \
-" .align 2\n" \
-" " END_2(tramp_name) "\n" \
-" .previous");
-
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
- TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup); \
- TRAMPOLINE_TEMPLATE (_dl_profile_resolve, profile_fixup);
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
- TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup); \
- void _dl_runtime_resolve (void); \
- strong_alias (_dl_runtime_resolve, _dl_profile_resolve);
-#endif
#ifdef HAVE_INLINED_SYSCALLS
/* We do not need _dl_starting_up. */
@@ -420,7 +334,8 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
resolve_fd = (Elf64_FuncDesc *) (profile ? _dl_profile_resolve
: _dl_runtime_resolve);
- if (profile && _dl_name_match_p (GLRO(dl_profile), map))
+ if (profile && GLRO(dl_profile) != NULL
+ && _dl_name_match_p (GLRO(dl_profile), map))
/* This is the object we are looking for. Say that we really
want profiling and the timers are started. */
GL(dl_profile_map) = map;
@@ -545,6 +460,11 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
return value + reloc->r_addend;
}
+
+/* Names of the architecture-specific auditing callback functions. */
+#define ARCH_LA_PLTENTER ppc64_gnu_pltenter
+#define ARCH_LA_PLTEXIT ppc64_gnu_pltexit
+
#endif /* dl_machine_h */
#ifdef RESOLVE_MAP
diff --git a/sysdeps/powerpc/powerpc64/dl-trampoline.S b/sysdeps/powerpc/powerpc64/dl-trampoline.S
new file mode 100644
index 0000000000..316f17a405
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/dl-trampoline.S
@@ -0,0 +1,196 @@
+/* PLT trampolines. PPC64 version.
+ Copyright (C) 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+
+ .section ".text"
+
+EALIGN(_dl_runtime_resolve, 4, 0)
+/* We need to save the registers used to pass parameters, ie. r3 thru
+ r10; the registers are saved in a stack frame. */
+ stdu r1,-128(r1)
+ std r3,48(r1)
+ mr r3,r11
+ std r4,56(r1)
+ sldi r4,r0,1
+ std r5,64(r1)
+ add r4,r4,r0
+ std r6,72(r1)
+ sldi r4,r4,3
+ std r7,80(r1)
+ mflr r0
+ std r8,88(r1)
+/* Store the LR in the LR Save area of the previous frame. */
+ std r0,128+16(r1)
+ mfcr r0
+ std r9,96(r1)
+ std r10,104(r1)
+/* I'm almost certain we don't have to save cr... be safe. */
+ std r0,8(r1)
+ bl JUMPTARGET(_dl_fixup)
+/* Put the registers back. */
+ ld r0,128+16(r1)
+ ld r10,104(r1)
+ ld r9,96(r1)
+ ld r8,88(r1)
+ ld r7,80(r1)
+ mtlr r0
+ ld r0,8(r1)
+ ld r6,72(r1)
+ ld r5,64(r1)
+ ld r4,56(r1)
+ mtcrf 0xFF,r0
+/* Load the target address, toc and static chain reg from the function
+ descriptor returned by fixup. */
+ ld r0,0(r3)
+ ld r2,8(r3)
+ mtctr r0
+ ld r11,16(r3)
+ ld r3,48(r1)
+/* Unwind the stack frame, and jump. */
+ addi r1,r1,128
+ bctr
+END(_dl_runtime_resolve)
+
+
+
+EALIGN(_dl_profile_resolve, 4, 0)
+/* We need to save the registers used to pass parameters, ie. r3 thru
+ r10; the registers are saved in a stack frame. */
+ stdu r1,-448(r1)
+ /* Stack layout:
+
+ +432 stackframe
+ +424 lr
+ +416 r1
+ +400 v12
+ +384 v11
+ +368 v10
+ +362 v9
+ +336 v8
+ +320 v7
+ +304 v6
+ +288 v5
+ +272 v4
+ +256 v3
+ +240 v2
+ +224 v1
+ +216 free
+ +208 fp13
+ +200 fp12
+ +192 fp11
+ +184 fp10
+ +176 fp9
+ +168 fp8
+ +160 fp7
+ +152 fp6
+ +144 fp5
+ +136 fp4
+ +128 fp3
+ +120 fp2
+ +112 fp1
+ +104 r10
+ +96 r9
+ +88 r8
+ +80 r7
+ +72 r6
+ +64 r5
+ +56 r4
+ +48 r3
+ +8 cr
+ r1 link
+ */
+ std r3,48(r1)
+ mr r3,r11
+ std r4,56(r1)
+ sldi r4,r0,1
+ std r5,64(r1)
+ add r4,r4,0
+ std r6,72(r1)
+ sldi r4,r4,3
+ std r7,80(r1)
+ mflr r5
+ std r8,88(r1)
+/* Store the LR in the LR Save area of the previous frame. */
+/* XXX Do we have to do this? */
+ std r5,448+16(r1)
+ std r5,424(r1)
+ mfcr r0
+ std r9,96(r1)
+ std r10,104(r1)
+/* I'm almost certain we don't have to save cr... be safe. */
+ std r0,8(r1)
+/* Save floating registers. */
+ stfd fp1,112(r1)
+ stfd fp2,120(r1)
+ stfd fp3,128(r1)
+ stfd fp4,136(r1)
+ stfd fp5,144(r1)
+ stfd fp6,152(r1)
+ stfd fp7,160(r1)
+ stfd fp8,168(r1)
+ stfd fp9,176(r1)
+ stfd fp10,184(r1)
+ stfd fp11,192(r1)
+ stfd fp12,200(r1)
+ stfd fp13,208(r1)
+/* XXX TODO: store vmx registers. */
+/* Load the extra parameters. */
+ addi r6,r1,48
+ addi r7,r1,432
+ li r0,-1
+ stdu r0,0(r7)
+ bl JUMPTARGET(_dl_profile_fixup)
+/* Put the registers back. */
+ ld r0,448+16(r1)
+ ld r10,104(r1)
+ ld r9,96(r1)
+ ld r8,88(r1)
+ ld r7,80(r1)
+ mtlr r0
+ ld r0,8(r1)
+ ld r6,72(r1)
+ ld r5,64(r1)
+ ld r4,56(r1)
+ mtcrf 0xFF,r0
+/* Load the target address, toc and static chain reg from the function
+ descriptor returned by fixup. */
+ ld r0,0(r3)
+ ld r2,8(r3)
+ mtctr r0
+ ld r11,16(r3)
+ ld r3,48(r1)
+/* Load the floating point registers. */
+ lfd fp1,112(r1)
+ lfd fp2,120(r1)
+ lfd fp3,128(r1)
+ lfd fp4,136(r1)
+ lfd fp5,144(r1)
+ lfd fp6,152(r1)
+ lfd fp7,160(r1)
+ lfd fp8,168(r1)
+ lfd fp9,176(r1)
+ lfd fp10,184(r1)
+ lfd fp11,192(r1)
+ lfd fp12,200(r1)
+ lfd fp13,208(r1)
+/* Unwind the stack frame, and jump. */
+ addi r1,r1,448
+ bctr
+END(_dl_profile_resolve)
diff --git a/sysdeps/powerpc/tst-stack-align.h b/sysdeps/powerpc/tst-stack-align.h
new file mode 100644
index 0000000000..99a0ffcef7
--- /dev/null
+++ b/sysdeps/powerpc/tst-stack-align.h
@@ -0,0 +1,47 @@
+/* Copyright (C) 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdio.h>
+#include <stdint.h>
+
+#define TEST_STACK_ALIGN() \
+ ({ \
+ /* Altivec __vector int etc. needs 16byte aligned stack. \
+ Instead of using altivec.h here, use aligned attribute instead. */ \
+ struct _S \
+ { \
+ int _i __attribute__((aligned (16))); \
+ int _j[3]; \
+ } _s = { ._i = 18, ._j[0] = 19, ._j[1] = 20, ._j[2] = 21 }; \
+ double _d = 12.0; \
+ long double _ld = 15.0; \
+ int _ret = 0; \
+ printf ("__vector int: { %d, %d, %d, %d } %p %zu\n", _s._i, _s._j[0], \
+ _s._j[1], _s._j[2], &_s, __alignof (_s)); \
+ if ((((uintptr_t) &_s) & (__alignof (_s) - 1)) != 0) \
+ _ret = 1; \
+ \
+ printf ("double: %g %p %zu\n", _d, &_d, __alignof (double)); \
+ if ((((uintptr_t) &_d) & (__alignof (double) - 1)) != 0) \
+ _ret = 1; \
+ \
+ printf ("ldouble: %Lg %p %zu\n", _ld, &_ld, __alignof (long double)); \
+ if ((((uintptr_t) &_ld) & (__alignof (long double) - 1)) != 0) \
+ _ret = 1; \
+ _ret; \
+ })
diff --git a/sysdeps/s390/bits/link.h b/sysdeps/s390/bits/link.h
index fc1fba363a..70f0043820 100644
--- a/sysdeps/s390/bits/link.h
+++ b/sysdeps/s390/bits/link.h
@@ -1,13 +1,111 @@
-#if __WORDSIZE == 64
-struct link_map_machine
- {
- Elf64_Addr plt; /* Address of .plt + 0x2e */
- Elf64_Addr gotplt; /* Address of .got + 0x18 */
- };
+/* Copyright (C) 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+#if __ELF_NATIVE_CLASS == 32
+
+/* Registers for entry into PLT on s390-32. */
+typedef struct La_s390_32_regs
+{
+ uint32_t lr_r2;
+ uint32_t lr_r3;
+ uint32_t lr_r4;
+ uint32_t lr_r5;
+ uint32_t lr_r6;
+ double lr_fp0;
+ double lr_fp2;
+} La_s390_32_regs;
+
+/* Return values for calls from PLT on s390-32. */
+typedef struct La_s390_32_retval
+{
+ uint32_t lrv_r2;
+ uint32_t lrv_r3;
+ double lrv_fp0;
+} La_s390_32_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_s390_32_gnu_pltenter (Elf32_Sym *__sym,
+ unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ La_s390_32_regs *__regs,
+ unsigned int *__flags,
+ const char *__symname,
+ long int *__framesizep);
+extern unsigned int la_s390_32_gnu_pltexit (Elf32_Sym *__sym,
+ unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ const La_s390_32_regs *__inregs,
+ La_s390_32_retval *__outregs,
+ const char *symname);
+
+__END_DECLS
+
#else
-struct link_map_machine
- {
- Elf32_Addr plt; /* Address of .plt + 0x2c */
- Elf32_Addr gotplt; /* Address of .got + 0x0c */
- };
+
+/* Registers for entry into PLT on s390-64. */
+typedef struct La_s390_64_regs
+{
+ uint64_t lr_r2;
+ uint64_t lr_r3;
+ uint64_t lr_r4;
+ uint64_t lr_r5;
+ uint64_t lr_r6;
+ double lr_fp0;
+ double lr_fp2;
+ double lr_fp4;
+ double lr_fp6;
+} La_s390_64_regs;
+
+/* Return values for calls from PLT on s390-64. */
+typedef struct La_s390_64_retval
+{
+ uint64_t lrv_r2;
+ double lrv_fp0;
+} La_s390_64_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf64_Addr la_s390_64_gnu_pltenter (Elf64_Sym *__sym,
+ unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ La_s390_64_regs *__regs,
+ unsigned int *__flags,
+ const char *__symname,
+ long int *__framesizep);
+extern unsigned int la_s390_64_gnu_pltexit (Elf64_Sym *__sym,
+ unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ const La_s390_64_regs *__inregs,
+ La_s390_64_retval *__outregs,
+ const char *symname);
+
+__END_DECLS
+
#endif
diff --git a/sysdeps/s390/bits/linkmap.h b/sysdeps/s390/bits/linkmap.h
new file mode 100644
index 0000000000..fc1fba363a
--- /dev/null
+++ b/sysdeps/s390/bits/linkmap.h
@@ -0,0 +1,13 @@
+#if __WORDSIZE == 64
+struct link_map_machine
+ {
+ Elf64_Addr plt; /* Address of .plt + 0x2e */
+ Elf64_Addr gotplt; /* Address of .got + 0x18 */
+ };
+#else
+struct link_map_machine
+ {
+ Elf32_Addr plt; /* Address of .plt + 0x2c */
+ Elf32_Addr gotplt; /* Address of .got + 0x0c */
+ };
+#endif
diff --git a/sysdeps/s390/bits/string.h b/sysdeps/s390/bits/string.h
index 7134827eb0..d83df39bb2 100644
--- a/sysdeps/s390/bits/string.h
+++ b/sysdeps/s390/bits/string.h
@@ -51,7 +51,7 @@ strlen (__const char *__str)
"0: srst %0,%1\n"
" jo 0b\n"
: "+&a" (__ptr), "+&a" (__tmp) :
- : "cc", "0" );
+ : "cc", "memory", "0" );
return (size_t) (__ptr - __str);
}
#endif
@@ -105,7 +105,7 @@ strncpy (char *__dest, __const char *__src, size_t __n)
#endif
"4:"
: "+&a" (__ptr), "+&a" (__n) : "a" (__diff)
- : "cc", "0" );
+ : "cc", "memory", "0" );
}
return __ret;
}
@@ -134,7 +134,7 @@ strcat(char *__dest, const char *__src)
"0: mvst %0,%1\n"
" jo 0b"
: "+&a" (__ptr), "+&a" (__src) :
- : "cc", "0" );
+ : "cc", "memory", "0" );
return __ret;
}
#endif
@@ -157,7 +157,7 @@ strncat (char *__dest, __const char *__src, size_t __n)
"0: srst %0,%1\n"
" jo 0b\n"
: "+&a" (__ptr), "+&a" (__tmp) :
- : "cc", "0" );
+ : "cc", "memory", "0" );
__diff = (size_t) (__ptr - __src);
__tmp = (char *) __src;
@@ -175,7 +175,7 @@ strncat (char *__dest, __const char *__src, size_t __n)
" stc 0,1(%2,%0)\n"
"2:"
: "+&a" (__tmp), "+&a" (__n) : "a" (__diff)
- : "cc", "0" );
+ : "cc", "memory", "0" );
}
return __ret;
@@ -200,7 +200,7 @@ memchr (__const void *__str, int __c, size_t __n)
" la %0,0\n"
"1:"
: "+&a" (__ptr), "+&a" (__tmp) : "d" (__c)
- : "cc", "0" );
+ : "cc", "memory", "0" );
return __ptr;
}
#endif
@@ -222,7 +222,7 @@ strcmp (__const char *__s1, __const char *__s2)
" ipm %0\n"
" srl %0,28"
: "=d" (__ret), "+&a" (__p1), "+&a" (__p2) :
- : "cc", "0" );
+ : "cc", "memory", "0" );
__ret = (__ret == 0) ? 0 : (__ret == 1) ? -1 : 1;
return __ret;
}
diff --git a/sysdeps/s390/s390-32/dl-machine.h b/sysdeps/s390/s390-32/dl-machine.h
index 52922a813b..8bbf858fbf 100644
--- a/sysdeps/s390/s390-32/dl-machine.h
+++ b/sysdeps/s390/s390-32/dl-machine.h
@@ -1,5 +1,6 @@
/* Machine-dependent ELF dynamic relocation inline functions. S390 Version.
- Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
Contributed by Carl Pederson & Martin Schwidefsky.
This file is part of the GNU C Library.
@@ -21,7 +22,6 @@
#ifndef dl_machine_h
#define dl_machine_h
-
#define ELF_MACHINE_NAME "s390"
#include <sys/param.h>
@@ -112,7 +112,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
got[2] = (Elf32_Addr) &_dl_runtime_profile;
- if (_dl_name_match_p (GLRO(dl_profile), l))
+ if (GLRO(dl_profile) != NULL
+ && _dl_name_match_p (GLRO(dl_profile), l))
/* This is the object we are looking for. Say that we really
want profiling and the timers are started. */
GL(dl_profile_map) = l;
@@ -126,124 +127,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
return lazy;
}
-/* This code is used in dl-runtime.c to call the `fixup' function
- and then redirect to the address it returns. */
-
-/* s390:
- Arguments are in register.
- r2 - r7 holds the original parameters for the function call, fixup
- and trampoline code use r0-r5 and r14-15. For the correct function
- call r2-r5 and r14-15 must be restored.
- Arguments from the PLT are stored at 24(r15) and 28(r15)
- and must be moved to r2 and r3 for the fixup call (see elf32-s390.c
- in the binutils for the PLT code).
- Fixup function address in r2.
-*/
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
- asm ( "\
- .text\n\
- .globl _dl_runtime_resolve\n\
- .type _dl_runtime_resolve, @function\n\
- .align 16\n\
- " CFI_STARTPROC "\n\
-_dl_runtime_resolve:\n\
- # save registers\n\
- stm 2,5,32(15)\n\
- st 14,48(15)\n\
- lr 0,15\n\
- ahi 15,-96\n\
- " CFI_ADJUST_CFA_OFFSET(96)"\n\
- st 0,0(15)\n\
- # load args saved by PLT\n\
- lm 2,3,120(15)\n\
- basr 1,0\n\
-0: ahi 1,1f-0b\n\
- l 14,0(1)\n\
- bas 14,0(14,1) # call fixup\n\
- lr 1,2 # function addr returned in r2\n\
- # restore registers\n\
- ahi 15,96\n\
- " CFI_ADJUST_CFA_OFFSET(-96)" \n\
- l 14,48(15)\n\
- lm 2,5,32(15)\n\
- br 1\n\
-1: .long fixup-1b\n\
- " CFI_ENDPROC "\n\
- .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-\n\
- .globl _dl_runtime_profile\n\
- .type _dl_runtime_profile, @function\n\
- .align 16\n\
- " CFI_STARTPROC "\n\
-_dl_runtime_profile:\n\
- # save registers\n\
- stm 2,5,32(15)\n\
- st 14,48(15)\n\
- lr 0,15\n\
- ahi 15,-96\n\
- " CFI_ADJUST_CFA_OFFSET(96)"\n\
- st 0,0(15)\n\
- # load args saved by PLT\n\
- lm 2,3,120(15)\n\
- # load return address as third parameter\n\
- lr 4,14\n\
- basr 1,0\n\
-0: ahi 1,1f-0b\n\
- l 14,0(1)\n\
- bas 14,0(14,1) # call fixup\n\
- lr 1,2 # function addr returned in r2\n\
- # restore registers\n\
- ahi 15,96\n\
- " CFI_ADJUST_CFA_OFFSET(-96)" \n\
- l 14,48(15)\n\
- lm 2,5,32(15)\n\
- br 1\n\
-1: .long profile_fixup-1b\n\
- " CFI_ENDPROC "\n\
- .size _dl_runtime_profile, .-_dl_runtime_profile\n\
-");
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
- asm ( "\
- .text\n\
- .globl _dl_runtime_resolve\n\
- .globl _dl_runtime_profile\n\
- .type _dl_runtime_resolve, @function\n\
- .type _dl_runtime_profile, @function\n\
- .align 16\n\
- " CFI_STARTPROC "\n\
-_dl_runtime_resolve:\n\
-_dl_runtime_profile:\n\
- # save registers\n\
- stm 2,5,32(15)\n\
- st 14,48(15)\n\
- lr 0,15\n\
- ahi 15,-96\n\
- " CFI_ADJUST_CFA_OFFSET(96)"\n\
- st 0,0(15)\n\
- # load args saved by PLT\n\
- lm 2,3,120(15)\n\
- # load return address as third parameter\n\
- lr 4,14\n\
- basr 1,0\n\
-0: ahi 1,1f-0b\n\
- l 14,0(1)\n\
- bas 14,0(14,1) # call fixup\n\
- lr 1,2 # function addr returned in r2\n\
- # restore registers\n\
- ahi 15,96\n\
- " CFI_ADJUST_CFA_OFFSET(-96)" \n\
- l 14,48(15)\n\
- lm 2,5,32(15)\n\
- br 1\n\
-1: .long fixup-1b\n\
- " CFI_ENDPROC "\n\
- .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
- .size _dl_runtime_profile, .-_dl_runtime_profile\n\
-");
-#endif
-
/* Mask identifying addresses reserved for the user program,
where the dynamic linker should not map anything. */
#define ELF_MACHINE_USER_ADDRESS_MASK 0xf8000000UL
@@ -375,15 +258,20 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
return value;
}
+/* Names of the architecture-specific auditing callback functions. */
+#define ARCH_LA_PLTENTER s390_32_gnu_pltenter
+#define ARCH_LA_PLTEXIT s390_32_gnu_pltexit
+
#endif /* !dl_machine_h */
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
MAP is the object containing the reloc. */
-static inline void
+auto inline void
+__attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version,
void *const reloc_addr_arg)
@@ -417,17 +305,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
#ifndef RESOLVE_CONFLICT_FIND_MAP
const Elf32_Sym *const refsym = sym;
#endif
-#if defined USE_TLS && !defined RTLD_BOOTSTRAP
struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
-#else
- Elf32_Addr value = RESOLVE (&sym, version, r_type);
-
-# ifndef RTLD_BOOTSTRAP
- if (sym)
-# endif
- value += sym->st_value;
-#endif /* use TLS and !RTLD_BOOTSTRAP */
switch (r_type)
{
@@ -539,7 +418,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
}
}
-static inline void
+auto inline void
+__attribute__ ((always_inline))
elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
void *const reloc_addr_arg)
{
@@ -547,7 +427,8 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
*reloc_addr = l_addr + reloc->r_addend;
}
-static inline void
+auto inline void
+__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
Elf32_Addr l_addr, const Elf32_Rela *reloc)
{
@@ -567,4 +448,4 @@ elf_machine_lazy_rel (struct link_map *map,
_dl_reloc_bad_type (map, r_type, 1);
}
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/s390/s390-32/dl-trampoline.S b/sysdeps/s390/s390-32/dl-trampoline.S
new file mode 100644
index 0000000000..4ee2295b89
--- /dev/null
+++ b/sysdeps/s390/s390-32/dl-trampoline.S
@@ -0,0 +1,133 @@
+/* PLT trampolines. s390 version.
+ Copyright (C) 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* This code is used in dl-runtime.c to call the `fixup' function
+ and then redirect to the address it returns. */
+
+/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
+ * with the following linkage:
+ * r2 - r6 : parameter registers
+ * f0, f2 : floating point parameter registers
+ * 24(r15), 28(r15) : PLT arguments PLT1, PLT2
+ * 96(r15) : additional stack parameters
+ * The normal clobber rules for function calls apply:
+ * r0 - r5 : call clobbered
+ * r6 - r13 : call saved
+ * r14 : return address (call clobbered)
+ * r15 : stack pointer (call saved)
+ * f4, f6 : call saved
+ * f0 - f3, f5, f7 - f15 : call clobbered
+ */
+
+#include <sysdep.h>
+
+ .text
+ .globl _dl_runtime_resolve
+ .type _dl_runtime_resolve, @function
+ cfi_startproc
+ .align 16
+_dl_runtime_resolve:
+ stm %r2,%r5,32(%r15) # save registers
+ st %r14,8(%r15)
+ lr %r0,%r15 # create stack frame
+ ahi %r15,-96
+ cfi_adjust_cfa_offset (96)
+ st 0,0(%r15)
+ lm %r2,%r3,120(%r15) # load args saved by PLT
+ basr %r1,0
+0: l %r14,1f-0b(%r1)
+ bas %r14,0(%r14,%r1) # call resolver
+ lr %r1,%r2 # function addr returned in r2
+ ahi %r15,96 # remove stack frame
+ cfi_adjust_cfa_offset (-96)
+ l %r14,8(15) # restore registers
+ lm %r2,%r5,32(%r15)
+ br %r1
+1: .long _dl_fixup - 0b
+ cfi_endproc
+ .size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+
+ .globl _dl_runtime_profile
+ .type _dl_runtime_profile, @function
+ cfi_startproc
+ .align 16
+_dl_runtime_profile:
+ stm %r2,%r6,32(%r15) # save registers
+ std %f0,56(%r15)
+ std %f2,64(%r15)
+ st %r6,8(%r15)
+ st %r12,12(%r15)
+ st %r14,16(%r15)
+ lr %r12,%r15 # create stack frame
+ cfi_def_cfa_register (12)
+ ahi %r15,-96
+ st %r12,0(%r15)
+ lm %r2,%r3,24(%r12) # load arguments saved by PLT
+ lr %r4,%r14 # return address as third parameter
+ basr %r1,0
+0: l %r14,6f-0b(%r1)
+ la %r5,32(%r12) # pointer to struct La_s390_32_regs
+ la %r6,20(%r12) # long int * framesize
+ bas %r14,0(%r14,%r1) # call resolver
+ lr %r1,%r2 # function addr returned in r2
+ icm %r0,15,20(%r12) # load & test framesize
+ jnm 2f
+ lm %r2,%r6,32(%r12)
+ ld %f0,56(%r12)
+ ld %f2,64(%r12)
+ basr %r14,%r1 # call resolved function
+1: lr %r15,%r12 # remove stack frame
+ cfi_def_cfa_register (15)
+ l %r14,16(%r15) # restore registers
+ l %r12,12(%r15)
+ l %r6,8(%r15)
+ br %r14
+ cfi_def_cfa_register (12)
+2: jz 4f # framesize == 0 ?
+ ahi %r0,7 # align framesize to 8
+ lhi %r2,-8
+ nr %r0,%r2
+ slr %r15,%r0 # make room for framesize bytes
+ st %r12,0(%r15)
+ la %r2,96(%r15)
+ la %r3,96(%r12)
+ srl %r0,3
+3: mvc 0(8,%r2),0(%r3) # copy additional parameters
+ la %r2,8(%r2)
+ la %r3,8(%r3)
+ brct %r0,3b
+4: lm %r2,%r6,32(%r12) # load register parameters
+ ld %f0,56(%r12)
+ ld %f2,64(%r12)
+ basr %r14,%r1 # call resolved function
+ stm %r2,%r3,72(%r12)
+ std %f0,80(%r12)
+ lm %r2,%r3,24(%r12) # load arguments saved by PLT
+ basr %r1,0
+5: l %r14,7f-5b(%r1)
+ la %r4,32(%r12) # pointer to struct La_s390_32_regs
+ la %r5,72(%r12) # pointer to struct La_s390_32_retval
+ basr %r14,%r1 # call _dl_call_pltexit
+ j 1b
+6: .long _dl_profile_fixup - 0b
+7: .long _dl_call_pltexit - 5b
+ cfi_endproc
+ .size _dl_runtime_profile, .-_dl_runtime_profile
+
diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h
index 82ece0be0f..5026a2edad 100644
--- a/sysdeps/s390/s390-64/dl-machine.h
+++ b/sysdeps/s390/s390-64/dl-machine.h
@@ -1,6 +1,6 @@
/* Machine-dependent ELF dynamic relocation inline functions.
64 bit S/390 Version.
- Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
This file is part of the GNU C Library.
@@ -105,7 +105,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
got[2] = (Elf64_Addr) &_dl_runtime_profile;
- if (_dl_name_match_p (GLRO(dl_profile), l))
+ if (GLRO(dl_profile) != NULL
+ && _dl_name_match_p (GLRO(dl_profile), l))
/* This is the object we are looking for. Say that we really
want profiling and the timers are started. */
GL(dl_profile_map) = l;
@@ -119,112 +120,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
return lazy;
}
-/* This code is used in dl-runtime.c to call the `fixup' function
- and then redirect to the address it returns. */
-
-/* s390:
- Arguments are in register.
- r2 - r7 holds the original parameters for the function call, fixup
- and trampoline code use r0-r5 and r14-15. For the correct function
- call r2-r5 and r14-15 must be restored.
- Arguments from the PLT are stored at 48(r15) and 56(r15)
- and must be moved to r2 and r3 for the fixup call (see elf32-s390.c
- in the binutils for the PLT code).
- Fixup function address in r2.
-*/
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
- asm ( "\
- .text\n\
- .globl _dl_runtime_resolve\n\
- .type _dl_runtime_resolve, @function\n\
- .align 16\n\
- " CFI_STARTPROC "\n\
-_dl_runtime_resolve:\n\
- # save registers\n\
- stmg 2,5,64(15)\n\
- stg 14,96(15)\n\
- lgr 0,15\n\
- aghi 15,-160\n\
- " CFI_ADJUST_CFA_OFFSET(160)"\n\
- stg 0,0(15)\n\
- # load args saved by PLT\n\
- lmg 2,3,208(15)\n\
- brasl 14,fixup # call fixup\n\
- lgr 1,2 # function addr returned in r2\n\
- # restore registers\n\
- aghi 15,160\n\
- " CFI_ADJUST_CFA_OFFSET(-160)" \n\
- lg 14,96(15)\n\
- lmg 2,5,64(15)\n\
- br 1\n\
- " CFI_ENDPROC "\n\
- .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-\n\
- .globl _dl_runtime_profile\n\
- .type _dl_runtime_profile, @function\n\
- .align 16\n\
- " CFI_STARTPROC "\n\
-_dl_runtime_profile:\n\
- # save registers\n\
- stmg 2,5,64(15)\n\
- stg 14,96(15)\n\
- lgr 0,15\n\
- aghi 15,-160\n\
- " CFI_ADJUST_CFA_OFFSET(160)"\n\
- stg 0,0(15)\n\
- # load args saved by PLT\n\
- lmg 2,3,208(15)\n\
- # load return address as third parameter\n\
- lgr 4,14\n\
- brasl 14,profile_fixup # call fixup\n\
- lgr 1,2 # function addr returned in r2\n\
- # restore registers\n\
- aghi 15,160\n\
- " CFI_ADJUST_CFA_OFFSET(-160)" \n\
- lg 14,96(15)\n\
- lmg 2,5,64(15)\n\
- br 1\n\
- " CFI_ENDPROC "\n\
- .size _dl_runtime_profile, .-_dl_runtime_profile\n\
-");
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
- asm ( "\
- .text\n\
- .globl _dl_runtime_resolve\n\
- .globl _dl_runtime_profile\n\
- .type _dl_runtime_resolve, @function\n\
- .type _dl_runtime_profile, @function\n\
- .align 16\n\
- " CFI_STARTPROC "\n\
-_dl_runtime_resolve:\n\
-_dl_runtime_profile:\n\
- # save registers\n\
- stmg 2,5,64(15)\n\
- stg 14,96(15)\n\
- lgr 0,15\n\
- aghi 15,-160\n\
- " CFI_ADJUST_CFA_OFFSET(160)"\n\
- stg 0,0(15)\n\
- # load args saved by PLT\n\
- lmg 2,3,208(15)\n\
- # load return address as third parameter\n\
- lgr 4,14\n\
- brasl 14,profile_fixup # call fixup\n\
- lgr 1,2 # function addr returned in r2\n\
- # restore registers\n\
- aghi 15,160\n\
- " CFI_ADJUST_CFA_OFFSET(-160)" \n\
- lg 14,96(15)\n\
- lmg 2,5,64(15)\n\
- br 1\n\
- " CFI_ENDPROC "\n\
- .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
- .size _dl_runtime_profile, .-_dl_runtime_profile\n\
-");
-#endif
-
/* 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. */
@@ -343,14 +238,19 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
return value;
}
+/* Names of the architecture-specific auditing callback functions. */
+#define ARCH_LA_PLTENTER s390_64_gnu_pltenter
+#define ARCH_LA_PLTEXIT s390_64_gnu_pltexit
+
#endif /* !dl_machine_h */
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
MAP is the object containing the reloc. */
-static inline void
+auto inline void
+__attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
const Elf64_Sym *sym, const struct r_found_version *version,
void *const reloc_addr_arg)
@@ -384,17 +284,8 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
#ifndef RESOLVE_CONFLICT_FIND_MAP
const Elf64_Sym *const refsym = sym;
#endif
-#if defined USE_TLS && !defined RTLD_BOOTSTRAP
struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
Elf64_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
-#else
- Elf64_Addr value = RESOLVE (&sym, version, r_type);
-
-# ifndef RTLD_BOOTSTRAP
- if (sym)
-# endif
- value += sym->st_value;
-#endif /* use TLS and !RTLD_BOOTSTRAP */
switch (r_type)
{
@@ -518,7 +409,8 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
}
}
-static inline void
+auto inline void
+__attribute__ ((always_inline))
elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
void *const reloc_addr_arg)
{
@@ -526,7 +418,8 @@ elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
*reloc_addr = l_addr + reloc->r_addend;
}
-static inline void
+auto inline void
+__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
Elf64_Addr l_addr, const Elf64_Rela *reloc)
{
@@ -546,4 +439,4 @@ elf_machine_lazy_rel (struct link_map *map,
_dl_reloc_bad_type (map, r_type, 1);
}
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/s390/s390-64/dl-trampoline.S b/sysdeps/s390/s390-64/dl-trampoline.S
new file mode 100644
index 0000000000..215d869803
--- /dev/null
+++ b/sysdeps/s390/s390-64/dl-trampoline.S
@@ -0,0 +1,126 @@
+/* PLT trampolines. s390 version.
+ Copyright (C) 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
+ * with the following linkage:
+ * r2 - r6 : parameter registers
+ * f0, f2, f4, f6 : floating point parameter registers
+ * 24(r15), 28(r15) : PLT arguments PLT1, PLT2
+ * 96(r15) : additional stack parameters
+ * The normal clobber rules for function calls apply:
+ * r0 - r5 : call clobbered
+ * r6 - r13 : call saved
+ * r14 : return address (call clobbered)
+ * r15 : stack pointer (call saved)
+ * f1, f3, f5, f7 : call saved
+ * f0 - f3, f5, f7 - f15 : call clobbered
+ */
+
+#include <sysdep.h>
+
+ .text
+ .globl _dl_runtime_resolve
+ .type _dl_runtime_resolve, @function
+ cfi_startproc
+ .align 16
+_dl_runtime_resolve:
+ stmg 2,5,64(15) # save registers
+ stg 14,96(15)
+ lgr 0,15 # create stack frame
+ aghi 15,-160
+ cfi_adjust_cfa_offset (160)
+ stg 0,0(15)
+ lmg 2,3,208(15) # load args saved by PLT
+ brasl 14,_dl_fixup # call fixup
+ lgr 1,2 # function addr returned in r2
+ aghi 15,160 # remove stack frame
+ cfi_adjust_cfa_offset (-160)
+ lg 14,96(15) # restore registers
+ lmg 2,5,64(15)
+ br 1
+ cfi_endproc
+ .size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+
+ .globl _dl_runtime_profile
+ .type _dl_runtime_profile, @function
+ cfi_startproc
+ .align 16
+_dl_runtime_profile:
+ stmg %r2,%r6,64(%r15) # save registers
+ std %f0,104(%r15)
+ std %f2,112(%r15)
+ std %f4,120(%r15)
+ std %f6,128(%r15)
+ stg %r6,16(%r15)
+ stg %r12,24(%r15)
+ stg %r14,32(%r15)
+ lgr %r12,%r15 # create stack frame
+ cfi_def_cfa_register (12)
+ aghi %r15,-160
+ stg %r12,0(%r15)
+ lmg %r2,%r3,48(%r12) # load arguments saved by PLT
+ lgr %r4,%r14 # return address as third parameter
+ la %r5,64(%r12) # pointer to struct La_s390_32_regs
+ la %r6,40(%r12) # long int * framesize
+ brasl %r14,_dl_profile_fixup # call resolver
+ lgr %r1,%r2 # function addr returned in r2
+ lg %r0,40(%r12) # load framesize
+ ltgr %r0,%r0
+ jnm 1f
+ lmg %r2,%r6,64(%r12)
+ ld %f0,104(%r12)
+ ld %f2,112(%r12)
+ ld %f4,120(%r12)
+ ld %f6,128(%r12)
+ basr %r14,%r1 # call resolved function
+0: lr %r15,%r12 # remove stack frame
+ cfi_def_cfa_register (15)
+ lg %r14,32(%r15) # restore registers
+ lg %r12,24(%r15)
+ lg %r6,16(%r15)
+ br %r14
+ cfi_def_cfa_register (12)
+1: jz 4f # framesize == 0 ?
+ aghi %r0,7 # align framesize to 8
+ nill %r0,0xfff8
+ slgr %r15,%r0 # make room for framesize bytes
+ stg %r12,0(%r15)
+ la %r2,160(%r15)
+ la %r3,160(%r12)
+ srlg %r0,%r0,3
+3: mvc 0(8,%r2),0(%r3) # copy additional parameters
+ la %r2,8(%r2)
+ la %r3,8(%r3)
+ brctg %r0,3b
+4: lmg %r2,%r6,64(%r12) # load register parameters
+ ld %f0,104(%r12)
+ ld %f2,112(%r12)
+ ld %f4,120(%r12)
+ ld %f6,128(%r12)
+ basr %r14,%r1 # call resolved function
+ stg %r2,136(%r12)
+ std %f0,144(%r12)
+ lmg %r2,%r3,48(%r12) # load arguments saved by PLT
+ la %r4,32(%r12) # pointer to struct La_s390_32_regs
+ la %r5,72(%r12) # pointer to struct La_s390_32_retval
+ brasl %r14,_dl_call_pltexit
+ j 0b
+ cfi_endproc
+ .size _dl_runtime_profile, .-_dl_runtime_profile
diff --git a/sysdeps/sh/bits/link.h b/sysdeps/sh/bits/link.h
index bb2fbb5f16..2826677336 100644
--- a/sysdeps/sh/bits/link.h
+++ b/sysdeps/sh/bits/link.h
@@ -1,5 +1,70 @@
-struct link_map_machine
- {
- Elf32_Addr plt; /* Address of .plt + 36 */
- Elf32_Addr gotplt; /* Address of .got + 0x0c */
- };
+/* Copyright (C) 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+/* Registers for entry into PLT on SH. */
+typedef struct La_sh_regs
+{
+ uint32_t lr_r2;
+ uint32_t lr_r3;
+ uint32_t lr_r4;
+ uint32_t lr_r5;
+ uint32_t lr_r6;
+ uint32_t lr_r7;
+ uint32_t lr_fpscr;
+ float lr_fr4;
+ float lr_fr5;
+ float lr_fr6;
+ float lr_fr7;
+ float lr_fr8;
+ float lr_fr9;
+ float lr_fr10;
+ float lr_fr11;
+} La_sh_regs;
+
+/* Return values for calls from PLT on SH. */
+typedef struct La_sh_retval
+{
+ uint32_t lrv_r0;
+ uint32_t lrv_r1;
+ float lrv_fr0;
+ float lrv_fr1;
+} La_sh_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_sh_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ La_sh_regs *__regs,
+ unsigned int *__flags,
+ const char *__symname,
+ long int *__framesizep);
+extern unsigned int la_sh_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ const La_sh_regs *__inregs,
+ La_sh_retval *__outregs,
+ const char *symname);
+
+__END_DECLS
diff --git a/sysdeps/sh/bits/linkmap.h b/sysdeps/sh/bits/linkmap.h
new file mode 100644
index 0000000000..bb2fbb5f16
--- /dev/null
+++ b/sysdeps/sh/bits/linkmap.h
@@ -0,0 +1,5 @@
+struct link_map_machine
+ {
+ Elf32_Addr plt; /* Address of .plt + 36 */
+ Elf32_Addr gotplt; /* Address of .got + 0x0c */
+ };
diff --git a/sysdeps/sh/dl-machine.h b/sysdeps/sh/dl-machine.h
index 271666a2a3..b66b4f0e42 100644
--- a/sysdeps/sh/dl-machine.h
+++ b/sysdeps/sh/dl-machine.h
@@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation inline functions. SH version.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -21,8 +21,6 @@
#ifndef dl_machine_h
#define dl_machine_h
-/* Only dummy. This doesn't work. */
-
#define ELF_MACHINE_NAME "SH"
#include <sys/param.h>
@@ -106,7 +104,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
got[2] = (Elf32_Addr) &_dl_runtime_profile;
/* Say that we really want profiling and the timers are started. */
- GL(dl_profile_map) = l;
+ if (GLRO(dl_profile) != NULL
+ && _dl_name_match_p (GLRO(dl_profile), l))
+ GL(dl_profile_map) = l;
}
else
/* This function will get called to fix up the GOT entry indicated by
@@ -116,273 +116,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
return lazy;
}
-/* 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_FIXUP_ARGS int plt_type
-#ifdef SHARED
-#define FUN_ADDR "\
- mov.l 1f,r2\n\
- mova 1f,r0\n\
- bra 2f\n\
- add r0,r2 ! Get GOT address in r2\n\
-0: .align 2\n\
-1: .long _GLOBAL_OFFSET_TABLE_\n\
-2: mov.l 3f,r0\n\
- add r2,r0"
-#define GOTJMP(x) #x "@GOTOFF"
-#else
-#define FUN_ADDR "\
- mov.l 3f,r0"
-#define GOTJMP(x) #x
-#endif
-
-#ifdef HAVE_FPU
-#define FGR_SAVE "\
- sts.l fpscr, @-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov #8,r3\n\
- swap.w r3, r3\n\
- lds r3, fpscr\n\
- fmov.s fr11, @-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- fmov.s fr10, @-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- fmov.s fr9, @-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- fmov.s fr8, @-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- fmov.s fr7, @-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- fmov.s fr6, @-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- fmov.s fr5, @-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- fmov.s fr4, @-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4)
-#define FGR_LOAD "\
- fmov.s @r15+, fr4\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- fmov.s @r15+, fr5\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- fmov.s @r15+, fr6\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- fmov.s @r15+, fr7\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- fmov.s @r15+, fr8\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- fmov.s @r15+, fr9\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- fmov.s @r15+, fr10\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- fmov.s @r15+, fr11\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- lds.l @r15+, fpscr\n\
- " CFI_ADJUST_CFA_OFFSET (-4)
-#else
-#define FGR_SAVE ""
-#define FGR_LOAD ""
-#endif
-
-#ifndef PROF
-# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
- .text\n\
- .globl _dl_runtime_resolve\n\
- .type _dl_runtime_resolve, @function\n\
- " CFI_STARTPROC "\n\
- .align 5\n\
-_dl_runtime_resolve:\n\
- mov.l r2,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r3,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r4,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r5,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r6,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r7,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r12,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- movt r3 ! Save T flag.\n\
- mov.l r3,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- " FGR_SAVE "\n\
- sts.l pr,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- tst r0,r0\n\
- bt 1f\n\
- mov r0,r2\n\
-1:\n\
- mov r0,r4 ! PLT type\n\
- mov r2,r5 ! link map address\n\
- " FUN_ADDR "\n\
- jsr @r0 ! Call resolver.\n\
- mov r1,r6 ! reloc offset\n\
- lds.l @r15+,pr ! Get register content back.\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- " FGR_LOAD "\n\
- mov.l @r15+,r3\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- shal r3 ! Lode T flag.\n\
- mov.l @r15+,r12\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- mov.l @r15+,r7\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- mov.l @r15+,r6\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- mov.l @r15+,r5\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- mov.l @r15+,r4\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- mov.l @r15+,r3\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- jmp @r0 ! Jump to function address.\n\
- mov.l @r15+,r2\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- .align 2\n\
-3:\n\
- .long " GOTJMP (fixup) "\n\
- " CFI_ENDPROC "\n\
- .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-\n\
- .globl _dl_runtime_profile\n\
- .type _dl_runtime_profile, @function\n\
- " CFI_STARTPROC "\n\
- .align 5\n\
-_dl_runtime_profile:\n\
- mov.l r2,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r3,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r4,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r5,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r6,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r7,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r12,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- movt r3 ! Save T flag.\n\
- mov.l r3,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- " FGR_SAVE "\n\
- sts.l pr,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- tst r0,r0\n\
- bt 1f\n\
- mov r0,r2\n\
-1:\n\
- mov r0,r4 ! PLT type\n\
- mov r2,r5 ! link map address\n\
- sts pr,r7 ! return address\n\
- " FUN_ADDR "\n\
- jsr @r0 ! Call resolver.\n\
- mov r1,r6 ! reloc offset\n\
- lds.l @r15+,pr ! Get register content back.\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- " FGR_LOAD "\n\
- mov.l @r15+,r3\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- shal r3 ! Lode T flag.\n\
- mov.l @r15+,r12\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- mov.l @r15+,r7\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- mov.l @r15+,r6\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- mov.l @r15+,r5\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- mov.l @r15+,r4\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- mov.l @r15+,r3\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- jmp @r0 ! Jump to function address.\n\
- mov.l @r15+,r2\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- .align 2\n\
-3:\n\
- .long " GOTJMP (profile_fixup) "\n\
- " CFI_ENDPROC "\n\
- .size _dl_runtime_profile, .-_dl_runtime_profile\n\
- .previous\n\
-");
-#else
-# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
- .text\n\
- .globl _dl_runtime_resolve\n\
- .globl _dl_runtime_profile\n\
- .type _dl_runtime_resolve, @function\n\
- .type _dl_runtime_profile, @function\n\
- .align 5\n\
-_dl_runtime_resolve:\n\
-_dl_runtime_profile:\n\
- mov.l r2,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r3,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r4,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r5,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r6,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r7,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- mov.l r12,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- movt r3 ! Save T flag.\n\
- mov.l r3,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- " FGR_SAVE "\n\
- sts.l pr,@-r15\n\
- " CFI_ADJUST_CFA_OFFSET (4) "\n\
- tst r0,r0\n\
- bt 1f\n\
- mov r0,r2\n\
-1:\n\
- mov r0,r4 ! PLT type\n\
- mov r2,r5 ! link map address\n\
- sts pr,r7 ! return address\n\
- " FUN_ADDR "\n\
- jsr @r0 ! Call resolver.\n\
- mov r1,r6 ! reloc offset\n\
- lds.l @r15+,pr ! Get register content back.\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- " FGR_LOAD "\n\
- mov.l @r15+,r3\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- shal r3 ! Lode T flag.\n\
- mov.l @r15+,r12\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- mov.l @r15+,r7\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- mov.l @r15+,r6\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- mov.l @r15+,r5\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- mov.l @r15+,r4\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- mov.l @r15+,r3\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- jmp @r0 ! Jump to function address.\n\
- mov.l @r15+,r2\n\
- " CFI_ADJUST_CFA_OFFSET (-4) "\n\
- .align 2\n\
-3:\n\
- .long " GOTJMP (fixup) "\n\
- " CFI_ENDPROC "\n\
- .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
- .size _dl_runtime_profile, .-_dl_runtime_profile\n\
- .previous\n\
-");
-#endif
-
/* Mask identifying addresses reserved for the user program,
where the dynamic linker should not map anything. */
#define ELF_MACHINE_USER_ADDRESS_MASK 0x80000000UL
@@ -459,6 +194,12 @@ _dl_start_user:\n\
.long _rtld_local@GOT\n\
.L_dl_fini:\n\
.long _dl_fini@GOT\n\
+ .type __fpscr_values,@object\n\
+ .global __fpscr_values\n\
+__fpscr_values:\n\
+ .long 0\n\
+ .long 0x80000\n\
+ .weak __fpscr_values\n\
.previous\n\
");
@@ -510,9 +251,12 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
return value + reloc->r_addend;
}
+#define ARCH_LA_PLTENTER sh_gnu_pltenter
+#define ARCH_LA_PLTEXIT sh_gnu_pltexit
+
#endif /* !dl_machine_h */
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
/* SH never uses Elf32_Rel relocations. */
#define ELF_MACHINE_NO_REL 1
@@ -579,18 +323,9 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
else
{
const Elf32_Sym *const refsym = sym;
-#if defined USE_TLS && !defined RTLD_BOOTSTRAP
struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
- value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
-#else
-
- value = RESOLVE (&sym, version, r_type);
-# ifndef RTLD_BOOTSTRAP
- if (sym != NULL)
-# endif
- value += sym->st_value;
-#endif
+ value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
value += reloc->r_addend;
switch (r_type)
@@ -736,4 +471,4 @@ elf_machine_lazy_rel (struct link_map *map,
_dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 1);
}
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/sh/dl-trampoline.S b/sysdeps/sh/dl-trampoline.S
new file mode 100644
index 0000000000..79493d50b9
--- /dev/null
+++ b/sysdeps/sh/dl-trampoline.S
@@ -0,0 +1,431 @@
+/* PLT trampolines. SH version.
+ Copyright (C) 2005 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
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+
+ .text
+ .globl _dl_runtime_resolve
+ .type _dl_runtime_resolve, @function
+ cfi_startproc
+ .align 5
+_dl_runtime_resolve:
+ mov.l r2,@-r15
+ cfi_adjust_cfa_offset (4)
+ mov.l r3,@-r15
+ cfi_adjust_cfa_offset (4)
+ mov.l r4,@-r15
+ cfi_adjust_cfa_offset (4)
+ mov.l r5,@-r15
+ cfi_adjust_cfa_offset (4)
+ mov.l r6,@-r15
+ cfi_adjust_cfa_offset (4)
+ mov.l r7,@-r15
+ cfi_adjust_cfa_offset (4)
+ mov.l r12,@-r15
+ cfi_adjust_cfa_offset (4)
+ sts.l macl,@-r15
+ cfi_adjust_cfa_offset (4)
+ sts.l mach,@-r15
+ cfi_adjust_cfa_offset (4)
+ movt r3 ! Save T flag.
+ mov.l r3,@-r15
+ cfi_adjust_cfa_offset (4)
+#ifdef HAVE_FPU
+ sts.l fpscr,@-r15
+ cfi_adjust_cfa_offset (4)
+ mov #8,r3
+ swap.w r3,r3
+ lds r3,fpscr
+ fmov.s fr11,@-r15
+ cfi_adjust_cfa_offset (4)
+ fmov.s fr10,@-r15
+ cfi_adjust_cfa_offset (4)
+ fmov.s fr9,@-r15
+ cfi_adjust_cfa_offset (4)
+ fmov.s fr8,@-r15
+ cfi_adjust_cfa_offset (4)
+ fmov.s fr7,@-r15
+ cfi_adjust_cfa_offset (4)
+ fmov.s fr6,@-r15
+ cfi_adjust_cfa_offset (4)
+ fmov.s fr5,@-r15
+ cfi_adjust_cfa_offset (4)
+ fmov.s fr4,@-r15
+ cfi_adjust_cfa_offset (4)
+#endif
+ sts.l pr,@-r15
+ cfi_adjust_cfa_offset (4)
+ tst r0,r0
+ bt 1f
+ mov r0,r2
+1:
+ mov r0,r4 ! PLT type
+ mov r2,r5 ! link map address
+#ifdef SHARED
+ mov.l 2f,r2
+ mova 2f,r0
+ add r0,r2 ! Get GOT address in r2
+ mov.l 3f,r0
+ add r2,r0
+#else
+ mov.l 3f,r0
+#endif
+ jsr @r0 ! Call resolver.
+ mov r1,r6 ! reloc offset
+ lds.l @r15+,pr ! Get register content back.
+ cfi_adjust_cfa_offset (-4)
+#ifdef HAVE_FPU
+ fmov.s @r15+,fr4
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr5
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr6
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr7
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr8
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr9
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr10
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr11
+ cfi_adjust_cfa_offset (-4)
+ lds.l @r15+,fpscr
+ cfi_adjust_cfa_offset (-4)
+#endif
+ mov.l @r15+,r3
+ cfi_adjust_cfa_offset (-4)
+ shal r3 ! Lode T flag.
+ lds.l @r15+,mach
+ cfi_adjust_cfa_offset (-4)
+ lds.l @r15+,macl
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r12
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r7
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r6
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r5
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r4
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r3
+ cfi_adjust_cfa_offset (-4)
+ jmp @r0 ! Jump to function address.
+ mov.l @r15+,r2
+ cfi_adjust_cfa_offset (-4)
+ .align 2
+#ifdef SHARED
+2: .long _GLOBAL_OFFSET_TABLE_
+3: .long _dl_fixup@GOTOFF
+#else
+3: .long _dl_fixup
+#endif
+ cfi_endproc
+ .size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+
+ .globl _dl_runtime_profile
+ .type _dl_runtime_profile,@function
+ cfi_startproc
+ .align 5
+_dl_runtime_profile:
+ mov.l r12,@-r15
+ cfi_adjust_cfa_offset (4)
+#ifdef HAVE_FPU
+ sts.l fpscr,@-r15
+ cfi_adjust_cfa_offset (4)
+ mov #8,r12
+ swap.w r12,r12
+ lds r12,fpscr
+ fmov.s fr11,@-r15
+ cfi_adjust_cfa_offset (4)
+ fmov.s fr10,@-r15
+ cfi_adjust_cfa_offset (4)
+ fmov.s fr9,@-r15
+ cfi_adjust_cfa_offset (4)
+ fmov.s fr8,@-r15
+ cfi_adjust_cfa_offset (4)
+ fmov.s fr7,@-r15
+ cfi_adjust_cfa_offset (4)
+ fmov.s fr6,@-r15
+ cfi_adjust_cfa_offset (4)
+ fmov.s fr5,@-r15
+ cfi_adjust_cfa_offset (4)
+ fmov.s fr4,@-r15
+ cfi_adjust_cfa_offset (4)
+#else
+ add #-36,r15
+ cfi_adjust_cfa_offset (36)
+#endif
+ mov.l r7,@-r15
+ cfi_adjust_cfa_offset (4)
+ mov.l r6,@-r15
+ cfi_adjust_cfa_offset (4)
+ mov.l r5,@-r15
+ cfi_adjust_cfa_offset (4)
+ mov.l r4,@-r15
+ cfi_adjust_cfa_offset (4)
+ mov.l r3,@-r15
+ cfi_adjust_cfa_offset (4)
+ mov.l r2,@-r15
+ cfi_adjust_cfa_offset (4)
+ sts.l macl,@-r15
+ cfi_adjust_cfa_offset (4)
+ sts.l mach,@-r15
+ cfi_adjust_cfa_offset (4)
+ movt r3 ! Save T flag.
+ mov.l r3,@-r15
+ cfi_adjust_cfa_offset (4)
+ sts.l pr,@-r15
+ cfi_adjust_cfa_offset (4)
+ tst r0,r0
+ bt 1f
+ mov r0,r2
+1:
+ mov r0,r4 ! PLT type
+ mov r2,r5 ! link map address
+ sts pr,r7 ! return address
+ add #-24,r15
+ cfi_adjust_cfa_offset (24)
+ mov #40,r0
+ add r15,r0
+ mov.l r0,@r15 ! Address of the register structure
+ mov #-1,r0
+ mov.l r0,@(8,r15)
+ mov #8,r0
+ add r15,r0
+ mov.l r0,@(4,r15)
+ mov.l r5,@(12,r15)
+ mov.l r1,@(16,r15)
+#ifdef SHARED
+ mov.l 2f,r12
+ mova 2f,r0
+ add r0,r12 ! Get GOT address in r12
+ mov.l 3f,r0
+ add r12,r0
+#else
+ mov.l 3f,r0
+#endif
+ jsr @r0 ! Call resolver.
+ mov r1,r6 ! reloc offset
+ mov.l @(8,r15),r1
+ cmp/pz r1
+ bt 4f
+ add #24,r15
+ cfi_adjust_cfa_offset (-24)
+ lds.l @r15+,pr ! Get register content back.
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r3
+ cfi_adjust_cfa_offset (-4)
+ shal r3 ! Lode T flag.
+ lds.l @r15+,mach
+ cfi_adjust_cfa_offset (-4)
+ lds.l @r15+,macl
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r2
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r3
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r4
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r5
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r6
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r7
+ cfi_adjust_cfa_offset (-4)
+#ifdef HAVE_FPU
+ fmov.s @r15+,fr4
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr5
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr6
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr7
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr8
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr9
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr10
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr11
+ cfi_adjust_cfa_offset (-4)
+ lds.l @r15+,fpscr
+ cfi_adjust_cfa_offset (-4)
+#else
+ add #36,r15
+ cfi_adjust_cfa_offset (-36)
+#endif
+ jmp @r0 ! Jump to function address.
+ mov.l @r15+,r12
+ cfi_adjust_cfa_offset (-4)
+ .align 2
+#ifdef SHARED
+2: .long _GLOBAL_OFFSET_TABLE_
+3: .long _dl_profile_fixup@GOTOFF
+#else
+3: .long _dl_profile_fixup
+#endif
+
+ cfi_adjust_cfa_offset (104)
+4:
+ mov #104,r3
+ add r15,r3 ! Original stack
+ mov.l r8,@(20,r15)
+ cfi_rel_offset (r8, 20)
+ mov r15,r8
+ sub r1,r15
+ shlr2 r15
+ shll2 r15
+ mov r15,r4
+ shlr2 r1
+ tst r1,r1
+5:
+ bt/s 6f
+ dt r1
+ mov.l @r3+,r2
+ mov.l r2,@r4
+ bra 5b
+ add #4,r4
+6:
+ mov.l @r8,r12
+ mov.l @r12+,r2
+ mov.l @r12+,r3
+ mov.l @r12+,r4
+ mov.l @r12+,r5
+ mov.l @r12+,r6
+ mov.l @r12+,r7
+#ifdef HAVE_FPU
+ fmov.s @r12+,fr4
+ fmov.s @r12+,fr5
+ fmov.s @r12+,fr6
+ fmov.s @r12+,fr7
+ fmov.s @r12+,fr8
+ fmov.s @r12+,fr9
+ fmov.s @r12+,fr10
+ fmov.s @r12+,fr11
+ lds.l @r12+,fpscr
+#else
+ add #36,r2
+#endif
+ jsr @r0 ! Call function.
+ nop
+ mov r8,r15
+ mov.l @(12,r15),r4 ! link map address
+ mov.l @(16,r15),r5 ! reloc offset
+ mov.l @r15,r6 ! input registers
+#ifdef HAVE_FPU
+ mov #16,r8
+ add r15,r8
+ fmov.s fr1,@-r8
+ fmov.s fr0,@-r8
+#else
+ mov #8,r8
+ add r15,r8
+#endif
+ mov.l r1,@-r8
+ mov.l r0,@-r8
+ mov.l @(20,r15),r8
+ cfi_restore (r8)
+#ifdef SHARED
+ mov.l 7f,r12
+ mova 7f,r0
+ add r0,r12 ! Get GOT address in r12
+ mov.l 8f,r0
+ add r12,r0
+#else
+ mov.l 8f,r0
+#endif
+ jsr @r0
+ mov r15,r7 ! output registers
+ mov.l @r15+,r0
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r1
+ cfi_adjust_cfa_offset (-4)
+#ifdef HAVE_FPU
+ fmov.s @r15+,fr0
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr1
+ cfi_adjust_cfa_offset (-4)
+ add #8,r15
+ cfi_adjust_cfa_offset (-8)
+#else
+ add #16,r15
+ cfi_adjust_cfa_offset (-16)
+#endif
+ lds.l @r15+,pr ! Get register content back.
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r3
+ cfi_adjust_cfa_offset (-4)
+ shal r3 ! Lode T flag.
+ lds.l @r15+,mach
+ cfi_adjust_cfa_offset (-4)
+ lds.l @r15+,macl
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r2
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r3
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r4
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r5
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r6
+ cfi_adjust_cfa_offset (-4)
+ mov.l @r15+,r7
+ cfi_adjust_cfa_offset (-4)
+#ifdef HAVE_FPU
+ fmov.s @r15+,fr4
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr5
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr6
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr7
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr8
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr9
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr10
+ cfi_adjust_cfa_offset (-4)
+ fmov.s @r15+,fr11
+ cfi_adjust_cfa_offset (-4)
+ lds.l @r15+,fpscr
+ cfi_adjust_cfa_offset (-4)
+#else
+ add #36,r15
+ cfi_adjust_cfa_offset (-36)
+#endif
+ rts ! Jump to function address.
+ mov.l @r15+,r12
+ cfi_adjust_cfa_offset (-4)
+ cfi_endproc
+ .align 2
+#ifdef SHARED
+7: .long _GLOBAL_OFFSET_TABLE_
+8: .long _dl_call_pltexit@GOTOFF
+#else
+8: .long _dl_call_pltexit
+#endif
+ .size _dl_runtime_profile, .-_dl_runtime_profile
diff --git a/sysdeps/sh/sh4/Versions b/sysdeps/sh/sh4/Versions
new file mode 100644
index 0000000000..8cc1c7b7d4
--- /dev/null
+++ b/sysdeps/sh/sh4/Versions
@@ -0,0 +1,5 @@
+ld {
+ GLIBC_PRIVATE {
+ __fpscr_values;
+ }
+}
diff --git a/sysdeps/sh/sh4/dl-machine.h b/sysdeps/sh/sh4/dl-machine.h
deleted file mode 100644
index ec9f6f7b45..0000000000
--- a/sysdeps/sh/sh4/dl-machine.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#define HAVE_FPU
-#include <sysdeps/sh/dl-machine.h>
diff --git a/sysdeps/sh/sh4/dl-trampoline.S b/sysdeps/sh/sh4/dl-trampoline.S
new file mode 100644
index 0000000000..f9529851a1
--- /dev/null
+++ b/sysdeps/sh/sh4/dl-trampoline.S
@@ -0,0 +1,2 @@
+#define HAVE_FPU
+#include <sysdeps/sh/dl-trampoline.S>
diff --git a/sysdeps/unix/i386/sysdep.S b/sysdeps/unix/i386/sysdep.S
index 6056cbeef2..3bc872add8 100644
--- a/sysdeps/unix/i386/sysdep.S
+++ b/sysdeps/unix/i386/sysdep.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 2000, 2002, 2004
+/* Copyright (C) 1991,1992,1993,1994,1995,1996,1997,2000,2002,2004,2005
Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -47,7 +47,12 @@ notb:
#endif
#ifndef PIC
# if USE___THREAD
+# ifndef NO_TLS_DIRECT_SEG_REFS
movl %eax, %gs:C_SYMBOL_NAME(errno@NTPOFF)
+# else
+ movl %gs:0, %ecx
+ movl %eax, C_SYMBOL_NAME(errno@NTPOFF)(%ecx)
+# endif
# elif !defined _LIBC_REENTRANT
movl %eax, C_SYMBOL_NAME(errno)
# else
@@ -66,7 +71,12 @@ notb:
/* Pop %ebx value saved before jumping here. */
popl %ebx
+# ifndef NO_TLS_DIRECT_SEG_REFS
+ addl %gs:0, %ecx
+ movl %eax, (%ecx)
+# else
movl %eax, %gs:0(%ecx)
+# endif
# elif RTLD_PRIVATE_ERRNO
movl %eax, C_SYMBOL_NAME(rtld_errno@GOTOFF)(%ebx)
diff --git a/sysdeps/unix/rewinddir.c b/sysdeps/unix/rewinddir.c
index 9f3724fc6a..051e93595e 100644
--- a/sysdeps/unix/rewinddir.c
+++ b/sysdeps/unix/rewinddir.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1995-1998, 2005 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
@@ -30,6 +30,7 @@ rewinddir (dirp)
{
__libc_lock_lock (dirp->lock);
(void) __lseek (dirp->fd, (off_t) 0, SEEK_SET);
+ dirp->filepos = 0;
dirp->offset = 0;
dirp->size = 0;
__libc_lock_unlock (dirp->lock);
diff --git a/sysdeps/unix/sysv/linux/alpha/oldglob.c b/sysdeps/unix/sysv/linux/alpha/oldglob.c
index 9d39176f6b..6d9b79f2c3 100644
--- a/sysdeps/unix/sysv/linux/alpha/oldglob.c
+++ b/sysdeps/unix/sysv/linux/alpha/oldglob.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 2000, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 2000, 2004, 2005 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
@@ -91,6 +91,7 @@ __old_globfree (old_glob_t *pglob)
/* We only need these two symbols. */
correct.gl_pathc = pglob->gl_pathc;
correct.gl_pathv = pglob->gl_pathv;
+ correct.gl_offs = pglob->gl_offs;
globfree (&correct);
}
diff --git a/sysdeps/unix/sysv/linux/dl-execstack.c b/sysdeps/unix/sysv/linux/dl-execstack.c
index 6ef9679045..b38d0c4238 100644
--- a/sysdeps/unix/sysv/linux/dl-execstack.c
+++ b/sysdeps/unix/sysv/linux/dl-execstack.c
@@ -1,5 +1,5 @@
/* Stack executability handling for GNU dynamic linker. Linux version.
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005 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
@@ -24,6 +24,7 @@
#include <stdbool.h>
#include <stackinfo.h>
#include <caller.h>
+#include <sysdep.h>
#include "kernel-features.h"
@@ -38,6 +39,7 @@ _dl_make_stack_executable (void **stack_endp)
/* This gives us the highest/lowest page that needs to be changed. */
uintptr_t page = ((uintptr_t) *stack_endp
& -(intptr_t) GLRO(dl_pagesize));
+ int result = 0;
/* Challenge the caller. */
if (__builtin_expect (__check_caller (RETURN_ADDRESS (0),
@@ -60,7 +62,10 @@ _dl_make_stack_executable (void **stack_endp)
no_growsupdown = true;
else
# endif
- return errno;
+ {
+ result = errno;
+ goto out;
+ }
}
#endif
@@ -85,7 +90,10 @@ _dl_make_stack_executable (void **stack_endp)
else
{
if (errno != ENOMEM) /* Unexpected failure mode. */
- return errno;
+ {
+ result = errno;
+ goto out;
+ }
if (size == GLRO(dl_pagesize))
/* We just tried to mprotect the top hole page and failed.
@@ -108,7 +116,10 @@ _dl_make_stack_executable (void **stack_endp)
else
{
if (errno != ENOMEM) /* Unexpected failure mode. */
- return errno;
+ {
+ result = errno;
+ goto out;
+ }
if (size == GLRO(dl_pagesize))
/* We just tried to mprotect the lowest hole page and failed.
@@ -133,6 +144,11 @@ _dl_make_stack_executable (void **stack_endp)
/* Remember that we changed the permission. */
GL(dl_stack_flags) |= PF_X;
- return 0;
+ out:
+#ifdef check_consistency
+ check_consistency ();
+#endif
+
+ return result;
}
rtld_hidden_def (_dl_make_stack_executable)
diff --git a/sysdeps/unix/sysv/linux/futimes.c b/sysdeps/unix/sysv/linux/futimes.c
index f43f568ec1..0c4be2b67f 100644
--- a/sysdeps/unix/sysv/linux/futimes.c
+++ b/sysdeps/unix/sysv/linux/futimes.c
@@ -1,5 +1,5 @@
/* futimes -- change access and modification times of open file. Linux version.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2005 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
@@ -23,6 +23,7 @@
#include <utime.h>
#include <sys/time.h>
#include <stdio-common/_itoa.h>
+#include <fcntl.h>
#include "kernel-features.h"
@@ -40,31 +41,58 @@ __futimes (int fd, const struct timeval tvp[2])
char *cp = _itoa_word ((unsigned int) fd, fname + sizeof (fname) - 1, 10, 0);
cp = memcpy (cp - sizeof (selffd) + 1, selffd, sizeof (selffd) - 1);
+ int result;
#ifdef __NR_utimes
- int result = INLINE_SYSCALL (utimes, 2, cp, tvp);
+ result = INLINE_SYSCALL (utimes, 2, cp, tvp);
# ifndef __ASSUME_UTIMES
- if (result != -1 || errno != ENOSYS)
+ if (result == -1 && errno == ENOSYS)
# endif
- return result;
#endif
-
- /* The utimes() syscall does not exist or is not available in the
- used kernel. Use utime(). For this we have to convert to the
- data format utime() expects. */
+ {
+ /* The utimes() syscall does not exist or is not available in the
+ used kernel. Use utime(). For this we have to convert to the
+ data format utime() expects. */
#ifndef __ASSUME_UTIMES
- struct utimbuf buf;
- struct utimbuf *times;
+ struct utimbuf buf;
+ struct utimbuf *times;
- if (tvp != NULL)
- {
- times = &buf;
- buf.actime = tvp[0].tv_sec + (tvp[0].tv_usec + 500000) / 1000000;
- buf.modtime = tvp[1].tv_sec + (tvp[1].tv_usec + 500000) / 1000000;
- }
- else
- times = NULL;
+ if (tvp != NULL)
+ {
+ times = &buf;
+ buf.actime = tvp[0].tv_sec + (tvp[0].tv_usec + 500000) / 1000000;
+ buf.modtime = tvp[1].tv_sec + (tvp[1].tv_usec + 500000) / 1000000;
+ }
+ else
+ times = NULL;
- return INLINE_SYSCALL (utime, 2, cp, times);
+ result = INLINE_SYSCALL (utime, 2, cp, times);
#endif
+ }
+
+ if (result == -1)
+ /* Check for errors that result from failing to find /proc.
+ This means we can't do futimes at all, so return ENOSYS
+ rather than some confusing error. */
+ switch (errno)
+ {
+ case EACCES:
+ if (tvp == NULL) /* Could be a path problem or a file problem. */
+ break;
+ /*FALLTHROUGH*/
+ case ELOOP:
+ case ENAMETOOLONG:
+ case ENOTDIR:
+ __set_errno (ENOSYS);
+ break;
+
+ case ENOENT:
+ /* Validate the file descriptor by letting fcntl set errno to
+ EBADF if it's bogus. Otherwise it's a /proc issue. */
+ if (INLINE_SYSCALL (fcntl, 3, fd, F_GETFD, 0) != -1)
+ __set_errno (ENOSYS);
+ break;
+ }
+
+ return result;
}
weak_alias (__futimes, futimes)
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h
index af75d4c51a..6bea9d2044 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.h
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.h
@@ -1,5 +1,5 @@</