static int ctfdump_functions_cb(const char *name, ulong_t symidx, ctf_funcinfo_t *ctc, void *arg) { int i; if (ctc->ctc_argc != 0) { ctfdump_fargs_grow(ctc->ctc_argc); if (ctf_func_args(g_fp, symidx, g_nfargc, g_fargc) == CTF_ERR) ctfdump_fatal("failed to get arguments for function " "%s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); } ctfdump_printf(CTFDUMP_FUNCTIONS, " [%lu] %s (%lu) returns: %u args: (", g_stats.cs_nfuncs, name, symidx, ctc->ctc_return); for (i = 0; i < ctc->ctc_argc; i++) ctfdump_printf(CTFDUMP_FUNCTIONS, "%lu%s", g_fargc[i], i + 1 == ctc->ctc_argc ? "" : ", "); if (ctc->ctc_flags & CTF_FUNC_VARARG) ctfdump_printf(CTFDUMP_FUNCTIONS, "%s...", ctc->ctc_argc == 0 ? "" : ", "); ctfdump_printf(CTFDUMP_FUNCTIONS, ")\n"); g_stats.cs_nfuncs++; g_stats.cs_nfuncargs += ctc->ctc_argc; g_stats.cs_nfuncmax = MAX(ctc->ctc_argc, g_stats.cs_nfuncmax); return (0); }
int mdb_ctf_func_args(const mdb_ctf_funcinfo_t *funcp, uint_t len, mdb_ctf_id_t *argv) { ctf_file_t *fp; ctf_id_t cargv[32]; int i; if (len > (sizeof (cargv) / sizeof (cargv[0]))) return (set_errno(EINVAL)); if (funcp == NULL || argv == NULL) return (set_errno(EINVAL)); fp = mdb_ctf_type_file(funcp->mtf_return); if (ctf_func_args(fp, funcp->mtf_symidx, len, cargv) == CTF_ERR) return (set_errno(ctf_to_errno(ctf_errno(fp)))); for (i = MIN(len, funcp->mtf_argc) - 1; i >= 0; i--) { set_ctf_id(&argv[i], fp, cargv[i]); } return (0); }
static char * nm_func_signature(ctf_file_t *fp, uint_t index, char *buf, size_t len) { int n; ctf_funcinfo_t f; ctf_id_t argv[32]; char arg[32]; char *start = buf; char *sep = ""; int i; if (ctf_func_info(fp, index, &f) == CTF_ERR) return (NULL); if (ctf_type_name(fp, f.ctc_return, arg, sizeof (arg)) != NULL) n = mdb_snprintf(buf, len, "%s (*)(", arg); else n = mdb_snprintf(buf, len, "<%ld> (*)(", f.ctc_return); if (len <= n) return (start); buf += n; len -= n; (void) ctf_func_args(fp, index, sizeof (argv) / sizeof (argv[0]), argv); for (i = 0; i < f.ctc_argc; i++) { if (ctf_type_name(fp, argv[i], arg, sizeof (arg)) != NULL) n = mdb_snprintf(buf, len, "%s%s", sep, arg); else n = mdb_snprintf(buf, len, "%s<%ld>", sep, argv[i]); if (len <= n) return (start); buf += n; len -= n; sep = ", "; } if (f.ctc_flags & CTF_FUNC_VARARG) { n = mdb_snprintf(buf, len, "%s...", sep); if (len <= n) return (start); buf += n; len -= n; } else if (f.ctc_argc == 0) { n = mdb_snprintf(buf, len, "void"); if (len <= n) return (start); buf += n; len -= n; } (void) mdb_snprintf(buf, len, ")"); return (start); }
static void ctfsrc_function(ctf_idname_t *idn) { ctf_funcinfo_t *cfi = &idn->ci_funcinfo; char name[MAX_NAMELEN] = "unknown_t"; (void) ctf_type_name(g_fp, cfi->ctc_return, name, sizeof (name)); (void) printf("extern %s %s(", name, idn->ci_name); if (cfi->ctc_argc != 0) { ctfdump_fargs_grow(cfi->ctc_argc); if (ctf_func_args(g_fp, idn->ci_symidx, g_nfargc, g_fargc) == CTF_ERR) { ctfdump_fatal("failed to get arguments for function " "%s: %s\n", idn->ci_name, ctf_errmsg(ctf_errno(g_fp))); } for (size_t i = 0; i < cfi->ctc_argc; i++) { ctf_id_t aid = g_fargc[i]; name[0] = '\0'; (void) ctf_type_name(g_fp, aid, name, sizeof (name)); (void) printf("%s%s", name, i + 1 == cfi->ctc_argc ? "" : ", "); } } else { if (!(cfi->ctc_flags & CTF_FUNC_VARARG)) (void) printf("void"); } if (cfi->ctc_flags & CTF_FUNC_VARARG) (void) printf("%s...", cfi->ctc_argc == 0 ? "" : ", "); (void) printf(");\n"); }
/*ARGSUSED*/ static void fbt_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc) { fbt_probe_t *fbt = parg; struct modctl *ctl = fbt->fbtp_ctl; struct module *mp = ctl->mod_mp; ctf_file_t *fp = NULL, *pfp; ctf_funcinfo_t f; int error; ctf_id_t argv[32], type; int argc = sizeof (argv) / sizeof (ctf_id_t); const char *parent; if (!ctl->mod_loaded || (ctl->mod_loadcnt != fbt->fbtp_loadcnt)) goto err; if (fbt->fbtp_roffset != 0 && desc->dtargd_ndx == 0) { (void) strlcpy(desc->dtargd_native, "int", sizeof(desc->dtargd_native)); return; } if ((fp = ctf_modopen(mp, &error)) == NULL) { /* * We have no CTF information for this module -- and therefore * no args[] information. */ goto err; } /* * If we have a parent container, we must manually import it. */ if ((parent = ctf_parent_name(fp)) != NULL) { struct modctl *mp = &modules; struct modctl *mod = NULL; /* * We must iterate over all modules to find the module that * is our parent. */ do { if (strcmp(mp->mod_modname, parent) == 0) { mod = mp; break; } } while ((mp = mp->mod_next) != &modules); if (mod == NULL) goto err; if ((pfp = ctf_modopen(mod->mod_mp, &error)) == NULL) { goto err; } if (ctf_import(fp, pfp) != 0) { ctf_close(pfp); goto err; } ctf_close(pfp); } if (ctf_func_info(fp, fbt->fbtp_symndx, &f) == CTF_ERR) goto err; if (fbt->fbtp_roffset != 0) { if (desc->dtargd_ndx > 1) goto err; ASSERT(desc->dtargd_ndx == 1); type = f.ctc_return; } else { if (desc->dtargd_ndx + 1 > f.ctc_argc) goto err; if (ctf_func_args(fp, fbt->fbtp_symndx, argc, argv) == CTF_ERR) goto err; type = argv[desc->dtargd_ndx]; } if (ctf_type_name(fp, type, desc->dtargd_native, DTRACE_ARGTYPELEN) != NULL) { ctf_close(fp); return; } err: if (fp != NULL) ctf_close(fp); desc->dtargd_ndx = DTRACE_ARGNONE; }
uintptr_t la_i86_pltenter(Elf32_Sym *symp, uint_t symndx, uintptr_t *refcookie, uintptr_t *defcookie, La_i86_regs *regset, uint_t *sb_flags) #endif { char *defname = (char *)(*defcookie); char *refname = (char *)(*refcookie); sigset_t omask; #if !defined(_LP64) char const *sym_name = (char const *)symp->st_name; #endif char buf[256]; GElf_Sym sym; prsyminfo_t si; ctf_file_t *ctfp; ctf_funcinfo_t finfo; int argc; ctf_id_t argt[NUM_ARGS]; ulong_t argv[NUM_ARGS]; int i; char *sep = ""; ctf_id_t type, rtype; int kind; abilock(&omask); if (pidout) (void) fprintf(ABISTREAM, "%7u:", (unsigned int)getpid()); if ((ctfp = Pname_to_ctf(proc_hdl, defname)) == NULL) goto fail; if (Pxlookup_by_name(proc_hdl, PR_LMID_EVERY, defname, sym_name, &sym, &si) != 0) goto fail; if (ctf_func_info(ctfp, si.prs_id, &finfo) == CTF_ERR) goto fail; (void) type_name(ctfp, finfo.ctc_return, buf, sizeof (buf)); (void) fprintf(ABISTREAM, "-> %-8s -> %8s:%s %s(", refname, defname, buf, sym_name); /* * According to bug in la_pltexit(), it can't return * if the type is just a struct/union. So, if the return * type is a struct/union, la_pltexit() should be off. */ rtype = ctf_type_resolve(ctfp, finfo.ctc_return); type = ctf_type_reference(ctfp, rtype); rtype = ctf_type_resolve(ctfp, type); kind = ctf_type_kind(ctfp, rtype); if ((kind == CTF_K_STRUCT || kind == CTF_K_UNION) && strpbrk(buf, "*") == NULL) *sb_flags |= LA_SYMB_NOPLTEXIT; argc = MIN(sizeof (argt) / sizeof (argt[0]), finfo.ctc_argc); (void) ctf_func_args(ctfp, si.prs_id, argc, argt); argv[0] = GETARG0(regset); if (argc > 1) argv[1] = GETARG1(regset); if (argc > 2) argv[2] = GETARG2(regset); if (argc > 3) argv[3] = GETARG3(regset); if (argc > 4) argv[4] = GETARG4(regset); if (argc > 5) argv[5] = GETARG5(regset); if (argc > 6) { for (i = 6; i < argc; i++) argv[i] = GETARG_6NUP(i, regset); } for (i = 0; i < argc; i++) { (void) type_name(ctfp, argt[i], buf, sizeof (buf)); (void) fprintf(ABISTREAM, "%s%s = ", sep, buf); rtype = ctf_type_resolve(ctfp, argt[i]); type = ctf_type_reference(ctfp, rtype); rtype = ctf_type_resolve(ctfp, type); kind = ctf_type_kind(ctfp, rtype); if (kind == CTF_K_STRUCT || kind == CTF_K_UNION) (void) fprintf(ABISTREAM, "0x%p", (void *)argv[i]); else print_value(ctfp, argt[i], argv[i]); sep = ", "; } if (finfo.ctc_flags & CTF_FUNC_VARARG) (void) fprintf(ABISTREAM, "%s...", sep); else if (argc == 0) (void) fprintf(ABISTREAM, "void"); if ((*sb_flags & LA_SYMB_NOPLTEXIT) != 0) (void) fprintf(ABISTREAM, ") ** ST\n"); else (void) fprintf(ABISTREAM, ")\n"); if (verbose_list != NULL && check_intlist(verbose_list, sym_name) != 0) { for (i = 0; i < argc; i++) { (void) type_name(ctfp, argt[i], buf, sizeof (buf)); (void) fprintf(ABISTREAM, "\targ%d = (%s) ", i, buf); print_value(ctfp, argt[i], argv[i]); (void) fprintf(ABISTREAM, "\n"); } if ((*sb_flags & LA_SYMB_NOPLTEXIT) != 0) { if (kind == CTF_K_STRUCT) (void) fprintf(ABISTREAM, "\treturn = (struct), apptrace " "will not trace the return\n"); else (void) fprintf(ABISTREAM, "\treturn = (union), apptrace " "will not trace the return\n"); } } (void) fflush(ABISTREAM); abiunlock(&omask); return (symp->st_value); fail: (void) fprintf(ABISTREAM, "-> %-8s -> %8s:%s(0x%lx, 0x%lx, 0x%lx) ** NR\n", refname, defname, sym_name, (ulong_t)GETARG0(regset), (ulong_t)GETARG1(regset), (ulong_t)GETARG2(regset)); *sb_flags |= LA_SYMB_NOPLTEXIT; (void) fflush(ABISTREAM); abiunlock(&omask); return (symp->st_value); }
/*ARGSUSED*/ static void instr_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc) { instr_probe_t *fbt = parg; struct modctl *ctl = fbt->insp_ctl; struct module *mp = (struct module *) ctl; ctf_file_t *fp = NULL; ctf_funcinfo_t f; // int error; ctf_id_t argv[32], type; int argc = sizeof (argv) / sizeof (ctf_id_t); // const char *parent; if (mp->state != MODULE_STATE_LIVE || get_refcount(mp) != fbt->insp_loadcnt) return; if (fbt->insp_roffset != 0 && desc->dtargd_ndx == 0) { (void) strcpy(desc->dtargd_native, "int"); return; } # if 0 if ((fp = ctf_modopen(mp, &error)) == NULL) { /* * We have no CTF information for this module -- and therefore * no args[] information. */ goto err; } # endif //TODO(); if (fp == NULL) goto err; # if 0 /* * If we have a parent container, we must manually import it. */ if ((parent = ctf_parent_name(fp)) != NULL) { ctf_file_t *pfp; TODO(); struct modctl *mod; /* * We must iterate over all modules to find the module that * is our parent. */ for (mod = &modules; mod != NULL; mod = mod->mod_next) { if (strcmp(mod->mod_filename, parent) == 0) break; } if (mod == NULL) goto err; if ((pfp = ctf_modopen(mod->mod_mp, &error)) == NULL) goto err; if (ctf_import(fp, pfp) != 0) { ctf_close(pfp); goto err; } ctf_close(pfp); } # endif if (ctf_func_info(fp, fbt->insp_symndx, &f) == CTF_ERR) goto err; if (fbt->insp_roffset != 0) { if (desc->dtargd_ndx > 1) goto err; ASSERT(desc->dtargd_ndx == 1); type = f.ctc_return; } else { if (desc->dtargd_ndx + 1 > f.ctc_argc) goto err; if (ctf_func_args(fp, fbt->insp_symndx, argc, argv) == CTF_ERR) goto err; type = argv[desc->dtargd_ndx]; } if (ctf_type_name(fp, type, desc->dtargd_native, DTRACE_ARGTYPELEN) != NULL) { ctf_close(fp); return; } err: if (fp != NULL) ctf_close(fp); desc->dtargd_ndx = DTRACE_ARGNONE; }
/* * Read arguments from the frame indicated by regs into args, return the * number of arguments successfully read */ static int read_args(struct ps_prochandle *P, uintptr_t fp, uintptr_t pc, prgreg_t *args, size_t argsize) { GElf_Sym sym; ctf_file_t *ctfp = NULL; ctf_funcinfo_t finfo; prsyminfo_t si = {0}; uint8_t ins[SAVEARGS_INSN_SEQ_LEN]; size_t insnsize; int argc = 0; int rettype = 0; int start_index = 0; int args_style = 0; int i; ctf_id_t args_types[5]; if (Pxlookup_by_addr(P, pc, NULL, 0, &sym, &si) != 0) return (0); if ((ctfp = Paddr_to_ctf(P, pc)) == NULL) return (0); if (ctf_func_info(ctfp, si.prs_id, &finfo) == CTF_ERR) return (0); argc = finfo.ctc_argc; if (argc == 0) return (0); rettype = ctf_type_kind(ctfp, finfo.ctc_return); /* * If the function returns a structure or union greater than 16 bytes * in size %rdi contains the address in which to store the return * value rather than for an argument. */ if (((rettype == CTF_K_STRUCT) || (rettype == CTF_K_UNION)) && ctf_type_size(ctfp, finfo.ctc_return) > 16) start_index = 1; else start_index = 0; /* * If any of the first 5 arguments are a structure less than 16 bytes * in size, it will be passed spread across two argument registers, * and we will not cope. */ if (ctf_func_args(ctfp, si.prs_id, 5, args_types) == CTF_ERR) return (0); for (i = 0; i < MIN(5, finfo.ctc_argc); i++) { int t = ctf_type_kind(ctfp, args_types[i]); if (((t == CTF_K_STRUCT) || (t == CTF_K_UNION)) && ctf_type_size(ctfp, args_types[i]) <= 16) return (0); } /* * The number of instructions to search for argument saving is limited * such that only instructions prior to %pc are considered and we * never read arguments from a function where the saving code has not * in fact yet executed. */ insnsize = MIN(MIN(sym.st_size, SAVEARGS_INSN_SEQ_LEN), pc - sym.st_value); if (Pread(P, ins, insnsize, sym.st_value) != insnsize) return (0); if ((argc != 0) && ((args_style = saveargs_has_args(ins, insnsize, argc, start_index)) != SAVEARGS_NO_ARGS)) { int regargs = MIN((6 - start_index), argc); size_t size = regargs * sizeof (long); int i; /* * If Studio pushed a structure return address as an argument, * we need to read one more argument than actually exists (the * addr) to make everything line up. */ if (args_style == SAVEARGS_STRUCT_ARGS) size += sizeof (long); if (Pread(P, args, size, (fp - size)) != size) return (0); for (i = 0; i < (regargs / 2); i++) { prgreg_t t = args[i]; args[i] = args[regargs - i - 1]; args[regargs - i - 1] = t; } if (argc > regargs) { size = MIN((argc - regargs) * sizeof (long), argsize - (regargs * sizeof (long))); if (Pread(P, &args[regargs], size, fp + (sizeof (uintptr_t) * 2)) != size) return (6); } return (argc); } else { return (0); } }