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