📄 xcoffread.c
字号:
return NULL;}#endif /* 0 *//* Save the vital information for use when closing off the current file. NAME is the file name the symbols came from, START_ADDR is the first text address for the file, and SIZE is the number of bytes of text. */#define complete_symtab(name, start_addr) { \ last_source_file = savestring (name, strlen (name)); \ last_source_start_addr = start_addr; \}/* Refill the symbol table input buffer and set the variables that control fetching entries from it. Reports an error if no data available. This function can read past the end of the symbol table (into the string table) but this does no harm. *//* Reading symbol table has to be fast! Keep the followings as macros, rather than functions. */#define RECORD_MINIMAL_SYMBOL(NAME, ADDR, TYPE, ALLOCED) \{ \ char *namestr; \ if (ALLOCED) \ namestr = (NAME) + 1; \ else { \ (NAME) = namestr = \ obstack_copy0 (&objfile->symbol_obstack, (NAME) + 1, strlen ((NAME)+1)); \ (ALLOCED) = 1; \ } \ prim_record_minimal_symbol (namestr, (ADDR), (TYPE)); \ misc_func_recorded = 1; \}/* A parameter template, used by ADD_PARM_TO_PENDING. */static struct symbol parmsym = { /* default parameter symbol */ "", /* name */ VAR_NAMESPACE, /* namespace */ LOC_ARG, /* class */ NULL, /* type */ 0, /* line number */ 0, /* value */};/* Add a parameter to a given pending symbol list. */ #define ADD_PARM_TO_PENDING(PARM, VALUE, PTYPE, PENDING_SYMBOLS) \{ \ PARM = (struct symbol *) \ obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); \ *(PARM) = parmsym; \ SYMBOL_TYPE (PARM) = PTYPE; \ SYMBOL_VALUE (PARM) = VALUE; \ add_symbol_to_list (PARM, &PENDING_SYMBOLS); \}/* xcoff has static blocks marked in `.bs', `.es' pairs. They cannot be nested. At any given time, a symbol can only be in one static block. This is the base address of current static block, zero if non exists. */ static int static_block_base = 0;/* true if space for symbol name has been allocated. */static int symname_alloced = 0;/* read the whole symbol table of a given bfd. */static voidread_xcoff_symtab (objfile, nsyms) struct objfile *objfile; /* Object file we're reading from */ int nsyms; /* # of symbols */{ bfd *abfd = objfile->obfd; char *raw_symbol; /* Pointer into raw seething symbol table */ char *raw_auxptr; /* Pointer to first raw aux entry for sym */ sec_ptr textsec; /* Pointer to text section */ TracebackInfo *ptb; /* Pointer to traceback table */ struct internal_syment symbol[1]; union internal_auxent main_aux[1]; struct coff_symbol cs[1]; CORE_ADDR file_start_addr = 0; CORE_ADDR file_end_addr = 0; int next_file_symnum = -1; int just_started = 1; int depth = 0; int toc_offset = 0; /* toc offset value in data section. */ int val; int fcn_last_line; int fcn_start_addr; long fcn_line_offset; size_t size; struct coff_symbol fcn_stab_saved; /* fcn_cs_saved is global because process_xcoff_symbol needs it. */ union internal_auxent fcn_aux_saved; struct type *fcn_type_saved = NULL; struct context_stack *new; char *filestring = " _start_ "; /* Name of the current file. */ char *last_csect_name; /* last seen csect's name and value */ CORE_ADDR last_csect_val; int misc_func_recorded; /* true if any misc. function */ current_objfile = objfile; /* Get the appropriate COFF "constants" related to the file we're handling. */ N_TMASK = coff_data (abfd)->local_n_tmask; N_BTSHFT = coff_data (abfd)->local_n_btshft; local_symesz = coff_data (abfd)->local_symesz; last_source_file = NULL; last_csect_name = 0; last_csect_val = 0; misc_func_recorded = 0; start_stabs (); start_symtab (filestring, (char *)NULL, file_start_addr); symnum = 0; first_object_file_end = 0; /* Allocate space for the entire symbol table at once, and read it all in. The bfd is already positioned at the beginning of the symbol table. */ size = coff_data (abfd)->local_symesz * nsyms; symtbl = xmalloc (size); val = bfd_read (symtbl, size, 1, abfd); if (val != size) perror_with_name ("reading symbol table"); raw_symbol = symtbl; textsec = bfd_get_section_by_name (abfd, ".text"); if (!textsec) { printf ("Unable to locate text section!\n"); } while (symnum < nsyms) { QUIT; /* make this command interruptable. */ /* READ_ONE_SYMBOL (symbol, cs, symname_alloced); */ /* read one symbol into `cs' structure. After processing the whole symbol table, only string table will be kept in memory, symbol table and debug section of xcoff will be freed. Thus we can mark symbols with names in string table as `alloced'. */ { int ii; /* Swap and align the symbol into a reasonable C structure. */ bfd_coff_swap_sym_in (abfd, raw_symbol, symbol); cs->c_symnum = symnum; cs->c_nsyms = symbol->n_numaux; if (symbol->n_zeroes) { symname_alloced = 0; /* We must use the original, unswapped, name here so the name field pointed to by cs->c_name will persist throughout xcoffread. If we use the new field, it gets overwritten for each symbol. */ cs->c_name = ((struct external_syment *)raw_symbol)->e.e_name; } else if (symbol->n_sclass & 0x80) { cs->c_name = debugsec + symbol->n_offset; symname_alloced = 0; } else { /* in string table */ cs->c_name = strtbl + (int)symbol->n_offset; symname_alloced = 1; } cs->c_value = symbol->n_value; /* n_sclass is signed (FIXME), so we had better not mask off any high bits it contains, since the values we will be comparing it to are also signed (FIXME). Defined in <coff/internal.h>. At this point (3Jun92, gnu@cygnus.com) I think the fix is to make the fields and values unsigned chars, but changing the next line is a simple patch late in the release cycle, for now. */ cs->c_sclass = symbol->n_sclass /* & 0xff */; cs->c_secnum = symbol->n_scnum; cs->c_type = (unsigned)symbol->n_type; raw_symbol += coff_data (abfd)->local_symesz; ++symnum; raw_auxptr = raw_symbol; /* Save addr of first aux entry */ /* Skip all the auxents associated with this symbol. */ for (ii = symbol->n_numaux; ii; --ii ) { raw_symbol += coff_data (abfd)->local_auxesz; ++symnum; } } /* if symbol name starts with ".$" or "$", ignore it. */ if (cs->c_name[0] == '$' || (cs->c_name[1] == '$' && cs->c_name[0] == '.')) continue; if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE) { if (last_source_file) { end_symtab (cur_src_end_addr, 1, 0, objfile); end_stabs (); } start_stabs (); start_symtab ("_globals_", (char *)NULL, (CORE_ADDR)0); cur_src_end_addr = first_object_file_end; /* done with all files, everything from here on is globals */ } /* if explicitly specified as a function, treat is as one. */ if (ISFCN(cs->c_type) && cs->c_sclass != C_TPDEF) { bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass, main_aux); goto function_entry_point; } if ((cs->c_sclass == C_EXT || cs->c_sclass == C_HIDEXT) && cs->c_nsyms == 1) { /* dealing with a symbol with a csect entry. */# define CSECT(PP) ((PP)->x_csect)# define CSECT_LEN(PP) (CSECT(PP).x_scnlen)# define CSECT_ALIGN(PP) (SMTYP_ALIGN(CSECT(PP).x_smtyp))# define CSECT_SMTYP(PP) (SMTYP_SMTYP(CSECT(PP).x_smtyp))# define CSECT_SCLAS(PP) (CSECT(PP).x_smclas) /* Convert the auxent to something we can access. */ bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass, main_aux); switch (CSECT_SMTYP (main_aux)) { case XTY_ER : continue; /* ignore all external references. */ case XTY_SD : /* a section description. */ { switch (CSECT_SCLAS (main_aux)) { case XMC_PR : /* a `.text' csect. */ { /* A program csect is seen. We have to allocate one symbol table for each program csect. Normally gdb prefers one symtab for each compilation unit (CU). In case of AIX, one CU might include more than one prog csect, and they don't have to be adjacent in terms of the space they occupy in memory. Thus, one single CU might get fragmented in the memory and gdb's file start and end address approach does not work! */ if (last_csect_name) { /* if no misc. function recorded in the last seen csect, enter it as a function. This will take care of functions like strcmp() compiled by xlc. */ if (!misc_func_recorded) { int alloced = 0; RECORD_MINIMAL_SYMBOL (last_csect_name, last_csect_val, mst_text, alloced); } complete_symtab (filestring, file_start_addr); cur_src_end_addr = file_end_addr; end_symtab (file_end_addr, 1, 0, objfile); end_stabs (); start_stabs (); start_symtab ((char *)NULL, (char *)NULL, (CORE_ADDR)0); } /* If this is the very first csect seen, basically `__start'. */ if (just_started) { first_object_file_end = cs->c_value + CSECT_LEN (main_aux); just_started = 0; } file_start_addr = cs->c_value; file_end_addr = cs->c_value + CSECT_LEN (main_aux); if (cs->c_name && cs->c_name[0] == '.') { last_csect_name = cs->c_name; last_csect_val = cs->c_value; } } misc_func_recorded = 0; continue; case XMC_RW : break; /* If the section is not a data description, ignore it. Note that uninitialized data will show up as XTY_CM/XMC_RW pair. */ case XMC_TC0: if (toc_offset) warning ("More than one xmc_tc0 symbol found."); toc_offset = cs->c_value; continue; case XMC_TC : /* ignore toc entries */ default : /* any other XMC_XXX */ continue; } } break; /* switch CSECT_SCLAS() */ case XTY_LD : /* a function entry point. */ if (CSECT_SCLAS (main_aux) == XMC_PR) {function_entry_point: RECORD_MINIMAL_SYMBOL (cs->c_name, cs->c_value, mst_text, symname_alloced); fcn_line_offset = main_aux->x_sym.x_fcnary.x_fcn.x_lnnoptr; fcn_start_addr = cs->c_value; /* save the function header info, which will be used when `.bf' is seen. */ fcn_cs_saved = *cs; fcn_aux_saved = *main_aux; ptb = NULL; /* If function has two auxent, then debugging information is already available for it. Process traceback table for functions with only one auxent. */ if (cs->c_nsyms == 1) ptb = retrieve_tracebackinfo (abfd, textsec, cs); else if (cs->c_nsyms != 2) abort (); /* If there is traceback info, create and add parameters for it. */ if (ptb && (ptb->fixedparms || ptb->floatparms)) { int parmcnt = ptb->fixedparms + ptb->floatparms; char *parmcode = (char*) &ptb->parminfo; int parmvalue = ptb->framesize + 0x18; /* sizeof(LINK AREA) == 0x18 */ unsigned int ii, mask; for (ii=0, mask = 0x80000000; ii <parmcnt; ++ii) { struct symbol *parm; if (ptb->parminfo & mask) { /* float or double */ mask = mask >> 1; if (ptb->parminfo & mask) { /* double parm */ ADD_PARM_TO_PENDING (parm, parmvalue, builtin_type_double, local_symbols); parmvalue += sizeof (double); } else { /* float parm */ ADD_PARM_TO_PENDING (parm, parmvalue, builtin_type_float, local_symbols); parmvalue += sizeof (float); } } else { /* fixed parm, use (int*) for hex rep. */ ADD_PARM_TO_PENDING (parm, parmvalue, lookup_pointer_type (builtin_type_int), local_symbols); parmvalue += sizeof (int); } mask = mask >> 1; } /* Fake this as a function. Needed in process_xcoff_symbol() */ cs->c_type = 32; finish_block(process_xcoff_symbol (cs, objfile), &local_symbols, pending_blocks, cs->c_value, cs->c_value + ptb->fsize, objfile); } continue; } /* shared library function trampoline code entry point. */ else if (CSECT_SCLAS (main_aux) == XMC_GL) { /* record trampoline code entries as mst_unknown symbol. When we lookup mst symbols, we will choose mst_text over mst_unknown. */#if 1 /* After the implementation of incremental loading of shared libraries, we don't want to access trampoline entries. This approach has a consequence of the necessity to bring the whole shared library at first, in order do anything with it (putting breakpoints, using malloc, etc). On the other side, this is consistient with gdb's behaviour on a SUN platform. */ /* Trying to prefer *real* function entry over its trampoline, by assigning `mst_unknown' type to trampoline entries fails. Gdb treats those entries as chars. FIXME. */ /* Recording this entry is necessary. Single stepping relies on this vector to get an idea about function address boundaries. */ prim_record_minimal_symbol (0, cs->c_value, mst_unknown);#else /* record trampoline code entries as mst_unknown symbol. When we lookup mst symbols, we will choose mst_text over mst_unknown. */ RECORD_MINIMAL_SYMBOL (cs->c_name, cs->c_value, mst_unknown, symname_alloced);#endif continue; } break; default : /* all other XTY_XXXs */ break; } /* switch CSECT_SMTYP() */ } switch (cs->c_sclass) { case C_FILE: /* see if the last csect needs to be recorded. */ if (last_csect_name && !misc_func_recorded) { /* if no misc. function recorded in the last seen csect, enter it as a function. This will take care of functions like strcmp() compiled by xlc. */ int alloced = 0; RECORD_MINIMAL_SYMBOL (last_csect_name, last_csect_val, mst_text, alloced); } /* 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; /* complete symbol table for last object file containing debugging information. */ /* Whether or not there was a csect in the previous file, we have to call `end_stabs' and `start_stabs' to reset type_vector, line_vector, etc. structures. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -