dvlahovski updated this revision to Diff 72659.
dvlahovski added a comment.

Addressing Zachary's and Adrian's comments


https://reviews.llvm.org/D24919

Files:
  source/Plugins/Process/minidump/CMakeLists.txt
  source/Plugins/Process/minidump/MinidumpParser.cpp
  source/Plugins/Process/minidump/MinidumpParser.h
  source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp
  source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.h
  unittests/Process/minidump/MinidumpParserTest.cpp

Index: unittests/Process/minidump/MinidumpParserTest.cpp
===================================================================
--- unittests/Process/minidump/MinidumpParserTest.cpp
+++ unittests/Process/minidump/MinidumpParserTest.cpp
@@ -8,16 +8,19 @@
 //===----------------------------------------------------------------------===//
 
 // Project includes
+#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
 #include "Plugins/Process/minidump/MinidumpParser.h"
 #include "Plugins/Process/minidump/MinidumpTypes.h"
+#include "Plugins/Process/minidump/RegisterContextMinidump_x86_64.h"
 
 // Other libraries and framework includes
 #include "gtest/gtest.h"
 
 #include "lldb/Core/ArchSpec.h"
 #include "lldb/Core/DataExtractor.h"
 #include "lldb/Host/FileSpec.h"
 
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
@@ -50,7 +53,7 @@
         MinidumpParser::Create(data_sp);
     ASSERT_TRUE(optional_parser.hasValue());
     parser.reset(new MinidumpParser(optional_parser.getValue()));
-    ASSERT_GT(parser->GetByteSize(), 0UL);
+    ASSERT_GT(parser->GetData().size(), 0UL);
   }
 
   llvm::SmallString<128> inputs_folder;
@@ -167,3 +170,61 @@
   ASSERT_TRUE(pid.hasValue());
   ASSERT_EQ(4440UL, pid.getValue());
 }
