This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix LD_PROFILE for hppa and ia64 (1/2)


libc-alpha,

These are the generic changes required to implement a working LD_PROFILE
for hppa and ia64. The current loader crashes on both architectures when
running with LD_PROFILE. Since the profiler cache is really just a copy
of the PLT, we make it the right size for architectures that have
multi-word PLT entries (i.e. PLT contains a function descriptor).  This
involves defining ELF_MACHINE_SIZEOF_JMP_SLOT, and a suitable fallback
for architectures that don't define the value. The actual implementation
requires only a few changes, namely calculating the offset into the
profiler cache. The dl_bind_not case is moved down to facilitate using
ELF_MACHINE_PROFILE_FIXUP_PLT to fixup the cached PLT entry.
ELF_MACHINE_PROFILE_FIXUP_PLT is defined in both ia64's and hppa's
dl-machine.h. ELF_MACHINE_PROFILE_FIXUP_PLT is required since the
function must check if the relocation is already cached, if so there is
no map and the function descriptor can't be generated, so we leave the
cache without modification. The architecture specific patches are next.

Notes:

I had initially thought to fix the broken dl_bind_not case but without
some temporary storage it gets messy. It would require duplicating the
idea of a PLT cache and possibly degrade the common case performance.
If someone is truly interested in fixing LD_BIND_NOT then I might take
another whack at the issue.

Fixes LD_PROFILE on ia64 and hppa. Tested on i386, hppa, ia64 with no
regressions. Simple hppa/ia64 tests with LD_PROFILE=libc.so.6 (or 6.1)
seem to work and sprof.

2004-04-25  Carlos O'Donell  <carlos@baldric.uwo.ca>

	* elf/dl-reloc.c (_dl_relocate_object): Each element in
	l_reloc_result is ELF_MACHINE_SIZEOF_JMP_SLOT bytes.
	* elf/dl-runtime.c (profile_fixup): Calculate correct offset into 
	l_reloc_result array, call ELF_MACHINE_PROFILE_FIXUP_PLT to fixup 
	cached plt slot.
	* elf/dynamic-link.h [!ELF_MACHINE_SIZEOF_JMP_SLOT]:
	Define ELF_MACHINE_SIZEOF_JMP_SLOT to be atleast 
	sizeof ( ElfW(Addr) ).

Index: elf/dl-reloc.c
===================================================================
RCS file: /cvs/glibc/libc/elf/dl-reloc.c,v
retrieving revision 1.96
diff -u -p -r1.96 dl-reloc.c
--- elf/dl-reloc.c	7 Mar 2004 05:21:01 -0000	1.96
+++ elf/dl-reloc.c	5 Apr 2004 02:25:04 -0000
@@ -284,7 +284,7 @@ _dl_relocate_object (struct link_map *l,
 	  }
 
 	l->l_reloc_result =
-	  (ElfW(Addr) *) calloc (sizeof (ElfW(Addr)),
+	  (ElfW(Addr) *) calloc (ELF_MACHINE_SIZEOF_JMP_SLOT,
 				 l->l_info[DT_PLTRELSZ]->d_un.d_val);
 	if (l->l_reloc_result == NULL)
 	  {
Index: elf/dl-runtime.c
===================================================================
RCS file: /cvs/glibc/libc/elf/dl-runtime.c,v
retrieving revision 1.65
diff -u -p -r1.65 dl-runtime.c
--- elf/dl-runtime.c	9 Mar 2004 07:42:59 -0000	1.65
+++ elf/dl-runtime.c	5 Apr 2004 02:25:04 -0000
@@ -137,12 +137,15 @@ profile_fixup (
 {
   void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = INTUSE(_dl_mcount);
   ElfW(Addr) *resultp;
-  lookup_t result;
+  lookup_t result = (lookup_t)(NULL);
   ElfW(Addr) value;
+  const PLTREL *const reloc
+    = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
+  int reloc_result_pos = reloc_offset * ELF_MACHINE_SIZEOF_JMP_SLOT / sizeof(PLTREL);
 
   /* This is the address in the array where we store the result of previous
      relocations.  */
-  resultp = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
+  resultp = l->l_reloc_result + reloc_result_pos;
 
   value = *resultp;
   if (value == 0)
@@ -152,8 +155,6 @@ profile_fixup (
 	= (const void *) D_PTR (l, l_info[DT_SYMTAB]);
       const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
 
-      const PLTREL *const reloc
-	= (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
       const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
 
       /* Sanity check that we're really looking at a PLT relocation.  */
@@ -200,15 +201,25 @@ profile_fixup (
 	}
       /* And now perhaps the relocation addend.  */
       value = elf_machine_plt_value (l, reloc, value);
-
-      /* Store the result for later runs.  */
-      if (__builtin_expect (! GLRO(dl_bind_not), 1))
-	*resultp = value;
     }
 
   (*mcount_fct) (retaddr, value);
 
+  if (__builtin_expect (GLRO(dl_bind_not), 0))
+    return value;
+  
+#ifdef ELF_MACHINE_PROFILE_FIXUP_PLT
+  /* Fixup the l_reloc_result cache, not the real .got/.plt.
+     The "result" could be NULL if looking at a cached reloc. */
+  return ELF_MACHINE_PROFILE_FIXUP_PLT (l, result, reloc, resultp, value);
+#else
+  if (__builtin_expect (result != (lookup_t)(NULL), 0))
+    {
+	/* Store result into the profiler cache before returning */
+        *resultp = value;
+    }
   return value;
+#endif
 }
 
 #endif /* PROF && ELF_MACHINE_NO_PLT */
Index: elf/dynamic-link.h
===================================================================
RCS file: /cvs/glibc/libc/elf/dynamic-link.h,v
retrieving revision 1.50
diff -u -p -r1.50 dynamic-link.h
--- elf/dynamic-link.h	6 Mar 2004 09:47:17 -0000	1.50
+++ elf/dynamic-link.h	5 Apr 2004 02:25:05 -0000
@@ -62,6 +62,9 @@ elf_machine_lazy_rel (struct link_map *m
 # define VERSYMIDX(sym)	(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
 #endif
 
+#ifndef ELF_MACHINE_SIZEOF_JMP_SLOT
+# define ELF_MACHINE_SIZEOF_JMP_SLOT sizeof(ElfW(Addr))
+#endif
 
 /* Read the dynamic section at DYN and fill in INFO with indices DT_*.  */
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]