LLDB  mainline
MinidumpFileBuilder.cpp
Go to the documentation of this file.
1 //===-- MinidumpFileBuilder.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 "MinidumpFileBuilder.h"
10 
12 
13 #include "lldb/Core/Module.h"
14 #include "lldb/Core/ModuleList.h"
15 #include "lldb/Core/Section.h"
17 #include "lldb/Target/Process.h"
19 #include "lldb/Target/StopInfo.h"
20 #include "lldb/Target/ThreadList.h"
23 
24 #include "llvm/ADT/StringRef.h"
25 #include "llvm/BinaryFormat/Minidump.h"
26 #include "llvm/Support/ConvertUTF.h"
27 #include "llvm/Support/Error.h"
28 
30 
31 #include <cinttypes>
32 
33 using namespace lldb;
34 using namespace lldb_private;
35 using namespace llvm::minidump;
36 
37 void MinidumpFileBuilder::AddDirectory(StreamType type, size_t stream_size) {
38  LocationDescriptor loc;
39  loc.DataSize = static_cast<llvm::support::ulittle32_t>(stream_size);
40  // Stream will begin at the current end of data section
41  loc.RVA = static_cast<llvm::support::ulittle32_t>(GetCurrentDataEndOffset());
42 
43  Directory dir;
44  dir.Type = static_cast<llvm::support::little_t<StreamType>>(type);
45  dir.Location = loc;
46 
47  m_directories.push_back(dir);
48 }
49 
50 Status MinidumpFileBuilder::AddSystemInfo(const llvm::Triple &target_triple) {
51  Status error;
52  AddDirectory(StreamType::SystemInfo, sizeof(llvm::minidump::SystemInfo));
53 
54  llvm::minidump::ProcessorArchitecture arch;
55  switch (target_triple.getArch()) {
56  case llvm::Triple::ArchType::x86_64:
57  arch = ProcessorArchitecture::AMD64;
58  break;
59  case llvm::Triple::ArchType::x86:
60  arch = ProcessorArchitecture::X86;
61  break;
62  case llvm::Triple::ArchType::arm:
63  arch = ProcessorArchitecture::ARM;
64  break;
65  case llvm::Triple::ArchType::aarch64:
66  arch = ProcessorArchitecture::ARM64;
67  break;
68  case llvm::Triple::ArchType::mips64:
69  case llvm::Triple::ArchType::mips64el:
70  case llvm::Triple::ArchType::mips:
71  case llvm::Triple::ArchType::mipsel:
72  arch = ProcessorArchitecture::MIPS;
73  break;
74  case llvm::Triple::ArchType::ppc64:
75  case llvm::Triple::ArchType::ppc:
76  case llvm::Triple::ArchType::ppc64le:
77  arch = ProcessorArchitecture::PPC;
78  break;
79  default:
80  error.SetErrorStringWithFormat("Architecture %s not supported.",
81  target_triple.getArchName().str().c_str());
82  return error;
83  };
84 
85  llvm::support::little_t<OSPlatform> platform_id;
86  switch (target_triple.getOS()) {
87  case llvm::Triple::OSType::Linux:
88  if (target_triple.getEnvironment() ==
89  llvm::Triple::EnvironmentType::Android)
90  platform_id = OSPlatform::Android;
91  else
92  platform_id = OSPlatform::Linux;
93  break;
94  case llvm::Triple::OSType::Win32:
95  platform_id = OSPlatform::Win32NT;
96  break;
97  case llvm::Triple::OSType::MacOSX:
98  platform_id = OSPlatform::MacOSX;
99  break;
100  case llvm::Triple::OSType::IOS:
101  platform_id = OSPlatform::IOS;
102  break;
103  default:
104  error.SetErrorStringWithFormat("OS %s not supported.",
105  target_triple.getOSName().str().c_str());
106  return error;
107  };
108 
109  llvm::minidump::SystemInfo sys_info;
110  sys_info.ProcessorArch =
111  static_cast<llvm::support::little_t<ProcessorArchitecture>>(arch);
112  // Global offset to beginning of a csd_string in a data section
113  sys_info.CSDVersionRVA = static_cast<llvm::support::ulittle32_t>(
114  GetCurrentDataEndOffset() + sizeof(llvm::minidump::SystemInfo));
115  sys_info.PlatformId = platform_id;
116  m_data.AppendData(&sys_info, sizeof(llvm::minidump::SystemInfo));
117 
118  std::string csd_string;
119 
120  error = WriteString(csd_string, &m_data);
121  if (error.Fail()) {
122  error.SetErrorString("Unable to convert the csd string to UTF16.");
123  return error;
124  }
125 
126  return error;
127 }
128 
131  Status error;
132  // let the StringRef eat also null termination char
133  llvm::StringRef to_write_ref(to_write.c_str(), to_write.size() + 1);
134  llvm::SmallVector<llvm::UTF16, 128> to_write_utf16;
135 
136  bool converted = convertUTF8ToUTF16String(to_write_ref, to_write_utf16);
137  if (!converted) {
138  error.SetErrorStringWithFormat(
139  "Unable to convert the string to UTF16. Failed to convert %s",
140  to_write.c_str());
141  return error;
142  }
143 
144  // size of the UTF16 string should be written without the null termination
145  // character that is stored in 2 bytes
146  llvm::support::ulittle32_t to_write_size(to_write_utf16.size_in_bytes() - 2);
147 
148  buffer->AppendData(&to_write_size, sizeof(llvm::support::ulittle32_t));
149  buffer->AppendData(to_write_utf16.data(), to_write_utf16.size_in_bytes());
150 
151  return error;
152 }
153 
154 llvm::Expected<uint64_t> getModuleFileSize(Target &target,
155  const ModuleSP &mod) {
156  SectionSP sect_sp = mod->GetObjectFile()->GetBaseAddress().GetSection();
157  uint64_t SizeOfImage = 0;
158 
159  if (!sect_sp) {
160  return llvm::createStringError(std::errc::operation_not_supported,
161  "Couldn't obtain the section information.");
162  }
163  lldb::addr_t sect_addr = sect_sp->GetLoadBaseAddress(&target);
164  // Use memory size since zero fill sections, like ".bss", will be smaller on
165  // disk.
166  lldb::addr_t sect_size = sect_sp->GetByteSize();
167  // This will usually be zero, but make sure to calculate the BaseOfImage
168  // offset.
169  const lldb::addr_t base_sect_offset =
170  mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target) -
171  sect_addr;
172  SizeOfImage = sect_size - base_sect_offset;
173  lldb::addr_t next_sect_addr = sect_addr + sect_size;
174  Address sect_so_addr;
175  target.ResolveLoadAddress(next_sect_addr, sect_so_addr);
176  lldb::SectionSP next_sect_sp = sect_so_addr.GetSection();
177  while (next_sect_sp &&
178  next_sect_sp->GetLoadBaseAddress(&target) == next_sect_addr) {
179  sect_size = sect_sp->GetByteSize();
180  SizeOfImage += sect_size;
181  next_sect_addr += sect_size;
182  target.ResolveLoadAddress(next_sect_addr, sect_so_addr);
183  next_sect_sp = sect_so_addr.GetSection();
184  }
185 
186  return SizeOfImage;
187 }
188 
189 // ModuleList stream consists of a number of modules, followed by an array
190 // of llvm::minidump::Module's structures. Every structure informs about a
191 // single module. Additional data of variable length, such as module's names,
192 // are stored just after the ModuleList stream. The llvm::minidump::Module
193 // structures point to this helper data by global offset.
195  constexpr size_t minidump_module_size = sizeof(llvm::minidump::Module);
196  Status error;
197 
198  const ModuleList &modules = target.GetImages();
199  llvm::support::ulittle32_t modules_count =
200  static_cast<llvm::support::ulittle32_t>(modules.GetSize());
201 
202  // This helps us with getting the correct global offset in minidump
203  // file later, when we will be setting up offsets from the
204  // the llvm::minidump::Module's structures into helper data
205  size_t size_before = GetCurrentDataEndOffset();
206 
207  // This is the size of the main part of the ModuleList stream.
208  // It consists of a module number and corresponding number of
209  // structs describing individual modules
210  size_t module_stream_size =
211  sizeof(llvm::support::ulittle32_t) + modules_count * minidump_module_size;
212 
213  // Adding directory describing this stream.
214  AddDirectory(StreamType::ModuleList, module_stream_size);
215 
216  m_data.AppendData(&modules_count, sizeof(llvm::support::ulittle32_t));
217 
218  // Temporary storage for the helper data (of variable length)
219  // as these cannot be dumped to m_data before dumping entire
220  // array of module structures.
221  DataBufferHeap helper_data;
222 
223  for (size_t i = 0; i < modules_count; ++i) {
224  ModuleSP mod = modules.GetModuleAtIndex(i);
225  std::string module_name = mod->GetSpecificationDescription();
226  auto maybe_mod_size = getModuleFileSize(target, mod);
227  if (!maybe_mod_size) {
228  error.SetErrorStringWithFormat("Unable to get the size of module %s.",
229  module_name.c_str());
230  return error;
231  }
232 
233  uint64_t mod_size = std::move(*maybe_mod_size);
234 
235  llvm::support::ulittle32_t signature =
236  static_cast<llvm::support::ulittle32_t>(
237  static_cast<uint32_t>(minidump::CvSignature::ElfBuildId));
238  auto uuid = mod->GetUUID().GetBytes();
239 
240  VSFixedFileInfo info;
241  info.Signature = static_cast<llvm::support::ulittle32_t>(0u);
242  info.StructVersion = static_cast<llvm::support::ulittle32_t>(0u);
243  info.FileVersionHigh = static_cast<llvm::support::ulittle32_t>(0u);
244  info.FileVersionLow = static_cast<llvm::support::ulittle32_t>(0u);
245  info.ProductVersionHigh = static_cast<llvm::support::ulittle32_t>(0u);
246  info.ProductVersionLow = static_cast<llvm::support::ulittle32_t>(0u);
247  info.FileFlagsMask = static_cast<llvm::support::ulittle32_t>(0u);
248  info.FileFlags = static_cast<llvm::support::ulittle32_t>(0u);
249  info.FileOS = static_cast<llvm::support::ulittle32_t>(0u);
250  info.FileType = static_cast<llvm::support::ulittle32_t>(0u);
251  info.FileSubtype = static_cast<llvm::support::ulittle32_t>(0u);
252  info.FileDateHigh = static_cast<llvm::support::ulittle32_t>(0u);
253  info.FileDateLow = static_cast<llvm::support::ulittle32_t>(0u);
254 
255  LocationDescriptor ld;
256  ld.DataSize = static_cast<llvm::support::ulittle32_t>(0u);
257  ld.RVA = static_cast<llvm::support::ulittle32_t>(0u);
258 
259  // Setting up LocationDescriptor for uuid string. The global offset into
260  // minidump file is calculated.
261  LocationDescriptor ld_cv;
262  ld_cv.DataSize = static_cast<llvm::support::ulittle32_t>(
263  sizeof(llvm::support::ulittle32_t) + uuid.size());
264  ld_cv.RVA = static_cast<llvm::support::ulittle32_t>(
265  size_before + module_stream_size + helper_data.GetByteSize());
266 
267  helper_data.AppendData(&signature, sizeof(llvm::support::ulittle32_t));
268  helper_data.AppendData(uuid.begin(), uuid.size());
269 
270  llvm::minidump::Module m;
271  m.BaseOfImage = static_cast<llvm::support::ulittle64_t>(
272  mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target));
273  m.SizeOfImage = static_cast<llvm::support::ulittle32_t>(mod_size);
274  m.Checksum = static_cast<llvm::support::ulittle32_t>(0);
275  m.TimeDateStamp =
276  static_cast<llvm::support::ulittle32_t>(std::time(nullptr));
277  m.ModuleNameRVA = static_cast<llvm::support::ulittle32_t>(
278  size_before + module_stream_size + helper_data.GetByteSize());
279  m.VersionInfo = info;
280  m.CvRecord = ld_cv;
281  m.MiscRecord = ld;
282 
283  error = WriteString(module_name, &helper_data);
284 
285  if (error.Fail())
286  return error;
287 
288  m_data.AppendData(&m, sizeof(llvm::minidump::Module));
289  }
290 
291  m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize());
292  return error;
293 }
294 
296  const std::string &reg_name) {
297  const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
298  if (!reg_info)
299  return 0;
300  lldb_private::RegisterValue reg_value;
301  bool success = reg_ctx->ReadRegister(reg_info, reg_value);
302  if (!success)
303  return 0;
304  return reg_value.GetAsUInt16();
305 }
306 
308  const std::string &reg_name) {
309  const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
310  if (!reg_info)
311  return 0;
312  lldb_private::RegisterValue reg_value;
313  bool success = reg_ctx->ReadRegister(reg_info, reg_value);
314  if (!success)
315  return 0;
316  return reg_value.GetAsUInt32();
317 }
318 
320  const std::string &reg_name) {
321  const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
322  if (!reg_info)
323  return 0;
324  lldb_private::RegisterValue reg_value;
325  bool success = reg_ctx->ReadRegister(reg_info, reg_value);
326  if (!success)
327  return 0;
328  return reg_value.GetAsUInt64();
329 }
330 
331 llvm::support::ulittle16_t read_register_u16(RegisterContext *reg_ctx,
332  const std::string &reg_name) {
333  return static_cast<llvm::support::ulittle16_t>(
334  read_register_u16_raw(reg_ctx, reg_name));
335 }
336 
337 llvm::support::ulittle32_t read_register_u32(RegisterContext *reg_ctx,
338  const std::string &reg_name) {
339  return static_cast<llvm::support::ulittle32_t>(
340  read_register_u32_raw(reg_ctx, reg_name));
341 }
342 
343 llvm::support::ulittle64_t read_register_u64(RegisterContext *reg_ctx,
344  const std::string &reg_name) {
345  return static_cast<llvm::support::ulittle64_t>(
346  read_register_u64_raw(reg_ctx, reg_name));
347 }
348 
352  thread_context.p1_home = {};
353  thread_context.context_flags = static_cast<uint32_t>(
358  thread_context.rax = read_register_u64(reg_ctx, "rax");
359  thread_context.rbx = read_register_u64(reg_ctx, "rbx");
360  thread_context.rcx = read_register_u64(reg_ctx, "rcx");
361  thread_context.rdx = read_register_u64(reg_ctx, "rdx");
362  thread_context.rdi = read_register_u64(reg_ctx, "rdi");
363  thread_context.rsi = read_register_u64(reg_ctx, "rsi");
364  thread_context.rbp = read_register_u64(reg_ctx, "rbp");
365  thread_context.rsp = read_register_u64(reg_ctx, "rsp");
366  thread_context.r8 = read_register_u64(reg_ctx, "r8");
367  thread_context.r9 = read_register_u64(reg_ctx, "r9");
368  thread_context.r10 = read_register_u64(reg_ctx, "r10");
369  thread_context.r11 = read_register_u64(reg_ctx, "r11");
370  thread_context.r12 = read_register_u64(reg_ctx, "r12");
371  thread_context.r13 = read_register_u64(reg_ctx, "r13");
372  thread_context.r14 = read_register_u64(reg_ctx, "r14");
373  thread_context.r15 = read_register_u64(reg_ctx, "r15");
374  thread_context.rip = read_register_u64(reg_ctx, "rip");
375  thread_context.eflags = read_register_u32(reg_ctx, "rflags");
376  thread_context.cs = read_register_u16(reg_ctx, "cs");
377  thread_context.fs = read_register_u16(reg_ctx, "fs");
378  thread_context.gs = read_register_u16(reg_ctx, "gs");
379  thread_context.ss = read_register_u16(reg_ctx, "ss");
380  thread_context.ds = read_register_u16(reg_ctx, "ds");
381  return thread_context;
382 }
383 
384 // Function returns start and size of the memory region that contains
385 // memory location pointed to by the current stack pointer.
386 llvm::Expected<std::pair<addr_t, addr_t>>
387 findStackHelper(const lldb::ProcessSP &process_sp, uint64_t rsp) {
388  MemoryRegionInfo range_info;
389  Status error = process_sp->GetMemoryRegionInfo(rsp, range_info);
390  // Skip failed memory region requests or any regions with no permissions.
391  if (error.Fail() || range_info.GetLLDBPermissions() == 0)
392  return llvm::createStringError(
393  std::errc::not_supported,
394  "unable to load stack segment of the process");
395 
396  const addr_t addr = range_info.GetRange().GetRangeBase();
397  const addr_t size = range_info.GetRange().GetByteSize();
398 
399  if (size == 0)
400  return llvm::createStringError(std::errc::not_supported,
401  "stack segment of the process is empty");
402 
403  return std::make_pair(addr, size);
404 }
405 
406 Status MinidumpFileBuilder::AddThreadList(const lldb::ProcessSP &process_sp) {
407  constexpr size_t minidump_thread_size = sizeof(llvm::minidump::Thread);
408  lldb_private::ThreadList thread_list = process_sp->GetThreadList();
409 
410  // size of the entire thread stream consists of:
411  // number of threads and threads array
412  size_t thread_stream_size = sizeof(llvm::support::ulittle32_t) +
413  thread_list.GetSize() * minidump_thread_size;
414  // save for the ability to set up RVA
415  size_t size_before = GetCurrentDataEndOffset();
416 
417  AddDirectory(StreamType::ThreadList, thread_stream_size);
418 
419  llvm::support::ulittle32_t thread_count =
420  static_cast<llvm::support::ulittle32_t>(thread_list.GetSize());
421  m_data.AppendData(&thread_count, sizeof(llvm::support::ulittle32_t));
422 
423  DataBufferHeap helper_data;
424 
425  const uint32_t num_threads = thread_list.GetSize();
426 
427  for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
428  ThreadSP thread_sp(thread_list.GetThreadAtIndex(thread_idx));
429  RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
430  Status error;
431 
432  if (!reg_ctx_sp) {
433  error.SetErrorString("Unable to get the register context.");
434  return error;
435  }
436  RegisterContext *reg_ctx = reg_ctx_sp.get();
437  auto thread_context = GetThreadContext_64(reg_ctx);
438  uint64_t rsp = read_register_u64_raw(reg_ctx, "rsp");
439  auto expected_address_range = findStackHelper(process_sp, rsp);
440 
441  if (!expected_address_range) {
442  error.SetErrorString("Unable to get the stack address.");
443  return error;
444  }
445 
446  std::pair<uint64_t, uint64_t> range = std::move(*expected_address_range);
447  uint64_t addr = range.first;
448  uint64_t size = range.second;
449 
450  auto data_up = std::make_unique<DataBufferHeap>(size, 0);
451  const size_t stack_bytes_read =
452  process_sp->ReadMemory(addr, data_up->GetBytes(), size, error);
453 
454  if (error.Fail())
455  return error;
456 
457  LocationDescriptor stack_memory;
458  stack_memory.DataSize =
459  static_cast<llvm::support::ulittle32_t>(stack_bytes_read);
460  stack_memory.RVA = static_cast<llvm::support::ulittle32_t>(
461  size_before + thread_stream_size + helper_data.GetByteSize());
462 
463  MemoryDescriptor stack;
464  stack.StartOfMemoryRange = static_cast<llvm::support::ulittle64_t>(addr);
465  stack.Memory = stack_memory;
466 
467  helper_data.AppendData(data_up->GetBytes(), stack_bytes_read);
468 
469  LocationDescriptor thread_context_memory_locator;
470  thread_context_memory_locator.DataSize =
471  static_cast<llvm::support::ulittle32_t>(sizeof(thread_context));
472  thread_context_memory_locator.RVA = static_cast<llvm::support::ulittle32_t>(
473  size_before + thread_stream_size + helper_data.GetByteSize());
474 
475  helper_data.AppendData(
476  &thread_context,
478 
479  llvm::minidump::Thread t;
480  t.ThreadId = static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
481  t.SuspendCount = static_cast<llvm::support::ulittle32_t>(
482  (thread_sp->GetState() == StateType::eStateSuspended) ? 1 : 0);
483  t.PriorityClass = static_cast<llvm::support::ulittle32_t>(0);
484  t.Priority = static_cast<llvm::support::ulittle32_t>(0);
485  t.EnvironmentBlock = static_cast<llvm::support::ulittle64_t>(0);
486  t.Stack = stack, t.Context = thread_context_memory_locator;
487 
488  m_data.AppendData(&t, sizeof(llvm::minidump::Thread));
489  }
490 
491  m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize());
492  return Status();
493 }
494 
495 Status MinidumpFileBuilder::AddException(const lldb::ProcessSP &process_sp) {
496  Status error;
497  lldb_private::ThreadList thread_list = process_sp->GetThreadList();
498 
499  const uint32_t num_threads = thread_list.GetSize();
500  uint32_t stop_reason_thread_idx = 0;
501  for (stop_reason_thread_idx = 0; stop_reason_thread_idx < num_threads;
502  ++stop_reason_thread_idx) {
503  ThreadSP thread_sp(thread_list.GetThreadAtIndex(stop_reason_thread_idx));
504  StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
505 
506  if (stop_info_sp && stop_info_sp->IsValid())
507  break;
508  }
509 
510  if (stop_reason_thread_idx == num_threads) {
511  error.SetErrorString("No stop reason thread found.");
512  return error;
513  }
514 
515  constexpr size_t minidump_exception_size =
516  sizeof(llvm::minidump::ExceptionStream);
517  AddDirectory(StreamType::Exception, minidump_exception_size);
518  size_t size_before = GetCurrentDataEndOffset();
519 
520  ThreadSP thread_sp(thread_list.GetThreadAtIndex(stop_reason_thread_idx));
521  RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
522  RegisterContext *reg_ctx = reg_ctx_sp.get();
523  auto thread_context = GetThreadContext_64(reg_ctx);
524  StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
525 
526  DataBufferHeap helper_data;
527 
528  LocationDescriptor thread_context_memory_locator;
529  thread_context_memory_locator.DataSize =
530  static_cast<llvm::support::ulittle32_t>(sizeof(thread_context));
531  thread_context_memory_locator.RVA = static_cast<llvm::support::ulittle32_t>(
532  size_before + minidump_exception_size + helper_data.GetByteSize());
533 
534  helper_data.AppendData(
535  &thread_context, sizeof(lldb_private::minidump::MinidumpContext_x86_64));
536 
537  Exception exp_record = {};
538  exp_record.ExceptionCode =
539  static_cast<llvm::support::ulittle32_t>(stop_info_sp->GetValue());
540  exp_record.ExceptionFlags = static_cast<llvm::support::ulittle32_t>(0);
541  exp_record.ExceptionRecord = static_cast<llvm::support::ulittle64_t>(0);
542  exp_record.ExceptionAddress = read_register_u64(reg_ctx, "rip");
543  exp_record.NumberParameters = static_cast<llvm::support::ulittle32_t>(0);
544  exp_record.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
545  // exp_record.ExceptionInformation;
546 
547  ExceptionStream exp_stream;
548  exp_stream.ThreadId =
549  static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
550  exp_stream.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
551  exp_stream.ExceptionRecord = exp_record;
552  exp_stream.ThreadContext = thread_context_memory_locator;
553 
554  m_data.AppendData(&exp_stream, minidump_exception_size);
555  m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize());
556  return error;
557 }
558 
560 MinidumpFileBuilder::AddMemoryList(const lldb::ProcessSP &process_sp) {
561  Status error;
562 
563  if (error.Fail()) {
564  error.SetErrorString("Process doesn't support getting memory region info.");
565  return error;
566  }
567 
568  // Get interesting addresses
569  std::vector<size_t> interesting_addresses;
570  auto thread_list = process_sp->GetThreadList();
571  for (size_t i = 0; i < thread_list.GetSize(); ++i) {
572  ThreadSP thread_sp(thread_list.GetThreadAtIndex(i));
573  RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
574  RegisterContext *reg_ctx = reg_ctx_sp.get();
575 
576  interesting_addresses.push_back(read_register_u64(reg_ctx, "rsp"));
577  interesting_addresses.push_back(read_register_u64(reg_ctx, "rip"));
578  }
579 
580  DataBufferHeap helper_data;
581  std::vector<MemoryDescriptor> mem_descriptors;
582 
583  std::set<addr_t> visited_region_base_addresses;
584  for (size_t interesting_address : interesting_addresses) {
585  MemoryRegionInfo range_info;
586  error = process_sp->GetMemoryRegionInfo(interesting_address, range_info);
587  // Skip failed memory region requests or any regions with no permissions.
588  if (error.Fail() || range_info.GetLLDBPermissions() == 0)
589  continue;
590  const addr_t addr = range_info.GetRange().GetRangeBase();
591  // Skip any regions we have already saved out.
592  if (visited_region_base_addresses.insert(addr).second == false)
593  continue;
594  const addr_t size = range_info.GetRange().GetByteSize();
595  if (size == 0)
596  continue;
597  auto data_up = std::make_unique<DataBufferHeap>(size, 0);
598  const size_t bytes_read =
599  process_sp->ReadMemory(addr, data_up->GetBytes(), size, error);
600  if (bytes_read == 0)
601  continue;
602  // We have a good memory region with valid bytes to store.
603  LocationDescriptor memory_dump;
604  memory_dump.DataSize = static_cast<llvm::support::ulittle32_t>(bytes_read);
605  memory_dump.RVA =
606  static_cast<llvm::support::ulittle32_t>(GetCurrentDataEndOffset());
607  MemoryDescriptor memory_desc;
608  memory_desc.StartOfMemoryRange =
609  static_cast<llvm::support::ulittle64_t>(addr);
610  memory_desc.Memory = memory_dump;
611  mem_descriptors.push_back(memory_desc);
612  m_data.AppendData(data_up->GetBytes(), bytes_read);
613  }
614 
615  AddDirectory(StreamType::MemoryList,
616  sizeof(llvm::support::ulittle32_t) +
617  mem_descriptors.size() *
618  sizeof(llvm::minidump::MemoryDescriptor));
619  llvm::support::ulittle32_t memory_ranges_num(mem_descriptors.size());
620 
621  m_data.AppendData(&memory_ranges_num, sizeof(llvm::support::ulittle32_t));
622  for (auto memory_descriptor : mem_descriptors) {
623  m_data.AppendData(&memory_descriptor,
624  sizeof(llvm::minidump::MemoryDescriptor));
625  }
626 
627  return error;
628 }
629 
630 void MinidumpFileBuilder::AddMiscInfo(const lldb::ProcessSP &process_sp) {
631  AddDirectory(StreamType::MiscInfo,
633 
635  misc_info.size = static_cast<llvm::support::ulittle32_t>(
637  // Default set flags1 to 0, in case that we will not be able to
638  // get any information
639  misc_info.flags1 = static_cast<llvm::support::ulittle32_t>(0);
640 
642  process_sp->GetProcessInfo(process_info);
643  if (process_info.ProcessIDIsValid()) {
644  // Set flags1 to reflect that PID is filled in
645  misc_info.flags1 =
646  static_cast<llvm::support::ulittle32_t>(static_cast<uint32_t>(
648  misc_info.process_id =
649  static_cast<llvm::support::ulittle32_t>(process_info.GetProcessID());
650  }
651 
652  m_data.AppendData(&misc_info,
654 }
655 
656 std::unique_ptr<llvm::MemoryBuffer>
658  auto maybe_stream = llvm::MemoryBuffer::getFileAsStream(path);
659  if (!maybe_stream)
660  return nullptr;
661  return std::move(maybe_stream.get());
662 }
663 
665  const lldb::ProcessSP &process_sp) {
666  std::vector<std::pair<StreamType, std::string>> files_with_stream_types = {
667  {StreamType::LinuxCPUInfo, "/proc/cpuinfo"},
668  {StreamType::LinuxLSBRelease, "/etc/lsb-release"},
669  };
670 
672  process_sp->GetProcessInfo(process_info);
673  if (process_info.ProcessIDIsValid()) {
674  lldb::pid_t pid = process_info.GetProcessID();
675  std::string pid_str = std::to_string(pid);
676  files_with_stream_types.push_back(
677  {StreamType::LinuxProcStatus, "/proc/" + pid_str + "/status"});
678  files_with_stream_types.push_back(
679  {StreamType::LinuxCMDLine, "/proc/" + pid_str + "/cmdline"});
680  files_with_stream_types.push_back(
681  {StreamType::LinuxEnviron, "/proc/" + pid_str + "/environ"});
682  files_with_stream_types.push_back(
683  {StreamType::LinuxAuxv, "/proc/" + pid_str + "/auxv"});
684  files_with_stream_types.push_back(
685  {StreamType::LinuxMaps, "/proc/" + pid_str + "/maps"});
686  files_with_stream_types.push_back(
687  {StreamType::LinuxProcStat, "/proc/" + pid_str + "/stat"});
688  files_with_stream_types.push_back(
689  {StreamType::LinuxProcFD, "/proc/" + pid_str + "/fd"});
690  }
691 
692  for (const auto &entry : files_with_stream_types) {
693  StreamType stream = entry.first;
694  std::string path = entry.second;
695  auto memory_buffer = getFileStreamHelper(path);
696 
697  if (memory_buffer) {
698  size_t size = memory_buffer->getBufferSize();
699  if (size == 0)
700  continue;
701  AddDirectory(stream, size);
702  m_data.AppendData(memory_buffer->getBufferStart(), size);
703  }
704  }
705 }
706 
707 Status MinidumpFileBuilder::Dump(lldb::FileUP &core_file) const {
708  constexpr size_t header_size = sizeof(llvm::minidump::Header);
709  constexpr size_t directory_size = sizeof(llvm::minidump::Directory);
710 
711  // write header
712  llvm::minidump::Header header;
713  header.Signature = static_cast<llvm::support::ulittle32_t>(
714  llvm::minidump::Header::MagicSignature);
715  header.Version = static_cast<llvm::support::ulittle32_t>(
716  llvm::minidump::Header::MagicVersion);
717  header.NumberOfStreams =
718  static_cast<llvm::support::ulittle32_t>(GetDirectoriesNum());
719  header.StreamDirectoryRVA =
720  static_cast<llvm::support::ulittle32_t>(GetCurrentDataEndOffset());
721  header.Checksum = static_cast<llvm::support::ulittle32_t>(
722  0u), // not used in most of the writers
723  header.TimeDateStamp =
724  static_cast<llvm::support::ulittle32_t>(std::time(nullptr));
725  header.Flags =
726  static_cast<llvm::support::ulittle64_t>(0u); // minidump normal flag
727 
728  Status error;
729  size_t bytes_written;
730 
731  bytes_written = header_size;
732  error = core_file->Write(&header, bytes_written);
733  if (error.Fail() || bytes_written != header_size) {
734  if (bytes_written != header_size)
735  error.SetErrorStringWithFormat(
736  "unable to write the header (written %zd/%zd)", bytes_written,
737  header_size);
738  return error;
739  }
740 
741  // write data
742  bytes_written = m_data.GetByteSize();
743  error = core_file->Write(m_data.GetBytes(), bytes_written);
744  if (error.Fail() || bytes_written != m_data.GetByteSize()) {
745  if (bytes_written != m_data.GetByteSize())
746  error.SetErrorStringWithFormat(
747  "unable to write the data (written %zd/%" PRIu64 ")", bytes_written,
748  m_data.GetByteSize());
749  return error;
750  }
751 
752  // write directories
753  for (const Directory &dir : m_directories) {
754  bytes_written = directory_size;
755  error = core_file->Write(&dir, bytes_written);
756  if (error.Fail() || bytes_written != directory_size) {
757  if (bytes_written != directory_size)
758  error.SetErrorStringWithFormat(
759  "unable to write the directory (written %zd/%zd)", bytes_written,
760  directory_size);
761  return error;
762  }
763  }
764 
765  return error;
766 }
767 
769  return m_directories.size();
770 }
771 
773  return sizeof(llvm::minidump::Header) + m_data.GetByteSize();
774 }
lldb_private::ProcessInstanceInfo
Definition: ProcessInfo.h:106
lldb_private::minidump::MinidumpContext_x86_64_Flags::Integer
@ Integer
getFileStreamHelper
std::unique_ptr< llvm::MemoryBuffer > getFileStreamHelper(const std::string &path)
Definition: MinidumpFileBuilder.cpp:657
lldb_private::Range::GetRangeBase
BaseType GetRangeBase() const
Definition: RangeMap.h:46
lldb_private::minidump::MinidumpMiscInfo
Definition: MinidumpTypes.h:75
lldb_private::DataBufferHeap::GetByteSize
lldb::offset_t GetByteSize() const override
Definition: DataBufferHeap.cpp:43
GetThreadContext_64
lldb_private::minidump::MinidumpContext_x86_64 GetThreadContext_64(RegisterContext *reg_ctx)
Definition: MinidumpFileBuilder.cpp:350
lldb_private::ProcessInfo::ProcessIDIsValid
bool ProcessIDIsValid() const
Definition: ProcessInfo.h:70
lldb_private::DataBufferHeap::AppendData
void AppendData(const void *src, uint64_t src_len)
Definition: DataBufferHeap.cpp:61
MinidumpFileBuilder::AddMemoryList
lldb_private::Status AddMemoryList(const lldb::ProcessSP &process_sp)
Definition: MinidumpFileBuilder.cpp:560
MinidumpFileBuilder::AddMiscInfo
void AddMiscInfo(const lldb::ProcessSP &process_sp)
Definition: MinidumpFileBuilder.cpp:630
lldb_private::RegisterValue
Definition: RegisterValue.h:28
lldb_private::minidump::MinidumpContext_x86_64::rsi
llvm::support::ulittle64_t rsi
Definition: RegisterContextMinidump_x86_64.h:116
lldb_private::minidump::MinidumpMiscInfoFlags::ProcessID
@ ProcessID
lldb_private::minidump::MinidumpMiscInfo::process_id
llvm::support::ulittle32_t process_id
Definition: MinidumpTypes.h:79
lldb_private::minidump::MinidumpContext_x86_64::r14
llvm::support::ulittle64_t r14
Definition: RegisterContextMinidump_x86_64.h:124
MinidumpTypes.h
lldb_private::RegisterContext::ReadRegister
virtual bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)=0
read_register_u32_raw
uint32_t read_register_u32_raw(RegisterContext *reg_ctx, const std::string &reg_name)
Definition: MinidumpFileBuilder.cpp:307
lldb_private::MemoryRegionInfo::GetLLDBPermissions
uint32_t GetLLDBPermissions() const
Definition: MemoryRegionInfo.h:82
Module.h
lldb_private::minidump::MinidumpContext_x86_64
Definition: RegisterContextMinidump_x86_64.h:63
lldb_private::minidump::MinidumpContext_x86_64::r15
llvm::support::ulittle64_t r15
Definition: RegisterContextMinidump_x86_64.h:125
lldb_private::ProcessInfo::GetProcessID
lldb::pid_t GetProcessID() const
Definition: ProcessInfo.h:66
RegisterValue.h
lldb_private::MemoryRegionInfo
Definition: MemoryRegionInfo.h:21
read_register_u16_raw
uint16_t read_register_u16_raw(RegisterContext *reg_ctx, const std::string &reg_name)
Definition: MinidumpFileBuilder.cpp:295
lldb_private::minidump::MinidumpContext_x86_64::fs
llvm::support::ulittle16_t fs
Definition: RegisterContextMinidump_x86_64.h:85
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
lldb_private::minidump::MinidumpContext_x86_64::rcx
llvm::support::ulittle64_t rcx
Definition: RegisterContextMinidump_x86_64.h:105
lldb_private::minidump::MinidumpContext_x86_64::context_flags
llvm::support::ulittle32_t context_flags
Definition: RegisterContextMinidump_x86_64.h:74
lldb_private::Target::ResolveLoadAddress
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, uint32_t stop_id=SectionLoadHistory::eStopIDNow)
Definition: Target.cpp:2973
lldb_private::Target
Definition: Target.h:469
Section.h
read_register_u64
llvm::support::ulittle64_t read_register_u64(RegisterContext *reg_ctx, const std::string &reg_name)
Definition: MinidumpFileBuilder.cpp:343
lldb_private::Target::GetImages
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:947
lldb_private::minidump::MinidumpContext_x86_64::p1_home
llvm::support::ulittle64_t p1_home
Definition: RegisterContextMinidump_x86_64.h:65
MinidumpFileBuilder::AddException
lldb_private::Status AddException(const lldb::ProcessSP &process_sp)
Definition: MinidumpFileBuilder.cpp:495
Process.h
lldb_private::RegisterValue::GetAsUInt64
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
Definition: RegisterValue.cpp:556
lldb_private::minidump::MinidumpContext_x86_64::eflags
llvm::support::ulittle32_t eflags
Definition: RegisterContextMinidump_x86_64.h:91
lldb_private::minidump::MinidumpContext_x86_64::ss
llvm::support::ulittle16_t ss
Definition: RegisterContextMinidump_x86_64.h:90
lldb_private::minidump::MinidumpContext_x86_64::rbp
llvm::support::ulittle64_t rbp
Definition: RegisterContextMinidump_x86_64.h:115
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::ModuleList::GetSize
size_t GetSize() const
Gets the size of the module list.
Definition: ModuleList.cpp:635
lldb_private::minidump::MinidumpContext_x86_64::r8
llvm::support::ulittle64_t r8
Definition: RegisterContextMinidump_x86_64.h:118
ModuleList.h
lldb_private::minidump::MinidumpMiscInfo::size
llvm::support::ulittle32_t size
Definition: MinidumpTypes.h:76
MinidumpFileBuilder::GetCurrentDataEndOffset
size_t GetCurrentDataEndOffset() const
Definition: MinidumpFileBuilder.cpp:772
lldb_private::ModuleList
Definition: ModuleList.h:82
lldb_private::minidump::MinidumpContext_x86_64::gs
llvm::support::ulittle16_t gs
Definition: RegisterContextMinidump_x86_64.h:86
read_register_u32
llvm::support::ulittle32_t read_register_u32(RegisterContext *reg_ctx, const std::string &reg_name)
Definition: MinidumpFileBuilder.cpp:337
MemoryRegionInfo.h
lldb_private::RegisterValue::GetAsUInt16
uint16_t GetAsUInt16(uint16_t fail_value=UINT16_MAX, bool *success_ptr=nullptr) const
Definition: RegisterValue.cpp:500
lldb_private::ThreadList
Definition: ThreadList.h:26
lldb_private::minidump::MinidumpContext_x86_64_Flags::Control
@ Control
lldb_private::minidump::MinidumpContext_x86_64_Flags::Segments
@ Segments
lldb_private::minidump::MinidumpContext_x86_64::r13
llvm::support::ulittle64_t r13
Definition: RegisterContextMinidump_x86_64.h:123
lldb_private::minidump::MinidumpContext_x86_64::rip
llvm::support::ulittle64_t rip
Definition: RegisterContextMinidump_x86_64.h:129
RegisterContextMinidump_x86_64.h
ThreadList.h
lldb_private::minidump::MinidumpContext_x86_64::rdx
llvm::support::ulittle64_t rdx
Definition: RegisterContextMinidump_x86_64.h:106
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
lldb_private::ThreadList::GetThreadAtIndex
lldb::ThreadSP GetThreadAtIndex(uint32_t idx, bool can_update=true)
Definition: ThreadList.cpp:91
lldb_private::Address::GetSection
lldb::SectionSP GetSection() const
Get const accessor for the section.
Definition: Address.h:429
lldb_private::WindowsLog::Exception
@ Exception
MinidumpFileBuilder::AddThreadList
lldb_private::Status AddThreadList(const lldb::ProcessSP &process_sp)
Definition: MinidumpFileBuilder.cpp:406
lldb_private::RegisterContext
Definition: RegisterContext.h:17
read_register_u64_raw
uint64_t read_register_u64_raw(RegisterContext *reg_ctx, const std::string &reg_name)
Definition: MinidumpFileBuilder.cpp:319
MinidumpFileBuilder::Dump
lldb_private::Status Dump(lldb::FileUP &core_file) const
Definition: MinidumpFileBuilder.cpp:707
lldb_private::minidump::MinidumpContext_x86_64::rax
llvm::support::ulittle64_t rax
Definition: RegisterContextMinidump_x86_64.h:104
MinidumpFileBuilder::GetDirectoriesNum
size_t GetDirectoriesNum() const
Definition: MinidumpFileBuilder.cpp:768
lldb_private::minidump::MinidumpMiscInfo::flags1
llvm::support::ulittle32_t flags1
Definition: MinidumpTypes.h:78
lldb::eStateSuspended
@ eStateSuspended
Process or thread is in a suspended state as far as the debugger is concerned while other processes o...
Definition: lldb-enumerations.h:92
lldb_private::Status
Definition: Status.h:44
uint32_t
lldb_private::Address
Definition: Address.h:59
lldb::pid_t
uint64_t pid_t
Definition: lldb-types.h:85
lldb_private::minidump::MinidumpContext_x86_64_Flags::x86_64_Flag
@ x86_64_Flag
lldb_private::minidump::MinidumpContext_x86_64::rsp
llvm::support::ulittle64_t rsp
Definition: RegisterContextMinidump_x86_64.h:111
lldb_private::minidump::MinidumpContext_x86_64::r11
llvm::support::ulittle64_t r11
Definition: RegisterContextMinidump_x86_64.h:121
lldb_private::ThreadList::GetSize
uint32_t GetSize(bool can_update=true)
Definition: ThreadList.cpp:83
WriteString
Status WriteString(const std::string &to_write, lldb_private::DataBufferHeap *buffer)
Definition: MinidumpFileBuilder.cpp:129
lldb_private::minidump::MinidumpContext_x86_64::r9
llvm::support::ulittle64_t r9
Definition: RegisterContextMinidump_x86_64.h:119
lldb_private::Range::GetByteSize
SizeType GetByteSize() const
Definition: RangeMap.h:87
lldb_private::minidump::MinidumpContext_x86_64::rdi
llvm::support::ulittle64_t rdi
Definition: RegisterContextMinidump_x86_64.h:117
StopInfo.h
uint16_t
getModuleFileSize
llvm::Expected< uint64_t > getModuleFileSize(Target &target, const ModuleSP &mod)
Definition: MinidumpFileBuilder.cpp:154
DataExtractor.h
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
MinidumpFileBuilder::AddSystemInfo
lldb_private::Status AddSystemInfo(const llvm::Triple &target_triple)
Definition: MinidumpFileBuilder.cpp:50
lldb_private::minidump::MinidumpContext_x86_64::ds
llvm::support::ulittle16_t ds
Definition: RegisterContextMinidump_x86_64.h:83
lldb_private::ModuleList::GetModuleAtIndex
lldb::ModuleSP GetModuleAtIndex(size_t idx) const
Get the module shared pointer for the module at index idx.
Definition: ModuleList.cpp:411
MinidumpFileBuilder::AddModuleList
lldb_private::Status AddModuleList(lldb_private::Target &target)
Definition: MinidumpFileBuilder.cpp:194
MinidumpFileBuilder::AddDirectory
void AddDirectory(llvm::minidump::StreamType type, size_t stream_size)
Definition: MinidumpFileBuilder.cpp:37
MinidumpFileBuilder::AddLinuxFileStreams
void AddLinuxFileStreams(const lldb::ProcessSP &process_sp)
Definition: MinidumpFileBuilder.cpp:664
MinidumpFileBuilder.h
findStackHelper
llvm::Expected< std::pair< addr_t, addr_t > > findStackHelper(const lldb::ProcessSP &process_sp, uint64_t rsp)
Definition: MinidumpFileBuilder.cpp:387
lldb_private::minidump::MinidumpContext_x86_64::r10
llvm::support::ulittle64_t r10
Definition: RegisterContextMinidump_x86_64.h:120
lldb_private::DataBufferHeap
Definition: DataBufferHeap.h:30
lldb_private::RegisterValue::GetAsUInt32
uint32_t GetAsUInt32(uint32_t fail_value=UINT32_MAX, bool *success_ptr=nullptr) const
Definition: RegisterValue.cpp:526
read_register_u16
llvm::support::ulittle16_t read_register_u16(RegisterContext *reg_ctx, const std::string &reg_name)
Definition: MinidumpFileBuilder.cpp:331
lldb
Definition: SBAddress.h:15
lldb_private::minidump::MinidumpContext_x86_64::cs
llvm::support::ulittle16_t cs
Definition: RegisterContextMinidump_x86_64.h:79
RegisterContext.h
lldb_private::minidump::MinidumpContext_x86_64::rbx
llvm::support::ulittle64_t rbx
Definition: RegisterContextMinidump_x86_64.h:107
lldb_private::RegisterContext::GetRegisterInfoByName
const RegisterInfo * GetRegisterInfoByName(llvm::StringRef reg_name, uint32_t start_idx=0)
Definition: RegisterContext.cpp:52
rsp
@ rsp
Definition: CompactUnwindInfo.cpp:701
lldb_private::minidump::MinidumpContext_x86_64::r12
llvm::support::ulittle64_t r12
Definition: RegisterContextMinidump_x86_64.h:122