1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
#include "wrapper.h"
#include <stdio.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/mman.h>
#include "verbose.h"
#include <pthread.h>
static __thread bool skip_trace;
void
verbose_log(const char *fmt, ...)
{
if (skip_trace)
return;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mutex);
va_list ap;
va_start(ap, fmt);
static char buf[1024];
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
fprintf(stderr, "%lu: %s\n", pthread_self(), buf);
pthread_mutex_unlock(&mutex);
}
#ifdef VERBOSE_FUNCTIONS
# ifdef ANDROID_X86_LINKER
__asm__(
"wrapper_start: nop\n"
"wrapper_store: push %edi\npush %esp\npush %ebp\npush %ebx\npush %eax\npush %ecx\npush %edx\n"
"wrapper_symbol: pushl $0xFAFBFCFD\n"
"wrapper_trace: .byte 0xE8, 0xFA, 0xFB, 0xFC, 0xFD\n"
"wrapper_restore: pop %eax\npop %edx\npop %ecx\npop %eax\npop %ebx\npop %ebp\npop %esp\npop %edi\n"
"wrapper_jmp: .byte 0xE9, 0xFA, 0xFB, 0xFC, 0xFD\n"
"wrapper_ud: .byte 0x0F, 0xFF\n"
"wrapper_end: nop\n"
);
# define WRAPPER_TRACE
# else
# warning "no wrapper asm for this platform, function tracing is not available"
# endif
#endif
#ifdef WRAPPER_TRACE
extern unsigned char wrapper_start, wrapper_symbol, wrapper_trace, wrapper_restore, wrapper_jmp, wrapper_ud, wrapper_end;
static union {
void *ptr;
char* (*fun)(const char *mangled_name, char *output_buffer, size_t *length, int *status);
} __cxa_demangle;
static void
trace(const char *const symbol)
{
assert(symbol);
if (__cxa_demangle.ptr) {
int status;
char *demangled;
static __thread char *data;
static __thread size_t size;
if (skip_trace)
return;
skip_trace = true;
demangled = __cxa_demangle.fun(symbol, data, &size, &status);
skip_trace = false;
if (demangled) {
data = (data != demangled ? demangled : data);
verbose("trace: %s", demangled);
return;
}
}
verbose("trace: %s", symbol);
}
#endif
void
wrapper_set_cpp_demangler(void *function)
{
#ifdef WRAPPER_TRACE
__cxa_demangle.ptr = function;
verbose_log("wrapper: set cpp_demangler to %p", function);
#endif
}
void*
wrapper_create(const char *const symbol, void *function)
{
assert(symbol);
if (!function) {
verbose_log("FIXME: unimplemented symbol: %s", symbol);
return NULL;
}
#ifdef WRAPPER_TRACE
static const union {
void *ptr;
void (*fun)(const char*);
} tracefun = { .fun = trace };
const size_t len = strlen(symbol) + 1;
char *copy = malloc(len);
assert(copy && "welp, malloc failed");
memcpy(copy, symbol, len);
const size_t sz = &wrapper_end - &wrapper_start;
unsigned char *fun = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
assert(fun != MAP_FAILED);
memcpy(fun, &wrapper_start, sz);
#ifdef ANDROID_X86_LINKER
memcpy(fun + (&wrapper_symbol - &wrapper_start) + 1, ©, sizeof(copy));
{
const unsigned char *from = fun + (&wrapper_restore - &wrapper_start);
const intptr_t to = (unsigned char*)tracefun.ptr - from;
memcpy(fun + (&wrapper_trace - &wrapper_start) + 1, &to, sizeof(to));
}{
const unsigned char *from = fun + (&wrapper_ud - &wrapper_start);
const intptr_t to = (unsigned char*)function - from;
memcpy(fun + (&wrapper_jmp - &wrapper_start) + 1, &to, sizeof(to));
}
#else
# error "you forgot to implement the pointer setups for your asm platform"
#endif
mprotect(fun, sz, PROT_READ | PROT_EXEC);
return fun;
#else
return function;
#endif
}
|