diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2013-06-26 05:01:35 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2013-06-26 05:01:35 +0000 |
commit | 50188c1f42c122640ab9ccac2134acf371c26b2c (patch) | |
tree | 05539e5a83063a0eeda3c9211dfb8153cc750f0c /lib | |
parent | 2c63b27e9f36dddc2660639026b19e606ad52cd0 (diff) | |
download | llvm-50188c1f42c122640ab9ccac2134acf371c26b2c.tar.gz llvm-50188c1f42c122640ab9ccac2134acf371c26b2c.tar.bz2 llvm-50188c1f42c122640ab9ccac2134acf371c26b2c.tar.xz |
Port GetMainExecutable over to PathV2.
I will remove the V1 version as soon as I change clang in the next commit.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184914 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Support/Unix/PathV2.inc | 106 | ||||
-rw-r--r-- | lib/Support/Windows/PathV2.inc | 7 |
2 files changed, 113 insertions, 0 deletions
diff --git a/lib/Support/Unix/PathV2.inc b/lib/Support/Unix/PathV2.inc index f5903f1530..c7a1c92d46 100644 --- a/lib/Support/Unix/PathV2.inc +++ b/lib/Support/Unix/PathV2.inc @@ -109,6 +109,112 @@ namespace { namespace llvm { namespace sys { namespace fs { +#if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ + defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) || \ + defined(__linux__) || defined(__CYGWIN__) +static int +test_dir(char buf[PATH_MAX], char ret[PATH_MAX], + const char *dir, const char *bin) +{ + struct stat sb; + + snprintf(buf, PATH_MAX, "%s/%s", dir, bin); + if (realpath(buf, ret) == NULL) + return (1); + if (stat(buf, &sb) != 0) + return (1); + + return (0); +} + +static char * +getprogpath(char ret[PATH_MAX], const char *bin) +{ + char *pv, *s, *t, buf[PATH_MAX]; + + /* First approach: absolute path. */ + if (bin[0] == '/') { + if (test_dir(buf, ret, "/", bin) == 0) + return (ret); + return (NULL); + } + + /* Second approach: relative path. */ + if (strchr(bin, '/') != NULL) { + if (getcwd(buf, PATH_MAX) == NULL) + return (NULL); + if (test_dir(buf, ret, buf, bin) == 0) + return (ret); + return (NULL); + } + + /* Third approach: $PATH */ + if ((pv = getenv("PATH")) == NULL) + return (NULL); + s = pv = strdup(pv); + if (pv == NULL) + return (NULL); + while ((t = strsep(&s, ":")) != NULL) { + if (test_dir(buf, ret, t, bin) == 0) { + free(pv); + return (ret); + } + } + free(pv); + return (NULL); +} +#endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__ + +/// GetMainExecutable - Return the path to the main executable, given the +/// value of argv[0] from program startup. +std::string getMainExecutable(const char *argv0, void *MainAddr) { +#if defined(__APPLE__) + // On OS X the executable path is saved to the stack by dyld. Reading it + // from there is much faster than calling dladdr, especially for large + // binaries with symbols. + char exe_path[MAXPATHLEN]; + uint32_t size = sizeof(exe_path); + if (_NSGetExecutablePath(exe_path, &size) == 0) { + char link_path[MAXPATHLEN]; + if (realpath(exe_path, link_path)) + return Path(link_path); + } +#elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ + defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) + char exe_path[PATH_MAX]; + + if (getprogpath(exe_path, argv0) != NULL) + return Path(exe_path); +#elif defined(__linux__) || defined(__CYGWIN__) + char exe_path[MAXPATHLEN]; + StringRef aPath("/proc/self/exe"); + if (sys::fs::exists(aPath)) { + // /proc is not always mounted under Linux (chroot for example). + ssize_t len = readlink(aPath.str().c_str(), exe_path, sizeof(exe_path)); + if (len >= 0) + return StringRef(exe_path, len); + } else { + // Fall back to the classical detection. + if (getprogpath(exe_path, argv0) != NULL) + return exe_path; + } +#elif defined(HAVE_DLFCN_H) + // Use dladdr to get executable path if available. + Dl_info DLInfo; + int err = dladdr(MainAddr, &DLInfo); + if (err == 0) + return Path(); + + // If the filename is a symlink, we need to resolve and return the location of + // the actual executable. + char link_path[MAXPATHLEN]; + if (realpath(DLInfo.dli_fname, link_path)) + return Path(link_path); +#else +#error GetMainExecutable is not implemented on this host yet. +#endif + return ""; +} TimeValue file_status::getLastModificationTime() const { TimeValue Ret; diff --git a/lib/Support/Windows/PathV2.inc b/lib/Support/Windows/PathV2.inc index 0c12bb440e..6987e5fc9d 100644 --- a/lib/Support/Windows/PathV2.inc +++ b/lib/Support/Windows/PathV2.inc @@ -128,6 +128,13 @@ namespace llvm { namespace sys { namespace fs { +std::string getMainExecutable(const char *argv0, void *MainExecAddr) { + char pathname[MAX_PATH]; + DWORD ret = ::GetModuleFileNameA(NULL, pathname, MAX_PATH); + return ret != MAX_PATH ? pathname : ""; +} + + TimeValue file_status::getLastModificationTime() const { ULARGE_INTEGER UI; UI.LowPart = LastWriteTimeLow; |