]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Updated to fedora-glibc-20050208T0948 cvs/fedora-glibc-2_3_4-6
authorJakub Jelinek <jakub@redhat.com>
Tue, 8 Feb 2005 10:05:09 +0000 (10:05 +0000)
committerJakub Jelinek <jakub@redhat.com>
Tue, 8 Feb 2005 10:05:09 +0000 (10:05 +0000)
219 files changed:
ChangeLog
Makeconfig
catgets/gencat.c
configure
configure.in
csu/elf-init.c
csu/version.c
debug/catchsegv.sh
debug/chk_fail.c
debug/xtrace.sh
dirent/tst-seekdir.c
dlfcn/Makefile
dlfcn/dlclose.c
dlfcn/dlfcn.c [new file with mode: 0644]
dlfcn/dlmopen.c
dlfcn/dlopen.c
dlfcn/dlopenold.c
elf/Makefile
elf/Versions
elf/dl-close.c
elf/dl-debug.c
elf/dl-fini.c
elf/dl-init.c
elf/dl-libc.c
elf/dl-load.c
elf/dl-object.c
elf/dl-open.c
elf/dl-reloc.c
elf/dl-runtime.c
elf/dl-sym.c
elf/dynamic-link.h
elf/ldconfig.c
elf/ldd.bash.in
elf/link.h
elf/rtld.c
elf/sprof.c
elf/tst-align2.c [new file with mode: 0644]
elf/tst-alignmod2.c [new file with mode: 0644]
elf/tst-audit1.c [new file with mode: 0644]
elf/tst-auditmod1.c [new file with mode: 0644]
fedora/branch.mk
fedora/glibc.spec.in
grp/putgrent.c
hurd/sigunwind.c
iconv/iconv_prog.c
iconv/iconvconfig.c
iconv/strtab.c
iconvdata/jis0208.h
include/dlfcn.h
include/link.h
libio/fmemopen.c
libio/iofopncook.c
libio/stdio.h
linuxthreads/ChangeLog
linuxthreads/Makefile
linuxthreads/pthread.c
linuxthreads/specific.c
linuxthreads/sysdeps/alpha/tls.h
linuxthreads/sysdeps/i386/tls.h
linuxthreads/sysdeps/ia64/tls.h
linuxthreads/sysdeps/powerpc/tls.h
linuxthreads/sysdeps/s390/tls.h
linuxthreads/sysdeps/sh/tls.h
linuxthreads/sysdeps/sparc/tls.h
linuxthreads/sysdeps/x86_64/tls.h
linuxthreads/tst-tsd1.c [new file with mode: 0644]
linuxthreads_db/ChangeLog
linuxthreads_db/td_thr_tlsbase.c
locale/programs/locale.c
locale/programs/localedef.c
malloc/malloc.c
malloc/malloc.h
malloc/memusage.sh
malloc/mtrace.pl
manual/.cvsignore
manual/memory.texi
manual/string.texi
manual/users.texi
math/math_private.h
misc/sys/cdefs.h
nptl/ChangeLog
nptl/allocatestack.c
nptl/sysdeps/alpha/tls.h
nptl/sysdeps/generic/lowlevellock.h
nptl/sysdeps/i386/tls.h
nptl/sysdeps/ia64/tls.h
nptl/sysdeps/powerpc/tls.h
nptl/sysdeps/pthread/pthread.h
nptl/sysdeps/s390/tls.h
nptl/sysdeps/sh/tls.h
nptl/sysdeps/sparc/tls.h
nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S
nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S
nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S
nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S
nptl/sysdeps/x86_64/tls.h
nscd/Makefile
nscd/connections.c
nscd/nscd.c
nscd/nscd.init
nscd/nscd_getai.c
nscd/nscd_helper.c
nscd/nscd_initgroups.c
nscd/nscd_nischeck.c
nss/getent.c
posix/Makefile
posix/bug-regex19.c
posix/execl.c
posix/execle.c
posix/execlp.c
posix/execvp.c
posix/getconf.c
posix/regcomp.c
posix/regex_internal.c
posix/regex_internal.h
posix/regexec.c
posix/rxspencer/tests
posix/tst-rxspencer.c
posix/unistd.h
pwd/putpwent.c
shadow/sgetspent_r.c
stdio-common/tst-fmemopen2.c
stdlib/Makefile
stdlib/fmtmsg.c
stdlib/stdlib.h
stdlib/tst-fmtmsg.c
sunrpc/openchild.c
sunrpc/rpc_main.c
sunrpc/svc_tcp.c
sunrpc/svc_unix.c
sysdeps/alpha/bits/link.h [new file with mode: 0644]
sysdeps/alpha/dl-machine.h
sysdeps/alpha/dl-trampoline.S [new file with mode: 0644]
sysdeps/alpha/fpu/bits/mathinline.h
sysdeps/alpha/libc-tls.c
sysdeps/arm/bits/link.h
sysdeps/arm/bits/linkmap.h [new file with mode: 0644]
sysdeps/generic/bits/link.h
sysdeps/generic/bits/linkmap.h [new file with mode: 0644]
sysdeps/generic/dl-fptr.h
sysdeps/generic/dl-lookupcfg.h
sysdeps/generic/dl-tls.c
sysdeps/generic/dl-trampoline.c [new file with mode: 0644]
sysdeps/generic/ldsodefs.h
sysdeps/generic/libc-start.c
sysdeps/generic/libc-tls.c
sysdeps/generic/syslog.c [moved from misc/syslog.c with 96% similarity]
sysdeps/generic/unsecvars.h
sysdeps/generic/wordexp.c
sysdeps/hppa/bits/link.h
sysdeps/hppa/bits/linkmap.h [new file with mode: 0644]
sysdeps/hppa/dl-lookupcfg.h
sysdeps/i386/Makefile
sysdeps/i386/bits/link.h
sysdeps/i386/bits/linkmap.h [new file with mode: 0644]
sysdeps/i386/dl-machine.h
sysdeps/i386/dl-trampoline.S [new file with mode: 0644]
sysdeps/ia64/bits/link.h
sysdeps/ia64/bits/linkmap.h [new file with mode: 0644]
sysdeps/ia64/dl-lookupcfg.h
sysdeps/ia64/dl-machine.h
sysdeps/ia64/dl-trampoline.S [new file with mode: 0644]
sysdeps/ia64/fpu/e_logl.c [deleted file]
sysdeps/ia64/libc-tls.c
sysdeps/linkmap.h [new file with mode: 0644]
sysdeps/m68k/bits/link.h [new file with mode: 0644]
sysdeps/m68k/dl-machine.h
sysdeps/m68k/dl-trampoline.S [new file with mode: 0644]
sysdeps/mach/hurd/tls.h
sysdeps/powerpc/powerpc32/bits/link.h [new file with mode: 0644]
sysdeps/powerpc/powerpc32/dl-machine.c
sysdeps/powerpc/powerpc32/dl-machine.h
sysdeps/powerpc/powerpc32/dl-trampoline.S [new file with mode: 0644]
sysdeps/powerpc/powerpc64/bits/link.h [new file with mode: 0644]
sysdeps/powerpc/powerpc64/dl-lookupcfg.h
sysdeps/powerpc/powerpc64/dl-machine.h
sysdeps/powerpc/powerpc64/dl-trampoline.S [new file with mode: 0644]
sysdeps/powerpc/tst-stack-align.h [new file with mode: 0644]
sysdeps/s390/bits/link.h
sysdeps/s390/bits/linkmap.h [new file with mode: 0644]
sysdeps/s390/bits/string.h
sysdeps/s390/s390-32/dl-machine.h
sysdeps/s390/s390-32/dl-trampoline.S [new file with mode: 0644]
sysdeps/s390/s390-64/dl-machine.h
sysdeps/s390/s390-64/dl-trampoline.S [new file with mode: 0644]
sysdeps/sh/bits/link.h
sysdeps/sh/bits/linkmap.h [new file with mode: 0644]
sysdeps/sh/dl-machine.h
sysdeps/sh/dl-trampoline.S [new file with mode: 0644]
sysdeps/sh/sh4/Versions [new file with mode: 0644]
sysdeps/sh/sh4/dl-machine.h [deleted file]
sysdeps/sh/sh4/dl-trampoline.S [new file with mode: 0644]
sysdeps/unix/i386/sysdep.S
sysdeps/unix/rewinddir.c
sysdeps/unix/sysv/linux/alpha/oldglob.c
sysdeps/unix/sysv/linux/dl-execstack.c
sysdeps/unix/sysv/linux/futimes.c
sysdeps/unix/sysv/linux/i386/sysdep.h
sysdeps/unix/sysv/linux/init-first.c
sysdeps/unix/sysv/linux/kernel-features.h
sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S
sysdeps/unix/sysv/linux/powerpc/powerpc64/swapcontext.S
sysdeps/unix/sysv/linux/syslog.c [new file with mode: 0644]
sysdeps/x86_64/bits/link.h
sysdeps/x86_64/bits/linkmap.h [new file with mode: 0644]
sysdeps/x86_64/dl-machine.h
sysdeps/x86_64/dl-trampoline.S [new file with mode: 0644]
time/strptime_l.c
time/tst-strptime.c
timezone/asia
timezone/backward
timezone/europe
timezone/leapseconds
timezone/northamerica
timezone/private.h
timezone/southamerica
timezone/tzfile.h
timezone/zdump.c
timezone/zic.c

index ab874d8fedb8cbc1a530c826afcd9d9f1987ed69..ba9d8763271f906461c8d030446f94d8d0c6f02f 100644 (file)
--- 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>
 
 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.
index d267e5af21c0ee5a053395c7d65f2eeea2ea5cd0..5ecda01169ded1f21fee0ed82271f293b62d2b87 100644 (file)
@@ -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)
index 2f6c81dc1d6d634b61df3310517cf39a2f59b346..39938097d3be8a8b93369775e0e7b0c23d13372f 100644 (file)
@@ -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");
 }
 
index e10f4b98360acba50132949aa03d9143786fb7ca..1e9e50c4919314638bf0d4422da5dc0b28585369 100755 (executable)
--- 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"
 
index 4ad54cfefd0088e437acca04cae58a74d52aabb1..11f78b0ec3348a14088915f50e704cfee667de07 100644 (file)
@@ -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"
 
index c538627dfd249eb82748e75316577ac344edcdd5..dbd2a91cb7778010160406dc478ab1c7b4f341ce 100644 (file)
@@ -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
 }
index 1104fa91370b07be691ce8b076b6aa862368272d..606246a6e13262cb55178173d3bc41d1b588e357 100644 (file)
@@ -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\
index 14556f712a2b35f6f69243fda036492b1649d426..f7e79bce42e89b1a70aa0e369a8ab09d9b44f026 100755 (executable)
@@ -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.'
index dc1c3d70b6cf2c1921dd6393fb9f83995995f2a9..29df08b9cae9c24674f49dd557624bdfb7a4708a 100644 (file)
@@ -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
 #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)
index 4ce88884904335ac4e2822d32161fd52ea44ffef..811d6ba9a617c374fd1129674ce29d068736995b 100755 (executable)
@@ -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
index b833c30705fc06864956c2c75c7355dc0afbf3f4..43808fecb58a48d41bae0464293cae0a677e8c1b 100644 (file)
@@ -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;
index ed20ae5ccd279845f7e89b18b3f04aab47362bb8..7b538fed2b0ab9529c6980d60e7e2998a2390272 100644 (file)
@@ -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)
index 3ddedcffbe388320ad76faf505644b5d6d002818..5a344f31ca1fae44cafe7c570ec7eed9f33459e5 100644 (file)
@@ -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 (file)
index 0000000..9c0a84a
--- /dev/null
@@ -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;
+}
index 5fd65436555f78c505c6b5f73ca45394a8ddaac0..0a6d47ea2e234bc0e576db6fa440a055debe8544 100644 (file)
@@ -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);
 }
 
 
index 6381ffc9b1ab4f8d53391fc5111bb2af3dd14980..bffb512aa3cb71542211cb781459f20ed6fbe7e9 100644 (file)
@@ -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
    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);
 }
 
 
index 148716cdb027d2a93f3b0d96b158ed161182d024..8dae1c40cecdbc88e048e4f772b3cfb639328351 100644 (file)
@@ -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);
index 87172d367d829096133066e987c40509a0abe3ee..47e6ea4d589ff9a06d69c7cb9d69858852feeecc 100644 (file)
@@ -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
index e24b2de04cbc078624ae700044242a50b5ee75c7..aaacf3e4ea23a0989aeb3b87d7eb83d68d79a11a 100644 (file)
@@ -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;
index c823b176427fedae1afc5260ba43a9d9ed468b6a..eb5e805dd43c4eff58fd418678fa66fad0418297 100644 (file)
@@ -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
index bd6ee69189ccda38011c6f045419df9ad2650610..bc7d793435e8e6768c8de29b98df6c28dd2f4d8d 100644 (file)
@@ -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;
 }
 
 
index f43f4a00ed2fc89f860fbccff8d51ac58e8d1a3c..b3282089a933ce5dca3ba8b0e34b292d745e6a9f 100644 (file)
@@ -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"
index e700dffb3a5f254f32eebfeb00cdb6a80606d3cc..e7b67570fd29a0807d1f41862b516652852b8e38 100644 (file)
@@ -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;
index 8a3f542e01aa5017f6d171c40d5332f8ded623f6..5e76069139eb5886c70c8a0605ab0e2e21faf0f9 100644 (file)
 #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;
 
index eb1a7919fb8d00250491b0a979915670d84ba80f..f307dada2e013375f8e5f9d5e88ebcb871e0099e 100644 (file)
@@ -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;
 }
 \f
@@ -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.  */
index b46ebdc33f543ae9c5874fc052452d4f7f2dc0d6..86f7a8e4d9355d3427a733764e85558918bbe29c 100644 (file)
@@ -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'
index 7e890ad7f7bd9fc56ff40ad2f998263161468de7..4de20720ed0052018d3a9176a4d8ac5d920b76cc 100644 (file)
@@ -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
index 4004316c5a3e5fa49b8011a194bd7b83ca9eb8d5..b680683198bf49dfde52e09e3f0422c35494d15c 100644 (file)
@@ -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;
          }
       }
index a0aecda2e83cb04e4d3a54bdefa68446ecf34383..f92cbe26bd25c9d9086b0c5dab3c3be1eb8f4e2b 100644 (file)
@@ -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"
 
    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
+}
index ba00ef56f4b5dd2e88f75094bf6c88b0f0c89de4..ca83daf21dfb5f25d3879bbe3d0579105d0eda3e 100644 (file)
@@ -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;
index f9559dc59c203133607bdce55ca8e99c1cb5bb15..51181441741c833b6239fde87317087c33f630d1 100644 (file)
@@ -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)
index f8504fb95eb7bcae6a3e58fc2d5ede86aa30febf..70f3a8f402bdf9dce2958dc22f9c42eee9053053 100644 (file)
@@ -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");
 }
index 4d7c33c728643250bc02531344d1566050f7c3b0..4587efd1cb9f33ad88672c9b161daab1a73e32c2 100644 (file)
@@ -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
index 6d5ad9d98c66da85f8abd32da5f16df4c691b3b9..fdda019cbefb04d4c2531b46a0cde54688f11ebe 100644 (file)
@@ -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
 
index 3835a207ec73a06902fca827c2d6a83ad213752e..9fda5b8122c7bbb7defb4616556d58507b94c5cb 100644 (file)
@@ -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
 {
@@ -590,6 +599,28 @@ map_doit (void *a)
                              LM_ID_BASE);
 }
 
+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)
 {
@@ -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");
     }
 }
 \f