+
+// Register stuff
+// TODO probably split register stuff tests into different file?
+#define REG_VAL(x) *(reinterpret_cast<uint64_t *>(x))
+
+TEST_F(MinidumpParserTest, ConvertRegisterContext) {
+  SetUpData("linux-x86_64.dmp");
+  llvm::ArrayRef<MinidumpThread> thread_list = parser->GetThreads();
+  const MinidumpThread thread = thread_list[0];
+  llvm::ArrayRef<uint8_t> registers(parser->GetData().data() +
+                                        thread.thread_context.rva,
+                                    thread.thread_context.data_size);
+
+  ArchSpec arch = parser->GetArchitecture();
+  RegisterInfoInterface *reg_interface = new RegisterContextLinux_x86_64(arch);
+  lldb::DataBufferSP buf =
+      ConvertMinidumpContextToRegIface(registers, reg_interface);
+  ASSERT_EQ(reg_interface->GetGPRSize(), buf->GetByteSize());
+
+  const RegisterInfo *reg_info = reg_interface->GetRegisterInfo();
+
+  std::map<uint64_t, uint64_t> reg_values;
+
+  // clang-format off
+  reg_values[lldb_rax_x86_64]    =  0x0000000000000000;
+  reg_values[lldb_rbx_x86_64]    =  0x0000000000000000;
+  reg_values[lldb_rcx_x86_64]    =  0x0000000000000010;
+  reg_values[lldb_rdx_x86_64]    =  0x0000000000000000;
+  reg_values[lldb_rdi_x86_64]    =  0x00007ffceb349cf0;
+  reg_values[lldb_rsi_x86_64]    =  0x0000000000000000;
+  reg_values[lldb_rbp_x86_64]    =  0x00007ffceb34a210;
+  reg_values[lldb_rsp_x86_64]    =  0x00007ffceb34a210;
+  reg_values[lldb_r8_x86_64]     =  0x00007fe9bc1aa9c0;
+  reg_values[lldb_r9_x86_64]     =  0x0000000000000000;
+  reg_values[lldb_r10_x86_64]    =  0x00007fe9bc3f16a0;
+  reg_values[lldb_r11_x86_64]    =  0x0000000000000246;
+  reg_values[lldb_r12_x86_64]    =  0x0000000000401c92;
+  reg_values[lldb_r13_x86_64]    =  0x00007ffceb34a430;
+  reg_values[lldb_r14_x86_64]    =  0x0000000000000000;
+  reg_values[lldb_r15_x86_64]    =  0x0000000000000000;
+  reg_values[lldb_rip_x86_64]    =  0x0000000000401dc6;
+  reg_values[lldb_rflags_x86_64] =  0x0000000000010206;
+  reg_values[lldb_cs_x86_64]     =  0x0000000000000033;
+  reg_values[lldb_fs_x86_64]     =  0x0000000000000000;
+  reg_values[lldb_gs_x86_64]     =  0x0000000000000000;
+  reg_values[lldb_ss_x86_64]     =  0x0000000000000000;
+  reg_values[lldb_ds_x86_64]     =  0x0000000000000000;
+  reg_values[lldb_es_x86_64]     =  0x0000000000000000;
+  // clang-format on
+
+  for (uint32_t reg_index = 0; reg_index < reg_interface->GetRegisterCount();
+       ++reg_index) {
+    if (reg_values.find(reg_index) != reg_values.end()) {
+      EXPECT_EQ(reg_values[reg_index],
+                REG_VAL(buf->GetBytes() + reg_info[reg_index].byte_offset));
+    }
+  }
+}
Index: source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.h
===================================================================
--- /dev/null
+++ source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.h
@@ -0,0 +1,119 @@
+//===-- RegisterContextMinidump_x86_64.h ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextMinidump_h_
+#define liblldb_RegisterContextMinidump_h_
+
+// Project includes
+#include "MinidumpTypes.h"
+
+// Other libraries and framework includes
+#include "Plugins/Process/Utility/RegisterInfoInterface.h"
+#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
+
+#include "lldb/Target/RegisterContext.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitmaskEnum.h"
+
+// C includes
+// C++ includes
+
+namespace lldb_private {
+
+namespace minidump {
+
+// The content of the Minidump register context is as follows:
+// (for reference see breakpad's source or WinNT.h)
+// Register parameter home addresses: (p1_home .. p6_home)
+// - uint64_t p1_home
+// - uint64_t p2_home
+// - uint64_t p3_home
+// - uint64_t p4_home
+// - uint64_t p5_home
+// - uint64_t p6_home
+//
+// - uint32_t context_flags - field that determines the layout of the structure
+//     and which parts of it are populated
+// - uint32_t mx_csr
+//
+// - uint16_t cs - included if MinidumpContext_x86_64_Flags::Control
+//
+// - uint16_t ds - included if MinidumpContext_x86_64_Flags::Segments
+// - uint16_t es - included if MinidumpContext_x86_64_Flags::Segments
+// - uint16_t fs - included if MinidumpContext_x86_64_Flags::Segments
+// - uint16_t gs - included if MinidumpContext_x86_64_Flags::Segments
+//
+// - uint16_t ss     - included if MinidumpContext_x86_64_Flags::Control
+// - uint32_t rflags - included if MinidumpContext_x86_64_Flags::Control
+//
+// Debug registers: (included if MinidumpContext_x86_64_Flags::DebugRegisters)
+// - uint64_t dr0
+// - uint64_t dr1
+// - uint64_t dr2
+// - uint64_t dr3
+// - uint64_t dr6
+// - uint64_t dr7
+//
+// The next 4 registers are included if MinidumpContext_x86_64_Flags::Integer
+// - uint64_t rax
+// - uint64_t rcx
+// - uint64_t rdx
+// - uint64_t rbx
+//
+// - uint64_t rsp - included if MinidumpContext_x86_64_Flags::Control
+//
+// The next 11 registers are included if MinidumpContext_x86_64_Flags::Integer
+// - uint64_t rbp
+// - uint64_t rsi
+// - uint64_t rdi
+// - uint64_t r8
+// - uint64_t r9
+// - uint64_t r10
+// - uint64_t r11
+// - uint64_t r12
+// - uint64_t r13
+// - uint64_t r14
+// - uint64_t r15
+//
+// - uint64_t rip - included if MinidumpContext_x86_64_Flags::Control
+//
+// TODO: add floating point registers here
+
+// This function receives an ArrayRef pointing to the bytes of the Minidump
+// register context and returns a DataBuffer that's ordered by the offsets
+// specified in the RegisterInfoInterface argument
+// This way we can reuse the already existing register contexts
+lldb::DataBufferSP
+ConvertMinidumpContextToRegIface(llvm::ArrayRef<uint8_t> source_data,
+                                 RegisterInfoInterface *target_reg_interface);
+
+// For context_flags. These values indicate the type of
+// context stored in the structure.  The high 24 bits identify the CPU, the
+// low 8 bits identify the type of context saved.
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+
+enum class MinidumpContext_x86_64_Flags : uint32_t {
+  x86_64_Flag = 0x00100000,
+  Control = x86_64_Flag | 0x00000001,
+  Integer = x86_64_Flag | 0x00000002,
+  Segments = x86_64_Flag | 0x00000004,
+  FloatingPoint = x86_64_Flag | 0x00000008,
+  DebugRegisters = x86_64_Flag | 0x00000010,
+  XState = x86_64_Flag | 0x00000040,
+
+  Full = Control | Integer | FloatingPoint,
+  All = Full | Segments | DebugRegisters,
+
+  LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ All)
+};
+
+} // end namespace minidump
+} // end namespace lldb_private
+#endif // liblldb_RegisterContextMinidump_h_
Index: source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp
===================================================================
--- /dev/null
+++ source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp
@@ -0,0 +1,163 @@
+//===-- RegisterContextMinidump_x86_64.cpp ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Project includes
+#include "RegisterContextMinidump_x86_64.h"
+
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+
+// C includes
+// C++ includes
+
+using namespace lldb_private;
+using namespace minidump;
+
+// void writeRegister(llvm::ArrayRef<uint8_t> &source_data, uint8_t *base,
+//                    const RegisterInfo *reg_info, size_t size) {
+
+void writeRegister(llvm::ArrayRef<uint8_t> &reg_src,
+                   llvm::MutableArrayRef<uint8_t> reg_dest,
+                   const RegisterInfo &reg_info) {
+  memcpy(reg_dest.data() + reg_info.byte_offset, reg_src.data(),
+         reg_dest.size());
+  reg_src = reg_src.drop_front(reg_dest.size());
+}
+
+llvm::MutableArrayRef<uint8_t> getDestRegister(uint8_t *reg_data_base,
+                                               uint32_t lldb_reg_num) {
+  size_t size;
+  switch (lldb_reg_num) {
+  case lldb_cs_x86_64:
+  case lldb_ds_x86_64:
+  case lldb_es_x86_64:
+  case lldb_fs_x86_64:
+  case lldb_gs_x86_64:
+  case lldb_ss_x86_64:
+    size = 2;
+    break;
+  case lldb_rflags_x86_64:
+    size = 4;
+    break;
+  default:
+    size = 8;
+    break;
+  }
+
+  return llvm::MutableArrayRef<uint8_t>(reg_data_base, size);
+}
+
+lldb::DataBufferSP lldb_private::minidump::ConvertMinidumpContextToRegIface(
+    llvm::ArrayRef<uint8_t> source_data,
+    RegisterInfoInterface *target_reg_interface) {
+
+  const RegisterInfo *reg_info = target_reg_interface->GetRegisterInfo();
+
+  lldb::DataBufferSP result_context_buf(
+      new DataBufferHeap(target_reg_interface->GetGPRSize(), 0));
+  uint8_t *result_base = result_context_buf->GetBytes();
+
+  source_data = source_data.drop_front(6 * 8); // p[1-6] home registers
+  const uint32_t *context_flags;
+  consumeObject(source_data, context_flags);
+  const uint32_t x86_64_Flag =
+      static_cast<uint32_t>(MinidumpContext_x86_64_Flags::x86_64_Flag);
+  const uint32_t ControlFlag =
+      static_cast<uint32_t>(MinidumpContext_x86_64_Flags::Control);
+  const uint32_t IntegerFlag =
+      static_cast<uint32_t>(MinidumpContext_x86_64_Flags::Integer);
+  const uint32_t SegmentsFlag =
+      static_cast<uint32_t>(MinidumpContext_x86_64_Flags::Segments);
+  const uint32_t DebugRegistersFlag =
+      static_cast<uint32_t>(MinidumpContext_x86_64_Flags::DebugRegisters);
+
+  if (!(*context_flags & x86_64_Flag)) {
+    return result_context_buf; // error
+  }
+
+  source_data = source_data.drop_front(4); // mx_csr
+
+  if (*context_flags & ControlFlag) {
+    writeRegister(source_data, getDestRegister(result_base, lldb_cs_x86_64),
+                  reg_info[lldb_cs_x86_64]);
+  }
+
+  if (*context_flags & SegmentsFlag) {
+    writeRegister(source_data, getDestRegister(result_base, lldb_ds_x86_64),
+                  reg_info[lldb_ds_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_es_x86_64),
+                  reg_info[lldb_es_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_fs_x86_64),
+                  reg_info[lldb_fs_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_gs_x86_64),
+                  reg_info[lldb_gs_x86_64]);
+  }
+
+  if (*context_flags & ControlFlag) {
+    writeRegister(source_data, getDestRegister(result_base, lldb_ss_x86_64),
+                  reg_info[lldb_ss_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_rflags_x86_64),
+                  reg_info[lldb_rflags_x86_64]);
+  }
+
+  if (*context_flags & DebugRegistersFlag) {
+    source_data =
+        source_data.drop_front(6 * 8); // 6 debug registers 64 bit each
+  }
+
+  if (*context_flags & IntegerFlag) {
+    writeRegister(source_data, getDestRegister(result_base, lldb_rax_x86_64),
+                  reg_info[lldb_rax_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_rcx_x86_64),
+                  reg_info[lldb_rcx_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_rdx_x86_64),
+                  reg_info[lldb_rdx_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_rbx_x86_64),
+                  reg_info[lldb_rbx_x86_64]);
+  }
+
+  if (*context_flags & ControlFlag) {
+    writeRegister(source_data, getDestRegister(result_base, lldb_rsp_x86_64),
+                  reg_info[lldb_rsp_x86_64]);
+  }
+
+  if (*context_flags & IntegerFlag) {
+    writeRegister(source_data, getDestRegister(result_base, lldb_rbp_x86_64),
+                  reg_info[lldb_rbp_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_rsi_x86_64),
+                  reg_info[lldb_rsi_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_rdi_x86_64),
+                  reg_info[lldb_rdi_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_r8_x86_64),
+                  reg_info[lldb_r8_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_r9_x86_64),
+                  reg_info[lldb_r9_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_r10_x86_64),
+                  reg_info[lldb_r10_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_r11_x86_64),
+                  reg_info[lldb_r11_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_r12_x86_64),
+                  reg_info[lldb_r12_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_r13_x86_64),
+                  reg_info[lldb_r13_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_r14_x86_64),
+                  reg_info[lldb_r14_x86_64]);
+    writeRegister(source_data, getDestRegister(result_base, lldb_r15_x86_64),
+                  reg_info[lldb_r15_x86_64]);
+  }
+
+  if (*context_flags & ControlFlag) {
+    writeRegister(source_data, getDestRegister(result_base, lldb_rip_x86_64),
+                  reg_info[lldb_rip_x86_64]);
+  }
+
+  // TODO parse the floating point registers
+
+  return result_context_buf;
+}
Index: source/Plugins/Process/minidump/MinidumpParser.h
===================================================================
--- source/Plugins/Process/minidump/MinidumpParser.h
+++ source/Plugins/Process/minidump/MinidumpParser.h
@@ -39,7 +39,7 @@
   static llvm::Optional<MinidumpParser>
   Create(const lldb::DataBufferSP &data_buf_sp);
 
