/** * Verifies and corrects any overlapping ranges. * The ranges array is assumed to be sorted already. * * @param[out] range pointer that will be set to an array that holds the * memory ranges * @param[out] ranges number of ranges valid in @p range * * @return 0 on success, any other value on failure. */ static int fixup_memory_ranges(struct memory_range **range, int *ranges) { int i; int j; int change_made; int nr_ranges = *ranges; struct memory_range *rp = *range; again: change_made = 0; for (i = 0; i < (nr_ranges-1); i++) { j = i+1; if (rp[i].start > rp[j].start) { fprintf(stderr, "memory out of order!!\n"); return 1; } if (rp[i].type != rp[j].type) continue; if (rp[i].start == rp[j].start) { if (rp[i].end >= rp[j].end) { remove_range(rp, nr_ranges, j); nr_ranges--; change_made++; } else { remove_range(rp, nr_ranges, i); nr_ranges--; change_made++; } } else { if (rp[i].end > rp[j].start) { if (rp[i].end < rp[j].end) { rp[j].start = rp[i].end; change_made++; } else if (rp[i].end >= rp[j].end) { remove_range(rp, nr_ranges, j); nr_ranges--; change_made++; } } } } /* fixing/removing an entry may make it wrong relative to the next */ if (change_made) goto again; *ranges = nr_ranges; return 0; }
static int free_memory() { if ((mboot.flags & MBOOT_MMAP) == 0) panic("Bootloader did not provide memory map info!"); range_t ranges[32], ranges_cpy[32]; uint32_t i = mboot.mmap_addr; unsigned n = 0; uint64_t extent = 0; while (i < mboot.mmap_addr+mboot.mmap_length) { if (n >= 128) break; multiboot_mmap_entry_t *entry = (multiboot_mmap_entry_t*)i; if (MBOOT_IS_MMAP_TYPE_RAM(entry->type)) { ranges[n].start = entry->base_addr; ranges[n++].extent = entry->length; if (entry->base_addr + entry->length > extent) extent = entry->base_addr + entry->length; } //kprintf("e: sz %x addr %x len %x ty %x\n", entry->size, (uint32_t)entry->base_addr, (uint32_t)entry->length, entry->type); i += entry->size + 4; } extern int __start, __end; uintptr_t end = (((uintptr_t)&__end) & ~get_page_mask()) + get_page_size(); for (i = 0; i < n; ++i) remove_range(&ranges[i], (uintptr_t)&__start, end); for (i = 0; i < n; ++i) { //kprintf("r: %x ext %x\n", (uint32_t)ranges[i].start, (uint32_t)ranges[i].extent); } /* Copy the ranges to a backup, as init_physical_memory mutates them and init_cow_refcnts needs to run after init_physical_memory */ for (i = 0; i < n; ++i) ranges_cpy[i] = ranges[i]; init_physical_memory_early(ranges, n, extent); init_virtual_memory(ranges, n); init_physical_memory(); init_cow_refcnts(ranges, n); return 0; }
static int match_strnlen(struct expression *call, void *unused, struct range_list **rl) { struct expression *limit; sval_t fixed; sval_t bound; sval_t ulong_max = sval_type_val(&ulong_ctype, ULONG_MAX); match_strlen(call, NULL, rl); limit = get_argument_from_call_expr(call->args, 1); if (!get_implied_max(limit, &bound)) return 1; if (sval_cmp(bound, ulong_max) == 0) return 1; if (rl_to_sval(*rl, &fixed) && sval_cmp(fixed, bound) >= 0) { *rl = alloc_rl(bound, bound); return 1; } bound.value++; *rl = remove_range(*rl, bound, ulong_max); return 1; }
/* * eval_mm_valid - Check the mm malloc package for correctness */ static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges) { int i, j; int index; int size; int oldsize; char *newp; char *oldp; char *p; /* Reset the heap and free any records in the range list */ mem_reset_brk(); clear_ranges(ranges); /* Call the mm package's init function */ if (mm_init() < 0) { malloc_error(tracenum, 0, "mm_init failed."); return 0; } /* Interpret each operation in the trace in order */ for (i = 0; i < trace->num_ops; i++) { index = trace->ops[i].index; size = trace->ops[i].size; switch (trace->ops[i].type) { case ALLOC: /* mm_malloc */ /* Call the student's malloc */ if ((p = mm_malloc(size)) == NULL) { malloc_error(tracenum, i, "mm_malloc failed."); return 0; } /* * Test the range of the new block for correctness and add it * to the range list if OK. The block must be be aligned properly, * and must not overlap any currently allocated block. */ if (add_range(ranges, p, size, tracenum, i) == 0) return 0; /* ADDED: cgw * fill range with low byte of index. This will be used later * if we realloc the block and wish to make sure that the old * data was copied to the new block */ memset(p, index & 0xFF, size); /* Remember region */ trace->blocks[index] = p; trace->block_sizes[index] = size; break; case REALLOC: /* mm_realloc */ /* Call the student's realloc */ oldp = trace->blocks[index]; if ((newp = mm_realloc(oldp, size)) == NULL) { malloc_error(tracenum, i, "mm_realloc failed."); return 0; } /* Remove the old region from the range list */ remove_range(ranges, oldp); /* Check new block for correctness and add it to range list */ if (add_range(ranges, newp, size, tracenum, i) == 0) return 0; /* ADDED: cgw * Make sure that the new block contains the data from the old * block and then fill in the new block with the low order byte * of the new index */ oldsize = trace->block_sizes[index]; if (size < oldsize) oldsize = size; for (j = 0; j < oldsize; j++) { if (newp[j] != (index & 0xFF)) { malloc_error(tracenum, i, "mm_realloc did not preserve the " "data from old block"); return 0; } } memset(newp, index & 0xFF, size); /* Remember region */ trace->blocks[index] = newp; trace->block_sizes[index] = size; break; case FREE: /* mm_free */ /* Remove region from list and call student's free function */ p = trace->blocks[index]; remove_range(ranges, p); mm_free(p); break; default: app_error("Nonexistent request type in eval_mm_valid"); } } /* As far as we know, this is a valid malloc package */ return 1; }
int sub_gid_remove (const char *owner, gid_t start, unsigned long count) { return remove_range (&subordinate_gid_db, owner, start, count); }
/* * mm_free - Coalesce with surrounding blocks, and put it to Red-black tree */ void mm_free(void *ptr) { size_t size, new_size; void *prev, *cur, *next, *new_block; cur = ptr - HEADER_SIZE; /* double free */ if(CUR_FREE(cur)){ printf("try to free a freed memory block(%p) is detected.\n", cur); return ; } new_block = cur; new_size = CUR_SIZE_MASKED(cur); /* coalesce with the previous block if free */ if(PREV_FREE(cur)){ size = PREV_SIZE_MASKED(cur); prev = PREV_BLOCK(cur, size); if(IS_IN_RB(prev)){ rb_delete(prev); } new_block = prev; new_size += size; } /* coalesce with the next block if exists and free */ size = CUR_SIZE_MASKED(cur); next = NEXT_BLOCK(cur, size); if(next + 4 <= mem_heap_hi() && CUR_FREE(next)){ size = CUR_SIZE_MASKED(next); if(IS_IN_RB(next)){ rb_delete(next); } new_size += size; } /* new free block setting */ CUR_SIZE(new_block) = PREV_SIZE(NEXT_BLOCK(new_block, new_size)) = new_size | 1; if(IS_IN_RB(new_block)){ rb_insert(new_block); } #ifdef DEBUG printf("mm_free(%p) called\n", ptr); printf("new_block = %p\n", new_block); rb_print_preorder(); printf("\n"); #endif /* DEBUG */ #ifdef CHECK if(!mm_check()){ rb_print_preorder(); exit(0); } #endif /* CHECK */ /* DON't MODIFY THIS STAGE AND LEAVE IT AS IT WAS */ if (gl_ranges) remove_range(gl_ranges, ptr); }