📄 chunk.c
字号:
skip_alloc_t *other_p; pnt_info_t pnt_info; int out_len, dump_size, offset; dmalloc_error(where); if (slot_p == NULL) { prev_file = NULL; prev_line = 0; user_size = 0; start_user = user_pnt; } else { prev_file = slot_p->sa_file; prev_line = slot_p->sa_line; user_size = slot_p->sa_user_size; if (user_pnt == NULL) { get_pnt_info(slot_p, &pnt_info); start_user = pnt_info.pi_user_start; } else { start_user = user_pnt; } } /* get a proper reason string */ if (reason != NULL) { dmalloc_message(" error details: %s", reason); } /* dump the pointer information */ if (start_user == NULL) { dmalloc_message(" from '%s' prev access '%s'", _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), now_file, now_line), _dmalloc_chunk_desc_pnt(where_buf2, sizeof(where_buf2), prev_file, prev_line)); } else { dmalloc_message(" pointer '%#lx' from '%s' prev access '%s'", (unsigned long)start_user, _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), now_file, now_line), _dmalloc_chunk_desc_pnt(where_buf2, sizeof(where_buf2), prev_file, prev_line)); } /* * If we aren't logging bad space or we didn't error with an * overwrite error then don't log the bad bytes. */ if ((! BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_BAD_SPACE)) || (dmalloc_errno != ERROR_UNDER_FENCE && dmalloc_errno != ERROR_OVER_FENCE && dmalloc_errno != ERROR_FREE_OVERWRITTEN)) { return; } /* NOTE: display memory like this has the potential for generating a core */ if (dmalloc_errno == ERROR_UNDER_FENCE) { /* NOTE: only dump out the proper fence-post area once */ if (! dump_bottom_b) { out_len = expand_chars(fence_bottom, FENCE_BOTTOM_SIZE, out, sizeof(out)); dmalloc_message(" dump of proper fence-bottom bytes: '%.*s'", out_len, out); dump_bottom_b = 1; } offset = -FENCE_BOTTOM_SIZE; dump_size = DUMP_SPACE + FENCE_BOTTOM_SIZE; if (dump_size > user_size + FENCE_OVERHEAD_SIZE) { dump_size = user_size + FENCE_OVERHEAD_SIZE; } } else if (dmalloc_errno == ERROR_OVER_FENCE && user_size > 0) { /* NOTE: only dump out the proper fence-post area once */ if (! dump_top_b) { out_len = expand_chars(fence_top, FENCE_TOP_SIZE, out, sizeof(out)); dmalloc_message(" dump of proper fence-top bytes: '%.*s'", out_len, out); dump_top_b = 1; } /* * The size includes the bottom fence post area. We want it to * align with the start of the top fence post area. */ if (DUMP_SPACE > user_size + FENCE_OVERHEAD_SIZE) { dump_size = user_size + FENCE_OVERHEAD_SIZE; offset = -FENCE_BOTTOM_SIZE; } else { dump_size = DUMP_SPACE; /* we will go backwards possibly up to FENCE_BOTTOM_SIZE offset */ offset = user_size + FENCE_TOP_SIZE - DUMP_SPACE; } } else { dump_size = DUMP_SPACE; offset = 0; if (user_size > 0 && dump_size > user_size) { dump_size = user_size; } } dump_pnt = (char *)start_user + offset; if (IS_IN_HEAP(dump_pnt)) { out_len = expand_chars(dump_pnt, dump_size, out, sizeof(out)); dmalloc_message(" dump of '%#lx'%+d: '%.*s'", (unsigned long)start_user, offset, out_len, out); } else { dmalloc_message(" dump of '%#lx'%+d failed: not in heap", (unsigned long)start_user, offset); } /* find the previous pointer in case it ran over */ if (dmalloc_errno == ERROR_UNDER_FENCE && start_user != NULL) { other_p = find_address((char *)start_user - FENCE_BOTTOM_SIZE - 1, 1 /* not exact pointer */, skip_update); if (other_p != NULL) { dmalloc_message(" prev pointer '%#lx' (size %u) may have run over from '%s'", (unsigned long)other_p->sa_mem, other_p->sa_user_size, _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), other_p->sa_file, other_p->sa_line)); } } /* find the next pointer in case it ran under */ else if (dmalloc_errno == ERROR_OVER_FENCE && start_user != NULL && slot_p != NULL) { other_p = find_address((char *)slot_p->sa_mem + slot_p->sa_total_size, 1 /* not exact pointer */, skip_update); if (other_p != NULL) { dmalloc_message(" next pointer '%#lx' (size %u) may have run under from '%s'", (unsigned long)other_p->sa_mem, other_p->sa_user_size, _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), other_p->sa_file, other_p->sa_line)); } }}/* * static int fence_read * * DESCRIPTION * * Check a pointer for fence-post magic numbers. * * RETURNS: * * Success - 1 if the fence posts are good. * * Failure - 0 if they are not. * * ARGUMENTS: * * info_p -> Pointer information that we are checking. */static int fence_read(const pnt_info_t *info_p){ /* check magic numbers in bottom of allocation block */ if (memcmp(fence_bottom, info_p->pi_fence_bottom, FENCE_BOTTOM_SIZE) != 0) { dmalloc_errno = ERROR_UNDER_FENCE; return 0; } /* check numbers at top of allocation block */ if (memcmp(fence_top, info_p->pi_fence_top, FENCE_TOP_SIZE) != 0) { dmalloc_errno = ERROR_OVER_FENCE; return 0; } return 1;}/* * static void clear_alloc * * DESCRIPTION * * Setup allocations by writing fence post and doing any necessary * clearing of memory. * * RETURNS: * * Success - 1 if the fence posts are good. * * Failure - 0 if they are not. * * ARGUMENTS: * * slot_p <-> Slot we are clearing. * * info_p -> Pointer to information about the allocation. * * old_size -> If there was an old-size that we have copied into the * new pointer then set this. If 0 then it will clear the entire * allocation. * * func_id -> ID of the function which is doing the allocation. Used * to determine if we should 0 memory for [re]calloc. */static void clear_alloc(skip_alloc_t *slot_p, pnt_info_t *info_p, const unsigned int old_size, const int func_id){ char *start_p; int num; /* * NOTE: The alloc blank flag is set so we blank a slot when it is * allocated. It used to be that the allocated spaces were blanked * and the free spaces of the allocated chunk were blanked only if * the FREE_BLANK flag was enabled. Wrong! */ /* * Set our slot blank flag if the flags are set now. This will * carry over with a realloc. */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_ALLOC_BLANK) || BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_BLANK)) { BIT_SET(slot_p->sa_flags, ALLOC_FLAG_BLANK); } /* * If we have a fence post protected valloc then there is almost a * full block at the front what is "free". Set it with blank chars. */ if (info_p->pi_fence_b) { num = (char *)info_p->pi_fence_bottom - (char *)info_p->pi_alloc_start; /* alloc-blank NOT free-blank */ if (num > 0 && BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_BLANK)) { memset(info_p->pi_alloc_start, ALLOC_BLANK_CHAR, num); } } /* * If we are allocating or extending memory, write in our alloc * chars. */ start_p = (char *)info_p->pi_user_start + old_size; num = (char *)info_p->pi_user_bounds - start_p; if (num > 0) { if (func_id == DMALLOC_FUNC_CALLOC || func_id == DMALLOC_FUNC_RECALLOC) { memset(start_p, 0, num); } else if (BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_BLANK)) { memset(start_p, ALLOC_BLANK_CHAR, num); } } /* write in fence-post info */ if (info_p->pi_fence_b) { memcpy(info_p->pi_fence_bottom, fence_bottom, FENCE_BOTTOM_SIZE); memcpy(info_p->pi_fence_top, fence_top, FENCE_TOP_SIZE); } /* * Now clear the rest of the block above any fence post space with * free characters. * * NOTE alloc-blank NOT free-blank */ if (BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_BLANK)) { if (info_p->pi_fence_b) { start_p = (char *)info_p->pi_fence_top + FENCE_TOP_SIZE; } else { start_p = info_p->pi_user_bounds; } num = (char *)info_p->pi_alloc_bounds - start_p; if (num > 0) { memset(start_p, ALLOC_BLANK_CHAR, num); } }}/************************** administration functions *************************//* * static int create_divided_chunks * * DESCRIPTION: * * Get a divided-block from the free list or heap allocation. * * RETURNS: * * Success - 1 * * Failure - 0 * * ARGUMENTS: * * div_size -> Size of the divided block that we are allocating. */static int create_divided_chunks(const unsigned int div_size){ void *mem, *bounds_p; /* allocate a 1 block chunk that we will cut up into pieces */ mem = _dmalloc_heap_alloc(BLOCK_SIZE); if (mem == HEAP_ALLOC_ERROR) { /* error code set in _dmalloc_heap_alloc */ return 0; } user_block_c++; /* * now run through the block and add the the locations to the * free-list */ /* end of the block */ bounds_p = (char *)mem + BLOCK_SIZE - div_size; for (; mem <= bounds_p; mem = (char *)mem + div_size) { /* insert the rest of the blocks into the free-list */ if (insert_address(mem, 1 /* free list */, div_size) == NULL) { /* error set in insert_address */ return 0; } free_space_bytes += div_size; } return 1;}/* * static skip_alloc_t *use_free_memory * * DESCRIPTION: * * Find a free memory chunk and remove it from the free list and put * it on the used list if available. * * RETURNS: * * Success - Valid slot pointer * * Failure - NULL * * ARGUMENTS: * * size -> Size of the block that we are looking for. * * update_p -> Pointer to the skip_alloc entry we are using to hold * the update pointers. */static skip_alloc_t *use_free_memory(const unsigned int size, skip_alloc_t *update_p){ skip_alloc_t *slot_p; #if FREED_POINTER_DELAY /* * check the free wait list to see if any of the waiting pointers * need to be moved off and inserted into the free list */ for (slot_p = free_wait_list_head; slot_p != NULL; ) { skip_alloc_t *next_p; /* we are done if we find a pointer delay in the future */ if (slot_p->sa_use_iter + FREED_POINTER_DELAY > _dmalloc_iter_c) { break; } /* put slot on free list */ next_p = slot_p->sa_next_p[0]; if (! insert_slot(slot_p, 1 /* free list */)) { /* error dumped in insert_slot */ return NULL; } /* adjust our linked list */ slot_p = next_p; free_wait_list_head = slot_p; if (slot_p == NULL) { free_wait_list_tail = NULL; } }#endif /* find a free block which matches the size */ slot_p = find_free_size(size, update_p); if (slot_p == NULL) { return NULL; } /* sanity check */ if (slot_p->sa_total_size != size) { dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("use_free_memory"); return NULL; } /* remove from free list */ if (! remove_slot(slot_p, update_p)) { /* error reported in remove_slot */ return NULL; } /* set to user allocated space */ slot_p->sa_flags = ALLOC_FLAG_USER; /* insert it into our address list */ if (! insert_slot(slot_p, 0 /* used list */)) { /* error set in insert_slot */ return NULL; } free_space_bytes -= slot_p->sa_total_size; return slot_p;}/* * static skip_alloc_t *get_divided_memory * * DESCRIPTION: * * Get a divided memory block from the free list or heap allocation. * * RETURNS: * * Success - Valid skip slot pointer. * * Failure - NULL * * ARGUMENTS: * * size -> Size of the block that we are allocating. */static skip_alloc_t *get_divided_memory(const unsigned int size){ skip_alloc_t *slot_p; unsigned int need_size; int *bits_p; for (bits_p = bit_sizes;; bits_p++) { if (*bits_p >= size) { break; } } need_size = *bits_p; /* find a free block which matches the size */ slot_p = use_free_memory(need_size, skip_update); if (slot_p != NULL) { return slot_p; } /* need to get more slots */ if (! create_divided_chunks(need_size)) { /* errors dumped in create_divided_chunks */ return NULL; } /* now we ask again for the free memory */ slot_p = use_free_memory(need_size, skip_update); if (slot_p == NULL) { /* huh? This isn't right. */ dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("get_divided_memory"); return NULL; } return slot_p;}/* * static skip_alloc_t *get_memory * * DESCRIPTION: * * Get a block from the free list or heap allocation. * * RETURNS: * * Success - Valid skip slot pointer. * * Failure - NULL * * ARGUMENTS: * * size -> Size of the block that we are allocating. */static skip_alloc_t *get_memory(const unsigned int size){ skip_alloc_t *slot_p, *update_p; void *mem; unsigned int need_size, block_n; /* do we need to print admin info? */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_ADMIN)) { dmalloc_message("need %d bytes", size); } /* will this allocate put us over the limit? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -