vsk updated this revision to Diff 239753.
vsk edited the summary of this revision.
This revision is now accepted and ready to land.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73148/new/

https://reviews.llvm.org/D73148

Files:
  lldb/packages/Python/lldbsuite/test/functionalities/dw_op_piece/Makefile
  
lldb/packages/Python/lldbsuite/test/functionalities/dw_op_piece/TestDW_OP_piece.py
  lldb/packages/Python/lldbsuite/test/functionalities/dw_op_piece/main.cpp
  lldb/source/Core/Value.cpp
  lldb/unittests/Expression/DWARFExpressionTest.cpp

Index: lldb/unittests/Expression/DWARFExpressionTest.cpp
===================================================================
--- lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -360,4 +360,27 @@
       // Note that the "00" should really be "undef", but we can't
       // represent that yet.
       llvm::HasValue(GetScalar(16, 0xff00, true)));
+
+  for (unsigned char ByteSize = 1; ByteSize <= 8; ++ByteSize) {
+    llvm::Expected<Scalar> empty = Evaluate({DW_OP_piece, ByteSize});
+    // Note that the "0" should really be "undef", but we can't
+    // represent that yet.
+    EXPECT_THAT_EXPECTED(empty,
+                         llvm::HasValue(GetScalar(ByteSize * 8, 0, true)));
+
+    Value pieces;
+    ASSERT_EQ(pieces.AppendDataToHostBuffer(empty.get()), ByteSize);
+    ASSERT_EQ(pieces.GetValueByteSize(nullptr, nullptr), ByteSize);
+  }
+
+  // When CommandObjectFrameVariable constructs an empty Value, check that
+  // we do not successfully report its size as 0. A CompilerType is needed to
+  // get the size in this special case.
+  {
+    Value empty;
+    empty.ResizeData(0);
+    Status error;
+    ASSERT_EQ(empty.GetValueByteSize(&error, nullptr), 0);
+    ASSERT_TRUE(error.Fail());
+  }
 }
Index: lldb/source/Core/Value.cpp
===================================================================
--- lldb/source/Core/Value.cpp
+++ lldb/source/Core/Value.cpp
@@ -222,6 +222,12 @@
   case eContextTypeLLDBType: // Type *
   case eContextTypeVariable: // Variable *
   {
+    // The size of this Value may be less than the size of the type of its
+    // source variable due to truncating operations such as DW_OP_piece.
+    if (m_value_type == eValueTypeHostAddress)
+      if (uint64_t buffer_size = GetBuffer().GetByteSize())
+        return buffer_size;
+
     auto *scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
     if (llvm::Optional<uint64_t> size = GetCompilerType().GetByteSize(scope)) {
       if (error_ptr)
Index: lldb/packages/Python/lldbsuite/test/functionalities/dw_op_piece/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/functionalities/dw_op_piece/main.cpp
@@ -0,0 +1,62 @@
+// The point of this test is to exercise lldb's DW_OP_piece evaluation logic.
+// The CHECK lines in the test depend on aspects of the optimizer's behavior
+// that aren't guaranteed. If the test fails after a compiler change, run it in
+// trace mode (./bin/lldb-dotest -t ...): this should print out the new location
+// expressions.
+
+__attribute__((noinline, optnone)) int use(int x) { return x; }
+
+volatile int sink;
+
+struct S1 {
+  int f1;
+  int *f2;
+};
+
+struct S2 {
+  char a, b;
+  int pad;
+  S2(int x) {
+    a = x & 0xff;
+    b = x & 0xff00;
+  }
+};
+
+int main() {
+  S1 v1;
+  v1.f1 = sink;
+  v1.f2 = nullptr;
+
+  // 1) Check that "v1" is described by 3 pieces (one each for "f1" and "f2"
+  // (in registers), and a third for padding (a literal)).
+  //
+  //% self.filecheck("image lookup -va $pc", "main.cpp", "-check-prefix=INFO-V1")
+  // INFO-V1: name = "v1", type = "S1", location = DW_OP_reg0 RAX, DW_OP_piece 0x4, DW_OP_piece 0x4, DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x8, decl
+  sink++;
+
+  // 2) Check that lldb displays "v1" correctly.
+  //
+  //% self.filecheck("frame variable v1", "main.cpp", "-check-prefix=SHOW-V1")
+  // SHOW-V1:      (S1) v1 = {
+  // SHOW-V1-NEXT:   f1 = 0
+  // SHOW-V1-NEXT:   f2 = 0x{{0+$}}
+  // SHOW-V1-NEXT: }
+
+  S2 v2(v1.f1);
+
+  // 3) Check that "v2" is described by 2 pieces (one each for "a" and "b").
+  // Note that a piece for "pad" is left out: this is crucial, as it means that
+  // DWARFExpression::Evaluate() will produce a 2-byte Value. We want to test
+  // that lldb can handle the Value without smashing memory (this is a
+  // regression test for a bug found by ASan).
+  sink += use(v2.a);
+  //% self.filecheck("image lookup -va $pc", "main.cpp", "-check-prefix=INFO-V2")
+  // INFO-V2: name = "v2", type = "S2", location = DW_OP_piece 0x1, DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x1, decl
+
+  // 4) Check that lldb displays "v2" correctly.
+  sink += use(v2.pad);
+  //% self.filecheck("frame variable v2", "main.cpp", "-check-prefix=SHOW-V2")
+  // SHOW-V2: (S2) v2 = (a = '\0', b = '\0', pad = {{.*}})
+
+  return 0;
+}
Index: lldb/packages/Python/lldbsuite/test/functionalities/dw_op_piece/TestDW_OP_piece.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/functionalities/dw_op_piece/TestDW_OP_piece.py
@@ -0,0 +1,5 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(),
+        [decorators.skipUnlessArch('x86_64')])
Index: lldb/packages/Python/lldbsuite/test/functionalities/dw_op_piece/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/functionalities/dw_op_piece/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+CXXFLAGS_EXTRAS := -O2
+include Makefile.rules
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to