Bug Summary

File:tools/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
Warning:line 139, column 17
Called C++ object pointer is uninitialized

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name MinidumpParser.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-8/lib/clang/8.0.0 -D HAVE_ROUND -D LLDB_CONFIGURATION_RELEASE -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/lldb/source/Plugins/Process/minidump -I /build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/minidump -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/lldb/include -I /build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/include -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/include -I /build/llvm-toolchain-snapshot-8~svn345461/include -I /usr/include/python2.7 -I /build/llvm-toolchain-snapshot-8~svn345461/tools/clang/include -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/. -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/include/clang/8.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-8/lib/clang/8.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-deprecated-register -Wno-vla-extension -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/lldb/source/Plugins/Process/minidump -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-10-27-211344-32123-1 -x c++ /build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp -faddrsig

/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp

1//===-- MinidumpParser.cpp ---------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// Project includes
11#include "MinidumpParser.h"
12#include "NtStructures.h"
13#include "RegisterContextMinidump_x86_32.h"
14
15// Other libraries and framework includes
16#include "lldb/Target/MemoryRegionInfo.h"
17#include "lldb/Utility/LLDBAssert.h"
18
19// C includes
20// C++ includes
21#include <algorithm>
22#include <map>
23#include <vector>
24
25using namespace lldb_private;
26using namespace minidump;
27
28llvm::Optional<MinidumpParser>
29MinidumpParser::Create(const lldb::DataBufferSP &data_buf_sp) {
30 if (data_buf_sp->GetByteSize() < sizeof(MinidumpHeader)) {
31 return llvm::None;
32 }
33 return MinidumpParser(data_buf_sp);
34}
35
36MinidumpParser::MinidumpParser(const lldb::DataBufferSP &data_buf_sp)
37 : m_data_sp(data_buf_sp) {}
38
39llvm::ArrayRef<uint8_t> MinidumpParser::GetData() {
40 return llvm::ArrayRef<uint8_t>(m_data_sp->GetBytes(),
41 m_data_sp->GetByteSize());
42}
43
44llvm::ArrayRef<uint8_t>
45MinidumpParser::GetStream(MinidumpStreamType stream_type) {
46 auto iter = m_directory_map.find(static_cast<uint32_t>(stream_type));
47 if (iter == m_directory_map.end())
48 return {};
49
50 // check if there is enough data
51 if (iter->second.rva + iter->second.data_size > m_data_sp->GetByteSize())
52 return {};
53
54 return llvm::ArrayRef<uint8_t>(m_data_sp->GetBytes() + iter->second.rva,
55 iter->second.data_size);
56}
57
58llvm::Optional<std::string> MinidumpParser::GetMinidumpString(uint32_t rva) {
59 auto arr_ref = m_data_sp->GetData();
60 if (rva > arr_ref.size())
61 return llvm::None;
62 arr_ref = arr_ref.drop_front(rva);
63 return parseMinidumpString(arr_ref);
64}
65
66UUID MinidumpParser::GetModuleUUID(const MinidumpModule *module) {
67 auto cv_record =
68 GetData().slice(module->CV_record.rva, module->CV_record.data_size);
69
70 // Read the CV record signature
71 const llvm::support::ulittle32_t *signature = nullptr;
72 Status error = consumeObject(cv_record, signature);
73 if (error.Fail())
74 return UUID();
75
76 const CvSignature cv_signature =
77 static_cast<CvSignature>(static_cast<const uint32_t>(*signature));
78
79 if (cv_signature == CvSignature::Pdb70) {
80 // PDB70 record
81 const CvRecordPdb70 *pdb70_uuid = nullptr;
82 Status error = consumeObject(cv_record, pdb70_uuid);
83 if (!error.Fail()) {
84 auto arch = GetArchitecture();
85 // For Apple targets we only need a 16 byte UUID so that we can match
86 // the UUID in the Module to actual UUIDs from the built binaries. The
87 // "Age" field is zero in breakpad minidump files for Apple targets, so
88 // we restrict the UUID to the "Uuid" field so we have a UUID we can use
89 // to match.
90 if (arch.GetTriple().getVendor() == llvm::Triple::Apple)
91 return UUID::fromData(pdb70_uuid->Uuid, sizeof(pdb70_uuid->Uuid));
92 else
93 return UUID::fromData(pdb70_uuid, sizeof(*pdb70_uuid));
94 }
95 } else if (cv_signature == CvSignature::ElfBuildId)
96 return UUID::fromData(cv_record);
97
98 return UUID();
99}
100
101llvm::ArrayRef<MinidumpThread> MinidumpParser::GetThreads() {
102 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::ThreadList);
103
104 if (data.size() == 0)
105 return llvm::None;
106
107 return MinidumpThread::ParseThreadList(data);
108}
109
110llvm::ArrayRef<uint8_t>
111MinidumpParser::GetThreadContext(const MinidumpThread &td) {
112 if (td.thread_context.rva + td.thread_context.data_size > GetData().size())
113 return {};
114
115 return GetData().slice(td.thread_context.rva, td.thread_context.data_size);
116}
117
118llvm::ArrayRef<uint8_t>
119MinidumpParser::GetThreadContextWow64(const MinidumpThread &td) {
120 // On Windows, a 32-bit process can run on a 64-bit machine under WOW64. If
121 // the minidump was captured with a 64-bit debugger, then the CONTEXT we just
122 // grabbed from the mini_dump_thread is the one for the 64-bit "native"
123 // process rather than the 32-bit "guest" process we care about. In this
124 // case, we can get the 32-bit CONTEXT from the TEB (Thread Environment
125 // Block) of the 64-bit process.
126 auto teb_mem = GetMemory(td.teb, sizeof(TEB64));
127 if (teb_mem.empty())
1
Assuming the condition is false
2
Taking false branch
128 return {};
129
130 const TEB64 *wow64teb;
3
'wow64teb' declared without an initial value
131 Status error = consumeObject(teb_mem, wow64teb);
4
Calling 'consumeObject<lldb_private::minidump::TEB64>'
8
Returning from 'consumeObject<lldb_private::minidump::TEB64>'
132 if (error.Fail())
9
Assuming the condition is false
10
Taking false branch
133 return {};
134
135 // Slot 1 of the thread-local storage in the 64-bit TEB points to a structure
136 // that includes the 32-bit CONTEXT (after a ULONG). See:
137 // https://msdn.microsoft.com/en-us/library/ms681670.aspx
138 auto context =
139 GetMemory(wow64teb->tls_slots[1] + 4, sizeof(MinidumpContext_x86_32));
11
Called C++ object pointer is uninitialized
140 if (context.size() < sizeof(MinidumpContext_x86_32))
141 return {};
142
143 return context;
144 // NOTE: We don't currently use the TEB for anything else. If we
145 // need it in the future, the 32-bit TEB is located according to the address
146 // stored in the first slot of the 64-bit TEB (wow64teb.Reserved1[0]).
147}
148
149const MinidumpSystemInfo *MinidumpParser::GetSystemInfo() {
150 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::SystemInfo);
151
152 if (data.size() == 0)
153 return nullptr;
154
155 return MinidumpSystemInfo::Parse(data);
156}
157
158ArchSpec MinidumpParser::GetArchitecture() {
159 if (m_arch.IsValid())
160 return m_arch;
161
162 // Set the architecture in m_arch
163 const MinidumpSystemInfo *system_info = GetSystemInfo();
164
165 if (!system_info)
166 return m_arch;
167
168 // TODO what to do about big endiand flavors of arm ?
169 // TODO set the arm subarch stuff if the minidump has info about it
170
171 llvm::Triple triple;
172 triple.setVendor(llvm::Triple::VendorType::UnknownVendor);
173
174 const MinidumpCPUArchitecture arch =
175 static_cast<const MinidumpCPUArchitecture>(
176 static_cast<const uint32_t>(system_info->processor_arch));
177
178 switch (arch) {
179 case MinidumpCPUArchitecture::X86:
180 triple.setArch(llvm::Triple::ArchType::x86);
181 break;
182 case MinidumpCPUArchitecture::AMD64:
183 triple.setArch(llvm::Triple::ArchType::x86_64);
184 break;
185 case MinidumpCPUArchitecture::ARM:
186 triple.setArch(llvm::Triple::ArchType::arm);
187 break;
188 case MinidumpCPUArchitecture::ARM64:
189 triple.setArch(llvm::Triple::ArchType::aarch64);
190 break;
191 default:
192 triple.setArch(llvm::Triple::ArchType::UnknownArch);
193 break;
194 }
195
196 const MinidumpOSPlatform os = static_cast<const MinidumpOSPlatform>(
197 static_cast<const uint32_t>(system_info->platform_id));
198
199 // TODO add all of the OSes that Minidump/breakpad distinguishes?
200 switch (os) {
201 case MinidumpOSPlatform::Win32S:
202 case MinidumpOSPlatform::Win32Windows:
203 case MinidumpOSPlatform::Win32NT:
204 case MinidumpOSPlatform::Win32CE:
205 triple.setOS(llvm::Triple::OSType::Win32);
206 break;
207 case MinidumpOSPlatform::Linux:
208 triple.setOS(llvm::Triple::OSType::Linux);
209 break;
210 case MinidumpOSPlatform::MacOSX:
211 triple.setOS(llvm::Triple::OSType::MacOSX);
212 triple.setVendor(llvm::Triple::Apple);
213 break;
214 case MinidumpOSPlatform::IOS:
215 triple.setOS(llvm::Triple::OSType::IOS);
216 triple.setVendor(llvm::Triple::Apple);
217 break;
218 case MinidumpOSPlatform::Android:
219 triple.setOS(llvm::Triple::OSType::Linux);
220 triple.setEnvironment(llvm::Triple::EnvironmentType::Android);
221 break;
222 default: {
223 triple.setOS(llvm::Triple::OSType::UnknownOS);
224 std::string csd_version;
225 if (auto s = GetMinidumpString(system_info->csd_version_rva))
226 csd_version = *s;
227 if (csd_version.find("Linux") != std::string::npos)
228 triple.setOS(llvm::Triple::OSType::Linux);
229 break;
230 }
231 }
232 m_arch.SetTriple(triple);
233 return m_arch;
234}
235
236const MinidumpMiscInfo *MinidumpParser::GetMiscInfo() {
237 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::MiscInfo);
238
239 if (data.size() == 0)
240 return nullptr;
241
242 return MinidumpMiscInfo::Parse(data);
243}
244
245llvm::Optional<LinuxProcStatus> MinidumpParser::GetLinuxProcStatus() {
246 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::LinuxProcStatus);
247
248 if (data.size() == 0)
249 return llvm::None;
250
251 return LinuxProcStatus::Parse(data);
252}
253
254llvm::Optional<lldb::pid_t> MinidumpParser::GetPid() {
255 const MinidumpMiscInfo *misc_info = GetMiscInfo();
256 if (misc_info != nullptr) {
257 return misc_info->GetPid();
258 }
259
260 llvm::Optional<LinuxProcStatus> proc_status = GetLinuxProcStatus();
261 if (proc_status.hasValue()) {
262 return proc_status->GetPid();
263 }
264
265 return llvm::None;
266}
267
268llvm::ArrayRef<MinidumpModule> MinidumpParser::GetModuleList() {
269 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::ModuleList);
270
271 if (data.size() == 0)
272 return {};
273
274 return MinidumpModule::ParseModuleList(data);
275}
276
277std::vector<const MinidumpModule *> MinidumpParser::GetFilteredModuleList() {
278 llvm::ArrayRef<MinidumpModule> modules = GetModuleList();
279 // map module_name -> pair(load_address, pointer to module struct in memory)
280 llvm::StringMap<std::pair<uint64_t, const MinidumpModule *>> lowest_addr;
281
282 std::vector<const MinidumpModule *> filtered_modules;
283
284 llvm::Optional<std::string> name;
285 std::string module_name;
286
287 for (const auto &module : modules) {
288 name = GetMinidumpString(module.module_name_rva);
289
290 if (!name)
291 continue;
292
293 module_name = name.getValue();
294
295 auto iter = lowest_addr.end();
296 bool exists;
297 std::tie(iter, exists) = lowest_addr.try_emplace(
298 module_name, std::make_pair(module.base_of_image, &module));
299
300 if (exists && module.base_of_image < iter->second.first)
301 iter->second = std::make_pair(module.base_of_image, &module);
302 }
303
304 filtered_modules.reserve(lowest_addr.size());
305 for (const auto &module : lowest_addr) {
306 filtered_modules.push_back(module.second.second);
307 }
308
309 return filtered_modules;
310}
311
312const MinidumpExceptionStream *MinidumpParser::GetExceptionStream() {
313 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::Exception);
314
315 if (data.size() == 0)
316 return nullptr;
317
318 return MinidumpExceptionStream::Parse(data);
319}
320
321llvm::Optional<minidump::Range>
322MinidumpParser::FindMemoryRange(lldb::addr_t addr) {
323 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::MemoryList);
324 llvm::ArrayRef<uint8_t> data64 = GetStream(MinidumpStreamType::Memory64List);
325
326 if (data.empty() && data64.empty())
327 return llvm::None;
328
329 if (!data.empty()) {
330 llvm::ArrayRef<MinidumpMemoryDescriptor> memory_list =
331 MinidumpMemoryDescriptor::ParseMemoryList(data);
332
333 if (memory_list.empty())
334 return llvm::None;
335
336 for (const auto &memory_desc : memory_list) {
337 const MinidumpLocationDescriptor &loc_desc = memory_desc.memory;
338 const lldb::addr_t range_start = memory_desc.start_of_memory_range;
339 const size_t range_size = loc_desc.data_size;
340
341 if (loc_desc.rva + loc_desc.data_size > GetData().size())
342 return llvm::None;
343
344 if (range_start <= addr && addr < range_start + range_size) {
345 return minidump::Range(range_start,
346 GetData().slice(loc_desc.rva, range_size));
347 }
348 }
349 }
350
351 // Some Minidumps have a Memory64ListStream that captures all the heap memory
352 // (full-memory Minidumps). We can't exactly use the same loop as above,
353 // because the Minidump uses slightly different data structures to describe
354 // those
355
356 if (!data64.empty()) {
357 llvm::ArrayRef<MinidumpMemoryDescriptor64> memory64_list;
358 uint64_t base_rva;
359 std::tie(memory64_list, base_rva) =
360 MinidumpMemoryDescriptor64::ParseMemory64List(data64);
361
362 if (memory64_list.empty())
363 return llvm::None;
364
365 for (const auto &memory_desc64 : memory64_list) {
366 const lldb::addr_t range_start = memory_desc64.start_of_memory_range;
367 const size_t range_size = memory_desc64.data_size;
368
369 if (base_rva + range_size > GetData().size())
370 return llvm::None;
371
372 if (range_start <= addr && addr < range_start + range_size) {
373 return minidump::Range(range_start,
374 GetData().slice(base_rva, range_size));
375 }
376 base_rva += range_size;
377 }
378 }
379
380 return llvm::None;
381}
382
383llvm::ArrayRef<uint8_t> MinidumpParser::GetMemory(lldb::addr_t addr,
384 size_t size) {
385 // I don't have a sense of how frequently this is called or how many memory
386 // ranges a Minidump typically has, so I'm not sure if searching for the
387 // appropriate range linearly each time is stupid. Perhaps we should build
388 // an index for faster lookups.
389 llvm::Optional<minidump::Range> range = FindMemoryRange(addr);
390 if (!range)
391 return {};
392
393 // There's at least some overlap between the beginning of the desired range
394 // (addr) and the current range. Figure out where the overlap begins and how
395 // much overlap there is.
396
397 const size_t offset = addr - range->start;
398
399 if (addr < range->start || offset >= range->range_ref.size())
400 return {};
401
402 const size_t overlap = std::min(size, range->range_ref.size() - offset);
403 return range->range_ref.slice(offset, overlap);
404}
405
406llvm::Optional<MemoryRegionInfo>
407MinidumpParser::GetMemoryRegionInfo(lldb::addr_t load_addr) {
408 MemoryRegionInfo info;
409 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::MemoryInfoList);
410 if (data.empty())
411 return llvm::None;
412
413 std::vector<const MinidumpMemoryInfo *> mem_info_list =
414 MinidumpMemoryInfo::ParseMemoryInfoList(data);
415 if (mem_info_list.empty())
416 return llvm::None;
417
418 const auto yes = MemoryRegionInfo::eYes;
419 const auto no = MemoryRegionInfo::eNo;
420
421 const MinidumpMemoryInfo *next_entry = nullptr;
422 for (const auto &entry : mem_info_list) {
423 const auto head = entry->base_address;
424 const auto tail = head + entry->region_size;
425
426 if (head <= load_addr && load_addr < tail) {
427 info.GetRange().SetRangeBase(
428 (entry->state != uint32_t(MinidumpMemoryInfoState::MemFree))
429 ? head
430 : load_addr);
431 info.GetRange().SetRangeEnd(tail);
432
433 const uint32_t PageNoAccess =
434 static_cast<uint32_t>(MinidumpMemoryProtectionContants::PageNoAccess);
435 info.SetReadable((entry->protect & PageNoAccess) == 0 ? yes : no);
436
437 const uint32_t PageWritable =
438 static_cast<uint32_t>(MinidumpMemoryProtectionContants::PageWritable);
439 info.SetWritable((entry->protect & PageWritable) != 0 ? yes : no);
440
441 const uint32_t PageExecutable = static_cast<uint32_t>(
442 MinidumpMemoryProtectionContants::PageExecutable);
443 info.SetExecutable((entry->protect & PageExecutable) != 0 ? yes : no);
444
445 const uint32_t MemFree =
446 static_cast<uint32_t>(MinidumpMemoryInfoState::MemFree);
447 info.SetMapped((entry->state != MemFree) ? yes : no);
448
449 return info;
450 } else if (head > load_addr &&
451 (next_entry == nullptr || head < next_entry->base_address)) {
452 // In case there is no region containing load_addr keep track of the
453 // nearest region after load_addr so we can return the distance to it.
454 next_entry = entry;
455 }
456 }
457
458 // No containing region found. Create an unmapped region that extends to the
459 // next region or LLDB_INVALID_ADDRESS
460 info.GetRange().SetRangeBase(load_addr);
461 info.GetRange().SetRangeEnd((next_entry != nullptr) ? next_entry->base_address
462 : LLDB_INVALID_ADDRESS(18446744073709551615UL));
463 info.SetReadable(no);
464 info.SetWritable(no);
465 info.SetExecutable(no);
466 info.SetMapped(no);
467
468 // Note that the memory info list doesn't seem to contain ranges in kernel
469 // space, so if you're walking a stack that has kernel frames, the stack may
470 // appear truncated.
471 return info;
472}
473
474Status MinidumpParser::Initialize() {
475 Status error;
476
477 lldbassert(m_directory_map.empty())lldb_private::lldb_assert(static_cast<bool>(m_directory_map
.empty()), "m_directory_map.empty()", __FUNCTION__, "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp"
, 477)
;
478
479 llvm::ArrayRef<uint8_t> header_data(m_data_sp->GetBytes(),
480 sizeof(MinidumpHeader));
481 const MinidumpHeader *header = MinidumpHeader::Parse(header_data);
482 if (header == nullptr) {
483 error.SetErrorString("invalid minidump: can't parse the header");
484 return error;
485 }
486
487 // A minidump without at least one stream is clearly ill-formed
488 if (header->streams_count == 0) {
489 error.SetErrorString("invalid minidump: no streams present");
490 return error;
491 }
492
493 struct FileRange {
494 uint32_t offset = 0;
495 uint32_t size = 0;
496
497 FileRange(uint32_t offset, uint32_t size) : offset(offset), size(size) {}
498 uint32_t end() const { return offset + size; }
499 };
500
501 const uint32_t file_size = m_data_sp->GetByteSize();
502
503 // Build a global minidump file map, checking for:
504 // - overlapping streams/data structures
505 // - truncation (streams pointing past the end of file)
506 std::vector<FileRange> minidump_map;
507
508 // Add the minidump header to the file map
509 if (sizeof(MinidumpHeader) > file_size) {
510 error.SetErrorString("invalid minidump: truncated header");
511 return error;
512 }
513 minidump_map.emplace_back( 0, sizeof(MinidumpHeader) );
514
515 // Add the directory entries to the file map
516 FileRange directory_range(header->stream_directory_rva,
517 header->streams_count *
518 sizeof(MinidumpDirectory));
519 if (directory_range.end() > file_size) {
520 error.SetErrorString("invalid minidump: truncated streams directory");
521 return error;
522 }
523 minidump_map.push_back(directory_range);
524
525 // Parse stream directory entries
526 llvm::ArrayRef<uint8_t> directory_data(
527 m_data_sp->GetBytes() + directory_range.offset, directory_range.size);
528 for (uint32_t i = 0; i < header->streams_count; ++i) {
529 const MinidumpDirectory *directory_entry = nullptr;
530 error = consumeObject(directory_data, directory_entry);
531 if (error.Fail())
532 return error;
533 if (directory_entry->stream_type == 0) {
534 // Ignore dummy streams (technically ill-formed, but a number of
535 // existing minidumps seem to contain such streams)
536 if (directory_entry->location.data_size == 0)
537 continue;
538 error.SetErrorString("invalid minidump: bad stream type");
539 return error;
540 }
541 // Update the streams map, checking for duplicate stream types
542 if (!m_directory_map
543 .insert({directory_entry->stream_type, directory_entry->location})
544 .second) {
545 error.SetErrorString("invalid minidump: duplicate stream type");
546 return error;
547 }
548 // Ignore the zero-length streams for layout checks
549 if (directory_entry->location.data_size != 0) {
550 minidump_map.emplace_back(directory_entry->location.rva,
551 directory_entry->location.data_size);
552 }
553 }
554
555 // Sort the file map ranges by start offset
556 std::sort(minidump_map.begin(), minidump_map.end(),
557 [](const FileRange &a, const FileRange &b) {
558 return a.offset < b.offset;
559 });
560
561 // Check for overlapping streams/data structures
562 for (size_t i = 1; i < minidump_map.size(); ++i) {
563 const auto &prev_range = minidump_map[i - 1];
564 if (prev_range.end() > minidump_map[i].offset) {
565 error.SetErrorString("invalid minidump: overlapping streams");
566 return error;
567 }
568 }
569
570 // Check for streams past the end of file
571 const auto &last_range = minidump_map.back();
572 if (last_range.end() > file_size) {
573 error.SetErrorString("invalid minidump: truncated stream");
574 return error;
575 }
576
577 return error;
578}

