LLDB  mainline
MinidumpParser.cpp
Go to the documentation of this file.
1 //===-- MinidumpParser.cpp ------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "MinidumpParser.h"
10 #include "NtStructures.h"
12 
15 #include "lldb/Utility/LLDBLog.h"
16 #include "lldb/Utility/Log.h"
17 
18 // C includes
19 // C++ includes
20 #include <algorithm>
21 #include <map>
22 #include <vector>
23 #include <utility>
24 
25 using namespace lldb_private;
26 using namespace minidump;
27 
28 llvm::Expected<MinidumpParser>
29 MinidumpParser::Create(const lldb::DataBufferSP &data_sp) {
30  auto ExpectedFile = llvm::object::MinidumpFile::create(
31  llvm::MemoryBufferRef(toStringRef(data_sp->GetData()), "minidump"));
32  if (!ExpectedFile)
33  return ExpectedFile.takeError();
34 
35  return MinidumpParser(data_sp, std::move(*ExpectedFile));
36 }
37 
38 MinidumpParser::MinidumpParser(lldb::DataBufferSP data_sp,
39  std::unique_ptr<llvm::object::MinidumpFile> file)
40  : m_data_sp(std::move(data_sp)), m_file(std::move(file)) {}
41 
42 llvm::ArrayRef<uint8_t> MinidumpParser::GetData() {
43  return llvm::ArrayRef<uint8_t>(m_data_sp->GetBytes(),
44  m_data_sp->GetByteSize());
45 }
46 
47 llvm::ArrayRef<uint8_t> MinidumpParser::GetStream(StreamType stream_type) {
48  return m_file->getRawStream(stream_type).value_or(llvm::ArrayRef<uint8_t>());
49 }
50 
51 UUID MinidumpParser::GetModuleUUID(const minidump::Module *module) {
52  auto cv_record =
53  GetData().slice(module->CvRecord.RVA, module->CvRecord.DataSize);
54 
55  // Read the CV record signature
56  const llvm::support::ulittle32_t *signature = nullptr;
57  Status error = consumeObject(cv_record, signature);
58  if (error.Fail())
59  return UUID();
60 
61  const CvSignature cv_signature =
62  static_cast<CvSignature>(static_cast<uint32_t>(*signature));
63 
64  if (cv_signature == CvSignature::Pdb70) {
65  const UUID::CvRecordPdb70 *pdb70_uuid = nullptr;
66  Status error = consumeObject(cv_record, pdb70_uuid);
67  if (error.Fail())
68  return UUID();
69  if (GetArchitecture().GetTriple().isOSBinFormatELF()) {
70  if (pdb70_uuid->Age != 0)
71  return UUID(pdb70_uuid, sizeof(*pdb70_uuid));
72  return UUID(&pdb70_uuid->Uuid,
73  sizeof(pdb70_uuid->Uuid));
74  }
75  return UUID(*pdb70_uuid);
76  } else if (cv_signature == CvSignature::ElfBuildId)
77  return UUID(cv_record);
78 
79  return UUID();
80 }
81 
82 llvm::ArrayRef<minidump::Thread> MinidumpParser::GetThreads() {
83  auto ExpectedThreads = GetMinidumpFile().getThreadList();
84  if (ExpectedThreads)
85  return *ExpectedThreads;
86 
87  LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), ExpectedThreads.takeError(),
88  "Failed to read thread list: {0}");
89  return {};
90 }
91 
92 llvm::ArrayRef<uint8_t>
93 MinidumpParser::GetThreadContext(const LocationDescriptor &location) {
94  if (location.RVA + location.DataSize > GetData().size())
95  return {};
96  return GetData().slice(location.RVA, location.DataSize);
97 }
98 
99 llvm::ArrayRef<uint8_t>
100 MinidumpParser::GetThreadContext(const minidump::Thread &td) {
101  return GetThreadContext(td.Context);
102 }
103 
104 llvm::ArrayRef<uint8_t>
105 MinidumpParser::GetThreadContextWow64(const minidump::Thread &td) {
106  // On Windows, a 32-bit process can run on a 64-bit machine under WOW64. If
107  // the minidump was captured with a 64-bit debugger, then the CONTEXT we just
108  // grabbed from the mini_dump_thread is the one for the 64-bit "native"
109  // process rather than the 32-bit "guest" process we care about. In this
110  // case, we can get the 32-bit CONTEXT from the TEB (Thread Environment
111  // Block) of the 64-bit process.
112  auto teb_mem = GetMemory(td.EnvironmentBlock, sizeof(TEB64));
113  if (teb_mem.empty())
114  return {};
115 
116  const TEB64 *wow64teb;
117  Status error = consumeObject(teb_mem, wow64teb);
118  if (error.Fail())
119  return {};
120 
121  // Slot 1 of the thread-local storage in the 64-bit TEB points to a structure
122  // that includes the 32-bit CONTEXT (after a ULONG). See:
123  // https://msdn.microsoft.com/en-us/library/ms681670.aspx
124  auto context =
125  GetMemory(wow64teb->tls_slots[1] + 4, sizeof(MinidumpContext_x86_32));
126  if (context.size() < sizeof(MinidumpContext_x86_32))
127  return {};
128 
129  return context;
130  // NOTE: We don't currently use the TEB for anything else. If we
131  // need it in the future, the 32-bit TEB is located according to the address
132  // stored in the first slot of the 64-bit TEB (wow64teb.Reserved1[0]).
133 }
134 
136  if (m_arch.IsValid())
137  return m_arch;
138 
139  // Set the architecture in m_arch
140  llvm::Expected<const SystemInfo &> system_info = m_file->getSystemInfo();
141 
142  if (!system_info) {
143  LLDB_LOG_ERROR(GetLog(LLDBLog::Process), system_info.takeError(),
144  "Failed to read SystemInfo stream: {0}");
145  return m_arch;
146  }
147 
148  // TODO what to do about big endiand flavors of arm ?
149  // TODO set the arm subarch stuff if the minidump has info about it
150 
151  llvm::Triple triple;
152  triple.setVendor(llvm::Triple::VendorType::UnknownVendor);
153 
154  switch (system_info->ProcessorArch) {
155  case ProcessorArchitecture::X86:
156  triple.setArch(llvm::Triple::ArchType::x86);
157  break;
158  case ProcessorArchitecture::AMD64:
159  triple.setArch(llvm::Triple::ArchType::x86_64);
160  break;
161  case ProcessorArchitecture::ARM:
162  triple.setArch(llvm::Triple::ArchType::arm);
163  break;
164  case ProcessorArchitecture::ARM64:
165  case ProcessorArchitecture::BP_ARM64:
166  triple.setArch(llvm::Triple::ArchType::aarch64);
167  break;
168  default:
169  triple.setArch(llvm::Triple::ArchType::UnknownArch);
170  break;
171  }
172 
173  // TODO add all of the OSes that Minidump/breakpad distinguishes?
174  switch (system_info->PlatformId) {
175  case OSPlatform::Win32S:
176  case OSPlatform::Win32Windows:
177  case OSPlatform::Win32NT:
178  case OSPlatform::Win32CE:
179  triple.setOS(llvm::Triple::OSType::Win32);
180  triple.setVendor(llvm::Triple::VendorType::PC);
181  break;
182  case OSPlatform::Linux:
183  triple.setOS(llvm::Triple::OSType::Linux);
184  break;
185  case OSPlatform::MacOSX:
186  triple.setOS(llvm::Triple::OSType::MacOSX);
187  triple.setVendor(llvm::Triple::Apple);
188  break;
189  case OSPlatform::IOS:
190  triple.setOS(llvm::Triple::OSType::IOS);
191  triple.setVendor(llvm::Triple::Apple);
192  break;
193  case OSPlatform::Android:
194  triple.setOS(llvm::Triple::OSType::Linux);
195  triple.setEnvironment(llvm::Triple::EnvironmentType::Android);
196  break;
197  default: {
198  triple.setOS(llvm::Triple::OSType::UnknownOS);
199  auto ExpectedCSD = m_file->getString(system_info->CSDVersionRVA);
200  if (!ExpectedCSD) {
201  LLDB_LOG_ERROR(GetLog(LLDBLog::Process), ExpectedCSD.takeError(),
202  "Failed to CSD Version string: {0}");
203  } else {
204  if (ExpectedCSD->find("Linux") != std::string::npos)
205  triple.setOS(llvm::Triple::OSType::Linux);
206  }
207  break;
208  }
209  }
210  m_arch.SetTriple(triple);
211  return m_arch;
212 }
213 
215  llvm::ArrayRef<uint8_t> data = GetStream(StreamType::MiscInfo);
216 
217  if (data.size() == 0)
218  return nullptr;
219 
220  return MinidumpMiscInfo::Parse(data);
221 }
222 
223 llvm::Optional<LinuxProcStatus> MinidumpParser::GetLinuxProcStatus() {
224  llvm::ArrayRef<uint8_t> data = GetStream(StreamType::LinuxProcStatus);
225 
226  if (data.size() == 0)
227  return llvm::None;
228 
229  return LinuxProcStatus::Parse(data);
230 }
231 
232 llvm::Optional<lldb::pid_t> MinidumpParser::GetPid() {
233  const MinidumpMiscInfo *misc_info = GetMiscInfo();
234  if (misc_info != nullptr) {
235  return misc_info->GetPid();
236  }
237 
238  llvm::Optional<LinuxProcStatus> proc_status = GetLinuxProcStatus();
239  if (proc_status) {
240  return proc_status->GetPid();
241  }
242 
243  return llvm::None;
244 }
245 
246 llvm::ArrayRef<minidump::Module> MinidumpParser::GetModuleList() {
247  auto ExpectedModules = GetMinidumpFile().getModuleList();
248  if (ExpectedModules)
249  return *ExpectedModules;
250 
251  LLDB_LOG_ERROR(GetLog(LLDBLog::Modules), ExpectedModules.takeError(),
252  "Failed to read module list: {0}");
253  return {};
254 }
255 
256 static bool
258  std::vector<MemoryRegionInfo> &regions) {
259  auto data = parser.GetStream(StreamType::LinuxMaps);
260  if (data.empty())
261  return false;
262 
265  llvm::toStringRef(data),
266  [&regions, &log](llvm::Expected<MemoryRegionInfo> region) -> bool {
267  if (region)
268  regions.push_back(*region);
269  else
270  LLDB_LOG_ERROR(log, region.takeError(),
271  "Reading memory region from minidump failed: {0}");
272  return true;
273  });
274  return !regions.empty();
275 }
276 
277 /// Check for the memory regions starting at \a load_addr for a contiguous
278 /// section that has execute permissions that matches the module path.
279 ///
280 /// When we load a breakpad generated minidump file, we might have the
281 /// /proc/<pid>/maps text for a process that details the memory map of the
282 /// process that the minidump is describing. This checks the sorted memory
283 /// regions for a section that has execute permissions. A sample maps files
284 /// might look like:
285 ///
286 /// 00400000-00401000 r--p 00000000 fd:01 2838574 /tmp/a.out
287 /// 00401000-00402000 r-xp 00001000 fd:01 2838574 /tmp/a.out
288 /// 00402000-00403000 r--p 00002000 fd:01 2838574 /tmp/a.out
289 /// 00403000-00404000 r--p 00002000 fd:01 2838574 /tmp/a.out
290 /// 00404000-00405000 rw-p 00003000 fd:01 2838574 /tmp/a.out
291 /// ...
292 ///
293 /// This function should return true when given 0x00400000 and "/tmp/a.out"
294 /// is passed in as the path since it has a consecutive memory region for
295 /// "/tmp/a.out" that has execute permissions at 0x00401000. This will help us
296 /// differentiate if a file has been memory mapped into a process for reading
297 /// and breakpad ends up saving a minidump file that has two module entries for
298 /// a given file: one that is read only for the entire file, and then one that
299 /// is the real executable that is loaded into memory for execution. For memory
300 /// mapped files they will typically show up and r--p permissions and a range
301 /// matcning the entire range of the file on disk:
302 ///
303 /// 00800000-00805000 r--p 00000000 fd:01 2838574 /tmp/a.out
304 /// 00805000-00806000 r-xp 00001000 fd:01 1234567 /usr/lib/libc.so
305 ///
306 /// This function should return false when asked about 0x00800000 with
307 /// "/tmp/a.out" as the path.
308 ///
309 /// \param[in] path
310 /// The path to the module to check for in the memory regions. Only sequential
311 /// memory regions whose paths match this path will be considered when looking
312 /// for execute permissions.
313 ///
314 /// \param[in] regions
315 /// A sorted list of memory regions obtained from a call to
316 /// CreateRegionsCacheFromLinuxMaps.
317 ///
318 /// \param[in] base_of_image
319 /// The load address of this module from BaseOfImage in the modules list.
320 ///
321 /// \return
322 /// True if a contiguous region of memory belonging to the module with a
323 /// matching path exists that has executable permissions. Returns false if
324 /// \a regions is empty or if there are no regions with execute permissions
325 /// that match \a path.
326 
328  const MemoryRegionInfos &regions,
329  lldb::addr_t base_of_image) {
330  if (regions.empty())
331  return false;
332  lldb::addr_t addr = base_of_image;
334  while (region.GetName() == path) {
335  if (region.GetExecutable() == MemoryRegionInfo::eYes)
336  return true;
337  addr += region.GetRange().GetByteSize();
338  region = MinidumpParser::GetMemoryRegionInfo(regions, addr);
339  }
340  return false;
341 }
342 
343 std::vector<const minidump::Module *> MinidumpParser::GetFilteredModuleList() {
344  Log *log = GetLog(LLDBLog::Modules);
345  auto ExpectedModules = GetMinidumpFile().getModuleList();
346  if (!ExpectedModules) {
347  LLDB_LOG_ERROR(log, ExpectedModules.takeError(),
348  "Failed to read module list: {0}");
349  return {};
350  }
351 
352  // Create memory regions from the linux maps only. We do this to avoid issues
353  // with breakpad generated minidumps where if someone has mmap'ed a shared
354  // library into memory to access its data in the object file, we can get a
355  // minidump with two mappings for a binary: one whose base image points to a
356  // memory region that is read + execute and one that is read only.
357  MemoryRegionInfos linux_regions;
358  if (CreateRegionsCacheFromLinuxMaps(*this, linux_regions))
359  llvm::sort(linux_regions);
360 
361  // map module_name -> filtered_modules index
362  typedef llvm::StringMap<size_t> MapType;
363  MapType module_name_to_filtered_index;
364 
365  std::vector<const minidump::Module *> filtered_modules;
366 
367  for (const auto &module : *ExpectedModules) {
368  auto ExpectedName = m_file->getString(module.ModuleNameRVA);
369  if (!ExpectedName) {
370  LLDB_LOG_ERROR(log, ExpectedName.takeError(),
371  "Failed to get module name: {0}");
372  continue;
373  }
374 
375  MapType::iterator iter;
376  bool inserted;
377  // See if we have inserted this module aready into filtered_modules. If we
378  // haven't insert an entry into module_name_to_filtered_index with the
379  // index where we will insert it if it isn't in the vector already.
380  std::tie(iter, inserted) = module_name_to_filtered_index.try_emplace(
381  *ExpectedName, filtered_modules.size());
382 
383  if (inserted) {
384  // This module has not been seen yet, insert it into filtered_modules at
385  // the index that was inserted into module_name_to_filtered_index using
386  // "filtered_modules.size()" above.
387  filtered_modules.push_back(&module);
388  } else {
389  // We have a duplicate module entry. Check the linux regions to see if
390  // either module is not really a mapped executable. If one but not the
391  // other is a real mapped executable, prefer the executable one. This
392  // can happen when a process mmap's in the file for an executable in
393  // order to read bytes from the executable file. A memory region mapping
394  // will exist for the mmap'ed version and for the loaded executable, but
395  // only one will have a consecutive region that is executable in the
396  // memory regions.
397  auto dup_module = filtered_modules[iter->second];
398  ConstString name(*ExpectedName);
399  bool is_executable =
400  CheckForLinuxExecutable(name, linux_regions, module.BaseOfImage);
401  bool dup_is_executable =
402  CheckForLinuxExecutable(name, linux_regions, dup_module->BaseOfImage);
403 
404  if (is_executable != dup_is_executable) {
405  if (is_executable)
406  filtered_modules[iter->second] = &module;
407  continue;
408  }
409  // This module has been seen. Modules are sometimes mentioned multiple
410  // times when they are mapped discontiguously, so find the module with
411  // the lowest "base_of_image" and use that as the filtered module.
412  if (module.BaseOfImage < dup_module->BaseOfImage)
413  filtered_modules[iter->second] = &module;
414  }
415  }
416  return filtered_modules;
417 }
418 
419 const minidump::ExceptionStream *MinidumpParser::GetExceptionStream() {
420  auto ExpectedStream = GetMinidumpFile().getExceptionStream();
421  if (ExpectedStream)
422  return &*ExpectedStream;
423 
424  LLDB_LOG_ERROR(GetLog(LLDBLog::Process), ExpectedStream.takeError(),
425  "Failed to read minidump exception stream: {0}");
426  return nullptr;
427 }
428 
429 llvm::Optional<minidump::Range>
431  llvm::ArrayRef<uint8_t> data64 = GetStream(StreamType::Memory64List);
432  Log *log = GetLog(LLDBLog::Modules);
433 
434  auto ExpectedMemory = GetMinidumpFile().getMemoryList();
435  if (!ExpectedMemory) {
436  LLDB_LOG_ERROR(log, ExpectedMemory.takeError(),
437  "Failed to read memory list: {0}");
438  } else {
439  for (const auto &memory_desc : *ExpectedMemory) {
440  const LocationDescriptor &loc_desc = memory_desc.Memory;
441  const lldb::addr_t range_start = memory_desc.StartOfMemoryRange;
442  const size_t range_size = loc_desc.DataSize;
443 
444  if (loc_desc.RVA + loc_desc.DataSize > GetData().size())
445  return llvm::None;
446 
447  if (range_start <= addr && addr < range_start + range_size) {
448  auto ExpectedSlice = GetMinidumpFile().getRawData(loc_desc);
449  if (!ExpectedSlice) {
450  LLDB_LOG_ERROR(log, ExpectedSlice.takeError(),
451  "Failed to get memory slice: {0}");
452  return llvm::None;
453  }
454  return minidump::Range(range_start, *ExpectedSlice);
455  }
456  }
457  }
458 
459  // Some Minidumps have a Memory64ListStream that captures all the heap memory
460  // (full-memory Minidumps). We can't exactly use the same loop as above,
461  // because the Minidump uses slightly different data structures to describe
462  // those
463 
464  if (!data64.empty()) {
465  llvm::ArrayRef<MinidumpMemoryDescriptor64> memory64_list;
466  uint64_t base_rva;
467  std::tie(memory64_list, base_rva) =
469 
470  if (memory64_list.empty())
471  return llvm::None;
472 
473  for (const auto &memory_desc64 : memory64_list) {
474  const lldb::addr_t range_start = memory_desc64.start_of_memory_range;
475  const size_t range_size = memory_desc64.data_size;
476 
477  if (base_rva + range_size > GetData().size())
478  return llvm::None;
479 
480  if (range_start <= addr && addr < range_start + range_size) {
481  return minidump::Range(range_start,
482  GetData().slice(base_rva, range_size));
483  }
484  base_rva += range_size;
485  }
486  }
487 
488  return llvm::None;
489 }
490 
491 llvm::ArrayRef<uint8_t> MinidumpParser::GetMemory(lldb::addr_t addr,
492  size_t size) {
493  // I don't have a sense of how frequently this is called or how many memory
494  // ranges a Minidump typically has, so I'm not sure if searching for the
495  // appropriate range linearly each time is stupid. Perhaps we should build
496  // an index for faster lookups.
497  llvm::Optional<minidump::Range> range = FindMemoryRange(addr);
498  if (!range)
499  return {};
500 
501  // There's at least some overlap between the beginning of the desired range
502  // (addr) and the current range. Figure out where the overlap begins and how
503  // much overlap there is.
504 
505  const size_t offset = addr - range->start;
506 
507  if (addr < range->start || offset >= range->range_ref.size())
508  return {};
509 
510  const size_t overlap = std::min(size, range->range_ref.size() - offset);
511  return range->range_ref.slice(offset, overlap);
512 }
513 
514 static bool
516  std::vector<MemoryRegionInfo> &regions) {
517  Log *log = GetLog(LLDBLog::Modules);
518  auto ExpectedInfo = parser.GetMinidumpFile().getMemoryInfoList();
519  if (!ExpectedInfo) {
520  LLDB_LOG_ERROR(log, ExpectedInfo.takeError(),
521  "Failed to read memory info list: {0}");
522  return false;
523  }
524  constexpr auto yes = MemoryRegionInfo::eYes;
525  constexpr auto no = MemoryRegionInfo::eNo;
526  for (const MemoryInfo &entry : *ExpectedInfo) {
527  MemoryRegionInfo region;
528  region.GetRange().SetRangeBase(entry.BaseAddress);
529  region.GetRange().SetByteSize(entry.RegionSize);
530 
531  MemoryProtection prot = entry.Protect;
532  region.SetReadable(bool(prot & MemoryProtection::NoAccess) ? no : yes);
533  region.SetWritable(
534  bool(prot & (MemoryProtection::ReadWrite | MemoryProtection::WriteCopy |
535  MemoryProtection::ExecuteReadWrite |
536  MemoryProtection::ExeciteWriteCopy))
537  ? yes
538  : no);
539  region.SetExecutable(
540  bool(prot & (MemoryProtection::Execute | MemoryProtection::ExecuteRead |
541  MemoryProtection::ExecuteReadWrite |
542  MemoryProtection::ExeciteWriteCopy))
543  ? yes
544  : no);
545  region.SetMapped(entry.State != MemoryState::Free ? yes : no);
546  regions.push_back(region);
547  }
548  return !regions.empty();
549 }
550 
551 static bool
553  std::vector<MemoryRegionInfo> &regions) {
554  Log *log = GetLog(LLDBLog::Modules);
555  auto ExpectedMemory = parser.GetMinidumpFile().getMemoryList();
556  if (!ExpectedMemory) {
557  LLDB_LOG_ERROR(log, ExpectedMemory.takeError(),
558  "Failed to read memory list: {0}");
559  return false;
560  }
561  regions.reserve(ExpectedMemory->size());
562  for (const MemoryDescriptor &memory_desc : *ExpectedMemory) {
563  if (memory_desc.Memory.DataSize == 0)
564  continue;
565  MemoryRegionInfo region;
566  region.GetRange().SetRangeBase(memory_desc.StartOfMemoryRange);
567  region.GetRange().SetByteSize(memory_desc.Memory.DataSize);
570  regions.push_back(region);
571  }
572  regions.shrink_to_fit();
573  return !regions.empty();
574 }
575 
576 static bool
578  std::vector<MemoryRegionInfo> &regions) {
579  llvm::ArrayRef<uint8_t> data =
580  parser.GetStream(StreamType::Memory64List);
581  if (data.empty())
582  return false;
583  llvm::ArrayRef<MinidumpMemoryDescriptor64> memory64_list;
584  uint64_t base_rva;
585  std::tie(memory64_list, base_rva) =
587 
588  if (memory64_list.empty())
589  return false;
590 
591  regions.reserve(memory64_list.size());
592  for (const auto &memory_desc : memory64_list) {
593  if (memory_desc.data_size == 0)
594  continue;
595  MemoryRegionInfo region;
596  region.GetRange().SetRangeBase(memory_desc.start_of_memory_range);
597  region.GetRange().SetByteSize(memory_desc.data_size);
600  regions.push_back(region);
601  }
602  regions.shrink_to_fit();
603  return !regions.empty();
604 }
605 
606 std::pair<MemoryRegionInfos, bool> MinidumpParser::BuildMemoryRegions() {
607  // We create the region cache using the best source. We start with
608  // the linux maps since they are the most complete and have names for the
609  // regions. Next we try the MemoryInfoList since it has
610  // read/write/execute/map data, and then fall back to the MemoryList and
611  // Memory64List to just get a list of the memory that is mapped in this
612  // core file
613  MemoryRegionInfos result;
614  const auto &return_sorted = [&](bool is_complete) {
615  llvm::sort(result);
616  return std::make_pair(std::move(result), is_complete);
617  };
618  if (CreateRegionsCacheFromLinuxMaps(*this, result))
619  return return_sorted(true);
620  if (CreateRegionsCacheFromMemoryInfoList(*this, result))
621  return return_sorted(true);
622  if (CreateRegionsCacheFromMemoryList(*this, result))
623  return return_sorted(false);
624  CreateRegionsCacheFromMemory64List(*this, result);
625  return return_sorted(false);
626 }
627 
628 #define ENUM_TO_CSTR(ST) \
629  case StreamType::ST: \
630  return #ST
631 
632 llvm::StringRef
633 MinidumpParser::GetStreamTypeAsString(StreamType stream_type) {
634  switch (stream_type) {
635  ENUM_TO_CSTR(Unused);
638  ENUM_TO_CSTR(MemoryList);
640  ENUM_TO_CSTR(SystemInfo);
641  ENUM_TO_CSTR(ThreadExList);
642  ENUM_TO_CSTR(Memory64List);
643  ENUM_TO_CSTR(CommentA);
644  ENUM_TO_CSTR(CommentW);
645  ENUM_TO_CSTR(HandleData);
646  ENUM_TO_CSTR(FunctionTable);
647  ENUM_TO_CSTR(UnloadedModuleList);
648  ENUM_TO_CSTR(MiscInfo);
649  ENUM_TO_CSTR(MemoryInfoList);
650  ENUM_TO_CSTR(ThreadInfoList);
651  ENUM_TO_CSTR(HandleOperationList);
652  ENUM_TO_CSTR(Token);
653  ENUM_TO_CSTR(JavascriptData);
654  ENUM_TO_CSTR(SystemMemoryInfo);
655  ENUM_TO_CSTR(ProcessVMCounters);
656  ENUM_TO_CSTR(LastReserved);
657  ENUM_TO_CSTR(BreakpadInfo);
658  ENUM_TO_CSTR(AssertionInfo);
659  ENUM_TO_CSTR(LinuxCPUInfo);
661  ENUM_TO_CSTR(LinuxLSBRelease);
662  ENUM_TO_CSTR(LinuxCMDLine);
663  ENUM_TO_CSTR(LinuxEnviron);
664  ENUM_TO_CSTR(LinuxAuxv);
665  ENUM_TO_CSTR(LinuxMaps);
666  ENUM_TO_CSTR(LinuxDSODebug);
667  ENUM_TO_CSTR(LinuxProcStat);
668  ENUM_TO_CSTR(LinuxProcUptime);
669  ENUM_TO_CSTR(LinuxProcFD);
670  ENUM_TO_CSTR(FacebookAppCustomData);
671  ENUM_TO_CSTR(FacebookBuildID);
672  ENUM_TO_CSTR(FacebookAppVersionName);
673  ENUM_TO_CSTR(FacebookJavaStack);
674  ENUM_TO_CSTR(FacebookDalvikInfo);
675  ENUM_TO_CSTR(FacebookUnwindSymbols);
676  ENUM_TO_CSTR(FacebookDumpErrorLog);
677  ENUM_TO_CSTR(FacebookAppStateLog);
678  ENUM_TO_CSTR(FacebookAbortReason);
679  ENUM_TO_CSTR(FacebookThreadName);
680  ENUM_TO_CSTR(FacebookLogcat);
681  }
682  return "unknown stream type";
683 }
684 
687  lldb::addr_t load_addr) {
688  MemoryRegionInfo region;
689  auto pos = llvm::upper_bound(regions, load_addr);
690  if (pos != regions.begin() &&
691  std::prev(pos)->GetRange().Contains(load_addr)) {
692  return *std::prev(pos);
693  }
694 
695  if (pos == regions.begin())
696  region.GetRange().SetRangeBase(0);
697  else
698  region.GetRange().SetRangeBase(std::prev(pos)->GetRange().GetRangeEnd());
699 
700  if (pos == regions.end())
701  region.GetRange().SetRangeEnd(UINT64_MAX);
702  else
703  region.GetRange().SetRangeEnd(pos->GetRange().GetRangeBase());
704 
709  return region;
710 }
lldb_private::UUID::CvRecordPdb70::Age
llvm::support::ulittle32_t Age
Definition: UUID.h:46
lldb_private::UUID
Definition: UUID.h:23
lldb_private::minidump::CvSignature::ElfBuildId
@ ElfBuildId
lldb_private::minidump::MinidumpMiscInfo
Definition: MinidumpTypes.h:75
lldb_private::ArchSpec
Definition: ArchSpec.h:32
RegisterContextMinidump_x86_32.h
lldb_private::minidump::MinidumpMemoryDescriptor64::ParseMemory64List
static std::pair< llvm::ArrayRef< MinidumpMemoryDescriptor64 >, uint64_t > ParseMemory64List(llvm::ArrayRef< uint8_t > &data)
Definition: MinidumpTypes.cpp:61
lldb_private::minidump::MinidumpParser::GetLinuxProcStatus
llvm::Optional< LinuxProcStatus > GetLinuxProcStatus()
Definition: MinidumpParser.cpp:223
lldb_private::UUID::CvRecordPdb70::Uuid
struct lldb_private::UUID::CvRecordPdb70::@43 Uuid
lldb_private::minidump::MinidumpParser::GetFilteredModuleList
std::vector< const minidump::Module * > GetFilteredModuleList()
Definition: MinidumpParser.cpp:343
lldb_private::minidump::MinidumpParser::GetExceptionStream
const llvm::minidump::ExceptionStream * GetExceptionStream()
Definition: MinidumpParser.cpp:419
lldb_private::minidump::MinidumpParser::m_arch
ArchSpec m_arch
Definition: MinidumpParser.h:108
lldb_private::minidump::MinidumpParser::FindMemoryRange
llvm::Optional< Range > FindMemoryRange(lldb::addr_t addr)
Definition: MinidumpParser.cpp:430
lldb_private::ParseLinuxMapRegions
void ParseLinuxMapRegions(llvm::StringRef linux_map, LinuxMapCallback const &callback)
Definition: LinuxProcMaps.cpp:122
lldb_private::minidump::MinidumpParser::GetModuleUUID
UUID GetModuleUUID(const minidump::Module *module)
Definition: MinidumpParser.cpp:51
lldb_private::minidump::MinidumpParser::GetPid
llvm::Optional< lldb::pid_t > GetPid()
Definition: MinidumpParser.cpp:232
lldb_private::minidump::TEB64::tls_slots
llvm::support::ulittle64_t tls_slots[64]
Definition: minidump/NtStructures.h:30
lldb_private::minidump::MinidumpMiscInfo::GetPid
llvm::Optional< lldb::pid_t > GetPid() const
Definition: MinidumpTypes.cpp:27
lldb_private::minidump::MinidumpParser::GetThreadContext
llvm::ArrayRef< uint8_t > GetThreadContext(const LocationDescriptor &location)
Definition: MinidumpParser.cpp:93
lldb_private::MemoryRegionInfo
Definition: MemoryRegionInfo.h:21
lldb_private::minidump::TEB64
Definition: minidump/NtStructures.h:25
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
lldb_private::MemoryRegionInfo::SetReadable
void SetReadable(OptionalBool val)
Definition: MemoryRegionInfo.h:58
lldb_private::LLDBLog::Modules
@ Modules
lldb_private::minidump::MinidumpParser::GetArchitecture
ArchSpec GetArchitecture()
Definition: MinidumpParser.cpp:135
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::Range::SetRangeEnd
void SetRangeEnd(BaseType end)
Definition: RangeMap.h:80
MinidumpParser.h
LLDBAssert.h
lldb_private::MemoryRegionInfo::GetExecutable
OptionalBool GetExecutable() const
Definition: MemoryRegionInfo.h:48
lldb_private::minidump::MinidumpParser::GetStream
llvm::ArrayRef< uint8_t > GetStream(StreamType stream_type)
Definition: MinidumpParser.cpp:47
lldb_private::ModuleList
Definition: ModuleList.h:82
Log.h
lldb_private::MemoryRegionInfo::SetExecutable
void SetExecutable(OptionalBool val)
Definition: MemoryRegionInfo.h:62
lldb_private::minidump::MinidumpParser::GetStreamTypeAsString
static llvm::StringRef GetStreamTypeAsString(StreamType stream_type)
Definition: MinidumpParser.cpp:633
lldb_private::minidump::MinidumpParser
Definition: MinidumpParser.h:50
lldb_private::ArchSpec::SetTriple
bool SetTriple(const llvm::Triple &triple)
Architecture triple setter.
Definition: ArchSpec.cpp:750
lldb_private::minidump::LinuxProcStatus
Definition: MinidumpTypes.h:92
lldb_private::LLDBLog::Process
@ Process
lldb_private::minidump::MinidumpParser::GetMinidumpFile
llvm::object::MinidumpFile & GetMinidumpFile()
Definition: MinidumpParser.h:97
lldb_private::LLDBLog::Thread
@ Thread
lldb_private::MemoryRegionInfo::eYes
@ eYes
Definition: MemoryRegionInfo.h:25
lldb_private::MemoryRegionInfos
Definition: MemoryRegionInfo.h:172
lldb_private::minidump::LinuxProcStatus::Parse
static llvm::Optional< LinuxProcStatus > Parse(llvm::ArrayRef< uint8_t > &data)
Definition: MinidumpTypes.cpp:38
lldb_private::ThreadList
Definition: ThreadList.h:26
lldb_private::minidump::MinidumpParser::GetThreads
llvm::ArrayRef< minidump::Thread > GetThreads()
Definition: MinidumpParser.cpp:82
lldb_private::ConstString
Definition: ConstString.h:39
lldb_private::minidump::MinidumpParser::m_data_sp
lldb::DataBufferSP m_data_sp
Definition: MinidumpParser.h:106
CreateRegionsCacheFromLinuxMaps
static bool CreateRegionsCacheFromLinuxMaps(MinidumpParser &parser, std::vector< MemoryRegionInfo > &regions)
Definition: MinidumpParser.cpp:257
lldb_private::minidump::MinidumpParser::GetData
llvm::ArrayRef< uint8_t > GetData()
Definition: MinidumpParser.cpp:42
lldb_private::MemoryRegionInfo::GetName
ConstString GetName() const
Definition: MemoryRegionInfo.h:54
CreateRegionsCacheFromMemory64List
static bool CreateRegionsCacheFromMemory64List(MinidumpParser &parser, std::vector< MemoryRegionInfo > &regions)
Definition: MinidumpParser.cpp:577
lldb_private::MemoryRegionInfo::eNo
@ eNo
Definition: MemoryRegionInfo.h:25
lldb_private::ArchSpec::IsValid
bool IsValid() const
Tests if this ArchSpec is valid.
Definition: ArchSpec.h:361
lldb_private::WindowsLog::Exception
@ Exception
lldb_private::minidump::MinidumpParser::m_file
std::unique_ptr< llvm::object::MinidumpFile > m_file
Definition: MinidumpParser.h:107
lldb_private::minidump::CvSignature::Pdb70
@ Pdb70
lldb_private::MemoryRegionInfo::SetWritable
void SetWritable(OptionalBool val)
Definition: MemoryRegionInfo.h:60
CreateRegionsCacheFromMemoryInfoList
static bool CreateRegionsCacheFromMemoryInfoList(MinidumpParser &parser, std::vector< MemoryRegionInfo > &regions)
Definition: MinidumpParser.cpp:515
lldb_private::minidump::MinidumpParser::GetThreadContextWow64
llvm::ArrayRef< uint8_t > GetThreadContextWow64(const minidump::Thread &td)
Definition: MinidumpParser.cpp:105
lldb_private::Status
Definition: Status.h:44
lldb_private::minidump::MinidumpContext_x86_32
Definition: RegisterContextMinidump_x86_32.h:57
lldb_private::minidump::MinidumpParser::GetModuleList
llvm::ArrayRef< minidump::Module > GetModuleList()
Definition: MinidumpParser.cpp:246
uint32_t
lldb_private::minidump::MinidumpMiscInfo::Parse
static const MinidumpMiscInfo * Parse(llvm::ArrayRef< uint8_t > &data)
Definition: MinidumpTypes.cpp:18
lldb_private::UUID::CvRecordPdb70
Definition: UUID.h:39
CreateRegionsCacheFromMemoryList
static bool CreateRegionsCacheFromMemoryList(MinidumpParser &parser, std::vector< MemoryRegionInfo > &regions)
Definition: MinidumpParser.cpp:552
CheckForLinuxExecutable
static bool CheckForLinuxExecutable(ConstString path, const MemoryRegionInfos &regions, lldb::addr_t base_of_image)
Check for the memory regions starting at load_addr for a contiguous section that has execute permissi...
Definition: MinidumpParser.cpp:327
lldb_private::MemoryRegionInfo::SetMapped
void SetMapped(OptionalBool val)
Definition: MemoryRegionInfo.h:66
lldb_private::Range::SetRangeBase
void SetRangeBase(BaseType b)
Definition: RangeMap.h:48
NtStructures.h
lldb_private::Range::GetByteSize
SizeType GetByteSize() const
Definition: RangeMap.h:87
lldb_private::Range::SetByteSize
void SetByteSize(SizeType s)
Definition: RangeMap.h:89
lldb_private::minidump::consumeObject
Status consumeObject(llvm::ArrayRef< uint8_t > &Buffer, const T *&Object)
Definition: MinidumpTypes.h:50
lldb_private::minidump::MinidumpParser::GetMiscInfo
const MinidumpMiscInfo * GetMiscInfo()
Definition: MinidumpParser.cpp:214
ENUM_TO_CSTR
#define ENUM_TO_CSTR(ST)
Definition: MinidumpParser.cpp:628
lldb_private::MemoryRegionInfo::GetRange
RangeType & GetRange()
Definition: MemoryRegionInfo.h:38
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::minidump::MinidumpParser::GetMemoryRegionInfo
static MemoryRegionInfo GetMemoryRegionInfo(const MemoryRegionInfos &regions, lldb::addr_t load_addr)
Definition: MinidumpParser.cpp:686
lldb_private::minidump::Range
Definition: MinidumpParser.h:37
lldb_private::minidump::MinidumpParser::Create
static llvm::Expected< MinidumpParser > Create(const lldb::DataBufferSP &data_buf_sp)
Definition: MinidumpParser.cpp:29
LinuxProcMaps.h
lldb_private::minidump::MinidumpParser::BuildMemoryRegions
std::pair< MemoryRegionInfos, bool > BuildMemoryRegions()
Returns a list of memory regions and a flag indicating whether the list is complete (includes all reg...
Definition: MinidumpParser.cpp:606
lldb_private::Log
Definition: Log.h:115
lldb_private::minidump::MinidumpParser::GetMemory
llvm::ArrayRef< uint8_t > GetMemory(lldb::addr_t addr, size_t size)
Definition: MinidumpParser.cpp:491
lldb_private::GetLog
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:309
lldb_private::LLDBLog::Expressions
@ Expressions
LLDB_LOG_ERROR
#define LLDB_LOG_ERROR(log, error,...)
Definition: Log.h:360
lldb_private::minidump::MinidumpParser::MinidumpParser
MinidumpParser(lldb::DataBufferSP data_sp, std::unique_ptr< llvm::object::MinidumpFile > file)
Definition: MinidumpParser.cpp:38
LLDBLog.h
UINT64_MAX
#define UINT64_MAX
Definition: lldb-defines.h:23
lldb_private::minidump::CvSignature
CvSignature
Definition: MinidumpTypes.h:38