diff --git a/lldb/include/lldb/Core/FileSpec.h b/lldb/include/lldb/Core/FileSpec.h index 2c2822b22243..4305534bb5e6 100644 --- a/lldb/include/lldb/Core/FileSpec.h +++ b/lldb/include/lldb/Core/FileSpec.h @@ -521,7 +521,7 @@ public: static size_t Resolve (const char *src_path, char *dst_path, size_t dst_len); -#if LLDB_CONFIG_TILDE_RESOLVES_TO_USER +#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER //------------------------------------------------------------------ diff --git a/lldb/include/lldb/Host/Host.h b/lldb/include/lldb/Host/Host.h index 28901504b990..af8383c04940 100644 --- a/lldb/include/lldb/Host/Host.h +++ b/lldb/include/lldb/Host/Host.h @@ -346,8 +346,15 @@ public: static size_t GetEnvironment (StringList &env); + enum DynamicLibraryOpenOptions + { + eDynamicLibraryOpenOptionLazy = (1u << 0), // Lazily resolve symbols in this dynamic library + eDynamicLibraryOpenOptionLocal = (1u << 1), // Only open a shared library with local access (hide it from the global symbol namespace) + eDynamicLibraryOpenOptionLimitGetSymbol = (1u << 2) // DynamicLibraryGetSymbol calls on this handle will only return matches from this shared library + }; static void * DynamicLibraryOpen (const FileSpec &file_spec, + uint32_t options, Error &error); static Error diff --git a/lldb/include/lldb/Host/freebsd/Config.h b/lldb/include/lldb/Host/freebsd/Config.h index e74d18cf9116..b91d7d398775 100644 --- a/lldb/include/lldb/Host/freebsd/Config.h +++ b/lldb/include/lldb/Host/freebsd/Config.h @@ -19,4 +19,10 @@ #define LLDB_CONFIG_TERMIOS_SUPPORTED 1 +#define LLDB_CONFIG_TERMIOS_SUPPORTED 1 + +#define LLDB_CONFIG_TILDE_RESOLVES_TO_USER 1 + +//#define LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED 1 + #endif // #ifndef liblldb_Platform_Config_h_ \ No newline at end of file diff --git a/lldb/include/lldb/Host/linux/Config.h b/lldb/include/lldb/Host/linux/Config.h index 1da720bf9094..9408936f15f3 100644 --- a/lldb/include/lldb/Host/linux/Config.h +++ b/lldb/include/lldb/Host/linux/Config.h @@ -23,4 +23,6 @@ #define LLDB_CONFIG_TILDE_RESOLVES_TO_USER 1 +//#define LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED 1 + #endif // #ifndef liblldb_Platform_Config_h_ diff --git a/lldb/include/lldb/Host/macosx/Config.h b/lldb/include/lldb/Host/macosx/Config.h index 1da720bf9094..6735a92bfdc6 100644 --- a/lldb/include/lldb/Host/macosx/Config.h +++ b/lldb/include/lldb/Host/macosx/Config.h @@ -23,4 +23,6 @@ #define LLDB_CONFIG_TILDE_RESOLVES_TO_USER 1 +#define LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED 1 + #endif // #ifndef liblldb_Platform_Config_h_ diff --git a/lldb/include/lldb/Host/mingw/Config.h b/lldb/include/lldb/Host/mingw/Config.h index db2b6dfb207e..a90cfc754a21 100644 --- a/lldb/include/lldb/Host/mingw/Config.h +++ b/lldb/include/lldb/Host/mingw/Config.h @@ -19,8 +19,10 @@ #define LLDB_CONFIG_SUPPORTS_SETLINEBUFFERED 1 -#define LLDB_CONFIG_TERMIOS_SUPPORTED 0 +//#define LLDB_CONFIG_TERMIOS_SUPPORTED 1 -#define LLDB_CONFIG_TILDE_RESOLVES_TO_USER 0 +//#define LLDB_CONFIG_TILDE_RESOLVES_TO_USER 1 + +//#define LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED 1 #endif // #ifndef liblldb_Platform_Config_h_ diff --git a/lldb/source/Commands/CommandCompletions.cpp b/lldb/source/Commands/CommandCompletions.cpp index 675bd53f275b..fd372661d992 100644 --- a/lldb/source/Commands/CommandCompletions.cpp +++ b/lldb/source/Commands/CommandCompletions.cpp @@ -153,7 +153,7 @@ DiskFilesOrDirectories if (end_ptr == NULL) { -#if LLDB_CONFIG_TILDE_RESOLVES_TO_USER +#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER // There's no directory. If the thing begins with a "~" then this is a bare // user name. @@ -207,7 +207,7 @@ DiskFilesOrDirectories return matches.GetSize(); } else -#endif // LLDB_CONFIG_TILDE_RESOLVES_TO_USER +#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER { // The containing part is the CWD, and the whole string is the remainder. @@ -239,7 +239,7 @@ DiskFilesOrDirectories // Look for a user name in the containing part, and if it's there, resolve it and stick the // result back into the containing_part: -#if LLDB_CONFIG_TILDE_RESOLVES_TO_USER +#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER if (*partial_name_copy == '~') { size_t resolved_username_len = FileSpec::ResolveUsername(containing_part, containing_part, sizeof (containing_part)); @@ -247,7 +247,7 @@ DiskFilesOrDirectories if (resolved_username_len == 0 || resolved_username_len >= sizeof (containing_part)) return matches.GetSize(); } -#endif // #if LLDB_CONFIG_TILDE_RESOLVES_TO_USER +#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER // Okay, containing_part is now the directory we want to open and look for files: diff --git a/lldb/source/Core/FileSpec.cpp b/lldb/source/Core/FileSpec.cpp index de8a15be5bb0..f141fe839b36 100644 --- a/lldb/source/Core/FileSpec.cpp +++ b/lldb/source/Core/FileSpec.cpp @@ -16,7 +16,7 @@ #include #include "lldb/Host/Config.h" // Have to include this before we test the define... -#if LLDB_CONFIG_TILDE_RESOLVES_TO_USER +#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER #include #endif @@ -44,7 +44,7 @@ GetFileStats (const FileSpec *file_spec, struct stat *stats_ptr) return false; } -#if LLDB_CONFIG_TILDE_RESOLVES_TO_USER +#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER static const char* GetCachedGlobTildeSlash() @@ -134,7 +134,7 @@ FileSpec::ResolveUsername (const char *src_path, char *dst_path, size_t dst_len) else return ::snprintf (dst_path, dst_len, "%s%s", home_dir, remainder); } -#endif // #if LLDB_CONFIG_TILDE_RESOLVES_TO_USER +#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER size_t FileSpec::Resolve (const char *src_path, char *dst_path, size_t dst_len) @@ -144,7 +144,7 @@ FileSpec::Resolve (const char *src_path, char *dst_path, size_t dst_len) // Glob if needed for ~/, otherwise copy in case src_path is same as dst_path... char unglobbed_path[PATH_MAX]; -#if LLDB_CONFIG_TILDE_RESOLVES_TO_USER +#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER if (src_path[0] == '~') { size_t return_count = ResolveUsername(src_path, unglobbed_path, sizeof(unglobbed_path)); @@ -155,7 +155,7 @@ FileSpec::Resolve (const char *src_path, char *dst_path, size_t dst_len) ::snprintf (unglobbed_path, sizeof(unglobbed_path), "%s", src_path); } else -#endif // LLDB_CONFIG_TILDE_RESOLVES_TO_USER +#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER { ::snprintf(unglobbed_path, sizeof(unglobbed_path), "%s", src_path); } diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp index 9117754fa2f6..3f6315d420b5 100644 --- a/lldb/source/Core/PluginManager.cpp +++ b/lldb/source/Core/PluginManager.cpp @@ -95,7 +95,11 @@ LoadPluginCallback else { PluginInfo plugin_info = { NULL, NULL, NULL }; - plugin_info.plugin_handle = Host::DynamicLibraryOpen (plugin_file_spec, error); + uint32_t flags = Host::eDynamicLibraryOpenOptionLazy | + Host::eDynamicLibraryOpenOptionLocal | + Host::eDynamicLibraryOpenOptionLimitGetSymbol; + + plugin_info.plugin_handle = Host::DynamicLibraryOpen (plugin_file_spec, flags, error); if (plugin_info.plugin_handle) { bool success = false; diff --git a/lldb/source/Core/StreamFile.cpp b/lldb/source/Core/StreamFile.cpp index f422f8ad04cf..909591054942 100644 --- a/lldb/source/Core/StreamFile.cpp +++ b/lldb/source/Core/StreamFile.cpp @@ -98,10 +98,10 @@ StreamFile::Open (const char *path, const char *permissions) void StreamFile::SetLineBuffered () { -#if LLDB_CONFIG_SUPPORTS_SETLINEBUFFERED +#ifdef LLDB_CONFIG_SUPPORTS_SETLINEBUFFERED if (m_file != NULL) setlinebuf (m_file); -#endif // #if LLDB_CONFIG_SUPPORTS_SETLINEBUFFERED +#endif // #ifdef LLDB_CONFIG_SUPPORTS_SETLINEBUFFERED } void diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index 061a31eef595..9c4b61fcc040 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -14,6 +14,7 @@ #include "lldb/Core/FileSpec.h" #include "lldb/Core/Log.h" #include "lldb/Core/StreamString.h" +#include "lldb/Host/Config.h" #include "lldb/Host/Endian.h" #include "lldb/Host/Mutex.h" @@ -21,12 +22,16 @@ #include #if defined (__APPLE__) + #include #include #include #include + #elif defined (__linux__) + #include + #endif using namespace lldb; @@ -643,21 +648,48 @@ Host::ResolveExecutableInBundle (FileSpec &file) } #endif -void * -Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error) +// Opaque info that tracks a dynamic library that was loaded +struct DynamicLibraryInfo +{ + DynamicLibraryInfo (const FileSpec &fs, int o, void *h) : + file_spec (fs), + open_options (o), + handle (h) + { + } + + const FileSpec file_spec; + uint32_t open_options; + void * handle; +}; + +void * +Host::DynamicLibraryOpen (const FileSpec &file_spec, uint32_t options, Error &error) { - void *dynamic_library_handle = NULL; char path[PATH_MAX]; if (file_spec.GetPath(path, sizeof(path))) { -#if defined (__linux__) - dynamic_library_handle = ::dlopen (path, RTLD_LAZY | RTLD_GLOBAL); -#else - dynamic_library_handle = ::dlopen (path, RTLD_LAZY | RTLD_GLOBAL | RTLD_FIRST); + int mode = 0; + + if (options & eDynamicLibraryOpenOptionLazy) + mode |= RTLD_LAZY; + + if (options & eDynamicLibraryOpenOptionLocal) + mode |= RTLD_LOCAL; + else + mode |= RTLD_GLOBAL; + +#ifdef LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED + if (options & eDynamicLibraryOpenOptionLimitGetSymbol) + mode |= RTLD_FIRST; #endif - if (dynamic_library_handle) + + void * opaque = ::dlopen (path, mode); + + if (opaque) { error.Clear(); + return new DynamicLibraryInfo (file_spec, options, opaque); } else { @@ -668,40 +700,73 @@ Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error) { error.SetErrorString("failed to extract path"); } - - return dynamic_library_handle; + return NULL; } Error -Host::DynamicLibraryClose (void *dynamic_library_handle) +Host::DynamicLibraryClose (void *opaque) { Error error; - if (dynamic_library_handle == NULL) + if (opaque == NULL) { error.SetErrorString ("invalid dynamic library handle"); } - else if (::dlclose(dynamic_library_handle) != 0) + else { - error.SetErrorString(::dlerror()); + DynamicLibraryInfo *dylib_info = (DynamicLibraryInfo *) opaque; + if (::dlclose (dylib_info->handle) != 0) + { + error.SetErrorString(::dlerror()); + } + + dylib_info->open_options = 0; + dylib_info->handle = 0; + delete dylib_info; } return error; } void * -Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error) +Host::DynamicLibraryGetSymbol (void *opaque, const char *symbol_name, Error &error) { - if (dynamic_library_handle == NULL) + if (opaque == NULL) { error.SetErrorString ("invalid dynamic library handle"); - return NULL; } - - void *symbol_addr = ::dlsym (dynamic_library_handle, symbol_name); - if (symbol_addr == NULL) - error.SetErrorString(::dlerror()); else - error.Clear(); - return symbol_addr; + { + DynamicLibraryInfo *dylib_info = (DynamicLibraryInfo *) opaque; + + void *symbol_addr = ::dlsym (dylib_info->handle, symbol_name); + if (symbol_addr) + { +#ifndef LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED + // This host doesn't support limiting searches to this shared library + // so we need to verify that the match came from this shared library + // if it was requested in the Host::DynamicLibraryOpen() function. + if (dylib_info->options & eDynamicLibraryOpenOptionLimitGetSymbol) + { + FileSpec match_dylib_spec (Host::GetModuleFileSpecForHostAddress (symbol_addr)); + if (match_dylib_spec != dylib_info->file_spec) + { + char dylib_path[PATH_MAX]; + if (dylib_info->file_spec.GetPath (dylib_path, sizeof(dylib_path))) + error.SetErrorStringWithFormat ("symbol not found in \"%s\"", dylib_path); + else + error.SetErrorString ("symbol not found"); + return NULL; + } + } +#endif + error.Clear(); + return symbol_addr; + } + else + { + error.SetErrorString(::dlerror()); + } + } + return NULL; } bool diff --git a/lldb/source/Host/common/Terminal.cpp b/lldb/source/Host/common/Terminal.cpp index 0511b73586bb..61cedb7b298e 100644 --- a/lldb/source/Host/common/Terminal.cpp +++ b/lldb/source/Host/common/Terminal.cpp @@ -14,7 +14,7 @@ #include #include -#if LLDB_CONFIG_TERMIOS_SUPPORTED +#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED #include #endif @@ -33,7 +33,7 @@ Terminal::SetEcho (bool enabled) { if (FileDescriptorIsValid()) { -#if LLDB_CONFIG_TERMIOS_SUPPORTED +#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED if (IsATerminal ()) { struct termios fd_termios; @@ -60,7 +60,7 @@ Terminal::SetEcho (bool enabled) return ::tcsetattr (m_fd, TCSANOW, &fd_termios) == 0; } } -#endif +#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED } return false; } @@ -70,7 +70,7 @@ Terminal::SetCanonical (bool enabled) { if (FileDescriptorIsValid()) { -#if LLDB_CONFIG_TERMIOS_SUPPORTED +#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED if (IsATerminal ()) { struct termios fd_termios; @@ -97,7 +97,7 @@ Terminal::SetCanonical (bool enabled) return ::tcsetattr (m_fd, TCSANOW, &fd_termios) == 0; } } -#endif +#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED } return false; } @@ -132,13 +132,13 @@ TerminalState::Save (int fd, bool save_process_group) if (m_tty.IsATerminal()) { m_tflags = ::fcntl (fd, F_GETFL, 0); -#if LLDB_CONFIG_TERMIOS_SUPPORTED +#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED if (m_termios_ap.get() == NULL) m_termios_ap.reset (new struct termios); int err = ::tcgetattr (fd, m_termios_ap.get()); if (err != 0) m_termios_ap.reset(); -#endif // #if LLDB_CONFIG_TERMIOS_SUPPORTED +#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED if (save_process_group) m_process_group = ::tcgetpgrp (0); else @@ -168,10 +168,10 @@ TerminalState::Restore () const if (TFlagsIsValid()) result = fcntl (fd, F_SETFL, m_tflags); -#if LLDB_CONFIG_TERMIOS_SUPPORTED +#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED if (TTYStateIsValid()) result = tcsetattr (fd, TCSANOW, m_termios_ap.get()); -#endif // #if LLDB_CONFIG_TERMIOS_SUPPORTED +#endif // #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED if (ProcessGroupIsValid()) {