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