]> sourceware.org Git - systemtap.git/blob - runtime/stack.c
2007-01-31 Martin Hunt <hunt@redhat.com>
[systemtap.git] / runtime / stack.c
1 /* -*- linux-c -*-
2 * Stack tracing functions
3 * Copyright (C) 2005, 2006, 2007 Red Hat Inc.
4 * Copyright (C) 2005 Intel Corporation.
5 *
6 * This file is part of systemtap, and is free software. You can
7 * redistribute it and/or modify it under the terms of the GNU General
8 * Public License (GPL); either version 2, or (at your option) any
9 * later version.
10 */
11
12 #ifndef _STACK_C_
13 #define _STACK_C_
14
15 /** @file stack.c
16 * @brief Stack Tracing Functions
17 */
18
19 /** @addtogroup stack Stack Tracing Functions
20 *
21 * @{
22 */
23
24 #include "sym.c"
25 #include "regs.h"
26 static int _stp_kta(unsigned long addr);
27
28 #if defined (__x86_64__)
29 #include "stack-x86_64.c"
30 #elif defined (__ia64__)
31 #include "stack-ia64.c"
32 #elif defined (__i386__)
33 #include "stack-i386.c"
34 #elif defined (__powerpc64__)
35 #include "stack-ppc64.c"
36 #elif defined (__s390__) || defined (__s390x__)
37 #include "stack-s390.c"
38 #else
39 #error "Unsupported architecture"
40 #endif
41
42
43 /* our copy of kernel_text_address() */
44 static int _stp_kta(unsigned long addr)
45 {
46 static unsigned long stext, etext, sinittext, einittext;
47 static int init = 0;
48
49 if (init == 0) {
50 init = 1;
51 etext = _stp_kallsyms_lookup_name("_etext");
52 stext = _stp_kallsyms_lookup_name("_stext");
53 sinittext = _stp_kallsyms_lookup_name("_sinittext");
54 einittext = _stp_kallsyms_lookup_name("_einittext");
55 }
56
57 if (addr >= stext && addr <= etext)
58 return 1;
59
60 if (addr >= sinittext && addr <= einittext)
61 return 1;
62
63 return 0;
64 }
65
66 /** Prints the stack backtrace
67 * @param regs A pointer to the struct pt_regs.
68 */
69
70 void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe_instance *pi)
71 {
72 if (verbose) {
73 /* print the current address */
74 if (pi) {
75 _stp_print("Returning from: ");
76 _stp_symbol_print((unsigned long)_stp_probe_addr_r(pi));
77 _stp_print("\nReturning to : ");
78 _stp_symbol_print((unsigned long)_stp_ret_addr_r(pi));
79 } else {
80 _stp_print_char(' ');
81 _stp_symbol_print (REG_IP(regs));
82 }
83 _stp_print_char('\n');
84 } else
85 _stp_printf ("%p ", REG_IP(regs));
86 __stp_stack_print (regs, verbose, 0);
87 }
88
89 /** Writes stack backtrace to a string
90 *
91 * @param str string
92 * @param regs A pointer to the struct pt_regs.
93 * @returns void
94 */
95 void _stp_stack_snprint (char *str, int size, struct pt_regs *regs, int verbose, struct kretprobe_instance *pi)
96 {
97 /* To get a string, we use a simple trick. First flush the print buffer, */
98 /* then call _stp_stack_print, then copy the result into the output string */
99 /* and clear the print buffer. */
100 _stp_pbuf *pb = per_cpu_ptr(Stp_pbuf, smp_processor_id());
101 _stp_print_flush();
102 _stp_stack_print(regs, verbose, pi);
103 strlcpy(str, pb->buf, size < pb->len ? size : pb->len);
104 pb->len = 0;
105 }
106
107
108 /** Prints the user stack backtrace
109 * @param str string
110 * @returns Same string as was input with trace info appended,
111 * @note Currently limited to a depth of two. Works from jprobes and kprobes.
112 */
113 #if 0
114 void _stp_ustack_print (char *str)
115 {
116 struct pt_regs *nregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) current->thread_info)) - 1;
117 _stp_printf ("%p : [user]\n", REG_IP(nregs));
118 if (REG_SP(nregs))
119 _stp_printf ("%p : [user]\n", *(unsigned long *)REG_SP(nregs));
120 }
121 #endif /* 0 */
122
123 /** @} */
124 #endif /* _STACK_C_ */
This page took 0.043839 seconds and 5 git commands to generate.