-
Notifications
You must be signed in to change notification settings - Fork 4.6k
/
crashinfo.h
169 lines (152 loc) · 7.54 KB
/
crashinfo.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#ifdef __APPLE__
#include "../dbgutil/machoreader.h"
#else
#include "../dbgutil/elfreader.h"
// typedef for our parsing of the auxv variables in /proc/pid/auxv.
#if TARGET_64BIT
typedef Elf64_auxv_t elf_aux_entry;
#define PRIx PRIx64
#define PRIu PRIu64
#define PRId PRId64
#define PRIA "016"
#define PRIxA PRIA PRIx
#else
typedef Elf32_auxv_t elf_aux_entry;
#define PRIx PRIx32
#define PRIu PRIu32
#define PRId PRId32
#define PRIA "08"
#define PRIxA PRIA PRIx
#endif
typedef __typeof__(((elf_aux_entry*) 0)->a_un.a_val) elf_aux_val_t;
// All interesting auvx entry types are AT_SYSINFO_EHDR and below
#define AT_MAX (AT_SYSINFO_EHDR + 1)
#endif
extern const std::string GetFileName(const std::string& fileName);
extern const std::string GetDirectory(const std::string& fileName);
extern std::string FormatString(const char* format, ...);
extern std::string ConvertString(const WCHAR* str);
extern std::string FormatGuid(const GUID* guid);
class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, public ICLRDataLoggingCallback,
#ifdef __APPLE__
public MachOReader
#else
public ElfReader
#endif
{
private:
LONG m_ref; // reference count
pid_t m_pid; // pid
pid_t m_ppid; // parent pid
pid_t m_tgid; // process group
HMODULE m_hdac; // dac module handle when loaded
ICLRDataEnumMemoryRegions* m_pClrDataEnumRegions; // dac enumerate memory interface instance
IXCLRDataProcess* m_pClrDataProcess; // dac process interface instance
bool m_gatherFrames; // if true, add the native and managed stack frames to the thread info
pid_t m_crashThread; // crashing thread id or 0 if none
uint32_t m_signal; // crash signal code or 0 if none
std::string m_name; // exe name
#ifdef __APPLE__
vm_map_t m_task; // the mach task for the process
#else
siginfo_t m_siginfo; // signal info (if any)
bool m_canUseProcVmReadSyscall;
int m_fdMem; // /proc/<pid>/mem handle
int m_fdPagemap; // /proc/<pid>/pagemap handle
#endif
std::string m_coreclrPath; // the path of the coreclr module or empty if none
uint64_t m_runtimeBaseAddress;
#ifdef __APPLE__
std::set<MemoryRegion> m_allMemoryRegions; // all memory regions on MacOS
#else
std::array<elf_aux_val_t, AT_MAX> m_auxvValues; // auxv values
std::vector<elf_aux_entry> m_auxvEntries; // full auxv entries
#endif
std::vector<ThreadInfo*> m_threads; // threads found and suspended
std::set<MemoryRegion> m_moduleMappings; // module memory mappings
std::set<MemoryRegion> m_otherMappings; // other memory mappings
std::set<MemoryRegion> m_memoryRegions; // memory regions from DAC, etc.
std::set<MemoryRegion> m_moduleAddresses; // memory region to module base address
std::set<ModuleInfo*, bool (*)(const ModuleInfo* lhs, const ModuleInfo* rhs)> m_moduleInfos; // module infos (base address and module name)
ModuleInfo* m_mainModule; // the module containing "Main"
// no public copy constructor
CrashInfo(const CrashInfo&) = delete;
void operator=(const CrashInfo&) = delete;
public:
CrashInfo(const CreateDumpOptions& options);
virtual ~CrashInfo();
// Memory usage stats
uint64_t m_cbModuleMappings;
int m_dataTargetPagesAdded;
int m_enumMemoryPagesAdded;
bool Initialize();
void CleanupAndResumeProcess();
bool EnumerateAndSuspendThreads();
bool GatherCrashInfo(MINIDUMP_TYPE minidumpType);
void CombineMemoryRegions();
bool EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType);
bool ReadMemory(void* address, void* buffer, size_t size); // read memory and add to dump
bool ReadProcessMemory(void* address, void* buffer, size_t size, size_t* read); // read raw memory
uint64_t GetBaseAddressFromAddress(uint64_t address);
uint64_t GetBaseAddressFromName(const char* moduleName);
ModuleInfo* GetModuleInfoFromBaseAddress(uint64_t baseAddress);
void AddModuleAddressRange(uint64_t startAddress, uint64_t endAddress, uint64_t baseAddress);
void AddModuleInfo(bool isManaged, uint64_t baseAddress, IXCLRDataModule* pClrDataModule, const std::string& moduleName);
int InsertMemoryRegion(uint64_t address, size_t size);
static const MemoryRegion* SearchMemoryRegions(const std::set<MemoryRegion>& regions, const MemoryRegion& search);
inline pid_t Pid() const { return m_pid; }
inline pid_t Ppid() const { return m_ppid; }
inline pid_t Tgid() const { return m_tgid; }
#ifdef __APPLE__
inline vm_map_t Task() const { return m_task; }
#endif
inline const bool GatherFrames() const { return m_gatherFrames; }
inline const pid_t CrashThread() const { return m_crashThread; }
inline const uint32_t Signal() const { return m_signal; }
inline const std::string& Name() const { return m_name; }
inline const ModuleInfo* MainModule() const { return m_mainModule; }
inline const uint64_t RuntimeBaseAddress() const { return m_runtimeBaseAddress; }
inline const std::vector<ThreadInfo*>& Threads() const { return m_threads; }
inline const std::set<MemoryRegion>& ModuleMappings() const { return m_moduleMappings; }
inline const std::set<MemoryRegion>& OtherMappings() const { return m_otherMappings; }
inline const std::set<MemoryRegion>& MemoryRegions() const { return m_memoryRegions; }
#ifndef __APPLE__
inline const std::vector<elf_aux_entry>& AuxvEntries() const { return m_auxvEntries; }
inline size_t GetAuxvSize() const { return m_auxvEntries.size() * sizeof(elf_aux_entry); }
inline const siginfo_t* SigInfo() const { return &m_siginfo; }
#endif
// IUnknown
STDMETHOD(QueryInterface)(___in REFIID InterfaceId, ___out PVOID* Interface);
STDMETHOD_(ULONG, AddRef)();
STDMETHOD_(ULONG, Release)();
// ICLRDataEnumMemoryRegionsCallback
virtual HRESULT STDMETHODCALLTYPE EnumMemoryRegion(/* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 size);
// ICLRDataLoggingCallback
virtual HRESULT STDMETHODCALLTYPE LogMessage( /* [in] */ LPCSTR message);
private:
#ifdef __APPLE__
bool EnumerateMemoryRegions();
void InitializeOtherMappings();
void VisitModule(MachOModule& module);
void VisitSegment(MachOModule& module, const segment_command_64& segment);
void VisitSection(MachOModule& module, const section_64& section);
#else
bool GetAuxvEntries();
bool GetDSOInfo();
void VisitModule(uint64_t baseAddress, std::string& moduleName);
void VisitProgramHeader(uint64_t loadbias, uint64_t baseAddress, ElfW(Phdr)* phdr);
bool EnumerateMemoryRegions();
#endif
bool InitializeDAC();
bool EnumerateManagedModules();
bool UnwindAllThreads();
void AddOrReplaceModuleMapping(CLRDATA_ADDRESS baseAddress, ULONG64 size, const std::string& pszName);
int InsertMemoryRegion(const MemoryRegion& region);
uint32_t GetMemoryRegionFlags(uint64_t start);
bool PageCanBeRead(uint64_t start);
bool PageMappedToPhysicalMemory(uint64_t start);
void Trace(const char* format, ...);
void TraceVerbose(const char* format, ...);
};