1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
From 5c1494757f27f3ec4feb6b9d85d91d8368ee9d25 Mon Sep 17 00:00:00 2001
From: Justus Winter <4winter@informatik.uni-hamburg.de>
Date: Thu, 18 Sep 2014 18:38:04 +0200
Subject: [PATCH] procfs: implement /proc/N/maps
* procfs/process.c (process_file_gc_maps): New function.
(entries): Use the new function to implement /proc/N/maps.
---
procfs/process.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)
diff --git a/procfs/process.c b/procfs/process.c
index 4854148..feb68ff 100644
--- a/procfs/process.c
+++ b/procfs/process.c
@@ -109,6 +109,93 @@ process_file_gc_environ (struct proc_stat *ps, char **contents)
}
static ssize_t
+process_file_gc_maps (struct proc_stat *ps, char **contents)
+{
+ error_t err;
+ FILE *s;
+ size_t contents_len;
+ vm_offset_t addr = 0;
+ vm_size_t size;
+ vm_prot_t prot, max_prot;
+ mach_port_t obj;
+ vm_offset_t offs;
+ vm_inherit_t inh;
+ int shared;
+
+ /* Unfortunately we cannot resolve memory objects to their backing
+ file (yet), so we use the port name as identifier. To avoid the
+ same name from being used again and again, we defer the
+ deallocation until the end of the function. We use a simple
+ linked list for this purpose. */
+ struct mem_obj
+ {
+ mach_port_t port;
+ struct mem_obj *next;
+ };
+ struct mem_obj *objects = NULL;
+
+ s = open_memstream (contents, &contents_len);
+
+ while (1)
+ {
+ err =
+ vm_region (ps->task, &addr, &size, &prot, &max_prot, &inh,
+ &shared, &obj, &offs);
+ if (err)
+ break;
+
+ fprintf (s, "%0*x-%0*x %c%c%c%c %0*x %s %d ",
+ /* Address range. */
+ 2*sizeof s, addr,
+ 2*sizeof s, addr + size,
+ /* Permissions. */
+ prot & VM_PROT_READ? 'r': '-',
+ prot & VM_PROT_WRITE? 'w': '-',
+ prot & VM_PROT_EXECUTE? 'x': '-',
+ shared? 's': 'p',
+ /* Offset. */
+ 2*sizeof s, offs,
+ /* Device. */
+ "00:00",
+ /* Inode. */
+ 0);
+
+ /* Pathname. */
+ if (MACH_PORT_VALID (obj))
+ {
+ struct mem_obj *o = malloc (sizeof *o);
+ if (o)
+ {
+ o->port = obj;
+ o->next = objects;
+ objects = o;
+ }
+ else
+ mach_port_deallocate (mach_task_self (), obj);
+
+ fprintf (s, "[mem_obj=%d]\n", obj);
+ }
+ else
+ fprintf (s, "\n");
+
+ addr += size;
+ }
+
+ while (objects)
+ {
+ mach_port_deallocate (mach_task_self (), objects->port);
+ objects = objects->next;
+ }
+
+ /* This is a bit awkward, fortunately vm_region should not fail. */
+ if (err != KERN_NO_SPACE)
+ fprintf (s, "%s\n", strerror (err));
+
+ fclose (s);
+ return contents_len;
+}
+
+static ssize_t
process_file_gc_stat (struct proc_stat *ps, char **contents)
{
struct procinfo *pi = proc_stat_proc_info (ps);
@@ -348,6 +435,14 @@ static struct procfs_dir_entry entries[] = {
},
},
{
+ .name = "maps",
+ .hook = & (struct process_file_desc) {
+ .get_contents = process_file_gc_maps,
+ .needs = PSTAT_TASK,
+ .mode = 0400,
+ },
+ },
+ {
.name = "stat",
.hook = & (struct process_file_desc) {
.get_contents = process_file_gc_stat,
--
2.1.0
|