aboutsummaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-09-06 14:32:30 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-09-06 14:32:30 +0000
commit027f1c9655391dcb2b0117f931f720211ac933db (patch)
tree94980f450aa3daec3e1fec217374704ad62cfe45 /source
parent5e95aa85bb660d45e9905ef1d7180b2678280660 (diff)
downloadsrc-027f1c9655391dcb2b0117f931f720211ac933db.tar.gz
src-027f1c9655391dcb2b0117f931f720211ac933db.zip
Vendor import of (stripped) lldb trunk r242221:vendor/lldb/lldb-trunk-r242221
Notes
Notes: svn path=/vendor/lldb/dist/; revision=287503 svn path=/vendor/lldb/lldb-trunk-r242221/; revision=287504; tag=vendor/lldb/lldb-trunk-r242221
Diffstat (limited to 'source')
-rw-r--r--source/API/SBBlock.cpp10
-rw-r--r--source/API/SBFrame.cpp58
-rw-r--r--source/API/SBFunction.cpp22
-rw-r--r--source/API/SBPlatform.cpp9
-rw-r--r--source/API/SBProcess.cpp10
-rw-r--r--source/API/SBSymbol.cpp16
-rw-r--r--source/API/SBTarget.cpp13
-rw-r--r--source/API/SBThread.cpp2
-rw-r--r--source/API/SBUnixSignals.cpp105
-rw-r--r--source/API/SystemInitializerFull.cpp5
-rw-r--r--source/Breakpoint/BreakpointLocation.cpp4
-rw-r--r--source/Commands/CommandObjectBreakpoint.cpp34
-rw-r--r--source/Commands/CommandObjectBreakpointCommand.cpp251
-rw-r--r--source/Commands/CommandObjectCommands.cpp171
-rw-r--r--source/Commands/CommandObjectExpression.cpp62
-rw-r--r--source/Commands/CommandObjectPlatform.cpp20
-rw-r--r--source/Commands/CommandObjectProcess.cpp47
-rw-r--r--source/Commands/CommandObjectSettings.cpp37
-rw-r--r--source/Commands/CommandObjectType.cpp257
-rw-r--r--source/Commands/CommandObjectWatchpoint.cpp23
-rw-r--r--source/Commands/CommandObjectWatchpointCommand.cpp221
-rw-r--r--source/Core/ArchSpec.cpp113
-rw-r--r--source/Core/DataExtractor.cpp24
-rw-r--r--source/Core/FormatEntity.cpp8
-rw-r--r--source/Core/Mangled.cpp44
-rw-r--r--source/Core/StructuredData.cpp343
-rw-r--r--source/DataFormatters/FormatManager.cpp20
-rw-r--r--source/DataFormatters/VectorType.cpp48
-rw-r--r--source/Expression/ClangExpressionDeclMap.cpp25
-rw-r--r--source/Expression/ClangExpressionParser.cpp5
-rw-r--r--source/Expression/ClangModulesDeclVendor.cpp43
-rw-r--r--source/Expression/ClangUserExpression.cpp3
-rw-r--r--source/Expression/IRExecutionUnit.cpp2
-rw-r--r--source/Expression/IRForTarget.cpp4
-rw-r--r--source/Expression/IRInterpreter.cpp277
-rw-r--r--source/Expression/IRMemoryMap.cpp26
-rw-r--r--source/Host/common/Host.cpp10
-rw-r--r--source/Host/common/NativeProcessProtocol.cpp22
-rw-r--r--source/Host/common/StringConvert.cpp142
-rw-r--r--source/Host/freebsd/Host.cpp9
-rw-r--r--source/Host/posix/MainLoopPosix.cpp193
-rw-r--r--source/Initialization/SystemInitializerCommon.cpp3
-rw-r--r--source/Interpreter/CommandObject.cpp26
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp3
-rw-r--r--source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp2
-rw-r--r--source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp5
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp6
-rw-r--r--source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp102
-rw-r--r--source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h43
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp2
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp23
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.cpp11
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.h3
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp103
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h6
-rw-r--r--source/Plugins/Process/FreeBSD/FreeBSDThread.cpp2
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp6
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessPOSIX.h2
-rw-r--r--source/Plugins/Process/Utility/FreeBSDSignals.cpp2
-rw-r--r--source/Plugins/Process/Utility/FreeBSDSignals.h9
-rw-r--r--source/Plugins/Process/Utility/GDBRemoteSignals.cpp32
-rw-r--r--source/Plugins/Process/Utility/GDBRemoteSignals.h36
-rw-r--r--source/Plugins/Process/Utility/LinuxSignals.cpp2
-rw-r--r--source/Plugins/Process/Utility/LinuxSignals.h23
-rw-r--r--source/Plugins/Process/Utility/MipsLinuxSignals.cpp2
-rw-r--r--source/Plugins/Process/Utility/MipsLinuxSignals.h23
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.cpp176
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.h12
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.cpp22
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp6
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp23
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h4
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp64
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h14
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp33
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h3
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp252
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h5
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp4
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp16
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp49
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp4
-rw-r--r--source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp2
-rw-r--r--source/Symbol/ClangASTContext.cpp1
-rw-r--r--source/Symbol/ClangASTImporter.cpp143
-rw-r--r--source/Symbol/ClangASTType.cpp4
-rw-r--r--source/Symbol/Function.cpp54
-rw-r--r--source/Symbol/Symbol.cpp34
-rw-r--r--source/Symbol/SymbolContext.cpp36
-rw-r--r--source/Symbol/Symtab.cpp12
-rw-r--r--source/Symbol/Variable.cpp33
-rw-r--r--source/Target/Platform.cpp37
-rw-r--r--source/Target/Process.cpp35
-rw-r--r--source/Target/ProcessLaunchInfo.cpp7
-rw-r--r--source/Target/StopInfo.cpp12
-rw-r--r--source/Target/ThreadPlanCallFunction.cpp52
-rw-r--r--source/Target/ThreadPlanCallFunctionUsingABI.cpp91
-rw-r--r--source/Target/ThreadPlanStepOverRange.cpp2
-rw-r--r--source/Target/UnixSignals.cpp64
-rw-r--r--source/Utility/JSON.cpp470
-rw-r--r--source/Utility/StringExtractor.cpp11
-rw-r--r--source/Utility/StringExtractor.h164
-rw-r--r--source/Utility/StringExtractorGDBRemote.cpp8
-rw-r--r--source/Utility/StringExtractorGDBRemote.h4
106 files changed, 3557 insertions, 1625 deletions
diff --git a/source/API/SBBlock.cpp b/source/API/SBBlock.cpp
index c8a665f7d6fb..fdbbbc045279 100644
--- a/source/API/SBBlock.cpp
+++ b/source/API/SBBlock.cpp
@@ -75,7 +75,15 @@ SBBlock::GetInlinedName () const
{
const InlineFunctionInfo* inlined_info = m_opaque_ptr->GetInlinedFunctionInfo ();
if (inlined_info)
- return inlined_info->GetName().AsCString (NULL);
+ {
+ Function *function = m_opaque_ptr->CalculateSymbolContextFunction();
+ LanguageType language;
+ if (function)
+ language = function->GetLanguage();
+ else
+ language = lldb::eLanguageTypeUnknown;
+ return inlined_info->GetName(language).AsCString (NULL);
+ }
}
return NULL;
}
diff --git a/source/API/SBFrame.cpp b/source/API/SBFrame.cpp
index e845aef41f45..08a5822cb781 100644
--- a/source/API/SBFrame.cpp
+++ b/source/API/SBFrame.cpp
@@ -1571,7 +1571,7 @@ SBFrame::GetFunctionName() const
if (inlined_block)
{
const InlineFunctionInfo* inlined_info = inlined_block->GetInlinedFunctionInfo();
- name = inlined_info->GetName().AsCString();
+ name = inlined_info->GetName(sc.function->GetLanguage()).AsCString();
}
}
@@ -1602,3 +1602,59 @@ SBFrame::GetFunctionName() const
}
return name;
}
+
+const char *
+SBFrame::GetDisplayFunctionName()
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ const char *name = NULL;
+ ExecutionContext exe_ctx(m_opaque_sp.get());
+ StackFrame *frame = NULL;
+ Target *target = exe_ctx.GetTargetPtr();
+ Process *process = exe_ctx.GetProcessPtr();
+ if (target && process)
+ {
+ Process::StopLocker stop_locker;
+ if (stop_locker.TryLock(&process->GetRunLock()))
+ {
+ frame = exe_ctx.GetFramePtr();
+ if (frame)
+ {
+ SymbolContext sc (frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol));
+ if (sc.block)
+ {
+ Block *inlined_block = sc.block->GetContainingInlinedBlock ();
+ if (inlined_block)
+ {
+ const InlineFunctionInfo* inlined_info = inlined_block->GetInlinedFunctionInfo();
+ name = inlined_info->GetDisplayName(sc.function->GetLanguage()).AsCString();
+ }
+ }
+
+ if (name == NULL)
+ {
+ if (sc.function)
+ name = sc.function->GetDisplayName().GetCString();
+ }
+
+ if (name == NULL)
+ {
+ if (sc.symbol)
+ name = sc.symbol->GetDisplayName().GetCString();
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("SBFrame::GetDisplayFunctionName () => error: could not reconstruct frame object for this SBFrame.");
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("SBFrame::GetDisplayFunctionName() => error: process is running");
+
+ }
+ }
+ return name;
+}
diff --git a/source/API/SBFunction.cpp b/source/API/SBFunction.cpp
index bf5e9180a437..2ec6072b51eb 100644
--- a/source/API/SBFunction.cpp
+++ b/source/API/SBFunction.cpp
@@ -60,7 +60,7 @@ SBFunction::GetName() const
{
const char *cstr = NULL;
if (m_opaque_ptr)
- cstr = m_opaque_ptr->GetMangled().GetName().AsCString();
+ cstr = m_opaque_ptr->GetName().AsCString();
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
@@ -76,6 +76,26 @@ SBFunction::GetName() const
}
const char *
+SBFunction::GetDisplayName() const
+{
+ const char *cstr = NULL;
+ if (m_opaque_ptr)
+ cstr = m_opaque_ptr->GetMangled().GetDisplayDemangledName(m_opaque_ptr->GetLanguage()).AsCString();
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ {
+ if (cstr)
+ log->Printf ("SBFunction(%p)::GetDisplayName () => \"%s\"",
+ static_cast<void*>(m_opaque_ptr), cstr);
+ else
+ log->Printf ("SBFunction(%p)::GetDisplayName () => NULL",
+ static_cast<void*>(m_opaque_ptr));
+ }
+ return cstr;
+}
+
+const char *
SBFunction::GetMangledName () const
{
const char *cstr = NULL;
diff --git a/source/API/SBPlatform.cpp b/source/API/SBPlatform.cpp
index 5662f36b514d..97ffcf149750 100644
--- a/source/API/SBPlatform.cpp
+++ b/source/API/SBPlatform.cpp
@@ -11,6 +11,7 @@
#include "lldb/API/SBError.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBLaunchInfo.h"
+#include "lldb/API/SBUnixSignals.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Error.h"
#include "lldb/Host/File.h"
@@ -638,3 +639,11 @@ SBPlatform::SetFilePermissions (const char *path, uint32_t file_permissions)
}
+SBUnixSignals
+SBPlatform::GetUnixSignals() const
+{
+ if (auto platform_sp = GetSP())
+ return SBUnixSignals{platform_sp};
+
+ return {};
+}
diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp
index a1dbf686da03..01bfaf9aff01 100644
--- a/source/API/SBProcess.cpp
+++ b/source/API/SBProcess.cpp
@@ -912,14 +912,10 @@ SBProcess::Signal (int signo)
SBUnixSignals
SBProcess::GetUnixSignals()
{
- SBUnixSignals sb_unix_signals;
- ProcessSP process_sp(GetSP());
- if (process_sp)
- {
- sb_unix_signals.SetSP(process_sp);
- }
+ if (auto process_sp = GetSP())
+ return SBUnixSignals{process_sp};
- return sb_unix_signals;
+ return {};
}
void
diff --git a/source/API/SBSymbol.cpp b/source/API/SBSymbol.cpp
index 246a455d93a7..22d1e546b5ee 100644
--- a/source/API/SBSymbol.cpp
+++ b/source/API/SBSymbol.cpp
@@ -63,7 +63,7 @@ SBSymbol::GetName() const
{
const char *name = NULL;
if (m_opaque_ptr)
- name = m_opaque_ptr->GetMangled().GetName().AsCString();
+ name = m_opaque_ptr->GetName().AsCString();
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
@@ -73,6 +73,20 @@ SBSymbol::GetName() const
}
const char *
+SBSymbol::GetDisplayName() const
+{
+ const char *name = NULL;
+ if (m_opaque_ptr)
+ name = m_opaque_ptr->GetMangled().GetDisplayDemangledName(m_opaque_ptr->GetLanguage()).AsCString();
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ log->Printf ("SBSymbol(%p)::GetDisplayName () => \"%s\"",
+ static_cast<void*>(m_opaque_ptr), name ? name : "");
+ return name;
+}
+
+const char *
SBSymbol::GetMangledName () const
{
const char *name = NULL;
diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp
index 923885223a5f..6597d4e77c73 100644
--- a/source/API/SBTarget.cpp
+++ b/source/API/SBTarget.cpp
@@ -2293,6 +2293,19 @@ SBTarget::FindSymbols (const char *name, lldb::SymbolType symbol_type)
}
+lldb::SBValue
+SBTarget::EvaluateExpression (const char *expr)
+{
+ TargetSP target_sp(GetSP());
+ if (!target_sp)
+ return SBValue();
+
+ SBExpressionOptions options;
+ lldb::DynamicValueType fetch_dynamic_value = target_sp->GetPreferDynamicValue();
+ options.SetFetchDynamicValue (fetch_dynamic_value);
+ options.SetUnwindOnError (true);
+ return EvaluateExpression(expr, options);
+}
lldb::SBValue
SBTarget::EvaluateExpression (const char *expr, const SBExpressionOptions &options)
diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp
index dfc7ce9629f3..42b5c9affe50 100644
--- a/source/API/SBThread.cpp
+++ b/source/API/SBThread.cpp
@@ -392,7 +392,7 @@ SBThread::GetStopDescription (char *dst, size_t dst_len)
case eStopReasonSignal:
{
- stop_desc = exe_ctx.GetProcessPtr()->GetUnixSignals ().GetSignalAsCString (stop_info_sp->GetValue());
+ stop_desc = exe_ctx.GetProcessPtr()->GetUnixSignals()->GetSignalAsCString(stop_info_sp->GetValue());
if (stop_desc == NULL || stop_desc[0] == '\0')
{
static char signal_desc[] = "signal";
diff --git a/source/API/SBUnixSignals.cpp b/source/API/SBUnixSignals.cpp
index ca321d82fd60..531c9782973d 100644
--- a/source/API/SBUnixSignals.cpp
+++ b/source/API/SBUnixSignals.cpp
@@ -9,6 +9,7 @@
#include "lldb/lldb-defines.h"
#include "lldb/Target/Process.h"
+#include "lldb/Target/Platform.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Core/Log.h"
@@ -25,8 +26,13 @@ SBUnixSignals::SBUnixSignals (const SBUnixSignals &rhs) :
{
}
-SBUnixSignals::SBUnixSignals (ProcessSP &process_sp) :
- m_opaque_wp(process_sp)
+SBUnixSignals::SBUnixSignals(ProcessSP &process_sp) :
+ m_opaque_wp(process_sp ? process_sp->GetUnixSignals() : nullptr)
+{
+}
+
+SBUnixSignals::SBUnixSignals(PlatformSP &platform_sp) :
+ m_opaque_wp(platform_sp ? platform_sp->GetUnixSignals() : nullptr)
{
}
@@ -42,16 +48,16 @@ SBUnixSignals::~SBUnixSignals()
{
}
-ProcessSP
+UnixSignalsSP
SBUnixSignals::GetSP() const
{
return m_opaque_wp.lock();
}
void
-SBUnixSignals::SetSP (const ProcessSP &process_sp)
+SBUnixSignals::SetSP(const UnixSignalsSP &signals_sp)
{
- m_opaque_wp = process_sp;
+ m_opaque_wp = signals_sp;
}
void
@@ -63,30 +69,33 @@ SBUnixSignals::Clear ()
bool
SBUnixSignals::IsValid() const
{
- return (bool) GetSP();
+ return static_cast<bool>(GetSP());
}
const char *
SBUnixSignals::GetSignalAsCString (int32_t signo) const
{
- ProcessSP process_sp(GetSP());
- if (process_sp) return process_sp->GetUnixSignals().GetSignalAsCString(signo);
- return NULL;
+ if (auto signals_sp = GetSP())
+ return signals_sp->GetSignalAsCString(signo);
+
+ return nullptr;
}
int32_t
SBUnixSignals::GetSignalNumberFromName (const char *name) const
{
- ProcessSP process_sp(GetSP());
- if (process_sp) return process_sp->GetUnixSignals().GetSignalNumberFromName(name);
- return -1;
+ if (auto signals_sp = GetSP())
+ return signals_sp->GetSignalNumberFromName(name);
+
+ return LLDB_INVALID_SIGNAL_NUMBER;
}
bool
SBUnixSignals::GetShouldSuppress (int32_t signo) const
{
- ProcessSP process_sp(GetSP());
- if (process_sp) return process_sp->GetUnixSignals().GetShouldSuppress(signo);
+ if (auto signals_sp = GetSP())
+ return signals_sp->GetShouldSuppress(signo);
+
return false;
}
@@ -94,25 +103,28 @@ bool
SBUnixSignals::SetShouldSuppress (int32_t signo, bool value)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
- ProcessSP process_sp(GetSP());
+ auto signals_sp = GetSP();
if (log)
{
log->Printf ("SBUnixSignals(%p)::SetShouldSuppress (signo=%d, value=%d)",
- static_cast<void*>(process_sp.get()),
+ static_cast<void*>(signals_sp.get()),
signo,
value);
}
- if (process_sp) return process_sp->GetUnixSignals().SetShouldSuppress(signo, value);
+ if (signals_sp)
+ return signals_sp->SetShouldSuppress(signo, value);
+
return false;
}
bool
SBUnixSignals::GetShouldStop (int32_t signo) const
{
- ProcessSP process_sp(GetSP());
- if (process_sp) return process_sp->GetUnixSignals().GetShouldStop(signo);
+ if (auto signals_sp = GetSP())
+ return signals_sp->GetShouldStop(signo);
+
return false;
}
@@ -120,25 +132,28 @@ bool
SBUnixSignals::SetShouldStop (int32_t signo, bool value)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
- ProcessSP process_sp(GetSP());
+ auto signals_sp = GetSP();
if (log)
{
log->Printf ("SBUnixSignals(%p)::SetShouldStop (signo=%d, value=%d)",
- static_cast<void*>(process_sp.get()),
+ static_cast<void*>(signals_sp.get()),
signo,
value);
}
- if (process_sp) return process_sp->GetUnixSignals().SetShouldStop(signo, value);
+ if (signals_sp)
+ return signals_sp->SetShouldStop(signo, value);
+
return false;
}
bool
SBUnixSignals::GetShouldNotify (int32_t signo) const
{
- ProcessSP process_sp(GetSP());
- if (process_sp) return process_sp->GetUnixSignals().GetShouldNotify(signo);
+ if (auto signals_sp = GetSP())
+ return signals_sp->GetShouldNotify(signo);
+
return false;
}
@@ -146,54 +161,36 @@ bool
SBUnixSignals::SetShouldNotify (int32_t signo, bool value)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
- ProcessSP process_sp(GetSP());
+ auto signals_sp = GetSP();
if (log)
{
log->Printf ("SBUnixSignals(%p)::SetShouldNotify (signo=%d, value=%d)",
- static_cast<void*>(process_sp.get()),
+ static_cast<void*>(signals_sp.get()),
signo,
value);
}
- if (process_sp) return process_sp->GetUnixSignals().SetShouldNotify(signo, value);
+ if (signals_sp)
+ return signals_sp->SetShouldNotify(signo, value);
+
return false;
}
int32_t
SBUnixSignals::GetNumSignals () const
{
- if (auto process_sp = GetSP())
- {
- // only valid while we hold process_sp
- UnixSignals *unix_signals_ptr = &process_sp->GetUnixSignals();
- int32_t num_signals = 0;
- for (int32_t signo = unix_signals_ptr->GetFirstSignalNumber();
- signo != LLDB_INVALID_SIGNAL_NUMBER;
- signo = unix_signals_ptr->GetNextSignalNumber(signo))
- {
- num_signals++;
- }
- return num_signals;
- }
- return LLDB_INVALID_SIGNAL_NUMBER;
+ if (auto signals_sp = GetSP())
+ return signals_sp->GetNumSignals();
+
+ return -1;
}
int32_t
SBUnixSignals::GetSignalAtIndex (int32_t index) const
{
- if (auto process_sp = GetSP())
- {
- // only valid while we hold process_sp
- UnixSignals *unix_signals_ptr = &process_sp->GetUnixSignals();
- int32_t idx = 0;
- for (int32_t signo = unix_signals_ptr->GetFirstSignalNumber();
- signo != LLDB_INVALID_SIGNAL_NUMBER;
- signo = unix_signals_ptr->GetNextSignalNumber(signo))
- {
- if (index == idx) return signo;
- idx++;
- }
- }
+ if (auto signals_sp = GetSP())
+ return signals_sp->GetSignalAtIndex(index);
+
return LLDB_INVALID_SIGNAL_NUMBER;
}
diff --git a/source/API/SystemInitializerFull.cpp b/source/API/SystemInitializerFull.cpp
index 731d38a37bee..01ad8157646e 100644
--- a/source/API/SystemInitializerFull.cpp
+++ b/source/API/SystemInitializerFull.cpp
@@ -58,7 +58,6 @@
#if defined(_MSC_VER)
#include "lldb/Host/windows/windows.h"
-#include "Plugins/Process/Windows/DynamicLoaderWindows.h"
#include "Plugins/Process/Windows/ProcessWindows.h"
#endif
@@ -264,7 +263,6 @@ SystemInitializerFull::Initialize()
RenderScriptRuntime::Initialize();
#if defined(_MSC_VER)
- DynamicLoaderWindows::Initialize();
ProcessWindows::Initialize();
#endif
#if defined(__FreeBSD__)
@@ -369,9 +367,6 @@ SystemInitializerFull::Terminate()
ProcessKDP::Terminate();
SymbolVendorMacOSX::Terminate();
#endif
-#if defined(_MSC_VER)
- DynamicLoaderWindows::Terminate();
-#endif
#if defined(__FreeBSD__)
ProcessFreeBSD::Terminate();
diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp
index ef9144778df0..a199d390803b 100644
--- a/source/Breakpoint/BreakpointLocation.cpp
+++ b/source/Breakpoint/BreakpointLocation.cpp
@@ -611,7 +611,7 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
{
s->EOL();
s->Indent("function = ");
- s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>"));
+ s->PutCString (sc.function->GetName().AsCString("<unknown>"));
}
if (sc.line_entry.line > 0)
@@ -632,7 +632,7 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
s->Indent ("re-exported target = ");
else
s->Indent("symbol = ");
- s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
+ s->PutCString(sc.symbol->GetName().AsCString("<unknown>"));
}
}
}
diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp
index 4cbcb70d5fd2..162bfb4b5a76 100644
--- a/source/Commands/CommandObjectBreakpoint.cpp
+++ b/source/Commands/CommandObjectBreakpoint.cpp
@@ -1249,27 +1249,27 @@ public:
CommandObjectBreakpointDisable (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
"breakpoint disable",
- "Disable the specified breakpoint(s) without removing it/them. If no breakpoints are specified, disable them all.",
+ "Disable the specified breakpoint(s) without removing them. If none are specified, disable all breakpoints.",
NULL)
{
SetHelpLong(
-"Disable the specified breakpoint(s) without removing it/them. \n\
-If no breakpoints are specified, disable them all.\n\
-\n\
-Note: disabling a breakpoint will cause none of its locations to be hit\n\
-regardless of whether they are enabled or disabled. So the sequence: \n\
-\n\
- (lldb) break disable 1\n\
- (lldb) break enable 1.1\n\
-\n\
-will NOT cause location 1.1 to get hit. To achieve that, do:\n\
-\n\
- (lldb) break disable 1.*\n\
- (lldb) break enable 1.1\n\
-\n\
-The first command disables all the locations of breakpoint 1, \n\
+"Disable the specified breakpoint(s) without removing them. \
+If none are specified, disable all breakpoints." R"(
+
+)" "Note: disabling a breakpoint will cause none of its locations to be hit \
+regardless of whether they are enabled or disabled. After the sequence:" R"(
+
+ (lldb) break disable 1
+ (lldb) break enable 1.1
+
+execution will NOT stop at location 1.1. To achieve that, type:
+
+ (lldb) break disable 1.*
+ (lldb) break enable 1.1
+
+)" "The first command disables all the locations of breakpoint 1, \
the second re-enables the first location."
- );
+ );
CommandArgumentEntry arg;
CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);
diff --git a/source/Commands/CommandObjectBreakpointCommand.cpp b/source/Commands/CommandObjectBreakpointCommand.cpp
index 180ab600a50e..ac9c9a64188c 100644
--- a/source/Commands/CommandObjectBreakpointCommand.cpp
+++ b/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -49,143 +49,120 @@ public:
m_options (interpreter)
{
SetHelpLong (
-"\nGeneral information about entering breakpoint commands\n\
-------------------------------------------------------\n\
-\n\
-This command will cause you to be prompted to enter the command or set of\n\
-commands you wish to be executed when the specified breakpoint is hit. You\n\
-will be told to enter your command(s), and will see a '> 'prompt. Because\n\
-you can enter one or many commands to be executed when a breakpoint is hit,\n\
-you will continue to be prompted after each new-line that you enter, until you\n\
-enter the word 'DONE', which will cause the commands you have entered to be\n\
-stored with the breakpoint and executed when the breakpoint is hit.\n\
-\n\
-Syntax checking is not necessarily done when breakpoint commands are entered.\n\
-An improperly written breakpoint command will attempt to get executed when the\n\
-breakpoint gets hit, and usually silently fail. If your breakpoint command does\n\
-not appear to be getting executed, go back and check your syntax.\n\
-\n\
-Special information about PYTHON breakpoint commands\n\
-----------------------------------------------------\n\
-\n\
-You may enter either one line of Python, multiple lines of Python (including\n\
-function definitions), or specify a Python function in a module that has already,\n\
-or will be imported. If you enter a single line of Python, that will be passed\n\
-to the Python interpreter 'as is' when the breakpoint gets hit. If you enter\n\
-function definitions, they will be passed to the Python interpreter as soon as\n\
-you finish entering the breakpoint command, and they can be called later (don't\n\
-forget to add calls to them, if you want them called when the breakpoint is\n\
-hit). If you enter multiple lines of Python that are not function definitions,\n\
-they will be collected into a new, automatically generated Python function, and\n\
-a call to the newly generated function will be attached to the breakpoint.\n\
-\n\
-\n\
-This auto-generated function is passed in three arguments:\n\
-\n\
- frame: a lldb.SBFrame object for the frame which hit breakpoint.\n\
- bp_loc: a lldb.SBBreakpointLocation object that represents the breakpoint\n\
- location that was hit.\n\
- dict: the python session dictionary hit.\n\
-\n\
-When specifying a python function with the --python-function option, you need\n\
-to supply the function name prepended by the module name. So if you import a\n\
-module named 'myutils' that contains a 'breakpoint_callback' function, you would\n\
-specify the option as:\n\
-\n\
- --python-function myutils.breakpoint_callback\n\
-\n\
-The function itself must have the following prototype:\n\
-\n\
-def breakpoint_callback(frame, bp_loc, dict):\n\
- # Your code goes here\n\
-\n\
-The arguments are the same as the 3 auto generation function arguments listed\n\
-above. Note that the global variable 'lldb.frame' will NOT be setup when this\n\
-function is called, so be sure to use the 'frame' argument. The 'frame' argument\n\
-can get you to the thread (frame.GetThread()), the thread can get you to the\n\
-process (thread.GetProcess()), and the process can get you back to the target\n\
-(process.GetTarget()).\n\
-\n\
-Important Note: Because loose Python code gets collected into functions, if you\n\
-want to access global variables in the 'loose' code, you need to specify that\n\
-they are global, using the 'global' keyword. Be sure to use correct Python\n\
-syntax, including indentation, when entering Python breakpoint commands.\n\
-\n\
-As a third option, you can pass the name of an already existing Python function\n\
-and that function will be attached to the breakpoint. It will get passed the\n\
-frame and bp_loc arguments mentioned above.\n\
-\n\
-Example Python one-line breakpoint command:\n\
-\n\
-(lldb) breakpoint command add -s python 1\n\
-Enter your Python command(s). Type 'DONE' to end.\n\
-> print \"Hit this breakpoint!\"\n\
-> DONE\n\
-\n\
-As a convenience, this also works for a short Python one-liner:\n\
-(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\"\n\
-(lldb) run\n\
-Launching '.../a.out' (x86_64)\n\
-(lldb) Fri Sep 10 12:17:45 2010\n\
-Process 21778 Stopped\n\
-* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread\n\
- 36 \n\
- 37 int c(int val)\n\
- 38 {\n\
- 39 -> return val + 3;\n\
- 40 }\n\
- 41 \n\
- 42 int main (int argc, char const *argv[])\n\
-(lldb)\n\
-\n\
-Example multiple line Python breakpoint command, using function definition:\n\
-\n\
-(lldb) breakpoint command add -s python 1\n\
-Enter your Python command(s). Type 'DONE' to end.\n\
-> def breakpoint_output (bp_no):\n\
-> out_string = \"Hit breakpoint number \" + repr (bp_no)\n\
-> print out_string\n\
-> return True\n\
-> breakpoint_output (1)\n\
-> DONE\n\
-\n\
-\n\
-Example multiple line Python breakpoint command, using 'loose' Python:\n\
-\n\
-(lldb) breakpoint command add -s p 1\n\
-Enter your Python command(s). Type 'DONE' to end.\n\
-> global bp_count\n\
-> bp_count = bp_count + 1\n\
-> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\"\n\
-> DONE\n\
-\n\
-In this case, since there is a reference to a global variable,\n\
-'bp_count', you will also need to make sure 'bp_count' exists and is\n\
-initialized:\n\
-\n\
-(lldb) script\n\
->>> bp_count = 0\n\
->>> quit()\n\
-\n\
-(lldb)\n\
-\n\
-\n\
-Your Python code, however organized, can optionally return a value.\n\
-If the returned value is False, that tells LLDB not to stop at the breakpoint\n\
-to which the code is associated. Returning anything other than False, or even\n\
-returning None, or even omitting a return statement entirely, will cause\n\
-LLDB to stop.\n\
-\n\
-Final Note: If you get a warning that no breakpoint command was generated, but\n\
-you did not get any syntax errors, you probably forgot to add a call to your\n\
-functions.\n\
-\n\
-Special information about debugger command breakpoint commands\n\
---------------------------------------------------------------\n\
-\n\
-You may enter any debugger command, exactly as you would at the debugger prompt.\n\
-You may enter as many debugger commands as you like, but do NOT enter more than\n\
-one command per line.\n" );
+R"(
+General information about entering breakpoint commands
+------------------------------------------------------
+
+)" "This command will prompt for commands to be executed when the specified \
+breakpoint is hit. Each command is typed on its own line following the '> ' \
+prompt until 'DONE' is entered." R"(
+
+)" "Syntactic errors may not be detected when initially entered, and many \
+malformed commands can silently fail when executed. If your breakpoint commands \
+do not appear to be executing, double-check the command syntax." R"(
+
+)" "Note: You may enter any debugger command exactly as you would at the debugger \
+prompt. There is no limit to the number of commands supplied, but do NOT enter \
+more than one command per line." R"(
+
+Special information about PYTHON breakpoint commands
+----------------------------------------------------
+
+)" "You may enter either one or more lines of Python, including function \
+definitions or calls to functions that will have been imported by the time \
+the code executes. Single line breakpoint commands will be interpreted 'as is' \
+when the breakpoint is hit. Multiple lines of Python will be wrapped in a \
+generated function, and a call to the function will be attached to the breakpoint." R"(
+
+This auto-generated function is passed in three arguments:
+
+ frame: an lldb.SBFrame object for the frame which hit breakpoint.
+
+ bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit.
+
+ dict: the python session dictionary hit.
+
+)" "When specifying a python function with the --python-function option, you need \
+to supply the function name prepended by the module name:" R"(
+
+ --python-function myutils.breakpoint_callback
+
+The function itself must have the following prototype:
+
+def breakpoint_callback(frame, bp_loc, dict):
+ # Your code goes here
+
+)" "The arguments are the same as the arguments passed to generated functions as \
+described above. Note that the global variable 'lldb.frame' will NOT be updated when \
+this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
+can get you to the thread via frame.GetThread(), the thread can get you to the \
+process via thread.GetProcess(), and the process can get you back to the target \
+via process.GetTarget()." R"(
+
+)" "Important Note: As Python code gets collected into functions, access to global \
+variables requires explicit scoping using the 'global' keyword. Be sure to use correct \
+Python syntax, including indentation, when entering Python breakpoint commands." R"(
+
+Example Python one-line breakpoint command:
+
+(lldb) breakpoint command add -s python 1
+Enter your Python command(s). Type 'DONE' to end.
+> print "Hit this breakpoint!"
+> DONE
+
+As a convenience, this also works for a short Python one-liner:
+
+(lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()'
+(lldb) run
+Launching '.../a.out' (x86_64)
+(lldb) Fri Sep 10 12:17:45 2010
+Process 21778 Stopped
+* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
+ 36
+ 37 int c(int val)
+ 38 {
+ 39 -> return val + 3;
+ 40 }
+ 41
+ 42 int main (int argc, char const *argv[])
+
+Example multiple line Python breakpoint command:
+
+(lldb) breakpoint command add -s p 1
+Enter your Python command(s). Type 'DONE' to end.
+> global bp_count
+> bp_count = bp_count + 1
+> print "Hit this breakpoint " + repr(bp_count) + " times!"
+> DONE
+
+Example multiple line Python breakpoint command, using function definition:
+
+(lldb) breakpoint command add -s python 1
+Enter your Python command(s). Type 'DONE' to end.
+> def breakpoint_output (bp_no):
+> out_string = "Hit breakpoint number " + repr (bp_no)
+> print out_string
+> return True
+> breakpoint_output (1)
+> DONE
+
+)" "In this case, since there is a reference to a global variable, \
+'bp_count', you will also need to make sure 'bp_count' exists and is \
+initialized:" R"(
+
+(lldb) script
+>>> bp_count = 0
+>>> quit()
+
+)" "Your Python code, however organized, can optionally return a value. \
+If the returned value is False, that tells LLDB not to stop at the breakpoint \
+to which the code is associated. Returning anything other than False, or even \
+returning None, or even omitting a return statement entirely, will cause \
+LLDB to stop." R"(
+
+)" "Final Note: A warning that no breakpoint command was generated when there \
+are no syntax errors may indicate that a function was declared but never called."
+ );
CommandArgumentEntry arg;
CommandArgumentData bp_id_arg;
diff --git a/source/Commands/CommandObjectCommands.cpp b/source/Commands/CommandObjectCommands.cpp
index 5fd99cfdabf4..f56d089877de 100644
--- a/source/Commands/CommandObjectCommands.cpp
+++ b/source/Commands/CommandObjectCommands.cpp
@@ -450,60 +450,74 @@ public:
NULL)
{
SetHelpLong(
- "'alias' allows the user to create a short-cut or abbreviation for long \n\
- commands, multi-word commands, and commands that take particular options. \n\
- Below are some simple examples of how one might use the 'alias' command: \n\
- \n 'command alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\
- // command. \n\
- 'command alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\
- // command. Since breakpoint commands are two-word \n\
- // commands, the user will still need to enter the \n\
- // second word after 'bp', e.g. 'bp enable' or \n\
- // 'bp delete'. \n\
- 'command alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
- // two-word command 'breakpoint list'. \n\
- \nAn alias can include some options for the command, with the values either \n\
- filled in at the time the alias is created, or specified as positional \n\
- arguments, to be filled in when the alias is invoked. The following example \n\
- shows how to create aliases with options: \n\
- \n\
- 'command alias bfl breakpoint set -f %1 -l %2' \n\
- \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
- options already part of the alias. So if the user wants to set a breakpoint \n\
- by file and line without explicitly having to use the -f and -l options, the \n\
- user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\
- for the actual arguments that will be passed when the alias command is used. \n\
- The number in the placeholder refers to the position/order the actual value \n\
- occupies when the alias is used. All the occurrences of '%1' in the alias \n\
- will be replaced with the first argument, all the occurrences of '%2' in the \n\
- alias will be replaced with the second argument, and so on. This also allows \n\
- actual arguments to be used multiple times within an alias (see 'process \n\
- launch' example below). \n\
- Note: the positional arguments must substitute as whole words in the resultant\n\
- command, so you can't at present do something like:\n\
- \n\
- command alias bcppfl breakpoint set -f %1.cpp -l %2\n\
- \n\
- to get the file extension \".cpp\" automatically appended. For more complex\n\
- aliasing, use the \"command regex\" command instead.\n\
- \nSo in the 'bfl' case, the actual file value will be \n\
- filled in with the first argument following 'bfl' and the actual line number \n\
- value will be filled in with the second argument. The user would use this \n\
- alias as follows: \n\
- \n (lldb) command alias bfl breakpoint set -f %1 -l %2 \n\
- <... some time later ...> \n\
- (lldb) bfl my-file.c 137 \n\
- \nThis would be the same as if the user had entered \n\
- 'breakpoint set -f my-file.c -l 137'. \n\
- \nAnother example: \n\
- \n (lldb) command alias pltty process launch -s -o %1 -e %1 \n\
- (lldb) pltty /dev/tty0 \n\
- // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
- \nIf the user always wanted to pass the same value to a particular option, the \n\
- alias could be defined with that value directly in the alias as a constant, \n\
- rather than using a positional placeholder: \n\
- \n command alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\
- // 3 of whatever file is indicated. \n");
+"'alias' allows the user to create a short-cut or abbreviation for long \
+commands, multi-word commands, and commands that take particular options. \
+Below are some simple examples of how one might use the 'alias' command:" R"(
+
+(lldb) command alias sc script
+
+ Creates the abbreviation 'sc' for the 'script' command.
+
+(lldb) command alias bp breakpoint
+
+)" " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \
+breakpoint commands are two-word commands, the user would still need to \
+enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." R"(
+
+(lldb) command alias bpl breakpoint list
+
+ Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
+
+)" "An alias can include some options for the command, with the values either \
+filled in at the time the alias is created, or specified as positional \
+arguments, to be filled in when the alias is invoked. The following example \
+shows how to create aliases with options:" R"(
+
+(lldb) command alias bfl breakpoint set -f %1 -l %2
+
+)" " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
+options already part of the alias. So if the user wants to set a breakpoint \
+by file and line without explicitly having to use the -f and -l options, the \
+user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \
+for the actual arguments that will be passed when the alias command is used. \
+The number in the placeholder refers to the position/order the actual value \
+occupies when the alias is used. All the occurrences of '%1' in the alias \
+will be replaced with the first argument, all the occurrences of '%2' in the \
+alias will be replaced with the second argument, and so on. This also allows \
+actual arguments to be used multiple times within an alias (see 'process \
+launch' example below)." R"(
+
+)" "Note: the positional arguments must substitute as whole words in the resultant \
+command, so you can't at present do something like this to append the file extension \
+\".cpp\":" R"(
+
+(lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
+
+)" "For more complex aliasing, use the \"command regex\" command instead. In the \
+'bfl' case above, the actual file value will be filled in with the first argument \
+following 'bfl' and the actual line number value will be filled in with the second \
+argument. The user would use this alias as follows:" R"(
+
+(lldb) command alias bfl breakpoint set -f %1 -l %2
+(lldb) bfl my-file.c 137
+
+This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
+
+Another example:
+
+(lldb) command alias pltty process launch -s -o %1 -e %1
+(lldb) pltty /dev/tty0
+
+ Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
+
+)" "If the user always wanted to pass the same value to a particular option, the \
+alias could be defined with that value directly in the alias as a constant, \
+rather than using a positional placeholder:" R"(
+
+(lldb) command alias bl3 breakpoint set -f %1 -l 3
+
+ Always sets a breakpoint on line 3 of whatever file is indicated.)"
+ );
CommandArgumentEntry arg1;
CommandArgumentEntry arg2;
@@ -960,31 +974,30 @@ public:
IOHandlerDelegateMultiline ("", IOHandlerDelegate::Completion::LLDBCommand),
m_options (interpreter)
{
- SetHelpLong(
-"This command allows the user to create powerful regular expression commands\n"
-"with substitutions. The regular expressions and substitutions are specified\n"
-"using the regular expression substitution format of:\n"
-"\n"
-" s/<regex>/<subst>/\n"
-"\n"
-"<regex> is a regular expression that can use parenthesis to capture regular\n"
-"expression input and substitute the captured matches in the output using %1\n"
-"for the first match, %2 for the second, and so on.\n"
-"\n"
-"The regular expressions can all be specified on the command line if more than\n"
-"one argument is provided. If just the command name is provided on the command\n"
-"line, then the regular expressions and substitutions can be entered on separate\n"
-" lines, followed by an empty line to terminate the command definition.\n"
-"\n"
-"EXAMPLES\n"
-"\n"
-"The following example will define a regular expression command named 'f' that\n"
-"will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n"
-"a number follows 'f':\n"
-"\n"
-" (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n"
-"\n"
- );
+ SetHelpLong(R"(
+)" "This command allows the user to create powerful regular expression commands \
+with substitutions. The regular expressions and substitutions are specified \
+using the regular expression substitution format of:" R"(
+
+ s/<regex>/<subst>/
+
+)" "<regex> is a regular expression that can use parenthesis to capture regular \
+expression input and substitute the captured matches in the output using %1 \
+for the first match, %2 for the second, and so on." R"(
+
+)" "The regular expressions can all be specified on the command line if more than \
+one argument is provided. If just the command name is provided on the command \
+line, then the regular expressions and substitutions can be entered on separate \
+lines, followed by an empty line to terminate the command definition." R"(
+
+EXAMPLES
+
+)" "The following example will define a regular expression command named 'f' that \
+will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
+a number follows 'f':" R"(
+
+ (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"
+ );
}
~CommandObjectCommandsAddRegex()
diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp
index f4bb8fbac11e..1be17a0cfddc 100644
--- a/source/Commands/CommandObjectExpression.cpp
+++ b/source/Commands/CommandObjectExpression.cpp
@@ -202,35 +202,39 @@ CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interprete
m_expr_line_count (0),
m_expr_lines ()
{
- SetHelpLong(
-"Timeouts:\n\
- If the expression can be evaluated statically (without running code) then it will be.\n\
- Otherwise, by default the expression will run on the current thread with a short timeout:\n\
- currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted\n\
- and resumed with all threads running. You can use the -a option to disable retrying on all\n\
- threads. You can use the -t option to set a shorter timeout.\n\
-\n\
-User defined variables:\n\
- You can define your own variables for convenience or to be used in subsequent expressions.\n\
- You define them the same way you would define variables in C. If the first character of \n\
- your user defined variable is a $, then the variable's value will be available in future\n\
- expressions, otherwise it will just be available in the current expression.\n\
-\n\
-\n\
-Continuing evaluation after a breakpoint:\n\
- If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once\n\
- you are done with your investigation, you can either remove the expression execution frames\n\
- from the stack with \"thread return -x\" or if you are still interested in the expression result\n\
- you can issue the \"continue\" command and the expression evaluation will complete and the\n\
- expression result will be available using the \"thread.completed-expression\" key in the thread\n\
- format.\n\
-\n\
-Examples: \n\
-\n\
- expr my_struct->a = my_array[3] \n\
- expr -f bin -- (index * 8) + 5 \n\
- expr unsigned int $foo = 5\n\
- expr char c[] = \"foo\"; c[0]\n");
+ SetHelpLong(
+R"(
+Timeouts:
+
+)" " If the expression can be evaluated statically (without running code) then it will be. \
+Otherwise, by default the expression will run on the current thread with a short timeout: \
+currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted \
+and resumed with all threads running. You can use the -a option to disable retrying on all \
+threads. You can use the -t option to set a shorter timeout." R"(
+
+User defined variables:
+
+)" " You can define your own variables for convenience or to be used in subsequent expressions. \
+You define them the same way you would define variables in C. If the first character of \
+your user defined variable is a $, then the variable's value will be available in future \
+expressions, otherwise it will just be available in the current expression." R"(
+
+Continuing evaluation after a breakpoint:
+
+)" " If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once \
+you are done with your investigation, you can either remove the expression execution frames \
+from the stack with \"thread return -x\" or if you are still interested in the expression result \
+you can issue the \"continue\" command and the expression evaluation will complete and the \
+expression result will be available using the \"thread.completed-expression\" key in the thread \
+format." R"(
+
+Examples:
+
+ expr my_struct->a = my_array[3]
+ expr -f bin -- (index * 8) + 5
+ expr unsigned int $foo = 5
+ expr char c[] = \"foo\"; c[0])"
+ );
CommandArgumentEntry arg;
CommandArgumentData expression_arg;
diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp
index 866587fb4ebc..a0979d059edb 100644
--- a/source/Commands/CommandObjectPlatform.cpp
+++ b/source/Commands/CommandObjectPlatform.cpp
@@ -1067,10 +1067,12 @@ public:
0)
{
SetHelpLong(
-"Examples: \n\
-\n\
- platform get-file /the/remote/file/path /the/local/file/path\n\
- # Transfer a file from the remote end with file path /the/remote/file/path to the local host.\n");
+R"(Examples:
+
+(lldb) platform get-file /the/remote/file/path /the/local/file/path
+
+ Transfer a file from the remote end with file path /the/remote/file/path to the local host.)"
+ );
CommandArgumentEntry arg1, arg2;
CommandArgumentData file_arg_remote, file_arg_host;
@@ -1150,10 +1152,12 @@ public:
0)
{
SetHelpLong(
-"Examples: \n\
-\n\
- platform get-size /the/remote/file/path\n\
- # Get the file size from the remote end with path /the/remote/file/path.\n");
+R"(Examples:
+
+(lldb) platform get-size /the/remote/file/path
+
+ Get the file size from the remote end with path /the/remote/file/path.)"
+ );
CommandArgumentEntry arg1;
CommandArgumentData file_arg_remote;
diff --git a/source/Commands/CommandObjectProcess.cpp b/source/Commands/CommandObjectProcess.cpp
index 4414bdf2a2c8..e587eadfa3d6 100644
--- a/source/Commands/CommandObjectProcess.cpp
+++ b/source/Commands/CommandObjectProcess.cpp
@@ -1337,7 +1337,7 @@ protected:
if (::isxdigit (signal_name[0]))
signo = StringConvert::ToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
else
- signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
+ signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name);
if (signo == LLDB_INVALID_SIGNAL_NUMBER)
{
@@ -1681,7 +1681,8 @@ public:
NULL),
m_options (interpreter)
{
- SetHelpLong ("If no signals are specified, update them all. If no update option is specified, list the current values.\n");
+ SetHelpLong ("\nIf no signals are specified, update them all. If no update "
+ "option is specified, list the current values.");
CommandArgumentEntry arg;
CommandArgumentData signal_arg;
@@ -1734,14 +1735,14 @@ public:
}
void
- PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
+ PrintSignal(Stream &str, int32_t signo, const char *sig_name, const UnixSignalsSP &signals_sp)
{
bool stop;
bool suppress;
bool notify;
str.Printf ("%-11s ", sig_name);
- if (signals.GetSignalInfo (signo, suppress, stop, notify))
+ if (signals_sp->GetSignalInfo(signo, suppress, stop, notify))
{
bool pass = !suppress;
str.Printf ("%s %s %s",
@@ -1753,7 +1754,7 @@ public:
}
void
- PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
+ PrintSignalInformation(Stream &str, Args &signal_args, int num_valid_signals, const UnixSignalsSP &signals_sp)
{
PrintSignalHeader (str);
@@ -1762,18 +1763,18 @@ public:
size_t num_args = signal_args.GetArgumentCount();
for (size_t i = 0; i < num_args; ++i)
{
- int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
+ int32_t signo = signals_sp->GetSignalNumberFromName(signal_args.GetArgumentAtIndex(i));
if (signo != LLDB_INVALID_SIGNAL_NUMBER)
- PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
+ PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals_sp);
}
}
else // Print info for ALL signals
{
- int32_t signo = signals.GetFirstSignalNumber();
+ int32_t signo = signals_sp->GetFirstSignalNumber();
while (signo != LLDB_INVALID_SIGNAL_NUMBER)
{
- PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
- signo = signals.GetNextSignalNumber (signo);
+ PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), signals_sp);
+ signo = signals_sp->GetNextSignalNumber(signo);
}
}
}
@@ -1830,27 +1831,27 @@ protected:
}
size_t num_args = signal_args.GetArgumentCount();
- UnixSignals &signals = process_sp->GetUnixSignals();
+ UnixSignalsSP signals_sp = process_sp->GetUnixSignals();
int num_signals_set = 0;
if (num_args > 0)
{
for (size_t i = 0; i < num_args; ++i)
{
- int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
+ int32_t signo = signals_sp->GetSignalNumberFromName(signal_args.GetArgumentAtIndex(i));
if (signo != LLDB_INVALID_SIGNAL_NUMBER)
{
// Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
// the value is either 0 or 1.
if (stop_action != -1)
- signals.SetShouldStop (signo, (bool) stop_action);
+ signals_sp->SetShouldStop(signo, stop_action);
if (pass_action != -1)
{
- bool suppress = ! ((bool) pass_action);
- signals.SetShouldSuppress (signo, suppress);
+ bool suppress = !pass_action;
+ signals_sp->SetShouldSuppress(signo, suppress);
}
if (notify_action != -1)
- signals.SetShouldNotify (signo, (bool) notify_action);
+ signals_sp->SetShouldNotify(signo, notify_action);
++num_signals_set;
}
else
@@ -1866,25 +1867,25 @@ protected:
{
if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
{
- int32_t signo = signals.GetFirstSignalNumber();
+ int32_t signo = signals_sp->GetFirstSignalNumber();
while (signo != LLDB_INVALID_SIGNAL_NUMBER)
{
if (notify_action != -1)
- signals.SetShouldNotify (signo, (bool) notify_action);
+ signals_sp->SetShouldNotify(signo, notify_action);
if (stop_action != -1)
- signals.SetShouldStop (signo, (bool) stop_action);
+ signals_sp->SetShouldStop(signo, stop_action);
if (pass_action != -1)
{
- bool suppress = ! ((bool) pass_action);
- signals.SetShouldSuppress (signo, suppress);
+ bool suppress = !pass_action;
+ signals_sp->SetShouldSuppress(signo, suppress);
}
- signo = signals.GetNextSignalNumber (signo);
+ signo = signals_sp->GetNextSignalNumber(signo);
}
}
}
}
- PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
+ PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals_sp);
if (num_signals_set > 0)
result.SetStatus (eReturnStatusSuccessFinishNoResult);
diff --git a/source/Commands/CommandObjectSettings.cpp b/source/Commands/CommandObjectSettings.cpp
index ccbf98c767f1..8ed783b211f6 100644
--- a/source/Commands/CommandObjectSettings.cpp
+++ b/source/Commands/CommandObjectSettings.cpp
@@ -60,24 +60,25 @@ public:
m_arguments.push_back (arg2);
SetHelpLong (
-"When setting a dictionary or array variable, you can set multiple entries \n\
-at once by giving the values to the set command. For example: \n\
-\n\
-(lldb) settings set target.run-args value1 value2 value3 \n\
-(lldb) settings set target.env-vars MYPATH=~/.:/usr/bin SOME_ENV_VAR=12345 \n\
-\n\
-(lldb) settings show target.run-args \n\
- [0]: 'value1' \n\
- [1]: 'value2' \n\
- [3]: 'value3' \n\
-(lldb) settings show target.env-vars \n\
- 'MYPATH=~/.:/usr/bin'\n\
- 'SOME_ENV_VAR=12345' \n\
-\n\
-Warning: The 'set' command re-sets the entire array or dictionary. If you \n\
-just want to add, remove or update individual values (or add something to \n\
-the end), use one of the other settings sub-commands: append, replace, \n\
-insert-before or insert-after.\n");
+"\nWhen setting a dictionary or array variable, you can set multiple entries \
+at once by giving the values to the set command. For example:" R"(
+
+(lldb) settings set target.run-args value1 value2 value3
+(lldb) settings set target.env-vars MYPATH=~/.:/usr/bin SOME_ENV_VAR=12345
+
+(lldb) settings show target.run-args
+ [0]: 'value1'
+ [1]: 'value2'
+ [3]: 'value3'
+(lldb) settings show target.env-vars
+ 'MYPATH=~/.:/usr/bin'
+ 'SOME_ENV_VAR=12345'
+
+)" "Warning: The 'set' command re-sets the entire array or dictionary. If you \
+just want to add, remove or update individual values (or add something to \
+the end), use one of the other settings sub-commands: append, replace, \
+insert-before or insert-after."
+ );
}
diff --git a/source/Commands/CommandObjectType.cpp b/source/Commands/CommandObjectType.cpp
index 7c8061a6ca08..584e94d0452d 100644
--- a/source/Commands/CommandObjectType.cpp
+++ b/source/Commands/CommandObjectType.cpp
@@ -764,31 +764,39 @@ public:
m_arguments.push_back (type_arg);
SetHelpLong(
- "Some examples of using this command.\n"
- "We use as reference the following snippet of code:\n"
- "\n"
- "typedef int Aint;\n"
- "typedef float Afloat;\n"
- "typedef Aint Bint;\n"
- "typedef Afloat Bfloat;\n"
- "\n"
- "Aint ix = 5;\n"
- "Bint iy = 5;\n"
- "\n"
- "Afloat fx = 3.14;\n"
- "BFloat fy = 3.14;\n"
- "\n"
- "Typing:\n"
- "type format add -f hex AInt\n"
- "frame variable iy\n"
- "will produce an hex display of iy, because no formatter is available for Bint and the one for Aint is used instead\n"
- "To prevent this type\n"
- "type format add -f hex -C no AInt\n"
- "\n"
- "A similar reasoning applies to\n"
- "type format add -f hex -C no float -p\n"
- "which now prints all floats and float&s as hexadecimal, but does not format float*s\n"
- "and does not change the default display for Afloat and Bfloat objects.\n"
+R"(
+The following examples of 'type format add' refer to this code snippet for context:
+
+ typedef int Aint;
+ typedef float Afloat;
+ typedef Aint Bint;
+ typedef Afloat Bfloat;
+
+ Aint ix = 5;
+ Bint iy = 5;
+
+ Afloat fx = 3.14;
+ BFloat fy = 3.14;
+
+Adding default formatting:
+
+(lldb) type format add -f hex AInt
+(lldb) frame variable iy
+
+)" " Produces hexidecimal display of iy, because no formatter is available for Bint and \
+the one for Aint is used instead." R"(
+
+To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
+
+
+(lldb) type format add -f hex -C no AInt
+
+Similar reasoning applies to this:
+
+(lldb) type format add -f hex -C no float -p
+
+)" " All float values and float references are now formatted as hexadecimal, but not \
+pointers to floats. Nor will it change the default display for Afloat and Bfloat objects."
);
// Add the "--format" to all options groups
@@ -1736,69 +1744,86 @@ CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &in
m_arguments.push_back (type_arg);
SetHelpLong(
- "Some examples of using this command.\n"
- "We use as reference the following snippet of code:\n"
- "struct JustADemo\n"
- "{\n"
- "int* ptr;\n"
- "float value;\n"
- "JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}\n"
- "};\n"
- "JustADemo object(42,3.14);\n"
- "struct AnotherDemo : public JustADemo\n"
- "{\n"
- "uint8_t byte;\n"
- "AnotherDemo(uint8_t b = 'E', int p = 1, float v = 0.1) : JustADemo(p,v), byte(b) {}\n"
- "};\n"
- "AnotherDemo *another_object = new AnotherDemo('E',42,3.14);\n"
- "\n"
- "type summary add --summary-string \"the answer is ${*var.ptr}\" JustADemo\n"
- "when typing frame variable object you will get \"the answer is 42\"\n"
- "type summary add --summary-string \"the answer is ${*var.ptr}, and the question is ${var.value}\" JustADemo\n"
- "when typing frame variable object you will get \"the answer is 42 and the question is 3.14\"\n"
- "\n"
- "Alternatively, you could also say\n"
- "type summary add --summary-string \"${var%V} -> ${*var}\" \"int *\"\n"
- "and replace the above summary string with\n"
- "type summary add --summary-string \"the answer is ${var.ptr}, and the question is ${var.value}\" JustADemo\n"
- "to obtain a similar result\n"
- "\n"
- "To add a summary valid for both JustADemo and AnotherDemo you can use the scoping operator, as in:\n"
- "type summary add --summary-string \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes\n"
- "\n"
- "This will be used for both variables of type JustADemo and AnotherDemo. To prevent this, change the -C to read -C no\n"
- "If you do not want pointers to be shown using that summary, you can use the -p option, as in:\n"
- "type summary add --summary-string \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes -p\n"
- "A similar option -r exists for references.\n"
- "\n"
- "If you simply want a one-line summary of the content of your variable, without typing an explicit string to that effect\n"
- "you can use the -c option, without giving any summary string:\n"
- "type summary add -c JustADemo\n"
- "frame variable object\n"
- "the output being similar to (ptr=0xsomeaddress, value=3.14)\n"
- "\n"
- "If you want to display some summary text, but also expand the structure of your object, you can add the -e option, as in:\n"
- "type summary add -e --summary-string \"*ptr = ${*var.ptr}\" JustADemo\n"
- "Here the value of the int* is displayed, followed by the standard LLDB sequence of children objects, one per line.\n"
- "to get an output like:\n"
- "\n"
- "*ptr = 42 {\n"
- " ptr = 0xsomeaddress\n"
- " value = 3.14\n"
- "}\n"
- "\n"
- "You can also add Python summaries, in which case you will use lldb public API to gather information from your variables"
- "and elaborate them to a meaningful summary inside a script written in Python. The variable object will be passed to your"
- "script as an SBValue object. The following example might help you when starting to use the Python summaries feature:\n"
- "type summary add JustADemo -o \"value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();\"\n"
- "If you prefer to type your scripts on multiple lines, you will use the -P option and then type your script, ending it with "
- "the word DONE on a line by itself to mark you're finished editing your code:\n"
- "(lldb)type summary add JustADemo -P\n"
- " value = valobj.GetChildMemberWithName('value');\n"
- " return 'My value is ' + value.GetValue();\n"
- "DONE\n"
- "(lldb) <-- type further LLDB commands here\n"
- );
+R"(
+The following examples of 'type summary add' refer to this code snippet for context:
+
+ struct JustADemo
+ {
+ int* ptr;
+ float value;
+ JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
+ };
+ JustADemo demo_instance(42, 3.14);
+
+ typedef JustADemo NewDemo;
+ NewDemo new_demo_instance(42, 3.14);
+
+(lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
+
+ Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
+
+(lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
+
+ Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
+
+)" "Alternatively, you could define formatting for all pointers to integers and \
+rely on that when formatting JustADemo to obtain the same result:" R"(
+
+(lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
+(lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
+
+)" "Type summaries are automatically applied to derived typedefs, so the examples \
+above apply to both JustADemo and NewDemo. The cascade option can be used to \
+suppress this behavior:" R"(
+
+(lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
+
+ The summary will now be used for values of JustADemo but not NewDemo.
+
+)" "By default summaries are shown for pointers and references to values of the \
+specified type. To suppress formatting for pointers use the -p option, or apply \
+the corresponding -r option to suppress formatting for references:" R"(
+
+(lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
+
+)" "One-line summaries including all fields in a type can be inferred without supplying an \
+explicit summary string by passing the -c option:" R"(
+
+(lldb) type summary add -c JustADemo
+(lldb) frame variable demo_instance
+(ptr=<address>, value=3.14)
+
+)" "Type summaries normally suppress the nested display of individual fields. To \
+supply a summary to supplement the default structure add the -e option:" R"(
+
+(lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
+
+)" "Now when displaying JustADemo values the int* is displayed, followed by the \
+standard LLDB sequence of children, one per line:" R"(
+
+*ptr = 42 {
+ ptr = <address>
+ value = 3.14
+}
+
+)" "You can also add summaries written in Python. These scripts use lldb public API to \
+gather information from your variables and produce a meaningful summary. To start a \
+multi-line script use the -P option. The function declaration will be displayed along with \
+a comment describing the two arguments. End your script with the word 'DONE' on a line by \
+itself:" R"(
+
+(lldb) type summary add JustADemo -P
+def function (valobj,internal_dict):
+"""valobj: an SBValue which you want to provide a summary for
+internal_dict: an LLDB support object not to be used"""
+ value = valobj.GetChildMemberWithName('value');
+ return 'My value is ' + value.GetValue();
+ DONE
+
+Alternatively, the -o option can be used when providing a simple one-line Python script:
+
+(lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")"
+ );
}
bool
@@ -4117,31 +4142,37 @@ public:
m_arguments.push_back (type_arg);
SetHelpLong(
- "Some examples of using this command.\n"
- "We use as reference the following snippet of code:\n"
- "\n"
- "class Foo {;\n"
- " int a;\n"
- " int b;\n"
- " int c;\n"
- " int d;\n"
- " int e;\n"
- " int f;\n"
- " int g;\n"
- " int h;\n"
- " int i;\n"
- "} \n"
- "Typing:\n"
- "type filter add --child a --child g Foo\n"
- "frame variable a_foo\n"
- "will produce an output where only a and g are displayed\n"
- "Other children of a_foo (b,c,d,e,f,h and i) are available by asking for them, as in:\n"
- "frame variable a_foo.b a_foo.c ... a_foo.i\n"
- "\n"
- "Use option --raw to frame variable prevails on the filter\n"
- "frame variable a_foo --raw\n"
- "shows all the children of a_foo (a thru i) as if no filter was defined\n"
- );
+R"(
+The following examples of 'type filter add' refer to this code snippet for context:
+
+ class Foo {
+ int a;
+ int b;
+ int c;
+ int d;
+ int e;
+ int f;
+ int g;
+ int h;
+ int i;
+ }
+ Foo my_foo;
+
+Adding a simple filter:
+
+(lldb) type filter add --child a --child g Foo
+(lldb) frame variable my_foo
+
+)" "Produces output where only a and g are displayed. Other children of my_foo \
+(b, c, d, e, f, h and i) are available by asking for them explicitly:" R"(
+
+(lldb) frame variable my_foo.b my_foo.c my_foo.i
+
+)" "The formatting option --raw on frame variable bypasses the filter, showing \
+all children of my_foo as if no filter was defined:" R"(
+
+(lldb) frame variable my_foo --raw)"
+ );
}
~CommandObjectTypeFilterAdd ()
diff --git a/source/Commands/CommandObjectWatchpoint.cpp b/source/Commands/CommandObjectWatchpoint.cpp
index 650fd253af02..414e78403cc8 100644
--- a/source/Commands/CommandObjectWatchpoint.cpp
+++ b/source/Commands/CommandObjectWatchpoint.cpp
@@ -931,10 +931,14 @@ public:
m_option_watchpoint ()
{
SetHelpLong(
- "Examples: \n\
- \n\
- watchpoint set variable -w read_write my_global_var \n\
- # Watch my_global_var for read/write access, with the region to watch corresponding to the byte size of the data type.\n");
+R"(
+Examples:
+
+(lldb) watchpoint set variable -w read_write my_global_var
+
+)" " Watches my_global_var for read/write access, with the region to watch \
+corresponding to the byte size of the data type."
+ );
CommandArgumentEntry arg;
CommandArgumentData var_name_arg;
@@ -1138,10 +1142,13 @@ public:
m_option_watchpoint ()
{
SetHelpLong(
- "Examples: \n\
- \n\
- watchpoint set expression -w write -x 1 -- foo + 32\n\
- # Watch write access for the 1-byte region pointed to by the address 'foo + 32'.\n");
+R"(
+Examples:
+
+(lldb) watchpoint set expression -w write -x 1 -- foo + 32
+
+ Watches write access for the 1-byte region pointed to by the address 'foo + 32')"
+ );
CommandArgumentEntry arg;
CommandArgumentData expression_arg;
diff --git a/source/Commands/CommandObjectWatchpointCommand.cpp b/source/Commands/CommandObjectWatchpointCommand.cpp
index d7d064e5fed9..84342cc8ffdf 100644
--- a/source/Commands/CommandObjectWatchpointCommand.cpp
+++ b/source/Commands/CommandObjectWatchpointCommand.cpp
@@ -48,121 +48,112 @@ public:
m_options (interpreter)
{
SetHelpLong (
-"\nGeneral information about entering watchpoint commands \n\
------------------------------------------------------- \n\
- \n\
-This command will cause you to be prompted to enter the command or set \n\
-of commands you wish to be executed when the specified watchpoint is \n\
-hit. You will be told to enter your command(s), and will see a '> ' \n\
-prompt. Because you can enter one or many commands to be executed when \n\
-a watchpoint is hit, you will continue to be prompted after each \n\
-new-line that you enter, until you enter the word 'DONE', which will \n\
-cause the commands you have entered to be stored with the watchpoint \n\
-and executed when the watchpoint is hit. \n\
- \n\
-Syntax checking is not necessarily done when watchpoint commands are \n\
-entered. An improperly written watchpoint command will attempt to get \n\
-executed when the watchpoint gets hit, and usually silently fail. If \n\
-your watchpoint command does not appear to be getting executed, go \n\
-back and check your syntax. \n\
- \n\
- \n\
-Special information about PYTHON watchpoint commands \n\
----------------------------------------------------- \n\
- \n\
-You may enter either one line of Python or multiple lines of Python \n\
-(including defining whole functions, if desired). If you enter a \n\
-single line of Python, that will be passed to the Python interpreter \n\
-'as is' when the watchpoint gets hit. If you enter function \n\
-definitions, they will be passed to the Python interpreter as soon as \n\
-you finish entering the watchpoint command, and they can be called \n\
-later (don't forget to add calls to them, if you want them called when \n\
-the watchpoint is hit). If you enter multiple lines of Python that \n\
-are not function definitions, they will be collected into a new, \n\
-automatically generated Python function, and a call to the newly \n\
-generated function will be attached to the watchpoint. \n\
- \n\
-This auto-generated function is passed in two arguments: \n\
- \n\
- frame: an SBFrame object representing the frame which hit the watchpoint. \n\
- From the frame you can get back to the thread and process. \n\
- wp: the watchpoint that was hit. \n\
- \n\
-Important Note: Because loose Python code gets collected into functions, \n\
-if you want to access global variables in the 'loose' code, you need to \n\
-specify that they are global, using the 'global' keyword. Be sure to \n\
-use correct Python syntax, including indentation, when entering Python \n\
-watchpoint commands. \n\
- \n\
-As a third option, you can pass the name of an already existing Python function \n\
-and that function will be attached to the watchpoint. It will get passed the \n\
-frame and wp_loc arguments mentioned above. \n\
- \n\
-Example Python one-line watchpoint command: \n\
- \n\
-(lldb) watchpoint command add -s python 1 \n\
-Enter your Python command(s). Type 'DONE' to end. \n\
-> print \"Hit this watchpoint!\" \n\
-> DONE \n\
- \n\
-As a convenience, this also works for a short Python one-liner: \n\
-(lldb) watchpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
-(lldb) run \n\
-Launching '.../a.out' (x86_64) \n\
-(lldb) Fri Sep 10 12:17:45 2010 \n\
-Process 21778 Stopped \n\
-* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = watchpoint 1.1, queue = com.apple.main-thread \n\
- 36 \n\
- 37 int c(int val)\n\
- 38 {\n\
- 39 -> return val + 3;\n\
- 40 }\n\
- 41 \n\
- 42 int main (int argc, char const *argv[])\n\
-(lldb) \n\
- \n\
-Example multiple line Python watchpoint command, using function definition: \n\
- \n\
-(lldb) watchpoint command add -s python 1 \n\
-Enter your Python command(s). Type 'DONE' to end. \n\
-> def watchpoint_output (wp_no): \n\
-> out_string = \"Hit watchpoint number \" + repr (wp_no) \n\
-> print out_string \n\
-> return True \n\
-> watchpoint_output (1) \n\
-> DONE \n\
- \n\
- \n\
-Example multiple line Python watchpoint command, using 'loose' Python: \n\
- \n\
-(lldb) watchpoint command add -s p 1 \n\
-Enter your Python command(s). Type 'DONE' to end. \n\
-> global wp_count \n\
-> wp_count = wp_count + 1 \n\
-> print \"Hit this watchpoint \" + repr(wp_count) + \" times!\" \n\
-> DONE \n\
- \n\
-In this case, since there is a reference to a global variable, \n\
-'wp_count', you will also need to make sure 'wp_count' exists and is \n\
-initialized: \n\
- \n\
-(lldb) script \n\
->>> wp_count = 0 \n\
->>> quit() \n\
- \n\
-(lldb) \n\
- \n\
- \n\
-Final Note: If you get a warning that no watchpoint command was generated, \n\
-but you did not get any syntax errors, you probably forgot to add a call \n\
-to your functions. \n\
- \n\
-Special information about debugger command watchpoint commands \n\
--------------------------------------------------------------- \n\
- \n\
-You may enter any debugger command, exactly as you would at the \n\
-debugger prompt. You may enter as many debugger commands as you like, \n\
-but do NOT enter more than one command per line. \n" );
+R"(
+General information about entering watchpoint commands
+------------------------------------------------------
+
+)" "This command will prompt for commands to be executed when the specified \
+watchpoint is hit. Each command is typed on its own line following the '> ' \
+prompt until 'DONE' is entered." R"(
+
+)" "Syntactic errors may not be detected when initially entered, and many \
+malformed commands can silently fail when executed. If your watchpoint commands \
+do not appear to be executing, double-check the command syntax." R"(
+
+)" "Note: You may enter any debugger command exactly as you would at the debugger \
+prompt. There is no limit to the number of commands supplied, but do NOT enter \
+more than one command per line." R"(
+
+Special information about PYTHON watchpoint commands
+----------------------------------------------------
+
+)" "You may enter either one or more lines of Python, including function \
+definitions or calls to functions that will have been imported by the time \
+the code executes. Single line watchpoint commands will be interpreted 'as is' \
+when the watchpoint is hit. Multiple lines of Python will be wrapped in a \
+generated function, and a call to the function will be attached to the watchpoint." R"(
+
+This auto-generated function is passed in three arguments:
+
+ frame: an lldb.SBFrame object for the frame which hit the watchpoint.
+
+ wp: the watchpoint that was hit.
+
+)" "When specifying a python function with the --python-function option, you need \
+to supply the function name prepended by the module name:" R"(
+
+ --python-function myutils.watchpoint_callback
+
+The function itself must have the following prototype:
+
+def watchpoint_callback(frame, wp):
+ # Your code goes here
+
+)" "The arguments are the same as the arguments passed to generated functions as \
+described above. Note that the global variable 'lldb.frame' will NOT be updated when \
+this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
+can get you to the thread via frame.GetThread(), the thread can get you to the \
+process via thread.GetProcess(), and the process can get you back to the target \
+via process.GetTarget()." R"(
+
+)" "Important Note: As Python code gets collected into functions, access to global \
+variables requires explicit scoping using the 'global' keyword. Be sure to use correct \
+Python syntax, including indentation, when entering Python watchpoint commands." R"(
+
+Example Python one-line watchpoint command:
+
+(lldb) watchpoint command add -s python 1
+Enter your Python command(s). Type 'DONE' to end.
+> print "Hit this watchpoint!"
+> DONE
+
+As a convenience, this also works for a short Python one-liner:
+
+(lldb) watchpoint command add -s python 1 -o 'import time; print time.asctime()'
+(lldb) run
+Launching '.../a.out' (x86_64)
+(lldb) Fri Sep 10 12:17:45 2010
+Process 21778 Stopped
+* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = watchpoint 1.1, queue = com.apple.main-thread
+ 36
+ 37 int c(int val)
+ 38 {
+ 39 -> return val + 3;
+ 40 }
+ 41
+ 42 int main (int argc, char const *argv[])
+
+Example multiple line Python watchpoint command, using function definition:
+
+(lldb) watchpoint command add -s python 1
+Enter your Python command(s). Type 'DONE' to end.
+> def watchpoint_output (wp_no):
+> out_string = "Hit watchpoint number " + repr (wp_no)
+> print out_string
+> return True
+> watchpoint_output (1)
+> DONE
+
+Example multiple line Python watchpoint command, using 'loose' Python:
+
+(lldb) watchpoint command add -s p 1
+Enter your Python command(s). Type 'DONE' to end.
+> global wp_count
+> wp_count = wp_count + 1
+> print "Hit this watchpoint " + repr(wp_count) + " times!"
+> DONE
+
+)" "In this case, since there is a reference to a global variable, \
+'wp_count', you will also need to make sure 'wp_count' exists and is \
+initialized:" R"(
+
+(lldb) script
+>>> wp_count = 0
+>>> quit()
+
+)" "Final Note: A warning that no watchpoint command was generated when there \
+are no syntax errors may indicate that a function was declared but never called."
+ );
CommandArgumentEntry arg;
CommandArgumentData wp_id_arg;
diff --git a/source/Core/ArchSpec.cpp b/source/Core/ArchSpec.cpp
index 33cbede9ce14..36344307743e 100644
--- a/source/Core/ArchSpec.cpp
+++ b/source/Core/ArchSpec.cpp
@@ -887,20 +887,15 @@ ArchSpec::SetArchitecture (ArchitectureType arch_type, uint32_t cpu, uint32_t su
}
else if (arch_type == eArchTypeELF)
{
- llvm::Triple::OSType ostype;
switch (os)
{
- case llvm::ELF::ELFOSABI_AIX: ostype = llvm::Triple::OSType::AIX; break;
- case llvm::ELF::ELFOSABI_FREEBSD: ostype = llvm::Triple::OSType::FreeBSD; break;
- case llvm::ELF::ELFOSABI_GNU: ostype = llvm::Triple::OSType::Linux; break;
- case llvm::ELF::ELFOSABI_NETBSD: ostype = llvm::Triple::OSType::NetBSD; break;
- case llvm::ELF::ELFOSABI_OPENBSD: ostype = llvm::Triple::OSType::OpenBSD; break;
- case llvm::ELF::ELFOSABI_SOLARIS: ostype = llvm::Triple::OSType::Solaris; break;
- default:
- ostype = llvm::Triple::OSType::UnknownOS;
+ case llvm::ELF::ELFOSABI_AIX: m_triple.setOS (llvm::Triple::OSType::AIX); break;
+ case llvm::ELF::ELFOSABI_FREEBSD: m_triple.setOS (llvm::Triple::OSType::FreeBSD); break;
+ case llvm::ELF::ELFOSABI_GNU: m_triple.setOS (llvm::Triple::OSType::Linux); break;
+ case llvm::ELF::ELFOSABI_NETBSD: m_triple.setOS (llvm::Triple::OSType::NetBSD); break;
+ case llvm::ELF::ELFOSABI_OPENBSD: m_triple.setOS (llvm::Triple::OSType::OpenBSD); break;
+ case llvm::ELF::ELFOSABI_SOLARIS: m_triple.setOS (llvm::Triple::OSType::Solaris); break;
}
- m_triple.setOS (ostype);
- m_triple.setVendor (llvm::Triple::UnknownVendor);
}
// Fall back onto setting the machine type if the arch by name failed...
if (m_triple.getArch () == llvm::Triple::UnknownArch)
@@ -1186,11 +1181,46 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in
}
break;
+ case ArchSpec::eCore_mips32:
+ if (!enforce_exact_match)
+ {
+ if (core2 >= ArchSpec::kCore_mips32_first && core2 <= ArchSpec::kCore_mips32_last)
+ return true;
+ try_inverse = false;
+ }
+ break;
+
+ case ArchSpec::eCore_mips32el:
+ if (!enforce_exact_match)
+ {
+ if (core2 >= ArchSpec::kCore_mips32el_first && core2 <= ArchSpec::kCore_mips32el_last)
+ return true;
+ try_inverse = false;
+ }
+
case ArchSpec::eCore_mips64:
+ if (!enforce_exact_match)
+ {
+ if (core2 >= ArchSpec::kCore_mips32_first && core2 <= ArchSpec::kCore_mips32_last)
+ return true;
+ if (core2 >= ArchSpec::kCore_mips64_first && core2 <= ArchSpec::kCore_mips64_last)
+ return true;
+ try_inverse = false;
+ }
+
+ case ArchSpec::eCore_mips64el:
+ if (!enforce_exact_match)
+ {
+ if (core2 >= ArchSpec::kCore_mips32el_first && core2 <= ArchSpec::kCore_mips32el_last)
+ return true;
+ if (core2 >= ArchSpec::kCore_mips64el_first && core2 <= ArchSpec::kCore_mips64el_last)
+ return true;
+ try_inverse = false;
+ }
+
case ArchSpec::eCore_mips64r2:
case ArchSpec::eCore_mips64r3:
case ArchSpec::eCore_mips64r5:
- case ArchSpec::eCore_mips64r6:
if (!enforce_exact_match)
{
if (core2 >= ArchSpec::kCore_mips32_first && core2 <= (core1 - 10))
@@ -1201,11 +1231,9 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in
}
break;
- case ArchSpec::eCore_mips64el:
case ArchSpec::eCore_mips64r2el:
case ArchSpec::eCore_mips64r3el:
case ArchSpec::eCore_mips64r5el:
- case ArchSpec::eCore_mips64r6el:
if (!enforce_exact_match)
{
if (core2 >= ArchSpec::kCore_mips32el_first && core2 <= (core1 - 10))
@@ -1216,6 +1244,63 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in
}
break;
+ case ArchSpec::eCore_mips32r2:
+ case ArchSpec::eCore_mips32r3:
+ case ArchSpec::eCore_mips32r5:
+ if (!enforce_exact_match)
+ {
+ if (core2 >= ArchSpec::kCore_mips32_first && core2 <= core1)
+ return true;
+ }
+ break;
+
+ case ArchSpec::eCore_mips32r2el:
+ case ArchSpec::eCore_mips32r3el:
+ case ArchSpec::eCore_mips32r5el:
+ if (!enforce_exact_match)
+ {
+ if (core2 >= ArchSpec::kCore_mips32el_first && core2 <= core1)
+ return true;
+ }
+ break;
+
+ case ArchSpec::eCore_mips32r6:
+ if (!enforce_exact_match)
+ {
+ if (core2 == ArchSpec::eCore_mips32 || core2 == ArchSpec::eCore_mips32r6)
+ return true;
+ }
+ break;
+
+ case ArchSpec::eCore_mips32r6el:
+ if (!enforce_exact_match)
+ {
+ if (core2 == ArchSpec::eCore_mips32el || core2 == ArchSpec::eCore_mips32r6el)
+ return true;
+ return true;
+ }
+ break;
+
+ case ArchSpec::eCore_mips64r6:
+ if (!enforce_exact_match)
+ {
+ if (core2 == ArchSpec::eCore_mips32 || core2 == ArchSpec::eCore_mips32r6)
+ return true;
+ if (core2 == ArchSpec::eCore_mips64 || core2 == ArchSpec::eCore_mips64r6)
+ return true;
+ }
+ break;
+
+ case ArchSpec::eCore_mips64r6el:
+ if (!enforce_exact_match)
+ {
+ if (core2 == ArchSpec::eCore_mips32el || core2 == ArchSpec::eCore_mips32r6el)
+ return true;
+ if (core2 == ArchSpec::eCore_mips64el || core2 == ArchSpec::eCore_mips64r6el)
+ return true;
+ }
+ break;
+
default:
break;
}
diff --git a/source/Core/DataExtractor.cpp b/source/Core/DataExtractor.cpp
index b4b43ed97780..861bece98da9 100644
--- a/source/Core/DataExtractor.cpp
+++ b/source/Core/DataExtractor.cpp
@@ -1830,26 +1830,14 @@ DataExtractor::Dump (Stream *s,
}
else if (item_bit_size == ast->getTypeSize(ast->LongDoubleTy))
{
+ const auto &semantics = ast->getFloatTypeSemantics(ast->LongDoubleTy);
+ const auto byte_size = (llvm::APFloat::getSizeInBits(semantics) + 7) / 8;
+
llvm::APInt apint;
- switch (target_sp->GetArchitecture().GetMachine())
+ if (GetAPInt(*this, &offset, byte_size, apint))
{
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- // clang will assert when constructing the apfloat if we use a 16 byte integer value
- if (GetAPInt (*this, &offset, 10, apint))
- {
- llvm::APFloat apfloat (ast->getFloatTypeSemantics(ast->LongDoubleTy), apint);
- apfloat.toString(sv, format_precision, format_max_padding);
- }
- break;
-
- default:
- if (GetAPInt (*this, &offset, item_byte_size, apint))
- {
- llvm::APFloat apfloat (ast->getFloatTypeSemantics(ast->LongDoubleTy), apint);
- apfloat.toString(sv, format_precision, format_max_padding);
- }
- break;
+ llvm::APFloat apfloat(semantics, apint);
+ apfloat.toString(sv, format_precision, format_max_padding);
}
}
else if (item_bit_size == ast->getTypeSize(ast->HalfTy))
diff --git a/source/Core/FormatEntity.cpp b/source/Core/FormatEntity.cpp
index 2ebe95747bc0..e89d6c9cb4a9 100644
--- a/source/Core/FormatEntity.cpp
+++ b/source/Core/FormatEntity.cpp
@@ -1666,7 +1666,7 @@ FormatEntity::Format (const Entry &entry,
if (inline_info)
{
s.PutCString(" [inlined] ");
- inline_info->GetName().Dump(&s);
+ inline_info->GetName(sc->function->GetLanguage()).Dump(&s);
}
}
}
@@ -1679,9 +1679,9 @@ FormatEntity::Format (const Entry &entry,
{
ConstString name;
if (sc->function)
- name = sc->function->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments);
+ name = sc->function->GetNameNoArguments();
else if (sc->symbol)
- name = sc->symbol->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments);
+ name = sc->symbol->GetNameNoArguments();
if (name)
{
s.PutCString(name.GetCString());
@@ -1724,7 +1724,7 @@ FormatEntity::Format (const Entry &entry,
{
s.PutCString (cstr);
s.PutCString (" [inlined] ");
- cstr = inline_info->GetName().GetCString();
+ cstr = inline_info->GetName(sc->function->GetLanguage()).GetCString();
}
VariableList args;
diff --git a/source/Core/Mangled.cpp b/source/Core/Mangled.cpp
index 3e1a8bb89139..a1916fe913c4 100644
--- a/source/Core/Mangled.cpp
+++ b/source/Core/Mangled.cpp
@@ -66,7 +66,7 @@ cstring_is_mangled(const char *s)
}
static const ConstString &
-get_demangled_name_without_arguments (const Mangled *obj)
+get_demangled_name_without_arguments (ConstString mangled, ConstString demangled)
{
// This pair is <mangled name, demangled name without function arguments>
static std::pair<ConstString, ConstString> g_most_recent_mangled_to_name_sans_args;
@@ -77,9 +77,6 @@ get_demangled_name_without_arguments (const Mangled *obj)
static ConstString g_last_mangled;
static ConstString g_last_demangled;
- ConstString mangled = obj->GetMangledName ();
- ConstString demangled = obj->GetDemangledName ();
-
if (mangled && g_most_recent_mangled_to_name_sans_args.first == mangled)
{
return g_most_recent_mangled_to_name_sans_args.second;
@@ -197,7 +194,7 @@ Mangled::Clear ()
int
Mangled::Compare (const Mangled& a, const Mangled& b)
{
- return ConstString::Compare(a.GetName(ePreferMangled), a.GetName(ePreferMangled));
+ return ConstString::Compare(a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled), a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled));
}
@@ -261,7 +258,7 @@ Mangled::SetValue (const ConstString &name)
// object's lifetime.
//----------------------------------------------------------------------
const ConstString&
-Mangled::GetDemangledName () const
+Mangled::GetDemangledName (lldb::LanguageType language) const
{
// Check to make sure we have a valid mangled name and that we
// haven't already decoded our mangled name.
@@ -339,13 +336,20 @@ Mangled::GetDemangledName () const
}
+ConstString
+Mangled::GetDisplayDemangledName (lldb::LanguageType language) const
+{
+ return GetDemangledName(language);
+}
+
bool
-Mangled::NameMatches (const RegularExpression& regex) const
+Mangled::NameMatches (const RegularExpression& regex, lldb::LanguageType language) const
{
if (m_mangled && regex.Execute (m_mangled.AsCString()))
return true;
-
- if (GetDemangledName() && regex.Execute (m_demangled.AsCString()))
+
+ ConstString demangled = GetDemangledName(language);
+ if (demangled && regex.Execute (demangled.AsCString()))
return true;
return false;
}
@@ -353,30 +357,28 @@ Mangled::NameMatches (const RegularExpression& regex) const
//----------------------------------------------------------------------
// Get the demangled name if there is one, else return the mangled name.
//----------------------------------------------------------------------
-const ConstString&
-Mangled::GetName (Mangled::NamePreference preference) const
+ConstString
+Mangled::GetName (lldb::LanguageType language, Mangled::NamePreference preference) const
{
+ ConstString demangled = GetDemangledName(language);
+
if (preference == ePreferDemangledWithoutArguments)
{
- // Call the accessor to make sure we get a demangled name in case
- // it hasn't been demangled yet...
- GetDemangledName();
-
- return get_demangled_name_without_arguments (this);
+ return get_demangled_name_without_arguments (m_mangled, demangled);
}
if (preference == ePreferDemangled)
{
// Call the accessor to make sure we get a demangled name in case
// it hasn't been demangled yet...
- if (GetDemangledName())
- return m_demangled;
+ if (demangled)
+ return demangled;
return m_mangled;
}
else
{
if (m_mangled)
return m_mangled;
- return GetDemangledName();
+ return demangled;
}
}
@@ -429,7 +431,7 @@ Mangled::GuessLanguage () const
ConstString mangled = GetMangledName();
if (mangled)
{
- if (GetDemangledName())
+ if (GetDemangledName(lldb::eLanguageTypeUnknown))
{
if (cstring_is_mangled(mangled.GetCString()))
return lldb::eLanguageTypeC_plus_plus;
@@ -447,7 +449,7 @@ operator << (Stream& s, const Mangled& obj)
if (obj.GetMangledName())
s << "mangled = '" << obj.GetMangledName() << "'";
- const ConstString& demangled = obj.GetDemangledName();
+ const ConstString& demangled = obj.GetDemangledName(lldb::eLanguageTypeUnknown);
if (demangled)
s << ", demangled = '" << demangled << '\'';
else
diff --git a/source/Core/StructuredData.cpp b/source/Core/StructuredData.cpp
index a2c440948af1..efc104f1f3e8 100644
--- a/source/Core/StructuredData.cpp
+++ b/source/Core/StructuredData.cpp
@@ -14,301 +14,148 @@
#include <inttypes.h>
#include "lldb/Core/StreamString.h"
+#include "lldb/Host/StringConvert.h"
+#include "lldb/Utility/JSON.h"
using namespace lldb_private;
-static StructuredData::ObjectSP read_json_object (const char **ch);
-static StructuredData::ObjectSP read_json_array (const char **ch);
+//----------------------------------------------------------------------
+// Functions that use a JSONParser to parse JSON into StructuredData
+//----------------------------------------------------------------------
+static StructuredData::ObjectSP ParseJSONValue (JSONParser &json_parser);
+static StructuredData::ObjectSP ParseJSONObject (JSONParser &json_parser);
+static StructuredData::ObjectSP ParseJSONArray (JSONParser &json_parser);
static StructuredData::ObjectSP
-read_json_number (const char **ch)
+ParseJSONObject (JSONParser &json_parser)
{
- StructuredData::ObjectSP object_sp;
- while (isspace (**ch))
- (*ch)++;
- const char *start_of_number = *ch;
- bool is_integer = true;
- bool is_float = false;
- while (isdigit(**ch) || **ch == '-' || **ch == '.' || **ch == '+' || **ch == 'e' || **ch == 'E')
- {
- if (isdigit(**ch) == false && **ch != '-')
- {
- is_integer = false;
- is_float = true;
- }
- (*ch)++;
- }
- while (isspace (**ch))
- (*ch)++;
- if (**ch == ',' || **ch == ']' || **ch == '}')
+ // The "JSONParser::Token::ObjectStart" token should have already been consumed
+ // by the time this function is called
+ std::unique_ptr<StructuredData::Dictionary> dict_up(new StructuredData::Dictionary());
+
+ std::string value;
+ std::string key;
+ while (1)
{
- if (is_integer)
+ JSONParser::Token token = json_parser.GetToken(value);
+
+ if (token == JSONParser::Token::String)
{
- errno = 0;
- uint64_t val = strtoul (start_of_number, NULL, 10);
- if (errno == 0)
+ key.swap(value);
+ token = json_parser.GetToken(value);
+ if (token == JSONParser::Token::Colon)
{
- object_sp.reset(new StructuredData::Integer());
- object_sp->GetAsInteger()->SetValue (val);
+ StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser);
+ if (value_sp)
+ dict_up->AddItem(key, value_sp);
+ else
+ break;
}
}
- if (is_float)
+ else if (token == JSONParser::Token::ObjectEnd)
{
- char *end_of_number = NULL;
- errno = 0;
- double val = strtod (start_of_number, &end_of_number);
- if (errno == 0 && end_of_number != start_of_number && end_of_number != NULL)
- {
- object_sp.reset(new StructuredData::Float());
- object_sp->GetAsFloat()->SetValue (val);
- }
+ return StructuredData::ObjectSP(dict_up.release());
}
- }
- return object_sp;
-}
-
-static std::string
-read_json_string (const char **ch)
-{
- std::string string;
- if (**ch == '"')
- {
- (*ch)++;
- while (**ch != '\0')
+ else if (token == JSONParser::Token::Comma)
{
- if (**ch == '"')
- {
- (*ch)++;
- while (isspace (**ch))
- (*ch)++;
- break;
- }
- else if (**ch == '\\')
- {
- switch (**ch)
- {
- case '"':
- string.push_back('"');
- *ch += 2;
- break;
- case '\\':
- string.push_back('\\');
- *ch += 2;
- break;
- case '/':
- string.push_back('/');
- *ch += 2;
- break;
- case 'b':
- string.push_back('\b');
- *ch += 2;
- break;
- case 'f':
- string.push_back('\f');
- *ch += 2;
- break;
- case 'n':
- string.push_back('\n');
- *ch += 2;
- break;
- case 'r':
- string.push_back('\r');
- *ch += 2;
- break;
- case 't':
- string.push_back('\t');
- *ch += 2;
- break;
- case 'u':
- // FIXME handle four-hex-digits
- *ch += 10;
- break;
- default:
- *ch += 1;
- }
- }
- else
- {
- string.push_back (**ch);
- }
- (*ch)++;
+ continue;
+ }
+ else
+ {
+ break;
}
}
- return string;
+ return StructuredData::ObjectSP();
}
static StructuredData::ObjectSP
-read_json_value (const char **ch)
+ParseJSONArray (JSONParser &json_parser)
{
- StructuredData::ObjectSP object_sp;
- while (isspace (**ch))
- (*ch)++;
+ // The "JSONParser::Token::ObjectStart" token should have already been consumed
+ // by the time this function is called
+ std::unique_ptr<StructuredData::Array> array_up(new StructuredData::Array());
- if (**ch == '{')
- {
- object_sp = read_json_object (ch);
- }
- else if (**ch == '[')
+ std::string value;
+ std::string key;
+ while (1)
{
- object_sp = read_json_array (ch);
- }
- else if (**ch == '"')
- {
- std::string string = read_json_string (ch);
- object_sp.reset(new StructuredData::String());
- object_sp->GetAsString()->SetValue(string);
- }
- else
- {
- if (strncmp (*ch, "true", 4) == 0)
- {
- object_sp.reset(new StructuredData::Boolean());
- object_sp->GetAsBoolean()->SetValue(true);
- *ch += 4;
- }
- else if (strncmp (*ch, "false", 5) == 0)
+ StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser);
+ if (value_sp)
+ array_up->AddItem(value_sp);
+ else
+ break;
+
+ JSONParser::Token token = json_parser.GetToken(value);
+ if (token == JSONParser::Token::Comma)
{
- object_sp.reset(new StructuredData::Boolean());
- object_sp->GetAsBoolean()->SetValue(false);
- *ch += 5;
+ continue;
}
- else if (strncmp (*ch, "null", 4) == 0)
+ else if (token == JSONParser::Token::ArrayEnd)
{
- object_sp.reset(new StructuredData::Null());
- *ch += 4;
+ return StructuredData::ObjectSP(array_up.release());
}
else
{
- object_sp = read_json_number (ch);
+ break;
}
}
- return object_sp;
+ return StructuredData::ObjectSP();
}
static StructuredData::ObjectSP
-read_json_array (const char **ch)
+ParseJSONValue (JSONParser &json_parser)
{
- StructuredData::ObjectSP object_sp;
- if (**ch == '[')
+ std::string value;
+ const JSONParser::Token token = json_parser.GetToken(value);
+ switch (token)
{
- (*ch)++;
- while (isspace (**ch))
- (*ch)++;
+ case JSONParser::Token::ObjectStart:
+ return ParseJSONObject(json_parser);
- bool first_value = true;
- while (**ch != '\0' && (first_value || **ch == ','))
- {
- if (**ch == ',')
- (*ch)++;
- first_value = false;
- while (isspace (**ch))
- (*ch)++;
- lldb_private::StructuredData::ObjectSP value_sp = read_json_value (ch);
- if (value_sp)
+ case JSONParser::Token::ArrayStart:
+ return ParseJSONArray(json_parser);
+
+ case JSONParser::Token::Integer:
{
- if (object_sp.get() == NULL)
- {
- object_sp.reset(new StructuredData::Array());
- }
- object_sp->GetAsArray()->Push (value_sp);
+ bool success = false;
+ uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success);
+ if (success)
+ return StructuredData::ObjectSP(new StructuredData::Integer(uval));
}
- while (isspace (**ch))
- (*ch)++;
- }
- if (**ch == ']')
- {
- // FIXME should throw an error if we don't see a } to close out the JSON object
- (*ch)++;
- while (isspace (**ch))
- (*ch)++;
- }
- }
- return object_sp;
-}
+ break;
-static StructuredData::ObjectSP
-read_json_object (const char **ch)
-{
- StructuredData::ObjectSP object_sp;
- if (**ch == '{')
- {
- (*ch)++;
- while (isspace (**ch))
- (*ch)++;
- bool first_pair = true;
- while (**ch != '\0' && (first_pair || **ch == ','))
- {
- first_pair = false;
- if (**ch == ',')
- (*ch)++;
- while (isspace (**ch))
- (*ch)++;
- if (**ch != '"')
- break;
- std::string key_string = read_json_string (ch);
- while (isspace (**ch))
- (*ch)++;
- if (key_string.size() > 0 && **ch == ':')
+ case JSONParser::Token::Float:
{
- (*ch)++;
- while (isspace (**ch))
- (*ch)++;
- lldb_private::StructuredData::ObjectSP value_sp = read_json_value (ch);
- if (value_sp.get())
- {
- if (object_sp.get() == NULL)
- {
- object_sp.reset(new StructuredData::Dictionary());
- }
- object_sp->GetAsDictionary()->AddItem (key_string.c_str(), value_sp);
- }
+ bool success = false;
+ double val = StringConvert::ToDouble(value.c_str(), 0.0, &success);
+ if (success)
+ return StructuredData::ObjectSP(new StructuredData::Float(val));
}
- while (isspace (**ch))
- (*ch)++;
- }
- if (**ch == '}')
- {
- // FIXME should throw an error if we don't see a } to close out the JSON object
- (*ch)++;
- while (isspace (**ch))
- (*ch)++;
- }
+ break;
+
+ case JSONParser::Token::String:
+ return StructuredData::ObjectSP(new StructuredData::String(value));
+
+ case JSONParser::Token::True:
+ case JSONParser::Token::False:
+ return StructuredData::ObjectSP(new StructuredData::Boolean(token == JSONParser::Token::True));
+
+ case JSONParser::Token::Null:
+ return StructuredData::ObjectSP(new StructuredData::Null());
+
+ default:
+ break;
}
- return object_sp;
-}
+ return StructuredData::ObjectSP();
+}
StructuredData::ObjectSP
StructuredData::ParseJSON (std::string json_text)
{
- StructuredData::ObjectSP object_sp;
- const size_t json_text_size = json_text.size();
- if (json_text_size > 0)
- {
- const char *start_of_json_text = json_text.c_str();
- const char *c = json_text.c_str();
- while (*c != '\0' &&
- static_cast<size_t>(c - start_of_json_text) <= json_text_size)
- {
- while (isspace (*c) &&
- static_cast<size_t>(c - start_of_json_text) < json_text_size)
- c++;
- if (*c == '{')
- {
- object_sp = read_json_object (&c);
- }
- else if (*c == '[')
- {
- object_sp = read_json_array (&c);
- }
- else
- {
- // We have bad characters here, this is likely an illegal JSON string.
- return object_sp;
- }
- }
- }
+ JSONParser json_parser(json_text.c_str());
+ StructuredData::ObjectSP object_sp = ParseJSONValue(json_parser);
return object_sp;
}
@@ -395,7 +242,7 @@ StructuredData::Integer::Dump (Stream &s) const
void
StructuredData::Float::Dump (Stream &s) const
{
- s.Printf ("%lf", m_value);
+ s.Printf ("%lg", m_value);
}
void
diff --git a/source/DataFormatters/FormatManager.cpp b/source/DataFormatters/FormatManager.cpp
index 47456ba5c45b..4e0fffbe6a1a 100644
--- a/source/DataFormatters/FormatManager.cpp
+++ b/source/DataFormatters/FormatManager.cpp
@@ -1608,6 +1608,26 @@ FormatManager::LoadHardcodedFormatters()
}
return nullptr;
});
+ m_hardcoded_summaries.push_back(
+ [](lldb_private::ValueObject& valobj,
+ lldb::DynamicValueType,
+ FormatManager& fmt_mgr) -> TypeSummaryImpl::SharedPointer {
+ static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags()
+ .SetCascades(true)
+ .SetDontShowChildren(true)
+ .SetHideItemNames(true)
+ .SetShowMembersOneLiner(true)
+ .SetSkipPointers(true)
+ .SetSkipReferences(false),
+ lldb_private::formatters::VectorTypeSummaryProvider,
+ "vector_type pointer summary provider"));
+ if (valobj.GetClangType().IsVectorType(nullptr, nullptr))
+ {
+ if (fmt_mgr.GetCategory(fmt_mgr.m_vectortypes_category_name)->IsEnabled())
+ return formatter_sp;
+ }
+ return nullptr;
+ });
}
{
// insert code to load synthetics here
diff --git a/source/DataFormatters/VectorType.cpp b/source/DataFormatters/VectorType.cpp
index 57bf696ba4fa..316d7b540bcd 100644
--- a/source/DataFormatters/VectorType.cpp
+++ b/source/DataFormatters/VectorType.cpp
@@ -7,9 +7,10 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+#include "lldb/DataFormatters/VectorType.h"
#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/CXXFormatterFunctions.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangASTType.h"
@@ -267,6 +268,51 @@ namespace lldb_private {
}
}
+bool
+lldb_private::formatters::VectorTypeSummaryProvider (ValueObject& valobj,
+ Stream& s,
+ const TypeSummaryOptions&)
+{
+ auto synthetic_children = VectorTypeSyntheticFrontEndCreator(nullptr, valobj.GetSP());
+ if (!synthetic_children)
+ return false;
+
+ synthetic_children->Update();
+
+ s.PutChar('(');
+ bool first = true;
+
+ size_t idx = 0, len = synthetic_children->CalculateNumChildren();
+
+ for (;
+ idx < len;
+ idx++)
+ {
+ auto child_sp = synthetic_children->GetChildAtIndex(idx);
+ if (!child_sp)
+ continue;
+ child_sp = child_sp->GetQualifiedRepresentationIfAvailable(lldb::eDynamicDontRunTarget, true);
+
+ const char* child_value = child_sp->GetValueAsCString();
+ if (child_value && *child_value)
+ {
+ if (first)
+ {
+ s.Printf("%s", child_value);
+ first = false;
+ }
+ else
+ {
+ s.Printf(", %s", child_value);
+ }
+ }
+ }
+
+ s.PutChar(')');
+
+ return true;
+}
+
lldb_private::SyntheticChildrenFrontEnd*
lldb_private::formatters::VectorTypeSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
{
diff --git a/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp
index 1013bb540601..2c66a0aa4278 100644
--- a/source/Expression/ClangExpressionDeclMap.cpp
+++ b/source/Expression/ClangExpressionDeclMap.cpp
@@ -1527,6 +1527,31 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
context.m_found.function_with_type_info = true;
context.m_found.function = true;
}
+ else if (llvm::isa<clang::VarDecl>(decl_from_modules))
+ {
+ if (log)
+ {
+ log->Printf(" CAS::FEVD[%u] Matching variable found for \"%s\" in the modules",
+ current_id,
+ name.GetCString());
+ }
+
+ clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
+ clang::VarDecl *copied_var_decl = copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl) : nullptr;
+
+ if (!copied_var_decl)
+ {
+ if (log)
+ log->Printf(" CAS::FEVD[%u] - Couldn't export a variable declaration from the modules",
+ current_id);
+
+ break;
+ }
+
+ context.AddNamedDecl(copied_var_decl);
+
+ context.m_found.variable = true;
+ }
}
} while (0);
}
diff --git a/source/Expression/ClangExpressionParser.cpp b/source/Expression/ClangExpressionParser.cpp
index 3d5350d34028..2b344b0c3733 100644
--- a/source/Expression/ClangExpressionParser.cpp
+++ b/source/Expression/ClangExpressionParser.cpp
@@ -541,10 +541,11 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule());
Error interpret_error;
+ Process *process = exe_ctx.GetProcessPtr();
- can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error);
+ bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls();
+ can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error, interpret_function_calls);
- Process *process = exe_ctx.GetProcessPtr();
if (!ir_can_run)
{
diff --git a/source/Expression/ClangModulesDeclVendor.cpp b/source/Expression/ClangModulesDeclVendor.cpp
index 97a4d088b982..e8253630724a 100644
--- a/source/Expression/ClangModulesDeclVendor.cpp
+++ b/source/Expression/ClangModulesDeclVendor.cpp
@@ -18,6 +18,7 @@
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/LLDBAssert.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
@@ -444,18 +445,18 @@ ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVec
}
ssize_t found_priority = -1;
- clang::MacroInfo *info = nullptr;
+ clang::MacroInfo *macro_info = nullptr;
- for (clang::ModuleMacro *macro : m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii))
+ for (clang::ModuleMacro *module_macro : m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii))
{
- clang::Module *module = macro->getOwningModule();
+ clang::Module *module = module_macro->getOwningModule();
{
ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(module));
if (pi != module_priorities.end() && pi->second > found_priority)
{
- info = macro->getMacroInfo();
+ macro_info = module_macro->getMacroInfo();
found_priority = pi->second;
}
}
@@ -465,26 +466,20 @@ ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVec
if (top_level_module != module)
{
ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(top_level_module));
-
+
if ((pi != module_priorities.end()) && pi->second > found_priority)
{
- info = macro->getMacroInfo();
+ macro_info = module_macro->getMacroInfo();
found_priority = pi->second;
}
}
}
- if (!info)
+ if (macro_info)
{
- continue;
- }
-
- if (mi->second.getLatest()->getKind() == clang::MacroDirective::MD_Define)
- {
std::string macro_expansion = "#define ";
macro_expansion.append(mi->first->getName().str().c_str());
-
- if (clang::MacroInfo *macro_info = mi->second.getLatest()->getMacroInfo())
+
{
if (macro_info->isFunctionLike())
{
@@ -560,9 +555,7 @@ ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVec
if (invalid)
{
-#ifdef LLDB_CONFIGURATION_DEBUG
- assert(!"Unhandled token kind");
-#endif
+ lldbassert(!"Unhandled token kind");
macro_expansion.append("<unknown literal value>");
}
else
@@ -594,17 +587,11 @@ ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVec
}
}
}
- }
- else
- {
-#ifdef LLDB_CONFIGURATION_DEBUG
- assert(!"#define with no macro info");
-#endif
- }
-
- if (handler(macro_expansion))
- {
- return;
+
+ if (handler(macro_expansion))
+ {
+ return;
+ }
}
}
}
diff --git a/source/Expression/ClangUserExpression.cpp b/source/Expression/ClangUserExpression.cpp
index 661bab0e4b43..0da70e2b0a70 100644
--- a/source/Expression/ClangUserExpression.cpp
+++ b/source/Expression/ClangUserExpression.cpp
@@ -891,7 +891,8 @@ ClangUserExpression::Execute (Stream &error_stream,
*m_execution_unit_sp.get(),
interpreter_error,
function_stack_bottom,
- function_stack_top);
+ function_stack_top,
+ exe_ctx);
if (!interpreter_error.Success())
{
diff --git a/source/Expression/IRExecutionUnit.cpp b/source/Expression/IRExecutionUnit.cpp
index 7232685e4f41..59c7fb6f786f 100644
--- a/source/Expression/IRExecutionUnit.cpp
+++ b/source/Expression/IRExecutionUnit.cpp
@@ -373,7 +373,7 @@ IRExecutionUnit::GetRunnableInfo(Error &error,
ss.PutCString("\n");
emitNewLine = true;
ss.PutCString(" ");
- ss.PutCString(Mangled(failed_lookup).GetDemangledName().AsCString());
+ ss.PutCString(Mangled(failed_lookup).GetDemangledName(lldb::eLanguageTypeObjC_plus_plus).AsCString());
}
m_failed_lookups.clear();
diff --git a/source/Expression/IRForTarget.cpp b/source/Expression/IRForTarget.cpp
index 11bc011d6d64..cf2a93b3ea7f 100644
--- a/source/Expression/IRForTarget.cpp
+++ b/source/Expression/IRForTarget.cpp
@@ -267,11 +267,11 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun,
{
if (mangled_name.GetMangledName())
m_error_stream->Printf("error: call to a function '%s' ('%s') that is not present in the target\n",
- mangled_name.GetName().GetCString(),
+ mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString(),
mangled_name.GetMangledName().GetCString());
else
m_error_stream->Printf("error: call to a function '%s' that is not present in the target\n",
- mangled_name.GetName().GetCString());
+ mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString());
}
return LookupResult::Fail;
}
diff --git a/source/Expression/IRInterpreter.cpp b/source/Expression/IRInterpreter.cpp
index d11bdc1671b6..926d1f22b6aa 100644
--- a/source/Expression/IRInterpreter.cpp
+++ b/source/Expression/IRInterpreter.cpp
@@ -10,17 +10,28 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Host/Endian.h"
+#include "lldb/Target/ABI.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallFunctionUsingABI.h"
+
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"
@@ -455,7 +466,8 @@ static const char *infinite_loop_error = "Interpreter ran for too m
bool
IRInterpreter::CanInterpret (llvm::Module &module,
llvm::Function &function,
- lldb_private::Error &error)
+ lldb_private::Error &error,
+ const bool support_function_calls)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -507,7 +519,7 @@ IRInterpreter::CanInterpret (llvm::Module &module,
return false;
}
- if (!CanIgnoreCall(call_inst))
+ if (!CanIgnoreCall(call_inst) && !support_function_calls)
{
if (log)
log->Printf("Unsupported instruction: %s", PrintValue(ii).c_str());
@@ -611,7 +623,8 @@ IRInterpreter::Interpret (llvm::Module &module,
lldb_private::IRMemoryMap &memory_map,
lldb_private::Error &error,
lldb::addr_t stack_frame_bottom,
- lldb::addr_t stack_frame_top)
+ lldb::addr_t stack_frame_top,
+ lldb_private::ExecutionContext &exe_ctx)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -668,29 +681,7 @@ IRInterpreter::Interpret (llvm::Module &module,
{
default:
break;
- case Instruction::Call:
- {
- const CallInst *call_inst = dyn_cast<CallInst>(inst);
-
- if (!call_inst)
- {
- if (log)
- log->Printf("getOpcode() returns %s, but instruction is not a CallInst", inst->getOpcodeName());
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
- if (!CanIgnoreCall(call_inst))
- {
- if (log)
- log->Printf("The interpreter shouldn't have accepted %s", PrintValue(call_inst).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
- }
- break;
case Instruction::Add:
case Instruction::Sub:
case Instruction::Mul:
@@ -1476,6 +1467,242 @@ IRInterpreter::Interpret (llvm::Module &module,
}
}
break;
+ case Instruction::Call:
+ {
+ const CallInst *call_inst = dyn_cast<CallInst>(inst);
+
+ if (!call_inst)
+ {
+ if (log)
+ log->Printf("getOpcode() returns %s, but instruction is not a CallInst", inst->getOpcodeName());
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ if (CanIgnoreCall(call_inst))
+ break;
+
+ // Get the return type
+ llvm::Type *returnType = call_inst->getType();
+ if (returnType == nullptr)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("unable to access return type");
+ return false;
+ }
+
+ // Work with void, integer and pointer return types
+ if (!returnType->isVoidTy() &&
+ !returnType->isIntegerTy() &&
+ !returnType->isPointerTy())
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("return type is not supported");
+ return false;
+ }
+
+ // Check we can actually get a thread
+ if (exe_ctx.GetThreadPtr() == nullptr)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("unable to acquire thread");
+ return false;
+ }
+
+ // Make sure we have a valid process
+ if (!exe_ctx.GetProcessPtr())
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("unable to get the process");
+ return false;
+ }
+
+ // Find the address of the callee function
+ lldb_private::Scalar I;
+ const llvm::Value *val = call_inst->getCalledValue();
+
+ if (!frame.EvaluateValue(I, val, module))
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("unable to get address of function");
+ return false;
+ }
+ lldb_private::Address funcAddr(I.ULongLong(LLDB_INVALID_ADDRESS));
+
+ lldb_private::StreamString error_stream;
+ lldb_private::EvaluateExpressionOptions options;
+
+ // We generally receive a function pointer which we must dereference
+ llvm::Type* prototype = val->getType();
+ if (!prototype->isPointerTy())
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("call need function pointer");
+ return false;
+ }
+
+ // Dereference the function pointer
+ prototype = prototype->getPointerElementType();
+ if (!(prototype->isFunctionTy() || prototype->isFunctionVarArg()))
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("call need function pointer");
+ return false;
+ }
+
+ // Find number of arguments
+ const int numArgs = call_inst->getNumArgOperands();
+
+ // We work with a fixed array of 16 arguments which is our upper limit
+ static lldb_private::ABI::CallArgument rawArgs[16];
+ if (numArgs >= 16)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("function takes too many arguments");
+ return false;
+ }
+
+ // Push all function arguments to the argument list that will
+ // be passed to the call function thread plan
+ for (int i = 0; i < numArgs; i++)
+ {
+ // Get details of this argument
+ llvm::Value *arg_op = call_inst->getArgOperand(i);
+ llvm::Type *arg_ty = arg_op->getType();
+
+ // Ensure that this argument is an supported type
+ if (!arg_ty->isIntegerTy() && !arg_ty->isPointerTy())
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("argument %d must be integer type", i);
+ return false;
+ }
+
+ // Extract the arguments value
+ lldb_private::Scalar tmp_op = 0;
+ if (!frame.EvaluateValue(tmp_op, arg_op, module))
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("unable to evaluate argument %d", i);
+ return false;
+ }
+
+ // Check if this is a string literal or constant string pointer
+ if (arg_ty->isPointerTy())
+ {
+ // Pointer to just one type
+ assert(arg_ty->getNumContainedTypes() == 1);
+
+ lldb::addr_t addr = tmp_op.ULongLong();
+ size_t dataSize = 0;
+
+ if (memory_map.GetAllocSize(addr, dataSize))
+ {
+ // Create the required buffer
+ rawArgs[i].size = dataSize;
+ rawArgs[i].data_ap.reset(new uint8_t[dataSize + 1]);
+
+ // Read string from host memory
+ memory_map.ReadMemory(rawArgs[i].data_ap.get(), addr, dataSize, error);
+ if (error.Fail())
+ {
+ assert(!"we have failed to read the string from memory");
+ return false;
+ }
+ // Add null terminator
+ rawArgs[i].data_ap[dataSize] = '\0';
+ rawArgs[i].type = lldb_private::ABI::CallArgument::HostPointer;
+ }
+ else
+ {
+ assert(!"unable to locate host data for transfer to device");
+ return false;
+ }
+ }
+ else /* if ( arg_ty->isPointerTy() ) */
+ {
+ rawArgs[i].type = lldb_private::ABI::CallArgument::TargetValue;
+ // Get argument size in bytes
+ rawArgs[i].size = arg_ty->getIntegerBitWidth() / 8;
+ // Push value into argument list for thread plan
+ rawArgs[i].value = tmp_op.ULongLong();
+ }
+
+ }
+
+ // Pack the arguments into an llvm::array
+ llvm::ArrayRef<lldb_private::ABI::CallArgument> args(rawArgs, numArgs);
+
+ // Setup a thread plan to call the target function
+ lldb::ThreadPlanSP call_plan_sp
+ (
+ new lldb_private::ThreadPlanCallFunctionUsingABI
+ (
+ exe_ctx.GetThreadRef(),
+ funcAddr,
+ *prototype,
+ *returnType,
+ args,
+ options
+ )
+ );
+
+ // Check if the plan is valid
+ if (!call_plan_sp || !call_plan_sp->ValidatePlan(&error_stream))
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("unable to make ThreadPlanCallFunctionUsingABI for 0x%llx", I.ULongLong());
+ return false;
+ }
+
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
+
+ // Execute the actual function call thread plan
+ lldb::ExpressionResults res = exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, error_stream);
+
+ // Check that the thread plan completed successfully
+ if (res != lldb::ExpressionResults::eExpressionCompleted)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("ThreadPlanCallFunctionUsingABI failed");
+ return false;
+ }
+
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
+
+ // Void return type
+ if (returnType->isVoidTy())
+ {
+ // Cant assign to void types, so we leave the frame untouched
+ }
+ else
+ // Integer or pointer return type
+ if (returnType->isIntegerTy() || returnType->isPointerTy())
+ {
+ // Get the encapsulated return value
+ lldb::ValueObjectSP retVal = call_plan_sp.get()->GetReturnValueObject();
+
+ lldb_private::Scalar returnVal = -1;
+ lldb_private::ValueObject *vobj = retVal.get();
+
+ // Check if the return value is valid
+ if (vobj == nullptr || retVal.empty())
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("unable to get the return value");
+ return false;
+ }
+
+ // Extract the return value as a integer
+ lldb_private::Value & value = vobj->GetValue();
+ returnVal = value.GetScalar();
+
+ // Push the return value as the result
+ frame.AssignValue(inst, returnVal, module);
+ }
+ }
+ break;
}
++frame.m_ii;
diff --git a/source/Expression/IRMemoryMap.cpp b/source/Expression/IRMemoryMap.cpp
index a4fe7a968379..4733b16d5f1c 100644
--- a/source/Expression/IRMemoryMap.cpp
+++ b/source/Expression/IRMemoryMap.cpp
@@ -418,6 +418,32 @@ IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
m_allocations.erase(iter);
}
+bool
+IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size)
+{
+ AllocationMap::iterator iter = FindAllocation(address, size);
+ if (iter == m_allocations.end())
+ return false;
+
+ Allocation &al = iter->second;
+
+ if (address > (al.m_process_start + al.m_size))
+ {
+ size = 0;
+ return false;
+ }
+
+ if (address > al.m_process_start)
+ {
+ int dif = address - al.m_process_start;
+ size = al.m_size - dif;
+ return true;
+ }
+
+ size = al.m_size;
+ return true;
+}
+
void
IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
{
diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp
index 20d6355e6195..94c78a015651 100644
--- a/source/Host/common/Host.cpp
+++ b/source/Host/common/Host.cpp
@@ -1070,13 +1070,9 @@ Host::SetCrashDescription (const char *description)
#endif
-#if !defined (__linux__) && !defined (__FreeBSD__) && !defined(__FreeBSD_kernel__) && !defined (__NetBSD__)
-
-const lldb_private::UnixSignalsSP&
-Host::GetUnixSignals ()
+const UnixSignalsSP &
+Host::GetUnixSignals()
{
- static UnixSignalsSP s_unix_signals_sp (new UnixSignals ());
+ static const auto s_unix_signals_sp = UnixSignals::Create(HostInfo::GetArchitecture());
return s_unix_signals_sp;
}
-
-#endif
diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp
index 35003f5d0207..818d69bdabdc 100644
--- a/source/Host/common/NativeProcessProtocol.cpp
+++ b/source/Host/common/NativeProcessProtocol.cpp
@@ -441,3 +441,25 @@ NativeProcessProtocol::Terminate ()
{
// Default implementation does nothing.
}
+
+#ifndef __linux__
+// These need to be implemented to support lldb-gdb-server on a given platform. Stubs are
+// provided to make the rest of the code link on non-supported platforms.
+
+Error
+NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info,
+ NativeDelegate &native_delegate,
+ NativeProcessProtocolSP &process_sp)
+{
+ llvm_unreachable("Platform has no NativeProcessProtocol support");
+}
+
+Error
+NativeProcessProtocol::Attach (lldb::pid_t pid,
+ NativeDelegate &native_delegate,
+ NativeProcessProtocolSP &process_sp)
+{
+ llvm_unreachable("Platform has no NativeProcessProtocol support");
+}
+
+#endif
diff --git a/source/Host/common/StringConvert.cpp b/source/Host/common/StringConvert.cpp
index 0a8e75f4b877..c4ff67515d4e 100644
--- a/source/Host/common/StringConvert.cpp
+++ b/source/Host/common/StringConvert.cpp
@@ -15,79 +15,103 @@
// Project includes
#include "lldb/Host/StringConvert.h"
-namespace lldb_private {
-
-namespace StringConvert {
-
-int32_t
-ToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr)
+namespace lldb_private
{
- if (s && s[0])
+ namespace StringConvert
{
- char *end = nullptr;
- const long sval = ::strtol (s, &end, base);
- if (*end == '\0')
+
+ int32_t
+ ToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr)
{
+ if (s && s[0])
+ {
+ char *end = nullptr;
+ const long sval = ::strtol (s, &end, base);
+ if (*end == '\0')
+ {
+ if (success_ptr)
+ *success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN));
+ return (int32_t)sval; // All characters were used, return the result
+ }
+ }
if (success_ptr)
- *success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN));
- return (int32_t)sval; // All characters were used, return the result
+ *success_ptr = false;
+ return fail_value;
}
- }
- if (success_ptr) *success_ptr = false;
- return fail_value;
-}
-uint32_t
-ToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr)
-{
- if (s && s[0])
- {
- char *end = nullptr;
- const unsigned long uval = ::strtoul (s, &end, base);
- if (*end == '\0')
+ uint32_t
+ ToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr)
{
+ if (s && s[0])
+ {
+ char *end = nullptr;
+ const unsigned long uval = ::strtoul (s, &end, base);
+ if (*end == '\0')
+ {
+ if (success_ptr)
+ *success_ptr = (uval <= UINT32_MAX);
+ return (uint32_t)uval; // All characters were used, return the result
+ }
+ }
if (success_ptr)
- *success_ptr = (uval <= UINT32_MAX);
- return (uint32_t)uval; // All characters were used, return the result
+ *success_ptr = false;
+ return fail_value;
}
- }
- if (success_ptr) *success_ptr = false;
- return fail_value;
-}
-int64_t
-ToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr)
-{
- if (s && s[0])
- {
- char *end = nullptr;
- int64_t uval = ::strtoll (s, &end, base);
- if (*end == '\0')
+ int64_t
+ ToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr)
{
- if (success_ptr) *success_ptr = true;
- return uval; // All characters were used, return the result
+ if (s && s[0])
+ {
+ char *end = nullptr;
+ int64_t uval = ::strtoll (s, &end, base);
+ if (*end == '\0')
+ {
+ if (success_ptr)
+ *success_ptr = true;
+ return uval; // All characters were used, return the result
+ }
+ }
+ if (success_ptr)
+ *success_ptr = false;
+ return fail_value;
}
- }
- if (success_ptr) *success_ptr = false;
- return fail_value;
-}
-uint64_t
-ToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr)
-{
- if (s && s[0])
- {
- char *end = nullptr;
- uint64_t uval = ::strtoull (s, &end, base);
- if (*end == '\0')
+ uint64_t
+ ToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr)
{
- if (success_ptr) *success_ptr = true;
- return uval; // All characters were used, return the result
+ if (s && s[0])
+ {
+ char *end = nullptr;
+ uint64_t uval = ::strtoull (s, &end, base);
+ if (*end == '\0')
+ {
+ if (success_ptr)
+ *success_ptr = true;
+ return uval; // All characters were used, return the result
+ }
+ }
+ if (success_ptr) *success_ptr = false;
+ return fail_value;
}
- }
- if (success_ptr) *success_ptr = false;
- return fail_value;
-}
-}
+ double
+ ToDouble (const char *s, double fail_value, bool *success_ptr)
+ {
+ if (s && s[0])
+ {
+ char *end = nullptr;
+ double val = strtod (s, &end);
+ if (*end == '\0')
+ {
+ if (success_ptr)
+ *success_ptr = true;
+ return val; // All characters were used, return the result
+ }
+ }
+ if (success_ptr)
+ *success_ptr = false;
+ return fail_value;
+ }
+ }
}
diff --git a/source/Host/freebsd/Host.cpp b/source/Host/freebsd/Host.cpp
index 8b1c580af27d..7f8d7ae96e7a 100644
--- a/source/Host/freebsd/Host.cpp
+++ b/source/Host/freebsd/Host.cpp
@@ -40,8 +40,6 @@
#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/NameMatches.h"
-#include "Plugins/Process/Utility/FreeBSDSignals.h"
-
#include "llvm/Support/Host.h"
extern "C" {
@@ -277,13 +275,6 @@ Host::GetAuxvData(lldb_private::Process *process)
return buf_sp;
}
-const UnixSignalsSP&
-Host::GetUnixSignals ()
-{
- static const lldb_private::UnixSignalsSP s_unix_signals_sp (new FreeBSDSignals ());
- return s_unix_signals_sp;
-}
-
Error
Host::ShellExpandArguments (ProcessLaunchInfo &launch_info)
{
diff --git a/source/Host/posix/MainLoopPosix.cpp b/source/Host/posix/MainLoopPosix.cpp
new file mode 100644
index 000000000000..cb213b9b79f1
--- /dev/null
+++ b/source/Host/posix/MainLoopPosix.cpp
@@ -0,0 +1,193 @@
+//===-- MainLoopPosix.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/posix/MainLoopPosix.h"
+
+#include <vector>
+
+#include "lldb/Core/Error.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static sig_atomic_t g_signal_flags[NSIG];
+
+static void
+SignalHandler(int signo, siginfo_t *info, void *)
+{
+ assert(signo < NSIG);
+ g_signal_flags[signo] = 1;
+}
+
+
+MainLoopPosix::~MainLoopPosix()
+{
+ assert(m_read_fds.size() == 0);
+ assert(m_signals.size() == 0);
+}
+
+MainLoopPosix::ReadHandleUP
+MainLoopPosix::RegisterReadObject(const IOObjectSP &object_sp, const Callback &callback, Error &error)
+{
+ if (!object_sp || !object_sp->IsValid())
+ {
+ error.SetErrorString("IO object is not valid.");
+ return nullptr;
+ }
+
+ const bool inserted = m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second;
+ if (! inserted)
+ {
+ error.SetErrorStringWithFormat("File descriptor %d already monitored.",
+ object_sp->GetWaitableHandle());
+ return nullptr;
+ }
+
+ return CreateReadHandle(object_sp);
+}
+
+// We shall block the signal, then install the signal handler. The signal will be unblocked in
+// the Run() function to check for signal delivery.
+MainLoopPosix::SignalHandleUP
+MainLoopPosix::RegisterSignal(int signo, const Callback &callback, Error &error)
+{
+ if (m_signals.find(signo) != m_signals.end())
+ {
+ error.SetErrorStringWithFormat("Signal %d already monitored.", signo);
+ return nullptr;
+ }
+
+ SignalInfo info;
+ info.callback = callback;
+ struct sigaction new_action;
+ new_action.sa_sigaction = &SignalHandler;
+ new_action.sa_flags = SA_SIGINFO;
+ sigemptyset(&new_action.sa_mask);
+ sigaddset(&new_action.sa_mask, signo);
+
+ sigset_t old_set;
+ if (int ret = pthread_sigmask(SIG_BLOCK, &new_action.sa_mask, &old_set))
+ {
+ error.SetErrorStringWithFormat("pthread_sigmask failed with error %d\n", ret);
+ return nullptr;
+ }
+
+ info.was_blocked = sigismember(&old_set, signo);
+ if (sigaction(signo, &new_action, &info.old_action) == -1)
+ {
+ error.SetErrorToErrno();
+ if (!info.was_blocked)
+ pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, nullptr);
+ return nullptr;
+ }
+
+ m_signals.insert({signo, info});
+ g_signal_flags[signo] = 0;
+
+ return SignalHandleUP(new SignalHandle(*this, signo));
+}
+
+void
+MainLoopPosix::UnregisterReadObject(const lldb::IOObjectSP &object_sp)
+{
+ bool erased = m_read_fds.erase(object_sp->GetWaitableHandle());
+ (void) erased;
+ assert(erased);
+}
+
+void
+MainLoopPosix::UnregisterSignal(int signo)
+{
+ // We undo the actions of RegisterSignal on a best-effort basis.
+ auto it = m_signals.find(signo);
+ assert(it != m_signals.end());
+
+ sigaction(signo, &it->second.old_action, nullptr);
+
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set, signo);
+ pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set, nullptr);
+
+ m_signals.erase(it);
+}
+
+Error
+MainLoopPosix::Run()
+{
+ std::vector<int> signals;
+ sigset_t sigmask;
+ std::vector<int> read_fds;
+ fd_set read_fd_set;
+ m_terminate_request = false;
+
+ // run until termination or until we run out of things to listen to
+ while (! m_terminate_request && (!m_read_fds.empty() || !m_signals.empty()))
+ {
+ // To avoid problems with callbacks changing the things we're supposed to listen to, we
+ // will store the *real* list of events separately.
+ signals.clear();
+ read_fds.clear();
+ FD_ZERO(&read_fd_set);
+ int nfds = 0;
+
+ if (int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask))
+ return Error("pthread_sigmask failed with error %d\n", ret);
+
+ for (const auto &fd: m_read_fds)
+ {
+ read_fds.push_back(fd.first);
+ FD_SET(fd.first, &read_fd_set);
+ nfds = std::max(nfds, fd.first+1);
+ }
+
+ for (const auto &sig: m_signals)
+ {
+ signals.push_back(sig.first);
+ sigdelset(&sigmask, sig.first);
+ }
+
+ if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == -1 && errno != EINTR)
+ return Error(errno, eErrorTypePOSIX);
+
+ for (int sig: signals)
+ {
+ if (g_signal_flags[sig] == 0)
+ continue; // No signal
+ g_signal_flags[sig] = 0;
+
+ auto it = m_signals.find(sig);
+ if (it == m_signals.end())
+ continue; // Signal must have gotten unregistered in the meantime
+
+ it->second.callback(*this); // Do the work
+
+ if (m_terminate_request)
+ return Error();
+ }
+
+ for (int fd: read_fds)
+ {
+ if (!FD_ISSET(fd, &read_fd_set))
+ continue; // Not ready
+
+ auto it = m_read_fds.find(fd);
+ if (it == m_read_fds.end())
+ continue; // File descriptor must have gotten unregistered in the meantime
+
+ it->second(*this); // Do the work
+
+ if (m_terminate_request)
+ return Error();
+ }
+ }
+ return Error();
+}
+
+
diff --git a/source/Initialization/SystemInitializerCommon.cpp b/source/Initialization/SystemInitializerCommon.cpp
index 35189c103f7c..51f32a2776a8 100644
--- a/source/Initialization/SystemInitializerCommon.cpp
+++ b/source/Initialization/SystemInitializerCommon.cpp
@@ -17,6 +17,7 @@
#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
+#include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h"
#include "Plugins/Instruction/ARM/EmulateInstructionARM.h"
#include "Plugins/Instruction/MIPS/EmulateInstructionMIPS.h"
#include "Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h"
@@ -106,6 +107,7 @@ SystemInitializerCommon::Initialize()
ObjectFileELF::Initialize();
ObjectFilePECOFF::Initialize();
DynamicLoaderPOSIXDYLD::Initialize();
+ DynamicLoaderWindowsDYLD::Initialize();
platform_freebsd::PlatformFreeBSD::Initialize();
platform_linux::PlatformLinux::Initialize();
PlatformWindows::Initialize();
@@ -152,6 +154,7 @@ SystemInitializerCommon::Terminate()
ObjectFileELF::Terminate();
ObjectFilePECOFF::Terminate();
DynamicLoaderPOSIXDYLD::Terminate();
+ DynamicLoaderWindowsDYLD::Terminate();
platform_freebsd::PlatformFreeBSD::Terminate();
platform_linux::PlatformLinux::Terminate();
PlatformWindows::Terminate();
diff --git a/source/Interpreter/CommandObject.cpp b/source/Interpreter/CommandObject.cpp
index d67f76eba7b6..c0efd9e33c08 100644
--- a/source/Interpreter/CommandObject.cpp
+++ b/source/Interpreter/CommandObject.cpp
@@ -10,6 +10,7 @@
#include "lldb/Interpreter/CommandObject.h"
#include <string>
+#include <sstream>
#include <map>
#include <stdlib.h>
@@ -921,6 +922,27 @@ ExprPathHelpTextCallback()
}
void
+CommandObject::FormatLongHelpText (Stream &output_strm, const char *long_help)
+{
+ CommandInterpreter& interpreter = GetCommandInterpreter();
+ std::stringstream lineStream (long_help);
+ std::string line;
+ while (std::getline (lineStream, line)) {
+ if (line.empty()) {
+ output_strm << "\n";
+ continue;
+ }
+ size_t result = line.find_first_not_of (" \t");
+ if (result == std::string::npos) {
+ result = 0;
+ }
+ std::string whitespace_prefix = line.substr (0, result);
+ std::string remainder = line.substr (result);
+ interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix.c_str(), remainder.c_str());
+ }
+}
+
+void
CommandObject::GenerateHelpText (CommandReturnObject &result)
{
GenerateHelpText(result.GetOutputStream());
@@ -947,7 +969,7 @@ CommandObject::GenerateHelpText (Stream &output_strm)
const char *long_help = GetHelpLong();
if ((long_help != nullptr)
&& (strlen (long_help) > 0))
- output_strm.Printf ("\n%s", long_help);
+ FormatLongHelpText (output_strm, long_help);
if (WantsRawCommandString() && !WantsCompletion())
{
// Emit the message about using ' -- ' between the end of the command options and the raw input
@@ -984,7 +1006,7 @@ CommandObject::GenerateHelpText (Stream &output_strm)
const char *long_help = GetHelpLong();
if ((long_help != nullptr)
&& (strlen (long_help) > 0))
- output_strm.Printf ("%s", long_help);
+ FormatLongHelpText (output_strm, long_help);
else if (WantsRawCommandString())
{
std::string help_text (GetHelp());
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
index 0853fe286963..4204d18769b8 100644
--- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
@@ -236,7 +236,8 @@ ABISP
ABIMacOSX_i386::CreateInstance (const ArchSpec &arch)
{
static ABISP g_abi_sp;
- if (arch.GetTriple().getArch() == llvm::Triple::x86)
+ if ((arch.GetTriple().getArch() == llvm::Triple::x86) &&
+ (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS()))
{
if (!g_abi_sp)
g_abi_sp.reset (new ABIMacOSX_i386);
diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
index e9e68bc0e949..69129df1f16b 100644
--- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
+++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
@@ -257,7 +257,7 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
sp -= argSize;
// write this argument onto the stack of the host process
- proc.get( )->WriteMemory( sp, arg.data, arg.size, error );
+ proc.get( )->WriteMemory( sp, arg.data_ap.get(), arg.size, error );
if ( error.Fail( ) )
return false;
diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
index bbafcf73fa16..2308129b8cab 100644
--- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
+++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
@@ -168,6 +168,9 @@ DynamicLoaderHexagonDYLD::DidAttach()
// Disable JIT for hexagon targets because its not supported
m_process->SetCanJIT(false);
+ // Enable Interpreting of function call expressions
+ m_process->SetCanInterpretFunctionCalls(true);
+
// Add the current executable to the module list
ModuleList module_list;
module_list.Append(executable);
@@ -500,7 +503,7 @@ DynamicLoaderHexagonDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop
if (sym == NULL || !sym->IsTrampoline())
return thread_plan_sp;
- const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled);
+ const ConstString sym_name = sym->GetMangled().GetName(lldb::eLanguageTypeUnknown, Mangled::ePreferMangled);
if (!sym_name)
return thread_plan_sp;
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 6330b42ca14a..8724fc039cb9 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -458,7 +458,7 @@ DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop)
if (sym == NULL || !sym->IsTrampoline())
return thread_plan_sp;
- const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled);
+ ConstString sym_name = sym->GetName();
if (!sym_name)
return thread_plan_sp;
@@ -667,7 +667,9 @@ DynamicLoaderPOSIXDYLD::ResolveExecutableModule (lldb::ModuleSP &module_sp)
if (module_sp && module_sp->MatchesModuleSpec (module_spec))
return;
- auto error = platform_sp->ResolveExecutable (module_spec, module_sp, nullptr);
+ const auto executable_search_paths (Target::GetDefaultExecutableSearchPaths());
+ auto error = platform_sp->ResolveExecutable (
+ module_spec, module_sp, !executable_search_paths.IsEmpty() ? &executable_search_paths : nullptr);
if (error.Fail ())
{
StreamString stream;
diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
new file mode 100644
index 000000000000..56b56ab3a194
--- /dev/null
+++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
@@ -0,0 +1,102 @@
+//===-- DynamicLoaderWindowsDYLD.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DynamicLoaderWindowsDYLD.h"
+
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "llvm/ADT/Triple.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+DynamicLoaderWindowsDYLD::DynamicLoaderWindowsDYLD(Process *process)
+ : DynamicLoader(process)
+{
+
+}
+
+DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD()
+{
+
+}
+
+void DynamicLoaderWindowsDYLD::Initialize()
+{
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ CreateInstance);
+}
+
+void DynamicLoaderWindowsDYLD::Terminate()
+{
+
+}
+
+ConstString DynamicLoaderWindowsDYLD::GetPluginNameStatic()
+{
+ static ConstString g_plugin_name("windows-dyld");
+ return g_plugin_name;
+}
+
+const char *DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic()
+{
+ return "Dynamic loader plug-in that watches for shared library "
+ "loads/unloads in Windows processes.";
+}
+
+
+DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool force)
+{
+ bool should_create = force;
+ if (!should_create)
+ {
+ const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
+ if (triple_ref.getOS() == llvm::Triple::Win32)
+ should_create = true;
+ }
+
+ if (should_create)
+ return new DynamicLoaderWindowsDYLD (process);
+
+ return nullptr;
+}
+
+void DynamicLoaderWindowsDYLD::DidAttach()
+{
+
+}
+
+void DynamicLoaderWindowsDYLD::DidLaunch()
+{
+
+}
+
+Error DynamicLoaderWindowsDYLD::CanLoadImage()
+{
+ return Error();
+}
+
+ConstString DynamicLoaderWindowsDYLD::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t DynamicLoaderWindowsDYLD::GetPluginVersion()
+{
+ return 1;
+}
+
+ThreadPlanSP
+DynamicLoaderWindowsDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop)
+{
+ return ThreadPlanSP();
+}
diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h
new file mode 100644
index 000000000000..d12b999f4627
--- /dev/null
+++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h
@@ -0,0 +1,43 @@
+//===-- DynamicLoaderWindowsDYLDh ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_H_
+#define liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_H_
+
+#include "lldb/lldb-forward.h"
+#include "lldb/Target/DynamicLoader.h"
+
+namespace lldb_private
+{
+
+class DynamicLoaderWindowsDYLD : public DynamicLoader
+{
+ public:
+ DynamicLoaderWindowsDYLD(Process *process);
+ virtual ~DynamicLoaderWindowsDYLD();
+
+ static void Initialize();
+ static void Terminate();
+ static ConstString GetPluginNameStatic();
+ static const char *GetPluginDescriptionStatic();
+
+ static DynamicLoader *CreateInstance(Process *process, bool force);
+
+ void DidAttach () override;
+ void DidLaunch () override;
+ Error CanLoadImage () override;
+ lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, bool stop) override;
+
+ ConstString GetPluginName() override;
+ uint32_t GetPluginVersion() override;
+};
+
+}
+
+#endif
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index 7d21b779ebd2..3a3878ef09a1 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -106,7 +106,7 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
Symbol *symbol = sc.symbol;
if (symbol != NULL)
{
- const char *name = symbol->GetMangled().GetDemangledName().AsCString();
+ const char *name = symbol->GetMangled().GetDemangledName(lldb::eLanguageTypeC_plus_plus).AsCString();
if (name && strstr(name, vtable_demangled_prefix) == name)
{
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index f9cec2415382..5fc83f06157c 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -1558,7 +1558,7 @@ ObjectFileELF::GetSegmentDataByIndex(lldb::user_id_t id)
std::string
ObjectFileELF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const
{
- size_t pos = symbol_name.find("@");
+ size_t pos = symbol_name.find('@');
return symbol_name.substr(0, pos).str();
}
@@ -1795,7 +1795,16 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
static ConstString bss_section_name(".bss");
static ConstString opd_section_name(".opd"); // For ppc64
- //StreamFile strm(stdout, false);
+ // On Android the oatdata and the oatexec symbols in system@framework@boot.oat covers the full
+ // .text section what causes issues with displaying unusable symbol name to the user and very
+ // slow unwinding speed because the instruction emulation based unwind plans try to emulate all
+ // instructions in these symbols. Don't add these symbols to the symbol list as they have no
+ // use for the debugger and they are causing a lot of trouble.
+ // Filtering can't be restricted to Android because this special object file don't contain the
+ // note section specifying the environment to Android but the custom extension and file name
+ // makes it highly unlikely that this will collide with anything else.
+ bool skip_oatdata_oatexec = m_file.GetFilename() == ConstString("system@framework@boot.oat");
+
unsigned i;
for (i = 0; i < num_symbols; ++i)
{
@@ -1809,7 +1818,10 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
(symbol_name == NULL || symbol_name[0] == '\0'))
continue;
- //symbol.Dump (&strm, i, &strtab_data, section_list);
+ // Skipping oatdata and oatexec sections if it is requested. See details above the
+ // definition of skip_oatdata_oatexec for the reasons.
+ if (skip_oatdata_oatexec && (::strcmp(symbol_name, "oatdata") == 0 || ::strcmp(symbol_name, "oatexec") == 0))
+ continue;
SectionSP symbol_section_sp;
SymbolType symbol_type = eSymbolTypeInvalid;
@@ -2031,8 +2043,9 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
if (! mangled_name.empty())
mangled.SetMangledName( ConstString((mangled_name + suffix).str()) );
- llvm::StringRef demangled_name = mangled.GetDemangledName().GetStringRef();
- if (! demangled_name.empty())
+ ConstString demangled = mangled.GetDemangledName(lldb::eLanguageTypeUnknown);
+ llvm::StringRef demangled_name = demangled.GetStringRef();
+ if (!demangled_name.empty())
mangled.SetDemangledName( ConstString((demangled_name + suffix).str()) );
}
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index fe425e02103b..b4f841a16dec 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -535,6 +535,14 @@ PlatformPOSIX::CalculateMD5 (const FileSpec& file_spec,
return false;
}
+const lldb::UnixSignalsSP &
+PlatformPOSIX::GetRemoteUnixSignals() {
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetRemoteUnixSignals();
+ return Platform::GetRemoteUnixSignals();
+}
+
+
FileSpec
PlatformPOSIX::GetRemoteWorkingDirectory()
{
@@ -785,9 +793,6 @@ PlatformPOSIX::Attach (ProcessAttachInfo &attach_info,
if (process_sp)
{
- // Set UnixSignals appropriately.
- process_sp->SetUnixSignals (Host::GetUnixSignals ());
-
auto listener_sp = attach_info.GetHijackListener();
if (listener_sp == nullptr)
{
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
index 19a3f0c4eef1..82686dcef6b0 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -109,6 +109,9 @@ public:
lldb_private::ArchSpec
GetRemoteSystemArchitecture () override;
+ const lldb::UnixSignalsSP &
+ GetRemoteUnixSignals() override;
+
size_t
GetEnvironment (lldb_private::StringList &environment) override;
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index df0484c4e69b..b0e75d4f3457 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -32,6 +32,8 @@
#include "Utility/UriParser.h"
+#include "Plugins/Process/Utility/GDBRemoteSignals.h"
+
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::platform_gdb_server;
@@ -139,13 +141,14 @@ PlatformRemoteGDBServer::ResolveExecutable (const ModuleSpec &module_spec,
// Resolve any executable within an apk on Android?
//Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
- if (resolved_module_spec.GetFileSpec().Exists())
+ if (resolved_module_spec.GetFileSpec().Exists() ||
+ module_spec.GetUUID().IsValid())
{
if (resolved_module_spec.GetArchitecture().IsValid() || resolved_module_spec.GetUUID().IsValid())
{
error = ModuleList::GetSharedModule (resolved_module_spec,
exe_module_sp,
- NULL,
+ module_search_paths_ptr,
NULL,
NULL);
@@ -161,7 +164,7 @@ PlatformRemoteGDBServer::ResolveExecutable (const ModuleSpec &module_spec,
{
error = ModuleList::GetSharedModule (resolved_module_spec,
exe_module_sp,
- NULL,
+ module_search_paths_ptr,
NULL,
NULL);
// Did we find an executable using one of the
@@ -413,6 +416,7 @@ PlatformRemoteGDBServer::DisconnectRemote ()
{
Error error;
m_gdb_client.Disconnect(&error);
+ m_remote_signals_sp.reset();
return error;
}
@@ -871,6 +875,97 @@ PlatformRemoteGDBServer::RunShellCommand(const char *command, // Shoul
void
PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames ()
-{
+{
m_trap_handlers.push_back (ConstString ("_sigtramp"));
}
+
+const UnixSignalsSP &
+PlatformRemoteGDBServer::GetRemoteUnixSignals()
+{
+ if (!IsConnected())
+ return Platform::GetRemoteUnixSignals();
+
+ if (m_remote_signals_sp)
+ return m_remote_signals_sp;
+
+ // If packet not implemented or JSON failed to parse,
+ // we'll guess the signal set based on the remote architecture.
+ m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture());
+
+ const char packet[] = "jSignalsInfo";
+ StringExtractorGDBRemote response;
+ auto result = m_gdb_client.SendPacketAndWaitForResponse(
+ packet, strlen(packet), response, false);
+
+ if (result != decltype(result)::Success ||
+ response.GetResponseType() != response.eResponse)
+ return m_remote_signals_sp;
+
+ auto object_sp = StructuredData::ParseJSON(response.GetStringRef());
+ if (!object_sp || !object_sp->IsValid())
+ return m_remote_signals_sp;
+
+ auto array_sp = object_sp->GetAsArray();
+ if (!array_sp || !array_sp->IsValid())
+ return m_remote_signals_sp;
+
+ auto remote_signals_sp = std::make_shared<lldb_private::GDBRemoteSignals>();
+
+ bool done = array_sp->ForEach(
+ [&remote_signals_sp](StructuredData::Object *object) -> bool
+ {
+ if (!object || !object->IsValid())
+ return false;
+
+ auto dict = object->GetAsDictionary();
+ if (!dict || !dict->IsValid())
+ return false;
+
+ // Signal number and signal name are required.
+ int signo;
+ if (!dict->GetValueForKeyAsInteger("signo", signo))
+ return false;
+
+ std::string name;
+ if (!dict->GetValueForKeyAsString("name", name))
+ return false;
+
+ // We can live without short_name, description, etc.
+ std::string short_name{""};
+ auto object_sp = dict->GetValueForKey("short_name");
+ if (object_sp && object_sp->IsValid())
+ short_name = object_sp->GetStringValue();
+
+ bool suppress{false};
+ object_sp = dict->GetValueForKey("suppress");
+ if (object_sp && object_sp->IsValid())
+ suppress = object_sp->GetBooleanValue();
+
+ bool stop{false};
+ object_sp = dict->GetValueForKey("stop");
+ if (object_sp && object_sp->IsValid())
+ stop = object_sp->GetBooleanValue();
+
+ bool notify{false};
+ object_sp = dict->GetValueForKey("notify");
+ if (object_sp && object_sp->IsValid())
+ notify = object_sp->GetBooleanValue();
+
+ std::string description{""};
+ object_sp = dict->GetValueForKey("description");
+ if (object_sp && object_sp->IsValid())
+ description = object_sp->GetStringValue();
+
+ remote_signals_sp->AddSignal(signo,
+ name.c_str(),
+ short_name.c_str(),
+ suppress, stop, notify,
+ description.c_str());
+ return true;
+ });
+
+ if (done)
+ m_remote_signals_sp = std::move(remote_signals_sp);
+
+ return m_remote_signals_sp;
+}
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
index 1d97b4dbc683..0bf013fdfb68 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -18,6 +18,7 @@
// Project includes
#include "lldb/Target/Platform.h"
#include "../../Process/gdb-remote/GDBRemoteCommunicationClient.h"
+#include "Plugins/Process/Utility/GDBRemoteSignals.h"
namespace lldb_private {
namespace platform_gdb_server {
@@ -213,12 +214,17 @@ public:
void
CalculateTrapHandlerSymbolNames () override;
+ const lldb::UnixSignalsSP &
+ GetRemoteUnixSignals() override;
+
protected:
process_gdb_remote::GDBRemoteCommunicationClient m_gdb_client;
std::string m_platform_description; // After we connect we can get a more complete description of what we are connected to
std::string m_platform_scheme;
std::string m_platform_hostname;
+ lldb::UnixSignalsSP m_remote_signals_sp;
+
// Launch the lldb-gdbserver on the remote host and return the port it is listening on or 0 on
// failure. Subclasses should override this method if they want to do extra actions before or
// after launching the lldb-gdbserver.
diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
index cce7a1ef28c1..5e46c836beac 100644
--- a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
+++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
@@ -46,7 +46,7 @@ FreeBSDThread::WillResume(lldb::StateType resume_state)
ProcessSP process_sp(GetProcess());
ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(process_sp.get());
int signo = GetResumeSignal();
- bool signo_valid = process->GetUnixSignals().SignalIsValid(signo);
+ bool signo_valid = process->GetUnixSignals()->SignalIsValid(signo);
switch (resume_state)
{
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index 28bca0916148..427c66ce3e6b 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -1297,7 +1297,7 @@ ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
if (log)
log->Printf ("ProcessMonitor::%s() received signal %s with code %s, pid = %d",
__FUNCTION__,
- monitor->m_process->GetUnixSignals().GetSignalAsCString (signo),
+ monitor->m_process->GetUnixSignals()->GetSignalAsCString (signo),
"SI_USER",
info->si_pid);
if (info->si_pid == getpid())
@@ -1307,7 +1307,7 @@ ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
}
if (log)
- log->Printf ("ProcessMonitor::%s() received signal %s", __FUNCTION__, monitor->m_process->GetUnixSignals().GetSignalAsCString (signo));
+ log->Printf ("ProcessMonitor::%s() received signal %s", __FUNCTION__, monitor->m_process->GetUnixSignals()->GetSignalAsCString (signo));
switch (signo)
{
@@ -1483,7 +1483,7 @@ ProcessMonitor::Resume(lldb::tid_t unused, uint32_t signo)
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
if (log) {
- const char *signame = m_process->GetUnixSignals().GetSignalAsCString (signo);
+ const char *signame = m_process->GetUnixSignals()->GetSignalAsCString (signo);
if (signame == nullptr)
signame = "<none>";
log->Printf("ProcessMonitor::%s() resuming pid %" PRIu64 " with signal %s",
diff --git a/source/Plugins/Process/FreeBSD/ProcessPOSIX.h b/source/Plugins/Process/FreeBSD/ProcessPOSIX.h
index 70694cb9b193..627017c547dc 100644
--- a/source/Plugins/Process/FreeBSD/ProcessPOSIX.h
+++ b/source/Plugins/Process/FreeBSD/ProcessPOSIX.h
@@ -33,7 +33,7 @@ public:
//------------------------------------------------------------------
ProcessPOSIX(lldb_private::Target& target,
lldb_private::Listener &listener,
- lldb_private::UnixSignalsSP &unix_signals_sp);
+ lldb::UnixSignalsSP &unix_signals_sp);
virtual
~ProcessPOSIX();
diff --git a/source/Plugins/Process/Utility/FreeBSDSignals.cpp b/source/Plugins/Process/Utility/FreeBSDSignals.cpp
index f082e143059c..c143d36e87c7 100644
--- a/source/Plugins/Process/Utility/FreeBSDSignals.cpp
+++ b/source/Plugins/Process/Utility/FreeBSDSignals.cpp
@@ -13,6 +13,8 @@
// Project includes
#include "FreeBSDSignals.h"
+using namespace lldb_private;
+
FreeBSDSignals::FreeBSDSignals()
: UnixSignals()
{
diff --git a/source/Plugins/Process/Utility/FreeBSDSignals.h b/source/Plugins/Process/Utility/FreeBSDSignals.h
index 1e14ccb9fc4d..b715c62c81e9 100644
--- a/source/Plugins/Process/Utility/FreeBSDSignals.h
+++ b/source/Plugins/Process/Utility/FreeBSDSignals.h
@@ -13,16 +13,19 @@
// Project includes
#include "lldb/Target/UnixSignals.h"
+namespace lldb_private {
+
/// FreeBSD specific set of Unix signals.
-class FreeBSDSignals
- : public lldb_private::UnixSignals
+class FreeBSDSignals : public UnixSignals
{
public:
FreeBSDSignals();
private:
void
- Reset();
+ Reset() override;
};
+} // namespace lldb_private
+
#endif // liblldb_FreeBSDSignals_H_
diff --git a/source/Plugins/Process/Utility/GDBRemoteSignals.cpp b/source/Plugins/Process/Utility/GDBRemoteSignals.cpp
new file mode 100644
index 000000000000..4e355c63b3aa
--- /dev/null
+++ b/source/Plugins/Process/Utility/GDBRemoteSignals.cpp
@@ -0,0 +1,32 @@
+//===-- GDBRemoteSignals.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "GDBRemoteSignals.h"
+
+using namespace lldb_private;
+
+GDBRemoteSignals::GDBRemoteSignals()
+ : UnixSignals()
+{
+ Reset();
+}
+
+GDBRemoteSignals::GDBRemoteSignals(const lldb::UnixSignalsSP &rhs)
+ : UnixSignals(*rhs)
+{
+}
+
+void
+GDBRemoteSignals::Reset()
+{
+ m_signals.clear();
+}
diff --git a/source/Plugins/Process/Utility/GDBRemoteSignals.h b/source/Plugins/Process/Utility/GDBRemoteSignals.h
new file mode 100644
index 000000000000..bbb631a14090
--- /dev/null
+++ b/source/Plugins/Process/Utility/GDBRemoteSignals.h
@@ -0,0 +1,36 @@
+//===-- GDBRemoteSignals.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GDBRemoteSignals_H_
+#define liblldb_GDBRemoteSignals_H_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/UnixSignals.h"
+
+namespace lldb_private {
+
+/// Empty set of Unix signals to be filled by PlatformRemoteGDBServer
+class GDBRemoteSignals : public UnixSignals
+{
+public:
+ GDBRemoteSignals();
+
+ GDBRemoteSignals(const lldb::UnixSignalsSP &rhs);
+
+private:
+ void
+ Reset() override;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_GDBRemoteSignals_H_
diff --git a/source/Plugins/Process/Utility/LinuxSignals.cpp b/source/Plugins/Process/Utility/LinuxSignals.cpp
index 0680d268233c..cd1fc8165eb9 100644
--- a/source/Plugins/Process/Utility/LinuxSignals.cpp
+++ b/source/Plugins/Process/Utility/LinuxSignals.cpp
@@ -12,7 +12,7 @@
// Project includes
#include "LinuxSignals.h"
-using namespace lldb_private::process_linux;
+using namespace lldb_private;
LinuxSignals::LinuxSignals()
: UnixSignals()
diff --git a/source/Plugins/Process/Utility/LinuxSignals.h b/source/Plugins/Process/Utility/LinuxSignals.h
index 5102bcb95e74..dd9062f040a2 100644
--- a/source/Plugins/Process/Utility/LinuxSignals.h
+++ b/source/Plugins/Process/Utility/LinuxSignals.h
@@ -17,21 +17,18 @@
#include "lldb/Target/UnixSignals.h"
namespace lldb_private {
-namespace process_linux {
- /// Linux specific set of Unix signals.
- class LinuxSignals
- : public lldb_private::UnixSignals
- {
- public:
- LinuxSignals();
+/// Linux specific set of Unix signals.
+class LinuxSignals : public UnixSignals
+{
+public:
+ LinuxSignals();
- private:
- void
- Reset();
- };
+private:
+ void
+ Reset() override;
+};
} // namespace lldb_private
-} // namespace process_linux
-#endif
+#endif // liblldb_LinuxSignals_H_
diff --git a/source/Plugins/Process/Utility/MipsLinuxSignals.cpp b/source/Plugins/Process/Utility/MipsLinuxSignals.cpp
index e4e654626eaa..1dc0be81c0ae 100644
--- a/source/Plugins/Process/Utility/MipsLinuxSignals.cpp
+++ b/source/Plugins/Process/Utility/MipsLinuxSignals.cpp
@@ -12,7 +12,7 @@
// Project includes
#include "MipsLinuxSignals.h"
-using namespace lldb_private::process_linux;
+using namespace lldb_private;
MipsLinuxSignals::MipsLinuxSignals()
: UnixSignals()
diff --git a/source/Plugins/Process/Utility/MipsLinuxSignals.h b/source/Plugins/Process/Utility/MipsLinuxSignals.h
index 2e603fbbdf3c..a5041b50eea3 100644
--- a/source/Plugins/Process/Utility/MipsLinuxSignals.h
+++ b/source/Plugins/Process/Utility/MipsLinuxSignals.h
@@ -17,21 +17,18 @@
#include "lldb/Target/UnixSignals.h"
namespace lldb_private {
-namespace process_linux {
- /// Linux specific set of Unix signals.
- class MipsLinuxSignals
- : public lldb_private::UnixSignals
- {
- public:
- MipsLinuxSignals();
+/// Linux specific set of Unix signals.
+class MipsLinuxSignals : public UnixSignals
+{
+public:
+ MipsLinuxSignals();
- private:
- void
- Reset();
- };
+private:
+ void
+ Reset() override;
+};
} // namespace lldb_private
-} // namespace process_linux
-#endif
+#endif // liblldb_MipsLinuxSignals_H_
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp
index 02d3ecd7b3c5..1cdae9011673 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -120,29 +120,28 @@ unwind_done:
return false;
}
-// For adding a non-zero stack frame to m_frames.
-bool
-UnwindLLDB::AddOneMoreFrame (ABI *abi)
+UnwindLLDB::CursorSP
+UnwindLLDB::GetOneMoreFrame (ABI* abi)
{
+ assert (m_frames.size() != 0 && "Get one more frame called with empty frame list");
+
// If we've already gotten to the end of the stack, don't bother to try again...
if (m_unwind_complete)
- return false;
+ return nullptr;
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
- CursorSP cursor_sp(new Cursor ());
- // Frame zero is a little different
- if (m_frames.size() == 0)
- return false;
+ CursorSP prev_frame = m_frames.back();
+ uint32_t cur_idx = m_frames.size();
- uint32_t cur_idx = m_frames.size ();
+ CursorSP cursor_sp(new Cursor ());
RegisterContextLLDBSP reg_ctx_sp(new RegisterContextLLDB (m_thread,
- m_frames[cur_idx - 1]->reg_ctx_lldb_sp,
+ prev_frame->reg_ctx_lldb_sp,
cursor_sp->sctx,
cur_idx,
*this));
- // We want to detect an unwind that cycles erronously and stop backtracing.
+ // We want to detect an unwind that cycles erroneously and stop backtracing.
// Don't want this maximum unwind limit to be too low -- if you have a backtrace
// with an "infinitely recursing" bug, it will crash when the stack blows out
// and the first 35,000 frames are uninteresting - it's the top most 5 frames that
@@ -154,21 +153,20 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
if (log)
log->Printf ("%*sFrame %d unwound too many frames, assuming unwind has gone astray, stopping.",
cur_idx < 100 ? cur_idx : 100, "", cur_idx);
- goto unwind_done;
+ return nullptr;
}
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 (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ return GetOneMoreFrame (abi);
+
if (log)
log->Printf ("%*sFrame %d did not get a RegisterContext, stopping.",
cur_idx < 100 ? cur_idx : 100, "", cur_idx);
- goto unwind_done;
+ return nullptr;
}
if (!reg_ctx_sp->IsValid())
@@ -176,31 +174,25 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
// We failed to get a valid RegisterContext.
// See if the regctx below this on the stack has a fallback unwind plan it can use.
// Subsequent calls to TryFallbackUnwindPlan() will return false.
- if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
- {
- return AddOneMoreFrame (abi);
- }
+ if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ return GetOneMoreFrame (abi);
+
if (log)
- {
log->Printf("%*sFrame %d invalid RegisterContext for this frame, stopping stack walk",
cur_idx < 100 ? cur_idx : 100, "", cur_idx);
- }
- goto unwind_done;
+ return nullptr;
}
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 (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ return GetOneMoreFrame (abi);
+
if (log)
- {
log->Printf("%*sFrame %d did not get CFA for this frame, stopping stack walk",
cur_idx < 100 ? cur_idx : 100, "", cur_idx);
- }
- goto unwind_done;
+ return nullptr;
}
if (abi && !abi->CallFrameAddressIsValid(cursor_sp->cfa))
{
@@ -219,24 +211,19 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
|| reg_ctx_sp->GetCFA (cursor_sp->cfa) == false
|| abi->CallFrameAddressIsValid(cursor_sp->cfa) == false)
{
- if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
- {
- return AddOneMoreFrame (abi);
- }
+ if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ return GetOneMoreFrame (abi);
+
if (log)
- {
log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
cur_idx < 100 ? cur_idx : 100, "", cur_idx);
- }
- goto unwind_done;
+ return nullptr;
}
else
{
if (log)
- {
log->Printf("%*sFrame %d had a bad CFA value but we switched the UnwindPlan being used and got one that looks more realistic.",
cur_idx < 100 ? cur_idx : 100, "", cur_idx);
- }
}
}
}
@@ -244,54 +231,103 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
{
// 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 (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ return GetOneMoreFrame (abi);
+
if (log)
- {
log->Printf("%*sFrame %d did not get PC for this frame, stopping stack walk",
cur_idx < 100 ? cur_idx : 100, "", cur_idx);
- }
- goto unwind_done;
+ return nullptr;
}
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 (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ return GetOneMoreFrame (abi);
+
if (log)
- {
log->Printf("%*sFrame %d did not get a valid PC, stopping stack walk",
cur_idx < 100 ? cur_idx : 100, "", cur_idx);
- }
- goto unwind_done;
+ return nullptr;
}
- if (!m_frames.empty())
+ // Infinite loop where the current cursor is the same as the previous one...
+ if (prev_frame->start_pc == cursor_sp->start_pc && prev_frame->cfa == cursor_sp->cfa)
{
- // Infinite loop where the current cursor is the same as the previous one...
- if (m_frames.back()->start_pc == cursor_sp->start_pc && m_frames.back()->cfa == cursor_sp->cfa)
- {
- if (log)
- log->Printf ("th%d pc of this frame is the same as the previous frame and CFAs for both frames are identical -- stopping unwind", m_thread.GetIndexID());
- goto unwind_done;
- }
+ if (log)
+ log->Printf ("th%d pc of this frame is the same as the previous frame and CFAs for both frames are identical -- stopping unwind", m_thread.GetIndexID());
+ return nullptr;
}
cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp;
- m_frames.push_back (cursor_sp);
- return true;
-
-unwind_done:
- if (log)
+ return cursor_sp;
+}
+
+bool
+UnwindLLDB::AddOneMoreFrame (ABI *abi)
+{
+ Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+
+ // Frame zero is a little different
+ if (m_frames.empty())
+ return false;
+
+ // If we've already gotten to the end of the stack, don't bother to try again...
+ if (m_unwind_complete)
+ return false;
+
+ CursorSP new_frame = m_candidate_frame;
+ if (new_frame == nullptr)
+ new_frame = GetOneMoreFrame(abi);
+
+ if (new_frame == nullptr)
{
- log->Printf ("th%d Unwind of this thread is complete.", m_thread.GetIndexID());
+ if (log)
+ log->Printf ("th%d Unwind of this thread is complete.", m_thread.GetIndexID());
+ m_unwind_complete = true;
+ return false;
}
- m_unwind_complete = true;
- return false;
+
+ m_frames.push_back(new_frame);
+
+ // If we can get one more frame further then accept that we get back a correct frame.
+ m_candidate_frame = GetOneMoreFrame(abi);
+ if (m_candidate_frame)
+ return true;
+
+ // We can't go further from the frame returned by GetOneMore frame. Lets try to get a
+ // different frame with using the fallback unwind plan.
+ if (!m_frames[m_frames.size() - 2]->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ {
+ // We don't have a valid fallback unwind plan. Accept the frame as it is. This is a
+ // valid situation when we are at the bottom of the stack.
+ return true;
+ }
+
+ // Remove the possibly incorrect frame from the frame list and try to add a different one with
+ // the newly selected fallback unwind plan.
+ m_frames.pop_back();
+ CursorSP new_frame_v2 = GetOneMoreFrame(abi);
+ if (new_frame_v2 == nullptr)
+ {
+ // We haven't got a new frame from the fallback unwind plan. Accept the frame from the
+ // original unwind plan. This is a valid situation when we are at the bottom of the stack.
+ m_frames.push_back(new_frame);
+ return true;
+ }
+
+ // Push the new frame to the list and try to continue from this frame. If we can get a new frame
+ // then accept it as the correct one.
+ m_frames.push_back(new_frame_v2);
+ m_candidate_frame = GetOneMoreFrame(abi);
+ if (m_candidate_frame)
+ return true;
+
+ // The new frame isn't helped in unwinding. Fall back to the original one as the default unwind
+ // plan is usually more reliable then the fallback one.
+ m_frames.pop_back();
+ m_frames.push_back(new_frame);
+ return true;
}
bool
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.h b/source/Plugins/Process/Utility/UnwindLLDB.h
index 35d85e2e3d26..ce897cd82423 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.h
+++ b/source/Plugins/Process/Utility/UnwindLLDB.h
@@ -65,6 +65,7 @@ protected:
DoClear()
{
m_frames.clear();
+ m_candidate_frame.reset();
m_unwind_complete = false;
}
@@ -126,14 +127,21 @@ private:
typedef std::shared_ptr<Cursor> CursorSP;
std::vector<CursorSP> m_frames;
+ CursorSP m_candidate_frame;
bool m_unwind_complete; // If this is true, we've enumerated all the frames in the stack, and m_frames.size() is the
// number of frames, etc. Otherwise we've only gone as far as directly asked, and m_frames.size()
// is how far we've currently gone.
std::vector<ConstString> m_user_supplied_trap_handler_functions;
- bool AddOneMoreFrame (ABI *abi);
- bool AddFirstFrame ();
+ CursorSP
+ GetOneMoreFrame (ABI* abi);
+
+ bool
+ AddOneMoreFrame (ABI *abi);
+
+ bool
+ AddFirstFrame ();
//------------------------------------------------------------------
// For UnwindLLDB only
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 2fff36dd4ee5..bf5cad8e39c5 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -29,8 +29,6 @@
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
-#include "Plugins/Process/Utility/FreeBSDSignals.h"
-#include "Plugins/Process/Utility/LinuxSignals.h"
// Project includes
#include "ProcessElfCore.h"
@@ -237,23 +235,7 @@ ProcessElfCore::DoLoadCore ()
if (arch.IsValid())
m_target.SetArchitecture(arch);
- switch (m_os)
- {
- case llvm::Triple::FreeBSD:
- {
- static UnixSignalsSP s_freebsd_signals_sp(new FreeBSDSignals ());
- SetUnixSignals(s_freebsd_signals_sp);
- break;
- }
- case llvm::Triple::Linux:
- {
- static UnixSignalsSP s_linux_signals_sp(new process_linux::LinuxSignals ());
- SetUnixSignals(s_linux_signals_sp);
- break;
- }
- default:
- break;
- }
+ SetUnixSignals(UnixSignals::Create(GetArchitecture()));
return error;
}
@@ -370,7 +352,7 @@ ProcessElfCore::Clear()
m_thread_list.Clear();
m_os = llvm::Triple::UnknownOS;
- static UnixSignalsSP s_default_unix_signals_sp(new UnixSignals());
+ static const auto s_default_unix_signals_sp = std::make_shared<UnixSignals>();
SetUnixSignals(s_default_unix_signals_sp);
}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 1af3947a75f3..9c263c8c4087 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -564,8 +564,12 @@ GDBRemoteCommunication::DecompressPacket ()
return true;
size_t pkt_size = m_bytes.size();
- if (pkt_size < 6)
+
+ // Smallest possible compressed packet is $N#00 - an uncompressed empty reply, most commonly indicating
+ // an unsupported packet. Anything less than 5 characters, it's definitely not a compressed packet.
+ if (pkt_size < 5)
return true;
+
if (m_bytes[0] != '$' && m_bytes[0] != '%')
return true;
if (m_bytes[1] != 'C' && m_bytes[1] != 'N')
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index ae0a2f5e66c5..2a253c5a99e8 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -87,6 +87,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() :
m_supports_qXfer_features_read (eLazyBoolCalculate),
m_supports_augmented_libraries_svr4_read (eLazyBoolCalculate),
m_supports_jThreadExtendedInfo (eLazyBoolCalculate),
+ m_supports_jLoadedDynamicLibrariesInfos (eLazyBoolCalculate),
m_supports_qProcessInfoPID (true),
m_supports_qfProcessInfo (true),
m_supports_qUserName (true),
@@ -654,6 +655,24 @@ GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported ()
}
bool
+GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported ()
+{
+ if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate)
+ {
+ StringExtractorGDBRemote response;
+ m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolNo;
+ if (SendPacketAndWaitForResponse("jGetLoadedDynamicLibrariesInfos:", response, false) == PacketResult::Success)
+ {
+ if (response.IsOKResponse())
+ {
+ m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolYes;
+ }
+ }
+ }
+ return m_supports_jLoadedDynamicLibrariesInfos;
+}
+
+bool
GDBRemoteCommunicationClient::GetxPacketSupported ()
{
if (m_supports_x == eLazyBoolCalculate)
@@ -1037,8 +1056,8 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
// may change if we are interrupted and we continue after an async packet...
std::string continue_packet(payload, packet_length);
- const auto sigstop_signo = process->GetUnixSignals().GetSignalNumberFromName("SIGSTOP");
- const auto sigint_signo = process->GetUnixSignals().GetSignalNumberFromName("SIGINT");
+ const auto sigstop_signo = process->GetUnixSignals()->GetSignalNumberFromName("SIGSTOP");
+ const auto sigint_signo = process->GetUnixSignals()->GetSignalNumberFromName("SIGINT");
bool got_async_packet = false;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 65a2981018ea..deb41b066b45 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -550,6 +550,9 @@ public:
GetThreadExtendedInfoSupported();
bool
+ GetLoadedDynamicLibrariesInfosSupported();
+
+ bool
GetModuleInfo (const FileSpec& module_file_spec,
const ArchSpec& arch_spec,
ModuleSpec &module_spec);
@@ -614,6 +617,7 @@ protected:
LazyBool m_supports_qXfer_features_read;
LazyBool m_supports_augmented_libraries_svr4_read;
LazyBool m_supports_jThreadExtendedInfo;
+ LazyBool m_supports_jLoadedDynamicLibrariesInfos;
bool
m_supports_qProcessInfoPID:1,
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 13ce9b2dc5c3..4ee66b84d474 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -132,7 +132,7 @@ GDBRemoteCommunicationServer::SendOKResponse ()
}
bool
-GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
+GDBRemoteCommunicationServer::HandshakeWithClient()
{
return GetAck() == PacketResult::Success;
}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index 992c6dffaf54..44c0f6a32f5b 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -54,7 +54,7 @@ public:
// After connecting, do a little handshake with the client to make sure
// we are at least communicating
bool
- HandshakeWithClient (Error *error_ptr);
+ HandshakeWithClient ();
protected:
std::map<StringExtractorGDBRemote::ServerPacketType, PacketHandler> m_packet_handlers;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index e8955ddbd6e4..c4523252f190 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -75,10 +75,11 @@ namespace
// GDBRemoteCommunicationServerLLGS constructor
//----------------------------------------------------------------------
GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(
- const lldb::PlatformSP& platform_sp) :
+ const lldb::PlatformSP& platform_sp,
+ MainLoop &mainloop) :
GDBRemoteCommunicationServerCommon ("gdb-remote.server", "gdb-remote.server.rx_packet"),
m_platform_sp (platform_sp),
- m_async_thread (LLDB_INVALID_HOST_THREAD),
+ m_mainloop (mainloop),
m_current_tid (LLDB_INVALID_THREAD_ID),
m_continue_tid (LLDB_INVALID_THREAD_ID),
m_debugged_process_mutex (Mutex::eMutexTypeRecursive),
@@ -88,7 +89,8 @@ GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(
m_active_auxv_buffer_sp (),
m_saved_registers_mutex (),
m_saved_registers_map (),
- m_next_saved_registers_id (1)
+ m_next_saved_registers_id (1),
+ m_handshake_completed (false)
{
assert(platform_sp);
RegisterPacketHandlers();
@@ -218,7 +220,7 @@ GDBRemoteCommunicationServerLLGS::LaunchProcess ()
{
Mutex::Locker locker (m_debugged_process_mutex);
assert (!m_debugged_process_sp && "lldb-gdbserver creating debugged process but one already exists");
- error = m_platform_sp->LaunchNativeProcess (
+ error = NativeProcessProtocol::Launch(
m_process_launch_info,
*this,
m_debugged_process_sp);
@@ -306,7 +308,7 @@ GDBRemoteCommunicationServerLLGS::AttachToProcess (lldb::pid_t pid)
}
// Try to attach.
- error = m_platform_sp->AttachNativeProcess (pid, *this, m_debugged_process_sp);
+ error = NativeProcessProtocol::Attach(pid, *this, m_debugged_process_sp);
if (!error.Success ())
{
fprintf (stderr, "%s: failed to attach to process %" PRIu64 ": %s", __FUNCTION__, pid, error.AsCString ());
@@ -782,6 +784,58 @@ GDBRemoteCommunicationServerLLGS::DidExec (NativeProcessProtocol *process)
ClearProcessSpecificData ();
}
+void
+GDBRemoteCommunicationServerLLGS::DataAvailableCallback ()
+{
+ Log *log (GetLogIfAnyCategoriesSet(GDBR_LOG_COMM));
+
+ if (! m_handshake_completed)
+ {
+ if (! HandshakeWithClient())
+ {
+ if(log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s handshake with client failed, exiting",
+ __FUNCTION__);
+ m_read_handle_up.reset();
+ m_mainloop.RequestTermination();
+ return;
+ }
+ m_handshake_completed = true;
+ }
+
+ bool interrupt = false;
+ bool done = false;
+ Error error;
+ while (true)
+ {
+ const PacketResult result = GetPacketAndSendResponse (0, error, interrupt, done);
+ if (result == PacketResult::ErrorReplyTimeout)
+ break; // No more packets in the queue
+
+ if ((result != PacketResult::Success))
+ {
+ if(log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s processing a packet failed: %s",
+ __FUNCTION__, error.AsCString());
+ m_read_handle_up.reset();
+ m_mainloop.RequestTermination();
+ break;
+ }
+ }
+}
+
+Error
+GDBRemoteCommunicationServerLLGS::InitializeConnection (std::unique_ptr<Connection> &&connection)
+{
+ IOObjectSP read_object_sp = connection->GetReadObject();
+ GDBRemoteCommunicationServer::SetConnection(connection.release());
+
+ Error error;
+ m_read_handle_up = m_mainloop.RegisterReadObject(read_object_sp,
+ [this] (MainLoopBase &) { DataAvailableCallback(); }, error);
+ return error;
+}
+
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::SendONotification (const char *buffer, uint32_t len)
{
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index 1eda0b052bb7..29f3fdebcfb0 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -19,6 +19,7 @@
#include "lldb/Core/Communication.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
+#include "lldb/Host/MainLoop.h"
// Project includes
#include "GDBRemoteCommunicationServerCommon.h"
@@ -26,6 +27,7 @@
class StringExtractorGDBRemote;
namespace lldb_private {
+
namespace process_gdb_remote {
class ProcessGDBRemote;
@@ -38,7 +40,7 @@ public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
- GDBRemoteCommunicationServerLLGS(const lldb::PlatformSP& platform_sp);
+ GDBRemoteCommunicationServerLLGS(const lldb::PlatformSP& platform_sp, MainLoop &mainloop);
virtual
~GDBRemoteCommunicationServerLLGS();
@@ -111,9 +113,13 @@ public:
void
DidExec (NativeProcessProtocol *process) override;
+ Error
+ InitializeConnection (std::unique_ptr<Connection> &&connection);
+
protected:
lldb::PlatformSP m_platform_sp;
- lldb::thread_t m_async_thread;
+ MainLoop &m_mainloop;
+ MainLoop::ReadHandleUP m_read_handle_up;
lldb::tid_t m_current_tid;
lldb::tid_t m_continue_tid;
Mutex m_debugged_process_mutex;
@@ -124,6 +130,7 @@ protected:
Mutex m_saved_registers_mutex;
std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map;
uint32_t m_next_saved_registers_id;
+ bool m_handshake_completed : 1;
PacketResult
SendONotification (const char *buffer, uint32_t len);
@@ -295,6 +302,9 @@ private:
void
RegisterPacketHandlers ();
+ void
+ DataAvailableCallback ();
+
//------------------------------------------------------------------
// For GDBRemoteCommunicationServerLLGS only
//------------------------------------------------------------------
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
index f5e5d76f2e6f..1205049db3fb 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -19,6 +19,7 @@
// Other libraries and framework includes
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Core/StructuredData.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Host.h"
@@ -26,6 +27,7 @@
#include "lldb/Target/FileAction.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
+#include "lldb/Target/UnixSignals.h"
// Project includes
#include "Utility/StringExtractorGDBRemote.h"
@@ -54,6 +56,8 @@ GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform() :
&GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
&GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_jSignalsInfo,
+ &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);
RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
[this](StringExtractorGDBRemote packet,
@@ -251,6 +255,35 @@ GDBRemoteCommunicationServerPlatform::Handle_qC (StringExtractorGDBRemote &packe
return SendPacketNoLock (response.GetData(), response.GetSize());
}
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(StringExtractorGDBRemote &packet)
+{
+ StructuredData::Array signal_array;
+
+ const auto &signals = Host::GetUnixSignals();
+ for (auto signo = signals->GetFirstSignalNumber();
+ signo != LLDB_INVALID_SIGNAL_NUMBER;
+ signo = signals->GetNextSignalNumber(signo))
+ {
+ auto dictionary = std::make_shared<StructuredData::Dictionary>();
+
+ dictionary->AddIntegerItem("signo", signo);
+ dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));
+
+ bool suppress, stop, notify;
+ signals->GetSignalInfo(signo, suppress, stop, notify);
+ dictionary->AddBooleanItem("suppress", suppress);
+ dictionary->AddBooleanItem("stop", stop);
+ dictionary->AddBooleanItem("notify", notify);
+
+ signal_array.Push(dictionary);
+ }
+
+ StreamString response;
+ signal_array.Dump(response);
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+}
+
bool
GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped (lldb::pid_t pid)
{
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
index 4124b0424f5d..5c011371a3eb 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
@@ -79,6 +79,9 @@ protected:
PacketResult
Handle_qC (StringExtractorGDBRemote &packet);
+ PacketResult
+ Handle_jSignalsInfo(StringExtractorGDBRemote &packet);
+
private:
bool
DebugserverProcessReaped (lldb::pid_t pid);
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 5cb4da514a7f..0bcc8ca4e5e3 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -65,10 +65,8 @@
// Project includes
#include "lldb/Host/Host.h"
-#include "Plugins/Process/Utility/FreeBSDSignals.h"
+#include "Plugins/Process/Utility/GDBRemoteSignals.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
-#include "Plugins/Process/Utility/LinuxSignals.h"
-#include "Plugins/Process/Utility/MipsLinuxSignals.h"
#include "Plugins/Process/Utility/StopInfoMachException.h"
#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h"
#include "Utility/StringExtractorGDBRemote.h"
@@ -823,41 +821,8 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
if (log)
log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": normalized target architecture triple: %s", __FUNCTION__, GetID (), GetTarget ().GetArchitecture ().GetTriple ().getTriple ().c_str ());
- // Set the Unix signals properly for the target.
- // FIXME Add a gdb-remote packet to discover dynamically.
- if (error.Success ())
- {
- const ArchSpec arch_spec = m_gdb_comm.GetHostArchitecture();
- if (arch_spec.IsValid ())
- {
- if (log)
- log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": determining unix signals type based on architecture %s, triple %s", __FUNCTION__, GetID (), arch_spec.GetArchitectureName () ? arch_spec.GetArchitectureName () : "<null>", arch_spec.GetTriple ().getTriple ().c_str ());
-
- switch (arch_spec.GetTriple ().getOS ())
- {
- case llvm::Triple::Linux:
- if (arch_spec.GetTriple ().getArch () == llvm::Triple::mips64 || arch_spec.GetTriple ().getArch () == llvm::Triple::mips64el)
- SetUnixSignals (UnixSignalsSP (new process_linux::MipsLinuxSignals ()));
- else
- SetUnixSignals (UnixSignalsSP (new process_linux::LinuxSignals ()));
- if (log)
- log->Printf ("ProcessGDBRemote::%s using Linux unix signals type for pid %" PRIu64, __FUNCTION__, GetID ());
- break;
- case llvm::Triple::OpenBSD:
- case llvm::Triple::FreeBSD:
- case llvm::Triple::NetBSD:
- SetUnixSignals (UnixSignalsSP (new FreeBSDSignals ()));
- if (log)
- log->Printf ("ProcessGDBRemote::%s using *BSD unix signals type for pid %" PRIu64, __FUNCTION__, GetID ());
- break;
- default:
- SetUnixSignals (UnixSignalsSP (new UnixSignals ()));
- if (log)
- log->Printf ("ProcessGDBRemote::%s using generic unix signals type for pid %" PRIu64, __FUNCTION__, GetID ());
- break;
- }
- }
- }
+ if (error.Success())
+ SetUnixSignals(std::make_shared<GDBRemoteSignals>(GetTarget().GetPlatform()->GetUnixSignals()));
return error;
}
@@ -3524,7 +3489,7 @@ ProcessGDBRemote::MonitorDebugserverProcess
char error_str[1024];
if (signo)
{
- const char *signal_cstr = process->GetUnixSignals().GetSignalAsCString (signo);
+ const char *signal_cstr = process->GetUnixSignals()->GetSignalAsCString(signo);
if (signal_cstr)
::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr);
else
@@ -3985,6 +3950,44 @@ ProcessGDBRemote::GetExtendedInfoForThread (lldb::tid_t tid)
{
if (!response.Empty())
{
+ object_sp = StructuredData::ParseJSON (response.GetStringRef());
+ }
+ }
+ }
+ }
+ return object_sp;
+}
+
+StructuredData::ObjectSP
+ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_address, lldb::addr_t image_count)
+{
+ StructuredData::ObjectSP object_sp;
+
+ if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported())
+ {
+ StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
+ args_dict->GetAsDictionary()->AddIntegerItem ("image_list_address", image_list_address);
+ args_dict->GetAsDictionary()->AddIntegerItem ("image_count", image_count);
+
+ StreamString packet;
+ packet << "jGetLoadedDynamicLibrariesInfos:";
+ args_dict->Dump (packet);
+
+ // FIXME the final character of a JSON dictionary, '}', is the escape
+ // character in gdb-remote binary mode. lldb currently doesn't escape
+ // these characters in its packet output -- so we add the quoted version
+ // of the } character here manually in case we talk to a debugserver which
+ // un-escapes the characters at packet read time.
+ packet << (char) (0x7d ^ 0x20);
+
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success)
+ {
+ StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType();
+ if (response_type == StringExtractorGDBRemote::eResponse)
+ {
+ if (!response.Empty())
+ {
// The packet has already had the 0x7d xor quoting stripped out at the
// GDBRemoteCommunication packet receive level.
object_sp = StructuredData::ParseJSON (response.GetStringRef());
@@ -3995,6 +3998,7 @@ ProcessGDBRemote::GetExtendedInfoForThread (lldb::tid_t tid)
return object_sp;
}
+
// Establish the largest memory read/write payloads we should use.
// If the remote stub has a max packet size, stay under that size.
//
@@ -4418,83 +4422,135 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
GDBRemoteCommunicationClient & comm = m_gdb_comm;
// check that we have extended feature read support
- if (!comm.GetQXferLibrariesSVR4ReadSupported ())
- return Error (0, ErrorType::eErrorTypeGeneric);
+ if (comm.GetQXferLibrariesSVR4ReadSupported ()) {
+ list.clear ();
- list.clear ();
+ // request the loaded library list
+ std::string raw;
+ lldb_private::Error lldberr;
- // request the loaded library list
- std::string raw;
- lldb_private::Error lldberr;
- if (!comm.ReadExtFeature (ConstString ("libraries-svr4"), ConstString (""), raw, lldberr))
- return Error (0, ErrorType::eErrorTypeGeneric);
+ if (!comm.ReadExtFeature (ConstString ("libraries-svr4"), ConstString (""), raw, lldberr))
+ return Error (0, ErrorType::eErrorTypeGeneric);
- // parse the xml file in memory
- if (log)
- log->Printf ("parsing: %s", raw.c_str());
- XMLDocument doc;
-
- if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
- return Error (0, ErrorType::eErrorTypeGeneric);
+ // parse the xml file in memory
+ if (log)
+ log->Printf ("parsing: %s", raw.c_str());
+ XMLDocument doc;
+
+ if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
+ return Error (0, ErrorType::eErrorTypeGeneric);
- XMLNode root_element = doc.GetRootElement("library-list-svr4");
- if (!root_element)
- return Error();
+ XMLNode root_element = doc.GetRootElement("library-list-svr4");
+ if (!root_element)
+ return Error();
- // main link map structure
- llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm");
- if (!main_lm.empty())
- {
- list.m_link_map = StringConvert::ToUInt64(main_lm.data(), LLDB_INVALID_ADDRESS, 0);
- }
+ // main link map structure
+ llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm");
+ if (!main_lm.empty())
+ {
+ list.m_link_map = StringConvert::ToUInt64(main_lm.data(), LLDB_INVALID_ADDRESS, 0);
+ }
- root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool {
+ root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool {
- GDBLoadedModuleInfoList::LoadedModuleInfo module;
+ GDBLoadedModuleInfoList::LoadedModuleInfo module;
- library.ForEachAttribute([log, &module](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
-
- if (name == "name")
- module.set_name (value.str());
- else if (name == "lm")
- {
- // the address of the link_map struct.
- module.set_link_map(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
- }
- else if (name == "l_addr")
- {
- // the displacement as read from the field 'l_addr' of the link_map struct.
- module.set_base(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
+ library.ForEachAttribute([log, &module](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
- }
- else if (name == "l_ld")
+ if (name == "name")
+ module.set_name (value.str());
+ else if (name == "lm")
+ {
+ // the address of the link_map struct.
+ module.set_link_map(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
+ }
+ else if (name == "l_addr")
+ {
+ // the displacement as read from the field 'l_addr' of the link_map struct.
+ module.set_base(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
+
+ }
+ else if (name == "l_ld")
+ {
+ // the memory address of the libraries PT_DYAMIC section.
+ module.set_dynamic(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
+ }
+
+ return true; // Keep iterating over all properties of "library"
+ });
+
+ if (log)
{
- // the memory address of the libraries PT_DYAMIC section.
- module.set_dynamic(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
+ std::string name;
+ lldb::addr_t lm=0, base=0, ld=0;
+
+ module.get_name (name);
+ module.get_link_map (lm);
+ module.get_base (base);
+ module.get_dynamic (ld);
+
+ log->Printf ("found (link_map:0x08%" PRIx64 ", base:0x08%" PRIx64 ", ld:0x08%" PRIx64 ", name:'%s')", lm, base, ld, name.c_str());
}
-
- return true; // Keep iterating over all properties of "library"
+
+ list.add (module);
+ return true; // Keep iterating over all "library" elements in the root node
});
if (log)
- {
- std::string name;
- lldb::addr_t lm=0, base=0, ld=0;
+ log->Printf ("found %" PRId32 " modules in total", (int) list.m_list.size());
+ } else if (comm.GetQXferLibrariesReadSupported ()) {
+ list.clear ();
- module.get_name (name);
- module.get_link_map (lm);
- module.get_base (base);
- module.get_dynamic (ld);
+ // request the loaded library list
+ std::string raw;
+ lldb_private::Error lldberr;
- log->Printf ("found (link_map:0x08%" PRIx64 ", base:0x08%" PRIx64 ", ld:0x08%" PRIx64 ", name:'%s')", lm, base, ld, name.c_str());
- }
+ if (!comm.ReadExtFeature (ConstString ("libraries"), ConstString (""), raw, lldberr))
+ return Error (0, ErrorType::eErrorTypeGeneric);
- list.add (module);
- return true; // Keep iterating over all "library" elements in the root node
- });
+ if (log)
+ log->Printf ("parsing: %s", raw.c_str());
+ XMLDocument doc;
- if (log)
- log->Printf ("found %" PRId32 " modules in total", (int) list.m_list.size());
+ if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
+ return Error (0, ErrorType::eErrorTypeGeneric);
+
+ XMLNode root_element = doc.GetRootElement("library-list");
+ if (!root_element)
+ return Error();
+
+ root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool {
+ GDBLoadedModuleInfoList::LoadedModuleInfo module;
+
+ llvm::StringRef name = library.GetAttributeValue("name");
+ module.set_name(name.str());
+
+ // The base address of a given library will be the address of its
+ // first section. Most remotes send only one section for Windows
+ // targets for example.
+ const XMLNode &section = library.FindFirstChildElementWithName("section");
+ llvm::StringRef address = section.GetAttributeValue("address");
+ module.set_base(StringConvert::ToUInt64(address.data(), LLDB_INVALID_ADDRESS, 0));
+
+ if (log)
+ {
+ std::string name;
+ lldb::addr_t base = 0;
+ module.get_name (name);
+ module.get_base (base);
+
+ log->Printf ("found (base:0x%" PRIx64 ", name:'%s')", base, name.c_str());
+ }
+
+ list.add (module);
+ return true; // Keep iterating over all "library" elements in the root node
+ });
+
+ if (log)
+ log->Printf ("found %" PRId32 " modules in total", (int) list.m_list.size());
+ } else {
+ return Error (0, ErrorType::eErrorTypeGeneric);
+ }
return Error();
}
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 0a5e4a8a41b4..45c74ea64ee5 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -27,11 +27,11 @@
#include "lldb/Core/ThreadSafeValue.h"
#include "lldb/Host/HostThread.h"
#include "lldb/lldb-private-forward.h"
+#include "lldb/Utility/StringExtractor.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
#include "GDBRemoteCommunicationClient.h"
-#include "Utility/StringExtractor.h"
#include "GDBRemoteRegisterContext.h"
namespace lldb_private {
@@ -247,6 +247,9 @@ public:
void
ModulesDidLoad (ModuleList &module_list) override;
+ StructuredData::ObjectSP
+ GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_address, lldb::addr_t image_count) override;
+
protected:
friend class ThreadGDBRemote;
friend class GDBRemoteCommunicationClient;
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 59c701d75a68..d2a6503caf8e 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -215,14 +215,14 @@ ThreadGDBRemote::WillResume (StateType resume_state)
break;
case eStateRunning:
- if (gdb_process->GetUnixSignals().SignalIsValid (signo))
+ if (gdb_process->GetUnixSignals()->SignalIsValid(signo))
gdb_process->m_continue_C_tids.push_back(std::make_pair(tid, signo));
else
gdb_process->m_continue_c_tids.push_back(tid);
break;
case eStateStepping:
- if (gdb_process->GetUnixSignals().SignalIsValid (signo))
+ if (gdb_process->GetUnixSignals()->SignalIsValid(signo))
gdb_process->m_continue_S_tids.push_back(std::make_pair(tid, signo));
else
gdb_process->m_continue_s_tids.push_back(tid);
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
index 75934f966bcd..60933108c97a 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -669,6 +669,7 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
GetOffset());
}
+ const LanguageType cu_language = GetLanguageType();
DWARFDebugInfoEntry::const_iterator pos;
DWARFDebugInfoEntry::const_iterator begin = m_die_array.begin();
DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
@@ -882,8 +883,9 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
{
Mangled mangled (ConstString(mangled_cstr), true);
func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset());
- if (mangled.GetDemangledName())
- func_fullnames.Insert (mangled.GetDemangledName(), die.GetOffset());
+ ConstString demangled = mangled.GetDemangledName(cu_language);
+ if (demangled)
+ func_fullnames.Insert (demangled, die.GetOffset());
}
}
}
@@ -904,8 +906,9 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
{
Mangled mangled (ConstString(mangled_cstr), true);
func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset());
- if (mangled.GetDemangledName())
- func_fullnames.Insert (mangled.GetDemangledName(), die.GetOffset());
+ ConstString demangled = mangled.GetDemangledName(cu_language);
+ if (demangled)
+ func_fullnames.Insert (demangled, die.GetOffset());
}
}
else
@@ -951,8 +954,9 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
{
Mangled mangled (ConstString(mangled_cstr), true);
globals.Insert (mangled.GetMangledName(), die.GetOffset());
- if (mangled.GetDemangledName())
- globals.Insert (mangled.GetDemangledName(), die.GetOffset());
+ ConstString demangled = mangled.GetDemangledName(cu_language);
+ if (demangled)
+ globals.Insert (demangled, die.GetOffset());
}
}
break;
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index dafd389449a2..ea8aedcc2be0 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -988,24 +988,38 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx)
std::string remapped_file;
if (module_sp->RemapSourceFile(cu_file_spec.GetCString(), remapped_file))
cu_file_spec.SetFile(remapped_file, false);
+ }
- LanguageType cu_language = DWARFCompileUnit::LanguageTypeFromDWARF(cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_language, 0));
+ LanguageType cu_language = DWARFCompileUnit::LanguageTypeFromDWARF(cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_language, 0));
- cu_sp.reset(new CompileUnit (module_sp,
- dwarf_cu,
- cu_file_spec,
- MakeUserID(dwarf_cu->GetOffset()),
- cu_language));
- if (cu_sp)
+ cu_sp.reset(new CompileUnit (module_sp,
+ dwarf_cu,
+ cu_file_spec,
+ MakeUserID(dwarf_cu->GetOffset()),
+ cu_language));
+ if (cu_sp)
+ {
+ // If we just created a compile unit with an invalid file spec, try and get the
+ // first entry in the supports files from the line table as that should be the
+ // compile unit.
+ if (!cu_file_spec)
{
- dwarf_cu->SetUserData(cu_sp.get());
-
- // Figure out the compile unit index if we weren't given one
- if (cu_idx == UINT32_MAX)
- DebugInfo()->GetCompileUnit(dwarf_cu->GetOffset(), &cu_idx);
-
- m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(cu_idx, cu_sp);
+ cu_file_spec = cu_sp->GetSupportFiles().GetFileSpecAtIndex(1);
+ if (cu_file_spec)
+ {
+ (FileSpec &)(*cu_sp) = cu_file_spec;
+ // Also fix the invalid file spec which was copied from the compile unit.
+ cu_sp->GetSupportFiles().Replace(0, cu_file_spec);
+ }
}
+
+ dwarf_cu->SetUserData(cu_sp.get());
+
+ // Figure out the compile unit index if we weren't given one
+ if (cu_idx == UINT32_MAX)
+ DebugInfo()->GetCompileUnit(dwarf_cu->GetOffset(), &cu_idx);
+
+ m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(cu_idx, cu_sp);
}
}
}
@@ -2196,7 +2210,7 @@ SymbolFileDWARF::ParseChildMembers
}
}
- if (prop_name != NULL)
+ if (prop_name != NULL && member_type)
{
clang::ObjCIvarDecl *ivar_decl = NULL;
@@ -3761,9 +3775,10 @@ SymbolFileDWARF::FunctionDieMatchesPartialName (const DWARFDebugInfoEntry* die,
}
}
- if (best_name.GetDemangledName())
+ const LanguageType cu_language = const_cast<DWARFCompileUnit *>(dwarf_cu)->GetLanguageType();
+ if (best_name.GetDemangledName(cu_language))
{
- const char *demangled = best_name.GetDemangledName().GetCString();
+ const char *demangled = best_name.GetDemangledName(cu_language).GetCString();
if (demangled)
{
std::string name_no_parens(partial_name, base_name_end - partial_name);
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index 5579a23ce716..de972acd7ed7 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -113,7 +113,7 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa
// correctly to the new addresses in the main executable.
// First we find the original symbol in the .o file's symbol table
- Symbol *oso_fun_symbol = oso_symtab->FindFirstSymbolWithNameAndType (exe_symbol->GetMangled().GetName(Mangled::ePreferMangled),
+ Symbol *oso_fun_symbol = oso_symtab->FindFirstSymbolWithNameAndType (exe_symbol->GetMangled().GetName(lldb::eLanguageTypeUnknown, Mangled::ePreferMangled),
eSymbolTypeCode,
Symtab::eDebugNo,
Symtab::eVisibilityAny);
@@ -145,7 +145,7 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa
// sizes from the DWARF info as we are parsing.
// Next we find the non-stab entry that corresponds to the N_GSYM in the .o file
- Symbol *oso_gsym_symbol = oso_symtab->FindFirstSymbolWithNameAndType (exe_symbol->GetMangled().GetName(Mangled::ePreferMangled),
+ Symbol *oso_gsym_symbol = oso_symtab->FindFirstSymbolWithNameAndType (exe_symbol->GetMangled().GetName(lldb::eLanguageTypeUnknown, Mangled::ePreferMangled),
eSymbolTypeData,
Symtab::eDebugNo,
Symtab::eVisibilityAny);
diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
index 64c88ab716bf..09b919782608 100644
--- a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
+++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
@@ -161,7 +161,7 @@ SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx)
{
const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]);
if (cu_symbol)
- cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetMangled().GetName().AsCString(), 0, eLanguageTypeUnknown));
+ cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetName().AsCString(), 0, eLanguageTypeUnknown));
}
return cu_sp;
}
diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp
index 3c3e2e51d9af..68bcde8a47c1 100644
--- a/source/Symbol/ClangASTContext.cpp
+++ b/source/Symbol/ClangASTContext.cpp
@@ -1592,6 +1592,7 @@ ClangASTContext::CreateObjCClass
SourceLocation(),
&ast->Idents.get(name),
nullptr,
+ nullptr,
SourceLocation(),
/*isForwardDecl,*/
isInternal);
diff --git a/source/Symbol/ClangASTImporter.cpp b/source/Symbol/ClangASTImporter.cpp
index 64a7323d25cf..dd73b35d86a9 100644
--- a/source/Symbol/ClangASTImporter.cpp
+++ b/source/Symbol/ClangASTImporter.cpp
@@ -17,6 +17,7 @@
#include "lldb/Symbol/ClangASTImporter.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/ClangNamespaceDecl.h"
+#include "lldb/Utility/LLDBAssert.h"
using namespace lldb_private;
using namespace clang;
@@ -109,6 +110,134 @@ ClangASTImporter::CopyDecl (clang::ASTContext *dst_ast,
return nullptr;
}
+class DeclContextOverride
+{
+private:
+ struct Backup
+ {
+ clang::DeclContext *decl_context;
+ clang::DeclContext *lexical_decl_context;
+ };
+
+ std::map<clang::Decl *, Backup> m_backups;
+
+ void OverrideOne(clang::Decl *decl)
+ {
+ if (m_backups.find(decl) != m_backups.end())
+ {
+ return;
+ }
+
+ m_backups[decl] = { decl->getDeclContext(), decl->getLexicalDeclContext() };
+
+ decl->setDeclContext(decl->getASTContext().getTranslationUnitDecl());
+ decl->setLexicalDeclContext(decl->getASTContext().getTranslationUnitDecl());
+ }
+
+ bool ChainPassesThrough(clang::Decl *decl,
+ clang::DeclContext *base,
+ clang::DeclContext *(clang::Decl::*contextFromDecl)(),
+ clang::DeclContext *(clang::DeclContext::*contextFromContext)())
+ {
+ for (DeclContext *decl_ctx = (decl->*contextFromDecl)();
+ decl_ctx;
+ decl_ctx = (decl_ctx->*contextFromContext)())
+ {
+ if (decl_ctx == base)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ clang::Decl *GetEscapedChild(clang::Decl *decl, clang::DeclContext *base = nullptr)
+ {
+ if (base)
+ {
+ // decl's DeclContext chains must pass through base.
+
+ if (!ChainPassesThrough(decl, base, &clang::Decl::getDeclContext, &clang::DeclContext::getParent) ||
+ !ChainPassesThrough(decl, base, &clang::Decl::getLexicalDeclContext, &clang::DeclContext::getLexicalParent))
+ {
+ return decl;
+ }
+ }
+ else
+ {
+ base = clang::dyn_cast<clang::DeclContext>(decl);
+
+ if (!base)
+ {
+ return nullptr;
+ }
+ }
+
+ if (clang::DeclContext *context = clang::dyn_cast<clang::DeclContext>(decl))
+ {
+ for (clang::Decl *decl : context->decls())
+ {
+ if (clang::Decl *escaped_child = GetEscapedChild(decl))
+ {
+ return escaped_child;
+ }
+ }
+ }
+
+ return nullptr;
+ }
+
+ void Override(clang::Decl *decl)
+ {
+ if (clang::Decl *escaped_child = GetEscapedChild(decl))
+ {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ log->Printf(" [ClangASTImporter] DeclContextOverride couldn't override (%sDecl*)%p - its child (%sDecl*)%p escapes",
+ decl->getDeclKindName(), static_cast<void*>(decl),
+ escaped_child->getDeclKindName(), static_cast<void*>(escaped_child));
+ lldbassert(0 && "Couldn't override!");
+ }
+
+ OverrideOne(decl);
+ }
+
+public:
+ DeclContextOverride()
+ {
+ }
+
+ void OverrideAllDeclsFromContainingFunction(clang::Decl *decl)
+ {
+ for (DeclContext *decl_context = decl->getLexicalDeclContext();
+ decl_context;
+ decl_context = decl_context->getLexicalParent())
+ {
+ DeclContext *redecl_context = decl_context->getRedeclContext();
+
+ if (llvm::isa<FunctionDecl>(redecl_context) &&
+ llvm::isa<TranslationUnitDecl>(redecl_context->getLexicalParent()))
+ {
+ for (clang::Decl *child_decl : decl_context->decls())
+ {
+ Override(child_decl);
+ }
+ }
+ }
+ }
+
+ ~DeclContextOverride()
+ {
+ for (const std::pair<clang::Decl *, Backup> &backup : m_backups)
+ {
+ backup.first->setDeclContext(backup.second.decl_context);
+ backup.first->setLexicalDeclContext(backup.second.lexical_decl_context);
+ }
+ }
+};
+
lldb::clang_type_t
ClangASTImporter::DeportType (clang::ASTContext *dst_ctx,
clang::ASTContext *src_ctx,
@@ -122,6 +251,13 @@ ClangASTImporter::DeportType (clang::ASTContext *dst_ctx,
std::set<NamedDecl *> decls_to_deport;
std::set<NamedDecl *> decls_already_deported;
+ DeclContextOverride decl_context_override;
+
+ if (const clang::TagType *tag_type = clang::QualType::getFromOpaquePtr(type)->getAs<TagType>())
+ {
+ decl_context_override.OverrideAllDeclsFromContainingFunction(tag_type->getDecl());
+ }
+
minion_sp->InitDeportWorkQueues(&decls_to_deport,
&decls_already_deported);
@@ -156,6 +292,10 @@ ClangASTImporter::DeportDecl (clang::ASTContext *dst_ctx,
std::set<NamedDecl *> decls_to_deport;
std::set<NamedDecl *> decls_already_deported;
+
+ DeclContextOverride decl_context_override;
+
+ decl_context_override.OverrideAllDeclsFromContainingFunction(decl);
minion_sp->InitDeportWorkQueues(&decls_to_deport,
&decls_already_deported);
@@ -568,7 +708,8 @@ ClangASTImporter::Minion::ImportDefinitionTo (clang::Decl *to, clang::Decl *from
if (!to_objc_interface->hasDefinition())
to_objc_interface->startDefinition();
- to_objc_interface->setSuperClass(imported_from_superclass);
+ to_objc_interface->setSuperClass(
+ m_source_ctx->getTrivialTypeSourceInfo(m_source_ctx->getObjCInterfaceType(imported_from_superclass)));
}
while (0);
}
diff --git a/source/Symbol/ClangASTType.cpp b/source/Symbol/ClangASTType.cpp
index a62cc9f45a6b..6f1002fbd9fc 100644
--- a/source/Symbol/ClangASTType.cpp
+++ b/source/Symbol/ClangASTType.cpp
@@ -5354,7 +5354,9 @@ ClangASTType::SetObjCSuperClass (const ClangASTType &superclass_clang_type)
clang::ObjCInterfaceDecl *super_interface_decl = superclass_clang_type.GetAsObjCInterfaceDecl ();
if (class_interface_decl && super_interface_decl)
{
- class_interface_decl->setSuperClass(super_interface_decl);
+
+ class_interface_decl->setSuperClass(
+ m_ast->getTrivialTypeSourceInfo(m_ast->getObjCInterfaceType(super_interface_decl)));
return true;
}
}
diff --git a/source/Symbol/Function.cpp b/source/Symbol/Function.cpp
index 0b7430ad75e3..77448d4f2a22 100644
--- a/source/Symbol/Function.cpp
+++ b/source/Symbol/Function.cpp
@@ -77,7 +77,7 @@ FunctionInfo::GetDeclaration() const
return m_declaration;
}
-const ConstString&
+ConstString
FunctionInfo::GetName() const
{
return m_name;
@@ -140,25 +140,32 @@ InlineFunctionInfo::Dump(Stream *s, bool show_fullpaths) const
}
void
-InlineFunctionInfo::DumpStopContext (Stream *s) const
+InlineFunctionInfo::DumpStopContext (Stream *s, LanguageType language) const
{
// s->Indent("[inlined] ");
s->Indent();
if (m_mangled)
- s->PutCString (m_mangled.GetName().AsCString());
+ s->PutCString (m_mangled.GetName(language).AsCString());
else
s->PutCString (m_name.AsCString());
}
-const ConstString &
-InlineFunctionInfo::GetName () const
+ConstString
+InlineFunctionInfo::GetName (LanguageType language) const
{
if (m_mangled)
- return m_mangled.GetName();
+ return m_mangled.GetName(language);
return m_name;
}
+ConstString
+InlineFunctionInfo::GetDisplayName (LanguageType language) const
+{
+ if (m_mangled)
+ return m_mangled.GetDisplayDemangledName(language);
+ return m_name;
+}
Declaration &
InlineFunctionInfo::GetCallSite ()
@@ -459,6 +466,14 @@ Function::MemorySize () const
return mem_size;
}
+ConstString
+Function::GetDisplayName () const
+{
+ if (!m_mangled)
+ return ConstString();
+ return m_mangled.GetDisplayDemangledName(GetLanguage());
+}
+
clang::DeclContext *
Function::GetClangDeclContext()
{
@@ -602,5 +617,32 @@ Function::GetPrologueByteSize ()
return m_prologue_byte_size;
}
+lldb::LanguageType
+Function::GetLanguage() const
+{
+ if (m_comp_unit)
+ return m_comp_unit->GetLanguage();
+ else
+ return lldb::eLanguageTypeUnknown;
+}
+
+ConstString
+Function::GetName() const
+{
+ LanguageType language = lldb::eLanguageTypeUnknown;
+ if (m_comp_unit)
+ language = m_comp_unit->GetLanguage();
+ return m_mangled.GetName(language);
+}
+
+ConstString
+Function::GetNameNoArguments() const
+{
+ LanguageType language = lldb::eLanguageTypeUnknown;
+ if (m_comp_unit)
+ language = m_comp_unit->GetLanguage();
+ return m_mangled.GetName(language, Mangled::ePreferDemangledWithoutArguments);
+}
+
diff --git a/source/Symbol/Symbol.cpp b/source/Symbol/Symbol.cpp
index dff15dd92613..5884fcaa551d 100644
--- a/source/Symbol/Symbol.cpp
+++ b/source/Symbol/Symbol.cpp
@@ -185,6 +185,14 @@ Symbol::ValueIsAddress() const
}
ConstString
+Symbol::GetDisplayName () const
+{
+ if (!m_mangled)
+ return ConstString();
+ return m_mangled.GetDisplayDemangledName(GetLanguage());
+}
+
+ConstString
Symbol::GetReExportedSymbolName() const
{
if (m_type == eSymbolTypeReExported)
@@ -288,8 +296,9 @@ Symbol::GetDescription (Stream *s, lldb::DescriptionLevel level, Target *target)
else
s->Printf (", value = 0x%16.16" PRIx64, m_addr_range.GetBaseAddress().GetOffset());
}
- if (m_mangled.GetDemangledName())
- s->Printf(", name=\"%s\"", m_mangled.GetDemangledName().AsCString());
+ ConstString demangled = m_mangled.GetDemangledName(GetLanguage());
+ if (demangled)
+ s->Printf(", name=\"%s\"", demangled.AsCString());
if (m_mangled.GetMangledName())
s->Printf(", mangled=\"%s\"", m_mangled.GetMangledName().AsCString());
@@ -309,6 +318,7 @@ Symbol::Dump(Stream *s, Target *target, uint32_t index) const
// Make sure the size of the symbol is up to date before dumping
GetByteSize();
+ ConstString name = m_mangled.GetName(GetLanguage());
if (ValueIsAddress())
{
if (!m_addr_range.GetBaseAddress().Dump(s, nullptr, Address::DumpStyleFileAddress))
@@ -325,13 +335,13 @@ Symbol::Dump(Stream *s, Target *target, uint32_t index) const
s->Printf( format,
GetByteSize(),
m_flags,
- m_mangled.GetName().AsCString(""));
+ name.AsCString(""));
}
else if (m_type == eSymbolTypeReExported)
{
s->Printf (" 0x%8.8x %s",
m_flags,
- m_mangled.GetName().AsCString(""));
+ name.AsCString(""));
ConstString reexport_name = GetReExportedSymbolName();
intptr_t shlib = m_addr_range.GetByteSize();
@@ -349,7 +359,7 @@ Symbol::Dump(Stream *s, Target *target, uint32_t index) const
m_addr_range.GetBaseAddress().GetOffset(),
GetByteSize(),
m_flags,
- m_mangled.GetName().AsCString(""));
+ name.AsCString(""));
}
}
@@ -439,7 +449,7 @@ bool
Symbol::Compare(const ConstString& name, SymbolType type) const
{
if (type == eSymbolTypeAny || m_type == type)
- return m_mangled.GetMangledName() == name || m_mangled.GetDemangledName() == name;
+ return m_mangled.GetMangledName() == name || m_mangled.GetDemangledName(GetLanguage()) == name;
return false;
}
@@ -635,6 +645,18 @@ Symbol::GetLoadAddress (Target *target) const
return LLDB_INVALID_ADDRESS;
}
+ConstString
+Symbol::GetName () const
+{
+ return m_mangled.GetName(GetLanguage());
+}
+
+ConstString
+Symbol::GetNameNoArguments () const
+{
+ return m_mangled.GetName(GetLanguage(), Mangled::ePreferDemangledWithoutArguments);
+}
+
lldb::addr_t
Symbol::ResolveCallableAddress(Target &target) const
diff --git a/source/Symbol/SymbolContext.cpp b/source/Symbol/SymbolContext.cpp
index 8e4240a4587d..4fb0dbc237c8 100644
--- a/source/Symbol/SymbolContext.cpp
+++ b/source/Symbol/SymbolContext.cpp
@@ -160,15 +160,15 @@ SymbolContext::DumpStopContext (
s->Printf("<");
dumped_something = true;
}
- else if (show_function_arguments == false && function->GetMangled().GetName(Mangled::ePreferDemangledWithoutArguments))
- {
- dumped_something = true;
- function->GetMangled().GetName(Mangled::ePreferDemangledWithoutArguments).Dump(s);
- }
- else if (function->GetMangled().GetName())
+ else
{
- dumped_something = true;
- function->GetMangled().GetName().Dump(s);
+ ConstString name;
+ if (show_function_arguments == false)
+ name = function->GetNameNoArguments();
+ if (!name)
+ name = function->GetName();
+ if (name)
+ name.Dump(s);
}
if (addr.IsValid())
@@ -192,7 +192,7 @@ SymbolContext::DumpStopContext (
dumped_something = true;
Block *inlined_block = block->GetContainingInlinedBlock();
const InlineFunctionInfo* inlined_block_info = inlined_block->GetInlinedFunctionInfo();
- s->Printf (" [inlined] %s", inlined_block_info->GetName().GetCString());
+ s->Printf (" [inlined] %s", inlined_block_info->GetName(function->GetLanguage()).GetCString());
lldb_private::AddressRange block_range;
if (inlined_block->GetRangeContainingAddress(addr, block_range))
@@ -235,12 +235,12 @@ SymbolContext::DumpStopContext (
s->Printf("<");
dumped_something = true;
}
- else if (symbol->GetMangled().GetName())
+ else if (symbol->GetName())
{
dumped_something = true;
if (symbol->GetType() == eSymbolTypeTrampoline)
s->PutCString("symbol stub for: ");
- symbol->GetMangled().GetName().Dump(s);
+ symbol->GetName().Dump(s);
}
if (addr.IsValid() && symbol->ValueIsAddress())
@@ -438,7 +438,7 @@ SymbolContext::Dump(Stream *s, Target *target) const
s->Indent();
*s << "Symbol = " << (void *)symbol;
if (symbol != nullptr && symbol->GetMangled())
- *s << ' ' << symbol->GetMangled().GetName().AsCString();
+ *s << ' ' << symbol->GetName().AsCString();
s->EOL();
*s << "Variable = " << (void *)variable;
if (variable != nullptr)
@@ -681,14 +681,14 @@ SymbolContext::GetFunctionName (Mangled::NamePreference preference) const
{
const InlineFunctionInfo *inline_info = inlined_block->GetInlinedFunctionInfo();
if (inline_info)
- return inline_info->GetName();
+ return inline_info->GetName(function->GetLanguage());
}
}
- return function->GetMangled().GetName(preference);
+ return function->GetMangled().GetName(function->GetLanguage(), preference);
}
else if (symbol && symbol->ValueIsAddress())
{
- return symbol->GetMangled().GetName(preference);
+ return symbol->GetMangled().GetName(symbol->GetLanguage(), preference);
}
else
{
@@ -916,7 +916,7 @@ SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc)
{
was_inlined = true;
const Mangled &name = inline_info->GetMangled();
- if (!name.NameMatches (func_name))
+ if (!name.NameMatches (func_name, sc.function->GetLanguage()))
return false;
}
}
@@ -925,12 +925,12 @@ SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc)
{
if (sc.function != nullptr)
{
- if (!sc.function->GetMangled().NameMatches(func_name))
+ if (!sc.function->GetMangled().NameMatches(func_name, sc.function->GetLanguage()))
return false;
}
else if (sc.symbol != nullptr)
{
- if (!sc.symbol->GetMangled().NameMatches(func_name))
+ if (!sc.symbol->GetMangled().NameMatches(func_name, sc.function->GetLanguage()))
return false;
}
}
diff --git a/source/Symbol/Symtab.cpp b/source/Symbol/Symtab.cpp
index 4cc03345d05b..c11efc0d9b24 100644
--- a/source/Symbol/Symtab.cpp
+++ b/source/Symbol/Symtab.cpp
@@ -136,7 +136,7 @@ Symtab::Dump (Stream *s, Target *target, SortOrder sort_order)
CStringToSymbol name_map;
for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); pos != end; ++pos)
{
- const char *name = pos->GetMangled().GetName(Mangled::ePreferDemangled).AsCString();
+ const char *name = pos->GetName().AsCString();
if (name && name[0])
name_map.insert (std::make_pair(name, &(*pos)));
}
@@ -329,7 +329,7 @@ Symtab::InitNameIndexes()
entry.cstring[2] != 'G' && // avoid guard variables
entry.cstring[2] != 'Z')) // named local entities (if we eventually handle eSymbolTypeData, we will want this back)
{
- CPPLanguageRuntime::MethodName cxx_method (mangled.GetDemangledName());
+ CPPLanguageRuntime::MethodName cxx_method (mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus));
entry.cstring = ConstString(cxx_method.GetBasename()).GetCString();
if (entry.cstring && entry.cstring[0])
{
@@ -378,7 +378,7 @@ Symtab::InitNameIndexes()
}
}
- entry.cstring = mangled.GetDemangledName().GetCString();
+ entry.cstring = mangled.GetDemangledName(symbol->GetLanguage()).GetCString();
if (entry.cstring && entry.cstring[0]) {
m_name_to_index.Append (entry);
@@ -486,7 +486,7 @@ Symtab::AppendSymbolNamesToMap (const IndexCollection &indexes,
const Mangled &mangled = symbol->GetMangled();
if (add_demangled)
{
- entry.cstring = mangled.GetDemangledName().GetCString();
+ entry.cstring = mangled.GetDemangledName(symbol->GetLanguage()).GetCString();
if (entry.cstring && entry.cstring[0])
name_to_index_map.Append (entry);
}
@@ -746,7 +746,7 @@ Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp
{
if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
{
- const char *name = m_symbols[i].GetMangled().GetName().AsCString();
+ const char *name = m_symbols[i].GetName().AsCString();
if (name)
{
if (regexp.Execute (name))
@@ -773,7 +773,7 @@ Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp
if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false)
continue;
- const char *name = m_symbols[i].GetMangled().GetName().AsCString();
+ const char *name = m_symbols[i].GetName().AsCString();
if (name)
{
if (regexp.Execute (name))
diff --git a/source/Symbol/Variable.cpp b/source/Symbol/Variable.cpp
index 5665e4702ca6..2490e98ac1e8 100644
--- a/source/Symbol/Variable.cpp
+++ b/source/Symbol/Variable.cpp
@@ -15,6 +15,7 @@
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Type.h"
@@ -65,22 +66,48 @@ Variable::~Variable()
{
}
+lldb::LanguageType
+Variable::GetLanguage () const
+{
+ SymbolContext variable_sc;
+ m_owner_scope->CalculateSymbolContext(&variable_sc);
+ if (variable_sc.comp_unit)
+ return variable_sc.comp_unit->GetLanguage();
+ return lldb::eLanguageTypeUnknown;
+}
+
-const ConstString&
+
+ConstString
Variable::GetName() const
{
- const ConstString &name = m_mangled.GetName();
+ ConstString name = m_mangled.GetName(GetLanguage());
if (name)
return name;
return m_name;
}
bool
+Variable::NameMatches (const ConstString &name) const
+{
+ if (m_name == name)
+ return true;
+ SymbolContext variable_sc;
+ m_owner_scope->CalculateSymbolContext(&variable_sc);
+
+ LanguageType language = eLanguageTypeUnknown;
+ if (variable_sc.comp_unit)
+ language = variable_sc.comp_unit->GetLanguage();
+ return m_mangled.NameMatches (name, language);
+}
+bool
Variable::NameMatches (const RegularExpression& regex) const
{
if (regex.Execute (m_name.AsCString()))
return true;
- return m_mangled.NameMatches (regex);
+ if (m_mangled)
+ return m_mangled.NameMatches (regex, GetLanguage());
+ return false;
}
Type *
diff --git a/source/Target/Platform.cpp b/source/Target/Platform.cpp
index 6758ecf7e22e..2b586933ccd4 100644
--- a/source/Target/Platform.cpp
+++ b/source/Target/Platform.cpp
@@ -36,6 +36,7 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
+#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/Utils.h"
#include "llvm/Support/FileSystem.h"
@@ -1536,27 +1537,6 @@ Platform::CalculateMD5 (const FileSpec& file_spec,
return false;
}
-Error
-Platform::LaunchNativeProcess (
- ProcessLaunchInfo &launch_info,
- lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
- NativeProcessProtocolSP &process_sp)
-{
- // Platforms should override this implementation if they want to
- // support lldb-gdbserver.
- return Error("unimplemented");
-}
-
-Error
-Platform::AttachNativeProcess (lldb::pid_t pid,
- lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
- NativeProcessProtocolSP &process_sp)
-{
- // Platforms should override this implementation if they want to
- // support lldb-gdbserver.
- return Error("unimplemented");
-}
-
void
Platform::SetLocalCacheDirectory (const char* local)
{
@@ -1951,3 +1931,18 @@ Platform::GetCacheHostname ()
{
return GetHostname ();
}
+
+const UnixSignalsSP &
+Platform::GetRemoteUnixSignals()
+{
+ static const auto s_default_unix_signals_sp = std::make_shared<UnixSignals>();
+ return s_default_unix_signals_sp;
+}
+
+const UnixSignalsSP &
+Platform::GetUnixSignals()
+{
+ if (IsHost())
+ return Host::GetUnixSignals();
+ return GetRemoteUnixSignals();
+}
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index 41942829ca55..3abae4fce5b1 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -693,7 +693,7 @@ Process::GetStaticBroadcasterClass ()
// Process constructor
//----------------------------------------------------------------------
Process::Process(Target &target, Listener &listener) :
- Process(target, listener, Host::GetUnixSignals ())
+ Process(target, listener, UnixSignals::Create(HostInfo::GetArchitecture()))
{
// This constructor just delegates to the full Process constructor,
// defaulting to using the Host's UnixSignals.
@@ -754,6 +754,7 @@ Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_s
m_force_next_event_delivery (false),
m_last_broadcast_state (eStateInvalid),
m_destroy_in_process (false),
+ m_can_interpret_function_calls(false),
m_can_jit(eCanJITDontKnow)
{
CheckInWithManager ();
@@ -763,14 +764,14 @@ Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_s
log->Printf ("%p Process::Process()", static_cast<void*>(this));
if (!m_unix_signals_sp)
- m_unix_signals_sp.reset (new UnixSignals ());
+ m_unix_signals_sp = std::make_shared<UnixSignals>();
SetEventName (eBroadcastBitStateChanged, "state-changed");
SetEventName (eBroadcastBitInterrupt, "interrupt");
SetEventName (eBroadcastBitSTDOUT, "stdout-available");
SetEventName (eBroadcastBitSTDERR, "stderr-available");
SetEventName (eBroadcastBitProfileData, "profile-data-available");
-
+
m_private_state_control_broadcaster.SetEventName (eBroadcastInternalStateControlStop , "control-stop" );
m_private_state_control_broadcaster.SetEventName (eBroadcastInternalStateControlPause , "control-pause" );
m_private_state_control_broadcaster.SetEventName (eBroadcastInternalStateControlResume, "control-resume");
@@ -1145,6 +1146,7 @@ Process::HandleProcessStateChangedEvent (const EventSP &event_sp,
// Prefer a thread that has just completed its plan over another thread as current thread.
ThreadSP plan_thread;
ThreadSP other_thread;
+
const size_t num_threads = thread_list.GetSize();
size_t i;
for (i = 0; i < num_threads; ++i)
@@ -1157,10 +1159,22 @@ Process::HandleProcessStateChangedEvent (const EventSP &event_sp,
case eStopReasonNone:
break;
+ case eStopReasonSignal:
+ {
+ // Don't select a signal thread if we weren't going to stop at that
+ // signal. We have to have had another reason for stopping here, and
+ // the user doesn't want to see this thread.
+ uint64_t signo = thread->GetStopInfo()->GetValue();
+ if (process_sp->GetUnixSignals()->GetShouldStop(signo))
+ {
+ if (!other_thread)
+ other_thread = thread;
+ }
+ break;
+ }
case eStopReasonTrace:
case eStopReasonBreakpoint:
case eStopReasonWatchpoint:
- case eStopReasonSignal:
case eStopReasonException:
case eStopReasonExec:
case eStopReasonThreadExiting:
@@ -1510,7 +1524,7 @@ Process::SetProcessExitStatus (void *callback_baton,
{
const char *signal_cstr = NULL;
if (signo)
- signal_cstr = process_sp->GetUnixSignals().GetSignalAsCString (signo);
+ signal_cstr = process_sp->GetUnixSignals()->GetSignalAsCString(signo);
process_sp->SetExitStatus (exit_status, signal_cstr);
}
@@ -2998,6 +3012,13 @@ Process::SetCanJIT (bool can_jit)
m_can_jit = (can_jit ? eCanJITYes : eCanJITNo);
}
+void
+Process::SetCanRunCode (bool can_run_code)
+{
+ SetCanJIT(can_run_code);
+ m_can_interpret_function_calls = can_run_code;
+}
+
Error
Process::DeallocateMemory (addr_t ptr)
{
@@ -4088,11 +4109,11 @@ Process::SetUnixSignals (const UnixSignalsSP &signals_sp)
m_unix_signals_sp = signals_sp;
}
-UnixSignals &
+const lldb::UnixSignalsSP &
Process::GetUnixSignals ()
{
assert (m_unix_signals_sp && "null m_unix_signals_sp");
- return *m_unix_signals_sp;
+ return m_unix_signals_sp;
}
lldb::ByteOrder
diff --git a/source/Target/ProcessLaunchInfo.cpp b/source/Target/ProcessLaunchInfo.cpp
index 30c5aee63cad..bd2e1bc4c4a1 100644
--- a/source/Target/ProcessLaunchInfo.cpp
+++ b/source/Target/ProcessLaunchInfo.cpp
@@ -284,6 +284,13 @@ ProcessLaunchInfo::FinalizeFileActions (Target *target, bool default_to_use_pty)
log->Printf ("ProcessLaunchInfo::%s at least one of stdin/stdout/stderr was not set, evaluating default handling",
__FUNCTION__);
+ if (m_flags.Test(eLaunchFlagLaunchInTTY))
+ {
+ // Do nothing, if we are launching in a remote terminal
+ // no file actions should be done at all.
+ return;
+ }
+
if (m_flags.Test(eLaunchFlagDisableSTDIO))
{
if (log)
diff --git a/source/Target/StopInfo.cpp b/source/Target/StopInfo.cpp
index 76e5f374f952..4f6ef7a92949 100644
--- a/source/Target/StopInfo.cpp
+++ b/source/Target/StopInfo.cpp
@@ -891,7 +891,7 @@ public:
{
ThreadSP thread_sp (m_thread_wp.lock());
if (thread_sp)
- return thread_sp->GetProcess()->GetUnixSignals().GetShouldStop (m_value);
+ return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value);
return false;
}
@@ -900,7 +900,7 @@ public:
{
ThreadSP thread_sp (m_thread_wp.lock());
if (thread_sp)
- return thread_sp->GetProcess()->GetUnixSignals().GetShouldStop (m_value);
+ return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value);
return false;
}
@@ -912,13 +912,13 @@ public:
ThreadSP thread_sp (m_thread_wp.lock());
if (thread_sp)
{
- bool should_notify = thread_sp->GetProcess()->GetUnixSignals().GetShouldNotify (m_value);
+ bool should_notify = thread_sp->GetProcess()->GetUnixSignals()->GetShouldNotify(m_value);
if (should_notify)
{
StreamString strm;
strm.Printf ("thread %d received signal: %s",
thread_sp->GetIndexID(),
- thread_sp->GetProcess()->GetUnixSignals().GetSignalAsCString (m_value));
+ thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString(m_value));
Process::ProcessEventData::AddRestartedReason(event_ptr, strm.GetData());
}
return should_notify;
@@ -933,7 +933,7 @@ public:
ThreadSP thread_sp (m_thread_wp.lock());
if (thread_sp)
{
- if (thread_sp->GetProcess()->GetUnixSignals().GetShouldSuppress(m_value) == false)
+ if (thread_sp->GetProcess()->GetUnixSignals()->GetShouldSuppress(m_value) == false)
thread_sp->SetResumeSignal(m_value);
}
}
@@ -947,7 +947,7 @@ public:
if (thread_sp)
{
StreamString strm;
- const char *signal_name = thread_sp->GetProcess()->GetUnixSignals().GetSignalAsCString (m_value);
+ const char *signal_name = thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString(m_value);
if (signal_name)
strm.Printf("signal %s", signal_name);
else
diff --git a/source/Target/ThreadPlanCallFunction.cpp b/source/Target/ThreadPlanCallFunction.cpp
index e742ece7ec50..e7b3abd3c941 100644
--- a/source/Target/ThreadPlanCallFunction.cpp
+++ b/source/Target/ThreadPlanCallFunction.cpp
@@ -147,15 +147,16 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
m_trap_exceptions (options.GetTrapExceptions()),
m_function_addr (function),
m_function_sp (0),
- m_return_type (return_type),
m_takedown_done (false),
m_should_clear_objc_exception_bp(false),
m_should_clear_cxx_exception_bp (false),
- m_stop_address (LLDB_INVALID_ADDRESS)
+ m_stop_address (LLDB_INVALID_ADDRESS),
+ m_return_type (return_type)
{
- lldb::addr_t start_load_addr;
- ABI *abi;
- lldb::addr_t function_load_addr;
+ lldb::addr_t start_load_addr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t function_load_addr = LLDB_INVALID_ADDRESS;
+ ABI *abi = nullptr;
+
if (!ConstructorSetup (thread, abi, start_load_addr, function_load_addr))
return;
@@ -171,6 +172,27 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
m_valid = true;
}
+ThreadPlanCallFunction::ThreadPlanCallFunction(Thread &thread,
+ const Address &function,
+ const EvaluateExpressionOptions &options) :
+ ThreadPlan(ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
+ m_valid(false),
+ m_stop_other_threads(options.GetStopOthers()),
+ m_unwind_on_error(options.DoesUnwindOnError()),
+ m_ignore_breakpoints(options.DoesIgnoreBreakpoints()),
+ m_debug_execution(options.GetDebug()),
+ m_trap_exceptions(options.GetTrapExceptions()),
+ m_function_addr(function),
+ m_function_sp(0),
+ m_takedown_done(false),
+ m_should_clear_objc_exception_bp(false),
+ m_should_clear_cxx_exception_bp(false),
+ m_stop_address(LLDB_INVALID_ADDRESS),
+ m_return_type(ClangASTType())
+{
+
+}
+
ThreadPlanCallFunction::~ThreadPlanCallFunction ()
{
DoTakedown(PlanSucceeded());
@@ -222,13 +244,7 @@ ThreadPlanCallFunction::DoTakedown (bool success)
{
if (success)
{
- ProcessSP process_sp (m_thread.GetProcess());
- const ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
- if (abi && m_return_type.IsValid())
- {
- const bool persistent = false;
- m_return_valobj_sp = abi->GetReturnValueObject (m_thread, m_return_type, persistent);
- }
+ SetReturnValue();
}
if (log)
log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called for thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n",
@@ -574,3 +590,15 @@ ThreadPlanCallFunction::RestoreThreadState()
return GetThread().RestoreThreadStateFromCheckpoint(m_stored_thread_state);
}
+
+void
+ThreadPlanCallFunction::SetReturnValue()
+{
+ ProcessSP process_sp(m_thread.GetProcess());
+ const ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
+ if (abi && m_return_type.IsValid())
+ {
+ const bool persistent = false;
+ m_return_valobj_sp = abi->GetReturnValueObject(m_thread, m_return_type, persistent);
+ }
+}
diff --git a/source/Target/ThreadPlanCallFunctionUsingABI.cpp b/source/Target/ThreadPlanCallFunctionUsingABI.cpp
new file mode 100644
index 000000000000..53fabd2464e6
--- /dev/null
+++ b/source/Target/ThreadPlanCallFunctionUsingABI.cpp
@@ -0,0 +1,91 @@
+//===-- ThreadPlanCallFunctionUsingABI.cpp ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadPlanCallFunctionUsingABI.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//--------------------------------------------------------------------------------------------
+// ThreadPlanCallFunctionUsingABI: Plan to call a single function using the ABI instead of JIT
+//-------------------------------------------------------------------------------------------
+ThreadPlanCallFunctionUsingABI::ThreadPlanCallFunctionUsingABI (Thread &thread,
+ const Address &function,
+ llvm::Type &prototype,
+ llvm::Type &return_type,
+ llvm::ArrayRef<ABI::CallArgument> args,
+ const EvaluateExpressionOptions &options) :
+ ThreadPlanCallFunction(thread,function,options),
+ m_return_type(return_type)
+{
+ lldb::addr_t start_load_addr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t function_load_addr = LLDB_INVALID_ADDRESS;
+ ABI *abi = nullptr;
+
+ if (!ConstructorSetup(thread, abi, start_load_addr, function_load_addr))
+ return;
+
+ if (!abi->PrepareTrivialCall(thread,
+ m_function_sp,
+ function_load_addr,
+ start_load_addr,
+ prototype,
+ args))
+ return;
+
+ ReportRegisterState("ABI Function call was set up. Register state was:");
+
+ m_valid = true;
+}
+
+ThreadPlanCallFunctionUsingABI::~ThreadPlanCallFunctionUsingABI()
+{
+
+}
+
+void
+ThreadPlanCallFunctionUsingABI::GetDescription(Stream *s, DescriptionLevel level)
+{
+ if (level == eDescriptionLevelBrief)
+ {
+ s->Printf("Function call thread plan using ABI instead of JIT");
+ }
+ else
+ {
+ TargetSP target_sp(m_thread.CalculateTarget());
+ s->Printf("Thread plan to call 0x%" PRIx64" using ABI instead of JIT", m_function_addr.GetLoadAddress(target_sp.get()));
+ }
+}
+
+void
+ThreadPlanCallFunctionUsingABI::SetReturnValue()
+{
+ ProcessSP process_sp(m_thread.GetProcess());
+ const ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
+
+ // Ask the abi for the return value
+ if (abi)
+ {
+ const bool persistent = false;
+ m_return_valobj_sp = abi->GetReturnValueObject(m_thread, m_return_type, persistent);
+ }
+}
diff --git a/source/Target/ThreadPlanStepOverRange.cpp b/source/Target/ThreadPlanStepOverRange.cpp
index 701e93d3c4de..aba89224239c 100644
--- a/source/Target/ThreadPlanStepOverRange.cpp
+++ b/source/Target/ThreadPlanStepOverRange.cpp
@@ -430,7 +430,7 @@ ThreadPlanStepOverRange::DoWillResume (lldb::StateType resume_state, bool curren
const InlineFunctionInfo *inline_info = frame_block->GetInlinedFunctionInfo();
const char *name;
if (inline_info)
- name = inline_info->GetName().AsCString();
+ name = inline_info->GetName(frame_block->CalculateSymbolContextFunction()->GetLanguage()).AsCString();
else
name = "<unknown-notinlined>";
diff --git a/source/Target/UnixSignals.cpp b/source/Target/UnixSignals.cpp
index 7f57579c1ee5..91579e8d7852 100644
--- a/source/Target/UnixSignals.cpp
+++ b/source/Target/UnixSignals.cpp
@@ -13,16 +13,21 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Core/ArchSpec.h"
#include "lldb/Host/StringConvert.h"
+#include "Plugins/Process/Utility/FreeBSDSignals.h"
+#include "Plugins/Process/Utility/LinuxSignals.h"
+#include "Plugins/Process/Utility/MipsLinuxSignals.h"
+
using namespace lldb_private;
-UnixSignals::Signal::Signal
+UnixSignals::Signal::Signal
(
- const char *name,
- const char *short_name,
- bool default_suppress,
- bool default_stop,
+ const char *name,
+ const char *short_name,
+ bool default_suppress,
+ bool default_stop,
bool default_notify,
const char *description
) :
@@ -37,6 +42,34 @@ UnixSignals::Signal::Signal
m_description.assign (description);
}
+lldb::UnixSignalsSP
+UnixSignals::Create(const ArchSpec &arch)
+{
+ const auto &triple = arch.GetTriple();
+ switch (triple.getOS())
+ {
+ case llvm::Triple::Linux:
+ {
+ switch (triple.getArch())
+ {
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ return std::make_shared<MipsLinuxSignals>();
+ default:
+ return std::make_shared<LinuxSignals>();
+ }
+ }
+ case llvm::Triple::FreeBSD:
+ case llvm::Triple::OpenBSD:
+ case llvm::Triple::NetBSD:
+ return std::make_shared<FreeBSDSignals>();
+ default:
+ return std::make_shared<UnixSignals>();
+ }
+}
+
//----------------------------------------------------------------------
// UnixSignals constructor
//----------------------------------------------------------------------
@@ -45,6 +78,11 @@ UnixSignals::UnixSignals ()
Reset ();
}
+UnixSignals::UnixSignals(const UnixSignals &rhs)
+ : m_signals(rhs.m_signals)
+{
+}
+
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
@@ -291,3 +329,19 @@ UnixSignals::SetShouldNotify (const char *signal_name, bool value)
return SetShouldNotify (signo, value);
return false;
}
+
+int32_t
+UnixSignals::GetNumSignals() const
+{
+ return m_signals.size();
+}
+
+int32_t
+UnixSignals::GetSignalAtIndex(int32_t index) const
+{
+ if (index < 0 || m_signals.size() <= static_cast<size_t>(index))
+ return LLDB_INVALID_SIGNAL_NUMBER;
+ auto it = m_signals.begin();
+ std::advance(it, index);
+ return it->first;
+}
diff --git a/source/Utility/JSON.cpp b/source/Utility/JSON.cpp
index 0ba8cf4399ce..1e16a5ac9952 100644
--- a/source/Utility/JSON.cpp
+++ b/source/Utility/JSON.cpp
@@ -9,6 +9,10 @@
#include "lldb/Utility/JSON.h"
+#include <limits.h>
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/StringConvert.h"
+
using namespace lldb_private;
std::string
@@ -33,20 +37,20 @@ JSONString::json_string_quote_metachars (const std::string &s)
}
JSONString::JSONString () :
-JSONValue(JSONValue::Kind::String),
-m_data()
+ JSONValue(JSONValue::Kind::String),
+ m_data()
{
}
JSONString::JSONString (const char* s) :
-JSONValue(JSONValue::Kind::String),
-m_data(s ? s : "")
+ JSONValue(JSONValue::Kind::String),
+ m_data(s ? s : "")
{
}
JSONString::JSONString (const std::string& s) :
-JSONValue(JSONValue::Kind::String),
-m_data(s)
+ JSONValue(JSONValue::Kind::String),
+ m_data(s)
{
}
@@ -57,25 +61,41 @@ JSONString::Write (Stream& s)
}
JSONNumber::JSONNumber () :
-JSONValue(JSONValue::Kind::Number),
-m_data(0)
+ JSONValue(JSONValue::Kind::Number),
+ m_is_integer(true),
+ m_data(0),
+ m_double(0.0)
+{
+}
+
+JSONNumber::JSONNumber (uint64_t i) :
+ JSONValue(JSONValue::Kind::Number),
+ m_is_integer(true),
+ m_data(i),
+ m_double(0.0)
{
}
-JSONNumber::JSONNumber (int64_t i) :
-JSONValue(JSONValue::Kind::Number),
-m_data(i)
+
+JSONNumber::JSONNumber (double d) :
+ JSONValue(JSONValue::Kind::Number),
+ m_is_integer(false),
+ m_data(0),
+ m_double(d)
{
}
void
JSONNumber::Write (Stream& s)
{
- s.Printf("%" PRId64, m_data);
+ if (m_is_integer)
+ s.Printf("%" PRIu64, m_data);
+ else
+ s.Printf("%g", m_double);
}
JSONTrue::JSONTrue () :
-JSONValue(JSONValue::Kind::True)
+ JSONValue(JSONValue::Kind::True)
{
}
@@ -86,7 +106,7 @@ JSONTrue::Write(Stream& s)
}
JSONFalse::JSONFalse () :
-JSONValue(JSONValue::Kind::False)
+ JSONValue(JSONValue::Kind::False)
{
}
@@ -97,7 +117,7 @@ JSONFalse::Write(Stream& s)
}
JSONNull::JSONNull () :
-JSONValue(JSONValue::Kind::Null)
+ JSONValue(JSONValue::Kind::Null)
{
}
@@ -108,7 +128,7 @@ JSONNull::Write(Stream& s)
}
JSONObject::JSONObject () :
-JSONValue(JSONValue::Kind::Object)
+ JSONValue(JSONValue::Kind::Object)
{
}
@@ -153,7 +173,7 @@ JSONObject::GetObject (const std::string& key)
}
JSONArray::JSONArray () :
-JSONValue(JSONValue::Kind::Array)
+ JSONValue(JSONValue::Kind::Array)
{
}
@@ -215,3 +235,419 @@ JSONArray::GetNumElements ()
{
return m_elements.size();
}
+
+
+JSONParser::JSONParser (const char *cstr) :
+ StringExtractor(cstr)
+{
+}
+
+JSONParser::Token
+JSONParser::GetToken (std::string &value)
+{
+ StreamString error;
+
+ value.clear();
+ SkipSpaces ();
+ const uint64_t start_index = m_index;
+ const char ch = GetChar();
+ switch (ch)
+ {
+ case '{': return Token::ObjectStart;
+ case '}': return Token::ObjectEnd;
+ case '[': return Token::ArrayStart;
+ case ']': return Token::ArrayEnd;
+ case ',': return Token::Comma;
+ case ':': return Token::Colon;
+ case '\0': return Token::EndOfFile;
+ case 't':
+ if (GetChar() == 'r')
+ if (GetChar() == 'u')
+ if (GetChar() == 'e')
+ return Token::True;
+ break;
+
+ case 'f':
+ if (GetChar() == 'a')
+ if (GetChar() == 'l')
+ if (GetChar() == 's')
+ if (GetChar() == 'e')
+ return Token::False;
+ break;
+
+ case 'n':
+ if (GetChar() == 'u')
+ if (GetChar() == 'l')
+ if (GetChar() == 'l')
+ return Token::Null;
+ break;
+
+ case '"':
+ {
+ while (1)
+ {
+ bool was_escaped = false;
+ int escaped_ch = GetEscapedChar(was_escaped);
+ if (escaped_ch == -1)
+ {
+ error.Printf("error: an error occurred getting a character from offset %" PRIu64, start_index);
+ value = std::move(error.GetString());
+ return Token::Error;
+
+ }
+ else
+ {
+ const bool is_end_quote = escaped_ch == '"';
+ const bool is_null = escaped_ch == 0;
+ if (was_escaped || (!is_end_quote && !is_null))
+ {
+ if (CHAR_MIN <= escaped_ch && escaped_ch <= CHAR_MAX)
+ {
+ value.append(1, (char)escaped_ch);
+ }
+ else
+ {
+ error.Printf("error: wide character support is needed for unicode character 0x%4.4x at offset %" PRIu64, escaped_ch, start_index);
+ value = std::move(error.GetString());
+ return Token::Error;
+ }
+ }
+ else if (is_end_quote)
+ {
+ return Token::String;
+ }
+ else if (is_null)
+ {
+ value = "error: missing end quote for string";
+ return Token::Error;
+ }
+ }
+ }
+ }
+ break;
+
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ bool done = false;
+ bool got_decimal_point = false;
+ uint64_t exp_index = 0;
+ bool got_int_digits = (ch >= '0') && (ch <= '9');
+ bool got_frac_digits = false;
+ bool got_exp_digits = false;
+ while (!done)
+ {
+ const char next_ch = PeekChar();
+ switch (next_ch)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (exp_index != 0)
+ {
+ got_exp_digits = true;
+ }
+ else if (got_decimal_point)
+ {
+ got_frac_digits = true;
+ }
+ else
+ {
+ got_int_digits = true;
+ }
+ ++m_index; // Skip this character
+ break;
+
+ case '.':
+ if (got_decimal_point)
+ {
+ error.Printf("error: extra decimal point found at offset %" PRIu64, start_index);
+ value = std::move(error.GetString());
+ return Token::Error;
+ }
+ else
+ {
+ got_decimal_point = true;
+ ++m_index; // Skip this character
+ }
+ break;
+
+ case 'e':
+ case 'E':
+ if (exp_index != 0)
+ {
+ error.Printf("error: extra expenent character found at offset %" PRIu64, start_index);
+ value = std::move(error.GetString());
+ return Token::Error;
+ }
+ else
+ {
+ exp_index = m_index;
+ ++m_index; // Skip this character
+ }
+ break;
+
+ case '+':
+ case '-':
+ // The '+' and '-' can only come after an exponent character...
+ if (exp_index == m_index - 1)
+ {
+ ++m_index; // Skip the exponent sign character
+ }
+ else
+ {
+ error.Printf("error: unexpected %c character at offset %" PRIu64, next_ch, start_index);
+ value = std::move(error.GetString());
+ return Token::Error;
+ }
+
+ default:
+ done = true;
+ break;
+ }
+ }
+
+ if (m_index > start_index)
+ {
+ value = m_packet.substr(start_index, m_index - start_index);
+ if (got_decimal_point)
+ {
+ if (exp_index != 0)
+ {
+ // We have an exponent, make sure we got exponent digits
+ if (got_exp_digits)
+ {
+ return Token::Float;
+ }
+ else
+ {
+ error.Printf("error: got exponent character but no exponent digits at offset in float value \"%s\"", value.c_str());
+ value = std::move(error.GetString());
+ return Token::Error;
+ }
+ }
+ else
+ {
+ // No exponent, but we need at least one decimal after the decimal point
+ if (got_frac_digits)
+ {
+ return Token::Float;
+ }
+ else
+ {
+ error.Printf("error: no digits after decimal point \"%s\"", value.c_str());
+ value = std::move(error.GetString());
+ return Token::Error;
+ }
+ }
+ }
+ else
+ {
+ // No decimal point
+ if (got_int_digits)
+ {
+ // We need at least some integer digits to make an integer
+ return Token::Integer;
+ }
+ else
+ {
+ error.Printf("error: no digits negate sign \"%s\"", value.c_str());
+ value = std::move(error.GetString());
+ return Token::Error;
+ }
+ }
+ }
+ else
+ {
+ error.Printf("error: invalid number found at offset %" PRIu64, start_index);
+ value = std::move(error.GetString());
+ return Token::Error;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ error.Printf("error: failed to parse token at offset %" PRIu64 " (around character '%c')", start_index, ch);
+ value = std::move(error.GetString());
+ return Token::Error;
+}
+
+int
+JSONParser::GetEscapedChar(bool &was_escaped)
+{
+ was_escaped = false;
+ const char ch = GetChar();
+ if (ch == '\\')
+ {
+ was_escaped = true;
+ const char ch2 = GetChar();
+ switch (ch2)
+ {
+ case '"':
+ case '\\':
+ case '/':
+ default:
+ break;
+
+ case 'b': return '\b';
+ case 'f': return '\f';
+ case 'n': return '\n';
+ case 'r': return '\r';
+ case 't': return '\t';
+ case 'u':
+ {
+ const int hi_byte = DecodeHexU8();
+ const int lo_byte = DecodeHexU8();
+ if (hi_byte >=0 && lo_byte >= 0)
+ return hi_byte << 8 | lo_byte;
+ return -1;
+ }
+ break;
+ }
+ return ch2;
+ }
+ return ch;
+}
+
+JSONValue::SP
+JSONParser::ParseJSONObject ()
+{
+ // The "JSONParser::Token::ObjectStart" token should have already been consumed
+ // by the time this function is called
+ std::unique_ptr<JSONObject> dict_up(new JSONObject());
+
+ std::string value;
+ std::string key;
+ while (1)
+ {
+ JSONParser::Token token = GetToken(value);
+
+ if (token == JSONParser::Token::String)
+ {
+ key.swap(value);
+ token = GetToken(value);
+ if (token == JSONParser::Token::Colon)
+ {
+ JSONValue::SP value_sp = ParseJSONValue();
+ if (value_sp)
+ dict_up->SetObject(key, value_sp);
+ else
+ break;
+ }
+ }
+ else if (token == JSONParser::Token::ObjectEnd)
+ {
+ return JSONValue::SP(dict_up.release());
+ }
+ else if (token == JSONParser::Token::Comma)
+ {
+ continue;
+ }
+ else
+ {
+ break;
+ }
+ }
+ return JSONValue::SP();
+}
+
+JSONValue::SP
+JSONParser::ParseJSONArray ()
+{
+ // The "JSONParser::Token::ObjectStart" token should have already been consumed
+ // by the time this function is called
+ std::unique_ptr<JSONArray> array_up(new JSONArray());
+
+ std::string value;
+ std::string key;
+ while (1)
+ {
+ JSONValue::SP value_sp = ParseJSONValue();
+ if (value_sp)
+ array_up->AppendObject(value_sp);
+ else
+ break;
+
+ JSONParser::Token token = GetToken(value);
+ if (token == JSONParser::Token::Comma)
+ {
+ continue;
+ }
+ else if (token == JSONParser::Token::ArrayEnd)
+ {
+ return JSONValue::SP(array_up.release());
+ }
+ else
+ {
+ break;
+ }
+ }
+ return JSONValue::SP();
+}
+
+JSONValue::SP
+JSONParser::ParseJSONValue ()
+{
+ std::string value;
+ const JSONParser::Token token = GetToken(value);
+ switch (token)
+ {
+ case JSONParser::Token::ObjectStart:
+ return ParseJSONObject();
+
+ case JSONParser::Token::ArrayStart:
+ return ParseJSONArray();
+
+ case JSONParser::Token::Integer:
+ {
+ bool success = false;
+ uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success);
+ if (success)
+ return JSONValue::SP(new JSONNumber(uval));
+ }
+ break;
+
+ case JSONParser::Token::Float:
+ {
+ bool success = false;
+ double val = StringConvert::ToDouble(value.c_str(), 0.0, &success);
+ if (success)
+ return JSONValue::SP(new JSONNumber(val));
+ }
+ break;
+
+ case JSONParser::Token::String:
+ return JSONValue::SP(new JSONString(value));
+
+ case JSONParser::Token::True:
+ return JSONValue::SP(new JSONTrue());
+
+ case JSONParser::Token::False:
+ return JSONValue::SP(new JSONFalse());
+
+ case JSONParser::Token::Null:
+ return JSONValue::SP(new JSONNull());
+
+ default:
+ break;
+ }
+ return JSONValue::SP();
+
+}
diff --git a/source/Utility/StringExtractor.cpp b/source/Utility/StringExtractor.cpp
index e82c83dfd093..6302c033c0c1 100644
--- a/source/Utility/StringExtractor.cpp
+++ b/source/Utility/StringExtractor.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "Utility/StringExtractor.h"
+#include "lldb/Utility/StringExtractor.h"
// C Includes
#include <stdlib.h>
@@ -476,3 +476,12 @@ StringExtractor::GetNameColonValue (std::string &name, std::string &value)
m_index = UINT64_MAX;
return false;
}
+
+void
+StringExtractor::SkipSpaces ()
+{
+ const size_t n = m_packet.size();
+ while (m_index < n && isspace(m_packet[m_index]))
+ ++m_index;
+}
+
diff --git a/source/Utility/StringExtractor.h b/source/Utility/StringExtractor.h
deleted file mode 100644
index 49dfe99bd358..000000000000
--- a/source/Utility/StringExtractor.h
+++ /dev/null
@@ -1,164 +0,0 @@
-//===-- StringExtractor.h ---------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef utility_StringExtractor_h_
-#define utility_StringExtractor_h_
-
-// C Includes
-// C++ Includes
-#include <string>
-#include <stdint.h>
-
-// Other libraries and framework includes
-// Project includes
-
-class StringExtractor
-{
-public:
-
- enum {
- BigEndian = 0,
- LittleEndian = 1
- };
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- StringExtractor();
- StringExtractor(const char *packet_cstr);
- StringExtractor(const StringExtractor& rhs);
- virtual ~StringExtractor();
-
- //------------------------------------------------------------------
- // Operators
- //------------------------------------------------------------------
- const StringExtractor&
- operator=(const StringExtractor& rhs);
-
- // Returns true if the file position is still valid for the data
- // contained in this string extractor object.
- bool
- IsGood() const
- {
- return m_index != UINT64_MAX;
- }
-
- uint64_t
- GetFilePos () const
- {
- return m_index;
- }
-
- void
- SetFilePos (uint32_t idx)
- {
- m_index = idx;
- }
-
- void
- Clear ()
- {
- m_packet.clear();
- m_index = 0;
- }
-
- std::string &
- GetStringRef ()
- {
- return m_packet;
- }
-
- const std::string &
- GetStringRef () const
- {
- return m_packet;
- }
-
- bool
- Empty()
- {
- return m_packet.empty();
- }
-
- size_t
- GetBytesLeft ()
- {
- if (m_index < m_packet.size())
- return m_packet.size() - m_index;
- return 0;
- }
-
- char
- GetChar (char fail_value = '\0');
-
- int
- DecodeHexU8();
-
- uint8_t
- GetHexU8 (uint8_t fail_value = 0, bool set_eof_on_fail = true);
-
- bool
- GetNameColonValue (std::string &name, std::string &value);
-
- int32_t
- GetS32 (int32_t fail_value, int base = 0);
-
- uint32_t
- GetU32 (uint32_t fail_value, int base = 0);
-
- int64_t
- GetS64 (int64_t fail_value, int base = 0);
-
- uint64_t
- GetU64 (uint64_t fail_value, int base = 0);
-
- uint32_t
- GetHexMaxU32 (bool little_endian, uint32_t fail_value);
-
- uint64_t
- GetHexMaxU64 (bool little_endian, uint64_t fail_value);
-
- size_t
- GetHexBytes (void *dst, size_t dst_len, uint8_t fail_fill_value);
-
- size_t
- GetHexBytesAvail (void *dst, size_t dst_len);
-
- uint64_t
- GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value);
-
- size_t
- GetHexByteString (std::string &str);
-
- size_t
- GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length);
-
- size_t
- GetHexByteStringTerminatedBy (std::string &str,
- char terminator);
-
- const char *
- Peek ()
- {
- if (m_index < m_packet.size())
- return m_packet.c_str() + m_index;
- return nullptr;
- }
-
-protected:
- //------------------------------------------------------------------
- // For StringExtractor only
- //------------------------------------------------------------------
- std::string m_packet; // The string in which to extract data.
- uint64_t m_index; // When extracting data from a packet, this index
- // will march along as things get extracted. If set
- // to UINT64_MAX the end of the packet data was
- // reached when decoding information
-};
-
-#endif // utility_StringExtractor_h_
diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp
index aeceaa00fa1c..17ee0b63f3e5 100644
--- a/source/Utility/StringExtractorGDBRemote.cpp
+++ b/source/Utility/StringExtractorGDBRemote.cpp
@@ -82,7 +82,7 @@ StringExtractorGDBRemote::GetServerPacketType () const
case 'A':
return eServerPacketType_A;
-
+
case 'Q':
switch (packet_cstr[1])
@@ -122,7 +122,7 @@ StringExtractorGDBRemote::GetServerPacketType () const
break;
}
break;
-
+
case 'q':
switch (packet_cstr[1])
{
@@ -219,6 +219,10 @@ StringExtractorGDBRemote::GetServerPacketType () const
break;
}
break;
+
+ case 'j':
+ if (PACKET_MATCHES("jSignalInfo")) return eServerPacketType_jSignalsInfo;
+
case 'v':
if (PACKET_STARTS_WITH("vFile:"))
{
diff --git a/source/Utility/StringExtractorGDBRemote.h b/source/Utility/StringExtractorGDBRemote.h
index beb07e5b57ea..475b5a8e36c8 100644
--- a/source/Utility/StringExtractorGDBRemote.h
+++ b/source/Utility/StringExtractorGDBRemote.h
@@ -15,7 +15,7 @@
#include <string>
// Other libraries and framework includes
// Project includes
-#include "Utility/StringExtractor.h"
+#include "lldb/Utility/StringExtractor.h"
class StringExtractorGDBRemote : public StringExtractor
{
@@ -118,6 +118,8 @@ public:
eServerPacketType_qWatchpointSupportInfoSupported,
eServerPacketType_qXfer_auxv_read,
+ eServerPacketType_jSignalsInfo,
+
eServerPacketType_vAttach,
eServerPacketType_vAttachWait,
eServerPacketType_vAttachOrWait,