forked from OSchip/llvm-project
Python summary strings:
- you can use a Python script to write a summary string for data-types, in one of three ways: -P option and typing the script a line at a time -s option and passing a one-line Python script -F option and passing the name of a Python function these options all work for the "type summary add" command your Python code (if provided through -P or -s) is wrapped in a function that accepts two parameters: valobj (a ValueObject) and dict (an LLDB internal dictionary object). if you use -F and give a function name, you're expected to define the function on your own and with the right prototype. your function, however defined, must return a Python string - test case for the Python summary feature - a few quirks: Python summaries cannot have names, and cannot use regex as type names both issues will be fixed ASAP major redesign of type summary code: - type summary working with strings and type summary working with Python code are two classes, with a common base class SummaryFormat - SummaryFormat classes now are able to actively format objects rather than just aggregating data - cleaner code to print descriptions for summaries the public API now exports a method to easily navigate a ValueObject hierarchy New InputReaderEZ and PriorityPointerPair classes Several minor fixes and improvements llvm-svn: 135238
This commit is contained in:
parent
a83b37a9db
commit
f2bbf717f7
|
@ -167,6 +167,10 @@ public:
|
|||
// classes.
|
||||
lldb::SBValue
|
||||
GetChildMemberWithName (const char *name, lldb::DynamicValueType use_dynamic);
|
||||
|
||||
// Expands nested expressions like .a->b[0].c[1]->d
|
||||
lldb::SBValue
|
||||
GetValueForExpressionPath(const char* expr_path);
|
||||
|
||||
uint32_t
|
||||
GetNumChildren ();
|
||||
|
@ -190,12 +194,12 @@ public:
|
|||
bool
|
||||
GetExpressionPath (lldb::SBStream &description, bool qualify_cxx_base_classes);
|
||||
|
||||
SBValue (const lldb::ValueObjectSP &value_sp);
|
||||
|
||||
protected:
|
||||
friend class SBValueList;
|
||||
friend class SBFrame;
|
||||
|
||||
SBValue (const lldb::ValueObjectSP &value_sp);
|
||||
|
||||
#ifndef SWIG
|
||||
|
||||
// Mimic shared pointer...
|
||||
|
|
|
@ -576,8 +576,6 @@ public:
|
|||
static uint32_t
|
||||
GetCount();
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
|
|
@ -69,6 +69,9 @@ public:
|
|||
explicit
|
||||
Error (ValueType err, lldb::ErrorType type = lldb::eErrorTypeGeneric);
|
||||
|
||||
explicit
|
||||
Error (const char* err_str);
|
||||
|
||||
Error (const Error &rhs);
|
||||
//------------------------------------------------------------------
|
||||
/// Assignment operator.
|
||||
|
|
|
@ -50,8 +50,10 @@ namespace std
|
|||
#include "lldb/Core/UserID.h"
|
||||
#include "lldb/Core/UserSettingsController.h"
|
||||
#include "lldb/Core/ValueObject.h"
|
||||
#include "lldb/Interpreter/ScriptInterpreterPython.h"
|
||||
#include "lldb/Target/ExecutionContext.h"
|
||||
#include "lldb/Target/Platform.h"
|
||||
#include "lldb/Target/StackFrame.h"
|
||||
#include "lldb/Target/TargetList.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
@ -67,7 +69,262 @@ public:
|
|||
|
||||
};
|
||||
|
||||
struct ValueFormat
|
||||
{
|
||||
bool m_cascades;
|
||||
bool m_skip_pointers;
|
||||
bool m_skip_references;
|
||||
lldb::Format m_format;
|
||||
ValueFormat (lldb::Format f = lldb::eFormatInvalid,
|
||||
bool casc = false,
|
||||
bool skipptr = false,
|
||||
bool skipref = false) :
|
||||
m_cascades(casc),
|
||||
m_skip_pointers(skipptr),
|
||||
m_skip_references(skipref),
|
||||
m_format (f)
|
||||
{
|
||||
}
|
||||
|
||||
typedef lldb::SharedPtr<ValueFormat>::Type SharedPointer;
|
||||
typedef bool(*ValueCallback)(void*, const char*, const ValueFormat::SharedPointer&);
|
||||
|
||||
~ValueFormat()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Cascades()
|
||||
{
|
||||
return m_cascades;
|
||||
}
|
||||
bool
|
||||
SkipsPointers()
|
||||
{
|
||||
return m_skip_pointers;
|
||||
}
|
||||
bool
|
||||
SkipsReferences()
|
||||
{
|
||||
return m_skip_references;
|
||||
}
|
||||
|
||||
lldb::Format
|
||||
GetFormat()
|
||||
{
|
||||
return m_format;
|
||||
}
|
||||
|
||||
std::string
|
||||
FormatObject(lldb::ValueObjectSP object)
|
||||
{
|
||||
if (!object.get())
|
||||
return "NULL";
|
||||
|
||||
StreamString sstr;
|
||||
|
||||
if (ClangASTType::DumpTypeValue (object->GetClangAST(), // The clang AST
|
||||
object->GetClangType(), // The clang type to display
|
||||
&sstr,
|
||||
m_format, // Format to display this type with
|
||||
object->GetDataExtractor(), // Data to extract from
|
||||
0, // Byte offset into "data"
|
||||
object->GetByteSize(), // Byte size of item in "data"
|
||||
object->GetBitfieldBitSize(), // Bitfield bit size
|
||||
object->GetBitfieldBitOffset())) // Bitfield bit offset
|
||||
return (sstr.GetString());
|
||||
else
|
||||
{
|
||||
return ("unsufficient data for value");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct SummaryFormat
|
||||
{
|
||||
bool m_cascades;
|
||||
bool m_skip_pointers;
|
||||
bool m_skip_references;
|
||||
bool m_dont_show_children;
|
||||
bool m_dont_show_value;
|
||||
bool m_show_members_oneliner;
|
||||
|
||||
SummaryFormat(bool casc = false,
|
||||
bool skipptr = false,
|
||||
bool skipref = false,
|
||||
bool nochildren = true,
|
||||
bool novalue = true,
|
||||
bool oneliner = false) :
|
||||
m_cascades(casc),
|
||||
m_skip_pointers(skipptr),
|
||||
m_skip_references(skipref),
|
||||
m_dont_show_children(nochildren),
|
||||
m_dont_show_value(novalue),
|
||||
m_show_members_oneliner(oneliner)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Cascades()
|
||||
{
|
||||
return m_cascades;
|
||||
}
|
||||
bool
|
||||
SkipsPointers()
|
||||
{
|
||||
return m_skip_pointers;
|
||||
}
|
||||
bool
|
||||
SkipsReferences()
|
||||
{
|
||||
return m_skip_references;
|
||||
}
|
||||
|
||||
bool
|
||||
DoesPrintChildren() const
|
||||
{
|
||||
return !m_dont_show_children;
|
||||
}
|
||||
|
||||
bool
|
||||
DoesPrintValue() const
|
||||
{
|
||||
return !m_dont_show_value;
|
||||
}
|
||||
|
||||
bool
|
||||
IsOneliner() const
|
||||
{
|
||||
return m_show_members_oneliner;
|
||||
}
|
||||
|
||||
virtual
|
||||
~SummaryFormat()
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
FormatObject(lldb::ValueObjectSP object) = 0;
|
||||
|
||||
virtual std::string
|
||||
GetDescription() = 0;
|
||||
|
||||
typedef lldb::SharedPtr<SummaryFormat>::Type SharedPointer;
|
||||
typedef bool(*SummaryCallback)(void*, const char*, const SummaryFormat::SharedPointer&);
|
||||
typedef bool(*RegexSummaryCallback)(void*, lldb::RegularExpressionSP, const SummaryFormat::SharedPointer&);
|
||||
|
||||
};
|
||||
|
||||
// simple string-based summaries, using ${var to show data
|
||||
struct StringSummaryFormat : public SummaryFormat
|
||||
{
|
||||
std::string m_format;
|
||||
|
||||
StringSummaryFormat(bool casc = false,
|
||||
bool skipptr = false,
|
||||
bool skipref = false,
|
||||
bool nochildren = true,
|
||||
bool novalue = true,
|
||||
bool oneliner = false,
|
||||
std::string f = "") :
|
||||
SummaryFormat(casc,skipptr,skipref,nochildren,novalue,oneliner),
|
||||
m_format(f)
|
||||
{
|
||||
}
|
||||
|
||||
std::string
|
||||
GetFormat()
|
||||
{
|
||||
return m_format;
|
||||
}
|
||||
|
||||
virtual
|
||||
~StringSummaryFormat()
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
FormatObject(lldb::ValueObjectSP object);
|
||||
|
||||
virtual std::string
|
||||
GetDescription()
|
||||
{
|
||||
StreamString sstr;
|
||||
sstr.Printf ("`%s`%s%s%s%s%s%s\n", m_format.c_str(),
|
||||
m_cascades ? "" : " (not cascading)",
|
||||
m_dont_show_children ? "" : " (show children)",
|
||||
m_dont_show_value ? " (hide value)" : "",
|
||||
m_show_members_oneliner ? " (one-line printout)" : "",
|
||||
m_skip_pointers ? " (skip pointers)" : "",
|
||||
m_skip_references ? " (skip references)" : "");
|
||||
return sstr.GetString();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Python-based summaries, running script code to show data
|
||||
struct ScriptSummaryFormat : public SummaryFormat
|
||||
{
|
||||
std::string m_function_name;
|
||||
std::string m_python_script;
|
||||
|
||||
ScriptSummaryFormat(bool casc = false,
|
||||
bool skipptr = false,
|
||||
bool skipref = false,
|
||||
bool nochildren = true,
|
||||
bool novalue = true,
|
||||
bool oneliner = false,
|
||||
std::string fname = "",
|
||||
std::string pscri = "") :
|
||||
SummaryFormat(casc,skipptr,skipref,nochildren,novalue,oneliner),
|
||||
m_function_name(fname),
|
||||
m_python_script(pscri)
|
||||
{
|
||||
}
|
||||
|
||||
std::string
|
||||
GetFunctionName()
|
||||
{
|
||||
return m_function_name;
|
||||
}
|
||||
|
||||
std::string
|
||||
GetPythonScript()
|
||||
{
|
||||
return m_python_script;
|
||||
}
|
||||
|
||||
virtual
|
||||
~ScriptSummaryFormat()
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
FormatObject(lldb::ValueObjectSP object)
|
||||
{
|
||||
return std::string(ScriptInterpreterPython::CallPythonScriptFunction(m_function_name.c_str(),
|
||||
object).c_str());
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
GetDescription()
|
||||
{
|
||||
StreamString sstr;
|
||||
sstr.Printf ("%s%s%s\n%s\n", m_cascades ? "" : " (not cascading)",
|
||||
m_skip_pointers ? " (skip pointers)" : "",
|
||||
m_skip_references ? " (skip references)" : "",
|
||||
m_python_script.c_str());
|
||||
return sstr.GetString();
|
||||
|
||||
}
|
||||
|
||||
typedef lldb::SharedPtr<ScriptSummaryFormat>::Type SharedPointer;
|
||||
|
||||
};
|
||||
|
||||
/*struct SummaryFormat
|
||||
{
|
||||
std::string m_format;
|
||||
bool m_dont_show_children;
|
||||
|
@ -116,32 +373,35 @@ struct SummaryFormat
|
|||
typedef bool(*RegexSummaryCallback)(void*, lldb::RegularExpressionSP, const SummaryFormat::SharedPointer&);
|
||||
|
||||
};
|
||||
|
||||
struct ValueFormat
|
||||
|
||||
struct ScriptFormat
|
||||
{
|
||||
lldb::Format m_format;
|
||||
std::string m_function_name;
|
||||
std::string m_python_script;
|
||||
bool m_cascades;
|
||||
bool m_skip_references;
|
||||
bool m_skip_pointers;
|
||||
ValueFormat (lldb::Format f = lldb::eFormatInvalid,
|
||||
bool c = false,
|
||||
bool skipptr = false,
|
||||
bool skipref = false) :
|
||||
m_format (f),
|
||||
ScriptFormat (std::string n,
|
||||
std::string s = "",
|
||||
bool c = false,
|
||||
bool skipptr = false,
|
||||
bool skipref = false) :
|
||||
m_function_name (n),
|
||||
m_python_script(s),
|
||||
m_cascades (c),
|
||||
m_skip_references(skipref),
|
||||
m_skip_pointers(skipptr)
|
||||
{
|
||||
}
|
||||
|
||||
typedef lldb::SharedPtr<ValueFormat>::Type SharedPointer;
|
||||
typedef bool(*ValueCallback)(void*, const char*, const ValueFormat::SharedPointer&);
|
||||
typedef lldb::SharedPtr<ScriptFormat>::Type SharedPointer;
|
||||
typedef bool(*ScriptCallback)(void*, const char*, const ScriptFormat::SharedPointer&);
|
||||
|
||||
~ValueFormat()
|
||||
~ScriptFormat()
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
};*/
|
||||
|
||||
template<typename KeyType, typename ValueType>
|
||||
class FormatNavigator;
|
||||
|
@ -457,11 +717,13 @@ private:
|
|||
typedef FormatNavigator<const char*, ValueFormat> ValueNavigator;
|
||||
typedef FormatNavigator<const char*, SummaryFormat> SummaryNavigator;
|
||||
typedef FormatNavigator<lldb::RegularExpressionSP, SummaryFormat> RegexSummaryNavigator;
|
||||
typedef FormatNavigator<const char*, SummaryFormat> ScriptNavigator;
|
||||
|
||||
typedef ValueNavigator::MapType ValueMap;
|
||||
typedef SummaryNavigator::MapType SummaryMap;
|
||||
typedef RegexSummaryNavigator::MapType RegexSummaryMap;
|
||||
typedef FormatMap<const char*, SummaryFormat> NamedSummariesMap;
|
||||
typedef ScriptNavigator::MapType ScriptMap;
|
||||
|
||||
ValueNavigator m_value_nav;
|
||||
SummaryNavigator m_summary_nav;
|
||||
|
@ -469,6 +731,8 @@ private:
|
|||
|
||||
NamedSummariesMap m_named_summaries_map;
|
||||
|
||||
ScriptNavigator m_script_nav;
|
||||
|
||||
uint32_t m_last_revision;
|
||||
|
||||
public:
|
||||
|
@ -478,6 +742,7 @@ public:
|
|||
m_summary_nav(this),
|
||||
m_regex_summary_nav(this),
|
||||
m_named_summaries_map(this),
|
||||
m_script_nav(this),
|
||||
m_last_revision(0)
|
||||
{
|
||||
}
|
||||
|
@ -487,6 +752,7 @@ public:
|
|||
SummaryNavigator& Summary() { return m_summary_nav; }
|
||||
RegexSummaryNavigator& RegexSummary() { return m_regex_summary_nav; }
|
||||
NamedSummariesMap& NamedSummary() { return m_named_summaries_map; }
|
||||
ScriptNavigator& Script() { return m_script_nav; }
|
||||
|
||||
static bool
|
||||
GetFormatFromCString (const char *format_cstr,
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include "lldb/lldb-public.h"
|
||||
#include "lldb/lldb-enumerations.h"
|
||||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Host/Predicate.h"
|
||||
|
||||
|
||||
|
@ -27,6 +27,31 @@ public:
|
|||
lldb::InputReaderAction notification,
|
||||
const char *bytes,
|
||||
size_t bytes_len);
|
||||
|
||||
struct HandlerData
|
||||
{
|
||||
InputReader& reader;
|
||||
const char *bytes;
|
||||
size_t bytes_len;
|
||||
void* baton;
|
||||
|
||||
HandlerData(InputReader& r,
|
||||
const char* b,
|
||||
size_t l,
|
||||
void* t) :
|
||||
reader(r),
|
||||
bytes(b),
|
||||
bytes_len(l),
|
||||
baton(t)
|
||||
{
|
||||
}
|
||||
|
||||
lldb::StreamSP
|
||||
GetOutStream();
|
||||
|
||||
bool
|
||||
GetBatchMode();
|
||||
};
|
||||
|
||||
InputReader (Debugger &debugger);
|
||||
|
||||
|
@ -41,6 +66,41 @@ public:
|
|||
const char *prompt,
|
||||
bool echo);
|
||||
|
||||
virtual Error Initialize(void* baton,
|
||||
lldb::InputReaderGranularity token_size = lldb::eInputReaderGranularityLine,
|
||||
const char* end_token = "DONE",
|
||||
const char *prompt = "> ",
|
||||
bool echo = true)
|
||||
{
|
||||
return Error("unimplemented");
|
||||
}
|
||||
|
||||
// to use these handlers instead of the Callback function, you must subclass
|
||||
// InputReaderEZ, and redefine the handlers for the events you care about
|
||||
virtual void
|
||||
ActivateHandler(HandlerData&) {}
|
||||
|
||||
virtual void
|
||||
DeactivateHandler(HandlerData&) {}
|
||||
|
||||
virtual void
|
||||
ReactivateHandler(HandlerData&) {}
|
||||
|
||||
virtual void
|
||||
AsynchronousOutputWrittenHandler(HandlerData&) {}
|
||||
|
||||
virtual void
|
||||
GotTokenHandler(HandlerData&) {}
|
||||
|
||||
virtual void
|
||||
InterruptHandler(HandlerData&) {}
|
||||
|
||||
virtual void
|
||||
EOFHandler(HandlerData&) {}
|
||||
|
||||
virtual void
|
||||
DoneHandler(HandlerData&) {}
|
||||
|
||||
bool
|
||||
IsDone () const
|
||||
{
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
//===-- InputReaderEZ.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_InputReaderEZ_h_
|
||||
#define liblldb_InputReaderEZ_h_
|
||||
|
||||
#include "lldb/lldb-public.h"
|
||||
#include "lldb/lldb-enumerations.h"
|
||||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Core/InputReader.h"
|
||||
#include "lldb/Host/Predicate.h"
|
||||
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
class InputReaderEZ : public InputReader
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
static size_t Callback_Impl(void *baton,
|
||||
InputReader &reader,
|
||||
lldb::InputReaderAction notification,
|
||||
const char *bytes,
|
||||
size_t bytes_len);
|
||||
public:
|
||||
|
||||
InputReaderEZ (Debugger &debugger) :
|
||||
InputReader(debugger)
|
||||
{}
|
||||
|
||||
virtual
|
||||
~InputReaderEZ ();
|
||||
|
||||
virtual Error Initialize(void* baton,
|
||||
lldb::InputReaderGranularity token_size = lldb::eInputReaderGranularityLine,
|
||||
const char* end_token = "DONE",
|
||||
const char *prompt = "> ",
|
||||
bool echo = true);
|
||||
|
||||
virtual void
|
||||
ActivateHandler(HandlerData&) {}
|
||||
|
||||
virtual void
|
||||
DeactivateHandler(HandlerData&) {}
|
||||
|
||||
virtual void
|
||||
ReactivateHandler(HandlerData&) {}
|
||||
|
||||
virtual void
|
||||
AsynchronousOutputWrittenHandler(HandlerData&) {}
|
||||
|
||||
virtual void
|
||||
GotTokenHandler(HandlerData&) {}
|
||||
|
||||
virtual void
|
||||
InterruptHandler(HandlerData&) {}
|
||||
|
||||
virtual void
|
||||
EOFHandler(HandlerData&) {}
|
||||
|
||||
virtual void
|
||||
DoneHandler(HandlerData&) {}
|
||||
|
||||
protected:
|
||||
friend class Debugger;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (InputReaderEZ);
|
||||
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // #ifndef liblldb_InputReaderEZ_h_
|
|
@ -68,7 +68,17 @@ public:
|
|||
|
||||
size_t
|
||||
SplitIntoLines (const char *lines, size_t len);
|
||||
|
||||
std::string
|
||||
CopyList(const char* item_preamble = NULL,
|
||||
const char* items_sep = "\n");
|
||||
|
||||
StringList&
|
||||
operator << (const char* str);
|
||||
|
||||
StringList&
|
||||
operator << (StringList strings);
|
||||
|
||||
private:
|
||||
|
||||
STLStringArray m_strings;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "lldb/Target/ExecutionContext.h"
|
||||
#include "lldb/Target/ExecutionContextScope.h"
|
||||
#include "lldb/Target/StackID.h"
|
||||
#include "lldb/Utility/PriorityPointerPair.h"
|
||||
#include "lldb/Utility/SharedCluster.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
@ -75,7 +76,8 @@ public:
|
|||
{
|
||||
eDisplayValue = 1,
|
||||
eDisplaySummary,
|
||||
eDisplayLanguageSpecific
|
||||
eDisplayLanguageSpecific,
|
||||
eDisplayLocation
|
||||
};
|
||||
|
||||
enum ExpressionPathScanEndReason
|
||||
|
@ -731,8 +733,8 @@ protected:
|
|||
lldb::Format m_format;
|
||||
uint32_t m_last_format_mgr_revision;
|
||||
lldb::SummaryFormatSP m_last_summary_format;
|
||||
lldb::ValueFormatSP m_last_value_format;
|
||||
lldb::SummaryFormatSP m_forced_summary_format;
|
||||
lldb::ValueFormatSP m_last_value_format;
|
||||
lldb::user_id_t m_user_id_of_forced_summary;
|
||||
bool m_value_is_valid:1,
|
||||
m_value_did_change:1,
|
||||
|
@ -802,6 +804,9 @@ protected:
|
|||
|
||||
void
|
||||
SetValueIsValid (bool valid);
|
||||
|
||||
void
|
||||
ClearUserVisibleData();
|
||||
|
||||
public:
|
||||
lldb::addr_t
|
||||
|
|
|
@ -26,6 +26,13 @@ public:
|
|||
const char *session_dictionary_name,
|
||||
const lldb::StackFrameSP& frame_sp,
|
||||
const lldb::BreakpointLocationSP &bp_loc_sp);
|
||||
|
||||
typedef
|
||||
|
||||
typedef std::string (*SWIGPythonTypeScriptCallbackFunction) (const char *python_function_name,
|
||||
const char *session_dictionary_name,
|
||||
const lldb::ValueObjectSP& valobj_sp);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eCharPtr,
|
||||
|
@ -77,6 +84,25 @@ public:
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
GenerateTypeScriptFunction (StringList &input, StringList &output)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// use this if the function code is just a one-liner script
|
||||
virtual bool
|
||||
GenerateTypeScriptFunction (const char* oneliner, StringList &output)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
GenerateFunction(std::string& signature, StringList &input, StringList &output)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void
|
||||
CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
|
||||
|
@ -104,7 +130,8 @@ public:
|
|||
|
||||
static void
|
||||
InitializeInterpreter (SWIGInitCallback python_swig_init_callback,
|
||||
SWIGBreakpointCallbackFunction python_swig_breakpoint_callback);
|
||||
SWIGBreakpointCallbackFunction python_swig_breakpoint_callback,
|
||||
SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback);
|
||||
|
||||
static void
|
||||
TerminateInterpreter ();
|
||||
|
|
|
@ -49,6 +49,16 @@ public:
|
|||
bool
|
||||
ExportFunctionDefinitionToInterpreter (StringList &function_def);
|
||||
|
||||
bool
|
||||
GenerateTypeScriptFunction (StringList &input, StringList &output);
|
||||
|
||||
// use this if the function code is just a one-liner script
|
||||
bool
|
||||
GenerateTypeScriptFunction (const char* oneliner, StringList &output);
|
||||
|
||||
bool
|
||||
GenerateFunction(std::string& signature, StringList &input, StringList &output);
|
||||
|
||||
bool
|
||||
GenerateBreakpointCommandCallbackData (StringList &input, StringList &output);
|
||||
|
||||
|
@ -64,6 +74,10 @@ public:
|
|||
StoppointCallbackContext *context,
|
||||
lldb::user_id_t break_id,
|
||||
lldb::user_id_t break_loc_id);
|
||||
|
||||
static std::string
|
||||
CallPythonScriptFunction (const char *python_function_name,
|
||||
lldb::ValueObjectSP valobj);
|
||||
|
||||
void
|
||||
CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
|
||||
|
@ -88,7 +102,8 @@ public:
|
|||
|
||||
static void
|
||||
InitializeInterpreter (SWIGInitCallback python_swig_init_callback,
|
||||
SWIGBreakpointCallbackFunction python_swig_breakpoint_callback);
|
||||
SWIGBreakpointCallbackFunction python_swig_breakpoint_callback,
|
||||
SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback);
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
//===-- PriorityPointerPair.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_PriorityPointerPair_h_
|
||||
#define liblldb_PriorityPointerPair_h_
|
||||
|
||||
#include "lldb/lldb-public.h"
|
||||
#include "lldb/Utility/SharingPtr.h"
|
||||
|
||||
namespace lldb_utility {
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// A prioritized pair of SharedPtr<T>. One of the two pointers is high
|
||||
// priority, the other is low priority.
|
||||
// The Get() method always returns high, if *high != NULL,
|
||||
// otherwise, low is returned (even if *low == NULL)
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
class PriorityPointerPair
|
||||
{
|
||||
public:
|
||||
|
||||
typedef T& reference_type;
|
||||
typedef T* pointer_type;
|
||||
|
||||
typedef typename lldb::SharedPtr<T>::Type T_SP;
|
||||
|
||||
PriorityPointerPair() :
|
||||
m_high(),
|
||||
m_low()
|
||||
{}
|
||||
|
||||
PriorityPointerPair(pointer_type high,
|
||||
pointer_type low) :
|
||||
m_high(high),
|
||||
m_low(low)
|
||||
{}
|
||||
|
||||
PriorityPointerPair(pointer_type low) :
|
||||
m_high(),
|
||||
m_low(low)
|
||||
{}
|
||||
|
||||
PriorityPointerPair(T_SP& high,
|
||||
T_SP& low) :
|
||||
m_high(high),
|
||||
m_low(low)
|
||||
{}
|
||||
|
||||
PriorityPointerPair(T_SP& low) :
|
||||
m_high(),
|
||||
m_low(low)
|
||||
{}
|
||||
|
||||
void
|
||||
SwapLow(pointer_type l)
|
||||
{
|
||||
m_low.swap(l);
|
||||
}
|
||||
|
||||
void
|
||||
SwapHigh(pointer_type h)
|
||||
{
|
||||
m_high.swap(h);
|
||||
}
|
||||
|
||||
void
|
||||
SwapLow(T_SP l)
|
||||
{
|
||||
m_low.swap(l);
|
||||
}
|
||||
|
||||
void
|
||||
SwapHigh(T_SP h)
|
||||
{
|
||||
m_high.swap(h);
|
||||
}
|
||||
|
||||
T_SP
|
||||
GetLow()
|
||||
{
|
||||
return m_low;
|
||||
}
|
||||
|
||||
T_SP
|
||||
GetHigh()
|
||||
{
|
||||
return m_high;
|
||||
}
|
||||
|
||||
T_SP
|
||||
Get()
|
||||
{
|
||||
if (m_high.get())
|
||||
return m_high;
|
||||
return m_low;
|
||||
}
|
||||
|
||||
void
|
||||
ResetHigh()
|
||||
{
|
||||
m_high.reset();
|
||||
}
|
||||
|
||||
void
|
||||
ResetLow()
|
||||
{
|
||||
m_low.reset();
|
||||
}
|
||||
|
||||
void
|
||||
Reset()
|
||||
{
|
||||
ResetLow();
|
||||
ResetHigh();
|
||||
}
|
||||
|
||||
reference_type
|
||||
operator*() const
|
||||
{
|
||||
return Get().operator*();
|
||||
}
|
||||
|
||||
pointer_type
|
||||
operator->() const
|
||||
{
|
||||
return Get().operator->();
|
||||
}
|
||||
|
||||
~PriorityPointerPair();
|
||||
|
||||
private:
|
||||
|
||||
T_SP m_high;
|
||||
T_SP m_low;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN (PriorityPointerPair);
|
||||
|
||||
};
|
||||
|
||||
} // namespace lldb_utility
|
||||
|
||||
#endif // #ifndef liblldb_PriorityPointerPair_h_
|
|
@ -20,8 +20,6 @@ namespace lldb_utility {
|
|||
// RefCounter ref(ptr);
|
||||
// (of course, the pointer is a shared resource, and must be accessible to
|
||||
// everyone who needs it). Synchronization is handled by RefCounter itself
|
||||
// To check if more than 1 RefCounter is attached to the same value, you can
|
||||
// either call shared(), or simply cast ref to bool
|
||||
// The counter is decreased each time a RefCounter to it goes out of scope
|
||||
//----------------------------------------------------------------------
|
||||
class RefCounter
|
||||
|
|
|
@ -56,11 +56,13 @@ namespace lldb {
|
|||
typedef SharedPtr<lldb_private::RegularExpression>::Type RegularExpressionSP;
|
||||
typedef SharedPtr<lldb_private::Section>::Type SectionSP;
|
||||
typedef SharedPtr<lldb_private::SearchFilter>::Type SearchFilterSP;
|
||||
typedef SharedPtr<lldb_private::ScriptSummaryFormat>::Type ScriptFormatSP;
|
||||
typedef SharedPtr<lldb_private::StackFrame>::Type StackFrameSP;
|
||||
typedef SharedPtr<lldb_private::StackFrameList>::Type StackFrameListSP;
|
||||
typedef SharedPtr<lldb_private::StopInfo>::Type StopInfoSP;
|
||||
typedef SharedPtr<lldb_private::StoppointLocation>::Type StoppointLocationSP;
|
||||
typedef SharedPtr<lldb_private::Stream>::Type StreamSP;
|
||||
typedef SharedPtr<lldb_private::StringSummaryFormat>::Type StringSummaryFormatSP;
|
||||
typedef SharedPtr<lldb_private::SummaryFormat>::Type SummaryFormatSP;
|
||||
typedef SharedPtr<lldb_private::SymbolFile>::Type SymbolFileSP;
|
||||
typedef SharedPtr<lldb_private::SymbolContextSpecifier>::Type SymbolContextSpecifierSP;
|
||||
|
|
|
@ -114,6 +114,7 @@ class RegisterLocationList;
|
|||
class RegisterValue;
|
||||
class RegularExpression;
|
||||
class Scalar;
|
||||
class ScriptSummaryFormat;
|
||||
class ScriptInterpreter;
|
||||
class ScriptInterpreterPython;
|
||||
class SearchFilter;
|
||||
|
@ -131,6 +132,7 @@ class Stream;
|
|||
class StreamFile;
|
||||
class StreamString;
|
||||
class StringList;
|
||||
class StringSummaryFormat;
|
||||
class SummaryFormat;
|
||||
class Symbol;
|
||||
class SymbolContext;
|
||||
|
|
|
@ -402,6 +402,7 @@
|
|||
4CCA645613B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644813B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp */; };
|
||||
4CCA645813B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644A13B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp */; };
|
||||
4CD0BD0F134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */; };
|
||||
94031A9E13CF486700DCFF3C /* InputReaderEZ.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */; };
|
||||
9415F61813B2C0EF00A52B36 /* FormatManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */; };
|
||||
94611EB213CCA4A4003A22AF /* RefCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94611EB113CCA4A4003A22AF /* RefCounter.cpp */; };
|
||||
9463D4CD13B1798800C230D4 /* CommandObjectType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */; };
|
||||
|
@ -631,8 +632,8 @@
|
|||
261B5A5311C3F2AD00AABD0A /* SharingPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SharingPtr.h; path = include/lldb/Utility/SharingPtr.h; sourceTree = "<group>"; };
|
||||
26217930133BC8640083B112 /* lldb-private-types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-types.h"; path = "include/lldb/lldb-private-types.h"; sourceTree = "<group>"; };
|
||||
26217932133BCB850083B112 /* lldb-private-enumerations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-enumerations.h"; path = "include/lldb/lldb-private-enumerations.h"; sourceTree = "<group>"; };
|
||||
263664921140A4930075843B /* Debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Debugger.cpp; path = source/Core/Debugger.cpp; sourceTree = "<group>"; };
|
||||
263664941140A4C10075843B /* Debugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Debugger.h; path = include/lldb/Core/Debugger.h; sourceTree = "<group>"; };
|
||||
263664921140A4930075843B /* Debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = Debugger.cpp; path = source/Core/Debugger.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||
263664941140A4C10075843B /* Debugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = Debugger.h; path = include/lldb/Core/Debugger.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
26368A3B126B697600E8659F /* darwin-debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "darwin-debug.cpp"; path = "tools/darwin-debug/darwin-debug.cpp"; sourceTree = "<group>"; };
|
||||
263E949D13661AE400E7D1CE /* UnwindAssembly-x86.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "UnwindAssembly-x86.cpp"; sourceTree = "<group>"; };
|
||||
263E949E13661AE400E7D1CE /* UnwindAssembly-x86.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UnwindAssembly-x86.h"; sourceTree = "<group>"; };
|
||||
|
@ -677,7 +678,7 @@
|
|||
266F5CBB12FC846200DFCE33 /* Config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Config.h; path = include/lldb/Host/Config.h; sourceTree = "<group>"; };
|
||||
2671A0CD134825F6003A87BB /* ConnectionMachPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConnectionMachPort.h; path = include/lldb/Core/ConnectionMachPort.h; sourceTree = "<group>"; };
|
||||
2671A0CF13482601003A87BB /* ConnectionMachPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConnectionMachPort.cpp; path = source/Core/ConnectionMachPort.cpp; sourceTree = "<group>"; };
|
||||
2672D8461189055500FF4019 /* CommandObjectFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectFrame.cpp; path = source/Commands/CommandObjectFrame.cpp; sourceTree = "<group>"; };
|
||||
2672D8461189055500FF4019 /* CommandObjectFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = CommandObjectFrame.cpp; path = source/Commands/CommandObjectFrame.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||
2672D8471189055500FF4019 /* CommandObjectFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectFrame.h; path = source/Commands/CommandObjectFrame.h; sourceTree = "<group>"; };
|
||||
26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationClient.cpp; sourceTree = "<group>"; };
|
||||
26744EEE1338317700EF765A /* GDBRemoteCommunicationClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationClient.h; sourceTree = "<group>"; };
|
||||
|
@ -724,7 +725,7 @@
|
|||
26A0604811A5D03C00F75969 /* Baton.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Baton.cpp; path = source/Core/Baton.cpp; sourceTree = "<group>"; };
|
||||
26A3B4AC1181454800381BC2 /* ObjectContainerBSDArchive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectContainerBSDArchive.cpp; sourceTree = "<group>"; };
|
||||
26A3B4AD1181454800381BC2 /* ObjectContainerBSDArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectContainerBSDArchive.h; sourceTree = "<group>"; };
|
||||
26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLDBWrapPython.cpp; path = source/LLDBWrapPython.cpp; sourceTree = "<group>"; };
|
||||
26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = LLDBWrapPython.cpp; path = source/LLDBWrapPython.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||
26A7A034135E6E4200FB369E /* NamedOptionValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NamedOptionValue.cpp; path = source/Interpreter/NamedOptionValue.cpp; sourceTree = "<group>"; };
|
||||
26A7A036135E6E5300FB369E /* NamedOptionValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NamedOptionValue.h; path = include/lldb/Interpreter/NamedOptionValue.h; sourceTree = "<group>"; };
|
||||
26B167A41123BF5500DC7B4F /* ThreadSafeValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSafeValue.h; path = include/lldb/Core/ThreadSafeValue.h; sourceTree = "<group>"; };
|
||||
|
@ -830,7 +831,7 @@
|
|||
26BC7D7E10F1B77400F91463 /* Timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Timer.h; path = include/lldb/Core/Timer.h; sourceTree = "<group>"; };
|
||||
26BC7D8010F1B77400F91463 /* UserID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UserID.h; path = include/lldb/Core/UserID.h; sourceTree = "<group>"; };
|
||||
26BC7D8110F1B77400F91463 /* Value.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Value.h; path = include/lldb/Core/Value.h; sourceTree = "<group>"; };
|
||||
26BC7D8210F1B77400F91463 /* ValueObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObject.h; path = include/lldb/Core/ValueObject.h; sourceTree = "<group>"; };
|
||||
26BC7D8210F1B77400F91463 /* ValueObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = ValueObject.h; path = include/lldb/Core/ValueObject.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
26BC7D8310F1B77400F91463 /* ValueObjectChild.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectChild.h; path = include/lldb/Core/ValueObjectChild.h; sourceTree = "<group>"; };
|
||||
26BC7D8410F1B77400F91463 /* ValueObjectList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectList.h; path = include/lldb/Core/ValueObjectList.h; sourceTree = "<group>"; };
|
||||
26BC7D8510F1B77400F91463 /* ValueObjectVariable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectVariable.h; path = include/lldb/Core/ValueObjectVariable.h; sourceTree = "<group>"; };
|
||||
|
@ -928,7 +929,7 @@
|
|||
26BC7E9610F1B85900F91463 /* Timer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Timer.cpp; path = source/Core/Timer.cpp; sourceTree = "<group>"; };
|
||||
26BC7E9810F1B85900F91463 /* UserID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UserID.cpp; path = source/Core/UserID.cpp; sourceTree = "<group>"; };
|
||||
26BC7E9910F1B85900F91463 /* Value.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Value.cpp; path = source/Core/Value.cpp; sourceTree = "<group>"; };
|
||||
26BC7E9A10F1B85900F91463 /* ValueObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObject.cpp; path = source/Core/ValueObject.cpp; sourceTree = "<group>"; };
|
||||
26BC7E9A10F1B85900F91463 /* ValueObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = ValueObject.cpp; path = source/Core/ValueObject.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||
26BC7E9B10F1B85900F91463 /* ValueObjectChild.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectChild.cpp; path = source/Core/ValueObjectChild.cpp; sourceTree = "<group>"; };
|
||||
26BC7E9C10F1B85900F91463 /* ValueObjectList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectList.cpp; path = source/Core/ValueObjectList.cpp; sourceTree = "<group>"; };
|
||||
26BC7E9D10F1B85900F91463 /* ValueObjectVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectVariable.cpp; path = source/Core/ValueObjectVariable.cpp; sourceTree = "<group>"; };
|
||||
|
@ -1019,8 +1020,8 @@
|
|||
26DB3E141379E7AD0080DC73 /* ABISysV_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ABISysV_x86_64.h; sourceTree = "<group>"; };
|
||||
26DC6A101337FE6900FF7998 /* lldb-platform */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "lldb-platform"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
26DC6A1C1337FECA00FF7998 /* lldb-platform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lldb-platform.cpp"; path = "tools/lldb-platform/lldb-platform.cpp"; sourceTree = "<group>"; };
|
||||
26DE1E6911616C2E00A093E2 /* lldb-forward-rtti.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-forward-rtti.h"; path = "include/lldb/lldb-forward-rtti.h"; sourceTree = "<group>"; };
|
||||
26DE1E6A11616C2E00A093E2 /* lldb-forward.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-forward.h"; path = "include/lldb/lldb-forward.h"; sourceTree = "<group>"; };
|
||||
26DE1E6911616C2E00A093E2 /* lldb-forward-rtti.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = "lldb-forward-rtti.h"; path = "include/lldb/lldb-forward-rtti.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
26DE1E6A11616C2E00A093E2 /* lldb-forward.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = "lldb-forward.h"; path = "include/lldb/lldb-forward.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
26DE204011618AB900A093E2 /* SBSymbolContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBSymbolContext.h; path = include/lldb/API/SBSymbolContext.h; sourceTree = "<group>"; };
|
||||
26DE204211618ACA00A093E2 /* SBAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBAddress.h; path = include/lldb/API/SBAddress.h; sourceTree = "<group>"; };
|
||||
26DE204411618ADA00A093E2 /* SBAddress.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBAddress.cpp; path = source/API/SBAddress.cpp; sourceTree = "<group>"; };
|
||||
|
@ -1169,11 +1170,14 @@
|
|||
69A01E1E1236C5D400C660B5 /* Mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mutex.cpp; sourceTree = "<group>"; };
|
||||
69A01E1F1236C5D400C660B5 /* Symbols.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Symbols.cpp; sourceTree = "<group>"; };
|
||||
69A01E201236C5D400C660B5 /* TimeValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimeValue.cpp; sourceTree = "<group>"; };
|
||||
9415F61613B2C0DC00A52B36 /* FormatManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormatManager.h; path = include/lldb/Core/FormatManager.h; sourceTree = "<group>"; };
|
||||
9415F61713B2C0EF00A52B36 /* FormatManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatManager.cpp; path = source/Core/FormatManager.cpp; sourceTree = "<group>"; };
|
||||
94031A9B13CF484600DCFF3C /* InputReaderEZ.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InputReaderEZ.h; path = include/lldb/Core/InputReaderEZ.h; sourceTree = "<group>"; };
|
||||
94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InputReaderEZ.cpp; path = source/Core/InputReaderEZ.cpp; sourceTree = "<group>"; };
|
||||
94031A9F13CF5B3D00DCFF3C /* PriorityPointerPair.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PriorityPointerPair.h; path = include/lldb/Utility/PriorityPointerPair.h; sourceTree = "<group>"; };
|
||||
9415F61613B2C0DC00A52B36 /* FormatManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = FormatManager.h; path = include/lldb/Core/FormatManager.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
9415F61713B2C0EF00A52B36 /* FormatManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = FormatManager.cpp; path = source/Core/FormatManager.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||
94611EAF13CCA363003A22AF /* RefCounter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RefCounter.h; path = include/lldb/Utility/RefCounter.h; sourceTree = "<group>"; };
|
||||
94611EB113CCA4A4003A22AF /* RefCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RefCounter.cpp; path = source/Utility/RefCounter.cpp; sourceTree = "<group>"; };
|
||||
9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectType.cpp; path = source/Commands/CommandObjectType.cpp; sourceTree = "<group>"; };
|
||||
9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = CommandObjectType.cpp; path = source/Commands/CommandObjectType.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||
9463D4CE13B179A500C230D4 /* CommandObjectType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandObjectType.h; path = source/Commands/CommandObjectType.h; sourceTree = "<group>"; };
|
||||
9467E65113C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeHierarchyNavigator.cpp; path = source/Symbol/TypeHierarchyNavigator.cpp; sourceTree = "<group>"; };
|
||||
9467E65413C3D98900B3B6F3 /* TypeHierarchyNavigator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeHierarchyNavigator.h; path = include/lldb/Symbol/TypeHierarchyNavigator.h; sourceTree = "<group>"; };
|
||||
|
@ -1797,6 +1801,7 @@
|
|||
2676A093119C93C8008A98EF /* StringExtractorGDBRemote.cpp */,
|
||||
2682F16B115EDA0D00CCFF99 /* PseudoTerminal.h */,
|
||||
2682F16A115EDA0D00CCFF99 /* PseudoTerminal.cpp */,
|
||||
94031A9F13CF5B3D00DCFF3C /* PriorityPointerPair.h */,
|
||||
);
|
||||
name = Utility;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1929,6 +1934,8 @@
|
|||
26F73061139D8FDB00FD51C7 /* History.cpp */,
|
||||
9AA69DBB118A029E00D753A0 /* InputReader.h */,
|
||||
9AA69DB5118A027A00D753A0 /* InputReader.cpp */,
|
||||
94031A9B13CF484600DCFF3C /* InputReaderEZ.h */,
|
||||
94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */,
|
||||
9A9E1F0013980943005AC039 /* InputReaderStack.h */,
|
||||
9A9E1EFE1398086D005AC039 /* InputReaderStack.cpp */,
|
||||
26BC7D6510F1B77400F91463 /* IOStreamMacros.h */,
|
||||
|
@ -3271,6 +3278,7 @@
|
|||
26ED3D6D13C563810017D45E /* OptionGroupVariable.cpp in Sources */,
|
||||
26F4214413C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp in Sources */,
|
||||
94611EB213CCA4A4003A22AF /* RefCounter.cpp in Sources */,
|
||||
94031A9E13CF486700DCFF3C /* InputReaderEZ.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -359,4 +359,128 @@ LLDBSwigPythonBreakpointCallbackFunction
|
|||
return stop_at_breakpoint;
|
||||
}
|
||||
|
||||
SWIGEXPORT std::string
|
||||
LLDBSwigPythonCallTypeScript
|
||||
(
|
||||
const char *python_function_name,
|
||||
const char *session_dictionary_name,
|
||||
const lldb::ValueObjectSP& valobj_sp
|
||||
)
|
||||
{
|
||||
lldb::SBValue sb_value (valobj_sp);
|
||||
|
||||
std::string retval = "";
|
||||
|
||||
PyObject *ValObj_PyObj = SWIG_NewPointerObj((void *) &valobj_sp, SWIGTYPE_p_lldb__SBValue, 0);
|
||||
|
||||
if (ValObj_PyObj == NULL)
|
||||
return retval;
|
||||
|
||||
if (!python_function_name || !session_dictionary_name)
|
||||
return retval;
|
||||
|
||||
PyObject *pmodule, *main_dict, *session_dict, *pfunc;
|
||||
PyObject *pargs, *pvalue;
|
||||
|
||||
pmodule = PyImport_AddModule ("__main__");
|
||||
if (pmodule != NULL)
|
||||
{
|
||||
main_dict = PyModule_GetDict (pmodule);
|
||||
if (main_dict != NULL)
|
||||
{
|
||||
PyObject *key, *value;
|
||||
Py_ssize_t pos = 0;
|
||||
|
||||
// Find the current session's dictionary in the main module's dictionary.
|
||||
|
||||
if (PyDict_Check (main_dict))
|
||||
|
||||
{
|
||||
session_dict = NULL;
|
||||
while (PyDict_Next (main_dict, &pos, &key, &value))
|
||||
{
|
||||
// We have stolen references to the key and value objects in the dictionary; we need to increment
|
||||
// them now so that Python's garbage collector doesn't collect them out from under us.
|
||||
Py_INCREF (key);
|
||||
Py_INCREF (value);
|
||||
if (strcmp (PyString_AsString (key), session_dictionary_name) == 0)
|
||||
{
|
||||
session_dict = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!session_dict || !PyDict_Check (session_dict))
|
||||
return retval;
|
||||
|
||||
// Find the function we need to call in the current session's dictionary.
|
||||
|
||||
pos = 0;
|
||||
pfunc = NULL;
|
||||
while (PyDict_Next (session_dict, &pos, &key, &value))
|
||||
{
|
||||
if (PyString_Check (key))
|
||||
{
|
||||
// We have stolen references to the key and value objects in the dictionary; we need to increment
|
||||
// them now so that Python's garbage collector doesn't collect them out from under us.
|
||||
Py_INCREF (key);
|
||||
Py_INCREF (value);
|
||||
if (strcmp (PyString_AsString (key), python_function_name) == 0)
|
||||
{
|
||||
pfunc = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the arguments and call the function.
|
||||
|
||||
if (pfunc && PyCallable_Check (pfunc))
|
||||
{
|
||||
pargs = PyTuple_New (2);
|
||||
if (pargs == NULL)
|
||||
{
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Clear();
|
||||
return retval;
|
||||
}
|
||||
|
||||
PyTuple_SetItem (pargs, 0, ValObj_PyObj); // This "steals" a reference to ValObj_PyObj
|
||||
PyTuple_SetItem (pargs, 1, session_dict); // This "steals" a reference to session_dict
|
||||
pvalue = PyObject_CallObject (pfunc, pargs);
|
||||
Py_DECREF (pargs);
|
||||
|
||||
if (pvalue != NULL)
|
||||
{
|
||||
if (pvalue != Py_None)
|
||||
retval = std::string(PyString_AsString(pvalue));
|
||||
else
|
||||
retval = "None";
|
||||
Py_DECREF (pvalue);
|
||||
}
|
||||
else if (PyErr_Occurred ())
|
||||
{
|
||||
PyErr_Clear();
|
||||
}
|
||||
Py_INCREF (session_dict);
|
||||
}
|
||||
else if (PyErr_Occurred())
|
||||
{
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
else if (PyErr_Occurred())
|
||||
{
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
else if (PyErr_Occurred ())
|
||||
{
|
||||
PyErr_Clear ();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
%}
|
||||
|
|
|
@ -314,6 +314,15 @@ LLDBSwigPythonBreakpointCallbackFunction
|
|||
const lldb::BreakpointLocationSP& sb_bp_loc
|
||||
);
|
||||
|
||||
extern "C" std::string
|
||||
LLDBSwigPythonCallTypeScript
|
||||
(
|
||||
const char *python_function_name,
|
||||
const char *session_dictionary_name,
|
||||
const lldb::ValueObjectSP& valobj_sp
|
||||
);
|
||||
|
||||
|
||||
extern "C" void init_lldb(void);
|
||||
|
||||
void
|
||||
|
@ -324,6 +333,7 @@ SBCommandInterpreter::InitializeSWIG ()
|
|||
{
|
||||
g_initialized = true;
|
||||
ScriptInterpreter::InitializeInterpreter (init_lldb,
|
||||
LLDBSwigPythonBreakpointCallbackFunction);
|
||||
LLDBSwigPythonBreakpointCallbackFunction,
|
||||
LLDBSwigPythonCallTypeScript);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -472,6 +472,28 @@ SBValue::GetChildMemberWithName (const char *name, lldb::DynamicValueType use_dy
|
|||
return sb_value;
|
||||
}
|
||||
|
||||
lldb::SBValue
|
||||
SBValue::GetValueForExpressionPath(const char* expr_path)
|
||||
{
|
||||
lldb::ValueObjectSP child_sp;
|
||||
if (m_opaque_sp)
|
||||
{
|
||||
if (m_opaque_sp->GetUpdatePoint().GetTarget())
|
||||
{
|
||||
Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex());
|
||||
// using default values for all the fancy options, just do it if you can
|
||||
child_sp = m_opaque_sp->GetValueForExpressionPath(expr_path);
|
||||
}
|
||||
}
|
||||
|
||||
SBValue sb_value (child_sp);
|
||||
|
||||
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
||||
if (log)
|
||||
log->Printf ("SBValue(%p)::GetValueForExpressionPath (expr_path=\"%s\") => SBValue(%p)", m_opaque_sp.get(), expr_path, sb_value.get());
|
||||
|
||||
return sb_value;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SBValue::GetNumChildren ()
|
||||
|
|
|
@ -15,8 +15,10 @@
|
|||
#include "lldb/Core/ConstString.h"
|
||||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Core/FormatManager.h"
|
||||
#include "lldb/Core/InputReaderEZ.h"
|
||||
#include "lldb/Core/RegularExpression.h"
|
||||
#include "lldb/Core/State.h"
|
||||
#include "lldb/Core/StringList.h"
|
||||
#include "lldb/Interpreter/CommandInterpreter.h"
|
||||
#include "lldb/Interpreter/CommandObject.h"
|
||||
#include "lldb/Interpreter/CommandReturnObject.h"
|
||||
|
@ -416,6 +418,162 @@ CommandObjectTypeFormatList_LoopCallback (
|
|||
// CommandObjectTypeSummaryAdd
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
class ScriptAddOptions
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
bool m_skip_pointers;
|
||||
bool m_skip_references;
|
||||
bool m_cascade;
|
||||
bool m_callback_is_synchronous;
|
||||
StringList m_target_types;
|
||||
StringList m_user_source;
|
||||
|
||||
ScriptAddOptions(bool p,
|
||||
bool r,
|
||||
bool c) :
|
||||
m_skip_pointers(p),
|
||||
m_skip_references(r),
|
||||
m_cascade(c),
|
||||
m_target_types(),
|
||||
m_user_source()
|
||||
{
|
||||
}
|
||||
|
||||
typedef lldb::SharedPtr<ScriptAddOptions>::Type SharedPointer;
|
||||
|
||||
};
|
||||
|
||||
static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.";
|
||||
|
||||
class TypeScriptAddInputReader : public InputReaderEZ
|
||||
{
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (TypeScriptAddInputReader);
|
||||
public:
|
||||
TypeScriptAddInputReader(Debugger& debugger) :
|
||||
InputReaderEZ(debugger)
|
||||
{}
|
||||
|
||||
virtual
|
||||
~TypeScriptAddInputReader()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ActivateHandler(HandlerData& data)
|
||||
{
|
||||
StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
|
||||
bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
|
||||
if (!batch_mode)
|
||||
{
|
||||
out_stream->Printf ("%s\n", g_reader_instructions);
|
||||
if (data.reader.GetPrompt())
|
||||
out_stream->Printf ("%s", data.reader.GetPrompt());
|
||||
out_stream->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ReactivateHandler(HandlerData& data)
|
||||
{
|
||||
StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
|
||||
bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
|
||||
if (data.reader.GetPrompt() && !batch_mode)
|
||||
{
|
||||
out_stream->Printf ("%s", data.reader.GetPrompt());
|
||||
out_stream->Flush();
|
||||
}
|
||||
}
|
||||
virtual void GotTokenHandler(HandlerData& data)
|
||||
{
|
||||
StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
|
||||
bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
|
||||
if (data.bytes && data.bytes_len && data.baton)
|
||||
{
|
||||
((ScriptAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len);
|
||||
}
|
||||
if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
|
||||
{
|
||||
out_stream->Printf ("%s", data.reader.GetPrompt());
|
||||
out_stream->Flush();
|
||||
}
|
||||
}
|
||||
virtual void InterruptHandler(HandlerData& data)
|
||||
{
|
||||
StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
|
||||
bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
|
||||
data.reader.SetIsDone (true);
|
||||
if (!batch_mode)
|
||||
{
|
||||
out_stream->Printf ("Warning: No command attached to breakpoint.\n");
|
||||
out_stream->Flush();
|
||||
}
|
||||
}
|
||||
virtual void EOFHandler(HandlerData& data)
|
||||
{
|
||||
data.reader.SetIsDone (true);
|
||||
}
|
||||
virtual void DoneHandler(HandlerData& data)
|
||||
{
|
||||
StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
|
||||
ScriptAddOptions *options_ptr = ((ScriptAddOptions*)data.baton);
|
||||
if (!options_ptr)
|
||||
{
|
||||
out_stream->Printf ("Internal error #1: no script attached.\n");
|
||||
out_stream->Flush();
|
||||
return;
|
||||
}
|
||||
|
||||
ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope
|
||||
|
||||
ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
|
||||
if (!interpreter)
|
||||
{
|
||||
out_stream->Printf ("Internal error #2: no script attached.\n");
|
||||
out_stream->Flush();
|
||||
return;
|
||||
}
|
||||
StringList funct_name_sl;
|
||||
if (!interpreter->GenerateTypeScriptFunction (options->m_user_source,
|
||||
funct_name_sl))
|
||||
{
|
||||
out_stream->Printf ("Internal error #3: no script attached.\n");
|
||||
out_stream->Flush();
|
||||
return;
|
||||
}
|
||||
if (funct_name_sl.GetSize() == 0)
|
||||
{
|
||||
out_stream->Printf ("Internal error #4: no script attached.\n");
|
||||
out_stream->Flush();
|
||||
return;
|
||||
}
|
||||
const char *funct_name = funct_name_sl.GetStringAtIndex(0);
|
||||
if (!funct_name || !funct_name[0])
|
||||
{
|
||||
out_stream->Printf ("Internal error #5: no script attached.\n");
|
||||
out_stream->Flush();
|
||||
return;
|
||||
}
|
||||
// now I have a valid function name, let's add this as script for every type in the list
|
||||
|
||||
SummaryFormatSP script_format;
|
||||
script_format.reset(new ScriptSummaryFormat(options->m_cascade,
|
||||
options->m_skip_pointers,
|
||||
options->m_skip_references,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
std::string(funct_name),
|
||||
options->m_user_source.CopyList(" ")));
|
||||
|
||||
for (int i = 0; i < options->m_target_types.GetSize(); i++)
|
||||
{
|
||||
const char *type_name = options->m_target_types.GetStringAtIndex(i);
|
||||
Debugger::SummaryFormats::Add(ConstString(type_name), script_format);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class CommandObjectTypeSummaryAdd : public CommandObject
|
||||
{
|
||||
|
||||
|
@ -471,6 +629,17 @@ private:
|
|||
case 'n':
|
||||
m_name = new ConstString(option_arg);
|
||||
break;
|
||||
case 's':
|
||||
m_python_script = std::string(option_arg);
|
||||
m_is_add_script = true;
|
||||
break;
|
||||
case 'F':
|
||||
m_python_function = std::string(option_arg);
|
||||
m_is_add_script = true;
|
||||
break;
|
||||
case 'P':
|
||||
m_is_add_script = true;
|
||||
break;
|
||||
default:
|
||||
error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
|
||||
break;
|
||||
|
@ -490,6 +659,9 @@ private:
|
|||
m_skip_pointers = false;
|
||||
m_regex = false;
|
||||
m_name = NULL;
|
||||
m_python_script = "";
|
||||
m_python_function = "";
|
||||
m_is_add_script = false;
|
||||
}
|
||||
|
||||
const OptionDefinition*
|
||||
|
@ -513,6 +685,9 @@ private:
|
|||
bool m_regex;
|
||||
std::string m_format_string;
|
||||
ConstString* m_name;
|
||||
std::string m_python_script;
|
||||
std::string m_python_function;
|
||||
bool m_is_add_script;
|
||||
};
|
||||
|
||||
CommandOptions m_options;
|
||||
|
@ -601,8 +776,169 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
CollectPythonScript
|
||||
(
|
||||
ScriptAddOptions *options,
|
||||
CommandReturnObject &result
|
||||
)
|
||||
{
|
||||
InputReaderSP reader_sp (new TypeScriptAddInputReader(m_interpreter.GetDebugger()));
|
||||
if (reader_sp && options)
|
||||
{
|
||||
|
||||
Error err (reader_sp->Initialize (options));
|
||||
if (err.Success())
|
||||
{
|
||||
m_interpreter.GetDebugger().PushInputReader (reader_sp);
|
||||
result.SetStatus (eReturnStatusSuccessFinishNoResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError (err.AsCString());
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError("out of memory");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
Execute (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
if (m_options.m_is_add_script)
|
||||
return Execute_ScriptSummary(command, result);
|
||||
else
|
||||
return Execute_StringSummary(command, result);
|
||||
}
|
||||
|
||||
bool
|
||||
Execute_ScriptSummary (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
const size_t argc = command.GetArgumentCount();
|
||||
|
||||
if (argc < 1)
|
||||
{
|
||||
result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_options.m_python_function.empty()) // we have a Python function ready to use
|
||||
{
|
||||
ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
|
||||
if (!interpreter)
|
||||
{
|
||||
result.AppendError ("Internal error #1N: no script attached.\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
const char *funct_name = m_options.m_python_function.c_str();
|
||||
if (!funct_name || !funct_name[0])
|
||||
{
|
||||
result.AppendError ("Internal error #2N: no script attached.\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
// now I have a valid function name, let's add this as script for every type in the list
|
||||
|
||||
SummaryFormatSP script_format;
|
||||
script_format.reset(new ScriptSummaryFormat(m_options.m_cascade,
|
||||
m_options.m_skip_pointers,
|
||||
m_options.m_skip_references,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
std::string(funct_name),
|
||||
" " + m_options.m_python_function + "(valobj,dict)"));
|
||||
|
||||
for (int i = 0; i < command.GetArgumentCount(); i++)
|
||||
{
|
||||
const char *type_name = command.GetArgumentAtIndex(i);
|
||||
Debugger::SummaryFormats::Add(ConstString(type_name), script_format);
|
||||
}
|
||||
}
|
||||
else if (m_options.m_python_script.empty()) // use an InputReader to grab Python code from the user
|
||||
{
|
||||
ScriptAddOptions *options = new ScriptAddOptions(m_options.m_skip_pointers,
|
||||
m_options.m_skip_references,
|
||||
m_options.m_cascade);
|
||||
|
||||
for(int i = 0; i < argc; i++) {
|
||||
const char* typeA = command.GetArgumentAtIndex(i);
|
||||
if (typeA && *typeA)
|
||||
options->m_target_types << typeA;
|
||||
else
|
||||
{
|
||||
result.AppendError("empty typenames not allowed");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CollectPythonScript(options,result);
|
||||
return result.Succeeded();
|
||||
}
|
||||
else // we have a quick 1-line script, just use it
|
||||
{
|
||||
ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
|
||||
if (!interpreter)
|
||||
{
|
||||
result.AppendError ("Internal error #1Q: no script attached.\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
StringList funct_sl;
|
||||
funct_sl << m_options.m_python_script.c_str();
|
||||
StringList funct_name_sl;
|
||||
if (!interpreter->GenerateTypeScriptFunction (funct_sl,
|
||||
funct_name_sl))
|
||||
{
|
||||
result.AppendError ("Internal error #2Q: no script attached.\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
if (funct_name_sl.GetSize() == 0)
|
||||
{
|
||||
result.AppendError ("Internal error #3Q: no script attached.\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
const char *funct_name = funct_name_sl.GetStringAtIndex(0);
|
||||
if (!funct_name || !funct_name[0])
|
||||
{
|
||||
result.AppendError ("Internal error #4Q: no script attached.\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
// now I have a valid function name, let's add this as script for every type in the list
|
||||
|
||||
ScriptFormatSP script_format;
|
||||
script_format.reset(new ScriptSummaryFormat(m_options.m_cascade,
|
||||
m_options.m_skip_pointers,
|
||||
m_options.m_skip_references,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
std::string(funct_name),
|
||||
" " + m_options.m_python_script));
|
||||
|
||||
for (int i = 0; i < command.GetArgumentCount(); i++)
|
||||
{
|
||||
const char *type_name = command.GetArgumentAtIndex(i);
|
||||
Debugger::SummaryFormats::Add(ConstString(type_name), script_format);
|
||||
}
|
||||
}
|
||||
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
||||
bool
|
||||
Execute_StringSummary (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
const size_t argc = command.GetArgumentCount();
|
||||
|
||||
|
@ -624,11 +960,13 @@ public:
|
|||
|
||||
Error error;
|
||||
|
||||
SummaryFormat::SharedPointer entry(new SummaryFormat(format_cstr,m_options.m_cascade,
|
||||
m_options.m_no_children,m_options.m_no_value,
|
||||
m_options.m_one_liner,
|
||||
m_options.m_skip_pointers,
|
||||
m_options.m_skip_references));
|
||||
SummaryFormat::SharedPointer entry(new StringSummaryFormat(m_options.m_cascade,
|
||||
m_options.m_skip_pointers,
|
||||
m_options.m_skip_references,
|
||||
m_options.m_no_children,
|
||||
m_options.m_no_value,
|
||||
m_options.m_one_liner,
|
||||
format_cstr));
|
||||
|
||||
if (error.Fail())
|
||||
{
|
||||
|
@ -698,6 +1036,9 @@ CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] =
|
|||
{ LLDB_OPT_SET_2 , true, "format-string", 'f', required_argument, NULL, 0, eArgTypeSummaryString, "Format string used to display text and object contents."},
|
||||
{ LLDB_OPT_SET_2, false, "expand", 'e', no_argument, NULL, 0, eArgTypeBoolean, "Expand aggregate data types to show children on separate lines."},
|
||||
{ LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeName, "A name for this summary string."},
|
||||
{ LLDB_OPT_SET_3, false, "python-script", 's', required_argument, NULL, 0, eArgTypeName, "Give a one-liner Python script as part of the command."},
|
||||
{ LLDB_OPT_SET_3, false, "python-function", 'F', required_argument, NULL, 0, eArgTypeName, "Give the name of a Python function to use for this type."},
|
||||
{ LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeName, "Input Python code to use for this type manually."},
|
||||
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
|
||||
};
|
||||
|
||||
|
@ -808,8 +1149,8 @@ public:
|
|||
// CommandObjectTypeSummaryList
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const SummaryFormat::SharedPointer& entry);
|
||||
bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SummaryFormat::SharedPointer& entry);
|
||||
bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const StringSummaryFormat::SharedPointer& entry);
|
||||
bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const StringSummaryFormat::SharedPointer& entry);
|
||||
|
||||
class CommandObjectTypeSummaryList;
|
||||
|
||||
|
@ -912,16 +1253,7 @@ private:
|
|||
CommandReturnObject *result)
|
||||
{
|
||||
if (regex == NULL || regex->Execute(type))
|
||||
{
|
||||
result->GetOutputStream().Printf ("%s: `%s`%s%s%s%s%s%s\n", type,
|
||||
entry->m_format.c_str(),
|
||||
entry->m_cascades ? "" : " (not cascading)",
|
||||
entry->m_dont_show_children ? "" : " (show children)",
|
||||
entry->m_dont_show_value ? " (hide value)" : "",
|
||||
entry->m_show_members_oneliner ? " (one-line printout)" : "",
|
||||
entry->m_skip_pointers ? " (skip pointers)" : "",
|
||||
entry->m_skip_references ? " (skip references)" : "");
|
||||
}
|
||||
result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -951,8 +1283,6 @@ CommandObjectTypeRXSummaryList_LoopCallback (
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class CommandObjectTypeFormat : public CommandObjectMultiword
|
||||
{
|
||||
public:
|
||||
|
@ -983,10 +1313,10 @@ public:
|
|||
"A set of commands for editing variable summary display options",
|
||||
"type summary [<sub-command-options>] ")
|
||||
{
|
||||
LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter)));
|
||||
LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter)));
|
||||
LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter)));
|
||||
LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter)));
|
||||
LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter)));
|
||||
LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter)));
|
||||
LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter)));
|
||||
LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter)));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -733,6 +733,8 @@ ScanFormatDescriptor(const char* var_name_begin,
|
|||
// if this is a V, print the value using the default format
|
||||
if (*format_name == 'V')
|
||||
*val_obj_display = ValueObject::eDisplayValue;
|
||||
if (*format_name == 'L')
|
||||
*val_obj_display = ValueObject::eDisplayLocation;
|
||||
}
|
||||
// a good custom format tells us to print the value using it
|
||||
else
|
||||
|
|
|
@ -51,6 +51,14 @@ Error::Error (const Error &rhs) :
|
|||
{
|
||||
}
|
||||
|
||||
Error::Error (const char* err_str):
|
||||
m_code (0),
|
||||
m_type (eErrorTypeInvalid),
|
||||
m_string ()
|
||||
{
|
||||
SetErrorString(err_str);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Assignment operator
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
|
||||
#include "lldb/Core/Debugger.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
|
@ -217,3 +219,54 @@ FormatManager::GetSingleItemFormat(lldb::Format vector_format)
|
|||
return lldb::eFormatInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
StringSummaryFormat::FormatObject(lldb::ValueObjectSP object)
|
||||
{
|
||||
if (!object.get())
|
||||
return "NULL";
|
||||
|
||||
StreamString s;
|
||||
ExecutionContext exe_ctx;
|
||||
object->GetExecutionContextScope()->CalculateExecutionContext(exe_ctx);
|
||||
SymbolContext sc;
|
||||
if (exe_ctx.frame)
|
||||
sc = exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextEverything);
|
||||
|
||||
if (m_show_members_oneliner)
|
||||
{
|
||||
const uint32_t num_children = object->GetNumChildren();
|
||||
if (num_children)
|
||||
{
|
||||
s.PutChar('(');
|
||||
|
||||
for (uint32_t idx=0; idx<num_children; ++idx)
|
||||
{
|
||||
lldb::ValueObjectSP child_sp(object->GetChildAtIndex(idx, true));
|
||||
if (child_sp.get())
|
||||
{
|
||||
if (idx)
|
||||
s.PutCString(", ");
|
||||
s.PutCString(child_sp.get()->GetName().AsCString());
|
||||
s.PutChar('=');
|
||||
s.PutCString(child_sp.get()->GetPrintableRepresentation());
|
||||
}
|
||||
}
|
||||
|
||||
s.PutChar(')');
|
||||
|
||||
return s.GetString();
|
||||
}
|
||||
else
|
||||
return "";
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Debugger::FormatPrompt(m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, object.get()))
|
||||
return s.GetString();
|
||||
else
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -370,3 +370,14 @@ InputReader::GranularityAsCString (lldb::InputReaderGranularity granularity)
|
|||
return unknown_state_string;
|
||||
}
|
||||
|
||||
bool
|
||||
InputReader::HandlerData::GetBatchMode()
|
||||
{
|
||||
return reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
|
||||
}
|
||||
|
||||
lldb::StreamSP
|
||||
InputReader::HandlerData::GetOutStream()
|
||||
{
|
||||
return reader.GetDebugger().GetAsyncOutputStream();
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
//===-- InputReaderEZ.cpp ---------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "lldb/Core/InputReaderEZ.h"
|
||||
|
||||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Interpreter/CommandInterpreter.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
size_t
|
||||
InputReaderEZ::Callback_Impl(void *baton,
|
||||
InputReader &reader,
|
||||
lldb::InputReaderAction notification,
|
||||
const char *bytes,
|
||||
size_t bytes_len)
|
||||
|
||||
{
|
||||
HandlerData hand_data(reader,
|
||||
bytes,
|
||||
bytes_len,
|
||||
baton);
|
||||
|
||||
switch (notification)
|
||||
{
|
||||
case eInputReaderActivate:
|
||||
reader.ActivateHandler(hand_data);
|
||||
break;
|
||||
case eInputReaderDeactivate:
|
||||
reader.DeactivateHandler(hand_data);
|
||||
break;
|
||||
case eInputReaderReactivate:
|
||||
reader.ReactivateHandler(hand_data);
|
||||
break;
|
||||
case eInputReaderAsynchronousOutputWritten:
|
||||
reader.AsynchronousOutputWrittenHandler(hand_data);
|
||||
break;
|
||||
case eInputReaderGotToken:
|
||||
reader.GotTokenHandler(hand_data);
|
||||
break;
|
||||
case eInputReaderInterrupt:
|
||||
reader.InterruptHandler(hand_data);
|
||||
break;
|
||||
case eInputReaderEndOfFile:
|
||||
reader.EOFHandler(hand_data);
|
||||
break;
|
||||
case eInputReaderDone:
|
||||
reader.DoneHandler(hand_data);
|
||||
break;
|
||||
}
|
||||
return bytes_len;
|
||||
}
|
||||
|
||||
Error
|
||||
InputReaderEZ::Initialize(void* baton,
|
||||
lldb::InputReaderGranularity token_size,
|
||||
const char* end_token,
|
||||
const char *prompt,
|
||||
bool echo)
|
||||
{
|
||||
return InputReader::Initialize(Callback_Impl,
|
||||
baton,
|
||||
token_size,
|
||||
end_token,
|
||||
prompt,
|
||||
echo);
|
||||
}
|
||||
|
||||
InputReaderEZ::~InputReaderEZ ()
|
||||
{
|
||||
}
|
|
@ -8,6 +8,8 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/Core/StringList.h"
|
||||
|
||||
#include "lldb/Core/StreamString.h"
|
||||
#include "lldb/Host/FileSpec.h"
|
||||
|
||||
#include <string>
|
||||
|
@ -205,3 +207,33 @@ StringList::RemoveBlankLines ()
|
|||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
StringList::CopyList(const char* item_preamble,
|
||||
const char* items_sep)
|
||||
{
|
||||
StreamString strm;
|
||||
for (int i = 0; i < GetSize(); i++)
|
||||
{
|
||||
if (i && items_sep && items_sep[0])
|
||||
strm << items_sep;
|
||||
if (item_preamble)
|
||||
strm << item_preamble;
|
||||
strm << GetStringAtIndex(i);
|
||||
}
|
||||
return std::string(strm.GetData());
|
||||
}
|
||||
|
||||
StringList&
|
||||
StringList::operator << (const char* str)
|
||||
{
|
||||
AppendString(str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringList&
|
||||
StringList::operator << (StringList strings)
|
||||
{
|
||||
AppendList(strings);
|
||||
return *this;
|
||||
}
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "lldb/Host/Endian.h"
|
||||
|
||||
#include "lldb/Interpreter/ScriptInterpreterPython.h"
|
||||
|
||||
#include "lldb/Symbol/ClangASTType.h"
|
||||
#include "lldb/Symbol/ClangASTContext.h"
|
||||
#include "lldb/Symbol/Type.h"
|
||||
|
@ -79,8 +81,8 @@ ValueObject::ValueObject (ValueObject &parent) :
|
|||
m_is_array_item_for_pointer(false),
|
||||
m_is_bitfield_for_scalar(false),
|
||||
m_last_format_mgr_revision(0),
|
||||
m_last_summary_format(),
|
||||
m_last_value_format(),
|
||||
m_last_summary_format(),
|
||||
m_forced_summary_format(),
|
||||
m_dump_printable_counter(0)
|
||||
{
|
||||
|
@ -118,8 +120,8 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope) :
|
|||
m_is_array_item_for_pointer(false),
|
||||
m_is_bitfield_for_scalar(false),
|
||||
m_last_format_mgr_revision(0),
|
||||
m_last_summary_format(),
|
||||
m_last_value_format(),
|
||||
m_last_summary_format(),
|
||||
m_forced_summary_format(),
|
||||
m_dump_printable_counter(0)
|
||||
{
|
||||
|
@ -164,10 +166,9 @@ ValueObject::UpdateValueIfNeeded (bool update_format)
|
|||
m_old_value_str.swap (m_value_str);
|
||||
m_value_str.clear();
|
||||
}
|
||||
m_location_str.clear();
|
||||
m_summary_str.clear();
|
||||
m_object_desc_str.clear();
|
||||
|
||||
ClearUserVisibleData();
|
||||
|
||||
const bool value_was_valid = GetValueIsValid();
|
||||
SetValueDidChange (false);
|
||||
|
||||
|
@ -204,15 +205,15 @@ ValueObject::UpdateFormatsIfNeeded()
|
|||
if (m_last_format_mgr_revision != Debugger::ValueFormats::GetCurrentRevision())
|
||||
{
|
||||
if (m_last_summary_format.get())
|
||||
m_last_summary_format.reset((SummaryFormat*)NULL);
|
||||
m_last_summary_format.reset((StringSummaryFormat*)NULL);
|
||||
if (m_last_value_format.get())
|
||||
m_last_value_format.reset((ValueFormat*)NULL);
|
||||
Debugger::ValueFormats::Get(*this, m_last_value_format);
|
||||
if (!Debugger::SummaryFormats::Get(*this, m_last_summary_format))
|
||||
Debugger::RegexSummaryFormats::Get(*this, m_last_summary_format);
|
||||
m_last_format_mgr_revision = Debugger::ValueFormats::GetCurrentRevision();
|
||||
m_value_str.clear();
|
||||
m_summary_str.clear();
|
||||
|
||||
ClearUserVisibleData();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -507,221 +508,177 @@ ValueObject::GetSummaryAsCString ()
|
|||
{
|
||||
if (m_summary_str.empty())
|
||||
{
|
||||
SummaryFormat* summary_format = GetSummaryFormat().get();
|
||||
SummaryFormat *summary_format = GetSummaryFormat().get();
|
||||
|
||||
if (summary_format)
|
||||
{
|
||||
StreamString s;
|
||||
ExecutionContext exe_ctx;
|
||||
this->GetExecutionContextScope()->CalculateExecutionContext(exe_ctx);
|
||||
SymbolContext sc;
|
||||
if (exe_ctx.frame)
|
||||
sc = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything);
|
||||
|
||||
if (summary_format->m_show_members_oneliner)
|
||||
{
|
||||
const uint32_t num_children = GetNumChildren();
|
||||
if (num_children)
|
||||
{
|
||||
|
||||
s.PutChar('(');
|
||||
|
||||
for (uint32_t idx=0; idx<num_children; ++idx)
|
||||
{
|
||||
ValueObjectSP child_sp(GetChildAtIndex(idx, true));
|
||||
if (child_sp.get())
|
||||
{
|
||||
if (idx)
|
||||
s.PutCString(", ");
|
||||
s.PutCString(child_sp.get()->GetName().AsCString());
|
||||
s.PutChar('=');
|
||||
s.PutCString(child_sp.get()->GetPrintableRepresentation());
|
||||
}
|
||||
}
|
||||
|
||||
s.PutChar(')');
|
||||
|
||||
m_summary_str.swap(s.GetString());
|
||||
return m_summary_str.c_str();
|
||||
}
|
||||
else
|
||||
return "()";
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Debugger::FormatPrompt(summary_format->m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, this))
|
||||
{
|
||||
m_summary_str.swap(s.GetString());
|
||||
return m_summary_str.c_str();
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
m_summary_str = summary_format->FormatObject(GetSP());
|
||||
}
|
||||
|
||||
clang_type_t clang_type = GetClangType();
|
||||
|
||||
// See if this is a pointer to a C string?
|
||||
if (clang_type)
|
||||
else
|
||||
{
|
||||
StreamString sstr;
|
||||
clang_type_t elem_or_pointee_clang_type;
|
||||
const Flags type_flags (ClangASTContext::GetTypeInfo (clang_type,
|
||||
GetClangAST(),
|
||||
&elem_or_pointee_clang_type));
|
||||
clang_type_t clang_type = GetClangType();
|
||||
|
||||
ExecutionContextScope *exe_scope = GetExecutionContextScope();
|
||||
if (exe_scope)
|
||||
// See if this is a pointer to a C string?
|
||||
if (clang_type)
|
||||
{
|
||||
if (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) &&
|
||||
ClangASTContext::IsCharType (elem_or_pointee_clang_type))
|
||||
{
|
||||
Target *target = exe_scope->CalculateTarget();
|
||||
if (target != NULL)
|
||||
{
|
||||
lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS;
|
||||
AddressType cstr_address_type = eAddressTypeInvalid;
|
||||
StreamString sstr;
|
||||
clang_type_t elem_or_pointee_clang_type;
|
||||
const Flags type_flags (ClangASTContext::GetTypeInfo (clang_type,
|
||||
GetClangAST(),
|
||||
&elem_or_pointee_clang_type));
|
||||
|
||||
size_t cstr_len = 0;
|
||||
bool capped_data = false;
|
||||
if (type_flags.Test (ClangASTContext::eTypeIsArray))
|
||||
ExecutionContextScope *exe_scope = GetExecutionContextScope();
|
||||
if (exe_scope)
|
||||
{
|
||||
if (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) &&
|
||||
ClangASTContext::IsCharType (elem_or_pointee_clang_type))
|
||||
{
|
||||
Target *target = exe_scope->CalculateTarget();
|
||||
if (target != NULL)
|
||||
{
|
||||
// We have an array
|
||||
cstr_len = ClangASTContext::GetArraySize (clang_type);
|
||||
if (cstr_len > 512) // TODO: make cap a setting
|
||||
lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS;
|
||||
AddressType cstr_address_type = eAddressTypeInvalid;
|
||||
|
||||
size_t cstr_len = 0;
|
||||
bool capped_data = false;
|
||||
if (type_flags.Test (ClangASTContext::eTypeIsArray))
|
||||
{
|
||||
// We have an array
|
||||
cstr_len = ClangASTContext::GetArraySize (clang_type);
|
||||
if (cstr_len > 512) // TODO: make cap a setting
|
||||
{
|
||||
capped_data = true;
|
||||
cstr_len = 512;
|
||||
}
|
||||
}
|
||||
cstr_address = GetAddressOf (cstr_address_type, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have a pointer
|
||||
cstr_address = GetPointerValue (cstr_address_type, true);
|
||||
}
|
||||
if (cstr_address != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
Address cstr_so_addr (NULL, cstr_address);
|
||||
DataExtractor data;
|
||||
size_t bytes_read = 0;
|
||||
std::vector<char> data_buffer;
|
||||
Error error;
|
||||
bool prefer_file_cache = false;
|
||||
if (cstr_len > 0)
|
||||
{
|
||||
data_buffer.resize(cstr_len);
|
||||
data.SetData (&data_buffer.front(), data_buffer.size(), lldb::endian::InlHostByteOrder());
|
||||
bytes_read = target->ReadMemory (cstr_so_addr,
|
||||
prefer_file_cache,
|
||||
&data_buffer.front(),
|
||||
cstr_len,
|
||||
error);
|
||||
if (bytes_read > 0)
|
||||
{
|
||||
sstr << '"';
|
||||
data.Dump (&sstr,
|
||||
0, // Start offset in "data"
|
||||
eFormatCharArray, // Print as characters
|
||||
1, // Size of item (1 byte for a char!)
|
||||
bytes_read, // How many bytes to print?
|
||||
UINT32_MAX, // num per line
|
||||
LLDB_INVALID_ADDRESS,// base address
|
||||
0, // bitfield bit size
|
||||
0); // bitfield bit offset
|
||||
if (capped_data)
|
||||
sstr << "...";
|
||||
sstr << '"';
|
||||
cstr_len = ClangASTContext::GetArraySize (clang_type);
|
||||
if (cstr_len > 512) // TODO: make cap a setting
|
||||
{
|
||||
capped_data = true;
|
||||
cstr_len = 512;
|
||||
}
|
||||
}
|
||||
cstr_address = GetAddressOf (cstr_address_type, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t k_max_buf_size = 256;
|
||||
data_buffer.resize (k_max_buf_size + 1);
|
||||
// NULL terminate in case we don't get the entire C string
|
||||
data_buffer.back() = '\0';
|
||||
|
||||
sstr << '"';
|
||||
|
||||
data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder());
|
||||
while ((bytes_read = target->ReadMemory (cstr_so_addr,
|
||||
prefer_file_cache,
|
||||
&data_buffer.front(),
|
||||
k_max_buf_size,
|
||||
error)) > 0)
|
||||
{
|
||||
size_t len = strlen(&data_buffer.front());
|
||||
if (len == 0)
|
||||
break;
|
||||
if (len > bytes_read)
|
||||
len = bytes_read;
|
||||
|
||||
data.Dump (&sstr,
|
||||
0, // Start offset in "data"
|
||||
eFormatCharArray, // Print as characters
|
||||
1, // Size of item (1 byte for a char!)
|
||||
len, // How many bytes to print?
|
||||
UINT32_MAX, // num per line
|
||||
LLDB_INVALID_ADDRESS,// base address
|
||||
0, // bitfield bit size
|
||||
0); // bitfield bit offset
|
||||
|
||||
if (len < k_max_buf_size)
|
||||
break;
|
||||
cstr_so_addr.Slide (k_max_buf_size);
|
||||
}
|
||||
sstr << '"';
|
||||
// We have a pointer
|
||||
cstr_address = GetPointerValue (cstr_address_type, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sstr.GetSize() > 0)
|
||||
m_summary_str.assign (sstr.GetData(), sstr.GetSize());
|
||||
}
|
||||
else if (ClangASTContext::IsFunctionPointerType (clang_type))
|
||||
{
|
||||
AddressType func_ptr_address_type = eAddressTypeInvalid;
|
||||
lldb::addr_t func_ptr_address = GetPointerValue (func_ptr_address_type, true);
|
||||
|
||||
if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
switch (func_ptr_address_type)
|
||||
{
|
||||
case eAddressTypeInvalid:
|
||||
case eAddressTypeFile:
|
||||
break;
|
||||
|
||||
case eAddressTypeLoad:
|
||||
if (cstr_address != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
Address so_addr;
|
||||
Target *target = exe_scope->CalculateTarget();
|
||||
if (target && target->GetSectionLoadList().IsEmpty() == false)
|
||||
Address cstr_so_addr (NULL, cstr_address);
|
||||
DataExtractor data;
|
||||
size_t bytes_read = 0;
|
||||
std::vector<char> data_buffer;
|
||||
Error error;
|
||||
bool prefer_file_cache = false;
|
||||
if (cstr_len > 0)
|
||||
{
|
||||
if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr))
|
||||
data_buffer.resize(cstr_len);
|
||||
data.SetData (&data_buffer.front(), data_buffer.size(), lldb::endian::InlHostByteOrder());
|
||||
bytes_read = target->ReadMemory (cstr_so_addr,
|
||||
prefer_file_cache,
|
||||
&data_buffer.front(),
|
||||
cstr_len,
|
||||
error);
|
||||
if (bytes_read > 0)
|
||||
{
|
||||
so_addr.Dump (&sstr,
|
||||
exe_scope,
|
||||
Address::DumpStyleResolvedDescription,
|
||||
Address::DumpStyleSectionNameOffset);
|
||||
sstr << '"';
|
||||
data.Dump (&sstr,
|
||||
0, // Start offset in "data"
|
||||
eFormatCharArray, // Print as characters
|
||||
1, // Size of item (1 byte for a char!)
|
||||
bytes_read, // How many bytes to print?
|
||||
UINT32_MAX, // num per line
|
||||
LLDB_INVALID_ADDRESS,// base address
|
||||
0, // bitfield bit size
|
||||
0); // bitfield bit offset
|
||||
if (capped_data)
|
||||
sstr << "...";
|
||||
sstr << '"';
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
else
|
||||
{
|
||||
const size_t k_max_buf_size = 256;
|
||||
data_buffer.resize (k_max_buf_size + 1);
|
||||
// NULL terminate in case we don't get the entire C string
|
||||
data_buffer.back() = '\0';
|
||||
|
||||
case eAddressTypeHost:
|
||||
break;
|
||||
sstr << '"';
|
||||
|
||||
data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder());
|
||||
while ((bytes_read = target->ReadMemory (cstr_so_addr,
|
||||
prefer_file_cache,
|
||||
&data_buffer.front(),
|
||||
k_max_buf_size,
|
||||
error)) > 0)
|
||||
{
|
||||
size_t len = strlen(&data_buffer.front());
|
||||
if (len == 0)
|
||||
break;
|
||||
if (len > bytes_read)
|
||||
len = bytes_read;
|
||||
|
||||
data.Dump (&sstr,
|
||||
0, // Start offset in "data"
|
||||
eFormatCharArray, // Print as characters
|
||||
1, // Size of item (1 byte for a char!)
|
||||
len, // How many bytes to print?
|
||||
UINT32_MAX, // num per line
|
||||
LLDB_INVALID_ADDRESS,// base address
|
||||
0, // bitfield bit size
|
||||
0); // bitfield bit offset
|
||||
|
||||
if (len < k_max_buf_size)
|
||||
break;
|
||||
cstr_so_addr.Slide (k_max_buf_size);
|
||||
}
|
||||
sstr << '"';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sstr.GetSize() > 0)
|
||||
m_summary_str.assign (sstr.GetData(), sstr.GetSize());
|
||||
}
|
||||
if (sstr.GetSize() > 0)
|
||||
else if (ClangASTContext::IsFunctionPointerType (clang_type))
|
||||
{
|
||||
m_summary_str.assign (1, '(');
|
||||
m_summary_str.append (sstr.GetData(), sstr.GetSize());
|
||||
m_summary_str.append (1, ')');
|
||||
AddressType func_ptr_address_type = eAddressTypeInvalid;
|
||||
lldb::addr_t func_ptr_address = GetPointerValue (func_ptr_address_type, true);
|
||||
|
||||
if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
switch (func_ptr_address_type)
|
||||
{
|
||||
case eAddressTypeInvalid:
|
||||
case eAddressTypeFile:
|
||||
break;
|
||||
|
||||
case eAddressTypeLoad:
|
||||
{
|
||||
Address so_addr;
|
||||
Target *target = exe_scope->CalculateTarget();
|
||||
if (target && target->GetSectionLoadList().IsEmpty() == false)
|
||||
{
|
||||
if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr))
|
||||
{
|
||||
so_addr.Dump (&sstr,
|
||||
exe_scope,
|
||||
Address::DumpStyleResolvedDescription,
|
||||
Address::DumpStyleSectionNameOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case eAddressTypeHost:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sstr.GetSize() > 0)
|
||||
{
|
||||
m_summary_str.assign (1, '(');
|
||||
m_summary_str.append (sstr.GetData(), sstr.GetSize());
|
||||
m_summary_str.append (1, ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -960,34 +917,35 @@ ValueObject::GetValueAsCString ()
|
|||
clang_type_t clang_type = GetClangType ();
|
||||
if (clang_type)
|
||||
{
|
||||
StreamString sstr;
|
||||
Format format = GetFormat();
|
||||
if (format == eFormatDefault)
|
||||
if (m_last_value_format)
|
||||
{
|
||||
if (m_last_value_format)
|
||||
format = m_last_value_format->m_format;
|
||||
else
|
||||
// force the system into using unsigned integers for bitfields
|
||||
format = (m_is_bitfield_for_scalar ? eFormatUnsigned :
|
||||
ClangASTType::GetFormat(clang_type));
|
||||
m_value_str = m_last_value_format->FormatObject(GetSP());
|
||||
}
|
||||
|
||||
if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST
|
||||
clang_type, // The clang type to display
|
||||
&sstr,
|
||||
format, // Format to display this type with
|
||||
m_data, // Data to extract from
|
||||
0, // Byte offset into "m_data"
|
||||
GetByteSize(), // Byte size of item in "m_data"
|
||||
GetBitfieldBitSize(), // Bitfield bit size
|
||||
GetBitfieldBitOffset())) // Bitfield bit offset
|
||||
m_value_str.swap(sstr.GetString());
|
||||
else
|
||||
{
|
||||
m_error.SetErrorStringWithFormat ("unsufficient data for value (only %u of %u bytes available)",
|
||||
m_data.GetByteSize(),
|
||||
GetByteSize());
|
||||
m_value_str.clear();
|
||||
StreamString sstr;
|
||||
Format format = GetFormat();
|
||||
if (format == eFormatDefault)
|
||||
format = (m_is_bitfield_for_scalar ? eFormatUnsigned :
|
||||
ClangASTType::GetFormat(clang_type));
|
||||
|
||||
if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST
|
||||
clang_type, // The clang type to display
|
||||
&sstr,
|
||||
format, // Format to display this type with
|
||||
m_data, // Data to extract from
|
||||
0, // Byte offset into "m_data"
|
||||
GetByteSize(), // Byte size of item in "m_data"
|
||||
GetBitfieldBitSize(), // Bitfield bit size
|
||||
GetBitfieldBitOffset())) // Bitfield bit offset
|
||||
m_value_str.swap(sstr.GetString());
|
||||
else
|
||||
{
|
||||
m_error.SetErrorStringWithFormat ("unsufficient data for value (only %u of %u bytes available)",
|
||||
m_data.GetByteSize(),
|
||||
GetByteSize());
|
||||
m_value_str.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1046,6 +1004,9 @@ ValueObject::GetPrintableRepresentation(ValueObjectRepresentationStyle val_obj_d
|
|||
case eDisplayLanguageSpecific:
|
||||
return_value = GetObjectDescription();
|
||||
break;
|
||||
case eDisplayLocation:
|
||||
return_value = GetLocationAsCString();
|
||||
break;
|
||||
}
|
||||
|
||||
// this code snippet might lead to endless recursion, thus we use a RefCounter here to
|
||||
|
@ -3221,3 +3182,12 @@ ValueObject::EvaluationPoint::SetContext (ExecutionContextScope *exe_scope)
|
|||
|
||||
return needs_update;
|
||||
}
|
||||
|
||||
void
|
||||
ValueObject::ClearUserVisibleData()
|
||||
{
|
||||
m_location_str.clear();
|
||||
m_value_str.clear();
|
||||
m_summary_str.clear();
|
||||
m_object_desc_str.clear();
|
||||
}
|
|
@ -92,10 +92,12 @@ ScriptInterpreter::LanguageToString (lldb::ScriptLanguage language)
|
|||
|
||||
void
|
||||
ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_callback,
|
||||
SWIGBreakpointCallbackFunction python_swig_breakpoint_callback)
|
||||
SWIGBreakpointCallbackFunction python_swig_breakpoint_callback,
|
||||
SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback)
|
||||
{
|
||||
ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback,
|
||||
python_swig_breakpoint_callback);
|
||||
python_swig_breakpoint_callback,
|
||||
python_swig_typescript_callback);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -34,6 +34,7 @@ using namespace lldb_private;
|
|||
|
||||
static ScriptInterpreter::SWIGInitCallback g_swig_init_callback = NULL;
|
||||
static ScriptInterpreter::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = NULL;
|
||||
static ScriptInterpreter::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = NULL;
|
||||
|
||||
|
||||
static int
|
||||
|
@ -1140,6 +1141,117 @@ ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &func
|
|||
return ExecuteMultipleLines (function_def_string.c_str());
|
||||
}
|
||||
|
||||
// TODO move both GenerateTypeScriptFunction and GenerateBreakpointCommandCallbackData to actually
|
||||
// use this code to generate their functions
|
||||
bool
|
||||
ScriptInterpreterPython::GenerateFunction(std::string& signature, StringList &input, StringList &output)
|
||||
{
|
||||
int num_lines = input.GetSize ();
|
||||
if (num_lines == 0)
|
||||
return false;
|
||||
StreamString sstr;
|
||||
StringList auto_generated_function;
|
||||
auto_generated_function.AppendString (signature.c_str());
|
||||
auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary
|
||||
auto_generated_function.AppendString (" new_keys = dict.keys()"); // Make a list of keys in the session dict
|
||||
auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict
|
||||
auto_generated_function.AppendString (" global_dict.update (dict)"); // Add the session dictionary to the
|
||||
// global dictionary.
|
||||
|
||||
// Wrap everything up inside the function, increasing the indentation.
|
||||
|
||||
for (int i = 0; i < num_lines; ++i)
|
||||
{
|
||||
sstr.Clear ();
|
||||
sstr.Printf (" %s", input.GetStringAtIndex (i));
|
||||
auto_generated_function.AppendString (sstr.GetData());
|
||||
}
|
||||
auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict
|
||||
auto_generated_function.AppendString (" dict[key] = global_dict[key]"); // Update session dict values
|
||||
auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict
|
||||
auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict
|
||||
|
||||
// Verify that the results are valid Python.
|
||||
|
||||
if (!ExportFunctionDefinitionToInterpreter (auto_generated_function))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// this implementation is identical to GenerateBreakpointCommandCallbackData (apart from the name
|
||||
// given to generated functions, of course)
|
||||
bool
|
||||
ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, StringList &output)
|
||||
{
|
||||
static int num_created_functions = 0;
|
||||
user_input.RemoveBlankLines ();
|
||||
int num_lines = user_input.GetSize ();
|
||||
StreamString sstr;
|
||||
|
||||
// Check to see if we have any data; if not, just return.
|
||||
if (user_input.GetSize() == 0)
|
||||
return false;
|
||||
|
||||
// Take what the user wrote, wrap it all up inside one big auto-generated Python function, passing in the
|
||||
// ValueObject as parameter to the function.
|
||||
|
||||
sstr.Printf ("lldb_autogen_python_type_print_func_%d", num_created_functions);
|
||||
++num_created_functions;
|
||||
std::string auto_generated_function_name = sstr.GetData();
|
||||
|
||||
sstr.Clear();
|
||||
StringList auto_generated_function;
|
||||
|
||||
// Create the function name & definition string.
|
||||
|
||||
sstr.Printf ("def %s (valobj, dict):", auto_generated_function_name.c_str());
|
||||
auto_generated_function.AppendString (sstr.GetData());
|
||||
|
||||
// Pre-pend code for setting up the session dictionary.
|
||||
|
||||
auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary
|
||||
auto_generated_function.AppendString (" new_keys = dict.keys()"); // Make a list of keys in the session dict
|
||||
auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict
|
||||
auto_generated_function.AppendString (" global_dict.update (dict)"); // Add the session dictionary to the
|
||||
// global dictionary.
|
||||
|
||||
// Wrap everything up inside the function, increasing the indentation.
|
||||
|
||||
for (int i = 0; i < num_lines; ++i)
|
||||
{
|
||||
sstr.Clear ();
|
||||
sstr.Printf (" %s", user_input.GetStringAtIndex (i));
|
||||
auto_generated_function.AppendString (sstr.GetData());
|
||||
}
|
||||
|
||||
// Append code to clean up the global dictionary and update the session dictionary (all updates in the function
|
||||
// got written to the values in the global dictionary, not the session dictionary).
|
||||
|
||||
auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict
|
||||
auto_generated_function.AppendString (" dict[key] = global_dict[key]"); // Update session dict values
|
||||
auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict
|
||||
auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict
|
||||
|
||||
// Verify that the results are valid Python.
|
||||
|
||||
if (!ExportFunctionDefinitionToInterpreter (auto_generated_function))
|
||||
return false;
|
||||
|
||||
// Store the name of the auto-generated function to be called.
|
||||
|
||||
output.AppendString (auto_generated_function_name.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, StringList &output)
|
||||
{
|
||||
StringList input(oneliner);
|
||||
return GenerateTypeScriptFunction(input, output);
|
||||
}
|
||||
|
||||
bool
|
||||
ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, StringList &callback_data)
|
||||
{
|
||||
|
@ -1206,6 +1318,63 @@ ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user
|
|||
return true;
|
||||
}
|
||||
|
||||
std::string
|
||||
ScriptInterpreterPython::CallPythonScriptFunction (const char *python_function_name,
|
||||
lldb::ValueObjectSP valobj)
|
||||
{
|
||||
|
||||
if (!python_function_name || !(*python_function_name))
|
||||
return "<no function>";
|
||||
|
||||
if (!valobj.get())
|
||||
return "<no object>";
|
||||
|
||||
Target *target = valobj->GetUpdatePoint().GetTarget();
|
||||
|
||||
if (!target)
|
||||
return "<no target>";
|
||||
|
||||
Debugger &debugger = target->GetDebugger();
|
||||
ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
|
||||
ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
|
||||
|
||||
if (!script_interpreter)
|
||||
return "<no python>";
|
||||
|
||||
std::string ret_val;
|
||||
|
||||
if (python_function_name
|
||||
&& *python_function_name)
|
||||
{
|
||||
FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
|
||||
if (CurrentThreadHasPythonLock())
|
||||
{
|
||||
python_interpreter->EnterSession ();
|
||||
ret_val = g_swig_typescript_callback (python_function_name,
|
||||
python_interpreter->m_dictionary_name.c_str(),
|
||||
valobj);
|
||||
python_interpreter->LeaveSession ();
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!GetPythonLock (1))
|
||||
fprintf (tmp_fh,
|
||||
"Python interpreter locked on another thread; waiting to acquire lock...\n");
|
||||
python_interpreter->EnterSession ();
|
||||
ret_val = g_swig_typescript_callback (python_function_name,
|
||||
python_interpreter->m_dictionary_name.c_str(),
|
||||
valobj);
|
||||
python_interpreter->LeaveSession ();
|
||||
ReleasePythonLock ();
|
||||
}
|
||||
}
|
||||
else
|
||||
return "<no function name>";
|
||||
|
||||
return ret_val;
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
ScriptInterpreterPython::BreakpointCallbackFunction
|
||||
(
|
||||
|
@ -1399,10 +1568,12 @@ ScriptInterpreterPython::RunEmbeddedPythonInterpreter (lldb::thread_arg_t baton)
|
|||
|
||||
void
|
||||
ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_init_callback,
|
||||
SWIGBreakpointCallbackFunction python_swig_breakpoint_callback)
|
||||
SWIGBreakpointCallbackFunction python_swig_breakpoint_callback,
|
||||
SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback)
|
||||
{
|
||||
g_swig_init_callback = python_swig_init_callback;
|
||||
g_swig_breakpoint_callback = python_swig_breakpoint_callback;
|
||||
g_swig_breakpoint_callback = python_swig_breakpoint_callback;
|
||||
g_swig_typescript_callback = python_swig_typescript_callback;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/State.h"
|
||||
#include "lldb/Core/StreamString.h"
|
||||
#include "lldb/Host/Endian.h"
|
||||
#include "lldb/Host/Host.h"
|
||||
#include "lldb/Host/TimeValue.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
LEVEL = ../../../make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
|
@ -0,0 +1,110 @@
|
|||
"""
|
||||
Test lldb data formatter subsystem.
|
||||
"""
|
||||
|
||||
import os, time
|
||||
import unittest2
|
||||
import lldb
|
||||
from lldbtest import *
|
||||
|
||||
class DataFormatterTestCase(TestBase):
|
||||
|
||||
mydir = os.path.join("functionalities", "data-formatter", "data-formatter-script")
|
||||
|
||||
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
||||
def test_with_dsym_and_run_command(self):
|
||||
"""Test data formatter commands."""
|
||||
self.buildDsym()
|
||||
self.data_formatter_commands()
|
||||
|
||||
def test_with_dwarf_and_run_command(self):
|
||||
"""Test data formatter commands."""
|
||||
self.buildDwarf()
|
||||
self.data_formatter_commands()
|
||||
|
||||
def setUp(self):
|
||||
# Call super's setUp().
|
||||
TestBase.setUp(self)
|
||||
# Find the line number to break at.
|
||||
self.line = line_number('main.cpp', '// Set break point at this line.')
|
||||
|
||||
def data_formatter_commands(self):
|
||||
"""Test that that file and class static variables display correctly."""
|
||||
self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
|
||||
|
||||
self.expect("breakpoint set -f main.cpp -l %d" % self.line,
|
||||
BREAKPOINT_CREATED,
|
||||
startstr = "Breakpoint created: 1: file ='main.cpp', line = %d, locations = 1" %
|
||||
self.line)
|
||||
|
||||
self.runCmd("run", RUN_SUCCEEDED)
|
||||
|
||||
# The stop reason of the thread should be breakpoint.
|
||||
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
||||
substrs = ['stopped',
|
||||
'stop reason = breakpoint'])
|
||||
|
||||
# This is the function to remove the custom formats in order to have a
|
||||
# clean slate for the next test case.
|
||||
def cleanup():
|
||||
self.runCmd('type format clear', check=False)
|
||||
self.runCmd('type summary clear', check=False)
|
||||
|
||||
# Execute the cleanup function during test case tear down.
|
||||
self.addTearDownHook(cleanup)
|
||||
|
||||
# Set the script here to ease the formatting
|
||||
script = 'a = valobj.GetChildMemberWithName(\'integer\'); a_val = a.GetValue(); str = \'Hello from Python, \' + a_val + \' time\'; return str + (\'!\' if a_val == \'1\' else \'s!\');'
|
||||
|
||||
self.runCmd("type summary add add i_am_cool -s \"%s\"" % script)
|
||||
|
||||
self.expect("frame variable one",
|
||||
substrs = ['Hello from Python',
|
||||
'1 time!'])
|
||||
|
||||
self.expect("frame variable two",
|
||||
substrs = ['Hello from Python',
|
||||
'4 times!'])
|
||||
|
||||
self.runCmd("n"); # skip ahead to make values change
|
||||
|
||||
self.expect("frame variable three",
|
||||
substrs = ['Hello from Python, 10 times!',
|
||||
'Hello from Python, 4 times!'])
|
||||
|
||||
self.runCmd("n"); # skip ahead to make values change
|
||||
|
||||
self.expect("frame variable two",
|
||||
substrs = ['Hello from Python',
|
||||
'1 time!'])
|
||||
|
||||
script = 'a = valobj.GetChildMemberWithName(\'integer\'); a_val = a.GetValue(); str = \'int says \' + a_val; return str;'
|
||||
|
||||
# Check that changes in the script are immediately reflected
|
||||
self.runCmd("type summary add i_am_cool -s \"%s\"" % script)
|
||||
|
||||
self.expect("frame variable two",
|
||||
substrs = ['int says 1'])
|
||||
|
||||
# Change the summary
|
||||
self.runCmd("type summary add -f \"int says ${var.integer}, and float says ${var.floating}\" i_am_cool")
|
||||
|
||||
self.expect("frame variable two",
|
||||
substrs = ['int says 1',
|
||||
'and float says 2.71'])
|
||||
# Try it for pointers
|
||||
self.expect("frame variable twoptr",
|
||||
substrs = ['int says 1',
|
||||
'and float says 2.71'])
|
||||
|
||||
# Force a failure for pointers
|
||||
self.runCmd("type summary add i_am_cool -p -s \"%s\"" % script)
|
||||
|
||||
self.expect("frame variable twoptr", matching=False,
|
||||
substrs = ['and float says 2.71'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
import atexit
|
||||
lldb.SBDebugger.Initialize()
|
||||
atexit.register(lambda: lldb.SBDebugger.Terminate())
|
||||
unittest2.main()
|
|
@ -0,0 +1,49 @@
|
|||
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct i_am_cool
|
||||
{
|
||||
int integer;
|
||||
float floating;
|
||||
char character;
|
||||
i_am_cool(int I, float F, char C) :
|
||||
integer(I), floating(F), character(C) {}
|
||||
i_am_cool() : integer(1), floating(2), character('3') {}
|
||||
|
||||
};
|
||||
|
||||
struct i_am_cooler
|
||||
{
|
||||
i_am_cool first_cool;
|
||||
i_am_cool second_cool;
|
||||
float floating;
|
||||
|
||||
i_am_cooler(int I1, int I2, float F1, float F2, char C1, char C2) :
|
||||
first_cool(I1,F1,C1),
|
||||
second_cool(I2,F2,C2),
|
||||
floating((F1 + F2)/2) {}
|
||||
};
|
||||
|
||||
int main (int argc, const char * argv[])
|
||||
{
|
||||
i_am_cool one(1,3.14,'E');
|
||||
i_am_cool two(4,2.71,'G');
|
||||
|
||||
i_am_cool* twoptr = &two;
|
||||
|
||||
i_am_cooler three(10,4,1985,1/1/2011,'B','E'); // Set break point at this line.
|
||||
|
||||
two.integer = 1;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -784,6 +784,17 @@
|
|||
(i_am_cool) one = x=3<br>
|
||||
</code> </p>
|
||||
|
||||
<p>When defining a named summmary, binding it to one or more types becomes optional.
|
||||
Even if you bind the named summary to a type, and later change the summary string
|
||||
for that type, the named summary will not be changed by that. You can delete
|
||||
named summaries by using the <code>type summary delete</code> command, as if the
|
||||
summary name was the datatype that the summary is applied to</p>
|
||||
|
||||
<p>A summary attached to a variable using the </code>--summary</code> option,
|
||||
has the same semantics that a custom format attached using the <code>-f</code>
|
||||
option has: it stays attached till you attach a new one, or till you let
|
||||
your program run again.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Reference in New Issue