📄 mipsread.c
字号:
val = bfd_read((PTR)&filhdr, sizeof filhdr, 1, abfd); if (end_of_text_segp) *end_of_text_segp = bfd_h_get_32 (abfd, filhdr.a.text_start) + bfd_h_get_32 (abfd, filhdr.a.tsize); /* Find and read the symbol table header */ st_hdrsize = bfd_h_get_32 (abfd, filhdr.f.f_nsyms); st_filptr = bfd_h_get_32 (abfd, filhdr.f.f_symptr); if (st_filptr == 0) return; bfd_seek (abfd, st_filptr, L_SET); if (st_hdrsize != sizeof (hdr_ext)) { /* Profanity check */ error ("Wrong header size: %d, not %d", st_hdrsize, sizeof (hdr_ext)); } if (bfd_read((PTR)&hdr_ext, st_hdrsize, 1, abfd) != st_hdrsize) goto readerr; ecoff_swap_hdr_in (abfd, &hdr_ext, &st_hdr); /* Find out how large the symbol table is */ stsize = (st_hdr.cbExtOffset - (st_filptr + st_hdrsize)) + st_hdr.iextMax * cbEXTR; /* Allocate space for the symbol table. Read it in. */ cur_hdr = (HDRR *) xmalloc(stsize + st_hdrsize); memcpy((PTR)cur_hdr, (PTR)&hdr_ext, st_hdrsize); if (bfd_read((char *)cur_hdr + st_hdrsize, stsize, 1, abfd) != stsize) goto readerr; /* Fixup file_pointers in it */ fixup_symtab(cur_hdr, (char *) cur_hdr + st_hdrsize, st_filptr + st_hdrsize, abfd); return;readerr: error("Short read on %s", bfd_get_filename (abfd));}/* Turn all file-relative pointers in the symtab described by HDR into memory pointers, given that the symtab itself is located at DATA in memory and F_PTR in the file. Byte-swap all the data structures, in place, while we are at it -- except AUX entries, which we leave in their original byte order. They will be swapped as they are used instead. (FIXME: we ought to do all the data structures that way.) */static voidfixup_symtab (hdr, data, f_ptr, abfd) HDRR *hdr; char *data; file_ptr f_ptr; bfd *abfd;{ int f_idx, s_idx, i; FDR *fh; SYMR *sh; PDR *pr; EXTR *esh; struct rfd_ext *rbase; /* This function depends on the external and internal forms of the MIPS symbol table taking identical space. Check this assumption at compile-time. DO NOT DELETE THESE ENTRIES, OR COMMENT THEM OUT, JUST BECAUSE SOME "LINT" OR COMPILER THINKS THEY ARE UNUSED! Thank you. */ static check_hdr1[1 + sizeof (struct hdr_ext) - sizeof (HDRR)] = {0}; static check_hdr2[1 + sizeof (HDRR) - sizeof (struct hdr_ext)] = {0}; static check_fdr1[1 + sizeof (struct fdr_ext) - sizeof (FDR)] = {0}; static check_fdr2[1 + sizeof (FDR) - sizeof (struct fdr_ext)] = {0}; static check_pdr1[1 + sizeof (struct pdr_ext) - sizeof (PDR)] = {0}; static check_pdr2[1 + sizeof (PDR) - sizeof (struct pdr_ext)] = {0}; static check_sym1[1 + sizeof (struct sym_ext) - sizeof (SYMR)] = {0}; static check_sym2[1 + sizeof (SYMR) - sizeof (struct sym_ext)] = {0}; static check_ext1[1 + sizeof (struct ext_ext) - sizeof (EXTR)] = {0}; static check_ext2[1 + sizeof (EXTR) - sizeof (struct ext_ext)] = {0}; static check_rfd1[1 + sizeof (struct rfd_ext) - sizeof (RFDT)] = {0}; static check_rfd2[1 + sizeof (RFDT) - sizeof (struct rfd_ext)] = {0}; /* Swap in the header record. */ ecoff_swap_hdr_in (abfd, hdr, hdr); /* * These fields are useless (and empty) by now: * hdr->cbDnOffset, hdr->cbOptOffset * We use them for other internal purposes. */ hdr->cbDnOffset = 0; hdr->cbOptOffset = 0;#define FIX(off) \ if (hdr->off) hdr->off = (unsigned int)data + (hdr->off - f_ptr); FIX(cbLineOffset); FIX(cbPdOffset); FIX(cbSymOffset); FIX(cbOptOffset); FIX(cbAuxOffset); FIX(cbSsOffset); FIX(cbSsExtOffset); FIX(cbFdOffset); FIX(cbRfdOffset); FIX(cbExtOffset);#undef FIX /* Fix all the RFD's. */ rbase = (struct rfd_ext *)(hdr->cbRfdOffset); for (i = 0; i < hdr->crfd; i++) { ecoff_swap_rfd_in (abfd, rbase+i, (pRFDT) rbase+i); } /* Fix all string pointers inside the symtab, and the FDR records. Also fix other miscellany. */ for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) { register unsigned code_offset; /* Header itself, and strings */ fh = (FDR *) (hdr->cbFdOffset) + f_idx; /* Swap in the FDR */ ecoff_swap_fdr_in (abfd, fh, fh); fh->issBase += hdr->cbSsOffset; if (fh->rss != -1) fh->rss = (long)fh->rss + fh->issBase; /* Local symbols */ fh->isymBase = (int)((SYMR*)(hdr->cbSymOffset)+fh->isymBase); /* FIXME! Probably don't want to do this here! */ for (s_idx = 0; s_idx < fh->csym; s_idx++) { sh = (SYMR*)fh->isymBase + s_idx; ecoff_swap_sym_in (abfd, sh, sh); sh->iss = (long) sh->iss + fh->issBase; sh->reserved = 0; } cur_fd = f_idx; /* cannot fix fh->ipdFirst because it is a short */#define IPDFIRST(h,fh) \ ((long)h->cbPdOffset + fh->ipdFirst * sizeof(PDR)) /* Optional symbols (actually used for partial_symtabs) */ fh->ioptBase = 0; fh->copt = 0; /* Aux symbols */ if (fh->caux) fh->iauxBase = hdr->cbAuxOffset + fh->iauxBase * sizeof(union aux_ext); /* Relative file descriptor table */ fh->rfdBase = hdr->cbRfdOffset + fh->rfdBase * sizeof(RFDT); /* Line numbers */ if (fh->cbLine) fh->cbLineOffset += hdr->cbLineOffset; /* Procedure symbols. (XXX This should be done later) */ code_offset = fh->adr; for (s_idx = 0; s_idx < fh->cpd; s_idx++) { unsigned name, only_ext; pr = (PDR*)(IPDFIRST(hdr,fh)) + s_idx; ecoff_swap_pdr_in (abfd, pr, pr); /* Simple rule to find files linked "-x" */ only_ext = fh->rss == -1; if (only_ext) { if (pr->isym == -1) { /* static function */ sh = (SYMR*)-1; } else { /* external */ name = hdr->cbExtOffset + pr->isym * sizeof(EXTR); sh = &((EXTR*)name)->asym; } } else { /* Full symbols */ sh = (SYMR*)fh->isymBase + pr->isym; /* Included code ? */ if (s_idx == 0 && pr->adr != 0) code_offset -= pr->adr; } /* Turn index into a pointer */ pr->isym = (long)sh; /* Fix line numbers */ pr->cbLineOffset += fh->cbLineOffset; /* Relocate address */ if (!only_ext) pr->adr += code_offset; } } /* External symbols: swap in, and fix string */ for (s_idx = 0; s_idx < hdr->iextMax; s_idx++) { esh = (EXTR*)(hdr->cbExtOffset) + s_idx; ecoff_swap_ext_in (abfd, esh, esh); esh->asym.iss = esh->asym.iss + hdr->cbSsExtOffset; }}/* Find a file descriptor given its index RF relative to a file CF */static FDR *get_rfd (cf, rf) int cf, rf;{ register FDR *f; f = (FDR *) (cur_hdr->cbFdOffset) + cf; /* Object files do not have the RFD table, all refs are absolute */ if (f->rfdBase == 0) return (FDR *) (cur_hdr->cbFdOffset) + rf; cf = *((pRFDT) f->rfdBase + rf); return (FDR *) (cur_hdr->cbFdOffset) + cf;}/* Return a safer print NAME for a file descriptor */static char *fdr_name(name) char *name;{ if (name == (char *) -1) return "<stripped file>"; if (UNSAFE_DATA_ADDR(name)) return "<NFY>"; return name;}/* Read in and parse the symtab of the file OBJFILE. Symbols from different sections are relocated via the SECTION_OFFSETS. */static voidread_mips_symtab (objfile, section_offsets) struct objfile *objfile; struct section_offsets *section_offsets;{ CORE_ADDR end_of_text_seg; read_the_mips_symtab(objfile->obfd, &end_of_text_seg); parse_partial_symbols(end_of_text_seg, objfile, section_offsets);#if 0 /* * Check to make sure file was compiled with -g. * If not, warn the user of this limitation. */ if (compare_glevel(max_glevel, GLEVEL_2) < 0) { if (max_gdbinfo == 0) printf ("\n%s not compiled with -g, debugging support is limited.\n", objfile->name); printf("You should compile with -g2 or -g3 for best debugging support.\n"); fflush(stdout); }#endif}/* Local utilities *//* Map of FDR indexes to partial symtabs */struct pst_map { struct partial_symtab *pst; /* the psymtab proper */ int n_globals; /* exported globals (external symbols) */ int globals_offset; /* cumulative */};/* Utility stack, used to nest procedures and blocks properly. It is a doubly linked list, to avoid too many alloc/free. Since we might need it quite a few times it is NOT deallocated after use. */static struct parse_stack { struct parse_stack *next, *prev; struct symtab *cur_st; /* Current symtab. */ struct block *cur_block; /* Block in it. */ int blocktype; /* What are we parsing. */ int maxsyms; /* Max symbols in this block. */ struct type *cur_type; /* Type we parse fields for. */ int cur_field; /* Field number in cur_type. */ int procadr; /* Start addres of this procedure */ int numargs; /* Its argument count */} *top_stack; /* Top stack ptr *//* Enter a new lexical context */static voidpush_parse_stack(){ struct parse_stack *new; /* Reuse frames if possible */ if (top_stack && top_stack->prev) new = top_stack->prev; else new = (struct parse_stack *) xzalloc(sizeof(struct parse_stack)); /* Initialize new frame with previous content */ if (top_stack) { register struct parse_stack *prev = new->prev; *new = *top_stack; top_stack->prev = new; new->prev = prev; new->next = top_stack; } top_stack = new;}/* Exit a lexical context */static voidpop_parse_stack(){ if (!top_stack) return; if (top_stack->next) top_stack = top_stack->next;}/* Cross-references might be to things we haven't looked at yet, e.g. type references. To avoid too many type duplications we keep a quick fixup table, an array of lists of references indexed by file descriptor */static struct mips_pending { struct mips_pending *next; /* link */ SYMR *s; /* the symbol */ struct type *t; /* its partial type descriptor */} **pending_list;/* Check whether we already saw symbol SH in file FH as undefined */static struct mips_pending *is_pending_symbol(fh, sh) FDR *fh; SYMR *sh;{ int f_idx = fh - (FDR *) cur_hdr->cbFdOffset; register struct mips_pending *p; /* Linear search is ok, list is typically no more than 10 deep */ for (p = pending_list[f_idx]; p; p = p->next) if (p->s == sh) break; return p;}/* Add a new undef symbol SH of type T */static voidadd_pending(fh, sh, t) FDR *fh; SYMR *sh; struct type *t;{ int f_idx = fh - (FDR *) cur_hdr->cbFdOffset; struct mips_pending *p = is_pending_symbol(fh, sh); /* Make sure we do not make duplicates */ if (!p) { p = (struct mips_pending *) xmalloc(sizeof(*p)); p->s = sh; p->t = t; p->next = pending_list[f_idx]; pending_list[f_idx] = p; } sh->reserved = 1; /* for quick check */}/* Throw away undef entries when done with file index F_IDX *//* FIXME -- storage leak. This is never called!!! --gnu */#if 0static voidfree_pending(f_idx) int f_idx;{ register struct mips_pending *p, *q; for (p = pending_list[f_idx]; p; p = q) { q = p->next; free((PTR)p); } pending_list[f_idx] = 0;}#endifstatic char *prepend_tag_kind(tag_name, type_code) char *tag_name; enum type_code type_code;{ char *prefix; char *result; switch (type_code) { case TYPE_CODE_ENUM: prefix = "enum "; break; case TYPE_CODE_STRUCT: prefix = "struct "; break; case TYPE_CODE_UNION: prefix = "union "; break; default: prefix = ""; } result = (char*)obstack_alloc (¤t_objfile->symbol_obstack, strlen(prefix) + strlen(tag_name) + 1); sprintf(result, "%s%s", prefix, tag_name); return result;}/* Parsing Routines proper. *//* Parse a single symbol. Mostly just make up a GDB symbol for it. For blocks, procedures and types we open a new lexical context. This is basically just a big switch on the symbol's type. Argument AX is the base pointer of aux symbols for this file (fh->iauxBase). BIGEND says whether aux symbols are big-endian or little-endian. Return count of SYMR's handled (normally one). */static intparse_symbol(sh, ax, bigend) SYMR *sh; union aux_ext *ax; int bigend;{ char *name; struct symbol *s; struct block *b; struct type *t; struct field *f; int count = 1; /* When a symbol is cross-referenced from other files/symbols
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -