Issue 208898
Summary [lldb] DW_OP_piece serializes scalar fragments in host byte order but interprets them in target byte order
Labels
Assignees
Reporter firmiana402
    When LLDB assembles a composite value for `DW_OP_piece`, the completed piece buffer represents the target object's byte layout and is interpreted using target byte order. Scalar fragments are nevertheless serialized into that buffer using host byte order, while memory-backed fragments retain their raw target bytes. If the host and target have different endianness, scalar pieces are byte-swapped in the final value.

## Minimal Case

On a big-endian target debugged from a little-endian host, consider a two-byte scalar piece:

```text
DW_OP_const2u 0x1122
DW_OP_stack_value
DW_OP_piece 2
```

On a big-endian target, the two-byte target representation of `0x1122` is `11 22`. GDB preserves this value and prints `0x1122`. LLDB instead serializes the scalar in little-endian host order as `22 11`; those bytes are then interpreted as big-endian target data, yielding `0x2211`.

## Source Evidence

In [`DWARFExpression.cpp`](https://github.com/llvm/llvm-project/blob/main/lldb/source/_expression_/DWARFExpression.cpp), the scalar `DW_OP_piece` path truncates the scalar to the piece size and appends it to the composite buffer through `AppendDataToHostBuffer`:

```cpp
case Value::ValueType::Scalar: {
 uint32_t bit_size = piece_byte_size * 8;
  ...
 scalar.TruncOrExtendTo(bit_size, /*sign=*/false);
  curr_piece.GetScalar() = scalar;
} break;

...

eval_ctx.pieces.AppendDataToHostBuffer(curr_piece);
```

When piece evaluation finishes, this buffer is returned as the composite value:

```cpp
if (eval_ctx.pieces.GetBuffer().GetByteSize())
  return eval_ctx.pieces;
```

Although the buffer resides in LLDB's host memory, its bytes represent the target object. `Value::GetValueAsData` later assigns target byte order to a non-register `HostAddress` value:

```cpp
data.SetByteOrder(m_context_type == ContextType::RegisterInfo
                      ? endian::InlHostByteOrder()
                      : target->GetArchitecture().GetByteOrder());
```

The scalar branch of [`Value::AppendDataToHostBuffer`](https://github.com/llvm/llvm-project/blob/main/lldb/source/Core/Value.cpp) serializes that value using host byte order:

```cpp
rhs.m_value.GetAsMemoryData(m_data_buffer.GetBytes() + curr_size,
                            scalar_size, endian::InlHostByteOrder(),
                            error);
```

By contrast, memory pieces are read as raw target bytes and copied directly into the same buffer. The result is a mixed-endian composite whenever the target byte order differs from the host byte order.

_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to