X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/blobdiff_plain/28d6226a81417152c8f97594804850f1aac12e79..f4e821f3d4fe27827b527dc619f7cc51805285be:/sys/kern/kern_linker.c diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index d8a33a1a5e..aabe8adeac 100644 --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/kern/kern_linker.c,v 1.41.2.3 2001/11/21 17:50:35 luigi Exp $ - * $DragonFly: src/sys/kern/kern_linker.c,v 1.33 2007/01/15 20:51:14 dillon Exp $ + * $DragonFly: src/sys/kern/kern_linker.c,v 1.44 2008/09/01 19:39:44 dillon Exp $ */ #include "opt_ddb.h" @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,10 @@ #include +#ifdef _KERNEL_VIRTUAL +#include +#endif + #ifdef KLD_DEBUG int kld_debug = 0; #endif @@ -71,7 +76,7 @@ linker_init(void* arg) TAILQ_INIT(&linker_files); } -SYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0); +SYSINIT(linker, SI_BOOT2_KLD, SI_ORDER_FIRST, linker_init, 0); int linker_add_class(const char* desc, void* priv, @@ -79,10 +84,9 @@ linker_add_class(const char* desc, void* priv, { linker_class_t lc; - lc = kmalloc(sizeof(struct linker_class), M_LINKER, M_NOWAIT); + lc = kmalloc(sizeof(struct linker_class), M_LINKER, M_NOWAIT | M_ZERO); if (!lc) return ENOMEM; - bzero(lc, sizeof(*lc)); lc->desc = desc; lc->priv = priv; @@ -146,7 +150,7 @@ linker_file_sysinit(linker_file_t lf) * Perform each task, and continue on to the next task. */ for (sipp = start; sipp < stop; sipp++) { - if ((*sipp)->subsystem == SI_SUB_DUMMY) + if ((*sipp)->subsystem == SI_SPECIAL_DUMMY) continue; /* skip dummy task(s)*/ /* Call function */ @@ -194,7 +198,7 @@ linker_file_sysuninit(linker_file_t lf) * Perform each task, and continue on to the next task. */ for (sipp = start; sipp < stop; sipp++) { - if ((*sipp)->subsystem == SI_SUB_DUMMY) + if ((*sipp)->subsystem == SI_SPECIAL_DUMMY) continue; /* skip dummy task(s)*/ /* Call function */ @@ -257,14 +261,10 @@ linker_load_file(const char* filename, linker_file_t* result) } koname = kmalloc(strlen(filename) + 4, M_LINKER, M_WAITOK); - if (koname == NULL) { - error = ENOMEM; - goto out; - } ksprintf(koname, "%s.ko", filename); lf = NULL; foundfile = 0; - for (lc = TAILQ_FIRST(&classes); lc; lc = TAILQ_NEXT(lc, link)) { + TAILQ_FOREACH(lc, &classes, link) { KLD_DPF(FILE, ("linker_load_file: trying to load %s as %s\n", filename, lc->desc)); @@ -294,9 +294,8 @@ linker_load_file(const char* filename, linker_file_t* result) * Format not recognized or otherwise unloadable. * When loading a module that is statically built into * the kernel EEXIST percolates back up as the return - * value. Preserve this so that apps like sysinstall - * can recognize this special case and not post bogus - * dialog messages. + * value. Preserve this so that apps can recognize this + * special case. */ if (error != EEXIST) error = ENOEXEC; @@ -322,12 +321,10 @@ linker_find_file_by_name(const char* filename) filename += i; koname = kmalloc(strlen(filename) + 4, M_LINKER, M_WAITOK); - if (koname == NULL) - goto out; ksprintf(koname, "%s.ko", filename); lockmgr(&lock, LK_SHARED); - for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { + TAILQ_FOREACH(lf, &linker_files, link) { if (!strcmp(lf->filename, koname)) break; if (!strcmp(lf->filename, filename)) @@ -335,7 +332,6 @@ linker_find_file_by_name(const char* filename) } lockmgr(&lock, LK_RELEASE); -out: if (koname) kfree(koname, M_LINKER); return lf; @@ -347,7 +343,7 @@ linker_find_file_by_id(int fileid) linker_file_t lf = 0; lockmgr(&lock, LK_SHARED); - for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) + TAILQ_FOREACH(lf, &linker_files, link) if (lf->id == fileid) break; lockmgr(&lock, LK_RELEASE); @@ -372,8 +368,6 @@ linker_make_file(const char* pathname, void* priv, struct linker_file_ops* ops) lockmgr(&lock, LK_EXCLUSIVE); namelen = strlen(filename) + 1; lf = kmalloc(sizeof(struct linker_file) + namelen, M_LINKER, M_WAITOK); - if (!lf) - goto out; bzero(lf, sizeof(*lf)); lf->refs = 1; @@ -391,7 +385,6 @@ linker_make_file(const char* pathname, void* priv, struct linker_file_ops* ops) lf->ops = ops; TAILQ_INSERT_TAIL(&linker_files, lf, link); -out: lockmgr(&lock, LK_RELEASE); return lf; } @@ -490,16 +483,13 @@ out: return error; } -int +void linker_file_add_dependancy(linker_file_t file, linker_file_t dep) { linker_file_t* newdeps; newdeps = kmalloc((file->ndeps + 1) * sizeof(linker_file_t*), - M_LINKER, M_WAITOK); - if (newdeps == NULL) - return ENOMEM; - bzero(newdeps, (file->ndeps + 1) * sizeof(linker_file_t*)); + M_LINKER, M_WAITOK | M_ZERO); if (file->deps) { bcopy(file->deps, newdeps, file->ndeps * sizeof(linker_file_t*)); @@ -508,8 +498,6 @@ linker_file_add_dependancy(linker_file_t file, linker_file_t dep) file->deps = newdeps; file->deps[file->ndeps] = dep; file->ndeps++; - - return 0; } /* @@ -564,7 +552,7 @@ linker_file_lookup_symbol(linker_file_t file, const char* name, int deps, caddr_ } /* If we have not found it in the dependencies, search globally */ - for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { + TAILQ_FOREACH(lf, &linker_files, link) { /* But skip the current file if it's on the list */ if (lf == file) continue; @@ -589,8 +577,7 @@ linker_file_lookup_symbol(linker_file_t file, const char* name, int deps, caddr_ */ struct common_symbol* cp; - for (cp = STAILQ_FIRST(&file->common); cp; - cp = STAILQ_NEXT(cp, link)) + STAILQ_FOREACH(cp, &file->common, link) if (!strcmp(cp->name, name)) { KLD_DPF(SYM, ("linker_file_lookup_symbol: old common value=%x\n", cp->address)); *raddr = cp->address; @@ -604,12 +591,7 @@ linker_file_lookup_symbol(linker_file_t file, const char* name, int deps, caddr_ cp = kmalloc(sizeof(struct common_symbol) + common_size + strlen(name) + 1, - M_LINKER, M_WAITOK); - if (!cp) { - KLD_DPF(SYM, ("linker_file_lookup_symbol: nomem\n")); - return ENOMEM; - } - bzero(cp, sizeof(struct common_symbol) + common_size + strlen(name)+ 1); + M_LINKER, M_WAITOK | M_ZERO); cp->address = (caddr_t) (cp + 1); cp->name = cp->address + common_size; @@ -622,6 +604,14 @@ linker_file_lookup_symbol(linker_file_t file, const char* name, int deps, caddr_ return 0; } +#ifdef _KERNEL_VIRTUAL + *raddr = dlsym(RTLD_NEXT, name); + if (*raddr != NULL) { + KLD_DPF(SYM, ("linker_file_lookup_symbol: found dlsym=%x\n", *raddr)); + return 0; + } +#endif + KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n")); return ENOENT; } @@ -641,7 +631,7 @@ linker_ddb_lookup(const char *symstr, c_linker_sym_t *sym) { linker_file_t lf; - for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { + TAILQ_FOREACH(lf, &linker_files, link) { if (lf->ops->lookup_symbol(lf, symstr, sym) == 0) return 0; } @@ -659,7 +649,7 @@ linker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp) best = 0; bestdiff = off; - for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { + TAILQ_FOREACH(lf, &linker_files, link) { if (lf->ops->search_symbol(lf, value, &es, &diff) != 0) continue; if (es != 0 && diff < bestdiff) { @@ -685,7 +675,7 @@ linker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval) { linker_file_t lf; - for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { + TAILQ_FOREACH(lf, &linker_files, link) { if (lf->ops->symbol_values(lf, sym, symval) == 0) return 0; } @@ -928,7 +918,7 @@ sys_kldsym(struct kldsym_args *uap) } else error = ENOENT; } else { - for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { + TAILQ_FOREACH(lf, &linker_files, link) { if (lf->ops->lookup_symbol(lf, symstr, &sym) == 0 && lf->ops->symbol_values(lf, sym, &symval) == 0) { lookup.symvalue = (uintptr_t)symval.value; @@ -1030,7 +1020,7 @@ linker_preload(void* arg) continue; } lf = NULL; - for (lc = TAILQ_FIRST(&classes); lc; lc = TAILQ_NEXT(lc, link)) { + TAILQ_FOREACH(lc, &classes, link) { error = lc->ops->load_file(modname, &lf); if (error) { lf = NULL; @@ -1062,7 +1052,7 @@ linker_preload(void* arg) } } -SYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0); +SYSINIT(preload, SI_BOOT2_KLD, SI_ORDER_MIDDLE, linker_preload, 0); /* * Search for a not-loaded module by name. @@ -1079,18 +1069,19 @@ SYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0); * character as a separator to be consistent with the bootloader. */ -static char linker_path[MAXPATHLEN] = "/;/boot/;/modules/"; +static char linker_path[MAXPATHLEN] = "/boot;/boot/modules;/;/modules"; SYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path, sizeof(linker_path), "module load search path"); +TUNABLE_STR("module_path", linker_path, sizeof(linker_path)); static char * linker_strdup(const char *str) { char *result; - if ((result = kmalloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL) - strcpy(result, str); + result = kmalloc(strlen(str) + 1, M_LINKER, M_WAITOK); + strcpy(result, str); return(result); } @@ -1099,6 +1090,8 @@ linker_search_path(const char *name) { struct nlookupdata nd; char *cp, *ep, *result; + size_t name_len, prefix_len; + int sep; int error; enum vtype type; @@ -1108,17 +1101,28 @@ linker_search_path(const char *name) /* traverse the linker path */ cp = linker_path; + name_len = strlen(name); for (;;) { /* find the end of this component */ for (ep = cp; (*ep != 0) && (*ep != ';'); ep++) ; - result = kmalloc((strlen(name) + (ep - cp) + 1), M_LINKER, M_WAITOK); - if (result == NULL) /* actually ENOMEM */ - return(NULL); + prefix_len = ep - cp; + /* if this component doesn't end with a slash, add one */ + if (ep == cp || *(ep - 1) != '/') + sep = 1; + else + sep = 0; + + /* + * +2 : possible separator, plus terminator. + */ + result = kmalloc(prefix_len + name_len + 2, M_LINKER, M_WAITOK); - strncpy(result, cp, ep - cp); - strcpy(result + (ep - cp), name); + strncpy(result, cp, prefix_len); + if (sep) + result[prefix_len++] = '/'; + strcpy(result + prefix_len, name); /* * Attempt to open the file, and return the path if we succeed and it's