+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;
+         }
+      }
+}
+\f
 /* 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:
index afe3955ad8b7e84acfe3b8df24276a396243b0fb..9567e4689fdbd2ecbdd3704e012e216b4f596c91 100644 (file)
@@ -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 (file)
index 0000000..4fc0330
--- /dev/null
@@ -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 (file)
index 0000000..21dcc53
--- /dev/null
@@ -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 (file)
index 0000000..63656b4
--- /dev/null
@@ -0,0 +1 @@
+#include "../io/pwd.c"
diff --git a/elf/tst-auditmod1.c b/elf/tst-auditmod1.c
new file mode 100644 (file)
index 0000000..9b07588
--- /dev/null
@@ -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;
+}
index 4c1e1f0f5c2248d4adaa84b041dd4ca17ab77cf8..96a37d0f31be0c03602e41ff37614f2be9be5609 100644 (file)
@@ -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
index d063010b1f4d8056a4e581497a4bbca5acfb7e8f..f508a0dae2c0d519920ed3b6ae33abedc447c051 100644 (file)
@@ -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)
index cb9b6b1f79956802ecf8c23c5977b3f4946151c1..382d6a4daa88a8666ead0761d08899e7192b0a5f 100644 (file)
@@ -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);
index 450a385a2abf3f339ef72a130b0d95388dd0fe14..1c6489b3b320b6249da9a4e9c9afaf2964583981 100644 (file)
@@ -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;
index 86852857a3fae270e48f02bf54cf68094ad89345..5b3d35ecaaecf8ff0ba4e4febb1b3b2f2c7024f9 100644 (file)
@@ -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");
 }
 
index 0ed210b794571fec71607564358fd06158f84835..8c56d29bb08e87a26b49a8d35aa392c9f26e187c 100644 (file)
@@ -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");
 }
 
index e6feb2cf24a79803198e746370c1e63ef4e0c080..4a8f29a67577c77d4c06386325821fd5a8a39e53 100644 (file)
@@ -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;
index 9dea38973ca73d635257cdb3875f99da9a8a5a37..8255bafc62f97e2abcff628b6631a68fb61bc86e 100644 (file)
@@ -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.
 
 #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)
index bfa1b9041ba051c651c190c750388fa8fce37e7c..460c037ed1aac4e22df13fd87edda1f52c2fafdb 100644 (file)
@@ -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
index 3078b72a87c7bc0be5bd11a73c38deb20f1288ee..965419126dfdaf07f257f2963bd88caf44e8c921 100644 (file)
@@ -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;
index 51e849e846466523d63ecef72678e31b5c8b731c..7c8769a130892826ddccfb3d001c553828af04ca 100644 (file)
@@ -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"
index eba3d435dcfa5254cce226351c32db3f7c60269c..9c5503d1f2741986e215cd50a0e02e148be0e3cd 100644 (file)
@@ -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
index 9b529dd839f156a8964fa59b6dab320d5857748f..ac42b3e2ac7af97401777fe8dd6b46321434c612 100644 (file)
@@ -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
 
 
index ff1b7fea934fd77f4ca97f53d06c9649f3cfb68a..329f2d8b12132b2f9373f4e162005ed822157ca6 100644 (file)
@@ -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.
index d9bf476c7ee735e19a1c2016568ce0b6802cd3c1..c2b548b38b8d219c956d16104754d08646ab227b 100644 (file)
@@ -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
index 24f0eb02b01e98255abf9023b55fa97f375c8449..39863f2b5456a2e10a689819f96fd05221dd657f 100644 (file)
@@ -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),
index f54fabaeb9bbde5349fa49671a6ad0fe068f6c9c..92eec3d99a553252e94809c5b81da29b68b5f25a 100644 (file)
@@ -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;
index 9e15318b792acb6bc8280fd87193411a481f8168..1eabf5b890cef4e34450c12f90450afeebfeb6c8 100644 (file)
@@ -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
 #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;
 
 
index d296340ad8c475501fbf11d4bf458443027de71c..f5d555baece8ba6da44e67da988414567d6ce1f1 100644 (file)
@@ -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>
 
 typedef union dtv
 {
   size_t counter;
-  void *pointer;
+  struct
+  {
+    void *val;
+    bool is_static;
+  } pointer;
 } dtv_t;
 
 
index 6bdf819d8d89cc1e27694f309bf2b0e188d9c80e..fe8fcd15f8cacb0e3d80bf25164509265127fa13 100644 (file)
@@ -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
 
 # 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__ */
index fda953976e4f40c1afea72a323d70e15b992f08c..35472081d6467457aa117760341de68e61664fc5 100644 (file)
@@ -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
 #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 *) \
index f420195bd285b1548389d66fe9374dd519ebd544..00a4df9382318c71e4bf076e150557d678009452 100644 (file)
@@ -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
 #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
index bc9d44fa854d37fe53e15f66d4385f78e19d0ac1..fbc6f01151b5c937e825493ea982c16cf8998578 100644 (file)
@@ -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>
 
 typedef union dtv
 {
   size_t counter;
-  void *pointer;
+  struct
+  {
+    void *val;
+    bool is_static;
+  } pointer;
 } dtv_t;
 
 #else /* __ASSEMBLER__ */
index 50538240585b94bcd35eb7a2c5a5ea0b46bf3a56..3e550fa7c7e86f29286ac1af758a1301810514dd 100644 (file)
@@ -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
 #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
index d979bbd896ee69a7c00828ba9fbfe6742a88cb4a..67d80b28d9cc0530ea25a16ad44faf8659098c28 100644 (file)
@@ -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
 #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 (file)
index 0000000..ba7973f
--- /dev/null
@@ -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"
index 338bf8207f401d98ca5f309a2915a1d88fd869d4..4bda6fb47a9b82125bb4f3e55a51cab5228eb4c6 100644 (file)
@@ -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.
index 081e8d0e7029426f8d5806168fa7a1d83a63e08b..5a7e31b9e19b1fc8d9330deba6064d1f70b70321 100644 (file)
@@ -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
index adf99445789c1bc04ca30f4bdc0483f66234d963..d64bb0b5609353f20756917569ee36c3a9ecc7fa 100644 (file)
@@ -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");
 }
 
index 28cb7b316e1e62923bb2ee218b45ca57a91bbc5c..326113c1753fa44601e5701176bcbd2c171d9ccd 100644 (file)
@@ -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");
 }
 
index e3ccbde7b5b84affbf6ff2387a5151310235f0a3..4d2169bf78f32375c984dd8d9214333493cce112 100644 (file)
@@ -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 ();
index 753539e7b0fbb59584315054ae1781be66a53583..0f99e837c31abde8fd282b4a1cc6ffd95e215f41 100644 (file)
@@ -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
 #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.  */
 
 #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 */
index be8f755a20e704d4efa9797f4e4cba0db9860cc1..b2e08c6039ea52b3053962151e9a8372254e4e91 100755 (executable)
@@ -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
index 1640fa652db164143a9054ee67696b74ec395170..0036f33f5918ffacc3041d9ee5d34cc41678eecf 100644 (file)
@@ -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";
index f1254e92d3fa6830a3b2d0850b6629d568480bef..54abbbb5a4258d5400388804820ed07e8e04a74e 100644 (file)
@@ -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
index 91abb7f5d446a1d336811890f58d63ef64cffe2a..ee2cd75c440fe4ee246fb386868b9eca9dcbe38e 100644 (file)
@@ -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
index 21ab71461aa0240f527521aaa37c0f5cf6eaa9c8..d9de12996e3d2b919ebdff5859a87fd1211f6b06 100644 (file)
@@ -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
index 20deeabdd279bc2275bc020ac4774123e02dd01a..b52ee44439cac63e314720d0fda6ecba0e35a59e 100644 (file)
@@ -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
 
index f545841df089cc8f768cf17b8aa75e6fe45c2a26..a6a85d3b1eccbf6c3bf8132154ddfe901a57e85d 100644 (file)
@@ -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.  */
index 6ac21013cc1196315445bf2fcea4c40a34d58a23..8d529bfadc93f1734a5c8a39adfc937ecf3c9f86 100644 (file)
@@ -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
 
 /* 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
 
index ec4d10b7ad31b88187ba594265f506ef4ac213e1..f372bde30e429047c5d54ea87da3aa766dcdc365 100644 (file)
@@ -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.
        * 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>
index 8875209a11ee576f2456a2793d587eaa67b98166..fcb6c6e475680c7c97f60a186ded19871bcbb4ed 100644 (file)
@@ -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),
index bc6630953f2d85d4c116cc997431a5830d6b9439..fa3c832a68d229bb0599c3f6133b8e4722640918 100644 (file)
@@ -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>
 
 typedef union dtv
 {
   size_t counter;
-  void *pointer;
+  struct
+  {
+    void *val;
+    bool is_static;
+  } pointer;
 } dtv_t;
 
 #else /* __ASSEMBLER__ */
index 9cffca83e67e3afac708422b7955fb2e92beac32..7f95daadadcda1d42e9bd16967a2f213363feda1 100644 (file)
@@ -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
index 945a4c71d65b273ff7373581f18714cd0d5c6777..e243f8b2cf9db557e93baa9dc91d85f1885bc47c 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <dl-sysdep.h>
 #ifndef __ASSEMBLER__
+# include <stdbool.h>
 # include <stddef.h>
 # include <stdint.h>
 # include <stdlib.h>
 typedef union dtv
 {
   size_t counter;
-  void *pointer;
+  struct
+  {
+    void *val;
+    bool is_static;
+  } pointer;
 } dtv_t;
 
 
index 4591a415c0569ea5b821196fa9f219447a36c3a5..a435f966cac268d34fad42b8d7654a05ce6d73bd 100644 (file)
@@ -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>
 typedef union dtv
 {
   size_t counter;
-  void *pointer;
+  struct
+  {
+    void *val;
+    bool is_static;
+  } pointer;
 } dtv_t;
 
 
index ce7f5bd53d425588fadbf903a95ac1b1b39d12b1..a7f69074e90772c46609478c23384d9a41a90395 100644 (file)
@@ -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>
 
 typedef union dtv
 {
   size_t counter;
-  void *pointer;
+  struct
+  {
+    void *val;
+    bool is_static;
+  } pointer;
 } dtv_t;
 
 #else /* __ASSEMBLER__ */
index 5046a6976baf92b82fff9c49267579a5616aac99..57024e1e845ce23268907c4d302d128dcab8af73 100644 (file)
@@ -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.  */
index c9b991df32d278a93adac465904f402dee5c31a5..e93f3d080c8b1b36ae644b32295e2d02926118ff 100644 (file)
@@ -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>
 typedef union dtv
 {
   size_t counter;
-  void *pointer;
+  struct
+  {
+    void *val;
+    bool is_static;
+  } pointer;
 } dtv_t;
 
 
index db490ab7ee62b34231453be6188b83f547959c89..e883bae99334957123694b60f8e2a1a19e16a64e 100644 (file)
@@ -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>
 
 typedef union dtv
 {
   size_t counter;
-  void *pointer;
+  struct
+  {
+    void *val;
+    bool is_static;
+  } pointer;
 } dtv_t;
 
 typedef struct
index 8980f9fc0ccae70563ee90ca1b035234a0f7e82a..8f54a0bb237df9bbac704d4c418d5e63b920e861 100644 (file)
@@ -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>
 typedef union dtv
 {
   size_t counter;
-  void *pointer;
+  struct
+  {
+    void *val;
+    bool is_static;
+  } pointer;
 } dtv_t;
 
 typedef struct
index 3d67329bd1569d76de0bca331bd57f0a7c26aee9..71e96d2228ef6f51175b0cd840cf9bdd97f485e9 100644 (file)
@@ -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)
index 5b244769361ae3cd79c9f5158113e7e275ea81cd..318b53a87340004483e4c0cb287a1350db9c3c7e 100644 (file)
@@ -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)
index a7c405d95f3f1b5ca801e8c6c1c13b5b54a3a0f0..d36a1088fbc9fd18c75caeec36dd4102ac967210 100644 (file)
@@ -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)
index b7674dc3baf85e0574a7fefd0a1245decd8ad4fb..1605b69b6902b7357f224208d96bdd4a4d1ff060 100644 (file)
@@ -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)
index 3d6111f4e3fb89a989c7b5ab33da9cff07302f5a..12da9dc81f01d7025ab5a02ab308f78e8fde3a50 100644 (file)
@@ -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>
 typedef union dtv
 {
   size_t counter;
-  void *pointer;
+  struct
+  {
+    void *val;
+    bool is_static;
+  } pointer;
 } dtv_t;
 
 
index 70a35198c2e0ca208c8490963c9d1529ef34d5e7..9c32c68681a8ad298c27c5c2f0ad4c73c256c6c5 100644 (file)
@@ -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.
index aa760e02523409c33f5301f7b701734af97ae161..fe4989d6efdf581e308def7e38911b9a518d434d 100644 (file)
@@ -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);
index 5cca127f91b41180bc01bb2d6374ddfc402cae58..3ae401f1f733f6db74e7dc832a8e472c08c94360 100644 (file)
@@ -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;
 
index d5c1cb9ae31222da91ed808621ab4631b7a3a3d8..23e20c3a82ad173347e98060b5f50d50d224bb77 100644 (file)
@@ -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
index 24b374b0dc8ae7555471e7aa43ccdcf9551306bd..866f7b2a5feb3a99f4e6c344b084fb67716a34a1 100644 (file)
@@ -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;
 
index 0e16cb8aeb6b5b21fd04898c67a4c0706b641c2d..ea4fb968dbd61d2fb6dd1bf02474c45e18d0cd50 100644 (file)
@@ -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);
index 2ea9e7f86230934787aa7d70f98b6054f59ce583..daddf2e164f28885992ab2fa925224b0dafcd72b 100644 (file)
@@ -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:
index a6817cf79ea40826c50d804251aa17924eb08b50..20f7bb062078a0e3f07c27481e0967dfc9d57e8a 100644 (file)
@@ -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");
 }
index c0a273241fc014cd46323e9431370d5341fa5164..0aea5eed2ae4bc9424751011c50987569edaddb4 100644 (file)
@@ -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");
 }
 
index 149283c65d81f1309fef489dc808f13c2a2bddb6..3af9e6681d0aded08365820d24b7d1b2e3868e5b 100644 (file)
@@ -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
index 4000b19b4d539a08c4b8c9493bd9cefa130d8aa2..3a173a6ca02d3e94ed4a60e7390728c40cf60851 100644 (file)
@@ -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},
index 62fd45db588f3123152dbd31e4aa5f0b613f3a8d..12b59f9de3d8571910216daa551509a6eb7b4188 100644 (file)
@@ -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
    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>
 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)
index 2199ebeb746068230bf06c3408108daba6871beb..70522ad2e5f23fe50cd226d839f6e74a2fc470d7 100644 (file)
@@ -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
    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>
 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)
index ba8fc74c90e8e58e8de2f7a2f3a8944dcda9e907..66996a93672a9ed478a4b13e20fb43aa8a0504ab 100644 (file)
@@ -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
    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>
 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)
index d6f60c02e7950a31d55db9c443101daf71e2ddc9..9ccfd7fc22ca934d95d4dbc57ad4ea34ffc54864 100644 (file)
@@ -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).  */
index 4ce4f8e41342c2fe7bf2087240bd16c5347363a2..0cc0c0d7b5dbb7eb98cefe7ac040cd894b8fda3c 100644 (file)
@@ -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;
     }
