PERFORCE change 50172 for review
Peter Wemm
peter at FreeBSD.org
Thu Apr 1 23:40:06 PST 2004
http://perforce.freebsd.org/chv.cgi?CH=50172
Change 50172 by peter at 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);
More information about the p4-projects
mailing list