Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 10 Oct 2009 15:27:10 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r197931 - head/libexec/rtld-elf
Message-ID:  <200910101527.n9AFRAwQ085645@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sat Oct 10 15:27:10 2009
New Revision: 197931
URL: http://svn.freebsd.org/changeset/base/197931

Log:
  Calculate relocation base for the main object, and apply the relocation
  adjustment for all virtual addresses encoded into the ELF structures of
  it. PIE binary could and should be loaded at non-zero mapbase.
  
  For sym_zero pseudosymbol used as a return value from find_symdef()
  for undefined weak symbols, st_value also should be adjusted, since
  _rtld_bind corrects symbol values by relocbase.
  
  Discussed with:	bz
  Reviewed by:	kan
  Tested by:	bz (i386, amd64), bsam (linux)
  MFC after:	some time

Modified:
  head/libexec/rtld-elf/rtld.c

Modified: head/libexec/rtld-elf/rtld.c
==============================================================================
--- head/libexec/rtld-elf/rtld.c	Sat Oct 10 14:56:34 2009	(r197930)
+++ head/libexec/rtld-elf/rtld.c	Sat Oct 10 15:27:10 2009	(r197931)
@@ -474,6 +474,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_
     /* Initialize a fake symbol for resolving undefined weak references. */
     sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
     sym_zero.st_shndx = SHN_UNDEF;
+    sym_zero.st_value = -(uintptr_t)obj_main->relocbase;
 
     if (!libmap_disable)
         libmap_disable = (bool)lm_init(libmap_override);
@@ -991,26 +992,26 @@ digest_phdr(const Elf_Phdr *phdr, int ph
 
     obj = obj_new();
     for (ph = phdr;  ph < phlimit;  ph++) {
-	switch (ph->p_type) {
+	if (ph->p_type != PT_PHDR)
+	    continue;
 
-	case PT_PHDR:
-	    if ((const Elf_Phdr *)ph->p_vaddr != phdr) {
-		_rtld_error("%s: invalid PT_PHDR", path);
-		return NULL;
-	    }
-	    obj->phdr = (const Elf_Phdr *) ph->p_vaddr;
-	    obj->phsize = ph->p_memsz;
-	    break;
+	obj->phdr = phdr;
+	obj->phsize = ph->p_memsz;
+	obj->relocbase = (caddr_t)phdr - ph->p_vaddr;
+	break;
+    }
+
+    for (ph = phdr;  ph < phlimit;  ph++) {
+	switch (ph->p_type) {
 
 	case PT_INTERP:
-	    obj->interp = (const char *) ph->p_vaddr;
+	    obj->interp = (const char *)(ph->p_vaddr + obj->relocbase);
 	    break;
 
 	case PT_LOAD:
 	    if (nsegs == 0) {	/* First load segment */
 		obj->vaddrbase = trunc_page(ph->p_vaddr);
-		obj->mapbase = (caddr_t) obj->vaddrbase;
-		obj->relocbase = obj->mapbase - obj->vaddrbase;
+		obj->mapbase = obj->vaddrbase + obj->relocbase;
 		obj->textsize = round_page(ph->p_vaddr + ph->p_memsz) -
 		  obj->vaddrbase;
 	    } else {		/* Last load segment */
@@ -1021,7 +1022,7 @@ digest_phdr(const Elf_Phdr *phdr, int ph
 	    break;
 
 	case PT_DYNAMIC:
-	    obj->dynamic = (const Elf_Dyn *) ph->p_vaddr;
+	    obj->dynamic = (const Elf_Dyn *)(ph->p_vaddr + obj->relocbase);
 	    break;
 
 	case PT_TLS:
@@ -1029,7 +1030,7 @@ digest_phdr(const Elf_Phdr *phdr, int ph
 	    obj->tlssize = ph->p_memsz;
 	    obj->tlsalign = ph->p_align;
 	    obj->tlsinitsize = ph->p_filesz;
-	    obj->tlsinit = (void*) ph->p_vaddr;
+	    obj->tlsinit = (void*)(ph->p_vaddr + obj->relocbase);
 	    break;
 	}
     }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200910101527.n9AFRAwQ085645>