1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1914 casper * Common Development and Distribution License (the "License"). 6 1914 casper * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 11053 Surya * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel /* 27 0 stevel * User Process Target 28 0 stevel * 29 0 stevel * The user process target is invoked when the -u or -p command-line options 30 0 stevel * are used, or when an ELF executable file or ELF core file is specified on 31 0 stevel * the command-line. This target is also selected by default when no target 32 0 stevel * options are present. In this case, it defaults the executable name to 33 0 stevel * "a.out". If no process or core file is currently attached, the target 34 0 stevel * functions as a kind of virtual /dev/zero (in accordance with adb(1) 35 0 stevel * semantics); reads from the virtual address space return zeroes and writes 36 0 stevel * fail silently. The proc target itself is designed as a wrapper around the 37 0 stevel * services provided by libproc.so: t->t_pshandle is set to the struct 38 0 stevel * ps_prochandle pointer returned as a handle by libproc. The target also 39 0 stevel * opens the executable file itself using the MDB GElf services, for 40 0 stevel * interpreting the .symtab and .dynsym if no libproc handle has been 41 0 stevel * initialized, and for handling i/o to and from the object file. Currently, 42 0 stevel * the only ISA-dependent portions of the proc target are the $r and ::fpregs 43 0 stevel * dcmds, the callbacks for t_next() and t_step_out(), and the list of named 44 0 stevel * registers; these are linked in from the proc_isadep.c file for each ISA and 45 0 stevel * called from the common code in this file. 46 0 stevel * 47 0 stevel * The user process target implements complete user process control using the 48 0 stevel * facilities provided by libproc.so. The MDB execution control model and 49 0 stevel * an overview of software event management is described in mdb_target.c. The 50 0 stevel * proc target implements breakpoints by replacing the instruction of interest 51 0 stevel * with a trap instruction, and then restoring the original instruction to step 52 0 stevel * over the breakpoint. The idea of replacing program text with instructions 53 0 stevel * that transfer control to the debugger dates back as far as 1951 [1]. When 54 0 stevel * the target stops, we replace each breakpoint with the original instruction 55 0 stevel * as part of the disarm operation. This means that no special processing is 56 0 stevel * required for t_vread() because the instrumented instructions will never be 57 0 stevel * seen by the debugger once the target stops. Some debuggers have improved 58 0 stevel * start/stop performance by leaving breakpoint traps in place and then 59 0 stevel * handling a read from a breakpoint address as a special case. Although this 60 0 stevel * improves efficiency for a source-level debugger, it runs somewhat contrary 61 0 stevel * to the philosophy of the low-level debugger. Since we remove the 62 0 stevel * instructions, users can apply other external debugging tools to the process 63 0 stevel * once it has stopped (e.g. the proc(1) tools) and not be misled by MDB 64 0 stevel * instrumentation. The tracing of faults, signals, system calls, and 65 0 stevel * watchpoints and general process inspection is implemented directly using 66 0 stevel * the mechanisms provided by /proc, as described originally in [2] and [3]. 67 0 stevel * 68 0 stevel * References 69 0 stevel * 70 0 stevel * [1] S. Gill, "The Diagnosis Of Mistakes In Programmes on the EDSAC", 71 0 stevel * Proceedings of the Royal Society Series A Mathematical and Physical 72 0 stevel * Sciences, Cambridge University Press, 206(1087), May 1951, pp. 538-554. 73 0 stevel * 74 0 stevel * [2] T.J. Killian, "Processes as Files", Proceedings of the USENIX Association 75 0 stevel * Summer Conference, Salt Lake City, June 1984, pp. 203-207. 76 0 stevel * 77 0 stevel * [3] Roger Faulkner and Ron Gomes, "The Process File System and Process 78 0 stevel * Model in UNIX System V", Proceedings of the USENIX Association 79 0 stevel * Winter Conference, Dallas, January 1991, pp. 243-252. 80 0 stevel */ 81 0 stevel 82 0 stevel #include <mdb/mdb_proc.h> 83 0 stevel #include <mdb/mdb_disasm.h> 84 0 stevel #include <mdb/mdb_signal.h> 85 0 stevel #include <mdb/mdb_string.h> 86 0 stevel #include <mdb/mdb_module.h> 87 0 stevel #include <mdb/mdb_debug.h> 88 0 stevel #include <mdb/mdb_conf.h> 89 0 stevel #include <mdb/mdb_err.h> 90 0 stevel #include <mdb/mdb_types.h> 91 0 stevel #include <mdb/mdb.h> 92 0 stevel 93 0 stevel #include <sys/utsname.h> 94 0 stevel #include <sys/wait.h> 95 0 stevel #include <sys/stat.h> 96 0 stevel #include <termio.h> 97 0 stevel #include <signal.h> 98 1914 casper #include <stdio_ext.h> 99 0 stevel #include <stdlib.h> 100 0 stevel #include <string.h> 101 0 stevel 102 0 stevel #define PC_FAKE -1UL /* illegal pc value unequal 0 */ 103 0 stevel 104 0 stevel static const char PT_EXEC_PATH[] = "a.out"; /* Default executable */ 105 0 stevel static const char PT_CORE_PATH[] = "core"; /* Default core file */ 106 0 stevel 107 0 stevel static const pt_ptl_ops_t proc_lwp_ops; 108 0 stevel static const pt_ptl_ops_t proc_tdb_ops; 109 0 stevel static const mdb_se_ops_t proc_brkpt_ops; 110 0 stevel static const mdb_se_ops_t proc_wapt_ops; 111 0 stevel 112 0 stevel static int pt_setrun(mdb_tgt_t *, mdb_tgt_status_t *, int); 113 0 stevel static void pt_activate_common(mdb_tgt_t *); 114 0 stevel static mdb_tgt_vespec_f pt_ignore_sig; 115 0 stevel static mdb_tgt_se_f pt_fork; 116 0 stevel static mdb_tgt_se_f pt_exec; 117 0 stevel 118 0 stevel static int pt_lookup_by_name_thr(mdb_tgt_t *, const char *, 119 0 stevel const char *, GElf_Sym *, mdb_syminfo_t *, mdb_tgt_tid_t); 120 0 stevel static int tlsbase(mdb_tgt_t *, mdb_tgt_tid_t, Lmid_t, const char *, 121 0 stevel psaddr_t *); 122 0 stevel 123 0 stevel /* 124 0 stevel * The Perror_printf() function interposes on the default, empty libproc 125 0 stevel * definition. It will be called to report additional information on complex 126 0 stevel * errors, such as a corrupt core file. We just pass the args to vwarn. 127 0 stevel */ 128 0 stevel /*ARGSUSED*/ 129 0 stevel void 130 0 stevel Perror_printf(struct ps_prochandle *P, const char *format, ...) 131 0 stevel { 132 0 stevel va_list alist; 133 0 stevel 134 0 stevel va_start(alist, format); 135 0 stevel vwarn(format, alist); 136 0 stevel va_end(alist); 137 0 stevel } 138 0 stevel 139 0 stevel /* 140 0 stevel * Open the specified i/o backend as the a.out executable file, and attempt to 141 0 stevel * load its standard and dynamic symbol tables. Note that if mdb_gelf_create 142 0 stevel * succeeds, io is assigned to p_fio and is automatically held by gelf_create. 143 0 stevel */ 144 0 stevel static mdb_gelf_file_t * 145 0 stevel pt_open_aout(mdb_tgt_t *t, mdb_io_t *io) 146 0 stevel { 147 0 stevel pt_data_t *pt = t->t_data; 148 0 stevel GElf_Sym s1, s2; 149 0 stevel 150 0 stevel if ((pt->p_file = mdb_gelf_create(io, ET_NONE, GF_FILE)) == NULL) 151 0 stevel return (NULL); 152 0 stevel 153 0 stevel pt->p_symtab = mdb_gelf_symtab_create_file(pt->p_file, 154 0 stevel SHT_SYMTAB, MDB_TGT_SYMTAB); 155 0 stevel pt->p_dynsym = mdb_gelf_symtab_create_file(pt->p_file, 156 0 stevel SHT_DYNSYM, MDB_TGT_DYNSYM); 157 0 stevel 158 0 stevel /* 159 0 stevel * If we've got an _start symbol with a zero size, prime the private 160 0 stevel * symbol table with a copy of _start with its size set to the distance 161 0 stevel * between _mcount and _start. We do this because DevPro has shipped 162 0 stevel * the Intel crt1.o without proper .size directives for years, which 163 0 stevel * precludes proper identification of _start in stack traces. 164 0 stevel */ 165 0 stevel if (mdb_gelf_symtab_lookup_by_name(pt->p_dynsym, "_start", &s1, 166 0 stevel NULL) == 0 && s1.st_size == 0 && 167 0 stevel GELF_ST_TYPE(s1.st_info) == STT_FUNC) { 168 0 stevel if (mdb_gelf_symtab_lookup_by_name(pt->p_dynsym, "_mcount", 169 0 stevel &s2, NULL) == 0 && GELF_ST_TYPE(s2.st_info) == STT_FUNC) { 170 0 stevel s1.st_size = s2.st_value - s1.st_value; 171 0 stevel mdb_gelf_symtab_insert(mdb.m_prsym, "_start", &s1); 172 0 stevel } 173 0 stevel } 174 0 stevel 175 0 stevel pt->p_fio = io; 176 0 stevel return (pt->p_file); 177 0 stevel } 178 0 stevel 179 0 stevel /* 180 0 stevel * Destroy the symbol tables and GElf file object associated with p_fio. Note 181 0 stevel * that we do not need to explicitly free p_fio: its reference count is 182 0 stevel * automatically decremented by mdb_gelf_destroy, which will free it if needed. 183 0 stevel */ 184 0 stevel static void 185 0 stevel pt_close_aout(mdb_tgt_t *t) 186 0 stevel { 187 0 stevel pt_data_t *pt = t->t_data; 188 0 stevel 189 0 stevel if (pt->p_symtab != NULL) { 190 0 stevel mdb_gelf_symtab_destroy(pt->p_symtab); 191 0 stevel pt->p_symtab = NULL; 192 0 stevel } 193 0 stevel 194 0 stevel if (pt->p_dynsym != NULL) { 195 0 stevel mdb_gelf_symtab_destroy(pt->p_dynsym); 196 0 stevel pt->p_dynsym = NULL; 197 0 stevel } 198 0 stevel 199 0 stevel if (pt->p_file != NULL) { 200 0 stevel mdb_gelf_destroy(pt->p_file); 201 0 stevel pt->p_file = NULL; 202 0 stevel } 203 0 stevel 204 0 stevel mdb_gelf_symtab_delete(mdb.m_prsym, "_start", NULL); 205 0 stevel pt->p_fio = NULL; 206 0 stevel } 207 0 stevel 208 7928 Edward typedef struct tdb_mapping { 209 7928 Edward const char *tm_thr_lib; 210 7928 Edward const char *tm_db_dir; 211 7928 Edward const char *tm_db_name; 212 7928 Edward } tdb_mapping_t; 213 7928 Edward 214 7928 Edward static const tdb_mapping_t tdb_map[] = { 215 7928 Edward { "/lwp/amd64/libthread.so", "/usr/lib/lwp/", "libthread_db.so" }, 216 7928 Edward { "/lwp/sparcv9/libthread.so", "/usr/lib/lwp/", "libthread_db.so" }, 217 7928 Edward { "/lwp/libthread.so", "/usr/lib/lwp/", "libthread_db.so" }, 218 7928 Edward { "/libthread.so", "/lib/", "libthread_db.so" }, 219 7928 Edward { "/libc_hwcap", "/lib/", "libc_db.so" }, 220 7928 Edward { "/libc.so", "/lib/", "libc_db.so" } 221 7928 Edward }; 222 7928 Edward 223 0 stevel /* 224 0 stevel * Pobject_iter callback that we use to search for the presence of libthread in 225 0 stevel * order to load the corresponding libthread_db support. We derive the 226 0 stevel * libthread_db path dynamically based on the libthread path. If libthread is 227 0 stevel * found, this function returns 1 (and thus Pobject_iter aborts and returns 1) 228 0 stevel * regardless of whether it was successful in loading the libthread_db support. 229 0 stevel * If we iterate over all objects and no libthread is found, 0 is returned. 230 0 stevel * Since libthread_db support was then merged into libc_db, we load either 231 0 stevel * libc_db or libthread_db, depending on which library we see first. 232 0 stevel */ 233 0 stevel /*ARGSUSED*/ 234 0 stevel static int 235 0 stevel thr_check(mdb_tgt_t *t, const prmap_t *pmp, const char *name) 236 0 stevel { 237 0 stevel pt_data_t *pt = t->t_data; 238 0 stevel const mdb_tdb_ops_t *ops; 239 7928 Edward char *p; 240 7928 Edward 241 7928 Edward char path[MAXPATHLEN]; 242 7928 Edward 243 0 stevel int libn; 244 0 stevel 245 0 stevel if (name == NULL) 246 0 stevel return (0); /* no rtld_db object name; keep going */ 247 0 stevel 248 7928 Edward for (libn = 0; libn < sizeof (tdb_map) / sizeof (tdb_map[0]); libn++) { 249 7928 Edward if ((p = strstr(name, tdb_map[libn].tm_thr_lib)) != NULL) 250 0 stevel break; 251 0 stevel } 252 0 stevel 253 0 stevel if (p == NULL) 254 0 stevel return (0); /* no match; keep going */ 255 0 stevel 256 7928 Edward path[0] = '\0'; 257 7928 Edward (void) strlcat(path, mdb.m_root, sizeof (path)); 258 7928 Edward (void) strlcat(path, tdb_map[libn].tm_db_dir, sizeof (path)); 259 7928 Edward #if !defined(_ILP32) 260 7928 Edward (void) strlcat(path, "64/", sizeof (path)); 261 7928 Edward #endif /* !_ILP32 */ 262 7928 Edward (void) strlcat(path, tdb_map[libn].tm_db_name, sizeof (path)); 263 7928 Edward 264 7928 Edward /* Append the trailing library version number. */ 265 7928 Edward (void) strlcat(path, strrchr(name, '.'), sizeof (path)); 266 0 stevel 267 0 stevel if ((ops = mdb_tdb_load(path)) == NULL) { 268 0 stevel if (libn != 0 || errno != ENOENT) 269 0 stevel warn("failed to load %s", path); 270 0 stevel goto err; 271 0 stevel } 272 0 stevel 273 0 stevel if (ops == pt->p_tdb_ops) 274 0 stevel return (1); /* no changes needed */ 275 0 stevel 276 0 stevel PTL_DTOR(t); 277 0 stevel pt->p_tdb_ops = ops; 278 0 stevel pt->p_ptl_ops = &proc_tdb_ops; 279 0 stevel pt->p_ptl_hdl = NULL; 280 0 stevel 281 0 stevel if (PTL_CTOR(t) == -1) { 282 0 stevel warn("failed to initialize %s", path); 283 0 stevel goto err; 284 0 stevel } 285 0 stevel 286 0 stevel mdb_dprintf(MDB_DBG_TGT, "loaded %s for debugging %s\n", path, name); 287 0 stevel (void) mdb_tgt_status(t, &t->t_status); 288 0 stevel return (1); 289 0 stevel err: 290 0 stevel PTL_DTOR(t); 291 0 stevel pt->p_tdb_ops = NULL; 292 0 stevel pt->p_ptl_ops = &proc_lwp_ops; 293 0 stevel pt->p_ptl_hdl = NULL; 294 0 stevel 295 0 stevel if (libn != 0 || errno != ENOENT) { 296 0 stevel warn("warning: debugger will only be able to " 297 0 stevel "examine raw LWPs\n"); 298 0 stevel } 299 0 stevel 300 0 stevel (void) mdb_tgt_status(t, &t->t_status); 301 0 stevel return (1); 302 0 stevel } 303 0 stevel 304 0 stevel /* 305 0 stevel * Whenever the link map is consistent following an add or delete event, we ask 306 0 stevel * libproc to update its mappings, check to see if we need to load libthread_db, 307 0 stevel * and then update breakpoints which have been mapped or unmapped. 308 0 stevel */ 309 0 stevel /*ARGSUSED*/ 310 0 stevel static void 311 0 stevel pt_rtld_event(mdb_tgt_t *t, int vid, void *private) 312 0 stevel { 313 0 stevel struct ps_prochandle *P = t->t_pshandle; 314 0 stevel pt_data_t *pt = t->t_data; 315 0 stevel rd_event_msg_t rdm; 316 7928 Edward int docontinue = 1; 317 0 stevel 318 0 stevel if (rd_event_getmsg(pt->p_rtld, &rdm) == RD_OK) { 319 0 stevel 320 0 stevel mdb_dprintf(MDB_DBG_TGT, "rtld event type 0x%x state 0x%x\n", 321 0 stevel rdm.type, rdm.u.state); 322 0 stevel 323 0 stevel if (rdm.type == RD_DLACTIVITY && rdm.u.state == RD_CONSISTENT) { 324 0 stevel mdb_sespec_t *sep, *nsep = mdb_list_next(&t->t_active); 325 0 stevel pt_brkpt_t *ptb; 326 0 stevel 327 0 stevel Pupdate_maps(P); 328 0 stevel 329 7928 Edward if (Pobject_iter(P, (proc_map_f *)thr_check, t) == 0 && 330 7928 Edward pt->p_ptl_ops != &proc_lwp_ops) { 331 0 stevel mdb_dprintf(MDB_DBG_TGT, "unloading thread_db " 332 0 stevel "support after dlclose\n"); 333 0 stevel PTL_DTOR(t); 334 0 stevel pt->p_tdb_ops = NULL; 335 0 stevel pt->p_ptl_ops = &proc_lwp_ops; 336 0 stevel pt->p_ptl_hdl = NULL; 337 0 stevel (void) mdb_tgt_status(t, &t->t_status); 338 0 stevel } 339 0 stevel 340 0 stevel for (sep = nsep; sep != NULL; sep = nsep) { 341 0 stevel nsep = mdb_list_next(sep); 342 0 stevel ptb = sep->se_data; 343 0 stevel 344 0 stevel if (sep->se_ops == &proc_brkpt_ops && 345 0 stevel Paddr_to_map(P, ptb->ptb_addr) == NULL) 346 0 stevel mdb_tgt_sespec_idle_one(t, sep, 347 0 stevel EMDB_NOMAP); 348 0 stevel } 349 0 stevel 350 0 stevel if (!mdb_tgt_sespec_activate_all(t) && 351 0 stevel (mdb.m_flags & MDB_FL_BPTNOSYMSTOP) && 352 0 stevel pt->p_rtld_finished) { 353 0 stevel /* 354 0 stevel * We weren't able to activate the breakpoints. 355 0 stevel * If so requested, we'll return without 356 0 stevel * calling continue, thus throwing the user into 357 0 stevel * the debugger. 358 0 stevel */ 359 0 stevel docontinue = 0; 360 0 stevel } 361 0 stevel 362 0 stevel if (pt->p_rdstate == PT_RD_ADD) 363 0 stevel pt->p_rdstate = PT_RD_CONSIST; 364 0 stevel } 365 0 stevel 366 0 stevel if (rdm.type == RD_PREINIT) 367 0 stevel (void) mdb_tgt_sespec_activate_all(t); 368 0 stevel 369 0 stevel if (rdm.type == RD_POSTINIT) { 370 0 stevel pt->p_rtld_finished = TRUE; 371 0 stevel if (!mdb_tgt_sespec_activate_all(t) && 372 0 stevel (mdb.m_flags & MDB_FL_BPTNOSYMSTOP)) { 373 0 stevel /* 374 0 stevel * Now that rtld has been initialized, we 375 0 stevel * should be able to initialize all deferred 376 0 stevel * breakpoints. If we can't, don't let the 377 0 stevel * target continue. 378 0 stevel */ 379 0 stevel docontinue = 0; 380 0 stevel } 381 0 stevel } 382 0 stevel 383 0 stevel if (rdm.type == RD_DLACTIVITY && rdm.u.state == RD_ADD && 384 0 stevel pt->p_rtld_finished) 385 0 stevel pt->p_rdstate = MAX(pt->p_rdstate, PT_RD_ADD); 386 0 stevel } 387 0 stevel 388 0 stevel if (docontinue) 389 0 stevel (void) mdb_tgt_continue(t, NULL); 390 0 stevel } 391 0 stevel 392 0 stevel static void 393 0 stevel pt_post_attach(mdb_tgt_t *t) 394 0 stevel { 395 0 stevel struct ps_prochandle *P = t->t_pshandle; 396 0 stevel const lwpstatus_t *psp = &Pstatus(P)->pr_lwp; 397 0 stevel pt_data_t *pt = t->t_data; 398 0 stevel int hflag = MDB_TGT_SPEC_HIDDEN; 399 0 stevel 400 0 stevel mdb_dprintf(MDB_DBG_TGT, "attach pr_flags=0x%x pr_why=%d pr_what=%d\n", 401 0 stevel psp->pr_flags, psp->pr_why, psp->pr_what); 402 0 stevel 403 0 stevel /* 404 0 stevel * When we grab a process, the initial setting of p_rtld_finished 405 0 stevel * should be false if the process was just created by exec; otherwise 406 0 stevel * we permit unscoped references to resolve because we do not know how 407 0 stevel * far the process has proceeded through linker initialization. 408 0 stevel */ 409 0 stevel if ((psp->pr_flags & PR_ISTOP) && psp->pr_why == PR_SYSEXIT && 410 0 stevel psp->pr_errno == 0 && (psp->pr_what == SYS_exec || 411 0 stevel psp->pr_what == SYS_execve)) { 412 0 stevel if (mdb.m_target == NULL) { 413 0 stevel warn("target performed exec of %s\n", 414 0 stevel IOP_NAME(pt->p_fio)); 415 0 stevel } 416 0 stevel pt->p_rtld_finished = FALSE; 417 0 stevel } else 418 0 stevel pt->p_rtld_finished = TRUE; 419 0 stevel 420 0 stevel /* 421 0 stevel * When we grab a process, if it is stopped by job control and part of 422 0 stevel * the same session (i.e. same controlling tty), set MDB_FL_JOBCTL so 423 0 stevel * we will know to bring it to the foreground when we continue it. 424 0 stevel */ 425 0 stevel if (mdb.m_term != NULL && (psp->pr_flags & PR_STOPPED) && 426 0 stevel psp->pr_why == PR_JOBCONTROL && getsid(0) == Pstatus(P)->pr_sid) 427 0 stevel mdb.m_flags |= MDB_FL_JOBCTL; 428 0 stevel 429 0 stevel /* 430 0 stevel * When we grab control of a live process, set F_RDWR so that the 431 0 stevel * target layer permits writes to the target's address space. 432 0 stevel */ 433 0 stevel t->t_flags |= MDB_TGT_F_RDWR; 434 0 stevel 435 0 stevel (void) Pfault(P, FLTBPT, TRUE); /* always trace breakpoints */ 436 0 stevel (void) Pfault(P, FLTWATCH, TRUE); /* always trace watchpoints */ 437 0 stevel (void) Pfault(P, FLTTRACE, TRUE); /* always trace single-step */ 438 0 stevel 439 0 stevel (void) Punsetflags(P, PR_ASYNC); /* require synchronous mode */ 440 0 stevel (void) Psetflags(P, PR_BPTADJ); /* always adjust eip on x86 */ 441 0 stevel (void) Psetflags(P, PR_FORK); /* inherit tracing on fork */ 442 0 stevel 443 0 stevel /* 444 0 stevel * Install event specifiers to track fork and exec activities: 445 0 stevel */ 446 0 stevel (void) mdb_tgt_add_sysexit(t, SYS_forkall, hflag, pt_fork, NULL); 447 0 stevel (void) mdb_tgt_add_sysexit(t, SYS_fork1, hflag, pt_fork, NULL); 448 0 stevel (void) mdb_tgt_add_sysexit(t, SYS_vfork, hflag, pt_fork, NULL); 449 3235 raf (void) mdb_tgt_add_sysexit(t, SYS_forksys, hflag, pt_fork, NULL); 450 0 stevel (void) mdb_tgt_add_sysexit(t, SYS_exec, hflag, pt_exec, NULL); 451 0 stevel (void) mdb_tgt_add_sysexit(t, SYS_execve, hflag, pt_exec, NULL); 452 0 stevel 453 0 stevel /* 454 0 stevel * Attempt to instantiate the librtld_db agent and set breakpoints 455 0 stevel * to track rtld activity. We will legitimately fail to instantiate 456 0 stevel * the rtld_db agent if the target is statically linked. 457 0 stevel */ 458 0 stevel if (pt->p_rtld == NULL && (pt->p_rtld = Prd_agent(P)) != NULL) { 459 0 stevel rd_notify_t rdn; 460 0 stevel rd_err_e err; 461 0 stevel 462 0 stevel if ((err = rd_event_enable(pt->p_rtld, TRUE)) != RD_OK) { 463 0 stevel warn("failed to enable rtld_db event tracing: %s\n", 464 0 stevel rd_errstr(err)); 465 0 stevel goto out; 466 0 stevel } 467 0 stevel 468 0 stevel if ((err = rd_event_addr(pt->p_rtld, RD_PREINIT, 469 0 stevel &rdn)) == RD_OK && rdn.type == RD_NOTIFY_BPT) { 470 0 stevel (void) mdb_tgt_add_vbrkpt(t, rdn.u.bptaddr, 471 0 stevel hflag, pt_rtld_event, NULL); 472 0 stevel } else { 473 0 stevel warn("failed to install rtld_db preinit tracing: %s\n", 474 0 stevel rd_errstr(err)); 475 0 stevel } 476 0 stevel 477 0 stevel if ((err = rd_event_addr(pt->p_rtld, RD_POSTINIT, 478 0 stevel &rdn)) == RD_OK && rdn.type == RD_NOTIFY_BPT) { 479 0 stevel (void) mdb_tgt_add_vbrkpt(t, rdn.u.bptaddr, 480 0 stevel hflag, pt_rtld_event, NULL); 481 0 stevel } else { 482 0 stevel warn("failed to install rtld_db postinit tracing: %s\n", 483 0 stevel rd_errstr(err)); 484 0 stevel } 485 0 stevel 486 0 stevel if ((err = rd_event_addr(pt->p_rtld, RD_DLACTIVITY, 487 0 stevel &rdn)) == RD_OK && rdn.type == RD_NOTIFY_BPT) { 488 0 stevel (void) mdb_tgt_add_vbrkpt(t, rdn.u.bptaddr, 489 0 stevel hflag, pt_rtld_event, NULL); 490 0 stevel } else { 491 0 stevel warn("failed to install rtld_db activity tracing: %s\n", 492 0 stevel rd_errstr(err)); 493 0 stevel } 494 0 stevel } 495 0 stevel out: 496 0 stevel Pupdate_maps(P); 497 0 stevel Psync(P); 498 0 stevel 499 0 stevel /* 500 0 stevel * If librtld_db failed to initialize due to an error or because we are 501 0 stevel * debugging a statically linked executable, allow unscoped references. 502 0 stevel */ 503 0 stevel if (pt->p_rtld == NULL) 504 0 stevel pt->p_rtld_finished = TRUE; 505 0 stevel 506 0 stevel (void) mdb_tgt_sespec_activate_all(t); 507 0 stevel } 508 0 stevel 509 0 stevel /*ARGSUSED*/ 510 0 stevel static int 511 0 stevel pt_vespec_delete(mdb_tgt_t *t, void *private, int id, void *data) 512 0 stevel { 513 0 stevel if (id < 0) { 514 0 stevel ASSERT(data == NULL); /* we don't use any ve_data */ 515 0 stevel (void) mdb_tgt_vespec_delete(t, id); 516 0 stevel } 517 0 stevel return (0); 518 0 stevel } 519 0 stevel 520 0 stevel static void 521 0 stevel pt_pre_detach(mdb_tgt_t *t, int clear_matched) 522 0 stevel { 523 0 stevel const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp; 524 0 stevel pt_data_t *pt = t->t_data; 525 0 stevel long cmd = 0; 526 0 stevel 527 0 stevel /* 528 0 stevel * If we are about to release the process and it is stopped on a traced 529 0 stevel * SIGINT, breakpoint fault, single-step fault, or watchpoint, make 530 0 stevel * sure to clear this event prior to releasing the process so that it 531 0 stevel * does not subsequently reissue the fault and die from SIGTRAP. 532 0 stevel */ 533 0 stevel if (psp->pr_flags & PR_ISTOP) { 534 0 stevel if (psp->pr_why == PR_FAULTED && (psp->pr_what == FLTBPT || 535 0 stevel psp->pr_what == FLTTRACE || psp->pr_what == FLTWATCH)) 536 0 stevel cmd = PCCFAULT; 537 0 stevel else if (psp->pr_why == PR_SIGNALLED && psp->pr_what == SIGINT) 538 0 stevel cmd = PCCSIG; 539 0 stevel 540 0 stevel if (cmd != 0) 541 0 stevel (void) write(Pctlfd(t->t_pshandle), &cmd, sizeof (cmd)); 542 0 stevel } 543 0 stevel 544 0 stevel if (Pstate(t->t_pshandle) == PS_UNDEAD) 545 0 stevel (void) waitpid(Pstatus(t->t_pshandle)->pr_pid, NULL, WNOHANG); 546 0 stevel 547 0 stevel (void) mdb_tgt_vespec_iter(t, pt_vespec_delete, NULL); 548 0 stevel mdb_tgt_sespec_idle_all(t, EMDB_NOPROC, clear_matched); 549 0 stevel 550 0 stevel if (pt->p_fio != pt->p_aout_fio) { 551 0 stevel pt_close_aout(t); 552 0 stevel (void) pt_open_aout(t, pt->p_aout_fio); 553 0 stevel } 554 0 stevel 555 0 stevel PTL_DTOR(t); 556 0 stevel pt->p_tdb_ops = NULL; 557 0 stevel pt->p_ptl_ops = &proc_lwp_ops; 558 0 stevel pt->p_ptl_hdl = NULL; 559 0 stevel 560 0 stevel pt->p_rtld = NULL; 561 0 stevel pt->p_signal = 0; 562 0 stevel pt->p_rtld_finished = FALSE; 563 0 stevel pt->p_rdstate = PT_RD_NONE; 564 0 stevel } 565 0 stevel 566 0 stevel static void 567 0 stevel pt_release_parents(mdb_tgt_t *t) 568 0 stevel { 569 0 stevel struct ps_prochandle *P = t->t_pshandle; 570 0 stevel pt_data_t *pt = t->t_data; 571 0 stevel 572 0 stevel mdb_sespec_t *sep; 573 0 stevel pt_vforkp_t *vfp; 574 0 stevel 575 0 stevel while ((vfp = mdb_list_next(&pt->p_vforkp)) != NULL) { 576 0 stevel mdb_dprintf(MDB_DBG_TGT, "releasing vfork parent %d\n", 577 0 stevel (int)Pstatus(vfp->p_pshandle)->pr_pid); 578 0 stevel 579 0 stevel /* 580 0 stevel * To release vfork parents, we must also wipe out any armed 581 0 stevel * events in the parent by switching t_pshandle and calling 582 0 stevel * se_disarm(). Do not change states or lose the matched list. 583 0 stevel */ 584 0 stevel t->t_pshandle = vfp->p_pshandle; 585 0 stevel 586 0 stevel for (sep = mdb_list_next(&t->t_active); sep != NULL; 587 0 stevel sep = mdb_list_next(sep)) { 588 0 stevel if (sep->se_state == MDB_TGT_SPEC_ARMED) 589 0 stevel (void) sep->se_ops->se_disarm(t, sep); 590 0 stevel } 591 0 stevel 592 0 stevel t->t_pshandle = P; 593 0 stevel 594 0 stevel Prelease(vfp->p_pshandle, PRELEASE_CLEAR); 595 0 stevel mdb_list_delete(&pt->p_vforkp, vfp); 596 0 stevel mdb_free(vfp, sizeof (pt_vforkp_t)); 597 0 stevel } 598 0 stevel } 599 0 stevel 600 0 stevel /*ARGSUSED*/ 601 0 stevel static void 602 0 stevel pt_fork(mdb_tgt_t *t, int vid, void *private) 603 0 stevel { 604 0 stevel struct ps_prochandle *P = t->t_pshandle; 605 0 stevel const lwpstatus_t *psp = &Pstatus(P)->pr_lwp; 606 0 stevel pt_data_t *pt = t->t_data; 607 0 stevel mdb_sespec_t *sep; 608 0 stevel 609 0 stevel int follow_parent = mdb.m_forkmode != MDB_FM_CHILD; 610 3235 raf int is_vfork = (psp->pr_what == SYS_vfork || 611 3235 raf (psp->pr_what == SYS_forksys && psp->pr_sysarg[0] == 2)); 612 0 stevel 613 0 stevel struct ps_prochandle *C; 614 0 stevel const lwpstatus_t *csp; 615 0 stevel char sysname[32]; 616 0 stevel int gcode; 617 0 stevel char c; 618 0 stevel 619 0 stevel mdb_dprintf(MDB_DBG_TGT, "parent %s: errno=%d rv1=%ld rv2=%ld\n", 620 0 stevel proc_sysname(psp->pr_what, sysname, sizeof (sysname)), 621 0 stevel psp->pr_errno, psp->pr_rval1, psp->pr_rval2); 622 0 stevel 623 0 stevel if (psp->pr_errno != 0) { 624 0 stevel (void) mdb_tgt_continue(t, NULL); 625 0 stevel return; /* fork failed */ 626 0 stevel } 627 0 stevel 628 0 stevel /* 629 0 stevel * If forkmode is ASK and stdout is a terminal, then ask the user to 630 0 stevel * explicitly set the fork behavior for this particular fork. 631 0 stevel */ 632 0 stevel if (mdb.m_forkmode == MDB_FM_ASK && mdb.m_term != NULL) { 633 0 stevel mdb_iob_printf(mdb.m_err, "%s: %s detected: follow (p)arent " 634 0 stevel "or (c)hild? ", mdb.m_pname, sysname); 635 0 stevel mdb_iob_flush(mdb.m_err); 636 0 stevel 637 0 stevel while (IOP_READ(mdb.m_term, &c, sizeof (c)) == sizeof (c)) { 638 0 stevel if (c == 'P' || c == 'p') { 639 0 stevel mdb_iob_printf(mdb.m_err, "%c\n", c); 640 0 stevel follow_parent = TRUE; 641 0 stevel break; 642 0 stevel } else if (c == 'C' || c == 'c') { 643 0 stevel mdb_iob_printf(mdb.m_err, "%c\n", c); 644 0 stevel follow_parent = FALSE; 645 0 stevel break; 646 0 stevel } 647 0 stevel } 648 0 stevel } 649 0 stevel 650 0 stevel /* 651 0 stevel * The parent is now stopped on exit from its fork call. We must now 652 0 stevel * grab the child on its return from fork in order to manipulate it. 653 0 stevel */ 654 0 stevel if ((C = Pgrab(psp->pr_rval1, PGRAB_RETAIN, &gcode)) == NULL) { 655 0 stevel warn("failed to grab forked child process %ld: %s\n", 656 0 stevel psp->pr_rval1, Pgrab_error(gcode)); 657 0 stevel return; /* just stop if we failed to grab the child */ 658 0 stevel } 659 0 stevel 660 0 stevel /* 661 0 stevel * We may have grabbed the child and stopped it prematurely before it 662 0 stevel * stopped on exit from fork. If so, wait up to 1 sec for it to settle. 663 0 stevel */ 664 0 stevel if (Pstatus(C)->pr_lwp.pr_why != PR_SYSEXIT) 665 0 stevel (void) Pwait(C, MILLISEC); 666 0 stevel 667 0 stevel csp = &Pstatus(C)->pr_lwp; 668 0 stevel 669 3235 raf if (csp->pr_why != PR_SYSEXIT || 670 3235 raf (csp->pr_what != SYS_forkall && 671 3235 raf csp->pr_what != SYS_fork1 && 672 3235 raf csp->pr_what != SYS_vfork && 673 3235 raf csp->pr_what != SYS_forksys)) { 674 0 stevel warn("forked child process %ld did not stop on exit from " 675 0 stevel "fork as expected\n", psp->pr_rval1); 676 0 stevel } 677 0 stevel 678 0 stevel warn("target forked child process %ld (debugger following %s)\n", 679 0 stevel psp->pr_rval1, follow_parent ? "parent" : "child"); 680 0 stevel 681 0 stevel (void) Punsetflags(C, PR_ASYNC); /* require synchronous mode */ 682 0 stevel (void) Psetflags(C, PR_BPTADJ); /* always adjust eip on x86 */ 683 0 stevel (void) Prd_agent(C); /* initialize librtld_db */ 684 0 stevel 685 0 stevel /* 686 0 stevel * At the time pt_fork() is called, the target event engine has already 687 0 stevel * disarmed the specifiers on the active list, clearing out events in 688 0 stevel * the parent process. However, this means that events that change 689 0 stevel * the address space (e.g. breakpoints) have not been effectively 690 0 stevel * disarmed in the child since its address space reflects the state of 691 0 stevel * the process at the time of fork when events were armed. We must 692 0 stevel * therefore handle this as a special case and re-invoke the disarm 693 0 stevel * callback of each active specifier to clean out the child process. 694 0 stevel */ 695 0 stevel if (!is_vfork) { 696 0 stevel for (t->t_pshandle = C, sep = mdb_list_next(&t->t_active); 697 0 stevel sep != NULL; sep = mdb_list_next(sep)) { 698 0 stevel if (sep->se_state == MDB_TGT_SPEC_ACTIVE) 699 0 stevel (void) sep->se_ops->se_disarm(t, sep); 700 0 stevel } 701 0 stevel 702 0 stevel t->t_pshandle = P; /* restore pshandle to parent */ 703 0 stevel } 704 0 stevel 705 0 stevel /* 706 0 stevel * If we're following the parent process, we need to temporarily change 707 0 stevel * t_pshandle to refer to the child handle C so that we can clear out 708 0 stevel * all the events in the child prior to releasing it below. If we are 709 0 stevel * tracing a vfork, we also need to explicitly wait for the child to 710 0 stevel * exec, exit, or die before we can reset and continue the parent. We 711 0 stevel * avoid having to deal with the vfork child forking again by clearing 712 0 stevel * PR_FORK and setting PR_RLC; if it does fork it will effectively be 713 0 stevel * released from our control and we will continue following the parent. 714 0 stevel */ 715 0 stevel if (follow_parent) { 716 0 stevel if (is_vfork) { 717 0 stevel mdb_tgt_status_t status; 718 0 stevel 719 0 stevel ASSERT(psp->pr_flags & PR_VFORKP); 720 0 stevel mdb_tgt_sespec_idle_all(t, EBUSY, FALSE); 721 0 stevel t->t_pshandle = C; 722 0 stevel 723 0 stevel (void) Psysexit(C, SYS_exec, TRUE); 724 0 stevel (void) Psysexit(C, SYS_execve, TRUE); 725 0 stevel 726 0 stevel (void) Punsetflags(C, PR_FORK | PR_KLC); 727 0 stevel (void) Psetflags(C, PR_RLC); 728 0 stevel 729 0 stevel do { 730 0 stevel if (pt_setrun(t, &status, 0) == -1 || 731 0 stevel status.st_state == MDB_TGT_UNDEAD || 732 0 stevel status.st_state == MDB_TGT_LOST) 733 0 stevel break; /* failure or process died */ 734 0 stevel 735 0 stevel } while (csp->pr_why != PR_SYSEXIT || 736 0 stevel csp->pr_errno != 0 || (csp->pr_what != SYS_exec && 737 0 stevel csp->pr_what != SYS_execve)); 738 0 stevel } else 739 0 stevel t->t_pshandle = C; 740 0 stevel } 741 0 stevel 742 0 stevel /* 743 0 stevel * If we are following the child, destroy any active libthread_db 744 0 stevel * handle before we release the parent process. 745 0 stevel */ 746 0 stevel if (!follow_parent) { 747 0 stevel PTL_DTOR(t); 748 0 stevel pt->p_tdb_ops = NULL; 749 0 stevel pt->p_ptl_ops = &proc_lwp_ops; 750 0 stevel pt->p_ptl_hdl = NULL; 751 0 stevel } 752 0 stevel 753 0 stevel /* 754 0 stevel * Idle all events to make sure the address space and tracing flags are 755 0 stevel * restored, and then release the process we are not tracing. If we 756 0 stevel * are following the child of a vfork, we push the parent's pshandle 757 0 stevel * on to a list of vfork parents to be released when we exec or exit. 758 0 stevel */ 759 0 stevel if (is_vfork && !follow_parent) { 760 0 stevel pt_vforkp_t *vfp = mdb_alloc(sizeof (pt_vforkp_t), UM_SLEEP); 761 0 stevel 762 0 stevel ASSERT(psp->pr_flags & PR_VFORKP); 763 0 stevel vfp->p_pshandle = P; 764 0 stevel mdb_list_append(&pt->p_vforkp, vfp); 765 0 stevel mdb_tgt_sespec_idle_all(t, EBUSY, FALSE); 766 0 stevel 767 0 stevel } else { 768 0 stevel mdb_tgt_sespec_idle_all(t, EBUSY, FALSE); 769 0 stevel Prelease(t->t_pshandle, PRELEASE_CLEAR); 770 0 stevel if (!follow_parent) 771 0 stevel pt_release_parents(t); 772 0 stevel } 773 0 stevel 774 0 stevel /* 775 0 stevel * Now that all the hard stuff is done, switch t_pshandle back to the 776 0 stevel * process we are following and reset our events to the ACTIVE state. 777 0 stevel * If we are following the child, reset the libthread_db handle as well 778 0 stevel * as the rtld agent. 779 0 stevel */ 780 0 stevel if (follow_parent) 781 0 stevel t->t_pshandle = P; 782 0 stevel else { 783 0 stevel t->t_pshandle = C; 784 0 stevel pt->p_rtld = Prd_agent(C); 785 7928 Edward (void) Pobject_iter(t->t_pshandle, (proc_map_f *)thr_check, t); 786 0 stevel } 787 0 stevel 788 0 stevel (void) mdb_tgt_sespec_activate_all(t); 789 0 stevel (void) mdb_tgt_continue(t, NULL); 790 0 stevel } 791 0 stevel 792 0 stevel /*ARGSUSED*/ 793 0 stevel static void 794 0 stevel pt_exec(mdb_tgt_t *t, int vid, void *private) 795 0 stevel { 796 0 stevel struct ps_prochandle *P = t->t_pshandle; 797 0 stevel const pstatus_t *psp = Pstatus(P); 798 0 stevel pt_data_t *pt = t->t_data; 799 0 stevel int follow_exec = mdb.m_execmode == MDB_EM_FOLLOW; 800 0 stevel pid_t pid = psp->pr_pid; 801 0 stevel 802 0 stevel char execname[MAXPATHLEN]; 803 0 stevel mdb_sespec_t *sep, *nsep; 804 0 stevel mdb_io_t *io; 805 0 stevel char c; 806 0 stevel 807 0 stevel mdb_dprintf(MDB_DBG_TGT, "exit from %s: errno=%d\n", proc_sysname( 808 0 stevel psp->pr_lwp.pr_what, execname, sizeof (execname)), 809 0 stevel psp->pr_lwp.pr_errno); 810 0 stevel 811 0 stevel if (psp->pr_lwp.pr_errno != 0) { 812 0 stevel (void) mdb_tgt_continue(t, NULL); 813 0 stevel return; /* exec failed */ 814 0 stevel } 815 0 stevel 816 0 stevel /* 817 0 stevel * If execmode is ASK and stdout is a terminal, then ask the user to 818 0 stevel * explicitly set the exec behavior for this particular exec. If 819 0 stevel * Pstate() still shows PS_LOST, we are being called from pt_setrun() 820 0 stevel * directly and therefore we must resume the terminal since it is still 821 0 stevel * in the suspended state as far as tgt_continue() is concerned. 822 0 stevel */ 823 0 stevel if (mdb.m_execmode == MDB_EM_ASK && mdb.m_term != NULL) { 824 0 stevel if (Pstate(P) == PS_LOST) 825 0 stevel IOP_RESUME(mdb.m_term); 826 0 stevel 827 0 stevel mdb_iob_printf(mdb.m_err, "%s: %s detected: (f)ollow new " 828 0 stevel "program or (s)top? ", mdb.m_pname, execname); 829 0 stevel mdb_iob_flush(mdb.m_err); 830 0 stevel 831 0 stevel while (IOP_READ(mdb.m_term, &c, sizeof (c)) == sizeof (c)) { 832 0 stevel if (c == 'F' || c == 'f') { 833 0 stevel mdb_iob_printf(mdb.m_err, "%c\n", c); 834 0 stevel follow_exec = TRUE; 835 0 stevel break; 836 0 stevel } else if (c == 'S' || c == 's') { 837 0 stevel mdb_iob_printf(mdb.m_err, "%c\n", c); 838 0 stevel follow_exec = FALSE; 839 0 stevel break; 840 0 stevel } 841 0 stevel } 842 0 stevel 843 0 stevel if (Pstate(P) == PS_LOST) 844 0 stevel IOP_SUSPEND(mdb.m_term); 845 0 stevel } 846 0 stevel 847 0 stevel pt_release_parents(t); /* release any waiting vfork parents */ 848 0 stevel pt_pre_detach(t, FALSE); /* remove our breakpoints and idle events */ 849 0 stevel Preset_maps(P); /* libproc must delete mappings and symtabs */ 850 0 stevel pt_close_aout(t); /* free pt symbol tables and GElf file data */ 851 0 stevel 852 0 stevel /* 853 0 stevel * If we lost control of the process across the exec and are not able 854 0 stevel * to reopen it, we have no choice but to clear the matched event list 855 0 stevel * and wait for the user to quit or otherwise release the process. 856 0 stevel */ 857 0 stevel if (Pstate(P) == PS_LOST && Preopen(P) == -1) { 858 0 stevel int error = errno; 859 0 stevel 860 0 stevel warn("lost control of PID %d due to exec of %s executable\n", 861 0 stevel (int)pid, error == EOVERFLOW ? "64-bit" : "set-id"); 862 0 stevel 863 0 stevel for (sep = t->t_matched; sep != T_SE_END; sep = nsep) { 864 0 stevel nsep = sep->se_matched; 865 0 stevel sep->se_matched = NULL; 866 0 stevel mdb_tgt_sespec_rele(t, sep); 867 0 stevel } 868 0 stevel 869 0 stevel if (error != EOVERFLOW) 870 0 stevel return; /* just stop if we exec'd a set-id executable */ 871 0 stevel } 872 0 stevel 873 0 stevel if (Pstate(P) != PS_LOST) { 874 0 stevel if (Pexecname(P, execname, sizeof (execname)) == NULL) { 875 0 stevel (void) mdb_iob_snprintf(execname, sizeof (execname), 876 0 stevel "/proc/%d/object/a.out", (int)pid); 877 0 stevel } 878 0 stevel 879 0 stevel if (follow_exec == FALSE || psp->pr_dmodel == PR_MODEL_NATIVE) 880 0 stevel warn("target performed exec of %s\n", execname); 881 0 stevel 882 0 stevel io = mdb_fdio_create_path(NULL, execname, pt->p_oflags, 0); 883 0 stevel if (io == NULL) { 884 0 stevel warn("failed to open %s", execname); 885 0 stevel warn("a.out symbol tables will not be available\n"); 886 0 stevel } else if (pt_open_aout(t, io) == NULL) { 887 0 stevel (void) mdb_dis_select(pt_disasm(NULL)); 888 0 stevel mdb_io_destroy(io); 889 0 stevel } else 890 0 stevel (void) mdb_dis_select(pt_disasm(&pt->p_file->gf_ehdr)); 891 0 stevel } 892 0 stevel 893 0 stevel /* 894 0 stevel * We reset our libthread_db state here, but deliberately do NOT call 895 0 stevel * PTL_DTOR because we do not want to call libthread_db's td_ta_delete. 896 0 stevel * This interface is hopelessly broken in that it writes to the process 897 0 stevel * address space (which we do not want it to do after an exec) and it 898 0 stevel * doesn't bother deallocating any of its storage anyway. 899 0 stevel */ 900 0 stevel pt->p_tdb_ops = NULL; 901 0 stevel pt->p_ptl_ops = &proc_lwp_ops; 902 0 stevel pt->p_ptl_hdl = NULL; 903 0 stevel 904 0 stevel if (follow_exec && psp->pr_dmodel != PR_MODEL_NATIVE) { 905 0 stevel const char *argv[3]; 906 0 stevel char *state, *env; 907 0 stevel char pidarg[16]; 908 0 stevel size_t envlen; 909 0 stevel 910 0 stevel if (realpath(getexecname(), execname) == NULL) { 911 0 stevel warn("cannot follow PID %d -- failed to resolve " 912 0 stevel "debugger pathname for re-exec", (int)pid); 913 0 stevel return; 914 0 stevel } 915 0 stevel 916 0 stevel warn("restarting debugger to follow PID %d ...\n", (int)pid); 917 0 stevel mdb_dprintf(MDB_DBG_TGT, "re-exec'ing %s\n", execname); 918 0 stevel 919 0 stevel (void) mdb_snprintf(pidarg, sizeof (pidarg), "-p%d", (int)pid); 920 0 stevel 921 0 stevel state = mdb_get_config(); 922 0 stevel envlen = strlen(MDB_CONFIG_ENV_VAR) + 1 + strlen(state) + 1; 923 0 stevel env = mdb_alloc(envlen, UM_SLEEP); 924 11053 Surya (void) snprintf(env, envlen, 925 11053 Surya "%s=%s", MDB_CONFIG_ENV_VAR, state); 926 0 stevel 927 0 stevel (void) putenv(env); 928 0 stevel 929 0 stevel argv[0] = mdb.m_pname; 930 0 stevel argv[1] = pidarg; 931 0 stevel argv[2] = NULL; 932 0 stevel 933 0 stevel if (mdb.m_term != NULL) 934 0 stevel IOP_SUSPEND(mdb.m_term); 935 0 stevel 936 0 stevel Prelease(P, PRELEASE_CLEAR | PRELEASE_HANG); 937 0 stevel (void) execv(execname, (char *const *)argv); 938 0 stevel warn("failed to re-exec debugger"); 939 0 stevel 940 0 stevel if (mdb.m_term != NULL) 941 0 stevel IOP_RESUME(mdb.m_term); 942 0 stevel 943 0 stevel t->t_pshandle = pt->p_idlehandle; 944 0 stevel return; 945 0 stevel } 946 0 stevel 947 0 stevel pt_post_attach(t); /* install tracing flags and activate events */ 948 0 stevel pt_activate_common(t); /* initialize librtld_db and libthread_db */ 949 0 stevel 950 0 stevel if (psp->pr_dmodel != PR_MODEL_NATIVE && mdb.m_term != NULL) { 951 0 stevel warn("loadable dcmds will not operate on non-native %d-bit " 952 0 stevel "data model\n", psp->pr_dmodel == PR_MODEL_ILP32 ? 32 : 64); 953 0 stevel warn("use ::release -a and then run mdb -p %d to restart " 954 0 stevel "debugger\n", (int)pid); 955 0 stevel } 956 0 stevel 957 0 stevel if (follow_exec) 958 0 stevel (void) mdb_tgt_continue(t, NULL); 959 0 stevel } 960 0 stevel 961 0 stevel static int 962 0 stevel pt_setflags(mdb_tgt_t *t, int flags) 963 0 stevel { 964 0 stevel pt_data_t *pt = t->t_data; 965 0 stevel 966 0 stevel if ((flags ^ t->t_flags) & MDB_TGT_F_RDWR) { 967 0 stevel int mode = (flags & MDB_TGT_F_RDWR) ? O_RDWR : O_RDONLY; 968 0 stevel mdb_io_t *io; 969 0 stevel 970 0 stevel if (pt->p_fio == NULL) 971 0 stevel return (set_errno(EMDB_NOEXEC)); 972 0 stevel 973 0 stevel io = mdb_fdio_create_path(NULL, IOP_NAME(pt->p_fio), mode, 0); 974 0 stevel 975 0 stevel if (io == NULL) 976 0 stevel return (-1); /* errno is set for us */ 977 0 stevel 978 0 stevel t->t_flags = (t->t_flags & ~MDB_TGT_F_RDWR) | 979 0 stevel (flags & MDB_TGT_F_RDWR); 980 0 stevel 981 0 stevel pt->p_fio = mdb_io_hold(io); 982 0 stevel mdb_io_rele(pt->p_file->gf_io); 983 0 stevel pt->p_file->gf_io = pt->p_fio; 984 0 stevel } 985 0 stevel 986 0 stevel if (flags & MDB_TGT_F_FORCE) { 987 0 stevel t->t_flags |= MDB_TGT_F_FORCE; 988 0 stevel pt->p_gflags |= PGRAB_FORCE; 989 0 stevel } 990 0 stevel 991 0 stevel return (0); 992 0 stevel } 993 0 stevel 994 0 stevel /*ARGSUSED*/ 995 0 stevel static int 996 0 stevel pt_frame(void *arglim, uintptr_t pc, uint_t argc, const long *argv, 997 0 stevel const mdb_tgt_gregset_t *gregs) 998 0 stevel { 999 0 stevel argc = MIN(argc, (uint_t)(uintptr_t)arglim); 1000 0 stevel mdb_printf("%a(", pc); 1001 0 stevel 1002 0 stevel if (argc != 0) { 1003 0 stevel mdb_printf("%lr", *argv++); 1004 0 stevel for (argc--; argc != 0; argc--) 1005 0 stevel mdb_printf(", %lr", *argv++); 1006 0 stevel } 1007 0 stevel 1008 0 stevel mdb_printf(")\n"); 1009 0 stevel return (0); 1010 0 stevel } 1011 0 stevel 1012 0 stevel static int 1013 0 stevel pt_framev(void *arglim, uintptr_t pc, uint_t argc, const long *argv, 1014 0 stevel const mdb_tgt_gregset_t *gregs) 1015 0 stevel { 1016 0 stevel argc = MIN(argc, (uint_t)(uintptr_t)arglim); 1017 0 stevel #if defined(__i386) || defined(__amd64) 1018 0 stevel mdb_printf("%0?lr %a(", gregs->gregs[R_FP], pc); 1019 0 stevel #else 1020 0 stevel mdb_printf("%0?lr %a(", gregs->gregs[R_SP], pc); 1021 0 stevel #endif 1022 0 stevel if (argc != 0) { 1023 0 stevel mdb_printf("%lr", *argv++); 1024 0 stevel for (argc--; argc != 0; argc--) 1025 0 stevel mdb_printf(", %lr", *argv++); 1026 0 stevel } 1027 0 stevel 1028 0 stevel mdb_printf(")\n"); 1029 0 stevel return (0); 1030 0 stevel } 1031 0 stevel 1032 0 stevel static int 1033 0 stevel pt_framer(void *arglim, uintptr_t pc, uint_t argc, const long *argv, 1034 0 stevel const mdb_tgt_gregset_t *gregs) 1035 0 stevel { 1036 0 stevel if (pt_frameregs(arglim, pc, argc, argv, gregs, pc == PC_FAKE) == -1) { 1037 0 stevel /* 1038 0 stevel * Use verbose format if register format is not supported. 1039 0 stevel */ 1040 0 stevel return (pt_framev(arglim, pc, argc, argv, gregs)); 1041 0 stevel } 1042 0 stevel 1043 0 stevel return (0); 1044 0 stevel } 1045 0 stevel 1046 0 stevel /*ARGSUSED*/ 1047 0 stevel static int 1048 0 stevel pt_stack_common(uintptr_t addr, uint_t flags, int argc, 1049 0 stevel const mdb_arg_t *argv, mdb_tgt_stack_f *func, prgreg_t saved_pc) 1050 0 stevel { 1051 0 stevel void *arg = (void *)(uintptr_t)mdb.m_nargs; 1052 0 stevel mdb_tgt_t *t = mdb.m_target; 1053 0 stevel mdb_tgt_gregset_t gregs; 1054 0 stevel 1055 0 stevel if (argc != 0) { 1056 0 stevel if (argv->a_type == MDB_TYPE_CHAR || argc > 1) 1057 0 stevel return (DCMD_USAGE); 1058 0 stevel 1059 0 stevel if (argv->a_type == MDB_TYPE_STRING) 1060 0 stevel arg = (void *)(uintptr_t)mdb_strtoull(argv->a_un.a_str); 1061 0 stevel else 1062 0 stevel arg = (void *)(uintptr_t)argv->a_un.a_val; 1063 0 stevel } 1064 0 stevel 1065 0 stevel if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_IDLE) { 1066 0 stevel mdb_warn("no process active\n"); 1067 0 stevel return (DCMD_ERR); 1068 0 stevel } 1069 0 stevel 1070 0 stevel /* 1071 0 stevel * In the universe of sparcv7, sparcv9, ia32, and amd64 this code can be 1072 0 stevel * common: <sys/procfs_isa.h> conveniently #defines R_FP to be the 1073 0 stevel * appropriate register we need to set in order to perform a stack 1074 0 stevel * traceback from a given frame address. 1075 0 stevel */ 1076 0 stevel if (flags & DCMD_ADDRSPEC) { 1077 0 stevel bzero(&gregs, sizeof (gregs)); 1078 0 stevel gregs.gregs[R_FP] = addr; 1079 0 stevel #ifdef __sparc 1080 0 stevel gregs.gregs[R_I7] = saved_pc; 1081 0 stevel #endif /* __sparc */ 1082 0 stevel } else if (PTL_GETREGS(t, PTL_TID(t), gregs.gregs) != 0) { 1083 0 stevel mdb_warn("failed to get current register set"); 1084 0 stevel return (DCMD_ERR); 1085 0 stevel } 1086 0 stevel 1087 0 stevel (void) mdb_tgt_stack_iter(t, &gregs, func, arg); 1088 0 stevel return (DCMD_OK); 1089 0 stevel } 1090 0 stevel 1091 0 stevel static int 1092 0 stevel pt_stack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1093 0 stevel { 1094 0 stevel return (pt_stack_common(addr, flags, argc, argv, pt_frame, 0)); 1095 0 stevel } 1096 0 stevel 1097 0 stevel static int 1098 0 stevel pt_stackv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1099 0 stevel { 1100 0 stevel return (pt_stack_common(addr, flags, argc, argv, pt_framev, 0)); 1101 0 stevel } 1102 0 stevel 1103 0 stevel static int 1104 0 stevel pt_stackr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1105 0 stevel { 1106 0 stevel /* 1107 0 stevel * Force printing of first register window, by setting the 1108 0 stevel * saved pc (%i7) to PC_FAKE. 1109 0 stevel */ 1110 0 stevel return (pt_stack_common(addr, flags, argc, argv, pt_framer, PC_FAKE)); 1111 0 stevel } 1112 0 stevel 1113 0 stevel /*ARGSUSED*/ 1114 0 stevel static int 1115 0 stevel pt_ignored(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1116 0 stevel { 1117 0 stevel struct ps_prochandle *P = mdb.m_target->t_pshandle; 1118 0 stevel char buf[PRSIGBUFSZ]; 1119 0 stevel 1120 0 stevel if ((flags & DCMD_ADDRSPEC) || argc != 0) 1121 0 stevel return (DCMD_USAGE); 1122 0 stevel 1123 0 stevel if (P == NULL) { 1124 0 stevel mdb_warn("no process is currently active\n"); 1125 0 stevel return (DCMD_ERR); 1126 0 stevel } 1127 0 stevel 1128 0 stevel mdb_printf("%s\n", proc_sigset2str(&Pstatus(P)->pr_sigtrace, " ", 1129 0 stevel FALSE, buf, sizeof (buf))); 1130 0 stevel 1131 0 stevel return (DCMD_OK); 1132 0 stevel } 1133 0 stevel 1134 0 stevel /*ARGSUSED*/ 1135 0 stevel static int 1136 0 stevel pt_lwpid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1137 0 stevel { 1138 0 stevel struct ps_prochandle *P = mdb.m_target->t_pshandle; 1139 0 stevel 1140 0 stevel if ((flags & DCMD_ADDRSPEC) || argc != 0) 1141 0 stevel return (DCMD_USAGE); 1142 0 stevel 1143 0 stevel if (P == NULL) { 1144 0 stevel mdb_warn("no process is currently active\n"); 1145 0 stevel return (DCMD_ERR); 1146 0 stevel } 1147 0 stevel 1148 0 stevel mdb_printf("%d\n", Pstatus(P)->pr_lwp.pr_lwpid); 1149 0 stevel return (DCMD_OK); 1150 0 stevel } 1151 0 stevel 1152 0 stevel static int 1153 0 stevel pt_print_lwpid(int *n, const lwpstatus_t *psp) 1154 0 stevel { 1155 0 stevel struct ps_prochandle *P = mdb.m_target->t_pshandle; 1156 0 stevel int nlwp = Pstatus(P)->pr_nlwp; 1157 0 stevel 1158 0 stevel if (*n == nlwp - 2) 1159 0 stevel mdb_printf("%d and ", (int)psp->pr_lwpid); 1160 0 stevel else if (*n == nlwp - 1) 1161 0 stevel mdb_printf("%d are", (int)psp->pr_lwpid); 1162 0 stevel else 1163 0 stevel mdb_printf("%d, ", (int)psp->pr_lwpid); 1164 0 stevel 1165 0 stevel (*n)++; 1166 0 stevel return (0); 1167 0 stevel } 1168 0 stevel 1169 0 stevel /*ARGSUSED*/ 1170 0 stevel static int 1171 0 stevel pt_lwpids(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1172 0 stevel { 1173 0 stevel struct ps_prochandle *P = mdb.m_target->t_pshandle; 1174 0 stevel int n = 0; 1175 0 stevel 1176 0 stevel if (P == NULL) { 1177 0 stevel mdb_warn("no process is currently active\n"); 1178 0 stevel return (DCMD_ERR); 1179 0 stevel } 1180 0 stevel 1181 0 stevel switch (Pstatus(P)->pr_nlwp) { 1182 0 stevel case 0: 1183 0 stevel mdb_printf("no lwps are"); 1184 0 stevel break; 1185 0 stevel case 1: 1186 0 stevel mdb_printf("lwpid %d is the only lwp", 1187 0 stevel Pstatus(P)->pr_lwp.pr_lwpid); 1188 0 stevel break; 1189 0 stevel default: 1190 0 stevel mdb_printf("lwpids "); 1191 0 stevel (void) Plwp_iter(P, (proc_lwp_f *)pt_print_lwpid, &n); 1192 0 stevel } 1193 0 stevel 1194 0 stevel switch (Pstate(P)) { 1195 0 stevel case PS_DEAD: 1196 0 stevel mdb_printf(" in core of process %d.\n", Pstatus(P)->pr_pid); 1197 0 stevel break; 1198 0 stevel case PS_IDLE: 1199 0 stevel mdb_printf(" in idle target.\n"); 1200 0 stevel break; 1201 0 stevel default: 1202 0 stevel mdb_printf(" in process %d.\n", (int)Pstatus(P)->pr_pid); 1203 0 stevel break; 1204 0 stevel } 1205 0 stevel 1206 0 stevel return (DCMD_OK); 1207 0 stevel } 1208 0 stevel 1209 0 stevel /*ARGSUSED*/ 1210 0 stevel static int 1211 0 stevel pt_ignore(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1212 0 stevel { 1213 0 stevel pt_data_t *pt = mdb.m_target->t_data; 1214 0 stevel 1215 0 stevel if (!(flags & DCMD_ADDRSPEC) || argc != 0) 1216 0 stevel return (DCMD_USAGE); 1217 0 stevel 1218 0 stevel if (addr < 1 || addr > pt->p_maxsig) { 1219 0 stevel mdb_warn("invalid signal number -- 0t%lu\n", addr); 1220 0 stevel return (DCMD_ERR); 1221 0 stevel } 1222 0 stevel 1223 0 stevel (void) mdb_tgt_vespec_iter(mdb.m_target, pt_ignore_sig, (void *)addr); 1224 0 stevel return (DCMD_OK); 1225 0 stevel } 1226 0 stevel 1227 0 stevel /*ARGSUSED*/ 1228 0 stevel static int 1229 0 stevel pt_attach(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1230 0 stevel { 1231 0 stevel mdb_tgt_t *t = mdb.m_target; 1232 0 stevel pt_data_t *pt = t->t_data; 1233 0 stevel int state, perr; 1234 0 stevel 1235 0 stevel if (!(flags & DCMD_ADDRSPEC) && argc == 0) 1236 0 stevel return (DCMD_USAGE); 1237 0 stevel 1238 0 stevel if (((flags & DCMD_ADDRSPEC) && argc != 0) || argc > 1 || 1239 0 stevel (argc != 0 && argv->a_type != MDB_TYPE_STRING)) 1240 0 stevel return (DCMD_USAGE); 1241 0 stevel 1242 0 stevel if (t->t_pshandle != NULL && Pstate(t->t_pshandle) != PS_IDLE) { 1243 0 stevel mdb_warn("debugger is already attached to a %s\n", 1244 0 stevel (Pstate(t->t_pshandle) == PS_DEAD) ? "core" : "process"); 1245 0 stevel return (DCMD_ERR); 1246 0 stevel } 1247 0 stevel 1248 0 stevel if (pt->p_fio == NULL) { 1249 0 stevel mdb_warn("attach requires executable to be specified on " 1250 0 stevel "command-line (or use -p)\n"); 1251 0 stevel return (DCMD_ERR); 1252 0 stevel } 1253 0 stevel 1254 0 stevel if (flags & DCMD_ADDRSPEC) 1255 0 stevel t->t_pshandle = Pgrab((pid_t)addr, pt->p_gflags, &perr); 1256 0 stevel else 1257 0 stevel t->t_pshandle = proc_arg_grab(argv->a_un.a_str, 1258 0 stevel PR_ARG_ANY, pt->p_gflags, &perr); 1259 0 stevel 1260 0 stevel if (t->t_pshandle == NULL) { 1261 0 stevel t->t_pshandle = pt->p_idlehandle; 1262 0 stevel mdb_warn("cannot attach: %s\n", Pgrab_error(perr)); 1263 0 stevel return (DCMD_ERR); 1264 0 stevel } 1265 0 stevel 1266 0 stevel state = Pstate(t->t_pshandle); 1267 0 stevel if (state != PS_DEAD && state != PS_IDLE) { 1268 0 stevel (void) Punsetflags(t->t_pshandle, PR_KLC); 1269 0 stevel (void) Psetflags(t->t_pshandle, PR_RLC); 1270 0 stevel pt_post_attach(t); 1271 0 stevel pt_activate_common(t); 1272 0 stevel } 1273 0 stevel 1274 0 stevel (void) mdb_tgt_status(t, &t->t_status); 1275 0 stevel mdb_module_load_all(0); 1276 0 stevel return (DCMD_OK); 1277 0 stevel } 1278 0 stevel 1279 0 stevel static int 1280 0 stevel pt_regstatus(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1281 0 stevel { 1282 0 stevel mdb_tgt_t *t = mdb.m_target; 1283 0 stevel 1284 0 stevel if (t->t_pshandle != NULL) { 1285 0 stevel const pstatus_t *psp = Pstatus(t->t_pshandle); 1286 0 stevel int cursig = psp->pr_lwp.pr_cursig; 1287 0 stevel char signame[SIG2STR_MAX]; 1288 0 stevel int state = Pstate(t->t_pshandle); 1289 0 stevel 1290 0 stevel if (state != PS_DEAD && state != PS_IDLE) 1291 0 stevel mdb_printf("process id = %d\n", psp->pr_pid); 1292 0 stevel else 1293 0 stevel mdb_printf("no process\n"); 1294 0 stevel 1295 0 stevel if (cursig != 0 && sig2str(cursig, signame) == 0) 1296 0 stevel mdb_printf("SIG%s: %s\n", signame, strsignal(cursig)); 1297 0 stevel } 1298 0 stevel 1299 0 stevel return (pt_regs(addr, flags, argc, argv)); 1300 0 stevel } 1301 0 stevel 1302 0 stevel static int 1303 0 stevel pt_findstack(uintptr_t tid, uint_t flags, int argc, const mdb_arg_t *argv) 1304 0 stevel { 1305 0 stevel mdb_tgt_t *t = mdb.m_target; 1306 0 stevel mdb_tgt_gregset_t gregs; 1307 0 stevel int showargs = 0; 1308 0 stevel int count; 1309 0 stevel uintptr_t pc, sp; 1310 0 stevel 1311 0 stevel if (!(flags & DCMD_ADDRSPEC)) 1312 0 stevel return (DCMD_USAGE); 1313 0 stevel 1314 0 stevel count = mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &showargs, 1315 0 stevel NULL); 1316 0 stevel argc -= count; 1317 0 stevel argv += count; 1318 0 stevel 1319 0 stevel if (argc > 1 || (argc == 1 && argv->a_type != MDB_TYPE_STRING)) 1320 0 stevel return (DCMD_USAGE); 1321 0 stevel 1322 0 stevel if (PTL_GETREGS(t, tid, gregs.gregs) != 0) { 1323 0 stevel mdb_warn("failed to get register set for thread %p", tid); 1324 0 stevel return (DCMD_ERR); 1325 0 stevel } 1326 0 stevel 1327 0 stevel pc = gregs.gregs[R_PC]; 1328 0 stevel #if defined(__i386) || defined(__amd64) 1329 0 stevel sp = gregs.gregs[R_FP]; 1330 0 stevel #else 1331 0 stevel sp = gregs.gregs[R_SP]; 1332 0 stevel #endif 1333 0 stevel mdb_printf("stack pointer for thread %p: %p\n", tid, sp); 1334 0 stevel if (pc != 0) 1335 0 stevel mdb_printf("[ %0?lr %a() ]\n", sp, pc); 1336 0 stevel 1337 0 stevel (void) mdb_inc_indent(2); 1338 0 stevel mdb_set_dot(sp); 1339 0 stevel 1340 0 stevel if (argc == 1) 1341 0 stevel (void) mdb_eval(argv->a_un.a_str); 1342 0 stevel else if (showargs) 1343 0 stevel (void) mdb_eval("<.$C"); 1344 0 stevel else 1345 0 stevel (void) mdb_eval("<.$C0"); 1346 0 stevel 1347 0 stevel (void) mdb_dec_indent(2); 1348 0 stevel return (DCMD_OK); 1349 0 stevel } 1350 0 stevel 1351 0 stevel /*ARGSUSED*/ 1352 0 stevel static int 1353 0 stevel pt_gcore(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1354 0 stevel { 1355 0 stevel mdb_tgt_t *t = mdb.m_target; 1356 0 stevel char *prefix = "core"; 1357 0 stevel char *content_str = NULL; 1358 0 stevel core_content_t content = CC_CONTENT_DEFAULT; 1359 0 stevel size_t size; 1360 0 stevel char *fname; 1361 0 stevel pid_t pid; 1362 0 stevel 1363 0 stevel if (flags & DCMD_ADDRSPEC) 1364 0 stevel return (DCMD_USAGE); 1365 0 stevel 1366 0 stevel if (mdb_getopts(argc, argv, 1367 0 stevel 'o', MDB_OPT_STR, &prefix, 1368 0 stevel 'c', MDB_OPT_STR, &content_str, NULL) != argc) 1369 0 stevel return (DCMD_USAGE); 1370 0 stevel 1371 0 stevel if (content_str != NULL && 1372 0 stevel (proc_str2content(content_str, &content) != 0 || 1373 0 stevel content == CC_CONTENT_INVALID)) { 1374 0 stevel mdb_warn("invalid content string '%s'\n", content_str); 1375 1125 eschrock return (DCMD_ERR); 1376 1125 eschrock } 1377 1125 eschrock 1378 1125 eschrock if (t->t_pshandle == NULL) { 1379 1125 eschrock mdb_warn("no process active\n"); 1380 0 stevel return (DCMD_ERR); 1381 0 stevel } 1382 0 stevel 1383 0 stevel pid = Pstatus(t->t_pshandle)->pr_pid; 1384 0 stevel size = 1 + mdb_snprintf(NULL, 0, "%s.%d", prefix, (int)pid); 1385 0 stevel fname = mdb_alloc(size, UM_SLEEP | UM_GC); 1386 0 stevel (void) mdb_snprintf(fname, size, "%s.%d", prefix, (int)pid); 1387 0 stevel 1388 0 stevel if (Pgcore(t->t_pshandle, fname, content) != 0) { 1389 0 stevel mdb_warn("couldn't dump core"); 1390 0 stevel return (DCMD_ERR); 1391 0 stevel } 1392 0 stevel 1393 0 stevel mdb_warn("%s dumped\n", fname); 1394 0 stevel 1395 0 stevel return (DCMD_OK); 1396 0 stevel } 1397 0 stevel 1398 0 stevel /*ARGSUSED*/ 1399 0 stevel static int 1400 0 stevel pt_kill(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1401 0 stevel { 1402 0 stevel mdb_tgt_t *t = mdb.m_target; 1403 0 stevel pt_data_t *pt = t->t_data; 1404 0 stevel int state; 1405 0 stevel 1406 0 stevel if ((flags & DCMD_ADDRSPEC) || argc != 0) 1407 0 stevel return (DCMD_USAGE); 1408 0 stevel 1409 0 stevel if (t->t_pshandle != NULL && 1410 0 stevel (state = Pstate(t->t_pshandle)) != PS_DEAD && state != PS_IDLE) { 1411 0 stevel mdb_warn("victim process PID %d forcibly terminated\n", 1412 0 stevel (int)Pstatus(t->t_pshandle)->pr_pid); 1413 0 stevel pt_pre_detach(t, TRUE); 1414 0 stevel pt_release_parents(t); 1415 0 stevel Prelease(t->t_pshandle, PRELEASE_KILL); 1416 0 stevel t->t_pshandle = pt->p_idlehandle; 1417 0 stevel (void) mdb_tgt_status(t, &t->t_status); 1418 0 stevel mdb.m_flags &= ~(MDB_FL_VCREATE | MDB_FL_JOBCTL); 1419 0 stevel } else 1420 0 stevel mdb_warn("no victim process is currently under control\n"); 1421 0 stevel 1422 0 stevel return (DCMD_OK); 1423 0 stevel } 1424 0 stevel 1425 0 stevel /*ARGSUSED*/ 1426 0 stevel static int 1427 0 stevel pt_detach(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1428 0 stevel { 1429 0 stevel mdb_tgt_t *t = mdb.m_target; 1430 0 stevel pt_data_t *pt = t->t_data; 1431 0 stevel int rflags = pt->p_rflags; 1432 0 stevel 1433 0 stevel if (argc != 0 && argv->a_type == MDB_TYPE_STRING && 1434 0 stevel strcmp(argv->a_un.a_str, "-a") == 0) { 1435 0 stevel rflags = PRELEASE_HANG | PRELEASE_CLEAR; 1436 0 stevel argv++; 1437 0 stevel argc--; 1438 0 stevel } 1439 0 stevel 1440 0 stevel if ((flags & DCMD_ADDRSPEC) || argc != 0) 1441 0 stevel return (DCMD_USAGE); 1442 0 stevel 1443 0 stevel if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_IDLE) { 1444 0 stevel mdb_warn("debugger is not currently attached to a process " 1445 0 stevel "or core file\n"); 1446 0 stevel return (DCMD_ERR); 1447 0 stevel } 1448 0 stevel 1449 0 stevel pt_pre_detach(t, TRUE); 1450 0 stevel pt_release_parents(t); 1451 0 stevel Prelease(t->t_pshandle, rflags); 1452 0 stevel t->t_pshandle = pt->p_idlehandle; 1453 0 stevel (void) mdb_tgt_status(t, &t->t_status); 1454 0 stevel mdb.m_flags &= ~(MDB_FL_VCREATE | MDB_FL_JOBCTL); 1455 0 stevel 1456 0 stevel return (DCMD_OK); 1457 0 stevel } 1458 0 stevel 1459 0 stevel static uintmax_t 1460 0 stevel reg_disc_get(const mdb_var_t *v) 1461 0 stevel { 1462 0 stevel mdb_tgt_t *t = MDB_NV_COOKIE(v); 1463 0 stevel mdb_tgt_tid_t tid = PTL_TID(t); 1464 0 stevel mdb_tgt_reg_t r = 0; 1465 0 stevel 1466 0 stevel if (tid != (mdb_tgt_tid_t)-1L) 1467 0 stevel (void) mdb_tgt_getareg(t, tid, mdb_nv_get_name(v), &r); 1468 0 stevel 1469 0 stevel return (r); 1470 0 stevel } 1471 0 stevel 1472 0 stevel static void 1473 0 stevel reg_disc_set(mdb_var_t *v, uintmax_t r) 1474 0 stevel { 1475 0 stevel mdb_tgt_t *t = MDB_NV_COOKIE(v); 1476 0 stevel mdb_tgt_tid_t tid = PTL_TID(t); 1477 0 stevel 1478 0 stevel if (tid != (mdb_tgt_tid_t)-1L && mdb_tgt_putareg(t, tid, 1479 0 stevel mdb_nv_get_name(v), r) == -1) 1480 0 stevel mdb_warn("failed to modify %%%s register", mdb_nv_get_name(v)); 1481 0 stevel } 1482 0 stevel 1483 0 stevel static void 1484 0 stevel pt_print_reason(const lwpstatus_t *psp) 1485 0 stevel { 1486 0 stevel char name[SIG2STR_MAX + 4]; /* enough for SIG+name+\0, syscall or flt */ 1487 0 stevel const char *desc; 1488 0 stevel 1489 0 stevel switch (psp->pr_why) { 1490 0 stevel case PR_REQUESTED: 1491 0 stevel mdb_printf("stopped by debugger"); 1492 0 stevel break; 1493 0 stevel case PR_SIGNALLED: 1494 0 stevel mdb_printf("stopped on %s (%s)", proc_signame(psp->pr_what, 1495 0 stevel name, sizeof (name)), strsignal(psp->pr_what)); 1496 0 stevel break; 1497 0 stevel case PR_SYSENTRY: 1498 0 stevel mdb_printf("stopped on entry to %s system call", 1499 0 stevel proc_sysname(psp->pr_what, name, sizeof (name))); 1500 0 stevel break; 1501 0 stevel case PR_SYSEXIT: 1502 0 stevel mdb_printf("stopped on exit from %s system call", 1503 0 stevel proc_sysname(psp->pr_what, name, sizeof (name))); 1504 0 stevel break; 1505 0 stevel case PR_JOBCONTROL: 1506 0 stevel mdb_printf("stopped by job control"); 1507 0 stevel break; 1508 0 stevel case PR_FAULTED: 1509 0 stevel if (psp->pr_what == FLTBPT) { 1510 0 stevel mdb_printf("stopped on a breakpoint"); 1511 0 stevel } else if (psp->pr_what == FLTWATCH) { 1512 0 stevel switch (psp->pr_info.si_code) { 1513 0 stevel case TRAP_RWATCH: 1514 0 stevel desc = "read"; 1515 0 stevel break; 1516 0 stevel case TRAP_WWATCH: 1517 0 stevel desc = "write"; 1518 0 stevel break; 1519 0 stevel case TRAP_XWATCH: 1520 0 stevel desc = "execute"; 1521 0 stevel break; 1522 0 stevel default: 1523 0 stevel desc = "unknown"; 1524 0 stevel } 1525 0 stevel mdb_printf("stopped %s a watchpoint (%s access to %p)", 1526 0 stevel psp->pr_info.si_trapafter ? "after" : "on", 1527 0 stevel desc, psp->pr_info.si_addr); 1528 0 stevel } else if (psp->pr_what == FLTTRACE) { 1529 0 stevel mdb_printf("stopped after a single-step"); 1530 0 stevel } else { 1531 0 stevel mdb_printf("stopped on a %s fault", 1532 0 stevel proc_fltname(psp->pr_what, name, sizeof (name))); 1533 0 stevel } 1534 0 stevel break; 1535 0 stevel case PR_SUSPENDED: 1536 0 stevel case PR_CHECKPOINT: 1537 0 stevel mdb_printf("suspended by the kernel"); 1538 0 stevel break; 1539 0 stevel default: 1540 0 stevel mdb_printf("stopped for unknown reason (%d/%d)", 1541 0 stevel psp->pr_why, psp->pr_what); 1542 0 stevel } 1543 0 stevel } 1544 0 stevel 1545 0 stevel /*ARGSUSED*/ 1546 0 stevel static int 1547 0 stevel pt_status_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1548 0 stevel { 1549 0 stevel mdb_tgt_t *t = mdb.m_target; 1550 0 stevel struct ps_prochandle *P = t->t_pshandle; 1551 0 stevel pt_data_t *pt = t->t_data; 1552 0 stevel 1553 0 stevel if (P != NULL) { 1554 0 stevel const psinfo_t *pip = Ppsinfo(P); 1555 0 stevel const pstatus_t *psp = Pstatus(P); 1556 0 stevel int cursig = 0, bits = 0, coredump = 0; 1557 0 stevel int state; 1558 0 stevel GElf_Sym sym; 1559 0 stevel uintptr_t panicstr; 1560 0 stevel char panicbuf[128]; 1561 7760 Krishnendu const siginfo_t *sip = &(psp->pr_lwp.pr_info); 1562 0 stevel 1563 0 stevel char execname[MAXPATHLEN], buf[BUFSIZ]; 1564 0 stevel char signame[SIG2STR_MAX + 4]; /* enough for SIG+name+\0 */ 1565 0 stevel 1566 0 stevel mdb_tgt_spec_desc_t desc; 1567 0 stevel mdb_sespec_t *sep; 1568 0 stevel 1569 0 stevel struct utsname uts; 1570 0 stevel prcred_t cred; 1571 0 stevel psinfo_t pi; 1572 0 stevel 1573 0 stevel (void) strcpy(uts.nodename, "unknown machine"); 1574 0 stevel (void) Puname(P, &uts); 1575 0 stevel 1576 0 stevel if (pip != NULL) { 1577 0 stevel bcopy(pip, &pi, sizeof (psinfo_t)); 1578 0 stevel proc_unctrl_psinfo(&pi); 1579 0 stevel } else 1580 0 stevel bzero(&pi, sizeof (psinfo_t)); 1581 0 stevel 1582 0 stevel bits = pi.pr_dmodel == PR_MODEL_ILP32 ? 32 : 64; 1583 0 stevel 1584 0 stevel state = Pstate(P); 1585 0 stevel if (psp != NULL && state != PS_UNDEAD && state != PS_IDLE) 1586 0 stevel cursig = psp->pr_lwp.pr_cursig; 1587 0 stevel 1588 0 stevel if (state == PS_DEAD && pip != NULL) { 1589 0 stevel mdb_printf("debugging core file of %s (%d-bit) " 1590 0 stevel "from %s\n", pi.pr_fname, bits, uts.nodename); 1591 0 stevel 1592 0 stevel } else if (state == PS_DEAD) { 1593 0 stevel mdb_printf("debugging core file\n"); 1594 0 stevel 1595 0 stevel } else if (state == PS_IDLE) { 1596 0 stevel const GElf_Ehdr *ehp = &pt->p_file->gf_ehdr; 1597 0 stevel 1598 0 stevel mdb_printf("debugging %s file (%d-bit)\n", 1599 0 stevel ehp->e_type == ET_EXEC ? "executable" : "object", 1600 0 stevel ehp->e_ident[EI_CLASS] == ELFCLASS32 ? 32 : 64); 1601 0 stevel 1602 0 stevel } else if (state == PS_UNDEAD && pi.pr_pid == 0) { 1603 0 stevel mdb_printf("debugging defunct process\n"); 1604 0 stevel 1605 0 stevel } else { 1606 0 stevel mdb_printf("debugging PID %d (%d-bit)\n", 1607 0 stevel pi.pr_pid, bits); 1608 0 stevel } 1609 0 stevel 1610 0 stevel if (Pexecname(P, execname, sizeof (execname)) != NULL) 1611 0 stevel mdb_printf("file: %s\n", execname); 1612 0 stevel 1613 0 stevel if (pip != NULL && state == PS_DEAD) 1614 0 stevel mdb_printf("initial argv: %s\n", pi.pr_psargs); 1615 0 stevel 1616 0 stevel if (state != PS_UNDEAD && state != PS_IDLE) { 1617 0 stevel mdb_printf("threading model: "); 1618 0 stevel if (pt->p_ptl_ops == &proc_lwp_ops) 1619 0 stevel mdb_printf("raw lwps\n"); 1620 0 stevel else 1621 0 stevel mdb_printf("native threads\n"); 1622 0 stevel } 1623 0 stevel 1624 0 stevel mdb_printf("status: "); 1625 0 stevel switch (state) { 1626 0 stevel case PS_RUN: 1627 0 stevel ASSERT(!(psp->pr_flags & PR_STOPPED)); 1628 0 stevel mdb_printf("process is running"); 1629 0 stevel if (psp->pr_flags & PR_DSTOP) 1630 0 stevel mdb_printf(", debugger stop directive pending"); 1631 0 stevel mdb_printf("\n"); 1632 0 stevel break; 1633 0 stevel 1634 0 stevel case PS_STOP: 1635 0 stevel ASSERT(psp->pr_flags & PR_STOPPED); 1636 0 stevel pt_print_reason(&psp->pr_lwp); 1637 0 stevel 1638 0 stevel if (psp->pr_flags & PR_DSTOP) 1639 0 stevel mdb_printf(", debugger stop directive pending"); 1640 0 stevel if (psp->pr_flags & PR_ASLEEP) 1641 0 stevel mdb_printf(", sleeping in %s system call", 1642 0 stevel proc_sysname(psp->pr_lwp.pr_syscall, 1643 0 stevel signame, sizeof (signame))); 1644 0 stevel 1645 0 stevel mdb_printf("\n"); 1646 0 stevel 1647 0 stevel for (sep = t->t_matched; sep != T_SE_END; 1648 0 stevel sep = sep->se_matched) { 1649 0 stevel mdb_printf("event: %s\n", sep->se_ops->se_info( 1650 0 stevel t, sep, mdb_list_next(&sep->se_velist), 1651 0 stevel &desc, buf, sizeof (buf))); 1652 0 stevel } 1653 0 stevel break; 1654 0 stevel 1655 0 stevel case PS_LOST: 1656 0 stevel mdb_printf("debugger lost control of process\n"); 1657 0 stevel break; 1658 0 stevel 1659 0 stevel case PS_UNDEAD: 1660 0 stevel coredump = WIFSIGNALED(pi.pr_wstat) && 1661 0 stevel WCOREDUMP(pi.pr_wstat); 1662 0 stevel /*FALLTHRU*/ 1663 0 stevel 1664 0 stevel case PS_DEAD: 1665 0 stevel if (cursig == 0 && WIFSIGNALED(pi.pr_wstat)) 1666 0 stevel cursig = WTERMSIG(pi.pr_wstat); 1667 0 stevel /* 1668 0 stevel * We can only use pr_wstat == 0 as a test for gcore if 1669 0 stevel * an NT_PRCRED note is present; these features were 1670 0 stevel * added at the same time in Solaris 8. 1671 0 stevel */ 1672 0 stevel if (pi.pr_wstat == 0 && Pstate(P) == PS_DEAD && 1673 0 stevel Pcred(P, &cred, 1) == 0) { 1674 0 stevel mdb_printf("process core file generated " 1675 0 stevel "with gcore(1)\n"); 1676 0 stevel } else if (cursig != 0) { 1677 0 stevel mdb_printf("process terminated by %s (%s)", 1678 0 stevel proc_signame(cursig, signame, 1679 0 stevel sizeof (signame)), strsignal(cursig)); 1680 7760 Krishnendu 1681 7760 Krishnendu if (sip->si_signo != 0 && SI_FROMUSER(sip) && 1682 7760 Krishnendu sip->si_pid != 0) { 1683 7760 Krishnendu mdb_printf(", pid=%d uid=%u", 1684 7760 Krishnendu (int)sip->si_pid, sip->si_uid); 1685 7760 Krishnendu if (sip->si_code != 0) { 1686 7760 Krishnendu mdb_printf(" code=%d", 1687 7760 Krishnendu sip->si_code); 1688 7760 Krishnendu } 1689 7760 Krishnendu } else { 1690 7760 Krishnendu switch (sip->si_signo) { 1691 7760 Krishnendu case SIGILL: 1692 7760 Krishnendu case SIGTRAP: 1693 7760 Krishnendu case SIGFPE: 1694 7760 Krishnendu case SIGSEGV: 1695 7760 Krishnendu case SIGBUS: 1696 7760 Krishnendu case SIGEMT: 1697 7760 Krishnendu mdb_printf(", addr=%p", 1698 7760 Krishnendu sip->si_addr); 1699 7760 Krishnendu default: 1700 7760 Krishnendu break; 1701 7760 Krishnendu } 1702 7760 Krishnendu } 1703 7760 Krishnendu 1704 0 stevel if (coredump) 1705 0 stevel mdb_printf(" - core file dumped"); 1706 0 stevel mdb_printf("\n"); 1707 0 stevel } else { 1708 0 stevel mdb_printf("process terminated with exit " 1709 0 stevel "status %d\n", WEXITSTATUS(pi.pr_wstat)); 1710 0 stevel } 1711 0 stevel 1712 0 stevel if (Plookup_by_name(t->t_pshandle, "libc.so", 1713 0 stevel "panicstr", &sym) == 0 && 1714 0 stevel Pread(t->t_pshandle, &panicstr, sizeof (panicstr), 1715 0 stevel sym.st_value) == sizeof (panicstr) && 1716 0 stevel Pread_string(t->t_pshandle, panicbuf, 1717 0 stevel sizeof (panicbuf), panicstr) > 0) { 1718 0 stevel mdb_printf("panic message: %s", 1719 0 stevel panicbuf); 1720 0 stevel } 1721 0 stevel 1722 0 stevel 1723 0 stevel break; 1724 0 stevel 1725 0 stevel case PS_IDLE: 1726 0 stevel mdb_printf("idle\n"); 1727 0 stevel break; 1728 0 stevel 1729 0 stevel default: 1730 0 stevel mdb_printf("unknown libproc Pstate: %d\n", Pstate(P)); 1731 0 stevel } 1732 0 stevel 1733 0 stevel } else if (pt->p_file != NULL) { 1734 0 stevel const GElf_Ehdr *ehp = &pt->p_file->gf_ehdr; 1735 0 stevel 1736 0 stevel mdb_printf("debugging %s file (%d-bit)\n", 1737 0 stevel ehp->e_type == ET_EXEC ? "executable" : "object", 1738 0 stevel ehp->e_ident[EI_CLASS] == ELFCLASS32 ? 32 : 64); 1739 0 stevel mdb_printf("executable file: %s\n", IOP_NAME(pt->p_fio)); 1740 0 stevel mdb_printf("status: idle\n"); 1741 0 stevel } 1742 0 stevel 1743 0 stevel return (DCMD_OK); 1744 0 stevel } 1745 0 stevel 1746 0 stevel static int 1747 0 stevel pt_tls(uintptr_t tid, uint_t flags, int argc, const mdb_arg_t *argv) 1748 0 stevel { 1749 0 stevel const char *name; 1750 0 stevel const char *object; 1751 0 stevel GElf_Sym sym; 1752 0 stevel mdb_syminfo_t si; 1753 0 stevel mdb_tgt_t *t = mdb.m_target; 1754 0 stevel 1755 0 stevel if (!(flags & DCMD_ADDRSPEC) || argc > 1) 1756 0 stevel return (DCMD_USAGE); 1757 0 stevel 1758 0 stevel if (argc == 0) { 1759 0 stevel psaddr_t b; 1760 0 stevel 1761 0 stevel if (tlsbase(t, tid, PR_LMID_EVERY, MDB_TGT_OBJ_EXEC, &b) != 0) { 1762 0 stevel mdb_warn("failed to lookup tlsbase for %r", tid); 1763 0 stevel return (DCMD_ERR); 1764 0 stevel } 1765 0 stevel 1766 0 stevel mdb_printf("%lr\n", b); 1767 0 stevel mdb_set_dot(b); 1768 0 stevel 1769 0 stevel return (DCMD_OK); 1770 0 stevel } 1771 0 stevel 1772 0 stevel name = argv[0].a_un.a_str; 1773 0 stevel object = MDB_TGT_OBJ_EVERY; 1774 0 stevel 1775 0 stevel if (pt_lookup_by_name_thr(t, object, name, &sym, &si, tid) != 0) { 1776 0 stevel mdb_warn("failed to lookup %s", name); 1777 0 stevel return (DCMD_ABORT); /* avoid repeated failure */ 1778 0 stevel } 1779 0 stevel 1780 0 stevel if (GELF_ST_TYPE(sym.st_info) != STT_TLS && DCMD_HDRSPEC(flags)) 1781 0 stevel mdb_warn("%s does not refer to thread local storage\n", name); 1782 0 stevel 1783 0 stevel mdb_printf("%llr\n", sym.st_value); 1784 0 stevel mdb_set_dot(sym.st_value); 1785 0 stevel 1786 0 stevel return (DCMD_OK); 1787 0 stevel } 1788 0 stevel 1789 0 stevel /*ARGSUSED*/ 1790 0 stevel static int 1791 0 stevel pt_tmodel(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1792 0 stevel { 1793 0 stevel mdb_tgt_t *t = mdb.m_target; 1794 0 stevel pt_data_t *pt = t->t_data; 1795 0 stevel const pt_ptl_ops_t *ptl_ops; 1796 0 stevel 1797 0 stevel if (argc != 1 || argv->a_type != MDB_TYPE_STRING) 1798 0 stevel return (DCMD_USAGE); 1799 0 stevel 1800 0 stevel if (strcmp(argv->a_un.a_str, "thread") == 0) 1801 0 stevel ptl_ops = &proc_tdb_ops; 1802 0 stevel else if (strcmp(argv->a_un.a_str, "lwp") == 0) 1803 0 stevel ptl_ops = &proc_lwp_ops; 1804 0 stevel else 1805 0 stevel return (DCMD_USAGE); 1806 0 stevel 1807 0 stevel if (t->t_pshandle != NULL && pt->p_ptl_ops != ptl_ops) { 1808 0 stevel PTL_DTOR(t); 1809 0 stevel pt->p_tdb_ops = NULL; 1810 0 stevel pt->p_ptl_ops = &proc_lwp_ops; 1811 0 stevel pt->p_ptl_hdl = NULL; 1812 0 stevel 1813 0 stevel if (ptl_ops == &proc_tdb_ops) { 1814 7928 Edward (void) Pobject_iter(t->t_pshandle, (proc_map_f *) 1815 7928 Edward thr_check, t); 1816 0 stevel } 1817 0 stevel } 1818 0 stevel 1819 0 stevel (void) mdb_tgt_status(t, &t->t_status); 1820 0 stevel return (DCMD_OK); 1821 0 stevel } 1822 0 stevel 1823 0 stevel static const char * 1824 0 stevel env_match(const char *cmp, const char *nameval) 1825 0 stevel { 1826 0 stevel const char *loc; 1827 0 stevel size_t cmplen = strlen(cmp); 1828 0 stevel 1829 0 stevel loc = strchr(nameval, '='); 1830 0 stevel if (loc != NULL && (loc - nameval) == cmplen && 1831 0 stevel strncmp(nameval, cmp, cmplen) == 0) { 1832 0 stevel return (loc + 1); 1833 0 stevel } 1834 0 stevel 1835 0 stevel return (NULL); 1836 0 stevel } 1837 0 stevel 1838 0 stevel /*ARGSUSED*/ 1839 0 stevel static int 1840 0 stevel print_env(void *data, struct ps_prochandle *P, uintptr_t addr, 1841 0 stevel const char *nameval) 1842 0 stevel { 1843 0 stevel const char *value; 1844 0 stevel 1845 0 stevel if (nameval == NULL) { 1846 0 stevel mdb_printf("<0x%p>\n", addr); 1847 0 stevel } else { 1848 0 stevel if (data == NULL) 1849 0 stevel mdb_printf("%s\n", nameval); 1850 0 stevel else if ((value = env_match(data, nameval)) != NULL) 1851 0 stevel mdb_printf("%s\n", value); 1852 0 stevel } 1853 0 stevel 1854 0 stevel return (0); 1855 0 stevel } 1856 0 stevel 1857 0 stevel /*ARGSUSED*/ 1858 0 stevel static int 1859 0 stevel pt_getenv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1860 0 stevel { 1861 0 stevel mdb_tgt_t *t = mdb.m_target; 1862 0 stevel pt_data_t *pt = t->t_data; 1863 0 stevel int i; 1864 0 stevel uint_t opt_t = 0; 1865 0 stevel mdb_var_t *v; 1866 0 stevel 1867 0 stevel i = mdb_getopts(argc, argv, 1868 0 stevel 't', MDB_OPT_SETBITS, TRUE, &opt_t, NULL); 1869 0 stevel 1870 0 stevel argc -= i; 1871 0 stevel argv += i; 1872 0 stevel 1873 0 stevel if ((flags & DCMD_ADDRSPEC) || argc > 1) 1874 0 stevel return (DCMD_USAGE); 1875 0 stevel 1876 0 stevel if (argc == 1 && argv->a_type != MDB_TYPE_STRING) 1877 0 stevel return (DCMD_USAGE); 1878 0 stevel 1879 1125 eschrock if (opt_t && t->t_pshandle == NULL) { 1880 1125 eschrock mdb_warn("no process active\n"); 1881 1125 eschrock return (DCMD_ERR); 1882 1125 eschrock } 1883 1125 eschrock 1884 0 stevel if (opt_t && (Pstate(t->t_pshandle) == PS_IDLE || 1885 0 stevel Pstate(t->t_pshandle) == PS_UNDEAD)) { 1886 0 stevel mdb_warn("-t option requires target to be running\n"); 1887 0 stevel return (DCMD_ERR); 1888 0 stevel } 1889 0 stevel 1890 0 stevel if (opt_t != 0) { 1891 0 stevel if (Penv_iter(t->t_pshandle, print_env, 1892 0 stevel argc == 0 ? NULL : (void *)argv->a_un.a_str) != 0) 1893 0 stevel return (DCMD_ERR); 1894 0 stevel } else if (argc == 1) { 1895 0 stevel if ((v = mdb_nv_lookup(&pt->p_env, argv->a_un.a_str)) == NULL) 1896 0 stevel return (DCMD_ERR); 1897 0 stevel 1898 0 stevel ASSERT(strchr(mdb_nv_get_cookie(v), '=') != NULL); 1899 0 stevel mdb_printf("%s\n", strchr(mdb_nv_get_cookie(v), '=') + 1); 1900 0 stevel } else { 1901 0 stevel 1902 0 stevel mdb_nv_rewind(&pt->p_env); 1903 0 stevel while ((v = mdb_nv_advance(&pt->p_env)) != NULL) 1904 0 stevel mdb_printf("%s\n", mdb_nv_get_cookie(v)); 1905 0 stevel } 1906 0 stevel 1907 0 stevel return (DCMD_OK); 1908 0 stevel } 1909 0 stevel 1910 0 stevel /* 1911 0 stevel * Function to set a variable in the internal environment, which is used when 1912 0 stevel * creating new processes. Note that it is possible that 'nameval' can refer to 1913 0 stevel * read-only memory, if mdb calls putenv() on an existing value before calling 1914 0 stevel * this function. While we should avoid this situation, this function is 1915 0 stevel * designed to be robust in the face of such changes. 1916 0 stevel */ 1917 0 stevel static void 1918 0 stevel pt_env_set(pt_data_t *pt, const char *nameval) 1919 0 stevel { 1920 0 stevel mdb_var_t *v; 1921 0 stevel char *equals, *val; 1922 0 stevel const char *name; 1923 0 stevel size_t len; 1924 0 stevel 1925 0 stevel if ((equals = strchr(nameval, '=')) != NULL) { 1926 0 stevel val = strdup(nameval); 1927 0 stevel equals = val + (equals - nameval); 1928 0 stevel } else { 1929 0 stevel /* 1930 0 stevel * nameval doesn't contain an equals character. Convert this to 1931 0 stevel * be 'nameval='. 1932 0 stevel */ 1933 0 stevel len = strlen(nameval); 1934 0 stevel val = mdb_alloc(len + 2, UM_SLEEP); 1935 0 stevel (void) mdb_snprintf(val, len + 2, "%s=", nameval); 1936 0 stevel equals = val + len; 1937 0 stevel } 1938 0 stevel 1939 0 stevel /* temporary truncate the string for lookup/insert */ 1940 0 stevel *equals = '\0'; 1941 0 stevel v = mdb_nv_lookup(&pt->p_env, val); 1942 0 stevel 1943 0 stevel if (v != NULL) { 1944 0 stevel char *old = mdb_nv_get_cookie(v); 1945 0 stevel mdb_free(old, strlen(old) + 1); 1946 0 stevel name = mdb_nv_get_name(v); 1947 0 stevel } else { 1948 0 stevel /* 1949 0 stevel * The environment is created using MDB_NV_EXTNAME, so we must 1950 0 stevel * provide external storage for the variable names. 1951 0 stevel */ 1952 0 stevel name = strdup(val); 1953 0 stevel } 1954 0 stevel 1955 0 stevel *equals = '='; 1956 0 stevel 1957 0 stevel (void) mdb_nv_insert(&pt->p_env, name, NULL, (uintptr_t)val, 1958 0 stevel MDB_NV_EXTNAME); 1959 0 stevel 1960 0 stevel if (equals) 1961 0 stevel *equals = '='; 1962 0 stevel } 1963 0 stevel 1964 0 stevel /* 1965 0 stevel * Clears the internal environment. 1966 0 stevel */ 1967 0 stevel static void 1968 0 stevel pt_env_clear(pt_data_t *pt) 1969 0 stevel { 1970 0 stevel mdb_var_t *v; 1971 0 stevel char *val, *name; 1972 0 stevel 1973 0 stevel mdb_nv_rewind(&pt->p_env); 1974 0 stevel while ((v = mdb_nv_advance(&pt->p_env)) != NULL) { 1975 0 stevel 1976 0 stevel name = (char *)mdb_nv_get_name(v); 1977 0 stevel val = mdb_nv_get_cookie(v); 1978 0 stevel 1979 0 stevel mdb_nv_remove(&pt->p_env, v); 1980 0 stevel 1981 0 stevel mdb_free(name, strlen(name) + 1); 1982 0 stevel mdb_free(val, strlen(val) + 1); 1983 0 stevel } 1984 0 stevel } 1985 0 stevel 1986 0 stevel /*ARGSUSED*/ 1987 0 stevel static int 1988 0 stevel pt_setenv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1989 0 stevel { 1990 0 stevel mdb_tgt_t *t = mdb.m_target; 1991 0 stevel pt_data_t *pt = t->t_data; 1992 0 stevel char *nameval; 1993 0 stevel size_t len; 1994 0 stevel int alloc; 1995 0 stevel 1996 0 stevel if ((flags & DCMD_ADDRSPEC) || argc == 0 || argc > 2) 1997 0 stevel return (DCMD_USAGE); 1998 0 stevel 1999 0 stevel if ((argc > 0 && argv[0].a_type != MDB_TYPE_STRING) || 2000 0 stevel (argc > 1 && argv[1].a_type != MDB_TYPE_STRING)) 2001 0 stevel return (DCMD_USAGE); 2002 0 stevel 2003 1125 eschrock if (t->t_pshandle == NULL) { 2004 1125 eschrock mdb_warn("no process active\n"); 2005 1125 eschrock return (DCMD_ERR); 2006 1125 eschrock } 2007 1125 eschrock 2008 0 stevel /* 2009 0 stevel * If the process is in some sort of running state, warn the user that 2010 0 stevel * changes won't immediately take effect. 2011 0 stevel */ 2012 0 stevel if (Pstate(t->t_pshandle) == PS_RUN || 2013 0 stevel Pstate(t->t_pshandle) == PS_STOP) { 2014 0 stevel mdb_warn("warning: changes will not take effect until process" 2015 0 stevel " is restarted\n"); 2016 0 stevel } 2017 0 stevel 2018 0 stevel /* 2019 0 stevel * We allow two forms of operation. The first is the usual "name=value" 2020 0 stevel * parameter. We also allow the user to specify two arguments, where 2021 0 stevel * the first is the name of the variable, and the second is the value. 2022 0 stevel */ 2023 0 stevel alloc = 0; 2024 0 stevel if (argc == 1) { 2025 0 stevel nameval = (char *)argv->a_un.a_str; 2026 0 stevel } else { 2027 0 stevel len = strlen(argv[0].a_un.a_str) + 2028 0 stevel strlen(argv[1].a_un.a_str) + 2; 2029 0 stevel nameval = mdb_alloc(len, UM_SLEEP); 2030 0 stevel (void) mdb_snprintf(nameval, len, "%s=%s", argv[0].a_un.a_str, 2031 0 stevel argv[1].a_un.a_str); 2032 0 stevel alloc = 1; 2033 0 stevel } 2034 0 stevel 2035 0 stevel pt_env_set(pt, nameval); 2036 0 stevel 2037 0 stevel if (alloc) 2038 0 stevel mdb_free(nameval, strlen(nameval) + 1); 2039 0 stevel 2040 0 stevel return (DCMD_OK); 2041 0 stevel } 2042 0 stevel 2043 0 stevel /*ARGSUSED*/ 2044 0 stevel static int 2045 0 stevel pt_unsetenv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2046 0 stevel { 2047 0 stevel mdb_tgt_t *t = mdb.m_target; 2048 0 stevel pt_data_t *pt = t->t_data; 2049 0 stevel mdb_var_t *v; 2050 0 stevel char *value, *name; 2051 0 stevel 2052 0 stevel if ((flags & DCMD_ADDRSPEC) || argc > 1) 2053 0 stevel return (DCMD_USAGE); 2054 0 stevel 2055 0 stevel if (argc == 1 && argv->a_type != MDB_TYPE_STRING) 2056 0 stevel return (DCMD_USAGE); 2057 1125 eschrock 2058 1125 eschrock if (t->t_pshandle == NULL) { 2059 1125 eschrock mdb_warn("no process active\n"); 2060 1125 eschrock return (DCMD_ERR); 2061 1125 eschrock } 2062 0 stevel 2063 0 stevel /* 2064 0 stevel * If the process is in some sort of running state, warn the user that 2065 0 stevel * changes won't immediately take effect. 2066 0 stevel */ 2067 0 stevel if (Pstate(t->t_pshandle) == PS_RUN || 2068 0 stevel Pstate(t->t_pshandle) == PS_STOP) { 2069 0 stevel mdb_warn("warning: changes will not take effect until process" 2070 0 stevel " is restarted\n"); 2071 0 stevel } 2072 0 stevel 2073 0 stevel if (argc == 0) { 2074 0 stevel pt_env_clear(pt); 2075 0 stevel } else { 2076 0 stevel if ((v = mdb_nv_lookup(&pt->p_env, argv->a_un.a_str)) != NULL) { 2077 0 stevel name = (char *)mdb_nv_get_name(v); 2078 0 stevel value = mdb_nv_get_cookie(v); 2079 0 stevel 2080 0 stevel mdb_nv_remove(&pt->p_env, v); 2081 0 stevel 2082 0 stevel mdb_free(name, strlen(name) + 1); 2083 0 stevel mdb_free(value, strlen(value) + 1); 2084 0 stevel } 2085 0 stevel } 2086 0 stevel 2087 0 stevel return (DCMD_OK); 2088 0 stevel } 2089 0 stevel 2090 5987 johnlev void 2091 5987 johnlev getenv_help(void) 2092 5987 johnlev { 2093 5987 johnlev mdb_printf("-t show current process environment" 2094 5987 johnlev " instead of initial environment.\n"); 2095 5987 johnlev } 2096 5987 johnlev 2097 0 stevel static const mdb_dcmd_t pt_dcmds[] = { 2098 0 stevel { "$c", "?[cnt]", "print stack backtrace", pt_stack }, 2099 0 stevel { "$C", "?[cnt]", "print stack backtrace", pt_stackv }, 2100 0 stevel { "$i", NULL, "print signals that are ignored", pt_ignored }, 2101 0 stevel { "$l", NULL, "print the representative thread's lwp id", pt_lwpid }, 2102 0 stevel { "$L", NULL, "print list of the active lwp ids", pt_lwpids }, 2103 0 stevel { "$r", "?", "print general-purpose registers", pt_regs }, 2104 0 stevel { "$x", "?", "print floating point registers", pt_fpregs }, 2105 0 stevel { "$X", "?", "print floating point registers", pt_fpregs }, 2106 0 stevel { "$y", "?", "print floating point registers", pt_fpregs }, 2107 0 stevel { "$Y", "?", "print floating point registers", pt_fpregs }, 2108 0 stevel { "$?", "?", "print status and registers", pt_regstatus }, 2109 0 stevel { ":A", "?[core|pid]", "attach to process or core file", pt_attach }, 2110 0 stevel { ":i", ":", "ignore signal (delete all matching events)", pt_ignore }, 2111 0 stevel { ":k", NULL, "forcibly kill and release target", pt_kill }, 2112 0 stevel { ":R", "[-a]", "release the previously attached process", pt_detach }, 2113 0 stevel { "attach", "?[core|pid]", 2114 0 stevel "attach to process or core file", pt_attach }, 2115 0 stevel { "findstack", ":[-v]", "find user thread stack", pt_findstack }, 2116 0 stevel { "gcore", "[-o prefix] [-c content]", 2117 0 stevel "produce a core file for the attached process", pt_gcore }, 2118 0 stevel { "getenv", "[-t] [name]", "display an environment variable", 2119 5987 johnlev pt_getenv, getenv_help }, 2120 0 stevel { "kill", NULL, "forcibly kill and release target", pt_kill }, 2121 0 stevel { "release", "[-a]", 2122 0 stevel "release the previously attached process", pt_detach }, 2123 0 stevel { "regs", "?", "print general-purpose registers", pt_regs }, 2124 0 stevel { "fpregs", "?[-dqs]", "print floating point registers", pt_fpregs }, 2125 0 stevel { "setenv", "name=value", "set an environment variable", pt_setenv }, 2126 0 stevel { "stack", "?[cnt]", "print stack backtrace", pt_stack }, 2127 0 stevel { "stackregs", "?", "print stack backtrace and registers", pt_stackr }, 2128 0 stevel { "status", NULL, "print summary of current target", pt_status_dcmd }, 2129 0 stevel { "tls", ":symbol", 2130 0 stevel "lookup TLS data in the context of a given thread", pt_tls }, 2131 0 stevel { "tmodel", "{thread|lwp}", NULL, pt_tmodel }, 2132 0 stevel { "unsetenv", "[name]", "clear an environment variable", pt_unsetenv }, 2133 0 stevel { NULL } 2134 0 stevel }; 2135 0 stevel 2136 0 stevel static void 2137 0 stevel pt_thr_walk_fini(mdb_walk_state_t *wsp) 2138 0 stevel { 2139 0 stevel mdb_addrvec_destroy(wsp->walk_data); 2140 0 stevel mdb_free(wsp->walk_data, sizeof (mdb_addrvec_t)); 2141 0 stevel } 2142 0 stevel 2143 0 stevel static int 2144 0 stevel pt_thr_walk_init(mdb_walk_state_t *wsp) 2145 0 stevel { 2146 0 stevel wsp->walk_data = mdb_zalloc(sizeof (mdb_addrvec_t), UM_SLEEP); 2147 0 stevel mdb_addrvec_create(wsp->walk_data); 2148 0 stevel 2149 0 stevel if (PTL_ITER(mdb.m_target, wsp->walk_data) == -1) { 2150 0 stevel mdb_warn("failed to iterate over threads"); 2151 0 stevel pt_thr_walk_fini(wsp); 2152 0 stevel return (WALK_ERR); 2153 0 stevel } 2154 0 stevel 2155 0 stevel return (WALK_NEXT); 2156 0 stevel } 2157 0 stevel 2158 0 stevel static int 2159 0 stevel pt_thr_walk_step(mdb_walk_state_t *wsp) 2160 0 stevel { 2161 0 stevel if (mdb_addrvec_length(wsp->walk_data) != 0) { 2162 0 stevel return (wsp->walk_callback(mdb_addrvec_shift(wsp->walk_data), 2163 0 stevel NULL, wsp->walk_cbdata)); 2164 0 stevel } 2165 0 stevel return (WALK_DONE); 2166 0 stevel } 2167 0 stevel 2168 0 stevel static const mdb_walker_t pt_walkers[] = { 2169 0 stevel { "thread", "walk list of valid thread identifiers", 2170 0 stevel pt_thr_walk_init, pt_thr_walk_step, pt_thr_walk_fini }, 2171 0 stevel { NULL } 2172 0 stevel }; 2173 0 stevel 2174 0 stevel 2175 0 stevel static void 2176 0 stevel pt_activate_common(mdb_tgt_t *t) 2177 0 stevel { 2178 0 stevel pt_data_t *pt = t->t_data; 2179 0 stevel GElf_Sym sym; 2180 0 stevel 2181 0 stevel /* 2182 0 stevel * If we have a libproc handle and AT_BASE is set, the process or core 2183 0 stevel * is dynamically linked. We call Prd_agent() to force libproc to 2184 0 stevel * try to initialize librtld_db, and issue a warning if that fails. 2185 0 stevel */ 2186 0 stevel if (t->t_pshandle != NULL && Pgetauxval(t->t_pshandle, 2187 0 stevel AT_BASE) != -1L && Prd_agent(t->t_pshandle) == NULL) { 2188 0 stevel mdb_warn("warning: librtld_db failed to initialize; shared " 2189 0 stevel "library information will not be available\n"); 2190 0 stevel } 2191 0 stevel 2192 0 stevel /* 2193 0 stevel * If we have a libproc handle and libthread is loaded, attempt to load 2194 0 stevel * and initialize the corresponding libthread_db. If this fails, fall 2195 0 stevel * back to our native LWP implementation and issue a warning. 2196 0 stevel */ 2197 7928 Edward if (t->t_pshandle != NULL && Pstate(t->t_pshandle) != PS_IDLE) 2198 7928 Edward (void) Pobject_iter(t->t_pshandle, (proc_map_f *)thr_check, t); 2199 0 stevel 2200 0 stevel /* 2201 0 stevel * If there's a global object named '_mdb_abort_info', assuming we're 2202 0 stevel * debugging mdb itself and load the developer support module. 2203 0 stevel */ 2204 0 stevel if (mdb_gelf_symtab_lookup_by_name(pt->p_symtab, "_mdb_abort_info", 2205 0 stevel &sym, NULL) == 0 && GELF_ST_TYPE(sym.st_info) == STT_OBJECT) { 2206 0 stevel if (mdb_module_load("mdb_ds", MDB_MOD_SILENT) < 0) 2207 0 stevel mdb_warn("warning: failed to load developer support\n"); 2208 0 stevel } 2209 0 stevel 2210 0 stevel mdb_tgt_elf_export(pt->p_file); 2211 0 stevel } 2212 0 stevel 2213 0 stevel static void 2214 0 stevel pt_activate(mdb_tgt_t *t) 2215 0 stevel { 2216 0 stevel static const mdb_nv_disc_t reg_disc = { reg_disc_set, reg_disc_get }; 2217 0 stevel 2218 0 stevel pt_data_t *pt = t->t_data; 2219 0 stevel struct utsname u1, u2; 2220 0 stevel mdb_var_t *v; 2221 0 stevel core_content_t content; 2222 0 stevel 2223 0 stevel if (t->t_pshandle) { 2224 0 stevel mdb_prop_postmortem = (Pstate(t->t_pshandle) == PS_DEAD); 2225 0 stevel mdb_prop_kernel = FALSE; 2226 0 stevel } else 2227 0 stevel mdb_prop_kernel = mdb_prop_postmortem = FALSE; 2228 0 stevel 2229 0 stevel mdb_prop_datamodel = MDB_TGT_MODEL_NATIVE; 2230 0 stevel 2231 0 stevel /* 2232 0 stevel * If we're examining a core file that doesn't contain program text, 2233 0 stevel * and uname(2) doesn't match the NT_UTSNAME note recorded in the 2234 0 stevel * core file, issue a warning. 2235 0 stevel */ 2236 0 stevel if (mdb_prop_postmortem == TRUE && 2237 0 stevel ((content = Pcontent(t->t_pshandle)) == CC_CONTENT_INVALID || 2238 0 stevel !(content & CC_CONTENT_TEXT)) && 2239 0 stevel uname(&u1) >= 0 && Puname(t->t_pshandle, &u2) == 0 && 2240 0 stevel (strcmp(u1.release, u2.release) != 0 || 2241 0 stevel strcmp(u1.version, u2.version) != 0)) { 2242 0 stevel mdb_warn("warning: core file is from %s %s %s; shared text " 2243 0 stevel "mappings may not match installed libraries\n", 2244 0 stevel u2.sysname, u2.release, u2.version); 2245 0 stevel } 2246 0 stevel 2247 0 stevel /* 2248 0 stevel * Perform the common initialization tasks -- these are shared with 2249 0 stevel * the pt_exec() and pt_run() subroutines. 2250 0 stevel */ 2251 0 stevel pt_activate_common(t); 2252 0 stevel 2253 0 stevel (void) mdb_tgt_register_dcmds(t, &pt_dcmds[0], MDB_MOD_FORCE); 2254 0 stevel (void) mdb_tgt_register_walkers(t, &pt_walkers[0], MDB_MOD_FORCE); 2255 0 stevel 2256 0 stevel /* 2257 0 stevel * Iterate through our register description list and export 2258 0 stevel * each register as a named variable. 2259 0 stevel */ 2260 0 stevel mdb_nv_rewind(&pt->p_regs); 2261 0 stevel while ((v = mdb_nv_advance(&pt->p_regs)) != NULL) { 2262 0 stevel ushort_t rd_flags = MDB_TGT_R_FLAGS(mdb_nv_get_value(v)); 2263 0 stevel 2264 0 stevel if (!(rd_flags & MDB_TGT_R_EXPORT)) 2265 0 stevel continue; /* Don't export register as a variable */ 2266 0 stevel 2267 0 stevel (void) mdb_nv_insert(&mdb.m_nv, mdb_nv_get_name(v), ®_disc, 2268 0 stevel (uintptr_t)t, MDB_NV_PERSIST); 2269 0 stevel } 2270 0 stevel } 2271 0 stevel 2272 0 stevel static void 2273 0 stevel pt_deactivate(mdb_tgt_t *t) 2274 0 stevel { 2275 0 stevel pt_data_t *pt = t->t_data; 2276 0 stevel const mdb_dcmd_t *dcp; 2277 0 stevel const mdb_walker_t *wp; 2278 0 stevel mdb_var_t *v, *w; 2279 0 stevel 2280 0 stevel mdb_nv_rewind(&pt->p_regs); 2281 0 stevel while ((v = mdb_nv_advance(&pt->p_regs)) != NULL) { 2282 0 stevel ushort_t rd_flags = MDB_TGT_R_FLAGS(mdb_nv_get_value(v)); 2283 0 stevel 2284 0 stevel if (!(rd_flags & MDB_TGT_R_EXPORT)) 2285 0 stevel continue; /* Didn't export register as a variable */ 2286 0 stevel 2287 0 stevel if (w = mdb_nv_lookup(&mdb.m_nv, mdb_nv_get_name(v))) { 2288 0 stevel w->v_flags &= ~MDB_NV_PERSIST; 2289 0 stevel mdb_nv_remove(&mdb.m_nv, w); 2290 0 stevel } 2291 0 stevel } 2292 0 stevel 2293 0 stevel for (wp = &pt_walkers[0]; wp->walk_name != NULL; wp++) { 2294 0 stevel if (mdb_module_remove_walker(t->t_module, wp->walk_name) == -1) 2295 0 stevel warn("failed to remove walk %s", wp->walk_name); 2296 0 stevel } 2297 0 stevel 2298 0 stevel for (dcp = &pt_dcmds[0]; dcp->dc_name != NULL; dcp++) { 2299 0 stevel if (mdb_module_remove_dcmd(t->t_module, dcp->dc_name) == -1) 2300 0 stevel warn("failed to remove dcmd %s", dcp->dc_name); 2301 0 stevel } 2302 0 stevel 2303 0 stevel mdb_prop_postmortem = FALSE; 2304 0 stevel mdb_prop_kernel = FALSE; 2305 0 stevel mdb_prop_datamodel = MDB_TGT_MODEL_UNKNOWN; 2306 0 stevel } 2307 0 stevel 2308 0 stevel static void 2309 0 stevel pt_periodic(mdb_tgt_t *t) 2310 0 stevel { 2311 0 stevel pt_data_t *pt = t->t_data; 2312 0 stevel 2313 0 stevel if (pt->p_rdstate == PT_RD_CONSIST) { 2314 0 stevel if (t->t_pshandle != NULL && Pstate(t->t_pshandle) < PS_LOST && 2315 0 stevel !(mdb.m_flags & MDB_FL_NOMODS)) { 2316 0 stevel mdb_printf("%s: You've got symbols!\n", mdb.m_pname); 2317 0 stevel mdb_module_load_all(0); 2318 0 stevel } 2319 0 stevel pt->p_rdstate = PT_RD_NONE; 2320 0 stevel } 2321 0 stevel } 2322 0 stevel 2323 0 stevel static void 2324 0 stevel pt_destroy(mdb_tgt_t *t) 2325 0 stevel { 2326 0 stevel pt_data_t *pt = t->t_data; 2327 0 stevel 2328 0 stevel if (pt->p_idlehandle != NULL && pt->p_idlehandle != t->t_pshandle) 2329 0 stevel Prelease(pt->p_idlehandle, 0); 2330 0 stevel 2331 0 stevel if (t->t_pshandle != NULL) { 2332 0 stevel PTL_DTOR(t); 2333 0 stevel pt_release_parents(t); 2334 0 stevel pt_pre_detach(t, TRUE); 2335 0 stevel Prelease(t->t_pshandle, pt->p_rflags); 2336 0 stevel } 2337 0 stevel 2338 0 stevel mdb.m_flags &= ~(MDB_FL_VCREATE | MDB_FL_JOBCTL); 2339 0 stevel pt_close_aout(t); 2340 0 stevel 2341 0 stevel if (pt->p_aout_fio != NULL) 2342 0 stevel mdb_io_rele(pt->p_aout_fio); 2343 0 stevel 2344 0 stevel pt_env_clear(pt); 2345 0 stevel mdb_nv_destroy(&pt->p_env); 2346 0 stevel 2347 0 stevel mdb_nv_destroy(&pt->p_regs); 2348 0 stevel mdb_free(pt, sizeof (pt_data_t)); 2349 0 stevel } 2350 0 stevel 2351 0 stevel /*ARGSUSED*/ 2352 0 stevel static const char * 2353 0 stevel pt_name(mdb_tgt_t *t) 2354 0 stevel { 2355 0 stevel return ("proc"); 2356 0 stevel } 2357 0 stevel 2358 0 stevel static const char * 2359 0 stevel pt_platform(mdb_tgt_t *t) 2360 0 stevel { 2361 0 stevel pt_data_t *pt = t->t_data; 2362 0 stevel 2363 0 stevel if (t->t_pshandle != NULL && 2364 0 stevel Pplatform(t->t_pshandle, pt->p_platform, MAXNAMELEN) != NULL) 2365 0 stevel return (pt->p_platform); 2366 0 stevel 2367 0 stevel return (mdb_conf_platform()); 2368 0 stevel } 2369 0 stevel 2370 0 stevel static int 2371 0 stevel pt_uname(mdb_tgt_t *t, struct utsname *utsp) 2372 0 stevel { 2373 0 stevel if (t->t_pshandle != NULL) 2374 0 stevel return (Puname(t->t_pshandle, utsp)); 2375 0 stevel 2376 0 stevel return (uname(utsp) >= 0 ? 0 : -1); 2377 0 stevel } 2378 0 stevel 2379 0 stevel static int 2380 0 stevel pt_dmodel(mdb_tgt_t *t) 2381 0 stevel { 2382 0 stevel if (t->t_pshandle == NULL) 2383 0 stevel return (MDB_TGT_MODEL_NATIVE); 2384 0 stevel 2385 0 stevel switch (Pstatus(t->t_pshandle)->pr_dmodel) { 2386 0 stevel case PR_MODEL_ILP32: 2387 0 stevel return (MDB_TGT_MODEL_ILP32); 2388 0 stevel case PR_MODEL_LP64: 2389 0 stevel return (MDB_TGT_MODEL_LP64); 2390 0 stevel } 2391 0 stevel 2392 0 stevel return (MDB_TGT_MODEL_UNKNOWN); 2393 0 stevel } 2394 0 stevel 2395 0 stevel static ssize_t 2396 0 stevel pt_vread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr) 2397 0 stevel { 2398 0 stevel ssize_t n; 2399 0 stevel 2400 0 stevel /* 2401 0 stevel * If no handle is open yet, reads from virtual addresses are 2402 0 stevel * allowed to succeed but return zero-filled memory. 2403 0 stevel */ 2404 0 stevel if (t->t_pshandle == NULL) { 2405 0 stevel bzero(buf, nbytes); 2406 0 stevel return (nbytes); 2407 0 stevel } 2408 0 stevel 2409 0 stevel if ((n = Pread(t->t_pshandle, buf, nbytes, addr)) <= 0) 2410 0 stevel return (set_errno(EMDB_NOMAP)); 2411 0 stevel 2412 0 stevel return (n); 2413 0 stevel } 2414 0 stevel 2415 0 stevel static ssize_t 2416 0 stevel pt_vwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr) 2417 0 stevel { 2418 0 stevel ssize_t n; 2419 0 stevel 2420 0 stevel /* 2421 0 stevel * If no handle is open yet, writes to virtual addresses are 2422 0 stevel * allowed to succeed but do not actually modify anything. 2423 0 stevel */ 2424 0 stevel if (t->t_pshandle == NULL) 2425 0 stevel return (nbytes); 2426 0 stevel 2427 0 stevel n = Pwrite(t->t_pshandle, buf, nbytes, addr); 2428 0 stevel 2429 0 stevel if (n == -1 && errno == EIO) 2430 0 stevel return (set_errno(EMDB_NOMAP)); 2431 0 stevel 2432 0 stevel return (n); 2433 0 stevel } 2434 0 stevel 2435 0 stevel static ssize_t 2436 0 stevel pt_fread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr) 2437 0 stevel { 2438 0 stevel pt_data_t *pt = t->t_data; 2439 0 stevel 2440 0 stevel if (pt->p_file != NULL) { 2441 0 stevel return (mdb_gelf_rw(pt->p_file, buf, nbytes, addr, 2442 0 stevel IOPF_READ(pt->p_fio), GIO_READ)); 2443 0 stevel } 2444 0 stevel 2445 0 stevel bzero(buf, nbytes); 2446 0 stevel return (nbytes); 2447 0 stevel } 2448 0 stevel 2449 0 stevel static ssize_t 2450 0 stevel pt_fwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr) 2451 0 stevel { 2452 0 stevel pt_data_t *pt = t->t_data; 2453 0 stevel 2454 0 stevel if (pt->p_file != NULL) { 2455 0 stevel return (mdb_gelf_rw(pt->p_file, (void *)buf, nbytes, addr, 2456 0 stevel IOPF_WRITE(pt->p_fio), GIO_WRITE)); 2457 0 stevel } 2458 0 stevel 2459 0 stevel return (nbytes); 2460 0 stevel } 2461 0 stevel 2462 0 stevel static const char * 2463 0 stevel pt_resolve_lmid(const char *object, Lmid_t *lmidp) 2464 0 stevel { 2465 0 stevel Lmid_t lmid = PR_LMID_EVERY; 2466 0 stevel const char *p; 2467 0 stevel 2468 0 stevel if (object == MDB_TGT_OBJ_EVERY || object == MDB_TGT_OBJ_EXEC) 2469 0 stevel lmid = LM_ID_BASE; /* restrict scope to a.out's link map */ 2470 0 stevel else if (object != MDB_TGT_OBJ_RTLD && strncmp(object, "LM", 2) == 0 && 2471 0 stevel (p = strchr(object, '`')) != NULL) { 2472 0 stevel object += 2; /* skip past initial "LM" prefix */ 2473 0 stevel lmid = strntoul(object, (size_t)(p - object), mdb.m_radix); 2474 0 stevel object = p + 1; /* skip past link map specifier */ 2475 0 stevel } 2476 0 stevel 2477 0 stevel *lmidp = lmid; 2478 0 stevel return (object); 2479 0 stevel } 2480 0 stevel 2481 0 stevel static int 2482 0 stevel tlsbase(mdb_tgt_t *t, mdb_tgt_tid_t tid, Lmid_t lmid, const char *object, 2483 0 stevel psaddr_t *basep) 2484 0 stevel { 2485 0 stevel pt_data_t *pt = t->t_data; 2486 0 stevel const rd_loadobj_t *loadobjp; 2487 0 stevel td_thrhandle_t th; 2488 0 stevel td_err_e err; 2489 0 stevel 2490 0 stevel if (object == MDB_TGT_OBJ_EVERY) 2491 0 stevel return (set_errno(EINVAL)); 2492 0 stevel 2493 0 stevel if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_IDLE) 2494 0 stevel return (set_errno(EMDB_NOPROC)); 2495 0 stevel 2496 0 stevel if (pt->p_tdb_ops == NULL) 2497 0 stevel return (set_errno(EMDB_TDB)); 2498 0 stevel 2499 0 stevel err = pt->p_tdb_ops->td_ta_map_id2thr(pt->p_ptl_hdl, tid, &th); 2500 0 stevel if (err != TD_OK) 2501 0 stevel return (set_errno(tdb_to_errno(err))); 2502 0 stevel 2503 0 stevel /* 2504 0 stevel * If this fails, rtld_db has failed to initialize properly. 2505 0 stevel */ 2506 0 stevel if ((loadobjp = Plmid_to_loadobj(t->t_pshandle, lmid, object)) == NULL) 2507 0 stevel return (set_errno(EMDB_NORTLD)); 2508 0 stevel 2509 0 stevel /* 2510 0 stevel * This will fail if the TLS block has not been allocated for the 2511 0 stevel * object that contains the TLS symbol in question. 2512 0 stevel */ 2513 0 stevel err = pt->p_tdb_ops->td_thr_tlsbase(&th, loadobjp->rl_tlsmodid, basep); 2514 0 stevel if (err != TD_OK) 2515 0 stevel return (set_errno(tdb_to_errno(err))); 2516 0 stevel 2517 0 stevel return (0); 2518 0 stevel } 2519 0 stevel 2520 0 stevel typedef struct { 2521 0 stevel mdb_tgt_t *pl_tgt; 2522 0 stevel const char *pl_name; 2523 0 stevel Lmid_t pl_lmid; 2524 0 stevel GElf_Sym *pl_symp; 2525 0 stevel mdb_syminfo_t *pl_sip; 2526 0 stevel mdb_tgt_tid_t pl_tid; 2527 0 stevel mdb_bool_t pl_found; 2528 0 stevel } pt_lookup_t; 2529 0 stevel 2530 0 stevel /*ARGSUSED*/ 2531 0 stevel static int 2532 0 stevel pt_lookup_cb(void *data, const prmap_t *pmp, const char *object) 2533 0 stevel { 2534 0 stevel pt_lookup_t *plp = data; 2535 0 stevel struct ps_prochandle *P = plp->pl_tgt->t_pshandle; 2536 0 stevel prsyminfo_t si; 2537 0 stevel GElf_Sym sym; 2538 0 stevel 2539 0 stevel if (Pxlookup_by_name(P, plp->pl_lmid, object, plp->pl_name, &sym, 2540 0 stevel &si) != 0) 2541 0 stevel return (0); 2542 0 stevel 2543 0 stevel /* 2544 0 stevel * If we encounter a match with SHN_UNDEF, keep looking for a 2545 0 stevel * better match. Return the first match with SHN_UNDEF set if no 2546 0 stevel * better match is found. 2547 0 stevel */ 2548 0 stevel if (sym.st_shndx == SHN_UNDEF) { 2549 0 stevel if (!plp->pl_found) { 2550 0 stevel plp->pl_found = TRUE; 2551 0 stevel *plp->pl_symp = sym; 2552 0 stevel plp->pl_sip->sym_table = si.prs_table; 2553 0 stevel plp->pl_sip->sym_id = si.prs_id; 2554 0 stevel } 2555 0 stevel 2556 0 stevel return (0); 2557 0 stevel } 2558 0 stevel 2559 0 stevel /* 2560 0 stevel * Note that if the symbol's st_shndx is SHN_UNDEF we don't have the 2561 0 stevel * TLS offset anyway, so adding in the tlsbase would be worthless. 2562 0 stevel */ 2563 0 stevel if (GELF_ST_TYPE(sym.st_info) == STT_TLS && 2564 0 stevel plp->pl_tid != (mdb_tgt_tid_t)-1) { 2565 0 stevel psaddr_t base; 2566 0 stevel 2567 0 stevel if (tlsbase(plp->pl_tgt, plp->pl_tid, plp->pl_lmid, object, 2568 0 stevel &base) != 0) 2569 0 stevel return (-1); /* errno is set for us */ 2570 0 stevel 2571 0 stevel sym.st_value += base; 2572 0 stevel } 2573 0 stevel 2574 0 stevel plp->pl_found = TRUE; 2575 0 stevel *plp->pl_symp = sym; 2576 0 stevel plp->pl_sip->sym_table = si.prs_table; 2577 0 stevel plp->pl_sip->sym_id = si.prs_id; 2578 0 stevel 2579 0 stevel return (1); 2580 0 stevel } 2581 0 stevel 2582 0 stevel /* 2583 0 stevel * Lookup the symbol with a thread context so that we can adjust TLS symbols 2584 0 stevel * to get the values as they would appear in the context of the given thread. 2585 0 stevel */ 2586 0 stevel static int 2587 0 stevel pt_lookup_by_name_thr(mdb_tgt_t *t, const char *object, 2588 0 stevel const char *name, GElf_Sym *symp, mdb_syminfo_t *sip, mdb_tgt_tid_t tid) 2589 0 stevel { 2590 0 stevel struct ps_prochandle *P = t->t_pshandle; 2591 0 stevel pt_data_t *pt = t->t_data; 2592 0 stevel Lmid_t lmid; 2593 0 stevel uint_t i; 2594 0 stevel const rd_loadobj_t *aout_lop; 2595 0 stevel 2596 0 stevel object = pt_resolve_lmid(object, &lmid); 2597 0 stevel 2598 0 stevel if (P != NULL) { 2599 0 stevel pt_lookup_t pl; 2600 0 stevel 2601 0 stevel pl.pl_tgt = t; 2602 0 stevel pl.pl_name = name; 2603 0 stevel pl.pl_lmid = lmid; 2604 0 stevel pl.pl_symp = symp; 2605 0 stevel pl.pl_sip = sip; 2606 0 stevel pl.pl_tid = tid; 2607 0 stevel pl.pl_found = FALSE; 2608 0 stevel 2609 0 stevel if (object == MDB_TGT_OBJ_EVERY) { 2610 7928 Edward if (Pobject_iter_resolved(P, pt_lookup_cb, &pl) == -1) 2611 7928 Edward return (-1); /* errno is set for us */ 2612 7928 Edward if ((!pl.pl_found) && 2613 7928 Edward (Pobject_iter(P, pt_lookup_cb, &pl) == -1)) 2614 7928 Edward return (-1); /* errno is set for us */ 2615 0 stevel } else { 2616 0 stevel const prmap_t *pmp; 2617 0 stevel 2618 0 stevel /* 2619 0 stevel * This can fail either due to an invalid lmid or 2620 0 stevel * an invalid object. To determine which is 2621 0 stevel * faulty, we test the lmid against known valid 2622 0 stevel * lmids and then see if using a wild-card lmid 2623 0 stevel * improves ths situation. 2624 0 stevel */ 2625 0 stevel if ((pmp = Plmid_to_map(P, lmid, object)) == NULL) { 2626 0 stevel if (lmid != PR_LMID_EVERY && 2627 0 stevel lmid != LM_ID_BASE && 2628 0 stevel lmid != LM_ID_LDSO && 2629 0 stevel Plmid_to_map(P, PR_LMID_EVERY, object) 2630 0 stevel != NULL) 2631 0 stevel return (set_errno(EMDB_NOLMID)); 2632 0 stevel else 2633 0 stevel return (set_errno(EMDB_NOOBJ)); 2634 0 stevel } 2635 0 stevel 2636 0 stevel if (pt_lookup_cb(&pl, pmp, object) == -1) 2637 0 stevel return (-1); /* errno is set for us */ 2638 0 stevel } 2639 0 stevel 2640 0 stevel if (pl.pl_found) 2641 0 stevel return (0); 2642 0 stevel } 2643 0 stevel 2644 0 stevel /* 2645 0 stevel * If libproc doesn't have the symbols for rtld, we're cooked -- 2646 0 stevel * mdb doesn't have those symbols either. 2647 0 stevel */ 2648 0 stevel if (object == MDB_TGT_OBJ_RTLD) 2649 0 stevel return (set_errno(EMDB_NOSYM)); 2650 0 stevel 2651 0 stevel if (object != MDB_TGT_OBJ_EXEC && object != MDB_TGT_OBJ_EVERY) { 2652 0 stevel int status = mdb_gelf_symtab_lookup_by_file(pt->p_symtab, 2653 0 stevel object, name, symp, &sip->sym_id); 2654 0 stevel 2655 0 stevel if (status != 0) { 2656 0 stevel if (P != NULL && 2657 0 stevel Plmid_to_map(P, PR_LMID_EVERY, object) != NULL) 2658 0 stevel return (set_errno(EMDB_NOSYM)); 2659 0 stevel else 2660 0 stevel return (-1); /* errno set from lookup_by_file */ 2661 0 stevel } 2662 0 stevel 2663 0 stevel goto found; 2664 0 stevel } 2665 0 stevel 2666 0 stevel if (mdb_gelf_symtab_lookup_by_name(pt->p_symtab, name, symp, &i) == 0) { 2667 0 stevel sip->sym_table = MDB_TGT_SYMTAB; 2668 0 stevel sip->sym_id = i; 2669 0 stevel goto local_found; 2670 0 stevel } 2671 0 stevel 2672 0 stevel if (mdb_gelf_symtab_lookup_by_name(pt->p_dynsym, name, symp, &i) == 0) { 2673 0 stevel sip->sym_table = MDB_TGT_DYNSYM; 2674 0 stevel sip->sym_id = i; 2675 0 stevel goto local_found; 2676 0 stevel } 2677 0 stevel 2678 0 stevel return (set_errno(EMDB_NOSYM)); 2679 0 stevel 2680 0 stevel local_found: 2681 0 stevel if (pt->p_file != NULL && 2682 0 stevel pt->p_file->gf_ehdr.e_type == ET_DYN && 2683 0 stevel P != NULL && 2684 0 stevel (aout_lop = Pname_to_loadobj(P, PR_OBJ_EXEC)) != NULL) 2685 0 stevel symp->st_value += aout_lop->rl_base; 2686 0 stevel 2687 0 stevel found: 2688 0 stevel /* 2689 0 stevel * If the symbol has type TLS, libproc should have found the symbol 2690 0 stevel * if it exists and has been allocated. 2691 0 stevel */ 2692 0 stevel if (GELF_ST_TYPE(symp->st_info) == STT_TLS) 2693 0 stevel return (set_errno(EMDB_TLS)); 2694 0 stevel 2695 0 stevel return (0); 2696 0 stevel } 2697 0 stevel 2698 0 stevel static int 2699 0 stevel pt_lookup_by_name(mdb_tgt_t *t, const char *object, 2700 0 stevel const char *name, GElf_Sym *symp, mdb_syminfo_t *sip) 2701 0 stevel { 2702 0 stevel return (pt_lookup_by_name_thr(t, object, name, symp, sip, PTL_TID(t))); 2703 0 stevel } 2704 0 stevel 2705 0 stevel static int 2706 0 stevel pt_lookup_by_addr(mdb_tgt_t *t, uintptr_t addr, uint_t flags, 2707 0 stevel char *buf, size_t nbytes, GElf_Sym *symp, mdb_syminfo_t *sip) 2708 0 stevel { 2709 0 stevel struct ps_prochandle *P = t->t_pshandle; 2710 0 stevel pt_data_t *pt = t->t_data; 2711 0 stevel rd_plt_info_t rpi = { 0 }; 2712 7675 Edward 2713 0 stevel const char *pltsym; 2714 7675 Edward int rv, match, i; 2715 0 stevel 2716 0 stevel mdb_gelf_symtab_t *gsts[3]; /* mdb.m_prsym, .symtab, .dynsym */ 2717 0 stevel int gstc = 0; /* number of valid gsts[] entries */ 2718 0 stevel 2719 0 stevel mdb_gelf_symtab_t *gst = NULL; /* set if 'sym' is from a gst */ 2720 0 stevel const prmap_t *pmp = NULL; /* set if 'sym' is from libproc */ 2721 0 stevel GElf_Sym sym; /* best symbol found so far if !exact */ 2722 0 stevel prsyminfo_t si; 2723 0 stevel 2724 0 stevel /* 2725 0 stevel * Fill in our array of symbol table pointers with the private symbol 2726 0 stevel * table, static symbol table, and dynamic symbol table if applicable. 2727 0 stevel * These are done in order of precedence so that if we match and 2728 0 stevel * MDB_TGT_SYM_EXACT is set, we need not look any further. 2729 0 stevel */ 2730 0 stevel if (mdb.m_prsym != NULL) 2731 0 stevel gsts[gstc++] = mdb.m_prsym; 2732 0 stevel if (P == NULL && pt->p_symtab != NULL) 2733 0 stevel gsts[gstc++] = pt->p_symtab; 2734 0 stevel if (P == NULL && pt->p_dynsym != NULL) 2735 0 stevel gsts[gstc++] = pt->p_dynsym; 2736 0 stevel 2737 0 stevel /* 2738 0 stevel * Loop through our array attempting to match the address. If we match 2739 0 stevel * and we're in exact mode, we're done. Otherwise save the symbol in 2740 0 stevel * the local sym variable if it is closer than our previous match. 2741 0 stevel * We explicitly watch for zero-valued symbols since DevPro insists 2742 0 stevel * on storing __fsr_init_value's value as the symbol value instead 2743 0 stevel * of storing it in a constant integer. 2744 0 stevel */ 2745 0 stevel for (i = 0; i < gstc; i++) { 2746 0 stevel if (mdb_gelf_symtab_lookup_by_addr(gsts[i], addr, flags, buf, 2747 0 stevel nbytes, symp, &sip->sym_id) != 0 || symp->st_value == 0) 2748 0 stevel continue; 2749 0 stevel 2750 0 stevel if (flags & MDB_TGT_SYM_EXACT) { 2751 0 stevel gst = gsts[i]; 2752 0 stevel goto found; 2753 0 stevel } 2754 0 stevel 2755 0 stevel if (gst == NULL || mdb_gelf_sym_closer(symp, &sym, addr)) { 2756 0 stevel gst = gsts[i]; 2757 0 stevel sym = *symp; 2758 0 stevel } 2759 0 stevel } 2760 0 stevel 2761 0 stevel /* 2762 0 stevel * If we have no libproc handle active, we're done: fail if gst is 2763 0 stevel * NULL; otherwise copy out our best symbol and skip to the end. 2764 0 stevel * We also skip to found if gst is the private symbol table: we 2765 0 stevel * want this to always take precedence over PLT re-vectoring. 2766 0 stevel */ 2767 0 stevel if (P == NULL || (gst != NULL && gst == mdb.m_prsym)) { 2768 0 stevel if (gst == NULL) 2769 0 stevel return (set_errno(EMDB_NOSYMADDR)); 2770 0 stevel *symp = sym; 2771 0 stevel goto found; 2772 0 stevel } 2773 0 stevel 2774 0 stevel /* 2775 0 stevel * Check to see if the address is in a PLT: if it is, use librtld_db to 2776 0 stevel * attempt to resolve the PLT entry. If the entry is bound, reset addr 2777 0 stevel * to the bound address, add a special prefix to the caller's buf, 2778 0 stevel * forget our previous guess, and then continue using the new addr. 2779 0 stevel * If the entry is not bound, copy the corresponding symbol name into 2780 0 stevel * buf and return a fake symbol for the given address. 2781 0 stevel */ 2782 0 stevel if ((pltsym = Ppltdest(P, addr)) != NULL) { 2783 0 stevel const rd_loadobj_t *rlp; 2784 0 stevel rd_agent_t *rap; 2785 0 stevel 2786 0 stevel if ((rap = Prd_agent(P)) != NULL && 2787 0 stevel (rlp = Paddr_to_loadobj(P, addr)) != NULL && 2788 0 stevel rd_plt_resolution(rap, addr, Pstatus(P)->pr_lwp.pr_lwpid, 2789 0 stevel rlp->rl_plt_base, &rpi) == RD_OK && 2790 0 stevel (rpi.pi_flags & RD_FLG_PI_PLTBOUND)) { 2791 0 stevel size_t n; 2792 0 stevel n = mdb_iob_snprintf(buf, nbytes, "PLT="); 2793 0 stevel addr = rpi.pi_baddr; 2794 0 stevel if (n > nbytes) { 2795 0 stevel buf += nbytes; 2796 0 stevel nbytes = 0; 2797 0 stevel } else { 2798 0 stevel buf += n; 2799 0 stevel nbytes -= n; 2800 0 stevel } 2801 0 stevel gst = NULL; 2802 0 stevel } else { 2803 0 stevel (void) mdb_iob_snprintf(buf, nbytes, "PLT:%s", pltsym); 2804 0 stevel bzero(symp, sizeof (GElf_Sym)); 2805 0 stevel symp->st_value = addr; 2806 0 stevel symp->st_info = GELF_ST_INFO(STB_GLOBAL, STT_FUNC); 2807 0 stevel return (0); 2808 0 stevel } 2809 0 stevel } 2810 0 stevel 2811 0 stevel /* 2812 0 stevel * Ask libproc to convert the address to the closest symbol for us. 2813 0 stevel * Once we get the closest symbol, we perform the EXACT match or 2814 0 stevel * smart-mode or absolute distance check ourself: 2815 0 stevel */ 2816 7675 Edward if ((mdb.m_flags & MDB_FL_LMRAW) == 0) { 2817 7675 Edward rv = Pxlookup_by_addr_resolved(P, addr, buf, nbytes, 2818 7675 Edward symp, &si); 2819 7675 Edward } else { 2820 7675 Edward rv = Pxlookup_by_addr(P, addr, buf, nbytes, 2821 7675 Edward symp, &si); 2822 7675 Edward } 2823 7675 Edward if ((rv == 0) && (symp->st_value != 0) && 2824 7675 Edward (gst == NULL || mdb_gelf_sym_closer(symp, &sym, addr))) { 2825 0 stevel 2826 0 stevel if (flags & MDB_TGT_SYM_EXACT) 2827 0 stevel match = (addr == symp->st_value); 2828 0 stevel else if (mdb.m_symdist == 0) 2829 0 stevel match = (addr >= symp->st_value && 2830 0 stevel addr < symp->st_value + symp->st_size); 2831 0 stevel else 2832 0 stevel match = (addr >= symp->st_value && 2833 0 stevel addr < symp->st_value + mdb.m_symdist); 2834 0 stevel 2835 0 stevel if (match) { 2836 0 stevel pmp = Paddr_to_map(P, addr); 2837 0 stevel gst = NULL; 2838 0 stevel sip->sym_table = si.prs_table; 2839 0 stevel sip->sym_id = si.prs_id; 2840 0 stevel goto found; 2841 0 stevel } 2842 0 stevel } 2843 0 stevel 2844 0 stevel /* 2845 0 stevel * If we get here, Plookup_by_addr has failed us. If we have no 2846 0 stevel * previous best symbol (gst == NULL), we've failed completely. 2847 0 stevel * Otherwise we copy out that symbol and continue on to 'found'. 2848 0 stevel */ 2849 0 stevel if (gst == NULL) 2850 0 stevel return (set_errno(EMDB_NOSYMADDR)); 2851 0 stevel *symp = sym; 2852 0 stevel found: 2853 0 stevel /* 2854 0 stevel * Once we've found something, copy the final name into the caller's 2855 0 stevel * buffer and prefix it with the mapping name if appropriate. 2856 0 stevel */ 2857 0 stevel if (pmp != NULL && pmp != Pname_to_map(P, PR_OBJ_EXEC)) { 2858 0 stevel const char *prefix = pmp->pr_mapname; 2859 0 stevel Lmid_t lmid; 2860 0 stevel 2861 7675 Edward if ((mdb.m_flags & MDB_FL_LMRAW) == 0) { 2862 7675 Edward if (Pobjname_resolved(P, addr, pt->p_objname, 2863 7675 Edward MDB_TGT_MAPSZ)) 2864 7675 Edward prefix = pt->p_objname; 2865 7675 Edward } else { 2866 7675 Edward if (Pobjname(P, addr, pt->p_objname, MDB_TGT_MAPSZ)) 2867 7675 Edward prefix = pt->p_objname; 2868 7675 Edward } 2869 0 stevel 2870 0 stevel if (buf != NULL && nbytes > 1) { 2871 0 stevel (void) strncpy(pt->p_symname, buf, MDB_TGT_SYM_NAMLEN); 2872 0 stevel pt->p_symname[MDB_TGT_SYM_NAMLEN - 1] = '\0'; 2873 0 stevel } else { 2874 0 stevel pt->p_symname[0] = '\0'; 2875 0 stevel } 2876 0 stevel 2877 0 stevel if (prefix == pt->p_objname && Plmid(P, addr, &lmid) == 0 && ( 2878 0 stevel (lmid != LM_ID_BASE && lmid != LM_ID_LDSO) || 2879 0 stevel (mdb.m_flags & MDB_FL_SHOWLMID))) { 2880 0 stevel (void) mdb_iob_snprintf(buf, nbytes, "LM%lr`%s`%s", 2881 0 stevel lmid, strbasename(prefix), pt->p_symname); 2882 0 stevel } else { 2883 0 stevel (void) mdb_iob_snprintf(buf, nbytes, "%s`%s", 2884 0 stevel strbasename(prefix), pt->p_symname); 2885 0 stevel } 2886 0 stevel 2887 0 stevel } else if (gst != NULL && buf != NULL && nbytes > 0) { 2888 0 stevel (void) strncpy(buf, mdb_gelf_sym_name(gst, symp), nbytes); 2889 0 stevel buf[nbytes - 1] = '\0'; 2890 0 stevel } 2891 0 stevel 2892 0 stevel return (0); 2893 0 stevel } 2894 0 stevel 2895 0 stevel 2896 0 stevel static int 2897 0 stevel pt_symbol_iter_cb(void *arg, const GElf_Sym *sym, const char *name, 2898 0 stevel const prsyminfo_t *sip) 2899 0 stevel { 2900 0 stevel pt_symarg_t *psp = arg; 2901 0 stevel 2902 0 stevel psp->psym_info.sym_id = sip->prs_id; 2903 0 stevel 2904 0 stevel return (psp->psym_func(psp->psym_private, sym, name, &psp->psym_info, 2905 0 stevel psp->psym_obj)); 2906 0 stevel } 2907 0 stevel 2908 0 stevel static int 2909 0 stevel pt_objsym_iter(void *arg, const prmap_t *pmp, const char *object) 2910 0 stevel { 2911 0 stevel Lmid_t lmid = PR_LMID_EVERY; 2912 0 stevel pt_symarg_t *psp = arg; 2913 0 stevel 2914 0 stevel psp->psym_obj = object; 2915 0 stevel 2916 0 stevel (void) Plmid(psp->psym_targ->t_pshandle, pmp->pr_vaddr, &lmid); 2917 0 stevel (void) Pxsymbol_iter(psp->psym_targ->t_pshandle, lmid, object, 2918 0 stevel psp->psym_which, psp->psym_type, pt_symbol_iter_cb, arg); 2919 0 stevel 2920 0 stevel return (0); 2921 0 stevel } 2922 0 stevel 2923 0 stevel static int 2924 0 stevel pt_symbol_filt(void *arg, const GElf_Sym *sym, const char *name, uint_t id) 2925 0 stevel { 2926 0 stevel pt_symarg_t *psp = arg; 2927 0 stevel 2928 0 stevel if (mdb_tgt_sym_match(sym, psp->psym_type)) { 2929 0 stevel psp->psym_info.sym_id = id; 2930 0 stevel return (psp->psym_func(psp->psym_private, sym, name, 2931 0 stevel &psp->psym_info, psp->psym_obj)); 2932 0 stevel } 2933 0 stevel 2934 0 stevel return (0); 2935 0 stevel } 2936 0 stevel 2937 0 stevel static int 2938 0 stevel pt_symbol_iter(mdb_tgt_t *t, const char *object, uint_t which, 2939 0 stevel uint_t type, mdb_tgt_sym_f *func, void *private) 2940 0 stevel { 2941 0 stevel pt_data_t *pt = t->t_data; 2942 0 stevel mdb_gelf_symtab_t *gst; 2943 0 stevel pt_symarg_t ps; 2944 0 stevel Lmid_t lmid; 2945 0 stevel 2946 0 stevel object = pt_resolve_lmid(object, &lmid); 2947 0 stevel 2948 0 stevel ps.psym_targ = t; 2949 0 stevel ps.psym_which = which; 2950 0 stevel ps.psym_type = type; 2951 0 stevel ps.psym_func = func; 2952 0 stevel ps.psym_private = private; 2953 0 stevel ps.psym_obj = object; 2954 0 stevel 2955 0 stevel if (t->t_pshandle != NULL) { 2956 0 stevel if (object != MDB_TGT_OBJ_EVERY) { 2957 0 stevel if (Plmid_to_map(t->t_pshandle, lmid, object) == NULL) 2958 0 stevel return (set_errno(EMDB_NOOBJ)); 2959 0 stevel (void) Pxsymbol_iter(t->t_pshandle, lmid, object, 2960 0 stevel which, type, pt_symbol_iter_cb, &ps); 2961 0 stevel return (0); 2962 0 stevel } else if (Prd_agent(t->t_pshandle) != NULL) { 2963 7675 Edward if ((mdb.m_flags & MDB_FL_LMRAW) == 0) { 2964 7675 Edward (void) Pobject_iter_resolved(t->t_pshandle, 2965 7675 Edward pt_objsym_iter, &ps); 2966 7675 Edward } else { 2967 7675 Edward (void) Pobject_iter(t->t_pshandle, 2968 7675 Edward pt_objsym_iter, &ps); 2969 7675 Edward } 2970 0 stevel return (0); 2971 0 stevel } 2972 0 stevel } 2973 0 stevel 2974 0 stevel if (lmid != LM_ID_BASE && lmid != PR_LMID_EVERY) 2975 0 stevel return (set_errno(EMDB_NOLMID)); 2976 0 stevel 2977 0 stevel if (object != MDB_TGT_OBJ_EXEC && object != MDB_TGT_OBJ_EVERY && 2978 0 stevel pt->p_fio != NULL && 2979 0 stevel strcmp(object, IOP_NAME(pt->p_fio)) != 0) 2980 0 stevel return (set_errno(EMDB_NOOBJ)); 2981 0 stevel 2982 0 <