[Lldb-commits] [lldb] [lldb] Evaluate DW_OP_abs and DW_OP_shra with signed operand semantics (PR #225772)

via lldb-commits lldb-commits at lists.llvm.org
Sun Sep 27 19:14:37 PDT 2026


https://github.com/firmiana402 updated https://github.com/llvm/llvm-project/pull/225772

>From ed85a0b5b193fb69223ac1923ee1b2fd0d8adc51 Mon Sep 17 00:00:00 2001
From: firmiana402 <firmiana402 at gmail.com>
Date: Wed, 23 Sep 2026 21:38:27 +0800
Subject: [PATCH 1/2] [lldb] Evaluate DW_OP_abs with signed operand semantics

Interpret integer operand bits as signed for DW_OP_abs, then restore the original Scalar signedness so the result retains its type. Add 32- and 64-bit regression cases for generic all-ones values.
---
 lldb/source/Expression/DWARFExpression.cpp      | 14 +++++++++++---
 .../Expression/DWARFExpressionTest.cpp          | 17 +++++++++++++++--
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index f884724766714b..6b522ab5733f3c 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -1604,12 +1604,20 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
       stack[last_idx - 2] = old_top;
     } break;
 
-    case DW_OP_abs:
-      if (!stack.back().GetScalar().AbsoluteValue()) {
+    case DW_OP_abs: {
+      Scalar &operand = stack.back().GetScalar();
+      const bool was_unsigned =
+          operand.GetType() == Scalar::e_int && !operand.IsSigned();
+      // DW_OP_abs interprets the bits as signed without changing the result
+      // type.
+      operand.MakeSigned();
+      if (!operand.AbsoluteValue()) {
         return llvm::createStringError(
             "failed to take the absolute value of the first stack item");
       }
-      break;
+      if (was_unsigned)
+        operand.MakeUnsigned();
+    } break;
 
     case DW_OP_and:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index 31e629967c6a28..1337d99da48463 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -261,10 +261,11 @@ static llvm::Expected<Value> Evaluate(llvm::ArrayRef<uint8_t> expr,
                                       lldb::ModuleSP module_sp = {},
                                       DWARFExpression::Delegate *unit = nullptr,
                                       ExecutionContext *exe_ctx = nullptr,
-                                      RegisterContext *reg_ctx = nullptr) {
+                                      RegisterContext *reg_ctx = nullptr,
+                                      uint8_t address_size = 4) {
   DataExtractor extractor(
       expr.data(), expr.size(), lldb::eByteOrderLittle,
-      /*addr_size*/ exe_ctx ? exe_ctx->GetAddressByteSize() : 4);
+      /*addr_size*/ exe_ctx ? exe_ctx->GetAddressByteSize() : address_size);
 
   return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, extractor, unit,
                                    lldb::eRegisterKindLLDB,
@@ -1089,6 +1090,18 @@ TEST(DWARFExpression, DW_OP_abs) {
       Evaluate({DW_OP_const1s, static_cast<uint8_t>(-5), DW_OP_abs}),
       ExpectScalar(5));
   EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit5, DW_OP_abs}), ExpectScalar(5));
+
+  // Generic values have unspecified signedness, but DW_OP_abs interprets its
+  // operand as signed.
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const4u, 0xff, 0xff, 0xff, 0xff,
+                                 DW_OP_abs, DW_OP_stack_value}),
+                       ExpectScalar(32, 1, false));
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_const8u, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                DW_OP_abs, DW_OP_stack_value},
+               {}, nullptr, nullptr, nullptr,
+               /*address_size=*/8),
+      ExpectScalar(64, 1, false));
 }
 
 TEST(DWARFExpression, DW_OP_div_int_min_by_neg_one) {

>From 8d91d8cdeea6b63184d70bd2d42998971f25290f Mon Sep 17 00:00:00 2001
From: firmiana402 <firmiana402 at gmail.com>
Date: Wed, 23 Sep 2026 21:39:51 +0800
Subject: [PATCH 2/2] [lldb] Evaluate DW_OP_shra with signed operand semantics

Interpret integer operand bits as signed for DW_OP_shra so an arithmetic right shift propagates the sign bit. Restore the original Scalar signedness after shifting and cover 32- and 64-bit generic values.
---
 lldb/source/Expression/DWARFExpression.cpp        | 13 ++++++++++---
 lldb/unittests/Expression/DWARFExpressionTest.cpp | 12 ++++++++++++
 2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 6b522ab5733f3c..a04c498f22a9bb 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -1753,15 +1753,22 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
         return llvm::createStringError("DW_OP_shr failed");
       break;
 
-    case DW_OP_shra:
+    case DW_OP_shra: {
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
               stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
               opcode, address_size))
         return err;
       tmp = stack.back();
       stack.pop_back();
-      stack.back().GetScalar() >>= tmp.GetScalar();
-      break;
+      Scalar &operand = stack.back().GetScalar();
+      const bool was_unsigned =
+          operand.GetType() == Scalar::e_int && !operand.IsSigned();
+      // DW_OP_shra shifts signed bits without changing the result type.
+      operand.MakeSigned();
+      operand >>= tmp.GetScalar();
+      if (was_unsigned)
+        operand.MakeUnsigned();
+    } break;
 
     case DW_OP_xor:
       if (llvm::Error err = CheckScalarOperandsHaveSameType(
diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index 1337d99da48463..f5a0e89ebbbd07 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -1389,6 +1389,18 @@ TEST(DWARFExpression, DW_OP_shra) {
   EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1s, static_cast<uint8_t>(-8),
                                  DW_OP_lit1, DW_OP_shra}),
                        ExpectScalar(static_cast<int32_t>(-4)));
+
+  // Generic values have unspecified signedness, but DW_OP_shra performs a
+  // signed arithmetic right shift.
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_const4u, 0xff, 0xff, 0xff, 0xff, DW_OP_const1u, 31,
+                DW_OP_shra, DW_OP_stack_value}),
+      ExpectScalar(32, 0xffffffff, false));
+  EXPECT_THAT_EXPECTED(
+      Evaluate({DW_OP_const8u, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                DW_OP_const1u, 63, DW_OP_shra, DW_OP_stack_value},
+               {}, nullptr, nullptr, nullptr, /*address_size=*/8),
+      ExpectScalar(64, 0xffffffffffffffffULL, false));
 }
 
 TEST(DWARFExpression, DW_OP_shl_overflow_count) {



More information about the lldb-commits mailing list