index 5de5bf725ac66f00400d9d82d6e03b449618ff97..1a5f7952c37486923fddee56f3d6bf428a55125c 100644 (file)
@@ -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);
 \f
 /* 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
 \f
-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;
-}
-\f
 /* 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;
 }
index f15cb575eb08654cc4768765279644fe4237a90e..c3295a851c202a3c6463e05afa4ca57d739a950a 100644 (file)
@@ -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)
index 23765c970edc717d3bee46a13b4a9608d154c8cc..f065cf449d42e7791027812fe003f87569b42bdf 100644 (file)
@@ -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,
index 1b21b699e92ced53f23608079b6bf7428ec29b56..636396e6f7aa6da099ac9922b99380c443b13830 100644 (file)
@@ -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);
index a724252d8c9724b37da948291d1a289d5f079c36..a8b6e4baa82085967a8c63bbdfb200ac27164fec 100644 (file)
@@ -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
index cb40421797bf2f8fb3e7151880d25f433006b4f9..a68bab2de980f492240f1ced5cc6d01df4a5b966 100644 (file)
@@ -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
       {
index 06c8ca7c2153b3602cb47fb0e0f565a141b996a7..744c10c50b646e015c94b7afb73fedfcf4b1a393 100644 (file)
@@ -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;
index 8b7767bd4a7e12ae2f03d193eecbe1cafe2a66d8..a1041ec1c22b555daf44f4d740f405559f2daf97 100644 (file)
@@ -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;
 }
index 01d22876ba08a49219c7161a40381beacf5026bb..2ed350a1ad62781b3ee053cdc701a611b3f5c1ba 100644 (file)
@@ -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;
index 6a0ee836a2751382e9fdf33dd23a4cf54856b7d2..bcb136e8c1f0e226f6b6ff30dc6165675d382b39 100644 (file)
@@ -1,5 +1,6 @@
 #include <assert.h>
 #include <stdio.h>
+#include <string.h>
 #include <sys/types.h>
 
 
index b766fb8656fd79efa7812a69d52b5bfc0d0f97d5..a0c0e71704c1b2ede1230cb8d11ab6d3247e5834 100644 (file)
@@ -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)))
index 2ab97b7d9033945a36b6d09da041d56cf73f39a4..b5d7436956af2b08a88d446aa1d668e5a34b0d1a 100644 (file)
@@ -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);
       }
index e1d60d7619cd8bf0a51be3d8d675bb2c2787ed96..4a1571e7dbdbaaf487cdfea2dece1a5cba903c34 100644 (file)
@@ -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
index d5369bda621503fd7654262d39c17cb2a39cada7..c3748d64d5be3c964df47d76cd6226a2813f4d9a 100644 (file)
@@ -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;
 }
index 16f6a34e7a36cf2ed98dff6fee9a2d39188c2b69..29ddfa6b75581bfb2e9bfa74e06b94dffbe71073 100644 (file)
@@ -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);
 
index fee83514d1a7d394b325c44879c782913b2f577d..acc0132603a8b809192440f785f65f44d9443320 100644 (file)
@@ -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)
index 4decfa4fd0bc36112193106c460a44ac6e2ae55e..873d39d52a232c30b18315605a899e6a4807910f 100644 (file)
@@ -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)
index cfbc63866b9d768b3d85ef177cafc66441be912f..d95e8844342b6e999c3eca708c7e368534b64492 100644 (file)
@@ -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 (file)
index 0000000..429faff
--- /dev/null
@@ -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
index 780a3a57fd36b72237869e01704051ca8525f917..4166e8c498a72702c4d3d07c36a36d4354cdd04e 100644 (file)
@@ -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 (file)
index 0000000..4235083
--- /dev/null
@@ -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
index 187bd42f33d0f64a82e8c9dd8f18301de80659be..87d40058c351007833bbf4c3ad17f4ccfd241299 100644 (file)
@@ -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))                                        \
index 434d5d931308a22e10c0221b75aff7c3f01f4f6a..a3b68e928f3a08f37f66bb2c4053ea844a64b067 100644 (file)
@@ -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
index 648976d7d25191ed0e657356d8b726f47245f024..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -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 (file)
index 0000000..648976d
--- /dev/null
@@ -0,0 +1,4 @@
+struct link_map_machine
+  {
+    Elf32_Addr plt; /* Address of .plt */
+  };
index 470b4d3e5fe06f16286f2ba035cd46a4aa9adc4c..6b4f811c25d9c2151eb8fd96b86fa0264442e193 100644 (file)
@@ -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 (file)
index 0000000..470b4d3
--- /dev/null
@@ -0,0 +1,4 @@
+struct link_map_machine
+  {
+    /* empty by default */
+  };
index 8156981e6e04b747e62236569f68005d1e6c4fee..d47fb7b6356deff918b325b4bd515917dcef4d8b 100644 (file)
@@ -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) *,
index f48cb0a844c799770a771e2412c879578c19d4f1..2b29989600679ed209c5cd303ee4c59e0f6ca327 100644 (file)
@@ -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
    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)
index 2282dda9cc35cc5477dc591f7995270c6fc061fa..099742ceff5468d8a247dfd2dfe653bccb9cf9ee 100644 (file)
@@ -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 (file)
index 0000000..3ca89f3
--- /dev/null
@@ -0,0 +1 @@
+#error "Architecture specific PLT trampolines must be defined."
index ec68e1a565781f7ae40a340d127d2d9abaceb3ef..08039e18cad7573b13bcb268cc8dffefb47e1b40 100644 (file)
@@ -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 */
index ad5ebe0911d866bc37c0e8a5e275e43627880a6d..5bb8a9b35297cc9bfa07c1fa5e2c346f544b1d5c 100644 (file)
@@ -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
@@ -183,6 +183,22 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
 #endif
             );
 
+#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]);
index b5ecc3643682ad0bc6a826bca0032cb48cfec146..b88ede06a203c9b6479f792e48b96709e32a65ab 100644 (file)
@@ -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.  */
 
similarity index 96%
rename from misc/syslog.c
rename to sysdeps/generic/syslog.c
index 6916356da717a0f58aa48db5dbac687452b6a8e2..9c8f422aad114d7f41fd60d0dc8966dc76732639 100644 (file)
@@ -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()
index eb77b260d875bf5b3f7992c522754e46be50e808..a7378b742f611d16709f61cb47c937de39139866 100644 (file)
@@ -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"                                                           \
index 3e37d6449c3b43be9378c861ee1e7949d600ce6c..c3d382fb95fc3e1c5e0788fcc29fb663fd432b27 100644 (file)
@@ -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;
 }
index 54842b22992276cd44165d5ac1668caff3423a09..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -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 (file)
index 0000000..54842b2
--- /dev/null
@@ -0,0 +1,6 @@
+/* Used to store the function descriptor table */
+struct link_map_machine
+  {
+    size_t fptr_table_len;
+    ElfW(Addr) *fptr_table;
+  };
index d393b3e4272b6429804be9ce28a07be3610dd486..84436e7c56a35e8b7839209df245a7b7f3ec09c6 100644 (file)
@@ -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))
-
index 52faaa31091b4bdafa4bc68f601e868f975dadd9..ece94f361098a761401339ec36f59eac9b776f76 100644 (file)
@@ -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
index 3be9b7eae814c16f42657fe84defc2f8ddb5cf30..985d040413cc99f3020964579b4f319d60e8ed66 100644 (file)
@@ -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 (file)
index 0000000..3be9b7e
--- /dev/null
@@ -0,0 +1,5 @@
+struct link_map_machine
+  {
+    Elf32_Addr plt; /* Address of .plt + 0x16 */
+    Elf32_Addr gotplt; /* Address of .got + 0x0c */
+  };
index c48d9d325eaa07577e5d4c62d7031a03180a2493..78c083f6ab834afd02ef54f4f8184e3f695f2595 100644 (file)
@@ -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 (file)
index 0000000..80dd300
--- /dev/null
@@ -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
index 7f8b0550d96882a5ffd0b32825bed19cbacff4ed..f751c23fd1e300e5e486c05a126b79dbb499f63a 100644 (file)
@@ -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 (file)
index 0000000..7f8b055
--- /dev/null
@@ -0,0 +1,5 @@
+struct link_map_machine
+  {
+    size_t fptr_table_len;
+    Elf64_Addr *fptr_table;
+  };
index 0ae3dd68baf6b25c09a70d4f3e0474450cd503a6..b50030ebd2c4f4770d488257242e7c127cb1b760 100644 (file)
@@ -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
    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))
index 310804786951acf3d8a251b2c3a5dfe75fef172b..55349690e316d05bbbab9c8c06ceb7ab4c48f819 100644 (file)
@@ -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 (file)
index 0000000..b7969a6
--- /dev/null
@@ -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 (file)
index 41254ae..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/* Not needed. */
index f1df4cd12ee9e9de0d87393ccfe61dbd37c7a739..3a6b8e5532ff119272c1b22d9d532bc821c45f6b 100644 (file)
@@ -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 (file)
index 0000000..470b4d3
--- /dev/null
@@ -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 (file)
index 0000000..9d0a945
--- /dev/null
@@ -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
index 146c5866a9eedac2570cd4da08294cced01e2102..89d7106365693d7b53a9340b472e39ba62f7808a 100644 (file)
@@ -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 (file)
index 0000000..8791280
--- /dev/null
@@ -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
index bc15b4dab674883f1871b8febf5f636ce7368a4e..cce42ef37426f3595330c297ef4a62412317479c 100644 (file)
@@ -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>
 
 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 (file)
index 0000000..7f44087
--- /dev/null
@@ -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
index 06960716b9de210cfea3d1f46fdcc36b3df56e71..4120a0238214123e293c23fb3e40b4e8d6c8a9c5 100644 (file)
@@ -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;
index a8c1e3e4907d5b1eb9038f115868190477250b68..de3b9e923ab1bd4204e4c1952c6d024061ade83e 100644 (file)
@@ -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 (file)
index 0000000..ea5ce7b
--- /dev/null
@@ -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 (file)
index 0000000..8633362
--- /dev/null
@@ -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
index e50294101516805ce6947eae271d1e770fd6c740..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -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
index 3fcf77df71bce47a640407940f89df4920bc6f85..5ddc22e3c9c31c386bc3fc73ee97b621fce7ff49 100644 (file)
@@ -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 (file)
index 0000000..316f17a
--- /dev/null
@@ -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 (file)
index 0000000..99a0ffc
--- /dev/null
@@ -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;                                                                   \
+    })
index fc1fba363a59ada42f52ff8e6b0e0a1a0c221ee0..70f004382054139ee0a69d4c5d04d1d8be1339e1 100644 (file)
-#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 (file)
index 0000000..fc1fba3
--- /dev/null
@@ -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
index 7134827eb025a7de55d0c66f9f99c5d272a92c2d..d83df39bb20c5809bb54bbb6c0df0ff9137b8bf4 100644 (file)
@@ -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;
 }
index 52922a813b65c7e36893ae473a424d5dcdade8c2..8bbf858fbf092446433ea9e0613f72a628e4eebb 100644 (file)
@@ -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 (file)
index 0000000..4ee2295
--- /dev/null
@@ -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
+
index 82ece0be0f9f2079d4b1298cccc80b85a5183537..5026a2edad9981d56cd27a5dc7fef630f2d1f739 100644 (file)
@@ -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 (file)
index 0000000..215d869
--- /dev/null
@@ -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
index bb2fbb5f1613a15056a9a849664b5d1a69b6de0e..2826677336507855900791740a07365d05a0fe6e 100644 (file)
@@ -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 (file)
index 0000000..bb2fbb5
--- /dev/null
@@ -0,0 +1,5 @@
+struct link_map_machine
+  {
+    Elf32_Addr plt; /* Address of .plt + 36 */
+    Elf32_Addr gotplt; /* Address of .got + 0x0c */
+  };
index 271666a2a3b730fa03fcc8fe3b2583bc27e0e580..b66b4f0e428c264e24c3bf983e529722d99c199b 100644 (file)
@@ -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 (file)
index 0000000..79493d5
--- /dev/null
@@ -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 (file)
index 0000000..8cc1c7b
--- /dev/null
@@ -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 (file)
index ec9f6f7..0000000
+++ /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 (file)
index 0000000..f952985
--- /dev/null
@@ -0,0 +1,2 @@
+#define HAVE_FPU
+#include <sysdeps/sh/dl-trampoline.S>
index 6056cbeef2784e5831b5b1a2561eef94b0331779..3bc872add84c5a44eeabd95dff542045172571bc 100644 (file)
@@ -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)
 
index 9f3724fc6af61c712a26436377e980210ae502a3..051e93595e6dcab4783db01d0879ef67eef0f04c 100644 (file)
@@ -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);
index 9d39176f6bbae72b1ed4808d9fbd6c8de8589be7..6d9b79f2c3f6415ececa596989bf308dd23b5b5c 100644 (file)
@@ -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);
 }
index 6ef9679045a3019e152087763b5fe6d9337ef80d..b38d0c4238ea9ad15d26e16e41d4e8d833c087c6 100644 (file)
@@ -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)
index f43f568ec141239bb32df4dc12a4dbf2c8043324..0c4be2b67ff8ec15b83a94ca137f1036d918a65a 100644 (file)
@@ -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)
index af75d4c51ab7e9adc6b457d16f7c635d8388068e..6bea9d20440b67d22ab4feb5133d93688a2cd05f 100644 (file)
@@ -1,5 +1,5 @@
-/* Copyright (C) 1992,1993,1995-2000,2002,2003,2004
-   Free Software Foundation, Inc.
+/* Copyright (C) 1992,1993,1995,1996,1997,1998,1999,2000,2002,2003,2004,2005
+       Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper, <drepper@gnu.org>, August 1995.
 
@@ -154,9 +154,17 @@ __i686.get_pc_thunk.reg:                                                 \
   movl SYSCALL_ERROR_ERRNO@GOTNTPOFF(%ecx), %ecx;                            \
   xorl %edx, %edx;                                                           \
   subl %eax, %edx;                                                           \
-  movl %edx, %gs:0(%ecx);                                                    \
+  SYSCALL_ERROR_HANDLER_TLS_STORE (%edx, %ecx);                                      \
   orl $-1, %eax;                                                             \
   jmp L(pseudo_end);
+#   ifndef NO_TLS_DIRECT_SEG_REFS
+#    define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff)                    \
+  movl src, %gs:(destoff)
+#   else
+#    define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff)                    \
+  addl %gs:0, destoff;                                                       \
+  movl src, (destoff)
+#   endif
 #  else
 #   define SYSCALL_ERROR_HANDLER                                             \
 0:pushl %ebx;                                                                \
@@ -532,6 +540,29 @@ asm (".L__X'%ebx = 1\n\t"
 # define EXTRAVAR_5
 #endif
 
+/* Consistency check for position-independent code.  */
+#ifdef __PIC__
+# define check_consistency()                                                 \
+  ({ int __res;                                                                      \
+     __asm__ __volatile__                                                    \
+       ("call __i686.get_pc_thunk.cx;"                                       \
+       "addl $_GLOBAL_OFFSET_TABLE_, %%ecx;"                                 \
+       "subl %%ebx, %%ecx;"                                                  \
+       "je 1f;"                                                              \
+       "ud2;"                                                                \
+       "1:\n"                                                                \
+       ".section .gnu.linkonce.t.__i686.get_pc_thunk.cx,\"ax\",@progbits;"   \
+       ".globl __i686.get_pc_thunk.cx;"                                      \
+       ".hidden __i686.get_pc_thunk.cx;"                                     \
+       ".type __i686.get_pc_thunk.cx,@function;"                             \
+       "__i686.get_pc_thunk.cx:"                                             \
+       "movl (%%esp), %%ecx;"                                                \
+       "ret;"                                                                \
+       ".previous"                                                           \
+       : "=c" (__res));                                                      \
+     __res; })
+#endif
+
 #endif /* __ASSEMBLER__ */
 
 #endif /* linux/i386/sysdep.h */
index 7f0b963cb74c8dc67b0d0088219633944c6626f6..b061a848c6182419c8c99ff89f4ce5131fd37ebb 100644 (file)
@@ -40,7 +40,6 @@ char **__libc_argv attribute_hidden;
 
 
 void
