diff --git a/LICENSE.apkenv b/LICENSE.apkenv new file mode 100644 index 0000000..6c0cf3d --- /dev/null +++ b/LICENSE.apkenv @@ -0,0 +1,28 @@ +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ diff --git a/README b/README new file mode 100644 index 0000000..b1aea1f --- /dev/null +++ b/README @@ -0,0 +1,112 @@ + +apkenv +====== + +A compatibility layer for applications packaged as .apk. + +Support website: http://thp.io/2012/apkenv/ + + +Example module and .apk +======================= + +An example module is provided in modules/trg2.c - you can use this module as a +basis to create your own modules. You can download the .apk that works with +this example module from: + + http://thp.io/2011/trg2/ + + +softfp vs. hardfp +================= + +Android is softfp. +Maemo 5 is softfp. +MeeGo 1.2 Harmattan is hardfp. + +softfp and hardfp differ in the way functions with floating point arguments +get called. Trying to call a hardfp function with the softfp calling +convention will not work and likely result in a crash or worse. To avoid +this, you can add an attribute to function declarations to make sure that +the function accepts its parameters using the softfp calling convention, +like this: + + __attribute__((pcs("aapcs"))) + +There's a convenience #define in apkenv.h called "SOFTFP" with which you can +decorate all functions that are either in a native library (i.e. in +modules/) or that will be called from the native library (i.e. in compat/). +Please note that in theory this attribute is only required on functions that +pass float values in the arguments, but do it always to save you some +headaches. + + +Debugging crashes +================= + +First of all, enable debugging in the makefile (set DEBUG=1). Then rebuild +to get a debug build with lots of debug output. You can then check which +symbols get mapped from where at the linker phase (e.g. apkenv x.apk | grep +'from libc') - in general, most libc functions must be mapped in order to +avoid problems (e.g. stdio functions don't work in Bionic libc, so we have +to hack around these issues - the same is true for memory (de-)allocation, +etc..). + +When you have all relevant functions mapped, ltrace'ing apkenv can help you +find the library function in which it crashes - this will not list functions +from Bionic libs, but only from your system libraries (another reason why it +is usually a good idea to map system-level functions). + + +Documentation +============= + +JNI Invocation API +http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/invocation.html + +JNI Functions +http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html + +JNI Types and Data Structures +http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/types.html + +GCC Function Attributes +http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html + +ARM Hard Float Point: VFP Comparison +http://wiki.debian.org/ArmHardFloatPort/VfpComparison + +Android MotionEvent +http://developer.android.com/reference/android/view/MotionEvent.html + + +Third Party Code +================ + +All code written by me (thp) for apkenv is licensed under a simplified BSD +license (see LICENSE.apkenv). However, code from third parties might be +licensed under a different license, and have different copyright holders: + +apklib/unzip.{c,h}, apklib/ioapi.{c,h}: + The MiniZip project - http://www.winimage.com/zLibDll/minizip.html + Copyright (C) 1998-2010 Gilles Vollant (minizip) + Copyright (C) 2007-2008 Even Rouault + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + +apklib/ioapi_mem.c: + ioapi implementation for accessing .zip files in memory + Copyright (C) 1998-2003 Gilles Vollant + Copyright (C) 2003 Justin Fletcher + +linker/*: + The Android Bionic Linker + The Android Bionic C Library + Copyright (c) 2005-2008, The Android Open Source Project + +jni/jni.h: + libnativehelper: Support functions for Android's class libraries + Copyright (C) 2006 The Android Open Source Project + +compat/hooks.c, compat/pthread_wrapper.c: + pthread wrapper implementation based on code from libhybris + Copyright (C) 2012 Carsten Munk + diff --git a/apkenv.c b/apkenv.c new file mode 100644 index 0000000..eebbb43 --- /dev/null +++ b/apkenv.c @@ -0,0 +1,367 @@ + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + +#include +#include +#include +#include +#include + +#include +#ifdef FREMANTLE +# include +#endif + +#include +#include +#include + +#include "jni/jnienv.h" +#include "jni/shlib.h" +#include "apklib/apklib.h" + +#include "apkenv.h" + +/* Global application state */ +struct GlobalState global; + +void * +lookup_symbol_impl(const char *method) +{ + return jni_shlib_resolve(&global, method); +} + +void +foreach_file_impl(const char *prefix, apk_for_each_file_callback callback) +{ + apk_for_each_file(global.apklib_handle, prefix, callback); +} + +int +read_file_impl(const char *filename, char **buffer, size_t *size) +{ + return (apk_read_file(global.apklib_handle, + filename, buffer, size) == APK_OK); +} + +void register_module(struct SupportModule *module) +{ + struct SupportModule **current = &(global.support_modules); + + while ((*current) != NULL) { + if ((*current)->priority < module->priority) { + break; + } + current = &((*current)->next); + } + + module->next = *current; + *current = module; +} + +void load_module(const char *filename) +{ + void *dl = dlopen(filename, RTLD_LAZY); + if (dl == NULL) { + printf("Cannot load module: %s\n", filename); + return; + } + + struct SupportModule *module = calloc(1, sizeof(struct SupportModule)); + module->global = &global; + module->filename = strdup(filename); + + apkenv_module_init_t module_init = (apkenv_module_init_t)dlsym(dl, + APKENV_MODULE_INIT); + + if (module_init != NULL) { + int version = module_init(APKENV_MODULE_VERSION, module); + switch (version) { + case 0: + printf("Cannot init module: %s\n", filename); + break; + case APKENV_MODULE_VERSION: + printf("Loaded module: %s (%d)\n", filename, module->priority); + register_module(module); + return; + default: + printf("Wrong module ABI version: %x (need %x)\n", + version, APKENV_MODULE_VERSION); + break; + } + } else { + printf("Cannot find %s(): %s\n", APKENV_MODULE_INIT, filename); + } + + free(module->filename); + free(module); + dlclose(dl); +} + +void load_modules(const char *dirname) +{ + DIR *dir = opendir(dirname); + assert(dir != NULL); + + char tmp[PATH_MAX]; + strcpy(tmp, dirname); + strcat(tmp, "/"); + char *filename = tmp + strlen(dirname) + 1; + + struct dirent *ent; + while ((ent = readdir(dir)) != NULL) { + int len = strlen(ent->d_name) - strlen(APKENV_MODULE_SUFFIX); + if (len > 0) { + char *suffix = ent->d_name + len; + if (strcmp(suffix, APKENV_MODULE_SUFFIX) == 0) { + strcpy(filename, ent->d_name); + load_module(tmp); + } + } + } + closedir(dir); +} + +void install_overrides(struct SupportModule *module) +{ + int i; + void **override, **fake; + + /* Install overrides for JNIEnv */ + override = (void**)(&(module->override_env)); + fake = (void**)(&(global.fake_env)); + for (i=0; ioverride_env)/sizeof(void*); i++) { + if (override[i]) { + fake[i] = override[i]; + } + } + + /* Install overrides for JavaVM */ + override = (void**)(&(module->override_vm)); + fake = (void**)(&(global.fake_vm)); + for (i=0; ioverride_vm)/sizeof(void*); i++) { + if (override[i]) { + fake[i] = override[i]; + } + } +} + +#define MEEGOTOUCH_BORDER 16 + +int main(int argc, char **argv) +{ + char **tmp; + + global.apkenv_executable = argv[0]; + global.apkenv_headline = APKENV_HEADLINE; + global.apkenv_copyright = APKENV_COPYRIGHT; + + printf("%s\n%s\n\n", global.apkenv_headline, global.apkenv_copyright); + + if (argc != 2) { + printf("Usage: %s \n", global.apkenv_executable); + return 1; + } + + global.lookup_symbol = lookup_symbol_impl; + global.foreach_file = foreach_file_impl; + global.read_file = read_file_impl; + jnienv_init(&global); + javavm_init(&global); + global.apk_filename = strdup(argv[1]); + global.apklib_handle = apk_open(argv[1]); + global.support_modules = NULL; + + const char *shlib = apk_get_shared_library(global.apklib_handle); + if (shlib == NULL) { + printf("Not a native APK.\n"); + return 0; + } + + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) { + printf("SDL Init failed.\n"); + return 0; + } + + SDL_Surface *screen; + + /** + * The following block looks scary, but it just creates an SDL surface + * with the right OpenGL ES context version. The block looks so scary, + * because on Fremantle, javispedro's SDL_gles is used and on Harmattan + * (where the GLES features are integrated directly into libSDL), only + * SDL is used. + **/ +#ifdef FREMANTLE +#ifdef APKENV_GLES2 + SDL_GLES_Init(SDL_GLES_VERSION_2_0); +#else /* APKENV_GLES2 */ + SDL_GLES_Init(SDL_GLES_VERSION_1_1); +#endif /* APKENV_GLES2 */ + screen = SDL_SetVideoMode(0, 0, 0, SDL_FULLSCREEN); + SDL_GLES_MakeCurrent(SDL_GLES_CreateContext()); +#else /* FREMANTLE */ +#ifdef APKENV_GLES2 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); +#else /* APKENV_GLES2 */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); +#endif /* APKENV_GLES2 */ + screen = SDL_SetVideoMode(0, 0, 0, SDL_OPENGLES | SDL_FULLSCREEN); +#endif /* FREMANTLE */ + + SDL_ShowCursor(0); + +#ifndef FREMANTLE + /* Set up swipe lock (left and right) */ + SDL_SysWMinfo wm; + SDL_VERSION(&wm.version); + SDL_GetWMInfo(&wm); + Display *dpy = wm.info.x11.display; + Atom atom = XInternAtom(dpy, "_MEEGOTOUCH_CUSTOM_REGION", False); + unsigned int region[] = { + 0, + MEEGOTOUCH_BORDER, + screen->w, + screen->h - 2*MEEGOTOUCH_BORDER, + }; + XChangeProperty(dpy, wm.info.x11.wmwindow, atom, XA_CARDINAL, 32, + PropModeReplace, (unsigned char*)region, 4); +#endif + + global.method_table = jni_shlib_find_methods(shlib); + global.jni_library = android_dlopen(shlib, RTLD_LAZY); + unlink(shlib); + if (!(global.jni_library)) { + printf("Missing library dependencies.\n"); + return 0; + } + + load_modules("."); + if (global.support_modules == NULL) { + printf("No support modules found.\n"); + } + + /* Search for a suitable module to handle the library */ + struct SupportModule *module = global.support_modules; + while (module != NULL) { + if (module->try_init(module)) { + break; + } + module = module->next; + } + + if (module == NULL) { + printf("Not supported yet, but found JNI methods:\n"); + tmp = global.method_table; + while (*tmp) { + printf(" %s\n", *tmp); + tmp++; + } + goto finish; + } + + global.active_module = module; + printf("Using module: %s\n", module->filename); + install_overrides(module); + + struct stat st; + if (stat(DATA_DIRECTORY_BASE, &st) != 0) { + mkdir(DATA_DIRECTORY_BASE, 0700); + } + + char data_directory[PATH_MAX]; + strcpy(data_directory, DATA_DIRECTORY_BASE); + + char *fn = strdup(global.apk_filename); + char *start = strrchr(fn, '/'); + if (start != NULL) { + start++; + } else { + start = fn; + } + strcat(data_directory, start); + strcat(data_directory, "/"); + free(fn); + + if (stat(data_directory, &st) != 0) { + mkdir(data_directory, 0700); + } + + module->init(module, screen->w, screen->h, data_directory); + + while (1) { + SDL_Event e; + while (SDL_PollEvent(&e)) { + if (e.type == SDL_MOUSEBUTTONDOWN) { + module->input(module, ACTION_DOWN, e.button.x, e.button.y, e.button.which); + } else if (e.type == SDL_MOUSEBUTTONUP) { + module->input(module, ACTION_UP, e.button.x, e.button.y, e.button.which); + } else if (e.type == SDL_MOUSEMOTION) { + module->input(module, ACTION_MOVE, e.motion.x, e.motion.y, e.motion.which); + } else if (e.type == SDL_QUIT) { + module->deinit(module); + goto finish; + } else if (e.type == SDL_ACTIVEEVENT) { + if (e.active.state == SDL_APPACTIVE && e.active.gain == 0) { + module->pause(module); + while (1) { + SDL_WaitEvent(&e); + if (e.type == SDL_ACTIVEEVENT) { + if (e.active.state == SDL_APPACTIVE && + e.active.gain == 1) { + break; + } + } else if (e.type == SDL_QUIT) { + goto finish; + } + } + module->resume(module); + } + } + } + module->update(module); +#ifdef FREMANTLE + SDL_GLES_SwapBuffers(); +#else + SDL_GL_SwapBuffers(); +#endif + } + +finish: + tmp = global.method_table; + while (*tmp) { + free(*tmp++); + } + free(global.method_table); + apk_close(global.apklib_handle); + + return 0; +} + diff --git a/apkenv.h b/apkenv.h new file mode 100644 index 0000000..0dd64a2 --- /dev/null +++ b/apkenv.h @@ -0,0 +1,116 @@ +#ifndef APKENV_H +#define APKENV_H + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + +#include "apklib/apklib.h" +#include "jni/jni.h" + +#define APKENV_NAME "apkenv" +#define APKENV_VERSION "42.1.0" +#define APKENV_WEBSITE "http://thp.io/2012/apkenv/" +#define APKENV_HEADLINE APKENV_NAME " " APKENV_VERSION " - " APKENV_WEBSITE +#define APKENV_COPYRIGHT "Copyright (c) 2012 Thomas Perl " + +struct GlobalState; +struct SupportModulePriv; + +struct SupportModule { + struct GlobalState *global; + struct SupportModulePriv *priv; + char *filename; + int priority; + + struct JNINativeInterface override_env; + struct JNIInvokeInterface override_vm; + + int (*try_init)(struct SupportModule *self); + void (*init)(struct SupportModule *self, int width, int height, const char *home); + void (*input)(struct SupportModule *self, int event, int x, int y, int finger); + void (*update)(struct SupportModule *self); + void (*deinit)(struct SupportModule *self); + void (*pause)(struct SupportModule *self); + void (*resume)(struct SupportModule *self); + + struct SupportModule *next; +}; + +typedef void *(*lookup_symbol_t)(const char *method); +typedef void (*foreach_file_t)(const char *prefix, apk_for_each_file_callback callback); +typedef int (*read_file_t)(const char *filename, char **buffer, size_t *size); + +struct GlobalState { + const char *apkenv_executable; + const char *apkenv_headline; + const char *apkenv_copyright; + + struct JNINativeInterface fake_env; + JNIEnv env; + struct JNIInvokeInterface fake_vm; + JavaVM vm; + + const char *apk_filename; + AndroidApk *apklib_handle; + + void *jni_library; + char **method_table; + + struct SupportModule *support_modules; + struct SupportModule *active_module; + + lookup_symbol_t lookup_symbol; + foreach_file_t foreach_file; + read_file_t read_file; +}; + +#define VM(global_ptr) (&((global_ptr)->vm)) +#define ENV(global_ptr) (&((global_ptr)->env)) + +#define DATA_DIRECTORY_BASE "/home/user/.apkenv/" + +/* Android MotionEvent */ +#define ACTION_DOWN 0 +#define ACTION_UP 1 +#define ACTION_MOVE 2 + +/* Attribute for softfp-calling-style functions */ +#define SOFTFP __attribute__((pcs("aapcs"))) + +/* Forward-declarations for the Bionic linker */ +void *android_dlopen(const char *filename, int flag); +void *android_dlsym(void *handle, const char *symbol); + +/* Module support */ +typedef int (*apkenv_module_init_t)(int version, struct SupportModule *module); +#define APKENV_MODULE_INIT "apkenv_module_init" +#define APKENV_MODULE_SUFFIX ".apkenv.so" +#define APKENV_MODULE_VERSION 0x010000 + +#endif /* APKENV_H */ diff --git a/apklib/apklib.c b/apklib/apklib.c new file mode 100644 index 0000000..88ef4f0 --- /dev/null +++ b/apklib/apklib.c @@ -0,0 +1,199 @@ + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + +#include +#include +#include +#include + +#include "unzip.h" +#include "ioapi_mem.h" + +#include "apklib.h" + +AndroidApk * +apk_open(const char *filename) +{ + AndroidApk *apk = calloc(1, sizeof(AndroidApk)); + apk->zip = unzOpen(filename); + return apk; +} + +char * +apk_get_shared_library(AndroidApk *apk) +{ + assert(apk != NULL); + + char filename[PATH_MAX]; + FILE *result = NULL; + char buf[64*1024]; + int read; + + if (unzGoToFirstFile(apk->zip) != UNZ_OK) { + return NULL; + } + + do { + if (unzGetCurrentFileInfo(apk->zip, NULL, filename, sizeof(filename), + NULL, 0, NULL, 0) == UNZ_OK) { + if (memcmp(filename, "lib/armeabi", 11) == 0) { + if (unzOpenCurrentFile(apk->zip) == UNZ_OK) { + strcpy(filename, "/home/user/.apkenv-XXXXXX"); + int fd = mkstemp(filename); + result = fdopen(fd, "w+b"); + while (!unzeof(apk->zip)) { + read = unzReadCurrentFile(apk->zip, buf, sizeof(buf)); + if (read) { + assert(fwrite(buf, read, 1, result) == 1); + } + } + fclose(result); + unzCloseCurrentFile(apk->zip); + return strdup(filename); + } + break; + } + } + } while (unzGoToNextFile(apk->zip) == UNZ_OK); + + return NULL; +} + +enum ApkResult +apk_uncompress_internal(AndroidApk *apk, char **buffer, size_t *size) +{ + zlib_filefunc_def filefunc; + fill_memory_filefunc(&filefunc); + char *old_buffer = *buffer; + char path[1024]; + sprintf(path, "%x+%x", *buffer, *size); + + /* Decompress a single file in a .zip from memory */ + unz_file_info info; + unzFile *unz = unzOpen2(path, &filefunc); + unzGoToFirstFile(unz); + unzGetCurrentFileInfo(unz, &info, NULL, 0, NULL, 0, NULL, 0); + *size = info.uncompressed_size; + *buffer = malloc(*size); + unzOpenCurrentFile(unz); + unzReadCurrentFile(unz, *buffer, *size); + unzCloseCurrentFile(unz); + unzClose(unz); + free(old_buffer); + + return APK_OK; +} + +enum ApkResult +apk_read_file(AndroidApk *apk, const char *filename, char **buffer, size_t *size) +{ + assert(apk != NULL); + + unz_file_info info; + int read; + char *write_pos; + int remaining; + int is_zipfile = 0; + + if (unzLocateFile(apk->zip, filename, 2) != UNZ_OK) { + char *filename2 = malloc(strlen(filename) + strlen(".zip") + 1); + sprintf(filename2, "%s.zip", filename); + if (unzLocateFile(apk->zip, filename2, 2) == UNZ_OK) { + is_zipfile = 1; + } else { + return APK_ERROR; + } + } + + if (unzGetCurrentFileInfo(apk->zip, &info, NULL, 0, + NULL, 0, NULL, 0) == UNZ_OK) { + if (unzOpenCurrentFile(apk->zip) == UNZ_OK) { + *size = info.uncompressed_size; + *buffer = malloc(*size); + + write_pos = *buffer; + remaining = *size; + while (!unzeof(apk->zip)) { + read = unzReadCurrentFile(apk->zip, write_pos, remaining); + write_pos += read; + remaining -= read; + } + unzCloseCurrentFile(apk->zip); + + if (is_zipfile) { + return apk_uncompress_internal(apk, buffer, size); + } + return APK_OK; + } + } + + return APK_ERROR; +} + +void +apk_for_each_file(AndroidApk *apk, const char *prefix, + apk_for_each_file_callback callback) +{ + assert(apk != NULL); + + unz_file_info info; + char filename[PATH_MAX]; + char *buf; + size_t size; + + if (unzGoToFirstFile(apk->zip) != UNZ_OK) { + return; + } + + do { + if (unzGetCurrentFileInfo(apk->zip, &info, filename, sizeof(filename), + NULL, 0, NULL, 0) == UNZ_OK) { + if (memcmp(filename, prefix, strlen(prefix)) == 0) { + if (unzOpenCurrentFile(apk->zip) == UNZ_OK) { + size = info.uncompressed_size; + buf = malloc(info.uncompressed_size); + size = unzReadCurrentFile(apk->zip, buf, + info.uncompressed_size); + callback(filename, buf, size); + free(buf); + unzCloseCurrentFile(apk->zip); + } + } + } + } while (unzGoToNextFile(apk->zip) == UNZ_OK); +} + +void +apk_close(AndroidApk *apk) +{ + assert(apk != NULL); + unzClose(apk->zip); +} + diff --git a/apklib/apklib.h b/apklib/apklib.h new file mode 100644 index 0000000..65e4a04 --- /dev/null +++ b/apklib/apklib.h @@ -0,0 +1,54 @@ +#ifndef APKLIB_H +#define APKLIB_H + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + +#include "unzip.h" + +struct AndroidApk { + unzFile *zip; +}; +typedef struct AndroidApk AndroidApk; + +enum ApkResult { + APK_OK, + APK_ERROR, +}; + +typedef void (*apk_for_each_file_callback)(const char *filename, char *buffer, size_t size); + +/* apklib.c */ +AndroidApk *apk_open(const char *filename); +char *apk_get_shared_library(AndroidApk *apk); +enum ApkResult apk_read_file(AndroidApk *apk, const char *filename, char **buffer, size_t *size); +void apk_for_each_file(AndroidApk *apk, const char *prefix, apk_for_each_file_callback callback); +void apk_close(AndroidApk *apk); + +#endif /* APKLIB_H */ diff --git a/apklib/ioapi.c b/apklib/ioapi.c new file mode 100644 index 0000000..7f5c191 --- /dev/null +++ b/apklib/ioapi.c @@ -0,0 +1,247 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + +*/ + +#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS))) + #define _CRT_SECURE_NO_WARNINGS +#endif + +#if defined(__APPLE__) || defined(IOAPI_NO_64) +// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions +#define FOPEN_FUNC(filename, mode) fopen(filename, mode) +#define FTELLO_FUNC(stream) ftello(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) +#else +#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) +#define FTELLO_FUNC(stream) ftello64(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) +#endif + + +#include "ioapi.h" + +voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) +{ + if (pfilefunc->zfile_func64.zopen64_file != NULL) + return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); + else + { + return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode); + } +} + +long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) +{ + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); + else + { + uLong offsetTruncated = (uLong)offset; + if (offsetTruncated != offset) + return -1; + else + return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); + } +} + +ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) +{ + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); + else + { + uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); + if ((tell_uLong) == MAXU32) + return (ZPOS64_T)-1; + else + return tell_uLong; + } +} + +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) +{ + p_filefunc64_32->zfile_func64.zopen64_file = NULL; + p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; + p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; + p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; + p_filefunc64_32->zfile_func64.ztell64_file = NULL; + p_filefunc64_32->zfile_func64.zseek64_file = NULL; + p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; + p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; + p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; + p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; +} + + + +static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); +static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); +static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); +static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); +static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); + +static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen(filename, mode_fopen); + return file; +} + +static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = FOPEN_FUNC((const char*)filename, mode_fopen); + return file; +} + + +static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) +{ + uLong ret; + ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) +{ + uLong ret; + ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) +{ + long ret; + ret = ftell((FILE *)stream); + return ret; +} + + +static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) +{ + ZPOS64_T ret; + ret = FTELLO_FUNC((FILE *)stream); + return ret; +} + +static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + if (fseek((FILE *)stream, offset, fseek_origin) != 0) + ret = -1; + return ret; +} + +static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + + if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0) + ret = -1; + + return ret; +} + + +static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) +{ + int ret; + ret = fclose((FILE *)stream); + return ret; +} + +static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) +{ + int ret; + ret = ferror((FILE *)stream); + return ret; +} + +void fill_fopen_filefunc (pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def; +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = fopen64_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell64_file = ftell64_file_func; + pzlib_filefunc_def->zseek64_file = fseek64_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/apklib/ioapi.h b/apklib/ioapi.h new file mode 100644 index 0000000..8dcbdb0 --- /dev/null +++ b/apklib/ioapi.h @@ -0,0 +1,208 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + Changes + + Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this) + Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux. + More if/def section may be needed to support other platforms + Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows. + (but you should use iowin32.c for windows instead) + +*/ + +#ifndef _ZLIBIOAPI64_H +#define _ZLIBIOAPI64_H + +#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) + + // Linux needs this to support file operation on files larger then 4+GB + // But might need better if/def to select just the platforms that needs them. + + #ifndef __USE_FILE_OFFSET64 + #define __USE_FILE_OFFSET64 + #endif + #ifndef __USE_LARGEFILE64 + #define __USE_LARGEFILE64 + #endif + #ifndef _LARGEFILE64_SOURCE + #define _LARGEFILE64_SOURCE + #endif + #ifndef _FILE_OFFSET_BIT + #define _FILE_OFFSET_BIT 64 + #endif + +#endif + +#include +#include +#include "zlib.h" + +#if defined(USE_FILE32API) +#define fopen64 fopen +#define ftello64 ftell +#define fseeko64 fseek +#else +#ifdef __FreeBSD__ +#define fopen64 fopen +#define ftello64 ftello +#define fseeko64 fseeko +#endif +#ifdef _MSC_VER + #define fopen64 fopen + #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC))) + #define ftello64 _ftelli64 + #define fseeko64 _fseeki64 + #else // old MSC + #define ftello64 ftell + #define fseeko64 fseek + #endif +#endif +#endif + +/* +#ifndef ZPOS64_T + #ifdef _WIN32 + #define ZPOS64_T fpos_t + #else + #include + #define ZPOS64_T uint64_t + #endif +#endif +*/ + +#ifdef HAVE_MINIZIP64_CONF_H +#include "mz64conf.h" +#endif + +/* a type choosen by DEFINE */ +#ifdef HAVE_64BIT_INT_CUSTOM +typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; +#else +#ifdef HAS_STDINT_H +#include "stdint.h" +typedef uint64_t ZPOS64_T; +#else + +/* Maximum unsigned 32-bit value used as placeholder for zip64 */ +#define MAXU32 0xffffffff + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef unsigned __int64 ZPOS64_T; +#else +typedef unsigned long long int ZPOS64_T; +#endif +#endif +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) + #define ZCALLBACK CALLBACK + #else + #define ZCALLBACK + #endif +#endif + + + + +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); + +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); + + +/* here is the "old" 32 bits structure structure */ +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + +typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); + +typedef struct zlib_filefunc64_def_s +{ + open64_file_func zopen64_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell64_file_func ztell64_file; + seek64_file_func zseek64_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc64_def; + +void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +/* now internal definition, only for zip.c and unzip.h */ +typedef struct zlib_filefunc64_32_def_s +{ + zlib_filefunc64_def zfile_func64; + open_file_func zopen32_file; + tell_file_func ztell32_file; + seek_file_func zseek32_file; +} zlib_filefunc64_32_def; + + +#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) +//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) +#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) + +voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); +long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); +ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); + +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); + +#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) +#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) +#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/apklib/ioapi_mem.c b/apklib/ioapi_mem.c new file mode 100644 index 0000000..4e7458f --- /dev/null +++ b/apklib/ioapi_mem.c @@ -0,0 +1,219 @@ +/* ioapi_mem.c -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + This version of ioapi is designed to access memory rather than files. + We do use a region of memory to put data in to and take it out of. We do + not have auto-extending buffers and do not inform anyone else that the + data has been written. It is really intended for accessing a zip archive + embedded in an application such that I can write an installer with no + external files. Creation of archives has not been attempted, although + parts of the framework are present. + + Based on Unzip ioapi.c version 0.22, May 19th, 2003 + + Copyright (C) 1998-2003 Gilles Vollant + (C) 2003 Justin Fletcher + + This file is under the same license as the Unzip tool it is distributed + with. +*/ + + +#include +#include +#include + +#include "zlib.h" +#include "ioapi.h" + + + +voidpf ZCALLBACK fopen_mem_func OF(( + voidpf opaque, + const char* filename, + int mode)); + +uLong ZCALLBACK fread_mem_func OF(( + voidpf opaque, + voidpf stream, + void* buf, + uLong size)); + +uLong ZCALLBACK fwrite_mem_func OF(( + voidpf opaque, + voidpf stream, + const void* buf, + uLong size)); + +long ZCALLBACK ftell_mem_func OF(( + voidpf opaque, + voidpf stream)); + +long ZCALLBACK fseek_mem_func OF(( + voidpf opaque, + voidpf stream, + uLong offset, + int origin)); + +int ZCALLBACK fclose_mem_func OF(( + voidpf opaque, + voidpf stream)); + +int ZCALLBACK ferror_mem_func OF(( + voidpf opaque, + voidpf stream)); + + +typedef struct ourmemory_s { + char *base; /* Base of the region of memory we're using */ + uLong size; /* Size of the region of memory we're using */ + uLong limit; /* Furthest we've written */ + uLong cur_offset; /* Current offset in the area */ +} ourmemory_t; + +voidpf ZCALLBACK fopen_mem_func (opaque, filename, mode) + voidpf opaque; + const char* filename; + int mode; +{ + ourmemory_t *mem = malloc(sizeof(*mem)); + if (mem==NULL) + return NULL; /* Can't allocate space, so failed */ + + /* Filenames are specified in the form : + * + + * This may not work where memory addresses are longer than the + * size of an int and therefore may need addressing for 64bit + * architectures + */ + if (sscanf(filename,"%x+%x",&mem->base,&mem->size)!=2) + return NULL; + + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mem->limit=0; /* When writing we start with 0 bytes written */ + else + mem->limit=mem->size; + + mem->cur_offset = 0; + + return mem; +} + + +uLong ZCALLBACK fread_mem_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + void* buf; + uLong size; +{ + ourmemory_t *mem = (ourmemory_t *)stream; + + if (size > mem->size - mem->cur_offset) + size = mem->size - mem->cur_offset; + + memcpy(buf, mem->base + mem->cur_offset, size); + mem->cur_offset+=size; + + return size; +} + + +uLong ZCALLBACK fwrite_mem_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + const void* buf; + uLong size; +{ + ourmemory_t *mem = (ourmemory_t *)stream; + + if (size > mem->size - mem->cur_offset) + size = mem->size - mem->cur_offset; + + memcpy(mem->base + mem->cur_offset, buf, size); + mem->cur_offset+=size; + if (mem->cur_offset > mem->limit) + mem->limit = mem->cur_offset; + + return size; +} + +long ZCALLBACK ftell_mem_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + ourmemory_t *mem = (ourmemory_t *)stream; + + return mem->cur_offset; +} + +long ZCALLBACK fseek_mem_func (opaque, stream, offset, origin) + voidpf opaque; + voidpf stream; + uLong offset; + int origin; +{ + ourmemory_t *mem = (ourmemory_t *)stream; + uLong new_pos; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + new_pos = mem->cur_offset + offset; + break; + case ZLIB_FILEFUNC_SEEK_END : + new_pos = mem->limit + offset; + break; + case ZLIB_FILEFUNC_SEEK_SET : + new_pos = offset; + break; + default: return -1; + } + + if (new_pos > mem->size) + return 1; /* Failed to seek that far */ + + if (new_pos > mem->limit) + memset(mem->base + mem->limit, 0, new_pos - mem->limit); + + mem->cur_offset = new_pos; + return 0; +} + +int ZCALLBACK fclose_mem_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + ourmemory_t *mem = (ourmemory_t *)stream; + + /* Note that once we've written to the buffer we don't tell anyone + about it here. Probably the opaque handle could be used to inform + some other component of how much data was written. + + This, and other aspects of writing through this interface, has + not been tested. + */ + + free (mem); + return 0; +} + +int ZCALLBACK ferror_mem_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + //ourmemory_t *mem = (ourmemory_t *)stream; + /* We never return errors */ + return 0; +} + +void fill_memory_filefunc (pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def; +{ + pzlib_filefunc_def->zopen_file = fopen_mem_func; + pzlib_filefunc_def->zread_file = fread_mem_func; + pzlib_filefunc_def->zwrite_file = fwrite_mem_func; + pzlib_filefunc_def->ztell_file = ftell_mem_func; + pzlib_filefunc_def->zseek_file = fseek_mem_func; + pzlib_filefunc_def->zclose_file = fclose_mem_func; + pzlib_filefunc_def->zerror_file = ferror_mem_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/apklib/ioapi_mem.h b/apklib/ioapi_mem.h new file mode 100644 index 0000000..8215b14 --- /dev/null +++ b/apklib/ioapi_mem.h @@ -0,0 +1,7 @@ +#ifndef IOAPI_MEM_H +#define IOAPI_MEM_H + +/* ioapi_mem.c */ +void fill_memory_filefunc(zlib_filefunc_def *pzlib_filefunc_def); + +#endif /* IOAPI_MEM_H */ diff --git a/apklib/unzip.c b/apklib/unzip.c new file mode 100644 index 0000000..affad4b --- /dev/null +++ b/apklib/unzip.c @@ -0,0 +1,2125 @@ +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + + ------------------------------------------------------------------------------------ + Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of + compatibility with older software. The following is from the original crypt.c. + Code woven in by Terry Thorsen 1/2003. + + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html + + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + ------------------------------------------------------------------------------------ + + Changes in unzip.c + + 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos + 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz* + 2007-2008 - Even Rouault - Remove old C style function prototypes + 2007-2008 - Even Rouault - Add unzip support for ZIP64 + + Copyright (C) 2007-2008 Even Rouault + + + Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). + Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G + should only read the compressed/uncompressed size from the Zip64 format if + the size from normal header was 0xFFFFFFFF + Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant + Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required) + Patch created by Daniel Borca + + Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer + + Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson + +*/ + + +#include +#include +#include + +#ifndef NOUNCRYPT + #define NOUNCRYPT +#endif + +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO +# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# define CASESENSITIVITYDEFAULT_NO +# endif +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + +const char unz_copyright[] = + " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info64_internal_s +{ + ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ +} unz_file_info64_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + +#ifdef HAVE_BZIP2 + bz_stream bstream; /* bzLib stream structure for bziped */ +#endif + + ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + ZPOS64_T offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/ + ZPOS64_T total_out_64; + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ + ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + zlib_filefunc64_32_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip64_read_info_s; + + +/* unz64_s contain internal information about the zipfile +*/ +typedef struct +{ + zlib_filefunc64_32_def z_filefunc; + int is64bitOpenFunction; + voidpf filestream; /* io structore of the zipfile */ + unz_global_info64 gi; /* public global information */ + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + ZPOS64_T num_file; /* number of the current file in the zipfile*/ + ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/ + ZPOS64_T current_file_ok; /* flag about the usability of the current file*/ + ZPOS64_T central_pos; /* position of the beginning of the central dir*/ + + ZPOS64_T size_central_dir; /* size of the central directory */ + ZPOS64_T offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info64 cur_file_info; /* public info about the current file in zip*/ + unz_file_info64_internal cur_file_info_internal; /* private info about it*/ + file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ + int encrypted; + + int isZip64; + +# ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; +# endif +} unz64_s; + + +#ifndef NOUNCRYPT +#include "crypt.h" +#endif + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ + + +local int unz64local_getByte OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi) +{ + unsigned char c; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unz64local_getShort OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong64 OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX)); + + +local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX) +{ + ZPOS64_T x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (ZPOS64_T)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<8; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<16; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<24; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<32; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<40; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<48; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<56; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, + const char* fileName2, + int iCaseSensitivity) + +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); +local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + + +/* + Locate the Central directory 64 of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T unz64local_SearchCentralDir64 OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream)); + +local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + uLong uL; + ZPOS64_T relativeOffset; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + if (uPosFound == 0) + return 0; + + /* Zip64 end of central directory locator */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature, already checked */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + + /* number of the disk with the start of the zip64 end of central directory */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + if (uL != 0) + return 0; + + /* relative offset of the zip64 end of central directory record */ + if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK) + return 0; + + /* total number of disks */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + if (uL != 1) + return 0; + + /* Goto end of central directory record */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + + if (uL != 0x06064b50) + return 0; + + return relativeOffset; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer + "zlib/zlib114.zip". + If the zipfile cannot be opened (file doesn't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +local unzFile unzOpenInternal (const void *path, + zlib_filefunc64_32_def* pzlib_filefunc64_32_def, + int is64bitOpenFunction) +{ + unz64_s us; + unz64_s *s; + ZPOS64_T central_pos; + uLong uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + ZPOS64_T number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + us.z_filefunc.zseek32_file = NULL; + us.z_filefunc.ztell32_file = NULL; + if (pzlib_filefunc64_32_def==NULL) + fill_fopen64_filefunc(&us.z_filefunc.zfile_func64); + else + us.z_filefunc = *pzlib_filefunc64_32_def; + us.is64bitOpenFunction = is64bitOpenFunction; + + + + us.filestream = ZOPEN64(us.z_filefunc, + path, + ZLIB_FILEFUNC_MODE_READ | + ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) + return NULL; + + central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream); + if (central_pos) + { + uLong uS; + ZPOS64_T uL64; + + us.isZip64 = 1; + + if (ZSEEK64(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* size of zip64 end of central directory record */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK) + err=UNZ_ERRNO; + + /* version made by */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) + err=UNZ_ERRNO; + + /* version needed to extract */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central directory on this disk */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central directory */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + us.gi.size_comment = 0; + } + else + { + central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream); + if (central_pos==0) + err=UNZ_ERRNO; + + us.isZip64 = 0; + + if (ZSEEK64(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.gi.number_entry = uL; + + /* total number of entries in the central dir */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + number_entry_CD = uL; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.size_central_dir = uL; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.offset_central_dir = uL; + + /* zipfile comment length */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + } + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + ZCLOSE64(s->z_filefunc, s->filestream); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + +extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + /* to do : check if number_entry is not truncated */ + pglobal_info32->number_entry = (uLong)s->gi.number_entry; + pglobal_info32->size_comment = s->gi.size_comment; + return UNZ_OK; +} +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) +{ + ZPOS64_T uDate; + uDate = (ZPOS64_T)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unz64local_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unz64local_GetCurrentFileInfoInternal (unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize) +{ + unz64_s* s; + unz_file_info64 file_info; + unz_file_info64_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + uLong uL; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (ZSEEK64(s->z_filefunc, s->filestream, + s->pos_in_central_dir+s->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + { + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + } + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info.compressed_size = uL; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info.uncompressed_size = uL; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + // relative offset of local header + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info_internal.offset_curfile = uL; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + // Read extrafield + if ((err==UNZ_OK) && (extraField!=NULL)) + { + ZPOS64_T uSizeRead ; + if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + + lSeek += file_info.size_file_extra - (uLong)uSizeRead; + } + else + lSeek += file_info.size_file_extra; + + + if ((err==UNZ_OK) && (file_info.size_file_extra != 0)) + { + uLong acc = 0; + + // since lSeek now points to after the extra field we need to move back + lSeek -= file_info.size_file_extra; + + if (lSeek!=0) + { + if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + while(acc < file_info.size_file_extra) + { + uLong headerId; + uLong dataSize; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK) + err=UNZ_ERRNO; + + /* ZIP64 extra fields */ + if (headerId == 0x0001) + { + uLong uL; + + if(file_info.uncompressed_size == MAXU32) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info.compressed_size == MAXU32) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info_internal.offset_curfile == MAXU32) + { + /* Relative Header offset */ + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info.disk_num_start == MAXU32) + { + /* Disk Start Number */ + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + } + + } + else + { + if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0) + err=UNZ_ERRNO; + } + + acc += 2 + 2 + dataSize; + } + } + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file, + unz_file_info64 * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) +{ + return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, + unz_file_info * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) +{ + int err; + unz_file_info64 file_info64; + err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); + if ((err==UNZ_OK) && (pfile_info != NULL)) + { + pfile_info->version = file_info64.version; + pfile_info->version_needed = file_info64.version_needed; + pfile_info->flag = file_info64.flag; + pfile_info->compression_method = file_info64.compression_method; + pfile_info->dosDate = file_info64.dosDate; + pfile_info->crc = file_info64.crc; + + pfile_info->size_filename = file_info64.size_filename; + pfile_info->size_file_extra = file_info64.size_file_extra; + pfile_info->size_file_comment = file_info64.size_file_comment; + + pfile_info->disk_num_start = file_info64.disk_num_start; + pfile_info->internal_fa = file_info64.internal_fa; + pfile_info->external_fa = file_info64.external_fa; + + pfile_info->tmu_date = file_info64.tmu_date, + + + pfile_info->compressed_size = (uLong)file_info64.compressed_size; + pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size; + + } + return err; +} +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (unzFile file) +{ + int err=UNZ_OK; + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (unzFile file) +{ + unz64_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) +{ + unz64_s* s; + int err; + + /* We remember the 'current' position in the file so that we can jump + * back there if we fail. + */ + unz_file_info64 cur_file_infoSaved; + unz_file_info64_internal cur_file_info_internalSaved; + ZPOS64_T num_fileSaved; + ZPOS64_T pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + cur_file_infoSaved = s->cur_file_info; + cur_file_info_internalSaved = s->cur_file_info_internal; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + err = unzGetCurrentFileInfo64(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (err == UNZ_OK) + { + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + } + + /* We failed, so restore the state of the 'current file' to where we + * were. + */ + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + s->cur_file_info = cur_file_infoSaved; + s->cur_file_info_internal = cur_file_info_internalSaved; + return err; +} + + +/* +/////////////////////////////////////////// +// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) +// I need random access +// +// Further optimization could be realized by adding an ability +// to cache the directory in memory. The goal being a single +// comprehensive file read to put the file I need in a memory. +*/ + +/* +typedef struct unz_file_pos_s +{ + ZPOS64_T pos_in_zip_directory; // offset in file + ZPOS64_T num_of_file; // # of file +} unz_file_pos; +*/ + +extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) +{ + unz64_s* s; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos) +{ + unz64_file_pos file_pos64; + int err = unzGetFilePos64(file,&file_pos64); + if (err==UNZ_OK) + { + file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory; + file_pos->num_of_file = (uLong)file_pos64.num_of_file; + } + return err; +} + +extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) +{ + unz64_s* s; + int err; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos) +{ + unz64_file_pos file_pos64; + if (file_pos == NULL) + return UNZ_PARAMERROR; + + file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory; + file_pos64.num_of_file = file_pos->num_of_file; + return unzGoToFilePos64(file,&file_pos64); +} + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// +*/ + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, + ZPOS64_T * poffset_local_extrafield, + uInt * psize_local_extrafield) +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + { + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + } + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, + int* level, int raw, const char* password) +{ + int err=UNZ_OK; + uInt iSizeVar; + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + ZPOS64_T offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ +# ifndef NOUNCRYPT + char source[12]; +# else + if (password != NULL) + return UNZ_PARAMERROR; +# endif + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + pfile_in_zip_read_info->raw=raw; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if (method!=NULL) + *method = (int)s->cur_file_info.compression_method; + + if (level!=NULL) + { + *level = 6; + switch (s->cur_file_info.flag & 0x06) + { + case 6 : *level = 1; break; + case 4 : *level = 2; break; + case 2 : *level = 9; break; + } + } + + if ((s->cur_file_info.compression_method!=0) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ + (s->cur_file_info.compression_method!=Z_DEFLATED)) + + err=UNZ_BADZIPFILE; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->total_out_64=0; + pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream=s->filestream; + pfile_in_zip_read_info->z_filefunc=s->z_filefunc; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw)) + { +#ifdef HAVE_BZIP2 + pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0; + pfile_in_zip_read_info->bstream.bzfree = (free_func)0; + pfile_in_zip_read_info->bstream.opaque = (voidpf)0; + pfile_in_zip_read_info->bstream.state = (voidpf)0; + + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } +#else + pfile_in_zip_read_info->raw=1; +#endif + } + else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw)) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = 0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=Z_DEFLATED; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + s->encrypted = 0; + +# ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = get_crc_table(); + init_keys(password,s->keys,s->pcrc_32_tab); + if (ZSEEK64(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + + s->pfile_in_zip_read->byte_before_the_zipfile, + SEEK_SET)!=0) + return UNZ_INTERNALERROR; + if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12) + return UNZ_INTERNALERROR; + + for (i = 0; i<12; i++) + zdecode(s->keys,s->pcrc_32_tab,source[i]); + + s->pfile_in_zip_read->pos_in_zipfile+=12; + s->encrypted=1; + } +# endif + + + return UNZ_OK; +} + +extern int ZEXPORT unzOpenCurrentFile (unzFile file) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw) +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/** Addition for GDAL : START */ + +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + s=(unz64_s*)file; + if (file==NULL) + return 0; //UNZ_PARAMERROR; + pfile_in_zip_read_info=s->pfile_in_zip_read; + if (pfile_in_zip_read_info==NULL) + return 0; //UNZ_PARAMERROR; + return pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile; +} + +/** Addition for GDAL : END */ + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) +{ + int err=UNZ_OK; + uInt iRead = 0; + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->read_buffer == NULL) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && + (!(pfile_in_zip_read_info->raw))) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + if (ZREAD64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer, + uReadThis)!=uReadThis) + return UNZ_ERRNO; + + +# ifndef NOUNCRYPT + if(s->encrypted) + { + uInt i; + for(i=0;iread_buffer[i] = + zdecode(s->keys,s->pcrc_32_tab, + pfile_in_zip_read_info->read_buffer[i]); + } +# endif + + + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) + { + uInt uDoCopy,i ; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (iRead==0) ? UNZ_EOF : iRead; + + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy; + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) + { +#ifdef HAVE_BZIP2 + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + + pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in; + pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in; + pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in; + pfile_in_zip_read_info->bstream.total_in_hi32 = 0; + pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out; + pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out; + pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out; + pfile_in_zip_read_info->bstream.total_out_hi32 = 0; + + uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32; + bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out; + + err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream); + + uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); + pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in; + pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in; + pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32; + pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out; + pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out; + pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32; + + if (err==BZ_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=BZ_OK) + break; +#endif + } // end Z_BZIP2ED + else + { + ZPOS64_T uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + ZPOS64_T uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) + err = Z_DATA_ERROR; + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + +extern ZPOS64_T ZEXPORT unztell64 (unzFile file) +{ + + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return (ZPOS64_T)-1; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return (ZPOS64_T)-1; + + return pfile_in_zip_read_info->total_out_64; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* +Read extra field from the current file (opened by unzOpenCurrentFile) +This is the local-header version of the extra field (sometimes, there is +more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + uInt read_now; + ZPOS64_T size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (ZREAD64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + buf,read_now)!=read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (unzFile file) +{ + int err=UNZ_OK; + + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) + inflateEnd(&pfile_in_zip_read_info->stream); +#ifdef HAVE_BZIP2 + else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED) + BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream); +#endif + + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf) +{ + unz64_s* s; + uLong uReadThis ; + if (file==NULL) + return (int)UNZ_PARAMERROR; + s=(unz64_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + +/* Additions by RX '2004 */ +extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) +{ + unz64_s* s; + + if (file==NULL) + return 0; //UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file==s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +extern uLong ZEXPORT unzGetOffset (unzFile file) +{ + ZPOS64_T offset64; + + if (file==NULL) + return 0; //UNZ_PARAMERROR; + offset64 = unzGetOffset64(file); + return (uLong)offset64; +} + +extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) +{ + unz64_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) +{ + return unzSetOffset64(file,pos); +} diff --git a/apklib/unzip.h b/apklib/unzip.h new file mode 100644 index 0000000..3183968 --- /dev/null +++ b/apklib/unzip.h @@ -0,0 +1,437 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + --------------------------------------------------------------------------------- + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + --------------------------------------------------------------------------------- + + Changes + + See header of unzip64.c + +*/ + +#ifndef _unz64_H +#define _unz64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#ifdef HAVE_BZIP2 +#include "bzlib.h" +#endif + +#define Z_BZIP2ED 12 + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info64_s +{ + ZPOS64_T number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info64; + +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info64_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + ZPOS64_T compressed_size; /* compressed size 8 bytes */ + ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info64; + +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +extern unzFile ZEXPORT unzOpen64 OF((const void *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. + the "64" function take a const void* pointer, because the path is just the + value passed to the open64_file_func callback. + Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path + is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* + does not describe the reality +*/ + + +extern unzFile ZEXPORT unzOpen2 OF((const char *path, + zlib_filefunc_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, + zlib_filefunc64_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unz64Open, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); + +extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, + unz_global_info64 *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +typedef struct unz64_file_pos_s +{ + ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */ + ZPOS64_T num_of_file; /* # of file */ +} unz64_file_pos; + +extern int ZEXPORT unzGetFilePos64( + unzFile file, + unz64_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos64( + unzFile file, + const unz64_file_pos* file_pos); + +/* ****************************************** */ + +extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, + unz_file_info64 *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + + +/** Addition for GDAL : START */ + +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); + +/** Addition for GDAL : END */ + + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, + const char* password)); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, + int* method, + int* level, + int raw)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, + int* method, + int* level, + int raw, + const char* password)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); + +extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file); +extern uLong ZEXPORT unzGetOffset (unzFile file); + +/* Set the current file offset */ +extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos); +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _unz64_H */ diff --git a/compat/README b/compat/README new file mode 100644 index 0000000..e868afd --- /dev/null +++ b/compat/README @@ -0,0 +1,7 @@ + +Some of these wrapper functions have been created with the wrapper generator +(and sometimes subsequently edited/modified) - using the wrapper generator +might be easier (and less error prone) than writing wrapper code by hand: + + https://github.com/harmattan/apkenv-wrapper-generator + diff --git a/compat/gles2_mapping.h b/compat/gles2_mapping.h new file mode 100644 index 0000000..b4055e2 --- /dev/null +++ b/compat/gles2_mapping.h @@ -0,0 +1,162 @@ +#ifdef APKENV_GLES2 +{"glActiveTexture", my_glActiveTexture}, +{"glAttachShader", my_glAttachShader}, +{"glBindAttribLocation", my_glBindAttribLocation}, +{"glBindBuffer", my_glBindBuffer}, +{"glBindFramebuffer", my_glBindFramebuffer}, +{"glBindRenderbuffer", my_glBindRenderbuffer}, +{"glBindTexture", my_glBindTexture}, +{"glBlendColor", my_glBlendColor}, +{"glBlendEquation", my_glBlendEquation}, +{"glBlendEquationSeparate", my_glBlendEquationSeparate}, +{"glBlendFunc", my_glBlendFunc}, +{"glBlendFuncSeparate", my_glBlendFuncSeparate}, +{"glBufferData", my_glBufferData}, +{"glBufferSubData", my_glBufferSubData}, +{"glCheckFramebufferStatus", my_glCheckFramebufferStatus}, +{"glClear", my_glClear}, +{"glClearColor", my_glClearColor}, +{"glClearDepthf", my_glClearDepthf}, +{"glClearStencil", my_glClearStencil}, +{"glColorMask", my_glColorMask}, +{"glCompileShader", my_glCompileShader}, +{"glCompressedTexImage2D", my_glCompressedTexImage2D}, +{"glCompressedTexSubImage2D", my_glCompressedTexSubImage2D}, +{"glCopyTexImage2D", my_glCopyTexImage2D}, +{"glCopyTexSubImage2D", my_glCopyTexSubImage2D}, +{"glCreateProgram", my_glCreateProgram}, +{"glCreateShader", my_glCreateShader}, +{"glCullFace", my_glCullFace}, +{"glDeleteBuffers", my_glDeleteBuffers}, +{"glDeleteFramebuffers", my_glDeleteFramebuffers}, +{"glDeleteProgram", my_glDeleteProgram}, +{"glDeleteRenderbuffers", my_glDeleteRenderbuffers}, +{"glDeleteShader", my_glDeleteShader}, +{"glDeleteTextures", my_glDeleteTextures}, +{"glDepthFunc", my_glDepthFunc}, +{"glDepthMask", my_glDepthMask}, +{"glDepthRangef", my_glDepthRangef}, +{"glDetachShader", my_glDetachShader}, +{"glDisable", my_glDisable}, +{"glDisableVertexAttribArray", my_glDisableVertexAttribArray}, +{"glDrawArrays", my_glDrawArrays}, +{"glDrawElements", my_glDrawElements}, +{"glEnable", my_glEnable}, +{"glEnableVertexAttribArray", my_glEnableVertexAttribArray}, +{"glFinish", my_glFinish}, +{"glFlush", my_glFlush}, +{"glFramebufferRenderbuffer", my_glFramebufferRenderbuffer}, +{"glFramebufferTexture2D", my_glFramebufferTexture2D}, +{"glFrontFace", my_glFrontFace}, +{"glGenBuffers", my_glGenBuffers}, +{"glGenerateMipmap", my_glGenerateMipmap}, +{"glGenFramebuffers", my_glGenFramebuffers}, +{"glGenRenderbuffers", my_glGenRenderbuffers}, +{"glGenTextures", my_glGenTextures}, +{"glGetActiveAttrib", my_glGetActiveAttrib}, +{"glGetActiveUniform", my_glGetActiveUniform}, +{"glGetAttachedShaders", my_glGetAttachedShaders}, +{"glGetAttribLocation", my_glGetAttribLocation}, +{"glGetBooleanv", my_glGetBooleanv}, +{"glGetBufferParameteriv", my_glGetBufferParameteriv}, +{"glGetError", my_glGetError}, +{"glGetFloatv", my_glGetFloatv}, +{"glGetFramebufferAttachmentParameteriv", my_glGetFramebufferAttachmentParameteriv}, +{"glGetIntegerv", my_glGetIntegerv}, +{"glGetProgramiv", my_glGetProgramiv}, +{"glGetProgramInfoLog", my_glGetProgramInfoLog}, +{"glGetRenderbufferParameteriv", my_glGetRenderbufferParameteriv}, +{"glGetShaderiv", my_glGetShaderiv}, +{"glGetShaderInfoLog", my_glGetShaderInfoLog}, +{"glGetShaderPrecisionFormat", my_glGetShaderPrecisionFormat}, +{"glGetShaderSource", my_glGetShaderSource}, +{"glGetString", my_glGetString}, +{"glGetTexParameterfv", my_glGetTexParameterfv}, +{"glGetTexParameteriv", my_glGetTexParameteriv}, +{"glGetUniformfv", my_glGetUniformfv}, +{"glGetUniformiv", my_glGetUniformiv}, +{"glGetUniformLocation", my_glGetUniformLocation}, +{"glGetVertexAttribfv", my_glGetVertexAttribfv}, +{"glGetVertexAttribiv", my_glGetVertexAttribiv}, +{"glGetVertexAttribPointerv", my_glGetVertexAttribPointerv}, +{"glHint", my_glHint}, +{"glIsBuffer", my_glIsBuffer}, +{"glIsEnabled", my_glIsEnabled}, +{"glIsFramebuffer", my_glIsFramebuffer}, +{"glIsProgram", my_glIsProgram}, +{"glIsRenderbuffer", my_glIsRenderbuffer}, +{"glIsShader", my_glIsShader}, +{"glIsTexture", my_glIsTexture}, +{"glLineWidth", my_glLineWidth}, +{"glLinkProgram", my_glLinkProgram}, +{"glPixelStorei", my_glPixelStorei}, +{"glPolygonOffset", my_glPolygonOffset}, +{"glReadPixels", my_glReadPixels}, +{"glReleaseShaderCompiler", my_glReleaseShaderCompiler}, +{"glRenderbufferStorage", my_glRenderbufferStorage}, +{"glSampleCoverage", my_glSampleCoverage}, +{"glScissor", my_glScissor}, +{"glShaderBinary", my_glShaderBinary}, +{"glShaderSource", my_glShaderSource}, +{"glStencilFunc", my_glStencilFunc}, +{"glStencilFuncSeparate", my_glStencilFuncSeparate}, +{"glStencilMask", my_glStencilMask}, +{"glStencilMaskSeparate", my_glStencilMaskSeparate}, +{"glStencilOp", my_glStencilOp}, +{"glStencilOpSeparate", my_glStencilOpSeparate}, +{"glTexImage2D", my_glTexImage2D}, +{"glTexParameterf", my_glTexParameterf}, +{"glTexParameterfv", my_glTexParameterfv}, +{"glTexParameteri", my_glTexParameteri}, +{"glTexParameteriv", my_glTexParameteriv}, +{"glTexSubImage2D", my_glTexSubImage2D}, +{"glUniform1f", my_glUniform1f}, +{"glUniform1fv", my_glUniform1fv}, +{"glUniform1i", my_glUniform1i}, +{"glUniform1iv", my_glUniform1iv}, +{"glUniform2f", my_glUniform2f}, +{"glUniform2fv", my_glUniform2fv}, +{"glUniform2i", my_glUniform2i}, +{"glUniform2iv", my_glUniform2iv}, +{"glUniform3f", my_glUniform3f}, +{"glUniform3fv", my_glUniform3fv}, +{"glUniform3i", my_glUniform3i}, +{"glUniform3iv", my_glUniform3iv}, +{"glUniform4f", my_glUniform4f}, +{"glUniform4fv", my_glUniform4fv}, +{"glUniform4i", my_glUniform4i}, +{"glUniform4iv", my_glUniform4iv}, +{"glUniformMatrix2fv", my_glUniformMatrix2fv}, +{"glUniformMatrix3fv", my_glUniformMatrix3fv}, +{"glUniformMatrix4fv", my_glUniformMatrix4fv}, +{"glUseProgram", my_glUseProgram}, +{"glValidateProgram", my_glValidateProgram}, +{"glVertexAttrib1f", my_glVertexAttrib1f}, +{"glVertexAttrib1fv", my_glVertexAttrib1fv}, +{"glVertexAttrib2f", my_glVertexAttrib2f}, +{"glVertexAttrib2fv", my_glVertexAttrib2fv}, +{"glVertexAttrib3f", my_glVertexAttrib3f}, +{"glVertexAttrib3fv", my_glVertexAttrib3fv}, +{"glVertexAttrib4f", my_glVertexAttrib4f}, +{"glVertexAttrib4fv", my_glVertexAttrib4fv}, +{"glVertexAttribPointer", my_glVertexAttribPointer}, +{"glViewport", my_glViewport}, +{"glEGLImageTargetTexture2DOES", my_glEGLImageTargetTexture2DOES}, +{"glEGLImageTargetRenderbufferStorageOES", my_glEGLImageTargetRenderbufferStorageOES}, +{"glMapBufferOES", my_glMapBufferOES}, +{"glUnmapBufferOES", my_glUnmapBufferOES}, +{"glGetBufferPointervOES", my_glGetBufferPointervOES}, +{"glTexImage3DOES", my_glTexImage3DOES}, +{"glTexSubImage3DOES", my_glTexSubImage3DOES}, +{"glCopyTexSubImage3DOES", my_glCopyTexSubImage3DOES}, +{"glCompressedTexImage3DOES", my_glCompressedTexImage3DOES}, +{"glCompressedTexSubImage3DOES", my_glCompressedTexSubImage3DOES}, +{"glFramebufferTexture3DOES", my_glFramebufferTexture3DOES}, +{"glMultiDrawArraysEXT", my_glMultiDrawArraysEXT}, +{"glMultiDrawElementsEXT", my_glMultiDrawElementsEXT}, +{"glTexBindStreamIMG", my_glTexBindStreamIMG}, +{"glGetTexStreamDeviceAttributeivIMG", my_glGetTexStreamDeviceAttributeivIMG}, +{"glGetTexStreamDeviceNameIMG", my_glGetTexStreamDeviceNameIMG}, +{"glGetProgramBinaryOES", my_glGetProgramBinaryOES}, +{"glProgramBinaryOES", my_glProgramBinaryOES}, +#endif /* APKENV_GLES2 */ diff --git a/compat/gles2_wrappers.c b/compat/gles2_wrappers.c new file mode 100644 index 0000000..888332f --- /dev/null +++ b/compat/gles2_wrappers.c @@ -0,0 +1,969 @@ +#ifdef APKENV_GLES2 +#include "gles2_wrappers.h" +#include +#ifdef APKENV_DEBUG +# define WRAPPERS_DEBUG_PRINTF(...) printf(__VA_ARGS__) +#else +# define WRAPPERS_DEBUG_PRINTF(...) +#endif +void +my_glActiveTexture(GLenum texture) +{ + WRAPPERS_DEBUG_PRINTF("glActiveTexture()\n", texture); + glActiveTexture(texture); +} +void +my_glAttachShader(GLuint program, GLuint shader) +{ + WRAPPERS_DEBUG_PRINTF("glAttachShader()\n", program, shader); + glAttachShader(program, shader); +} +void +my_glBindAttribLocation(GLuint program, GLuint index, const char *name) +{ + WRAPPERS_DEBUG_PRINTF("glBindAttribLocation()\n", program, index, name); + glBindAttribLocation(program, index, name); +} +void +my_glBindBuffer(GLenum target, GLuint buffer) +{ + WRAPPERS_DEBUG_PRINTF("glBindBuffer()\n", target, buffer); + glBindBuffer(target, buffer); +} +void +my_glBindFramebuffer(GLenum target, GLuint framebuffer) +{ + WRAPPERS_DEBUG_PRINTF("glBindFramebuffer()\n", target, framebuffer); + glBindFramebuffer(target, framebuffer); +} +void +my_glBindRenderbuffer(GLenum target, GLuint renderbuffer) +{ + WRAPPERS_DEBUG_PRINTF("glBindRenderbuffer()\n", target, renderbuffer); + glBindRenderbuffer(target, renderbuffer); +} +void +my_glBindTexture(GLenum target, GLuint texture) +{ + WRAPPERS_DEBUG_PRINTF("glBindTexture()\n", target, texture); + glBindTexture(target, texture); +} +void +my_glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + WRAPPERS_DEBUG_PRINTF("glBlendColor()\n", red, green, blue, alpha); + glBlendColor(red, green, blue, alpha); +} +void +my_glBlendEquation(GLenum mode) +{ + WRAPPERS_DEBUG_PRINTF("glBlendEquation()\n", mode); + glBlendEquation(mode); +} +void +my_glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +{ + WRAPPERS_DEBUG_PRINTF("glBlendEquationSeparate()\n", modeRGB, modeAlpha); + glBlendEquationSeparate(modeRGB, modeAlpha); +} +void +my_glBlendFunc(GLenum sfactor, GLenum dfactor) +{ + WRAPPERS_DEBUG_PRINTF("glBlendFunc()\n", sfactor, dfactor); + glBlendFunc(sfactor, dfactor); +} +void +my_glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +{ + WRAPPERS_DEBUG_PRINTF("glBlendFuncSeparate()\n", srcRGB, dstRGB, srcAlpha, dstAlpha); + glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); +} +void +my_glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage) +{ + WRAPPERS_DEBUG_PRINTF("glBufferData()\n", target, size, data, usage); + glBufferData(target, size, data, usage); +} +void +my_glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data) +{ + WRAPPERS_DEBUG_PRINTF("glBufferSubData()\n", target, offset, size, data); + glBufferSubData(target, offset, size, data); +} +GLenum +my_glCheckFramebufferStatus(GLenum target) +{ + WRAPPERS_DEBUG_PRINTF("glCheckFramebufferStatus()\n", target); + return glCheckFramebufferStatus(target); +} +void +my_glClear(GLbitfield mask) +{ + WRAPPERS_DEBUG_PRINTF("glClear()\n", mask); + glClear(mask); +} +void +my_glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + WRAPPERS_DEBUG_PRINTF("glClearColor()\n", red, green, blue, alpha); + glClearColor(red, green, blue, alpha); +} +void +my_glClearDepthf(GLclampf depth) +{ + WRAPPERS_DEBUG_PRINTF("glClearDepthf()\n", depth); + glClearDepthf(depth); +} +void +my_glClearStencil(GLint s) +{ + WRAPPERS_DEBUG_PRINTF("glClearStencil()\n", s); + glClearStencil(s); +} +void +my_glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +{ + WRAPPERS_DEBUG_PRINTF("glColorMask()\n", red, green, blue, alpha); + glColorMask(red, green, blue, alpha); +} +void +my_glCompileShader(GLuint shader) +{ + WRAPPERS_DEBUG_PRINTF("glCompileShader()\n", shader); + glCompileShader(shader); +} +void +my_glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) +{ + WRAPPERS_DEBUG_PRINTF("glCompressedTexImage2D()\n", target, level, internalformat, width, height, border, imageSize, data); + glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); +} +void +my_glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) +{ + WRAPPERS_DEBUG_PRINTF("glCompressedTexSubImage2D()\n", target, level, xoffset, yoffset, width, height, format, imageSize, data); + glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); +} +void +my_glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + WRAPPERS_DEBUG_PRINTF("glCopyTexImage2D()\n", target, level, internalformat, x, y, width, height, border); + glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); +} +void +my_glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + WRAPPERS_DEBUG_PRINTF("glCopyTexSubImage2D()\n", target, level, xoffset, yoffset, x, y, width, height); + glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); +} +GLuint +my_glCreateProgram() +{ + WRAPPERS_DEBUG_PRINTF("glCreateProgram()\n"); + return glCreateProgram(); +} +GLuint +my_glCreateShader(GLenum type) +{ + WRAPPERS_DEBUG_PRINTF("glCreateShader()\n", type); + return glCreateShader(type); +} +void +my_glCullFace(GLenum mode) +{ + WRAPPERS_DEBUG_PRINTF("glCullFace()\n", mode); + glCullFace(mode); +} +void +my_glDeleteBuffers(GLsizei n, const GLuint *buffers) +{ + WRAPPERS_DEBUG_PRINTF("glDeleteBuffers()\n", n, buffers); + glDeleteBuffers(n, buffers); +} +void +my_glDeleteFramebuffers(GLsizei n, const GLuint *framebuffers) +{ + WRAPPERS_DEBUG_PRINTF("glDeleteFramebuffers()\n", n, framebuffers); + glDeleteFramebuffers(n, framebuffers); +} +void +my_glDeleteProgram(GLuint program) +{ + WRAPPERS_DEBUG_PRINTF("glDeleteProgram()\n", program); + glDeleteProgram(program); +} +void +my_glDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) +{ + WRAPPERS_DEBUG_PRINTF("glDeleteRenderbuffers()\n", n, renderbuffers); + glDeleteRenderbuffers(n, renderbuffers); +} +void +my_glDeleteShader(GLuint shader) +{ + WRAPPERS_DEBUG_PRINTF("glDeleteShader()\n", shader); + glDeleteShader(shader); +} +void +my_glDeleteTextures(GLsizei n, const GLuint *textures) +{ + WRAPPERS_DEBUG_PRINTF("glDeleteTextures()\n", n, textures); + glDeleteTextures(n, textures); +} +void +my_glDepthFunc(GLenum func) +{ + WRAPPERS_DEBUG_PRINTF("glDepthFunc()\n", func); + glDepthFunc(func); +} +void +my_glDepthMask(GLboolean flag) +{ + WRAPPERS_DEBUG_PRINTF("glDepthMask()\n", flag); + glDepthMask(flag); +} +void +my_glDepthRangef(GLclampf zNear, GLclampf zFar) +{ + WRAPPERS_DEBUG_PRINTF("glDepthRangef()\n", zNear, zFar); + glDepthRangef(zNear, zFar); +} +void +my_glDetachShader(GLuint program, GLuint shader) +{ + WRAPPERS_DEBUG_PRINTF("glDetachShader()\n", program, shader); + glDetachShader(program, shader); +} +void +my_glDisable(GLenum cap) +{ + WRAPPERS_DEBUG_PRINTF("glDisable()\n", cap); + glDisable(cap); +} +void +my_glDisableVertexAttribArray(GLuint index) +{ + WRAPPERS_DEBUG_PRINTF("glDisableVertexAttribArray()\n", index); + glDisableVertexAttribArray(index); +} +void +my_glDrawArrays(GLenum mode, GLint first, GLsizei count) +{ + WRAPPERS_DEBUG_PRINTF("glDrawArrays()\n", mode, first, count); + glDrawArrays(mode, first, count); +} +void +my_glDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) +{ + WRAPPERS_DEBUG_PRINTF("glDrawElements()\n", mode, count, type, indices); + glDrawElements(mode, count, type, indices); +} +void +my_glEnable(GLenum cap) +{ + WRAPPERS_DEBUG_PRINTF("glEnable()\n", cap); + glEnable(cap); +} +void +my_glEnableVertexAttribArray(GLuint index) +{ + WRAPPERS_DEBUG_PRINTF("glEnableVertexAttribArray()\n", index); + glEnableVertexAttribArray(index); +} +void +my_glFinish() +{ + WRAPPERS_DEBUG_PRINTF("glFinish()\n"); + glFinish(); +} +void +my_glFlush() +{ + WRAPPERS_DEBUG_PRINTF("glFlush()\n"); + glFlush(); +} +void +my_glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ + WRAPPERS_DEBUG_PRINTF("glFramebufferRenderbuffer()\n", target, attachment, renderbuffertarget, renderbuffer); + glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); +} +void +my_glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + WRAPPERS_DEBUG_PRINTF("glFramebufferTexture2D()\n", target, attachment, textarget, texture, level); + glFramebufferTexture2D(target, attachment, textarget, texture, level); +} +void +my_glFrontFace(GLenum mode) +{ + WRAPPERS_DEBUG_PRINTF("glFrontFace()\n", mode); + glFrontFace(mode); +} +void +my_glGenBuffers(GLsizei n, GLuint *buffers) +{ + WRAPPERS_DEBUG_PRINTF("glGenBuffers()\n", n, buffers); + glGenBuffers(n, buffers); +} +void +my_glGenerateMipmap(GLenum target) +{ + WRAPPERS_DEBUG_PRINTF("glGenerateMipmap()\n", target); + glGenerateMipmap(target); +} +void +my_glGenFramebuffers(GLsizei n, GLuint *framebuffers) +{ + WRAPPERS_DEBUG_PRINTF("glGenFramebuffers()\n", n, framebuffers); + glGenFramebuffers(n, framebuffers); +} +void +my_glGenRenderbuffers(GLsizei n, GLuint *renderbuffers) +{ + WRAPPERS_DEBUG_PRINTF("glGenRenderbuffers()\n", n, renderbuffers); + glGenRenderbuffers(n, renderbuffers); +} +void +my_glGenTextures(GLsizei n, GLuint *textures) +{ + WRAPPERS_DEBUG_PRINTF("glGenTextures()\n", n, textures); + glGenTextures(n, textures); +} +void +my_glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name) +{ + WRAPPERS_DEBUG_PRINTF("glGetActiveAttrib()\n", program, index, bufsize, length, size, type, name); + glGetActiveAttrib(program, index, bufsize, length, size, type, name); +} +void +my_glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name) +{ + WRAPPERS_DEBUG_PRINTF("glGetActiveUniform()\n", program, index, bufsize, length, size, type, name); + glGetActiveUniform(program, index, bufsize, length, size, type, name); +} +void +my_glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders) +{ + WRAPPERS_DEBUG_PRINTF("glGetAttachedShaders()\n", program, maxcount, count, shaders); + glGetAttachedShaders(program, maxcount, count, shaders); +} +int +my_glGetAttribLocation(GLuint program, const char *name) +{ + WRAPPERS_DEBUG_PRINTF("glGetAttribLocation()\n", program, name); + return glGetAttribLocation(program, name); +} +void +my_glGetBooleanv(GLenum pname, GLboolean *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetBooleanv()\n", pname, params); + glGetBooleanv(pname, params); +} +void +my_glGetBufferParameteriv(GLenum target, GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetBufferParameteriv()\n", target, pname, params); + glGetBufferParameteriv(target, pname, params); +} +GLenum +my_glGetError() +{ + WRAPPERS_DEBUG_PRINTF("glGetError()\n"); + return glGetError(); +} +void +my_glGetFloatv(GLenum pname, GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetFloatv()\n", pname, params); + glGetFloatv(pname, params); +} +void +my_glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetFramebufferAttachmentParameteriv()\n", target, attachment, pname, params); + glGetFramebufferAttachmentParameteriv(target, attachment, pname, params); +} +void +my_glGetIntegerv(GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetIntegerv()\n", pname, params); + glGetIntegerv(pname, params); +} +void +my_glGetProgramiv(GLuint program, GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetProgramiv()\n", program, pname, params); + glGetProgramiv(program, pname, params); +} +void +my_glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei *length, char *infolog) +{ + WRAPPERS_DEBUG_PRINTF("glGetProgramInfoLog()\n", program, bufsize, length, infolog); + glGetProgramInfoLog(program, bufsize, length, infolog); +} +void +my_glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetRenderbufferParameteriv()\n", target, pname, params); + glGetRenderbufferParameteriv(target, pname, params); +} +void +my_glGetShaderiv(GLuint shader, GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetShaderiv()\n", shader, pname, params); + glGetShaderiv(shader, pname, params); +} +void +my_glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei *length, char *infolog) +{ + WRAPPERS_DEBUG_PRINTF("glGetShaderInfoLog()\n", shader, bufsize, length, infolog); + glGetShaderInfoLog(shader, bufsize, length, infolog); +} +void +my_glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision) +{ + WRAPPERS_DEBUG_PRINTF("glGetShaderPrecisionFormat()\n", shadertype, precisiontype, range, precision); + glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision); +} +void +my_glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei *length, char *source) +{ + WRAPPERS_DEBUG_PRINTF("glGetShaderSource()\n", shader, bufsize, length, source); + glGetShaderSource(shader, bufsize, length, source); +} +const GLubyte * +my_glGetString(GLenum name) +{ + WRAPPERS_DEBUG_PRINTF("glGetString()\n", name); + return glGetString(name); +} +void +my_glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexParameterfv()\n", target, pname, params); + glGetTexParameterfv(target, pname, params); +} +void +my_glGetTexParameteriv(GLenum target, GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexParameteriv()\n", target, pname, params); + glGetTexParameteriv(target, pname, params); +} +void +my_glGetUniformfv(GLuint program, GLint location, GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetUniformfv()\n", program, location, params); + glGetUniformfv(program, location, params); +} +void +my_glGetUniformiv(GLuint program, GLint location, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetUniformiv()\n", program, location, params); + glGetUniformiv(program, location, params); +} +int +my_glGetUniformLocation(GLuint program, const char *name) +{ + WRAPPERS_DEBUG_PRINTF("glGetUniformLocation()\n", program, name); + return glGetUniformLocation(program, name); +} +void +my_glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetVertexAttribfv()\n", index, pname, params); + glGetVertexAttribfv(index, pname, params); +} +void +my_glGetVertexAttribiv(GLuint index, GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetVertexAttribiv()\n", index, pname, params); + glGetVertexAttribiv(index, pname, params); +} +void +my_glGetVertexAttribPointerv(GLuint index, GLenum pname, void **pointer) +{ + WRAPPERS_DEBUG_PRINTF("glGetVertexAttribPointerv()\n", index, pname, pointer); + glGetVertexAttribPointerv(index, pname, pointer); +} +void +my_glHint(GLenum target, GLenum mode) +{ + WRAPPERS_DEBUG_PRINTF("glHint()\n", target, mode); + glHint(target, mode); +} +GLboolean +my_glIsBuffer(GLuint buffer) +{ + WRAPPERS_DEBUG_PRINTF("glIsBuffer()\n", buffer); + return glIsBuffer(buffer); +} +GLboolean +my_glIsEnabled(GLenum cap) +{ + WRAPPERS_DEBUG_PRINTF("glIsEnabled()\n", cap); + return glIsEnabled(cap); +} +GLboolean +my_glIsFramebuffer(GLuint framebuffer) +{ + WRAPPERS_DEBUG_PRINTF("glIsFramebuffer()\n", framebuffer); + return glIsFramebuffer(framebuffer); +} +GLboolean +my_glIsProgram(GLuint program) +{ + WRAPPERS_DEBUG_PRINTF("glIsProgram()\n", program); + return glIsProgram(program); +} +GLboolean +my_glIsRenderbuffer(GLuint renderbuffer) +{ + WRAPPERS_DEBUG_PRINTF("glIsRenderbuffer()\n", renderbuffer); + return glIsRenderbuffer(renderbuffer); +} +GLboolean +my_glIsShader(GLuint shader) +{ + WRAPPERS_DEBUG_PRINTF("glIsShader()\n", shader); + return glIsShader(shader); +} +GLboolean +my_glIsTexture(GLuint texture) +{ + WRAPPERS_DEBUG_PRINTF("glIsTexture()\n", texture); + return glIsTexture(texture); +} +void +my_glLineWidth(GLfloat width) +{ + WRAPPERS_DEBUG_PRINTF("glLineWidth()\n", width); + glLineWidth(width); +} +void +my_glLinkProgram(GLuint program) +{ + WRAPPERS_DEBUG_PRINTF("glLinkProgram()\n", program); + glLinkProgram(program); +} +void +my_glPixelStorei(GLenum pname, GLint param) +{ + WRAPPERS_DEBUG_PRINTF("glPixelStorei()\n", pname, param); + glPixelStorei(pname, param); +} +void +my_glPolygonOffset(GLfloat factor, GLfloat units) +{ + WRAPPERS_DEBUG_PRINTF("glPolygonOffset()\n", factor, units); + glPolygonOffset(factor, units); +} +void +my_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) +{ + WRAPPERS_DEBUG_PRINTF("glReadPixels()\n", x, y, width, height, format, type, pixels); + glReadPixels(x, y, width, height, format, type, pixels); +} +void +my_glReleaseShaderCompiler() +{ + WRAPPERS_DEBUG_PRINTF("glReleaseShaderCompiler()\n"); + glReleaseShaderCompiler(); +} +void +my_glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ + WRAPPERS_DEBUG_PRINTF("glRenderbufferStorage()\n", target, internalformat, width, height); + glRenderbufferStorage(target, internalformat, width, height); +} +void +my_glSampleCoverage(GLclampf value, GLboolean invert) +{ + WRAPPERS_DEBUG_PRINTF("glSampleCoverage()\n", value, invert); + glSampleCoverage(value, invert); +} +void +my_glScissor(GLint x, GLint y, GLsizei width, GLsizei height) +{ + WRAPPERS_DEBUG_PRINTF("glScissor()\n", x, y, width, height); + glScissor(x, y, width, height); +} +void +my_glShaderBinary(GLint n, const GLuint *shaders, GLenum binaryformat, const void *binary, GLint length) +{ + WRAPPERS_DEBUG_PRINTF("glShaderBinary()\n", n, shaders, binaryformat, binary, length); + glShaderBinary(n, shaders, binaryformat, binary, length); +} +void +my_glShaderSource(GLuint shader, GLsizei count, const char **string, const GLint *length) +{ + WRAPPERS_DEBUG_PRINTF("glShaderSource()\n", shader, count, string, length); + glShaderSource(shader, count, string, length); +} +void +my_glStencilFunc(GLenum func, GLint ref, GLuint mask) +{ + WRAPPERS_DEBUG_PRINTF("glStencilFunc()\n", func, ref, mask); + glStencilFunc(func, ref, mask); +} +void +my_glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ + WRAPPERS_DEBUG_PRINTF("glStencilFuncSeparate()\n", face, func, ref, mask); + glStencilFuncSeparate(face, func, ref, mask); +} +void +my_glStencilMask(GLuint mask) +{ + WRAPPERS_DEBUG_PRINTF("glStencilMask()\n", mask); + glStencilMask(mask); +} +void +my_glStencilMaskSeparate(GLenum face, GLuint mask) +{ + WRAPPERS_DEBUG_PRINTF("glStencilMaskSeparate()\n", face, mask); + glStencilMaskSeparate(face, mask); +} +void +my_glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) +{ + WRAPPERS_DEBUG_PRINTF("glStencilOp()\n", fail, zfail, zpass); + glStencilOp(fail, zfail, zpass); +} +void +my_glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + WRAPPERS_DEBUG_PRINTF("glStencilOpSeparate()\n", face, fail, zfail, zpass); + glStencilOpSeparate(face, fail, zfail, zpass); +} +void +my_glTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) +{ + WRAPPERS_DEBUG_PRINTF("glTexImage2D()\n", target, level, internalformat, width, height, border, format, type, pixels); + glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); +} +void +my_glTexParameterf(GLenum target, GLenum pname, GLfloat param) +{ + WRAPPERS_DEBUG_PRINTF("glTexParameterf()\n", target, pname, param); + glTexParameterf(target, pname, param); +} +void +my_glTexParameterfv(GLenum target, GLenum pname, const GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glTexParameterfv()\n", target, pname, params); + glTexParameterfv(target, pname, params); +} +void +my_glTexParameteri(GLenum target, GLenum pname, GLint param) +{ + WRAPPERS_DEBUG_PRINTF("glTexParameteri()\n", target, pname, param); + glTexParameteri(target, pname, param); +} +void +my_glTexParameteriv(GLenum target, GLenum pname, const GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glTexParameteriv()\n", target, pname, params); + glTexParameteriv(target, pname, params); +} +void +my_glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) +{ + WRAPPERS_DEBUG_PRINTF("glTexSubImage2D()\n", target, level, xoffset, yoffset, width, height, format, type, pixels); + glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); +} +void +my_glUniform1f(GLint location, GLfloat x) +{ + WRAPPERS_DEBUG_PRINTF("glUniform1f()\n", location, x); + glUniform1f(location, x); +} +void +my_glUniform1fv(GLint location, GLsizei count, const GLfloat *v) +{ + WRAPPERS_DEBUG_PRINTF("glUniform1fv()\n", location, count, v); + glUniform1fv(location, count, v); +} +void +my_glUniform1i(GLint location, GLint x) +{ + WRAPPERS_DEBUG_PRINTF("glUniform1i()\n", location, x); + glUniform1i(location, x); +} +void +my_glUniform1iv(GLint location, GLsizei count, const GLint *v) +{ + WRAPPERS_DEBUG_PRINTF("glUniform1iv()\n", location, count, v); + glUniform1iv(location, count, v); +} +void +my_glUniform2f(GLint location, GLfloat x, GLfloat y) +{ + WRAPPERS_DEBUG_PRINTF("glUniform2f()\n", location, x, y); + glUniform2f(location, x, y); +} +void +my_glUniform2fv(GLint location, GLsizei count, const GLfloat *v) +{ + WRAPPERS_DEBUG_PRINTF("glUniform2fv()\n", location, count, v); + glUniform2fv(location, count, v); +} +void +my_glUniform2i(GLint location, GLint x, GLint y) +{ + WRAPPERS_DEBUG_PRINTF("glUniform2i()\n", location, x, y); + glUniform2i(location, x, y); +} +void +my_glUniform2iv(GLint location, GLsizei count, const GLint *v) +{ + WRAPPERS_DEBUG_PRINTF("glUniform2iv()\n", location, count, v); + glUniform2iv(location, count, v); +} +void +my_glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) +{ + WRAPPERS_DEBUG_PRINTF("glUniform3f()\n", location, x, y, z); + glUniform3f(location, x, y, z); +} +void +my_glUniform3fv(GLint location, GLsizei count, const GLfloat *v) +{ + WRAPPERS_DEBUG_PRINTF("glUniform3fv()\n", location, count, v); + glUniform3fv(location, count, v); +} +void +my_glUniform3i(GLint location, GLint x, GLint y, GLint z) +{ + WRAPPERS_DEBUG_PRINTF("glUniform3i()\n", location, x, y, z); + glUniform3i(location, x, y, z); +} +void +my_glUniform3iv(GLint location, GLsizei count, const GLint *v) +{ + WRAPPERS_DEBUG_PRINTF("glUniform3iv()\n", location, count, v); + glUniform3iv(location, count, v); +} +void +my_glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + WRAPPERS_DEBUG_PRINTF("glUniform4f()\n", location, x, y, z, w); + glUniform4f(location, x, y, z, w); +} +void +my_glUniform4fv(GLint location, GLsizei count, const GLfloat *v) +{ + WRAPPERS_DEBUG_PRINTF("glUniform4fv()\n", location, count, v); + glUniform4fv(location, count, v); +} +void +my_glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) +{ + WRAPPERS_DEBUG_PRINTF("glUniform4i()\n", location, x, y, z, w); + glUniform4i(location, x, y, z, w); +} +void +my_glUniform4iv(GLint location, GLsizei count, const GLint *v) +{ + WRAPPERS_DEBUG_PRINTF("glUniform4iv()\n", location, count, v); + glUniform4iv(location, count, v); +} +void +my_glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + WRAPPERS_DEBUG_PRINTF("glUniformMatrix2fv()\n", location, count, transpose, value); + glUniformMatrix2fv(location, count, transpose, value); +} +void +my_glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + WRAPPERS_DEBUG_PRINTF("glUniformMatrix3fv()\n", location, count, transpose, value); + glUniformMatrix3fv(location, count, transpose, value); +} +void +my_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + WRAPPERS_DEBUG_PRINTF("glUniformMatrix4fv()\n", location, count, transpose, value); + glUniformMatrix4fv(location, count, transpose, value); +} +void +my_glUseProgram(GLuint program) +{ + WRAPPERS_DEBUG_PRINTF("glUseProgram()\n", program); + glUseProgram(program); +} +void +my_glValidateProgram(GLuint program) +{ + WRAPPERS_DEBUG_PRINTF("glValidateProgram()\n", program); + glValidateProgram(program); +} +void +my_glVertexAttrib1f(GLuint indx, GLfloat x) +{ + WRAPPERS_DEBUG_PRINTF("glVertexAttrib1f()\n", indx, x); + glVertexAttrib1f(indx, x); +} +void +my_glVertexAttrib1fv(GLuint indx, const GLfloat *values) +{ + WRAPPERS_DEBUG_PRINTF("glVertexAttrib1fv()\n", indx, values); + glVertexAttrib1fv(indx, values); +} +void +my_glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) +{ + WRAPPERS_DEBUG_PRINTF("glVertexAttrib2f()\n", indx, x, y); + glVertexAttrib2f(indx, x, y); +} +void +my_glVertexAttrib2fv(GLuint indx, const GLfloat *values) +{ + WRAPPERS_DEBUG_PRINTF("glVertexAttrib2fv()\n", indx, values); + glVertexAttrib2fv(indx, values); +} +void +my_glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) +{ + WRAPPERS_DEBUG_PRINTF("glVertexAttrib3f()\n", indx, x, y, z); + glVertexAttrib3f(indx, x, y, z); +} +void +my_glVertexAttrib3fv(GLuint indx, const GLfloat *values) +{ + WRAPPERS_DEBUG_PRINTF("glVertexAttrib3fv()\n", indx, values); + glVertexAttrib3fv(indx, values); +} +void +my_glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + WRAPPERS_DEBUG_PRINTF("glVertexAttrib4f()\n", indx, x, y, z, w); + glVertexAttrib4f(indx, x, y, z, w); +} +void +my_glVertexAttrib4fv(GLuint indx, const GLfloat *values) +{ + WRAPPERS_DEBUG_PRINTF("glVertexAttrib4fv()\n", indx, values); + glVertexAttrib4fv(indx, values); +} +void +my_glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *ptr) +{ + WRAPPERS_DEBUG_PRINTF("glVertexAttribPointer()\n", indx, size, type, normalized, stride, ptr); + glVertexAttribPointer(indx, size, type, normalized, stride, ptr); +} +void +my_glViewport(GLint x, GLint y, GLsizei width, GLsizei height) +{ + WRAPPERS_DEBUG_PRINTF("glViewport()\n", x, y, width, height); + glViewport(x, y, width, height); +} +void +my_glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) +{ + WRAPPERS_DEBUG_PRINTF("glEGLImageTargetTexture2DOES()\n", target, image); + /* No CALL */ assert(0/*glEGLImageTargetTexture2DOES*/); +} +void +my_glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) +{ + WRAPPERS_DEBUG_PRINTF("glEGLImageTargetRenderbufferStorageOES()\n", target, image); + /* No CALL */ assert(0/*glEGLImageTargetRenderbufferStorageOES*/); +} +void * +my_glMapBufferOES(GLenum target, GLenum access) +{ + WRAPPERS_DEBUG_PRINTF("glMapBufferOES()\n", target, access); + /* No CALL */ assert(0/*glMapBufferOES*/); +} +GLboolean +my_glUnmapBufferOES(GLenum target) +{ + WRAPPERS_DEBUG_PRINTF("glUnmapBufferOES()\n", target); + /* No CALL */ assert(0/*glUnmapBufferOES*/); +} +void +my_glGetBufferPointervOES(GLenum target, GLenum pname, void **params) +{ + WRAPPERS_DEBUG_PRINTF("glGetBufferPointervOES()\n", target, pname, params); + /* No CALL */ assert(0/*glGetBufferPointervOES*/); +} +void +my_glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels) +{ + WRAPPERS_DEBUG_PRINTF("glTexImage3DOES()\n", target, level, internalformat, width, height, depth, border, format, type, pixels); + /* No CALL */ assert(0/*glTexImage3DOES*/); +} +void +my_glTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels) +{ + WRAPPERS_DEBUG_PRINTF("glTexSubImage3DOES()\n", target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); + /* No CALL */ assert(0/*glTexSubImage3DOES*/); +} +void +my_glCopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + WRAPPERS_DEBUG_PRINTF("glCopyTexSubImage3DOES()\n", target, level, xoffset, yoffset, zoffset, x, y, width, height); + /* No CALL */ assert(0/*glCopyTexSubImage3DOES*/); +} +void +my_glCompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data) +{ + WRAPPERS_DEBUG_PRINTF("glCompressedTexImage3DOES()\n", target, level, internalformat, width, height, depth, border, imageSize, data); + /* No CALL */ assert(0/*glCompressedTexImage3DOES*/); +} +void +my_glCompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data) +{ + WRAPPERS_DEBUG_PRINTF("glCompressedTexSubImage3DOES()\n", target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); + /* No CALL */ assert(0/*glCompressedTexSubImage3DOES*/); +} +void +my_glFramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) +{ + WRAPPERS_DEBUG_PRINTF("glFramebufferTexture3DOES()\n", target, attachment, textarget, texture, level, zoffset); + /* No CALL */ assert(0/*glFramebufferTexture3DOES*/); +} +void +my_glMultiDrawArraysEXT(GLenum mode, GLint *first, GLsizei *count, GLsizei primcount) +{ + WRAPPERS_DEBUG_PRINTF("glMultiDrawArraysEXT()\n", mode, first, count, primcount); + /* No CALL */ assert(0/*glMultiDrawArraysEXT*/); +} +void +my_glMultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount) +{ + WRAPPERS_DEBUG_PRINTF("glMultiDrawElementsEXT()\n", mode, count, type, indices, primcount); + /* No CALL */ assert(0/*glMultiDrawElementsEXT*/); +} +void +my_glTexBindStreamIMG(GLint device, GLint deviceoffset) +{ + WRAPPERS_DEBUG_PRINTF("glTexBindStreamIMG()\n", device, deviceoffset); + /* No CALL */ assert(0/*glTexBindStreamIMG*/); +} +void +my_glGetTexStreamDeviceAttributeivIMG(GLint device, GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexStreamDeviceAttributeivIMG()\n", device, pname, params); + /* No CALL */ assert(0/*glGetTexStreamDeviceAttributeivIMG*/); +} +const GLubyte * +my_glGetTexStreamDeviceNameIMG(GLint device) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexStreamDeviceNameIMG()\n", device); + /* No CALL */ assert(0/*glGetTexStreamDeviceNameIMG*/); +} +void +my_glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) +{ + WRAPPERS_DEBUG_PRINTF("glGetProgramBinaryOES()\n", program, bufSize, length, binaryFormat, binary); + /* No CALL */ assert(0/*glGetProgramBinaryOES*/); +} +void +my_glProgramBinaryOES(GLuint program, GLenum binaryFormat, const void *binary, GLint length) +{ + WRAPPERS_DEBUG_PRINTF("glProgramBinaryOES()\n", program, binaryFormat, binary, length); + /* No CALL */ assert(0/*glProgramBinaryOES*/); +} +#endif /* APKENV_GLES2 */ diff --git a/compat/gles2_wrappers.h b/compat/gles2_wrappers.h new file mode 100644 index 0000000..cfe538e --- /dev/null +++ b/compat/gles2_wrappers.h @@ -0,0 +1,327 @@ +#ifdef APKENV_GLES2 +#include +#define GL_GLEXT_PROTOTYPES +#include + +#include "../apkenv.h" +void +my_glActiveTexture(GLenum texture) SOFTFP; +void +my_glAttachShader(GLuint program, GLuint shader) SOFTFP; +void +my_glBindAttribLocation(GLuint program, GLuint index, const char *name) SOFTFP; +void +my_glBindBuffer(GLenum target, GLuint buffer) SOFTFP; +void +my_glBindFramebuffer(GLenum target, GLuint framebuffer) SOFTFP; +void +my_glBindRenderbuffer(GLenum target, GLuint renderbuffer) SOFTFP; +void +my_glBindTexture(GLenum target, GLuint texture) SOFTFP; +void +my_glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) SOFTFP; +void +my_glBlendEquation(GLenum mode) SOFTFP; +void +my_glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) SOFTFP; +void +my_glBlendFunc(GLenum sfactor, GLenum dfactor) SOFTFP; +void +my_glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) SOFTFP; +void +my_glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage) SOFTFP; +void +my_glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data) SOFTFP; +GLenum +my_glCheckFramebufferStatus(GLenum target) SOFTFP; +void +my_glClear(GLbitfield mask) SOFTFP; +void +my_glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) SOFTFP; +void +my_glClearDepthf(GLclampf depth) SOFTFP; +void +my_glClearStencil(GLint s) SOFTFP; +void +my_glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) SOFTFP; +void +my_glCompileShader(GLuint shader) SOFTFP; +void +my_glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) SOFTFP; +void +my_glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) SOFTFP; +void +my_glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) SOFTFP; +void +my_glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) SOFTFP; +GLuint +my_glCreateProgram() SOFTFP; +GLuint +my_glCreateShader(GLenum type) SOFTFP; +void +my_glCullFace(GLenum mode) SOFTFP; +void +my_glDeleteBuffers(GLsizei n, const GLuint *buffers) SOFTFP; +void +my_glDeleteFramebuffers(GLsizei n, const GLuint *framebuffers) SOFTFP; +void +my_glDeleteProgram(GLuint program) SOFTFP; +void +my_glDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) SOFTFP; +void +my_glDeleteShader(GLuint shader) SOFTFP; +void +my_glDeleteTextures(GLsizei n, const GLuint *textures) SOFTFP; +void +my_glDepthFunc(GLenum func) SOFTFP; +void +my_glDepthMask(GLboolean flag) SOFTFP; +void +my_glDepthRangef(GLclampf zNear, GLclampf zFar) SOFTFP; +void +my_glDetachShader(GLuint program, GLuint shader) SOFTFP; +void +my_glDisable(GLenum cap) SOFTFP; +void +my_glDisableVertexAttribArray(GLuint index) SOFTFP; +void +my_glDrawArrays(GLenum mode, GLint first, GLsizei count) SOFTFP; +void +my_glDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) SOFTFP; +void +my_glEnable(GLenum cap) SOFTFP; +void +my_glEnableVertexAttribArray(GLuint index) SOFTFP; +void +my_glFinish() SOFTFP; +void +my_glFlush() SOFTFP; +void +my_glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) SOFTFP; +void +my_glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) SOFTFP; +void +my_glFrontFace(GLenum mode) SOFTFP; +void +my_glGenBuffers(GLsizei n, GLuint *buffers) SOFTFP; +void +my_glGenerateMipmap(GLenum target) SOFTFP; +void +my_glGenFramebuffers(GLsizei n, GLuint *framebuffers) SOFTFP; +void +my_glGenRenderbuffers(GLsizei n, GLuint *renderbuffers) SOFTFP; +void +my_glGenTextures(GLsizei n, GLuint *textures) SOFTFP; +void +my_glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name) SOFTFP; +void +my_glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, char *name) SOFTFP; +void +my_glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders) SOFTFP; +int +my_glGetAttribLocation(GLuint program, const char *name) SOFTFP; +void +my_glGetBooleanv(GLenum pname, GLboolean *params) SOFTFP; +void +my_glGetBufferParameteriv(GLenum target, GLenum pname, GLint *params) SOFTFP; +GLenum +my_glGetError() SOFTFP; +void +my_glGetFloatv(GLenum pname, GLfloat *params) SOFTFP; +void +my_glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint *params) SOFTFP; +void +my_glGetIntegerv(GLenum pname, GLint *params) SOFTFP; +void +my_glGetProgramiv(GLuint program, GLenum pname, GLint *params) SOFTFP; +void +my_glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei *length, char *infolog) SOFTFP; +void +my_glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params) SOFTFP; +void +my_glGetShaderiv(GLuint shader, GLenum pname, GLint *params) SOFTFP; +void +my_glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei *length, char *infolog) SOFTFP; +void +my_glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision) SOFTFP; +void +my_glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei *length, char *source) SOFTFP; +const GLubyte * +my_glGetString(GLenum name) SOFTFP; +void +my_glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params) SOFTFP; +void +my_glGetTexParameteriv(GLenum target, GLenum pname, GLint *params) SOFTFP; +void +my_glGetUniformfv(GLuint program, GLint location, GLfloat *params) SOFTFP; +void +my_glGetUniformiv(GLuint program, GLint location, GLint *params) SOFTFP; +int +my_glGetUniformLocation(GLuint program, const char *name) SOFTFP; +void +my_glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params) SOFTFP; +void +my_glGetVertexAttribiv(GLuint index, GLenum pname, GLint *params) SOFTFP; +void +my_glGetVertexAttribPointerv(GLuint index, GLenum pname, void **pointer) SOFTFP; +void +my_glHint(GLenum target, GLenum mode) SOFTFP; +GLboolean +my_glIsBuffer(GLuint buffer) SOFTFP; +GLboolean +my_glIsEnabled(GLenum cap) SOFTFP; +GLboolean +my_glIsFramebuffer(GLuint framebuffer) SOFTFP; +GLboolean +my_glIsProgram(GLuint program) SOFTFP; +GLboolean +my_glIsRenderbuffer(GLuint renderbuffer) SOFTFP; +GLboolean +my_glIsShader(GLuint shader) SOFTFP; +GLboolean +my_glIsTexture(GLuint texture) SOFTFP; +void +my_glLineWidth(GLfloat width) SOFTFP; +void +my_glLinkProgram(GLuint program) SOFTFP; +void +my_glPixelStorei(GLenum pname, GLint param) SOFTFP; +void +my_glPolygonOffset(GLfloat factor, GLfloat units) SOFTFP; +void +my_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) SOFTFP; +void +my_glReleaseShaderCompiler() SOFTFP; +void +my_glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) SOFTFP; +void +my_glSampleCoverage(GLclampf value, GLboolean invert) SOFTFP; +void +my_glScissor(GLint x, GLint y, GLsizei width, GLsizei height) SOFTFP; +void +my_glShaderBinary(GLint n, const GLuint *shaders, GLenum binaryformat, const void *binary, GLint length) SOFTFP; +void +my_glShaderSource(GLuint shader, GLsizei count, const char **string, const GLint *length) SOFTFP; +void +my_glStencilFunc(GLenum func, GLint ref, GLuint mask) SOFTFP; +void +my_glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) SOFTFP; +void +my_glStencilMask(GLuint mask) SOFTFP; +void +my_glStencilMaskSeparate(GLenum face, GLuint mask) SOFTFP; +void +my_glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) SOFTFP; +void +my_glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) SOFTFP; +void +my_glTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) SOFTFP; +void +my_glTexParameterf(GLenum target, GLenum pname, GLfloat param) SOFTFP; +void +my_glTexParameterfv(GLenum target, GLenum pname, const GLfloat *params) SOFTFP; +void +my_glTexParameteri(GLenum target, GLenum pname, GLint param) SOFTFP; +void +my_glTexParameteriv(GLenum target, GLenum pname, const GLint *params) SOFTFP; +void +my_glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) SOFTFP; +void +my_glUniform1f(GLint location, GLfloat x) SOFTFP; +void +my_glUniform1fv(GLint location, GLsizei count, const GLfloat *v) SOFTFP; +void +my_glUniform1i(GLint location, GLint x) SOFTFP; +void +my_glUniform1iv(GLint location, GLsizei count, const GLint *v) SOFTFP; +void +my_glUniform2f(GLint location, GLfloat x, GLfloat y) SOFTFP; +void +my_glUniform2fv(GLint location, GLsizei count, const GLfloat *v) SOFTFP; +void +my_glUniform2i(GLint location, GLint x, GLint y) SOFTFP; +void +my_glUniform2iv(GLint location, GLsizei count, const GLint *v) SOFTFP; +void +my_glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) SOFTFP; +void +my_glUniform3fv(GLint location, GLsizei count, const GLfloat *v) SOFTFP; +void +my_glUniform3i(GLint location, GLint x, GLint y, GLint z) SOFTFP; +void +my_glUniform3iv(GLint location, GLsizei count, const GLint *v) SOFTFP; +void +my_glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) SOFTFP; +void +my_glUniform4fv(GLint location, GLsizei count, const GLfloat *v) SOFTFP; +void +my_glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) SOFTFP; +void +my_glUniform4iv(GLint location, GLsizei count, const GLint *v) SOFTFP; +void +my_glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) SOFTFP; +void +my_glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) SOFTFP; +void +my_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) SOFTFP; +void +my_glUseProgram(GLuint program) SOFTFP; +void +my_glValidateProgram(GLuint program) SOFTFP; +void +my_glVertexAttrib1f(GLuint indx, GLfloat x) SOFTFP; +void +my_glVertexAttrib1fv(GLuint indx, const GLfloat *values) SOFTFP; +void +my_glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) SOFTFP; +void +my_glVertexAttrib2fv(GLuint indx, const GLfloat *values) SOFTFP; +void +my_glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) SOFTFP; +void +my_glVertexAttrib3fv(GLuint indx, const GLfloat *values) SOFTFP; +void +my_glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) SOFTFP; +void +my_glVertexAttrib4fv(GLuint indx, const GLfloat *values) SOFTFP; +void +my_glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *ptr) SOFTFP; +void +my_glViewport(GLint x, GLint y, GLsizei width, GLsizei height) SOFTFP; +void +my_glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) SOFTFP; +void +my_glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) SOFTFP; +void * +my_glMapBufferOES(GLenum target, GLenum access) SOFTFP; +GLboolean +my_glUnmapBufferOES(GLenum target) SOFTFP; +void +my_glGetBufferPointervOES(GLenum target, GLenum pname, void **params) SOFTFP; +void +my_glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels) SOFTFP; +void +my_glTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels) SOFTFP; +void +my_glCopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) SOFTFP; +void +my_glCompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data) SOFTFP; +void +my_glCompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data) SOFTFP; +void +my_glFramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) SOFTFP; +void +my_glMultiDrawArraysEXT(GLenum mode, GLint *first, GLsizei *count, GLsizei primcount) SOFTFP; +void +my_glMultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount) SOFTFP; +void +my_glTexBindStreamIMG(GLint device, GLint deviceoffset) SOFTFP; +void +my_glGetTexStreamDeviceAttributeivIMG(GLint device, GLenum pname, GLint *params) SOFTFP; +const GLubyte * +my_glGetTexStreamDeviceNameIMG(GLint device) SOFTFP; +void +my_glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) SOFTFP; +void +my_glProgramBinaryOES(GLuint program, GLenum binaryFormat, const void *binary, GLint length) SOFTFP; +#endif /* APKENV_GLES2 */ diff --git a/compat/gles_mapping.h b/compat/gles_mapping.h new file mode 100644 index 0000000..9ea8b5c --- /dev/null +++ b/compat/gles_mapping.h @@ -0,0 +1,259 @@ +#ifdef APKENV_GLES +{"glAlphaFunc", my_glAlphaFunc}, +{"glClearColor", my_glClearColor}, +{"glClearDepthf", my_glClearDepthf}, +{"glClipPlanef", my_glClipPlanef}, +{"glColor4f", my_glColor4f}, +{"glDepthRangef", my_glDepthRangef}, +{"glFogf", my_glFogf}, +{"glFogfv", my_glFogfv}, +{"glFrustumf", my_glFrustumf}, +{"glGetClipPlanef", my_glGetClipPlanef}, +{"glGetFloatv", my_glGetFloatv}, +{"glGetLightfv", my_glGetLightfv}, +{"glGetMaterialfv", my_glGetMaterialfv}, +{"glGetTexEnvfv", my_glGetTexEnvfv}, +{"glGetTexParameterfv", my_glGetTexParameterfv}, +{"glLightModelf", my_glLightModelf}, +{"glLightModelfv", my_glLightModelfv}, +{"glLightf", my_glLightf}, +{"glLightfv", my_glLightfv}, +{"glLineWidth", my_glLineWidth}, +{"glLoadMatrixf", my_glLoadMatrixf}, +{"glMaterialf", my_glMaterialf}, +{"glMaterialfv", my_glMaterialfv}, +{"glMultMatrixf", my_glMultMatrixf}, +{"glMultiTexCoord4f", my_glMultiTexCoord4f}, +{"glNormal3f", my_glNormal3f}, +{"glOrthof", my_glOrthof}, +{"glPointParameterf", my_glPointParameterf}, +{"glPointParameterfv", my_glPointParameterfv}, +{"glPointSize", my_glPointSize}, +{"glPolygonOffset", my_glPolygonOffset}, +{"glRotatef", my_glRotatef}, +{"glScalef", my_glScalef}, +{"glTexEnvf", my_glTexEnvf}, +{"glTexEnvfv", my_glTexEnvfv}, +{"glTexParameterf", my_glTexParameterf}, +{"glTexParameterfv", my_glTexParameterfv}, +{"glTranslatef", my_glTranslatef}, +{"glActiveTexture", my_glActiveTexture}, +{"glAlphaFuncx", my_glAlphaFuncx}, +{"glBindBuffer", my_glBindBuffer}, +{"glBindTexture", my_glBindTexture}, +{"glBlendFunc", my_glBlendFunc}, +{"glBufferData", my_glBufferData}, +{"glBufferSubData", my_glBufferSubData}, +{"glClear", my_glClear}, +{"glClearColorx", my_glClearColorx}, +{"glClearDepthx", my_glClearDepthx}, +{"glClearStencil", my_glClearStencil}, +{"glClientActiveTexture", my_glClientActiveTexture}, +{"glClipPlanex", my_glClipPlanex}, +{"glColor4ub", my_glColor4ub}, +{"glColor4x", my_glColor4x}, +{"glColorMask", my_glColorMask}, +{"glColorPointer", my_glColorPointer}, +{"glCompressedTexImage2D", my_glCompressedTexImage2D}, +{"glCompressedTexSubImage2D", my_glCompressedTexSubImage2D}, +{"glCopyTexImage2D", my_glCopyTexImage2D}, +{"glCopyTexSubImage2D", my_glCopyTexSubImage2D}, +{"glCullFace", my_glCullFace}, +{"glDeleteBuffers", my_glDeleteBuffers}, +{"glDeleteTextures", my_glDeleteTextures}, +{"glDepthFunc", my_glDepthFunc}, +{"glDepthMask", my_glDepthMask}, +{"glDepthRangex", my_glDepthRangex}, +{"glDisable", my_glDisable}, +{"glDisableClientState", my_glDisableClientState}, +{"glDrawArrays", my_glDrawArrays}, +{"glDrawElements", my_glDrawElements}, +{"glEnable", my_glEnable}, +{"glEnableClientState", my_glEnableClientState}, +{"glFinish", my_glFinish}, +{"glFlush", my_glFlush}, +{"glFogx", my_glFogx}, +{"glFogxv", my_glFogxv}, +{"glFrontFace", my_glFrontFace}, +{"glFrustumx", my_glFrustumx}, +{"glGetBooleanv", my_glGetBooleanv}, +{"glGetBufferParameteriv", my_glGetBufferParameteriv}, +{"glGetClipPlanex", my_glGetClipPlanex}, +{"glGenBuffers", my_glGenBuffers}, +{"glGenTextures", my_glGenTextures}, +{"glGetError", my_glGetError}, +{"glGetFixedv", my_glGetFixedv}, +{"glGetIntegerv", my_glGetIntegerv}, +{"glGetLightxv", my_glGetLightxv}, +{"glGetMaterialxv", my_glGetMaterialxv}, +{"glGetPointerv", my_glGetPointerv}, +{"glGetString", my_glGetString}, +{"glGetTexEnviv", my_glGetTexEnviv}, +{"glGetTexEnvxv", my_glGetTexEnvxv}, +{"glGetTexParameteriv", my_glGetTexParameteriv}, +{"glGetTexParameterxv", my_glGetTexParameterxv}, +{"glHint", my_glHint}, +{"glIsBuffer", my_glIsBuffer}, +{"glIsEnabled", my_glIsEnabled}, +{"glIsTexture", my_glIsTexture}, +{"glLightModelx", my_glLightModelx}, +{"glLightModelxv", my_glLightModelxv}, +{"glLightx", my_glLightx}, +{"glLightxv", my_glLightxv}, +{"glLineWidthx", my_glLineWidthx}, +{"glLoadIdentity", my_glLoadIdentity}, +{"glLoadMatrixx", my_glLoadMatrixx}, +{"glLogicOp", my_glLogicOp}, +{"glMaterialx", my_glMaterialx}, +{"glMaterialxv", my_glMaterialxv}, +{"glMatrixMode", my_glMatrixMode}, +{"glMultMatrixx", my_glMultMatrixx}, +{"glMultiTexCoord4x", my_glMultiTexCoord4x}, +{"glNormal3x", my_glNormal3x}, +{"glNormalPointer", my_glNormalPointer}, +{"glOrthox", my_glOrthox}, +{"glPixelStorei", my_glPixelStorei}, +{"glPointParameterx", my_glPointParameterx}, +{"glPointParameterxv", my_glPointParameterxv}, +{"glPointSizex", my_glPointSizex}, +{"glPolygonOffsetx", my_glPolygonOffsetx}, +{"glPopMatrix", my_glPopMatrix}, +{"glPushMatrix", my_glPushMatrix}, +{"glReadPixels", my_glReadPixels}, +{"glRotatex", my_glRotatex}, +{"glSampleCoverage", my_glSampleCoverage}, +{"glSampleCoveragex", my_glSampleCoveragex}, +{"glScalex", my_glScalex}, +{"glScissor", my_glScissor}, +{"glShadeModel", my_glShadeModel}, +{"glStencilFunc", my_glStencilFunc}, +{"glStencilMask", my_glStencilMask}, +{"glStencilOp", my_glStencilOp}, +{"glTexCoordPointer", my_glTexCoordPointer}, +{"glTexEnvi", my_glTexEnvi}, +{"glTexEnvx", my_glTexEnvx}, +{"glTexEnviv", my_glTexEnviv}, +{"glTexEnvxv", my_glTexEnvxv}, +{"glTexImage2D", my_glTexImage2D}, +{"glTexParameteri", my_glTexParameteri}, +{"glTexParameterx", my_glTexParameterx}, +{"glTexParameteriv", my_glTexParameteriv}, +{"glTexParameterxv", my_glTexParameterxv}, +{"glTexSubImage2D", my_glTexSubImage2D}, +{"glTranslatex", my_glTranslatex}, +{"glVertexPointer", my_glVertexPointer}, +{"glViewport", my_glViewport}, +{"glPointSizePointerOES", my_glPointSizePointerOES}, +{"glBlendEquationSeparateOES", my_glBlendEquationSeparateOES}, +{"glBlendFuncSeparateOES", my_glBlendFuncSeparateOES}, +{"glBlendEquationOES", my_glBlendEquationOES}, +{"glDrawTexsOES", my_glDrawTexsOES}, +{"glDrawTexiOES", my_glDrawTexiOES}, +{"glDrawTexxOES", my_glDrawTexxOES}, +{"glDrawTexsvOES", my_glDrawTexsvOES}, +{"glDrawTexivOES", my_glDrawTexivOES}, +{"glDrawTexxvOES", my_glDrawTexxvOES}, +{"glDrawTexfOES", my_glDrawTexfOES}, +{"glDrawTexfvOES", my_glDrawTexfvOES}, +{"glAlphaFuncxOES", my_glAlphaFuncxOES}, +{"glClearColorxOES", my_glClearColorxOES}, +{"glClearDepthxOES", my_glClearDepthxOES}, +{"glClipPlanexOES", my_glClipPlanexOES}, +{"glColor4xOES", my_glColor4xOES}, +{"glDepthRangexOES", my_glDepthRangexOES}, +{"glFogxOES", my_glFogxOES}, +{"glFogxvOES", my_glFogxvOES}, +{"glFrustumxOES", my_glFrustumxOES}, +{"glGetClipPlanexOES", my_glGetClipPlanexOES}, +{"glGetFixedvOES", my_glGetFixedvOES}, +{"glGetLightxvOES", my_glGetLightxvOES}, +{"glGetMaterialxvOES", my_glGetMaterialxvOES}, +{"glGetTexEnvxvOES", my_glGetTexEnvxvOES}, +{"glGetTexParameterxvOES", my_glGetTexParameterxvOES}, +{"glLightModelxOES", my_glLightModelxOES}, +{"glLightModelxvOES", my_glLightModelxvOES}, +{"glLightxOES", my_glLightxOES}, +{"glLightxvOES", my_glLightxvOES}, +{"glLineWidthxOES", my_glLineWidthxOES}, +{"glLoadMatrixxOES", my_glLoadMatrixxOES}, +{"glMaterialxOES", my_glMaterialxOES}, +{"glMaterialxvOES", my_glMaterialxvOES}, +{"glMultMatrixxOES", my_glMultMatrixxOES}, +{"glMultiTexCoord4xOES", my_glMultiTexCoord4xOES}, +{"glNormal3xOES", my_glNormal3xOES}, +{"glOrthoxOES", my_glOrthoxOES}, +{"glPointParameterxOES", my_glPointParameterxOES}, +{"glPointParameterxvOES", my_glPointParameterxvOES}, +{"glPointSizexOES", my_glPointSizexOES}, +{"glPolygonOffsetxOES", my_glPolygonOffsetxOES}, +{"glRotatexOES", my_glRotatexOES}, +{"glSampleCoveragexOES", my_glSampleCoveragexOES}, +{"glScalexOES", my_glScalexOES}, +{"glTexEnvxOES", my_glTexEnvxOES}, +{"glTexEnvxvOES", my_glTexEnvxvOES}, +{"glTexParameterxOES", my_glTexParameterxOES}, +{"glTexParameterxvOES", my_glTexParameterxvOES}, +{"glTranslatexOES", my_glTranslatexOES}, +{"glIsRenderbufferOES", my_glIsRenderbufferOES}, +{"glBindRenderbufferOES", my_glBindRenderbufferOES}, +{"glDeleteRenderbuffersOES", my_glDeleteRenderbuffersOES}, +{"glGenRenderbuffersOES", my_glGenRenderbuffersOES}, +{"glRenderbufferStorageOES", my_glRenderbufferStorageOES}, +{"glGetRenderbufferParameterivOES", my_glGetRenderbufferParameterivOES}, +{"glIsFramebufferOES", my_glIsFramebufferOES}, +{"glBindFramebufferOES", my_glBindFramebufferOES}, +{"glDeleteFramebuffersOES", my_glDeleteFramebuffersOES}, +{"glGenFramebuffersOES", my_glGenFramebuffersOES}, +{"glCheckFramebufferStatusOES", my_glCheckFramebufferStatusOES}, +{"glFramebufferRenderbufferOES", my_glFramebufferRenderbufferOES}, +{"glFramebufferTexture2DOES", my_glFramebufferTexture2DOES}, +{"glGetFramebufferAttachmentParameterivOES", my_glGetFramebufferAttachmentParameterivOES}, +{"glGenerateMipmapOES", my_glGenerateMipmapOES}, +{"glCurrentPaletteMatrixOES", my_glCurrentPaletteMatrixOES}, +{"glLoadPaletteFromModelViewMatrixOES", my_glLoadPaletteFromModelViewMatrixOES}, +{"glMatrixIndexPointerOES", my_glMatrixIndexPointerOES}, +{"glWeightPointerOES", my_glWeightPointerOES}, +{"glQueryMatrixxOES", my_glQueryMatrixxOES}, +{"glDepthRangefOES", my_glDepthRangefOES}, +{"glFrustumfOES", my_glFrustumfOES}, +{"glOrthofOES", my_glOrthofOES}, +{"glClipPlanefOES", my_glClipPlanefOES}, +{"glGetClipPlanefOES", my_glGetClipPlanefOES}, +{"glClearDepthfOES", my_glClearDepthfOES}, +{"glTexGenfOES", my_glTexGenfOES}, +{"glTexGenfvOES", my_glTexGenfvOES}, +{"glTexGeniOES", my_glTexGeniOES}, +{"glTexGenivOES", my_glTexGenivOES}, +{"glTexGenxOES", my_glTexGenxOES}, +{"glTexGenxvOES", my_glTexGenxvOES}, +{"glGetTexGenfvOES", my_glGetTexGenfvOES}, +{"glGetTexGenivOES", my_glGetTexGenivOES}, +{"glGetTexGenxvOES", my_glGetTexGenxvOES}, +{"glEGLImageTargetTexture2DOES", my_glEGLImageTargetTexture2DOES}, +{"glEGLImageTargetRenderbufferStorageOES", my_glEGLImageTargetRenderbufferStorageOES}, +{"glMapBufferOES", my_glMapBufferOES}, +{"glUnmapBufferOES", my_glUnmapBufferOES}, +{"glGetBufferPointervOES", my_glGetBufferPointervOES}, +{"glTexBindStreamIMG", my_glTexBindStreamIMG}, +{"glGetTexStreamDeviceAttributeivIMG", my_glGetTexStreamDeviceAttributeivIMG}, +{"glGetTexStreamDeviceNameIMG", my_glGetTexStreamDeviceNameIMG}, +{"glVertexAttrib4fARB", my_glVertexAttrib4fARB}, +{"glProgramEnvParameter4fARB", my_glProgramEnvParameter4fARB}, +{"glProgramEnvParameter4fvARB", my_glProgramEnvParameter4fvARB}, +{"glProgramLocalParameter4fARB", my_glProgramLocalParameter4fARB}, +{"glProgramLocalParameter4fvARB", my_glProgramLocalParameter4fvARB}, +{"glVertexAttrib4xIMG", my_glVertexAttrib4xIMG}, +{"glProgramLocalParameter4xIMG", my_glProgramLocalParameter4xIMG}, +{"glProgramLocalParameter4xvIMG", my_glProgramLocalParameter4xvIMG}, +{"glProgramEnvParameter4xIMG", my_glProgramEnvParameter4xIMG}, +{"glProgramEnvParameter4xvIMG", my_glProgramEnvParameter4xvIMG}, +{"glVertexAttribPointerARB", my_glVertexAttribPointerARB}, +{"glEnableVertexAttribArrayARB", my_glEnableVertexAttribArrayARB}, +{"glDisableVertexAttribArrayARB", my_glDisableVertexAttribArrayARB}, +{"glProgramStringARB", my_glProgramStringARB}, +{"glBindProgramARB", my_glBindProgramARB}, +{"glDeleteProgramsARB", my_glDeleteProgramsARB}, +{"glGenProgramsARB", my_glGenProgramsARB}, +{"glMultiDrawArraysEXT", my_glMultiDrawArraysEXT}, +{"glMultiDrawElementsEXT", my_glMultiDrawElementsEXT}, +#endif /* APKENV_GLES */ diff --git a/compat/gles_wrappers.c b/compat/gles_wrappers.c new file mode 100644 index 0000000..78e1ade --- /dev/null +++ b/compat/gles_wrappers.c @@ -0,0 +1,1551 @@ +#ifdef APKENV_GLES +#include "gles_wrappers.h" +#include +#ifdef APKENV_DEBUG +# define WRAPPERS_DEBUG_PRINTF(...) printf(__VA_ARGS__) +#else +# define WRAPPERS_DEBUG_PRINTF(...) +#endif +void +my_glAlphaFunc(GLenum func, GLclampf ref) +{ + WRAPPERS_DEBUG_PRINTF("glAlphaFunc()\n", func, ref); + glAlphaFunc(func, ref); +} +void +my_glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + WRAPPERS_DEBUG_PRINTF("glClearColor()\n", red, green, blue, alpha); + glClearColor(red, green, blue, alpha); +} +void +my_glClearDepthf(GLclampf depth) +{ + WRAPPERS_DEBUG_PRINTF("glClearDepthf()\n", depth); + glClearDepthf(depth); +} +void +my_glClipPlanef(GLenum plane, const GLfloat *equation) +{ + WRAPPERS_DEBUG_PRINTF("glClipPlanef()\n", plane, equation); + glClipPlanef(plane, equation); +} +void +my_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) +{ + WRAPPERS_DEBUG_PRINTF("glColor4f()\n", red, green, blue, alpha); + glColor4f(red, green, blue, alpha); +} +void +my_glDepthRangef(GLclampf zNear, GLclampf zFar) +{ + WRAPPERS_DEBUG_PRINTF("glDepthRangef()\n", zNear, zFar); + glDepthRangef(zNear, zFar); +} +void +my_glFogf(GLenum pname, GLfloat param) +{ + WRAPPERS_DEBUG_PRINTF("glFogf()\n", pname, param); + glFogf(pname, param); +} +void +my_glFogfv(GLenum pname, const GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glFogfv()\n", pname, params); + glFogfv(pname, params); +} +void +my_glFrustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) +{ + WRAPPERS_DEBUG_PRINTF("glFrustumf()\n", left, right, bottom, top, zNear, zFar); + glFrustumf(left, right, bottom, top, zNear, zFar); +} +void +my_glGetClipPlanef(GLenum pname, GLfloat eqn[4]) +{ + WRAPPERS_DEBUG_PRINTF("glGetClipPlanef()\n", pname, eqn); + glGetClipPlanef(pname, eqn); +} +void +my_glGetFloatv(GLenum pname, GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetFloatv()\n", pname, params); + glGetFloatv(pname, params); +} +void +my_glGetLightfv(GLenum light, GLenum pname, GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetLightfv()\n", light, pname, params); + glGetLightfv(light, pname, params); +} +void +my_glGetMaterialfv(GLenum face, GLenum pname, GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetMaterialfv()\n", face, pname, params); + glGetMaterialfv(face, pname, params); +} +void +my_glGetTexEnvfv(GLenum env, GLenum pname, GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexEnvfv()\n", env, pname, params); + glGetTexEnvfv(env, pname, params); +} +void +my_glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexParameterfv()\n", target, pname, params); + glGetTexParameterfv(target, pname, params); +} +void +my_glLightModelf(GLenum pname, GLfloat param) +{ + WRAPPERS_DEBUG_PRINTF("glLightModelf()\n", pname, param); + glLightModelf(pname, param); +} +void +my_glLightModelfv(GLenum pname, const GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glLightModelfv()\n", pname, params); + glLightModelfv(pname, params); +} +void +my_glLightf(GLenum light, GLenum pname, GLfloat param) +{ + WRAPPERS_DEBUG_PRINTF("glLightf()\n", light, pname, param); + glLightf(light, pname, param); +} +void +my_glLightfv(GLenum light, GLenum pname, const GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glLightfv()\n", light, pname, params); + glLightfv(light, pname, params); +} +void +my_glLineWidth(GLfloat width) +{ + WRAPPERS_DEBUG_PRINTF("glLineWidth()\n", width); + glLineWidth(width); +} +void +my_glLoadMatrixf(const GLfloat *m) +{ + WRAPPERS_DEBUG_PRINTF("glLoadMatrixf()\n", m); + glLoadMatrixf(m); +} +void +my_glMaterialf(GLenum face, GLenum pname, GLfloat param) +{ + WRAPPERS_DEBUG_PRINTF("glMaterialf()\n", face, pname, param); + glMaterialf(face, pname, param); +} +void +my_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glMaterialfv()\n", face, pname, params); + glMaterialfv(face, pname, params); +} +void +my_glMultMatrixf(const GLfloat *m) +{ + WRAPPERS_DEBUG_PRINTF("glMultMatrixf()\n", m); + glMultMatrixf(m); +} +void +my_glMultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) +{ + WRAPPERS_DEBUG_PRINTF("glMultiTexCoord4f()\n", target, s, t, r, q); + glMultiTexCoord4f(target, s, t, r, q); +} +void +my_glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) +{ + WRAPPERS_DEBUG_PRINTF("glNormal3f()\n", nx, ny, nz); + glNormal3f(nx, ny, nz); +} +void +my_glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) +{ + WRAPPERS_DEBUG_PRINTF("glOrthof()\n", left, right, bottom, top, zNear, zFar); + glOrthof(left, right, bottom, top, zNear, zFar); +} +void +my_glPointParameterf(GLenum pname, GLfloat param) +{ + WRAPPERS_DEBUG_PRINTF("glPointParameterf()\n", pname, param); + glPointParameterf(pname, param); +} +void +my_glPointParameterfv(GLenum pname, const GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glPointParameterfv()\n", pname, params); + glPointParameterfv(pname, params); +} +void +my_glPointSize(GLfloat size) +{ + WRAPPERS_DEBUG_PRINTF("glPointSize()\n", size); + glPointSize(size); +} +void +my_glPolygonOffset(GLfloat factor, GLfloat units) +{ + WRAPPERS_DEBUG_PRINTF("glPolygonOffset()\n", factor, units); + glPolygonOffset(factor, units); +} +void +my_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) +{ + WRAPPERS_DEBUG_PRINTF("glRotatef()\n", angle, x, y, z); + glRotatef(angle, x, y, z); +} +void +my_glScalef(GLfloat x, GLfloat y, GLfloat z) +{ + WRAPPERS_DEBUG_PRINTF("glScalef()\n", x, y, z); + glScalef(x, y, z); +} +void +my_glTexEnvf(GLenum target, GLenum pname, GLfloat param) +{ + WRAPPERS_DEBUG_PRINTF("glTexEnvf()\n", target, pname, param); + glTexEnvf(target, pname, param); +} +void +my_glTexEnvfv(GLenum target, GLenum pname, const GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glTexEnvfv()\n", target, pname, params); + glTexEnvfv(target, pname, params); +} +void +my_glTexParameterf(GLenum target, GLenum pname, GLfloat param) +{ + WRAPPERS_DEBUG_PRINTF("glTexParameterf()\n", target, pname, param); + glTexParameterf(target, pname, param); +} +void +my_glTexParameterfv(GLenum target, GLenum pname, const GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glTexParameterfv()\n", target, pname, params); + glTexParameterfv(target, pname, params); +} +void +my_glTranslatef(GLfloat x, GLfloat y, GLfloat z) +{ + WRAPPERS_DEBUG_PRINTF("glTranslatef()\n", x, y, z); + glTranslatef(x, y, z); +} +void +my_glActiveTexture(GLenum texture) +{ + WRAPPERS_DEBUG_PRINTF("glActiveTexture()\n", texture); + glActiveTexture(texture); +} +void +my_glAlphaFuncx(GLenum func, GLclampx ref) +{ + WRAPPERS_DEBUG_PRINTF("glAlphaFuncx()\n", func, ref); + glAlphaFuncx(func, ref); +} +void +my_glBindBuffer(GLenum target, GLuint buffer) +{ + WRAPPERS_DEBUG_PRINTF("glBindBuffer()\n", target, buffer); + glBindBuffer(target, buffer); +} +void +my_glBindTexture(GLenum target, GLuint texture) +{ + WRAPPERS_DEBUG_PRINTF("glBindTexture()\n", target, texture); + glBindTexture(target, texture); +} +void +my_glBlendFunc(GLenum sfactor, GLenum dfactor) +{ + WRAPPERS_DEBUG_PRINTF("glBlendFunc()\n", sfactor, dfactor); + glBlendFunc(sfactor, dfactor); +} +void +my_glBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) +{ + WRAPPERS_DEBUG_PRINTF("glBufferData()\n", target, size, data, usage); + glBufferData(target, size, data, usage); +} +void +my_glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) +{ + WRAPPERS_DEBUG_PRINTF("glBufferSubData()\n", target, offset, size, data); + glBufferSubData(target, offset, size, data); +} +void +my_glClear(GLbitfield mask) +{ + WRAPPERS_DEBUG_PRINTF("glClear()\n", mask); + glClear(mask); +} +void +my_glClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) +{ + WRAPPERS_DEBUG_PRINTF("glClearColorx()\n", red, green, blue, alpha); + glClearColorx(red, green, blue, alpha); +} +void +my_glClearDepthx(GLclampx depth) +{ + WRAPPERS_DEBUG_PRINTF("glClearDepthx()\n", depth); + glClearDepthx(depth); +} +void +my_glClearStencil(GLint s) +{ + WRAPPERS_DEBUG_PRINTF("glClearStencil()\n", s); + glClearStencil(s); +} +void +my_glClientActiveTexture(GLenum texture) +{ + WRAPPERS_DEBUG_PRINTF("glClientActiveTexture()\n", texture); + glClientActiveTexture(texture); +} +void +my_glClipPlanex(GLenum plane, const GLfixed *equation) +{ + WRAPPERS_DEBUG_PRINTF("glClipPlanex()\n", plane, equation); + glClipPlanex(plane, equation); +} +void +my_glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) +{ + WRAPPERS_DEBUG_PRINTF("glColor4ub()\n", red, green, blue, alpha); + glColor4ub(red, green, blue, alpha); +} +void +my_glColor4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) +{ + WRAPPERS_DEBUG_PRINTF("glColor4x()\n", red, green, blue, alpha); + glColor4x(red, green, blue, alpha); +} +void +my_glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +{ + WRAPPERS_DEBUG_PRINTF("glColorMask()\n", red, green, blue, alpha); + glColorMask(red, green, blue, alpha); +} +void +my_glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + WRAPPERS_DEBUG_PRINTF("glColorPointer()\n", size, type, stride, pointer); + glColorPointer(size, type, stride, pointer); +} +void +my_glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) +{ + WRAPPERS_DEBUG_PRINTF("glCompressedTexImage2D()\n", target, level, internalformat, width, height, border, imageSize, data); + glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); +} +void +my_glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + WRAPPERS_DEBUG_PRINTF("glCompressedTexSubImage2D()\n", target, level, xoffset, yoffset, width, height, format, imageSize, data); + glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); +} +void +my_glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + WRAPPERS_DEBUG_PRINTF("glCopyTexImage2D()\n", target, level, internalformat, x, y, width, height, border); + glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); +} +void +my_glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + WRAPPERS_DEBUG_PRINTF("glCopyTexSubImage2D()\n", target, level, xoffset, yoffset, x, y, width, height); + glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); +} +void +my_glCullFace(GLenum mode) +{ + WRAPPERS_DEBUG_PRINTF("glCullFace()\n", mode); + glCullFace(mode); +} +void +my_glDeleteBuffers(GLsizei n, const GLuint *buffers) +{ + WRAPPERS_DEBUG_PRINTF("glDeleteBuffers()\n", n, buffers); + glDeleteBuffers(n, buffers); +} +void +my_glDeleteTextures(GLsizei n, const GLuint *textures) +{ + WRAPPERS_DEBUG_PRINTF("glDeleteTextures()\n", n, textures); + glDeleteTextures(n, textures); +} +void +my_glDepthFunc(GLenum func) +{ + WRAPPERS_DEBUG_PRINTF("glDepthFunc()\n", func); + glDepthFunc(func); +} +void +my_glDepthMask(GLboolean flag) +{ + WRAPPERS_DEBUG_PRINTF("glDepthMask()\n", flag); + glDepthMask(flag); +} +void +my_glDepthRangex(GLclampx zNear, GLclampx zFar) +{ + WRAPPERS_DEBUG_PRINTF("glDepthRangex()\n", zNear, zFar); + glDepthRangex(zNear, zFar); +} +void +my_glDisable(GLenum cap) +{ + WRAPPERS_DEBUG_PRINTF("glDisable()\n", cap); + glDisable(cap); +} +void +my_glDisableClientState(GLenum array) +{ + WRAPPERS_DEBUG_PRINTF("glDisableClientState()\n", array); + glDisableClientState(array); +} +void +my_glDrawArrays(GLenum mode, GLint first, GLsizei count) +{ + WRAPPERS_DEBUG_PRINTF("glDrawArrays()\n", mode, first, count); + glDrawArrays(mode, first, count); +} +void +my_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) +{ + WRAPPERS_DEBUG_PRINTF("glDrawElements()\n", mode, count, type, indices); + glDrawElements(mode, count, type, indices); +} +void +my_glEnable(GLenum cap) +{ + WRAPPERS_DEBUG_PRINTF("glEnable()\n", cap); + glEnable(cap); +} +void +my_glEnableClientState(GLenum array) +{ + WRAPPERS_DEBUG_PRINTF("glEnableClientState()\n", array); + glEnableClientState(array); +} +void +my_glFinish() +{ + WRAPPERS_DEBUG_PRINTF("glFinish()\n"); + glFinish(); +} +void +my_glFlush() +{ + WRAPPERS_DEBUG_PRINTF("glFlush()\n"); + glFlush(); +} +void +my_glFogx(GLenum pname, GLfixed param) +{ + WRAPPERS_DEBUG_PRINTF("glFogx()\n", pname, param); + glFogx(pname, param); +} +void +my_glFogxv(GLenum pname, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glFogxv()\n", pname, params); + glFogxv(pname, params); +} +void +my_glFrontFace(GLenum mode) +{ + WRAPPERS_DEBUG_PRINTF("glFrontFace()\n", mode); + glFrontFace(mode); +} +void +my_glFrustumx(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) +{ + WRAPPERS_DEBUG_PRINTF("glFrustumx()\n", left, right, bottom, top, zNear, zFar); + glFrustumx(left, right, bottom, top, zNear, zFar); +} +void +my_glGetBooleanv(GLenum pname, GLboolean *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetBooleanv()\n", pname, params); + glGetBooleanv(pname, params); +} +void +my_glGetBufferParameteriv(GLenum target, GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetBufferParameteriv()\n", target, pname, params); + glGetBufferParameteriv(target, pname, params); +} +void +my_glGetClipPlanex(GLenum pname, GLfixed eqn[4]) +{ + WRAPPERS_DEBUG_PRINTF("glGetClipPlanex()\n", pname, eqn); + glGetClipPlanex(pname, eqn); +} +void +my_glGenBuffers(GLsizei n, GLuint *buffers) +{ + WRAPPERS_DEBUG_PRINTF("glGenBuffers()\n", n, buffers); + glGenBuffers(n, buffers); +} +void +my_glGenTextures(GLsizei n, GLuint *textures) +{ + WRAPPERS_DEBUG_PRINTF("glGenTextures()\n", n, textures); + glGenTextures(n, textures); +} +GLenum +my_glGetError() +{ + WRAPPERS_DEBUG_PRINTF("glGetError()\n"); + return glGetError(); +} +void +my_glGetFixedv(GLenum pname, GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetFixedv()\n", pname, params); + glGetFixedv(pname, params); +} +void +my_glGetIntegerv(GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetIntegerv()\n", pname, params); + glGetIntegerv(pname, params); +} +void +my_glGetLightxv(GLenum light, GLenum pname, GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetLightxv()\n", light, pname, params); + glGetLightxv(light, pname, params); +} +void +my_glGetMaterialxv(GLenum face, GLenum pname, GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetMaterialxv()\n", face, pname, params); + glGetMaterialxv(face, pname, params); +} +void +my_glGetPointerv(GLenum pname, void **params) +{ + WRAPPERS_DEBUG_PRINTF("glGetPointerv()\n", pname, params); + glGetPointerv(pname, params); +} +const GLubyte * +my_glGetString(GLenum name) +{ + WRAPPERS_DEBUG_PRINTF("glGetString()\n", name); + return glGetString(name); +} +void +my_glGetTexEnviv(GLenum env, GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexEnviv()\n", env, pname, params); + glGetTexEnviv(env, pname, params); +} +void +my_glGetTexEnvxv(GLenum env, GLenum pname, GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexEnvxv()\n", env, pname, params); + glGetTexEnvxv(env, pname, params); +} +void +my_glGetTexParameteriv(GLenum target, GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexParameteriv()\n", target, pname, params); + glGetTexParameteriv(target, pname, params); +} +void +my_glGetTexParameterxv(GLenum target, GLenum pname, GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexParameterxv()\n", target, pname, params); + glGetTexParameterxv(target, pname, params); +} +void +my_glHint(GLenum target, GLenum mode) +{ + WRAPPERS_DEBUG_PRINTF("glHint()\n", target, mode); + glHint(target, mode); +} +GLboolean +my_glIsBuffer(GLuint buffer) +{ + WRAPPERS_DEBUG_PRINTF("glIsBuffer()\n", buffer); + return glIsBuffer(buffer); +} +GLboolean +my_glIsEnabled(GLenum cap) +{ + WRAPPERS_DEBUG_PRINTF("glIsEnabled()\n", cap); + return glIsEnabled(cap); +} +GLboolean +my_glIsTexture(GLuint texture) +{ + WRAPPERS_DEBUG_PRINTF("glIsTexture()\n", texture); + return glIsTexture(texture); +} +void +my_glLightModelx(GLenum pname, GLfixed param) +{ + WRAPPERS_DEBUG_PRINTF("glLightModelx()\n", pname, param); + glLightModelx(pname, param); +} +void +my_glLightModelxv(GLenum pname, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glLightModelxv()\n", pname, params); + glLightModelxv(pname, params); +} +void +my_glLightx(GLenum light, GLenum pname, GLfixed param) +{ + WRAPPERS_DEBUG_PRINTF("glLightx()\n", light, pname, param); + glLightx(light, pname, param); +} +void +my_glLightxv(GLenum light, GLenum pname, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glLightxv()\n", light, pname, params); + glLightxv(light, pname, params); +} +void +my_glLineWidthx(GLfixed width) +{ + WRAPPERS_DEBUG_PRINTF("glLineWidthx()\n", width); + glLineWidthx(width); +} +void +my_glLoadIdentity() +{ + WRAPPERS_DEBUG_PRINTF("glLoadIdentity()\n"); + glLoadIdentity(); +} +void +my_glLoadMatrixx(const GLfixed *m) +{ + WRAPPERS_DEBUG_PRINTF("glLoadMatrixx()\n", m); + glLoadMatrixx(m); +} +void +my_glLogicOp(GLenum opcode) +{ + WRAPPERS_DEBUG_PRINTF("glLogicOp()\n", opcode); + glLogicOp(opcode); +} +void +my_glMaterialx(GLenum face, GLenum pname, GLfixed param) +{ + WRAPPERS_DEBUG_PRINTF("glMaterialx()\n", face, pname, param); + glMaterialx(face, pname, param); +} +void +my_glMaterialxv(GLenum face, GLenum pname, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glMaterialxv()\n", face, pname, params); + glMaterialxv(face, pname, params); +} +void +my_glMatrixMode(GLenum mode) +{ + WRAPPERS_DEBUG_PRINTF("glMatrixMode()\n", mode); + glMatrixMode(mode); +} +void +my_glMultMatrixx(const GLfixed *m) +{ + WRAPPERS_DEBUG_PRINTF("glMultMatrixx()\n", m); + glMultMatrixx(m); +} +void +my_glMultiTexCoord4x(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) +{ + WRAPPERS_DEBUG_PRINTF("glMultiTexCoord4x()\n", target, s, t, r, q); + glMultiTexCoord4x(target, s, t, r, q); +} +void +my_glNormal3x(GLfixed nx, GLfixed ny, GLfixed nz) +{ + WRAPPERS_DEBUG_PRINTF("glNormal3x()\n", nx, ny, nz); + glNormal3x(nx, ny, nz); +} +void +my_glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer) +{ + WRAPPERS_DEBUG_PRINTF("glNormalPointer()\n", type, stride, pointer); + glNormalPointer(type, stride, pointer); +} +void +my_glOrthox(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) +{ + WRAPPERS_DEBUG_PRINTF("glOrthox()\n", left, right, bottom, top, zNear, zFar); + glOrthox(left, right, bottom, top, zNear, zFar); +} +void +my_glPixelStorei(GLenum pname, GLint param) +{ + WRAPPERS_DEBUG_PRINTF("glPixelStorei()\n", pname, param); + glPixelStorei(pname, param); +} +void +my_glPointParameterx(GLenum pname, GLfixed param) +{ + WRAPPERS_DEBUG_PRINTF("glPointParameterx()\n", pname, param); + glPointParameterx(pname, param); +} +void +my_glPointParameterxv(GLenum pname, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glPointParameterxv()\n", pname, params); + glPointParameterxv(pname, params); +} +void +my_glPointSizex(GLfixed size) +{ + WRAPPERS_DEBUG_PRINTF("glPointSizex()\n", size); + glPointSizex(size); +} +void +my_glPolygonOffsetx(GLfixed factor, GLfixed units) +{ + WRAPPERS_DEBUG_PRINTF("glPolygonOffsetx()\n", factor, units); + glPolygonOffsetx(factor, units); +} +void +my_glPopMatrix() +{ + WRAPPERS_DEBUG_PRINTF("glPopMatrix()\n"); + glPopMatrix(); +} +void +my_glPushMatrix() +{ + WRAPPERS_DEBUG_PRINTF("glPushMatrix()\n"); + glPushMatrix(); +} +void +my_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) +{ + WRAPPERS_DEBUG_PRINTF("glReadPixels()\n", x, y, width, height, format, type, pixels); + glReadPixels(x, y, width, height, format, type, pixels); +} +void +my_glRotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) +{ + WRAPPERS_DEBUG_PRINTF("glRotatex()\n", angle, x, y, z); + glRotatex(angle, x, y, z); +} +void +my_glSampleCoverage(GLclampf value, GLboolean invert) +{ + WRAPPERS_DEBUG_PRINTF("glSampleCoverage()\n", value, invert); + glSampleCoverage(value, invert); +} +void +my_glSampleCoveragex(GLclampx value, GLboolean invert) +{ + WRAPPERS_DEBUG_PRINTF("glSampleCoveragex()\n", value, invert); + glSampleCoveragex(value, invert); +} +void +my_glScalex(GLfixed x, GLfixed y, GLfixed z) +{ + WRAPPERS_DEBUG_PRINTF("glScalex()\n", x, y, z); + glScalex(x, y, z); +} +void +my_glScissor(GLint x, GLint y, GLsizei width, GLsizei height) +{ + WRAPPERS_DEBUG_PRINTF("glScissor()\n", x, y, width, height); + glScissor(x, y, width, height); +} +void +my_glShadeModel(GLenum mode) +{ + WRAPPERS_DEBUG_PRINTF("glShadeModel()\n", mode); + glShadeModel(mode); +} +void +my_glStencilFunc(GLenum func, GLint ref, GLuint mask) +{ + WRAPPERS_DEBUG_PRINTF("glStencilFunc()\n", func, ref, mask); + glStencilFunc(func, ref, mask); +} +void +my_glStencilMask(GLuint mask) +{ + WRAPPERS_DEBUG_PRINTF("glStencilMask()\n", mask); + glStencilMask(mask); +} +void +my_glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) +{ + WRAPPERS_DEBUG_PRINTF("glStencilOp()\n", fail, zfail, zpass); + glStencilOp(fail, zfail, zpass); +} +void +my_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + WRAPPERS_DEBUG_PRINTF("glTexCoordPointer()\n", size, type, stride, pointer); + glTexCoordPointer(size, type, stride, pointer); +} +void +my_glTexEnvi(GLenum target, GLenum pname, GLint param) +{ + WRAPPERS_DEBUG_PRINTF("glTexEnvi()\n", target, pname, param); + glTexEnvi(target, pname, param); +} +void +my_glTexEnvx(GLenum target, GLenum pname, GLfixed param) +{ + WRAPPERS_DEBUG_PRINTF("glTexEnvx()\n", target, pname, param); + glTexEnvx(target, pname, param); +} +void +my_glTexEnviv(GLenum target, GLenum pname, const GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glTexEnviv()\n", target, pname, params); + glTexEnviv(target, pname, params); +} +void +my_glTexEnvxv(GLenum target, GLenum pname, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glTexEnvxv()\n", target, pname, params); + glTexEnvxv(target, pname, params); +} +void +my_glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + WRAPPERS_DEBUG_PRINTF("glTexImage2D()\n", target, level, internalformat, width, height, border, format, type, pixels); + glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); +} +void +my_glTexParameteri(GLenum target, GLenum pname, GLint param) +{ + WRAPPERS_DEBUG_PRINTF("glTexParameteri()\n", target, pname, param); + glTexParameteri(target, pname, param); +} +void +my_glTexParameterx(GLenum target, GLenum pname, GLfixed param) +{ + WRAPPERS_DEBUG_PRINTF("glTexParameterx()\n", target, pname, param); + glTexParameterx(target, pname, param); +} +void +my_glTexParameteriv(GLenum target, GLenum pname, const GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glTexParameteriv()\n", target, pname, params); + glTexParameteriv(target, pname, params); +} +void +my_glTexParameterxv(GLenum target, GLenum pname, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glTexParameterxv()\n", target, pname, params); + glTexParameterxv(target, pname, params); +} +void +my_glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) +{ + WRAPPERS_DEBUG_PRINTF("glTexSubImage2D()\n", target, level, xoffset, yoffset, width, height, format, type, pixels); + glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); +} +void +my_glTranslatex(GLfixed x, GLfixed y, GLfixed z) +{ + WRAPPERS_DEBUG_PRINTF("glTranslatex()\n", x, y, z); + glTranslatex(x, y, z); +} +void +my_glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + WRAPPERS_DEBUG_PRINTF("glVertexPointer()\n", size, type, stride, pointer); + glVertexPointer(size, type, stride, pointer); +} +void +my_glViewport(GLint x, GLint y, GLsizei width, GLsizei height) +{ + WRAPPERS_DEBUG_PRINTF("glViewport()\n", x, y, width, height); + glViewport(x, y, width, height); +} +void +my_glPointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *pointer) +{ + WRAPPERS_DEBUG_PRINTF("glPointSizePointerOES()\n", type, stride, pointer); + /* No CALL */ assert(0/*glPointSizePointerOES*/); +} +void +my_glBlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha) +{ + WRAPPERS_DEBUG_PRINTF("glBlendEquationSeparateOES()\n", modeRGB, modeAlpha); + /* No CALL */ assert(0/*glBlendEquationSeparateOES*/); +} +void +my_glBlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +{ + WRAPPERS_DEBUG_PRINTF("glBlendFuncSeparateOES()\n", srcRGB, dstRGB, srcAlpha, dstAlpha); + /* No CALL */ assert(0/*glBlendFuncSeparateOES*/); +} +void +my_glBlendEquationOES(GLenum mode) +{ + WRAPPERS_DEBUG_PRINTF("glBlendEquationOES()\n", mode); + /* No CALL */ assert(0/*glBlendEquationOES*/); +} +void +my_glDrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height) +{ + WRAPPERS_DEBUG_PRINTF("glDrawTexsOES()\n", x, y, z, width, height); + /* No CALL */ assert(0/*glDrawTexsOES*/); +} +void +my_glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height) +{ + WRAPPERS_DEBUG_PRINTF("glDrawTexiOES()\n", x, y, z, width, height); + /* No CALL */ assert(0/*glDrawTexiOES*/); +} +void +my_glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height) +{ + WRAPPERS_DEBUG_PRINTF("glDrawTexxOES()\n", x, y, z, width, height); + /* No CALL */ assert(0/*glDrawTexxOES*/); +} +void +my_glDrawTexsvOES(const GLshort *coords) +{ + WRAPPERS_DEBUG_PRINTF("glDrawTexsvOES()\n", coords); + /* No CALL */ assert(0/*glDrawTexsvOES*/); +} +void +my_glDrawTexivOES(const GLint *coords) +{ + WRAPPERS_DEBUG_PRINTF("glDrawTexivOES()\n", coords); + /* No CALL */ assert(0/*glDrawTexivOES*/); +} +void +my_glDrawTexxvOES(const GLfixed *coords) +{ + WRAPPERS_DEBUG_PRINTF("glDrawTexxvOES()\n", coords); + /* No CALL */ assert(0/*glDrawTexxvOES*/); +} +void +my_glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) +{ + WRAPPERS_DEBUG_PRINTF("glDrawTexfOES()\n", x, y, z, width, height); + /* No CALL */ assert(0/*glDrawTexfOES*/); +} +void +my_glDrawTexfvOES(const GLfloat *coords) +{ + WRAPPERS_DEBUG_PRINTF("glDrawTexfvOES()\n", coords); + /* No CALL */ assert(0/*glDrawTexfvOES*/); +} +void +my_glAlphaFuncxOES(GLenum func, GLclampx ref) +{ + WRAPPERS_DEBUG_PRINTF("glAlphaFuncxOES()\n", func, ref); + /* No CALL */ assert(0/*glAlphaFuncxOES*/); +} +void +my_glClearColorxOES(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) +{ + WRAPPERS_DEBUG_PRINTF("glClearColorxOES()\n", red, green, blue, alpha); + /* No CALL */ assert(0/*glClearColorxOES*/); +} +void +my_glClearDepthxOES(GLclampx depth) +{ + WRAPPERS_DEBUG_PRINTF("glClearDepthxOES()\n", depth); + /* No CALL */ assert(0/*glClearDepthxOES*/); +} +void +my_glClipPlanexOES(GLenum plane, const GLfixed *equation) +{ + WRAPPERS_DEBUG_PRINTF("glClipPlanexOES()\n", plane, equation); + /* No CALL */ assert(0/*glClipPlanexOES*/); +} +void +my_glColor4xOES(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) +{ + WRAPPERS_DEBUG_PRINTF("glColor4xOES()\n", red, green, blue, alpha); + /* No CALL */ assert(0/*glColor4xOES*/); +} +void +my_glDepthRangexOES(GLclampx zNear, GLclampx zFar) +{ + WRAPPERS_DEBUG_PRINTF("glDepthRangexOES()\n", zNear, zFar); + /* No CALL */ assert(0/*glDepthRangexOES*/); +} +void +my_glFogxOES(GLenum pname, GLfixed param) +{ + WRAPPERS_DEBUG_PRINTF("glFogxOES()\n", pname, param); + /* No CALL */ assert(0/*glFogxOES*/); +} +void +my_glFogxvOES(GLenum pname, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glFogxvOES()\n", pname, params); + /* No CALL */ assert(0/*glFogxvOES*/); +} +void +my_glFrustumxOES(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) +{ + WRAPPERS_DEBUG_PRINTF("glFrustumxOES()\n", left, right, bottom, top, zNear, zFar); + /* No CALL */ assert(0/*glFrustumxOES*/); +} +void +my_glGetClipPlanexOES(GLenum pname, GLfixed eqn[4]) +{ + WRAPPERS_DEBUG_PRINTF("glGetClipPlanexOES()\n", pname, eqn); + /* No CALL */ assert(0/*glGetClipPlanexOES*/); +} +void +my_glGetFixedvOES(GLenum pname, GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetFixedvOES()\n", pname, params); + /* No CALL */ assert(0/*glGetFixedvOES*/); +} +void +my_glGetLightxvOES(GLenum light, GLenum pname, GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetLightxvOES()\n", light, pname, params); + /* No CALL */ assert(0/*glGetLightxvOES*/); +} +void +my_glGetMaterialxvOES(GLenum face, GLenum pname, GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetMaterialxvOES()\n", face, pname, params); + /* No CALL */ assert(0/*glGetMaterialxvOES*/); +} +void +my_glGetTexEnvxvOES(GLenum env, GLenum pname, GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexEnvxvOES()\n", env, pname, params); + /* No CALL */ assert(0/*glGetTexEnvxvOES*/); +} +void +my_glGetTexParameterxvOES(GLenum target, GLenum pname, GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexParameterxvOES()\n", target, pname, params); + /* No CALL */ assert(0/*glGetTexParameterxvOES*/); +} +void +my_glLightModelxOES(GLenum pname, GLfixed param) +{ + WRAPPERS_DEBUG_PRINTF("glLightModelxOES()\n", pname, param); + /* No CALL */ assert(0/*glLightModelxOES*/); +} +void +my_glLightModelxvOES(GLenum pname, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glLightModelxvOES()\n", pname, params); + /* No CALL */ assert(0/*glLightModelxvOES*/); +} +void +my_glLightxOES(GLenum light, GLenum pname, GLfixed param) +{ + WRAPPERS_DEBUG_PRINTF("glLightxOES()\n", light, pname, param); + /* No CALL */ assert(0/*glLightxOES*/); +} +void +my_glLightxvOES(GLenum light, GLenum pname, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glLightxvOES()\n", light, pname, params); + /* No CALL */ assert(0/*glLightxvOES*/); +} +void +my_glLineWidthxOES(GLfixed width) +{ + WRAPPERS_DEBUG_PRINTF("glLineWidthxOES()\n", width); + /* No CALL */ assert(0/*glLineWidthxOES*/); +} +void +my_glLoadMatrixxOES(const GLfixed *m) +{ + WRAPPERS_DEBUG_PRINTF("glLoadMatrixxOES()\n", m); + /* No CALL */ assert(0/*glLoadMatrixxOES*/); +} +void +my_glMaterialxOES(GLenum face, GLenum pname, GLfixed param) +{ + WRAPPERS_DEBUG_PRINTF("glMaterialxOES()\n", face, pname, param); + /* No CALL */ assert(0/*glMaterialxOES*/); +} +void +my_glMaterialxvOES(GLenum face, GLenum pname, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glMaterialxvOES()\n", face, pname, params); + /* No CALL */ assert(0/*glMaterialxvOES*/); +} +void +my_glMultMatrixxOES(const GLfixed *m) +{ + WRAPPERS_DEBUG_PRINTF("glMultMatrixxOES()\n", m); + /* No CALL */ assert(0/*glMultMatrixxOES*/); +} +void +my_glMultiTexCoord4xOES(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) +{ + WRAPPERS_DEBUG_PRINTF("glMultiTexCoord4xOES()\n", target, s, t, r, q); + /* No CALL */ assert(0/*glMultiTexCoord4xOES*/); +} +void +my_glNormal3xOES(GLfixed nx, GLfixed ny, GLfixed nz) +{ + WRAPPERS_DEBUG_PRINTF("glNormal3xOES()\n", nx, ny, nz); + /* No CALL */ assert(0/*glNormal3xOES*/); +} +void +my_glOrthoxOES(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) +{ + WRAPPERS_DEBUG_PRINTF("glOrthoxOES()\n", left, right, bottom, top, zNear, zFar); + /* No CALL */ assert(0/*glOrthoxOES*/); +} +void +my_glPointParameterxOES(GLenum pname, GLfixed param) +{ + WRAPPERS_DEBUG_PRINTF("glPointParameterxOES()\n", pname, param); + /* No CALL */ assert(0/*glPointParameterxOES*/); +} +void +my_glPointParameterxvOES(GLenum pname, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glPointParameterxvOES()\n", pname, params); + /* No CALL */ assert(0/*glPointParameterxvOES*/); +} +void +my_glPointSizexOES(GLfixed size) +{ + WRAPPERS_DEBUG_PRINTF("glPointSizexOES()\n", size); + /* No CALL */ assert(0/*glPointSizexOES*/); +} +void +my_glPolygonOffsetxOES(GLfixed factor, GLfixed units) +{ + WRAPPERS_DEBUG_PRINTF("glPolygonOffsetxOES()\n", factor, units); + /* No CALL */ assert(0/*glPolygonOffsetxOES*/); +} +void +my_glRotatexOES(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) +{ + WRAPPERS_DEBUG_PRINTF("glRotatexOES()\n", angle, x, y, z); + /* No CALL */ assert(0/*glRotatexOES*/); +} +void +my_glSampleCoveragexOES(GLclampx value, GLboolean invert) +{ + WRAPPERS_DEBUG_PRINTF("glSampleCoveragexOES()\n", value, invert); + /* No CALL */ assert(0/*glSampleCoveragexOES*/); +} +void +my_glScalexOES(GLfixed x, GLfixed y, GLfixed z) +{ + WRAPPERS_DEBUG_PRINTF("glScalexOES()\n", x, y, z); + /* No CALL */ assert(0/*glScalexOES*/); +} +void +my_glTexEnvxOES(GLenum target, GLenum pname, GLfixed param) +{ + WRAPPERS_DEBUG_PRINTF("glTexEnvxOES()\n", target, pname, param); + /* No CALL */ assert(0/*glTexEnvxOES*/); +} +void +my_glTexEnvxvOES(GLenum target, GLenum pname, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glTexEnvxvOES()\n", target, pname, params); + /* No CALL */ assert(0/*glTexEnvxvOES*/); +} +void +my_glTexParameterxOES(GLenum target, GLenum pname, GLfixed param) +{ + WRAPPERS_DEBUG_PRINTF("glTexParameterxOES()\n", target, pname, param); + /* No CALL */ assert(0/*glTexParameterxOES*/); +} +void +my_glTexParameterxvOES(GLenum target, GLenum pname, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glTexParameterxvOES()\n", target, pname, params); + /* No CALL */ assert(0/*glTexParameterxvOES*/); +} +void +my_glTranslatexOES(GLfixed x, GLfixed y, GLfixed z) +{ + WRAPPERS_DEBUG_PRINTF("glTranslatexOES()\n", x, y, z); + /* No CALL */ assert(0/*glTranslatexOES*/); +} +GLboolean +my_glIsRenderbufferOES(GLuint renderbuffer) +{ + WRAPPERS_DEBUG_PRINTF("glIsRenderbufferOES()\n", renderbuffer); + /* No CALL */ assert(0/*glIsRenderbufferOES*/); +} +void +my_glBindRenderbufferOES(GLenum target, GLuint renderbuffer) +{ + WRAPPERS_DEBUG_PRINTF("glBindRenderbufferOES()\n", target, renderbuffer); + /* No CALL */ assert(0/*glBindRenderbufferOES*/); +} +void +my_glDeleteRenderbuffersOES(GLsizei n, const GLuint *renderbuffers) +{ + WRAPPERS_DEBUG_PRINTF("glDeleteRenderbuffersOES()\n", n, renderbuffers); + /* No CALL */ assert(0/*glDeleteRenderbuffersOES*/); +} +void +my_glGenRenderbuffersOES(GLsizei n, GLuint *renderbuffers) +{ + WRAPPERS_DEBUG_PRINTF("glGenRenderbuffersOES()\n", n, renderbuffers); + /* No CALL */ assert(0/*glGenRenderbuffersOES*/); +} +void +my_glRenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ + WRAPPERS_DEBUG_PRINTF("glRenderbufferStorageOES()\n", target, internalformat, width, height); + /* No CALL */ assert(0/*glRenderbufferStorageOES*/); +} +void +my_glGetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetRenderbufferParameterivOES()\n", target, pname, params); + /* No CALL */ assert(0/*glGetRenderbufferParameterivOES*/); +} +GLboolean +my_glIsFramebufferOES(GLuint framebuffer) +{ + WRAPPERS_DEBUG_PRINTF("glIsFramebufferOES()\n", framebuffer); + /* No CALL */ assert(0/*glIsFramebufferOES*/); +} +void +my_glBindFramebufferOES(GLenum target, GLuint framebuffer) +{ + WRAPPERS_DEBUG_PRINTF("glBindFramebufferOES()\n", target, framebuffer); + /* No CALL */ assert(0/*glBindFramebufferOES*/); +} +void +my_glDeleteFramebuffersOES(GLsizei n, const GLuint *framebuffers) +{ + WRAPPERS_DEBUG_PRINTF("glDeleteFramebuffersOES()\n", n, framebuffers); + /* No CALL */ assert(0/*glDeleteFramebuffersOES*/); +} +void +my_glGenFramebuffersOES(GLsizei n, GLuint *framebuffers) +{ + WRAPPERS_DEBUG_PRINTF("glGenFramebuffersOES()\n", n, framebuffers); + /* No CALL */ assert(0/*glGenFramebuffersOES*/); +} +GLenum +my_glCheckFramebufferStatusOES(GLenum target) +{ + WRAPPERS_DEBUG_PRINTF("glCheckFramebufferStatusOES()\n", target); + /* No CALL */ assert(0/*glCheckFramebufferStatusOES*/); +} +void +my_glFramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ + WRAPPERS_DEBUG_PRINTF("glFramebufferRenderbufferOES()\n", target, attachment, renderbuffertarget, renderbuffer); + /* No CALL */ assert(0/*glFramebufferRenderbufferOES*/); +} +void +my_glFramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + WRAPPERS_DEBUG_PRINTF("glFramebufferTexture2DOES()\n", target, attachment, textarget, texture, level); + /* No CALL */ assert(0/*glFramebufferTexture2DOES*/); +} +void +my_glGetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetFramebufferAttachmentParameterivOES()\n", target, attachment, pname, params); + /* No CALL */ assert(0/*glGetFramebufferAttachmentParameterivOES*/); +} +void +my_glGenerateMipmapOES(GLenum target) +{ + WRAPPERS_DEBUG_PRINTF("glGenerateMipmapOES()\n", target); + /* No CALL */ assert(0/*glGenerateMipmapOES*/); +} +void +my_glCurrentPaletteMatrixOES(GLuint matrixpaletteindex) +{ + WRAPPERS_DEBUG_PRINTF("glCurrentPaletteMatrixOES()\n", matrixpaletteindex); + /* No CALL */ assert(0/*glCurrentPaletteMatrixOES*/); +} +void +my_glLoadPaletteFromModelViewMatrixOES() +{ + WRAPPERS_DEBUG_PRINTF("glLoadPaletteFromModelViewMatrixOES()\n"); + /* No CALL */ assert(0/*glLoadPaletteFromModelViewMatrixOES*/); +} +void +my_glMatrixIndexPointerOES(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + WRAPPERS_DEBUG_PRINTF("glMatrixIndexPointerOES()\n", size, type, stride, pointer); + /* No CALL */ assert(0/*glMatrixIndexPointerOES*/); +} +void +my_glWeightPointerOES(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + WRAPPERS_DEBUG_PRINTF("glWeightPointerOES()\n", size, type, stride, pointer); + /* No CALL */ assert(0/*glWeightPointerOES*/); +} +GLbitfield +my_glQueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16]) +{ + WRAPPERS_DEBUG_PRINTF("glQueryMatrixxOES()\n", mantissa, exponent); + /* No CALL */ assert(0/*glQueryMatrixxOES*/); +} +void +my_glDepthRangefOES(GLclampf zNear, GLclampf zFar) +{ + WRAPPERS_DEBUG_PRINTF("glDepthRangefOES()\n", zNear, zFar); + /* No CALL */ assert(0/*glDepthRangefOES*/); +} +void +my_glFrustumfOES(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) +{ + WRAPPERS_DEBUG_PRINTF("glFrustumfOES()\n", left, right, bottom, top, zNear, zFar); + /* No CALL */ assert(0/*glFrustumfOES*/); +} +void +my_glOrthofOES(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) +{ + WRAPPERS_DEBUG_PRINTF("glOrthofOES()\n", left, right, bottom, top, zNear, zFar); + /* No CALL */ assert(0/*glOrthofOES*/); +} +void +my_glClipPlanefOES(GLenum plane, const GLfloat *equation) +{ + WRAPPERS_DEBUG_PRINTF("glClipPlanefOES()\n", plane, equation); + /* No CALL */ assert(0/*glClipPlanefOES*/); +} +void +my_glGetClipPlanefOES(GLenum pname, GLfloat eqn[4]) +{ + WRAPPERS_DEBUG_PRINTF("glGetClipPlanefOES()\n", pname, eqn); + /* No CALL */ assert(0/*glGetClipPlanefOES*/); +} +void +my_glClearDepthfOES(GLclampf depth) +{ + WRAPPERS_DEBUG_PRINTF("glClearDepthfOES()\n", depth); + /* No CALL */ assert(0/*glClearDepthfOES*/); +} +void +my_glTexGenfOES(GLenum coord, GLenum pname, GLfloat param) +{ + WRAPPERS_DEBUG_PRINTF("glTexGenfOES()\n", coord, pname, param); + /* No CALL */ assert(0/*glTexGenfOES*/); +} +void +my_glTexGenfvOES(GLenum coord, GLenum pname, const GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glTexGenfvOES()\n", coord, pname, params); + /* No CALL */ assert(0/*glTexGenfvOES*/); +} +void +my_glTexGeniOES(GLenum coord, GLenum pname, GLint param) +{ + WRAPPERS_DEBUG_PRINTF("glTexGeniOES()\n", coord, pname, param); + /* No CALL */ assert(0/*glTexGeniOES*/); +} +void +my_glTexGenivOES(GLenum coord, GLenum pname, const GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glTexGenivOES()\n", coord, pname, params); + /* No CALL */ assert(0/*glTexGenivOES*/); +} +void +my_glTexGenxOES(GLenum coord, GLenum pname, GLfixed param) +{ + WRAPPERS_DEBUG_PRINTF("glTexGenxOES()\n", coord, pname, param); + /* No CALL */ assert(0/*glTexGenxOES*/); +} +void +my_glTexGenxvOES(GLenum coord, GLenum pname, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glTexGenxvOES()\n", coord, pname, params); + /* No CALL */ assert(0/*glTexGenxvOES*/); +} +void +my_glGetTexGenfvOES(GLenum coord, GLenum pname, GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexGenfvOES()\n", coord, pname, params); + /* No CALL */ assert(0/*glGetTexGenfvOES*/); +} +void +my_glGetTexGenivOES(GLenum coord, GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexGenivOES()\n", coord, pname, params); + /* No CALL */ assert(0/*glGetTexGenivOES*/); +} +void +my_glGetTexGenxvOES(GLenum coord, GLenum pname, GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexGenxvOES()\n", coord, pname, params); + /* No CALL */ assert(0/*glGetTexGenxvOES*/); +} +void +my_glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) +{ + WRAPPERS_DEBUG_PRINTF("glEGLImageTargetTexture2DOES()\n", target, image); + /* No CALL */ assert(0/*glEGLImageTargetTexture2DOES*/); +} +void +my_glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) +{ + WRAPPERS_DEBUG_PRINTF("glEGLImageTargetRenderbufferStorageOES()\n", target, image); + /* No CALL */ assert(0/*glEGLImageTargetRenderbufferStorageOES*/); +} +void * +my_glMapBufferOES(GLenum target, GLenum access) +{ + WRAPPERS_DEBUG_PRINTF("glMapBufferOES()\n", target, access); + /* No CALL */ assert(0/*glMapBufferOES*/); +} +GLboolean +my_glUnmapBufferOES(GLenum target) +{ + WRAPPERS_DEBUG_PRINTF("glUnmapBufferOES()\n", target); + /* No CALL */ assert(0/*glUnmapBufferOES*/); +} +void +my_glGetBufferPointervOES(GLenum target, GLenum pname, void **params) +{ + WRAPPERS_DEBUG_PRINTF("glGetBufferPointervOES()\n", target, pname, params); + /* No CALL */ assert(0/*glGetBufferPointervOES*/); +} +void +my_glTexBindStreamIMG(GLint device, GLint deviceoffset) +{ + WRAPPERS_DEBUG_PRINTF("glTexBindStreamIMG()\n", device, deviceoffset); + /* No CALL */ assert(0/*glTexBindStreamIMG*/); +} +void +my_glGetTexStreamDeviceAttributeivIMG(GLint device, GLenum pname, GLint *params) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexStreamDeviceAttributeivIMG()\n", device, pname, params); + /* No CALL */ assert(0/*glGetTexStreamDeviceAttributeivIMG*/); +} +const GLubyte * +my_glGetTexStreamDeviceNameIMG(GLint device) +{ + WRAPPERS_DEBUG_PRINTF("glGetTexStreamDeviceNameIMG()\n", device); + /* No CALL */ assert(0/*glGetTexStreamDeviceNameIMG*/); +} +void +my_glVertexAttrib4fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + WRAPPERS_DEBUG_PRINTF("glVertexAttrib4fARB()\n", index, x, y, z, w); + /* No CALL */ assert(0/*glVertexAttrib4fARB*/); +} +void +my_glProgramEnvParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + WRAPPERS_DEBUG_PRINTF("glProgramEnvParameter4fARB()\n", target, index, x, y, z, w); + /* No CALL */ assert(0/*glProgramEnvParameter4fARB*/); +} +void +my_glProgramEnvParameter4fvARB(GLenum target, GLuint index, const GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glProgramEnvParameter4fvARB()\n", target, index, params); + /* No CALL */ assert(0/*glProgramEnvParameter4fvARB*/); +} +void +my_glProgramLocalParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + WRAPPERS_DEBUG_PRINTF("glProgramLocalParameter4fARB()\n", target, index, x, y, z, w); + /* No CALL */ assert(0/*glProgramLocalParameter4fARB*/); +} +void +my_glProgramLocalParameter4fvARB(GLenum target, GLuint index, const GLfloat *params) +{ + WRAPPERS_DEBUG_PRINTF("glProgramLocalParameter4fvARB()\n", target, index, params); + /* No CALL */ assert(0/*glProgramLocalParameter4fvARB*/); +} +void +my_glVertexAttrib4xIMG(GLuint index, GLfixed x, GLfixed y, GLfixed z, GLfixed w) +{ + WRAPPERS_DEBUG_PRINTF("glVertexAttrib4xIMG()\n", index, x, y, z, w); + /* No CALL */ assert(0/*glVertexAttrib4xIMG*/); +} +void +my_glProgramLocalParameter4xIMG(GLenum target, GLuint index, GLfixed x, GLfixed y, GLfixed z, GLfixed w) +{ + WRAPPERS_DEBUG_PRINTF("glProgramLocalParameter4xIMG()\n", target, index, x, y, z, w); + /* No CALL */ assert(0/*glProgramLocalParameter4xIMG*/); +} +void +my_glProgramLocalParameter4xvIMG(GLenum target, GLuint index, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glProgramLocalParameter4xvIMG()\n", target, index, params); + /* No CALL */ assert(0/*glProgramLocalParameter4xvIMG*/); +} +void +my_glProgramEnvParameter4xIMG(GLenum target, GLuint index, GLfixed x, GLfixed y, GLfixed z, GLfixed w) +{ + WRAPPERS_DEBUG_PRINTF("glProgramEnvParameter4xIMG()\n", target, index, x, y, z, w); + /* No CALL */ assert(0/*glProgramEnvParameter4xIMG*/); +} +void +my_glProgramEnvParameter4xvIMG(GLenum target, GLuint index, const GLfixed *params) +{ + WRAPPERS_DEBUG_PRINTF("glProgramEnvParameter4xvIMG()\n", target, index, params); + /* No CALL */ assert(0/*glProgramEnvParameter4xvIMG*/); +} +void +my_glVertexAttribPointerARB(GLuint index, GLsizei size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) +{ + WRAPPERS_DEBUG_PRINTF("glVertexAttribPointerARB()\n", index, size, type, normalized, stride, pointer); + /* No CALL */ assert(0/*glVertexAttribPointerARB*/); +} +void +my_glEnableVertexAttribArrayARB(GLuint index) +{ + WRAPPERS_DEBUG_PRINTF("glEnableVertexAttribArrayARB()\n", index); + /* No CALL */ assert(0/*glEnableVertexAttribArrayARB*/); +} +void +my_glDisableVertexAttribArrayARB(GLuint index) +{ + WRAPPERS_DEBUG_PRINTF("glDisableVertexAttribArrayARB()\n", index); + /* No CALL */ assert(0/*glDisableVertexAttribArrayARB*/); +} +void +my_glProgramStringARB(GLenum target, GLenum format, GLsizei len, const void *string) +{ + WRAPPERS_DEBUG_PRINTF("glProgramStringARB()\n", target, format, len, string); + /* No CALL */ assert(0/*glProgramStringARB*/); +} +void +my_glBindProgramARB(GLenum target, GLuint program) +{ + WRAPPERS_DEBUG_PRINTF("glBindProgramARB()\n", target, program); + /* No CALL */ assert(0/*glBindProgramARB*/); +} +void +my_glDeleteProgramsARB(GLsizei n, const GLuint *programs) +{ + WRAPPERS_DEBUG_PRINTF("glDeleteProgramsARB()\n", n, programs); + /* No CALL */ assert(0/*glDeleteProgramsARB*/); +} +void +my_glGenProgramsARB(GLsizei n, GLuint *programs) +{ + WRAPPERS_DEBUG_PRINTF("glGenProgramsARB()\n", n, programs); + /* No CALL */ assert(0/*glGenProgramsARB*/); +} +void +my_glMultiDrawArraysEXT(GLenum mode, GLint *first, GLsizei *count, GLsizei primcount) +{ + WRAPPERS_DEBUG_PRINTF("glMultiDrawArraysEXT()\n", mode, first, count, primcount); + /* No CALL */ assert(0/*glMultiDrawArraysEXT*/); +} +void +my_glMultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount) +{ + WRAPPERS_DEBUG_PRINTF("glMultiDrawElementsEXT()\n", mode, count, type, indices, primcount); + /* No CALL */ assert(0/*glMultiDrawElementsEXT*/); +} +#endif /* APKENV_GLES */ diff --git a/compat/gles_wrappers.h b/compat/gles_wrappers.h new file mode 100644 index 0000000..f8aef75 --- /dev/null +++ b/compat/gles_wrappers.h @@ -0,0 +1,521 @@ +#ifdef APKENV_GLES +#include +#define GL_GLEXT_PROTOTYPES +#include + +#include "../apkenv.h" +void +my_glAlphaFunc(GLenum func, GLclampf ref) SOFTFP; +void +my_glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) SOFTFP; +void +my_glClearDepthf(GLclampf depth) SOFTFP; +void +my_glClipPlanef(GLenum plane, const GLfloat *equation) SOFTFP; +void +my_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) SOFTFP; +void +my_glDepthRangef(GLclampf zNear, GLclampf zFar) SOFTFP; +void +my_glFogf(GLenum pname, GLfloat param) SOFTFP; +void +my_glFogfv(GLenum pname, const GLfloat *params) SOFTFP; +void +my_glFrustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) SOFTFP; +void +my_glGetClipPlanef(GLenum pname, GLfloat eqn[4]) SOFTFP; +void +my_glGetFloatv(GLenum pname, GLfloat *params) SOFTFP; +void +my_glGetLightfv(GLenum light, GLenum pname, GLfloat *params) SOFTFP; +void +my_glGetMaterialfv(GLenum face, GLenum pname, GLfloat *params) SOFTFP; +void +my_glGetTexEnvfv(GLenum env, GLenum pname, GLfloat *params) SOFTFP; +void +my_glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params) SOFTFP; +void +my_glLightModelf(GLenum pname, GLfloat param) SOFTFP; +void +my_glLightModelfv(GLenum pname, const GLfloat *params) SOFTFP; +void +my_glLightf(GLenum light, GLenum pname, GLfloat param) SOFTFP; +void +my_glLightfv(GLenum light, GLenum pname, const GLfloat *params) SOFTFP; +void +my_glLineWidth(GLfloat width) SOFTFP; +void +my_glLoadMatrixf(const GLfloat *m) SOFTFP; +void +my_glMaterialf(GLenum face, GLenum pname, GLfloat param) SOFTFP; +void +my_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) SOFTFP; +void +my_glMultMatrixf(const GLfloat *m) SOFTFP; +void +my_glMultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) SOFTFP; +void +my_glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) SOFTFP; +void +my_glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) SOFTFP; +void +my_glPointParameterf(GLenum pname, GLfloat param) SOFTFP; +void +my_glPointParameterfv(GLenum pname, const GLfloat *params) SOFTFP; +void +my_glPointSize(GLfloat size) SOFTFP; +void +my_glPolygonOffset(GLfloat factor, GLfloat units) SOFTFP; +void +my_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) SOFTFP; +void +my_glScalef(GLfloat x, GLfloat y, GLfloat z) SOFTFP; +void +my_glTexEnvf(GLenum target, GLenum pname, GLfloat param) SOFTFP; +void +my_glTexEnvfv(GLenum target, GLenum pname, const GLfloat *params) SOFTFP; +void +my_glTexParameterf(GLenum target, GLenum pname, GLfloat param) SOFTFP; +void +my_glTexParameterfv(GLenum target, GLenum pname, const GLfloat *params) SOFTFP; +void +my_glTranslatef(GLfloat x, GLfloat y, GLfloat z) SOFTFP; +void +my_glActiveTexture(GLenum texture) SOFTFP; +void +my_glAlphaFuncx(GLenum func, GLclampx ref) SOFTFP; +void +my_glBindBuffer(GLenum target, GLuint buffer) SOFTFP; +void +my_glBindTexture(GLenum target, GLuint texture) SOFTFP; +void +my_glBlendFunc(GLenum sfactor, GLenum dfactor) SOFTFP; +void +my_glBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) SOFTFP; +void +my_glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) SOFTFP; +void +my_glClear(GLbitfield mask) SOFTFP; +void +my_glClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) SOFTFP; +void +my_glClearDepthx(GLclampx depth) SOFTFP; +void +my_glClearStencil(GLint s) SOFTFP; +void +my_glClientActiveTexture(GLenum texture) SOFTFP; +void +my_glClipPlanex(GLenum plane, const GLfixed *equation) SOFTFP; +void +my_glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) SOFTFP; +void +my_glColor4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) SOFTFP; +void +my_glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) SOFTFP; +void +my_glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) SOFTFP; +void +my_glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) SOFTFP; +void +my_glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) SOFTFP; +void +my_glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) SOFTFP; +void +my_glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) SOFTFP; +void +my_glCullFace(GLenum mode) SOFTFP; +void +my_glDeleteBuffers(GLsizei n, const GLuint *buffers) SOFTFP; +void +my_glDeleteTextures(GLsizei n, const GLuint *textures) SOFTFP; +void +my_glDepthFunc(GLenum func) SOFTFP; +void +my_glDepthMask(GLboolean flag) SOFTFP; +void +my_glDepthRangex(GLclampx zNear, GLclampx zFar) SOFTFP; +void +my_glDisable(GLenum cap) SOFTFP; +void +my_glDisableClientState(GLenum array) SOFTFP; +void +my_glDrawArrays(GLenum mode, GLint first, GLsizei count) SOFTFP; +void +my_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) SOFTFP; +void +my_glEnable(GLenum cap) SOFTFP; +void +my_glEnableClientState(GLenum array) SOFTFP; +void +my_glFinish() SOFTFP; +void +my_glFlush() SOFTFP; +void +my_glFogx(GLenum pname, GLfixed param) SOFTFP; +void +my_glFogxv(GLenum pname, const GLfixed *params) SOFTFP; +void +my_glFrontFace(GLenum mode) SOFTFP; +void +my_glFrustumx(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) SOFTFP; +void +my_glGetBooleanv(GLenum pname, GLboolean *params) SOFTFP; +void +my_glGetBufferParameteriv(GLenum target, GLenum pname, GLint *params) SOFTFP; +void +my_glGetClipPlanex(GLenum pname, GLfixed eqn[4]) SOFTFP; +void +my_glGenBuffers(GLsizei n, GLuint *buffers) SOFTFP; +void +my_glGenTextures(GLsizei n, GLuint *textures) SOFTFP; +GLenum +my_glGetError() SOFTFP; +void +my_glGetFixedv(GLenum pname, GLfixed *params) SOFTFP; +void +my_glGetIntegerv(GLenum pname, GLint *params) SOFTFP; +void +my_glGetLightxv(GLenum light, GLenum pname, GLfixed *params) SOFTFP; +void +my_glGetMaterialxv(GLenum face, GLenum pname, GLfixed *params) SOFTFP; +void +my_glGetPointerv(GLenum pname, void **params) SOFTFP; +const GLubyte * +my_glGetString(GLenum name) SOFTFP; +void +my_glGetTexEnviv(GLenum env, GLenum pname, GLint *params) SOFTFP; +void +my_glGetTexEnvxv(GLenum env, GLenum pname, GLfixed *params) SOFTFP; +void +my_glGetTexParameteriv(GLenum target, GLenum pname, GLint *params) SOFTFP; +void +my_glGetTexParameterxv(GLenum target, GLenum pname, GLfixed *params) SOFTFP; +void +my_glHint(GLenum target, GLenum mode) SOFTFP; +GLboolean +my_glIsBuffer(GLuint buffer) SOFTFP; +GLboolean +my_glIsEnabled(GLenum cap) SOFTFP; +GLboolean +my_glIsTexture(GLuint texture) SOFTFP; +void +my_glLightModelx(GLenum pname, GLfixed param) SOFTFP; +void +my_glLightModelxv(GLenum pname, const GLfixed *params) SOFTFP; +void +my_glLightx(GLenum light, GLenum pname, GLfixed param) SOFTFP; +void +my_glLightxv(GLenum light, GLenum pname, const GLfixed *params) SOFTFP; +void +my_glLineWidthx(GLfixed width) SOFTFP; +void +my_glLoadIdentity() SOFTFP; +void +my_glLoadMatrixx(const GLfixed *m) SOFTFP; +void +my_glLogicOp(GLenum opcode) SOFTFP; +void +my_glMaterialx(GLenum face, GLenum pname, GLfixed param) SOFTFP; +void +my_glMaterialxv(GLenum face, GLenum pname, const GLfixed *params) SOFTFP; +void +my_glMatrixMode(GLenum mode) SOFTFP; +void +my_glMultMatrixx(const GLfixed *m) SOFTFP; +void +my_glMultiTexCoord4x(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) SOFTFP; +void +my_glNormal3x(GLfixed nx, GLfixed ny, GLfixed nz) SOFTFP; +void +my_glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer) SOFTFP; +void +my_glOrthox(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) SOFTFP; +void +my_glPixelStorei(GLenum pname, GLint param) SOFTFP; +void +my_glPointParameterx(GLenum pname, GLfixed param) SOFTFP; +void +my_glPointParameterxv(GLenum pname, const GLfixed *params) SOFTFP; +void +my_glPointSizex(GLfixed size) SOFTFP; +void +my_glPolygonOffsetx(GLfixed factor, GLfixed units) SOFTFP; +void +my_glPopMatrix() SOFTFP; +void +my_glPushMatrix() SOFTFP; +void +my_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) SOFTFP; +void +my_glRotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) SOFTFP; +void +my_glSampleCoverage(GLclampf value, GLboolean invert) SOFTFP; +void +my_glSampleCoveragex(GLclampx value, GLboolean invert) SOFTFP; +void +my_glScalex(GLfixed x, GLfixed y, GLfixed z) SOFTFP; +void +my_glScissor(GLint x, GLint y, GLsizei width, GLsizei height) SOFTFP; +void +my_glShadeModel(GLenum mode) SOFTFP; +void +my_glStencilFunc(GLenum func, GLint ref, GLuint mask) SOFTFP; +void +my_glStencilMask(GLuint mask) SOFTFP; +void +my_glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) SOFTFP; +void +my_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) SOFTFP; +void +my_glTexEnvi(GLenum target, GLenum pname, GLint param) SOFTFP; +void +my_glTexEnvx(GLenum target, GLenum pname, GLfixed param) SOFTFP; +void +my_glTexEnviv(GLenum target, GLenum pname, const GLint *params) SOFTFP; +void +my_glTexEnvxv(GLenum target, GLenum pname, const GLfixed *params) SOFTFP; +void +my_glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) SOFTFP; +void +my_glTexParameteri(GLenum target, GLenum pname, GLint param) SOFTFP; +void +my_glTexParameterx(GLenum target, GLenum pname, GLfixed param) SOFTFP; +void +my_glTexParameteriv(GLenum target, GLenum pname, const GLint *params) SOFTFP; +void +my_glTexParameterxv(GLenum target, GLenum pname, const GLfixed *params) SOFTFP; +void +my_glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) SOFTFP; +void +my_glTranslatex(GLfixed x, GLfixed y, GLfixed z) SOFTFP; +void +my_glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) SOFTFP; +void +my_glViewport(GLint x, GLint y, GLsizei width, GLsizei height) SOFTFP; +void +my_glPointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *pointer) SOFTFP; +void +my_glBlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha) SOFTFP; +void +my_glBlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) SOFTFP; +void +my_glBlendEquationOES(GLenum mode) SOFTFP; +void +my_glDrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height) SOFTFP; +void +my_glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height) SOFTFP; +void +my_glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height) SOFTFP; +void +my_glDrawTexsvOES(const GLshort *coords) SOFTFP; +void +my_glDrawTexivOES(const GLint *coords) SOFTFP; +void +my_glDrawTexxvOES(const GLfixed *coords) SOFTFP; +void +my_glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) SOFTFP; +void +my_glDrawTexfvOES(const GLfloat *coords) SOFTFP; +void +my_glAlphaFuncxOES(GLenum func, GLclampx ref) SOFTFP; +void +my_glClearColorxOES(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) SOFTFP; +void +my_glClearDepthxOES(GLclampx depth) SOFTFP; +void +my_glClipPlanexOES(GLenum plane, const GLfixed *equation) SOFTFP; +void +my_glColor4xOES(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) SOFTFP; +void +my_glDepthRangexOES(GLclampx zNear, GLclampx zFar) SOFTFP; +void +my_glFogxOES(GLenum pname, GLfixed param) SOFTFP; +void +my_glFogxvOES(GLenum pname, const GLfixed *params) SOFTFP; +void +my_glFrustumxOES(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) SOFTFP; +void +my_glGetClipPlanexOES(GLenum pname, GLfixed eqn[4]) SOFTFP; +void +my_glGetFixedvOES(GLenum pname, GLfixed *params) SOFTFP; +void +my_glGetLightxvOES(GLenum light, GLenum pname, GLfixed *params) SOFTFP; +void +my_glGetMaterialxvOES(GLenum face, GLenum pname, GLfixed *params) SOFTFP; +void +my_glGetTexEnvxvOES(GLenum env, GLenum pname, GLfixed *params) SOFTFP; +void +my_glGetTexParameterxvOES(GLenum target, GLenum pname, GLfixed *params) SOFTFP; +void +my_glLightModelxOES(GLenum pname, GLfixed param) SOFTFP; +void +my_glLightModelxvOES(GLenum pname, const GLfixed *params) SOFTFP; +void +my_glLightxOES(GLenum light, GLenum pname, GLfixed param) SOFTFP; +void +my_glLightxvOES(GLenum light, GLenum pname, const GLfixed *params) SOFTFP; +void +my_glLineWidthxOES(GLfixed width) SOFTFP; +void +my_glLoadMatrixxOES(const GLfixed *m) SOFTFP; +void +my_glMaterialxOES(GLenum face, GLenum pname, GLfixed param) SOFTFP; +void +my_glMaterialxvOES(GLenum face, GLenum pname, const GLfixed *params) SOFTFP; +void +my_glMultMatrixxOES(const GLfixed *m) SOFTFP; +void +my_glMultiTexCoord4xOES(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) SOFTFP; +void +my_glNormal3xOES(GLfixed nx, GLfixed ny, GLfixed nz) SOFTFP; +void +my_glOrthoxOES(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) SOFTFP; +void +my_glPointParameterxOES(GLenum pname, GLfixed param) SOFTFP; +void +my_glPointParameterxvOES(GLenum pname, const GLfixed *params) SOFTFP; +void +my_glPointSizexOES(GLfixed size) SOFTFP; +void +my_glPolygonOffsetxOES(GLfixed factor, GLfixed units) SOFTFP; +void +my_glRotatexOES(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) SOFTFP; +void +my_glSampleCoveragexOES(GLclampx value, GLboolean invert) SOFTFP; +void +my_glScalexOES(GLfixed x, GLfixed y, GLfixed z) SOFTFP; +void +my_glTexEnvxOES(GLenum target, GLenum pname, GLfixed param) SOFTFP; +void +my_glTexEnvxvOES(GLenum target, GLenum pname, const GLfixed *params) SOFTFP; +void +my_glTexParameterxOES(GLenum target, GLenum pname, GLfixed param) SOFTFP; +void +my_glTexParameterxvOES(GLenum target, GLenum pname, const GLfixed *params) SOFTFP; +void +my_glTranslatexOES(GLfixed x, GLfixed y, GLfixed z) SOFTFP; +GLboolean +my_glIsRenderbufferOES(GLuint renderbuffer) SOFTFP; +void +my_glBindRenderbufferOES(GLenum target, GLuint renderbuffer) SOFTFP; +void +my_glDeleteRenderbuffersOES(GLsizei n, const GLuint *renderbuffers) SOFTFP; +void +my_glGenRenderbuffersOES(GLsizei n, GLuint *renderbuffers) SOFTFP; +void +my_glRenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) SOFTFP; +void +my_glGetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint *params) SOFTFP; +GLboolean +my_glIsFramebufferOES(GLuint framebuffer) SOFTFP; +void +my_glBindFramebufferOES(GLenum target, GLuint framebuffer) SOFTFP; +void +my_glDeleteFramebuffersOES(GLsizei n, const GLuint *framebuffers) SOFTFP; +void +my_glGenFramebuffersOES(GLsizei n, GLuint *framebuffers) SOFTFP; +GLenum +my_glCheckFramebufferStatusOES(GLenum target) SOFTFP; +void +my_glFramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) SOFTFP; +void +my_glFramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) SOFTFP; +void +my_glGetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint *params) SOFTFP; +void +my_glGenerateMipmapOES(GLenum target) SOFTFP; +void +my_glCurrentPaletteMatrixOES(GLuint matrixpaletteindex) SOFTFP; +void +my_glLoadPaletteFromModelViewMatrixOES() SOFTFP; +void +my_glMatrixIndexPointerOES(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) SOFTFP; +void +my_glWeightPointerOES(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) SOFTFP; +GLbitfield +my_glQueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16]) SOFTFP; +void +my_glDepthRangefOES(GLclampf zNear, GLclampf zFar) SOFTFP; +void +my_glFrustumfOES(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) SOFTFP; +void +my_glOrthofOES(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) SOFTFP; +void +my_glClipPlanefOES(GLenum plane, const GLfloat *equation) SOFTFP; +void +my_glGetClipPlanefOES(GLenum pname, GLfloat eqn[4]) SOFTFP; +void +my_glClearDepthfOES(GLclampf depth) SOFTFP; +void +my_glTexGenfOES(GLenum coord, GLenum pname, GLfloat param) SOFTFP; +void +my_glTexGenfvOES(GLenum coord, GLenum pname, const GLfloat *params) SOFTFP; +void +my_glTexGeniOES(GLenum coord, GLenum pname, GLint param) SOFTFP; +void +my_glTexGenivOES(GLenum coord, GLenum pname, const GLint *params) SOFTFP; +void +my_glTexGenxOES(GLenum coord, GLenum pname, GLfixed param) SOFTFP; +void +my_glTexGenxvOES(GLenum coord, GLenum pname, const GLfixed *params) SOFTFP; +void +my_glGetTexGenfvOES(GLenum coord, GLenum pname, GLfloat *params) SOFTFP; +void +my_glGetTexGenivOES(GLenum coord, GLenum pname, GLint *params) SOFTFP; +void +my_glGetTexGenxvOES(GLenum coord, GLenum pname, GLfixed *params) SOFTFP; +void +my_glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) SOFTFP; +void +my_glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) SOFTFP; +void * +my_glMapBufferOES(GLenum target, GLenum access) SOFTFP; +GLboolean +my_glUnmapBufferOES(GLenum target) SOFTFP; +void +my_glGetBufferPointervOES(GLenum target, GLenum pname, void **params) SOFTFP; +void +my_glTexBindStreamIMG(GLint device, GLint deviceoffset) SOFTFP; +void +my_glGetTexStreamDeviceAttributeivIMG(GLint device, GLenum pname, GLint *params) SOFTFP; +const GLubyte * +my_glGetTexStreamDeviceNameIMG(GLint device) SOFTFP; +void +my_glVertexAttrib4fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) SOFTFP; +void +my_glProgramEnvParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) SOFTFP; +void +my_glProgramEnvParameter4fvARB(GLenum target, GLuint index, const GLfloat *params) SOFTFP; +void +my_glProgramLocalParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) SOFTFP; +void +my_glProgramLocalParameter4fvARB(GLenum target, GLuint index, const GLfloat *params) SOFTFP; +void +my_glVertexAttrib4xIMG(GLuint index, GLfixed x, GLfixed y, GLfixed z, GLfixed w) SOFTFP; +void +my_glProgramLocalParameter4xIMG(GLenum target, GLuint index, GLfixed x, GLfixed y, GLfixed z, GLfixed w) SOFTFP; +void +my_glProgramLocalParameter4xvIMG(GLenum target, GLuint index, const GLfixed *params) SOFTFP; +void +my_glProgramEnvParameter4xIMG(GLenum target, GLuint index, GLfixed x, GLfixed y, GLfixed z, GLfixed w) SOFTFP; +void +my_glProgramEnvParameter4xvIMG(GLenum target, GLuint index, const GLfixed *params) SOFTFP; +void +my_glVertexAttribPointerARB(GLuint index, GLsizei size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) SOFTFP; +void +my_glEnableVertexAttribArrayARB(GLuint index) SOFTFP; +void +my_glDisableVertexAttribArrayARB(GLuint index) SOFTFP; +void +my_glProgramStringARB(GLenum target, GLenum format, GLsizei len, const void *string) SOFTFP; +void +my_glBindProgramARB(GLenum target, GLuint program) SOFTFP; +void +my_glDeleteProgramsARB(GLsizei n, const GLuint *programs) SOFTFP; +void +my_glGenProgramsARB(GLsizei n, GLuint *programs) SOFTFP; +void +my_glMultiDrawArraysEXT(GLenum mode, GLint *first, GLsizei *count, GLsizei primcount) SOFTFP; +void +my_glMultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount) SOFTFP; +#endif /* APKENV_GLES */ diff --git a/compat/hooks.c b/compat/hooks.c new file mode 100644 index 0000000..00980a7 --- /dev/null +++ b/compat/hooks.c @@ -0,0 +1,78 @@ + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * Based on code from libhybris: Copyright (c) 2012 Carsten Munk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + +#define _GNU_SOURCE +#include +#include +#include + +#include "hooks.h" + +#include "libc_wrappers.h" +#include "liblog_wrappers.h" +#include "gles_wrappers.h" +#include "gles2_wrappers.h" +#include "pthread_wrappers.h" + + +char my___sF[1024]; + +static struct _hook hooks[] = { +#include "libc_mapping.h" +#include "liblog_mapping.h" +#include "gles_mapping.h" +#include "gles2_mapping.h" +#include "pthread_mapping.h" + + {"__sF", my___sF}, + + {NULL, NULL}, +}; + +void *get_hooked_symbol(char *sym) +{ + struct _hook *ptr = &hooks[0]; + + while (ptr->name != NULL) { + if (strcmp(sym, ptr->name) == 0) { + return ptr->func; + } + ptr++; + } + + if (strstr(sym, "pthread") != NULL) { + printf("Unimplemented: %s\n", sym); + exit(0); + } + + return NULL; +} + diff --git a/compat/hooks.h b/compat/hooks.h new file mode 100644 index 0000000..8d006a7 --- /dev/null +++ b/compat/hooks.h @@ -0,0 +1,42 @@ +#ifndef COMPAT_HOOKS_H +#define COMPAT_HOOKS_H + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * Based on code from libhybris: Copyright (c) 2012 Carsten Munk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + + +struct _hook { + const char *name; + void *func; +}; + +void *get_hooked_symbol(char *sym); + +#endif /* COMPAT_HOOKS_H */ diff --git a/compat/libc_mapping.h b/compat/libc_mapping.h new file mode 100644 index 0000000..e7b3520 --- /dev/null +++ b/compat/libc_mapping.h @@ -0,0 +1,216 @@ + +{"malloc", malloc}, +{"realloc", realloc}, +{"calloc", calloc}, +{"free", free}, +{"strdup", strdup}, + +{"open", open}, +{"read", read}, +{"write", write}, +{"writev", writev}, +{"lseek", lseek}, +{"select", select}, +{"close", close}, +{"fstat", fstat}, + +{"printf", printf}, +{"sprintf", sprintf}, +{"snprintf", my_snprintf}, +//{"vsnprintf", my_vsnprintf}, + +{"fopen", my_fopen}, +{"fdopen", fdopen}, +{"freopen", freopen}, +{"fflush", my_fflush}, +{"fclose", my_fclose}, +{"fcntl", fcntl}, +{"fprintf", my_fprintf}, +{"vprintf", vprintf}, +{"vfprintf", my_vfprintf}, +{"fputc", fputc}, +{"fputs", fputs}, +{"fgets", fgets}, +{"fgetpos", fgetpos}, +{"fsetpos", fsetpos}, +{"fscanf", fscanf}, +{"sscanf", sscanf}, +{"fseek", fseek}, +{"fileno", fileno}, +{"fsync", fsync}, +{"ftell", ftell}, +{"fread", fread}, +{"fwrite", fwrite}, +{"puts", puts}, +{"putc", putc}, +{"putchar", putchar}, +{"getc", putc}, +{"ungetc", ungetc}, +{"tmpfile", tmpfile}, +{"setvbuf", setvbuf}, +{"ftello", ftello}, +{"fseeko", fseeko}, +{"ferror", ferror}, + +{"setenv", setenv}, +{"sysconf", sysconf}, + +{"getaddrinfo", getaddrinfo}, +{"freeaddrinfo", freeaddrinfo}, + +{"gmtime", gmtime}, +{"localtime", localtime}, +{"mktime", mktime}, +{"strftime", strftime}, + +{"setlocale", setlocale}, + +{"getenv", my_getenv}, +{"geteuid", geteuid}, +{"getpid", getpid}, +{"geteuid", geteuid}, + +{"clearerr", clearerr}, + +{"ioctl", ioctl}, +{"mmap", mmap}, +{"munmap", munmap}, +{"poll", poll}, + +{"mkdir", mkdir}, +{"chmod", chmod}, +{"umask", umask}, +{"clearerr", clearerr}, +{"remove", my_remove}, +{"rename", my_rename}, +{"stat", stat}, + +{"accept", accept}, +{"listen", listen}, +{"alarm", alarm}, +{"atoi", atoi}, +{"atol", atol}, +{"basename", basename}, +{"bind", bind}, +{"clock_gettime", clock_gettime}, + +{"geteuid", geteuid}, +{"getpeername", getpeername}, +{"getpwuid", getpwuid}, +{"getsockname", getsockname}, +{"getsockopt", getsockopt}, +{"gmtime_r", gmtime_r}, +{"inet_ntop", inet_ntop}, +{"inet_pton", inet_pton}, +{"inet_pton", inet_pton}, + +{"memrchr", memrchr}, +{"qsort", qsort}, +{"bsearch", bsearch}, +{"shutdown", shutdown}, +{"sigaction", sigaction}, +{"siglongjmp", siglongjmp}, +//{"sigsetjmp", _sigsetjmp}, +{"strtok_r", strtok_r}, +{"strncasecmp", strncasecmp}, + +{"strerror_r", strerror_r}, +{"strerror", strerror}, +{"strcspn", strcspn}, +{"strsep", strsep}, +{"strcoll", strcoll}, +{"strcspn", my_strcspn}, +{"strerror", my_strerror}, +{"strpbrk", my_strpbrk}, +{"system", my_system}, +{"tmpnam", my_tmpnam}, +{"usleep", usleep}, + +{"connect", my_connect}, +{"recv", my_recv}, +{"sched_yield", my_sched_yield}, +{"send", my_send}, +{"socket", my_socket}, +{"setsockopt", my_setsockopt}, + +{"gettimeofday", my_gettimeofday}, + +{"abort", my_abort}, +{"clock", my_clock}, +{"difftime", my_difftime}, +{"exit", my_exit}, + +{"strchr", strchr}, +{"strcpy", strcpy}, +{"strcasecmp", strcasecmp}, +{"strcat", strcat}, +{"strtoul", strtoul}, +{"strrchr", strrchr}, +{"strncmp", strncmp}, +{"strncat", strncat}, +{"strlen", strlen}, +{"strtod", my_strtod}, +{"strtol", strtol}, +{"strtok", strtok}, +{"strncpy", strncpy}, +{"strcmp", strcmp}, +{"strstr", strstr}, +{"memmove", memmove}, +{"memset", memset}, +{"memcpy", memcpy}, +{"memchr", memchr}, +{"memcmp", memcmp}, +{"time", time}, + +{"setjmp", setjmp}, +{"longjmp", longjmp}, +{"raise", raise}, + +{"srand48", srand48}, +{"lrand48", lrand48}, + +{"iswalpha", iswalpha}, +{"iswspace", iswspace}, +{"iswlower", iswlower}, +{"islower", islower}, +{"isupper", isupper}, +{"ispunct", ispunct}, +{"iswxdigit", iswxdigit}, +{"iscntrl", iscntrl}, +{"iswprint", iswprint}, +{"iswupper", iswupper}, +{"iswcntrl", iswcntrl}, +{"iswpunct", iswpunct}, +{"iswdigit", iswdigit}, +{"isprint", isprint}, +{"isalpha", isalpha}, +{"isspace", isspace}, +{"isxdigit", isxdigit}, + +{"tolower", tolower}, +{"toupper", toupper}, +{"towlower", towlower}, +{"towupper", towupper}, +{"wcsncpy", wcsncpy}, +{"wcscmp", wcscmp}, +{"wmemmove", wmemmove}, +{"wmemset", wmemset}, +{"wmemcpy", wmemcpy}, +{"wmemchr", wmemchr}, +{"wmemcmp", wmemcmp}, +{"wcslen", wcslen}, + +/* zlib */ +{"inflate", inflate}, +{"inflateInit_", inflateInit_}, +{"inflateInit2_", inflateInit2_}, +{"inflateReset", inflateReset}, +{"inflateEnd", inflateEnd}, +{"deflate", deflate}, +{"deflateInit2_", deflateInit2_}, +{"deflateEnd", deflateEnd}, +{"crc32", crc32}, +{"gzopen", gzopen}, +{"gzclose", gzclose}, +{"gzgets", gzgets}, + diff --git a/compat/libc_wrappers.c b/compat/libc_wrappers.c new file mode 100644 index 0000000..65bef95 --- /dev/null +++ b/compat/libc_wrappers.c @@ -0,0 +1,727 @@ +#include "libc_wrappers.h" + +#include + +#ifdef APKENV_DEBUG +# define WRAPPERS_DEBUG_PRINTF(...) printf(__VA_ARGS__) +#else +# define WRAPPERS_DEBUG_PRINTF(...) +#endif + +extern char my___sF[1024]; + +void +my_abort() +{ + WRAPPERS_DEBUG_PRINTF("abort()\n"); + abort(); +} +double +my_acos(double __x) +{ + WRAPPERS_DEBUG_PRINTF("acos()\n", __x); + return acos(__x); +} +double +my_asin(double __x) +{ + WRAPPERS_DEBUG_PRINTF("asin()\n", __x); + return asin(__x); +} +double +my_atan(double __x) +{ + WRAPPERS_DEBUG_PRINTF("atan()\n", __x); + return atan(__x); +} +double +my_atan2(double __y, double __x) +{ + WRAPPERS_DEBUG_PRINTF("atan2()\n", __y, __x); + return atan2(__y, __x); +} +double +my_ceil(double __x) +{ + WRAPPERS_DEBUG_PRINTF("ceil()\n", __x); + return ceil(__x); +} +clock_t +my_clock() +{ + WRAPPERS_DEBUG_PRINTF("clock()\n"); + return clock(); +} +int +my_close(int __fd) +{ + WRAPPERS_DEBUG_PRINTF("close()\n", __fd); + return close(__fd); +} +int +my_connect(int __fd, __const struct sockaddr *__addr, socklen_t __len) +{ + WRAPPERS_DEBUG_PRINTF("connect()\n", __fd, __addr, __len); + return connect(__fd, __addr, __len); +} +double +my_cos(double __x) +{ + WRAPPERS_DEBUG_PRINTF("cos()\n", __x); + return cos(__x); +} +double +my_cosh(double __x) +{ + WRAPPERS_DEBUG_PRINTF("cosh()\n", __x); + return cosh(__x); +} +uLong +my_crc32(uLong crc, const Bytef *buf, uInt len) +{ + WRAPPERS_DEBUG_PRINTF("crc32()\n", crc, buf, len); + return crc32(crc, buf, len); +} +double +my_difftime(time_t __time1, time_t __time0) +{ + WRAPPERS_DEBUG_PRINTF("difftime()\n", __time1, __time0); + return difftime(__time1, __time0); +} +void +my_exit(int __status) +{ + WRAPPERS_DEBUG_PRINTF("exit()\n", __status); + exit(__status); +} +double +my_exp(double __x) +{ + WRAPPERS_DEBUG_PRINTF("exp()\n", __x); + return exp(__x); +} +int +my_fclose(FILE *__stream) +{ + //WRAPPERS_DEBUG_PRINTF("fclose(%x, %x)\n", __stream, &my___sF); + int offset = ((void*)__stream - (void*)(&my___sF)); + //printf("offset: %d\n", offset); + if (offset < 1000) { + printf("IGNORING CLOSE\n"); + return 0; + } + return fclose(__stream); +} +int +my_fcntl(int __fd, int __cmd, ...) +{ + WRAPPERS_DEBUG_PRINTF("fcntl()\n", __fd, __cmd); + return fcntl(__fd, __cmd); +} +char * +my_fgets(char *__restrict __s, int __n, FILE *__restrict __stream) +{ + WRAPPERS_DEBUG_PRINTF("fgets()\n", __s, __n, __stream); + return fgets(__s, __n, __stream); +} +double +my_floor(double __x) +{ + WRAPPERS_DEBUG_PRINTF("floor()\n", __x); + return floor(__x); +} +double +my_fmod(double __x, double __y) +{ + WRAPPERS_DEBUG_PRINTF("fmod()\n", __x, __y); + return fmod(__x, __y); +} +FILE * +my_fopen(__const char *__restrict __filename, __const char *__restrict __modes) +{ + //WRAPPERS_DEBUG_PRINTF("fopen(%s, %s)\n", __filename, __modes); + return fopen(__filename, __modes); +} +int +my_fputc(int __c, FILE *__stream) +{ + WRAPPERS_DEBUG_PRINTF("fputc()\n", __c, __stream); + return fputc(__c, __stream); +} +int +my_fputs(__const char *__restrict __s, FILE *__restrict __stream) +{ + WRAPPERS_DEBUG_PRINTF("fputs()\n", __s, __stream); + return fputs(__s, __stream); +} +size_t +my_fread(void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __stream) +{ + WRAPPERS_DEBUG_PRINTF("fread(%x, %d, %d, %x)\n", __ptr, __size, __n, __stream); + size_t result = fread(__ptr, __size, __n, __stream); + WRAPPERS_DEBUG_PRINTF("fread done: %d\n", result); + return result; +} +void +my_free(void *__ptr) +{ + WRAPPERS_DEBUG_PRINTF("free()\n", __ptr); + free(__ptr); +} +void +my_freeaddrinfo(struct addrinfo *__ai) +{ + WRAPPERS_DEBUG_PRINTF("freeaddrinfo()\n", __ai); + freeaddrinfo(__ai); +} +FILE * +my_freopen(__const char *__restrict __filename, __const char *__restrict __modes, FILE *__restrict __stream) +{ + WRAPPERS_DEBUG_PRINTF("freopen()\n", __filename, __modes, __stream); + return freopen(__filename, __modes, __stream); +} +double +my_frexp(double __x, int *__exponent) +{ + WRAPPERS_DEBUG_PRINTF("frexp()\n", __x, __exponent); + return frexp(__x, __exponent); +} +int +my_fscanf(FILE *__restrict __stream, __const char *__restrict __format, ...) +{ + WRAPPERS_DEBUG_PRINTF("fscanf()\n", __stream, __format); + return fscanf(__stream, __format); +} +int +my_fseek(FILE *__stream, long int __off, int __whence) +{ + WRAPPERS_DEBUG_PRINTF("fseek(%x, %d, %d)\n", __stream, __off, __whence); + return fseek(__stream, __off, __whence); +} +int +my_fsync(int __fd) +{ + WRAPPERS_DEBUG_PRINTF("fsync()\n", __fd); + return fsync(__fd); +} +long int +my_ftell(FILE *__stream) +{ + WRAPPERS_DEBUG_PRINTF("ftell()\n", __stream); + return ftell(__stream); +} +size_t +my_fwrite(__const void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __s) +{ + WRAPPERS_DEBUG_PRINTF("fwrite()\n", __ptr, __size, __n, __s); + return fwrite(__ptr, __size, __n, __s); +} +int +my_getaddrinfo(__const char *__restrict __name, __const char *__restrict __service, __const struct addrinfo *__restrict __req, struct addrinfo **__restrict __pai) +{ + WRAPPERS_DEBUG_PRINTF("getaddrinfo()\n", __name, __service, __req, __pai); + return getaddrinfo(__name, __service, __req, __pai); +} +char * +my_getenv(__const char *__name) +{ + WRAPPERS_DEBUG_PRINTF("getenv(%s)\n", __name); + return getenv(__name); +} +int +my_gettimeofday(struct timeval *__restrict __tv, __timezone_ptr_t __tz) +{ + WRAPPERS_DEBUG_PRINTF("gettimeofday()\n", __tv, __tz); + return gettimeofday(__tv, __tz); +} +struct tm * +my_gmtime(__const time_t *__timer) +{ + WRAPPERS_DEBUG_PRINTF("gmtime()\n", __timer); + return gmtime(__timer); +} +int +my_inflate(z_streamp strm, int flush) +{ + WRAPPERS_DEBUG_PRINTF("inflate()\n", strm, flush); + return inflate(strm, flush); +} +int +my_inflateEnd(z_streamp strm) +{ + WRAPPERS_DEBUG_PRINTF("inflateEnd()\n", strm); + return inflateEnd(strm); +} +int +my_inflateInit_(z_streamp strm, const char *version, int stream_size) +{ + WRAPPERS_DEBUG_PRINTF("inflateInit_()\n", strm, version, stream_size); + return inflateInit_(strm, version, stream_size); +} +int +my_inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size) +{ + WRAPPERS_DEBUG_PRINTF("inflateInit2_()\n", strm, windowBits, version, stream_size); + return inflateInit2_(strm, windowBits, version, stream_size); +} +int +my_inflateReset(z_streamp strm) +{ + WRAPPERS_DEBUG_PRINTF("inflateReset()\n", strm); + return inflateReset(strm); +} +double +my_ldexp(double __x, int __exponent) +{ + WRAPPERS_DEBUG_PRINTF("ldexp()\n", __x, __exponent); + return ldexp(__x, __exponent); +} +struct tm * +my_localtime(__const time_t *__timer) +{ + WRAPPERS_DEBUG_PRINTF("localtime()\n", __timer); + return localtime(__timer); +} +double +my_log(double __x) +{ + WRAPPERS_DEBUG_PRINTF("log()\n", __x); + return log(__x); +} +double +my_log10(double __x) +{ + WRAPPERS_DEBUG_PRINTF("log10()\n", __x); + return log10(__x); +} +void +my_longjmp(struct __jmp_buf_tag __env[1], int __val) +{ + WRAPPERS_DEBUG_PRINTF("longjmp()\n", __env, __val); + longjmp(__env, __val); +} +long int +my_lrand48() +{ + WRAPPERS_DEBUG_PRINTF("lrand48()\n"); + return lrand48(); +} +__off_t +my_lseek(int __fd, __off_t __offset, int __whence) +{ + WRAPPERS_DEBUG_PRINTF("lseek()\n", __fd, __offset, __whence); + return lseek(__fd, __offset, __whence); +} +void * +my_malloc(size_t __size) +{ + WRAPPERS_DEBUG_PRINTF("malloc()\n", __size); + return malloc(__size); +} +void * +my_memchr(__const void *__s, int __c, size_t __n) +{ + WRAPPERS_DEBUG_PRINTF("memchr()\n", __s, __c, __n); + return memchr(__s, __c, __n); +} +int +my_memcmp(__const void *__s1, __const void *__s2, size_t __n) +{ + WRAPPERS_DEBUG_PRINTF("memcmp()\n", __s1, __s2, __n); + return memcmp(__s1, __s2, __n); +} +void * +my_memcpy(void *__restrict __dest, __const void *__restrict __src, size_t __n) +{ + WRAPPERS_DEBUG_PRINTF("memcpy() -> memmove!\n", __dest, __src, __n); + return memmove(__dest, __src, __n); +} +void * +my_memmove(void *__dest, __const void *__src, size_t __n) +{ + WRAPPERS_DEBUG_PRINTF("memmove()\n", __dest, __src, __n); + return memmove(__dest, __src, __n); +} +void * +my_memset(void *__s, int __c, size_t __n) +{ + WRAPPERS_DEBUG_PRINTF("memset()\n", __s, __c, __n); + return memset(__s, __c, __n); +} +time_t +my_mktime(struct tm *__tp) +{ + WRAPPERS_DEBUG_PRINTF("mktime()\n", __tp); + return mktime(__tp); +} +double +my_modf(double __x, double *__iptr) +{ + WRAPPERS_DEBUG_PRINTF("modf()\n", __x, __iptr); + return modf(__x, __iptr); +} +int +my_open(__const char *__file, int __oflag, ...) +{ + WRAPPERS_DEBUG_PRINTF("open()\n", __file, __oflag); + return open(__file, __oflag); +} +double +my_pow(double __x, double __y) +{ + WRAPPERS_DEBUG_PRINTF("pow()\n", __x, __y); + return pow(__x, __y); +} +int +my_printf(__const char *__restrict __format, ...) +{ + WRAPPERS_DEBUG_PRINTF("WRAPPERS_DEBUG_PRINTF()\n", __format); + return WRAPPERS_DEBUG_PRINTF(__format); +} +int +my_puts(__const char *__s) +{ + WRAPPERS_DEBUG_PRINTF("puts()\n", __s); + return puts(__s); +} +int +my_raise(int __sig) +{ + WRAPPERS_DEBUG_PRINTF("raise()\n", __sig); + return raise(__sig); +} +ssize_t +my_read(int __fd, void *__buf, size_t __nbytes) +{ + WRAPPERS_DEBUG_PRINTF("read()\n", __fd, __buf, __nbytes); + return read(__fd, __buf, __nbytes); +} +void * +my_realloc(void *__ptr, size_t __size) +{ + WRAPPERS_DEBUG_PRINTF("realloc()\n", __ptr, __size); + return realloc(__ptr, __size); +} +ssize_t +my_recv(int __fd, void *__buf, size_t __n, int __flags) +{ + WRAPPERS_DEBUG_PRINTF("recv()\n", __fd, __buf, __n, __flags); + return recv(__fd, __buf, __n, __flags); +} +int +my_remove(__const char *__filename) +{ + WRAPPERS_DEBUG_PRINTF("remove()\n", __filename); + return remove(__filename); +} +int +my_rename(__const char *__old, __const char *__new) +{ + WRAPPERS_DEBUG_PRINTF("rename()\n", __old, __new); + return rename(__old, __new); +} +int +my_sched_yield() +{ + WRAPPERS_DEBUG_PRINTF("sched_yield()\n"); + return sched_yield(); +} +int +my_select(int __nfds, fd_set *__restrict __readfds, fd_set *__restrict __writefds, fd_set *__restrict __exceptfds, struct timeval *__restrict __timeout) +{ + WRAPPERS_DEBUG_PRINTF("select()\n", __nfds, __readfds, __writefds, __exceptfds, __timeout); + return select(__nfds, __readfds, __writefds, __exceptfds, __timeout); +} +ssize_t +my_send(int __fd, __const void *__buf, size_t __n, int __flags) +{ + WRAPPERS_DEBUG_PRINTF("send()\n", __fd, __buf, __n, __flags); + return send(__fd, __buf, __n, __flags); +} +int +my_setjmp(jmp_buf __env) +{ + WRAPPERS_DEBUG_PRINTF("setjmp()\n", __env); + return setjmp(__env); +} +char * +my_setlocale(int __category, __const char *__locale) +{ + WRAPPERS_DEBUG_PRINTF("setlocale()\n", __category, __locale); + return setlocale(__category, __locale); +} +int +my_setsockopt(int __fd, int __level, int __optname, __const void *__optval, socklen_t __optlen) +{ + WRAPPERS_DEBUG_PRINTF("setsockopt()\n", __fd, __level, __optname, __optval, __optlen); + return setsockopt(__fd, __level, __optname, __optval, __optlen); +} +int +my_setvbuf(FILE *__restrict __stream, char *__restrict __buf, int __modes, size_t __n) +{ + WRAPPERS_DEBUG_PRINTF("setvbuf()\n", __stream, __buf, __modes, __n); + return setvbuf(__stream, __buf, __modes, __n); +} +double +my_sin(double __x) +{ + WRAPPERS_DEBUG_PRINTF("sin(%lf)\n", __x); + return sin(__x); +} +double +my_sinh(double __x) +{ + WRAPPERS_DEBUG_PRINTF("sinh()\n", __x); + return sinh(__x); +} +int +my_socket(int __domain, int __type, int __protocol) +{ + WRAPPERS_DEBUG_PRINTF("socket()\n", __domain, __type, __protocol); + return socket(__domain, __type, __protocol); +} +double +my_sqrt(double __x) +{ + WRAPPERS_DEBUG_PRINTF("sqrt()\n", __x); + return sqrt(__x); +} +void +my_srand48(long int __seedval) +{ + WRAPPERS_DEBUG_PRINTF("srand48()\n", __seedval); + srand48(__seedval); +} +int +my_strcasecmp(__const char *__s1, __const char *__s2) +{ + WRAPPERS_DEBUG_PRINTF("strcasecmp()\n", __s1, __s2); + return strcasecmp(__s1, __s2); +} +char * +my_strcat(char *__restrict __dest, __const char *__restrict __src) +{ + WRAPPERS_DEBUG_PRINTF("strcat()\n", __dest, __src); + return strcat(__dest, __src); +} +char * +my_strchr(__const char *__s, int __c) +{ + WRAPPERS_DEBUG_PRINTF("strchr()\n", __s, __c); + return strchr(__s, __c); +} +int +my_strcmp(__const char *__s1, __const char *__s2) +{ + WRAPPERS_DEBUG_PRINTF("strcmp()\n", __s1, __s2); + return strcmp(__s1, __s2); +} +int +my_strcoll(__const char *__s1, __const char *__s2) +{ + WRAPPERS_DEBUG_PRINTF("strcoll()\n", __s1, __s2); + return strcoll(__s1, __s2); +} +char * +my_strcpy(char *__restrict __dest, __const char *__restrict __src) +{ + WRAPPERS_DEBUG_PRINTF("strcpy()\n", __dest, __src); + return strcpy(__dest, __src); +} +size_t +my_strcspn(__const char *__s, __const char *__reject) +{ + WRAPPERS_DEBUG_PRINTF("strcspn()\n", __s, __reject); + return strcspn(__s, __reject); +} +char * +my_strerror(int __errnum) +{ + WRAPPERS_DEBUG_PRINTF("strerror()\n", __errnum); + return strerror(__errnum); +} +size_t +my_strftime(char *__restrict __s, size_t __maxsize, __const char *__restrict __format, __const struct tm *__restrict __tp) +{ + WRAPPERS_DEBUG_PRINTF("strftime()\n", __s, __maxsize, __format, __tp); + return strftime(__s, __maxsize, __format, __tp); +} +size_t +my_strlen(__const char *__s) +{ + WRAPPERS_DEBUG_PRINTF("strlen()\n", __s); + return strlen(__s); +} +char * +my_strncat(char *__restrict __dest, __const char *__restrict __src, size_t __n) +{ + WRAPPERS_DEBUG_PRINTF("strncat()\n", __dest, __src, __n); + return strncat(__dest, __src, __n); +} +int +my_strncmp(__const char *__s1, __const char *__s2, size_t __n) +{ + WRAPPERS_DEBUG_PRINTF("strncmp()\n", __s1, __s2, __n); + return strncmp(__s1, __s2, __n); +} +char * +my_strncpy(char *__restrict __dest, __const char *__restrict __src, size_t __n) +{ + WRAPPERS_DEBUG_PRINTF("strncpy()\n", __dest, __src, __n); + return strncpy(__dest, __src, __n); +} +char * +my_strpbrk(__const char *__s, __const char *__accept) +{ + WRAPPERS_DEBUG_PRINTF("strpbrk()\n", __s, __accept); + return strpbrk(__s, __accept); +} +char * +my_strrchr(__const char *__s, int __c) +{ + WRAPPERS_DEBUG_PRINTF("strrchr()\n", __s, __c); + return strrchr(__s, __c); +} +char * +my_strstr(__const char *__haystack, __const char *__needle) +{ + WRAPPERS_DEBUG_PRINTF("strstr()\n", __haystack, __needle); + return strstr(__haystack, __needle); +} +double +my_strtod(__const char *__restrict __nptr, char **__restrict __endptr) +{ + //WRAPPERS_DEBUG_PRINTF("strtod()\n", __nptr, __endptr); + return strtod(__nptr, __endptr); +} +char * +my_strtok(char *__restrict __s, __const char *__restrict __delim) +{ + WRAPPERS_DEBUG_PRINTF("strtok()\n", __s, __delim); + return strtok(__s, __delim); +} +long int +my_strtol(__const char *__restrict __nptr, char **__restrict __endptr, int __base) +{ + WRAPPERS_DEBUG_PRINTF("strtol()\n", __nptr, __endptr, __base); + return strtol(__nptr, __endptr, __base); +} +unsigned long int +my_strtoul(__const char *__restrict __nptr, char **__restrict __endptr, int __base) +{ + WRAPPERS_DEBUG_PRINTF("strtoul()\n", __nptr, __endptr, __base); + return strtoul(__nptr, __endptr, __base); +} +int +my_system(__const char *__command) +{ + WRAPPERS_DEBUG_PRINTF("system()\n", __command); + return system(__command); +} +double +my_tan(double __x) +{ + WRAPPERS_DEBUG_PRINTF("tan()\n", __x); + return tan(__x); +} +double +my_tanh(double __x) +{ + WRAPPERS_DEBUG_PRINTF("tanh()\n", __x); + return tanh(__x); +} +time_t +my_time(time_t *__timer) +{ + WRAPPERS_DEBUG_PRINTF("time()\n", __timer); + return time(__timer); +} +FILE * +my_tmpfile() +{ + WRAPPERS_DEBUG_PRINTF("tmpfile()\n"); + return tmpfile(); +} +char * +my_tmpnam(char *__s) +{ + WRAPPERS_DEBUG_PRINTF("tmpnam()\n", __s); + //return tmpnam(__s); + return NULL; +} +int +my_ungetc(int __c, FILE *__stream) +{ + WRAPPERS_DEBUG_PRINTF("ungetc()\n", __c, __stream); + return ungetc(__c, __stream); +} +int +my_usleep(__useconds_t __useconds) +{ + WRAPPERS_DEBUG_PRINTF("usleep()\n", __useconds); + return usleep(__useconds); +} +ssize_t +my_write(int __fd, __const void *__buf, size_t __n) +{ + WRAPPERS_DEBUG_PRINTF("write()\n", __fd, __buf, __n); + return write(__fd, __buf, __n); +} + +int +my_fprintf(FILE *stream, const char *format, ...) +{ + //WRAPPERS_DEBUG_PRINTF("my_fprintf(%x, %s)\n", stream, format); + va_list ap; + va_start(ap, format); + int result = vfprintf(stderr, format, ap); + va_end(ap); + return result; +} + +int +my_vfprintf(FILE *stream, const char *format, va_list ap) +{ + //WRAPPERS_DEBUG_PRINTF("my_vfprintf(%x, %s)\n", stream, format); + return vfprintf(stderr, format, ap); +} + +int +my_fflush(FILE *stream) +{ + //WRAPPERS_DEBUG_PRINTF("my_fflush(%x)\n", stream); + int offset = ((void*)stream - (void*)(&my___sF)); + //printf("offset: %d\n", offset); + if (offset < 1000) { + printf("IGNORING FFLUSH\n"); + return 0; + } + return fflush(stream); +} + +int my_sprintf(char *str, const char *format, ...) +{ + printf("sprintf\n"); + va_list ap; + va_start(ap, format); + int result = vsprintf(str, format, ap); + va_end(ap); + return result; +} + +int my_snprintf(char *str, size_t size, const char *format, ...) +{ + printf("snprintf\n"); + va_list ap; + va_start(ap, format); + int result = vsnprintf(str, size, format, ap); + va_end(ap); + return result; +} + +int my_vsnprintf(char *str, size_t size, const char *format, va_list ap) +{ + printf("vsnprintf '%s'\n", format); + return vsnprintf(str, size, format, ap); +} + diff --git a/compat/libc_wrappers.h b/compat/libc_wrappers.h new file mode 100644 index 0000000..92146f3 --- /dev/null +++ b/compat/libc_wrappers.h @@ -0,0 +1,255 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../apkenv.h" + +void +my_abort() SOFTFP; +double +my_acos(double __x) SOFTFP; +double +my_asin(double __x) SOFTFP; +double +my_atan(double __x) SOFTFP; +double +my_atan2(double __y, double __x) SOFTFP; +double +my_ceil(double __x) SOFTFP; +clock_t +my_clock() SOFTFP; +int +my_close(int __fd) SOFTFP; +int +my_connect(int __fd, __const struct sockaddr *__addr, socklen_t __len) SOFTFP; +double +my_cos(double __x) SOFTFP; +double +my_cosh(double __x) SOFTFP; +uLong +my_crc32(uLong crc, const Bytef *buf, uInt len) SOFTFP; +double +my_difftime(time_t __time1, time_t __time0) SOFTFP; +void +my_exit(int __status) SOFTFP; +double +my_exp(double __x) SOFTFP; +int +my_fclose(FILE *__stream) SOFTFP; +char * +my_fgets(char *__restrict __s, int __n, FILE *__restrict __stream) SOFTFP; +int +my_fprintf(FILE *stream, const char *format, ...); +int +my_vfprintf(FILE *stream, const char *format, va_list ap) SOFTFP; +int +my_fflush(FILE *stream) SOFTFP; +double +my_floor(double __x) SOFTFP; +double +my_fmod(double __x, double __y) SOFTFP; +FILE * +my_fopen(__const char *__restrict __filename, __const char *__restrict __modes) SOFTFP; +int +my_fputc(int __c, FILE *__stream) SOFTFP; +int +my_fputs(__const char *__restrict __s, FILE *__restrict __stream) SOFTFP; +size_t +my_fread(void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __stream) SOFTFP; +void +my_free(void *__ptr) SOFTFP; +void +my_freeaddrinfo(struct addrinfo *__ai) SOFTFP; +FILE * +my_freopen(__const char *__restrict __filename, __const char *__restrict __modes, FILE *__restrict __stream) SOFTFP; +double +my_frexp(double __x, int *__exponent) SOFTFP; +int +my_fseek(FILE *__stream, long int __off, int __whence) SOFTFP; +int +my_fsync(int __fd) SOFTFP; +long int +my_ftell(FILE *__stream) SOFTFP; +size_t +my_fwrite(__const void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __s) SOFTFP; +int +my_getaddrinfo(__const char *__restrict __name, __const char *__restrict __service, __const struct addrinfo *__restrict __req, struct addrinfo **__restrict __pai) SOFTFP; +char * +my_getenv(__const char *__name) SOFTFP; +int +my_gettimeofday(struct timeval *__restrict __tv, __timezone_ptr_t __tz) SOFTFP; +struct tm * +my_gmtime(__const time_t *__timer) SOFTFP; +int +my_inflate(z_streamp strm, int flush) SOFTFP; +int +my_inflateEnd(z_streamp strm) SOFTFP; +int +my_inflateInit_(z_streamp strm, const char *version, int stream_size) SOFTFP; +int +my_inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size) SOFTFP; +int +my_inflateReset(z_streamp strm) SOFTFP; +double +my_ldexp(double __x, int __exponent) SOFTFP; +struct tm * +my_localtime(__const time_t *__timer) SOFTFP; +double +my_log(double __x) SOFTFP; +double +my_log10(double __x) SOFTFP; +void +my_longjmp(struct __jmp_buf_tag __env[1], int __val) SOFTFP; +long int +my_lrand48() SOFTFP; +__off_t +my_lseek(int __fd, __off_t __offset, int __whence) SOFTFP; +void * +my_malloc(size_t __size) SOFTFP; +void * +my_memchr(__const void *__s, int __c, size_t __n) SOFTFP; +int +my_memcmp(__const void *__s1, __const void *__s2, size_t __n) SOFTFP; +void * +my_memcpy(void *__restrict __dest, __const void *__restrict __src, size_t __n) SOFTFP; +void * +my_memmove(void *__dest, __const void *__src, size_t __n) SOFTFP; +void * +my_memset(void *__s, int __c, size_t __n) SOFTFP; +time_t +my_mktime(struct tm *__tp) SOFTFP; +double +my_modf(double __x, double *__iptr) SOFTFP; +double +my_pow(double __x, double __y) SOFTFP; +int +my_puts(__const char *__s) SOFTFP; +int +my_raise(int __sig) SOFTFP; +ssize_t +my_read(int __fd, void *__buf, size_t __nbytes) SOFTFP; +void * +my_realloc(void *__ptr, size_t __size) SOFTFP; +ssize_t +my_recv(int __fd, void *__buf, size_t __n, int __flags) SOFTFP; +int +my_remove(__const char *__filename) SOFTFP; +int +my_rename(__const char *__old, __const char *__new) SOFTFP; +int +my_sched_yield() SOFTFP; +int +my_select(int __nfds, fd_set *__restrict __readfds, fd_set *__restrict __writefds, fd_set *__restrict __exceptfds, struct timeval *__restrict __timeout) SOFTFP; +ssize_t +my_send(int __fd, __const void *__buf, size_t __n, int __flags) SOFTFP; +int +my_setjmp(jmp_buf __env) SOFTFP; +char * +my_setlocale(int __category, __const char *__locale) SOFTFP; +int +my_setsockopt(int __fd, int __level, int __optname, __const void *__optval, socklen_t __optlen) SOFTFP; +int +my_setvbuf(FILE *__restrict __stream, char *__restrict __buf, int __modes, size_t __n) SOFTFP; +double +my_sin(double __x) SOFTFP; +double +my_sinh(double __x) SOFTFP; +int +my_socket(int __domain, int __type, int __protocol) SOFTFP; +double +my_sqrt(double __x) SOFTFP; +void +my_srand48(long int __seedval) SOFTFP; +int +my_strcasecmp(__const char *__s1, __const char *__s2) SOFTFP; +char * +my_strcat(char *__restrict __dest, __const char *__restrict __src) SOFTFP; +char * +my_strchr(__const char *__s, int __c) SOFTFP; +int +my_strcmp(__const char *__s1, __const char *__s2) SOFTFP; +int +my_strcoll(__const char *__s1, __const char *__s2) SOFTFP; +char * +my_strcpy(char *__restrict __dest, __const char *__restrict __src) SOFTFP; +size_t +my_strcspn(__const char *__s, __const char *__reject) SOFTFP; +char * +my_strerror(int __errnum) SOFTFP; +size_t +my_strftime(char *__restrict __s, size_t __maxsize, __const char *__restrict __format, __const struct tm *__restrict __tp) SOFTFP; +size_t +my_strlen(__const char *__s) SOFTFP; +char * +my_strncat(char *__restrict __dest, __const char *__restrict __src, size_t __n) SOFTFP; +int +my_strncmp(__const char *__s1, __const char *__s2, size_t __n) SOFTFP; +char * +my_strncpy(char *__restrict __dest, __const char *__restrict __src, size_t __n) SOFTFP; +char * +my_strpbrk(__const char *__s, __const char *__accept) SOFTFP; +char * +my_strrchr(__const char *__s, int __c) SOFTFP; +char * +my_strstr(__const char *__haystack, __const char *__needle) SOFTFP; +double +my_strtod(__const char *__restrict __nptr, char **__restrict __endptr) SOFTFP; +char * +my_strtok(char *__restrict __s, __const char *__restrict __delim) SOFTFP; +long int +my_strtol(__const char *__restrict __nptr, char **__restrict __endptr, int __base) SOFTFP; +unsigned long int +my_strtoul(__const char *__restrict __nptr, char **__restrict __endptr, int __base) SOFTFP; +int +my_system(__const char *__command) SOFTFP; +double +my_tan(double __x) SOFTFP; +double +my_tanh(double __x) SOFTFP; +time_t +my_time(time_t *__timer) SOFTFP; +FILE * +my_tmpfile() SOFTFP; +char * +my_tmpnam(char *__s) SOFTFP; +int +my_ungetc(int __c, FILE *__stream) SOFTFP; +int +my_usleep(__useconds_t __useconds) SOFTFP; +ssize_t +my_write(int __fd, __const void *__buf, size_t __n) SOFTFP; + +int my_sprintf(char *str, const char *format, ...) SOFTFP; +int my_snprintf(char *str, size_t size, const char *format, ...) SOFTFP; +int my_vsnprintf(char *str, size_t size, const char *format, va_list ap) SOFTFP; + diff --git a/compat/liblog_mapping.h b/compat/liblog_mapping.h new file mode 100644 index 0000000..32fea2e --- /dev/null +++ b/compat/liblog_mapping.h @@ -0,0 +1,3 @@ +{"__android_log_print", my__android_log_print}, +{"__android_log_vprint", my__android_log_vprint}, +{"__android_log_write", my__android_log_write}, diff --git a/compat/liblog_wrappers.c b/compat/liblog_wrappers.c new file mode 100644 index 0000000..b1ab839 --- /dev/null +++ b/compat/liblog_wrappers.c @@ -0,0 +1,57 @@ + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + +#include "liblog_wrappers.h" + +int +my__android_log_print(int prio, const char *tag, const char **fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int result = vprintf((const char *)fmt, ap); + va_end(ap); + result += printf("\n"); + return result; +} + +int +my__android_log_vprint(int prio, const char *tag, const char **fmt, va_list ap) +{ + int result = vprintf((const char *)fmt, ap); + result += printf("\n"); + return result; +} + +int +my__android_log_write(int prio, const char *tag, const char *msg) +{ + return printf("%s\n", msg); +} + diff --git a/compat/liblog_wrappers.h b/compat/liblog_wrappers.h new file mode 100644 index 0000000..c0d87eb --- /dev/null +++ b/compat/liblog_wrappers.h @@ -0,0 +1,42 @@ + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + +#include +#include + +#include "../apkenv.h" + +int +my__android_log_print(int prio, const char *tag, const char **fmt, ...) SOFTFP; +int +my__android_log_vprint(int prio, const char *tag, const char **fmt, va_list ap) SOFTFP; +int +my__android_log_write(int prio, const char *tag, const char *msg) SOFTFP; + diff --git a/compat/pthread_mapping.h b/compat/pthread_mapping.h new file mode 100644 index 0000000..50cc23d --- /dev/null +++ b/compat/pthread_mapping.h @@ -0,0 +1,43 @@ +{"pthread_attr_init", my_pthread_attr_init}, +{"pthread_attr_setdetachstate", my_pthread_attr_setdetachstate}, +{"pthread_attr_setstacksize", my_pthread_attr_setstacksize}, +{"pthread_attr_destroy", my_pthread_attr_destroy}, + +{"pthread_cond_init", my_pthread_cond_init}, +{"pthread_cond_broadcast", my_pthread_cond_broadcast}, +{"pthread_cond_signal", my_pthread_cond_signal}, +{"pthread_cond_timedwait", my_pthread_cond_timedwait}, +{"pthread_cond_wait", my_pthread_cond_wait}, +{"pthread_cond_destroy", my_pthread_cond_destroy}, + +{"pthread_create", pthread_create}, +{"pthread_self", pthread_self}, +{"pthread_equal", pthread_equal}, +{"pthread_getschedparam", pthread_getschedparam}, +{"pthread_setschedparam", pthread_setschedparam}, +{"pthread_join", pthread_join}, +{"pthread_detach", pthread_detach}, +{"pthread_exit", pthread_exit}, + +{"pthread_key_create", pthread_key_create}, +{"pthread_getspecific", pthread_getspecific}, +{"pthread_setspecific", pthread_setspecific}, +{"pthread_key_delete", pthread_key_delete}, + +{"pthread_mutexattr_init", pthread_mutexattr_init}, +{"pthread_mutexattr_settype", pthread_mutexattr_settype}, +{"pthread_mutexattr_destroy", pthread_mutexattr_destroy}, + +{"pthread_mutex_init", my_pthread_mutex_init}, +{"pthread_mutex_lock", my_pthread_mutex_lock}, +{"pthread_mutex_trylock", my_pthread_mutex_trylock}, +{"pthread_mutex_unlock", my_pthread_mutex_unlock}, +{"pthread_mutex_destroy", my_pthread_mutex_destroy}, + +{"pthread_once", pthread_once}, + +{"pthread_rwlock_init", pthread_rwlock_init}, +{"pthread_rwlock_rdlock", pthread_rwlock_rdlock}, +{"pthread_rwlock_unlock", pthread_rwlock_unlock}, +{"pthread_rwlock_wrlock", pthread_rwlock_wrlock}, +{"pthread_rwlock_destroy", pthread_rwlock_destroy}, diff --git a/compat/pthread_wrappers.c b/compat/pthread_wrappers.c new file mode 100644 index 0000000..9de2d97 --- /dev/null +++ b/compat/pthread_wrappers.c @@ -0,0 +1,248 @@ + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * Based on code from libhybris: Copyright (c) 2012 Carsten Munk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + +#include "pthread_wrappers.h" + +/** + * This will take care of doing the right thing for mutexes that are not + * yet initialized correctly (e.g. because they were statically initialized + * on the Bionic-using side). This function should be called at the start + * of every function that takes a pthread_mutex_t * as parameter. + * + * Returns the "real" glibc pthread_mutex_t * + **/ +pthread_mutex_t * +late_init_pthread_mutex(pthread_mutex_t *mutex) +{ + if (mutex == NULL) { + printf("Mutex is NULL in %s\n", __func__); + exit(1); + } + + pthread_mutex_t *realmutex = (pthread_mutex_t*) (*((int*)mutex)); + if (realmutex == NULL) { + printf("late-initializing normal mutex\n"); + realmutex = malloc(sizeof(pthread_mutex_t)); + pthread_mutex_init(realmutex, NULL); + *((int *)mutex) = (int)realmutex; + } else if (realmutex == BIONIC_PTHREAD_RECURSIVE_MUTEX) { + printf("late-initializing recursive mutex\n"); + realmutex = malloc(sizeof(pthread_mutex_t)); + pthread_mutex_t tmp = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + memcpy(realmutex, &tmp, sizeof(pthread_mutex_t)); + *((int *)mutex) = (int)realmutex; + } else if (realmutex == BIONIC_PTHREAD_ERRORCHECK_MUTEX) { + printf("late-initializing errorcheck mutex\n"); + realmutex = malloc(sizeof(pthread_mutex_t)); + pthread_mutex_t tmp = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; + memcpy(realmutex, &tmp, sizeof(pthread_mutex_t)); + *((int *)mutex) = (int)realmutex; + } + + return realmutex; +} + +/** + * Same thing as above, but for pthread_cond_t * variables. + * + * Returns the "real" glibc pthread_cond_t * + **/ +pthread_cond_t * +late_init_pthread_cond(pthread_cond_t *cond) +{ + if (cond == NULL) { + printf("Cond iS NULL in %s\n", __func__); + exit(1); + } + + pthread_cond_t *realcond = (pthread_cond_t *) *(int *) cond; + if (realcond == NULL) { + printf("late-initializing cond\n"); + realcond = malloc(sizeof(pthread_cond_t)); + pthread_cond_t tmp = PTHREAD_COND_INITIALIZER; + memcpy(realcond, &tmp, sizeof(pthread_cond_t)); + *((int *) cond) = (int)realcond; + } + + return realcond; +} + +int +my_pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutexattr) +{ + pthread_mutex_t *realmutex = malloc(sizeof(pthread_mutex_t)); + *((int *)__mutex) = (int) realmutex; + return pthread_mutex_init(realmutex, __mutexattr); +} + +int +my_pthread_mutex_lock (pthread_mutex_t *__mutex) +{ + pthread_mutex_t *realmutex = late_init_pthread_mutex(__mutex); + return pthread_mutex_lock(realmutex); +} + +int +my_pthread_mutex_trylock (pthread_mutex_t *__mutex) +{ + pthread_mutex_t *realmutex = late_init_pthread_mutex(__mutex); + return pthread_mutex_trylock(realmutex); +} + +int +my_pthread_mutex_unlock (pthread_mutex_t *__mutex) +{ + pthread_mutex_t *realmutex = late_init_pthread_mutex(__mutex); + return pthread_mutex_unlock(realmutex); +} + +int +my_pthread_mutex_destroy (pthread_mutex_t *__mutex) +{ + pthread_mutex_t *realmutex = late_init_pthread_mutex(__mutex); + int ret = pthread_mutex_destroy(realmutex); + free(realmutex); + return ret; +} + +int +my_pthread_cond_init(pthread_cond_t *cond, + const pthread_condattr_t *attr) +{ + assert(cond != NULL); + pthread_cond_t *realcond = malloc(sizeof(pthread_cond_t)); + *((int *) cond) = (int) realcond; + return pthread_cond_init(realcond, attr); +} + +int +my_pthread_cond_destroy(pthread_cond_t *cond) +{ + pthread_cond_t *realcond = late_init_pthread_cond(cond); + int ret = pthread_cond_destroy(realcond); + free(realcond); + return ret; +} + +int +my_pthread_cond_broadcast(pthread_cond_t *cond) +{ + pthread_cond_t *realcond = late_init_pthread_cond(cond); + return pthread_cond_broadcast(realcond); +} + +int +my_pthread_cond_signal(pthread_cond_t *cond) +{ + pthread_cond_t *realcond = late_init_pthread_cond(cond); + return pthread_cond_signal(realcond); +} + +int +my_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + pthread_cond_t *realcond = late_init_pthread_cond(cond); + pthread_mutex_t *realmutex = late_init_pthread_mutex(mutex); + return pthread_cond_wait(realcond, realmutex); +} + +int +my_pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, const struct timespec *abstime) +{ + pthread_cond_t *realcond = late_init_pthread_cond(cond); + pthread_mutex_t *realmutex = late_init_pthread_mutex(mutex); + return pthread_cond_timedwait(realcond, realmutex, abstime); +} + +int +my_pthread_attr_init(pthread_attr_t *__attr) +{ + assert(__attr != NULL); + pthread_attr_t *realattr = (pthread_attr_t *) *(int *) __attr; + + realattr = malloc(sizeof(pthread_attr_t)); + *((int *)__attr) = (int) realattr; + + return pthread_attr_init(realattr); +} + +int +my_pthread_attr_destroy(pthread_attr_t *__attr) +{ + assert(__attr != NULL); + pthread_attr_t *realattr = (pthread_attr_t *) *(int *) __attr; + assert(realattr != NULL); + return pthread_attr_destroy(realattr); +} + +int +my_pthread_attr_setdetachstate(pthread_attr_t *__attr, int detachstate) +{ + assert(__attr != NULL); + pthread_attr_t *realattr = (pthread_attr_t *) *(int *) __attr; + assert(realattr != NULL); + return pthread_attr_setdetachstate(realattr, detachstate); +} + +int +my_pthread_attr_setstacksize(pthread_attr_t *__attr, size_t stacksize) +{ + assert(__attr != NULL); + pthread_attr_t *realattr = (pthread_attr_t *) *(int *) __attr; + assert(realattr != NULL); + return pthread_attr_setstacksize (realattr,stacksize); +} + +void * +start_wrapped_thread(void *arg) +{ + struct WrappedThread *wrapped = arg; + //printf("XXX THREAD START XXX\n"); + void *result = wrapped->start_routine(wrapped->arg); + //printf("XXX THREAD END XXX\n"); + free(wrapped); + return result; +} + +int my_pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg) +{ + struct WrappedThread *wrapped = malloc( + sizeof(struct WrappedThread)); + wrapped->start_routine = start_routine; + wrapped->arg = arg; + + //printf("XXX PTHREAD CREATE XXX\n"); + return pthread_create(thread, attr, start_wrapped_thread, (void*)wrapped); +} + diff --git a/compat/pthread_wrappers.h b/compat/pthread_wrappers.h new file mode 100644 index 0000000..796f6cc --- /dev/null +++ b/compat/pthread_wrappers.h @@ -0,0 +1,99 @@ + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +/* pthread_once_t: int in glibc, volatile int in Bionic */ +/* pthread_mutexattr_t: union{char[4],int} in glibc, long in Bionic */ +/* pthread_condattr_t: union{char[4],int} in glibc, long in Bionic */ + +/* pthread_mutex_t: big struct in glibc, struct{int} in Bionic -> wrap */ +/* pthread_cond_t: big struct in glibc, struct{int} in Bionic -> wrap */ +/* pthread_attr_t: big struct in glibc, small struct in Bionic -> wrap */ + +/* Static initializer values for pthread_mutex_t in Bionic */ +#define BIONIC_PTHREAD_RECURSIVE_MUTEX (void*)0x4000 +#define BIONIC_PTHREAD_ERRORCHECK_MUTEX (void*)0x8000 + +pthread_mutex_t * +late_init_pthread_mutex(pthread_mutex_t *mutex); +pthread_cond_t * +late_init_pthread_cond(pthread_cond_t *cond); +int +my_pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutexattr); +int +my_pthread_mutex_lock (pthread_mutex_t *__mutex); +int +my_pthread_mutex_trylock (pthread_mutex_t *__mutex); +int +my_pthread_mutex_unlock (pthread_mutex_t *__mutex); +int +my_pthread_mutex_destroy (pthread_mutex_t *__mutex); +int +my_pthread_cond_init(pthread_cond_t *cond, + const pthread_condattr_t *attr); +int +my_pthread_cond_destroy(pthread_cond_t *cond); +int +my_pthread_cond_broadcast(pthread_cond_t *cond); +int +my_pthread_cond_signal(pthread_cond_t *cond); +int +my_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); +int +my_pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, const struct timespec *abstime); +int +my_pthread_attr_init(pthread_attr_t *__attr); +int +my_pthread_attr_destroy(pthread_attr_t *__attr); +int +my_pthread_attr_setdetachstate(pthread_attr_t *__attr, + int detachstate); +int +my_pthread_attr_setstacksize(pthread_attr_t *__attr, size_t stacksize); + +struct WrappedThread { + void *(*start_routine)(void *); + void *arg; +}; + +void * +start_wrapped_thread(void *arg); +int +my_pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg); + diff --git a/jni/jni.h b/jni/jni.h new file mode 100644 index 0000000..e4d74cf --- /dev/null +++ b/jni/jni.h @@ -0,0 +1,1154 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * JNI specification, as defined by Sun: + * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html + * + * Everything here is expected to be VM-neutral. + */ + +#ifndef JNI_H_ +#define JNI_H_ + +#include + +/* + * Primitive types that match up with Java equivalents. + */ +#ifdef HAVE_INTTYPES_H +# include /* C99 */ +typedef uint8_t jboolean; /* unsigned 8 bits */ +typedef int8_t jbyte; /* signed 8 bits */ +typedef uint16_t jchar; /* unsigned 16 bits */ +typedef int16_t jshort; /* signed 16 bits */ +typedef int32_t jint; /* signed 32 bits */ +typedef int64_t jlong; /* signed 64 bits */ +typedef float jfloat; /* 32-bit IEEE 754 */ +typedef double jdouble; /* 64-bit IEEE 754 */ +#else +typedef unsigned char jboolean; /* unsigned 8 bits */ +typedef signed char jbyte; /* signed 8 bits */ +typedef unsigned short jchar; /* unsigned 16 bits */ +typedef short jshort; /* signed 16 bits */ +typedef int jint; /* signed 32 bits */ +typedef long long jlong; /* signed 64 bits */ +typedef float jfloat; /* 32-bit IEEE 754 */ +typedef double jdouble; /* 64-bit IEEE 754 */ +#endif + +/* "cardinal indices and sizes" */ +typedef jint jsize; + +#ifdef __cplusplus +/* + * Reference types, in C++ + */ +class _jobject {}; +class _jclass : public _jobject {}; +class _jstring : public _jobject {}; +class _jarray : public _jobject {}; +class _jobjectArray : public _jarray {}; +class _jbooleanArray : public _jarray {}; +class _jbyteArray : public _jarray {}; +class _jcharArray : public _jarray {}; +class _jshortArray : public _jarray {}; +class _jintArray : public _jarray {}; +class _jlongArray : public _jarray {}; +class _jfloatArray : public _jarray {}; +class _jdoubleArray : public _jarray {}; +class _jthrowable : public _jobject {}; + +typedef _jobject* jobject; +typedef _jclass* jclass; +typedef _jstring* jstring; +typedef _jarray* jarray; +typedef _jobjectArray* jobjectArray; +typedef _jbooleanArray* jbooleanArray; +typedef _jbyteArray* jbyteArray; +typedef _jcharArray* jcharArray; +typedef _jshortArray* jshortArray; +typedef _jintArray* jintArray; +typedef _jlongArray* jlongArray; +typedef _jfloatArray* jfloatArray; +typedef _jdoubleArray* jdoubleArray; +typedef _jthrowable* jthrowable; +typedef _jobject* jweak; + + +#else /* not __cplusplus */ + +/* + * Reference types, in C. + */ +typedef void* jobject; +typedef jobject jclass; +typedef jobject jstring; +typedef jobject jarray; +typedef jarray jobjectArray; +typedef jarray jbooleanArray; +typedef jarray jbyteArray; +typedef jarray jcharArray; +typedef jarray jshortArray; +typedef jarray jintArray; +typedef jarray jlongArray; +typedef jarray jfloatArray; +typedef jarray jdoubleArray; +typedef jobject jthrowable; +typedef jobject jweak; + +#endif /* not __cplusplus */ + +struct _jfieldID; /* opaque structure */ +typedef struct _jfieldID* jfieldID; /* field IDs */ + +struct _jmethodID; /* opaque structure */ +typedef struct _jmethodID* jmethodID; /* method IDs */ + +struct JNIInvokeInterface; + +typedef union jvalue { + jboolean z; + jbyte b; + jchar c; + jshort s; + jint i; + jlong j; + jfloat f; + jdouble d; + jobject l; +} jvalue; + +typedef enum jobjectRefType { + JNIInvalidRefType = 0, + JNILocalRefType = 1, + JNIGlobalRefType = 2, + JNIWeakGlobalRefType = 3 +} jobjectRefType; + +typedef struct { + const char* name; + const char* signature; + void* fnPtr; +} JNINativeMethod; + +struct _JNIEnv; +struct _JavaVM; +typedef const struct JNINativeInterface* C_JNIEnv; + +#if defined(__cplusplus) +typedef _JNIEnv JNIEnv; +typedef _JavaVM JavaVM; +#else +typedef const struct JNINativeInterface* JNIEnv; +typedef const struct JNIInvokeInterface* JavaVM; +#endif + +/* + * Table of interface function pointers. + */ +struct JNINativeInterface { + void* reserved0; + void* reserved1; + void* reserved2; + void* reserved3; + + jint (*GetVersion)(JNIEnv *); + + jclass (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*, + jsize); + jclass (*FindClass)(JNIEnv*, const char*); + + jmethodID (*FromReflectedMethod)(JNIEnv*, jobject); + jfieldID (*FromReflectedField)(JNIEnv*, jobject); + /* spec doesn't show jboolean parameter */ + jobject (*ToReflectedMethod)(JNIEnv*, jclass, jmethodID, jboolean); + + jclass (*GetSuperclass)(JNIEnv*, jclass); + jboolean (*IsAssignableFrom)(JNIEnv*, jclass, jclass); + + /* spec doesn't show jboolean parameter */ + jobject (*ToReflectedField)(JNIEnv*, jclass, jfieldID, jboolean); + + jint (*Throw)(JNIEnv*, jthrowable); + jint (*ThrowNew)(JNIEnv *, jclass, const char *); + jthrowable (*ExceptionOccurred)(JNIEnv*); + void (*ExceptionDescribe)(JNIEnv*); + void (*ExceptionClear)(JNIEnv*); + void (*FatalError)(JNIEnv*, const char*); + + jint (*PushLocalFrame)(JNIEnv*, jint); + jobject (*PopLocalFrame)(JNIEnv*, jobject); + + jobject (*NewGlobalRef)(JNIEnv*, jobject); + void (*DeleteGlobalRef)(JNIEnv*, jobject); + void (*DeleteLocalRef)(JNIEnv*, jobject); + jboolean (*IsSameObject)(JNIEnv*, jobject, jobject); + + jobject (*NewLocalRef)(JNIEnv*, jobject); + jint (*EnsureLocalCapacity)(JNIEnv*, jint); + + jobject (*AllocObject)(JNIEnv*, jclass); + jobject (*NewObject)(JNIEnv*, jclass, jmethodID, ...); + jobject (*NewObjectV)(JNIEnv*, jclass, jmethodID, va_list); + jobject (*NewObjectA)(JNIEnv*, jclass, jmethodID, jvalue*); + + jclass (*GetObjectClass)(JNIEnv*, jobject); + jboolean (*IsInstanceOf)(JNIEnv*, jobject, jclass); + jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*); + + jobject (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...); + jobject (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jobject (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + jboolean (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...); + jboolean (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jboolean (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + jbyte (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...); + jbyte (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jbyte (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + jchar (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...); + jchar (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jchar (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + jshort (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...); + jshort (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jshort (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...); + jint (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jint (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + jlong (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...); + jlong (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jlong (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + jfloat (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...); + jfloat (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jfloat (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + jdouble (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...); + jdouble (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list); + jdouble (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...); + void (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list); + void (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*); + + jobject (*CallNonvirtualObjectMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jobject (*CallNonvirtualObjectMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jobject (*CallNonvirtualObjectMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + jboolean (*CallNonvirtualBooleanMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jboolean (*CallNonvirtualBooleanMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jboolean (*CallNonvirtualBooleanMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + jbyte (*CallNonvirtualByteMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jbyte (*CallNonvirtualByteMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jbyte (*CallNonvirtualByteMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + jchar (*CallNonvirtualCharMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jchar (*CallNonvirtualCharMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jchar (*CallNonvirtualCharMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + jshort (*CallNonvirtualShortMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jshort (*CallNonvirtualShortMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jshort (*CallNonvirtualShortMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + jint (*CallNonvirtualIntMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jint (*CallNonvirtualIntMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jint (*CallNonvirtualIntMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + jlong (*CallNonvirtualLongMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jlong (*CallNonvirtualLongMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jlong (*CallNonvirtualLongMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + jfloat (*CallNonvirtualFloatMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jfloat (*CallNonvirtualFloatMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jfloat (*CallNonvirtualFloatMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + jdouble (*CallNonvirtualDoubleMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + jdouble (*CallNonvirtualDoubleMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + jdouble (*CallNonvirtualDoubleMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + void (*CallNonvirtualVoidMethod)(JNIEnv*, jobject, jclass, + jmethodID, ...); + void (*CallNonvirtualVoidMethodV)(JNIEnv*, jobject, jclass, + jmethodID, va_list); + void (*CallNonvirtualVoidMethodA)(JNIEnv*, jobject, jclass, + jmethodID, jvalue*); + + jfieldID (*GetFieldID)(JNIEnv*, jclass, const char*, const char*); + + jobject (*GetObjectField)(JNIEnv*, jobject, jfieldID); + jboolean (*GetBooleanField)(JNIEnv*, jobject, jfieldID); + jbyte (*GetByteField)(JNIEnv*, jobject, jfieldID); + jchar (*GetCharField)(JNIEnv*, jobject, jfieldID); + jshort (*GetShortField)(JNIEnv*, jobject, jfieldID); + jint (*GetIntField)(JNIEnv*, jobject, jfieldID); + jlong (*GetLongField)(JNIEnv*, jobject, jfieldID); + jfloat (*GetFloatField)(JNIEnv*, jobject, jfieldID); + jdouble (*GetDoubleField)(JNIEnv*, jobject, jfieldID); + + void (*SetObjectField)(JNIEnv*, jobject, jfieldID, jobject); + void (*SetBooleanField)(JNIEnv*, jobject, jfieldID, jboolean); + void (*SetByteField)(JNIEnv*, jobject, jfieldID, jbyte); + void (*SetCharField)(JNIEnv*, jobject, jfieldID, jchar); + void (*SetShortField)(JNIEnv*, jobject, jfieldID, jshort); + void (*SetIntField)(JNIEnv*, jobject, jfieldID, jint); + void (*SetLongField)(JNIEnv*, jobject, jfieldID, jlong); + void (*SetFloatField)(JNIEnv*, jobject, jfieldID, jfloat); + void (*SetDoubleField)(JNIEnv*, jobject, jfieldID, jdouble); + + jmethodID (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*); + + jobject (*CallStaticObjectMethod)(JNIEnv*, jclass, jmethodID, ...); + jobject (*CallStaticObjectMethodV)(JNIEnv*, jclass, jmethodID, va_list); + jobject (*CallStaticObjectMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + jboolean (*CallStaticBooleanMethod)(JNIEnv*, jclass, jmethodID, ...); + jboolean (*CallStaticBooleanMethodV)(JNIEnv*, jclass, jmethodID, + va_list); + jboolean (*CallStaticBooleanMethodA)(JNIEnv*, jclass, jmethodID, + jvalue*); + jbyte (*CallStaticByteMethod)(JNIEnv*, jclass, jmethodID, ...); + jbyte (*CallStaticByteMethodV)(JNIEnv*, jclass, jmethodID, va_list); + jbyte (*CallStaticByteMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + jchar (*CallStaticCharMethod)(JNIEnv*, jclass, jmethodID, ...); + jchar (*CallStaticCharMethodV)(JNIEnv*, jclass, jmethodID, va_list); + jchar (*CallStaticCharMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + jshort (*CallStaticShortMethod)(JNIEnv*, jclass, jmethodID, ...); + jshort (*CallStaticShortMethodV)(JNIEnv*, jclass, jmethodID, va_list); + jshort (*CallStaticShortMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + jint (*CallStaticIntMethod)(JNIEnv*, jclass, jmethodID, ...); + jint (*CallStaticIntMethodV)(JNIEnv*, jclass, jmethodID, va_list); + jint (*CallStaticIntMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + jlong (*CallStaticLongMethod)(JNIEnv*, jclass, jmethodID, ...); + jlong (*CallStaticLongMethodV)(JNIEnv*, jclass, jmethodID, va_list); + jlong (*CallStaticLongMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + jfloat (*CallStaticFloatMethod)(JNIEnv*, jclass, jmethodID, ...); + jfloat (*CallStaticFloatMethodV)(JNIEnv*, jclass, jmethodID, va_list); + jfloat (*CallStaticFloatMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + jdouble (*CallStaticDoubleMethod)(JNIEnv*, jclass, jmethodID, ...); + jdouble (*CallStaticDoubleMethodV)(JNIEnv*, jclass, jmethodID, va_list); + jdouble (*CallStaticDoubleMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + void (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...); + void (*CallStaticVoidMethodV)(JNIEnv*, jclass, jmethodID, va_list); + void (*CallStaticVoidMethodA)(JNIEnv*, jclass, jmethodID, jvalue*); + + jfieldID (*GetStaticFieldID)(JNIEnv*, jclass, const char*, + const char*); + + jobject (*GetStaticObjectField)(JNIEnv*, jclass, jfieldID); + jboolean (*GetStaticBooleanField)(JNIEnv*, jclass, jfieldID); + jbyte (*GetStaticByteField)(JNIEnv*, jclass, jfieldID); + jchar (*GetStaticCharField)(JNIEnv*, jclass, jfieldID); + jshort (*GetStaticShortField)(JNIEnv*, jclass, jfieldID); + jint (*GetStaticIntField)(JNIEnv*, jclass, jfieldID); + jlong (*GetStaticLongField)(JNIEnv*, jclass, jfieldID); + jfloat (*GetStaticFloatField)(JNIEnv*, jclass, jfieldID); + jdouble (*GetStaticDoubleField)(JNIEnv*, jclass, jfieldID); + + void (*SetStaticObjectField)(JNIEnv*, jclass, jfieldID, jobject); + void (*SetStaticBooleanField)(JNIEnv*, jclass, jfieldID, jboolean); + void (*SetStaticByteField)(JNIEnv*, jclass, jfieldID, jbyte); + void (*SetStaticCharField)(JNIEnv*, jclass, jfieldID, jchar); + void (*SetStaticShortField)(JNIEnv*, jclass, jfieldID, jshort); + void (*SetStaticIntField)(JNIEnv*, jclass, jfieldID, jint); + void (*SetStaticLongField)(JNIEnv*, jclass, jfieldID, jlong); + void (*SetStaticFloatField)(JNIEnv*, jclass, jfieldID, jfloat); + void (*SetStaticDoubleField)(JNIEnv*, jclass, jfieldID, jdouble); + + jstring (*NewString)(JNIEnv*, const jchar*, jsize); + jsize (*GetStringLength)(JNIEnv*, jstring); + const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*); + void (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*); + jstring (*NewStringUTF)(JNIEnv*, const char*); + jsize (*GetStringUTFLength)(JNIEnv*, jstring); + /* JNI spec says this returns const jbyte*, but that's inconsistent */ + const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*); + void (*ReleaseStringUTFChars)(JNIEnv*, jstring, const char*); + jsize (*GetArrayLength)(JNIEnv*, jarray); + jobjectArray (*NewObjectArray)(JNIEnv*, jsize, jclass, jobject); + jobject (*GetObjectArrayElement)(JNIEnv*, jobjectArray, jsize); + void (*SetObjectArrayElement)(JNIEnv*, jobjectArray, jsize, jobject); + + jbooleanArray (*NewBooleanArray)(JNIEnv*, jsize); + jbyteArray (*NewByteArray)(JNIEnv*, jsize); + jcharArray (*NewCharArray)(JNIEnv*, jsize); + jshortArray (*NewShortArray)(JNIEnv*, jsize); + jintArray (*NewIntArray)(JNIEnv*, jsize); + jlongArray (*NewLongArray)(JNIEnv*, jsize); + jfloatArray (*NewFloatArray)(JNIEnv*, jsize); + jdoubleArray (*NewDoubleArray)(JNIEnv*, jsize); + + jboolean* (*GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*); + jbyte* (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*); + jchar* (*GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*); + jshort* (*GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*); + jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); + jlong* (*GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*); + jfloat* (*GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*); + jdouble* (*GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*); + + void (*ReleaseBooleanArrayElements)(JNIEnv*, jbooleanArray, + jboolean*, jint); + void (*ReleaseByteArrayElements)(JNIEnv*, jbyteArray, + jbyte*, jint); + void (*ReleaseCharArrayElements)(JNIEnv*, jcharArray, + jchar*, jint); + void (*ReleaseShortArrayElements)(JNIEnv*, jshortArray, + jshort*, jint); + void (*ReleaseIntArrayElements)(JNIEnv*, jintArray, + jint*, jint); + void (*ReleaseLongArrayElements)(JNIEnv*, jlongArray, + jlong*, jint); + void (*ReleaseFloatArrayElements)(JNIEnv*, jfloatArray, + jfloat*, jint); + void (*ReleaseDoubleArrayElements)(JNIEnv*, jdoubleArray, + jdouble*, jint); + + void (*GetBooleanArrayRegion)(JNIEnv*, jbooleanArray, + jsize, jsize, jboolean*); + void (*GetByteArrayRegion)(JNIEnv*, jbyteArray, + jsize, jsize, jbyte*); + void (*GetCharArrayRegion)(JNIEnv*, jcharArray, + jsize, jsize, jchar*); + void (*GetShortArrayRegion)(JNIEnv*, jshortArray, + jsize, jsize, jshort*); + void (*GetIntArrayRegion)(JNIEnv*, jintArray, + jsize, jsize, jint*); + void (*GetLongArrayRegion)(JNIEnv*, jlongArray, + jsize, jsize, jlong*); + void (*GetFloatArrayRegion)(JNIEnv*, jfloatArray, + jsize, jsize, jfloat*); + void (*GetDoubleArrayRegion)(JNIEnv*, jdoubleArray, + jsize, jsize, jdouble*); + + /* spec shows these without const; some jni.h do, some don't */ + void (*SetBooleanArrayRegion)(JNIEnv*, jbooleanArray, + jsize, jsize, const jboolean*); + void (*SetByteArrayRegion)(JNIEnv*, jbyteArray, + jsize, jsize, const jbyte*); + void (*SetCharArrayRegion)(JNIEnv*, jcharArray, + jsize, jsize, const jchar*); + void (*SetShortArrayRegion)(JNIEnv*, jshortArray, + jsize, jsize, const jshort*); + void (*SetIntArrayRegion)(JNIEnv*, jintArray, + jsize, jsize, const jint*); + void (*SetLongArrayRegion)(JNIEnv*, jlongArray, + jsize, jsize, const jlong*); + void (*SetFloatArrayRegion)(JNIEnv*, jfloatArray, + jsize, jsize, const jfloat*); + void (*SetDoubleArrayRegion)(JNIEnv*, jdoubleArray, + jsize, jsize, const jdouble*); + + jint (*RegisterNatives)(JNIEnv*, jclass, const JNINativeMethod*, + jint); + jint (*UnregisterNatives)(JNIEnv*, jclass); + jint (*MonitorEnter)(JNIEnv*, jobject); + jint (*MonitorExit)(JNIEnv*, jobject); + jint (*GetJavaVM)(JNIEnv*, JavaVM**); + + void (*GetStringRegion)(JNIEnv*, jstring, jsize, jsize, jchar*); + void (*GetStringUTFRegion)(JNIEnv*, jstring, jsize, jsize, char*); + + void* (*GetPrimitiveArrayCritical)(JNIEnv*, jarray, jboolean*); + void (*ReleasePrimitiveArrayCritical)(JNIEnv*, jarray, void*, jint); + + const jchar* (*GetStringCritical)(JNIEnv*, jstring, jboolean*); + void (*ReleaseStringCritical)(JNIEnv*, jstring, const jchar*); + + jweak (*NewWeakGlobalRef)(JNIEnv*, jobject); + void (*DeleteWeakGlobalRef)(JNIEnv*, jweak); + + jboolean (*ExceptionCheck)(JNIEnv*); + + jobject (*NewDirectByteBuffer)(JNIEnv*, void*, jlong); + void* (*GetDirectBufferAddress)(JNIEnv*, jobject); + jlong (*GetDirectBufferCapacity)(JNIEnv*, jobject); + + /* added in JNI 1.6 */ + jobjectRefType (*GetObjectRefType)(JNIEnv*, jobject); +}; + +/* + * C++ object wrapper. + * + * This is usually overlaid on a C struct whose first element is a + * JNINativeInterface*. We rely somewhat on compiler behavior. + */ +struct _JNIEnv { + /* do not rename this; it does not seem to be entirely opaque */ + const struct JNINativeInterface* functions; + +#if defined(__cplusplus) + + jint GetVersion() + { return functions->GetVersion(this); } + + jclass DefineClass(const char *name, jobject loader, const jbyte* buf, + jsize bufLen) + { return functions->DefineClass(this, name, loader, buf, bufLen); } + + jclass FindClass(const char* name) + { return functions->FindClass(this, name); } + + jmethodID FromReflectedMethod(jobject method) + { return functions->FromReflectedMethod(this, method); } + + jfieldID FromReflectedField(jobject field) + { return functions->FromReflectedField(this, field); } + + jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) + { return functions->ToReflectedMethod(this, cls, methodID, isStatic); } + + jclass GetSuperclass(jclass clazz) + { return functions->GetSuperclass(this, clazz); } + + jboolean IsAssignableFrom(jclass clazz1, jclass clazz2) + { return functions->IsAssignableFrom(this, clazz1, clazz2); } + + jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) + { return functions->ToReflectedField(this, cls, fieldID, isStatic); } + + jint Throw(jthrowable obj) + { return functions->Throw(this, obj); } + + jint ThrowNew(jclass clazz, const char* message) + { return functions->ThrowNew(this, clazz, message); } + + jthrowable ExceptionOccurred() + { return functions->ExceptionOccurred(this); } + + void ExceptionDescribe() + { functions->ExceptionDescribe(this); } + + void ExceptionClear() + { functions->ExceptionClear(this); } + + void FatalError(const char* msg) + { functions->FatalError(this, msg); } + + jint PushLocalFrame(jint capacity) + { return functions->PushLocalFrame(this, capacity); } + + jobject PopLocalFrame(jobject result) + { return functions->PopLocalFrame(this, result); } + + jobject NewGlobalRef(jobject obj) + { return functions->NewGlobalRef(this, obj); } + + void DeleteGlobalRef(jobject globalRef) + { functions->DeleteGlobalRef(this, globalRef); } + + void DeleteLocalRef(jobject localRef) + { functions->DeleteLocalRef(this, localRef); } + + jboolean IsSameObject(jobject ref1, jobject ref2) + { return functions->IsSameObject(this, ref1, ref2); } + + jobject NewLocalRef(jobject ref) + { return functions->NewLocalRef(this, ref); } + + jint EnsureLocalCapacity(jint capacity) + { return functions->EnsureLocalCapacity(this, capacity); } + + jobject AllocObject(jclass clazz) + { return functions->AllocObject(this, clazz); } + + jobject NewObject(jclass clazz, jmethodID methodID, ...) + { + va_list args; + va_start(args, methodID); + jobject result = functions->NewObjectV(this, clazz, methodID, args); + va_end(args); + return result; + } + + jobject NewObjectV(jclass clazz, jmethodID methodID, va_list args) + { return functions->NewObjectV(this, clazz, methodID, args); } + + jobject NewObjectA(jclass clazz, jmethodID methodID, jvalue* args) + { return functions->NewObjectA(this, clazz, methodID, args); } + + jclass GetObjectClass(jobject obj) + { return functions->GetObjectClass(this, obj); } + + jboolean IsInstanceOf(jobject obj, jclass clazz) + { return functions->IsInstanceOf(this, obj, clazz); } + + jmethodID GetMethodID(jclass clazz, const char* name, const char* sig) + { return functions->GetMethodID(this, clazz, name, sig); } + +#define CALL_TYPE_METHOD(_jtype, _jname) \ + _jtype Call##_jname##Method(jobject obj, jmethodID methodID, ...) \ + { \ + _jtype result; \ + va_list args; \ + va_start(args, methodID); \ + result = functions->Call##_jname##MethodV(this, obj, methodID, \ + args); \ + va_end(args); \ + return result; \ + } +#define CALL_TYPE_METHODV(_jtype, _jname) \ + _jtype Call##_jname##MethodV(jobject obj, jmethodID methodID, \ + va_list args) \ + { return functions->Call##_jname##MethodV(this, obj, methodID, args); } +#define CALL_TYPE_METHODA(_jtype, _jname) \ + _jtype Call##_jname##MethodA(jobject obj, jmethodID methodID, \ + jvalue* args) \ + { return functions->Call##_jname##MethodA(this, obj, methodID, args); } + +#define CALL_TYPE(_jtype, _jname) \ + CALL_TYPE_METHOD(_jtype, _jname) \ + CALL_TYPE_METHODV(_jtype, _jname) \ + CALL_TYPE_METHODA(_jtype, _jname) + + CALL_TYPE(jobject, Object) + CALL_TYPE(jboolean, Boolean) + CALL_TYPE(jbyte, Byte) + CALL_TYPE(jchar, Char) + CALL_TYPE(jshort, Short) + CALL_TYPE(jint, Int) + CALL_TYPE(jlong, Long) + CALL_TYPE(jfloat, Float) + CALL_TYPE(jdouble, Double) + + void CallVoidMethod(jobject obj, jmethodID methodID, ...) + { + va_list args; + va_start(args, methodID); + functions->CallVoidMethodV(this, obj, methodID, args); + va_end(args); + } + void CallVoidMethodV(jobject obj, jmethodID methodID, va_list args) + { functions->CallVoidMethodV(this, obj, methodID, args); } + void CallVoidMethodA(jobject obj, jmethodID methodID, jvalue* args) + { functions->CallVoidMethodA(this, obj, methodID, args); } + +#define CALL_NONVIRT_TYPE_METHOD(_jtype, _jname) \ + _jtype CallNonvirtual##_jname##Method(jobject obj, jclass clazz, \ + jmethodID methodID, ...) \ + { \ + _jtype result; \ + va_list args; \ + va_start(args, methodID); \ + result = functions->CallNonvirtual##_jname##MethodV(this, obj, \ + clazz, methodID, args); \ + va_end(args); \ + return result; \ + } +#define CALL_NONVIRT_TYPE_METHODV(_jtype, _jname) \ + _jtype CallNonvirtual##_jname##MethodV(jobject obj, jclass clazz, \ + jmethodID methodID, va_list args) \ + { return functions->CallNonvirtual##_jname##MethodV(this, obj, clazz, \ + methodID, args); } +#define CALL_NONVIRT_TYPE_METHODA(_jtype, _jname) \ + _jtype CallNonvirtual##_jname##MethodA(jobject obj, jclass clazz, \ + jmethodID methodID, jvalue* args) \ + { return functions->CallNonvirtual##_jname##MethodA(this, obj, clazz, \ + methodID, args); } + +#define CALL_NONVIRT_TYPE(_jtype, _jname) \ + CALL_NONVIRT_TYPE_METHOD(_jtype, _jname) \ + CALL_NONVIRT_TYPE_METHODV(_jtype, _jname) \ + CALL_NONVIRT_TYPE_METHODA(_jtype, _jname) + + CALL_NONVIRT_TYPE(jobject, Object) + CALL_NONVIRT_TYPE(jboolean, Boolean) + CALL_NONVIRT_TYPE(jbyte, Byte) + CALL_NONVIRT_TYPE(jchar, Char) + CALL_NONVIRT_TYPE(jshort, Short) + CALL_NONVIRT_TYPE(jint, Int) + CALL_NONVIRT_TYPE(jlong, Long) + CALL_NONVIRT_TYPE(jfloat, Float) + CALL_NONVIRT_TYPE(jdouble, Double) + + void CallNonvirtualVoidMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) + { + va_list args; + va_start(args, methodID); + functions->CallNonvirtualVoidMethodV(this, obj, clazz, methodID, args); + va_end(args); + } + void CallNonvirtualVoidMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) + { functions->CallNonvirtualVoidMethodV(this, obj, clazz, methodID, args); } + void CallNonvirtualVoidMethodA(jobject obj, jclass clazz, + jmethodID methodID, jvalue* args) + { functions->CallNonvirtualVoidMethodA(this, obj, clazz, methodID, args); } + + jfieldID GetFieldID(jclass clazz, const char* name, const char* sig) + { return functions->GetFieldID(this, clazz, name, sig); } + + jobject GetObjectField(jobject obj, jfieldID fieldID) + { return functions->GetObjectField(this, obj, fieldID); } + jboolean GetBooleanField(jobject obj, jfieldID fieldID) + { return functions->GetBooleanField(this, obj, fieldID); } + jbyte GetByteField(jobject obj, jfieldID fieldID) + { return functions->GetByteField(this, obj, fieldID); } + jchar GetCharField(jobject obj, jfieldID fieldID) + { return functions->GetCharField(this, obj, fieldID); } + jshort GetShortField(jobject obj, jfieldID fieldID) + { return functions->GetShortField(this, obj, fieldID); } + jint GetIntField(jobject obj, jfieldID fieldID) + { return functions->GetIntField(this, obj, fieldID); } + jlong GetLongField(jobject obj, jfieldID fieldID) + { return functions->GetLongField(this, obj, fieldID); } + jfloat GetFloatField(jobject obj, jfieldID fieldID) + { return functions->GetFloatField(this, obj, fieldID); } + jdouble GetDoubleField(jobject obj, jfieldID fieldID) + { return functions->GetDoubleField(this, obj, fieldID); } + + void SetObjectField(jobject obj, jfieldID fieldID, jobject value) + { functions->SetObjectField(this, obj, fieldID, value); } + void SetBooleanField(jobject obj, jfieldID fieldID, jboolean value) + { functions->SetBooleanField(this, obj, fieldID, value); } + void SetByteField(jobject obj, jfieldID fieldID, jbyte value) + { functions->SetByteField(this, obj, fieldID, value); } + void SetCharField(jobject obj, jfieldID fieldID, jchar value) + { functions->SetCharField(this, obj, fieldID, value); } + void SetShortField(jobject obj, jfieldID fieldID, jshort value) + { functions->SetShortField(this, obj, fieldID, value); } + void SetIntField(jobject obj, jfieldID fieldID, jint value) + { functions->SetIntField(this, obj, fieldID, value); } + void SetLongField(jobject obj, jfieldID fieldID, jlong value) + { functions->SetLongField(this, obj, fieldID, value); } + void SetFloatField(jobject obj, jfieldID fieldID, jfloat value) + { functions->SetFloatField(this, obj, fieldID, value); } + void SetDoubleField(jobject obj, jfieldID fieldID, jdouble value) + { functions->SetDoubleField(this, obj, fieldID, value); } + + jmethodID GetStaticMethodID(jclass clazz, const char* name, const char* sig) + { return functions->GetStaticMethodID(this, clazz, name, sig); } + +#define CALL_STATIC_TYPE_METHOD(_jtype, _jname) \ + _jtype CallStatic##_jname##Method(jclass clazz, jmethodID methodID, \ + ...) \ + { \ + _jtype result; \ + va_list args; \ + va_start(args, methodID); \ + result = functions->CallStatic##_jname##MethodV(this, clazz, \ + methodID, args); \ + va_end(args); \ + return result; \ + } +#define CALL_STATIC_TYPE_METHODV(_jtype, _jname) \ + _jtype CallStatic##_jname##MethodV(jclass clazz, jmethodID methodID, \ + va_list args) \ + { return functions->CallStatic##_jname##MethodV(this, clazz, methodID, \ + args); } +#define CALL_STATIC_TYPE_METHODA(_jtype, _jname) \ + _jtype CallStatic##_jname##MethodA(jclass clazz, jmethodID methodID, \ + jvalue* args) \ + { return functions->CallStatic##_jname##MethodA(this, clazz, methodID, \ + args); } + +#define CALL_STATIC_TYPE(_jtype, _jname) \ + CALL_STATIC_TYPE_METHOD(_jtype, _jname) \ + CALL_STATIC_TYPE_METHODV(_jtype, _jname) \ + CALL_STATIC_TYPE_METHODA(_jtype, _jname) + + CALL_STATIC_TYPE(jobject, Object) + CALL_STATIC_TYPE(jboolean, Boolean) + CALL_STATIC_TYPE(jbyte, Byte) + CALL_STATIC_TYPE(jchar, Char) + CALL_STATIC_TYPE(jshort, Short) + CALL_STATIC_TYPE(jint, Int) + CALL_STATIC_TYPE(jlong, Long) + CALL_STATIC_TYPE(jfloat, Float) + CALL_STATIC_TYPE(jdouble, Double) + + void CallStaticVoidMethod(jclass clazz, jmethodID methodID, ...) + { + va_list args; + va_start(args, methodID); + functions->CallStaticVoidMethodV(this, clazz, methodID, args); + va_end(args); + } + void CallStaticVoidMethodV(jclass clazz, jmethodID methodID, va_list args) + { functions->CallStaticVoidMethodV(this, clazz, methodID, args); } + void CallStaticVoidMethodA(jclass clazz, jmethodID methodID, jvalue* args) + { functions->CallStaticVoidMethodA(this, clazz, methodID, args); } + + jfieldID GetStaticFieldID(jclass clazz, const char* name, const char* sig) + { return functions->GetStaticFieldID(this, clazz, name, sig); } + + jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) + { return functions->GetStaticObjectField(this, clazz, fieldID); } + jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) + { return functions->GetStaticBooleanField(this, clazz, fieldID); } + jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) + { return functions->GetStaticByteField(this, clazz, fieldID); } + jchar GetStaticCharField(jclass clazz, jfieldID fieldID) + { return functions->GetStaticCharField(this, clazz, fieldID); } + jshort GetStaticShortField(jclass clazz, jfieldID fieldID) + { return functions->GetStaticShortField(this, clazz, fieldID); } + jint GetStaticIntField(jclass clazz, jfieldID fieldID) + { return functions->GetStaticIntField(this, clazz, fieldID); } + jlong GetStaticLongField(jclass clazz, jfieldID fieldID) + { return functions->GetStaticLongField(this, clazz, fieldID); } + jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) + { return functions->GetStaticFloatField(this, clazz, fieldID); } + jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) + { return functions->GetStaticDoubleField(this, clazz, fieldID); } + + void SetStaticObjectField(jclass clazz, jfieldID fieldID, jobject value) + { functions->SetStaticObjectField(this, clazz, fieldID, value); } + void SetStaticBooleanField(jclass clazz, jfieldID fieldID, jboolean value) + { functions->SetStaticBooleanField(this, clazz, fieldID, value); } + void SetStaticByteField(jclass clazz, jfieldID fieldID, jbyte value) + { functions->SetStaticByteField(this, clazz, fieldID, value); } + void SetStaticCharField(jclass clazz, jfieldID fieldID, jchar value) + { functions->SetStaticCharField(this, clazz, fieldID, value); } + void SetStaticShortField(jclass clazz, jfieldID fieldID, jshort value) + { functions->SetStaticShortField(this, clazz, fieldID, value); } + void SetStaticIntField(jclass clazz, jfieldID fieldID, jint value) + { functions->SetStaticIntField(this, clazz, fieldID, value); } + void SetStaticLongField(jclass clazz, jfieldID fieldID, jlong value) + { functions->SetStaticLongField(this, clazz, fieldID, value); } + void SetStaticFloatField(jclass clazz, jfieldID fieldID, jfloat value) + { functions->SetStaticFloatField(this, clazz, fieldID, value); } + void SetStaticDoubleField(jclass clazz, jfieldID fieldID, jdouble value) + { functions->SetStaticDoubleField(this, clazz, fieldID, value); } + + jstring NewString(const jchar* unicodeChars, jsize len) + { return functions->NewString(this, unicodeChars, len); } + + jsize GetStringLength(jstring string) + { return functions->GetStringLength(this, string); } + + const jchar* GetStringChars(jstring string, jboolean* isCopy) + { return functions->GetStringChars(this, string, isCopy); } + + void ReleaseStringChars(jstring string, const jchar* chars) + { functions->ReleaseStringChars(this, string, chars); } + + jstring NewStringUTF(const char* bytes) + { return functions->NewStringUTF(this, bytes); } + + jsize GetStringUTFLength(jstring string) + { return functions->GetStringUTFLength(this, string); } + + const char* GetStringUTFChars(jstring string, jboolean* isCopy) + { return functions->GetStringUTFChars(this, string, isCopy); } + + void ReleaseStringUTFChars(jstring string, const char* utf) + { functions->ReleaseStringUTFChars(this, string, utf); } + + jsize GetArrayLength(jarray array) + { return functions->GetArrayLength(this, array); } + + jobjectArray NewObjectArray(jsize length, jclass elementClass, + jobject initialElement) + { return functions->NewObjectArray(this, length, elementClass, + initialElement); } + + jobject GetObjectArrayElement(jobjectArray array, jsize index) + { return functions->GetObjectArrayElement(this, array, index); } + + void SetObjectArrayElement(jobjectArray array, jsize index, jobject value) + { functions->SetObjectArrayElement(this, array, index, value); } + + jbooleanArray NewBooleanArray(jsize length) + { return functions->NewBooleanArray(this, length); } + jbyteArray NewByteArray(jsize length) + { return functions->NewByteArray(this, length); } + jcharArray NewCharArray(jsize length) + { return functions->NewCharArray(this, length); } + jshortArray NewShortArray(jsize length) + { return functions->NewShortArray(this, length); } + jintArray NewIntArray(jsize length) + { return functions->NewIntArray(this, length); } + jlongArray NewLongArray(jsize length) + { return functions->NewLongArray(this, length); } + jfloatArray NewFloatArray(jsize length) + { return functions->NewFloatArray(this, length); } + jdoubleArray NewDoubleArray(jsize length) + { return functions->NewDoubleArray(this, length); } + + jboolean* GetBooleanArrayElements(jbooleanArray array, jboolean* isCopy) + { return functions->GetBooleanArrayElements(this, array, isCopy); } + jbyte* GetByteArrayElements(jbyteArray array, jboolean* isCopy) + { return functions->GetByteArrayElements(this, array, isCopy); } + jchar* GetCharArrayElements(jcharArray array, jboolean* isCopy) + { return functions->GetCharArrayElements(this, array, isCopy); } + jshort* GetShortArrayElements(jshortArray array, jboolean* isCopy) + { return functions->GetShortArrayElements(this, array, isCopy); } + jint* GetIntArrayElements(jintArray array, jboolean* isCopy) + { return functions->GetIntArrayElements(this, array, isCopy); } + jlong* GetLongArrayElements(jlongArray array, jboolean* isCopy) + { return functions->GetLongArrayElements(this, array, isCopy); } + jfloat* GetFloatArrayElements(jfloatArray array, jboolean* isCopy) + { return functions->GetFloatArrayElements(this, array, isCopy); } + jdouble* GetDoubleArrayElements(jdoubleArray array, jboolean* isCopy) + { return functions->GetDoubleArrayElements(this, array, isCopy); } + + void ReleaseBooleanArrayElements(jbooleanArray array, jboolean* elems, + jint mode) + { functions->ReleaseBooleanArrayElements(this, array, elems, mode); } + void ReleaseByteArrayElements(jbyteArray array, jbyte* elems, + jint mode) + { functions->ReleaseByteArrayElements(this, array, elems, mode); } + void ReleaseCharArrayElements(jcharArray array, jchar* elems, + jint mode) + { functions->ReleaseCharArrayElements(this, array, elems, mode); } + void ReleaseShortArrayElements(jshortArray array, jshort* elems, + jint mode) + { functions->ReleaseShortArrayElements(this, array, elems, mode); } + void ReleaseIntArrayElements(jintArray array, jint* elems, + jint mode) + { functions->ReleaseIntArrayElements(this, array, elems, mode); } + void ReleaseLongArrayElements(jlongArray array, jlong* elems, + jint mode) + { functions->ReleaseLongArrayElements(this, array, elems, mode); } + void ReleaseFloatArrayElements(jfloatArray array, jfloat* elems, + jint mode) + { functions->ReleaseFloatArrayElements(this, array, elems, mode); } + void ReleaseDoubleArrayElements(jdoubleArray array, jdouble* elems, + jint mode) + { functions->ReleaseDoubleArrayElements(this, array, elems, mode); } + + void GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len, + jboolean* buf) + { functions->GetBooleanArrayRegion(this, array, start, len, buf); } + void GetByteArrayRegion(jbyteArray array, jsize start, jsize len, + jbyte* buf) + { functions->GetByteArrayRegion(this, array, start, len, buf); } + void GetCharArrayRegion(jcharArray array, jsize start, jsize len, + jchar* buf) + { functions->GetCharArrayRegion(this, array, start, len, buf); } + void GetShortArrayRegion(jshortArray array, jsize start, jsize len, + jshort* buf) + { functions->GetShortArrayRegion(this, array, start, len, buf); } + void GetIntArrayRegion(jintArray array, jsize start, jsize len, + jint* buf) + { functions->GetIntArrayRegion(this, array, start, len, buf); } + void GetLongArrayRegion(jlongArray array, jsize start, jsize len, + jlong* buf) + { functions->GetLongArrayRegion(this, array, start, len, buf); } + void GetFloatArrayRegion(jfloatArray array, jsize start, jsize len, + jfloat* buf) + { functions->GetFloatArrayRegion(this, array, start, len, buf); } + void GetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, + jdouble* buf) + { functions->GetDoubleArrayRegion(this, array, start, len, buf); } + + void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len, + const jboolean* buf) + { functions->SetBooleanArrayRegion(this, array, start, len, buf); } + void SetByteArrayRegion(jbyteArray array, jsize start, jsize len, + const jbyte* buf) + { functions->SetByteArrayRegion(this, array, start, len, buf); } + void SetCharArrayRegion(jcharArray array, jsize start, jsize len, + const jchar* buf) + { functions->SetCharArrayRegion(this, array, start, len, buf); } + void SetShortArrayRegion(jshortArray array, jsize start, jsize len, + const jshort* buf) + { functions->SetShortArrayRegion(this, array, start, len, buf); } + void SetIntArrayRegion(jintArray array, jsize start, jsize len, + const jint* buf) + { functions->SetIntArrayRegion(this, array, start, len, buf); } + void SetLongArrayRegion(jlongArray array, jsize start, jsize len, + const jlong* buf) + { functions->SetLongArrayRegion(this, array, start, len, buf); } + void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, + const jfloat* buf) + { functions->SetFloatArrayRegion(this, array, start, len, buf); } + void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, + const jdouble* buf) + { functions->SetDoubleArrayRegion(this, array, start, len, buf); } + + jint RegisterNatives(jclass clazz, const JNINativeMethod* methods, + jint nMethods) + { return functions->RegisterNatives(this, clazz, methods, nMethods); } + + jint UnregisterNatives(jclass clazz) + { return functions->UnregisterNatives(this, clazz); } + + jint MonitorEnter(jobject obj) + { return functions->MonitorEnter(this, obj); } + + jint MonitorExit(jobject obj) + { return functions->MonitorExit(this, obj); } + + jint GetJavaVM(JavaVM** vm) + { return functions->GetJavaVM(this, vm); } + + void GetStringRegion(jstring str, jsize start, jsize len, jchar* buf) + { functions->GetStringRegion(this, str, start, len, buf); } + + void GetStringUTFRegion(jstring str, jsize start, jsize len, char* buf) + { return functions->GetStringUTFRegion(this, str, start, len, buf); } + + void* GetPrimitiveArrayCritical(jarray array, jboolean* isCopy) + { return functions->GetPrimitiveArrayCritical(this, array, isCopy); } + + void ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode) + { functions->ReleasePrimitiveArrayCritical(this, array, carray, mode); } + + const jchar* GetStringCritical(jstring string, jboolean* isCopy) + { return functions->GetStringCritical(this, string, isCopy); } + + void ReleaseStringCritical(jstring string, const jchar* carray) + { functions->ReleaseStringCritical(this, string, carray); } + + jweak NewWeakGlobalRef(jobject obj) + { return functions->NewWeakGlobalRef(this, obj); } + + void DeleteWeakGlobalRef(jweak obj) + { functions->DeleteWeakGlobalRef(this, obj); } + + jboolean ExceptionCheck() + { return functions->ExceptionCheck(this); } + + jobject NewDirectByteBuffer(void* address, jlong capacity) + { return functions->NewDirectByteBuffer(this, address, capacity); } + + void* GetDirectBufferAddress(jobject buf) + { return functions->GetDirectBufferAddress(this, buf); } + + jlong GetDirectBufferCapacity(jobject buf) + { return functions->GetDirectBufferCapacity(this, buf); } + + /* added in JNI 1.6 */ + jobjectRefType GetObjectRefType(jobject obj) + { return functions->GetObjectRefType(this, obj); } +#endif /*__cplusplus*/ +}; + + +/* + * JNI invocation interface. + */ +struct JNIInvokeInterface { + void* reserved0; + void* reserved1; + void* reserved2; + + jint (*DestroyJavaVM)(JavaVM*); + jint (*AttachCurrentThread)(JavaVM*, JNIEnv**, void*); + jint (*DetachCurrentThread)(JavaVM*); + jint (*GetEnv)(JavaVM*, void**, jint); + jint (*AttachCurrentThreadAsDaemon)(JavaVM*, JNIEnv**, void*); +}; + +/* + * C++ version. + */ +struct _JavaVM { + const struct JNIInvokeInterface* functions; + +#if defined(__cplusplus) + jint DestroyJavaVM() + { return functions->DestroyJavaVM(this); } + jint AttachCurrentThread(JNIEnv** p_env, void* thr_args) + { return functions->AttachCurrentThread(this, p_env, thr_args); } + jint DetachCurrentThread() + { return functions->DetachCurrentThread(this); } + jint GetEnv(void** env, jint version) + { return functions->GetEnv(this, env, version); } + jint AttachCurrentThreadAsDaemon(JNIEnv** p_env, void* thr_args) + { return functions->AttachCurrentThreadAsDaemon(this, p_env, thr_args); } +#endif /*__cplusplus*/ +}; + +struct JavaVMAttachArgs { + jint version; /* must be >= JNI_VERSION_1_2 */ + const char* name; /* NULL or name of thread as modified UTF-8 str */ + jobject group; /* global ref of a ThreadGroup object, or NULL */ +}; +typedef struct JavaVMAttachArgs JavaVMAttachArgs; + +/* + * JNI 1.2+ initialization. (As of 1.6, the pre-1.2 structures are no + * longer supported.) + */ +typedef struct JavaVMOption { + const char* optionString; + void* extraInfo; +} JavaVMOption; + +typedef struct JavaVMInitArgs { + jint version; /* use JNI_VERSION_1_2 or later */ + + jint nOptions; + JavaVMOption* options; + jboolean ignoreUnrecognized; +} JavaVMInitArgs; + +#ifdef __cplusplus +extern "C" { +#endif +/* + * VM initialization functions. + * + * Note these are the only symbols exported for JNI by the VM. + */ +jint JNI_GetDefaultJavaVMInitArgs(void*); +jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*); +jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*); + +#define JNIIMPORT +#define JNIEXPORT __attribute__ ((visibility ("default"))) +#define JNICALL + +/* + * Prototypes for functions exported by loadable shared libs. These are + * called by JNI, not provided by JNI. + */ +JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved); +JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved); + +#ifdef __cplusplus +} +#endif + + +/* + * Manifest constants. + */ +#define JNI_FALSE 0 +#define JNI_TRUE 1 + +#define JNI_VERSION_1_1 0x00010001 +#define JNI_VERSION_1_2 0x00010002 +#define JNI_VERSION_1_4 0x00010004 +#define JNI_VERSION_1_6 0x00010006 + +#define JNI_OK (0) /* no error */ +#define JNI_ERR (-1) /* generic error */ +#define JNI_EDETACHED (-2) /* thread detached from the VM */ +#define JNI_EVERSION (-3) /* JNI version error */ + +#define JNI_COMMIT 1 /* copy content, do not free buffer */ +#define JNI_ABORT 2 /* free buffer w/o copying back */ + +#endif /* JNI_H_ */ diff --git a/jni/jnienv.c b/jni/jnienv.c new file mode 100644 index 0000000..c04bebc --- /dev/null +++ b/jni/jnienv.c @@ -0,0 +1,2152 @@ + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + +#include +#include +#include + +#include "jnienv.h" +#include "../apkenv.h" + +#ifdef APKENV_DEBUG +# define JNIENV_DEBUG_PRINTF(...) printf(__VA_ARGS__) +#else +# define JNIENV_DEBUG_PRINTF(...) +#endif + +jint +JNIEnv_GetVersion(JNIEnv * p0) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetVersion()\n"); + return 0; +} + + +jclass +JNIEnv_DefineClass(JNIEnv* p0, const char* p1, jobject p2, const jbyte* p3, jsize p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_DefineClass()\n"); + return NULL; +} + + +jclass +JNIEnv_FindClass(JNIEnv* p0, const char* p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_FindClass('%s')\n", p1); + struct dummy_jclass *class = malloc(sizeof(struct dummy_jclass)); + class->name = strdup(p1); + return class; +} + + +jmethodID +JNIEnv_FromReflectedMethod(JNIEnv* p0, jobject p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_FromReflectedMethod()\n"); + return NULL; +} + + +jfieldID +JNIEnv_FromReflectedField(JNIEnv* p0, jobject p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_FromReflectedField()\n"); + return NULL; +} + + +jobject +JNIEnv_ToReflectedMethod(JNIEnv* p0, jclass p1, jmethodID p2, jboolean p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ToReflectedMethod()\n"); + return NULL; +} + + +jclass +JNIEnv_GetSuperclass(JNIEnv* p0, jclass p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetSuperclass()\n"); + return NULL; +} + + +jboolean +JNIEnv_IsAssignableFrom(JNIEnv* p0, jclass p1, jclass p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_IsAssignableFrom()\n"); + return 0; +} + + +jobject +JNIEnv_ToReflectedField(JNIEnv* p0, jclass p1, jfieldID p2, jboolean p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ToReflectedField()\n"); + return NULL; +} + + +jint +JNIEnv_Throw(JNIEnv* p0, jthrowable p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_Throw()\n"); + return 0; +} + + +jint +JNIEnv_ThrowNew(JNIEnv * p0, jclass p1, const char * p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ThrowNew()\n"); + return 0; +} + + +jthrowable +JNIEnv_ExceptionOccurred(JNIEnv* p0) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ExceptionOccurred()\n"); + return NULL; +} + + +void +JNIEnv_ExceptionDescribe(JNIEnv* p0) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ExceptionDescribe()\n"); +} + + +void +JNIEnv_ExceptionClear(JNIEnv* p0) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ExceptionClear()\n"); +} + + +void +JNIEnv_FatalError(JNIEnv* p0, const char* p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_FatalError()\n"); +} + + +jint +JNIEnv_PushLocalFrame(JNIEnv* p0, jint p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_PushLocalFrame()\n"); + return 0; +} + + +jobject +JNIEnv_PopLocalFrame(JNIEnv* p0, jobject p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_PopLocalFrame()\n"); + return NULL; +} + + +jobject +JNIEnv_NewGlobalRef(JNIEnv* p0, jobject p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewGlobalRef(%x)\n", p1); + return NULL; +} + + +void +JNIEnv_DeleteGlobalRef(JNIEnv* p0, jobject p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_DeleteGlobalRef()\n"); +} + + +void +JNIEnv_DeleteLocalRef(JNIEnv* p0, jobject p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_DeleteLocalRef(%x)\n", p1); +} + + +jboolean +JNIEnv_IsSameObject(JNIEnv* p0, jobject p1, jobject p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_IsSameObject()\n"); + return 0; +} + + +jobject +JNIEnv_NewLocalRef(JNIEnv* p0, jobject p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewLocalRef()\n"); + return NULL; +} + + +jint +JNIEnv_EnsureLocalCapacity(JNIEnv* p0, jint p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_EnsureLocalCapacity()\n"); + return 0; +} + + +jobject +JNIEnv_AllocObject(JNIEnv* p0, jclass p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_AllocObject()\n"); + return NULL; +} + + +jobject +JNIEnv_NewObject(JNIEnv* p0, jclass p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewObject(%x, %s)\n", p1, p2->name); + return NULL; +} + + +jobject +JNIEnv_NewObjectV(JNIEnv *env, jclass p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewObjectV(%x, %s)\n", p1, p2->name); + return GLOBAL_J(env); +} + + +jobject +JNIEnv_NewObjectA(JNIEnv* p0, jclass p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewObjectA()\n"); + return NULL; +} + + +jclass +JNIEnv_GetObjectClass(JNIEnv* env, jobject p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetObjectClass(%x, %x)\n", env, p1); + return GLOBAL_J(env); +} + + +jboolean +JNIEnv_IsInstanceOf(JNIEnv* p0, jobject p1, jclass p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_IsInstanceOf()\n"); + return 0; +} + +jmethodID +jnienv_make_method(jclass clazz, const char *name, const char *sig) +{ + jmethodID id = malloc(sizeof(struct _jmethodID)); + id->clazz = clazz; + id->name = strdup(name); + id->sig = strdup(sig); + return id; +} + +jmethodID +JNIEnv_GetMethodID(JNIEnv* p0, jclass clazz, const char* name, const char* sig) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetMethodID(%x, '%s', '%s')\n", clazz, name, sig); + return jnienv_make_method(clazz, name, sig); +} + + +jobject +JNIEnv_CallObjectMethod(JNIEnv* p0, jobject p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallObjectMethod()\n"); + return NULL; +} + + +jobject +JNIEnv_CallObjectMethodV(JNIEnv *env, jobject p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallObjectMethodV(%x, %s, %s, ...)\n", p1, p2->name, p2->sig); + return GLOBAL_J(env); +} + + +jobject +JNIEnv_CallObjectMethodA(JNIEnv* p0, jobject p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallObjectMethodA()\n"); + return NULL; +} + + +jboolean +JNIEnv_CallBooleanMethod(JNIEnv* p0, jobject p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallBooleanMethod()\n"); + return 0; +} + + +jboolean +JNIEnv_CallBooleanMethodV(JNIEnv* p0, jobject p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallBooleanMethodV(%s)\n", p2->name); + return 0; +} + + +jboolean +JNIEnv_CallBooleanMethodA(JNIEnv* p0, jobject p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallBooleanMethodA()\n"); + return 0; +} + + +jbyte +JNIEnv_CallByteMethod(JNIEnv* p0, jobject p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallByteMethod()\n"); + return 0; +} + + +jbyte +JNIEnv_CallByteMethodV(JNIEnv* p0, jobject p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallByteMethodV()\n"); + return 0; +} + + +jbyte +JNIEnv_CallByteMethodA(JNIEnv* p0, jobject p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallByteMethodA()\n"); + return 0; +} + + +jchar +JNIEnv_CallCharMethod(JNIEnv* p0, jobject p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallCharMethod()\n"); + return 0; +} + + +jchar +JNIEnv_CallCharMethodV(JNIEnv* p0, jobject p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallCharMethodV()\n"); + return 0; +} + + +jchar +JNIEnv_CallCharMethodA(JNIEnv* p0, jobject p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallCharMethodA()\n"); + return 0; +} + + +jshort +JNIEnv_CallShortMethod(JNIEnv* p0, jobject p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallShortMethod()\n"); + return 0; +} + + +jshort +JNIEnv_CallShortMethodV(JNIEnv* p0, jobject p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallShortMethodV()\n"); + return 0; +} + + +jshort +JNIEnv_CallShortMethodA(JNIEnv* p0, jobject p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallShortMethodA()\n"); + return 0; +} + + +jint +JNIEnv_CallIntMethod(JNIEnv* p0, jobject p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallIntMethod()\n"); + return 0; +} + + +jint +JNIEnv_CallIntMethodV(JNIEnv* p0, jobject p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallIntMethodV()\n"); + return 0; +} + + +jint +JNIEnv_CallIntMethodA(JNIEnv* p0, jobject p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallIntMethodA()\n"); + return 0; +} + + +jlong +JNIEnv_CallLongMethod(JNIEnv* p0, jobject p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallLongMethod()\n"); + return 0; +} + + +jlong +JNIEnv_CallLongMethodV(JNIEnv* p0, jobject p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallLongMethodV(%s)\n", p2->name); + return 0; +} + + +jlong +JNIEnv_CallLongMethodA(JNIEnv* p0, jobject p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallLongMethodA()\n"); + return 0; +} + + +jfloat +JNIEnv_CallFloatMethod(JNIEnv* p0, jobject p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallFloatMethod()\n"); + return 0.f; +} + + +jfloat +JNIEnv_CallFloatMethodV(JNIEnv* p0, jobject p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallFloatMethodV()\n"); + return 0.f; +} + + +jfloat +JNIEnv_CallFloatMethodA(JNIEnv* p0, jobject p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallFloatMethodA()\n"); + return 0.f; +} + + +jdouble +JNIEnv_CallDoubleMethod(JNIEnv* p0, jobject p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallDoubleMethod()\n"); + return 0.; +} + + +jdouble +JNIEnv_CallDoubleMethodV(JNIEnv* p0, jobject p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallDoubleMethodV()\n"); + return 0.; +} + + +jdouble +JNIEnv_CallDoubleMethodA(JNIEnv* p0, jobject p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallDoubleMethodA()\n"); + return 0.; +} + + +void +JNIEnv_CallVoidMethod(JNIEnv* p0, jobject p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallVoidMethod(%x)\n", p1); +} + + +void +JNIEnv_CallVoidMethodV(JNIEnv* p0, jobject p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallVoidMethodV(%x, %s, %s)\n", p1, p2->name, p2->sig); +} + + +void +JNIEnv_CallVoidMethodA(JNIEnv* p0, jobject p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallVoidMethodA()\n"); +} + + +jobject +JNIEnv_CallNonvirtualObjectMethod(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualObjectMethod()\n"); + return NULL; +} + + +jobject +JNIEnv_CallNonvirtualObjectMethodV(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, va_list p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualObjectMethodV()\n"); + return NULL; +} + + +jobject +JNIEnv_CallNonvirtualObjectMethodA(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, jvalue* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualObjectMethodA()\n"); + return NULL; +} + + +jboolean +JNIEnv_CallNonvirtualBooleanMethod(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualBooleanMethod()\n"); + return 0; +} + + +jboolean +JNIEnv_CallNonvirtualBooleanMethodV(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, va_list p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualBooleanMethodV()\n"); + return 0; +} + + +jboolean +JNIEnv_CallNonvirtualBooleanMethodA(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, jvalue* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualBooleanMethodA()\n"); + return 0; +} + + +jbyte +JNIEnv_CallNonvirtualByteMethod(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualByteMethod()\n"); + return 0; +} + + +jbyte +JNIEnv_CallNonvirtualByteMethodV(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, va_list p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualByteMethodV()\n"); + return 0; +} + + +jbyte +JNIEnv_CallNonvirtualByteMethodA(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, jvalue* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualByteMethodA()\n"); + return 0; +} + + +jchar +JNIEnv_CallNonvirtualCharMethod(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualCharMethod()\n"); + return 0; +} + + +jchar +JNIEnv_CallNonvirtualCharMethodV(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, va_list p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualCharMethodV()\n"); + return 0; +} + + +jchar +JNIEnv_CallNonvirtualCharMethodA(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, jvalue* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualCharMethodA()\n"); + return 0; +} + + +jshort +JNIEnv_CallNonvirtualShortMethod(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualShortMethod()\n"); + return 0; +} + + +jshort +JNIEnv_CallNonvirtualShortMethodV(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, va_list p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualShortMethodV()\n"); + return 0; +} + + +jshort +JNIEnv_CallNonvirtualShortMethodA(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, jvalue* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualShortMethodA()\n"); + return 0; +} + + +jint +JNIEnv_CallNonvirtualIntMethod(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualIntMethod()\n"); + return 0; +} + + +jint +JNIEnv_CallNonvirtualIntMethodV(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, va_list p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualIntMethodV()\n"); + return 0; +} + + +jint +JNIEnv_CallNonvirtualIntMethodA(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, jvalue* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualIntMethodA()\n"); + return 0; +} + + +jlong +JNIEnv_CallNonvirtualLongMethod(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualLongMethod()\n"); + return 0; +} + + +jlong +JNIEnv_CallNonvirtualLongMethodV(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, va_list p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualLongMethodV()\n"); + return 0; +} + + +jlong +JNIEnv_CallNonvirtualLongMethodA(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, jvalue* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualLongMethodA()\n"); + return 0; +} + + +jfloat +JNIEnv_CallNonvirtualFloatMethod(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualFloatMethod()\n"); + return 0.f; +} + + +jfloat +JNIEnv_CallNonvirtualFloatMethodV(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, va_list p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualFloatMethodV()\n"); + return 0.f; +} + + +jfloat +JNIEnv_CallNonvirtualFloatMethodA(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, jvalue* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualFloatMethodA()\n"); + return 0.f; +} + + +jdouble +JNIEnv_CallNonvirtualDoubleMethod(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualDoubleMethod()\n"); + return 0.; +} + + +jdouble +JNIEnv_CallNonvirtualDoubleMethodV(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, va_list p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualDoubleMethodV()\n"); + return 0.; +} + + +jdouble +JNIEnv_CallNonvirtualDoubleMethodA(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, jvalue* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualDoubleMethodA()\n"); + return 0.; +} + + +void +JNIEnv_CallNonvirtualVoidMethod(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualVoidMethod()\n"); +} + + +void +JNIEnv_CallNonvirtualVoidMethodV(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, va_list p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualVoidMethodV()\n"); +} + + +void +JNIEnv_CallNonvirtualVoidMethodA(JNIEnv* p0, jobject p1, jclass p2, jmethodID p3, jvalue* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallNonvirtualVoidMethodA()\n"); +} + + +jfieldID +JNIEnv_GetFieldID(JNIEnv* p0, jclass p1, const char* p2, const char* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetFieldID()\n"); + return NULL; +} + + +jobject +JNIEnv_GetObjectField(JNIEnv* p0, jobject p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetObjectField()\n"); + return NULL; +} + + +jboolean +JNIEnv_GetBooleanField(JNIEnv* p0, jobject p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetBooleanField()\n"); + return 0; +} + + +jbyte +JNIEnv_GetByteField(JNIEnv* p0, jobject p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetByteField()\n"); + return 0; +} + + +jchar +JNIEnv_GetCharField(JNIEnv* p0, jobject p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetCharField()\n"); + return 0; +} + + +jshort +JNIEnv_GetShortField(JNIEnv* p0, jobject p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetShortField()\n"); + return 0; +} + + +jint +JNIEnv_GetIntField(JNIEnv* p0, jobject p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetIntField()\n"); + return 0; +} + + +jlong +JNIEnv_GetLongField(JNIEnv* p0, jobject p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetLongField()\n"); + return 0; +} + + +jfloat +JNIEnv_GetFloatField(JNIEnv* p0, jobject p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetFloatField()\n"); + return 0.f; +} + + +jdouble +JNIEnv_GetDoubleField(JNIEnv* p0, jobject p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetDoubleField()\n"); + return 0.; +} + + +void +JNIEnv_SetObjectField(JNIEnv* p0, jobject p1, jfieldID p2, jobject p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetObjectField()\n"); +} + + +void +JNIEnv_SetBooleanField(JNIEnv* p0, jobject p1, jfieldID p2, jboolean p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetBooleanField()\n"); +} + + +void +JNIEnv_SetByteField(JNIEnv* p0, jobject p1, jfieldID p2, jbyte p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetByteField()\n"); +} + + +void +JNIEnv_SetCharField(JNIEnv* p0, jobject p1, jfieldID p2, jchar p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetCharField()\n"); +} + + +void +JNIEnv_SetShortField(JNIEnv* p0, jobject p1, jfieldID p2, jshort p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetShortField()\n"); +} + + +void +JNIEnv_SetIntField(JNIEnv* p0, jobject p1, jfieldID p2, jint p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetIntField()\n"); +} + + +void +JNIEnv_SetLongField(JNIEnv* p0, jobject p1, jfieldID p2, jlong p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetLongField()\n"); +} + + +void +JNIEnv_SetFloatField(JNIEnv* p0, jobject p1, jfieldID p2, jfloat p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetFloatField()\n"); +} + + +void +JNIEnv_SetDoubleField(JNIEnv* p0, jobject p1, jfieldID p2, jdouble p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetDoubleField()\n"); +} + + +jmethodID +JNIEnv_GetStaticMethodID(JNIEnv* p0, jclass clazz, const char* name, const char* sig) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStaticMethodID(%x, %s, %s)\n", + clazz, name, sig); + return jnienv_make_method(clazz, name, sig); +} + + +jobject +JNIEnv_CallStaticObjectMethod(JNIEnv* p0, jclass p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticObjectMethod()\n"); + return NULL; +} + + +jobject +JNIEnv_CallStaticObjectMethodV(JNIEnv* p0, jclass p1, jmethodID p2, va_list p3) +{ + struct dummy_jclass *jcl = p1; + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticObjectMethodV(%s, %s, %s)\n", + jcl->name, p2->name, p2->sig); + return NULL; +} + + +jobject +JNIEnv_CallStaticObjectMethodA(JNIEnv* p0, jclass p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticObjectMethodA()\n"); + return NULL; +} + + +jboolean +JNIEnv_CallStaticBooleanMethod(JNIEnv* p0, jclass p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticBooleanMethod()\n"); + return 0; +} + + +jboolean +JNIEnv_CallStaticBooleanMethodV(JNIEnv* p0, jclass p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticBooleanMethodV()\n"); + return 0; +} + + +jboolean +JNIEnv_CallStaticBooleanMethodA(JNIEnv* p0, jclass p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticBooleanMethodA()\n"); + return 0; +} + + +jbyte +JNIEnv_CallStaticByteMethod(JNIEnv* p0, jclass p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticByteMethod()\n"); + return 0; +} + + +jbyte +JNIEnv_CallStaticByteMethodV(JNIEnv* p0, jclass p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticByteMethodV()\n"); + return 0; +} + + +jbyte +JNIEnv_CallStaticByteMethodA(JNIEnv* p0, jclass p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticByteMethodA()\n"); + return 0; +} + + +jchar +JNIEnv_CallStaticCharMethod(JNIEnv* p0, jclass p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticCharMethod()\n"); + return 0; +} + + +jchar +JNIEnv_CallStaticCharMethodV(JNIEnv* p0, jclass p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticCharMethodV()\n"); + return 0; +} + + +jchar +JNIEnv_CallStaticCharMethodA(JNIEnv* p0, jclass p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticCharMethodA()\n"); + return 0; +} + + +jshort +JNIEnv_CallStaticShortMethod(JNIEnv* p0, jclass p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticShortMethod()\n"); + return 0; +} + + +jshort +JNIEnv_CallStaticShortMethodV(JNIEnv* p0, jclass p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticShortMethodV()\n"); + return 0; +} + + +jshort +JNIEnv_CallStaticShortMethodA(JNIEnv* p0, jclass p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticShortMethodA()\n"); + return 0; +} + + +jint +JNIEnv_CallStaticIntMethod(JNIEnv* p0, jclass p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticIntMethod()\n"); + return 0; +} + + +jint +JNIEnv_CallStaticIntMethodV(JNIEnv* p0, jclass p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticIntMethodV()\n"); + return 0; +} + + +jint +JNIEnv_CallStaticIntMethodA(JNIEnv* p0, jclass p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticIntMethodA()\n"); + return 0; +} + + +jlong +JNIEnv_CallStaticLongMethod(JNIEnv* p0, jclass p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticLongMethod()\n"); + return 0; +} + + +jlong +JNIEnv_CallStaticLongMethodV(JNIEnv* p0, jclass p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticLongMethodV()\n"); + return 0; +} + + +jlong +JNIEnv_CallStaticLongMethodA(JNIEnv* p0, jclass p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticLongMethodA()\n"); + return 0; +} + + +jfloat +JNIEnv_CallStaticFloatMethod(JNIEnv* p0, jclass p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticFloatMethod()\n"); + return 0.f; +} + + +jfloat +JNIEnv_CallStaticFloatMethodV(JNIEnv* p0, jclass p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticFloatMethodV()\n"); + return 0.f; +} + + +jfloat +JNIEnv_CallStaticFloatMethodA(JNIEnv* p0, jclass p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticFloatMethodA()\n"); + return 0.f; +} + + +jdouble +JNIEnv_CallStaticDoubleMethod(JNIEnv* p0, jclass p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticDoubleMethod()\n"); + return 0.; +} + + +jdouble +JNIEnv_CallStaticDoubleMethodV(JNIEnv* p0, jclass p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticDoubleMethodV()\n"); + return 0.; +} + + +jdouble +JNIEnv_CallStaticDoubleMethodA(JNIEnv* p0, jclass p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticDoubleMethodA()\n"); + return 0.; +} + + +void +JNIEnv_CallStaticVoidMethod(JNIEnv* p0, jclass p1, jmethodID p2, ...) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticVoidMethod()\n"); +} + + +void +JNIEnv_CallStaticVoidMethodV(JNIEnv* p0, jclass p1, jmethodID p2, va_list p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticVoidMethodV()\n"); +} + + +void +JNIEnv_CallStaticVoidMethodA(JNIEnv* p0, jclass p1, jmethodID p2, jvalue* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_CallStaticVoidMethodA()\n"); +} + + +jfieldID +JNIEnv_GetStaticFieldID(JNIEnv* env, jclass p1, const char* p2, const char* p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStaticFieldID(%s, %s)\n", p2, p3); + return (jfieldID)GLOBAL_J(env); +} + + +jobject +JNIEnv_GetStaticObjectField(JNIEnv* p0, jclass p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStaticObjectField()\n"); + return NULL; +} + + +jboolean +JNIEnv_GetStaticBooleanField(JNIEnv* p0, jclass p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStaticBooleanField()\n"); + return 0; +} + + +jbyte +JNIEnv_GetStaticByteField(JNIEnv* p0, jclass p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStaticByteField()\n"); + return 0; +} + + +jchar +JNIEnv_GetStaticCharField(JNIEnv* p0, jclass p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStaticCharField()\n"); + return 0; +} + + +jshort +JNIEnv_GetStaticShortField(JNIEnv* p0, jclass p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStaticShortField()\n"); + return 0; +} + + +jint +JNIEnv_GetStaticIntField(JNIEnv* p0, jclass p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStaticIntField()\n"); + return 0; +} + + +jlong +JNIEnv_GetStaticLongField(JNIEnv* p0, jclass p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStaticLongField()\n"); + return 0; +} + + +jfloat +JNIEnv_GetStaticFloatField(JNIEnv* p0, jclass p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStaticFloatField()\n"); + return 0.f; +} + + +jdouble +JNIEnv_GetStaticDoubleField(JNIEnv* p0, jclass p1, jfieldID p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStaticDoubleField()\n"); + return 0.; +} + + +void +JNIEnv_SetStaticObjectField(JNIEnv* p0, jclass p1, jfieldID p2, jobject p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetStaticObjectField()\n"); +} + + +void +JNIEnv_SetStaticBooleanField(JNIEnv* p0, jclass p1, jfieldID p2, jboolean p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetStaticBooleanField()\n"); +} + + +void +JNIEnv_SetStaticByteField(JNIEnv* p0, jclass p1, jfieldID p2, jbyte p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetStaticByteField()\n"); +} + + +void +JNIEnv_SetStaticCharField(JNIEnv* p0, jclass p1, jfieldID p2, jchar p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetStaticCharField()\n"); +} + + +void +JNIEnv_SetStaticShortField(JNIEnv* p0, jclass p1, jfieldID p2, jshort p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetStaticShortField()\n"); +} + + +void +JNIEnv_SetStaticIntField(JNIEnv* p0, jclass p1, jfieldID p2, jint p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetStaticIntField()\n"); +} + + +void +JNIEnv_SetStaticLongField(JNIEnv* p0, jclass p1, jfieldID p2, jlong p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetStaticLongField()\n"); +} + + +void +JNIEnv_SetStaticFloatField(JNIEnv* p0, jclass p1, jfieldID p2, jfloat p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetStaticFloatField()\n"); +} + + +void +JNIEnv_SetStaticDoubleField(JNIEnv* p0, jclass p1, jfieldID p2, jdouble p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetStaticDoubleField()\n"); +} + + +jstring +JNIEnv_NewString(JNIEnv* p0, const jchar* p1, jsize p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewString(%s, %d)\n", p1, p2); + char *str = malloc(p2+1); + int i; + for (i=0; i %s\n", str); + struct dummy_jstring *result = malloc(sizeof(struct dummy_jstring)); + result->data = str; + return result; +} + + +jsize +JNIEnv_GetStringLength(JNIEnv* p0, jstring p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStringLength()\n"); + return 0; +} + + +const jchar* +JNIEnv_GetStringChars(JNIEnv* p0, jstring p1, jboolean* p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStringChars()\n"); + return NULL; +} + + +void +JNIEnv_ReleaseStringChars(JNIEnv* p0, jstring p1, const jchar* p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ReleaseStringChars()\n"); +} + + +jstring +JNIEnv_NewStringUTF(JNIEnv* p0, const char* p1) +{ + struct dummy_jstring *result = malloc(sizeof(struct dummy_jstring)); + JNIENV_DEBUG_PRINTF("JNIEnv_NewStringUTF('%s') -> %x\n", p1, result); + result->data = strdup(p1); + return result; +} + + +jsize +JNIEnv_GetStringUTFLength(JNIEnv* p0, jstring p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStringUTFLength()\n"); + struct dummy_jstring *result = p1; + return strlen(result->data); +} + + +jsize +JNIEnv_GetArrayLength(JNIEnv* env, jarray p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetArrayLength(%x)\n", p1); + if (p1 != GLOBAL_J(env)) { + struct dummy_byte_array *array = p1; + JNIENV_DEBUG_PRINTF("JNIEnv_GetArrayLength(%x) -> %d\n", p1, array->size); + return array->size; + } + return 0; +} + + +jobjectArray +JNIEnv_NewObjectArray(JNIEnv* p0, jsize p1, jclass p2, jobject p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewObjectArray()\n"); + return NULL; +} + + +jobject +JNIEnv_GetObjectArrayElement(JNIEnv* p0, jobjectArray p1, jsize p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetObjectArrayElement()\n"); + return NULL; +} + + +void +JNIEnv_SetObjectArrayElement(JNIEnv* p0, jobjectArray p1, jsize p2, jobject p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetObjectArrayElement()\n"); +} + + +jbooleanArray +JNIEnv_NewBooleanArray(JNIEnv* p0, jsize p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewBooleanArray()\n"); + return NULL; +} + + +jbyteArray +JNIEnv_NewByteArray(JNIEnv* p0, jsize p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewByteArray()\n"); + return NULL; +} + + +jcharArray +JNIEnv_NewCharArray(JNIEnv* p0, jsize p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewCharArray()\n"); + return NULL; +} + + +jshortArray +JNIEnv_NewShortArray(JNIEnv* p0, jsize p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewShortArray()\n"); + return NULL; +} + + +jintArray +JNIEnv_NewIntArray(JNIEnv* p0, jsize p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewIntArray()\n"); + return NULL; +} + + +jlongArray +JNIEnv_NewLongArray(JNIEnv* p0, jsize p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewLongArray()\n"); + return NULL; +} + + +jfloatArray +JNIEnv_NewFloatArray(JNIEnv* p0, jsize p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewFloatArray()\n"); + return NULL; +} + + +jdoubleArray +JNIEnv_NewDoubleArray(JNIEnv* p0, jsize p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewDoubleArray()\n"); + return NULL; +} + + +jboolean* +JNIEnv_GetBooleanArrayElements(JNIEnv* p0, jbooleanArray p1, jboolean* p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetBooleanArrayElements()\n"); + return NULL; +} + + +jbyte* +JNIEnv_GetByteArrayElements(JNIEnv* p0, jbyteArray p1, jboolean* p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetByteArrayElements(%x)\n", p1); + return p1; +} + + +jchar* +JNIEnv_GetCharArrayElements(JNIEnv* p0, jcharArray p1, jboolean* p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetCharArrayElements()\n"); + return NULL; +} + + +jshort* +JNIEnv_GetShortArrayElements(JNIEnv* p0, jshortArray p1, jboolean* p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetShortArrayElements()\n"); + return NULL; +} + + +jint* +JNIEnv_GetIntArrayElements(JNIEnv* p0, jintArray p1, jboolean* p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetIntArrayElements()\n"); + return NULL; +} + + +jlong* +JNIEnv_GetLongArrayElements(JNIEnv* p0, jlongArray p1, jboolean* p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetLongArrayElements()\n"); + return NULL; +} + + +jfloat* +JNIEnv_GetFloatArrayElements(JNIEnv* p0, jfloatArray p1, jboolean* p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetFloatArrayElements()\n"); + return NULL; +} + + +jdouble* +JNIEnv_GetDoubleArrayElements(JNIEnv* p0, jdoubleArray p1, jboolean* p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetDoubleArrayElements()\n"); + return NULL; +} + + +void +JNIEnv_ReleaseBooleanArrayElements(JNIEnv* p0, jbooleanArray p1, jboolean* p2, jint p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ReleaseBooleanArrayElements()\n"); +} + + +void +JNIEnv_ReleaseByteArrayElements(JNIEnv* p0, jbyteArray p1, jbyte* p2, jint p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ReleaseByteArrayElements()\n"); +} + + +void +JNIEnv_ReleaseCharArrayElements(JNIEnv* p0, jcharArray p1, jchar* p2, jint p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ReleaseCharArrayElements()\n"); +} + + +void +JNIEnv_ReleaseShortArrayElements(JNIEnv* p0, jshortArray p1, jshort* p2, jint p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ReleaseShortArrayElements()\n"); +} + + +void +JNIEnv_ReleaseIntArrayElements(JNIEnv* p0, jintArray p1, jint* p2, jint p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ReleaseIntArrayElements()\n"); +} + + +void +JNIEnv_ReleaseLongArrayElements(JNIEnv* p0, jlongArray p1, jlong* p2, jint p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ReleaseLongArrayElements()\n"); +} + + +void +JNIEnv_ReleaseFloatArrayElements(JNIEnv* p0, jfloatArray p1, jfloat* p2, jint p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ReleaseFloatArrayElements()\n"); +} + + +void +JNIEnv_ReleaseDoubleArrayElements(JNIEnv* p0, jdoubleArray p1, jdouble* p2, jint p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ReleaseDoubleArrayElements()\n"); +} + + +void +JNIEnv_GetBooleanArrayRegion(JNIEnv* p0, jbooleanArray p1, jsize p2, jsize p3, jboolean* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetBooleanArrayRegion()\n"); +} + + +void +JNIEnv_GetByteArrayRegion(JNIEnv *env, jbyteArray arrayobj, jsize start, jsize len, jbyte* buf) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetByteArrayRegion(%x, %d, %d, %x)\n", arrayobj, start, len, buf); + if (arrayobj != GLOBAL_J(env)) { + struct dummy_byte_array *array = arrayobj; + memcpy(buf, array->data+start, len); + } +} + + +void +JNIEnv_GetCharArrayRegion(JNIEnv* p0, jcharArray p1, jsize p2, jsize p3, jchar* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetCharArrayRegion()\n"); +} + + +void +JNIEnv_GetShortArrayRegion(JNIEnv* p0, jshortArray p1, jsize p2, jsize p3, jshort* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetShortArrayRegion()\n"); +} + + +void +JNIEnv_GetIntArrayRegion(JNIEnv* p0, jintArray p1, jsize p2, jsize p3, jint* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetIntArrayRegion()\n"); +} + + +void +JNIEnv_GetLongArrayRegion(JNIEnv* p0, jlongArray p1, jsize p2, jsize p3, jlong* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetLongArrayRegion()\n"); +} + + +void +JNIEnv_GetFloatArrayRegion(JNIEnv* p0, jfloatArray p1, jsize p2, jsize p3, jfloat* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetFloatArrayRegion(%x, %d, %d, %x)\n", p1, p2, p3, p4); +} + + +void +JNIEnv_GetDoubleArrayRegion(JNIEnv* p0, jdoubleArray p1, jsize p2, jsize p3, jdouble* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetDoubleArrayRegion()\n"); +} + + +void +JNIEnv_SetBooleanArrayRegion(JNIEnv* p0, jbooleanArray p1, jsize p2, jsize p3, const jboolean* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetBooleanArrayRegion()\n"); +} + + +void +JNIEnv_SetByteArrayRegion(JNIEnv* p0, jbyteArray p1, jsize p2, jsize p3, const jbyte* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetByteArrayRegion()\n"); +} + + +void +JNIEnv_SetCharArrayRegion(JNIEnv* p0, jcharArray p1, jsize p2, jsize p3, const jchar* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetCharArrayRegion()\n"); +} + + +void +JNIEnv_SetShortArrayRegion(JNIEnv* p0, jshortArray p1, jsize p2, jsize p3, const jshort* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetShortArrayRegion()\n"); +} + + +void +JNIEnv_SetIntArrayRegion(JNIEnv* p0, jintArray p1, jsize p2, jsize p3, const jint* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetIntArrayRegion()\n"); +} + + +void +JNIEnv_SetLongArrayRegion(JNIEnv* p0, jlongArray p1, jsize p2, jsize p3, const jlong* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetLongArrayRegion()\n"); +} + + +void +JNIEnv_SetFloatArrayRegion(JNIEnv* p0, jfloatArray p1, jsize p2, jsize p3, const jfloat* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetFloatArrayRegion()\n"); +} + + +void +JNIEnv_SetDoubleArrayRegion(JNIEnv* p0, jdoubleArray p1, jsize p2, jsize p3, const jdouble* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_SetDoubleArrayRegion()\n"); +} + + +jint +JNIEnv_RegisterNatives(JNIEnv* p0, jclass p1, const JNINativeMethod* p2, jint p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_RegisterNatives()\n"); + + struct dummy_jclass *clazz = (struct dummy_jclass*)p1; + JNIENV_DEBUG_PRINTF("\n\tClass: %s\n", clazz->name); + + int i=0; + const JNINativeMethod *method = p2; + while (iname, method->signature, method->fnPtr); + method++; + i++; + } + JNIENV_DEBUG_PRINTF("\n"); + return 0; +} + + +jint +JNIEnv_UnregisterNatives(JNIEnv* p0, jclass p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_UnregisterNatives()\n"); + return 0; +} + + +jint +JNIEnv_MonitorEnter(JNIEnv* p0, jobject p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_MonitorEnter()\n"); + return 0; +} + + +jint +JNIEnv_MonitorExit(JNIEnv* p0, jobject p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_MonitorExit()\n"); + return 0; +} + + +jint +JNIEnv_GetJavaVM(JNIEnv* env, JavaVM** vm) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetJavaVM()\n"); + struct GlobalState *global = GLOBAL_J(env); + *vm = VM(global); + return 0; +} + + +void +JNIEnv_GetStringRegion(JNIEnv* p0, jstring p1, jsize p2, jsize p3, jchar* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStringRegion()\n"); +} + + +void +JNIEnv_GetStringUTFRegion(JNIEnv* p0, jstring p1, jsize p2, jsize p3, char* p4) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStringUTFRegion()\n"); +} + + +void* +JNIEnv_GetPrimitiveArrayCritical(JNIEnv* p0, jarray p1, jboolean* p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetPrimitiveArrayCritical()\n"); + return NULL; +} + + +void +JNIEnv_ReleasePrimitiveArrayCritical(JNIEnv* p0, jarray p1, void* p2, jint p3) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ReleasePrimitiveArrayCritical()\n"); +} + + +const jchar* +JNIEnv_GetStringCritical(JNIEnv* p0, jstring p1, jboolean* p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStringCritical()\n"); + return NULL; +} + + +void +JNIEnv_ReleaseStringCritical(JNIEnv* p0, jstring p1, const jchar* p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ReleaseStringCritical()\n"); +} + + +jweak +JNIEnv_NewWeakGlobalRef(JNIEnv* p0, jobject p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewWeakGlobalRef()\n"); + return NULL; +} + + +void +JNIEnv_DeleteWeakGlobalRef(JNIEnv* p0, jweak p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_DeleteWeakGlobalRef()\n"); +} + + +jboolean +JNIEnv_ExceptionCheck(JNIEnv* p0) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ExceptionCheck()\n"); + return 0; +} + + +jobject +JNIEnv_NewDirectByteBuffer(JNIEnv* p0, void* p1, jlong p2) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_NewDirectByteBuffer()\n"); + return NULL; +} + + +void* +JNIEnv_GetDirectBufferAddress(JNIEnv* p0, jobject p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetDirectBufferAddress()\n"); + return NULL; +} + + +jlong +JNIEnv_GetDirectBufferCapacity(JNIEnv* p0, jobject p1) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetDirectBufferCapacity()\n"); + return 0; +} + +const char * +JNIEnv_GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_GetStringUTFChars(%x)\n", string); + if (string == GLOBAL_J(env)) { + JNIENV_DEBUG_PRINTF("WARNING: GetStringUTFChars on global\n"); + return NULL; + } + if (string == NULL) { + return strdup(""); + } + struct dummy_jstring *str = (struct dummy_jstring*)string; + JNIENV_DEBUG_PRINTF(" \\-> %s\n", str->data); + return str->data; +} + +void +JNIEnv_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf) +{ + JNIENV_DEBUG_PRINTF("JNIEnv_ReleaseStringUTFChars()\n"); + if (string == GLOBAL_J(env)) { + JNIENV_DEBUG_PRINTF("WARNING: ReleaseStringUTFChars on global\n"); + return; + } + free((void*)utf); +} + +void +jnienv_init(struct GlobalState *global) +{ + global->fake_env.reserved0 = global; + global->fake_env.GetStringUTFChars = JNIEnv_GetStringUTFChars; + global->fake_env.ReleaseStringUTFChars = JNIEnv_ReleaseStringUTFChars; + global->fake_env.GetVersion = JNIEnv_GetVersion; + global->fake_env.DefineClass = JNIEnv_DefineClass; + global->fake_env.FindClass = JNIEnv_FindClass; + global->fake_env.FromReflectedMethod = JNIEnv_FromReflectedMethod; + global->fake_env.FromReflectedField = JNIEnv_FromReflectedField; + global->fake_env.ToReflectedMethod = JNIEnv_ToReflectedMethod; + global->fake_env.GetSuperclass = JNIEnv_GetSuperclass; + global->fake_env.IsAssignableFrom = JNIEnv_IsAssignableFrom; + global->fake_env.ToReflectedField = JNIEnv_ToReflectedField; + global->fake_env.Throw = JNIEnv_Throw; + global->fake_env.ThrowNew = JNIEnv_ThrowNew; + global->fake_env.ExceptionOccurred = JNIEnv_ExceptionOccurred; + global->fake_env.ExceptionDescribe = JNIEnv_ExceptionDescribe; + global->fake_env.ExceptionClear = JNIEnv_ExceptionClear; + global->fake_env.FatalError = JNIEnv_FatalError; + global->fake_env.PushLocalFrame = JNIEnv_PushLocalFrame; + global->fake_env.PopLocalFrame = JNIEnv_PopLocalFrame; + global->fake_env.NewGlobalRef = JNIEnv_NewGlobalRef; + global->fake_env.DeleteGlobalRef = JNIEnv_DeleteGlobalRef; + global->fake_env.DeleteLocalRef = JNIEnv_DeleteLocalRef; + global->fake_env.IsSameObject = JNIEnv_IsSameObject; + global->fake_env.NewLocalRef = JNIEnv_NewLocalRef; + global->fake_env.EnsureLocalCapacity = JNIEnv_EnsureLocalCapacity; + global->fake_env.AllocObject = JNIEnv_AllocObject; + global->fake_env.NewObject = JNIEnv_NewObject; + global->fake_env.NewObjectV = JNIEnv_NewObjectV; + global->fake_env.NewObjectA = JNIEnv_NewObjectA; + global->fake_env.GetObjectClass = JNIEnv_GetObjectClass; + global->fake_env.IsInstanceOf = JNIEnv_IsInstanceOf; + global->fake_env.GetMethodID = JNIEnv_GetMethodID; + global->fake_env.CallObjectMethod = JNIEnv_CallObjectMethod; + global->fake_env.CallObjectMethodV = JNIEnv_CallObjectMethodV; + global->fake_env.CallObjectMethodA = JNIEnv_CallObjectMethodA; + global->fake_env.CallBooleanMethod = JNIEnv_CallBooleanMethod; + global->fake_env.CallBooleanMethodV = JNIEnv_CallBooleanMethodV; + global->fake_env.CallBooleanMethodA = JNIEnv_CallBooleanMethodA; + global->fake_env.CallByteMethod = JNIEnv_CallByteMethod; + global->fake_env.CallByteMethodV = JNIEnv_CallByteMethodV; + global->fake_env.CallByteMethodA = JNIEnv_CallByteMethodA; + global->fake_env.CallCharMethod = JNIEnv_CallCharMethod; + global->fake_env.CallCharMethodV = JNIEnv_CallCharMethodV; + global->fake_env.CallCharMethodA = JNIEnv_CallCharMethodA; + global->fake_env.CallShortMethod = JNIEnv_CallShortMethod; + global->fake_env.CallShortMethodV = JNIEnv_CallShortMethodV; + global->fake_env.CallShortMethodA = JNIEnv_CallShortMethodA; + global->fake_env.CallIntMethod = JNIEnv_CallIntMethod; + global->fake_env.CallIntMethodV = JNIEnv_CallIntMethodV; + global->fake_env.CallIntMethodA = JNIEnv_CallIntMethodA; + global->fake_env.CallLongMethod = JNIEnv_CallLongMethod; + global->fake_env.CallLongMethodV = JNIEnv_CallLongMethodV; + global->fake_env.CallLongMethodA = JNIEnv_CallLongMethodA; + global->fake_env.CallFloatMethod = JNIEnv_CallFloatMethod; + global->fake_env.CallFloatMethodV = JNIEnv_CallFloatMethodV; + global->fake_env.CallFloatMethodA = JNIEnv_CallFloatMethodA; + global->fake_env.CallDoubleMethod = JNIEnv_CallDoubleMethod; + global->fake_env.CallDoubleMethodV = JNIEnv_CallDoubleMethodV; + global->fake_env.CallDoubleMethodA = JNIEnv_CallDoubleMethodA; + global->fake_env.CallVoidMethod = JNIEnv_CallVoidMethod; + global->fake_env.CallVoidMethodV = JNIEnv_CallVoidMethodV; + global->fake_env.CallVoidMethodA = JNIEnv_CallVoidMethodA; + global->fake_env.CallNonvirtualObjectMethod = JNIEnv_CallNonvirtualObjectMethod; + global->fake_env.CallNonvirtualObjectMethodV = JNIEnv_CallNonvirtualObjectMethodV; + global->fake_env.CallNonvirtualObjectMethodA = JNIEnv_CallNonvirtualObjectMethodA; + global->fake_env.CallNonvirtualBooleanMethod = JNIEnv_CallNonvirtualBooleanMethod; + global->fake_env.CallNonvirtualBooleanMethodV = JNIEnv_CallNonvirtualBooleanMethodV; + global->fake_env.CallNonvirtualBooleanMethodA = JNIEnv_CallNonvirtualBooleanMethodA; + global->fake_env.CallNonvirtualByteMethod = JNIEnv_CallNonvirtualByteMethod; + global->fake_env.CallNonvirtualByteMethodV = JNIEnv_CallNonvirtualByteMethodV; + global->fake_env.CallNonvirtualByteMethodA = JNIEnv_CallNonvirtualByteMethodA; + global->fake_env.CallNonvirtualCharMethod = JNIEnv_CallNonvirtualCharMethod; + global->fake_env.CallNonvirtualCharMethodV = JNIEnv_CallNonvirtualCharMethodV; + global->fake_env.CallNonvirtualCharMethodA = JNIEnv_CallNonvirtualCharMethodA; + global->fake_env.CallNonvirtualShortMethod = JNIEnv_CallNonvirtualShortMethod; + global->fake_env.CallNonvirtualShortMethodV = JNIEnv_CallNonvirtualShortMethodV; + global->fake_env.CallNonvirtualShortMethodA = JNIEnv_CallNonvirtualShortMethodA; + global->fake_env.CallNonvirtualIntMethod = JNIEnv_CallNonvirtualIntMethod; + global->fake_env.CallNonvirtualIntMethodV = JNIEnv_CallNonvirtualIntMethodV; + global->fake_env.CallNonvirtualIntMethodA = JNIEnv_CallNonvirtualIntMethodA; + global->fake_env.CallNonvirtualLongMethod = JNIEnv_CallNonvirtualLongMethod; + global->fake_env.CallNonvirtualLongMethodV = JNIEnv_CallNonvirtualLongMethodV; + global->fake_env.CallNonvirtualLongMethodA = JNIEnv_CallNonvirtualLongMethodA; + global->fake_env.CallNonvirtualFloatMethod = JNIEnv_CallNonvirtualFloatMethod; + global->fake_env.CallNonvirtualFloatMethodV = JNIEnv_CallNonvirtualFloatMethodV; + global->fake_env.CallNonvirtualFloatMethodA = JNIEnv_CallNonvirtualFloatMethodA; + global->fake_env.CallNonvirtualDoubleMethod = JNIEnv_CallNonvirtualDoubleMethod; + global->fake_env.CallNonvirtualDoubleMethodV = JNIEnv_CallNonvirtualDoubleMethodV; + global->fake_env.CallNonvirtualDoubleMethodA = JNIEnv_CallNonvirtualDoubleMethodA; + global->fake_env.CallNonvirtualVoidMethod = JNIEnv_CallNonvirtualVoidMethod; + global->fake_env.CallNonvirtualVoidMethodV = JNIEnv_CallNonvirtualVoidMethodV; + global->fake_env.CallNonvirtualVoidMethodA = JNIEnv_CallNonvirtualVoidMethodA; + global->fake_env.GetFieldID = JNIEnv_GetFieldID; + global->fake_env.GetObjectField = JNIEnv_GetObjectField; + global->fake_env.GetBooleanField = JNIEnv_GetBooleanField; + global->fake_env.GetByteField = JNIEnv_GetByteField; + global->fake_env.GetCharField = JNIEnv_GetCharField; + global->fake_env.GetShortField = JNIEnv_GetShortField; + global->fake_env.GetIntField = JNIEnv_GetIntField; + global->fake_env.GetLongField = JNIEnv_GetLongField; + global->fake_env.GetFloatField = JNIEnv_GetFloatField; + global->fake_env.GetDoubleField = JNIEnv_GetDoubleField; + global->fake_env.SetObjectField = JNIEnv_SetObjectField; + global->fake_env.SetBooleanField = JNIEnv_SetBooleanField; + global->fake_env.SetByteField = JNIEnv_SetByteField; + global->fake_env.SetCharField = JNIEnv_SetCharField; + global->fake_env.SetShortField = JNIEnv_SetShortField; + global->fake_env.SetIntField = JNIEnv_SetIntField; + global->fake_env.SetLongField = JNIEnv_SetLongField; + global->fake_env.SetFloatField = JNIEnv_SetFloatField; + global->fake_env.SetDoubleField = JNIEnv_SetDoubleField; + global->fake_env.GetStaticMethodID = JNIEnv_GetStaticMethodID; + global->fake_env.CallStaticObjectMethod = JNIEnv_CallStaticObjectMethod; + global->fake_env.CallStaticObjectMethodV = JNIEnv_CallStaticObjectMethodV; + global->fake_env.CallStaticObjectMethodA = JNIEnv_CallStaticObjectMethodA; + global->fake_env.CallStaticBooleanMethod = JNIEnv_CallStaticBooleanMethod; + global->fake_env.CallStaticBooleanMethodV = JNIEnv_CallStaticBooleanMethodV; + global->fake_env.CallStaticBooleanMethodA = JNIEnv_CallStaticBooleanMethodA; + global->fake_env.CallStaticByteMethod = JNIEnv_CallStaticByteMethod; + global->fake_env.CallStaticByteMethodV = JNIEnv_CallStaticByteMethodV; + global->fake_env.CallStaticByteMethodA = JNIEnv_CallStaticByteMethodA; + global->fake_env.CallStaticCharMethod = JNIEnv_CallStaticCharMethod; + global->fake_env.CallStaticCharMethodV = JNIEnv_CallStaticCharMethodV; + global->fake_env.CallStaticCharMethodA = JNIEnv_CallStaticCharMethodA; + global->fake_env.CallStaticShortMethod = JNIEnv_CallStaticShortMethod; + global->fake_env.CallStaticShortMethodV = JNIEnv_CallStaticShortMethodV; + global->fake_env.CallStaticShortMethodA = JNIEnv_CallStaticShortMethodA; + global->fake_env.CallStaticIntMethod = JNIEnv_CallStaticIntMethod; + global->fake_env.CallStaticIntMethodV = JNIEnv_CallStaticIntMethodV; + global->fake_env.CallStaticIntMethodA = JNIEnv_CallStaticIntMethodA; + global->fake_env.CallStaticLongMethod = JNIEnv_CallStaticLongMethod; + global->fake_env.CallStaticLongMethodV = JNIEnv_CallStaticLongMethodV; + global->fake_env.CallStaticLongMethodA = JNIEnv_CallStaticLongMethodA; + global->fake_env.CallStaticFloatMethod = JNIEnv_CallStaticFloatMethod; + global->fake_env.CallStaticFloatMethodV = JNIEnv_CallStaticFloatMethodV; + global->fake_env.CallStaticFloatMethodA = JNIEnv_CallStaticFloatMethodA; + global->fake_env.CallStaticDoubleMethod = JNIEnv_CallStaticDoubleMethod; + global->fake_env.CallStaticDoubleMethodV = JNIEnv_CallStaticDoubleMethodV; + global->fake_env.CallStaticDoubleMethodA = JNIEnv_CallStaticDoubleMethodA; + global->fake_env.CallStaticVoidMethod = JNIEnv_CallStaticVoidMethod; + global->fake_env.CallStaticVoidMethodV = JNIEnv_CallStaticVoidMethodV; + global->fake_env.CallStaticVoidMethodA = JNIEnv_CallStaticVoidMethodA; + global->fake_env.GetStaticFieldID = JNIEnv_GetStaticFieldID; + global->fake_env.GetStaticObjectField = JNIEnv_GetStaticObjectField; + global->fake_env.GetStaticBooleanField = JNIEnv_GetStaticBooleanField; + global->fake_env.GetStaticByteField = JNIEnv_GetStaticByteField; + global->fake_env.GetStaticCharField = JNIEnv_GetStaticCharField; + global->fake_env.GetStaticShortField = JNIEnv_GetStaticShortField; + global->fake_env.GetStaticIntField = JNIEnv_GetStaticIntField; + global->fake_env.GetStaticLongField = JNIEnv_GetStaticLongField; + global->fake_env.GetStaticFloatField = JNIEnv_GetStaticFloatField; + global->fake_env.GetStaticDoubleField = JNIEnv_GetStaticDoubleField; + global->fake_env.SetStaticObjectField = JNIEnv_SetStaticObjectField; + global->fake_env.SetStaticBooleanField = JNIEnv_SetStaticBooleanField; + global->fake_env.SetStaticByteField = JNIEnv_SetStaticByteField; + global->fake_env.SetStaticCharField = JNIEnv_SetStaticCharField; + global->fake_env.SetStaticShortField = JNIEnv_SetStaticShortField; + global->fake_env.SetStaticIntField = JNIEnv_SetStaticIntField; + global->fake_env.SetStaticLongField = JNIEnv_SetStaticLongField; + global->fake_env.SetStaticFloatField = JNIEnv_SetStaticFloatField; + global->fake_env.SetStaticDoubleField = JNIEnv_SetStaticDoubleField; + global->fake_env.NewString = JNIEnv_NewString; + global->fake_env.GetStringLength = JNIEnv_GetStringLength; + global->fake_env.GetStringChars = JNIEnv_GetStringChars; + global->fake_env.ReleaseStringChars = JNIEnv_ReleaseStringChars; + global->fake_env.NewStringUTF = JNIEnv_NewStringUTF; + global->fake_env.GetStringUTFLength = JNIEnv_GetStringUTFLength; + global->fake_env.GetArrayLength = JNIEnv_GetArrayLength; + global->fake_env.NewObjectArray = JNIEnv_NewObjectArray; + global->fake_env.GetObjectArrayElement = JNIEnv_GetObjectArrayElement; + global->fake_env.SetObjectArrayElement = JNIEnv_SetObjectArrayElement; + global->fake_env.NewBooleanArray = JNIEnv_NewBooleanArray; + global->fake_env.NewByteArray = JNIEnv_NewByteArray; + global->fake_env.NewCharArray = JNIEnv_NewCharArray; + global->fake_env.NewShortArray = JNIEnv_NewShortArray; + global->fake_env.NewIntArray = JNIEnv_NewIntArray; + global->fake_env.NewLongArray = JNIEnv_NewLongArray; + global->fake_env.NewFloatArray = JNIEnv_NewFloatArray; + global->fake_env.NewDoubleArray = JNIEnv_NewDoubleArray; + global->fake_env.GetBooleanArrayElements = JNIEnv_GetBooleanArrayElements; + global->fake_env.GetByteArrayElements = JNIEnv_GetByteArrayElements; + global->fake_env.GetCharArrayElements = JNIEnv_GetCharArrayElements; + global->fake_env.GetShortArrayElements = JNIEnv_GetShortArrayElements; + global->fake_env.GetIntArrayElements = JNIEnv_GetIntArrayElements; + global->fake_env.GetLongArrayElements = JNIEnv_GetLongArrayElements; + global->fake_env.GetFloatArrayElements = JNIEnv_GetFloatArrayElements; + global->fake_env.GetDoubleArrayElements = JNIEnv_GetDoubleArrayElements; + global->fake_env.ReleaseBooleanArrayElements = JNIEnv_ReleaseBooleanArrayElements; + global->fake_env.ReleaseByteArrayElements = JNIEnv_ReleaseByteArrayElements; + global->fake_env.ReleaseCharArrayElements = JNIEnv_ReleaseCharArrayElements; + global->fake_env.ReleaseShortArrayElements = JNIEnv_ReleaseShortArrayElements; + global->fake_env.ReleaseIntArrayElements = JNIEnv_ReleaseIntArrayElements; + global->fake_env.ReleaseLongArrayElements = JNIEnv_ReleaseLongArrayElements; + global->fake_env.ReleaseFloatArrayElements = JNIEnv_ReleaseFloatArrayElements; + global->fake_env.ReleaseDoubleArrayElements = JNIEnv_ReleaseDoubleArrayElements; + global->fake_env.GetBooleanArrayRegion = JNIEnv_GetBooleanArrayRegion; + global->fake_env.GetByteArrayRegion = JNIEnv_GetByteArrayRegion; + global->fake_env.GetCharArrayRegion = JNIEnv_GetCharArrayRegion; + global->fake_env.GetShortArrayRegion = JNIEnv_GetShortArrayRegion; + global->fake_env.GetIntArrayRegion = JNIEnv_GetIntArrayRegion; + global->fake_env.GetLongArrayRegion = JNIEnv_GetLongArrayRegion; + global->fake_env.GetFloatArrayRegion = JNIEnv_GetFloatArrayRegion; + global->fake_env.GetDoubleArrayRegion = JNIEnv_GetDoubleArrayRegion; + global->fake_env.SetBooleanArrayRegion = JNIEnv_SetBooleanArrayRegion; + global->fake_env.SetByteArrayRegion = JNIEnv_SetByteArrayRegion; + global->fake_env.SetCharArrayRegion = JNIEnv_SetCharArrayRegion; + global->fake_env.SetShortArrayRegion = JNIEnv_SetShortArrayRegion; + global->fake_env.SetIntArrayRegion = JNIEnv_SetIntArrayRegion; + global->fake_env.SetLongArrayRegion = JNIEnv_SetLongArrayRegion; + global->fake_env.SetFloatArrayRegion = JNIEnv_SetFloatArrayRegion; + global->fake_env.SetDoubleArrayRegion = JNIEnv_SetDoubleArrayRegion; + global->fake_env.RegisterNatives = JNIEnv_RegisterNatives; + global->fake_env.UnregisterNatives = JNIEnv_UnregisterNatives; + global->fake_env.MonitorEnter = JNIEnv_MonitorEnter; + global->fake_env.MonitorExit = JNIEnv_MonitorExit; + global->fake_env.GetJavaVM = JNIEnv_GetJavaVM; + global->fake_env.GetStringRegion = JNIEnv_GetStringRegion; + global->fake_env.GetStringUTFRegion = JNIEnv_GetStringUTFRegion; + global->fake_env.GetPrimitiveArrayCritical = JNIEnv_GetPrimitiveArrayCritical; + global->fake_env.ReleasePrimitiveArrayCritical = JNIEnv_ReleasePrimitiveArrayCritical; + global->fake_env.GetStringCritical = JNIEnv_GetStringCritical; + global->fake_env.ReleaseStringCritical = JNIEnv_ReleaseStringCritical; + global->fake_env.NewWeakGlobalRef = JNIEnv_NewWeakGlobalRef; + global->fake_env.DeleteWeakGlobalRef = JNIEnv_DeleteWeakGlobalRef; + global->fake_env.ExceptionCheck = JNIEnv_ExceptionCheck; + global->fake_env.NewDirectByteBuffer = JNIEnv_NewDirectByteBuffer; + global->fake_env.GetDirectBufferAddress = JNIEnv_GetDirectBufferAddress; + global->fake_env.GetDirectBufferCapacity = JNIEnv_GetDirectBufferCapacity; + global->env = &(global->fake_env); +} + +jint +JavaVM_DestroyJavaVM(JavaVM *vm) +{ + JNIENV_DEBUG_PRINTF("JavaVM_DestroyJavaVM()\n"); + return 0; +} + +jint +JavaVM_AttachCurrentThread(JavaVM *vm, JNIEnv **env, void *args) +{ + JNIENV_DEBUG_PRINTF("JavaVM_AttachCurrentThread()\n"); + struct GlobalState *global = (*vm)->reserved0; + *env = ENV(global); + return 0; +} + +jint +JavaVM_DetachCurrentThread(JavaVM *vm) +{ + JNIENV_DEBUG_PRINTF("JavaVM_DetachCurrentThread()\n"); + return 0; +} + +jint +JavaVM_GetEnv(JavaVM *vm, void **env, jint version) +{ + JNIENV_DEBUG_PRINTF("JavaVM_GetEnv(%x, %d)\n", env, version); + struct GlobalState *global = (*vm)->reserved0; + *env = ENV(global); + return 0; +} + +jint +JavaVM_AttachCurrentThreadAsDaemon(JavaVM *vm, JNIEnv **env, void *args) +{ + JNIENV_DEBUG_PRINTF("JavaVM_AttachCurrentThreadAsDaemon()\n"); + struct GlobalState *global = (*vm)->reserved0; + *env = ENV(global); + return 0; +} + +void +javavm_init(struct GlobalState *global) +{ + global->fake_vm.reserved0 = global; + global->fake_vm.DestroyJavaVM = JavaVM_DestroyJavaVM; + global->fake_vm.AttachCurrentThread = JavaVM_AttachCurrentThread; + global->fake_vm.DetachCurrentThread = JavaVM_DetachCurrentThread; + global->fake_vm.GetEnv = JavaVM_GetEnv; + global->fake_vm.AttachCurrentThreadAsDaemon = JavaVM_AttachCurrentThreadAsDaemon; + global->vm = &(global->fake_vm); +} + + diff --git a/jni/jnienv.h b/jni/jnienv.h new file mode 100644 index 0000000..96dbc92 --- /dev/null +++ b/jni/jnienv.h @@ -0,0 +1,297 @@ +#ifndef JNIENV_H +#define JNIENV_H + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + +#include "../apkenv.h" + +#include "jni.h" + +#define GLOBAL_J(env) ((struct GlobalState*)((*env)->reserved0)) + +struct dummy_jstring { + char *data; +}; + +struct dummy_byte_array { + char *data; + long size; +}; + +struct dummy_jclass { + char *name; +}; + +struct _jmethodID { + jclass clazz; + char *name; + char *sig; +}; + +jint JNIEnv_GetVersion(JNIEnv *p0) SOFTFP; +jclass JNIEnv_DefineClass(JNIEnv *p0, const char *p1, jobject p2, const jbyte *p3, jsize p4) SOFTFP; +jclass JNIEnv_FindClass(JNIEnv *p0, const char *p1) SOFTFP; +jmethodID JNIEnv_FromReflectedMethod(JNIEnv *p0, jobject p1) SOFTFP; +jfieldID JNIEnv_FromReflectedField(JNIEnv *p0, jobject p1) SOFTFP; +jobject JNIEnv_ToReflectedMethod(JNIEnv *p0, jclass p1, jmethodID p2, jboolean p3) SOFTFP; +jclass JNIEnv_GetSuperclass(JNIEnv *p0, jclass p1) SOFTFP; +jboolean JNIEnv_IsAssignableFrom(JNIEnv *p0, jclass p1, jclass p2) SOFTFP; +jobject JNIEnv_ToReflectedField(JNIEnv *p0, jclass p1, jfieldID p2, jboolean p3) SOFTFP; +jint JNIEnv_Throw(JNIEnv *p0, jthrowable p1) SOFTFP; +jint JNIEnv_ThrowNew(JNIEnv *p0, jclass p1, const char *p2) SOFTFP; +jthrowable JNIEnv_ExceptionOccurred(JNIEnv *p0) SOFTFP; +void JNIEnv_ExceptionDescribe(JNIEnv *p0) SOFTFP; +void JNIEnv_ExceptionClear(JNIEnv *p0) SOFTFP; +void JNIEnv_FatalError(JNIEnv *p0, const char *p1) SOFTFP; +jint JNIEnv_PushLocalFrame(JNIEnv *p0, jint p1) SOFTFP; +jobject JNIEnv_PopLocalFrame(JNIEnv *p0, jobject p1) SOFTFP; +jobject JNIEnv_NewGlobalRef(JNIEnv *p0, jobject p1) SOFTFP; +void JNIEnv_DeleteGlobalRef(JNIEnv *p0, jobject p1) SOFTFP; +void JNIEnv_DeleteLocalRef(JNIEnv *p0, jobject p1) SOFTFP; +jboolean JNIEnv_IsSameObject(JNIEnv *p0, jobject p1, jobject p2) SOFTFP; +jobject JNIEnv_NewLocalRef(JNIEnv *p0, jobject p1) SOFTFP; +jint JNIEnv_EnsureLocalCapacity(JNIEnv *p0, jint p1) SOFTFP; +jobject JNIEnv_AllocObject(JNIEnv *p0, jclass p1) SOFTFP; +jobject JNIEnv_NewObject(JNIEnv *p0, jclass p1, jmethodID p2, ...) SOFTFP; +jobject JNIEnv_NewObjectV(JNIEnv *p0, jclass p1, jmethodID p2, va_list p3) SOFTFP; +jobject JNIEnv_NewObjectA(JNIEnv *p0, jclass p1, jmethodID p2, jvalue *p3) SOFTFP; +jclass JNIEnv_GetObjectClass(JNIEnv *p0, jobject p1) SOFTFP; +jboolean JNIEnv_IsInstanceOf(JNIEnv *p0, jobject p1, jclass p2) SOFTFP; +jmethodID JNIEnv_GetMethodID(JNIEnv *p0, jclass clazz, const char *name, const char *sig) SOFTFP; +jobject JNIEnv_CallObjectMethod(JNIEnv *p0, jobject p1, jmethodID p2, ...) SOFTFP; +jobject JNIEnv_CallObjectMethodV(JNIEnv *p0, jobject p1, jmethodID p2, va_list p3) SOFTFP; +jobject JNIEnv_CallObjectMethodA(JNIEnv *p0, jobject p1, jmethodID p2, jvalue *p3) SOFTFP; +jboolean JNIEnv_CallBooleanMethod(JNIEnv *p0, jobject p1, jmethodID p2, ...) SOFTFP; +jboolean JNIEnv_CallBooleanMethodV(JNIEnv *p0, jobject p1, jmethodID p2, va_list p3) SOFTFP; +jboolean JNIEnv_CallBooleanMethodA(JNIEnv *p0, jobject p1, jmethodID p2, jvalue *p3) SOFTFP; +jbyte JNIEnv_CallByteMethod(JNIEnv *p0, jobject p1, jmethodID p2, ...) SOFTFP; +jbyte JNIEnv_CallByteMethodV(JNIEnv *p0, jobject p1, jmethodID p2, va_list p3) SOFTFP; +jbyte JNIEnv_CallByteMethodA(JNIEnv *p0, jobject p1, jmethodID p2, jvalue *p3) SOFTFP; +jchar JNIEnv_CallCharMethod(JNIEnv *p0, jobject p1, jmethodID p2, ...) SOFTFP; +jchar JNIEnv_CallCharMethodV(JNIEnv *p0, jobject p1, jmethodID p2, va_list p3) SOFTFP; +jchar JNIEnv_CallCharMethodA(JNIEnv *p0, jobject p1, jmethodID p2, jvalue *p3) SOFTFP; +jshort JNIEnv_CallShortMethod(JNIEnv *p0, jobject p1, jmethodID p2, ...) SOFTFP; +jshort JNIEnv_CallShortMethodV(JNIEnv *p0, jobject p1, jmethodID p2, va_list p3) SOFTFP; +jshort JNIEnv_CallShortMethodA(JNIEnv *p0, jobject p1, jmethodID p2, jvalue *p3) SOFTFP; +jint JNIEnv_CallIntMethod(JNIEnv *p0, jobject p1, jmethodID p2, ...) SOFTFP; +jint JNIEnv_CallIntMethodV(JNIEnv *p0, jobject p1, jmethodID p2, va_list p3) SOFTFP; +jint JNIEnv_CallIntMethodA(JNIEnv *p0, jobject p1, jmethodID p2, jvalue *p3) SOFTFP; +jlong JNIEnv_CallLongMethod(JNIEnv *p0, jobject p1, jmethodID p2, ...) SOFTFP; +jlong JNIEnv_CallLongMethodV(JNIEnv *p0, jobject p1, jmethodID p2, va_list p3) SOFTFP; +jlong JNIEnv_CallLongMethodA(JNIEnv *p0, jobject p1, jmethodID p2, jvalue *p3) SOFTFP; +jfloat JNIEnv_CallFloatMethod(JNIEnv *p0, jobject p1, jmethodID p2, ...) SOFTFP; +jfloat JNIEnv_CallFloatMethodV(JNIEnv *p0, jobject p1, jmethodID p2, va_list p3) SOFTFP; +jfloat JNIEnv_CallFloatMethodA(JNIEnv *p0, jobject p1, jmethodID p2, jvalue *p3) SOFTFP; +jdouble JNIEnv_CallDoubleMethod(JNIEnv *p0, jobject p1, jmethodID p2, ...) SOFTFP; +jdouble JNIEnv_CallDoubleMethodV(JNIEnv *p0, jobject p1, jmethodID p2, va_list p3) SOFTFP; +jdouble JNIEnv_CallDoubleMethodA(JNIEnv *p0, jobject p1, jmethodID p2, jvalue *p3) SOFTFP; +void JNIEnv_CallVoidMethod(JNIEnv *p0, jobject p1, jmethodID p2, ...) SOFTFP; +void JNIEnv_CallVoidMethodV(JNIEnv *p0, jobject p1, jmethodID p2, va_list p3) SOFTFP; +void JNIEnv_CallVoidMethodA(JNIEnv *p0, jobject p1, jmethodID p2, jvalue *p3) SOFTFP; +jobject JNIEnv_CallNonvirtualObjectMethod(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, ...) SOFTFP; +jobject JNIEnv_CallNonvirtualObjectMethodV(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, va_list p4) SOFTFP; +jobject JNIEnv_CallNonvirtualObjectMethodA(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, jvalue *p4) SOFTFP; +jboolean JNIEnv_CallNonvirtualBooleanMethod(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, ...) SOFTFP; +jboolean JNIEnv_CallNonvirtualBooleanMethodV(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, va_list p4) SOFTFP; +jboolean JNIEnv_CallNonvirtualBooleanMethodA(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, jvalue *p4) SOFTFP; +jbyte JNIEnv_CallNonvirtualByteMethod(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, ...) SOFTFP; +jbyte JNIEnv_CallNonvirtualByteMethodV(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, va_list p4) SOFTFP; +jbyte JNIEnv_CallNonvirtualByteMethodA(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, jvalue *p4) SOFTFP; +jchar JNIEnv_CallNonvirtualCharMethod(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, ...) SOFTFP; +jchar JNIEnv_CallNonvirtualCharMethodV(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, va_list p4) SOFTFP; +jchar JNIEnv_CallNonvirtualCharMethodA(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, jvalue *p4) SOFTFP; +jshort JNIEnv_CallNonvirtualShortMethod(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, ...) SOFTFP; +jshort JNIEnv_CallNonvirtualShortMethodV(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, va_list p4) SOFTFP; +jshort JNIEnv_CallNonvirtualShortMethodA(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, jvalue *p4) SOFTFP; +jint JNIEnv_CallNonvirtualIntMethod(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, ...) SOFTFP; +jint JNIEnv_CallNonvirtualIntMethodV(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, va_list p4) SOFTFP; +jint JNIEnv_CallNonvirtualIntMethodA(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, jvalue *p4) SOFTFP; +jlong JNIEnv_CallNonvirtualLongMethod(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, ...) SOFTFP; +jlong JNIEnv_CallNonvirtualLongMethodV(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, va_list p4) SOFTFP; +jlong JNIEnv_CallNonvirtualLongMethodA(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, jvalue *p4) SOFTFP; +jfloat JNIEnv_CallNonvirtualFloatMethod(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, ...) SOFTFP; +jfloat JNIEnv_CallNonvirtualFloatMethodV(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, va_list p4) SOFTFP; +jfloat JNIEnv_CallNonvirtualFloatMethodA(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, jvalue *p4) SOFTFP; +jdouble JNIEnv_CallNonvirtualDoubleMethod(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, ...) SOFTFP; +jdouble JNIEnv_CallNonvirtualDoubleMethodV(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, va_list p4) SOFTFP; +jdouble JNIEnv_CallNonvirtualDoubleMethodA(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, jvalue *p4) SOFTFP; +void JNIEnv_CallNonvirtualVoidMethod(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, ...) SOFTFP; +void JNIEnv_CallNonvirtualVoidMethodV(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, va_list p4) SOFTFP; +void JNIEnv_CallNonvirtualVoidMethodA(JNIEnv *p0, jobject p1, jclass p2, jmethodID p3, jvalue *p4) SOFTFP; +jfieldID JNIEnv_GetFieldID(JNIEnv *p0, jclass p1, const char *p2, const char *p3) SOFTFP; +jobject JNIEnv_GetObjectField(JNIEnv *p0, jobject p1, jfieldID p2) SOFTFP; +jboolean JNIEnv_GetBooleanField(JNIEnv *p0, jobject p1, jfieldID p2) SOFTFP; +jbyte JNIEnv_GetByteField(JNIEnv *p0, jobject p1, jfieldID p2) SOFTFP; +jchar JNIEnv_GetCharField(JNIEnv *p0, jobject p1, jfieldID p2) SOFTFP; +jshort JNIEnv_GetShortField(JNIEnv *p0, jobject p1, jfieldID p2) SOFTFP; +jint JNIEnv_GetIntField(JNIEnv *p0, jobject p1, jfieldID p2) SOFTFP; +jlong JNIEnv_GetLongField(JNIEnv *p0, jobject p1, jfieldID p2) SOFTFP; +jfloat JNIEnv_GetFloatField(JNIEnv *p0, jobject p1, jfieldID p2) SOFTFP; +jdouble JNIEnv_GetDoubleField(JNIEnv *p0, jobject p1, jfieldID p2) SOFTFP; +void JNIEnv_SetObjectField(JNIEnv *p0, jobject p1, jfieldID p2, jobject p3) SOFTFP; +void JNIEnv_SetBooleanField(JNIEnv *p0, jobject p1, jfieldID p2, jboolean p3) SOFTFP; +void JNIEnv_SetByteField(JNIEnv *p0, jobject p1, jfieldID p2, jbyte p3) SOFTFP; +void JNIEnv_SetCharField(JNIEnv *p0, jobject p1, jfieldID p2, jchar p3) SOFTFP; +void JNIEnv_SetShortField(JNIEnv *p0, jobject p1, jfieldID p2, jshort p3) SOFTFP; +void JNIEnv_SetIntField(JNIEnv *p0, jobject p1, jfieldID p2, jint p3) SOFTFP; +void JNIEnv_SetLongField(JNIEnv *p0, jobject p1, jfieldID p2, jlong p3) SOFTFP; +void JNIEnv_SetFloatField(JNIEnv *p0, jobject p1, jfieldID p2, jfloat p3) SOFTFP; +void JNIEnv_SetDoubleField(JNIEnv *p0, jobject p1, jfieldID p2, jdouble p3) SOFTFP; +jmethodID JNIEnv_GetStaticMethodID(JNIEnv *p0, jclass p1, const char *p2, const char *p3) SOFTFP; +jobject JNIEnv_CallStaticObjectMethod(JNIEnv *p0, jclass p1, jmethodID p2, ...) SOFTFP; +jobject JNIEnv_CallStaticObjectMethodV(JNIEnv *p0, jclass p1, jmethodID p2, va_list p3) SOFTFP; +jobject JNIEnv_CallStaticObjectMethodA(JNIEnv *p0, jclass p1, jmethodID p2, jvalue *p3) SOFTFP; +jboolean JNIEnv_CallStaticBooleanMethod(JNIEnv *p0, jclass p1, jmethodID p2, ...) SOFTFP; +jboolean JNIEnv_CallStaticBooleanMethodV(JNIEnv *p0, jclass p1, jmethodID p2, va_list p3) SOFTFP; +jboolean JNIEnv_CallStaticBooleanMethodA(JNIEnv *p0, jclass p1, jmethodID p2, jvalue *p3) SOFTFP; +jbyte JNIEnv_CallStaticByteMethod(JNIEnv *p0, jclass p1, jmethodID p2, ...) SOFTFP; +jbyte JNIEnv_CallStaticByteMethodV(JNIEnv *p0, jclass p1, jmethodID p2, va_list p3) SOFTFP; +jbyte JNIEnv_CallStaticByteMethodA(JNIEnv *p0, jclass p1, jmethodID p2, jvalue *p3) SOFTFP; +jchar JNIEnv_CallStaticCharMethod(JNIEnv *p0, jclass p1, jmethodID p2, ...) SOFTFP; +jchar JNIEnv_CallStaticCharMethodV(JNIEnv *p0, jclass p1, jmethodID p2, va_list p3) SOFTFP; +jchar JNIEnv_CallStaticCharMethodA(JNIEnv *p0, jclass p1, jmethodID p2, jvalue *p3) SOFTFP; +jshort JNIEnv_CallStaticShortMethod(JNIEnv *p0, jclass p1, jmethodID p2, ...) SOFTFP; +jshort JNIEnv_CallStaticShortMethodV(JNIEnv *p0, jclass p1, jmethodID p2, va_list p3) SOFTFP; +jshort JNIEnv_CallStaticShortMethodA(JNIEnv *p0, jclass p1, jmethodID p2, jvalue *p3) SOFTFP; +jint JNIEnv_CallStaticIntMethod(JNIEnv *p0, jclass p1, jmethodID p2, ...) SOFTFP; +jint JNIEnv_CallStaticIntMethodV(JNIEnv *p0, jclass p1, jmethodID p2, va_list p3) SOFTFP; +jint JNIEnv_CallStaticIntMethodA(JNIEnv *p0, jclass p1, jmethodID p2, jvalue *p3) SOFTFP; +jlong JNIEnv_CallStaticLongMethod(JNIEnv *p0, jclass p1, jmethodID p2, ...) SOFTFP; +jlong JNIEnv_CallStaticLongMethodV(JNIEnv *p0, jclass p1, jmethodID p2, va_list p3) SOFTFP; +jlong JNIEnv_CallStaticLongMethodA(JNIEnv *p0, jclass p1, jmethodID p2, jvalue *p3) SOFTFP; +jfloat JNIEnv_CallStaticFloatMethod(JNIEnv *p0, jclass p1, jmethodID p2, ...) SOFTFP; +jfloat JNIEnv_CallStaticFloatMethodV(JNIEnv *p0, jclass p1, jmethodID p2, va_list p3) SOFTFP; +jfloat JNIEnv_CallStaticFloatMethodA(JNIEnv *p0, jclass p1, jmethodID p2, jvalue *p3) SOFTFP; +jdouble JNIEnv_CallStaticDoubleMethod(JNIEnv *p0, jclass p1, jmethodID p2, ...) SOFTFP; +jdouble JNIEnv_CallStaticDoubleMethodV(JNIEnv *p0, jclass p1, jmethodID p2, va_list p3) SOFTFP; +jdouble JNIEnv_CallStaticDoubleMethodA(JNIEnv *p0, jclass p1, jmethodID p2, jvalue *p3) SOFTFP; +void JNIEnv_CallStaticVoidMethod(JNIEnv *p0, jclass p1, jmethodID p2, ...) SOFTFP; +void JNIEnv_CallStaticVoidMethodV(JNIEnv *p0, jclass p1, jmethodID p2, va_list p3) SOFTFP; +void JNIEnv_CallStaticVoidMethodA(JNIEnv *p0, jclass p1, jmethodID p2, jvalue *p3) SOFTFP; +jfieldID JNIEnv_GetStaticFieldID(JNIEnv *p0, jclass p1, const char *p2, const char *p3) SOFTFP; +jobject JNIEnv_GetStaticObjectField(JNIEnv *p0, jclass p1, jfieldID p2) SOFTFP; +jboolean JNIEnv_GetStaticBooleanField(JNIEnv *p0, jclass p1, jfieldID p2) SOFTFP; +jbyte JNIEnv_GetStaticByteField(JNIEnv *p0, jclass p1, jfieldID p2) SOFTFP; +jchar JNIEnv_GetStaticCharField(JNIEnv *p0, jclass p1, jfieldID p2) SOFTFP; +jshort JNIEnv_GetStaticShortField(JNIEnv *p0, jclass p1, jfieldID p2) SOFTFP; +jint JNIEnv_GetStaticIntField(JNIEnv *p0, jclass p1, jfieldID p2) SOFTFP; +jlong JNIEnv_GetStaticLongField(JNIEnv *p0, jclass p1, jfieldID p2) SOFTFP; +jfloat JNIEnv_GetStaticFloatField(JNIEnv *p0, jclass p1, jfieldID p2) SOFTFP; +jdouble JNIEnv_GetStaticDoubleField(JNIEnv *p0, jclass p1, jfieldID p2) SOFTFP; +void JNIEnv_SetStaticObjectField(JNIEnv *p0, jclass p1, jfieldID p2, jobject p3) SOFTFP; +void JNIEnv_SetStaticBooleanField(JNIEnv *p0, jclass p1, jfieldID p2, jboolean p3) SOFTFP; +void JNIEnv_SetStaticByteField(JNIEnv *p0, jclass p1, jfieldID p2, jbyte p3) SOFTFP; +void JNIEnv_SetStaticCharField(JNIEnv *p0, jclass p1, jfieldID p2, jchar p3) SOFTFP; +void JNIEnv_SetStaticShortField(JNIEnv *p0, jclass p1, jfieldID p2, jshort p3) SOFTFP; +void JNIEnv_SetStaticIntField(JNIEnv *p0, jclass p1, jfieldID p2, jint p3) SOFTFP; +void JNIEnv_SetStaticLongField(JNIEnv *p0, jclass p1, jfieldID p2, jlong p3) SOFTFP; +void JNIEnv_SetStaticFloatField(JNIEnv *p0, jclass p1, jfieldID p2, jfloat p3) SOFTFP; +void JNIEnv_SetStaticDoubleField(JNIEnv *p0, jclass p1, jfieldID p2, jdouble p3) SOFTFP; +jstring JNIEnv_NewString(JNIEnv *p0, const jchar *p1, jsize p2) SOFTFP; +jsize JNIEnv_GetStringLength(JNIEnv *p0, jstring p1) SOFTFP; +const jchar *JNIEnv_GetStringChars(JNIEnv *p0, jstring p1, jboolean *p2) SOFTFP; +void JNIEnv_ReleaseStringChars(JNIEnv *p0, jstring p1, const jchar *p2) SOFTFP; +jstring JNIEnv_NewStringUTF(JNIEnv *p0, const char *p1) SOFTFP; +jsize JNIEnv_GetStringUTFLength(JNIEnv *p0, jstring p1) SOFTFP; +jsize JNIEnv_GetArrayLength(JNIEnv *p0, jarray p1) SOFTFP; +jobjectArray JNIEnv_NewObjectArray(JNIEnv *p0, jsize p1, jclass p2, jobject p3) SOFTFP; +jobject JNIEnv_GetObjectArrayElement(JNIEnv *p0, jobjectArray p1, jsize p2) SOFTFP; +void JNIEnv_SetObjectArrayElement(JNIEnv *p0, jobjectArray p1, jsize p2, jobject p3) SOFTFP; +jbooleanArray JNIEnv_NewBooleanArray(JNIEnv *p0, jsize p1) SOFTFP; +jbyteArray JNIEnv_NewByteArray(JNIEnv *p0, jsize p1) SOFTFP; +jcharArray JNIEnv_NewCharArray(JNIEnv *p0, jsize p1) SOFTFP; +jshortArray JNIEnv_NewShortArray(JNIEnv *p0, jsize p1) SOFTFP; +jintArray JNIEnv_NewIntArray(JNIEnv *p0, jsize p1) SOFTFP; +jlongArray JNIEnv_NewLongArray(JNIEnv *p0, jsize p1) SOFTFP; +jfloatArray JNIEnv_NewFloatArray(JNIEnv *p0, jsize p1) SOFTFP; +jdoubleArray JNIEnv_NewDoubleArray(JNIEnv *p0, jsize p1) SOFTFP; +jboolean *JNIEnv_GetBooleanArrayElements(JNIEnv *p0, jbooleanArray p1, jboolean *p2) SOFTFP; +jbyte *JNIEnv_GetByteArrayElements(JNIEnv *p0, jbyteArray p1, jboolean *p2) SOFTFP; +jchar *JNIEnv_GetCharArrayElements(JNIEnv *p0, jcharArray p1, jboolean *p2) SOFTFP; +jshort *JNIEnv_GetShortArrayElements(JNIEnv *p0, jshortArray p1, jboolean *p2) SOFTFP; +jint *JNIEnv_GetIntArrayElements(JNIEnv *p0, jintArray p1, jboolean *p2) SOFTFP; +jlong *JNIEnv_GetLongArrayElements(JNIEnv *p0, jlongArray p1, jboolean *p2) SOFTFP; +jfloat *JNIEnv_GetFloatArrayElements(JNIEnv *p0, jfloatArray p1, jboolean *p2) SOFTFP; +jdouble *JNIEnv_GetDoubleArrayElements(JNIEnv *p0, jdoubleArray p1, jboolean *p2) SOFTFP; +void JNIEnv_ReleaseBooleanArrayElements(JNIEnv *p0, jbooleanArray p1, jboolean *p2, jint p3) SOFTFP; +void JNIEnv_ReleaseByteArrayElements(JNIEnv *p0, jbyteArray p1, jbyte *p2, jint p3) SOFTFP; +void JNIEnv_ReleaseCharArrayElements(JNIEnv *p0, jcharArray p1, jchar *p2, jint p3) SOFTFP; +void JNIEnv_ReleaseShortArrayElements(JNIEnv *p0, jshortArray p1, jshort *p2, jint p3) SOFTFP; +void JNIEnv_ReleaseIntArrayElements(JNIEnv *p0, jintArray p1, jint *p2, jint p3) SOFTFP; +void JNIEnv_ReleaseLongArrayElements(JNIEnv *p0, jlongArray p1, jlong *p2, jint p3) SOFTFP; +void JNIEnv_ReleaseFloatArrayElements(JNIEnv *p0, jfloatArray p1, jfloat *p2, jint p3) SOFTFP; +void JNIEnv_ReleaseDoubleArrayElements(JNIEnv *p0, jdoubleArray p1, jdouble *p2, jint p3) SOFTFP; +void JNIEnv_GetBooleanArrayRegion(JNIEnv *p0, jbooleanArray p1, jsize p2, jsize p3, jboolean *p4) SOFTFP; +void JNIEnv_GetByteArrayRegion(JNIEnv *p0, jbyteArray arrayobj, jsize start, jsize len, jbyte *buf) SOFTFP; +void JNIEnv_GetCharArrayRegion(JNIEnv *p0, jcharArray p1, jsize p2, jsize p3, jchar *p4) SOFTFP; +void JNIEnv_GetShortArrayRegion(JNIEnv *p0, jshortArray p1, jsize p2, jsize p3, jshort *p4) SOFTFP; +void JNIEnv_GetIntArrayRegion(JNIEnv *p0, jintArray p1, jsize p2, jsize p3, jint *p4) SOFTFP; +void JNIEnv_GetLongArrayRegion(JNIEnv *p0, jlongArray p1, jsize p2, jsize p3, jlong *p4) SOFTFP; +void JNIEnv_GetFloatArrayRegion(JNIEnv *p0, jfloatArray p1, jsize p2, jsize p3, jfloat *p4) SOFTFP; +void JNIEnv_GetDoubleArrayRegion(JNIEnv *p0, jdoubleArray p1, jsize p2, jsize p3, jdouble *p4) SOFTFP; +void JNIEnv_SetBooleanArrayRegion(JNIEnv *p0, jbooleanArray p1, jsize p2, jsize p3, const jboolean *p4) SOFTFP; +void JNIEnv_SetByteArrayRegion(JNIEnv *p0, jbyteArray p1, jsize p2, jsize p3, const jbyte *p4) SOFTFP; +void JNIEnv_SetCharArrayRegion(JNIEnv *p0, jcharArray p1, jsize p2, jsize p3, const jchar *p4) SOFTFP; +void JNIEnv_SetShortArrayRegion(JNIEnv *p0, jshortArray p1, jsize p2, jsize p3, const jshort *p4) SOFTFP; +void JNIEnv_SetIntArrayRegion(JNIEnv *p0, jintArray p1, jsize p2, jsize p3, const jint *p4) SOFTFP; +void JNIEnv_SetLongArrayRegion(JNIEnv *p0, jlongArray p1, jsize p2, jsize p3, const jlong *p4) SOFTFP; +void JNIEnv_SetFloatArrayRegion(JNIEnv *p0, jfloatArray p1, jsize p2, jsize p3, const jfloat *p4) SOFTFP; +void JNIEnv_SetDoubleArrayRegion(JNIEnv *p0, jdoubleArray p1, jsize p2, jsize p3, const jdouble *p4) SOFTFP; +jint JNIEnv_RegisterNatives(JNIEnv *p0, jclass p1, const JNINativeMethod *p2, jint p3) SOFTFP; +jint JNIEnv_UnregisterNatives(JNIEnv *p0, jclass p1) SOFTFP; +jint JNIEnv_MonitorEnter(JNIEnv *p0, jobject p1) SOFTFP; +jint JNIEnv_MonitorExit(JNIEnv *p0, jobject p1) SOFTFP; +jint JNIEnv_GetJavaVM(JNIEnv *p0, JavaVM **p1) SOFTFP; +void JNIEnv_GetStringRegion(JNIEnv *p0, jstring p1, jsize p2, jsize p3, jchar *p4) SOFTFP; +void JNIEnv_GetStringUTFRegion(JNIEnv *p0, jstring p1, jsize p2, jsize p3, char *p4) SOFTFP; +void *JNIEnv_GetPrimitiveArrayCritical(JNIEnv *p0, jarray p1, jboolean *p2) SOFTFP; +void JNIEnv_ReleasePrimitiveArrayCritical(JNIEnv *p0, jarray p1, void *p2, jint p3) SOFTFP; +const jchar *JNIEnv_GetStringCritical(JNIEnv *p0, jstring p1, jboolean *p2) SOFTFP; +void JNIEnv_ReleaseStringCritical(JNIEnv *p0, jstring p1, const jchar *p2) SOFTFP; +jweak JNIEnv_NewWeakGlobalRef(JNIEnv *p0, jobject p1) SOFTFP; +void JNIEnv_DeleteWeakGlobalRef(JNIEnv *p0, jweak p1) SOFTFP; +jboolean JNIEnv_ExceptionCheck(JNIEnv *p0) SOFTFP; +jobject JNIEnv_NewDirectByteBuffer(JNIEnv *p0, void *p1, jlong p2) SOFTFP; +void *JNIEnv_GetDirectBufferAddress(JNIEnv *p0, jobject p1) SOFTFP; +jlong JNIEnv_GetDirectBufferCapacity(JNIEnv *p0, jobject p1) SOFTFP; +const char *JNIEnv_GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy) SOFTFP; +void JNIEnv_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf) SOFTFP; + +void jnienv_init(struct GlobalState *global) SOFTFP; + +jint JavaVM_DestroyJavaVM(JavaVM *vm) SOFTFP; +jint JavaVM_AttachCurrentThread(JavaVM *vm, JNIEnv **env, void *args) SOFTFP; +jint JavaVM_DetachCurrentThread(JavaVM *vm) SOFTFP; +jint JavaVM_GetEnv(JavaVM *vm, void **env, jint version) SOFTFP; +jint JavaVM_AttachCurrentThreadAsDaemon(JavaVM *vm, JNIEnv **env, void *args) SOFTFP; + +void javavm_init(struct GlobalState *global) SOFTFP; + +#endif /* JNIENV_H */ diff --git a/jni/shlib.c b/jni/shlib.c new file mode 100644 index 0000000..7cc7cdc --- /dev/null +++ b/jni/shlib.c @@ -0,0 +1,116 @@ + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + +#include +#include +#include +#include +#include + +#include "../apkenv.h" + +#ifdef APKENV_DEBUG +# define JNISHLIB_DEBUG_PRINTF(...) printf(__VA_ARGS__) +#else +# define JNISHLIB_DEBUG_PRINTF(...) +#endif + + +char ** +jni_shlib_find_methods(const char *filename) +{ + int method_table_size = 32; + int method_table_offset = 0; + char **method_table = calloc(method_table_size, sizeof(char*)); + + FILE *fp = fopen(filename, "rb"); + + char tmp[1024]; + int remaining_bytes, i; + Elf32_Ehdr header; + Elf32_Shdr section; + + fseek(fp, 0, SEEK_SET); + fread(&header, sizeof(Elf32_Ehdr), 1, fp); + fseek(fp, header.e_shoff, SEEK_SET); + + for (i=0; i= sizeof(tmp)) { + break; + } + tmp[i] = fgetc(fp); + remaining_bytes--; + if (tmp[i] == '\0') { + if ((memcmp(tmp, "Java_", 5) == 0) || + (memcmp(tmp, "JNI_", 4) == 0)) { + method_table[method_table_offset++] = strdup(tmp); + if (method_table_offset == method_table_size) { + method_table_size *= 2; + method_table = realloc(method_table, + method_table_size*sizeof(char*)); + } + } + i = 0; + continue; + } + i++; + } + break; + } + } + + fclose(fp); + method_table[method_table_offset] = NULL; + return method_table; +} + +void * +jni_shlib_resolve(struct GlobalState *global, const char *method) +{ + char **method_table = global->method_table; + + while (*method_table) { + if (strstr(*method_table, method) != NULL) { + JNISHLIB_DEBUG_PRINTF("[shlib] Found symbol: %s\n", + *method_table); + return android_dlsym(global->jni_library, *method_table); + } + method_table++; + } + + return NULL; +} + diff --git a/jni/shlib.h b/jni/shlib.h new file mode 100644 index 0000000..640726c --- /dev/null +++ b/jni/shlib.h @@ -0,0 +1,41 @@ +#ifndef JNI_SHLIB_H +#define JNI_SHLIB_H + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + +#include "../apkenv.h" + +char ** +jni_shlib_find_methods(const char *filename); + +void * +jni_shlib_resolve(struct GlobalState *global, const char *method); + +#endif /* JNI_SHLIB_H */ diff --git a/libs/README b/libs/README new file mode 100644 index 0000000..700bbcd --- /dev/null +++ b/libs/README @@ -0,0 +1,5 @@ + +These libraries have been extracted from + + http://downloads.nitdroid.com/e-yes/n9/nitdroid_n9_ics_alpha4.tar.bz2 + diff --git a/libs/libc.so b/libs/libc.so new file mode 100644 index 0000000..3dc8579 Binary files /dev/null and b/libs/libc.so differ diff --git a/libs/libm.so b/libs/libm.so new file mode 100644 index 0000000..e70c429 Binary files /dev/null and b/libs/libm.so differ diff --git a/libs/libstdc++.so b/libs/libstdc++.so new file mode 100644 index 0000000..b726970 Binary files /dev/null and b/libs/libstdc++.so differ diff --git a/linker/NOTICE b/linker/NOTICE new file mode 100644 index 0000000..c5b1efa --- /dev/null +++ b/linker/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2005-2008, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/linker/README.TXT b/linker/README.TXT new file mode 100644 index 0000000..f920b97 --- /dev/null +++ b/linker/README.TXT @@ -0,0 +1,144 @@ +Android Dynamic Linker Design Notes +=================================== + +Introduction: +------------- + +This document provides several notes related to the design of the Android +dynamic linker. + + +Prelinking: +----------- + +System libraries in Android are internally prelinked, which means that +any internal relocations within them are stripped from the corresponding +shared object, in order to reduce size and speed up loading. + +Such libraries can only be loaded at the very specific virtual memory address +they have been prelinked to (during the build process). The list of prelinked +system libraries and their corresponding virtual memory address is found in +the file: + + build/core/prelink-linux-.map + +It should be updated each time a new system library is added to the +system. + +The prelink step happens at build time, and uses the 'soslim' and 'apriori' +tools: + + - 'apriori' is the real prelink tool which removes relocations from the + shared object, however, it must be given a list of symbols to remove + from the file. + + - 'soslim' is used to find symbols in an executable ELF file + and generate a list that can be passed to 'apriori'. + +By default, these tools are only used to remove internal symbols from +libraries, though they have been designed to allow more aggressive +optimizations (e.g. 'global' prelinking and symbol stripping, which +prevent replacing individual system libraries though). + +You can disable prelinking at build time by modifying your Android.mk with +a line like: + + LOCAL_PRELINK_MODULE := false + + +Initialization and Termination functions: +----------------------------------------- + +The Unix Sys V Binary Interface standard states that an +executable can have the following entries in its .dynamic +section: + + DT_INIT + Points to the address of an initialization function + that must be called when the file is loaded. + + DT_INIT_ARRAY + Points to an array of function addresses that must be + called, in-order, to perform initialization. Some of + the entries in the array can be 0 or -1, and should + be ignored. + + Note: this is generally stored in a .init_array section + + DT_INIT_ARRAYSZ + The size of the DT_INITARRAY, if any + + DT_FINI + Points to the address of a finalization function which + must be called when the file is unloaded or the process + terminated. + + DT_FINI_ARRAY + Same as DT_INITARRAY but for finalizers. Note that the + functions must be called in reverse-order though + + Note: this is generally stored in a .fini_array section + + DT_FINI_ARRAYSZ + Size of FT_FINIARRAY + + DT_PREINIT_ARRAY + An array similar to DT_INIT_ARRAY which must *only* be + present in executables, not shared libraries, which contains + a list of functions that need to be called before any other + initialization function (i.e. DT_INIT and/or DT_INIT_ARRAY) + in the executable or any of its libraries. + + Note: this is generally stored in a .preinit_array section + + DT_PREINIT_ARRAYSZ + The size of DT_PREINIT_ARRAY + +If both a DT_INIT and DT_INITARRAY entry are present, the DT_INIT +function must be called before the DT_INITARRAY functions. + +Consequently, the DT_FINIARRAY must be parsed in reverse order before +the DT_FINI function, if both are available. + +Note that the implementation of static C++ constructors is very +much processor dependent, and may use different ELF sections. + +On the ARM (see "C++ ABI for ARM" document), the static constructors +must be called explicitly from the DT_INIT_ARRAY, and each one of them +shall register a destructor by calling the special __eabi_atexit() +function (provided by the C library). The DT_FINI_ARRAY is not used +by static C++ destructors. + +On x86, the lists of constructors and destructors are placed in special +sections named ".ctors" and ".dtors", and the DT_INIT / DT_FINI functions +are in charge of calling them explicitly. + + +Debugging: +---------- + +It is possible to enable debug output in the dynamic linker. To do so, +follow these steps: + +1/ Modify the line in Android.mk that says: + + LOCAL_CFLAGS += -DLINKER_DEBUG=0 + + Into the following: + + LOCAL_CFLAGS += -DLINKER_DEBUG=1 + +2/ Force-rebuild the dynamic linker: + + cd bionic/linker + mm -B + +3/ Rebuild a new system image. + +You can increase the verbosity of debug traces by defining the DEBUG +environment variable to a numeric value from 0 to 2. This will only +affect new processes being launched. + +By default, traces are sent to logcat, with the "linker" tag. You can +change this to go to stdout instead by setting the definition of +LINKER_DEBUG_TO_LOG to 0 in "linker_debug.h". diff --git a/linker/bionic_tls.h b/linker/bionic_tls.h new file mode 100644 index 0000000..3907a83 --- /dev/null +++ b/linker/bionic_tls.h @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _SYS_TLS_H +#define _SYS_TLS_H + +#define HAVE_ARM_TLS_REGISTER + +#include + +__BEGIN_DECLS + +/** WARNING WARNING WARNING + ** + ** This header file is *NOT* part of the public Bionic ABI/API + ** and should not be used/included by user-serviceable parts of + ** the system (e.g. applications). + ** + ** It is only provided here for the benefit of the system dynamic + ** linker and the OpenGL sub-system (which needs to access the + ** pre-allocated slot directly for performance reason). + **/ + +/* maximum number of elements in the TLS array */ +#define BIONIC_TLS_SLOTS 64 + +/* note that slot 0, called TLS_SLOT_SELF must point to itself. + * this is required to implement thread-local storage with the x86 + * Linux kernel, that reads the TLS from fs:[0], where 'fs' is a + * thread-specific segment descriptor... + */ + +/* Well known TLS slots */ +#define TLS_SLOT_SELF 0 +#define TLS_SLOT_THREAD_ID 1 +#define TLS_SLOT_ERRNO 2 + +#define TLS_SLOT_OPENGL_API 3 +#define TLS_SLOT_OPENGL 4 + +/* this slot is only used to pass information from the dynamic linker to + * libc.so when the C library is loaded in to memory. The C runtime init + * function will then clear it. Since its use is extremely temporary, + * we reuse an existing location. + */ +#define TLS_SLOT_BIONIC_PREINIT (TLS_SLOT_ERRNO+1) + +/* small technical note: it is not possible to call pthread_setspecific + * on keys that are <= TLS_SLOT_MAX_WELL_KNOWN, which is why it is set to + * TLS_SLOT_ERRNO. + * + * later slots like TLS_SLOT_OPENGL are pre-allocated through the use of + * TLS_DEFAULT_ALLOC_MAP. this means that there is no need to use + * pthread_key_create() to initialize them. on the other hand, there is + * no destructor associated to them (we might need to implement this later) + */ +#define TLS_SLOT_MAX_WELL_KNOWN TLS_SLOT_ERRNO + +#define TLS_DEFAULT_ALLOC_MAP 0x0000001F + +/* set the Thread Local Storage, must contain at least BIONIC_TLS_SLOTS pointers */ +extern void __init_tls(void** tls, void* thread_info); + +/* syscall only, do not call directly */ +extern int __set_tls(void *ptr); + +/* get the TLS */ +#ifdef __arm__ +/* The standard way to get the TLS is to call a kernel helper + * function (i.e. a function provided at a fixed address in a + * "magic page" mapped in all user-space address spaces ), which + * contains the most appropriate code path for the target device. + * + * However, for performance reasons, we're going to use our own + * machine code for the system's C shared library. + * + * We cannot use this optimization in the static version of the + * C library, because we don't know where the corresponding code + * is going to run. + */ +# ifdef LIBC_STATIC + +/* Use the kernel helper in static C library. */ + typedef volatile void* (__kernel_get_tls_t)(void); +# define __get_tls() (*(__kernel_get_tls_t *)0xffff0fe0)() + +# else /* !LIBC_STATIC */ +/* Use optimized code path. + * Note that HAVE_ARM_TLS_REGISTER is build-specific + * (it must match your kernel configuration) + */ +# ifdef HAVE_ARM_TLS_REGISTER + /* We can read the address directly from a coprocessor + * register, which avoids touching the data cache + * completely. + */ +# define __get_tls() \ + ({ register unsigned int __val asm("r0"); \ + asm ("mrc p15, 0, r0, c13, c0, 3" : "=r"(__val) ); \ + (volatile void*)__val; }) +# else /* !HAVE_ARM_TLS_REGISTER */ + /* The kernel provides the address of the TLS at a fixed + * address of the magic page too. + */ +# define __get_tls() ( *((volatile void **) 0xffff0ff0) ) +# endif +# endif /* !LIBC_STATIC */ +#else /* !ARM */ +extern void* __get_tls( void ); +#endif /* !ARM */ + +/* return the stack base and size, used by our malloc debugger */ +extern void* __get_stack_base(int *p_stack_size); + +__END_DECLS + +#endif /* _SYS_TLS_H */ diff --git a/linker/dlfcn.c b/linker/dlfcn.c new file mode 100644 index 0000000..2a6d01c --- /dev/null +++ b/linker/dlfcn.c @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "linker.h" +#include "linker_format.h" + +/* This file hijacks the symbols stubbed out in libdl.so. */ + +#define DL_SUCCESS 0 +#define DL_ERR_CANNOT_LOAD_LIBRARY 1 +#define DL_ERR_INVALID_LIBRARY_HANDLE 2 +#define DL_ERR_BAD_SYMBOL_NAME 3 +#define DL_ERR_SYMBOL_NOT_FOUND 4 +#define DL_ERR_SYMBOL_NOT_GLOBAL 5 + +static char dl_err_buf[1024]; +static const char *dl_err_str; + +static const char *dl_errors[] = { + [DL_ERR_CANNOT_LOAD_LIBRARY] = "Cannot load library", + [DL_ERR_INVALID_LIBRARY_HANDLE] = "Invalid library handle", + [DL_ERR_BAD_SYMBOL_NAME] = "Invalid symbol name", + [DL_ERR_SYMBOL_NOT_FOUND] = "Symbol not found", + [DL_ERR_SYMBOL_NOT_GLOBAL] = "Symbol is not global", +}; + +#define likely(expr) __builtin_expect (expr, 1) +#define unlikely(expr) __builtin_expect (expr, 0) + +pthread_mutex_t dl_lock = PTHREAD_MUTEX_INITIALIZER; + +static void set_dlerror(int err) +{ + format_buffer(dl_err_buf, sizeof(dl_err_buf), "%s: %s", dl_errors[err], + linker_get_error()); + dl_err_str = (const char *)&dl_err_buf[0]; +}; + +void *android_dlopen(const char *filename, int flag) +{ + soinfo *ret; + + pthread_mutex_lock(&dl_lock); + ret = find_library(filename); + if (unlikely(ret == NULL)) { + set_dlerror(DL_ERR_CANNOT_LOAD_LIBRARY); + } else { + call_constructors_recursive(ret); + ret->refcount++; + } + pthread_mutex_unlock(&dl_lock); + return ret; +} + +const char *android_dlerror(void) +{ + const char *tmp = dl_err_str; + dl_err_str = NULL; + return (const char *)tmp; +} + +void *android_dlsym(void *handle, const char *symbol) +{ + soinfo *found; + Elf32_Sym *sym; + unsigned bind; + + pthread_mutex_lock(&dl_lock); + + if(unlikely(handle == 0)) { + set_dlerror(DL_ERR_INVALID_LIBRARY_HANDLE); + goto err; + } + if(unlikely(symbol == 0)) { + set_dlerror(DL_ERR_BAD_SYMBOL_NAME); + goto err; + } + + if(handle == RTLD_DEFAULT) { + sym = lookup(symbol, &found, NULL); + } else if(handle == RTLD_NEXT) { + void *ret_addr = __builtin_return_address(0); + soinfo *si = find_containing_library(ret_addr); + + sym = NULL; + if(si && si->next) { + sym = lookup(symbol, &found, si->next); + } + } else { + found = (soinfo*)handle; + sym = lookup_in_library(found, symbol); + } + + if(likely(sym != 0)) { + bind = ELF32_ST_BIND(sym->st_info); + + if(likely((bind == STB_GLOBAL) && (sym->st_shndx != 0))) { + unsigned ret = sym->st_value + found->base; + pthread_mutex_unlock(&dl_lock); + return (void*)ret; + } + + set_dlerror(DL_ERR_SYMBOL_NOT_GLOBAL); + } + else + set_dlerror(DL_ERR_SYMBOL_NOT_FOUND); + +err: + pthread_mutex_unlock(&dl_lock); + return 0; +} + +int android_dladdr(const void *addr, Dl_info *info) +{ + int ret = 0; + + pthread_mutex_lock(&dl_lock); + + /* Determine if this address can be found in any library currently mapped */ + soinfo *si = find_containing_library(addr); + + if(si) { + memset(info, 0, sizeof(Dl_info)); + + info->dli_fname = si->name; + info->dli_fbase = (void*)si->base; + + /* Determine if any symbol in the library contains the specified address */ + Elf32_Sym *sym = find_containing_symbol(addr, si); + + if(sym != NULL) { + info->dli_sname = si->strtab + sym->st_name; + info->dli_saddr = (void*)(si->base + sym->st_value); + } + + ret = 1; + } + + pthread_mutex_unlock(&dl_lock); + + return ret; +} + +int android_dlclose(void *handle) +{ + pthread_mutex_lock(&dl_lock); + (void)unload_library((soinfo*)handle); + pthread_mutex_unlock(&dl_lock); + return 0; +} + + +#if defined(ANDROID_ARM_LINKER) +// 0000000 00011111 111112 22222222 2333333 333344444444445555555 +// 0123456 78901234 567890 12345678 9012345 678901234567890123456 +#define ANDROID_LIBDL_STRTAB \ + "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_unwind_find_exidx\0" + +_Unwind_Ptr android_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); + +#elif defined(ANDROID_X86_LINKER) +// 0000000 00011111 111112 22222222 2333333 3333444444444455 +// 0123456 78901234 567890 12345678 9012345 6789012345678901 +#define ANDROID_LIBDL_STRTAB \ + "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0" +int +android_dl_iterate_phdr(int (*cb)(struct dl_phdr_info *info, size_t size, void *data), + void *data); + +#else +#error Unsupported architecture. Only ARM and x86 are presently supported. +#endif + + +static Elf32_Sym libdl_symtab[] = { + // total length of libdl_info.strtab, including trailing 0 + // This is actually the the STH_UNDEF entry. Technically, it's + // supposed to have st_name == 0, but instead, it points to an index + // in the strtab with a \0 to make iterating through the symtab easier. + { st_name: sizeof(ANDROID_LIBDL_STRTAB) - 1, + }, + { st_name: 0, // starting index of the name in libdl_info.strtab + st_value: (Elf32_Addr) &android_dlopen, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, + { st_name: 7, + st_value: (Elf32_Addr) &android_dlclose, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, + { st_name: 15, + st_value: (Elf32_Addr) &android_dlsym, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, + { st_name: 21, + st_value: (Elf32_Addr) &android_dlerror, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, + { st_name: 29, + st_value: (Elf32_Addr) &android_dladdr, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, +#ifdef ANDROID_ARM_LINKER + { st_name: 36, + st_value: (Elf32_Addr) &android_dl_unwind_find_exidx, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, +#elif defined(ANDROID_X86_LINKER) + { st_name: 36, + st_value: (Elf32_Addr) &android_dl_iterate_phdr, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, +#endif +}; + +/* Fake out a hash table with a single bucket. + * A search of the hash table will look through + * libdl_symtab starting with index [1], then + * use libdl_chains to find the next index to + * look at. libdl_chains should be set up to + * walk through every element in libdl_symtab, + * and then end with 0 (sentinel value). + * + * I.e., libdl_chains should look like + * { 0, 2, 3, ... N, 0 } where N is the number + * of actual symbols, or nelems(libdl_symtab)-1 + * (since the first element of libdl_symtab is not + * a real symbol). + * + * (see _elf_lookup()) + * + * Note that adding any new symbols here requires + * stubbing them out in libdl. + */ +static unsigned libdl_buckets[1] = { 1 }; +static unsigned libdl_chains[7] = { 0, 2, 3, 4, 5, 6, 0 }; + +soinfo libdl_info = { + name: "libdl.so", + flags: FLAG_LINKED, + + strtab: ANDROID_LIBDL_STRTAB, + symtab: libdl_symtab, + + nbucket: 1, + nchain: 7, + bucket: libdl_buckets, + chain: libdl_chains, +}; + diff --git a/linker/linker.c b/linker/linker.c new file mode 100644 index 0000000..fa3d6cd --- /dev/null +++ b/linker/linker.c @@ -0,0 +1,2325 @@ +/* + * Copyright (C) 2008, 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef APKENV_DEBUG +# define LINKER_DEBUG_PRINTF(...) printf(__VA_ARGS__) +#else +# define LINKER_DEBUG_PRINTF(...) +#endif + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +/* special private C library header - see Android.mk */ +#include "bionic_tls.h" + +#include "strlcpy.h" + +/* for get_hooked_symbol */ +#include "../compat/hooks.h" + +#include "linker.h" +#include "linker_debug.h" +#include "linker_environ.h" +#include "linker_format.h" + +#define ALLOW_SYMBOLS_FROM_MAIN 1 +#define SO_MAX 128 + +/* Assume average path length of 64 and max 8 paths */ +#define LDPATH_BUFSIZE 512 +#define LDPATH_MAX 8 + +#define LDPRELOAD_BUFSIZE 512 +#define LDPRELOAD_MAX 8 + +/* >>> IMPORTANT NOTE - READ ME BEFORE MODIFYING <<< + * + * Do NOT use malloc() and friends or pthread_*() code here. + * Don't use printf() either; it's caused mysterious memory + * corruption in the past. + * The linker runs before we bring up libc and it's easiest + * to make sure it does not depend on any complex libc features + * + * open issues / todo: + * + * - are we doing everything we should for ARM_COPY relocations? + * - cleaner error reporting + * - after linking, set as much stuff as possible to READONLY + * and NOEXEC + * - linker hardcodes PAGE_SIZE and PAGE_MASK because the kernel + * headers provide versions that are negative... + * - allocate space for soinfo structs dynamically instead of + * having a hard limit (64) +*/ + + +static int link_image(soinfo *si, unsigned wr_offset); + +static int socount = 0; +static soinfo sopool[SO_MAX]; +static soinfo *freelist = NULL; +static soinfo *solist = &libdl_info; +static soinfo *sonext = &libdl_info; +#if ALLOW_SYMBOLS_FROM_MAIN +static soinfo *somain; /* main process, always the one after libdl_info */ +#endif + + +static inline int validate_soinfo(soinfo *si) +{ + return (si >= sopool && si < sopool + SO_MAX) || + si == &libdl_info; +} + +static char ldpaths_buf[LDPATH_BUFSIZE]; +static const char *ldpaths[LDPATH_MAX + 1]; + +static char ldpreloads_buf[LDPRELOAD_BUFSIZE]; +static const char *ldpreload_names[LDPRELOAD_MAX + 1]; + +static soinfo *preloads[LDPRELOAD_MAX + 1]; + +#if LINKER_DEBUG +int debug_verbosity; +#endif + +static int pid; + +/* This boolean is set if the program being loaded is setuid */ +static int program_is_setuid; + +#if STATS +struct _link_stats linker_stats; +#endif + +#if COUNT_PAGES +unsigned bitmask[4096]; +#endif + +#ifndef PT_ARM_EXIDX +#define PT_ARM_EXIDX 0x70000001 /* .ARM.exidx segment */ +#endif + +static char tmp_err_buf[768]; +static char __linker_dl_err_buf[768]; +#define DL_ERR(fmt, x...) \ + do { \ + format_buffer(__linker_dl_err_buf, sizeof(__linker_dl_err_buf), \ + "%s[%d]: " fmt, __func__, __LINE__, ##x); \ + ERROR(fmt "\n", ##x); \ + } while(0) + +const char *linker_get_error(void) +{ + return (const char *)&__linker_dl_err_buf[0]; +} + +/* + * This function is an empty stub where GDB locates a breakpoint to get notified + * about linker activity. + */ +extern void __attribute__((noinline)) rtld_db_dlactivity(void); + +static struct r_debug _r_debug = {1, NULL, &rtld_db_dlactivity, + RT_CONSISTENT, 0}; +static struct link_map *r_debug_tail = 0; + +static pthread_mutex_t _r_debug_lock = PTHREAD_MUTEX_INITIALIZER; + +static void insert_soinfo_into_debug_map(soinfo * info) +{ + struct link_map * map; + + /* Copy the necessary fields into the debug structure. + */ + map = &(info->linkmap); + map->l_addr = info->base; + map->l_name = (char*) info->name; + map->l_ld = (uintptr_t)info->dynamic; + + /* Stick the new library at the end of the list. + * gdb tends to care more about libc than it does + * about leaf libraries, and ordering it this way + * reduces the back-and-forth over the wire. + */ + if (r_debug_tail) { + r_debug_tail->l_next = map; + map->l_prev = r_debug_tail; + map->l_next = 0; + } else { + _r_debug.r_map = map; + map->l_prev = 0; + map->l_next = 0; + } + r_debug_tail = map; +} + +static void remove_soinfo_from_debug_map(soinfo * info) +{ + struct link_map * map = &(info->linkmap); + + if (r_debug_tail == map) + r_debug_tail = map->l_prev; + + if (map->l_prev) map->l_prev->l_next = map->l_next; + if (map->l_next) map->l_next->l_prev = map->l_prev; +} + +void notify_gdb_of_load(soinfo * info) +{ + if (info->flags & FLAG_EXE) { + // GDB already knows about the main executable + return; + } + + pthread_mutex_lock(&_r_debug_lock); + + _r_debug.r_state = RT_ADD; + rtld_db_dlactivity(); + + insert_soinfo_into_debug_map(info); + + _r_debug.r_state = RT_CONSISTENT; + rtld_db_dlactivity(); + + pthread_mutex_unlock(&_r_debug_lock); +} + +void notify_gdb_of_unload(soinfo * info) +{ + if (info->flags & FLAG_EXE) { + // GDB already knows about the main executable + return; + } + + pthread_mutex_lock(&_r_debug_lock); + + _r_debug.r_state = RT_DELETE; + rtld_db_dlactivity(); + + remove_soinfo_from_debug_map(info); + + _r_debug.r_state = RT_CONSISTENT; + rtld_db_dlactivity(); + + pthread_mutex_unlock(&_r_debug_lock); +} + +void notify_gdb_of_libraries() +{ + _r_debug.r_state = RT_ADD; + rtld_db_dlactivity(); + _r_debug.r_state = RT_CONSISTENT; + rtld_db_dlactivity(); +} + +static soinfo *alloc_info(const char *name) +{ + soinfo *si; + + if(strlen(name) >= SOINFO_NAME_LEN) { + DL_ERR("%5d library name %s too long", pid, name); + return NULL; + } + + /* The freelist is populated when we call free_info(), which in turn is + done only by dlclose(), which is not likely to be used. + */ + if (!freelist) { + if(socount == SO_MAX) { + DL_ERR("%5d too many libraries when loading %s", pid, name); + return NULL; + } + freelist = sopool + socount++; + freelist->next = NULL; + } + + si = freelist; + freelist = freelist->next; + + /* Make sure we get a clean block of soinfo */ + memset(si, 0, sizeof(soinfo)); + strlcpy((char*) si->name, name, sizeof(si->name)); + sonext->next = si; + si->next = NULL; + si->refcount = 0; + sonext = si; + + TRACE("%5d name %s: allocated soinfo @ %p\n", pid, name, si); + return si; +} + +static void free_info(soinfo *si) +{ + soinfo *prev = NULL, *trav; + + TRACE("%5d name %s: freeing soinfo @ %p\n", pid, si->name, si); + + for(trav = solist; trav != NULL; trav = trav->next){ + if (trav == si) + break; + prev = trav; + } + if (trav == NULL) { + /* si was not ni solist */ + DL_ERR("%5d name %s is not in solist!", pid, si->name); + return; + } + + /* prev will never be NULL, because the first entry in solist is + always the static libdl_info. + */ + prev->next = si->next; + if (si == sonext) sonext = prev; + si->next = freelist; + freelist = si; +} + +const char *addr_to_name(unsigned addr) +{ + soinfo *si; + + for(si = solist; si != 0; si = si->next){ + if((addr >= si->base) && (addr < (si->base + si->size))) { + return si->name; + } + } + + return ""; +} + +/* For a given PC, find the .so that it belongs to. + * Returns the base address of the .ARM.exidx section + * for that .so, and the number of 8-byte entries + * in that section (via *pcount). + * + * Intended to be called by libc's __gnu_Unwind_Find_exidx(). + * + * This function is exposed via dlfcn.c and libdl.so. + */ +#ifdef ANDROID_ARM_LINKER +_Unwind_Ptr android_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount) +{ + soinfo *si; + unsigned addr = (unsigned)pc; + + for (si = solist; si != 0; si = si->next){ + if ((addr >= si->base) && (addr < (si->base + si->size))) { + *pcount = si->ARM_exidx_count; + return (_Unwind_Ptr)(si->base + (unsigned long)si->ARM_exidx); + } + } + *pcount = 0; + return NULL; +} +#elif defined(ANDROID_X86_LINKER) +/* Here, we only have to provide a callback to iterate across all the + * loaded libraries. gcc_eh does the rest. */ +int +android_dl_iterate_phdr(int (*cb)(struct dl_phdr_info *info, size_t size, void *data), + void *data) +{ + soinfo *si; + struct dl_phdr_info dl_info; + int rv = 0; + + for (si = solist; si != NULL; si = si->next) { + dl_info.dlpi_addr = si->linkmap.l_addr; + dl_info.dlpi_name = si->linkmap.l_name; + dl_info.dlpi_phdr = si->phdr; + dl_info.dlpi_phnum = si->phnum; + rv = cb(&dl_info, sizeof (struct dl_phdr_info), data); + if (rv != 0) + break; + } + return rv; +} +#endif + +static Elf32_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name) +{ + Elf32_Sym *s; + Elf32_Sym *symtab = si->symtab; + const char *strtab = si->strtab; + unsigned n; + + TRACE_TYPE(LOOKUP, "%5d SEARCH %s in %s@0x%08x %08x %d\n", pid, + name, si->name, si->base, hash, hash % si->nbucket); + if (si->nbucket == 0) { + return NULL; + } + n = hash % si->nbucket; + + for(n = si->bucket[hash % si->nbucket]; n != 0; n = si->chain[n]){ + s = symtab + n; + if(strcmp(strtab + s->st_name, name)) continue; + + /* only concern ourselves with global and weak symbol definitions */ + switch(ELF32_ST_BIND(s->st_info)){ + case STB_GLOBAL: + case STB_WEAK: + /* no section == undefined */ + if(s->st_shndx == 0) continue; + + TRACE_TYPE(LOOKUP, "%5d FOUND %s in %s (%08x) %d\n", pid, + name, si->name, s->st_value, s->st_size); + return s; + } + } + + return NULL; +} + +static unsigned elfhash(const char *_name) +{ + const unsigned char *name = (const unsigned char *) _name; + unsigned h = 0, g; + + while(*name) { + h = (h << 4) + *name++; + g = h & 0xf0000000; + h ^= g; + h ^= g >> 24; + } + return h; +} + +const char *last_library_used = NULL; + +static Elf32_Sym * +_do_lookup(soinfo *si, const char *name, unsigned *base) +{ + unsigned elf_hash = elfhash(name); + Elf32_Sym *s; + unsigned *d; + soinfo *lsi = si; + int i; + + /* Look for symbols in the local scope (the object who is + * searching). This happens with C++ templates on i386 for some + * reason. + * + * Notes on weak symbols: + * The ELF specs are ambigious about treatment of weak definitions in + * dynamic linking. Some systems return the first definition found + * and some the first non-weak definition. This is system dependent. + * Here we return the first definition found for simplicity. */ + + s = _elf_lookup(si, elf_hash, name); + if(s != NULL) + goto done; + + /* Next, look for it in the preloads list */ + for(i = 0; preloads[i] != NULL; i++) { + lsi = preloads[i]; + s = _elf_lookup(lsi, elf_hash, name); + if(s != NULL) + goto done; + } + + for(d = si->dynamic; *d; d += 2) { + if(d[0] == DT_NEEDED){ + lsi = (soinfo *)d[1]; + if (!validate_soinfo(lsi)) { + DL_ERR("%5d bad DT_NEEDED pointer in %s", + pid, si->name); + return NULL; + } + + DEBUG("%5d %s: looking up %s in %s\n", + pid, si->name, name, lsi->name); + s = _elf_lookup(lsi, elf_hash, name); + if ((s != NULL) && (s->st_shndx != SHN_UNDEF)) + goto done; + } + } + +#if ALLOW_SYMBOLS_FROM_MAIN + /* If we are resolving relocations while dlopen()ing a library, it's OK for + * the library to resolve a symbol that's defined in the executable itself, + * although this is rare and is generally a bad idea. + */ + if (somain) { + lsi = somain; + DEBUG("%5d %s: looking up %s in executable %s\n", + pid, si->name, name, lsi->name); + s = _elf_lookup(lsi, elf_hash, name); + } +#endif + +done: + if(s != NULL) { + TRACE_TYPE(LOOKUP, "%5d si %s sym %s s->st_value = 0x%08x, " + "found in %s, base = 0x%08x\n", + pid, si->name, name, s->st_value, lsi->name, lsi->base); + last_library_used = lsi->name; + *base = lsi->base; + return s; + } + + return NULL; +} + +/* This is used by dl_sym(). It performs symbol lookup only within the + specified soinfo object and not in any of its dependencies. + */ +Elf32_Sym *lookup_in_library(soinfo *si, const char *name) +{ + return _elf_lookup(si, elfhash(name), name); +} + +/* This is used by dl_sym(). It performs a global symbol lookup. + */ +Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start) +{ + unsigned elf_hash = elfhash(name); + Elf32_Sym *s = NULL; + soinfo *si; + + if(start == NULL) { + start = solist; + } + + for(si = start; (s == NULL) && (si != NULL); si = si->next) + { + if(si->flags & FLAG_ERROR) + continue; + s = _elf_lookup(si, elf_hash, name); + if (s != NULL) { + *found = si; + break; + } + } + + if(s != NULL) { + TRACE_TYPE(LOOKUP, "%5d %s s->st_value = 0x%08x, " + "si->base = 0x%08x\n", pid, name, s->st_value, si->base); + return s; + } + + return NULL; +} + +soinfo *find_containing_library(const void *addr) +{ + soinfo *si; + + for(si = solist; si != NULL; si = si->next) + { + if((unsigned)addr >= si->base && (unsigned)addr - si->base < si->size) { + return si; + } + } + + return NULL; +} + +Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si) +{ + unsigned int i; + unsigned soaddr = (unsigned)addr - si->base; + + /* Search the library's symbol table for any defined symbol which + * contains this address */ + for(i=0; inchain; i++) { + Elf32_Sym *sym = &si->symtab[i]; + + if(sym->st_shndx != SHN_UNDEF && + soaddr >= sym->st_value && + soaddr < sym->st_value + sym->st_size) { + return sym; + } + } + + return NULL; +} + +#if 0 +static void dump(soinfo *si) +{ + Elf32_Sym *s = si->symtab; + unsigned n; + + for(n = 0; n < si->nchain; n++) { + TRACE("%5d %04d> %08x: %02x %04x %08x %08x %s\n", pid, n, s, + s->st_info, s->st_shndx, s->st_value, s->st_size, + si->strtab + s->st_name); + s++; + } +} +#endif + +static const char *sopaths[] = { + "/vendor/lib", + "/system/lib", + 0 +}; + +static int _open_lib(const char *name) +{ + int fd; + struct stat filestat; + + if ((stat(name, &filestat) >= 0) && S_ISREG(filestat.st_mode)) { + if ((fd = open(name, O_RDONLY)) >= 0) + return fd; + } + + return -1; +} + +static int open_library(const char *name) +{ + int fd; + char buf[512]; + const char **path; + int n; + + TRACE("[ %5d opening %s ]\n", pid, name); + + if(name == 0) return -1; + if(strlen(name) > 256) return -1; + + if ((name[0] == '/') && ((fd = _open_lib(name)) >= 0)) + return fd; + + if (((fd = _open_lib(name)) >= 0)) + return fd; + + for (path = ldpaths; *path; path++) { + n = format_buffer(buf, sizeof(buf), "%s/%s", *path, name); + if (n < 0 || n >= (int)sizeof(buf)) { + WARN("Ignoring very long library path: %s/%s\n", *path, name); + continue; + } + if ((fd = _open_lib(buf)) >= 0) + return fd; + } + for (path = sopaths; *path; path++) { + n = format_buffer(buf, sizeof(buf), "%s/%s", *path, name); + if (n < 0 || n >= (int)sizeof(buf)) { + WARN("Ignoring very long library path: %s/%s\n", *path, name); + continue; + } + if ((fd = _open_lib(buf)) >= 0) + return fd; + } + + return -1; +} + +/* temporary space for holding the first page of the shared lib + * which contains the elf header (with the pht). */ +static unsigned char __header[PAGE_SIZE]; + +typedef struct { + long mmap_addr; + char tag[4]; /* 'P', 'R', 'E', ' ' */ +} prelink_info_t; + +/* Returns the requested base address if the library is prelinked, + * and 0 otherwise. */ +static unsigned long +is_prelinked(int fd, const char *name) +{ + off_t sz; + prelink_info_t info; + + sz = lseek(fd, -sizeof(prelink_info_t), SEEK_END); + if (sz < 0) { + DL_ERR("lseek() failed!"); + return 0; + } + + if (read(fd, &info, sizeof(info)) != sizeof(info)) { + WARN("Could not read prelink_info_t structure for `%s`\n", name); + return 0; + } + + if (strncmp(info.tag, "PRE ", 4)) { + WARN("`%s` is not a prelinked library\n", name); + return 0; + } + + return (unsigned long)info.mmap_addr; +} + +/* verify_elf_object + * Verifies if the object @ base is a valid ELF object + * + * Args: + * + * Returns: + * 0 on success + * -1 if no valid ELF object is found @ base. + */ +static int +verify_elf_object(void *base, const char *name) +{ + Elf32_Ehdr *hdr = (Elf32_Ehdr *) base; + + if (hdr->e_ident[EI_MAG0] != ELFMAG0) return -1; + if (hdr->e_ident[EI_MAG1] != ELFMAG1) return -1; + if (hdr->e_ident[EI_MAG2] != ELFMAG2) return -1; + if (hdr->e_ident[EI_MAG3] != ELFMAG3) return -1; + + /* TODO: Should we verify anything else in the header? */ +#ifdef ANDROID_ARM_LINKER + if (hdr->e_machine != EM_ARM) return -1; +#elif defined(ANDROID_X86_LINKER) + if (hdr->e_machine != EM_386) return -1; +#endif + return 0; +} + + +/* get_lib_extents + * Retrieves the base (*base) address where the ELF object should be + * mapped and its overall memory size (*total_sz). + * + * Args: + * fd: Opened file descriptor for the library + * name: The name of the library + * _hdr: Pointer to the header page of the library + * total_sz: Total size of the memory that should be allocated for + * this library + * + * Returns: + * -1 if there was an error while trying to get the lib extents. + * The possible reasons are: + * - Could not determine if the library was prelinked. + * - The library provided is not a valid ELF object + * 0 if the library did not request a specific base offset (normal + * for non-prelinked libs) + * > 0 if the library requests a specific address to be mapped to. + * This indicates a pre-linked library. + */ +static unsigned +get_lib_extents(int fd, const char *name, void *__hdr, unsigned *total_sz) +{ + unsigned req_base; + unsigned min_vaddr = 0xffffffff; + unsigned max_vaddr = 0; + unsigned char *_hdr = (unsigned char *)__hdr; + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)_hdr; + Elf32_Phdr *phdr; + int cnt; + + TRACE("[ %5d Computing extents for '%s'. ]\n", pid, name); + if (verify_elf_object(_hdr, name) < 0) { + DL_ERR("%5d - %s is not a valid ELF object", pid, name); + return (unsigned)-1; + } + + req_base = (unsigned) is_prelinked(fd, name); + if (req_base == (unsigned)-1) + return -1; + else if (req_base != 0) { + TRACE("[ %5d - Prelinked library '%s' requesting base @ 0x%08x ]\n", + pid, name, req_base); + } else { + TRACE("[ %5d - Non-prelinked library '%s' found. ]\n", pid, name); + } + + phdr = (Elf32_Phdr *)(_hdr + ehdr->e_phoff); + + /* find the min/max p_vaddrs from all the PT_LOAD segments so we can + * get the range. */ + for (cnt = 0; cnt < ehdr->e_phnum; ++cnt, ++phdr) { + if (phdr->p_type == PT_LOAD) { + if ((phdr->p_vaddr + phdr->p_memsz) > max_vaddr) + max_vaddr = phdr->p_vaddr + phdr->p_memsz; + if (phdr->p_vaddr < min_vaddr) + min_vaddr = phdr->p_vaddr; + } + } + + if ((min_vaddr == 0xffffffff) && (max_vaddr == 0)) { + DL_ERR("%5d - No loadable segments found in %s.", pid, name); + return (unsigned)-1; + } + + /* truncate min_vaddr down to page boundary */ + min_vaddr &= ~PAGE_MASK; + + /* round max_vaddr up to the next page */ + max_vaddr = (max_vaddr + PAGE_SIZE - 1) & ~PAGE_MASK; + + *total_sz = (max_vaddr - min_vaddr); + return (unsigned)req_base; +} + +/* reserve_mem_region + * + * This function reserves a chunk of memory to be used for mapping in + * a prelinked shared library. We reserve the entire memory region here, and + * then the rest of the linker will relocate the individual loadable + * segments into the correct locations within this memory range. + * + * Args: + * si->base: The requested base of the allocation. + * si->size: The size of the allocation. + * + * Returns: + * -1 on failure, and 0 on success. On success, si->base will contain + * the virtual address at which the library will be mapped. + */ + +static int reserve_mem_region(soinfo *si) +{ + void *base = mmap((void *)si->base, si->size, PROT_NONE, + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (base == MAP_FAILED) { + DL_ERR("%5d can NOT map (%sprelinked) library '%s' at 0x%08x " + "as requested, will try general pool: %d (%s)", + pid, (si->base ? "" : "non-"), si->name, si->base, + errno, strerror(errno)); + return -1; + } else if (base != (void *)si->base) { + DL_ERR("OOPS: %5d %sprelinked library '%s' mapped at 0x%08x, " + "not at 0x%08x", pid, (si->base ? "" : "non-"), + si->name, (unsigned)base, si->base); + munmap(base, si->size); + return -1; + } + return 0; +} + +static int alloc_mem_region(soinfo *si) +{ + if (si->base) { + /* Attempt to mmap a prelinked library. */ + return reserve_mem_region(si); + } + + /* This is not a prelinked library, so we use the kernel's default + allocator. + */ + + void *base = mmap(NULL, si->size, PROT_NONE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (base == MAP_FAILED) { + DL_ERR("%5d mmap of library '%s' failed: %d (%s)\n", + pid, si->name, + errno, strerror(errno)); + goto err; + } + si->base = (unsigned) base; + PRINT("%5d mapped library '%s' to %08x via kernel allocator.\n", + pid, si->name, si->base); + return 0; + +err: + DL_ERR("OOPS: %5d cannot map library '%s'. no vspace available.", + pid, si->name); + return -1; +} + +#define MAYBE_MAP_FLAG(x,from,to) (((x) & (from)) ? (to) : 0) +#define PFLAGS_TO_PROT(x) (MAYBE_MAP_FLAG((x), PF_X, PROT_EXEC) | \ + MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \ + MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE)) +/* load_segments + * + * This function loads all the loadable (PT_LOAD) segments into memory + * at their appropriate memory offsets off the base address. + * + * Args: + * fd: Open file descriptor to the library to load. + * header: Pointer to a header page that contains the ELF header. + * This is needed since we haven't mapped in the real file yet. + * si: ptr to soinfo struct describing the shared object. + * + * Returns: + * 0 on success, -1 on failure. + */ +static int +load_segments(int fd, void *header, soinfo *si) +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)header; + Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned char *)header + ehdr->e_phoff); + Elf32_Addr base = (Elf32_Addr) si->base; + int cnt; + unsigned len; + Elf32_Addr tmp; + unsigned char *pbase; + unsigned char *extra_base; + unsigned extra_len; + unsigned total_sz = 0; + + si->wrprotect_start = 0xffffffff; + si->wrprotect_end = 0; + + TRACE("[ %5d - Begin loading segments for '%s' @ 0x%08x ]\n", + pid, si->name, (unsigned)si->base); + /* Now go through all the PT_LOAD segments and map them into memory + * at the appropriate locations. */ + for (cnt = 0; cnt < ehdr->e_phnum; ++cnt, ++phdr) { + if (phdr->p_type == PT_LOAD) { + DEBUG_DUMP_PHDR(phdr, "PT_LOAD", pid); + /* we want to map in the segment on a page boundary */ + tmp = base + (phdr->p_vaddr & (~PAGE_MASK)); + /* add the # of bytes we masked off above to the total length. */ + len = phdr->p_filesz + (phdr->p_vaddr & PAGE_MASK); + + TRACE("[ %d - Trying to load segment from '%s' @ 0x%08x " + "(0x%08x). p_vaddr=0x%08x p_offset=0x%08x ]\n", pid, si->name, + (unsigned)tmp, len, phdr->p_vaddr, phdr->p_offset); + pbase = mmap((void *)tmp, len, PFLAGS_TO_PROT(phdr->p_flags), + MAP_PRIVATE | MAP_FIXED, fd, + phdr->p_offset & (~PAGE_MASK)); + if (pbase == MAP_FAILED) { + DL_ERR("%d failed to map segment from '%s' @ 0x%08x (0x%08x). " + "p_vaddr=0x%08x p_offset=0x%08x", pid, si->name, + (unsigned)tmp, len, phdr->p_vaddr, phdr->p_offset); + goto fail; + } + + /* If 'len' didn't end on page boundary, and it's a writable + * segment, zero-fill the rest. */ + if ((len & PAGE_MASK) && (phdr->p_flags & PF_W)) + memset((void *)(pbase + len), 0, PAGE_SIZE - (len & PAGE_MASK)); + + /* Check to see if we need to extend the map for this segment to + * cover the diff between filesz and memsz (i.e. for bss). + * + * base _+---------------------+ page boundary + * . . + * | | + * . . + * pbase _+---------------------+ page boundary + * | | + * . . + * base + p_vaddr _| | + * . \ \ . + * . | filesz | . + * pbase + len _| / | | + * <0 pad> . . . + * extra_base _+------------|--------+ page boundary + * / . . . + * | . . . + * | +------------|--------+ page boundary + * extra_len-> | | | | + * | . | memsz . + * | . | . + * \ _| / | + * . . + * | | + * _+---------------------+ page boundary + */ + tmp = (Elf32_Addr)(((unsigned)pbase + len + PAGE_SIZE - 1) & + (~PAGE_MASK)); + if (tmp < (base + phdr->p_vaddr + phdr->p_memsz)) { + extra_len = base + phdr->p_vaddr + phdr->p_memsz - tmp; + TRACE("[ %5d - Need to extend segment from '%s' @ 0x%08x " + "(0x%08x) ]\n", pid, si->name, (unsigned)tmp, extra_len); + /* map in the extra page(s) as anonymous into the range. + * This is probably not necessary as we already mapped in + * the entire region previously, but we just want to be + * sure. This will also set the right flags on the region + * (though we can probably accomplish the same thing with + * mprotect). + */ + extra_base = mmap((void *)tmp, extra_len, + PFLAGS_TO_PROT(phdr->p_flags), + MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, + -1, 0); + if (extra_base == MAP_FAILED) { + DL_ERR("[ %5d - failed to extend segment from '%s' @ 0x%08x" + " (0x%08x) ]", pid, si->name, (unsigned)tmp, + extra_len); + goto fail; + } + /* TODO: Check if we need to memset-0 this region. + * Anonymous mappings are zero-filled copy-on-writes, so we + * shouldn't need to. */ + TRACE("[ %5d - Segment from '%s' extended @ 0x%08x " + "(0x%08x)\n", pid, si->name, (unsigned)extra_base, + extra_len); + } + /* set the len here to show the full extent of the segment we + * just loaded, mostly for debugging */ + len = (((unsigned)base + phdr->p_vaddr + phdr->p_memsz + + PAGE_SIZE - 1) & (~PAGE_MASK)) - (unsigned)pbase; + TRACE("[ %5d - Successfully loaded segment from '%s' @ 0x%08x " + "(0x%08x). p_vaddr=0x%08x p_offset=0x%08x\n", pid, si->name, + (unsigned)pbase, len, phdr->p_vaddr, phdr->p_offset); + total_sz += len; + /* Make the section writable just in case we'll have to write to + * it during relocation (i.e. text segment). However, we will + * remember what range of addresses should be write protected. + * + */ + if (!(phdr->p_flags & PF_W)) { + if ((unsigned)pbase < si->wrprotect_start) + si->wrprotect_start = (unsigned)pbase; + if (((unsigned)pbase + len) > si->wrprotect_end) + si->wrprotect_end = (unsigned)pbase + len; + mprotect(pbase, len, + PFLAGS_TO_PROT(phdr->p_flags) | PROT_WRITE); + } + } else if (phdr->p_type == PT_DYNAMIC) { + DEBUG_DUMP_PHDR(phdr, "PT_DYNAMIC", pid); + /* this segment contains the dynamic linking information */ + si->dynamic = (unsigned *)(base + phdr->p_vaddr); + } else if (phdr->p_type == PT_GNU_RELRO) { + if ((phdr->p_vaddr >= si->size) + || ((phdr->p_vaddr + phdr->p_memsz) > si->size) + || ((base + phdr->p_vaddr + phdr->p_memsz) < base)) { + DL_ERR("%d invalid GNU_RELRO in '%s' " + "p_vaddr=0x%08x p_memsz=0x%08x", pid, si->name, + phdr->p_vaddr, phdr->p_memsz); + goto fail; + } + si->gnu_relro_start = (Elf32_Addr) (base + phdr->p_vaddr); + si->gnu_relro_len = (unsigned) phdr->p_memsz; + } else { +#ifdef ANDROID_ARM_LINKER + if (phdr->p_type == PT_ARM_EXIDX) { + DEBUG_DUMP_PHDR(phdr, "PT_ARM_EXIDX", pid); + /* exidx entries (used for stack unwinding) are 8 bytes each. + */ + si->ARM_exidx = (unsigned *)phdr->p_vaddr; + si->ARM_exidx_count = phdr->p_memsz / 8; + } +#endif + } + + } + + /* Sanity check */ + if (total_sz > si->size) { + DL_ERR("%5d - Total length (0x%08x) of mapped segments from '%s' is " + "greater than what was allocated (0x%08x). THIS IS BAD!", + pid, total_sz, si->name, si->size); + goto fail; + } + + TRACE("[ %5d - Finish loading segments for '%s' @ 0x%08x. " + "Total memory footprint: 0x%08x bytes ]\n", pid, si->name, + (unsigned)si->base, si->size); + return 0; + +fail: + /* We can just blindly unmap the entire region even though some things + * were mapped in originally with anonymous and others could have been + * been mapped in from the file before we failed. The kernel will unmap + * all the pages in the range, irrespective of how they got there. + */ + munmap((void *)si->base, si->size); + si->flags |= FLAG_ERROR; + return -1; +} + +/* TODO: Implement this to take care of the fact that Android ARM + * ELF objects shove everything into a single loadable segment that has the + * write bit set. wr_offset is then used to set non-(data|bss) pages to be + * non-writable. + */ +#if 0 +static unsigned +get_wr_offset(int fd, const char *name, Elf32_Ehdr *ehdr) +{ + Elf32_Shdr *shdr_start; + Elf32_Shdr *shdr; + int shdr_sz = ehdr->e_shnum * sizeof(Elf32_Shdr); + int cnt; + unsigned wr_offset = 0xffffffff; + + shdr_start = mmap(0, shdr_sz, PROT_READ, MAP_PRIVATE, fd, + ehdr->e_shoff & (~PAGE_MASK)); + if (shdr_start == MAP_FAILED) { + WARN("%5d - Could not read section header info from '%s'. Will not " + "not be able to determine write-protect offset.\n", pid, name); + return (unsigned)-1; + } + + for(cnt = 0, shdr = shdr_start; cnt < ehdr->e_shnum; ++cnt, ++shdr) { + if ((shdr->sh_type != SHT_NULL) && (shdr->sh_flags & SHF_WRITE) && + (shdr->sh_addr < wr_offset)) { + wr_offset = shdr->sh_addr; + } + } + + munmap(shdr_start, shdr_sz); + return wr_offset; +} +#endif + +static soinfo * +load_library(const char *name) +{ + int fd = open_library(name); + int cnt; + unsigned ext_sz; + unsigned req_base; + const char *bname; + soinfo *si = NULL; + Elf32_Ehdr *hdr; + + if(fd == -1) { + DL_ERR("Library '%s' not found", name); + return NULL; + } + + /* We have to read the ELF header to figure out what to do with this image + */ + if (lseek(fd, 0, SEEK_SET) < 0) { + DL_ERR("lseek() failed!"); + goto fail; + } + + if ((cnt = read(fd, &__header[0], PAGE_SIZE)) < 0) { + DL_ERR("read() failed!"); + goto fail; + } + + /* Parse the ELF header and get the size of the memory footprint for + * the library */ + req_base = get_lib_extents(fd, name, &__header[0], &ext_sz); + if (req_base == (unsigned)-1) + goto fail; + TRACE("[ %5d - '%s' (%s) wants base=0x%08x sz=0x%08x ]\n", pid, name, + (req_base ? "prelinked" : "not pre-linked"), req_base, ext_sz); + + /* Now configure the soinfo struct where we'll store all of our data + * for the ELF object. If the loading fails, we waste the entry, but + * same thing would happen if we failed during linking. Configuring the + * soinfo struct here is a lot more convenient. + */ + bname = strrchr(name, '/'); + si = alloc_info(bname ? bname + 1 : name); + if (si == NULL) + goto fail; + + /* Carve out a chunk of memory where we will map in the individual + * segments */ + si->base = req_base; + si->size = ext_sz; + si->flags = 0; + si->entry = 0; + si->dynamic = (unsigned *)-1; + if (alloc_mem_region(si) < 0) + goto fail; + + TRACE("[ %5d allocated memory for %s @ %p (0x%08x) ]\n", + pid, name, (void *)si->base, (unsigned) ext_sz); + + /* Now actually load the library's segments into right places in memory */ + if (load_segments(fd, &__header[0], si) < 0) { + goto fail; + } + + /* this might not be right. Technically, we don't even need this info + * once we go through 'load_segments'. */ + hdr = (Elf32_Ehdr *)si->base; + si->phdr = (Elf32_Phdr *)((unsigned char *)si->base + hdr->e_phoff); + si->phnum = hdr->e_phnum; + /**/ + + close(fd); + return si; + +fail: + if (si) free_info(si); + close(fd); + return NULL; +} + +static soinfo * +init_library(soinfo *si) +{ + unsigned wr_offset = 0xffffffff; + + /* At this point we know that whatever is loaded @ base is a valid ELF + * shared library whose segments are properly mapped in. */ + TRACE("[ %5d init_library base=0x%08x sz=0x%08x name='%s') ]\n", + pid, si->base, si->size, si->name); + + if(link_image(si, wr_offset)) { + /* We failed to link. However, we can only restore libbase + ** if no additional libraries have moved it since we updated it. + */ + munmap((void *)si->base, si->size); + return NULL; + } + + return si; +} + +soinfo *find_library(const char *name) +{ + soinfo *si; + const char *bname; + +#if ALLOW_SYMBOLS_FROM_MAIN + if (name == NULL) + return somain; +#else + if (name == NULL) + return NULL; +#endif + + bname = strrchr(name, '/'); + bname = bname ? bname + 1 : name; + + for(si = solist; si != 0; si = si->next){ + if(!strcmp(bname, si->name)) { + if(si->flags & FLAG_ERROR) { + DL_ERR("%5d '%s' failed to load previously", pid, bname); + return NULL; + } + if(si->flags & FLAG_LINKED) return si; + DL_ERR("OOPS: %5d recursive link to '%s'", pid, si->name); + return NULL; + } + } + + TRACE("[ %5d '%s' has not been loaded yet. Locating...]\n", pid, name); + si = load_library(name); + if(si == NULL) + return NULL; + return init_library(si); +} + +/* TODO: + * notify gdb of unload + * for non-prelinked libraries, find a way to decrement libbase + */ +static void call_destructors(soinfo *si); +unsigned unload_library(soinfo *si) +{ + unsigned *d; + if (si->refcount == 1) { + TRACE("%5d unloading '%s'\n", pid, si->name); + call_destructors(si); + + /* + * Make sure that we undo the PT_GNU_RELRO protections we added + * in link_image. This is needed to undo the DT_NEEDED hack below. + */ + if ((si->gnu_relro_start != 0) && (si->gnu_relro_len != 0)) { + Elf32_Addr start = (si->gnu_relro_start & ~PAGE_MASK); + unsigned len = (si->gnu_relro_start - start) + si->gnu_relro_len; + if (mprotect((void *) start, len, PROT_READ | PROT_WRITE) < 0) + DL_ERR("%5d %s: could not undo GNU_RELRO protections. " + "Expect a crash soon. errno=%d (%s)", + pid, si->name, errno, strerror(errno)); + + } + + for(d = si->dynamic; *d; d += 2) { + if(d[0] == DT_NEEDED){ + soinfo *lsi = (soinfo *)d[1]; + + // The next line will segfault if the we don't undo the + // PT_GNU_RELRO protections (see comments above and in + // link_image(). + d[1] = 0; + + if (validate_soinfo(lsi)) { + TRACE("%5d %s needs to unload %s\n", pid, + si->name, lsi->name); + unload_library(lsi); + } + else + DL_ERR("%5d %s: could not unload dependent library", + pid, si->name); + } + } + + munmap((char *)si->base, si->size); + notify_gdb_of_unload(si); + free_info(si); + si->refcount = 0; + } + else { + si->refcount--; + PRINT("%5d not unloading '%s', decrementing refcount to %d\n", + pid, si->name, si->refcount); + } + return si->refcount; +} + +/* TODO: don't use unsigned for addrs below. It works, but is not + * ideal. They should probably be either uint32_t, Elf32_Addr, or unsigned + * long. + */ +static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) +{ + Elf32_Sym *symtab = si->symtab; + const char *strtab = si->strtab; + Elf32_Sym *s; + unsigned base; + Elf32_Rel *start = rel; + unsigned idx; + + for (idx = 0; idx < count; ++idx) { + unsigned type = ELF32_R_TYPE(rel->r_info); + unsigned sym = ELF32_R_SYM(rel->r_info); + unsigned reloc = (unsigned)(rel->r_offset + si->base); + unsigned sym_addr = 0; + char *sym_name = NULL; + + DEBUG("%5d Processing '%s' relocation at index %d\n", pid, + si->name, idx); + if(sym != 0) { + sym_name = (char *)(strtab + symtab[sym].st_name); + sym_addr = 0; + if ((sym_addr = (unsigned)get_hooked_symbol(sym_name)) != 0) { + LINKER_DEBUG_PRINTF("%s hooked symbol %s to %x\n", si->name, sym_name, sym_addr); + } + else + { + s = _do_lookup(si, sym_name, &base); + } + if(sym_addr != 0) + { + } else + if(s == NULL) { + /* We only allow an undefined symbol if this is a weak + reference.. */ + s = &symtab[sym]; + if (ELF32_ST_BIND(s->st_info) != STB_WEAK) { + DL_ERR("%5d cannot locate '%s'...\n", pid, sym_name); + return -1; + } + + /* IHI0044C AAELF 4.5.1.1: + + Libraries are not searched to resolve weak references. + It is not an error for a weak reference to remain + unsatisfied. + + During linking, the value of an undefined weak reference is: + - Zero if the relocation type is absolute + - The address of the place if the relocation is pc-relative + - The address of nominial base address if the relocation + type is base-relative. + */ + + switch (type) { +#if defined(ANDROID_ARM_LINKER) + case R_ARM_JUMP_SLOT: + case R_ARM_GLOB_DAT: + case R_ARM_ABS32: + case R_ARM_RELATIVE: /* Don't care. */ + case R_ARM_NONE: /* Don't care. */ +#elif defined(ANDROID_X86_LINKER) + case R_386_JUMP_SLOT: + case R_386_GLOB_DAT: + case R_386_32: + case R_386_RELATIVE: /* Dont' care. */ +#endif /* ANDROID_*_LINKER */ + /* sym_addr was initialized to be zero above or relocation + code below does not care about value of sym_addr. + No need to do anything. */ + break; + +#if defined(ANDROID_X86_LINKER) + case R_386_PC32: + sym_addr = reloc; + break; +#endif /* ANDROID_X86_LINKER */ + +#if defined(ANDROID_ARM_LINKER) + case R_ARM_COPY: + /* Fall through. Can't really copy if weak symbol is + not found in run-time. */ +#endif /* ANDROID_ARM_LINKER */ + default: + DL_ERR("%5d unknown weak reloc type %d @ %p (%d)\n", + pid, type, rel, (int) (rel - start)); + return -1; + } + } else { + /* We got a definition. */ +#if 0 + if((base == 0) && (si->base != 0)){ + /* linking from libraries to main image is bad */ + DL_ERR("%5d cannot locate '%s'...", + pid, strtab + symtab[sym].st_name); + return -1; + } +#endif + sym_addr = (unsigned)(s->st_value + base); + LINKER_DEBUG_PRINTF("%s symbol (from %s) %s to %x\n", si->name, last_library_used, sym_name, sym_addr); + } + COUNT_RELOC(RELOC_SYMBOL); + } else { + s = NULL; + } + +/* TODO: This is ugly. Split up the relocations by arch into + * different files. + */ + switch(type){ +#if defined(ANDROID_ARM_LINKER) + case R_ARM_JUMP_SLOT: + COUNT_RELOC(RELOC_ABSOLUTE); + MARK(rel->r_offset); + TRACE_TYPE(RELO, "%5d RELO JMP_SLOT %08x <- %08x %s\n", pid, + reloc, sym_addr, sym_name); + *((unsigned*)reloc) = sym_addr; + break; + case R_ARM_GLOB_DAT: + COUNT_RELOC(RELOC_ABSOLUTE); + MARK(rel->r_offset); + TRACE_TYPE(RELO, "%5d RELO GLOB_DAT %08x <- %08x %s\n", pid, + reloc, sym_addr, sym_name); + *((unsigned*)reloc) = sym_addr; + break; + case R_ARM_ABS32: + COUNT_RELOC(RELOC_ABSOLUTE); + MARK(rel->r_offset); + TRACE_TYPE(RELO, "%5d RELO ABS %08x <- %08x %s\n", pid, + reloc, sym_addr, sym_name); + *((unsigned*)reloc) += sym_addr; + break; + case R_ARM_REL32: + COUNT_RELOC(RELOC_RELATIVE); + MARK(rel->r_offset); + TRACE_TYPE(RELO, "%5d RELO REL32 %08x <- %08x - %08x %s\n", pid, + reloc, sym_addr, rel->r_offset, sym_name); + *((unsigned*)reloc) += sym_addr - rel->r_offset; + break; +#elif defined(ANDROID_X86_LINKER) + case R_386_JUMP_SLOT: + COUNT_RELOC(RELOC_ABSOLUTE); + MARK(rel->r_offset); + TRACE_TYPE(RELO, "%5d RELO JMP_SLOT %08x <- %08x %s\n", pid, + reloc, sym_addr, sym_name); + *((unsigned*)reloc) = sym_addr; + break; + case R_386_GLOB_DAT: + COUNT_RELOC(RELOC_ABSOLUTE); + MARK(rel->r_offset); + TRACE_TYPE(RELO, "%5d RELO GLOB_DAT %08x <- %08x %s\n", pid, + reloc, sym_addr, sym_name); + *((unsigned*)reloc) = sym_addr; + break; +#endif /* ANDROID_*_LINKER */ + +#if defined(ANDROID_ARM_LINKER) + case R_ARM_RELATIVE: +#elif defined(ANDROID_X86_LINKER) + case R_386_RELATIVE: +#endif /* ANDROID_*_LINKER */ + COUNT_RELOC(RELOC_RELATIVE); + MARK(rel->r_offset); + if(sym){ + DL_ERR("%5d odd RELATIVE form...", pid); + return -1; + } + TRACE_TYPE(RELO, "%5d RELO RELATIVE %08x <- +%08x\n", pid, + reloc, si->base); + *((unsigned*)reloc) += si->base; + break; + +#if defined(ANDROID_X86_LINKER) + case R_386_32: + COUNT_RELOC(RELOC_RELATIVE); + MARK(rel->r_offset); + + TRACE_TYPE(RELO, "%5d RELO R_386_32 %08x <- +%08x %s\n", pid, + reloc, sym_addr, sym_name); + *((unsigned *)reloc) += (unsigned)sym_addr; + break; + + case R_386_PC32: + COUNT_RELOC(RELOC_RELATIVE); + MARK(rel->r_offset); + TRACE_TYPE(RELO, "%5d RELO R_386_PC32 %08x <- " + "+%08x (%08x - %08x) %s\n", pid, reloc, + (sym_addr - reloc), sym_addr, reloc, sym_name); + *((unsigned *)reloc) += (unsigned)(sym_addr - reloc); + break; +#endif /* ANDROID_X86_LINKER */ + +#ifdef ANDROID_ARM_LINKER + case R_ARM_COPY: + COUNT_RELOC(RELOC_COPY); + MARK(rel->r_offset); + TRACE_TYPE(RELO, "%5d RELO %08x <- %d @ %08x %s\n", pid, + reloc, s->st_size, sym_addr, sym_name); + memcpy((void*)reloc, (void*)sym_addr, s->st_size); + break; + case R_ARM_NONE: + break; +#endif /* ANDROID_ARM_LINKER */ + + default: + DL_ERR("%5d unknown reloc type %d @ %p (%d)", + pid, type, rel, (int) (rel - start)); + return -1; + } + rel++; + } + return 0; +} + +/* Please read the "Initialization and Termination functions" functions. + * of the linker design note in bionic/linker/README.TXT to understand + * what the following code is doing. + * + * The important things to remember are: + * + * DT_PREINIT_ARRAY must be called first for executables, and should + * not appear in shared libraries. + * + * DT_INIT should be called before DT_INIT_ARRAY if both are present + * + * DT_FINI should be called after DT_FINI_ARRAY if both are present + * + * DT_FINI_ARRAY must be parsed in reverse order. + */ + +static void call_array(unsigned *ctor, int count, int reverse) +{ + int n, inc = 1; + + if (reverse) { + ctor += (count-1); + inc = -1; + } + + for(n = count; n > 0; n--) { + TRACE("[ %5d Looking at %s *0x%08x == 0x%08x ]\n", pid, + reverse ? "dtor" : "ctor", + (unsigned)ctor, (unsigned)*ctor); + void (*func)() = (void (*)()) *ctor; + ctor += inc; + if(((int) func == 0) || ((int) func == -1)) continue; + TRACE("[ %5d Calling func @ 0x%08x ]\n", pid, (unsigned)func); + func(); + } +} + +void call_constructors_recursive(soinfo *si) +{ + if (si->constructors_called) + return; + if (strcmp(si->name, "libc.so") == 0) + return; + // Set this before actually calling the constructors, otherwise it doesn't + // protect against recursive constructor calls. One simple example of + // constructor recursion is the libc debug malloc, which is implemented in + // libc_malloc_debug_leak.so: + // 1. The program depends on libc, so libc's constructor is called here. + // 2. The libc constructor calls dlopen() to load libc_malloc_debug_leak.so. + // 3. dlopen() calls call_constructors_recursive() with the newly created + // soinfo for libc_malloc_debug_leak.so. + // 4. The debug so depends on libc, so call_constructors_recursive() is + // called again with the libc soinfo. If it doesn't trigger the early- + // out above, the libc constructor will be called again (recursively!). + si->constructors_called = 1; + + if (si->flags & FLAG_EXE) { + TRACE("[ %5d Calling preinit_array @ 0x%08x [%d] for '%s' ]\n", + pid, (unsigned)si->preinit_array, si->preinit_array_count, + si->name); + call_array(si->preinit_array, si->preinit_array_count, 0); + TRACE("[ %5d Done calling preinit_array for '%s' ]\n", pid, si->name); + } else { + if (si->preinit_array) { + DL_ERR("%5d Shared library '%s' has a preinit_array table @ 0x%08x." + " This is INVALID.", pid, si->name, + (unsigned)si->preinit_array); + } + } + + if (si->dynamic) { + unsigned *d; + for(d = si->dynamic; *d; d += 2) { + if(d[0] == DT_NEEDED){ + soinfo* lsi = (soinfo *)d[1]; + if (!validate_soinfo(lsi)) { + DL_ERR("%5d bad DT_NEEDED pointer in %s", + pid, si->name); + } else { + call_constructors_recursive(lsi); + } + } + } + } + + if (si->init_func) { + TRACE("[ %5d Calling init_func @ 0x%08x for '%s' ]\n", pid, + (unsigned)si->init_func, si->name); + si->init_func(); + TRACE("[ %5d Done calling init_func for '%s' ]\n", pid, si->name); + } + + if (si->init_array) { + TRACE("[ %5d Calling init_array @ 0x%08x [%d] for '%s' ]\n", pid, + (unsigned)si->init_array, si->init_array_count, si->name); + call_array(si->init_array, si->init_array_count, 0); + TRACE("[ %5d Done calling init_array for '%s' ]\n", pid, si->name); + } + +} + +static void call_destructors(soinfo *si) +{ + if (si->fini_array) { + TRACE("[ %5d Calling fini_array @ 0x%08x [%d] for '%s' ]\n", pid, + (unsigned)si->fini_array, si->fini_array_count, si->name); + call_array(si->fini_array, si->fini_array_count, 1); + TRACE("[ %5d Done calling fini_array for '%s' ]\n", pid, si->name); + } + + if (si->fini_func) { + TRACE("[ %5d Calling fini_func @ 0x%08x for '%s' ]\n", pid, + (unsigned)si->fini_func, si->name); + si->fini_func(); + TRACE("[ %5d Done calling fini_func for '%s' ]\n", pid, si->name); + } +} + +/* Force any of the closed stdin, stdout and stderr to be associated with + /dev/null. */ +static int nullify_closed_stdio (void) +{ + int dev_null, i, status; + int return_value = 0; + + dev_null = open("/dev/null", O_RDWR); + if (dev_null < 0) { + DL_ERR("Cannot open /dev/null."); + return -1; + } + TRACE("[ %5d Opened /dev/null file-descriptor=%d]\n", pid, dev_null); + + /* If any of the stdio file descriptors is valid and not associated + with /dev/null, dup /dev/null to it. */ + for (i = 0; i < 3; i++) { + /* If it is /dev/null already, we are done. */ + if (i == dev_null) + continue; + + TRACE("[ %5d Nullifying stdio file descriptor %d]\n", pid, i); + /* The man page of fcntl does not say that fcntl(..,F_GETFL) + can be interrupted but we do this just to be safe. */ + do { + status = fcntl(i, F_GETFL); + } while (status < 0 && errno == EINTR); + + /* If file is openned, we are good. */ + if (status >= 0) + continue; + + /* The only error we allow is that the file descriptor does not + exist, in which case we dup /dev/null to it. */ + if (errno != EBADF) { + DL_ERR("nullify_stdio: unhandled error %s", strerror(errno)); + return_value = -1; + continue; + } + + /* Try dupping /dev/null to this stdio file descriptor and + repeat if there is a signal. Note that any errors in closing + the stdio descriptor are lost. */ + do { + status = dup2(dev_null, i); + } while (status < 0 && errno == EINTR); + + if (status < 0) { + DL_ERR("nullify_stdio: dup2 error %s", strerror(errno)); + return_value = -1; + continue; + } + } + + /* If /dev/null is not one of the stdio file descriptors, close it. */ + if (dev_null > 2) { + TRACE("[ %5d Closing /dev/null file-descriptor=%d]\n", pid, dev_null); + do { + status = close(dev_null); + } while (status < 0 && errno == EINTR); + + if (status < 0) { + DL_ERR("nullify_stdio: close error %s", strerror(errno)); + return_value = -1; + } + } + + return return_value; +} + +static int link_image(soinfo *si, unsigned wr_offset) +{ + unsigned *d; + Elf32_Phdr *phdr = si->phdr; + int phnum = si->phnum; + + INFO("[ %5d linking %s ]\n", pid, si->name); + DEBUG("%5d si->base = 0x%08x si->flags = 0x%08x\n", pid, + si->base, si->flags); + + if (si->flags & (FLAG_EXE | FLAG_LINKER)) { + /* Locate the needed program segments (DYNAMIC/ARM_EXIDX) for + * linkage info if this is the executable or the linker itself. + * If this was a dynamic lib, that would have been done at load time. + * + * TODO: It's unfortunate that small pieces of this are + * repeated from the load_library routine. Refactor this just + * slightly to reuse these bits. + */ + si->size = 0; + for(; phnum > 0; --phnum, ++phdr) { +#ifdef ANDROID_ARM_LINKER + if(phdr->p_type == PT_ARM_EXIDX) { + /* exidx entries (used for stack unwinding) are 8 bytes each. + */ + si->ARM_exidx = (unsigned *)phdr->p_vaddr; + si->ARM_exidx_count = phdr->p_memsz / 8; + } +#endif + if (phdr->p_type == PT_LOAD) { + /* For the executable, we use the si->size field only in + dl_unwind_find_exidx(), so the meaning of si->size + is not the size of the executable; it is the distance + between the load location of the executable and the last + address of the loadable part of the executable. + We use the range [si->base, si->base + si->size) to + determine whether a PC value falls within the executable + section. Of course, if a value is between si->base and + (si->base + phdr->p_vaddr), it's not in the executable + section, but a) we shouldn't be asking for such a value + anyway, and b) if we have to provide an EXIDX for such a + value, then the executable's EXIDX is probably the better + choice. + */ + DEBUG_DUMP_PHDR(phdr, "PT_LOAD", pid); + if (phdr->p_vaddr + phdr->p_memsz > si->size) + si->size = phdr->p_vaddr + phdr->p_memsz; + /* try to remember what range of addresses should be write + * protected */ + if (!(phdr->p_flags & PF_W)) { + unsigned _end; + + if (si->base + phdr->p_vaddr < si->wrprotect_start) + si->wrprotect_start = si->base + phdr->p_vaddr; + _end = (((si->base + phdr->p_vaddr + phdr->p_memsz + PAGE_SIZE - 1) & + (~PAGE_MASK))); + if (_end > si->wrprotect_end) + si->wrprotect_end = _end; + /* Make the section writable just in case we'll have to + * write to it during relocation (i.e. text segment). + * However, we will remember what range of addresses + * should be write protected. + */ + mprotect((void *) (si->base + phdr->p_vaddr), + phdr->p_memsz, + PFLAGS_TO_PROT(phdr->p_flags) | PROT_WRITE); + } + } else if (phdr->p_type == PT_DYNAMIC) { + if (si->dynamic != (unsigned *)-1) { + DL_ERR("%5d multiple PT_DYNAMIC segments found in '%s'. " + "Segment at 0x%08x, previously one found at 0x%08x", + pid, si->name, si->base + phdr->p_vaddr, + (unsigned)si->dynamic); + goto fail; + } + DEBUG_DUMP_PHDR(phdr, "PT_DYNAMIC", pid); + si->dynamic = (unsigned *) (si->base + phdr->p_vaddr); + } else if (phdr->p_type == PT_GNU_RELRO) { + if ((phdr->p_vaddr >= si->size) + || ((phdr->p_vaddr + phdr->p_memsz) > si->size) + || ((si->base + phdr->p_vaddr + phdr->p_memsz) < si->base)) { + DL_ERR("%d invalid GNU_RELRO in '%s' " + "p_vaddr=0x%08x p_memsz=0x%08x", pid, si->name, + phdr->p_vaddr, phdr->p_memsz); + goto fail; + } + si->gnu_relro_start = (Elf32_Addr) (si->base + phdr->p_vaddr); + si->gnu_relro_len = (unsigned) phdr->p_memsz; + } + } + } + + if (si->dynamic == (unsigned *)-1) { + DL_ERR("%5d missing PT_DYNAMIC?!", pid); + goto fail; + } + + DEBUG("%5d dynamic = %p\n", pid, si->dynamic); + + /* extract useful information from dynamic section */ + for(d = si->dynamic; *d; d++){ + DEBUG("%5d d = %p, d[0] = 0x%08x d[1] = 0x%08x\n", pid, d, d[0], d[1]); + switch(*d++){ + case DT_HASH: + si->nbucket = ((unsigned *) (si->base + *d))[0]; + si->nchain = ((unsigned *) (si->base + *d))[1]; + si->bucket = (unsigned *) (si->base + *d + 8); + si->chain = (unsigned *) (si->base + *d + 8 + si->nbucket * 4); + break; + case DT_STRTAB: + si->strtab = (const char *) (si->base + *d); + break; + case DT_SYMTAB: + si->symtab = (Elf32_Sym *) (si->base + *d); + break; + case DT_PLTREL: + if(*d != DT_REL) { + DL_ERR("DT_RELA not supported"); + goto fail; + } + break; + case DT_JMPREL: + si->plt_rel = (Elf32_Rel*) (si->base + *d); + break; + case DT_PLTRELSZ: + si->plt_rel_count = *d / 8; + break; + case DT_REL: + si->rel = (Elf32_Rel*) (si->base + *d); + break; + case DT_RELSZ: + si->rel_count = *d / 8; + break; + case DT_PLTGOT: + /* Save this in case we decide to do lazy binding. We don't yet. */ + si->plt_got = (unsigned *)(si->base + *d); + break; + case DT_DEBUG: + // Set the DT_DEBUG entry to the addres of _r_debug for GDB + *d = (int) &_r_debug; + break; + case DT_RELA: + DL_ERR("%5d DT_RELA not supported", pid); + goto fail; + case DT_INIT: + si->init_func = (void (*)(void))(si->base + *d); + DEBUG("%5d %s constructors (init func) found at %p\n", + pid, si->name, si->init_func); + break; + case DT_FINI: + si->fini_func = (void (*)(void))(si->base + *d); + DEBUG("%5d %s destructors (fini func) found at %p\n", + pid, si->name, si->fini_func); + break; + case DT_INIT_ARRAY: + si->init_array = (unsigned *)(si->base + *d); + DEBUG("%5d %s constructors (init_array) found at %p\n", + pid, si->name, si->init_array); + break; + case DT_INIT_ARRAYSZ: + si->init_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); + break; + case DT_FINI_ARRAY: + si->fini_array = (unsigned *)(si->base + *d); + DEBUG("%5d %s destructors (fini_array) found at %p\n", + pid, si->name, si->fini_array); + break; + case DT_FINI_ARRAYSZ: + si->fini_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); + break; + case DT_PREINIT_ARRAY: + si->preinit_array = (unsigned *)(si->base + *d); + DEBUG("%5d %s constructors (preinit_array) found at %p\n", + pid, si->name, si->preinit_array); + break; + case DT_PREINIT_ARRAYSZ: + si->preinit_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); + break; + case DT_TEXTREL: + /* TODO: make use of this. */ + /* this means that we might have to write into where the text + * segment was loaded during relocation... Do something with + * it. + */ + DEBUG("%5d Text segment should be writable during relocation.\n", + pid); + break; + } + } + + DEBUG("%5d si->base = 0x%08x, si->strtab = %p, si->symtab = %p\n", + pid, si->base, si->strtab, si->symtab); + + if((si->strtab == 0) || (si->symtab == 0)) { + DL_ERR("%5d missing essential tables", pid); + goto fail; + } + + /* if this is the main executable, then load all of the preloads now */ + if(si->flags & FLAG_EXE) { + int i; + memset(preloads, 0, sizeof(preloads)); + for(i = 0; ldpreload_names[i] != NULL; i++) { + soinfo *lsi = find_library(ldpreload_names[i]); + if(lsi == 0) { + strlcpy(tmp_err_buf, linker_get_error(), sizeof(tmp_err_buf)); + DL_ERR("%5d could not load needed library '%s' for '%s' (%s)", + pid, ldpreload_names[i], si->name, tmp_err_buf); + goto fail; + } + lsi->refcount++; + preloads[i] = lsi; + } + } + + for(d = si->dynamic; *d; d += 2) { + if(d[0] == DT_NEEDED){ + DEBUG("%5d %s needs %s\n", pid, si->name, si->strtab + d[1]); + soinfo *lsi = find_library(si->strtab + d[1]); + if(lsi == 0) { + /** + * XXX Dirty Hack Alarm --thp XXX + * + * For libraries that are not found, simply use libdl's soinfo, + * in order to not break downstream users of the library while + * still allowing the application to start up. + **/ + lsi = &libdl_info; + //strlcpy(tmp_err_buf, linker_get_error(), sizeof(tmp_err_buf)); + //DL_ERR("%5d could not load needed library '%s' for '%s' (%s)", + // pid, si->strtab + d[1], si->name, tmp_err_buf); + //continue; + //goto fail; + } + /* Save the soinfo of the loaded DT_NEEDED library in the payload + of the DT_NEEDED entry itself, so that we can retrieve the + soinfo directly later from the dynamic segment. This is a hack, + but it allows us to map from DT_NEEDED to soinfo efficiently + later on when we resolve relocations, trying to look up a symbol + with dlsym(). + */ + d[1] = (unsigned)lsi; + lsi->refcount++; + } + } + + if(si->plt_rel) { + DEBUG("[ %5d relocating %s plt ]\n", pid, si->name ); + if(reloc_library(si, si->plt_rel, si->plt_rel_count)) + goto fail; + } + if(si->rel) { + DEBUG("[ %5d relocating %s ]\n", pid, si->name ); + if(reloc_library(si, si->rel, si->rel_count)) + goto fail; + } + + si->flags |= FLAG_LINKED; + DEBUG("[ %5d finished linking %s ]\n", pid, si->name); + +#if 0 + /* This is the way that the old dynamic linker did protection of + * non-writable areas. It would scan section headers and find where + * .text ended (rather where .data/.bss began) and assume that this is + * the upper range of the non-writable area. This is too coarse, + * and is kept here for reference until we fully move away from single + * segment elf objects. See the code in get_wr_offset (also #if'd 0) + * that made this possible. + */ + if(wr_offset < 0xffffffff){ + mprotect((void*) si->base, wr_offset, PROT_READ | PROT_EXEC); + } +#else + /* TODO: Verify that this does the right thing in all cases, as it + * presently probably does not. It is possible that an ELF image will + * come with multiple read-only segments. What we ought to do is scan + * the program headers again and mprotect all the read-only segments. + * To prevent re-scanning the program header, we would have to build a + * list of loadable segments in si, and then scan that instead. */ + if (si->wrprotect_start != 0xffffffff && si->wrprotect_end != 0) { + mprotect((void *)si->wrprotect_start, + si->wrprotect_end - si->wrprotect_start, + PROT_READ | PROT_EXEC); + } +#endif + + if (si->gnu_relro_start != 0 && si->gnu_relro_len != 0) { + Elf32_Addr start = (si->gnu_relro_start & ~PAGE_MASK); + unsigned len = (si->gnu_relro_start - start) + si->gnu_relro_len; + if (mprotect((void *) start, len, PROT_READ) < 0) { + DL_ERR("%5d GNU_RELRO mprotect of library '%s' failed: %d (%s)\n", + pid, si->name, errno, strerror(errno)); + goto fail; + } + } + + /* If this is a SET?ID program, dup /dev/null to opened stdin, + stdout and stderr to close a security hole described in: + + ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-02:23.stdio.asc + + */ + if (program_is_setuid) + nullify_closed_stdio (); + notify_gdb_of_load(si); + return 0; + +fail: + ERROR("failed to link %s\n", si->name); + si->flags |= FLAG_ERROR; + return -1; +} + +static void parse_library_path(const char *path, char *delim) +{ + size_t len; + char *ldpaths_bufp = ldpaths_buf; + int i = 0; + + len = strlcpy(ldpaths_buf, path, sizeof(ldpaths_buf)); + + while (i < LDPATH_MAX && (ldpaths[i] = strsep(&ldpaths_bufp, delim))) { + if (*ldpaths[i] != '\0') + ++i; + } + + /* Forget the last path if we had to truncate; this occurs if the 2nd to + * last char isn't '\0' (i.e. not originally a delim). */ + if (i > 0 && len >= sizeof(ldpaths_buf) && + ldpaths_buf[sizeof(ldpaths_buf) - 2] != '\0') { + ldpaths[i - 1] = NULL; + } else { + ldpaths[i] = NULL; + } +} + +static void parse_preloads(const char *path, char *delim) +{ + size_t len; + char *ldpreloads_bufp = ldpreloads_buf; + int i = 0; + + len = strlcpy(ldpreloads_buf, path, sizeof(ldpreloads_buf)); + + while (i < LDPRELOAD_MAX && (ldpreload_names[i] = strsep(&ldpreloads_bufp, delim))) { + if (*ldpreload_names[i] != '\0') { + ++i; + } + } + + /* Forget the last path if we had to truncate; this occurs if the 2nd to + * last char isn't '\0' (i.e. not originally a delim). */ + if (i > 0 && len >= sizeof(ldpreloads_buf) && + ldpreloads_buf[sizeof(ldpreloads_buf) - 2] != '\0') { + ldpreload_names[i - 1] = NULL; + } else { + ldpreload_names[i] = NULL; + } +} + +/* + * This code is called after the linker has linked itself and + * fixed it's own GOT. It is safe to make references to externs + * and other non-local data at this point. + */ +static unsigned __linker_init_post_relocation(unsigned **elfdata) +{ + static soinfo linker_soinfo; + + int argc = (int) *elfdata; + char **argv = (char**) (elfdata + 1); + unsigned *vecs = (unsigned*) (argv + argc + 1); + unsigned *v; + soinfo *si; + struct link_map * map; + const char *ldpath_env = NULL; + const char *ldpreload_env = NULL; + + /* NOTE: we store the elfdata pointer on a special location + * of the temporary TLS area in order to pass it to + * the C Library's runtime initializer. + * + * The initializer must clear the slot and reset the TLS + * to point to a different location to ensure that no other + * shared library constructor can access it. + */ +#if 0 + __libc_init_tls(elfdata); +#endif + + pid = getpid(); + +#if TIMING + struct timeval t0, t1; + gettimeofday(&t0, 0); +#endif + + /* Initialize environment functions, and get to the ELF aux vectors table */ + vecs = linker_env_init(vecs); + + /* Check auxv for AT_SECURE first to see if program is setuid, setgid, + has file caps, or caused a SELinux/AppArmor domain transition. */ + for (v = vecs; v[0]; v += 2) { + if (v[0] == AT_SECURE) { + /* kernel told us whether to enable secure mode */ + program_is_setuid = v[1]; + goto sanitize; + } + } + + /* Kernel did not provide AT_SECURE - fall back on legacy test. */ + program_is_setuid = (getuid() != geteuid()) || (getgid() != getegid()); + +sanitize: + /* Sanitize environment if we're loading a setuid program */ + if (program_is_setuid) + linker_env_secure(); + +#if 0 + debugger_init(); +#endif + + /* Get a few environment variables */ + { +#if LINKER_DEBUG + const char* env; + env = linker_env_get("DEBUG"); /* XXX: TODO: Change to LD_DEBUG */ + if (env) + debug_verbosity = atoi(env); +#endif + + /* Normally, these are cleaned by linker_env_secure, but the test + * against program_is_setuid doesn't cost us anything */ + if (!program_is_setuid) { + ldpath_env = getenv("LD_LIBRARY_PATH"); + ldpreload_env = getenv("LD_PRELOAD"); + } + } + + INFO("[ android linker & debugger ]\n"); + DEBUG("%5d elfdata @ 0x%08x\n", pid, (unsigned)elfdata); + + si = alloc_info(argv[0]); + if(si == 0) { + exit(-1); + } + + /* bootstrap the link map, the main exe always needs to be first */ + si->flags |= FLAG_EXE; + map = &(si->linkmap); + + map->l_addr = 0; + map->l_name = argv[0]; + map->l_prev = NULL; + map->l_next = NULL; + + _r_debug.r_map = map; + r_debug_tail = map; + + /* gdb expects the linker to be in the debug shared object list, + * and we need to make sure that the reported load address is zero. + * Without this, gdb gets the wrong idea of where rtld_db_dlactivity() + * is. Don't use alloc_info(), because the linker shouldn't + * be on the soinfo list. + */ + strlcpy((char*) linker_soinfo.name, "/system/bin/linker", sizeof linker_soinfo.name); + linker_soinfo.flags = 0; + linker_soinfo.base = 0; // This is the important part; must be zero. + insert_soinfo_into_debug_map(&linker_soinfo); + + /* extract information passed from the kernel */ + while(vecs[0] != 0){ + switch(vecs[0]){ + case AT_PHDR: + si->phdr = (Elf32_Phdr*) vecs[1]; + break; + case AT_PHNUM: + si->phnum = (int) vecs[1]; + break; + case AT_ENTRY: + si->entry = vecs[1]; + break; + } + vecs += 2; + } + + /* Compute the value of si->base. We can't rely on the fact that + * the first entry is the PHDR because this will not be true + * for certain executables (e.g. some in the NDK unit test suite) + */ + int nn; + si->base = 0; + for ( nn = 0; nn < si->phnum; nn++ ) { + if (si->phdr[nn].p_type == PT_PHDR) { + si->base = (Elf32_Addr) si->phdr - si->phdr[nn].p_vaddr; + break; + } + } + si->dynamic = (unsigned *)-1; + si->wrprotect_start = 0xffffffff; + si->wrprotect_end = 0; + si->refcount = 1; + si->gnu_relro_start = 0; + si->gnu_relro_len = 0; + + /* Use LD_LIBRARY_PATH if we aren't setuid/setgid */ + if (ldpath_env) + parse_library_path(ldpath_env, ":"); + + if (ldpreload_env) { + parse_preloads(ldpreload_env, " :"); + } + + if(link_image(si, 0)) { + char errmsg[] = "CANNOT LINK EXECUTABLE\n"; + write(2, __linker_dl_err_buf, strlen(__linker_dl_err_buf)); + write(2, errmsg, sizeof(errmsg)); + exit(-1); + } + + call_constructors_recursive(si); + +#if ALLOW_SYMBOLS_FROM_MAIN + /* Set somain after we've loaded all the libraries in order to prevent + * linking of symbols back to the main image, which is not set up at that + * point yet. + */ + somain = si; +#endif + +#if TIMING + gettimeofday(&t1,NULL); + PRINT("LINKER TIME: %s: %d microseconds\n", argv[0], (int) ( + (((long long)t1.tv_sec * 1000000LL) + (long long)t1.tv_usec) - + (((long long)t0.tv_sec * 1000000LL) + (long long)t0.tv_usec) + )); +#endif +#if STATS + PRINT("RELO STATS: %s: %d abs, %d rel, %d copy, %d symbol\n", argv[0], + linker_stats.reloc[RELOC_ABSOLUTE], + linker_stats.reloc[RELOC_RELATIVE], + linker_stats.reloc[RELOC_COPY], + linker_stats.reloc[RELOC_SYMBOL]); +#endif +#if COUNT_PAGES + { + unsigned n; + unsigned i; + unsigned count = 0; + for(n = 0; n < 4096; n++){ + if(bitmask[n]){ + unsigned x = bitmask[n]; + for(i = 0; i < 8; i++){ + if(x & 1) count++; + x >>= 1; + } + } + } + PRINT("PAGES MODIFIED: %s: %d (%dKB)\n", argv[0], count, count * 4); + } +#endif + +#if TIMING || STATS || COUNT_PAGES + fflush(stdout); +#endif + + TRACE("[ %5d Ready to execute '%s' @ 0x%08x ]\n", pid, si->name, + si->entry); + return si->entry; +} + +/* + * Find the value of AT_BASE passed to us by the kernel. This is the load + * location of the linker. + */ +static unsigned find_linker_base(unsigned **elfdata) { + int argc = (int) *elfdata; + char **argv = (char**) (elfdata + 1); + unsigned *vecs = (unsigned*) (argv + argc + 1); + while (vecs[0] != 0) { + vecs++; + } + + /* The end of the environment block is marked by two NULL pointers */ + vecs++; + + while(vecs[0]) { + if (vecs[0] == AT_BASE) { + return vecs[1]; + } + vecs += 2; + } + + return 0; // should never happen +} + +/* + * This is the entry point for the linker, called from begin.S. This + * method is responsible for fixing the linker's own relocations, and + * then calling __linker_init_post_relocation(). + * + * Because this method is called before the linker has fixed it's own + * relocations, any attempt to reference an extern variable, extern + * function, or other GOT reference will generate a segfault. + */ +unsigned __linker_init(unsigned **elfdata) { + unsigned linker_addr = find_linker_base(elfdata); + Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *) linker_addr; + Elf32_Phdr *phdr = + (Elf32_Phdr *)((unsigned char *) linker_addr + elf_hdr->e_phoff); + + soinfo linker_so; + memset(&linker_so, 0, sizeof(soinfo)); + + linker_so.base = linker_addr; + linker_so.dynamic = (unsigned *) -1; + linker_so.phdr = phdr; + linker_so.phnum = elf_hdr->e_phnum; + linker_so.flags |= FLAG_LINKER; + linker_so.wrprotect_start = 0xffffffff; + linker_so.wrprotect_end = 0; + linker_so.gnu_relro_start = 0; + linker_so.gnu_relro_len = 0; + + if (link_image(&linker_so, 0)) { + // It would be nice to print an error message, but if the linker + // can't link itself, there's no guarantee that we'll be able to + // call write() (because it involves a GOT reference). + // + // This situation should never occur unless the linker itself + // is corrupt. + exit(-1); + } + + // We have successfully fixed our own relocations. It's safe to run + // the main part of the linker now. + return __linker_init_post_relocation(elfdata); +} diff --git a/linker/linker.h b/linker/linker.h new file mode 100644 index 0000000..c5ef41c --- /dev/null +++ b/linker/linker.h @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINKER_H_ +#define _LINKER_H_ + +#define ANDROID_ARM_LINKER + +#include +#include +#include + +#undef PAGE_MASK +#undef PAGE_SIZE +#define PAGE_SIZE 4096 +#define PAGE_MASK 4095 + +void debugger_init(); +const char *addr_to_name(unsigned addr); + +/* magic shared structures that GDB knows about */ + +struct link_map +{ + uintptr_t l_addr; + char * l_name; + uintptr_t l_ld; + struct link_map * l_next; + struct link_map * l_prev; +}; + +/* needed for dl_iterate_phdr to be passed to the callbacks provided */ +struct dl_phdr_info +{ + Elf32_Addr dlpi_addr; + const char *dlpi_name; + const Elf32_Phdr *dlpi_phdr; + Elf32_Half dlpi_phnum; +}; + + +// Values for r_debug->state +enum { + RT_CONSISTENT, + RT_ADD, + RT_DELETE +}; + +struct r_debug +{ + int32_t r_version; + struct link_map * r_map; + void (*r_brk)(void); + int32_t r_state; + uintptr_t r_ldbase; +}; + +typedef struct soinfo soinfo; + +#define FLAG_LINKED 0x00000001 +#define FLAG_ERROR 0x00000002 +#define FLAG_EXE 0x00000004 // The main executable +#define FLAG_LINKER 0x00000010 // The linker itself + +#define SOINFO_NAME_LEN 128 + +struct soinfo +{ + const char name[SOINFO_NAME_LEN]; + Elf32_Phdr *phdr; + int phnum; + unsigned entry; + unsigned base; + unsigned size; + + int unused; // DO NOT USE, maintained for compatibility. + + unsigned *dynamic; + + unsigned wrprotect_start; + unsigned wrprotect_end; + + soinfo *next; + unsigned flags; + + const char *strtab; + Elf32_Sym *symtab; + + unsigned nbucket; + unsigned nchain; + unsigned *bucket; + unsigned *chain; + + unsigned *plt_got; + + Elf32_Rel *plt_rel; + unsigned plt_rel_count; + + Elf32_Rel *rel; + unsigned rel_count; + + unsigned *preinit_array; + unsigned preinit_array_count; + + unsigned *init_array; + unsigned init_array_count; + unsigned *fini_array; + unsigned fini_array_count; + + void (*init_func)(void); + void (*fini_func)(void); + +#ifdef ANDROID_ARM_LINKER + /* ARM EABI section used for stack unwinding. */ + unsigned *ARM_exidx; + unsigned ARM_exidx_count; +#endif + + unsigned refcount; + struct link_map linkmap; + + int constructors_called; + + Elf32_Addr gnu_relro_start; + unsigned gnu_relro_len; + +}; + + +extern soinfo libdl_info; + +#ifdef ANDROID_ARM_LINKER + +#define R_ARM_COPY 20 +#define R_ARM_GLOB_DAT 21 +#define R_ARM_JUMP_SLOT 22 +#define R_ARM_RELATIVE 23 + +/* According to the AAPCS specification, we only + * need the above relocations. However, in practice, + * the following ones turn up from time to time. + */ +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 + +#elif defined(ANDROID_X86_LINKER) + +#define R_386_32 1 +#define R_386_PC32 2 +#define R_386_GLOB_DAT 6 +#define R_386_JUMP_SLOT 7 +#define R_386_RELATIVE 8 + +#endif + +#ifndef DT_INIT_ARRAY +#define DT_INIT_ARRAY 25 +#endif + +#ifndef DT_FINI_ARRAY +#define DT_FINI_ARRAY 26 +#endif + +#ifndef DT_INIT_ARRAYSZ +#define DT_INIT_ARRAYSZ 27 +#endif + +#ifndef DT_FINI_ARRAYSZ +#define DT_FINI_ARRAYSZ 28 +#endif + +#ifndef DT_PREINIT_ARRAY +#define DT_PREINIT_ARRAY 32 +#endif + +#ifndef DT_PREINIT_ARRAYSZ +#define DT_PREINIT_ARRAYSZ 33 +#endif + +soinfo *find_library(const char *name); +unsigned unload_library(soinfo *si); +Elf32_Sym *lookup_in_library(soinfo *si, const char *name); +Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start); +soinfo *find_containing_library(const void *addr); +Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si); +const char *linker_get_error(void); +void call_constructors_recursive(soinfo *si); + +#ifdef ANDROID_ARM_LINKER +typedef long unsigned int *_Unwind_Ptr; +_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); +#elif defined(ANDROID_X86_LINKER) +int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), void *); +#endif + +#endif diff --git a/linker/linker_debug.h b/linker/linker_debug.h new file mode 100644 index 0000000..37a27e9 --- /dev/null +++ b/linker/linker_debug.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2008-2010 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINKER_DEBUG_H_ +#define _LINKER_DEBUG_H_ + +#include + +#ifndef LINKER_DEBUG +#error LINKER_DEBUG should be defined to either 1 or 0 in Android.mk +#endif + +/* set LINKER_DEBUG_TO_LOG to 1 to send the logs to logcat, + * or 0 to use stdout instead. + */ +#define LINKER_DEBUG_TO_LOG 0 +#define TRACE_DEBUG 1 +#define DO_TRACE_LOOKUP 1 +#define DO_TRACE_RELO 1 +#define TIMING 0 +#define STATS 0 +#define COUNT_PAGES 0 + +/********************************************************************* + * You shouldn't need to modify anything below unless you are adding + * more debugging information. + * + * To enable/disable specific debug options, change the defines above + *********************************************************************/ + + +/*********************************************************************/ +#undef TRUE +#undef FALSE +#define TRUE 1 +#define FALSE 0 + +/* Only use printf() during debugging. We have seen occasional memory + * corruption when the linker uses printf(). + */ +#if LINKER_DEBUG +#include "linker_format.h" +extern int debug_verbosity; +#if LINKER_DEBUG_TO_LOG +extern int format_log(int, const char *, const char *, ...); +#define _PRINTVF(v,f,x...) \ + do { \ + if (debug_verbosity > (v)) format_log(5-(v),"linker",x); \ + } while (0) +#else /* !LINKER_DEBUG_TO_LOG */ +extern int format_fd(int, const char *, ...); +#define _PRINTVF(v,f,x...) \ + do { \ + if (debug_verbosity > (v)) format_fd(1, x); \ + } while (0) +#endif /* !LINKER_DEBUG_TO_LOG */ +#else /* !LINKER_DEBUG */ +#define _PRINTVF(v,f,x...) do {} while(0) +#endif /* LINKER_DEBUG */ + +#define PRINT(x...) _PRINTVF(-1, FALSE, x) +#define INFO(x...) _PRINTVF(1, TRUE, x) +#define TRACE(x...) _PRINTVF(1, TRUE, x) +#define WARN(fmt,args...) \ + _PRINTVF(-1, TRUE, "%s:%d| WARNING: " fmt, __FILE__, __LINE__, ## args) +#define ERROR(fmt,args...) \ + _PRINTVF(-1, TRUE, "%s:%d| ERROR: " fmt, __FILE__, __LINE__, ## args) + + +#if TRACE_DEBUG +#define DEBUG(x...) _PRINTVF(2, TRUE, "DEBUG: " x) +#else /* !TRACE_DEBUG */ +#define DEBUG(x...) do {} while (0) +#endif /* TRACE_DEBUG */ + +#if LINKER_DEBUG +#define TRACE_TYPE(t,x...) do { if (DO_TRACE_##t) { TRACE(x); } } while (0) +#else /* !LINKER_DEBUG */ +#define TRACE_TYPE(t,x...) do {} while (0) +#endif /* LINKER_DEBUG */ + +#if STATS +#define RELOC_ABSOLUTE 0 +#define RELOC_RELATIVE 1 +#define RELOC_COPY 2 +#define RELOC_SYMBOL 3 +#define NUM_RELOC_STATS 4 + +struct _link_stats { + int reloc[NUM_RELOC_STATS]; +}; +extern struct _link_stats linker_stats; + +#define COUNT_RELOC(type) \ + do { if (type >= 0 && type < NUM_RELOC_STATS) { \ + linker_stats.reloc[type] += 1; \ + } else { \ + PRINT("Unknown reloc stat requested\n"); \ + } \ + } while(0) +#else /* !STATS */ +#define COUNT_RELOC(type) do {} while(0) +#endif /* STATS */ + +#if TIMING +#undef WARN +#define WARN(x...) do {} while (0) +#endif /* TIMING */ + +#if COUNT_PAGES +extern unsigned bitmask[]; +#define MARK(offset) do { \ + bitmask[((offset) >> 12) >> 3] |= (1 << (((offset) >> 12) & 7)); \ + } while(0) +#else +#define MARK(x) do {} while (0) +#endif + +#define DEBUG_DUMP_PHDR(phdr, name, pid) do { \ + DEBUG("%5d %s (phdr = 0x%08x)\n", (pid), (name), (unsigned)(phdr)); \ + DEBUG("\t\tphdr->offset = 0x%08x\n", (unsigned)((phdr)->p_offset)); \ + DEBUG("\t\tphdr->p_vaddr = 0x%08x\n", (unsigned)((phdr)->p_vaddr)); \ + DEBUG("\t\tphdr->p_paddr = 0x%08x\n", (unsigned)((phdr)->p_paddr)); \ + DEBUG("\t\tphdr->p_filesz = 0x%08x\n", (unsigned)((phdr)->p_filesz)); \ + DEBUG("\t\tphdr->p_memsz = 0x%08x\n", (unsigned)((phdr)->p_memsz)); \ + DEBUG("\t\tphdr->p_flags = 0x%08x\n", (unsigned)((phdr)->p_flags)); \ + DEBUG("\t\tphdr->p_align = 0x%08x\n", (unsigned)((phdr)->p_align)); \ + } while (0) + +#endif /* _LINKER_DEBUG_H_ */ diff --git a/linker/linker_environ.c b/linker/linker_environ.c new file mode 100644 index 0000000..b71dd80 --- /dev/null +++ b/linker/linker_environ.c @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "linker_environ.h" +#include + +static char** _envp; + +/* Returns 1 if 'str' points to a valid environment variable definition. + * For now, we check that: + * - It is smaller than MAX_ENV_LEN (to detect non-zero terminated strings) + * - It contains at least one equal sign that is not the first character + */ +static int +_is_valid_definition(const char* str) +{ + int pos = 0; + int first_equal_pos = -1; + + /* According to its sources, the kernel uses 32*PAGE_SIZE by default + * as the maximum size for an env. variable definition. + */ + const int MAX_ENV_LEN = 32*4096; + + if (str == NULL) + return 0; + + /* Parse the string, looking for the first '=' there, and its size */ + do { + if (str[pos] == '\0') + break; + if (str[pos] == '=' && first_equal_pos < 0) + first_equal_pos = pos; + pos++; + } while (pos < MAX_ENV_LEN); + + if (pos >= MAX_ENV_LEN) /* Too large */ + return 0; + + if (first_equal_pos < 1) /* No equal sign, or it is the first character */ + return 0; + + return 1; +} + +unsigned* +linker_env_init(unsigned* vecs) +{ + /* Store environment pointer - can't be NULL */ + _envp = (char**) vecs; + + /* Skip over all definitions */ + while (vecs[0] != 0) + vecs++; + /* The end of the environment block is marked by two NULL pointers */ + vecs++; + + /* As a sanity check, we're going to remove all invalid variable + * definitions from the environment array. + */ + { + char** readp = _envp; + char** writep = _envp; + for ( ; readp[0] != NULL; readp++ ) { + if (!_is_valid_definition(readp[0])) + continue; + writep[0] = readp[0]; + writep++; + } + writep[0] = NULL; + } + + /* Return the address of the aux vectors table */ + return vecs; +} + +/* Check if the environment variable definition at 'envstr' + * starts with '=', and if so return the address of the + * first character after the equal sign. Otherwise return NULL. + */ +static char* +env_match(char* envstr, const char* name) +{ + size_t cnt = 0; + + while (envstr[cnt] == name[cnt] && name[cnt] != '\0') + cnt++; + + if (name[cnt] == '\0' && envstr[cnt] == '=') + return envstr + cnt + 1; + + return NULL; +} + +#define MAX_ENV_LEN (16*4096) + +const char* +linker_env_get(const char* name) +{ + char** readp = _envp; + + if (name == NULL || name[0] == '\0') + return NULL; + + for ( ; readp[0] != NULL; readp++ ) { + char* val = env_match(readp[0], name); + if (val != NULL) { + /* Return NULL for empty strings, or if it is too large */ + if (val[0] == '\0') + val = NULL; + return val; + } + } + return NULL; +} + + +void +linker_env_unset(const char* name) +{ + char** readp = _envp; + char** writep = readp; + + if (name == NULL || name[0] == '\0') + return; + + for ( ; readp[0] != NULL; readp++ ) { + if (env_match(readp[0], name)) + continue; + writep[0] = readp[0]; + writep++; + } + /* end list with a NULL */ + writep[0] = NULL; +} + + + +/* Remove unsafe environment variables. This should be used when + * running setuid programs. */ +void +linker_env_secure(void) +{ + /* The same list than GLibc at this point */ + static const char* const unsec_vars[] = { + "GCONV_PATH", + "GETCONF_DIR", + "HOSTALIASES", + "LD_AUDIT", + "LD_DEBUG", + "LD_DEBUG_OUTPUT", + "LD_DYNAMIC_WEAK", + "LD_LIBRARY_PATH", + "LD_ORIGIN_PATH", + "LD_PRELOAD", + "LD_PROFILE", + "LD_SHOW_AUXV", + "LD_USE_LOAD_BIAS", + "LOCALDOMAIN", + "LOCPATH", + "MALLOC_TRACE", + "MALLOC_CHECK_", + "NIS_PATH", + "NLSPATH", + "RESOLV_HOST_CONF", + "RES_OPTIONS", + "TMPDIR", + "TZDIR", + "LD_AOUT_LIBRARY_PATH", + "LD_AOUT_PRELOAD", + }; + + const char* const* cp = unsec_vars; + const char* const* endp = cp + sizeof(unsec_vars)/sizeof(unsec_vars[0]); + + while (cp < endp) { + linker_env_unset(*cp); + cp++; + } +} diff --git a/linker/linker_environ.h b/linker/linker_environ.h new file mode 100644 index 0000000..98ad1de --- /dev/null +++ b/linker/linker_environ.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef LINKER_ENVIRON_H +#define LINKER_ENVIRON_H + +/* Call this function before anything else. 'vecs' must be the pointer + * to the environment block in the ELF data block. The function returns + * the start of the aux vectors after the env block. + */ +extern unsigned* linker_env_init(unsigned* vecs); + +/* Unset a given environment variable. In case the variable is defined + * multiple times, unset all instances. This modifies the environment + * block, so any pointer returned by linker_env_get() after this call + * might become invalid */ +extern void linker_env_unset(const char* name); + + +/* Returns the value of environment variable 'name' if defined and not + * empty, or NULL otherwise. Note that the returned pointer may become + * invalid if linker_env_unset() or linker_env_secure() are called + * after this function. */ +extern const char* linker_env_get(const char* name); + +/* Remove unsecure environment variables. This should be used when + * running setuid programs. */ +extern void linker_env_secure(void); + +#endif /* LINKER_ENVIRON_H */ diff --git a/linker/linker_format.c b/linker/linker_format.c new file mode 100644 index 0000000..d310f79 --- /dev/null +++ b/linker/linker_format.c @@ -0,0 +1,707 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include "linker_format.h" +#include "linker_debug.h" + +/* define UNIT_TESTS to build this file as a single executable that runs + * the formatter's unit tests + */ +#define xxUNIT_TESTS + +/*** Generic output sink + ***/ + +typedef struct { + void *opaque; + void (*send)(void *opaque, const char *data, int len); +} Out; + +static void +out_send(Out *o, const void *data, size_t len) +{ + o->send(o->opaque, data, (int)len); +} + +static void +out_send_repeat(Out *o, char ch, int count) +{ + char pad[8]; + const int padSize = (int)sizeof(pad); + + memset(pad, ch, sizeof(pad)); + while (count > 0) { + int avail = count; + if (avail > padSize) { + avail = padSize; + } + o->send(o->opaque, pad, avail); + count -= avail; + } +} + +/* forward declaration */ +static void +out_vformat(Out *o, const char *format, va_list args); + +/*** Bounded buffer output + ***/ + +typedef struct { + Out out[1]; + char *buffer; + char *pos; + char *end; + int total; +} BufOut; + +static void +buf_out_send(void *opaque, const char *data, int len) +{ + BufOut *bo = opaque; + + if (len < 0) + len = strlen(data); + + bo->total += len; + + while (len > 0) { + int avail = bo->end - bo->pos; + if (avail == 0) + break; + if (avail > len) + avail = len; + memcpy(bo->pos, data, avail); + bo->pos += avail; + bo->pos[0] = '\0'; + len -= avail; + } +} + +static Out* +buf_out_init(BufOut *bo, char *buffer, size_t size) +{ + if (size == 0) + return NULL; + + bo->out->opaque = bo; + bo->out->send = buf_out_send; + bo->buffer = buffer; + bo->end = buffer + size - 1; + bo->pos = bo->buffer; + bo->pos[0] = '\0'; + bo->total = 0; + + return bo->out; +} + +static int +buf_out_length(BufOut *bo) +{ + return bo->total; +} + +static int +vformat_buffer(char *buff, size_t buffsize, const char *format, va_list args) +{ + BufOut bo; + Out *out; + + out = buf_out_init(&bo, buff, buffsize); + if (out == NULL) + return 0; + + out_vformat(out, format, args); + + return buf_out_length(&bo); +} + +int +format_buffer(char *buff, size_t buffsize, const char *format, ...) +{ + va_list args; + int ret; + + va_start(args, format); + ret = vformat_buffer(buff, buffsize, format, args); + va_end(args); + + return ret; +} + +/* The __stack_chk_fail() function calls __libc_android_log_print() + * which calls vsnprintf(). + * + * We define our version of the function here to avoid dragging + * about 25 KB of C library routines related to formatting. + */ +int +vsnprintf(char *buff, size_t bufsize, const char *format, va_list args) +{ + return format_buffer(buff, bufsize, format, args); +} + +#if LINKER_DEBUG + +#if !LINKER_DEBUG_TO_LOG + +/*** File descriptor output + ***/ + +typedef struct { + Out out[1]; + int fd; + int total; +} FdOut; + +static void +fd_out_send(void *opaque, const char *data, int len) +{ + FdOut *fdo = opaque; + + if (len < 0) + len = strlen(data); + + while (len > 0) { + int ret = write(fdo->fd, data, len); + if (ret < 0) { + if (errno == EINTR) + continue; + break; + } + data += ret; + len -= ret; + fdo->total += ret; + } +} + +static Out* +fd_out_init(FdOut *fdo, int fd) +{ + fdo->out->opaque = fdo; + fdo->out->send = fd_out_send; + fdo->fd = fd; + fdo->total = 0; + + return fdo->out; +} + +static int +fd_out_length(FdOut *fdo) +{ + return fdo->total; +} + + +int +format_fd(int fd, const char *format, ...) +{ + FdOut fdo; + Out* out; + va_list args; + + out = fd_out_init(&fdo, fd); + if (out == NULL) + return 0; + + va_start(args, format); + out_vformat(out, format, args); + va_end(args); + + return fd_out_length(&fdo); +} + +#else /* LINKER_DEBUG_TO_LOG */ + +/*** Log output + ***/ + +/* We need our own version of __libc_android_log_vprint, otherwise + * the log output is completely broken. Probably due to the fact + * that the C library is not initialized yet. + * + * You can test that by setting CUSTOM_LOG_VPRINT to 0 + */ +#define CUSTOM_LOG_VPRINT 1 + +#if CUSTOM_LOG_VPRINT + +#include +#include +#include + +static int log_vprint(int prio, const char *tag, const char *fmt, va_list args) +{ + char buf[1024]; + int result; + static int log_fd = -1; + + result = vformat_buffer(buf, sizeof buf, fmt, args); + + if (log_fd < 0) { + log_fd = open("/dev/log/main", O_WRONLY); + if (log_fd < 0) + return result; + } + + { + ssize_t ret; + struct iovec vec[3]; + + vec[0].iov_base = (unsigned char *) &prio; + vec[0].iov_len = 1; + vec[1].iov_base = (void *) tag; + vec[1].iov_len = strlen(tag) + 1; + vec[2].iov_base = (void *) buf; + vec[2].iov_len = strlen(buf) + 1; + + do { + ret = writev(log_fd, vec, 3); + } while ((ret < 0) && (errno == EINTR)); + } + return result; +} + +#define __libc_android_log_vprint log_vprint + +#else /* !CUSTOM_LOG_VPRINT */ + +extern int __libc_android_log_vprint(int prio, const char* tag, const char* format, va_list ap); + +#endif /* !CUSTOM_LOG_VPRINT */ + +int +format_log(int prio, const char *tag, const char *format, ...) +{ + int ret; + va_list args; + va_start(args, format); + ret = __libc_android_log_vprint(prio, tag, format, args); + va_end(args); + return ret; +} + +#endif /* LINKER_DEBUG_TO_LOG */ + +#endif /* LINKER_DEBUG */ + +/*** formatted output implementation + ***/ + +/* Parse a decimal string from 'format + *ppos', + * return the value, and writes the new position past + * the decimal string in '*ppos' on exit. + * + * NOTE: Does *not* handle a sign prefix. + */ +static unsigned +parse_decimal(const char *format, int *ppos) +{ + const char* p = format + *ppos; + unsigned result = 0; + + for (;;) { + int ch = *p; + unsigned d = (unsigned)(ch - '0'); + + if (d >= 10U) + break; + + result = result*10 + d; + p++; + } + *ppos = p - format; + return result; +} + +/* write an octal/decimal/number into a bounded buffer. + * assumes that bufsize > 0, and 'digits' is a string of + * digits of at least 'base' values. + */ +static void +format_number(char *buffer, size_t bufsize, uint64_t value, int base, const char *digits) +{ + char *pos = buffer; + char *end = buffer + bufsize - 1; + + /* generate digit string in reverse order */ + while (value) { + unsigned d = value % base; + value /= base; + if (pos < end) { + *pos++ = digits[d]; + } + } + + /* special case for 0 */ + if (pos == buffer) { + if (pos < end) { + *pos++ = '0'; + } + } + pos[0] = '\0'; + + /* now reverse digit string in-place */ + end = pos - 1; + pos = buffer; + while (pos < end) { + int ch = pos[0]; + pos[0] = end[0]; + end[0] = (char) ch; + pos++; + end--; + } +} + +/* Write an integer (octal or decimal) into a buffer, assumes buffsize > 2 */ +static void +format_integer(char *buffer, size_t buffsize, uint64_t value, int base, int isSigned) +{ + if (isSigned && (int64_t)value < 0) { + buffer[0] = '-'; + buffer += 1; + buffsize -= 1; + value = (uint64_t)(-(int64_t)value); + } + + format_number(buffer, buffsize, value, base, "0123456789"); +} + +#if 0 +/* Write an octal into a buffer, assumes buffsize > 2 */ +static void +format_octal(char *buffer, size_t buffsize, uint64_t value, int isSigned) +{ + format_integer(buffer, buffsize, value, 8, isSigned); +} + +/* Write a decimal into a buffer, assumes buffsize > 2 */ +static void +format_decimal(char *buffer, size_t buffsize, uint64_t value, int isSigned) +{ + format_integer(buffer, buffsize, value, 10, isSigned); +} +#endif + +/* Write an hexadecimal into a buffer, isCap is true for capital alphas. + * Assumes bufsize > 2 */ +static void +format_hex(char *buffer, size_t buffsize, uint64_t value, int isCap) +{ + const char *digits = isCap ? "0123456789ABCDEF" : "0123456789abcdef"; + + format_number(buffer, buffsize, value, 16, digits); +} + + +/* Perform formatted output to an output target 'o' */ +static void +out_vformat(Out *o, const char *format, va_list args) +{ + int nn = 0; + + for (;;) { + int mm; + int padZero = 0; + int padLeft = 0; + char sign = '\0'; + int width = -1; + int prec = -1; + size_t bytelen = sizeof(int); + const char* str; + int slen; + char buffer[32]; /* temporary buffer used to format numbers */ + + char c; + + /* first, find all characters that are not 0 or '%' */ + /* then send them to the output directly */ + mm = nn; + do { + c = format[mm]; + if (c == '\0' || c == '%') + break; + mm++; + } while (1); + + if (mm > nn) { + out_send(o, format+nn, mm-nn); + nn = mm; + } + + /* is this it ? then exit */ + if (c == '\0') + break; + + /* nope, we are at a '%' modifier */ + nn++; // skip it + + /* parse flags */ + for (;;) { + c = format[nn++]; + if (c == '\0') { /* single trailing '%' ? */ + c = '%'; + out_send(o, &c, 1); + return; + } + else if (c == '0') { + padZero = 1; + continue; + } + else if (c == '-') { + padLeft = 1; + continue; + } + else if (c == ' ' || c == '+') { + sign = c; + continue; + } + break; + } + + /* parse field width */ + if ((c >= '0' && c <= '9')) { + nn --; + width = (int)parse_decimal(format, &nn); + c = format[nn++]; + } + + /* parse precision */ + if (c == '.') { + prec = (int)parse_decimal(format, &nn); + c = format[nn++]; + } + + /* length modifier */ + switch (c) { + case 'h': + bytelen = sizeof(short); + if (format[nn] == 'h') { + bytelen = sizeof(char); + nn += 1; + } + c = format[nn++]; + break; + case 'l': + bytelen = sizeof(long); + if (format[nn] == 'l') { + bytelen = sizeof(long long); + nn += 1; + } + c = format[nn++]; + break; + case 'z': + bytelen = sizeof(size_t); + c = format[nn++]; + break; + case 't': + bytelen = sizeof(ptrdiff_t); + c = format[nn++]; + break; + default: + ; + } + + /* conversion specifier */ + if (c == 's') { + /* string */ + str = va_arg(args, const char*); + } else if (c == 'c') { + /* character */ + /* NOTE: char is promoted to int when passed through the stack */ + buffer[0] = (char) va_arg(args, int); + buffer[1] = '\0'; + str = buffer; + } else if (c == 'p') { + uint64_t value = (uintptr_t) va_arg(args, void*); + buffer[0] = '0'; + buffer[1] = 'x'; + format_hex(buffer + 2, sizeof buffer-2, value, 0); + str = buffer; + } else { + /* integers - first read value from stack */ + uint64_t value; + int isSigned = (c == 'd' || c == 'i' || c == 'o'); + + /* NOTE: int8_t and int16_t are promoted to int when passed + * through the stack + */ + switch (bytelen) { + case 1: value = (uint8_t) va_arg(args, int); break; + case 2: value = (uint16_t) va_arg(args, int); break; + case 4: value = va_arg(args, uint32_t); break; + case 8: value = va_arg(args, uint64_t); break; + default: return; /* should not happen */ + } + + /* sign extension, if needed */ + if (isSigned) { + int shift = 64 - 8*bytelen; + value = (uint64_t)(((int64_t)(value << shift)) >> shift); + } + + /* format the number properly into our buffer */ + switch (c) { + case 'i': case 'd': + format_integer(buffer, sizeof buffer, value, 10, isSigned); + break; + case 'o': + format_integer(buffer, sizeof buffer, value, 8, isSigned); + break; + case 'x': case 'X': + format_hex(buffer, sizeof buffer, value, (c == 'X')); + break; + default: + buffer[0] = '\0'; + } + /* then point to it */ + str = buffer; + } + + /* if we are here, 'str' points to the content that must be + * outputted. handle padding and alignment now */ + + slen = strlen(str); + + if (slen < width && !padLeft) { + char padChar = padZero ? '0' : ' '; + out_send_repeat(o, padChar, width - slen); + } + + out_send(o, str, slen); + + if (slen < width && padLeft) { + char padChar = padZero ? '0' : ' '; + out_send_repeat(o, padChar, width - slen); + } + } +} + + +#ifdef UNIT_TESTS + +#include + +static int gFails = 0; + +#define MARGIN 40 + +#define UTEST_CHECK(condition,message) \ + printf("Checking %-*s: ", MARGIN, message); fflush(stdout); \ + if (!(condition)) { \ + printf("KO\n"); \ + gFails += 1; \ + } else { \ + printf("ok\n"); \ + } + +static void +utest_BufOut(void) +{ + char buffer[16]; + BufOut bo[1]; + Out* out; + int ret; + + buffer[0] = '1'; + out = buf_out_init(bo, buffer, sizeof buffer); + UTEST_CHECK(buffer[0] == '\0', "buf_out_init clears initial byte"); + out_send(out, "abc", 3); + UTEST_CHECK(!memcmp(buffer, "abc", 4), "out_send() works with BufOut"); + out_send_repeat(out, 'X', 4); + UTEST_CHECK(!memcmp(buffer, "abcXXXX", 8), "out_send_repeat() works with BufOut"); + buffer[sizeof buffer-1] = 'x'; + out_send_repeat(out, 'Y', 2*sizeof(buffer)); + UTEST_CHECK(buffer[sizeof buffer-1] == '\0', "overflows always zero-terminates"); + + out = buf_out_init(bo, buffer, sizeof buffer); + out_send_repeat(out, 'X', 2*sizeof(buffer)); + ret = buf_out_length(bo); + UTEST_CHECK(ret == 2*sizeof(buffer), "correct size returned on overflow"); +} + +static void +utest_expect(const char* result, const char* format, ...) +{ + va_list args; + BufOut bo[1]; + char buffer[256]; + Out* out = buf_out_init(bo, buffer, sizeof buffer); + + printf("Checking %-*s: ", MARGIN, format); fflush(stdout); + va_start(args, format); + out_vformat(out, format, args); + va_end(args); + + if (strcmp(result, buffer)) { + printf("KO. got '%s' expecting '%s'\n", buffer, result); + gFails += 1; + } else { + printf("ok. got '%s'\n", result); + } +} + +int main(void) +{ + utest_BufOut(); + utest_expect("", ""); + utest_expect("a", "a"); + utest_expect("01234", "01234", ""); + utest_expect("01234", "%s", "01234"); + utest_expect("aabbcc", "aa%scc", "bb"); + utest_expect("a", "%c", 'a'); + utest_expect("1234", "%d", 1234); + utest_expect("-8123", "%d", -8123); + utest_expect("16", "%hd", 0x7fff0010); + utest_expect("16", "%hhd", 0x7fffff10); + utest_expect("68719476736", "%lld", 0x1000000000LL); + utest_expect("70000", "%ld", 70000); + utest_expect("0xb0001234", "%p", (void*)0xb0001234); + utest_expect("12ab", "%x", 0x12ab); + utest_expect("12AB", "%X", 0x12ab); + utest_expect("00123456", "%08x", 0x123456); + utest_expect("01234", "0%d", 1234); + utest_expect(" 1234", "%5d", 1234); + utest_expect("01234", "%05d", 1234); + utest_expect(" 1234", "%8d", 1234); + utest_expect("1234 ", "%-8d", 1234); + utest_expect("abcdef ", "%-11s", "abcdef"); + utest_expect("something:1234", "%s:%d", "something", 1234); + utest_expect("005:5:05", "%03d:%d:%02d", 5, 5, 5); + utest_expect("5,0x0", "%d,%p", 5, NULL); + utest_expect("68719476736,6,7,8", "%lld,%d,%d,%d", 0x1000000000LL, 6, 7, 8); + return gFails != 0; +} + +#endif /* UNIT_TESTS */ diff --git a/linker/linker_format.h b/linker/linker_format.h new file mode 100644 index 0000000..6ae2bad --- /dev/null +++ b/linker/linker_format.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _LINKER_FORMAT_H +#define _LINKER_FORMAT_H + +#include +#include + +/* Formatting routines for the dynamic linker's debug traces */ +/* We want to avoid dragging the whole C library fprintf() */ +/* implementation into the dynamic linker since this creates */ +/* issues (it uses malloc()/free()) and increases code size */ + +int format_buffer(char *buffer, size_t bufsize, const char *format, ...); + +#endif /* _LINKER_FORMAT_H */ diff --git a/linker/rt.c b/linker/rt.c new file mode 100644 index 0000000..30d5a48 --- /dev/null +++ b/linker/rt.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This function is an empty stub where GDB locates a breakpoint to get notified + * about linker activity. + */ +void __attribute__((noinline)) rtld_db_dlactivity(void) +{ +} + diff --git a/linker/strlcpy.c b/linker/strlcpy.c new file mode 100644 index 0000000..b6b600b --- /dev/null +++ b/linker/strlcpy.c @@ -0,0 +1,50 @@ +/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "strlcpy.h" + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} diff --git a/linker/strlcpy.h b/linker/strlcpy.h new file mode 100644 index 0000000..59e34fb --- /dev/null +++ b/linker/strlcpy.h @@ -0,0 +1,10 @@ +#ifndef STRLCPY_H +#define STRLCPY_H + +#include +#include + +size_t +strlcpy(char *dst, const char *src, size_t siz); + +#endif diff --git a/makefile b/makefile new file mode 100644 index 0000000..71bd717 --- /dev/null +++ b/makefile @@ -0,0 +1,73 @@ + +# Android Gingerbread linker +LINKER_SOURCES=$(wildcard linker/*.c) + +# Compatibility wrappers and hooks +COMPAT_SOURCES=$(wildcard compat/*.c) + +# Library for getting files out of .apk files +APKLIB_SOURCES=$(wildcard apklib/*.c) + +# Our own JNI environment implementation +JNIENV_SOURCES=$(wildcard jni/*.c) + +# Support modules for specific applications +MODULES_SOURCES=$(wildcard modules/*.c) + +TARGET = apkenv + +SOURCES += $(TARGET).c +SOURCES += $(LINKER_SOURCES) +SOURCES += $(COMPAT_SOURCES) +SOURCES += $(APKLIB_SOURCES) +SOURCES += $(JNIENV_SOURCES) + +OBJS = $(patsubst %.c,%.o,$(SOURCES)) +MODULES = $(patsubst modules/%.c,%.apkenv.so,$(MODULES_SOURCES)) + +LDFLAGS = -fPIC -ldl -lz -lSDL -lSDL_mixer -pthread + +# Selection of OpenGL ES version support (if any) to include +GLES ?= 1 +ifeq ($(GLES),2) + CFLAGS += -DAPKENV_GLES2 + LDFLAGS += -lGLESv2 +else + CFLAGS += -DAPKENV_GLES + LDFLAGS += -lGLES_CM +endif + +FREMANTLE ?= 0 +ifeq ($(FREMANTLE),1) + CFLAGS += -DFREMANTLE + LDFLAGS += -lSDL_gles +endif + +DEBUG ?= 1 +ifeq ($(DEBUG),1) + CFLAGS += -g -Wall -DLINKER_DEBUG=1 -DAPKENV_DEBUG -Wformat=0 +else + CFLAGS += -O2 -DLINKER_DEBUG=0 +endif + +all: $(TARGET) $(MODULES) + +%.o: %.c + @echo -e "\tCC\t$@" + @$(CC) $(CFLAGS) -c -o $@ $< + +$(TARGET): $(OBJS) + @echo -e "\tLINK\t$@" + @$(CC) $(LDFLAGS) $(OBJS) -o $@ + +%.apkenv.so: modules/%.c + @echo -e "\tMOD\t$@" + @$(CC) -fPIC -shared $(CFLAGS) -o $@ $< + +strip: + @echo -e "\tSTRIP" + @strip $(TARGET) $(MODULES) + +clean: + rm -rf $(TARGET) $(OBJS) $(MODULES) + diff --git a/modules/common.h b/modules/common.h new file mode 100644 index 0000000..0d59624 --- /dev/null +++ b/modules/common.h @@ -0,0 +1,85 @@ +#ifndef APKENV_MODULES_COMMON_H +#define APKENV_MODULES_COMMON_H + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + +#include "../apkenv.h" +#include "../jni/jnienv.h" + +/* Macros to be used inside extension modules */ +#define GLOBAL_M (self->global) +#define ENV_M ENV(GLOBAL_M) +#define VM_M VM(GLOBAL_M) +#define LOOKUP_M(method) (GLOBAL_M->lookup_symbol(method)) + +/* Version check (for compatibility) */ +#define APKENV_MODULE_CHECK_VERSION(version) \ + if ((version) != APKENV_MODULE_VERSION) { \ + return APKENV_MODULE_VERSION; \ + } + +/* Add init function for module export */ +#define APKENV_MODULE(modulename, modulepriority) \ + int \ + apkenv_module_init(int version, struct SupportModule *module) { \ + APKENV_MODULE_CHECK_VERSION(version); \ + module->priv = &modulename ## _priv; \ + module->priority = modulepriority; \ + module->try_init = modulename ## _try_init; \ + module->init = modulename ## _init; \ + module->input = modulename ## _input; \ + module->update = modulename ## _update; \ + module->deinit = modulename ## _deinit; \ + module->pause = modulename ## _pause; \ + module->resume = modulename ## _resume; \ + return APKENV_MODULE_VERSION; \ + } + + +/* Module priorities */ +enum { + /* For really generic modules - lowest priority */ + MODULE_PRIORITY_GENERIC = 1 << 1, + + /* For modules targetting a specific engine */ + MODULE_PRIORITY_ENGINE = 1 << 3, + + /* For modules targetting a specific game */ + MODULE_PRIORITY_GAME = 1 << 6, + + /* For modules targetting a specific version of a game */ + MODULE_PRIORITY_GAME_VERSION = 1 << 9, +}; + +/* JNI functions for JNI_OnLoad() and JNI_OnUnLoad() */ +typedef void (*jni_onload_t)(JavaVM *vm, void *reserved) SOFTFP; +typedef void (*jni_onunload_t)(JavaVM *vm, void *reserved) SOFTFP; + +#endif /* APKENV_MODULES_COMMON_H */ diff --git a/modules/generic.c b/modules/generic.c new file mode 100644 index 0000000..3b08040 --- /dev/null +++ b/modules/generic.c @@ -0,0 +1,83 @@ + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + +/** + * Generic support module - can be used as a template for new modules + * This module does not do anything useful, except for calling JNI_OnLoad + **/ + +#include "common.h" + +struct SupportModulePriv { + jni_onload_t JNI_OnLoad; +}; +static struct SupportModulePriv generic_priv; + +static int +generic_try_init(struct SupportModule *self) +{ + self->priv->JNI_OnLoad = (jni_onload_t)LOOKUP_M("JNI_OnLoad"); + + return (self->priv->JNI_OnLoad != NULL); +} + +static void +generic_init(struct SupportModule *self, int width, int height, const char *home) +{ + self->priv->JNI_OnLoad(VM_M, NULL); +} + +static void +generic_input(struct SupportModule *self, int event, int x, int y, int finger) +{ +} + +static void +generic_update(struct SupportModule *self) +{ +} + +static void +generic_deinit(struct SupportModule *self) +{ +} + +static void +generic_pause(struct SupportModule *self) +{ +} + +static void +generic_resume(struct SupportModule *self) +{ +} + +APKENV_MODULE(generic, MODULE_PRIORITY_GENERIC) + diff --git a/modules/trg2.c b/modules/trg2.c new file mode 100644 index 0000000..ef8887f --- /dev/null +++ b/modules/trg2.c @@ -0,0 +1,123 @@ + +/** + * apkenv + * Copyright (c) 2012, Thomas Perl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **/ + + +/** + * Support module for That Rabbit Game 2 + * Download free .apk from: http://thp.io/2011/trg2/ + **/ + +#include "common.h" + +#include + +typedef void (*trg2_init_t)(JNIEnv *env, jobject obj) SOFTFP; +typedef void (*trg2_resize_t)(JNIEnv *env, jobject obj, jint width, jint height) SOFTFP; +typedef void (*trg2_touch_t)(JNIEnv *env, jobject obj, jint action, jfloat x, jfloat y, jint finger) SOFTFP; +typedef jboolean (*trg2_render_t)(JNIEnv *env, jobject obj) SOFTFP; +typedef jboolean (*trg2_accelerometer_t)(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) SOFTFP; + +struct SupportModulePriv { + jni_onload_t JNI_OnLoad; + trg2_init_t native_init; + trg2_resize_t native_resize; + trg2_touch_t native_touch; + trg2_render_t native_render; + trg2_accelerometer_t native_accelerometer; + SDL_Joystick *joystick; +}; +static struct SupportModulePriv trg2_priv; + +static int +trg2_try_init(struct SupportModule *self) +{ + self->priv->JNI_OnLoad = (jni_onload_t)LOOKUP_M("JNI_OnLoad"); + self->priv->native_init = (trg2_init_t)LOOKUP_M("nativeInit"); + self->priv->native_resize = (trg2_resize_t)LOOKUP_M("nativeResize"); + self->priv->native_touch = (trg2_touch_t)LOOKUP_M("nativeTouch"); + self->priv->native_render = (trg2_render_t)LOOKUP_M("nativeRender"); + self->priv->native_accelerometer = (trg2_accelerometer_t)LOOKUP_M("nativeAccelerometer"); + + return (self->priv->JNI_OnLoad != NULL && + self->priv->native_init != NULL && + self->priv->native_resize != NULL && + self->priv->native_touch != NULL && + self->priv->native_render != NULL); +} + +static void +trg2_init(struct SupportModule *self, int width, int height, const char *home) +{ + self->priv->joystick = SDL_JoystickOpen(0); + self->priv->JNI_OnLoad(VM_M, NULL); + self->priv->native_init(ENV_M, GLOBAL_M); + self->priv->native_resize(ENV_M, GLOBAL_M, width, height); +} + +static void +trg2_input(struct SupportModule *self, int event, int x, int y, int finger) +{ + self->priv->native_touch(ENV_M, GLOBAL_M, event, x, y, finger); +} + +#define CONVERT_ACCELEROMETER(x) ((float)(x) / 32768. * 9.81 * 2) +#define GET_AXIS(j, x) CONVERT_ACCELEROMETER(SDL_JoystickGetAxis(j, x)) + +static void +trg2_update(struct SupportModule *self) +{ + if (self->priv->native_accelerometer != NULL) { + SDL_JoystickUpdate(); + self->priv->native_accelerometer(ENV_M, GLOBAL_M, + GET_AXIS(self->priv->joystick, 0), + GET_AXIS(self->priv->joystick, 1), + GET_AXIS(self->priv->joystick, 2)); + } + + self->priv->native_render(ENV_M, GLOBAL_M); +} + +static void +trg2_deinit(struct SupportModule *self) +{ +} + +static void +trg2_pause(struct SupportModule *self) +{ +} + +static void +trg2_resume(struct SupportModule *self) +{ +} + +APKENV_MODULE(trg2, MODULE_PRIORITY_GAME) +