Changeset View
Changeset View
Standalone View
Standalone View
cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c
Show First 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | |||||
* structure, we check to see if there have been any corresponding forward | * structure, we check to see if there have been any corresponding forward | ||||
* declarations. If so, we redirect the tdescs which referenced the forward | * declarations. If so, we redirect the tdescs which referenced the forward | ||||
* declarations to the structure or union definition. | * declarations to the structure or union definition. | ||||
* | * | ||||
* XXX see if a post traverser will allow the elimination of repeated pass 2 | * XXX see if a post traverser will allow the elimination of repeated pass 2 | ||||
* traversals. | * traversals. | ||||
*/ | */ | ||||
#include <stdbool.h> | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <strings.h> | #include <strings.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <libelf.h> | #include <libelf.h> | ||||
#include <libdwarf.h> | #include <libdwarf.h> | ||||
#include <libgen.h> | #include <libgen.h> | ||||
Show All 32 Lines | |||||
typedef struct dwarf { | typedef struct dwarf { | ||||
Dwarf_Debug dw_dw; /* for libdwarf */ | Dwarf_Debug dw_dw; /* for libdwarf */ | ||||
Dwarf_Error dw_err; /* for libdwarf */ | Dwarf_Error dw_err; /* for libdwarf */ | ||||
Dwarf_Off dw_maxoff; /* highest legal offset in this cu */ | Dwarf_Off dw_maxoff; /* highest legal offset in this cu */ | ||||
tdata_t *dw_td; /* root of the tdesc/iidesc tree */ | tdata_t *dw_td; /* root of the tdesc/iidesc tree */ | ||||
hash_t *dw_tidhash; /* hash of tdescs by t_id */ | hash_t *dw_tidhash; /* hash of tdescs by t_id */ | ||||
hash_t *dw_fwdhash; /* hash of fwd decls by name */ | hash_t *dw_fwdhash; /* hash of fwd decls by name */ | ||||
hash_t *dw_constvhash; /* hash of constval tdescs by value */ | |||||
hash_t *dw_enumhash; /* hash of memberless enums by name */ | hash_t *dw_enumhash; /* hash of memberless enums by name */ | ||||
tdesc_t *dw_void; /* manufactured void type */ | tdesc_t *dw_void; /* manufactured void type */ | ||||
tdesc_t *dw_long; /* manufactured long type for arrays */ | tdesc_t *dw_long; /* manufactured long type for arrays */ | ||||
size_t dw_ptrsz; /* size of a pointer in this file */ | size_t dw_ptrsz; /* size of a pointer in this file */ | ||||
tid_t dw_mfgtid_last; /* last mfg'd type ID used */ | tid_t dw_mfgtid_last; /* last mfg'd type ID used */ | ||||
uint_t dw_nunres; /* count of unresolved types */ | uint_t dw_nunres; /* count of unresolved types */ | ||||
char *dw_cuname; /* name of compilation unit */ | char *dw_cuname; /* name of compilation unit */ | ||||
} dwarf_t; | } dwarf_t; | ||||
Show All 22 Lines | tdesc_lookup(dwarf_t *dw, int tid) | ||||
tmpl.t_id = tid; | tmpl.t_id = tid; | ||||
if (hash_find(dw->dw_tidhash, &tmpl, &tdp)) | if (hash_find(dw->dw_tidhash, &tmpl, &tdp)) | ||||
return (tdp); | return (tdp); | ||||
else | else | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
#define TDLOOKUP_CREATE_IF_MISSING 0x1 | |||||
#define TDLOOKUP_VALIDFLAGS TDLOOKUP_CREATE_IF_MISSING | |||||
static tdesc_t * | |||||
tdesc_lookup_for_typed_constval(dwarf_t *dw, tdesc_t *ttdp, int64_t val, | |||||
int flags) | |||||
{ | |||||
tdesc_t tmpl, *valp; | |||||
int tid; | |||||
void *v; | |||||
if ((flags & ~TDLOOKUP_VALIDFLAGS) != 0) | |||||
terminate("%s: bad flags %x\n", __func__, (unsigned)flags); | |||||
#undef TDLOOKUP_VALIDFLAGS | |||||
tmpl = (tdesc_t) { | |||||
.t_type = CONSTVAL, | |||||
.t_tdesc = ttdp, | |||||
.t_extra = val, | |||||
}; | |||||
if (hash_find(dw->dw_constvhash, &tmpl, &v)) | |||||
return (v); | |||||
if ((flags & TDLOOKUP_CREATE_IF_MISSING) == 0) | |||||
return (NULL); | |||||
valp = xcalloc(sizeof (*valp)); | |||||
*valp = tmpl; | |||||
tid = valp->t_id = mfgtid_next(dw); | |||||
debug(3, "Creating new constval type %d <%x>\n", tid, tid); | |||||
hash_add(dw->dw_constvhash, valp); | |||||
tdesc_add(dw, valp); | |||||
return (valp); | |||||
} | |||||
/* | /* | ||||
* Resolve a tdesc down to a node which should have a size. Returns the size, | * Resolve a tdesc down to a node which should have a size. Returns the size, | ||||
* zero if the size hasn't yet been determined. | * zero if the size hasn't yet been determined. | ||||
*/ | */ | ||||
static size_t | static size_t | ||||
tdesc_size(tdesc_t *tdp) | tdesc_size(tdesc_t *tdp) | ||||
{ | { | ||||
for (;;) { | for (;;) { | ||||
▲ Show 20 Lines • Show All 300 Lines • ▼ Show 20 Lines | die_lookup_pass1(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name) | ||||
tdesc_t *tdp; | tdesc_t *tdp; | ||||
if ((tdp = tdesc_lookup(dw, ref)) != NULL) | if ((tdp = tdesc_lookup(dw, ref)) != NULL) | ||||
return (tdp); | return (tdp); | ||||
return (die_add(dw, ref)); | return (die_add(dw, ref)); | ||||
} | } | ||||
/* | |||||
* Given a DW_TAG_formal_parameter, look up or create the relevant type object. | |||||
*/ | |||||
static tdesc_t * | |||||
die_lookup_funarg_pass1(dwarf_t *dw, Dwarf_Die die) | |||||
{ | |||||
Dwarf_Attribute dat; | |||||
Dwarf_Bool hasloc, hasconst; | |||||
Dwarf_Error err; | |||||
Dwarf_Half form; | |||||
Dwarf_Off off; | |||||
tdesc_t *tdp; | |||||
char *name; | |||||
union { | |||||
Dwarf_Unsigned uns_val; | |||||
Dwarf_Signed s_val; | |||||
} _u; | |||||
bool sign; | |||||
tdp = die_lookup_pass1(dw, die, DW_AT_type); | |||||
if (dwarf_hasattr(die, DW_AT_location, &hasloc, &err) != DW_DLV_OK) | |||||
markj: If you handle the !hasconst case first, you can de-indent the rest of the function. | |||||
Done Inline Actionssure, will do cem: sure, will do | |||||
terminate("dwarf_hasattr: %d\n", err); | |||||
if (dwarf_hasattr(die, DW_AT_const_value, &hasconst, &err) != DW_DLV_OK) | |||||
terminate("dwarf_hasattr: %d\n", err); | |||||
if (!hasconst) { | |||||
if (!hasloc) | |||||
debug(3, "die '%s': func arg has no location nor " | |||||
"constval\n", die_name(dw, die)); | |||||
return (tdp); | |||||
} | |||||
if (hasloc) | |||||
terminate("die '%s': func arg has both location and constval\n", | |||||
die_name(dw, die)); | |||||
if (dwarf_attr(die, DW_AT_const_value, &dat, &err) != | |||||
DW_DLV_OK) | |||||
terminate("dwarf_attr: %d\n", err); | |||||
if (dwarf_whatform(dat, &form, &err) != DW_DLV_OK) | |||||
terminate("dwarf_whatform: %d\n", err); | |||||
switch (form) { | |||||
case DW_FORM_data1: | |||||
case DW_FORM_data2: | |||||
case DW_FORM_data4: | |||||
case DW_FORM_data8: | |||||
case DW_FORM_sdata: | |||||
if (dwarf_attrval_signed(die, DW_AT_const_value, | |||||
&_u.s_val, &err) != DW_DLV_OK) | |||||
terminate("dwarf_attrval_signed: %d\n", err); | |||||
sign = true; | |||||
break; | |||||
case DW_FORM_addr: | |||||
case DW_FORM_udata: | |||||
case DW_FORM_ref1: | |||||
case DW_FORM_ref2: | |||||
case DW_FORM_ref4: | |||||
case DW_FORM_ref8: | |||||
case DW_FORM_ref_udata: | |||||
if (dwarf_attrval_unsigned(die, DW_AT_const_value, | |||||
&_u.uns_val, &err) != DW_DLV_OK) | |||||
terminate("dwarf_attrval_unsigned: %d\n", err); | |||||
sign = false; | |||||
break; | |||||
default: | |||||
terminate("dwarf_whatform: unrecognized form %d for " | |||||
"die '%s':DW_AT_const_value\n", form, die_name(dw, | |||||
die)); | |||||
} | |||||
off = die_off(dw, die); | |||||
name = die_name(dw, die); | |||||
debug(3, "die %llu <%llx>: creating constval function argument" | |||||
" %s (%jd)\n", off, off, name, | |||||
sign ? (intmax_t)_u.s_val : (intmax_t)_u.uns_val); | |||||
free(name); | |||||
tdp = tdesc_lookup_for_typed_constval(dw, tdp, | |||||
sign ? (int64_t)_u.s_val : (int64_t)_u.uns_val, | |||||
TDLOOKUP_CREATE_IF_MISSING); | |||||
return (tdp); | |||||
} | |||||
static int | static int | ||||
die_mem_offset(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, | die_mem_offset(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, | ||||
Dwarf_Unsigned *valp, int req __unused) | Dwarf_Unsigned *valp, int req __unused) | ||||
{ | { | ||||
Dwarf_Locdesc *loc = NULL; | Dwarf_Locdesc *loc = NULL; | ||||
Dwarf_Signed locnum = 0; | Dwarf_Signed locnum = 0; | ||||
Dwarf_Attribute at; | Dwarf_Attribute at; | ||||
Dwarf_Half form; | Dwarf_Half form; | ||||
▲ Show 20 Lines • Show All 1,134 Lines • ▼ Show 20 Lines | if (ii->ii_nargs > 0) { | ||||
ii->ii_args = xcalloc(sizeof (tdesc_t) * ii->ii_nargs); | ii->ii_args = xcalloc(sizeof (tdesc_t) * ii->ii_nargs); | ||||
for (arg = die_child(dw, die), i = 0; | for (arg = die_child(dw, die), i = 0; | ||||
arg != NULL && i < ii->ii_nargs; | arg != NULL && i < ii->ii_nargs; | ||||
arg = die_sibling(dw, arg)) { | arg = die_sibling(dw, arg)) { | ||||
if (die_tag(dw, arg) != DW_TAG_formal_parameter) | if (die_tag(dw, arg) != DW_TAG_formal_parameter) | ||||
continue; | continue; | ||||
ii->ii_args[i++] = die_lookup_pass1(dw, arg, | ii->ii_args[i++] = die_lookup_funarg_pass1(dw, arg); | ||||
DW_AT_type); | |||||
} | } | ||||
} | } | ||||
iidesc_add(dw->dw_td->td_iihash, ii); | iidesc_add(dw->dw_td->td_iihash, ii); | ||||
} | } | ||||
/*ARGSUSED3*/ | /*ARGSUSED3*/ | ||||
static void | static void | ||||
▲ Show 20 Lines • Show All 129 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
die_create(dwarf_t *dw, Dwarf_Die die) | die_create(dwarf_t *dw, Dwarf_Die die) | ||||
{ | { | ||||
do { | do { | ||||
die_create_one(dw, die); | die_create_one(dw, die); | ||||
} while ((die = die_sibling(dw, die)) != NULL); | } while ((die = die_sibling(dw, die)) != NULL); | ||||
} | } | ||||
static tdtrav_cb_f die_resolvers[] = { | static tdtrav_cb_f die_resolvers[STABTYPE_LAST] = { | ||||
NULL, | [ARRAY] = die_array_resolve, | ||||
NULL, /* intrinsic */ | [STRUCT] = die_sou_resolve, | ||||
NULL, /* pointer */ | [UNION] = die_sou_resolve, | ||||
die_array_resolve, /* array */ | [ENUM] = die_enum_resolve, | ||||
NULL, /* function */ | [FORWARD] = die_fwd_resolve, | ||||
die_sou_resolve, /* struct */ | |||||
die_sou_resolve, /* union */ | |||||
die_enum_resolve, /* enum */ | |||||
die_fwd_resolve, /* forward */ | |||||
NULL, /* typedef */ | |||||
NULL, /* typedef unres */ | |||||
NULL, /* volatile */ | |||||
NULL, /* const */ | |||||
NULL, /* restrict */ | |||||
}; | }; | ||||
static tdtrav_cb_f die_fail_reporters[] = { | static tdtrav_cb_f die_fail_reporters[STABTYPE_LAST] = { | ||||
NULL, | [ARRAY] = die_array_failed, | ||||
NULL, /* intrinsic */ | [STRUCT] = die_sou_failed, | ||||
NULL, /* pointer */ | [UNION] = die_sou_failed, | ||||
die_array_failed, /* array */ | |||||
NULL, /* function */ | |||||
die_sou_failed, /* struct */ | |||||
die_sou_failed, /* union */ | |||||
NULL, /* enum */ | |||||
NULL, /* forward */ | |||||
NULL, /* typedef */ | |||||
NULL, /* typedef unres */ | |||||
NULL, /* volatile */ | |||||
NULL, /* const */ | |||||
NULL, /* restrict */ | |||||
}; | }; | ||||
static void | static void | ||||
die_resolve(dwarf_t *dw) | die_resolve(dwarf_t *dw) | ||||
{ | { | ||||
int last = -1; | int last = -1; | ||||
int pass = 0; | int pass = 0; | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | dw_read(tdata_t *td, Elf *elf, char *filename __unused) | ||||
dw.dw_td = td; | dw.dw_td = td; | ||||
dw.dw_ptrsz = elf_ptrsz(elf); | dw.dw_ptrsz = elf_ptrsz(elf); | ||||
dw.dw_mfgtid_last = TID_MFGTID_BASE; | dw.dw_mfgtid_last = TID_MFGTID_BASE; | ||||
dw.dw_tidhash = hash_new(TDESC_HASH_BUCKETS, tdesc_idhash, tdesc_idcmp); | dw.dw_tidhash = hash_new(TDESC_HASH_BUCKETS, tdesc_idhash, tdesc_idcmp); | ||||
dw.dw_fwdhash = hash_new(TDESC_HASH_BUCKETS, tdesc_namehash, | dw.dw_fwdhash = hash_new(TDESC_HASH_BUCKETS, tdesc_namehash, | ||||
tdesc_namecmp); | tdesc_namecmp); | ||||
dw.dw_enumhash = hash_new(TDESC_HASH_BUCKETS, tdesc_namehash, | dw.dw_enumhash = hash_new(TDESC_HASH_BUCKETS, tdesc_namehash, | ||||
tdesc_namecmp); | tdesc_namecmp); | ||||
dw.dw_constvhash = hash_new(TDESC_HASH_BUCKETS, tdesc_cvhash, | |||||
tdesc_cvcmp); | |||||
if ((rc = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dw.dw_dw, | if ((rc = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dw.dw_dw, | ||||
&dw.dw_err)) == DW_DLV_NO_ENTRY) { | &dw.dw_err)) == DW_DLV_NO_ENTRY) { | ||||
if (should_have_dwarf(elf)) { | if (should_have_dwarf(elf)) { | ||||
errno = ENOENT; | errno = ENOENT; | ||||
return (-1); | return (-1); | ||||
} else { | } else { | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 91 Lines • Show Last 20 Lines |
If you handle the !hasconst case first, you can de-indent the rest of the function.