| 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 | |