2 * Copyright (c) 2005 Antoine Brodin
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
33 #include <sys/kernel.h>
37 #include <sys/linker.h>
38 #include <sys/malloc.h>
40 #include <sys/stack.h>
41 #include <sys/systm.h>
43 static MALLOC_DEFINE(M_STACK
, "stack", "Stack Traces");
45 static void stack_symbol(vm_offset_t pc
, char *namebuf
, u_int buflen
,
48 static void stack_symbol_ddb(vm_offset_t pc
, char *namebuf
, u_int buflen
,
57 st
= malloc(sizeof *st
, M_STACK
, M_WAITOK
| M_ZERO
);
62 stack_destroy(struct stack
*st
)
69 stack_put(struct stack
*st
, vm_offset_t pc
)
72 if (st
->depth
< STACK_MAX
) {
73 st
->pcs
[st
->depth
++] = pc
;
80 stack_copy(struct stack
*src
, struct stack
*dst
)
87 stack_zero(struct stack
*st
)
90 bzero(st
, sizeof *st
);
94 stack_print(struct stack
*st
)
100 KASSERT(st
->depth
<= STACK_MAX
, ("bogus stack"));
101 for (i
= 0; i
< st
->depth
; i
++) {
102 stack_symbol(st
->pcs
[i
], namebuf
, sizeof(namebuf
), &offset
);
103 printf("#%d %p at %s+%#lx\n", i
, (void *)st
->pcs
[i
],
110 stack_print_ddb(struct stack
*st
)
116 KASSERT(st
->depth
<= STACK_MAX
, ("bogus stack"));
117 for (i
= 0; i
< st
->depth
; i
++) {
118 stack_symbol_ddb(st
->pcs
[i
], namebuf
, sizeof(namebuf
),
120 printf("#%d %p at %s+%#lx\n", i
, (void *)st
->pcs
[i
],
127 * Two print routines -- one for use from DDB and DDB-like contexts, the
128 * other for use in the live kernel.
131 stack_sbuf_print(struct sbuf
*sb
, struct stack
*st
)
137 KASSERT(st
->depth
<= STACK_MAX
, ("bogus stack"));
138 for (i
= 0; i
< st
->depth
; i
++) {
139 stack_symbol(st
->pcs
[i
], namebuf
, sizeof(namebuf
), &offset
);
140 sbuf_printf(sb
, "#%d %p at %s+%#lx\n", i
, (void *)st
->pcs
[i
],
147 stack_sbuf_print_ddb(struct sbuf
*sb
, struct stack
*st
)
153 KASSERT(st
->depth
<= STACK_MAX
, ("bogus stack"));
154 for (i
= 0; i
< st
->depth
; i
++) {
155 stack_symbol_ddb(st
->pcs
[i
], namebuf
, sizeof(namebuf
),
157 sbuf_printf(sb
, "#%d %p at %s+%#lx\n", i
, (void *)st
->pcs
[i
],
164 stack_ktr(u_int mask
, const char *file
, int line
, struct stack
*st
, u_int depth
,
171 KASSERT(st
->depth
<= STACK_MAX
, ("bogus stack"));
173 ktr_tracepoint(mask
, file
, line
, "#0 %p %p %p %p %p %p",
174 st
->pcs
[0], st
->pcs
[1], st
->pcs
[2], st
->pcs
[3],
175 st
->pcs
[4], st
->pcs
[5]);
178 ktr_tracepoint(mask
, file
, line
, "#1 %p %p %p %p %p %p",
179 st
->pcs
[6], st
->pcs
[7], st
->pcs
[8], st
->pcs
[9],
180 st
->pcs
[10], st
->pcs
[11]);
183 ktr_tracepoint(mask
, file
, line
, "#2 %p %p %p %p %p %p",
184 st
->pcs
[12], st
->pcs
[13], st
->pcs
[14], st
->pcs
[15],
185 st
->pcs
[16], st
->pcs
[17]);
187 if (depth
== 0 || st
->depth
< depth
)
189 for (i
= 0; i
< depth
; i
++) {
190 stack_symbol_ddb(st
->pcs
[i
], namebuf
,
191 sizeof(namebuf
), &offset
);
192 ktr_tracepoint(mask
, file
, line
, "#%d %p at %s+%#lx",
193 i
, st
->pcs
[i
], (u_long
)namebuf
, offset
, 0, 0);
201 * Two variants of stack symbol lookup -- one that uses the DDB interfaces
202 * and bypasses linker locking, and the other that doesn't.
205 stack_symbol(vm_offset_t pc
, char *namebuf
, u_int buflen
, long *offset
)
208 if (linker_search_symbol_name((caddr_t
)pc
, namebuf
, buflen
,
211 strlcpy(namebuf
, "??", buflen
);
217 stack_symbol_ddb(vm_offset_t pc
, char *namebuf
, u_int buflen
, long *offset
)
220 if (linker_ddb_search_symbol_name((caddr_t
)pc
, namebuf
, buflen
,
223 strlcpy(namebuf
, "??", buflen
);