aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins')
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp22
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h37
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h16
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp6
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp3
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp2
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp111
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.h17
-rw-r--r--source/Plugins/Process/POSIX/POSIXThread.cpp26
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp14
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp15
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIX.h4
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp16
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.cpp115
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.h20
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.cpp36
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp7
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp134
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp157
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp6
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h1
21 files changed, 567 insertions, 198 deletions
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)&regs, 0)) < 0) {
+ m_result = false;
+ } else {
+ if (m_size == sizeof(uintptr_t))
+ m_value = *(uintptr_t *)(((caddr_t)&regs) + m_offset);
+ else
+ memcpy(&m_value, (((caddr_t)&regs) + 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)&regs, 0) < 0) {
+ m_result = false;
+ return;
+ }
+ *(uintptr_t *)(((caddr_t)&regs) + m_offset) = (uintptr_t)m_value.GetAsUInt64();
+ if (PTRACE(PT_SETDBREGS, m_tid, (caddr_t)&regs, 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,