📄 mipsread.c
字号:
we mark it explicitly */ int pend = (sh->reserved == 1); enum address_class class; TIR tir; switch (sh->st) { case stNil: break; case stGlobal: /* external symbol, goes into global block */ class = LOC_STATIC; b = BLOCKVECTOR_BLOCK(BLOCKVECTOR(top_stack->cur_st), GLOBAL_BLOCK); s = new_symbol((char *)sh->iss); SYMBOL_VALUE_ADDRESS(s) = (CORE_ADDR)sh->value; goto data; case stStatic: /* static data, goes into current block. */ class = LOC_STATIC; b = top_stack->cur_block; s = new_symbol((char *)sh->iss); SYMBOL_VALUE_ADDRESS(s) = (CORE_ADDR)sh->value; goto data; case stLocal: /* local variable, goes into current block */ if (sh->sc == scRegister) { class = LOC_REGISTER; if (sh->value > 31) sh->value += FP0_REGNUM-32; } else class = LOC_LOCAL; b = top_stack->cur_block; s = new_symbol((char *)sh->iss); SYMBOL_VALUE(s) = sh->value;data: /* Common code for symbols describing data */ SYMBOL_NAMESPACE(s) = VAR_NAMESPACE; SYMBOL_CLASS(s) = class; add_symbol(s, b); /* Type could be missing in a number of cases */ if (sh->sc == scUndefined || sh->sc == scNil || sh->index == 0xfffff) SYMBOL_TYPE(s) = builtin_type_int; /* undefined? */ else SYMBOL_TYPE(s) = parse_type(ax + sh->index, 0, bigend); /* Value of a data symbol is its memory address */ break; case stParam: /* arg to procedure, goes into current block */ max_gdbinfo++; top_stack->numargs++; name = (char*)sh->iss; /* Special GNU C++ name. */ if (name[0] == CPLUS_MARKER && name[1] == 't' && name[2] == 0) name = "this"; /* FIXME, not alloc'd in obstack */ s = new_symbol(name); SYMBOL_NAMESPACE(s) = VAR_NAMESPACE; if (sh->sc == scRegister) { SYMBOL_CLASS(s) = LOC_REGPARM; if (sh->value > 31) sh->value += FP0_REGNUM-32; } else SYMBOL_CLASS(s) = LOC_ARG; SYMBOL_VALUE(s) = sh->value; SYMBOL_TYPE(s) = parse_type(ax + sh->index, 0, bigend); add_symbol(s, top_stack->cur_block);#if 0 /* FIXME: This has not been tested. See dbxread.c */ /* Add the type of this parameter to the function/procedure type of this block. */ add_param_to_type(&top_stack->cur_block->function->type,s);#endif break; case stLabel: /* label, goes into current block */ s = new_symbol((char *)sh->iss); SYMBOL_NAMESPACE(s) = VAR_NAMESPACE; /* so that it can be used */ SYMBOL_CLASS(s) = LOC_LABEL; /* but not misused */ SYMBOL_VALUE_ADDRESS(s) = (CORE_ADDR)sh->value; SYMBOL_TYPE(s) = builtin_type_int; add_symbol(s, top_stack->cur_block); break; case stProc: /* Procedure, usually goes into global block */ case stStaticProc: /* Static procedure, goes into current block */ s = new_symbol((char *)sh->iss); SYMBOL_NAMESPACE(s) = VAR_NAMESPACE; SYMBOL_CLASS(s) = LOC_BLOCK; /* Type of the return value */ if (sh->sc == scUndefined || sh->sc == scNil) t = builtin_type_int; else t = parse_type(ax + sh->index + 1, 0, bigend); b = top_stack->cur_block; if (sh->st == stProc) { struct blockvector *bv = BLOCKVECTOR(top_stack->cur_st); /* The next test should normally be true, but provides a hook for nested functions (which we don't want to make global). */ if (b == BLOCKVECTOR_BLOCK(bv, STATIC_BLOCK)) b = BLOCKVECTOR_BLOCK(bv, GLOBAL_BLOCK); } add_symbol(s, b); /* Make a type for the procedure itself */#if 0 /* FIXME: This has not been tested yet! See dbxread.c */ /* Generate a template for the type of this function. The types of the arguments will be added as we read the symbol table. */ bcopy(SYMBOL_TYPE(s),lookup_function_type(t),sizeof(struct type));#else SYMBOL_TYPE(s) = lookup_function_type (t);#endif /* Create and enter a new lexical context */ b = new_block(top_stack->maxsyms); SYMBOL_BLOCK_VALUE(s) = b; BLOCK_FUNCTION(b) = s; BLOCK_START(b) = BLOCK_END(b) = sh->value; BLOCK_SUPERBLOCK(b) = top_stack->cur_block; add_block(b, top_stack->cur_st); /* Not if we only have partial info */ if (sh->sc == scUndefined || sh->sc == scNil) break; push_parse_stack(); top_stack->cur_block = b; top_stack->blocktype = sh->st; top_stack->cur_type = SYMBOL_TYPE(s); top_stack->cur_field = -1; top_stack->procadr = sh->value; top_stack->numargs = 0; sh->value = (long) SYMBOL_TYPE(s); break; /* Beginning of code for structure, union, and enum definitions. They all share a common set of local variables, defined here. */ { enum type_code type_code; SYMR *tsym; int nfields; long max_value; struct field *f; case stStruct: /* Start a block defining a struct type */ type_code = TYPE_CODE_STRUCT; goto structured_common; case stUnion: /* Start a block defining a union type */ type_code = TYPE_CODE_UNION; goto structured_common; case stEnum: /* Start a block defining an enum type */ type_code = TYPE_CODE_ENUM; goto structured_common; case stBlock: /* Either a lexical block, or some type */ if (sh->sc != scInfo) goto case_stBlock_code; /* Lexical block */ type_code = TYPE_CODE_UNDEF; /* We have a type. */ /* Common code for handling struct, union, enum, and/or as-yet- unknown-type blocks of info about structured data. `type_code' has been set to the proper TYPE_CODE, if we know it. */ structured_common: push_parse_stack(); top_stack->blocktype = stBlock; s = new_symbol((char *)sh->iss); SYMBOL_NAMESPACE(s) = STRUCT_NAMESPACE; SYMBOL_CLASS(s) = LOC_TYPEDEF; SYMBOL_VALUE(s) = 0; add_symbol(s, top_stack->cur_block); /* First count the number of fields and the highest value. */ nfields = 0; max_value = 0; for (tsym = sh+1; tsym->st != stEnd; tsym++) { if (tsym->st == stMember) { if (nfields == 0 && type_code == TYPE_CODE_UNDEF) /* If the type of the member is Nil (or Void), assume the tag is an enumeration. */ if (tsym->index == indexNil) type_code = TYPE_CODE_ENUM; else { ecoff_swap_tir_in (bigend, &ax[tsym->index].a_ti, &tir); if (tir.bt == btNil || tir.bt == btVoid) type_code = TYPE_CODE_ENUM; } nfields++; if (tsym->value > max_value) max_value = tsym->value; } else if (tsym->st == stBlock || tsym->st == stUnion || tsym->st == stEnum || tsym->st == stStruct || tsym->st == stParsed) { if (tsym->sc == scVariant) ; /*UNIMPLEMENTED*/ if (tsym->index != 0) tsym = ((SYMR*)cur_fdr->isymBase) + tsym->index-1; } else complain (&block_member_complaint, (char *)tsym->st); } /* In an stBlock, there is no way to distinguish structs, unions, and enums at this point. This is a bug in the original design (that has been fixed with the recent addition of the stStruct, stUnion, and stEnum symbol types.) The way you can tell is if/when you see a variable or field of that type. In that case the variable's type (in the AUX table) says if the type is struct, union, or enum, and points back to the stBlock here. So you can patch the tag kind up later - but only if there actually is a variable or field of that type. So until we know for sure, we will guess at this point. The heuristic is: If the first member has index==indexNil or a void type, assume we have an enumeration. Otherwise, if there is more than one member, and all the members have offset 0, assume we have a union. Otherwise, assume we have a struct. The heuristic could guess wrong in the case of of an enumeration with no members or a union with one (or zero) members, or when all except the last field of a struct have width zero. These are uncommon and/or illegal situations, and in any case guessing wrong probably doesn't matter much. But if we later do find out we were wrong, we fixup the tag kind. Members of an enumeration must be handled differently from struct/union fields, and that is harder to patch up, but luckily we shouldn't need to. (If there are any enumeration members, we can tell for sure it's an enum here.) */ if (type_code == TYPE_CODE_UNDEF) if (nfields > 1 && max_value == 0) type_code = TYPE_CODE_UNION; else type_code = TYPE_CODE_STRUCT; /* If this type was expected, use its partial definition */ if (pend) t = is_pending_symbol(cur_fdr, sh)->t; else t = new_type(prepend_tag_kind((char *)sh->iss, type_code)); TYPE_CODE(t) = type_code; TYPE_LENGTH(t) = sh->value; TYPE_NFIELDS(t) = nfields; TYPE_FIELDS(t) = f = (struct field*) TYPE_ALLOC (t, nfields * sizeof (struct field)); if (type_code == TYPE_CODE_ENUM) { /* This is a non-empty enum. */ for (tsym = sh + 1; tsym->st == stMember; tsym++) { struct symbol *enum_sym; f->bitpos = tsym->value; f->type = t; f->name = (char*)tsym->iss; f->bitsize = 0; enum_sym = (struct symbol *) obstack_alloc (¤t_objfile->symbol_obstack, sizeof (struct symbol)); memset ((PTR)enum_sym, 0, sizeof (struct symbol)); SYMBOL_NAME (enum_sym) = f->name; SYMBOL_CLASS (enum_sym) = LOC_CONST; SYMBOL_TYPE (enum_sym) = t; SYMBOL_NAMESPACE (enum_sym) = VAR_NAMESPACE; SYMBOL_VALUE (enum_sym) = tsym->value; add_symbol(enum_sym, top_stack->cur_block); /* Skip the stMembers that we've handled. */ count++; f++; } } SYMBOL_TYPE(s) = t; /* make this the current type */ top_stack->cur_type = t; top_stack->cur_field = 0; /* Mark that symbol has a type, and say which one */ sh->value = (long) t; break; /* End of local variables shared by struct, union, enum, and block (as yet unknown struct/union/enum) processing. */ } case_stBlock_code: /* beginnning of (code) block. Value of symbol is the displacement from procedure start */ push_parse_stack(); top_stack->blocktype = stBlock; b = new_block(top_stack->maxsyms); BLOCK_START(b) = sh->value + top_stack->procadr; BLOCK_SUPERBLOCK(b) = top_stack->cur_block; top_stack->cur_block = b; add_block(b, top_stack->cur_st); break; case stEnd: /* end (of anything) */ if (sh->sc == scInfo) { /* Finished with type */ top_stack->cur_type = 0; } else if (sh->sc == scText && (top_stack->blocktype == stProc || top_stack->blocktype == stStaticProc)) { /* Finished with procedure */ struct blockvector *bv = BLOCKVECTOR(top_stack->cur_st); struct mips_extra_func_info *e; struct block *b; int i; BLOCK_END(top_stack->cur_block) += sh->value; /* size */ /* Make up special symbol to contain procedure specific info */ s = new_symbol(MIPS_EFI_SYMBOL_NAME); SYMBOL_NAMESPACE(s) = LABEL_NAMESPACE; SYMBOL_CLASS(s) = LOC_CONST; SYMBOL_TYPE(s) = builtin_type_void; e = (struct mips_extra_func_info *) obstack_alloc (¤t_objfile->symbol_obstack, sizeof (struct mips_extra_func_info)); SYMBOL_VALUE(s) = (int)e; e->numargs = top_stack->numargs; add_symbol(s, top_stack->cur_block); /* Reallocate symbols, saving memory */ b = shrink_block(top_stack->cur_block, top_stack->cur_st); /* f77 emits proc-level with address bounds==[0,0], So look for such child blocks, and patch them. */ for (i = 0; i < BLOCKVECTOR_NBLOCKS(bv); i++) { struct block *b_bad = BLOCKVECTOR_BLOCK(bv,i); if (BLOCK_SUPERBLOCK(b_bad) == b && BLOCK_START(b_bad) == top_stack->procadr && BLOCK_END(b_bad) == top_stack->procadr) { BLOCK_START(b_bad) = BLOCK_START(b); BLOCK_END(b_bad) = BLOCK_END(b); } } } else if (sh->sc == scText && top_stack->blocktype == stBlock) { /* End of (code) block. The value of the symbol is the displacement from the procedure`s start address of the end of this block. */ BLOCK_END(top_stack->cur_block) = sh->value + top_stack->procadr; shrink_block(top_stack->cur_block, top_stack->cur_st); } else if (sh->sc == scText && top_stack->blocktype == stFile) { /* End of file. Pop parse stack and ignore. Higher level code deals with this. */ ; } else complain (&stEnd_complaint, (char *)sh->sc); pop_parse_stack(); /* restore previous lexical context */ break; case stMember: /* member of struct or union */ f = &TYPE_FIELDS(top_stack->cur_type)[top_stack->cur_field++]; f->name = (char*)sh->iss; f->bitpos = sh->value; f->bitsize = 0; f->type = parse_type(ax + sh->index, &f->bitsize, bigend); break; case stTypedef: /* type definition */ s = new_symbol((char *)sh->iss); SYMBOL_NAMESPACE(s) = VAR_NAMESPACE; SYMBOL_CLASS(s) = LOC_TYPEDEF; SYMBOL_BLOCK_VALUE(s) = top_stack->cur_block; add_symbol(s, top_stack->cur_block); SYMBOL_TYPE(s) = parse_type(ax + sh->index, 0, bigend); sh->value = (long) SYMBOL_TYPE(s); break; case stFile: /* file name */ push_parse_stack(); top_stack->blocktype = sh->st; break; /* I`ve never seen these for C */ case stRegReloc: break; /* register relocation */ case stForward: break; /* forwarding address */ case stConstant: break; /* constant */ default: complain(&unknown_mips_symtype_complaint, (char *)sh->st); break; } sh->st = stParsed; return count;}/* Parse the type information provided in the raw AX entries for the symbol SH. Return the bitfield size in BS, in case. We must byte-swap the AX entries before we use them; BIGEND says whether they are big-endian or little-endian (from fh->fBigendian). */static struct type *parse_type(ax, bs, bigend) union aux_ext *ax; int *bs; int bigend;{ /* Null entries in this map are treated specially */ static struct type **map_bt[] = { &builtin_type_void, /* btNil */ 0, /* btAdr */ &builtin_type_char, /* btChar */ &builtin_type_unsigned_char, /* btUChar */ &builtin_type_short, /* btShort */ &builtin_type_unsigned_short, /* btUShort */ &builtin_type_int, /* btInt */ &builtin_type_unsigned_int, /* btUInt */ &builtin_type_long, /* btLong */ &builtin_type_unsigned_long, /* btULong */ &builtin_type_float, /* btFloat */ &builtin_type_double, /* btDouble */ 0, /* btStruct */ 0, /* btUnion */ 0, /* btEnum */ 0, /* btTypedef */ 0, /* btRange */ 0, /* btSet */ &builtin_type_complex, /* btComplex */ &builtin_type_double_complex, /* btDComplex */ 0, /* btIndirect */ &builtin_type_fixed_dec, /* btFixedDec */ &builtin_type_float_dec, /* btFloatDec */ &builtin_type_string, /* btString */ 0, /* btBit */ 0, /* btPicture */ &builtin_type_void, /* btVoid */ &builtin_type_long_long, /* btLongLong */ &builtin_type_unsigned_long_long,/* btULongLong */ };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -