Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

latehooks and function tracing #35

Merged
merged 1 commit into from
Mar 2, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
130 changes: 113 additions & 17 deletions apkenv.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "apklib/apklib.h"
#include "imagelib/imagelib_priv.h"
#include "debug/debug.h"
#include "debug/wrappers.h"
#include "compat/gles_wrappers.h"
#include "compat/gles2_wrappers.h"
#include "linker/linker.h"
Expand Down Expand Up @@ -227,10 +228,22 @@ static void
usage()
{
if (global.platform->get_path(PLATFORM_PATH_INSTALL_DIRECTORY) != NULL) {
printf("Usage: %s <file.apk>\n",global.apkenv_executable);
printf("Usage: %s [options] <file.apk>\n",global.apkenv_executable);
printf("Available options are:\n");
} else {
printf("Usage: %s [--install] <file.apk>\n",global.apkenv_executable);
printf("Usage: %s [options] <file.apk>\n",global.apkenv_executable);
printf("Available options are:\n");
printf("\t--install\tinstall the apk and set up desktop entries.\n");
}
printf("\t--enable-trace-latehooked|-l\t\tEnable tracing of late hooked functions.\n");
printf("\t--enable-trace_unhooked|-u\t\tEnable tracing of unhooked functions.\n");
printf("\t--enable-trace-dynhook|-d\t\tEnable tracing of dynamically loaded functions.\n");
printf("\t--enable-trace-arm-injection|-ai\tEnable tracing of unhooked internal ARM functions. (EXPERIMENTAL)\n");
printf("\t--enable-trace-thumb-injection|-ti\tEnable tracing of unhooked internal THUMB functions. (HIGHLY EXPERIMENTAL)\n");
printf("\t--trace-function|-tf <function>\t\tTrace the specified function.\n");
printf("\t--trace-all|-ta\t\t\t\tTrace all functions.\n");
printf("\t--help|-h\t\t\t\tPrint this help.\n");

exit(1);
}

Expand Down Expand Up @@ -311,10 +324,7 @@ operation(const char *operation, const char *filename)
app_name, apkenv_absolute, apk_absolute, icon_filename);
fclose(desktop);
printf("Installed: %s\n", desktop_filename);
exit(0);
}

usage();
}


Expand Down Expand Up @@ -354,20 +364,95 @@ int main(int argc, char **argv)
global.apkenv_copyright = APKENV_COPYRIGHT;

printf("%s\n%s\n\n", global.apkenv_headline, global.apkenv_copyright);

switch (argc) {
case 2:
/* One argument - the .apk (continue below) */
break;
case 3:
/* Two arguments - operation + the apk */
operation(argv[1], argv[2]);
break;
default:
/* Wrong number of arguments */
usage();

global.trace_all = 0;
global.trace_latehooked = 0;
global.trace_unhooked = 0;
global.trace_dynhooked = 0;
global.trace_arm_injection = 0;
global.trace_thumb_injection = 0;
global.functions_to_trace = NULL;

if(argc <= 1) {
printf("ERROR: too few arguments\n");
usage();
}

if(argc >= 2) {
int i;
// parse argv, last argument has to be the apk
for(i=1;i<argc;i++) {
if(0 == strcmp(argv[i], "--install")) {
i++;
if(i >= argc) {
printf("missing argument to --install\n");
return -1;
}
operation(argv[i-1],argv[i]);
}
else if(0 == strcmp(argv[i], "--help")
|| 0 == strcmp(argv[i], "-h")) {
usage();
}
else if(0 == strcmp(argv[i], "--enable-trace-latehooked")
|| 0 == strcmp(argv[i], "-l")) {
global.trace_latehooked = 1;
}
else if(0 == strcmp(argv[i], "--enable-trace-unhooked")
|| 0 == strcmp(argv[i], "-u")) {
global.trace_unhooked = 1;
}
else if(0 == strcmp(argv[i], "--enable-trace-dynhooked")
|| 0 == strcmp(argv[i], "-d")) {
global.trace_dynhooked = 1;
}
else if(0 == strcmp(argv[i], "--enable-trace-arm-injection")
|| 0 == strcmp(argv[i], "-ai")) {
global.trace_arm_injection = 1;
}
else if(0 == strcmp(argv[i], "--enable-trace-thumb-injection")
|| 0 == strcmp(argv[i], "-ti")) {
global.trace_thumb_injection = 1;
}
else if(0 == strcmp(argv[i], "--trace-all")
|| 0 == strcmp(argv[i], "-ta")) {
global.trace_all = 1;
}
else if(0 == strcmp(argv[i], "--trace-function")
|| 0 == strcmp(argv[i], "-tf")) {
i++;
if(i >= argc) {
printf("ERROR: missing argument to %s", argv[i-1]);
usage();
}
if(NULL == global.functions_to_trace) {
global.functions_to_trace = (struct trace_list*)malloc(sizeof(struct trace_list));
global.functions_to_trace->name = argv[i];
global.functions_to_trace->next = NULL;
}
else {
struct trace_list *it = global.functions_to_trace;
struct trace_list *last = NULL;
while(NULL != it) {
last = it;
it = it->next;
}
last->next = (struct trace_list*)malloc(sizeof(struct trace_list));
last->next->name = argv[i];
last->next->next = NULL;
}
}
}
}

if((global.trace_all || NULL != global.functions_to_trace)
&& !global.trace_latehooked && !global.trace_unhooked
&& !global.trace_dynhooked && !global.trace_arm_injection
&& !global.trace_thumb_injection) {
printf("WARNING: specified --trace-all or --trace-function but no type of tracing is enabled\n");
usage();
}

memset(&global_module_hacks,0,sizeof(global_module_hacks));

global.lookup_symbol = lookup_symbol_impl;
Expand Down Expand Up @@ -569,6 +654,17 @@ int main(int argc, char **argv)
apk_close(global.apklib_handle);
global.platform->exit();

release_all_wrappers();
if(NULL != global.functions_to_trace) {
struct trace_list *it = global.functions_to_trace;
struct trace_list *next;
while(it != NULL) {
next = it->next;
free(it);
it = next;
}
}

return 0;
}

