summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1997-09-24 23:03:42 +0000
committerUlrich Drepper <drepper@redhat.com>1997-09-24 23:03:42 +0000
commit650425ceb40e840b2123b6c8cc65389589f41218 (patch)
tree70ff83fbe8f34a7829b4a0b511d2cb02ccbcbf2a /elf
parent2604afb1b2d9acc3c70b1214285f996200bf0358 (diff)
downloadglibc-650425ceb40e840b2123b6c8cc65389589f41218.tar.gz
glibc-650425ceb40e840b2123b6c8cc65389589f41218.tar.xz
glibc-650425ceb40e840b2123b6c8cc65389589f41218.zip
1997-09-25 00:23  Ulrich Drepper  <drepper@cygnus.com>

	* 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  <Philip.Blundell@pobox.com>

	* 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  <Philip.Blundell@pobox.com>

	* csu/Makefile (before-compile): Don't try to build abi-tags.h if
	not using ELF.

1997-09-21  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* 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  <geoffk@ozemail.com.au>

	* 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  <schwab@issan.informatik.uni-dortmund.de>

	* 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  <kukuk@vt.uni-paderborn.de>

	* 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  <zack@rabi.phys.columbia.edu>

	* 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  <kukuk@vt.uni-paderborn.de>

	* 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  <schwab@issan.informatik.uni-dortmund.de>

	* 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  <drepper@cygnus.com>

	* sysdeps/i386/i486/atomicity.h (exchange_and_add): Really address
	memory in xadd not %1.

1997-09-21 13:56  Ulrich Drepper  <drepper@cygnus.com>

	* manual/maint.texi (Supported Configurations): Add SPARC64 to
	list of supported platforms.
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-profile.c88
-rw-r--r--elf/dl-runtime.c27
-rw-r--r--elf/sofini.c10
-rw-r--r--elf/soinit.c13
4 files changed, 86 insertions, 52 deletions
diff --git a/elf/dl-profile.c b/elf/dl-profile.c
index 9b020e8fe9..dcbbcd026e 100644
--- a/elf/dl-profile.c
+++ b/elf/dl-profile.c
@@ -30,6 +30,7 @@
 #include <sys/gmon.h>
 #include <sys/gmon_out.h>
 #include <sys/mman.h>
+#include <sys/param.h>
 #include <sys/stat.h>
 #include <atomicity.h>
 
@@ -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 46c0e1b8ab..e7132ed832 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 e44041b5ec..6da0062d06 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 0310b74b93..0c3f5b3163 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
 }