1 /* Copyright (C) 2007-2010 The Android Open Source Project 2 ** 3 ** This software is licensed under the terms of the GNU General Public 4 ** License version 2, as published by the Free Software Foundation, and 5 ** may be copied, distributed, and modified under those terms. 6 ** 7 ** This program is distributed in the hope that it will be useful, 8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 ** GNU General Public License for more details. 11 */ 12 13 /* 14 * Contains declarations of structures, routines, etc. that are commonly used 15 * in memechecker framework. 16 */ 17 18 #ifndef QEMU_MEMCHECK_MEMCHECK_COMMON_H 19 #define QEMU_MEMCHECK_MEMCHECK_COMMON_H 20 21 /* This file should compile iff qemu is built with memory checking 22 * configuration turned on. */ 23 #ifndef CONFIG_MEMCHECK 24 #error CONFIG_MEMCHECK is not defined. 25 #endif // CONFIG_MEMCHECK 26 27 #include "qemu-common.h" 28 #include "cpu.h" 29 30 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 // ============================================================================= 35 // Events generated by the guest system. 36 // ============================================================================= 37 38 /* Notifies the emulator that libc has been initialized for a process. 39 * Event's value parameter is PID for the process in context of which libc has 40 * been initialized. 41 */ 42 #define TRACE_DEV_REG_LIBC_INIT 1536 43 44 /* Notifies the emulator about new memory block being allocated. 45 * Event's value parameter points to MallocDesc instance in the guest's address 46 * space that contains allocated block information. Note that 'libc_pid' field 47 * of the descriptor is used by emulator to report failure in handling this 48 * event. In case of failure emulator will zero that filed before completing 49 * this event. 50 */ 51 #define TRACE_DEV_REG_MALLOC 1537 52 53 /* Notifies the emulator about memory block being freed. 54 * Event's value parameter points to MallocFree descriptor instance in the 55 * guest's address space that contains information about block that's being 56 * freed. Note that 'libc_pid' field of the descriptor is used by emulator to 57 * report failure in handling this event. In case of failure emulator will zero 58 * that filed before completing this event. 59 */ 60 #define TRACE_DEV_REG_FREE_PTR 1538 61 62 /* Queries the emulator about memory block information. 63 * Event's value parameter points to MallocDescQuery descriptor instance in the 64 * guest's address space that contains query parameters. Note that 'libc_pid' 65 * field of the descriptor is used by emulator to report failure in handling 66 * this event. In case of failure emulator will zero that filed before 67 * completing this event. 68 */ 69 #define TRACE_DEV_REG_QUERY_MALLOC 1539 70 71 /* Queries the emulator to print a string to its stdout. 72 * Event's value parameter points to zero-terminated string to be printed. Note 73 * that this string is located in the guest's address space. 74 */ 75 #define TRACE_DEV_REG_PRINT_USER_STR 1540 76 77 // ============================================================================= 78 // Communication structures 79 // ============================================================================= 80 81 /* Describes memory block allocated from the heap. This structure is passed 82 * along with TRACE_DEV_REG_MALLOC event. This descriptor is used to inform 83 * the emulator about new memory block being allocated from the heap. The entire 84 * structure is initialized by the guest system before event is fired up. It is 85 * important to remember that same structure (an exact copy) is also declared 86 * in the libc's sources. So, every time a change is made to any of these 87 * two declaration, another one must be also updated accordingly. */ 88 typedef struct MallocDesc { 89 /* Poniter to the memory block actually allocated from the heap. Note that 90 * this is not the pointer that is returned to the malloc's caller. Pointer 91 * returned to the caller is calculated by adding value stored in this field 92 * to the value stored in prefix_size field of this structure. 93 */ 94 target_ulong ptr; 95 96 /* Nuber of bytes requested by the malloc's caller. */ 97 uint32_t requested_bytes; 98 99 /* Byte size of the prefix data. Actual pointer returned to the malloc's 100 * caller is calculated by adding value stored in this field to the value 101 * stored in in the ptr field of this structure. 102 */ 103 uint32_t prefix_size; 104 105 /* Byte size of the suffix data. */ 106 uint32_t suffix_size; 107 108 /* Id of the process that initialized libc instance, in which allocation 109 * has occurred. This field is used by the emulator to report errors in 110 * the course of TRACE_DEV_REG_MALLOC event handling. In case of an error, 111 * emulator sets this field to zero (invalid value for a process ID). 112 */ 113 uint32_t libc_pid; 114 115 /* Id of the process in context of which allocation has occurred. 116 * Value in this field may differ from libc_pid value, if process that 117 * is doing allocation has been forked from the process that initialized 118 * libc instance. 119 */ 120 uint32_t allocator_pid; 121 122 /* Number of access violations detected on this allocation. */ 123 uint32_t av_count; 124 } MallocDesc; 125 /* Helpers for addressing field in MallocDesc structure, using which emulator 126 * reports an error back to the guest. 127 */ 128 #define ALLOC_RES_OFFSET ((uint32_t)&(((MallocDesc*)0)->libc_pid)) 129 #define ALLOC_RES_ADDRESS(p) (p + ALLOC_RES_OFFSET) 130 131 /* Describes memory block info queried from emulator. This structure is passed 132 * along with TRACE_DEV_REG_QUERY_MALLOC event. When handling free and realloc 133 * calls, it is required that we have information about memory blocks that were 134 * actually allocated in previous calls to malloc, memalign, or realloc. Since 135 * we don't keep this information directlry in the allocated block, but rather 136 * we keep it in the emulator, we need to query emulator for that information 137 * with TRACE_DEV_REG_QUERY_MALLOC query. The entire structure is initialized 138 * by the guest system before event is fired up It is important to remember that 139 * same structure (an exact copy) is also declared in the libc's sources. So, 140 * every time a change is made to any of these two declaration, another one 141 * must be also updated accordingly. 142 */ 143 typedef struct MallocDescQuery { 144 /* Pointer for which information is queried. Note that this pointer doesn't 145 * have to be exact pointer returned to malloc's caller, but can point 146 * anywhere inside an allocated block, including guarding areas. Emulator 147 * will respond with information about allocated block that contains this 148 * pointer. 149 */ 150 target_ulong ptr; 151 152 /* Id of the process that initialized libc instance, in which this query 153 * is called. This field is used by the emulator to report errors in 154 * the course of TRACE_DEV_REG_QUERY_MALLOC event handling. In case of an 155 * error, emulator sets this field to zero (invalid value for a process ID). 156 */ 157 uint32_t libc_pid; 158 159 /* Process ID in context of which query is made. */ 160 uint32_t query_pid; 161 162 /* Code of the allocation routine, in context of which query has been made: 163 * 1 - free 164 * 2 - realloc 165 */ 166 uint32_t routine; 167 168 /* Address in guest's virtual space of memory allocation descriptor for the 169 * queried pointer. Descriptor, addressed by this field is initialized by 170 * the emulator in response to the query. 171 */ 172 target_ulong desc; 173 } MallocDescQuery; 174 /* Helpers for addressing field in MallocDescQuery structure using which 175 * emulator reports an error back to the guest. 176 */ 177 #define QUERY_RES_OFFSET ((uint32_t)&(((MallocDescQuery*)0)->libc_pid)) 178 #define QUERY_RES_ADDRESS(p) (p + QUERY_RES_OFFSET) 179 180 /* Describes memory block that is being freed back to the heap. This structure 181 * is passed along with TRACE_DEV_REG_FREE_PTR event. The entire structure is 182 * initialized by the guest system before event is fired up. It is important to 183 * remember that same structure (an exact copy) is also declared in the libc's 184 * sources. So, every time a change is made to any of these two declaration, 185 * another one must be also updated accordingly. 186 */ 187 typedef struct MallocFree { 188 /* Pointer to be freed. */ 189 uint32_t ptr; 190 191 /* Id of the process that initialized libc instance, in which this free 192 * is called. This field is used by the emulator to report errors in 193 * the course of TRACE_DEV_REG_FREE_PTR event handling. In case of an 194 * error, emulator sets this field to zero (invalid value for a process ID). 195 */ 196 uint32_t libc_pid; 197 198 /* Process ID in context of which memory is being freed. */ 199 uint32_t free_pid; 200 } MallocFree; 201 /* Helpers for addressing field in MallocFree structure, using which emulator 202 * reports an error back to the guest. 203 */ 204 #define FREE_RES_OFFSET ((uint32_t)&(((MallocFree*)0)->libc_pid)) 205 #define FREE_RES_ADDRESS(p) (p + FREE_RES_OFFSET) 206 207 /* Extends MallocDesc structure with additional information, used by memchecker. 208 */ 209 typedef struct MallocDescEx { 210 /* Allocation descriptor this structure extends. */ 211 MallocDesc malloc_desc; 212 213 /* Call stack that lead to memory allocation. The array is arranged in 214 * accending order, where entry at index 0 corresponds to the routine 215 * that allocated memory. */ 216 target_ulong* call_stack; 217 218 /* Number of entries in call_stack array. */ 219 uint32_t call_stack_count; 220 221 /* Set of misc. flags. See MDESC_FLAG_XXX bellow. */ 222 uint32_t flags; 223 } MallocDescEx; 224 225 /* Indicates that memory has been allocated before process started execution. 226 * After a process has been forked, but before it actually starts executing, 227 * allocations can be made in context of that process PID. This flag marks such 228 * allocations in the process' allocation descriptors map. 229 */ 230 #define MDESC_FLAG_TRANSITION_ENTRY 0x00000001 231 232 /* Indicates that memory block has been inherited from the parent process. 233 * When a process is forked from its parent process, the forked process inherits 234 * a copy of the parent process' heap. Thus, all allocations that were recorded 235 * for the parent process must be also recorded for the forked process. This 236 * flag marks entries in the forked process' allocation descriptors map that 237 * were copied over from the parent process' allocation descriptors map. 238 */ 239 #define MDESC_FLAG_INHERITED_ON_FORK 0x00000002 240 241 /* Describes a memory mapping of an execution module in the guest system. */ 242 typedef struct MMRangeDesc { 243 /* Starting address of mmapping of a module in the guest's address space. */ 244 target_ulong map_start; 245 246 /* Ending address of mmapping of a module in the guest's address space. */ 247 target_ulong map_end; 248 249 /* Mmapping's execution offset. */ 250 target_ulong exec_offset; 251 252 /* Image path of the module that has been mapped with this mmapping. */ 253 char* path; 254 } MMRangeDesc; 255 256 /* Enumerates returned values for insert routines implemeted for red-black 257 * tree maps. 258 */ 259 typedef enum { 260 /* New entry has been inserted into the map. */ 261 RBT_MAP_RESULT_ENTRY_INSERTED = 0, 262 263 /* An entry, matching the new one already exists in the map. */ 264 RBT_MAP_RESULT_ENTRY_ALREADY_EXISTS, 265 266 /* An existing entry, matching the new one has been replaced 267 * with the new entry. 268 */ 269 RBT_MAP_RESULT_ENTRY_REPLACED, 270 271 /* An error has occurred when inserting entry into the map. */ 272 RBT_MAP_RESULT_ERROR = -1, 273 } RBTMapResult; 274 275 /* Encapsulates an array of guest addresses, sorted in accending order. */ 276 typedef struct AddrArray { 277 /* Array of addresses. */ 278 target_ulong* addr; 279 280 /* Number of elements in the array. */ 281 int num; 282 } AddrArray; 283 284 // ============================================================================= 285 // Inlines 286 // ============================================================================= 287 288 /* Gets pointer returned to malloc caller for the given allocation decriptor. 289 * Param: 290 * desc - Allocation descriptor. 291 * Return: 292 * Pointer to the allocated memory returned to the malloc caller. 293 */ 294 static inline target_ulong 295 mallocdesc_get_user_ptr(const MallocDesc* desc) 296 { 297 return desc->ptr + desc->prefix_size; 298 } 299 300 /* Gets total size of the allocated block for the given descriptor. 301 * Param: 302 * desc - Descriptor for the memory block, allocated in malloc handler. 303 * Return: 304 * Total size of memory block allocated in malloc handler. 305 */ 306 static inline uint32_t 307 mallocdesc_get_alloc_size(const MallocDesc* desc) 308 { 309 return desc->prefix_size + desc->requested_bytes + desc->suffix_size; 310 } 311 312 /* Gets the end of the allocated block for the given descriptor. 313 * Param: 314 * desc - Descriptor for the memory block, allocated in malloc handler. 315 * Return: 316 * Pointer to the end of the allocated block (next byte past the block). 317 */ 318 static inline target_ulong 319 mallocdesc_get_alloc_end(const MallocDesc* desc) 320 { 321 return desc->ptr + mallocdesc_get_alloc_size(desc); 322 } 323 324 /* Gets the end of the allocated block available to the user for the given 325 * descriptor. 326 * Param: 327 * desc - Descriptor for the memory block, allocated in malloc handler. 328 * Return: 329 * Pointer to the end of the allocated block available to the user (next byte 330 * past the block - suffix guarding area). 331 */ 332 static inline target_ulong 333 mallocdesc_get_user_alloc_end(const MallocDesc* desc) 334 { 335 return mallocdesc_get_user_ptr(desc) + desc->requested_bytes; 336 } 337 338 /* Checks if allocation has been made before process started execution. 339 * Param: 340 * desc - Allocation descriptor to check. 341 * Return: 342 * boolean: 1 if allocation has been made before process started execution, 343 * or 0 if allocation has been made after process started execution. 344 */ 345 static inline int 346 mallocdescex_is_transition_entry(const MallocDescEx* desc) 347 { 348 return (desc->flags & MDESC_FLAG_TRANSITION_ENTRY) != 0; 349 } 350 351 /* Checks if allocation block has been inherited on fork. 352 * Param: 353 * desc - Allocation descriptor to check. 354 * Return: 355 * boolean: 1 if allocation has been inherited on fork, or 0 if allocation 356 * has been made by this process.. 357 */ 358 static inline int 359 mallocdescex_is_inherited_on_fork(const MallocDescEx* desc) 360 { 361 return (desc->flags & MDESC_FLAG_INHERITED_ON_FORK) != 0; 362 } 363 364 /* Gets offset for the given address inside a mapped module. 365 * Param: 366 * address - Address to get offset for. 367 * Return: 368 * Offset of the given address inside a mapped module, represented with the 369 * given mmaping range descriptor. 370 */ 371 static inline target_ulong 372 mmrangedesc_get_module_offset(const MMRangeDesc* rdesc, target_ulong address) 373 { 374 return address - rdesc->map_start + rdesc->exec_offset; 375 } 376 377 /* Checks if given address is contained in the given address array. 378 * Return: 379 * boolean: 1 if address is contained in the array, or zero if it's not. 380 */ 381 static inline int 382 addrarray_check(const AddrArray* addr_array, target_ulong addr) 383 { 384 if (addr_array->num != 0) { 385 int m_min = 0; 386 int m_max = addr_array->num - 1; 387 388 /* May be odd for THUMB mode. */ 389 addr &= ~1; 390 /* Since array is sorted we can do binary search here. */ 391 while (m_min <= m_max) { 392 const int m = (m_min + m_max) >> 1; 393 const target_ulong saved = addr_array->addr[m]; 394 if (addr == saved) { 395 return 1; 396 } 397 if (addr < saved) { 398 m_max = m - 1; 399 } else { 400 m_min = m + 1; 401 } 402 } 403 } 404 return 0; 405 } 406 407 /* Adds an address to the address array. 408 * Return: 409 * 1 - Address has been added to the array. 410 * -1 - Address already exists in the array. 411 * 0 - Unable to expand the array. 412 */ 413 static inline int 414 addrarray_add(AddrArray* addr_array, target_ulong addr) 415 { 416 target_ulong* new_arr; 417 int m_min; 418 int m_max; 419 420 /* May be odd for THUMB mode. */ 421 addr &= ~1; 422 if (addr_array->num == 0) { 423 /* First element. */ 424 addr_array->addr = qemu_malloc(sizeof(target_ulong)); 425 assert(addr_array->addr != NULL); 426 if (addr_array->addr == NULL) { 427 return 0; 428 } 429 *addr_array->addr = addr; 430 addr_array->num++; 431 return 1; 432 } 433 434 /* Using binary search find the place where to insert new address. */ 435 m_min = 0; 436 m_max = addr_array->num - 1; 437 while (m_min <= m_max) { 438 const int m = (m_min + m_max) >> 1; 439 const target_ulong saved = addr_array->addr[m]; 440 if (addr == saved) { 441 return -1; 442 } 443 if (addr < saved) { 444 m_max = m - 1; 445 } else { 446 m_min = m + 1; 447 } 448 } 449 if (m_max < 0) { 450 m_max = 0; 451 } 452 /* Expand the array. */ 453 new_arr = qemu_malloc(sizeof(target_ulong) * (addr_array->num + 1)); 454 assert(new_arr != NULL); 455 if (new_arr == NULL) { 456 return 0; 457 } 458 /* Copy preceding elements to the new array. */ 459 if (m_max != 0) { 460 memcpy(new_arr, addr_array->addr, m_max * sizeof(target_ulong)); 461 } 462 if (addr > addr_array->addr[m_max]) { 463 new_arr[m_max] = addr_array->addr[m_max]; 464 m_max++; 465 } 466 /* Insert new address. */ 467 new_arr[m_max] = addr; 468 /* Copy remaining elements to the new array. */ 469 if (m_max < addr_array->num) { 470 memcpy(new_arr + m_max + 1, addr_array->addr + m_max, 471 (addr_array->num - m_max) * sizeof(target_ulong)); 472 } 473 /* Swap arrays. */ 474 qemu_free(addr_array->addr); 475 addr_array->addr = new_arr; 476 addr_array->num++; 477 return 1; 478 } 479 480 #ifdef __cplusplus 481 }; /* end of extern "C" */ 482 #endif 483 484 #endif // QEMU_MEMCHECK_MEMCHECK_COMMON_H 485