2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2002, 2003, 2004, 2005 Jeffrey Roberson <jeff@FreeBSD.org>
5 * Copyright (c) 2004, 2005 Bosko Milekic <bmilekic@FreeBSD.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice unmodified, this list of conditions, and the following
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * uma_dbg.c Debugging features for UMA users
35 #include <sys/cdefs.h>
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/bitset.h>
41 #include <sys/kernel.h>
42 #include <sys/types.h>
43 #include <sys/queue.h>
45 #include <sys/mutex.h>
46 #include <sys/malloc.h>
49 #include <vm/vm_object.h>
50 #include <vm/vm_page.h>
52 #include <vm/uma_int.h>
53 #include <vm/uma_dbg.h>
54 #include <vm/memguard.h>
56 #include <machine/stack.h>
58 static const u_long uma_junk = (u_long)0xdeadc0dedeadc0de;
61 * Checks an item to make sure it hasn't been overwritten since it was freed,
62 * prior to subsequent reallocation.
64 * Complies with standard ctor arg/return. arg should be zone pointer or NULL.
67 trash_ctor(void *mem, int size, void *arg, int flags)
69 struct uma_zone *zone = arg;
74 if (is_memguard_addr(mem))
78 e = p + size / sizeof(*p);
80 if (__predict_false(*p != uma_junk))
86 off = (uintptr_t)p - (uintptr_t)mem;
87 panic("Memory modified after free %p (%d, %s) + %d = %lx\n",
88 mem, size, zone ? zone->uz_name : "", off, *p);
93 * Fills an item with predictable garbage
95 * Complies with standard dtor arg/return
98 trash_dtor(void *mem, int size, void *arg)
102 #ifdef DEBUG_MEMGUARD
103 if (is_memguard_addr(mem))
107 e = p + size / sizeof(*p);
113 * Fills an item with predictable garbage
115 * Complies with standard init arg/return
118 trash_init(void *mem, int size, int flags)
120 trash_dtor(mem, size, NULL);
125 * Checks an item to make sure it hasn't been overwritten since it was freed,
126 * prior to freeing it back to available memory.
128 * Complies with standard fini arg/return
131 trash_fini(void *mem, int size)
133 (void)trash_ctor(mem, size, NULL, 0);
137 * Checks an item to make sure it hasn't been overwritten since it was freed,
138 * prior to subsequent reallocation.
140 * Complies with standard ctor arg/return. arg should be zone pointer or NULL.
143 mtrash_ctor(void *mem, int size, void *arg, int flags)
145 struct uma_zone *zone = arg;
147 struct malloc_type **ksp;
148 int off, osize = size;
150 #ifdef DEBUG_MEMGUARD
151 if (is_memguard_addr(mem))
155 size -= sizeof(struct malloc_type *);
157 e = p + size / sizeof(*p);
159 if (__predict_false(*p != uma_junk))
165 off = (uintptr_t)p - (uintptr_t)mem;
166 ksp = (struct malloc_type **)mem;
167 ksp += size / sizeof(struct malloc_type *);
170 && INKERNEL((uintptr_t)*ksp)
174 * If *ksp is corrupted we may be unable to panic clean,
175 * so print what we have reliably while we still can.
177 printf("Memory modified after free %p (%d, %s, %p) + %d = %lx\n",
178 mem, osize, zone ? zone->uz_name : "", *ksp, off, *p);
179 panic("Memory modified after free %p (%d, %s, %s) + %d = %lx\n",
180 mem, osize, zone ? zone->uz_name : "", (*ksp)->ks_shortdesc,
183 panic("Memory modified after free %p (%d, %s, %p) + %d = %lx\n",
184 mem, osize, zone ? zone->uz_name : "", *ksp, off, *p);
190 * Fills an item with predictable garbage
192 * Complies with standard dtor arg/return
195 mtrash_dtor(void *mem, int size, void *arg)
199 #ifdef DEBUG_MEMGUARD
200 if (is_memguard_addr(mem))
204 size -= sizeof(struct malloc_type *);
206 e = p + size / sizeof(*p);
212 * Fills an item with predictable garbage
214 * Complies with standard init arg/return
217 mtrash_init(void *mem, int size, int flags)
219 struct malloc_type **ksp;
221 #ifdef DEBUG_MEMGUARD
222 if (is_memguard_addr(mem))
226 mtrash_dtor(mem, size, NULL);
228 ksp = (struct malloc_type **)mem;
229 ksp += (size / sizeof(struct malloc_type *)) - 1;
235 * Checks an item to make sure it hasn't been overwritten since it was freed,
236 * prior to freeing it back to available memory.
238 * Complies with standard fini arg/return
241 mtrash_fini(void *mem, int size)
243 (void)mtrash_ctor(mem, size, NULL, 0);