xref: /haiku/src/system/libroot/posix/dlfcn.c (revision ad2226790662c78e979960a0c7237cf4b5a6fad2)
1 /*
2  * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2003-2010, 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 = __builtin_return_address(0);
45 	}
46 
47 	status = __gRuntimeLoader->get_library_symbol(handle, caller, name,
48 		&location);
49 	sStatus = status;
50 
51 	if (status < B_OK)
52 		return NULL;
53 
54 	return location;
55 }
56 
57 
58 int
59 dlclose(void *handle)
60 {
61 	return sStatus = __gRuntimeLoader->unload_library(handle);
62 }
63 
64 
65 char *
66 dlerror(void)
67 {
68 	if (sStatus < B_OK)
69 		return strerror(sStatus);
70 
71 	return NULL;
72 }
73 
74 
75 int
76 dladdr(const void *address, Dl_info *info)
77 {
78 	image_id image;
79 	char* imagePath;
80 	char* symbolName;
81 	void* location;
82 	image_info imageInfo;
83 
84 	sStatus = __gRuntimeLoader->get_nearest_symbol_at_address(address, &image,
85 		&imagePath, NULL, &symbolName, NULL, &location, NULL);
86 	if (sStatus != B_OK)
87 		return 0;
88 
89 	sStatus = get_image_info(image, &imageInfo);
90 	if (sStatus != B_OK)
91 		return 0;
92 
93 	info->dli_fname = imagePath;
94 	info->dli_fbase = imageInfo.text;
95 	info->dli_sname = symbolName;
96 	info->dli_saddr = location;
97 
98 	return 1;
99 }
100 
101 
102 // __libc_dl*** wrappers
103 // We use a mixed glibc / bsd libc, and glibc wants these
104 void *__libc_dlopen(const char *name);
105 void *__libc_dlsym(void *handle, const char *name);
106 void __libc_dlclose(void *handle);
107 
108 void *
109 __libc_dlopen(const char *name)
110 {
111 	return dlopen(name, 0);
112 }
113 
114 
115 void *
116 __libc_dlsym(void *handle, const char *name)
117 {
118 	return dlsym(handle, name);
119 }
120 
121 
122 void
123 __libc_dlclose(void *handle)
124 {
125 	dlclose(handle);
126 }
127