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

Forgot to run clang-format. Also changed a helper function in the tests to make 
it simpler.


https://reviews.llvm.org/D25569

Files:
  source/Plugins/Process/minidump/MinidumpParser.cpp
  source/Plugins/Process/minidump/MinidumpParser.h
  source/Plugins/Process/minidump/MinidumpTypes.cpp
  source/Plugins/Process/minidump/MinidumpTypes.h
  unittests/Process/minidump/CMakeLists.txt
  unittests/Process/minidump/Inputs/fizzbuzz_wow64.dmp
  unittests/Process/minidump/Inputs/linux-x86_64_not_crashed.dmp
  unittests/Process/minidump/MinidumpParserTest.cpp

Index: unittests/Process/minidump/MinidumpParserTest.cpp
===================================================================
--- unittests/Process/minidump/MinidumpParserTest.cpp
+++ unittests/Process/minidump/MinidumpParserTest.cpp
@@ -19,6 +19,7 @@
 #include "lldb/Core/ArchSpec.h"
 #include "lldb/Core/DataExtractor.h"
 #include "lldb/Host/FileSpec.h"
+#include "lldb/Target/MemoryRegionInfo.h"
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Optional.h"
@@ -68,7 +69,11 @@
   ASSERT_EQ(1UL, thread_list.size());
 
   const MinidumpThread thread = thread_list[0];
-  ASSERT_EQ(16001UL, thread.thread_id);
+
+  EXPECT_EQ(16001UL, thread.thread_id);
+
+  llvm::ArrayRef<uint8_t> context = parser->GetThreadContext(thread);
+  EXPECT_EQ(1232UL, context.size());
 }
 
 TEST_F(MinidumpParserTest, GetThreadsTruncatedFile) {
@@ -131,14 +136,98 @@
   }
 }
 
+TEST_F(MinidumpParserTest, FilterModuleList) {
+  SetUpData("linux-x86_64_not_crashed.dmp");
+  llvm::ArrayRef<MinidumpModule> modules = parser->GetModuleList();
+  std::vector<const MinidumpModule *> filtered_modules =
+      parser->FilterModuleList(modules);
+  EXPECT_GT(modules.size(), filtered_modules.size());
+  bool found = false;
+  for (size_t i = 0; i < filtered_modules.size(); ++i) {
+    llvm::Optional<std::string> name =
+        parser->GetMinidumpString(filtered_modules[i]->module_name_rva);
+    ASSERT_TRUE(name.hasValue());
+    if (name.getValue() == "/tmp/test/linux-x86_64_not_crashed") {
+      ASSERT_FALSE(found) << "There should be only one module with this name "
+                             "in the filtered module list";
+      found = true;
+      ASSERT_EQ(0x400000UL, filtered_modules[i]->base_of_image);
+    }
+  }
+}
+
 TEST_F(MinidumpParserTest, GetExceptionStream) {
   SetUpData("linux-x86_64.dmp");
   const MinidumpExceptionStream *exception_stream =
       parser->GetExceptionStream();
   ASSERT_NE(nullptr, exception_stream);
   ASSERT_EQ(11UL, exception_stream->exception_record.exception_code);
 }
 
