Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Jan 2003 16:56:30 +0100 (CET)
From:      Hartmut Brandt <brandt@fokus.gmd.de>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   sparc64/46870: loader does not resolve module dependencies
Message-ID:  <200301081556.h08FuUGE000695@catssrv.fokus.gmd.de>

next in thread | raw e-mail | index | archive | help

>Number:         46870
>Category:       sparc64
>Synopsis:       loader does not resolve module dependencies
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-sparc
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jan 08 08:00:00 PST 2003
>Closed-Date:
>Last-Modified:
>Originator:     Hartmut Brandt
>Release:        FreeBSD 5.0-CURRENT sparc64
>Organization:
FhI Fokus
>Environment:
System: FreeBSD catssrv.fokus.gmd.de 5.0-CURRENT FreeBSD 5.0-CURRENT #3: Tue Jan 7 18:15:41 CET 2003 root@catssrv.fokus.gmd.de:/opt/obj/usr/src/sys/CATSSRV sparc64


	
>Description:

The boot loader does not resolve module dependencies and does not load
modules upon which a given module depends.

	
>How-To-Repeat:

Build if_hme.ko and insert the following line into /boot/loader.conf:

	if_hme_load="YES"

Reboot and observe the loader to load if_hme.ko but not miibus.ko. Observe
further that the kernel later on reports a missing dependency of hme on
miibus.

	
>Fix:

The problem is the same as with kldxref and the kernel linker: the loader
fails to process relocation correctly by assuming that only REL records exist.
The correct fix is to have machine dependent relocation routines call from
load_elf.c. This is somewhat complicated by the fact, that load_elf itself
is called via a machine dependent function pointer.

The attached patch is
a hack rather than a fix. Based on the precedent of an #ifdef __i386__
in load_elf.c, MD processing is done for __sparc__ in load_elf.c to do
just enough relocation processing to correctly access dependency information.
Note, that this does not really relocate the loaded image - this is done later
in the kernel linker. Instead local copies of the pointers are relocated.
	

Index: load_elf.c
===================================================================
RCS file: /usr/ncvs/src/sys/boot/common/load_elf.c,v
retrieving revision 1.24
diff -c -r1.24 load_elf.c
*** load_elf.c	10 May 2002 01:20:37 -0000	1.24
--- load_elf.c	8 Jan 2003 15:47:10 -0000
***************
*** 52,57 ****
--- 52,61 ----
      Elf_Hashelt	nchains;
      Elf_Hashelt	*buckets;
      Elf_Hashelt	*chains;
+ #ifdef __sparc__
+     Elf_Rela	*rela;
+     size_t	relasz;
+ #endif
      char	*strtab;
      size_t	strsz;
      int		fd;
***************
*** 63,68 ****
--- 67,76 ----
  
  static int elf_loadimage(struct preloaded_file *mp, elf_file_t ef, vm_offset_t loadaddr);
  static int elf_lookup_symbol(struct preloaded_file *mp, elf_file_t ef, const char* name,	Elf_Sym* sym);
+ #ifdef __sparc__
+ static void elf_reloc_ptr(struct preloaded_file *mp, elf_file_t ef,
+     void *p, void *val, size_t len);
+ #endif
  static int elf_parse_modmetadata(struct preloaded_file *mp, elf_file_t ef);
  static char	*fake_modname(const char *name);
  
***************
*** 491,496 ****
--- 499,512 ----
  	case DT_SYMTAB:
  	    ef->symtab = (Elf_Sym*)(dp[i].d_un.d_ptr + off);
  	    break;
+ #ifdef __sparc__
+ 	case DT_RELA:
+ 	    ef->rela = (Elf_Rela *)(dp[i].d_un.d_ptr + off);
+ 	    break;
+ 	case DT_RELASZ:
+ 	    ef->relasz = dp[i].d_un.d_val;
+ 	    break;
+ #endif
  	default:
  	    break;
  	}
***************
*** 566,591 ****
--- 582,628 ----
  
      modcnt = 0;
      while (p < p_stop) {
+ #ifdef __sparc__
+ 	COPYOUT(p, &v, sizeof(v));
+ 	elf_reloc_ptr(fp, ef, p, &v, sizeof(v));
+ 	COPYOUT(v, &md, sizeof(md));
+ 	elf_reloc_ptr(fp, ef, v, &md, sizeof(md));
+ 	p++;
+ #else
  	COPYOUT(p++, &v, sizeof(v));
  	COPYOUT(v + ef->off, &md, sizeof(md));
+ #endif
  	switch(md.md_type) {
  	  case MDT_DEPEND:
  	    if (ef->kernel)		/* kernel must not depend on anything */
  	      break;
+ #ifdef __sparc__
+ 	    s = strdupout((vm_offset_t)md.md_cval);
+ #else
  	    s = strdupout((vm_offset_t)(md.md_cval + ef->off));
+ #endif
  	    minfolen = sizeof(*mdepend) + strlen(s) + 1;
  	    mdepend = malloc(minfolen);
  	    if (mdepend == NULL)
  		return ENOMEM;
+ #ifdef __sparc__
+ 	    COPYOUT((vm_offset_t)md.md_data, mdepend, sizeof(*mdepend));
+ #else
  	    COPYOUT((vm_offset_t)(md.md_data + ef->off), mdepend, sizeof(*mdepend));
+ #endif
  	    strcpy((char*)(mdepend + 1), s);
  	    free(s);
  	    file_addmetadata(fp, MODINFOMD_DEPLIST, minfolen, mdepend);
  	    free(mdepend);
  	    break;
  	  case MDT_VERSION:
+ #ifdef __sparc__
+ 	    s = strdupout((vm_offset_t)md.md_cval);
+ 	    COPYOUT((vm_offset_t)md.md_data, &mver, sizeof(mver));
+ #else
  	    s = strdupout((vm_offset_t)(md.md_cval + ef->off));
  	    COPYOUT((vm_offset_t)(md.md_data + ef->off), &mver, sizeof(mver));
+ #endif
  	    file_addmodule(fp, s, mver.mv_version, NULL);
  	    free(s);
  	    modcnt++;
***************
*** 657,659 ****
--- 694,723 ----
      }
      return ENOENT;
  }
+ 
+ #ifdef __sparc__
+ /*
+  * Apply any intra-module relocations to the value. *p is the load address
+  * of the value and val/len is the value to be modified. This does NOT modify
+  * the image in-place, because this is done by kern_linker later on.
+  */
+ static void
+ elf_reloc_ptr(struct preloaded_file *mp, elf_file_t ef,
+     void *p, void *val, size_t len)
+ {
+ 	Elf_Addr off = (Elf_Addr)p - ef->off, word;
+ 	size_t n;
+ 	Elf_Rela r;
+ 
+ 	for (n = 0; n < ef->relasz / sizeof(r); n++) {
+ 		COPYOUT(ef->rela + n, &r, sizeof(r));
+ 
+ 		if (r.r_offset >= off && r.r_offset < off + len &&
+ 		    ELF_R_TYPE(r.r_info) == R_SPARC_RELATIVE) {
+ 			word = ef->off + r.r_addend;
+ 			bcopy(&word, (char *)val + (r.r_offset - off),
+ 			    sizeof(word));
+ 		}
+ 	}
+ }
+ #endif

>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-sparc" in the body of the message




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