Bug Summary

File:tools/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
Warning:line 59, column 47
Called C++ object pointer is null

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-eagerly-assume -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-7/lib/clang/7.0.0 -D HAVE_ROUND -D LLDB_CONFIGURATION_RELEASE -D LLDB_USE_BUILTIN_DEMANGLER -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/tools/lldb/source/Plugins/Process/minidump -I /build/llvm-toolchain-snapshot-7~svn329677/tools/lldb/source/Plugins/Process/minidump -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/tools/lldb/include -I /build/llvm-toolchain-snapshot-7~svn329677/tools/lldb/include -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn329677/include -I /usr/include/python2.7 -I /build/llvm-toolchain-snapshot-7~svn329677/tools/clang/include -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-7~svn329677/tools/lldb/source/. -I /build/llvm-toolchain-snapshot-7~svn329677/tools/lldb/source/Plugins/Process/minidump/../Utility -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.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-7~svn329677/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-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-04-11-031539-24776-1 -x c++ /build/llvm-toolchain-snapshot-7~svn329677/tools/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp

/build/llvm-toolchain-snapshot-7~svn329677/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
18// C includes
19// C++ includes
20#include <map>
21
22using namespace lldb_private;
23using namespace minidump;
24
25llvm::Optional<MinidumpParser>
26MinidumpParser::Create(const lldb::DataBufferSP &data_buf_sp) {
27 if (data_buf_sp->GetByteSize() < sizeof(MinidumpHeader)) {
1
Assuming the condition is false
2
Taking false branch
28 return llvm::None;
29 }
30
31 llvm::ArrayRef<uint8_t> header_data(data_buf_sp->GetBytes(),
32 sizeof(MinidumpHeader));
33 const MinidumpHeader *header = MinidumpHeader::Parse(header_data);
34
35 if (header == nullptr) {
3
Assuming the condition is false
4
Taking false branch
36 return llvm::None;
37 }
38
39 lldb::offset_t directory_list_offset = header->stream_directory_rva;
40 // check if there is enough data for the parsing of the directory list
41 if ((directory_list_offset +
5
Taking false branch
42 sizeof(MinidumpDirectory) * header->streams_count) >
43 data_buf_sp->GetByteSize()) {
44 return llvm::None;
45 }
46
47 const MinidumpDirectory *directory = nullptr;
6
'directory' initialized to a null pointer value
48 Status error;
49 llvm::ArrayRef<uint8_t> directory_data(
50 data_buf_sp->GetBytes() + directory_list_offset,
51 sizeof(MinidumpDirectory) * header->streams_count);
52 llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> directory_map;
53
54 for (uint32_t i = 0; i < header->streams_count; ++i) {
7
Assuming the condition is true
8
Loop condition is true. Entering loop body
55 error = consumeObject(directory_data, directory);
9
Calling 'consumeObject'
13
Returning from 'consumeObject'
56 if (error.Fail()) {
14
Assuming the condition is false
15
Taking false branch
57 return llvm::None;
58 }
59 directory_map[static_cast<const uint32_t>(directory->stream_type)] =
16
Called C++ object pointer is null
60 directory->location;
61 }
62
63 return MinidumpParser(data_buf_sp, header, std::move(directory_map));
64}
65
66MinidumpParser::MinidumpParser(
67 const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header,
68 llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &&directory_map)
69 : m_data_sp(data_buf_sp), m_header(header), m_directory_map(directory_map) {
70}
71
72llvm::ArrayRef<uint8_t> MinidumpParser::GetData() {
73 return llvm::ArrayRef<uint8_t>(m_data_sp->GetBytes(),
74 m_data_sp->GetByteSize());
75}
76
77llvm::ArrayRef<uint8_t>
78MinidumpParser::GetStream(MinidumpStreamType stream_type) {
79 auto iter = m_directory_map.find(static_cast<uint32_t>(stream_type));
80 if (iter == m_directory_map.end())
81 return {};
82
83 // check if there is enough data
84 if (iter->second.rva + iter->second.data_size > m_data_sp->GetByteSize())
85 return {};
86
87 return llvm::ArrayRef<uint8_t>(m_data_sp->GetBytes() + iter->second.rva,
88 iter->second.data_size);
89}
90
91llvm::Optional<std::string> MinidumpParser::GetMinidumpString(uint32_t rva) {
92 auto arr_ref = m_data_sp->GetData();
93 if (rva > arr_ref.size())
94 return llvm::None;
95 arr_ref = arr_ref.drop_front(rva);
96 return parseMinidumpString(arr_ref);
97}
98
99llvm::ArrayRef<MinidumpThread> MinidumpParser::GetThreads() {
100 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::ThreadList);
101
102 if (data.size() == 0)
103 return llvm::None;
104
105 return MinidumpThread::ParseThreadList(data);
106}
107
108llvm::ArrayRef<uint8_t>
109MinidumpParser::GetThreadContext(const MinidumpThread &td) {
110 if (td.thread_context.rva + td.thread_context.data_size > GetData().size())
111 return {};
112
113 return GetData().slice(td.thread_context.rva, td.thread_context.data_size);
114}
115
116llvm::ArrayRef<uint8_t>
117MinidumpParser::GetThreadContextWow64(const MinidumpThread &td) {
118 // On Windows, a 32-bit process can run on a 64-bit machine under
119 // WOW64. If the minidump was captured with a 64-bit debugger, then
120 // the CONTEXT we just grabbed from the mini_dump_thread is the one
121 // for the 64-bit "native" process rather than the 32-bit "guest"
122 // process we care about. In this case, we can get the 32-bit CONTEXT
123 // from the TEB (Thread Environment Block) of the 64-bit process.
124 auto teb_mem = GetMemory(td.teb, sizeof(TEB64));
125 if (teb_mem.empty())
126 return {};
127
128 const TEB64 *wow64teb;
129 Status error = consumeObject(teb_mem, wow64teb);
130 if (error.Fail())
131 return {};
132
133 // Slot 1 of the thread-local storage in the 64-bit TEB points to a
134 // structure that includes the 32-bit CONTEXT (after a ULONG).
135 // See: https://msdn.microsoft.com/en-us/library/ms681670.aspx
136 auto context =
137 GetMemory(wow64teb->tls_slots[1] + 4, sizeof(MinidumpContext_x86_32));
138 if (context.size() < sizeof(MinidumpContext_x86_32))
139 return {};
140
141 return context;
142 // NOTE: We don't currently use the TEB for anything else. If we
143 // need it in the future, the 32-bit TEB is located according to the address
144 // stored in the first slot of the 64-bit TEB (wow64teb.Reserved1[0]).
145}
146
147const MinidumpSystemInfo *MinidumpParser::GetSystemInfo() {
148 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::SystemInfo);
149
150 if (data.size() == 0)
151 return nullptr;
152
153 return MinidumpSystemInfo::Parse(data);
154}
155
156ArchSpec MinidumpParser::GetArchitecture() {
157 ArchSpec arch_spec;
158 const MinidumpSystemInfo *system_info = GetSystemInfo();
159
160 if (!system_info)
161 return arch_spec;
162
163 // TODO what to do about big endiand flavors of arm ?
164 // TODO set the arm subarch stuff if the minidump has info about it
165
166 llvm::Triple triple;
167 triple.setVendor(llvm::Triple::VendorType::UnknownVendor);
168
169 const MinidumpCPUArchitecture arch =
170 static_cast<const MinidumpCPUArchitecture>(
171 static_cast<const uint32_t>(system_info->processor_arch));
172
173 switch (arch) {
174 case MinidumpCPUArchitecture::X86:
175 triple.setArch(llvm::Triple::ArchType::x86);
176 break;
177 case MinidumpCPUArchitecture::AMD64:
178 triple.setArch(llvm::Triple::ArchType::x86_64);
179 break;
180 case MinidumpCPUArchitecture::ARM:
181 triple.setArch(llvm::Triple::ArchType::arm);
182 break;
183 case MinidumpCPUArchitecture::ARM64:
184 triple.setArch(llvm::Triple::ArchType::aarch64);
185 break;
186 default:
187 triple.setArch(llvm::Triple::ArchType::UnknownArch);
188 break;
189 }
190
191 const MinidumpOSPlatform os = static_cast<const MinidumpOSPlatform>(
192 static_cast<const uint32_t>(system_info->platform_id));
193
194 // TODO add all of the OSes that Minidump/breakpad distinguishes?
195 switch (os) {
196 case MinidumpOSPlatform::Win32S:
197 case MinidumpOSPlatform::Win32Windows:
198 case MinidumpOSPlatform::Win32NT:
199 case MinidumpOSPlatform::Win32CE:
200 triple.setOS(llvm::Triple::OSType::Win32);
201 break;
202 case MinidumpOSPlatform::Linux:
203 triple.setOS(llvm::Triple::OSType::Linux);
204 break;
205 case MinidumpOSPlatform::MacOSX:
206 triple.setOS(llvm::Triple::OSType::MacOSX);
207 break;
208 case MinidumpOSPlatform::Android:
209 triple.setOS(llvm::Triple::OSType::Linux);
210 triple.setEnvironment(llvm::Triple::EnvironmentType::Android);
211 break;
212 default:
213 triple.setOS(llvm::Triple::OSType::UnknownOS);
214 break;
215 }
216
217 arch_spec.SetTriple(triple);
218
219 return arch_spec;
220}
221
222const MinidumpMiscInfo *MinidumpParser::GetMiscInfo() {
223 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::MiscInfo);
224
225 if (data.size() == 0)
226 return nullptr;
227
228 return MinidumpMiscInfo::Parse(data);
229}
230
231llvm::Optional<LinuxProcStatus> MinidumpParser::GetLinuxProcStatus() {
232 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::LinuxProcStatus);
233
234 if (data.size() == 0)
235 return llvm::None;
236
237 return LinuxProcStatus::Parse(data);
238}
239
240llvm::Optional<lldb::pid_t> MinidumpParser::GetPid() {
241 const MinidumpMiscInfo *misc_info = GetMiscInfo();
242 if (misc_info != nullptr) {
243 return misc_info->GetPid();
244 }
245
246 llvm::Optional<LinuxProcStatus> proc_status = GetLinuxProcStatus();
247 if (proc_status.hasValue()) {
248 return proc_status->GetPid();
249 }
250
251 return llvm::None;
252}
253
254llvm::ArrayRef<MinidumpModule> MinidumpParser::GetModuleList() {
255 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::ModuleList);
256
257 if (data.size() == 0)
258 return {};
259
260 return MinidumpModule::ParseModuleList(data);
261}
262
263std::vector<const MinidumpModule *> MinidumpParser::GetFilteredModuleList() {
264 llvm::ArrayRef<MinidumpModule> modules = GetModuleList();
265 // map module_name -> pair(load_address, pointer to module struct in memory)
266 llvm::StringMap<std::pair<uint64_t, const MinidumpModule *>> lowest_addr;
267
268 std::vector<const MinidumpModule *> filtered_modules;
269
270 llvm::Optional<std::string> name;
271 std::string module_name;
272
273 for (const auto &module : modules) {
274 name = GetMinidumpString(module.module_name_rva);
275
276 if (!name)
277 continue;
278
279 module_name = name.getValue();
280
281 auto iter = lowest_addr.end();
282 bool exists;
283 std::tie(iter, exists) = lowest_addr.try_emplace(
284 module_name, std::make_pair(module.base_of_image, &module));
285
286 if (exists && module.base_of_image < iter->second.first)
287 iter->second = std::make_pair(module.base_of_image, &module);
288 }
289
290 filtered_modules.reserve(lowest_addr.size());
291 for (const auto &module : lowest_addr) {
292 filtered_modules.push_back(module.second.second);
293 }
294
295 return filtered_modules;
296}
297
298const MinidumpExceptionStream *MinidumpParser::GetExceptionStream() {
299 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::Exception);
300
301 if (data.size() == 0)
302 return nullptr;
303
304 return MinidumpExceptionStream::Parse(data);
305}
306
307llvm::Optional<minidump::Range>
308MinidumpParser::FindMemoryRange(lldb::addr_t addr) {
309 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::MemoryList);
310 llvm::ArrayRef<uint8_t> data64 = GetStream(MinidumpStreamType::Memory64List);
311
312 if (data.empty() && data64.empty())
313 return llvm::None;
314
315 if (!data.empty()) {
316 llvm::ArrayRef<MinidumpMemoryDescriptor> memory_list =
317 MinidumpMemoryDescriptor::ParseMemoryList(data);
318
319 if (memory_list.empty())
320 return llvm::None;
321
322 for (const auto &memory_desc : memory_list) {
323 const MinidumpLocationDescriptor &loc_desc = memory_desc.memory;
324 const lldb::addr_t range_start = memory_desc.start_of_memory_range;
325 const size_t range_size = loc_desc.data_size;
326
327 if (loc_desc.rva + loc_desc.data_size > GetData().size())
328 return llvm::None;
329
330 if (range_start <= addr && addr < range_start + range_size) {
331 return minidump::Range(range_start,
332 GetData().slice(loc_desc.rva, range_size));
333 }
334 }
335 }
336
337 // Some Minidumps have a Memory64ListStream that captures all the heap
338 // memory (full-memory Minidumps). We can't exactly use the same loop as
339 // above, because the Minidump uses slightly different data structures to
340 // describe those
341
342 if (!data64.empty()) {
343 llvm::ArrayRef<MinidumpMemoryDescriptor64> memory64_list;
344 uint64_t base_rva;
345 std::tie(memory64_list, base_rva) =
346 MinidumpMemoryDescriptor64::ParseMemory64List(data64);
347
348 if (memory64_list.empty())
349 return llvm::None;
350
351 for (const auto &memory_desc64 : memory64_list) {
352 const lldb::addr_t range_start = memory_desc64.start_of_memory_range;
353 const size_t range_size = memory_desc64.data_size;
354
355 if (base_rva + range_size > GetData().size())
356 return llvm::None;
357
358 if (range_start <= addr && addr < range_start + range_size) {
359 return minidump::Range(range_start,
360 GetData().slice(base_rva, range_size));
361 }
362 base_rva += range_size;
363 }
364 }
365
366 return llvm::None;
367}
368
369llvm::ArrayRef<uint8_t> MinidumpParser::GetMemory(lldb::addr_t addr,
370 size_t size) {
371 // I don't have a sense of how frequently this is called or how many memory
372 // ranges a Minidump typically has, so I'm not sure if searching for the
373 // appropriate range linearly each time is stupid. Perhaps we should build
374 // an index for faster lookups.
375 llvm::Optional<minidump::Range> range = FindMemoryRange(addr);
376 if (!range)
377 return {};
378
379 // There's at least some overlap between the beginning of the desired range
380 // (addr) and the current range. Figure out where the overlap begins and
381 // how much overlap there is.
382
383 const size_t offset = addr - range->start;
384
385 if (addr < range->start || offset >= range->range_ref.size())
386 return {};
387
388 const size_t overlap = std::min(size, range->range_ref.size() - offset);
389 return range->range_ref.slice(offset, overlap);
390}
391
392llvm::Optional<MemoryRegionInfo>
393MinidumpParser::GetMemoryRegionInfo(lldb::addr_t load_addr) {
394 MemoryRegionInfo info;
395 llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::MemoryInfoList);
396 if (data.empty())
397 return llvm::None;
398
399 std::vector<const MinidumpMemoryInfo *> mem_info_list =
400 MinidumpMemoryInfo::ParseMemoryInfoList(data);
401 if (mem_info_list.empty())
402 return llvm::None;
403
404 const auto yes = MemoryRegionInfo::eYes;
405 const auto no = MemoryRegionInfo::eNo;
406
407 const MinidumpMemoryInfo *next_entry = nullptr;
408 for (const auto &entry : mem_info_list) {
409 const auto head = entry->base_address;
410 const auto tail = head + entry->region_size;
411
412 if (head <= load_addr && load_addr < tail) {
413 info.GetRange().SetRangeBase(
414 (entry->state != uint32_t(MinidumpMemoryInfoState::MemFree))
415 ? head
416 : load_addr);
417 info.GetRange().SetRangeEnd(tail);
418
419 const uint32_t PageNoAccess =
420 static_cast<uint32_t>(MinidumpMemoryProtectionContants::PageNoAccess);
421 info.SetReadable((entry->protect & PageNoAccess) == 0 ? yes : no);
422
423 const uint32_t PageWritable =
424 static_cast<uint32_t>(MinidumpMemoryProtectionContants::PageWritable);
425 info.SetWritable((entry->protect & PageWritable) != 0 ? yes : no);
426
427 const uint32_t PageExecutable = static_cast<uint32_t>(
428 MinidumpMemoryProtectionContants::PageExecutable);
429 info.SetExecutable((entry->protect & PageExecutable) != 0 ? yes : no);
430
431 const uint32_t MemFree =
432 static_cast<uint32_t>(MinidumpMemoryInfoState::MemFree);
433 info.SetMapped((entry->state != MemFree) ? yes : no);
434
435 return info;
436 } else if (head > load_addr &&
437 (next_entry == nullptr || head < next_entry->base_address)) {
438 // In case there is no region containing load_addr keep track of the
439 // nearest region after load_addr so we can return the distance to it.
440 next_entry = entry;
441 }
442 }
443
444 // No containing region found. Create an unmapped region that extends to the
445 // next region or LLDB_INVALID_ADDRESS
446 info.GetRange().SetRangeBase(load_addr);
447 info.GetRange().SetRangeEnd((next_entry != nullptr) ? next_entry->base_address
448 : LLDB_INVALID_ADDRESS(18446744073709551615UL));
449 info.SetReadable(no);
450 info.SetWritable(no);
451 info.SetExecutable(no);
452 info.SetMapped(no);
453
454 // Note that the memory info list doesn't seem to contain ranges in kernel
455 // space, so if you're walking a stack that has kernel frames, the stack may
456 // appear truncated.
457 return info;
458}

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