+void check_mem_range_exists(std::unique_ptr<MinidumpParser> &parser,
+                            const uint64_t range_start,
+                            const uint64_t range_size) {
+  llvm::Optional<minidump::Range> range = parser->FindMemoryRange(range_start);
+  ASSERT_TRUE(range.hasValue()) << "There is no range containing this address";
+  EXPECT_EQ(range_start, range->start);
+  EXPECT_EQ(range_start + range_size, range->start + range->range_ref.size());
+}
+
+TEST_F(MinidumpParserTest, GetMemoryRange) {
+  SetUpData("linux-x86_64.dmp");
+  // There are two memory ranges in the file (size is in bytes, decimal):
+  // 1) 0x401d46 256
+  // 2) 0x7ffceb34a000 12288
+  EXPECT_FALSE(parser->FindMemoryRange(0x00).hasValue());
+  EXPECT_FALSE(parser->FindMemoryRange(0x2a).hasValue());
+
+  check_mem_range_exists(parser, 0x401d46, 256);
+  EXPECT_FALSE(parser->FindMemoryRange(0x401d46 + 256).hasValue());
+
+  check_mem_range_exists(parser, 0x7ffceb34a000, 12288);
+  EXPECT_FALSE(parser->FindMemoryRange(0x7ffceb34a000 + 12288).hasValue());
+}
+
+TEST_F(MinidumpParserTest, GetMemoryRangeWithFullMemoryMinidump) {
+  SetUpData("fizzbuzz_wow64.dmp");
+
+  // There are a lot of ranges in the file, just testing with some of them
+  EXPECT_FALSE(parser->FindMemoryRange(0x00).hasValue());
+  EXPECT_FALSE(parser->FindMemoryRange(0x2a).hasValue());
+  check_mem_range_exists(parser, 0x10000, 65536); // first range
+  check_mem_range_exists(parser, 0x40000, 4096);
+  EXPECT_FALSE(parser->FindMemoryRange(0x40000 + 4096).hasValue());
+  check_mem_range_exists(parser, 0x77c12000, 8192);
+  check_mem_range_exists(parser, 0x7ffe0000, 4096); // last range
+  EXPECT_FALSE(parser->FindMemoryRange(0x7ffe0000 + 4096).hasValue());
+}
+
+void check_region_info(std::unique_ptr<MinidumpParser> &parser,
+                       const uint64_t addr, MemoryRegionInfo::OptionalBool read,
+                       MemoryRegionInfo::OptionalBool write,
+                       MemoryRegionInfo::OptionalBool exec) {
+  lldb_private::MemoryRegionInfo range_info;
+  Error error = parser->GetMemoryRegionInfo(addr, range_info);
+  ASSERT_TRUE(error.Success());
+  EXPECT_EQ(read, range_info.GetReadable());
+  EXPECT_EQ(write, range_info.GetWritable());
+  EXPECT_EQ(exec, range_info.GetExecutable());
+}
+
+TEST_F(MinidumpParserTest, GetMemoryRegionInfo) {
+  SetUpData("fizzbuzz_wow64.dmp");
+
+  const auto yes = MemoryRegionInfo::eYes;
+  const auto no = MemoryRegionInfo::eNo;
+
+  check_region_info(parser, 0x00000, no, no, no);
+  check_region_info(parser, 0x10000, yes, yes, no);
+  check_region_info(parser, 0x20000, yes, yes, no);
+  check_region_info(parser, 0x30000, yes, yes, no);
+  check_region_info(parser, 0x31000, no, no, no);
+  check_region_info(parser, 0x40000, yes, no, no);
+}
+
 // Windows Minidump tests
 // fizzbuzz_no_heap.dmp is copied from the WinMiniDump tests
 TEST_F(MinidumpParserTest, GetArchitectureWindows) {
Index: unittests/Process/minidump/CMakeLists.txt
===================================================================
--- unittests/Process/minidump/CMakeLists.txt
+++ unittests/Process/minidump/CMakeLists.txt
@@ -4,6 +4,8 @@
 
 set(test_inputs
    linux-x86_64.dmp
-   fizzbuzz_no_heap.dmp)
+   linux-x86_64_not_crashed.dmp
+   fizzbuzz_no_heap.dmp
+   fizzbuzz_wow64.dmp)
 
 add_unittest_inputs(LLDBMinidumpTests "${test_inputs}")
Index: source/Plugins/Process/minidump/MinidumpTypes.h
===================================================================
--- source/Plugins/Process/minidump/MinidumpTypes.h
+++ source/Plugins/Process/minidump/MinidumpTypes.h
@@ -207,10 +207,23 @@
 struct MinidumpMemoryDescriptor {
   llvm::support::ulittle64_t start_of_memory_range;
   MinidumpLocationDescriptor memory;
+
+  static llvm::ArrayRef<MinidumpMemoryDescriptor>
+  ParseMemoryList(llvm::ArrayRef<uint8_t> &data);
 };
 static_assert(sizeof(MinidumpMemoryDescriptor) == 16,
               "sizeof MinidumpMemoryDescriptor is not correct!");
 
