[Lldb-commits] [PATCH] D98370: [lldb] Fix SBValue::Persist() for constant values
Andy Yankovsky via Phabricator via lldb-commits
lldb-commits at lists.llvm.org
Thu Apr 22 13:42:28 PDT 2021
werat added a comment.
In D98370#2709828 <https://reviews.llvm.org/D98370#2709828>, @jingham wrote:
> Be careful here. There are really two kinds of persistent variables: "expression results" and variables created in the expression parser. The former are by design constant. The idea is that you can use them to checkpoint the state of a value and refer to it later. You can use their values in expressions, but they aren't supposed to be modifiable. Those are the ones called $NUM.
>
> The ones you make in an expression, like:
>
> (lldb) expr int $myVar = 20
>
> on the other hand are modifiable.
What about the values created via `SBValue::Persist()` then? They have names like `$NUM`, but they can be either of the two you mentioned and more (values created via `CreateValueFromData` or values acquired via `FindVariable`):
v = frame.EvaluateExpression("...") # `v` is "$0" -- it's an "expression result" by your classification
vp = v.Persist() # `vp` is "$1" -- I assume it should point the same value as "$0" and be non-modifiable
--
v = frame.EvaluateExpression("$myVar = 20") # `v` is "$0" -- it's an "expression result" by your classification
vp = v.Persist() # `vp` is "$1" -- I assume it should point the same value as "$0" and be non-modifiable
myVar = frame.EvaluateExpression("$myVar") # now `myVar` is "$myVar" -- it's a "variables created in the expression parser"
myVarP= myVar.Persist() # `myVarP` is "$2" -- ?? Should it point the same value as `myVar` and be modifiable?
--
v = target.CreateValueFromData(...)
vp = v.Persist() # `vp` is "$0" -- ?? Should it be modifiable? Should it point to the original `v`?
------
I think at this point I should explain the problem I'm solving from the beginning.
I have built an expression evaluator for LLDB (and based on LLDB) -- https://github.com/google/lldb-eval. It's much faster than LLDB's `EvaluateExpression`, but has some limitations -- it doesn't support user-defined function calls, doesn't allows to evaluate arbitrary C++ code, etc.
It is used in Stadia for Visual Studio debugger (https://github.com/googlestadia/vsi-lldb) complementing LLDB. Expressions that are not supported by `lldb-eval` are evaluated by `LLDB`, thus from user perspective everything "just works". In some situations we need to maintain some "state", which can be read/written by multiple consecutive expressions. Simplified example:
EvaluateExpression("$index += 1");
v1 = EvaluateExpression("array[$index]")
EvaluateExpression("$index += 1");
v2 = EvaluateExpression("array[$index]")
In case of `LLDB` we create `$index` via something like `expr $index = 0` and then the expressions can modify it. In `lldb-eval`, however, we don't want to use LLDB's persistent variables, so the state is represented via regular map of `SBValue` objects (https://werat.dev/blog/blazing-fast-expression-evaluation-for-c-in-lldb/#maintaning-state). Basically the API is something like this:
state = {"index": some_sbvalue}
EvaluateExpression("index += 1", state);
v1 = EvaluateExpression("array[index]", state)
EvaluateExpression("index += 1", state);
v2 = EvaluateExpression("array[index]", state)
some_sbvalue.GetValue() # == 2
But as I mentioned before, our debugger shell is "smart" and can fallback to `LLDB` if `lldb-eval` fails to evaluate the expression. If there was a state involved, it needs to be converted to LLDB's persistent variables. Right now we workaround this issues by always allocating "state" values in LLDB (https://github.com/googlestadia/vsi-lldb/blob/0fcbe30a498fac70230efdb815125ee5f6f087bb/YetiVSI/DebugEngine/NatvisEngine/NatvisExpressionEvaluator.cs#L315) -- this way we don't need to convert it back. However it would be better to convert only if needed and for that I was hoping to use `SBValue::Persist()`.
The example below doesn't work, but that's what I would like to fix (code is simplified):
// We can assume here the result is created via something like `CreateValueFromData()`
//
lldb::SBValue counter = lldb_eval::EvaluateExpression("10");
lldb_eval::ContextVariableList vars = { {"counter", &counter } };
while (counter.GetValueAsUnsigned() > 5) {
lldb_eval::EvaluateExpression("--counter", vars);
}
lldb::SBValue p = counter.Persist(); // Assume `p.GetName()` is "$1"
lldb::SBValue v1 = lldb::EvaluateExpression("$1"); // v1.GetValue() == 5
lldb::SBValue v2 = lldb::EvaluateExpression("--$1"); // v2.GetValue() == 4
Sorry for the long message, I hope it's more clear what I'm trying to do here :)
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D98370/new/
https://reviews.llvm.org/D98370
More information about the lldb-commits
mailing list