[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