summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2003-07-05 23:21:58 +0000
committermarcel <marcel@FreeBSD.org>2003-07-05 23:21:58 +0000
commit14925f9a36e64e845453b06cbb70062456babab4 (patch)
treee2bb5d615a630a383fd3b199caec93942dad8dcf /sys
parent59addbcbd245add35cd2906afcbf4f137e684e3e (diff)
downloadFreeBSD-src-14925f9a36e64e845453b06cbb70062456babab4.zip
FreeBSD-src-14925f9a36e64e845453b06cbb70062456babab4.tar.gz
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.
Diffstat (limited to 'sys')
-rw-r--r--sys/ia64/ia64/db_trace.c2
-rw-r--r--sys/ia64/ia64/unwind.c152
-rw-r--r--sys/ia64/include/unwind.h27
3 files changed, 124 insertions, 57 deletions
diff --git a/sys/ia64/ia64/db_trace.c b/sys/ia64/ia64/db_trace.c
index f093561..4e164b2 100644
--- a/sys/ia64/ia64/db_trace.c
+++ b/sys/ia64/ia64/db_trace.c
@@ -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
diff --git a/sys/ia64/ia64/unwind.c b/sys/ia64/ia64/unwind.c
index 7fa68b7..cfc5af7 100644
--- a/sys/ia64/ia64/unwind.c
+++ b/sys/ia64/ia64/unwind.c
@@ -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,41 +60,91 @@ 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)
{
-
- return (malloc(sz, M_UNWIND, M_NOWAIT));
+#ifdef DDB
+ struct mhdr *hdr, *hfree;
+
+ 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)
{
-
- 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;
+#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;
}
- return ((start < end) ? mid : NULL);
-}
#endif
+ free(p, M_UNWIND);
+}
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);
diff --git a/sys/ia64/include/unwind.h b/sys/ia64/include/unwind.h
index 1cf9f4a..794a85d 100644
--- a/sys/ia64/include/unwind.h
+++ b/sys/ia64/include/unwind.h
@@ -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);
OpenPOWER on IntegriCloud