From: Cliff W. <cp...@sg...> - 2008-07-02 12:56:25
|
This patch enables the use of an ia32 (i386) kerntypes file. It seems that such a kerntypes file has some structures that reference themselves, or else reference a pointer that references themselves. In either case lcrash goes into an endless recursive loop trying to find the "real" type of the structure. The main check is in look_for_realtype(). Plus there's some debugging left in, conditional to DWARF_DEBUG. Signed-off-by: Cliff Wickman <cp...@sg...> --- lib/libklib/kl_dwarf.c | 72 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 14 deletions(-) Index: lkcdutils/lib/libklib/kl_dwarf.c =================================================================== --- lkcdutils.orig/lib/libklib/kl_dwarf.c +++ lkcdutils/lib/libklib/kl_dwarf.c @@ -99,8 +99,8 @@ static void process_common_die(Dwarf_Die void process_struct_members(kltype_t *); static void find_realtypes(void); -static kltype_t * find_realtype_from_offset(Dwarf_Off); -void look_for_realtype(kltype_t *); +static kltype_t * find_realtype_from_offset(Dwarf_Off, kltype_t *, int); +void look_for_realtype(kltype_t *, kltype_t *, int); static void do_final_operations(kltype_t *); static void process_array(kltype_t *); @@ -256,8 +256,14 @@ static void read_dwarf_dies(void) /* find the realtypes of dies */ find_realtypes(); +#ifdef DWARF_DEBUG + fprintf (stderr, "begin find_member_sizes\n"); +#endif /* find the size of struct/union members */ find_member_sizes(); +#ifdef DWARF_DEBUG + fprintf (stderr, "end find_member_sizes\n"); +#endif } typedef struct die_stack_rec { @@ -496,8 +502,10 @@ static Dwarf_Die process_die(Dwarf_Die d sym_ptr->sym_type = DBG_TYPE; /* Name of base type itself is the type */ - strcpy(kltype_ptr->kl_typestr, kltype_ptr->kl_name); - strcat(kltype_ptr->kl_typestr, " "); + if (kltype_ptr->kl_name) { + strcpy(kltype_ptr->kl_typestr, kltype_ptr->kl_name); + strcat(kltype_ptr->kl_typestr, " "); + } /* Encoding */ encoding = get_constant(die, DW_AT_encoding); @@ -884,7 +892,7 @@ static void process_array(kltype_t *kltp typenum = TYPENUM(dw_idx_ptr, dw_idx_ptr->targetoffset); mp->kl_realtype = - find_realtype_from_offset(typenum); + find_realtype_from_offset(typenum, 0, 0); } cur_kltp->kl_indextype = mp->kl_realtype; cur_kltp->kl_size = (cur_kltp->kl_high_bounds+1) - @@ -938,6 +946,9 @@ static void find_realtypes(void) }; int i; kltype_t *source; +#ifdef DWARF_DEBUG + fprintf(stderr, "begin find_realtypes\n"); +#endif i=0; while((source = klptr_list[i++])) { @@ -947,10 +958,13 @@ static void find_realtypes(void) fprintf(stderr, "0x%lx: kl_name=%s\n", source, source->kl_name); #endif - look_for_realtype(source); + look_for_realtype(source, source, 0); } } +#ifdef DWARF_DEBUG + fprintf(stderr, "next while find_realtypes\n"); +#endif i=0; while((source = klptr_list[i++])) { for(; source; source = kl_next_type(source)) { @@ -974,10 +988,13 @@ static void find_realtypes(void) } } /* end of for loop */ } /* end of while loop */ +#ifdef DWARF_DEBUG + fprintf(stderr, "end find_realtypes\n"); +#endif } /* Just find the realtype and return */ -void look_for_realtype(kltype_t *src) +void look_for_realtype(kltype_t *src, kltype_t *original, int depth) { uint64_t typenum; dw_type_t *dw_ptr = (dw_type_t*)src; @@ -986,6 +1003,25 @@ void look_for_realtype(kltype_t *src) if(dw_ptr->complete) { return; } + if (dw_ptr->dieoffset == dw_ptr->targetoffset) { +#ifdef DWARF_DEBUG + fprintf(stderr, "loop! dieoffset == targetoffset %lld\n", + dw_ptr->targetoffset); +#endif + src->kl_realtype=original; + dw_ptr->complete = 1; + return; + } + if (depth && src == original) { +#ifdef DWARF_DEBUG + fprintf(stderr, "loop! die offset:%lld loops back to itself\n", + dw_ptr->dieoffset); +#endif + src->kl_realtype=original; + dw_ptr->complete = 1; + return; + } + /* If there exists target offset and if realtype is not found yet, find the realtype */ if(!(src->kl_realtype) && (dw_ptr->targetoffset)) { @@ -993,7 +1029,9 @@ void look_for_realtype(kltype_t *src) * namelist indix indicator... */ typenum = TYPENUM(dw_ptr, dw_ptr->targetoffset); - src->kl_realtype = find_realtype_from_offset(typenum); + src->kl_realtype = find_realtype_from_offset(typenum, + original, depth); + } if(src->kl_realtype) { /* Complete the final operations */ @@ -1005,15 +1043,15 @@ void look_for_realtype(kltype_t *src) } /* Lookup for the symbol in tree given an offset and find its realtype */ -static kltype_t * find_realtype_from_offset(Dwarf_Off offset) +static kltype_t * find_realtype_from_offset(Dwarf_Off offset, + kltype_t *original,int depth) { dbg_sym_t *sym_ptr; /* Look up for this symbol */ - if(( sym_ptr = dbg_find_sym(NULL, DBG_TYPE, offset))) { - + if(( sym_ptr = dbg_find_sym(NULL, DBG_TYPE, offset))) { /* Fill up the realtype for this symbol */ - look_for_realtype(sym_ptr->sym_kltype); + look_for_realtype(sym_ptr->sym_kltype, original, depth+1); return (sym_ptr->sym_kltype); } @@ -1039,7 +1077,7 @@ void process_struct_members(kltype_t *so kltype_t *member = source->kl_member; for(; member; member = member->kl_member) { - look_for_realtype(member); + look_for_realtype(member, member, 0); if(member->kl_realtype) { /* If a structure member is of struct type, @@ -1061,9 +1099,11 @@ void process_struct_members(kltype_t *so /* If something is NOT found */ void not_processed (Dwarf_Off dieoffset, Dwarf_Off targetoffset) { +#ifdef DWARF_DEBUG fprintf(stderr,"not found...."); fprintf(stderr,"source-off:%"FMT64"x \t dest-off:%"FMT64"x\n", (uint64_t)dieoffset, (uint64_t)targetoffset); +#endif } @@ -1346,7 +1386,11 @@ static int setup_member_size(kltype_t *k case KLT_UNKNOWN: { /* DW_TAG_const_type DW_TAG_volatile_type */ - setup_member_size(kltype_ptr->kl_realtype); + if (kltype_ptr == kltype_ptr->kl_realtype) { + g_dwarf_size *= kltype_ptr->kl_size; + } else { + setup_member_size(kltype_ptr->kl_realtype); + } break; } case KLT_BASE: { |