]> sourceware.org Git - systemtap.git/blob - runtime/stack.c
common_probe_context.h: Put Individual Probe State (ips) into a union.
[systemtap.git] / runtime / stack.c
1 /* -*- linux-c -*-
2 * Stack tracing functions
3 * Copyright (C) 2005-2009 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 /*
13 The translator will only include this file if the session needs any
14 of the backtrace functions. Currently indicated by having the session
15 need_unwind flag, which is set by tapset functions marked with
16 pragme:unwind.
17 */
18
19 #ifndef _STACK_C_
20 #define _STACK_C_
21
22 /* Maximum number of backtrace levels. */
23 #ifndef MAXBACKTRACE
24 #define MAXBACKTRACE 20
25 #endif
26
27 /** @file stack.c
28 * @brief Stack Tracing Functions
29 */
30
31 /** @addtogroup stack Stack Tracing Functions
32 *
33 * @{
34 */
35
36 #include "sym.c"
37 #include "regs.h"
38
39 #define MAXBACKTRACE 20
40
41 /* If uprobes isn't in the kernel, pull it in from the runtime. */
42 #if defined(CONFIG_UTRACE) /* uprobes doesn't work without utrace */
43 #if defined(CONFIG_UPROBES) || defined(CONFIG_UPROBES_MODULE)
44 #include <linux/uprobes.h>
45 #else
46 #include "uprobes/uprobes.h"
47 #endif
48 #ifndef UPROBES_API_VERSION
49 #define UPROBES_API_VERSION 1
50 #endif
51 #else
52 struct uretprobe_instance;
53 #endif
54
55 #if defined(STAPCONF_KERNEL_STACKTRACE)
56 #include <linux/stacktrace.h>
57 #include <asm/stacktrace.h>
58 #endif
59
60 static void _stp_stack_print_fallback(unsigned long, int, int);
61
62 #if (defined(__i386__) || defined(__x86_64__))
63 #include "stack-x86.c"
64 #elif defined (__ia64__)
65 #include "stack-ia64.c"
66 #elif defined (__powerpc__)
67 #include "stack-ppc.c"
68 #elif defined (__arm__)
69 #include "stack-arm.c"
70 #elif defined (__s390__) || defined (__s390x__)
71 #include "stack-s390.c"
72 #else
73 #error "Unsupported architecture"
74 #endif
75
76 #if defined(STAPCONF_KERNEL_STACKTRACE)
77
78 struct print_stack_data
79 {
80 int verbose;
81 int max_level;
82 int level;
83 };
84
85 #if defined(STAPCONF_STACKTRACE_OPS_WARNING)
86 static void print_stack_warning(void *data, char *msg)
87 {
88 }
89
90 static void
91 print_stack_warning_symbol(void *data, char *msg, unsigned long symbol)
92 {
93 }
94 #endif
95
96 static int print_stack_stack(void *data, char *name)
97 {
98 return -1;
99 }
100
101 static void print_stack_address(void *data, unsigned long addr, int reliable)
102 {
103 struct print_stack_data *sdata = data;
104 if (sdata->level++ < sdata->max_level)
105 _stp_print_addr(addr, sdata->verbose | _STP_SYM_INEXACT, NULL);
106 }
107
108 static const struct stacktrace_ops print_stack_ops = {
109 #if defined(STAPCONF_STACKTRACE_OPS_WARNING)
110 .warning = print_stack_warning,
111 .warning_symbol = print_stack_warning_symbol,
112 #endif
113 .stack = print_stack_stack,
114 .address = print_stack_address,
115 #if defined(STAPCONF_WALK_STACK)
116 .walk_stack = print_context_stack,
117 #endif
118 };
119
120 /* Currently only used by the stack-x64.c code when dwarf unwinding fails. */
121 static void _stp_stack_print_fallback(unsigned long stack, int verbose, int levels)
122 {
123 struct print_stack_data print_data;
124 print_data.verbose = verbose;
125 print_data.max_level = levels;
126 print_data.level = 0;
127 dump_trace(current, NULL, (long *)stack, 0, &print_stack_ops,
128 &print_data);
129 }
130 #else
131 static void _stp_stack_print_fallback(unsigned long s, int v, int l) {
132 /* Don't guess, just give up. */
133 _stp_print_addr(0, v | _STP_SYM_INEXACT, NULL);
134 }
135 #endif /* defined(STAPCONF_KERNEL_STACKTRACE) */
136
137 // Without KPROBES very little works atm.
138 // But this file is unconditionally imported, while these two functions are only
139 // used through context-unwind.stp.
140 #if defined (CONFIG_KPROBES)
141
142 /** Prints the stack backtrace
143 * @param regs A pointer to the struct pt_regs.
144 * @param verbose _STP_SYM_FULL or _STP_SYM_BRIEF
145 */
146
147 static void _stp_stack_print(struct context *c, int sym_flags, int stack_flags)
148 {
149 struct pt_regs *regs = NULL;
150 struct task_struct *tsk = NULL;
151 int uregs_valid = 0;
152 struct uretprobe_instance *ri;
153
154 if (c->probe_type == _STP_PROBE_HANDLER_URETPROBE)
155 ri = c->ips.ri;
156 else if (c->probe_type == _STP_PROBE_HANDLER_UPROBE)
157 ri = GET_PC_URETPROBE_NONE;
158 else
159 ri = NULL;
160
161 if (stack_flags == _STP_STACK_KERNEL) {
162 if (! c->regs || (c->regflags & _STP_REGS_USER_FLAG)) {
163 if (sym_flags & _STP_SYM_SYMBOL)
164 _stp_printf("<no kernel backtrace at %s>\n",
165 c->probe_point);
166 else
167 _stp_print("\n");
168 return;
169 } else {
170 regs = c->regs;
171 ri = NULL; /* This is a hint for GCC so that it can
172 eliminate the call to uprobe_get_pc()
173 in __stp_stack_print() below. */
174 }
175 } else if (stack_flags == _STP_STACK_USER) {
176 /* use task_pt_regs, regs might be kernel regs, or not set. */
177 if (c->regs && (c->regflags & _STP_REGS_USER_FLAG)) {
178 regs = c->regs;
179 uregs_valid = 1;
180 } else {
181 regs = task_pt_regs(current);
182 uregs_valid = _stp_task_pt_regs_valid(current, regs);
183 }
184
185 if (! current->mm || ! regs) {
186 if (sym_flags & _STP_SYM_SYMBOL)
187 _stp_printf("<no user backtrace at %s>\n",
188 c->probe_point);
189 else
190 _stp_print("\n");
191 return;
192 } else {
193 tsk = current;
194 }
195 }
196
197 /* print the current address */
198 if (c->probe_type == _STP_PROBE_HANDLER_KRETPROBE && c->ips.krp.pi) {
199 if ((sym_flags & _STP_SYM_FULL) == _STP_SYM_FULL) {
200 _stp_print("Returning from: ");
201 _stp_print_addr((unsigned long)_stp_probe_addr_r(c->ips.krp.pi),
202 sym_flags, tsk);
203 _stp_print("Returning to : ");
204 }
205 _stp_print_addr((unsigned long)_stp_ret_addr_r(c->ips.krp.pi),
206 sym_flags, tsk);
207 #ifdef STAPCONF_UPROBE_GET_PC
208 } else if (c->probe_type == _STP_PROBE_HANDLER_URETPROBE && ri) {
209 if ((sym_flags & _STP_SYM_FULL) == _STP_SYM_FULL) {
210 _stp_print("Returning from: ");
211 /* ... otherwise this dereference fails */
212 _stp_print_addr(ri->rp->u.vaddr, sym_flags, tsk);
213 _stp_print("Returning to : ");
214 _stp_print_addr(ri->ret_addr, sym_flags, tsk);
215 } else
216 _stp_print_addr(ri->ret_addr, sym_flags, tsk);
217 #endif
218 } else {
219 _stp_print_addr(REG_IP(regs), sym_flags, tsk);
220 }
221
222 /* print rest of stack... */
223 __stp_stack_print(regs, sym_flags, MAXBACKTRACE, tsk,
224 &c->uwcontext, ri, uregs_valid);
225 }
226
227 /** Writes stack backtrace to a string
228 *
229 * @param str string
230 * @param regs A pointer to the struct pt_regs.
231 * @returns void
232 */
233 static void _stp_stack_sprint(char *str, int size, struct context* c,
234 int sym_flags, int stack_flags)
235 {
236 /* To get an hex string, we use a simple trick.
237 * First flush the print buffer,
238 * then call _stp_stack_print,
239 * then copy the result into the output string
240 * and clear the print buffer. */
241 _stp_pbuf *pb = per_cpu_ptr(Stp_pbuf, smp_processor_id());
242 _stp_print_flush();
243
244 _stp_stack_print(c, sym_flags, stack_flags);
245
246 strlcpy(str, pb->buf, size < (int)pb->len ? size : (int)pb->len);
247 pb->len = 0;
248 }
249
250 #endif /* CONFIG_KPROBES */
251
252 #endif /* _STACK_C_ */
This page took 0.046133 seconds and 6 git commands to generate.