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