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>