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