diff options
author | Ed Maste <emaste@FreeBSD.org> | 2014-02-25 21:42:16 +0000 |
---|---|---|
committer | Ed Maste <emaste@FreeBSD.org> | 2014-02-25 21:42:16 +0000 |
commit | 03b99097822ca3ac69252d9afae716a584ed56c4 (patch) | |
tree | e0f754ea0922908b0f1be8f01c4efbdfc20462eb | |
parent | 866dcdacfe59f5f448e008fe2c4cb9dfcf72b2ec (diff) |
Notes
39 files changed, 735 insertions, 248 deletions
diff --git a/include/lldb/Core/ArchSpec.h b/include/lldb/Core/ArchSpec.h index 4ec8e06c8b35..1ccb385783a0 100644 --- a/include/lldb/Core/ArchSpec.h +++ b/include/lldb/Core/ArchSpec.h @@ -92,6 +92,10 @@ public: eCore_x86_64_x86_64, eCore_x86_64_x86_64h, // Haswell enabled x86_64 + eCore_hexagon_generic, + eCore_hexagon_hexagonv4, + eCore_hexagon_hexagonv5, + eCore_uknownMach32, eCore_uknownMach64, kNumCores, @@ -103,6 +107,7 @@ public: kCore_ppc_any, kCore_ppc64_any, kCore_x86_32_any, + kCore_hexagon_any, kCore_arm_first = eCore_arm_generic, kCore_arm_last = eCore_arm_xscale, @@ -117,7 +122,10 @@ public: kCore_ppc64_last = eCore_ppc64_ppc970_64, kCore_x86_32_first = eCore_x86_32_i386, - kCore_x86_32_last = eCore_x86_32_i486sx + kCore_x86_32_last = eCore_x86_32_i486sx, + + kCore_hexagon_first = eCore_hexagon_generic, + kCore_hexagon_last = eCore_hexagon_hexagonv5 }; //------------------------------------------------------------------ diff --git a/include/lldb/Core/IOHandler.h b/include/lldb/Core/IOHandler.h index a7d4880da0d3..78d1e7447db4 100644 --- a/include/lldb/Core/IOHandler.h +++ b/include/lldb/Core/IOHandler.h @@ -63,6 +63,16 @@ namespace lldb_private { virtual void Refresh () = 0; + // Called when an input reader should relinquish its control so another + // can be pushed onto the IO handler stack, or so the current IO + // handler can pop itself off the stack + + virtual void + Cancel () = 0; + + // Called when CTRL+C is pressed which usually causes + // Debugger::DispatchInputInterrupt to be called. + virtual void Interrupt () = 0; @@ -395,6 +405,9 @@ namespace lldb_private { Refresh (); virtual void + Cancel (); + + virtual void Interrupt (); virtual void @@ -500,7 +513,10 @@ namespace lldb_private { virtual void Refresh (); - + + virtual void + Cancel (); + virtual void Interrupt (); diff --git a/include/lldb/Host/HostGetOpt.h b/include/lldb/Host/HostGetOpt.h index 6fb7b51dddba..f4b2c87be230 100644 --- a/include/lldb/Host/HostGetOpt.h +++ b/include/lldb/Host/HostGetOpt.h @@ -17,4 +17,4 @@ #include <lldb/Host/windows/GetOptInc.h> -#endif
\ No newline at end of file +#endif diff --git a/include/lldb/Interpreter/PythonDataObjects.h b/include/lldb/Interpreter/PythonDataObjects.h index 55df4fd1b0a1..63f1ad5f67bf 100644 --- a/include/lldb/Interpreter/PythonDataObjects.h +++ b/include/lldb/Interpreter/PythonDataObjects.h @@ -98,6 +98,9 @@ namespace lldb_private { return m_py_obj != NULL; } + bool + IsNULLOrNone () const; + protected: PyObject* m_py_obj; }; diff --git a/include/lldb/Symbol/VariableList.h b/include/lldb/Symbol/VariableList.h index 2ce6146f4627..08efd3d5b9a1 100644 --- a/include/lldb/Symbol/VariableList.h +++ b/include/lldb/Symbol/VariableList.h @@ -49,10 +49,16 @@ public: lldb::VariableSP FindVariable (const ConstString& name); + + lldb::VariableSP + FindVariable (const ConstString& name, lldb::ValueType value_type); uint32_t FindVariableIndex (const lldb::VariableSP &var_sp); - + + size_t + AppendVariablesIfUnique(VariableList &var_list); + // Returns the actual number of unique variables that were added to the // list. "total_matches" will get updated with the actualy number of // matches that were found regardless of whether they were unique or not diff --git a/include/lldb/Target/Process.h b/include/lldb/Target/Process.h index f52b54da52cf..b74347d37e68 100644 --- a/include/lldb/Target/Process.h +++ b/include/lldb/Target/Process.h @@ -815,9 +815,16 @@ public: return m_monitor_callback_baton; } + // If the LaunchInfo has a monitor callback, then arrange to monitor the process. + // Return true if the LaunchInfo has taken care of monitoring the process, and false if the + // caller might want to monitor the process themselves. + bool MonitorProcess () const { + if (GetFlags().Test(lldb::eLaunchFlagsDontMonitorProcess)) + return true; + if (m_monitor_callback && ProcessIDIsValid()) { Host::StartMonitoringChildProcess (m_monitor_callback, diff --git a/include/lldb/lldb-enumerations.h b/include/lldb/lldb-enumerations.h index c8294960a7b2..347e20f21df6 100644 --- a/include/lldb/lldb-enumerations.h +++ b/include/lldb/lldb-enumerations.h @@ -46,7 +46,9 @@ namespace lldb { eLaunchFlagDisableSTDIO = (1u << 4), ///< Disable stdio for inferior process (e.g. for a GUI app) eLaunchFlagLaunchInTTY = (1u << 5), ///< Launch the process in a new TTY if supported by the host eLaunchFlagLaunchInShell= (1u << 6), ///< Launch the process inside a shell to get shell expansion - eLaunchFlagLaunchInSeparateProcessGroup = (1u << 7) ///< Launch the process in a separate process group + eLaunchFlagLaunchInSeparateProcessGroup = (1u << 7), ///< Launch the process in a separate process group + eLaunchFlagsDontMonitorProcess = (1u << 8) ///< If you are going to hand the process off (e.g. to debugserver) + ///< set this flag so lldb & the handee don't race to reap it. } LaunchFlags; //---------------------------------------------------------------------- diff --git a/source/API/SBFrame.cpp b/source/API/SBFrame.cpp index cff460208070..44fc654c44b6 100644 --- a/source/API/SBFrame.cpp +++ b/source/API/SBFrame.cpp @@ -845,6 +845,8 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy frame = exe_ctx.GetFramePtr(); if (frame) { + VariableList variable_list; + switch (value_type) { case eValueTypeVariableGlobal: // global variable @@ -852,8 +854,7 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy case eValueTypeVariableArgument: // function argument variables case eValueTypeVariableLocal: // function local variables { - VariableList *variable_list = frame->GetVariableList(true); - + SymbolContext sc (frame->GetSymbolContext (eSymbolContextBlock)); const bool can_create = true; @@ -863,21 +864,22 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy if (sc.block && sc.block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, - variable_list)) + &variable_list)) { + if (value_type == eValueTypeVariableGlobal) + { + const bool get_file_globals = true; + VariableList* frame_vars = frame->GetVariableList(get_file_globals); + if (frame_vars) + frame_vars->AppendVariablesIfUnique(variable_list); + } ConstString const_name(name); - const uint32_t num_variables = variable_list->GetSize(); - for (uint32_t i = 0; i < num_variables; ++i) + VariableSP variable_sp(variable_list.FindVariable(const_name,value_type)); + if (variable_sp) { - VariableSP variable_sp (variable_list->GetVariableAtIndex(i)); - if (variable_sp && - variable_sp->GetScope() == value_type && - variable_sp->GetName() == const_name) - { - value_sp = frame->GetValueObjectForFrameVariable (variable_sp, eNoDynamicValues); - sb_value.SetSP (value_sp, use_dynamic); - break; - } + value_sp = frame->GetValueObjectForFrameVariable (variable_sp, eNoDynamicValues); + sb_value.SetSP (value_sp, use_dynamic); + break; } } } diff --git a/source/Core/ArchSpec.cpp b/source/Core/ArchSpec.cpp index f4fa22437a9c..a93f4bd7b5f7 100644 --- a/source/Core/ArchSpec.cpp +++ b/source/Core/ArchSpec.cpp @@ -105,6 +105,10 @@ static const CoreDefinition g_core_definitions[ArchSpec::kNumCores] = { eByteOrderLittle, 8, 1, 15, llvm::Triple::x86_64 , ArchSpec::eCore_x86_64_x86_64 , "x86_64" }, { eByteOrderLittle, 8, 1, 15, llvm::Triple::x86_64 , ArchSpec::eCore_x86_64_x86_64h , "x86_64h" }, + { eByteOrderLittle, 4, 4, 4, llvm::Triple::hexagon , ArchSpec::eCore_hexagon_generic, "hexagon" }, + { eByteOrderLittle, 4, 4, 4, llvm::Triple::hexagon , ArchSpec::eCore_hexagon_hexagonv4, "hexagonv4" }, + { eByteOrderLittle, 4, 4, 4, llvm::Triple::hexagon , ArchSpec::eCore_hexagon_hexagonv5, "hexagonv5" }, + { eByteOrderLittle, 4, 4, 4 , llvm::Triple::UnknownArch , ArchSpec::eCore_uknownMach32 , "unknown-mach-32" }, { eByteOrderLittle, 8, 4, 4 , llvm::Triple::UnknownArch , ArchSpec::eCore_uknownMach64 , "unknown-mach-64" } }; @@ -237,7 +241,8 @@ static const ArchDefinitionEntry g_elf_arch_entries[] = { ArchSpec::eCore_arm_generic , llvm::ELF::EM_ARM , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARM { ArchSpec::eCore_sparc9_generic , llvm::ELF::EM_SPARCV9, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // SPARC V9 { ArchSpec::eCore_x86_64_x86_64 , llvm::ELF::EM_X86_64 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // AMD64 - { ArchSpec::eCore_mips64 , llvm::ELF::EM_MIPS , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu } // MIPS + { ArchSpec::eCore_mips64 , llvm::ELF::EM_MIPS , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // MIPS + { ArchSpec::eCore_hexagon_generic , llvm::ELF::EM_HEXAGON, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu } // HEXAGON }; static const ArchDefinition g_elf_arch_def = { @@ -919,6 +924,10 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in if (core2 == ArchSpec::eCore_arm_armv7) return true; } + + case ArchSpec::kCore_hexagon_any: + if ((core2 >= ArchSpec::kCore_hexagon_first && core2 <= ArchSpec::kCore_hexagon_last) || (core2 == ArchSpec::kCore_hexagon_any)) + return true; break; case ArchSpec::eCore_arm_armv7m: diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp index 5b346ed636d6..34e0e329f092 100644 --- a/source/Core/Debugger.cpp +++ b/source/Core/Debugger.cpp @@ -846,7 +846,7 @@ Debugger::ClearIOHandlers () { m_input_reader_stack.Pop(); reader_sp->SetIsDone(true); - reader_sp->Interrupt(); + reader_sp->Cancel(); } } } diff --git a/source/Core/IOHandler.cpp b/source/Core/IOHandler.cpp index bdec19ccb06f..168a8f67a08e 100644 --- a/source/Core/IOHandler.cpp +++ b/source/Core/IOHandler.cpp @@ -588,6 +588,13 @@ IOHandlerEditline::Refresh () } void +IOHandlerEditline::Cancel () +{ + if (m_editline_ap) + m_editline_ap->Interrupt (); +} + +void IOHandlerEditline::Interrupt () { if (m_editline_ap) @@ -5279,6 +5286,10 @@ IOHandlerCursesGUI::Refresh () { } +void +IOHandlerCursesGUI::Cancel () +{ +} void IOHandlerCursesGUI::Interrupt () diff --git a/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp index 64ef98297cd2..198fde93386e 100644 --- a/source/Expression/ClangExpressionDeclMap.cpp +++ b/source/Expression/ClangExpressionDeclMap.cpp @@ -1428,6 +1428,10 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, if (data_symbol) { + std::string warning("got name from symbols: "); + warning.append(name.AsCString()); + const unsigned diag_id = m_ast_context->getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Level::Warning, "%0"); + m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str(); AddOneGenericVariable(context, *data_symbol, current_id); context.m_found.variable = true; } diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp index 9e5e4cbdb04a..d43221c0e136 100644 --- a/source/Host/common/Host.cpp +++ b/source/Host/common/Host.cpp @@ -1743,25 +1743,32 @@ Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_i // posix_spawnattr_setbinpref_np appears to be an Apple extension per: // http://www.unix.com/man-page/OSX/3/posix_spawnattr_setbinpref_np/ #if defined (__APPLE__) && !defined (__arm__) + + // Don't set the binpref if a shell was provided. After all, that's only going to affect what version of the shell + // is launched, not what fork of the binary is launched. We insert "arch --arch <ARCH> as part of the shell invocation + // to do that job on OSX. + + if (launch_info.GetShell() == nullptr) + { + // We don't need to do this for ARM, and we really shouldn't now that we + // have multiple CPU subtypes and no posix_spawnattr call that allows us + // to set which CPU subtype to launch... + const ArchSpec &arch_spec = launch_info.GetArchitecture(); + cpu_type_t cpu = arch_spec.GetMachOCPUType(); + cpu_type_t sub = arch_spec.GetMachOCPUSubType(); + if (cpu != 0 && + cpu != UINT32_MAX && + cpu != LLDB_INVALID_CPUTYPE && + !(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try to set the CPU type or we will fail + { + size_t ocount = 0; + error.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), eErrorTypePOSIX); + if (error.Fail() || log) + error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %llu )", cpu, (uint64_t)ocount); - // We don't need to do this for ARM, and we really shouldn't now that we - // have multiple CPU subtypes and no posix_spawnattr call that allows us - // to set which CPU subtype to launch... - const ArchSpec &arch_spec = launch_info.GetArchitecture(); - cpu_type_t cpu = arch_spec.GetMachOCPUType(); - cpu_type_t sub = arch_spec.GetMachOCPUSubType(); - if (cpu != 0 && - cpu != UINT32_MAX && - cpu != LLDB_INVALID_CPUTYPE && - !(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try to set the CPU type or we will fail - { - size_t ocount = 0; - error.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), eErrorTypePOSIX); - if (error.Fail() || log) - error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %llu )", cpu, (uint64_t)ocount); - - if (error.Fail() || ocount != 1) - return error; + if (error.Fail() || ocount != 1) + return error; + } } #endif diff --git a/source/Interpreter/PythonDataObjects.cpp b/source/Interpreter/PythonDataObjects.cpp index 01f2754a2cc9..053ff34b9d77 100644 --- a/source/Interpreter/PythonDataObjects.cpp +++ b/source/Interpreter/PythonDataObjects.cpp @@ -84,6 +84,12 @@ PythonObject::Str () return PythonString(str); } +bool +PythonObject::IsNULLOrNone () const +{ + return ((m_py_obj == nullptr) || (m_py_obj == Py_None)); +} + //---------------------------------------------------------------------- // PythonString //---------------------------------------------------------------------- diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp index 624a662e26bf..c1d28e88afc1 100644 --- a/source/Interpreter/ScriptInterpreterPython.cpp +++ b/source/Interpreter/ScriptInterpreterPython.cpp @@ -781,7 +781,13 @@ public: { } - + + virtual void + Cancel () + { + + } + virtual void Interrupt () { @@ -2278,7 +2284,6 @@ ScriptInterpreterPython::LoadScriptingModule (const char* pathname, command_stream.Clear(); command_stream.Printf("sys.modules.__contains__('%s')",basename.c_str()); bool does_contain = false; - int refcount = 0; // this call will succeed if the module was ever imported in any Debugger in the lifetime of the process // in which this LLDB framework is living bool was_imported_globally = (ExecuteOneLineWithReturn(command_stream.GetData(), @@ -2288,10 +2293,7 @@ ScriptInterpreterPython::LoadScriptingModule (const char* pathname, // this call will fail if the module was not imported in this Debugger before command_stream.Clear(); command_stream.Printf("sys.getrefcount(%s)",basename.c_str()); - bool was_imported_locally = (ExecuteOneLineWithReturn(command_stream.GetData(), - ScriptInterpreterPython::eScriptReturnTypeInt, - &refcount, - ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)) && refcount > 0); + bool was_imported_locally = !(GetSessionDictionary().GetItemForKey(basename.c_str()).IsNULLOrNone()); bool was_imported = (was_imported_globally || was_imported_locally); @@ -2546,8 +2548,8 @@ ScriptInterpreterPython::InitializePrivate () Py_InitializeEx (0); // Initialize SWIG after setting up python - assert (g_swig_init_callback != NULL); - g_swig_init_callback (); + if (g_swig_init_callback) + g_swig_init_callback (); // Update the path python uses to search for modules to include the current directory. diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp index f360a182e065..8596381b3cbc 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp @@ -235,22 +235,12 @@ ABIMacOSX_i386::GetRedZoneSize () const ABISP ABIMacOSX_i386::CreateInstance (const ArchSpec &arch) { - static ABISP g_abi_mac_sp; - static ABISP g_abi_other_sp; - if (arch.GetTriple().getArch() == llvm::Triple::x86) - { - if (arch.GetTriple().isOSDarwin()) - { - if (!g_abi_mac_sp) - g_abi_mac_sp.reset (new ABIMacOSX_i386(true)); - return g_abi_mac_sp; - } - else - { - if (!g_abi_other_sp) - g_abi_other_sp.reset (new ABIMacOSX_i386(false)); - return g_abi_other_sp; - } + static ABISP g_abi_sp; + if (arch.GetTriple().getArch() == llvm::Triple::x86) + { + if (!g_abi_sp) + g_abi_sp.reset (new ABIMacOSX_i386); + return g_abi_sp; } return ABISP(); } diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h index a2eee280fa38..43784a5c9111 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h @@ -71,24 +71,25 @@ public: return true; } + // The Darwin i386 ABI requires that stack frames be 16 byte aligned. + // When there is a trap handler on the stack, e.g. _sigtramp in userland + // code, we've seen that the stack pointer is often not aligned properly + // before the handler is invoked. This means that lldb will stop the unwind + // early -- before the function which caused the trap. + // + // To work around this, we relax that alignment to be just word-size (4-bytes). + // Whitelisting the trap handlers for user space would be easy (_sigtramp) but + // in other environments there can be a large number of different functions + // involved in async traps. + // + // If we were to enforce 16-byte alignment, we also need to relax to 4-byte + // alignment for non-darwin i386 targets. virtual bool CallFrameAddressIsValid (lldb::addr_t cfa) { - // Darwin call frame addresses must be 16-byte aligned, but other OS's - // only need 4-byte alignment. Otherwise the ABI matches, so we have - // this one minor override here. - if (target_is_darwin) - { - // Make sure the stack call frame addresses are are 16 byte aligned - if (cfa & (16ull - 1ull)) - return false; // Not 16 byte aligned - } - else - { - // Make sure the stack call frame addresses are are 4 byte aligned - if (cfa & (4ull - 1ull)) - return false; // Not 4 byte aligned - } + // Make sure the stack call frame addresses are are 4 byte aligned + if (cfa & (4ull - 1ull)) + return false; // Not 4 byte aligned if (cfa == 0) return false; // Zero is not a valid stack address return true; @@ -139,11 +140,7 @@ protected: RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); private: - ABIMacOSX_i386(bool is_darwin) : lldb_private::ABI(), - target_is_darwin(is_darwin) - { } // Call CreateInstance instead. - - bool target_is_darwin; + ABIMacOSX_i386() : lldb_private::ABI() { } // Call CreateInstance instead. }; diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h index 5ccb6e5fa744..7fd1b6c4b0f3 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h @@ -68,12 +68,22 @@ public: return true; } + // The SysV x86_64 ABI requires that stack frames be 16 byte aligned. + // When there is a trap handler on the stack, e.g. _sigtramp in userland + // code, we've seen that the stack pointer is often not aligned properly + // before the handler is invoked. This means that lldb will stop the unwind + // early -- before the function which caused the trap. + // + // To work around this, we relax that alignment to be just word-size (8-bytes). + // Whitelisting the trap handlers for user space would be easy (_sigtramp) but + // in other environments there can be a large number of different functions + // involved in async traps. virtual bool CallFrameAddressIsValid (lldb::addr_t cfa) { - // Make sure the stack call frame addresses are 16 byte aligned - if (cfa & (16ull - 1ull)) - return false; // Not 16 byte aligned + // Make sure the stack call frame addresses are 8 byte aligned + if (cfa & (8ull - 1ull)) + return false; // Not 8 byte aligned if (cfa == 0) return false; // Zero is not a valid stack address return true; diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 02db05b3c6b2..335090cc0c36 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -468,7 +468,6 @@ ObjectFileELF::SetLoadAddress (Target &target, lldb::addr_t value, bool value_is_offset) { - bool changed = false; ModuleSP module_sp = GetModule(); if (module_sp) { @@ -480,7 +479,7 @@ ObjectFileELF::SetLoadAddress (Target &target, { const size_t num_sections = section_list->GetSize(); size_t sect_idx = 0; - + for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) { // Iterate through the object file sections to find all @@ -493,7 +492,6 @@ ObjectFileELF::SetLoadAddress (Target &target, ++num_loaded_sections; } } - changed = num_loaded_sections > 0; return num_loaded_sections > 0; } else @@ -503,7 +501,7 @@ ObjectFileELF::SetLoadAddress (Target &target, } } } - return changed; + return false; // If it changed } ByteOrder diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index ce5645ea74fe..3832265638db 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -265,9 +265,6 @@ PlatformRemoteGDBServer::ConnectRemote (Args& args) // If a working directory was set prior to connecting, send it down now if (m_working_dir) m_gdb_client.SetWorkingDir(m_working_dir.GetCString()); -#if 0 - m_gdb_client.TestPacketSpeed(10000); -#endif } else { diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp index 083f08ebba84..d13b9a485858 100644 --- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp @@ -132,6 +132,8 @@ ProcessFreeBSD::DoDetach(bool keep_stopped) return error; } + DisableAllBreakpointSites(); + error = m_monitor->Detach(GetID()); if (error.Success()) diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index 3b260538b190..3d793d0c1c20 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -101,8 +101,8 @@ PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, log->Printf("ptrace() failed; errno=%d (%s)", errno, str); } -#ifdef __amd64__ if (log) { +#ifdef __amd64__ if (req == PT_GETREGS) { struct reg *r = (struct reg *) addr; @@ -111,8 +111,15 @@ PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, log->Printf("PT_GETREGS: bp=0x%lx", r->r_rbp); log->Printf("PT_GETREGS: ax=0x%lx", r->r_rax); } - } #endif + if (req == PT_GETDBREGS || req == PT_SETDBREGS) { + struct dbreg *r = (struct dbreg *) addr; + char setget = (req == PT_GETDBREGS) ? 'G' : 'S'; + + for (int i = 0; i <= 7; i++) + log->Printf("PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]); + } + } return result; } @@ -348,6 +355,82 @@ WriteRegOperation::Execute(ProcessMonitor *monitor) } //------------------------------------------------------------------------------ +/// @class ReadDebugRegOperation +/// @brief Implements ProcessMonitor::ReadDebugRegisterValue. +class ReadDebugRegOperation : public Operation +{ +public: + ReadDebugRegOperation(lldb::tid_t tid, unsigned offset, unsigned size, + RegisterValue &value, bool &result) + : m_tid(tid), m_offset(offset), m_size(size), + m_value(value), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + lldb::tid_t m_tid; + unsigned m_offset; + unsigned m_size; + RegisterValue &m_value; + bool &m_result; +}; + +void +ReadDebugRegOperation::Execute(ProcessMonitor *monitor) +{ + struct dbreg regs; + int rc; + + if ((rc = PTRACE(PT_GETDBREGS, m_tid, (caddr_t)®s, 0)) < 0) { + m_result = false; + } else { + if (m_size == sizeof(uintptr_t)) + m_value = *(uintptr_t *)(((caddr_t)®s) + m_offset); + else + memcpy(&m_value, (((caddr_t)®s) + m_offset), m_size); + m_result = true; + } +} + +//------------------------------------------------------------------------------ +/// @class WriteDebugRegOperation +/// @brief Implements ProcessMonitor::WriteDebugRegisterValue. +class WriteDebugRegOperation : public Operation +{ +public: + WriteDebugRegOperation(lldb::tid_t tid, unsigned offset, + const RegisterValue &value, bool &result) + : m_tid(tid), m_offset(offset), + m_value(value), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + lldb::tid_t m_tid; + unsigned m_offset; + const RegisterValue &m_value; + bool &m_result; +}; + +void +WriteDebugRegOperation::Execute(ProcessMonitor *monitor) +{ + struct dbreg regs; + + if (PTRACE(PT_GETDBREGS, m_tid, (caddr_t)®s, 0) < 0) { + m_result = false; + return; + } + *(uintptr_t *)(((caddr_t)®s) + m_offset) = (uintptr_t)m_value.GetAsUInt64(); + if (PTRACE(PT_SETDBREGS, m_tid, (caddr_t)®s, 0) < 0) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ /// @class ReadGPROperation /// @brief Implements ProcessMonitor::ReadGPR. class ReadGPROperation : public Operation @@ -1175,7 +1258,7 @@ ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, case 0: case TRAP_TRACE: if (log) - log->Printf ("ProcessMonitor::%s() received trace event, tid = %" PRIu64, __FUNCTION__, tid); + log->Printf ("ProcessMonitor::%s() received trace event, tid = %" PRIu64 " : si_code = %d", __FUNCTION__, tid, info->si_code); message = ProcessMessage::Trace(tid); break; @@ -1464,6 +1547,28 @@ ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset, } bool +ProcessMonitor::ReadDebugRegisterValue(lldb::tid_t tid, unsigned offset, + const char *reg_name, unsigned size, + lldb_private::RegisterValue &value) +{ + bool result; + ReadDebugRegOperation op(tid, offset, size, value, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::WriteDebugRegisterValue(lldb::tid_t tid, unsigned offset, + const char *reg_name, + const lldb_private::RegisterValue &value) +{ + bool result; + WriteDebugRegOperation op(tid, offset, value, result); + DoOperation(&op); + return result; +} + +bool ProcessMonitor::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size) { bool result; diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h index 84bbac16e5e5..4c8198fb2e4c 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h @@ -116,6 +116,23 @@ public: WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name, const lldb_private::RegisterValue &value); + /// Reads the contents from the debug register identified by the given + /// (architecture dependent) offset. + /// + /// This method is provided for use by RegisterContextFreeBSD derivatives. + bool + ReadDebugRegisterValue(lldb::tid_t tid, unsigned offset, + const char *reg_name, unsigned size, + lldb_private::RegisterValue &value); + + /// Writes the given value to the debug register identified by the given + /// (architecture dependent) offset. + /// + /// This method is provided for use by RegisterContextFreeBSD derivatives. + bool + WriteDebugRegisterValue(lldb::tid_t tid, unsigned offset, + const char *reg_name, + const lldb_private::RegisterValue &value); /// Reads all general purpose registers into the specified buffer. bool ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size); diff --git a/source/Plugins/Process/POSIX/POSIXThread.cpp b/source/Plugins/Process/POSIX/POSIXThread.cpp index 8d4c71ff269a..cc759eaad96d 100644 --- a/source/Plugins/Process/POSIX/POSIXThread.cpp +++ b/source/Plugins/Process/POSIX/POSIXThread.cpp @@ -65,7 +65,16 @@ POSIXThread::POSIXThread(Process &process, lldb::tid_t tid) lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx); if (wp.get() && wp->IsEnabled()) { - assert(EnableHardwareWatchpoint(wp.get())); + // This watchpoint as been enabled; obviously this "new" thread + // has been created since that watchpoint was enabled. Since + // the POSIXBreakpointProtocol has yet to be initialized, its + // m_watchpoints_initialized member will be FALSE. Attempting to + // read the debug status register to determine if a watchpoint + // has been hit would result in the zeroing of that register. + // Since the active debug registers would have been cloned when + // this thread was created, simply force the m_watchpoints_initized + // member to TRUE and avoid resetting dr6 and dr7. + GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized(); } } } @@ -509,6 +518,21 @@ POSIXThread::WatchNotify(const ProcessMessage &message) void POSIXThread::TraceNotify(const ProcessMessage &message) { + POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); + if (reg_ctx) + { + uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); + uint32_t wp_idx; + for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) + { + if (reg_ctx->IsWatchpointHit(wp_idx)) + { + WatchNotify(message); + return; + } + } + } + SetStopInfo (StopInfo::CreateStopReasonToTrace(*this)); } diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp index 50ec8d414a12..01c9bb4cde8f 100644 --- a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp +++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp @@ -37,8 +37,18 @@ struct GPR uint32_t gs; }; -#define DR_SIZE 0 -#define DR_OFFSET(reg_index) 0 +struct dbreg { + uint32_t dr[8]; /* debug registers */ + /* Index 0-3: debug address registers */ + /* Index 4-5: reserved */ + /* Index 6: debug status */ + /* Index 7: debug control */ +}; + + +#define DR_SIZE sizeof(uint32_t) +#define DR_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(dbreg, dr[reg_index])) //--------------------------------------------------------------------------- // Include RegisterInfos_i386 to declare our g_register_infos_i386 structure. diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp index 471734580fff..2162aaffff18 100644 --- a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp +++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp @@ -46,8 +46,19 @@ typedef struct _GPR uint64_t ss; } GPR; -#define DR_SIZE 0 -#define DR_OFFSET(reg_index) 0 +struct dbreg { + uint64_t dr[16]; /* debug registers */ + /* Index 0-3: debug address registers */ + /* Index 4-5: reserved */ + /* Index 6: debug status */ + /* Index 7: debug control */ + /* Index 8-15: reserved */ +}; + +#define DR_SIZE sizeof(uint64_t) +#define DR_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(dbreg, dr[reg_index])) + //--------------------------------------------------------------------------- // Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 structure. diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX.h b/source/Plugins/Process/POSIX/RegisterContextPOSIX.h index e48c528403e3..600dae73b5b7 100644 --- a/source/Plugins/Process/POSIX/RegisterContextPOSIX.h +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX.h @@ -66,6 +66,10 @@ public: virtual uint32_t NumSupportedHardwareWatchpoints () = 0; + // Force m_watchpoints_initialized to TRUE + void + ForceWatchpointsInitialized () {m_watchpoints_initialized = true;} + protected: bool m_watchpoints_initialized; }; diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp index f833c9b47520..c446bbfa7dce 100644 --- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp @@ -109,6 +109,15 @@ RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(const unsigned reg, RegisterValue &value) { ProcessMonitor &monitor = GetMonitor(); + +#if defined(__FreeBSD__) + if (reg >= m_reg_info.first_dr) + return monitor.ReadDebugRegisterValue(m_thread.GetID(), + GetRegisterOffset(reg), + GetRegisterName(reg), + GetRegisterSize(reg), + value); +#endif return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg), GetRegisterName(reg), @@ -164,6 +173,13 @@ RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(const unsigned reg, } ProcessMonitor &monitor = GetMonitor(); +#if defined(__FreeBSD__) + if (reg >= m_reg_info.first_dr) + return monitor.WriteDebugRegisterValue(m_thread.GetID(), + GetRegisterOffset(reg_to_write), + GetRegisterName(reg_to_write), + value_to_write); +#endif return monitor.WriteRegisterValue(m_thread.GetID(), GetRegisterOffset(reg_to_write), GetRegisterName(reg_to_write), diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index f87db5810740..f209d538a712 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -50,6 +50,7 @@ RegisterContextLLDB::RegisterContextLLDB m_thread(thread), m_fast_unwind_plan_sp (), m_full_unwind_plan_sp (), + m_fallback_unwind_plan_sp (), m_all_registers_available(false), m_frame_type (-1), m_cfa (LLDB_INVALID_ADDRESS), @@ -764,8 +765,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () { m_fast_unwind_plan_sp.reset(); unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one); - if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) + if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc) && unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) + { return unwind_plan_sp; + } } // Ask the DynamicLoader if the eh_frame CFI should be trusted in this frame even when it's frame zero @@ -791,6 +794,15 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) { + if (unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) + { + // We probably have an UnwindPlan created by inspecting assembly instructions, and we probably + // don't have any eh_frame instructions available. + // The assembly profilers work really well with compiler-generated functions but hand-written + // assembly can be problematic. We'll set the architecture default UnwindPlan as our fallback + // UnwindPlan in case this doesn't work out when we try to unwind. + m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp; + } UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString()); return unwind_plan_sp; } @@ -808,6 +820,16 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () // We'd prefer to use an UnwindPlan intended for call sites when we're at a call site but if we've // struck out on that, fall back to using the non-call-site assembly inspection UnwindPlan if possible. unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread); + if (unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) + { + // We probably have an UnwindPlan created by inspecting assembly instructions, and we probably + // don't have any eh_frame instructions available. + // The assembly profilers work really well with compiler-generated functions but hand-written + // assembly can be problematic. We'll set the architecture default UnwindPlan as our fallback + // UnwindPlan in case this doesn't work out when we try to unwind. + m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp; + } + if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) { UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString()); @@ -1176,21 +1198,22 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat m_full_unwind_plan_sp->GetSourceName().GetCString()); // Throw away the full unwindplan; install the arch default unwindplan - InvalidateFullUnwindPlan(); - - // Now re-fetch the pc value we're searching for - uint32_t arch_default_pc_reg = LLDB_INVALID_REGNUM; - UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); - if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, m_full_unwind_plan_sp->GetRegisterKind(), arch_default_pc_reg) - && arch_default_pc_reg != LLDB_INVALID_REGNUM - && active_row - && active_row->GetRegisterInfo (arch_default_pc_reg, unwindplan_regloc)) + if (TryFallbackUnwindPlan()) { - have_unwindplan_regloc = true; - } - else - { - have_unwindplan_regloc = false; + // Now re-fetch the pc value we're searching for + uint32_t arch_default_pc_reg = LLDB_INVALID_REGNUM; + UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); + if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, m_full_unwind_plan_sp->GetRegisterKind(), arch_default_pc_reg) + && arch_default_pc_reg != LLDB_INVALID_REGNUM + && active_row + && active_row->GetRegisterInfo (arch_default_pc_reg, unwindplan_regloc)) + { + have_unwindplan_regloc = true; + } + else + { + have_unwindplan_regloc = false; + } } } } @@ -1333,54 +1356,48 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat } // If the Full unwindplan has been determined to be incorrect, this method will -// replace it with the architecture's default unwindplna, if one is defined. +// replace it with the architecture's default unwindplan, if one is defined. // It will also find the FuncUnwinders object for this function and replace the // Full unwind method for the function there so we don't use the errant Full unwindplan // again in the future of this debug session. // We're most likely doing this because the Full unwindplan was generated by assembly // instruction profiling and the profiler got something wrong. -void -RegisterContextLLDB::InvalidateFullUnwindPlan () +bool +RegisterContextLLDB::TryFallbackUnwindPlan () { UnwindPlan::Row::RegisterLocation unwindplan_regloc; - ExecutionContext exe_ctx (m_thread.shared_from_this()); - Process *process = exe_ctx.GetProcessPtr(); - ABI *abi = process ? process->GetABI().get() : NULL; - if (abi) + if (m_fallback_unwind_plan_sp.get() == NULL) + return false; + + UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp; + UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); + + if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM) { - UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp; - UnwindPlanSP arch_default_unwind_plan_sp; - arch_default_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp); - if (arch_default_unwind_plan_sp) + FuncUnwindersSP func_unwinders_sp; + if (m_sym_ctx_valid && m_current_pc.IsValid() && m_current_pc.GetModule()) { - UnwindPlan::RowSP active_row = arch_default_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); - - if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM) + func_unwinders_sp = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx); + if (func_unwinders_sp) { - FuncUnwindersSP func_unwinders_sp; - if (m_sym_ctx_valid && m_current_pc.IsValid() && m_current_pc.GetModule()) - { - func_unwinders_sp = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx); - if (func_unwinders_sp) - { - func_unwinders_sp->InvalidateNonCallSiteUnwindPlan (m_thread); - } - } - m_registers.clear(); - m_full_unwind_plan_sp = arch_default_unwind_plan_sp; - addr_t cfa_regval = LLDB_INVALID_ADDRESS; - if (ReadGPRValue (arch_default_unwind_plan_sp->GetRegisterKind(), active_row->GetCFARegister(), cfa_regval)) - { - m_cfa = cfa_regval + active_row->GetCFAOffset (); - } - - UnwindLogMsg ("full unwind plan '%s' has been replaced by architecture default unwind plan '%s' for this function from now on.", - original_full_unwind_plan_sp->GetSourceName().GetCString(), arch_default_unwind_plan_sp->GetSourceName().GetCString()); + func_unwinders_sp->InvalidateNonCallSiteUnwindPlan (m_thread); } } + m_registers.clear(); + m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; + addr_t cfa_regval = LLDB_INVALID_ADDRESS; + if (ReadGPRValue (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row->GetCFARegister(), cfa_regval)) + { + m_cfa = cfa_regval + active_row->GetCFAOffset (); + } + + UnwindLogMsg ("full unwind plan '%s' has been replaced by architecture default unwind plan '%s' for this function from now on.", + original_full_unwind_plan_sp->GetSourceName().GetCString(), m_fallback_unwind_plan_sp->GetSourceName().GetCString()); + m_fallback_unwind_plan_sp.reset(); } + + return true; } // Retrieve a general purpose register value for THIS frame, as saved by the NEXT frame, i.e. the frame that diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.h b/source/Plugins/Process/Utility/RegisterContextLLDB.h index bf9dd9a29319..0a60bfe382b5 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.h +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.h @@ -160,8 +160,20 @@ private: const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); - void - InvalidateFullUnwindPlan (); + //------------------------------------------------------------------ + /// If the unwind has to the caller frame has failed, try something else + /// + /// If lldb is using an assembly language based UnwindPlan for a frame and + /// the unwind to the caller frame fails, try falling back to a generic + /// UnwindPlan (architecture default unwindplan) to see if that might work + /// better. This is mostly helping to work around problems where the + /// assembly language inspection fails on hand-written assembly code. + /// + /// @return + /// Returns true if a fallback unwindplan was found & was installed. + //------------------------------------------------------------------ + bool + TryFallbackUnwindPlan (); // Get the contents of a general purpose (address-size) register for this frame // (usually retrieved from the next frame) @@ -191,8 +203,10 @@ private: // i.e. where THIS frame saved them /// - lldb::UnwindPlanSP m_fast_unwind_plan_sp; // may be NULL + lldb::UnwindPlanSP m_fast_unwind_plan_sp; // may be NULL lldb::UnwindPlanSP m_full_unwind_plan_sp; + lldb::UnwindPlanSP m_fallback_unwind_plan_sp; // may be NULL + bool m_all_registers_available; // Can we retrieve all regs or just nonvolatile regs? int m_frame_type; // enum FrameType diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp index a3a7002ea099..5db08e5c26de 100644 --- a/source/Plugins/Process/Utility/UnwindLLDB.cpp +++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp @@ -158,6 +158,12 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi) if (reg_ctx_sp.get() == NULL) { + // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return + // true. Subsequent calls to TryFallbackUnwindPlan() will return false. + if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) + { + return AddOneMoreFrame (abi); + } if (log) log->Printf ("%*sFrame %d did not get a RegisterContext, stopping.", cur_idx < 100 ? cur_idx : 100, "", cur_idx); @@ -166,6 +172,12 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi) if (!reg_ctx_sp->IsValid()) { + // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return + // true. Subsequent calls to TryFallbackUnwindPlan() will return false. + if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) + { + return AddOneMoreFrame (abi); + } if (log) { log->Printf("%*sFrame %d invalid RegisterContext for this frame, stopping stack walk", @@ -175,6 +187,12 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi) } if (!reg_ctx_sp->GetCFA (cursor_sp->cfa)) { + // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return + // true. Subsequent calls to TryFallbackUnwindPlan() will return false. + if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) + { + return AddOneMoreFrame (abi); + } if (log) { log->Printf("%*sFrame %d did not get CFA for this frame, stopping stack walk", @@ -189,6 +207,12 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi) // these. if (reg_ctx_sp->IsTrapHandlerFrame() == false) { + // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return + // true. Subsequent calls to TryFallbackUnwindPlan() will return false. + if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) + { + return AddOneMoreFrame (abi); + } if (log) { log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk", @@ -199,6 +223,12 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi) } if (!reg_ctx_sp->ReadPC (cursor_sp->start_pc)) { + // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return + // true. Subsequent calls to TryFallbackUnwindPlan() will return false. + if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) + { + return AddOneMoreFrame (abi); + } if (log) { log->Printf("%*sFrame %d did not get PC for this frame, stopping stack walk", @@ -208,6 +238,12 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi) } if (abi && !abi->CodeAddressIsValid (cursor_sp->start_pc)) { + // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return + // true. Subsequent calls to TryFallbackUnwindPlan() will return false. + if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) + { + return AddOneMoreFrame (abi); + } if (log) { log->Printf("%*sFrame %d did not get a valid PC, stopping stack walk", diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 1ec75a4bc7af..72600d835934 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -497,6 +497,13 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri for (int i = 0; i < repeat_count; ++i) packet_str.push_back(char_to_repeat); } + else if (*c == 0x7d) + { + // 0x7d is the escape character. The next character is to + // be XOR'd with 0x20. + char escapee = *++c ^ 0x20; + packet_str.push_back(escapee); + } else { packet_str.push_back(*c); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index aa60ec1b4a27..ab3bf7f5aa2a 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -136,6 +136,11 @@ GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr) // a live connection to a remote GDB server... if (QueryNoAckModeSupported()) { +#if 0 + // Set above line to "#if 1" to test packet speed if remote GDB server + // supports the qSpeedTest packet... + TestPacketSpeed(10000); +#endif return true; } else @@ -2420,50 +2425,81 @@ GDBRemoteCommunicationClient::TestPacketSpeed (const uint32_t num_packets) uint32_t i; TimeValue start_time, end_time; uint64_t total_time_nsec; - float packets_per_second; if (SendSpeedTestPacket (0, 0)) { - for (uint32_t send_size = 0; send_size <= 1024; send_size *= 2) + static uint32_t g_send_sizes[] = { 0, 64, 128, 512, 1024 }; + static uint32_t g_recv_sizes[] = { 0, 64, 128, 512, 1024 }; //, 4*1024, 8*1024, 16*1024, 32*1024, 48*1024, 64*1024, 96*1024, 128*1024 }; + const size_t k_num_send_sizes = sizeof(g_send_sizes)/sizeof(uint32_t); + const size_t k_num_recv_sizes = sizeof(g_recv_sizes)/sizeof(uint32_t); + const uint64_t k_recv_amount = 4*1024*1024; // Receive 4MB + for (uint32_t send_idx = 0; send_idx < k_num_send_sizes; ++send_idx) { - for (uint32_t recv_size = 0; recv_size <= 1024; recv_size *= 2) + const uint32_t send_size = g_send_sizes[send_idx]; + for (uint32_t recv_idx = 0; recv_idx < k_num_recv_sizes; ++recv_idx) { + const uint32_t recv_size = g_recv_sizes[recv_idx]; + StreamString packet; + packet.Printf ("qSpeedTest:response_size:%i;data:", recv_size); + uint32_t bytes_left = send_size; + while (bytes_left > 0) + { + if (bytes_left >= 26) + { + packet.PutCString("abcdefghijklmnopqrstuvwxyz"); + bytes_left -= 26; + } + else + { + packet.Printf ("%*.*s;", bytes_left, bytes_left, "abcdefghijklmnopqrstuvwxyz"); + bytes_left = 0; + } + } + start_time = TimeValue::Now(); - for (i=0; i<num_packets; ++i) + if (recv_size == 0) { - SendSpeedTestPacket (send_size, recv_size); + for (i=0; i<num_packets; ++i) + { + StringExtractorGDBRemote response; + SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false); + } + } + else + { + uint32_t bytes_read = 0; + while (bytes_read < k_recv_amount) + { + StringExtractorGDBRemote response; + SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false); + bytes_read += recv_size; + } } end_time = TimeValue::Now(); total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970(); - packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec; - printf ("%u qSpeedTest(send=%-5u, recv=%-5u) in %" PRIu64 ".%9.9" PRIu64 " sec for %f packets/sec.\n", - num_packets, - send_size, - recv_size, - total_time_nsec / TimeValue::NanoSecPerSec, - total_time_nsec % TimeValue::NanoSecPerSec, - packets_per_second); if (recv_size == 0) - recv_size = 32; + { + float packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec; + printf ("%u qSpeedTest(send=%-7u, recv=%-7u) in %" PRIu64 ".%9.9" PRIu64 " sec for %f packets/sec.\n", + num_packets, + send_size, + recv_size, + total_time_nsec / TimeValue::NanoSecPerSec, + total_time_nsec % TimeValue::NanoSecPerSec, + packets_per_second); + } + else + { + float mb_second = ((((float)k_recv_amount)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec) / (1024.0*1024.0); + printf ("%u qSpeedTest(send=%-7u, recv=%-7u) sent 4MB in %" PRIu64 ".%9.9" PRIu64 " sec for %f MB/sec.\n", + num_packets, + send_size, + recv_size, + total_time_nsec / TimeValue::NanoSecPerSec, + total_time_nsec % TimeValue::NanoSecPerSec, + mb_second); + } } - if (send_size == 0) - send_size = 32; - } - } - else - { - start_time = TimeValue::Now(); - for (i=0; i<num_packets; ++i) - { - GetCurrentProcessID (); } - end_time = TimeValue::Now(); - total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970(); - packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec; - printf ("%u 'qC' packets packets in 0x%" PRIu64 "%9.9" PRIu64 " sec for %f packets/sec.\n", - num_packets, - total_time_nsec / TimeValue::NanoSecPerSec, - total_time_nsec % TimeValue::NanoSecPerSec, - packets_per_second); } } @@ -2639,15 +2675,10 @@ GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtracto uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, bool insert, addr_t addr, uint32_t length) { - switch (type) - { - case eBreakpointSoftware: if (!m_supports_z0) return UINT8_MAX; break; - case eBreakpointHardware: if (!m_supports_z1) return UINT8_MAX; break; - case eWatchpointWrite: if (!m_supports_z2) return UINT8_MAX; break; - case eWatchpointRead: if (!m_supports_z3) return UINT8_MAX; break; - case eWatchpointReadWrite: if (!m_supports_z4) return UINT8_MAX; break; - } - + // Check if the stub is known not to support this breakpoint type + if (!SupportsGDBStoppointPacket(type)) + return UINT8_MAX; + // Construct the breakpoint packet char packet[64]; const int packet_len = ::snprintf (packet, sizeof(packet), @@ -2656,28 +2687,35 @@ GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, type, addr, length); - + // Check we havent overwritten the end of the packet buffer assert (packet_len + 1 < (int)sizeof(packet)); StringExtractorGDBRemote response; + // Try to send the breakpoint packet, and check that it was correctly sent if (SendPacketAndWaitForResponse(packet, packet_len, response, true) == PacketResult::Success) { + // Receive and OK packet when the breakpoint successfully placed if (response.IsOKResponse()) return 0; - else if (response.IsErrorResponse()) + + // Error while setting breakpoint, send back specific error + if (response.IsErrorResponse()) return response.GetError(); - } - else - { - switch (type) + + // Empty packet informs us that breakpoint is not supported + if (response.IsUnsupportedResponse()) { + // Disable this breakpoint type since it is unsupported + switch (type) + { case eBreakpointSoftware: m_supports_z0 = false; break; case eBreakpointHardware: m_supports_z1 = false; break; case eWatchpointWrite: m_supports_z2 = false; break; case eWatchpointRead: m_supports_z3 = false; break; case eWatchpointReadWrite: m_supports_z4 = false; break; + } } } - + // Signal generic faliure return UINT8_MAX; } diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index e1989eb1dd14..1172222d62a4 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1645,6 +1645,21 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) } } + // If the response is old style 'S' packet which does not provide us with thread information + // then update the thread list and choose the first one. + if (!thread_sp) + { + UpdateThreadIDList (); + + if (!m_thread_ids.empty ()) + { + Mutex::Locker locker (m_thread_list_real.GetMutex ()); + thread_sp = m_thread_list_real.FindThreadByProtocolID (m_thread_ids.front (), false); + if (thread_sp) + gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get ()); + } + } + if (thread_sp) { // Clear the stop info just in case we don't set it to anything @@ -1720,7 +1735,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) } } - if (signo && did_exec == false) + if (!handled && signo && did_exec == false) { if (signo == SIGTRAP) { @@ -2007,6 +2022,24 @@ ProcessGDBRemote::DoDestroy () if (packet_cmd == 'W' || packet_cmd == 'X') { +#if defined(__APPLE__) + // For Native processes on Mac OS X, we launch through the Host Platform, then hand the process off + // to debugserver, which becomes the parent process through "PT_ATTACH". Then when we go to kill + // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then we call waitpid which returns + // with no error and the correct status. But amusingly enough that doesn't seem to actually reap + // the process, but instead it is left around as a Zombie. Probably the kernel is in the process of + // switching ownership back to lldb which was the original parent, and gets confused in the handoff. + // Anyway, so call waitpid here to finally reap it. + PlatformSP platform_sp(GetTarget().GetPlatform()); + if (platform_sp && platform_sp->IsHost()) + { + int status; + ::pid_t reap_pid; + reap_pid = waitpid (GetID(), &status, WNOHANG); + if (log) + log->Printf ("Reaped pid: %d, status: %d.\n", reap_pid, status); + } +#endif SetLastStopPacket (response); ClearThreadIDList (); exit_status = response.GetHexU8(); @@ -2277,70 +2310,106 @@ Error ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site) { Error error; - assert (bp_site != NULL); + assert(bp_site != NULL); - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS)); + // Get logging info + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS)); user_id_t site_id = bp_site->GetID(); + + // Get the breakpoint address const addr_t addr = bp_site->GetLoadAddress(); + + // Log that a breakpoint was requested if (log) - log->Printf ("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64, site_id, (uint64_t)addr); + log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64, site_id, (uint64_t)addr); + // Breakpoint already exists and is enabled if (bp_site->IsEnabled()) { if (log) - log->Printf ("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", site_id, (uint64_t)addr); + log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", site_id, (uint64_t)addr); return error; } - else + + // Get the software breakpoint trap opcode size + const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site); + + // SupportsGDBStoppointPacket() simply checks a boolean, indicating if this breakpoint type + // is supported by the remote stub. These are set to true by default, and later set to false + // only after we receive an unimplemented response when sending a breakpoint packet. This means + // initially that unless we were specifically instructed to use a hardware breakpoint, LLDB will + // attempt to set a software breakpoint. HardwareRequired() also queries a boolean variable which + // indicates if the user specifically asked for hardware breakpoints. If true then we will + // skip over software breakpoints. + if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) && (!bp_site->HardwareRequired())) { - const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site); + // Try to send off a software breakpoint packet ($Z0) + if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0) + { + // The breakpoint was placed successfully + bp_site->SetEnabled(true); + bp_site->SetType(BreakpointSite::eExternal); + return error; + } + + // SendGDBStoppointTypePacket() will return an error if it was unable to set this + // breakpoint. We need to differentiate between a error specific to placing this breakpoint + // or if we have learned that this breakpoint type is unsupported. To do this, we + // must test the support boolean for this breakpoint type to see if it now indicates that + // this breakpoint type is unsupported. If they are still supported then we should return + // with the error code. If they are now unsupported, then we would like to fall through + // and try another form of breakpoint. + if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) + return error; - if (bp_site->HardwareRequired()) + // We reach here when software breakpoints have been found to be unsupported. For future + // calls to set a breakpoint, we will not attempt to set a breakpoint with a type that is + // known not to be supported. + if (log) + log->Printf("Software breakpoints are unsupported"); + + // So we will fall through and try a hardware breakpoint + } + + // The process of setting a hardware breakpoint is much the same as above. We check the + // supported boolean for this breakpoint type, and if it is thought to be supported then we + // will try to set this breakpoint with a hardware breakpoint. + if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) + { + // Try to send off a hardware breakpoint packet ($Z1) + if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size) == 0) { - // Try and set hardware breakpoint, and if that fails, fall through - // and set a software breakpoint? - if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointHardware)) - { - if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size) == 0) - { - bp_site->SetEnabled(true); - bp_site->SetType (BreakpointSite::eHardware); - } - else - { - error.SetErrorString("failed to set hardware breakpoint (hardware breakpoint resources might be exhausted or unavailable)"); - } - } - else - { - error.SetErrorString("hardware breakpoints are not supported"); - } + // The breakpoint was placed successfully + bp_site->SetEnabled(true); + bp_site->SetType(BreakpointSite::eHardware); return error; } - else if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware)) + + // Check if the error was something other then an unsupported breakpoint type + if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { - if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0) - { - bp_site->SetEnabled(true); - bp_site->SetType (BreakpointSite::eExternal); - return error; - } + // Unable to set this hardware breakpoint + error.SetErrorString("failed to set hardware breakpoint (hardware breakpoint resources might be exhausted or unavailable)"); + return error; } - return EnableSoftwareBreakpoint (bp_site); + // We will reach here when the stub gives an unsported response to a hardware breakpoint + if (log) + log->Printf("Hardware breakpoints are unsupported"); + + // Finally we will falling through to a #trap style breakpoint } - if (log) + // Don't fall through when hardware breakpoints were specifically requested + if (bp_site->HardwareRequired()) { - const char *err_string = error.AsCString(); - log->Printf ("ProcessGDBRemote::EnableBreakpointSite () error for breakpoint at 0x%8.8" PRIx64 ": %s", - bp_site->GetLoadAddress(), - err_string ? err_string : "NULL"); + error.SetErrorString("hardware breakpoints are not supported"); + return error; } - // We shouldn't reach here on a successful breakpoint enable... - if (error.Success()) - error.SetErrorToGenericError(); - return error; + + // As a last resort we want to place a manual breakpoint. An instruction + // is placed into the process memory using memory write packets. + return EnableSoftwareBreakpoint(bp_site); } Error @@ -2366,7 +2435,7 @@ ProcessGDBRemote::DisableBreakpointSite (BreakpointSite *bp_site) break; case BreakpointSite::eHardware: - if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size)) + if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false, addr, bp_op_size)) error.SetErrorToGenericError(); break; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index ef03cac540c6..c1aecfe8eb62 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -4199,6 +4199,7 @@ SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc, const DWARFDebugInfoEntry *parent_die, bool skip_artificial, bool &is_static, + bool &is_variadic, TypeList* type_list, std::vector<ClangASTType>& function_param_types, std::vector<clang::ParmVarDecl*>& function_param_decls, @@ -4350,6 +4351,10 @@ SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc, } break; + case DW_TAG_unspecified_parameters: + is_variadic = true; + break; + case DW_TAG_template_type_parameter: case DW_TAG_template_value_parameter: ParseTemplateDIE (dwarf_cu, die,template_param_infos); @@ -6589,6 +6594,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, die, skip_artificial, is_static, + is_variadic, type_list, function_param_types, function_param_decls, diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 55886572ada3..8dac209361ed 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -364,6 +364,7 @@ protected: const DWARFDebugInfoEntry *parent_die, bool skip_artificial, bool &is_static, + bool &is_variadic, lldb_private::TypeList* type_list, std::vector<lldb_private::ClangASTType>& function_args, std::vector<clang::ParmVarDecl*>& function_param_decls, diff --git a/source/Symbol/VariableList.cpp b/source/Symbol/VariableList.cpp index 3451166e52d4..75eb8700c9ff 100644 --- a/source/Symbol/VariableList.cpp +++ b/source/Symbol/VariableList.cpp @@ -115,6 +115,32 @@ VariableList::FindVariable(const ConstString& name) return var_sp; } +VariableSP +VariableList::FindVariable (const ConstString& name, lldb::ValueType value_type) +{ + VariableSP var_sp; + iterator pos, end = m_variables.end(); + for (pos = m_variables.begin(); pos != end; ++pos) + { + if ((*pos)->NameMatches(name) && (*pos)->GetScope() == value_type) + { + var_sp = (*pos); + break; + } + } + return var_sp; +} + +size_t +VariableList::AppendVariablesIfUnique(VariableList &var_list) +{ + const size_t initial_size = var_list.GetSize(); + iterator pos, end = m_variables.end(); + for (pos = m_variables.begin(); pos != end; ++pos) + var_list.AddVariableIfUnique(*pos); + return var_list.GetSize() - initial_size; +} + size_t VariableList::AppendVariablesIfUnique (const RegularExpression& regex, VariableList &var_list, size_t& total_matches) { diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp index 40d3e4950c6d..1256ad34c975 100644 --- a/source/Target/Process.cpp +++ b/source/Target/Process.cpp @@ -4824,13 +4824,21 @@ public: { } + virtual void - Interrupt () + Cancel () { size_t n = 1; char ch = 'q'; m_pipe_write.Write (&ch, n); } + + virtual void + Interrupt () + { + if (StateIsRunningState(m_process->GetState())) + m_process->SendAsyncInterrupt(); + } virtual void GotEOF() @@ -4859,7 +4867,7 @@ Process::CancelWatchForSTDIN (bool exited) { if (exited) m_process_input_reader->SetIsDone(true); - m_process_input_reader->Interrupt(); + m_process_input_reader->Cancel(); } } @@ -4903,7 +4911,7 @@ Process::PopProcessIOHandler () IOHandlerSP io_handler_sp (m_process_input_reader); if (io_handler_sp) { - io_handler_sp->Interrupt(); + io_handler_sp->Cancel(); m_target.GetDebugger().PopIOHandler (io_handler_sp); } } diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp index 72de5b8a3cf5..39f269952882 100644 --- a/source/Target/Thread.cpp +++ b/source/Target/Thread.cpp @@ -2023,6 +2023,7 @@ Thread::GetUnwinder () case llvm::Triple::arm: case llvm::Triple::thumb: case llvm::Triple::mips64: + case llvm::Triple::hexagon: m_unwinder_ap.reset (new UnwindLLDB (*this)); break; |