[sheepdog] [PATCH v2] logger: use gdb commands to dump stack and variable
MORITA Kazutaka
morita.kazutaka at gmail.com
Thu Aug 29 09:19:13 CEST 2013
From: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
This patch uses gdb features to dump stack and variable, and
simplifies logger.c a lot. With this patch, gdb outputs will be
logged to gdb.txt instead of sheep.txt.
Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
---
v2:
- pass getpid() instead of gettid() to get a stacktrace from every thread.
lib/logger.c | 140 +++++++++++++---------------------------------------------
1 file changed, 30 insertions(+), 110 deletions(-)
diff --git a/lib/logger.c b/lib/logger.c
index 13d2aa1..1a31314 100644
--- a/lib/logger.c
+++ b/lib/logger.c
@@ -681,27 +681,11 @@ static bool check_gdb(void)
return system("which gdb > /dev/null") == 0;
}
-/*
- * __builtin_frame_address() returns address in frame pointer register if any
- * (e.g, in x86 it returns EBP). If no dedicated register, the frame address is
- * normally the address of the first word pushed on to the stack by the function
- *
- * For a normal subroutine setup, above the value __builtin_frame_address
- * returns, there are two addresses, which stores old EBP and old EIP, being
- * pushed on to the stack. So we have to plus 2 to get the right value for the
- * frame address, which is expected by GDB.
- *
- * This is tested on X86, other architetures aren't tested. But even if this
- * formula is wrong, GDB just doesn't procude anything useful after panic.
- */
-#define FRAME_POINTER ((unsigned long *)__builtin_frame_address(0) + 2)
-
-__attribute__ ((__noinline__))
-int __sd_dump_variable(const char *var)
+static int gdb_cmd(const char *cmd)
{
- char cmd[ARG_MAX], path[PATH_MAX], info[256];
- FILE *f = NULL;
- void *base_sp = FRAME_POINTER;
+ char path[PATH_MAX], time_str[256], cmd_str[ARG_MAX];
+ time_t ti;
+ struct tm tm;
if (!check_gdb()) {
sd_debug("cannot find gdb");
@@ -711,102 +695,38 @@ int __sd_dump_variable(const char *var)
if (get_my_path(path, sizeof(path)) < 0)
return -1;
- snprintf(cmd, sizeof(cmd), "gdb -nw %s %d -batch -ex 'set width 80'"
- " -ex 'select-frame %p' -ex 'up 1' -ex 'p %s' 2> /dev/null",
- path, gettid(), base_sp, var);
- f = popen(cmd, "r");
- if (f == NULL) {
- sd_err("failed to run gdb");
- return -1;
- }
-
- /*
- * The expected outputs of gdb are:
- *
- * [some info we don't need]
- * $1 = {
- * <variable info>
- * }
- */
- sd_emerg("dump %s", var);
- while (fgets(info, sizeof(info), f) != NULL) {
- if (info[0] == '$') {
- sd_emerg("%s", chomp(info));
- break;
- }
- }
- while (fgets(info, sizeof(info), f) != NULL)
- sd_emerg("%s", chomp(info));
-
- pclose(f);
- return 0;
+ time(&ti);
+ localtime_r(&ti, &tm);
+ strftime(time_str, sizeof(time_str), "%b %2d %H:%M:%S ", &tm);
+
+ snprintf(cmd_str, sizeof(cmd_str),
+ "gdb -nw %s %d -batch >/dev/null 2>&1"
+ " -ex 'set logging on'"
+ " -ex 'echo \\n'"
+ " -ex 'echo ==\\n'"
+ " -ex 'echo == %s\\n'"
+ " -ex 'echo == program: %s\\n'"
+ " -ex 'echo == command: %s\\n'"
+ " -ex 'echo ==\\n'"
+ " -ex '%s'"
+ " -ex 'set logging off'",
+ path, getpid(), time_str, path, cmd, cmd);
+
+ return system(cmd_str);
}
-__attribute__ ((__noinline__))
-static int dump_stack_frames(void)
+int __sd_dump_variable(const char *var)
{
- char path[PATH_MAX];
- int i, stack_no = 0;
- void *base_sp = FRAME_POINTER;
-
- if (!check_gdb()) {
- sd_debug("cannot find gdb");
- return -1;
- }
-
- if (get_my_path(path, sizeof(path)) < 0)
- return -1;
+ char cmd[256];
- for (i = 1; i < SD_MAX_STACK_DEPTH; i++) {
- char cmd[ARG_MAX], info[256];
- FILE *f = NULL;
- bool found = false;
+ snprintf(cmd, sizeof(cmd), "p %s", var);
- snprintf(cmd, sizeof(cmd), "gdb -nw %s %d -batch"
- " -ex 'set width 80' -ex 'select-frame %p'"
- " -ex 'up %d' -ex 'info locals' 2> /dev/null",
- path, gettid(), base_sp, i);
- f = popen(cmd, "r");
- if (f == NULL)
- return -1;
- /*
- * The expected outputs of gdb are:
- *
- * [some info we don't need]
- * #<stack no> <addr> in <func>(<arg>) at <file>:<line>
- * <line> <source>
- * <local variables>
- */
- while (fgets(info, sizeof(info), f) != NULL) {
- int no;
- if (sscanf(info, "#%d ", &no) == 1) {
- if (no <= stack_no) {
- /* reached to the end of the stacks */
- pclose(f);
- return 0;
- }
- stack_no = no;
- found = true;
- sd_emerg("%s", chomp(info));
- break;
- }
- }
-
- if (!found) {
- sd_info("Cannot get info from GDB");
- sd_info("Set /proc/sys/kernel/yama/ptrace_scope to"
- " zero if you are using Ubuntu.");
- pclose(f);
- return -1;
- }
-
- while (fgets(info, sizeof(info), f) != NULL)
- sd_emerg("%s", chomp(info));
-
- pclose(f);
- }
+ return gdb_cmd(cmd);
+}
- return 0;
+static int dump_stack_frames(void)
+{
+ return gdb_cmd("thread apply all where full");
}
__attribute__ ((__noinline__))
--
1.7.9.5
More information about the sheepdog
mailing list