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