7 #if !defined(WHEREAMI_H)
15 #if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC)
19 #if !defined(WAI_MALLOC)
20 #define WAI_MALLOC(size) malloc(size)
23 #if !defined(WAI_FREE)
24 #define WAI_FREE(p) free(p)
27 #if !defined(WAI_REALLOC)
28 #define WAI_REALLOC(p, size) realloc(p, size)
33 #define WAI_NOINLINE __declspec(noinline)
34 #elif defined(__GNUC__)
35 #define WAI_NOINLINE __attribute__((noinline))
37 #error unsupported compiler
42 #define WAI_RETURN_ADDRESS() _ReturnAddress()
43 #elif defined(__GNUC__)
44 #define WAI_RETURN_ADDRESS() __builtin_extract_return_addr(__builtin_return_address(0))
46 #error unsupported compiler
51 #ifndef WIN32_LEAN_AND_MEAN
52 #define WIN32_LEAN_AND_MEAN
55 #pragma warning(push, 3)
64 static int WAI_PREFIX(getModulePath_)(HMODULE module,
char* out,
int capacity,
int* dirname_length)
66 wchar_t buffer1[MAX_PATH];
67 wchar_t buffer2[MAX_PATH];
72 for (ok =
false; !ok; ok =
true)
75 int length_, length__;
77 size = GetModuleFileNameW(module, buffer1,
sizeof(buffer1) /
sizeof(buffer1[0]));
81 else if (size == (DWORD)(
sizeof(buffer1) /
sizeof(buffer1[0])))
93 size = GetModuleFileNameW(module,
path, size_);
95 while (size == size_);
103 if (!_wfullpath(buffer2,
path, MAX_PATH))
105 length_ = (int)wcslen(buffer2);
106 length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_ , out, capacity, NULL, NULL);
109 length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_, NULL, 0, NULL, NULL);
113 if (length__ <= capacity && dirname_length)
117 for (i = length__ - 1; i >= 0; --i)
133 return ok ? length : -1;
139 return WAI_PREFIX(getModulePath_)(NULL, out, capacity, dirname_length);
148 #if defined(_MSC_VER)
149 #pragma warning(push)
150 #pragma warning(disable: 4054)
152 if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)
WAI_RETURN_ADDRESS(), &module))
153 #
if defined(_MSC_VER)
157 length =
WAI_PREFIX(getModulePath_)(module, out, capacity, dirname_length);
163 #elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun) || defined(WAI_USE_PROC_SELF_EXE)
168 #if defined(__linux__)
169 #include <linux/limits.h>
173 #ifndef __STDC_FORMAT_MACROS
174 #define __STDC_FORMAT_MACROS
176 #include <inttypes.h>
179 #if !defined(WAI_PROC_SELF_EXE)
181 #define WAI_PROC_SELF_EXE "/proc/self/path/a.out"
183 #define WAI_PROC_SELF_EXE "/proc/self/exe"
190 char buffer[PATH_MAX];
191 char* resolved = NULL;
195 for (ok =
false; !ok; ok =
true)
197 resolved = realpath(WAI_PROC_SELF_EXE, buffer);
201 length = (int)strlen(resolved);
202 if (length <= capacity)
204 memcpy(out, resolved, length);
210 for (i = length - 1; i >= 0; --i)
222 return ok ? length : -1;
225 #if !defined(WAI_PROC_SELF_MAPS_RETRY)
226 #define WAI_PROC_SELF_MAPS_RETRY 5
229 #if !defined(WAI_PROC_SELF_MAPS)
231 #define WAI_PROC_SELF_MAPS "/proc/self/map"
233 #define WAI_PROC_SELF_MAPS "/proc/self/maps"
237 #if defined(__ANDROID__) || defined(ANDROID)
239 #include <sys/mman.h>
250 for (
int r = 0;
r < WAI_PROC_SELF_MAPS_RETRY; ++
r)
252 maps = fopen(WAI_PROC_SELF_MAPS,
"r");
258 char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX];
262 uint32_t major, minor;
266 if (!fgets(buffer,
sizeof(buffer), maps))
269 if (sscanf(buffer,
"%" PRIx64
"-%" PRIx64
" %s %" PRIx64
" %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode,
path) == 8)
272 if (low <= addr && addr <= high)
276 resolved = realpath(
path, buffer);
280 length = (int)strlen(resolved);
281 #if defined(__ANDROID__) || defined(ANDROID)
283 &&buffer[length - 1] ==
'k'
284 &&buffer[length - 2] ==
'p'
285 &&buffer[length - 3] ==
'a'
286 &&buffer[length - 4] ==
'.')
288 int fd = open(
path, O_RDONLY);
295 char* begin = (
char*)mmap(0, offset, PROT_READ, MAP_SHARED, fd, 0);
296 if (begin == MAP_FAILED)
303 char*
p = begin + offset - 30;
306 if (*((uint32_t*)
p) == 0x04034b50UL)
308 uint16_t length_ = *((uint16_t*)(
p + 26));
310 if (length + 2 + length_ < (
int)
sizeof(buffer))
312 memcpy(&buffer[length],
"!/", 2);
313 memcpy(&buffer[length + 2],
p + 30, length_);
314 length += 2 + length_;
323 munmap(begin, offset);
327 if (length <= capacity)
329 memcpy(out, resolved, length);
335 for (i = length - 1; i >= 0; --i)
361 #elif defined(__APPLE__)
363 #define _DARWIN_BETTER_REALPATH
364 #include <mach-o/dyld.h>
374 char buffer1[PATH_MAX];
375 char buffer2[PATH_MAX];
376 char*
path = buffer1;
377 char* resolved = NULL;
381 for (ok =
false; !ok; ok =
true)
383 uint32_t size = (uint32_t)
sizeof(buffer1);
384 if (_NSGetExecutablePath(
path, &size) == -1)
387 if (!_NSGetExecutablePath(
path, &size))
391 resolved = realpath(
path, buffer2);
395 length = (int)strlen(resolved);
396 if (length <= capacity)
398 memcpy(out, resolved, length);
404 for (i = length - 1; i >= 0; --i)
419 return ok ? length : -1;
425 char buffer[PATH_MAX];
426 char* resolved = NULL;
435 resolved = realpath(info.dli_fname, buffer);
439 length = (int)strlen(resolved);
440 if (length <= capacity)
442 memcpy(out, resolved, length);
448 for (i = length - 1; i >= 0; --i)
466 #elif defined(__QNXNTO__)
475 #if !defined(WAI_PROC_SELF_EXE)
476 #define WAI_PROC_SELF_EXE "/proc/self/exefile"
482 char buffer1[PATH_MAX];
483 char buffer2[PATH_MAX];
484 char* resolved = NULL;
485 FILE* self_exe = NULL;
489 for (ok =
false; !ok; ok =
true)
491 self_exe = fopen(WAI_PROC_SELF_EXE,
"r");
495 if (!fgets(buffer1,
sizeof(buffer1), self_exe))
498 resolved = realpath(buffer1, buffer2);
502 length = (int)strlen(resolved);
503 if (length <= capacity)
505 memcpy(out, resolved, length);
511 for (i = length - 1; i >= 0; --i)
525 return ok ? length : -1;
531 char buffer[PATH_MAX];
532 char* resolved = NULL;
541 resolved = realpath(info.dli_fname, buffer);
545 length = (int)strlen(resolved);
546 if (length <= capacity)
548 memcpy(out, resolved, length);
554 for (i = length - 1; i >= 0; --i)
572 #elif defined(__DragonFly__) || defined(__FreeBSD__) || \
573 defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
578 #include <sys/types.h>
579 #include <sys/sysctl.h>
583 #if defined(__OpenBSD__)
591 char buffer2[PATH_MAX];
592 char buffer3[PATH_MAX];
593 char** argv = (
char**)buffer1;
594 char* resolved = NULL;
598 for (ok =
false; !ok; ok =
true)
600 int mib[4] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV };
603 if (sysctl(mib, 4, NULL, &size, NULL, 0) != 0)
606 if (size >
sizeof(buffer1))
613 if (sysctl(mib, 4, argv, &size, NULL, 0) != 0)
616 if (strchr(argv[0],
'/'))
618 resolved = realpath(argv[0], buffer2);
624 const char* PATH = getenv(
"PATH");
628 size_t argv0_length = strlen(argv[0]);
630 const char* begin = PATH;
633 const char* separator = strchr(begin,
':');
634 const char*
end = separator ? separator : begin + strlen(begin);
638 if (*(
end -1) ==
'/')
641 if (((
end - begin) + 1 + argv0_length + 1) <=
sizeof(buffer2))
643 memcpy(buffer2, begin,
end - begin);
644 buffer2[
end - begin] =
'/';
645 memcpy(buffer2 + (
end - begin) + 1, argv[0], argv0_length + 1);
647 resolved = realpath(buffer2, buffer3);
663 length = (int)strlen(resolved);
664 if (length <= capacity)
666 memcpy(out, resolved, length);
672 for (i = length - 1; i >= 0; --i)
684 if (argv != (
char**)buffer1)
687 return ok ? length : -1;
695 char buffer1[PATH_MAX];
696 char buffer2[PATH_MAX];
697 char*
path = buffer1;
698 char* resolved = NULL;
702 for (ok =
false; !ok; ok =
true)
704 #if defined(__NetBSD__)
705 int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME };
707 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
709 size_t size =
sizeof(buffer1);
711 if (sysctl(mib, 4,
path, &size, NULL, 0) != 0)
714 resolved = realpath(
path, buffer2);
718 length = (int)strlen(resolved);
719 if (length <= capacity)
721 memcpy(out, resolved, length);
727 for (i = length - 1; i >= 0; --i)
739 return ok ? length : -1;
747 char buffer[PATH_MAX];
748 char* resolved = NULL;
757 resolved = realpath(info.dli_fname, buffer);
761 length = (int)strlen(resolved);
762 if (length <= capacity)
764 memcpy(out, resolved, length);
770 for (i = length - 1; i >= 0; --i)
790 #error unsupported platform
#define WAI_RETURN_ADDRESS()
#define WAI_REALLOC(p, size)
WAI_FUNCSPEC int WAI_PREFIX() getExecutablePath(char *out, int capacity, int *dirname_length)
Returns the path to the current executable.
WAI_FUNCSPEC int WAI_PREFIX() getModulePath(char *out, int capacity, int *dirname_length)
Returns the path to the current module.
#define WAI_PREFIX(function)