+struct bm_helper {
+ void *buf;
+ size_t buflen;
+ size_t sofar;
+};
+
+static void get_needed_sz_cb(struct vm_region *vmr, void *arg)
+{
+ struct bm_helper *bmh = (struct bm_helper*)arg;
+
+ /* ballpark estimate of a line */
+ bmh->buflen += 150;
+}
+
+static void build_maps_cb(struct vm_region *vmr, void *arg)
+{
+ struct bm_helper *bmh = (struct bm_helper*)arg;
+ size_t old_sofar;
+ char path_buf[MAX_FILENAME_SZ];
+ char *path;
+ unsigned long inode_nr;
+
+ if (vmr->vm_file) {
+ path = file_abs_path(vmr->vm_file, path_buf, sizeof(path_buf));
+ inode_nr = vmr->vm_file->f_dentry->d_inode->i_ino;
+ } else {
+ strlcpy(path_buf, "[heap]", sizeof(path_buf));
+ path = path_buf;
+ inode_nr = 0;
+ }
+
+ old_sofar = bmh->sofar;
+ bmh->sofar += snprintf(bmh->buf + bmh->sofar, bmh->buflen - bmh->sofar,
+ "%08lx-%08lx %c%c%c%c %08x %02d:%02d %d ",
+ vmr->vm_base, vmr->vm_end,
+ vmr->vm_prot & PROT_READ ? 'r' : '-',
+ vmr->vm_prot & PROT_WRITE ? 'w' : '-',
+ vmr->vm_prot & PROT_EXEC ? 'x' : '-',
+ vmr->vm_flags & MAP_PRIVATE ? 'p' : '-',
+ vmr->vm_file ? vmr->vm_foff : 0,
+ vmr->vm_file ? 1 : 0, /* VFS == 1 for major */
+ 0,
+ inode_nr);
+ /* Align the filename to the 74th char, like Linux (73 chars so far) */
+ bmh->sofar += snprintf(bmh->buf + bmh->sofar, bmh->buflen - bmh->sofar,
+ "%*s", 73 - (bmh->sofar - old_sofar), "");
+ bmh->sofar += snprintf(bmh->buf + bmh->sofar, bmh->buflen - bmh->sofar,
+ "%s\n", path);
+}
+
+static struct sized_alloc *build_maps(struct proc *p)
+{
+ struct bm_helper bmh[1];
+ struct sized_alloc *sza;
+
+ /* Try to figure out the size needed: start with extra space, then add a bit
+ * for each VMR */
+ bmh->buflen = 150;
+ enumerate_vmrs(p, get_needed_sz_cb, bmh);
+ sza = sized_kzmalloc(bmh->buflen, MEM_WAIT);
+ bmh->buf = sza->buf;
+ bmh->sofar = 0;
+ enumerate_vmrs(p, build_maps_cb, bmh);
+ return sza;
+}
+