//===-- MinidumpTypes.h -----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef liblldb_MinidumpTypes_h_ #define liblldb_MinidumpTypes_h_ // Project includes // Other libraries and framework includes #include "lldb/Utility/Status.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitmaskEnum.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Endian.h" // C includes // C++ includes // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms679293(v=vs.85).aspx // https://chromium.googlesource.com/breakpad/breakpad/ namespace lldb_private { namespace minidump { LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); enum class MinidumpHeaderConstants : uint32_t { Signature = 0x504d444d, // 'PMDM' Version = 0x0000a793, // 42899 LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Signature) }; // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680394.aspx enum class MinidumpStreamType : uint32_t { Unused = 0, Reserved0 = 1, Reserved1 = 2, ThreadList = 3, ModuleList = 4, MemoryList = 5, Exception = 6, SystemInfo = 7, ThreadExList = 8, Memory64List = 9, CommentA = 10, CommentW = 11, HandleData = 12, FunctionTable = 13, UnloadedModuleList = 14, MiscInfo = 15, MemoryInfoList = 16, ThreadInfoList = 17, HandleOperationList = 18, Token = 19, JavascriptData = 20, SystemMemoryInfo = 21, ProcessVMCounters = 22, LastReserved = 0x0000ffff, /* Breakpad extension types. 0x4767 = "Gg" */ BreakpadInfo = 0x47670001, AssertionInfo = 0x47670002, /* These are additional minidump stream values which are specific to * the linux breakpad implementation. */ LinuxCPUInfo = 0x47670003, /* /proc/cpuinfo */ LinuxProcStatus = 0x47670004, /* /proc/$x/status */ LinuxLSBRelease = 0x47670005, /* /etc/lsb-release */ LinuxCMDLine = 0x47670006, /* /proc/$x/cmdline */ LinuxEnviron = 0x47670007, /* /proc/$x/environ */ LinuxAuxv = 0x47670008, /* /proc/$x/auxv */ LinuxMaps = 0x47670009, /* /proc/$x/maps */ LinuxDSODebug = 0x4767000A }; // for MinidumpSystemInfo.processor_arch enum class MinidumpCPUArchitecture : uint16_t { X86 = 0, /* PROCESSOR_ARCHITECTURE_INTEL */ MIPS = 1, /* PROCESSOR_ARCHITECTURE_MIPS */ Alpha = 2, /* PROCESSOR_ARCHITECTURE_ALPHA */ PPC = 3, /* PROCESSOR_ARCHITECTURE_PPC */ SHX = 4, /* PROCESSOR_ARCHITECTURE_SHX (Super-H) */ ARM = 5, /* PROCESSOR_ARCHITECTURE_ARM */ IA64 = 6, /* PROCESSOR_ARCHITECTURE_IA64 */ Alpha64 = 7, /* PROCESSOR_ARCHITECTURE_ALPHA64 */ MSIL = 8, /* PROCESSOR_ARCHITECTURE_MSIL * (Microsoft Intermediate Language) */ AMD64 = 9, /* PROCESSOR_ARCHITECTURE_AMD64 */ X86Win64 = 10, /* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */ SPARC = 0x8001, /* Breakpad-defined value for SPARC */ PPC64 = 0x8002, /* Breakpad-defined value for PPC64 */ ARM64 = 0x8003, /* Breakpad-defined value for ARM64 */ MIPS64 = 0x8004, /* Breakpad-defined value for MIPS64 */ Unknown = 0xffff /* PROCESSOR_ARCHITECTURE_UNKNOWN */ }; // for MinidumpSystemInfo.platform_id enum class MinidumpOSPlatform : uint32_t { Win32S = 0, /* VER_PLATFORM_WIN32s (Windows 3.1) */ Win32Windows = 1, /* VER_PLATFORM_WIN32_WINDOWS (Windows 95-98-Me) */ Win32NT = 2, /* VER_PLATFORM_WIN32_NT (Windows NT, 2000+) */ Win32CE = 3, /* VER_PLATFORM_WIN32_CE, VER_PLATFORM_WIN32_HH * (Windows CE, Windows Mobile, "Handheld") */ /* The following values are Breakpad-defined. */ Unix = 0x8000, /* Generic Unix-ish */ MacOSX = 0x8101, /* Mac OS X/Darwin */ IOS = 0x8102, /* iOS */ Linux = 0x8201, /* Linux */ Solaris = 0x8202, /* Solaris */ Android = 0x8203, /* Android */ PS3 = 0x8204, /* PS3 */ NaCl = 0x8205 /* Native Client (NaCl) */ }; // For MinidumpCPUInfo.arm_cpu_info.elf_hwcaps. // This matches the Linux kernel definitions from enum class MinidumpPCPUInformationARMElfHwCaps : uint32_t { SWP = (1 << 0), Half = (1 << 1), Thumb = (1 << 2), _26BIT = (1 << 3), FastMult = (1 << 4), FPA = (1 << 5), VFP = (1 << 6), EDSP = (1 << 7), Java = (1 << 8), IWMMXT = (1 << 9), Crunch = (1 << 10), ThumbEE = (1 << 11), Neon = (1 << 12), VFPv3 = (1 << 13), VFPv3D16 = (1 << 14), TLS = (1 << 15), VFPv4 = (1 << 16), IDIVA = (1 << 17), IDIVT = (1 << 18), LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IDIVT) }; enum class MinidumpMiscInfoFlags : uint32_t { ProcessID = (1 << 0), ProcessTimes = (1 << 1), LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ ProcessTimes) }; template Status consumeObject(llvm::ArrayRef &Buffer, const T *&Object) { Status error; if (Buffer.size() < sizeof(T)) { error.SetErrorString("Insufficient buffer!"); return error; } Object = reinterpret_cast(Buffer.data()); Buffer = Buffer.drop_front(sizeof(T)); return error; } // parse a MinidumpString which is with UTF-16 // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680395(v=vs.85).aspx llvm::Optional parseMinidumpString(llvm::ArrayRef &data); // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680378(v=vs.85).aspx struct MinidumpHeader { llvm::support::ulittle32_t signature; llvm::support::ulittle32_t version; // The high 16 bits of version field are implementation specific llvm::support::ulittle32_t streams_count; llvm::support::ulittle32_t stream_directory_rva; // offset of the stream directory llvm::support::ulittle32_t checksum; llvm::support::ulittle32_t time_date_stamp; // time_t format llvm::support::ulittle64_t flags; static const MinidumpHeader *Parse(llvm::ArrayRef &data); }; static_assert(sizeof(MinidumpHeader) == 32, "sizeof MinidumpHeader is not correct!"); // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680383.aspx struct MinidumpLocationDescriptor { llvm::support::ulittle32_t data_size; llvm::support::ulittle32_t rva; }; static_assert(sizeof(MinidumpLocationDescriptor) == 8, "sizeof MinidumpLocationDescriptor is not correct!"); // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680384(v=vs.85).aspx struct MinidumpMemoryDescriptor { llvm::support::ulittle64_t start_of_memory_range; MinidumpLocationDescriptor memory; static llvm::ArrayRef ParseMemoryList(llvm::ArrayRef &data); }; static_assert(sizeof(MinidumpMemoryDescriptor) == 16, "sizeof MinidumpMemoryDescriptor is not correct!"); struct MinidumpMemoryDescriptor64 { llvm::support::ulittle64_t start_of_memory_range; llvm::support::ulittle64_t data_size; static std::pair, uint64_t> ParseMemory64List(llvm::ArrayRef &data); }; static_assert(sizeof(MinidumpMemoryDescriptor64) == 16, "sizeof MinidumpMemoryDescriptor64 is not correct!"); // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680365.aspx struct MinidumpDirectory { llvm::support::ulittle32_t stream_type; MinidumpLocationDescriptor location; }; static_assert(sizeof(MinidumpDirectory) == 12, "sizeof MinidumpDirectory is not correct!"); // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680385(v=vs.85).aspx struct MinidumpMemoryInfoListHeader { llvm::support::ulittle32_t size_of_header; llvm::support::ulittle32_t size_of_entry; llvm::support::ulittle64_t num_of_entries; }; static_assert(sizeof(MinidumpMemoryInfoListHeader) == 16, "sizeof MinidumpMemoryInfoListHeader is not correct!"); // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680386(v=vs.85).aspx struct MinidumpMemoryInfo { llvm::support::ulittle64_t base_address; llvm::support::ulittle64_t allocation_base; llvm::support::ulittle32_t allocation_protect; llvm::support::ulittle32_t alignment1; llvm::support::ulittle64_t region_size; llvm::support::ulittle32_t state; llvm::support::ulittle32_t protect; llvm::support::ulittle32_t type; llvm::support::ulittle32_t alignment2; static std::vector ParseMemoryInfoList(llvm::ArrayRef &data); }; static_assert(sizeof(MinidumpMemoryInfo) == 48, "sizeof MinidumpMemoryInfo is not correct!"); enum class MinidumpMemoryInfoState : uint32_t { MemCommit = 0x1000, MemFree = 0x10000, MemReserve = 0x2000, LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ MemFree) }; enum class MinidumpMemoryInfoType : uint32_t { MemImage = 0x1000000, MemMapped = 0x40000, MemPrivate = 0x20000, LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ MemImage) }; // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/aa366786(v=vs.85).aspx enum class MinidumpMemoryProtectionContants : uint32_t { PageExecute = 0x10, PageExecuteRead = 0x20, PageExecuteReadWrite = 0x40, PageExecuteWriteCopy = 0x80, PageNoAccess = 0x01, PageReadOnly = 0x02, PageReadWrite = 0x04, PageWriteCopy = 0x08, PageTargetsInvalid = 0x40000000, PageTargetsNoUpdate = 0x40000000, PageWritable = PageExecuteReadWrite | PageExecuteWriteCopy | PageReadWrite | PageWriteCopy, PageExecutable = PageExecute | PageExecuteRead | PageExecuteReadWrite | PageExecuteWriteCopy, LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ PageTargetsInvalid) }; // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680517(v=vs.85).aspx struct MinidumpThread { llvm::support::ulittle32_t thread_id; llvm::support::ulittle32_t suspend_count; llvm::support::ulittle32_t priority_class; llvm::support::ulittle32_t priority; llvm::support::ulittle64_t teb; MinidumpMemoryDescriptor stack; MinidumpLocationDescriptor thread_context; static const MinidumpThread *Parse(llvm::ArrayRef &data); static llvm::ArrayRef ParseThreadList(llvm::ArrayRef &data); }; static_assert(sizeof(MinidumpThread) == 48, "sizeof MinidumpThread is not correct!"); // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680396(v=vs.85).aspx union MinidumpCPUInfo { struct { llvm::support::ulittle32_t vendor_id[3]; /* cpuid 0: ebx, edx, ecx */ llvm::support::ulittle32_t version_information; /* cpuid 1: eax */ llvm::support::ulittle32_t feature_information; /* cpuid 1: edx */ llvm::support::ulittle32_t amd_extended_cpu_features; /* cpuid 0x80000001, ebx */ } x86_cpu_info; struct { llvm::support::ulittle32_t cpuid; llvm::support::ulittle32_t elf_hwcaps; /* linux specific, 0 otherwise */ } arm_cpu_info; struct { llvm::support::ulittle64_t processor_features[2]; } other_cpu_info; }; static_assert(sizeof(MinidumpCPUInfo) == 24, "sizeof MinidumpCPUInfo is not correct!"); // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680396(v=vs.85).aspx struct MinidumpSystemInfo { llvm::support::ulittle16_t processor_arch; llvm::support::ulittle16_t processor_level; llvm::support::ulittle16_t processor_revision; uint8_t number_of_processors; uint8_t product_type; llvm::support::ulittle32_t major_version; llvm::support::ulittle32_t minor_version; llvm::support::ulittle32_t build_number; llvm::support::ulittle32_t platform_id; llvm::support::ulittle32_t csd_version_rva; llvm::support::ulittle16_t suit_mask; llvm::support::ulittle16_t reserved2; MinidumpCPUInfo cpu; static const MinidumpSystemInfo *Parse(llvm::ArrayRef &data); }; static_assert(sizeof(MinidumpSystemInfo) == 56, "sizeof MinidumpSystemInfo is not correct!"); // TODO misc2, misc3 ? // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680389(v=vs.85).aspx struct MinidumpMiscInfo { llvm::support::ulittle32_t size; // flags1 represents what info in the struct is valid llvm::support::ulittle32_t flags1; llvm::support::ulittle32_t process_id; llvm::support::ulittle32_t process_create_time; llvm::support::ulittle32_t process_user_time; llvm::support::ulittle32_t process_kernel_time; static const MinidumpMiscInfo *Parse(llvm::ArrayRef &data); llvm::Optional GetPid() const; }; static_assert(sizeof(MinidumpMiscInfo) == 24, "sizeof MinidumpMiscInfo is not correct!"); // The /proc/pid/status is saved as an ascii string in the file class LinuxProcStatus { public: llvm::StringRef proc_status; lldb::pid_t pid; static llvm::Optional Parse(llvm::ArrayRef &data); lldb::pid_t GetPid() const; private: LinuxProcStatus() = default; }; // MinidumpModule stuff struct MinidumpVSFixedFileInfo { llvm::support::ulittle32_t signature; llvm::support::ulittle32_t struct_version; llvm::support::ulittle32_t file_version_hi; llvm::support::ulittle32_t file_version_lo; llvm::support::ulittle32_t product_version_hi; llvm::support::ulittle32_t product_version_lo; // file_flags_mask - identifies valid bits in fileFlags llvm::support::ulittle32_t file_flags_mask; llvm::support::ulittle32_t file_flags; llvm::support::ulittle32_t file_os; llvm::support::ulittle32_t file_type; llvm::support::ulittle32_t file_subtype; llvm::support::ulittle32_t file_date_hi; llvm::support::ulittle32_t file_date_lo; }; static_assert(sizeof(MinidumpVSFixedFileInfo) == 52, "sizeof MinidumpVSFixedFileInfo is not correct!"); struct MinidumpModule { llvm::support::ulittle64_t base_of_image; llvm::support::ulittle32_t size_of_image; llvm::support::ulittle32_t checksum; llvm::support::ulittle32_t time_date_stamp; llvm::support::ulittle32_t module_name_rva; MinidumpVSFixedFileInfo version_info; MinidumpLocationDescriptor CV_record; MinidumpLocationDescriptor misc_record; llvm::support::ulittle32_t reserved0[2]; llvm::support::ulittle32_t reserved1[2]; static const MinidumpModule *Parse(llvm::ArrayRef &data); static llvm::ArrayRef ParseModuleList(llvm::ArrayRef &data); }; static_assert(sizeof(MinidumpModule) == 108, "sizeof MinidumpVSFixedFileInfo is not correct!"); // Exception stuff struct MinidumpException { enum : unsigned { ExceptonInfoMaxParams = 15, DumpRequested = 0xFFFFFFFF, }; llvm::support::ulittle32_t exception_code; llvm::support::ulittle32_t exception_flags; llvm::support::ulittle64_t exception_record; llvm::support::ulittle64_t exception_address; llvm::support::ulittle32_t number_parameters; llvm::support::ulittle32_t unused_alignment; llvm::support::ulittle64_t exception_information[ExceptonInfoMaxParams]; }; static_assert(sizeof(MinidumpException) == 152, "sizeof MinidumpException is not correct!"); struct MinidumpExceptionStream { llvm::support::ulittle32_t thread_id; llvm::support::ulittle32_t alignment; MinidumpException exception_record; MinidumpLocationDescriptor thread_context; static const MinidumpExceptionStream *Parse(llvm::ArrayRef &data); }; static_assert(sizeof(MinidumpExceptionStream) == 168, "sizeof MinidumpExceptionStream is not correct!"); } // namespace minidump } // namespace lldb_private #endif // liblldb_MinidumpTypes_h_