Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 3 Jan 2003 16:29:12 +0100 (CET)
From:      Hartmut Brandt <brandt@fokus.gmd.de>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   sparc64/46732: kernel linker cannot resolve dependencies
Message-ID:  <200301031529.h03FTCMT003875@catssrv.fokus.gmd.de>

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

>Number:         46732
>Category:       sparc64
>Synopsis:       kernel linker cannot resolve dependencies
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-sparc
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jan 03 07:30:03 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 #20: Fri Jan 3 14:08:11 CET 2003 hbb@catssrv.fokus.gmd.de:/opt/obj/usr/src/sys/CATSSRV sparc64


	
>Description:

The kernel linker (kern_linker.c) needs to access module metadata in the
module it tries to load to resolve dependencies. This access involves pointers
and therefor relocation is needed to correctly access these pointers. The
kernel linker uses a routine linker_reloc_ptr, that assumes, that all relocation
of pointers is done via ELF REL relocation records, by adding the original
contents of the pointer to relocate (as red from the file) to the load address.
This does not work for sparc64 because sparc64 uses RELA records, where the
value to add is in the relocation records itself not in the location to be
relocated. This leads to the kernel linker access random locations in memory
and not beeing able to process dependency information.

An unrelated problem are some wrong printf format characters in the linker
debugging code.

	
>How-To-Repeat:

Compile the modules netgraph.ko and ng_socket.ko and try to load ng_socket via

	kldload ng_socket

observer /var/log/message to contain a kernel message about an unresolved
external symbol.

	
>Fix:

The fix is to move the relocation entirely to the MD file, where it belongs to.
This is done, by removing all the relocation stuff from kern_linker.c and
expect elf linker link_elf.c to process all intra-module relocation before
the linker tries to access module metadata.

In link_elf.c there are two places affected. For preloaded modules local
relocations are processed just before returning to the linker and for
kldloaded modules before calling linker_load_dependencies. This is done
by a function link_elf_reloc_local, which loops through all relocation
records and calling the MD elf_reloc_local.

In the MD parts elf_reloc is split. elf_reloc_local processes all relocations
that are intra-module (R_*_RELATIVE) and ignores all others. elf_reloc
ignores all intra-module relocations and processes all others.

The first of the following two patches changes kern_linker, link_elf,
i386/i386/elf_machdep.c and sparc64/sparc64/elf_machdep.c in the way described.
This patch has been tested on both i386 and sparc64. It corrects also
some broken printf format strings for the debugging code.

The seconds patch applies to alpha/alpha/elf_machdep.c and
ia64/ia64/elf_machdep.c and has neither been compiled nor tested
(I have no IA64 or Alpha), but should be simple to verify.

-------------- PATCH 1 -------------------------------------------


Index: kern/kern_linker.c
===================================================================
RCS file: /usr/ncvs/src/sys/kern/kern_linker.c,v
retrieving revision 1.101
diff -c -r1.101 kern_linker.c
*** kern/kern_linker.c	14 Dec 2002 08:18:05 -0000	1.101
--- kern/kern_linker.c	3 Jan 2003 12:15:30 -0000
***************
*** 499,505 ****
  			 * Give the module a chance to veto the unload.
  			 */
  			if ((error = module_unload(mod)) != 0) {
! 				KLD_DPF(FILE, ("linker_file_unload: module %x"
  				    " vetoes unload\n", mod));
  				goto out;
  			} else
--- 499,505 ----
  			 * Give the module a chance to veto the unload.
  			 */
  			if ((error = module_unload(mod)) != 0) {
! 				KLD_DPF(FILE, ("linker_file_unload: module %p"
  				    " vetoes unload\n", mod));
  				goto out;
  			} else
***************
*** 594,600 ****
  	size_t common_size = 0;
  	int i;
  
! 	KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%x, name=%s, deps=%d\n",
  	    file, name, deps));
  
  	if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) {
--- 594,600 ----
  	size_t common_size = 0;
  	int i;
  
! 	KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n",
  	    file, name, deps));
  
  	if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) {
***************
*** 608,614 ****
  			common_size = symval.size;
  		else {
  			KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol"
! 			    ".value=%x\n", symval.value));
  			return (symval.value);
  		}
  	}
