Add -k option to print stack trace after each syscall

Print the stack trace of the traced process after each system call when
-k option is specified.  It is implemented using libunwind to unwind the
stack and to obtain the function name pointed by the IP.

Based on the code that was originally taken from strace-plus
of Philip J. Guo.

* configure.ac: Add --with-libunwind option.  Check libunwind support.
* Makefile.am: Add libunwind support.
* defs.h (struct tcb) [USE_LIBUNWIND]: Append libunwind specific fields.
[USE_LIBUNWIND] (stack_trace_enabled, alloc_mmap_cache,
delete_mmap_cache, print_stacktrace): New prototypes.
* mem.c (print_mmap, sys_munmap, sys_mprotect): Add libunwind support.
* process.c (sys_execve): Likewise.
* strace.c (usage, alloctcb, droptcb, init): Likewise.
* syscall.c (trace_syscall_exiting): Likewise.
* unwind.c: New file.
* strace.1: Document -k option.
diff --git a/strace.c b/strace.c
index 35ee7be..a8b04b0 100644
--- a/strace.c
+++ b/strace.c
@@ -50,6 +50,10 @@
 extern int optind;
 extern char *optarg;
 
+#ifdef USE_LIBUNWIND
+/* if this is true do the stack trace for every system call */
+bool stack_trace_enabled = false;
+#endif
 
 #if defined __NR_tkill
 # define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
@@ -233,6 +237,10 @@
 -E var -- remove var from the environment for command\n\
 -P path -- trace accesses to path\n\
 "
+#ifdef USE_LIBUNWIND
+"-k obtain stack trace between each syscall\n\
+"
+#endif
 /* ancient, no one should use it
 -F -- attempt to follow vforks (deprecated, use -f)\n\
  */
@@ -695,6 +703,12 @@
 #if SUPPORTED_PERSONALITIES > 1
 			tcp->currpers = current_personality;
 #endif
+
+#ifdef USE_LIBUNWIND
+			if (stack_trace_enabled)
+				init_libunwind_ui(tcp);
+#endif
+
 			nprocs++;
 			if (debug_flag)
 				fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
@@ -731,6 +745,12 @@
 	if (printing_tcp == tcp)
 		printing_tcp = NULL;
 
+#ifdef USE_LIBUNWIND
+	if (stack_trace_enabled) {
+		delete_mmap_cache(tcp);
+		free_libunwind_ui(tcp);
+	}
+#endif
 	memset(tcp, 0, sizeof(*tcp));
 }
 
@@ -1653,6 +1673,9 @@
 	qualify("signal=all");
 	while ((c = getopt(argc, argv,
 		"+b:cCdfFhiqrtTvVwxyz"
+#ifdef USE_LIBUNWIND
+		"k"
+#endif
 		"D"
 		"a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
 		switch (c) {
@@ -1758,6 +1781,11 @@
 		case 'u':
 			username = strdup(optarg);
 			break;
+#ifdef USE_LIBUNWIND
+		case 'k':
+			stack_trace_enabled = true;
+			break;
+#endif
 		case 'E':
 			if (putenv(optarg) < 0)
 				die_out_of_memory();
@@ -1789,6 +1817,11 @@
 		error_msg_and_die("-D and -p are mutually exclusive");
 	}
 
+#ifdef USE_LIBUNWIND
+	if (stack_trace_enabled)
+		init_unwind_addr_space();
+#endif
+
 	if (!followfork)
 		followfork = optF;