#include "defs.h"
#include "bfd.h"
-/* AIX XCOFF names have a preceeding dot `.' */
-#define NAMES_HAVE_DOT 1
-
#include <sys/types.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/debug.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 */
+
#include "symtab.h"
#include "gdbtypes.h"
#include "symfile.h"
#include "objfiles.h"
#include "buildsym.h"
#include "stabsread.h"
-#include "gdb-stabs.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 */
struct coff_symbol {
char *c_name;
int c_symnum; /* symbol number of this entry */
- int c_nsyms; /* 0 if syment only, 1 if syment + auxent */
+ int c_naux; /* 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;
};
static void
xcoff_new_init PARAMS ((struct objfile *));
-#ifdef __STDC__
-struct section_offset;
-#endif
-
static void
-xcoff_symfile_read PARAMS ((struct objfile *, struct section_offset *, int));
+xcoff_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
static void
xcoff_symfile_finish PARAMS ((struct objfile *));
static int
init_lineno PARAMS ((bfd *, file_ptr, int));
+static void
+free_linetab PARAMS ((void));
+
static void
find_linenos PARAMS ((bfd *, sec_ptr, PTR));
+static void
+read_symbol PARAMS ((struct internal_syment *, int));
+
static int
read_symbol_lineno PARAMS ((int));
static void
add_stab_to_list PARAMS ((char *, struct pending_stabs **));
-static void
-sort_syms PARAMS ((void));
-
-static int
-compare_symbols PARAMS ((const void *, const void *));
-
-/* Call sort_syms to sort alphabetically
- the symbols of each block of each symtab. */
-
-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));
-}
-
-
-/* Sort a vector of symbols by their value. */
-
-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);
- }
- }
- }
- }
-}
-
-
/* add a given stab string into given stab vector. */
static void
}
(*stabvector)->stab [(*stabvector)->count++] = stabname;
}
+\f
+/* 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;
+ 2) aix symbol table might look like:
- /* 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;
-
- if (*(pp-1) == 'F' || *(pp-1) == 'f')
- SYMBOL_TYPE (sym) = lookup_function_type (read_type (&pp, objfile));
- 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;
}
/* 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)
record_include_begin (cs)
struct coff_symbol *cs;
{
- /* In xcoff, we assume include files cannot be nested (not in .c files
- of course, but in corresponding .s files.) */
-
if (inclDepth)
- fatal ("xcoff 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;
}
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;
InclTable *pTbl;
if (inclDepth == 0)
- fatal ("xcoff 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;
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)
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. */
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
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. */
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;
}
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;
}
/* 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, OBJFILE) \
{ \
char *namestr; \
if (ALLOCED) \
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), (OBJFILE)); \
misc_func_recorded = 1; \
}
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;
+/* Next symbol to read. Pointer into raw seething symbol table. */
+
+static char *raw_symbol;
+
+/* This is the function which stabsread.c calls to get symbol
+ continuations. */
+static char *
+xcoff_next_symbol_text ()
+{
+ struct internal_syment symbol;
+ static struct complaint msg =
+ {"Unexpected symbol continuation", 0, 0};
+ char *retval;
+
+ bfd_coff_swap_sym_in (current_objfile->obfd, raw_symbol, &symbol);
+ if (symbol.n_zeroes)
+ {
+ complain (&msg);
+
+ /* Return something which points to '\0' and hope the symbol reading
+ code does something reasonable. */
+ retval = "";
+ }
+ else if (symbol.n_sclass & 0x80)
+ {
+ retval = debugsec + symbol.n_offset;
+ raw_symbol += coff_data (current_objfile->obfd)->local_symesz;
+ ++symnum;
+ }
+ else
+ {
+ complain (&msg);
+
+ /* Return something which points to '\0' and hope the symbol reading
+ code does something reasonable. */
+ retval = "";
+ }
+ return retval;
+}
+
/* read the whole symbol table of a given bfd. */
static void
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];
+ union internal_auxent main_aux;
struct coff_symbol cs[1];
CORE_ADDR file_start_addr = 0;
CORE_ADDR file_end_addr = 0;
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;
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");
}
+ next_symbol_text_func = xcoff_next_symbol_text;
+
while (symnum < nsyms) {
QUIT; /* make this command interruptable. */
bfd_coff_swap_sym_in (abfd, raw_symbol, symbol);
cs->c_symnum = symnum;
- cs->c_nsyms = symbol->n_numaux;
+ cs->c_naux = 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;
+ /* 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;
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>.
- 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;
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 ();
}
/* 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);
+ 0, cs->c_naux, &main_aux);
goto function_entry_point;
}
- if ((cs->c_sclass == C_EXT || cs->c_sclass == C_HIDEXT) && cs->c_nsyms == 1)
+ if ((cs->c_sclass == C_EXT || cs->c_sclass == C_HIDEXT) && cs->c_naux == 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_LEN(PP) (CSECT(PP).x_scnlen.l)
# 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);
+ 0, cs->c_naux, &main_aux);
- switch (CSECT_SMTYP (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)) {
+ 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! */
+ /* 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) {
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,
+ objfile);
}
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 ((char *)NULL, (char *)NULL, (CORE_ADDR)0);
+ /* 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'. */
if (just_started) {
- first_object_file_end = cs->c_value + CSECT_LEN (main_aux);
+ 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);
+ 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;
+ last_csect_sec = cs->c_secnum;
}
}
misc_func_recorded = 0;
case XTY_LD :
/* a function entry point. */
- if (CSECT_SCLAS (main_aux) == XMC_PR) {
+ if (CSECT_SCLAS (&main_aux) == XMC_PR) {
function_entry_point:
RECORD_MINIMAL_SYMBOL (cs->c_name, cs->c_value, mst_text,
- symname_alloced);
+ symname_alloced, cs->c_secnum, objfile);
- fcn_line_offset = main_aux->x_sym.x_fcnary.x_fcn.x_lnnoptr;
+ 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;
+ fcn_aux_saved = main_aux;
ptb = NULL;
already available for it. Process traceback table for
functions with only one auxent. */
- if (cs->c_nsyms == 1)
+ if (cs->c_naux == 1)
ptb = retrieve_tracebackinfo (abfd, textsec, cs);
- else if (cs->c_nsyms != 2)
- abort ();
+ else if (cs->c_naux != 2)
+ {
+ static struct complaint msg =
+ {"Expected one or two auxents for function", 0, 0};
+ complain (&msg);
+ }
/* If there is traceback info, create and add parameters for it. */
continue;
}
/* shared library function trampoline code entry point. */
- else if (CSECT_SCLAS (main_aux) == XMC_GL) {
+ 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. */
+ /* record trampoline code entries as mst_solib_trampoline symbol.
+ When we lookup mst symbols, we will choose mst_text over
+ mst_solib_trampoline. */
#if 1
/* After the implementation of incremental loading of shared
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. */
+ by assigning `mst_solib_trampoline' 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 ("<trampoline>", cs->c_value,
- mst_unknown);
+ prim_record_minimal_symbol_and_info
+ ("<trampoline>", cs->c_value, mst_solib_trampoline,
+ (char *)NULL, cs->c_secnum, objfile);
#else
- /* record trampoline code entries as mst_unknown symbol. When we
- lookup mst symbols, we will choose mst_text over mst_unknown. */
+ /* record trampoline code entries as mst_solib_trampoline symbol.
+ When we lookup mst symbols, we will choose mst_text over
+ mst_solib_trampoline. */
- RECORD_MINIMAL_SYMBOL (cs->c_name, cs->c_value, mst_unknown,
- symname_alloced);
+ RECORD_MINIMAL_SYMBOL (cs->c_name, cs->c_value,
+ mst_solib_trampoline,
+ symname_alloced, objfile);
#endif
continue;
}
- break;
+ continue;
default : /* all other XTY_XXXs */
break;
int alloced = 0;
RECORD_MINIMAL_SYMBOL (last_csect_name, last_csect_val,
- mst_text, alloced);
+ mst_text, alloced, last_csect_sec, objfile);
}
/* c_value field contains symnum of next .file entry in table
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 ();
+
+ /* XCOFF, according to the AIX 3.2 documentation, puts the filename
+ in cs->c_name. But xlc 1.3.0.2 has decided to do things the
+ standard COFF way and put it in the auxent. We use the auxent if
+ there is one, otherwise use the name. Simple enough. */
+ if (cs->c_naux > 0)
+ filestring = coff_getfilename (&main_aux);
+ else
+ filestring = cs->c_name;
+
start_stabs ();
- start_symtab (cs->c_name, (char *)NULL, (CORE_ADDR)0);
+ start_symtab (filestring, (char *)NULL, (CORE_ADDR)0);
last_csect_name = 0;
/* reset file start and end addresses. A compilation unit with no text
(only data) should have zero file boundaries. */
file_start_addr = file_end_addr = 0;
-
- filestring = cs->c_name;
break;
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;
if (STREQ (cs->c_name, ".bf")) {
bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
- main_aux);
+ 0, cs->c_naux, &main_aux);
within_function = 1;
- /* Linenos are now processed on a file-by-file, not fn-by-fn, 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_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 (STREQ (cs->c_name, ".ef")) {
bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
- main_aux);
+ 0, cs->c_naux, &main_aux);
/* 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 '}' */
- fcn_last_line = main_aux->x_sym.x_misc.x_lnsz.x_lnno;
+ fcn_last_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno;
new = pop_context ();
if (context_stack_depth != 0)
error ("invalid symbol data; .bf/.ef/.bb/.eb symbol mismatch, at symbol %d.",
break;
case C_BSTAT : /* begin static block */
- static_block_base = read_symbol_nvalue (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. */
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.. */
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 ();
}
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)) {
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, objfile);
-
- /* 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. */
+ /* For xlc (not GCC), the 'V' symbol descriptor is used for all
+ statics and we need to distinguish file-scope versus function-scope
+ using within_function. We do this by changing the string we pass
+ to define_symbol to use 'S' where we need to, which is not necessarily
+ super-clean, but seems workable enough. */
- if (*name == ':' || (pp = (char *) index (name, ':')) == NULL)
- return 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;
- return sym;
-#endif
+ ++pp;
+ if (*pp == 'V' && !within_function)
+ *pp = 'S';
+ sym = define_symbol (cs->c_value, cs->c_name, 0, 0, objfile);
+ if (sym != NULL)
+ {
+ SYMBOL_VALUE (sym) += static_block_base;
+ SYMBOL_SECTION (sym) = static_block_section;
+ }
+ return sym;
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;
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;
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:
pp = (char*) strchr (name, ':');
-#ifdef NO_DEFINE_SYMBOL
- 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 {
complain (&rsym_complaint, name);
return NULL;
}
-#endif
-
- default :
- complain (&storclass_complaint, cs->c_sclass);
- return NULL;
}
}
return sym2;
}
-/* Get value corresponding to symbol number symno in symtbl. */
-
-static int
-read_symbol_nvalue (symno)
+/* Set *SYMBOL to symbol number symno in symtbl. */
+static void
+read_symbol (symbol, symno)
+ struct internal_syment *symbol;
int symno;
{
- struct internal_syment symbol[1];
-
if (symno < 0 || symno >= symtbl_num_syms)
{
- struct complaint msg =
+ static struct complaint msg =
{"Invalid symbol offset", 0, 0};
complain (&msg);
- return 0;
+ 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 (symno)
+ int symno;
+{
+ struct internal_syment symbol[1];
+
+ read_symbol (symbol, symno);
return symbol->n_value;
}
/* take aux entry and return its lineno */
symno++;
bfd_coff_swap_aux_in (symfile_bfd, symtbl+(symno*local_symesz),
- symbol->n_type, symbol->n_sclass, main_aux);
+ symbol->n_type, symbol->n_sclass,
+ 0, symbol->n_numaux, main_aux);
return main_aux->x_sym.x_misc.x_lnsz.x_lnno;
}
{
int val;
+ free_linetab ();
+
if (bfd_seek(abfd, offset, L_SET) < 0)
return -1;
linetab_offset = offset;
linetab_size = size;
- make_cleanup (free, linetab); /* Be sure it gets de-allocated. */
return 0;
}
-\f
-/* 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 xcoff. */
-
-#undef next_symbol_text
-#define next_symbol_text() \
- printf ("Gdb Error: symbol names on multiple lines not implemented.\n")
-
+static void
+free_linetab ()
+{
+ if (linetab)
+ free (linetab);
+ linetab = NULL;
+}
+\f
static void
xcoff_new_init (objfile)
struct objfile *objfile;
if (strtbl == NULL)
return -1;
- bcopy(&length, strtbl, sizeof length);
+ memcpy(strtbl, &length, sizeof length);
if (length == sizeof length)
return 0;
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;
static void
xcoff_symfile_read (objfile, section_offset, mainline)
struct objfile *objfile;
- struct section_offset *section_offset;
+ struct section_offsets *section_offset;
int mainline;
{
int num_symbols; /* # of symbols */
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;
&& 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,
(int) (info->max_lineno_offset - info->min_lineno_offset));
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.
- Plain and simple for now. */
+/* 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 *
{
struct section_offsets *section_offsets;
int i;
-
- section_offsets = (struct section_offsets *)
- obstack_alloc (&objfile -> psymbol_obstack,
- sizeof (struct section_offsets) +
- sizeof (section_offsets->offsets) * (SECT_OFF_MAX-1));
- for (i = 0; i < SECT_OFF_MAX; i++)
- ANOFFSET (section_offsets, i) = addr;
+ 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 xcoff BFD files. */
+
+/* Register our ability to parse symbols for xcoff BFD files. */
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 */
+
+ /* 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 */