--- 608,614 ----
  			common_size = symval.size;
  		else {
  			KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol"
! 			    ".value=%p\n", symval.value));
  			return (symval.value);
  		}
  	}
***************
*** 618,624 ****
  			    name, 0);
  			if (address) {
  				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
! 				    " deps value=%x\n", address));
  				return (address);
  			}
  		}
--- 618,624 ----
  			    name, 0);
  			if (address) {
  				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
! 				    " deps value=%p\n", address));
  				return (address);
  			}
  		}
***************
*** 634,640 ****
  		STAILQ_FOREACH(cp, &file->common, link) {
  			if (strcmp(cp->name, name) == 0) {
  				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
! 				    " old common value=%x\n", cp->address));
  				return (cp->address);
  			}
  		}
--- 634,640 ----
  		STAILQ_FOREACH(cp, &file->common, link) {
  			if (strcmp(cp->name, name) == 0) {
  				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
! 				    " old common value=%p\n", cp->address));
  				return (cp->address);
  			}
  		}
***************
*** 656,662 ****
  		STAILQ_INSERT_TAIL(&file->common, cp, link);
  
  		KLD_DPF(SYM, ("linker_file_lookup_symbol: new common"
! 		    " value=%x\n", cp->address));
  		return (cp->address);
  	}
  	KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n"));
--- 656,662 ----
  		STAILQ_INSERT_TAIL(&file->common, cp, link);
  
  		KLD_DPF(SYM, ("linker_file_lookup_symbol: new common"
! 		    " value=%p\n", cp->address));
  		return (cp->address);
  	}
  	KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n"));
***************
*** 1106,1151 ****
  	return (mod);
  }
  
- /*
-  * This routine is cheap and nasty but will work for data pointers.
-  */
- static void *
- linker_reloc_ptr(linker_file_t lf, const void *offset)
- {
- 	return (lf->address + (uintptr_t)offset);
- }
- 
- /*
-  * Dereference MDT_VERSION metadata into module name and version
-  */
- static void
- linker_mdt_version(linker_file_t lf, struct mod_metadata *mp,
-     const char **modname, int *version)
- {
- 	struct mod_version *mvp;
- 
- 	if (modname)
- 		*modname = linker_reloc_ptr(lf, mp->md_cval);
- 	if (version) {
- 		mvp = linker_reloc_ptr(lf, mp->md_data);
- 		*version = mvp->mv_version;
- 	}
- }
- 
- /*
-  * Dereference MDT_DEPEND metadata into module name and mod_depend structure
-  */
- static void
- linker_mdt_depend(linker_file_t lf, struct mod_metadata *mp,
-     const char **modname, struct mod_depend **verinfo)
- {
- 
- 	if (modname)
- 		*modname = linker_reloc_ptr(lf, mp->md_cval);
- 	if (verinfo)
- 		*verinfo = linker_reloc_ptr(lf, mp->md_data);
- }
- 
  static void
  linker_addmodules(linker_file_t lf, struct mod_metadata **start,
      struct mod_metadata **stop, int preload)
