diff options
author | Ulrich Drepper <drepper@redhat.com> | 1997-08-10 18:37:15 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 1997-08-10 18:37:15 +0000 |
commit | 0413b54c02d31cae62e8d13b3ee7ac109ceeff0e (patch) | |
tree | 5159587edd2bf4a39fcb5c42588aa35c7350fe8d /elf | |
parent | 55c14926be46b12fda4e01d0977911d3b0883db7 (diff) | |
download | glibc-0413b54c02d31cae62e8d13b3ee7ac109ceeff0e.zip glibc-0413b54c02d31cae62e8d13b3ee7ac109ceeff0e.tar.gz glibc-0413b54c02d31cae62e8d13b3ee7ac109ceeff0e.tar.bz2 |
Update.cvs/libc-ud-970810
1997-08-10 18:48 Ulrich Drepper <drepper@cygnus.com>
* Makeconfig: Define build-programs to no if not set and $(config-os)
is none.
* Makerules (+depfiles): Don't add $(others) if not build-programs.
* Rules (others): Don't depend on $(install-bin), $(install-rootbin)
and $(install-sbin) if not build-programs.
* Makefile (subdirs): Remove login.
* sysdeps/mach/hurd/Subdirs: Add login.
* sysdeps/unix/Subdirs: Add login.
* sysdeps/generic/sys/mman.h: Test feature macros before defining
non-POSIX things. Add MAP_FAILED.
* sysdeps/unix/bsd/osf/sys/mman.h: Likewise.
* sysdeps/unix/bsd/sun/sunos4/sys/mman.h: Likewise.
* sysdeps/unix/bsd/ultrix4/sys/mman.h: Likewise.
* sysdeps/unix/sysv/irix4/sys/mman.h: Likewise.
* sysdeps/unix/sysv/linux/sys/mman.h: Rewrite to not use kernel header
but bits/mman.h. Test feature macros before definitions non-POSIX
functions.
* sysdeps/unix/sysv/linux/alpha/bits/mman.h: New file.
* sysdeps/unix/sysv/linux/i386/bits/mman.h: New file.
* sysdeps/unix/sysv/linux/m68k/bits/mman.h: New file.
* sysdeps/unix/sysv/linux/mips/bits/mman.h: New file.
* sysdeps/unix/sysv/linux/powerpc/bits/mman.h: New file.
* sysdeps/unix/sysv/linux/sparc/bits/mman.h: New file.
* sysdeps/unix/sysv/linux/sparc64/bits/mman.h: New file.
* sysdeps/unix/sysv/linux/alpha/Dist: Add bits/mman.h.
* sysdeps/unix/sysv/linux/i386/Dist: Likewise.
* sysdeps/unix/sysv/linux/m68k/Dist: Likewise.
* sysdeps/unix/sysv/linux/mips/Dist: Likewise.
* sysdeps/unix/sysv/linux/powerpc/Dist: Likewise.
* sysdeps/unix/sysv/linux/sparc/Dist: Likewise.
* sysdeps/unix/sysv/linux/sparc64/Dist: New file. Likewise.
* catgets/open_catalog.c (__open_catalog): Compare result of mmap
with MAP_FAILED and not -1.
* elf/dl-load.c (_dl_map_object_from_fd): Likewise.
* elf/dl-minimal.c (malloc): Likewise.
* elf/dl-misc.c (_dl_sysdep_read_whole_file): Likewise.
* locale/loadlocale.c (_nl_load_locale): Likewise.
* locale/programs/localedef.c: Likewise.
* malloc/malloc.c (mmap_chunk): Likewise.
(new_heap): Likewise.
* string/stratcliff.c: Likewise.
* string/tester.c: Add tests for stpcpy.
* gmon/gmon.c (__monstartup): Use calloc instead of malloc+memset.
* gmon/sys/gmon.h: Add prototype for write_profiling.
* elf/dl-profile.c: Add decsriptions and implement reading of
existing data in profiling file.
* gmon/sys/gmon_out.h (GMON_SHOBJ_VERSION): New macro for shared
lib profiling data.
* sysdeps/stub/bits/libc-lock.h (__libc_once_define): Add new first
parameter for class.
* inet/inet_ntoa.c: Make once control variable static.
Correctly handle case where key cannot be retrieved.
* inet/Makefile (tests): Add tst-ntoa.
* inet/tst-ntoa.c: New file.
* manual/time.texi: Document localtime_r, gmtime_r, asctime_r, and
ctime_r.
Mention that tzname values must not be changed.
* manual/users.texi: Document UTMP/WTMP handling functions.
Mainly written by Mark Kettenis.
* math/libm-test.c (cbrt_test): Add test for number with aboslute
value < 1.0.
* nss/nss_files/files-XXX.c (internal_setent): If opening of file
failed with EGAIN return NSS_STATUS_TRYAGAIN.
* nss/nss_files/files-alias.c (internal_setent): Likewise.
* sysdeps/generic/bits/utmp.h: Pretty print.
* sysdeps/i386/i586/strcpy.S: New file. Much faster implementation.
* sysdeps/i386/i586/stpcpy.S: New file.
* sysdeps/i386/i686/Implies: Don't fall back on i586 versions since
these are less efficient than i486/i386 versions.
* sysdeps/libm-i387/e_rem_pio2.c: Add empty file to prevent the
version from libm-ieee754 be compiled since the later is not needed.
* sysdeps/libm-i387/e_rem_pio2f.c: Likewise.
* sysdeps/libm-i387/e_rem_pio2l.c: Likewise.
* sysdeps/libm-i387/k_rem_pio2.c: Likewise.
* sysdeps/libm-i387/k_rem_pio2f.c: Likewise.
* sysdeps/libm-i387/k_rem_pio2l.c: Likewise.
* sysdeps/m68k/fpu/e_rem_pio2.c: Likewise.
* sysdeps/m68k/fpu/e_rem_pio2f.c: Likewise.
* sysdeps/m68k/fpu/e_rem_pio2l.c: Likewise.
* sysdeps/m68k/fpu/k_rem_pio2.c: Likewise.
* sysdeps/m68k/fpu/k_rem_pio2f.c: Likewise.
* sysdeps/m68k/fpu/k_rem_pio2l.c: Likewise.
* sysdeps/libm-i387/s_cbrt.S: Fix several bugs.
* sysdeps/libm-i387/s_cbrtf.S: Likewise.
* sysdeps/libm-i387/s_cbrtl.S: Likewise.
* sysdeps/unix/sysv/linux/if_index.c (if_indextoname): Correct
little bug.
* sysdeps/unix/sysv/linux/bits/socket.h (struct msghdr): Make field
msg_iovlen of type int.
* time/tzfile.c: Change return type of __tzstring to char *.
* time/tzset.c: Likewise. Change definition of __tzstring.
* time/tzset.c: Interpret no DST information in user provided time
zone specification as it is meant: no DST.
Patch by Paul Eggert <eggert@twinsun.com>.
1997-07-20 03:01 Geoff Keating <geoffk@ozemail.com.au>
* sysdeps/elf/dl-load.c (add_name_to_object): New procedure.
(_dl_map_object_from_fd): Use add_name_to_object.
(_dl_map_object): If an object's SONAME is used to resolve a
dependency, add it to the list of the object's names.
* inet/getnameinfo.c: Make `domain' non-const.
* sysdeps/unix/sysv/linux/powerpc/kernel_termios.c: Clean up.
* math/test-fenv.c (feenv_nomask_test): Don't execute if
FE_NOMASK_ENV is not defined, or if fesetenv(FE_NOMASK_ENV)
sets errno to ENOSYS.
* sysdeps/powerpc/dl-machine.h: Print proper error message on
unknown reloc type (rather than using assert).
* sysdeps/unix/sysv/linux/powerpc/profil-counter.h: New file.
* sysdeps/unix/sysv/linux/powerpc/profil.c: Deleted.
1997-07-16 12:47 Geoff Keating <geoffk@ozemail.com.au>
* sysdeps/powerpc/bits/fenv.h (feraiseexcept): New optimising macro.
(feclearexcept): New optimising macro.
(FE_NOMASK_ENV): Change to procedure so it can enable exceptions.
(FE_ENABLED_ENV): Add.
(FE_NONIEEE_ENV): Add.
* sysdeps/powerpc/bits/fenv_const.c: Add __fe_enabled_env,
__fe_nonieee_env; delete __fe_nomask_env.
* sysdeps/powerpc/bits/fe_nomask.c: New file (stub warning until it
gets implemented in the kernel).
* sysdeps/powerpc/fraiseenv.c: Deal with chips that don't have
FE_INVALID_SOFTWARE implemented. Use macros for bit names for clarity.
* sysdeps/powerpc/fsetexcptflag.c: Likewise.
* io/ftw.c: Don't compare holes in structures.
* sysdeps/unix/sysv/linux/sys/sysmacros.h: Cast the result of the
macros to `int', because otherwise it might be `long long' which
the calling code is probably not expecting.
* sysdeps/libm-ieee754/s_lround.c [NO_LONG_DOUBLE]: Fix a few bugs,
document the existence of some more.
* sysdeps/powerpc/s_llrint.c: New file.
* sysdeps/powerpc/s_lrint.c: New file.
* sysdeps/powerpc/s_llround.c: New file.
* sysdeps/powerpc/s_lround.c: New file.
* sysdeps/powerpc/s_sqrt.c: New file.
* sysdeps/powerpc/s_sqrtf.c: New file.
* sysdeps/powerpc/w_sqrt.s: New empty file.
* sysdeps/powerpc/w_sqrtf.s: New empty file.
* sysdeps/powerpc/t_sqrt.c: New file.
* sysdeps/powerpc/test-arithf.c: New file.
* sysdeps/powerpc/Makefile [subdir=math]: Add t_sqrt to support
routines. Add test-arithf to test programs.
* sysdeps/powerpc/bits/mathdef.h: Add FP_ILOGB0, FP_ILOGBNAN.
* sysdeps/powerpc/strcmp.s: Simplify drastically. Now much neater,
and possibly faster (or possibly slower, depending on input).
1997-06-08 22:55 Geoff Keating <geoffk@ozemail.com.au>
* sysdeps/powerpc/fenvbits.h: Correct FE_DFL_ENV and FE_NOMASK_ENV
macros.
* sysdeps/powerpc/s_rint.c: New file.
1997-05-22 08:47 Geoff Keating <geoffk@ozemail.com.au>
* sysdeps/powerpc/Makefile [subdir=math]: Add q_* routines.
* sysdeps/powerpc/Dist: Add quad_float.h.
* sysdeps/powerpc/q_dtoq.c: New file.
* sysdeps/powerpc/q_itoq.c: New file.
* sysdeps/powerpc/q_lltoq.c: New file.
* sysdeps/powerpc/q_neg.c: New file.
* sysdeps/powerpc/q_qtoi.c: New file.
* sysdeps/powerpc/q_qtoll.c: New file.
* sysdeps/powerpc/q_qtos.c: New file.
* sysdeps/powerpc/q_qtou.c: New file.
* sysdeps/powerpc/q_qtoull.c: New file.
* sysdeps/powerpc/q_stoq.c: New file.
* sysdeps/powerpc/q_ulltoq.c: New file.
* sysdeps/powerpc/q_utoq.c: New file.
* sysdeps/powerpc/quad_float.h: New file.
* sysdeps/powerpc/test-arith.c: New file.
* sysdeps/powerpc/fpu_control.h: Fix _FPU_GETCW.
* sysdeps/powerpc/fegetround.c: Use mcrfs to be faster and not
require a stack frame.
* sysdeps/powerpc/bits/fenv.h: Include inline macro for fegetround.
1997-05-18 05:55 Geoff Keating <geoffk@ozemail.com.au>
* sysdeps/powerpc/fenv_libc.h (fegetenv_register,
fesetenv_register): Add 'volatile'.
(set_fpscr_bit, reset_fpscr_bit): New macros, FPSCR_*
constants to use with them.
* sysdeps/powerpc/s_copysign.S: New file.
* sysdeps/powerpc/s_copysignf.s: New file.
* sysdeps/powerpc/s_fabs.S: New file.
* sysdeps/powerpc/s_fabsf.s: New file.
* sysdeps/powerpc/s_isnan.c: New file.
* sysdeps/powerpc/s_isnanf.s: New file.
* sysdeps/powerpc/s_rintf.c: New file.
* sysdeps/powerpc/fenvbits.h: Make FE_INVALID the summary
bit in the FPSCR, not the enable bit.
* sysdeps/powerpc/fraiseexcpt.c: Consequent change to the above.
* sysdeps/powerpc/fclrexcpt.c: Correct.
* sysdeps/powerpc/fsetexcptflag.c: Correct.
* sysdeps/powerpc/ftestexcpt.c: Is now much simpler.
* sysdeps/powerpc/fgetexcptflg.c: Simplify.
* sysdeps/powerpc/strlen.s: Schedule better, save 3 clocks :-).
* sysdeps/powerpc/dl-machine.h (elf_machine_rela): Add comment
explaining some reentrancy issues with lazy PLT entries.
1997-08-09 13:04 Mark Kettenis <kettenis@phys.uva.nl>
* login/logout.c (logout): utmpname returns -1 on error.
* login/libutil.map: Remove updwtmp.
* login/getutline.c: Rename getutline to __getutline and make
getutline a weak alias. Make getutxline a weak alias for
__getutline.
* login/getutid.c: Rename getutid to __getutid and make getutid a
weak alias. Make getutxid a weak alias for __getutid.
* libc.map: Add getutxid, getutxline.
* login/utmpname.c (__utmpname): Reset backend right after backend
endutent call.
* login/utmp_file.c: Reordered functions. Remove unecessary
header files.
(getutent_r_file, pututline_file): Do not call setutent_file. At this
point the file is guaranteed to be open (assert!).
(getutid_r_file, getutline_r_file): Remove check for validity of file
descriptor. At this point the file is guaranteed to be open.
(getutent_r_file, internal_getut_r, getutline_r_file, pututline_file,
updwtmp_file): Do not wait when unlocking file.
* login/utmp_daemon.c: General cleanup and a bit of reordering.
(getutent_r_daemon, pututline_daemon): Do not call setutent_daemon.
At this point the socket is guaranteed to be open (assert!).
(getutid_r_daemon, getutline_r_daemon): Do not check if daemon_sock is
valid. At this point the socket is guaranteed to be open (assert!).
* login/getutline_r.c: Remove unnecessary header files.
(__getutline_r): Do not call backend setutent.
* login/getutid_r.c: Remove unnecessary header files.
(__getutid_r): Do not call backend setutent.
* login/getutent_r.c: Remove unneccesary header files.
(__libc_utmp_unknown_functions): Added getutid_r_unknown,
getutline_r_unknown.
(setutent_unknown): Only set file backend if setutent for the file
backend was successful.
(getutent_r_unknown, pututline_unknown): Call setutent_unknown instead
of __setutent. Report failure if no backend was selected.
(getutid_r_unknown): New function.
(getutline_r_unknown): New function.
(__endutent): Reset backend. This makes sure all backends are checked
on the next setutent call.
1997-08-08 20:20 Thorsten Kukuk <kukuk@vt.uni-paderborn.de>
* nis_cache.c: Replace dummy functions.
* libc.map: Add xdr_sizeof symbol.
* sunrpc/Makefile: Add xdr_sizeof to routines.
* sunrpc/rpc/xdr.h: Add xdr_sizeof prototype.
* sunrpc/xdr_sizeof.c: New, from tirpc 2.3.
1997-08-08 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
* sysdeps/mach/bits/libc-lock.h (__libc_once): Define correctly.
1997-08-07 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
* sysdeps/mach/hurd/profil.c (fetch_samples): Put parens in the
right place.
1997-08-06 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
* sysdeps/mach/hurd/profil.c (fetch_samples): Do arithmetic on
PC's in long long to avoid overflow.
1997-08-07 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
* sysdeps/mach/bits/libc-lock.h (__libc_once, __libc_once_define):
New macros.
1997-08-06 Andreas Jaeger <aj@arthur.rhein-neckar.de>
* nis/Makefile (headers): Remove bits/nislib.h.
1997-08-06 14:54 Ulrich Drepper <drepper@cygnus.com>
* sysdeps/mach/hurd/Subdirs: Add login.
1997-08-06 14:23 Klaus Espenlaub <kespenla@hydra.informatik.uni-ulm.de>
* db/hash/hash.c (init_hash): Don't use stat() if it doesn't provide
the preferred block size.
* login/programs/database.c (store_state_entry): Don't compile if
there is no ut_type field.
(store_state_entry, store_process_entry): Use the ut_tv field
for timestamps if supported.
* login/programs/utmpdump.c (print_entry): Always use ut_tv field.
* login/programs/xtmp.c: Fix numerous xtmp/utmp typos. Use the ut_tv
field for timestamps if supported.
* login/programs/xtmp.h: Fix xtmp/utmp typo.
* sysdeps/posix/defs.c (stdstream): Change (PTR) to (void *).
* sysdeps/stub/connect.c (connect): Change to __connect, add alias.
* sysdeps/stub/send.c (send): Likewise.
* sysdeps/stub/s_exp2f.c: Emit correct stub_warning().
* sysdeps/stub/statfs.c: Move stub_warning() to the usual place.
* sysdeps/stub/init-first.c: Add definition of __libc_pid.
1997-08-05 13:28 Philip Blundell <pb@spring.nexus.co.uk>
* sysdeps/standalone/arm/bits/errno.h: Add EISDIR, EOPNOTSUPP;
tidy up formatting.
* Makefile (subdirs): Remove `login'.
* sysdeps/unix/Subdirs: New file; build `login' subdirectory
for Unix systems.
1997-08-05 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* sysdeps/generic/bits/utmpx.h: New file.
* sysdeps/mach/hurd/Dist: Add some files.
* sysdeps/mips/Dist: Likewise.
* sysdeps/mips/mips64/Dist: Likewise.
* sysdeps/sparc/Dist: Likewise.
* sysdeps/unix/sysv/linux/mips/Dist: Likewise.
* sysdeps/unix/sysv/linux/sparc/Dist: Likewise.
* sysdeps/mips/mipsel/Dist: New file.
* sysdeps/sparc64/elf/Dist: New file.
* sysdeps/unix/sysv/linux/sparc64/Dist: New file.
1997-08-05 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* libc.map: Add missing symbols.
1997-08-05 Andreas Jaeger <aj@arthur.rhein-neckar.de>
* manual/socket.texi: Correct typos.
* manual/math.texi: Correct typos.
* manual/time.texi (Formatting Date and Time): Likewise.
1997-08-04 13:06 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
* gmon/gmon.c (write_gmon): New function; guts from _mcleanup.
(_mcleanup): Use write_gmon.
(write_profiling): This function can be safely called at any time
to write a current histogram without interfering with ongoing
profiling.
* sysdeps/mach/hurd/profil.c (fetch_samples): Initialize NSAMPLES.
1997-08-01 17:53 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
* sysdeps/mach/hurd/profil.c (fetch_samples): Sample buffer need
not be vm_deallocated; it's a stack buffer.
(profil_vm_deallocate): Delete prototype.
(#include <../mach/RPC_vm_deallocate_rpc.c>): Drop this
inclusion.
* sysdeps/mach/hurd/Makefile
($(common-objpfx)hurd/../mach/RPC_vm_deallocate_rpc.c): Delete
this rule.
* sysdeps/mach/hurd/profil.c (fetch_samples): New function, guts
from profile_waiter.
(profile_waiter): Use fetch_samples.
(profil): When turning off profiling, fetch the last bunch of
samples before disabling PC sampling.
(fetch_samples): Add prototype.
1997-07-30 12:53 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
* sysdeps/mach/hurd/Makefile: Give normal rules for the mach RPC
source included by profil.c instead of trying to use
before-compile grot.
1997-07-23 15:04 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
* sysdeps/mach/hurd/profil.c (profile_waiter): Do vm_deallocate
after releasing lock. Use special RPC stubs and avoid assert,
thus making this function entirely independent of the threadvar
mechanism and of cthreads.
(lock): Convert to be a spin lock instead of a mutex, so that the
waiter thread need not use cthreads. Use a fork prepare hook
instead of _hurd_fork_locks to make sure we are clean before
forking.
(fork_profil_child): Renamed from fork_profil.
(profil_reply_port): New variable.
(profil_vm_deallocate, profil_task_get_sampled_pcs): Special RPC
stubs made by special hacks.
* sysdeps/mach/hurd/Makefile (before-compile): Add the mach RPC
source files that profil.c needs if we are in the gmon directory.
* mach/setup-thread.c (__mach_setup_thread): Delete avoidance of a
cthreads bug that hasn't existed for two years.
* stdio-common/printf_fp.c (__printf_fp): Correct rounding of numbers
* locale/programs/locale.c (print_escaped): New function.
* time/australasia: Likewise.
(open_database, synchronize_database, initialize_database):
* nss/nss_files/files-netgrp.c (_nss_netgroup_parseline): Don't
* Makerules (load-map-file): Currectly handle missing map file.
cannot rely on M_SQRT2 being defined.
(log1p): Use __M_SQRT2 not M_SQRT2.
Diffstat (limited to 'elf')
-rw-r--r-- | elf/dl-load.c | 97 | ||||
-rw-r--r-- | elf/dl-minimal.c | 2 | ||||
-rw-r--r-- | elf/dl-misc.c | 2 | ||||
-rw-r--r-- | elf/dl-profile.c | 251 |
4 files changed, 254 insertions, 98 deletions
diff --git a/elf/dl-load.c b/elf/dl-load.c index f7c2c53..f0af292 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -107,27 +107,51 @@ local_strdup (const char *s) return (char *) memcpy (new, s, len); } - -/* Implement cache for search path lookup. */ -#if 0 -/* This is how generated should look like. I'll remove this once I'm - sure everything works correctly. */ -static struct r_search_path_elem rtld_search_dir1 = - { "/lib/", 5, unknown, 0, unknown, NULL }; -static struct r_search_path_elem rtld_search_dir2 = - { "/usr/lib/", 9, unknown, 0, unknown, &r ld_search_dir1 }; - -static struct r_search_path_elem *rtld_search_dirs[] = +/* Add `name' to the list of names for a particular shared object. + `name' is expected to have been allocated with malloc and will + be freed if the shared object already has this name. + Returns false if the object already had this name. */ +static int +add_name_to_object (struct link_map *l, char *name) { - &rtld_search_dir1, - &rtld_search_dir2, - NULL -}; + struct libname_list *lnp, *lastp; + struct libname_list *newname; -static struct r_search_path_elem *all_dirs = &rtld_search_dir2; -#else -# include "rtldtbl.h" -#endif + if (name == NULL) + { + /* No more memory. */ + _dl_signal_error (ENOMEM, NULL, _("could not allocate name string")); + return 0; + } + + lastp = NULL; + for (lnp = l->l_libname; lnp != NULL; lastp = lnp, lnp = lnp->next) + if (strcmp (name, lnp->name) == 0) + { + free (name); + return 0; + } + + newname = malloc (sizeof *newname); + if (newname == NULL) + { + /* No more memory. */ + _dl_signal_error (ENOMEM, name, _("cannot allocate name record")); + free(name); + return 0; + } + /* The object should have a libname set from _dl_new_object. */ + assert (lastp != NULL); + + newname->name = name; + newname->next = NULL; + lastp->next = newname; + return 1; +} + + +/* Implement cache for search path lookup. */ +#include "rtldtbl.h" static size_t max_dirnamelen; @@ -423,9 +447,10 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, l->l_next->l_prev = l->l_prev; free (l); } - free (name); /* XXX Can this be correct? --drepper */ free (realname); _dl_signal_error (code, name, msg); + free (name); /* Hmmm. Can this leak memory? Better + than a segfault, anyway. */ } inline caddr_t map_segment (ElfW(Addr) mapstart, size_t len, @@ -434,7 +459,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, caddr_t mapat = __mmap ((caddr_t) mapstart, len, prot, fixed|MAP_COPY|MAP_FILE, fd, offset); - if (mapat == (caddr_t) -1) + if (mapat == MAP_FAILED) lose (errno, "failed to map segment from shared object"); return mapat; } @@ -451,7 +476,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, mapping_size &= ~(_dl_pagesize - 1); result = __mmap (file_mapping, mapping_size, PROT_READ, MAP_COPY|MAP_FILE, fd, 0); - if (result == (void *) -1) + if (result == MAP_FAILED) lose (errno, "cannot map file data"); file_mapping = result; } @@ -467,7 +492,6 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, for (l = _dl_loaded; l; l = l->l_next) if (! strcmp (realname, l->l_name)) { - struct libname_list *lnp, *lastp; /* The object is already loaded. Just bump its reference count and return it. */ __close (fd); @@ -475,26 +499,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, /* If the name is not in the list of names for this object add it. */ free (realname); - lastp = NULL; - for (lnp = l->l_libname; lnp != NULL; lastp = lnp, lnp = lnp->next) - if (strcmp (name, lnp->name) == 0) - { - free (name); - break; - } - if (lnp == NULL) - { - struct libname_list *newname = malloc (sizeof *newname); - if (newname == NULL) - /* No more memory. */ - lose (ENOMEM, "cannot allocate name record"); - /* The object should have a libname set. */ - assert (lastp != NULL); - - newname->name = name; - newname->next = NULL; - lastp->next = newname; - } + add_name_to_object (l, name); ++l->l_opencount; return l; } @@ -701,7 +706,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage, c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED, ANONFD, 0); - if (mapat == (caddr_t) -1) + if (mapat == MAP_FAILED) lose (errno, "cannot map zero-fill pages"); } } @@ -876,6 +881,10 @@ _dl_map_object (struct link_map *loader, const char *name, int type, { /* The object is already loaded. Just bump its reference count and return it. */ + const char *soname = (const char *) (l->l_addr + + l->l_info[DT_STRTAB]->d_un.d_ptr + + l->l_info[DT_SONAME]->d_un.d_val); + add_name_to_object (l, local_strdup (soname)); ++l->l_opencount; return l; } diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c index f5b2568..486e5bc 100644 --- a/elf/dl-minimal.c +++ b/elf/dl-minimal.c @@ -66,7 +66,7 @@ malloc (size_t n) assert (n <= _dl_pagesize); page = __mmap (0, _dl_pagesize, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0); - assert (page != (caddr_t) -1); + assert (page != MAP_FAILED); if (page != alloc_end) alloc_ptr = page; alloc_end = page + _dl_pagesize; diff --git a/elf/dl-misc.c b/elf/dl-misc.c index d5b1464..0894a72 100644 --- a/elf/dl-misc.c +++ b/elf/dl-misc.c @@ -62,7 +62,7 @@ _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot) | MAP_FILE #endif , fd, 0); - if (result == (void *) -1) + if (result == MAP_FAILED) result = NULL; else *sizep = st.st_size; diff --git a/elf/dl-profile.c b/elf/dl-profile.c index 8056249..c8028a7 100644 --- a/elf/dl-profile.c +++ b/elf/dl-profile.c @@ -50,29 +50,129 @@ This approach is very different from the normal profiling. We have to use the profiling data in exactly the way they are expected to - be written to disk. */ + be written to disk. But the normal format used by gprof is not usable + to do this. It is optimized for size. It writes the tags as single + bytes but this means that the following 32/64 bit values are + unaligned. + + Therefore we use a new format. This will look like this + + 0 1 2 3 <- byte is 32 bit word + 0000 g m o n + 0004 *version* <- GMON_SHOBJ_VERSION + 0008 00 00 00 00 + 000c 00 00 00 00 + 0010 00 00 00 00 + + 0014 *tag* <- GMON_TAG_TIME_HIST + 0018 ?? ?? ?? ?? + ?? ?? ?? ?? <- 32/64 bit LowPC + 0018+A ?? ?? ?? ?? + ?? ?? ?? ?? <- 32/64 bit HighPC + 0018+2*A *histsize* + 001c+2*A *profrate* + 0020+2*A s e c o + 0024+2*A n d s \0 + 0028+2*A \0 \0 \0 \0 + 002c+2*A \0 \0 \0 + 002f+2*A s + + 0030+2*A ?? ?? ?? ?? <- Count data + ... ... + 0030+2*A+K ?? ?? ?? ?? + + 0030+2*A+K *tag* <- GMON_TAG_CG_ARC + 0034+2*A+K *lastused* + 0038+2*A+K ?? ?? ?? ?? + ?? ?? ?? ?? <- FromPC#1 + 0038+3*A+K ?? ?? ?? ?? + ?? ?? ?? ?? <- ToPC#1 + 0038+4*A+K ?? ?? ?? ?? <- Count#1 + ... ... ... + 0038+(2*(CN-1)+2)*A+(CN-1)*4+K ?? ?? ?? ?? + ?? ?? ?? ?? <- FromPC#CGN + 0038+(2*(CN-1)+3)*A+(CN-1)*4+K ?? ?? ?? ?? + ?? ?? ?? ?? <- ToPC#CGN + 0038+(2*CN+2)*A+(CN-1)*4+K ?? ?? ?? ?? <- Count#CGN + + We put (for now? no basic block information in the file since this would + introduce rase conditions among all the processes who want to write them. + + `K' is the number of count entries which is computed as + + textsize / HISTFRACTION + + `CG' in the above table is the number of call graph arcs. Normally, + the table is sparse and the profiling code writes out only the those + entries which are really used in the program run. But since we must + not extend this table (the profiling file) we'll keep them all here. + So CN can be executed in advance as + + MINARCS <= textsize*(ARCDENSITY/100) <= MAXARCS + + Now the remaining question is: how to build the data structures we can + work with from this data. We need the from set and must associate the + froms with all the associated tos. We will do this by constructing this + data structures at the program start. To do this we'll simply visit all + entries in the call graph table and add it to the appropriate list. */ extern char *_strerror_internal __P ((int, char *buf, size_t)); extern int __profile_frequency __P ((void)); - -static struct gmonparam param; - /* We define a special type to address the elements of the arc table. This is basically the `gmon_cg_arc_record' format but it includes the room for the tag and it uses real types. */ struct here_cg_arc_record { - char tag; - uintptr_t from_pc __attribute__ ((packed)); - uintptr_t self_pc __attribute__ ((packed)); - uint32_t count __attribute__ ((packed)); - }; + uintptr_t from_pc; + uintptr_t self_pc; + uint32_t count; + } __attribute__ ((packed)); static struct here_cg_arc_record *data; +/* This is the number of entry which have been incorporated in the toset. */ +static uint32_t narcs; +/* This is a pointer to the object representing the number of entries + currently in the mmaped file. At no point of time this has to be the + same as NARCS. If it is equal all entries from the file are in our + lists. */ +static uint32_t *narcsp; + +/* Description of the currently profiled object. */ +static long int state; +static volatile uint16_t *kcount; +static size_t kcountsize; + +struct here_tostruct + { + struct here_cg_arc_record volatile *here; + uint16_t link; + }; + +static uint16_t *froms; +static size_t fromssize; + +static struct here_tostruct *tos; +static size_t tossize; +static size_t tolimit; +static size_t toidx; + +static uintptr_t lowpc; +static uintptr_t highpc; +static size_t textsize; +static unsigned int hashfraction; +static unsigned int log_hashfraction; + +/* This is the information about the mmaped memory. */ +static struct gmon_hdr *addr; +static off_t expected_size; + + +/* Set up profiling data to profile object desribed by MAP. The output + file is found (or created) in OUTPUT_DIR. */ void _dl_start_profile (struct link_map *map, const char *output_dir) { @@ -82,11 +182,10 @@ _dl_start_profile (struct link_map *map, const char *output_dir) const ElfW(Phdr) *ph; ElfW(Addr) mapstart = ~((ElfW(Addr)) 0); ElfW(Addr) mapend = 0; - off_t expected_size; struct gmon_hdr gmon_hdr; struct gmon_hist_hdr hist_hdr; - struct gmon_hdr *addr; char *hist; + size_t idx; /* Compute the size of the sections which contain program code. */ for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph) @@ -104,40 +203,41 @@ _dl_start_profile (struct link_map *map, const char *output_dir) /* Now we can compute the size of the profiling data. This is done with the same formulars as in `monstartup' (see gmon.c). */ - param.state = GMON_PROF_OFF; - param.lowpc = mapstart + map->l_addr; - param.highpc = mapend + map->l_addr; - param.textsize = mapend - mapstart; - param.kcountsize = param.textsize / HISTFRACTION; - param.hashfraction = HASHFRACTION; - param.log_hashfraction = -1; + state = GMON_PROF_OFF; + lowpc = ROUNDDOWN (mapstart + map->l_addr, + HISTFRACTION * sizeof(HISTCOUNTER)); + highpc = ROUNDUP (mapend + map->l_addr, + HISTFRACTION * sizeof(HISTCOUNTER)); + textsize = highpc - lowpc; + kcountsize = textsize / HISTFRACTION; + hashfraction = HASHFRACTION; if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) /* If HASHFRACTION is a power of two, mcount can use shifting instead of integer division. Precompute shift amount. */ - param.log_hashfraction = ffs (param.hashfraction - * sizeof (*param.froms)) - 1; - param.fromssize = param.textsize / HASHFRACTION; - param.tolimit = param.textsize * ARCDENSITY / 100; - if (param.tolimit < MINARCS) - param.tolimit = MINARCS; - if (param.tolimit > MAXARCS) - param.tolimit = MAXARCS; - param.tossize = param.tolimit * sizeof (struct tostruct); + log_hashfraction = __builtin_ffs (hashfraction * sizeof (*froms)) - 1; + else + log_hashfraction = -1; + fromssize = textsize / HASHFRACTION; + tolimit = textsize * ARCDENSITY / 100; + if (tolimit < MINARCS) + tolimit = MINARCS; + if (tolimit > MAXARCS) + tolimit = MAXARCS; + tossize = tolimit * sizeof (struct here_tostruct); expected_size = (sizeof (struct gmon_hdr) - + 1 + sizeof (struct gmon_hist_hdr) - + ((1 + sizeof (struct gmon_cg_arc_record)) - * (param.fromssize / sizeof (*param.froms)))); + + 4 + sizeof (struct gmon_hist_hdr) + kcountsize + + 4 + 4 + tossize * sizeof (struct here_cg_arc_record)); /* Create the gmon_hdr we expect or write. */ memset (&gmon_hdr, '\0', sizeof (struct gmon_hdr)); memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie)); - *(int32_t *) gmon_hdr.version = GMON_VERSION; + *(int32_t *) gmon_hdr.version = GMON_SHOBJ_VERSION; /* Create the hist_hdr we expect or write. */ *(char **) hist_hdr.low_pc = (char *) mapstart; *(char **) hist_hdr.high_pc = (char *) mapend; - *(int32_t *) hist_hdr.hist_size = param.kcountsize / sizeof (HISTCOUNTER); + *(int32_t *) hist_hdr.hist_size = kcountsize / sizeof (HISTCOUNTER); *(int32_t *) hist_hdr.prof_rate = __profile_frequency (); strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen)); hist_hdr.dimen_abbrev = 's'; @@ -193,15 +293,19 @@ _dl_start_profile (struct link_map *map, const char *output_dir) { __close (fd); wrong_format: + + if (addr != NULL) + __munmap ((void *) addr, expected_size); + _dl_sysdep_error (filename, ": file is no correct profile data file for `", _dl_profile, "'\n", NULL); return; } - addr = (void *) __mmap (NULL, expected_size, PROT_READ|PROT_WRITE, - MAP_SHARED|MAP_FILE, fd, 0); - if (addr == (void *) -1) + addr = (struct gmon_hdr *) __mmap (NULL, expected_size, PROT_READ|PROT_WRITE, + MAP_SHARED|MAP_FILE, fd, 0); + if (addr == (struct gmon_hdr *) MAP_FAILED) { char buf[400]; int errnum = errno; @@ -217,54 +321,97 @@ _dl_start_profile (struct link_map *map, const char *output_dir) /* Pointer to data after the header. */ hist = (char *) (addr + 1); + kcount = (uint16_t *) ((char *) hist + sizeof (uint32_t) + + sizeof (struct gmon_hist_hdr)); /* Compute pointer to array of the arc information. */ - data = (struct here_cg_arc_record *) (hist + 1 - + sizeof (struct gmon_hist_hdr)); + data = (struct here_cg_arc_record *) ((char *) kcount + kcountsize + + 2 * sizeof (uint32_t)); + narcsp = (uint32_t *) (hist + sizeof (uint32_t) + + sizeof (struct gmon_hist_hdr) + sizeof (uint32_t)); if (st.st_size == 0) { /* Create the signature. */ - size_t cnt; - memcpy (addr, &gmon_hdr, sizeof (struct gmon_hdr)); - *hist = GMON_TAG_TIME_HIST; - memcpy (hist + 1, &hist_hdr, sizeof (struct gmon_hist_hdr)); + *(uint32_t *) hist = GMON_TAG_TIME_HIST; + memcpy (hist + sizeof (uint32_t), &hist_hdr, + sizeof (struct gmon_hist_hdr)); - for (cnt = 0; cnt < param.fromssize / sizeof (*param.froms); ++cnt) - data[cnt].tag = GMON_TAG_CG_ARC; + *(uint32_t *) (hist + sizeof (uint32_t) + sizeof (struct gmon_hist_hdr) + + kcountsize) = GMON_TAG_CG_ARC; } else { /* Test the signature in the file. */ if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0 - || *hist != GMON_TAG_TIME_HIST - || memcmp (hist + 1, &hist_hdr, sizeof (struct gmon_hist_hdr)) != 0) + || *(uint32_t *) hist != GMON_TAG_TIME_HIST + || memcmp (hist + sizeof (uint32_t), &hist_hdr, + sizeof (struct gmon_hist_hdr)) != 0 + || (*(uint32_t *) (hist + sizeof (uint32_t) + + sizeof (struct gmon_hist_hdr) + kcountsize) + != GMON_TAG_CG_ARC)) goto wrong_format; } + /* Allocate memory for the froms data and the pointer to the tos records. */ + froms = (uint16_t *) calloc (fromssize + tossize, 1); + if (froms == NULL) + { + __munmap ((void *) addr, expected_size); + _dl_sysdep_fatal ("Out of memory while initializing profiler", NULL); + /* NOTREACHED */ + } + + tos = (struct here_tostruct *) ((char *) froms + fromssize); + toidx = 0; + + /* Now we have to process all the arc count entries. BTW: it is + not critical whether the *NARCSP value changes meanwhile. Before + we enter a new entry in to toset we will check that everything is + available in TOS. This happens in _dl_mcount. + + Loading the entries in reverse order should help to get the most + frequently used entries at the front of the list. */ + for (idx = narcs = *narcsp; idx > 0; ) + { + size_t from_index; + size_t newtoidx; + --idx; + from_index = ((data[idx].from_pc - lowpc) + / (hashfraction * sizeof (*froms))); + newtoidx = toidx++; + tos[newtoidx].here = &data[idx]; + tos[newtoidx].link = froms[from_index]; + froms[from_index] = newtoidx; + } + /* Turn on profiling. */ - param.state = GMON_PROF_ON; + state = GMON_PROF_ON; } void _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc) { - if (param.state != GMON_PROF_ON) + if (state != GMON_PROF_ON) return; - param.state = GMON_PROF_BUSY; + state = GMON_PROF_BUSY; /* Compute relative addresses. The shared object can be loaded at any address. The value of frompc could be anything. We cannot restrict it in any way, just set to a fixed value (0) in case it is outside the allowed range. These calls show up as calls from <external> in the gprof output. */ - frompc -= param.lowpc; - if (frompc >= param.textsize) + frompc -= lowpc; + if (frompc >= textsize) frompc = 0; - selfpc -= param.lowpc; + selfpc -= lowpc; + if (selfpc >= textsize) + goto done; + - param.state = GMON_PROF_ON; + done: + state = GMON_PROF_ON; } |