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