📄 chunk.c
字号:
if (_dmalloc_memory_limit > 0 && alloc_cur_given + size > _dmalloc_memory_limit) { dmalloc_errno = ERROR_OVER_LIMIT; dmalloc_error("get_memory"); return NULL; } /* do we have a divided block here? */ if (size <= BLOCK_SIZE / 2) { return get_divided_memory(size); } /* round up to the nearest block size */ need_size = size + BLOCK_SIZE - 1; block_n = need_size / BLOCK_SIZE; need_size = block_n * BLOCK_SIZE; update_p = skip_update; /* find a free block which matches the size */ slot_p = use_free_memory(need_size, update_p); if (slot_p != NULL) { return slot_p; } /* if there are blocks that are larger than this */ slot_p = update_p->sa_next_p[0]; if (slot_p != NULL && slot_p->sa_total_size > size) { /* * now we ask again for the memory because we need to reset the * update pointer list */ slot_p = use_free_memory(need_size, update_p); if (slot_p != NULL) { /* huh? This isn't right. */ dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("get_memory"); return NULL; } } /* allocate the memory necessary for the new blocks */ mem = _dmalloc_heap_alloc(need_size); if (mem == HEAP_ALLOC_ERROR) { /* error code set in _dmalloc_heap_alloc */ return NULL; } user_block_c += block_n; /* create our slot */ slot_p = insert_address(mem, 0 /* used list */, need_size); if (slot_p == NULL) { /* error set in insert_address */ return NULL; } return slot_p;}/* * static int check_used_slot * * Check out the pointer in a allocated slot to make sure it is good. * * RETURNS: * * Success - 1 * * Failure - 0 * * ARGUMENTS: * * slot_p -> Slot that we are checking. * * user_pnt -> User pointer which was used to get the slot or NULL. * * exact_b -> Set to 1 to find the pointer specifically. Otherwise we * can find the pointer inside of an allocation. */static int check_used_slot(const skip_alloc_t *slot_p, const void *user_pnt, const int exact_b){ const char *file, *name_p, *bounds_p, *mem_p; unsigned int line, num; pnt_info_t pnt_info; if (! (BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_USER) || BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_EXTERN) || BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_ADMIN))) { dmalloc_errno = ERROR_SLOT_CORRUPT; return 0; } /* get pointer info */ get_pnt_info(slot_p, &pnt_info); /* if we need the exact pointer, make sure that the user_pnt agrees */ if (exact_b && user_pnt != pnt_info.pi_user_start) { dmalloc_errno = ERROR_NOT_START_BLOCK; return 0; } #if LARGEST_ALLOCATION /* have we exceeded the upper bounds */ if (slot_p->sa_user_size > LARGEST_ALLOCATION) { dmalloc_errno = ERROR_BAD_SIZE; return 0; }#endif /* check our total block size */ if (slot_p->sa_total_size > BLOCK_SIZE / 2 && slot_p->sa_total_size % BLOCK_SIZE != 0) { dmalloc_errno = ERROR_BAD_SIZE; return 0; } /* * If we have a valloc allocation then the _user_ pnt should be * block aligned otherwise the chunk_pnt should be. */ if (pnt_info.pi_valloc_b) { if ((long)pnt_info.pi_user_start % BLOCK_SIZE != 0) { dmalloc_errno = ERROR_NOT_ON_BLOCK; return 0; } if (slot_p->sa_total_size < BLOCK_SIZE) { dmalloc_errno = ERROR_SLOT_CORRUPT; return 0; } /* now check the below space to make sure it is still clear */ if (pnt_info.pi_fence_b && pnt_info.pi_blanked_b) { num = (char *)pnt_info.pi_fence_bottom - (char *)pnt_info.pi_alloc_start; if (num > 0) { for (mem_p = pnt_info.pi_alloc_start; mem_p < (char *)pnt_info.pi_fence_bottom; mem_p++) { if (*mem_p != ALLOC_BLANK_CHAR) { dmalloc_errno = ERROR_FREE_OVERWRITTEN; return 0; } } } } } /* check out the fence-posts */ if (pnt_info.pi_fence_b && (! fence_read(&pnt_info))) { /* errno set in fence_read */ return 0; } /* check above the allocation to see if it's been overwritten */ if (pnt_info.pi_blanked_b) { if (pnt_info.pi_fence_b) { mem_p = (char *)pnt_info.pi_fence_top + FENCE_TOP_SIZE; } else { mem_p = pnt_info.pi_user_bounds; } for (; mem_p < (char *)pnt_info.pi_alloc_bounds; mem_p++) { if (*mem_p != ALLOC_BLANK_CHAR) { dmalloc_errno = ERROR_FREE_OVERWRITTEN; return 0; } } } file = slot_p->sa_file; line = slot_p->sa_line; /* check line number */#if MAX_LINE_NUMBER if (line > MAX_LINE_NUMBER) { dmalloc_errno = ERROR_BAD_LINE; return 0; }#endif /* * Check file pointer only if file is not NULL and line is not 0 * which implies that file is a return-addr. */#if MAX_FILE_LENGTH if (file != DMALLOC_DEFAULT_FILE && line != DMALLOC_DEFAULT_LINE) { /* NOTE: we don't use strlen here because we might check too far */ bounds_p = file + MAX_FILE_LENGTH; for (name_p = file; name_p < bounds_p && *name_p != '\0'; name_p++) { } if (name_p >= bounds_p || name_p < file + MIN_FILE_LENGTH) { dmalloc_errno = ERROR_BAD_FILE; return 0; } }#endif #if LOG_PNT_SEEN_COUNT /* * We divide by 2 here because realloc which returns the same * pointer will seen_c += 2. However, it will never be more than * twice the iteration value. We divide by two to not overflow * iter_c * 2. */ if (slot_p->sa_seen_c / 2 > _dmalloc_iter_c) { dmalloc_errno = ERROR_SLOT_CORRUPT; return 0; }#endif return 1;}/* * static int check_free_slot * * Check out the pointer in a slot to make sure it is good. * * RETURNS: * * Success - 1 * * Failure - 0 * * ARGUMENTS: * * slot_p -> Slot that we are checking. */static int check_free_slot(const skip_alloc_t *slot_p){ char *check_p; if (! BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_FREE)) { dmalloc_errno = ERROR_SLOT_CORRUPT; return 0; } if (BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_BLANK)) { for (check_p = (char *)slot_p->sa_mem; check_p < (char *)slot_p->sa_mem + slot_p->sa_total_size; check_p++) { if (*check_p != FREE_BLANK_CHAR) { dmalloc_errno = ERROR_FREE_OVERWRITTEN; return 0; } } } #if LOG_PNT_SEEN_COUNT /* * We divide by 2 here because realloc which returns the same * pointer will seen_c += 2. However, it will never be more than * twice the iteration value. We divide by two to not overflow * iter_c * 2. */ if (slot_p->sa_seen_c / 2 > _dmalloc_iter_c) { dmalloc_errno = ERROR_SLOT_CORRUPT; return 0; }#endif return 1;}/***************************** exported routines *****************************//* * int _dmalloc_chunk_startup * * DESCRIPTION: * * Startup the low level malloc routines. * * RETURNS: * * Success - 1 * * Failure - 0 * * ARGUMENTS: * * None. */int _dmalloc_chunk_startup(void){ unsigned int value; char *pos_p, *max_p; int bit_c, *bits_p; value = FENCE_MAGIC_BOTTOM; max_p = fence_bottom + FENCE_BOTTOM_SIZE; for (pos_p = fence_bottom; pos_p < max_p; pos_p += sizeof(value)) { if (pos_p + sizeof(value) <= max_p) { memcpy(pos_p, (char *)&value, sizeof(value)); } else { memcpy(pos_p, (char *)&value, max_p - pos_p); } } value = FENCE_MAGIC_TOP; max_p = fence_top + FENCE_TOP_SIZE; for (pos_p = fence_top; pos_p < max_p; pos_p += sizeof(value)) { if (pos_p + sizeof(value) <= max_p) { memcpy(pos_p, (char *)&value, sizeof(value)); } else { memcpy(pos_p, (char *)&value, max_p - pos_p); } } /* initialize the bits array */ bits_p = bit_sizes; for (bit_c = 0; bit_c < BASIC_BLOCK; bit_c++) { if ((1 << bit_c) >= CHUNK_SMALLEST_BLOCK) { *bits_p++ = 1 << bit_c; } } /* set the admin flags on the two statically allocated slots */ skip_free_list->sa_flags = ALLOC_FLAG_ADMIN; skip_address_list->sa_flags = ALLOC_FLAG_ADMIN; return 1;}/* * char *_dmalloc_chunk_desc_pnt * * DESCRIPTION: * * Write into a buffer a pointer description with file and * line-number. * * RETURNS: * * Pointer to buffer 1st argument. * * ARGUMENTS: * * buf <-> Passed in buffer which will be filled with a description of * the pointer. * * buf_size -> Size of the buffer in bytes. * * file -> File name, return address, or NULL. * * line -> Line number or 0. */char *_dmalloc_chunk_desc_pnt(char *buf, const int buf_size, const char *file, const unsigned int line){ if (file == DMALLOC_DEFAULT_FILE && line == DMALLOC_DEFAULT_LINE) { (void)loc_snprintf(buf, buf_size, "unknown"); } else if (line == DMALLOC_DEFAULT_LINE) { (void)loc_snprintf(buf, buf_size, "ra=%#lx", (unsigned long)file); } else if (file == DMALLOC_DEFAULT_FILE) { (void)loc_snprintf(buf, buf_size, "ra=ERROR(line=%u)", line); } else { (void)loc_snprintf(buf, buf_size, "%.*s:%u", MAX_FILE_LENGTH, file, line); } return buf;}/* * int _dmalloc_chunk_read_info * * DESCRIPTION: * * Return some information associated with a pointer. * * RETURNS: * * Success - 1 pointer is okay * * Failure - 0 problem with pointer * * ARGUMENTS: * * user_pnt -> Pointer we are checking. * * where <- Where the check is being made from. * * user_size_p <- Pointer to an unsigned int which, if not NULL, will * be set to the size of bytes that the user requested. * * alloc_size_p <- Pointer to an unsigned int which, if not NULL, will * be set to the total given size of bytes including block overhead. * * file_p <- Pointer to a character pointer which, if not NULL, will * be set to the file where the pointer was allocated. * * line_p <- Pointer to a character pointer which, if not NULL, will * be set to the line-number where the pointer was allocated. * * ret_attr_p <- Pointer to a void pointer, if not NULL, will be set * to the return-address where the pointer was allocated. * * seen_cp <- Pointer to an unsigned long which, if not NULL, will be * set to the number of times the pointer has been "seen". * * used_p <- Pointer to an unsigned long which, if not NULL, will be * set to the last time the pointer was "used". * * valloc_bp <- Pointer to an integer which, if not NULL, will be set * to 1 if the pointer was allocated with valloc otherwise 0. * * fence_bp <- Pointer to an integer which, if not NULL, will be set * to 1 if the pointer has the fence bit set otherwise 0. */int _dmalloc_chunk_read_info(const void *user_pnt, const char *where, unsigned int *user_size_p, unsigned int *alloc_size_p, char **file_p, unsigned int *line_p, void **ret_attr_p, unsigned long **seen_cp, unsigned long *used_p, int *valloc_bp, int *fence_bp){ skip_alloc_t *slot_p; if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_TRANS)) { dmalloc_message("reading info about pointer '%#lx'", (unsigned long)user_pnt); } /* find the pointer with loose checking for fence */ slot_p = find_address(user_pnt, 0 /* not exact pointer */, skip_update); if (slot_p == NULL) { dmalloc_errno = ERROR_NOT_FOUND; log_error_info(NULL, 0, user_pnt, NULL, "finding address in heap", where); return 0; } /* might as well check the pointer now */ if (! check_used_slot(slot_p, user_pnt, 1 /* exact */)) { /* errno set in check_slot */ log_error_info(NULL, 0, user_pnt, slot_p, "checking pointer admin", where); return 0; } /* write info back to user space */ SET_POINTER(user_size_p, slot_p->sa_user_size); SET_POINTER(alloc_size_p, slot_p->sa_total_size); if (slot_p->sa_file == DMALLOC_DEFAULT_FILE) { SET_POINTER(file_p, NULL); } else { SET_POINTER(file_p, (char *)slot_p->sa_file); } SET_POINTER(line_p, slot_p->sa_line); /* if the line is blank then the file will be 0 or the return address */ if (slot_p->sa_line == DMALLOC_DEFAULT_LINE) { SET_POINTER(ret_attr_p, (char *)slot_p->sa_file); } else { SET_POINTER(ret_attr_p, NULL); }#if LOG_PNT_SEEN_COUNT SET_POINTER(seen_cp, &slot_p->sa_seen_c);#else SET_POINTER(seen_cp, NULL);#endif SET_POINTER(used_p, slot_p->sa_use_iter); SET_POINTER(valloc_bp, BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_VALLOC)); SET_POINTER(fence_bp, BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_FENCE)); return 1;}/******************************* heap checking *******************************//* * int _dmalloc_chunk_heap_check * * DESCRIPTION: * * Run extensive tests on the entire heap. * * RETURNS: * * Success - 1 if the heap is okay * * Failure - 0 if a problem was detected * * ARGUMENTS: * * None. */int _dmalloc_chunk_heap_check(void){ skip_alloc_t *slot_p; entry_block_t *block_p; int ret, level_c, checking_list_c = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -