userland can ask for an array of a processes memory mappings via sysctl, starting from a specified point. currently that starting point is found by iterating over the mappings from start to finish, but because the mappings are in an RBT we can do a binary search instead.
ok? Index: uvm_map.c =================================================================== RCS file: /cvs/src/sys/uvm/uvm_map.c,v retrieving revision 1.231 diff -u -p -r1.231 uvm_map.c --- uvm_map.c 17 May 2017 08:13:33 -0000 1.231 +++ uvm_map.c 20 Jun 2017 00:35:50 -0000 @@ -5211,7 +5211,7 @@ int uvm_map_fill_vmmap(struct vm_map *map, struct kinfo_vmentry *kve, size_t *lenp) { - struct vm_map_entry *entry; + struct vm_map_entry *entry = NULL, *tmp; vaddr_t start; int cnt, maxcnt, error = 0; @@ -5229,13 +5229,21 @@ uvm_map_fill_vmmap(struct vm_map *map, s start = (vaddr_t)kve[0].kve_start; vm_map_lock(map); - RBT_FOREACH(entry, uvm_map_addr, &map->addr) { - if (cnt == maxcnt) { - error = ENOMEM; + /* look for the starting address by doing nfind (by hand) */ + tmp = RBT_ROOT(uvm_map_addr, &map->addr); + while (tmp != NULL) { + if (start < tmp->start) { + entry = tmp; + tmp = RBT_LEFT(uvm_map_addr, tmp); + } else if (start > tmp->start) { + tmp = RBT_RIGHT(uvm_map_addr, tmp); + } else { /* exact match */ + entry = tmp; break; } - if (start != 0 && entry->start < start) - continue; + } + + while (entry != NULL) { kve->kve_start = entry->start; kve->kve_end = entry->end; kve->kve_guard = entry->guard; @@ -5249,8 +5257,14 @@ uvm_map_fill_vmmap(struct vm_map *map, s kve->kve_advice = entry->advice; kve->kve_inheritance = entry->inheritance; kve->kve_flags = entry->flags; + + if (++cnt == maxcnt) { + error = ENOMEM; + break; + } + kve++; - cnt++; + entry = RBT_NEXT(uvm_map_addr, entry); } vm_map_unlock(map);