-attribute_hidden
 __libc_init_first (int argc, char **argv, char **envp)
 {
 #ifdef SHARED
index f499a712c4bc8448d57fb7ebaf501201cffe73ac..83ebe0cf74c3bd9e2795cb74af03cc6f45684850 100644 (file)
@@ -1,6 +1,6 @@
 /* Set flags signalling availability of kernel features based on given
    kernel version number.
-   Copyright (C) 1999-2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1999-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
 # define __ASSUME_SIOCGIFNAME          1
 #endif
 
+/* MSG_NOSIGNAL was at least available with Linux 2.2.0.  */
+#if __LINUX_KERNEL_VERSION >= 131584
+# define __ASSUME_MSG_NOSIGNAL         1
+#endif
+
 /* On x86 another `getrlimit' syscall was added in 2.3.25.  */
 #if __LINUX_KERNEL_VERSION >= 131865 && defined __i386__
 # define __ASSUME_NEW_GETRLIMIT_SYSCALL        1
index 6514f442a6effc8cdc8476a1a320daa731e5361f..7eaaad20a437a42c59ef94d5fcaed4fad161c7ce 100644 (file)
@@ -1,5 +1,5 @@
 /* Switch to context.
-   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 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
@@ -47,7 +47,7 @@ ENTRY(__novec_setcontext)
  * of a procedure call (makecontext), so we don't need to restore
  * msr and ctr.  We don't restore r13 since it will be used as
  * the TLS pointer.  */
-  lwz    r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
+  l    r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
   cmpdi r0,0
   bne    L(nv_do_sigret)
 
@@ -104,7 +104,7 @@ ENTRY(__novec_setcontext)
   ld   r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
   ld   r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
   ld   r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
-  mfcr r0
+  mtcr r0
   ld   r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
   ld   r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
   ld   r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
@@ -213,7 +213,7 @@ ENTRY(__setcontext)
  * of a procedure call (makecontext), so we don't need to restore
  * msr and ctr.  We don't restore r13 since it will be used as
  * the TLS pointer.  */
-  lwz    r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
+  l    r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
   cmpdi r0,0
   bne    L(do_sigret)
 
@@ -380,11 +380,11 @@ L(has_no_vec):
   ld   r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
   ld   r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
   ld   r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
-  mfcr r0
   ld   r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
   ld   r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
   ld   r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
   ld   r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
+  mtcr r0
   ld   r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
   ld   r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
   ld   r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
index f99df951a2643beae2ca917a2703ce3a71b71338..772adacfe4de1e836bc9aee01644d2dd3b7e3103 100644 (file)
@@ -1,5 +1,5 @@
 /* Save current context and install the given one.
-   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 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
@@ -150,7 +150,7 @@ ENTRY(__novec_swapcontext)
  * of a procedure call (makecontext), so we don't need to restore
  * msr and ctr.  We don't restore r13 since it will be used as
  * the TLS pointer.  */
-  lwz    r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
+  l    r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
   cmpdi r0,0
   bne    L(nv_do_sigret)
 
@@ -199,7 +199,7 @@ ENTRY(__novec_swapcontext)
   ld   r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
   ld   r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
   ld   r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
-  mfcr r0
+  mtcr r0
   ld   r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
   ld   r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
   ld   r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
@@ -521,7 +521,7 @@ L(has_no_vec):
  * of a procedure call (makecontext), so we don't need to restore
  * msr and ctr.  We don't restore r13 since it will be used as
  * the TLS pointer.  */
-  lwz    r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
+  l    r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
   cmpdi r0,0
   bne    L(do_sigret)
 
@@ -681,11 +681,11 @@ L(has_no_vec2):
   ld   r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
   ld   r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
   ld   r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
-  mfcr r0
   ld   r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
   ld   r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
   ld   r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
   ld   r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
+  mtcr r0
   ld   r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
   ld   r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
   ld   r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
diff --git a/sysdeps/unix/sysv/linux/syslog.c b/sysdeps/unix/sysv/linux/syslog.c
new file mode 100644 (file)
index 0000000..eaaa983
--- /dev/null
@@ -0,0 +1,10 @@
+#include "kernel-features.h"
+
+#if __ASSUME_MSG_NOSIGNAL
+# define NO_SIGPIPE
+# define send_flags MSG_NOSIGNAL
+#else
+# define send_flags 0
+#endif
+
+#include <sysdeps/generic/syslog.c>
index 8ea7157156a518a06d49c8a0cf9ec62cb9579a68..2890c2d88d36773a7ab376d2d7ecb5d1432786af 100644 (file)
-#if __WORDSIZE == 64
-struct link_map_machine
-  {
-    Elf64_Addr plt; /* Address of .plt + 0x16 */
-    Elf64_Addr gotplt; /* Address of .got + 0x18 */
-  };
+/* 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 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
 
 #else
-struct link_map_machine
-  {
-    Elf32_Addr plt; /* Address of .plt + 0x16 */
-    Elf32_Addr gotplt; /* Address of .got + 0x0c */
-  };
+
+/* Registers for entry into PLT on x86-64.  */
+# if __GNUC_PREREQ (4,0)
+typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
+# else
+typedef float La_x86_64_xmm __attribute__ ((__mode__ (__V4SF__)));
+# endif
+
+typedef struct La_x86_64_regs
+{
+  uint64_t lr_rdx;
+  uint64_t lr_r8;
+  uint64_t lr_r9;
+  uint64_t lr_rcx;
+  uint64_t lr_rsi;
+  uint64_t lr_rdi;
+  uint64_t lr_rbp;
+  uint64_t lr_rsp;
+  La_x86_64_xmm lr_xmm[8];
+} La_x86_64_regs;
+
+/* Return values for calls from PLT on x86-64.  */
+typedef struct La_x86_64_retval
+{
+  uint64_t lrv_rax;
+  uint64_t lrv_rdx;
+  La_x86_64_xmm lrv_xmm0;
+  La_x86_64_xmm lrv_xmm1;
+  long double lrv_st0;
+  long double lrv_st1;
+} La_x86_64_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf64_Addr la_x86_64_gnu_pltenter (Elf64_Sym *__sym,
+                                         unsigned int __ndx,
+                                         uintptr_t *__refcook,
+                                         uintptr_t *__defcook,
+                                         La_x86_64_regs *__regs,
+                                         unsigned int *__flags,
+                                         const char *__symname,
+                                         long int *__framesizep);
+extern unsigned int la_x86_64_gnu_pltexit (Elf64_Sym *__sym,
+                                          unsigned int __ndx,
+                                          uintptr_t *__refcook,
+                                          uintptr_t *__defcook,
+                                          const La_x86_64_regs *__inregs,
+                                          La_x86_64_retval *__outregs,
+                                          const char *symname);
+
+__END_DECLS
+
 #endif
diff --git a/sysdeps/x86_64/bits/linkmap.h b/sysdeps/x86_64/bits/linkmap.h
new file mode 100644 (file)
index 0000000..8ea7157
--- /dev/null
@@ -0,0 +1,14 @@
+#if __WORDSIZE == 64
+struct link_map_machine
+  {
+    Elf64_Addr plt; /* Address of .plt + 0x16 */
+    Elf64_Addr gotplt; /* Address of .got + 0x18 */
+  };
+
+#else
+struct link_map_machine
+  {
+    Elf32_Addr plt; /* Address of .plt + 0x16 */
+    Elf32_Addr gotplt; /* Address of .got + 0x0c */
+  };
+#endif
index b932f51d1552a03a3a160bba7097b41d702938e8..bb0c77fd0b3f3eda2a647d6fbc47b207089bed5a 100644 (file)
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  x86-64 version.
-   Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Andreas Jaeger <aj@suse.de>.
 
@@ -116,7 +116,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;
@@ -130,128 +131,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.  */
-#ifndef PROF
-# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\
-       .text\n\
-       .globl _dl_runtime_resolve\n\
-       .type _dl_runtime_resolve, @function\n\
-       .align 16\n\
-       " CFI_STARTPROC "\n\
-_dl_runtime_resolve:\n\
-       subq $56,%rsp\n\
-       " CFI_ADJUST_CFA_OFFSET(72)" # Incorporate PLT\n\
-       movq %rax,(%rsp)        # Preserve registers otherwise clobbered.\n\
-       movq %rcx,8(%rsp)\n\
-       movq %rdx,16(%rsp)\n\
-       movq %rsi,24(%rsp)\n\
-       movq %rdi,32(%rsp)\n\
-       movq %r8,40(%rsp)\n\
-       movq %r9,48(%rsp)\n\
-       movq 64(%rsp), %rsi     # Copy args pushed by PLT in register.\n\
-       movq %rsi,%r11          # Multiply by 24\n\
-       addq %r11,%rsi\n\
-       addq %r11,%rsi\n\
-       shlq $3, %rsi\n\
-       movq 56(%rsp), %rdi     # %rdi: link_map, %rsi: reloc_offset\n\
-       call fixup              # Call resolver.\n\
-       movq %rax, %r11         # Save return value\n\
-       movq 48(%rsp),%r9       # Get register content back.\n\
-       movq 40(%rsp),%r8\n\
-       movq 32(%rsp),%rdi\n\
-       movq 24(%rsp),%rsi\n\
-       movq 16(%rsp),%rdx\n\
-       movq 8(%rsp),%rcx\n\
-       movq (%rsp),%rax\n\
-       addq $72,%rsp           # Adjust stack(PLT did 2 pushes)\n\
-       " CFI_ADJUST_CFA_OFFSET(-72)" \n\
-       jmp *%r11               # 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\
-       .align 16\n\
-       " CFI_STARTPROC "\n\
-_dl_runtime_profile:\n\
-       subq $56,%rsp\n\
-       " CFI_ADJUST_CFA_OFFSET(72)" # Incorporate PLT\n\
-       movq %rax,(%rsp)        # Preserve registers otherwise clobbered.\n\
-       movq %rcx,8(%rsp)\n\
-       movq %rdx,16(%rsp)\n\
-       movq %rsi,24(%rsp)\n\
-       movq %rdi,32(%rsp)\n\
-       movq %r8,40(%rsp)\n\
-       movq %r9,48(%rsp)\n\
-       movq 72(%rsp), %rdx     # Load return address if needed\n\
-       movq 64(%rsp), %rsi     # Copy args pushed by PLT in register.\n\
-       movq %rsi,%r11          # Multiply by 24\n\
-       addq %r11,%rsi\n\
-       addq %r11,%rsi\n\
-       shlq $3, %rsi\n\
-       movq 56(%rsp), %rdi     # %rdi: link_map, %rsi: reloc_offset\n\
-       call profile_fixup      # Call resolver.\n\
-       movq %rax, %r11         # Save return value\n\
-       movq 48(%rsp),%r9       # Get register content back.\n\
-       movq 40(%rsp),%r8\n\
-       movq 32(%rsp),%rdi\n\
-       movq 24(%rsp),%rsi\n\
-       movq 16(%rsp),%rdx\n\
-       movq 8(%rsp),%rcx\n\
-       movq (%rsp),%rax\n\
-       addq $72,%rsp           # Adjust stack\n\
-       " CFI_ADJUST_CFA_OFFSET(-72)"\n\
-       jmp *%r11               # 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\
-       .align 16\n\
-       " CFI_STARTPROC "\n\
-_dl_runtime_resolve:\n\
-_dl_runtime_profile:\n\
-       subq $56,%rsp\n\
-       " CFI_ADJUST_CFA_OFFSET(72)" # Incorporate PLT\n\
-       movq %rax,(%rsp)        # Preserve registers otherwise clobbered.\n\
-       movq %rcx,8(%rsp)\n\
-       movq %rdx,16(%rsp)\n\
-       movq %rsi,24(%rsp)\n\
-       movq %rdi,32(%rsp)\n\
-       movq %r8,40(%rsp)\n\
-       movq %r9,48(%rsp)\n\
-       movq 64(%rsp), %rsi     # Copy args pushed by PLT in register.\n\
-       movq %rsi,%r11          # Multiply by 24\n\
-       addq %r11,%rsi\n\
-       addq %r11,%rsi\n\
-       shlq $3, %rsi\n\
-       movq 56(%rsp), %rdi     # %rdi: link_map, %rsi: reloc_offset\n\
-       call fixup              # Call resolver.\n\
-       movq %rax, %r11         # Save return value\n\
-       movq 48(%rsp),%r9       # Get register content back.\n\
-       movq 40(%rsp),%r8\n\
-       movq 32(%rsp),%rdi\n\
-       movq 24(%rsp),%rsi\n\
-       movq 16(%rsp),%rdx\n\
-       movq 8(%rsp),%rcx\n\
-       movq (%rsp),%rax\n\
-       addq $72,%rsp           # Adjust stack\n\
-       " CFI_ADJUST_CFA_OFFSET(-72)"\n\
-       jmp *%r11               # 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
-
 /* 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.  */
@@ -280,16 +159,24 @@ _dl_start_user:\n\
        # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env)\n\
        # argc -> rsi\n\
        movq %rdx, %rsi\n\
+       # Save %rsp value in %r13.\n\
+       movq %rsp, %r13\n\
+       # And align stack for the _dl_init_internal call. \n\
+       andq $-16, %rsp\n\
        # _dl_loaded -> rdi\n\
        movq _rtld_local(%rip), %rdi\n\
        # env -> rcx\n\
-       leaq 16(%rsp,%rdx,8), %rcx\n\
+       leaq 16(%r13,%rdx,8), %rcx\n\
        # argv -> rdx\n\
-       leaq 8(%rsp), %rdx\n\
+       leaq 8(%r13), %rdx\n\
+       # Clear %rbp to mark outermost frame obviously even for constructors.\n\
+       xorq %rbp, %rbp\n\
        # Call the function to run the initializers.\n\
        call _dl_init_internal@PLT\n\
        # Pass our finalizer function to the user in %rdx, as per ELF ABI.\n\
        leaq _dl_fini(%rip), %rdx\n\
+       # And make sure %rsp points to argc stored on the stack.\n\
+       movq %r13, %rsp\n\
        # Jump to the user's entry point.\n\
        jmp *%r12\n\
 .previous\n\
@@ -348,9 +235,14 @@ 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 x86_64_gnu_pltenter
+#define ARCH_LA_PLTEXIT x86_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.  */
@@ -390,18 +282,9 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
 #ifndef RTLD_BOOTSTRAP
       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
                          : (Elf64_Addr) sym_map->l_addr + sym->st_value);
-#else
-      Elf64_Addr value = RESOLVE (&sym, version, r_type);
-
-# ifndef RTLD_BOOTSTRAP
-      if (sym != NULL)
-# endif
-       value += sym->st_value;
-#endif
 
 #if defined RTLD_BOOTSTRAP && !USE___THREAD
       assert (r_type == R_X86_64_GLOB_DAT || r_type == R_X86_64_JUMP_SLOT);