/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/minidump/MinidumpTypes.h

1//===-- MinidumpTypes.h -----------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef liblldb_MinidumpTypes_h_
11#define liblldb_MinidumpTypes_h_
12
13// Project includes
14
15// Other libraries and framework includes
16#include "lldb/Utility/Status.h"
17
18#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/BitmaskEnum.h"
20#include "llvm/ADT/Optional.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/Support/ConvertUTF.h"
24#include "llvm/Support/Endian.h"
25
26// C includes
27// C++ includes
28
29// Reference:
30// https://msdn.microsoft.com/en-us/library/windows/desktop/ms679293(v=vs.85).aspx
31// https://chromium.googlesource.com/breakpad/breakpad/
32
33namespace lldb_private {
34
35namespace minidump {
36
37LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()using ::llvm::BitmaskEnumDetail::operator~; using ::llvm::BitmaskEnumDetail
::operator|; using ::llvm::BitmaskEnumDetail::operator&; using
::llvm::BitmaskEnumDetail::operator^; using ::llvm::BitmaskEnumDetail
::operator|=; using ::llvm::BitmaskEnumDetail::operator&=
; using ::llvm::BitmaskEnumDetail::operator^=
;
38
39enum class MinidumpHeaderConstants : uint32_t {
40 Signature = 0x504d444d, // 'PMDM'
41 Version = 0x0000a793, // 42899
42 LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Signature)LLVM_BITMASK_LARGEST_ENUMERATOR = Signature
43
44};
45
46enum class CvSignature : uint32_t {
47 Pdb70 = 0x53445352, // RSDS
48 ElfBuildId = 0x4270454c, // BpEL (Breakpad/Crashpad minidumps)
49};
50
51// Reference:
52// https://crashpad.chromium.org/doxygen/structcrashpad_1_1CodeViewRecordPDB70.html
53struct CvRecordPdb70 {
54 uint8_t Uuid[16];
55 llvm::support::ulittle32_t Age;
56 // char PDBFileName[];
57};
58static_assert(sizeof(CvRecordPdb70) == 20,
59 "sizeof CvRecordPdb70 is not correct!");
60
61// Reference:
62// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680394.aspx
63enum class MinidumpStreamType : uint32_t {
64 Unused = 0,
65 Reserved0 = 1,
66 Reserved1 = 2,
67 ThreadList = 3,
68 ModuleList = 4,
69 MemoryList = 5,
70 Exception = 6,
71 SystemInfo = 7,
72 ThreadExList = 8,
73 Memory64List = 9,
74 CommentA = 10,
75 CommentW = 11,
76 HandleData = 12,
77 FunctionTable = 13,
78 UnloadedModuleList = 14,
79 MiscInfo = 15,
80 MemoryInfoList = 16,
81 ThreadInfoList = 17,
82 HandleOperationList = 18,
83 Token = 19,
84 JavascriptData = 20,
85 SystemMemoryInfo = 21,
86 ProcessVMCounters = 22,
87 LastReserved = 0x0000ffff,
88
89 /* Breakpad extension types. 0x4767 = "Gg" */
90 BreakpadInfo = 0x47670001,
91 AssertionInfo = 0x47670002,
92 /* These are additional minidump stream values which are specific to
93 * the linux breakpad implementation. */
94 LinuxCPUInfo = 0x47670003, /* /proc/cpuinfo */
95 LinuxProcStatus = 0x47670004, /* /proc/$x/status */
96 LinuxLSBRelease = 0x47670005, /* /etc/lsb-release */
97 LinuxCMDLine = 0x47670006, /* /proc/$x/cmdline */
98 LinuxEnviron = 0x47670007, /* /proc/$x/environ */
99 LinuxAuxv = 0x47670008, /* /proc/$x/auxv */
100 LinuxMaps = 0x47670009, /* /proc/$x/maps */
101 LinuxDSODebug = 0x4767000A
102};
103
104// for MinidumpSystemInfo.processor_arch
105enum class MinidumpCPUArchitecture : uint16_t {
106 X86 = 0, /* PROCESSOR_ARCHITECTURE_INTEL */
107 MIPS = 1, /* PROCESSOR_ARCHITECTURE_MIPS */
108 Alpha = 2, /* PROCESSOR_ARCHITECTURE_ALPHA */
109 PPC = 3, /* PROCESSOR_ARCHITECTURE_PPC */
110 SHX = 4, /* PROCESSOR_ARCHITECTURE_SHX (Super-H) */
111 ARM = 5, /* PROCESSOR_ARCHITECTURE_ARM */
112 IA64 = 6, /* PROCESSOR_ARCHITECTURE_IA64 */
113 Alpha64 = 7, /* PROCESSOR_ARCHITECTURE_ALPHA64 */
114 MSIL = 8, /* PROCESSOR_ARCHITECTURE_MSIL
115 * (Microsoft Intermediate Language) */
116 AMD64 = 9, /* PROCESSOR_ARCHITECTURE_AMD64 */
117 X86Win64 = 10, /* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */
118 SPARC = 0x8001, /* Breakpad-defined value for SPARC */
119 PPC64 = 0x8002, /* Breakpad-defined value for PPC64 */
120 ARM64 = 0x8003, /* Breakpad-defined value for ARM64 */
121 MIPS64 = 0x8004, /* Breakpad-defined value for MIPS64 */
122 Unknown = 0xffff /* PROCESSOR_ARCHITECTURE_UNKNOWN */
123};
124
125// for MinidumpSystemInfo.platform_id
126enum class MinidumpOSPlatform : uint32_t {
127 Win32S = 0, /* VER_PLATFORM_WIN32s (Windows 3.1) */
128 Win32Windows = 1, /* VER_PLATFORM_WIN32_WINDOWS (Windows 95-98-Me) */
129 Win32NT = 2, /* VER_PLATFORM_WIN32_NT (Windows NT, 2000+) */
130 Win32CE = 3, /* VER_PLATFORM_WIN32_CE, VER_PLATFORM_WIN32_HH
131 * (Windows CE, Windows Mobile, "Handheld") */
132
133 /* The following values are Breakpad-defined. */
134 Unix = 0x8000, /* Generic Unix-ish */
135 MacOSX = 0x8101, /* Mac OS X/Darwin */
136 IOS = 0x8102, /* iOS */
137 Linux = 0x8201, /* Linux */
138 Solaris = 0x8202, /* Solaris */
139 Android = 0x8203, /* Android */
140 PS3 = 0x8204, /* PS3 */
141 NaCl = 0x8205 /* Native Client (NaCl) */
142};
143
144// For MinidumpCPUInfo.arm_cpu_info.elf_hwcaps.
145// This matches the Linux kernel definitions from <asm/hwcaps.h>
146enum class MinidumpPCPUInformationARMElfHwCaps : uint32_t {
147 SWP = (1 << 0),
148 Half = (1 << 1),
149 Thumb = (1 << 2),
150 _26BIT = (1 << 3),
151 FastMult = (1 << 4),
152 FPA = (1 << 5),
153 VFP = (1 << 6),
154 EDSP = (1 << 7),
155 Java = (1 << 8),
156 IWMMXT = (1 << 9),
157 Crunch = (1 << 10),
158 ThumbEE = (1 << 11),
159 Neon = (1 << 12),
160 VFPv3 = (1 << 13),
161 VFPv3D16 = (1 << 14),
162 TLS = (1 << 15),
163 VFPv4 = (1 << 16),
164 IDIVA = (1 << 17),
165 IDIVT = (1 << 18),
166 LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IDIVT)LLVM_BITMASK_LARGEST_ENUMERATOR = IDIVT
167};
168
169enum class MinidumpMiscInfoFlags : uint32_t {
170 ProcessID = (1 << 0),
171 ProcessTimes = (1 << 1),
172 LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ ProcessTimes)LLVM_BITMASK_LARGEST_ENUMERATOR = ProcessTimes
173};
174
175template <typename T>
176Status consumeObject(llvm::ArrayRef<uint8_t> &Buffer, const T *&Object) {
177 Status error;
178 if (Buffer.size() < sizeof(T)) {
5
Assuming the condition is true
6
Taking true branch
179 error.SetErrorString("Insufficient buffer!");
180 return error;
7
Returning without writing to 'Object'
181 }
182
183 Object = reinterpret_cast<const T *>(Buffer.data());
184 Buffer = Buffer.drop_front(sizeof(T));
185 return error;
186}
187
188// parse a MinidumpString which is with UTF-16
189// Reference:
190// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680395(v=vs.85).aspx
191llvm::Optional<std::string> parseMinidumpString(llvm::ArrayRef<uint8_t> &data);
192
193// Reference:
194// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680378(v=vs.85).aspx
195struct MinidumpHeader {
196 llvm::support::ulittle32_t signature;
197 llvm::support::ulittle32_t
198 version; // The high 16 bits of version field are implementation specific
199 llvm::support::ulittle32_t streams_count;
200 llvm::support::ulittle32_t
201 stream_directory_rva; // offset of the stream directory
202 llvm::support::ulittle32_t checksum;
203 llvm::support::ulittle32_t time_date_stamp; // time_t format
204 llvm::support::ulittle64_t flags;
205
206 static const MinidumpHeader *Parse(llvm::ArrayRef<uint8_t> &data);
207};
208static_assert(sizeof(MinidumpHeader) == 32,
209 "sizeof MinidumpHeader is not correct!");
210
211// Reference:
212// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680383.aspx
213struct MinidumpLocationDescriptor {
214 llvm::support::ulittle32_t data_size;
215 llvm::support::ulittle32_t rva;
216};
217static_assert(sizeof(MinidumpLocationDescriptor) == 8,
218 "sizeof MinidumpLocationDescriptor is not correct!");
219
220// Reference:
221// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680384(v=vs.85).aspx
222struct MinidumpMemoryDescriptor {
223 llvm::support::ulittle64_t start_of_memory_range;
224 MinidumpLocationDescriptor memory;
225
226 static llvm::ArrayRef<MinidumpMemoryDescriptor>
227 ParseMemoryList(llvm::ArrayRef<uint8_t> &data);
228};
229static_assert(sizeof(MinidumpMemoryDescriptor) == 16,
230 "sizeof MinidumpMemoryDescriptor is not correct!");
231
232struct MinidumpMemoryDescriptor64 {
233 llvm::support::ulittle64_t start_of_memory_range;
234 llvm::support::ulittle64_t data_size;
235
236 static std::pair<llvm::ArrayRef<MinidumpMemoryDescriptor64>, uint64_t>
237 ParseMemory64List(llvm::ArrayRef<uint8_t> &data);
238};
239static_assert(sizeof(MinidumpMemoryDescriptor64) == 16,
240 "sizeof MinidumpMemoryDescriptor64 is not correct!");
241
242// Reference:
243// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680365.aspx
244struct MinidumpDirectory {
245 llvm::support::ulittle32_t stream_type;
246 MinidumpLocationDescriptor location;
247};
248static_assert(sizeof(MinidumpDirectory) == 12,
249 "sizeof MinidumpDirectory is not correct!");
250
251// Reference:
252// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680385(v=vs.85).aspx
253struct MinidumpMemoryInfoListHeader {
254 llvm::support::ulittle32_t size_of_header;
255 llvm::support::ulittle32_t size_of_entry;
256 llvm::support::ulittle64_t num_of_entries;
257};
258static_assert(sizeof(MinidumpMemoryInfoListHeader) == 16,
259 "sizeof MinidumpMemoryInfoListHeader is not correct!");
260
261// Reference:
262// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680386(v=vs.85).aspx
263struct MinidumpMemoryInfo {
264 llvm::support::ulittle64_t base_address;
265 llvm::support::ulittle64_t allocation_base;
266 llvm::support::ulittle32_t allocation_protect;
267 llvm::support::ulittle32_t alignment1;
268 llvm::support::ulittle64_t region_size;
269 llvm::support::ulittle32_t state;
270 llvm::support::ulittle32_t protect;
271 llvm::support::ulittle32_t type;
272 llvm::support::ulittle32_t alignment2;
273
274 static std::vector<const MinidumpMemoryInfo *>
275 ParseMemoryInfoList(llvm::ArrayRef<uint8_t> &data);
276};
277static_assert(sizeof(MinidumpMemoryInfo) == 48,
278 "sizeof MinidumpMemoryInfo is not correct!");
279
280enum class MinidumpMemoryInfoState : uint32_t {
281 MemCommit = 0x1000,
282 MemFree = 0x10000,
283 MemReserve = 0x2000,
284 LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ MemFree)LLVM_BITMASK_LARGEST_ENUMERATOR = MemFree
285};
286
287enum class MinidumpMemoryInfoType : uint32_t {
288 MemImage = 0x1000000,
289 MemMapped = 0x40000,
290 MemPrivate = 0x20000,
291 LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ MemImage)LLVM_BITMASK_LARGEST_ENUMERATOR = MemImage
292};
293
294// Reference:
295// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366786(v=vs.85).aspx
296enum class MinidumpMemoryProtectionContants : uint32_t {
297 PageExecute = 0x10,
298 PageExecuteRead = 0x20,
299 PageExecuteReadWrite = 0x40,
300 PageExecuteWriteCopy = 0x80,
301 PageNoAccess = 0x01,
302 PageReadOnly = 0x02,
303 PageReadWrite = 0x04,
304 PageWriteCopy = 0x08,
305 PageTargetsInvalid = 0x40000000,
306 PageTargetsNoUpdate = 0x40000000,
307
308 PageWritable = PageExecuteReadWrite | PageExecuteWriteCopy | PageReadWrite |
309 PageWriteCopy,
310 PageExecutable = PageExecute | PageExecuteRead | PageExecuteReadWrite |
311 PageExecuteWriteCopy,
312 LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ PageTargetsInvalid)LLVM_BITMASK_LARGEST_ENUMERATOR = PageTargetsInvalid
313};
314
315// Reference:
316// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680517(v=vs.85).aspx
317struct MinidumpThread {
318 llvm::support::ulittle32_t thread_id;
319 llvm::support::ulittle32_t suspend_count;
320 llvm::support::ulittle32_t priority_class;
321 llvm::support::ulittle32_t priority;
322 llvm::support::ulittle64_t teb;
323 MinidumpMemoryDescriptor stack;
324 MinidumpLocationDescriptor thread_context;
325
326 static const MinidumpThread *Parse(llvm::ArrayRef<uint8_t> &data);
327
328 static llvm::ArrayRef<MinidumpThread>
329 ParseThreadList(llvm::ArrayRef<uint8_t> &data);
330};
331static_assert(sizeof(MinidumpThread) == 48,
332 "sizeof MinidumpThread is not correct!");
333
334// Reference:
335// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680396(v=vs.85).aspx
336union MinidumpCPUInfo {
337 struct {
338 llvm::support::ulittle32_t vendor_id[3]; /* cpuid 0: ebx, edx, ecx */
339 llvm::support::ulittle32_t version_information; /* cpuid 1: eax */
340 llvm::support::ulittle32_t feature_information; /* cpuid 1: edx */
341 llvm::support::ulittle32_t
342 amd_extended_cpu_features; /* cpuid 0x80000001, ebx */
343 } x86_cpu_info;
344 struct {
345 llvm::support::ulittle32_t cpuid;
346 llvm::support::ulittle32_t elf_hwcaps; /* linux specific, 0 otherwise */
347 } arm_cpu_info;
348 struct {
349 llvm::support::ulittle64_t processor_features[2];
350 } other_cpu_info;
351};
352static_assert(sizeof(MinidumpCPUInfo) == 24,
353 "sizeof MinidumpCPUInfo is not correct!");
354
355// Reference:
356// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680396(v=vs.85).aspx
357struct MinidumpSystemInfo {
358 llvm::support::ulittle16_t processor_arch;
359 llvm::support::ulittle16_t processor_level;
360 llvm::support::ulittle16_t processor_revision;
361
362 uint8_t number_of_processors;
363 uint8_t product_type;
364
365 llvm::support::ulittle32_t major_version;
366 llvm::support::ulittle32_t minor_version;
367 llvm::support::ulittle32_t build_number;
368 llvm::support::ulittle32_t platform_id;
369 llvm::support::ulittle32_t csd_version_rva;
370
371 llvm::support::ulittle16_t suit_mask;
372 llvm::support::ulittle16_t reserved2;
373
374 MinidumpCPUInfo cpu;
375
376 static const MinidumpSystemInfo *Parse(llvm::ArrayRef<uint8_t> &data);
377};
378static_assert(sizeof(MinidumpSystemInfo) == 56,
379 "sizeof MinidumpSystemInfo is not correct!");
380
381// TODO misc2, misc3 ?
382// Reference:
383// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680389(v=vs.85).aspx
384struct MinidumpMiscInfo {
385 llvm::support::ulittle32_t size;
386 // flags1 represents what info in the struct is valid
387 llvm::support::ulittle32_t flags1;
388 llvm::support::ulittle32_t process_id;
389 llvm::support::ulittle32_t process_create_time;
390 llvm::support::ulittle32_t process_user_time;
391 llvm::support::ulittle32_t process_kernel_time;
392
393 static const MinidumpMiscInfo *Parse(llvm::ArrayRef<uint8_t> &data);
394
395 llvm::Optional<lldb::pid_t> GetPid() const;
396};
397static_assert(sizeof(MinidumpMiscInfo) == 24,
398 "sizeof MinidumpMiscInfo is not correct!");
399
400// The /proc/pid/status is saved as an ascii string in the file
401class LinuxProcStatus {
402public:
403 llvm::StringRef proc_status;
404 lldb::pid_t pid;
405
406 static llvm::Optional<LinuxProcStatus> Parse(llvm::ArrayRef<uint8_t> &data);
407
408 lldb::pid_t GetPid() const;
409
410private:
411 LinuxProcStatus() = default;
412};
413
414// MinidumpModule stuff
415struct MinidumpVSFixedFileInfo {
416 llvm::support::ulittle32_t signature;
417 llvm::support::ulittle32_t struct_version;
418 llvm::support::ulittle32_t file_version_hi;
419 llvm::support::ulittle32_t file_version_lo;
420 llvm::support::ulittle32_t product_version_hi;
421 llvm::support::ulittle32_t product_version_lo;
422 // file_flags_mask - identifies valid bits in fileFlags
423 llvm::support::ulittle32_t file_flags_mask;
424 llvm::support::ulittle32_t file_flags;
425 llvm::support::ulittle32_t file_os;
426 llvm::support::ulittle32_t file_type;
427 llvm::support::ulittle32_t file_subtype;
428 llvm::support::ulittle32_t file_date_hi;
429 llvm::support::ulittle32_t file_date_lo;
430};
431static_assert(sizeof(MinidumpVSFixedFileInfo) == 52,
432 "sizeof MinidumpVSFixedFileInfo is not correct!");
433
434struct MinidumpModule {
435 llvm::support::ulittle64_t base_of_image;
436 llvm::support::ulittle32_t size_of_image;
437 llvm::support::ulittle32_t checksum;
438 llvm::support::ulittle32_t time_date_stamp;
439 llvm::support::ulittle32_t module_name_rva;
440 MinidumpVSFixedFileInfo version_info;
441 MinidumpLocationDescriptor CV_record;
442 MinidumpLocationDescriptor misc_record;
443 llvm::support::ulittle32_t reserved0[2];
444 llvm::support::ulittle32_t reserved1[2];
445
446 static const MinidumpModule *Parse(llvm::ArrayRef<uint8_t> &data);
447
448 static llvm::ArrayRef<MinidumpModule>
449 ParseModuleList(llvm::ArrayRef<uint8_t> &data);
450};
451static_assert(sizeof(MinidumpModule) == 108,
452 "sizeof MinidumpVSFixedFileInfo is not correct!");
453
454// Exception stuff
455struct MinidumpException {
456 enum : unsigned {
457 ExceptonInfoMaxParams = 15,
458 DumpRequested = 0xFFFFFFFF,
459 };
460
461 llvm::support::ulittle32_t exception_code;
462 llvm::support::ulittle32_t exception_flags;
463 llvm::support::ulittle64_t exception_record;
464 llvm::support::ulittle64_t exception_address;
465 llvm::support::ulittle32_t number_parameters;
466 llvm::support::ulittle32_t unused_alignment;
467 llvm::support::ulittle64_t exception_information[ExceptonInfoMaxParams];
468};
469static_assert(sizeof(MinidumpException) == 152,
470 "sizeof MinidumpException is not correct!");
471
472struct MinidumpExceptionStream {
473 llvm::support::ulittle32_t thread_id;
474 llvm::support::ulittle32_t alignment;
475 MinidumpException exception_record;
476 MinidumpLocationDescriptor thread_context;
477
478 static const MinidumpExceptionStream *Parse(llvm::ArrayRef<uint8_t> &data);
479};
480static_assert(sizeof(MinidumpExceptionStream) == 168,
481 "sizeof MinidumpExceptionStream is not correct!");
482
483} // namespace minidump
484} // namespace lldb_private
485#endif // liblldb_MinidumpTypes_h_