Print this page
OS-5223 removed shm segment is no longer available
Reviewed by: Bryan Cantrill <bryan@joyent.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/mdb/common/modules/ipc/ipc.c
+++ new/usr/src/cmd/mdb/common/modules/ipc/ipc.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 + * Copyright 2016 Joyent, Inc.
24 25 */
25 26
26 27 #include <mdb/mdb_modapi.h>
27 28 #include <mdb/mdb_ks.h>
28 29
29 30 #include <sys/types.h>
30 31 #include <sys/mman.h>
31 32 #include <sys/project.h>
32 33 #include <sys/ipc_impl.h>
33 34 #include <sys/shm_impl.h>
34 35 #include <sys/sem_impl.h>
35 36 #include <sys/msg_impl.h>
36 37
37 38 #include <vm/anon.h>
38 39
39 40 #define CMN_HDR_START "%<u>"
40 41 #define CMN_HDR_END "%</u>\n"
41 42 #define CMN_INDENT (4)
42 43 #define CMN_INACTIVE "%s facility inactive.\n"
43 44
44 45 /*
45 46 * Bitmap data for page protection flags suitable for use with %b.
46 47 */
47 48 const mdb_bitmask_t prot_flag_bits[] = {
48 49 { "PROT_READ", PROT_READ, PROT_READ },
49 50 { "PROT_WRITE", PROT_WRITE, PROT_WRITE },
50 51 { "PROT_EXEC", PROT_EXEC, PROT_EXEC },
51 52 { "PROT_USER", PROT_USER, PROT_USER },
52 53 { NULL, 0, 0 }
53 54 };
54 55
55 56 static void
56 57 printtime_nice(const char *str, time_t time)
57 58 {
58 59 if (time)
59 60 mdb_printf("%s%Y\n", str, time);
60 61 else
61 62 mdb_printf("%sn/a\n", str);
62 63 }
63 64
64 65 /*
65 66 * Print header common to all IPC types.
66 67 */
67 68 static void
68 69 ipcperm_header()
69 70 {
70 71 mdb_printf(CMN_HDR_START "%?s %5s %5s %8s %5s %5s %6s %5s %5s %5s %5s"
71 72 CMN_HDR_END, "ADDR", "REF", "ID", "KEY", "MODE", "PRJID", "ZONEID",
72 73 "OWNER", "GROUP", "CREAT", "CGRP");
73 74 }
74 75
75 76 /*
76 77 * Print data common to all IPC types.
77 78 */
78 79 static void
79 80 ipcperm_print(uintptr_t addr, kipc_perm_t *perm)
80 81 {
81 82 kproject_t proj;
82 83 int res;
83 84
84 85 res = mdb_vread(&proj, sizeof (kproject_t), (uintptr_t)perm->ipc_proj);
85 86
86 87 if (res == -1)
87 88 mdb_warn("failed to read kproject_t at %#p", perm->ipc_proj);
88 89
89 90 mdb_printf("%0?p %5d %5d", addr, perm->ipc_ref, perm->ipc_id);
90 91 if (perm->ipc_key)
91 92 mdb_printf(" %8x", perm->ipc_key);
92 93 else
93 94 mdb_printf(" %8s", "private");
94 95 mdb_printf(" %5#o", perm->ipc_mode & 07777);
95 96 if (res == -1)
96 97 mdb_printf(" %5s %5s", "<flt>", "<flt>");
97 98 else
98 99 mdb_printf(" %5d %6d", proj.kpj_id, proj.kpj_zoneid);
99 100 mdb_printf(" %5d %5d %5d %5d\n", perm->ipc_uid, perm->ipc_gid,
100 101 perm->ipc_cuid, perm->ipc_cgid);
101 102
102 103 }
103 104
104 105 /*ARGSUSED*/
105 106 static int
106 107 ipcperm(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
107 108 {
108 109 kipc_perm_t perm;
109 110
110 111 if (!(flags & DCMD_ADDRSPEC))
111 112 return (DCMD_USAGE);
112 113
113 114 if (DCMD_HDRSPEC(flags))
114 115 ipcperm_header();
115 116
116 117 if (mdb_vread(&perm, sizeof (kipc_perm_t), addr) == -1) {
117 118 mdb_warn("failed to read kipc_perm_t at %#lx", addr);
118 119 return (DCMD_ERR);
119 120 }
120 121
121 122 ipcperm_print(addr, &perm);
122 123 return (DCMD_OK);
123 124 }
124 125
125 126
126 127 #define MSG_SND_SIZE 0x1
127 128 static int
128 129 msgq_check_for_waiters(list_t *walk_this, int min, int max,
129 130 int copy_wait, uintptr_t addr, int flag)
130 131
131 132 {
132 133 int found = 0;
133 134 int ii;
134 135 msgq_wakeup_t *walker, next;
135 136 uintptr_t head;
136 137
137 138 for (ii = min; ii < max; ii++) {
138 139 head = ((ulong_t)addr) + sizeof (list_t)*ii +
139 140 sizeof (list_node_t);
140 141 if (head != (uintptr_t)walk_this[ii].list_head.list_next) {
141 142 walker =
142 143 (msgq_wakeup_t *)walk_this[ii].list_head.list_next;
143 144 while (head != (uintptr_t)walker) {
144 145 if (mdb_vread(&next, sizeof (msgq_wakeup_t),
145 146 (uintptr_t)walker) == -1) {
146 147 mdb_warn(
147 148 "Failed to read message queue\n");
148 149 return (found);
149 150 }
150 151
151 152 if (flag & MSG_SND_SIZE) {
152 153 mdb_printf("%15lx\t%6d\t%15lx\t%15d\n",
153 154 next.msgw_thrd, next.msgw_type,
154 155 walker + (uintptr_t)
155 156 OFFSETOF(msgq_wakeup_t,
156 157 msgw_wake_cv), next.msgw_snd_size);
157 158 } else {
158 159 mdb_printf("%15lx\t%6d\t%15lx\t%15s\n",
159 160 next.msgw_thrd, next.msgw_type,
160 161 walker + (uintptr_t)
161 162 OFFSETOF(msgq_wakeup_t,
162 163 msgw_wake_cv),
163 164 (copy_wait ? "yes":"no"));
164 165 }
165 166 found++;
166 167 walker =
167 168 (msgq_wakeup_t *)next.msgw_list.list_next;
168 169 }
169 170 }
170 171 }
171 172 return (found);
172 173 }
173 174
174 175 static void
175 176 msq_print(kmsqid_t *msqid, uintptr_t addr)
176 177 {
177 178 int total = 0;
178 179
179 180 mdb_printf("&list: %-?p\n", addr + OFFSETOF(kmsqid_t, msg_list));
180 181 mdb_printf("cbytes: 0t%lu qnum: 0t%lu qbytes: 0t%lu"
181 182 " qmax: 0t%lu\n", msqid->msg_cbytes, msqid->msg_qnum,
182 183 msqid->msg_qbytes, msqid->msg_qmax);
183 184 mdb_printf("lspid: 0t%d lrpid: 0t%d\n",
184 185 (int)msqid->msg_lspid, (int)msqid->msg_lrpid);
185 186 printtime_nice("stime: ", msqid->msg_stime);
186 187 printtime_nice("rtime: ", msqid->msg_rtime);
187 188 printtime_nice("ctime: ", msqid->msg_ctime);
188 189 mdb_printf("snd_cnt: 0t%lld snd_cv: %hd (%p)\n",
189 190 msqid->msg_snd_cnt, msqid->msg_snd_cv._opaque,
190 191 addr + (uintptr_t)OFFSETOF(kmsqid_t, msg_snd_cv));
191 192 mdb_printf("Blocked recievers\n");
192 193 mdb_printf("%15s\t%6s\t%15s\t%15s\n", "Thread Addr",
193 194 "Type", "cv addr", "copyout-wait?");
194 195 total += msgq_check_for_waiters(&msqid->msg_cpy_block,
195 196 0, 1, 1, addr + OFFSETOF(kmsqid_t, msg_cpy_block), 0);
196 197 total += msgq_check_for_waiters(msqid->msg_wait_snd_ngt,
197 198 0, MSG_MAX_QNUM + 1, 0,
198 199 addr + OFFSETOF(kmsqid_t, msg_wait_snd_ngt), 0);
199 200 mdb_printf("Blocked senders\n");
200 201 total += msgq_check_for_waiters(&msqid->msg_wait_rcv,
201 202 0, 1, 1, addr + OFFSETOF(kmsqid_t, msg_wait_rcv),
202 203 MSG_SND_SIZE);
203 204 mdb_printf("%15s\t%6s\t%15s\t%15s\n", "Thread Addr",
204 205 "Type", "cv addr", "Msg Size");
205 206 total += msgq_check_for_waiters(msqid->msg_wait_snd,
206 207 0, MSG_MAX_QNUM + 1, 0, addr + OFFSETOF(kmsqid_t,
207 208 msg_wait_snd), 0);
208 209 mdb_printf("Total number of waiters: %d\n", total);
209 210 }
210 211
211 212
212 213 /*ARGSUSED1*/
213 214 static void
214 215 shm_print(kshmid_t *shmid, uintptr_t addr)
215 216 {
216 217 shmatt_t nattch;
217 218
218 219 nattch = shmid->shm_perm.ipc_ref - (IPC_FREE(&shmid->shm_perm) ? 0 : 1);
219 220
220 221 mdb_printf(CMN_HDR_START "%10s %?s %5s %7s %7s %7s %7s" CMN_HDR_END,
221 222 "SEGSZ", "AMP", "LKCNT", "LPID", "CPID", "NATTCH", "CNATTCH");
|
↓ open down ↓ |
188 lines elided |
↑ open up ↑ |
222 223 mdb_printf("%10#lx %?p %5u %7d %7d %7lu %7lu\n",
223 224 shmid->shm_segsz, shmid->shm_amp, shmid->shm_lkcnt,
224 225 (int)shmid->shm_lpid, (int)shmid->shm_cpid, nattch,
225 226 shmid->shm_ismattch);
226 227
227 228 printtime_nice("atime: ", shmid->shm_atime);
228 229 printtime_nice("dtime: ", shmid->shm_dtime);
229 230 printtime_nice("ctime: ", shmid->shm_ctime);
230 231 mdb_printf("sptinfo: %-?p sptseg: %-?p\n",
231 232 shmid->shm_sptinfo, shmid->shm_sptseg);
232 - mdb_printf("sptprot: <%lb>\n", shmid->shm_sptprot, prot_flag_bits);
233 + mdb_printf("opts: rmpend: %d prot: <%b>\n",
234 + ((shmid->shm_opts & SHM_RM_PENDING) != 0),
235 + (shmid->shm_opts & SHM_PROT_MASK), prot_flag_bits);
233 236 }
234 237
235 238
236 239 /*ARGSUSED1*/
237 240 static void
238 241 sem_print(ksemid_t *semid, uintptr_t addr)
239 242 {
240 243 mdb_printf("base: %-?p nsems: 0t%u\n",
241 244 semid->sem_base, semid->sem_nsems);
242 245 printtime_nice("otime: ", semid->sem_otime);
243 246 printtime_nice("ctime: ", semid->sem_ctime);
244 247 mdb_printf("binary: %s\n", semid->sem_binary ? "yes" : "no");
245 248 }
246 249
247 250 typedef struct ipc_ops_vec {
248 251 char *iv_wcmd; /* walker name */
249 252 char *iv_ocmd; /* output dcmd */
250 253 char *iv_service; /* service pointer */
251 254 void (*iv_print)(void *, uintptr_t); /* output callback */
252 255 size_t iv_idsize;
253 256 } ipc_ops_vec_t;
254 257
255 258 ipc_ops_vec_t msq_ops_vec = {
256 259 "msq",
257 260 "kmsqid",
258 261 "msq_svc",
259 262 (void(*)(void *, uintptr_t))msq_print,
260 263 sizeof (kmsqid_t)
261 264 };
262 265
263 266 ipc_ops_vec_t shm_ops_vec = {
264 267 "shm",
265 268 "kshmid",
266 269 "shm_svc",
267 270 (void(*)(void *, uintptr_t))shm_print,
268 271 sizeof (kshmid_t)
269 272 };
270 273
271 274 ipc_ops_vec_t sem_ops_vec = {
272 275 "sem",
273 276 "ksemid",
274 277 "sem_svc",
275 278 (void(*)(void *, uintptr_t))sem_print,
276 279 sizeof (ksemid_t)
277 280 };
278 281
279 282
280 283 /*
281 284 * Generic IPC data structure display code
282 285 */
283 286 static int
284 287 ds_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
285 288 ipc_ops_vec_t *iv)
286 289 {
287 290 void *iddata;
288 291
289 292 if (!(flags & DCMD_ADDRSPEC)) {
290 293 uint_t oflags = 0;
291 294
292 295 if (mdb_getopts(argc, argv, 'l', MDB_OPT_SETBITS, 1, &oflags,
293 296 NULL) != argc)
294 297 return (DCMD_USAGE);
295 298
296 299 if (mdb_walk_dcmd(iv->iv_wcmd, oflags ? iv->iv_ocmd : "ipcperm",
297 300 argc, argv) == -1) {
298 301 mdb_warn("can't walk '%s'", iv->iv_wcmd);
299 302 return (DCMD_ERR);
300 303 }
301 304 return (DCMD_OK);
302 305 }
303 306
304 307 iddata = mdb_alloc(iv->iv_idsize, UM_SLEEP | UM_GC);
305 308 if (mdb_vread(iddata, iv->iv_idsize, addr) == -1) {
306 309 mdb_warn("failed to read %s at %#lx", iv->iv_ocmd, addr);
307 310 return (DCMD_ERR);
308 311 }
309 312
310 313 if (!DCMD_HDRSPEC(flags) && iv->iv_print)
311 314 mdb_printf("\n");
312 315
313 316 if (DCMD_HDRSPEC(flags) || iv->iv_print)
314 317 ipcperm_header();
315 318
316 319 ipcperm_print(addr, (struct kipc_perm *)iddata);
317 320 if (iv->iv_print) {
318 321 mdb_inc_indent(CMN_INDENT);
319 322 iv->iv_print(iddata, addr);
320 323 mdb_dec_indent(CMN_INDENT);
321 324 }
322 325
323 326 return (DCMD_OK);
324 327 }
325 328
326 329
327 330 /*
328 331 * Stubs to call ds_print with the appropriate ops vector
329 332 */
330 333 static int
331 334 cmd_kshmid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
332 335 {
333 336 return (ds_print(addr, flags, argc, argv, &shm_ops_vec));
334 337 }
335 338
336 339
337 340 static int
338 341 cmd_kmsqid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
339 342 {
340 343 return (ds_print(addr, flags, argc, argv, &msq_ops_vec));
341 344 }
342 345
343 346 static int
344 347 cmd_ksemid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
345 348 {
346 349 return (ds_print(addr, flags, argc, argv, &sem_ops_vec));
347 350 }
348 351
349 352 /*
350 353 * Generic IPC walker
351 354 */
352 355
353 356 static int
354 357 ds_walk_init(mdb_walk_state_t *wsp)
355 358 {
356 359 ipc_ops_vec_t *iv = wsp->walk_arg;
357 360
358 361 if (wsp->walk_arg != NULL && wsp->walk_addr != NULL)
359 362 mdb_printf("ignoring provided address\n");
360 363
361 364 if (wsp->walk_arg)
362 365 if (mdb_readvar(&wsp->walk_addr, iv->iv_service) == -1) {
363 366 mdb_printf("failed to read '%s'; module not present\n",
364 367 iv->iv_service);
365 368 return (WALK_DONE);
366 369 }
367 370 else
368 371 wsp->walk_addr = wsp->walk_addr +
369 372 OFFSETOF(ipc_service_t, ipcs_usedids);
370 373
371 374 if (mdb_layered_walk("list", wsp) == -1)
372 375 return (WALK_ERR);
373 376
374 377 return (WALK_NEXT);
375 378 }
376 379
377 380
378 381 static int
379 382 ds_walk_step(mdb_walk_state_t *wsp)
380 383 {
381 384 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
382 385 wsp->walk_cbdata));
383 386 }
384 387
385 388 /*
386 389 * Generic IPC ID/key to pointer code
387 390 */
388 391
389 392 static int
390 393 ipcid_impl(uintptr_t svcptr, uintptr_t id, uintptr_t *addr)
391 394 {
392 395 ipc_service_t service;
393 396 kipc_perm_t perm;
394 397 ipc_slot_t slot;
395 398 uintptr_t slotptr;
396 399 uint_t index;
397 400
398 401 if (id > INT_MAX) {
399 402 mdb_warn("id out of range\n");
400 403 return (DCMD_ERR);
401 404 }
402 405
403 406 if (mdb_vread(&service, sizeof (ipc_service_t), svcptr) == -1) {
404 407 mdb_warn("failed to read ipc_service_t at %#lx", svcptr);
405 408 return (DCMD_ERR);
406 409 }
407 410
408 411 index = (uint_t)id & (service.ipcs_tabsz - 1);
409 412 slotptr = (uintptr_t)(service.ipcs_table + index);
410 413
411 414 if (mdb_vread(&slot, sizeof (ipc_slot_t), slotptr) == -1) {
412 415 mdb_warn("failed to read ipc_slot_t at %#lx", slotptr);
413 416 return (DCMD_ERR);
414 417 }
415 418
416 419 if (slot.ipct_data == NULL)
417 420 return (DCMD_ERR);
418 421
419 422 if (mdb_vread(&perm, sizeof (kipc_perm_t),
420 423 (uintptr_t)slot.ipct_data) == -1) {
421 424 mdb_warn("failed to read kipc_perm_t at %#p",
422 425 slot.ipct_data);
423 426 return (DCMD_ERR);
424 427 }
425 428
426 429 if (perm.ipc_id != (uint_t)id)
427 430 return (DCMD_ERR);
428 431
429 432 *addr = (uintptr_t)slot.ipct_data;
430 433
431 434 return (DCMD_OK);
432 435 }
433 436
434 437
435 438 typedef struct findkey_data {
436 439 key_t fk_key;
437 440 uintptr_t fk_addr;
438 441 boolean_t fk_found;
439 442 } findkey_data_t;
440 443
441 444 static int
442 445 findkey(uintptr_t addr, kipc_perm_t *perm, findkey_data_t *arg)
443 446 {
444 447 if (perm->ipc_key == arg->fk_key) {
445 448 arg->fk_found = B_TRUE;
446 449 arg->fk_addr = addr;
447 450 return (WALK_DONE);
448 451 }
449 452 return (WALK_NEXT);
450 453 }
451 454
452 455 static int
453 456 ipckey_impl(uintptr_t svcptr, uintptr_t key, uintptr_t *addr)
454 457 {
455 458 ipc_service_t service;
456 459 findkey_data_t fkdata;
457 460
458 461 if ((key == IPC_PRIVATE) || (key > INT_MAX)) {
459 462 mdb_warn("key out of range\n");
460 463 return (DCMD_ERR);
461 464 }
462 465
463 466 if (mdb_vread(&service, sizeof (ipc_service_t), svcptr) == -1) {
464 467 mdb_warn("failed to read ipc_service_t at %#lx", svcptr);
465 468 return (DCMD_ERR);
466 469 }
467 470
468 471 fkdata.fk_key = (key_t)key;
469 472 fkdata.fk_found = B_FALSE;
470 473 if ((mdb_pwalk("avl", (mdb_walk_cb_t)findkey, &fkdata,
471 474 svcptr + OFFSETOF(ipc_service_t, ipcs_keys)) == -1) ||
472 475 !fkdata.fk_found)
473 476 return (DCMD_ERR);
474 477
475 478 *addr = fkdata.fk_addr;
476 479
477 480 return (DCMD_OK);
478 481 }
479 482
480 483 static int
481 484 ipckeyid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
482 485 int(*fp)(uintptr_t, uintptr_t, uintptr_t *))
483 486 {
484 487 uintmax_t val;
485 488 uintptr_t raddr;
486 489 int result;
487 490
488 491 if (!(flags & DCMD_ADDRSPEC) || (argc != 1))
489 492 return (DCMD_USAGE);
490 493
491 494 if (argv[0].a_type == MDB_TYPE_IMMEDIATE)
492 495 val = argv[0].a_un.a_val;
493 496 else if (argv[0].a_type == MDB_TYPE_STRING)
494 497 val = mdb_strtoull(argv[0].a_un.a_str);
495 498 else
496 499 return (DCMD_USAGE);
497 500
498 501 result = fp(addr, val, &raddr);
499 502
500 503 if (result == DCMD_OK)
501 504 mdb_printf("%lx", raddr);
502 505
503 506 return (result);
504 507 }
505 508
506 509 static int
507 510 ipckey(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
508 511 {
509 512 return (ipckeyid(addr, flags, argc, argv, ipckey_impl));
510 513 }
511 514
512 515 static int
513 516 ipcid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
514 517 {
515 518 return (ipckeyid(addr, flags, argc, argv, ipcid_impl));
516 519 }
517 520
518 521 static int
519 522 ds_ptr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
520 523 ipc_ops_vec_t *iv)
521 524 {
522 525 uint_t kflag = FALSE;
523 526 uintptr_t svcptr, raddr;
524 527 int result;
525 528
526 529 if (!(flags & DCMD_ADDRSPEC))
527 530 return (DCMD_USAGE);
528 531
529 532 if (mdb_getopts(argc, argv,
530 533 'k', MDB_OPT_SETBITS, TRUE, &kflag, NULL) != argc)
531 534 return (DCMD_USAGE);
532 535
533 536 if (mdb_readvar(&svcptr, iv->iv_service) == -1) {
534 537 mdb_warn("failed to read '%s'; module not present\n",
535 538 iv->iv_service);
536 539 return (DCMD_ERR);
537 540 }
538 541
539 542 result = kflag ? ipckey_impl(svcptr, addr, &raddr) :
540 543 ipcid_impl(svcptr, addr, &raddr);
541 544
542 545 if (result == DCMD_OK)
543 546 mdb_printf("%lx", raddr);
544 547
545 548 return (result);
546 549 }
547 550
548 551 /*
549 552 * Stubs to call ds_ptr with the appropriate ops vector
550 553 */
551 554 static int
552 555 id2shm(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
553 556 {
554 557 return (ds_ptr(addr, flags, argc, argv, &shm_ops_vec));
555 558 }
556 559
557 560 static int
558 561 id2msq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
559 562 {
560 563 return (ds_ptr(addr, flags, argc, argv, &msq_ops_vec));
561 564 }
562 565
563 566 static int
564 567 id2sem(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
565 568 {
566 569 return (ds_ptr(addr, flags, argc, argv, &sem_ops_vec));
567 570 }
568 571
569 572
570 573 /*
571 574 * The message queue contents walker
572 575 */
573 576
574 577 static int
575 578 msg_walk_init(mdb_walk_state_t *wsp)
576 579 {
577 580 wsp->walk_addr += OFFSETOF(kmsqid_t, msg_list);
578 581 if (mdb_layered_walk("list", wsp) == -1)
579 582 return (WALK_ERR);
580 583
581 584 return (WALK_NEXT);
582 585 }
583 586
584 587 static int
585 588 msg_walk_step(mdb_walk_state_t *wsp)
586 589 {
587 590 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
588 591 wsp->walk_cbdata));
589 592 }
590 593
591 594 /*
592 595 * The "::ipcs" command itself. Just walks each IPC type in turn.
593 596 */
594 597
595 598 /*ARGSUSED*/
596 599 static int
597 600 ipcs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
598 601 {
599 602 uint_t oflags = 0;
600 603
601 604 if ((flags & DCMD_ADDRSPEC) || mdb_getopts(argc, argv, 'l',
602 605 MDB_OPT_SETBITS, 1, &oflags, NULL) != argc)
603 606 return (DCMD_USAGE);
604 607
605 608 mdb_printf("Message queues:\n");
606 609 if (mdb_walk_dcmd("msq", oflags ? "kmsqid" : "ipcperm", argc, argv) ==
607 610 -1) {
608 611 mdb_warn("can't walk 'msq'");
609 612 return (DCMD_ERR);
610 613 }
611 614
612 615 mdb_printf("\nShared memory:\n");
613 616 if (mdb_walk_dcmd("shm", oflags ? "kshmid" : "ipcperm", argc, argv) ==
614 617 -1) {
615 618 mdb_warn("can't walk 'shm'");
616 619 return (DCMD_ERR);
617 620 }
618 621
619 622 mdb_printf("\nSemaphores:\n");
620 623 if (mdb_walk_dcmd("sem", oflags ? "ksemid" : "ipcperm", argc, argv) ==
621 624 -1) {
622 625 mdb_warn("can't walk 'sem'");
623 626 return (DCMD_ERR);
624 627 }
625 628
626 629 return (DCMD_OK);
627 630 }
628 631
629 632 static int
630 633 msgprint(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
631 634 {
632 635 struct msg message;
633 636 uint_t lflag = FALSE;
634 637 long type = 0;
635 638 char *tflag = NULL;
636 639
637 640 if (!(flags & DCMD_ADDRSPEC) || (mdb_getopts(argc, argv,
638 641 'l', MDB_OPT_SETBITS, TRUE, &lflag,
639 642 't', MDB_OPT_STR, &tflag, NULL) != argc))
640 643 return (DCMD_USAGE);
641 644
642 645 /*
643 646 * Handle negative values.
644 647 */
645 648 if (tflag != NULL) {
646 649 if (*tflag == '-') {
647 650 tflag++;
648 651 type = -1;
649 652 } else {
650 653 type = 1;
651 654 }
652 655 type *= mdb_strtoull(tflag);
653 656 }
654 657
655 658 if (DCMD_HDRSPEC(flags))
656 659 mdb_printf("%<u>%?s %?s %8s %8s %8s%</u>\n",
657 660 "ADDR", "TEXT", "SIZE", "TYPE", "REF");
658 661
659 662 if (mdb_vread(&message, sizeof (struct msg), addr) == -1) {
660 663 mdb_warn("failed to read msg at %#lx", addr);
661 664 return (DCMD_ERR);
662 665 }
663 666
664 667 /*
665 668 * If we are meeting our type contraints, display the message.
666 669 * If -l was specified, we will also display the message
667 670 * contents.
668 671 */
669 672 if ((type == 0) ||
670 673 (type > 0 && message.msg_type == type) ||
671 674 (type < 0 && message.msg_type <= -type)) {
672 675
673 676 if (lflag && !DCMD_HDRSPEC(flags))
674 677 mdb_printf("\n");
675 678
676 679 mdb_printf("%0?lx %?p %8ld %8ld %8ld\n", addr, message.msg_addr,
677 680 message.msg_size, message.msg_type, message.msg_copycnt);
678 681
679 682 if (lflag) {
680 683 mdb_printf("\n");
681 684 mdb_inc_indent(CMN_INDENT);
682 685 if (mdb_dumpptr(
683 686 (uintptr_t)message.msg_addr, message.msg_size,
684 687 MDB_DUMP_RELATIVE | MDB_DUMP_TRIM |
685 688 MDB_DUMP_ASCII | MDB_DUMP_HEADER |
686 689 MDB_DUMP_GROUP(4),
687 690 (mdb_dumpptr_cb_t)mdb_vread, NULL)) {
688 691 mdb_dec_indent(CMN_INDENT);
689 692 return (DCMD_ERR);
690 693 }
691 694 mdb_dec_indent(CMN_INDENT);
692 695 }
693 696 }
694 697
695 698 return (DCMD_OK);
696 699 }
697 700
698 701 /*
699 702 * MDB module linkage
700 703 */
701 704 static const mdb_dcmd_t dcmds[] = {
702 705 /* Generic routines */
703 706 { "ipcperm", ":", "display an IPC perm structure", ipcperm },
704 707 { "ipcid", ":id", "perform an IPC id lookup", ipcid },
705 708 { "ipckey", ":key", "perform an IPC key lookup", ipckey },
706 709
707 710 /* Specific routines */
708 711 { "kshmid", "?[-l]", "display a struct kshmid", cmd_kshmid },
709 712 { "kmsqid", "?[-l]", "display a struct kmsqid", cmd_kmsqid },
710 713 { "ksemid", "?[-l]", "display a struct ksemid", cmd_ksemid },
711 714 { "msg", ":[-l] [-t type]", "display contents of a message", msgprint },
712 715
713 716 /* Convenience routines */
714 717 { "id2shm", ":[-k]", "convert shared memory ID to pointer", id2shm },
715 718 { "id2msq", ":[-k]", "convert message queue ID to pointer", id2msq },
716 719 { "id2sem", ":[-k]", "convert semaphore ID to pointer", id2sem },
717 720
718 721 { "ipcs", "[-l]", "display System V IPC information", ipcs },
719 722 { NULL }
720 723 };
721 724
722 725 static const mdb_walker_t walkers[] = {
723 726 { "ipcsvc", "walk a System V IPC service",
724 727 ds_walk_init, ds_walk_step },
725 728 { "shm", "walk the active shmid_ds structures",
726 729 ds_walk_init, ds_walk_step, NULL, &shm_ops_vec },
727 730 { "msq", "walk the active msqid_ds structures",
728 731 ds_walk_init, ds_walk_step, NULL, &msq_ops_vec },
729 732 { "sem", "walk the active semid_ds structures",
730 733 ds_walk_init, ds_walk_step, NULL, &sem_ops_vec },
731 734 { "msgqueue", "walk messages on a message queue",
732 735 msg_walk_init, msg_walk_step },
733 736 { NULL }
734 737 };
735 738
736 739 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
737 740
738 741 const mdb_modinfo_t *
739 742 _mdb_init(void)
740 743 {
741 744 return (&modinfo);
742 745 }
|
↓ open down ↓ |
500 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX