static int apigetctype(int ctype, char *name, type_t *tout) { long size = 0; unsigned long long die = 0; switch (ctype) { case V_TYPEDEF: size = GET_DOMAIN(name, DWARF_INFO_GET_DOMAIN_TYPEDEF, &die); break; case V_STRUCT: size = GET_DOMAIN(name, DWARF_INFO_GET_DOMAIN_STRUCT, &die); break; case V_UNION: size = GET_DOMAIN(name, DWARF_INFO_GET_DOMAIN_UNION, &die); break; /* TODO * Implement for all the domains */ } if (size <= 0 || !die) return 0; /* populate */ eppic_type_settype(tout, ctype); eppic_type_setsize(tout, size); eppic_type_setidx(tout, (ull)(unsigned long)die); eppic_pushref(tout, 0); return 1; }
static value_t * eppic_exeadrof(adrof *a) { value_t *rv, *v=NODE_EXE(a->expr); #if 0 /* we can only do this op on something that came from system image Must not allow creation of references to local variable */ if(!v->mem) { eppic_freeval(v); eppic_rerror(&a->pos, "Invalid operand to '&' operator"); } #endif /* create the reference */ rv=eppic_newval(); eppic_duptype(&rv->type, &v->type); eppic_pushref(&rv->type, 1); /* remmember position in image */ if(eppic_defbsize()==8) rv->v.ull=v->mem; else rv->v.ul=v->mem; rv->mem=0; eppic_freeval(v); return rv; }
static void eppic_prtarray(type_t*t, ull mem, int level, int idx) { int i; int j, size=1; for(j=idx+1; t->idxlst[j]; j++) size *= t->idxlst[j]; size *= t->type==V_REF ? eppic_defbsize() : t->size; /* start printing */ eppic_msg("{"); eppic_msg("\n"); eppic_indent(level+1, 1); for(i=0; i<t->idxlst[idx]; i++, mem += size) { if(t->idxlst[idx+1]) { eppic_msg("[%d] = ", i); eppic_prtarray(t, mem, level+1, idx+1); } else { /* time to deref and print final type */ value_t *v=eppic_newval(), *vr=eppic_newval(); int *pi=t->idxlst; t->idxlst=0; eppic_duptype(&vr->type, t); eppic_pushref(&vr->type, 1); if(eppic_defbsize()==8) vr->v.ull=mem; else vr->v.ul=(ul)mem; eppic_do_deref(1, v, vr); if(is_ctype(v->type.type) || !(i%NBUNDLE)) eppic_msg("[%2d] ", i); eppic_ptype2(&v->type, v, level+1, 0, 0, 0, 1); eppic_msg(", "); /* anything else then struct/unions, print in buddles */ if(!is_ctype(v->type.type) && !((i+1)%NBUNDLE)) { eppic_msg("\n"); eppic_indent(level+1, 1); } eppic_freeval(v); eppic_freeval(vr); t->idxlst=pi; } } eppic_msg("\n"); eppic_indent(level, 1); eppic_msg("}"); }
int apigetval(char *name, ull *val, VALUE_S *value) { ull ptr = 0; ptr = GET_SYMBOL_ADDR_ALL(name); if (!ptr) return 0; *val = ptr; if (!value) return 1; /* Support for fully typed symbol access */ ull type; TYPE_S *stype; type = GET_DIE_OFFSET(name); stype = eppic_gettype(value); apigetrtype(type, stype); eppic_pushref(stype, 1); eppic_setmemaddr(value, *val); eppic_do_deref(1, value, value); *val = eppic_getval(value); if (!eppic_typeislocal(stype) && eppic_type_getidx(stype) > 100) { char *tname = GET_DIE_NAME(eppic_type_getidx(stype)); if (tname) { eppic_chktype(stype, tname); /* Free the memory allocated by makedumpfile. */ free(tname); } } return 1; }
/* * Drill down the type of the member and update eppic with information * about the member */ static char * drilldown(ull offset, type_t *t) { int type_flag, len = 0, t_len = 0, nidx = 0; int fctflg = 0, ref = 0, *idxlst = 0; ull die_off = offset, t_die_off; char *tstr = NULL, *tstr_dup = NULL; while (GET_DIE_ATTR_TYPE(die_off, &type_flag, &t_die_off)) { switch (type_flag) { /* typedef inserts a level of reference to the actual type */ case DW_TAG_pointer_type: ref++; die_off = t_die_off; /* * This could be a void *, in which case the drill * down stops here */ if (!GET_DIE_ATTR_TYPE(die_off, &type_flag, &t_die_off)) { /* make it a char* */ eppic_parsetype("char", t, ref); return eppic_strdup(""); } break; /* Handle pointer to function */ case DW_TAG_subroutine_type: fctflg = 1; die_off = t_die_off; break; /* Handle arrays */ case DW_TAG_array_type: if (!idxlst) { idxlst = eppic_calloc(sizeof(int) * \ (MAX_ARRAY_DIMENSION + 1)); if (!idxlst) { ERRMSG("Out of memory\n"); return NULL; } } if (nidx >= MAX_ARRAY_DIMENSION) { ERRMSG("Too many array indexes. Max=%d\n", MAX_ARRAY_DIMENSION); return NULL; } /* handle multi-dimensional array */ len = GET_DIE_LENGTH(die_off, FALSE); t_len = GET_DIE_LENGTH(t_die_off, FALSE); if (len > 0 && t_len > 0) idxlst[nidx++] = len / t_len; die_off = t_die_off; break; /* Handle typedef */ case DW_TAG_typedef: die_off = t_die_off; break; case DW_TAG_base_type: eppic_parsetype(tstr = GET_DIE_NAME(t_die_off), t, 0); goto out; case DW_TAG_union_type: eppic_type_mkunion(t); goto label; case DW_TAG_enumeration_type: eppic_type_mkenum(t); goto label; case DW_TAG_structure_type: eppic_type_mkstruct(t); goto label; /* Unknown TAG ? */ default: die_off = t_die_off; break; } } label: eppic_type_setsize(t, GET_DIE_LENGTH(t_die_off, TRUE)); eppic_type_setidx(t, (ull)t_die_off); tstr = GET_DIE_NAME(t_die_off); out: eppic_setupidx(t, ref, nidx, idxlst); if (fctflg) eppic_type_setfct(t, 1); eppic_pushref(t, ref + (nidx ? 1 : 0)); tstr_dup = (tstr) ? eppic_strdup(tstr) : eppic_strdup(""); /* Free the memory allocated by makedumpfile. */ free(tstr); return tstr_dup; }
/* Print a type. Typical output of the 'whatis' command. */ static void eppic_ptype2(type_t*t, value_t*v, int level, int indent, char *name, int ref, int justv) { int type=t->type; eppic_indent(level, indent); switch(type) { case V_STRUCT: case V_UNION: /* make sure we have all the member info */ eppic_print_ctype(t, v, level, 0, name, ref, justv); break; case V_TYPEDEF: /* no typedef should get here */ eppic_warning("Typedef in print!"); break; case V_ENUM: /* no enum should get here */ eppic_warning("ENUM in print!"); break; case V_REF: { int refi=t->ref, ref=refi; /* decrement ref if this was declared as a array */ if(t->idxlst) ref--; /* print the referenced type */ eppic_popref(t, t->ref); eppic_ptype2(t, 0, level, 0, 0, 1, justv); eppic_pushref(t, refi); if(!justv) { char buf[100], buf2[100]; int pos=0, len=sizeof(buf); buf[0]='\0'; if(t->fct) buf[pos++]='('; if(pos < len) pos += snprintf(buf+pos, len-pos, "%s%s", eppic_getref(ref), name?name:""); if(pos < len) pos += snprintf(buf+pos, len-pos, "%s", eppic_getidx(t, buf2, sizeof(buf2))); if(pos < len && t->fct) pos += snprintf(buf+pos, len-pos, "%s", ")()"); eppic_msg("%*s ", NAMESPACE, buf); } /* arrays are ref with boundaries... */ if(t->idxlst && v) { if(t->idxlst[1] || t->rtype!=V_BASE || t->size!=1 || !eppic_prtstr(v, justv)) { if(!justv) eppic_msg("= "); eppic_popref(t, 1); eppic_prtarray(t, v->mem, level, 0); eppic_pushref(t, 1); } } else if(v) { if(!justv) eppic_msg("= "); if(!eppic_getval(v)) eppic_msg("(nil)"); else { if(eppic_defbsize()==8) eppic_msg("0x%016llx", eppic_getval(v)); else eppic_msg("0x%08x", eppic_getval(v)); } if(t->ref==1 && t->rtype==V_BASE && t->size==1) { (void)eppic_prtstr(v, justv); } } } break; case V_BASE: { if(eppic_isenum(t->typattr)) { stinfo_t *st=eppic_getstbyindex(t->rtype, V_ENUM); if(!justv) { char buf[200]; snprintf(buf, sizeof(buf), "enum %s", st->name?st->name:""); eppic_msg("%-*s ", SPACER, buf); eppic_msg("%*s ", NAMESPACE, (name&&v)?name:""); } if(v) { enum_t *e=st->enums; eppic_msg("= "); eppic_prbval(v); while(e) { if(e->value==eppic_getval(v)) { eppic_msg(" [%s]", e->name); break; } e=e->next; } if(!e) eppic_msg(" [???]"); }else{ enum_t *e=st->enums; int count=0; eppic_msg(" {"); while(e) { if(!(count%4)) { eppic_msg("\n"); eppic_indent(level+1, 1); } count ++; eppic_msg("%s = %d, ", e->name, e->value); e=e->next; } eppic_msg("\n"); eppic_indent(level, 1); eppic_msg("%-*s ", SPACER, "}"); if(ref) return; eppic_msg("%*s ", NAMESPACE, name?name:""); } } else { if(!justv) { eppic_msg("%-*s " , SPACER , eppic_getbtypename(t->typattr)); if(ref) return; eppic_msg("%s%*s ", eppic_getref(t->ref), NAMESPACE, name?name:""); } if(v) { if(!justv) eppic_msg("= "); eppic_prbval(v); } } } break; case V_STRING: if(!justv) { eppic_msg("%-*s " , SPACER , "string"); eppic_msg("%*s ", NAMESPACE, name?name:""); } if(v) { if(!justv) eppic_msg("= "); eppic_msg("\"%s\"", v->v.data); } break; } if(indent) eppic_msg("\n"); }
/* this is the main variable declaration function. We support the global scope attribute that make the declared variable accessible to all function from all scripts. By default the scope of a variable either the statement block where it was declared (or first used): { int var; ... } Then it's scope is the block itself. Or the file, if it was declared outside of a function. Storage is by default 'automatic' and can be made permanent by using the 'static' keywork in the declaration. 'Volatile' and 'register' storage classes are supported but have no effect. */ var_t* eppic_vardecl(dvar_t*dv, type_t*t) { var_t*vlist=eppic_newvlist(); var_t*var; /* type *and* dv can have ref counts. First comes from typedef parsing second comes from the declaration itself */ dv->ref += t->ref; /* add one level of ref for arrays */ if(dv->idx) dv->ref++; /* reset ref level for tests below */ eppic_popref(t, t->ref); TAG(vlist); if(!t->type) { int sto=eppic_isstor(t->typattr); eppic_freetype(t); t=eppic_newbtype(0); t->typattr |= sto; } else if(t->type==V_BASE && !dv->ref) { eppic_chksign(t); eppic_chksize(t); } /* is this a new typedef declaration ? */ /* typedef is considered just like any other storage class */ if(eppic_istdef(t->typattr)) { eppic_tdef_decl(dv, t); return 0; } while(dv) { /* disalow var names that match against already defined vars */ if(dv->name[0]) { type_t *t=eppic_getctype(V_TYPEDEF, dv->name, 1); if(t) { eppic_freetype(t); eppic_warning("Variable '%s' already defined as typedef.\n"); } } /* some sanity checks here that apply to both var and struct declarations */ if(is_ctype(t->type) && !dv->ref) { if(dv->name[0]) { if(!instruct) { if(!eppic_isxtern(t->typattr)) { eppic_freesvs(vlist); eppic_error("struct/union instances not supported, please use pointers"); } } else if(eppic_ispartial(t)) { eppic_freesvs(vlist); eppic_error("Reference to incomplete type"); } } } if(dv->nbits) { if(t->type != V_BASE) { eppic_freesvs(vlist); eppic_error("Bit fields can only be of integer type"); } if(dv->idx) { eppic_freesvs(vlist); eppic_error("An array of bits ? Come on..."); } } var=eppic_newvar(dv->name); t->fct=dv->fct; eppic_duptype(&var->v->type, t); eppic_pushref(&var->v->type, dv->ref); var->dv=dv; TAG(var); if(t->type == V_STRING) { eppic_setstrval(var->v, ""); } eppic_setpos(&dv->pos); /* toff */ /* add to parsing list */ if(var->name[0]) { var_t *plist=eppic_newvlist(); eppic_enqueue(plist, var); eppic_addsvs(S_PARSE, eppic_dupvlist(plist)); } eppic_enqueue(vlist, var); next: dv=dv->next; } eppic_free(t); TAG(vlist); return vlist; }