Import LLDB as of SVN r202189 (git 32871eb)
(A number of files not required for the FreeBSD build have been removed.) Sponsored by: DARPA, AFRL
This commit is contained in:
parent
866dcdacfe
commit
03b9909782
@ -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
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
|
||||
@ -394,6 +404,9 @@ namespace lldb_private {
|
||||
virtual void
|
||||
Refresh ();
|
||||
|
||||
virtual void
|
||||
Cancel ();
|
||||
|
||||
virtual void
|
||||
Interrupt ();
|
||||
|
||||
@ -500,7 +513,10 @@ namespace lldb_private {
|
||||
|
||||
virtual void
|
||||
Refresh ();
|
||||
|
||||
|
||||
virtual void
|
||||
Cancel ();
|
||||
|
||||
virtual void
|
||||
Interrupt ();
|
||||
|
||||
|
@ -17,4 +17,4 @@
|
||||
|
||||
#include <lldb/Host/windows/GetOptInc.h>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -98,6 +98,9 @@ namespace lldb_private {
|
||||
return m_py_obj != NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
IsNULLOrNone () const;
|
||||
|
||||
protected:
|
||||
PyObject* m_py_obj;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -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))
|
||||
{
|
||||
ConstString const_name(name);
|
||||
const uint32_t num_variables = variable_list->GetSize();
|
||||
for (uint32_t i = 0; i < num_variables; ++i)
|
||||
if (value_type == eValueTypeVariableGlobal)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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);
|
||||
VariableSP variable_sp(variable_list.FindVariable(const_name,value_type));
|
||||
if (variable_sp)
|
||||
{
|
||||
value_sp = frame->GetValueObjectForFrameVariable (variable_sp, eNoDynamicValues);
|
||||
sb_value.SetSP (value_sp, use_dynamic);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -846,7 +846,7 @@ Debugger::ClearIOHandlers ()
|
||||
{
|
||||
m_input_reader_stack.Pop();
|
||||
reader_sp->SetIsDone(true);
|
||||
reader_sp->Interrupt();
|
||||
reader_sp->Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -587,6 +587,13 @@ IOHandlerEditline::Refresh ()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IOHandlerEditline::Cancel ()
|
||||
{
|
||||
if (m_editline_ap)
|
||||
m_editline_ap->Interrupt ();
|
||||
}
|
||||
|
||||
void
|
||||
IOHandlerEditline::Interrupt ()
|
||||
{
|
||||
@ -5279,6 +5286,10 @@ IOHandlerCursesGUI::Refresh ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
IOHandlerCursesGUI::Cancel ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
IOHandlerCursesGUI::Interrupt ()
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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__)
|
||||
|
||||
// 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
|
||||
|
||||
// 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)
|
||||
{
|
||||
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
|
||||
|
@ -84,6 +84,12 @@ PythonObject::Str ()
|
||||
return PythonString(str);
|
||||
}
|
||||
|
||||
bool
|
||||
PythonObject::IsNULLOrNone () const
|
||||
{
|
||||
return ((m_py_obj == nullptr) || (m_py_obj == Py_None));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// PythonString
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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.
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -132,6 +132,8 @@ ProcessFreeBSD::DoDetach(bool keep_stopped)
|
||||
return error;
|
||||
}
|
||||
|
||||
DisableAllBreakpointSites();
|
||||
|
||||
error = m_monitor->Detach(GetID());
|
||||
|
||||
if (error.Success())
|
||||
|
@ -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;
|
||||
}
|
||||
@ -347,6 +354,82 @@ WriteRegOperation::Execute(ProcessMonitor *monitor)
|
||||
m_result = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// @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.
|
||||
@ -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;
|
||||
|
||||
@ -1463,6 +1546,28 @@ ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset,
|
||||
return result;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
UnwindPlan::RowSP active_row = arch_default_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
|
||||
|
||||
if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM)
|
||||
{
|
||||
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 ();
|
||||
}
|
||||
if (m_fallback_unwind_plan_sp.get() == NULL)
|
||||
return false;
|
||||
|
||||
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());
|
||||
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)
|
||||
{
|
||||
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 = 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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
|
@ -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,51 +2425,82 @@ 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)
|
||||
{
|
||||
start_time = TimeValue::Now();
|
||||
for (i=0; i<num_packets; ++i)
|
||||
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)
|
||||
{
|
||||
SendSpeedTestPacket (send_size, recv_size);
|
||||
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();
|
||||
if (recv_size == 0)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
const addr_t addr = bp_site->GetLoadAddress();
|
||||
if (log)
|
||||
log->Printf ("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64, site_id, (uint64_t)addr);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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
|
||||
{
|
||||
const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
|
||||
|
||||
if (bp_site->HardwareRequired())
|
||||
// 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()))
|
||||
{
|
||||
// Try to send off a software breakpoint packet ($Z0)
|
||||
if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, 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::eExternal);
|
||||
return error;
|
||||
}
|
||||
else if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware))
|
||||
|
||||
// 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;
|
||||
|
||||
// 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)
|
||||
{
|
||||
if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0)
|
||||
{
|
||||
bp_site->SetEnabled(true);
|
||||
bp_site->SetType (BreakpointSite::eExternal);
|
||||
return error;
|
||||
}
|
||||
// The breakpoint was placed successfully
|
||||
bp_site->SetEnabled(true);
|
||||
bp_site->SetType(BreakpointSite::eHardware);
|
||||
return error;
|
||||
}
|
||||
|
||||
return EnableSoftwareBreakpoint (bp_site);
|
||||
// Check if the error was something other then an unsupported breakpoint type
|
||||
if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware))
|
||||
{
|
||||
// Unable to set this hardware breakpoint
|
||||
error.SetErrorString("failed to set hardware breakpoint (hardware breakpoint resources might be exhausted or unavailable)");
|
||||
return error;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user