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__)
7typedef 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__)
14typedef 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
22typedef __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
27class CrashInfo : public ICLRDataEnumMemoryRegionsCallback
28{
29private:
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
46public:
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
79private:
80 bool GetAuxvEntries();
81 bool EnumerateModuleMappings();
82 bool GetDSOInfo();
83 bool GetELFInfo(uint64_t baseAddress);
84 bool EnumerateProgramHeaders(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