diff options
author | Ulrich Drepper <drepper@redhat.com> | 1998-06-07 14:06:56 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 1998-06-07 14:06:56 +0000 |
commit | c0fb8a563c1c49e5fbec9bc22deac618910a3ff4 (patch) | |
tree | e7db886672cef990feba6c4357ebece5a820d7cf | |
parent | 737547be99fd9afffbdf3f7ac817da0a06fffc9e (diff) | |
download | glibc-c0fb8a563c1c49e5fbec9bc22deac618910a3ff4.zip glibc-c0fb8a563c1c49e5fbec9bc22deac618910a3ff4.tar.gz glibc-c0fb8a563c1c49e5fbec9bc22deac618910a3ff4.tar.bz2 |
Update.
1998-06-07 13:32 Ulrich Drepper <drepper@cygnus.com>
* libc.map: Add _dl_profile.
* elf/dl-reloc.c (_dl_relocate_object): Take extra argument, pass
this to ELF_DYNAMIC_RELOCATE.
Always allocate array for relocation result if LD_PROFILE is defined.
* elf/ldsodefs.h: Adjust prototypes.
* elf/dl-open.c (_dl_open): Call relocation function with extra
argument.
* elf/rtld.c: Likewise.
* elf/dl-profile.c (_dl_mcount): Don't mark as internal function.
Correct loop condition.
* elf/dynamic-link.h: Don't examine _dl_profile variable, pass
consider_profile to runtime setup function.
* sysdeps/i386/dl-machine.h (elf_machine_runtime_setup): Use
_dl_runtime_profile for all shared objects if LD_PROFILE is defined.
* elf/dl-support.c: Define __libc_stack_end.
* elf/rtld.c: Likewise.
* sysdeps/generic/libc-start.c: Store last stack address in
__libc_stack_end.
* sysdeps/i386/dl-machine.h (_dl_start_user): Store stack address.
* sysdeps/i386/elf/start.s: Call __libc_start_main with extra argument.
* elf/elf.h: Include <features.h>, not <sys/cdefs.h>.
Include <stdint.h>, not <inttypes.h>.
* elf/sprof.c: Implement flat profiling.
* libio/fgetc.c: Call _IO_cleanup_region_end with 0 and call
_IO_funlockfile explicitly.
* libio/fileops.c: Likewise.
* libio/fputc.c: Likewise.
* libio/freopen.c: Likewise.
* libio/freopen64.c: Likewise.
* libio/fseek.c: Likewise.
* libio/fseeko.c: Likewise.
* libio/fseeko64.c: Likewise.
* libio/ftello.c: Likewise.
* libio/ftello64.c: Likewise.
* libio/getc.c: Likewise.
* libio/getchar.c: Likewise.
* libio/iofclose.c: Likewise.
* libio/iofflush.c: Likewise.
* libio/iofgetpos.c: Likewise.
* libio/iofgetpos64.c: Likewise.
* libio/iofgets.c: Likewise.
* libio/iofputs.c: Likewise.
* libio/iofread.c: Likewise.
* libio/iofsetpos.c: Likewise.
* libio/iofsetpos64.c: Likewise.
* libio/ioftell.c: Likewise.
* libio/iofwrite.c: Likewise.
* libio/iogetdelim.c: Likewise.
* libio/iogets.c: Likewise.
* libio/ioputs.c: Likewise.
* libio/ioseekoff.c: Likewise.
* libio/ioseekpos.c: Likewise.
* libio/iosetbuffer.c: Likewise.
* libio/iosetvbuf.c: Likewise.
* libio/ioungetc.c: Likewise.
* libio/iovsprintf.c: Likewise.
* libio/iovsscanf.c: Likewise.
* libio/oldfileops.c: Likewise.
* libio/oldiofclose.c: Likewise.
* libio/peekc.c: Likewise.
* libio/putc.c: Likewise.
* libio/putchar.c: Likewise.
* libio/rewind.c: Likewise.
* malloc/mtrace.c: Pretty print.
* misc/mntent.h (struct mentent): Make string elements const char *.
* nis/nis_printf.c: Optimize I/O a little bit.
* signal/Makefile (distribute): Add sigset-cvt-mask.h.
* sysdeps/generic/sigset-cvt-mask.h: New file.
* sysdeps/unix/sysv/linux/sigset-cvt-mask.h: New file.
* sysdeps/unix/sysv/sysv4/sigset-cvt-mask.h: New file.
* sysdeps/posix/sigvec.c: Rewrite the use definitions from
sigset-cvt-mask.h to do the dirty work.
Patches by Joe Keane.
* sysdeps/posix/mkstemp.c: Save one precious byte of rodata.
* sysdeps/unix/sysv/linux/i386/sysdep.h: Rewrite PSEUDO etc to make
syscall_error label in case of PIC anonymous.
* sysdeps/unix/sysv/linux/i386/i686/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/i386/clone.S: Adapt for this change.
* sysdeps/unix/sysv/linux/i386/mmap.S: Adapt for this change.
* sysdeps/unix/sysv/linux/i386/s_pread64.S: Adapt for this change.
* sysdeps/unix/sysv/linux/i386/s_pwrite64.S: Adapt for this change.
* sysdeps/unix/sysv/linux/i386/socket.S: Adapt for this change.
* sysdeps/unix/sysv/linux/i386/syscall.S: Adapt for this change.
75 files changed, 703 insertions, 295 deletions
@@ -1,3 +1,99 @@ +1998-06-07 13:32 Ulrich Drepper <drepper@cygnus.com> + + * libc.map: Add _dl_profile. + * elf/dl-reloc.c (_dl_relocate_object): Take extra argument, pass + this to ELF_DYNAMIC_RELOCATE. + Always allocate array for relocation result if LD_PROFILE is defined. + * elf/ldsodefs.h: Adjust prototypes. + * elf/dl-open.c (_dl_open): Call relocation function with extra + argument. + * elf/rtld.c: Likewise. + * elf/dl-profile.c (_dl_mcount): Don't mark as internal function. + Correct loop condition. + * elf/dynamic-link.h: Don't examine _dl_profile variable, pass + consider_profile to runtime setup function. + * sysdeps/i386/dl-machine.h (elf_machine_runtime_setup): Use + _dl_runtime_profile for all shared objects if LD_PROFILE is defined. + + * elf/dl-support.c: Define __libc_stack_end. + * elf/rtld.c: Likewise. + * sysdeps/generic/libc-start.c: Store last stack address in + __libc_stack_end. + * sysdeps/i386/dl-machine.h (_dl_start_user): Store stack address. + * sysdeps/i386/elf/start.s: Call __libc_start_main with extra argument. + + * elf/elf.h: Include <features.h>, not <sys/cdefs.h>. + Include <stdint.h>, not <inttypes.h>. + + * elf/sprof.c: Implement flat profiling. + + * libio/fgetc.c: Call _IO_cleanup_region_end with 0 and call + _IO_funlockfile explicitly. + * libio/fileops.c: Likewise. + * libio/fputc.c: Likewise. + * libio/freopen.c: Likewise. + * libio/freopen64.c: Likewise. + * libio/fseek.c: Likewise. + * libio/fseeko.c: Likewise. + * libio/fseeko64.c: Likewise. + * libio/ftello.c: Likewise. + * libio/ftello64.c: Likewise. + * libio/getc.c: Likewise. + * libio/getchar.c: Likewise. + * libio/iofclose.c: Likewise. + * libio/iofflush.c: Likewise. + * libio/iofgetpos.c: Likewise. + * libio/iofgetpos64.c: Likewise. + * libio/iofgets.c: Likewise. + * libio/iofputs.c: Likewise. + * libio/iofread.c: Likewise. + * libio/iofsetpos.c: Likewise. + * libio/iofsetpos64.c: Likewise. + * libio/ioftell.c: Likewise. + * libio/iofwrite.c: Likewise. + * libio/iogetdelim.c: Likewise. + * libio/iogets.c: Likewise. + * libio/ioputs.c: Likewise. + * libio/ioseekoff.c: Likewise. + * libio/ioseekpos.c: Likewise. + * libio/iosetbuffer.c: Likewise. + * libio/iosetvbuf.c: Likewise. + * libio/ioungetc.c: Likewise. + * libio/iovsprintf.c: Likewise. + * libio/iovsscanf.c: Likewise. + * libio/oldfileops.c: Likewise. + * libio/oldiofclose.c: Likewise. + * libio/peekc.c: Likewise. + * libio/putc.c: Likewise. + * libio/putchar.c: Likewise. + * libio/rewind.c: Likewise. + + * malloc/mtrace.c: Pretty print. + + * misc/mntent.h (struct mentent): Make string elements const char *. + + * nis/nis_printf.c: Optimize I/O a little bit. + + * signal/Makefile (distribute): Add sigset-cvt-mask.h. + * sysdeps/generic/sigset-cvt-mask.h: New file. + * sysdeps/unix/sysv/linux/sigset-cvt-mask.h: New file. + * sysdeps/unix/sysv/sysv4/sigset-cvt-mask.h: New file. + * sysdeps/posix/sigvec.c: Rewrite the use definitions from + sigset-cvt-mask.h to do the dirty work. + Patches by Joe Keane. + + * sysdeps/posix/mkstemp.c: Save one precious byte of rodata. + + * sysdeps/unix/sysv/linux/i386/sysdep.h: Rewrite PSEUDO etc to make + syscall_error label in case of PIC anonymous. + * sysdeps/unix/sysv/linux/i386/i686/sysdep.h: Likewise. + * sysdeps/unix/sysv/linux/i386/clone.S: Adapt for this change. + * sysdeps/unix/sysv/linux/i386/mmap.S: Adapt for this change. + * sysdeps/unix/sysv/linux/i386/s_pread64.S: Adapt for this change. + * sysdeps/unix/sysv/linux/i386/s_pwrite64.S: Adapt for this change. + * sysdeps/unix/sysv/linux/i386/socket.S: Adapt for this change. + * sysdeps/unix/sysv/linux/i386/syscall.S: Adapt for this change. + 1998-06-05 Ulrich Drepper <drepper@cygnus.com> * sunrpc/xdr_rec.c (xdrrec_create): Add cast for *_ops array since @@ -3330,10 +3330,14 @@ while test -n "$ac_sources"; do done EOF cat >> $CONFIG_STATUS <<EOF -echo '$config_vars' >> config.make; test -d bits || mkdir bits +config_vars='$config_vars' EOF cat >> $CONFIG_STATUS <<\EOF +case $CONFIG_FILES in *config.make*) +echo "$config_vars" >> config.make;; +esac +test -d bits || mkdir bits exit 0 EOF chmod +x $CONFIG_STATUS diff --git a/elf/dl-open.c b/elf/dl-open.c index 308175a..4c4c8ab 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -102,7 +102,8 @@ _dl_open (const char *file, int mode) asm ("" : "=r" (reloc) : "0" (reloc)); (*reloc) (l, _dl_object_relocation_scope (l), - (mode & RTLD_BINDING_MASK) == RTLD_LAZY); + ((mode & RTLD_BINDING_MASK) == RTLD_LAZY + || _dl_profile != NULL), _dl_profile != NULL); *_dl_global_scope_end = NULL; } diff --git a/elf/dl-profile.c b/elf/dl-profile.c index c7ac360..a9f8dd6 100644 --- a/elf/dl-profile.c +++ b/elf/dl-profile.c @@ -436,7 +436,6 @@ _dl_start_profile (struct link_map *map, const char *output_dir) void -internal_function _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc) { uint16_t *topcindex; @@ -479,7 +478,7 @@ _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc) /* We have to look through the chain of arcs whether there is already an entry for our arc. */ - while (fromp->here->from_pc == frompc) + while (fromp->here->from_pc != frompc) { if (fromp->link != 0) do @@ -523,8 +522,7 @@ _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc) data[newarc].self_pc = selfpc; data[newarc].count = 0; fromp->link = 0; - - narcs++; + ++narcs; break; } diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index 898fb48..e0eae3c 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -28,7 +28,8 @@ void internal_function -_dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy) +_dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy, + int consider_profiling) { if (l->l_relocated) return; @@ -72,9 +73,9 @@ _dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy) l->l_name, (flags))) #include "dynamic-link.h" - ELF_DYNAMIC_RELOCATE (l, lazy, 1); + ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling); - if (_dl_profile_map == l) + if (_dl_profile != NULL) { /* Allocate the array which will contain the already found relocations. */ diff --git a/elf/dl-support.c b/elf/dl-support.c index 9012a0c..85f656c 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -58,6 +58,9 @@ struct link_map *_dl_profile_map; /* Names of shared object for which the RPATHs should be ignored. */ const char *_dl_inhibit_rpath; +/* This is the address of the last stack address ever used. */ +void *__libc_stack_end; + static void non_dynamic_init (void) __attribute__ ((unused)); diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index aedee20..9d7ae3d 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -1,5 +1,5 @@ /* Inline functions for dynamic linking. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997, 1998 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 @@ -161,10 +161,8 @@ elf_get_dynamic_info (ElfW(Dyn) *dyn, to inline functions containing inlines themselves. */ #define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile) \ do { \ - int profile = (consider_profile && _dl_profile != NULL \ - && _dl_name_match_p (_dl_profile, (map))); \ - int edr_lazy = elf_machine_runtime_setup ((map), (lazy) || profile, \ - profile); \ + int edr_lazy = elf_machine_runtime_setup ((map), (lazy), \ + (consider_profile)); \ ELF_DYNAMIC_DO_REL ((map), edr_lazy); \ ELF_DYNAMIC_DO_RELA ((map), edr_lazy); \ } while (0) @@ -1,5 +1,5 @@ /* This file defines standard ELF types, structures, and macros. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ian Lance Taylor <ian@cygnus.com>. @@ -21,13 +21,13 @@ #ifndef _ELF_H #define _ELF_H 1 -#include <sys/cdefs.h> +#include <features.h> __BEGIN_DECLS /* Standard ELF types. */ -#include <inttypes.h> +#include <stdint.h> /* Type for a 16-bit quantity. */ typedef uint16_t Elf32_Half; diff --git a/elf/ldsodefs.h b/elf/ldsodefs.h index a2bfc0b..45c2a5e 100644 --- a/elf/ldsodefs.h +++ b/elf/ldsodefs.h @@ -363,7 +363,8 @@ extern struct link_map *_dl_new_object (char *realname, const char *libname, If LAZY is nonzero, don't relocate its PLT. */ extern void _dl_relocate_object (struct link_map *map, struct link_map *scope[], - int lazy) internal_function; + int lazy, int consider_profiling) + internal_function; /* Check the version dependencies of all objects available through MAP. If VERBOSE print some more diagnostics. */ @@ -406,8 +407,7 @@ extern void _dl_start_profile (struct link_map *map, const char *output_dir) internal_function; /* The actual functions used to keep book on the calls. */ -extern void _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc) - internal_function; +extern void _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc); /* Show the members of the auxiliary array passed up from the kernel. */ @@ -93,6 +93,9 @@ const char *_dl_inhibit_rpath; /* RPATH values which should be never be called. */ int _dl_starting_up; +/* This variable contains the lowest stack address ever used. */ +void *__libc_stack_end; + static void dl_main (const ElfW(Phdr) *phdr, ElfW(Half) phent, ElfW(Addr) *user_entry); @@ -201,7 +204,7 @@ relocate_doit (void *a) struct relocate_args *args = (struct relocate_args *) a; _dl_relocate_object (args->l, _dl_object_relocation_scope (args->l), - args->lazy); + args->lazy, 0); } static void @@ -852,6 +855,11 @@ of this helper program; chances are you did not intend to run this program.\n\ know that because it is self-contained). */ struct link_map *l; + int consider_profiling = _dl_profile != NULL; + + /* If we are profiling we also must do lazy reloaction. */ + lazy |= consider_profiling; + l = _dl_loaded; while (l->l_next) l = l->l_next; @@ -859,7 +867,8 @@ of this helper program; chances are you did not intend to run this program.\n\ { if (l != &_dl_rtld_map) { - _dl_relocate_object (l, _dl_object_relocation_scope (l), lazy); + _dl_relocate_object (l, _dl_object_relocation_scope (l), lazy, + consider_profiling); *_dl_global_scope_end = NULL; } l = l->l_prev; @@ -875,7 +884,7 @@ of this helper program; chances are you did not intend to run this program.\n\ if (_dl_rtld_map.l_opencount > 0) /* There was an explicit ref to the dynamic linker as a shared lib. Re-relocate ourselves with user-controlled symbol definitions. */ - _dl_relocate_object (&_dl_rtld_map, &_dl_default_scope[2], 0); + _dl_relocate_object (&_dl_rtld_map, &_dl_default_scope[2], 0, 0); } { diff --git a/elf/sprof.c b/elf/sprof.c index 95e9664..477d95a 100644 --- a/elf/sprof.c +++ b/elf/sprof.c @@ -68,15 +68,15 @@ extern int __profile_frequency __P ((void)); static void print_version (FILE *stream, struct argp_state *state); void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; -#define OPT_COUNT_TOTAL 1 -#define OPT_TEST 2 +#define OPT_TEST 1 /* Definitions of arguments for argp functions. */ static const struct argp_option options[] = { { NULL, 0, NULL, 0, N_("Output selection:") }, - { "count-total", OPT_COUNT_TOTAL, NULL, 0, - N_("print number of invocations for each function") }, + { "flat-profile", 'p', NULL, 0, + N_("generate flat profile with counts and ticks") }, + { "test", OPT_TEST, NULL, OPTION_HIDDEN, NULL }, { NULL, 0, NULL, 0, NULL } }; @@ -101,7 +101,9 @@ static struct argp argp = static enum { NONE = 0, - COUNT_TOTAL + FLAT_MODE = 1 << 0, + + DEFAULT_MODE = FLAT_MODE } mode; /* If nonzero the total number of invocations of a function is emitted. */ @@ -135,6 +137,7 @@ struct known_symbol size_t size; uintmax_t ticks; + uintmax_t calls; }; @@ -173,6 +176,7 @@ struct profdata off_t size; char *hist; + struct gmon_hist_hdr *hist_hdr; uint16_t *kcount; uint32_t narcs; /* Number of arcs in toset. */ struct here_cg_arc_record *data; @@ -192,7 +196,9 @@ static void unload_shobj (struct shobj *shobj); static struct profdata *load_profdata (const char *name, struct shobj *shobj); static void unload_profdata (struct profdata *profdata); static void count_total_ticks (struct shobj *shobj, struct profdata *profdata); +static void count_calls (struct shobj *shobj, struct profdata *profdata); static void read_symbols (struct shobj *shobj); +static void generate_flat_profile (struct profdata *profdata); int @@ -266,26 +272,19 @@ no filename for profiling data given and shared object `%s' has no soname"), read_symbols (shobj_handle); + /* Count the ticks. */ + count_total_ticks (shobj_handle, profdata_handle); + + /* Count the calls. */ + count_calls (shobj_handle, profdata_handle); + + /* If no mode is specified fall back to the default mode. */ + if (mode == NONE) + mode = DEFAULT_MODE; + /* Do some work. */ - switch (mode) - { - case COUNT_TOTAL: - count_total_ticks (shobj_handle, profdata_handle); - { - size_t n; - for (n = 0; n < symidx; ++n) - if (sortsym[n]->ticks != 0) - printf ("Name: %-30s, Ticks: %" PRIdMAX "\n", sortsym[n]->name, - sortsym[n]->ticks); - printf ("Total ticks: %" PRIdMAX "\n", total_ticks); - } - break; - case NONE: - /* Do nothing. */ - break; - default: - assert (! "Internal error"); - } + if (mode & FLAT_MODE) + generate_flat_profile (profdata_handle); /* Free the resources. */ unload_shobj (shobj_handle); @@ -301,9 +300,6 @@ parse_opt (int key, char *arg, struct argp_state *state) { switch (key) { - case OPT_COUNT_TOTAL: - mode = COUNT_TOTAL; - break; case OPT_TEST: do_test = 1; break; @@ -689,6 +685,8 @@ load_profdata (const char *name, struct shobj *shobj) /* Pointer to data after the header. */ result->hist = (char *) ((struct gmon_hdr *) addr + 1); + result->hist_hdr = (struct gmon_hist_hdr *) ((char *) result->hist + + sizeof (uint32_t)); result->kcount = (uint16_t *) ((char *) result->hist + sizeof (uint32_t) + sizeof (struct gmon_hist_hdr)); @@ -709,7 +707,7 @@ load_profdata (const char *name, struct shobj *shobj) *(char **) hist_hdr.high_pc = (char *) shobj->highpc - shobj->map->l_addr; if (do_test) printf ("low_pc = %p\nhigh_pc = %p\n", - hist_hdr.low_pc, hist_hdr.high_pc); + *(char **) hist_hdr.low_pc, *(char **) hist_hdr.high_pc); *(int32_t *) hist_hdr.hist_size = shobj->kcountsize / sizeof (HISTCOUNTER); *(int32_t *) hist_hdr.prof_rate = __profile_frequency (); strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen)); @@ -718,7 +716,7 @@ load_profdata (const char *name, struct shobj *shobj) /* Test whether the header of the profiling data is ok. */ if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0 || *(uint32_t *) result->hist != GMON_TAG_TIME_HIST - || memcmp (result->hist + sizeof (uint32_t), &hist_hdr, + || memcmp (result->hist_hdr, &hist_hdr, sizeof (struct gmon_hist_hdr)) != 0 || narcsp[-1] != GMON_TAG_CG_ARC) { @@ -802,6 +800,49 @@ count_total_ticks (struct shobj *shobj, struct profdata *profdata) } +static struct known_symbol * +find_symbol (uintptr_t addr) +{ + size_t sidx = 0; + + while (sidx < symidx) + { + uintptr_t start = sortsym[sidx]->addr; + uintptr_t end = start + sortsym[sidx]->size; + + if (addr >= start && addr < end) + return sortsym[sidx]; + + if (addr < start) + break; + + ++sidx; + } + + return NULL; +} + + +static void +count_calls (struct shobj *shobj, struct profdata *profdata) +{ + struct here_cg_arc_record *data = profdata->data; + uint32_t narcs = profdata->narcs; + uint32_t cnt; + + for (cnt = 0; cnt < narcs; ++cnt) + { + uintptr_t here = data[cnt].self_pc; + struct known_symbol *symbol; + + /* Find the symbol for this address. */ + symbol = find_symbol (here); + if (symbol != NULL) + symbol->calls += data[cnt].count; + } +} + + static int symorder (const void *o1, const void *o2) { @@ -843,6 +884,7 @@ read_symbols (struct shobj *shobj) || ELFW(ST_TYPE) (sym->st_info) == STT_NOTYPE) && sym->st_size != 0) { + struct known_symbol **existp; struct known_symbol *newsym = (struct known_symbol *) obstack_alloc (&shobj->ob_sym, sizeof (*newsym)); @@ -853,9 +895,25 @@ read_symbols (struct shobj *shobj) newsym->addr = sym->st_value; newsym->size = sym->st_size; newsym->ticks = 0; - - tsearch (newsym, &symroot, symorder); - ++n; + newsym->calls = 0; + + existp = tfind (newsym, &symroot, symorder); + if (existp == NULL) + { + /* New function. */ + tsearch (newsym, &symroot, symorder); + ++n; + } + else + { + /* The function is already defined. See whether we have + a better name here. */ + if ((*existp)->name[0] == '_' && newsym->name[0] != '_') + *existp = newsym; + else + /* We don't need the allocated memory. */ + obstack_free (&shobj->ob_sym, newsym); + } } } else @@ -872,11 +930,12 @@ read_symbols (struct shobj *shobj) dynamic symbol table!! */ while ((void *) symtab < (void *) strtab) { - if (/*(ELFW(ST_TYPE)(symtab->st_info) == STT_FUNC - || ELFW(ST_TYPE)(symtab->st_info) == STT_NOTYPE) - &&*/ symtab->st_size != 0) + if ((ELFW(ST_TYPE)(symtab->st_info) == STT_FUNC + || ELFW(ST_TYPE)(symtab->st_info) == STT_NOTYPE) + && symtab->st_size != 0) { struct known_symbol *newsym; + struct known_symbol **existp; newsym = (struct known_symbol *) obstack_alloc (&shobj->ob_sym, @@ -889,8 +948,23 @@ read_symbols (struct shobj *shobj) newsym->size = symtab->st_size; newsym->ticks = 0; - tsearch (newsym, &symroot, symorder); - ++n; + existp = tfind (newsym, &symroot, symorder); + if (existp == NULL) + { + /* New function. */ + tsearch (newsym, &symroot, symorder); + ++n; + } + else + { + /* The function is already defined. See whether we have + a better name here. */ + if ((*existp)->name[0] == '_' && newsym->name[0] != '_') + *existp = newsym; + else + /* We don't need the allocated memory. */ + obstack_free (&shobj->ob_sym, newsym); + } } } @@ -903,3 +977,75 @@ read_symbols (struct shobj *shobj) twalk (symroot, printsym); } + + +static int +countorder (const void *p1, const void *p2) +{ + struct known_symbol *s1 = (struct known_symbol *) p1; + struct known_symbol *s2 = (struct known_symbol *) p2; + + if (s1->ticks != s2->ticks) + return (int) (s2->ticks - s1->ticks); + + if (s1->calls != s2->calls) + return (int) (s2->calls - s1->calls); + + return strcmp (s1->name, s2->name); +} + + +static double tick_unit; +static uintmax_t cumu_ticks; + +static void +printflat (const void *node, VISIT value, int level) +{ + if (value == leaf || value == postorder) + { + struct known_symbol *s = *(struct known_symbol **) node; + + cumu_ticks += s->ticks; + + printf ("%6.2f%10.2f%9.2f%9" PRIdMAX "%9.2f%9.2f %s\n", + total_ticks ? (100.0 * s->ticks) / total_ticks : 0.0, + tick_unit * cumu_ticks, + tick_unit * s->ticks, + s->calls, + s->calls ? (s->ticks * 1000000) * tick_unit / s->calls : 0, + 0.0, /* FIXME: don't know about called functions. */ + s->name); + } +} + + +/* ARGUSED */ +static void +freenoop (void *p) +{ +} + + +static void +generate_flat_profile (struct profdata *profdata) +{ + size_t n; + void *data = NULL; + + tick_unit = 1.0 / *(uint32_t *) profdata->hist_hdr->prof_rate; + + printf ("Flat profile:\n\n" + "Each sample counts as %g %s.\n", + tick_unit, profdata->hist_hdr->dimen); + fputs (" % cumulative self self total\n" + " time seconds seconds calls us/call us/call name\n", + stdout); + + for (n = 0; n < symidx; ++n) + if (sortsym[n]->calls != 0 || sortsym[n]->ticks != 0) + tsearch (sortsym[n], &data, countorder); + + twalk (data, printflat); + + tdestroy (data, freenoop); +} @@ -474,6 +474,7 @@ GLIBC_2.1 { # global variables _IO_2_1_stdin_; _IO_2_1_stdout_; _IO_2_1_stderr_; __gconv_alias_db; __gconv_nmodules; __gconv_modules_db; + _dl_profile; # This is for ix86 only. _fp_hw; @@ -489,6 +490,7 @@ GLIBC_2.1 { __syscall_rt_sigqueueinfo; __xstat64; __fxstat64; __lxstat64; __pread64; __pwrite64; + __backtrace; __backtracesyms; # helper functions __libc_current_sigrtmin; __libc_current_sigrtmax; __libc_allocate_rtsig; @@ -533,6 +535,9 @@ GLIBC_2.1 { authdes_create; authdes_getucred; authdes_pk_create; + # b* + backtrace; backtracesyms; + # c* capget; capset; cbc_crypt; creat64; diff --git a/libio/fgetc.c b/libio/fgetc.c index 174e60f..094c5fe 100644 --- a/libio/fgetc.c +++ b/libio/fgetc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -35,6 +35,7 @@ fgetc (fp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); result = _IO_getc_unlocked (fp); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/fileops.c b/libio/fileops.c index e5ffb24..1219abe 100644 --- a/libio/fileops.c +++ b/libio/fileops.c @@ -460,7 +460,8 @@ _IO_file_sync (fp) fp->_offset = _IO_pos_BAD; /* FIXME: Cleanup - can this be shared? */ /* setg(base(), ptr, ptr); */ - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return retval; } diff --git a/libio/fputc.c b/libio/fputc.c index 22cdfab..3ec8b69 100644 --- a/libio/fputc.c +++ b/libio/fputc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -36,6 +36,7 @@ fputc (c, fp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); result = _IO_putc_unlocked (c, fp); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/freopen.c b/libio/freopen.c index 0452e7e..22f2434 100644 --- a/libio/freopen.c +++ b/libio/freopen.c @@ -54,6 +54,7 @@ freopen (filename, mode, fp) else #endif result = _IO_freopen (filename, mode, fp); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/freopen64.c b/libio/freopen64.c index 78e994d..c521631 100644 --- a/libio/freopen64.c +++ b/libio/freopen64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -40,7 +40,8 @@ freopen64 (filename, mode, fp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); result = _IO_freopen64 (filename, mode, fp); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; #else __set_errno (ENOSYS); diff --git a/libio/fseek.c b/libio/fseek.c index f2563d3..f928457 100644 --- a/libio/fseek.c +++ b/libio/fseek.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -37,6 +37,7 @@ fseek (fp, offset, whence) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); result = _IO_fseek (fp, offset, whence); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/fseeko.c b/libio/fseeko.c index 0ebdfa9..1836047 100644 --- a/libio/fseeko.c +++ b/libio/fseeko.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -37,6 +37,7 @@ fseeko (fp, offset, whence) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); result = _IO_fseek (fp, offset, whence); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/fseeko64.c b/libio/fseeko64.c index 81c17b3..55699ae 100644 --- a/libio/fseeko64.c +++ b/libio/fseeko64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -39,7 +39,8 @@ fseeko64 (fp, offset, whence) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); result = _IO_fseek (fp, offset, whence); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; #else __set_errno (ENOSYS); diff --git a/libio/ftello.c b/libio/ftello.c index 7585eea..662b954 100644 --- a/libio/ftello.c +++ b/libio/ftello.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -37,7 +37,8 @@ ftello (fp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); if (pos == _IO_pos_BAD) { #ifdef EIO diff --git a/libio/ftello64.c b/libio/ftello64.c index 886591d..96eeb18 100644 --- a/libio/ftello64.c +++ b/libio/ftello64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -38,7 +38,8 @@ ftello64 (fp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); if (pos == _IO_pos_BAD) { #ifdef EIO diff --git a/libio/getc.c b/libio/getc.c index 1dc53b5e..81a4b52 100644 --- a/libio/getc.c +++ b/libio/getc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -37,7 +37,8 @@ _IO_getc (fp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); result = _IO_getc_unlocked (fp); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/getchar.c b/libio/getchar.c index 93194b3..fdc2ec3 100644 --- a/libio/getchar.c +++ b/libio/getchar.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -33,8 +33,9 @@ getchar () { int result; _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, stdin); - _IO_flockfile (stdin); + _IO_flockfile (_IO_stdin); result = _IO_getc_unlocked (stdin); - _IO_cleanup_region_end (1); + _IO_funlockfile (_IO_stdin); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/iofclose.c b/libio/iofclose.c index 7100425..f896e09 100644 --- a/libio/iofclose.c +++ b/libio/iofclose.c @@ -43,7 +43,8 @@ _IO_new_fclose (fp) else status = fp->_flags & _IO_ERR_SEEN ? -1 : 0; _IO_FINISH (fp); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); if (fp != _IO_stdin && fp != _IO_stdout && fp != _IO_stderr) { fp->_IO_file_flags = 0; diff --git a/libio/iofflush.c b/libio/iofflush.c index 540c99d..724ff26 100644 --- a/libio/iofflush.c +++ b/libio/iofflush.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -39,7 +39,8 @@ _IO_fflush (fp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); result = _IO_SYNC (fp) ? EOF : 0; - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; } } diff --git a/libio/iofgetpos.c b/libio/iofgetpos.c index 6afc323..5fed6c3 100644 --- a/libio/iofgetpos.c +++ b/libio/iofgetpos.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -36,7 +36,8 @@ _IO_fgetpos (fp, posp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); if (pos == _IO_pos_BAD) { /* ANSI explicitly requires setting errno to a positive value on diff --git a/libio/iofgetpos64.c b/libio/iofgetpos64.c index 0cb79d6..8a7733b 100644 --- a/libio/iofgetpos64.c +++ b/libio/iofgetpos64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -37,7 +37,8 @@ _IO_fgetpos64 (fp, posp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); if (pos == _IO_pos_BAD) { /* ANSI explicitly requires setting errno to a positive value on diff --git a/libio/iofgets.c b/libio/iofgets.c index 91db09f..d61fb81 100644 --- a/libio/iofgets.c +++ b/libio/iofgets.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -54,7 +54,8 @@ _IO_fgets (buf, n, fp) result = buf; } fp->_IO_file_flags |= old_error; - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/iofputs.c b/libio/iofputs.c index 1a329bb..1805387 100644 --- a/libio/iofputs.c +++ b/libio/iofputs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -40,7 +40,8 @@ _IO_fputs (str, fp) result = EOF; else result = 1; - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/iofread.c b/libio/iofread.c index c83d2b6..3664006 100644 --- a/libio/iofread.c +++ b/libio/iofread.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -40,7 +40,8 @@ _IO_fread (buf, size, count, fp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); bytes_read = _IO_sgetn (fp, (char *) buf, bytes_requested); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return bytes_requested == bytes_read ? count : bytes_read / size; } diff --git a/libio/iofsetpos.c b/libio/iofsetpos.c index a8d816f..cbf7734 100644 --- a/libio/iofsetpos.c +++ b/libio/iofsetpos.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -47,7 +47,8 @@ _IO_fsetpos (fp, posp) } else result = 0; - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/iofsetpos64.c b/libio/iofsetpos64.c index 534e0cf..13ce0fb 100644 --- a/libio/iofsetpos64.c +++ b/libio/iofsetpos64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -48,7 +48,8 @@ _IO_fsetpos64 (fp, posp) } else result = 0; - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; #else __set_errno (ENOSYS); diff --git a/libio/ioftell.c b/libio/ioftell.c index d8a1ce1..3a0e7a6 100644 --- a/libio/ioftell.c +++ b/libio/ioftell.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -36,7 +36,8 @@ _IO_ftell (fp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); if (pos == _IO_pos_BAD) { #ifdef EIO diff --git a/libio/iofwrite.c b/libio/iofwrite.c index 5bc525f..0f82797 100644 --- a/libio/iofwrite.c +++ b/libio/iofwrite.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -40,7 +40,8 @@ _IO_fwrite (buf, size, count, fp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); written = _IO_sputn (fp, (const char *) buf, request); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); /* Many traditional implementations return 0 if size==0 && count > 0, but ANSI requires us to return count in this case. */ if (written == request) diff --git a/libio/iogetdelim.c b/libio/iogetdelim.c index 50918b3..56524d6 100644 --- a/libio/iogetdelim.c +++ b/libio/iogetdelim.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -115,7 +115,8 @@ _IO_getdelim (lineptr, n, delimiter, fp) result = cur_len; unlock_return: - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/iogets.c b/libio/iogets.c index a61699d..b36d29b 100644 --- a/libio/iogets.c +++ b/libio/iogets.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -65,7 +65,8 @@ _IO_gets (buf) buf[count] = 0; retval = buf; unlock_return: - _IO_cleanup_region_end (1); + _IO_funlockfile (_IO_stdin); + _IO_cleanup_region_end (0); return retval; } diff --git a/libio/ioputs.c b/libio/ioputs.c index ab5e6aa..9ed8fe6 100644 --- a/libio/ioputs.c +++ b/libio/ioputs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -40,7 +40,8 @@ _IO_puts (str) result = len + 1; else result = EOF; - _IO_cleanup_region_end (1); + _IO_funlockfile (_IO_stdout); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/ioseekoff.c b/libio/ioseekoff.c index 13086ee..b83e1ad 100644 --- a/libio/ioseekoff.c +++ b/libio/ioseekoff.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -49,6 +49,7 @@ _IO_seekoff (fp, offset, dir, mode) } retval = _IO_SEEKOFF (fp, offset, dir, mode); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return retval; } diff --git a/libio/ioseekpos.c b/libio/ioseekpos.c index 5b59ed7..c81c333 100644 --- a/libio/ioseekpos.c +++ b/libio/ioseekpos.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -43,6 +43,7 @@ _IO_seekpos (fp, pos, mode) _IO_free_backup_area (fp); retval = _IO_SEEKPOS (fp, pos, mode); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return retval; } diff --git a/libio/iosetbuffer.c b/libio/iosetbuffer.c index f140a9a..d615da5 100644 --- a/libio/iosetbuffer.c +++ b/libio/iosetbuffer.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -38,7 +38,8 @@ _IO_setbuffer (fp, buf, size) if (!buf) size = 0; (void) _IO_SETBUF (fp, buf, size); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); } #ifdef weak_alias diff --git a/libio/iosetvbuf.c b/libio/iosetvbuf.c index 65eeea5..02f4eef 100644 --- a/libio/iosetvbuf.c +++ b/libio/iosetvbuf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -91,7 +91,8 @@ _IO_setvbuf (fp, buf, mode, size) } result = _IO_SETBUF (fp, buf, size) == NULL ? EOF : 0; unlock_return: - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/ioungetc.c b/libio/ioungetc.c index 07f38e7..abc27ff 100644 --- a/libio/ioungetc.c +++ b/libio/ioungetc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -37,7 +37,8 @@ _IO_ungetc (c, fp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); result = _IO_sputbackc (fp, (unsigned char) c); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/iovsprintf.c b/libio/iovsprintf.c index 3491958..a1ece2d 100644 --- a/libio/iovsprintf.c +++ b/libio/iovsprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -44,11 +44,8 @@ _IO_vsprintf (string, format, args) _IO_init (&sf._sbf._f, 0); _IO_JUMPS (&sf._sbf._f) = &_IO_str_jumps; _IO_str_init_static (&sf._sbf._f, string, -1, string); - _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, &sf); - _IO_flockfile (&sf._sbf._f); ret = _IO_vfprintf (&sf._sbf._f, format, args); _IO_putc_unlocked ('\0', &sf._sbf._f); - _IO_cleanup_region_end (1); return ret; } diff --git a/libio/iovsscanf.c b/libio/iovsscanf.c index 1917d63..923e829 100644 --- a/libio/iovsscanf.c +++ b/libio/iovsscanf.c @@ -41,10 +41,7 @@ _IO_vsscanf (string, format, args) _IO_init (&sf._sbf._f, 0); _IO_JUMPS (&sf._sbf._f) = &_IO_str_jumps; _IO_str_init_static (&sf._sbf._f, (char*)string, 0, NULL); - _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, &sf); - _IO_flockfile (&sf._sbf._f); ret = _IO_vfscanf (&sf._sbf._f, format, args, NULL); - _IO_cleanup_region_end (1); return ret; } diff --git a/libio/oldfileops.c b/libio/oldfileops.c index 7cf4fdf..251dc78 100644 --- a/libio/oldfileops.c +++ b/libio/oldfileops.c @@ -426,7 +426,8 @@ _IO_old_file_sync (fp) fp->_old_offset = _IO_pos_BAD; /* FIXME: Cleanup - can this be shared? */ /* setg(base(), ptr, ptr); */ - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return retval; } diff --git a/libio/oldiofclose.c b/libio/oldiofclose.c index 5f3e102..e256d57 100644 --- a/libio/oldiofclose.c +++ b/libio/oldiofclose.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -44,7 +44,8 @@ _IO_old_fclose (fp) else status = fp->_flags & _IO_ERR_SEEN ? -1 : 0; _IO_FINISH (fp); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); if (fp != _IO_stdin && fp != _IO_stdout && fp != _IO_stderr) { fp->_IO_file_flags = 0; diff --git a/libio/peekc.c b/libio/peekc.c index 0b3b514..8ad274e 100644 --- a/libio/peekc.c +++ b/libio/peekc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -37,6 +37,7 @@ _IO_peekc_locked (fp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); result = _IO_peekc_unlocked (fp); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/putc.c b/libio/putc.c index 3c35c36..72cd2a1 100644 --- a/libio/putc.c +++ b/libio/putc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1995, 1996, 1997, 1998 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 @@ -31,7 +31,8 @@ _IO_putc (c, fp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); result = _IO_putc_unlocked (c, fp); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/putchar.c b/libio/putchar.c index 1e1dd13..143796d 100644 --- a/libio/putchar.c +++ b/libio/putchar.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1995, 1996, 1997, 1998 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 @@ putchar (c) _IO_stdout); _IO_flockfile (_IO_stdout); result = _IO_putc_unlocked (c, _IO_stdout); - _IO_cleanup_region_end (1); + _IO_funlockfile (_IO_stdout); + _IO_cleanup_region_end (0); return result; } diff --git a/libio/rewind.c b/libio/rewind.c index bce2757..fb6afbc 100644 --- a/libio/rewind.c +++ b/libio/rewind.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -34,5 +34,6 @@ rewind (fp) _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); _IO_rewind (fp); - _IO_cleanup_region_end (1); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); } diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index 4b4de6a..c89ef1e 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,7 @@ +1998-06-07 13:47 Ulrich Drepper <drepper@cygnus.com> + + * sysdeps/pthread/bits/libc-lock.h: Optimize cleanup handlers a bit. + 1998-06-03 Andreas Jaeger <aj@arthur.rhein-neckar.de> * attr.c: Correct typo. diff --git a/linuxthreads/sysdeps/pthread/bits/libc-lock.h b/linuxthreads/sysdeps/pthread/bits/libc-lock.h index 530d48c..ed64cbf 100644 --- a/linuxthreads/sysdeps/pthread/bits/libc-lock.h +++ b/linuxthreads/sysdeps/pthread/bits/libc-lock.h @@ -1,5 +1,5 @@ /* libc-internal interface for mutex locks. LinuxThreads version. - Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998 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 @@ -119,13 +119,14 @@ typedef pthread_key_t __libc_key_t; /* Start critical region with cleanup. */ #define __libc_cleanup_region_start(FCT, ARG) \ { struct _pthread_cleanup_buffer _buffer; \ - if (_pthread_cleanup_push_defer != NULL) { \ + int _avail = _pthread_cleanup_push_defer != NULL; \ + if (_avail) { \ _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG)); \ } /* End critical region with cleanup. */ #define __libc_cleanup_region_end(DOIT) \ - if (_pthread_cleanup_push_defer != NULL) { \ + if (_avail) { \ _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ } \ } diff --git a/malloc/mtrace.c b/malloc/mtrace.c index f3c1387..64fb62a 100644 --- a/malloc/mtrace.c +++ b/malloc/mtrace.c @@ -146,7 +146,7 @@ tr_mallochook (size, caller) tr_where (caller); /* We could be printing a NULL here; that's OK. */ - fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long)size); + fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size); if (hdr == mallwatch) tr_break (); @@ -184,11 +184,12 @@ tr_reallochook (ptr, size, caller) tr_where (caller); if (hdr == NULL) /* Failed realloc. */ - fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long)size); + fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) size); else if (ptr == NULL) - fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long)size); + fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size); else - fprintf (mallstream, "< %p\n> %p %#lx\n", ptr, hdr, (unsigned long)size); + fprintf (mallstream, "< %p\n> %p %#lx\n", ptr, hdr, + (unsigned long int) size); if (hdr == mallwatch) tr_break (); diff --git a/misc/mntent.h b/misc/mntent.h index fc93022..1d079a3 100644 --- a/misc/mntent.h +++ b/misc/mntent.h @@ -1,5 +1,5 @@ /* Utilities for reading/writing fstab, mtab, etc. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997, 1998 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 @@ -53,10 +53,10 @@ __BEGIN_DECLS /* Structure describing a mount table entry. */ struct mntent { - char *mnt_fsname; /* Device or server for filesystem. */ - char *mnt_dir; /* Directory mounted on. */ - char *mnt_type; /* Type of filesystem: ufs, nfs, etc. */ - char *mnt_opts; /* Comma-separated options for fs. */ + const char *mnt_fsname; /* Device or server for filesystem. */ + const char *mnt_dir; /* Directory mounted on. */ + const char *mnt_type; /* Type of filesystem: ufs, nfs, etc. */ + const char *mnt_opts; /* Comma-separated options for fs. */ int mnt_freq; /* Dump frequency (in days). */ int mnt_passno; /* Pass number for `fsck'. */ }; diff --git a/nis/nis_print.c b/nis/nis_print.c index 5aa43c3..01a2d9d 100644 --- a/nis/nis_print.c +++ b/nis/nis_print.c @@ -1,4 +1,4 @@ -/* Copyright (c) 1997 Free Software Foundation, Inc. +/* Copyright (c) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. @@ -150,7 +150,7 @@ nis_print_rights (const u_long access) acc >>= 8; } - printf ("%s", result); + fputs (result, stdout); } void @@ -176,20 +176,19 @@ nis_print_directory (const directory_obj *dir) fputs (_("None.\n"), stdout); break; case NIS_PK_DH: - fprintf (stdout, _("Diffie-Hellmann (%d bits)\n"), - (sptr->pkey.n_len - 1) * 4); + printf (_("Diffie-Hellmann (%d bits)\n"), + (sptr->pkey.n_len - 1) * 4); /* sptr->pkey.n_len counts the last 0, too */ break; case NIS_PK_RSA: - fprintf (stdout, _("RSA (%d bits)\n"), - (sptr->pkey.n_len - 1) * 4); + printf (_("RSA (%d bits)\n"), (sptr->pkey.n_len - 1) * 4); break; case NIS_PK_KERB: fputs (_("Kerberos.\n"), stdout); break; default: - fprintf (stdout, _("Unknown (type = %d, bits = %d)\n"), - sptr->key_type, (sptr->pkey.n_len - 1) * 4); + printf (_("Unknown (type = %d, bits = %d)\n"), sptr->key_type, + (sptr->pkey.n_len - 1) * 4); break; } @@ -214,7 +213,7 @@ nis_print_directory (const directory_obj *dir) if (ptr->uaddr != NULL && strlen (ptr->uaddr) > 0) printf ("%s\n", ptr->uaddr); else - printf ("-\n"); + fputs ("-\n", stdout); ptr++; } } @@ -233,7 +232,7 @@ nis_print_directory (const directory_obj *dir) { nis_print_rights (ptr->oa_rights); printf (_("\tType : %s\n"), nis_nstype2str (ptr->oa_otype)); - printf (_("\tAccess rights: ")); + fputs (_("\tAccess rights: "), stdout); nis_print_rights (ptr->oa_rights); fputs ("\n", stdout); ptr++; diff --git a/signal/Makefile b/signal/Makefile index cec0782..ee15a2c 100644 --- a/signal/Makefile +++ b/signal/Makefile @@ -38,7 +38,7 @@ routines := signal raise killpg \ tests := tst-signal -distribute := sigsetops.h testrtsig.h +distribute := sigsetops.h testrtsig.h sigset-cvt-mask.h include ../Rules diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index 85558a1..a40acb7 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -1472,7 +1472,12 @@ do_positional: all_done: /* Unlock the stream. */ - __libc_cleanup_region_end (1); +#ifdef USE_IN_LIBIO + _IO_funlockfile (s); +#else + __funlockfile (s); +#endif + __libc_cleanup_region_end (0); return done; } diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c index 7666c87..c1ff269 100644 --- a/stdio-common/vfscanf.c +++ b/stdio-common/vfscanf.c @@ -100,7 +100,9 @@ # define LOCK_STREAM(S) \ __libc_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, (S)); \ _IO_flockfile (S) -# define UNLOCK_STREAM __libc_cleanup_region_end (1) +# define UNLOCK_STREAM(S) \ + _IO_funlockfile (S); \ + __libc_cleanup_region_end (0) #else # define ungetc(c, s) ((void) (c != EOF && --read_in), ungetc (c, s)) # define inchar() (c == EOF ? EOF \ @@ -143,12 +145,14 @@ # define flockfile(S) /* nothing */ # define funlockfile(S) /* nothing */ # define LOCK_STREAM(S) -# define UNLOCK_STREAM +# define UNLOCK_STREAM(S) #else # define LOCK_STREAM(S) \ __libc_cleanup_region_start (&__funlockfile, (S)); \ __flockfile (S) -# define UNLOCK_STREAM __libc_cleanup_region_end (1) +# define UNLOCK_STREAM(S) \ + __funlockfile (S); \ + __libc_cleanup_region_end (0) #endif #endif @@ -1216,7 +1220,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) } /* Unlock stream. */ - UNLOCK_STREAM; + UNLOCK_STREAM (s); return done; } diff --git a/sysdeps/generic/libc-start.c b/sysdeps/generic/libc-start.c index 3225a7c..1e07929 100644 --- a/sysdeps/generic/libc-start.c +++ b/sysdeps/generic/libc-start.c @@ -25,11 +25,12 @@ extern void __libc_init_first (int argc, char **argv, char **envp); extern int _dl_starting_up; weak_extern (_dl_starting_up) extern int __libc_multiple_libcs; +extern void *__libc_stack_end; int __libc_start_main (int (*main) (int, char **, char **), int argc, char **argv, void (*init) (void), void (*fini) (void), - void (*rtld_fini) (void)) + void (*rtld_fini) (void), void *stack_end) { #ifndef PIC /* The next variable is only here to work around a bug in gcc <= 2.7.2.2. @@ -38,6 +39,9 @@ __libc_start_main (int (*main) (int, char **, char **), int argc, int *dummy_addr = &_dl_starting_up; __libc_multiple_libcs = dummy_addr && !_dl_starting_up; + + /* Store the lowest stack address. */ + __libc_stack_end = stack_end; #endif /* Set the global _environ variable correctly. */ diff --git a/sysdeps/generic/sigset-cvt-mask.h b/sysdeps/generic/sigset-cvt-mask.h new file mode 100644 index 0000000..749ed5e --- /dev/null +++ b/sysdeps/generic/sigset-cvt-mask.h @@ -0,0 +1,24 @@ +/* Convert between lowlevel sigmask and libc representation of sigset_t. + Generic version. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Joe Keane <jgk@jgk.org>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define sigset_set_old_mask(set, mask) (*(set) = (unsigned long int) (mask)) + +#define sigset_get_old_mask(set, mask) ((mask) = (unsigned int) *(set)) diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h index 2f936e3..542c35f 100644 --- a/sysdeps/i386/dl-machine.h +++ b/sysdeps/i386/dl-machine.h @@ -105,8 +105,11 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) if (profile) { got[2] = (Elf32_Addr) &_dl_runtime_profile; - /* Say that we really want profiling and the timers are started. */ - _dl_profile_map = l; + + if (_dl_name_match_p (_dl_profile, l)) + /* This is the object we are looking for. Say that we really + want profiling and the timers are started. */ + _dl_profile_map = l; } else /* This function will get called to fix up the GOT entry indicated by @@ -209,6 +212,8 @@ _dl_start_user:\n\ call 0f\n\ 0: popl %ebx\n\ addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx\n\ + # Store the highest stack address\n\ + movl %esp,__libc_stack_end@GOT(%ebx)\n\ # See if we were run as a command with the executable file\n\ # name as an extra leading argument.\n\ movl _dl_skip_args@GOT(%ebx), %eax\n\ diff --git a/sysdeps/i386/elf/start.S b/sysdeps/i386/elf/start.S index 95f74ed..019e749 100644 --- a/sysdeps/i386/elf/start.S +++ b/sysdeps/i386/elf/start.S @@ -53,6 +53,11 @@ _start: boundary to avoid penalties from misaligned accesses. Thanks to Edward Seidl <seidl@janed.com> for pointing this out. */ andl $0xfffffff8, %esp + + /* Provide the highest stack address to the user code (for stacks + which grow downwards). */ + pushl %esp + pushl %edx /* Push address of the shared library termination function. */ diff --git a/sysdeps/posix/mkstemp.c b/sysdeps/posix/mkstemp.c index f0db5d5..2c9c96b 100644 --- a/sysdeps/posix/mkstemp.c +++ b/sysdeps/posix/mkstemp.c @@ -33,7 +33,7 @@ int mkstemp (template) char *template; { - static const char letters[] + static const char letters[62] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; static uint64_t value; struct timeval tv; diff --git a/sysdeps/posix/sigvec.c b/sysdeps/posix/sigvec.c index 12285fa..cc4839d 100644 --- a/sysdeps/posix/sigvec.c +++ b/sysdeps/posix/sigvec.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 92, 94, 95, 96, 97 Free Software Foundation, Inc. +/* Copyright (C) 1991, 92, 94, 95, 96, 97, 98 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,55 +20,20 @@ #include <errno.h> #include <stddef.h> +/* Include macros to convert between `sigset_t' and old-style mask. */ +#include "sigset-cvt-mask.h" /* We use a wrapper handler to support SV_RESETHAND. */ - -static __sighandler_t wrapped_handlers[NSIG]; -static sigset_t wrapped_masks[NSIG]; - -static void wrapper_handler __P ((int sig)); -static inline int convert_mask __P ((sigset_t *set, const int mask)); - -static void -wrapper_handler (sig) - int sig; +struct sigvec_wrapper_data { - int save; - struct sigaction act; + __sighandler_t sw_handler; + unsigned int sw_mask; +}; - act.sa_handler = SIG_DFL; - act.sa_mask = wrapped_masks[sig]; - act.sa_flags = 0; - save = errno; - (void) __sigaction (sig, &act, (struct sigaction *) NULL); - __set_errno (save); +static void sigvec_wrapper_handler __P ((int sig)); - (*wrapped_handlers[sig]) (sig); -} +static struct sigvec_wrapper_data sigvec_wrapper_data[NSIG]; -static inline int -convert_mask (set, mask) - sigset_t *set; - const int mask; -{ - register int sig; - - if (sizeof (*set) == sizeof (mask)) - *(int *) set = mask; - else if (sizeof (*set) == sizeof (unsigned long int)) - *(unsigned long int *) set = (unsigned int) mask; - else - { - if (__sigemptyset (set) < 0) - return -1; - - for (sig = 1; sig < NSIG && sig <= sizeof (mask) * 8; ++sig) - if ((mask & sigmask (sig)) && __sigaddset (set, sig) < 0) - return -1; - } - - return 0; -} /* If VEC is non-NULL, set the handler for SIG to the `sv_handler' member of VEC. The signals in `sv_mask' will be blocked while the handler runs. @@ -91,25 +56,32 @@ __sigvec (sig, vec, ovec) n = NULL; else { - n = &new; - n->sa_handler = vec->sv_handler; - if (convert_mask (&n->sa_mask, vec->sv_mask) < 0) - return -1; - n->sa_flags = 0; - - if (vec->sv_flags & SV_ONSTACK) + __sighandler_t handler; + unsigned int mask; + unsigned int sv_flags; + unsigned int sa_flags; + + handler = vec->sv_handler; + mask = vec->sv_mask; + sv_flags = vec->sv_flags; + sa_flags = 0; + if (sv_flags & SV_ONSTACK) { #ifdef SA_ONSTACK - n->sa_flags |= SA_ONSTACK; + sa_flags |= SA_ONSTACK; #else __set_errno (ENOSYS); return -1; #endif } #ifdef SA_RESTART - if (!(vec->sv_flags & SV_INTERRUPT)) - n->sa_flags |= SA_RESTART; + if (!(sv_flags & SV_INTERRUPT)) + sa_flags |= SA_RESTART; #endif + n = &new; + new.sa_handler = handler; + sigset_set_old_mask (&new.sa_mask, mask); + new.sa_flags = sa_flags; } if (__sigaction (sig, n, &old) < 0) @@ -117,12 +89,18 @@ __sigvec (sig, vec, ovec) } else { + __sighandler_t handler; + unsigned int mask; + struct sigvec_wrapper_data *data; struct sigaction wrapper; - wrapper.sa_handler = wrapper_handler; - wrapped_handlers[sig] = vec->sv_handler; - if (convert_mask (&wrapped_masks[sig], vec->sv_mask) < 0) - return -1; + handler = vec->sv_handler; + mask = (unsigned int)vec->sv_mask; + data = &sigvec_wrapper_data[sig]; + wrapper.sa_handler = sigvec_wrapper_handler; + /* FIXME: should we set wrapper.sa_mask, wrapper.sa_flags?? */ + data->sw_handler = handler; + data->sw_mask = mask; if (__sigaction (sig, &wrapper, &old) < 0) return -1; @@ -130,38 +108,58 @@ __sigvec (sig, vec, ovec) if (ovec != NULL) { - register int i; - int mask = 0; - - if (sizeof (int) == sizeof (sigset_t)) - mask = *(int *) &old.sa_mask; - else if (sizeof (unsigned long int) == sizeof (sigset_t)) - mask = *(unsigned long int *) &old.sa_mask; - else - for (i = 1; i < NSIG && i <= sizeof (mask) * 8; ++i) - if (__sigismember (&old.sa_mask, i)) - mask |= sigmask (i); - - ovec->sv_mask = mask; - ovec->sv_flags = 0; + __sighandler_t handler; + unsigned int sv_flags; + unsigned int sa_flags; + unsigned int mask; + + handler = old.sa_handler; + sv_flags = 0; + sa_flags = old.sa_flags; + if (handler == sigvec_wrapper_handler) + { + handler = sigvec_wrapper_data[sig].sw_handler; + /* should we use data->sw_mask?? */ + sv_flags |= SV_RESETHAND; + } + sigset_get_old_mask (&old.sa_mask, mask); #ifdef SA_ONSTACK - if (old.sa_flags & SA_ONSTACK) - ovec->sv_flags |= SV_ONSTACK; + if (sa_flags & SA_ONSTACK) + sv_flags |= SV_ONSTACK; #endif #ifdef SA_RESTART - if (!(old.sa_flags & SA_RESTART)) + if (!(sa_flags & SA_RESTART)) #endif - ovec->sv_flags |= SV_INTERRUPT; - if (old.sa_handler == wrapper_handler) - { - ovec->sv_flags |= SV_RESETHAND; - ovec->sv_handler = wrapped_handlers[sig]; - } - else - ovec->sv_handler = old.sa_handler; + sv_flags |= SV_INTERRUPT; + ovec->sv_handler = handler; + ovec->sv_mask = (int)mask; + ovec->sv_flags = (int)sv_flags; } return 0; } weak_alias (__sigvec, sigvec) + + +static void +sigvec_wrapper_handler (sig) + int sig; +{ + struct sigvec_wrapper_data *data; + unsigned int mask; + struct sigaction act; + int save; + __sighandler_t handler; + + data = &sigvec_wrapper_data[sig]; + mask = data->sw_mask; + act.sa_handler = SIG_DFL; + sigset_set_old_mask (&act.sa_mask, mask); + act.sa_flags = 0; + save = errno; + handler = data->sw_handler; + (void) __sigaction (sig, &act, (struct sigaction *) NULL); + __set_errno (save); + (*handler) (sig); +} diff --git a/sysdeps/unix/sysv/linux/i386/clone.S b/sysdeps/unix/sysv/linux/i386/clone.S index 88d0e27..d654d98 100644 --- a/sysdeps/unix/sysv/linux/i386/clone.S +++ b/sysdeps/unix/sysv/linux/i386/clone.S @@ -33,10 +33,10 @@ ENTRY(__clone) movl $-EINVAL,%eax movl 4(%esp),%ecx /* no NULL function pointers */ testl %ecx,%ecx - jz syscall_error + jz SYSCALL_ERROR_LABEL movl 8(%esp),%ecx /* no NULL stack pointers */ testl %ecx,%ecx - jz syscall_error + jz SYSCALL_ERROR_LABEL /* Insert the argument onto the new stack. */ subl $8,%ecx @@ -56,7 +56,7 @@ ENTRY(__clone) popl %ebx test %eax,%eax - jl syscall_error + jl SYSCALL_ERROR_LABEL jz thread_start L(pseudo_end): diff --git a/sysdeps/unix/sysv/linux/i386/i686/sysdep.h b/sysdeps/unix/sysv/linux/i386/i686/sysdep.h index 001f3fc..3f1391f 100644 --- a/sysdeps/unix/sysv/linux/i386/i686/sysdep.h +++ b/sysdeps/unix/sysv/linux/i386/i686/sysdep.h @@ -31,12 +31,10 @@ /* Store (- %eax) into errno through the GOT. */ # ifdef _LIBC_REENTRANT # define SYSCALL_ERROR_HANDLER \ - .type syscall_error,@function; \ -0:movl (%esp),%ebx; \ +1:movl (%esp),%ebx; \ ret; \ -syscall_error: \ - pushl %ebx; \ - call 0b; \ +0:pushl %ebx; \ + call 1b; \ addl $_GLOBAL_OFFSET_TABLE_, %ebx; \ xorl %edx, %edx; \ subl %eax, %edx; \ @@ -46,25 +44,22 @@ syscall_error: \ popl %ebx; \ movl %ecx, (%eax); \ movl $-1, %eax; \ - jmp L(pseudo_end); \ - .size syscall_error,.-syscall_error; + jmp L(pseudo_end); /* A quick note: it is assumed that the call to `__errno_location' does not modify the stack! */ # else # define SYSCALL_ERROR_HANDLER \ .type syscall_error,@function; \ -0:movl (%esp),%ecx; \ +1:movl (%esp),%ecx; \ ret; \ -syscall_error: \ - call 0b; \ +0:call 1b; \ addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ xorl %edx, %edx; \ subl %eax, %edx; \ movl errno@GOT(%ecx), %ecx; \ movl %edx, (%ecx); \ movl $-1, %eax; \ - jmp L(pseudo_end); \ - .size syscall_error,.-syscall_error; + jmp L(pseudo_end); # endif /* _LIBC_REENTRANT */ #endif /* PIC */ diff --git a/sysdeps/unix/sysv/linux/i386/mmap.S b/sysdeps/unix/sysv/linux/i386/mmap.S index 5c2449e..e0dde22 100644 --- a/sysdeps/unix/sysv/linux/i386/mmap.S +++ b/sysdeps/unix/sysv/linux/i386/mmap.S @@ -37,7 +37,7 @@ ENTRY (__mmap) /* If 0 > %eax > -4096 there was an error. */ cmpl $-4096, %eax - ja syscall_error + ja SYSCALL_ERROR_LABEL /* Successful; return the syscall's value. */ L(pseudo_end): diff --git a/sysdeps/unix/sysv/linux/i386/s_pread64.S b/sysdeps/unix/sysv/linux/i386/s_pread64.S index 23d7d14..7817cf7 100644 --- a/sysdeps/unix/sysv/linux/i386/s_pread64.S +++ b/sysdeps/unix/sysv/linux/i386/s_pread64.S @@ -44,10 +44,10 @@ ENTRY (__syscall_pread64) movl 0x10(%esp,1),%ebx /* Load syscall number into %eax. */ movl $SYS_ify(pread), %eax - int $0x80 /* Do the system call. */ - POPARGS_5 /* Restore register contents. */ - cmpl $-4095, %eax /* Check %eax for error. */ - jae syscall_error /* Jump to error handler if error. */ + int $0x80 /* Do the system call. */ + POPARGS_5 /* Restore register contents. */ + cmpl $-4095, %eax /* Check %eax for error. */ + jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ #endif L(pseudo_end): ret /* Return to caller. */ diff --git a/sysdeps/unix/sysv/linux/i386/s_pwrite64.S b/sysdeps/unix/sysv/linux/i386/s_pwrite64.S index 7b72d12..89449b6 100644 --- a/sysdeps/unix/sysv/linux/i386/s_pwrite64.S +++ b/sysdeps/unix/sysv/linux/i386/s_pwrite64.S @@ -44,10 +44,10 @@ ENTRY (__syscall_pwrite64) movl 0x10(%esp,1),%ebx /* Load syscall number into %eax. */ movl $SYS_ify(pwrite), %eax - int $0x80 /* Do the system call. */ - POPARGS_5 /* Restore register contents. */ - cmpl $-4095, %eax /* Check %eax for error. */ - jae syscall_error /* Jump to error handler if error. */ + int $0x80 /* Do the system call. */ + POPARGS_5 /* Restore register contents. */ + cmpl $-4095, %eax /* Check %eax for error. */ + jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ #endif L(pseudo_end): ret /* Return to caller. */ diff --git a/sysdeps/unix/sysv/linux/i386/socket.S b/sysdeps/unix/sysv/linux/i386/socket.S index 4326676..245d37a 100644 --- a/sysdeps/unix/sysv/linux/i386/socket.S +++ b/sysdeps/unix/sysv/linux/i386/socket.S @@ -55,7 +55,7 @@ ENTRY (__socket) /* %eax is < 0 if there was an error. */ cmpl $-125, %eax - jae syscall_error + jae SYSCALL_ERROR_LABEL /* Successful; return the syscall's value. */ L(pseudo_end): diff --git a/sysdeps/unix/sysv/linux/i386/syscall.S b/sysdeps/unix/sysv/linux/i386/syscall.S index 349408d..48328c2 100644 --- a/sysdeps/unix/sysv/linux/i386/syscall.S +++ b/sysdeps/unix/sysv/linux/i386/syscall.S @@ -30,7 +30,7 @@ ENTRY (syscall) int $0x80 /* Do the system call. */ POPARGS_5 /* Restore register contents. */ cmpl $-4095, %eax /* Check %eax for error. */ - jae syscall_error /* Jump to error handler if error. */ + jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ L(pseudo_end): ret /* Return to caller. */ diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h index 5231d3e..8c046ef 100644 --- a/sysdeps/unix/sysv/linux/i386/sysdep.h +++ b/sysdeps/unix/sysv/linux/i386/sysdep.h @@ -46,13 +46,22 @@ is a real error number. Linus said he will make sure the no syscall returns a value in -1 .. -4095 as a valid result so we can savely test with -4095. */ + +/* We don't want the label for the error handle to be global when we define + it here. */ +#ifdef PIC +# define SYSCALL_ERROR_LABEL 0f +#else +# define SYSCALL_ERROR_LABEL syscall_error +#endif + #undef PSEUDO #define PSEUDO(name, syscall_name, args) \ .text; \ ENTRY (name) \ DO_CALL (args, syscall_name); \ cmpl $-4095, %eax; \ - jae syscall_error; \ + jae SYSCALL_ERROR_LABEL; \ L(pseudo_end): #undef PSEUDO_END @@ -66,13 +75,11 @@ /* Store (- %eax) into errno through the GOT. */ #ifdef _LIBC_REENTRANT #define SYSCALL_ERROR_HANDLER \ - .type syscall_error,@function; \ -syscall_error: \ - pushl %ebx; \ - call 0f; \ -0:popl %ebx; \ +0:pushl %ebx; \ + call 1f; \ +1:popl %ebx; \ xorl %edx, %edx; \ - addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx; \ + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx; \ subl %eax, %edx; \ pushl %edx; \ call __errno_location@PLT; \ @@ -80,24 +87,20 @@ syscall_error: \ popl %ebx; \ movl %ecx, (%eax); \ movl $-1, %eax; \ - jmp L(pseudo_end); \ - .size syscall_error,.-syscall_error; + jmp L(pseudo_end); /* A quick note: it is assumed that the call to `__errno_location' does not modify the stack! */ #else #define SYSCALL_ERROR_HANDLER \ - .type syscall_error,@function; \ -syscall_error: \ - call 0f; \ -0:popl %ecx; \ +0:call 1f; \ +1:popl %ecx; \ xorl %edx, %edx; \ - addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ecx; \ + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx; \ subl %eax, %edx; \ movl errno@GOT(%ecx), %ecx; \ movl %edx, (%ecx); \ movl $-1, %eax; \ - jmp L(pseudo_end); \ - .size syscall_error,.-syscall_error; + jmp L(pseudo_end); #endif /* _LIBC_REENTRANT */ #endif /* PIC */ diff --git a/sysdeps/unix/sysv/linux/sigset-cvt-mask.h b/sysdeps/unix/sysv/linux/sigset-cvt-mask.h new file mode 100644 index 0000000..aefb805 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sigset-cvt-mask.h @@ -0,0 +1,35 @@ +/* Convert between lowlevel sigmask and libc representation of sigset_t. + Linux version. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Joe Keane <jgk@jgk.org>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define sigset_set_old_mask(set, mask) \ + do { \ + unsigned long int *__ptr; \ + int __cnt; \ + __ptr = &(set)->__val[0]; \ + *__ptr++ = (unsigned long int) (mask); \ + __cnt = _SIGSET_NWORDS - 2; \ + do \ + *__ptr++ = 0ul; \ + while (--__cnt >= 0); \ + } while (0) + +#define sigset_get_old_mask(set, mask) \ + ((mask) = (unsigned int) (set)->__val[0]) diff --git a/sysdeps/unix/sysv/sysv4/sigset-cvt-mask.h b/sysdeps/unix/sysv/sysv4/sigset-cvt-mask.h new file mode 100644 index 0000000..4daab22 --- /dev/null +++ b/sysdeps/unix/sysv/sysv4/sigset-cvt-mask.h @@ -0,0 +1,33 @@ +/* Convert between lowlevel sigmask and libc representation of sigset_t. + SysVr4 version. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Joe Keane <jgk@jgk.org>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define sigset_set_old_mask(set, mask) \ + do { \ + unsigned long int *__ptr; \ + __ptr = &(set)->__sigbits[0]; \ + __ptr[0] = (mask); \ + __ptr[1] = 0ul; \ + __ptr[2] = 0ul; \ + __ptr[3] = 0ul; \ + } while (0) + +#define sigset_get_old_mask(set, mask) \ + ((mask) = (unsigned int) (set)->__sigbits[0]) |