|
|
01add4 |
From 77243901ca72e4f49ed650eecfe501edfb2344df Mon Sep 17 00:00:00 2001
|
|
|
01add4 |
From: Matej Habrnal <mhabrnal@redhat.com>
|
|
|
01add4 |
Date: Tue, 30 Aug 2016 11:09:50 +0200
|
|
|
01add4 |
Subject: [PATCH] testsuite: add test for limit frame number in GDB core
|
|
|
01add4 |
unwinder
|
|
|
01add4 |
|
|
|
01add4 |
Related to #1260074
|
|
|
01add4 |
|
|
|
01add4 |
Signed-off-by: Matej Habrnal <mhabrnal@redhat.com>
|
|
|
01add4 |
---
|
|
|
01add4 |
tests/core_stacktrace.at | 158 +++++++++++++++++++++++++++++++++++++++
|
|
|
01add4 |
1 file changed, 158 insertions(+)
|
|
|
01add4 |
|
|
|
01add4 |
diff --git a/tests/core_stacktrace.at b/tests/core_stacktrace.at
|
|
|
01add4 |
index f45e126..313d8b8 100644
|
|
|
01add4 |
--- a/tests/core_stacktrace.at
|
|
|
01add4 |
+++ b/tests/core_stacktrace.at
|
|
|
01add4 |
@@ -197,3 +197,161 @@ main(void)
|
|
|
01add4 |
return 0;
|
|
|
01add4 |
}
|
|
|
01add4 |
]])
|
|
|
01add4 |
+
|
|
|
01add4 |
+## --------------------------------- ##
|
|
|
01add4 |
+## sr_core_stacktrace_from_gdb_limit ##
|
|
|
01add4 |
+## --------------------------------- ##
|
|
|
01add4 |
+
|
|
|
01add4 |
+AT_TESTFUN([sr_core_stacktrace_from_gdb_limit],
|
|
|
01add4 |
+[[
|
|
|
01add4 |
+#define _GNU_SOURCE
|
|
|
01add4 |
+#include "stacktrace.h"
|
|
|
01add4 |
+#include "core/stacktrace.h"
|
|
|
01add4 |
+#include "core/thread.h"
|
|
|
01add4 |
+#include "core/frame.h"
|
|
|
01add4 |
+#include "core/unwind.h"
|
|
|
01add4 |
+#include "strbuf.h"
|
|
|
01add4 |
+#include "utils.h"
|
|
|
01add4 |
+#include "report_type.h"
|
|
|
01add4 |
+#include <assert.h>
|
|
|
01add4 |
+#include <stdio.h>
|
|
|
01add4 |
+#include "internal_unwind.h"
|
|
|
01add4 |
+#include <stdlib.h>
|
|
|
01add4 |
+#include <unistd.h>
|
|
|
01add4 |
+#include <sys/types.h>
|
|
|
01add4 |
+#include <sys/wait.h>
|
|
|
01add4 |
+#include <errno.h>
|
|
|
01add4 |
+#include <err.h>
|
|
|
01add4 |
+#include <unistd.h>
|
|
|
01add4 |
+#include <fcntl.h>
|
|
|
01add4 |
+
|
|
|
01add4 |
+char *generate_coredump(int start)
|
|
|
01add4 |
+{
|
|
|
01add4 |
+
|
|
|
01add4 |
+ if (start)
|
|
|
01add4 |
+ {
|
|
|
01add4 |
+ return generate_coredump(--start);
|
|
|
01add4 |
+ }
|
|
|
01add4 |
+
|
|
|
01add4 |
+ const char* coredump_pattern = "/tmp/satyr.core";
|
|
|
01add4 |
+
|
|
|
01add4 |
+ char *mypid = NULL;
|
|
|
01add4 |
+ asprintf(&mypid, "%d", getpid());
|
|
|
01add4 |
+ if (mypid == NULL)
|
|
|
01add4 |
+ err(1, "asprintf");
|
|
|
01add4 |
+
|
|
|
01add4 |
+ pid_t pid = fork();
|
|
|
01add4 |
+ if (pid < 0)
|
|
|
01add4 |
+ err(1, "fork");
|
|
|
01add4 |
+ if (pid == 0)
|
|
|
01add4 |
+ {
|
|
|
01add4 |
+ char *args[] = { "gcore", "-o", (char *)coredump_pattern, mypid, NULL };
|
|
|
01add4 |
+ execv("/usr/bin/gcore", args);
|
|
|
01add4 |
+ }
|
|
|
01add4 |
+
|
|
|
01add4 |
+ int status;
|
|
|
01add4 |
+ int r;
|
|
|
01add4 |
+ while ((r = waitpid(pid, &status, 0)) < 0)
|
|
|
01add4 |
+ {
|
|
|
01add4 |
+ if (errno != EAGAIN)
|
|
|
01add4 |
+ err(1, "waitpid");
|
|
|
01add4 |
+ }
|
|
|
01add4 |
+
|
|
|
01add4 |
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
|
|
|
01add4 |
+ errx(1, "gcore failed");
|
|
|
01add4 |
+
|
|
|
01add4 |
+ return sr_asprintf("%s.%s", coredump_pattern, mypid);
|
|
|
01add4 |
+}
|
|
|
01add4 |
+struct sr_strbuf *
|
|
|
01add4 |
+get_backtrace(const char *core_file, const char *executable)
|
|
|
01add4 |
+{
|
|
|
01add4 |
+ unsigned i = 0;
|
|
|
01add4 |
+ char *args[25];
|
|
|
01add4 |
+ args[i++] = (char*)"/usr/bin/gdb";
|
|
|
01add4 |
+ args[i++] = (char*)"-batch";
|
|
|
01add4 |
+ args[i++] = (char*)"-iex";
|
|
|
01add4 |
+ args[i++] = (char*)"set debug-file-directory /";
|
|
|
01add4 |
+ args[i++] = (char*)"-ex";
|
|
|
01add4 |
+ args[i++] = sr_asprintf("file %s", executable);
|
|
|
01add4 |
+ args[i++] = (char*)"-ex";
|
|
|
01add4 |
+ args[i++] = sr_asprintf("core-file %s", core_file);
|
|
|
01add4 |
+ args[i++] = (char*)"-ex";
|
|
|
01add4 |
+ args[i++] = (char*)"thread apply all backtrace 1024 full";
|
|
|
01add4 |
+ args[i++] = (char*)"-ex";
|
|
|
01add4 |
+ args[i++] = (char*)"info sharedlib";
|
|
|
01add4 |
+ args[i++] = (char*)"-ex";
|
|
|
01add4 |
+ args[i++] = (char*)"print (char*)__abort_msg";
|
|
|
01add4 |
+ args[i++] = (char*)"-ex";
|
|
|
01add4 |
+ args[i++] = (char*)"print (char*)__glib_assert_msg";
|
|
|
01add4 |
+ args[i++] = (char*)"-ex";
|
|
|
01add4 |
+ args[i++] = (char*)"info all-registers";
|
|
|
01add4 |
+ args[i++] = (char*)"-ex";
|
|
|
01add4 |
+ args[i++] = (char*)"disassemble";
|
|
|
01add4 |
+ args[i++] = NULL;
|
|
|
01add4 |
+
|
|
|
01add4 |
+ int p[2];
|
|
|
01add4 |
+ int pipe_return = pipe(p);
|
|
|
01add4 |
+ if (pipe_return != 0)
|
|
|
01add4 |
+ err(1, "pipe");
|
|
|
01add4 |
+
|
|
|
01add4 |
+ pid_t pid = fork();
|
|
|
01add4 |
+ if (pid < 0)
|
|
|
01add4 |
+ err(1, "fork");
|
|
|
01add4 |
+ if (pid == 0) /* child */
|
|
|
01add4 |
+ {
|
|
|
01add4 |
+ close(p[0]);
|
|
|
01add4 |
+ dup2(p[1], 1); // send stdout to the pipe
|
|
|
01add4 |
+ dup2(p[1], 2); // send stderr to the pipe
|
|
|
01add4 |
+
|
|
|
01add4 |
+ execv(args[0], args);
|
|
|
01add4 |
+ }
|
|
|
01add4 |
+ close(p[1]);
|
|
|
01add4 |
+
|
|
|
01add4 |
+ struct sr_strbuf *gdb_buf = sr_strbuf_new();
|
|
|
01add4 |
+ sr_strbuf_init(gdb_buf);
|
|
|
01add4 |
+ char buf[256];
|
|
|
01add4 |
+ ssize_t size;
|
|
|
01add4 |
+ while((size = read(p[0], buf, sizeof(buf)-1)) > 0 && errno != EINTR)
|
|
|
01add4 |
+ {
|
|
|
01add4 |
+ buf[size] = '\0';
|
|
|
01add4 |
+ sr_strbuf_append_str(gdb_buf, (const char*) buf);
|
|
|
01add4 |
+ }
|
|
|
01add4 |
+
|
|
|
01add4 |
+ int status, r;
|
|
|
01add4 |
+ while ((r = waitpid(pid, &status, 0)) < 0)
|
|
|
01add4 |
+ {
|
|
|
01add4 |
+ if (errno != EAGAIN)
|
|
|
01add4 |
+ err(1, "waitpid");
|
|
|
01add4 |
+ }
|
|
|
01add4 |
+
|
|
|
01add4 |
+ return gdb_buf;
|
|
|
01add4 |
+}
|
|
|
01add4 |
+
|
|
|
01add4 |
+int
|
|
|
01add4 |
+main(int argc, char* argv[])
|
|
|
01add4 |
+{
|
|
|
01add4 |
+ char *coredump_path = generate_coredump(257);
|
|
|
01add4 |
+
|
|
|
01add4 |
+ struct sr_strbuf *gdb_output = get_backtrace(coredump_path, argv[0]);
|
|
|
01add4 |
+ assert(gdb_output);
|
|
|
01add4 |
+ assert(gdb_output->buf);
|
|
|
01add4 |
+
|
|
|
01add4 |
+ char *error_msg = NULL;
|
|
|
01add4 |
+ struct sr_core_stacktrace *core_stacktrace = sr_core_stacktrace_from_gdb(gdb_output->buf, coredump_path, argv[0], &error_msg);
|
|
|
01add4 |
+ assert(!error_msg);
|
|
|
01add4 |
+
|
|
|
01add4 |
+ struct sr_core_thread *threads = core_stacktrace->threads;
|
|
|
01add4 |
+ struct sr_core_frame *frames = threads->frames;
|
|
|
01add4 |
+ unsigned nframes = 0;
|
|
|
01add4 |
+ for(; frames; ++nframes, frames = frames->next)
|
|
|
01add4 |
+ ;
|
|
|
01add4 |
+
|
|
|
01add4 |
+ /* max num of frames is CORE_STACKTRACE_FRAME_LIMIT */
|
|
|
01add4 |
+ assert(nframes == CORE_STACKTRACE_FRAME_LIMIT);
|
|
|
01add4 |
+
|
|
|
01add4 |
+ free(coredump_path);
|
|
|
01add4 |
+ sr_strbuf_free(gdb_output);
|
|
|
01add4 |
+
|
|
|
01add4 |
+ return 0;
|
|
|
01add4 |
+}
|
|
|
01add4 |
+]])
|
|
|
01add4 |
--
|
|
|
01add4 |
2.17.1
|
|
|
01add4 |
|