@@ -553,4 +436,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/x86_64/dl-trampoline.S b/sysdeps/x86_64/dl-trampoline.S
new file mode 100644 (file)
index 0000000..eb46f29
--- /dev/null
@@ -0,0 +1,188 @@
+/* PLT trampolines.  x86-64 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
+       .align 16
+       cfi_startproc
+_dl_runtime_resolve:
+       subq $56,%rsp
+       cfi_adjust_cfa_offset(72) # Incorporate PLT
+       movq %rax,(%rsp)        # Preserve registers otherwise clobbered.
+       movq %rcx, 8(%rsp)
+       movq %rdx, 16(%rsp)
+       movq %rsi, 24(%rsp)
+       movq %rdi, 32(%rsp)
+       movq %r8, 40(%rsp)
+       movq %r9, 48(%rsp)
+       movq 64(%rsp), %rsi     # Copy args pushed by PLT in register.
+       movq %rsi, %r11         # Multiply by 24
+       addq %r11, %rsi
+       addq %r11, %rsi
+       shlq $3, %rsi
+       movq 56(%rsp), %rdi     # %rdi: link_map, %rsi: reloc_offset
+       call _dl_fixup          # Call resolver.
+       movq %rax, %r11         # Save return value
+       movq 48(%rsp), %r9      # Get register content back.
+       movq 40(%rsp), %r8
+       movq 32(%rsp), %rdi
+       movq 24(%rsp), %rsi
+       movq 16(%rsp), %rdx
+       movq 8(%rsp), %rcx
+       movq (%rsp), %rax
+       addq $72, %rsp          # Adjust stack(PLT did 2 pushes)
+       cfi_adjust_cfa_offset(-72)
+       jmp *%r11               # Jump to function address.
+       cfi_endproc
+       .size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+
+
+       .globl _dl_runtime_profile
+       .type _dl_runtime_profile, @function
+       .align 16
+       cfi_startproc
+_dl_runtime_profile:
+       subq $80, %rsp
+       cfi_adjust_cfa_offset(96) # Incorporate PLT
+       movq %rax, (%rsp)       # Preserve registers otherwise clobbered.
+       movq %rdx, 8(%rsp)
+       movq %r8, 16(%rsp)
+       movq %r9, 24(%rsp)
+       movq %rcx, 32(%rsp)
+       movq %rsi, 40(%rsp)
+       movq %rdi, 48(%rsp)
+       movq %rbp, 56(%rsp)     # Information for auditors.
+       leaq 96(%rsp), %rax
+       movq %rax, 64(%rsp)
+       leaq 8(%rsp), %rcx
+       movq 96(%rsp), %rdx     # Load return address if needed
+       movq 88(%rsp), %rsi     # Copy args pushed by PLT in register.
+       movq %rsi,%r11          # Multiply by 24
+       addq %r11,%rsi
+       addq %r11,%rsi
+       shlq $3, %rsi
+       movq 80(%rsp), %rdi     # %rdi: link_map, %rsi: reloc_offset
+       leaq 72(%rsp), %r8
+       call _dl_profile_fixup  # Call resolver.
+       movq %rax, %r11         # Save return value
+       movq 8(%rsp), %rdx      # Get back register content.
+       movq 16(%rsp), %r8
+       movq 24(%rsp), %r9
+       movq (%rsp),%rax
+       movq 72(%rsp), %r10
+       testq %r10, %r10
+       jns 1f
+       movq 32(%rsp), %rcx
+       movq 40(%rsp), %rsi
+       movq 48(%rsp), %rdi
+       addq $96,%rsp           # Adjust stack
+       cfi_adjust_cfa_offset (-96)
+       jmp *%r11               # Jump to function address.
+
+       /*
+           +96     return address
+           +88     PLT2
+           +80     PLT1
+           +72     free
+           +64     %rsp
+           +56     %rbp
+           +48     %rdi
+           +40     %rsi
+           +32     %rcx
+           +24     %r9
+           +16     %r8
+           +8      %rdx
+          %esp     %rax
+       */
+       cfi_adjust_cfa_offset (96)
+1:     movq %rbx, 72(%rsp)
+       cfi_rel_offset (1, 72)
+       leaq 104(%rsp), %rsi
+       movq %rsp, %rbx
+       cfi_def_cfa_register (1)
+       subq %r10, %rsp
+       movq %rsp, %rdi
+       movq %r10, %rcx
+       shrq $3, %rcx
+       rep
+       movsq
+       andq $0xfffffffffffffff0, %rsp
+       movq 32(%rbx), %rcx
+       movq 40(%rbx), %rsi
+       movq 48(%rbx), %rdi
+       call *%r11
+       movq %rbx, %rsp
+       cfi_def_cfa_register (7)
+       subq $72, %rsp
+       cfi_adjust_cfa_offset (72)
+       movq %rsp, %rcx
+       movq %rax, (%rcx)
+       movq %rdx, 8(%rcx)
+       /* Even though the stack is correctly aligned to allow using movaps
+          we use movups.  Some callers might provide an incorrectly aligned
+          stack and we do not want to have it blow up here.  */
+       movups %xmm0, 16(%rcx)
+       movups %xmm1, 32(%rcx)
+       fstpt 48(%rcx)
+       fstpt 64(%rcx)
+       /*
+           +168    return address
+           +160    PLT2
+           +152    PLT1
+           +144    free
+           +136    %rsp
+           +128    %rbp
+           +120    %rdi
+           +112    %rsi
+           +104    %rcx
+           +96     %r9
+           +88     %r8
+           +80     %rdx
+           +64     %st1 result
+           +48     %st result
+           +32     %xmm1 result
+           +16     %xmm0 result
+           +8      %rdx result
+          %esp     %rax result
+       */
+       leaq 80(%rsp), %rdx
+       movq 144(%rsp), %rbx
+       cfi_restore (1)
+       movq 160(%rsp), %rsi    # Copy args pushed by PLT in register.
+       movq %rsi,%r11          # Multiply by 24
+       addq %r11,%rsi
+       addq %r11,%rsi
+       shlq $3, %rsi
+       movq 152(%rsp), %rdi    # %rdi: link_map, %rsi: reloc_offset
+       call _dl_call_pltexit
+       movq (%rsp), %rax
+       movq 8(%rsp), %rdx
+       movups 16(%rsp), %xmm0
+       movups 32(%rsp), %xmm1
+       fldt 64(%rsp)
+       fldt 48(%rsp)
+       addq $168, %rsp
+       cfi_adjust_cfa_offset (-168)
+       retq
+       cfi_endproc
+       .size _dl_runtime_profile, .-_dl_runtime_profile
index df98099f0a45eb991db8cec86172147370d43ee7..01c4f8282a8b6bab9280e4e05c86d0e24206a125 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 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
@@ -539,10 +539,12 @@ __strptime_internal (rp, fmt, tm, decided, era_cnt LOCALE_PARAM)
            }
 #endif
          if (!match_string (HERE_AM_STR, rp))
-           if (match_string (HERE_PM_STR, rp))
-             is_pm = 1;
-           else
-             return NULL;
+           {
+             if (match_string (HERE_PM_STR, rp))
+               is_pm = 1;
+             else
+               return NULL;
+           }
          break;
        case 'r':
 #ifdef _NL_CURRENT
index a0b2ebedd2a29f7a8f2d21b4973c23453a7ec3a2..6356aa0d41d1dd4a00bbcfaa209b8f70390d409e 100644 (file)
@@ -42,6 +42,10 @@ static const struct
   { "C", "19990502123412", "%Y%m%d%H%M%S", 0, 121, 4, 2 },
   { "C", "2001 20 Mon", "%Y %U %a", 1, 140, 4, 21 },
   { "C", "2001 21 Mon", "%Y %W %a", 1, 140, 4, 21 },
+  { "ja_JP.EUC-JP", "2000-01-01 08:12:21 AM", "%Y-%m-%d %I:%M:%S %p",
+    6, 0, 0, 1 },
+  { "en_US.ISO-8859-1", "2000-01-01 08:12:21 PM", "%Y-%m-%d %I:%M:%S %p",
+    6, 0, 0, 1 },
   { "ja_JP.EUC-JP", "2001 20 \xb7\xee", "%Y %U %a", 1, 140, 4, 21 },
   { "ja_JP.EUC-JP", "2001 21 \xb7\xee", "%Y %W %a", 1, 140, 4, 21 },
 };
