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 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * User Process Target
  29  *
  30  * The user process target is invoked when the -u or -p command-line options
  31  * are used, or when an ELF executable file or ELF core file is specified on
  32  * the command-line.  This target is also selected by default when no target
  33  * options are present.  In this case, it defaults the executable name to
  34  * "a.out".  If no process or core file is currently attached, the target
  35  * functions as a kind of virtual /dev/zero (in accordance with adb(1)
  36  * semantics); reads from the virtual address space return zeroes and writes
  37  * fail silently.  The proc target itself is designed as a wrapper around the
  38  * services provided by libproc.so: t->t_pshandle is set to the struct
  39  * ps_prochandle pointer returned as a handle by libproc.  The target also
  40  * opens the executable file itself using the MDB GElf services, for
  41  * interpreting the .symtab and .dynsym if no libproc handle has been
  42  * initialized, and for handling i/o to and from the object file.  Currently,
  43  * the only ISA-dependent portions of the proc target are the $r and ::fpregs
  44  * dcmds, the callbacks for t_next() and t_step_out(), and the list of named
  45  * registers; these are linked in from the proc_isadep.c file for each ISA and
  46  * called from the common code in this file.
  47  *
  48  * The user process target implements complete user process control using the
  49  * facilities provided by libproc.so.  The MDB execution control model and
  50  * an overview of software event management is described in mdb_target.c.  The
  51  * proc target implements breakpoints by replacing the instruction of interest
  52  * with a trap instruction, and then restoring the original instruction to step
  53  * over the breakpoint.  The idea of replacing program text with instructions
  54  * that transfer control to the debugger dates back as far as 1951 [1].  When
  55  * the target stops, we replace each breakpoint with the original instruction
  56  * as part of the disarm operation.  This means that no special processing is
  57  * required for t_vread() because the instrumented instructions will never be
  58  * seen by the debugger once the target stops.  Some debuggers have improved
  59  * start/stop performance by leaving breakpoint traps in place and then
  60  * handling a read from a breakpoint address as a special case.  Although this
  61  * improves efficiency for a source-level debugger, it runs somewhat contrary
  62  * to the philosophy of the low-level debugger.  Since we remove the
  63  * instructions, users can apply other external debugging tools to the process
  64  * once it has stopped (e.g. the proc(1) tools) and not be misled by MDB
  65  * instrumentation.  The tracing of faults, signals, system calls, and
  66  * watchpoints and general process inspection is implemented directly using
  67  * the mechanisms provided by /proc, as described originally in [2] and [3].
  68  *
  69  * References
  70  *
  71  * [1] S. Gill, "The Diagnosis Of Mistakes In Programmes on the EDSAC",
  72  *     Proceedings of the Royal Society Series A Mathematical and Physical
  73  *     Sciences, Cambridge University Press, 206(1087), May 1951, pp. 538-554.
  74  *
  75  * [2] T.J. Killian, "Processes as Files", Proceedings of the USENIX Association
  76  *     Summer Conference, Salt Lake City, June 1984, pp. 203-207.
  77  *
  78  * [3] Roger Faulkner and Ron Gomes, "The Process File System and Process
  79  *     Model in UNIX System V", Proceedings of the USENIX Association
  80  *     Winter Conference, Dallas, January 1991, pp. 243-252.
  81  */
  82 
  83 #include <mdb/mdb_proc.h>
  84 #include <mdb/mdb_disasm.h>
  85 #include <mdb/mdb_signal.h>
  86 #include <mdb/mdb_string.h>
  87 #include <mdb/mdb_module.h>
  88 #include <mdb/mdb_debug.h>
  89 #include <mdb/mdb_conf.h>
  90 #include <mdb/mdb_err.h>
  91 #include <mdb/mdb_types.h>
  92 #include <mdb/mdb.h>
  93 
  94 #include <sys/utsname.h>
  95 #include <sys/wait.h>
  96 #include <sys/stat.h>
  97 #include <termio.h>
  98 #include <signal.h>
  99 #include <stdio_ext.h>
 100 #include <stdlib.h>
 101 #include <string.h>
 102 
 103 #define PC_FAKE         -1UL                    /* illegal pc value unequal 0 */
 104 
 105 static const char PT_EXEC_PATH[] = "a.out";     /* Default executable */
 106 static const char PT_CORE_PATH[] = "core";      /* Default core file */
 107 
 108 static const pt_ptl_ops_t proc_lwp_ops;
 109 static const pt_ptl_ops_t proc_tdb_ops;
 110 static const mdb_se_ops_t proc_brkpt_ops;
 111 static const mdb_se_ops_t proc_wapt_ops;
 112 
 113 static int pt_setrun(mdb_tgt_t *, mdb_tgt_status_t *, int);
 114 static void pt_activate_common(mdb_tgt_t *);
 115 static mdb_tgt_vespec_f pt_ignore_sig;
 116 static mdb_tgt_se_f pt_fork;
 117 static mdb_tgt_se_f pt_exec;
 118 
 119 static int pt_lookup_by_name_thr(mdb_tgt_t *, const char *,
 120     const char *, GElf_Sym *, mdb_syminfo_t *, mdb_tgt_tid_t);
 121 static int tlsbase(mdb_tgt_t *, mdb_tgt_tid_t, Lmid_t, const char *,
 122     psaddr_t *);
 123 
 124 /*
 125  * The Perror_printf() function interposes on the default, empty libproc
 126  * definition.  It will be called to report additional information on complex
 127  * errors, such as a corrupt core file.  We just pass the args to vwarn.
 128  */
 129 /*ARGSUSED*/
 130 void
 131 Perror_printf(struct ps_prochandle *P, const char *format, ...)
 132 {
 133         va_list alist;
 134 
 135         va_start(alist, format);
 136         vwarn(format, alist);
 137         va_end(alist);
 138 }
 139 
 140 /*
 141  * Open the specified i/o backend as the a.out executable file, and attempt to
 142  * load its standard and dynamic symbol tables.  Note that if mdb_gelf_create
 143  * succeeds, io is assigned to p_fio and is automatically held by gelf_create.
 144  */
 145 static mdb_gelf_file_t *
 146 pt_open_aout(mdb_tgt_t *t, mdb_io_t *io)
 147 {
 148         pt_data_t *pt = t->t_data;
 149         GElf_Sym s1, s2;
 150 
 151         if ((pt->p_file = mdb_gelf_create(io, ET_NONE, GF_FILE)) == NULL)
 152                 return (NULL);
 153 
 154         pt->p_symtab = mdb_gelf_symtab_create_file(pt->p_file,
 155             SHT_SYMTAB, MDB_TGT_SYMTAB);
 156         pt->p_dynsym = mdb_gelf_symtab_create_file(pt->p_file,
 157             SHT_DYNSYM, MDB_TGT_DYNSYM);
 158 
 159         /*
 160          * If we've got an _start symbol with a zero size, prime the private
 161          * symbol table with a copy of _start with its size set to the distance
 162          * between _mcount and _start.  We do this because DevPro has shipped
 163          * the Intel crt1.o without proper .size directives for years, which
 164          * precludes proper identification of _start in stack traces.
 165          */
 166         if (mdb_gelf_symtab_lookup_by_name(pt->p_dynsym, "_start", &s1,
 167             NULL) == 0 && s1.st_size == 0 &&
 168             GELF_ST_TYPE(s1.st_info) == STT_FUNC) {
 169                 if (mdb_gelf_symtab_lookup_by_name(pt->p_dynsym, "_mcount",
 170                     &s2, NULL) == 0 && GELF_ST_TYPE(s2.st_info) == STT_FUNC) {
 171                         s1.st_size = s2.st_value - s1.st_value;
 172                         mdb_gelf_symtab_insert(mdb.m_prsym, "_start", &s1);
 173                 }
 174         }
 175 
 176         pt->p_fio = io;
 177         return (pt->p_file);
 178 }
 179 
 180 /*
 181  * Destroy the symbol tables and GElf file object associated with p_fio.  Note
 182  * that we do not need to explicitly free p_fio: its reference count is
 183  * automatically decremented by mdb_gelf_destroy, which will free it if needed.
 184  */
 185 static void
 186 pt_close_aout(mdb_tgt_t *t)
 187 {
 188         pt_data_t *pt = t->t_data;
 189 
 190         if (pt->p_symtab != NULL) {
 191                 mdb_gelf_symtab_destroy(pt->p_symtab);
 192                 pt->p_symtab = NULL;
 193         }
 194 
 195         if (pt->p_dynsym != NULL) {
 196                 mdb_gelf_symtab_destroy(pt->p_dynsym);
 197                 pt->p_dynsym = NULL;
 198         }
 199 
 200         if (pt->p_file != NULL) {
 201                 mdb_gelf_destroy(pt->p_file);
 202                 pt->p_file = NULL;
 203         }
 204 
 205         mdb_gelf_symtab_delete(mdb.m_prsym, "_start", NULL);
 206         pt->p_fio = NULL;
 207 }
 208 
 209 typedef struct tdb_mapping {
 210         const char *tm_thr_lib;
 211         const char *tm_db_dir;
 212         const char *tm_db_name;
 213 } tdb_mapping_t;
 214 
 215 static const tdb_mapping_t tdb_map[] = {
 216         { "/lwp/amd64/libthread.so",    "/usr/lib/lwp/", "libthread_db.so" },
 217         { "/lwp/sparcv9/libthread.so",  "/usr/lib/lwp/", "libthread_db.so" },
 218         { "/lwp/libthread.so",          "/usr/lib/lwp/", "libthread_db.so" },
 219         { "/libthread.so",              "/lib/", "libthread_db.so" },
 220         { "/libc_hwcap",                "/lib/", "libc_db.so" },
 221         { "/libc.so",                   "/lib/", "libc_db.so" }
 222 };
 223 
 224 /*
 225  * Pobject_iter callback that we use to search for the presence of libthread in
 226  * order to load the corresponding libthread_db support.  We derive the
 227  * libthread_db path dynamically based on the libthread path.  If libthread is
 228  * found, this function returns 1 (and thus Pobject_iter aborts and returns 1)
 229  * regardless of whether it was successful in loading the libthread_db support.
 230  * If we iterate over all objects and no libthread is found, 0 is returned.
 231  * Since libthread_db support was then merged into libc_db, we load either
 232  * libc_db or libthread_db, depending on which library we see first.
 233  */
 234 /*ARGSUSED*/
 235 static int
 236 thr_check(mdb_tgt_t *t, const prmap_t *pmp, const char *name)
 237 {
 238         pt_data_t *pt = t->t_data;
 239         const mdb_tdb_ops_t *ops;
 240         char *p;
 241 
 242         char path[MAXPATHLEN];
 243 
 244         int libn;
 245 
 246         if (name == NULL)
 247                 return (0); /* no rtld_db object name; keep going */
 248 
 249         for (libn = 0; libn < sizeof (tdb_map) / sizeof (tdb_map[0]); libn++) {
 250                 if ((p = strstr(name, tdb_map[libn].tm_thr_lib)) != NULL)
 251                         break;
 252         }
 253 
 254         if (p == NULL)
 255                 return (0); /* no match; keep going */
 256 
 257         path[0] = '\0';
 258         (void) strlcat(path, mdb.m_root, sizeof (path));
 259         (void) strlcat(path, tdb_map[libn].tm_db_dir, sizeof (path));
 260 #if !defined(_ILP32)
 261         (void) strlcat(path, "64/", sizeof (path));
 262 #endif /* !_ILP32 */
 263         (void) strlcat(path, tdb_map[libn].tm_db_name, sizeof (path));
 264 
 265         /* Append the trailing library version number. */
 266         (void) strlcat(path, strrchr(name, '.'), sizeof (path));
 267 
 268         if ((ops = mdb_tdb_load(path)) == NULL) {
 269                 if (libn != 0 || errno != ENOENT)
 270                         warn("failed to load %s", path);
 271                 goto err;
 272         }
 273 
 274         if (ops == pt->p_tdb_ops)
 275                 return (1); /* no changes needed */
 276 
 277         PTL_DTOR(t);
 278         pt->p_tdb_ops = ops;
 279         pt->p_ptl_ops = &proc_tdb_ops;
 280         pt->p_ptl_hdl = NULL;
 281 
 282         if (PTL_CTOR(t) == -1) {
 283                 warn("failed to initialize %s", path);
 284                 goto err;
 285         }
 286 
 287         mdb_dprintf(MDB_DBG_TGT, "loaded %s for debugging %s\n", path, name);
 288         (void) mdb_tgt_status(t, &t->t_status);
 289         return (1);
 290 err:
 291         PTL_DTOR(t);
 292         pt->p_tdb_ops = NULL;
 293         pt->p_ptl_ops = &proc_lwp_ops;
 294         pt->p_ptl_hdl = NULL;
 295 
 296         if (libn != 0 || errno != ENOENT) {
 297                 warn("warning: debugger will only be able to "
 298                     "examine raw LWPs\n");
 299         }
 300 
 301         (void) mdb_tgt_status(t, &t->t_status);
 302         return (1);
 303 }
 304 
 305 /*
 306  * Whenever the link map is consistent following an add or delete event, we ask
 307  * libproc to update its mappings, check to see if we need to load libthread_db,
 308  * and then update breakpoints which have been mapped or unmapped.
 309  */
 310 /*ARGSUSED*/
 311 static void
 312 pt_rtld_event(mdb_tgt_t *t, int vid, void *private)
 313 {
 314         struct ps_prochandle *P = t->t_pshandle;
 315         pt_data_t *pt = t->t_data;
 316         rd_event_msg_t rdm;
 317         int docontinue = 1;
 318 
 319         if (rd_event_getmsg(pt->p_rtld, &rdm) == RD_OK) {
 320 
 321                 mdb_dprintf(MDB_DBG_TGT, "rtld event type 0x%x state 0x%x\n",
 322                     rdm.type, rdm.u.state);
 323 
 324                 if (rdm.type == RD_DLACTIVITY && rdm.u.state == RD_CONSISTENT) {
 325                         mdb_sespec_t *sep, *nsep = mdb_list_next(&t->t_active);
 326                         pt_brkpt_t *ptb;
 327 
 328                         Pupdate_maps(P);
 329 
 330                         if (Pobject_iter(P, (proc_map_f *)thr_check, t) == 0 &&
 331                             pt->p_ptl_ops != &proc_lwp_ops) {
 332                                 mdb_dprintf(MDB_DBG_TGT, "unloading thread_db "
 333                                     "support after dlclose\n");
 334                                 PTL_DTOR(t);
 335                                 pt->p_tdb_ops = NULL;
 336                                 pt->p_ptl_ops = &proc_lwp_ops;
 337                                 pt->p_ptl_hdl = NULL;
 338                                 (void) mdb_tgt_status(t, &t->t_status);
 339                         }
 340 
 341                         for (sep = nsep; sep != NULL; sep = nsep) {
 342                                 nsep = mdb_list_next(sep);
 343                                 ptb = sep->se_data;
 344 
 345                                 if (sep->se_ops == &proc_brkpt_ops &&
 346                                     Paddr_to_map(P, ptb->ptb_addr) == NULL)
 347                                         mdb_tgt_sespec_idle_one(t, sep,
 348                                             EMDB_NOMAP);
 349                         }
 350 
 351                         if (!mdb_tgt_sespec_activate_all(t) &&
 352                             (mdb.m_flags & MDB_FL_BPTNOSYMSTOP) &&
 353                             pt->p_rtld_finished) {
 354                                 /*
 355                                  * We weren't able to activate the breakpoints.
 356                                  * If so requested, we'll return without
 357                                  * calling continue, thus throwing the user into
 358                                  * the debugger.
 359                                  */
 360                                 docontinue = 0;
 361                         }
 362 
 363                         if (pt->p_rdstate == PT_RD_ADD)
 364                                 pt->p_rdstate = PT_RD_CONSIST;
 365                 }
 366 
 367                 if (rdm.type == RD_PREINIT)
 368                         (void) mdb_tgt_sespec_activate_all(t);
 369 
 370                 if (rdm.type == RD_POSTINIT) {
 371                         pt->p_rtld_finished = TRUE;
 372                         if (!mdb_tgt_sespec_activate_all(t) &&
 373                             (mdb.m_flags & MDB_FL_BPTNOSYMSTOP)) {
 374                                 /*
 375                                  * Now that rtld has been initialized, we
 376                                  * should be able to initialize all deferred
 377                                  * breakpoints.  If we can't, don't let the
 378                                  * target continue.
 379                                  */
 380                                 docontinue = 0;
 381                         }
 382                 }
 383 
 384                 if (rdm.type == RD_DLACTIVITY && rdm.u.state == RD_ADD &&
 385                     pt->p_rtld_finished)
 386                         pt->p_rdstate = MAX(pt->p_rdstate, PT_RD_ADD);
 387         }
 388 
 389         if (docontinue)
 390                 (void) mdb_tgt_continue(t, NULL);
 391 }
 392 
 393 static void
 394 pt_post_attach(mdb_tgt_t *t)
 395 {
 396         struct ps_prochandle *P = t->t_pshandle;
 397         const lwpstatus_t *psp = &Pstatus(P)->pr_lwp;
 398         pt_data_t *pt = t->t_data;
 399         int hflag = MDB_TGT_SPEC_HIDDEN;
 400 
 401         mdb_dprintf(MDB_DBG_TGT, "attach pr_flags=0x%x pr_why=%d pr_what=%d\n",
 402             psp->pr_flags, psp->pr_why, psp->pr_what);
 403 
 404         /*
 405          * When we grab a process, the initial setting of p_rtld_finished
 406          * should be false if the process was just created by exec; otherwise
 407          * we permit unscoped references to resolve because we do not know how
 408          * far the process has proceeded through linker initialization.
 409          */
 410         if ((psp->pr_flags & PR_ISTOP) && psp->pr_why == PR_SYSEXIT &&
 411             psp->pr_errno == 0 && psp->pr_what == SYS_execve) {
 412                 if (mdb.m_target == NULL) {
 413                         warn("target performed exec of %s\n",
 414                             IOP_NAME(pt->p_fio));
 415                 }
 416                 pt->p_rtld_finished = FALSE;
 417         } else
 418                 pt->p_rtld_finished = TRUE;
 419 
 420         /*
 421          * When we grab a process, if it is stopped by job control and part of
 422          * the same session (i.e. same controlling tty), set MDB_FL_JOBCTL so
 423          * we will know to bring it to the foreground when we continue it.
 424          */
 425         if (mdb.m_term != NULL && (psp->pr_flags & PR_STOPPED) &&
 426             psp->pr_why == PR_JOBCONTROL && getsid(0) == Pstatus(P)->pr_sid)
 427                 mdb.m_flags |= MDB_FL_JOBCTL;
 428 
 429         /*
 430          * When we grab control of a live process, set F_RDWR so that the
 431          * target layer permits writes to the target's address space.
 432          */
 433         t->t_flags |= MDB_TGT_F_RDWR;
 434 
 435         (void) Pfault(P, FLTBPT, TRUE);         /* always trace breakpoints */
 436         (void) Pfault(P, FLTWATCH, TRUE);       /* always trace watchpoints */
 437         (void) Pfault(P, FLTTRACE, TRUE);       /* always trace single-step */
 438 
 439         (void) Punsetflags(P, PR_ASYNC);        /* require synchronous mode */
 440         (void) Psetflags(P, PR_BPTADJ);         /* always adjust eip on x86 */
 441         (void) Psetflags(P, PR_FORK);           /* inherit tracing on fork */
 442 
 443         /*
 444          * Install event specifiers to track fork and exec activities:
 445          */
 446         (void) mdb_tgt_add_sysexit(t, SYS_vfork, hflag, pt_fork, NULL);
 447         (void) mdb_tgt_add_sysexit(t, SYS_forksys, hflag, pt_fork, NULL);
 448         (void) mdb_tgt_add_sysexit(t, SYS_execve, hflag, pt_exec, NULL);
 449 
 450         /*
 451          * Attempt to instantiate the librtld_db agent and set breakpoints
 452          * to track rtld activity.  We will legitimately fail to instantiate
 453          * the rtld_db agent if the target is statically linked.
 454          */
 455         if (pt->p_rtld == NULL && (pt->p_rtld = Prd_agent(P)) != NULL) {
 456                 rd_notify_t rdn;
 457                 rd_err_e err;
 458 
 459                 if ((err = rd_event_enable(pt->p_rtld, TRUE)) != RD_OK) {
 460                         warn("failed to enable rtld_db event tracing: %s\n",
 461                             rd_errstr(err));
 462                         goto out;
 463                 }
 464 
 465                 if ((err = rd_event_addr(pt->p_rtld, RD_PREINIT,
 466                     &rdn)) == RD_OK && rdn.type == RD_NOTIFY_BPT) {
 467                         (void) mdb_tgt_add_vbrkpt(t, rdn.u.bptaddr,
 468                             hflag, pt_rtld_event, NULL);
 469                 } else {
 470                         warn("failed to install rtld_db preinit tracing: %s\n",
 471                             rd_errstr(err));
 472                 }
 473 
 474                 if ((err = rd_event_addr(pt->p_rtld, RD_POSTINIT,
 475                     &rdn)) == RD_OK && rdn.type == RD_NOTIFY_BPT) {
 476                         (void) mdb_tgt_add_vbrkpt(t, rdn.u.bptaddr,
 477                             hflag, pt_rtld_event, NULL);
 478                 } else {
 479                         warn("failed to install rtld_db postinit tracing: %s\n",
 480                             rd_errstr(err));
 481                 }
 482 
 483                 if ((err = rd_event_addr(pt->p_rtld, RD_DLACTIVITY,
 484                     &rdn)) == RD_OK && rdn.type == RD_NOTIFY_BPT) {
 485                         (void) mdb_tgt_add_vbrkpt(t, rdn.u.bptaddr,
 486                             hflag, pt_rtld_event, NULL);
 487                 } else {
 488                         warn("failed to install rtld_db activity tracing: %s\n",
 489                             rd_errstr(err));
 490                 }
 491         }
 492 out:
 493         Pupdate_maps(P);
 494         Psync(P);
 495 
 496         /*
 497          * If librtld_db failed to initialize due to an error or because we are
 498          * debugging a statically linked executable, allow unscoped references.
 499          */
 500         if (pt->p_rtld == NULL)
 501                 pt->p_rtld_finished = TRUE;
 502 
 503         (void) mdb_tgt_sespec_activate_all(t);
 504 }
 505 
 506 /*ARGSUSED*/
 507 static int
 508 pt_vespec_delete(mdb_tgt_t *t, void *private, int id, void *data)
 509 {
 510         if (id < 0) {
 511                 ASSERT(data == NULL); /* we don't use any ve_data */
 512                 (void) mdb_tgt_vespec_delete(t, id);
 513         }
 514         return (0);
 515 }
 516 
 517 static void
 518 pt_pre_detach(mdb_tgt_t *t, int clear_matched)
 519 {
 520         const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
 521         pt_data_t *pt = t->t_data;
 522         long cmd = 0;
 523 
 524         /*
 525          * If we are about to release the process and it is stopped on a traced
 526          * SIGINT, breakpoint fault, single-step fault, or watchpoint, make
 527          * sure to clear this event prior to releasing the process so that it
 528          * does not subsequently reissue the fault and die from SIGTRAP.
 529          */
 530         if (psp->pr_flags & PR_ISTOP) {
 531                 if (psp->pr_why == PR_FAULTED && (psp->pr_what == FLTBPT ||
 532                     psp->pr_what == FLTTRACE || psp->pr_what == FLTWATCH))
 533                         cmd = PCCFAULT;
 534                 else if (psp->pr_why == PR_SIGNALLED && psp->pr_what == SIGINT)
 535                         cmd = PCCSIG;
 536 
 537                 if (cmd != 0)
 538                         (void) write(Pctlfd(t->t_pshandle), &cmd, sizeof (cmd));
 539         }
 540 
 541         if (Pstate(t->t_pshandle) == PS_UNDEAD)
 542                 (void) waitpid(Pstatus(t->t_pshandle)->pr_pid, NULL, WNOHANG);
 543 
 544         (void) mdb_tgt_vespec_iter(t, pt_vespec_delete, NULL);
 545         mdb_tgt_sespec_idle_all(t, EMDB_NOPROC, clear_matched);
 546 
 547         if (pt->p_fio != pt->p_aout_fio) {
 548                 pt_close_aout(t);
 549                 (void) pt_open_aout(t, pt->p_aout_fio);
 550         }
 551 
 552         PTL_DTOR(t);
 553         pt->p_tdb_ops = NULL;
 554         pt->p_ptl_ops = &proc_lwp_ops;
 555         pt->p_ptl_hdl = NULL;
 556 
 557         pt->p_rtld = NULL;
 558         pt->p_signal = 0;
 559         pt->p_rtld_finished = FALSE;
 560         pt->p_rdstate = PT_RD_NONE;
 561 }
 562 
 563 static void
 564 pt_release_parents(mdb_tgt_t *t)
 565 {
 566         struct ps_prochandle *P = t->t_pshandle;
 567         pt_data_t *pt = t->t_data;
 568 
 569         mdb_sespec_t *sep;
 570         pt_vforkp_t *vfp;
 571 
 572         while ((vfp = mdb_list_next(&pt->p_vforkp)) != NULL) {
 573                 mdb_dprintf(MDB_DBG_TGT, "releasing vfork parent %d\n",
 574                     (int)Pstatus(vfp->p_pshandle)->pr_pid);
 575 
 576                 /*
 577                  * To release vfork parents, we must also wipe out any armed
 578                  * events in the parent by switching t_pshandle and calling
 579                  * se_disarm().  Do not change states or lose the matched list.
 580                  */
 581                 t->t_pshandle = vfp->p_pshandle;
 582 
 583                 for (sep = mdb_list_next(&t->t_active); sep != NULL;
 584                     sep = mdb_list_next(sep)) {
 585                         if (sep->se_state == MDB_TGT_SPEC_ARMED)
 586                                 (void) sep->se_ops->se_disarm(t, sep);
 587                 }
 588 
 589                 t->t_pshandle = P;
 590 
 591                 Prelease(vfp->p_pshandle, PRELEASE_CLEAR);
 592                 mdb_list_delete(&pt->p_vforkp, vfp);
 593                 mdb_free(vfp, sizeof (pt_vforkp_t));
 594         }
 595 }
 596 
 597 /*ARGSUSED*/
 598 static void
 599 pt_fork(mdb_tgt_t *t, int vid, void *private)
 600 {
 601         struct ps_prochandle *P = t->t_pshandle;
 602         const lwpstatus_t *psp = &Pstatus(P)->pr_lwp;
 603         pt_data_t *pt = t->t_data;
 604         mdb_sespec_t *sep;
 605 
 606         int follow_parent = mdb.m_forkmode != MDB_FM_CHILD;
 607         int is_vfork = (psp->pr_what == SYS_vfork ||
 608             (psp->pr_what == SYS_forksys && psp->pr_sysarg[0] == 2));
 609 
 610         struct ps_prochandle *C;
 611         const lwpstatus_t *csp;
 612         char sysname[32];
 613         int gcode;
 614         char c;
 615 
 616         mdb_dprintf(MDB_DBG_TGT, "parent %s: errno=%d rv1=%ld rv2=%ld\n",
 617             proc_sysname(psp->pr_what, sysname, sizeof (sysname)),
 618             psp->pr_errno, psp->pr_rval1, psp->pr_rval2);
 619 
 620         if (psp->pr_errno != 0) {
 621                 (void) mdb_tgt_continue(t, NULL);
 622                 return; /* fork failed */
 623         }
 624 
 625         /*
 626          * If forkmode is ASK and stdout is a terminal, then ask the user to
 627          * explicitly set the fork behavior for this particular fork.
 628          */
 629         if (mdb.m_forkmode == MDB_FM_ASK && mdb.m_term != NULL) {
 630                 mdb_iob_printf(mdb.m_err, "%s: %s detected: follow (p)arent "
 631                     "or (c)hild? ", mdb.m_pname, sysname);
 632                 mdb_iob_flush(mdb.m_err);
 633 
 634                 while (IOP_READ(mdb.m_term, &c, sizeof (c)) == sizeof (c)) {
 635                         if (c == 'P' || c == 'p') {
 636                                 mdb_iob_printf(mdb.m_err, "%c\n", c);
 637                                 follow_parent = TRUE;
 638                                 break;
 639                         } else if (c == 'C' || c == 'c') {
 640                                 mdb_iob_printf(mdb.m_err, "%c\n", c);
 641                                 follow_parent = FALSE;
 642                                 break;
 643                         }
 644                 }
 645         }
 646 
 647         /*
 648          * The parent is now stopped on exit from its fork call.  We must now
 649          * grab the child on its return from fork in order to manipulate it.
 650          */
 651         if ((C = Pgrab(psp->pr_rval1, PGRAB_RETAIN, &gcode)) == NULL) {
 652                 warn("failed to grab forked child process %ld: %s\n",
 653                     psp->pr_rval1, Pgrab_error(gcode));
 654                 return; /* just stop if we failed to grab the child */
 655         }
 656 
 657         /*
 658          * We may have grabbed the child and stopped it prematurely before it
 659          * stopped on exit from fork.  If so, wait up to 1 sec for it to settle.
 660          */
 661         if (Pstatus(C)->pr_lwp.pr_why != PR_SYSEXIT)
 662                 (void) Pwait(C, MILLISEC);
 663 
 664         csp = &Pstatus(C)->pr_lwp;
 665 
 666         if (csp->pr_why != PR_SYSEXIT ||
 667             (csp->pr_what != SYS_vfork && csp->pr_what != SYS_forksys)) {
 668                 warn("forked child process %ld did not stop on exit from "
 669                     "fork as expected\n", psp->pr_rval1);
 670         }
 671 
 672         warn("target forked child process %ld (debugger following %s)\n",
 673             psp->pr_rval1, follow_parent ? "parent" : "child");
 674 
 675         (void) Punsetflags(C, PR_ASYNC);        /* require synchronous mode */
 676         (void) Psetflags(C, PR_BPTADJ);         /* always adjust eip on x86 */
 677         (void) Prd_agent(C);                    /* initialize librtld_db */
 678 
 679         /*
 680          * At the time pt_fork() is called, the target event engine has already
 681          * disarmed the specifiers on the active list, clearing out events in
 682          * the parent process.  However, this means that events that change
 683          * the address space (e.g. breakpoints) have not been effectively
 684          * disarmed in the child since its address space reflects the state of
 685          * the process at the time of fork when events were armed.  We must
 686          * therefore handle this as a special case and re-invoke the disarm
 687          * callback of each active specifier to clean out the child process.
 688          */
 689         if (!is_vfork) {
 690                 for (t->t_pshandle = C, sep = mdb_list_next(&t->t_active);
 691                     sep != NULL; sep = mdb_list_next(sep)) {
 692                         if (sep->se_state == MDB_TGT_SPEC_ACTIVE)
 693                                 (void) sep->se_ops->se_disarm(t, sep);
 694                 }
 695 
 696                 t->t_pshandle = P; /* restore pshandle to parent */
 697         }
 698 
 699         /*
 700          * If we're following the parent process, we need to temporarily change
 701          * t_pshandle to refer to the child handle C so that we can clear out
 702          * all the events in the child prior to releasing it below.  If we are
 703          * tracing a vfork, we also need to explicitly wait for the child to
 704          * exec, exit, or die before we can reset and continue the parent.  We
 705          * avoid having to deal with the vfork child forking again by clearing
 706          * PR_FORK and setting PR_RLC; if it does fork it will effectively be
 707          * released from our control and we will continue following the parent.
 708          */
 709         if (follow_parent) {
 710                 if (is_vfork) {
 711                         mdb_tgt_status_t status;
 712 
 713                         ASSERT(psp->pr_flags & PR_VFORKP);
 714                         mdb_tgt_sespec_idle_all(t, EBUSY, FALSE);
 715                         t->t_pshandle = C;
 716 
 717                         (void) Psysexit(C, SYS_execve, TRUE);
 718 
 719                         (void) Punsetflags(C, PR_FORK | PR_KLC);
 720                         (void) Psetflags(C, PR_RLC);
 721 
 722                         do {
 723                                 if (pt_setrun(t, &status, 0) == -1 ||
 724                                     status.st_state == MDB_TGT_UNDEAD ||
 725                                     status.st_state == MDB_TGT_LOST)
 726                                         break; /* failure or process died */
 727 
 728                         } while (csp->pr_why != PR_SYSEXIT ||
 729                             csp->pr_errno != 0 || csp->pr_what != SYS_execve);
 730                 } else
 731                         t->t_pshandle = C;
 732         }
 733 
 734         /*
 735          * If we are following the child, destroy any active libthread_db
 736          * handle before we release the parent process.
 737          */
 738         if (!follow_parent) {
 739                 PTL_DTOR(t);
 740                 pt->p_tdb_ops = NULL;
 741                 pt->p_ptl_ops = &proc_lwp_ops;
 742                 pt->p_ptl_hdl = NULL;
 743         }
 744 
 745         /*
 746          * Idle all events to make sure the address space and tracing flags are
 747          * restored, and then release the process we are not tracing.  If we
 748          * are following the child of a vfork, we push the parent's pshandle
 749          * on to a list of vfork parents to be released when we exec or exit.
 750          */
 751         if (is_vfork && !follow_parent) {
 752                 pt_vforkp_t *vfp = mdb_alloc(sizeof (pt_vforkp_t), UM_SLEEP);
 753 
 754                 ASSERT(psp->pr_flags & PR_VFORKP);
 755                 vfp->p_pshandle = P;
 756                 mdb_list_append(&pt->p_vforkp, vfp);
 757                 mdb_tgt_sespec_idle_all(t, EBUSY, FALSE);
 758 
 759         } else {
 760                 mdb_tgt_sespec_idle_all(t, EBUSY, FALSE);
 761                 Prelease(t->t_pshandle, PRELEASE_CLEAR);
 762                 if (!follow_parent)
 763                         pt_release_parents(t);
 764         }
 765 
 766         /*
 767          * Now that all the hard stuff is done, switch t_pshandle back to the
 768          * process we are following and reset our events to the ACTIVE state.
 769          * If we are following the child, reset the libthread_db handle as well
 770          * as the rtld agent.
 771          */
 772         if (follow_parent)
 773                 t->t_pshandle = P;
 774         else {
 775                 t->t_pshandle = C;
 776                 pt->p_rtld = Prd_agent(C);
 777                 (void) Pobject_iter(t->t_pshandle, (proc_map_f *)thr_check, t);
 778         }
 779 
 780         (void) mdb_tgt_sespec_activate_all(t);
 781         (void) mdb_tgt_continue(t, NULL);
 782 }
 783 
 784 /*ARGSUSED*/
 785 static void
 786 pt_exec(mdb_tgt_t *t, int vid, void *private)
 787 {
 788         struct ps_prochandle *P = t->t_pshandle;
 789         const pstatus_t *psp = Pstatus(P);
 790         pt_data_t *pt = t->t_data;
 791         int follow_exec = mdb.m_execmode == MDB_EM_FOLLOW;
 792         pid_t pid = psp->pr_pid;
 793 
 794         char execname[MAXPATHLEN];
 795         mdb_sespec_t *sep, *nsep;
 796         mdb_io_t *io;
 797         char c;
 798 
 799         mdb_dprintf(MDB_DBG_TGT, "exit from %s: errno=%d\n", proc_sysname(
 800             psp->pr_lwp.pr_what, execname, sizeof (execname)),
 801             psp->pr_lwp.pr_errno);
 802 
 803         if (psp->pr_lwp.pr_errno != 0) {
 804                 (void) mdb_tgt_continue(t, NULL);
 805                 return; /* exec failed */
 806         }
 807 
 808         /*
 809          * If execmode is ASK and stdout is a terminal, then ask the user to
 810          * explicitly set the exec behavior for this particular exec.  If
 811          * Pstate() still shows PS_LOST, we are being called from pt_setrun()
 812          * directly and therefore we must resume the terminal since it is still
 813          * in the suspended state as far as tgt_continue() is concerned.
 814          */
 815         if (mdb.m_execmode == MDB_EM_ASK && mdb.m_term != NULL) {
 816                 if (Pstate(P) == PS_LOST)
 817                         IOP_RESUME(mdb.m_term);
 818 
 819                 mdb_iob_printf(mdb.m_err, "%s: %s detected: (f)ollow new "
 820                     "program or (s)top? ", mdb.m_pname, execname);
 821                 mdb_iob_flush(mdb.m_err);
 822 
 823                 while (IOP_READ(mdb.m_term, &c, sizeof (c)) == sizeof (c)) {
 824                         if (c == 'F' || c == 'f') {
 825                                 mdb_iob_printf(mdb.m_err, "%c\n", c);
 826                                 follow_exec = TRUE;
 827                                 break;
 828                         } else if (c == 'S' || c == 's') {
 829                                 mdb_iob_printf(mdb.m_err, "%c\n", c);
 830                                 follow_exec = FALSE;
 831                                 break;
 832                         }
 833                 }
 834 
 835                 if (Pstate(P) == PS_LOST)
 836                         IOP_SUSPEND(mdb.m_term);
 837         }
 838 
 839         pt_release_parents(t);  /* release any waiting vfork parents */
 840         pt_pre_detach(t, FALSE); /* remove our breakpoints and idle events */
 841         Preset_maps(P);         /* libproc must delete mappings and symtabs */
 842         pt_close_aout(t);       /* free pt symbol tables and GElf file data */
 843 
 844         /*
 845          * If we lost control of the process across the exec and are not able
 846          * to reopen it, we have no choice but to clear the matched event list
 847          * and wait for the user to quit or otherwise release the process.
 848          */
 849         if (Pstate(P) == PS_LOST && Preopen(P) == -1) {
 850                 int error = errno;
 851 
 852                 warn("lost control of PID %d due to exec of %s executable\n",
 853                     (int)pid, error == EOVERFLOW ? "64-bit" : "set-id");
 854 
 855                 for (sep = t->t_matched; sep != T_SE_END; sep = nsep) {
 856                         nsep = sep->se_matched;
 857                         sep->se_matched = NULL;
 858                         mdb_tgt_sespec_rele(t, sep);
 859                 }
 860 
 861                 if (error != EOVERFLOW)
 862                         return; /* just stop if we exec'd a set-id executable */
 863         }
 864 
 865         if (Pstate(P) != PS_LOST) {
 866                 if (Pexecname(P, execname, sizeof (execname)) == NULL) {
 867                         (void) mdb_iob_snprintf(execname, sizeof (execname),
 868                             "/proc/%d/object/a.out", (int)pid);
 869                 }
 870 
 871                 if (follow_exec == FALSE || psp->pr_dmodel == PR_MODEL_NATIVE)
 872                         warn("target performed exec of %s\n", execname);
 873 
 874                 io = mdb_fdio_create_path(NULL, execname, pt->p_oflags, 0);
 875                 if (io == NULL) {
 876                         warn("failed to open %s", execname);
 877                         warn("a.out symbol tables will not be available\n");
 878                 } else if (pt_open_aout(t, io) == NULL) {
 879                         (void) mdb_dis_select(pt_disasm(NULL));
 880                         mdb_io_destroy(io);
 881                 } else
 882                         (void) mdb_dis_select(pt_disasm(&pt->p_file->gf_ehdr));
 883         }
 884 
 885         /*
 886          * We reset our libthread_db state here, but deliberately do NOT call
 887          * PTL_DTOR because we do not want to call libthread_db's td_ta_delete.
 888          * This interface is hopelessly broken in that it writes to the process
 889          * address space (which we do not want it to do after an exec) and it
 890          * doesn't bother deallocating any of its storage anyway.
 891          */
 892         pt->p_tdb_ops = NULL;
 893         pt->p_ptl_ops = &proc_lwp_ops;
 894         pt->p_ptl_hdl = NULL;
 895 
 896         if (follow_exec && psp->pr_dmodel != PR_MODEL_NATIVE) {
 897                 const char *argv[3];
 898                 char *state, *env;
 899                 char pidarg[16];
 900                 size_t envlen;
 901 
 902                 if (realpath(getexecname(), execname) == NULL) {
 903                         warn("cannot follow PID %d -- failed to resolve "
 904                             "debugger pathname for re-exec", (int)pid);
 905                         return;
 906                 }
 907 
 908                 warn("restarting debugger to follow PID %d ...\n", (int)pid);
 909                 mdb_dprintf(MDB_DBG_TGT, "re-exec'ing %s\n", execname);
 910 
 911                 (void) mdb_snprintf(pidarg, sizeof (pidarg), "-p%d", (int)pid);
 912 
 913                 state = mdb_get_config();
 914                 envlen = strlen(MDB_CONFIG_ENV_VAR) + 1 + strlen(state) + 1;
 915                 env = mdb_alloc(envlen, UM_SLEEP);
 916                 (void) snprintf(env, envlen,
 917                     "%s=%s", MDB_CONFIG_ENV_VAR, state);
 918 
 919                 (void) putenv(env);
 920 
 921                 argv[0] = mdb.m_pname;
 922                 argv[1] = pidarg;
 923                 argv[2] = NULL;
 924 
 925                 if (mdb.m_term != NULL)
 926                         IOP_SUSPEND(mdb.m_term);
 927 
 928                 Prelease(P, PRELEASE_CLEAR | PRELEASE_HANG);
 929                 (void) execv(execname, (char *const *)argv);
 930                 warn("failed to re-exec debugger");
 931 
 932                 if (mdb.m_term != NULL)
 933                         IOP_RESUME(mdb.m_term);
 934 
 935                 t->t_pshandle = pt->p_idlehandle;
 936                 return;
 937         }
 938 
 939         pt_post_attach(t);      /* install tracing flags and activate events */
 940         pt_activate_common(t);  /* initialize librtld_db and libthread_db */
 941 
 942         if (psp->pr_dmodel != PR_MODEL_NATIVE && mdb.m_term != NULL) {
 943                 warn("loadable dcmds will not operate on non-native %d-bit "
 944                     "data model\n", psp->pr_dmodel == PR_MODEL_ILP32 ? 32 : 64);
 945                 warn("use ::release -a and then run mdb -p %d to restart "
 946                     "debugger\n", (int)pid);
 947         }
 948 
 949         if (follow_exec)
 950                 (void) mdb_tgt_continue(t, NULL);
 951 }
 952 
 953 static int
 954 pt_setflags(mdb_tgt_t *t, int flags)
 955 {
 956         pt_data_t *pt = t->t_data;
 957 
 958         if ((flags ^ t->t_flags) & MDB_TGT_F_RDWR) {
 959                 int mode = (flags & MDB_TGT_F_RDWR) ? O_RDWR : O_RDONLY;
 960                 mdb_io_t *io;
 961 
 962                 if (pt->p_fio == NULL)
 963                         return (set_errno(EMDB_NOEXEC));
 964 
 965                 io = mdb_fdio_create_path(NULL, IOP_NAME(pt->p_fio), mode, 0);
 966 
 967                 if (io == NULL)
 968                         return (-1); /* errno is set for us */
 969 
 970                 t->t_flags = (t->t_flags & ~MDB_TGT_F_RDWR) |
 971                     (flags & MDB_TGT_F_RDWR);
 972 
 973                 pt->p_fio = mdb_io_hold(io);
 974                 mdb_io_rele(pt->p_file->gf_io);
 975                 pt->p_file->gf_io = pt->p_fio;
 976         }
 977 
 978         if (flags & MDB_TGT_F_FORCE) {
 979                 t->t_flags |= MDB_TGT_F_FORCE;
 980                 pt->p_gflags |= PGRAB_FORCE;
 981         }
 982 
 983         return (0);
 984 }
 985 
 986 /*ARGSUSED*/
 987 static int
 988 pt_frame(void *arglim, uintptr_t pc, uint_t argc, const long *argv,
 989     const mdb_tgt_gregset_t *gregs)
 990 {
 991         argc = MIN(argc, (uint_t)(uintptr_t)arglim);
 992         mdb_printf("%a(", pc);
 993 
 994         if (argc != 0) {
 995                 mdb_printf("%lr", *argv++);
 996                 for (argc--; argc != 0; argc--)
 997                         mdb_printf(", %lr", *argv++);
 998         }
 999 
1000         mdb_printf(")\n");
1001         return (0);
1002 }
1003 
1004 static int
1005 pt_framev(void *arglim, uintptr_t pc, uint_t argc, const long *argv,
1006     const mdb_tgt_gregset_t *gregs)
1007 {
1008         argc = MIN(argc, (uint_t)(uintptr_t)arglim);
1009 #if defined(__i386) || defined(__amd64)
1010         mdb_printf("%0?lr %a(", gregs->gregs[R_FP], pc);
1011 #else
1012         mdb_printf("%0?lr %a(", gregs->gregs[R_SP], pc);
1013 #endif
1014         if (argc != 0) {
1015                 mdb_printf("%lr", *argv++);
1016                 for (argc--; argc != 0; argc--)
1017                         mdb_printf(", %lr", *argv++);
1018         }
1019 
1020         mdb_printf(")\n");
1021         return (0);
1022 }
1023 
1024 static int
1025 pt_framer(void *arglim, uintptr_t pc, uint_t argc, const long *argv,
1026     const mdb_tgt_gregset_t *gregs)
1027 {
1028         if (pt_frameregs(arglim, pc, argc, argv, gregs, pc == PC_FAKE) == -1) {
1029                 /*
1030                  * Use verbose format if register format is not supported.
1031                  */
1032                 return (pt_framev(arglim, pc, argc, argv, gregs));
1033         }
1034 
1035         return (0);
1036 }
1037 
1038 /*ARGSUSED*/
1039 static int
1040 pt_stack_common(uintptr_t addr, uint_t flags, int argc,
1041     const mdb_arg_t *argv, mdb_tgt_stack_f *func, prgreg_t saved_pc)
1042 {
1043         void *arg = (void *)(uintptr_t)mdb.m_nargs;
1044         mdb_tgt_t *t = mdb.m_target;
1045         mdb_tgt_gregset_t gregs;
1046 
1047         if (argc != 0) {
1048                 if (argv->a_type == MDB_TYPE_CHAR || argc > 1)
1049                         return (DCMD_USAGE);
1050 
1051                 if (argv->a_type == MDB_TYPE_STRING)
1052                         arg = (void *)(uintptr_t)mdb_strtoull(argv->a_un.a_str);
1053                 else
1054                         arg = (void *)(uintptr_t)argv->a_un.a_val;
1055         }
1056 
1057         if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_IDLE) {
1058                 mdb_warn("no process active\n");
1059                 return (DCMD_ERR);
1060         }
1061 
1062         /*
1063          * In the universe of sparcv7, sparcv9, ia32, and amd64 this code can be
1064          * common: <sys/procfs_isa.h> conveniently #defines R_FP to be the
1065          * appropriate register we need to set in order to perform a stack
1066          * traceback from a given frame address.
1067          */
1068         if (flags & DCMD_ADDRSPEC) {
1069                 bzero(&gregs, sizeof (gregs));
1070                 gregs.gregs[R_FP] = addr;
1071 #ifdef __sparc
1072                 gregs.gregs[R_I7] = saved_pc;
1073 #endif /* __sparc */
1074         } else if (PTL_GETREGS(t, PTL_TID(t), gregs.gregs) != 0) {
1075                 mdb_warn("failed to get current register set");
1076                 return (DCMD_ERR);
1077         }
1078 
1079         (void) mdb_tgt_stack_iter(t, &gregs, func, arg);
1080         return (DCMD_OK);
1081 }
1082 
1083 static int
1084 pt_stack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1085 {
1086         return (pt_stack_common(addr, flags, argc, argv, pt_frame, 0));
1087 }
1088 
1089 static int
1090 pt_stackv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1091 {
1092         return (pt_stack_common(addr, flags, argc, argv, pt_framev, 0));
1093 }
1094 
1095 static int
1096 pt_stackr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1097 {
1098         /*
1099          * Force printing of first register window, by setting  the
1100          * saved pc (%i7) to PC_FAKE.
1101          */
1102         return (pt_stack_common(addr, flags, argc, argv, pt_framer, PC_FAKE));
1103 }
1104 
1105 /*ARGSUSED*/
1106 static int
1107 pt_ignored(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1108 {
1109         struct ps_prochandle *P = mdb.m_target->t_pshandle;
1110         char buf[PRSIGBUFSZ];
1111 
1112         if ((flags & DCMD_ADDRSPEC) || argc != 0)
1113                 return (DCMD_USAGE);
1114 
1115         if (P == NULL) {
1116                 mdb_warn("no process is currently active\n");
1117                 return (DCMD_ERR);
1118         }
1119 
1120         mdb_printf("%s\n", proc_sigset2str(&Pstatus(P)->pr_sigtrace, " ",
1121             FALSE, buf, sizeof (buf)));
1122 
1123         return (DCMD_OK);
1124 }
1125 
1126 /*ARGSUSED*/
1127 static int
1128 pt_lwpid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1129 {
1130         struct ps_prochandle *P = mdb.m_target->t_pshandle;
1131 
1132         if ((flags & DCMD_ADDRSPEC) || argc != 0)
1133                 return (DCMD_USAGE);
1134 
1135         if (P == NULL) {
1136                 mdb_warn("no process is currently active\n");
1137                 return (DCMD_ERR);
1138         }
1139 
1140         mdb_printf("%d\n", Pstatus(P)->pr_lwp.pr_lwpid);
1141         return (DCMD_OK);
1142 }
1143 
1144 static int
1145 pt_print_lwpid(int *n, const lwpstatus_t *psp)
1146 {
1147         struct ps_prochandle *P = mdb.m_target->t_pshandle;
1148         int nlwp = Pstatus(P)->pr_nlwp;
1149 
1150         if (*n == nlwp - 2)
1151                 mdb_printf("%d and ", (int)psp->pr_lwpid);
1152         else if (*n == nlwp - 1)
1153                 mdb_printf("%d are", (int)psp->pr_lwpid);
1154         else
1155                 mdb_printf("%d, ", (int)psp->pr_lwpid);
1156 
1157         (*n)++;
1158         return (0);
1159 }
1160 
1161 /*ARGSUSED*/
1162 static int
1163 pt_lwpids(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1164 {
1165         struct ps_prochandle *P = mdb.m_target->t_pshandle;
1166         int n = 0;
1167 
1168         if (P == NULL) {
1169                 mdb_warn("no process is currently active\n");
1170                 return (DCMD_ERR);
1171         }
1172 
1173         switch (Pstatus(P)->pr_nlwp) {
1174         case 0:
1175                 mdb_printf("no lwps are");
1176                 break;
1177         case 1:
1178                 mdb_printf("lwpid %d is the only lwp",
1179                     Pstatus(P)->pr_lwp.pr_lwpid);
1180                 break;
1181         default:
1182                 mdb_printf("lwpids ");
1183                 (void) Plwp_iter(P, (proc_lwp_f *)pt_print_lwpid, &n);
1184         }
1185 
1186         switch (Pstate(P)) {
1187         case PS_DEAD:
1188                 mdb_printf(" in core of process %d.\n", Pstatus(P)->pr_pid);
1189                 break;
1190         case PS_IDLE:
1191                 mdb_printf(" in idle target.\n");
1192                 break;
1193         default:
1194                 mdb_printf(" in process %d.\n", (int)Pstatus(P)->pr_pid);
1195                 break;
1196         }
1197 
1198         return (DCMD_OK);
1199 }
1200 
1201 /*ARGSUSED*/
1202 static int
1203 pt_ignore(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1204 {
1205         pt_data_t *pt = mdb.m_target->t_data;
1206 
1207         if (!(flags & DCMD_ADDRSPEC) || argc != 0)
1208                 return (DCMD_USAGE);
1209 
1210         if (addr < 1 || addr > pt->p_maxsig) {
1211                 mdb_warn("invalid signal number -- 0t%lu\n", addr);
1212                 return (DCMD_ERR);
1213         }
1214 
1215         (void) mdb_tgt_vespec_iter(mdb.m_target, pt_ignore_sig, (void *)addr);
1216         return (DCMD_OK);
1217 }
1218 
1219 /*ARGSUSED*/
1220 static int
1221 pt_attach(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1222 {
1223         mdb_tgt_t *t = mdb.m_target;
1224         pt_data_t *pt = t->t_data;
1225         int state, perr;
1226 
1227         if (!(flags & DCMD_ADDRSPEC) && argc == 0)
1228                 return (DCMD_USAGE);
1229 
1230         if (((flags & DCMD_ADDRSPEC) && argc != 0) || argc > 1 ||
1231             (argc != 0 && argv->a_type != MDB_TYPE_STRING))
1232                 return (DCMD_USAGE);
1233 
1234         if (t->t_pshandle != NULL && Pstate(t->t_pshandle) != PS_IDLE) {
1235                 mdb_warn("debugger is already attached to a %s\n",
1236                     (Pstate(t->t_pshandle) == PS_DEAD) ? "core" : "process");
1237                 return (DCMD_ERR);
1238         }
1239 
1240         if (pt->p_fio == NULL) {
1241                 mdb_warn("attach requires executable to be specified on "
1242                     "command-line (or use -p)\n");
1243                 return (DCMD_ERR);
1244         }
1245 
1246         if (flags & DCMD_ADDRSPEC)
1247                 t->t_pshandle = Pgrab((pid_t)addr, pt->p_gflags, &perr);
1248         else
1249                 t->t_pshandle = proc_arg_grab(argv->a_un.a_str,
1250                     PR_ARG_ANY, pt->p_gflags, &perr);
1251 
1252         if (t->t_pshandle == NULL) {
1253                 t->t_pshandle = pt->p_idlehandle;
1254                 mdb_warn("cannot attach: %s\n", Pgrab_error(perr));
1255                 return (DCMD_ERR);
1256         }
1257 
1258         state = Pstate(t->t_pshandle);
1259         if (state != PS_DEAD && state != PS_IDLE) {
1260                 (void) Punsetflags(t->t_pshandle, PR_KLC);
1261                 (void) Psetflags(t->t_pshandle, PR_RLC);
1262                 pt_post_attach(t);
1263                 pt_activate_common(t);
1264         }
1265 
1266         (void) mdb_tgt_status(t, &t->t_status);
1267         mdb_module_load_all(0);
1268         return (DCMD_OK);
1269 }
1270 
1271 static int
1272 pt_regstatus(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1273 {
1274         mdb_tgt_t *t = mdb.m_target;
1275 
1276         if (t->t_pshandle != NULL) {
1277                 const pstatus_t *psp = Pstatus(t->t_pshandle);
1278                 int cursig = psp->pr_lwp.pr_cursig;
1279                 char signame[SIG2STR_MAX];
1280                 int state = Pstate(t->t_pshandle);
1281 
1282                 if (state != PS_DEAD && state != PS_IDLE)
1283                         mdb_printf("process id = %d\n", psp->pr_pid);
1284                 else
1285                         mdb_printf("no process\n");
1286 
1287                 if (cursig != 0 && sig2str(cursig, signame) == 0)
1288                         mdb_printf("SIG%s: %s\n", signame, strsignal(cursig));
1289         }
1290 
1291         return (pt_regs(addr, flags, argc, argv));
1292 }
1293 
1294 static int
1295 pt_findstack(uintptr_t tid, uint_t flags, int argc, const mdb_arg_t *argv)
1296 {
1297         mdb_tgt_t *t = mdb.m_target;
1298         mdb_tgt_gregset_t gregs;
1299         int showargs = 0;
1300         int count;
1301         uintptr_t pc, sp;
1302 
1303         if (!(flags & DCMD_ADDRSPEC))
1304                 return (DCMD_USAGE);
1305 
1306         count = mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &showargs,
1307             NULL);
1308         argc -= count;
1309         argv += count;
1310 
1311         if (argc > 1 || (argc == 1 && argv->a_type != MDB_TYPE_STRING))
1312                 return (DCMD_USAGE);
1313 
1314         if (PTL_GETREGS(t, tid, gregs.gregs) != 0) {
1315                 mdb_warn("failed to get register set for thread %p", tid);
1316                 return (DCMD_ERR);
1317         }
1318 
1319         pc = gregs.gregs[R_PC];
1320 #if defined(__i386) || defined(__amd64)
1321         sp = gregs.gregs[R_FP];
1322 #else
1323         sp = gregs.gregs[R_SP];
1324 #endif
1325         mdb_printf("stack pointer for thread %p: %p\n", tid, sp);
1326         if (pc != 0)
1327                 mdb_printf("[ %0?lr %a() ]\n", sp, pc);
1328 
1329         (void) mdb_inc_indent(2);
1330         mdb_set_dot(sp);
1331 
1332         if (argc == 1)
1333                 (void) mdb_eval(argv->a_un.a_str);
1334         else if (showargs)
1335                 (void) mdb_eval("<.$C");
1336         else
1337                 (void) mdb_eval("<.$C0");
1338 
1339         (void) mdb_dec_indent(2);
1340         return (DCMD_OK);
1341 }
1342 
1343 /*ARGSUSED*/
1344 static int
1345 pt_gcore(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1346 {
1347         mdb_tgt_t *t = mdb.m_target;
1348         char *prefix = "core";
1349         char *content_str = NULL;
1350         core_content_t content = CC_CONTENT_DEFAULT;
1351         size_t size;
1352         char *fname;
1353         pid_t pid;
1354 
1355         if (flags & DCMD_ADDRSPEC)
1356                 return (DCMD_USAGE);
1357 
1358         if (mdb_getopts(argc, argv,
1359             'o', MDB_OPT_STR, &prefix,
1360             'c', MDB_OPT_STR, &content_str, NULL) != argc)
1361                 return (DCMD_USAGE);
1362 
1363         if (content_str != NULL &&
1364             (proc_str2content(content_str, &content) != 0 ||
1365             content == CC_CONTENT_INVALID)) {
1366                 mdb_warn("invalid content string '%s'\n", content_str);
1367                 return (DCMD_ERR);
1368         }
1369 
1370         if (t->t_pshandle == NULL) {
1371                 mdb_warn("no process active\n");
1372                 return (DCMD_ERR);
1373         }
1374 
1375         pid = Pstatus(t->t_pshandle)->pr_pid;
1376         size = 1 + mdb_snprintf(NULL, 0, "%s.%d", prefix, (int)pid);
1377         fname = mdb_alloc(size, UM_SLEEP | UM_GC);
1378         (void) mdb_snprintf(fname, size, "%s.%d", prefix, (int)pid);
1379 
1380         if (Pgcore(t->t_pshandle, fname, content) != 0) {
1381                 mdb_warn("couldn't dump core");
1382                 return (DCMD_ERR);
1383         }
1384 
1385         mdb_warn("%s dumped\n", fname);
1386 
1387         return (DCMD_OK);
1388 }
1389 
1390 /*ARGSUSED*/
1391 static int
1392 pt_kill(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1393 {
1394         mdb_tgt_t *t = mdb.m_target;
1395         pt_data_t *pt = t->t_data;
1396         int state;
1397 
1398         if ((flags & DCMD_ADDRSPEC) || argc != 0)
1399                 return (DCMD_USAGE);
1400 
1401         if (t->t_pshandle != NULL &&
1402             (state = Pstate(t->t_pshandle)) != PS_DEAD && state != PS_IDLE) {
1403                 mdb_warn("victim process PID %d forcibly terminated\n",
1404                     (int)Pstatus(t->t_pshandle)->pr_pid);
1405                 pt_pre_detach(t, TRUE);
1406                 pt_release_parents(t);
1407                 Prelease(t->t_pshandle, PRELEASE_KILL);
1408                 t->t_pshandle = pt->p_idlehandle;
1409                 (void) mdb_tgt_status(t, &t->t_status);
1410                 mdb.m_flags &= ~(MDB_FL_VCREATE | MDB_FL_JOBCTL);
1411         } else
1412                 mdb_warn("no victim process is currently under control\n");
1413 
1414         return (DCMD_OK);
1415 }
1416 
1417 /*ARGSUSED*/
1418 static int
1419 pt_detach(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1420 {
1421         mdb_tgt_t *t = mdb.m_target;
1422         pt_data_t *pt = t->t_data;
1423         int rflags = pt->p_rflags;
1424 
1425         if (argc != 0 && argv->a_type == MDB_TYPE_STRING &&
1426             strcmp(argv->a_un.a_str, "-a") == 0) {
1427                 rflags = PRELEASE_HANG | PRELEASE_CLEAR;
1428                 argv++;
1429                 argc--;
1430         }
1431 
1432         if ((flags & DCMD_ADDRSPEC) || argc != 0)
1433                 return (DCMD_USAGE);
1434 
1435         if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_IDLE) {
1436                 mdb_warn("debugger is not currently attached to a process "
1437                     "or core file\n");
1438                 return (DCMD_ERR);
1439         }
1440 
1441         pt_pre_detach(t, TRUE);
1442         pt_release_parents(t);
1443         Prelease(t->t_pshandle, rflags);
1444         t->t_pshandle = pt->p_idlehandle;
1445         (void) mdb_tgt_status(t, &t->t_status);
1446         mdb.m_flags &= ~(MDB_FL_VCREATE | MDB_FL_JOBCTL);
1447 
1448         return (DCMD_OK);
1449 }
1450 
1451 static uintmax_t
1452 reg_disc_get(const mdb_var_t *v)
1453 {
1454         mdb_tgt_t *t = MDB_NV_COOKIE(v);
1455         mdb_tgt_tid_t tid = PTL_TID(t);
1456         mdb_tgt_reg_t r = 0;
1457 
1458         if (tid != (mdb_tgt_tid_t)-1L)
1459                 (void) mdb_tgt_getareg(t, tid, mdb_nv_get_name(v), &r);
1460 
1461         return (r);
1462 }
1463 
1464 static void
1465 reg_disc_set(mdb_var_t *v, uintmax_t r)
1466 {
1467         mdb_tgt_t *t = MDB_NV_COOKIE(v);
1468         mdb_tgt_tid_t tid = PTL_TID(t);
1469 
1470         if (tid != (mdb_tgt_tid_t)-1L && mdb_tgt_putareg(t, tid,
1471             mdb_nv_get_name(v), r) == -1)
1472                 mdb_warn("failed to modify %%%s register", mdb_nv_get_name(v));
1473 }
1474 
1475 static void
1476 pt_print_reason(const lwpstatus_t *psp)
1477 {
1478         char name[SIG2STR_MAX + 4]; /* enough for SIG+name+\0, syscall or flt */
1479         const char *desc;
1480 
1481         switch (psp->pr_why) {
1482         case PR_REQUESTED:
1483                 mdb_printf("stopped by debugger");
1484                 break;
1485         case PR_SIGNALLED:
1486                 mdb_printf("stopped on %s (%s)", proc_signame(psp->pr_what,
1487                     name, sizeof (name)), strsignal(psp->pr_what));
1488                 break;
1489         case PR_SYSENTRY:
1490                 mdb_printf("stopped on entry to %s system call",
1491                     proc_sysname(psp->pr_what, name, sizeof (name)));
1492                 break;
1493         case PR_SYSEXIT:
1494                 mdb_printf("stopped on exit from %s system call",
1495                     proc_sysname(psp->pr_what, name, sizeof (name)));
1496                 break;
1497         case PR_JOBCONTROL:
1498                 mdb_printf("stopped by job control");
1499                 break;
1500         case PR_FAULTED:
1501                 if (psp->pr_what == FLTBPT) {
1502                         mdb_printf("stopped on a breakpoint");
1503                 } else if (psp->pr_what == FLTWATCH) {
1504                         switch (psp->pr_info.si_code) {
1505                         case TRAP_RWATCH:
1506                                 desc = "read";
1507                                 break;
1508                         case TRAP_WWATCH:
1509                                 desc = "write";
1510                                 break;
1511                         case TRAP_XWATCH:
1512                                 desc = "execute";
1513                                 break;
1514                         default:
1515                                 desc = "unknown";
1516                         }
1517                         mdb_printf("stopped %s a watchpoint (%s access to %p)",
1518                             psp->pr_info.si_trapafter ? "after" : "on",
1519                             desc, psp->pr_info.si_addr);
1520                 } else if (psp->pr_what == FLTTRACE) {
1521                         mdb_printf("stopped after a single-step");
1522                 } else {
1523                         mdb_printf("stopped on a %s fault",
1524                             proc_fltname(psp->pr_what, name, sizeof (name)));
1525                 }
1526                 break;
1527         case PR_SUSPENDED:
1528         case PR_CHECKPOINT:
1529                 mdb_printf("suspended by the kernel");
1530                 break;
1531         default:
1532                 mdb_printf("stopped for unknown reason (%d/%d)",
1533                     psp->pr_why, psp->pr_what);
1534         }
1535 }
1536 
1537 /*ARGSUSED*/
1538 static int
1539 pt_status_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1540 {
1541         mdb_tgt_t *t = mdb.m_target;
1542         struct ps_prochandle *P = t->t_pshandle;
1543         pt_data_t *pt = t->t_data;
1544 
1545         if (P != NULL) {
1546                 const psinfo_t *pip = Ppsinfo(P);
1547                 const pstatus_t *psp = Pstatus(P);
1548                 int cursig = 0, bits = 0, coredump = 0;
1549                 int state;
1550                 GElf_Sym sym;
1551                 uintptr_t panicstr;
1552                 char panicbuf[128];
1553                 const siginfo_t *sip = &(psp->pr_lwp.pr_info);
1554 
1555                 char execname[MAXPATHLEN], buf[BUFSIZ];
1556                 char signame[SIG2STR_MAX + 4]; /* enough for SIG+name+\0 */
1557 
1558                 mdb_tgt_spec_desc_t desc;
1559                 mdb_sespec_t *sep;
1560 
1561                 struct utsname uts;
1562                 prcred_t cred;
1563                 psinfo_t pi;
1564 
1565                 (void) strcpy(uts.nodename, "unknown machine");
1566                 (void) Puname(P, &uts);
1567 
1568                 if (pip != NULL) {
1569                         bcopy(pip, &pi, sizeof (psinfo_t));
1570                         proc_unctrl_psinfo(&pi);
1571                 } else
1572                         bzero(&pi, sizeof (psinfo_t));
1573 
1574                 bits = pi.pr_dmodel == PR_MODEL_ILP32 ? 32 : 64;
1575 
1576                 state = Pstate(P);
1577                 if (psp != NULL && state != PS_UNDEAD && state != PS_IDLE)
1578                         cursig = psp->pr_lwp.pr_cursig;
1579 
1580                 if (state == PS_DEAD && pip != NULL) {
1581                         mdb_printf("debugging core file of %s (%d-bit) "
1582                             "from %s\n", pi.pr_fname, bits, uts.nodename);
1583 
1584                 } else if (state == PS_DEAD) {
1585                         mdb_printf("debugging core file\n");
1586 
1587                 } else if (state == PS_IDLE) {
1588                         const GElf_Ehdr *ehp = &pt->p_file->gf_ehdr;
1589 
1590                         mdb_printf("debugging %s file (%d-bit)\n",
1591                             ehp->e_type == ET_EXEC ? "executable" : "object",
1592                             ehp->e_ident[EI_CLASS] == ELFCLASS32 ? 32 : 64);
1593 
1594                 } else if (state == PS_UNDEAD && pi.pr_pid == 0) {
1595                         mdb_printf("debugging defunct process\n");
1596 
1597                 } else {
1598                         mdb_printf("debugging PID %d (%d-bit)\n",
1599                             pi.pr_pid, bits);
1600                 }
1601 
1602                 if (Pexecname(P, execname, sizeof (execname)) != NULL)
1603                         mdb_printf("file: %s\n", execname);
1604 
1605                 if (pip != NULL && state == PS_DEAD)
1606                         mdb_printf("initial argv: %s\n", pi.pr_psargs);
1607 
1608                 if (state != PS_UNDEAD && state != PS_IDLE) {
1609                         mdb_printf("threading model: ");
1610                         if (pt->p_ptl_ops == &proc_lwp_ops)
1611                                 mdb_printf("raw lwps\n");
1612                         else
1613                                 mdb_printf("native threads\n");
1614                 }
1615 
1616                 mdb_printf("status: ");
1617                 switch (state) {
1618                 case PS_RUN:
1619                         ASSERT(!(psp->pr_flags & PR_STOPPED));
1620                         mdb_printf("process is running");
1621                         if (psp->pr_flags & PR_DSTOP)
1622                                 mdb_printf(", debugger stop directive pending");
1623                         mdb_printf("\n");
1624                         break;
1625 
1626                 case PS_STOP:
1627                         ASSERT(psp->pr_flags & PR_STOPPED);
1628                         pt_print_reason(&psp->pr_lwp);
1629 
1630                         if (psp->pr_flags & PR_DSTOP)
1631                                 mdb_printf(", debugger stop directive pending");
1632                         if (psp->pr_flags & PR_ASLEEP)
1633                                 mdb_printf(", sleeping in %s system call",
1634                                     proc_sysname(psp->pr_lwp.pr_syscall,
1635                                     signame, sizeof (signame)));
1636 
1637                         mdb_printf("\n");
1638 
1639                         for (sep = t->t_matched; sep != T_SE_END;
1640                             sep = sep->se_matched) {
1641                                 mdb_printf("event: %s\n", sep->se_ops->se_info(
1642                                     t, sep, mdb_list_next(&sep->se_velist),
1643                                     &desc, buf, sizeof (buf)));
1644                         }
1645                         break;
1646 
1647                 case PS_LOST:
1648                         mdb_printf("debugger lost control of process\n");
1649                         break;
1650 
1651                 case PS_UNDEAD:
1652                         coredump = WIFSIGNALED(pi.pr_wstat) &&
1653                             WCOREDUMP(pi.pr_wstat);
1654                         /*FALLTHRU*/
1655 
1656                 case PS_DEAD:
1657                         if (cursig == 0 && WIFSIGNALED(pi.pr_wstat))
1658                                 cursig = WTERMSIG(pi.pr_wstat);
1659                         /*
1660                          * We can only use pr_wstat == 0 as a test for gcore if
1661                          * an NT_PRCRED note is present; these features were
1662                          * added at the same time in Solaris 8.
1663                          */
1664                         if (pi.pr_wstat == 0 && Pstate(P) == PS_DEAD &&
1665                             Pcred(P, &cred, 1) == 0) {
1666                                 mdb_printf("process core file generated "
1667                                     "with gcore(1)\n");
1668                         } else if (cursig != 0) {
1669                                 mdb_printf("process terminated by %s (%s)",
1670                                     proc_signame(cursig, signame,
1671                                     sizeof (signame)), strsignal(cursig));
1672 
1673                                 if (sip->si_signo != 0 && SI_FROMUSER(sip) &&
1674                                     sip->si_pid != 0) {
1675                                         mdb_printf(", pid=%d uid=%u",
1676                                             (int)sip->si_pid, sip->si_uid);
1677                                         if (sip->si_code != 0) {
1678                                                 mdb_printf(" code=%d",
1679                                                     sip->si_code);
1680                                         }
1681                                 } else {
1682                                         switch (sip->si_signo) {
1683                                         case SIGILL:
1684                                         case SIGTRAP:
1685                                         case SIGFPE:
1686                                         case SIGSEGV:
1687                                         case SIGBUS:
1688                                         case SIGEMT:
1689                                                 mdb_printf(", addr=%p",
1690                                                     sip->si_addr);
1691                                         default:
1692                                                 break;
1693                                         }
1694                                 }
1695 
1696                                 if (coredump)
1697                                         mdb_printf(" - core file dumped");
1698                                 mdb_printf("\n");
1699                         } else {
1700                                 mdb_printf("process terminated with exit "
1701                                     "status %d\n", WEXITSTATUS(pi.pr_wstat));
1702                         }
1703 
1704                         if (Plookup_by_name(t->t_pshandle, "libc.so",
1705                             "panicstr", &sym) == 0 &&
1706                             Pread(t->t_pshandle, &panicstr, sizeof (panicstr),
1707                             sym.st_value) == sizeof (panicstr) &&
1708                             Pread_string(t->t_pshandle, panicbuf,
1709                             sizeof (panicbuf), panicstr) > 0) {
1710                                 mdb_printf("panic message: %s",
1711                                     panicbuf);
1712                         }
1713 
1714 
1715                         break;
1716 
1717                 case PS_IDLE:
1718                         mdb_printf("idle\n");
1719                         break;
1720 
1721                 default:
1722                         mdb_printf("unknown libproc Pstate: %d\n", Pstate(P));
1723                 }
1724 
1725         } else if (pt->p_file != NULL) {
1726                 const GElf_Ehdr *ehp = &pt->p_file->gf_ehdr;
1727 
1728                 mdb_printf("debugging %s file (%d-bit)\n",
1729                     ehp->e_type == ET_EXEC ? "executable" : "object",
1730                     ehp->e_ident[EI_CLASS] == ELFCLASS32 ? 32 : 64);
1731                 mdb_printf("executable file: %s\n", IOP_NAME(pt->p_fio));
1732                 mdb_printf("status: idle\n");
1733         }
1734 
1735         return (DCMD_OK);
1736 }
1737 
1738 static int
1739 pt_tls(uintptr_t tid, uint_t flags, int argc, const mdb_arg_t *argv)
1740 {
1741         const char *name;
1742         const char *object;
1743         GElf_Sym sym;
1744         mdb_syminfo_t si;
1745         mdb_tgt_t *t = mdb.m_target;
1746 
1747         if (!(flags & DCMD_ADDRSPEC) || argc > 1)
1748                 return (DCMD_USAGE);
1749 
1750         if (argc == 0) {
1751                 psaddr_t b;
1752 
1753                 if (tlsbase(t, tid, PR_LMID_EVERY, MDB_TGT_OBJ_EXEC, &b) != 0) {
1754                         mdb_warn("failed to lookup tlsbase for %r", tid);
1755                         return (DCMD_ERR);
1756                 }
1757 
1758                 mdb_printf("%lr\n", b);
1759                 mdb_set_dot(b);
1760 
1761                 return (DCMD_OK);
1762         }
1763 
1764         name = argv[0].a_un.a_str;
1765         object = MDB_TGT_OBJ_EVERY;
1766 
1767         if (pt_lookup_by_name_thr(t, object, name, &sym, &si, tid) != 0) {
1768                 mdb_warn("failed to lookup %s", name);
1769                 return (DCMD_ABORT); /* avoid repeated failure */
1770         }
1771 
1772         if (GELF_ST_TYPE(sym.st_info) != STT_TLS && DCMD_HDRSPEC(flags))
1773                 mdb_warn("%s does not refer to thread local storage\n", name);
1774 
1775         mdb_printf("%llr\n", sym.st_value);
1776         mdb_set_dot(sym.st_value);
1777 
1778         return (DCMD_OK);
1779 }
1780 
1781 /*ARGSUSED*/
1782 static int
1783 pt_tmodel(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1784 {
1785         mdb_tgt_t *t = mdb.m_target;
1786         pt_data_t *pt = t->t_data;
1787         const pt_ptl_ops_t *ptl_ops;
1788 
1789         if (argc != 1 || argv->a_type != MDB_TYPE_STRING)
1790                 return (DCMD_USAGE);
1791 
1792         if (strcmp(argv->a_un.a_str, "thread") == 0)
1793                 ptl_ops = &proc_tdb_ops;
1794         else if (strcmp(argv->a_un.a_str, "lwp") == 0)
1795                 ptl_ops = &proc_lwp_ops;
1796         else
1797                 return (DCMD_USAGE);
1798 
1799         if (t->t_pshandle != NULL && pt->p_ptl_ops != ptl_ops) {
1800                 PTL_DTOR(t);
1801                 pt->p_tdb_ops = NULL;
1802                 pt->p_ptl_ops = &proc_lwp_ops;
1803                 pt->p_ptl_hdl = NULL;
1804 
1805                 if (ptl_ops == &proc_tdb_ops) {
1806                         (void) Pobject_iter(t->t_pshandle, (proc_map_f *)
1807                             thr_check, t);
1808                 }
1809         }
1810 
1811         (void) mdb_tgt_status(t, &t->t_status);
1812         return (DCMD_OK);
1813 }
1814 
1815 static const char *
1816 env_match(const char *cmp, const char *nameval)
1817 {
1818         const char *loc;
1819         size_t cmplen = strlen(cmp);
1820 
1821         loc = strchr(nameval, '=');
1822         if (loc != NULL && (loc - nameval) == cmplen &&
1823             strncmp(nameval, cmp, cmplen) == 0) {
1824                 return (loc + 1);
1825         }
1826 
1827         return (NULL);
1828 }
1829 
1830 /*ARGSUSED*/
1831 static int
1832 print_env(void *data, struct ps_prochandle *P, uintptr_t addr,
1833     const char *nameval)
1834 {
1835         const char *value;
1836 
1837         if (nameval == NULL) {
1838                 mdb_printf("<0x%p>\n", addr);
1839         } else {
1840                 if (data == NULL)
1841                         mdb_printf("%s\n", nameval);
1842                 else if ((value = env_match(data, nameval)) != NULL)
1843                         mdb_printf("%s\n", value);
1844         }
1845 
1846         return (0);
1847 }
1848 
1849 /*ARGSUSED*/
1850 static int
1851 pt_getenv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1852 {
1853         mdb_tgt_t *t = mdb.m_target;
1854         pt_data_t *pt = t->t_data;
1855         int i;
1856         uint_t opt_t = 0;
1857         mdb_var_t *v;
1858 
1859         i = mdb_getopts(argc, argv,
1860             't', MDB_OPT_SETBITS, TRUE, &opt_t, NULL);
1861 
1862         argc -= i;
1863         argv += i;
1864 
1865         if ((flags & DCMD_ADDRSPEC) || argc > 1)
1866                 return (DCMD_USAGE);
1867 
1868         if (argc == 1 && argv->a_type != MDB_TYPE_STRING)
1869                 return (DCMD_USAGE);
1870 
1871         if (opt_t && t->t_pshandle == NULL) {
1872                 mdb_warn("no process active\n");
1873                 return (DCMD_ERR);
1874         }
1875 
1876         if (opt_t && (Pstate(t->t_pshandle) == PS_IDLE ||
1877             Pstate(t->t_pshandle) == PS_UNDEAD)) {
1878                 mdb_warn("-t option requires target to be running\n");
1879                 return (DCMD_ERR);
1880         }
1881 
1882         if (opt_t != 0) {
1883                 if (Penv_iter(t->t_pshandle, print_env,
1884                     argc == 0 ? NULL : (void *)argv->a_un.a_str) != 0)
1885                         return (DCMD_ERR);
1886         } else if (argc == 1) {
1887                 if ((v = mdb_nv_lookup(&pt->p_env, argv->a_un.a_str)) == NULL)
1888                         return (DCMD_ERR);
1889 
1890                 ASSERT(strchr(mdb_nv_get_cookie(v), '=') != NULL);
1891                 mdb_printf("%s\n", strchr(mdb_nv_get_cookie(v), '=') + 1);
1892         } else {
1893 
1894                 mdb_nv_rewind(&pt->p_env);
1895                 while ((v = mdb_nv_advance(&pt->p_env)) != NULL)
1896                         mdb_printf("%s\n", mdb_nv_get_cookie(v));
1897         }
1898 
1899         return (DCMD_OK);
1900 }
1901 
1902 /*
1903  * Function to set a variable in the internal environment, which is used when
1904  * creating new processes.  Note that it is possible that 'nameval' can refer to
1905  * read-only memory, if mdb calls putenv() on an existing value before calling
1906  * this function.  While we should avoid this situation, this function is
1907  * designed to be robust in the face of such changes.
1908  */
1909 static void
1910 pt_env_set(pt_data_t *pt, const char *nameval)
1911 {
1912         mdb_var_t *v;
1913         char *equals, *val;
1914         const char *name;
1915         size_t len;
1916 
1917         if ((equals = strchr(nameval, '=')) != NULL) {
1918                 val = strdup(nameval);
1919                 equals = val + (equals - nameval);
1920         } else {
1921                 /*
1922                  * nameval doesn't contain an equals character.  Convert this to
1923                  * be 'nameval='.
1924                  */
1925                 len = strlen(nameval);
1926                 val = mdb_alloc(len + 2, UM_SLEEP);
1927                 (void) mdb_snprintf(val, len + 2, "%s=", nameval);
1928                 equals = val + len;
1929         }
1930 
1931         /* temporary truncate the string for lookup/insert */
1932         *equals = '\0';
1933         v = mdb_nv_lookup(&pt->p_env, val);
1934 
1935         if (v != NULL) {
1936                 char *old = mdb_nv_get_cookie(v);
1937                 mdb_free(old, strlen(old) + 1);
1938                 name = mdb_nv_get_name(v);
1939         } else {
1940                 /*
1941                  * The environment is created using MDB_NV_EXTNAME, so we must
1942                  * provide external storage for the variable names.
1943                  */
1944                 name = strdup(val);
1945         }
1946 
1947         *equals = '=';
1948 
1949         (void) mdb_nv_insert(&pt->p_env, name, NULL, (uintptr_t)val,
1950             MDB_NV_EXTNAME);
1951 
1952         if (equals)
1953                 *equals = '=';
1954 }
1955 
1956 /*
1957  * Clears the internal environment.
1958  */
1959 static void
1960 pt_env_clear(pt_data_t *pt)
1961 {
1962         mdb_var_t *v;
1963         char *val, *name;
1964 
1965         mdb_nv_rewind(&pt->p_env);
1966         while ((v = mdb_nv_advance(&pt->p_env)) != NULL) {
1967 
1968                 name = (char *)mdb_nv_get_name(v);
1969                 val = mdb_nv_get_cookie(v);
1970 
1971                 mdb_nv_remove(&pt->p_env, v);
1972 
1973                 mdb_free(name, strlen(name) + 1);
1974                 mdb_free(val, strlen(val) + 1);
1975         }
1976 }
1977 
1978 /*ARGSUSED*/
1979 static int
1980 pt_setenv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1981 {
1982         mdb_tgt_t *t = mdb.m_target;
1983         pt_data_t *pt = t->t_data;
1984         char *nameval;
1985         size_t len;
1986         int alloc;
1987 
1988         if ((flags & DCMD_ADDRSPEC) || argc == 0 || argc > 2)
1989                 return (DCMD_USAGE);
1990 
1991         if ((argc > 0 && argv[0].a_type != MDB_TYPE_STRING) ||
1992             (argc > 1 && argv[1].a_type != MDB_TYPE_STRING))
1993                 return (DCMD_USAGE);
1994 
1995         if (t->t_pshandle == NULL) {
1996                 mdb_warn("no process active\n");
1997                 return (DCMD_ERR);
1998         }
1999 
2000         /*
2001          * If the process is in some sort of running state, warn the user that
2002          * changes won't immediately take effect.
2003          */
2004         if (Pstate(t->t_pshandle) == PS_RUN ||
2005             Pstate(t->t_pshandle) == PS_STOP) {
2006                 mdb_warn("warning: changes will not take effect until process"
2007                     " is restarted\n");
2008         }
2009 
2010         /*
2011          * We allow two forms of operation.  The first is the usual "name=value"
2012          * parameter.  We also allow the user to specify two arguments, where
2013          * the first is the name of the variable, and the second is the value.
2014          */
2015         alloc = 0;
2016         if (argc == 1) {
2017                 nameval = (char *)argv->a_un.a_str;
2018         } else {
2019                 len = strlen(argv[0].a_un.a_str) +
2020                     strlen(argv[1].a_un.a_str) + 2;
2021                 nameval = mdb_alloc(len, UM_SLEEP);
2022                 (void) mdb_snprintf(nameval, len, "%s=%s", argv[0].a_un.a_str,
2023                     argv[1].a_un.a_str);
2024                 alloc = 1;
2025         }
2026 
2027         pt_env_set(pt, nameval);
2028 
2029         if (alloc)
2030                 mdb_free(nameval, strlen(nameval) + 1);
2031 
2032         return (DCMD_OK);
2033 }
2034 
2035 /*ARGSUSED*/
2036 static int
2037 pt_unsetenv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2038 {
2039         mdb_tgt_t *t = mdb.m_target;
2040         pt_data_t *pt = t->t_data;
2041         mdb_var_t *v;
2042         char *value, *name;
2043 
2044         if ((flags & DCMD_ADDRSPEC) || argc > 1)
2045                 return (DCMD_USAGE);
2046 
2047         if (argc == 1 && argv->a_type != MDB_TYPE_STRING)
2048                 return (DCMD_USAGE);
2049 
2050         if (t->t_pshandle == NULL) {
2051                 mdb_warn("no process active\n");
2052                 return (DCMD_ERR);
2053         }
2054 
2055         /*
2056          * If the process is in some sort of running state, warn the user that
2057          * changes won't immediately take effect.
2058          */
2059         if (Pstate(t->t_pshandle) == PS_RUN ||
2060             Pstate(t->t_pshandle) == PS_STOP) {
2061                 mdb_warn("warning: changes will not take effect until process"
2062                     " is restarted\n");
2063         }
2064 
2065         if (argc == 0) {
2066                 pt_env_clear(pt);
2067         } else {
2068                 if ((v = mdb_nv_lookup(&pt->p_env, argv->a_un.a_str)) != NULL) {
2069                         name = (char *)mdb_nv_get_name(v);
2070                         value = mdb_nv_get_cookie(v);
2071 
2072                         mdb_nv_remove(&pt->p_env, v);
2073 
2074                         mdb_free(name, strlen(name) + 1);
2075                         mdb_free(value, strlen(value) + 1);
2076                 }
2077         }
2078 
2079         return (DCMD_OK);
2080 }
2081 
2082 void
2083 getenv_help(void)
2084 {
2085         mdb_printf("-t  show current process environment"
2086             " instead of initial environment.\n");
2087 }
2088 
2089 static const mdb_dcmd_t pt_dcmds[] = {
2090         { "$c", "?[cnt]", "print stack backtrace", pt_stack },
2091         { "$C", "?[cnt]", "print stack backtrace", pt_stackv },
2092         { "$i", NULL, "print signals that are ignored", pt_ignored },
2093         { "$l", NULL, "print the representative thread's lwp id", pt_lwpid },
2094         { "$L", NULL, "print list of the active lwp ids", pt_lwpids },
2095         { "$r", "?", "print general-purpose registers", pt_regs },
2096         { "$x", "?", "print floating point registers", pt_fpregs },
2097         { "$X", "?", "print floating point registers", pt_fpregs },
2098         { "$y", "?", "print floating point registers", pt_fpregs },
2099         { "$Y", "?", "print floating point registers", pt_fpregs },
2100         { "$?", "?", "print status and registers", pt_regstatus },
2101         { ":A", "?[core|pid]", "attach to process or core file", pt_attach },
2102         { ":i", ":", "ignore signal (delete all matching events)", pt_ignore },
2103         { ":k", NULL, "forcibly kill and release target", pt_kill },
2104         { ":R", "[-a]", "release the previously attached process", pt_detach },
2105         { "attach", "?[core|pid]",
2106             "attach to process or core file", pt_attach },
2107         { "findstack", ":[-v]", "find user thread stack", pt_findstack },
2108         { "gcore", "[-o prefix] [-c content]",
2109             "produce a core file for the attached process", pt_gcore },
2110         { "getenv", "[-t] [name]", "display an environment variable",
2111                 pt_getenv, getenv_help },
2112         { "kill", NULL, "forcibly kill and release target", pt_kill },
2113         { "release", "[-a]",
2114             "release the previously attached process", pt_detach },
2115         { "regs", "?", "print general-purpose registers", pt_regs },
2116         { "fpregs", "?[-dqs]", "print floating point registers", pt_fpregs },
2117         { "setenv", "name=value", "set an environment variable", pt_setenv },
2118         { "stack", "?[cnt]", "print stack backtrace", pt_stack },
2119         { "stackregs", "?", "print stack backtrace and registers", pt_stackr },
2120         { "status", NULL, "print summary of current target", pt_status_dcmd },
2121         { "tls", ":symbol",
2122             "lookup TLS data in the context of a given thread", pt_tls },
2123         { "tmodel", "{thread|lwp}", NULL, pt_tmodel },
2124         { "unsetenv", "[name]", "clear an environment variable", pt_unsetenv },
2125         { NULL }
2126 };
2127 
2128 static void
2129 pt_thr_walk_fini(mdb_walk_state_t *wsp)
2130 {
2131         mdb_addrvec_destroy(wsp->walk_data);
2132         mdb_free(wsp->walk_data, sizeof (mdb_addrvec_t));
2133 }
2134 
2135 static int
2136 pt_thr_walk_init(mdb_walk_state_t *wsp)
2137 {
2138         wsp->walk_data = mdb_zalloc(sizeof (mdb_addrvec_t), UM_SLEEP);
2139         mdb_addrvec_create(wsp->walk_data);
2140 
2141         if (PTL_ITER(mdb.m_target, wsp->walk_data) == -1) {
2142                 mdb_warn("failed to iterate over threads");
2143                 pt_thr_walk_fini(wsp);
2144                 return (WALK_ERR);
2145         }
2146 
2147         return (WALK_NEXT);
2148 }
2149 
2150 static int
2151 pt_thr_walk_step(mdb_walk_state_t *wsp)
2152 {
2153         if (mdb_addrvec_length(wsp->walk_data) != 0) {
2154                 return (wsp->walk_callback(mdb_addrvec_shift(wsp->walk_data),
2155                     NULL, wsp->walk_cbdata));
2156         }
2157         return (WALK_DONE);
2158 }
2159 
2160 static const mdb_walker_t pt_walkers[] = {
2161         { "thread", "walk list of valid thread identifiers",
2162             pt_thr_walk_init, pt_thr_walk_step, pt_thr_walk_fini },
2163         { NULL }
2164 };
2165 
2166 
2167 static void
2168 pt_activate_common(mdb_tgt_t *t)
2169 {
2170         pt_data_t *pt = t->t_data;
2171         GElf_Sym sym;
2172 
2173         /*
2174          * If we have a libproc handle and AT_BASE is set, the process or core
2175          * is dynamically linked.  We call Prd_agent() to force libproc to
2176          * try to initialize librtld_db, and issue a warning if that fails.
2177          */
2178         if (t->t_pshandle != NULL && Pgetauxval(t->t_pshandle,
2179             AT_BASE) != -1L && Prd_agent(t->t_pshandle) == NULL) {
2180                 mdb_warn("warning: librtld_db failed to initialize; shared "
2181                     "library information will not be available\n");
2182         }
2183 
2184         /*
2185          * If we have a libproc handle and libthread is loaded, attempt to load
2186          * and initialize the corresponding libthread_db.  If this fails, fall
2187          * back to our native LWP implementation and issue a warning.
2188          */
2189         if (t->t_pshandle != NULL && Pstate(t->t_pshandle) != PS_IDLE)
2190                 (void) Pobject_iter(t->t_pshandle, (proc_map_f *)thr_check, t);
2191 
2192         /*
2193          * If there's a global object named '_mdb_abort_info', assuming we're
2194          * debugging mdb itself and load the developer support module.
2195          */
2196         if (mdb_gelf_symtab_lookup_by_name(pt->p_symtab, "_mdb_abort_info",
2197             &sym, NULL) == 0 && GELF_ST_TYPE(sym.st_info) == STT_OBJECT) {
2198                 if (mdb_module_load("mdb_ds", MDB_MOD_SILENT) < 0)
2199                         mdb_warn("warning: failed to load developer support\n");
2200         }
2201 
2202         mdb_tgt_elf_export(pt->p_file);
2203 }
2204 
2205 static void
2206 pt_activate(mdb_tgt_t *t)
2207 {
2208         static const mdb_nv_disc_t reg_disc = { reg_disc_set, reg_disc_get };
2209 
2210         pt_data_t *pt = t->t_data;
2211         struct utsname u1, u2;
2212         mdb_var_t *v;
2213         core_content_t content;
2214 
2215         if (t->t_pshandle) {
2216                 mdb_prop_postmortem = (Pstate(t->t_pshandle) == PS_DEAD);
2217                 mdb_prop_kernel = FALSE;
2218         } else
2219                 mdb_prop_kernel = mdb_prop_postmortem = FALSE;
2220 
2221         mdb_prop_datamodel = MDB_TGT_MODEL_NATIVE;
2222 
2223         /*
2224          * If we're examining a core file that doesn't contain program text,
2225          * and uname(2) doesn't match the NT_UTSNAME note recorded in the
2226          * core file, issue a warning.
2227          */
2228         if (mdb_prop_postmortem == TRUE &&
2229             ((content = Pcontent(t->t_pshandle)) == CC_CONTENT_INVALID ||
2230             !(content & CC_CONTENT_TEXT)) &&
2231             uname(&u1) >= 0 && Puname(t->t_pshandle, &u2) == 0 &&
2232             (strcmp(u1.release, u2.release) != 0 ||
2233             strcmp(u1.version, u2.version) != 0)) {
2234                 mdb_warn("warning: core file is from %s %s %s; shared text "
2235                     "mappings may not match installed libraries\n",
2236                     u2.sysname, u2.release, u2.version);
2237         }
2238 
2239         /*
2240          * Perform the common initialization tasks -- these are shared with
2241          * the pt_exec() and pt_run() subroutines.
2242          */
2243         pt_activate_common(t);
2244 
2245         (void) mdb_tgt_register_dcmds(t, &pt_dcmds[0], MDB_MOD_FORCE);
2246         (void) mdb_tgt_register_walkers(t, &pt_walkers[0], MDB_MOD_FORCE);
2247 
2248         /*
2249          * Iterate through our register description list and export
2250          * each register as a named variable.
2251          */
2252         mdb_nv_rewind(&pt->p_regs);
2253         while ((v = mdb_nv_advance(&pt->p_regs)) != NULL) {
2254                 ushort_t rd_flags = MDB_TGT_R_FLAGS(mdb_nv_get_value(v));
2255 
2256                 if (!(rd_flags & MDB_TGT_R_EXPORT))
2257                         continue; /* Don't export register as a variable */
2258 
2259                 (void) mdb_nv_insert(&mdb.m_nv, mdb_nv_get_name(v), &reg_disc,
2260                     (uintptr_t)t, MDB_NV_PERSIST);
2261         }
2262 }
2263 
2264 static void
2265 pt_deactivate(mdb_tgt_t *t)
2266 {
2267         pt_data_t *pt = t->t_data;
2268         const mdb_dcmd_t *dcp;
2269         const mdb_walker_t *wp;
2270         mdb_var_t *v, *w;
2271 
2272         mdb_nv_rewind(&pt->p_regs);
2273         while ((v = mdb_nv_advance(&pt->p_regs)) != NULL) {
2274                 ushort_t rd_flags = MDB_TGT_R_FLAGS(mdb_nv_get_value(v));
2275 
2276                 if (!(rd_flags & MDB_TGT_R_EXPORT))
2277                         continue; /* Didn't export register as a variable */
2278 
2279                 if (w = mdb_nv_lookup(&mdb.m_nv, mdb_nv_get_name(v))) {
2280                         w->v_flags &= ~MDB_NV_PERSIST;
2281                         mdb_nv_remove(&mdb.m_nv, w);
2282                 }
2283         }
2284 
2285         for (wp = &pt_walkers[0]; wp->walk_name != NULL; wp++) {
2286                 if (mdb_module_remove_walker(t->t_module, wp->walk_name) == -1)
2287                         warn("failed to remove walk %s", wp->walk_name);
2288         }
2289 
2290         for (dcp = &pt_dcmds[0]; dcp->dc_name != NULL; dcp++) {
2291                 if (mdb_module_remove_dcmd(t->t_module, dcp->dc_name) == -1)
2292                         warn("failed to remove dcmd %s", dcp->dc_name);
2293         }
2294 
2295         mdb_prop_postmortem = FALSE;
2296         mdb_prop_kernel = FALSE;
2297         mdb_prop_datamodel = MDB_TGT_MODEL_UNKNOWN;
2298 }
2299 
2300 static void
2301 pt_periodic(mdb_tgt_t *t)
2302 {
2303         pt_data_t *pt = t->t_data;
2304 
2305         if (pt->p_rdstate == PT_RD_CONSIST) {
2306                 if (t->t_pshandle != NULL && Pstate(t->t_pshandle) < PS_LOST &&
2307                     !(mdb.m_flags & MDB_FL_NOMODS)) {
2308                         mdb_printf("%s: You've got symbols!\n", mdb.m_pname);
2309                         mdb_module_load_all(0);
2310                 }
2311                 pt->p_rdstate = PT_RD_NONE;
2312         }
2313 }
2314 
2315 static void
2316 pt_destroy(mdb_tgt_t *t)
2317 {
2318         pt_data_t *pt = t->t_data;
2319 
2320         if (pt->p_idlehandle != NULL && pt->p_idlehandle != t->t_pshandle)
2321                 Prelease(pt->p_idlehandle, 0);
2322 
2323         if (t->t_pshandle != NULL) {
2324                 PTL_DTOR(t);
2325                 pt_release_parents(t);
2326                 pt_pre_detach(t, TRUE);
2327                 Prelease(t->t_pshandle, pt->p_rflags);
2328         }
2329 
2330         mdb.m_flags &= ~(MDB_FL_VCREATE | MDB_FL_JOBCTL);
2331         pt_close_aout(t);
2332 
2333         if (pt->p_aout_fio != NULL)
2334                 mdb_io_rele(pt->p_aout_fio);
2335 
2336         pt_env_clear(pt);
2337         mdb_nv_destroy(&pt->p_env);
2338 
2339         mdb_nv_destroy(&pt->p_regs);
2340         mdb_free(pt, sizeof (pt_data_t));
2341 }
2342 
2343 /*ARGSUSED*/
2344 static const char *
2345 pt_name(mdb_tgt_t *t)
2346 {
2347         return ("proc");
2348 }
2349 
2350 static const char *
2351 pt_platform(mdb_tgt_t *t)
2352 {
2353         pt_data_t *pt = t->t_data;
2354 
2355         if (t->t_pshandle != NULL &&
2356             Pplatform(t->t_pshandle, pt->p_platform, MAXNAMELEN) != NULL)
2357                 return (pt->p_platform);
2358 
2359         return (mdb_conf_platform());
2360 }
2361 
2362 static int
2363 pt_uname(mdb_tgt_t *t, struct utsname *utsp)
2364 {
2365         if (t->t_pshandle != NULL)
2366                 return (Puname(t->t_pshandle, utsp));
2367 
2368         return (uname(utsp) >= 0 ? 0 : -1);
2369 }
2370 
2371 static int
2372 pt_dmodel(mdb_tgt_t *t)
2373 {
2374         if (t->t_pshandle == NULL)
2375                 return (MDB_TGT_MODEL_NATIVE);
2376 
2377         switch (Pstatus(t->t_pshandle)->pr_dmodel) {
2378         case PR_MODEL_ILP32:
2379                 return (MDB_TGT_MODEL_ILP32);
2380         case PR_MODEL_LP64:
2381                 return (MDB_TGT_MODEL_LP64);
2382         }
2383 
2384         return (MDB_TGT_MODEL_UNKNOWN);
2385 }
2386 
2387 static ssize_t
2388 pt_vread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr)
2389 {
2390         ssize_t n;
2391 
2392         /*
2393          * If no handle is open yet, reads from virtual addresses are
2394          * allowed to succeed but return zero-filled memory.
2395          */
2396         if (t->t_pshandle == NULL) {
2397                 bzero(buf, nbytes);
2398                 return (nbytes);
2399         }
2400 
2401         if ((n = Pread(t->t_pshandle, buf, nbytes, addr)) <= 0)
2402                 return (set_errno(EMDB_NOMAP));
2403 
2404         return (n);
2405 }
2406 
2407 static ssize_t
2408 pt_vwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
2409 {
2410         ssize_t n;
2411 
2412         /*
2413          * If no handle is open yet, writes to virtual addresses are
2414          * allowed to succeed but do not actually modify anything.
2415          */
2416         if (t->t_pshandle == NULL)
2417                 return (nbytes);
2418 
2419         n = Pwrite(t->t_pshandle, buf, nbytes, addr);
2420 
2421         if (n == -1 && errno == EIO)
2422                 return (set_errno(EMDB_NOMAP));
2423 
2424         return (n);
2425 }
2426 
2427 static ssize_t
2428 pt_fread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr)
2429 {
2430         pt_data_t *pt = t->t_data;
2431 
2432         if (pt->p_file != NULL) {
2433                 return (mdb_gelf_rw(pt->p_file, buf, nbytes, addr,
2434                     IOPF_READ(pt->p_fio), GIO_READ));
2435         }
2436 
2437         bzero(buf, nbytes);
2438         return (nbytes);
2439 }
2440 
2441 static ssize_t
2442 pt_fwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
2443 {
2444         pt_data_t *pt = t->t_data;
2445 
2446         if (pt->p_file != NULL) {
2447                 return (mdb_gelf_rw(pt->p_file, (void *)buf, nbytes, addr,
2448                     IOPF_WRITE(pt->p_fio), GIO_WRITE));
2449         }
2450 
2451         return (nbytes);
2452 }
2453 
2454 static const char *
2455 pt_resolve_lmid(const char *object, Lmid_t *lmidp)
2456 {
2457         Lmid_t lmid = PR_LMID_EVERY;
2458         const char *p;
2459 
2460         if (object == MDB_TGT_OBJ_EVERY || object == MDB_TGT_OBJ_EXEC)
2461                 lmid = LM_ID_BASE; /* restrict scope to a.out's link map */
2462         else if (object != MDB_TGT_OBJ_RTLD && strncmp(object, "LM", 2) == 0 &&
2463             (p = strchr(object, '`')) != NULL) {
2464                 object += 2;    /* skip past initial "LM" prefix */
2465                 lmid = strntoul(object, (size_t)(p - object), mdb.m_radix);
2466                 object = p + 1; /* skip past link map specifier */
2467         }
2468 
2469         *lmidp = lmid;
2470         return (object);
2471 }
2472 
2473 static int
2474 tlsbase(mdb_tgt_t *t, mdb_tgt_tid_t tid, Lmid_t lmid, const char *object,
2475     psaddr_t *basep)
2476 {
2477         pt_data_t *pt = t->t_data;
2478         const rd_loadobj_t *loadobjp;
2479         td_thrhandle_t th;
2480         td_err_e err;
2481 
2482         if (object == MDB_TGT_OBJ_EVERY)
2483                 return (set_errno(EINVAL));
2484 
2485         if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_IDLE)
2486                 return (set_errno(EMDB_NOPROC));
2487 
2488         if (pt->p_tdb_ops == NULL)
2489                 return (set_errno(EMDB_TDB));
2490 
2491         err = pt->p_tdb_ops->td_ta_map_id2thr(pt->p_ptl_hdl, tid, &th);
2492         if (err != TD_OK)
2493                 return (set_errno(tdb_to_errno(err)));
2494 
2495         /*
2496          * If this fails, rtld_db has failed to initialize properly.
2497          */
2498         if ((loadobjp = Plmid_to_loadobj(t->t_pshandle, lmid, object)) == NULL)
2499                 return (set_errno(EMDB_NORTLD));
2500 
2501         /*
2502          * This will fail if the TLS block has not been allocated for the
2503          * object that contains the TLS symbol in question.
2504          */
2505         err = pt->p_tdb_ops->td_thr_tlsbase(&th, loadobjp->rl_tlsmodid, basep);
2506         if (err != TD_OK)
2507                 return (set_errno(tdb_to_errno(err)));
2508 
2509         return (0);
2510 }
2511 
2512 typedef struct {
2513         mdb_tgt_t       *pl_tgt;
2514         const char      *pl_name;
2515         Lmid_t          pl_lmid;
2516         GElf_Sym        *pl_symp;
2517         mdb_syminfo_t   *pl_sip;
2518         mdb_tgt_tid_t   pl_tid;
2519         mdb_bool_t      pl_found;
2520 } pt_lookup_t;
2521 
2522 /*ARGSUSED*/
2523 static int
2524 pt_lookup_cb(void *data, const prmap_t *pmp, const char *object)
2525 {
2526         pt_lookup_t *plp = data;
2527         struct ps_prochandle *P = plp->pl_tgt->t_pshandle;
2528         prsyminfo_t si;
2529         GElf_Sym sym;
2530 
2531         if (Pxlookup_by_name(P, plp->pl_lmid, object, plp->pl_name, &sym,
2532             &si) != 0)
2533                 return (0);
2534 
2535         /*
2536          * If we encounter a match with SHN_UNDEF, keep looking for a
2537          * better match. Return the first match with SHN_UNDEF set if no
2538          * better match is found.
2539          */
2540         if (sym.st_shndx == SHN_UNDEF) {
2541                 if (!plp->pl_found) {
2542                         plp->pl_found = TRUE;
2543                         *plp->pl_symp = sym;
2544                         plp->pl_sip->sym_table = si.prs_table;
2545                         plp->pl_sip->sym_id = si.prs_id;
2546                 }
2547 
2548                 return (0);
2549         }
2550 
2551         /*
2552          * Note that if the symbol's st_shndx is SHN_UNDEF we don't have the
2553          * TLS offset anyway, so adding in the tlsbase would be worthless.
2554          */
2555         if (GELF_ST_TYPE(sym.st_info) == STT_TLS &&
2556             plp->pl_tid != (mdb_tgt_tid_t)-1) {
2557                 psaddr_t base;
2558 
2559                 if (tlsbase(plp->pl_tgt, plp->pl_tid, plp->pl_lmid, object,
2560                     &base) != 0)
2561                         return (-1); /* errno is set for us */
2562 
2563                 sym.st_value += base;
2564         }
2565 
2566         plp->pl_found = TRUE;
2567         *plp->pl_symp = sym;
2568         plp->pl_sip->sym_table = si.prs_table;
2569         plp->pl_sip->sym_id = si.prs_id;
2570 
2571         return (1);
2572 }
2573 
2574 /*
2575  * Lookup the symbol with a thread context so that we can adjust TLS symbols
2576  * to get the values as they would appear in the context of the given thread.
2577  */
2578 static int
2579 pt_lookup_by_name_thr(mdb_tgt_t *t, const char *object,
2580     const char *name, GElf_Sym *symp, mdb_syminfo_t *sip, mdb_tgt_tid_t tid)
2581 {
2582         struct ps_prochandle *P = t->t_pshandle;
2583         pt_data_t *pt = t->t_data;
2584         Lmid_t lmid;
2585         uint_t i;
2586         const rd_loadobj_t *aout_lop;
2587 
2588         object = pt_resolve_lmid(object, &lmid);
2589 
2590         if (P != NULL) {
2591                 pt_lookup_t pl;
2592 
2593                 pl.pl_tgt = t;
2594                 pl.pl_name = name;
2595                 pl.pl_lmid = lmid;
2596                 pl.pl_symp = symp;
2597                 pl.pl_sip = sip;
2598                 pl.pl_tid = tid;
2599                 pl.pl_found = FALSE;
2600 
2601                 if (object == MDB_TGT_OBJ_EVERY) {
2602                         if (Pobject_iter_resolved(P, pt_lookup_cb, &pl) == -1)
2603                                 return (-1); /* errno is set for us */
2604                         if ((!pl.pl_found) &&
2605                             (Pobject_iter(P, pt_lookup_cb, &pl) == -1))
2606                                 return (-1); /* errno is set for us */
2607                 } else {
2608                         const prmap_t *pmp;
2609 
2610                         /*
2611                          * This can fail either due to an invalid lmid or
2612                          * an invalid object. To determine which is
2613                          * faulty, we test the lmid against known valid
2614                          * lmids and then see if using a wild-card lmid
2615                          * improves ths situation.
2616                          */
2617                         if ((pmp = Plmid_to_map(P, lmid, object)) == NULL) {
2618                                 if (lmid != PR_LMID_EVERY &&
2619                                     lmid != LM_ID_BASE &&
2620                                     lmid != LM_ID_LDSO &&
2621                                     Plmid_to_map(P, PR_LMID_EVERY, object)
2622                                     != NULL)
2623                                         return (set_errno(EMDB_NOLMID));
2624                                 else
2625                                         return (set_errno(EMDB_NOOBJ));
2626                         }
2627 
2628                         if (pt_lookup_cb(&pl, pmp, object) == -1)
2629                                 return (-1); /* errno is set for us */
2630                 }
2631 
2632                 if (pl.pl_found)
2633                         return (0);
2634         }
2635 
2636         /*
2637          * If libproc doesn't have the symbols for rtld, we're cooked --
2638          * mdb doesn't have those symbols either.
2639          */
2640         if (object == MDB_TGT_OBJ_RTLD)
2641                 return (set_errno(EMDB_NOSYM));
2642 
2643         if (object != MDB_TGT_OBJ_EXEC && object != MDB_TGT_OBJ_EVERY) {
2644                 int status = mdb_gelf_symtab_lookup_by_file(pt->p_symtab,
2645                     object, name, symp, &sip->sym_id);
2646 
2647                 if (status != 0) {
2648                         if (P != NULL &&
2649                             Plmid_to_map(P, PR_LMID_EVERY, object) != NULL)
2650                                 return (set_errno(EMDB_NOSYM));
2651                         else
2652                                 return (-1); /* errno set from lookup_by_file */
2653                 }
2654 
2655                 goto found;
2656         }
2657 
2658         if (mdb_gelf_symtab_lookup_by_name(pt->p_symtab, name, symp, &i) == 0) {
2659                 sip->sym_table = MDB_TGT_SYMTAB;
2660                 sip->sym_id = i;
2661                 goto local_found;
2662         }
2663 
2664         if (mdb_gelf_symtab_lookup_by_name(pt->p_dynsym, name, symp, &i) == 0) {
2665                 sip->sym_table = MDB_TGT_DYNSYM;
2666                 sip->sym_id = i;
2667                 goto local_found;
2668         }
2669 
2670         return (set_errno(EMDB_NOSYM));
2671 
2672 local_found:
2673         if (pt->p_file != NULL &&
2674             pt->p_file->gf_ehdr.e_type == ET_DYN &&
2675             P != NULL &&
2676             (aout_lop = Pname_to_loadobj(P, PR_OBJ_EXEC)) != NULL)
2677                 symp->st_value += aout_lop->rl_base;
2678 
2679 found:
2680         /*
2681          * If the symbol has type TLS, libproc should have found the symbol
2682          * if it exists and has been allocated.
2683          */
2684         if (GELF_ST_TYPE(symp->st_info) == STT_TLS)
2685                 return (set_errno(EMDB_TLS));
2686 
2687         return (0);
2688 }
2689 
2690 static int
2691 pt_lookup_by_name(mdb_tgt_t *t, const char *object,
2692     const char *name, GElf_Sym *symp, mdb_syminfo_t *sip)
2693 {
2694         return (pt_lookup_by_name_thr(t, object, name, symp, sip, PTL_TID(t)));
2695 }
2696 
2697 static int
2698 pt_lookup_by_addr(mdb_tgt_t *t, uintptr_t addr, uint_t flags,
2699     char *buf, size_t nbytes, GElf_Sym *symp, mdb_syminfo_t *sip)
2700 {
2701         struct ps_prochandle *P = t->t_pshandle;
2702         pt_data_t *pt = t->t_data;
2703         rd_plt_info_t rpi = { 0 };
2704 
2705         const char *pltsym;
2706         int rv, match, i;
2707 
2708         mdb_gelf_symtab_t *gsts[3];     /* mdb.m_prsym, .symtab, .dynsym */
2709         int gstc = 0;                   /* number of valid gsts[] entries */
2710 
2711         mdb_gelf_symtab_t *gst = NULL;  /* set if 'sym' is from a gst */
2712         const prmap_t *pmp = NULL;      /* set if 'sym' is from libproc */
2713         GElf_Sym sym;                   /* best symbol found so far if !exact */
2714         prsyminfo_t si;
2715 
2716         /*
2717          * Fill in our array of symbol table pointers with the private symbol
2718          * table, static symbol table, and dynamic symbol table if applicable.
2719          * These are done in order of precedence so that if we match and
2720          * MDB_TGT_SYM_EXACT is set, we need not look any further.
2721          */
2722         if (mdb.m_prsym != NULL)
2723                 gsts[gstc++] = mdb.m_prsym;
2724         if (P == NULL && pt->p_symtab != NULL)
2725                 gsts[gstc++] = pt->p_symtab;
2726         if (P == NULL && pt->p_dynsym != NULL)
2727                 gsts[gstc++] = pt->p_dynsym;
2728 
2729         /*
2730          * Loop through our array attempting to match the address.  If we match
2731          * and we're in exact mode, we're done.  Otherwise save the symbol in
2732          * the local sym variable if it is closer than our previous match.
2733          * We explicitly watch for zero-valued symbols since DevPro insists
2734          * on storing __fsr_init_value's value as the symbol value instead
2735          * of storing it in a constant integer.
2736          */
2737         for (i = 0; i < gstc; i++) {
2738                 if (mdb_gelf_symtab_lookup_by_addr(gsts[i], addr, flags, buf,
2739                     nbytes, symp, &sip->sym_id) != 0 || symp->st_value == 0)
2740                         continue;
2741 
2742                 if (flags & MDB_TGT_SYM_EXACT) {
2743                         gst = gsts[i];
2744                         goto found;
2745                 }
2746 
2747                 if (gst == NULL || mdb_gelf_sym_closer(symp, &sym, addr)) {
2748                         gst = gsts[i];
2749                         sym = *symp;
2750                 }
2751         }
2752 
2753         /*
2754          * If we have no libproc handle active, we're done: fail if gst is
2755          * NULL; otherwise copy out our best symbol and skip to the end.
2756          * We also skip to found if gst is the private symbol table: we
2757          * want this to always take precedence over PLT re-vectoring.
2758          */
2759         if (P == NULL || (gst != NULL && gst == mdb.m_prsym)) {
2760                 if (gst == NULL)
2761                         return (set_errno(EMDB_NOSYMADDR));
2762                 *symp = sym;
2763                 goto found;
2764         }
2765 
2766         /*
2767          * Check to see if the address is in a PLT: if it is, use librtld_db to
2768          * attempt to resolve the PLT entry.  If the entry is bound, reset addr
2769          * to the bound address, add a special prefix to the caller's buf,
2770          * forget our previous guess, and then continue using the new addr.
2771          * If the entry is not bound, copy the corresponding symbol name into
2772          * buf and return a fake symbol for the given address.
2773          */
2774         if ((pltsym = Ppltdest(P, addr)) != NULL) {
2775                 const rd_loadobj_t *rlp;
2776                 rd_agent_t *rap;
2777 
2778                 if ((rap = Prd_agent(P)) != NULL &&
2779                     (rlp = Paddr_to_loadobj(P, addr)) != NULL &&
2780                     rd_plt_resolution(rap, addr, Pstatus(P)->pr_lwp.pr_lwpid,
2781                     rlp->rl_plt_base, &rpi) == RD_OK &&
2782                     (rpi.pi_flags & RD_FLG_PI_PLTBOUND)) {
2783                         size_t n;
2784                         n = mdb_iob_snprintf(buf, nbytes, "PLT=");
2785                         addr = rpi.pi_baddr;
2786                         if (n > nbytes) {
2787                                 buf += nbytes;
2788                                 nbytes = 0;
2789                         } else {
2790                                 buf += n;
2791                                 nbytes -= n;
2792                         }
2793                         gst = NULL;
2794                 } else {
2795                         (void) mdb_iob_snprintf(buf, nbytes, "PLT:%s", pltsym);
2796                         bzero(symp, sizeof (GElf_Sym));
2797                         symp->st_value = addr;
2798                         symp->st_info = GELF_ST_INFO(STB_GLOBAL, STT_FUNC);
2799                         return (0);
2800                 }
2801         }
2802 
2803         /*
2804          * Ask libproc to convert the address to the closest symbol for us.
2805          * Once we get the closest symbol, we perform the EXACT match or
2806          * smart-mode or absolute distance check ourself:
2807          */
2808         if ((mdb.m_flags & MDB_FL_LMRAW) == 0) {
2809                 rv = Pxlookup_by_addr_resolved(P, addr, buf, nbytes,
2810                     symp, &si);
2811         } else {
2812                 rv = Pxlookup_by_addr(P, addr, buf, nbytes,
2813                     symp, &si);
2814         }
2815         if ((rv == 0) && (symp->st_value != 0) &&
2816             (gst == NULL || mdb_gelf_sym_closer(symp, &sym, addr))) {
2817 
2818                 if (flags & MDB_TGT_SYM_EXACT)
2819                         match = (addr == symp->st_value);
2820                 else if (mdb.m_symdist == 0)
2821                         match = (addr >= symp->st_value &&
2822                             addr < symp->st_value + symp->st_size);
2823                 else
2824                         match = (addr >= symp->st_value &&
2825                             addr < symp->st_value + mdb.m_symdist);
2826 
2827                 if (match) {
2828                         pmp = Paddr_to_map(P, addr);
2829                         gst = NULL;
2830                         sip->sym_table = si.prs_table;
2831                         sip->sym_id = si.prs_id;
2832                         goto found;
2833                 }
2834         }
2835 
2836         /*
2837          * If we get here, Plookup_by_addr has failed us.  If we have no
2838          * previous best symbol (gst == NULL), we've failed completely.
2839          * Otherwise we copy out that symbol and continue on to 'found'.
2840          */
2841         if (gst == NULL)
2842                 return (set_errno(EMDB_NOSYMADDR));
2843         *symp = sym;
2844 found:
2845         /*
2846          * Once we've found something, copy the final name into the caller's
2847          * buffer and prefix it with the mapping name if appropriate.
2848          */
2849         if (pmp != NULL && pmp != Pname_to_map(P, PR_OBJ_EXEC)) {
2850                 const char *prefix = pmp->pr_mapname;
2851                 Lmid_t lmid;
2852 
2853                 if ((mdb.m_flags & MDB_FL_LMRAW) == 0) {
2854                         if (Pobjname_resolved(P, addr, pt->p_objname,
2855                             MDB_TGT_MAPSZ))
2856                                 prefix = pt->p_objname;
2857                 } else {
2858                         if (Pobjname(P, addr, pt->p_objname, MDB_TGT_MAPSZ))
2859                                 prefix = pt->p_objname;
2860                 }
2861 
2862                 if (buf != NULL && nbytes > 1) {
2863                         (void) strncpy(pt->p_symname, buf, MDB_TGT_SYM_NAMLEN);
2864                         pt->p_symname[MDB_TGT_SYM_NAMLEN - 1] = '\0';
2865                 } else {
2866                         pt->p_symname[0] = '\0';
2867                 }
2868 
2869                 if (prefix == pt->p_objname && Plmid(P, addr, &lmid) == 0 && (
2870                     (lmid != LM_ID_BASE && lmid != LM_ID_LDSO) ||
2871                     (mdb.m_flags & MDB_FL_SHOWLMID))) {
2872                         (void) mdb_iob_snprintf(buf, nbytes, "LM%lr`%s`%s",
2873                             lmid, strbasename(prefix), pt->p_symname);
2874                 } else {
2875                         (void) mdb_iob_snprintf(buf, nbytes, "%s`%s",
2876                             strbasename(prefix), pt->p_symname);
2877                 }
2878 
2879         } else if (gst != NULL && buf != NULL && nbytes > 0) {
2880                 (void) strncpy(buf, mdb_gelf_sym_name(gst, symp), nbytes);
2881                 buf[nbytes - 1] = '\0';
2882         }
2883 
2884         return (0);
2885 }
2886 
2887 
2888 static int
2889 pt_symbol_iter_cb(void *arg, const GElf_Sym *sym, const char *name,
2890     const prsyminfo_t *sip)
2891 {
2892         pt_symarg_t *psp = arg;
2893 
2894         psp->psym_info.sym_id = sip->prs_id;
2895 
2896         return (psp->psym_func(psp->psym_private, sym, name, &psp->psym_info,
2897             psp->psym_obj));
2898 }
2899 
2900 static int
2901 pt_objsym_iter(void *arg, const prmap_t *pmp, const char *object)
2902 {
2903         Lmid_t lmid = PR_LMID_EVERY;
2904         pt_symarg_t *psp = arg;
2905 
2906         psp->psym_obj = object;
2907 
2908         (void) Plmid(psp->psym_targ->t_pshandle, pmp->pr_vaddr, &lmid);
2909         (void) Pxsymbol_iter(psp->psym_targ->t_pshandle, lmid, object,
2910             psp->psym_which, psp->psym_type, pt_symbol_iter_cb, arg);
2911 
2912         return (0);
2913 }
2914 
2915 static int
2916 pt_symbol_filt(void *arg, const GElf_Sym *sym, const char *name, uint_t id)
2917 {
2918         pt_symarg_t *psp = arg;
2919 
2920         if (mdb_tgt_sym_match(sym, psp->psym_type)) {
2921                 psp->psym_info.sym_id = id;
2922                 return (psp->psym_func(psp->psym_private, sym, name,
2923                     &psp->psym_info, psp->psym_obj));
2924         }
2925 
2926         return (0);
2927 }
2928 
2929 static int
2930 pt_symbol_iter(mdb_tgt_t *t, const char *object, uint_t which,
2931     uint_t type, mdb_tgt_sym_f *func, void *private)
2932 {
2933         pt_data_t *pt = t->t_data;
2934         mdb_gelf_symtab_t *gst;
2935         pt_symarg_t ps;
2936         Lmid_t lmid;
2937 
2938         object = pt_resolve_lmid(object, &lmid);
2939 
2940         ps.psym_targ = t;
2941         ps.psym_which = which;
2942         ps.psym_type = type;
2943         ps.psym_func = func;
2944         ps.psym_private = private;
2945         ps.psym_obj = object;
2946 
2947         if (t->t_pshandle != NULL) {
2948                 if (object != MDB_TGT_OBJ_EVERY) {
2949                         if (Plmid_to_map(t->t_pshandle, lmid, object) == NULL)
2950                                 return (set_errno(EMDB_NOOBJ));
2951                         (void) Pxsymbol_iter(t->t_pshandle, lmid, object,
2952                             which, type, pt_symbol_iter_cb, &ps);
2953                         return (0);
2954                 } else if (Prd_agent(t->t_pshandle) != NULL) {
2955                         if ((mdb.m_flags & MDB_FL_LMRAW) == 0) {
2956                                 (void) Pobject_iter_resolved(t->t_pshandle,
2957                                     pt_objsym_iter, &ps);
2958                         } else {
2959                                 (void) Pobject_iter(t->t_pshandle,
2960                                     pt_objsym_iter, &ps);
2961                         }
2962                         return (0);
2963                 }
2964         }
2965 
2966         if (lmid != LM_ID_BASE && lmid != PR_LMID_EVERY)
2967                 return (set_errno(EMDB_NOLMID));
2968 
2969         if (object != MDB_TGT_OBJ_EXEC && object != MDB_TGT_OBJ_EVERY &&
2970             pt->p_fio != NULL &&
2971             strcmp(object, IOP_NAME(pt->p_fio)) != 0)
2972                 return (set_errno(EMDB_NOOBJ));
2973 
2974         if (which == MDB_TGT_SYMTAB)
2975                 gst = pt->p_symtab;
2976         else
2977                 gst = pt->p_dynsym;
2978 
2979         if (gst != NULL) {
2980                 ps.psym_info.sym_table = gst->gst_tabid;
2981                 mdb_gelf_symtab_iter(gst, pt_symbol_filt, &ps);
2982         }
2983 
2984         return (0);
2985 }
2986 
2987 static const mdb_map_t *
2988 pt_prmap_to_mdbmap(mdb_tgt_t *t, const prmap_t *prp, mdb_map_t *mp)
2989 {
2990         struct ps_prochandle *P = t->t_pshandle;
2991         char *rv, name[MAXPATHLEN];
2992         Lmid_t lmid;
2993 
2994         if ((mdb.m_flags & MDB_FL_LMRAW) == 0) {
2995                 rv = Pobjname_resolved(P, prp->pr_vaddr, name, sizeof (name));
2996         } else {
2997                 rv = Pobjname(P, prp->pr_vaddr, name, sizeof (name));
2998         }
2999 
3000         if (rv != NULL) {
3001                 if (Plmid(P, prp->pr_vaddr, &lmid) == 0 && (
3002                     (lmid != LM_ID_BASE && lmid != LM_ID_LDSO) ||
3003                     (mdb.m_flags & MDB_FL_SHOWLMID))) {
3004                         (void) mdb_iob_snprintf(mp->map_name, MDB_TGT_MAPSZ,
3005                             "LM%lr`%s", lmid, name);
3006                 } else {
3007                         (void) strncpy(mp->map_name, name, MDB_TGT_MAPSZ - 1);
3008                         mp->map_name[MDB_TGT_MAPSZ - 1] = '\0';
3009                 }
3010         } else {
3011                 (void) strncpy(mp->map_name, prp->pr_mapname,
3012                     MDB_TGT_MAPSZ - 1);
3013                 mp->map_name[MDB_TGT_MAPSZ - 1] = '\0';
3014         }
3015 
3016         mp->map_base = prp->pr_vaddr;
3017         mp->map_size = prp->pr_size;
3018         mp->map_flags = 0;
3019 
3020         if (prp->pr_mflags & MA_READ)
3021                 mp->map_flags |= MDB_TGT_MAP_R;
3022         if (prp->pr_mflags & MA_WRITE)
3023                 mp->map_flags |= MDB_TGT_MAP_W;
3024         if (prp->pr_mflags & MA_EXEC)
3025                 mp->map_flags |= MDB_TGT_MAP_X;
3026 
3027         if (prp->pr_mflags & MA_SHM)
3028                 mp->map_flags |= MDB_TGT_MAP_SHMEM;
3029         if (prp->pr_mflags & MA_BREAK)
3030                 mp->map_flags |= MDB_TGT_MAP_HEAP;
3031         if (prp->pr_mflags & MA_STACK)
3032                 mp->map_flags |= MDB_TGT_MAP_STACK;
3033         if (prp->pr_mflags & MA_ANON)
3034                 mp->map_flags |= MDB_TGT_MAP_ANON;
3035 
3036         return (mp);
3037 }
3038 
3039 /*ARGSUSED*/
3040 static int
3041 pt_map_apply(void *arg, const prmap_t *prp, const char *name)
3042 {
3043         pt_maparg_t *pmp = arg;
3044         mdb_map_t map;
3045 
3046         return (pmp->pmap_func(pmp->pmap_private,
3047             pt_prmap_to_mdbmap(pmp->pmap_targ, prp, &map), map.map_name));
3048 }
3049 
3050 static int
3051 pt_mapping_iter(mdb_tgt_t *t, mdb_tgt_map_f *func, void *private)
3052 {
3053         if (t->t_pshandle != NULL) {
3054                 pt_maparg_t pm;
3055 
3056                 pm.pmap_targ = t;
3057                 pm.pmap_func = func;
3058                 pm.pmap_private = private;
3059 
3060                 if ((mdb.m_flags & MDB_FL_LMRAW) == 0) {
3061                         (void) Pmapping_iter_resolved(t->t_pshandle,
3062                             pt_map_apply, &pm);
3063                 } else {
3064                         (void) Pmapping_iter(t->t_pshandle,
3065                             pt_map_apply, &pm);
3066                 }
3067                 return (0);
3068         }
3069 
3070         return (set_errno(EMDB_NOPROC));
3071 }
3072 
3073 static int
3074 pt_object_iter(mdb_tgt_t *t, mdb_tgt_map_f *func, void *private)
3075 {
3076         pt_data_t *pt = t->t_data;
3077 
3078         /*
3079          * If we have a libproc handle, we can just call Pobject_iter to
3080          * iterate over its list of load object information.
3081          */
3082         if (t->t_pshandle != NULL) {
3083                 pt_maparg_t pm;
3084 
3085                 pm.pmap_targ = t;
3086                 pm.pmap_func = func;
3087                 pm.pmap_private = private;
3088 
3089                 if ((mdb.m_flags & MDB_FL_LMRAW) == 0) {
3090                         (void) Pobject_iter_resolved(t->t_pshandle,
3091                             pt_map_apply, &pm);
3092                 } else {
3093                         (void) Pobject_iter(t->t_pshandle,
3094                             pt_map_apply, &pm);
3095                 }
3096                 return (0);
3097         }
3098 
3099         /*
3100          * If we're examining an executable or other ELF file but we have no
3101          * libproc handle, fake up some information based on DT_NEEDED entries.
3102          */
3103         if (pt->p_dynsym != NULL && pt->p_file->gf_dyns != NULL &&
3104             pt->p_fio != NULL) {
3105                 mdb_gelf_sect_t *gsp = pt->p_dynsym->gst_ssect;
3106                 GElf_Dyn *dynp = pt->p_file->gf_dyns;
3107                 mdb_map_t *mp = &pt->p_map;
3108                 const char *s = IOP_NAME(pt->p_fio);
3109                 size_t i;
3110 
3111                 (void) strncpy(mp->map_name, s, MDB_TGT_MAPSZ);
3112                 mp->map_name[MDB_TGT_MAPSZ - 1] = '\0';
3113                 mp->map_flags = MDB_TGT_MAP_R | MDB_TGT_MAP_X;
3114                 mp->map_base = NULL;
3115                 mp->map_size = 0;
3116 
3117                 if (func(private, mp, s) != 0)
3118                         return (0);
3119 
3120                 for (i = 0; i < pt->p_file->gf_ndyns; i++, dynp++) {
3121                         if (dynp->d_tag == DT_NEEDED) {
3122                                 s = (char *)gsp->gs_data + dynp->d_un.d_val;
3123                                 (void) strncpy(mp->map_name, s, MDB_TGT_MAPSZ);
3124                                 mp->map_name[MDB_TGT_MAPSZ - 1] = '\0';
3125                                 if (func(private, mp, s) != 0)
3126                                         return (0);
3127                         }
3128                 }
3129 
3130                 return (0);
3131         }
3132 
3133         return (set_errno(EMDB_NOPROC));
3134 }
3135 
3136 static const mdb_map_t *
3137 pt_addr_to_map(mdb_tgt_t *t, uintptr_t addr)
3138 {
3139         pt_data_t *pt = t->t_data;
3140         const prmap_t *pmp;
3141 
3142         if (t->t_pshandle == NULL) {
3143                 (void) set_errno(EMDB_NOPROC);
3144                 return (NULL);
3145         }
3146 
3147         if ((pmp = Paddr_to_map(t->t_pshandle, addr)) == NULL) {
3148                 (void) set_errno(EMDB_NOMAP);
3149                 return (NULL);
3150         }
3151 
3152         return (pt_prmap_to_mdbmap(t, pmp, &pt->p_map));
3153 }
3154 
3155 static const mdb_map_t *
3156 pt_name_to_map(mdb_tgt_t *t, const char *object)
3157 {
3158         pt_data_t *pt = t->t_data;
3159         const prmap_t *pmp;
3160         Lmid_t lmid;
3161 
3162         if (t->t_pshandle == NULL) {
3163                 (void) set_errno(EMDB_NOPROC);
3164                 return (NULL);
3165         }
3166 
3167         object = pt_resolve_lmid(object, &lmid);
3168 
3169         if ((pmp = Plmid_to_map(t->t_pshandle, lmid, object)) == NULL) {
3170                 (void) set_errno(EMDB_NOOBJ);
3171                 return (NULL);
3172         }
3173 
3174         return (pt_prmap_to_mdbmap(t, pmp, &pt->p_map));
3175 }
3176 
3177 static ctf_file_t *
3178 pt_addr_to_ctf(mdb_tgt_t *t, uintptr_t addr)
3179 {
3180         ctf_file_t *ret;
3181 
3182         if (t->t_pshandle == NULL) {
3183                 (void) set_errno(EMDB_NOPROC);
3184                 return (NULL);
3185         }
3186 
3187         if ((ret = Paddr_to_ctf(t->t_pshandle, addr)) == NULL) {
3188                 (void) set_errno(EMDB_NOOBJ);
3189                 return (NULL);
3190         }
3191 
3192         return (ret);
3193 }
3194 
3195 static ctf_file_t *
3196 pt_name_to_ctf(mdb_tgt_t *t, const char *name)
3197 {
3198         ctf_file_t *ret;
3199 
3200         if (t->t_pshandle == NULL) {
3201                 (void) set_errno(EMDB_NOPROC);
3202                 return (NULL);
3203         }
3204 
3205         if ((ret = Pname_to_ctf(t->t_pshandle, name)) == NULL) {
3206                 (void) set_errno(EMDB_NOOBJ);
3207                 return (NULL);
3208         }
3209 
3210         return (ret);
3211 }
3212 
3213 static int
3214 pt_status(mdb_tgt_t *t, mdb_tgt_status_t *tsp)
3215 {
3216         const pstatus_t *psp;
3217         prgregset_t gregs;
3218         int state;
3219 
3220         bzero(tsp, sizeof (mdb_tgt_status_t));
3221 
3222         if (t->t_pshandle == NULL) {
3223                 tsp->st_state = MDB_TGT_IDLE;
3224                 return (0);
3225         }
3226 
3227         switch (state = Pstate(t->t_pshandle)) {
3228         case PS_RUN:
3229                 tsp->st_state = MDB_TGT_RUNNING;
3230                 break;
3231 
3232         case PS_STOP:
3233                 tsp->st_state = MDB_TGT_STOPPED;
3234                 psp = Pstatus(t->t_pshandle);
3235 
3236                 tsp->st_tid = PTL_TID(t);
3237                 if (PTL_GETREGS(t, tsp->st_tid, gregs) == 0)
3238                         tsp->st_pc = gregs[R_PC];
3239 
3240                 if (psp->pr_flags & PR_ISTOP)
3241                         tsp->st_flags |= MDB_TGT_ISTOP;
3242                 if (psp->pr_flags & PR_DSTOP)
3243                         tsp->st_flags |= MDB_TGT_DSTOP;
3244 
3245                 break;
3246 
3247         case PS_LOST:
3248                 tsp->st_state = MDB_TGT_LOST;
3249                 break;
3250         case PS_UNDEAD:
3251                 tsp->st_state = MDB_TGT_UNDEAD;
3252                 break;
3253         case PS_DEAD:
3254                 tsp->st_state = MDB_TGT_DEAD;
3255                 break;
3256         case PS_IDLE:
3257                 tsp->st_state = MDB_TGT_IDLE;
3258                 break;
3259         default:
3260                 fail("unknown libproc state (%d)\n", state);
3261         }
3262 
3263         if (t->t_flags & MDB_TGT_F_BUSY)
3264                 tsp->st_flags |= MDB_TGT_BUSY;
3265 
3266         return (0);
3267 }
3268 
3269 static void
3270 pt_dupfd(const char *file, int oflags, mode_t mode, int dfd)
3271 {
3272         int fd;
3273 
3274         if ((fd = open(file, oflags, mode)) >= 0) {
3275                 (void) fcntl(fd, F_DUP2FD, dfd);
3276                 (void) close(fd);
3277         } else
3278                 warn("failed to open %s as descriptor %d", file, dfd);
3279 }
3280 
3281 /*
3282  * The Pcreate_callback() function interposes on the default, empty libproc
3283  * definition.  It will be called following a fork of a new child process by
3284  * Pcreate() below, but before the exec of the new process image.  We use this
3285  * callback to optionally redirect stdin and stdout and reset the dispositions
3286  * of SIGPIPE and SIGQUIT from SIG_IGN back to SIG_DFL.
3287  */
3288 /*ARGSUSED*/
3289 void
3290 Pcreate_callback(struct ps_prochandle *P)
3291 {
3292         pt_data_t *pt = mdb.m_target->t_data;
3293 
3294         if (pt->p_stdin != NULL)
3295                 pt_dupfd(pt->p_stdin, O_RDWR, 0, STDIN_FILENO);
3296         if (pt->p_stdout != NULL)
3297                 pt_dupfd(pt->p_stdout, O_CREAT | O_WRONLY, 0666, STDOUT_FILENO);
3298 
3299         (void) mdb_signal_sethandler(SIGPIPE, SIG_DFL, NULL);
3300         (void) mdb_signal_sethandler(SIGQUIT, SIG_DFL, NULL);
3301 }
3302 
3303 static int
3304 pt_run(mdb_tgt_t *t, int argc, const mdb_arg_t *argv)
3305 {
3306         pt_data_t *pt = t->t_data;
3307         struct ps_prochandle *P;
3308         char execname[MAXPATHLEN];
3309         const char **pargv;
3310         int pargc = 0;
3311         int i, perr;
3312         char **penv;
3313         mdb_var_t *v;
3314 
3315         if (pt->p_aout_fio == NULL) {
3316                 warn("run requires executable to be specified on "
3317                     "command-line\n");
3318                 return (set_errno(EMDB_TGT));
3319         }
3320 
3321         pargv = mdb_alloc(sizeof (char *) * (argc + 2), UM_SLEEP);
3322         pargv[pargc++] = strbasename(IOP_NAME(pt->p_aout_fio));
3323 
3324         for (i = 0; i < argc; i++) {
3325                 if (argv[i].a_type != MDB_TYPE_STRING) {
3326                         mdb_free(pargv, sizeof (char *) * (argc + 2));
3327                         return (set_errno(EINVAL));
3328                 }
3329                 if (argv[i].a_un.a_str[0] == '<')
3330                         pt->p_stdin = argv[i].a_un.a_str + 1;
3331                 else if (argv[i].a_un.a_str[0] == '>')
3332                         pt->p_stdout = argv[i].a_un.a_str + 1;
3333                 else
3334                         pargv[pargc++] = argv[i].a_un.a_str;
3335         }
3336         pargv[pargc] = NULL;
3337 
3338         /*
3339          * Since Pcreate() uses execvp() and "." may not be present in $PATH,
3340          * we must manually prepend "./" when the executable is a simple name.
3341          */
3342         if (strchr(IOP_NAME(pt->p_aout_fio), '/') == NULL) {
3343                 (void) snprintf(execname, sizeof (execname), "./%s",
3344                     IOP_NAME(pt->p_aout_fio));
3345         } else {
3346                 (void) snprintf(execname, sizeof (execname), "%s",
3347                     IOP_NAME(pt->p_aout_fio));
3348         }
3349 
3350         penv = mdb_alloc((mdb_nv_size(&pt->p_env)+ 1) * sizeof (char *),
3351             UM_SLEEP);
3352         for (mdb_nv_rewind(&pt->p_env), i = 0;
3353             (v = mdb_nv_advance(&pt->p_env)) != NULL; i++)
3354                 penv[i] = mdb_nv_get_cookie(v);
3355         penv[i] = NULL;
3356 
3357         P = Pxcreate(execname, (char **)pargv, penv, &perr, NULL, 0);
3358         mdb_free(pargv, sizeof (char *) * (argc + 2));
3359         pt->p_stdin = pt->p_stdout = NULL;
3360 
3361         mdb_free(penv, i * sizeof (char *));
3362 
3363         if (P == NULL) {
3364                 warn("failed to create process: %s\n", Pcreate_error(perr));
3365                 return (set_errno(EMDB_TGT));
3366         }
3367 
3368         if (t->t_pshandle != NULL) {
3369                 pt_pre_detach(t, TRUE);
3370                 if (t->t_pshandle != pt->p_idlehandle)
3371                         Prelease(t->t_pshandle, pt->p_rflags);
3372         }
3373 
3374         (void) Punsetflags(P, PR_RLC);  /* make sure run-on-last-close is off */
3375         (void) Psetflags(P, PR_KLC);    /* kill on last close by debugger */
3376         pt->p_rflags = PRELEASE_KILL;        /* kill on debugger Prelease */
3377         t->t_pshandle = P;
3378 
3379         pt_post_attach(t);
3380         pt_activate_common(t);
3381         (void) mdb_tgt_status(t, &t->t_status);
3382         mdb.m_flags |= MDB_FL_VCREATE;
3383 
3384         return (0);
3385 }
3386 
3387 /*
3388  * Forward a signal to the victim process in order to force it to stop or die.
3389  * Refer to the comments above pt_setrun(), below, for more info.
3390  */
3391 /*ARGSUSED*/
3392 static void
3393 pt_sigfwd(int sig, siginfo_t *sip, ucontext_t *ucp, mdb_tgt_t *t)
3394 {
3395         struct ps_prochandle *P = t->t_pshandle;
3396         const lwpstatus_t *psp = &Pstatus(P)->pr_lwp;
3397         pid_t pid = Pstatus(P)->pr_pid;
3398         long ctl[2];
3399 
3400         if (getpgid(pid) != mdb.m_pgid) {
3401                 mdb_dprintf(MDB_DBG_TGT, "fwd SIG#%d to %d\n", sig, (int)pid);
3402                 (void) kill(pid, sig);
3403         }
3404 
3405         if (Pwait(P, 1) == 0 && (psp->pr_flags & PR_STOPPED) &&
3406             psp->pr_why == PR_JOBCONTROL && Pdstop(P) == 0) {
3407                 /*
3408                  * If we're job control stopped and our DSTOP is pending, the
3409                  * victim will never see our signal, so undo the kill() and
3410                  * then send SIGCONT the victim to kick it out of the job
3411                  * control stop and force our DSTOP to take effect.
3412                  */
3413                 if ((psp->pr_flags & PR_DSTOP) &&
3414                     prismember(&Pstatus(P)->pr_sigpend, sig)) {
3415                         ctl[0] = PCUNKILL;
3416                         ctl[1] = sig;
3417                         (void) write(Pctlfd(P), ctl, sizeof (ctl));
3418                 }
3419 
3420                 mdb_dprintf(MDB_DBG_TGT, "fwd SIGCONT to %d\n", (int)pid);
3421                 (void) kill(pid, SIGCONT);
3422         }
3423 }
3424 
3425 /*
3426  * Common code for step and continue: if no victim process has been created,
3427  * call pt_run() to create one.  Then set the victim running, clearing any
3428  * pending fault.  One special case is that if the victim was previously
3429  * stopped on reception of SIGINT, we know that SIGINT was traced and the user
3430  * requested the victim to stop, so clear this signal before continuing.
3431  * For all other traced signals, the signal will be delivered on continue.
3432  *
3433  * Once the victim process is running, we wait for it to stop on an event of
3434  * interest.  Although libproc provides the basic primitive to wait for the
3435  * victim, we must be careful in our handling of signals.  We want to allow the
3436  * user to issue a SIGINT or SIGQUIT using the designated terminal control
3437  * character (typically ^C and ^\), and have these signals stop the target and
3438  * return control to the debugger if the signals are traced.  There are three
3439  * cases to be considered in our implementation:
3440  *
3441  * (1) If the debugger and victim are in the same process group, both receive
3442  * the signal from the terminal driver.  The debugger returns from Pwait() with
3443  * errno = EINTR, so we want to loop back and continue waiting until the victim
3444  * stops on receipt of its SIGINT or SIGQUIT.
3445  *
3446  * (2) If the debugger and victim are in different process groups, and the
3447  * victim is a member of the foreground process group, it will receive the
3448  * signal from the terminal driver and the debugger will not.  As such, we
3449  * will remain blocked in Pwait() until the victim stops on its signal.
3450  *
3451  * (3) If the debugger and victim are in different process groups, and the
3452  * debugger is a member of the foreground process group, it will receive the
3453  * signal from the terminal driver, and the victim will not.  The debugger
3454  * returns from Pwait() with errno = EINTR, so we need to forward the signal
3455  * to the victim process directly and then Pwait() again for it to stop.
3456  *
3457  * We can observe that all three cases are handled by simply calling Pwait()
3458  * repeatedly if it fails with EINTR, and forwarding SIGINT and SIGQUIT to
3459  * the victim if it is in a different process group, using pt_sigfwd() above.
3460  *
3461  * An additional complication is that the process may not be able to field
3462  * the signal if it is currently stopped by job control.  In this case, we
3463  * also DSTOP the process, and then send it a SIGCONT to wake it up from
3464  * job control and force it to re-enter stop() under the control of /proc.
3465  *
3466  * Finally, we would like to allow the user to suspend the process using the
3467  * terminal suspend character (typically ^Z) if both are in the same session.
3468  * We again employ pt_sigfwd() to forward SIGTSTP to the victim, wait for it to
3469  * stop from job control, and then capture it using /proc.  Once the process
3470  * has stopped, normal SIGTSTP processing is restored and the user can issue
3471  * another ^Z in order to suspend the debugger and return to the parent shell.
3472  */
3473 static int
3474 pt_setrun(mdb_tgt_t *t, mdb_tgt_status_t *tsp, int flags)
3475 {
3476         struct ps_prochandle *P = t->t_pshandle;
3477         pt_data_t *pt = t->t_data;
3478         pid_t old_pgid = -1;
3479 
3480         mdb_signal_f *intf, *quitf, *tstpf;
3481         const lwpstatus_t *psp;
3482         void *intd, *quitd, *tstpd;
3483 
3484         int sig = pt->p_signal;
3485         int error = 0;
3486         int pgid = -1;
3487 
3488         pt->p_signal = 0; /* clear pending signal */
3489 
3490         if (P == NULL && pt_run(t, 0, NULL) == -1)
3491                 return (-1); /* errno is set for us */
3492 
3493         P = t->t_pshandle;
3494         psp = &Pstatus(P)->pr_lwp;
3495 
3496         if (sig == 0 && psp->pr_why == PR_SIGNALLED && psp->pr_what == SIGINT)
3497                 flags |= PRCSIG; /* clear pending SIGINT */
3498         else
3499                 flags |= PRCFAULT; /* clear any pending fault (e.g. BPT) */
3500 
3501         intf = mdb_signal_gethandler(SIGINT, &intd);
3502         quitf = mdb_signal_gethandler(SIGQUIT, &quitd);
3503         tstpf = mdb_signal_gethandler(SIGTSTP, &tstpd);
3504 
3505         (void) mdb_signal_sethandler(SIGINT, (mdb_signal_f *)pt_sigfwd, t);
3506         (void) mdb_signal_sethandler(SIGQUIT, (mdb_signal_f *)pt_sigfwd, t);
3507         (void) mdb_signal_sethandler(SIGTSTP, (mdb_signal_f *)pt_sigfwd, t);
3508 
3509         if (sig != 0 && Pstate(P) == PS_RUN &&
3510             kill(Pstatus(P)->pr_pid, sig) == -1) {
3511                 error = errno;
3512                 goto out;
3513         }
3514 
3515         /*
3516          * If we attached to a job stopped background process in the same
3517          * session, make its pgid the foreground process group before running
3518          * it.  Ignore SIGTTOU while doing this to avoid being suspended.
3519          */
3520         if (mdb.m_flags & MDB_FL_JOBCTL) {
3521                 (void) mdb_signal_sethandler(SIGTTOU, SIG_IGN, NULL);
3522                 (void) IOP_CTL(mdb.m_term, TIOCGPGRP, &old_pgid);
3523                 (void) IOP_CTL(mdb.m_term, TIOCSPGRP,
3524                     (void *)&Pstatus(P)->pr_pgid);
3525                 (void) mdb_signal_sethandler(SIGTTOU, SIG_DFL, NULL);
3526         }
3527 
3528         if (Pstate(P) != PS_RUN && Psetrun(P, sig, flags) == -1) {
3529                 error = errno;
3530                 goto out;
3531         }
3532 
3533         /*
3534          * If the process is stopped on job control, resume its process group
3535          * by sending it a SIGCONT if we are in the same session.  Otherwise
3536          * we have no choice but to wait for someone else to foreground it.
3537          */
3538         if (psp->pr_why == PR_JOBCONTROL) {
3539                 if (mdb.m_flags & MDB_FL_JOBCTL)
3540                         (void) kill(-Pstatus(P)->pr_pgid, SIGCONT);
3541                 else if (mdb.m_term != NULL)
3542                         warn("process is still suspended by job control ...\n");
3543         }
3544 
3545         /*
3546          * Wait for the process to stop.  As described above, we loop around if
3547          * we are interrupted (EINTR).  If we lose control, attempt to re-open
3548          * the process, or call pt_exec() if that fails to handle a re-exec.
3549          * If the process dies (ENOENT) or Pwait() fails, break out of the loop.
3550          */
3551         while (Pwait(P, 0) == -1) {
3552                 if (errno != EINTR) {
3553                         if (Pstate(P) == PS_LOST) {
3554                                 if (Preopen(P) == 0)
3555                                         continue; /* Pwait() again */
3556                                 else
3557                                         pt_exec(t, 0, NULL);
3558                         } else if (errno != ENOENT)
3559                                 warn("failed to wait for event");
3560                         break;
3561                 }
3562         }
3563 
3564         /*
3565          * If we changed the foreground process group, restore the old pgid
3566          * while ignoring SIGTTOU so we are not accidentally suspended.
3567          */
3568         if (old_pgid != -1) {
3569                 (void) mdb_signal_sethandler(SIGTTOU, SIG_IGN, NULL);
3570                 (void) IOP_CTL(mdb.m_term, TIOCSPGRP, &pgid);
3571                 (void) mdb_signal_sethandler(SIGTTOU, SIG_DFL, NULL);
3572         }
3573 
3574         /*
3575          * If we're now stopped on exit from a successful exec, release any
3576          * vfork parents and clean out their address space before returning
3577          * to tgt_continue() and perturbing the list of armed event specs.
3578          * If we're stopped for any other reason, just update the mappings.
3579          */
3580         switch (Pstate(P)) {
3581         case PS_STOP:
3582                 if (psp->pr_why == PR_SYSEXIT && psp->pr_errno == 0 &&
3583                     psp->pr_what == SYS_execve)
3584                         pt_release_parents(t);
3585                 else
3586                         Pupdate_maps(P);
3587                 break;
3588 
3589         case PS_UNDEAD:
3590         case PS_LOST:
3591                 pt_release_parents(t);
3592                 break;
3593         }
3594 
3595 out:
3596         (void) mdb_signal_sethandler(SIGINT, intf, intd);
3597         (void) mdb_signal_sethandler(SIGQUIT, quitf, quitd);
3598         (void) mdb_signal_sethandler(SIGTSTP, tstpf, tstpd);
3599         (void) pt_status(t, tsp);
3600 
3601         return (error ? set_errno(error) : 0);
3602 }
3603 
3604 static int
3605 pt_step(mdb_tgt_t *t, mdb_tgt_status_t *tsp)
3606 {
3607         return (pt_setrun(t, tsp, PRSTEP));
3608 }
3609 
3610 static int
3611 pt_continue(mdb_tgt_t *t, mdb_tgt_status_t *tsp)
3612 {
3613         return (pt_setrun(t, tsp, 0));
3614 }
3615 
3616 static int
3617 pt_signal(mdb_tgt_t *t, int sig)
3618 {
3619         pt_data_t *pt = t->t_data;
3620 
3621         if (sig > 0 && sig <= pt->p_maxsig) {
3622                 pt->p_signal = sig; /* pending until next pt_setrun */
3623                 return (0);
3624         }
3625 
3626         return (set_errno(EMDB_BADSIGNUM));
3627 }
3628 
3629 static int
3630 pt_sysenter_ctor(mdb_tgt_t *t, mdb_sespec_t *sep, void *args)
3631 {
3632         struct ps_prochandle *P = t->t_pshandle;
3633 
3634         if (P != NULL && Pstate(P) < PS_LOST) {
3635                 sep->se_data = args; /* data is raw system call number */
3636                 return (Psysentry(P, (intptr_t)args, TRUE) < 0 ? -1 : 0);
3637         }
3638 
3639         return (set_errno(EMDB_NOPROC));
3640 }
3641 
3642 static void
3643 pt_sysenter_dtor(mdb_tgt_t *t, mdb_sespec_t *sep)
3644 {
3645         (void) Psysentry(t->t_pshandle, (intptr_t)sep->se_data, FALSE);
3646 }
3647 
3648 /*ARGSUSED*/
3649 static char *
3650 pt_sysenter_info(mdb_tgt_t *t, mdb_sespec_t *sep, mdb_vespec_t *vep,
3651     mdb_tgt_spec_desc_t *sp, char *buf, size_t nbytes)
3652 {
3653         char name[32];
3654         int sysnum;
3655 
3656         if (vep != NULL)
3657                 sysnum = (intptr_t)vep->ve_args;
3658         else
3659                 sysnum = (intptr_t)sep->se_data;
3660 
3661         (void) proc_sysname(sysnum, name, sizeof (name));
3662         (void) mdb_iob_snprintf(buf, nbytes, "stop on entry to %s", name);
3663 
3664         return (buf);
3665 }
3666 
3667 /*ARGSUSED*/
3668 static int
3669 pt_sysenter_match(mdb_tgt_t *t, mdb_sespec_t *sep, mdb_tgt_status_t *tsp)
3670 {
3671         const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
3672         int sysnum = (intptr_t)sep->se_data;
3673 
3674         return (psp->pr_why == PR_SYSENTRY && psp->pr_what == sysnum);
3675 }
3676 
3677 static const mdb_se_ops_t proc_sysenter_ops = {
3678         pt_sysenter_ctor,       /* se_ctor */
3679         pt_sysenter_dtor,       /* se_dtor */
3680         pt_sysenter_info,       /* se_info */
3681         no_se_secmp,            /* se_secmp */
3682         no_se_vecmp,            /* se_vecmp */
3683         no_se_arm,              /* se_arm */
3684         no_se_disarm,           /* se_disarm */
3685         no_se_cont,             /* se_cont */
3686         pt_sysenter_match       /* se_match */
3687 };
3688 
3689 static int
3690 pt_sysexit_ctor(mdb_tgt_t *t, mdb_sespec_t *sep, void *args)
3691 {
3692         struct ps_prochandle *P = t->t_pshandle;
3693 
3694         if (P != NULL && Pstate(P) < PS_LOST) {
3695                 sep->se_data = args; /* data is raw system call number */
3696                 return (Psysexit(P, (intptr_t)args, TRUE) < 0 ? -1 : 0);
3697         }
3698 
3699         return (set_errno(EMDB_NOPROC));
3700 }
3701 
3702 static void
3703 pt_sysexit_dtor(mdb_tgt_t *t, mdb_sespec_t *sep)
3704 {
3705         (void) Psysexit(t->t_pshandle, (intptr_t)sep->se_data, FALSE);
3706 }
3707 
3708 /*ARGSUSED*/
3709 static char *
3710 pt_sysexit_info(mdb_tgt_t *t, mdb_sespec_t *sep, mdb_vespec_t *vep,
3711     mdb_tgt_spec_desc_t *sp, char *buf, size_t nbytes)
3712 {
3713         char name[32];
3714         int sysnum;
3715 
3716         if (vep != NULL)
3717                 sysnum = (intptr_t)vep->ve_args;
3718         else
3719                 sysnum = (intptr_t)sep->se_data;
3720 
3721         (void) proc_sysname(sysnum, name, sizeof (name));
3722         (void) mdb_iob_snprintf(buf, nbytes, "stop on exit from %s", name);
3723 
3724         return (buf);
3725 }
3726 
3727 /*ARGSUSED*/
3728 static int
3729 pt_sysexit_match(mdb_tgt_t *t, mdb_sespec_t *sep, mdb_tgt_status_t *tsp)
3730 {
3731         const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
3732         int sysnum = (intptr_t)sep->se_data;
3733 
3734         return (psp->pr_why == PR_SYSEXIT && psp->pr_what == sysnum);
3735 }
3736 
3737 static const mdb_se_ops_t proc_sysexit_ops = {
3738         pt_sysexit_ctor,        /* se_ctor */
3739         pt_sysexit_dtor,        /* se_dtor */
3740         pt_sysexit_info,        /* se_info */
3741         no_se_secmp,            /* se_secmp */
3742         no_se_vecmp,            /* se_vecmp */
3743         no_se_arm,              /* se_arm */
3744         no_se_disarm,           /* se_disarm */
3745         no_se_cont,             /* se_cont */
3746         pt_sysexit_match        /* se_match */
3747 };
3748 
3749 static int
3750 pt_signal_ctor(mdb_tgt_t *t, mdb_sespec_t *sep, void *args)
3751 {
3752         struct ps_prochandle *P = t->t_pshandle;
3753 
3754         if (P != NULL && Pstate(P) < PS_LOST) {
3755                 sep->se_data = args; /* data is raw signal number */
3756                 return (Psignal(P, (intptr_t)args, TRUE) < 0 ? -1 : 0);
3757         }
3758 
3759         return (set_errno(EMDB_NOPROC));
3760 }
3761 
3762 static void
3763 pt_signal_dtor(mdb_tgt_t *t, mdb_sespec_t *sep)
3764 {
3765         (void) Psignal(t->t_pshandle, (intptr_t)sep->se_data, FALSE);
3766 }
3767 
3768 /*ARGSUSED*/
3769 static char *
3770 pt_signal_info(mdb_tgt_t *t, mdb_sespec_t *sep, mdb_vespec_t *vep,
3771     mdb_tgt_spec_desc_t *sp, char *buf, size_t nbytes)
3772 {
3773         char name[SIG2STR_MAX];
3774         int signum;
3775 
3776         if (vep != NULL)
3777                 signum = (intptr_t)vep->ve_args;
3778         else
3779                 signum = (intptr_t)sep->se_data;
3780 
3781         (void) proc_signame(signum, name, sizeof (name));
3782         (void) mdb_iob_snprintf(buf, nbytes, "stop on %s", name);
3783 
3784         return (buf);
3785 }
3786 
3787 /*ARGSUSED*/
3788 static int
3789 pt_signal_match(mdb_tgt_t *t, mdb_sespec_t *sep, mdb_tgt_status_t *tsp)
3790 {
3791         const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
3792         int signum = (intptr_t)sep->se_data;
3793 
3794         return (psp->pr_why == PR_SIGNALLED && psp->pr_what == signum);
3795 }
3796 
3797 static const mdb_se_ops_t proc_signal_ops = {
3798         pt_signal_ctor,         /* se_ctor */
3799         pt_signal_dtor,         /* se_dtor */
3800         pt_signal_info,         /* se_info */
3801         no_se_secmp,            /* se_secmp */
3802         no_se_vecmp,            /* se_vecmp */
3803         no_se_arm,              /* se_arm */
3804         no_se_disarm,           /* se_disarm */
3805         no_se_cont,             /* se_cont */
3806         pt_signal_match         /* se_match */
3807 };
3808 
3809 static int
3810 pt_fault_ctor(mdb_tgt_t *t, mdb_sespec_t *sep, void *args)
3811 {
3812         struct ps_prochandle *P = t->t_pshandle;
3813 
3814         if (P != NULL && Pstate(P) < PS_LOST) {
3815                 sep->se_data = args; /* data is raw fault number */
3816                 return (Pfault(P, (intptr_t)args, TRUE) < 0 ? -1 : 0);
3817         }
3818 
3819         return (set_errno(EMDB_NOPROC));
3820 }
3821 
3822 static void
3823 pt_fault_dtor(mdb_tgt_t *t, mdb_sespec_t *sep)
3824 {
3825         int fault = (intptr_t)sep->se_data;
3826 
3827         if (fault != FLTBPT && fault != FLTTRACE && fault != FLTWATCH)
3828                 (void) Pfault(t->t_pshandle, fault, FALSE);
3829 }
3830 
3831 /*ARGSUSED*/
3832 static char *
3833 pt_fault_info(mdb_tgt_t *t, mdb_sespec_t *sep, mdb_vespec_t *vep,
3834     mdb_tgt_spec_desc_t *sp, char *buf, size_t nbytes)
3835 {
3836         char name[32];
3837         int fltnum;
3838 
3839         if (vep != NULL)
3840                 fltnum = (intptr_t)vep->ve_args;
3841         else
3842                 fltnum = (intptr_t)sep->se_data;
3843 
3844         (void) proc_fltname(fltnum, name, sizeof (name));
3845         (void) mdb_iob_snprintf(buf, nbytes, "stop on %s", name);
3846 
3847         return (buf);
3848 }
3849 
3850 /*ARGSUSED*/
3851 static int
3852 pt_fault_match(mdb_tgt_t *t, mdb_sespec_t *sep, mdb_tgt_status_t *tsp)
3853 {
3854         const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
3855         int fltnum = (intptr_t)sep->se_data;
3856 
3857         return (psp->pr_why == PR_FAULTED && psp->pr_what == fltnum);
3858 }
3859 
3860 static const mdb_se_ops_t proc_fault_ops = {
3861         pt_fault_ctor,          /* se_ctor */
3862         pt_fault_dtor,          /* se_dtor */
3863         pt_fault_info,          /* se_info */
3864         no_se_secmp,            /* se_secmp */
3865         no_se_vecmp,            /* se_vecmp */
3866         no_se_arm,              /* se_arm */
3867         no_se_disarm,           /* se_disarm */
3868         no_se_cont,             /* se_cont */
3869         pt_fault_match          /* se_match */
3870 };
3871 
3872 /*
3873  * Callback for pt_ignore() dcmd above: for each VID, determine if it
3874  * corresponds to a vespec that traces the specified signal, and delete it.
3875  */
3876 /*ARGSUSED*/
3877 static int
3878 pt_ignore_sig(mdb_tgt_t *t, void *sig, int vid, void *data)
3879 {
3880         mdb_vespec_t *vep = mdb_tgt_vespec_lookup(t, vid);
3881 
3882         if (vep->ve_se->se_ops == &proc_signal_ops && vep->ve_args == sig)
3883                 (void) mdb_tgt_vespec_delete(t, vid);
3884 
3885         return (0);
3886 }
3887 
3888 static int
3889 pt_brkpt_ctor(mdb_tgt_t *t, mdb_sespec_t *sep, void *args)
3890 {
3891         pt_data_t *pt = t->t_data;
3892         pt_bparg_t *pta = args;
3893         pt_brkpt_t *ptb;
3894         GElf_Sym s;
3895 
3896         if (t->t_pshandle == NULL || Pstate(t->t_pshandle) >= PS_LOST)
3897                 return (set_errno(EMDB_NOPROC));
3898 
3899         if (pta->pta_symbol != NULL) {
3900                 if (!pt->p_rtld_finished &&
3901                     strchr(pta->pta_symbol, '`') == NULL)
3902                         return (set_errno(EMDB_NOSYM));
3903                 if (mdb_tgt_lookup_by_scope(t, pta->pta_symbol, &s,
3904                     NULL) == -1) {
3905                         if (errno != EMDB_NOOBJ && !(errno == EMDB_NOSYM &&
3906                             (!(mdb.m_flags & MDB_FL_BPTNOSYMSTOP) ||
3907                             !pt->p_rtld_finished))) {
3908                                 warn("breakpoint %s activation failed",
3909                                     pta->pta_symbol);
3910                         }
3911                         return (-1); /* errno is set for us */
3912                 }
3913 
3914                 pta->pta_addr = (uintptr_t)s.st_value;
3915         }
3916 
3917 #ifdef __sparc
3918         if (pta->pta_addr & 3)
3919                 return (set_errno(EMDB_BPALIGN));
3920 #endif
3921 
3922         if (Paddr_to_map(t->t_pshandle, pta->pta_addr) == NULL)
3923                 return (set_errno(EMDB_NOMAP));
3924 
3925         ptb = mdb_alloc(sizeof (pt_brkpt_t), UM_SLEEP);
3926         ptb->ptb_addr = pta->pta_addr;
3927         ptb->ptb_instr = NULL;
3928         sep->se_data = ptb;
3929 
3930         return (0);
3931 }
3932 
3933 /*ARGSUSED*/
3934 static void
3935 pt_brkpt_dtor(mdb_tgt_t *t, mdb_sespec_t *sep)
3936 {
3937         mdb_free(sep->se_data, sizeof (pt_brkpt_t));
3938 }
3939 
3940 /*ARGSUSED*/
3941 static char *
3942 pt_brkpt_info(mdb_tgt_t *t, mdb_sespec_t *sep, mdb_vespec_t *vep,
3943     mdb_tgt_spec_desc_t *sp, char *buf, size_t nbytes)
3944 {
3945         uintptr_t addr = NULL;
3946 
3947         if (vep != NULL) {
3948                 pt_bparg_t *pta = vep->ve_args;
3949 
3950                 if (pta->pta_symbol != NULL) {
3951                         (void) mdb_iob_snprintf(buf, nbytes, "stop at %s",
3952                             pta->pta_symbol);
3953                 } else {
3954                         (void) mdb_iob_snprintf(buf, nbytes, "stop at %a",
3955                             pta->pta_addr);
3956                         addr = pta->pta_addr;
3957                 }
3958 
3959         } else {
3960                 addr = ((pt_brkpt_t *)sep->se_data)->ptb_addr;
3961                 (void) mdb_iob_snprintf(buf, nbytes, "stop at %a", addr);
3962         }
3963 
3964         sp->spec_base = addr;
3965         sp->spec_size = sizeof (instr_t);
3966 
3967         return (buf);
3968 }
3969 
3970 static int
3971 pt_brkpt_secmp(mdb_tgt_t *t, mdb_sespec_t *sep, void *args)
3972 {
3973         pt_brkpt_t *ptb = sep->se_data;
3974         pt_bparg_t *pta = args;
3975         GElf_Sym sym;
3976 
3977         if (pta->pta_symbol != NULL) {
3978                 return (mdb_tgt_lookup_by_scope(t, pta->pta_symbol,
3979                     &sym, NULL) == 0 && sym.st_value == ptb->ptb_addr);
3980         }
3981 
3982         return (pta->pta_addr == ptb->ptb_addr);
3983 }
3984 
3985 /*ARGSUSED*/
3986 static int
3987 pt_brkpt_vecmp(mdb_tgt_t *t, mdb_vespec_t *vep, void *args)
3988 {
3989         pt_bparg_t *pta1 = vep->ve_args;
3990         pt_bparg_t *pta2 = args;
3991 
3992         if (pta1->pta_symbol != NULL && pta2->pta_symbol != NULL)
3993                 return (strcmp(pta1->pta_symbol, pta2->pta_symbol) == 0);
3994 
3995         if (pta1->pta_symbol == NULL && pta2->pta_symbol == NULL)
3996                 return (pta1->pta_addr == pta2->pta_addr);
3997 
3998         return (0); /* fail if one is symbolic, other is an explicit address */
3999 }
4000 
4001 static int
4002 pt_brkpt_arm(mdb_tgt_t *t, mdb_sespec_t *sep)
4003 {
4004         pt_brkpt_t *ptb = sep->se_data;
4005         return (Psetbkpt(t->t_pshandle, ptb->ptb_addr, &ptb->ptb_instr));
4006 }
4007 
4008 /*
4009  * In order to disarm a breakpoint, we replace the trap instruction at ptb_addr
4010  * with the saved instruction.  However, if we have stopped after a successful
4011  * exec(2), we do not want to restore ptb_instr because the address space has
4012  * now been replaced with the text of a different executable, and so restoring
4013  * the saved instruction would be incorrect.  The exec itself has effectively
4014  * removed all breakpoint trap instructions for us, so we can just return.
4015  */
4016 static int
4017 pt_brkpt_disarm(mdb_tgt_t *t, mdb_sespec_t *sep)
4018 {
4019         const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
4020         pt_brkpt_t *ptb = sep->se_data;
4021 
4022         if (psp->pr_why == PR_SYSEXIT && psp->pr_errno == 0 &&
4023             psp->pr_what == SYS_execve)
4024                 return (0); /* do not restore saved instruction */
4025 
4026         return (Pdelbkpt(t->t_pshandle, ptb->ptb_addr, ptb->ptb_instr));
4027 }
4028 
4029 /*
4030  * Determine whether the specified sespec is an armed watchpoint that overlaps
4031  * with the given breakpoint and has the given flags set.  We use this to find
4032  * conflicts with breakpoints, below.
4033  */
4034 static int
4035 pt_wp_overlap(mdb_sespec_t *sep, pt_brkpt_t *ptb, int flags)
4036 {
4037         const prwatch_t *wp = sep->se_data;
4038 
4039         return (sep->se_state == MDB_TGT_SPEC_ARMED &&
4040             sep->se_ops == &proc_wapt_ops && (wp->pr_wflags & flags) &&
4041             ptb->ptb_addr - wp->pr_vaddr < wp->pr_size);
4042 }
4043 
4044 /*
4045  * We step over breakpoints using Pxecbkpt() in libproc.  If a conflicting
4046  * watchpoint is present, we must temporarily remove it before stepping over
4047  * the breakpoint so we do not immediately re-trigger the watchpoint.  We know
4048  * the watchpoint has already triggered on our trap instruction as part of
4049  * fetching it.  Before we return, we must re-install any disabled watchpoints.
4050  */
4051 static int
4052 pt_brkpt_cont(mdb_tgt_t *t, mdb_sespec_t *sep, mdb_tgt_status_t *tsp)
4053 {
4054         pt_brkpt_t *ptb = sep->se_data;
4055         int status = -1;
4056         int error;
4057         const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
4058 
4059         /*
4060          * If the PC no longer matches our original address, then the user has
4061          * changed it while we have been stopped. In this case, it no longer
4062          * makes any sense to continue over this breakpoint.  We return as if we
4063          * continued normally.
4064          */
4065         if ((uintptr_t)psp->pr_info.si_addr != psp->pr_reg[R_PC])
4066                 return (pt_status(t, tsp));
4067 
4068         for (sep = mdb_list_next(&t->t_active); sep; sep = mdb_list_next(sep)) {
4069                 if (pt_wp_overlap(sep, ptb, WA_EXEC))
4070                         (void) Pdelwapt(t->t_pshandle, sep->se_data);
4071         }
4072 
4073         if (Pxecbkpt(t->t_pshandle, ptb->ptb_instr) == 0 &&
4074             Pdelbkpt(t->t_pshandle, ptb->ptb_addr, ptb->ptb_instr) == 0)
4075                 status = pt_status(t, tsp);
4076 
4077         error = errno; /* save errno from Pxecbkpt, Pdelbkpt, or pt_status */
4078 
4079         for (sep = mdb_list_next(&t->t_active); sep; sep = mdb_list_next(sep)) {
4080                 if (pt_wp_overlap(sep, ptb, WA_EXEC) &&
4081                     Psetwapt(t->t_pshandle, sep->se_data) == -1) {
4082                         sep->se_state = MDB_TGT_SPEC_ERROR;
4083                         sep->se_errno = errno;
4084                 }
4085         }
4086 
4087         (void) set_errno(error);
4088         return (status);
4089 }
4090 
4091 /*ARGSUSED*/
4092 static int
4093 pt_brkpt_match(mdb_tgt_t *t, mdb_sespec_t *sep, mdb_tgt_status_t *tsp)
4094 {
4095         const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
4096         pt_brkpt_t *ptb = sep->se_data;
4097 
4098         return (psp->pr_why == PR_FAULTED && psp->pr_what == FLTBPT &&
4099             psp->pr_reg[R_PC] == ptb->ptb_addr);
4100 }
4101 
4102 static const mdb_se_ops_t proc_brkpt_ops = {
4103         pt_brkpt_ctor,          /* se_ctor */
4104         pt_brkpt_dtor,          /* se_dtor */
4105         pt_brkpt_info,          /* se_info */
4106         pt_brkpt_secmp,         /* se_secmp */
4107         pt_brkpt_vecmp,         /* se_vecmp */
4108         pt_brkpt_arm,           /* se_arm */
4109         pt_brkpt_disarm,        /* se_disarm */
4110         pt_brkpt_cont,          /* se_cont */
4111         pt_brkpt_match          /* se_match */
4112 };
4113 
4114 static int
4115 pt_wapt_ctor(mdb_tgt_t *t, mdb_sespec_t *sep, void *args)
4116 {
4117         if (t->t_pshandle == NULL || Pstate(t->t_pshandle) >= PS_LOST)
4118                 return (set_errno(EMDB_NOPROC));
4119 
4120         sep->se_data = mdb_alloc(sizeof (prwatch_t), UM_SLEEP);
4121         bcopy(args, sep->se_data, sizeof (prwatch_t));
4122         return (0);
4123 }
4124 
4125 /*ARGSUSED*/
4126 static void
4127 pt_wapt_dtor(mdb_tgt_t *t, mdb_sespec_t *sep)
4128 {
4129         mdb_free(sep->se_data, sizeof (prwatch_t));
4130 }
4131 
4132 /*ARGSUSED*/
4133 static char *
4134 pt_wapt_info(mdb_tgt_t *t, mdb_sespec_t *sep, mdb_vespec_t *vep,
4135     mdb_tgt_spec_desc_t *sp, char *buf, size_t nbytes)
4136 {
4137         prwatch_t *wp = vep != NULL ? vep->ve_args : sep->se_data;
4138         char desc[24];
4139 
4140         ASSERT(wp->pr_wflags != 0);
4141         desc[0] = '\0';
4142 
4143         switch (wp->pr_wflags) {
4144         case WA_READ:
4145                 (void) strcat(desc, "/read");
4146                 break;
4147         case WA_WRITE:
4148                 (void) strcat(desc, "/write");
4149                 break;
4150         case WA_EXEC:
4151                 (void) strcat(desc, "/exec");
4152                 break;
4153         default:
4154                 if (wp->pr_wflags & WA_READ)
4155                         (void) strcat(desc, "/r");
4156                 if (wp->pr_wflags & WA_WRITE)
4157                         (void) strcat(desc, "/w");
4158                 if (wp->pr_wflags & WA_EXEC)
4159                         (void) strcat(desc, "/x");
4160         }
4161 
4162         (void) mdb_iob_snprintf(buf, nbytes, "stop on %s of [%la, %la)",
4163             desc + 1, wp->pr_vaddr, wp->pr_vaddr + wp->pr_size);
4164 
4165         sp->spec_base = wp->pr_vaddr;
4166         sp->spec_size = wp->pr_size;
4167 
4168         return (buf);
4169 }
4170 
4171 /*ARGSUSED*/
4172 static int
4173 pt_wapt_secmp(mdb_tgt_t *t, mdb_sespec_t *sep, void *args)
4174 {
4175         prwatch_t *wp1 = sep->se_data;
4176         prwatch_t *wp2 = args;
4177 
4178         return (wp1->pr_vaddr == wp2->pr_vaddr &&
4179             wp1->pr_size == wp2->pr_size && wp1->pr_wflags == wp2->pr_wflags);
4180 }
4181 
4182 /*ARGSUSED*/
4183 static int
4184 pt_wapt_vecmp(mdb_tgt_t *t, mdb_vespec_t *vep, void *args)
4185 {
4186         prwatch_t *wp1 = vep->ve_args;
4187         prwatch_t *wp2 = args;
4188 
4189         return (wp1->pr_vaddr == wp2->pr_vaddr &&
4190             wp1->pr_size == wp2->pr_size && wp1->pr_wflags == wp2->pr_wflags);
4191 }
4192 
4193 static int
4194 pt_wapt_arm(mdb_tgt_t *t, mdb_sespec_t *sep)
4195 {
4196         return (Psetwapt(t->t_pshandle, sep->se_data));
4197 }
4198 
4199 static int
4200 pt_wapt_disarm(mdb_tgt_t *t, mdb_sespec_t *sep)
4201 {
4202         return (Pdelwapt(t->t_pshandle, sep->se_data));
4203 }
4204 
4205 /*
4206  * Determine whether the specified sespec is an armed breakpoint at the
4207  * given %pc.  We use this to find conflicts with watchpoints below.
4208  */
4209 static int
4210 pt_bp_overlap(mdb_sespec_t *sep, uintptr_t pc)
4211 {
4212         pt_brkpt_t *ptb = sep->se_data;
4213 
4214         return (sep->se_state == MDB_TGT_SPEC_ARMED &&
4215             sep->se_ops == &proc_brkpt_ops && ptb->ptb_addr == pc);
4216 }
4217 
4218 /*
4219  * We step over watchpoints using Pxecwapt() in libproc.  If a conflicting
4220  * breakpoint is present, we must temporarily disarm it before stepping
4221  * over the watchpoint so we do not immediately re-trigger the breakpoint.
4222  * This is similar to the case handled in pt_brkpt_cont(), above.
4223  */
4224 static int
4225 pt_wapt_cont(mdb_tgt_t *t, mdb_sespec_t *sep, mdb_tgt_status_t *tsp)
4226 {
4227         const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
4228         mdb_sespec_t *bep = NULL;
4229         int status = -1;
4230         int error;
4231 
4232         /*
4233          * If the PC no longer matches our original address, then the user has
4234          * changed it while we have been stopped. In this case, it no longer
4235          * makes any sense to continue over this instruction.  We return as if
4236          * we continued normally.
4237          */
4238         if ((uintptr_t)psp->pr_info.si_pc != psp->pr_reg[R_PC])
4239                 return (pt_status(t, tsp));
4240 
4241         if (psp->pr_info.si_code != TRAP_XWATCH) {
4242                 for (bep = mdb_list_next(&t->t_active); bep != NULL;
4243                     bep = mdb_list_next(bep)) {
4244                         if (pt_bp_overlap(bep, psp->pr_reg[R_PC])) {
4245                                 (void) bep->se_ops->se_disarm(t, bep);
4246                                 bep->se_state = MDB_TGT_SPEC_ACTIVE;
4247                                 break;
4248                         }
4249                 }
4250         }
4251 
4252         if (Pxecwapt(t->t_pshandle, sep->se_data) == 0)
4253                 status = pt_status(t, tsp);
4254 
4255         error = errno; /* save errno from Pxecwapt or pt_status */
4256 
4257         if (bep != NULL)
4258                 mdb_tgt_sespec_arm_one(t, bep);
4259 
4260         (void) set_errno(error);
4261         return (status);
4262 }
4263 
4264 /*ARGSUSED*/
4265 static int
4266 pt_wapt_match(mdb_tgt_t *t, mdb_sespec_t *sep, mdb_tgt_status_t *tsp)
4267 {
4268         const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp;
4269         prwatch_t *wp = sep->se_data;
4270 
4271         return (psp->pr_why == PR_FAULTED && psp->pr_what == FLTWATCH &&
4272             (uintptr_t)psp->pr_info.si_addr - wp->pr_vaddr < wp->pr_size);
4273 }
4274 
4275 static const mdb_se_ops_t proc_wapt_ops = {
4276         pt_wapt_ctor,           /* se_ctor */
4277         pt_wapt_dtor,           /* se_dtor */
4278         pt_wapt_info,           /* se_info */
4279         pt_wapt_secmp,          /* se_secmp */
4280         pt_wapt_vecmp,          /* se_vecmp */
4281         pt_wapt_arm,            /* se_arm */
4282         pt_wapt_disarm,         /* se_disarm */
4283         pt_wapt_cont,           /* se_cont */
4284         pt_wapt_match           /* se_match */
4285 };
4286 
4287 static void
4288 pt_bparg_dtor(mdb_vespec_t *vep)
4289 {
4290         pt_bparg_t *pta = vep->ve_args;
4291 
4292         if (pta->pta_symbol != NULL)
4293                 strfree(pta->pta_symbol);
4294 
4295         mdb_free(pta, sizeof (pt_bparg_t));
4296 }
4297 
4298 static int
4299 pt_add_vbrkpt(mdb_tgt_t *t, uintptr_t addr,
4300     int spec_flags, mdb_tgt_se_f *func, void *data)
4301 {
4302         pt_bparg_t *pta = mdb_alloc(sizeof (pt_bparg_t), UM_SLEEP);
4303 
4304         pta->pta_symbol = NULL;
4305         pta->pta_addr = addr;
4306 
4307         return (mdb_tgt_vespec_insert(t, &proc_brkpt_ops, spec_flags,
4308             func, data, pta, pt_bparg_dtor));
4309 }
4310 
4311 static int
4312 pt_add_sbrkpt(mdb_tgt_t *t, const char *sym,
4313     int spec_flags, mdb_tgt_se_f *func, void *data)
4314 {
4315         pt_bparg_t *pta;
4316 
4317         if (sym[0] == '`') {
4318                 (void) set_errno(EMDB_NOOBJ);
4319                 return (0);
4320         }
4321 
4322         if (sym[strlen(sym) - 1] == '`') {
4323                 (void) set_errno(EMDB_NOSYM);
4324                 return (0);
4325         }
4326 
4327         pta = mdb_alloc(sizeof (pt_bparg_t), UM_SLEEP);
4328         pta->pta_symbol = strdup(sym);
4329         pta->pta_addr = NULL;
4330 
4331         return (mdb_tgt_vespec_insert(t, &proc_brkpt_ops, spec_flags,
4332             func, data, pta, pt_bparg_dtor));
4333 }
4334 
4335 static int
4336 pt_wparg_overlap(const prwatch_t *wp1, const prwatch_t *wp2)
4337 {
4338         if (wp2->pr_vaddr + wp2->pr_size <= wp1->pr_vaddr)
4339                 return (0); /* no range overlap */
4340 
4341         if (wp1->pr_vaddr + wp1->pr_size <= wp2->pr_vaddr)
4342                 return (0); /* no range overlap */
4343 
4344         return (wp1->pr_vaddr != wp2->pr_vaddr ||
4345             wp1->pr_size != wp2->pr_size || wp1->pr_wflags != wp2->pr_wflags);
4346 }
4347 
4348 static void
4349 pt_wparg_dtor(mdb_vespec_t *vep)
4350 {
4351         mdb_free(vep->ve_args, sizeof (prwatch_t));
4352 }
4353 
4354 static int
4355 pt_add_vwapt(mdb_tgt_t *t, uintptr_t addr, size_t len, uint_t wflags,
4356     int spec_flags, mdb_tgt_se_f *func, void *data)
4357 {
4358         prwatch_t *wp = mdb_alloc(sizeof (prwatch_t), UM_SLEEP);
4359         mdb_sespec_t *sep;
4360 
4361         wp->pr_vaddr = addr;
4362         wp->pr_size = len;
4363         wp->pr_wflags = 0;
4364 
4365         if (wflags & MDB_TGT_WA_R)
4366                 wp->pr_wflags |= WA_READ;
4367         if (wflags & MDB_TGT_WA_W)
4368                 wp->pr_wflags |= WA_WRITE;
4369         if (wflags & MDB_TGT_WA_X)
4370                 wp->pr_wflags |= WA_EXEC;
4371 
4372         for (sep = mdb_list_next(&t->t_active); sep; sep = mdb_list_next(sep)) {
4373                 if (sep->se_ops == &proc_wapt_ops &&
4374                     mdb_list_next(&sep->se_velist) != NULL &&
4375                     pt_wparg_overlap(wp, sep->se_data))
4376                         goto dup;
4377         }
4378 
4379         for (sep = mdb_list_next(&t->t_idle); sep; sep = mdb_list_next(sep)) {
4380                 if (sep->se_ops == &proc_wapt_ops && pt_wparg_overlap(wp,
4381                     ((mdb_vespec_t *)mdb_list_next(&sep->se_velist))->ve_args))
4382                         goto dup;
4383         }
4384 
4385         return (mdb_tgt_vespec_insert(t, &proc_wapt_ops, spec_flags,
4386             func, data, wp, pt_wparg_dtor));
4387 
4388 dup:
4389         mdb_free(wp, sizeof (prwatch_t));
4390         (void) set_errno(EMDB_WPDUP);
4391         return (0);
4392 }
4393 
4394 static int
4395 pt_add_sysenter(mdb_tgt_t *t, int sysnum,
4396     int spec_flags, mdb_tgt_se_f *func, void *data)
4397 {
4398         if (sysnum <= 0 || sysnum > PRMAXSYS) {
4399                 (void) set_errno(EMDB_BADSYSNUM);
4400                 return (0);
4401         }
4402 
4403         return (mdb_tgt_vespec_insert(t, &proc_sysenter_ops, spec_flags,
4404             func, data, (void *)(uintptr_t)sysnum, no_ve_dtor));
4405 }
4406 
4407 static int
4408 pt_add_sysexit(mdb_tgt_t *t, int sysnum,
4409     int spec_flags, mdb_tgt_se_f *func, void *data)
4410 {
4411         if (sysnum <= 0 || sysnum > PRMAXSYS) {
4412                 (void) set_errno(EMDB_BADSYSNUM);
4413                 return (0);
4414         }
4415 
4416         return (mdb_tgt_vespec_insert(t, &proc_sysexit_ops, spec_flags,
4417             func, data, (void *)(uintptr_t)sysnum, no_ve_dtor));
4418 }
4419 
4420 static int
4421 pt_add_signal(mdb_tgt_t *t, int signum,
4422     int spec_flags, mdb_tgt_se_f *func, void *data)
4423 {
4424         pt_data_t *pt = t->t_data;
4425 
4426         if (signum <= 0 || signum > pt->p_maxsig) {
4427                 (void) set_errno(EMDB_BADSIGNUM);
4428                 return (0);
4429         }
4430 
4431         return (mdb_tgt_vespec_insert(t, &proc_signal_ops, spec_flags,
4432             func, data, (void *)(uintptr_t)signum, no_ve_dtor));
4433 }
4434 
4435 static int
4436 pt_add_fault(mdb_tgt_t *t, int fltnum,
4437     int spec_flags, mdb_tgt_se_f *func, void *data)
4438 {
4439         if (fltnum <= 0 || fltnum > PRMAXFAULT) {
4440                 (void) set_errno(EMDB_BADFLTNUM);
4441                 return (0);
4442         }
4443 
4444         return (mdb_tgt_vespec_insert(t, &proc_fault_ops, spec_flags,
4445             func, data, (void *)(uintptr_t)fltnum, no_ve_dtor));
4446 }
4447 
4448 static int
4449 pt_getareg(mdb_tgt_t *t, mdb_tgt_tid_t tid,
4450     const char *rname, mdb_tgt_reg_t *rp)
4451 {
4452         pt_data_t *pt = t->t_data;
4453         prgregset_t grs;
4454         mdb_var_t *v;
4455 
4456         if (t->t_pshandle == NULL)
4457                 return (set_errno(EMDB_NOPROC));
4458 
4459         if ((v = mdb_nv_lookup(&pt->p_regs, rname)) != NULL) {
4460                 uintmax_t rd_nval = mdb_nv_get_value(v);
4461                 ushort_t rd_num = MDB_TGT_R_NUM(rd_nval);
4462                 ushort_t rd_flags = MDB_TGT_R_FLAGS(rd_nval);
4463 
4464                 if (!MDB_TGT_R_IS_FP(rd_flags)) {
4465                         mdb_tgt_reg_t r = 0;
4466 
4467 #if defined(__sparc) && defined(_ILP32)
4468                         /*
4469                          * If we are debugging on 32-bit SPARC, the globals and
4470                          * outs can have 32 upper bits hiding in the xregs.
4471                          */
4472                         /* gcc doesn't like >= R_G0 because R_G0 == 0 */
4473                         int is_g = (rd_num == R_G0 ||
4474                             rd_num >= R_G1 && rd_num <= R_G7);
4475                         int is_o = (rd_num >= R_O0 && rd_num <= R_O7);
4476                         prxregset_t xrs;
4477 
4478                         if (is_g && PTL_GETXREGS(t, tid, &xrs) == 0 &&
4479                             xrs.pr_type == XR_TYPE_V8P) {
4480                                 r |= (uint64_t)xrs.pr_un.pr_v8p.pr_xg[
4481                                     rd_num - R_G0 + XR_G0] << 32;
4482                         }
4483 
4484                         if (is_o && PTL_GETXREGS(t, tid, &xrs) == 0 &&
4485                             xrs.pr_type == XR_TYPE_V8P) {
4486                                 r |= (uint64_t)xrs.pr_un.pr_v8p.pr_xo[
4487                                     rd_num - R_O0 + XR_O0] << 32;
4488                         }
4489 #endif  /* __sparc && _ILP32 */
4490 
4491                         /*
4492                          * Avoid sign-extension by casting: recall that procfs
4493                          * defines prgreg_t as a long or int and our native
4494                          * register handling uses uint64_t's.
4495                          */
4496                         if (PTL_GETREGS(t, tid, grs) == 0) {
4497                                 *rp = r | (ulong_t)grs[rd_num];
4498                                 return (0);
4499                         }
4500                         return (-1);
4501                 } else
4502                         return (pt_getfpreg(t, tid, rd_num, rd_flags, rp));
4503         }
4504 
4505         return (set_errno(EMDB_BADREG));
4506 }
4507 
4508 static int
4509 pt_putareg(mdb_tgt_t *t, mdb_tgt_tid_t tid, const char *rname, mdb_tgt_reg_t r)
4510 {
4511         pt_data_t *pt = t->t_data;
4512         prgregset_t grs;
4513         mdb_var_t *v;
4514 
4515         if (t->t_pshandle == NULL)
4516                 return (set_errno(EMDB_NOPROC));
4517 
4518         if ((v = mdb_nv_lookup(&pt->p_regs, rname)) != NULL) {
4519                 uintmax_t rd_nval = mdb_nv_get_value(v);
4520                 ushort_t rd_num = MDB_TGT_R_NUM(rd_nval);
4521                 ushort_t rd_flags = MDB_TGT_R_FLAGS(rd_nval);
4522 
4523                 if (!MDB_TGT_R_IS_FP(rd_flags)) {
4524 #if defined(__sparc) && defined(_ILP32)
4525                         /*
4526                          * If we are debugging on 32-bit SPARC, the globals and
4527                          * outs can have 32 upper bits stored in the xregs.
4528                          */
4529                         int is_g = (rd_num == R_G0 ||
4530                             rd_num >= R_G1 && rd_num <= R_G7);
4531                         int is_o = (rd_num >= R_O0 && rd_num <= R_O7);
4532                         prxregset_t xrs;
4533 
4534                         if ((is_g || is_o) && PTL_GETXREGS(t, tid, &xrs) == 0 &&
4535                             xrs.pr_type == XR_TYPE_V8P) {
4536                                 if (is_g) {
4537                                         xrs.pr_un.pr_v8p.pr_xg[rd_num -
4538                                             R_G0 + XR_G0] = (uint32_t)(r >> 32);
4539                                 } else if (is_o) {
4540                                         xrs.pr_un.pr_v8p.pr_xo[rd_num -
4541                                             R_O0 + XR_O0] = (uint32_t)(r >> 32);
4542                                 }
4543 
4544                                 if (PTL_SETXREGS(t, tid, &xrs) == -1)
4545                                         return (-1);
4546                         }
4547 #endif  /* __sparc && _ILP32 */
4548 
4549                         if (PTL_GETREGS(t, tid, grs) == 0) {
4550                                 grs[rd_num] = (prgreg_t)r;
4551                                 return (PTL_SETREGS(t, tid, grs));
4552                         }
4553                         return (-1);
4554                 } else
4555                         return (pt_putfpreg(t, tid, rd_num, rd_flags, r));
4556         }
4557 
4558         return (set_errno(EMDB_BADREG));
4559 }
4560 
4561 static int
4562 pt_stack_call(pt_stkarg_t *psp, const prgregset_t grs, uint_t argc, long *argv)
4563 {
4564         psp->pstk_gotpc |= (grs[R_PC] != 0);
4565 
4566         if (!psp->pstk_gotpc)
4567                 return (0); /* skip initial zeroed frames */
4568 
4569         return (psp->pstk_func(psp->pstk_private, grs[R_PC],
4570             argc, argv, (const struct mdb_tgt_gregset *)grs));
4571 }
4572 
4573 static int
4574 pt_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp,
4575     mdb_tgt_stack_f *func, void *arg)
4576 {
4577         if (t->t_pshandle != NULL) {
4578                 pt_stkarg_t pstk;
4579 
4580                 pstk.pstk_func = func;
4581                 pstk.pstk_private = arg;
4582                 pstk.pstk_gotpc = FALSE;
4583 
4584                 (void) Pstack_iter(t->t_pshandle, gsp->gregs,
4585                     (proc_stack_f *)pt_stack_call, &pstk);
4586 
4587                 return (0);
4588         }
4589 
4590         return (set_errno(EMDB_NOPROC));
4591 }
4592 
4593 static int
4594 pt_auxv(mdb_tgt_t *t, const auxv_t **auxvp)
4595 {
4596         if (t->t_pshandle != NULL) {
4597                 *auxvp = Pgetauxvec(t->t_pshandle);
4598                 return (0);
4599         }
4600 
4601         return (set_errno(EMDB_NOPROC));
4602 }
4603 
4604 
4605 static const mdb_tgt_ops_t proc_ops = {
4606         pt_setflags,                            /* t_setflags */
4607         (int (*)()) mdb_tgt_notsup,             /* t_setcontext */
4608         pt_activate,                            /* t_activate */
4609         pt_deactivate,                          /* t_deactivate */
4610         pt_periodic,                            /* t_periodic */
4611         pt_destroy,                             /* t_destroy */
4612         pt_name,                                /* t_name */
4613         (const char *(*)()) mdb_conf_isa,       /* t_isa */
4614         pt_platform,                            /* t_platform */
4615         pt_uname,                               /* t_uname */
4616         pt_dmodel,                              /* t_dmodel */
4617         (ssize_t (*)()) mdb_tgt_notsup,         /* t_aread */
4618         (ssize_t (*)()) mdb_tgt_notsup,         /* t_awrite */
4619         pt_vread,                               /* t_vread */
4620         pt_vwrite,                              /* t_vwrite */
4621         (ssize_t (*)()) mdb_tgt_notsup,         /* t_pread */
4622         (ssize_t (*)()) mdb_tgt_notsup,         /* t_pwrite */
4623         pt_fread,                               /* t_fread */
4624         pt_fwrite,                              /* t_fwrite */
4625         (ssize_t (*)()) mdb_tgt_notsup,         /* t_ioread */
4626         (ssize_t (*)()) mdb_tgt_notsup,         /* t_iowrite */
4627         (int (*)()) mdb_tgt_notsup,             /* t_vtop */
4628         pt_lookup_by_name,                      /* t_lookup_by_name */
4629         pt_lookup_by_addr,                      /* t_lookup_by_addr */
4630         pt_symbol_iter,                         /* t_symbol_iter */
4631         pt_mapping_iter,                        /* t_mapping_iter */
4632         pt_object_iter,                         /* t_object_iter */
4633         pt_addr_to_map,                         /* t_addr_to_map */
4634         pt_name_to_map,                         /* t_name_to_map */
4635         pt_addr_to_ctf,                         /* t_addr_to_ctf */
4636         pt_name_to_ctf,                         /* t_name_to_ctf */
4637         pt_status,                              /* t_status */
4638         pt_run,                                 /* t_run */
4639         pt_step,                                /* t_step */
4640         pt_step_out,                            /* t_step_out */
4641         (int (*)()) mdb_tgt_notsup,             /* t_step_branch */
4642         pt_next,                                /* t_next */
4643         pt_continue,                            /* t_cont */
4644         pt_signal,                              /* t_signal */
4645         pt_add_vbrkpt,                          /* t_add_vbrkpt */
4646         pt_add_sbrkpt,                          /* t_add_sbrkpt */
4647         (int (*)()) mdb_tgt_null,               /* t_add_pwapt */
4648         pt_add_vwapt,                           /* t_add_vwapt */
4649         (int (*)()) mdb_tgt_null,               /* t_add_iowapt */
4650         pt_add_sysenter,                        /* t_add_sysenter */
4651         pt_add_sysexit,                         /* t_add_sysexit */
4652         pt_add_signal,                          /* t_add_signal */
4653         pt_add_fault,                           /* t_add_fault */
4654         pt_getareg,                             /* t_getareg */
4655         pt_putareg,                             /* t_putareg */
4656         pt_stack_iter,                          /* t_stack_iter */
4657         pt_auxv                                 /* t_auxv */
4658 };
4659 
4660 /*
4661  * Utility function for converting libproc errno values to mdb error values
4662  * for the ptl calls below.  Currently, we only need to convert ENOENT to
4663  * EMDB_NOTHREAD to produce a more useful error message for the user.
4664  */
4665 static int
4666 ptl_err(int error)
4667 {
4668         if (error != 0 && errno == ENOENT)
4669                 return (set_errno(EMDB_NOTHREAD));
4670 
4671         return (error);
4672 }
4673 
4674 /*ARGSUSED*/
4675 static mdb_tgt_tid_t
4676 pt_lwp_tid(mdb_tgt_t *t, void *tap)
4677 {
4678         if (t->t_pshandle != NULL)
4679                 return (Pstatus(t->t_pshandle)->pr_lwp.pr_lwpid);
4680 
4681         return (set_errno(EMDB_NOPROC));
4682 }
4683 
4684 static int
4685 pt_lwp_add(mdb_addrvec_t *ap, const lwpstatus_t *psp)
4686 {
4687         mdb_addrvec_unshift(ap, psp->pr_lwpid);
4688         return (0);
4689 }
4690 
4691 /*ARGSUSED*/
4692 static int
4693 pt_lwp_iter(mdb_tgt_t *t, void *tap, mdb_addrvec_t *ap)
4694 {
4695         if (t->t_pshandle != NULL)
4696                 return (Plwp_iter(t->t_pshandle, (proc_lwp_f *)pt_lwp_add, ap));
4697 
4698         return (set_errno(EMDB_NOPROC));
4699 }
4700 
4701 /*ARGSUSED*/
4702 static int
4703 pt_lwp_getregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prgregset_t gregs)
4704 {
4705         if (t->t_pshandle != NULL) {
4706                 return (ptl_err(Plwp_getregs(t->t_pshandle,
4707                     (lwpid_t)tid, gregs)));
4708         }
4709         return (set_errno(EMDB_NOPROC));
4710 }
4711 
4712 /*ARGSUSED*/
4713 static int
4714 pt_lwp_setregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prgregset_t gregs)
4715 {
4716         if (t->t_pshandle != NULL) {
4717                 return (ptl_err(Plwp_setregs(t->t_pshandle,
4718                     (lwpid_t)tid, gregs)));
4719         }
4720         return (set_errno(EMDB_NOPROC));
4721 }
4722 
4723 /*ARGSUSED*/
4724 static int
4725 pt_lwp_getxregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prxregset_t *xregs)
4726 {
4727         if (t->t_pshandle != NULL) {
4728                 return (ptl_err(Plwp_getxregs(t->t_pshandle,
4729                     (lwpid_t)tid, xregs)));
4730         }
4731         return (set_errno(EMDB_NOPROC));
4732 }
4733 
4734 /*ARGSUSED*/
4735 static int
4736 pt_lwp_setxregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
4737     const prxregset_t *xregs)
4738 {
4739         if (t->t_pshandle != NULL) {
4740                 return (ptl_err(Plwp_setxregs(t->t_pshandle,
4741                     (lwpid_t)tid, xregs)));
4742         }
4743         return (set_errno(EMDB_NOPROC));
4744 }
4745 
4746 /*ARGSUSED*/
4747 static int
4748 pt_lwp_getfpregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
4749     prfpregset_t *fpregs)
4750 {
4751         if (t->t_pshandle != NULL) {
4752                 return (ptl_err(Plwp_getfpregs(t->t_pshandle,
4753                     (lwpid_t)tid, fpregs)));
4754         }
4755         return (set_errno(EMDB_NOPROC));
4756 }
4757 
4758 /*ARGSUSED*/
4759 static int
4760 pt_lwp_setfpregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
4761     const prfpregset_t *fpregs)
4762 {
4763         if (t->t_pshandle != NULL) {
4764                 return (ptl_err(Plwp_setfpregs(t->t_pshandle,
4765                     (lwpid_t)tid, fpregs)));
4766         }
4767         return (set_errno(EMDB_NOPROC));
4768 }
4769 
4770 static const pt_ptl_ops_t proc_lwp_ops = {
4771         (int (*)()) mdb_tgt_nop,
4772         (void (*)()) mdb_tgt_nop,
4773         pt_lwp_tid,
4774         pt_lwp_iter,
4775         pt_lwp_getregs,
4776         pt_lwp_setregs,
4777         pt_lwp_getxregs,
4778         pt_lwp_setxregs,
4779         pt_lwp_getfpregs,
4780         pt_lwp_setfpregs
4781 };
4782 
4783 static int
4784 pt_tdb_ctor(mdb_tgt_t *t)
4785 {
4786         pt_data_t *pt = t->t_data;
4787         td_thragent_t *tap;
4788         td_err_e err;
4789 
4790         if ((err = pt->p_tdb_ops->td_ta_new(t->t_pshandle, &tap)) != TD_OK)
4791                 return (set_errno(tdb_to_errno(err)));
4792 
4793         pt->p_ptl_hdl = tap;
4794         return (0);
4795 }
4796 
4797 static void
4798 pt_tdb_dtor(mdb_tgt_t *t, void *tap)
4799 {
4800         pt_data_t *pt = t->t_data;
4801 
4802         ASSERT(tap == pt->p_ptl_hdl);
4803         (void) pt->p_tdb_ops->td_ta_delete(tap);
4804         pt->p_ptl_hdl = NULL;
4805 }
4806 
4807 static mdb_tgt_tid_t
4808 pt_tdb_tid(mdb_tgt_t *t, void *tap)
4809 {
4810         pt_data_t *pt = t->t_data;
4811 
4812         td_thrhandle_t th;
4813         td_thrinfo_t ti;
4814         td_err_e err;
4815 
4816         if (t->t_pshandle == NULL)
4817                 return (set_errno(EMDB_NOPROC));
4818 
4819         if ((err = pt->p_tdb_ops->td_ta_map_lwp2thr(tap,
4820             Pstatus(t->t_pshandle)->pr_lwp.pr_lwpid, &th)) != TD_OK)
4821                 return (set_errno(tdb_to_errno(err)));
4822 
4823         if ((err = pt->p_tdb_ops->td_thr_get_info(&th, &ti)) != TD_OK)
4824                 return (set_errno(tdb_to_errno(err)));
4825 
4826         return (ti.ti_tid);
4827 }
4828 
4829 static int
4830 pt_tdb_add(const td_thrhandle_t *thp, pt_addarg_t *pap)
4831 {
4832         td_thrinfo_t ti;
4833 
4834         if (pap->pa_pt->p_tdb_ops->td_thr_get_info(thp, &ti) == TD_OK &&
4835             ti.ti_state != TD_THR_ZOMBIE)
4836                 mdb_addrvec_unshift(pap->pa_ap, ti.ti_tid);
4837 
4838         return (0);
4839 }
4840 
4841 static int
4842 pt_tdb_iter(mdb_tgt_t *t, void *tap, mdb_addrvec_t *ap)
4843 {
4844         pt_data_t *pt = t->t_data;
4845         pt_addarg_t arg;
4846         int err;
4847 
4848         if (t->t_pshandle == NULL)
4849                 return (set_errno(EMDB_NOPROC));
4850 
4851         arg.pa_pt = pt;
4852         arg.pa_ap = ap;
4853 
4854         if ((err = pt->p_tdb_ops->td_ta_thr_iter(tap, (td_thr_iter_f *)
4855             pt_tdb_add, &arg, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
4856             TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS)) != TD_OK)
4857                 return (set_errno(tdb_to_errno(err)));
4858 
4859         return (0);
4860 }
4861 
4862 static int
4863 pt_tdb_getregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prgregset_t gregs)
4864 {
4865         pt_data_t *pt = t->t_data;
4866 
4867         td_thrhandle_t th;
4868         td_err_e err;
4869 
4870         if (t->t_pshandle == NULL)
4871                 return (set_errno(EMDB_NOPROC));
4872 
4873         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
4874                 return (set_errno(tdb_to_errno(err)));
4875 
4876         err = pt->p_tdb_ops->td_thr_getgregs(&th, gregs);
4877         if (err != TD_OK && err != TD_PARTIALREG)
4878                 return (set_errno(tdb_to_errno(err)));
4879 
4880         return (0);
4881 }
4882 
4883 static int
4884 pt_tdb_setregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prgregset_t gregs)
4885 {
4886         pt_data_t *pt = t->t_data;
4887 
4888         td_thrhandle_t th;
4889         td_err_e err;
4890 
4891         if (t->t_pshandle == NULL)
4892                 return (set_errno(EMDB_NOPROC));
4893 
4894         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
4895                 return (set_errno(tdb_to_errno(err)));
4896 
4897         err = pt->p_tdb_ops->td_thr_setgregs(&th, gregs);
4898         if (err != TD_OK && err != TD_PARTIALREG)
4899                 return (set_errno(tdb_to_errno(err)));
4900 
4901         return (0);
4902 }
4903 
4904 #ifdef __sparc
4905 
4906 static int
4907 pt_tdb_getxregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid, prxregset_t *xregs)
4908 {
4909         pt_data_t *pt = t->t_data;
4910 
4911         td_thrhandle_t th;
4912         td_err_e err;
4913 
4914         if (t->t_pshandle == NULL)
4915                 return (set_errno(EMDB_NOPROC));
4916 
4917         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
4918                 return (set_errno(tdb_to_errno(err)));
4919 
4920         err = pt->p_tdb_ops->td_thr_getxregs(&th, xregs);
4921         if (err != TD_OK && err != TD_PARTIALREG)
4922                 return (set_errno(tdb_to_errno(err)));
4923 
4924         return (0);
4925 }
4926 
4927 static int
4928 pt_tdb_setxregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
4929     const prxregset_t *xregs)
4930 {
4931         pt_data_t *pt = t->t_data;
4932 
4933         td_thrhandle_t th;
4934         td_err_e err;
4935 
4936         if (t->t_pshandle == NULL)
4937                 return (set_errno(EMDB_NOPROC));
4938 
4939         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
4940                 return (set_errno(tdb_to_errno(err)));
4941 
4942         err = pt->p_tdb_ops->td_thr_setxregs(&th, xregs);
4943         if (err != TD_OK && err != TD_PARTIALREG)
4944                 return (set_errno(tdb_to_errno(err)));
4945 
4946         return (0);
4947 }
4948 
4949 #endif  /* __sparc */
4950 
4951 static int
4952 pt_tdb_getfpregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
4953     prfpregset_t *fpregs)
4954 {
4955         pt_data_t *pt = t->t_data;
4956 
4957         td_thrhandle_t th;
4958         td_err_e err;
4959 
4960         if (t->t_pshandle == NULL)
4961                 return (set_errno(EMDB_NOPROC));
4962 
4963         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
4964                 return (set_errno(tdb_to_errno(err)));
4965 
4966         err = pt->p_tdb_ops->td_thr_getfpregs(&th, fpregs);
4967         if (err != TD_OK && err != TD_PARTIALREG)
4968                 return (set_errno(tdb_to_errno(err)));
4969 
4970         return (0);
4971 }
4972 
4973 static int
4974 pt_tdb_setfpregs(mdb_tgt_t *t, void *tap, mdb_tgt_tid_t tid,
4975     const prfpregset_t *fpregs)
4976 {
4977         pt_data_t *pt = t->t_data;
4978 
4979         td_thrhandle_t th;
4980         td_err_e err;
4981 
4982         if (t->t_pshandle == NULL)
4983                 return (set_errno(EMDB_NOPROC));
4984 
4985         if ((err = pt->p_tdb_ops->td_ta_map_id2thr(tap, tid, &th)) != TD_OK)
4986                 return (set_errno(tdb_to_errno(err)));
4987 
4988         err = pt->p_tdb_ops->td_thr_setfpregs(&th, fpregs);
4989         if (err != TD_OK && err != TD_PARTIALREG)
4990                 return (set_errno(tdb_to_errno(err)));
4991 
4992         return (0);
4993 }
4994 
4995 static const pt_ptl_ops_t proc_tdb_ops = {
4996         pt_tdb_ctor,
4997         pt_tdb_dtor,
4998         pt_tdb_tid,
4999         pt_tdb_iter,
5000         pt_tdb_getregs,
5001         pt_tdb_setregs,
5002 #ifdef __sparc
5003         pt_tdb_getxregs,
5004         pt_tdb_setxregs,
5005 #endif
5006         pt_tdb_getfpregs,
5007         pt_tdb_setfpregs
5008 };
5009 
5010 static ssize_t
5011 pt_xd_auxv(mdb_tgt_t *t, void *buf, size_t nbytes)
5012 {
5013         struct ps_prochandle *P = t->t_pshandle;
5014         const auxv_t *auxp, *auxv = NULL;
5015         int auxn = 0;
5016 
5017         if (P != NULL && (auxv = Pgetauxvec(P)) != NULL &&
5018             auxv->a_type != AT_NULL) {
5019                 for (auxp = auxv, auxn = 1; auxp->a_type != NULL; auxp++)
5020                         auxn++;
5021         }
5022 
5023         if (buf == NULL && nbytes == 0)
5024                 return (sizeof (auxv_t) * auxn);
5025 
5026         if (auxn == 0)
5027                 return (set_errno(ENODATA));
5028 
5029         nbytes = MIN(nbytes, sizeof (auxv_t) * auxn);
5030         bcopy(auxv, buf, nbytes);
5031         return (nbytes);
5032 }
5033 
5034 static ssize_t
5035 pt_xd_cred(mdb_tgt_t *t, void *buf, size_t nbytes)
5036 {
5037         prcred_t cr, *crp;
5038         size_t cbytes = 0;
5039 
5040         if (t->t_pshandle != NULL && Pcred(t->t_pshandle, &cr, 1) == 0) {
5041                 cbytes = (cr.pr_ngroups <= 1) ? sizeof (prcred_t) :
5042                     (sizeof (prcred_t) + (cr.pr_ngroups - 1) * sizeof (gid_t));
5043         }
5044 
5045         if (buf == NULL && nbytes == 0)
5046                 return (cbytes);
5047 
5048         if (cbytes == 0)
5049                 return (set_errno(ENODATA));
5050 
5051         crp = mdb_alloc(cbytes, UM_SLEEP);
5052 
5053         if (Pcred(t->t_pshandle, crp, cr.pr_ngroups) == -1)
5054                 return (set_errno(ENODATA));
5055 
5056         nbytes = MIN(nbytes, cbytes);
5057         bcopy(crp, buf, nbytes);
5058         mdb_free(crp, cbytes);
5059         return (nbytes);
5060 }
5061 
5062 static ssize_t
5063 pt_xd_ehdr(mdb_tgt_t *t, void *buf, size_t nbytes)
5064 {
5065         pt_data_t *pt = t->t_data;
5066 
5067         if (buf == NULL && nbytes == 0)
5068                 return (sizeof (GElf_Ehdr));
5069 
5070         if (pt->p_file == NULL)
5071                 return (set_errno(ENODATA));
5072 
5073         nbytes = MIN(nbytes, sizeof (GElf_Ehdr));
5074         bcopy(&pt->p_file->gf_ehdr, buf, nbytes);
5075         return (nbytes);
5076 }
5077 
5078 static int
5079 pt_copy_lwp(lwpstatus_t **lspp, const lwpstatus_t *lsp)
5080 {
5081         bcopy(lsp, *lspp, sizeof (lwpstatus_t));
5082         (*lspp)++;
5083         return (0);
5084 }
5085 
5086 static ssize_t
5087 pt_xd_lwpstatus(mdb_tgt_t *t, void *buf, size_t nbytes)
5088 {
5089         lwpstatus_t *lsp, *lbuf;
5090         const pstatus_t *psp;
5091         int nlwp = 0;
5092 
5093         if (t->t_pshandle != NULL && (psp = Pstatus(t->t_pshandle)) != NULL)
5094                 nlwp = psp->pr_nlwp;
5095 
5096         if (buf == NULL && nbytes == 0)
5097                 return (sizeof (lwpstatus_t) * nlwp);
5098 
5099         if (nlwp == 0)
5100                 return (set_errno(ENODATA));
5101 
5102         lsp = lbuf = mdb_alloc(sizeof (lwpstatus_t) * nlwp, UM_SLEEP);
5103         nbytes = MIN(nbytes, sizeof (lwpstatus_t) * nlwp);
5104 
5105         (void) Plwp_iter(t->t_pshandle, (proc_lwp_f *)pt_copy_lwp, &lsp);
5106         bcopy(lbuf, buf, nbytes);
5107 
5108         mdb_free(lbuf, sizeof (lwpstatus_t) * nlwp);
5109         return (nbytes);
5110 }
5111 
5112 static ssize_t
5113 pt_xd_pshandle(mdb_tgt_t *t, void *buf, size_t nbytes)
5114 {
5115         if (buf == NULL && nbytes == 0)
5116                 return (sizeof (struct ps_prochandle *));
5117 
5118         if (t->t_pshandle == NULL || nbytes != sizeof (struct ps_prochandle *))
5119                 return (set_errno(ENODATA));
5120 
5121         bcopy(&t->t_pshandle, buf, nbytes);
5122         return (nbytes);
5123 }
5124 
5125 static ssize_t
5126 pt_xd_psinfo(mdb_tgt_t *t, void *buf, size_t nbytes)
5127 {
5128         const psinfo_t *psp;
5129 
5130         if (buf == NULL && nbytes == 0)
5131                 return (sizeof (psinfo_t));
5132 
5133         if (t->t_pshandle == NULL || (psp = Ppsinfo(t->t_pshandle)) == NULL)
5134                 return (set_errno(ENODATA));
5135 
5136         nbytes = MIN(nbytes, sizeof (psinfo_t));
5137         bcopy(psp, buf, nbytes);
5138         return (nbytes);
5139 }
5140 
5141 static ssize_t
5142 pt_xd_pstatus(mdb_tgt_t *t, void *buf, size_t nbytes)
5143 {
5144         const pstatus_t *psp;
5145 
5146         if (buf == NULL && nbytes == 0)
5147                 return (sizeof (pstatus_t));
5148 
5149         if (t->t_pshandle == NULL || (psp = Pstatus(t->t_pshandle)) == NULL)
5150                 return (set_errno(ENODATA));
5151 
5152         nbytes = MIN(nbytes, sizeof (pstatus_t));
5153         bcopy(psp, buf, nbytes);
5154         return (nbytes);
5155 }
5156 
5157 static ssize_t
5158 pt_xd_utsname(mdb_tgt_t *t, void *buf, size_t nbytes)
5159 {
5160         struct utsname uts;
5161 
5162         if (buf == NULL && nbytes == 0)
5163                 return (sizeof (struct utsname));
5164 
5165         if (t->t_pshandle == NULL || Puname(t->t_pshandle, &uts) != 0)
5166                 return (set_errno(ENODATA));
5167 
5168         nbytes = MIN(nbytes, sizeof (struct utsname));
5169         bcopy(&uts, buf, nbytes);
5170         return (nbytes);
5171 }
5172 
5173 int
5174 mdb_proc_tgt_create(mdb_tgt_t *t, int argc, const char *argv[])
5175 {
5176         pt_data_t *pt = mdb_zalloc(sizeof (pt_data_t), UM_SLEEP);
5177 
5178         const char *aout_path = argc > 0 ? argv[0] : PT_EXEC_PATH;
5179         const char *core_path = argc > 1 ? argv[1] : NULL;
5180 
5181         const mdb_tgt_regdesc_t *rdp;
5182         char execname[MAXPATHLEN];
5183         struct stat64 st;
5184         int perr;
5185         int state;
5186         struct rlimit rlim;
5187         int i;
5188 
5189         if (argc > 2) {
5190                 mdb_free(pt, sizeof (pt_data_t));
5191                 return (set_errno(EINVAL));
5192         }
5193 
5194         if (t->t_flags & MDB_TGT_F_RDWR)
5195                 pt->p_oflags = O_RDWR;
5196         else
5197                 pt->p_oflags = O_RDONLY;
5198 
5199         if (t->t_flags & MDB_TGT_F_FORCE)
5200                 pt->p_gflags |= PGRAB_FORCE;
5201         if (t->t_flags & MDB_TGT_F_NOSTOP)
5202                 pt->p_gflags |= PGRAB_NOSTOP;
5203 
5204         pt->p_ptl_ops = &proc_lwp_ops;
5205         pt->p_maxsig = sysconf(_SC_SIGRT_MAX);
5206 
5207         (void) mdb_nv_create(&pt->p_regs, UM_SLEEP);
5208         (void) mdb_nv_create(&pt->p_env, UM_SLEEP);
5209 
5210         t->t_ops = &proc_ops;
5211         t->t_data = pt;
5212 
5213         /*
5214          * If no core file name was specified, but the file ./core is present,
5215          * infer that we want to debug it.  I find this behavior confusing,
5216          * so we only do this when precise adb(1) compatibility is required.
5217          */
5218         if (core_path == NULL && (mdb.m_flags & MDB_FL_ADB) &&
5219             access(PT_CORE_PATH, F_OK) == 0)
5220                 core_path = PT_CORE_PATH;
5221 
5222         /*
5223          * For compatibility with adb(1), the special name "-" may be used
5224          * to suppress the loading of the executable or core file.
5225          */
5226         if (aout_path != NULL && strcmp(aout_path, "-") == 0)
5227                 aout_path = NULL;
5228         if (core_path != NULL && strcmp(core_path, "-") == 0)
5229                 core_path = NULL;
5230 
5231         /*
5232          * If a core file or pid was specified, attempt to grab it now using
5233          * proc_arg_grab(); otherwise we'll create a fresh process later.
5234          */
5235         if (core_path != NULL && (t->t_pshandle = proc_arg_xgrab(core_path,
5236             aout_path == PT_EXEC_PATH ? NULL : aout_path, PR_ARG_ANY,
5237             pt->p_gflags, &perr, NULL)) == NULL) {
5238                 mdb_warn("cannot debug %s: %s\n", core_path, Pgrab_error(perr));
5239                 goto err;
5240         }
5241 
5242         if (aout_path != NULL &&
5243             (pt->p_idlehandle = Pgrab_file(aout_path, &perr)) != NULL &&
5244             t->t_pshandle == NULL)
5245                 t->t_pshandle = pt->p_idlehandle;
5246 
5247         if (t->t_pshandle != NULL)
5248                 state = Pstate(t->t_pshandle);
5249 
5250         /*
5251          * Make sure we'll have enough file descriptors to handle a target
5252          * has many many mappings.
5253          */
5254         if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
5255                 rlim.rlim_cur = rlim.rlim_max;
5256                 (void) setrlimit(RLIMIT_NOFILE, &rlim);
5257                 (void) enable_extended_FILE_stdio(-1, -1);
5258         }
5259 
5260         /*
5261          * If we don't have an executable path or the executable path is the
5262          * /proc/<pid>/object/a.out path, but we now have a libproc handle,
5263          * attempt to derive the executable path using Pexecname().  We need
5264          * to do this in the /proc case in order to open the executable for
5265          * writing because /proc/object/<file> permission are masked with 0555.
5266          * If Pexecname() fails us, fall back to /proc/<pid>/object/a.out.
5267          */
5268         if (t->t_pshandle != NULL && (aout_path == NULL || (stat64(aout_path,
5269             &st) == 0 && strcmp(st.st_fstype, "proc") == 0))) {
5270                 GElf_Sym s;
5271                 aout_path = Pexecname(t->t_pshandle, execname, MAXPATHLEN);
5272                 if (aout_path == NULL && state != PS_DEAD && state != PS_IDLE) {
5273                         (void) mdb_iob_snprintf(execname, sizeof (execname),
5274                             "/proc/%d/object/a.out",
5275                             (int)Pstatus(t->t_pshandle)->pr_pid);
5276                         aout_path = execname;
5277                 }
5278                 if (aout_path == NULL &&
5279                     Plookup_by_name(t->t_pshandle, "a.out", "_start", &s) != 0)
5280                         mdb_warn("warning: failed to infer pathname to "
5281                             "executable; symbol table will not be available\n");
5282 
5283                 mdb_dprintf(MDB_DBG_TGT, "a.out is %s\n", aout_path);
5284         }
5285 
5286         /*
5287          * Attempt to open the executable file.  We only want this operation
5288          * to actually cause the constructor to abort if the executable file
5289          * name was given explicitly.  If we defaulted to PT_EXEC_PATH or
5290          * derived the executable using Pexecname, then we want to continue
5291          * along with p_fio and p_file set to NULL.
5292          */
5293         if (aout_path != NULL && (pt->p_aout_fio = mdb_fdio_create_path(NULL,
5294             aout_path, pt->p_oflags, 0)) == NULL && argc > 0) {
5295                 mdb_warn("failed to open %s", aout_path);
5296                 goto err;
5297         }
5298 
5299         /*
5300          * Now create an ELF file from the input file, if we have one.  Again,
5301          * only abort the constructor if the name was given explicitly.
5302          */
5303         if (pt->p_aout_fio != NULL && pt_open_aout(t,
5304             mdb_io_hold(pt->p_aout_fio)) == NULL && argc > 0)
5305                 goto err;
5306 
5307         /*
5308          * If we've successfully opened an ELF file, select the appropriate
5309          * disassembler based on the ELF header.
5310          */
5311         if (pt->p_file != NULL)
5312                 (void) mdb_dis_select(pt_disasm(&pt->p_file->gf_ehdr));
5313         else
5314                 (void) mdb_dis_select(pt_disasm(NULL));
5315 
5316         /*
5317          * Add each register described in the target ISA register description
5318          * list to our hash table of register descriptions and then add any
5319          * appropriate ISA-specific floating-point register descriptions.
5320          */
5321         for (rdp = pt_regdesc; rdp->rd_name != NULL; rdp++) {
5322                 (void) mdb_nv_insert(&pt->p_regs, rdp->rd_name, NULL,
5323                     MDB_TGT_R_NVAL(rdp->rd_num, rdp->rd_flags), MDB_NV_RDONLY);
5324         }
5325         pt_addfpregs(t);
5326 
5327         /*
5328          * Certain important /proc structures may be of interest to mdb
5329          * modules and their dcmds.  Export these using the xdata interface:
5330          */
5331         (void) mdb_tgt_xdata_insert(t, "auxv",
5332             "procfs auxv_t array", pt_xd_auxv);
5333         (void) mdb_tgt_xdata_insert(t, "cred",
5334             "procfs prcred_t structure", pt_xd_cred);
5335         (void) mdb_tgt_xdata_insert(t, "ehdr",
5336             "executable file GElf_Ehdr structure", pt_xd_ehdr);
5337         (void) mdb_tgt_xdata_insert(t, "lwpstatus",
5338             "procfs lwpstatus_t array", pt_xd_lwpstatus);
5339         (void) mdb_tgt_xdata_insert(t, "pshandle",
5340             "libproc proc service API handle", pt_xd_pshandle);
5341         (void) mdb_tgt_xdata_insert(t, "psinfo",
5342             "procfs psinfo_t structure", pt_xd_psinfo);
5343         (void) mdb_tgt_xdata_insert(t, "pstatus",
5344             "procfs pstatus_t structure", pt_xd_pstatus);
5345         (void) mdb_tgt_xdata_insert(t, "utsname",
5346             "utsname structure", pt_xd_utsname);
5347 
5348         /*
5349          * Force a status update now so that we fill in t_status with the
5350          * latest information based on any successful grab.
5351          */
5352         (void) mdb_tgt_status(t, &t->t_status);
5353 
5354         /*
5355          * If we're not examining a core file, trace SIGINT and all signals
5356          * that cause the process to dump core as part of our initialization.
5357          */
5358         if ((t->t_pshandle != NULL && state != PS_DEAD && state != PS_IDLE) ||
5359             (pt->p_file != NULL && pt->p_file->gf_ehdr.e_type == ET_EXEC)) {
5360 
5361                 int tflag = MDB_TGT_SPEC_STICKY; /* default sigs are sticky */
5362 
5363                 (void) mdb_tgt_add_signal(t, SIGINT, tflag, no_se_f, NULL);
5364                 (void) mdb_tgt_add_signal(t, SIGQUIT, tflag, no_se_f, NULL);
5365                 (void) mdb_tgt_add_signal(t, SIGILL, tflag, no_se_f, NULL);
5366                 (void) mdb_tgt_add_signal(t, SIGTRAP, tflag, no_se_f, NULL);
5367                 (void) mdb_tgt_add_signal(t, SIGABRT, tflag, no_se_f, NULL);
5368                 (void) mdb_tgt_add_signal(t, SIGEMT, tflag, no_se_f, NULL);
5369                 (void) mdb_tgt_add_signal(t, SIGFPE, tflag, no_se_f, NULL);
5370                 (void) mdb_tgt_add_signal(t, SIGBUS, tflag, no_se_f, NULL);
5371                 (void) mdb_tgt_add_signal(t, SIGSEGV, tflag, no_se_f, NULL);
5372                 (void) mdb_tgt_add_signal(t, SIGSYS, tflag, no_se_f, NULL);
5373                 (void) mdb_tgt_add_signal(t, SIGXCPU, tflag, no_se_f, NULL);
5374                 (void) mdb_tgt_add_signal(t, SIGXFSZ, tflag, no_se_f, NULL);
5375         }
5376 
5377         /*
5378          * If we've grabbed a live process, establish our initial breakpoints
5379          * and librtld_db agent so we can track rtld activity.  If FL_VCREATE
5380          * is set, this process was created by a previous instantiation of
5381          * the debugger, so reset pr_flags to kill it; otherwise we attached
5382          * to an already running process.  Pgrab() has already set the PR_RLC
5383          * flag appropriately based on whether the process was stopped when we
5384          * attached.
5385          */
5386         if (t->t_pshandle != NULL && state != PS_DEAD && state != PS_IDLE) {
5387                 if (mdb.m_flags & MDB_FL_VCREATE) {
5388                         (void) Punsetflags(t->t_pshandle, PR_RLC);
5389                         (void) Psetflags(t->t_pshandle, PR_KLC);
5390                         pt->p_rflags = PRELEASE_KILL;
5391                 } else {
5392                         (void) Punsetflags(t->t_pshandle, PR_KLC);
5393                 }
5394                 pt_post_attach(t);
5395         }
5396 
5397         /*
5398          * Initialize a local copy of the environment, which can be modified
5399          * before running the program.
5400          */
5401         for (i = 0; mdb.m_env[i] != NULL; i++)
5402                 pt_env_set(pt, mdb.m_env[i]);
5403 
5404         /*
5405          * If adb(1) compatibility mode is on, then print the appropriate
5406          * greeting message if we have grabbed a core file.
5407          */
5408         if ((mdb.m_flags & MDB_FL_ADB) && t->t_pshandle != NULL &&
5409             state == PS_DEAD) {
5410                 const pstatus_t *psp = Pstatus(t->t_pshandle);
5411                 int cursig = psp->pr_lwp.pr_cursig;
5412                 char signame[SIG2STR_MAX];
5413 
5414                 mdb_printf("core file = %s -- program ``%s'' on platform %s\n",
5415                     core_path, aout_path ? aout_path : "?", pt_platform(t));
5416 
5417                 if (cursig != 0 && sig2str(cursig, signame) == 0)
5418                         mdb_printf("SIG%s: %s\n", signame, strsignal(cursig));
5419         }
5420 
5421         return (0);
5422 
5423 err:
5424         pt_destroy(t);
5425         return (-1);
5426 }