+struct MinidumpMemoryDescriptor64 {
+  llvm::support::ulittle64_t start_of_memory_range;
+  llvm::support::ulittle64_t data_size;
+
+  static std::pair<llvm::ArrayRef<MinidumpMemoryDescriptor64>, uint64_t>
+  ParseMemory64List(llvm::ArrayRef<uint8_t> &data);
+};
+static_assert(sizeof(MinidumpMemoryDescriptor64) == 16,
+              "sizeof MinidumpMemoryDescriptor64 is not correct!");
+
 // Reference:
 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680365.aspx
 struct MinidumpDirectory {
@@ -221,6 +234,67 @@
               "sizeof MinidumpDirectory is not correct!");
 
 // Reference:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680385(v=vs.85).aspx
+struct MinidumpMemoryInfoListHeader {
+  llvm::support::ulittle32_t size_of_header;
+  llvm::support::ulittle32_t size_of_entry;
+  llvm::support::ulittle64_t num_of_entries;
+};
+static_assert(sizeof(MinidumpMemoryInfoListHeader) == 16,
+              "sizeof MinidumpMemoryInfoListHeader is not correct!");
+
+// Reference:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680386(v=vs.85).aspx
+struct MinidumpMemoryInfo {
+  llvm::support::ulittle64_t base_address;
+  llvm::support::ulittle64_t allocation_base;
+  llvm::support::ulittle32_t allocation_protect;
+  llvm::support::ulittle32_t alignment1;
+  llvm::support::ulittle64_t region_size;
+  llvm::support::ulittle32_t state;
+  llvm::support::ulittle32_t protect;
+  llvm::support::ulittle32_t type;
+  llvm::support::ulittle32_t alignment2;
+
+  static std::vector<const MinidumpMemoryInfo *>
+  ParseMemoryInfoList(llvm::ArrayRef<uint8_t> &data);
+};
+static_assert(sizeof(MinidumpMemoryInfo) == 48,
+              "sizeof MinidumpMemoryInfo is not correct!");
+
+enum class MinidumpMemoryInfoState : uint32_t {
+  MemCommit = 0x1000,
+  MemFree = 0x10000,
+  MemReserve = 0x2000,
+};
+
+enum class MinidumpMemoryInfoType : uint32_t {
+  MemImage = 0x1000000,
+  MemMapped = 0x40000,
+  MemPrivate = 0x20000,
+};
+
+// Reference:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366786(v=vs.85).aspx
+enum class MinidumpMemoryProtectionContants : uint32_t {
+  PageExecute = 0x10,
+  PageExecuteRead = 0x20,
+  PageExecuteReadWrite = 0x40,
+  PageExecuteWriteCopy = 0x80,
+  PageNoAccess = 0x01,
+  PageReadOnly = 0x02,
+  PageReadWrite = 0x04,
+  PageWriteCopy = 0x08,
+  PageTargetsInvalid = 0x40000000,
+  PageTargetsNoUpdate = 0x40000000,
+
+  PageWritable = PageExecuteReadWrite | PageExecuteWriteCopy | PageReadWrite |
+                 PageWriteCopy,
+  PageExecutable = PageExecute | PageExecuteRead | PageExecuteReadWrite |
+                   PageExecuteWriteCopy,
+};
+
+// Reference:
 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680517(v=vs.85).aspx
 struct MinidumpThread {
   llvm::support::ulittle32_t thread_id;
Index: source/Plugins/Process/minidump/MinidumpTypes.cpp
===================================================================
--- source/Plugins/Process/minidump/MinidumpTypes.cpp
+++ source/Plugins/Process/minidump/MinidumpTypes.cpp
@@ -176,3 +176,62 @@
 
   return exception_stream;
 }
