summaryrefslogtreecommitdiff
path: root/usr/src/tools/ctf
diff options
context:
space:
mode:
authorJohn Sonnenschein <johns@joyent.com>2012-07-30 18:55:21 +0000
committerJohn Sonnenschein <johns@joyent.com>2012-07-30 18:55:21 +0000
commit3f12efe73c075bbfe7e254714e8fabfb50f86af0 (patch)
treef429351c58a9955c46f03b8789bce1e152d32660 /usr/src/tools/ctf
parent2453263d59c2317dbe88d1c9e12893a32abd91b8 (diff)
parent5ada8a07255938930de285f1d55b0ef0bdba90ff (diff)
downloadillumos-joyent-3f12efe73c075bbfe7e254714e8fabfb50f86af0.tar.gz
Illumos Sync
Merge github.com:illumos/illumos-gate Conflicts: exception_lists/check_rtime usr/src/Makefile.master usr/src/Makefile.master.64 usr/src/cmd/Makefile usr/src/cmd/lms/Makefile usr/src/cmd/lp/Makefile.lp usr/src/cmd/mdb/Makefile.mdb usr/src/cmd/mdb/common/mdb/mdb_cmds.c usr/src/cmd/mdb/common/mdb/mdb_print.c usr/src/cmd/mdb/common/mdb/mdb_print.h usr/src/cmd/mdb/common/mdb/mdb_tab.c usr/src/cmd/mdb/common/mdb/mdb_termio.c usr/src/cmd/mdb/common/mdb/mdb_whatis.c usr/src/cmd/svc/svccfg/svccfg_libscf.c usr/src/cmd/zpool/zpool_main.c usr/src/lib/Makefile usr/src/lib/libc/inc/thr_inlines.h usr/src/lib/libc/port/mapfile-vers usr/src/lib/libc/sparc/Makefile.com usr/src/lib/libc/sparc/crt/_rtld.c usr/src/lib/libc/sparcv9/Makefile.com usr/src/lib/libdtrace/common/dt_open.c usr/src/lib/libdtrace/common/dt_options.c usr/src/lib/libumem/common/envvar.c usr/src/lib/libumem/common/vmem_base.c usr/src/lib/libzfs/common/libzfs_impl.h usr/src/lib/libzfs/common/libzfs_iter.c usr/src/lib/libzfs/common/libzfs_util.c usr/src/lib/libzfs/common/mapfile-vers usr/src/lib/sun_fc/Makefile.com usr/src/lib/sun_fc/amd64/Makefile usr/src/lib/sun_fc/sparcv9/Makefile usr/src/man/man1m/Makefile usr/src/uts/common/Makefile.files usr/src/uts/common/dtrace/dtrace.c usr/src/uts/common/fs/zfs/arc.c usr/src/uts/common/fs/zfs/dmu.c usr/src/uts/common/fs/zfs/dsl_dataset.c usr/src/uts/common/fs/zfs/dsl_pool.c usr/src/uts/common/fs/zfs/sys/zio.h usr/src/uts/common/io/fibre-channel/fca/fcoei/fcoei_eth.c usr/src/uts/common/io/fibre-channel/fca/fcoei/fcoei_lv.c usr/src/uts/common/sys/dtrace.h
Diffstat (limited to 'usr/src/tools/ctf')
-rw-r--r--usr/src/tools/ctf/cvt/dwarf.c118
1 files changed, 115 insertions, 3 deletions
diff --git a/usr/src/tools/ctf/cvt/dwarf.c b/usr/src/tools/ctf/cvt/dwarf.c
index ce8f6f9601..e261818d3a 100644
--- a/usr/src/tools/ctf/cvt/dwarf.c
+++ b/usr/src/tools/ctf/cvt/dwarf.c
@@ -22,6 +22,10 @@
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2012 Jason King. All rights reserved.
+ * Use is subject to license terms.
+ */
/*
* DWARF to tdata conversion
@@ -360,6 +364,37 @@ die_attr_form(dwarf_t *dw, Dwarf_Attribute attr)
return (0);
}
+/*
+ * the following functions lookup the value of an attribute in a DIE:
+ *
+ * die_signed
+ * die_unsigned
+ * die_bool
+ * die_string
+ *
+ * They all take the same parameters (with the exception of valp which is
+ * a pointer to the type of the attribute we are looking up):
+ *
+ * dw - the dwarf object to look in
+ * die - the DIE we're interested in
+ * name - the name of the attribute to lookup
+ * valp - pointer to where the value of the attribute is placed
+ * req - if the value is required (0 / non-zero)
+ *
+ * If the attribute is not found, one of the following happens:
+ * - program terminates (req is non-zero)
+ * - function returns 0
+ *
+ * If the value is found, and in a form (class) we can handle, the function
+ * returns 1.
+ *
+ * Currently, we can only handle attribute values that are stored as
+ * constants (immediate value). If an attribute has a form we cannot
+ * handle (for example VLAs may store the dimensions of the array
+ * as a DWARF expression that can compute it at runtime by reading
+ * values off the stack or other locations in memory), it is treated
+ * the same as if the attribute does not exist.
+ */
static int
die_signed(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Signed *valp,
int req)
@@ -371,6 +406,9 @@ die_signed(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Signed *valp,
return (0); /* die_attr will terminate for us if necessary */
if (dwarf_formsdata(attr, &val, &dw->dw_err) != DW_DLV_OK) {
+ if (req == 0)
+ return (0);
+
terminate("die %llu: failed to get signed (form 0x%x)\n",
die_off(dw, die), die_attr_form(dw, attr));
}
@@ -392,6 +430,9 @@ die_unsigned(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Unsigned *valp,
return (0); /* die_attr will terminate for us if necessary */
if (dwarf_formudata(attr, &val, &dw->dw_err) != DW_DLV_OK) {
+ if (req == 0)
+ return (0);
+
terminate("die %llu: failed to get unsigned (form 0x%x)\n",
die_off(dw, die), die_attr_form(dw, attr));
}
@@ -412,6 +453,9 @@ die_bool(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Bool *valp, int req)
return (0); /* die_attr will terminate for us if necessary */
if (dwarf_formflag(attr, &val, &dw->dw_err) != DW_DLV_OK) {
+ if (req == 0)
+ return (0);
+
terminate("die %llu: failed to get bool (form 0x%x)\n",
die_off(dw, die), die_attr_form(dw, attr));
}
@@ -432,6 +476,9 @@ die_string(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, char **strp, int req)
return (0); /* die_attr will terminate for us if necessary */
if (dwarf_formstring(attr, &str, &dw->dw_err) != DW_DLV_OK) {
+ if (req == 0)
+ return (0);
+
terminate("die %llu: failed to get string (form 0x%x)\n",
die_off(dw, die), die_attr_form(dw, attr));
}
@@ -1791,6 +1838,59 @@ die_resolve(dwarf_t *dw)
} while (dw->dw_nunres != 0);
}
+/*
+ * Any object containing a function or object symbol at any scope should also
+ * contain DWARF data.
+ */
+static boolean_t
+should_have_dwarf(Elf *elf)
+{
+ Elf_Scn *scn = NULL;
+ Elf_Data *data = NULL;
+ GElf_Shdr shdr;
+ GElf_Sym sym;
+ uint32_t symdx = 0;
+ size_t nsyms = 0;
+ boolean_t found = B_FALSE;
+
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+ gelf_getshdr(scn, &shdr);
+
+ if (shdr.sh_type == SHT_SYMTAB) {
+ found = B_TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ terminate("cannot convert stripped objects\n");
+
+ data = elf_getdata(scn, NULL);
+ nsyms = shdr.sh_size / shdr.sh_entsize;
+
+ for (symdx = 0; symdx < nsyms; symdx++) {
+ gelf_getsym(data, symdx, &sym);
+
+ if ((GELF_ST_TYPE(sym.st_info) == STT_FUNC) ||
+ (GELF_ST_TYPE(sym.st_info) == STT_TLS) ||
+ (GELF_ST_TYPE(sym.st_info) == STT_OBJECT)) {
+ char *name;
+
+ name = elf_strptr(elf, shdr.sh_link, sym.st_name);
+
+ /* Studio emits these local symbols regardless */
+ if ((strcmp(name, "Bbss.bss") != 0) &&
+ (strcmp(name, "Ttbss.bss") != 0) &&
+ (strcmp(name, "Ddata.data") != 0) &&
+ (strcmp(name, "Ttdata.data") != 0) &&
+ (strcmp(name, "Drodata.rodata") != 0))
+ return (B_TRUE);
+ }
+ }
+
+ return (B_FALSE);
+}
+
/*ARGSUSED*/
int
dw_read(tdata_t *td, Elf *elf, const char *filename)
@@ -1814,8 +1914,12 @@ dw_read(tdata_t *td, Elf *elf, const char *filename)
if ((rc = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dw.dw_dw,
&dw.dw_err)) == DW_DLV_NO_ENTRY) {
- errno = ENOENT;
- return (-1);
+ if (should_have_dwarf(elf)) {
+ errno = ENOENT;
+ return (-1);
+ } else {
+ return (0);
+ }
} else if (rc != DW_DLV_OK) {
if (dwarf_errno(dw.dw_err) == DW_DLE_DEBUG_INFO_NULL) {
/*
@@ -1834,10 +1938,18 @@ dw_read(tdata_t *td, Elf *elf, const char *filename)
terminate("file does not contain valid DWARF data: %s\n",
dwarf_errmsg(dw.dw_err));
+ /*
+ * Some compilers emit no DWARF for empty files, others emit an empty
+ * compilation unit.
+ */
if ((cu = die_sibling(&dw, NULL)) == NULL ||
- (child = die_child(&dw, cu)) == NULL)
+ ((child = die_child(&dw, cu)) == NULL) &&
+ should_have_dwarf(elf)) {
terminate("file does not contain dwarf type data "
"(try compiling with -g)\n");
+ } else if (child == NULL) {
+ return (0);
+ }
dw.dw_maxoff = nxthdr - 1;