14 changes: 14 additions & 0 deletions apkenv.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ struct PlatformSupport {
void (*exit)();
};

struct trace_list {
char *name;
struct trace_list *next;
};

struct GlobalState {
const char *apkenv_executable;
const char *apkenv_headline;
Expand All @@ -143,6 +148,15 @@ struct GlobalState {

struct ResourceStrings resource_strings;

/* tracing/debugging */
int trace_latehooked;
int trace_unhooked;
int trace_dynhooked;
int trace_arm_injection;
int trace_thumb_injection;
struct trace_list *functions_to_trace;
int trace_all;

int loader_seen_glesv1;
int loader_seen_glesv2;

Expand Down
2 changes: 1 addition & 1 deletion compat/egl_wrappers.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ void *
my_eglGetProcAddress(const char *procname)
{
WRAPPERS_DEBUG_PRINTF("eglGetProcAddress(%s)\n", procname);
void *sym = get_hooked_symbol(procname);
void *sym = get_hooked_symbol(procname, 1);
if (sym == NULL)
printf("eglGetProcAddress: unimplemented: %s\n", procname);
return sym;
Expand Down
8 changes: 5 additions & 3 deletions compat/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
#include "gles2_wrappers.h"
#include "pthread_wrappers.h"

#include "../debug/wrappers.h"

extern struct GlobalState global;

char my___sF[SIZEOF_SF * 3];
Expand Down Expand Up @@ -106,7 +108,7 @@ hook_cmp(const void *p1, const void *p2)

#define HOOK_SIZE (sizeof(struct _hook))

void *get_hooked_symbol(const char *sym)
void *get_hooked_symbol(const char *sym, int die_if_pthread)
{
struct _hook target;
target.name = sym;
Expand All @@ -120,7 +122,7 @@ void *get_hooked_symbol(const char *sym)

if (strstr(sym, "pthread") != NULL) {
printf("Unimplemented: %s\n", sym);
exit(0);
if(die_if_pthread) exit(0);
}

return NULL;
Expand Down Expand Up @@ -154,7 +156,7 @@ void *get_hooked_symbol_dlfcn(void *handle, const char *sym)
#endif
}

return get_hooked_symbol(sym);
return get_hooked_symbol(sym, 1);
}

int register_hooks(const struct _hook *new_hooks, size_t count)
Expand Down
3 changes: 2 additions & 1 deletion compat/hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**/

#include <stddef.h>

struct _hook {
const char *name;
void *func;
};

void *get_hooked_symbol(const char *sym);
void *get_hooked_symbol(const char *sym, int die_if_pthread);
void *get_hooked_symbol_dlfcn(void *handle, const char *sym);
void *get_builtin_lib_handle(const char *libname);
int is_builtin_lib_handle(void *handle);
Expand Down