コード例 #1
0
ファイル: mdb_nm.c プロジェクト: AlainODea/illumos-gate
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);
}
コード例 #2
0
/*ARGSUSED*/
int
mdb_ctf_func_info(const GElf_Sym *symp, const mdb_syminfo_t *sip,
    mdb_ctf_funcinfo_t *mfp)
{
	ctf_file_t *fp = NULL;
	ctf_funcinfo_t f;
	mdb_tgt_t *t = mdb.m_target;
	char name[MDB_SYM_NAMLEN];
	const mdb_map_t *mp;
	mdb_syminfo_t si;
	int err;

	if (symp == NULL || mfp == NULL)
		return (set_errno(EINVAL));

	/*
	 * In case the input symbol came from a merged or private symbol table,
	 * re-lookup the address as a symbol, and then perform a fully scoped
	 * lookup of that symbol name to get the mdb_syminfo_t for its CTF.
	 */
	if ((fp = mdb_tgt_addr_to_ctf(t, symp->st_value)) == NULL ||
	    (mp = mdb_tgt_addr_to_map(t, symp->st_value)) == NULL ||
	    mdb_tgt_lookup_by_addr(t, symp->st_value, MDB_TGT_SYM_FUZZY,
	    name, sizeof (name), NULL, NULL) != 0)
		return (-1); /* errno is set for us */

	if (strchr(name, '`') != NULL)
		err = mdb_tgt_lookup_by_scope(t, name, NULL, &si);
	else
		err = mdb_tgt_lookup_by_name(t, mp->map_name, name, NULL, &si);

	if (err != 0)
		return (-1); /* errno is set for us */

	if (ctf_func_info(fp, si.sym_id, &f) == CTF_ERR)
		return (set_errno(ctf_to_errno(ctf_errno(fp))));

	set_ctf_id(&mfp->mtf_return, fp, f.ctc_return);
	mfp->mtf_argc = f.ctc_argc;
	mfp->mtf_flags = f.ctc_flags;
	mfp->mtf_symidx = si.sym_id;

	return (0);
}
コード例 #3
0
ファイル: ctf_lookup.c プロジェクト: ajinkya93/netbsd-src
/*
 * Given a symbol table index, return the arguments for the function described
 * by the corresponding entry in the symbol table.
 */
