]> git.zerfleddert.de Git - proxmark3-svn/blob - client/whereami.c
289aeb1f419e37dc617e5639acd7e0b9e3692a9c
[proxmark3-svn] / client / whereami.c
1 // (‑●‑●)> released under the WTFPL v2 license, by Gregory Pakosz (@gpakosz)
2 // https://github.com/gpakosz/whereami
3
4 // in case you want to #include "whereami.c" in a larger compilation unit
5 #if !defined(WHEREAMI_H)
6 #include <whereami.h>
7 #endif
8
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12
13 #if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC)
14 #include <stdlib.h>
15 #endif
16
17 #if !defined(WAI_MALLOC)
18 #define WAI_MALLOC(size) malloc(size)
19 #endif
20
21 #if !defined(WAI_FREE)
22 #define WAI_FREE(p) free(p)
23 #endif
24
25 #if !defined(WAI_REALLOC)
26 #define WAI_REALLOC(p, size) realloc(p, size)
27 #endif
28
29 #ifndef WAI_NOINLINE
30 #if defined(_MSC_VER)
31 #define WAI_NOINLINE __declspec(noinline)
32 #elif defined(__GNUC__)
33 #define WAI_NOINLINE __attribute__((noinline))
34 #else
35 #error unsupported compiler
36 #endif
37 #endif
38
39 #if defined(_MSC_VER)
40 #define WAI_RETURN_ADDRESS() _ReturnAddress()
41 #elif defined(__GNUC__)
42 #define WAI_RETURN_ADDRESS() __builtin_extract_return_addr(__builtin_return_address(0))
43 #else
44 #error unsupported compiler
45 #endif
46
47 #if defined(_WIN32)
48
49 #define WIN32_LEAN_AND_MEAN
50 #if defined(_MSC_VER)
51 #pragma warning(push, 3)
52 #endif
53 #include <windows.h>
54 #include <intrin.h>
55 #if defined(_MSC_VER)
56 #pragma warning(pop)
57 #endif
58
59 static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length)
60 {
61 wchar_t buffer1[MAX_PATH];
62 wchar_t buffer2[MAX_PATH];
63 wchar_t* path = NULL;
64 int length = -1;
65
66 for (;;)
67 {
68 DWORD size;
69 int length_, length__;
70
71 size = GetModuleFileNameW(module, buffer1, sizeof(buffer1) / sizeof(buffer1[0]));
72
73 if (size == 0)
74 break;
75 else if (size == (DWORD)(sizeof(buffer1) / sizeof(buffer1[0])))
76 {
77 DWORD size_ = size;
78 do
79 {
80 wchar_t* path_;
81
82 path_ = (wchar_t*)WAI_REALLOC(path, sizeof(wchar_t) * size_ * 2);
83 if (!path_)
84 break;
85 size_ *= 2;
86 path = path_;
87 size = GetModuleFileNameW(module, path, size_);
88 }
89 while (size == size_);
90
91 if (size == size_)
92 break;
93 }
94 else
95 path = buffer1;
96
97 if (!_wfullpath(buffer2, path, MAX_PATH))
98 break;
99 length_ = (int)wcslen(buffer2);
100 length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_ , out, capacity, NULL, NULL);
101
102 if (length__ == 0)
103 length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_, NULL, 0, NULL, NULL);
104 if (length__ == 0)
105 break;
106
107 if (length__ <= capacity && dirname_length)
108 {
109 int i;
110
111 for (i = length__ - 1; i >= 0; --i)
112 {
113 if (out[i] == '\\')
114 {
115 *dirname_length = i;
116 break;
117 }
118 }
119 }
120
121 length = length__;
122
123 break;
124 }
125
126 if (path != buffer1)
127 WAI_FREE(path);
128
129 return length;
130 }
131
132 WAI_NOINLINE
133 WAI_FUNCSPEC
134 int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
135 {
136 return WAI_PREFIX(getModulePath_)(NULL, out, capacity, dirname_length);
137 }
138
139 WAI_NOINLINE
140 WAI_FUNCSPEC
141 int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
142 {
143 HMODULE module;
144 int length = -1;
145
146 #if defined(_MSC_VER)
147 #pragma warning(push)
148 #pragma warning(disable: 4054)
149 #endif
150 if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)WAI_RETURN_ADDRESS(), &module))
151 #if defined(_MSC_VER)
152 #pragma warning(pop)
153 #endif
154 {
155 length = WAI_PREFIX(getModulePath_)(module, out, capacity, dirname_length);
156 }
157
158 return length;
159 }
160
161 #elif defined(__linux__)
162
163 #include <stdio.h>
164 #include <stdlib.h>
165 #include <string.h>
166 #include <limits.h>
167 #ifndef __STDC_FORMAT_MACROS
168 #define __STDC_FORMAT_MACROS
169 #endif
170 #include <inttypes.h>
171
172 #if !defined(WAI_PROC_SELF_EXE)
173 #define WAI_PROC_SELF_EXE "/proc/self/exe"
174 #endif
175
176 WAI_FUNCSPEC
177 int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
178 {
179 char buffer[PATH_MAX];
180 char* resolved = NULL;
181 int length = -1;
182
183 for (;;)
184 {
185 resolved = realpath(WAI_PROC_SELF_EXE, buffer);
186 if (!resolved)
187 break;
188
189 length = (int)strlen(resolved);
190 if (length <= capacity)
191 {
192 memcpy(out, resolved, length);
193
194 if (dirname_length)
195 {
196 int i;
197
198 for (i = length - 1; i >= 0; --i)
199 {
200 if (out[i] == '/')
201 {
202 *dirname_length = i;
203 break;
204 }
205 }
206 }
207 }
208
209 break;
210 }
211
212 return length;
213 }
214
215 #if !defined(WAI_PROC_SELF_MAPS_RETRY)
216 #define WAI_PROC_SELF_MAPS_RETRY 5
217 #endif
218
219 #if !defined(WAI_PROC_SELF_MAPS)
220 #define WAI_PROC_SELF_MAPS "/proc/self/maps"
221 #endif
222
223 #if defined(__ANDROID__) || defined(ANDROID)
224 #include <fcntl.h>
225 #include <sys/mman.h>
226 #endif
227
228 WAI_NOINLINE
229 WAI_FUNCSPEC
230 int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
231 {
232 int length = -1;
233 FILE* maps = NULL;
234 int i;
235
236 for (i = 0; i < WAI_PROC_SELF_MAPS_RETRY; ++i)
237 {
238 maps = fopen(WAI_PROC_SELF_MAPS, "r");
239 if (!maps)
240 break;
241
242 for (;;)
243 {
244 char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX];
245 uint64_t low, high;
246 char perms[5];
247 uint64_t offset;
248 uint32_t major, minor;
249 char path[PATH_MAX];
250 uint32_t inode;
251
252 if (!fgets(buffer, sizeof(buffer), maps))
253 break;
254
255 if (sscanf(buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8)
256 {
257 uint64_t addr = (uint64_t)(uintptr_t)WAI_RETURN_ADDRESS();
258 if (low <= addr && addr <= high)
259 {
260 char* resolved;
261
262 resolved = realpath(path, buffer);
263 if (!resolved)
264 break;
265
266 length = (int)strlen(resolved);
267 #if defined(__ANDROID__) || defined(ANDROID)
268 if (length > 4
269 &&buffer[length - 1] == 'k'
270 &&buffer[length - 2] == 'p'
271 &&buffer[length - 3] == 'a'
272 &&buffer[length - 4] == '.')
273 {
274 int fd = open(path, O_RDONLY);
275 char* begin;
276 char* p;
277
278 begin = (char*)mmap(0, offset, PROT_READ, MAP_SHARED, fd, 0);
279 p = begin + offset;
280
281 while (p >= begin) // scan backwards
282 {
283 if (*((uint32_t*)p) == 0x04034b50UL) // local file header found
284 {
285 uint16_t length_ = *((uint16_t*)(p + 26));
286
287 if (length + 2 + length_ < (int)sizeof(buffer))
288 {
289 memcpy(&buffer[length], "!/", 2);
290 memcpy(&buffer[length + 2], p + 30, length_);
291 length += 2 + length_;
292 }
293
294 break;
295 }
296
297 p -= 4;
298 }
299
300 munmap(begin, offset);
301 close(fd);
302 }
303 #endif
304 if (length <= capacity)
305 {
306 memcpy(out, resolved, length);
307
308 if (dirname_length)
309 {
310 int i;
311
312 for (i = length - 1; i >= 0; --i)
313 {
314 if (out[i] == '/')
315 {
316 *dirname_length = i;
317 break;
318 }
319 }
320 }
321 }
322
323 break;
324 }
325 }
326 }
327
328 fclose(maps);
329
330 if (length != -1)
331 break;
332 }
333
334 return length;
335 }
336
337 #elif defined(__APPLE__)
338
339 #define _DARWIN_BETTER_REALPATH
340 #include <mach-o/dyld.h>
341 #include <limits.h>
342 #include <stdlib.h>
343 #include <string.h>
344 #include <dlfcn.h>
345
346 WAI_FUNCSPEC
347 int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
348 {
349 char buffer1[PATH_MAX];
350 char buffer2[PATH_MAX];
351 char* path = buffer1;
352 char* resolved = NULL;
353 int length = -1;
354
355 for (;;)
356 {
357 uint32_t size = (uint32_t)sizeof(buffer1);
358 if (_NSGetExecutablePath(path, &size) == -1)
359 {
360 path = (char*)WAI_MALLOC(size);
361 if (!_NSGetExecutablePath(path, &size))
362 break;
363 }
364
365 resolved = realpath(path, buffer2);
366 if (!resolved)
367 break;
368
369 length = (int)strlen(resolved);
370 if (length <= capacity)
371 {
372 memcpy(out, resolved, length);
373
374 if (dirname_length)
375 {
376 int i;
377
378 for (i = length - 1; i >= 0; --i)
379 {
380 if (out[i] == '/')
381 {
382 *dirname_length = i;
383 break;
384 }
385 }
386 }
387 }
388
389 break;
390 }
391
392 if (path != buffer1)
393 WAI_FREE(path);
394
395 return length;
396 }
397
398 WAI_NOINLINE
399 WAI_FUNCSPEC
400 int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
401 {
402 char buffer[PATH_MAX];
403 char* resolved = NULL;
404 int length = -1;
405
406 for(;;)
407 {
408 Dl_info info;
409
410 if (dladdr(WAI_RETURN_ADDRESS(), &info))
411 {
412 resolved = realpath(info.dli_fname, buffer);
413 if (!resolved)
414 break;
415
416 length = (int)strlen(resolved);
417 if (length <= capacity)
418 {
419 memcpy(out, resolved, length);
420
421 if (dirname_length)
422 {
423 int i;
424
425 for (i = length - 1; i >= 0; --i)
426 {
427 if (out[i] == '/')
428 {
429 *dirname_length = i;
430 break;
431 }
432 }
433 }
434 }
435 }
436
437 break;
438 }
439
440 return length;
441 }
442
443 #elif defined(__QNXNTO__)
444
445 #include <limits.h>
446 #include <stdio.h>
447 #include <stdlib.h>
448 #include <string.h>
449 #include <dlfcn.h>
450
451 #if !defined(WAI_PROC_SELF_EXE)
452 #define WAI_PROC_SELF_EXE "/proc/self/exefile"
453 #endif
454
455 WAI_FUNCSPEC
456 int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
457 {
458 char buffer1[PATH_MAX];
459 char buffer2[PATH_MAX];
460 char* resolved = NULL;
461 FILE* self_exe = NULL;
462 int length = -1;
463
464 for (;;)
465 {
466 self_exe = fopen(WAI_PROC_SELF_EXE, "r");
467 if (!self_exe)
468 break;
469
470 if (!fgets(buffer1, sizeof(buffer1), self_exe))
471 break;
472
473 resolved = realpath(buffer1, buffer2);
474 if (!resolved)
475 break;
476
477 length = (int)strlen(resolved);
478 if (length <= capacity)
479 {
480 memcpy(out, resolved, length);
481
482 if (dirname_length)
483 {
484 int i;
485
486 for (i = length - 1; i >= 0; --i)
487 {
488 if (out[i] == '/')
489 {
490 *dirname_length = i;
491 break;
492 }
493 }
494 }
495 }
496
497 break;
498 }
499
500 fclose(self_exe);
501
502 return length;
503 }
504
505 WAI_FUNCSPEC
506 int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
507 {
508 char buffer[PATH_MAX];
509 char* resolved = NULL;
510 int length = -1;
511
512 for(;;)
513 {
514 Dl_info info;
515
516 if (dladdr(WAI_RETURN_ADDRESS(), &info))
517 {
518 resolved = realpath(info.dli_fname, buffer);
519 if (!resolved)
520 break;
521
522 length = (int)strlen(resolved);
523 if (length <= capacity)
524 {
525 memcpy(out, resolved, length);
526
527 if (dirname_length)
528 {
529 int i;
530
531 for (i = length - 1; i >= 0; --i)
532 {
533 if (out[i] == '/')
534 {
535 *dirname_length = i;
536 break;
537 }
538 }
539 }
540 }
541 }
542
543 break;
544 }
545
546 return length;
547 }
548
549 #elif defined(__DragonFly__) || defined(__FreeBSD__) || \
550 defined(__FreeBSD_kernel__) || defined(__NetBSD__)
551
552 #include <limits.h>
553 #include <stdlib.h>
554 #include <string.h>
555 #include <sys/types.h>
556 #include <sys/sysctl.h>
557 #include <dlfcn.h>
558
559 WAI_FUNCSPEC
560 int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
561 {
562 char buffer1[PATH_MAX];
563 char buffer2[PATH_MAX];
564 char* path = buffer1;
565 char* resolved = NULL;
566 int length = -1;
567
568 for (;;)
569 {
570 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
571 size_t size = sizeof(buffer1);
572
573 if (sysctl(mib, (u_int)(sizeof(mib) / sizeof(mib[0])), path, &size, NULL, 0) != 0)
574 break;
575
576 resolved = realpath(path, buffer2);
577 if (!resolved)
578 break;
579
580 length = (int)strlen(resolved);
581 if (length <= capacity)
582 {
583 memcpy(out, resolved, length);
584
585 if (dirname_length)
586 {
587 int i;
588
589 for (i = length - 1; i >= 0; --i)
590 {
591 if (out[i] == '/')
592 {
593 *dirname_length = i;
594 break;
595 }
596 }
597 }
598 }
599
600 break;
601 }
602
603 if (path != buffer1)
604 WAI_FREE(path);
605
606 return length;
607 }
608
609 WAI_NOINLINE
610 WAI_FUNCSPEC
611 int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
612 {
613 char buffer[PATH_MAX];
614 char* resolved = NULL;
615 int length = -1;
616
617 for(;;)
618 {
619 Dl_info info;
620
621 if (dladdr(WAI_RETURN_ADDRESS(), &info))
622 {
623 resolved = realpath(info.dli_fname, buffer);
624 if (!resolved)
625 break;
626
627 length = (int)strlen(resolved);
628 if (length <= capacity)
629 {
630 memcpy(out, resolved, length);
631
632 if (dirname_length)
633 {
634 int i;
635
636 for (i = length - 1; i >= 0; --i)
637 {
638 if (out[i] == '/')
639 {
640 *dirname_length = i;
641 break;
642 }
643 }
644 }
645 }
646 }
647
648 break;
649 }
650
651 return length;
652 }
653
654 #else
655
656 #error unsupported platform
657
658 #endif
659
660 #ifdef __cplusplus
661 }
662 #endif
Impressum, Datenschutz