summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2013-04-23 23:39:07 +0000
committerRobert Mustacchi <rm@joyent.com>2013-10-14 22:58:34 +0000
commit11af1bb7afbcd29d3a8278aa1ed8648c1c775366 (patch)
treec26fb0793f4f2fd20f8b336d4ef37213da64320e /usr/src/lib
parent538982ca29d23d6117075f50f261f1185cc51a3e (diff)
downloadillumos-joyent-11af1bb7afbcd29d3a8278aa1ed8648c1c775366.tar.gz
OS-2578 DTrace Userland CTF Support
OS-2579 DTrace userland Keyword OS-2580 pid provider types OS-2581 dtest should specify -fPIC when building shared objects OS-2582 dtrace(1) could have ctf OS-2583 dtest tests should explicitly build 32-bit libraries and executables OS-2584 dtest tests should call gcc, not cc OS-2585 dof emulation missing fault checks Reviewed by: Bryan Cantrill <bryan@joyent.com>
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/libctf/common/mapfile-vers6
-rw-r--r--usr/src/lib/libdtrace/common/dt_as.c8
-rw-r--r--usr/src/lib/libdtrace/common/dt_cc.c28
-rw-r--r--usr/src/lib/libdtrace/common/dt_decl.c10
-rw-r--r--usr/src/lib/libdtrace/common/dt_decl.h7
-rw-r--r--usr/src/lib/libdtrace/common/dt_dis.c10
-rw-r--r--usr/src/lib/libdtrace/common/dt_error.c3
-rw-r--r--usr/src/lib/libdtrace/common/dt_grammar.y8
-rw-r--r--usr/src/lib/libdtrace/common/dt_ident.c21
-rw-r--r--usr/src/lib/libdtrace/common/dt_impl.h7
-rw-r--r--usr/src/lib/libdtrace/common/dt_lex.l15
-rw-r--r--usr/src/lib/libdtrace/common/dt_module.c283
-rw-r--r--usr/src/lib/libdtrace/common/dt_module.h10
-rw-r--r--usr/src/lib/libdtrace/common/dt_open.c6
-rw-r--r--usr/src/lib/libdtrace/common/dt_parser.c155
-rw-r--r--usr/src/lib/libdtrace/common/dt_parser.h8
-rw-r--r--usr/src/lib/libdtrace/common/dt_pid.c164
-rw-r--r--usr/src/lib/libdtrace/common/dt_pid.h8
-rw-r--r--usr/src/lib/libdtrace/common/dt_print.c27
-rw-r--r--usr/src/lib/libdtrace/common/dt_printf.c6
-rw-r--r--usr/src/lib/libdtrace/common/dt_provider.c29
-rw-r--r--usr/src/lib/libdtrace/common/dt_xlator.c13
-rw-r--r--usr/src/lib/libdtrace/common/dtrace.h6
23 files changed, 720 insertions, 118 deletions
diff --git a/usr/src/lib/libctf/common/mapfile-vers b/usr/src/lib/libctf/common/mapfile-vers
index 0873de319e..5573e8db25 100644
--- a/usr/src/lib/libctf/common/mapfile-vers
+++ b/usr/src/lib/libctf/common/mapfile-vers
@@ -23,6 +23,10 @@
#
#
+# Copyright (c) 2013, Joyent, Inc. All rights reserved.
+#
+
+#
# MAPFILE HEADER START
#
# WARNING: STOP NOW. DO NOT MODIFY THIS FILE.
@@ -62,6 +66,7 @@ SYMBOL_VERSION SUNWprivate_1.2 {
ctf_create;
ctf_delete_type;
ctf_discard;
+ ctf_dup;
ctf_enum_value;
ctf_label_info;
ctf_label_iter;
@@ -104,6 +109,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
ctf_type_kind;
ctf_type_lname;
ctf_type_name;
+ ctf_type_qname;
ctf_type_reference;
ctf_type_resolve;
ctf_type_size;
diff --git a/usr/src/lib/libdtrace/common/dt_as.c b/usr/src/lib/libdtrace/common/dt_as.c
index 457b8fd721..f937261c35 100644
--- a/usr/src/lib/libdtrace/common/dt_as.c
+++ b/usr/src/lib/libdtrace/common/dt_as.c
@@ -23,8 +23,10 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
#include <sys/types.h>
#include <strings.h>
@@ -125,7 +127,7 @@ dt_copyvar(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
dvp->dtdv_flags |= DIFV_F_MOD;
bzero(&dn, sizeof (dn));
- dt_node_type_assign(&dn, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(&dn, idp->di_ctfp, idp->di_type, B_FALSE);
dt_node_diftype(pcb->pcb_hdl, &dn, &dvp->dtdv_type);
idp->di_flags &= ~(DT_IDFLG_DIFR | DT_IDFLG_DIFW);
diff --git a/usr/src/lib/libdtrace/common/dt_cc.c b/usr/src/lib/libdtrace/common/dt_cc.c
index f4b0509b4a..5d38704ffe 100644
--- a/usr/src/lib/libdtrace/common/dt_cc.c
+++ b/usr/src/lib/libdtrace/common/dt_cc.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@@ -662,6 +662,8 @@ dt_action_printflike(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp,
static void
dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
{
+ int ctflib;
+
dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
boolean_t istrace = (dnp->dn_ident->di_id == DT_ACT_TRACE);
const char *act = istrace ? "trace" : "print";
@@ -693,7 +695,10 @@ dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
* like arrays and function pointers that can't be resolved by
* ctf_type_lookup(). This is later processed by dtrace_dof_create()
* and turned into a reference into the string table so that we can
- * get the type information when we process the data after the fact.
+ * get the type information when we process the data after the fact. In
+ * the case where we are referring to userland CTF data, we also need to
+ * to identify which ctf container in question we care about and encode
+ * that within the name.
*/
if (dnp->dn_ident->di_id == DT_ACT_PRINT) {
dt_node_t *dret;
@@ -703,12 +708,25 @@ dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
dret = yypcb->pcb_dret;
dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
- n = snprintf(NULL, 0, "%s`%d", dmp->dm_name, dret->dn_type) + 1;
+ if (dmp->dm_pid != 0) {
+ ctflib = dt_module_getlibid(dtp, dmp, dret->dn_ctfp);
+ assert(ctflib >= 0);
+ n = snprintf(NULL, 0, "%s`%d`%d", dmp->dm_name,
+ ctflib, dret->dn_type) + 1;
+ } else {
+ n = snprintf(NULL, 0, "%s`%d", dmp->dm_name,
+ dret->dn_type) + 1;
+ }
sdp->dtsd_strdata = dt_alloc(dtp, n);
if (sdp->dtsd_strdata == NULL)
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
- (void) snprintf(sdp->dtsd_strdata, n, "%s`%d", dmp->dm_name,
- dret->dn_type);
+ if (dmp->dm_pid != 0) {
+ (void) snprintf(sdp->dtsd_strdata, n, "%s`%d`%d",
+ dmp->dm_name, ctflib, dret->dn_type);
+ } else {
+ (void) snprintf(sdp->dtsd_strdata, n, "%s`%d",
+ dmp->dm_name, dret->dn_type);
+ }
}
ap->dtad_difo = dt_as(yypcb);
diff --git a/usr/src/lib/libdtrace/common/dt_decl.c b/usr/src/lib/libdtrace/common/dt_decl.c
index 563c0057da..4e99ff4c9f 100644
--- a/usr/src/lib/libdtrace/common/dt_decl.c
+++ b/usr/src/lib/libdtrace/common/dt_decl.c
@@ -21,7 +21,8 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
*/
#include <strings.h>
@@ -775,7 +776,7 @@ dt_decl_enumerator(char *s, dt_node_t *dnp)
yyintdecimal = 0;
dnp = dt_node_int(value);
- dt_node_type_assign(dnp, dsp->ds_ctfp, dsp->ds_type);
+ dt_node_type_assign(dnp, dsp->ds_ctfp, dsp->ds_type, B_FALSE);
if ((inp = malloc(sizeof (dt_idnode_t))) == NULL)
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
@@ -817,6 +818,8 @@ dt_decl_type(dt_decl_t *ddp, dtrace_typeinfo_t *tip)
char *name;
int rv;
+ tip->dtt_flags = 0;
+
/*
* Based on our current #include depth and decl stack depth, determine
* which dynamic CTF module and scope to use when adding any new types.
@@ -824,6 +827,9 @@ dt_decl_type(dt_decl_t *ddp, dtrace_typeinfo_t *tip)
dmp = yypcb->pcb_idepth ? dtp->dt_cdefs : dtp->dt_ddefs;
flag = yypcb->pcb_dstack.ds_next ? CTF_ADD_NONROOT : CTF_ADD_ROOT;
+ if (ddp->dd_attr & DT_DA_USER)
+ tip->dtt_flags = DTT_FL_USER;
+
/*
* If we have already cached a CTF type for this decl, then we just
* return the type information for the cached type.
diff --git a/usr/src/lib/libdtrace/common/dt_decl.h b/usr/src/lib/libdtrace/common/dt_decl.h
index 2933155c78..d322875782 100644
--- a/usr/src/lib/libdtrace/common/dt_decl.h
+++ b/usr/src/lib/libdtrace/common/dt_decl.h
@@ -23,12 +23,14 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
#ifndef _DT_DECL_H
#define _DT_DECL_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <libctf.h>
#include <dtrace.h>
@@ -59,6 +61,7 @@ typedef struct dt_decl {
#define DT_DA_RESTRICT 0x0040 /* qualify type as restrict */
#define DT_DA_VOLATILE 0x0080 /* qualify type as volatile */
#define DT_DA_PAREN 0x0100 /* parenthesis tag */
+#define DT_DA_USER 0x0200 /* user-land type specifier */
typedef enum dt_dclass {
DT_DC_DEFAULT, /* no storage class specified */
diff --git a/usr/src/lib/libdtrace/common/dt_dis.c b/usr/src/lib/libdtrace/common/dt_dis.c
index fff4235a6b..c0af36420e 100644
--- a/usr/src/lib/libdtrace/common/dt_dis.c
+++ b/usr/src/lib/libdtrace/common/dt_dis.c
@@ -26,7 +26,8 @@
*/
/*
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
*/
#include <strings.h>
@@ -312,9 +313,10 @@ dt_dis_typestr(const dtrace_diftype_t *t, char *buf, size_t len)
(void) snprintf(ckind, sizeof (ckind), "0x%x", t->dtdt_ckind);
}
- if (t->dtdt_flags & DIF_TF_BYREF) {
- (void) snprintf(buf, len, "%s (%s) by ref (size %lu)",
- kind, ckind, (ulong_t)t->dtdt_size);
+ if (t->dtdt_flags & (DIF_TF_BYREF | DIF_TF_BYUREF)) {
+ (void) snprintf(buf, len, "%s (%s) by %sref (size %lu)",
+ kind, ckind, (t->dtdt_flags & DIF_TF_BYUREF) ? "user " : "",
+ (ulong_t)t->dtdt_size);
} else {
(void) snprintf(buf, len, "%s (%s) (size %lu)",
kind, ckind, (ulong_t)t->dtdt_size);
diff --git a/usr/src/lib/libdtrace/common/dt_error.c b/usr/src/lib/libdtrace/common/dt_error.c
index f7ad28ebae..d822e2d420 100644
--- a/usr/src/lib/libdtrace/common/dt_error.c
+++ b/usr/src/lib/libdtrace/common/dt_error.c
@@ -110,7 +110,8 @@ static const struct {
{ EDT_BADAGGVAR, "Invalid aggregation variable identifier" },
{ EDT_OVERSION, "Client requested deprecated version of library" },
{ EDT_ENABLING_ERR, "Failed to enable probe" },
- { EDT_NOPROBES, "No probe sites found for declared provider" }
+ { EDT_NOPROBES, "No probe sites found for declared provider" },
+ { EDT_CANTLOAD, "Failed to load module" },
};
static const int _dt_nerr = sizeof (_dt_errlist) / sizeof (_dt_errlist[0]);
diff --git a/usr/src/lib/libdtrace/common/dt_grammar.y b/usr/src/lib/libdtrace/common/dt_grammar.y
index 0c12623bc4..07790f4ebc 100644
--- a/usr/src/lib/libdtrace/common/dt_grammar.y
+++ b/usr/src/lib/libdtrace/common/dt_grammar.y
@@ -23,8 +23,10 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#include <dt_impl.h>
@@ -102,6 +104,7 @@
%token DT_KEY_TYPEDEF
%token DT_KEY_UNION
%token DT_KEY_UNSIGNED
+%token DT_KEY_USERLAND
%token DT_KEY_VOID
%token DT_KEY_VOLATILE
%token DT_KEY_WHILE
@@ -633,6 +636,7 @@ type_specifier: DT_KEY_VOID { $$ = dt_decl_spec(CTF_K_INTEGER, DUP("void")); }
| DT_KEY_DOUBLE { $$ = dt_decl_spec(CTF_K_FLOAT, DUP("double")); }
| DT_KEY_SIGNED { $$ = dt_decl_attr(DT_DA_SIGNED); }
| DT_KEY_UNSIGNED { $$ = dt_decl_attr(DT_DA_UNSIGNED); }
+ | DT_KEY_USERLAND { $$ = dt_decl_attr(DT_DA_USER); }
| DT_KEY_STRING {
$$ = dt_decl_spec(CTF_K_TYPEDEF, DUP("string"));
}
diff --git a/usr/src/lib/libdtrace/common/dt_ident.c b/usr/src/lib/libdtrace/common/dt_ident.c
index 3dfa058b16..33f94eb9fd 100644
--- a/usr/src/lib/libdtrace/common/dt_ident.c
+++ b/usr/src/lib/libdtrace/common/dt_ident.c
@@ -21,6 +21,8 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
*/
#include <sys/sysmacros.h>
@@ -95,7 +97,7 @@ dt_idcook_sign(dt_node_t *dnp, dt_ident_t *idp,
}
}
- dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
}
/*
@@ -154,7 +156,7 @@ dt_idcook_assc(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
if (argc != 0)
isp->dis_args[argc - 1].dn_list = NULL;
- dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
} else {
dt_idcook_sign(dnp, idp, argc, args,
@@ -294,7 +296,7 @@ dt_idcook_func(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
}
dt_node_type_assign(&isp->dis_args[i],
- dtt.dtt_ctfp, dtt.dtt_type);
+ dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
}
}
@@ -381,7 +383,9 @@ dt_idcook_args(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
dt_node_type_assign(dnp,
prp->pr_argv[ap->dn_value].dtt_ctfp,
- prp->pr_argv[ap->dn_value].dtt_type);
+ prp->pr_argv[ap->dn_value].dtt_type,
+ prp->pr_argv[ap->dn_value].dtt_flags & DTT_FL_USER ?
+ B_TRUE : B_FALSE);
} else if ((dxp = dt_xlator_lookup(dtp,
nnp, xnp, DT_XLATE_FUZZY)) != NULL || (
@@ -409,7 +413,8 @@ dt_idcook_args(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
dnp->dn_ident->di_ctfp = xidp->di_ctfp;
dnp->dn_ident->di_type = xidp->di_type;
- dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
+ B_FALSE);
} else {
xyerror(D_ARGS_XLATOR, "translator for %s[%lld] from %s to %s "
@@ -455,7 +460,7 @@ dt_idcook_regs(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
idp->di_ctfp = dtt.dtt_ctfp;
idp->di_type = dtt.dtt_type;
- dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
}
/*ARGSUSED*/
@@ -477,7 +482,7 @@ dt_idcook_type(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
idp->di_type = dtt.dtt_type;
}
- dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
}
/*ARGSUSED*/
@@ -485,7 +490,7 @@ static void
dt_idcook_thaw(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
{
if (idp->di_ctfp != NULL && idp->di_type != CTF_ERR)
- dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
}
static void
diff --git a/usr/src/lib/libdtrace/common/dt_impl.h b/usr/src/lib/libdtrace/common/dt_impl.h
index 6420524701..c0456f3cea 100644
--- a/usr/src/lib/libdtrace/common/dt_impl.h
+++ b/usr/src/lib/libdtrace/common/dt_impl.h
@@ -133,6 +133,10 @@ typedef struct dt_module {
GElf_Addr dm_bss_va; /* virtual address of BSS */
GElf_Xword dm_bss_size; /* size in bytes of BSS */
dt_idhash_t *dm_extern; /* external symbol definitions */
+ pid_t dm_pid; /* pid for this module */
+ uint_t dm_nctflibs; /* number of ctf children libraries */
+ ctf_file_t **dm_libctfp; /* process library ctf pointers */
+ char **dm_libctfn; /* names of process ctf containers */
} dt_module_t;
#define DT_DM_LOADED 0x1 /* module symbol and type data is loaded */
@@ -514,7 +518,8 @@ enum {
EDT_BADAGGVAR, /* invalid aggregation variable identifier */
EDT_OVERSION, /* client is requesting deprecated version */
EDT_ENABLING_ERR, /* failed to enable probe */
- EDT_NOPROBES /* no probes sites for declared provider */
+ EDT_NOPROBES, /* no probes sites for declared provider */
+ EDT_CANTLOAD /* failed to load a module */
};
/*
diff --git a/usr/src/lib/libdtrace/common/dt_lex.l b/usr/src/lib/libdtrace/common/dt_lex.l
index 5b2ad34d2e..5e990e2049 100644
--- a/usr/src/lib/libdtrace/common/dt_lex.l
+++ b/usr/src/lib/libdtrace/common/dt_lex.l
@@ -23,6 +23,10 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#include <string.h>
#include <stdlib.h>
@@ -60,13 +64,17 @@ static void unput(int);
%}
%e 1500 /* maximum nodes */
-%p 3700 /* maximum positions */
+%p 4900 /* maximum positions */
%n 600 /* maximum states */
+%a 3000 /* maximum transitions */
%s S0 S1 S2 S3 S4
RGX_AGG "@"[a-zA-Z_][0-9a-zA-Z_]*
RGX_PSPEC [-$:a-zA-Z_.?*\\\[\]!][-$:0-9a-zA-Z_.`?*\\\[\]!]*
+RGX_ALTIDENT [a-zA-Z_][0-9a-zA-Z_]*
+RGX_LMID LM[0-9a-fA-F]+`
+RGX_MOD_IDENT [a-zA-Z_`][0-9a-z.A-Z_`]*`
RGX_IDENT [a-zA-Z_`][0-9a-zA-Z_`]*
RGX_INT ([0-9]+|0[xX][0-9A-Fa-f]+)[uU]?[lL]?[lL]?
RGX_FP ([0-9]+("."?)[0-9]*|"."[0-9]+)((e|E)("+"|-)?[0-9]+)?[fFlL]?
@@ -136,6 +144,7 @@ if (yypcb->pcb_token != 0) {
<S0>typedef return (DT_KEY_TYPEDEF);
<S0>union return (DT_KEY_UNION);
<S0>unsigned return (DT_KEY_UNSIGNED);
+<S0>userland return (DT_KEY_USERLAND);
<S0>void return (DT_KEY_VOID);
<S0>volatile return (DT_KEY_VOLATILE);
<S0>while return (DT_KEY_WHILE);
@@ -314,7 +323,9 @@ if (yypcb->pcb_token != 0) {
return (DT_TOK_INT);
}
-<S0>{RGX_IDENT} {
+<S0>{RGX_IDENT} |
+<S0>{RGX_MOD_IDENT}{RGX_IDENT} |
+<S0>{RGX_MOD_IDENT} {
return (id_or_type(yytext));
}
diff --git a/usr/src/lib/libdtrace/common/dt_module.c b/usr/src/lib/libdtrace/common/dt_module.c
index 1490f775c3..0288f329da 100644
--- a/usr/src/lib/libdtrace/common/dt_module.c
+++ b/usr/src/lib/libdtrace/common/dt_module.c
@@ -22,6 +22,9 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#include <sys/types.h>
#include <sys/modctl.h>
@@ -418,6 +421,9 @@ static const dt_modops_t dt_modops_64 = {
dt_module_t *
dt_module_create(dtrace_hdl_t *dtp, const char *name)
{
+ long pid;
+ char *eptr;
+ dt_ident_t *idp;
uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_modbuckets;
dt_module_t *dmp;
@@ -441,6 +447,32 @@ dt_module_create(dtrace_hdl_t *dtp, const char *name)
else
dmp->dm_ops = &dt_modops_32;
+ /*
+ * Modules for userland processes are special. They always refer to a
+ * specific process and have a copy of their CTF data from a specific
+ * instant in time. Any dt_module_t that begins with 'pid' is a module
+ * for a specific process, much like how any probe description that
+ * begins with 'pid' is special. pid123 refers to process 123. A module
+ * that is just 'pid' refers specifically to pid$target. This is
+ * generally done as D does not currently allow for macros to be
+ * evaluated when working with types.
+ */
+ if (strncmp(dmp->dm_name, "pid", 3) == 0) {
+ errno = 0;
+ if (dmp->dm_name[3] == '\0') {
+ idp = dt_idhash_lookup(dtp->dt_macros, "target");
+ if (idp != NULL && idp->di_id != 0)
+ dmp->dm_pid = idp->di_id;
+ } else {
+ pid = strtol(dmp->dm_name + 3, &eptr, 10);
+ if (errno == 0 && *eptr == '\0')
+ dmp->dm_pid = (pid_t)pid;
+ else
+ dt_dprintf("encountered malformed pid "
+ "module: %s\n", dmp->dm_name);
+ }
+ }
+
return (dmp);
}
@@ -504,12 +536,169 @@ dt_module_load_sect(dtrace_hdl_t *dtp, dt_module_t *dmp, ctf_sect_t *ctsp)
return (0);
}
+typedef struct dt_module_cb_arg {
+ struct ps_prochandle *dpa_proc;
+ dtrace_hdl_t *dpa_dtp;
+ dt_module_t *dpa_dmp;
+ uint_t dpa_count;
+} dt_module_cb_arg_t;
+
+/* ARGSUSED */
+static int
+dt_module_load_proc_count(void *arg, const prmap_t *prmap, const char *obj)
+{
+ ctf_file_t *fp;
+ dt_module_cb_arg_t *dcp = arg;
+
+ /* Try to grab a ctf container if it exists */
+ fp = Pname_to_ctf(dcp->dpa_proc, obj);
+ if (fp != NULL)
+ dcp->dpa_count++;
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+dt_module_load_proc_build(void *arg, const prmap_t *prmap, const char *obj)
+{
+ ctf_file_t *fp;
+ char buf[MAXPATHLEN], *p;
+ dt_module_cb_arg_t *dcp = arg;
+ int count = dcp->dpa_count;
+ Lmid_t lmid;
+
+ fp = Pname_to_ctf(dcp->dpa_proc, obj);
+ if (fp == NULL)
+ return (0);
+ fp = ctf_dup(fp);
+ if (fp == NULL)
+ return (0);
+ dcp->dpa_dmp->dm_libctfp[count] = fp;
+ /*
+ * While it'd be nice to simply use objname here, because of our prior
+ * actions we'll always get a resolved object name to its on disk file.
+ * Like the pid provider, we need to tell a bit of a lie here. The type
+ * that the user thinks of is in terms of the libraries they requested,
+ * eg. libc.so.1, they don't care about the fact that it's
+ * libc_hwcap.so.1.
+ */
+ (void) Pobjname(dcp->dpa_proc, prmap->pr_vaddr, buf, sizeof (buf));
+ if ((p = strrchr(buf, '/')) == NULL)
+ p = buf;
+ else
+ p++;
+
+ /*
+ * If for some reason we can't find a link map id for this module, which
+ * would be really quite weird. We instead just say the link map id is
+ * zero.
+ */
+ if (Plmid(dcp->dpa_proc, prmap->pr_vaddr, &lmid) != 0)
+ lmid = 0;
+
+ if (lmid == 0)
+ dcp->dpa_dmp->dm_libctfn[count] = strdup(p);
+ else
+ (void) asprintf(&dcp->dpa_dmp->dm_libctfn[count],
+ "LM%lx`%s", lmid, p);
+ if (dcp->dpa_dmp->dm_libctfn[count] == NULL)
+ return (1);
+ ctf_setspecific(fp, dcp->dpa_dmp);
+ dcp->dpa_count++;
+ return (0);
+}
+
+/*
+ * We've been asked to load data that belongs to another process. As such we're
+ * going to pgrab it at this instant, load everything that we might ever care
+ * about, and then drive on. The reason for this is that the process that we're
+ * interested in might be changing. As long as we have grabbed it, then this
+ * can't be a problem for us.
+ *
+ * For now, we're actually going to punt on most things and just try to get CTF
+ * data, nothing else. Basically this is only useful as a source of type
+ * information, we can't go and do the stacktrace lookups, etc.
+ */
+static int
+dt_module_load_proc(dtrace_hdl_t *dtp, dt_module_t *dmp)
+{
+ struct ps_prochandle *p;
+ dt_module_cb_arg_t arg;
+
+ /*
+ * Note that on success we do not release this hold. We must hold this
+ * for our life time.
+ */
+ p = dt_proc_grab(dtp, dmp->dm_pid, 0, PGRAB_RDONLY | PGRAB_FORCE);
+ if (p == NULL) {
+ dt_dprintf("failed to grab pid: %d\n", (int)dmp->dm_pid);
+ return (dt_set_errno(dtp, EDT_CANTLOAD));
+ }
+ dt_proc_lock(dtp, p);
+
+ arg.dpa_proc = p;
+ arg.dpa_dtp = dtp;
+ arg.dpa_dmp = dmp;
+ arg.dpa_count = 0;
+ if (Pobject_iter_resolved(p, dt_module_load_proc_count, &arg) != 0) {
+ dt_dprintf("failed to iterate objects\n");
+ dt_proc_release(dtp, p);
+ return (dt_set_errno(dtp, EDT_CANTLOAD));
+ }
+
+ if (arg.dpa_count == 0) {
+ dt_dprintf("no ctf data present\n");
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+ return (dt_set_errno(dtp, EDT_CANTLOAD));
+ }
+
+ dmp->dm_libctfp = malloc(sizeof (ctf_file_t *) * arg.dpa_count);
+ if (dmp->dm_libctfp == NULL) {
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+ return (dt_set_errno(dtp, EDT_NOMEM));
+ }
+ bzero(dmp->dm_libctfp, sizeof (ctf_file_t *) * arg.dpa_count);
+
+ dmp->dm_libctfn = malloc(sizeof (char *) * arg.dpa_count);
+ if (dmp->dm_libctfn == NULL) {
+ free(dmp->dm_libctfp);
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+ return (dt_set_errno(dtp, EDT_NOMEM));
+ }
+ bzero(dmp->dm_libctfn, sizeof (char *) * arg.dpa_count);
+
+ dmp->dm_nctflibs = arg.dpa_count;
+
+ arg.dpa_count = 0;
+ if (Pobject_iter_resolved(p, dt_module_load_proc_build, &arg) != 0) {
+ dt_proc_unlock(dtp, p);
+ dt_module_unload(dtp, dmp);
+ dt_proc_release(dtp, p);
+ return (dt_set_errno(dtp, EDT_CANTLOAD));
+ }
+ assert(arg.dpa_count == dmp->dm_nctflibs);
+ dt_dprintf("loaded %d ctf modules for pid %d\n", arg.dpa_count,
+ (int)dmp->dm_pid);
+
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+ dmp->dm_flags |= DT_DM_LOADED;
+
+ return (0);
+}
+
int
dt_module_load(dtrace_hdl_t *dtp, dt_module_t *dmp)
{
if (dmp->dm_flags & DT_DM_LOADED)
return (0); /* module is already loaded */
+ if (dmp->dm_pid != 0)
+ return (dt_module_load_proc(dtp, dmp));
+
dmp->dm_ctdata.cts_name = ".SUNW_ctf";
dmp->dm_ctdata.cts_type = SHT_PROGBITS;
dmp->dm_ctdata.cts_flags = 0;
@@ -595,6 +784,14 @@ dt_module_load(dtrace_hdl_t *dtp, dt_module_t *dmp)
return (0);
}
+int
+dt_module_hasctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
+{
+ if (dmp->dm_pid != 0 && dmp->dm_nctflibs > 0)
+ return (1);
+ return (dt_module_getctf(dtp, dmp) != NULL);
+}
+
ctf_file_t *
dt_module_getctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
{
@@ -668,9 +865,22 @@ err:
void
dt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
{
+ int i;
+
ctf_close(dmp->dm_ctfp);
dmp->dm_ctfp = NULL;
+ if (dmp->dm_libctfp != NULL) {
+ for (i = 0; i < dmp->dm_nctflibs; i++) {
+ ctf_close(dmp->dm_libctfp[i]);
+ free(dmp->dm_libctfn[i]);
+ }
+ free(dmp->dm_libctfp);
+ free(dmp->dm_libctfn);
+ dmp->dm_libctfp = NULL;
+ dmp->dm_nctflibs = 0;
+ }
+
bzero(&dmp->dm_ctdata, sizeof (ctf_sect_t));
bzero(&dmp->dm_symtab, sizeof (ctf_sect_t));
bzero(&dmp->dm_strtab, sizeof (ctf_sect_t));
@@ -711,6 +921,8 @@ dt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
(void) elf_end(dmp->dm_elf);
dmp->dm_elf = NULL;
+ dmp->dm_pid = 0;
+
dmp->dm_flags &= ~DT_DM_LOADED;
}
@@ -799,6 +1011,34 @@ dt_module_modelname(dt_module_t *dmp)
return ("32-bit");
}
+/* ARGSUSED */
+int
+dt_module_getlibid(dtrace_hdl_t *dtp, dt_module_t *dmp, const ctf_file_t *fp)
+{
+ int i;
+
+ for (i = 0; i < dmp->dm_nctflibs; i++) {
+ if (dmp->dm_libctfp[i] == fp)
+ return (i);
+ }
+
+ return (-1);
+}
+
+/* ARGSUSED */
+ctf_file_t *
+dt_module_getctflib(dtrace_hdl_t *dtp, dt_module_t *dmp, const char *name)
+{
+ int i;
+
+ for (i = 0; i < dmp->dm_nctflibs; i++) {
+ if (strcmp(dmp->dm_libctfn[i], name) == 0)
+ return (dmp->dm_libctfp[i]);
+ }
+
+ return (NULL);
+}
+
/*
* Update our module cache by adding an entry for the specified module 'name'.
* We create the dt_module_t and populate it using /system/object/<name>/.
@@ -1140,8 +1380,10 @@ dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
dt_module_t *dmp;
int found = 0;
ctf_id_t id;
- uint_t n;
+ uint_t n, i;
int justone;
+ ctf_file_t *fp;
+ char *buf, *p, *q;
uint_t mask = 0; /* mask of dt_module flags to match */
uint_t bits = 0; /* flag bits that must be present */
@@ -1156,7 +1398,6 @@ dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
return (-1); /* dt_errno is set for us */
n = 1;
justone = 1;
-
} else {
if (object == DTRACE_OBJ_KMODS)
mask = bits = DT_DM_KERNEL;
@@ -1180,7 +1421,7 @@ dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
* module. If our search was scoped to only one module then
* return immediately leaving dt_errno unmodified.
*/
- if (dt_module_getctf(dtp, dmp) == NULL) {
+ if (dt_module_hasctf(dtp, dmp) == 0) {
if (justone)
return (-1);
continue;
@@ -1192,13 +1433,38 @@ dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
* 'tip' and keep going in the hope that we will locate the
* underlying structure definition. Otherwise just return.
*/
- if ((id = ctf_lookup_by_name(dmp->dm_ctfp, name)) != CTF_ERR) {
+ if (dmp->dm_pid == 0) {
+ id = ctf_lookup_by_name(dmp->dm_ctfp, name);
+ fp = dmp->dm_ctfp;
+ } else {
+ if ((p = strchr(name, '`')) != NULL) {
+ buf = strdup(name);
+ if (buf == NULL)
+ return (dt_set_errno(dtp, EDT_NOMEM));
+ p = strchr(buf, '`');
+ if ((q = strchr(p + 1, '`')) != NULL)
+ p = q;
+ *p = '\0';
+ fp = dt_module_getctflib(dtp, dmp, buf);
+ if (fp == NULL || (id = ctf_lookup_by_name(fp,
+ p + 1)) == CTF_ERR)
+ id = CTF_ERR;
+ free(buf);
+ } else {
+ for (i = 0; i < dmp->dm_nctflibs; i++) {
+ fp = dmp->dm_libctfp[i];
+ id = ctf_lookup_by_name(fp, name);
+ if (id != CTF_ERR)
+ break;
+ }
+ }
+ }
+ if (id != CTF_ERR) {
tip->dtt_object = dmp->dm_name;
- tip->dtt_ctfp = dmp->dm_ctfp;
+ tip->dtt_ctfp = fp;
tip->dtt_type = id;
-
- if (ctf_type_kind(dmp->dm_ctfp, ctf_type_resolve(
- dmp->dm_ctfp, id)) != CTF_K_FORWARD)
+ if (ctf_type_kind(fp, ctf_type_resolve(fp, id)) !=
+ CTF_K_FORWARD)
return (0);
found++;
@@ -1220,6 +1486,7 @@ dtrace_symbol_type(dtrace_hdl_t *dtp, const GElf_Sym *symp,
tip->dtt_object = NULL;
tip->dtt_ctfp = NULL;
tip->dtt_type = CTF_ERR;
+ tip->dtt_flags = 0;
if ((dmp = dt_module_lookup_by_name(dtp, sip->dts_object)) == NULL)
return (dt_set_errno(dtp, EDT_NOMOD));
diff --git a/usr/src/lib/libdtrace/common/dt_module.h b/usr/src/lib/libdtrace/common/dt_module.h
index 8334a2bb81..d103e028e4 100644
--- a/usr/src/lib/libdtrace/common/dt_module.h
+++ b/usr/src/lib/libdtrace/common/dt_module.h
@@ -23,12 +23,13 @@
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#ifndef _DT_MODULE_H
#define _DT_MODULE_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <dt_impl.h>
#ifdef __cplusplus
@@ -43,11 +44,16 @@ extern void dt_module_destroy(dtrace_hdl_t *, dt_module_t *);
extern dt_module_t *dt_module_lookup_by_name(dtrace_hdl_t *, const char *);
extern dt_module_t *dt_module_lookup_by_ctf(dtrace_hdl_t *, ctf_file_t *);
+extern int dt_module_hasctf(dtrace_hdl_t *, dt_module_t *);
extern ctf_file_t *dt_module_getctf(dtrace_hdl_t *, dt_module_t *);
extern dt_ident_t *dt_module_extern(dtrace_hdl_t *, dt_module_t *,
const char *, const dtrace_typeinfo_t *);
extern const char *dt_module_modelname(dt_module_t *);
+extern int dt_module_getlibid(dtrace_hdl_t *, dt_module_t *,
+ const ctf_file_t *);
+extern ctf_file_t *dt_module_getctflib(dtrace_hdl_t *, dt_module_t *,
+ const char *);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libdtrace/common/dt_open.c b/usr/src/lib/libdtrace/common/dt_open.c
index af3bc17b2c..1fa11f81e9 100644
--- a/usr/src/lib/libdtrace/common/dt_open.c
+++ b/usr/src/lib/libdtrace/common/dt_open.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@@ -112,8 +112,9 @@
#define DT_VERS_1_9 DT_VERSION_NUMBER(1, 9, 0)
#define DT_VERS_1_10 DT_VERSION_NUMBER(1, 10, 0)
#define DT_VERS_1_11 DT_VERSION_NUMBER(1, 11, 0)
+#define DT_VERS_1_12 DT_VERSION_NUMBER(1, 12, 0)
#define DT_VERS_LATEST DT_VERS_1_11
-#define DT_VERS_STRING "Sun D 1.11"
+#define DT_VERS_STRING "Sun D 1.12"
const dt_version_t _dtrace_versions[] = {
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -136,6 +137,7 @@ const dt_version_t _dtrace_versions[] = {
DT_VERS_1_9, /* D API 1.9 */
DT_VERS_1_10, /* D API 1.10 */
DT_VERS_1_11, /* D API 1.11 */
+ DT_VERS_1_12, /* D API 1.12 */
0
};
diff --git a/usr/src/lib/libdtrace/common/dt_parser.c b/usr/src/lib/libdtrace/common/dt_parser.c
index 6f837c4bed..753009f857 100644
--- a/usr/src/lib/libdtrace/common/dt_parser.c
+++ b/usr/src/lib/libdtrace/common/dt_parser.c
@@ -21,8 +21,8 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
/*
@@ -192,7 +192,7 @@ dt_type_lookup(const char *s, dtrace_typeinfo_t *tip)
{
static const char delimiters[] = " \t\n\r\v\f*`";
dtrace_hdl_t *dtp = yypcb->pcb_hdl;
- const char *p, *q, *end, *obj;
+ const char *p, *q, *r, *end, *obj;
for (p = s, end = s + strlen(s); *p != '\0'; p = q) {
while (isspace(*p))
@@ -220,8 +220,23 @@ dt_type_lookup(const char *s, dtrace_typeinfo_t *tip)
bcopy(s, type, (size_t)(p - s));
bcopy(q + 1, type + (size_t)(p - s), strlen(q + 1) + 1);
- if (strchr(q + 1, '`') != NULL)
- return (dt_set_errno(dtp, EDT_BADSCOPE));
+ /*
+ * There may be at most three delimeters. The second
+ * delimeter is usually used to distinguish the type
+ * within a given module, however, there could be a link
+ * map id on the scene in which case that delimeter
+ * would be the third. We determine presence of the lmid
+ * if it rouglhly meets the from LM[0-9]
+ */
+ if ((r = strchr(q + 1, '`')) != NULL &&
+ ((r = strchr(r + 1, '`')) != NULL)) {
+ if (strchr(r + 1, '`') != NULL)
+ return (dt_set_errno(dtp,
+ EDT_BADSCOPE));
+ if (q[1] != 'L' || q[2] != 'M')
+ return (dt_set_errno(dtp,
+ EDT_BADSCOPE));
+ }
return (dtrace_lookup_by_type(dtp, object, type, tip));
}
@@ -251,6 +266,7 @@ dt_type_pointer(dtrace_typeinfo_t *tip)
ctf_file_t *ctfp = tip->dtt_ctfp;
ctf_id_t type = tip->dtt_type;
ctf_id_t base = ctf_type_resolve(ctfp, type);
+ uint_t bflags = tip->dtt_flags;
dt_module_t *dmp;
ctf_id_t ptr;
@@ -282,6 +298,7 @@ dt_type_pointer(dtrace_typeinfo_t *tip)
tip->dtt_object = dmp->dm_name;
tip->dtt_ctfp = dmp->dm_ctfp;
tip->dtt_type = ptr;
+ tip->dtt_flags = bflags;
return (0);
}
@@ -385,7 +402,7 @@ void
dt_node_promote(dt_node_t *lp, dt_node_t *rp, dt_node_t *dnp)
{
dt_type_promote(lp, rp, &dnp->dn_ctfp, &dnp->dn_type);
- dt_node_type_assign(dnp, dnp->dn_ctfp, dnp->dn_type);
+ dt_node_type_assign(dnp, dnp->dn_ctfp, dnp->dn_type, B_FALSE);
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
}
@@ -654,7 +671,8 @@ dt_node_attr_assign(dt_node_t *dnp, dtrace_attribute_t attr)
}
void
-dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type)
+dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type,
+ boolean_t user)
{
ctf_id_t base = ctf_type_resolve(fp, type);
uint_t kind = ctf_type_kind(fp, base);
@@ -686,6 +704,9 @@ dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type)
type == DT_DYN_TYPE(yypcb->pcb_hdl))
dnp->dn_flags |= DT_NF_REF;
+ if (user)
+ dnp->dn_flags |= DT_NF_USERLAND;
+
dnp->dn_flags |= DT_NF_COOKED;
dnp->dn_ctfp = fp;
dnp->dn_type = type;
@@ -723,6 +744,7 @@ size_t
dt_node_type_size(const dt_node_t *dnp)
{
ctf_id_t base;
+ dtrace_hdl_t *dtp = yypcb->pcb_hdl;
if (dnp->dn_kind == DT_NODE_STRING)
return (strlen(dnp->dn_string) + 1);
@@ -735,6 +757,20 @@ dt_node_type_size(const dt_node_t *dnp)
if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_FORWARD)
return (0);
+ /*
+ * Here we have a 32-bit user pointer that is being used with a 64-bit
+ * kernel. When we're using it and its tagged as a userland reference --
+ * then we need to keep it as a 32-bit pointer. However, if we are
+ * referring to it as a kernel address, eg. being used after a copyin()
+ * then we need to make sure that we actually return the kernel's size
+ * of a pointer, 8 bytes.
+ */
+ if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_POINTER &&
+ ctf_getmodel(dnp->dn_ctfp) == CTF_MODEL_ILP32 &&
+ !(dnp->dn_flags & DT_NF_USERLAND) &&
+ dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64)
+ return (8);
+
return (ctf_type_size(dnp->dn_ctfp, dnp->dn_type));
}
@@ -1221,7 +1257,7 @@ dt_node_int(uintmax_t value)
if (value <= dtp->dt_ints[i].did_limit) {
dt_node_type_assign(dnp,
dtp->dt_ints[i].did_ctfp,
- dtp->dt_ints[i].did_type);
+ dtp->dt_ints[i].did_type, B_FALSE);
/*
* If a prefix character is present in macro text, add
@@ -1256,7 +1292,7 @@ dt_node_string(char *string)
dnp = dt_node_alloc(DT_NODE_STRING);
dnp->dn_op = DT_TOK_STRING;
dnp->dn_string = string;
- dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp), B_FALSE);
return (dnp);
}
@@ -1332,7 +1368,8 @@ dt_node_type(dt_decl_t *ddp)
dnp = dt_node_alloc(DT_NODE_TYPE);
dnp->dn_op = DT_TOK_IDENT;
dnp->dn_string = name;
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, dtt.dtt_flags);
if (dtt.dtt_ctfp == dtp->dt_cdefs->dm_ctfp ||
dtt.dtt_ctfp == dtp->dt_ddefs->dm_ctfp)
@@ -1576,7 +1613,8 @@ dt_node_decl(void)
bzero(&idn, sizeof (dt_node_t));
if (idp != NULL && idp->di_type != CTF_ERR)
- dt_node_type_assign(&idn, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(&idn, idp->di_ctfp, idp->di_type,
+ B_FALSE);
else if (idp != NULL)
(void) dt_ident_cook(&idn, idp, NULL);
@@ -1785,7 +1823,7 @@ dt_node_offsetof(dt_decl_t *ddp, char *s)
}
bzero(&dn, sizeof (dn));
- dt_node_type_assign(&dn, dtt.dtt_ctfp, ctm.ctm_type);
+ dt_node_type_assign(&dn, dtt.dtt_ctfp, ctm.ctm_type, B_FALSE);
if (dn.dn_flags & DT_NF_BITFIELD) {
xyerror(D_OFFSETOF_BITFIELD,
@@ -1841,7 +1879,8 @@ dt_node_op1(int op, dt_node_t *cp)
}
dt_node_type_assign(cp, dtp->dt_ddefs->dm_ctfp,
- ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"));
+ ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"),
+ B_FALSE);
cp->dn_kind = DT_NODE_INT;
cp->dn_op = DT_TOK_INT;
@@ -1919,17 +1958,17 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
case DT_TOK_LOR:
dnp->dn_value = l || r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_LXOR:
dnp->dn_value = (l != 0) ^ (r != 0);
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_LAND:
dnp->dn_value = l && r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_BOR:
dnp->dn_value = l | r;
@@ -1946,12 +1985,12 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
case DT_TOK_EQU:
dnp->dn_value = l == r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_NEQ:
dnp->dn_value = l != r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_LT:
dt_node_promote(lp, rp, dnp);
@@ -1960,7 +1999,7 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
else
dnp->dn_value = l < r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_LE:
dt_node_promote(lp, rp, dnp);
@@ -1969,7 +2008,7 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
else
dnp->dn_value = l <= r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_GT:
dt_node_promote(lp, rp, dnp);
@@ -1978,7 +2017,7 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
else
dnp->dn_value = l > r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_GE:
dt_node_promote(lp, rp, dnp);
@@ -1987,7 +2026,7 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
else
dnp->dn_value = l >= r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_LSH:
dnp->dn_value = l << r;
@@ -2228,7 +2267,7 @@ dt_node_inline(dt_node_t *expr)
* until we have successfully cooked the right-hand expression, below.
*/
dnp = dt_node_alloc(DT_NODE_INLINE);
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
dt_node_attr_assign(dnp, _dtrace_defattr);
if (dt_node_is_void(dnp)) {
@@ -2383,7 +2422,8 @@ dt_node_member(dt_decl_t *ddp, char *name, dt_node_t *expr)
dnp->dn_membexpr = expr;
if (ddp != NULL)
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
+ dtt.dtt_flags);
return (dnp);
}
@@ -2414,10 +2454,10 @@ dt_node_xlator(dt_decl_t *ddp, dt_decl_t *sdp, char *name, dt_node_t *members)
}
bzero(&sn, sizeof (sn));
- dt_node_type_assign(&sn, src.dtt_ctfp, src.dtt_type);
+ dt_node_type_assign(&sn, src.dtt_ctfp, src.dtt_type, B_FALSE);
bzero(&dn, sizeof (dn));
- dt_node_type_assign(&dn, dst.dtt_ctfp, dst.dtt_type);
+ dt_node_type_assign(&dn, dst.dtt_ctfp, dst.dtt_type, B_FALSE);
if (dt_xlator_lookup(dtp, &sn, &dn, DT_XLATE_EXACT) != NULL) {
xyerror(D_XLATE_REDECL,
@@ -2663,7 +2703,7 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create)
attr = dt_ident_cook(dnp, idp, NULL);
else {
dt_node_type_assign(dnp,
- DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);
attr = idp->di_attr;
}
@@ -2739,7 +2779,8 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create)
dnp->dn_ident = idp;
dnp->dn_flags |= DT_NF_LVALUE;
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
+ dtt.dtt_flags);
dt_node_attr_assign(dnp, _dtrace_symattr);
if (uref) {
@@ -2787,7 +2828,7 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create)
attr = dt_ident_cook(dnp, idp, NULL);
else {
dt_node_type_assign(dnp,
- DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);
attr = idp->di_attr;
}
@@ -2890,7 +2931,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
xyerror(D_TYPE_ERR, "failed to lookup int64_t\n");
dt_ident_type_assign(cp->dn_ident, dtt.dtt_ctfp, dtt.dtt_type);
- dt_node_type_assign(cp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(cp, dtt.dtt_ctfp, dtt.dtt_type,
+ dtt.dtt_flags);
}
if (cp->dn_kind == DT_NODE_VAR)
@@ -2907,7 +2949,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
dnp->dn_ident = &dxp->dx_souid;
dt_node_type_assign(dnp,
- dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type);
+ dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type,
+ cp->dn_flags & DT_NF_USERLAND);
break;
}
@@ -2927,7 +2970,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
"cannot dereference non-pointer type\n");
}
- dt_node_type_assign(dnp, cp->dn_ctfp, type);
+ dt_node_type_assign(dnp, cp->dn_ctfp, type,
+ cp->dn_flags & DT_NF_USERLAND);
base = ctf_type_resolve(cp->dn_ctfp, type);
kind = ctf_type_kind(cp->dn_ctfp, base);
@@ -2984,7 +3028,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
xyerror(D_OP_SCALAR, "operator %s requires an operand "
"of scalar type\n", opstr(dnp->dn_op));
}
- dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),
+ B_FALSE);
break;
case DT_TOK_ADDROF:
@@ -3017,10 +3062,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
dt_node_type_name(cp, n, sizeof (n)));
}
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
-
- if (cp->dn_flags & DT_NF_USERLAND)
- dnp->dn_flags |= DT_NF_USERLAND;
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
+ cp->dn_flags & DT_NF_USERLAND);
break;
case DT_TOK_SIZEOF:
@@ -3035,7 +3078,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
}
dt_node_type_assign(dnp, dtp->dt_ddefs->dm_ctfp,
- ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"));
+ ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"),
+ B_FALSE);
break;
case DT_TOK_STRINGOF:
@@ -3045,7 +3089,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
"cannot apply stringof to a value of type %s\n",
dt_node_type_name(cp, n, sizeof (n)));
}
- dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp),
+ cp->dn_flags & DT_NF_USERLAND);
break;
case DT_TOK_PREINC:
@@ -3238,7 +3283,8 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
"of scalar type\n", opstr(op));
}
- dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),
+ B_FALSE);
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
break;
@@ -3282,7 +3328,8 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
rp->dn_op = DT_TOK_INT;
rp->dn_value = (intmax_t)val;
- dt_node_type_assign(rp, lp->dn_ctfp, lp->dn_type);
+ dt_node_type_assign(rp, lp->dn_ctfp, lp->dn_type,
+ B_FALSE);
dt_node_attr_assign(rp, _dtrace_symattr);
}
@@ -3314,7 +3361,8 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
dt_node_type_name(rp, n2, sizeof (n2)));
}
- dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),
+ B_FALSE);
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
break;
@@ -3362,7 +3410,7 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
dt_node_type_name(rp, n2, sizeof (n2)));
}
- dt_node_type_assign(dnp, ctfp, type);
+ dt_node_type_assign(dnp, ctfp, type, B_FALSE);
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
if (uref)
@@ -3503,7 +3551,7 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
*/
if (lp->dn_kind == DT_NODE_VAR &&
dt_ident_unref(lp->dn_ident)) {
- dt_node_type_assign(lp, ctfp, type);
+ dt_node_type_assign(lp, ctfp, type, B_FALSE);
dt_ident_type_assign(lp->dn_ident, ctfp, type);
if (uref) {
@@ -3717,7 +3765,7 @@ asgn_common:
type = ctf_type_resolve(ctfp, m.ctm_type);
kind = ctf_type_kind(ctfp, type);
- dt_node_type_assign(dnp, ctfp, m.ctm_type);
+ dt_node_type_assign(dnp, ctfp, m.ctm_type, B_FALSE);
dt_node_attr_assign(dnp, lp->dn_attr);
if (op == DT_TOK_PTR && (kind != CTF_K_ARRAY ||
@@ -3843,7 +3891,8 @@ asgn_common:
}
dnp->dn_ident = dt_xlator_ident(dxp, lp->dn_ctfp, lp->dn_type);
- dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
+ B_FALSE);
dt_node_attr_assign(dnp,
dt_attr_min(rp->dn_attr, dnp->dn_ident->di_attr));
break;
@@ -4008,7 +4057,7 @@ dt_cook_op3(dt_node_t *dnp, uint_t idflags)
"used in a conditional context\n");
}
- dt_node_type_assign(dnp, ctfp, type);
+ dt_node_type_assign(dnp, ctfp, type, B_FALSE);
dt_node_attr_assign(dnp, dt_attr_min(dnp->dn_expr->dn_attr,
dt_attr_min(lp->dn_attr, rp->dn_attr)));
@@ -4041,7 +4090,8 @@ dt_cook_aggregation(dt_node_t *dnp, uint_t idflags)
dt_node_attr_assign(dnp, dt_ident_cook(dnp,
dnp->dn_ident, &dnp->dn_aggtup));
} else {
- dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
+ B_FALSE);
dt_node_attr_assign(dnp, dnp->dn_ident->di_attr);
}
@@ -4243,7 +4293,8 @@ dt_cook_xlator(dt_node_t *dnp, uint_t idflags)
}
(void) dt_node_cook(mnp, DT_IDFLG_REF);
- dt_node_type_assign(mnp, dxp->dx_dst_ctfp, ctm.ctm_type);
+ dt_node_type_assign(mnp, dxp->dx_dst_ctfp, ctm.ctm_type,
+ B_FALSE);
attr = dt_attr_min(attr, mnp->dn_attr);
if (dt_node_is_argcompat(mnp, mnp->dn_membexpr) == 0) {
@@ -4262,7 +4313,7 @@ dt_cook_xlator(dt_node_t *dnp, uint_t idflags)
dxp->dx_souid.di_attr = attr;
dxp->dx_ptrid.di_attr = attr;
- dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);
dt_node_attr_assign(dnp, _dtrace_defattr);
return (dnp);
@@ -4555,7 +4606,9 @@ dt_node_diftype(dtrace_hdl_t *dtp, const dt_node_t *dnp, dtrace_diftype_t *tp)
ctf_type_resolve(dnp->dn_ctfp, dnp->dn_type));
}
- tp->dtdt_flags = (dnp->dn_flags & DT_NF_REF) ? DIF_TF_BYREF : 0;
+ tp->dtdt_flags = (dnp->dn_flags & DT_NF_REF) ?
+ (dnp->dn_flags & DT_NF_USERLAND) ? DIF_TF_BYUREF :
+ DIF_TF_BYREF : 0;
tp->dtdt_pad = 0;
tp->dtdt_size = ctf_type_size(dnp->dn_ctfp, dnp->dn_type);
}
diff --git a/usr/src/lib/libdtrace/common/dt_parser.h b/usr/src/lib/libdtrace/common/dt_parser.h
index 6064efb2e6..38f21c9f2e 100644
--- a/usr/src/lib/libdtrace/common/dt_parser.h
+++ b/usr/src/lib/libdtrace/common/dt_parser.h
@@ -22,12 +22,14 @@
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
#ifndef _DT_PARSER_H
#define _DT_PARSER_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/dtrace.h>
@@ -223,7 +225,7 @@ extern void dt_node_list_free(dt_node_t **);
extern void dt_node_link_free(dt_node_t **);
extern void dt_node_attr_assign(dt_node_t *, dtrace_attribute_t);
-extern void dt_node_type_assign(dt_node_t *, ctf_file_t *, ctf_id_t);
+extern void dt_node_type_assign(dt_node_t *, ctf_file_t *, ctf_id_t, boolean_t);
extern void dt_node_type_propagate(const dt_node_t *, dt_node_t *);
extern const char *dt_node_type_name(const dt_node_t *, char *, size_t);
extern size_t dt_node_type_size(const dt_node_t *);
diff --git a/usr/src/lib/libdtrace/common/dt_pid.c b/usr/src/lib/libdtrace/common/dt_pid.c
index 241805154a..881db806f4 100644
--- a/usr/src/lib/libdtrace/common/dt_pid.c
+++ b/usr/src/lib/libdtrace/common/dt_pid.c
@@ -23,6 +23,9 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#include <assert.h>
#include <strings.h>
@@ -33,11 +36,13 @@
#include <alloca.h>
#include <libgen.h>
#include <stddef.h>
+#include <sys/sysmacros.h>
#include <dt_impl.h>
#include <dt_program.h>
#include <dt_pid.h>
#include <dt_string.h>
+#include <dt_module.h>
typedef struct dt_pid_probe {
dtrace_hdl_t *dpp_dtp;
@@ -755,3 +760,162 @@ dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr)
return (ret);
}
+
+/*
+ * libdtrace has a backroom deal with us to ask us for type information on
+ * behalf of pid provider probes when fasttrap doesn't return any type
+ * information. Instead we'll look up the module and see if there is type
+ * information available. However, if there is no type information available due
+ * to a lack of CTF data, then we want to make sure that DTrace still carries on
+ * in face of that. As such we don't have a meaningful exit code about failure.
+ * We emit information about why we failed to the dtrace debug log so someone
+ * can figure it out by asking nicely for DTRACE_DEBUG.
+ */
+void
+dt_pid_get_types(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp,
+ dtrace_argdesc_t *adp, int *nargs)
+{
+ dt_module_t *dmp;
+ ctf_file_t *fp;
+ ctf_funcinfo_t f;
+ ctf_id_t argv[32];
+ GElf_Sym sym;
+ prsyminfo_t si;
+ struct ps_prochandle *p;
+ int i, args;
+ char buf[DTRACE_ARGTYPELEN];
+ const char *mptr;
+ char *eptr;
+ int ret = 0;
+ int argc = sizeof (argv) / sizeof (ctf_id_t);
+ Lmid_t lmid;
+
+ /* Set up a potential outcome */
+ args = *nargs;
+ *nargs = 0;
+
+ /*
+ * If we don't have an entry or return probe then we can just stop right
+ * now as we don't have arguments for offset probes.
+ */
+ if (strcmp(pdp->dtpd_name, "entry") != 0 &&
+ strcmp(pdp->dtpd_name, "return") != 0)
+ return;
+
+ dmp = dt_module_create(dtp, pdp->dtpd_provider);
+ if (dmp == NULL) {
+ dt_dprintf("failed to find module for %s\n",
+ pdp->dtpd_provider);
+ return;
+ }
+ if (dt_module_load(dtp, dmp) != 0) {
+ dt_dprintf("failed to load module for %s\n",
+ pdp->dtpd_provider);
+ return;
+ }
+
+ /*
+ * We may be working with a module that doesn't have ctf. If that's the
+ * case then we just return now and move on with life.
+ */
+ fp = dt_module_getctflib(dtp, dmp, pdp->dtpd_mod);
+ if (fp == NULL) {
+ dt_dprintf("no ctf container for %s\n",
+ pdp->dtpd_mod);
+ return;
+ }
+ p = dt_proc_grab(dtp, dmp->dm_pid, 0, PGRAB_RDONLY | PGRAB_FORCE);
+ if (p == NULL) {
+ dt_dprintf("failed to grab pid\n");
+ return;
+ }
+ dt_proc_lock(dtp, p);
+
+ /*
+ * Check to see if the D module has a link map ID and separate that out
+ * for properly interrogating libproc.
+ */
+ if ((mptr = strchr(pdp->dtpd_mod, '`')) != NULL) {
+ if (strlen(pdp->dtpd_mod) < 3) {
+ dt_dprintf("found weird modname with linkmap, "
+ "aborting: %s\n", pdp->dtpd_mod);
+ goto out;
+ }
+ if (pdp->dtpd_mod[0] != 'L' || pdp->dtpd_mod[1] != 'M') {
+ dt_dprintf("missing leading 'LM', "
+ "aborting: %s\n", pdp->dtpd_mod);
+ goto out;
+ }
+ errno = 0;
+ lmid = strtol(pdp->dtpd_mod + 2, &eptr, 16);
+ if (errno == ERANGE || eptr != mptr) {
+ dt_dprintf("failed to parse out lmid, aborting: %s\n",
+ pdp->dtpd_mod);
+ goto out;
+ }
+ mptr++;
+ } else {
+ mptr = pdp->dtpd_mod;
+ lmid = 0;
+ }
+
+ if (Pxlookup_by_name(p, lmid, mptr, pdp->dtpd_func,
+ &sym, &si) != 0) {
+ dt_dprintf("failed to find function %s in %s`%s\n",
+ pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);
+ goto out;
+ }
+ if (ctf_func_info(fp, si.prs_id, &f) == CTF_ERR) {
+ dt_dprintf("failed to get ctf information for %s in %s`%s\n",
+ pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);
+ goto out;
+ }
+
+ (void) snprintf(buf, sizeof (buf), "%s`%s", pdp->dtpd_provider,
+ pdp->dtpd_mod);
+
+ if (strcmp(pdp->dtpd_name, "return") == 0) {
+ if (args < 2)
+ goto out;
+
+ bzero(adp, sizeof (dtrace_argdesc_t));
+ adp->dtargd_ndx = 0;
+ adp->dtargd_id = pdp->dtpd_id;
+ adp->dtargd_mapping = adp->dtargd_ndx;
+ /*
+ * We explicitly leave out the library here, we only care that
+ * it is some int. We are assuming that there is no ctf
+ * container in here that is lying about what an int is.
+ */
+ (void) snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
+ "user %s`%s", pdp->dtpd_provider, "int");
+ adp++;
+ bzero(adp, sizeof (dtrace_argdesc_t));
+ adp->dtargd_ndx = 1;
+ adp->dtargd_id = pdp->dtpd_id;
+ adp->dtargd_mapping = adp->dtargd_ndx;
+ ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
+ "userland ");
+ (void) ctf_type_qname(fp, f.ctc_return, adp->dtargd_native +
+ ret, DTRACE_ARGTYPELEN - ret, buf);
+ *nargs = 2;
+ } else {
+ if (ctf_func_args(fp, si.prs_id, argc, argv) == CTF_ERR)
+ goto out;
+
+ *nargs = MIN(args, f.ctc_argc);
+ for (i = 0; i < *nargs; i++, adp++) {
+ bzero(adp, sizeof (dtrace_argdesc_t));
+ adp->dtargd_ndx = i;
+ adp->dtargd_id = pdp->dtpd_id;
+ adp->dtargd_mapping = adp->dtargd_ndx;
+ ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
+ "userland ");
+ (void) ctf_type_qname(fp, argv[i], adp->dtargd_native +
+ ret, DTRACE_ARGTYPELEN - ret, buf);
+ }
+ }
+out:
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+}
diff --git a/usr/src/lib/libdtrace/common/dt_pid.h b/usr/src/lib/libdtrace/common/dt_pid.h
index 886e33d833..4bf39c8645 100644
--- a/usr/src/lib/libdtrace/common/dt_pid.h
+++ b/usr/src/lib/libdtrace/common/dt_pid.h
@@ -24,12 +24,13 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#ifndef _DT_PID_H
#define _DT_PID_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <libproc.h>
#include <sys/fasttrap.h>
#include <dt_impl.h>
@@ -57,6 +58,9 @@ extern int dt_pid_create_offset_probe(struct ps_prochandle *, dtrace_hdl_t *,
extern int dt_pid_create_glob_offset_probes(struct ps_prochandle *,
dtrace_hdl_t *, fasttrap_probe_spec_t *, const GElf_Sym *, const char *);
+extern void dt_pid_get_types(dtrace_hdl_t *, const dtrace_probedesc_t *,
+ dtrace_argdesc_t *, int *);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libdtrace/common/dt_print.c b/usr/src/lib/libdtrace/common/dt_print.c
index e258f9ac54..b71eddbf9d 100644
--- a/usr/src/lib/libdtrace/common/dt_print.c
+++ b/usr/src/lib/libdtrace/common/dt_print.c
@@ -649,12 +649,16 @@ dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename,
dt_printarg_t pa;
ctf_id_t id;
dt_module_t *dmp;
+ ctf_file_t *ctfp;
+ int libid;
/*
* Split the fully-qualified type ID (module`id). This should
* always be the format, but if for some reason we don't find the
* expected value, return 0 to fall back to the generic trace()
- * behavior.
+ * behavior. In the case of userland CTF modules this will actually be
+ * of the format (module`lib`id). This is due to the fact that those
+ * modules have multiple CTF containers which `lib` identifies.
*/
for (s = typename; *s != '\0' && *s != '`'; s++)
;
@@ -665,6 +669,20 @@ dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename,
object = alloca(s - typename + 1);
bcopy(typename, object, s - typename);
object[s - typename] = '\0';
+ dmp = dt_module_lookup_by_name(dtp, object);
+ if (dmp == NULL)
+ return (0);
+
+ if (dmp->dm_pid != 0) {
+ libid = atoi(s + 1);
+ s = strchr(s + 1, '`');
+ if (s == NULL || libid > dmp->dm_nctflibs)
+ return (0);
+ ctfp = dmp->dm_libctfp[libid];
+ } else {
+ ctfp = dt_module_getctf(dtp, dmp);
+ }
+
id = atoi(s + 1);
/*
@@ -672,16 +690,13 @@ dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename,
* wrong and we can't resolve the ID, bail out and let trace() do the
* work.
*/
- dmp = dt_module_lookup_by_name(dtp, object);
- if (dmp == NULL || ctf_type_kind(dt_module_getctf(dtp, dmp),
- id) == CTF_ERR) {
+ if (ctfp == NULL || ctf_type_kind(ctfp, id) == CTF_ERR)
return (0);
- }
/* setup the print structure and kick off the main print routine */
pa.pa_dtp = dtp;
pa.pa_addr = addr;
- pa.pa_ctfp = dt_module_getctf(dtp, dmp);
+ pa.pa_ctfp = ctfp;
pa.pa_nest = 0;
pa.pa_depth = 0;
pa.pa_file = fp;
diff --git a/usr/src/lib/libdtrace/common/dt_printf.c b/usr/src/lib/libdtrace/common/dt_printf.c
index 8d96bd4c71..7bd91b9f48 100644
--- a/usr/src/lib/libdtrace/common/dt_printf.c
+++ b/usr/src/lib/libdtrace/common/dt_printf.c
@@ -21,8 +21,8 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#include <sys/sysmacros.h>
@@ -1048,7 +1048,7 @@ dt_printf_validate(dt_pfargv_t *pfv, uint_t flags,
xyerror(D_TYPE_ERR, "failed to lookup agg type %s\n", aggtype);
bzero(&aggnode, sizeof (aggnode));
- dt_node_type_assign(&aggnode, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(&aggnode, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
for (i = 0, j = 0; i < pfv->pfv_argc; i++, pfd = pfd->pfd_next) {
const dt_pfconv_t *pfc = pfd->pfd_conv;
diff --git a/usr/src/lib/libdtrace/common/dt_provider.c b/usr/src/lib/libdtrace/common/dt_provider.c
index 86e1204e63..ef4b4470d5 100644
--- a/usr/src/lib/libdtrace/common/dt_provider.c
+++ b/usr/src/lib/libdtrace/common/dt_provider.c
@@ -23,8 +23,9 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#include <sys/types.h>
#include <sys/sysmacros.h>
@@ -41,6 +42,8 @@
#include <dt_module.h>
#include <dt_string.h>
#include <dt_list.h>
+#include <dt_pid.h>
+#include <dtrace.h>
static dt_provider_t *
dt_provider_insert(dtrace_hdl_t *dtp, dt_provider_t *pvp, uint_t h)
@@ -269,6 +272,21 @@ dt_probe_discover(dt_provider_t *pvp, const dtrace_probedesc_t *pdp)
nc++;
/*
+ * The pid provider believes in giving the kernel a break. No reason to
+ * give the kernel all the ctf containers that we're keeping ourselves
+ * just to get it back from it. So if we're coming from a pid provider
+ * probe and the kernel gave us no argument information we'll get some
+ * here. If for some crazy reason the kernel knows about our userland
+ * types then we just ignore this.
+ */
+ if (xc == 0 && nc == 0 &&
+ strncmp(pvp->pv_desc.dtvd_name, "pid", 3) == 0) {
+ nc = adc;
+ dt_pid_get_types(dtp, pdp, adv, &nc);
+ xc = nc;
+ }
+
+ /*
* Now that we have discovered the number of native and translated
* arguments from the argument descriptions, allocate a new probe ident
* and corresponding dt_probe_t and hash it into the provider.
@@ -314,7 +332,8 @@ dt_probe_discover(dt_provider_t *pvp, const dtrace_probedesc_t *pdp)
dtt.dtt_type = CTF_ERR;
} else {
dt_node_type_assign(prp->pr_nargv[adp->dtargd_mapping],
- dtt.dtt_ctfp, dtt.dtt_type);
+ dtt.dtt_ctfp, dtt.dtt_type,
+ dtt.dtt_flags & DTT_FL_USER ? B_TRUE : B_FALSE);
}
if (dtt.dtt_type != CTF_ERR && (adp->dtargd_xlate[0] == '\0' ||
@@ -333,7 +352,7 @@ dt_probe_discover(dt_provider_t *pvp, const dtrace_probedesc_t *pdp)
dtt.dtt_type = CTF_ERR;
} else {
dt_node_type_assign(prp->pr_xargv[i],
- dtt.dtt_ctfp, dtt.dtt_type);
+ dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
}
prp->pr_mapping[i] = adp->dtargd_mapping;
@@ -634,7 +653,7 @@ dt_probe_tag(dt_probe_t *prp, uint_t argn, dt_node_t *dnp)
bzero(dnp, sizeof (dt_node_t));
dnp->dn_kind = DT_NODE_TYPE;
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
dt_node_attr_assign(dnp, _dtrace_defattr);
return (dnp);
diff --git a/usr/src/lib/libdtrace/common/dt_xlator.c b/usr/src/lib/libdtrace/common/dt_xlator.c
index 7ac0cc42f5..74bd487861 100644
--- a/usr/src/lib/libdtrace/common/dt_xlator.c
+++ b/usr/src/lib/libdtrace/common/dt_xlator.c
@@ -23,8 +23,10 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
#include <strings.h>
#include <assert.h>
@@ -69,7 +71,7 @@ dt_xlator_create_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
enp->dn_op = DT_TOK_XLATE;
enp->dn_xlator = dxp;
enp->dn_xmember = mnp;
- dt_node_type_assign(enp, dxp->dx_dst_ctfp, type);
+ dt_node_type_assign(enp, dxp->dx_dst_ctfp, type, B_FALSE);
/*
* For the member itself, we use a DT_NODE_MEMBER as usual with the
@@ -83,7 +85,7 @@ dt_xlator_create_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
mnp->dn_membname = strdup(name);
mnp->dn_membexpr = enp;
- dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type);
+ dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type, B_FALSE);
if (mnp->dn_membname == NULL)
return (dt_set_errno(dtp, EDT_NOMEM));
@@ -318,7 +320,8 @@ dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags)
for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
dxp = dt_list_next(dxp)) {
- dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type);
+ dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type,
+ B_FALSE);
if (ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
dst_ctfp, dst_base) && dt_node_is_argcompat(src, &xn))
goto out;
diff --git a/usr/src/lib/libdtrace/common/dtrace.h b/usr/src/lib/libdtrace/common/dtrace.h
index d3031d8c4c..0578c6d307 100644
--- a/usr/src/lib/libdtrace/common/dtrace.h
+++ b/usr/src/lib/libdtrace/common/dtrace.h
@@ -25,7 +25,8 @@
*/
/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#ifndef _DTRACE_H
@@ -492,8 +493,11 @@ typedef struct dtrace_typeinfo {
const char *dtt_object; /* object containing type */
ctf_file_t *dtt_ctfp; /* CTF container handle */
ctf_id_t dtt_type; /* CTF type identifier */
+ uint_t dtt_flags; /* Misc. flags */
} dtrace_typeinfo_t;
+#define DTT_FL_USER 0x1 /* user type */
+
extern int dtrace_lookup_by_type(dtrace_hdl_t *, const char *, const char *,
dtrace_typeinfo_t *);