0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/types.h>
0014 #include <linux/sched.h>
0015 #include <linux/mm.h>
0016 #include <linux/kallsyms.h>
0017 #include <linux/stddef.h>
0018 #include <linux/vmalloc.h>
0019 #include <linux/ptrace.h>
0020 #include <linux/highmem.h>
0021 #include <linux/hardirq.h>
0022 #include <linux/delay.h>
0023 #include <linux/uaccess.h>
0024 #include <linux/kdb.h>
0025 #include <linux/slab.h>
0026 #include <linux/ctype.h>
0027 #include "kdb_private.h"
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 int kdbgetsymval(const char *symname, kdb_symtab_t *symtab)
0040 {
0041 kdb_dbg_printf(AR, "symname=%s, symtab=%px\n", symname, symtab);
0042 memset(symtab, 0, sizeof(*symtab));
0043 symtab->sym_start = kallsyms_lookup_name(symname);
0044 if (symtab->sym_start) {
0045 kdb_dbg_printf(AR, "returns 1, symtab->sym_start=0x%lx\n",
0046 symtab->sym_start);
0047 return 1;
0048 }
0049 kdb_dbg_printf(AR, "returns 0\n");
0050 return 0;
0051 }
0052 EXPORT_SYMBOL(kdbgetsymval);
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 int kdbnearsym(unsigned long addr, kdb_symtab_t *symtab)
0082 {
0083 int ret = 0;
0084 unsigned long symbolsize = 0;
0085 unsigned long offset = 0;
0086 static char namebuf[KSYM_NAME_LEN];
0087
0088 kdb_dbg_printf(AR, "addr=0x%lx, symtab=%px\n", addr, symtab);
0089 memset(symtab, 0, sizeof(*symtab));
0090
0091 if (addr < 4096)
0092 goto out;
0093
0094 symtab->sym_name = kallsyms_lookup(addr, &symbolsize , &offset,
0095 (char **)(&symtab->mod_name), namebuf);
0096 if (offset > 8*1024*1024) {
0097 symtab->sym_name = NULL;
0098 addr = offset = symbolsize = 0;
0099 }
0100 symtab->sym_start = addr - offset;
0101 symtab->sym_end = symtab->sym_start + symbolsize;
0102 ret = symtab->sym_name != NULL && *(symtab->sym_name) != '\0';
0103
0104 if (symtab->mod_name == NULL)
0105 symtab->mod_name = "kernel";
0106 kdb_dbg_printf(AR, "returns %d symtab->sym_start=0x%lx, symtab->mod_name=%px, symtab->sym_name=%px (%s)\n",
0107 ret, symtab->sym_start, symtab->mod_name, symtab->sym_name, symtab->sym_name);
0108 out:
0109 return ret;
0110 }
0111
0112 static char ks_namebuf[KSYM_NAME_LEN+1], ks_namebuf_prev[KSYM_NAME_LEN+1];
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126 int kallsyms_symbol_complete(char *prefix_name, int max_len)
0127 {
0128 loff_t pos = 0;
0129 int prefix_len = strlen(prefix_name), prev_len = 0;
0130 int i, number = 0;
0131 const char *name;
0132
0133 while ((name = kdb_walk_kallsyms(&pos))) {
0134 if (strncmp(name, prefix_name, prefix_len) == 0) {
0135 strscpy(ks_namebuf, name, sizeof(ks_namebuf));
0136
0137 if (++number == 1) {
0138 prev_len = min_t(int, max_len-1,
0139 strlen(ks_namebuf));
0140 memcpy(ks_namebuf_prev, ks_namebuf, prev_len);
0141 ks_namebuf_prev[prev_len] = '\0';
0142 continue;
0143 }
0144 for (i = 0; i < prev_len; i++) {
0145 if (ks_namebuf[i] != ks_namebuf_prev[i]) {
0146 prev_len = i;
0147 ks_namebuf_prev[i] = '\0';
0148 break;
0149 }
0150 }
0151 }
0152 }
0153 if (prev_len > prefix_len)
0154 memcpy(prefix_name, ks_namebuf_prev, prev_len+1);
0155 return number;
0156 }
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170 int kallsyms_symbol_next(char *prefix_name, int flag, int buf_size)
0171 {
0172 int prefix_len = strlen(prefix_name);
0173 static loff_t pos;
0174 const char *name;
0175
0176 if (!flag)
0177 pos = 0;
0178
0179 while ((name = kdb_walk_kallsyms(&pos))) {
0180 if (!strncmp(name, prefix_name, prefix_len))
0181 return strscpy(prefix_name, name, buf_size);
0182 }
0183 return 0;
0184 }
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198 void kdb_symbol_print(unsigned long addr, const kdb_symtab_t *symtab_p,
0199 unsigned int punc)
0200 {
0201 kdb_symtab_t symtab, *symtab_p2;
0202 if (symtab_p) {
0203 symtab_p2 = (kdb_symtab_t *)symtab_p;
0204 } else {
0205 symtab_p2 = &symtab;
0206 kdbnearsym(addr, symtab_p2);
0207 }
0208 if (!(symtab_p2->sym_name || (punc & KDB_SP_VALUE)))
0209 return;
0210 if (punc & KDB_SP_SPACEB)
0211 kdb_printf(" ");
0212 if (punc & KDB_SP_VALUE)
0213 kdb_printf(kdb_machreg_fmt0, addr);
0214 if (symtab_p2->sym_name) {
0215 if (punc & KDB_SP_VALUE)
0216 kdb_printf(" ");
0217 if (punc & KDB_SP_PAREN)
0218 kdb_printf("(");
0219 if (strcmp(symtab_p2->mod_name, "kernel"))
0220 kdb_printf("[%s]", symtab_p2->mod_name);
0221 kdb_printf("%s", symtab_p2->sym_name);
0222 if (addr != symtab_p2->sym_start)
0223 kdb_printf("+0x%lx", addr - symtab_p2->sym_start);
0224 if (punc & KDB_SP_SYMSIZE)
0225 kdb_printf("/0x%lx",
0226 symtab_p2->sym_end - symtab_p2->sym_start);
0227 if (punc & KDB_SP_PAREN)
0228 kdb_printf(")");
0229 }
0230 if (punc & KDB_SP_SPACEA)
0231 kdb_printf(" ");
0232 if (punc & KDB_SP_NEWLINE)
0233 kdb_printf("\n");
0234 }
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247 char *kdb_strdup(const char *str, gfp_t type)
0248 {
0249 int n = strlen(str)+1;
0250 char *s = kmalloc(n, type);
0251 if (!s)
0252 return NULL;
0253 return strcpy(s, str);
0254 }
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266 int kdb_getarea_size(void *res, unsigned long addr, size_t size)
0267 {
0268 int ret = copy_from_kernel_nofault((char *)res, (char *)addr, size);
0269 if (ret) {
0270 if (!KDB_STATE(SUPPRESS)) {
0271 kdb_func_printf("Bad address 0x%lx\n", addr);
0272 KDB_STATE_SET(SUPPRESS);
0273 }
0274 ret = KDB_BADADDR;
0275 } else {
0276 KDB_STATE_CLEAR(SUPPRESS);
0277 }
0278 return ret;
0279 }
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291 int kdb_putarea_size(unsigned long addr, void *res, size_t size)
0292 {
0293 int ret = copy_to_kernel_nofault((char *)addr, (char *)res, size);
0294 if (ret) {
0295 if (!KDB_STATE(SUPPRESS)) {
0296 kdb_func_printf("Bad address 0x%lx\n", addr);
0297 KDB_STATE_SET(SUPPRESS);
0298 }
0299 ret = KDB_BADADDR;
0300 } else {
0301 KDB_STATE_CLEAR(SUPPRESS);
0302 }
0303 return ret;
0304 }
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317 static int kdb_getphys(void *res, unsigned long addr, size_t size)
0318 {
0319 unsigned long pfn;
0320 void *vaddr;
0321 struct page *page;
0322
0323 pfn = (addr >> PAGE_SHIFT);
0324 if (!pfn_valid(pfn))
0325 return 1;
0326 page = pfn_to_page(pfn);
0327 vaddr = kmap_atomic(page);
0328 memcpy(res, vaddr + (addr & (PAGE_SIZE - 1)), size);
0329 kunmap_atomic(vaddr);
0330
0331 return 0;
0332 }
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343 int kdb_getphysword(unsigned long *word, unsigned long addr, size_t size)
0344 {
0345 int diag;
0346 __u8 w1;
0347 __u16 w2;
0348 __u32 w4;
0349 __u64 w8;
0350 *word = 0;
0351
0352 switch (size) {
0353 case 1:
0354 diag = kdb_getphys(&w1, addr, sizeof(w1));
0355 if (!diag)
0356 *word = w1;
0357 break;
0358 case 2:
0359 diag = kdb_getphys(&w2, addr, sizeof(w2));
0360 if (!diag)
0361 *word = w2;
0362 break;
0363 case 4:
0364 diag = kdb_getphys(&w4, addr, sizeof(w4));
0365 if (!diag)
0366 *word = w4;
0367 break;
0368 case 8:
0369 if (size <= sizeof(*word)) {
0370 diag = kdb_getphys(&w8, addr, sizeof(w8));
0371 if (!diag)
0372 *word = w8;
0373 break;
0374 }
0375 fallthrough;
0376 default:
0377 diag = KDB_BADWIDTH;
0378 kdb_func_printf("bad width %zu\n", size);
0379 }
0380 return diag;
0381 }
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393 int kdb_getword(unsigned long *word, unsigned long addr, size_t size)
0394 {
0395 int diag;
0396 __u8 w1;
0397 __u16 w2;
0398 __u32 w4;
0399 __u64 w8;
0400 *word = 0;
0401 switch (size) {
0402 case 1:
0403 diag = kdb_getarea(w1, addr);
0404 if (!diag)
0405 *word = w1;
0406 break;
0407 case 2:
0408 diag = kdb_getarea(w2, addr);
0409 if (!diag)
0410 *word = w2;
0411 break;
0412 case 4:
0413 diag = kdb_getarea(w4, addr);
0414 if (!diag)
0415 *word = w4;
0416 break;
0417 case 8:
0418 if (size <= sizeof(*word)) {
0419 diag = kdb_getarea(w8, addr);
0420 if (!diag)
0421 *word = w8;
0422 break;
0423 }
0424 fallthrough;
0425 default:
0426 diag = KDB_BADWIDTH;
0427 kdb_func_printf("bad width %zu\n", size);
0428 }
0429 return diag;
0430 }
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442 int kdb_putword(unsigned long addr, unsigned long word, size_t size)
0443 {
0444 int diag;
0445 __u8 w1;
0446 __u16 w2;
0447 __u32 w4;
0448 __u64 w8;
0449 switch (size) {
0450 case 1:
0451 w1 = word;
0452 diag = kdb_putarea(addr, w1);
0453 break;
0454 case 2:
0455 w2 = word;
0456 diag = kdb_putarea(addr, w2);
0457 break;
0458 case 4:
0459 w4 = word;
0460 diag = kdb_putarea(addr, w4);
0461 break;
0462 case 8:
0463 if (size <= sizeof(word)) {
0464 w8 = word;
0465 diag = kdb_putarea(addr, w8);
0466 break;
0467 }
0468 fallthrough;
0469 default:
0470 diag = KDB_BADWIDTH;
0471 kdb_func_printf("bad width %zu\n", size);
0472 }
0473 return diag;
0474 }
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485 char kdb_task_state_char (const struct task_struct *p)
0486 {
0487 unsigned long tmp;
0488 char state;
0489 int cpu;
0490
0491 if (!p ||
0492 copy_from_kernel_nofault(&tmp, (char *)p, sizeof(unsigned long)))
0493 return 'E';
0494
0495 state = task_state_to_char((struct task_struct *) p);
0496
0497 if (is_idle_task(p)) {
0498
0499
0500 cpu = kdb_process_cpu(p);
0501 if (!kdb_task_has_cpu(p) || kgdb_info[cpu].irq_depth == 1) {
0502 if (cpu != kdb_initial_cpu)
0503 state = '-';
0504 }
0505 } else if (!p->mm && strchr("IMS", state)) {
0506 state = tolower(state);
0507 }
0508 return state;
0509 }
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522 bool kdb_task_state(const struct task_struct *p, const char *mask)
0523 {
0524 char state = kdb_task_state_char(p);
0525
0526
0527
0528
0529
0530 if (!mask || mask[0] == '\0')
0531 return !strchr("-ims", state);
0532
0533
0534 if (strchr(mask, 'A'))
0535 return true;
0536
0537 return strchr(mask, state);
0538 }
0539
0540
0541
0542
0543
0544 static int kdb_flags_stack[4], kdb_flags_index;
0545
0546 void kdb_save_flags(void)
0547 {
0548 BUG_ON(kdb_flags_index >= ARRAY_SIZE(kdb_flags_stack));
0549 kdb_flags_stack[kdb_flags_index++] = kdb_flags;
0550 }
0551
0552 void kdb_restore_flags(void)
0553 {
0554 BUG_ON(kdb_flags_index <= 0);
0555 kdb_flags = kdb_flags_stack[--kdb_flags_index];
0556 }