Added a user-settable variable, 'target.expr-prefix',
which holds the name of a file whose contents are prefixed to each expression. For example, if the file ~/lldb.prefix.header contains: typedef unsigned short my_type; then you can do this: (lldb) settings set target.expr-prefix '~/lldb.prefix.header' (lldb) expr sizeof(my_type) (unsigned long) $0 = 2 When the variable is changed, the corresponding file is loaded and its contents are fetched into a string that is stored along with the target. This string is then passed to each expression and inserted into it during parsing, like this: typedef unsigned short my_type; void $__lldb_expr(void *$__lldb_arg) { sizeof(my_type); } llvm-svn: 117627
This commit is contained in:
parent
5d6f6a061b
commit
322f529b37
|
@ -45,8 +45,16 @@ class ClangUserExpression : public ClangExpression
|
|||
public:
|
||||
//------------------------------------------------------------------
|
||||
/// Constructor
|
||||
///
|
||||
/// @param[in] expr
|
||||
/// The expression to parse.
|
||||
///
|
||||
/// @param[in] expr_prefix
|
||||
/// If non-NULL, a C string containing translation-unit level
|
||||
/// definitions to be included when the expression is parsed.
|
||||
//------------------------------------------------------------------
|
||||
ClangUserExpression (const char *expr);
|
||||
ClangUserExpression (const char *expr,
|
||||
const char *expr_prefix);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Destructor
|
||||
|
@ -189,9 +197,23 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Evaluate one expression and return its result.
|
||||
///
|
||||
/// @param[in] exe_ctx
|
||||
/// The execution context to use when evaluating the expression.
|
||||
///
|
||||
/// @param[in] expr_cstr
|
||||
/// A C string containing the expression to be evaluated.
|
||||
///
|
||||
/// @param[in] expr_prefix
|
||||
/// If non-NULL, a C string containing translation-unit level
|
||||
/// definitions to be included when the expression is parsed.
|
||||
//------------------------------------------------------------------
|
||||
static lldb::ValueObjectSP
|
||||
Evaluate (ExecutionContext &exe_ctx, const char *expr_cstr);
|
||||
Evaluate (ExecutionContext &exe_ctx,
|
||||
const char *expr_cstr,
|
||||
const char *expr_prefix);
|
||||
|
||||
private:
|
||||
//------------------------------------------------------------------
|
||||
|
@ -207,6 +229,7 @@ private:
|
|||
lldb::addr_t &object_ptr);
|
||||
|
||||
std::string m_expr_text; ///< The text of the expression, as typed by the user
|
||||
std::string m_expr_prefix; ///< The text of the translation-level definitions, as provided by the user
|
||||
std::string m_transformed_text; ///< The text of the expression, as send to the parser
|
||||
|
||||
std::auto_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing and materializing the expression.
|
||||
|
|
|
@ -71,8 +71,8 @@ protected:
|
|||
const ConstString
|
||||
CreateInstanceName ();
|
||||
|
||||
private:
|
||||
|
||||
std::string m_expr_prefix_path;
|
||||
std::string m_expr_prefix_contents;
|
||||
};
|
||||
|
||||
class Target :
|
||||
|
@ -437,6 +437,9 @@ public:
|
|||
ClangASTContext *
|
||||
GetScratchClangASTContext();
|
||||
|
||||
const char *
|
||||
GetExpressionPrefixContentsAsCString ();
|
||||
|
||||
protected:
|
||||
friend class lldb::SBTarget;
|
||||
|
||||
|
|
|
@ -547,7 +547,13 @@ SBFrame::EvaluateExpression (const char *expr)
|
|||
{
|
||||
ExecutionContext exe_ctx;
|
||||
m_opaque_sp->CalculateExecutionContext (exe_ctx);
|
||||
*expr_result_value = ClangUserExpression::Evaluate (exe_ctx, expr);
|
||||
|
||||
const char *prefix = NULL;
|
||||
|
||||
if (exe_ctx.target)
|
||||
prefix = exe_ctx.target->GetExpressionPrefixContentsAsCString();
|
||||
|
||||
*expr_result_value = ClangUserExpression::Evaluate (exe_ctx, expr, prefix);
|
||||
}
|
||||
return expr_result_value;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ BreakpointOptions::BreakpointOptions(const BreakpointOptions& rhs) :
|
|||
if (rhs.m_thread_spec_ap.get() != NULL)
|
||||
m_thread_spec_ap.reset (new ThreadSpec(*rhs.m_thread_spec_ap.get()));
|
||||
if (rhs.m_condition_ap.get())
|
||||
m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText()));
|
||||
m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText(), NULL));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -76,7 +76,7 @@ BreakpointOptions::operator=(const BreakpointOptions& rhs)
|
|||
if (rhs.m_thread_spec_ap.get() != NULL)
|
||||
m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
|
||||
if (rhs.m_condition_ap.get())
|
||||
m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText()));
|
||||
m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText(), NULL));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ BreakpointOptions::SetCondition (const char *condition)
|
|||
}
|
||||
else
|
||||
{
|
||||
m_condition_ap.reset(new ClangUserExpression (condition));
|
||||
m_condition_ap.reset(new ClangUserExpression (condition, NULL));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -233,7 +233,12 @@ CommandObjectExpression::EvaluateExpression
|
|||
m_exe_ctx.process->SetDynamicCheckers(dynamic_checkers);
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP result_valobj_sp (ClangUserExpression::Evaluate (m_exe_ctx, expr));
|
||||
const char *prefix = NULL;
|
||||
|
||||
if (m_exe_ctx.target)
|
||||
prefix = m_exe_ctx.target->GetExpressionPrefixContentsAsCString();
|
||||
|
||||
lldb::ValueObjectSP result_valobj_sp (ClangUserExpression::Evaluate (m_exe_ctx, expr, prefix));
|
||||
assert (result_valobj_sp.get());
|
||||
if (result_valobj_sp->GetError().Success())
|
||||
{
|
||||
|
|
|
@ -35,8 +35,10 @@
|
|||
|
||||
using namespace lldb_private;
|
||||
|
||||
ClangUserExpression::ClangUserExpression (const char *expr) :
|
||||
ClangUserExpression::ClangUserExpression (const char *expr,
|
||||
const char *expr_prefix) :
|
||||
m_expr_text(expr),
|
||||
m_expr_prefix(expr_prefix),
|
||||
m_transformed_text(),
|
||||
m_jit_addr(LLDB_INVALID_ADDRESS),
|
||||
m_cplusplus(false),
|
||||
|
@ -129,12 +131,14 @@ ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx)
|
|||
|
||||
if (m_cplusplus)
|
||||
{
|
||||
m_transformed_stream.Printf("typedef unsigned short unichar; \n"
|
||||
m_transformed_stream.Printf("%s \n"
|
||||
"typedef unsigned short unichar; \n"
|
||||
"void \n"
|
||||
"$__lldb_class::%s(void *$__lldb_arg) \n"
|
||||
"{ \n"
|
||||
" %s; \n"
|
||||
"} \n",
|
||||
m_expr_prefix.c_str(),
|
||||
FunctionName(),
|
||||
m_expr_text.c_str());
|
||||
|
||||
|
@ -142,12 +146,14 @@ ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx)
|
|||
}
|
||||
else
|
||||
{
|
||||
m_transformed_stream.Printf("typedef unsigned short unichar;\n"
|
||||
m_transformed_stream.Printf("%s \n"
|
||||
"typedef unsigned short unichar;\n"
|
||||
"void \n"
|
||||
"%s(void *$__lldb_arg) \n"
|
||||
"{ \n"
|
||||
" %s; \n"
|
||||
"} \n",
|
||||
m_expr_prefix.c_str(),
|
||||
FunctionName(),
|
||||
m_expr_text.c_str());
|
||||
}
|
||||
|
@ -425,11 +431,13 @@ ClangUserExpression::DwarfOpcodeStream ()
|
|||
|
||||
|
||||
lldb::ValueObjectSP
|
||||
ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, const char *expr_cstr)
|
||||
ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
|
||||
const char *expr_cstr,
|
||||
const char *expr_prefix)
|
||||
{
|
||||
Error error;
|
||||
lldb::ValueObjectSP result_valobj_sp;
|
||||
ClangUserExpression user_expression (expr_cstr);
|
||||
ClangUserExpression user_expression (expr_cstr, expr_prefix);
|
||||
|
||||
StreamString error_stream;
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "lldb/Breakpoint/BreakpointResolverAddress.h"
|
||||
#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
|
||||
#include "lldb/Breakpoint/BreakpointResolverName.h"
|
||||
#include "lldb/Core/DataBufferMemoryMap.h"
|
||||
#include "lldb/Core/Event.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/Timer.h"
|
||||
|
@ -853,6 +854,12 @@ Target::UpdateInstanceName ()
|
|||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
Target::GetExpressionPrefixContentsAsCString ()
|
||||
{
|
||||
return m_expr_prefix_contents.c_str();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// class Target::SettingsController
|
||||
//--------------------------------------------------------------
|
||||
|
@ -976,6 +983,7 @@ TargetInstanceSettings::operator= (const TargetInstanceSettings &rhs)
|
|||
return *this;
|
||||
}
|
||||
|
||||
#define EXPR_PREFIX_STRING "expr-prefix"
|
||||
|
||||
void
|
||||
TargetInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name,
|
||||
|
@ -987,14 +995,64 @@ TargetInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_n
|
|||
Error &err,
|
||||
bool pending)
|
||||
{
|
||||
// Currently 'target' does not have any instance settings.
|
||||
static ConstString expr_prefix_str (EXPR_PREFIX_STRING);
|
||||
|
||||
if (var_name == expr_prefix_str)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
default:
|
||||
err.SetErrorToGenericError ();
|
||||
err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
|
||||
return;
|
||||
case lldb::eVarSetOperationAssign:
|
||||
{
|
||||
FileSpec file_spec(value, true);
|
||||
|
||||
if (!file_spec.Exists())
|
||||
{
|
||||
err.SetErrorToGenericError ();
|
||||
err.SetErrorStringWithFormat ("%s does not exist.\n", value);
|
||||
return;
|
||||
}
|
||||
|
||||
DataBufferMemoryMap buf;
|
||||
|
||||
if (!buf.MemoryMapFromFileSpec(&file_spec) &&
|
||||
buf.GetError().Fail())
|
||||
{
|
||||
err.SetErrorToGenericError ();
|
||||
err.SetErrorStringWithFormat ("Couldn't read from %s: %s\n", value, buf.GetError().AsCString());
|
||||
return;
|
||||
}
|
||||
|
||||
m_expr_prefix_path = value;
|
||||
m_expr_prefix_contents.assign(reinterpret_cast<const char *>(buf.GetBytes()), buf.GetByteSize());
|
||||
}
|
||||
return;
|
||||
case lldb::eVarSetOperationAppend:
|
||||
err.SetErrorToGenericError ();
|
||||
err.SetErrorString ("Cannot append to a path.\n");
|
||||
return;
|
||||
case lldb::eVarSetOperationClear:
|
||||
m_expr_prefix_path.clear ();
|
||||
m_expr_prefix_contents.clear ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TargetInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &new_settings,
|
||||
bool pending)
|
||||
{
|
||||
// Currently 'target' does not have any instance settings.
|
||||
TargetInstanceSettings *new_settings_ptr = static_cast <TargetInstanceSettings *> (new_settings.get());
|
||||
|
||||
if (!new_settings_ptr)
|
||||
return;
|
||||
|
||||
m_expr_prefix_path = new_settings_ptr->m_expr_prefix_path;
|
||||
m_expr_prefix_contents = new_settings_ptr->m_expr_prefix_contents;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1003,9 +1061,20 @@ TargetInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
|
|||
StringList &value,
|
||||
Error *err)
|
||||
{
|
||||
static ConstString expr_prefix_str (EXPR_PREFIX_STRING);
|
||||
|
||||
if (var_name == expr_prefix_str)
|
||||
{
|
||||
value.AppendString (m_expr_prefix_path.c_str(), m_expr_prefix_path.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (err)
|
||||
err->SetErrorString ("'target' does not have any instance settings");
|
||||
err->SetErrorStringWithFormat ("unrecognized variable name '%s'", var_name.AsCString());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const ConstString
|
||||
|
@ -1028,7 +1097,7 @@ TargetInstanceSettings::CreateInstanceName ()
|
|||
SettingEntry
|
||||
Target::SettingsController::global_settings_table[] =
|
||||
{
|
||||
//{ "var-name", var-type , "default", enum-table, init'd, hidden, "help-text"},
|
||||
//{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"},
|
||||
{ "default-arch", eSetVarTypeString, NULL, NULL, false, false, "Default architecture to choose, when there's a choice." },
|
||||
{ NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
|
||||
};
|
||||
|
@ -1037,5 +1106,6 @@ SettingEntry
|
|||
Target::SettingsController::instance_settings_table[] =
|
||||
{
|
||||
//{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"},
|
||||
{ EXPR_PREFIX_STRING, eSetVarTypeString, NULL, NULL, false, false, "Path to a file containing expressions to be prepended to all expressions." },
|
||||
{ NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue