From 650425ceb40e840b2123b6c8cc65389589f41218 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 24 Sep 1997 23:03:42 +0000 Subject: Update. 1997-09-25 00:23 Ulrich Drepper * elf/dl-profile.c: Correct implementation. * io/ftwtest-sh: Don't depend on TMPDIR == /tmp. * locale/setlocale.c: Rewrite a bit for more clarity. * math/Makefile (libm-calls): Add w_exp2. * math/math_private.h: Add prototypes for __ieee754_exp2{,f,l}. * sysdeps/libm-i387/s_exp2.S: Change name to __ieee754_exp2. * sysdeps/libm-i387/s_exp2f.S: Likewise. * sysdeps/libm-i387/s_exp2l.S: Likewise. * sysdeps/libm-ieee754/k_standard.c: Add error cases for exp2. * string/bits/string2.h (__strcpy_small): Optimize. (__stpcpy_small): Likewise. (strncpy): Use variable for dest argument since it's used more than once. (strncat): Likewise. (strcmp): Add optimization for this function. * sysdeps/i386/i486/string.h (strlen): Correctly use __builtin_strlen. (__strcpy_small): Optimize. (__stpcpy_small): Likewise. (__stpcpy_c): Correctly use __mempcpy_* macros. (__mempcpy_by2, __mempcpy_by4, __mempcpy_byn): Return pointer to byte following last copied. (strncat): Use variable for dest argument since it's used more than once. (strcmp): Add optimization for this function. * sysdeps/i386/dl-machine.h (ELF_MACHINE_RUNTIME_TRAMPOLINE): Use .text and .previous to select correct section. 1997-09-23 19:56 Philip Blundell * configure.in: Add `--disable-versioning' option to suppress the use of symbol versions even if binutils claims to support it. 1997-09-24 20:10 Philip Blundell * csu/Makefile (before-compile): Don't try to build abi-tags.h if not using ELF. 1997-09-21 Andreas Schwab * elf/sofini.c [HAVE_DWARF2_UNWIND_INFO]: Supply termination for the frame unwind info section. * elf/soinit.c [HAVE_DWARF2_UNWIND_INFO]: Register and unregister the frame unwind info. * config.h.in (HAVE_DWARF2_UNWIND_INFO): Add #undef. * configure.in: Check whether gcc supports DWARF2 unwind info. * libc.map: Export frame handling tables. 1997-09-10 06:56 Geoff Keating * sysdeps/unix/sysv/linux/powerpc/bits/kernel_termios.h: Use the size of the kernel's termios structure for ioctls. * sysdeps/powerpc/dl-machine.h: Prepare for library profiling. * sysdeps/powerpc/bits/mathinline.h: Add slightly slower versions of the C9X FP comparison macros. Delete 'fabs' and 'sqrt' inline routines, because gcc has them as internals. * sysdeps/powerpc/Makefile (pic-ccflags): Define this instead of CFLAGS-.os. * sysdeps/powerpc/bzero.S: New file. * sysdeps/powerpc/strcat.c: New file. * sysdeps/powerpc/strcpy.S: New file. * sysdeps/powerpc/stpcpy.S: New file. * math/Makefile: Add atest_exp2, test-reduce. * math/atest_exp2.c: New file. * math/test-reduce.c: New file. * sysdeps/libm-ieee754/Dist: New file. * sysdeps/libm-ieee754/s_exp2.c: New file. * sysdeps/libm-ieee754/s_exp2f.c: New file. * sysdeps/libm-ieee754/t_exp2.h: New file. * sysdeps/libm-ieee754/t_exp2f.h: New file. * math/libm-test.c (exp2_test): Add some more tests. * Rules: Use empty.os instead of empty.o, since it gets linked into libc.so... * configure.in: Add --disable-static to disable building .a files. * config.make.in: Substitute the new variable. * Makeconfig: Don't build .o files if not building .a files. * elf/dl-runtime.c (fixup): Factor out call to elf_machine_relplt. (profile_fixup): Likewise. 1997-09-23 Andreas Schwab * posix/globtest.c (main): Change to directory passed as first argument. * posix/globtest.sh: Don't cd before running the program, instead pass testdir as argument, so that $common_objpfx remains valid. 1997-09-23 18:01 Thorsten Kukuk * nis/nis_call.c (__do_niscall2): Fix multiple Server support. * nis/nis_findserver.c: Save latest working sockaddr_in. 1997-09-17 22:07 Zack Weinberg * configure.in: Automatically determine whether as and ld are the GNU versions. (options): --with-gnu-{as,ld,binutils} replaced by single option --with-binutils=PATH specifying a -B option to gcc. * aclocal.m4: Two new macros defined, LIBC_PROG_FOO_GNU and LIBC_PROG_BINUTILS. * configure.in: Allow the user to force configuration for unsupported platforms with an undocumented option. 1997-09-22 16:55 Thorsten Kukuk * sunrpc/get_myaddr.c (get_myaddress): Avoid loopback interfaces, return loopback address only if there is no other interface. * nis/Makefile: Add nis_callback libnsl-routines. * nis/nis_add.c: Use new __do_niscall* interface. * nis/nis_cache.c: Likewise. * nis/nis_checkpoint.c: Likewise. * nis/nis_lookup.c: Likewise. * nis/nis_mkdir.c: Likewise. * nis/nis_modify.c: Likewise. * nis/nis_ping.c: Likewise. * nis/nis_remove.c: Likewise. * nis/nis_rmdir.c: Likewise. * nis/nis_server.c: Likewise. * nis/nis_util.c: Likewise. * nis/rpcsvc/nis.h: Make C++ safe. * nis/nss_nisplus/nisplus-publickey.c (getsecretkey): Fix use of variables. * nis/nis_findserv.c: Make thread safe. * nis/nis_call.c: Add support for callback, Fix use of variables. * nis/nis_table.c: Add support for callback, FOLLOW_PATH and ALL_RESULTS. * nis/nis_callback.c: New, callback functions. * nis/nis_intern.h: Add callback declarations. 1997-09-20 Andreas Schwab * string/bits/string2.h: Fix logic in preprocessor directive. (__strsep_1c, __strsep_g): Don't declare __retval as pointing to const, to save a cast and a possible warning. 1997-09-22 04:12 Ulrich Drepper * sysdeps/i386/i486/atomicity.h (exchange_and_add): Really address memory in xadd not %1. 1997-09-21 13:56 Ulrich Drepper * manual/maint.texi (Supported Configurations): Add SPARC64 to list of supported platforms. --- elf/dl-profile.c | 88 ++++++++++++++++++++++++++++++-------------------------- elf/dl-runtime.c | 27 ++++++++++------- elf/sofini.c | 10 +++++++ elf/soinit.c | 13 +++++++++ 4 files changed, 86 insertions(+), 52 deletions(-) (limited to 'elf') diff --git a/elf/dl-profile.c b/elf/dl-profile.c index 9b020e8..dcbbcd0 100644 --- a/elf/dl-profile.c +++ b/elf/dl-profile.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -97,7 +98,7 @@ ?? ?? ?? ?? <- 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 + 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 @@ -140,10 +141,10 @@ static uint32_t narcs; 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; +static volatile uint32_t *narcsp; /* Description of the currently profiled object. */ -static long int state; +static long int state = GMON_PROF_OFF; static volatile uint16_t *kcount; static size_t kcountsize; @@ -260,13 +261,24 @@ _dl_start_profile (struct link_map *map, const char *output_dir) fd = __open (filename, O_RDWR | O_CREAT, 0666); if (fd == -1) - /* We cannot write the profiling data so don't do anthing. */ - return; + { + /* We cannot write the profiling data so don't do anthing. */ + char buf[400]; + _dl_sysdep_message (filename, ": cannot open file: ", + _strerror_internal (errno, buf, sizeof buf), + "\n", NULL); + return; + } if (fstat (fd, &st) < 0 || !S_ISREG (st.st_mode)) { /* Not stat'able or not a regular file => don't use it. */ - close (fd); + char buf[400]; + int errnum = errno; + __close (fd); + _dl_sysdep_message (filename, ": cannot stat file: ", + _strerror_internal (errnum, buf, sizeof buf), + "\n", NULL); return; } @@ -286,9 +298,9 @@ _dl_start_profile (struct link_map *map, const char *output_dir) cannot_create: errnum = errno; __close (fd); - _dl_sysdep_error (filename, ": cannot create file: ", - _strerror_internal (errnum, buf, sizeof buf), - "\n", NULL); + _dl_sysdep_message (filename, ": cannot create file: ", + _strerror_internal (errnum, buf, sizeof buf), + "\n", NULL); return; } @@ -304,9 +316,9 @@ _dl_start_profile (struct link_map *map, const char *output_dir) if (addr != NULL) __munmap ((void *) addr, expected_size); - _dl_sysdep_error (filename, - ": file is no correct profile data file for `", - _dl_profile, "'\n", NULL); + _dl_sysdep_message (filename, + ": file is no correct profile data file for `", + _dl_profile, "'\n", NULL); return; } @@ -317,9 +329,9 @@ _dl_start_profile (struct link_map *map, const char *output_dir) char buf[400]; int errnum = errno; __close (fd); - _dl_sysdep_error (filename, ": cannot map file: ", - _strerror_internal (errnum, buf, sizeof buf), - "\n", NULL); + _dl_sysdep_message (filename, ": cannot map file: ", + _strerror_internal (errnum, buf, sizeof buf), + "\n", NULL); return; } @@ -332,10 +344,8 @@ _dl_start_profile (struct link_map *map, const char *output_dir) + sizeof (struct gmon_hist_hdr)); /* Compute pointer to array of the arc information. */ - 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)); + narcsp = (uint32_t *) ((char *) kcount + kcountsize + sizeof (uint32_t)); + data = (struct here_cg_arc_record *) ((char *) narcsp + sizeof (uint32_t)); if (st.st_size == 0) { @@ -346,8 +356,7 @@ _dl_start_profile (struct link_map *map, const char *output_dir) memcpy (hist + sizeof (uint32_t), &hist_hdr, sizeof (struct gmon_hist_hdr)); - *(uint32_t *) (hist + sizeof (uint32_t) + sizeof (struct gmon_hist_hdr) - + kcountsize) = GMON_TAG_CG_ARC; + narcsp[-1] = GMON_TAG_CG_ARC; } else { @@ -356,18 +365,16 @@ _dl_start_profile (struct link_map *map, const char *output_dir) || *(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)) + || narcsp[-1] != GMON_TAG_CG_ARC) goto wrong_format; } /* Allocate memory for the froms data and the pointer to the tos records. */ tos = (uint16_t *) calloc (tossize + fromssize, 1); - if (froms == NULL) + if (tos == NULL) { __munmap ((void *) addr, expected_size); - _dl_sysdep_fatal ("Out of memory while initializing profiler", NULL); + _dl_sysdep_fatal ("Out of memory while initializing profiler\n", NULL); /* NOTREACHED */ } @@ -381,13 +388,12 @@ _dl_start_profile (struct link_map *map, const char *output_dir) 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; ) + for (idx = narcs = MIN (*narcsp, fromlimit); idx > 0; ) { size_t to_index; size_t newfromidx; --idx; - to_index = ((data[idx].self_pc - lowpc) - / (hashfraction * sizeof (*tos))); + to_index = (data[idx].self_pc / (hashfraction * sizeof (*tos))); newfromidx = fromidx++; froms[newfromidx].here = &data[idx]; froms[newfromidx].link = tos[to_index]; @@ -458,18 +464,18 @@ _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc) fromp = &froms[fromp->link]; while (fromp->link != 0 && fromp->here->from_pc != frompc); - if (fromp->link == 0) + if (fromp->here->from_pc != frompc) { topcindex = &fromp->link; check_new_or_add: /* Our entry is not among the entries we read so far from the data file. Now see whether we have to update the list. */ - while (narcs != *narcsp) + while (narcs != *narcsp && narcs < fromlimit) { size_t to_index; size_t newfromidx; - to_index = ((data[narcs].self_pc - lowpc) + to_index = (data[narcs].self_pc / (hashfraction * sizeof (*tos))); newfromidx = fromidx++; froms[newfromidx].here = &data[narcs]; @@ -481,22 +487,22 @@ _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc) /* If we still have no entry stop searching and insert. */ if (*topcindex == 0) { - fromidx = 1 + exchange_and_add (narcsp, 1); - ++narcs; + size_t newarc = 1 + exchange_and_add (narcsp, 1); /* In rare cases it could happen that all entries in FROMS are occupied. So we cannot count this anymore. */ - if (fromidx >= fromlimit) + if (newarc >= fromlimit) goto done; - *topcindex = fromindex; - fromp = &froms[fromindex]; - - fromp = &froms[fromp->link]; + fromp = &froms[*topcindex = fromidx++]; + fromp->here = &data[newarc]; + data[newarc].from_pc = frompc; + data[newarc].self_pc = selfpc; + data[newarc].count = 0; fromp->link = 0; - fromp->here->from_pc = frompc; - fromp->here->count = 0; + + narcs++; break; } diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c index 46c0e1b..e7132ed 100644 --- a/elf/dl-runtime.c +++ b/elf/dl-runtime.c @@ -130,6 +130,8 @@ fixup ( struct link_map **scope = _dl_object_relocation_scope (l); { + const struct r_found_version *here_version; + /* This macro is used as a callback from the elf_machine_relplt code. */ #define RESOLVE(ref, version, flags) \ ((version) != NULL && (version)->hash != 0 \ @@ -147,13 +149,13 @@ fixup ( l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr); ElfW(Half) ndx = version[ELFW(R_SYM) (reloc->r_info)]; - elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)], - &l->l_versions[ndx], - (void *) rel_addr); + here_version = &l->l_versions[ndx]; } else - elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)], - NULL, (void *) rel_addr); + here_version = NULL; + + elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)], + here_version, (void *) rel_addr); } *_dl_global_scope_end = NULL; @@ -194,6 +196,8 @@ profile_fixup ( struct link_map **scope = _dl_object_relocation_scope (l); { + const struct r_found_version *here_version; + /* This macro is used as a callback from the elf_machine_relplt code. */ #define RESOLVE(ref, version, flags) \ ((version) != NULL && (version)->hash != 0 \ @@ -211,19 +215,20 @@ profile_fixup ( l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr); ElfW(Half) ndx = version[ELFW(R_SYM) (reloc->r_info)]; - elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)], - &l->l_versions[ndx], (void *) &result); + here_version = &l->l_versions[ndx]; } else - elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)], - NULL, (void *) &result); + here_version = NULL; + + elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)], + here_version, (void *) &result); } *_dl_global_scope_end = NULL; - (*mcount_fct) (retaddr, result); + (*mcount_fct) (retaddr, ELF_FIXUP_RETURN_VALUE (l, result)); /* Return the address that was written by the relocation. */ - return ELF_FIXUP_RETURN_VALUE(l, result); + return ELF_FIXUP_RETURN_VALUE (l, result); } #endif diff --git a/elf/sofini.c b/elf/sofini.c index e44041b..6da0062 100644 --- a/elf/sofini.c +++ b/elf/sofini.c @@ -7,3 +7,13 @@ static void (*const __CTOR_END__[1]) (void) static void (*const __DTOR_END__[1]) (void) __attribute__ ((unused, section (".dtors"))) = { 0 }; + +#ifdef HAVE_DWARF2_UNWIND_INFO +/* Terminate the frame unwind info section with a 4byte 0 as a sentinel; + this would be the 'length' field in a real FDE. */ + +typedef unsigned int ui32 __attribute__ ((mode (SI))); +static const ui32 __FRAME_END__[1] + __attribute__ ((unused, section (".eh_frame"))) + = { 0 }; +#endif diff --git a/elf/soinit.c b/elf/soinit.c index 0310b74..0c3f5b3 100644 --- a/elf/soinit.c +++ b/elf/soinit.c @@ -17,6 +17,13 @@ run_hooks (void (*const list[]) (void)) (**list) (); } +#ifdef HAVE_DWARF2_UNWIND_INFO +static const char __EH_FRAME_BEGIN__[] + __attribute__ ((section (".eh_frame"))) + = { }; +extern void __register_frame (const void *); +extern void __deregister_frame (const void *); +#endif /* This function will be called from _init in init-first.c. */ void @@ -24,6 +31,9 @@ __libc_global_ctors (void) { /* Call constructor functions. */ run_hooks (__CTOR_LIST__); +#ifdef HAVE_DWARF2_UNWIND_INFO + __register_frame (__EH_FRAME_BEGIN__); +#endif } @@ -35,4 +45,7 @@ _fini (void) { /* Call destructor functions. */ run_hooks (__DTOR_LIST__); +#ifdef HAVE_DWARF2_UNWIND_INFO + __deregister_frame (__EH_FRAME_BEGIN__); +#endif } -- cgit v1.1