[Tizen] Add printf_status functions to libdnetmemoryenumlib
[platform/upstream/dotnet/runtime.git] / src / coreclr / debug / createdump / dnetmemoryenumlib.cpp
1 /*
2  * The MIT License (MIT)
3  *
4  * Copyright (c) 2019-2021 Samsung Electronics Co., Ltd.
5  *
6  * All rights reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in all
16  * copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26
27 #include <stdarg.h>
28 #include <iostream>
29 #include <vector>
30 #include "createdump.h"
31 #include "dnetmemoryenumlib.h"
32
33 const int DEFAULT_SIGNAL = 6;
34
35 bool g_diagnostics = false;
36 bool g_diagnosticsVerbose = false;
37
38 std::vector<SimpleMemoryRegion> sm_regions;
39
40 int
41 prepare_crash_info(pid_t pid, elf_prstatus **statuses, int statuses_count,
42                         DUMP_TYPE minidump_type, ReleaseHolder<CrashInfo> &crash_info)
43 {
44     g_diagnostics = true;
45
46     std::vector<elf_prstatus*> stats(statuses, statuses + statuses_count);
47
48     MINIDUMP_TYPE minidumpType;
49
50     switch (minidump_type) {
51     case DT_NORMAL:
52     default:
53         minidumpType = MiniDumpNormal;
54         break;
55     case DT_WITH_PRIV_AND_SHARED_MEM:
56         minidumpType = MiniDumpWithPrivateReadWriteMemory;
57         break;
58     case DT_FULL:
59         minidumpType = MiniDumpWithFullMemory;
60         break;
61     }
62
63     int exitCode = REGERR_OK;
64
65     if (pid != 0)
66     {
67         crash_info = new CrashInfo(pid, true, pid, DEFAULT_SIGNAL);
68
69         if (!crash_info->Initialize())
70         {
71             return REGERR_CRASHINFO_INITIALIZE_ERROR;
72         }
73
74         if (!crash_info->EnumerateAndSuspendThreads(false))
75         {
76             return REGERR_ENUMERATION_ERROR;
77         }
78         crash_info->SetThreadsRegisters(stats);
79         if (!crash_info->GatherCrashInfo(minidumpType, false))
80         {
81             return REGERR_GATHER_CRASHINFO_ERROR;
82         }
83         if (!crash_info->EnumerateMemoryRegionsWithDAC(minidumpType))
84         {
85             return REGERR_ENUMERATIONDAC_ERROR;
86         }
87     }
88     else
89     {
90         exitCode = REGERR_WRONG_PID;
91     }
92     return exitCode;
93 }
94
95 extern "C" DLLEXPORT int
96 DotNetMemoryEnumInit()
97 {
98     int exitCode = PAL_InitializeDLL();
99     return exitCode;
100 }
101
102 extern "C" DLLEXPORT void
103 DotNetMemoryEnumFinish()
104 {
105     PAL_TerminateEx(0);
106 }
107
108 extern "C" DLLEXPORT int
109 DotNetMemoryWriteDump(pid_t pid, elf_prstatus **statuses, int statuses_count,
110                         DUMP_TYPE minidump_type, const char *dump_path)
111 {
112     ReleaseHolder<CrashInfo> crashInfo;
113     int exitCode = prepare_crash_info(pid, statuses, statuses_count, minidump_type, crashInfo);
114
115     if (exitCode != REGERR_OK)
116         return exitCode;
117
118     DumpWriter dumpWriter(*crashInfo);
119
120     if (!dumpWriter.OpenDump(dump_path))
121         exitCode = REGERR_OPENDUMP_ERROR;
122
123     if (!dumpWriter.WriteDump())
124         exitCode = REGERR_WRITEDUMP_ERROR;
125
126     return exitCode;
127 }
128
129 void
130 printf_status(const char* format, ...)
131 {
132     va_list args;
133     va_start(args, format);
134     fprintf(stdout, "[createdump] ");
135     vfprintf(stdout, format, args);
136     fflush(stdout);
137     va_end(args);
138 }
139
140 void
141 printf_error(const char* format, ...)
142 {
143     va_list args;
144     va_start(args, format);
145     fprintf(stderr, "[createdump] ");
146     vfprintf(stderr, format, args);
147     fflush(stderr);
148     va_end(args);
149 }
150
151 void
152 trace_printf(const char* format, ...)
153 {
154     if (g_diagnostics)
155     {
156         va_list args;
157         va_start(args, format);
158         fprintf(stdout, "[createdump] ");
159         vfprintf(stdout, format, args);
160         fflush(stdout);
161         va_end(args);
162     }
163 }
164
165 void
166 trace_verbose_printf(const char* format, ...)
167 {
168     if (g_diagnosticsVerbose)
169     {
170         va_list args;
171         va_start(args, format);
172         fprintf(stdout, "[createdump] ");
173         vfprintf(stdout, format, args);
174         fflush(stdout);
175         va_end(args);
176     }
177 }