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 58 static 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 */ 66 int 67 trash_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 */ 99 void 100 trash_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 */ 122 int 123 trash_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 */ 135 void 136 trash_fini(void *mem, int size) 137 { 138 (void)trash_ctor(mem, size, NULL, 0); 139 } 140 141 int 142 mtrash_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 */ 174 void 175 mtrash_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 */ 198 int 199 mtrash_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 */ 223 void 224 mtrash_fini(void *mem, int size) 225 { 226 (void)mtrash_ctor(mem, size, NULL, 0); 227 } 228