summaryrefslogtreecommitdiff
path: root/src/debug/createdump/crashinfo.h
blob: 43e82691aabb99d5054cc9bf1b05a9da6f077a3a (plain)
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
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

// typedef for our parsing of the auxv variables in /proc/pid/auxv.
#if defined(__i386) || defined(__ARM_EABI__) 
typedef Elf32_auxv_t elf_aux_entry;
#elif defined(__x86_64) || defined(__aarch64__)
typedef Elf64_auxv_t elf_aux_entry;
#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)

class CrashInfo : public ICLRDataEnumMemoryRegionsCallback
{
private:
    LONG m_ref;                                     // reference count
    pid_t m_pid;                                    // pid
    pid_t m_ppid;                                   // parent pid
    pid_t m_tgid;                                   // process group
    char* m_name;                                   // exe name
    bool m_sos;                                     // true if running under sos
    ICLRDataTarget* m_dataTarget;                   // read process memory, etc.
    std::array<elf_aux_val_t, AT_MAX> m_auxvValues; // auxv values
    std::vector<elf_aux_entry> m_auxvEntries;       // full auxv entries
    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.

public:
    CrashInfo(pid_t pid, ICLRDataTarget* dataTarget, bool sos);
    virtual ~CrashInfo();
    bool EnumerateAndSuspendThreads();
    bool GatherCrashInfo(const char* programPath, MINIDUMP_TYPE minidumpType);
    void ResumeThreads();
    static bool GetStatus(pid_t pid, pid_t* ppid, pid_t* tgid, char** name);
    static const MemoryRegion* SearchMemoryRegions(const std::set<MemoryRegion>& regions, uint64_t start);

    const pid_t Pid() const { return m_pid; }
    const pid_t Ppid() const { return m_ppid; }
    const pid_t Tgid() const { return m_tgid; }
    const char* Name() const { return m_name; }
    ICLRDataTarget* DataTarget() const { return m_dataTarget; }

    const std::vector<ThreadInfo*> Threads() const { return m_threads; }
    const std::set<MemoryRegion> ModuleMappings() const { return m_moduleMappings; }
    const std::set<MemoryRegion> OtherMappings() const { return m_otherMappings; }
    const std::set<MemoryRegion> MemoryRegions() const { return m_memoryRegions; }
    const std::vector<elf_aux_entry> AuxvEntries() const { return m_auxvEntries; }
    const size_t GetAuxvSize() const { return m_auxvEntries.size() * sizeof(elf_aux_entry); }

    // 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);

private:
    bool GetAuxvEntries();
    bool EnumerateModuleMappings();
    bool GetDSOInfo();
    bool GetELFInfo(uint64_t baseAddress);
    bool EnumerateMemoryRegionsWithDAC(const char* programPath, MINIDUMP_TYPE minidumpType);
    bool EnumerateManagedModules(IXCLRDataProcess* clrDataProcess);
    void ReplaceModuleMapping(CLRDATA_ADDRESS baseAddress, const char* pszName);
    bool ReadMemory(void* address, void* buffer, size_t size);
    void InsertMemoryBackedRegion(const MemoryRegion& region);
    void InsertMemoryRegion(uint64_t address, size_t size);
    void InsertMemoryRegion(const MemoryRegion& region);
    uint32_t GetMemoryRegionFlags(uint64_t start);
    bool ValidRegion(const MemoryRegion& region);
    void CombineMemoryRegions();
};