static void create_mem_region (CORE_ADDR lo, CORE_ADDR hi, const struct mem_attrib *attrib) { struct mem_region newobj; int i, ix; /* lo == hi is a useless empty region. */ if (lo >= hi && hi != 0) { printf_unfiltered (_("invalid memory region: low >= high\n")); return; } mem_region_init (&newobj); newobj.lo = lo; newobj.hi = hi; ix = VEC_lower_bound (mem_region_s, mem_region_list, &newobj, mem_region_lessthan); /* Check for an overlapping memory region. We only need to check in the vicinity - at most one before and one after the insertion point. */ for (i = ix - 1; i < ix + 1; i++) { struct mem_region *n; if (i < 0) continue; if (i >= VEC_length (mem_region_s, mem_region_list)) continue; n = VEC_index (mem_region_s, mem_region_list, i); if ((lo >= n->lo && (lo < n->hi || n->hi == 0)) || (hi > n->lo && (hi <= n->hi || n->hi == 0)) || (lo <= n->lo && ((hi >= n->hi && n->hi != 0) || hi == 0))) { printf_unfiltered (_("overlapping memory region\n")); return; } } newobj.number = ++mem_number; newobj.attrib = *attrib; VEC_safe_insert (mem_region_s, mem_region_list, ix, &newobj); }
int main(void) { const struct dt_property *names, *ranges; struct mem_region *r; unsigned int i, l, c; uint64_t *rangep; const char *name; void *buf; /* Use malloc for the heap, so valgrind can find issues. */ skiboot_heap.start = (long)real_malloc(TEST_HEAP_SIZE); skiboot_heap.len = TEST_HEAP_SIZE; skiboot_os_reserve.len = skiboot_heap.start; dt_root = dt_new_root(""); dt_add_property_cells(dt_root, "#address-cells", 2); dt_add_property_cells(dt_root, "#size-cells", 2); buf = real_malloc(1024*1024); add_mem_node((unsigned long)buf, 1024*1024); /* Now convert. */ mem_region_init(); /* create our reservations */ for (i = 0; i < ARRAY_SIZE(test_regions); i++) mem_reserve(test_regions[i].name, test_regions[i].addr, 0x1000); /* release unused */ mem_region_release_unused(); /* and create reservations */ mem_region_add_dt_reserved(); /* ensure we can't create further reservations */ r = new_region("test.4", 0x5000, 0x1000, NULL, REGION_RESERVED); assert(!add_region(r)); /* check dt properties */ names = dt_find_property(dt_root, "reserved-names"); ranges = dt_find_property(dt_root, "reserved-ranges"); assert(names && ranges); /* walk through names & ranges properies, ensuring that the test * regions are all present */ for (name = names->prop, rangep = (uint64_t *)ranges->prop, c = 0; name < names->prop + names->len; name += l, rangep += 2) { uint64_t addr; addr = dt_get_number(rangep, 2); l = strlen(name) + 1; for (i = 0; i < ARRAY_SIZE(test_regions); i++) { if (strcmp(test_regions[i].name, name)) continue; assert(test_regions[i].addr == addr); assert(!test_regions[i].found); test_regions[i].found = true; c++; } } assert(c == ARRAY_SIZE(test_regions)); dt_free(dt_root); real_free(buf); real_free((void *)(long)skiboot_heap.start); return 0; }
struct mem_map *create_maps(int pid) { FILE *f; char *buf = NULL, *str = NULL; size_t total_read, capacity; size_t addr_start, addr_end, offset, len; char r, w, x, p; int dev_major, dev_minor, inode; char path[PATH_MAX]; struct mem_map *map = NULL; struct mem_region *region; capacity = 0x100000; buf = calloc(1, capacity); sprintf(buf, "/proc/%d/maps", pid); if ((f = fopen(buf, "r")) == NULL) { fprintf(stderr, "cannot open %s: %s\n", buf, strerror(errno)); return NULL; } map = malloc(sizeof(struct mem_map)); mem_map_init(map); memset(buf, 0, capacity); total_read = 0; while (!feof(f)) { fread(&buf[total_read], capacity - total_read - 1, 1, f); if (errno) { perror("maps"); mem_map_destroy(map); map = NULL; goto create_maps_end; } total_read = strlen(buf); if ((total_read + 1) == capacity) { capacity *= 2; buf = realloc(buf, capacity); memset(&buf[total_read], 0, capacity - total_read); } else { buf[total_read] = '\0'; } } str = &buf[0]; while (*str) { int scan; char *next; next = strchr(str, '\n'); if (next != NULL) *next = '\0'; scan = sscanf(str, "%zx-%zx %c%c%c%c %zx %x:%x %d %[^\t\n]", &addr_start, &addr_end, &r, &w, &x, &p, &offset, &dev_major, &dev_minor, &inode, path); if (scan < 10) { fprintf(stderr, "warning: unable to parse maps " "entry '%s' (read %d)\n", str, scan); break; } region = malloc(sizeof(struct mem_region)); mem_region_init(region); region->start = (void *)addr_start; region->length = addr_end - addr_start; region->offset = offset; if (scan > 10 && path[0] != '\0') { if (!strcmp(path, "[vdso]")) { region->type = MEM_REGION_TYPE_VDSO; } else if (!strcmp(path, "[vsyscall]")) { region->type = MEM_REGION_TYPE_VSYSCALL; } else if ((len = strlen(path)) > 10 && !strcmp(path + len - 10, " (deleted)")) { *(path + len - 10) = '\0'; region->path = strdup(path); region->type = MEM_REGION_TYPE_DELETED; } else { region->path = strdup(path); region->type = MEM_REGION_TYPE_MMAP; } } if (mem_map_add_region(map, region) != 0) { mem_map_destroy(map); map = NULL; break; } if (next != NULL) str = next + 1; } if (map != NULL) mem_map_create_region_index(map); create_maps_end: fclose(f); free(buf); return map; }