The current MIPS DDB stacktrace code doesn't work if no symbols are

available, so fall back to old-fashioned unwind code if no symbols.
This commit is contained in:
simonb 2020-09-23 09:52:02 +00:00
parent 24f144256a
commit 52a68e3bab
3 changed files with 73 additions and 56 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: mips_stacktrace.c,v 1.4 2020/08/17 21:50:14 mrg Exp $ */
/* $NetBSD: mips_stacktrace.c,v 1.5 2020/09/23 09:52:02 simonb Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mips_stacktrace.c,v 1.4 2020/08/17 21:50:14 mrg Exp $");
__KERNEL_RCSID(0, "$NetBSD: mips_stacktrace.c,v 1.5 2020/09/23 09:52:02 simonb Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@ -322,60 +322,66 @@ loop:
}
#ifdef DDB
/*
* Check the kernel symbol table to see the beginning of
* the current subroutine.
*/
diff = 0;
sym = db_search_symbol(pc, DB_STGY_ANY, &diff);
if (sym != DB_SYM_NULL && diff == 0) {
/* check func(foo) __attribute__((__noreturn__)) case */
if (!kdbpeek(pc - 2 * sizeof(unsigned), &instr))
return;
i.word = instr;
if (i.JType.op == OP_JAL) {
sym = db_search_symbol(pc - sizeof(int),
DB_STGY_ANY, &diff);
if (sym != DB_SYM_NULL && diff != 0)
diff += sizeof(int);
if (ksyms_available()) {
/*
* Check the kernel symbol table to see the beginning of
* the current subroutine.
*/
diff = 0;
sym = db_search_symbol(pc, DB_STGY_ANY, &diff);
if (sym != DB_SYM_NULL && diff == 0) {
/* check func(foo) __attribute__((__noreturn__)) case */
if (!kdbpeek(pc - 2 * sizeof(unsigned), &instr))
return;
i.word = instr;
if (i.JType.op == OP_JAL) {
sym = db_search_symbol(pc - sizeof(int),
DB_STGY_ANY, &diff);
if (sym != DB_SYM_NULL && diff != 0)
diff += sizeof(int);
}
}
}
if (sym == DB_SYM_NULL) {
ra = 0;
goto done;
}
va = pc - diff;
#else
/*
* Find the beginning of the current subroutine by scanning backwards
* from the current PC for the end of the previous subroutine.
*
* XXX This won't work well because nowadays gcc is so aggressive
* as to reorder instruction blocks for branch-predict.
* (i.e. 'jr ra' wouldn't indicate the end of subroutine)
*/
va = pc;
do {
va -= sizeof(int);
if (va <= (vaddr_t)verylocore)
goto finish;
if (!kdbpeek(va, &instr))
return;
if (instr == MIPS_ERET)
goto mips3_eret;
} while (instr != MIPS_JR_RA && instr != MIPS_JR_K0);
/* skip back over branch & delay slot */
va += sizeof(int);
mips3_eret:
va += sizeof(int);
/* skip over nulls which might separate .o files */
instr = 0;
while (instr == 0) {
if (!kdbpeek(va, &instr))
return;
if (sym == DB_SYM_NULL) {
ra = 0;
goto done;
}
va = pc - diff;
} else {
#endif /* DDB */
/*
* Find the beginning of the current subroutine by
* scanning backwards from the current PC for the end
* of the previous subroutine.
*
* XXX This won't work well because nowadays gcc is so
* aggressive as to reorder instruction blocks for
* branch-predict. (i.e. 'jr ra' wouldn't indicate
* the end of subroutine)
*/
va = pc;
do {
va -= sizeof(int);
if (va <= (vaddr_t)verylocore)
goto finish;
if (!kdbpeek(va, &instr))
return;
if (instr == MIPS_ERET)
goto mips3_eret;
} while (instr != MIPS_JR_RA && instr != MIPS_JR_K0);
/* skip back over branch & delay slot */
va += sizeof(int);
mips3_eret:
va += sizeof(int);
/* skip over nulls which might separate .o files */
instr = 0;
while (instr == 0) {
if (!kdbpeek(va, &instr))
return;
va += sizeof(int);
}
#ifdef DDB
}
#endif
#endif /* DDB */
subr = va;
/* scan forwards to find stack size and any saved registers */

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_ksyms.c,v 1.88 2020/01/05 21:12:34 pgoyette Exp $ */
/* $NetBSD: kern_ksyms.c,v 1.89 2020/09/23 09:52:02 simonb Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@ -73,7 +73,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.88 2020/01/05 21:12:34 pgoyette Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.89 2020/09/23 09:52:02 simonb Exp $");
#if defined(_KERNEL) && defined(_KERNEL_OPT)
#include "opt_copy_symtab.h"
@ -246,6 +246,16 @@ ksyms_init(void)
}
}
/*
* Are any symbols available?
*/
bool
ksyms_available(void)
{
return ksyms_loaded;
}
/*
* Add a symbol table.
* This is intended for use when the symbol table and its corresponding

View File

@ -1,4 +1,4 @@
/* $NetBSD: ksyms.h,v 1.37 2017/11/06 17:56:25 christos Exp $ */
/* $NetBSD: ksyms.h,v 1.38 2020/09/23 09:52:02 simonb Exp $ */
/*
* Copyright (c) 2001, 2003 Anders Magnusson (ragge@ludd.luth.se).
@ -144,6 +144,7 @@ int ksyms_delsymtab(const char *);
void ksyms_init(void);
void ksyms_addsyms_elf(int, void *, void *);
void ksyms_addsyms_explicit(void *, void *, size_t, void *, size_t);
bool ksyms_available(void);
int ksyms_sift(char *, char *, int);
void ksyms_modload(const char *, void *, vsize_t, char *, vsize_t);
void ksyms_modunload(const char *);