[lldb] Zero extend APInt when piece size is bigger than the bitwidth (#150149)

### Summary
We have internally seen cases like this 
`DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x28`
where we have longer op pieces than what Scalar supports (32, 64 or 128
bits). In these cases LLDB is currently hitting the assertion
`assert(ap_int.getBitWidth() >= bit_size);`

We are extending the generated APInt to the piece size by filling zeros.


### Test plan

Added a unit to cover this case. 

### Reviewers
@clayborg , @jeffreytan81 , @Jlalond
This commit is contained in:
satyanarayana reddy janga
2025-08-04 09:42:42 -07:00
committed by GitHub
parent 8f77fa7026
commit a0db29d647
2 changed files with 28 additions and 8 deletions

View File

@@ -1975,14 +1975,13 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
piece_byte_size,
(uint64_t)curr_piece_source_value.GetScalar().GetByteSize());
}
// Create curr_piece with bit_size. By default Scalar
// grows to the nearest host integer type.
llvm::APInt fail_value(1, 0, false);
llvm::APInt ap_int = scalar.UInt128(fail_value);
assert(ap_int.getBitWidth() >= bit_size);
llvm::ArrayRef<uint64_t> buf{ap_int.getRawData(),
ap_int.getNumWords()};
curr_piece.GetScalar() = Scalar(llvm::APInt(bit_size, buf));
// We have seen a case where we have expression like:
// DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x28
// here we are assuming the compiler was trying to zero
// extend the value that we should append to the buffer.
scalar.TruncOrExtendTo(bit_size, /*sign=*/false);
curr_piece.GetScalar() = scalar;
} break;
}

View File

@@ -462,6 +462,27 @@ TEST(DWARFExpression, DW_OP_piece) {
llvm::HasValue(GetScalar(16, 0xff00, true)));
}
TEST(DWARFExpression, DW_OP_piece_host_address) {
static const uint8_t expr_data[] = {DW_OP_lit2, DW_OP_stack_value,
DW_OP_piece, 40};
llvm::ArrayRef<uint8_t> expr(expr_data, sizeof(expr_data));
DataExtractor extractor(expr.data(), expr.size(), lldb::eByteOrderLittle, 4);
// This tests if ap_int is extended to the right width.
// expect 40*8 = 320 bits size.
llvm::Expected<Value> result =
DWARFExpression::Evaluate(nullptr, nullptr, nullptr, extractor, nullptr,
lldb::eRegisterKindDWARF, nullptr, nullptr);
ASSERT_THAT_EXPECTED(result, llvm::Succeeded());
ASSERT_EQ(result->GetValueType(), Value::ValueType::HostAddress);
ASSERT_EQ(result->GetBuffer().GetByteSize(), 40ul);
const uint8_t *data = result->GetBuffer().GetBytes();
ASSERT_EQ(data[0], 2);
for (int i = 1; i < 40; i++) {
ASSERT_EQ(data[i], 0);
}
}
TEST(DWARFExpression, DW_OP_implicit_value) {
unsigned char bytes = 4;