📄 mipsread.c
字号:
TIR t[1]; struct type *tp = 0; char *fmt; union aux_ext *tax; enum type_code type_code; /* Use aux as a type information record, map its basic type. */ tax = ax; ecoff_swap_tir_in (bigend, &tax->a_ti, t); if (t->bt > (sizeof (map_bt)/sizeof (*map_bt))) { complain (&basic_type_complaint, (char *)t->bt); return builtin_type_int; } if (map_bt[t->bt]) { tp = *map_bt[t->bt]; fmt = "%s"; } else { tp = NULL; /* Cannot use builtin types -- build our own */ switch (t->bt) { case btAdr: tp = lookup_pointer_type (builtin_type_void); fmt = "%s"; break; case btStruct: type_code = TYPE_CODE_STRUCT; fmt = "struct %s"; break; case btUnion: type_code = TYPE_CODE_UNION; fmt = "union %s"; break; case btEnum: type_code = TYPE_CODE_ENUM; fmt = "enum %s"; break; case btRange: type_code = TYPE_CODE_RANGE; fmt = "%s"; break; case btSet: type_code = TYPE_CODE_SET; fmt = "set %s"; break; case btTypedef: default: complain (&basic_type_complaint, (char *)t->bt); return builtin_type_int; } } /* Skip over any further type qualifiers (FIXME). */ if (t->continued) { /* This is the way it would work if the compiler worked */ TIR t1[1]; do { ax++; ecoff_swap_tir_in (bigend, ax, t1); } while (t1->continued); } /* Move on to next aux */ ax++; if (t->fBitfield) { if (bs != 0) *bs = AUX_GET_WIDTH (bigend, ax); ax++; } /* All these types really point to some (common) MIPS type definition, and only the type-qualifiers fully identify them. We'll make the same effort at sharing. */ if (t->bt == btIndirect || t->bt == btStruct || t->bt == btUnion || t->bt == btEnum || t->bt == btTypedef || t->bt == btRange || t->bt == btSet) { char name[256], *pn; /* Try to cross reference this type */ ax += cross_ref(ax, &tp, type_code, &pn, bigend); /* reading .o file ? */ if (UNSAFE_DATA_ADDR(tp)) tp = init_type(type_code, 0, 0, (char *) NULL, (struct objfile *) NULL); /* SOMEONE OUGHT TO FIX DBXREAD TO DROP "STRUCT" */ sprintf(name, fmt, pn); /* Usually, TYPE_CODE(tp) is already type_code. The main exception is if we guessed wrong re struct/union/enum. */ if (TYPE_CODE(tp) != type_code) { complain (&bad_tag_guess_complaint, name); TYPE_CODE(tp) = type_code; } if (TYPE_NAME(tp) == NULL || strcmp(TYPE_NAME(tp), name) != 0) TYPE_NAME(tp) = obsavestring(name, strlen(name), ¤t_objfile -> type_obstack); } /* Deal with range types */ if (t->bt == btRange) { TYPE_NFIELDS (tp) = 2; TYPE_FIELDS (tp) = (struct field *) TYPE_ALLOC (tp, 2 * sizeof (struct field)); TYPE_FIELD_NAME (tp, 0) = obsavestring ("Low", strlen ("Low"), ¤t_objfile -> type_obstack); TYPE_FIELD_BITPOS (tp, 0) = AUX_GET_DNLOW (bigend, ax); ax++; TYPE_FIELD_NAME (tp, 1) = obsavestring ("High", strlen ("High"), ¤t_objfile -> type_obstack); TYPE_FIELD_BITPOS (tp, 1) = AUX_GET_DNHIGH (bigend, ax); ax++; } /* Parse all the type qualifiers now. If there are more than 6 the game will continue in the next aux */#define PARSE_TQ(tq) \ if (t->tq != tqNil) ax += upgrade_type(&tp, t->tq, ax, bigend);again: PARSE_TQ(tq0); PARSE_TQ(tq1); PARSE_TQ(tq2); PARSE_TQ(tq3); PARSE_TQ(tq4); PARSE_TQ(tq5);#undef PARSE_TQ if (t->continued) { tax++; ecoff_swap_tir_in (bigend, &tax->a_ti, t); goto again; } return tp;}/* Make up a complex type from a basic one. Type is passed by reference in TPP and side-effected as necessary. The type qualifier TQ says how to handle the aux symbols at AX for the symbol SX we are currently analyzing. BIGEND says whether aux symbols are big-endian or little-endian. Returns the number of aux symbols we parsed. */static intupgrade_type(tpp, tq, ax, bigend) struct type **tpp; int tq; union aux_ext *ax; int bigend;{ int off; struct type *t; /* Used in array processing */ int rf, id; FDR *fh; struct field *f; int lower, upper; RNDXR rndx; switch (tq) { case tqPtr: t = lookup_pointer_type (*tpp); *tpp = t; return 0; case tqProc: t = lookup_function_type (*tpp); *tpp = t; return 0; case tqArray: off = 0; t = init_type(TYPE_CODE_ARRAY, 0, 0, (char *) NULL, (struct objfile *) NULL); TYPE_TARGET_TYPE(t) = *tpp; /* Determine and record the domain type (type of index) */ ecoff_swap_rndx_in (bigend, ax, &rndx); id = rndx.index; rf = rndx.rfd; if (rf == 0xfff) { ax++; rf = AUX_GET_ISYM (bigend, ax); off++; } fh = get_rfd(cur_fd, rf); /* Fields are kept in an array */ /* FIXME - Memory leak! */ if (TYPE_NFIELDS(t)) TYPE_FIELDS(t) = (struct field*) xrealloc((PTR) TYPE_FIELDS(t), (TYPE_NFIELDS(t)+1) * sizeof(struct field)); else TYPE_FIELDS(t) = (struct field*) xzalloc(sizeof(struct field)); f = &(TYPE_FIELD(t,TYPE_NFIELDS(t))); TYPE_NFIELDS(t)++; memset((PTR)f, 0, sizeof(struct field));/* XXX */ f->type = parse_type(id + (union aux_ext *)fh->iauxBase, &f->bitsize, bigend); ax++; lower = AUX_GET_DNLOW (bigend, ax); ax++; upper = AUX_GET_DNHIGH (bigend, ax); ax++; rf = AUX_GET_WIDTH (bigend, ax); /* bit size of array element */ /* Check whether supplied array element bit size matches the known size of the element type. If this complaint ends up not happening, we can remove this code. It's here because we aren't sure we understand this *&%&$ symbol format. */ id = TYPE_LENGTH(TYPE_TARGET_TYPE(t)) << 3; /* bitsize */ if (id == 0) { /* Most likely an undefined type */ id = rf; TYPE_LENGTH(TYPE_TARGET_TYPE(t)) = id >> 3; } if (id != rf) complain (&array_bitsize_complaint, (char *)rf); TYPE_LENGTH(t) = (upper < 0) ? 0 : (upper - lower + 1) * (rf >> 3); *tpp = t; return 4 + off; case tqVol: /* Volatile -- currently ignored */ return 0; case tqConst: /* Const -- currently ignored */ return 0; default: complain (&unknown_type_qual_complaint, (char *)tq); return 0; }}/* Parse a procedure descriptor record PR. Note that the procedure is parsed _after_ the local symbols, now we just insert the extra information we need into a MIPS_EFI_SYMBOL_NAME symbol that has already been placed in the procedure's main block. Note also that images that have been partially stripped (ld -x) have been deprived of local symbols, and we have to cope with them here. The procedure's code ends at BOUND */static voidparse_procedure (pr, bound, have_stabs) PDR *pr; int bound; int have_stabs;{ struct symbol *s, *i; SYMR *sh = (SYMR*)pr->isym; struct block *b; struct mips_extra_func_info *e; char *sh_name; /* Static procedure at address pr->adr. Sigh. */ if (sh == (SYMR*)-1) { complain (&pdr_static_symbol_complaint, (char *)pr->adr); return; } sh_name = (char*)sh->iss; if (have_stabs) s = lookup_symbol(sh_name, NULL, VAR_NAMESPACE, 0, NULL); else s = mylookup_symbol(sh_name, top_stack->cur_block, VAR_NAMESPACE, LOC_BLOCK); if (s != 0) { b = SYMBOL_BLOCK_VALUE(s); } else { complain (&pdr_for_nonsymbol_complaint, sh_name);#if 1 return;#else/* FIXME -- delete. We can't do symbol allocation now; it's all done. */ s = new_symbol(sh_name); SYMBOL_NAMESPACE(s) = VAR_NAMESPACE; SYMBOL_CLASS(s) = LOC_BLOCK; /* Donno its type, hope int is ok */ SYMBOL_TYPE(s) = lookup_function_type (builtin_type_int); add_symbol(s, top_stack->cur_block); /* Wont have symbols for this one */ b = new_block(2); SYMBOL_BLOCK_VALUE(s) = b; BLOCK_FUNCTION(b) = s; BLOCK_START(b) = pr->adr; BLOCK_END(b) = bound; BLOCK_SUPERBLOCK(b) = top_stack->cur_block; add_block(b, top_stack->cur_st);#endif } i = mylookup_symbol(MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE, LOC_CONST); if (i) { e = (struct mips_extra_func_info *)SYMBOL_VALUE(i); e->pdr = *pr; e->pdr.isym = (long)s; }}/* Parse the external symbol ES. Just call parse_symbol() after making sure we know where the aux are for it. For procedures, parsing of the PDRs has already provided all the needed information, we only parse them if SKIP_PROCEDURES is false, and only if this causes no symbol duplication. BIGEND says whether aux entries are big-endian or little-endian. This routine clobbers top_stack->cur_block and ->cur_st. */static voidparse_external(es, skip_procedures, bigend) EXTR *es; int skip_procedures; int bigend;{ union aux_ext *ax; if (es->ifd != ifdNil) { cur_fd = es->ifd; cur_fdr = (FDR*)(cur_hdr->cbFdOffset) + cur_fd; ax = (union aux_ext *)cur_fdr->iauxBase; } else { cur_fdr = (FDR*)(cur_hdr->cbFdOffset); ax = 0; } /* Reading .o files */ if (es->asym.sc == scUndefined || es->asym.sc == scNil) { char *what; switch (es->asym.st) { case stStaticProc: case stProc: what = "procedure"; n_undef_procs++; break; case stGlobal: what = "variable"; n_undef_vars++; break; case stLabel: what = "label"; n_undef_labels++; break; default : what = "symbol"; break; } n_undef_symbols++; /* FIXME: Turn this into a complaint? */ if (info_verbose) printf_filtered("Warning: %s `%s' is undefined (in %s)\n", what, es->asym.iss, fdr_name((char *)cur_fdr->rss)); return; } switch (es->asym.st) { case stProc: /* If we have full symbols we do not need more */ if (skip_procedures) return; if (mylookup_symbol ((char *)es->asym.iss, top_stack->cur_block, VAR_NAMESPACE, LOC_BLOCK)) break; /* fall through */ case stGlobal: case stLabel: /* * Note that the case of a symbol with indexNil * must be handled anyways by parse_symbol(). */ parse_symbol(&es->asym, ax, bigend); break; default: break; }}/* Parse the line number info for file descriptor FH into GDB's linetable LT. MIPS' encoding requires a little bit of magic to get things out. Note also that MIPS' line numbers can go back and forth, apparently we can live with that and do not need to reorder our linetables */static voidparse_lines(fh, lt) FDR *fh; struct linetable *lt;{ unsigned char *base = (unsigned char*)fh->cbLineOffset; int j, k; int delta, count, lineno = 0; PDR *pr; if (base == 0) return; /* Scan by procedure descriptors */ j = 0, k = 0; for (pr = (PDR*)IPDFIRST(cur_hdr,fh); j < fh->cpd; j++, pr++) { int l, halt; /* No code for this one */ if (pr->iline == ilineNil || pr->lnLow == -1 || pr->lnHigh == -1) continue; /* * Aurgh! To know where to stop expanding we * must look-ahead. */ for (l = 1; l < (fh->cpd - j); l++) if (pr[l].iline != -1) break; if (l == (fh->cpd - j)) halt = fh->cline; else halt = pr[l].iline; /* * When procedures are moved around the linenumbers * are attributed to the next procedure up */ if (pr->iline >= halt) continue; base = (unsigned char*)pr->cbLineOffset; l = pr->adr >> 2; /* in words */ halt += (pr->adr >> 2) - pr->iline; for (lineno = pr->lnLow; l < halt;) { count = *base & 0x0f; delta = *base++ >> 4; if (delta >= 8) delta -= 16; if (delta == -8) { delta = (base[0] << 8) | base[1]; if (delta >= 0x8000) delta -= 0x10000; base += 2; } lineno += delta;/* first delta is 0 */ k = add_line(lt, lineno, l, k); l += count + 1; } }}/* Master parsing procedure for first-pass reading of file symbols into a partial_symtab. Parses the symtab described by the global symbolic header CUR_HDR. END_OF_TEXT_SEG gives the address just after the text segment for the symtab we are reading. */static voidparse_partial_symbols (end_of_text_seg, objfile, section_offsets) int end_of_text_seg; struct objfile *objfile; struct section_offsets *section_offsets;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -