Bye, bye elf_lookup_symbol(), hello get_image_symbol().

Also renamed elf_load_kspace() to load_kernel_add_on(), and friends.
The new unload_kernel_add_on() now has an image_id as parameter, no longer
a path (like the former elf_unload_kspace()).
Fixed missign file system unload.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7527 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2004-05-11 19:52:38 +00:00
parent 81c323a767
commit b918b5035f
4 changed files with 254 additions and 253 deletions

View File

@ -55,8 +55,6 @@ static struct elf_image_info *sKernelImage = NULL;
static mutex sImageMutex;
static mutex sImageLoadMutex;
static status_t elf_unload_image(struct elf_image_info *image);
/** calculates hash for an image using its ID */
@ -114,79 +112,6 @@ register_elf_image(struct elf_image_info *image)
}
status_t
elf_lookup_symbol_address(addr address, addr *baseAddress, char *text, size_t length)
{
struct hash_iterator iterator;
struct elf_image_info *image;
struct Elf32_Sym *sym;
struct elf_image_info *found_image;
struct Elf32_Sym *found_sym;
long found_delta;
uint32 i;
int j,rv;
TRACE(("looking up %p\n",(void *)address));
mutex_lock(&sImageMutex);
hash_open(sImagesHash, &iterator);
found_sym = 0;
found_image = 0;
found_delta = 0x7fffffff;
while ((image = hash_next(sImagesHash, &iterator)) != NULL) {
TRACE((" image %p, base = %p, size = %p\n", image, (void *)image->regions[0].start, (void *)image->regions[0].size));
if ((address < image->regions[0].start) || (address >= (image->regions[0].start + image->regions[0].size)))
continue;
TRACE((" searching...\n"));
found_image = image;
for (i = 0; i < HASHTABSIZE(image); i++) {
for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) {
long d;
sym = &image->syms[j];
TRACE((" %p looking at %s, type = %d, bind = %d, addr = %p\n",sym,SYMNAME(image, sym),ELF32_ST_TYPE(sym->st_info),ELF32_ST_BIND(sym->st_info),(void *)sym->st_value));
TRACE((" symbol: %lx (%x + %lx)\n", sym->st_value + image->regions[0].delta, sym->st_value, image->regions[0].delta));
if ((ELF32_ST_TYPE(sym->st_info) != STT_FUNC) || (ELF32_ST_BIND(sym->st_info) != STB_GLOBAL))
continue;
d = (long)address - (long)(sym->st_value + image->regions[0].delta);
if ((d >= 0) && (d < found_delta)) {
found_delta = d;
found_sym = sym;
}
}
}
break;
}
if (found_sym != 0) {
TRACE(("symbol at %p, in image %p, name = %s\n", found_sym, found_image, found_image->name));
TRACE(("name index %d, '%s'\n", found_sym->st_name, SYMNAME(found_image, found_sym)));
TRACE(("addr = %#lx, offset = %#lx\n",(found_sym->st_value + found_image->regions[0].delta),found_delta));
strlcpy(text, SYMNAME(found_image, found_sym), length);
if (baseAddress)
*baseAddress = found_sym->st_value + found_image->regions[0].delta;
rv = B_OK;
} else {
TRACE(("symbol not found!\n"));
strlcpy(text, "symbol not found", length);
rv = B_ENTRY_NOT_FOUND;
}
hash_close(sImagesHash, &iterator, false);
mutex_unlock(&sImageMutex);
return rv;
}
static int
print_address_info(int argc, char **argv)
{
@ -368,32 +293,6 @@ elf_find_symbol(struct elf_image_info *image, const char *name)
}
addr_t
elf_lookup_symbol(image_id id, const char *symbol)
{
struct elf_image_info *image;
struct Elf32_Sym *sym;
TRACE(("elf_lookup_symbol: %s\n", symbol));
image = find_image(id);
if (!image)
return 0;
sym = elf_find_symbol(image, symbol);
if (!sym)
return 0;
if (sym->st_shndx == SHN_UNDEF)
return 0;
TRACE(("found: %lx (%x + %lx)\n", sym->st_value + image->regions[0].delta,
sym->st_value, image->regions[0].delta));
return sym->st_value + image->regions[0].delta;
}
static status_t
elf_parse_dynamic_section(struct elf_image_info *image)
{
@ -517,7 +416,7 @@ elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *sym, struct e
}
// XXX for now just link against the kernel
/** Until we have shared library support, just links against the kernel */
static int
elf_relocate(struct elf_image_info *image, const char *sym_prepend)
@ -575,8 +474,220 @@ verify_eheader(struct Elf32_Ehdr *eheader)
}
#if 0
static int
elf_unlink_relocs(struct elf_image_info *image)
{
elf_linked_image *link, *next_link;
for (link = image->linked_images; link; link = next_link) {
next_link = link->next;
elf_unload_image(link->image);
free(link);
}
return B_NO_ERROR;
}
#endif
static status_t
unload_elf_image(struct elf_image_info *image)
{
int i;
if (atomic_add(&image->ref_count, -1) > 0)
return B_NO_ERROR;
//elf_unlink_relocs(image);
// not yet used
for (i = 0; i < 2; ++i) {
delete_area(image->regions[i].id);
}
if (image->vnode)
vfs_put_vnode_ptr(image->vnode);
unregister_elf_image(image);
free(image->eheader);
free(image->name);
free(image);
return B_NO_ERROR;
}
static status_t
insert_preloaded_image(struct preloaded_image *preloadedImage)
{
struct Elf32_Ehdr *elfHeader;
struct elf_image_info *image;
status_t status;
elfHeader = (struct Elf32_Ehdr *)malloc(sizeof(struct Elf32_Ehdr));
if (elfHeader == NULL)
return B_NO_MEMORY;
memcpy(elfHeader, &preloadedImage->elf_header, sizeof(struct Elf32_Ehdr));
status = verify_eheader(elfHeader);
if (status < B_OK)
goto error1;
image = create_image_struct();
if (image == NULL) {
status = B_NO_MEMORY;
goto error1;
}
image->vnode = NULL;
image->eheader = elfHeader;
image->name = strdup(preloadedImage->name);
image->dynamic_ptr = preloadedImage->dynamic_section.start;
image->regions[0] = preloadedImage->text_region;
image->regions[1] = preloadedImage->data_region;
status = elf_parse_dynamic_section(image);
if (status < B_OK)
goto error2;
status = elf_relocate(image, "");
if (status < B_OK)
goto error2;
register_elf_image(image);
return B_OK;
error2:
free(image);
error1:
free(elfHeader);
return status;
}
// #pragma mark -
// public kernel API
status_t
elf_load_uspace(const char *path, struct team *p, int flags, addr *entry)
get_image_symbol(image_id id, const char *name, int32 sclass, void **_symbol)
{
struct elf_image_info *image;
struct Elf32_Sym *symbol;
status_t status = B_OK;
TRACE(("get_image_symbol(%s)\n", name));
mutex_lock(&sImageMutex);
image = find_image(id);
if (image == NULL) {
status = B_BAD_IMAGE_ID;
goto done;
}
symbol = elf_find_symbol(image, name);
if (symbol == NULL || symbol->st_shndx == SHN_UNDEF) {
status = B_ENTRY_NOT_FOUND;
goto done;
}
// ToDo: support the "sclass" parameter!
TRACE(("found: %lx (%x + %lx)\n", sym->st_value + image->regions[0].delta,
sym->st_value, image->regions[0].delta));
*_symbol = (void *)(symbol->st_value + image->regions[0].delta);
done:
mutex_unlock(&sImageMutex);
return status;
}
// #pragma mark -
// kernel private API
status_t
elf_lookup_symbol_address(addr address, addr *baseAddress, char *text, size_t length)
{
struct hash_iterator iterator;
struct elf_image_info *image;
struct Elf32_Sym *sym;
struct elf_image_info *found_image;
struct Elf32_Sym *found_sym;
long found_delta;
uint32 i;
int j,rv;
TRACE(("looking up %p\n",(void *)address));
mutex_lock(&sImageMutex);
hash_open(sImagesHash, &iterator);
found_sym = 0;
found_image = 0;
found_delta = 0x7fffffff;
while ((image = hash_next(sImagesHash, &iterator)) != NULL) {
TRACE((" image %p, base = %p, size = %p\n", image, (void *)image->regions[0].start, (void *)image->regions[0].size));
if ((address < image->regions[0].start) || (address >= (image->regions[0].start + image->regions[0].size)))
continue;
TRACE((" searching...\n"));
found_image = image;
for (i = 0; i < HASHTABSIZE(image); i++) {
for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) {
long d;
sym = &image->syms[j];
TRACE((" %p looking at %s, type = %d, bind = %d, addr = %p\n",sym,SYMNAME(image, sym),ELF32_ST_TYPE(sym->st_info),ELF32_ST_BIND(sym->st_info),(void *)sym->st_value));
TRACE((" symbol: %lx (%x + %lx)\n", sym->st_value + image->regions[0].delta, sym->st_value, image->regions[0].delta));
if ((ELF32_ST_TYPE(sym->st_info) != STT_FUNC) || (ELF32_ST_BIND(sym->st_info) != STB_GLOBAL))
continue;
d = (long)address - (long)(sym->st_value + image->regions[0].delta);
if ((d >= 0) && (d < found_delta)) {
found_delta = d;
found_sym = sym;
}
}
}
break;
}
if (found_sym != 0) {
TRACE(("symbol at %p, in image %p, name = %s\n", found_sym, found_image, found_image->name));
TRACE(("name index %d, '%s'\n", found_sym->st_name, SYMNAME(found_image, found_sym)));
TRACE(("addr = %#lx, offset = %#lx\n",(found_sym->st_value + found_image->regions[0].delta),found_delta));
strlcpy(text, SYMNAME(found_image, found_sym), length);
if (baseAddress)
*baseAddress = found_sym->st_value + found_image->regions[0].delta;
rv = B_OK;
} else {
TRACE(("symbol not found!\n"));
strlcpy(text, "symbol not found", length);
rv = B_ENTRY_NOT_FOUND;
}
hash_close(sImagesHash, &iterator, false);
mutex_unlock(&sImageMutex);
return rv;
}
status_t
elf_load_user_image(const char *path, struct team *p, int flags, addr *entry)
{
struct Elf32_Ehdr eheader;
struct Elf32_Phdr *pheaders = NULL;
@ -735,7 +846,7 @@ error:
image_id
elf_load_kspace(const char *path, const char *sym_prepend)
load_kernel_add_on(const char *path)
{
bool ro_segment_handled = false;
bool rw_segment_handled = false;
@ -905,7 +1016,7 @@ elf_load_kspace(const char *path, const char *sym_prepend)
if (err < 0)
goto error4;
err = elf_relocate(image, sym_prepend);
err = elf_relocate(image, "");
if (err < 0)
goto error4;
@ -942,140 +1053,26 @@ error0:
return err;
}
#if 0
static int
elf_unlink_relocs(struct elf_image_info *image)
{
elf_linked_image *link, *next_link;
for (link = image->linked_images; link; link = next_link) {
next_link = link->next;
elf_unload_image(link->image);
free(link);
}
return B_NO_ERROR;
}
#endif
static void
elf_unload_image_final(struct elf_image_info *image)
{
int i;
for (i = 0; i < 2; ++i) {
delete_area(image->regions[i].id);
}
if (image->vnode)
vfs_put_vnode_ptr(image->vnode);
unregister_elf_image(image);
free(image->eheader);
free(image->name);
free(image);
}
static status_t
elf_unload_image(struct elf_image_info *image)
{
if (atomic_add(&image->ref_count, -1) > 0)
return B_NO_ERROR;
//elf_unlink_relocs(image);
// not yet used
elf_unload_image_final(image);
return B_NO_ERROR;
}
status_t
elf_unload_kspace(const char *path)
unload_kernel_add_on(image_id id)
{
int fd;
int err;
void *vnode;
struct elf_image_info *image;
fd = sys_open(path, 0);
if (fd < 0)
return fd;
err = vfs_get_vnode_from_fd(fd, true, &vnode);
if (err < 0)
goto error0;
mutex_lock(&sImageLoadMutex);
image = find_image_by_vnode(vnode);
if (!image) {
dprintf("Tried to unload image that wasn't loaded (%s)\n", path);
err = B_ENTRY_NOT_FOUND;
goto error;
}
err = elf_unload_image(image);
error:
mutex_unlock(&sImageLoadMutex);
error0:
if(vnode)
vfs_put_vnode_ptr(vnode);
sys_close(fd);
return err;
}
static status_t
insert_preloaded_image(struct preloaded_image *preloadedImage)
{
struct Elf32_Ehdr *elfHeader;
struct elf_image_info *image;
status_t status;
elfHeader = (struct Elf32_Ehdr *)malloc(sizeof(struct Elf32_Ehdr));
if (elfHeader == NULL)
return B_NO_MEMORY;
mutex_lock(&sImageMutex);
image = find_image(id);
if (image != NULL) {
mutex_lock(&sImageLoadMutex);
memcpy(elfHeader, &preloadedImage->elf_header, sizeof(struct Elf32_Ehdr));
status = verify_eheader(elfHeader);
if (status < B_OK)
goto error1;
status = unload_elf_image(image);
image = create_image_struct();
if (image == NULL) {
status = B_NO_MEMORY;
goto error1;
}
image->vnode = NULL;
image->eheader = elfHeader;
image->name = strdup(preloadedImage->name);
image->dynamic_ptr = preloadedImage->dynamic_section.start;
image->regions[0] = preloadedImage->text_region;
image->regions[1] = preloadedImage->data_region;
status = elf_parse_dynamic_section(image);
if (status < B_OK)
goto error2;
status = elf_relocate(image, "");
if (status < B_OK)
goto error2;
register_elf_image(image);
return B_OK;
error2:
free(image);
error1:
free(elfHeader);
mutex_unlock(&sImageLoadMutex);
} else
status = B_BAD_IMAGE_ID;
mutex_unlock(&sImageMutex);
return status;
}

View File

@ -364,11 +364,11 @@ unload_file_system(file_system *fs)
if (fs->image < B_OK)
return B_OK;
uninit = (void (*)())elf_lookup_symbol(fs->image, "uninit_file_system");
if (uninit != NULL)
if (get_image_symbol(fs->image, "uninit_file_system",
B_SYMBOL_TYPE_TEXT, (void **)&uninit) == B_OK)
uninit();
// ToDo: unloading is not yet supported - we need a unload image_id first...
unload_kernel_add_on(fs->image);
free(fs);
return B_OK;
@ -385,22 +385,25 @@ load_file_system(const char *name)
void (*init)();
image_id image;
// ToDo: don't use fixed paths!!
// search in the user directory
sprintf(path, "/boot/home/config/add-ons/kernel/file_systems/%s", name);
image = elf_load_kspace(path, "");
image = load_kernel_add_on(path);
if (image == B_ENTRY_NOT_FOUND) {
// ToDo: this is not a BeOS compatible system directory (bootfs)
// search in the system directory
sprintf(path, "/boot/addons/fs/%s", name);
//sprintf(path, "/boot/beos/system/add-ons/kernel/file_systems/%s", name);
image = elf_load_kspace(path, "");
image = load_kernel_add_on(path);
}
if (image < B_OK)
return NULL;
init = (void (*)())elf_lookup_symbol(image, "init_file_system");
version = (int32 *)elf_lookup_symbol(image, "api_version");
ops = (fs_ops **)elf_lookup_symbol(image, "fs_entry");
if (init == NULL || version == NULL || ops == NULL) {
if (get_image_symbol(image, "init_file_system", B_SYMBOL_TYPE_TEXT, (void **)&init) != B_OK
|| get_image_symbol(image, "api_version", B_SYMBOL_TYPE_DATA, (void **)&version) != B_OK
|| get_image_symbol(image, "fs_entry", B_SYMBOL_TYPE_DATA, (void **)&ops) != B_OK) {
dprintf("vfs: add-on \"%s\" doesn't export all necessary symbols.\n", name);
goto err;
}
@ -422,7 +425,7 @@ load_file_system(const char *name)
return fs;
err:
elf_unload_kspace(path);
unload_kernel_add_on(image);
return NULL;
}

View File

@ -237,7 +237,7 @@ load_module_image(const char *path, module_image **_moduleImage)
TRACE(("load_module_image(path = \"%s\", _image = %p)\n", path, _moduleImage));
ASSERT(_moduleImage != NULL);
image = elf_load_kspace(path, "");
image = load_kernel_add_on(path);
if (image < 0) {
dprintf("load_module_image failed: %s\n", strerror(image));
return image;
@ -249,14 +249,16 @@ load_module_image(const char *path, module_image **_moduleImage)
goto err;
}
moduleImage->info = (module_info **)elf_lookup_symbol(image, "modules");
if (!moduleImage->info) {
if (get_image_symbol(image, "modules", B_SYMBOL_TYPE_DATA,
(void **)&moduleImage->info) != B_OK) {
FATAL(("load_module_image: Failed to load %s due to lack of 'modules' symbol\n", path));
status = B_BAD_TYPE;
goto err1;
}
moduleImage->dependencies = (module_dependency *)elf_lookup_symbol(image, "module_dependencies");
moduleImage->dependencies = NULL;
get_image_symbol(image, "module_dependencies", B_SYMBOL_TYPE_DATA,
(void **)&moduleImage->dependencies);
// this is allowed to be NULL
moduleImage->path = strdup(path);
@ -279,7 +281,7 @@ load_module_image(const char *path, module_image **_moduleImage)
err1:
free(moduleImage);
err:
elf_unload_kspace(path);
unload_kernel_add_on(image);
return status;
}
@ -306,7 +308,7 @@ unload_module_image(module_image *moduleImage, const char *path)
hash_remove(sModuleImagesHash, moduleImage);
recursive_lock_unlock(&sModulesLock);
elf_unload_kspace(moduleImage->path);
unload_kernel_add_on(moduleImage->image);
free(moduleImage->path);
free(moduleImage);

View File

@ -160,6 +160,7 @@ kfree_strings_array(char **strings, int strc)
{
int cnt = strc;
if (strings != NULL) {
for (cnt = 0; cnt < strc; cnt++){
free(strings[cnt]);
@ -543,7 +544,7 @@ team_create_team2(void *args)
uargs[arg_cnt] = NULL;
team->user_env_base = t->user_stack_base + STACK_SIZE + TLS_SIZE;
uenv = (char **)team->user_env_base;
uenv = (char **)team->user_env_base;
udest = (char *)team->user_env_base + ENV_SIZE - 1;
TRACE(("team_create_team2: envc: %d, envp: 0x%p\n", teamArgs->envc, (void *)teamArgs->envp));
@ -563,16 +564,14 @@ team_create_team2(void *args)
uspa->envc = env_cnt;
uspa->envp = uenv;
if (teamArgs->args != NULL)
kfree_strings_array(teamArgs->args, teamArgs->argc);
if (teamArgs->envp != NULL)
kfree_strings_array(teamArgs->envp, teamArgs->envc);
kfree_strings_array(teamArgs->args, teamArgs->argc);
kfree_strings_array(teamArgs->envp, teamArgs->envc);
path = teamArgs->path;
TRACE(("team_create_team2: loading elf binary '%s'\n", path));
err = elf_load_uspace("/boot/libexec/rld.so", team, 0, &entry);
if (err < 0){
err = elf_load_user_image("/boot/libexec/rld.so", team, 0, &entry);
if (err < 0) {
// XXX clean up team
return err;
}