+
+llvm::ArrayRef<MinidumpMemoryDescriptor>
+MinidumpMemoryDescriptor::ParseMemoryList(llvm::ArrayRef<uint8_t> &data) {
+  const llvm::support::ulittle32_t *mem_ranges_count;
+  Error error = consumeObject(data, mem_ranges_count);
+  if (error.Fail() ||
+      *mem_ranges_count * sizeof(MinidumpMemoryDescriptor) > data.size())
+    return {};
+
+  return llvm::makeArrayRef(
+      reinterpret_cast<const MinidumpMemoryDescriptor *>(data.data()),
+      *mem_ranges_count);
+}
+
+std::pair<llvm::ArrayRef<MinidumpMemoryDescriptor64>, uint64_t>
+MinidumpMemoryDescriptor64::ParseMemory64List(llvm::ArrayRef<uint8_t> &data) {
+  const llvm::support::ulittle64_t *mem_ranges_count;
+  Error error = consumeObject(data, mem_ranges_count);
+  if (error.Fail() ||
+      *mem_ranges_count * sizeof(MinidumpMemoryDescriptor64) > data.size())
+    return {};
+
+  const llvm::support::ulittle64_t *base_rva;
+  error = consumeObject(data, base_rva);
+  if (error.Fail())
+    return {};
+
+  return std::make_pair(
+      llvm::makeArrayRef(
+          reinterpret_cast<const MinidumpMemoryDescriptor64 *>(data.data()),
+          *mem_ranges_count),
+      *base_rva);
+}
+
+std::vector<const MinidumpMemoryInfo *>
+MinidumpMemoryInfo::ParseMemoryInfoList(llvm::ArrayRef<uint8_t> &data) {
+  const MinidumpMemoryInfoListHeader *header;
+  Error error = consumeObject(data, header);
+  if (error.Fail() ||
+      header->size_of_header < sizeof(MinidumpMemoryInfoListHeader) ||
+      header->size_of_entry < sizeof(MinidumpMemoryInfo))
+    return {};
+
+  if (header->size_of_header > sizeof(MinidumpMemoryInfoListHeader)) {
+    data = data.drop_front(header->size_of_header -
+                           sizeof(MinidumpMemoryInfoListHeader));
+  }
+
+  if (header->size_of_entry * header->num_of_entries > data.size())
+    return {};
+
+  std::vector<const MinidumpMemoryInfo *> result;
+  for (uint64_t i = 0; i < header->num_of_entries; ++i) {
+    result.push_back(reinterpret_cast<const MinidumpMemoryInfo *>(
+        data.data() + i * header->size_of_entry));
+  }
+
+  return result;
+}
Index: source/Plugins/Process/minidump/MinidumpParser.h
===================================================================
--- source/Plugins/Process/minidump/MinidumpParser.h
+++ source/Plugins/Process/minidump/MinidumpParser.h
@@ -34,6 +34,16 @@
 
 namespace minidump {
 
+// Describes a range of memory captured in the Minidump
+struct Range {
+  lldb::addr_t start; // virtual address of the beginning of the range
+  // range_ref - absolute pointer to the first byte of the range and size
+  llvm::ArrayRef<uint8_t> range_ref;
+
+  Range(lldb::addr_t start, llvm::ArrayRef<uint8_t> range_ref)
+      : start(start), range_ref(range_ref) {}
+};
+
 class MinidumpParser {
 public:
   static llvm::Optional<MinidumpParser>
@@ -47,6 +57,8 @@
 
   llvm::ArrayRef<MinidumpThread> GetThreads();
 
+  llvm::ArrayRef<uint8_t> GetThreadContext(const MinidumpThread &td);
+
   const MinidumpSystemInfo *GetSystemInfo();
 
   ArchSpec GetArchitecture();
@@ -59,8 +71,22 @@
 
   llvm::ArrayRef<MinidumpModule> GetModuleList();
 
+  // There are cases in which there is more than one record in the ModuleList
+  // for the same module name.(e.g. when the binary has non contiguous segments)
+  // So this function filters the module list - if it finds records that have
+  // the same name, it keeps the copy with the lowest load address.
+  std::vector<const MinidumpModule *>
+  FilterModuleList(llvm::ArrayRef<MinidumpModule> &modules);
+
   const MinidumpExceptionStream *GetExceptionStream();
 
+  llvm::Optional<Range> FindMemoryRange(lldb::addr_t addr);
+
+  size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error);
+
+  Error GetMemoryRegionInfo(lldb::addr_t load_addr,
+                            lldb_private::MemoryRegionInfo &info);
+
 private:
   lldb::DataBufferSP m_data_sp;
   const MinidumpHeader *m_header;
Index: source/Plugins/Process/minidump/MinidumpParser.cpp
===================================================================
--- source/Plugins/Process/minidump/MinidumpParser.cpp
+++ source/Plugins/Process/minidump/MinidumpParser.cpp
@@ -11,8 +11,12 @@
 #include "MinidumpParser.h"
 
 // Other libraries and framework includes
+#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Utility/LLDBAssert.h"
+
 // C includes
 // C++ includes
+#include <map>
 
 using namespace lldb_private;
 using namespace minidump;
@@ -100,6 +104,14 @@
   return MinidumpThread::ParseThreadList(data);
 }
 
