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