public inbox for libc-hacker@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Handle new PPC64 ABI .opd symbols in dladdr{,1}
       [not found] ` <20050830001706.GC2687@bubble.grove.modra.org>
@ 2005-08-30 12:54   ` Jakub Jelinek
  2005-08-30 22:33     ` Ulrich Drepper
  0 siblings, 1 reply; 2+ messages in thread
From: Jakub Jelinek @ 2005-08-30 12:54 UTC (permalink / raw)
  To: Ulrich Drepper, Alan Modra; +Cc: Glibc hackers

On Tue, Aug 30, 2005 at 09:47:06AM +0930, Alan Modra wrote:
> On Mon, Aug 29, 2005 at 05:18:40PM +0200, Jakub Jelinek wrote:
> > Is there any (reliable and cheap) way how to recognize new PPC64 ABI (==
> > dotless PPC64 ABI) .opd symbols from the dynamic linker/libc.so?
> > glibc can't use section header table for that (as it can be stripped
> > off and in any case isn't loaded at runtime).
> 
> Yes.  Any STT_FUNC symbol defined outside of the text segment must be in
> the .opd section.  You could use l->l_ld too.
> 
>   ((ELFW(ST_TYPE) (sym->st_info) == STT_FUNC
>     && l->l_addr + sym->st_value >= (ElfW(Addr)) (l->l_ld)
>     && l->l_addr + sym->st_value < l->l_map_end
>     && sym->st_size != 0)

Ok, here is a patch.  On ppc64 dladdr{,1} will with this patch handle
both the function descriptor area as well as actual function code chunk.
Whether size 16 or 24 should be used for the func descriptor is debatable
though.
binutils has support for .opd entry overlap, but upstream GCC doesn't make
use of this, only Red Hat/Fedora GCCs.  If the .opd entries don't overlap,
then each entry is 24 bytes long.  If they do overlap, then the patch
will DTRT in most cases too (as it prefers higher st_values over smaller
ones), but if there is:
|0 |4 |8 |12|16|24
|foo
|     |bar
+--+--+--+
|FN|TC|  |
+--+--+--+--+--+
      |FN|TC|AU|
      +--+--+--+
then dladdr for addr 8 above will return bar, as it has higher st_value.
The only problem is if bar is not an exported symbol, then dladdr for addr 8
will return foo, not nothing.  I think that's ok, but e.g. LSB libchk
would need to be adjusted to handle this.  On the other side, if 16 is used
instead of 24, dladdr will not find any symbol for the third quad in the
.opd entries, even when they are non-overlapping.

2005-08-30  Jakub Jelinek  <jakub@redhat.com>
	    Alan Modra  <amodra@bigpond.net.au>

	* elf/dl-addr.c (_dl_addr): Use DL_ADDR_SYM_MATCH macro.
	* sysdeps/generic/ldsodefs.h (DL_ADDR_SYM_MATCH): Define.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h: New file.

--- libc/elf/dl-addr.c.jj	2005-03-08 13:05:15.000000000 +0100
+++ libc/elf/dl-addr.c	2005-08-30 11:44:35.000000000 +0200
@@ -85,22 +85,15 @@ _dl_addr (const void *address, Dl_info *
 	   the string table which generally follows the symbol table.  */
 	symtabend = (const ElfW(Sym) *) strtab;
 
-      /* We assume that the string table follows the symbol table,
-	 because there is no way in ELF to know the size of the
-	 dynamic symbol table!!  */
       const ElfW(Sym) *matchsym;
       for (matchsym = NULL; (void *) symtab < (void *) symtabend; ++symtab)
-	if (addr >= match->l_addr + symtab->st_value
+	if ((ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
+	     || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
 #if defined USE_TLS
 	    && ELFW(ST_TYPE) (symtab->st_info) != STT_TLS
 #endif
-	    && ((symtab->st_size == 0
-		 && addr == match->l_addr + symtab->st_value)
-		|| addr < match->l_addr + symtab->st_value + symtab->st_size)
-	    && symtab->st_name < strtabsize
-	    && (matchsym == NULL || matchsym->st_value < symtab->st_value)
-	    && (ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
-		|| ELFW(ST_BIND) (symtab->st_info) == STB_WEAK))
+	    && DL_ADDR_SYM_MATCH (match, symtab, matchsym, addr)
+	    && symtab->st_name < strtabsize)
 	  matchsym = (ElfW(Sym) *) symtab;
 
       if (mapp)
--- libc/sysdeps/generic/ldsodefs.h.jj	2005-06-22 18:34:19.000000000 +0200
+++ libc/sysdeps/generic/ldsodefs.h	2005-08-30 12:38:02.000000000 +0200
@@ -62,7 +62,7 @@ typedef struct link_map *lookup_t;
 # define LOOKUP_VALUE(map) map
 # define LOOKUP_VALUE_ADDRESS(map) ((map) ? (map)->l_addr : 0)
 
-/* on some architectures a pointer to a function is not just a pointer
+/* On some architectures a pointer to a function is not just a pointer
    to the actual code of the function but rather an architecture
    specific descriptor. */
 #ifndef ELF_FUNCTION_PTR_IS_SPECIAL
@@ -73,6 +73,14 @@ typedef struct link_map *lookup_t;
 # define DL_DT_FINI_ADDRESS(map, start) (start)
 #endif
 
+/* On some architectures dladdr can't use st_size of all symbols this way.  */
+#define DL_ADDR_SYM_MATCH(L, SYM, MATCHSYM, ADDR) \
+  ((ADDR) >= (L)->l_addr + (SYM)->st_value				\
+   && (((SYM)->st_size == 0						\
+	&& (ADDR) == (L)->l_addr + (SYM)->st_value)			\
+       || (ADDR) < (L)->l_addr + (SYM)->st_value + (SYM)->st_size)	\
+   && ((MATCHSYM) == NULL || (MATCHSYM)->st_value < (SYM)->st_value))
+
 /* Unmap a loaded object, called by _dl_close (). */
 #ifndef DL_UNMAP_IS_SPECIAL
 # define DL_UNMAP(map) \
--- libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h.jj	2005-08-30 11:46:39.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h	2005-08-30 13:11:09.000000000 +0200
@@ -0,0 +1,77 @@
+/* Run-time dynamic linker data structures for loaded ELF shared objects.
+   Copyright (C) 2005 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef	_LDSODEFS_H
+
+/* Get the real definitions.  */
+#include_next <ldsodefs.h>
+
+/* Now define our stuff.  */
+
+static __always_inline bool
+_dl_ppc64_is_opd_sym (const struct link_map *l, const ElfW(Sym) *sym)
+{
+  return (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC
+	  && l->l_addr + sym->st_value >= (ElfW(Addr)) l->l_ld
+	  && l->l_addr + sym->st_value < l->l_map_end
+	  && sym->st_size != 0);
+}
+
+static __always_inline bool
+_dl_ppc64_addr_sym_match (const struct link_map *l, const ElfW(Sym) *sym,
+			  const ElfW(Sym) *matchsym, ElfW(Addr) addr)
+{
+  ElfW(Addr) value = l->l_addr + sym->st_value;
+  if (_dl_ppc64_is_opd_sym (l, sym))
+    {
+      if (addr < value || addr >= value + 24)
+	{
+	  value = *(ElfW(Addr) *) value;
+	  if (addr < value || addr >= value + sym->st_size)
+	    return false;
+	}
+    }
+  else if (sym->st_size == 0)
+    {
+      if (addr != value)
+	return false;
+    }
+  else if (addr < value || addr >= value + sym->st_size)
+    return false;
+
+  if (matchsym == NULL)
+    return true;
+
+  ElfW(Addr) matchvalue = l->l_addr + matchsym->st_value;
+  if (_dl_ppc64_is_opd_sym (l, matchsym)
+      && (addr < matchvalue || addr > matchvalue + 24))
+    matchvalue = *(ElfW(Addr) *) matchvalue;
+
+  return matchvalue < value;
+}
+
+/* If this is a function symbol defined past the end of our dynamic
+   section, then it must be a function descriptor.  Allow these symbols
+   to match their associated function code range as well as the
+   descriptor addresses.  */
+#undef DL_ADDR_SYM_MATCH
+#define DL_ADDR_SYM_MATCH(L, SYM, MATCHSYM, ADDR) \
+  _dl_ppc64_addr_sym_match (L, SYM, MATCHSYM, ADDR)
+
+#endif /* ldsodefs.h */


	Jakub

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] Handle new PPC64 ABI .opd symbols in dladdr{,1}
  2005-08-30 12:54   ` [PATCH] Handle new PPC64 ABI .opd symbols in dladdr{,1} Jakub Jelinek
@ 2005-08-30 22:33     ` Ulrich Drepper
  0 siblings, 0 replies; 2+ messages in thread
From: Ulrich Drepper @ 2005-08-30 22:33 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Alan Modra, Glibc hackers

[-- Attachment #1: Type: text/plain, Size: 101 bytes --]

Applied.

-- 
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 251 bytes --]

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2005-08-30 22:33 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20050829151840.GY15708@sunsite.mff.cuni.cz>
     [not found] ` <20050830001706.GC2687@bubble.grove.modra.org>
2005-08-30 12:54   ` [PATCH] Handle new PPC64 ABI .opd symbols in dladdr{,1} Jakub Jelinek
2005-08-30 22:33     ` Ulrich Drepper

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).