1816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner/* Copyright (C) 2011 The Android Open Source Project
2816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner**
3816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner** This software is licensed under the terms of the GNU General Public
4816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner** License version 2, as published by the Free Software Foundation, and
5816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner** may be copied, distributed, and modified under those terms.
6816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner**
7816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner** This program is distributed in the hope that it will be useful,
8816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner** but WITHOUT ANY WARRANTY; without even the implied warranty of
9816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner** GNU General Public License for more details.
11816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner*/
12816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner#include <android/utils/dll.h>
13816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner#include <android/utils/system.h>
14816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner#include <android/utils/path.h>
15816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
16816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner#include <stdlib.h>
17816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
18816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner/* Utility function, append one string to another, caller must free result */
19816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turnerstatic char*
20816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turnerappend_string( const char* str1, const char* str2 )
21816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner{
22816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    int   len1   = strlen(str1);
23816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    int   len2   = strlen(str2);
24816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    char* result = malloc(len1+len2+1);
25816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
26816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    if (result != NULL) {
27816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        memcpy(result, str1, len1);
28816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        memcpy(result + len1, str2, len2);
29816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        result[len1+len2] = '\0';
30816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    }
31816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    return result;
32816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner}
33816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
34816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner#ifdef _WIN32
35816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
36816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner#include <windows.h>
37816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
38816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' TurnerADynamicLibrary*
39816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' TurneradynamicLibrary_open( const char*  libraryName,
40816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner                      char**       pError)
41816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner{
42816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    char*  libName = (char*) libraryName;
43816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    void*  result;
44816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
45816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    /* Append a .dll to the library name if it doesn't have an extension */
46816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    if (strchr(libraryName,'.') == NULL) {
47816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        libName = append_string(libraryName, ".dll");
48816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    }
49816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
50816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    /* Now do our magic */
51816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    *pError = NULL;
52816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    result = (ADynamicLibrary*) LoadLibrary( libName );
53816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    if (result == NULL) {
54816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        *pError = ASTRDUP("Could not load DLL!");
55816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    }
56816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
57816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    /* Free the library name if we modified it */
58816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    if (libName != libraryName) {
59816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        free(libName);
60816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    }
61816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
62816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    return (ADynamicLibrary*) result;
63816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner}
64816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
65816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turnervoid*
66816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' TurneradynamicLibrary_findSymbol( ADynamicLibrary*  lib,
67816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner                            const char*       symbolName,
68816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner                            char**            pError)
69816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner{
70816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    void* result;
71816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
72816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    *pError = NULL;
73816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
74816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    if (lib == NULL) {
75816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        *pError = strdup("NULL library pointer");
76816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        return NULL;
77816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    }
78816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    if (symbolName == NULL || symbolName[0] == '\0') {
79816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        *pError = strdup("NULL or empty symbolName");
80816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        return NULL;
81816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    }
82816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    result = GetProcAddress( (HMODULE)lib, symbolName );
83816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    if (result == NULL) {
84816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        *pError = ASTRDUP("Could not find symbol");
85816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    }
86816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    return result;
87816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner}
88816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
89816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner/* Close/unload a given dynamic library */
90816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turnervoid
91816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' TurneradynamicLibrary_close( ADynamicLibrary*  lib )
92816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner{
93816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    if (lib != NULL) {
94816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        FreeLibrary( (HMODULE)lib );
95816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    }
96816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner}
97816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
98816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner#else /* !_WIN32 */
99816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
100816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner#include <dlfcn.h>
101816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner#include <stdlib.h>
102816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
103816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' TurnerADynamicLibrary*
104816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' TurneradynamicLibrary_open( const char*  libraryName,
105816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner                      char**       pError)
106816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner{
107816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    char*  libName = (char*) libraryName;
108816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    void*  result;
109816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
110816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner#ifdef __APPLE__
111816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner#  define SO_EXTENSION ".dylib"
112816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner#else
113816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner#  define SO_EXTENSION ".so"
114816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner#endif
115816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
116816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    /* Append a .so to the library name if it doesn't have an extension */
117816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    if (strchr(libraryName,'.') == NULL) {
118816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        libName = append_string(libraryName, SO_EXTENSION);
119816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    }
120816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
121816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    /* Now do our magic */
122816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    *pError = NULL;
123816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    result  = dlopen( libName, RTLD_LAZY );
124816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    if (result == NULL) {
125816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        *pError = strdup(dlerror());
126816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    }
127816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
128816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    /* Free the library name if we modified it */
129816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    if (libName != (char*)libraryName) {
130816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        free(libName);
131816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    }
132816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
133816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    return (ADynamicLibrary*) result;
134816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner}
135816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
136816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turnervoid*
137816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' TurneradynamicLibrary_findSymbol( ADynamicLibrary*  lib,
138816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner                            const char*       symbolName,
139816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner                            char**            pError)
140816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner{
141816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    void* result;
142816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
143816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    *pError = NULL;
144816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
145816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    if (lib == NULL) {
146816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        *pError = strdup("NULL library pointer");
147816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        return NULL;
148816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    }
149816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    if (symbolName == NULL || symbolName[0] == '\0') {
150816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        *pError = strdup("NULL or empty symbolName");
151816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        return NULL;
152816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    }
153816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    result = dlsym(lib, symbolName);
154816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    if (result == NULL) {
155816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        *pError = strdup(dlerror());
156816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    }
157816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    return result;
158816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner}
159816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
160816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner/* Close/unload a given dynamic library */
161816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turnervoid
162816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' TurneradynamicLibrary_close( ADynamicLibrary*  lib )
163816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner{
164816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    if (lib != NULL) {
165816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner        dlclose(lib);
166816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner    }
167816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner}
168816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner
169816e53ca385b64c18c9c7cfca569c4d747634e97David 'Digit' Turner#endif /* !_WIN32 */
170