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 25 extern "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. */ 82 typedef 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 */ 137 typedef 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 */ 181 typedef 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 */ 203 typedef 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. */ 236 typedef 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 */ 253 typedef 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. */ 270 typedef 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 */ 288 static inline target_ulong 289 mallocdesc_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 */ 300 static inline uint32_t 301 mallocdesc_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 */ 312 static inline target_ulong 313 mallocdesc_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 */ 326 static inline target_ulong 327 mallocdesc_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 */ 339 static inline int 340 mallocdescex_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 */ 352 static inline int 353 mallocdescex_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 */ 365 static inline target_ulong 366 mmrangedesc_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 */ 375 static inline int 376 addrarray_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 */ 407 static inline int 408 addrarray_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