1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  *
  25  * Copyright 2018 Joyent, Inc.
  26  */
  27 
  28 /*
  29  * MDB Target Layer
  30  *
  31  * The *target* is the program being inspected by the debugger.  The MDB target
  32  * layer provides a set of functions that insulate common debugger code,
  33  * including the MDB Module API, from the implementation details of how the
  34  * debugger accesses information from a given target.  Each target exports a
  35  * standard set of properties, including one or more address  spaces, one or
  36  * more symbol tables, a set of load objects, and a set of threads that can be
  37  * examined using the interfaces in <mdb/mdb_target.h>.  This technique has
  38  * been employed successfully in other debuggers, including [1], primarily
  39  * to improve portability, although the term "target" often refers to the
  40  * encapsulation of architectural or operating system-specific details.  The
  41  * target abstraction is useful for MDB because it allows us to easily extend
  42  * the debugger to examine a variety of different program forms.  Primarily,
  43  * the target functions validate input arguments and then call an appropriate
  44  * function in the target ops vector, defined in <mdb/mdb_target_impl.h>.
  45  * However, this interface layer provides a very high level of flexibility for
  46  * separating the debugger interface from instrumentation details.  Experience
  47  * has shown this kind of design can facilitate separating out debugger
  48  * instrumentation into an external agent [2] and enable the development of
  49  * advanced instrumentation frameworks [3].  We want MDB to be an ideal
  50  * extensible framework for the development of such applications.
  51  *
  52  * Aside from a set of wrapper functions, the target layer also provides event
  53  * management for targets that represent live executing programs.  Our model of
  54  * events is also extensible, and is based upon work in [3] and [4].  We define
  55  * a *software event* as a state transition in the target program (for example,
  56  * the transition of the program counter to a location of interest) that is
  57  * observed by the debugger or its agent.  A *software event specifier* is a
  58  * description of a class of software events that is used by the debugger to
  59  * instrument the target so that the corresponding software events can be
  60  * observed.  In MDB, software event specifiers are represented by the
  61  * mdb_sespec_t structure, defined in <mdb/mdb_target_impl.h>.  As the user,
  62  * the internal debugger code, and MDB modules may all wish to observe software
  63  * events and receive appropriate notification and callbacks, we do not expose
  64  * software event specifiers directly as part of the user interface.  Instead,
  65  * clients of the target layer request that events be observed by creating
  66  * new *virtual event specifiers*.  Each virtual specifier is named by a unique
  67  * non-zero integer (the VID), and is represented by a mdb_vespec_t structure.
  68  * One or more virtual specifiers are then associated with each underlying
  69  * software event specifier.  This design enforces the constraint that the
  70  * target must only insert one set of instrumentation, regardless of how many
  71  * times the target layer was asked to trace a given event.  For example, if
  72  * multiple clients request a breakpoint at a particular address, the virtual
  73  * specifiers will map to the same sespec, ensuring that only one breakpoint
  74  * trap instruction is actually planted at the given target address.  When no
  75  * virtual specifiers refer to an sespec, it is no longer needed and can be
  76  * removed, along with the corresponding instrumentation.
  77  *
  78  * The following state transition diagram illustrates the life cycle of a
  79  * software event specifier and example transitions:
  80  *
  81  *                                         cont/
  82  *     +--------+   delete   +--------+    stop    +-------+
  83  *    (|( DEAD )|) <------- (  ACTIVE  ) <------> (  ARMED  )
  84  *     +--------+            +--------+            +-------+
  85  *          ^   load/unload  ^        ^   failure/     |
  86  *   delete |        object /          \  reset        | failure
  87  *          |              v            v              |
  88  *          |      +--------+          +-------+       |
  89  *          +---- (   IDLE   )        (   ERR   ) <----+
  90  *          |      +--------+          +-------+
  91  *          |                              |
  92  *          +------------------------------+
  93  *
  94  * The MDB execution control model is based upon the synchronous debugging
  95  * model exported by Solaris proc(4).  A target program is set running or the
  96  * debugger is attached to a running target.  On ISTOP (stop on event of
  97  * interest), one target thread is selected as the representative.  The
  98  * algorithm for selecting the representative is target-specific, but we assume
  99  * that if an observed software event has occurred, the target will select the
 100  * thread that triggered the state transition of interest.  The other threads
 101  * are stopped in sympathy with the representative as soon as possible.  Prior
 102  * to continuing the target, we plant our instrumentation, transitioning event
 103  * specifiers from the ACTIVE to the ARMED state, and then back again when the
 104  * target stops.  We then query each active event specifier to learn which ones
 105  * are matched, and then invoke the callbacks associated with their vespecs.
 106  * If an OS error occurs while attempting to arm or disarm a specifier, the
 107  * specifier is transitioned to the ERROR state; we will attempt to arm it
 108  * again at the next continue.  If no target process is under our control or
 109  * if an event is not currently applicable (e.g. a deferred breakpoint on an
 110  * object that is not yet loaded), it remains in the IDLE state.  The target
 111  * implementation should intercept object load events and then transition the
 112  * specifier to the ACTIVE state when the corresponding object is loaded.
 113  *
 114  * To simplify the debugger implementation and allow targets to easily provide
 115  * new types of observable events, most of the event specifier management is
 116  * done by the target layer.  Each software event specifier provides an ops
 117  * vector of subroutines that the target layer can call to perform the
 118  * various state transitions described above.  The target maintains two lists
 119  * of mdb_sespec_t's: the t_idle list (IDLE state) and the t_active list
 120  * (ACTIVE, ARMED, and ERROR states).  Each mdb_sespec_t maintains a list of
 121  * associated mdb_vespec_t's.  If an sespec is IDLE or ERROR, its se_errno
 122  * field will have an errno value specifying the reason for its inactivity.
 123  * The vespec stores the client's callback function and private data, and the
 124  * arguments used to construct the sespec.  All objects are reference counted
 125  * so we can destroy an object when it is no longer needed.  The mdb_sespec_t
 126  * invariants for the respective states are as follows:
 127  *
 128  *   IDLE: on t_idle list, se_data == NULL, se_errno != 0, se_ctor not called
 129  * ACTIVE: on t_active list, se_data valid, se_errno == 0, se_ctor called
 130  *  ARMED: on t_active list, se_data valid, se_errno == 0, se_ctor called
 131  *  ERROR: on t_active list, se_data valid, se_errno != 0, se_ctor called
 132  *
 133  * Additional commentary on specific state transitions and issues involving
 134  * event management can be found below near the target layer functions.
 135  *
 136  * References
 137  *
 138  * [1] John Gilmore, "Working in GDB", Technical Report, Cygnus Support,
 139  *     1.84 edition, 1994.
 140  *
 141  * [2] David R. Hanson and Mukund Raghavachari, "A Machine-Independent
 142  *     Debugger", Software--Practice and Experience, 26(11), 1277-1299(1996).
 143  *
 144  * [3] Michael W. Shapiro, "RDB: A System for Incremental Replay Debugging",
 145  *     Technical Report CS-97-12, Department of Computer Science,
 146  *     Brown University.
 147  *
 148  * [4] Daniel B. Price, "New Techniques for Replay Debugging", Technical
 149  *     Report CS-98-05, Department of Computer Science, Brown University.
 150  */
 151 
 152 #include <mdb/mdb_target_impl.h>
 153 #include <mdb/mdb_debug.h>
 154 #include <mdb/mdb_modapi.h>
 155 #include <mdb/mdb_err.h>
 156 #include <mdb/mdb_callb.h>
 157 #include <mdb/mdb_gelf.h>
 158 #include <mdb/mdb_io_impl.h>
 159 #include <mdb/mdb_string.h>
 160 #include <mdb/mdb_signal.h>
 161 #include <mdb/mdb_frame.h>
 162 #include <mdb/mdb.h>
 163 
 164 #include <sys/stat.h>
 165 #include <sys/param.h>
 166 #include <sys/signal.h>
 167 #include <strings.h>
 168 #include <stdlib.h>
 169 #include <errno.h>
 170 
 171 /*
 172  * Define convenience macros for referencing the set of vespec flag bits that
 173  * are preserved by the target implementation, and the set of bits that
 174  * determine automatic ve_hits == ve_limit behavior.
 175  */
 176 #define T_IMPL_BITS     \
 177         (MDB_TGT_SPEC_INTERNAL | MDB_TGT_SPEC_SILENT | MDB_TGT_SPEC_MATCHED | \
 178         MDB_TGT_SPEC_DELETED)
 179 
 180 #define T_AUTO_BITS     \
 181         (MDB_TGT_SPEC_AUTOSTOP | MDB_TGT_SPEC_AUTODEL | MDB_TGT_SPEC_AUTODIS)
 182 
 183 /*
 184  * Define convenience macro for referencing target flag pending continue bits.
 185  */
 186 #define T_CONT_BITS     \
 187         (MDB_TGT_F_STEP | MDB_TGT_F_STEP_OUT | MDB_TGT_F_NEXT | MDB_TGT_F_CONT)
 188 
 189 mdb_tgt_t *
 190 mdb_tgt_create(mdb_tgt_ctor_f *ctor, int flags, int argc, const char *argv[])
 191 {
 192         mdb_module_t *mp;
 193         mdb_tgt_t *t;
 194 
 195         if (flags & ~MDB_TGT_F_ALL) {
 196                 (void) set_errno(EINVAL);
 197                 return (NULL);
 198         }
 199 
 200         t = mdb_zalloc(sizeof (mdb_tgt_t), UM_SLEEP);
 201         mdb_list_append(&mdb.m_tgtlist, t);
 202 
 203         t->t_module = &mdb.m_rmod;
 204         t->t_matched = T_SE_END;
 205         t->t_flags = flags;
 206         t->t_vepos = 1;
 207         t->t_veneg = 1;
 208 
 209         for (mp = mdb.m_mhead; mp != NULL; mp = mp->mod_next) {
 210                 if (ctor == mp->mod_tgt_ctor) {
 211                         t->t_module = mp;
 212                         break;
 213                 }
 214         }
 215 
 216         if (ctor(t, argc, argv) != 0) {
 217                 mdb_list_delete(&mdb.m_tgtlist, t);
 218                 mdb_free(t, sizeof (mdb_tgt_t));
 219                 return (NULL);
 220         }
 221 
 222         mdb_dprintf(MDB_DBG_TGT, "t_create %s (%p)\n",
 223             t->t_module->mod_name, (void *)t);
 224 
 225         (void) t->t_ops->t_status(t, &t->t_status);
 226         return (t);
 227 }
 228 
 229 int
 230 mdb_tgt_getflags(mdb_tgt_t *t)
 231 {
 232         return (t->t_flags);
 233 }
 234 
 235 int
 236 mdb_tgt_setflags(mdb_tgt_t *t, int flags)
 237 {
 238         if (flags & ~MDB_TGT_F_ALL)
 239                 return (set_errno(EINVAL));
 240 
 241         return (t->t_ops->t_setflags(t, flags));
 242 }
 243 
 244 int
 245 mdb_tgt_setcontext(mdb_tgt_t *t, void *context)
 246 {
 247         return (t->t_ops->t_setcontext(t, context));
 248 }
 249 
 250 /*ARGSUSED*/
 251 static int
 252 tgt_delete_vespec(mdb_tgt_t *t, void *private, int vid, void *data)
 253 {
 254         (void) mdb_tgt_vespec_delete(t, vid);
 255         return (0);
 256 }
 257 
 258 void
 259 mdb_tgt_destroy(mdb_tgt_t *t)
 260 {
 261         mdb_xdata_t *xdp, *nxdp;
 262 
 263         if (mdb.m_target == t) {
 264                 mdb_dprintf(MDB_DBG_TGT, "t_deactivate %s (%p)\n",
 265                     t->t_module->mod_name, (void *)t);
 266                 t->t_ops->t_deactivate(t);
 267                 mdb.m_target = NULL;
 268         }
 269 
 270         mdb_dprintf(MDB_DBG_TGT, "t_destroy %s (%p)\n",
 271             t->t_module->mod_name, (void *)t);
 272 
 273         for (xdp = mdb_list_next(&t->t_xdlist); xdp != NULL; xdp = nxdp) {
 274                 nxdp = mdb_list_next(xdp);
 275                 mdb_list_delete(&t->t_xdlist, xdp);
 276                 mdb_free(xdp, sizeof (mdb_xdata_t));
 277         }
 278 
 279         mdb_tgt_sespec_idle_all(t, EBUSY, TRUE);
 280         (void) mdb_tgt_vespec_iter(t, tgt_delete_vespec, NULL);
 281         t->t_ops->t_destroy(t);
 282 
 283         mdb_list_delete(&mdb.m_tgtlist, t);
 284         mdb_free(t, sizeof (mdb_tgt_t));
 285 
 286         if (mdb.m_target == NULL)
 287                 mdb_tgt_activate(mdb_list_prev(&mdb.m_tgtlist));
 288 }
 289 
 290 void
 291 mdb_tgt_activate(mdb_tgt_t *t)
 292 {
 293         mdb_tgt_t *otgt = mdb.m_target;
 294 
 295         if (mdb.m_target != NULL) {
 296                 mdb_dprintf(MDB_DBG_TGT, "t_deactivate %s (%p)\n",
 297                     mdb.m_target->t_module->mod_name, (void *)mdb.m_target);
 298                 mdb.m_target->t_ops->t_deactivate(mdb.m_target);
 299         }
 300 
 301         if ((mdb.m_target = t) != NULL) {
 302                 const char *v = strstr(mdb.m_root, "%V");
 303 
 304                 mdb_dprintf(MDB_DBG_TGT, "t_activate %s (%p)\n",
 305                     t->t_module->mod_name, (void *)t);
 306 
 307                 /*
 308                  * If the root was explicitly set with -R and contains %V,
 309                  * expand it like a path.  If the resulting directory is
 310                  * not present, then replace %V with "latest" and re-evaluate.
 311                  */
 312                 if (v != NULL) {
 313                         char old_root[MAXPATHLEN];
 314                         const char **p;
 315 #ifndef _KMDB
 316                         struct stat s;
 317 #endif
 318                         size_t len;
 319 
 320                         p = mdb_path_alloc(mdb.m_root, &len);
 321                         (void) strcpy(old_root, mdb.m_root);
 322                         (void) strncpy(mdb.m_root, p[0], MAXPATHLEN);
 323                         mdb.m_root[MAXPATHLEN - 1] = '\0';
 324                         mdb_path_free(p, len);
 325 
 326 #ifndef _KMDB
 327                         if (stat(mdb.m_root, &s) == -1 && errno == ENOENT) {
 328                                 mdb.m_flags |= MDB_FL_LATEST;
 329                                 p = mdb_path_alloc(old_root, &len);
 330                                 (void) strncpy(mdb.m_root, p[0], MAXPATHLEN);
 331                                 mdb.m_root[MAXPATHLEN - 1] = '\0';
 332                                 mdb_path_free(p, len);
 333                         }
 334 #endif
 335                 }
 336 
 337                 /*
 338                  * Re-evaluate the macro and dmod paths now that we have the
 339                  * new target set and m_root figured out.
 340                  */
 341                 if (otgt == NULL) {
 342                         mdb_set_ipath(mdb.m_ipathstr);
 343                         mdb_set_lpath(mdb.m_lpathstr);
 344                 }
 345 
 346                 t->t_ops->t_activate(t);
 347         }
 348 }
 349 
 350 void
 351 mdb_tgt_periodic(mdb_tgt_t *t)
 352 {
 353         t->t_ops->t_periodic(t);
 354 }
 355 
 356 const char *
 357 mdb_tgt_name(mdb_tgt_t *t)
 358 {
 359         return (t->t_ops->t_name(t));
 360 }
 361 
 362 const char *
 363 mdb_tgt_isa(mdb_tgt_t *t)
 364 {
 365         return (t->t_ops->t_isa(t));
 366 }
 367 
 368 const char *
 369 mdb_tgt_platform(mdb_tgt_t *t)
 370 {
 371         return (t->t_ops->t_platform(t));
 372 }
 373 
 374 int
 375 mdb_tgt_uname(mdb_tgt_t *t, struct utsname *utsp)
 376 {
 377         return (t->t_ops->t_uname(t, utsp));
 378 }
 379 
 380 int
 381 mdb_tgt_dmodel(mdb_tgt_t *t)
 382 {
 383         return (t->t_ops->t_dmodel(t));
 384 }
 385 
 386 int
 387 mdb_tgt_auxv(mdb_tgt_t *t, const auxv_t **auxvp)
 388 {
 389         return (t->t_ops->t_auxv(t, auxvp));
 390 }
 391 
 392 ssize_t
 393 mdb_tgt_aread(mdb_tgt_t *t, mdb_tgt_as_t as,
 394     void *buf, size_t n, mdb_tgt_addr_t addr)
 395 {
 396         if (t->t_flags & MDB_TGT_F_ASIO)
 397                 return (t->t_ops->t_aread(t, as, buf, n, addr));
 398 
 399         switch ((uintptr_t)as) {
 400         case (uintptr_t)MDB_TGT_AS_VIRT:
 401                 return (t->t_ops->t_vread(t, buf, n, addr));
 402         case (uintptr_t)MDB_TGT_AS_PHYS:
 403                 return (t->t_ops->t_pread(t, buf, n, addr));
 404         case (uintptr_t)MDB_TGT_AS_FILE:
 405                 return (t->t_ops->t_fread(t, buf, n, addr));
 406         case (uintptr_t)MDB_TGT_AS_IO:
 407                 return (t->t_ops->t_ioread(t, buf, n, addr));
 408         }
 409         return (t->t_ops->t_aread(t, as, buf, n, addr));
 410 }
 411 
 412 ssize_t
 413 mdb_tgt_awrite(mdb_tgt_t *t, mdb_tgt_as_t as,
 414     const void *buf, size_t n, mdb_tgt_addr_t addr)
 415 {
 416         if (!(t->t_flags & MDB_TGT_F_RDWR))
 417                 return (set_errno(EMDB_TGTRDONLY));
 418 
 419         if (t->t_flags & MDB_TGT_F_ASIO)
 420                 return (t->t_ops->t_awrite(t, as, buf, n, addr));
 421 
 422         switch ((uintptr_t)as) {
 423         case (uintptr_t)MDB_TGT_AS_VIRT:
 424                 return (t->t_ops->t_vwrite(t, buf, n, addr));
 425         case (uintptr_t)MDB_TGT_AS_PHYS:
 426                 return (t->t_ops->t_pwrite(t, buf, n, addr));
 427         case (uintptr_t)MDB_TGT_AS_FILE:
 428                 return (t->t_ops->t_fwrite(t, buf, n, addr));
 429         case (uintptr_t)MDB_TGT_AS_IO:
 430                 return (t->t_ops->t_iowrite(t, buf, n, addr));
 431         }
 432         return (t->t_ops->t_awrite(t, as, buf, n, addr));
 433 }
 434 
 435 ssize_t
 436 mdb_tgt_vread(mdb_tgt_t *t, void *buf, size_t n, uintptr_t addr)
 437 {
 438         return (t->t_ops->t_vread(t, buf, n, addr));
 439 }
 440 
 441 ssize_t
 442 mdb_tgt_vwrite(mdb_tgt_t *t, const void *buf, size_t n, uintptr_t addr)
 443 {
 444         if (t->t_flags & MDB_TGT_F_RDWR)
 445                 return (t->t_ops->t_vwrite(t, buf, n, addr));
 446 
 447         return (set_errno(EMDB_TGTRDONLY));
 448 }
 449 
 450 ssize_t
 451 mdb_tgt_pread(mdb_tgt_t *t, void *buf, size_t n, physaddr_t addr)
 452 {
 453         return (t->t_ops->t_pread(t, buf, n, addr));
 454 }
 455 
 456 ssize_t
 457 mdb_tgt_pwrite(mdb_tgt_t *t, const void *buf, size_t n, physaddr_t addr)
 458 {
 459         if (t->t_flags & MDB_TGT_F_RDWR)
 460                 return (t->t_ops->t_pwrite(t, buf, n, addr));
 461 
 462         return (set_errno(EMDB_TGTRDONLY));
 463 }
 464 
 465 ssize_t
 466 mdb_tgt_fread(mdb_tgt_t *t, void *buf, size_t n, uintptr_t addr)
 467 {
 468         return (t->t_ops->t_fread(t, buf, n, addr));
 469 }
 470 
 471 ssize_t
 472 mdb_tgt_fwrite(mdb_tgt_t *t, const void *buf, size_t n, uintptr_t addr)
 473 {
 474         if (t->t_flags & MDB_TGT_F_RDWR)
 475                 return (t->t_ops->t_fwrite(t, buf, n, addr));
 476 
 477         return (set_errno(EMDB_TGTRDONLY));
 478 }
 479 
 480 ssize_t
 481 mdb_tgt_ioread(mdb_tgt_t *t, void *buf, size_t n, uintptr_t addr)
 482 {
 483         return (t->t_ops->t_ioread(t, buf, n, addr));
 484 }
 485 
 486 ssize_t
 487 mdb_tgt_iowrite(mdb_tgt_t *t, const void *buf, size_t n, uintptr_t addr)
 488 {
 489         if (t->t_flags & MDB_TGT_F_RDWR)
 490                 return (t->t_ops->t_iowrite(t, buf, n, addr));
 491 
 492         return (set_errno(EMDB_TGTRDONLY));
 493 }
 494 
 495 int
 496 mdb_tgt_vtop(mdb_tgt_t *t, mdb_tgt_as_t as, uintptr_t va, physaddr_t *pap)
 497 {
 498         return (t->t_ops->t_vtop(t, as, va, pap));
 499 }
 500 
 501 ssize_t
 502 mdb_tgt_readstr(mdb_tgt_t *t, mdb_tgt_as_t as, char *buf,
 503     size_t nbytes, mdb_tgt_addr_t addr)
 504 {
 505         ssize_t n, nread = mdb_tgt_aread(t, as, buf, nbytes, addr);
 506         char *p;
 507 
 508         if (nread >= 0) {
 509                 if ((p = memchr(buf, '\0', nread)) != NULL)
 510                         nread = (size_t)(p - buf);
 511                 goto done;
 512         }
 513 
 514         nread = 0;
 515         p = &buf[0];
 516 
 517         while (nread < nbytes && (n = mdb_tgt_aread(t, as, p, 1, addr)) == 1) {
 518                 if (*p == '\0')
 519                         return (nread);
 520                 nread++;
 521                 addr++;
 522                 p++;
 523         }
 524 
 525         if (nread == 0 && n == -1)
 526                 return (-1); /* If we can't even read a byte, return -1 */
 527 
 528 done:
 529         if (nbytes != 0)
 530                 buf[MIN(nread, nbytes - 1)] = '\0';
 531 
 532         return (nread);
 533 }
 534 
 535 ssize_t
 536 mdb_tgt_writestr(mdb_tgt_t *t, mdb_tgt_as_t as,
 537     const char *buf, mdb_tgt_addr_t addr)
 538 {
 539         ssize_t nwritten = mdb_tgt_awrite(t, as, buf, strlen(buf) + 1, addr);
 540         return (nwritten > 0 ? nwritten - 1 : nwritten);
 541 }
 542 
 543 int
 544 mdb_tgt_lookup_by_name(mdb_tgt_t *t, const char *obj,
 545     const char *name, GElf_Sym *symp, mdb_syminfo_t *sip)
 546 {
 547         mdb_syminfo_t info;
 548         GElf_Sym sym;
 549         uint_t id;
 550 
 551         if (name == NULL || t == NULL)
 552                 return (set_errno(EINVAL));
 553 
 554         if (obj == MDB_TGT_OBJ_EVERY &&
 555             mdb_gelf_symtab_lookup_by_name(mdb.m_prsym, name, &sym, &id) == 0) {
 556                 info.sym_table = MDB_TGT_PRVSYM;
 557                 info.sym_id = id;
 558                 goto found;
 559         }
 560 
 561         if (t->t_ops->t_lookup_by_name(t, obj, name, &sym, &info) == 0)
 562                 goto found;
 563 
 564         return (-1);
 565 
 566 found:
 567         if (symp != NULL)
 568                 *symp = sym;
 569         if (sip != NULL)
 570                 *sip = info;
 571         return (0);
 572 }
 573 
 574 int
 575 mdb_tgt_lookup_by_addr(mdb_tgt_t *t, uintptr_t addr, uint_t flags,
 576     char *buf, size_t len, GElf_Sym *symp, mdb_syminfo_t *sip)
 577 {
 578         mdb_syminfo_t info;
 579         GElf_Sym sym;
 580 
 581         if (t == NULL)
 582                 return (set_errno(EINVAL));
 583 
 584         if (t->t_ops->t_lookup_by_addr(t, addr, flags,
 585             buf, len, &sym, &info) == 0) {
 586                 if (symp != NULL)
 587                         *symp = sym;
 588                 if (sip != NULL)
 589                         *sip = info;
 590                 return (0);
 591         }
 592 
 593         return (-1);
 594 }
 595 
 596 /*
 597  * The mdb_tgt_lookup_by_scope function is a convenience routine for code that
 598  * wants to look up a scoped symbol name such as "object`symbol".  It is
 599  * implemented as a simple wrapper around mdb_tgt_lookup_by_name.  Note that
 600  * we split on the *last* occurrence of "`", so the object name itself may
 601  * contain additional scopes whose evaluation is left to the target.  This
 602  * allows targets to implement additional scopes, such as source files,
 603  * function names, link map identifiers, etc.
 604  */
 605 int
 606 mdb_tgt_lookup_by_scope(mdb_tgt_t *t, const char *s, GElf_Sym *symp,
 607     mdb_syminfo_t *sip)
 608 {
 609         const char *object = MDB_TGT_OBJ_EVERY;
 610         const char *name = s;
 611         char buf[MDB_TGT_SYM_NAMLEN];
 612 
 613         if (t == NULL)
 614                 return (set_errno(EINVAL));
 615 
 616         if (strchr(name, '`') != NULL) {
 617 
 618                 (void) strncpy(buf, s, sizeof (buf));
 619                 buf[sizeof (buf) - 1] = '\0';
 620                 name = buf;
 621 
 622                 if ((s = strrsplit(buf, '`')) != NULL) {
 623                         object = buf;
 624                         name = s;
 625                         if (*object == '\0')
 626                                 return (set_errno(EMDB_NOOBJ));
 627                         if (*name == '\0')
 628                                 return (set_errno(EMDB_NOSYM));
 629                 }
 630         }
 631 
 632         return (mdb_tgt_lookup_by_name(t, object, name, symp, sip));
 633 }
 634 
 635 int
 636 mdb_tgt_symbol_iter(mdb_tgt_t *t, const char *obj, uint_t which,
 637     uint_t type, mdb_tgt_sym_f *cb, void *p)
 638 {
 639         if ((which != MDB_TGT_SYMTAB && which != MDB_TGT_DYNSYM) ||
 640             (type & ~(MDB_TGT_BIND_ANY | MDB_TGT_TYPE_ANY)) != 0)
 641                 return (set_errno(EINVAL));
 642 
 643         return (t->t_ops->t_symbol_iter(t, obj, which, type, cb, p));
 644 }
 645 
 646 ssize_t
 647 mdb_tgt_readsym(mdb_tgt_t *t, mdb_tgt_as_t as, void *buf, size_t nbytes,
 648     const char *obj, const char *name)
 649 {
 650         GElf_Sym sym;
 651 
 652         if (mdb_tgt_lookup_by_name(t, obj, name, &sym, NULL) == 0)
 653                 return (mdb_tgt_aread(t, as, buf, nbytes, sym.st_value));
 654 
 655         return (-1);
 656 }
 657 
 658 ssize_t
 659 mdb_tgt_writesym(mdb_tgt_t *t, mdb_tgt_as_t as, const void *buf,
 660     size_t nbytes, const char *obj, const char *name)
 661 {
 662         GElf_Sym sym;
 663 
 664         if (mdb_tgt_lookup_by_name(t, obj, name, &sym, NULL) == 0)
 665                 return (mdb_tgt_awrite(t, as, buf, nbytes, sym.st_value));
 666 
 667         return (-1);
 668 }
 669 
 670 int
 671 mdb_tgt_mapping_iter(mdb_tgt_t *t, mdb_tgt_map_f *cb, void *p)
 672 {
 673         return (t->t_ops->t_mapping_iter(t, cb, p));
 674 }
 675 
 676 int
 677 mdb_tgt_object_iter(mdb_tgt_t *t, mdb_tgt_map_f *cb, void *p)
 678 {
 679         return (t->t_ops->t_object_iter(t, cb, p));
 680 }
 681 
 682 const mdb_map_t *
 683 mdb_tgt_addr_to_map(mdb_tgt_t *t, uintptr_t addr)
 684 {
 685         return (t->t_ops->t_addr_to_map(t, addr));
 686 }
 687 
 688 const mdb_map_t *
 689 mdb_tgt_name_to_map(mdb_tgt_t *t, const char *name)
 690 {
 691         return (t->t_ops->t_name_to_map(t, name));
 692 }
 693 
 694 struct ctf_file *
 695 mdb_tgt_addr_to_ctf(mdb_tgt_t *t, uintptr_t addr)
 696 {
 697         return (t->t_ops->t_addr_to_ctf(t, addr));
 698 }
 699 
 700 struct ctf_file *
 701 mdb_tgt_name_to_ctf(mdb_tgt_t *t, const char *name)
 702 {
 703         return (t->t_ops->t_name_to_ctf(t, name));
 704 }
 705 
 706 /*
 707  * Return the latest target status.  We just copy out our cached copy.  The
 708  * status only needs to change when the target is run, stepped, or continued.
 709  */
 710 int
 711 mdb_tgt_status(mdb_tgt_t *t, mdb_tgt_status_t *tsp)
 712 {
 713         uint_t dstop = (t->t_status.st_flags & MDB_TGT_DSTOP);
 714         uint_t istop = (t->t_status.st_flags & MDB_TGT_ISTOP);
 715         uint_t state = t->t_status.st_state;
 716 
 717         if (tsp == NULL)
 718                 return (set_errno(EINVAL));
 719 
 720         /*
 721          * If we're called with the address of the target's internal status,
 722          * then call down to update it; otherwise copy out the saved status.
 723          */
 724         if (tsp == &t->t_status && t->t_ops->t_status(t, &t->t_status) != 0)
 725                 return (-1); /* errno is set for us */
 726 
 727         /*
 728          * Assert that our state is valid before returning it.  The state must
 729          * be valid, and DSTOP and ISTOP cannot be set simultaneously.  ISTOP
 730          * is only valid when stopped.  DSTOP is only valid when running or
 731          * stopped.  If any test fails, abort the debugger.
 732          */
 733         if (state > MDB_TGT_LOST)
 734                 fail("invalid target state (%u)\n", state);
 735         if (state != MDB_TGT_STOPPED && istop)
 736                 fail("target state is (%u) and ISTOP is set\n", state);
 737         if (state != MDB_TGT_STOPPED && state != MDB_TGT_RUNNING && dstop)
 738                 fail("target state is (%u) and DSTOP is set\n", state);
 739         if (istop && dstop)
 740                 fail("target has ISTOP and DSTOP set simultaneously\n");
 741 
 742         if (tsp != &t->t_status)
 743                 bcopy(&t->t_status, tsp, sizeof (mdb_tgt_status_t));
 744 
 745         return (0);
 746 }
 747 
 748 /*
 749  * For the given sespec, scan its list of vespecs for ones that are marked
 750  * temporary and delete them.  We use the same method as vespec_delete below.
 751  */
 752 /*ARGSUSED*/
 753 void
 754 mdb_tgt_sespec_prune_one(mdb_tgt_t *t, mdb_sespec_t *sep)
 755 {
 756         mdb_vespec_t *vep, *nvep;
 757 
 758         for (vep = mdb_list_next(&sep->se_velist); vep; vep = nvep) {
 759                 nvep = mdb_list_next(vep);
 760 
 761                 if ((vep->ve_flags & (MDB_TGT_SPEC_DELETED |
 762                     MDB_TGT_SPEC_TEMPORARY)) == MDB_TGT_SPEC_TEMPORARY) {
 763                         vep->ve_flags |= MDB_TGT_SPEC_DELETED;
 764                         mdb_tgt_vespec_rele(t, vep);
 765                 }
 766         }
 767 }
 768 
 769 /*
 770  * Prune each sespec on the active list of temporary vespecs.  This function
 771  * is called, for example, after the target finishes a continue operation.
 772  */
 773 void
 774 mdb_tgt_sespec_prune_all(mdb_tgt_t *t)
 775 {
 776         mdb_sespec_t *sep, *nsep;
 777 
 778         for (sep = mdb_list_next(&t->t_active); sep != NULL; sep = nsep) {
 779                 nsep = mdb_list_next(sep);
 780                 mdb_tgt_sespec_prune_one(t, sep);
 781         }
 782 }
 783 
 784 /*
 785  * Transition the given sespec to the IDLE state.  We invoke the destructor,
 786  * and then move the sespec from the active list to the idle list.
 787  */
 788 void
 789 mdb_tgt_sespec_idle_one(mdb_tgt_t *t, mdb_sespec_t *sep, int reason)
 790 {
 791         ASSERT(sep->se_state != MDB_TGT_SPEC_IDLE);
 792 
 793         if (sep->se_state == MDB_TGT_SPEC_ARMED)
 794                 (void) sep->se_ops->se_disarm(t, sep);
 795 
 796         sep->se_ops->se_dtor(t, sep);
 797         sep->se_data = NULL;
 798 
 799         sep->se_state = MDB_TGT_SPEC_IDLE;
 800         sep->se_errno = reason;
 801 
 802         mdb_list_delete(&t->t_active, sep);
 803         mdb_list_append(&t->t_idle, sep);
 804 
 805         mdb_tgt_sespec_prune_one(t, sep);
 806 }
 807 
 808 /*
 809  * Transition each sespec on the active list to the IDLE state.  This function
 810  * is called, for example, after the target terminates execution.
 811  */
 812 void
 813 mdb_tgt_sespec_idle_all(mdb_tgt_t *t, int reason, int clear_matched)
 814 {
 815         mdb_sespec_t *sep, *nsep;
 816         mdb_vespec_t *vep;
 817 
 818         while ((sep = t->t_matched) != T_SE_END && clear_matched) {
 819                 for (vep = mdb_list_next(&sep->se_velist); vep != NULL; ) {
 820                         vep->ve_flags &= ~MDB_TGT_SPEC_MATCHED;
 821                         vep = mdb_list_next(vep);
 822                 }
 823 
 824                 t->t_matched = sep->se_matched;
 825                 sep->se_matched = NULL;
 826                 mdb_tgt_sespec_rele(t, sep);
 827         }
 828 
 829         for (sep = mdb_list_next(&t->t_active); sep != NULL; sep = nsep) {
 830                 nsep = mdb_list_next(sep);
 831                 mdb_tgt_sespec_idle_one(t, sep, reason);
 832         }
 833 }
 834 
 835 /*
 836  * Attempt to transition the given sespec from the IDLE to ACTIVE state.  We
 837  * do this by invoking se_ctor -- if this fails, we save the reason in se_errno
 838  * and return -1 with errno set.  One strange case we need to deal with here is
 839  * the possibility that a given vespec is sitting on the idle list with its
 840  * corresponding sespec, but it is actually a duplicate of another sespec on the
 841  * active list.  This can happen if the sespec is associated with a
 842  * MDB_TGT_SPEC_DISABLED vespec that was just enabled, and is now ready to be
 843  * activated.  A more interesting reason this situation might arise is the case
 844  * where a virtual address breakpoint is set at an address just mmap'ed by
 845  * dlmopen.  Since no symbol table information is available for this mapping
 846  * yet, a pre-existing deferred symbolic breakpoint may already exist for this
 847  * address, but it is on the idle list.  When the symbol table is ready and the
 848  * DLACTIVITY event occurs, we now discover that the virtual address obtained by
 849  * evaluating the symbolic breakpoint matches the explicit virtual address of
 850  * the active virtual breakpoint.  To resolve this conflict in either case, we
 851  * destroy the idle sespec, and attach its list of vespecs to the existing
 852  * active sespec.
 853  */
 854 int
 855 mdb_tgt_sespec_activate_one(mdb_tgt_t *t, mdb_sespec_t *sep)
 856 {
 857         mdb_vespec_t *vep = mdb_list_next(&sep->se_velist);
 858 
 859         mdb_vespec_t *nvep;
 860         mdb_sespec_t *dup;
 861 
 862         ASSERT(sep->se_state == MDB_TGT_SPEC_IDLE);
 863         ASSERT(vep != NULL);
 864 
 865         if (vep->ve_flags & MDB_TGT_SPEC_DISABLED)
 866                 return (0); /* cannot be activated while disabled bit set */
 867 
 868         /*
 869          * First search the active list for an existing, duplicate sespec to
 870          * handle the special case described above.
 871          */
 872         for (dup = mdb_list_next(&t->t_active); dup; dup = mdb_list_next(dup)) {
 873                 if (dup->se_ops == sep->se_ops &&
 874                     dup->se_ops->se_secmp(t, dup, vep->ve_args)) {
 875                         ASSERT(dup != sep);
 876                         break;
 877                 }
 878         }
 879 
 880         /*
 881          * If a duplicate is found, destroy the existing, idle sespec, and
 882          * attach all of its vespecs to the duplicate sespec.
 883          */
 884         if (dup != NULL) {
 885                 for (vep = mdb_list_next(&sep->se_velist); vep; vep = nvep) {
 886                         mdb_dprintf(MDB_DBG_TGT, "merge [ %d ] to sespec %p\n",
 887                             vep->ve_id, (void *)dup);
 888 
 889                         if (dup->se_matched != NULL)
 890                                 vep->ve_flags |= MDB_TGT_SPEC_MATCHED;
 891 
 892                         nvep = mdb_list_next(vep);
 893                         vep->ve_hits = 0;
 894 
 895                         mdb_list_delete(&sep->se_velist, vep);
 896                         mdb_tgt_sespec_rele(t, sep);
 897 
 898                         mdb_list_append(&dup->se_velist, vep);
 899                         mdb_tgt_sespec_hold(t, dup);
 900                         vep->ve_se = dup;
 901                 }
 902 
 903                 mdb_dprintf(MDB_DBG_TGT, "merged idle sespec %p with %p\n",
 904                     (void *)sep, (void *)dup);
 905                 return (0);
 906         }
 907 
 908         /*
 909          * If no duplicate is found, call the sespec's constructor.  If this
 910          * is successful, move the sespec to the active list.
 911          */
 912         if (sep->se_ops->se_ctor(t, sep, vep->ve_args) < 0) {
 913                 sep->se_errno = errno;
 914                 sep->se_data = NULL;
 915 
 916                 return (-1);
 917         }
 918 
 919         for (vep = mdb_list_next(&sep->se_velist); vep; vep = nvep) {
 920                 nvep = mdb_list_next(vep);
 921                 vep->ve_hits = 0;
 922         }
 923         mdb_list_delete(&t->t_idle, sep);
 924         mdb_list_append(&t->t_active, sep);
 925         sep->se_state = MDB_TGT_SPEC_ACTIVE;
 926         sep->se_errno = 0;
 927 
 928         return (0);
 929 }
 930 
 931 /*
 932  * Transition each sespec on the idle list to the ACTIVE state.  This function
 933  * is called, for example, after the target's t_run() function returns.  If
 934  * the se_ctor() function fails, the specifier is not yet applicable; it will
 935  * remain on the idle list and can be activated later.
 936  *
 937  * Returns 1 if there weren't any unexpected activation failures; 0 if there
 938  * were.
 939  */
 940 int
 941 mdb_tgt_sespec_activate_all(mdb_tgt_t *t)
 942 {
 943         mdb_sespec_t *sep, *nsep;
 944         int rc = 1;
 945 
 946         for (sep = mdb_list_next(&t->t_idle); sep != NULL; sep = nsep) {
 947                 nsep = mdb_list_next(sep);
 948 
 949                 if (mdb_tgt_sespec_activate_one(t, sep) < 0 &&
 950                     sep->se_errno != EMDB_NOOBJ)
 951                         rc = 0;
 952         }
 953 
 954         return (rc);
 955 }
 956 
 957 /*
 958  * Transition the given sespec to the ARMED state.  Note that we attempt to
 959  * re-arm sespecs previously in the ERROR state.  If se_arm() fails the sespec
 960  * transitions to the ERROR state but stays on the active list.
 961  */
 962 void
 963 mdb_tgt_sespec_arm_one(mdb_tgt_t *t, mdb_sespec_t *sep)
 964 {
 965         ASSERT(sep->se_state != MDB_TGT_SPEC_IDLE);
 966 
 967         if (sep->se_state == MDB_TGT_SPEC_ARMED)
 968                 return; /* do not arm sespecs more than once */
 969 
 970         if (sep->se_ops->se_arm(t, sep) == -1) {
 971                 sep->se_state = MDB_TGT_SPEC_ERROR;
 972                 sep->se_errno = errno;
 973         } else {
 974                 sep->se_state = MDB_TGT_SPEC_ARMED;
 975                 sep->se_errno = 0;
 976         }
 977 }
 978 
 979 /*
 980  * Transition each sespec on the active list (except matched specs) to the
 981  * ARMED state.  This function is called prior to continuing the target.
 982  */
 983 void
 984 mdb_tgt_sespec_arm_all(mdb_tgt_t *t)
 985 {
 986         mdb_sespec_t *sep, *nsep;
 987 
 988         for (sep = mdb_list_next(&t->t_active); sep != NULL; sep = nsep) {
 989                 nsep = mdb_list_next(sep);
 990                 if (sep->se_matched == NULL)
 991                         mdb_tgt_sespec_arm_one(t, sep);
 992         }
 993 }
 994 
 995 /*
 996  * Transition each sespec on the active list that is in the ARMED state to
 997  * the ACTIVE state.  If se_disarm() fails, the sespec is transitioned to
 998  * the ERROR state instead, but left on the active list.
 999  */
