fix (heap): fixed bug that caused invalid addresses as result of memory allocations
This commit is contained in:
parent
9a35aa6648
commit
abf22ba917
|
@ -5,6 +5,7 @@
|
|||
#include "mm/page_frame.h"
|
||||
#include "utils/math.h"
|
||||
#include "utils/logger.h"
|
||||
#include "utils/memory.h"
|
||||
|
||||
void heap_segment_init(heap_segment_T* segment, heap_segment_T* next, heap_segment_T* prev, uint64_t size) {
|
||||
segment->magic = HEAP_SEGMENT_MAGIC;
|
||||
|
@ -18,7 +19,7 @@ bool heap_segment_validate(heap_segment_T* segment) {
|
|||
return segment->magic == HEAP_SEGMENT_MAGIC;
|
||||
}
|
||||
|
||||
bool heap_segment_combine_prev(heap_segment_T* segment) {
|
||||
bool heap_segment_combine_prev(heap_T* heap, heap_segment_T* segment) {
|
||||
if (segment->prev == NULL) { return false; }
|
||||
if (!segment->free || !segment->prev->free) { return false; }
|
||||
|
||||
|
@ -28,6 +29,10 @@ bool heap_segment_combine_prev(heap_segment_T* segment) {
|
|||
segment->next->prev = segment->prev;
|
||||
}
|
||||
|
||||
if (segment == heap->last_segment) {
|
||||
heap->last_segment = segment->prev;
|
||||
}
|
||||
|
||||
// fuse with previous segment
|
||||
segment->prev->size += sizeof(heap_segment_T) + segment->size;
|
||||
|
||||
|
@ -36,10 +41,10 @@ bool heap_segment_combine_prev(heap_segment_T* segment) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool heap_segment_combine_next(heap_segment_T* segment) {
|
||||
bool heap_segment_combine_next(heap_T* heap, heap_segment_T* segment) {
|
||||
if (segment->next == NULL) { return false; }
|
||||
|
||||
return heap_segment_combine_prev(segment->next);
|
||||
return heap_segment_combine_prev(heap, segment->next);
|
||||
}
|
||||
|
||||
bool heap_segment_shrink(heap_T* heap, heap_segment_T* segment, uint64_t size) {
|
||||
|
@ -59,7 +64,7 @@ bool heap_segment_shrink(heap_T* heap, heap_segment_T* segment, uint64_t size) {
|
|||
new_segment->prev = segment;
|
||||
|
||||
// try to combine the new segment with the segment that comes after it
|
||||
heap_segment_combine_next(new_segment);
|
||||
heap_segment_combine_next(heap, new_segment);
|
||||
|
||||
if (segment == heap->last_segment) {
|
||||
heap->last_segment = new_segment;
|
||||
|
@ -98,7 +103,7 @@ heap_segment_T* heap_append_segment(heap_T* heap, uint64_t minimum_size) {
|
|||
heap_segment_init(segment, NULL, heap->last_segment, size - sizeof(heap_segment_T));
|
||||
heap->last_segment->next = segment;
|
||||
|
||||
if (heap_segment_combine_prev(segment)) {
|
||||
if (heap_segment_combine_prev(heap, segment)) {
|
||||
segment = heap->last_segment;
|
||||
} else {
|
||||
heap->last_segment = segment;
|
||||
|
@ -116,7 +121,8 @@ void* heap_memory_allocate(heap_T* heap, uint64_t size) {
|
|||
heap_segment_T* segment = heap->start;
|
||||
while (segment != NULL) {
|
||||
if (!heap_segment_validate(segment)) {
|
||||
log(LOG_ERROR, "Heap Segment Invalid! while trying to allocate memory");
|
||||
log(LOG_ERROR, "Heap Segment (0x%x) Invalid! while trying to allocate memory", segment);
|
||||
heap_dump_segments(heap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -130,7 +136,7 @@ void* heap_memory_allocate(heap_T* heap, uint64_t size) {
|
|||
}
|
||||
|
||||
segment->free = false;
|
||||
return (heap_segment_T*)((uint64_t)segment + sizeof(heap_segment_T));
|
||||
return (void*)((uint64_t)segment + sizeof(heap_segment_T));
|
||||
}
|
||||
|
||||
segment = heap_append_segment(heap, size);
|
||||
|
@ -139,39 +145,51 @@ void* heap_memory_allocate(heap_T* heap, uint64_t size) {
|
|||
}
|
||||
segment->free = false;
|
||||
|
||||
return (heap_segment_T*)((uint64_t)segment + sizeof(heap_segment_T));
|
||||
return (void*)((uint64_t)segment + sizeof(heap_segment_T));
|
||||
}
|
||||
|
||||
void heap_dump_segments(heap_T* heap) {
|
||||
log(LOG_DEBUG, "<=====[ Dumping Heap Segments ]=====>");
|
||||
|
||||
log(LOG_NONE, " |-------------------------|");
|
||||
log(LOG_NONE, " | START |");
|
||||
log(LOG_NONE, " | 0x%x |", heap->start);
|
||||
log(LOG_NONE, " |------------v------------|");
|
||||
log(LOG_NONE, " |--------------------------|");
|
||||
log(LOG_NONE, " | START |");
|
||||
log(LOG_NONE, " | 0x%x |", heap->start);
|
||||
log(LOG_NONE, " |-------------v------------|");
|
||||
|
||||
heap_segment_T* segment = heap->start;
|
||||
while (segment != NULL) {
|
||||
log(LOG_NONE, " |");
|
||||
log(LOG_NONE, " |");
|
||||
log(LOG_NONE, " |------------^------------|");
|
||||
log(LOG_NONE, " | Header (size: 0x%xw) |", sizeof(heap_segment_T));
|
||||
log(LOG_NONE, " |-------------------------|");
|
||||
log(LOG_NONE, " | 0x%x |", (uint64_t)segment);
|
||||
log(LOG_NONE, " | Valid: %? |", heap_segment_validate(segment));
|
||||
log(LOG_NONE, " | Free: %? |", segment->free);
|
||||
log(LOG_NONE, " | Size: 0x%xd |", segment->size);
|
||||
log(LOG_NONE, " |------------v------------|");
|
||||
if (segment->magic != HEAP_SEGMENT_MAGIC) {
|
||||
log(LOG_NONE, " |");
|
||||
log(LOG_NONE, " |");
|
||||
log(LOG_NONE, " !~~~~~~~~~~~~~^~~~~~~~~~~~~!");
|
||||
log(LOG_NONE, " ! !!! Heap corrupted !!! !");
|
||||
log(LOG_NONE, " !~~~~~~~~~~~~~~~~~~~~~~~~~~!");
|
||||
memory_hexdump(segment, sizeof(heap_segment_T));
|
||||
return;
|
||||
}
|
||||
|
||||
log(LOG_NONE, " |");
|
||||
log(LOG_NONE, " |");
|
||||
log(LOG_NONE, " |-------------^------------|");
|
||||
log(LOG_NONE, " | Header (size: 0x%xw) |", sizeof(heap_segment_T));
|
||||
log(LOG_NONE, " |--------------------------|");
|
||||
log(LOG_NONE, " | 0x%x |", (uint64_t)segment);
|
||||
log(LOG_NONE, " | Valid: %? |", heap_segment_validate(segment));
|
||||
log(LOG_NONE, " | Free: %? |", segment->free);
|
||||
log(LOG_NONE, " | Size: 0x%xd |", segment->size);
|
||||
log(LOG_NONE, " | Prev: 0x%x |", (uint64_t)segment->prev);
|
||||
log(LOG_NONE, " | Next: 0x%x |", (uint64_t)segment->next);
|
||||
log(LOG_NONE, " |-------------v------------|");
|
||||
|
||||
segment = segment->next;
|
||||
}
|
||||
|
||||
log(LOG_NONE, " |");
|
||||
log(LOG_NONE, " |");
|
||||
log(LOG_NONE, " |------------^------------|");
|
||||
log(LOG_NONE, " | END |");
|
||||
log(LOG_NONE, " | 0x%x |", heap->end);
|
||||
log(LOG_NONE, " |-------------------------|");
|
||||
log(LOG_NONE, " |");
|
||||
log(LOG_NONE, " |");
|
||||
log(LOG_NONE, " |-------------^------------|");
|
||||
log(LOG_NONE, " | END |");
|
||||
log(LOG_NONE, " | 0x%x |", heap->end);
|
||||
log(LOG_NONE, " |--------------------------|");
|
||||
}
|
||||
|
||||
void heap_memory_free(heap_T* heap, void* address) {
|
||||
|
@ -185,8 +203,8 @@ void heap_memory_free(heap_T* heap, void* address) {
|
|||
segment->free = true;
|
||||
|
||||
// try to combine in both directions, so we don't splitter the heap in a ton of small segments
|
||||
heap_segment_combine_prev(segment);
|
||||
heap_segment_combine_next(segment);
|
||||
heap_segment_combine_prev(heap, segment);
|
||||
heap_segment_combine_next(heap, segment);
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue