|
fyrenmoo@2677
|
1 |
#include <stdio.h> |
|
fyrenmoo@2677
|
2 |
#include <dlfcn.h> |
|
fyrenmoo@2677
|
3 |
#include "string.h" |
|
fyrenmoo@2677
|
4 |
#include "malloc.h" |
|
fyrenmoo@2677
|
5 |
|
|
fyrenmoo@2677
|
6 |
extern "C" char * cplus_demangle(const char *, int); |
|
fyrenmoo@2677
|
7 |
#define DMGL_PARAMS (1 << 0) |
|
fyrenmoo@2677
|
8 |
|
|
fyrenmoo@2677
|
9 |
struct VOffset |
|
fyrenmoo@2677
|
10 |
{ |
|
fyrenmoo@2677
|
11 |
int linux_offset; |
|
fyrenmoo@2677
|
12 |
int windows_offset; |
|
fyrenmoo@2677
|
13 |
}; |
|
fyrenmoo@2677
|
14 |
|
|
fyrenmoo@2677
|
15 |
static bool FindVFunc(void *handle, void **vtable, const char* vtable_end, const char *class_function, const char *params, VOffset *offsets); |
|
dvander@2250
|
16 |
|
|
dvander@2250
|
17 |
int main(int argc, char **argv) |
|
dvander@2250
|
18 |
{ |
|
dvander@2250
|
19 |
void *handle; |
|
dvander@2250
|
20 |
void **pVtable; |
|
dvander@2250
|
21 |
|
|
dvander@2250
|
22 |
VOffset offsets; |
|
dvander@2250
|
23 |
char *params = NULL; |
|
dvander@2250
|
24 |
bool ret; |
|
dvander@2250
|
25 |
|
|
dvander@2250
|
26 |
if (argc < 4) |
|
dvander@2250
|
27 |
{ |
|
dvander@2250
|
28 |
fprintf(stderr, "Usage: <binary> <vtable start symbol> <function> <optional: params> <optional: vtable end symbol>\n"); |
|
dvander@2250
|
29 |
return -1; |
|
dvander@2250
|
30 |
} |
|
dvander@2250
|
31 |
|
|
pred@2464
|
32 |
handle = dlopen(argv[1], RTLD_NOW); |
|
pred@2464
|
33 |
|
|
dvander@2250
|
34 |
if (handle == NULL) |
|
dvander@2250
|
35 |
{ |
|
dvander@2250
|
36 |
fprintf(stderr, "Failed to open server image, error [%s]\n", dlerror()); |
|
dvander@2250
|
37 |
return -1; |
|
dvander@2250
|
38 |
} |
|
dvander@2250
|
39 |
|
|
dvander@2250
|
40 |
pVtable = (void **)dlsym(handle, argv[2]); |
|
dvander@2250
|
41 |
|
|
dvander@2250
|
42 |
if (pVtable == NULL) |
|
dvander@2250
|
43 |
{ |
|
fyrenmoo@2677
|
44 |
char startSym[128]; |
|
fyrenmoo@2677
|
45 |
snprintf(startSym, sizeof(startSym), "_ZTV%d%s", strlen(argv[2]), argv[2]); |
|
fyrenmoo@2677
|
46 |
pVtable = (void **)dlsym(handle, startSym); |
|
fyrenmoo@2677
|
47 |
} |
|
fyrenmoo@2677
|
48 |
|
|
fyrenmoo@2677
|
49 |
if (pVtable == NULL) |
|
fyrenmoo@2677
|
50 |
{ |
|
dvander@2250
|
51 |
fprintf(stderr, "Invalid vtable symbol \"%s\"\n", argv[2]); |
|
pred@2464
|
52 |
dlclose(handle); |
|
dvander@2250
|
53 |
return -1; |
|
dvander@2250
|
54 |
} |
|
dvander@2250
|
55 |
|
|
dvander@2250
|
56 |
if (argc >= 5) |
|
dvander@2250
|
57 |
{ |
|
dvander@2250
|
58 |
params = argv[4]; |
|
dvander@2250
|
59 |
|
|
dvander@2250
|
60 |
if (params[0] == '"') |
|
dvander@2250
|
61 |
{ |
|
dvander@2250
|
62 |
params++; |
|
dvander@2250
|
63 |
} |
|
dvander@2250
|
64 |
|
|
dvander@2250
|
65 |
int len = strlen(params)-1; |
|
dvander@2250
|
66 |
|
|
dvander@2250
|
67 |
if (params[len] == '"') |
|
dvander@2250
|
68 |
{ |
|
dvander@2250
|
69 |
params[len] = '\0'; |
|
dvander@2250
|
70 |
} |
|
dvander@2250
|
71 |
|
|
dvander@2250
|
72 |
if (params[0] == 0) |
|
dvander@2250
|
73 |
{ |
|
dvander@2250
|
74 |
params = NULL; |
|
dvander@2250
|
75 |
} |
|
dvander@2250
|
76 |
} |
|
dvander@2250
|
77 |
|
|
dvander@2250
|
78 |
if (argc == 6) |
|
dvander@2250
|
79 |
{ |
|
dvander@2250
|
80 |
ret = FindVFunc(handle, pVtable, argv[5], argv[3], params, &offsets); |
|
dvander@2250
|
81 |
} |
|
dvander@2250
|
82 |
else |
|
dvander@2250
|
83 |
{ |
|
dvander@2250
|
84 |
ret = FindVFunc(handle, pVtable, "_ZTI", argv[3], params, &offsets); |
|
dvander@2250
|
85 |
} |
|
dvander@2250
|
86 |
|
|
dvander@2250
|
87 |
if (ret) |
|
dvander@2250
|
88 |
{ |
|
dvander@2250
|
89 |
if (params != NULL) |
|
dvander@2250
|
90 |
{ |
|
dvander@2250
|
91 |
printf("%s%s - Win: %i Linux : %i\n", argv[3], params, offsets.windows_offset, offsets.linux_offset); |
|
dvander@2250
|
92 |
} |
|
dvander@2250
|
93 |
else |
|
dvander@2250
|
94 |
{ |
|
dvander@2250
|
95 |
printf("%s - Win: %i Linux : %i\n", argv[3], offsets.windows_offset, offsets.linux_offset); |
|
dvander@2250
|
96 |
} |
|
dvander@2250
|
97 |
|
|
pred@2464
|
98 |
dlclose(handle); |
|
dvander@2250
|
99 |
return 0; |
|
dvander@2250
|
100 |
} |
|
dvander@2250
|
101 |
|
|
dvander@2250
|
102 |
fprintf(stderr, "Failed to find function!"); |
|
pred@2464
|
103 |
dlclose(handle); |
|
dvander@2250
|
104 |
return -1; |
|
dvander@2250
|
105 |
} |
|
fyrenmoo@2677
|
106 |
|
|
fyrenmoo@2677
|
107 |
static bool FindVFunc(void *handle, void **vtable, const char* vtable_end, const char *class_function, const char *params, VOffset *offsets) |
|
fyrenmoo@2677
|
108 |
{ |
|
fyrenmoo@2677
|
109 |
Dl_info d; |
|
fyrenmoo@2677
|
110 |
|
|
fyrenmoo@2677
|
111 |
int linux_offset = -1; |
|
fyrenmoo@2677
|
112 |
int windows_offset = -1; |
|
fyrenmoo@2677
|
113 |
|
|
fyrenmoo@2677
|
114 |
int overloads = 0; |
|
fyrenmoo@2677
|
115 |
int location = 0; |
|
fyrenmoo@2677
|
116 |
int start_offset = -1; |
|
fyrenmoo@2677
|
117 |
|
|
fyrenmoo@2677
|
118 |
for (int i=0; i< 1000; i++) |
|
fyrenmoo@2677
|
119 |
{ |
|
fyrenmoo@2677
|
120 |
void *FuncPtr = vtable[i]; |
|
fyrenmoo@2677
|
121 |
|
|
fyrenmoo@2677
|
122 |
int status = dladdr(FuncPtr, &d); |
|
fyrenmoo@2677
|
123 |
|
|
fyrenmoo@2677
|
124 |
if (!status) |
|
fyrenmoo@2677
|
125 |
{ |
|
fyrenmoo@2677
|
126 |
continue; |
|
fyrenmoo@2677
|
127 |
} |
|
fyrenmoo@2677
|
128 |
|
|
fyrenmoo@2677
|
129 |
if (i > 1 && strncmp(d.dli_sname, vtable_end, strlen(vtable_end)) == 0) |
|
fyrenmoo@2677
|
130 |
{ |
|
fyrenmoo@2677
|
131 |
break; |
|
fyrenmoo@2677
|
132 |
} |
|
fyrenmoo@2677
|
133 |
|
|
fyrenmoo@2677
|
134 |
char *name = cplus_demangle(d.dli_sname, DMGL_PARAMS); |
|
fyrenmoo@2677
|
135 |
|
|
fyrenmoo@2677
|
136 |
if (name == NULL) |
|
fyrenmoo@2677
|
137 |
{ |
|
fyrenmoo@2677
|
138 |
printf("Demangling failed\n"); |
|
fyrenmoo@2677
|
139 |
continue; |
|
fyrenmoo@2677
|
140 |
} |
|
fyrenmoo@2677
|
141 |
|
|
fyrenmoo@2677
|
142 |
char *foundfunction = strpbrk(name, ":"); |
|
fyrenmoo@2677
|
143 |
|
|
fyrenmoo@2677
|
144 |
if (foundfunction == NULL) |
|
fyrenmoo@2677
|
145 |
{ |
|
fyrenmoo@2677
|
146 |
//printf("Couldnt split function\n"); |
|
fyrenmoo@2677
|
147 |
free(name); |
|
fyrenmoo@2677
|
148 |
continue; |
|
fyrenmoo@2677
|
149 |
} |
|
fyrenmoo@2677
|
150 |
|
|
fyrenmoo@2677
|
151 |
//Skip both ':' chars |
|
fyrenmoo@2677
|
152 |
foundfunction += 2; |
|
fyrenmoo@2677
|
153 |
|
|
fyrenmoo@2677
|
154 |
|
|
fyrenmoo@2677
|
155 |
if (strncmp(foundfunction, class_function, strlen(class_function)) == 0 && foundfunction[strlen(class_function)] == '(') |
|
fyrenmoo@2677
|
156 |
{ |
|
fyrenmoo@2677
|
157 |
//printf("Symbol: %s Demangled: %s Offset: %i\n", d.dli_sname, name, i); |
|
fyrenmoo@2677
|
158 |
|
|
fyrenmoo@2677
|
159 |
//We have a pointer to a function, but it may be overloaded. |
|
fyrenmoo@2677
|
160 |
overloads++; |
|
fyrenmoo@2677
|
161 |
|
|
fyrenmoo@2677
|
162 |
if (start_offset == -1) |
|
fyrenmoo@2677
|
163 |
{ |
|
fyrenmoo@2677
|
164 |
start_offset = i-1; |
|
fyrenmoo@2677
|
165 |
} |
|
fyrenmoo@2677
|
166 |
|
|
fyrenmoo@2677
|
167 |
char *foundparams = strpbrk(foundfunction, "("); |
|
fyrenmoo@2677
|
168 |
|
|
fyrenmoo@2677
|
169 |
if (foundparams == NULL) |
|
fyrenmoo@2677
|
170 |
{ |
|
fyrenmoo@2677
|
171 |
printf("ARGH\n"); |
|
fyrenmoo@2677
|
172 |
free(name); |
|
fyrenmoo@2677
|
173 |
continue; |
|
fyrenmoo@2677
|
174 |
} |
|
fyrenmoo@2677
|
175 |
|
|
fyrenmoo@2677
|
176 |
if(params == NULL || strcmp(foundparams, params) == 0) |
|
fyrenmoo@2677
|
177 |
{ |
|
fyrenmoo@2677
|
178 |
//This is actually our function - So this is the linux offset |
|
fyrenmoo@2677
|
179 |
linux_offset = i; |
|
fyrenmoo@2677
|
180 |
location = overloads; |
|
fyrenmoo@2677
|
181 |
} |
|
fyrenmoo@2677
|
182 |
} |
|
fyrenmoo@2677
|
183 |
|
|
fyrenmoo@2677
|
184 |
free(name); |
|
fyrenmoo@2677
|
185 |
} |
|
fyrenmoo@2677
|
186 |
|
|
fyrenmoo@2677
|
187 |
windows_offset = (overloads-location) + start_offset; |
|
fyrenmoo@2677
|
188 |
|
|
fyrenmoo@2677
|
189 |
offsets->linux_offset = linux_offset - 2; |
|
fyrenmoo@2677
|
190 |
offsets->windows_offset = windows_offset - 2; |
|
fyrenmoo@2677
|
191 |
|
|
fyrenmoo@2677
|
192 |
return true; |
|
fyrenmoo@2677
|
193 |
} |