@@ -73,7 +77,14 @@ test_tm (void)
     {
       memset (&tm, '\0', sizeof (tm));
 
-      if (*strptime (tm_tests[i].input, tm_tests[i].format, &tm) != '\0')
+      char *ret = strptime (tm_tests[i].input, tm_tests[i].format, &tm);
+      if (ret == NULL)
+       {
+         printf ("strptime returned NULL for `%s'\n", tm_tests[i].input);
+         result = 1;
+         continue;
+       }
+      else if (*ret != '\0')
        {
          printf ("not all of `%s' read\n", tm_tests[i].input);
          result = 1;
@@ -127,7 +138,14 @@ main (int argc, char *argv[])
          exit (EXIT_FAILURE);
        }
 
-      if (*strptime (day_tests[i].input, day_tests[i].format, &tm) != '\0')
+      char *ret = strptime (day_tests[i].input, day_tests[i].format, &tm);
+      if (ret == NULL)
+       {
+         printf ("strptime returned NULL for `%s'\n", day_tests[i].input);
+         result = 1;
+         continue;
+       }
+      else if (*ret != '\0')
        {
          printf ("not all of `%s' read\n", day_tests[i].input);
          result = 1;
index 3c2c1a1868e6d666d49f645238e181732ab78428..32e6e3c45f4d25e9dd91b3cf8d977b805f09a59c 100644 (file)
@@ -1,4 +1,4 @@
-# @(#)asia     7.77
+# @(#)asia     7.78
 
 # This data is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
@@ -639,7 +639,7 @@ Rule        Zion    1988    only    -       Apr      9      0:00    1:00    D
 Rule   Zion    1988    only    -       Sep      3      0:00    0       S
 
 # From Ephraim Silverberg <ephraim@cs.huji.ac.il>
-# (1997-03-04, 1998-03-16, 1998-12-28, 2000-01-17 and 2000-07-25):
+# (1997-03-04, 1998-03-16, 1998-12-28, 2000-01-17, 2000-07-25, and 2004-12-22):
 
 # According to the Office of the Secretary General of the Ministry of
 # Interior, there is NO set rule for Daylight-Savings/Standard time changes.
@@ -690,13 +690,13 @@ Rule      Zion    1995    only    -       Sep      3      0:00    0       S
 # time, Haim Ramon.  The official announcement regarding 1996-1998
 # (with the dates for 1997-1998 no longer being relevant) can be viewed at:
 #
-#   ftp://ftp.huji.ac.il/pub/tz/announcements/1996-1998.ramon.ps.gz
+#   ftp://ftp.cs.huji.ac.il/pub/tz/announcements/1996-1998.ramon.ps.gz
 #
 # The dates for 1997-1998 were altered by his successor, Rabbi Eli Suissa.
 #
 # The official announcements for the years 1997-1999 can be viewed at:
 #
-#   ftp://ftp.huji.ac.il/pub/tz/announcements/YYYY.ps.gz
+#   ftp://ftp.cs.huji.ac.il/pub/tz/announcements/YYYY.ps.gz
 #
 #       where YYYY is the relevant year.
 
@@ -716,12 +716,12 @@ Rule      Zion    1999    only    -       Sep      3      2:00    0       S
 #
 # The official announcement for the start date of 2000 can be viewed at:
 #
-#      ftp://ftp.huji.ac.il/pub/tz/announcements/2000-start.ps.gz
+#      ftp://ftp.cs.huji.ac.il/pub/tz/announcements/2000-start.ps.gz
 #
 # The official announcement for the end date of 2000 and the dates
 # for the years 2001-2004 can be viewed at:
 #
-#      ftp://ftp.huji.ac.il/pub/tz/announcements/2000-2004.ps.gz
+#      ftp://ftp.cs.huji.ac.il/pub/tz/announcements/2000-2004.ps.gz
 
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Zion    2000    only    -       Apr     14      2:00    1:00    D
@@ -735,52 +735,97 @@ Rule      Zion    2003    only    -       Oct      3      1:00    0       S
 Rule   Zion    2004    only    -       Apr      7      1:00    1:00    D
 Rule   Zion    2004    only    -       Sep     22      1:00    0       S
 
-# From Paul Eggert (2000-07-25):
-# Here are guesses for rules after 2004.
-# They are probably wrong, but they are more likely than no DST at all.
+# Yesterday, the Knesset Interior Committee passed a proposed (originally
+# in March 2004) change to the Time Setting Law that would make the dates
+# for DST from 2005 and beyond so that DST starts on the night _after_ the
+# first night of the Passover holiday at midnight until midnight of the
+# Saturday night _before_ the fast of Yom Kippur.
+#
+# Those who can read Hebrew can view the proposal at:
+#
+#      ftp://ftp.cs.huji.ac.il/pub/tz/announcements/2005+.ps
+#
+# The proposal still has to be passed by the Knesset (three readings) for
+# it to become law....
+
+# From Paul Eggert (2004-12-22):
+# For now, guess that the rules proposed on 2004-12-20 will be adopted.
+# This is quite possibly wrong, but it is more likely than no DST at all.
+# I used Ed Reingold's cal-hebrew in GNU Emacs 21.3, along with code
+# written by Ephraim Silverberg, to generate this list.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule   Zion    2005    max     -       Apr      1      1:00    1:00    D
-Rule   Zion    2005    max     -       Oct      1      1:00    0       S
+Rule   Zion    2005    only    -       Apr     25      0:00    1:00    D
+Rule   Zion    2005    only    -       Oct      9      0:00    0       S
+Rule   Zion    2006    only    -       Apr     14      0:00    1:00    D
+Rule   Zion    2006    only    -       Oct      1      0:00    0       S
+Rule   Zion    2007    only    -       Apr      4      0:00    1:00    D
+Rule   Zion    2007    only    -       Sep     16      0:00    0       S
+Rule   Zion    2008    only    -       Apr     21      0:00    1:00    D
+Rule   Zion    2008    only    -       Oct      5      0:00    0       S
+Rule   Zion    2009    only    -       Apr     10      0:00    1:00    D
+Rule   Zion    2009    only    -       Sep     27      0:00    0       S
+Rule   Zion    2010    only    -       Mar     31      0:00    1:00    D
+Rule   Zion    2010    only    -       Sep     12      0:00    0       S
+Rule   Zion    2011    only    -       Apr     20      0:00    1:00    D
+Rule   Zion    2011    only    -       Oct      2      0:00    0       S
+Rule   Zion    2012    only    -       Apr      8      0:00    1:00    D
+Rule   Zion    2012    only    -       Sep     23      0:00    0       S
+Rule   Zion    2013    only    -       Mar     27      0:00    1:00    D
+Rule   Zion    2013    only    -       Sep      8      0:00    0       S
+Rule   Zion    2014    only    -       Apr     16      0:00    1:00    D
+Rule   Zion    2014    only    -       Sep     28      0:00    0       S
+Rule   Zion    2015    only    -       Apr      5      0:00    1:00    D
+Rule   Zion    2015    only    -       Sep     20      0:00    0       S
+Rule   Zion    2016    only    -       Apr     24      0:00    1:00    D
+Rule   Zion    2016    only    -       Oct      9      0:00    0       S
+Rule   Zion    2017    only    -       Apr     12      0:00    1:00    D
+Rule   Zion    2017    only    -       Sep     24      0:00    0       S
+Rule   Zion    2018    only    -       Apr      1      0:00    1:00    D
+Rule   Zion    2018    only    -       Sep     16      0:00    0       S
+Rule   Zion    2019    only    -       Apr     21      0:00    1:00    D
+Rule   Zion    2019    only    -       Oct      6      0:00    0       S
+Rule   Zion    2020    only    -       Apr     10      0:00    1:00    D
+Rule   Zion    2020    only    -       Sep     27      0:00    0       S
+Rule   Zion    2021    only    -       Mar     29      0:00    1:00    D
+Rule   Zion    2021    only    -       Sep     12      0:00    0       S
+Rule   Zion    2022    only    -       Apr     17      0:00    1:00    D
+Rule   Zion    2022    only    -       Oct      2      0:00    0       S
+Rule   Zion    2023    only    -       Apr      7      0:00    1:00    D
+Rule   Zion    2023    only    -       Sep     24      0:00    0       S
+Rule   Zion    2024    only    -       Apr     24      0:00    1:00    D
+Rule   Zion    2024    only    -       Oct      6      0:00    0       S
+Rule   Zion    2025    only    -       Apr     14      0:00    1:00    D
+Rule   Zion    2025    only    -       Sep     28      0:00    0       S
+Rule   Zion    2026    only    -       Apr      3      0:00    1:00    D
+Rule   Zion    2026    only    -       Sep     20      0:00    0       S
+Rule   Zion    2027    only    -       Apr     23      0:00    1:00    D
+Rule   Zion    2027    only    -       Oct     10      0:00    0       S
+Rule   Zion    2028    only    -       Apr     12      0:00    1:00    D
+Rule   Zion    2028    only    -       Sep     24      0:00    0       S
+Rule   Zion    2029    only    -       Apr      1      0:00    1:00    D
+Rule   Zion    2029    only    -       Sep     16      0:00    0       S
+Rule   Zion    2030    only    -       Apr     19      0:00    1:00    D
+Rule   Zion    2030    only    -       Oct      6      0:00    0       S
+Rule   Zion    2031    only    -       Apr      9      0:00    1:00    D
+Rule   Zion    2031    only    -       Sep     21      0:00    0       S
+Rule   Zion    2032    only    -       Mar     28      0:00    1:00    D
+Rule   Zion    2032    only    -       Sep     12      0:00    0       S
+Rule   Zion    2033    only    -       Apr     15      0:00    1:00    D
+Rule   Zion    2033    only    -       Oct      2      0:00    0       S
+Rule   Zion    2034    only    -       Apr      5      0:00    1:00    D
+Rule   Zion    2034    only    -       Sep     17      0:00    0       S
+Rule   Zion    2035    only    -       Apr     25      0:00    1:00    D
+Rule   Zion    2035    only    -       Oct      7      0:00    0       S
+Rule   Zion    2036    only    -       Apr     13      0:00    1:00    D
+Rule   Zion    2036    only    -       Sep     28      0:00    0       S
+Rule   Zion    2037    only    -       Apr      1      0:00    1:00    D
+Rule   Zion    2037    only    -       Sep     13      0:00    0       S
 
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Jerusalem  2:20:56 -       LMT     1880
                        2:20:40 -       JMT     1918    # Jerusalem Mean Time?
                        2:00    Zion    I%sT
 
-# From Ephraim Silverberg (2003-03-23):
-#
-# Minister of Interior Poraz has announced that he will respect the law
-# passed in July 2000 (proposed at the time jointly by himself and
-# then-MK David Azulai [Shas]) fixing the dates for 2000-2004.  Hence,
-# the dates for 2003 and 2004 remain unchanged....
-#
-# As far as 2005 and beyond, no dates have been set.  However, the
-# minister has mentioned that he wishes to propose to move Israel's
-# timezone in 2005 from GMT+2 to GMT+3 and upon that have DST during
-# the summer months (i.e. GMT+4).  However, no legislation in this
-# direction is expected until the latter part of 2004 which is a long
-# time off in terms of Israeli politics.
-
-# (2004-09-20):
-# The latest rumour, however, is that in 2005, when the clock changes to
-# Daylight Saving Time (date as yet unknown), the move will be a two-hour leap
-# forward (from UTC+0200 to UTC+0400) and then, in the fall, the clock will
-# move back only an hour to UTC+0300 thus effectively moving Israel's timezone
-# from UTC+0200 to UTC+0300.  However, no actual draft has been put before the
-# Knesset (Israel's Parliament) though the intention is to do so this
-# month [2004-09].
-
-# (2004-09-26):
-# Even though the draft law for the above did pass the Ministerial Committee
-# for Legislative Matters three months ago, it was voted down in today's
-# Cabinet meeting.  The current suggestion is to keep the current timezone at
-# UTC+0200 but have an extended period of Daylight Saving Time (UTC+0300) from
-# the beginning of Passover holiday in the spring to after the Tabernacle
-# holiday in the fall (i.e. the dates of which are governed by the Hebrew
-# calendar but this means at least 184 days of DST).  However, this is only a
-# suggestion that was raised in today's cabinet meeting and has not yet been
-# drafted.
-
 
 
 ###############################################################################
index 6e118c2726e072deaa1ba088bec8a76aaef9e755..9fbab94d792975833ff57550190bcacfe3b2833d 100644 (file)
@@ -1,4 +1,4 @@
-# @(#)backward 7.26
+# @(#)backward 7.27
 
 # This file provides links between current names for time zones
 # and their old names.  Many names changed in late 1993.
@@ -13,7 +13,7 @@ Link  America/Argentina/Jujuy America/Jujuy
 Link   America/Indiana/Knox    America/Knox_IN
 Link   America/Argentina/Mendoza       America/Mendoza
 Link   America/Rio_Branco      America/Porto_Acre
-Link   America/Cordoba         America/Rosario
+Link   America/Argentina/Cordoba       America/Rosario
 Link   America/St_Thomas       America/Virgin
 Link   Asia/Ashgabat           Asia/Ashkhabad
 Link   Asia/Chongqing          Asia/Chungking
@@ -34,7 +34,7 @@ Link  Australia/Hobart        Australia/Tasmania
 Link   Australia/Melbourne     Australia/Victoria
 Link   Australia/Perth         Australia/West
 Link   Australia/Broken_Hill   Australia/Yancowinna
-Link   America/Porto_Acre      Brazil/Acre
+Link   America/Rio_Branco      Brazil/Acre
 Link   America/Noronha         Brazil/DeNoronha
 Link   America/Sao_Paulo       Brazil/East
 Link   America/Manaus          Brazil/West
@@ -55,10 +55,10 @@ Link        Europe/Dublin           Eire
 Link   Europe/Chisinau         Europe/Tiraspol
 Link   Europe/London           GB
 Link   Europe/London           GB-Eire
-Link   Etc/GMT+0               GMT+0
-Link   Etc/GMT-0               GMT-0
-Link   Etc/GMT0                GMT0
-Link   Etc/Greenwich           Greenwich
+Link   Etc/GMT                 GMT+0
+Link   Etc/GMT                 GMT-0
+Link   Etc/GMT                 GMT0
+Link   Etc/GMT                 Greenwich
 Link   Asia/Hong_Kong          Hongkong
 Link   Atlantic/Reykjavik      Iceland
 Link   Asia/Tehran             Iran
@@ -70,7 +70,7 @@ Link  Africa/Tripoli          Libya
 Link   America/Tijuana         Mexico/BajaNorte
 Link   America/Mazatlan        Mexico/BajaSur
 Link   America/Mexico_City     Mexico/General
-Link   America/Shiprock        Navajo
+Link   America/Denver          Navajo
 Link   Pacific/Auckland        NZ
 Link   Pacific/Chatham         NZ-CHAT
 Link   Pacific/Pago_Pago       Pacific/Samoa
@@ -95,6 +95,6 @@ Link  America/Denver          US/Mountain
 Link   America/Los_Angeles     US/Pacific
 Link   Pacific/Pago_Pago       US/Samoa
 Link   Etc/UTC                 UTC
-Link   Etc/Universal           Universal
+Link   Etc/UTC                 Universal
 Link   Europe/Moscow           W-SU
-Link   Etc/Zulu                Zulu
+Link   Etc/UTC                 Zulu
index eeb114f881adca1b2104d6e21c693e94b107c7b3..2da2df16db460c16bed2321de26a08387ba124b3 100644 (file)
@@ -1,4 +1,4 @@
-# @(#)europe   7.88
+# @(#)europe   7.91
 
 # This data is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
@@ -708,7 +708,7 @@ Zone        Europe/Sofia    1:33:16 -       LMT     1880
 # see Serbia and Montenegro
 
 # Cyprus
-# See the `asia' file.
+# Please see the `asia' file for Asia/Nicosia.
 
 # Czech Republic
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
@@ -754,6 +754,11 @@ Zone Atlantic/Faeroe       -0:27:04 -      LMT     1908 Jan 11     # Torshavn
                         0:00   -       WET     1981
                         0:00   EU      WE%sT
 #
+# From Paul Eggert (2004-10-31):
+# During World War II, Germany maintained secret manned weather stations in
+# East Greenland and Franz Josef Land, but we don't know their time zones.
+# My source for this is Wilhelm Dege's book mentioned under Svalbard.
+#
 # From Paul Eggert (1996-11-22):
 # Greenland joined the EU as part of Denmark, obtained home rule on 1979-05-01,
 # and left the EU on 1985-02-01.  It therefore should have been using EU
@@ -1055,6 +1060,11 @@ Zone     Europe/Berlin   0:53:28 -       LMT     1893 Apr
                        1:00    Germany CE%sT   1980
                        1:00    EU      CE%sT
 
+# Georgia
+# Please see the "asia" file for Asia/Tbilisi.
+# Herodotus (Histories, IV.45) says Georgia north of the Phasis (now Rioni)
+# is in Europe.  Our reference location Tbilisi is in the Asian part.
+
 # Gibraltar
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Europe/Gibraltar  -0:21:24 -      LMT     1880 Aug  2
@@ -1611,7 +1621,7 @@ Zone      Europe/Oslo     0:43:00 -       LMT     1895 Jan  1
 # From Paul Eggert (2001-05-01):
 #
 # Actually, Jan Mayen was never occupied by Germany during World War II,
-# so it must have diverged from Oslo time during the war, as Olso was
+# so it must have diverged from Oslo time during the war, as Oslo was
 # keeping Berlin time.
 #
 # <http://home.no.net/janmayen/history.htm> says that the meteorologists
@@ -1628,7 +1638,7 @@ Zone      Europe/Oslo     0:43:00 -       LMT     1895 Jan  1
 # <http://www.svalbard.com/SvalbardFAQ.html> says that the Germans were
 # expelled on 1942-05-14.  However, small parties of Germans did return,
 # and according to Wilhelm Dege's book "War North of 80" (1954)
-# <http://www.utpress.utoronto.ca/publishing/rights/dege_warnorthof80.htm>
+# <http://www.ucalgary.ca/UofC/departments/UP/1-55238/1-55238-110-2.html>
 # the German armed forces at the Svalbard weather station code-named
 # Haudegen did not surrender to the Allies until September 1945.
 #
index 7add3303f2b562f9db7d46513ade6d4d95465c62..385ee66ebd0e4f5ccc124069b47b9b7ab051743b 100644 (file)
@@ -1,4 +1,4 @@
-# @(#)leapseconds      7.17
+# @(#)leapseconds      7.18
 
 # Allowance for leapseconds added to each timezone file.
 
@@ -45,7 +45,6 @@ Leap  1997    Jun     30      23:59:60        +       S
 Leap   1998    Dec     31      23:59:60        +       S
 
 #      INTERNATIONAL EARTH ROTATION AND REFERENCE SYSTEMS SERVICE (IERS)
-# 
 # SERVICE INTERNATIONAL DE LA ROTATION TERRESTRE ET DES SYSTEMES DE REFERENCE
 # 
 # SERVICE DE LA ROTATION TERRESTRE
@@ -55,9 +54,10 @@ Leap 1998    Dec     31      23:59:60        +       S
 # FAX       : 33 (0) 1 40 51 22 91
 # Internet  : services.iers@obspm.fr
 # 
-#                                              Paris, 15 January 2004
+#                                              Paris, 21 July 2004
+# 
 # 
-#                                              Bulletin C 27
+#                                              Bulletin C 28
 # 
 #                                              To authorities responsible
 #                                              for the measurement and
@@ -65,7 +65,7 @@ Leap  1998    Dec     31      23:59:60        +       S
 # 
 #                      INFORMATION ON UTC - TAI
 # 
-# NO positive leap second will be introduced at the end of June 2004.
+# NO positive leap second will be introduced at the end of December 2004.
 # The difference between UTC and the International Atomic Time TAI is:
 # 
 #      from 1999 January 1, 0h UTC, until further notice : UTC-TAI = -32 s
@@ -78,4 +78,3 @@ Leap  1998    Dec     31      23:59:60        +       S
 #                                      Daniel GAMBIS
 #                                      Director
 #                                      Earth Orientation Center of IERS
-#                                      Observatoire de Paris, France
index 6e755b04b3c848e2ef6ba4c986beb30471e9cbde..f9d2f6a44740ba95a367e72576603a102a6d0f07 100644 (file)
@@ -1,4 +1,4 @@
-# @(#)northamerica     7.69
+# @(#)northamerica     7.71
 # also includes Central America and the Caribbean
 
 # This data is by no means authoritative; if you think you know better,
@@ -208,6 +208,13 @@ Rule       US      1987    max     -       Apr     Sun>=1  2:00    1:00    D
 # Pennsylvania, Rhode Island, South Carolina, eastern Tennessee,
 # Vermont, Virginia, West Virginia
 
+# From Dave Cantor (2004-11-02):
+# Early this summer I had the occasion to visit the Mount Washington
+# Observatory weather station atop (of course!) Mount Washington [, NH]....
+# One of the staff members said that the station was on Eastern Standard Time
+# and didn't change their clocks for Daylight Saving ... so that their
+# reports will always have times which are 5 hours behind UTC.
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER
 Rule   NYC     1920    only    -       Mar     lastSun 2:00    1:00    D
 Rule   NYC     1920    only    -       Oct     lastSun 2:00    0       S
@@ -355,10 +362,26 @@ Zone America/Adak  12:13:21 -     LMT     1867 Oct 18
                        -11:00  US      B%sT    1983 Oct 30 2:00
                        -10:00  US      AH%sT   1983 Nov 30
                        -10:00  US      HA%sT
+# The following switches don't quite make our 1970 cutoff.
+#
 # Shanks writes that part of southwest Alaska (e.g. Aniak)
 # switched from -11:00 to -10:00 on 1968-09-22 at 02:00,
 # and another part (e.g. Akiak) made the same switch five weeks later.
-# These switches don't quite make our 1970 cutoff.
+#
+# From David Flater (2004-11-09):
+# In e-mail, 2004-11-02, Ray Hudson, historian/liaison to the Unalaska
+# Historic Preservation Commission, provided this information, which
+# suggests that Unalaska deviated from statutory time from early 1967
+# possibly until 1983:
+#
+#  Minutes of the Unalaska City Council Meeting, January 10, 1967:
+#  "Except for St. Paul and Akutan, Unalaska is the only important
+#  location not on Alaska Standard Time.  The following resolution was
+#  made by William Robinson and seconded by Henry Swanson:  Be it
+#  resolved that the City of Unalaska hereby goes to Alaska Standard
+#  Time as of midnight Friday, January 13, 1967 (1 A.M. Saturday,
+#  January 14, Alaska Standard Time.)  This resolution was passed with
+#  three votes for and one against."
 
 # Hawaii
 #
@@ -1731,6 +1754,15 @@ Zone America/Costa_Rica  -5:36:20 -      LMT     1890            # San Jose
 # to DST--and one more hour on 1999-04-04--when the announcers will have
 # returned to Baltimore, which switches on that date.)
 
+# From Evert van der Veer via Steffen Thorsen (2004-10-28):
+# Cuba is not going back to standard time this year.
+# From Paul Eggert (2004-10-28):
+# http://www.granma.cu/ingles/2004/septiembre/juev30/41medid-i.html
+# says that it's due to a problem at the Antonio Guiteras
+# thermoelectric plant, and says "This October there will be no return
+# to normal hours (after daylight saving time)".
+# For now, let's assume that it's a one-year temporary measure.
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Cuba    1928    only    -       Jun     10      0:00    1:00    D
 Rule   Cuba    1928    only    -       Oct     10      0:00    0       S
@@ -1759,8 +1791,9 @@ Rule      Cuba    1991    1995    -       Oct     Sun>=8  0:00s   0       S
 Rule   Cuba    1996    only    -       Oct      6      0:00s   0       S
 Rule   Cuba    1997    only    -       Oct     12      0:00s   0       S
 Rule   Cuba    1998    1999    -       Mar     lastSun 0:00s   1:00    D
-Rule   Cuba    1998    max     -       Oct     lastSun 0:00s   0       S
+Rule   Cuba    1998    2003    -       Oct     lastSun 0:00s   0       S
 Rule   Cuba    2000    max     -       Apr     Sun>=1  0:00s   1:00    D
+Rule   Cuba    2005    max     -       Oct     lastSun 0:00s   0       S
 
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   America/Havana  -5:29:28 -      LMT     1890
index 57663052f09b0f581d103e0859a5902ceddb01dd..5de2f7dfe46d9ac84f8a0a8fdcbadb7a2591e60b 100644 (file)
@@ -21,7 +21,7 @@
 
 #ifndef lint
 #ifndef NOID
-static char    privatehid[] = "@(#)private.h   7.54";
+static char    privatehid[] = "@(#)private.h   7.55";
 #endif /* !defined NOID */
 #endif /* !defined lint */
 
@@ -208,6 +208,7 @@ extern char *       asctime_r();
 /*
 ** Private function declarations.
 */
+
 char * icalloc P((int nelem, int elsize));
 char * icatalloc P((char * old, const char * new));
 char * icpyalloc P((const char * string));
@@ -217,7 +218,6 @@ void        icfree P((char * pointer));
 void   ifree P((char * pointer));
 char * scheck P((const char *string, const char *format));
 
-
 /*
 ** Finally, some convenience items.
 */
@@ -238,6 +238,15 @@ char *     scheck P((const char *string, const char *format));
 #define TYPE_SIGNED(type) (((type) -1) < 0)
 #endif /* !defined TYPE_SIGNED */
 
+/*
+** Since the definition of TYPE_INTEGRAL contains floating point numbers,
+** it cannot be used in preprocessor directives.
+*/
+
+#ifndef TYPE_INTEGRAL
+#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
+#endif /* !defined TYPE_INTEGRAL */
+
 #ifndef INT_STRLEN_MAXIMUM
 /*
 ** 302 / 1000 is log10(2.0) rounded up.
index 912491049bec2786098eb7bf13e5e6ca3243861f..2e9faf49341703499b43cd3b82402d4c54c42d49 100644 (file)
@@ -1,4 +1,4 @@
-# @(#)southamerica     7.54
+# @(#)southamerica     7.57
 
 # This data is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
@@ -671,7 +671,7 @@ Zone America/Campo_Grande -3:38:28 -        LMT     1914
 # Mato Grosso (MT)
 Zone America/Cuiaba    -3:44:20 -      LMT     1914
                        -4:00   Brazil  AM%sT   2003 Sep 24
-                       -4:00   -       AMT     2004 Oct  4
+                       -4:00   -       AMT     2004 Oct  1
                        -4:00   Brazil  AM%sT
 #
 # west Para (PA), Rondonia (RO)
@@ -942,9 +942,16 @@ Rule       Para    1998    2001    -       Mar     Sun>=1  0:00    0       -
 # A decree was issued in Paraguay (no. 16350) on 2002-02-26 that changed the
 # dst method to be from the first Sunday in September to the first Sunday in
 # April.
-Rule   Para    2002    max     -       Apr     Sun>=1  0:00    0       -
-Rule   Para    2002    max     -       Sep     Sun>=1  0:00    1:00    S
-
+Rule   Para    2002    2004    -       Apr     Sun>=1  0:00    0       -
+Rule   Para    2002    2003    -       Sep     Sun>=1  0:00    1:00    S
+#
+# From Jesper Norgaard Welen (2005-01-02):
+# There are several sources that claim that Paraguay made
+# a timezone rule change in autumn 2004.
+# From Steffen Thorsen (2005-01-05):
+# Decree 1,867 (2004-03-05) <http://www.labor.com.py/noticias.asp?id=27>
+Rule   Para    2004    max     -       Oct     Sun>=15 0:00    1:00    S
+Rule   Para    2005    max     -       Mar     Sun>=8  0:00    0       -
 
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone America/Asuncion  -3:50:40 -      LMT     1890
index 0921c3c3396e8116ff749f3c8116011d09e00202..0e9966a9506b5f65c8623105f2f766138cf4078b 100644 (file)
@@ -21,7 +21,7 @@
 
 #ifndef lint
 #ifndef NOID
-static char    tzfilehid[] = "@(#)tzfile.h     7.14";
+static char    tzfilehid[] = "@(#)tzfile.h     7.16";
 #endif /* !defined NOID */
 #endif /* !defined lint */
 
@@ -156,12 +156,21 @@ struct tzhead {
 #define EPOCH_YEAR     1970
 #define EPOCH_WDAY     TM_THURSDAY
 
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+
 /*
-** Accurate only for the past couple of centuries;
-** that will probably do.
+** Since everything in isleap is modulo 400 (or a factor of 400), we know that
+**     isleap(y) == isleap(y % 400)
+** and so
+**     isleap(a + b) == isleap((a + b) % 400)
+** or
+**     isleap(a + b) == isleap(a % 400 + b % 400)
+** This is true even if % means modulo rather than Fortran remainder
+** (which is allowed by C89 but not C99).
+** We use this to avoid addition overflow problems.
 */
 
-#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+#define isleap_sum(a, b)       isleap((a) % 400 + (b) % 400)
 
 #ifndef USG
 
index 20bb916822b174394c207a59c0b7b1fc1e2eccaa..bd7132698f8bc6959c721740bb0e00215855e4f4 100644 (file)
@@ -1,4 +1,4 @@
-static char    elsieid[] = "@(#)zdump.c        7.40";
+static char    elsieid[] = "@(#)zdump.c        7.61";
 
 /*
 ** This code has been made independent of the rest of the time
@@ -11,6 +11,15 @@ static char  elsieid[] = "@(#)zdump.c        7.40";
 #include "sys/types.h" /* for time_t */
 #include "time.h"      /* for struct tm */
 #include "stdlib.h"    /* for exit, malloc, atoi */
+#include "float.h"     /* for FLT_MAX and DBL_MAX */
+
+#ifndef ZDUMP_LO_YEAR
+#define ZDUMP_LO_YEAR  (-500)
+#endif /* !defined ZDUMP_LO_YEAR */
+
+#ifndef ZDUMP_HI_YEAR
+#define ZDUMP_HI_YEAR  2500
+#endif /* !defined ZDUMP_HI_YEAR */
 
 #ifndef MAX_STRING_LENGTH
 #define MAX_STRING_LENGTH      1024
@@ -61,9 +70,20 @@ static char  elsieid[] = "@(#)zdump.c        7.40";
 #endif /* !defined DAYSPERNYEAR */
 
 #ifndef isleap
-#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
 #endif /* !defined isleap */
 
+#ifndef isleap_sum
+/*
+** See tzfile.h for details on isleap_sum.
+*/
+#define isleap_sum(a, b)       isleap((a) % 400 + (b) % 400)
+#endif /* !defined isleap_sum */
+
+#define SECSPERDAY     ((long) SECSPERHOUR * HOURSPERDAY)
+#define SECSPERNYEAR   (SECSPERDAY * DAYSPERNYEAR)
+#define SECSPERLYEAR   (SECSPERNYEAR + SECSPERDAY)
+
 #if HAVE_GETTEXT
 #include "locale.h"    /* for setlocale */
 #include "libintl.h"
@@ -115,18 +135,60 @@ static char       elsieid[] = "@(#)zdump.c        7.40";
 
 extern char ** environ;
 extern int     getopt P((int argc, char * const argv[],
-                         const char * options));
+                       const char * options));
 extern char *  optarg;
 extern int     optind;
 extern char *  tzname[2];
 
+static time_t  absolute_min_time;
+static time_t  absolute_max_time;
+static size_t  longest;
+static char *  progname;
+
 static char *  abbr P((struct tm * tmp));
 static long    delta P((struct tm * newp, struct tm * oldp));
+static void    dumptime P((const struct tm * tmp));
 static time_t  hunt P((char * name, time_t lot, time_t hit));
-static size_t  longest;
-static char *  progname;
+static void    setabsolutes P((void));
 static void    show P((char * zone, time_t t, int v));
-static void    dumptime P((const struct tm * tmp));
+static const char *    tformat P((void));
+static time_t  yeartot P((long y));
+
+#ifndef TYPECHECK
+#define my_localtime   localtime
+#else /* !defined TYPECHECK */
+static struct tm *
+my_localtime(tp)
+time_t *       tp;
+{
+       register struct tm *    tmp;
+
+       tmp = localtime(tp);
+       if (tp != NULL && tmp != NULL) {
+               struct tm       tm;
+               register time_t t;
+
+               tm = *tmp;
+               t = mktime(&tm);
+               if (t - *tp >= 1 || *tp - t >= 1) {
+                       (void) fflush(stdout);
+                       (void) fprintf(stderr, "\n%s: ", progname);
+                       (void) fprintf(stderr, tformat(), *tp);
+                       (void) fprintf(stderr, " ->");
+                       (void) fprintf(stderr, " sec %d", tmp->tm_sec);
+                       (void) fprintf(stderr, " min %d", tmp->tm_min);
+                       (void) fprintf(stderr, " hour %d", tmp->tm_hour);
+                       (void) fprintf(stderr, " mday %d", tmp->tm_mday);
+                       (void) fprintf(stderr, " mon %d", tmp->tm_mon);
+                       (void) fprintf(stderr, " year %d", tmp->tm_year);
+                       (void) fprintf(stderr, " -> ");
+                       (void) fprintf(stderr, tformat(), t);
+                       (void) fprintf(stderr, "\n");
+               }
+       }
+       return tmp;
+}
+#endif /* !defined TYPECHECK */
 
 int
 main(argc, argv)
@@ -136,18 +198,22 @@ char *    argv[];
        register int            i;
        register int            c;
        register int            vflag;
-       register char *         cutoff;
-       register int            cutyear;
-       register long           cuttime;
-       char **                 fakeenv;
+       register char *         cutarg;
+       register long           cutloyear = ZDUMP_LO_YEAR;
+       register long           cuthiyear = ZDUMP_HI_YEAR;
+       register time_t         cutlotime;
+       register time_t         cuthitime;
+       register char **        fakeenv;
        time_t                  now;
        time_t                  t;
        time_t                  newt;
-       time_t                  hibit;
        struct tm               tm;
        struct tm               newtm;
+       register struct tm *    tmp;
+       register struct tm *    newtmp;
 
-       INITIALIZE(cuttime);
+       INITIALIZE(cutlotime);
+       INITIALIZE(cuthitime);
 #if HAVE_GETTEXT
        (void) setlocale(LC_MESSAGES, "");
 #ifdef TZ_DOMAINDIR
@@ -162,39 +228,50 @@ char *    argv[];
                        (void) exit(EXIT_SUCCESS);
                }
        vflag = 0;
