In preparation for updating DIL to handle assignments, this adds a
member variable to the DIL Interpreter indicating whether or not
updating program variables is allowed. For invocations from the LLDB
command prompt (through "frame variable") we want to allow it, but from
other places we might not. Therefore we also add new StackFrame
ExpressionPathOption, eExpressionPathOptionsAllowVarUpdates, which we
add to calls from CommandObjectFrame, and which is checked in
GetValueForVariableExpressionPath. Finally, we also add a parameter,
can_update_vars, with a default value of true, to
ValueObject::SetValueFromInteger, as that will be the main function used
to by assignment in DIL.
In #186001, I said the last large chunk of downstream PtrAuth code in
LLDB was the expression evaluator support. However, that wasn't
accurate, as we also have changes to thread this through ValueObject.
Currently these functions take a target pointer. In Cross-language
projects this means it's down to chance what typesystem the resulting
value will be in, since the implementation returns the first scratch
type system in the target, which depends on the order of images and
their implementation language.
By passing in an execution context the selected frame is used to
determine the typesystem, which is usually the expected outcome when
using DIL.
This should be entirely NFC for Clang-only LLDBs, but is a necessity for
LLDBs with additional type system plugins such as the Swift plugin.
Assisted by Claude to patch the call sites.
The code was declaring a shared poiner and then immediately trying to
dereference it to initialize it's contents, but the dereference was
giving a seg fault. This fixes that issue.
This makes the constructions of string errors more concise and more
consistent, mainly by removing the `inconvertibleErrorCode()`.
Additional changes replace `createStringError(formatv(...), ...)` with
`createStringErrorV(...)`.
Assisted-by: Claude
This patch re-implements `TypeSystemClang::IsFloatingPointType` by
forwarding it to `clang::Type::isFloatingType`. The main difference is
that the latter returns false for float vector types. The motovation
here (apart from implementation simplicity) is that this is currently a
foot-gun because most callsites probably don't consider treating float
vector types. Callers should test for vectors explicitly using
`IsVectorType` (or use `GetTypeInfo`).
This patch makes all the callers of `IsFloatingPointType` now check
`GetTypeInfo() & eTypeIsFloat`. This is set for float vector types too,
so behaviour doesn't change.
To make sure we audit all the call-sites in `ValueObject.cpp`, I added a
helper `HasFloatRepresentation` (named after the
`clang::Type::hasFloatingRepresentation` API), which does the
`GetTypeInfo` check, and added a FIXME to it.
This patch moves ValueImpl and ValueLocker to ValueObject.{h,cpp}. This follows the example set in TypeImpl/SBType, where we have something that SBType uses internally that needs to be exposed in the layer below. In this case, SBValue uses ValueImpl, which wraps ValueObject. The wrapper helps avoid bugs, so we want to keep it, but the script interpreter needs to use it and said interpreter is conceptually *below* the SB layer...which means we can't use methods on SBValue.
This patch is purely the code motion part of that, future patches will actually make use of this moved code.
Consider the following program:
```
int main() {
int foo[2][3][4];
int (*bar)[3][4] = foo;
return 0;
}
```
If we:
- compile this program
- launch an LLDB debugging session
- launch the process and let it stop at the `return 0;` statement
then the following LLDB command:
```
(lldb) script lldb.frame.FindVariable("bar").GetChildAtIndex(0).get_expr_path()
```
will produce the following output:
```
bar->[0]
```
What we were expecting:
- a valid expression in the C programming language
- that would allow us (in the scope of the `main` function) access the
appropriate object.
What we've got is a string that does not represent a valid expression in
the C programming language.
This pull-request proposes a fix to this problem.
---------
Co-authored-by: Matej Košík <matej.kosik@codasip.com>
There were a couple of quirks with this parameter:
1. It wasn't being set consistently. E.g., vector types would be of
count `1` but complex types would be `2`. Hence, it wasn't clear what
count was referring to.
2. `count` was not being set if the input type was invalid, possibly
leaving the input reference uninitialized.
3. Only one callsite actually made use of `count`, and that in itself
seems like it could be improved (added a FIXME).
If we ever need a "how many elements does this type represent", we can
implement one with a new `TypeSystem` API that does exactly that.
Add `ValueObject::CreateValueObjectFromScalar` function and adjust
`Scalar::GetData` to be able to both extend and truncate the data bytes
in Scalar to the specified size.
`SBType::GetBasicType` fails on typedefs to primitive types. The docs
for `GetBasicType` state:
```
Returns the BasicType value that is most appropriate to this type
```
But, e.g., for `uint64_t` this would currently return
`eBasicTypeInvalid`.
`TypeSystemClang::GetBasicTypeEnumeration` (which is what
`SBType::GetBasicType` uses) doesn't see through typedefs. Inside LLDB
we almost always call `GetBasicTypeEnumeration` on the canonical type.
In the cases we don't I suspect those were just subtle bugs. This patch
gets the canonical type inside of `GetBasicTypeEnumeration` instead.
rdar://155829208
The problem was in calling GetLoadAddress on a value in the error state,
where `ValueObject::GetLoadAddress` could end up accessing the
uninitialized "address type" by-ref return value from `GetAddressOf`.
This probably happened because each function expected the other to
initialize it.
We can guarantee initialization by turning this into a proper return
value.
I've added a test, but it only (reliably) crashes if lldb is built with
ubsan.
A few files of lldb dir & few other files had duplicate headers
included. This patch removes those redundancies.
---------
Co-authored-by: Akash Agrawal <akashag@qti.qualcomm.com>
Motivation example:
```
> lldb -c altmain2.core
...
(lldb) var F
(const char *) F = 0x0804a000 ""
```
The variable `F` points to a read-only memory page not dumped to the
core file, so `Process::ReadMemory()` cannot read the data. The patch
switches to `Target::ReadMemory()`, which can read data both from the
process memory and the application binary.
`ValueObject::AddressOf()` used to return address as a value which has
it's own address, allowing to do `value.AddressOf().AddressOf()`.
This patch makes the return address a simple const value.
The function was always trying to dereference both the synthetic and
non-synthetic view of the object. This is wrong as the caller should be
able to determine which view of the object it wants to access, as is
done e.g. for child member access.
This patch removes the nonsynthetic->synthetic fallback, which is the
more surprising path, and fixes the callers to try both versions of the
object (when appropriate). I also snuck in simplification of the member
access code path because it was possible to use the same helper function
for that, and I wanted to be sure I understand the logic correctly.
I've left the synthetic->nonsynthetic fallback in place. I think we may
want to keep that one as we often have synthetic child providers for
pointer types. They usually don't provide an explicit dereference
operation but I think users would expect that a dereference operation on
those objects would work. What we may want to do is to try the
*synthetic* operation first in this case, so that the nonsynthetic case
is really a fallback.
---------
Co-authored-by: Ilia Kuklin <kuklin.iy@mail.ru>
When the data-formatters happen to break (e.g., due to layout changes in
libc++), there's no clear indicator of them failing from a user's
perspective. E.g., for `std::vector`s we would just show:
```
(std::vector<int>) v = size=0 {}
```
which is highly misleading, especially if `v.size()` returns a non-zero
size.
This patch surfaces the various errors that could occur when calculating
the number of children of a vector.
rdar://146964266
This patch pushes the error handling boundary for the GetBitSize()
methods from Runtime into the Type and CompilerType APIs. This makes it
easier to diagnose problems thanks to more meaningful error messages
being available. GetBitSize() is often the first thing LLDB asks about a
type, so this method is particularly important for a better user
experience.
rdar://145667239
…uffer
ValueObjectDynamicValue::UpdateValue() assumes that the dynamic type
found by GetDynamicTypeAndAddress() would return an address in the
inferior. This commit makes it so it can deal with being passed a host
address instead.
This is needed downstream by the Swift fork.
rdar://143357274
Update the error returns in ValueObject::CastToBasicType and
ValueObject::CastToEnumType to create new errors and return a
ValueObjectConstResult with the error, rather tnan updating the error in
(and returning) the input ValueObject.
This reverts commit 25909b811a7ddc983d042b15cb54ec271a673d63 due to
unresolved questions about the behavior of "frame var" and ValueObject
in the presence of references (see the original patch for discussion).
ValueObject is part of lldbCore for historical reasons, but conceptually
it deserves to be its own library. This does introduce a (link-time) circular
dependency between lldbCore and lldbValueObject, which is unfortunate
but probably unavoidable because so many things in LLDB rely on
ValueObject. We already have cycles and these libraries are never built
as dylibs so while this doesn't improve the situation, it also doesn't
make things worse.
The header includes were updated with the following command:
```
find . -type f -exec sed -i.bak "s%include \"lldb/Core/ValueObject%include \"lldb/ValueObject/ValueObject%" '{}' \;
```