1 /* 2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 * 6 * Copyright 2002, Manuel J. Petit. All rights reserved. 7 * Distributed under the terms of the NewOS License. 8 */ 9 10 11 #include <libroot_private.h> 12 13 #include <dlfcn.h> 14 #include <string.h> 15 16 #include <runtime_loader.h> 17 #include <user_runtime.h> 18 19 20 static status_t sStatus; 21 // Note, this is not thread-safe 22 23 24 void * 25 dlopen(char const *name, int mode) 26 { 27 void* handle; 28 image_id imageID = __gRuntimeLoader->load_library(name, mode, &handle); 29 30 sStatus = imageID >= 0 ? B_OK : imageID; 31 32 return imageID >= 0 ? handle : NULL; 33 } 34 35 36 void * 37 dlsym(void *handle, char const *name) 38 { 39 void* location; 40 status_t status; 41 void* caller = NULL; 42 43 if (handle == RTLD_NEXT) 44 caller = __arch_get_caller(); 45 46 status = __gRuntimeLoader->get_library_symbol(handle, caller, name, 47 &location); 48 sStatus = status; 49 50 if (status < B_OK) 51 return NULL; 52 53 return location; 54 } 55 56 57 int 58 dlclose(void *handle) 59 { 60 return sStatus = __gRuntimeLoader->unload_library(handle); 61 } 62 63 64 char * 65 dlerror(void) 66 { 67 if (sStatus < B_OK) 68 return strerror(sStatus); 69 70 return NULL; 71 } 72 73 74 int 75 dladdr(void *addr, Dl_info *info) 76 { 77 // TODO: This can be implemented more efficiently in the runtime loader. 78 // get_library_symbol() already has the code doing that. 79 char curSymName[NAME_MAX]; 80 static char symName[NAME_MAX]; 81 static char imageName[MAXPATHLEN]; 82 void *symLocation; 83 int32 cookie; 84 int32 symType, symNameLength; 85 uint32 symIndex; 86 image_info imageInfo; 87 88 if (info == NULL) 89 return 0; 90 91 imageName[0] = '\0'; 92 symName[0] = '\0'; 93 info->dli_fname = imageName; 94 info->dli_saddr = NULL; 95 info->dli_sname = symName; 96 97 cookie = 0; 98 while (get_next_image_info(0, &cookie, &imageInfo) == B_OK) { 99 // check if the image holds the symbol 100 if ((addr_t)addr >= (addr_t)imageInfo.text 101 && (addr_t)addr < (addr_t)imageInfo.text + imageInfo.text_size) { 102 strlcpy(imageName, imageInfo.name, MAXPATHLEN); 103 info->dli_fbase = imageInfo.text; 104 symIndex = 0; 105 symNameLength = NAME_MAX; 106 107 while (get_nth_image_symbol(imageInfo.id, symIndex, curSymName, 108 &symNameLength, &symType, &symLocation) == B_OK) { 109 // check if symbol is the nearest until now 110 if (symType == B_SYMBOL_TYPE_TEXT 111 && symLocation <= addr 112 && symLocation >= info->dli_saddr) { 113 strlcpy(symName, curSymName, NAME_MAX); 114 info->dli_saddr = symLocation; 115 116 // stop here if exact match 117 if (info->dli_saddr == addr) 118 return 1; 119 } 120 symIndex++; 121 symNameLength = NAME_MAX; 122 } 123 break; 124 } 125 } 126 127 if (info->dli_saddr != NULL) 128 return 1; 129 130 return 0; 131 } 132 133 134 // __libc_dl*** wrappers 135 // We use a mixed glibc / bsd libc, and glibc wants these 136 void *__libc_dlopen(const char *name); 137 void *__libc_dlsym(void *handle, const char *name); 138 void __libc_dlclose(void *handle); 139 140 void * 141 __libc_dlopen(const char *name) 142 { 143 return dlopen(name, 0); 144 } 145 146 147 void * 148 __libc_dlsym(void *handle, const char *name) 149 { 150 return dlsym(handle, name); 151 } 152 153 154 void 155 __libc_dlclose(void *handle) 156 { 157 dlclose(handle); 158 } 159