Skip site navigation (1)Skip section navigation (2)
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>