Is now using a hash for the images instead of a singly linked list.

Now registers its images as it should do (so you can use commands like
listimage in userland).
Added new debugger command "image".


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7522 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2004-05-11 17:18:02 +00:00
parent 11a5baaf67
commit a364fba7d4

View File

@ -14,8 +14,10 @@
#include <vfs.h>
#include <vm.h>
#include <thread.h>
#include <team.h>
#include <debug.h>
#include <kimage.h>
#include <khash.h>
#include <arch/cpu.h>
#include <arch/elf.h>
@ -37,6 +39,10 @@
#endif
#define IMAGE_HASH_SIZE 16
static hash_table *sImagesHash;
// XXX TK this shall contain a list of linked images
// (don't know enough about ELF how to get this list)
typedef struct elf_linked_image {
@ -44,19 +50,72 @@ typedef struct elf_linked_image {
struct elf_image_info *image;
} elf_linked_image;
static struct elf_image_info *kernel_images = NULL;
static struct elf_image_info *kernel_image = NULL;
static mutex image_lock;
static mutex image_load_lock;
static image_id next_image_id = 0;
static status_t elf_unload_image(struct elf_image_info *image);
/** calculates hash for an image using its ID */
static uint32
image_hash(void *_image, const void *_key, uint32 range)
{
struct elf_image_info *image = (struct elf_image_info *)_image;
image_id id = (image_id)_key;
if (image != NULL)
return image->id % range;
return id % range;
}
/** compares an image to a given ID */
static int
image_compare(void *_image, const void *_key)
{
struct elf_image_info *image = (struct elf_image_info *)_image;
image_id id = (image_id)_key;
return id - image->id;
}
static void
unregister_elf_image(struct elf_image_info *image)
{
hash_remove(sImagesHash, image);
}
static void
register_elf_image(struct elf_image_info *image)
{
image_info imageInfo;
image->id = register_image(team_get_kernel_team(), &imageInfo, sizeof(image_info));
memset(&imageInfo, 0, sizeof(image_info));
imageInfo.id = image->id;
imageInfo.type = B_SYSTEM_IMAGE;
strlcpy(imageInfo.name, image->name, sizeof(imageInfo.name));
imageInfo.text = (void *)image->regions[0].start;
imageInfo.text_size = image->regions[0].size;
imageInfo.data = (void *)image->regions[1].start;
imageInfo.data_size = image->regions[1].size;
hash_insert(sImagesHash, image);
}
status_t
elf_lookup_symbol_address(addr address, addr *baseAddress, char *text, size_t length)
{
struct elf_image_info **ptr;
struct hash_iterator iterator;
struct elf_image_info *image;
struct Elf32_Sym *sym;
struct elf_image_info *found_image;
@ -68,14 +127,13 @@ elf_lookup_symbol_address(addr address, addr *baseAddress, char *text, size_t le
PRINT(("looking up %p\n",(void *)address));
mutex_lock(&image_lock);
hash_open(sImagesHash, &iterator);
found_sym = 0;
found_image = 0;
found_delta = 0x7fffffff;
for (ptr = &kernel_images; *ptr; ptr = &(*ptr)->next) {
image = *ptr;
while ((image = hash_next(sImagesHash, &iterator)) != NULL) {
PRINT((" 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;
@ -120,7 +178,9 @@ elf_lookup_symbol_address(addr address, addr *baseAddress, char *text, size_t le
rv = B_ENTRY_NOT_FOUND;
}
hash_close(sImagesHash, &iterator, false);
mutex_unlock(&image_lock);
return rv;
}
@ -144,65 +204,28 @@ print_address_info(int argc, char **argv)
}
static void
insert_image_in_list(struct elf_image_info *image)
{
mutex_lock(&image_lock);
image->next = kernel_images;
kernel_images = image;
mutex_unlock(&image_lock);
}
static void
remove_image_from_list(struct elf_image_info *image)
{
struct elf_image_info **ptr;
mutex_lock(&image_lock);
for(ptr = &kernel_images; *ptr; ptr = &(*ptr)->next) {
if(*ptr == image) {
*ptr = image->next;
image->next = 0;
break;
}
}
mutex_unlock(&image_lock);
}
static struct elf_image_info *
find_image(image_id id)
{
struct elf_image_info *image;
mutex_lock(&image_lock);
for(image = kernel_images; image; image = image->next) {
if(image->id == id)
break;
}
mutex_unlock(&image_lock);
return image;
return hash_lookup(sImagesHash, (void *)id);
}
static struct elf_image_info *
find_image_by_vnode(void *vnode)
{
struct hash_iterator iterator;
struct elf_image_info *image;
mutex_lock(&image_lock);
hash_open(sImagesHash, &iterator);
for (image = kernel_images; image; image = image->next) {
while ((image = hash_next(sImagesHash, &iterator)) != NULL) {
if (image->vnode == vnode)
break;
}
hash_close(sImagesHash, &iterator, false);
mutex_unlock(&image_lock);
return image;
@ -220,7 +243,6 @@ create_image_struct()
image->regions[0].id = -1;
image->regions[1].id = -1;
image->id = atomic_add(&next_image_id, 1);
image->ref_count = 1;
image->linked_images = NULL;
@ -271,6 +293,43 @@ dump_image_info(struct elf_image_info *image)
dprintf(" pltrel_len 0x%x\n", image->pltrel_len);
}
static int
dump_image(int argc, char **argv)
{
struct hash_iterator iterator;
struct elf_image_info *image;
// if the argument looks like a hex number, treat it as such
if (argc > 1) {
uint32 num = strtoul(argv[1], NULL, 0);
if (IS_KERNEL_ADDRESS(num)) {
// semi-hack
dump_image_info((struct elf_image_info *)num);
} else {
image = hash_lookup(sImagesHash, (void *)num);
if (image == NULL)
dprintf("image 0x%lx doesn't exist in the kernel!\n", num);
else
dump_image_info(image);
}
return 0;
}
dprintf("loaded kernel images:\n");
hash_open(sImagesHash, &iterator);
while ((image = hash_next(sImagesHash, &iterator)) != NULL) {
dprintf("%p (%ld) %s\n", image, image->id, image->name);
}
hash_close(sImagesHash, &iterator, false);
return 0;
}
/* XXX - Currently unused
static void dump_symbol(struct elf_image_info *image, struct Elf32_Sym *sym)
{
@ -851,7 +910,7 @@ elf_load_kspace(const char *path, const char *sym_prepend)
free(pheaders);
sys_close(fd);
insert_image_in_list(image);
register_elf_image(image);
done:
mutex_unlock(&image_load_lock);
@ -907,7 +966,8 @@ elf_unload_image_final(struct elf_image_info *image)
if (image->vnode)
vfs_put_vnode_ptr(image->vnode);
remove_image_from_list(image);
unregister_elf_image(image);
free(image->eheader);
free(image->name);
free(image);
@ -1003,7 +1063,7 @@ insert_preloaded_image(struct preloaded_image *preloadedImage)
if (status < B_OK)
goto error2;
insert_image_in_list(image);
register_elf_image(image);
return B_OK;
error2:
@ -1026,6 +1086,10 @@ elf_init(kernel_args *ka)
mutex_init(&image_lock, "kimages_lock");
mutex_init(&image_load_lock, "kimages_load_lock");
sImagesHash = hash_init(IMAGE_HASH_SIZE, 0, image_compare, image_hash);
if (sImagesHash == NULL)
return B_NO_MEMORY;
// Build a image structure for the kernel, which has already been loaded.
// The VM has created areas for it under a known name already
@ -1058,7 +1122,7 @@ elf_init(kernel_args *ka)
dprintf("elf_init: WARNING elf_parse_dynamic_section couldn't find dynamic section.\n");
// insert it first in the list of kernel images loaded
insert_image_in_list(kernel_image);
register_elf_image(kernel_image);
// Build image structures for all preloaded images.
// Again, the VM has already created areas for them.
@ -1067,6 +1131,7 @@ elf_init(kernel_args *ka)
}
add_debugger_command("ls", &print_address_info, "lookup symbol for a particular address");
add_debugger_command("image", &dump_image, "dump image info");
return B_OK;
}