1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2002, 2003, 2004, 2005 Jeffrey Roberson <jeff@FreeBSD.org> 5 * Copyright (c) 2004, 2005 Bosko Milekic <bmilekic@FreeBSD.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice unmodified, this list of conditions, and the following 13 * disclaimer. 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. 17 * 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. 28 */ 29 30/* 31 * uma_dbg.c Debugging features for UMA users 32 * 33 */ 34 35#include <sys/cdefs.h> 36__FBSDID("$FreeBSD$"); 37 38#include "opt_vm.h" 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/bitset.h> 43#include <sys/kernel.h> 44#include <sys/types.h> 45#include <sys/queue.h> 46#include <sys/lock.h> 47#include <sys/mutex.h> 48#include <sys/malloc.h> 49 50#include <vm/vm.h> 51#include <vm/vm_object.h> 52#include <vm/vm_page.h> 53#include <vm/uma.h> 54#include <vm/uma_int.h> 55#include <vm/uma_dbg.h> 56#include <vm/memguard.h> 57 58static const uint32_t uma_junk = 0xdeadc0de; 59 60/* 61 * Checks an item to make sure it hasn't been overwritten since it was freed, 62 * prior to subsequent reallocation. 63 * 64 * Complies with standard ctor arg/return 65 */ 66int 67trash_ctor(void *mem, int size, void *arg, int flags) 68{ 69 int cnt; 70 uint32_t *p; 71 72#ifdef DEBUG_MEMGUARD 73 if (is_memguard_addr(mem)) 74 return (0); 75#endif 76 77 cnt = size / sizeof(uma_junk); 78 79 for (p = mem; cnt > 0; cnt--, p++) 80 if (*p != uma_junk) { 81#ifdef INVARIANTS 82 panic("Memory modified after free %p(%d) val=%x @ %p\n", 83 mem, size, *p, p); 84#else 85 printf("Memory modified after free %p(%d) val=%x @ %p\n", 86 mem, size, *p, p); 87#endif 88 return (0); 89 } 90 return (0); 91} 92 93/* 94 * Fills an item with predictable garbage 95 * 96 * Complies with standard dtor arg/return 97 * 98 */ 99void 100trash_dtor(void *mem, int size, void *arg) 101{ 102 int cnt; 103 uint32_t *p; 104 105#ifdef DEBUG_MEMGUARD 106 if (is_memguard_addr(mem)) 107 return; 108#endif 109 110 cnt = size / sizeof(uma_junk); 111 112 for (p = mem; cnt > 0; cnt--, p++) 113 *p = uma_junk; 114} 115 116/* 117 * Fills an item with predictable garbage 118 * 119 * Complies with standard init arg/return 120 * 121 */ 122int 123trash_init(void *mem, int size, int flags) 124{ 125 trash_dtor(mem, size, NULL); 126 return (0); 127} 128 129/* 130 * Checks an item to make sure it hasn't been overwritten since it was freed. 131 * 132 * Complies with standard fini arg/return 133 * 134 */ 135void 136trash_fini(void *mem, int size) 137{ 138 (void)trash_ctor(mem, size, NULL, 0); 139} 140 141int 142mtrash_ctor(void *mem, int size, void *arg, int flags) 143{ 144 struct malloc_type **ksp; 145 uint32_t *p = mem; 146 int cnt; 147 148#ifdef DEBUG_MEMGUARD 149 if (is_memguard_addr(mem)) 150 return (0); 151#endif 152 153 size -= sizeof(struct malloc_type *); 154 ksp = (struct malloc_type **)mem; 155 ksp += size / sizeof(struct malloc_type *); 156 cnt = size / sizeof(uma_junk); 157 158 for (p = mem; cnt > 0; cnt--, p++) 159 if (*p != uma_junk) { 160 printf("Memory modified after free %p(%d) val=%x @ %p\n", 161 mem, size, *p, p); 162 panic("Most recently used by %s\n", (*ksp == NULL)? 163 "none" : (*ksp)->ks_shortdesc); 164 } 165 return (0); 166} 167 168/* 169 * Fills an item with predictable garbage 170 * 171 * Complies with standard dtor arg/return 172 * 173 */ 174void 175mtrash_dtor(void *mem, int size, void *arg) 176{ 177 int cnt; 178 uint32_t *p; 179 180#ifdef DEBUG_MEMGUARD 181 if (is_memguard_addr(mem)) 182 return; 183#endif 184 185 size -= sizeof(struct malloc_type *); 186 cnt = size / sizeof(uma_junk); 187 188 for (p = mem; cnt > 0; cnt--, p++) 189 *p = uma_junk; 190} 191 192/* 193 * Fills an item with predictable garbage 194 * 195 * Complies with standard init arg/return 196 * 197 */ 198int 199mtrash_init(void *mem, int size, int flags) 200{ 201 struct malloc_type **ksp; 202 203#ifdef DEBUG_MEMGUARD 204 if (is_memguard_addr(mem)) 205 return (0); 206#endif 207 208 mtrash_dtor(mem, size, NULL); 209 210 ksp = (struct malloc_type **)mem; 211 ksp += (size / sizeof(struct malloc_type *)) - 1; 212 *ksp = NULL; 213 return (0); 214} 215 216/* 217 * Checks an item to make sure it hasn't been overwritten since it was freed, 218 * prior to freeing it back to available memory. 219 * 220 * Complies with standard fini arg/return 221 * 222 */ 223void 224mtrash_fini(void *mem, int size) 225{ 226 (void)mtrash_ctor(mem, size, NULL, 0); 227} 228