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