Subject: Re: port-amd64/30570: dlopen(..., RTLD_NOW) always returns non-null
To: Christos Zoulas <christos@zoulas.com>
From: Nick Hudson <nick.hudson@dsl.pipex.com>
List: netbsd-bugs
Date: 06/21/2005 07:21:04
--Boundary-00=_h/7tCyO/oKD8yup
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

On Tuesday 21 June 2005 04:22, Christos Zoulas wrote:
> On Jun 21,  4:16am, jlam@NetBSD.org (jlam@NetBSD.org) wrote:
> -- Subject: port-amd64/30570: dlopen(..., RTLD_NOW) always returns non-null
>
> | >Number:         30570
> | >Category:       port-amd64
> | >Synopsis:       dlopen(..., RTLD_NOW) always returns non-null
[...]
> Does this fix your problem?
>
> christos
>
> Index: reloc.c
> ===================================================================
> RCS file: /cvsroot/src/libexec/ld.elf_so/reloc.c,v
> retrieving revision 1.89
> diff -u -u -r1.89 reloc.c
> --- reloc.c	31 May 2005 19:30:38 -0000	1.89
> +++ reloc.c	21 Jun 2005 04:22:32 -0000
> @@ -192,7 +192,7 @@
>  #endif
>  #if defined(__i386__) || defined(__arm__) || defined(__hppa__) \
>
>      || defined(__sparc64__) || defined(__sparc__) || defined(__alpha__) \
>
> -    || defined(__sh3__)
> +    || defined(__sh3__) || defined(__x86_64__)
>  		if (bind_now) {
>  			dbg(("doing immediate PLT binding"));
>  			if (_rtld_relocate_plt_objects(obj) < 0)

You'll need something similiar to the attached patch as well.

Nick

--Boundary-00=_h/7tCyO/oKD8yup
Content-Type: text/x-diff;
  charset="iso-8859-1";
  name="ld.elf_so.x86_64.diffs"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="ld.elf_so.x86_64.diffs"

Index: arch/x86_64/mdreloc.c
===================================================================
RCS file: /cvsroot/src/libexec/ld.elf_so/arch/x86_64/mdreloc.c,v
retrieving revision 1.23
diff -u -r1.23 mdreloc.c
--- arch/x86_64/mdreloc.c	24 Jul 2003 10:12:30 -0000	1.23
+++ arch/x86_64/mdreloc.c	21 Jun 2005 06:18:18 -0000
@@ -84,6 +84,8 @@
 void _rtld_bind_start(void);
 void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
 caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);
+static inline int _rtld_relocate_plt_object(const Obj_Entry *obj,
+    const Elf_Rela *rela, Elf_Addr *tp);
 
 void
 _rtld_setup_pltgot(const Obj_Entry *obj)
@@ -248,10 +250,9 @@
 	return 0;
 }
 
-caddr_t
-_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
+static inline int
+_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp)
 {
-	const Elf_Rela *rela = obj->pltrela + reloff;
 	Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
 	Elf_Addr new_value;
 	const Elf_Sym  *def;
@@ -261,7 +262,7 @@
 
 	def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true);
 	if (def == NULL)
-		_rtld_die();
+		return -1;
 
 	new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
 	    rela->r_addend);
@@ -270,5 +271,34 @@
 	if (*where != new_value)
 		*where = new_value;
 
-	return (caddr_t)(new_value - rela->r_addend);
+	if (tp)
+		*tp = new_value - rela->r_addend;
+
+	return 0;
+}
+
+caddr_t
+_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
+{
+	const Elf_Rela *rela = obj->pltrela + reloff;
+	Elf_Addr new_value;
+	int err;
+
+	err = _rtld_relocate_plt_object(obj, relX, &new_value);
+	if (err)
+		_rtld_die();
+
+	return (caddr_t)new_value;
+}
+
+int
+_rtld_relocate_plt_objects(const Obj_Entry *obj)
+{
+	const Elf_Rela *rela;
+
+	for (rela = obj->pltrela; rela < obj->pltrelalim; rela++)
+		if (_rtld_relocate_plt_object(obj, rela, NULL) < 0)
+			return -1;
+
+	return 0;
 }

--Boundary-00=_h/7tCyO/oKD8yup--