diff options
| -rw-r--r-- | lldb/include/lldb/Core/UUID.h | 30 | ||||
| -rw-r--r-- | lldb/include/lldb/Interpreter/OptionGroupBoolean.h | 11 | ||||
| -rw-r--r-- | lldb/include/lldb/Interpreter/OptionValueFileSpec.h | 31 | ||||
| -rw-r--r-- | lldb/include/lldb/Interpreter/OptionValueUUID.h | 8 | ||||
| -rw-r--r-- | lldb/source/API/SBTarget.cpp | 2 | ||||
| -rw-r--r-- | lldb/source/Commands/CommandObjectTarget.cpp | 344 | ||||
| -rw-r--r-- | lldb/source/Core/UUID.cpp | 73 | ||||
| -rw-r--r-- | lldb/source/Host/macosx/Symbols.cpp | 165 | ||||
| -rw-r--r-- | lldb/source/Interpreter/OptionGroupBoolean.cpp | 23 | ||||
| -rw-r--r-- | lldb/source/Interpreter/OptionValueFileSpec.cpp | 31 | ||||
| -rw-r--r-- | lldb/source/Interpreter/OptionValueUUID.cpp | 52 | ||||
| -rw-r--r-- | lldb/source/Interpreter/Property.cpp | 2 |
12 files changed, 550 insertions, 222 deletions
diff --git a/lldb/include/lldb/Core/UUID.h b/lldb/include/lldb/Core/UUID.h index c36499f9216..f242122c743 100644 --- a/lldb/include/lldb/Core/UUID.h +++ b/lldb/include/lldb/Core/UUID.h @@ -58,8 +58,36 @@ public: GetAsCString (char *dst, size_t dst_len) const; size_t - SetfromCString (const char *c_str); + SetFromCString (const char *c_str); + // Decode as many UUID bytes (up to 16) as possible from the C string "cstr" + // This is used for auto completion where a partial UUID might have been + // typed in. It + //------------------------------------------------------------------ + /// Decode as many UUID bytes (up to 16) as possible from the C + /// string \a cstr. + /// + /// @param[in] cstr + /// A NULL terminate C string that points at a UUID string value + /// (no leading spaces). The string must contain only hex + /// characters and optionally can contain the '-' sepearators. + /// + /// @param[in] uuid_bytes + /// A buffer of bytes that will contain a full or patially + /// decoded UUID. + /// + /// @param[out] end + /// If \a end is not NULL, it will be filled in with the a + /// pointer to the character after the last successfully decoded + /// byte. + /// + /// @return + /// Returns the number of bytes that were successfully decoded + /// which should be 16 if a full UUID value was properly decoded. + //------------------------------------------------------------------ + static size_t + DecodeUUIDBytesFromCString (const char *cstr, ValueType &uuid_bytes, const char **end); + protected: //------------------------------------------------------------------ // Classes that inherit from UUID can see and modify these diff --git a/lldb/include/lldb/Interpreter/OptionGroupBoolean.h b/lldb/include/lldb/Interpreter/OptionGroupBoolean.h index 56978232f33..45f24640a2a 100644 --- a/lldb/include/lldb/Interpreter/OptionGroupBoolean.h +++ b/lldb/include/lldb/Interpreter/OptionGroupBoolean.h @@ -25,15 +25,16 @@ namespace lldb_private { class OptionGroupBoolean : public OptionGroup { public: - + // When 'no_argument_toggle_default' is true, then setting the option + // value does NOT require an argument, it sets the boolean value to the + // inverse of the default value OptionGroupBoolean (uint32_t usage_mask, bool required, const char *long_option, char short_option, - uint32_t completion_type, - lldb::CommandArgumentType argument_type, const char *usage_text, - bool default_value); + bool default_value, + bool no_argument_toggle_default); virtual ~OptionGroupBoolean (); @@ -76,7 +77,7 @@ namespace lldb_private { OptionDefinition m_option_definition; }; - + } // namespace lldb_private #endif // liblldb_OptionGroupBoolean_h_ diff --git a/lldb/include/lldb/Interpreter/OptionValueFileSpec.h b/lldb/include/lldb/Interpreter/OptionValueFileSpec.h index 67adaf9cc33..7e74b605660 100644 --- a/lldb/include/lldb/Interpreter/OptionValueFileSpec.h +++ b/lldb/include/lldb/Interpreter/OptionValueFileSpec.h @@ -22,30 +22,12 @@ namespace lldb_private { class OptionValueFileSpec : public OptionValue { public: - OptionValueFileSpec () : - OptionValue(), - m_current_value (), - m_default_value (), - m_data_sp() - { - } + OptionValueFileSpec (); - OptionValueFileSpec (const FileSpec &value) : - OptionValue(), - m_current_value (value), - m_default_value (value), - m_data_sp() - { - } + OptionValueFileSpec (const FileSpec &value); OptionValueFileSpec (const FileSpec ¤t_value, - const FileSpec &default_value) : - OptionValue(), - m_current_value (current_value), - m_default_value (default_value), - m_data_sp() - { - } + const FileSpec &default_value); virtual ~OptionValueFileSpec() @@ -129,10 +111,17 @@ public: const lldb::DataBufferSP & GetFileContents(bool null_terminate); + void + SetCompletionMask (uint32_t mask) + { + m_completion_mask = mask; + } + protected: FileSpec m_current_value; FileSpec m_default_value; lldb::DataBufferSP m_data_sp; + uint32_t m_completion_mask; }; } // namespace lldb_private diff --git a/lldb/include/lldb/Interpreter/OptionValueUUID.h b/lldb/include/lldb/Interpreter/OptionValueUUID.h index 980784014cd..caf436e576f 100644 --- a/lldb/include/lldb/Interpreter/OptionValueUUID.h +++ b/lldb/include/lldb/Interpreter/OptionValueUUID.h @@ -89,6 +89,14 @@ public: m_uuid = value; } + virtual size_t + AutoComplete (CommandInterpreter &interpreter, + const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + protected: UUID m_uuid; }; diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index e7ae0d65eff..e6e1e744870 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -1801,7 +1801,7 @@ SBTarget::AddModule (const char *path, module_spec.GetFileSpec().SetFile(path, false); if (uuid_cstr) - module_spec.GetUUID().SetfromCString(uuid_cstr); + module_spec.GetUUID().SetFromCString(uuid_cstr); if (triple) module_spec.GetArchitecture().SetTriple (triple, target_sp->GetPlatform ().get()); diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index c1e6486f035..226c00ff9d5 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -451,7 +451,7 @@ public: NULL, 0), m_option_group (interpreter), - m_cleanup_option (LLDB_OPT_SET_1, false, "clean", 'c', 0, eArgTypeNone, "Perform extra cleanup to minimize memory consumption after deleting the target.", false) + m_cleanup_option (LLDB_OPT_SET_1, false, "clean", 'c', "Perform extra cleanup to minimize memory consumption after deleting the target.", false, false) { m_option_group.Append (&m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Finalize(); @@ -3984,9 +3984,17 @@ public: CommandObjectTargetSymbolsAdd (CommandInterpreter &interpreter) : CommandObjectParsed (interpreter, "target symbols add", - "Add a debug symbol file to one of the target's current modules.", - "target symbols add [<symfile>]") + "Add a debug symbol file to one of the target's current modules by specifying a path to a debug symbols file, or using the options to specify a module to download symbols for.", + "target symbols add [<symfile>]"), + m_option_group (interpreter), + m_file_option (LLDB_OPT_SET_1, false, "shlib", 's', CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Fullpath or basename for module to find debug symbols for."), + m_current_frame_option (LLDB_OPT_SET_2, false, "frame", 'F', "Locate the debug symbols the currently selected frame.", false, true) + { + m_option_group.Append (&m_uuid_option_group, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append (&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append (&m_current_frame_option, LLDB_OPT_SET_2, LLDB_OPT_SET_2); + m_option_group.Finalize(); } virtual @@ -4018,152 +4026,260 @@ public: return matches.GetSize(); } + virtual Options * + GetOptions () + { + return &m_option_group; + } + + protected: + + bool + AddModuleSymbols (Target *target, + const FileSpec &symfile_spec, + bool &flush, + CommandReturnObject &result) + { + ModuleSP symfile_module_sp (new Module (symfile_spec, target->GetArchitecture())); + const UUID &symfile_uuid = symfile_module_sp->GetUUID(); + StreamString ss_symfile_uuid; + symfile_uuid.Dump(&ss_symfile_uuid); + + if (symfile_module_sp) + { + char symfile_path[PATH_MAX]; + symfile_spec.GetPath (symfile_path, sizeof(symfile_path)); + // We now have a module that represents a symbol file + // that can be used for a module that might exist in the + // current target, so we need to find that module in the + // target + + ModuleSP old_module_sp (target->GetImages().FindModule (symfile_uuid)); + if (old_module_sp) + { + // The module has not yet created its symbol vendor, we can just + // give the existing target module the symfile path to use for + // when it decides to create it! + old_module_sp->SetSymbolFileFileSpec (symfile_module_sp->GetFileSpec()); + + // Provide feedback that the symfile has been successfully added. + const FileSpec &module_fs = old_module_sp->GetFileSpec(); + result.AppendMessageWithFormat("symbol file '%s' with UUID %s has been successfully added to the '%s/%s' module\n", + symfile_path, ss_symfile_uuid.GetData(), + module_fs.GetDirectory().AsCString(), module_fs.GetFilename().AsCString()); + + // Let clients know something changed in the module + // if it is currently loaded + ModuleList module_list; + module_list.Append (old_module_sp); + target->ModulesDidLoad (module_list); + flush = true; + } + else + { + result.AppendErrorWithFormat ("symbol file '%s' with UUID %s does not match any existing module%s\n", + symfile_path, ss_symfile_uuid.GetData(), + (symfile_spec.GetFileType() != FileSpec::eFileTypeRegular) + ? "\n please specify the full path to the symbol file" + : ""); + return false; + } + } + else + { + result.AppendError ("one or more executable image paths must be specified"); + result.SetStatus (eReturnStatusFailed); + return false; + } + result.SetStatus (eReturnStatusSuccessFinishResult); + return true; + } + virtual bool DoExecute (Args& args, CommandReturnObject &result) { ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); Target *target = exe_ctx.GetTargetPtr(); + result.SetStatus (eReturnStatusFailed); if (target == NULL) { result.AppendError ("invalid target, create a debug target using the 'target create' command"); - result.SetStatus (eReturnStatusFailed); } else { bool flush = false; + ModuleSpec sym_spec; + const bool uuid_option_set = m_uuid_option_group.GetOptionValue().OptionWasSet(); + const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet(); + const bool frame_option_set = m_current_frame_option.GetOptionValue().OptionWasSet(); + const size_t argc = args.GetArgumentCount(); if (argc == 0) { - result.AppendError ("one or more symbol file paths must be specified"); - result.SetStatus (eReturnStatusFailed); - } - else - { - PlatformSP platform_sp (target->GetPlatform()); - - for (size_t i=0; i<argc; ++i) + if (uuid_option_set || file_option_set || frame_option_set) { - const char *symfile_path = args.GetArgumentAtIndex(i); - if (symfile_path) + bool success = false; + bool error_set = false; + if (frame_option_set) { - ModuleSpec sym_spec; - FileSpec symfile_spec; - sym_spec.GetSymbolFileSpec().SetFile(symfile_path, true); - if (platform_sp) - platform_sp->ResolveSymbolFile(*target, sym_spec, symfile_spec); - else - symfile_spec.SetFile(symfile_path, true); - - ArchSpec arch; - bool symfile_exists = symfile_spec.Exists(); - // The code below was testing the new "Symbols::DownloadObjectAndSymbolFile" - // functionality. Now that it works on MacOSX, it will be enabled soon with - // option values (like "--uuid <UUID>" or "--file <module>", or "--frame" - // for the current stack frame's module). So it is commented out for now. -// if (!symfile_exists) -// { -// if (sym_spec.GetUUID().SetfromCString(symfile_path)) -// { -// // A UUID was specified, look it up via UUID -// if (Symbols::DownloadObjectAndSymbolFile (sym_spec)) -// { -//// printf ("UUID: %s\n", symfile_path); -//// printf ("objfile_spec: %s/%s\n", -//// sym_spec.GetFileSpec().GetDirectory().GetCString(), -//// sym_spec.GetFileSpec().GetFilename().GetCString()); -//// printf ("symfile_spec: %s/%s\n", -//// sym_spec.GetSymbolFileSpec().GetDirectory().GetCString(), -//// sym_spec.GetSymbolFileSpec().GetFilename().GetCString()); -// symfile_spec = sym_spec.GetSymbolFileSpec(); -// symfile_exists = symfile_spec.Exists(); -// } -// } -// } - - if (symfile_exists) + Process *process = exe_ctx.GetProcessPtr(); + if (process) { - ModuleSP symfile_module_sp (new Module (symfile_spec, target->GetArchitecture())); - const UUID &symfile_uuid = symfile_module_sp->GetUUID(); - StreamString ss_symfile_uuid; - symfile_uuid.Dump(&ss_symfile_uuid); - - if (symfile_module_sp) + const StateType process_state = process->GetState(); + if (StateIsStoppedState (process_state, true)) { - // We now have a module that represents a symbol file - // that can be used for a module that might exist in the - // current target, so we need to find that module in the - // target - - ModuleSP old_module_sp (target->GetImages().FindModule (symfile_uuid)); - if (old_module_sp) + StackFrame *frame = exe_ctx.GetFramePtr(); + if (frame) { - // The module has not yet created its symbol vendor, we can just - // give the existing target module the symfile path to use for - // when it decides to create it! - old_module_sp->SetSymbolFileFileSpec (symfile_module_sp->GetFileSpec()); - - // Provide feedback that the symfile has been successfully added. - const FileSpec &module_fs = old_module_sp->GetFileSpec(); - result.AppendMessageWithFormat("symbol file '%s' with UUID %s has been successfully added to the '%s/%s' module\n", - symfile_path, ss_symfile_uuid.GetData(), - module_fs.GetDirectory().AsCString(), module_fs.GetFilename().AsCString()); - - // Let clients know something changed in the module - // if it is currently loaded - ModuleList module_list; - module_list.Append (old_module_sp); - target->ModulesDidLoad (module_list); - flush = true; + ModuleSP frame_module_sp (frame->GetSymbolContext(eSymbolContextModule).module_sp); + if (frame_module_sp) + { + if (frame_module_sp->GetPlatformFileSpec().Exists()) + { + sym_spec.GetArchitecture() = frame_module_sp->GetArchitecture(); + sym_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec(); + } + sym_spec.GetUUID() = frame_module_sp->GetUUID(); + success = sym_spec.GetUUID().IsValid() || sym_spec.GetFileSpec(); + } + else + { + result.AppendError ("frame has no module"); + error_set = true; + } } else { - result.AppendErrorWithFormat ("symbol file '%s' with UUID %s does not match any existing module%s\n", - symfile_path, ss_symfile_uuid.GetData(), - (symfile_spec.GetFileType() != FileSpec::eFileTypeRegular) - ? "\n please specify the full path to the symbol file" - : ""); - break; + result.AppendError ("invalid current frame"); + error_set = true; } } else { - result.AppendError ("one or more executable image paths must be specified"); - result.SetStatus (eReturnStatusFailed); - break; + result.AppendErrorWithFormat ("process is not stopped: %s", StateAsCString(process_state)); + error_set = true; } - result.SetStatus (eReturnStatusSuccessFinishResult); } else { -// sym_spec.GetSymbolFileSpec().Clear(); -// if (sym_spec.GetUUID().SetfromCString(symfile_path)) -// { -// if (Symbols::DownloadObjectAndSymbolFile (sym_spec)) -// { -// printf ("UUID: %s\n", symfile_path); -// printf ("objfile_spec: %s/%s\n", -// sym_spec.GetFileSpec().GetDirectory().GetCString(), -// sym_spec.GetFileSpec().GetFilename().GetCString()); -// printf ("symfile_spec: %s/%s\n", -// sym_spec.GetSymbolFileSpec().GetDirectory().GetCString(), -// sym_spec.GetSymbolFileSpec().GetFilename().GetCString()); -// } -// } + result.AppendError ("a process must exist in order to use the --frame option"); + error_set = true; + } + } + else + { + if (uuid_option_set) + { + sym_spec.GetUUID() = m_uuid_option_group.GetOptionValue().GetCurrentValue(); + success |= sym_spec.GetUUID().IsValid(); + } + else if (file_option_set) + { + sym_spec.GetFileSpec() = m_file_option.GetOptionValue().GetCurrentValue(); + ModuleSP module_sp (target->GetImages().FindFirstModule(sym_spec)); + if (module_sp) + { + sym_spec.GetFileSpec() = module_sp->GetFileSpec(); + sym_spec.GetPlatformFileSpec() = module_sp->GetPlatformFileSpec(); + sym_spec.GetUUID() = module_sp->GetUUID(); + sym_spec.GetArchitecture() = module_sp->GetArchitecture(); + } + else + { + sym_spec.GetArchitecture() = target->GetArchitecture(); + } + success |= sym_spec.GetFileSpec().Exists(); + } + } + + if (success) + { + if (Symbols::DownloadObjectAndSymbolFile (sym_spec)) + { + if (sym_spec.GetSymbolFileSpec()) + success = AddModuleSymbols (target, sym_spec.GetSymbolFileSpec(), flush, result); + } + } + + if (!success && !error_set) + { + StreamString error_strm; + if (uuid_option_set) + { + error_strm.PutCString("unable to find debug symbols for UUID "); + sym_spec.GetUUID().Dump (&error_strm); + } + else if (file_option_set) + { + error_strm.PutCString("unable to find debug symbols for the executable file "); + error_strm << sym_spec.GetFileSpec(); + } + else if (frame_option_set) + { + error_strm.PutCString("unable to find debug symbols for the current frame"); + } + result.AppendError (error_strm.GetData()); + } + } + else + { + result.AppendError ("one or more symbol file paths must be specified, or options must be specified"); + } + } + else + { + if (uuid_option_set) + { + result.AppendError ("specify either one or more paths to symbol files or use the --uuid option without arguments"); + } + else if (file_option_set) + { + result.AppendError ("specify either one or more paths to symbol files or use the --file option without arguments"); + } + else if (frame_option_set) + { + result.AppendError ("specify either one or more paths to symbol files or use the --frame option without arguments"); + } + else + { + PlatformSP platform_sp (target->GetPlatform()); + + for (size_t i=0; i<argc; ++i) + { + const char *symfile_path = args.GetArgumentAtIndex(i); + if (symfile_path) + { + FileSpec symfile_spec; + sym_spec.GetSymbolFileSpec().SetFile(symfile_path, true); + if (platform_sp) + platform_sp->ResolveSymbolFile(*target, sym_spec, symfile_spec); + else + symfile_spec.SetFile(symfile_path, true); - char resolved_symfile_path[PATH_MAX]; - result.SetStatus (eReturnStatusFailed); - if (symfile_spec.GetPath (resolved_symfile_path, sizeof(resolved_symfile_path))) + ArchSpec arch; + bool symfile_exists = symfile_spec.Exists(); + + if (symfile_exists) { - if (strcmp (resolved_symfile_path, symfile_path) != 0) - { - result.AppendErrorWithFormat ("invalid module path '%s' with resolved path '%s'\n", symfile_path, resolved_symfile_path); + if (!AddModuleSymbols (target, symfile_spec, flush, result)) break; + } + else + { + char resolved_symfile_path[PATH_MAX]; + if (symfile_spec.GetPath (resolved_symfile_path, sizeof(resolved_symfile_path))) + { + if (strcmp (resolved_symfile_path, symfile_path) != 0) + { + result.AppendErrorWithFormat ("invalid module path '%s' with resolved path '%s'\n", symfile_path, resolved_symfile_path); + break; + } } + result.AppendErrorWithFormat ("invalid module path '%s'\n", symfile_path); + break; } - result.AppendErrorWithFormat ("invalid module path '%s'\n", symfile_path); - break; } } } @@ -4179,6 +4295,12 @@ protected: return result.Succeeded(); } + OptionGroupOptions m_option_group; + OptionGroupUUID m_uuid_option_group; + OptionGroupFile m_file_option; + OptionGroupBoolean m_current_frame_option; + + }; diff --git a/lldb/source/Core/UUID.cpp b/lldb/source/Core/UUID.cpp index 520e31e8070..8ff97afebcc 100644 --- a/lldb/source/Core/UUID.cpp +++ b/lldb/source/Core/UUID.cpp @@ -128,47 +128,58 @@ xdigit_to_int (char ch) } size_t -UUID::SetfromCString (const char *cstr) +UUID::DecodeUUIDBytesFromCString (const char *p, ValueType &uuid_bytes, const char **end) +{ + size_t uuid_byte_idx = 0; + if (p) + { + while (*p) + { + if (isxdigit(p[0]) && isxdigit(p[1])) + { + int hi_nibble = xdigit_to_int(p[0]); + int lo_nibble = xdigit_to_int(p[1]); + // Translate the two hex nibble characters into a byte + uuid_bytes[uuid_byte_idx] = (hi_nibble << 4) + lo_nibble; + + // Skip both hex digits + p += 2; + + // Increment the byte that we are decoding within the UUID value + // and break out if we are done + if (++uuid_byte_idx == 16) + break; + } + else if (*p == '-') + { + // Skip dashes + p++; + } + else + { + // UUID values can only consist of hex characters and '-' chars + break; + } + } + } + if (end) + *end = p; + return uuid_byte_idx; +} +size_t +UUID::SetFromCString (const char *cstr) { if (cstr == NULL) return 0; - uint32_t uuid_byte_idx = 0; const char *p = cstr; // Skip leading whitespace characters while (isspace(*p)) ++p; + + const uint32_t uuid_byte_idx = UUID::DecodeUUIDBytesFromCString (p, m_uuid, &p); - // Try and decode a UUID - while (*p != '\0') - { - if (isxdigit(*p) && isxdigit(p[1])) - { - int hi_nibble = xdigit_to_int(p[0]); - int lo_nibble = xdigit_to_int(p[1]); - // Translate the two hex nibble characters into a byte - m_uuid[uuid_byte_idx] = (hi_nibble << 4) + lo_nibble; - - // Skip both hex digits - p += 2; - - // Increment the byte that we are decoding within the UUID value - // and break out if we are done - if (++uuid_byte_idx == 16) - break; - } - else if (*p == '-') - { - // Skip dashes - p++; - } - else - { - // UUID values can only consist of hex characters and '-' chars - return 0; - } - } // If we successfully decoded a UUID, return the amount of characters that // were consumed if (uuid_byte_idx == 16) diff --git a/lldb/source/Host/macosx/Symbols.cpp b/lldb/source/Host/macosx/Symbols.cpp index f7f08c80738..a66ecc1f362 100644 --- a/lldb/source/Host/macosx/Symbols.cpp +++ b/lldb/source/Host/macosx/Symbols.cpp @@ -585,6 +585,61 @@ Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec) } +static bool +GetModuleSpecInfoFromUUIDDictionary (CFDictionaryRef uuid_dict, ModuleSpec &module_spec) +{ + bool success = false; + if (uuid_dict != NULL && CFGetTypeID (uuid_dict) == CFDictionaryGetTypeID ()) + { + std::string str; + CFStringRef cf_str; + + cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGSymbolRichExecutable")); + if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ()) + { + if (CFCString::FileSystemRepresentation(cf_str, str)) + module_spec.GetFileSpec().SetFile (str.c_str(), true); + } + + cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGDSYMPath")); + if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ()) + { + if (CFCString::FileSystemRepresentation(cf_str, str)) + { + module_spec.GetSymbolFileSpec().SetFile (str.c_str(), true); + success = true; + } + } + + cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGArchitecture")); + if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ()) + { + if (CFCString::FileSystemRepresentation(cf_str, str)) + module_spec.GetArchitecture().SetTriple(str.c_str()); + } + + std::string DBGBuildSourcePath; + std::string DBGSourcePath; + + cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGBuildSourcePath")); + if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ()) + { + CFCString::FileSystemRepresentation(cf_str, DBGBuildSourcePath); + } + + cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGSourcePath")); + if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ()) + { + CFCString::FileSystemRepresentation(cf_str, DBGSourcePath); + } + + if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty()) + { + module_spec.GetSourceMappingList().Append (ConstString(DBGBuildSourcePath.c_str()), ConstString(DBGSourcePath.c_str()), true); + } + } + return success; +} bool @@ -592,7 +647,8 @@ Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec) { bool success = false; const UUID *uuid_ptr = module_spec.GetUUIDPtr(); - if (uuid_ptr) + const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr(); + if (uuid_ptr || (file_spec_ptr && file_spec_ptr->Exists())) { static bool g_located_dsym_for_uuid_exe = false; static bool g_dsym_for_uuid_exe_exists = false; @@ -623,55 +679,80 @@ Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec) } if (g_dsym_for_uuid_exe_exists) { - StreamString command; char uuid_cstr_buffer[64]; - const char *uuid_cstr = uuid_ptr->GetAsCString(uuid_cstr_buffer, sizeof(uuid_cstr_buffer)); - command.Printf("%s --copyExecutable %s", g_dsym_for_uuid_exe_path, uuid_cstr); - int exit_status = -1; - int signo = -1; - std::string command_output; - Error error = Host::RunShellCommand (command.GetData(), - NULL, // current working directory - &exit_status, // Exit status - &signo, // Signal int * - &command_output, // Command output - 30, // Large timeout to allow for long dsym download times - NULL); // Don't run in a shell (we don't need shell expansion) - if (error.Success() && exit_status == 0 && !command_output.empty()) + char file_path[PATH_MAX]; + uuid_cstr_buffer[0] = '\0'; + file_path[0] = '\0'; + const char *uuid_cstr = NULL; + + if (uuid_ptr) + uuid_cstr = uuid_ptr->GetAsCString(uuid_cstr_buffer, sizeof(uuid_cstr_buffer)); + + if (file_spec_ptr) + file_spec_ptr->GetPath(file_path, sizeof(file_path)); + + StreamString command; + if (uuid_cstr) + command.Printf("%s --copyExecutable %s", g_dsym_for_uuid_exe_path, uuid_cstr); + else if (file_path && file_path[0]) + command.Printf("%s --copyExecutable %s", g_dsym_for_uuid_exe_path, file_path); + + if (!command.GetString().empty()) { - CFCData data (CFDataCreateWithBytesNoCopy (NULL, - (const UInt8 *)command_output.data(), - command_output.size(), - kCFAllocatorNull)); - - CFCReleaser<CFPropertyListRef> plist(::CFPropertyListCreateFromXMLData (NULL, data.get(), kCFPropertyListImmutable, NULL)); - - if (CFGetTypeID (plist.get()) == CFDictionaryGetTypeID ()) + int exit_status = -1; + int signo = -1; + std::string command_output; + Error error = Host::RunShellCommand (command.GetData(), + NULL, // current working directory + &exit_status, // Exit status + &signo, // Signal int * + &command_output, // Command output + 30, // Large timeout to allow for long dsym download times + NULL); // Don't run in a shell (we don't need shell expansion) + if (error.Success() && exit_status == 0 && !command_output.empty()) { - std::string str; - CFCString uuid_cfstr(uuid_cstr); - CFTypeRef uuid_dict = CFDictionaryGetValue ((CFDictionaryRef) plist.get(), uuid_cfstr.get()); - if (uuid_dict != NULL && CFGetTypeID (uuid_dict) == CFDictionaryGetTypeID ()) + CFCData data (CFDataCreateWithBytesNoCopy (NULL, + (const UInt8 *)command_output.data(), + command_output.size(), + kCFAllocatorNull)); + + CFCReleaser<CFDictionaryRef> plist((CFDictionaryRef)::CFPropertyListCreateFromXMLData (NULL, data.get(), kCFPropertyListImmutable, NULL)); + + if (CFGetTypeID (plist.get()) == CFDictionaryGetTypeID ()) { - CFStringRef cf_str; - - cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGSymbolRichExecutable")); - if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ()) + if (uuid_cstr) { - if (CFCString::FileSystemRepresentation(cf_str, str)) - { - success = true; - module_spec.GetFileSpec().SetFile (str.c_str(), true); - } + CFCString uuid_cfstr(uuid_cstr); + CFDictionaryRef uuid_dict = (CFDictionaryRef)CFDictionaryGetValue (plist.get(), uuid_cfstr.get()); + success = GetModuleSpecInfoFromUUIDDictionary (uuid_dict, module_spec); } - - cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGDSYMPath")); - if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ()) + else { - if (CFCString::FileSystemRepresentation(cf_str, str)) + const CFIndex num_values = ::CFDictionaryGetCount(plist.get()); + if (num_values > 0) { - success = true; - module_spec.GetSymbolFileSpec().SetFile (str.c_str(), true); + std::vector<CFStringRef> keys (num_values, NULL); + std::vector<CFDictionaryRef> values (num_values, NULL); + ::CFDictionaryGetKeysAndValues(plist.get(), NULL, (const void **)&values[0]); + if (num_values == 1) + { + return GetModuleSpecInfoFromUUIDDictionary (values[0], module_spec); + } + else + { + for (CFIndex i=0; i<num_values; ++i) + { + ModuleSpec curr_module_spec; + if (GetModuleSpecInfoFromUUIDDictionary (values[i], curr_module_spec)) + { + if (module_spec.GetArchitecture() == curr_module_spec.GetArchitecture()) + { + module_spec = curr_module_spec; + return true; + } + } + } + } } } } diff --git a/lldb/source/Interpreter/OptionGroupBoolean.cpp b/lldb/source/Interpreter/OptionGroupBoolean.cpp index f5403cfb992..58ac0f1def8 100644 --- a/lldb/source/Interpreter/OptionGroupBoolean.cpp +++ b/lldb/source/Interpreter/OptionGroupBoolean.cpp @@ -21,20 +21,19 @@ OptionGroupBoolean::OptionGroupBoolean (uint32_t usage_mask, bool required, const char *long_option, char short_option, - uint32_t completion_type, - lldb::CommandArgumentType argument_type, const char *usage_text, - bool default_value) : + bool default_value, + bool no_argument_toggle_default) : m_value (default_value, default_value) { m_option_definition.usage_mask = usage_mask; m_option_definition.required = required; m_option_definition.long_option = long_option; m_option_definition.short_option = short_option; - m_option_definition.option_has_arg = required_argument; + m_option_definition.option_has_arg = no_argument_toggle_default ? no_argument : required_argument; m_option_definition.enum_values = NULL; - m_option_definition.completion_type = completion_type; - m_option_definition.argument_type = argument_type; + m_option_definition.completion_type = 0; + m_option_definition.argument_type = eArgTypeBoolean; m_option_definition.usage_text = usage_text; } @@ -47,7 +46,17 @@ OptionGroupBoolean::SetOptionValue (CommandInterpreter &interpreter, uint32_t option_idx, const char *option_arg) { - Error error (m_value.SetValueFromCString (option_arg)); + Error error; + if (m_option_definition.option_has_arg == no_argument) + { + // Not argument, toggle the default value and mark the option as having been set + m_value.SetCurrentValue (!m_value.GetDefaultValue()); + m_value.SetOptionWasSet (); + } + else + { + error = m_value.SetValueFromCString (option_arg); + } return error; } diff --git a/lldb/source/Interpreter/OptionValueFileSpec.cpp b/lldb/source/Interpreter/OptionValueFileSpec.cpp index 03608753658..62b80bc9f8b 100644 --- a/lldb/source/Interpreter/OptionValueFileSpec.cpp +++ b/lldb/source/Interpreter/OptionValueFileSpec.cpp @@ -21,6 +21,35 @@ using namespace lldb; using namespace lldb_private; + +OptionValueFileSpec::OptionValueFileSpec () : + OptionValue(), + m_current_value (), + m_default_value (), + m_data_sp(), + m_completion_mask (CommandCompletions::eDiskFileCompletion) +{ +} + +OptionValueFileSpec::OptionValueFileSpec (const FileSpec &value) : + OptionValue(), + m_current_value (value), + m_default_value (value), + m_data_sp(), + m_completion_mask (CommandCompletions::eDiskFileCompletion) +{ +} + +OptionValueFileSpec::OptionValueFileSpec (const FileSpec ¤t_value, + const FileSpec &default_value) : + OptionValue(), + m_current_value (current_value), + m_default_value (default_value), + m_data_sp(), + m_completion_mask (CommandCompletions::eDiskFileCompletion) +{ +} + void OptionValueFileSpec::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) { @@ -101,7 +130,7 @@ OptionValueFileSpec::AutoComplete (CommandInterpreter &interpreter, word_complete = false; matches.Clear(); CommandCompletions::InvokeCommonCompletionCallbacks (interpreter, - CommandCompletions::eDiskFileCompletion, + m_completion_mask, s, match_start_point, max_return_elements, diff --git a/lldb/source/Interpreter/OptionValueUUID.cpp b/lldb/source/Interpreter/OptionValueUUID.cpp index 03a5684b1d0..4db5a99ca3a 100644 --- a/lldb/source/Interpreter/OptionValueUUID.cpp +++ b/lldb/source/Interpreter/OptionValueUUID.cpp @@ -13,7 +13,10 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Core/Module.h" #include "lldb/Core/Stream.h" +#include "lldb/Core/StringList.h" +#include "lldb/Interpreter/CommandInterpreter.h" using namespace lldb; using namespace lldb_private; @@ -45,7 +48,7 @@ OptionValueUUID::SetValueFromCString (const char *value_cstr, case eVarSetOperationReplace: case eVarSetOperationAssign: { - if (m_uuid.SetfromCString(value_cstr) == 0) + if (m_uuid.SetFromCString(value_cstr) == 0) error.SetErrorStringWithFormat ("invalid uuid string value '%s'", value_cstr); else m_value_was_set = true; @@ -68,3 +71,50 @@ OptionValueUUID::DeepCopy () const { return OptionValueSP(new OptionValueUUID(*this)); } + +size_t +OptionValueUUID::AutoComplete (CommandInterpreter &interpreter, + const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) +{ + word_complete = false; + matches.Clear(); + ExecutionContext exe_ctx(interpreter.GetExecutionContext()); + Target *target = exe_ctx.GetTargetPtr(); + if (target) + { + const size_t num_modules = target->GetImages().GetSize(); + if (num_modules > 0) + { + char uuid_cstr[64]; + UUID::ValueType uuid_bytes; + const size_t num_bytes_decoded = UUID::DecodeUUIDBytesFromCString(s, uuid_bytes, NULL); + for (size_t i=0; i<num_modules; ++i) + { + ModuleSP module_sp (target->GetImages().GetModuleAtIndex(i)); + if (module_sp) + { + const UUID &module_uuid = module_sp->GetUUID(); + if (module_uuid.IsValid()) + { + bool add_uuid = false; + if (num_bytes_decoded == 0) + add_uuid = true; + else + add_uuid = ::memcmp(module_uuid.GetBytes(), uuid_bytes, num_bytes_decoded) == 0; + if (add_uuid) + { + if (module_uuid.GetAsCString(uuid_cstr, sizeof(uuid_cstr))) + matches.AppendString(uuid_cstr); + } + } + } + } + } + } + return matches.GetSize(); +} + diff --git a/lldb/source/Interpreter/Property.cpp b/lldb/source/Interpreter/Property.cpp index d2bf1e1fe98..a66c04d0b01 100644 --- a/lldb/source/Interpreter/Property.cpp +++ b/lldb/source/Interpreter/Property.cpp @@ -148,7 +148,7 @@ Property::Property (const PropertyDefinition &definition) : { UUID uuid; if (definition.default_cstr_value) - uuid.SetfromCString (definition.default_cstr_value); + uuid.SetFromCString (definition.default_cstr_value); m_value_sp.reset (new OptionValueUUID(uuid)); } break; |

