Don't call malloc() and free() while in the debugger and unwinding

to get a stacktrace. This does not work even with M_NOWAIT when we
have WITNESS and is generally a bad idea (pointed out by bde@). We
allocate an 8K heap for use by the unwinder when ddb is active. A
stack trace roughly takes up half of that in any case, so we have
some room for complex unwind situations. We don't want to waste too
much space though. Due to the nature of unwinding, we don't worry
too much about fragmentation or performance of unwinding while in
the debugger. For now we have our own heap management, but we may
be able to leverage from existing code at some later time.

While here:
o  Make sure we actually free the unwind environment after unwinding.
   This fixes a memory leak.
o  Replace Doug's license with mine in unwind.c and unwind.h. Both
   files don't have much, if any, of Doug's code left since the EPC
   syscall overhaul and the import of the unwinder.
o  Remove dead code.
o  Replace M_NOWAIT with M_WAITOK for all remaining malloc() calls.
This commit is contained in:
marcel 2003-07-05 23:21:58 +00:00
parent 59addbcbd2
commit 14925f9a36
3 changed files with 122 additions and 55 deletions

View File

@ -99,6 +99,8 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
db_printsym(ip, DB_STGY_PROC);
db_printf("\n");
}
unw_delete(&rs);
}
void

View File

@ -1,31 +1,34 @@
/*-
* Copyright (c) 2001 Doug Rabson
/*
* Copyright (c) 2003 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
@ -57,42 +60,92 @@ LIST_HEAD(unw_table_list, unw_table);
static struct unw_table_list unw_tables;
#ifdef DDB
#define DDBHEAPSZ 8192
struct mhdr {
uint32_t sig;
#define MSIG_FREE 0x65657246 /* "Free". */
#define MSIG_USED 0x64657355 /* "Used". */
uint32_t size;
int32_t next;
int32_t prev;
};
extern int db_active;
static struct mhdr *ddbheap;
#endif /* DDB */
static void *
unw_alloc(size_t sz)
{
#ifdef DDB
struct mhdr *hdr, *hfree;
return (malloc(sz, M_UNWIND, M_NOWAIT));
if (db_active) {
sz = (sz + 15) >> 4;
hdr = ddbheap;
while (hdr->sig != MSIG_FREE || hdr->size < sz) {
if (hdr->next == -1)
return (NULL);
hdr = ddbheap + hdr->next;
}
if (hdr->size > sz + 1) {
hfree = hdr + sz + 1;
hfree->sig = MSIG_FREE;
hfree->size = hdr->size - sz - 1;
hfree->prev = hdr - ddbheap;
hfree->next = hdr->next;
hdr->size = sz;
hdr->next = hfree - ddbheap;
if (hfree->next >= 0) {
hfree = ddbheap + hfree->next;
hfree->prev = hdr->next;
}
}
hdr->sig = MSIG_USED;
return (void*)(hdr + 1);
}
#endif
return (malloc(sz, M_UNWIND, M_WAITOK));
}
static void
unw_free(void *p)
{
#ifdef DDB
struct mhdr *hdr, *hfree;
if (db_active) {
hdr = (struct mhdr*)p - 1;
if (hdr->sig != MSIG_USED)
return;
hdr->sig = MSIG_FREE;
if (hdr->prev >= 0 && ddbheap[hdr->prev].sig == MSIG_FREE) {
hfree = ddbheap + hdr->prev;
hfree->size += hdr->size + 1;
hfree->next = hdr->next;
if (hdr->next >= 0) {
hfree = ddbheap + hdr->next;
hfree->prev = hdr->prev;
}
} else if (hdr->next >= 0 &&
ddbheap[hdr->next].sig == MSIG_FREE) {
hfree = ddbheap + hdr->next;
hdr->size += hfree->size + 1;
hdr->next = hfree->next;
if (hdr->next >= 0) {
hfree = ddbheap + hdr->next;
hfree->prev = hdr - ddbheap;
}
}
return;
}
#endif
free(p, M_UNWIND);
}
#if 0
static struct unw_entry *
unw_entry_lookup(struct unw_table *ut, uint64_t ip)
{
struct unw_entry *end, *mid, *start;
ip -= ut->ut_base;
start = ut->ut_start;
end = ut->ut_end - 1;
while (start < end) {
mid = start + ((end - start) >> 1);
if (ip < mid->ue_start)
end = mid;
else if (ip >= mid->ue_end)
start = mid + 1;
else
break;
}
return ((start < end) ? mid : NULL);
}
#endif
static struct unw_table *
unw_table_lookup(uint64_t ip)
{
@ -225,6 +278,13 @@ unw_create(struct unw_regstate *rs, struct trapframe *tf)
return ((uwxerr) ? EINVAL : 0); /* XXX */
}
void
unw_delete(struct unw_regstate *rs)
{
uwx_free(rs->env);
}
int
unw_step(struct unw_regstate *rs)
{
@ -266,10 +326,7 @@ unw_table_add(uint64_t base, uint64_t start, uint64_t end)
{
struct unw_table *ut;
ut = malloc(sizeof(struct unw_table), M_UNWIND, M_NOWAIT);
if (ut == NULL)
return (ENOMEM);
ut = malloc(sizeof(struct unw_table), M_UNWIND, M_WAITOK);
ut->ut_base = base;
ut->ut_start = (struct unw_entry*)start;
ut->ut_end = (struct unw_entry*)end;
@ -303,5 +360,12 @@ unw_initialize(void *dummy __unused)
LIST_INIT(&unw_tables);
uwx_register_alloc_cb(unw_alloc, unw_free);
#ifdef DDB
ddbheap = malloc(DDBHEAPSZ, M_UNWIND, M_WAITOK);
ddbheap->sig = MSIG_FREE;
ddbheap->size = (DDBHEAPSZ - sizeof(struct mhdr)) >> 4;
ddbheap->next = -1;
ddbheap->prev = -1;
#endif
}
SYSINIT(unwind, SI_SUB_KMEM, SI_ORDER_ANY, unw_initialize, 0);

View File

@ -1,27 +1,27 @@
/*-
* Copyright (c) 2001 Doug Rabson
/*
* Copyright (c) 2003 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
@ -38,6 +38,7 @@ struct unw_regstate {
};
int unw_create(struct unw_regstate *s, struct trapframe *tf);
void unw_delete(struct unw_regstate *s);
int unw_step(struct unw_regstate *s);
int unw_get_bsp(struct unw_regstate *s, uint64_t *r);