1000 static void
1001 tgt_disarm_sespecs(mdb_tgt_t *t)
1002 {
1003         mdb_sespec_t *sep;
1004 
1005         for (sep = mdb_list_next(&t->t_active); sep; sep = mdb_list_next(sep)) {
1006                 if (sep->se_state != MDB_TGT_SPEC_ARMED)
1007                         continue; /* do not disarm if in ERROR state */
1008 
1009                 if (sep->se_ops->se_disarm(t, sep) == -1) {
1010                         sep->se_state = MDB_TGT_SPEC_ERROR;
1011                         sep->se_errno = errno;
1012                 } else {
1013                         sep->se_state = MDB_TGT_SPEC_ACTIVE;
1014                         sep->se_errno = 0;
1015                 }
1016         }
1017 }
1018 
1019 /*
1020  * Determine if the software event that triggered the most recent stop matches
1021  * any of the active event specifiers.  If 'all' is TRUE, we consider all
1022  * sespecs in our search.   If 'all' is FALSE, we only consider ARMED sespecs.
1023  * If we successfully match an event, we add it to the t_matched list and
1024  * place an additional hold on it.
1025  */
1026 static mdb_sespec_t *
1027 tgt_match_sespecs(mdb_tgt_t *t, int all)
1028 {
1029         mdb_sespec_t *sep;
1030 
1031         for (sep = mdb_list_next(&t->t_active); sep; sep = mdb_list_next(sep)) {
1032                 if (all == FALSE && sep->se_state != MDB_TGT_SPEC_ARMED)
1033                         continue; /* restrict search to ARMED sespecs */
1034 
1035                 if (sep->se_state != MDB_TGT_SPEC_ERROR &&
1036                     sep->se_ops->se_match(t, sep, &t->t_status)) {
1037                         mdb_dprintf(MDB_DBG_TGT, "match se %p\n", (void *)sep);
1038                         mdb_tgt_sespec_hold(t, sep);
1039                         sep->se_matched = t->t_matched;
1040                         t->t_matched = sep;
1041                 }
1042         }
1043 
1044         return (t->t_matched);
1045 }
1046 
1047 /*
1048  * This function provides the low-level target continue algorithm.  We proceed
1049  * in three phases: (1) we arm the active sespecs, except the specs matched at
1050  * the time we last stopped, (2) we call se_cont() on any matched sespecs to
1051  * step over these event transitions, and then arm the corresponding sespecs,
1052  * and (3) we call the appropriate low-level continue routine.  Once the
1053  * target stops again, we determine which sespecs were matched, and invoke the
1054  * appropriate vespec callbacks and perform other vespec maintenance.
1055  */
1056 static int
1057 tgt_continue(mdb_tgt_t *t, mdb_tgt_status_t *tsp,
1058     int (*t_cont)(mdb_tgt_t *, mdb_tgt_status_t *))
1059 {
1060         mdb_var_t *hitv = mdb_nv_lookup(&mdb.m_nv, "hits");
1061         uintptr_t pc = t->t_status.st_pc;
1062         int error = 0;
1063 
1064         mdb_sespec_t *sep, *nsep, *matched;
1065         mdb_vespec_t *vep, *nvep;
1066         uintptr_t addr;
1067 
1068         uint_t cbits = 0;       /* union of pending continue bits */
1069         uint_t ncont = 0;       /* # of callbacks that requested cont */
1070         uint_t n = 0;           /* # of callbacks */
1071 
1072         /*
1073          * If the target is undead, dead, or lost, we no longer allow continue.
1074          * This effectively forces the user to use ::kill or ::run after death.
1075          */
1076         if (t->t_status.st_state == MDB_TGT_UNDEAD)
1077                 return (set_errno(EMDB_TGTZOMB));
1078         if (t->t_status.st_state == MDB_TGT_DEAD)
1079                 return (set_errno(EMDB_TGTCORE));
1080         if (t->t_status.st_state == MDB_TGT_LOST)
1081                 return (set_errno(EMDB_TGTLOST));
1082 
1083         /*
1084          * If any of single-step, step-over, or step-out is pending, it takes
1085          * precedence over an explicit or pending continue, because these are
1086          * all different specialized forms of continue.
1087          */
1088         if (t->t_flags & MDB_TGT_F_STEP)
1089                 t_cont = t->t_ops->t_step;
1090         else if (t->t_flags & MDB_TGT_F_NEXT)
1091                 t_cont = t->t_ops->t_step;
1092         else if (t->t_flags & MDB_TGT_F_STEP_OUT)
1093                 t_cont = t->t_ops->t_cont;
1094 
1095         /*
1096          * To handle step-over, we ask the target to find the address past the
1097          * next control transfer instruction.  If an address is found, we plant
1098          * a temporary breakpoint there and continue; otherwise just step.
1099          */
1100         if ((t->t_flags & MDB_TGT_F_NEXT) && !(t->t_flags & MDB_TGT_F_STEP)) {
1101                 if (t->t_ops->t_next(t, &addr) == -1 || mdb_tgt_add_vbrkpt(t,
1102                     addr, MDB_TGT_SPEC_HIDDEN | MDB_TGT_SPEC_TEMPORARY,
1103                     no_se_f, NULL) == 0) {
1104                         mdb_dprintf(MDB_DBG_TGT, "next falling back to step: "
1105                             "%s\n", mdb_strerror(errno));
1106                 } else
1107                         t_cont = t->t_ops->t_cont;
1108         }
1109 
1110         /*
1111          * To handle step-out, we ask the target to find the return address of
1112          * the current frame, plant a temporary breakpoint there, and continue.
1113          */
1114         if (t->t_flags & MDB_TGT_F_STEP_OUT) {
1115                 if (t->t_ops->t_step_out(t, &addr) == -1)
1116                         return (-1); /* errno is set for us */
1117 
1118                 if (mdb_tgt_add_vbrkpt(t, addr, MDB_TGT_SPEC_HIDDEN |
1119                     MDB_TGT_SPEC_TEMPORARY, no_se_f, NULL) == 0)
1120                         return (-1); /* errno is set for us */
1121         }
1122 
1123         (void) mdb_signal_block(SIGHUP);
1124         (void) mdb_signal_block(SIGTERM);
1125         mdb_intr_disable();
1126 
1127         t->t_flags &= ~T_CONT_BITS;
1128         t->t_flags |= MDB_TGT_F_BUSY;
1129         mdb_tgt_sespec_arm_all(t);
1130 
1131         ASSERT(t->t_matched != NULL);
1132         matched = t->t_matched;
1133         t->t_matched = T_SE_END;
1134 
1135         if (mdb.m_term != NULL)
1136                 IOP_SUSPEND(mdb.m_term);
1137 
1138         /*
1139          * Iterate over the matched sespec list, performing autostop processing
1140          * and clearing the matched bit for each associated vespec.  We then
1141          * invoke each sespec's se_cont callback in order to continue past
1142          * the corresponding event.  If the matched list has more than one
1143          * sespec, we assume that the se_cont callbacks are non-interfering.
1144          */
1145         for (sep = matched; sep != T_SE_END; sep = sep->se_matched) {
1146                 for (vep = mdb_list_next(&sep->se_velist); vep != NULL; ) {
1147                         if ((vep->ve_flags & MDB_TGT_SPEC_AUTOSTOP) &&
1148                             (vep->ve_limit && vep->ve_hits == vep->ve_limit))
1149                                 vep->ve_hits = 0;
1150 
1151                         vep->ve_flags &= ~MDB_TGT_SPEC_MATCHED;
1152                         vep = mdb_list_next(vep);
1153                 }
1154 
1155                 if (sep->se_ops->se_cont(t, sep, &t->t_status) == -1) {
1156                         error = errno ? errno : -1;
1157                         tgt_disarm_sespecs(t);
1158                         break;
1159                 }
1160 
1161                 if (!(t->t_status.st_flags & MDB_TGT_ISTOP)) {
1162                         tgt_disarm_sespecs(t);
1163                         if (t->t_status.st_state == MDB_TGT_UNDEAD)
1164                                 mdb_tgt_sespec_idle_all(t, EMDB_TGTZOMB, TRUE);
1165                         else if (t->t_status.st_state == MDB_TGT_LOST)
1166                                 mdb_tgt_sespec_idle_all(t, EMDB_TGTLOST, TRUE);
1167                         break;
1168                 }
1169         }
1170 
1171         /*
1172          * Clear the se_matched field for each matched sespec, and drop the
1173          * reference count since the sespec is no longer on the matched list.
1174          */
1175         for (sep = matched; sep != T_SE_END; sep = nsep) {
1176                 nsep = sep->se_matched;
1177                 sep->se_matched = NULL;
1178                 mdb_tgt_sespec_rele(t, sep);
1179         }
1180 
1181         /*
1182          * If the matched list was non-empty, see if we hit another event while
1183          * performing se_cont() processing.  If so, don't bother continuing any
1184          * further.  If not, arm the sespecs on the old matched list by calling
1185          * mdb_tgt_sespec_arm_all() again and then continue by calling t_cont.
1186          */
1187         if (matched != T_SE_END) {
1188                 if (error != 0 || !(t->t_status.st_flags & MDB_TGT_ISTOP))
1189                         goto out; /* abort now if se_cont() failed */
1190 
1191                 if ((t->t_matched = tgt_match_sespecs(t, FALSE)) != T_SE_END) {
1192                         tgt_disarm_sespecs(t);
1193                         goto out;
1194                 }
1195 
1196                 mdb_tgt_sespec_arm_all(t);
1197         }
1198 
1199         if (t_cont != t->t_ops->t_step || pc == t->t_status.st_pc) {
1200                 if (t_cont(t, &t->t_status) != 0)
1201                         error = errno ? errno : -1;
1202         }
1203 
1204         tgt_disarm_sespecs(t);
1205 
1206         if (t->t_flags & MDB_TGT_F_UNLOAD)
1207                 longjmp(mdb.m_frame->f_pcb, MDB_ERR_QUIT);
1208 
1209         if (t->t_status.st_state == MDB_TGT_UNDEAD)
1210                 mdb_tgt_sespec_idle_all(t, EMDB_TGTZOMB, TRUE);
1211         else if (t->t_status.st_state == MDB_TGT_LOST)
1212                 mdb_tgt_sespec_idle_all(t, EMDB_TGTLOST, TRUE);
1213         else if (t->t_status.st_flags & MDB_TGT_ISTOP)
1214                 t->t_matched = tgt_match_sespecs(t, TRUE);
1215 out:
1216         if (mdb.m_term != NULL)
1217                 IOP_RESUME(mdb.m_term);
1218 
1219         (void) mdb_signal_unblock(SIGTERM);
1220         (void) mdb_signal_unblock(SIGHUP);
1221         mdb_intr_enable();
1222 
1223         for (sep = t->t_matched; sep != T_SE_END; sep = sep->se_matched) {
1224                 /*
1225                  * When we invoke a ve_callback, it may in turn request that the
1226                  * target continue immediately after callback processing is
1227                  * complete.  We only allow this to occur if *all* callbacks
1228                  * agree to continue.  To implement this behavior, we keep a
1229                  * count (ncont) of such requests, and only apply the cumulative
1230                  * continue bits (cbits) to the target if ncont is equal to the
1231                  * total number of callbacks that are invoked (n).
1232                  */
1233                 for (vep = mdb_list_next(&sep->se_velist);
1234                     vep != NULL; vep = nvep, n++) {
1235                         /*
1236                          * Place an extra hold on the current vespec and pick
1237                          * up the next pointer before invoking the callback: we
1238                          * must be prepared for the vespec to be deleted or
1239                          * moved to a different list by the callback.
1240                          */
1241                         mdb_tgt_vespec_hold(t, vep);
1242                         nvep = mdb_list_next(vep);
1243 
1244                         vep->ve_flags |= MDB_TGT_SPEC_MATCHED;
1245                         vep->ve_hits++;
1246 
1247                         mdb_nv_set_value(mdb.m_dot, t->t_status.st_pc);
1248                         mdb_nv_set_value(hitv, vep->ve_hits);
1249 
1250                         ASSERT((t->t_flags & T_CONT_BITS) == 0);
1251                         vep->ve_callback(t, vep->ve_id, vep->ve_data);
1252 
1253                         ncont += (t->t_flags & T_CONT_BITS) != 0;
1254                         cbits |= (t->t_flags & T_CONT_BITS);
1255                         t->t_flags &= ~T_CONT_BITS;
1256 
1257                         if (vep->ve_limit && vep->ve_hits == vep->ve_limit) {
1258                                 if (vep->ve_flags & MDB_TGT_SPEC_AUTODEL)
1259                                         (void) mdb_tgt_vespec_delete(t,
1260                                             vep->ve_id);
1261                                 else if (vep->ve_flags & MDB_TGT_SPEC_AUTODIS)
1262                                         (void) mdb_tgt_vespec_disable(t,
1263                                             vep->ve_id);
1264                         }
1265 
1266                         if (vep->ve_limit && vep->ve_hits < vep->ve_limit) {
1267                                 if (vep->ve_flags & MDB_TGT_SPEC_AUTOSTOP)
1268                                         (void) mdb_tgt_continue(t, NULL);
1269                         }
1270 
1271                         mdb_tgt_vespec_rele(t, vep);
1272                 }
1273         }
1274 
1275         if (t->t_matched != T_SE_END && ncont == n)
1276                 t->t_flags |= cbits; /* apply continues (see above) */
1277 
1278         mdb_tgt_sespec_prune_all(t);
1279 
1280         t->t_status.st_flags &= ~MDB_TGT_BUSY;
1281         t->t_flags &= ~MDB_TGT_F_BUSY;
1282 
1283         if (tsp != NULL)
1284                 bcopy(&t->t_status, tsp, sizeof (mdb_tgt_status_t));
1285 
1286         if (error != 0)
1287                 return (set_errno(error));
1288 
1289         return (0);
1290 }
1291 
1292 /*
1293  * This function is the common glue that connects the high-level target layer
1294  * continue functions (e.g. step and cont below) with the low-level
1295  * tgt_continue() function above.  Since vespec callbacks may perform any
1296  * actions, including attempting to continue the target itself, we must be
1297  * prepared to be called while the target is still marked F_BUSY.  In this
1298  * case, we just set a pending bit and return.  When we return from the call
1299  * to tgt_continue() that made us busy into the tgt_request_continue() call
1300  * that is still on the stack, we will loop around and call tgt_continue()
1301  * again.  This allows vespecs to continue the target without recursion.
1302  */
1303 static int
1304 tgt_request_continue(mdb_tgt_t *t, mdb_tgt_status_t *tsp, uint_t tflag,
1305     int (*t_cont)(mdb_tgt_t *, mdb_tgt_status_t *))
1306 {
1307         mdb_tgt_spec_desc_t desc;
1308         mdb_sespec_t *sep;
1309         char buf[BUFSIZ];
1310         int status;
1311 
1312         if (t->t_flags & MDB_TGT_F_BUSY) {
1313                 t->t_flags |= tflag;
1314                 return (0);
1315         }
1316 
1317         do {
1318                 status = tgt_continue(t, tsp, t_cont);
1319         } while (status == 0 && (t->t_flags & T_CONT_BITS));
1320 
1321         if (status == 0) {
1322                 for (sep = t->t_matched; sep != T_SE_END;
1323                     sep = sep->se_matched) {
1324                         mdb_vespec_t *vep;
1325 
1326                         for (vep = mdb_list_next(&sep->se_velist); vep;
1327                             vep = mdb_list_next(vep)) {
1328                                 if (vep->ve_flags & MDB_TGT_SPEC_SILENT)
1329                                         continue;
1330                                 warn("%s\n", sep->se_ops->se_info(t, sep,
1331                                     vep, &desc, buf, sizeof (buf)));
1332                         }
1333                 }
1334 
1335                 mdb_callb_fire(MDB_CALLB_STCHG);
1336         }
1337 
1338         t->t_flags &= ~T_CONT_BITS;
1339         return (status);
1340 }
1341 
1342 /*
1343  * Restart target execution: we rely upon the underlying target implementation
1344  * to do most of the work for us.  In particular, we assume it will properly
1345  * preserve the state of our event lists if the run fails for some reason,
1346  * and that it will reset all events to the IDLE state if the run succeeds.
1347  * If it is successful, we attempt to activate all of the idle sespecs.  The
1348  * t_run() operation is defined to leave the target stopped at the earliest
1349  * possible point in execution, and then return control to the debugger,
1350  * awaiting a step or continue operation to set it running again.
1351  */
1352 int
1353 mdb_tgt_run(mdb_tgt_t *t, int argc, const mdb_arg_t *argv)
1354 {
1355         int i;
1356 
1357         for (i = 0; i < argc; i++) {
1358                 if (argv->a_type != MDB_TYPE_STRING)
1359                         return (set_errno(EINVAL));
1360         }
1361 
1362         if (t->t_ops->t_run(t, argc, argv) == -1)
1363                 return (-1); /* errno is set for us */
1364 
1365         t->t_flags &= ~T_CONT_BITS;
1366         (void) mdb_tgt_sespec_activate_all(t);
1367 
1368         if (mdb.m_term != NULL)
1369                 IOP_CTL(mdb.m_term, MDB_IOC_CTTY, NULL);
1370 
1371         return (0);
1372 }
1373 
1374 int
1375 mdb_tgt_step(mdb_tgt_t *t, mdb_tgt_status_t *tsp)
1376 {
1377         return (tgt_request_continue(t, tsp, MDB_TGT_F_STEP, t->t_ops->t_step));
1378 }
1379 
1380 int
1381 mdb_tgt_step_out(mdb_tgt_t *t, mdb_tgt_status_t *tsp)
1382 {
1383         t->t_flags |= MDB_TGT_F_STEP_OUT; /* set flag even if tgt not busy */
1384         return (tgt_request_continue(t, tsp, 0, t->t_ops->t_cont));
1385 }
1386 
1387 int
1388 mdb_tgt_next(mdb_tgt_t *t, mdb_tgt_status_t *tsp)
1389 {
1390         t->t_flags |= MDB_TGT_F_NEXT; /* set flag even if tgt not busy */
1391         return (tgt_request_continue(t, tsp, 0, t->t_ops->t_step));
1392 }
1393 
1394 int
1395 mdb_tgt_continue(mdb_tgt_t *t, mdb_tgt_status_t *tsp)
1396 {
1397         return (tgt_request_continue(t, tsp, MDB_TGT_F_CONT, t->t_ops->t_cont));
1398 }
1399 
1400 int
1401 mdb_tgt_signal(mdb_tgt_t *t, int sig)
1402 {
1403         return (t->t_ops->t_signal(t, sig));
1404 }
1405 
1406 void *
1407 mdb_tgt_vespec_data(mdb_tgt_t *t, int vid)
1408 {
1409         mdb_vespec_t *vep = mdb_tgt_vespec_lookup(t, vid);
1410 
1411         if (vep == NULL) {
1412                 (void) set_errno(EMDB_NOSESPEC);
1413                 return (NULL);
1414         }
1415 
1416         return (vep->ve_data);
1417 }
1418 
1419 /*
1420  * Return a structured description and comment string for the given vespec.
1421  * We fill in the common information from the vespec, and then call down to
1422  * the underlying sespec to provide the comment string and modify any
1423  * event type-specific information.
1424  */
1425 char *
1426 mdb_tgt_vespec_info(mdb_tgt_t *t, int vid, mdb_tgt_spec_desc_t *sp,
1427     char *buf, size_t nbytes)
1428 {
1429         mdb_vespec_t *vep = mdb_tgt_vespec_lookup(t, vid);
1430 
1431         mdb_tgt_spec_desc_t desc;
1432         mdb_sespec_t *sep;
1433 
1434         if (vep == NULL) {
1435                 if (sp != NULL)
1436                         bzero(sp, sizeof (mdb_tgt_spec_desc_t));
1437                 (void) set_errno(EMDB_NOSESPEC);
1438                 return (NULL);
1439         }
1440 
1441         if (sp == NULL)
1442                 sp = &desc;
1443 
1444         sep = vep->ve_se;
1445 
1446         sp->spec_id = vep->ve_id;
1447         sp->spec_flags = vep->ve_flags;
1448         sp->spec_hits = vep->ve_hits;
1449         sp->spec_limit = vep->ve_limit;
1450         sp->spec_state = sep->se_state;
1451         sp->spec_errno = sep->se_errno;
1452         sp->spec_base = NULL;
1453         sp->spec_size = 0;
1454         sp->spec_data = vep->ve_data;
1455 
1456         return (sep->se_ops->se_info(t, sep, vep, sp, buf, nbytes));
1457 }
1458 
1459 /*
1460  * Qsort callback for sorting vespecs by VID, used below.
1461  */
1462 static int
1463 tgt_vespec_compare(const mdb_vespec_t **lp, const mdb_vespec_t **rp)
1464 {
1465         return ((*lp)->ve_id - (*rp)->ve_id);
1466 }
1467 
1468 /*
1469  * Iterate over all vespecs and call the specified callback function with the
1470  * corresponding VID and caller data pointer.  We want the callback function
1471  * to see a consistent, sorted snapshot of the vespecs, and allow the callback
1472  * to take actions such as deleting the vespec itself, so we cannot simply
1473  * iterate over the lists.  Instead, we pre-allocate an array of vespec
1474  * pointers, fill it in and place an additional hold on each vespec, and then
1475  * sort it.  After the callback has been executed on each vespec in the
1476  * sorted array, we remove our hold and free the temporary array.
1477  */
1478 int
1479 mdb_tgt_vespec_iter(mdb_tgt_t *t, mdb_tgt_vespec_f *func, void *p)
1480 {
1481         mdb_vespec_t **veps, **vepp, **vend;
1482         mdb_vespec_t *vep, *nvep;
1483         mdb_sespec_t *sep;
1484 
1485         uint_t vecnt = t->t_vecnt;
1486 
1487         veps = mdb_alloc(sizeof (mdb_vespec_t *) * vecnt, UM_SLEEP);
1488         vend = veps + vecnt;
1489         vepp = veps;
1490 
1491         for (sep = mdb_list_next(&t->t_active); sep; sep = mdb_list_next(sep)) {
1492                 for (vep = mdb_list_next(&sep->se_velist); vep; vep = nvep) {
1493                         mdb_tgt_vespec_hold(t, vep);
1494                         nvep = mdb_list_next(vep);
1495                         *vepp++ = vep;
1496                 }
1497         }
1498 
1499         for (sep = mdb_list_next(&t->t_idle); sep; sep = mdb_list_next(sep)) {
1500                 for (vep = mdb_list_next(&sep->se_velist); vep; vep = nvep) {
1501                         mdb_tgt_vespec_hold(t, vep);
1502                         nvep = mdb_list_next(vep);
1503                         *vepp++ = vep;
1504                 }
1505         }
1506 
1507         if (vepp != vend) {
1508                 fail("target has %u vespecs on list but vecnt shows %u\n",
1509                     (uint_t)(vepp - veps), vecnt);
1510         }
1511 
1512         qsort(veps, vecnt, sizeof (mdb_vespec_t *),
1513             (int (*)(const void *, const void *))tgt_vespec_compare);
1514 
1515         for (vepp = veps; vepp < vend; vepp++) {
1516                 if (func(t, p, (*vepp)->ve_id, (*vepp)->ve_data) != 0)
1517                         break;
1518         }
1519 
1520         for (vepp = veps; vepp < vend; vepp++)
1521                 mdb_tgt_vespec_rele(t, *vepp);
1522 
1523         mdb_free(veps, sizeof (mdb_vespec_t *) * vecnt);
1524         return (0);
1525 }
1526 
1527 /*
1528  * Reset the vespec flags, match limit, and callback data to the specified
1529  * values.  We silently correct invalid parameters, except for the VID.
1530  * The caller is required to query the existing properties and pass back
1531  * the existing values for any properties that should not be modified.
1532  * If the callback data is modified, the caller is responsible for cleaning
1533  * up any state associated with the previous value.
1534  */
1535 int
1536 mdb_tgt_vespec_modify(mdb_tgt_t *t, int id, uint_t flags,
1537     uint_t limit, void *data)
1538 {
1539         mdb_vespec_t *vep = mdb_tgt_vespec_lookup(t, id);
1540 
1541         if (vep == NULL)
1542                 return (set_errno(EMDB_NOSESPEC));
1543 
1544         /*
1545          * If the value of the MDB_TGT_SPEC_DISABLED bit is changing, call the
1546          * appropriate vespec function to do the enable/disable work.
1547          */
1548         if ((flags & MDB_TGT_SPEC_DISABLED) !=
1549             (vep->ve_flags & MDB_TGT_SPEC_DISABLED)) {
1550                 if (flags & MDB_TGT_SPEC_DISABLED)
1551                         (void) mdb_tgt_vespec_disable(t, id);
1552                 else
1553                         (void) mdb_tgt_vespec_enable(t, id);
1554         }
1555 
1556         /*
1557          * Make that only one MDB_TGT_SPEC_AUTO* bit is set in the new flags
1558          * value: extra bits are cleared according to order of precedence.
1559          */
1560         if (flags & MDB_TGT_SPEC_AUTOSTOP)
1561                 flags &= ~(MDB_TGT_SPEC_AUTODEL | MDB_TGT_SPEC_AUTODIS);
1562         else if (flags & MDB_TGT_SPEC_AUTODEL)
1563                 flags &= ~MDB_TGT_SPEC_AUTODIS;
1564 
1565         /*
1566          * The TEMPORARY property always takes precedence over STICKY.
1567          */
1568         if (flags & MDB_TGT_SPEC_TEMPORARY)
1569                 flags &= ~MDB_TGT_SPEC_STICKY;
1570 
1571         /*
1572          * If any MDB_TGT_SPEC_AUTO* bits are changing, reset the hit count
1573          * back to zero and clear all of the old auto bits.
1574          */
1575         if ((flags & T_AUTO_BITS) != (vep->ve_flags & T_AUTO_BITS)) {
1576                 vep->ve_flags &= ~T_AUTO_BITS;
1577                 vep->ve_hits = 0;
1578         }
1579 
1580         vep->ve_flags = (vep->ve_flags & T_IMPL_BITS) | (flags & ~T_IMPL_BITS);
1581         vep->ve_data = data;
1582 
1583         /*
1584          * If any MDB_TGT_SPEC_AUTO* flags are set, make sure the limit is at
1585          * least one.  If none are set, reset it back to zero.
1586          */
1587         if (vep->ve_flags & T_AUTO_BITS)
1588                 vep->ve_limit = MAX(limit, 1);
1589         else
1590                 vep->ve_limit = 0;
1591 
1592         /*
1593          * As a convenience, we allow the caller to specify SPEC_DELETED in
1594          * the flags field as indication that the event should be deleted.
1595          */
1596         if (flags & MDB_TGT_SPEC_DELETED)
1597                 (void) mdb_tgt_vespec_delete(t, id);
1598 
1599         return (0);
1600 }
1601 
1602 /*
1603  * Remove the user disabled bit from the specified vespec, and attempt to
1604  * activate the underlying sespec and move it to the active list if possible.
1605  */
1606 int
1607 mdb_tgt_vespec_enable(mdb_tgt_t *t, int id)
1608 {
1609         mdb_vespec_t *vep = mdb_tgt_vespec_lookup(t, id);
1610 
1611         if (vep == NULL)
1612                 return (set_errno(EMDB_NOSESPEC));
1613 
1614         if (vep->ve_flags & MDB_TGT_SPEC_DISABLED) {
1615                 ASSERT(mdb_list_next(vep) == NULL);
1616                 vep->ve_flags &= ~MDB_TGT_SPEC_DISABLED;
1617                 if (mdb_tgt_sespec_activate_one(t, vep->ve_se) < 0)
1618                         return (-1); /* errno is set for us */
1619         }
1620 
1621         return (0);
1622 }
1623 
1624 /*
1625  * Set the user disabled bit on the specified vespec, and move it to the idle
1626  * list.  If the vespec is not alone with its sespec or if it is a currently
1627  * matched event, we must always create a new idle sespec and move the vespec
1628  * there.  If the vespec was alone and active, we can simply idle the sespec.
1629  */
1630 int
1631 mdb_tgt_vespec_disable(mdb_tgt_t *t, int id)
1632 {
1633         mdb_vespec_t *vep = mdb_tgt_vespec_lookup(t, id);
1634         mdb_sespec_t *sep;
1635 
1636         if (vep == NULL)
1637                 return (set_errno(EMDB_NOSESPEC));
1638 
1639         if (vep->ve_flags & MDB_TGT_SPEC_DISABLED)
1640                 return (0); /* already disabled */
1641 
1642         if (mdb_list_prev(vep) != NULL || mdb_list_next(vep) != NULL ||
1643             vep->ve_se->se_matched != NULL) {
1644 
1645                 sep = mdb_tgt_sespec_insert(t, vep->ve_se->se_ops, &t->t_idle);
1646 
1647                 mdb_list_delete(&vep->ve_se->se_velist, vep);
1648                 mdb_tgt_sespec_rele(t, vep->ve_se);
1649 
1650                 mdb_list_append(&sep->se_velist, vep);
1651                 mdb_tgt_sespec_hold(t, sep);
1652 
1653                 vep->ve_flags &= ~MDB_TGT_SPEC_MATCHED;
1654                 vep->ve_se = sep;
1655 
1656         } else if (vep->ve_se->se_state != MDB_TGT_SPEC_IDLE)
1657                 mdb_tgt_sespec_idle_one(t, vep->ve_se, EMDB_SPECDIS);
1658 
1659         vep->ve_flags |= MDB_TGT_SPEC_DISABLED;
1660         return (0);
1661 }
1662 
1663 /*
1664  * Delete the given vespec.  We use the MDB_TGT_SPEC_DELETED flag to ensure that
1665  * multiple calls to mdb_tgt_vespec_delete to not attempt to decrement the
1666  * reference count on the vespec more than once.  This is because the vespec
1667  * may remain referenced if it is currently held by another routine (e.g.
1668  * vespec_iter), and so the user could attempt to delete it more than once
1669  * since it reference count will be >= 2 prior to the first delete call.
1670  */
1671 int
1672 mdb_tgt_vespec_delete(mdb_tgt_t *t, int id)
1673 {
1674         mdb_vespec_t *vep = mdb_tgt_vespec_lookup(t, id);
1675 
1676         if (vep == NULL)
1677                 return (set_errno(EMDB_NOSESPEC));
1678 
1679         if (vep->ve_flags & MDB_TGT_SPEC_DELETED)
1680                 return (set_errno(EBUSY));
1681 
1682         vep->ve_flags |= MDB_TGT_SPEC_DELETED;
1683         mdb_tgt_vespec_rele(t, vep);
1684         return (0);
1685 }
1686 
1687 int
1688 mdb_tgt_add_vbrkpt(mdb_tgt_t *t, uintptr_t addr,
1689     int spec_flags, mdb_tgt_se_f *func, void *p)
1690 {
1691         return (t->t_ops->t_add_vbrkpt(t, addr, spec_flags, func, p));
1692 }
1693 
1694 int
1695 mdb_tgt_add_sbrkpt(mdb_tgt_t *t, const char *symbol,
1696     int spec_flags, mdb_tgt_se_f *func, void *p)
1697 {
1698         return (t->t_ops->t_add_sbrkpt(t, symbol, spec_flags, func, p));
1699 }
1700 
1701 int
1702 mdb_tgt_add_pwapt(mdb_tgt_t *t, physaddr_t pa, size_t n, uint_t flags,
1703     int spec_flags, mdb_tgt_se_f *func, void *p)
1704 {
1705         if ((flags & ~MDB_TGT_WA_RWX) || flags == 0) {
1706                 (void) set_errno(EINVAL);
1707                 return (0);
1708         }
1709 
1710         if (pa + n < pa) {
1711                 (void) set_errno(EMDB_WPRANGE);
1712                 return (0);
1713         }
1714 
1715         return (t->t_ops->t_add_pwapt(t, pa, n, flags, spec_flags, func, p));
1716 }
1717 
1718 int
1719 mdb_tgt_add_vwapt(mdb_tgt_t *t, uintptr_t va, size_t n, uint_t flags,
1720     int spec_flags, mdb_tgt_se_f *func, void *p)
1721 {
1722         if ((flags & ~MDB_TGT_WA_RWX) || flags == 0) {
1723                 (void) set_errno(EINVAL);
1724                 return (0);
1725         }
1726 
1727         if (va + n < va) {
1728                 (void) set_errno(EMDB_WPRANGE);
1729                 return (0);
1730         }
1731 
1732         return (t->t_ops->t_add_vwapt(t, va, n, flags, spec_flags, func, p));
1733 }
1734 
1735 int
1736 mdb_tgt_add_iowapt(mdb_tgt_t *t, uintptr_t addr, size_t n, uint_t flags,
1737     int spec_flags, mdb_tgt_se_f *func, void *p)
1738 {
1739         if ((flags & ~MDB_TGT_WA_RWX) || flags == 0) {
1740                 (void) set_errno(EINVAL);
1741                 return (0);
1742         }
1743 
1744         if (addr + n < addr) {
1745                 (void) set_errno(EMDB_WPRANGE);
1746                 return (0);
1747         }
1748 
1749         return (t->t_ops->t_add_iowapt(t, addr, n, flags, spec_flags, func, p));
1750 }
1751 
1752 int
1753 mdb_tgt_add_sysenter(mdb_tgt_t *t, int sysnum,
1754     int spec_flags, mdb_tgt_se_f *func, void *p)
1755 {
1756         return (t->t_ops->t_add_sysenter(t, sysnum, spec_flags, func, p));
1757 }
1758 
1759 int
1760 mdb_tgt_add_sysexit(mdb_tgt_t *t, int sysnum,
1761     int spec_flags, mdb_tgt_se_f *func, void *p)
1762 {
1763         return (t->t_ops->t_add_sysexit(t, sysnum, spec_flags, func, p));
1764 }
1765 
1766 int
1767 mdb_tgt_add_signal(mdb_tgt_t *t, int sig,
1768     int spec_flags, mdb_tgt_se_f *func, void *p)
1769 {
1770         return (t->t_ops->t_add_signal(t, sig, spec_flags, func, p));
1771 }
1772 
1773 int
1774 mdb_tgt_add_fault(mdb_tgt_t *t, int flt,
1775     int spec_flags, mdb_tgt_se_f *func, void *p)
1776 {
1777         return (t->t_ops->t_add_fault(t, flt, spec_flags, func, p));
1778 }
1779 
1780 int
1781 mdb_tgt_getareg(mdb_tgt_t *t, mdb_tgt_tid_t tid,
1782     const char *rname, mdb_tgt_reg_t *rp)
1783 {
1784         return (t->t_ops->t_getareg(t, tid, rname, rp));
1785 }
1786 
1787 int
1788 mdb_tgt_putareg(mdb_tgt_t *t, mdb_tgt_tid_t tid,
1789     const char *rname, mdb_tgt_reg_t r)
1790 {
1791         return (t->t_ops->t_putareg(t, tid, rname, r));
1792 }
1793 
1794 int
1795 mdb_tgt_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gregs,
1796     mdb_tgt_stack_f *cb, void *p)
1797 {
1798         return (t->t_ops->t_stack_iter(t, gregs, cb, p));
1799 }
1800 
1801 int
1802 mdb_tgt_xdata_iter(mdb_tgt_t *t, mdb_tgt_xdata_f *func, void *private)
1803 {
1804         mdb_xdata_t *xdp;
1805 
1806         for (xdp = mdb_list_next(&t->t_xdlist); xdp; xdp = mdb_list_next(xdp)) {
1807                 if (func(private, xdp->xd_name, xdp->xd_desc,
1808                     xdp->xd_copy(t, NULL, 0)) != 0)
1809                         break;
1810         }
1811 
1812         return (0);
1813 }
1814 
1815 ssize_t
1816 mdb_tgt_getxdata(mdb_tgt_t *t, const char *name, void *buf, size_t nbytes)
1817 {
1818         mdb_xdata_t *xdp;
1819 
1820         for (xdp = mdb_list_next(&t->t_xdlist); xdp; xdp = mdb_list_next(xdp)) {
1821                 if (strcmp(xdp->xd_name, name) == 0)
1822                         return (xdp->xd_copy(t, buf, nbytes));
1823         }
1824 
1825         return (set_errno(ENODATA));
1826 }
1827 
1828 long
1829 mdb_tgt_notsup()
1830 {
1831         return (set_errno(EMDB_TGTNOTSUP));
1832 }
1833 
1834 void *
1835 mdb_tgt_null()
1836 {
1837         (void) set_errno(EMDB_TGTNOTSUP);
1838         return (NULL);
1839 }
1840 
1841 long
1842 mdb_tgt_nop()
1843 {
1844         return (0L);
1845 }
1846 
1847 int
1848 mdb_tgt_xdata_insert(mdb_tgt_t *t, const char *name, const char *desc,
1849     ssize_t (*copy)(mdb_tgt_t *, void *, size_t))
1850 {
1851         mdb_xdata_t *xdp;
1852 
1853         for (xdp = mdb_list_next(&t->t_xdlist); xdp; xdp = mdb_list_next(xdp)) {
1854                 if (strcmp(xdp->xd_name, name) == 0)
1855                         return (set_errno(EMDB_XDEXISTS));
1856         }
1857 
1858         xdp = mdb_alloc(sizeof (mdb_xdata_t), UM_SLEEP);
1859         mdb_list_append(&t->t_xdlist, xdp);
1860 
1861         xdp->xd_name = name;
1862         xdp->xd_desc = desc;
1863         xdp->xd_copy = copy;
1864 
1865         return (0);
1866 }
1867 
1868 int
1869 mdb_tgt_xdata_delete(mdb_tgt_t *t, const char *name)
1870 {
1871         mdb_xdata_t *xdp;
1872 
1873         for (xdp = mdb_list_next(&t->t_xdlist); xdp; xdp = mdb_list_next(xdp)) {
1874                 if (strcmp(xdp->xd_name, name) == 0) {
1875                         mdb_list_delete(&t->t_xdlist, xdp);
1876                         mdb_free(xdp, sizeof (mdb_xdata_t));
1877                         return (0);
1878                 }
1879         }
1880 
1881         return (set_errno(EMDB_NOXD));
1882 }
1883 
1884 int
1885 mdb_tgt_sym_match(const GElf_Sym *sym, uint_t mask)
1886 {
1887 #if STT_NUM != (STT_TLS + 1)
1888 #error "STT_NUM has grown. update mdb_tgt_sym_match()"
1889 #endif
1890 
1891         uchar_t s_bind = GELF_ST_BIND(sym->st_info);
1892         uchar_t s_type = GELF_ST_TYPE(sym->st_info);
1893 
1894         /*
1895          * In case you haven't already guessed, this relies on the bitmask
1896          * used by <mdb/mdb_target.h> and <libproc.h> for encoding symbol
1897          * type and binding matching the order of STB and STT constants
1898          * in <sys/elf.h>.  Changes to ELF must maintain binary
1899          * compatibility, so I think this is reasonably fair game.
1900          */
1901         if (s_bind < STB_NUM && s_type < STT_NUM) {
1902                 uint_t type = (1 << (s_type + 8)) | (1 << s_bind);
1903                 return ((type & ~mask) == 0);
1904         }
1905 
1906         return (0); /* Unknown binding or type; fail to match */
1907 }
1908 
1909 void
1910 mdb_tgt_elf_export(mdb_gelf_file_t *gf)
1911 {
1912         GElf_Xword d = 0, t = 0;
1913         GElf_Addr b = 0, e = 0;
1914         uint32_t m = 0;
1915         mdb_var_t *v;
1916 
1917         /*
1918          * Reset legacy adb variables based on the specified ELF object file
1919          * provided by the target.  We define these variables:
1920          *
1921          * b - the address of the data segment (first writeable Phdr)
1922          * d - the size of the data segment
1923          * e - the address of the entry point
1924          * m - the magic number identifying the file
1925          * t - the address of the text segment (first executable Phdr)
1926          */
1927         if (gf != NULL) {
1928                 const GElf_Phdr *text = NULL, *data = NULL;
1929                 size_t i;
1930 
1931                 e = gf->gf_ehdr.e_entry;
1932                 bcopy(&gf->gf_ehdr.e_ident[EI_MAG0], &m, sizeof (m));
1933 
1934                 for (i = 0; i < gf->gf_npload; i++) {
1935                         if (text == NULL && (gf->gf_phdrs[i].p_flags & PF_X))
1936                                 text = &gf->gf_phdrs[i];
1937                         if (data == NULL && (gf->gf_phdrs[i].p_flags & PF_W))
1938                                 data = &gf->gf_phdrs[i];
1939                 }
1940 
1941                 if (text != NULL)
1942                         t = text->p_memsz;
1943                 if (data != NULL) {
1944                         b = data->p_vaddr;
1945                         d = data->p_memsz;
1946                 }
1947         }
1948 
1949         if ((v = mdb_nv_lookup(&mdb.m_nv, "b")) != NULL)
1950                 mdb_nv_set_value(v, b);
1951         if ((v = mdb_nv_lookup(&mdb.m_nv, "d")) != NULL)
1952                 mdb_nv_set_value(v, d);
1953         if ((v = mdb_nv_lookup(&mdb.m_nv, "e")) != NULL)
1954                 mdb_nv_set_value(v, e);
1955         if ((v = mdb_nv_lookup(&mdb.m_nv, "m")) != NULL)
1956                 mdb_nv_set_value(v, m);
1957         if ((v = mdb_nv_lookup(&mdb.m_nv, "t")) != NULL)
1958                 mdb_nv_set_value(v, t);
1959 }
1960 
1961 /*ARGSUSED*/
1962 void
1963 mdb_tgt_sespec_hold(mdb_tgt_t *t, mdb_sespec_t *sep)
1964 {
1965         sep->se_refs++;
1966         ASSERT(sep->se_refs != 0);
1967 }
1968 
1969 void
1970 mdb_tgt_sespec_rele(mdb_tgt_t *t, mdb_sespec_t *sep)
1971 {
1972         ASSERT(sep->se_refs != 0);
1973 
1974         if (--sep->se_refs == 0) {
1975                 mdb_dprintf(MDB_DBG_TGT, "destroying sespec %p\n", (void *)sep);
1976                 ASSERT(mdb_list_next(&sep->se_velist) == NULL);
1977 
1978                 if (sep->se_state != MDB_TGT_SPEC_IDLE) {
1979                         sep->se_ops->se_dtor(t, sep);
1980                         mdb_list_delete(&t->t_active, sep);
1981                 } else
1982                         mdb_list_delete(&t->t_idle, sep);
1983 
1984                 mdb_free(sep, sizeof (mdb_sespec_t));
1985         }
1986 }
1987 
1988 mdb_sespec_t *
1989 mdb_tgt_sespec_insert(mdb_tgt_t *t, const mdb_se_ops_t *ops, mdb_list_t *list)
1990 {
1991         mdb_sespec_t *sep = mdb_zalloc(sizeof (mdb_sespec_t), UM_SLEEP);
1992 
1993         if (list == &t->t_active)
1994                 sep->se_state = MDB_TGT_SPEC_ACTIVE;
1995         else
1996                 sep->se_state = MDB_TGT_SPEC_IDLE;
1997 
1998         mdb_list_append(list, sep);
1999         sep->se_ops = ops;
2000         return (sep);
2001 }
2002 
2003 mdb_sespec_t *
2004 mdb_tgt_sespec_lookup_active(mdb_tgt_t *t, const mdb_se_ops_t *ops, void *args)
2005 {
2006         mdb_sespec_t *sep;
2007 
2008         for (sep = mdb_list_next(&t->t_active); sep; sep = mdb_list_next(sep)) {
2009                 if (sep->se_ops == ops && sep->se_ops->se_secmp(t, sep, args))
2010                         break;
2011         }
2012 
2013         return (sep);
2014 }
2015 
2016 mdb_sespec_t *
2017 mdb_tgt_sespec_lookup_idle(mdb_tgt_t *t, const mdb_se_ops_t *ops, void *args)
2018 {
2019         mdb_sespec_t *sep;
2020 
2021         for (sep = mdb_list_next(&t->t_idle); sep; sep = mdb_list_next(sep)) {
2022                 if (sep->se_ops == ops && sep->se_ops->se_vecmp(t,
2023                     mdb_list_next(&sep->se_velist), args))
2024                         break;
2025         }
2026 
2027         return (sep);
2028 }
2029 
2030 /*ARGSUSED*/
2031 void
2032 mdb_tgt_vespec_hold(mdb_tgt_t *t, mdb_vespec_t *vep)
2033 {
2034         vep->ve_refs++;
2035         ASSERT(vep->ve_refs != 0);
2036 }
2037 
2038 void
2039 mdb_tgt_vespec_rele(mdb_tgt_t *t, mdb_vespec_t *vep)
2040 {
2041         ASSERT(vep->ve_refs != 0);
2042 
2043         if (--vep->ve_refs == 0) {
2044                 /*
2045                  * Remove this vespec from the sespec's velist and decrement
2046                  * the reference count on the sespec.
2047                  */
2048                 mdb_list_delete(&vep->ve_se->se_velist, vep);
2049                 mdb_tgt_sespec_rele(t, vep->ve_se);
2050 
2051                 /*
2052                  * If we are deleting the most recently assigned VID, reset
2053                  * t_vepos or t_veneg as appropriate to re-use that number.
2054                  * This could be enhanced to re-use any free number by
2055                  * maintaining a bitmap or hash of the allocated IDs.
2056                  */
2057                 if (vep->ve_id > 0 && t->t_vepos == vep->ve_id + 1)
2058                         t->t_vepos = vep->ve_id;
2059                 else if (vep->ve_id < 0 && t->t_veneg == -vep->ve_id + 1)
2060                         t->t_veneg = -vep->ve_id;
2061 
2062                 /*
2063                  * Call the destructor to clean up ve_args, and then free
2064                  * the actual vespec structure.
2065                  */
2066                 vep->ve_dtor(vep);
2067                 mdb_free(vep, sizeof (mdb_vespec_t));
2068 
2069                 ASSERT(t->t_vecnt != 0);
2070                 t->t_vecnt--;
2071         }
2072 }
2073 
2074 int
2075 mdb_tgt_vespec_insert(mdb_tgt_t *t, const mdb_se_ops_t *ops, int flags,
2076     mdb_tgt_se_f *func, void *data, void *args, void (*dtor)(mdb_vespec_t *))
2077 {
2078         mdb_vespec_t *vep = mdb_zalloc(sizeof (mdb_vespec_t), UM_SLEEP);
2079 
2080         int id, mult, *seqp;
2081         mdb_sespec_t *sep;
2082 
2083         /*
2084          * Make that only one MDB_TGT_SPEC_AUTO* bit is set in the new flags
2085          * value: extra bits are cleared according to order of precedence.
2086          */
2087         if (flags & MDB_TGT_SPEC_AUTOSTOP)
2088                 flags &= ~(MDB_TGT_SPEC_AUTODEL | MDB_TGT_SPEC_AUTODIS);
2089         else if (flags & MDB_TGT_SPEC_AUTODEL)
2090                 flags &= ~MDB_TGT_SPEC_AUTODIS;
2091 
2092         /*
2093          * The TEMPORARY property always takes precedence over STICKY.
2094          */
2095         if (flags & MDB_TGT_SPEC_TEMPORARY)
2096                 flags &= ~MDB_TGT_SPEC_STICKY;
2097 
2098         /*
2099          * Find a matching sespec or create a new one on the appropriate list.
2100          * We always create a new sespec if the vespec is created disabled.
2101          */
2102         if (flags & MDB_TGT_SPEC_DISABLED)
2103                 sep = mdb_tgt_sespec_insert(t, ops, &t->t_idle);
2104         else if ((sep = mdb_tgt_sespec_lookup_active(t, ops, args)) == NULL &&
2105             (sep = mdb_tgt_sespec_lookup_idle(t, ops, args)) == NULL)
2106                 sep = mdb_tgt_sespec_insert(t, ops, &t->t_active);
2107 
2108         /*
2109          * Generate a new ID for the vespec.  Increasing positive integers are
2110          * assigned to visible vespecs; decreasing negative integers are
2111          * assigned to hidden vespecs.  The target saves our most recent choice.
2112          */
2113         if (flags & MDB_TGT_SPEC_INTERNAL) {
2114                 seqp = &t->t_veneg;
2115                 mult = -1;
2116         } else {
2117                 seqp = &t->t_vepos;
2118                 mult = 1;
2119         }
2120 
2121         id = *seqp;
2122 
2123         while (mdb_tgt_vespec_lookup(t, id * mult) != NULL)
2124                 id = MAX(id + 1, 1);
2125 
2126         *seqp = MAX(id + 1, 1);
2127 
2128         vep->ve_id = id * mult;
2129         vep->ve_flags = flags & ~(MDB_TGT_SPEC_MATCHED | MDB_TGT_SPEC_DELETED);
2130         vep->ve_se = sep;
2131         vep->ve_callback = func;
2132         vep->ve_data = data;
2133         vep->ve_args = args;
2134         vep->ve_dtor = dtor;
2135 
2136         mdb_list_append(&sep->se_velist, vep);
2137         mdb_tgt_sespec_hold(t, sep);
2138 
2139         mdb_tgt_vespec_hold(t, vep);
2140         t->t_vecnt++;
2141 
2142         /*
2143          * If this vespec is the first reference to the sespec and it's active,
2144          * then it is newly created and we should attempt to initialize it.
2145          * If se_ctor fails, then move the sespec back to the idle list.
2146          */
2147         if (sep->se_refs == 1 && sep->se_state == MDB_TGT_SPEC_ACTIVE &&
2148             sep->se_ops->se_ctor(t, sep, vep->ve_args) == -1) {
2149 
2150                 mdb_list_delete(&t->t_active, sep);
2151                 mdb_list_append(&t->t_idle, sep);
2152 
2153                 sep->se_state = MDB_TGT_SPEC_IDLE;
2154                 sep->se_errno = errno;
2155                 sep->se_data = NULL;
2156         }
2157 
2158         /*
2159          * If the sespec is active and the target is currently running (because
2160          * we grabbed it using PGRAB_NOSTOP), then go ahead and attempt to arm
2161          * the sespec so it will take effect immediately.
2162          */
2163         if (sep->se_state == MDB_TGT_SPEC_ACTIVE &&
2164             t->t_status.st_state == MDB_TGT_RUNNING)
2165                 mdb_tgt_sespec_arm_one(t, sep);
2166 
2167         mdb_dprintf(MDB_DBG_TGT, "inserted [ %d ] sep=%p refs=%u state=%d\n",
2168             vep->ve_id, (void *)sep, sep->se_refs, sep->se_state);
2169 
2170         return (vep->ve_id);
2171 }
2172 
2173 /*
2174  * Search the target's active, idle, and disabled lists for the vespec matching
2175  * the specified VID, and return a pointer to it, or NULL if no match is found.
2176  */
2177 mdb_vespec_t *
2178 mdb_tgt_vespec_lookup(mdb_tgt_t *t, int vid)
2179 {
2180         mdb_sespec_t *sep;
2181         mdb_vespec_t *vep;
2182 
2183         if (vid == 0)
2184                 return (NULL); /* 0 is never a valid VID */
2185 
2186         for (sep = mdb_list_next(&t->t_active); sep; sep = mdb_list_next(sep)) {
2187                 for (vep = mdb_list_next(&sep->se_velist); vep;
2188                     vep = mdb_list_next(vep)) {
2189                         if (vep->ve_id == vid)
2190                                 return (vep);
2191                 }
2192         }
2193 
2194         for (sep = mdb_list_next(&t->t_idle); sep; sep = mdb_list_next(sep)) {
2195                 for (vep = mdb_list_next(&sep->se_velist); vep;
2196                     vep = mdb_list_next(vep)) {
2197                         if (vep->ve_id == vid)
2198                                 return (vep);
2199                 }
2200         }
2201 
2202         return (NULL);
2203 }
2204 
2205 /*ARGSUSED*/
2206 void
2207 no_ve_dtor(mdb_vespec_t *vep)
2208 {
2209         /* default destructor does nothing */
2210 }
2211 
2212 /*ARGSUSED*/
2213 void
2214 no_se_f(mdb_tgt_t *t, int vid, void *data)
2215 {
2216         /* default callback does nothing */
2217 }
2218 
2219 /*ARGSUSED*/
2220 void
2221 no_se_dtor(mdb_tgt_t *t, mdb_sespec_t *sep)
2222 {
2223         /* default destructor does nothing */
2224 }
2225 
2226 /*ARGSUSED*/
2227 int
2228 no_se_secmp(mdb_tgt_t *t, mdb_sespec_t *sep, void *args)
2229 {
2230         return (sep->se_data == args);
2231 }
2232 
2233 /*ARGSUSED*/
2234 int
2235 no_se_vecmp(mdb_tgt_t *t, mdb_vespec_t *vep, void *args)
2236 {
2237         return (vep->ve_args == args);
2238 }
2239 
2240 /*ARGSUSED*/
2241 int
2242 no_se_arm(mdb_tgt_t *t, mdb_sespec_t *sep)
2243 {
2244         return (0); /* return success */
2245 }
2246 
2247 /*ARGSUSED*/
2248 int
2249 no_se_disarm(mdb_tgt_t *t, mdb_sespec_t *sep)
2250 {
2251         return (0); /* return success */
2252 }
2253 
2254 /*ARGSUSED*/
2255 int
2256 no_se_cont(mdb_tgt_t *t, mdb_sespec_t *sep, mdb_tgt_status_t *tsp)
2257 {
2258         if (tsp != &t->t_status)
2259                 bcopy(&t->t_status, tsp, sizeof (mdb_tgt_status_t));
2260 
2261         return (0); /* return success */
2262 }
2263 
2264 int
2265 mdb_tgt_register_dcmds(mdb_tgt_t *t, const mdb_dcmd_t *dcp, int flags)
2266 {
2267         int fail = 0;
2268 
2269         for (; dcp->dc_name != NULL; dcp++) {
2270                 if (mdb_module_add_dcmd(t->t_module, dcp, flags) == -1) {
2271                         warn("failed to add dcmd %s", dcp->dc_name);
2272                         fail++;
2273                 }
2274         }
2275 
2276         return (fail > 0 ? -1 : 0);
2277 }
2278 
2279 int
2280 mdb_tgt_register_walkers(mdb_tgt_t *t, const mdb_walker_t *wp, int flags)
2281 {
2282         int fail = 0;
2283 
2284         for (; wp->walk_name != NULL; wp++) {
2285                 if (mdb_module_add_walker(t->t_module, wp, flags) == -1) {
2286                         warn("failed to add walk %s", wp->walk_name);
2287                         fail++;
2288                 }
2289         }
2290 
2291         return (fail > 0 ? -1 : 0);
2292 }
2293 
2294 void
2295 mdb_tgt_register_regvars(mdb_tgt_t *t, const mdb_tgt_regdesc_t *rdp,
2296     const mdb_nv_disc_t *disc, int flags)
2297 {
2298         for (; rdp->rd_name != NULL; rdp++) {
2299                 if (!(rdp->rd_flags & MDB_TGT_R_EXPORT))
2300                         continue; /* Don't export register as a variable */
2301 
2302                 if (rdp->rd_flags & MDB_TGT_R_RDONLY)
2303                         flags |= MDB_NV_RDONLY;
2304 
2305                 (void) mdb_nv_insert(&mdb.m_nv, rdp->rd_name, disc,
2306                     (uintptr_t)t, MDB_NV_PERSIST | flags);
2307         }
2308 }