diff options
author | Aleksandr Urakov <aleksandr.urakov@jetbrains.com> | 2019-02-05 09:14:36 +0000 |
---|---|---|
committer | Aleksandr Urakov <aleksandr.urakov@jetbrains.com> | 2019-02-05 09:14:36 +0000 |
commit | 40624a085c03fb6d41834885d41f7158ab72950e (patch) | |
tree | 669263f8f423f073f133b68787079cf8fecb8411 /lldb/source/API/SBValue.cpp | |
parent | de5220ed5e5ab1f7064e9bae57d7b4b8887277fa (diff) | |
download | bcm5719-llvm-40624a085c03fb6d41834885d41f7158ab72950e.tar.gz bcm5719-llvm-40624a085c03fb6d41834885d41f7158ab72950e.zip |
[Expressions] Add support of expressions evaluation in some object's context
Summary:
This patch adds support of expression evaluation in a context of some object.
Consider the following example:
```
struct S {
int a = 11;
int b = 12;
};
int main() {
S s;
int a = 1;
int b = 2;
// We have stopped here
return 0;
}
```
This patch allows to do something like that:
```
lldb.frame.FindVariable("s").EvaluateExpression("a + b")
```
and the result will be `33` (not `3`) because fields `a` and `b` of `s` will be
used (not locals `a` and `b`).
This is achieved by replacing of `this` type and object for the expression. This
has some limitations: an expression can be evaluated only for values located in
the debuggee process memory (they must have an address of `eAddressTypeLoad`
type).
Reviewers: teemperor, clayborg, jingham, zturner, labath, davide, spyffe, serge-sans-paille
Reviewed By: jingham
Subscribers: abidh, lldb-commits, leonid.mashinskiy
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D55318
llvm-svn: 353149
Diffstat (limited to 'lldb/source/API/SBValue.cpp')
-rw-r--r-- | lldb/source/API/SBValue.cpp | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index 31606af4a22..b83a4effcd5 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -1294,6 +1294,87 @@ bool SBValue::GetExpressionPath(SBStream &description, return false; } +lldb::SBValue SBValue::EvaluateExpression(const char* expr) const { + ValueLocker locker; + lldb::ValueObjectSP value_sp(GetSP(locker)); + if (!value_sp) + return SBValue(); + + lldb::TargetSP target_sp = value_sp->GetTargetSP(); + if (!target_sp) + return SBValue(); + + lldb::SBExpressionOptions options; + options.SetFetchDynamicValue(target_sp->GetPreferDynamicValue()); + options.SetUnwindOnError(true); + options.SetIgnoreBreakpoints(true); + + return EvaluateExpression(expr, options, nullptr); +} + +lldb::SBValue +SBValue::EvaluateExpression(const char *expr, + const SBExpressionOptions &options) const { + return EvaluateExpression(expr, options, nullptr); +} + +lldb::SBValue SBValue::EvaluateExpression(const char *expr, + const SBExpressionOptions &options, + const char *name) const { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); + + if (!expr || expr[0] == '\0') { + LLDB_LOG(log, + "SBValue::EvaluateExpression called with an empty expression"); + return SBValue(); + } + + LLDB_LOG(log, "SBValue()::EvaluateExpression (expr=\"{0}\")...", expr); + + ValueLocker locker; + lldb::ValueObjectSP value_sp(GetSP(locker)); + if (!value_sp) { + LLDB_LOG(log, "SBValue::EvaluateExpression () => error: could not " + "reconstruct value object for this SBValue"); + return SBValue(); + } + + lldb::TargetSP target_sp = value_sp->GetTargetSP(); + if (!target_sp) { + LLDB_LOG( + log, + "SBValue::EvaluateExpression () => error: could not retrieve target"); + return SBValue(); + } + + std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex()); + ExecutionContext exe_ctx(target_sp.get()); + + StackFrame *frame = exe_ctx.GetFramePtr(); + if (!frame) { + LLDB_LOG(log, "SBValue::EvaluateExpression () => error: could not retrieve " + "current stack frame"); + return SBValue(); + } + + ValueObjectSP res_val_sp; + ExpressionResults expr_res = target_sp->EvaluateExpression( + expr, frame, res_val_sp, options.ref(), nullptr, value_sp.get()); + + if (name) + res_val_sp->SetName(ConstString(name)); + + LLDB_LOG(log, + "SBValue(Name=\"{0}\")::EvaluateExpression (expr=\"{1}\") => " + "SBValue(Success={2}) (execution result={3})", + value_sp->GetName(), expr, res_val_sp->GetError().Success(), + expr_res); + + SBValue result; + result.SetSP(res_val_sp, options.GetFetchDynamicValue()); + return result; +} + bool SBValue::GetDescription(SBStream &description) { Stream &strm = description.ref(); |