https://github.com/MrEven132 created 
https://github.com/llvm/llvm-project/pull/216641

DW_OP_fbreg adds its signed displacement as an int64_t, which can widen a 
32-bit frame-base Scalar to 64 bits. Canonicalize the pushed result using the 
evaluator's existing generic conversion so subsequent arithmetic uses the 
target address width.

Add an i386 regression test that checks 32-bit wrapping and the resulting 
APSInt width.

Fixes #211007

>From dc852b227b8c8086b66470ef3beadfd072cf3c9f Mon Sep 17 00:00:00 2001
From: MrEven132 <[email protected]>
Date: Mon, 17 Aug 2026 12:08:31 +0800
Subject: [PATCH] [lldb] Keep DW_OP_fbreg results address-sized

DW_OP_fbreg adds its signed displacement as an int64_t, which can widen a 
32-bit frame-base Scalar to 64 bits. Canonicalize the pushed result using the 
evaluator's existing generic conversion so subsequent arithmetic uses the 
target address width.

Add an i386 regression test that checks 32-bit wrapping and the resulting 
APSInt width.

Fixes #211007
---
 lldb/source/Expression/DWARFExpression.cpp    |  2 ++
 .../Expression/DWARFExpressionTest.cpp        | 36 +++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/lldb/source/Expression/DWARFExpression.cpp 
b/lldb/source/Expression/DWARFExpression.cpp
index f4c4f519b09c7..0bc272ddd89b2 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -1925,6 +1925,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       if (llvm::Error err =
               Evaluate_DW_OP_fbreg(eval_ctx, op->getRawOperand(0)))
         return err;
+      stack.back().GetScalar() =
+          to_generic(stack.back().GetScalar().ULongLong());
       break;
 
     case DW_OP_nop:
diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp 
b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index c2752e16672f7..a1b5950ab4132 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -27,6 +27,7 @@
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/ABI.h"
 #include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
 #include "lldb/Utility/RegisterValue.h"
 #include "lldb/Utility/StreamString.h"
 #include "llvm/ADT/StringExtras.h"
@@ -230,6 +231,24 @@ class MockRegisterContext : public RegisterContext {
   RegisterInfo m_reg_info{};
   RegisterValue m_reg_value{};
 };
+
+class MockStackFrame : public StackFrame {
+public:
+  MockStackFrame(const lldb::ThreadSP &thread_sp, Scalar frame_base)
+      : StackFrame(thread_sp, /*frame_idx=*/0, /*concrete_frame_idx=*/0,
+                   /*cfa=*/0, /*cfa_is_valid=*/true, /*pc=*/0,
+                   StackFrame::Kind::Regular, /*artificial=*/false,
+                   /*behaves_like_zeroth_frame=*/true, /*sc_ptr=*/nullptr),
+        m_frame_base(std::move(frame_base)) {}
+
+  llvm::Error GetFrameBaseValue(Scalar &value) override {
+    value = m_frame_base;
+    return llvm::Error::success();
+  }
+
+private:
+  Scalar m_frame_base;
+};
 } // namespace
 
 static llvm::Expected<Value> Evaluate(llvm::ArrayRef<uint8_t> expr,
@@ -1375,6 +1394,23 @@ TEST_F(DWARFExpressionMockProcessTest, 
DW_OP_bregx_address_size) {
   EXPECT_EQ(result->GetScalar().GetAPSInt().getBitWidth(), 32u);
 }
 
+TEST_F(DWARFExpressionMockProcessTest, DW_OP_fbreg_address_size) {
+  TestContext ctx;
+  ASSERT_TRUE(CreateTestContext(&ctx, "i386-pc-linux"));
+  lldb::StackFrameSP frame_sp =
+      std::make_shared<MockStackFrame>(ctx.thread_sp, Scalar(uint32_t{0x2a}));
+  ExecutionContext exe_ctx(frame_sp);
+
+  // Address arithmetic wraps at the target address size. In particular,
+  // 0xffffffff + 1 is zero on this 32-bit target.
+  auto result =
+      Evaluate({DW_OP_fbreg, 0x7f, DW_OP_const4u, 0xff, 0xff, 0xff, 0xff,
+                DW_OP_plus, DW_OP_lit1, DW_OP_plus, DW_OP_stack_value},
+               {}, {}, &exe_ctx);
+  ASSERT_THAT_EXPECTED(result, ExpectScalar(32, 0x29, false));
+  EXPECT_EQ(result->GetScalar().GetAPSInt().getBitWidth(), 32u);
+}
+
 TEST_F(DWARFExpressionMockProcessTest, DW_OP_deref) {
   EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit0, DW_OP_deref}), llvm::Failed());
 

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

Reply via email to