~ubuntu-branches/debian/sid/libgtop2/sid

« back to all changes in this revision

Viewing changes to sysdeps/openbsd/procmap.c

  • Committer: Package Import Robot
  • Author(s): Michael Biebl
  • Date: 2013-09-05 02:53:46 UTC
  • mfrom: (1.1.21)
  • Revision ID: package-import@ubuntu.com-20130905025346-qfl4a2bg8b0s5clw
Tags: 2.28.5-1
* New upstream release.
* Remove those kfreebsd patches which have been merged upstream.
* Drop 99_ltmain_as-needed.patch and use dh_autoreconf --as-needed instead.
* Bump Standards-Version to 3.9.4. No further changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $OpenBSD: procmap.c,v 1.6 2011/06/06 17:12:12 jasper Exp $   */
 
1
/* $OpenBSD: patch-sysdeps_openbsd_procmap_c,v 1.7 2012/03/11 08:45:24 ajacoutot Exp $  */
2
2
 
3
3
/* Copyright (C) 1998 Joshua Sled
4
4
   This file is part of LibGTop 1.0.
29
29
#include <glibtop_suid.h>
30
30
 
31
31
#include <kvm.h>
 
32
#include <stdlib.h>
32
33
#include <sys/param.h>
33
34
#include <sys/proc.h>
34
35
#include <sys/resource.h>
56
57
(1L << GLIBTOP_MAP_ENTRY_OFFSET) + (1L << GLIBTOP_MAP_ENTRY_PERM) +
57
58
(1L << GLIBTOP_MAP_ENTRY_INODE) + (1L << GLIBTOP_MAP_ENTRY_DEVICE);
58
59
 
 
60
/* Local helper functions. */
 
61
 
 
62
ssize_t load_vmmap_entries(glibtop*, unsigned long, struct vm_map_entry**,
 
63
            struct vm_map_entry*);
 
64
void    unload_vmmap_entries(struct vm_map_entry *);
 
65
 
59
66
/* Init function. */
60
67
 
61
68
void
64
71
        server->sysdeps.proc_map = _glibtop_sysdeps_proc_map;
65
72
}
66
73
 
67
 
/* Provides detailed information about a process. */
 
74
/*
 
75
 * Download vmmap_entries from the kernel into our address space.
 
76
 * We fix up the addr tree while downloading.
 
77
 *
 
78
 * Returns: the size of the tree on succes, or -1 on failure.
 
79
 * On failure, *rptr needs to be passed to unload_vmmap_entries to free
 
80
 * the lot.
 
81
 */
 
82
ssize_t
 
83
load_vmmap_entries(glibtop *server, unsigned long kptr,
 
84
    struct vm_map_entry **rptr, struct vm_map_entry *parent)
 
85
{
 
86
        struct vm_map_entry *entry;
 
87
        unsigned long left_kptr, right_kptr;
 
88
        ssize_t left_sz;
 
89
        ssize_t right_sz;
 
90
 
 
91
        if (kptr == 0)
 
92
                return 0;
 
93
 
 
94
        /* Need space. */
 
95
        entry = malloc(sizeof(*entry));
 
96
        if (entry == NULL)
 
97
                return -1;
 
98
 
 
99
        /* Download entry at kptr. */
 
100
        if (kvm_read (server->machine.kd, kptr,
 
101
            (char *)entry, sizeof(*entry)) != sizeof(*entry)) {
 
102
                free(entry);
 
103
                return -1;
 
104
        }
 
105
 
 
106
        /*
 
107
         * Update addr pointers to have sane values in this address space.
 
108
         * We save the kernel pointers in {left,right}_kptr, so we have them
 
109
         * available to download children.
 
110
         */
 
111
        left_kptr = (unsigned long) RB_LEFT(entry, daddrs.addr_entry);
 
112
        right_kptr = (unsigned long) RB_RIGHT(entry, daddrs.addr_entry);
 
113
        RB_LEFT(entry, daddrs.addr_entry) =
 
114
            RB_RIGHT(entry, daddrs.addr_entry) = NULL;
 
115
        /* Fill in parent pointer. */
 
116
        RB_PARENT(entry, daddrs.addr_entry) = parent;
 
117
 
 
118
        /*
 
119
         * Consistent state reached, fill in *rptr.
 
120
         */
 
121
        *rptr = entry;
 
122
 
 
123
        /*
 
124
         * Download left, right.
 
125
         * On failure, our map is in a state that can be handled by
 
126
         * unload_vmmap_entries.
 
127
         */
 
128
        left_sz = load_vmmap_entries(server, left_kptr,
 
129
            &RB_LEFT(entry, daddrs.addr_entry), entry);
 
130
        if (left_sz == -1)
 
131
                return -1;
 
132
        right_sz = load_vmmap_entries(server, right_kptr,
 
133
            &RB_RIGHT(entry, daddrs.addr_entry), entry);
 
134
        if (right_sz == -1)
 
135
                return -1;
 
136
 
 
137
        return 1 + left_sz + right_sz;
 
138
}
 
