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

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


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

[PATCH] dl_next_phdr (was Re: fde-glibc.c bug)


On Tue, Jul 03, 2001 at 09:49:40AM -0700, Richard Henderson wrote:
> On Tue, Jul 03, 2001 at 05:29:22AM -0400, Jakub Jelinek wrote:
> > > I haven't looked at the problem and won't do it.  Not my job.  I'll
> > > not accept any additional exposure of existing data structures and no
> > > new global variables.
> > 
> > Ok, in that case I guess the only remaining solution is to do what
> > fde-glibc.c does inside of glibc, so that glibc internals don't have to be
> > exposed, because I don't think fde-glibc.c can find the ELF headers of
> > shared libraries just from the link_map exported portion.
> 
> This is unfortunate.  It's not like libgcc is the only application
> that wants to iterate over the set of mapped DSOs.
> 
> I'd be disapointed if the preferred solution was just to take 
> _Unwind_FindTableEntry (or _Unwind_Find_FDE) and drop it into glibc.
> That would mean that the next time someone wanted to do something
> similar, they'd not be able.
> 
> How about a for_each_dso type function that took a callback, takes
> care of the locking, passes the link_map and mapping bounds?  The
> callback returns 0 to keep searching, non-zero is passed back to
> the caller.

How about this?
This one does not have callback, but of course can be easily changed into
one if that is desired.
It does not do any locking (yet), but AFAIC dlsym and other functions don't do any
locking either.
There is another problem too: we don't compute l_phdr nor l_phnum for the
dynamic linker at all. On IA-64 it would be easy to get that using the
segrel trick in the dynamic linker, but as generic solution I can think just
of:
ehdr = (ElfW(Ehdr) *)(_dl_rtld_map.l_addr
		      + (_dl_rtld_map.l_info[DT_HASH]->d_un.d_ptr
			 & ~(ElfW(Addr))1023));
and go from there on.

2001-07-11  Jakub Jelinek  <jakub@redhat.com>

	* elf/Makefile (routines): Add dl-nextphdr and dl-nextphdrs.
	(elide-routines.os): Add dl-nextphdrs.
	* elf/dl-nextphdr.c: New.
	* elf/link.h (struct dl_phdr_info, dl_next_phdr): New.
	* elf/Versions (dl_next_phdr): Add at GLIBC_2.2.4.
	* include/link.h (struct dl_phdr_info): New.
	(dl_next_phdr, __dl_next_phdr): New.
	* sysdeps/generic/dl-nextphdrs.c: New.
	* sysdeps/unix/sysv/linux/ia64/dl-nextphdrs.c: New.

--- libc/elf/Makefile.jj	Mon Jun 25 10:50:33 2001
+++ libc/elf/Makefile	Wed Jul 11 19:11:01 2001
@@ -21,8 +21,9 @@
 subdir		:= elf
 
 headers		= elf.h bits/elfclass.h link.h
-routines	= $(dl-routines) dl-open dl-close dl-support \
-		  dl-addr enbl-secure dl-profstub dl-origin dl-libc dl-sym
+routines	= $(dl-routines) dl-open dl-close dl-support dl-nextphdr \
+		  dl-nextphdrs dl-addr enbl-secure dl-profstub dl-origin \
+		  dl-libc dl-sym
 
 # The core dynamic linking functions are in libc for the static and
 # profiled libraries.
@@ -31,7 +32,7 @@ dl-routines	= $(addprefix dl-,load cache
 				  version profile)
 all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
 # But they are absent from the shared libc, because that code is in ld.so.
-elide-routines.os = $(all-dl-routines) dl-support enbl-secure
+elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-nextphdrs
 
 # ld.so uses those routines, plus some special stuff for being the program
 # interpreter and operating independent of libc.
--- libc/elf/dl-nextphdr.c.jj	Wed Jul 11 17:19:29 2001
+++ libc/elf/dl-nextphdr.c	Wed Jul 11 19:53:37 2001
@@ -0,0 +1,48 @@
+/* Get shared library's program headers.
+   Copyright (C) 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <ldsodefs.h>
+#include <stddef.h>
+
+#ifdef SHARED
+
+const struct link_map *
+__dl_next_phdr (struct dl_phdr_info *info, const struct link_map *l)
+{
+  if (l == NULL)
+    l = _dl_loaded;
+  else
+    l = l->l_next;
+
+  if (l == NULL)
+    {
+      __set_errno (0);
+      return NULL;
+    }
+
+  info->dlpi_phdr = l->l_phdr;
+  info->dlpi_phnum = l->l_phnum;
+  return l;
+}
+
+weak_alias (__dl_next_phdr, dl_next_phdr);
+
+#endif
--- libc/elf/link.h.jj	Wed May 23 09:21:40 2001
+++ libc/elf/link.h	Wed Jul 11 19:27:18 2001
@@ -1,6 +1,6 @@
 /* Data structure for communication from the run-time dynamic linker for
    loaded ELF shared objects.
-   Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1995-1999, 2000, 2001 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
@@ -91,5 +91,31 @@ struct link_map
     ElfW(Dyn) *l_ld;		/* Dynamic section of the shared object.  */
     struct link_map *l_next, *l_prev; /* Chain of loaded objects.  */
   };
