1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | // typedef for our parsing of the auxv variables in /proc/pid/auxv. |
6 | #if defined(__i386) || defined(__ARM_EABI__) |
7 | typedef Elf32_auxv_t elf_aux_entry; |
8 | #define PRIx PRIx32 |
9 | #define PRIu PRIu32 |
10 | #define PRId PRId32 |
11 | #define PRIA "08" |
12 | #define PRIxA PRIA PRIx |
13 | #elif defined(__x86_64__) || defined(__aarch64__) |
14 | typedef Elf64_auxv_t elf_aux_entry; |
15 | #define PRIx PRIx64 |
16 | #define PRIu PRIu64 |
17 | #define PRId PRId64 |
18 | #define PRIA "016" |
19 | #define PRIxA PRIA PRIx |
20 | #endif |
21 | |
22 | typedef __typeof__(((elf_aux_entry*) 0)->a_un.a_val) elf_aux_val_t; |
23 | |
24 | // All interesting auvx entry types are AT_SYSINFO_EHDR and below |
25 | #define AT_MAX (AT_SYSINFO_EHDR + 1) |
26 | |
27 | class CrashInfo : public ICLRDataEnumMemoryRegionsCallback |
28 | { |
29 | private: |
30 | LONG m_ref; // reference count |
31 | pid_t m_pid; // pid |
32 | pid_t m_ppid; // parent pid |
33 | pid_t m_tgid; // process group |
34 | char* m_name; // exe name |
35 | bool m_sos; // if true, running under sos |
36 | std::string m_coreclrPath; // the path of the coreclr module or empty if none |
37 | ICLRDataTarget* m_dataTarget; // read process memory, etc. |
38 | std::array<elf_aux_val_t, AT_MAX> m_auxvValues; // auxv values |
39 | std::vector<elf_aux_entry> m_auxvEntries; // full auxv entries |
40 | std::vector<ThreadInfo*> m_threads; // threads found and suspended |
41 | std::set<MemoryRegion> m_moduleMappings; // module memory mappings |
42 | std::set<MemoryRegion> m_otherMappings; // other memory mappings |
43 | std::set<MemoryRegion> m_memoryRegions; // memory regions from DAC, etc. |
44 | std::set<MemoryRegion> m_moduleAddresses; // memory region to module base address |
45 | |
46 | public: |
47 | CrashInfo(pid_t pid, ICLRDataTarget* dataTarget, bool sos); |
48 | virtual ~CrashInfo(); |
49 | bool EnumerateAndSuspendThreads(); |
50 | bool GatherCrashInfo(MINIDUMP_TYPE minidumpType); |
51 | void ResumeThreads(); |
52 | bool ReadMemory(void* address, void* buffer, size_t size); |
53 | uint64_t GetBaseAddress(uint64_t ip); |
54 | void InsertMemoryRegion(uint64_t address, size_t size); |
55 | static bool GetStatus(pid_t pid, pid_t* ppid, pid_t* tgid, char** name); |
56 | static const MemoryRegion* SearchMemoryRegions(const std::set<MemoryRegion>& regions, const MemoryRegion& search); |
57 | |
58 | inline pid_t Pid() const { return m_pid; } |
59 | inline pid_t Ppid() const { return m_ppid; } |
60 | inline pid_t Tgid() const { return m_tgid; } |
61 | inline const char* Name() const { return m_name; } |
62 | inline ICLRDataTarget* DataTarget() const { return m_dataTarget; } |
63 | |
64 | inline const std::vector<ThreadInfo*> Threads() const { return m_threads; } |
65 | inline const std::set<MemoryRegion> ModuleMappings() const { return m_moduleMappings; } |
66 | inline const std::set<MemoryRegion> OtherMappings() const { return m_otherMappings; } |
67 | inline const std::set<MemoryRegion> MemoryRegions() const { return m_memoryRegions; } |
68 | inline const std::vector<elf_aux_entry> AuxvEntries() const { return m_auxvEntries; } |
69 | inline size_t GetAuxvSize() const { return m_auxvEntries.size() * sizeof(elf_aux_entry); } |
70 | |
71 | // IUnknown |
72 | STDMETHOD(QueryInterface)(___in REFIID InterfaceId, ___out PVOID* Interface); |
73 | STDMETHOD_(ULONG, AddRef)(); |
74 | STDMETHOD_(ULONG, Release)(); |
75 | |
76 | // ICLRDataEnumMemoryRegionsCallback |
77 | virtual HRESULT STDMETHODCALLTYPE EnumMemoryRegion(/* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 size); |
78 | |
79 | private: |
80 | bool GetAuxvEntries(); |
81 | bool EnumerateModuleMappings(); |
82 | bool GetDSOInfo(); |
83 | bool GetELFInfo(uint64_t baseAddress); |
84 | bool (ElfW(Phdr)* phdrAddr, int phnum, uint64_t baseAddress, ElfW(Dyn)** pdynamicAddr); |
85 | bool EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType); |
86 | bool EnumerateManagedModules(IXCLRDataProcess* pClrDataProcess); |
87 | bool UnwindAllThreads(IXCLRDataProcess* pClrDataProcess); |
88 | void ReplaceModuleMapping(CLRDATA_ADDRESS baseAddress, const char* pszName); |
89 | void InsertMemoryBackedRegion(const MemoryRegion& region); |
90 | void InsertMemoryRegion(const MemoryRegion& region); |
91 | uint32_t GetMemoryRegionFlags(uint64_t start); |
92 | bool ValidRegion(const MemoryRegion& region); |
93 | void CombineMemoryRegions(); |
94 | }; |
95 | |