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