+
+#ifdef __USE_GNU
+
+struct dl_phdr_info
+  {
+    const ElfW(Phdr) *dlpi_phdr;
+    ElfW(Half) dlpi_phnum;
+  };
+
+__BEGIN_DECLS
+
+/* This function lets a program step through the loaded object list,
+   returning pointers to link map structure and program headers.
+   If map argument is NULL, it returns the first loaded object's link map
+   and program headers, otherwise map should be a value returned by
+   some other dl_next_phdr call and dl_next_phdr returns the next loaded
+   object's after the specified one.
+   If there are no loaded objects after given one or if there was an error,
+   it returns NULL, setting errno appropriately.  */
+
+const struct link_map * dl_next_phdr (struct dl_phdr_info *info,
+				      const struct link_map * map) __THROW;
+
+__END_DECLS
+
+#endif
 
 #endif /* link.h */
--- libc/elf/Versions.jj	Wed May 23 09:21:37 2001
+++ libc/elf/Versions	Wed Jul 11 19:02:06 2001
@@ -14,6 +14,9 @@ libc {
     # functions used in other libraries
     _dl_sym; _dl_vsym;
   }
+  GLIBC_2.2.4 {
+    dl_next_phdr;
+  }
 }
 
 ld {
--- libc/include/link.h.jj	Mon Jun 25 10:50:33 2001
+++ libc/include/link.h	Wed Jul 11 19:52:08 2001
@@ -239,4 +239,15 @@ struct link_map
     ElfW(Word) l_machine_specific[2];
   };
 
+struct dl_phdr_info
+  {
+    const ElfW(Phdr) *dlpi_phdr;
+    ElfW(Half) dlpi_phnum;
+  };
+
+const struct link_map * dl_next_phdr (struct dl_phdr_info *info,
+				      const struct link_map * map);
+const struct link_map * __dl_next_phdr (struct dl_phdr_info *info,
+					const struct link_map * map);
+
 #endif /* link.h */
--- libc/sysdeps/generic/dl-nextphdrs.c.jj	Wed Jul 11 17:52:27 2001
+++ libc/sysdeps/generic/dl-nextphdrs.c	Wed Jul 11 19:15:28 2001
@@ -0,0 +1,30 @@
+/* Get static program's program headers.
+   Copyright (C) 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <elf/link.h>
+#include <stddef.h>
+
+const struct link_map *
+dl_next_phdr (struct dl_phdr_info *info, const struct link_map *l)
+{
+  __set_errno (ENOSYS);
+  return NULL;
+}
--- libc/sysdeps/unix/sysv/linux/ia64/dl-nextphdrs.c.jj	Wed Jul 11 17:52:27 2001
+++ libc/sysdeps/unix/sysv/linux/ia64/dl-nextphdrs.c	Wed Jul 11 18:50:39 2001
@@ -0,0 +1,59 @@
+/* Get static program's program headers. IA-64 version.
+   Copyright (C) 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <assert.h>
+#include <errno.h>
+#include <elf/link.h>
+#include <stddef.h>
+
+static struct link_map fake_map;
+extern unsigned long ip_segrel;
+
+asm (".section .rodata; ip_segrel: data8 @segrel(ip#); .previous");
+
+const struct link_map *
+dl_next_phdr (struct dl_phdr_info *info, const struct link_map *l)
+{
+  char *ip;
+  ElfW(Ehdr) *ehdr;
+
+  if (l != NULL)
+    {
+      __set_errno (0);
+      return NULL;
+    }
+
+  asm ("ip: mov %0 = ip" : "=r" (ip));
+  ehdr = (ElfW(Ehdr) *) (ip - ip_segrel);
+
+  assert (ehdr->e_ident[0] == 0x7f
+	  && ehdr->e_ident[1] == 'E'
+	  && ehdr->e_ident[2] == 'L'
+	  && ehdr->e_ident[3] == 'F'
+	  && ehdr->e_ident[EI_CLASS] == ELFCLASS64
+	  && ehdr->e_ident[EI_DATA] == ELFDATA2LSB
+	  && ehdr->e_machine == EM_IA_64
+	  && ehdr->e_type == ET_EXEC);
+
+  info->dlpi_phdr = (ElfW(Phdr) *) ((char *) ehdr + ehdr->e_phoff);
+  info->dlpi_phnum = ehdr->e_phnum;
+
+  return &fake_map;
+}

	Jakub


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