summaryrefslogtreecommitdiff
path: root/usr/src/lib/libdtrace/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libdtrace/common')
-rw-r--r--usr/src/lib/libdtrace/common/dt_link.c121
-rw-r--r--usr/src/lib/libdtrace/common/dt_open.c18
-rw-r--r--usr/src/lib/libdtrace/common/dt_program.c65
-rw-r--r--usr/src/lib/libdtrace/common/dt_strtab.c30
-rw-r--r--usr/src/lib/libdtrace/common/dt_strtab.h9
5 files changed, 164 insertions, 79 deletions
diff --git a/usr/src/lib/libdtrace/common/dt_link.c b/usr/src/lib/libdtrace/common/dt_link.c
index 60fe4b5f36..4092b19a46 100644
--- a/usr/src/lib/libdtrace/common/dt_link.c
+++ b/usr/src/lib/libdtrace/common/dt_link.c
@@ -86,23 +86,23 @@ static const char DOFSTR[] = "__SUNW_dof";
static const char DOFLAZYSTR[] = "___SUNW_dof";
typedef struct dt_link_pair {
- struct dt_link_pair *dlp_next; /* next pair in linked list */
- void *dlp_str; /* buffer for string table */
- void *dlp_sym; /* buffer for symbol table */
+ struct dt_link_pair *dlp_next; /* next pair in linked list */
+ void *dlp_str; /* buffer for string table */
+ void *dlp_sym; /* buffer for symbol table */
} dt_link_pair_t;
typedef struct dof_elf32 {
- uint32_t de_nrel; /* relocation count */
+ uint32_t de_nrel; /* relocation count */
#ifdef __sparc
- Elf32_Rela *de_rel; /* array of relocations for sparc */
+ Elf32_Rela *de_rel; /* array of relocations for sparc */
#else
- Elf32_Rel *de_rel; /* array of relocations for x86 */
+ Elf32_Rel *de_rel; /* array of relocations for x86 */
#endif
- uint32_t de_nsym; /* symbol count */
- Elf32_Sym *de_sym; /* array of symbols */
- uint32_t de_strlen; /* size of of string table */
- char *de_strtab; /* string table */
- uint32_t de_global; /* index of the first global symbol */
+ uint32_t de_nsym; /* symbol count */
+ Elf32_Sym *de_sym; /* array of symbols */
+ uint32_t de_strlen; /* size of of string table */
+ char *de_strtab; /* string table */
+ uint32_t de_global; /* index of the first global symbol */
} dof_elf32_t;
static int
@@ -994,9 +994,10 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
dt_provider_t *pvp;
dt_probe_t *prp;
uint32_t off, eclass, emachine1, emachine2;
- size_t count_sym, count_str, symsize;
+ size_t symsize, nsym, isym, istr, len;
key_t objkey;
dt_link_pair_t *pair, *bufs = NULL;
+ dt_strtab_t *strtab;
if ((fd = open64(obj, O_RDWR)) == -1) {
return (dt_link_error(dtp, elf, fd, bufs,
@@ -1130,11 +1131,12 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
* $dtrace<key>.<function>
*
* We take a first pass through all the relocations to
- * calculate an upper bound on the number of symbols we may
- * need to add as well as the size of the strings we may need
- * to add to the string table for those symbols.
+ * populate our string table and count the number of extra
+ * symbols we'll require.
*/
- count_sym = count_str = 0;
+ strtab = dt_strtab_create(1);
+ nsym = 0;
+
for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
if (shdr_rel.sh_type == SHT_RELA) {
@@ -1150,8 +1152,10 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
}
if (gelf_getsym(data_sym, GELF_R_SYM(rela.r_info),
- &rsym) == NULL)
+ &rsym) == NULL) {
+ dt_strtab_destroy(strtab);
goto err;
+ }
s = (char *)data_str->d_buf + rsym.st_name;
@@ -1159,14 +1163,18 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
continue;
if (dt_symtab_lookup(data_sym, rela.r_offset,
- shdr_rel.sh_info, &fsym) != 0)
+ shdr_rel.sh_info, &fsym) != 0) {
+ dt_strtab_destroy(strtab);
goto err;
+ }
if (GELF_ST_BIND(fsym.st_info) != STB_LOCAL)
continue;
- if (fsym.st_name > data_str->d_size)
+ if (fsym.st_name > data_str->d_size) {
+ dt_strtab_destroy(strtab);
goto err;
+ }
s = (char *)data_str->d_buf + fsym.st_name;
@@ -1175,13 +1183,26 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
* driven off the rails or the object file is corrupt.
*/
if (GELF_ST_TYPE(fsym.st_info) != STT_FUNC) {
+ dt_strtab_destroy(strtab);
return (dt_link_error(dtp, elf, fd, bufs,
"expected %s to be of type function", s));
}
- count_sym++;
- count_str += 1 + snprintf(NULL, 0, dt_symfmt,
- dt_symprefix, objkey, s);
+ len = snprintf(NULL, 0, dt_symfmt, dt_symprefix,
+ objkey, s) + 1;
+ if ((p = dt_alloc(dtp, len)) == NULL) {
+ dt_strtab_destroy(strtab);
+ goto err;
+ }
+ (void) snprintf(p, len, dt_symfmt, dt_symprefix,
+ objkey, s);
+
+ if (dt_strtab_index(strtab, p) == -1) {
+ nsym++;
+ (void) dt_strtab_insert(strtab, p);
+ }
+
+ dt_free(dtp, p);
}
/*
@@ -1192,20 +1213,29 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
* are still responsible for freeing them once we're done with
* the elf handle.
*/
- if (count_sym > 0) {
- assert(count_str > 0);
+ if (nsym > 0) {
+ /*
+ * The first byte of the string table is reserved for
+ * the \0 entry.
+ */
+ len = dt_strtab_size(strtab) - 1;
+
+ assert(len > 0);
+ assert(dt_strtab_index(strtab, "") == 0);
+
+ dt_strtab_destroy(strtab);
if ((pair = dt_alloc(dtp, sizeof (*pair))) == NULL)
goto err;
if ((pair->dlp_str = dt_alloc(dtp, data_str->d_size +
- count_str)) == NULL) {
+ len)) == NULL) {
dt_free(dtp, pair);
goto err;
}
if ((pair->dlp_sym = dt_alloc(dtp, data_sym->d_size +
- count_sym * symsize)) == NULL) {
+ nsym * symsize)) == NULL) {
dt_free(dtp, pair->dlp_str);
dt_free(dtp, pair);
goto err;
@@ -1214,25 +1244,31 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
pair->dlp_next = bufs;
bufs = pair;
+ istr = data_str->d_size;
+ isym = data_sym->d_size / symsize;
+
bcopy(data_str->d_buf, pair->dlp_str, data_str->d_size);
data_str->d_buf = pair->dlp_str;
- data_str->d_size += count_str;
+ data_str->d_size += len;
(void) elf_flagdata(data_str, ELF_C_SET, ELF_F_DIRTY);
- shdr_str.sh_size += count_str;
+ shdr_str.sh_size += len;
(void) gelf_update_shdr(scn_str, &shdr_str);
bcopy(data_sym->d_buf, pair->dlp_sym, data_sym->d_size);
data_sym->d_buf = pair->dlp_sym;
- data_sym->d_size += count_sym * symsize;
+ data_sym->d_size += nsym * symsize;
(void) elf_flagdata(data_sym, ELF_C_SET, ELF_F_DIRTY);
- shdr_sym.sh_size += count_sym * symsize;
+ shdr_sym.sh_size += nsym * symsize;
(void) gelf_update_shdr(scn_sym, &shdr_sym);
- }
- count_str = shdr_str.sh_size - count_str;
- count_sym = data_sym->d_size / symsize - count_sym;
+ nsym += isym;
+ } else {
+ istr = 0;
+ isym = 0;
+ dt_strtab_destroy(strtab);
+ }
/*
* Now that the tables have been allocated, perform the
@@ -1315,17 +1351,17 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
if (GELF_ST_BIND(fsym.st_info) == STB_LOCAL) {
dsym = fsym;
- dsym.st_name = count_str;
+ dsym.st_name = istr;
dsym.st_info = GELF_ST_INFO(STB_GLOBAL,
STT_FUNC);
dsym.st_other = ELF64_ST_VISIBILITY(STV_HIDDEN);
- (void) gelf_update_sym(data_sym, count_sym,
- &dsym);
+ (void) gelf_update_sym(data_sym, isym, &dsym);
- r = (char *)data_str->d_buf + count_str;
- count_str += 1 + sprintf(r, dt_symfmt,
+ r = (char *)data_str->d_buf + istr;
+ istr += 1 + sprintf(r, dt_symfmt,
dt_symprefix, objkey, s);
- count_sym++;
+ isym++;
+ assert(isym <= nsym);
} else if (strncmp(s, dt_symprefix,
strlen(dt_symprefix)) == 0) {
@@ -1373,13 +1409,6 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
(void) gelf_update_sym(data_sym, ndx, &rsym);
}
}
-
- /*
- * The full buffer may not have been used so shrink them here
- * to match the sizes actually used.
- */
- data_str->d_size = count_str;
- data_sym->d_size = count_sym * symsize;
}
if (mod && elf_update(elf, ELF_C_WRITE) == -1)
diff --git a/usr/src/lib/libdtrace/common/dt_open.c b/usr/src/lib/libdtrace/common/dt_open.c
index e2358ce89c..5a9321b178 100644
--- a/usr/src/lib/libdtrace/common/dt_open.c
+++ b/usr/src/lib/libdtrace/common/dt_open.c
@@ -98,8 +98,9 @@
#define DT_VERS_1_2 DT_VERSION_NUMBER(1, 2, 0)
#define DT_VERS_1_2_1 DT_VERSION_NUMBER(1, 2, 1)
#define DT_VERS_1_2_2 DT_VERSION_NUMBER(1, 2, 2)
-#define DT_VERS_LATEST DT_VERS_1_2_2
-#define DT_VERS_STRING "Sun D 1.2.2"
+#define DT_VERS_1_3 DT_VERSION_NUMBER(1, 3, 0)
+#define DT_VERS_LATEST DT_VERS_1_3
+#define DT_VERS_STRING "Sun D 1.3"
const dt_version_t _dtrace_versions[] = {
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -107,6 +108,7 @@ const dt_version_t _dtrace_versions[] = {
DT_VERS_1_2, /* D API 1.2.0 Solaris 10 Update 1 */
DT_VERS_1_2_1, /* D API 1.2.1 Solaris Express 4/06 */
DT_VERS_1_2_2, /* D API 1.2.2 Solaris Express 6/06 */
+ DT_VERS_1_3, /* D API 1.3 Solaris Express 10/06 */
0
};
@@ -214,6 +216,12 @@ static const dt_ident_t _dtrace_globals[] = {
{ "getminor", DT_IDENT_FUNC, 0, DIF_SUBR_GETMINOR,
DT_ATTR_EVOLCMN, DT_VERS_1_0,
&dt_idops_func, "genunix`minor_t(genunix`dev_t)" },
+{ "htonl", DT_IDENT_FUNC, 0, DIF_SUBR_HTONL, DT_ATTR_EVOLCMN, DT_VERS_1_3,
+ &dt_idops_func, "uint32_t(uint32_t)" },
+{ "htonll", DT_IDENT_FUNC, 0, DIF_SUBR_HTONLL, DT_ATTR_EVOLCMN, DT_VERS_1_3,
+ &dt_idops_func, "uint64_t(uint64_t)" },
+{ "htons", DT_IDENT_FUNC, 0, DIF_SUBR_HTONS, DT_ATTR_EVOLCMN, DT_VERS_1_3,
+ &dt_idops_func, "uint16_t(uint16_t)" },
{ "gid", DT_IDENT_SCALAR, 0, DIF_VAR_GID, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "gid_t" },
{ "id", DT_IDENT_SCALAR, 0, DIF_VAR_ID, DT_ATTR_STABCMN, DT_VERS_1_0,
@@ -253,6 +261,12 @@ static const dt_ident_t _dtrace_globals[] = {
{ "mutex_type_spin", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_TYPE_SPIN,
DT_ATTR_EVOLCMN, DT_VERS_1_0,
&dt_idops_func, "int(genunix`kmutex_t *)" },
+{ "ntohl", DT_IDENT_FUNC, 0, DIF_SUBR_NTOHL, DT_ATTR_EVOLCMN, DT_VERS_1_3,
+ &dt_idops_func, "uint32_t(uint32_t)" },
+{ "ntohll", DT_IDENT_FUNC, 0, DIF_SUBR_NTOHLL, DT_ATTR_EVOLCMN, DT_VERS_1_3,
+ &dt_idops_func, "uint64_t(uint64_t)" },
+{ "ntohs", DT_IDENT_FUNC, 0, DIF_SUBR_NTOHS, DT_ATTR_EVOLCMN, DT_VERS_1_3,
+ &dt_idops_func, "uint16_t(uint16_t)" },
{ "normalize", DT_IDENT_ACTFUNC, 0, DT_ACT_NORMALIZE, DT_ATTR_STABCMN,
DT_VERS_1_0, &dt_idops_func, "void(...)" },
{ "panic", DT_IDENT_ACTFUNC, 0, DT_ACT_PANIC, DT_ATTR_STABCMN, DT_VERS_1_0,
diff --git a/usr/src/lib/libdtrace/common/dt_program.c b/usr/src/lib/libdtrace/common/dt_program.c
index d751c4817b..8497dab01e 100644
--- a/usr/src/lib/libdtrace/common/dt_program.c
+++ b/usr/src/lib/libdtrace/common/dt_program.c
@@ -355,9 +355,9 @@ typedef struct dt_header_info {
FILE *dthi_out; /* output file */
char *dthi_pmname; /* provider macro name */
char *dthi_pfname; /* provider function name */
+ int dthi_empty; /* should we generate empty macros */
} dt_header_info_t;
-
static void
dt_header_fmt_macro(char *buf, const char *str)
{
@@ -472,32 +472,40 @@ dt_header_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
return (dt_set_errno(dtp, errno));
}
- if (fprintf(infop->dthi_out, ") \\\n\t") < 0)
- return (dt_set_errno(dtp, errno));
-
- if (fprintf(infop->dthi_out, "__dtrace_%s___%s(",
- infop->dthi_pfname, fname) < 0)
- return (dt_set_errno(dtp, errno));
-
- for (i = 0; i < prp->pr_nargc; i++) {
- if (fprintf(infop->dthi_out, "arg%d", i) < 0)
+ if (!infop->dthi_empty) {
+ if (fprintf(infop->dthi_out, ") \\\n\t") < 0)
return (dt_set_errno(dtp, errno));
- if (i + 1 != prp->pr_nargc &&
- fprintf(infop->dthi_out, ", ") < 0)
+ if (fprintf(infop->dthi_out, "__dtrace_%s___%s(",
+ infop->dthi_pfname, fname) < 0)
return (dt_set_errno(dtp, errno));
+
+ for (i = 0; i < prp->pr_nargc; i++) {
+ if (fprintf(infop->dthi_out, "arg%d", i) < 0)
+ return (dt_set_errno(dtp, errno));
+
+ if (i + 1 != prp->pr_nargc &&
+ fprintf(infop->dthi_out, ", ") < 0)
+ return (dt_set_errno(dtp, errno));
+ }
}
if (fprintf(infop->dthi_out, ")\n") < 0)
return (dt_set_errno(dtp, errno));
- if (fprintf(infop->dthi_out, "#define\t%s_%s_ENABLED() \\\n",
- infop->dthi_pmname, mname) < 0)
- return (dt_set_errno(dtp, errno));
+ if (!infop->dthi_empty) {
+ if (fprintf(infop->dthi_out, "#define\t%s_%s_ENABLED() \\\n",
+ infop->dthi_pmname, mname) < 0)
+ return (dt_set_errno(dtp, errno));
- if (fprintf(infop->dthi_out, "\t__dtraceenabled_%s___%s()\n",
- infop->dthi_pfname, fname) < 0)
- return (dt_set_errno(dtp, errno));
+ if (fprintf(infop->dthi_out, "\t__dtraceenabled_%s___%s()\n",
+ infop->dthi_pfname, fname) < 0)
+ return (dt_set_errno(dtp, errno));
+ } else {
+ if (fprintf(infop->dthi_out, "#define\t%s_%s_ENABLED() (0)\n",
+ infop->dthi_pmname, mname) < 0)
+ return (dt_set_errno(dtp, errno));
+ }
return (0);
}
@@ -512,12 +520,17 @@ dt_header_provider(dtrace_hdl_t *dtp, dt_provider_t *pvp, FILE *out)
if (pvp->pv_flags & DT_PROVIDER_IMPL)
return (0);
+ /*
+ * Count the instances of the '-' character since we'll need to double
+ * those up.
+ */
p = pvp->pv_desc.dtvd_name;
for (i = 0; (p = strchr(p, '-')) != NULL; i++)
p++;
info.dthi_dtp = dtp;
info.dthi_out = out;
+ info.dthi_empty = 0;
info.dthi_pmname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1);
dt_header_fmt_macro(info.dthi_pmname, pvp->pv_desc.dtvd_name);
@@ -525,6 +538,8 @@ dt_header_provider(dtrace_hdl_t *dtp, dt_provider_t *pvp, FILE *out)
info.dthi_pfname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1 + i);
dt_header_fmt_func(info.dthi_pfname, pvp->pv_desc.dtvd_name);
+ if (fprintf(out, "#if _DTRACE_VERSION\n\n") < 0)
+ return (dt_set_errno(dtp, errno));
if (dt_idhash_iter(pvp->pv_probes, dt_header_probe, &info) != 0)
return (-1); /* dt_errno is set for us */
@@ -533,6 +548,17 @@ dt_header_provider(dtrace_hdl_t *dtp, dt_provider_t *pvp, FILE *out)
if (dt_idhash_iter(pvp->pv_probes, dt_header_decl, &info) != 0)
return (-1); /* dt_errno is set for us */
+ if (fprintf(out, "\n#else\n\n") < 0)
+ return (dt_set_errno(dtp, errno));
+
+ info.dthi_empty = 1;
+
+ if (dt_idhash_iter(pvp->pv_probes, dt_header_probe, &info) != 0)
+ return (-1); /* dt_errno is set for us */
+
+ if (fprintf(out, "\n#endif\n\n") < 0)
+ return (dt_set_errno(dtp, errno));
+
return (0);
}
@@ -553,6 +579,9 @@ dtrace_program_header(dtrace_hdl_t *dtp, FILE *out, const char *fname)
return (dt_set_errno(dtp, errno));
}
+ if (fprintf(out, "#include <unistd.h>\n\n") < 0)
+ return (-1);
+
if (fprintf(out, "#ifdef\t__cplusplus\nextern \"C\" {\n#endif\n\n") < 0)
return (-1);
diff --git a/usr/src/lib/libdtrace/common/dt_strtab.c b/usr/src/lib/libdtrace/common/dt_strtab.c
index 42739eab6e..cf6bc48341 100644
--- a/usr/src/lib/libdtrace/common/dt_strtab.c
+++ b/usr/src/lib/libdtrace/common/dt_strtab.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -204,7 +204,7 @@ err:
}
ssize_t
-dt_strtab_insert(dt_strtab_t *sp, const char *str)
+dt_strtab_index(dt_strtab_t *sp, const char *str)
{
dt_strhash_t *hp;
size_t len;
@@ -215,15 +215,27 @@ dt_strtab_insert(dt_strtab_t *sp, const char *str)
h = dt_strtab_hash(str, &len) % sp->str_hashsz;
- /*
- * If the string is already in our hash table, just return the offset
- * of the existing string element and do not add a duplicate string.
- */
for (hp = sp->str_hash[h]; hp != NULL; hp = hp->str_next) {
if (dt_strtab_compare(sp, hp, str, len + 1) == 0)
return (hp->str_off);
}
+ return (-1);
+}
+
+ssize_t
+dt_strtab_insert(dt_strtab_t *sp, const char *str)
+{
+ dt_strhash_t *hp;
+ size_t len;
+ ssize_t off;
+ ulong_t h;
+
+ if ((off = dt_strtab_index(sp, str)) != -1)
+ return (off);
+
+ h = dt_strtab_hash(str, &len) % sp->str_hashsz;
+
/*
* Create a new hash bucket, initialize it, and insert it at the front
* of the hash chain for the appropriate bucket.
diff --git a/usr/src/lib/libdtrace/common/dt_strtab.h b/usr/src/lib/libdtrace/common/dt_strtab.h
index 1f0b2912c1..551dabbf67 100644
--- a/usr/src/lib/libdtrace/common/dt_strtab.h
+++ b/usr/src/lib/libdtrace/common/dt_strtab.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -58,6 +58,7 @@ typedef ssize_t dt_strtab_write_f(const char *, size_t, size_t, void *);
extern dt_strtab_t *dt_strtab_create(size_t);
extern void dt_strtab_destroy(dt_strtab_t *);
+extern ssize_t dt_strtab_index(dt_strtab_t *, const char *);
extern ssize_t dt_strtab_insert(dt_strtab_t *, const char *);
extern size_t dt_strtab_size(const dt_strtab_t *);
extern ssize_t dt_strtab_write(const dt_strtab_t *,