10c0fea5dSIngo Weinhold /* 2aa3507feSIngo Weinhold * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. 3b6455c08SAxel Dörfler * Copyright 2003-2011, Axel Dörfler, axeld@pinc-software.de. 40c0fea5dSIngo Weinhold * Distributed under the terms of the MIT License. 50c0fea5dSIngo Weinhold * 60c0fea5dSIngo Weinhold * Copyright 2002, Manuel J. Petit. All rights reserved. 70c0fea5dSIngo Weinhold * Copyright 2001, Travis Geiselbrecht. All rights reserved. 80c0fea5dSIngo Weinhold * Distributed under the terms of the NewOS License. 90c0fea5dSIngo Weinhold */ 100c0fea5dSIngo Weinhold 110c0fea5dSIngo Weinhold #include "runtime_loader_private.h" 120c0fea5dSIngo Weinhold 13ca618b22SIngo Weinhold #include <ctype.h> 140c85bd05SIngo Weinhold #include <dlfcn.h> 150c0fea5dSIngo Weinhold #include <stdio.h> 160c0fea5dSIngo Weinhold #include <stdlib.h> 1734982809SIngo Weinhold #include <string.h> 180c0fea5dSIngo Weinhold 19ca618b22SIngo Weinhold #include <OS.h> 20ca618b22SIngo Weinhold 217486b72dSIngo Weinhold #include <syscalls.h> 2210b4b5d1SIngo Weinhold #include <util/kernel_cpp.h> 237486b72dSIngo Weinhold 24f2bb2575SIngo Weinhold #include <locks.h> 25f2bb2575SIngo Weinhold 2694830eb2SIngo Weinhold #include "add_ons.h" 2794830eb2SIngo Weinhold #include "elf_load_image.h" 2894830eb2SIngo Weinhold #include "elf_symbol_lookup.h" 2944c0c4d3SPawel Dziepak #include "elf_tls.h" 3094830eb2SIngo Weinhold #include "elf_versioning.h" 3194830eb2SIngo Weinhold #include "errors.h" 3294830eb2SIngo Weinhold #include "images.h" 330c0fea5dSIngo Weinhold 340c0fea5dSIngo Weinhold 3510b4b5d1SIngo Weinhold // TODO: implement better locking strategy 3610b4b5d1SIngo Weinhold // TODO: implement lazy binding 370c0fea5dSIngo Weinhold 380c85bd05SIngo Weinhold // a handle returned by load_library() (dlopen()) 390c85bd05SIngo Weinhold #define RLD_GLOBAL_SCOPE ((void*)-2l) 400c85bd05SIngo Weinhold 41f7127458SIngo Weinhold static const char* const kLockName = "runtime loader"; 42f7127458SIngo Weinhold 430c0fea5dSIngo Weinhold 440c0fea5dSIngo Weinhold typedef void (*init_term_function)(image_id); 45354b60afSAugustin Cavalier typedef void (*initfini_array_function)(); 460c0fea5dSIngo Weinhold 4794830eb2SIngo Weinhold bool gProgramLoaded = false; 4894830eb2SIngo Weinhold image_t* gProgramImage; 49003ebb0eSIngo Weinhold 50*35fa85dbSJérôme Duval static image_t** sPreloadedAddons = NULL; 51*35fa85dbSJérôme Duval static uint32 sPreloadedAddonCount = 0; 520c0fea5dSIngo Weinhold 53f7127458SIngo Weinhold static recursive_lock sLock = RECURSIVE_LOCK_INITIALIZER(kLockName); 540c0fea5dSIngo Weinhold 557486b72dSIngo Weinhold 560c0fea5dSIngo Weinhold static const char * 570c0fea5dSIngo Weinhold find_dt_rpath(image_t *image) 580c0fea5dSIngo Weinhold { 590c0fea5dSIngo Weinhold int i; 60e3ac2588SAlex Smith elf_dyn *d = (elf_dyn *)image->dynamic_ptr; 610c0fea5dSIngo Weinhold 620c0fea5dSIngo Weinhold for (i = 0; d[i].d_tag != DT_NULL; i++) { 630c0fea5dSIngo Weinhold if (d[i].d_tag == DT_RPATH) 640c0fea5dSIngo Weinhold return STRING(image, d[i].d_un.d_val); 650c0fea5dSIngo Weinhold } 660c0fea5dSIngo Weinhold 670c0fea5dSIngo Weinhold return NULL; 680c0fea5dSIngo Weinhold } 690c0fea5dSIngo Weinhold 700c0fea5dSIngo Weinhold 71*35fa85dbSJérôme Duval image_id 72*35fa85dbSJérôme Duval preload_image(char const* path, image_t **image) 73*35fa85dbSJérôme Duval { 74*35fa85dbSJérôme Duval if (path == NULL) 75*35fa85dbSJérôme Duval return B_BAD_VALUE; 76*35fa85dbSJérôme Duval 77*35fa85dbSJérôme Duval KTRACE("rld: preload_image(\"%s\")", path); 78*35fa85dbSJérôme Duval 79*35fa85dbSJérôme Duval status_t status = load_image(path, B_LIBRARY_IMAGE, NULL, NULL, image); 80*35fa85dbSJérôme Duval if (status < B_OK) { 81*35fa85dbSJérôme Duval KTRACE("rld: preload_image(\"%s\") failed to load container: %s", path, 82*35fa85dbSJérôme Duval strerror(status)); 83*35fa85dbSJérôme Duval return status; 84*35fa85dbSJérôme Duval } 85*35fa85dbSJérôme Duval 86*35fa85dbSJérôme Duval if ((*image)->find_undefined_symbol == NULL) 87*35fa85dbSJérôme Duval (*image)->find_undefined_symbol = find_undefined_symbol_global; 88*35fa85dbSJérôme Duval 89*35fa85dbSJérôme Duval KTRACE("rld: preload_image(\"%s\") done: id: %" B_PRId32, path, (*image)->id); 90*35fa85dbSJérôme Duval 91*35fa85dbSJérôme Duval return (*image)->id; 92*35fa85dbSJérôme Duval } 93*35fa85dbSJérôme Duval 94*35fa85dbSJérôme Duval 95*35fa85dbSJérôme Duval static void 96*35fa85dbSJérôme Duval preload_images(image_t **image, int32 *_count = NULL) 97*35fa85dbSJérôme Duval { 98*35fa85dbSJérôme Duval const char* imagePaths = getenv("LD_PRELOAD"); 99*35fa85dbSJérôme Duval if (imagePaths == NULL) { 100*35fa85dbSJérôme Duval if (_count != NULL) 101*35fa85dbSJérôme Duval *_count = 0; 102*35fa85dbSJérôme Duval return; 103*35fa85dbSJérôme Duval } 104*35fa85dbSJérôme Duval 105*35fa85dbSJérôme Duval int32 count = 0; 106*35fa85dbSJérôme Duval 107*35fa85dbSJérôme Duval while (*imagePaths != '\0') { 108*35fa85dbSJérôme Duval // find begin of image path 109*35fa85dbSJérôme Duval while (*imagePaths != '\0' && isspace(*imagePaths)) 110*35fa85dbSJérôme Duval imagePaths++; 111*35fa85dbSJérôme Duval 112*35fa85dbSJérôme Duval if (*imagePaths == '\0') 113*35fa85dbSJérôme Duval break; 114*35fa85dbSJérôme Duval 115*35fa85dbSJérôme Duval // find end of image path 116*35fa85dbSJérôme Duval const char* imagePath = imagePaths; 117*35fa85dbSJérôme Duval while (*imagePaths != '\0' && !isspace(*imagePaths)) 118*35fa85dbSJérôme Duval imagePaths++; 119*35fa85dbSJérôme Duval 120*35fa85dbSJérôme Duval // extract the path 121*35fa85dbSJérôme Duval char path[B_PATH_NAME_LENGTH]; 122*35fa85dbSJérôme Duval size_t pathLen = imagePaths - imagePath; 123*35fa85dbSJérôme Duval if (pathLen > sizeof(path) - 1) 124*35fa85dbSJérôme Duval continue; 125*35fa85dbSJérôme Duval 126*35fa85dbSJérôme Duval if (image == NULL) { 127*35fa85dbSJérôme Duval count++; 128*35fa85dbSJérôme Duval continue; 129*35fa85dbSJérôme Duval } 130*35fa85dbSJérôme Duval memcpy(path, imagePath, pathLen); 131*35fa85dbSJérôme Duval path[pathLen] = '\0'; 132*35fa85dbSJérôme Duval 133*35fa85dbSJérôme Duval // load the image 134*35fa85dbSJérôme Duval preload_image(path, &image[count++]); 135*35fa85dbSJérôme Duval } 136*35fa85dbSJérôme Duval 137*35fa85dbSJérôme Duval KTRACE("rld: preload_images count: %d", count); 138*35fa85dbSJérôme Duval 139*35fa85dbSJérôme Duval if (_count != NULL) 140*35fa85dbSJérôme Duval *_count = count; 141*35fa85dbSJérôme Duval } 142*35fa85dbSJérôme Duval 143*35fa85dbSJérôme Duval 1440c0fea5dSIngo Weinhold static status_t 145*35fa85dbSJérôme Duval load_immediate_dependencies(image_t *image, bool preload) 1460c0fea5dSIngo Weinhold { 147e3ac2588SAlex Smith elf_dyn *d = (elf_dyn *)image->dynamic_ptr; 1484bef3723SAxel Dörfler bool reportErrors = report_errors(); 14974c0424aSAxel Dörfler status_t status = B_OK; 1500c0fea5dSIngo Weinhold uint32 i, j; 1510c0fea5dSIngo Weinhold const char *rpath; 1520c0fea5dSIngo Weinhold 1530c0fea5dSIngo Weinhold if (!d || (image->flags & RFLAG_DEPENDENCIES_LOADED)) 1540c0fea5dSIngo Weinhold return B_OK; 1550c0fea5dSIngo Weinhold 1560c0fea5dSIngo Weinhold image->flags |= RFLAG_DEPENDENCIES_LOADED; 1570c0fea5dSIngo Weinhold 158*35fa85dbSJérôme Duval int32 preloadedCount = 0; 159*35fa85dbSJérôme Duval if (preload) { 160*35fa85dbSJérôme Duval preload_images(NULL, &preloadedCount); 161*35fa85dbSJérôme Duval image->num_needed += preloadedCount; 162*35fa85dbSJérôme Duval } 1630c0fea5dSIngo Weinhold if (image->num_needed == 0) 1640c0fea5dSIngo Weinhold return B_OK; 1650c0fea5dSIngo Weinhold 166ded25be1SIngo Weinhold KTRACE("rld: load_dependencies(\"%s\", id: %" B_PRId32 ")", image->name, 1677486b72dSIngo Weinhold image->id); 1687486b72dSIngo Weinhold 1690c0fea5dSIngo Weinhold image->needed = (image_t**)malloc(image->num_needed * sizeof(image_t *)); 1700c0fea5dSIngo Weinhold if (image->needed == NULL) { 171c533f813SIngo Weinhold FATAL("%s: Failed to allocate needed struct\n", image->path); 172ded25be1SIngo Weinhold KTRACE("rld: load_dependencies(\"%s\", id: %" B_PRId32 173ded25be1SIngo Weinhold ") failed: no memory", image->name, image->id); 1740c0fea5dSIngo Weinhold return B_NO_MEMORY; 1750c0fea5dSIngo Weinhold } 1760c0fea5dSIngo Weinhold 1770c0fea5dSIngo Weinhold memset(image->needed, 0, image->num_needed * sizeof(image_t *)); 178*35fa85dbSJérôme Duval if (preload) 179*35fa85dbSJérôme Duval preload_images(image->needed); 1800c0fea5dSIngo Weinhold rpath = find_dt_rpath(image); 1810c0fea5dSIngo Weinhold 182*35fa85dbSJérôme Duval for (i = 0, j = preloadedCount; d[i].d_tag != DT_NULL; i++) { 1830c0fea5dSIngo Weinhold switch (d[i].d_tag) { 1840c0fea5dSIngo Weinhold case DT_NEEDED: 18574c0424aSAxel Dörfler { 18674c0424aSAxel Dörfler int32 neededOffset = d[i].d_un.d_val; 18774c0424aSAxel Dörfler const char *name = STRING(image, neededOffset); 1880c0fea5dSIngo Weinhold 18994830eb2SIngo Weinhold status_t loadStatus = load_image(name, B_LIBRARY_IMAGE, 1908d23c440SIngo Weinhold rpath, image->path, &image->needed[j]); 19174c0424aSAxel Dörfler if (loadStatus < B_OK) { 19274c0424aSAxel Dörfler status = loadStatus; 19374c0424aSAxel Dörfler // correct error code in case the file could not been found 19474c0424aSAxel Dörfler if (status == B_ENTRY_NOT_FOUND) { 19574c0424aSAxel Dörfler status = B_MISSING_LIBRARY; 19674c0424aSAxel Dörfler 19774c0424aSAxel Dörfler if (reportErrors) 19894830eb2SIngo Weinhold gErrorMessage.AddString("missing library", name); 19974c0424aSAxel Dörfler } 20074c0424aSAxel Dörfler 20174c0424aSAxel Dörfler // Collect all missing libraries in case we report back 2027486b72dSIngo Weinhold if (!reportErrors) { 203ded25be1SIngo Weinhold KTRACE("rld: load_dependencies(\"%s\", id: %" B_PRId32 204ded25be1SIngo Weinhold ") failed: %s", image->name, image->id, 2057486b72dSIngo Weinhold strerror(status)); 2060c0fea5dSIngo Weinhold return status; 20774c0424aSAxel Dörfler } 2087486b72dSIngo Weinhold } 2090c0fea5dSIngo Weinhold 2100c0fea5dSIngo Weinhold j += 1; 2110c0fea5dSIngo Weinhold break; 21274c0424aSAxel Dörfler } 2130c0fea5dSIngo Weinhold 2140c0fea5dSIngo Weinhold default: 2150c0fea5dSIngo Weinhold // ignore any other tag 2160c0fea5dSIngo Weinhold continue; 2170c0fea5dSIngo Weinhold } 2180c0fea5dSIngo Weinhold } 2190c0fea5dSIngo Weinhold 2207486b72dSIngo Weinhold if (status < B_OK) { 221ded25be1SIngo Weinhold KTRACE("rld: load_dependencies(\"%s\", id: %" B_PRId32 ") " 2227486b72dSIngo Weinhold "failed: %s", image->name, image->id, 2237486b72dSIngo Weinhold strerror(status)); 22474c0424aSAxel Dörfler return status; 2257486b72dSIngo Weinhold } 22674c0424aSAxel Dörfler 2270c0fea5dSIngo Weinhold if (j != image->num_needed) { 2280c0fea5dSIngo Weinhold FATAL("Internal error at load_dependencies()"); 229ded25be1SIngo Weinhold KTRACE("rld: load_dependencies(\"%s\", id: %" B_PRId32 ") " 2307486b72dSIngo Weinhold "failed: internal error", image->name, image->id); 2310c0fea5dSIngo Weinhold return B_ERROR; 2320c0fea5dSIngo Weinhold } 2330c0fea5dSIngo Weinhold 234ded25be1SIngo Weinhold KTRACE("rld: load_dependencies(\"%s\", id: %" B_PRId32 ") done", 235ded25be1SIngo Weinhold image->name, image->id); 2367486b72dSIngo Weinhold 2370c0fea5dSIngo Weinhold return B_OK; 2380c0fea5dSIngo Weinhold } 2390c0fea5dSIngo Weinhold 2400c0fea5dSIngo Weinhold 2410c85bd05SIngo Weinhold static status_t 242*35fa85dbSJérôme Duval load_dependencies(image_t* image, bool preload = false) 2430c85bd05SIngo Weinhold { 244003ebb0eSIngo Weinhold // load dependencies (breadth-first) 2450c85bd05SIngo Weinhold for (image_t* otherImage = image; otherImage != NULL; 2460c85bd05SIngo Weinhold otherImage = otherImage->next) { 247*35fa85dbSJérôme Duval status_t status = load_immediate_dependencies(otherImage, preload); 2480c85bd05SIngo Weinhold if (status != B_OK) 2490c85bd05SIngo Weinhold return status; 250*35fa85dbSJérôme Duval preload = false; 2510c85bd05SIngo Weinhold } 2520c85bd05SIngo Weinhold 253003ebb0eSIngo Weinhold // Check the needed versions for the given image and all newly loaded 254003ebb0eSIngo Weinhold // dependencies. 255003ebb0eSIngo Weinhold for (image_t* otherImage = image; otherImage != NULL; 256003ebb0eSIngo Weinhold otherImage = otherImage->next) { 257003ebb0eSIngo Weinhold status_t status = check_needed_image_versions(otherImage); 258003ebb0eSIngo Weinhold if (status != B_OK) 259003ebb0eSIngo Weinhold return status; 260003ebb0eSIngo Weinhold } 261003ebb0eSIngo Weinhold 2620c85bd05SIngo Weinhold return B_OK; 2630c85bd05SIngo Weinhold } 2640c85bd05SIngo Weinhold 2650c85bd05SIngo Weinhold 26694830eb2SIngo Weinhold static status_t 26794830eb2SIngo Weinhold relocate_image(image_t *rootImage, image_t *image) 2680c0fea5dSIngo Weinhold { 26925dc253dSIngo Weinhold SymbolLookupCache cache(image); 27025dc253dSIngo Weinhold 27125dc253dSIngo Weinhold status_t status = arch_relocate_image(rootImage, image, &cache); 27294830eb2SIngo Weinhold if (status < B_OK) { 273c533f813SIngo Weinhold FATAL("%s: Troubles relocating: %s\n", image->path, strerror(status)); 27494830eb2SIngo Weinhold return status; 2750c0fea5dSIngo Weinhold } 2760c0fea5dSIngo Weinhold 27794830eb2SIngo Weinhold _kern_image_relocated(image->id); 27894830eb2SIngo Weinhold image_event(image, IMAGE_EVENT_RELOCATED); 27994830eb2SIngo Weinhold return B_OK; 2800c0fea5dSIngo Weinhold } 2810c0fea5dSIngo Weinhold 2820c0fea5dSIngo Weinhold 2830c0fea5dSIngo Weinhold static status_t 2840c0fea5dSIngo Weinhold relocate_dependencies(image_t *image) 2850c0fea5dSIngo Weinhold { 286ca618b22SIngo Weinhold // get the images that still have to be relocated 287ca618b22SIngo Weinhold image_t **list; 288ca618b22SIngo Weinhold ssize_t count = get_sorted_image_list(image, &list, RFLAG_RELOCATED); 2890c0fea5dSIngo Weinhold if (count < B_OK) 2900c0fea5dSIngo Weinhold return count; 2910c0fea5dSIngo Weinhold 2920c85bd05SIngo Weinhold // relocate 293ca618b22SIngo Weinhold for (ssize_t i = 0; i < count; i++) { 29446f4d849SIngo Weinhold status_t status = relocate_image(image, list[i]); 2950c85bd05SIngo Weinhold if (status < B_OK) { 2960c85bd05SIngo Weinhold free(list); 2970c0fea5dSIngo Weinhold return status; 2980c0fea5dSIngo Weinhold } 2990c85bd05SIngo Weinhold } 3000c0fea5dSIngo Weinhold 3010c0fea5dSIngo Weinhold free(list); 3020c0fea5dSIngo Weinhold return B_OK; 3030c0fea5dSIngo Weinhold } 3040c0fea5dSIngo Weinhold 3050c0fea5dSIngo Weinhold 3060c0fea5dSIngo Weinhold static void 3070c0fea5dSIngo Weinhold init_dependencies(image_t *image, bool initHead) 3080c0fea5dSIngo Weinhold { 3090c0fea5dSIngo Weinhold image_t **initList; 3100c0fea5dSIngo Weinhold ssize_t count, i; 3110c0fea5dSIngo Weinhold 3123a75ef9aSJérôme Duval if (initHead && image->preinit_array) { 3133a75ef9aSJérôme Duval uint count_preinit = image->preinit_array_len / sizeof(addr_t); 3143a75ef9aSJérôme Duval for (uint j = 0; j < count_preinit; j++) 3153a75ef9aSJérôme Duval ((initfini_array_function)image->preinit_array[j])(); 3163a75ef9aSJérôme Duval } 3173a75ef9aSJérôme Duval 3180c0fea5dSIngo Weinhold count = get_sorted_image_list(image, &initList, RFLAG_INITIALIZED); 3190c0fea5dSIngo Weinhold if (count <= 0) 3200c0fea5dSIngo Weinhold return; 3210c0fea5dSIngo Weinhold 3220c0fea5dSIngo Weinhold if (!initHead) { 3230c0fea5dSIngo Weinhold // this removes the "calling" image 3240c0fea5dSIngo Weinhold image->flags &= ~RFLAG_INITIALIZED; 3250c0fea5dSIngo Weinhold initList[--count] = NULL; 3260c0fea5dSIngo Weinhold } 3270c0fea5dSIngo Weinhold 3280c0fea5dSIngo Weinhold TRACE(("%ld: init dependencies\n", find_thread(NULL))); 3290c0fea5dSIngo Weinhold for (i = 0; i < count; i++) { 3300c0fea5dSIngo Weinhold image = initList[i]; 3310c0fea5dSIngo Weinhold 3320c0fea5dSIngo Weinhold TRACE(("%ld: init: %s\n", find_thread(NULL), image->name)); 3330c0fea5dSIngo Weinhold 334354b60afSAugustin Cavalier init_term_function before; 335354b60afSAugustin Cavalier if (find_symbol(image, 336354b60afSAugustin Cavalier SymbolLookupInfo(B_INIT_BEFORE_FUNCTION_NAME, B_SYMBOL_TYPE_TEXT), 337354b60afSAugustin Cavalier (void**)&before) == B_OK) { 338354b60afSAugustin Cavalier before(image->id); 339e340f717SJérôme Duval } 340e340f717SJérôme Duval 341dd76bc97SIngo Weinhold if (image->init_routine != 0) 3420c0fea5dSIngo Weinhold ((init_term_function)image->init_routine)(image->id); 34310b4b5d1SIngo Weinhold 344e340f717SJérôme Duval if (image->init_array) { 345e340f717SJérôme Duval uint count_init = image->init_array_len / sizeof(addr_t); 346e340f717SJérôme Duval for (uint j = 0; j < count_init; j++) 347354b60afSAugustin Cavalier ((initfini_array_function)image->init_array[j])(); 348354b60afSAugustin Cavalier } 349354b60afSAugustin Cavalier 350354b60afSAugustin Cavalier init_term_function after; 351354b60afSAugustin Cavalier if (find_symbol(image, 352354b60afSAugustin Cavalier SymbolLookupInfo(B_INIT_AFTER_FUNCTION_NAME, B_SYMBOL_TYPE_TEXT), 353354b60afSAugustin Cavalier (void**)&after) == B_OK) { 354354b60afSAugustin Cavalier after(image->id); 355e340f717SJérôme Duval } 356e340f717SJérôme Duval 35710b4b5d1SIngo Weinhold image_event(image, IMAGE_EVENT_INITIALIZED); 3580c0fea5dSIngo Weinhold } 3590c0fea5dSIngo Weinhold TRACE(("%ld: init done.\n", find_thread(NULL))); 3600c0fea5dSIngo Weinhold 3610c0fea5dSIngo Weinhold free(initList); 3620c0fea5dSIngo Weinhold } 3630c0fea5dSIngo Weinhold 3640c0fea5dSIngo Weinhold 3650c0fea5dSIngo Weinhold static void 366ca618b22SIngo Weinhold inject_runtime_loader_api(image_t* rootImage) 367ca618b22SIngo Weinhold { 368ca618b22SIngo Weinhold // We patch any exported __gRuntimeLoader symbols to point to our private 369ca618b22SIngo Weinhold // API. 370ca618b22SIngo Weinhold image_t* image; 3710c85bd05SIngo Weinhold void* _export; 372003ebb0eSIngo Weinhold if (find_symbol_breadth_first(rootImage, 373003ebb0eSIngo Weinhold SymbolLookupInfo("__gRuntimeLoader", B_SYMBOL_TYPE_DATA), &image, 374003ebb0eSIngo Weinhold &_export) == B_OK) { 3750c85bd05SIngo Weinhold *(void**)_export = &gRuntimeLoader; 376ca618b22SIngo Weinhold } 377ca618b22SIngo Weinhold } 378ca618b22SIngo Weinhold 379ca618b22SIngo Weinhold 380ca618b22SIngo Weinhold static status_t 381*35fa85dbSJérôme Duval add_preloaded_addon(image_t* image) 382ca618b22SIngo Weinhold { 383ca618b22SIngo Weinhold // We realloc() everytime -- not particularly efficient, but good enough for 384*35fa85dbSJérôme Duval // small number of preloaded addons. 385*35fa85dbSJérôme Duval image_t** newArray = (image_t**)realloc(sPreloadedAddons, 386*35fa85dbSJérôme Duval sizeof(image_t*) * (sPreloadedAddonCount + 1)); 387ca618b22SIngo Weinhold if (newArray == NULL) 388ca618b22SIngo Weinhold return B_NO_MEMORY; 389ca618b22SIngo Weinhold 390*35fa85dbSJérôme Duval sPreloadedAddons = newArray; 391*35fa85dbSJérôme Duval newArray[sPreloadedAddonCount++] = image; 392ca618b22SIngo Weinhold 393ca618b22SIngo Weinhold return B_OK; 394ca618b22SIngo Weinhold } 395ca618b22SIngo Weinhold 396ca618b22SIngo Weinhold 397ca618b22SIngo Weinhold image_id 398*35fa85dbSJérôme Duval preload_addon(char const* path) 399ca618b22SIngo Weinhold { 400ca618b22SIngo Weinhold if (path == NULL) 401ca618b22SIngo Weinhold return B_BAD_VALUE; 402ca618b22SIngo Weinhold 403*35fa85dbSJérôme Duval KTRACE("rld: preload_addon(\"%s\")", path); 404ca618b22SIngo Weinhold 405ca618b22SIngo Weinhold image_t *image = NULL; 4068d23c440SIngo Weinhold status_t status = load_image(path, B_LIBRARY_IMAGE, NULL, NULL, &image); 407ca618b22SIngo Weinhold if (status < B_OK) { 408*35fa85dbSJérôme Duval KTRACE("rld: preload_addon(\"%s\") failed to load container: %s", path, 409ca618b22SIngo Weinhold strerror(status)); 410ca618b22SIngo Weinhold return status; 411ca618b22SIngo Weinhold } 412ca618b22SIngo Weinhold 4130c85bd05SIngo Weinhold if (image->find_undefined_symbol == NULL) 4140c85bd05SIngo Weinhold image->find_undefined_symbol = find_undefined_symbol_global; 4150c85bd05SIngo Weinhold 4160c85bd05SIngo Weinhold status = load_dependencies(image); 417ca618b22SIngo Weinhold if (status < B_OK) 418ca618b22SIngo Weinhold goto err; 4190c85bd05SIngo Weinhold 4200c85bd05SIngo Weinhold set_image_flags_recursively(image, RTLD_GLOBAL); 421ca618b22SIngo Weinhold 422ca618b22SIngo Weinhold status = relocate_dependencies(image); 423ca618b22SIngo Weinhold if (status < B_OK) 424ca618b22SIngo Weinhold goto err; 425ca618b22SIngo Weinhold 426*35fa85dbSJérôme Duval status = add_preloaded_addon(image); 427ca618b22SIngo Weinhold if (status < B_OK) 428ca618b22SIngo Weinhold goto err; 429ca618b22SIngo Weinhold 430ca618b22SIngo Weinhold inject_runtime_loader_api(image); 431ca618b22SIngo Weinhold 432ca618b22SIngo Weinhold remap_images(); 433ca618b22SIngo Weinhold init_dependencies(image, true); 434ca618b22SIngo Weinhold 43510b4b5d1SIngo Weinhold // if the image contains an add-on, register it 43610b4b5d1SIngo Weinhold runtime_loader_add_on* addOnStruct; 437003ebb0eSIngo Weinhold if (find_symbol(image, 438003ebb0eSIngo Weinhold SymbolLookupInfo("__gRuntimeLoaderAddOn", B_SYMBOL_TYPE_DATA), 43910b4b5d1SIngo Weinhold (void**)&addOnStruct) == B_OK) { 44094830eb2SIngo Weinhold add_add_on(image, addOnStruct); 44110b4b5d1SIngo Weinhold } 44210b4b5d1SIngo Weinhold 443*35fa85dbSJérôme Duval KTRACE("rld: preload_addon(\"%s\") done: id: %" B_PRId32, path, image->id); 444ca618b22SIngo Weinhold 445ca618b22SIngo Weinhold return image->id; 446ca618b22SIngo Weinhold 447ca618b22SIngo Weinhold err: 448*35fa85dbSJérôme Duval KTRACE("rld: preload_addon(\"%s\") failed: %s", path, strerror(status)); 449ca618b22SIngo Weinhold 45094830eb2SIngo Weinhold dequeue_loaded_image(image); 451ca618b22SIngo Weinhold delete_image(image); 452ca618b22SIngo Weinhold return status; 453ca618b22SIngo Weinhold } 454ca618b22SIngo Weinhold 455ca618b22SIngo Weinhold 456ca618b22SIngo Weinhold static void 457*35fa85dbSJérôme Duval preload_addons() 458ca618b22SIngo Weinhold { 459*35fa85dbSJérôme Duval const char* imagePaths = getenv("LD_PRELOAD_ADDONS"); 460ca618b22SIngo Weinhold if (imagePaths == NULL) 461ca618b22SIngo Weinhold return; 462ca618b22SIngo Weinhold 463ca618b22SIngo Weinhold while (*imagePaths != '\0') { 464ca618b22SIngo Weinhold // find begin of image path 465ca618b22SIngo Weinhold while (*imagePaths != '\0' && isspace(*imagePaths)) 466ca618b22SIngo Weinhold imagePaths++; 467ca618b22SIngo Weinhold 468ca618b22SIngo Weinhold if (*imagePaths == '\0') 469ca618b22SIngo Weinhold break; 470ca618b22SIngo Weinhold 471ca618b22SIngo Weinhold // find end of image path 472ca618b22SIngo Weinhold const char* imagePath = imagePaths; 473ca618b22SIngo Weinhold while (*imagePaths != '\0' && !isspace(*imagePaths)) 474ca618b22SIngo Weinhold imagePaths++; 475ca618b22SIngo Weinhold 476ca618b22SIngo Weinhold // extract the path 477ca618b22SIngo Weinhold char path[B_PATH_NAME_LENGTH]; 478ca618b22SIngo Weinhold size_t pathLen = imagePaths - imagePath; 479ca618b22SIngo Weinhold if (pathLen > sizeof(path) - 1) 480ca618b22SIngo Weinhold continue; 481ca618b22SIngo Weinhold memcpy(path, imagePath, pathLen); 482ca618b22SIngo Weinhold path[pathLen] = '\0'; 483ca618b22SIngo Weinhold 484ca618b22SIngo Weinhold // load the image 485*35fa85dbSJérôme Duval preload_addon(path); 486ca618b22SIngo Weinhold } 487ca618b22SIngo Weinhold } 488ca618b22SIngo Weinhold 489ca618b22SIngo Weinhold 49074c0424aSAxel Dörfler // #pragma mark - libroot.so exported functions 4910c0fea5dSIngo Weinhold 4920c0fea5dSIngo Weinhold 4930c0fea5dSIngo Weinhold image_id 4940c0fea5dSIngo Weinhold load_program(char const *path, void **_entry) 4950c0fea5dSIngo Weinhold { 4960c0fea5dSIngo Weinhold status_t status; 4970c0fea5dSIngo Weinhold image_t *image; 4980c0fea5dSIngo Weinhold 4997486b72dSIngo Weinhold KTRACE("rld: load_program(\"%s\")", path); 5007486b72dSIngo Weinhold 501f167d21aSAugustin Cavalier RecursiveLocker _(sLock); 5020c0fea5dSIngo Weinhold // for now, just do stupid simple global locking 5030c0fea5dSIngo Weinhold 504*35fa85dbSJérôme Duval preload_addons(); 505ca618b22SIngo Weinhold 5060c0fea5dSIngo Weinhold TRACE(("rld: load %s\n", path)); 5070c0fea5dSIngo Weinhold 5088d23c440SIngo Weinhold status = load_image(path, B_APP_IMAGE, NULL, NULL, &gProgramImage); 50974c0424aSAxel Dörfler if (status < B_OK) 51074c0424aSAxel Dörfler goto err; 5110c0fea5dSIngo Weinhold 51294830eb2SIngo Weinhold if (gProgramImage->find_undefined_symbol == NULL) 51394830eb2SIngo Weinhold gProgramImage->find_undefined_symbol = find_undefined_symbol_global; 5140c85bd05SIngo Weinhold 515*35fa85dbSJérôme Duval status = load_dependencies(gProgramImage, true); 5160c0fea5dSIngo Weinhold if (status < B_OK) 5170c0fea5dSIngo Weinhold goto err; 5180c85bd05SIngo Weinhold 51947bc6663SIngo Weinhold // Set RTLD_GLOBAL on all libraries including the program. 5200c85bd05SIngo Weinhold // This results in the desired symbol resolution for dlopen()ed libraries. 52194830eb2SIngo Weinhold set_image_flags_recursively(gProgramImage, RTLD_GLOBAL); 5220c0fea5dSIngo Weinhold 52394830eb2SIngo Weinhold status = relocate_dependencies(gProgramImage); 5240c0fea5dSIngo Weinhold if (status < B_OK) 5250c0fea5dSIngo Weinhold goto err; 5260c0fea5dSIngo Weinhold 52794830eb2SIngo Weinhold inject_runtime_loader_api(gProgramImage); 5280c0fea5dSIngo Weinhold 5290c0fea5dSIngo Weinhold remap_images(); 53094830eb2SIngo Weinhold init_dependencies(gProgramImage, true); 5310c0fea5dSIngo Weinhold 5320c0fea5dSIngo Weinhold // Since the images are initialized now, we no longer should use our 5330c0fea5dSIngo Weinhold // getenv(), but use the one from libroot.so 53494830eb2SIngo Weinhold find_symbol_breadth_first(gProgramImage, 535003ebb0eSIngo Weinhold SymbolLookupInfo("getenv", B_SYMBOL_TYPE_TEXT), &image, 536003ebb0eSIngo Weinhold (void**)&gGetEnv); 5370c0fea5dSIngo Weinhold 53894830eb2SIngo Weinhold if (gProgramImage->entry_point == 0) { 5390c0fea5dSIngo Weinhold status = B_NOT_AN_EXECUTABLE; 5400c0fea5dSIngo Weinhold goto err; 5410c0fea5dSIngo Weinhold } 5420c0fea5dSIngo Weinhold 54394830eb2SIngo Weinhold *_entry = (void *)(gProgramImage->entry_point); 5440c0fea5dSIngo Weinhold 54594830eb2SIngo Weinhold gProgramLoaded = true; 5465d0638bfSIngo Weinhold 547ded25be1SIngo Weinhold KTRACE("rld: load_program(\"%s\") done: entry: %p, id: %" B_PRId32 , path, 54894830eb2SIngo Weinhold *_entry, gProgramImage->id); 5497486b72dSIngo Weinhold 55094830eb2SIngo Weinhold return gProgramImage->id; 5510c0fea5dSIngo Weinhold 5520c0fea5dSIngo Weinhold err: 5537486b72dSIngo Weinhold KTRACE("rld: load_program(\"%s\") failed: %s", path, strerror(status)); 5547486b72dSIngo Weinhold 55594830eb2SIngo Weinhold delete_image(gProgramImage); 55674c0424aSAxel Dörfler 5574bef3723SAxel Dörfler if (report_errors()) { 5584bef3723SAxel Dörfler // send error message 55994830eb2SIngo Weinhold gErrorMessage.AddInt32("error", status); 56094830eb2SIngo Weinhold gErrorMessage.SetDeliveryInfo(gProgramArgs->error_token, 5614bef3723SAxel Dörfler -1, 0, find_thread(NULL)); 5624bef3723SAxel Dörfler 5634bef3723SAxel Dörfler _kern_write_port_etc(gProgramArgs->error_port, 'KMSG', 56494830eb2SIngo Weinhold gErrorMessage.Buffer(), gErrorMessage.ContentSize(), 0, 0); 56574c0424aSAxel Dörfler } 56674c0424aSAxel Dörfler _kern_loading_app_failed(status); 56774c0424aSAxel Dörfler 5680c0fea5dSIngo Weinhold return status; 5690c0fea5dSIngo Weinhold } 5700c0fea5dSIngo Weinhold 5710c0fea5dSIngo Weinhold 5720c0fea5dSIngo Weinhold image_id 5730c85bd05SIngo Weinhold load_library(char const *path, uint32 flags, bool addOn, void** _handle) 5740c0fea5dSIngo Weinhold { 5750c0fea5dSIngo Weinhold image_t *image = NULL; 5760c0fea5dSIngo Weinhold image_type type = (addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE); 5770c0fea5dSIngo Weinhold status_t status; 5780c0fea5dSIngo Weinhold 5790c85bd05SIngo Weinhold if (path == NULL && addOn) 5800c0fea5dSIngo Weinhold return B_BAD_VALUE; 5810c0fea5dSIngo Weinhold 582ded25be1SIngo Weinhold KTRACE("rld: load_library(\"%s\", %#" B_PRIx32 ", %d)", path, flags, addOn); 5837486b72dSIngo Weinhold 584f167d21aSAugustin Cavalier RecursiveLocker _(sLock); 5850c0fea5dSIngo Weinhold // for now, just do stupid simple global locking 5860c0fea5dSIngo Weinhold 5870c0fea5dSIngo Weinhold // have we already loaded this library? 5880c0fea5dSIngo Weinhold // Checking it at this stage saves loading its dependencies again 5890c0fea5dSIngo Weinhold if (!addOn) { 5900c85bd05SIngo Weinhold // a NULL path is fine -- it means the global scope shall be opened 5910c85bd05SIngo Weinhold if (path == NULL) { 5920c85bd05SIngo Weinhold *_handle = RLD_GLOBAL_SCOPE; 5930c85bd05SIngo Weinhold return 0; 5940c85bd05SIngo Weinhold } 5950c85bd05SIngo Weinhold 59694830eb2SIngo Weinhold image = find_loaded_image_by_name(path, APP_OR_LIBRARY_TYPE); 5970c85bd05SIngo Weinhold if (image != NULL && (flags & RTLD_GLOBAL) != 0) 5980c85bd05SIngo Weinhold set_image_flags_recursively(image, RTLD_GLOBAL); 5990c85bd05SIngo Weinhold 6000c0fea5dSIngo Weinhold if (image) { 6010c0fea5dSIngo Weinhold atomic_add(&image->ref_count, 1); 602ded25be1SIngo Weinhold KTRACE("rld: load_library(\"%s\"): already loaded: %" B_PRId32, 603ded25be1SIngo Weinhold path, image->id); 6040c85bd05SIngo Weinhold *_handle = image; 6050c0fea5dSIngo Weinhold return image->id; 6060c0fea5dSIngo Weinhold } 6070c0fea5dSIngo Weinhold } 6080c0fea5dSIngo Weinhold 6098d23c440SIngo Weinhold status = load_image(path, type, NULL, NULL, &image); 6100c0fea5dSIngo Weinhold if (status < B_OK) { 6117486b72dSIngo Weinhold KTRACE("rld: load_library(\"%s\") failed to load container: %s", path, 6127486b72dSIngo Weinhold strerror(status)); 6130c0fea5dSIngo Weinhold return status; 6140c0fea5dSIngo Weinhold } 6150c0fea5dSIngo Weinhold 6160c85bd05SIngo Weinhold if (image->find_undefined_symbol == NULL) { 6170c85bd05SIngo Weinhold if (addOn) 6180c85bd05SIngo Weinhold image->find_undefined_symbol = find_undefined_symbol_add_on; 6190c85bd05SIngo Weinhold else 6200c85bd05SIngo Weinhold image->find_undefined_symbol = find_undefined_symbol_global; 6210c85bd05SIngo Weinhold } 6220c85bd05SIngo Weinhold 6230c85bd05SIngo Weinhold status = load_dependencies(image); 6240c0fea5dSIngo Weinhold if (status < B_OK) 6250c0fea5dSIngo Weinhold goto err; 6260c85bd05SIngo Weinhold 6270c85bd05SIngo Weinhold // If specified, set the RTLD_GLOBAL flag recursively on this image and all 6280c85bd05SIngo Weinhold // dependencies. If not specified, we temporarily set 6290c85bd05SIngo Weinhold // RFLAG_USE_FOR_RESOLVING so that the dependencies will correctly be used 6300c85bd05SIngo Weinhold // for undefined symbol resolution. 6310c85bd05SIngo Weinhold if ((flags & RTLD_GLOBAL) != 0) 6320c85bd05SIngo Weinhold set_image_flags_recursively(image, RTLD_GLOBAL); 6330c85bd05SIngo Weinhold else 6340c85bd05SIngo Weinhold set_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING); 6350c0fea5dSIngo Weinhold 6360c0fea5dSIngo Weinhold status = relocate_dependencies(image); 6370c0fea5dSIngo Weinhold if (status < B_OK) 6380c0fea5dSIngo Weinhold goto err; 6390c0fea5dSIngo Weinhold 6400c85bd05SIngo Weinhold if ((flags & RTLD_GLOBAL) == 0) 6410c85bd05SIngo Weinhold clear_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING); 6420c85bd05SIngo Weinhold 6430c0fea5dSIngo Weinhold remap_images(); 6440c0fea5dSIngo Weinhold init_dependencies(image, true); 6450c0fea5dSIngo Weinhold 646ded25be1SIngo Weinhold KTRACE("rld: load_library(\"%s\") done: id: %" B_PRId32, path, image->id); 6477486b72dSIngo Weinhold 6480c85bd05SIngo Weinhold *_handle = image; 6490c0fea5dSIngo Weinhold return image->id; 6500c0fea5dSIngo Weinhold 6510c0fea5dSIngo Weinhold err: 6527486b72dSIngo Weinhold KTRACE("rld: load_library(\"%s\") failed: %s", path, strerror(status)); 6537486b72dSIngo Weinhold 65494830eb2SIngo Weinhold dequeue_loaded_image(image); 6550c0fea5dSIngo Weinhold delete_image(image); 6560c0fea5dSIngo Weinhold return status; 6570c0fea5dSIngo Weinhold } 6580c0fea5dSIngo Weinhold 6590c0fea5dSIngo Weinhold 6600c0fea5dSIngo Weinhold status_t 6610c85bd05SIngo Weinhold unload_library(void* handle, image_id imageID, bool addOn) 6620c0fea5dSIngo Weinhold { 6630c0fea5dSIngo Weinhold image_t *image; 6640c0fea5dSIngo Weinhold image_type type = addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE; 6650c0fea5dSIngo Weinhold 6660c85bd05SIngo Weinhold if (handle == NULL && imageID < 0) 6670c0fea5dSIngo Weinhold return B_BAD_IMAGE_ID; 6680c0fea5dSIngo Weinhold 6690c85bd05SIngo Weinhold if (handle == RLD_GLOBAL_SCOPE) 6700c85bd05SIngo Weinhold return B_OK; 6710c85bd05SIngo Weinhold 672f167d21aSAugustin Cavalier RecursiveLocker _(sLock); 6730c0fea5dSIngo Weinhold // for now, just do stupid simple global locking 6740c0fea5dSIngo Weinhold 67594830eb2SIngo Weinhold if (gInvalidImageIDs) { 6769a6072a3SAxel Dörfler // After fork, we lazily rebuild the image IDs of all loaded images 6779a6072a3SAxel Dörfler update_image_ids(); 6789a6072a3SAxel Dörfler } 6799a6072a3SAxel Dörfler 6800c0fea5dSIngo Weinhold // we only check images that have been already initialized 6810c0fea5dSIngo Weinhold 682df30098dSIngo Weinhold status_t status = B_BAD_IMAGE_ID; 683df30098dSIngo Weinhold 6840c85bd05SIngo Weinhold if (handle != NULL) { 6850c85bd05SIngo Weinhold image = (image_t*)handle; 6860c85bd05SIngo Weinhold put_image(image); 687df30098dSIngo Weinhold status = B_OK; 6880c85bd05SIngo Weinhold } else { 68994830eb2SIngo Weinhold image = find_loaded_image_by_id(imageID, true); 69094830eb2SIngo Weinhold if (image != NULL) { 6910c0fea5dSIngo Weinhold // unload image 6920c0fea5dSIngo Weinhold if (type == image->type) { 6930c0fea5dSIngo Weinhold put_image(image); 6940c0fea5dSIngo Weinhold status = B_OK; 6950c0fea5dSIngo Weinhold } else 6960c0fea5dSIngo Weinhold status = B_BAD_VALUE; 6970c0fea5dSIngo Weinhold } 6980c85bd05SIngo Weinhold } 6990c0fea5dSIngo Weinhold 7000c0fea5dSIngo Weinhold if (status == B_OK) { 70194830eb2SIngo Weinhold while ((image = get_disposable_images().head) != NULL) { 702d64f6189SIngo Weinhold // Call the exit hooks that live in this image. 703d64f6189SIngo Weinhold // Note: With the Itanium ABI this shouldn't really be done this 704d64f6189SIngo Weinhold // way anymore, since global destructors are registered via 705d64f6189SIngo Weinhold // __cxa_atexit() (the ones that are registered dynamically) and the 706d64f6189SIngo Weinhold // termination routine should call __cxa_finalize() for the image. 707d64f6189SIngo Weinhold // The reason why we still do it is that hooks registered with 708d64f6189SIngo Weinhold // atexit() aren't associated with the image. We could find out 709d64f6189SIngo Weinhold // there which image the hooks lives in and register it 710d64f6189SIngo Weinhold // respectively, but since that would be done always, that's 711d64f6189SIngo Weinhold // probably more expensive than calling 712d64f6189SIngo Weinhold // call_atexit_hooks_for_range() only here, which happens only when 713d64f6189SIngo Weinhold // libraries are unloaded dynamically. 7148c2a9d74SMichael Lotz if (gRuntimeLoader.call_atexit_hooks_for_range) { 7158c2a9d74SMichael Lotz gRuntimeLoader.call_atexit_hooks_for_range( 7163be509a2SMichael Lotz image->regions[0].vmstart, image->regions[0].vmsize); 7178c2a9d74SMichael Lotz } 7188c2a9d74SMichael Lotz 71910b4b5d1SIngo Weinhold image_event(image, IMAGE_EVENT_UNINITIALIZING); 72010b4b5d1SIngo Weinhold 721354b60afSAugustin Cavalier init_term_function before; 722354b60afSAugustin Cavalier if (find_symbol(image, 723354b60afSAugustin Cavalier SymbolLookupInfo(B_TERM_BEFORE_FUNCTION_NAME, B_SYMBOL_TYPE_TEXT), 724354b60afSAugustin Cavalier (void**)&before) == B_OK) { 725354b60afSAugustin Cavalier before(image->id); 726354b60afSAugustin Cavalier } 727354b60afSAugustin Cavalier 728e340f717SJérôme Duval if (image->term_array) { 729e340f717SJérôme Duval uint count_term = image->term_array_len / sizeof(addr_t); 730e340f717SJérôme Duval for (uint i = count_term; i-- > 0;) 731354b60afSAugustin Cavalier ((initfini_array_function)image->term_array[i])(); 732e340f717SJérôme Duval } 733e340f717SJérôme Duval 7340c0fea5dSIngo Weinhold if (image->term_routine) 7350c0fea5dSIngo Weinhold ((init_term_function)image->term_routine)(image->id); 7360c0fea5dSIngo Weinhold 737354b60afSAugustin Cavalier init_term_function after; 738354b60afSAugustin Cavalier if (find_symbol(image, 739354b60afSAugustin Cavalier SymbolLookupInfo(B_TERM_AFTER_FUNCTION_NAME, B_SYMBOL_TYPE_TEXT), 740354b60afSAugustin Cavalier (void**)&after) == B_OK) { 741354b60afSAugustin Cavalier after(image->id); 742354b60afSAugustin Cavalier } 743354b60afSAugustin Cavalier 74444c0c4d3SPawel Dziepak TLSBlockTemplates::Get().Unregister(image->dso_tls_id); 74544c0c4d3SPawel Dziepak 74694830eb2SIngo Weinhold dequeue_disposable_image(image); 7470c0fea5dSIngo Weinhold unmap_image(image); 7480c0fea5dSIngo Weinhold 74910b4b5d1SIngo Weinhold image_event(image, IMAGE_EVENT_UNLOADING); 75010b4b5d1SIngo Weinhold 7510c0fea5dSIngo Weinhold delete_image(image); 7520c0fea5dSIngo Weinhold } 7530c0fea5dSIngo Weinhold } 7540c0fea5dSIngo Weinhold 7550c0fea5dSIngo Weinhold return status; 7560c0fea5dSIngo Weinhold } 7570c0fea5dSIngo Weinhold 7580c0fea5dSIngo Weinhold 7590c0fea5dSIngo Weinhold status_t 7609a6072a3SAxel Dörfler get_nth_symbol(image_id imageID, int32 num, char *nameBuffer, 7619a6072a3SAxel Dörfler int32 *_nameLength, int32 *_type, void **_location) 7620c0fea5dSIngo Weinhold { 7630c0fea5dSIngo Weinhold int32 count = 0, j; 7640c0fea5dSIngo Weinhold uint32 i; 7650c0fea5dSIngo Weinhold image_t *image; 7660c0fea5dSIngo Weinhold 767f167d21aSAugustin Cavalier RecursiveLocker _(sLock); 7680c0fea5dSIngo Weinhold 7690c0fea5dSIngo Weinhold // get the image from those who have been already initialized 77094830eb2SIngo Weinhold image = find_loaded_image_by_id(imageID, false); 771f167d21aSAugustin Cavalier if (image == NULL) 7720c0fea5dSIngo Weinhold return B_BAD_IMAGE_ID; 7730c0fea5dSIngo Weinhold 7740c0fea5dSIngo Weinhold // iterate through all the hash buckets until we've found the one 7750c0fea5dSIngo Weinhold for (i = 0; i < HASHTABSIZE(image); i++) { 7760c0fea5dSIngo Weinhold for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { 777e3ac2588SAlex Smith elf_sym *symbol = &image->syms[j]; 7780c0fea5dSIngo Weinhold 7790c0fea5dSIngo Weinhold if (count == num) { 78010b4b5d1SIngo Weinhold const char* symbolName = SYMNAME(image, symbol); 78110b4b5d1SIngo Weinhold strlcpy(nameBuffer, symbolName, *_nameLength); 78210b4b5d1SIngo Weinhold *_nameLength = strlen(symbolName); 7830c0fea5dSIngo Weinhold 78410b4b5d1SIngo Weinhold void* location = (void*)(symbol->st_value 78510b4b5d1SIngo Weinhold + image->regions[0].delta); 78610b4b5d1SIngo Weinhold int32 type; 787e3ac2588SAlex Smith if (symbol->Type() == STT_FUNC) 78810b4b5d1SIngo Weinhold type = B_SYMBOL_TYPE_TEXT; 789e3ac2588SAlex Smith else if (symbol->Type() == STT_OBJECT) 79010b4b5d1SIngo Weinhold type = B_SYMBOL_TYPE_DATA; 7910c0fea5dSIngo Weinhold else 79210b4b5d1SIngo Weinhold type = B_SYMBOL_TYPE_ANY; 79310b4b5d1SIngo Weinhold // TODO: check with the return types of that BeOS function 7940c0fea5dSIngo Weinhold 79510b4b5d1SIngo Weinhold patch_defined_symbol(image, symbolName, &location, &type); 79610b4b5d1SIngo Weinhold 79710b4b5d1SIngo Weinhold if (_type != NULL) 79810b4b5d1SIngo Weinhold *_type = type; 7990c0fea5dSIngo Weinhold if (_location != NULL) 80010b4b5d1SIngo Weinhold *_location = location; 8010c0fea5dSIngo Weinhold goto out; 8020c0fea5dSIngo Weinhold } 8030c0fea5dSIngo Weinhold count++; 8040c0fea5dSIngo Weinhold } 8050c0fea5dSIngo Weinhold } 8060c0fea5dSIngo Weinhold out: 8070c0fea5dSIngo Weinhold if (num != count) 8080c0fea5dSIngo Weinhold return B_BAD_INDEX; 8090c0fea5dSIngo Weinhold 8100c0fea5dSIngo Weinhold return B_OK; 8110c0fea5dSIngo Weinhold } 8120c0fea5dSIngo Weinhold 8130c0fea5dSIngo Weinhold 8140c0fea5dSIngo Weinhold status_t 81543e7b1c2SHamish Morrison get_nearest_symbol_at_address(void* address, image_id* _imageID, 816ebdc1d48SMichael Lotz char** _imagePath, char** _imageName, char** _symbolName, int32* _type, 817ebdc1d48SMichael Lotz void** _location, bool* _exactMatch) 818b6455c08SAxel Dörfler { 819f167d21aSAugustin Cavalier RecursiveLocker _(sLock); 820b6455c08SAxel Dörfler 821b6455c08SAxel Dörfler image_t* image = find_loaded_image_by_address((addr_t)address); 822f167d21aSAugustin Cavalier if (image == NULL) 823b6455c08SAxel Dörfler return B_BAD_VALUE; 824b6455c08SAxel Dörfler 825ebdc1d48SMichael Lotz bool exactMatch = false; 826e3ac2588SAlex Smith elf_sym* foundSymbol = NULL; 82743e7b1c2SHamish Morrison addr_t foundLocation = (addr_t)NULL; 82843e7b1c2SHamish Morrison 829ebdc1d48SMichael Lotz for (uint32 i = 0; i < HASHTABSIZE(image) && !exactMatch; i++) { 830b6455c08SAxel Dörfler for (int32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF; 831b6455c08SAxel Dörfler j = HASHCHAINS(image)[j]) { 832e3ac2588SAlex Smith elf_sym *symbol = &image->syms[j]; 833b6455c08SAxel Dörfler addr_t location = symbol->st_value + image->regions[0].delta; 834b6455c08SAxel Dörfler 83543e7b1c2SHamish Morrison if (location <= (addr_t)address && location >= foundLocation) { 83643e7b1c2SHamish Morrison foundSymbol = symbol; 83743e7b1c2SHamish Morrison foundLocation = location; 838b6455c08SAxel Dörfler 83943e7b1c2SHamish Morrison // jump out if we have an exact match 840ebdc1d48SMichael Lotz if (location + symbol->st_size > (addr_t)address) { 841ebdc1d48SMichael Lotz exactMatch = true; 84243e7b1c2SHamish Morrison break; 84343e7b1c2SHamish Morrison } 84443e7b1c2SHamish Morrison } 84543e7b1c2SHamish Morrison } 84643e7b1c2SHamish Morrison } 847b6455c08SAxel Dörfler 848b6455c08SAxel Dörfler if (_imageID != NULL) 849b6455c08SAxel Dörfler *_imageID = image->id; 85043e7b1c2SHamish Morrison if (_imagePath != NULL) 85143e7b1c2SHamish Morrison *_imagePath = image->path; 852ebdc1d48SMichael Lotz if (_imageName != NULL) 853ebdc1d48SMichael Lotz *_imageName = image->name; 854ebdc1d48SMichael Lotz if (_exactMatch != NULL) 855ebdc1d48SMichael Lotz *_exactMatch = exactMatch; 85643e7b1c2SHamish Morrison 85743e7b1c2SHamish Morrison if (foundSymbol != NULL) { 85843e7b1c2SHamish Morrison *_symbolName = SYMNAME(image, foundSymbol); 85943e7b1c2SHamish Morrison 86043e7b1c2SHamish Morrison if (_type != NULL) { 861e3ac2588SAlex Smith if (foundSymbol->Type() == STT_FUNC) 86243e7b1c2SHamish Morrison *_type = B_SYMBOL_TYPE_TEXT; 863e3ac2588SAlex Smith else if (foundSymbol->Type() == STT_OBJECT) 86443e7b1c2SHamish Morrison *_type = B_SYMBOL_TYPE_DATA; 86543e7b1c2SHamish Morrison else 86643e7b1c2SHamish Morrison *_type = B_SYMBOL_TYPE_ANY; 86743e7b1c2SHamish Morrison // TODO: check with the return types of that BeOS function 86843e7b1c2SHamish Morrison } 86943e7b1c2SHamish Morrison 870b6455c08SAxel Dörfler if (_location != NULL) 87143e7b1c2SHamish Morrison *_location = (void*)foundLocation; 87243e7b1c2SHamish Morrison } else { 87343e7b1c2SHamish Morrison *_symbolName = NULL; 87443e7b1c2SHamish Morrison if (_location != NULL) 87543e7b1c2SHamish Morrison *_location = NULL; 87643e7b1c2SHamish Morrison } 877b6455c08SAxel Dörfler 878b6455c08SAxel Dörfler return B_OK; 879b6455c08SAxel Dörfler } 880b6455c08SAxel Dörfler 881b6455c08SAxel Dörfler 882b6455c08SAxel Dörfler status_t 8839a6072a3SAxel Dörfler get_symbol(image_id imageID, char const *symbolName, int32 symbolType, 88480ece785SIngo Weinhold bool recursive, image_id *_inImage, void **_location) 8850c0fea5dSIngo Weinhold { 8860c0fea5dSIngo Weinhold status_t status = B_OK; 8870c0fea5dSIngo Weinhold image_t *image; 8880c0fea5dSIngo Weinhold 8890c0fea5dSIngo Weinhold if (imageID < B_OK) 8900c0fea5dSIngo Weinhold return B_BAD_IMAGE_ID; 8910c0fea5dSIngo Weinhold if (symbolName == NULL) 8920c0fea5dSIngo Weinhold return B_BAD_VALUE; 8930c0fea5dSIngo Weinhold 894354b60afSAugustin Cavalier // Previously, these functions were called in __haiku_init_before 895354b60afSAugustin Cavalier // and __haiku_init_after. Now we call them inside runtime_loader, 896354b60afSAugustin Cavalier // so we prevent applications from fetching them. 897354b60afSAugustin Cavalier if (strcmp(symbolName, B_INIT_BEFORE_FUNCTION_NAME) == 0 898354b60afSAugustin Cavalier || strcmp(symbolName, B_INIT_AFTER_FUNCTION_NAME) == 0 899354b60afSAugustin Cavalier || strcmp(symbolName, B_TERM_BEFORE_FUNCTION_NAME) == 0 900354b60afSAugustin Cavalier || strcmp(symbolName, B_TERM_AFTER_FUNCTION_NAME) == 0) 901354b60afSAugustin Cavalier return B_BAD_VALUE; 902354b60afSAugustin Cavalier 903f167d21aSAugustin Cavalier RecursiveLocker _(sLock); 9040c0fea5dSIngo Weinhold // for now, just do stupid simple global locking 9050c0fea5dSIngo Weinhold 9060c0fea5dSIngo Weinhold // get the image from those who have been already initialized 90794830eb2SIngo Weinhold image = find_loaded_image_by_id(imageID, false); 90880ece785SIngo Weinhold if (image != NULL) { 90980ece785SIngo Weinhold if (recursive) { 91080ece785SIngo Weinhold // breadth-first search in the given image and its dependencies 911003ebb0eSIngo Weinhold status = find_symbol_breadth_first(image, 912003ebb0eSIngo Weinhold SymbolLookupInfo(symbolName, symbolType, NULL, 913003ebb0eSIngo Weinhold LOOKUP_FLAG_DEFAULT_VERSION), 91480ece785SIngo Weinhold &image, _location); 915003ebb0eSIngo Weinhold } else { 916003ebb0eSIngo Weinhold status = find_symbol(image, 917003ebb0eSIngo Weinhold SymbolLookupInfo(symbolName, symbolType, NULL, 918003ebb0eSIngo Weinhold LOOKUP_FLAG_DEFAULT_VERSION), 919003ebb0eSIngo Weinhold _location); 920003ebb0eSIngo Weinhold } 92180ece785SIngo Weinhold 92280ece785SIngo Weinhold if (status == B_OK && _inImage != NULL) 92380ece785SIngo Weinhold *_inImage = image->id; 92480ece785SIngo Weinhold } else 9250c0fea5dSIngo Weinhold status = B_BAD_IMAGE_ID; 9260c0fea5dSIngo Weinhold 9270c0fea5dSIngo Weinhold return status; 9280c0fea5dSIngo Weinhold } 9290c0fea5dSIngo Weinhold 9300c0fea5dSIngo Weinhold 9310c0fea5dSIngo Weinhold status_t 9320c85bd05SIngo Weinhold get_library_symbol(void* handle, void* caller, const char* symbolName, 9330c85bd05SIngo Weinhold void **_location) 9340c85bd05SIngo Weinhold { 9350c85bd05SIngo Weinhold status_t status = B_ENTRY_NOT_FOUND; 9360c85bd05SIngo Weinhold 9370c85bd05SIngo Weinhold if (symbolName == NULL) 9380c85bd05SIngo Weinhold return B_BAD_VALUE; 9390c85bd05SIngo Weinhold 940f167d21aSAugustin Cavalier RecursiveLocker _(sLock); 9410c85bd05SIngo Weinhold // for now, just do stupid simple global locking 9420c85bd05SIngo Weinhold 9430c85bd05SIngo Weinhold if (handle == RTLD_DEFAULT || handle == RLD_GLOBAL_SCOPE) { 9440c85bd05SIngo Weinhold // look in the default scope 9450c85bd05SIngo Weinhold image_t* image; 946e3ac2588SAlex Smith elf_sym* symbol = find_undefined_symbol_global(gProgramImage, 94794830eb2SIngo Weinhold gProgramImage, 948003ebb0eSIngo Weinhold SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_ANY, NULL, 949003ebb0eSIngo Weinhold LOOKUP_FLAG_DEFAULT_VERSION), 950003ebb0eSIngo Weinhold &image); 9510c85bd05SIngo Weinhold if (symbol != NULL) { 9520c85bd05SIngo Weinhold *_location = (void*)(symbol->st_value + image->regions[0].delta); 953e3ac2588SAlex Smith int32 symbolType = symbol->Type() == STT_FUNC 9540c85bd05SIngo Weinhold ? B_SYMBOL_TYPE_TEXT : B_SYMBOL_TYPE_DATA; 9550c85bd05SIngo Weinhold patch_defined_symbol(image, symbolName, _location, &symbolType); 9560c85bd05SIngo Weinhold status = B_OK; 9570c85bd05SIngo Weinhold } 9580c85bd05SIngo Weinhold } else if (handle == RTLD_NEXT) { 9590c85bd05SIngo Weinhold // Look in the default scope, but also in the dependencies of the 9600c85bd05SIngo Weinhold // calling image. Return the next after the caller symbol. 9610c85bd05SIngo Weinhold 962a2dad9e1SIngo Weinhold // First of all, find the caller image. 96394830eb2SIngo Weinhold image_t* callerImage = get_loaded_images().head; 9640c85bd05SIngo Weinhold for (; callerImage != NULL; callerImage = callerImage->next) { 9650c85bd05SIngo Weinhold elf_region_t& text = callerImage->regions[0]; 966a2dad9e1SIngo Weinhold if ((addr_t)caller >= text.vmstart 967a2dad9e1SIngo Weinhold && (addr_t)caller < text.vmstart + text.vmsize) { 968a2dad9e1SIngo Weinhold // found the image 9690c85bd05SIngo Weinhold break; 9700c85bd05SIngo Weinhold } 9710c85bd05SIngo Weinhold } 9720c85bd05SIngo Weinhold 973a2dad9e1SIngo Weinhold if (callerImage != NULL) { 9740c85bd05SIngo Weinhold // found the caller -- now search the global scope until we find 9750c85bd05SIngo Weinhold // the next symbol 976a2dad9e1SIngo Weinhold bool hitCallerImage = false; 9770c85bd05SIngo Weinhold set_image_flags_recursively(callerImage, RFLAG_USE_FOR_RESOLVING); 9780c85bd05SIngo Weinhold 979e3ac2588SAlex Smith elf_sym* candidateSymbol = NULL; 98025dc253dSIngo Weinhold image_t* candidateImage = NULL; 98125dc253dSIngo Weinhold 98294830eb2SIngo Weinhold image_t* image = get_loaded_images().head; 9830c85bd05SIngo Weinhold for (; image != NULL; image = image->next) { 984a2dad9e1SIngo Weinhold // skip the caller image 985a2dad9e1SIngo Weinhold if (image == callerImage) { 986a2dad9e1SIngo Weinhold hitCallerImage = true; 987a2dad9e1SIngo Weinhold continue; 988a2dad9e1SIngo Weinhold } 989a2dad9e1SIngo Weinhold 990a2dad9e1SIngo Weinhold // skip all images up to the caller image; also skip add-on 991a2dad9e1SIngo Weinhold // images and those not marked above for resolution 992a2dad9e1SIngo Weinhold if (!hitCallerImage || image->type == B_ADD_ON_IMAGE 9930c85bd05SIngo Weinhold || (image->flags 994a2dad9e1SIngo Weinhold & (RTLD_GLOBAL | RFLAG_USE_FOR_RESOLVING)) == 0) { 9950c85bd05SIngo Weinhold continue; 9960c85bd05SIngo Weinhold } 9970c85bd05SIngo Weinhold 998e3ac2588SAlex Smith elf_sym *symbol = find_symbol(image, 999003ebb0eSIngo Weinhold SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_TEXT, NULL, 1000003ebb0eSIngo Weinhold LOOKUP_FLAG_DEFAULT_VERSION)); 10010c85bd05SIngo Weinhold if (symbol == NULL) 10020c85bd05SIngo Weinhold continue; 10030c85bd05SIngo Weinhold 100425dc253dSIngo Weinhold // found a symbol 1005e3ac2588SAlex Smith bool isWeak = symbol->Bind() == STB_WEAK; 100625dc253dSIngo Weinhold if (candidateImage == NULL || !isWeak) { 100725dc253dSIngo Weinhold candidateSymbol = symbol; 100825dc253dSIngo Weinhold candidateImage = image; 100925dc253dSIngo Weinhold 101025dc253dSIngo Weinhold if (!isWeak) 101125dc253dSIngo Weinhold break; 101225dc253dSIngo Weinhold } 101325dc253dSIngo Weinhold 101425dc253dSIngo Weinhold // symbol is weak, so we need to continue 101525dc253dSIngo Weinhold } 101625dc253dSIngo Weinhold 101725dc253dSIngo Weinhold if (candidateSymbol != NULL) { 1018a2dad9e1SIngo Weinhold // found the symbol 101925dc253dSIngo Weinhold *_location = (void*)(candidateSymbol->st_value 102025dc253dSIngo Weinhold + candidateImage->regions[0].delta); 10210c85bd05SIngo Weinhold int32 symbolType = B_SYMBOL_TYPE_TEXT; 102225dc253dSIngo Weinhold patch_defined_symbol(candidateImage, symbolName, _location, 10230c85bd05SIngo Weinhold &symbolType); 10240c85bd05SIngo Weinhold status = B_OK; 10250c85bd05SIngo Weinhold } 10260c85bd05SIngo Weinhold 10270c85bd05SIngo Weinhold clear_image_flags_recursively(callerImage, RFLAG_USE_FOR_RESOLVING); 10280c85bd05SIngo Weinhold } 10290c85bd05SIngo Weinhold } else { 10300c85bd05SIngo Weinhold // breadth-first search in the given image and its dependencies 10310c85bd05SIngo Weinhold image_t* inImage; 1032003ebb0eSIngo Weinhold status = find_symbol_breadth_first((image_t*)handle, 1033003ebb0eSIngo Weinhold SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_ANY, NULL, 1034003ebb0eSIngo Weinhold LOOKUP_FLAG_DEFAULT_VERSION), 1035003ebb0eSIngo Weinhold &inImage, _location); 10360c85bd05SIngo Weinhold } 10370c85bd05SIngo Weinhold 10380c85bd05SIngo Weinhold return status; 10390c85bd05SIngo Weinhold } 10400c85bd05SIngo Weinhold 10410c85bd05SIngo Weinhold 10420c85bd05SIngo Weinhold status_t 10430c0fea5dSIngo Weinhold get_next_image_dependency(image_id id, uint32 *cookie, const char **_name) 10440c0fea5dSIngo Weinhold { 10450c0fea5dSIngo Weinhold uint32 i, j, searchIndex = *cookie; 1046e3ac2588SAlex Smith elf_dyn *dynamicSection; 10470c0fea5dSIngo Weinhold image_t *image; 10480c0fea5dSIngo Weinhold 10490c0fea5dSIngo Weinhold if (_name == NULL) 10500c0fea5dSIngo Weinhold return B_BAD_VALUE; 10510c0fea5dSIngo Weinhold 1052f167d21aSAugustin Cavalier RecursiveLocker _(sLock); 10530c0fea5dSIngo Weinhold 105494830eb2SIngo Weinhold image = find_loaded_image_by_id(id, false); 1055f167d21aSAugustin Cavalier if (image == NULL) 10560c0fea5dSIngo Weinhold return B_BAD_IMAGE_ID; 10570c0fea5dSIngo Weinhold 1058e3ac2588SAlex Smith dynamicSection = (elf_dyn *)image->dynamic_ptr; 1059f167d21aSAugustin Cavalier if (dynamicSection == NULL || image->num_needed <= searchIndex) 10600c0fea5dSIngo Weinhold return B_ENTRY_NOT_FOUND; 10610c0fea5dSIngo Weinhold 10620c0fea5dSIngo Weinhold for (i = 0, j = 0; dynamicSection[i].d_tag != DT_NULL; i++) { 10630c0fea5dSIngo Weinhold if (dynamicSection[i].d_tag != DT_NEEDED) 10640c0fea5dSIngo Weinhold continue; 10650c0fea5dSIngo Weinhold 10660c0fea5dSIngo Weinhold if (j++ == searchIndex) { 10670c0fea5dSIngo Weinhold int32 neededOffset = dynamicSection[i].d_un.d_val; 10680c0fea5dSIngo Weinhold 10690c0fea5dSIngo Weinhold *_name = STRING(image, neededOffset); 10700c0fea5dSIngo Weinhold *cookie = searchIndex + 1; 10710c0fea5dSIngo Weinhold return B_OK; 10720c0fea5dSIngo Weinhold } 10730c0fea5dSIngo Weinhold } 10740c0fea5dSIngo Weinhold 10750c0fea5dSIngo Weinhold return B_ENTRY_NOT_FOUND; 10760c0fea5dSIngo Weinhold } 10770c0fea5dSIngo Weinhold 10780c0fea5dSIngo Weinhold 107974c0424aSAxel Dörfler // #pragma mark - runtime_loader private exports 10800c0fea5dSIngo Weinhold 10810c0fea5dSIngo Weinhold 10829a6072a3SAxel Dörfler /*! Read and verify the ELF header */ 10830c0fea5dSIngo Weinhold status_t 1084e3ac2588SAlex Smith elf_verify_header(void *header, size_t length) 10850c0fea5dSIngo Weinhold { 10860c0fea5dSIngo Weinhold int32 programSize, sectionSize; 10870c0fea5dSIngo Weinhold 1088e3ac2588SAlex Smith if (length < sizeof(elf_ehdr)) 10890c0fea5dSIngo Weinhold return B_NOT_AN_EXECUTABLE; 10900c0fea5dSIngo Weinhold 1091e3ac2588SAlex Smith return parse_elf_header((elf_ehdr *)header, &programSize, §ionSize); 10920c0fea5dSIngo Weinhold } 10930c0fea5dSIngo Weinhold 10940c0fea5dSIngo Weinhold 10952aaad308SJérôme Duval #ifdef _COMPAT_MODE 10962aaad308SJérôme Duval #ifdef __x86_64__ 10972aaad308SJérôme Duval status_t 10982aaad308SJérôme Duval elf32_verify_header(void *header, size_t length) 10992aaad308SJérôme Duval { 11002aaad308SJérôme Duval int32 programSize, sectionSize; 11012aaad308SJérôme Duval 11022aaad308SJérôme Duval if (length < sizeof(Elf32_Ehdr)) 11032aaad308SJérôme Duval return B_NOT_AN_EXECUTABLE; 11042aaad308SJérôme Duval 11052aaad308SJérôme Duval return parse_elf32_header((Elf32_Ehdr *)header, &programSize, §ionSize); 11062aaad308SJérôme Duval } 11072aaad308SJérôme Duval #else 11082aaad308SJérôme Duval status_t 11092aaad308SJérôme Duval elf64_verify_header(void *header, size_t length) 11102aaad308SJérôme Duval { 11112aaad308SJérôme Duval int32 programSize, sectionSize; 11122aaad308SJérôme Duval 11132aaad308SJérôme Duval if (length < sizeof(Elf64_Ehdr)) 11142aaad308SJérôme Duval return B_NOT_AN_EXECUTABLE; 11152aaad308SJérôme Duval 11162aaad308SJérôme Duval return parse_elf64_header((Elf64_Ehdr *)header, &programSize, §ionSize); 11172aaad308SJérôme Duval } 11182aaad308SJérôme Duval #endif // __x86_64__ 11192aaad308SJérôme Duval #endif // _COMPAT_MODE 11202aaad308SJérôme Duval 11212aaad308SJérôme Duval 11220c0fea5dSIngo Weinhold void 11230c0fea5dSIngo Weinhold terminate_program(void) 11240c0fea5dSIngo Weinhold { 11250c0fea5dSIngo Weinhold image_t **termList; 11260c0fea5dSIngo Weinhold ssize_t count, i; 11270c0fea5dSIngo Weinhold 1128aa3507feSIngo Weinhold count = get_sorted_image_list(NULL, &termList, RFLAG_TERMINATED); 11290c0fea5dSIngo Weinhold if (count < B_OK) 11300c0fea5dSIngo Weinhold return; 11310c0fea5dSIngo Weinhold 113294830eb2SIngo Weinhold if (gInvalidImageIDs) { 11339a6072a3SAxel Dörfler // After fork, we lazily rebuild the image IDs of all loaded images 11349a6072a3SAxel Dörfler update_image_ids(); 11359a6072a3SAxel Dörfler } 11369a6072a3SAxel Dörfler 11370c0fea5dSIngo Weinhold TRACE(("%ld: terminate dependencies\n", find_thread(NULL))); 11380c0fea5dSIngo Weinhold for (i = count; i-- > 0;) { 11390c0fea5dSIngo Weinhold image_t *image = termList[i]; 11400c0fea5dSIngo Weinhold 11410c0fea5dSIngo Weinhold TRACE(("%ld: term: %s\n", find_thread(NULL), image->name)); 11420c0fea5dSIngo Weinhold 114310b4b5d1SIngo Weinhold image_event(image, IMAGE_EVENT_UNINITIALIZING); 114410b4b5d1SIngo Weinhold 1145e340f717SJérôme Duval if (image->term_array) { 1146e340f717SJérôme Duval uint count_term = image->term_array_len / sizeof(addr_t); 1147e340f717SJérôme Duval for (uint j = count_term; j-- > 0;) 1148e340f717SJérôme Duval ((init_term_function)image->term_array[j])(image->id); 1149e340f717SJérôme Duval } 1150e340f717SJérôme Duval 11510c0fea5dSIngo Weinhold if (image->term_routine) 11520c0fea5dSIngo Weinhold ((init_term_function)image->term_routine)(image->id); 115310b4b5d1SIngo Weinhold 115410b4b5d1SIngo Weinhold image_event(image, IMAGE_EVENT_UNLOADING); 11550c0fea5dSIngo Weinhold } 11560c0fea5dSIngo Weinhold TRACE(("%ld: term done.\n", find_thread(NULL))); 11570c0fea5dSIngo Weinhold 11580c0fea5dSIngo Weinhold free(termList); 11590c0fea5dSIngo Weinhold } 11600c0fea5dSIngo Weinhold 11610c0fea5dSIngo Weinhold 11620c0fea5dSIngo Weinhold void 11630c0fea5dSIngo Weinhold rldelf_init(void) 11640c0fea5dSIngo Weinhold { 116594830eb2SIngo Weinhold init_add_ons(); 116694830eb2SIngo Weinhold 11670c0fea5dSIngo Weinhold // create the debug area 11680c0fea5dSIngo Weinhold { 1169e3ac2588SAlex Smith size_t size = TO_PAGE_SIZE(sizeof(runtime_loader_debug_area)); 11700c0fea5dSIngo Weinhold 11710c0fea5dSIngo Weinhold runtime_loader_debug_area *area; 11720c0fea5dSIngo Weinhold area_id areaID = _kern_create_area(RUNTIME_LOADER_DEBUG_AREA_NAME, 11739f3bd497SPawel Dziepak (void **)&area, B_RANDOMIZED_ANY_ADDRESS, size, B_NO_LOCK, 11740c0fea5dSIngo Weinhold B_READ_AREA | B_WRITE_AREA); 11750c0fea5dSIngo Weinhold if (areaID < B_OK) { 11760c0fea5dSIngo Weinhold FATAL("Failed to create debug area.\n"); 11770c0fea5dSIngo Weinhold _kern_loading_app_failed(areaID); 11780c0fea5dSIngo Weinhold } 11790c0fea5dSIngo Weinhold 118094830eb2SIngo Weinhold area->loaded_images = &get_loaded_images(); 11810c0fea5dSIngo Weinhold } 118274c0424aSAxel Dörfler 118374c0424aSAxel Dörfler // initialize error message if needed 11844bef3723SAxel Dörfler if (report_errors()) { 118574c0424aSAxel Dörfler void *buffer = malloc(1024); 118674c0424aSAxel Dörfler if (buffer == NULL) 118774c0424aSAxel Dörfler return; 118874c0424aSAxel Dörfler 118994830eb2SIngo Weinhold gErrorMessage.SetTo(buffer, 1024, 'Rler'); 119074c0424aSAxel Dörfler } 11910c0fea5dSIngo Weinhold } 11921873b4b3SIngo Weinhold 11931873b4b3SIngo Weinhold 11941873b4b3SIngo Weinhold status_t 11959a6072a3SAxel Dörfler elf_reinit_after_fork(void) 11961873b4b3SIngo Weinhold { 1197f7127458SIngo Weinhold recursive_lock_init(&sLock, kLockName); 11981873b4b3SIngo Weinhold 11999a6072a3SAxel Dörfler // We also need to update the IDs of our images. We are the child and 1200cbc456deSIngo Weinhold // and have cloned images with different IDs. Since in most cases (fork() 1201cbc456deSIngo Weinhold // + exec*()) this would just increase the fork() overhead with no one 12029a6072a3SAxel Dörfler // caring, we do that lazily, when first doing something different. 120394830eb2SIngo Weinhold gInvalidImageIDs = true; 1204cbc456deSIngo Weinhold 12051873b4b3SIngo Weinhold return B_OK; 12061873b4b3SIngo Weinhold } 1207