X-Git-Url: https://repo.jachan.dev/binutils.git/blobdiff_plain/4ed3a9ea66ca93b7dea29c5cdc23d80e77e442bb..28f851f93a24640360f41dc544d346d33428336c:/gdb/xcoffread.c diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c index 429fcc510b..2ce0ce40e2 100644 --- a/gdb/xcoffread.c +++ b/gdb/xcoffread.c @@ -1,5 +1,6 @@ -/* Read AIXcoff symbol tables and convert to internal format, for GDB. - Copyright (C) 1986-1991 Free Software Foundation, Inc. +/* Read AIX xcoff symbol tables and convert to internal format, for GDB. + Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993 + Free Software Foundation, Inc. Derived from coffread.c, dbxread.c, and a lot of hacking. Contributed by IBM Corporation. @@ -19,15 +20,15 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* Native only: Need struct tbtable in from host, and + need xcoff_add_toc_to_loadinfo in rs6000-tdep.c from target. + need xcoff_init_loadinfo ditto. + However, if you grab and make it available on your + host, and define FAKING_RS6000, then this code will compile. */ + #include "defs.h" #include "bfd.h" -#ifdef IBM6000_HOST -/* Native only: Need struct tbtable in . */ - -/* AIX COFF names have a preceeding dot `.' */ -#define NAMES_HAVE_DOT 1 - #include #include #include @@ -45,23 +46,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "symfile.h" #include "objfiles.h" #include "buildsym.h" +#include "stabsread.h" +#include "complaints.h" #include "coff/internal.h" /* FIXME, internal data from BFD */ #include "libcoff.h" /* FIXME, internal data from BFD */ #include "coff/rs6000.h" /* FIXME, raw file-format guts of xcoff */ - -/* Define this if you want gdb use the old xcoff symbol processing. This - way it won't use common `define_symbol()' function and Sun dbx stab - string grammar. And likely it won't be able to do G++ debugging. */ - -/* #define NO_DEFINE_SYMBOL 1 */ - -/* Define this if you want gdb to ignore typdef stabs. This was needed for - one of Transarc, to reduce the size of the symbol table. Types won't be - recognized, but tag names will be. */ - -/* #define NO_TYPEDEFS 1 */ +/* For interface with stabsread.c. */ +#include "aout/stab_gnu.h" /* Simplified internal version of coff symbol table information */ @@ -70,7 +63,7 @@ struct coff_symbol { int c_symnum; /* symbol number of this entry */ int c_nsyms; /* 0 if syment only, 1 if syment + auxent */ long c_value; - int c_sclass; + unsigned char c_sclass; int c_secnum; unsigned int c_type; }; @@ -109,13 +102,13 @@ static char *debugsec; /* pointer to the a.out symbol table */ static char *symtbl; +/* Number of symbols in symtbl. */ +static int symtbl_num_syms; + /* initial symbol-table-debug-string vector length */ #define INITIAL_STABVECTOR_LENGTH 40 -struct pending_stabs *global_stabs; - - /* Nonzero if within a function (so symbols should be local, if nothing says specifically). */ @@ -142,25 +135,19 @@ static unsigned local_n_tmask; static unsigned local_symesz; - -/* coff_symfile_init() - is the coff-specific initialization routine for reading symbols. - It is passed a struct sym_fns which contains, among other things, - the BFD for the file whose symbols are being read, and a slot for - a pointer to "private data" which we fill with cookies and other - treats for coff_symfile_read(). - - We will only be called if this is a COFF or COFF-like file. - BFD handles figuring out the format of the file, and code in symtab.c - uses BFD's determination to vector to us. - - The ultimate result is a new symtab (or, FIXME, eventually a psymtab). */ - struct coff_symfile_info { file_ptr min_lineno_offset; /* Where in file lowest line#s are */ file_ptr max_lineno_offset; /* 1+last byte of line#s in file */ }; +static struct complaint rsym_complaint = + {"Non-stab C_RSYM `%s' needs special handling", 0, 0}; + +static struct complaint storclass_complaint = + {"Unexpected storage class: %d", 0, 0}; + +static struct complaint bf_notfound_complaint = + {"line numbers off, `.bf' symbol not found", 0, 0}; static void enter_line_range PARAMS ((struct subfile *, unsigned, unsigned, @@ -173,98 +160,53 @@ static int init_debugsection PARAMS ((bfd *)); static int -init_stringtab PARAMS ((bfd *, long, struct objfile *)); +init_stringtab PARAMS ((bfd *, file_ptr, struct objfile *)); static void -aixcoff_symfile_init PARAMS ((struct objfile *)); +xcoff_symfile_init PARAMS ((struct objfile *)); static void -aixcoff_new_init PARAMS ((struct objfile *)); +xcoff_new_init PARAMS ((struct objfile *)); -static void -aixcoff_symfile_read PARAMS ((struct objfile *, CORE_ADDR, int)); +#ifdef __STDC__ +struct section_offset; +#endif static void -aixcoff_symfile_finish PARAMS ((struct objfile *)); - -static int -init_lineno PARAMS ((bfd *, long, int)); +xcoff_symfile_read PARAMS ((struct objfile *, struct section_offset *, int)); static void -find_linenos PARAMS ((bfd *, sec_ptr, PTR)); +xcoff_symfile_finish PARAMS ((struct objfile *)); -static int -read_symbol_lineno PARAMS ((char *, int)); +static struct section_offsets * +xcoff_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR)); static int -read_symbol_nvalue PARAMS ((char *, int)); - -static struct symbol * -process_xcoff_symbol PARAMS ((struct coff_symbol *, struct objfile *)); +init_lineno PARAMS ((bfd *, file_ptr, int)); static void -read_xcoff_symtab PARAMS ((struct objfile *, int)); +free_linetab PARAMS ((void)); static void -add_stab_to_list PARAMS ((char *, struct pending_stabs **)); +find_linenos PARAMS ((bfd *, sec_ptr, PTR)); static void -sort_syms PARAMS ((void)); +read_symbol PARAMS ((struct internal_syment *, int)); static int -compare_symbols PARAMS ((const void *, const void *)); - -/* Call sort_syms to sort alphabetically - the symbols of each block of each symtab. */ +read_symbol_lineno PARAMS ((int)); static int -compare_symbols (s1p, s2p) - const PTR s1p; - const PTR s2p; -{ - /* Names that are less should come first. */ - register struct symbol **s1 = (struct symbol **) s1p; - register struct symbol **s2 = (struct symbol **) s2p; - register int namediff = strcmp (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2)); - if (namediff != 0) - return namediff; - - /* For symbols of the same name, registers should come first. */ - return ((SYMBOL_CLASS (*s2) == LOC_REGISTER) - - (SYMBOL_CLASS (*s1) == LOC_REGISTER)); -} +read_symbol_nvalue PARAMS ((int)); - -/* Sort a vector of symbols by their value. */ +static struct symbol * +process_xcoff_symbol PARAMS ((struct coff_symbol *, struct objfile *)); static void -sort_syms () -{ - register struct symtab *s; - register struct objfile *objfile; - register int i, nbl; - register struct blockvector *bv; - register struct block *b; - - for (objfile = object_files; objfile != NULL; objfile = objfile -> next) - { - for (s = objfile -> symtabs; s != NULL; s = s -> next) - { - bv = BLOCKVECTOR (s); - nbl = BLOCKVECTOR_NBLOCKS (bv); - for (i = 0; i < nbl; i++) - { - b = BLOCKVECTOR_BLOCK (bv, i); - if (BLOCK_SHOULD_SORT (b)) - { - qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b), - sizeof (struct symbol *), compare_symbols); - } - } - } - } -} +read_xcoff_symtab PARAMS ((struct objfile *, int)); +static void +add_stab_to_list PARAMS ((char *, struct pending_stabs **)); /* add a given stab string into given stab vector. */ @@ -288,54 +230,64 @@ struct pending_stabs **stabvector; } (*stabvector)->stab [(*stabvector)->count++] = stabname; } + +/* Linenos are processed on a file-by-file basis. + + Two reasons: + + 1) xlc (IBM's native c compiler) postpones static function code + emission to the end of a compilation unit. This way it can + determine if those functions (statics) are needed or not, and + can do some garbage collection (I think). This makes line + numbers and corresponding addresses unordered, and we end up + with a line table like: + + + lineno addr + foo() 10 0x100 + 20 0x200 + 30 0x300 + + foo3() 70 0x400 + 80 0x500 + 90 0x600 + + static foo2() + 40 0x700 + 50 0x800 + 60 0x900 + + and that breaks gdb's binary search on line numbers, if the + above table is not sorted on line numbers. And that sort + should be on function based, since gcc can emit line numbers + like: + + 10 0x100 - for the init/test part of a for stmt. + 20 0x200 + 30 0x300 + 10 0x400 - for the increment part of a for stmt. + arrange_linetable() will do this sorting. -#if 0 -/* for all the stabs in a given stab vector, build appropriate types - and fix their symbols in given symbol vector. */ - -void -patch_block_stabs (symbols, stabs) -struct pending *symbols; -struct pending_stabs *stabs; -{ - int ii; - - if (!stabs) - return; - - /* for all the stab entries, find their corresponding symbols and - patch their types! */ - - for (ii=0; ii < stabs->count; ++ii) { - char *name = stabs->stab[ii]; - char *pp = (char*) index (name, ':'); - struct symbol *sym = find_symbol_in_list (symbols, name, pp-name); - if (!sym) { - ; - /* printf ("ERROR! stab symbol not found!\n"); */ /* FIXME */ - /* The above is a false alarm. There are cases the we can have - a stab, without its symbol. xlc generates this for the extern - definitions in inner blocks. */ - } - else { - pp += 2; + 2) aix symbol table might look like: - if (*(pp-1) == 'F' || *(pp-1) == 'f') - SYMBOL_TYPE (sym) = lookup_function_type (read_type (&pp)); - else - SYMBOL_TYPE (sym) = read_type (&pp, objfile); - } - } -} -#endif + c_file // beginning of a new file + .bi // beginning of include file + .ei // end of include file + .bi + .ei + basically, .bi/.ei pairs do not necessarily encapsulate + their scope. They need to be recorded, and processed later + on when we come the end of the compilation unit. + Include table (inclTable) and process_linenos() handle + that. */ /* compare line table entry addresses. */ - static int +static int compare_lte (lte1, lte2) - struct linetable_entry *lte1, *lte2; + struct linetable_entry *lte1, *lte2; { return lte1->pc - lte2->pc; } @@ -343,6 +295,8 @@ compare_lte (lte1, lte2) /* Give a line table with function entries are marked, arrange its functions in assending order and strip off function entry markers and return it in a newly created table. If the old one is good enough, return the old one. */ +/* FIXME: I think all this stuff can be replaced by just passing + sort_linevec = 1 to end_symtab. */ static struct linetable * arrange_linetable (oldLineTb) @@ -360,7 +314,7 @@ arrange_linetable (oldLineTb) fentry_size = NUM_OF_FUNCTIONS; fentry = (struct linetable_entry*) - malloc (fentry_size * sizeof (struct linetable_entry)); + xmalloc (fentry_size * sizeof (struct linetable_entry)); for (function_count=0, ii=0; ii nitems; ++ii) { @@ -369,7 +323,7 @@ arrange_linetable (oldLineTb) if (function_count >= fentry_size) { /* make sure you have room. */ fentry_size *= 2; fentry = (struct linetable_entry*) - realloc (fentry, fentry_size * sizeof (struct linetable_entry)); + xrealloc (fentry, fentry_size * sizeof (struct linetable_entry)); } fentry[function_count].line = ii; fentry[function_count].pc = oldLineTb->item[ii].pc; @@ -385,8 +339,10 @@ arrange_linetable (oldLineTb) qsort (fentry, function_count, sizeof(struct linetable_entry), compare_lte); /* allocate a new line table. */ - newLineTb = (struct linetable*) malloc (sizeof (struct linetable) + - (oldLineTb->nitems - function_count) * sizeof (struct linetable_entry)); + newLineTb = (struct linetable *) + xmalloc + (sizeof (struct linetable) + + (oldLineTb->nitems - function_count) * sizeof (struct linetable_entry)); /* if line table does not start with a function beginning, copy up until a function begin. */ @@ -433,7 +389,11 @@ static unsigned first_fun_bf; typedef struct _inclTable { char *name; /* include filename */ - int begin, end; /* offsets to the line table */ + + /* Offsets to the line table. end points to the last entry which is + part of this include file. */ + int begin, end; + struct subfile *subfile; unsigned funStartLine; /* start line # of its function */ } InclTable; @@ -449,19 +409,24 @@ static void record_include_begin (cs) struct coff_symbol *cs; { - /* In aixcoff, we assume include files cannot be nested (not in .c files - of course, but in corresponding .s files.) */ - if (inclDepth) - fatal ("aix internal: pending include file exists."); - + { + /* In xcoff, we assume include files cannot be nested (not in .c files + of course, but in corresponding .s files.). */ + + /* This can happen with old versions of GCC. + GCC 2.3.3-930426 does not exhibit this on a test case which + a user said produced the message for him. */ + static struct complaint msg = {"Nested C_BINCL symbols", 0, 0}; + complain (&msg); + } ++inclDepth; /* allocate an include file, or make room for the new entry */ if (inclLength == 0) { inclTable = (InclTable*) xmalloc (sizeof (InclTable) * INITIAL_INCLUDE_TABLE_LENGTH); - bzero (inclTable, sizeof (InclTable) * INITIAL_INCLUDE_TABLE_LENGTH); + memset (inclTable, '\0', sizeof (InclTable) * INITIAL_INCLUDE_TABLE_LENGTH); inclLength = INITIAL_INCLUDE_TABLE_LENGTH; inclIndx = 0; } @@ -469,8 +434,8 @@ struct coff_symbol *cs; inclLength += INITIAL_INCLUDE_TABLE_LENGTH; inclTable = (InclTable*) xrealloc (inclTable, sizeof (InclTable) * inclLength); - bzero (inclTable+inclLength-INITIAL_INCLUDE_TABLE_LENGTH, - sizeof (InclTable)*INITIAL_INCLUDE_TABLE_LENGTH); + memset (inclTable+inclLength-INITIAL_INCLUDE_TABLE_LENGTH, + '\0', sizeof (InclTable)*INITIAL_INCLUDE_TABLE_LENGTH); } inclTable [inclIndx].name = cs->c_name; @@ -485,7 +450,10 @@ struct coff_symbol *cs; InclTable *pTbl; if (inclDepth == 0) - fatal ("aix internal: Mismatch C_BINCL/C_EINCL pair found."); + { + static struct complaint msg = {"Mismatched C_BINCL/C_EINCL pair", 0, 0}; + complain (&msg); + } pTbl = &inclTable [inclIndx]; pTbl->end = cs->c_value; @@ -522,7 +490,7 @@ process_linenos (start, end) if (!(offset = first_fun_line_offset)) goto return_after_cleanup; - bzero (&main_subfile, sizeof (main_subfile)); + memset (&main_subfile, '\0', sizeof (main_subfile)); first_fun_line_offset = 0; if (inclIndx == 0) @@ -551,7 +519,7 @@ process_linenos (start, end) tmpSubfile = inclTable[ii].subfile = (struct subfile*) xmalloc (sizeof (struct subfile)); - bzero (tmpSubfile, sizeof (struct subfile)); + memset (tmpSubfile, '\0', sizeof (struct subfile)); firstLine = &(inclTable[ii].funStartLine); /* enter include file's lines now. */ @@ -625,9 +593,8 @@ process_linenos (start, end) /* start_subfile (inclTable[ii].name, (char*)0); */ start_subfile (" ?", (char*)0); - current_subfile->name = - obsavestring (inclTable[ii].name, strlen (inclTable[ii].name), - ¤t_objfile->symbol_obstack); + free (current_subfile->name); + current_subfile->name = strdup (inclTable[ii].name); if (lv == lineTb) { current_subfile->line_vector = (struct linetable *) @@ -652,7 +619,7 @@ return_after_cleanup: inclIndx = 0; /* start with a fresh subfile structure for the next file. */ - bzero (&main_subfile, sizeof (struct subfile)); + memset (&main_subfile, '\0', sizeof (struct subfile)); } void @@ -666,7 +633,10 @@ aix_process_linenos () /* Enter a given range of lines into the line vector. can be called in the following two ways: enter_line_range (subfile, beginoffset, endoffset, startaddr, 0, firstLine) or - enter_line_range (subfile, beginoffset, 0, startaddr, endaddr, firstLine) */ + enter_line_range (subfile, beginoffset, 0, startaddr, endaddr, firstLine) + + endoffset points to the last line table entry that we should pay + attention to. */ static void enter_line_range (subfile, beginoffset, endoffset, startaddr, endaddr, firstLine) @@ -684,6 +654,13 @@ enter_line_range (subfile, beginoffset, endoffset, startaddr, endaddr, firstLine #define P_LINESYM(PP) (*(long*)((struct external_lineno*)(PP))->l_addr.l_symndx) pp = &linetab [beginoffset - linetab_offset]; + if (endoffset != 0 && endoffset - linetab_offset >= linetab_size) + { + static struct complaint msg = + {"Bad line table offset in C_EINCL directive", 0, 0}; + complain (&msg); + return; + } limit = endoffset ? &linetab [endoffset - linetab_offset] : &linetab [linetab_size -1]; @@ -691,13 +668,13 @@ enter_line_range (subfile, beginoffset, endoffset, startaddr, endaddr, firstLine /* find the address this line represents */ addr = P_LINENO(pp) ? - P_LINEADDR(pp) : read_symbol_nvalue (symtbl, P_LINESYM(pp)); + P_LINEADDR(pp) : read_symbol_nvalue (P_LINESYM(pp)); - if (addr < startaddr || (endaddr && addr > endaddr)) + if (addr < startaddr || (endaddr && addr >= endaddr)) return; if (P_LINENO(pp) == 0) { - *firstLine = read_symbol_lineno (symtbl, P_LINESYM(pp)); + *firstLine = read_symbol_lineno (P_LINESYM(pp)); record_line (subfile, 0, addr); --(*firstLine); } @@ -728,8 +705,6 @@ retrieve_tracebackinfo (abfd, textsec, cs) struct coff_symbol *cs; { #define TBTABLE_BUFSIZ 2000 -#define MIN_TBTABSIZ 50 /* minimum buffer size to hold a - traceback table. */ static TracebackInfo tbInfo; struct tbtable *ptb; @@ -742,18 +717,21 @@ retrieve_tracebackinfo (abfd, textsec, cs) int functionstart = cs->c_value - textsec->vma; - bzero (&tbInfo, sizeof (tbInfo)); + memset (&tbInfo, '\0', sizeof (tbInfo)); /* keep reading blocks of data from the text section, until finding a zero word and a traceback table. */ - while ( - bufferbytes = ( - (TBTABLE_BUFSIZ < (textsec->_raw_size - functionstart - bytesread)) ? - TBTABLE_BUFSIZ : (textsec->_raw_size - functionstart - bytesread)) - - && bfd_get_section_contents (abfd, textsec, buffer, - (file_ptr)(functionstart + bytesread), bufferbytes)) + /* Note: The logical thing way to write this code would be to assign + to bufferbytes within the while condition. But that triggers a + compiler (xlc in AIX 3.2) bug, so simplify it... */ + bufferbytes = + (TBTABLE_BUFSIZ < (textsec->_raw_size - functionstart - bytesread) ? + TBTABLE_BUFSIZ : (textsec->_raw_size - functionstart - bytesread)); + while (bufferbytes + && (bfd_get_section_contents + (abfd, textsec, buffer, + (file_ptr)(functionstart + bytesread), bufferbytes))) { bytesread += bufferbytes; pinsn = (int*) buffer; @@ -792,6 +770,7 @@ retrieve_tracebackinfo (abfd, textsec, cs) if (!tbInfo.framesize) return NULL; + } /* look for a zero word. */ @@ -812,18 +791,26 @@ retrieve_tracebackinfo (abfd, textsec, cs) /* if we don't have the whole traceback table in the buffer, re-read the whole thing. */ + /* This is how much to read to get the traceback table. + 8 bytes of the traceback table are always present, plus we + look at parminfo. */ +#define MIN_TBTABSIZ 12 + if ((char*)pinsn > (buffer + bufferbytes - MIN_TBTABSIZ)) { /* In case if we are *very* close to the end of the text section and cannot read properly from that point on, abort by returning NULL. + + This could happen if the traceback table is only 8 bytes, + but we try to read 12 bytes of it. Handle this case more graciously -- FIXME */ if (!bfd_get_section_contents ( abfd, textsec, buffer, (file_ptr)(functionstart + bytesread - (buffer + bufferbytes - (char*)pinsn)),MIN_TBTABSIZ)) - { printf ("Abnormal return!..\n"); return NULL; } + { printf_unfiltered ("Abnormal return!..\n"); return NULL; } ptb = (struct tbtable *)buffer; } @@ -835,6 +822,9 @@ retrieve_tracebackinfo (abfd, textsec, cs) tbInfo.parminfo = ptb->tb_ext.parminfo; return &tbInfo; } + bufferbytes = + (TBTABLE_BUFSIZ < (textsec->_raw_size - functionstart - bytesread) ? + TBTABLE_BUFSIZ : (textsec->_raw_size - functionstart - bytesread)); } return NULL; } @@ -902,7 +892,7 @@ retrieve_traceback (abfd, textsec, cs, size) abfd, textsec, buffer, (file_ptr)(functionstart + bytesread - (buffer + bufferbytes - pinsn)),MIN_TBTABSIZ)) - /* abort (); */ { printf ("abort!!!\n"); return NULL; } + /* abort (); */ { printf_unfiltered ("abort!!!\n"); return NULL; } return (struct tbtable *)buffer; } @@ -936,7 +926,7 @@ retrieve_traceback (abfd, textsec, cs, size) /* Reading symbol table has to be fast! Keep the followings as macros, rather than functions. */ -#define RECORD_MINIMAL_SYMBOL(NAME, ADDR, TYPE, ALLOCED) \ +#define RECORD_MINIMAL_SYMBOL(NAME, ADDR, TYPE, ALLOCED, SECTION) \ { \ char *namestr; \ if (ALLOCED) \ @@ -946,21 +936,17 @@ retrieve_traceback (abfd, textsec, cs, size) obstack_copy0 (&objfile->symbol_obstack, (NAME) + 1, strlen ((NAME)+1)); \ (ALLOCED) = 1; \ } \ - prim_record_minimal_symbol (namestr, (ADDR), (TYPE)); \ + prim_record_minimal_symbol_and_info (namestr, (ADDR), (TYPE), \ + (char *)NULL, (SECTION)); \ misc_func_recorded = 1; \ } -/* A parameter template, used by ADD_PARM_TO_PENDING. */ +/* A parameter template, used by ADD_PARM_TO_PENDING. It is initialized + in our initializer function at the bottom of the file, to avoid + dependencies on the exact "struct symbol" format. */ -static struct symbol parmsym = { /* default parameter symbol */ - "", /* name */ - VAR_NAMESPACE, /* namespace */ - LOC_ARG, /* class */ - NULL, /* type */ - 0, /* line number */ - 0, /* value */ -}; +static struct symbol parmsym; /* Add a parameter to a given pending symbol list. */ @@ -975,12 +961,16 @@ static struct symbol parmsym = { /* default parameter symbol */ } -/* aixcoff has static blocks marked in `.bs', `.es' pairs. They cannot be +/* 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; +/* Section number for the current static block. */ + +static int static_block_section = -1; + /* true if space for symbol name has been allocated. */ static int symname_alloced = 0; @@ -1025,6 +1015,7 @@ read_xcoff_symtab (objfile, nsyms) char *last_csect_name; /* last seen csect's name and value */ CORE_ADDR last_csect_val; + int last_csect_sec; int misc_func_recorded; /* true if any misc. function */ current_objfile = objfile; @@ -1034,11 +1025,12 @@ read_xcoff_symtab (objfile, nsyms) N_BTSHFT = coff_data (abfd)->local_n_btshft; local_symesz = coff_data (abfd)->local_symesz; - last_source_file = 0; + 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; @@ -1049,6 +1041,7 @@ read_xcoff_symtab (objfile, nsyms) size = coff_data (abfd)->local_symesz * nsyms; symtbl = xmalloc (size); + symtbl_num_syms = nsyms; val = bfd_read (symtbl, size, 1, abfd); if (val != size) @@ -1058,7 +1051,7 @@ read_xcoff_symtab (objfile, nsyms) textsec = bfd_get_section_by_name (abfd, ".text"); if (!textsec) { - printf ("Unable to locate text section!\n"); + printf_unfiltered ("Unable to locate text section!\n"); } while (symnum < nsyms) { @@ -1068,7 +1061,7 @@ read_xcoff_symtab (objfile, nsyms) /* 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 aixcoff will be freed. Thus we can mark symbols with names + section of xcoff will be freed. Thus we can mark symbols with names in string table as `alloced'. */ { int ii; @@ -1084,6 +1077,17 @@ read_xcoff_symtab (objfile, nsyms) 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; + /* If it's exactly E_SYMNMLEN characters long it isn't + '\0'-terminated. */ + if (cs->c_name[E_SYMNMLEN - 1] != '\0') + { + char *p; + p = obstack_alloc (&objfile->symbol_obstack, E_SYMNMLEN + 1); + strncpy (p, cs->c_name, E_SYMNMLEN); + p[E_SYMNMLEN] = '\0'; + cs->c_name = p; + symname_alloced = 1; + } } else if (symbol->n_sclass & 0x80) { cs->c_name = debugsec + symbol->n_offset; symname_alloced = 0; @@ -1092,13 +1096,7 @@ read_xcoff_symtab (objfile, nsyms) 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 . - 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_sclass = symbol->n_sclass; cs->c_secnum = symbol->n_scnum; cs->c_type = (unsigned)symbol->n_type; @@ -1120,8 +1118,12 @@ read_xcoff_symtab (objfile, nsyms) 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_symtab (cur_src_end_addr, 1, 0, objfile, textsec->target_index); + 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 */ @@ -1160,14 +1162,16 @@ read_xcoff_symtab (objfile, nsyms) 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! */ + /* A program csect is seen. We have to allocate one + symbol table for each program csect. Normally gdb + prefers one symtab for each source file. In case + of AIX, one source file might include more than one + [PR] csect, and they don't have to be adjacent in + terms of the space they occupy in memory. Thus, one + single source file might get fragmented in the + memory and gdb's file start and end address + approach does not work! GCC (and I think xlc) seem + to put all the code in the unnamed program csect. */ if (last_csect_name) { @@ -1178,14 +1182,19 @@ read_xcoff_symtab (objfile, nsyms) if (!misc_func_recorded) { int alloced = 0; RECORD_MINIMAL_SYMBOL (last_csect_name, last_csect_val, - mst_text, alloced); + mst_text, alloced, last_csect_sec); } complete_symtab (filestring, file_start_addr); cur_src_end_addr = file_end_addr; - end_symtab (file_end_addr, 1, 0, objfile); - start_symtab ((char *)NULL, (char *)NULL, (CORE_ADDR)0); + end_symtab (file_end_addr, 1, 0, objfile, + textsec->target_index); + end_stabs (); + start_stabs (); + /* Give all csects for this source file the same + name. */ + start_symtab (filestring, (char *)NULL, (CORE_ADDR)0); } /* If this is the very first csect seen, basically `__start'. */ @@ -1200,6 +1209,7 @@ read_xcoff_symtab (objfile, nsyms) if (cs->c_name && cs->c_name[0] == '.') { last_csect_name = cs->c_name; last_csect_val = cs->c_value; + last_csect_sec = cs->c_secnum; } } misc_func_recorded = 0; @@ -1231,7 +1241,7 @@ read_xcoff_symtab (objfile, nsyms) function_entry_point: RECORD_MINIMAL_SYMBOL (cs->c_name, cs->c_value, mst_text, - symname_alloced); + symname_alloced, cs->c_secnum); fcn_line_offset = main_aux->x_sym.x_fcnary.x_fcn.x_lnnoptr; fcn_start_addr = cs->c_value; @@ -1318,7 +1328,9 @@ function_entry_point: /* 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); + prim_record_minimal_symbol_and_info + ("", cs->c_value, mst_unknown, + (char *)NULL, cs->c_secnum); #else /* record trampoline code entries as mst_unknown symbol. When we @@ -1349,7 +1361,7 @@ function_entry_point: int alloced = 0; RECORD_MINIMAL_SYMBOL (last_csect_name, last_csect_val, - mst_text, alloced); + mst_text, alloced, last_csect_sec); } /* c_value field contains symnum of next .file entry in table @@ -1360,13 +1372,15 @@ function_entry_point: /* 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_symtab' and `start_symtab' to reset type_vector, + /* 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. */ complete_symtab (filestring, file_start_addr); cur_src_end_addr = file_end_addr; - end_symtab (file_end_addr, 1, 0, objfile); + end_symtab (file_end_addr, 1, 0, objfile, textsec->target_index); + end_stabs (); + start_stabs (); start_symtab (cs->c_name, (char *)NULL, (CORE_ADDR)0); last_csect_name = 0; @@ -1379,114 +1393,28 @@ function_entry_point: case C_FUN: - -#ifdef NO_DEFINE_SYMBOL - /* For a function stab, just save its type in `fcn_type_saved', and leave - it for the `.bf' processing. */ - { - char *pp = (char*) index (cs->c_name, ':'); - - if (!pp || ( *(pp+1) != 'F' && *(pp+1) != 'f')) - fatal ("Unrecognized stab"); - pp += 2; - - if (fcn_type_saved) - fatal ("Unprocessed function type"); - - fcn_type_saved = lookup_function_type (read_type (&pp, objfile)); - } -#else fcn_stab_saved = *cs; -#endif break; case C_FCN: - if (strcmp (cs->c_name, ".bf") == 0) { + if (STREQ (cs->c_name, ".bf")) { bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass, main_aux); within_function = 1; - /* Linenos are now processed on a file-by-file, not fn-by-fn, basis. - Metin did it, I'm not sure why. FIXME. -- gnu@cygnus.com */ - - /* Two reasons: - - 1) xlc (IBM's native c compiler) postpones static function code - emission to the end of a compilation unit. This way it can - determine if those functions (statics) are needed or not, and - can do some garbage collection (I think). This makes line - numbers and corresponding addresses unordered, and we end up - with a line table like: - - - lineno addr - foo() 10 0x100 - 20 0x200 - 30 0x300 - - foo3() 70 0x400 - 80 0x500 - 90 0x600 - - static foo2() - 40 0x700 - 50 0x800 - 60 0x900 - - and that breaks gdb's binary search on line numbers, if the - above table is not sorted on line numbers. And that sort - should be on function based, since gcc can emit line numbers - like: - - 10 0x100 - for the init/test part of a for stmt. - 20 0x200 - 30 0x300 - 10 0x400 - for the increment part of a for stmt. - - arrange_linenos() will do this sorting. - - - 2) aix symbol table might look like: - - c_file // beginning of a new file - .bi // beginning of include file - .ei // end of include file - .bi - .ei - - basically, .bi/.ei pairs do not necessarily encapsulate - their scope. They need to be recorded, and processed later - on when we come the end of the compilation unit. - Include table (inclTable) and process_linenos() handle - that. - */ mark_first_line (fcn_line_offset, cs->c_symnum); new = push_context (0, fcn_start_addr); -#ifdef NO_DEFINE_SYMBOL - new->name = process_xcoff_symbol (&fcn_cs_saved, objfile); - - /* Between a function symbol and `.bf', there always will be a function - stab. We save function type when processing that stab. */ - - if (fcn_type_saved == NULL) { - printf ("Unknown function type: symbol 0x%x\n", cs->c_symnum); - SYMBOL_TYPE (new->name) = lookup_function_type (builtin_type_int); - } - else { - SYMBOL_TYPE (new->name) = fcn_type_saved; - fcn_type_saved = NULL; - } -#else new->name = define_symbol (fcn_cs_saved.c_value, fcn_stab_saved.c_name, 0, 0, objfile); -#endif + if (new->name != NULL) + SYMBOL_SECTION (new->name) = cs->c_secnum; } - else if (strcmp (cs->c_name, ".ef") == 0) { + else if (STREQ (cs->c_name, ".ef")) { bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass, main_aux); @@ -1511,11 +1439,18 @@ function_entry_point: break; case C_BSTAT : /* begin static block */ - static_block_base = read_symbol_nvalue (symtbl, cs->c_value); + { + struct internal_syment symbol; + + read_symbol (&symbol, cs->c_value); + static_block_base = symbol.n_value; + static_block_section = symbol.n_scnum; + } break; case C_ESTAT : /* end of static block */ static_block_base = 0; + static_block_section = -1; break; case C_ARG : /* These are not implemented. */ @@ -1524,7 +1459,7 @@ function_entry_point: case C_STRTAG : case C_UNTAG : case C_ENTAG : - printf ("ERROR: Unimplemented storage class: %d.\n", cs->c_sclass); + printf_unfiltered ("ERROR: Unimplemented storage class: %d.\n", cs->c_sclass); break; case C_HIDEXT : /* ignore these.. */ @@ -1548,11 +1483,11 @@ function_entry_point: break; case C_BLOCK : - if (strcmp (cs->c_name, ".bb") == 0) { + if (STREQ (cs->c_name, ".bb")) { depth++; new = push_context (depth, cs->c_value); } - else if (strcmp (cs->c_name, ".eb") == 0) { + else if (STREQ (cs->c_name, ".eb")) { new = pop_context (); if (depth != new->depth) error ("Invalid symbol data: .bb/.eb symbol mismatch at symbol %d.", @@ -1576,7 +1511,10 @@ function_entry_point: } /* while */ if (last_source_file) - end_symtab (cur_src_end_addr, 1, 0, objfile); + { + end_symtab (cur_src_end_addr, 1, 0, objfile, textsec->target_index); + end_stabs (); + } free (symtbl); current_objfile = NULL; @@ -1585,7 +1523,9 @@ function_entry_point: If no XMC_TC0 is found, toc_offset should be zero. Another place to obtain this information would be file auxiliary header. */ +#ifndef FAKING_RS6000 xcoff_add_toc_to_loadinfo (toc_offset); +#endif } #define SYMBOL_DUP(SYMBOL1, SYMBOL2) \ @@ -1617,11 +1557,12 @@ process_xcoff_symbol (cs, objfile) if (name[0] == '.') ++name; - bzero (sym, sizeof (struct symbol)); + memset (sym, '\0', sizeof (struct symbol)); /* default assumptions */ SYMBOL_VALUE (sym) = cs->c_value; SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_SECTION (sym) = cs->c_secnum; if (ISFCN (cs->c_type)) { @@ -1657,185 +1598,67 @@ process_xcoff_symbol (cs, objfile) break; #endif - case C_DECL: /* a type decleration?? */ - -#if defined(NO_TYPEDEFS) || defined(NO_DEFINE_SYMBOL) - qq = (char*) strchr (name, ':'); - if (!qq) /* skip if there is no ':' */ - return NULL; - - nameless = (qq == name); - - struct_and_type_combined = (qq[1] == 'T' && qq[2] == 't'); - pp = qq + (struct_and_type_combined ? 3 : 2); - - - /* To handle GNU C++ typename abbreviation, we need to be able to fill - in a type's name as soon as space for that type is allocated. */ - - if (struct_and_type_combined && name != qq) { - - int typenums[2]; - struct type *tmp_type; - char *tmp_pp = pp; - - read_type_number (&tmp_pp, typenums); - tmp_type = dbx_alloc_type (typenums, objfile); - - if (tmp_type && !TYPE_NAME (tmp_type) && !nameless) - TYPE_NAME (tmp_type) = SYMBOL_NAME (sym) = - obsavestring (name, qq-name, - &objfile->symbol_obstack); - } - ttype = SYMBOL_TYPE (sym) = read_type (&pp); - - /* if there is no name for this typedef, you don't have to keep its - symbol, since nobody could ask for it. Otherwise, build a symbol - and add it into symbol_list. */ - - if (nameless) - return; - -#ifdef NO_TYPEDEFS - /* Transarc wants to eliminate type definitions from the symbol table. - Limited debugging capabilities, but faster symbol table processing - and less memory usage. Note that tag definitions (starting with - 'T') will remain intact. */ - - if (qq[1] != 'T' && (!TYPE_NAME (ttype) || *(TYPE_NAME (ttype)) == '\0')) { - - if (SYMBOL_NAME (sym)) - TYPE_NAME (ttype) = SYMBOL_NAME (sym); - else - TYPE_NAME (ttype) = obsavestring (name, qq-name); - - return; - } - -#endif /* !NO_TYPEDEFS */ - - /* read_type() will return null if type (or tag) definition was - unnnecessarily duplicated. Also, if the symbol doesn't have a name, - there is no need to keep it in symbol table. */ - /* The above argument no longer valid. read_type() never returns NULL. */ - - if (!ttype) - return NULL; - - /* if there is no name for this typedef, you don't have to keep its - symbol, since nobody could ask for it. Otherwise, build a symbol - and add it into symbol_list. */ - - if (qq[1] == 'T') - SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; - else if (qq[1] == 't') - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - else { - warning ("Unrecognized stab string.\n"); - return NULL; - } - - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - if (!SYMBOL_NAME (sym)) - SYMBOL_NAME (sym) = obsavestring (name, qq-name); - - SYMBOL_DUP (sym, sym2); - add_symbol_to_list - (sym2, within_function ? &local_symbols : &file_symbols); - - /* For a combination of struct and type, add one more symbol - for the type. */ - - if (struct_and_type_combined) { - SYMBOL_DUP (sym, sym2); - SYMBOL_NAMESPACE (sym2) = VAR_NAMESPACE; - add_symbol_to_list - (sym2, within_function ? &local_symbols : &file_symbols); - } - - /* assign a name to the type node. */ - - if (!TYPE_NAME (ttype) || *(TYPE_NAME (ttype)) == '\0') { - if (struct_and_type_combined) - TYPE_NAME (ttype) = SYMBOL_NAME (sym); - else if (qq[1] == 'T') /* struct namespace */ - TYPE_NAME (ttype) = concat ( - TYPE_CODE (ttype) == TYPE_CODE_UNION ? "union " : - TYPE_CODE (ttype) == TYPE_CODE_STRUCT? "struct " : "enum ", - SYMBOL_NAME (sym), NULL); - } - break; - -#else /* !NO_DEFINE_SYMBOL */ - return define_symbol (cs->c_value, cs->c_name, 0, 0, objfile); -#endif - case C_GSYM: add_stab_to_list (name, &global_stabs); break; + case C_BCOMM: + common_block_start (cs->c_name, objfile); + break; + + case C_ECOMM: + common_block_end (objfile); + break; + + default: + complain (&storclass_complaint, cs->c_sclass); + /* FALLTHROUGH */ + + case C_DECL: case C_PSYM: case C_RPSYM: + case C_ECOML: -#ifdef NO_DEFINE_SYMBOL - if (*name == ':' || (pp = (char *) strchr (name, ':')) == NULL) - return NULL; - SYMBOL_NAME (sym) = obsavestring (name, pp-name, &objfile -> symbol_obstack); - SYMBOL_CLASS (sym) = (cs->c_sclass == C_PSYM) ? LOC_ARG : LOC_REGPARM; - pp += 2; - SYMBOL_TYPE (sym) = read_type (&pp, objfile); - SYMBOL_DUP (sym, sym2); - add_symbol_to_list (sym2, &local_symbols); - break; -#else - sym = define_symbol (cs->c_value, cs->c_name, 0, 0, objfile); - SYMBOL_CLASS (sym) = (cs->c_sclass == C_PSYM) ? LOC_ARG : LOC_REGPARM; - return sym; -#endif + sym = define_symbol (cs->c_value, cs->c_name, 0, 0, objfile); + if (sym != NULL) + { + SYMBOL_SECTION (sym) = cs->c_secnum; + } + return sym; case C_STSYM: -#ifdef NO_DEFINE_SYMBOL - if (*name == ':' || (pp = (char *) strchr (name, ':')) == NULL) - return NULL; - SYMBOL_NAME (sym) = obsavestring (name, pp-name, &objfile -> symbol_obstack); - SYMBOL_CLASS (sym) = LOC_STATIC; - SYMBOL_VALUE (sym) += static_block_base; - pp += 2; - SYMBOL_TYPE (sym) = read_type (&pp, objfile); - SYMBOL_DUP (sym, sym2); - add_symbol_to_list - (sym2, within_function ? &local_symbols : &file_symbols); - break; -#else /* If we are going to use Sun dbx's define_symbol(), we need to massage our stab string a little. Change 'V' type to 'S' to be comparible with Sun. */ + /* FIXME: Is this to avoid a Sun-specific hack somewhere? + Needs more investigation. */ - if (*name == ':' || (pp = (char *) index (name, ':')) == NULL) + if (*name == ':' || (pp = (char *) strchr(name, ':')) == NULL) return NULL; ++pp; if (*pp == 'V') *pp = 'S'; sym = define_symbol (cs->c_value, cs->c_name, 0, 0, objfile); - SYMBOL_VALUE (sym) += static_block_base; + if (sym != NULL) + { + SYMBOL_VALUE (sym) += static_block_base; + SYMBOL_SECTION (sym) = static_block_section; + } return sym; -#endif case C_LSYM: - if (*name == ':' || (pp = (char *) strchr (name, ':')) == NULL) - return NULL; - SYMBOL_NAME (sym) = obsavestring (name, pp-name, &objfile -> symbol_obstack); - SYMBOL_CLASS (sym) = LOC_LOCAL; - pp += 1; - SYMBOL_TYPE (sym) = read_type (&pp, objfile); - SYMBOL_DUP (sym, sym2); - add_symbol_to_list (sym2, &local_symbols); - break; + sym = define_symbol (cs->c_value, cs->c_name, 0, N_LSYM, objfile); + if (sym != NULL) + { + SYMBOL_SECTION (sym) = cs->c_secnum; + } + return sym; case C_AUTO: SYMBOL_CLASS (sym) = LOC_LOCAL; SYMBOL_NAME (sym) = SYMNAME_ALLOC (name, symname_alloced); + SYMBOL_SECTION (sym) = cs->c_secnum; SYMBOL_DUP (sym, sym2); add_symbol_to_list (sym2, &local_symbols); break; @@ -1843,6 +1666,7 @@ process_xcoff_symbol (cs, objfile) case C_EXT: SYMBOL_CLASS (sym) = LOC_STATIC; SYMBOL_NAME (sym) = SYMNAME_ALLOC (name, symname_alloced); + SYMBOL_SECTION (sym) = cs->c_secnum; SYMBOL_DUP (sym, sym2); add_symbol_to_list (sym2, &global_symbols); break; @@ -1850,99 +1674,106 @@ process_xcoff_symbol (cs, objfile) case C_STAT: SYMBOL_CLASS (sym) = LOC_STATIC; SYMBOL_NAME (sym) = SYMNAME_ALLOC (name, symname_alloced); + SYMBOL_SECTION (sym) = cs->c_secnum; SYMBOL_DUP (sym, sym2); add_symbol_to_list (sym2, within_function ? &local_symbols : &file_symbols); break; case C_REG: - printf ("ERROR! C_REG is not fully implemented!\n"); + printf_unfiltered ("ERROR! C_REG is not fully implemented!\n"); SYMBOL_CLASS (sym) = LOC_REGISTER; SYMBOL_NAME (sym) = SYMNAME_ALLOC (name, symname_alloced); + SYMBOL_SECTION (sym) = cs->c_secnum; SYMBOL_DUP (sym, sym2); add_symbol_to_list (sym2, &local_symbols); break; case C_RSYM: - -#ifdef NO_DEFINE_SYMBOL pp = (char*) strchr (name, ':'); - SYMBOL_CLASS (sym) = LOC_REGISTER; - SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (cs->c_value); - if (pp) { - SYMBOL_NAME (sym) = obsavestring (name, pp-name, &objfile -> symbol_obstack); - pp += 2; - if (*pp) - SYMBOL_TYPE (sym) = read_type (&pp, objfile); - } - else - /* else this is not a stab entry, suppose the type is either - `int' or `float', depending on the register class. */ - - SYMBOL_TYPE (sym) = (SYMBOL_VALUE (sym) < 32) - ? lookup_fundamental_type (objfile, FT_INTEGER) - : lookup_fundamental_type (objfile, FT_FLOAT); - - SYMBOL_DUP (sym, sym2); - add_symbol_to_list (sym2, &local_symbols); - break; -#else if (pp) { sym = define_symbol (cs->c_value, cs->c_name, 0, 0, objfile); + if (sym != NULL) + SYMBOL_SECTION (sym) = cs->c_secnum; return sym; } else { - warning ("A non-stab C_RSYM needs special handling."); + complain (&rsym_complaint, name); return NULL; } -#endif - - default : - warning ("Unexpected storage class: %d.", cs->c_sclass); - return NULL; } } return sym2; } +/* Set *SYMBOL to symbol number symno in symtbl. */ +static void +read_symbol (symbol, symno) + struct internal_syment *symbol; + int symno; +{ + if (symno < 0 || symno >= symtbl_num_syms) + { + static struct complaint msg = + {"Invalid symbol offset", 0, 0}; + complain (&msg); + symbol->n_value = 0; + symbol->n_scnum = -1; + return; + } + bfd_coff_swap_sym_in (symfile_bfd, symtbl + (symno*local_symesz), symbol); +} + +/* Get value corresponding to symbol number symno in symtbl. */ static int -read_symbol_nvalue (symtable, symno) - char *symtable; +read_symbol_nvalue (symno) int symno; { struct internal_syment symbol[1]; - bfd_coff_swap_sym_in (symfile_bfd, symtable + (symno*local_symesz), symbol); + read_symbol (symbol, symno); return symbol->n_value; } +/* Find the address of the function corresponding to symno, where + symno is the symbol pointed to by the linetable. */ + static int -read_symbol_lineno (symtable, symno) - char *symtable; +read_symbol_lineno (symno) int symno; { struct internal_syment symbol[1]; union internal_auxent main_aux[1]; - int ii; + /* Note that just searching for a short distance (e.g. 50 symbols) + is not enough, at least in the following case. - for (ii = 0; ii < 50; ii++) { + .extern foo + [many .stabx entries] + [a few functions, referring to foo] + .globl foo + .bf + + What happens here is that the assembler moves the .stabx entries + to right before the ".bf" for foo, but the symbol for "foo" is before + all the stabx entries. See PR gdb/2222. */ + while (symno < symtbl_num_syms) { bfd_coff_swap_sym_in (symfile_bfd, - symtable + (symno*local_symesz), symbol); - if (symbol->n_sclass == C_FCN && 0 == strcmp (symbol->n_name, ".bf")) + symtbl + (symno*local_symesz), symbol); + if (symbol->n_sclass == C_FCN && STREQ (symbol->n_name, ".bf")) goto gotit; symno += symbol->n_numaux+1; } - printf ("GDB Error: `.bf' not found.\n"); + complain (&bf_notfound_complaint); return 0; gotit: /* take aux entry and return its lineno */ symno++; - bfd_coff_swap_aux_in (symfile_bfd, symtable+(symno*local_symesz), + bfd_coff_swap_aux_in (symfile_bfd, symtbl+(symno*local_symesz), symbol->n_type, symbol->n_sclass, main_aux); return main_aux->x_sym.x_misc.x_lnsz.x_lnno; @@ -1966,7 +1797,7 @@ PTR vpinfo; count = asect->lineno_count; - if (strcmp (asect->name, ".text") || count == 0) + if (!STREQ (asect->name, ".text") || count == 0) return; size = count * coff_data (symfile_bfd)->local_linesz; @@ -1989,12 +1820,14 @@ PTR vpinfo; static int init_lineno (abfd, offset, size) bfd *abfd; - long offset; + file_ptr offset; int size; { int val; - if (bfd_seek(abfd, offset, 0) < 0) + free_linetab (); + + if (bfd_seek(abfd, offset, L_SET) < 0) return -1; linetab = (char *) xmalloc(size); @@ -2005,121 +1838,51 @@ init_lineno (abfd, offset, size) linetab_offset = offset; linetab_size = size; - make_cleanup (free, linetab); /* Be sure it gets de-allocated. */ return 0; } + +static void +free_linetab () +{ + if (linetab) + free (linetab); + linetab = NULL; +} /* dbx allows the text of a symbol name to be continued into the next symbol name! When such a continuation is encountered (a \ at the end of the text of a name) call this function to get the continuation. */ /* So far, I haven't seen this happenning xlc output. I doubt we'll need this - for aixcoff. */ + for xcoff. */ #undef next_symbol_text #define next_symbol_text() \ - printf ("Gdb Error: symbol names on multiple lines not implemented.\n") + printf_unfiltered ("Gdb Error: symbol names on multiple lines not implemented.\n") -/* xlc/dbx combination uses a set of builtin types, starting from -1. return - the proper type node fora given builtin type #. */ - -struct type * -builtin_type (pp) -char **pp; -{ - int typenums[2]; - - if (**pp != '-') { - printf ("ERROR!, unknown built-in type!\n"); - return NULL; - } - *pp += 1; - read_type_number (pp, typenums); - - /* default types are defined in dbxstclass.h. */ - switch ( typenums[1] ) { - case 1: - return lookup_fundamental_type (current_objfile, FT_INTEGER); - case 2: - return lookup_fundamental_type (current_objfile, FT_CHAR); - case 3: - return lookup_fundamental_type (current_objfile, FT_SHORT); - case 4: - return lookup_fundamental_type (current_objfile, FT_LONG); - case 5: - return lookup_fundamental_type (current_objfile, FT_UNSIGNED_CHAR); - case 6: - return lookup_fundamental_type (current_objfile, FT_SIGNED_CHAR); - case 7: - return lookup_fundamental_type (current_objfile, FT_UNSIGNED_SHORT); - case 8: - return lookup_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER); - case 9: - return lookup_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER); - case 10: - return lookup_fundamental_type (current_objfile, FT_UNSIGNED_LONG); - case 11: - return lookup_fundamental_type (current_objfile, FT_VOID); - case 12: - return lookup_fundamental_type (current_objfile, FT_FLOAT); - case 13: - return lookup_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT); - case 14: - return lookup_fundamental_type (current_objfile, FT_EXT_PREC_FLOAT); - case 15: - /* requires a builtin `integer' */ - return lookup_fundamental_type (current_objfile, FT_INTEGER); - case 16: - return lookup_fundamental_type (current_objfile, FT_BOOLEAN); - case 17: - /* requires builtin `short real' */ - return lookup_fundamental_type (current_objfile, FT_FLOAT); - case 18: - /* requires builtin `real' */ - return lookup_fundamental_type (current_objfile, FT_FLOAT); - default : - printf ("ERROR! Unknown builtin type -%d\n", typenums[1]); - return NULL; - } -} - -#if 0 /* Seems to be unused, don't bother converting from old misc function - vector usage to new minimal symbol tables. FIXME: Delete this? */ - -/* if we now nothing about a function but its address, make a function symbol - out of it with the limited knowladge you have. This will be used when - somebody refers to a function, which doesn't exist in the symbol table, - but is in the minimal symbol table. */ - -struct symbol * -build_function_symbol (ind, objfile) - int ind; +static void +xcoff_new_init (objfile) struct objfile *objfile; { - struct symbol *sym = - (struct symbol *) obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); - SYMBOL_NAME (sym) = misc_function_vector[ind].name; - /* SYMBOL_VALUE (sym) = misc_function_vector[ind].address; */ - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - SYMBOL_CLASS (sym) = LOC_BLOCK; - SYMBOL_TYPE (sym) = lookup_function_type (lookup_fundamental_type (current_objfile, FT_INTEGER)); - SYMBOL_BLOCK_VALUE (sym) = (struct block *) - obstack_alloc (&objfile->symbol_obstack, sizeof (struct block)); - BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) = misc_function_vector[ind].address; - return sym; } -#endif -static void -aixcoff_new_init (objfile) - struct objfile *objfile; -{ -} +/* xcoff_symfile_init() + is the xcoff-specific initialization routine for reading symbols. + It is passed an objfile which contains, among other things, + the BFD for the file whose symbols are being read, and a slot for + a pointer to "private data" which we fill with cookies and other + treats for xcoff_symfile_read(). + + We will only be called if this is an XCOFF or XCOFF-like file. + BFD handles figuring out the format of the file, and code in symfile.c + uses BFD's determination to vector to us. + + The ultimate result is a new symtab (or, FIXME, eventually a psymtab). */ static void -aixcoff_symfile_init (objfile) +xcoff_symfile_init (objfile) struct objfile *objfile; { bfd *abfd = objfile->obfd; @@ -2136,7 +1899,7 @@ aixcoff_symfile_init (objfile) objfile struct from the global list of known objfiles. */ static void -aixcoff_symfile_finish (objfile) +xcoff_symfile_finish (objfile) struct objfile *objfile; { if (objfile -> sym_private != NULL) @@ -2158,14 +1921,14 @@ aixcoff_symfile_finish (objfile) static int init_stringtab(abfd, offset, objfile) bfd *abfd; - long offset; + file_ptr offset; struct objfile *objfile; { long length; int val; unsigned char lengthbuf[4]; - if (bfd_seek(abfd, offset, 0) < 0) + if (bfd_seek(abfd, offset, L_SET) < 0) return -1; val = bfd_read((char *)lengthbuf, 1, sizeof lengthbuf, abfd); @@ -2184,7 +1947,7 @@ init_stringtab(abfd, offset, objfile) if (strtbl == NULL) return -1; - bcopy(&length, strtbl, sizeof length); + memcpy(strtbl, &length, sizeof length); if (length == sizeof length) return 0; @@ -2220,7 +1983,7 @@ init_debugsection(abfd) return -1; if (!bfd_get_section_contents(abfd, secp, debugsec, (file_ptr) 0, length)) { - printf ("Can't read .debug section from symbol file\n"); + printf_unfiltered ("Can't read .debug section from symbol file\n"); return -1; } return 0; @@ -2235,21 +1998,22 @@ free_debugsection() } -/* aixcoff version of symbol file read. */ +/* xcoff version of symbol file read. */ static void -aixcoff_symfile_read (objfile, addr, mainline) +xcoff_symfile_read (objfile, section_offset, mainline) struct objfile *objfile; - CORE_ADDR addr; + struct section_offset *section_offset; int mainline; { - int num_symbols; /* # of symbols */ - int symtab_offset; /* symbol table and */ - int stringtab_offset; /* string table file offsets */ + int num_symbols; /* # of symbols */ + file_ptr symtab_offset; /* symbol table and */ + file_ptr stringtab_offset; /* string table file offsets */ int val; bfd *abfd; struct coff_symfile_info *info; char *name; + struct cleanup *back_to = make_cleanup (null_cleanup, 0); info = (struct coff_symfile_info *) objfile -> sym_private; symfile_bfd = abfd = objfile->obfd; @@ -2269,24 +2033,28 @@ aixcoff_symfile_read (objfile, addr, mainline) && info->max_lineno_offset > info->min_lineno_offset) { /* only read in the line # table if one exists */ + make_cleanup (free_linetab, 0); val = init_lineno(abfd, info->min_lineno_offset, - info->max_lineno_offset - info->min_lineno_offset); + (int) (info->max_lineno_offset - info->min_lineno_offset)); if (val < 0) error("\"%s\": error reading line numbers\n", name); } - val = init_stringtab(abfd, stringtab_offset, objfile); - if (val < 0) { - error ("\"%s\": can't get string table", name); - } + if (num_symbols > 0) + { + val = init_stringtab(abfd, stringtab_offset, objfile); + if (val < 0) { + error ("\"%s\": can't get string table", name); + } - if (init_debugsection(abfd) < 0) { - error ("Error reading .debug section of `%s'\n", name); - } + if (init_debugsection(abfd) < 0) { + error ("Error reading .debug section of `%s'\n", name); + } + } /* Position to read the symbol table. Do not read it all at once. */ - val = bfd_seek(abfd, (long)symtab_offset, 0); + val = bfd_seek(abfd, symtab_offset, L_SET); if (val < 0) perror_with_name(name); @@ -2296,9 +2064,11 @@ aixcoff_symfile_read (objfile, addr, mainline) init_minimal_symbol_collection (); make_cleanup (discard_minimal_symbols, 0); +#ifndef FAKING_RS6000 /* Initialize load info structure. */ if (mainline) xcoff_init_loadinfo (); +#endif /* Now that the executable file is positioned at symbol table, process it and define symbols accordingly. */ @@ -2309,41 +2079,98 @@ aixcoff_symfile_read (objfile, addr, mainline) free_debugsection (); /* Sort symbols alphabetically within each block. */ - sort_syms (); + { + struct symtab *s; + for (s = objfile -> symtabs; s != NULL; s = s -> next) + { + sort_symtab_syms (s); + } + } /* Install any minimal symbols that have been collected as the current minimal symbols for this objfile. */ install_minimal_symbols (objfile); - /* Make a default for file to list. */ - select_source_symtab (0); + do_cleanups (back_to); +} + +/* XCOFF-specific parsing routine for section offsets. */ + +static int largest_section; + +static void +note_one_section (abfd, asect, ptr) + bfd *abfd; + asection *asect; + PTR ptr; +{ + if (asect->target_index > largest_section) + largest_section = asect->target_index; +} + +static +struct section_offsets * +xcoff_symfile_offsets (objfile, addr) + struct objfile *objfile; + CORE_ADDR addr; +{ + struct section_offsets *section_offsets; + int i; + + largest_section = 0; + bfd_map_over_sections (objfile->obfd, note_one_section, NULL); + objfile->num_sections = largest_section + 1; + section_offsets = (struct section_offsets *) + obstack_alloc + (&objfile -> psymbol_obstack, + sizeof (struct section_offsets) + + sizeof (section_offsets->offsets) * (objfile->num_sections)); + + /* syms_from_objfile kindly subtracts from addr the bfd_section_vma + of the .text section. This strikes me as wrong--whether the + offset to be applied to symbol reading is relative to the start + address of the section depends on the symbol format. In any + event, this whole "addr" concept is pretty broken (it doesn't + handle any section but .text sensibly), so just ignore the addr + parameter and use 0. That matches the fact that xcoff_symfile_read + ignores the section_offsets). */ + for (i = 0; i < objfile->num_sections; i++) + ANOFFSET (section_offsets, i) = 0; + + return section_offsets; } -/* Register our ability to parse symbols for aixcoff BFD files. */ +/* Register our ability to parse symbols for xcoff BFD files. */ -static struct sym_fns aixcoff_sym_fns = +static struct sym_fns xcoff_sym_fns = { - "aixcoff-rs6000", /* sym_name: name or name prefix of BFD target type */ - 15, /* sym_namelen: number of significant sym_name chars */ - aixcoff_new_init, /* sym_new_init: init anything gbl to entire symtab */ - aixcoff_symfile_init, /* sym_init: read initial info, setup for sym_read() */ - aixcoff_symfile_read, /* sym_read: read a symbol file into symtab */ - aixcoff_symfile_finish, /* sym_finish: finished with file, cleanup */ + + /* Because the bfd uses coff_flavour, we need to specially kludge + the flavour. FIXME: coff and xcoff and fundamentally similar + except for debug format, and we should see if we can merge this + file with coffread.c. For example, the extra storage classes + used for stabs could presumably be recognized in any COFF file. */ + + (enum bfd_flavour)-1, + + xcoff_new_init, /* sym_new_init: init anything gbl to entire symtab */ + xcoff_symfile_init, /* sym_init: read initial info, setup for sym_read() */ + xcoff_symfile_read, /* sym_read: read a symbol file into symtab */ + xcoff_symfile_finish, /* sym_finish: finished with file, cleanup */ + xcoff_symfile_offsets, /* sym_offsets: xlate offsets ext->int form */ NULL /* next: pointer to next struct sym_fns */ }; void _initialize_xcoffread () { - add_symtab_fns(&aixcoff_sym_fns); -} - -#else /* IBM6000_HOST */ -struct type * -builtin_type (ignore) -char **ignore; -{ - fatal ("GDB internal eror: builtin_type called on non-RS/6000!"); + add_symtab_fns(&xcoff_sym_fns); + + /* Initialize symbol template later used for arguments. */ + SYMBOL_NAME (&parmsym) = ""; + SYMBOL_INIT_LANGUAGE_SPECIFIC (&parmsym, language_c); + SYMBOL_NAMESPACE (&parmsym) = VAR_NAMESPACE; + SYMBOL_CLASS (&parmsym) = LOC_ARG; + /* Its other fields are zero, or are filled in later. */ } -#endif /* IBM6000_HOST */