+llvm::ArrayRef<uint8_t>
+MinidumpParser::GetThreadContext(const MinidumpThread &td) {
+  if (td.thread_context.rva + td.thread_context.data_size > GetData().size())
+    return llvm::None;
+
+  return GetData().slice(td.thread_context.rva, td.thread_context.data_size);
+}
+
 const MinidumpSystemInfo *MinidumpParser::GetSystemInfo() {
   llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::SystemInfo);
 
@@ -216,11 +228,206 @@
   return MinidumpModule::ParseModuleList(data);
 }
 
+std::vector<const MinidumpModule *>
+MinidumpParser::FilterModuleList(llvm::ArrayRef<MinidumpModule> &modules) {
+  std::map<std::string, std::pair<uint64_t, const MinidumpModule *>>
+      lowest_addr;
+  std::vector<const MinidumpModule *> filtered_modules;
+
+  llvm::Optional<std::string> name;
+  std::string module_name;
+
+  for (size_t i = 0; i < modules.size(); ++i) {
+    name = GetMinidumpString(modules[i].module_name_rva);
+
+    if (!name)
+      continue;
+
+    module_name = name.getValue();
+
+    if (lowest_addr.find(module_name) == lowest_addr.end()) {
+      lowest_addr[module_name] =
+          std::make_pair(modules[i].base_of_image, &modules[i]);
+    } else if (modules[i].base_of_image < lowest_addr[module_name].first) {
+      lowest_addr[module_name].second = &modules[i];
+    }
+  }
+
+  for (auto module : lowest_addr) {
+    filtered_modules.push_back(module.second.second);
+  }
+
+  return filtered_modules;
+}
+
 const MinidumpExceptionStream *MinidumpParser::GetExceptionStream() {
   llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::Exception);
 
   if (data.size() == 0)
     return nullptr;
 
   return MinidumpExceptionStream::Parse(data);
 }
