llvm / llvm/llvm-project

[lldb] DW_OP_bit_piece is rejected for memory location descriptions

Open
#208,892 1 comment 0 reactions 0 assignees View on GitHub
lldb rejects-valid
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

LLDB rejects `DW_OP_bit_piece` when the preceding location description refers to target memory. [DWARF v5 Section 2.6.1.2](https://dwarfstd.org/doc/DWARF5.pdf) specifies that, for a memory location, `DW_OP_bit_piece` describes bits relative to the address on top of the DWARF stack. LLVM's [location-description stack extension](https://llvm.org/docs/AMDGPUDwarfExtensionAllowLocationDescriptionOnTheDwarfExpressionStack/AMDGPUDwarfExtensionAllowLocationDescriptionOnTheDwarfExpressionStack.html) likewise defines it as the bit-granular counterpart of `DW_OP_piece`.

This is related to #208888, which covers an empty location being rejected when the stack has no entry. This report covers a different branch: the stack contains a valid `LoadAddress`, but LLDB explicitly rejects it as an address value.

This is also distinct from #203224. That issue is rooted in `DW_OP_implicit_value` representing its payload as `ValueType::HostAddress`, which loses the implicit-storage semantics before piece composition. The expression here contains no `DW_OP_implicit_value`: `DW_OP_breg7 80` correctly produces a genuine `LoadAddress`, and the bug is in `DW_OP_bit_piece` itself rejecting that valid memory source.

## Two Equivalent Cases

These byte-aligned forms describe the same 16 bytes at the same register-relative memory location:

```text
DW_OP_breg7 80
DW_OP_piece 16
```

```text
DW_OP_breg7 80
DW_OP_bit_piece 128, 0
```

GDB evaluates both forms consistently. LLDB evaluates the `DW_OP_piece` form, but rejects the equivalent `DW_OP_bit_piece` form with:

```text
unable to extract DW_OP_bit_piece(bit_size = 128, bit_offset = 0) from an address value.
```

## Source Evidence

In [`DWARFExpression.cpp`](https://github.com/llvm/llvm-project/blob/main/lldb/source/Expression/DWARFExpression.cpp), `DW_OP_breg7 80` produces a genuine target-memory location represented as `ValueType::LoadAddress`. The `DW_OP_bit_piece` handler groups that source with other address kinds and rejects it:

```cpp
case Value::ValueType::FileAddress:
case Value::ValueType::LoadAddress:
case Value::ValueType::HostAddress:
return llvm::createStringError(
"unable to extract DW_OP_bit_piece(bit_size = %" PRIu64
", bit_offset = %" PRIu64 ") from an address value.",
piece_bit_size, piece_bit_offset);
```

By contrast, the byte-granular `Evaluate_DW_OP_piece` path supports `FileAddress` and `LoadAddress` by reading the requested bytes from target memory. A byte-aligned `DW_OP_bit_piece 128, 0` should use the same memory source and cover the same range as `DW_OP_piece 16`, rather than rejecting the location description.

Contributor guide

Open the contributing guide

Research direction

Start in lldb/source/Expression/DWARFExpression.cpp at the DW_OP_bit_piece handler, then compare it with the Evaluate_DW_OP_piece path for FileAddress and LoadAddress values. Check the equivalent DW_OP_breg7 80 expressions and relevant LLDB DWARF expression tests; done means byte-aligned DW_OP_bit_piece reads the same target-memory range as DW_OP_piece without rejecting the LoadAddress.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
devtools
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.