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
20static status_t sStatus;
21	// Note, this is not thread-safe
22
23
24void *
25dlopen(char const *name, int mode)
26{
27	void* handle;
28	void* caller = __builtin_return_address(0);
29	image_id imageID = __gRuntimeLoader->load_library(name, mode, caller,
30		&handle);
31
32	sStatus = imageID >= 0 ? B_OK : imageID;
33
34	return imageID >= 0 ? handle : NULL;
35}
36
37
38void *
39dlsym(void *handle, char const *name)
40{
41	void* location;
42	status_t status;
43	void* caller = NULL;
44
45	if (handle == RTLD_NEXT) {
46		caller = __builtin_return_address(0);
47	}
48
49	status = __gRuntimeLoader->get_library_symbol(handle, caller, name,
50		&location);
51	sStatus = status;
52
53	if (status < B_OK)
54		return NULL;
55
56	return location;
57}
58
59
60int
61dlclose(void *handle)
62{
63	return sStatus = __gRuntimeLoader->unload_library(handle);
64}
65
66
67char *
68dlerror(void)
69{
70	if (sStatus < B_OK)
71		return strerror(sStatus);
72
73	return NULL;
74}
75
76
77int
78dladdr(const void *address, Dl_info *info)
79{
80	image_id image;
81	char* imagePath;
82	char* symbolName;
83	void* location;
84	image_info imageInfo;
85
86	sStatus = __gRuntimeLoader->get_nearest_symbol_at_address(address, &image,
87		&imagePath, NULL, &symbolName, NULL, &location, NULL);
88	if (sStatus != B_OK)
89		return 0;
90
91	sStatus = get_image_info(image, &imageInfo);
92	if (sStatus != B_OK)
93		return 0;
94
95	info->dli_fname = imagePath;
96	info->dli_fbase = imageInfo.text;
97	info->dli_sname = symbolName;
98	info->dli_saddr = location;
99
100	return 1;
101}
102
103
104// __libc_dl*** wrappers
105// We use a mixed glibc / bsd libc, and glibc wants these
106void *__libc_dlopen(const char *name);
107void *__libc_dlsym(void *handle, const char *name);
108void __libc_dlclose(void *handle);
109
110void *
111__libc_dlopen(const char *name)
112{
113	return dlopen(name, 0);
114}
115
116
117void *
118__libc_dlsym(void *handle, const char *name)
119{
120	return dlsym(handle, name);
121}
122
123
124void
125__libc_dlclose(void *handle)
126{
127	dlclose(handle);
128}
129