diff options
Diffstat (limited to 'usr/src/lib/libdtrace/common')
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_link.c | 121 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_open.c | 18 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_program.c | 65 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_strtab.c | 30 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_strtab.h | 9 |
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 *, |