-       cutoff = NULL;
+       cutarg = NULL;
        while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
                if (c == 'v')
                        vflag = 1;
-               else    cutoff = optarg;
+               else    cutarg = optarg;
        if ((c != EOF && c != -1) ||
                (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
                        (void) fprintf(stderr,
-_("%s: usage is %s [ --version ] [ -v ] [ -c cutoff ] zonename ...\n"),
-                               argv[0], argv[0]);
+_("%s: usage is %s [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"),
+                               progname, progname);
                        (void) exit(EXIT_FAILURE);
        }
-       if (cutoff != NULL) {
-               int     y;
-
-               cutyear = atoi(cutoff);
-               cuttime = 0;
-               for (y = EPOCH_YEAR; y < cutyear; ++y)
-                       cuttime += DAYSPERNYEAR + isleap(y);
-               cuttime *= SECSPERHOUR * HOURSPERDAY;
+       if (vflag) {
+               if (cutarg != NULL) {
+                       long    lo;
+                       long    hi;
+                       char    dummy;
+
+                       if (sscanf(cutarg, "%ld%c", &hi, &dummy) == 1) {
+                               cuthiyear = hi;
+                       } else if (sscanf(cutarg, "%ld,%ld%c",
+                               &lo, &hi, &dummy) == 2) {
+                                       cutloyear = lo;
+                                       cuthiyear = hi;
+                       } else {
+(void) fprintf(stderr, _("%s: wild -c argument %s\n"),
+                                       progname, cutarg);
+                               (void) exit(EXIT_FAILURE);
+                       }
+               }
+               setabsolutes();
+               cutlotime = yeartot(cutloyear);
+               cuthitime = yeartot(cuthiyear);
        }
        (void) time(&now);
        longest = 0;
        for (i = optind; i < argc; ++i)
                if (strlen(argv[i]) > longest)
                        longest = strlen(argv[i]);
-       for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
-               continue;
        {
                register int    from;
                register int    to;
 
-               for (i = 0;  environ[i] != NULL;  ++i)
+               for (i = 0; environ[i] != NULL; ++i)
                        continue;
                fakeenv = (char **) malloc((size_t) ((i + 2) *
                        sizeof *fakeenv));
@@ -219,58 +296,129 @@ _("%s: usage is %s [ --version ] [ -v ] [ -c cutoff ] zonename ...\n"),
                        show(argv[i], now, FALSE);
                        continue;
                }
-               /*
-               ** Get lowest value of t.
-               */
-               t = hibit;
-               if (t > 0)              /* time_t is unsigned */
-                       t = 0;
+               t = absolute_min_time;
                show(argv[i], t, TRUE);
                t += SECSPERHOUR * HOURSPERDAY;
                show(argv[i], t, TRUE);
-               tm = *localtime(&t);
-               (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
+               if (t < cutlotime)
+                       t = cutlotime;
+               tmp = my_localtime(&t);
+               if (tmp != NULL) {
+                       tm = *tmp;
+                       (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
+               }
                for ( ; ; ) {
-                       if (cutoff != NULL && t >= cuttime)
+                       if (t >= cuthitime)
                                break;
                        newt = t + SECSPERHOUR * 12;
-                       if (cutoff != NULL && newt >= cuttime)
+                       if (newt >= cuthitime)
                                break;
                        if (newt <= t)
                                break;
-                       newtm = *localtime(&newt);
-                       if (delta(&newtm, &tm) != (newt - t) ||
+                       newtmp = localtime(&newt);
+                       if (newtmp != NULL)
+                               newtm = *newtmp;
+                       if ((tmp == NULL || newtmp == NULL) ?  (tmp != newtmp) :
+                               (delta(&newtm, &tm) != (newt - t) ||
                                newtm.tm_isdst != tm.tm_isdst ||
-                               strcmp(abbr(&newtm), buf) != 0) {
+                               strcmp(abbr(&newtm), buf) != 0)) {
                                        newt = hunt(argv[i], t, newt);
-                                       newtm = *localtime(&newt);
-                                       (void) strncpy(buf, abbr(&newtm),
-                                               (sizeof buf) - 1);
+                                       newtmp = localtime(&newt);
+                                       if (newtmp != NULL) {
+                                               newtm = *newtmp;
+                                               (void) strncpy(buf,
+                                                       abbr(&newtm),
+                                                       (sizeof buf) - 1);
+                                       }
                        }
                        t = newt;
                        tm = newtm;
+                       tmp = newtmp;
                }
-               /*
-               ** Get highest value of t.
-               */
-               t = ~((time_t) 0);
-               if (t < 0)              /* time_t is signed */
-                       t &= ~hibit;
+               t = absolute_max_time;
                t -= SECSPERHOUR * HOURSPERDAY;
                show(argv[i], t, TRUE);
                t += SECSPERHOUR * HOURSPERDAY;
                show(argv[i], t, TRUE);
        }
        if (fflush(stdout) || ferror(stdout)) {
-               (void) fprintf(stderr, "%s: ", argv[0]);
+               (void) fprintf(stderr, "%s: ", progname);
                (void) perror(_("Error writing standard output"));
                (void) exit(EXIT_FAILURE);
        }
        exit(EXIT_SUCCESS);
+       /* If exit fails to exit... */
+       return EXIT_FAILURE;
+}
+
+static void
+setabsolutes()
+{
+       if (0.5 == (time_t) 0.5) {
+               /*
+               ** time_t is floating.
+               */
+               if (sizeof (time_t) == sizeof (float)) {
+                       absolute_min_time = (time_t) -FLT_MAX;
+                       absolute_max_time = (time_t) FLT_MAX;
+               } else if (sizeof (time_t) == sizeof (double)) {
+                       absolute_min_time = (time_t) -DBL_MAX;
+                       absolute_max_time = (time_t) DBL_MAX;
+               } else {
+                       (void) fprintf(stderr,
+_("%s: use of -v on system with floating time_t other than float or double\n"),
+                               progname);
+                       (void) exit(EXIT_FAILURE);
+               }
+       } else if (0 > (time_t) -1) {
+               /*
+               ** time_t is signed.
+               */
+               register time_t hibit;
 
-       /* gcc -Wall pacifier */
-       for ( ; ; )
-               continue;
+               for (hibit = 1; (hibit * 2) != 0; hibit *= 2)
+                       continue;
+               absolute_min_time = hibit;
+               absolute_max_time = -(hibit + 1);
+       } else {
+               /*
+               ** time_t is unsigned.
+               */
+               absolute_min_time = 0;
+               absolute_max_time = absolute_min_time - 1;
+       }
+}
+
+static time_t
+yeartot(y)
+const long     y;
+{
+       register long   myy;
+       register long   seconds;
+       register time_t t;
+
+       myy = EPOCH_YEAR;
+       t = 0;
+       while (myy != y) {
+               if (myy < y) {
+                       seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR;
+                       ++myy;
+                       if (t > absolute_max_time - seconds) {
+                               t = absolute_max_time;
+                               break;
+                       }
+                       t += seconds;
+               } else {
+                       --myy;
+                       seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR;
+                       if (t < absolute_min_time + seconds) {
+                               t = absolute_min_time;
+                               break;
+                       }
+                       t -= seconds;
+               }
+       }
+       return t;
 }
 
 static time_t
@@ -279,25 +427,39 @@ char *    name;
 time_t lot;
 time_t hit;
 {
-       time_t          t;
-       struct tm       lotm;
-       struct tm       tm;
-       static char     loab[MAX_STRING_LENGTH];
-
-       lotm = *localtime(&lot);
-       (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
-       while ((hit - lot) >= 2) {
-               t = lot / 2 + hit / 2;
+       time_t                  t;
+       long                    diff;
+       struct tm               lotm;
+       register struct tm *    lotmp;
+       struct tm               tm;
+       register struct tm *    tmp;
+       char                    loab[MAX_STRING_LENGTH];
+
+       lotmp = my_localtime(&lot);
+       if (lotmp != NULL) {
+               lotm = *lotmp;
+               (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
+       }
+       for ( ; ; ) {
+               diff = (long) (hit - lot);
+               if (diff < 2)
+                       break;
+               t = lot;
+               t += diff / 2;
                if (t <= lot)
                        ++t;
                else if (t >= hit)
                        --t;
-               tm = *localtime(&t);
-               if (delta(&tm, &lotm) == (t - lot) &&
+               tmp = my_localtime(&t);
+               if (tmp != NULL)
+                       tm = *tmp;
+               if ((lotmp == NULL || tmp == NULL) ? (lotmp == tmp) :
+                       (delta(&tm, &lotm) == (t - lot) &&
                        tm.tm_isdst == lotm.tm_isdst &&
-                       strcmp(abbr(&tm), loab) == 0) {
+                       strcmp(abbr(&tm), loab) == 0)) {
                                lot = t;
                                lotm = tm;
+                               lotmp = tmp;
                } else  hit = t;
        }
        show(name, lot, TRUE);
@@ -314,14 +476,14 @@ delta(newp, oldp)
 struct tm *    newp;
 struct tm *    oldp;
 {
-       long    result;
-       int     tmy;
+       register long   result;
+       register int    tmy;
 
        if (newp->tm_year < oldp->tm_year)
                return -delta(oldp, newp);
        result = 0;
        for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
-               result += DAYSPERNYEAR + isleap(tmy + (long) TM_YEAR_BASE);
+               result += DAYSPERNYEAR + isleap_sum(tmy, TM_YEAR_BASE);
        result += newp->tm_yday - oldp->tm_yday;
        result *= HOURSPERDAY;
        result += newp->tm_hour - oldp->tm_hour;
@@ -338,22 +500,30 @@ char *    zone;
 time_t t;
 int    v;
 {
-       struct tm *     tmp;
+       register struct tm *    tmp;
 
        (void) printf("%-*s  ", (int) longest, zone);
        if (v) {
-               dumptime(gmtime(&t));
-               (void) printf(" UTC = ");
+               tmp = gmtime(&t);
+               if (tmp == NULL) {
+                       (void) printf(tformat(), t);
+               } else {
+                       dumptime(tmp);
+                       (void) printf(" UTC");
+               }
+               (void) printf(" = ");
        }
-       tmp = localtime(&t);
+       tmp = my_localtime(&t);
        dumptime(tmp);
-       if (*abbr(tmp) != '\0')
-               (void) printf(" %s", abbr(tmp));
-       if (v) {
-               (void) printf(" isdst=%d", tmp->tm_isdst);
+       if (tmp != NULL) {
+               if (*abbr(tmp) != '\0')
+                       (void) printf(" %s", abbr(tmp));
+               if (v) {
+                       (void) printf(" isdst=%d", tmp->tm_isdst);
 #ifdef TM_GMTOFF
-               (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
+                       (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
 #endif /* defined TM_GMTOFF */
+               }
        }
        (void) printf("\n");
 }
@@ -371,6 +541,33 @@ struct tm *        tmp;
        return (result == NULL) ? &nada : result;
 }
 
+/*
+** The code below can fail on certain theoretical systems;
+** it works on all known real-world systems as of 2004-12-30.
+*/
+
+static const char *
+tformat()
+{
+       if (0.5 == (time_t) 0.5) {      /* floating */
+               if (sizeof (time_t) > sizeof (double))
+                       return "%Lg";
+               return "%g";
+       }
+       if (0 > (time_t) -1) {          /* signed */
+               if (sizeof (time_t) > sizeof (long))
+                       return "%lld";
+               if (sizeof (time_t) > sizeof (int))
+                       return "%ld";
+               return "%d";
+       }
+       if (sizeof (time_t) > sizeof (unsigned long))
+               return "%llu";
+       if (sizeof (time_t) > sizeof (unsigned int))
+               return "%lu";
+       return "%u";
+}
+
 static void
 dumptime(timeptr)
 register const struct tm *     timeptr;
@@ -384,7 +581,13 @@ register const struct tm * timeptr;
        };
        register const char *   wn;
        register const char *   mn;
+       register int            lead;
+       register int            trail;
 
+       if (timeptr == NULL) {
+               (void) printf("NULL");
+               return;
+       }
        /*
        ** The packaged versions of localtime and gmtime never put out-of-range
        ** values in tm_wday or tm_mon, but since this code might be compiled
@@ -398,9 +601,23 @@ register const struct tm * timeptr;
                (int) (sizeof mon_name / sizeof mon_name[0]))
                        mn = "???";
        else            mn = mon_name[timeptr->tm_mon];
-       (void) printf("%.3s %.3s%3d %.2d:%.2d:%.2d %ld",
+       (void) printf("%.3s %.3s%3d %.2d:%.2d:%.2d ",
                wn, mn,
                timeptr->tm_mday, timeptr->tm_hour,
-               timeptr->tm_min, timeptr->tm_sec,
-               timeptr->tm_year + (long) TM_YEAR_BASE);
+               timeptr->tm_min, timeptr->tm_sec);
+#define DIVISOR        10
+       trail = timeptr->tm_year % DIVISOR + TM_YEAR_BASE % DIVISOR;
+       lead = timeptr->tm_year / DIVISOR + TM_YEAR_BASE / DIVISOR +
+               trail / DIVISOR;
+       trail %= DIVISOR;
+       if (trail < 0 && lead > 0) {
+               trail += DIVISOR;
+               --lead;
+       } else if (lead < 0 && trail > 0) {
+               trail -= DIVISOR;
+               ++lead;
+       }
+       if (lead == 0)
+               (void) printf("%d", trail);
+       else    (void) printf("%d%d", lead, ((trail < 0) ? -trail : trail));
 }
index 9bb8662e55ce34d0cd6036aef02da5ba860fb010..d855475f9fa55b0db3ed6fcf6dca2dd5d70c03fd 100644 (file)
@@ -1,4 +1,10 @@
-static char    elsieid[] = "@(#)zic.c  7.116";
+static char    elsieid[] = "@(#)zic.c  7.118";
+
+/*
+** Regardless of the type of time_t, we do our work using this type.
+*/
+
+typedef int    zic_t;
 
 #include "private.h"
 #include "locale.h"
@@ -50,7 +56,7 @@ struct rule {
        const char *    r_abbrvar;      /* variable part of abbreviation */
 
        int             r_todo;         /* a rule to do (used in outzone) */
-       time_t          r_temp;         /* used in outzone */
+       zic_t           r_temp;         /* used in outzone */
 };
 
 /*
@@ -76,7 +82,7 @@ struct zone {
        int             z_nrules;
 
        struct rule     z_untilrule;
-       time_t          z_untiltime;
+       zic_t           z_untiltime;
 };
 
 extern int     getopt P((int argc, char * const argv[],
@@ -85,10 +91,10 @@ extern int  link P((const char * fromname, const char * toname));
 extern char *  optarg;
 extern int     optind;
 
-static void    addtt P((time_t starttime, int type));
+static void    addtt P((zic_t starttime, int type));
 static int     addtype P((long gmtoff, const char * abbr, int isdst,
                                int ttisstd, int ttisgmt));
-static void    leapadd P((time_t t, int positive, int rolling, int count));
+static void    leapadd P((zic_t t, int positive, int rolling, int count));
 static void    adjleap P((void));
 static void    associate P((void));
 static int     ciequal P((const char * ap, const char * bp));
@@ -121,13 +127,13 @@ static long       oadd P((long t1, long t2));
 static void    outzone P((const struct zone * zp, int ntzones));
 static void    puttzcode P((long code, FILE * fp));
 static int     rcomp P((const void * leftp, const void * rightp));
-static time_t  rpytime P((const struct rule * rp, int wantedy));
+static zic_t   rpytime P((const struct rule * rp, int wantedy));
 static void    rulesub P((struct rule * rp,
                        const char * loyearp, const char * hiyearp,
                        const char * typep, const char * monthp,
                        const char * dayp, const char * timep));
 static void    setboundaries P((void));
-static time_t  tadd P((time_t t1, long t2));
+static zic_t   tadd P((zic_t t1, long t2));
 static void    usage P((void));
 static void    writezone P((const char * name));
 static int     yearistype P((int year, const char * type));
@@ -141,10 +147,10 @@ static int                errors;
 static const char *    filename;
 static int             leapcnt;
 static int             linenum;
-static time_t          max_time;
+static zic_t           max_time;
 static int             max_year;
 static int             max_year_representable;
-static time_t          min_time;
+static zic_t           min_time;
 static int             min_year;
 static int             min_year_representable;
 static int             noise;
@@ -334,7 +340,7 @@ static const int    len_years[2] = {
 };
 
 static struct attype {
-       time_t          at;
+       zic_t           at;
        unsigned char   type;
 }                      attypes[TZ_MAX_TIMES];
 static long            gmtoffs[TZ_MAX_TYPES];
@@ -343,7 +349,7 @@ static unsigned char        abbrinds[TZ_MAX_TYPES];
 static char            ttisstds[TZ_MAX_TYPES];
 static char            ttisgmts[TZ_MAX_TYPES];
 static char            chars[TZ_MAX_CHARS];
-static time_t          trans[TZ_MAX_LEAPS];
+static zic_t           trans[TZ_MAX_LEAPS];
 static long            corr[TZ_MAX_LEAPS];
 static char            roll[TZ_MAX_LEAPS];
 
@@ -629,7 +635,7 @@ const char * const  tofile;
                        register char * symlinkcontents = NULL;
                        while ((s = strchr(s+1, '/')) != NULL)
                                symlinkcontents = ecatalloc(symlinkcontents, "../");
-                       symlinkcontents = ecatalloc(symlinkcontents, fromname);
+                       symlinkcontents = ecatalloc(symlinkcontents, fromfile);
 
                        result = unlink(toname);
                        if (result != 0 && errno != ENOENT) {
@@ -676,25 +682,36 @@ warning(_("hard link failed, symbolic link used"));
 */
 
 #define MAX_BITS_IN_FILE       32
-#define TIME_T_BITS_IN_FILE    ((TYPE_BIT(time_t) < MAX_BITS_IN_FILE) ? TYPE_BIT(time_t) : MAX_BITS_IN_FILE)
+#define TIME_T_BITS_IN_FILE    ((TYPE_BIT(zic_t) < MAX_BITS_IN_FILE) ? \
+                                       TYPE_BIT(zic_t) : MAX_BITS_IN_FILE)
 
 static void
 setboundaries P((void))
 {
-       if (TYPE_SIGNED(time_t)) {
-               min_time = ~ (time_t) 0;
-               min_time <<= TIME_T_BITS_IN_FILE - 1;
-               max_time = ~ (time_t) 0 - min_time;
+       register int    i;
+
+       if (TYPE_SIGNED(zic_t)) {
+               min_time = -1;
+               for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i)
+                       min_time *= 2;
+               max_time = -(min_time + 1);
                if (sflag)
                        min_time = 0;
        } else {
                min_time = 0;
                max_time = 2 - sflag;
-               max_time <<= TIME_T_BITS_IN_FILE - 1;
+               for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i)
+                       max_time *= 2;
                --max_time;
        }
-       min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;
-       max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;
+       {
+               time_t  t;
+
+               t = (time_t) min_time;
+               min_year = TM_YEAR_BASE + gmtime(&t)->tm_year;
+               t = (time_t) max_time;
+               max_year = TM_YEAR_BASE + gmtime(&t)->tm_year;
+       }
        min_year_representable = min_year;
        max_year_representable = max_year;
 }
@@ -1120,7 +1137,7 @@ const int         nfields;
        register int                    i, j;
        int                             year, month, day;
        long                            dayoff, tod;
-       time_t                          t;
+       zic_t                           t;
 
        if (nfields != LEAP_FIELDS) {
                error(_("wrong number of fields on Leap line"));
@@ -1164,7 +1181,7 @@ const int         nfields;
                        return;
        }
        dayoff = oadd(dayoff, eitol(day - 1));
-       if (dayoff < 0 && !TYPE_SIGNED(time_t)) {
+       if (dayoff < 0 && !TYPE_SIGNED(zic_t)) {
                error(_("time before zero"));
                return;
        }
@@ -1176,7 +1193,7 @@ const int         nfields;
                error(_("time too large"));
                return;
        }
-       t = (time_t) dayoff * SECSPERDAY;
+       t = (zic_t) dayoff * SECSPERDAY;
        tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE);
        cp = fields[LP_CORR];
        {
@@ -1438,7 +1455,7 @@ const char * const        name;
        register int            i, j;
        static char *           fullname;
        static struct tzhead    tzh;
-       time_t                  ats[TZ_MAX_TIMES];
+       zic_t                   ats[TZ_MAX_TIMES];
        unsigned char           types[TZ_MAX_TIMES];
 
        /*
@@ -1603,7 +1620,7 @@ const int                 zonecount;
        register struct rule *          rp;
        register int                    i, j;
        register int                    usestart, useuntil;
-       register time_t                 starttime, untiltime;
+       register zic_t                  starttime, untiltime;
        register long                   gmtoff;
        register long                   stdoff;
        register int                    year;
@@ -1672,7 +1689,7 @@ const int                 zonecount;
                        }
                        for ( ; ; ) {
                                register int    k;
-                               register time_t jtime, ktime;
+                               register zic_t  jtime, ktime;
                                register long   offset;
                                char            buf[BUFSIZ];
 
@@ -1784,7 +1801,7 @@ error(_("can't determine time zone abbreviation to use just after until time"));
 
 static void
 addtt(starttime, type)
-const time_t   starttime;
+const zic_t    starttime;
 int            type;
 {
        if (starttime <= min_time ||
@@ -1868,7 +1885,7 @@ const int         ttisgmt;
 
 static void
 leapadd(t, positive, rolling, count)
-const time_t   t;
+const zic_t    t;
 const int      positive;
 const int      rolling;
 int            count;
@@ -2056,12 +2073,12 @@ const long      t2;
        return t;
 }
 
-static time_t
+static zic_t
 tadd(t1, t2)
-const time_t   t1;
+const zic_t    t1;
 const long     t2;
 {
-       register time_t t;
+       register zic_t  t;
 
        if (t1 == max_time && t2 > 0)
                return max_time;
@@ -2080,14 +2097,14 @@ const long      t2;
 ** 1970, 00:00 LOCAL time - in that year that the rule refers to.
 */
 
-static time_t
+static zic_t
 rpytime(rp, wantedy)
 register const struct rule * const     rp;
 register const int                     wantedy;
 {
        register int    y, m, i;
        register long   dayoff;                 /* with a nod to Margaret O. */
-       register time_t t;
+       register zic_t  t;
 
        if (wantedy == INT_MIN)
                return min_time;
@@ -2154,15 +2171,13 @@ register const int                      wantedy;
                                warning(_("rule goes past start/end of month--will not work with pre-2004 versions of zic"));
                }
        }
-       if (dayoff < 0 && !TYPE_SIGNED(time_t))
+       if (dayoff < 0 && !TYPE_SIGNED(zic_t))
                return min_time;
        if (dayoff < min_time / SECSPERDAY)
                return min_time;
        if (dayoff > max_time / SECSPERDAY)
                return max_time;
-       t = (time_t) dayoff * SECSPERDAY;
-       if (t > 0 && max_time - t < rp->r_tod)
-               return max_time;
+       t = (zic_t) dayoff * SECSPERDAY;
        return tadd(t, rp->r_tod);
 }