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