Date: Thu, 1 Apr 2004 23:40:05 -0800 (PST) From: Peter Wemm <peter@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 50172 for review Message-ID: <200404020740.i327e5j1003235@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=50172 Change 50172 by peter@peter_hammer on 2004/04/01 23:39:42 This commit brought to you by: link_elf_obj.c line 629: printf("HOLY SHIT! WE MADE IT!!!\n"); Translation: I just loaded a kernel module and it worked! Affected files ... .. //depot/projects/hammer/sys/amd64/amd64/elf_machdep.c#17 edit .. //depot/projects/hammer/sys/kern/kern_linker.c#10 edit .. //depot/projects/hammer/sys/kern/link_elf.c#16 edit .. //depot/projects/hammer/sys/kern/link_elf_obj.c#24 edit .. //depot/projects/hammer/sys/sys/linker.h#11 edit Differences ... ==== //depot/projects/hammer/sys/amd64/amd64/elf_machdep.c#17 (text+ko) ==== @@ -104,9 +104,8 @@ /* Process one elf relocation with addend. */ static int -elf_reloc_internal(linker_file_t lf, const void *data, int type, int local, elf_lookup_fn lu) +elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, int local, elf_lookup_fn lu) { - Elf_Addr relocbase = (Elf_Addr) lf->address; Elf64_Addr *where; Elf32_Addr *where32, val32; Elf_Addr addr; @@ -115,7 +114,7 @@ const Elf_Rel *rel; const Elf_Rela *rela; -printf("elf_reloc_internal: data %p, local %d\n", data, local); +printf("elf_reloc_internal: relocbase 0x%lx, data %p, local %d\n", relocbase, data, local); switch (type) { case ELF_RELOC_REL: rel = (const Elf_Rel *)data; @@ -138,6 +137,7 @@ } printf("where %p, addend 0x%lx, rtype %ld, symindx %ld\n", where, addend, rtype, symidx); +#if 0 if (local) { if (rtype == R_X86_64_RELATIVE) { /* A + B */ addr = relocbase + addend; @@ -148,9 +148,17 @@ } return (0); } +#endif switch (rtype) { + case R_X86_64_RELATIVE: + addr = relocbase + addend; +printf("R_X86_64_RELATIVE: addr 0x%lx\n", addr); + if (*where != addr) + *where = addr; + break; + case R_X86_64_NONE: /* none */ printf("R_X86_64_NONE\n"); break; @@ -213,8 +221,10 @@ printf("*where = 0x%lx\n", *where); break; +#if 0 case R_X86_64_RELATIVE: /* B + A */ break; +#endif default: printf("kldload: unexpected relocation type %ld\n", @@ -225,17 +235,17 @@ } int -elf_reloc(linker_file_t lf, const void *data, int type, elf_lookup_fn lu) +elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, elf_lookup_fn lu) { - return (elf_reloc_internal(lf, data, type, 0, lu)); + return (elf_reloc_internal(lf, relocbase, data, type, 0, lu)); } int -elf_reloc_local(linker_file_t lf, const void *data, int type, elf_lookup_fn lu) +elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, elf_lookup_fn lu) { - return (elf_reloc_internal(lf, data, type, 1, lu)); + return (elf_reloc_internal(lf, relocbase, data, type, 1, lu)); } int ==== //depot/projects/hammer/sys/kern/kern_linker.c#10 (text+ko) ==== @@ -55,6 +55,8 @@ int kld_debug = 0; #endif +extern int biteme; + /* * static char *linker_search_path(const char *name, struct mod_depend * *verinfo); @@ -291,7 +293,14 @@ } else return (0); } +if (biteme) printf("linker_file_register_modules: start %p, stop %p\n", start, stop); for (mdp = start; mdp < stop; mdp++) { +if (biteme) printf("mdp = %p\n", mdp); +if (biteme) printf("*mdp = %p\n", *mdp); +if ((*mdp) == NULL) { +printf("bugging out! continue!\n"); +continue; +} if ((*mdp)->md_type != MDT_MODULE) continue; moddata = (*mdp)->md_data; @@ -1717,7 +1726,14 @@ if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop, &count) != 0) return (0); +if (biteme) printf("linker_load_dependencies: start %p, stop %p\n", start, stop); for (mdp = start; mdp < stop; mdp++) { +if (biteme) printf("mdp = %p\n", mdp); +if (biteme) printf("*mdp = %p\n", *mdp); +if ((*mdp) == NULL) { +printf("bugging out! continue!\n"); +continue; +} mp = *mdp; if (mp->md_type != MDT_VERSION) continue; ==== //depot/projects/hammer/sys/kern/link_elf.c#16 (text+ko) ==== @@ -929,7 +929,7 @@ if (rel) { rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize); while (rel < rellim) { - if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL, elf_lookup)) { + if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rel, ELF_RELOC_REL, elf_lookup)) { symname = symbol_name(ef, rel->r_info); printf("link_elf: symbol %s undefined\n", symname); return ENOENT; @@ -943,7 +943,7 @@ if (rela) { relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize); while (rela < relalim) { - if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA, elf_lookup)) { + if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rela, ELF_RELOC_RELA, elf_lookup)) { symname = symbol_name(ef, rela->r_info); printf("link_elf: symbol %s undefined\n", symname); return ENOENT; @@ -957,7 +957,7 @@ if (rel) { rellim = (const Elf_Rel *)((const char *)ef->pltrel + ef->pltrelsize); while (rel < rellim) { - if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL, elf_lookup)) { + if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rel, ELF_RELOC_REL, elf_lookup)) { symname = symbol_name(ef, rel->r_info); printf("link_elf: symbol %s undefined\n", symname); return ENOENT; @@ -971,7 +971,7 @@ if (rela) { relalim = (const Elf_Rela *)((const char *)ef->pltrela + ef->pltrelasize); while (rela < relalim) { - if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA, elf_lookup)) { + if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rela, ELF_RELOC_RELA, elf_lookup)) { symname = symbol_name(ef, rela->r_info); printf("link_elf: symbol %s undefined\n", symname); return ENOENT; @@ -1298,7 +1298,7 @@ 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, elf_lookup); + elf_reloc_local(lf, (Elf_Addr)ef->address, rel, ELF_RELOC_REL, elf_lookup); rel++; } } @@ -1307,7 +1307,7 @@ 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, elf_lookup); + elf_reloc_local(lf, (Elf_Addr)ef->address, rela, ELF_RELOC_RELA, elf_lookup); rela++; } } ==== //depot/projects/hammer/sys/kern/link_elf_obj.c#24 (text+ko) ==== @@ -58,6 +58,8 @@ #include "linker_if.h" +int biteme = 0; + typedef struct { void *addr; Elf_Off fileoff; @@ -81,12 +83,14 @@ Elf_Rel *rel; Elf_Off fileoff; Elf_Off filesz; + int sec; } Elf_relent; typedef struct { Elf_Rela *rela; Elf_Off fileoff; Elf_Off filesz; + int sec; } Elf_relaent; @@ -290,6 +294,7 @@ printf("elf_load_obj: initial checks look ok!\n"); +biteme++; printf("section table read in ok\n"); lf = linker_make_file(filename, &link_elf_class); if (!lf) { @@ -477,6 +482,7 @@ printf("rel %ld allocated at %p\n", shdr[i].sh_size, ef->reltab[rl].rel); ef->reltab[rl].fileoff = shdr[i].sh_offset; ef->reltab[rl].filesz = shdr[i].sh_size; + ef->reltab[rl].sec = shdr[i].sh_info; rl++; break; case SHT_RELA: @@ -484,6 +490,7 @@ printf("rela %ld allocated at %p\n", shdr[i].sh_size, ef->relatab[ra].rela); ef->relatab[ra].fileoff = shdr[i].sh_offset; ef->relatab[ra].filesz = shdr[i].sh_size; + ef->relatab[ra].sec = shdr[i].sh_info; ra++; break; } @@ -631,6 +638,7 @@ VOP_UNLOCK(nd.ni_vp, 0, td); vn_close(nd.ni_vp, FREAD, td->td_ucred, td); +biteme--; return error; } @@ -669,6 +677,27 @@ return NULL; } +static Elf_Addr +findbase(elf_file_t ef, int sec) +{ + int i; + Elf_Addr base = 0; + + for (i = 0; i < ef->nprogtab; i++) { + if (sec == ef->progtab[i].sec) + base = (Elf_Addr)ef->progtab[i].addr; + } + if (base == 0) { + for (i = 0; i < ef->nnobittab; i++) { + if (sec == ef->nobittab[i].sec) + base = (Elf_Addr)ef->nobittab[i].addr; + } + } + if (base == 0) + base = (Elf_Addr)ef->address; + return base; +} + static int relocate_file(elf_file_t ef) { @@ -677,7 +706,10 @@ const Elf_Rela *relalim; const Elf_Rela *rela; const char *symname; + const Elf_Sym *sym; int i; + Elf_Word symidx; + Elf_Addr base; /* Perform relocations without addend if there are any: */ @@ -687,12 +719,19 @@ if (rel) { rellim = (const Elf_Rel *)((const char *)rel + ef->reltab[i].filesz); printf("rellim is %p\n", rellim); + base = findbase(ef, ef->reltab[i].sec); while (rel < rellim) { printf("rel doing: %p\n", rel); - if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL, elf_obj_lookup)) { - symname = symbol_name(ef, rel->r_info); - printf("link_elf: symbol %s undefined\n", symname); - return ENOENT; + symidx = ELF_R_SYM(rel->r_info); + if (symidx < ef->ddbsymcnt) { + sym = ef->ddbsymtab + symidx; + if (ELF64_ST_BIND(sym->st_info) != STB_LOCAL) { + if (elf_reloc(&ef->lf, base, rel, ELF_RELOC_REL, elf_obj_lookup)) { + symname = symbol_name(ef, rel->r_info); + printf("link_elf: symbol %s undefined\n", symname); + return ENOENT; + } + } } rel++; } @@ -706,12 +745,19 @@ if (rela) { relalim = (const Elf_Rela *)((const char *)rela + ef->relatab[i].filesz); printf("relalim is %p\n", relalim); + base = findbase(ef, ef->relatab[i].sec); while (rela < relalim) { printf("rela doing: %p\n", rela); - if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA, elf_obj_lookup)) { - symname = symbol_name(ef, rela->r_info); - printf("link_elf: symbol %s undefined\n", symname); - return ENOENT; + symidx = ELF_R_SYM(rela->r_info); + if (symidx < ef->ddbsymcnt) { + sym = ef->ddbsymtab + symidx; + if (ELF64_ST_BIND(sym->st_info) != STB_LOCAL) { + if (elf_reloc(&ef->lf, base, rela, ELF_RELOC_RELA, elf_obj_lookup)) { + symname = symbol_name(ef, rela->r_info); + printf("link_elf: symbol %s undefined\n", symname); + return ENOENT; + } + } } rela++; } @@ -946,15 +992,21 @@ } } + + static void link_elf_reloc_local(linker_file_t lf) { + elf_file_t ef = (elf_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; + const Elf_Sym *sym; + Elf_Addr base; int i; + Elf_Word symidx; + /* Perform relocations without addend if there are any: */ for (i = 0; i < ef->nrel; i++) { @@ -963,9 +1015,15 @@ if (rel) { rellim = (const Elf_Rel *)((const char *)rel + ef->reltab[i].filesz); printf("rellim is %p\n", rellim); + base = findbase(ef, ef->reltab[i].sec); while (rel < rellim) { printf("rel doing: %p\n", rel); - elf_reloc_local(lf, rel, ELF_RELOC_REL, elf_obj_lookup); + symidx = ELF_R_SYM(rel->r_info); + if (symidx < ef->ddbsymcnt) { + sym = ef->ddbsymtab + symidx; + if (ELF64_ST_BIND(sym->st_info) == STB_LOCAL) + elf_reloc_local(lf, base, rel, ELF_RELOC_REL, elf_obj_lookup); + } rel++; } } @@ -978,9 +1036,15 @@ if (rela) { relalim = (const Elf_Rela *)((const char *)rela + ef->relatab[i].filesz); printf("relalim is %p\n", relalim); + base = findbase(ef, ef->relatab[i].sec); while (rela < relalim) { printf("rela doing: %p\n", rela); - elf_reloc_local(lf, rela, ELF_RELOC_RELA, elf_obj_lookup); + symidx = ELF_R_SYM(rela->r_info); + if (symidx < ef->ddbsymcnt) { + sym = ef->ddbsymtab + symidx; + if (ELF64_ST_BIND(sym->st_info) == STB_LOCAL) + elf_reloc_local(lf, base, rela, ELF_RELOC_RELA, elf_obj_lookup); + } rela++; } } ==== //depot/projects/hammer/sys/sys/linker.h#11 (text+ko) ==== @@ -244,8 +244,8 @@ typedef Elf_Addr elf_lookup_fn(linker_file_t, Elf_Word, int); /* Support functions */ -int elf_reloc(linker_file_t _lf, const void *_rel, int _type, elf_lookup_fn _lu); -int elf_reloc_local(linker_file_t _lf, const void *_rel, int _type, elf_lookup_fn _lu); +int elf_reloc(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu); +int elf_reloc_local(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu); const Elf_Sym *elf_get_sym(linker_file_t _lf, Elf_Word _symidx); const char *elf_get_symname(linker_file_t _lf, Elf_Word _symidx);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200404020740.i327e5j1003235>