/**
 * 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;
}
Exemple #2
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;
}
Exemple #4
0
/*
 * 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;
}
Exemple #5
0
int sub_gid_remove (const char *owner, gid_t start, unsigned long count)
{
	return remove_range (&subordinate_gid_db, owner, start, count);
}
Exemple #6
0
/*
 * 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);
}