📄 chunk.c
字号:
/* extern pointer information set in _dmalloc_heap_alloc */ return block_p;}/* * static int remove_slot * * DESCRIPTION: * * Remove a slot from the skip list. * * RETURNS: * * Success - 1 * * Failure - 0 * * ARGUMENTS: * * delete_p -> Pointer to the block we are deleting from the list. * * update_p -> Pointer to the skip_alloc entry we are using to hold * the update pointers. */static int remove_slot(skip_alloc_t *delete_p, skip_alloc_t *update_p){ skip_alloc_t *adjust_p; int level_c; /* update the block skip list */ for (level_c = 0; level_c <= MAX_SKIP_LEVEL; level_c++) { /* * The update node holds pointers to the slots which are pointing * to the one we want since we need to update those pointers * ahead. */ adjust_p = update_p->sa_next_p[level_c]; /* * If the pointer in question is not pointing to the deleted slot * then the deleted slot is shorter than this level and we are * done. This is guaranteed if we have a proper skip list. */ if (adjust_p->sa_next_p[level_c] != delete_p) { break; } /* * We are deleting a slot after each of the slots in the update * array. So for each level, we get the slot we are adjusting, we * set it's next pointers to the next pointers at the same level * from the deleted slot. */ adjust_p->sa_next_p[level_c] = delete_p->sa_next_p[level_c]; } /* * Sanity check here, we should always have at least 1 pointer to * the found node that we are deleting. */ if (level_c == 0) { dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("remove_slot"); return 0; } return 1;}/* * static skip_alloc_t *get_slot * * DESCRIPTION: * * Get a new slot of a certain size. This calls alloc_slot and then * does a whole bunch of things if alloc_slots generates the need for * two new slots. Jumping through hoops to get this right. * * RETURNS: * * Success - Valid skip-alloc pointer. * * Failure - NULL * * ARGUMENTS: * * None. */static skip_alloc_t *get_slot(void){ skip_alloc_t *new_p; int level_n, slot_size; void *admin_mem; /* generate the level for our new slot */ level_n = random_level(MAX_SKIP_LEVEL); slot_size = SKIP_SLOT_SIZE(level_n); /* get an extry from the free list */ new_p = entry_free_list[level_n]; if (new_p != NULL) { /* shift the linked list over */ entry_free_list[level_n] = new_p->sa_next_p[0]; /* zero our slot entry */ memset(new_p, 0, slot_size); new_p->sa_level_n = level_n; return new_p; } /* * Okay, this is a little wild. Holding on? * * So we are trying to get a slot of a certain size to store * something in a skip list. We didn't have any on the free-list so * now we will allocate a block. We allocate a block of memory to * hold the slots meaning that we may need 1 new slot to account for * the admin and external memory in addition to the 1 requested. * * To do it right, would take a recursive call to get_slot which I * am not willing to do so we will have 2 blocks in a row which have * the same height. This is less than efficient but oh well. */ /* add in all of the unused slots to the linked list */ admin_mem = alloc_slots(level_n); if (admin_mem == NULL) { /* error code set in alloc_slots */ return NULL; } /* get one for the admin memory */ new_p = entry_free_list[level_n]; if (new_p == NULL) { /* * HUH? This isn't right. We should have created a whole bunch * of addresses */ dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("get_slot"); return NULL; } entry_free_list[level_n] = new_p->sa_next_p[0]; memset(new_p, 0, slot_size); new_p->sa_flags = ALLOC_FLAG_ADMIN; new_p->sa_mem = admin_mem; new_p->sa_total_size = BLOCK_SIZE; new_p->sa_level_n = level_n; /* now put it in the used list */ if (! insert_slot(new_p, 0 /* used list */)) { /* error reported above */ return NULL; } /* now get one for the user */ new_p = entry_free_list[level_n]; if (new_p == NULL) { /* * HUH? This isn't right. We should have created a whole bunch * of addresses */ dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("get_slot"); return NULL; } entry_free_list[level_n] = new_p->sa_next_p[0]; memset(new_p, 0, slot_size); new_p->sa_level_n = level_n; /* level_np set up top */ return new_p;}/* * static skip_alloc_t *insert_address * * DESCRIPTION: * * Insert an address entry into a skip list. * * RETURNS: * * Success - Valid slot pointer. * * Failure - NULL * * ARGUMENTS: * * address -> Address we are inserting into the address list. * * free_b -> Insert a free address in the free-size list otherwise it * will go into the used address list. * * tot_size -> Total size of the chunk that we are inserting into the * list. */static skip_alloc_t *insert_address(void *address, const int free_b, const unsigned int tot_size){ skip_alloc_t *new_p; /* get a new entry */ new_p = get_slot(); if (new_p == NULL) { /* error code set in get_slot */ return NULL; } if (free_b) { new_p->sa_flags = ALLOC_FLAG_FREE; } else { new_p->sa_flags = ALLOC_FLAG_USER; } new_p->sa_mem = address; new_p->sa_total_size = tot_size; /* now try and insert the slot into the skip-list */ if (! insert_slot(new_p, free_b)) { /* error code set in insert_slot */ return NULL; } return new_p;}/******************************* misc routines *******************************//* * static int expand_chars * * DESCRIPTION: * * Copies a buffer into a output buffer while translates * non-printables into %03o octal values. If it can, it will also * translate certain \ characters (\r, \n, etc.) into \\%c. The * routine is useful for printing out binary values. * * Note: It does _not_ add a \0 at the end of the output buffer. * * RETURNS: * * Returns the number of characters added to the output buffer. * * ARGUMENTS: * * buf - the buffer to convert. * * buf_size - size of the buffer. If < 0 then it will expand till it * sees a \0 character. * * out - destination buffer for the convertion. * * out_size - size of the output buffer. */static int expand_chars(const void *buf, const int buf_size, char *out, const int out_size){ int buf_c; const unsigned char *buf_p, *spec_p; char *out_p = out, *bounds_p; /* setup our max pointer */ bounds_p = out + out_size; /* run through the input buffer, counting the characters as we go */ for (buf_c = 0, buf_p = (const unsigned char *)buf;; buf_c++, buf_p++) { /* did we reach the end of the buffer? */ if (buf_size < 0) { if (*buf_p == '\0') { break; } } else { if (buf_c >= buf_size) { break; } } /* search for special characters */ for (spec_p = (unsigned char *)SPECIAL_CHARS + 1; *(spec_p - 1) != '\0'; spec_p += 2) { if (*spec_p == *buf_p) { break; } } /* did we find one? */ if (*(spec_p - 1) != '\0') { if (out_p + 2 >= bounds_p) { break; } out_p += loc_snprintf(out_p, bounds_p - out_p, "\\%c", *(spec_p - 1)); continue; } /* print out any 7-bit printable characters */ if (*buf_p < 128 && isprint(*buf_p)) { if (out_p + 1 >= bounds_p) { break; } *out_p = *(char *)buf_p; out_p += 1; } else { if (out_p + 4 >= bounds_p) { break; } out_p += loc_snprintf(out_p, bounds_p - out_p, "\\%03o", *buf_p); } } /* try to punch the null if we have space in case the %.*s doesn't work */ if (out_p < bounds_p) { *out_p = '\0'; } return out_p - out;}/* * static void get_pnt_info * * DESCRIPTION: * * With a slot, set a number of pointers to places within the block. * * RETURNS: * * None. * * ARGUMENTS: * * slot_p -> Pointer to a slot structure that we are getting info on. * * info_p <-> Pointer to an info structure that we are filling with * information. */static void get_pnt_info(const skip_alloc_t *slot_p, pnt_info_t *info_p){ info_p->pi_fence_b = BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_FENCE); info_p->pi_valloc_b = BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_VALLOC); info_p->pi_blanked_b = BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_BLANK); info_p->pi_alloc_start = slot_p->sa_mem; if (info_p->pi_fence_b) { if (info_p->pi_valloc_b) { info_p->pi_user_start = (char *)info_p->pi_alloc_start + BLOCK_SIZE; info_p->pi_fence_bottom = (char *)info_p->pi_user_start - FENCE_BOTTOM_SIZE; } else { info_p->pi_fence_bottom = info_p->pi_alloc_start; info_p->pi_user_start = (char *)info_p->pi_alloc_start + FENCE_BOTTOM_SIZE; } } else { info_p->pi_fence_bottom = NULL; info_p->pi_user_start = info_p->pi_alloc_start; } info_p->pi_user_bounds = (char *)info_p->pi_user_start + slot_p->sa_user_size; info_p->pi_alloc_bounds = (char *)slot_p->sa_mem + slot_p->sa_total_size; if (info_p->pi_fence_b) { info_p->pi_fence_top = info_p->pi_user_bounds; info_p->pi_upper_bounds = (char *)info_p->pi_alloc_bounds - FENCE_TOP_SIZE; } else { info_p->pi_fence_top = NULL; info_p->pi_upper_bounds = info_p->pi_alloc_bounds; }}/* * static char *display_pnt * * DESCRIPTION: * * Write into a buffer a discription of a pointer. * * RETURNS: * * Pointer to buffer 1st argument. * * ARGUMENTS: * * user_pnt -> Pointer that we are displaying. * * alloc_p -> Pointer to the skip slot which we are displaying. * * buf <-> Passed in buffer which will be filled with a description of * the pointer. * * buf_size -> Size of the buffer in bytes. */static char *display_pnt(const void *user_pnt, const skip_alloc_t *alloc_p, char *buf, const int buf_size){ char *buf_p, *bounds_p; int elapsed_b; buf_p = buf; bounds_p = buf_p + buf_size; buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%#lx", (unsigned long)user_pnt); #if LOG_PNT_SEEN_COUNT buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "|s%lu", alloc_p->sa_seen_c);#endif #if LOG_PNT_ITERATION buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "|i%lu", alloc_p->sa_iteration);#endif if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_ELAPSED_TIME)) { elapsed_b = 1; } else { elapsed_b = 0; } if (elapsed_b || BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_CURRENT_TIME)) {#if LOG_PNT_TIMEVAL { char time_buf[64]; buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "|w%s", _dmalloc_ptimeval(&alloc_p->sa_timeval, time_buf, sizeof(time_buf), elapsed_b)); }#else#if LOG_PNT_TIME { char time_buf[64]; buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "|w%s", _dmalloc_ptime(&alloc_p->sa_time, time_buf, sizeof(time_buf), elapsed_b)); }#endif#endif } #if LOG_PNT_THREAD_ID { char thread_id[256]; buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "|t"); THREAD_ID_TO_STRING(thread_id, sizeof(thread_id), alloc_p->sa_thread_id); buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s", thread_id); }#endif return buf;}/* * static void log_error_info * * DESCRIPTION: * * Logging information about a pointer, usually during an error * condition. * * RETURNS: * * None. * * ARGUMENTS: * * now_file -> File from where we generated the error. * * now_line -> Line number from where we generated the error. * * user_pnt -> Pointer in question. This can be 0L then it will use * the slot_p memory pointer. * * slot_p -> Pointer to the slot associated with the user_pnt or 0L. * * reason -> Reason string why something happened. * * where -> What routine is calling log_error_info. For instance * malloc or chunk_check. */static void log_error_info(const char *now_file, const unsigned int now_line, const void *user_pnt, const skip_alloc_t *slot_p, const char *reason, const char *where){ static int dump_bottom_b = 0, dump_top_b = 0; char out[(DUMP_SPACE + FENCE_BOTTOM_SIZE + FENCE_TOP_SIZE) * 4]; char where_buf[MAX_FILE_LENGTH + 64]; char where_buf2[MAX_FILE_LENGTH + 64]; const char *prev_file; const void *dump_pnt = user_pnt; const void *start_user; unsigned int prev_line, user_size;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -