📄 coffread.c
字号:
int nsyms; struct objfile *objfile;{ FILE *stream; register struct coff_context_stack *new; struct coff_symbol coff_symbol; register struct coff_symbol *cs = &coff_symbol; static struct internal_syment main_sym; static union internal_auxent main_aux; struct coff_symbol fcn_cs_saved; static struct internal_syment fcn_sym_saved; static union internal_auxent fcn_aux_saved; struct symtab *s; /* A .file is open. */ int in_source_file = 0; int num_object_files = 0; int next_file_symnum = -1; /* Name of the current file. */ char *filestring = ""; int depth = 0; int fcn_first_line = 0; int fcn_last_line = 0; int fcn_start_addr = 0; long fcn_line_ptr = 0; struct cleanup *old_chain; int val; stream = fopen (objfile->name, FOPEN_RB); if (!stream) perror_with_name(objfile->name); /* Position to read the symbol table. */ val = fseek (stream, (long)symtab_offset, 0); if (val < 0) perror_with_name (objfile->name); /* These cleanups will be discarded below if we succeed. */ old_chain = make_cleanup (free_objfile, objfile); make_cleanup (fclose, stream); current_objfile = objfile; nlist_stream_global = stream; nlist_nsyms_global = nsyms; last_source_file = NULL; memset (opaque_type_chain, 0, sizeof opaque_type_chain); if (type_vector) /* Get rid of previous one */ free ((PTR)type_vector); type_vector_length = 160; type_vector = (struct type **) xmalloc (type_vector_length * sizeof (struct type *)); memset (type_vector, 0, type_vector_length * sizeof (struct type *)); coff_start_symtab (); symnum = 0; while (symnum < nsyms) { QUIT; /* Make this command interruptable. */ read_one_sym (cs, &main_sym, &main_aux);#ifdef SEM temp_sem_val = cs->c_name[0] << 24 | cs->c_name[1] << 16 | cs->c_name[2] << 8 | cs->c_name[3]; if (int_sem_val == temp_sem_val) last_coffsem = (int) strtol (cs->c_name+4, (char **) NULL, 10);#endif if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE) { if (last_source_file) coff_end_symtab (objfile); coff_start_symtab (); complete_symtab ("_globals_", 0, first_object_file_end); /* done with all files, everything from here on out is globals */ } /* Special case for file with type declarations only, no text. */ if (!last_source_file && SDB_TYPE (cs->c_type) && cs->c_secnum == N_DEBUG) complete_symtab (filestring, 0, 0); /* Typedefs should not be treated as symbol definitions. */ if (ISFCN (cs->c_type) && cs->c_sclass != C_TPDEF) { /* record as a minimal symbol. if we get '.bf' next, * then we undo this step */ record_minimal_symbol (cs->c_name, cs->c_value, mst_text); fcn_line_ptr = main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr; fcn_start_addr = cs->c_value; fcn_cs_saved = *cs; fcn_sym_saved = main_sym; fcn_aux_saved = main_aux; continue; } switch (cs->c_sclass) { case C_EFCN: case C_EXTDEF: case C_ULABEL: case C_USTATIC: case C_LINE: case C_ALIAS: case C_HIDDEN: complain (&bad_sclass_complaint, cs->c_name); break; case C_FILE: /* * c_value field contains symnum of next .file entry in table * or symnum of first global after last .file. */ next_file_symnum = cs->c_value; filestring = getfilename (&main_aux); /* * Complete symbol table for last object file * containing debugging information. */ if (last_source_file) { coff_end_symtab (objfile); coff_start_symtab (); } in_source_file = 1; break; case C_STAT: if (cs->c_name[0] == '.') { if (strcmp (cs->c_name, ".text") == 0) { /* FIXME: don't wire in ".text" as section name or symbol name! */ if (++num_object_files == 1) { /* last address of startup file */ first_object_file_end = cs->c_value + main_aux.x_scn.x_scnlen; } /* Check for in_source_file deals with case of a file with debugging symbols followed by a later file with no symbols. */ if (in_source_file) complete_symtab (filestring, cs->c_value, main_aux.x_scn.x_scnlen); in_source_file = 0; } /* flush rest of '.' symbols */ break; } else if (!SDB_TYPE (cs->c_type) && cs->c_name[0] == 'L' && (strncmp (cs->c_name, "LI%", 3) == 0 || strncmp (cs->c_name, "LF%", 3) == 0 || strncmp (cs->c_name,"LC%",3) == 0 || strncmp (cs->c_name,"LP%",3) == 0 || strncmp (cs->c_name,"LPB%",4) == 0 || strncmp (cs->c_name,"LBB%",4) == 0 || strncmp (cs->c_name,"LBE%",4) == 0 || strncmp (cs->c_name,"LPBX%",5) == 0)) /* At least on a 3b1, gcc generates swbeg and string labels that look like this. Ignore them. */ break; /* fall in for static symbols that don't start with '.' */ case C_EXT: if (!SDB_TYPE (cs->c_type)) { /* FIXME: This is BOGUS Will Robinson! Coff should provide the SEC_CODE flag for executable sections, then if we could look up sections by section number we could see if the flags indicate SEC_CODE. If so, then record this symbol as a function in the minimal symbol table. But why are absolute syms recorded as functions, anyway? */ if (cs->c_secnum <= text_bfd_scnum+1) {/* text or abs */ record_minimal_symbol (cs->c_name, cs->c_value, mst_text); break; } else { record_minimal_symbol (cs->c_name, cs->c_value, mst_data); break; } } process_coff_symbol (cs, &main_aux, objfile); break; case C_FCN: if (strcmp (cs->c_name, ".bf") == 0) { within_function = 1; /* value contains address of first non-init type code */ /* main_aux.x_sym.x_misc.x_lnsz.x_lnno contains line number of '{' } */ if (cs->c_naux != 1) complain (&bf_no_aux_complaint, (char *) cs->c_symnum); fcn_first_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno; new = (struct coff_context_stack *) xmalloc (sizeof (struct coff_context_stack)); new->depth = depth = 0; new->next = 0; coff_context_stack = new; new->locals = 0; new->old_blocks = pending_blocks; new->start_addr = fcn_start_addr; fcn_cs_saved.c_name = getsymname (&fcn_sym_saved); new->name = process_coff_symbol (&fcn_cs_saved, &fcn_aux_saved, objfile); } else if (strcmp (cs->c_name, ".ef") == 0) { /* the value of .ef is the address of epilogue code; * not useful for gdb */ /* { main_aux.x_sym.x_misc.x_lnsz.x_lnno contains number of lines to '}' */ new = coff_context_stack; if (new == 0) { complain (&ef_complaint, (char *) cs->c_symnum); within_function = 0; break; } if (cs->c_naux != 1) { complain (&ef_no_aux_complaint, (char *) cs->c_symnum); fcn_last_line = 0x7FFFFFFF; } else { fcn_last_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno; } enter_linenos (fcn_line_ptr, fcn_first_line, fcn_last_line); coff_finish_block (new->name, &coff_local_symbols, new->old_blocks, new->start_addr,#if defined (FUNCTION_EPILOGUE_SIZE) /* This macro should be defined only on machines where the fcn_aux_saved.x_sym.x_misc.x_fsize field is always zero. So use the .bf record information that points to the epilogue and add the size of the epilogue. */ cs->c_value + FUNCTION_EPILOGUE_SIZE,#else fcn_cs_saved.c_value + fcn_aux_saved.x_sym.x_misc.x_fsize,#endif objfile ); coff_context_stack = 0; within_function = 0; free ((PTR)new); } break; case C_BLOCK: if (strcmp (cs->c_name, ".bb") == 0) { new = (struct coff_context_stack *) xmalloc (sizeof (struct coff_context_stack)); depth++; new->depth = depth; new->next = coff_context_stack; coff_context_stack = new; new->locals = coff_local_symbols; new->old_blocks = pending_blocks; new->start_addr = cs->c_value; new->name = 0; coff_local_symbols = 0; } else if (strcmp (cs->c_name, ".eb") == 0) { new = coff_context_stack; if (new == 0 || depth != new->depth) error ("Invalid symbol data: .bb/.eb symbol mismatch at symbol %d.", symnum); if (coff_local_symbols && coff_context_stack->next) { /* Make a block for the local symbols within. */ coff_finish_block (0, &coff_local_symbols, new->old_blocks, new->start_addr, cs->c_value, objfile); } depth--; coff_local_symbols = new->locals; coff_context_stack = new->next; free ((PTR)new); } break; default: process_coff_symbol (cs, &main_aux, objfile); break; } } if (last_source_file) coff_end_symtab (objfile); fclose (stream); /* Patch up any opaque types (references to types that are not defined in the file where they are referenced, e.g. "struct foo *bar"). */ ALL_OBJFILE_SYMTABS (objfile, s) patch_opaque_types (s); discard_cleanups (old_chain); current_objfile = NULL;}/* Routines for reading headers and symbols from executable. */#ifdef FIXME/* Move these XXXMAGIC symbol defns into BFD! *//* Read COFF file header, check magic number, and return number of symbols. */read_file_hdr (chan, file_hdr) int chan; FILHDR *file_hdr;{ lseek (chan, 0L, 0); if (myread (chan, (char *)file_hdr, FILHSZ) < 0) return -1; switch (file_hdr->f_magic) {#ifdef MC68MAGIC case MC68MAGIC:#endif#ifdef NS32GMAGIC case NS32GMAGIC: case NS32SMAGIC:#endif#ifdef I386MAGIC case I386MAGIC:#endif#ifdef CLIPPERMAGIC case CLIPPERMAGIC:#endif#if defined (MC68KWRMAGIC) \ && (!defined (MC68MAGIC) || MC68KWRMAGIC != MC68MAGIC) case MC68KWRMAGIC:#endif#ifdef MC68KROMAGIC case MC68KROMAGIC: case MC68KPGMAGIC:#endif#ifdef MC88DGMAGIC case MC88DGMAGIC:#endif #ifdef MC88MAGIC case MC88MAGIC:#endif #ifdef I960ROMAGIC case I960ROMAGIC: /* Intel 960 */#endif#ifdef I960RWMAGIC case I960RWMAGIC: /* Intel 960 */#endif return file_hdr->f_nsyms; default:#ifdef BADMAG if (BADMAG(file_hdr)) return -1; else return file_hdr->f_nsyms;#else return -1;#endif }}#endif/* Read the next symbol, swap it, and return it in both internal_syment form, and coff_symbol form. Also return its first auxent, if any, in internal_auxent form, and skip any other auxents. */static voidread_one_sym (cs, sym, aux) register struct coff_symbol *cs; register struct internal_syment *sym; register union internal_auxent *aux;{ int i; cs->c_symnum = symnum; fread (temp_sym, local_symesz, 1, nlist_stream_global); bfd_coff_swap_sym_in (symfile_bfd, temp_sym, (char *)sym); cs->c_naux = sym->n_numaux & 0xff; if (cs->c_naux >= 1) { fread (temp_aux, local_auxesz, 1, nlist_stream_global); bfd_coff_swap_aux_in (symfile_bfd, temp_aux, sym->n_type, sym->n_sclass, (char *)aux); /* If more than one aux entry, read past it (only the first aux is important). */ for (i = 1; i < cs->c_naux; i++) fread (temp_aux, local_auxesz, 1, nlist_stream_global); } cs->c_name = getsymname (sym); cs->c_value = sym->n_value; cs->c_sclass = (sym->n_sclass & 0xff); cs->c_secnum = sym->n_scnum; cs->c_type = (unsigned) sym->n_type; if (!SDB_TYPE (cs->c_type)) cs->c_type = 0; symnum += 1 + cs->c_naux;}/* Support for string table handling */static char *stringtab = NULL;static intinit_stringtab (chan, offset) int chan; long offset;{ long length; int val; unsigned char lengthbuf[4]; if (stringtab) { free (stringtab); stringtab = NULL; } if (lseek (chan, offset, 0) < 0) return -1; val = myread (chan, (char *)lengthbuf, sizeof lengthbuf); length = bfd_h_get_32 (symfile_bfd, lengthbuf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -