From owner-freebsd-sparc Fri Jan 3 7:30:24 2003 Delivered-To: freebsd-sparc@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 422C237B405 for ; Fri, 3 Jan 2003 07:30:05 -0800 (PST) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 52E0143EE1 for ; Fri, 3 Jan 2003 07:30:03 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.6/8.12.6) with ESMTP id h03FU3NS026068 for ; Fri, 3 Jan 2003 07:30:03 -0800 (PST) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.6/8.12.6/Submit) id h03FU3lO026067; Fri, 3 Jan 2003 07:30:03 -0800 (PST) Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id CE03F37B401 for ; Fri, 3 Jan 2003 07:29:16 -0800 (PST) Received: from mailhub.fokus.gmd.de (mailhub.fokus.gmd.de [193.174.154.14]) by mx1.FreeBSD.org (Postfix) with ESMTP id BF4C743ED8 for ; Fri, 3 Jan 2003 07:29:14 -0800 (PST) (envelope-from hbb@catssrv.fokus.gmd.de) Received: from catssrv.fokus.gmd.de (catssrv [192.168.229.23]) by mailhub.fokus.gmd.de (8.11.6/8.11.6) with ESMTP id h03FTDJ14937 for ; Fri, 3 Jan 2003 16:29:13 +0100 (MET) Received: from catssrv.fokus.gmd.de (localhost [127.0.0.1]) by catssrv.fokus.gmd.de (8.12.6/8.12.6) with ESMTP id h03FTDx5003876 for ; Fri, 3 Jan 2003 16:29:13 +0100 (CET) (envelope-from hbb@catssrv.fokus.gmd.de) Received: (from hbb@localhost) by catssrv.fokus.gmd.de (8.12.6/8.12.6/Submit) id h03FTCMT003875; Fri, 3 Jan 2003 16:29:12 +0100 (CET) (envelope-from hbb) Message-Id: <200301031529.h03FTCMT003875@catssrv.fokus.gmd.de> Date: Fri, 3 Jan 2003 16:29:12 +0100 (CET) From: Hartmut Brandt Reply-To: Hartmut Brandt To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: sparc64/46732: kernel linker cannot resolve dependencies Sender: owner-freebsd-sparc@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >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