139
 
 
140
/*
 
141
 * Free the vmmap entries in the given tree.
 
142
 */
 
143
void
 
144
unload_vmmap_entries(struct vm_map_entry *entry)
 
145
{
 
146
        if (entry == NULL)
 
147
                return;
 
148
 
 
149
        unload_vmmap_entries(RB_LEFT(entry, daddrs.addr_entry));
 
150
        unload_vmmap_entries(RB_RIGHT(entry, daddrs.addr_entry));
 
151
        free(entry);
 
152
}
 
153
 
 
154
/*
 
155
 * Provides detailed information about a process.
 
156
 * Due to the fact we are only requested info about one process, it's possible
 
157
 * the process has been reaped before we get to kvm_getprocs. Tough luck.
 
158
 */
68
159
 
69
160
glibtop_map_entry *
70
161
glibtop_get_proc_map_p (glibtop *server, glibtop_proc_map *buf,
71
162
                        pid_t pid)
72
163
{
73
 
        struct kinfo_proc2 *pinfo;
74
 
        struct vm_map_entry entry, *first;
 
164
        struct kinfo_proc *pinfo;
 
165
        struct vm_map_entry *entry;
 
166
        struct uvm_map_addr root;
75
167
        struct vmspace vmspace;
76
168
        struct vnode vnode;
77
169
        struct inode inode;
 
170
        ssize_t nentries;
78
171
        GArray *maps = g_array_sized_new(FALSE, FALSE,
79
172
                                         sizeof(glibtop_map_entry),
80
173
                                         100);
81
 
        int count, i = 0;
82
 
        int update = 0;
 
174
        int count = 0;
83
175
 
84
176
        glibtop_init_p (server, (1L << GLIBTOP_SYSDEPS_PROC_MAP), 0);
85
177
 
91
183
        glibtop_suid_enter (server);
92
184
 
93
185
        /* Get the process data */
94
 
        pinfo = kvm_getproc2 (server->machine.kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc2), &count);
 
186
        pinfo = kvm_getprocs (server->machine.kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &count);
95
187
        if ((pinfo == NULL) || (count < 1)) {
96
188
                glibtop_warn_io_r (server, "kvm_getprocs (%d)", pid);
97
189
                return (glibtop_map_entry*) g_array_free(maps, TRUE);
104
196
                      (char *) &vmspace, sizeof (vmspace)) != sizeof (vmspace))
105
197
                glibtop_error_io_r (server, "kvm_read (vmspace)");
106
198
 
107
 
        first = vmspace.vm_map.header.next;
108
 
 
109
 
        if (kvm_read (server->machine.kd,
110
 
                      (unsigned long) vmspace.vm_map.header.next,
111
 
                      (char *) &entry, sizeof (entry)) != sizeof (entry))
 
199
        RB_INIT(&root);
 
200
        nentries = load_vmmap_entries(server,
 
201
            (unsigned long) RB_ROOT(&vmspace.vm_map.addr),
 
202
            &RB_ROOT(&root), NULL);
 
203
        if (nentries == -1) {
 
204
                unload_vmmap_entries(RB_ROOT(&root));
112
205
                glibtop_error_io_r (server, "kvm_read (entry)");
 
206
        }
113
207
 
114
208
        /* Allocate space. */
115
209
 
116
 
        buf->number = vmspace.vm_map.nentries;
 
210
        buf->number = nentries;
