Remove building with NOCRYPTO option
[minix3.git] / external / bsd / kyua-testers / dist / stacktrace.c
blob5014370bd86e84c48756abed052f5504c52a971f
1 // Copyright 2012 Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of Google Inc. nor the names of its contributors
14 // may be used to endorse or promote products derived from this software
15 // without specific prior written permission.
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "stacktrace.h"
31 #include <sys/param.h>
32 #include <sys/wait.h>
34 #include <assert.h>
35 #include <fcntl.h>
36 #include <stdarg.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
42 #include "defs.h"
43 #include "fs.h"
44 #include "env.h"
45 #include "error.h"
46 #include "run.h"
47 #include "text.h"
50 /// Built-in path to GDB.
51 ///
52 /// This should be an absolute path for deterministic behavior. We also accept
53 /// a basename to cope with any issues that might arise from an invalid
54 /// configure check or a manual override of the GDB constant, in which case the
55 /// exec call below will (try to) locate the binary in the path.
56 ///
57 /// Note that the program pointed to by this variable is not required to exist.
58 /// If it does not, we fail gracefully.
59 ///
60 /// Test cases can override the value of this built-in constant to unit-test the
61 /// behavior of the functions below.
62 const char* kyua_stacktrace_gdb = GDB;
63 #undef GDB // We really want to use the variable, not the macro.
66 /// Time to give to the external GDB process to produce a stack trace.
67 ///
68 /// Test cases can override the value of this built-in constant to unit-test the
69 /// behavior of the functions below.
70 unsigned long kyua_stacktrace_gdb_timeout = 300;
73 /// Maximum length of the core file name, if known.
74 ///
75 /// Some operating systems impose a maximum length on the basename of the core
76 /// file. If MAXCOMLEN is defined, then we need to truncate the program name to
77 /// this length before searching for the core file. If we cannot figure out
78 /// what this limit is, we set it to zero, which we consider later as
79 /// "unlimited".
80 #if !defined(MAXCOMLEN)
81 # define MAXCOMLEN 0
82 #endif
85 static void run_gdb(const char* program, const char* core_name, FILE* output)
86 KYUA_DEFS_NORETURN;
89 /// Constructs the parameters to run GDB with.
90 ///
91 /// \param original_run_params Parameters used to run the binary that generated
92 /// the core dump.
93 ///
94 /// \return The run parameters with which to run GDB.
95 static kyua_run_params_t
96 gdb_run_params(const kyua_run_params_t* original_run_params)
98 kyua_run_params_t run_params = *original_run_params;
99 run_params.timeout_seconds = kyua_stacktrace_gdb_timeout;
100 return run_params;
104 /// Body of a subprocess to execute GDB.
106 /// This should be called from the child created by a kyua_run_fork() call,
107 /// which means that we do not have to take care of isolating the process.
109 /// \pre The caller must have flushed stdout before spawning this process, to
110 /// prevent double-flushing and/or corruption of data.
112 /// \param program Path to the program being debugged. Can be relative to
113 /// the given work directory.
114 /// \param core_name Path to the dumped core. Use find_core() to deduce
115 /// a valid candidate. Can be relative to the given work directory.
116 /// \param output Stream to which to send the output of GDB.
117 static void
118 run_gdb(const char* program, const char* core_name, FILE* output)
120 // TODO(jmmv): Should be done by kyua_run_fork(), but doing so would change
121 // the semantics of the ATF interface. Need to evaluate this carefully.
122 const kyua_error_t error = kyua_env_unset("TERM");
123 if (kyua_error_is_set(error)) {
124 kyua_error_warn(error, "Failed to unset TERM; GDB may misbehave");
125 free(error);
128 (void)close(STDIN_FILENO);
129 #if defined(__minix) && !defined(NDEBUG)
130 const int input_fd =
131 #endif /* defined(__minix) && !defined(NDEBUG) */
132 open("/dev/null", O_RDONLY);
133 assert(input_fd == STDIN_FILENO);
135 const int output_fd = fileno(output);
136 assert(output_fd != -1); // We expect a file-backed stream.
137 if (output_fd != STDOUT_FILENO) {
138 fflush(stdout);
139 (void)dup2(output_fd, STDOUT_FILENO);
141 if (output_fd != STDERR_FILENO) {
142 fflush(stderr);
143 (void)dup2(output_fd, STDERR_FILENO);
145 if (output_fd != STDOUT_FILENO && output_fd != STDERR_FILENO)
146 fclose(output);
148 const char* const gdb_args[] = {
149 "gdb", "-batch", "-q", "-ex", "bt", program, core_name, NULL };
150 kyua_run_exec(kyua_stacktrace_gdb, gdb_args);
154 /// Truncates a string.
156 /// \param source The string to truncate.
157 /// \param [out] buffer Output buffer into which to store the truncated text.
158 /// \param buffer_length Size of the buffer.
160 /// \return A pointer to the buffer.
161 static const char*
162 slice(const char* source, char* buffer, const size_t buffer_length)
164 const size_t source_length = strlen(source);
165 if (source_length < buffer_length) {
166 strcpy(buffer, source);
167 } else {
168 memcpy(buffer, source, buffer_length - 1);
169 buffer[buffer_length - 1] = '\0';
171 return buffer;
175 static char* try_core(const char* format, ...) KYUA_DEFS_FORMAT_PRINTF(1, 2);
178 /// Generates a path and checks if it exists.
180 /// \param format Formatting string for the path to generate.
181 /// \param ... Arguments to the formatting string.
183 /// \return A dynamically-allocated string containing the generated path if
184 /// there were no errors and the file pointed to by such path exists; NULL
185 /// otherwise. The returned string must be relesed with free() by the caller.
186 static char*
187 try_core(const char* format, ...)
189 char* path;
190 va_list ap;
192 va_start(ap, format);
193 kyua_error_t error = kyua_text_vprintf(&path, format, ap);
194 va_end(ap);
195 if (kyua_error_is_set(error)) {
196 // Something went really wrong (and should not have happened). Ignore
197 // this core file candidate.
198 kyua_error_free(error);
199 return NULL;
202 if (access(path, F_OK) == -1) {
203 free(path);
204 return NULL;
205 } else {
206 return path;
211 /// Simple version of basename() that operates on constant strings.
213 /// This is not 100% compatible with basename() because it may return an
214 /// unexpected string if the path ends with a slash. For our purposes, this
215 /// does not matter, so we can use this simplified trick.
217 /// \param path Path from which to compute the basename.
219 /// \return A pointer within the input path pointing at the last component.
220 static const char*
221 const_basename(const char* path)
223 const char* last_slash = strrchr(path, '/');
224 return last_slash == NULL ? path : last_slash + 1;
228 /// Looks for a core file for the given program.
230 /// \param name The basename of the binary that generated the core.
231 /// \param directory The directory from which the program was run. We expect to
232 /// find the core file in this directory.
233 /// \param dead_pid PID of the process that generated the core. This is needed
234 /// in some platforms.
236 /// \return The path to the core file if found; otherwise none.
237 char*
238 kyua_stacktrace_find_core(const char* name, const char* directory,
239 const pid_t dead_pid)
241 char* candidate = NULL;
243 // TODO(jmmv): Other than checking all these defaults, in NetBSD we should
244 // also inspect the value of the kern.defcorename sysctl(2) MIB and use that
245 // as the first candidate.
247 // In Linux, the way to determine the name is by looking at
248 // /proc/sys/kernel/core_{pattern,uses_pid} as described by core(5).
249 // Unfortunately, there does not seem to be a standard API to parse these
250 // files, which makes checking for core files quite difficult if the
251 // defaults have been modified.
253 // Default NetBSD naming scheme.
254 if (candidate == NULL && MAXCOMLEN > 0) {
255 char truncated[MAXCOMLEN + 1];
256 candidate = try_core("%s/%s.core", directory,
257 slice(name, truncated, sizeof(truncated)));
260 // Common naming scheme without the MAXCOMLEN truncation.
261 if (candidate == NULL)
262 candidate = try_core("%s/%s.core", directory, name);
264 // Common naming scheme found in Linux systems.
265 if (candidate == NULL)
266 candidate = try_core("%s/core.%d", directory, (int)dead_pid);
268 // Default Mac OS X naming scheme.
269 if (candidate == NULL)
270 candidate = try_core("/cores/core.%d", (int)dead_pid);
272 // Common naming scheme found in Linux systems. Attempted last due to the
273 // genericity of the core file name.
274 if (candidate == NULL)
275 candidate = try_core("%s/core", directory);
277 if (candidate != NULL) {
278 char* abs_candidate;
279 kyua_error_t error = kyua_fs_make_absolute(candidate, &abs_candidate);
280 if (kyua_error_is_set(error)) {
281 kyua_error_free(error);
282 return candidate; // Return possibly-relative path as a best guess.
283 } else {
284 free(candidate);
285 return abs_candidate;
287 } else {
288 return candidate;
293 /// Gathers a stacktrace of a crashed program.
295 /// \param program The name of the binary that crashed and dumped a core file.
296 /// Can be either absolute or relative.
297 /// \param dead_pid The PID of the process that dumped core.
298 /// \param original_run_params Parameters with which the original binary was
299 /// executed. These are reused to run GDB, but adjusted with GDB-specific
300 /// settings. Of special interest, the work directory is used to search for
301 /// the core file.
302 /// \param output Stream into which to dump the stack trace and any additional
303 /// information.
305 /// \post If anything goes wrong, the diagnostic messages are written to the
306 /// output. This function returns no errors.
307 void
308 kyua_stacktrace_dump(const char* program, const pid_t dead_pid,
309 const kyua_run_params_t* original_run_params, FILE* output)
311 fprintf(output, "Process with PID %d dumped core; attempting to gather "
312 "stack trace\n", dead_pid);
314 const kyua_run_params_t run_params = gdb_run_params(original_run_params);
316 kyua_error_t error = kyua_error_ok();
318 char* core_file = kyua_stacktrace_find_core(const_basename(program),
319 run_params.work_directory,
320 dead_pid);
321 if (core_file == NULL) {
322 fprintf(output, "Cannot find any core file\n");
323 goto out;
326 // We must flush the output stream right before invoking fork, so that the
327 // subprocess does not have any unflushed data. Failure to do so results in
328 // the messages above being written twice to the output.
329 fflush(output);
330 pid_t pid;
331 error = kyua_run_fork(&run_params, &pid);
332 if (!kyua_error_is_set(error) && pid == 0) {
333 run_gdb(program, core_file, output);
335 assert(pid != -1 && pid != 0);
336 if (kyua_error_is_set(error))
337 goto out_core_file;
339 int status; bool timed_out;
340 error = kyua_run_wait(pid, &status, &timed_out);
341 if (kyua_error_is_set(error))
342 goto out_core_file;
344 if (timed_out) {
345 fprintf(output, "GDB failed; timed out\n");
346 } else {
347 if (WIFEXITED(status)) {
348 if (WEXITSTATUS(status) == EXIT_SUCCESS)
349 fprintf(output, "GDB exited successfully\n");
350 else
351 fprintf(output, "GDB failed with code %d; see output above for "
352 "details\n", WEXITSTATUS(status));
353 } else {
354 assert(WIFSIGNALED(status));
355 fprintf(output, "GDB received signal %d; see output above for "
356 "details\n", WTERMSIG(status));
360 out_core_file:
361 free(core_file);
362 out:
363 if (kyua_error_is_set(error)) {
364 kyua_error_fprintf(output, error, "Failed to gather stacktrace");
365 free(error);