From 8c6cb8af0107fe8216dd2e5394c157fe7559cf13 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 27 Apr 2016 01:56:42 +0200 Subject: [PATCH] runtime loader: Register extended image info with kernel Add structure extended_image_info which extends image_info by the fields symbol_table, symbol_hash, string_table. --- headers/private/kernel/kimage.h | 11 ++- headers/private/system/image_defs.h | 12 +++- headers/private/system/syscalls.h | 4 +- src/system/kernel/debug/core_dump.cpp | 22 +++--- src/system/kernel/debug/system_profiler.cpp | 4 +- src/system/kernel/elf.cpp | 68 ++++++++++--------- src/system/kernel/image.cpp | 74 +++++++++++++++------ src/system/kernel/team.cpp | 22 +++--- src/system/runtime_loader/images.cpp | 42 ++++++------ 9 files changed, 159 insertions(+), 100 deletions(-) diff --git a/headers/private/kernel/kimage.h b/headers/private/kernel/kimage.h index cc8495c2df..34e87ef5bf 100644 --- a/headers/private/kernel/kimage.h +++ b/headers/private/kernel/kimage.h @@ -7,6 +7,8 @@ #include +#include + struct image; @@ -25,7 +27,7 @@ struct image { struct image* next; struct image* prev; struct image* hash_link; - image_info info; + extended_image_info info; team_id team; }; @@ -41,8 +43,10 @@ struct image { extern "C" { #endif -extern image_id register_image(Team *team, image_info *info, size_t size); +extern image_id register_image(Team *team, extended_image_info *info, + size_t size); extern status_t unregister_image(Team *team, image_id id); +extern status_t copy_images(team_id fromTeamId, Team *toTeam); extern int32 count_images(Team *team); extern status_t remove_images(Team *team); @@ -59,7 +63,8 @@ extern status_t image_init(void); // user-space exported calls extern status_t _user_unregister_image(image_id id); -extern image_id _user_register_image(image_info *userInfo, size_t size); +extern image_id _user_register_image(extended_image_info *userInfo, + size_t size); extern void _user_image_relocated(image_id id); extern void _user_loading_app_failed(status_t error); extern status_t _user_get_next_image_info(team_id team, int32 *_cookie, diff --git a/headers/private/system/image_defs.h b/headers/private/system/image_defs.h index 5247118080..49c1b1368f 100644 --- a/headers/private/system/image_defs.h +++ b/headers/private/system/image_defs.h @@ -1,11 +1,13 @@ /* - * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2009-2016, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #ifndef _SYSTEM_IMAGE_DEFS_H #define _SYSTEM_IMAGE_DEFS_H + #include +#include #define B_SHARED_OBJECT_HAIKU_VERSION_VARIABLE _gSharedObjectHaikuVersion @@ -15,4 +17,12 @@ #define B_SHARED_OBJECT_HAIKU_ABI_VARIABLE_NAME "_gSharedObjectHaikuABI" +typedef struct extended_image_info { + image_info basic_info; + void* symbol_table; + void* symbol_hash; + void* string_table; +} extended_image_info; + + #endif /* _SYSTEM_IMAGE_DEFS_H */ diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index f71fb3d013..b203434412 100644 --- a/headers/private/system/syscalls.h +++ b/headers/private/system/syscalls.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -223,7 +224,8 @@ extern status_t _kern_set_signal_stack(const stack_t *newStack, stack_t *oldStack); // image functions -extern image_id _kern_register_image(image_info *info, size_t size); +extern image_id _kern_register_image(extended_image_info *info, + size_t size); extern status_t _kern_unregister_image(image_id id); extern void _kern_image_relocated(image_id id); extern void _kern_loading_app_failed(status_t error); diff --git a/src/system/kernel/debug/core_dump.cpp b/src/system/kernel/debug/core_dump.cpp index bee04aae82..a4d41a4593 100644 --- a/src/system/kernel/debug/core_dump.cpp +++ b/src/system/kernel/debug/core_dump.cpp @@ -246,17 +246,17 @@ typedef DoublyLinkedList ThreadStateList; struct ImageInfo : DoublyLinkedListLinkImpl { ImageInfo(struct image* image) : - fId(image->info.id), - fType(image->info.type), - fDeviceId(image->info.device), - fNodeId(image->info.node), - fName(strdup(image->info.name)), - fInitRoutine((addr_t)image->info.init_routine), - fTermRoutine((addr_t)image->info.term_routine), - fText((addr_t)image->info.text), - fData((addr_t)image->info.data), - fTextSize(image->info.text_size), - fDataSize(image->info.data_size) + fId(image->info.basic_info.id), + fType(image->info.basic_info.type), + fDeviceId(image->info.basic_info.device), + fNodeId(image->info.basic_info.node), + fName(strdup(image->info.basic_info.name)), + fInitRoutine((addr_t)image->info.basic_info.init_routine), + fTermRoutine((addr_t)image->info.basic_info.term_routine), + fText((addr_t)image->info.basic_info.text), + fData((addr_t)image->info.basic_info.data), + fTextSize(image->info.basic_info.text_size), + fDataSize(image->info.basic_info.data_size) { } diff --git a/src/system/kernel/debug/system_profiler.cpp b/src/system/kernel/debug/system_profiler.cpp index 1ad27d276c..f931b3f7ba 100644 --- a/src/system/kernel/debug/system_profiler.cpp +++ b/src/system/kernel/debug/system_profiler.cpp @@ -1019,7 +1019,7 @@ SystemProfiler::_ImageAdded(struct image* image) return false; event->team = image->team; - event->info = image->info; + event->info = image->info.basic_info; fHeader->size = fBufferSize; @@ -1039,7 +1039,7 @@ SystemProfiler::_ImageRemoved(struct image* image) return false; event->team = image->team; - event->image = image->info.id; + event->image = image->info.basic_info.id; fHeader->size = fBufferSize; diff --git a/src/system/kernel/elf.cpp b/src/system/kernel/elf.cpp index 544fb5a8df..3a2abfbd13 100644 --- a/src/system/kernel/elf.cpp +++ b/src/system/kernel/elf.cpp @@ -108,23 +108,24 @@ unregister_elf_image(struct elf_image_info *image) static void register_elf_image(struct elf_image_info *image) { - image_info imageInfo; + extended_image_info imageInfo; - memset(&imageInfo, 0, sizeof(image_info)); - imageInfo.id = image->id; - imageInfo.type = B_SYSTEM_IMAGE; - strlcpy(imageInfo.name, image->name, sizeof(imageInfo.name)); + memset(&imageInfo, 0, sizeof(imageInfo)); + imageInfo.basic_info.id = image->id; + imageInfo.basic_info.type = B_SYSTEM_IMAGE; + strlcpy(imageInfo.basic_info.name, image->name, + sizeof(imageInfo.basic_info.name)); - imageInfo.text = (void *)image->text_region.start; - imageInfo.text_size = image->text_region.size; - imageInfo.data = (void *)image->data_region.start; - imageInfo.data_size = image->data_region.size; + imageInfo.basic_info.text = (void *)image->text_region.start; + imageInfo.basic_info.text_size = image->text_region.size; + imageInfo.basic_info.data = (void *)image->data_region.start; + imageInfo.basic_info.data_size = image->data_region.size; if (image->text_region.id >= 0) { // evaluate the API/ABI version symbols // Haiku API version - imageInfo.api_version = 0; + imageInfo.basic_info.api_version = 0; elf_sym* symbol = elf_find_symbol(image, B_SHARED_OBJECT_HAIKU_VERSION_VARIABLE_NAME, NULL, true); if (symbol != NULL && symbol->st_shndx != SHN_UNDEF @@ -135,12 +136,12 @@ register_elf_image(struct elf_image_info *image) if (symbolAddress >= image->text_region.start && symbolAddress - image->text_region.start + sizeof(uint32) <= image->text_region.size) { - imageInfo.api_version = *(uint32*)symbolAddress; + imageInfo.basic_info.api_version = *(uint32*)symbolAddress; } } // Haiku ABI - imageInfo.abi = 0; + imageInfo.basic_info.abi = 0; symbol = elf_find_symbol(image, B_SHARED_OBJECT_HAIKU_ABI_VARIABLE_NAME, NULL, true); if (symbol != NULL && symbol->st_shndx != SHN_UNDEF @@ -151,17 +152,17 @@ register_elf_image(struct elf_image_info *image) if (symbolAddress >= image->text_region.start && symbolAddress - image->text_region.start + sizeof(uint32) <= image->text_region.size) { - imageInfo.api_version = *(uint32*)symbolAddress; + imageInfo.basic_info.api_version = *(uint32*)symbolAddress; } } } else { // in-memory image -- use the current values - imageInfo.api_version = B_HAIKU_VERSION; - imageInfo.abi = B_HAIKU_ABI; + imageInfo.basic_info.api_version = B_HAIKU_VERSION; + imageInfo.basic_info.abi = B_HAIKU_ABI; } image->id = register_image(team_get_kernel_team(), &imageInfo, - sizeof(image_info)); + sizeof(imageInfo)); sImagesHash->Insert(image); } @@ -1902,8 +1903,8 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) goto error2; } - image_info imageInfo; - memset(&imageInfo, 0, sizeof(image_info)); + extended_image_info imageInfo; + memset(&imageInfo, 0, sizeof(imageInfo)); for (i = 0; i < elfHeader.e_phnum; i++) { char regionName[B_OS_NAME_LENGTH]; @@ -1948,8 +1949,8 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) } mappedAreas[i] = id; - imageInfo.data = regionAddress; - imageInfo.data_size = memUpperBound; + imageInfo.basic_info.data = regionAddress; + imageInfo.basic_info.data_size = memUpperBound; image->data_region.start = (addr_t)regionAddress; image->data_region.size = memUpperBound; @@ -2005,8 +2006,8 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) mappedAreas[i] = id; - imageInfo.text = regionAddress; - imageInfo.text_size = segmentSize; + imageInfo.basic_info.text = regionAddress; + imageInfo.basic_info.text_size = segmentSize; image->text_region.start = (addr_t)regionAddress; image->text_region.size = segmentSize; @@ -2053,20 +2054,25 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) } // register the loaded image - imageInfo.type = B_LIBRARY_IMAGE; - imageInfo.device = st.st_dev; - imageInfo.node = st.st_ino; - strlcpy(imageInfo.name, path, sizeof(imageInfo.name)); + imageInfo.basic_info.type = B_LIBRARY_IMAGE; + imageInfo.basic_info.device = st.st_dev; + imageInfo.basic_info.node = st.st_ino; + strlcpy(imageInfo.basic_info.name, path, sizeof(imageInfo.basic_info.name)); - imageInfo.api_version = B_HAIKU_VERSION; - imageInfo.abi = B_HAIKU_ABI; + imageInfo.basic_info.api_version = B_HAIKU_VERSION; + imageInfo.basic_info.abi = B_HAIKU_ABI; // TODO: Get the actual values for the shared object. Currently only // the runtime loader is loaded, so this is good enough for the time // being. - imageInfo.id = register_image(team, &imageInfo, sizeof(image_info)); - if (imageInfo.id >= 0 && team_get_current_team_id() == team->id) - user_debug_image_created(&imageInfo); + imageInfo.symbol_table = image->syms; + imageInfo.symbol_hash = image->symhash; + imageInfo.string_table = image->strtab; + + imageInfo.basic_info.id = register_image(team, &imageInfo, + sizeof(imageInfo)); + if (imageInfo.basic_info.id >= 0 && team_get_current_team_id() == team->id) + user_debug_image_created(&imageInfo.basic_info); // Don't care, if registering fails. It's not crucial. TRACE(("elf_load: done!\n")); diff --git a/src/system/kernel/image.cpp b/src/system/kernel/image.cpp index de985c33b4..31fe3088fc 100644 --- a/src/system/kernel/image.cpp +++ b/src/system/kernel/image.cpp @@ -40,9 +40,9 @@ struct ImageTableDefinition { typedef struct image ValueType; size_t HashKey(image_id key) const { return key; } - size_t Hash(struct image* value) const { return value->info.id; } + size_t Hash(struct image* value) const { return value->info.basic_info.id; } bool Compare(image_id key, struct image* value) const - { return value->info.id == key; } + { return value->info.basic_info.id == key; } struct image*& GetLink(struct image* value) const { return value->hash_link; } }; @@ -63,7 +63,7 @@ public: KMessage event; event.SetTo(eventBuffer, sizeof(eventBuffer), IMAGE_MONITOR); event.AddInt32("event", eventCode); - event.AddInt32("image", image->info.id); + event.AddInt32("image", image->info.basic_info.id); event.AddPointer("imageStruct", image); DefaultNotificationService::Notify(event, eventCode); @@ -81,8 +81,8 @@ static ImageNotificationService sNotificationService; /*! Registers an image with the specified team. */ -image_id -register_image(Team *team, image_info *_info, size_t size) +static image_id +register_image(Team *team, extended_image_info *info, size_t size, bool locked) { image_id id = atomic_add(&sNextImageID, 1); struct image *image; @@ -91,16 +91,17 @@ register_image(Team *team, image_info *_info, size_t size) if (image == NULL) return B_NO_MEMORY; - memcpy(&image->info, _info, sizeof(image_info)); + memcpy(&image->info, info, sizeof(extended_image_info)); image->team = team->id; - mutex_lock(&sImageMutex); + if (!locked) + mutex_lock(&sImageMutex); - image->info.id = id; + image->info.basic_info.id = id; // Add the app image to the head of the list. Some code relies on it being // the first image to be returned by get_next_image_info(). - if (image->info.type == B_APP_IMAGE) + if (image->info.basic_info.type == B_APP_IMAGE) list_add_link_to_head(&team->image_list, image); else list_add_item(&team->image_list, image); @@ -109,13 +110,23 @@ register_image(Team *team, image_info *_info, size_t size) // notify listeners sNotificationService.Notify(IMAGE_ADDED, image); - mutex_unlock(&sImageMutex); + if (!locked) + mutex_unlock(&sImageMutex); TRACE(("register_image(team = %p, image id = %ld, image = %p\n", team, id, image)); return id; } +/*! Registers an image with the specified team. +*/ +image_id +register_image(Team *team, extended_image_info *info, size_t size) +{ + return register_image(team, info, size, false); +} + + /*! Unregisters an image from the specified team. */ status_t @@ -136,7 +147,7 @@ unregister_image(Team *team, image_id id) if (status == B_OK) { // notify the debugger - user_debug_image_deleted(&image->info); + user_debug_image_deleted(&image->info.basic_info); // notify listeners sNotificationService.Notify(IMAGE_REMOVED, image); @@ -148,6 +159,30 @@ unregister_image(Team *team, image_id id) } +status_t +copy_images(team_id fromTeamId, Team *toTeam) +{ + // get the team + Team* fromTeam = Team::Get(fromTeamId); + if (fromTeam == NULL) + return B_BAD_TEAM_ID; + BReference teamReference(fromTeam, true); + + MutexLocker locker(sImageMutex); + + struct image *image = NULL; + while ((image = (struct image*)list_get_next_item(&fromTeam->image_list, + image)) != NULL) { + image_id id = register_image(toTeam, &image->info, sizeof(image->info), + true); + if (id < 0) + return id; + } + + return B_OK; +} + + /*! Counts the registered images from the specified team. Interrupts must be enabled. */ @@ -204,7 +239,7 @@ _get_image_info(image_id id, image_info *info, size_t size) struct image *image = sImageTable->Lookup(id); if (image != NULL) { - memcpy(info, &image->info, size); + memcpy(info, &image->info.basic_info, size); status = B_OK; } @@ -236,7 +271,7 @@ _get_next_image_info(team_id teamID, int32 *cookie, image_info *info, while ((image = (struct image*)list_get_next_item(&team->image_list, image)) != NULL) { if (count == *cookie) { - memcpy(info, &image->info, size); + memcpy(info, &image->info.basic_info, size); (*cookie)++; return B_OK; } @@ -270,7 +305,7 @@ dump_images_list(int argc, char **argv) while ((image = (struct image*)list_get_next_item(&team->image_list, image)) != NULL) { - image_info *info = &image->info; + image_info *info = &image->info.basic_info; kprintf("%6" B_PRId32 " %p %-7" B_PRId32 " %p %-7" B_PRId32 " %s\n", info->id, info->text, info->text_size, info->data, info->data_size, @@ -328,13 +363,14 @@ image_debug_lookup_user_symbol_address(Team *team, addr_t address, addr_t *_baseAddress, const char **_symbolName, const char **_imageName, bool *_exactMatch) { - // TODO: work together with ELF reader and runtime_loader + // TODO: Work together with ELF reader and runtime_loader. For regular user + // images we have the symbol and string table addresses. struct image *image = NULL; while ((image = (struct image*)list_get_next_item(&team->image_list, image)) != NULL) { - image_info *info = &image->info; + image_info *info = &image->info.basic_info; if ((address < (addr_t)info->text || address >= (addr_t)info->text + info->text_size) @@ -424,11 +460,11 @@ _user_unregister_image(image_id id) image_id -_user_register_image(image_info *userInfo, size_t size) +_user_register_image(extended_image_info *userInfo, size_t size) { - image_info info; + extended_image_info info; - if (size != sizeof(image_info)) + if (size != sizeof(info)) return B_BAD_VALUE; if (!IS_USER_ADDRESS(userInfo) diff --git a/src/system/kernel/team.cpp b/src/system/kernel/team.cpp index c55b23957e..279fe98000 100644 --- a/src/system/kernel/team.cpp +++ b/src/system/kernel/team.cpp @@ -1604,15 +1604,18 @@ team_create_thread_start_internal(void* args) // Register commpage image image_id commPageImage = get_commpage_image(); - image_info imageInfo; - err = get_image_info(commPageImage, &imageInfo); + extended_image_info imageInfo; + err = get_image_info(commPageImage, &imageInfo.basic_info); if (err != B_OK) { TRACE(("team_create_thread_start: get_image_info() failed: %s\n", strerror(err))); return err; } - imageInfo.text = team->commpage_address; - image_id image = register_image(team, &imageInfo, sizeof(image_info)); + imageInfo.basic_info.text = team->commpage_address; + imageInfo.symbol_table = NULL; + imageInfo.symbol_hash = NULL; + imageInfo.string_table = NULL; + image_id image = register_image(team, &imageInfo, sizeof(imageInfo)); if (image < 0) { TRACE(("team_create_thread_start: register_image() failed: %s\n", strerror(image))); @@ -2031,7 +2034,6 @@ fork_team(void) thread_id threadID; status_t status; ssize_t areaCookie; - int32 imageCookie; TRACE(("fork_team(): team %" B_PRId32 "\n", parentTeam->id)); @@ -2174,14 +2176,8 @@ fork_team(void) arch_store_fork_frame(forkArgs); // copy image list - image_info imageInfo; - imageCookie = 0; - while (get_next_image_info(parentTeam->id, &imageCookie, &imageInfo) - == B_OK) { - image_id image = register_image(team, &imageInfo, sizeof(imageInfo)); - if (image < 0) - goto err5; - } + if (copy_images(parentTeam->id, team) != B_OK) + goto err5; // create the main thread { diff --git a/src/system/runtime_loader/images.cpp b/src/system/runtime_loader/images.cpp index 2b7f6dfe8c..3fea3d2b59 100644 --- a/src/system/runtime_loader/images.cpp +++ b/src/system/runtime_loader/images.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include "add_ons.h" @@ -466,22 +467,22 @@ void register_image(image_t* image, int fd, const char* path) { struct stat stat; - image_info info; + extended_image_info info; // TODO: set these correctly - info.id = 0; - info.type = image->type; - info.sequence = 0; - info.init_order = 0; - info.init_routine = (void (*)())image->init_routine; - info.term_routine = (void (*)())image->term_routine; + info.basic_info.id = 0; + info.basic_info.type = image->type; + info.basic_info.sequence = 0; + info.basic_info.init_order = 0; + info.basic_info.init_routine = (void (*)())image->init_routine; + info.basic_info.term_routine = (void (*)())image->term_routine; if (_kern_read_stat(fd, NULL, false, &stat, sizeof(struct stat)) == B_OK) { - info.device = stat.st_dev; - info.node = stat.st_ino; + info.basic_info.device = stat.st_dev; + info.basic_info.node = stat.st_ino; } else { - info.device = -1; - info.node = -1; + info.basic_info.device = -1; + info.basic_info.node = -1; } // We may have split segments into separate regions. Compute the correct @@ -514,14 +515,17 @@ register_image(image_t* image, int fd, const char* path) } } - strlcpy(info.name, path, sizeof(info.name)); - info.text = (void*)textBase; - info.text_size = textEnd - textBase; - info.data = (void*)dataBase; - info.data_size = dataEnd - dataBase; - info.api_version = image->api_version; - info.abi = image->abi; - image->id = _kern_register_image(&info, sizeof(image_info)); + strlcpy(info.basic_info.name, path, sizeof(info.basic_info.name)); + info.basic_info.text = (void*)textBase; + info.basic_info.text_size = textEnd - textBase; + info.basic_info.data = (void*)dataBase; + info.basic_info.data_size = dataEnd - dataBase; + info.basic_info.api_version = image->api_version; + info.basic_info.abi = image->abi; + info.symbol_table = image->syms; + info.symbol_hash = image->symhash; + info.string_table = image->strtab; + image->id = _kern_register_image(&info, sizeof(info)); }