PERFORCE change 49690 for review
Peter Wemm
peter at FreeBSD.org
Thu Mar 25 15:38:09 PST 2004
http://perforce.freebsd.org/chv.cgi?CH=49690
Change 49690 by peter at peter_daintree on 2004/03/25 15:37:13
checkpoint. note that I got fed up and reindented. There are
changes, but not that many. Mostly preperation and validation.
Affected files ...
.. //depot/projects/hammer/sys/kern/link_elf_obj.c#3 edit
Differences ...
==== //depot/projects/hammer/sys/kern/link_elf_obj.c#3 (text+ko) ====
@@ -60,70 +60,69 @@
#include "linker_if.h"
typedef struct elf_file {
- struct linker_file lf; /* Common fields */
- caddr_t address; /* Relocation address */
+ struct linker_file lf; /* Common fields */
+ caddr_t address; /* Relocation address */
#ifdef SPARSE_MAPPING
- vm_object_t object; /* VM object to hold file pages */
+ vm_object_t object; /* VM object to hold file pages */
#endif
- caddr_t strtab; /* DT_STRTAB */
- int strsz; /* DT_STRSZ */
- const Elf_Sym* symtab; /* DT_SYMTAB */
- const Elf_Rel* pltrel; /* DT_JMPREL */
- int pltrelsize; /* DT_PLTRELSZ */
- const Elf_Rela* pltrela; /* DT_JMPREL */
- int pltrelasize; /* DT_PLTRELSZ */
- const Elf_Rel* rel; /* DT_REL */
- int relsize; /* DT_RELSZ */
- const Elf_Rela* rela; /* DT_RELA */
- int relasize; /* DT_RELASZ */
- caddr_t modptr;
- const Elf_Sym* ddbsymtab; /* The symbol table we are using */
- long ddbsymcnt; /* Number of symbols */
- caddr_t ddbstrtab; /* String table */
- long ddbstrcnt; /* number of bytes in string table */
- caddr_t symbase; /* malloc'ed symbold base */
- caddr_t strbase; /* malloc'ed string base */
+ caddr_t strtab; /* DT_STRTAB */
+ int strsz; /* DT_STRSZ */
+ const Elf_Sym* symtab; /* DT_SYMTAB */
+ const Elf_Rel* pltrel; /* DT_JMPREL */
+ int pltrelsize; /* DT_PLTRELSZ */
+ const Elf_Rela* pltrela; /* DT_JMPREL */
+ int pltrelasize; /* DT_PLTRELSZ */
+ const Elf_Rel* rel; /* DT_REL */
+ int relsize; /* DT_RELSZ */
+ const Elf_Rela* rela; /* DT_RELA */
+ int relasize; /* DT_RELASZ */
+ caddr_t modptr;
+ const Elf_Sym* ddbsymtab; /* The symbol table we are using */
+ long ddbsymcnt; /* Number of symbols */
+ caddr_t ddbstrtab; /* String table */
+ long ddbstrcnt; /* number of bytes in string table */
+ caddr_t symbase; /* malloc'ed symbold base */
+ caddr_t strbase; /* malloc'ed string base */
} *elf_file_t;
static int link_elf_link_common_finish(linker_file_t);
static int link_elf_link_preload(linker_class_t cls,
- const char*, linker_file_t*);
+ const char*, linker_file_t*);
static int link_elf_link_preload_finish(linker_file_t);
static int link_elf_load_file(linker_class_t, const char*, linker_file_t*);
static int link_elf_lookup_symbol(linker_file_t, const char*,
- c_linker_sym_t*);
+ c_linker_sym_t*);
static int link_elf_symbol_values(linker_file_t, c_linker_sym_t, linker_symval_t*);
static int link_elf_search_symbol(linker_file_t, caddr_t value,
- c_linker_sym_t* sym, long* diffp);
+ c_linker_sym_t* sym, long* diffp);
static void link_elf_unload_file(linker_file_t);
static int link_elf_lookup_set(linker_file_t, const char *,
- void ***, void ***, int *);
+ void ***, void ***, int *);
static int link_elf_each_function_name(linker_file_t,
- int (*)(const char *, void *),
- void *);
+ 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),
- KOBJMETHOD(linker_symbol_values, link_elf_symbol_values),
- KOBJMETHOD(linker_search_symbol, link_elf_search_symbol),
- KOBJMETHOD(linker_unload, link_elf_unload_file),
- KOBJMETHOD(linker_load_file, link_elf_load_file),
- KOBJMETHOD(linker_link_preload, link_elf_link_preload),
- KOBJMETHOD(linker_link_preload_finish, link_elf_link_preload_finish),
- KOBJMETHOD(linker_lookup_set, link_elf_lookup_set),
- KOBJMETHOD(linker_each_function_name, link_elf_each_function_name),
- { 0, 0 }
+ KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol),
+ KOBJMETHOD(linker_symbol_values, link_elf_symbol_values),
+ KOBJMETHOD(linker_search_symbol, link_elf_search_symbol),
+ KOBJMETHOD(linker_unload, link_elf_unload_file),
+ KOBJMETHOD(linker_load_file, link_elf_load_file),
+ KOBJMETHOD(linker_link_preload, link_elf_link_preload),
+ KOBJMETHOD(linker_link_preload_finish, link_elf_link_preload_finish),
+ KOBJMETHOD(linker_lookup_set, link_elf_lookup_set),
+ KOBJMETHOD(linker_each_function_name, link_elf_each_function_name),
+ { 0, 0 }
};
static struct linker_class link_elf_class = {
#if ELF_TARG_CLASS == ELFCLASS32
- "elf32",
+ "elf32",
#else
- "elf64",
+ "elf64",
#endif
- link_elf_methods, sizeof(struct elf_file)
+ link_elf_methods, sizeof(struct elf_file)
};
static int relocate_file(elf_file_t ef);
@@ -131,7 +130,7 @@
static void
link_elf_error(const char *s)
{
- printf("kldload: %s\n", s);
+ printf("kldload: %s\n", s);
}
/*
@@ -141,14 +140,14 @@
static int
link_elf_link_common_finish(linker_file_t lf)
{
- int error;
+ int error;
- /* Notify MD code that a module is being loaded. */
- error = elf_cpu_load_file(lf);
- if (error)
- return (error);
+ /* Notify MD code that a module is being loaded. */
+ error = elf_cpu_load_file(lf);
+ if (error)
+ return (error);
- return (0);
+ return (0);
}
static void
@@ -161,8 +160,8 @@
SYSINIT(link_elf, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0);
static int
-link_elf_link_preload(linker_class_t cls,
- const char* filename, linker_file_t *result)
+link_elf_link_preload(linker_class_t cls, const char* filename,
+ linker_file_t *result)
{
return (EFTYPE);
}
@@ -175,460 +174,455 @@
static int
link_elf_load_file(linker_class_t cls, const char* filename,
- linker_file_t* result)
+ linker_file_t* result)
{
- struct nameidata nd;
- struct thread* td = curthread; /* XXX */
- Elf_Ehdr *hdr;
- caddr_t firstpage;
- int nbytes, i;
- Elf_Phdr *phdr;
- Elf_Phdr *phlimit;
- Elf_Phdr *segs[2];
- int nsegs;
- Elf_Phdr *phdyn;
- Elf_Phdr *phphdr;
- caddr_t mapbase;
- size_t mapsize;
- Elf_Off base_offset;
- Elf_Addr base_vaddr;
- Elf_Addr base_vlimit;
- int error = 0;
- int resid, flags;
- elf_file_t ef;
- linker_file_t lf;
- Elf_Shdr *shdr;
- int symtabindex;
- int symstrindex;
- int symcnt;
- int strcnt;
+ struct nameidata nd;
+ struct thread* td = curthread; /* XXX */
+ Elf_Ehdr *hdr;
+ caddr_t firstpage;
+ int nbytes, i;
+ Elf_Phdr *phdr;
+ Elf_Phdr *phlimit;
+ Elf_Phdr *segs[2];
+ int nsegs;
+ caddr_t mapbase;
+ size_t mapsize;
+ Elf_Off base_offset;
+ Elf_Addr base_vaddr;
+ Elf_Addr base_vlimit;
+ int error = 0;
+ int resid, flags;
+ elf_file_t ef;
+ linker_file_t lf;
+ Elf_Shdr *shdr;
+ int symtabindex;
+ int symstrindex;
+ int symcnt;
+ int strcnt;
- GIANT_REQUIRED;
+ GIANT_REQUIRED;
- shdr = NULL;
- lf = NULL;
+ shdr = NULL;
+ lf = NULL;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td);
- flags = FREAD;
- error = vn_open(&nd, &flags, 0, -1);
- if (error)
- return error;
- NDFREE(&nd, NDF_ONLY_PNBUF);
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td);
+ flags = FREAD;
+ error = vn_open(&nd, &flags, 0, -1);
+ if (error)
+ return error;
+ NDFREE(&nd, NDF_ONLY_PNBUF);
#ifdef MAC
- error = mac_check_kld_load(curthread->td_ucred, nd.ni_vp);
- if (error) {
- firstpage = NULL;
- goto out;
- }
+ error = mac_check_kld_load(curthread->td_ucred, nd.ni_vp);
+ if (error) {
+ firstpage = NULL;
+ goto out;
+ }
#endif
- /*
- * Read the elf header from the file.
- */
- firstpage = malloc(PAGE_SIZE, M_LINKER, M_WAITOK);
- if (firstpage == NULL) {
- error = ENOMEM;
- goto out;
- }
- hdr = (Elf_Ehdr *)firstpage;
- error = vn_rdwr(UIO_READ, nd.ni_vp, firstpage, PAGE_SIZE, 0,
- UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
- &resid, td);
- nbytes = PAGE_SIZE - resid;
- if (error)
- goto out;
+ /*
+ * Read the elf header from the file.
+ */
+ firstpage = malloc(PAGE_SIZE, M_LINKER, M_WAITOK);
+ if (firstpage == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+ hdr = (Elf_Ehdr *)firstpage;
+ error = vn_rdwr(UIO_READ, nd.ni_vp, firstpage, PAGE_SIZE, 0,
+ UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
+ &resid, td);
+ nbytes = PAGE_SIZE - resid;
+ if (error)
+ goto out;
+ if (nbytes < sizeof(Elf_Ehdr))
+ error = ENOEXEC;
+ goto out;
+ }
- if (!IS_ELF(*hdr)) {
- error = ENOEXEC;
- goto out;
- }
+ if (!IS_ELF(*hdr)) {
+ error = ENOEXEC;
+ goto out;
+ }
- if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS
- || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
- link_elf_error("Unsupported file layout");
- error = ENOEXEC;
- goto out;
- }
- if (hdr->e_ident[EI_VERSION] != EV_CURRENT
- || hdr->e_version != EV_CURRENT) {
- link_elf_error("Unsupported file version");
- error = ENOEXEC;
- goto out;
- }
- if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) {
- link_elf_error("Unsupported file type");
- error = ENOEXEC;
- goto out;
- }
- if (hdr->e_machine != ELF_TARG_MACH) {
- link_elf_error("Unsupported machine");
- error = ENOEXEC;
- goto out;
- }
+ if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS
+ || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
+ link_elf_error("Unsupported file layout");
+ error = ENOEXEC;
+ goto out;
+ }
+ if (hdr->e_ident[EI_VERSION] != EV_CURRENT
+ || hdr->e_version != EV_CURRENT) {
+ link_elf_error("Unsupported file version");
+ error = ENOEXEC;
+ goto out;
+ }
+ if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) {
+ link_elf_error("Unsupported file type");
+ error = ENOEXEC;
+ goto out;
+ }
+ if (hdr->e_machine != ELF_TARG_MACH) {
+ link_elf_error("Unsupported machine");
+ error = ENOEXEC;
+ goto out;
+ }
- /*
- * We rely on the program header being in the first page. This is
- * not strictly required by the ABI specification, but it seems to
- * always true in practice. And, it simplifies things considerably.
- * XXX section table, not program header. And we should not depend
- * XXX on this because the section table is likely to be bigger.
- */
- if (!((hdr->e_phentsize == sizeof(Elf_Phdr)) &&
- (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE) &&
- (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= nbytes)))
- link_elf_error("Unreadable program headers");
+ /* Read in the section header */
+ nbytes = hdr->e_shnum * hdr->e_shentsize;
+ if (nbytes == 0 || hdr->e_shoff == 0 ||
+ hdr->e_shentsize != sizeof(Elf_Shdr)) {
+ error = ENOEXEC;
+ goto out;
+ }
+ shdr = malloc(nbytes, M_LINKER, M_WAITOK | M_ZERO);
+ if (shdr == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+ error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)shdr, nbytes, hdr->e_shoff,
+ UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td);
+ if (error)
+ goto out;
+ if (resid) {
+ error = ENOEXEC;
+ goto out;
+ }
- /*
- * Scan the program header entries, and save key information.
- *
- * We rely on there being exactly two load segments, text and data,
- * in that order.
- *
- * XXX do several passes of section table instead.
- * XXX 1) count various things needed to size arrays
- * XXX 2) grab info about things like PROGBITS/REL/RELA/STRTAB/SYMTAB
- * XXX 3) read the string and symbol tables so we can do relocations etc
- * XXX 4) (later on) load the rest of the entries.
- */
+ /*
+ * Scan the program header entries, and save key information.
+ *
+ * We rely on there being exactly two load segments, text and data,
+ * in that order.
+ *
+ * XXX do several passes of section table instead.
+ * XXX 1) count various things needed to size arrays
+ * XXX 2) grab info about things like PROGBITS/REL/RELA/STRTAB/SYMTAB
+ * XXX 3) read the string and symbol tables so we can do relocations etc
+ * XXX 4) (later on) load the rest of the entries.
+ */
/* XXX *************** STEP 1 GOES HERE ************* XXX */
- phdr = (Elf_Phdr *) (firstpage + hdr->e_phoff);
- phlimit = phdr + hdr->e_phnum;
- nsegs = 0;
- phdyn = NULL;
- phphdr = NULL;
- while (phdr < phlimit) {
- switch (phdr->p_type) {
-
- case PT_LOAD:
- if (nsegs == 2) {
- link_elf_error("Too many sections");
+ shdr = (Elf_Shdr *)shtbuf;
+ shlimit = shdr + hdr->e_phnum;
+ nbits = 0;
+ nnobits = 0;
+ nsym = 0;
+ nrel = 0;
+ nrela = 0;
+ for (i = 0; i < hdr->e_shnum; i++) {
+ switch (shdr[i].sh_type) {
+ case SHT_PROGBITS:
+ nprogbits++;
+ break;
+ case SHT_NOBITS:
+ nnobits++;
+ break;
+ case SHT_SYMTAB:
+ nsym++;
+ symstrindex = shdr[i].sh_link;
+ break;
+ case SHT_REL:
+ nrel++;
+ break;
+ case SHT_RELA:
+ nrela++;
+ break;
+ }
+ }
+ if (nprogbits == 0 && nnobits == 0) {
+ link_elf_error("file has no contents");
+ error = ENOEXEC;
+ goto out;
+ }
+ if (nsym != 1) {
+ link_elf_error("file has no valid symbol table");
+ error = ENOEXEC;
+ goto out;
+ }
+ if (symstrindex < 0 || sysmstrindex > hdr->e_shnum ||
+ shdr[symstrindex].sh_type != SHT_STRTAB) {
+ link_elf_error("file has invalid symbol strings");
error = ENOEXEC;
goto out;
- }
- /*
- * XXX: We just trust they come in right order ??
- */
- segs[nsegs] = phdr;
- ++nsegs;
- break;
+ }
- case PT_PHDR:
- phphdr = phdr;
- break;
+/* XXX *************** STEP 2 GOES HERE ************* XXX */
+ symtabindex = -1;
+ symstrindex = -1;
+ for (i = 0; i < hdr->e_shnum; i++) {
+ switch (shdr[i].sh_type) {
- case PT_DYNAMIC:
- phdyn = phdr;
- break;
-
- case PT_INTERP:
- link_elf_error("Unsupported file type");
- error = ENOEXEC;
- goto out;
+ case SHT_SYMTAB:
+ symtabindex = i;
+ symstrindex = shdr[i].sh_link;
+ break;
+ }
}
-
- ++phdr;
- }
- if (phdyn == NULL) {
- link_elf_error("Object is not dynamically-linked");
- error = ENOEXEC;
- goto out;
- }
- if (nsegs != 2) {
- link_elf_error("Too few sections");
- error = ENOEXEC;
- goto out;
- }
-/* XXX *************** STEP 2 GOES HERE ************* XXX */
/* XXX *************** STEP 3 GOES HERE ************* XXX */
- /* Try and load the symbol table if it's present. (you can strip it!) */
- nbytes = hdr->e_shnum * hdr->e_shentsize;
- if (nbytes == 0 || hdr->e_shoff == 0)
- goto nosyms;
- shdr = malloc(nbytes, M_LINKER, M_WAITOK | M_ZERO);
- if (shdr == NULL) {
- error = ENOMEM;
- goto out;
- }
- error = vn_rdwr(UIO_READ, nd.ni_vp,
- (caddr_t)shdr, nbytes, hdr->e_shoff,
- UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
- &resid, td);
- if (error)
- goto out;
- symtabindex = -1;
- symstrindex = -1;
- for (i = 0; i < hdr->e_shnum; i++) {
- if (shdr[i].sh_type == SHT_SYMTAB) {
- symtabindex = i;
- symstrindex = shdr[i].sh_link;
- }
- }
- if (symtabindex < 0 || symstrindex < 0)
- goto nosyms;
+ /* Load the symbol table. */
+ if (symtabindex < 0 || symstrindex < 0)
+ goto nosyms;
- symcnt = shdr[symtabindex].sh_size;
- ef->symbase = malloc(symcnt, M_LINKER, M_WAITOK);
- strcnt = shdr[symstrindex].sh_size;
- ef->strbase = malloc(strcnt, M_LINKER, M_WAITOK);
+ symcnt = shdr[symtabindex].sh_size;
+ ef->symbase = malloc(symcnt, M_LINKER, M_WAITOK);
+ strcnt = shdr[symstrindex].sh_size;
+ ef->strbase = malloc(strcnt, M_LINKER, M_WAITOK);
- if (ef->symbase == NULL || ef->strbase == NULL) {
- error = ENOMEM;
- goto out;
- }
- error = vn_rdwr(UIO_READ, nd.ni_vp,
- ef->symbase, symcnt, shdr[symtabindex].sh_offset,
- UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
- &resid, td);
- if (error)
- goto out;
- error = vn_rdwr(UIO_READ, nd.ni_vp,
- ef->strbase, strcnt, shdr[symstrindex].sh_offset,
- UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
- &resid, td);
- if (error)
- goto out;
+ if (ef->symbase == NULL || ef->strbase == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+ error = vn_rdwr(UIO_READ, nd.ni_vp,
+ ef->symbase, symcnt, shdr[symtabindex].sh_offset,
+ UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
+ &resid, td);
+ if (error)
+ goto out;
+ error = vn_rdwr(UIO_READ, nd.ni_vp,
+ ef->strbase, strcnt, shdr[symstrindex].sh_offset,
+ UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
+ &resid, td);
+ if (error)
+ goto out;
- ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
- ef->ddbsymtab = (const Elf_Sym *)ef->symbase;
- ef->ddbstrcnt = strcnt;
- ef->ddbstrtab = ef->strbase;
+ ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
+ ef->ddbsymtab = (const Elf_Sym *)ef->symbase;
+ ef->ddbstrcnt = strcnt;
+ ef->ddbstrtab = ef->strbase;
/* XXX *************** STEP 4 GOES HERE ************* XXX */
- /*
- * Allocate the entire address space of the object, to stake out our
- * contiguous region, and to establish the base address for relocation.
- */
- base_offset = trunc_page(segs[0]->p_offset);
- base_vaddr = trunc_page(segs[0]->p_vaddr);
- base_vlimit = round_page(segs[1]->p_vaddr + segs[1]->p_memsz);
- mapsize = base_vlimit - base_vaddr;
+ /*
+ * Allocate the entire address space of the object, to stake out our
+ * contiguous region, and to establish the base address for relocation.
+ */
+ base_offset = trunc_page(segs[0]->p_offset);
+ base_vaddr = trunc_page(segs[0]->p_vaddr);
+ base_vlimit = round_page(segs[1]->p_vaddr + segs[1]->p_memsz);
+ mapsize = base_vlimit - base_vaddr;
- lf = linker_make_file(filename, &link_elf_class);
- if (!lf) {
- error = ENOMEM;
- goto out;
- }
+ lf = linker_make_file(filename, &link_elf_class);
+ if (!lf) {
+ error = ENOMEM;
+ goto out;
+ }
- ef = (elf_file_t) lf;
+ ef = (elf_file_t) lf;
#ifdef SPARSE_MAPPING
- ef->object = vm_object_allocate(OBJT_DEFAULT, mapsize >> PAGE_SHIFT);
- if (ef->object == NULL) {
- error = ENOMEM;
- goto out;
- }
- vm_object_reference(ef->object);
- ef->address = (caddr_t) vm_map_min(kernel_map);
- error = vm_map_find(kernel_map, ef->object, 0,
- (vm_offset_t *) &ef->address,
- mapsize, 1,
- VM_PROT_ALL, VM_PROT_ALL, 0);
- if (error) {
- vm_object_deallocate(ef->object);
- ef->object = 0;
- goto out;
- }
+ ef->object = vm_object_allocate(OBJT_DEFAULT, mapsize >> PAGE_SHIFT);
+ if (ef->object == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+ vm_object_reference(ef->object);
+ ef->address = (caddr_t) vm_map_min(kernel_map);
+ error = vm_map_find(kernel_map, ef->object, 0,
+ (vm_offset_t *) &ef->address,
+ mapsize, 1,
+ VM_PROT_ALL, VM_PROT_ALL, 0);
+ if (error) {
+ vm_object_deallocate(ef->object);
+ ef->object = 0;
+ goto out;
+ }
#else
- ef->address = malloc(mapsize, M_LINKER, M_WAITOK);
- if (!ef->address) {
- error = ENOMEM;
- goto out;
- }
+ ef->address = malloc(mapsize, M_LINKER, M_WAITOK);
+ if (!ef->address) {
+ error = ENOMEM;
+ goto out;
+ }
#endif
- mapbase = ef->address;
+ mapbase = ef->address;
- /*
- * Read the text and data sections and zero the bss.
- */
- for (i = 0; i < 2; i++) {
- caddr_t segbase = mapbase + segs[i]->p_vaddr - base_vaddr;
- error = vn_rdwr(UIO_READ, nd.ni_vp,
- segbase, segs[i]->p_filesz, segs[i]->p_offset,
- UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
- &resid, td);
- if (error) {
- goto out;
- }
- bzero(segbase + segs[i]->p_filesz,
- segs[i]->p_memsz - segs[i]->p_filesz);
+ /*
+ * Read the text and data sections and zero the bss.
+ */
+ for (i = 0; i < 2; i++) {
+ caddr_t segbase = mapbase + segs[i]->p_vaddr - base_vaddr;
+ error = vn_rdwr(UIO_READ, nd.ni_vp,
+ segbase, segs[i]->p_filesz, segs[i]->p_offset,
+ UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
+ &resid, td);
+ if (error) {
+ goto out;
+ }
+ bzero(segbase + segs[i]->p_filesz,
+ segs[i]->p_memsz - segs[i]->p_filesz);
#ifdef SPARSE_MAPPING
- /*
- * Wire down the pages
- */
- vm_map_wire(kernel_map,
+ /*
+ * Wire down the pages
+ */
+ vm_map_wire(kernel_map,
(vm_offset_t) segbase,
(vm_offset_t) segbase + segs[i]->p_memsz,
VM_MAP_WIRE_SYSTEM|VM_MAP_WIRE_NOHOLES);
#endif
- }
+ }
- /* ef->dynamic = (Elf_Dyn *) (mapbase + phdyn->p_vaddr - base_vaddr); */
+ lf->address = ef->address;
+ lf->size = mapsize;
- lf->address = ef->address;
- lf->size = mapsize;
+ link_elf_reloc_local(lf);
- link_elf_reloc_local(lf);
+ error = linker_load_dependencies(lf);
+ if (error)
+ goto out;
+ error = relocate_file(ef);
+ if (error)
+ goto out;
- error = linker_load_dependencies(lf);
- if (error)
- goto out;
- error = relocate_file(ef);
- if (error)
- goto out;
+ error = link_elf_link_common_finish(lf);
+ if (error)
+ goto out;
- error = link_elf_link_common_finish(lf);
- if (error)
- goto out;
+ nosyms:
-nosyms:
+ *result = lf;
- *result = lf;
+ out:
+ if (error && lf)
+ linker_file_unload(lf);
+ if (shdr)
+ free(shdr, M_LINKER);
+ if (firstpage)
+ free(firstpage, M_LINKER);
+ VOP_UNLOCK(nd.ni_vp, 0, td);
+ vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
-out:
- if (error && lf)
- linker_file_unload(lf);
- if (shdr)
- free(shdr, M_LINKER);
- if (firstpage)
- free(firstpage, M_LINKER);
- VOP_UNLOCK(nd.ni_vp, 0, td);
- vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
-
- return error;
+ return error;
}
static void
link_elf_unload_file(linker_file_t file)
{
- elf_file_t ef = (elf_file_t) file;
+ elf_file_t ef = (elf_file_t) file;
- /* Notify MD code that a module is being unloaded. */
- elf_cpu_unload_file(file);
+ /* Notify MD code that a module is being unloaded. */
+ elf_cpu_unload_file(file);
#ifdef SPARSE_MAPPING
- if (ef->object) {
- vm_map_remove(kernel_map, (vm_offset_t) ef->address,
- (vm_offset_t) ef->address
- + (ef->object->size << PAGE_SHIFT));
- vm_object_deallocate(ef->object);
- }
+ if (ef->object) {
+ vm_map_remove(kernel_map, (vm_offset_t) ef->address,
+ (vm_offset_t) ef->address
+ + (ef->object->size << PAGE_SHIFT));
+ vm_object_deallocate(ef->object);
+ }
#else
- if (ef->address)
- free(ef->address, M_LINKER);
+ if (ef->address)
+ free(ef->address, M_LINKER);
#endif
- if (ef->symbase)
- free(ef->symbase, M_LINKER);
- if (ef->strbase)
- free(ef->strbase, M_LINKER);
+ if (ef->symbase)
+ free(ef->symbase, M_LINKER);
+ if (ef->strbase)
+ free(ef->strbase, M_LINKER);
}
static const char *
symbol_name(elf_file_t ef, Elf_Word r_info)
{
- const Elf_Sym *ref;
+ const Elf_Sym *ref;
- if (ELF_R_SYM(r_info)) {
- ref = ef->symtab + ELF_R_SYM(r_info);
- return ef->strtab + ref->st_name;
- } else
- return NULL;
+ if (ELF_R_SYM(r_info)) {
+ ref = ef->symtab + ELF_R_SYM(r_info);
+ return ef->strtab + ref->st_name;
+ } else
+ return NULL;
}
static int
relocate_file(elf_file_t ef)
{
- const Elf_Rel *rellim;
- const Elf_Rel *rel;
- const Elf_Rela *relalim;
- const Elf_Rela *rela;
- const char *symname;
+ const Elf_Rel *rellim;
+ const Elf_Rel *rel;
+ const Elf_Rela *relalim;
+ const Elf_Rela *rela;
+ const char *symname;
- /* Perform relocations without addend if there are any: */
- rel = ef->rel;
- if (rel) {
- rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize);
- while (rel < rellim) {
- if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) {
- symname = symbol_name(ef, rel->r_info);
- printf("link_elf: symbol %s undefined\n", symname);
- return ENOENT;
- }
- rel++;
+ /* Perform relocations without addend if there are any: */
+ rel = ef->rel;
+ if (rel) {
+ rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize);
+ while (rel < rellim) {
+ if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) {
+ symname = symbol_name(ef, rel->r_info);
+ printf("link_elf: symbol %s undefined\n", symname);
+ return ENOENT;
+ }
+ rel++;
+ }
}
- }
- /* Perform relocations with addend if there are any: */
- rela = ef->rela;
- if (rela) {
- relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize);
- while (rela < relalim) {
- if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) {
- symname = symbol_name(ef, rela->r_info);
- printf("link_elf: symbol %s undefined\n", symname);
- return ENOENT;
- }
- rela++;
+ /* Perform relocations with addend if there are any: */
+ rela = ef->rela;
+ if (rela) {
+ relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize);
+ while (rela < relalim) {
+ if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) {
+ symname = symbol_name(ef, rela->r_info);
+ printf("link_elf: symbol %s undefined\n", symname);
+ return ENOENT;
+ }
+ rela++;
+ }
}
- }
- /* Perform PLT relocations without addend if there are any: */
- rel = ef->pltrel;
- if (rel) {
- rellim = (const Elf_Rel *)((const char *)ef->pltrel + ef->pltrelsize);
- while (rel < rellim) {
- if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) {
- symname = symbol_name(ef, rel->r_info);
- printf("link_elf: symbol %s undefined\n", symname);
- return ENOENT;
- }
- rel++;
+ /* Perform PLT relocations without addend if there are any: */
+ rel = ef->pltrel;
+ if (rel) {
+ rellim = (const Elf_Rel *)((const char *)ef->pltrel + ef->pltrelsize);
+ while (rel < rellim) {
+ if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) {
+ symname = symbol_name(ef, rel->r_info);
+ printf("link_elf: symbol %s undefined\n", symname);
+ return ENOENT;
+ }
+ rel++;
+ }
}
- }
- /* Perform relocations with addend if there are any: */
- rela = ef->pltrela;
- if (rela) {
- relalim = (const Elf_Rela *)((const char *)ef->pltrela + ef->pltrelasize);
- while (rela < relalim) {
- if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) {
- symname = symbol_name(ef, rela->r_info);
- printf("link_elf: symbol %s undefined\n", symname);
- return ENOENT;
- }
- rela++;
+ /* Perform relocations with addend if there are any: */
+ rela = ef->pltrela;
+ if (rela) {
+ relalim = (const Elf_Rela *)((const char *)ef->pltrela + ef->pltrelasize);
+ while (rela < relalim) {
+ if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) {
+ symname = symbol_name(ef, rela->r_info);
+ printf("link_elf: symbol %s undefined\n", symname);
+ return ENOENT;
+ }
+ rela++;
+ }
}
- }
- return 0;
+ return 0;
}
static int
link_elf_lookup_symbol(linker_file_t lf, const char* name, c_linker_sym_t* sym)
{
- elf_file_t ef = (elf_file_t) lf;
- unsigned long symnum;
- const Elf_Sym* symp;
- const char *strp;
- int i;
+ elf_file_t ef = (elf_file_t) lf;
+ unsigned long symnum;
+ const Elf_Sym* symp;
+ const char *strp;
+ int i;
/* XXX search for globals first */
- /* Exhaustive search */
- for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
- strp = ef->ddbstrtab + symp->st_name;
- if (strcmp(name, strp) == 0) {
- if (symp->st_shndx != SHN_UNDEF ||
- (symp->st_value != 0 &&
- ELF_ST_TYPE(symp->st_info) == STT_FUNC)) {
- *sym = (c_linker_sym_t) symp;
- return 0;
- } else
- return ENOENT;
+ /* Exhaustive search */
+ for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
+ strp = ef->ddbstrtab + symp->st_name;
+ if (strcmp(name, strp) == 0) {
+ if (symp->st_shndx != SHN_UNDEF ||
+ (symp->st_value != 0 &&
+ ELF_ST_TYPE(symp->st_info) == STT_FUNC)) {
+ *sym = (c_linker_sym_t) symp;
+ return 0;
+ } else
+ return ENOENT;
+ }
}
- }
- return ENOENT;
+ return ENOENT;
}
static int
@@ -638,17 +632,17 @@
const Elf_Sym* es = (const Elf_Sym*) sym;
if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) {
- symval->name = ef->ddbstrtab + es->st_name;
- symval->value = (caddr_t) ef->address + es->st_value;
- symval->size = es->st_size;
- return 0;
+ symval->name = ef->ddbstrtab + es->st_name;
+ symval->value = (caddr_t) ef->address + es->st_value;
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list