/* * 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_unload: * * Unload an object previously loaded by kobj_load(). */ void kobj_unload(kobj_t ko) { int error; kobj_close(ko); kobj_jettison(ko); /* * Notify MD code that a module has been unloaded. */ if (ko->ko_loaded) { error = kobj_machdep(ko, (void *)ko->ko_address, ko->ko_size, false); if (error != 0) kobj_error(__func__, __LINE__, ko, "machine dependent deinit failed %d", error); } if (ko->ko_address != 0 && ko->ko_type != KT_MEMORY) { uvm_km_free(module_map, ko->ko_address, round_page(ko->ko_size), UVM_KMF_WIRED); } if (ko->ko_ksyms == true) { ksyms_modunload(ko->ko_name); } if (ko->ko_symtab != NULL) { kobj_free(ko, ko->ko_symtab, ko->ko_symcnt * sizeof(Elf_Sym)); } if (ko->ko_strtab != NULL) { kobj_free(ko, ko->ko_strtab, ko->ko_strtabsz); } if (ko->ko_progtab != NULL) { kobj_free(ko, ko->ko_progtab, ko->ko_nprogtab * sizeof(*ko->ko_progtab)); ko->ko_progtab = NULL; } if (ko->ko_shstrtab) { kobj_free(ko, ko->ko_shstrtab, ko->ko_shstrtabsz); ko->ko_shstrtab = NULL; } kmem_free(ko, sizeof(*ko)); }
/* * 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); strlcpy(ko->ko_name, name, sizeof(ko->ko_name)); /* Now do global relocations. */ error = kobj_relocate(ko, false); /* * Now that we know the name, register the symbol table. * Do after global relocations because ksyms will pack it. */ 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. */ if (error == 0) { error = kobj_machdep(ko, (void *)ko->ko_address, ko->ko_size, true); if (error != 0) { kobj_error("machine dependent init failed"); } ko->ko_loaded = true; } /* If there was an error, destroy the whole object. */ if (error != 0) { kobj_unload(ko); } return error; }