+
+llvm::Optional<minidump::Range>
+MinidumpParser::FindMemoryRange(lldb::addr_t addr) {
+  llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::MemoryList);
+  llvm::ArrayRef<uint8_t> data64 = GetStream(MinidumpStreamType::Memory64List);
+
+  if (data.size() == 0 && data64.size() == 0)
+    return llvm::None;
+
+  if (data.size() > 0) {
+    llvm::ArrayRef<MinidumpMemoryDescriptor> memory_list =
+        MinidumpMemoryDescriptor::ParseMemoryList(data);
+
+    if (memory_list.size() == 0)
+      return llvm::None;
+
+    for (auto memory_desc : memory_list) {
+      const MinidumpLocationDescriptor &loc_desc = memory_desc.memory;
+      const lldb::addr_t range_start = memory_desc.start_of_memory_range;
+      const size_t range_size = loc_desc.data_size;
+
+      if (loc_desc.rva + loc_desc.data_size > GetData().size())
+        return llvm::None;
+
+      if (range_start <= addr && addr < range_start + range_size) {
+        return minidump::Range(range_start,
+                               GetData().slice(loc_desc.rva, range_size));
+      }
+    }
+  }
+
+  // Some Minidumps have a Memory64ListStream that captures all the heap
+  // memory (full-memory Minidumps).  We can't exactly use the same loop as
+  // above, because the Minidump uses slightly different data structures to
+  // describe those
+
+  if (data64.size() > 0) {
+    llvm::ArrayRef<MinidumpMemoryDescriptor64> memory64_list;
+    uint64_t base_rva;
+    std::tie(memory64_list, base_rva) =
+        MinidumpMemoryDescriptor64::ParseMemory64List(data64);
+
+    if (memory64_list.size() == 0)
+      return llvm::None;
+
+    for (auto memory_desc64 : memory64_list) {
+      const lldb::addr_t range_start = memory_desc64.start_of_memory_range;
+      const size_t range_size = memory_desc64.data_size;
+
+      if (base_rva + range_size > GetData().size())
+        return llvm::None;
+
+      if (range_start <= addr && addr < range_start + range_size) {
+        return minidump::Range(range_start,
+                               GetData().slice(base_rva, range_size));
+      }
+      base_rva += range_size;
+    }
+  }
+
+  return llvm::None;
+}
+
+size_t MinidumpParser::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+                                    Error &error) {
+  // I don't have a sense of how frequently this is called or how many memory
+  // ranges a Minidump typically has, so I'm not sure if searching for the
+  // appropriate range linearly each time is stupid.  Perhaps we should build
+  // an index for faster lookups.
+  llvm::Optional<minidump::Range> range = FindMemoryRange(addr);
+  if (!range)
+    return 0;
+
+  // There's at least some overlap between the beginning of the desired range
+  // (addr) and the current range.  Figure out where the overlap begins and
+  // how much overlap there is, then copy it to the destination buffer.
+  lldbassert(range->start <= addr);
+  const size_t offset = addr - range->start;
+  lldbassert(offset < range->range_ref.size());
+  const size_t overlap = std::min(size, range->range_ref.size() - offset);
+  std::memcpy(buf, range->range_ref.data() + offset, overlap);
+  return overlap;
+}
+
+Error MinidumpParser::GetMemoryRegionInfo(
+    lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info) {
+
+  Error error;
+  llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::MemoryInfoList);
+  if (data.size() == 0) {
+    error.SetErrorString("Minidump doesn't have MemoryInfoList");
+    return error;
+  }
+
+  std::vector<const MinidumpMemoryInfo *> mem_info_list =
+      MinidumpMemoryInfo::ParseMemoryInfoList(data);
+  if (mem_info_list.size() == 0) {
+    error.SetErrorString("error while parsing the MinidumpMemoryInfoList");
+    return error;
+  }
+
+  const MinidumpMemoryInfo *next_entry = nullptr;
+  for (auto entry : mem_info_list) {
+    const auto head = entry->base_address;
+    const auto tail = head + entry->region_size;
+
+    if (head <= load_addr && load_addr < tail) {
+      info.GetRange().SetRangeBase(
+          (entry->state != uint32_t(MinidumpMemoryInfoState::MemFree))
+              ? head
+              : load_addr);
+      info.GetRange().SetRangeEnd(tail);
+
+      const uint32_t PageNoAccess =
+          static_cast<uint32_t>(MinidumpMemoryProtectionContants::PageNoAccess);
+      info.SetReadable((entry->protect & PageNoAccess) == 0
+                           ? MemoryRegionInfo::eYes
+                           : MemoryRegionInfo::eNo);
+
+      const uint32_t PageWritable =
+          static_cast<uint32_t>(MinidumpMemoryProtectionContants::PageWritable);
+      info.SetWritable((entry->protect & PageWritable) != 0
+                           ? MemoryRegionInfo::eYes
+                           : MemoryRegionInfo::eNo);
+
+      const uint32_t PageExecutable = static_cast<uint32_t>(
+          MinidumpMemoryProtectionContants::PageExecutable);
+      info.SetExecutable((entry->protect & PageExecutable) != 0
+                             ? MemoryRegionInfo::eYes
+                             : MemoryRegionInfo::eNo);
+
+      const uint32_t MemFree =
+          static_cast<uint32_t>(MinidumpMemoryInfoState::MemFree);
+      info.SetMapped((entry->state != MemFree) ? MemoryRegionInfo::eYes
+                                               : MemoryRegionInfo::eNo);
+
+      return error;
+    } else if (head > load_addr &&
+               (next_entry == nullptr || head < next_entry->base_address)) {
+      // In case there is no region containing load_addr keep track of the
+      // nearest region
+      // after load_addr so we can return the distance to it.
+      next_entry = entry;
+    }
+  }
+
+  // No containing region found. Create an unmapped region that extends to the
+  // next region
+  // or LLDB_INVALID_ADDRESS
+  info.GetRange().SetRangeBase(load_addr);
+  info.GetRange().SetRangeEnd((next_entry != nullptr) ? next_entry->base_address
+                                                      : LLDB_INVALID_ADDRESS);
+  info.SetReadable(MemoryRegionInfo::eNo);
+  info.SetWritable(MemoryRegionInfo::eNo);
+  info.SetExecutable(MemoryRegionInfo::eNo);
+  info.SetMapped(MemoryRegionInfo::eNo);
+
+  // Note that the memory info list doesn't seem to contain ranges in kernel
+  // space,
+  // so if you're walking a stack that has kernel frames, the stack may appear
+  // truncated.
+  return error;
+}
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to