Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/ddb/db_main.c
39476 views
1
/*-
2
* SPDX-License-Identifier: MIT-CMU
3
*
4
* Mach Operating System
5
* Copyright (c) 1991,1990 Carnegie Mellon University
6
* All Rights Reserved.
7
*
8
* Permission to use, copy, modify and distribute this software and its
9
* documentation is hereby granted, provided that both the copyright
10
* notice and this permission notice appear in all copies of the
11
* software, derivative works or modified versions, and any portions
12
* thereof, and that both notices appear in supporting documentation.
13
*
14
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
15
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17
*
18
* Carnegie Mellon requests users of this software to return to
19
*
20
* Software Distribution Coordinator or [email protected]
21
* School of Computer Science
22
* Carnegie Mellon University
23
* Pittsburgh PA 15213-3890
24
*
25
* any improvements or extensions that they make and grant Carnegie the
26
* rights to redistribute these changes.
27
*/
28
29
#include <sys/param.h>
30
#include <sys/systm.h>
31
#include <sys/cons.h>
32
#include <sys/linker.h>
33
#include <sys/kdb.h>
34
#include <sys/kernel.h>
35
#include <sys/pcpu.h>
36
#include <sys/proc.h>
37
#include <sys/reboot.h>
38
#include <sys/sysctl.h>
39
40
#include <machine/kdb.h>
41
#include <machine/pcb.h>
42
#include <machine/setjmp.h>
43
44
#include <ddb/ddb.h>
45
#include <ddb/db_command.h>
46
#include <ddb/db_sym.h>
47
48
struct db_private {
49
char* strtab;
50
vm_offset_t relbase;
51
};
52
typedef struct db_private *db_private_t;
53
54
#define DB_PRIVATE(x) ((db_private_t)(x->private))
55
56
SYSCTL_NODE(_debug, OID_AUTO, ddb, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
57
"DDB settings");
58
59
static dbbe_init_f db_init;
60
static dbbe_trap_f db_trap;
61
static dbbe_trace_f db_trace_self_wrapper;
62
static dbbe_trace_thread_f db_trace_thread_wrapper;
63
64
KDB_BACKEND(ddb, db_init, db_trace_self_wrapper, db_trace_thread_wrapper,
65
db_trap);
66
67
/*
68
* Symbols can be loaded by specifying the exact addresses of
69
* the symtab and strtab in memory. This is used when loaded from
70
* boot loaders different than the native one (like Xen).
71
*/
72
vm_offset_t ksymtab, kstrtab, ksymtab_size, ksymtab_relbase;
73
static struct db_private ksymtab_private;
74
75
bool
76
X_db_line_at_pc(db_symtab_t *symtab, c_db_sym_t sym, char **file, int *line,
77
db_expr_t off)
78
{
79
return (false);
80
}
81
82
c_db_sym_t
83
X_db_lookup(db_symtab_t *symtab, const char *symbol)
84
{
85
c_linker_sym_t lsym;
86
Elf_Sym *sym;
87
88
if (symtab->private == NULL) {
89
return ((c_db_sym_t)((!linker_ddb_lookup(symbol, &lsym))
90
? lsym : NULL));
91
} else {
92
sym = (Elf_Sym *)symtab->start;
93
while ((char *)sym < symtab->end) {
94
if (sym->st_name != 0 &&
95
!strcmp(DB_PRIVATE(symtab)->strtab +
96
sym->st_name, symbol))
97
return ((c_db_sym_t)sym);
98
sym++;
99
}
100
}
101
return (NULL);
102
}
103
104
c_db_sym_t
105
X_db_search_symbol(db_symtab_t *symtab, db_addr_t off, db_strategy_t strat,
106
db_expr_t *diffp)
107
{
108
c_linker_sym_t lsym;
109
Elf_Sym *sym, *match;
110
unsigned long diff;
111
db_addr_t stoffs = off;
112
113
if (symtab->private == NULL) {
114
if (!linker_ddb_search_symbol((caddr_t)off, &lsym, &diff)) {
115
*diffp = (db_expr_t)diff;
116
return ((c_db_sym_t)lsym);
117
}
118
return (NULL);
119
}
120
else
121
stoffs -= DB_PRIVATE(symtab)->relbase;
122
123
diff = ~0UL;
124
match = NULL;
125
for (sym = (Elf_Sym*)symtab->start; (char*)sym < symtab->end; sym++) {
126
if (sym->st_name == 0 || sym->st_shndx == SHN_UNDEF)
127
continue;
128
if (stoffs < sym->st_value)
129
continue;
130
if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT &&
131
ELF_ST_TYPE(sym->st_info) != STT_FUNC &&
132
ELF_ST_TYPE(sym->st_info) != STT_NOTYPE)
133
continue;
134
if ((stoffs - sym->st_value) > diff)
135
continue;
136
if ((stoffs - sym->st_value) < diff) {
137
diff = stoffs - sym->st_value;
138
match = sym;
139
} else {
140
if (match == NULL)
141
match = sym;
142
else if (ELF_ST_BIND(match->st_info) == STB_LOCAL &&
143
ELF_ST_BIND(sym->st_info) != STB_LOCAL)
144
match = sym;
145
}
146
if (diff == 0) {
147
if (strat == DB_STGY_PROC &&
148
ELF_ST_TYPE(sym->st_info) == STT_FUNC &&
149
ELF_ST_BIND(sym->st_info) != STB_LOCAL)
150
break;
151
if (strat == DB_STGY_ANY &&
152
ELF_ST_BIND(sym->st_info) != STB_LOCAL)
153
break;
154
}
155
}
156
157
*diffp = (match == NULL) ? off : diff;
158
return ((c_db_sym_t)match);
159
}
160
161
bool
162
X_db_sym_numargs(db_symtab_t *symtab, c_db_sym_t sym, int *nargp,
163
char **argp)
164
{
165
return (false);
166
}
167
168
void
169
X_db_symbol_values(db_symtab_t *symtab, c_db_sym_t sym, const char **namep,
170
db_expr_t *valp)
171
{
172
linker_symval_t lval;
173
174
if (symtab->private == NULL) {
175
linker_ddb_symbol_values((c_linker_sym_t)sym, &lval);
176
if (namep != NULL)
177
*namep = (const char*)lval.name;
178
if (valp != NULL)
179
*valp = (db_expr_t)lval.value;
180
} else {
181
if (namep != NULL)
182
*namep = (const char *)DB_PRIVATE(symtab)->strtab +
183
((const Elf_Sym *)sym)->st_name;
184
if (valp != NULL)
185
*valp = (db_expr_t)((const Elf_Sym *)sym)->st_value +
186
DB_PRIVATE(symtab)->relbase;
187
}
188
}
189
190
int
191
db_fetch_ksymtab(vm_offset_t ksym_start, vm_offset_t ksym_end,
192
vm_offset_t relbase)
193
{
194
Elf_Size strsz;
195
196
if (ksym_end > ksym_start && ksym_start != 0) {
197
ksymtab = ksym_start;
198
ksymtab_size = *(Elf_Size*)ksymtab;
199
ksymtab += sizeof(Elf_Size);
200
kstrtab = ksymtab + ksymtab_size;
201
strsz = *(Elf_Size*)kstrtab;
202
kstrtab += sizeof(Elf_Size);
203
ksymtab_relbase = relbase;
204
if (kstrtab + strsz > ksym_end) {
205
/* Sizes doesn't match, unset everything. */
206
ksymtab = ksymtab_size = kstrtab = ksymtab_relbase
207
= 0;
208
}
209
}
210
211
if (ksymtab == 0 || ksymtab_size == 0 || kstrtab == 0)
212
return (-1);
213
214
return (0);
215
}
216
217
static int
218
db_init(void)
219
{
220
221
db_command_init();
222
223
if (ksymtab != 0 && kstrtab != 0 && ksymtab_size != 0) {
224
ksymtab_private.strtab = (char *)kstrtab;
225
ksymtab_private.relbase = ksymtab_relbase;
226
db_add_symbol_table((char *)ksymtab,
227
(char *)(ksymtab + ksymtab_size), "elf", (char *)&ksymtab_private);
228
}
229
db_add_symbol_table(NULL, NULL, "kld", NULL);
230
return (1); /* We're the default debugger. */
231
}
232
233
static int
234
db_trap(int type, int code)
235
{
236
jmp_buf jb;
237
void *prev_jb;
238
bool bkpt, watchpt;
239
const char *why;
240
241
/*
242
* Don't handle the trap if the console is unavailable (i.e. it
243
* is in graphics mode).
244
*/
245
if (cnunavailable())
246
return (0);
247
248
if (db_stop_at_pc(type, code, &bkpt, &watchpt)) {
249
if (db_inst_count) {
250
db_printf("After %d instructions (%d loads, %d stores),\n",
251
db_inst_count, db_load_count, db_store_count);
252
}
253
prev_jb = kdb_jmpbuf(jb);
254
if (setjmp(jb) == 0) {
255
db_dot = PC_REGS();
256
db_print_thread();
257
if (bkpt)
258
db_printf("Breakpoint at\t");
259
else if (watchpt)
260
db_printf("Watchpoint at\t");
261
else
262
db_printf("Stopped at\t");
263
db_print_loc_and_inst(db_dot);
264
}
265
why = kdb_why;
266
db_script_kdbenter(why != KDB_WHY_UNSET ? why : "unknown");
267
db_command_loop();
268
(void)kdb_jmpbuf(prev_jb);
269
}
270
271
db_restart_at_pc(watchpt);
272
273
return (1);
274
}
275
276
static void
277
db_trace_self_wrapper(void)
278
{
279
jmp_buf jb;
280
void *prev_jb;
281
282
prev_jb = kdb_jmpbuf(jb);
283
if (setjmp(jb) == 0)
284
db_trace_self();
285
(void)kdb_jmpbuf(prev_jb);
286
}
287
288
static void
289
db_trace_thread_wrapper(struct thread *td)
290
{
291
jmp_buf jb;
292
void *prev_jb;
293
294
prev_jb = kdb_jmpbuf(jb);
295
if (setjmp(jb) == 0)
296
db_trace_thread(td, -1);
297
(void)kdb_jmpbuf(prev_jb);
298
}
299
300