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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
From 77c514cb7d3dd577576df13353b350052c37003a 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 1/7] procfs: implement /proc/N/maps
Fixes https://savannah.gnu.org/bugs/?32770 .
* procfs/process.c (process_file_gc_maps): New function.
(entries): Use the new function to implement /proc/N/maps.
---
procfs/process.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 103 insertions(+), 1 deletion(-)
diff --git a/procfs/process.c b/procfs/process.c
index 4854148..a9b1a59 100644
--- a/procfs/process.c
+++ b/procfs/process.c
@@ -1,5 +1,5 @@
/* Hurd /proc filesystem, implementation of process directories.
- Copyright (C) 2010 Free Software Foundation, Inc.
+ Copyright (C) 2010,14 Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -109,6 +109,100 @@ 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);
+ if (s == NULL)
+ {
+ *contents = NULL;
+ return 0;
+ }
+
+ 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)
+ {
+ struct mem_obj *o = objects;
+ mach_port_deallocate (mach_task_self (), o->port);
+ objects = o->next;
+ free (o);
+ }
+
+ /* 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 +442,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
|