-  lldb::offset_t GetByteSize();
+  llvm::ArrayRef<uint8_t> GetData();
 
   llvm::ArrayRef<uint8_t> GetStream(MinidumpStreamType stream_type);
 
@@ -71,6 +71,6 @@
       llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &&directory_map);
 };
 
-} // namespace minidump
-} // namespace lldb_private
+} // end namespace minidump
+} // end namespace lldb_private
 #endif // liblldb_MinidumpParser_h_
Index: source/Plugins/Process/minidump/MinidumpParser.cpp
===================================================================
--- source/Plugins/Process/minidump/MinidumpParser.cpp
+++ source/Plugins/Process/minidump/MinidumpParser.cpp
@@ -64,8 +64,9 @@
     : m_data_sp(data_buf_sp), m_header(header), m_directory_map(directory_map) {
 }
 
-lldb::offset_t MinidumpParser::GetByteSize() {
-  return m_data_sp->GetByteSize();
+llvm::ArrayRef<uint8_t> MinidumpParser::GetData() {
+  return llvm::ArrayRef<uint8_t>(m_data_sp->GetBytes(),
+                                 m_data_sp->GetByteSize());
 }
 
 llvm::ArrayRef<uint8_t>
Index: source/Plugins/Process/minidump/CMakeLists.txt
===================================================================
--- source/Plugins/Process/minidump/CMakeLists.txt
+++ source/Plugins/Process/minidump/CMakeLists.txt
@@ -3,4 +3,5 @@
 add_lldb_library(lldbPluginProcessMinidump
   MinidumpTypes.cpp
   MinidumpParser.cpp
+  RegisterContextMinidump_x86_64.cpp
   )
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to