/* * kobj_affix: * * Set an object's name and perform global relocs. May only be * called after the module and any requisite modules are loaded. */ int kobj_affix(kobj_t ko, const char *name) { int error; KASSERT(ko->ko_ksyms == false); KASSERT(ko->ko_loaded == false); kobj_setname(ko, name); /* Cache addresses of undefined symbols. */ error = kobj_checksyms(ko, true); /* Now do global relocations. */ if (error == 0) error = kobj_relocate(ko, false); /* * Now that we know the name, register the symbol table. * Do after global relocations because ksyms will pack * the table. */ if (error == 0) { ksyms_modload(ko->ko_name, ko->ko_symtab, ko->ko_symcnt * sizeof(Elf_Sym), ko->ko_strtab, ko->ko_strtabsz); ko->ko_ksyms = true; } /* Jettison unneeded memory post-link. */ kobj_jettison(ko); /* * Notify MD code that a module has been loaded. * * Most architectures use this opportunity to flush their caches. */ if (error == 0) { error = kobj_machdep(ko, (void *)ko->ko_address, ko->ko_size, true); if (error != 0) kobj_error(__func__, __LINE__, ko, "machine dependent init failed %d", error); ko->ko_loaded = true; } /* If there was an error, destroy the whole object. */ if (error != 0) { kobj_unload(ko); } return error; }
/* * kobj_load_vfs: * * Load an object located in the file system. */ int kobj_load_vfs(kobj_t *kop, const char *path, const bool nochroot) { struct nameidata nd; struct pathbuf *pb; kauth_cred_t cred; int error; kobj_t ko; KASSERT(path != NULL); if (strchr(path, '/') == NULL) return ENOENT; cred = kauth_cred_get(); ko = kmem_zalloc(sizeof(*ko), KM_SLEEP); if (ko == NULL) { return ENOMEM; } pb = pathbuf_create(path); if (pb == NULL) { kmem_free(ko, sizeof(*ko)); return ENOMEM; } NDINIT(&nd, LOOKUP, FOLLOW | (nochroot ? NOCHROOT : 0), pb); error = vn_open(&nd, FREAD, 0); if (error != 0) { pathbuf_destroy(pb); kmem_free(ko, sizeof(*ko)); return error; } ko->ko_type = KT_VNODE; kobj_setname(ko, path); ko->ko_source = nd.ni_vp; ko->ko_read = kobj_read_vfs; ko->ko_close = kobj_close_vfs; pathbuf_destroy(pb); *kop = ko; return kobj_load(ko); }
/* * kobj_load_mem: * * Load an object already resident in memory. If size is not -1, * the complete size of the object is known. */ int kobj_load_mem(kobj_t *kop, const char *name, void *base, ssize_t size) { kobj_t ko; ko = kmem_zalloc(sizeof(*ko), KM_SLEEP); if (ko == NULL) { return ENOMEM; } ko->ko_type = KT_MEMORY; kobj_setname(ko, name); ko->ko_source = base; ko->ko_memsize = size; ko->ko_read = kobj_read_mem; ko->ko_close = kobj_close_mem; *kop = ko; return kobj_load(ko); }