mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-13 14:35:54 +00:00
Port GetMainExecutable over to PathV2.
I will remove the V1 version as soon as I change clang in the next commit. llvm-svn: 184914
This commit is contained in:
parent
2d8fd3934d
commit
07ffa7d08b
@ -696,7 +696,10 @@ error_code map_file_pages(const Twine &path, off_t file_offset, size_t size,
|
||||
/// platform specific error_code.
|
||||
error_code unmap_file_pages(void *base, size_t size);
|
||||
|
||||
|
||||
/// Return the path to the main executable, given the value of argv[0] from
|
||||
/// program startup and the address of main itself. In extremis, this function
|
||||
/// may fail and return an empty path.
|
||||
std::string getMainExecutable(const char *argv0, void *MainExecAddr);
|
||||
|
||||
/// @}
|
||||
/// @name Iterators
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -252,8 +252,8 @@ static std::string PrependMainExecutablePath(const std::string &ExeName,
|
||||
// Check the directory that the calling program is in. We can do
|
||||
// this if ProgramPath contains at least one / character, indicating that it
|
||||
// is a relative path to the executable itself.
|
||||
sys::Path Main = sys::Path::GetMainExecutable(Argv0, MainAddr);
|
||||
StringRef Result = sys::path::parent_path(Main.str());
|
||||
std::string Main = sys::fs::getMainExecutable(Argv0, MainAddr);
|
||||
StringRef Result = sys::path::parent_path(Main);
|
||||
|
||||
if (!Result.empty()) {
|
||||
SmallString<128> Storage = Result;
|
||||
|
@ -162,11 +162,11 @@ Typical components:\n\
|
||||
}
|
||||
|
||||
/// \brief Compute the path to the main executable.
|
||||
llvm::sys::Path GetExecutablePath(const char *Argv0) {
|
||||
std::string GetExecutablePath(const char *Argv0) {
|
||||
// This just needs to be some symbol in the binary; C++ doesn't
|
||||
// allow taking the address of ::main however.
|
||||
void *P = (void*) (intptr_t) GetExecutablePath;
|
||||
return llvm::sys::Path::GetMainExecutable(Argv0, P);
|
||||
return llvm::sys::fs::getMainExecutable(Argv0, P);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
@ -180,7 +180,7 @@ int main(int argc, char **argv) {
|
||||
// tree.
|
||||
bool IsInDevelopmentTree;
|
||||
enum { MakefileStyle, CMakeStyle, CMakeBuildModeStyle } DevelopmentTreeLayout;
|
||||
llvm::SmallString<256> CurrentPath(GetExecutablePath(argv[0]).str());
|
||||
llvm::SmallString<256> CurrentPath(GetExecutablePath(argv[0]));
|
||||
std::string CurrentExecPrefix;
|
||||
std::string ActiveObjRoot;
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/PathV1.h"
|
||||
#include "llvm/Support/Program.h"
|
||||
@ -56,7 +57,8 @@ TEST(ProgramTest, CreateProcessTrailingSlash) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Path my_exe = Path::GetMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
|
||||
std::string my_exe =
|
||||
sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
|
||||
const char *argv[] = {
|
||||
my_exe.c_str(),
|
||||
"--gtest_filter=ProgramTest.CreateProcessTrailingSlashChild",
|
||||
@ -80,7 +82,7 @@ TEST(ProgramTest, CreateProcessTrailingSlash) {
|
||||
StringRef nul("/dev/null");
|
||||
#endif
|
||||
const StringRef *redirects[] = { &nul, &nul, 0 };
|
||||
int rc = ExecuteAndWait(my_exe.str(), argv, &envp[0], redirects,
|
||||
int rc = ExecuteAndWait(my_exe, argv, &envp[0], redirects,
|
||||
/*secondsToWait=*/ 10, /*memoryLimit=*/ 0, &error,
|
||||
&ExecutionFailed);
|
||||
EXPECT_FALSE(ExecutionFailed) << error;
|
||||
|
Loading…
Reference in New Issue
Block a user