int
ctf_func_args(ctf_file_t *fp, ulong_t symidx, uint_t argc, ctf_id_t *argv)
{
	const ushort_t *dp;
	ctf_funcinfo_t f;

	if (ctf_func_info(fp, symidx, &f) == CTF_ERR)
		return (CTF_ERR); /* errno is set for us */

	/*
	 * The argument data is two ushort_t's past the translation table
	 * offset: one for the function info, and one for the return type.
	 */
	dp = (ushort_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[symidx]) + 2;

	for (argc = MIN(argc, f.ctc_argc); argc != 0; argc--)
		*argv++ = *dp++;

	return (0);
}
コード例 #4
0
ファイル: dump.c プロジェクト: apprisi/illumos-gate
static void
walk_symtab(Elf *elf, char *fname, ctf_file_t *fp,
    void (*callback)(ctf_file_t *, symtab_sym_t *))
{
	Elf_Scn *stab = NULL;
	Elf_Scn *text = NULL;
	Elf_Data *stabdata = NULL;
	Elf_Data *textdata = NULL;
	GElf_Ehdr ehdr;
	GElf_Shdr stabshdr;
	GElf_Shdr textshdr;
	int foundtext = 0, foundstab = 0;
	symtab_sym_t ss;

	if ((gelf_getehdr(elf, &ehdr)) == NULL)
		errx(1, "could not read ELF header from %s\n",
		    fname);

	while ((stab = elf_nextscn(elf, stab)) != NULL) {
		(void) gelf_getshdr(stab, &stabshdr);

		if (stabshdr.sh_type == SHT_SYMTAB) {
			foundstab = 1;
			break;
		}
	}

	while ((text = elf_nextscn(elf, text)) != NULL) {
		(void) gelf_getshdr(text, &textshdr);

		if (strcmp(".text", elf_strptr(elf,
		    ehdr.e_shstrndx, (size_t)textshdr.sh_name)) == 0) {
			foundtext = 1;
			break;
		}
	}

	if (!foundstab || !foundtext)
		return;

	stabdata = elf_getdata(stab, NULL);
	textdata = elf_rawdata(text,  NULL);
	for (unsigned symdx = 0;
	    symdx < (stabshdr.sh_size / stabshdr.sh_entsize);
	    symdx++) {
		(void) gelf_getsym(stabdata, symdx, &ss.ss_sym);

		if ((GELF_ST_TYPE(ss.ss_sym.st_info) != STT_FUNC) ||
		    (ss.ss_sym.st_shndx == SHN_UNDEF))
			continue;

		ss.ss_name = elf_strptr(elf, stabshdr.sh_link,
		    ss.ss_sym.st_name);
		ss.ss_data = ((uint8_t *)(textdata->d_buf)) +
		    (ss.ss_sym.st_value - textshdr.sh_addr);

		if (ctf_func_info(fp, symdx, &ss.ss_finfo) == CTF_ERR) {
			fprintf(stderr, "failed to get funcinfo for: %s\n",
			    ss.ss_name);
			continue;
		}

		(void) callback(fp, &ss);
	}
}
コード例 #5
0
ファイル: fbt.c プロジェクト: aglab2/darwin-xnu
/*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;
}
コード例 #6
0
ファイル: apptrace.c プロジェクト: NanXiao/illumos-joyent
uintptr_t
la_pltexit(Elf32_Sym *symp, uint_t symndx, uintptr_t *refcookie,
	uintptr_t *defcookie, uintptr_t retval)
#endif
{
#if	!defined(_LP64)
	const char	*sym_name = (const char *)symp->st_name;
#endif
	sigset_t	omask;
	char		buf[256];
	GElf_Sym	sym;
	prsyminfo_t	si;
	ctf_file_t	*ctfp;
	ctf_funcinfo_t	finfo;
	char		*defname = (char *)(*defcookie);
	char		*refname = (char *)(*refcookie);

	abilock(&omask);

	if (pidout)
		(void) fprintf(ABISTREAM, "%7u:", (unsigned int)getpid());

	if (retval == 0) {
		if (verbose_list == NULL) {
			(void) fprintf(ABISTREAM, "<- %-8s -> %8s:%s()\n",
			    refname, defname, sym_name);
			(void) fflush(ABISTREAM);
		}
		abiunlock(&omask);
		return (retval);
	}

	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;

	if (verbose_list != NULL) {
		if (check_intlist(verbose_list, sym_name) != 0) {
			(void) type_name(ctfp, finfo.ctc_return, buf,
			    sizeof (buf));
			(void) fprintf(ABISTREAM, "\treturn = (%s) ", buf);
			print_value(ctfp, finfo.ctc_return, retval);
			(void) fprintf(ABISTREAM, "\n");
			(void) fprintf(ABISTREAM, "<- %-8s -> %8s:%s()",
			    refname, defname, sym_name);
			(void) fprintf(ABISTREAM, " = 0x%p\n", (void *)retval);
		}
	} else {
		(void) fprintf(ABISTREAM, "<- %-8s -> %8s:%s()",
		    refname, defname, sym_name);
		(void) fprintf(ABISTREAM, " = 0x%p\n", (void *)retval);
	}

	(void) fflush(ABISTREAM);
	abiunlock(&omask);
	return (retval);

fail:
	if (verbose_list != NULL) {
		if (check_intlist(verbose_list, sym_name) != 0) {
			(void) fprintf(ABISTREAM,
			    "\treturn = 0x%p\n", (void *)retval);
			(void) fprintf(ABISTREAM, "<- %-8s -> %8s:%s()",
			    refname, defname, sym_name);
			(void) fprintf(ABISTREAM, " = 0x%p\n", (void *)retval);
		}
	} else {
		(void) fprintf(ABISTREAM, "<- %-8s -> %8s:%s()",
		    refname, defname, sym_name);
		(void) fprintf(ABISTREAM, " = 0x%p\n", (void *)retval);
	}

	(void) fflush(ABISTREAM);
	abiunlock(&omask);
	return (retval);
}
コード例 #7
0
ファイル: apptrace.c プロジェクト: NanXiao/illumos-joyent
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);
}
コード例 #8
0
/*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;
}
コード例 #9
0
ファイル: Pisadep.c プロジェクト: apprisi/illumos-gate
/*
 * 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);
	}
}