aboutsummaryrefslogtreecommitdiffstats
path: root/android/utils
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@android.com>2011-08-17 18:33:45 +0200
committerDavid 'Digit' Turner <digit@android.com>2011-08-24 16:54:20 +0200
commit816e53ca385b64c18c9c7cfca569c4d747634e97 (patch)
tree22ecf23d95b0a165b2b00cf7a270c159825bd90b /android/utils
parent1fa2c1c394ce25ff41c4525d8d07983e00851266 (diff)
downloadexternal_qemu-816e53ca385b64c18c9c7cfca569c4d747634e97.zip
external_qemu-816e53ca385b64c18c9c7cfca569c4d747634e97.tar.gz
external_qemu-816e53ca385b64c18c9c7cfca569c4d747634e97.tar.bz2
Add DLL-loading head <android/utils/dll.h>
This patch adds several functions to make loading shared libraries dynamically easier. This will be used to load the GLES emulation libraries. Change-Id: Ib401af339530bc647bfa86fb23a2840fe0a201dd
Diffstat (limited to 'android/utils')
-rw-r--r--android/utils/dll.c194
-rw-r--r--android/utils/dll.h44
-rw-r--r--android/utils/path.c55
-rw-r--r--android/utils/path.h6
4 files changed, 299 insertions, 0 deletions
diff --git a/android/utils/dll.c b/android/utils/dll.c
new file mode 100644
index 0000000..a46a462
--- /dev/null
+++ b/android/utils/dll.c
@@ -0,0 +1,194 @@
+/* Copyright (C) 2011 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include <android/utils/dll.h>
+#include <android/utils/system.h>
+#include <android/utils/path.h>
+
+#include <stdlib.h>
+
+/* Utility function, append one string to another, caller must free result */
+static char*
+append_string( const char* str1, const char* str2 )
+{
+ int len1 = strlen(str1);
+ int len2 = strlen(str2);
+ char* result = malloc(len1+len2+1);
+
+ if (result != NULL) {
+ memcpy(result, str1, len1);
+ memcpy(result + len1, str2, len2);
+ result[len1+len2] = '\0';
+ }
+ return result;
+}
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+/* This function is used to revert all forward slashes (/) in a path
+ * string into unquoted backwards one (\). This is necessary because
+ * LoadLibrary() and AddDllDirectory() do not support forward slashes.
+ *
+ * Caller must free the result string
+ */
+static char*
+reverse_slashes( const char* path )
+{
+ int len = strlen(path);
+ char* result = malloc(len+1);
+ int nn;
+
+ for (nn = 0; nn < len; nn++) {
+ int ch = path[nn];
+ if (ch == '/') {
+ ch = '\\';
+ }
+ result[nn] = (char)ch;
+ }
+ result[nn] = '\0';
+
+ return result;
+}
+
+ADynamicLibrary*
+adynamicLibrary_open( const char* libraryName,
+ char** pError)
+{
+ char* libName = (char*) libraryName;
+ void* result;
+
+ /* Append a .dll to the library name if it doesn't have an extension */
+ if (strchr(libraryName,'.') == NULL) {
+ libName = append_string(libraryName, ".dll");
+ }
+
+ /* Now do our magic */
+ *pError = NULL;
+ result = (ADynamicLibrary*) LoadLibrary( libName );
+ if (result == NULL) {
+ *pError = ASTRDUP("Could not load DLL!");
+ }
+
+ /* Free the library name if we modified it */
+ if (libName != libraryName) {
+ free(libName);
+ }
+
+ return (ADynamicLibrary*) result;
+}
+
+void*
+adynamicLibrary_findSymbol( ADynamicLibrary* lib,
+ const char* symbolName,
+ char** pError)
+{
+ void* result;
+
+ *pError = NULL;
+
+ if (lib == NULL) {
+ *pError = strdup("NULL library pointer");
+ return NULL;
+ }
+ if (symbolName == NULL || symbolName[0] == '\0') {
+ *pError = strdup("NULL or empty symbolName");
+ return NULL;
+ }
+ result = GetProcAddress( (HMODULE)lib, symbolName );
+ if (result == NULL) {
+ *pError = ASTRDUP("Could not find symbol");
+ }
+ return result;
+}
+
+/* Close/unload a given dynamic library */
+void
+adynamicLibrary_close( ADynamicLibrary* lib )
+{
+ if (lib != NULL) {
+ FreeLibrary( (HMODULE)lib );
+ }
+}
+
+#else /* !_WIN32 */
+
+#include <dlfcn.h>
+#include <stdlib.h>
+
+ADynamicLibrary*
+adynamicLibrary_open( const char* libraryName,
+ char** pError)
+{
+ char* libName = (char*) libraryName;
+ void* result;
+
+#ifdef __APPLE__
+# define SO_EXTENSION ".dylib"
+#else
+# define SO_EXTENSION ".so"
+#endif
+
+ /* Append a .so to the library name if it doesn't have an extension */
+ if (strchr(libraryName,'.') == NULL) {
+ libName = append_string(libraryName, SO_EXTENSION);
+ }
+
+ /* Now do our magic */
+ *pError = NULL;
+ result = dlopen( libName, RTLD_LAZY );
+ if (result == NULL) {
+ *pError = strdup(dlerror());
+ }
+
+ /* Free the library name if we modified it */
+ if (libName != (char*)libraryName) {
+ free(libName);
+ }
+
+ return (ADynamicLibrary*) result;
+}
+
+void*
+adynamicLibrary_findSymbol( ADynamicLibrary* lib,
+ const char* symbolName,
+ char** pError)
+{
+ void* result;
+
+ *pError = NULL;
+
+ if (lib == NULL) {
+ *pError = strdup("NULL library pointer");
+ return NULL;
+ }
+ if (symbolName == NULL || symbolName[0] == '\0') {
+ *pError = strdup("NULL or empty symbolName");
+ return NULL;
+ }
+ result = dlsym(lib, symbolName);
+ if (result == NULL) {
+ *pError = strdup(dlerror());
+ }
+ return result;
+}
+
+/* Close/unload a given dynamic library */
+void
+adynamicLibrary_close( ADynamicLibrary* lib )
+{
+ if (lib != NULL) {
+ dlclose(lib);
+ }
+}
+
+#endif /* !_WIN32 */
diff --git a/android/utils/dll.h b/android/utils/dll.h
new file mode 100644
index 0000000..66f3a6d
--- /dev/null
+++ b/android/utils/dll.h
@@ -0,0 +1,44 @@
+/* Copyright (C) 2011 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#ifndef ANDROID_UTILS_DLL_H
+#define ANDROID_UTILS_DLL_H
+
+/* Opaque type to model a dynamic library handle */
+typedef struct ADynamicLibrary ADynamicLibrary;
+
+/* Try to load/open a dynamic library named 'libraryName', looking for
+ * it in the optional paths listed by 'libraryPaths'.
+ *
+ * Once opened, you can use adynamicLibrary_findSymbol() and
+ * adynamicLibrary_close() on it.
+ *
+ * libraryName :: library name, if no extension is provided, then '.so'
+ * will be appended on Unix systems, or '.dll' on Windows.
+ *
+ * pError :: On success, '*pError' will be set to NULL. On error, it will
+ * point to a string describing the error, which must be freed by
+ * the caller.
+ *
+ * returns an ADynamicLibrary pointer.
+ */
+ADynamicLibrary* adynamicLibrary_open( const char* libraryName,
+ char** pError);
+
+/* Find a symbol inside a dynamic library. */
+void* adynamicLibrary_findSymbol( ADynamicLibrary* lib,
+ const char* symbolName,
+ char** pError);
+
+/* Close/unload a given dynamic library */
+void adynamicLibrary_close( ADynamicLibrary* lib );
+
+#endif /* ANDROID_UTILS_DLL_H */
diff --git a/android/utils/path.c b/android/utils/path.c
index f64e517..1bcdc4e 100644
--- a/android/utils/path.c
+++ b/android/utils/path.c
@@ -427,6 +427,61 @@ path_is_absolute( const char* path )
#endif
}
+char*
+path_get_absolute( const char* path )
+{
+ if (path_is_absolute(path)) {
+ return ASTRDUP(path);
+ }
+
+#ifdef _WIN32
+ {
+ char* result;
+ int pathLen = strlen(path);
+ int currentLen = GetCurrentDirectory(0, NULL);
+
+ if (currentLen <= 0) {
+ /* Could not get size of working directory. something is
+ * really fishy here, return a simple copy */
+ return ASTRDUP(path);
+ }
+ result = malloc(currentLen + pathLen + 2);
+
+ GetCurrentDirectory(currentLen+1, result);
+ if (currentLen == 0 || result[currentLen-1] != '\\') {
+ result[currentLen++] = '\\';
+ }
+ memcpy(result + currentLen, path, pathLen+1);
+
+ return result;
+ }
+#else
+ {
+ int pathLen = strlen(path);
+ char currentDir[PATH_MAX];
+ int currentLen;
+ char* result;
+
+ if (getcwd(currentDir, sizeof(currentDir)) == NULL) {
+ /* Could not get the current working directory. something is really
+ * fishy here, so don't do anything and return a copy */
+ return ASTRDUP(path);
+ }
+
+ /* Make a new path with <current-path>/<path> */
+ currentLen = strlen(currentDir);
+ result = malloc(currentLen + pathLen + 2);
+
+ memcpy(result, currentDir, currentLen);
+ if (currentLen == 0 || result[currentLen-1] != '/') {
+ result[currentLen++] = '/';
+ }
+ memcpy(result + currentLen, path, pathLen+1);
+
+ return result;
+ }
+#endif
+}
/** OTHER FILE UTILITIES
**
diff --git a/android/utils/path.h b/android/utils/path.h
index 419e6bf..2926e5e 100644
--- a/android/utils/path.h
+++ b/android/utils/path.h
@@ -118,6 +118,12 @@ extern char* path_basename( const char* path );
*/
extern char* path_search_exec( const char* filename );
+/* Return the absolute version of a path. If 'path' is already absolute,
+ * this will be a simple copy. Otherwise, this function will prepend the
+ * current working directory to the result.
+ */
+extern char* path_get_absolute( const char* path );
+
/** OTHER FILE UTILITIES
**
** path_empty_file() creates an empty file at a given path location.