117
211
        buf->size = sizeof (glibtop_map_entry);
118
212
 
119
213
        buf->total = buf->number * buf->size;
124
218
 
125
219
        /* I tested this a few times with `mmap'; as soon as you write
126
220
         * to the mmap'ed area, the object type changes from OBJT_VNODE
127
 
         * to OBJT_DEFAULT so it seems this really works. */
 
221
         * to OBJT_DEFAULT so it seems this really works.
 
222
         */
128
223
 
129
 
        do {
 
224
        RB_FOREACH(entry, uvm_map_addr, &root) {
130
225
                glibtop_map_entry *mentry;
131
226
                unsigned long inum, dev;
132
227
                guint len;
133
228
 
134
 
                if (update) {
135
 
                        if (kvm_read (server->machine.kd,
136
 
                                      (unsigned long) entry.next,
137
 
                                      &entry, sizeof (entry)) != sizeof (entry))
138
 
                                glibtop_error_io_r (server, "kvm_read (entry)");
139
 
                } else {
140
 
                        update = 1;
141
 
                }
142
 
 
143
 
                if (UVM_ET_ISSUBMAP (&entry))
 
229
                if (UVM_ET_ISSUBMAP(entry))
144
230
                        continue;
145
 
 
146
 
                if (!entry.object.uvm_obj)
 
231
                if (!entry->object.uvm_obj)
147
232
                        continue;
148
233
 
149
234
                /* We're only interested in vnodes */
150
235
 
151
236
                if (kvm_read (server->machine.kd,
152
 
                              (unsigned long) entry.object.uvm_obj,
 
237
                              (unsigned long) entry->object.uvm_obj,
153
238
                              &vnode, sizeof (vnode)) != sizeof (vnode)) {
154
239
                        glibtop_warn_io_r (server, "kvm_read (vnode)");
 
240
                        unload_vmmap_entries(RB_ROOT(&root));
155
241
                        return (glibtop_map_entry*) g_array_free(maps, TRUE);
156
242
                }
157
243
 
176
262
 
177
263
                mentry->flags  = _glibtop_sysdeps_map_entry;
178
264
 
179
 
                mentry->start  = (guint64) entry.start;
180
 
                mentry->end    = (guint64) entry.end;
181
 
                mentry->offset = (guint64) entry.offset;
 
265
                mentry->start  = (guint64) entry->start;
 
266
                mentry->end    = (guint64) entry->end;
 
267
                mentry->offset = (guint64) entry->offset;
182
268
                mentry->device = (guint64) dev;
183
269
                mentry->inode  = (guint64) inum;
184
270
 
185
271
                mentry->perm   = (guint64) 0;
186
272
 
187
 
                if (entry.protection & VM_PROT_READ)
 
273
                if (entry->protection & VM_PROT_READ)
188
274
                        mentry->perm |= GLIBTOP_MAP_PERM_READ;
189
 
                if (entry.protection & VM_PROT_WRITE)
 
275
                if (entry->protection & VM_PROT_WRITE)
190
276
                        mentry->perm |= GLIBTOP_MAP_PERM_WRITE;
191
 
                if (entry.protection & VM_PROT_EXECUTE)
 
277
                if (entry->protection & VM_PROT_EXECUTE)
192
278
                        mentry->perm |= GLIBTOP_MAP_PERM_EXECUTE;
193
 
        } while (entry.next != first);
 
279
        }
194
280
 
195
281
        buf->flags = _glibtop_sysdeps_proc_map;
196
282
 
198
284
        buf->size = sizeof (glibtop_map_entry);
199
285
        buf->total = buf->number * buf->size;
200
286
 
 
287
        unload_vmmap_entries(RB_ROOT(&root));
201
288
        return (glibtop_map_entry*) g_array_free(maps, FALSE);
202
289
}
 
290
 
 
291
/*
 
292
 * Don't implement address comparison.
 
293
 */
 
294
static __inline int
 
295
no_impl(void *p, void *q)
 
296
{
 
297
        abort(); /* Should not be called. */
 
298
        return 0;
 
299
}
 
300
 
 
301
RB_GENERATE(uvm_map_addr, vm_map_entry, daddrs.addr_entry, no_impl);