summaryrefslogtreecommitdiff
path: root/src/debug/createdump/main.cpp
blob: cb4d3c6fcec5668bec31de2fa97fada6cc703ccc (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
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
// 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.

#include "createdump.h"

const char* g_help = "createdump [options] pid\n" 
"-f, --name - dump path and file name. The pid can be placed in the name with %d. The default is '/tmp/coredump.%d'\n"
"-n, --normal - create minidump.\n"
"-h, --withheap - create minidump with heap (default).\n" 
"-t, --triage - create triage minidump.\n" 
"-u, --full - create full core dump.\n" 
"-d, --diag - enable diagnostic messages.\n";

bool CreateDumpCommon(const char* programPath, const char* dumpPathTemplate, MINIDUMP_TYPE minidumpType, CrashInfo* crashInfo);

//
// Main entry point
//
int __cdecl main(const int argc, const char* argv[])
{
    MINIDUMP_TYPE minidumpType = MiniDumpWithPrivateReadWriteMemory;
#ifdef ANDROID
    const char* dumpPathTemplate = "/data/local/tmp/coredump.%d";
#else
    const char* dumpPathTemplate = "/tmp/coredump.%d";
#endif
    pid_t pid = 0;

    int exitCode = PAL_InitializeDLL();
    if (exitCode != 0)
    {
        fprintf(stderr, "PAL initialization FAILED %d\n", exitCode);
        return exitCode;
    }

    // Parse off the program name leaving just the path. Used to locate/load the DAC module.
    std::string programPath;
    programPath.append(*argv++);
    size_t last = programPath.find_last_of('/');
    programPath = programPath.substr(0, last);

    // Parse the command line options and target pid
    for (int i = 1; i < argc; i++)
    {
        if (*argv != nullptr)
        {
            if ((strcmp(*argv, "-f") == 0) || (strcmp(*argv, "--name") == 0))
            {
                dumpPathTemplate = *++argv;
            }
            else if ((strcmp(*argv, "-n") == 0) || (strcmp(*argv, "--normal") == 0))
            {
                minidumpType = MiniDumpNormal;
            }
            else if ((strcmp(*argv, "-h") == 0) || (strcmp(*argv, "--withheap") == 0))
            {
                minidumpType = MiniDumpWithPrivateReadWriteMemory;
            }
            else if ((strcmp(*argv, "-t") == 0) || (strcmp(*argv, "--triage") == 0))
            {
                minidumpType = MiniDumpFilterTriage;
            }
            else if ((strcmp(*argv, "-u") == 0) || (strcmp(*argv, "--full") == 0))
            {
                minidumpType = MiniDumpWithFullMemory;
            }
            else if ((strcmp(*argv, "-d") == 0) || (strcmp(*argv, "--diag") == 0))
            {
                g_diagnostics = true;
            }
            else {
                pid = atoll(*argv);
            }
            argv++;
        }
    }
    if (pid != 0)
    { 
        ReleaseHolder<DumpDataTarget> dataTarget = new DumpDataTarget(pid);
        ReleaseHolder<CrashInfo> crashInfo = new CrashInfo(pid, dataTarget, false);

        // The initialize the data target's ReadVirtual support (opens /proc/$pid/mem)
        if (dataTarget->Initialize(crashInfo))
        {
            if (!CreateDumpCommon(programPath.c_str(), dumpPathTemplate, minidumpType, crashInfo))
            {
                exitCode = -1;
            }
        }
        else 
        {
            exitCode = -1;
        }
    }
    else
    {
        // if no pid or invalid command line option
        fprintf(stderr, "%s", g_help);
        exitCode = -1;
    }
    PAL_TerminateEx(exitCode);
    return exitCode;
}