--- 1106,1111 ----
***************
*** 1155,1171 ****
  	int ver;
  
  	for (mdp = start; mdp < stop; mdp++) {
! 		if (preload)
! 			mp = *mdp;
! 		else
! 			mp = linker_reloc_ptr(lf, *mdp);
  		if (mp->md_type != MDT_VERSION)
  			continue;
! 		if (preload) {
! 			modname = mp->md_cval;
! 			ver = ((struct mod_version *)mp->md_data)->mv_version;
! 		} else
! 	        	linker_mdt_version(lf, mp, &modname, &ver);
  		if (modlist_lookup(modname, ver) != NULL) {
  			printf("module %s already present!\n", modname);
  			/* XXX what can we do? this is a build error. :-( */
--- 1115,1125 ----
  	int ver;
  
  	for (mdp = start; mdp < stop; mdp++) {
! 		mp = *mdp;
  		if (mp->md_type != MDT_VERSION)
  			continue;
! 		modname = mp->md_cval;
! 		ver = ((struct mod_version *)mp->md_data)->mv_version;
  		if (modlist_lookup(modname, ver) != NULL) {
  			printf("module %s already present!\n", modname);
  			/* XXX what can we do? this is a build error. :-( */
***************
*** 1249,1266 ****
  		resolves = 1;	/* unless we know otherwise */
  		if (!error) {
  			for (mdp = start; mdp < stop; mdp++) {
! 				mp = linker_reloc_ptr(lf, *mdp);
  				if (mp->md_type != MDT_DEPEND)
  					continue;
! 				linker_mdt_depend(lf, mp, &modname, &verinfo);
  				for (nmdp = start; nmdp < stop; nmdp++) {
! 					nmp = linker_reloc_ptr(lf, *nmdp);
  					if (nmp->md_type != MDT_VERSION)
  						continue;
! 					linker_mdt_version(lf, nmp, &nmodname,
! 					    NULL);
! 					nmodname = linker_reloc_ptr(lf,
! 					    nmp->md_cval);
  					if (strcmp(modname, nmodname) == 0)
  						break;
  				}
--- 1203,1218 ----
  		resolves = 1;	/* unless we know otherwise */
  		if (!error) {
  			for (mdp = start; mdp < stop; mdp++) {
! 				mp = *mdp;
  				if (mp->md_type != MDT_DEPEND)
  					continue;
! 				modname = mp->md_cval;
! 				verinfo = mp->md_data;
  				for (nmdp = start; nmdp < stop; nmdp++) {
! 					nmp = *nmdp;
  					if (nmp->md_type != MDT_VERSION)
  						continue;
! 					nmodname = nmp->md_cval;
  					if (strcmp(modname, nmodname) == 0)
  						break;
  				}
***************
*** 1283,1293 ****
  		if (resolves) {
  			if (!error) {
  				for (mdp = start; mdp < stop; mdp++) {
! 					mp = linker_reloc_ptr(lf, *mdp);
  					if (mp->md_type != MDT_VERSION)
  						continue;
! 					linker_mdt_version(lf, mp,
! 					    &modname, &nver);
  					if (modlist_lookup(modname,
  					    nver) != NULL) {
  						printf("module %s already"
--- 1235,1246 ----
  		if (resolves) {
  			if (!error) {
  				for (mdp = start; mdp < stop; mdp++) {
! 					mp = *mdp;
  					if (mp->md_type != MDT_VERSION)
  						continue;
! 					modname = mp->md_cval;
! 					nver = ((struct mod_version *)
! 					    mp->md_data)->mv_version;
  					if (modlist_lookup(modname,
  					    nver) != NULL) {
  						printf("module %s already"
***************
*** 1338,1347 ****
  		    &stop, NULL);
  		if (!error) {
  			for (mdp = start; mdp < stop; mdp++) {
! 				mp = linker_reloc_ptr(lf, *mdp);
  				if (mp->md_type != MDT_DEPEND)
  					continue;
! 				linker_mdt_depend(lf, mp, &modname, &verinfo);
  				mod = modlist_lookup2(modname, verinfo);
  				mod->container->refs++;
  				error = linker_file_add_dependency(lf,
--- 1291,1301 ----
  		    &stop, NULL);
  		if (!error) {
  			for (mdp = start; mdp < stop; mdp++) {
! 				mp = *mdp;
  				if (mp->md_type != MDT_DEPEND)
  					continue;
! 				modname = mp->md_cval;
! 				verinfo = mp->md_data;
  				mod = modlist_lookup2(modname, verinfo);
  				mod->container->refs++;
  				error = linker_file_add_dependency(lf,
***************
*** 1763,1772 ****
  	    &count) != 0)
  		return (0);
  	for (mdp = start; mdp < stop; mdp++) {
! 		mp = linker_reloc_ptr(lf, *mdp);
  		if (mp->md_type != MDT_VERSION)
  			continue;
! 		linker_mdt_version(lf, mp, &modname, &ver);
  		mod = modlist_lookup(modname, ver);
  		if (mod != NULL) {
  			printf("interface %s.%d already present in the KLD"
--- 1717,1727 ----
  	    &count) != 0)
  		return (0);
  	for (mdp = start; mdp < stop; mdp++) {
! 		mp = *mdp;
  		if (mp->md_type != MDT_VERSION)
  			continue;
! 		modname = mp->md_cval;
! 		ver = ((struct mod_version *)mp->md_data)->mv_version;
  		mod = modlist_lookup(modname, ver);
  		if (mod != NULL) {
  			printf("interface %s.%d already present in the KLD"
***************
*** 1777,1792 ****
  	}
  
  	for (mdp = start; mdp < stop; mdp++) {
! 		mp = linker_reloc_ptr(lf, *mdp);
  		if (mp->md_type != MDT_DEPEND)
  			continue;
! 		linker_mdt_depend(lf, mp, &modname, &verinfo);
  		nmodname = NULL;
  		for (nmdp = start; nmdp < stop; nmdp++) {
! 			nmp = linker_reloc_ptr(lf, *nmdp);
  			if (nmp->md_type != MDT_VERSION)
  				continue;
! 			nmodname = linker_reloc_ptr(lf, nmp->md_cval);
  			if (strcmp(modname, nmodname) == 0)
  				break;
  		}
--- 1732,1748 ----
  	}
  
  	for (mdp = start; mdp < stop; mdp++) {
! 		mp = *mdp;
  		if (mp->md_type != MDT_DEPEND)
  			continue;
! 		modname = mp->md_cval;
! 		verinfo = mp->md_data;
  		nmodname = NULL;
  		for (nmdp = start; nmdp < stop; nmdp++) {
! 			nmp = *nmdp;
  			if (nmp->md_type != MDT_VERSION)
  				continue;
! 			nmodname = nmp->md_cval;
  			if (strcmp(modname, nmodname) == 0)
  				break;
  		}
Index: kern/link_elf.c
===================================================================
RCS file: /usr/ncvs/src/sys/kern/link_elf.c,v
retrieving revision 1.68
diff -c -r1.68 link_elf.c
*** kern/link_elf.c	19 Nov 2002 22:12:42 -0000	1.68
--- kern/link_elf.c	3 Jan 2003 11:34:31 -0000
***************
*** 116,121 ****
--- 116,122 ----
  static int	link_elf_each_function_name(linker_file_t,
  				int (*)(const char *, void *),
  				void *);
+ static void	link_elf_reloc_local(linker_file_t);
  
  static kobj_method_t link_elf_methods[] = {
      KOBJMETHOD(linker_lookup_symbol,	link_elf_lookup_symbol),
***************
*** 488,493 ****
--- 489,495 ----
  	linker_file_unload(lf);
  	return error;
      }
+     link_elf_reloc_local(lf);
      *result = lf;
      return (0);
  }
***************
*** 748,753 ****
--- 750,757 ----
      error = parse_dynamic(ef);
      if (error)
  	goto out;
+     link_elf_reloc_local(lf);
+ 
      error = linker_load_dependencies(lf);
      if (error)
  	goto out;
***************
*** 1265,1268 ****
--- 1269,1300 ----
  		return (0);
  
  	return ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps));
+ }
+ 
+ static void
+ link_elf_reloc_local(linker_file_t lf)
+ {
+     const Elf_Rel *rellim;
+     const Elf_Rel *rel;
+     const Elf_Rela *relalim;
+     const Elf_Rela *rela;
+     elf_file_t ef = (elf_file_t)lf;
+ 
+     /* Perform relocations without addend if there are any: */
+     if ((rel = ef->rel) != NULL) {
+ 	rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize);
+ 	while (rel < rellim) {
+ 	    elf_reloc_local(lf, rel, ELF_RELOC_REL);
+ 	    rel++;
+ 	}
+     }
+ 
+     /* Perform relocations with addend if there are any: */
+     if ((rela = ef->rela) != NULL) {
+ 	relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize);
+ 	while (rela < relalim) {
+ 	    elf_reloc_local(lf, rela, ELF_RELOC_RELA);
+ 	    rela++;
+ 	}
+     }
  }
Index: sparc64/sparc64/elf_machdep.c
===================================================================
RCS file: /usr/ncvs/src/sys/sparc64/sparc64/elf_machdep.c,v
retrieving revision 1.12
diff -c -r1.12 elf_machdep.c
*** sparc64/sparc64/elf_machdep.c	2 Dec 2002 18:56:30 -0000	1.12
--- sparc64/sparc64/elf_machdep.c	3 Jan 2003 11:26:10 -0000
***************
*** 235,240 ****
--- 235,262 ----
  };
  #define RELOC_VALUE_BITMASK(t)	(reloc_target_bitmask[t])
  
+ int
+ elf_reloc_local(linker_file_t lf, const void *data, int type)
+ {
+ 	const Elf_Rela *rela;
+ 	Elf_Addr value;
+ 	Elf_Addr *where;
+ 
+ 	if (type != ELF_RELOC_RELA)
+ 		return (-1);
+ 
+ 	rela = (const Elf_Rela *)data;
+ 	if (ELF_R_TYPE(rela->r_info) != R_SPARC_RELATIVE)
+ 		return (-1);
+ 
+ 	value = rela->r_addend + (Elf_Addr)lf->address;
+ 	where = (Elf_Addr *)((Elf_Addr)lf->address + rela->r_offset);
+ 
+ 	*where = value;
+ 
+ 	return (0);
+ }
+ 
  /* Process one elf relocation with addend. */
  int
  elf_reloc(linker_file_t lf, const void *data, int type)
***************
*** 258,264 ****
  	rtype = ELF_R_TYPE(rela->r_info);
  	symidx = ELF_R_SYM(rela->r_info);
  
! 	if (rtype == R_SPARC_NONE)
  		return (0);
  
  	if (rtype == R_SPARC_JMP_SLOT || rtype == R_SPARC_COPY ||
--- 280,286 ----
  	rtype = ELF_R_TYPE(rela->r_info);
  	symidx = ELF_R_SYM(rela->r_info);
  
! 	if (rtype == R_SPARC_NONE || rtype == R_SPARC_RELATIVE)
  		return (0);
  
  	if (rtype == R_SPARC_JMP_SLOT || rtype == R_SPARC_COPY ||
Index: i386/i386/elf_machdep.c
===================================================================
RCS file: /usr/ncvs/src/sys/i386/i386/elf_machdep.c,v
retrieving revision 1.12
diff -c -r1.12 elf_machdep.c
*** i386/i386/elf_machdep.c	19 Oct 2002 19:16:03 -0000	1.12
--- i386/i386/elf_machdep.c	3 Jan 2003 11:25:49 -0000
***************
*** 86,93 ****
  	&freebsd_brand_info);
  
  /* Process one elf relocation with addend. */
! int
! elf_reloc(linker_file_t lf, const void *data, int type)
  {
  	Elf_Addr relocbase = (Elf_Addr) lf->address;
  	Elf_Addr *where;
--- 86,93 ----
  	&freebsd_brand_info);
  
  /* Process one elf relocation with addend. */
! static int
! elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
  {
  	Elf_Addr relocbase = (Elf_Addr) lf->address;
  	Elf_Addr *where;
***************
*** 116,121 ****
--- 116,130 ----
  		panic("unknown reloc type %d\n", type);
  	}
  
+ 	if (local) {
+ 		if (rtype == R_386_RELATIVE) {	/* A + B */
+ 			addr = relocbase + addend;
+ 			if (*where != addr)
+ 				*where = addr;
+ 		}
+ 		return (0);
+ 	}
+ 
  	switch (rtype) {
  
  		case R_386_NONE:	/* none */
***************
*** 156,165 ****
  				*where = addr;
  			break;
  
! 		case R_386_RELATIVE:	/* B + A */
! 			addr = relocbase + addend;
! 			if (*where != addr)
! 				*where = addr;
  			break;
  
  		default:
--- 165,171 ----
  				*where = addr;
  			break;
  
! 		case R_386_RELATIVE:
  			break;
  
  		default:
***************
*** 168,173 ****
--- 174,191 ----
  			return -1;
  	}
  	return(0);
+ }
+ 
+ int
+ elf_reloc(linker_file_t lf, const void *data, int type)
+ {
+ 	return (elf_reloc_internal(lf, data, type, 0));
+ }
+ 
+ int
+ elf_reloc_local(linker_file_t lf, const void *data, int type)
+ {
+ 	return (elf_reloc_internal(lf, data, type, 1));
  }
  
  int
	


-------------- PATCH 2 -------------------------------------------
Index: ia64/ia64/elf_machdep.c
===================================================================
RCS file: /usr/ncvs/src/sys/ia64/ia64/elf_machdep.c,v
retrieving revision 1.9
diff -c -r1.9 elf_machdep.c
*** ia64/ia64/elf_machdep.c	19 Oct 2002 19:30:38 -0000	1.9
--- ia64/ia64/elf_machdep.c	3 Jan 2003 11:19:39 -0000
***************
*** 141,148 ****
  }
  
  /* Process one elf relocation with addend. */
! int
! elf_reloc(linker_file_t lf, const void *data, int type)
  {
  	Elf_Addr relocbase = (Elf_Addr)lf->address;
  	Elf_Addr *where;
--- 141,148 ----
  }
  
  /* Process one elf relocation with addend. */
! static int
! elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
  {
  	Elf_Addr relocbase = (Elf_Addr)lf->address;
  	Elf_Addr *where;
***************
*** 179,184 ****
--- 179,190 ----
  		panic("%s: invalid ELF relocation (0x%x)\n", __func__, type);
  	}
  
+ 	if (local) {
+ 		if (rtype == R_IA64_REL64LSB)
+ 			*where = relocbase + addend;
+ 		return (0);
+ 	}
+ 
  	switch (rtype) {
  	case R_IA64_NONE:
  		break;
***************
*** 199,205 ****
  		*where = addr;
  		break;
  	case R_IA64_REL64LSB:	/* word64 LSB	BD + A */
- 		*where = relocbase + addend;
  		break;
  	case R_IA64_IPLTLSB:
  		addr = lookup_fdesc(lf, symidx);
--- 205,210 ----
***************
*** 215,220 ****
--- 220,237 ----
  	}
  
  	return (0);
+ }
+ 
+ int
+ elf_reloc(linker_file_t lf, const void *data, int type)
+ {
+ 	return (elf_reloc_internal(lf, data, type, 0));
+ }
+ 
+ int
+ elf_reloc_local(linker_file_t lf, const void *data, int type)
+ {
+ 	return (elf_reloc_internal(lf, data, type, 1));
  }
  
  int
Index: alpha/alpha/elf_machdep.c
===================================================================
RCS file: /usr/ncvs/src/sys/alpha/alpha/elf_machdep.c,v
retrieving revision 1.12
diff -c -r1.12 elf_machdep.c
*** alpha/alpha/elf_machdep.c	19 Oct 2002 19:16:02 -0000	1.12
--- alpha/alpha/elf_machdep.c	3 Jan 2003 11:21:33 -0000
***************
*** 89,96 ****
  	&freebsd_brand_info);
  
  /* Process one elf relocation with addend. */
! int
! elf_reloc(linker_file_t lf, const void *data, int type)
  {
  	Elf_Addr relocbase = (Elf_Addr) lf->address;
  	Elf_Addr *where;
--- 89,96 ----
  	&freebsd_brand_info);
  
  /* Process one elf relocation with addend. */
! static int
! elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
  {
  	Elf_Addr relocbase = (Elf_Addr) lf->address;
  	Elf_Addr *where;
***************
*** 119,124 ****
--- 119,133 ----
  		panic("elf_reloc: unknown relocation mode %d\n", type);
  	}
  
+ 	if (local) {
+ 		if (rtype == R_ALPHA_RELATIVE) {
+ 			addr = relocbase + addend;
+ 			if (*where != addr)
+ 				*where = addr;
+ 		}
+ 		return (0);
+ 	}
+ 
  	switch (rtype) {
  
  		case R_ALPHA_NONE:
***************
*** 152,160 ****
  			break;
  
  		case R_ALPHA_RELATIVE:
- 			addr = relocbase + addend;
- 			if (*where != addr)
- 				*where = addr;
  			break;
  
  		case R_ALPHA_COPY:
--- 161,166 ----
***************
*** 171,176 ****
--- 177,194 ----
  			return -1;
  	}
  	return(0);
+ }
+ 
+ int
+ elf_reloc(linker_file_t lf, const void *data, int type)
+ {
+ 	return (elf_reloc_internal(lf, data, type, 0));
+ }
+ 
+ int
+ elf_reloc_local(linker_file_t lf, const void *data, int type)
+ {
+ 	return (elf_reloc_internal(lf, data, type, 1));
  }
  
  int
>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?200301031529.h03FTCMT003875>