llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: MrEven132 <details> <summary>Changes</summary> `DW_OP_breg0..31` and `DW_OP_bregx` preserved the scalar width supplied by the register backend and added their displacement as a `uint64_t`. On 32-bit targets this could leave a 64-bit value on the expression stack, so later generic address arithmetic did not wrap at the target address size. Perform the register-plus-offset calculation using the evaluator's address-sized generic representation. This keeps `DW_OP_breg*` results at the target address width without changing shared register reading or the generic operand compatibility rule. Add unit tests for both compact and extended breg opcodes. They cover a 32-bit register value, a backend-provided 64-bit register value on i386, a negative displacement, and modulo-32-bit overflow. Fixes #<!-- -->209728 --- Full diff: https://github.com/llvm/llvm-project/pull/216291.diff 2 Files Affected: - (modified) lldb/source/Expression/DWARFExpression.cpp (+4-2) - (modified) lldb/unittests/Expression/DWARFExpressionTest.cpp (+29) ``````````diff diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 2dbf61a14eac4..f4c4f519b09c7 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -1901,7 +1901,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate( return err; int64_t breg_offset = op->getRawOperand(0); - tmp.GetScalar() += static_cast<uint64_t>(breg_offset); + tmp.GetScalar() = to_generic(tmp.GetScalar().ULongLong()); + tmp.GetScalar() += to_generic(breg_offset); tmp.ClearContext(); stack.push_back(tmp); stack.back().SetValueType(Value::ValueType::LoadAddress); @@ -1913,7 +1914,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate( return err; int64_t breg_offset = op->getRawOperand(1); - tmp.GetScalar() += static_cast<uint64_t>(breg_offset); + tmp.GetScalar() = to_generic(tmp.GetScalar().ULongLong()); + tmp.GetScalar() += to_generic(breg_offset); tmp.ClearContext(); stack.push_back(tmp); stack.back().SetValueType(Value::ValueType::LoadAddress); diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp index e8bca7208c8d5..2d5890570d8eb 100644 --- a/lldb/unittests/Expression/DWARFExpressionTest.cpp +++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -1344,6 +1344,35 @@ TEST_F(DWARFExpressionMockProcessTest, DW_OP_bregx) { ExpectLoadAddress(0x2010)); } +TEST_F(DWARFExpressionMockProcessTest, DW_OP_breg_address_size) { + TestContext ctx; + ASSERT_TRUE( + CreateTestContext(&ctx, "i386-pc-linux", RegisterValue(uint32_t{0x2a}))); + ExecutionContext exe_ctx(ctx.process_sp); + + // Address arithmetic wraps at the target address size. In particular, + // 0xffffffff + 1 is zero on this 32-bit target. + EXPECT_THAT_EXPECTED( + Evaluate({DW_OP_breg0, 0x7f, DW_OP_const4u, 0xff, 0xff, 0xff, 0xff, + DW_OP_plus, DW_OP_lit1, DW_OP_plus, DW_OP_stack_value}, + {}, {}, &exe_ctx, ctx.reg_ctx_sp.get()), + ExpectScalar(32, 0x29, false)); +} + +TEST_F(DWARFExpressionMockProcessTest, DW_OP_bregx_address_size) { + TestContext ctx; + ASSERT_TRUE(CreateTestContext(&ctx, "i386-pc-linux", + RegisterValue(uint64_t{0x10000002a}))); + ExecutionContext exe_ctx(ctx.process_sp); + + // The register backend may expose a value wider than the target address. + EXPECT_THAT_EXPECTED( + Evaluate({DW_OP_bregx, 0x40, 0x7f, DW_OP_const4u, 0xff, 0xff, 0xff, 0xff, + DW_OP_plus, DW_OP_lit1, DW_OP_plus, DW_OP_stack_value}, + {}, {}, &exe_ctx, ctx.reg_ctx_sp.get()), + ExpectScalar(32, 0x29, false)); +} + TEST_F(DWARFExpressionMockProcessTest, DW_OP_deref) { EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit0, DW_OP_deref}), llvm::Failed()); `````````` </details> https://github.com/llvm/llvm-project/pull/216291 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
