1178479Sjb/* 2178479Sjb * CDDL HEADER START 3178479Sjb * 4178479Sjb * The contents of this file are subject to the terms of the 5178479Sjb * Common Development and Distribution License (the "License"). 6178479Sjb * You may not use this file except in compliance with the License. 7178479Sjb * 8178479Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9178479Sjb * or http://www.opensolaris.org/os/licensing. 10178479Sjb * See the License for the specific language governing permissions 11178479Sjb * and limitations under the License. 12178479Sjb * 13178479Sjb * When distributing Covered Code, include this CDDL HEADER in each 14178479Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15178479Sjb * If applicable, add the following below this CDDL HEADER, with the 16178479Sjb * fields enclosed by brackets "[]" replaced with your own identifying 17178479Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 18178479Sjb * 19178479Sjb * CDDL HEADER END 20178479Sjb */ 21178479Sjb 22178479Sjb/* 23210767Srpaulo * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24178479Sjb * Use is subject to license terms. 25178479Sjb */ 26267941Srpaulo/* 27267941Srpaulo * Copyright (c) 2013, Joyent, Inc. All rights reserved. 28267941Srpaulo */ 29178479Sjb 30178479Sjb#include <assert.h> 31178479Sjb#include <strings.h> 32178479Sjb#include <stdlib.h> 33178479Sjb#include <stdio.h> 34178479Sjb#include <errno.h> 35178479Sjb#include <ctype.h> 36277300Ssmh#ifdef illumos 37178479Sjb#include <alloca.h> 38178568Sjb#endif 39178479Sjb#include <libgen.h> 40178479Sjb#include <stddef.h> 41267941Srpaulo#include <sys/sysmacros.h> 42178479Sjb 43178479Sjb#include <dt_impl.h> 44178479Sjb#include <dt_program.h> 45178479Sjb#include <dt_pid.h> 46178479Sjb#include <dt_string.h> 47281257Smarkj#include <dt_module.h> 48281257Smarkj 49277300Ssmh#ifndef illumos 50281257Smarkj#include <sys/sysctl.h> 51281257Smarkj#include <unistd.h> 52211554Srpaulo#include <libproc_compat.h> 53281257Smarkj#include <libelf.h> 54281257Smarkj#include <gelf.h> 55211554Srpaulo#endif 56178479Sjb 57178479Sjbtypedef struct dt_pid_probe { 58178479Sjb dtrace_hdl_t *dpp_dtp; 59178479Sjb dt_pcb_t *dpp_pcb; 60178479Sjb dt_proc_t *dpp_dpr; 61178479Sjb struct ps_prochandle *dpp_pr; 62178479Sjb const char *dpp_mod; 63178479Sjb char *dpp_func; 64178479Sjb const char *dpp_name; 65178479Sjb const char *dpp_obj; 66178479Sjb uintptr_t dpp_pc; 67178479Sjb size_t dpp_size; 68178479Sjb Lmid_t dpp_lmid; 69178479Sjb uint_t dpp_nmatches; 70178479Sjb uint64_t dpp_stret[4]; 71178479Sjb GElf_Sym dpp_last; 72178479Sjb uint_t dpp_last_taken; 73178479Sjb} dt_pid_probe_t; 74178479Sjb 75178479Sjb/* 76178479Sjb * Compose the lmid and object name into the canonical representation. We 77178479Sjb * omit the lmid for the default link map for convenience. 78178479Sjb */ 79178479Sjbstatic void 80178479Sjbdt_pid_objname(char *buf, size_t len, Lmid_t lmid, const char *obj) 81178479Sjb{ 82277300Ssmh#ifdef illumos 83178479Sjb if (lmid == LM_ID_BASE) 84178479Sjb (void) strncpy(buf, obj, len); 85178479Sjb else 86178479Sjb (void) snprintf(buf, len, "LM%lx`%s", lmid, obj); 87178568Sjb#else 88178568Sjb (void) strncpy(buf, obj, len); 89178568Sjb#endif 90178479Sjb} 91178479Sjb 92178479Sjbstatic int 93178479Sjbdt_pid_error(dtrace_hdl_t *dtp, dt_pcb_t *pcb, dt_proc_t *dpr, 94178479Sjb fasttrap_probe_spec_t *ftp, dt_errtag_t tag, const char *fmt, ...) 95178479Sjb{ 96178479Sjb va_list ap; 97178479Sjb int len; 98178479Sjb 99178479Sjb if (ftp != NULL) 100178479Sjb dt_free(dtp, ftp); 101178479Sjb 102178479Sjb va_start(ap, fmt); 103178479Sjb if (pcb == NULL) { 104178479Sjb assert(dpr != NULL); 105178479Sjb len = vsnprintf(dpr->dpr_errmsg, sizeof (dpr->dpr_errmsg), 106178479Sjb fmt, ap); 107178479Sjb assert(len >= 2); 108178479Sjb if (dpr->dpr_errmsg[len - 2] == '\n') 109178479Sjb dpr->dpr_errmsg[len - 2] = '\0'; 110178479Sjb } else { 111178479Sjb dt_set_errmsg(dtp, dt_errtag(tag), pcb->pcb_region, 112178479Sjb pcb->pcb_filetag, pcb->pcb_fileptr ? yylineno : 0, fmt, ap); 113178479Sjb } 114178479Sjb va_end(ap); 115178479Sjb 116178479Sjb return (1); 117178479Sjb} 118178479Sjb 119178479Sjbstatic int 120178479Sjbdt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func) 121178479Sjb{ 122178479Sjb dtrace_hdl_t *dtp = pp->dpp_dtp; 123178479Sjb dt_pcb_t *pcb = pp->dpp_pcb; 124178479Sjb dt_proc_t *dpr = pp->dpp_dpr; 125178479Sjb fasttrap_probe_spec_t *ftp; 126178479Sjb uint64_t off; 127178479Sjb char *end; 128178479Sjb uint_t nmatches = 0; 129178479Sjb ulong_t sz; 130178479Sjb int glob, err; 131178479Sjb int isdash = strcmp("-", func) == 0; 132178479Sjb pid_t pid; 133178479Sjb 134277300Ssmh#ifdef illumos 135178479Sjb pid = Pstatus(pp->dpp_pr)->pr_pid; 136178568Sjb#else 137178568Sjb pid = proc_getpid(pp->dpp_pr); 138178568Sjb#endif 139178479Sjb 140178479Sjb dt_dprintf("creating probe pid%d:%s:%s:%s\n", (int)pid, pp->dpp_obj, 141178479Sjb func, pp->dpp_name); 142178479Sjb 143178479Sjb sz = sizeof (fasttrap_probe_spec_t) + (isdash ? 4 : 144178479Sjb (symp->st_size - 1) * sizeof (ftp->ftps_offs[0])); 145178479Sjb 146178479Sjb if ((ftp = dt_alloc(dtp, sz)) == NULL) { 147178479Sjb dt_dprintf("proc_per_sym: dt_alloc(%lu) failed\n", sz); 148178479Sjb return (1); /* errno is set for us */ 149178479Sjb } 150178479Sjb 151178479Sjb ftp->ftps_pid = pid; 152178479Sjb (void) strncpy(ftp->ftps_func, func, sizeof (ftp->ftps_func)); 153178479Sjb 154178479Sjb dt_pid_objname(ftp->ftps_mod, sizeof (ftp->ftps_mod), pp->dpp_lmid, 155178479Sjb pp->dpp_obj); 156178479Sjb 157178479Sjb if (!isdash && gmatch("return", pp->dpp_name)) { 158178479Sjb if (dt_pid_create_return_probe(pp->dpp_pr, dtp, ftp, symp, 159178479Sjb pp->dpp_stret) < 0) { 160178479Sjb return (dt_pid_error(dtp, pcb, dpr, ftp, 161178479Sjb D_PROC_CREATEFAIL, "failed to create return probe " 162178479Sjb "for '%s': %s", func, 163178479Sjb dtrace_errmsg(dtp, dtrace_errno(dtp)))); 164178479Sjb } 165178479Sjb 166178479Sjb nmatches++; 167178479Sjb } 168178479Sjb 169178479Sjb if (!isdash && gmatch("entry", pp->dpp_name)) { 170178479Sjb if (dt_pid_create_entry_probe(pp->dpp_pr, dtp, ftp, symp) < 0) { 171178479Sjb return (dt_pid_error(dtp, pcb, dpr, ftp, 172178479Sjb D_PROC_CREATEFAIL, "failed to create entry probe " 173178479Sjb "for '%s': %s", func, 174178479Sjb dtrace_errmsg(dtp, dtrace_errno(dtp)))); 175178479Sjb } 176178479Sjb 177178479Sjb nmatches++; 178178479Sjb } 179178479Sjb 180178479Sjb glob = strisglob(pp->dpp_name); 181178479Sjb if (!glob && nmatches == 0) { 182178479Sjb off = strtoull(pp->dpp_name, &end, 16); 183178479Sjb if (*end != '\0') { 184178479Sjb return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_NAME, 185178479Sjb "'%s' is an invalid probe name", pp->dpp_name)); 186178479Sjb } 187178479Sjb 188178479Sjb if (off >= symp->st_size) { 189178479Sjb return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_OFF, 190178479Sjb "offset 0x%llx outside of function '%s'", 191178479Sjb (u_longlong_t)off, func)); 192178479Sjb } 193178479Sjb 194178479Sjb err = dt_pid_create_offset_probe(pp->dpp_pr, pp->dpp_dtp, ftp, 195178479Sjb symp, off); 196178479Sjb 197178479Sjb if (err == DT_PROC_ERR) { 198178479Sjb return (dt_pid_error(dtp, pcb, dpr, ftp, 199178479Sjb D_PROC_CREATEFAIL, "failed to create probe at " 200178479Sjb "'%s+0x%llx': %s", func, (u_longlong_t)off, 201178479Sjb dtrace_errmsg(dtp, dtrace_errno(dtp)))); 202178479Sjb } 203178479Sjb 204178479Sjb if (err == DT_PROC_ALIGN) { 205178479Sjb return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_ALIGN, 206178479Sjb "offset 0x%llx is not aligned on an instruction", 207178479Sjb (u_longlong_t)off)); 208178479Sjb } 209178479Sjb 210178479Sjb nmatches++; 211178479Sjb 212178479Sjb } else if (glob && !isdash) { 213178479Sjb if (dt_pid_create_glob_offset_probes(pp->dpp_pr, 214178479Sjb pp->dpp_dtp, ftp, symp, pp->dpp_name) < 0) { 215178479Sjb return (dt_pid_error(dtp, pcb, dpr, ftp, 216178479Sjb D_PROC_CREATEFAIL, 217178479Sjb "failed to create offset probes in '%s': %s", func, 218178479Sjb dtrace_errmsg(dtp, dtrace_errno(dtp)))); 219178479Sjb } 220178479Sjb 221178479Sjb nmatches++; 222178479Sjb } 223178479Sjb 224178479Sjb pp->dpp_nmatches += nmatches; 225178479Sjb 226178479Sjb dt_free(dtp, ftp); 227178479Sjb 228178479Sjb return (0); 229178479Sjb} 230178479Sjb 231178479Sjbstatic int 232178479Sjbdt_pid_sym_filt(void *arg, const GElf_Sym *symp, const char *func) 233178479Sjb{ 234178479Sjb dt_pid_probe_t *pp = arg; 235178479Sjb 236178479Sjb if (symp->st_shndx == SHN_UNDEF) 237178479Sjb return (0); 238178479Sjb 239178479Sjb if (symp->st_size == 0) { 240178479Sjb dt_dprintf("st_size of %s is zero\n", func); 241178479Sjb return (0); 242178479Sjb } 243178479Sjb 244178479Sjb if (pp->dpp_last_taken == 0 || 245178479Sjb symp->st_value != pp->dpp_last.st_value || 246178479Sjb symp->st_size != pp->dpp_last.st_size) { 247178479Sjb /* 248178479Sjb * Due to 4524008, _init and _fini may have a bloated st_size. 249178479Sjb * While this bug has been fixed for a while, old binaries 250178479Sjb * may exist that still exhibit this problem. As a result, we 251178479Sjb * don't match _init and _fini though we allow users to 252178479Sjb * specify them explicitly. 253178479Sjb */ 254178479Sjb if (strcmp(func, "_init") == 0 || strcmp(func, "_fini") == 0) 255178479Sjb return (0); 256178479Sjb 257178479Sjb if ((pp->dpp_last_taken = gmatch(func, pp->dpp_func)) != 0) { 258178479Sjb pp->dpp_last = *symp; 259178479Sjb return (dt_pid_per_sym(pp, symp, func)); 260178479Sjb } 261178479Sjb } 262178479Sjb 263178479Sjb return (0); 264178479Sjb} 265178479Sjb 266178479Sjbstatic int 267178479Sjbdt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj) 268178479Sjb{ 269178479Sjb dt_pid_probe_t *pp = arg; 270178479Sjb dtrace_hdl_t *dtp = pp->dpp_dtp; 271178479Sjb dt_pcb_t *pcb = pp->dpp_pcb; 272178479Sjb dt_proc_t *dpr = pp->dpp_dpr; 273178479Sjb GElf_Sym sym; 274178479Sjb 275178479Sjb if (obj == NULL) 276178479Sjb return (0); 277178479Sjb 278277300Ssmh#ifdef illumos 279178479Sjb (void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid); 280178568Sjb#endif 281178568Sjb 282178479Sjb 283178479Sjb if ((pp->dpp_obj = strrchr(obj, '/')) == NULL) 284178479Sjb pp->dpp_obj = obj; 285178479Sjb else 286178479Sjb pp->dpp_obj++; 287277300Ssmh#ifdef illumos 288178479Sjb if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret1", &sym, 289178479Sjb NULL) == 0) 290178479Sjb pp->dpp_stret[0] = sym.st_value; 291178479Sjb else 292178479Sjb pp->dpp_stret[0] = 0; 293178479Sjb 294178479Sjb if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret2", &sym, 295178479Sjb NULL) == 0) 296178479Sjb pp->dpp_stret[1] = sym.st_value; 297178479Sjb else 298178479Sjb pp->dpp_stret[1] = 0; 299178479Sjb 300178479Sjb if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret4", &sym, 301178479Sjb NULL) == 0) 302178479Sjb pp->dpp_stret[2] = sym.st_value; 303178479Sjb else 304178479Sjb pp->dpp_stret[2] = 0; 305178479Sjb 306178479Sjb if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, ".stret8", &sym, 307178479Sjb NULL) == 0) 308178479Sjb pp->dpp_stret[3] = sym.st_value; 309178479Sjb else 310178479Sjb pp->dpp_stret[3] = 0; 311178568Sjb#else 312211554Srpaulo pp->dpp_stret[0] = 0; 313211554Srpaulo pp->dpp_stret[1] = 0; 314211554Srpaulo pp->dpp_stret[2] = 0; 315211554Srpaulo pp->dpp_stret[3] = 0; 316178568Sjb#endif 317178568Sjb 318178479Sjb dt_dprintf("%s stret %llx %llx %llx %llx\n", obj, 319178479Sjb (u_longlong_t)pp->dpp_stret[0], (u_longlong_t)pp->dpp_stret[1], 320178479Sjb (u_longlong_t)pp->dpp_stret[2], (u_longlong_t)pp->dpp_stret[3]); 321178479Sjb 322178479Sjb /* 323178479Sjb * If pp->dpp_func contains any globbing meta-characters, we need 324178479Sjb * to iterate over the symbol table and compare each function name 325178479Sjb * against the pattern. 326178479Sjb */ 327178479Sjb if (!strisglob(pp->dpp_func)) { 328178479Sjb /* 329178479Sjb * If we fail to lookup the symbol, try interpreting the 330178479Sjb * function as the special "-" function that indicates that the 331178479Sjb * probe name should be interpreted as a absolute virtual 332178479Sjb * address. If that fails and we were matching a specific 333178479Sjb * function in a specific module, report the error, otherwise 334178479Sjb * just fail silently in the hopes that some other object will 335178479Sjb * contain the desired symbol. 336178479Sjb */ 337178479Sjb if (Pxlookup_by_name(pp->dpp_pr, pp->dpp_lmid, obj, 338178479Sjb pp->dpp_func, &sym, NULL) != 0) { 339178479Sjb if (strcmp("-", pp->dpp_func) == 0) { 340178479Sjb sym.st_name = 0; 341178479Sjb sym.st_info = 342178479Sjb GELF_ST_INFO(STB_LOCAL, STT_FUNC); 343178479Sjb sym.st_other = 0; 344178479Sjb sym.st_value = 0; 345277300Ssmh#ifdef illumos 346178479Sjb sym.st_size = Pstatus(pp->dpp_pr)->pr_dmodel == 347178479Sjb PR_MODEL_ILP32 ? -1U : -1ULL; 348178568Sjb#else 349178568Sjb sym.st_size = ~((Elf64_Xword) 0); 350178568Sjb#endif 351178479Sjb 352178479Sjb } else if (!strisglob(pp->dpp_mod)) { 353178479Sjb return (dt_pid_error(dtp, pcb, dpr, NULL, 354178479Sjb D_PROC_FUNC, 355178479Sjb "failed to lookup '%s' in module '%s'", 356178479Sjb pp->dpp_func, pp->dpp_mod)); 357178479Sjb } else { 358178479Sjb return (0); 359178479Sjb } 360178479Sjb } 361178479Sjb 362178479Sjb /* 363178479Sjb * Only match defined functions of non-zero size. 364178479Sjb */ 365178479Sjb if (GELF_ST_TYPE(sym.st_info) != STT_FUNC || 366178479Sjb sym.st_shndx == SHN_UNDEF || sym.st_size == 0) 367178479Sjb return (0); 368178479Sjb 369178479Sjb /* 370178479Sjb * We don't instrument PLTs -- they're dynamically rewritten, 371178479Sjb * and, so, inherently dicey to instrument. 372178479Sjb */ 373178568Sjb#ifdef DOODAD 374178479Sjb if (Ppltdest(pp->dpp_pr, sym.st_value) != NULL) 375178479Sjb return (0); 376178568Sjb#endif 377178479Sjb 378178479Sjb (void) Plookup_by_addr(pp->dpp_pr, sym.st_value, pp->dpp_func, 379178479Sjb DTRACE_FUNCNAMELEN, &sym); 380178479Sjb 381178479Sjb return (dt_pid_per_sym(pp, &sym, pp->dpp_func)); 382178479Sjb } else { 383178479Sjb uint_t nmatches = pp->dpp_nmatches; 384178479Sjb 385178479Sjb if (Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_SYMTAB, 386178479Sjb BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp) == 1) 387178479Sjb return (1); 388178479Sjb 389178479Sjb if (nmatches == pp->dpp_nmatches) { 390178479Sjb /* 391178479Sjb * If we didn't match anything in the PR_SYMTAB, try 392178479Sjb * the PR_DYNSYM. 393178479Sjb */ 394178479Sjb if (Psymbol_iter_by_addr(pp->dpp_pr, obj, PR_DYNSYM, 395178479Sjb BIND_ANY | TYPE_FUNC, dt_pid_sym_filt, pp) == 1) 396178479Sjb return (1); 397178479Sjb } 398178479Sjb } 399178479Sjb 400178479Sjb return (0); 401178479Sjb} 402178479Sjb 403178479Sjbstatic int 404178479Sjbdt_pid_mod_filt(void *arg, const prmap_t *pmp, const char *obj) 405178479Sjb{ 406178479Sjb char name[DTRACE_MODNAMELEN]; 407178479Sjb dt_pid_probe_t *pp = arg; 408178479Sjb 409178479Sjb if (gmatch(obj, pp->dpp_mod)) 410178479Sjb return (dt_pid_per_mod(pp, pmp, obj)); 411178479Sjb 412277300Ssmh#ifdef illumos 413178479Sjb (void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid); 414178568Sjb#else 415178568Sjb pp->dpp_lmid = 0; 416178568Sjb#endif 417178479Sjb 418178479Sjb if ((pp->dpp_obj = strrchr(obj, '/')) == NULL) 419178479Sjb pp->dpp_obj = obj; 420178479Sjb else 421178479Sjb pp->dpp_obj++; 422178479Sjb 423210767Srpaulo if (gmatch(pp->dpp_obj, pp->dpp_mod)) 424210767Srpaulo return (dt_pid_per_mod(pp, pmp, obj)); 425178479Sjb 426277300Ssmh#ifdef illumos 427210767Srpaulo (void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid); 428210775Srpaulo#endif 429210767Srpaulo 430210767Srpaulo dt_pid_objname(name, sizeof (name), pp->dpp_lmid, pp->dpp_obj); 431210767Srpaulo 432178479Sjb if (gmatch(name, pp->dpp_mod)) 433178479Sjb return (dt_pid_per_mod(pp, pmp, obj)); 434178479Sjb 435178479Sjb return (0); 436178479Sjb} 437178479Sjb 438178479Sjbstatic const prmap_t * 439178479Sjbdt_pid_fix_mod(dtrace_probedesc_t *pdp, struct ps_prochandle *P) 440178479Sjb{ 441178479Sjb char m[MAXPATHLEN]; 442178479Sjb Lmid_t lmid = PR_LMID_EVERY; 443178479Sjb const char *obj; 444178479Sjb const prmap_t *pmp; 445178479Sjb 446178479Sjb /* 447178479Sjb * Pick apart the link map from the library name. 448178479Sjb */ 449178479Sjb if (strchr(pdp->dtpd_mod, '`') != NULL) { 450178479Sjb char *end; 451178479Sjb 452178479Sjb if (strncmp(pdp->dtpd_mod, "LM", 2) != 0 || 453178479Sjb !isdigit(pdp->dtpd_mod[2])) 454178479Sjb return (NULL); 455178479Sjb 456178479Sjb lmid = strtoul(&pdp->dtpd_mod[2], &end, 16); 457178479Sjb 458178479Sjb obj = end + 1; 459178479Sjb 460178479Sjb if (*end != '`' || strchr(obj, '`') != NULL) 461178479Sjb return (NULL); 462178479Sjb 463178479Sjb } else { 464178479Sjb obj = pdp->dtpd_mod; 465178479Sjb } 466178479Sjb 467178479Sjb if ((pmp = Plmid_to_map(P, lmid, obj)) == NULL) 468178479Sjb return (NULL); 469178479Sjb 470178479Sjb (void) Pobjname(P, pmp->pr_vaddr, m, sizeof (m)); 471178479Sjb if ((obj = strrchr(m, '/')) == NULL) 472178479Sjb obj = &m[0]; 473178479Sjb else 474178479Sjb obj++; 475178479Sjb 476277300Ssmh#ifdef illumos 477178479Sjb (void) Plmid(P, pmp->pr_vaddr, &lmid); 478211554Srpaulo#endif 479178568Sjb 480178479Sjb dt_pid_objname(pdp->dtpd_mod, sizeof (pdp->dtpd_mod), lmid, obj); 481178479Sjb 482178479Sjb return (pmp); 483178479Sjb} 484178479Sjb 485178479Sjb 486178479Sjbstatic int 487178479Sjbdt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, 488178479Sjb dt_pcb_t *pcb, dt_proc_t *dpr) 489178479Sjb{ 490178479Sjb dt_pid_probe_t pp; 491178479Sjb int ret = 0; 492178479Sjb 493178479Sjb pp.dpp_dtp = dtp; 494178479Sjb pp.dpp_dpr = dpr; 495178479Sjb pp.dpp_pr = dpr->dpr_proc; 496178479Sjb pp.dpp_pcb = pcb; 497178479Sjb 498178568Sjb#ifdef DOODAD 499178479Sjb /* 500178479Sjb * We can only trace dynamically-linked executables (since we've 501178479Sjb * hidden some magic in ld.so.1 as well as libc.so.1). 502178479Sjb */ 503178479Sjb if (Pname_to_map(pp.dpp_pr, PR_OBJ_LDSO) == NULL) { 504178479Sjb return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_DYN, 505178479Sjb "process %s is not a dynamically-linked executable", 506178479Sjb &pdp->dtpd_provider[3])); 507178479Sjb } 508178568Sjb#endif 509178479Sjb 510178479Sjb pp.dpp_mod = pdp->dtpd_mod[0] != '\0' ? pdp->dtpd_mod : "*"; 511178479Sjb pp.dpp_func = pdp->dtpd_func[0] != '\0' ? pdp->dtpd_func : "*"; 512178479Sjb pp.dpp_name = pdp->dtpd_name[0] != '\0' ? pdp->dtpd_name : "*"; 513178479Sjb pp.dpp_last_taken = 0; 514178479Sjb 515178479Sjb if (strcmp(pp.dpp_func, "-") == 0) { 516178479Sjb const prmap_t *aout, *pmp; 517178479Sjb 518178479Sjb if (pdp->dtpd_mod[0] == '\0') { 519178479Sjb pp.dpp_mod = pdp->dtpd_mod; 520178479Sjb (void) strcpy(pdp->dtpd_mod, "a.out"); 521178479Sjb } else if (strisglob(pp.dpp_mod) || 522178479Sjb (aout = Pname_to_map(pp.dpp_pr, "a.out")) == NULL || 523178479Sjb (pmp = Pname_to_map(pp.dpp_pr, pp.dpp_mod)) == NULL || 524178479Sjb aout->pr_vaddr != pmp->pr_vaddr) { 525178479Sjb return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_LIB, 526178479Sjb "only the a.out module is valid with the " 527178479Sjb "'-' function")); 528178479Sjb } 529178479Sjb 530178479Sjb if (strisglob(pp.dpp_name)) { 531178479Sjb return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_NAME, 532178479Sjb "only individual addresses may be specified " 533178479Sjb "with the '-' function")); 534178479Sjb } 535178479Sjb } 536178479Sjb 537178479Sjb /* 538178479Sjb * If pp.dpp_mod contains any globbing meta-characters, we need 539178479Sjb * to iterate over each module and compare its name against the 540178479Sjb * pattern. An empty module name is treated as '*'. 541178479Sjb */ 542178479Sjb if (strisglob(pp.dpp_mod)) { 543178479Sjb ret = Pobject_iter(pp.dpp_pr, dt_pid_mod_filt, &pp); 544178479Sjb } else { 545178479Sjb const prmap_t *pmp; 546178479Sjb char *obj; 547178479Sjb 548178479Sjb /* 549178479Sjb * If we can't find a matching module, don't sweat it -- either 550178479Sjb * we'll fail the enabling because the probes don't exist or 551178479Sjb * we'll wait for that module to come along. 552178479Sjb */ 553178479Sjb if ((pmp = dt_pid_fix_mod(pdp, pp.dpp_pr)) != NULL) { 554178479Sjb if ((obj = strchr(pdp->dtpd_mod, '`')) == NULL) 555178479Sjb obj = pdp->dtpd_mod; 556178479Sjb else 557178479Sjb obj++; 558178479Sjb 559178479Sjb ret = dt_pid_per_mod(&pp, pmp, obj); 560178479Sjb } 561178479Sjb } 562178479Sjb 563178479Sjb return (ret); 564178479Sjb} 565178479Sjb 566178479Sjbstatic int 567178479Sjbdt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname) 568178479Sjb{ 569178479Sjb struct ps_prochandle *P = data; 570178479Sjb GElf_Sym sym; 571178479Sjb prsyminfo_t sip; 572178479Sjb dof_helper_t dh; 573178479Sjb GElf_Half e_type; 574178479Sjb const char *mname; 575178479Sjb const char *syms[] = { "___SUNW_dof", "__SUNW_dof" }; 576178479Sjb int i, fd = -1; 577178479Sjb 578178479Sjb /* 579178479Sjb * The symbol ___SUNW_dof is for lazy-loaded DOF sections, and 580178479Sjb * __SUNW_dof is for actively-loaded DOF sections. We try to force 581178479Sjb * in both types of DOF section since the process may not yet have 582178479Sjb * run the code to instantiate these providers. 583178479Sjb */ 584178479Sjb for (i = 0; i < 2; i++) { 585178479Sjb if (Pxlookup_by_name(P, PR_LMID_EVERY, oname, syms[i], &sym, 586178479Sjb &sip) != 0) { 587178479Sjb continue; 588178479Sjb } 589178479Sjb 590178479Sjb if ((mname = strrchr(oname, '/')) == NULL) 591178479Sjb mname = oname; 592178479Sjb else 593178479Sjb mname++; 594178479Sjb 595178479Sjb dt_dprintf("lookup of %s succeeded for %s\n", syms[i], mname); 596178479Sjb 597178479Sjb if (Pread(P, &e_type, sizeof (e_type), pmp->pr_vaddr + 598178479Sjb offsetof(Elf64_Ehdr, e_type)) != sizeof (e_type)) { 599178479Sjb dt_dprintf("read of ELF header failed"); 600178479Sjb continue; 601178479Sjb } 602178479Sjb 603291962Smarkj dh.dofhp_dof = sym.st_value; 604178479Sjb dh.dofhp_addr = (e_type == ET_EXEC) ? 0 : pmp->pr_vaddr; 605178479Sjb 606291962Smarkj dt_pid_objname(dh.dofhp_mod, sizeof (dh.dofhp_mod), 607291962Smarkj sip.prs_lmid, mname); 608281257Smarkj 609291962Smarkj#ifdef __FreeBSD__ 610281257Smarkj dh.dofhp_pid = proc_getpid(P); 611281257Smarkj 612281257Smarkj if (fd == -1 && 613281257Smarkj (fd = open("/dev/dtrace/helper", O_RDWR, 0)) < 0) { 614281257Smarkj dt_dprintf("open of helper device failed: %s\n", 615281257Smarkj strerror(errno)); 616281257Smarkj return (-1); /* errno is set for us */ 617281257Smarkj } 618281257Smarkj 619281257Smarkj if (ioctl(fd, DTRACEHIOC_ADDDOF, &dh, sizeof (dh)) < 0) 620281257Smarkj dt_dprintf("DOF was rejected for %s\n", dh.dofhp_mod); 621178568Sjb#else 622178479Sjb if (fd == -1 && 623178479Sjb (fd = pr_open(P, "/dev/dtrace/helper", O_RDWR, 0)) < 0) { 624178479Sjb dt_dprintf("pr_open of helper device failed: %s\n", 625178479Sjb strerror(errno)); 626178479Sjb return (-1); /* errno is set for us */ 627178479Sjb } 628178479Sjb 629178479Sjb if (pr_ioctl(P, fd, DTRACEHIOC_ADDDOF, &dh, sizeof (dh)) < 0) 630178479Sjb dt_dprintf("DOF was rejected for %s\n", dh.dofhp_mod); 631178568Sjb#endif 632178479Sjb } 633178479Sjb 634178479Sjb if (fd != -1) 635281257Smarkj#ifdef __FreeBSD__ 636281257Smarkj (void) close(fd); 637281257Smarkj#else 638178479Sjb (void) pr_close(P, fd); 639178568Sjb#endif 640178479Sjb 641178479Sjb return (0); 642178479Sjb} 643178479Sjb 644178479Sjbstatic int 645178479Sjbdt_pid_create_usdt_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, 646178479Sjb dt_pcb_t *pcb, dt_proc_t *dpr) 647178479Sjb{ 648178479Sjb struct ps_prochandle *P = dpr->dpr_proc; 649178479Sjb int ret = 0; 650178479Sjb 651210775Srpaulo assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 652178479Sjb (void) Pupdate_maps(P); 653178479Sjb if (Pobject_iter(P, dt_pid_usdt_mapping, P) != 0) { 654178479Sjb ret = -1; 655178479Sjb (void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_USDT, 656178479Sjb "failed to instantiate probes for pid %d: %s", 657277300Ssmh#ifdef illumos 658178479Sjb (int)Pstatus(P)->pr_pid, strerror(errno)); 659178568Sjb#else 660178568Sjb (int)proc_getpid(P), strerror(errno)); 661178568Sjb#endif 662178479Sjb } 663178479Sjb 664178479Sjb /* 665178479Sjb * Put the module name in its canonical form. 666178479Sjb */ 667178479Sjb (void) dt_pid_fix_mod(pdp, P); 668178479Sjb 669178479Sjb return (ret); 670178479Sjb} 671178479Sjb 672178479Sjbstatic pid_t 673178479Sjbdt_pid_get_pid(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb, 674178479Sjb dt_proc_t *dpr) 675178479Sjb{ 676178479Sjb pid_t pid; 677178479Sjb char *c, *last = NULL, *end; 678178479Sjb 679178479Sjb for (c = &pdp->dtpd_provider[0]; *c != '\0'; c++) { 680178479Sjb if (!isdigit(*c)) 681178479Sjb last = c; 682178479Sjb } 683178479Sjb 684178479Sjb if (last == NULL || (*(++last) == '\0')) { 685178479Sjb (void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_BADPROV, 686178479Sjb "'%s' is not a valid provider", pdp->dtpd_provider); 687178479Sjb return (-1); 688178479Sjb } 689178479Sjb 690178479Sjb errno = 0; 691178479Sjb pid = strtol(last, &end, 10); 692178479Sjb 693178479Sjb if (errno != 0 || end == last || end[0] != '\0' || pid <= 0) { 694178479Sjb (void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_BADPID, 695178479Sjb "'%s' does not contain a valid pid", pdp->dtpd_provider); 696178479Sjb return (-1); 697178479Sjb } 698178479Sjb 699178479Sjb return (pid); 700178479Sjb} 701178479Sjb 702178479Sjbint 703178479Sjbdt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb) 704178479Sjb{ 705178479Sjb char provname[DTRACE_PROVNAMELEN]; 706178479Sjb struct ps_prochandle *P; 707178479Sjb dt_proc_t *dpr; 708178479Sjb pid_t pid; 709178479Sjb int err = 0; 710178479Sjb 711178479Sjb assert(pcb != NULL); 712178479Sjb 713178479Sjb if ((pid = dt_pid_get_pid(pdp, dtp, pcb, NULL)) == -1) 714178479Sjb return (-1); 715178479Sjb 716178479Sjb if (dtp->dt_ftfd == -1) { 717178479Sjb if (dtp->dt_fterr == ENOENT) { 718178479Sjb (void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV, 719178479Sjb "pid provider is not installed on this system"); 720178479Sjb } else { 721178479Sjb (void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV, 722178479Sjb "pid provider is not available: %s", 723178479Sjb strerror(dtp->dt_fterr)); 724178479Sjb } 725178479Sjb 726178479Sjb return (-1); 727178479Sjb } 728178479Sjb 729178479Sjb (void) snprintf(provname, sizeof (provname), "pid%d", (int)pid); 730178479Sjb 731178479Sjb if (gmatch(provname, pdp->dtpd_provider) != 0) { 732178479Sjb if ((P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 733178479Sjb 0)) == NULL) { 734178479Sjb (void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB, 735178479Sjb "failed to grab process %d", (int)pid); 736178479Sjb return (-1); 737178479Sjb } 738178479Sjb 739178479Sjb dpr = dt_proc_lookup(dtp, P, 0); 740178479Sjb assert(dpr != NULL); 741178479Sjb (void) pthread_mutex_lock(&dpr->dpr_lock); 742178479Sjb 743178568Sjb if ((err = dt_pid_create_pid_probes(pdp, dtp, pcb, dpr)) == 0) { 744178568Sjb /* 745178568Sjb * Alert other retained enablings which may match 746178568Sjb * against the newly created probes. 747178568Sjb */ 748178568Sjb (void) dt_ioctl(dtp, DTRACEIOC_ENABLE, NULL); 749178568Sjb } 750178479Sjb 751178479Sjb (void) pthread_mutex_unlock(&dpr->dpr_lock); 752178479Sjb dt_proc_release(dtp, P); 753178479Sjb } 754178479Sjb 755178479Sjb /* 756178479Sjb * If it's not strictly a pid provider, we might match a USDT provider. 757178479Sjb */ 758178479Sjb if (strcmp(provname, pdp->dtpd_provider) != 0) { 759178479Sjb if ((P = dt_proc_grab(dtp, pid, 0, 1)) == NULL) { 760178479Sjb (void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB, 761178479Sjb "failed to grab process %d", (int)pid); 762178479Sjb return (-1); 763178479Sjb } 764178479Sjb 765178479Sjb dpr = dt_proc_lookup(dtp, P, 0); 766178479Sjb assert(dpr != NULL); 767178479Sjb (void) pthread_mutex_lock(&dpr->dpr_lock); 768178479Sjb 769178479Sjb if (!dpr->dpr_usdt) { 770178479Sjb err = dt_pid_create_usdt_probes(pdp, dtp, pcb, dpr); 771178479Sjb dpr->dpr_usdt = B_TRUE; 772178479Sjb } 773178479Sjb 774178479Sjb (void) pthread_mutex_unlock(&dpr->dpr_lock); 775178479Sjb dt_proc_release(dtp, P); 776178479Sjb } 777178479Sjb 778178479Sjb return (err ? -1 : 0); 779178479Sjb} 780178479Sjb 781178479Sjbint 782178479Sjbdt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr) 783178479Sjb{ 784178568Sjb dtrace_enable_io_t args; 785178479Sjb dtrace_prog_t *pgp; 786178479Sjb dt_stmt_t *stp; 787178479Sjb dtrace_probedesc_t *pdp, pd; 788178479Sjb pid_t pid; 789178479Sjb int ret = 0, found = B_FALSE; 790178479Sjb char provname[DTRACE_PROVNAMELEN]; 791178479Sjb 792178479Sjb (void) snprintf(provname, sizeof (provname), "pid%d", 793178479Sjb (int)dpr->dpr_pid); 794178479Sjb 795178479Sjb for (pgp = dt_list_next(&dtp->dt_programs); pgp != NULL; 796178479Sjb pgp = dt_list_next(pgp)) { 797178479Sjb 798178479Sjb for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; 799178479Sjb stp = dt_list_next(stp)) { 800178479Sjb 801178479Sjb pdp = &stp->ds_desc->dtsd_ecbdesc->dted_probe; 802178479Sjb pid = dt_pid_get_pid(pdp, dtp, NULL, dpr); 803178479Sjb if (pid != dpr->dpr_pid) 804178479Sjb continue; 805178479Sjb 806178479Sjb found = B_TRUE; 807178479Sjb 808178479Sjb pd = *pdp; 809178479Sjb 810178479Sjb if (gmatch(provname, pdp->dtpd_provider) != 0 && 811178479Sjb dt_pid_create_pid_probes(&pd, dtp, NULL, dpr) != 0) 812178479Sjb ret = 1; 813178479Sjb 814178479Sjb /* 815178479Sjb * If it's not strictly a pid provider, we might match 816178479Sjb * a USDT provider. 817178479Sjb */ 818178479Sjb if (strcmp(provname, pdp->dtpd_provider) != 0 && 819178479Sjb dt_pid_create_usdt_probes(&pd, dtp, NULL, dpr) != 0) 820178479Sjb ret = 1; 821178479Sjb } 822178479Sjb } 823178479Sjb 824178479Sjb if (found) { 825178479Sjb /* 826178479Sjb * Give DTrace a shot to the ribs to get it to check 827178479Sjb * out the newly created probes. 828178479Sjb */ 829178568Sjb args.dof = NULL; 830178568Sjb args.n_matched = 0; 831178568Sjb (void) dt_ioctl(dtp, DTRACEIOC_ENABLE, &args); 832178479Sjb } 833178479Sjb 834178479Sjb return (ret); 835178479Sjb} 836267941Srpaulo 837267941Srpaulo/* 838267941Srpaulo * libdtrace has a backroom deal with us to ask us for type information on 839267941Srpaulo * behalf of pid provider probes when fasttrap doesn't return any type 840267941Srpaulo * information. Instead we'll look up the module and see if there is type 841267941Srpaulo * information available. However, if there is no type information available due 842267941Srpaulo * to a lack of CTF data, then we want to make sure that DTrace still carries on 843267941Srpaulo * in face of that. As such we don't have a meaningful exit code about failure. 844267941Srpaulo * We emit information about why we failed to the dtrace debug log so someone 845267941Srpaulo * can figure it out by asking nicely for DTRACE_DEBUG. 846267941Srpaulo */ 847267941Srpaulovoid 848267941Srpaulodt_pid_get_types(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp, 849267941Srpaulo dtrace_argdesc_t *adp, int *nargs) 850267941Srpaulo{ 851267941Srpaulo dt_module_t *dmp; 852267941Srpaulo ctf_file_t *fp; 853267941Srpaulo ctf_funcinfo_t f; 854267941Srpaulo ctf_id_t argv[32]; 855267941Srpaulo GElf_Sym sym; 856267941Srpaulo prsyminfo_t si; 857267941Srpaulo struct ps_prochandle *p; 858267941Srpaulo int i, args; 859267941Srpaulo char buf[DTRACE_ARGTYPELEN]; 860267941Srpaulo const char *mptr; 861267941Srpaulo char *eptr; 862267941Srpaulo int ret = 0; 863267941Srpaulo int argc = sizeof (argv) / sizeof (ctf_id_t); 864267941Srpaulo Lmid_t lmid; 865267941Srpaulo 866267941Srpaulo /* Set up a potential outcome */ 867267941Srpaulo args = *nargs; 868267941Srpaulo *nargs = 0; 869267941Srpaulo 870267941Srpaulo /* 871267941Srpaulo * If we don't have an entry or return probe then we can just stop right 872267941Srpaulo * now as we don't have arguments for offset probes. 873267941Srpaulo */ 874267941Srpaulo if (strcmp(pdp->dtpd_name, "entry") != 0 && 875267941Srpaulo strcmp(pdp->dtpd_name, "return") != 0) 876267941Srpaulo return; 877267941Srpaulo 878267941Srpaulo dmp = dt_module_create(dtp, pdp->dtpd_provider); 879267941Srpaulo if (dmp == NULL) { 880267941Srpaulo dt_dprintf("failed to find module for %s\n", 881267941Srpaulo pdp->dtpd_provider); 882267941Srpaulo return; 883267941Srpaulo } 884267941Srpaulo if (dt_module_load(dtp, dmp) != 0) { 885267941Srpaulo dt_dprintf("failed to load module for %s\n", 886267941Srpaulo pdp->dtpd_provider); 887267941Srpaulo return; 888267941Srpaulo } 889267941Srpaulo 890267941Srpaulo /* 891267941Srpaulo * We may be working with a module that doesn't have ctf. If that's the 892267941Srpaulo * case then we just return now and move on with life. 893267941Srpaulo */ 894267941Srpaulo fp = dt_module_getctflib(dtp, dmp, pdp->dtpd_mod); 895267941Srpaulo if (fp == NULL) { 896267941Srpaulo dt_dprintf("no ctf container for %s\n", 897267941Srpaulo pdp->dtpd_mod); 898267941Srpaulo return; 899267941Srpaulo } 900267941Srpaulo p = dt_proc_grab(dtp, dmp->dm_pid, 0, PGRAB_RDONLY | PGRAB_FORCE); 901267941Srpaulo if (p == NULL) { 902267941Srpaulo dt_dprintf("failed to grab pid\n"); 903267941Srpaulo return; 904267941Srpaulo } 905267941Srpaulo dt_proc_lock(dtp, p); 906267941Srpaulo 907267941Srpaulo /* 908267941Srpaulo * Check to see if the D module has a link map ID and separate that out 909267941Srpaulo * for properly interrogating libproc. 910267941Srpaulo */ 911267941Srpaulo if ((mptr = strchr(pdp->dtpd_mod, '`')) != NULL) { 912267941Srpaulo if (strlen(pdp->dtpd_mod) < 3) { 913267941Srpaulo dt_dprintf("found weird modname with linkmap, " 914267941Srpaulo "aborting: %s\n", pdp->dtpd_mod); 915267941Srpaulo goto out; 916267941Srpaulo } 917267941Srpaulo if (pdp->dtpd_mod[0] != 'L' || pdp->dtpd_mod[1] != 'M') { 918267941Srpaulo dt_dprintf("missing leading 'LM', " 919267941Srpaulo "aborting: %s\n", pdp->dtpd_mod); 920267941Srpaulo goto out; 921267941Srpaulo } 922267941Srpaulo errno = 0; 923267941Srpaulo lmid = strtol(pdp->dtpd_mod + 2, &eptr, 16); 924267941Srpaulo if (errno == ERANGE || eptr != mptr) { 925267941Srpaulo dt_dprintf("failed to parse out lmid, aborting: %s\n", 926267941Srpaulo pdp->dtpd_mod); 927267941Srpaulo goto out; 928267941Srpaulo } 929267941Srpaulo mptr++; 930267941Srpaulo } else { 931267941Srpaulo mptr = pdp->dtpd_mod; 932267941Srpaulo lmid = 0; 933267941Srpaulo } 934267941Srpaulo 935267941Srpaulo if (Pxlookup_by_name(p, lmid, mptr, pdp->dtpd_func, 936267941Srpaulo &sym, &si) != 0) { 937267941Srpaulo dt_dprintf("failed to find function %s in %s`%s\n", 938267941Srpaulo pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod); 939267941Srpaulo goto out; 940267941Srpaulo } 941267941Srpaulo if (ctf_func_info(fp, si.prs_id, &f) == CTF_ERR) { 942267941Srpaulo dt_dprintf("failed to get ctf information for %s in %s`%s\n", 943267941Srpaulo pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod); 944267941Srpaulo goto out; 945267941Srpaulo } 946267941Srpaulo 947267941Srpaulo (void) snprintf(buf, sizeof (buf), "%s`%s", pdp->dtpd_provider, 948267941Srpaulo pdp->dtpd_mod); 949267941Srpaulo 950267941Srpaulo if (strcmp(pdp->dtpd_name, "return") == 0) { 951267941Srpaulo if (args < 2) 952267941Srpaulo goto out; 953267941Srpaulo 954267941Srpaulo bzero(adp, sizeof (dtrace_argdesc_t)); 955267941Srpaulo adp->dtargd_ndx = 0; 956267941Srpaulo adp->dtargd_id = pdp->dtpd_id; 957267941Srpaulo adp->dtargd_mapping = adp->dtargd_ndx; 958267941Srpaulo /* 959267941Srpaulo * We explicitly leave out the library here, we only care that 960267941Srpaulo * it is some int. We are assuming that there is no ctf 961267941Srpaulo * container in here that is lying about what an int is. 962267941Srpaulo */ 963267941Srpaulo (void) snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN, 964267941Srpaulo "user %s`%s", pdp->dtpd_provider, "int"); 965267941Srpaulo adp++; 966267941Srpaulo bzero(adp, sizeof (dtrace_argdesc_t)); 967267941Srpaulo adp->dtargd_ndx = 1; 968267941Srpaulo adp->dtargd_id = pdp->dtpd_id; 969267941Srpaulo adp->dtargd_mapping = adp->dtargd_ndx; 970267941Srpaulo ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN, 971267941Srpaulo "userland "); 972267941Srpaulo (void) ctf_type_qname(fp, f.ctc_return, adp->dtargd_native + 973267941Srpaulo ret, DTRACE_ARGTYPELEN - ret, buf); 974267941Srpaulo *nargs = 2; 975267941Srpaulo } else { 976267941Srpaulo if (ctf_func_args(fp, si.prs_id, argc, argv) == CTF_ERR) 977267941Srpaulo goto out; 978267941Srpaulo 979267941Srpaulo *nargs = MIN(args, f.ctc_argc); 980267941Srpaulo for (i = 0; i < *nargs; i++, adp++) { 981267941Srpaulo bzero(adp, sizeof (dtrace_argdesc_t)); 982267941Srpaulo adp->dtargd_ndx = i; 983267941Srpaulo adp->dtargd_id = pdp->dtpd_id; 984267941Srpaulo adp->dtargd_mapping = adp->dtargd_ndx; 985267941Srpaulo ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN, 986267941Srpaulo "userland "); 987267941Srpaulo (void) ctf_type_qname(fp, argv[i], adp->dtargd_native + 988267941Srpaulo ret, DTRACE_ARGTYPELEN - ret, buf); 989267941Srpaulo } 990267941Srpaulo } 991267941Srpauloout: 992267941Srpaulo dt_proc_unlock(dtp, p); 993267941Srpaulo dt_proc_release(dtp, p); 994267941Srpaulo} 995