Design and support routines derived from dbxread.c, and UMAX COFF
specific routines written 9/1/87 by David D. Johnson, Brown University.
Revised 11/27/87 ddj@cs.brown.edu
- Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc.
+ Copyright (C) 1987-1991 Free Software Foundation, Inc.
This file is part of GDB.
-GDB is free software; you can redistribute it and/or modify
+This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
-GDB is distributed in the hope that it will be useful,
+This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GDB; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
\f
+#include <stdio.h>
#include "defs.h"
#include "param.h"
-#ifdef COFF_FORMAT
#include "symtab.h"
+#include "breakpoint.h"
+#include "bfd.h"
+#include "symfile.h"
-#ifdef USG
-#include <sys/types.h>
-#include <fcntl.h>
-#endif
-
+#if defined (TDESC)
+/* Need to get C_VERSION and friends. */
#include <a.out.h>
-#include <stdio.h>
+#else /* not TDESC */
+#include <intel-coff.h>
+#endif /* not TDESC */
+
#include <obstack.h>
-#include <sys/param.h>
-#include <sys/file.h>
+#include <string.h>
+
+#include "internalcoff.h" /* Internal format of COFF symbols in BFD */
+#include "libcoff.h" /* FIXME secret internal data from BFD */
static void add_symbol_to_list ();
static void read_coff_symtab ();
static char *getsymname ();
static int init_lineno ();
static void enter_linenos ();
+static void read_one_sym ();
extern int fclose ();
extern void free_all_symtabs ();
extern void free_all_psymtabs ();
+/* To be an sdb debug type, type must have at least a basic or primary
+ derived type. Using this rather than checking against T_NULL is
+ said to prevent core dumps if we try to operate on Michael Bloom
+ dbx-in-coff file. */
+
+#define SDB_TYPE(type) (BTYPE(type) | (type & N_TMASK))
/* Name of source file whose symbol data we are now processing.
This comes from a symbol named ".file". */
static FILE *nlist_stream_global;
static int nlist_nsyms_global;
-/* The file, a.out and text section headers of the symbol file */
+/* The entry point (starting address) of the file, if it is an executable. */
-static FILHDR file_hdr;
-static SCNHDR text_hdr;
-static AOUTHDR aout_hdr;
+static CORE_ADDR entry_point;
/* The index in the symbol table of the last coff symbol that was processed. */
static int line_vector_length;
+#ifdef TDESC
+#include "tdesc.h"
+#define SEM
+int int_sem_val = 's' << 24 | 'e' << 16 | 'm' << 8 | '.';
+int temp_sem_val;
+int last_coffsem = 2;
+#if 0
+ /* This isn't used currently. */
+int last_coffsyn = 0;
+#endif
+int debug_info = 0; /*used by tdesc */
+extern dc_dcontext_t tdesc_handle;
+extern int safe_to_init_tdesc_context;
+#endif
+
/* Chain of typedefs of pointers to empty struct/union types.
- They are chained thru the SYMBOL_VALUE. */
+ They are chained thru the SYMBOL_VALUE_CHAIN. */
#define HASHSIZE 127
static struct symbol *opaque_type_chain[HASHSIZE];
extern CORE_ADDR startup_file_start; /* From blockframe.c */
extern CORE_ADDR startup_file_end; /* From blockframe.c */
-/* File name symbols were loaded from. */
+/* Complaints about various problems in the file being read */
+
+struct complaint ef_complaint =
+ {"Unmatched .ef symbol(s) ignored starting at symnum %d", 0, 0};
+
+struct complaint lineno_complaint =
+ {"Line number pointer %d lower than start of line numbers", 0, 0};
-static char *symfile;
\f
/* Look up a coff type-number index. Return the address of the slot
where the type for that index is stored.
/* Manage the vector of line numbers. */
-static
+static void
record_line (line, pc)
int line;
CORE_ADDR pc;
context_stack = 0;
within_function = 0;
last_source_file = 0;
+#ifdef TDESC
+ last_coffsem = 2;
+#if 0
+ /* This isn't used currently. */
+ last_coffsyn = 0;
+#endif
+#endif
- /* Initialize the source file information for this file. */
+ /* Initialize the source file line number information for this file. */
+ if (line_vector) /* Unlikely, but maybe possible? */
+ free (line_vector);
line_vector_index = 0;
line_vector_length = 1000;
prev_line_number = -2; /* Force first line number to be explicit */
+ line_vector_length * sizeof (struct linetable_entry));
}
-/* Save the vital information for use when closing off the current file.
+/* Save the vital information from when starting to read a file,
+ for use when closing off the current file.
NAME is the file name the symbols came from, START_ADDR is the first
text address for the file, and SIZE is the number of bytes of text. */
cur_src_start_addr = start_addr;
cur_src_end_addr = start_addr + size;
- if (aout_hdr.entry < cur_src_end_addr
- && aout_hdr.entry >= cur_src_start_addr)
+ if (entry_point < cur_src_end_addr
+ && entry_point >= cur_src_start_addr)
{
startup_file_start = cur_src_start_addr;
startup_file_end = cur_src_end_addr;
return;
}
- /* Create the two top-level blocks for this file. */
+ /* Create the two top-level blocks for this file (STATIC_BLOCK and
+ GLOBAL_BLOCK). */
finish_block (0, &file_symbols, 0, cur_src_start_addr, cur_src_end_addr);
finish_block (0, &global_symbols, 0, cur_src_start_addr, cur_src_end_addr);
symtab->blockvector = blockvector;
symtab->free_code = free_linetable;
symtab->filename = last_source_file;
+ symtab->dirname = NULL;
lv = line_vector;
lv->nitems = line_vector_index;
symtab->linetable = (struct linetable *)
symtab->nlines = 0;
symtab->line_charpos = 0;
+ symtab->language = language_unknown;
+ symtab->fullname = NULL;
+
+#ifdef TDESC
+ symtab->coffsem = last_coffsem;
+#if 0
+ /* This isn't used currently. Besides, if this is really about "syntax",
+ it shouldn't need to stick around past symbol read-in time. */
+ symtab->coffsyn = last_coffsyn;
+#endif
+#endif
+
+ free_named_symtabs (symtab->filename);
+
/* Link the new symtab into the list of such. */
symtab->next = symtab_list;
symtab_list = symtab;
last_source_file = 0;
}
\f
-/* Accumulate the misc functions in bunches of 127.
- At the end, copy them all into one newly allocated structure. */
-
-#define MISC_BUNCH_SIZE 127
-
-struct misc_bunch
-{
- struct misc_bunch *next;
- struct misc_function contents[MISC_BUNCH_SIZE];
-};
-
-/* Bunch currently being filled up.
- The next field points to chain of filled bunches. */
-
-static struct misc_bunch *misc_bunch;
-
-/* Number of slots filled in current bunch. */
-
-static int misc_bunch_index;
-
-/* Total number of misc functions recorded so far. */
-
-static int misc_count;
-
-static void
-init_misc_functions ()
-{
- misc_count = 0;
- misc_bunch = 0;
- misc_bunch_index = MISC_BUNCH_SIZE;
-}
-
static void
record_misc_function (name, address)
char *name;
CORE_ADDR address;
{
- register struct misc_bunch *new;
-
- if (misc_bunch_index == MISC_BUNCH_SIZE)
- {
- new = (struct misc_bunch *) xmalloc (sizeof (struct misc_bunch));
- misc_bunch_index = 0;
- new->next = misc_bunch;
- misc_bunch = new;
- }
- misc_bunch->contents[misc_bunch_index].name = savestring (name, strlen (name));
- misc_bunch->contents[misc_bunch_index].address = address;
- misc_bunch->contents[misc_bunch_index].type = mf_unknown;
- misc_bunch_index++;
- misc_count++;
+#ifdef TDESC
+ /* We don't want TDESC entry points on the misc_function_vector */
+ if (name[0] == '@') return;
+#endif
+ /* mf_text isn't true, but apparently COFF doesn't tell us what it really
+ is, so this guess is more useful than mf_unknown. */
+ prim_record_misc_function (savestring (name, strlen (name)),
+ address,
+ (int)mf_text);
}
+\f
+/* 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 */
+};
-/* if we see a function symbol, we do record_misc_function.
- * however, if it turns out the next symbol is '.bf', then
- * we call here to undo the misc definition
- */
-static void
-unrecord_misc_function ()
+void
+coff_symfile_init (sf)
+ struct sym_fns *sf;
{
- if (misc_bunch_index == 0)
- error ("Internal error processing symbol table, at symbol %d.",
- symnum);
- misc_bunch_index--;
- misc_count--;
-}
+ bfd *abfd = sf->sym_bfd;
+ /* Allocate struct to keep track of the symfile */
+ /* FIXME memory leak */
+ sf->sym_private = xmalloc (sizeof (struct coff_symfile_info));
-static int
-compare_misc_functions (fn1, fn2)
- struct misc_function *fn1, *fn2;
-{
- /* Return a signed result based on unsigned comparisons
- so that we sort into unsigned numeric order. */
- if (fn1->address < fn2->address)
- return -1;
- if (fn1->address > fn2->address)
- return 1;
- return 0;
-}
-
-static void
-discard_misc_bunches ()
-{
- register struct misc_bunch *next;
+#if defined (TDESC)
+ safe_to_init_tdesc_context = 0;
+#endif
- while (misc_bunch)
+ /* Save startup file's range of PC addresses to help blockframe.c
+ decide where the bottom of the stack is. */
+ if (bfd_get_file_flags (abfd) & EXEC_P)
{
- next = misc_bunch->next;
- free (misc_bunch);
- misc_bunch = next;
+ /* Executable file -- record its entry point so we'll recognize
+ the startup file because it contains the entry point. */
+ entry_point = bfd_get_start_address (abfd);
+ }
+ else
+ {
+ /* Examination of non-executable.o files. Short-circuit this stuff. */
+ /* ~0 will not be in any file, we hope. */
+ entry_point = ~0;
+ /* set the startup file to be an empty range. */
+ startup_file_start = 0;
+ startup_file_end = 0;
}
}
+/* This function is called for every section; it finds the outer limits
+ of the line table (minimum and maximum file offset) so that the
+ mainline code can read the whole thing for efficiency. */
+
+/* ARGSUSED */
static void
-condense_misc_bunches ()
+find_linenos (abfd, asect, vpinfo)
+ bfd *abfd;
+ sec_ptr asect;
+ void *vpinfo;
{
- register int i, j;
- register struct misc_bunch *bunch;
-#ifdef NAMES_HAVE_UNDERSCORE
- int offset = 1;
-#else
- int offset = 0;
-#endif
-
- misc_function_vector
- = (struct misc_function *)
- xmalloc (misc_count * sizeof (struct misc_function));
-
- j = 0;
- bunch = misc_bunch;
- while (bunch)
+ struct coff_symfile_info *info;
+ int size, count;
+ file_ptr offset, maxoff;
+
+/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */
+ count = asect->lineno_count;
+/* End of warning */
+
+ if (count == 0)
+ return;
+#if !defined (LINESZ)
+/* Just in case, you never know what to expect from those
+ COFF header files. */
+#define LINESZ (sizeof (struct lineno))
+#endif /* No LINESZ. */
+ size = count * LINESZ;
+
+ info = (struct coff_symfile_info *)vpinfo;
+/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */
+ offset = asect->line_filepos;
+/* End of warning */
+
+ if (offset < info->min_lineno_offset || info->min_lineno_offset == 0)
+ info->min_lineno_offset = offset;
+
+ maxoff = offset + size;
+ if (maxoff > info->max_lineno_offset)
+ info->max_lineno_offset = maxoff;
+#ifdef TDESC
+ /* While we're at it, find the debug_info. It's in the s_relptr
+ (or, in BFD-speak, rel_filepos) of the text segment section header. */
+ if (strcmp (bfd_section_name (abfd, asect), ".text") == 0)
{
- for (i = 0; i < misc_bunch_index; i++)
+ /* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */
+ debug_info = asect->rel_filepos;
+ /* End of warning */
+ if (tdesc_handle)
{
- register char *tmp;
-
- misc_function_vector[j] = bunch->contents[i];
- tmp = misc_function_vector[j].name;
- misc_function_vector[j].name = (tmp[0] == '_' ? tmp + offset : tmp);
- j++;
+ dc_terminate (tdesc_handle);
+ tdesc_handle = 0;
}
- bunch = bunch->next;
- misc_bunch_index = MISC_BUNCH_SIZE;
}
-
- misc_function_count = j;
-
- /* Sort the misc functions by address. */
-
- qsort (misc_function_vector, j, sizeof (struct misc_function),
- compare_misc_functions);
+#endif /* TDESC */
}
-/* Call sort_syms to sort alphabetically
- the symbols of each block of each symtab. */
-static int
-compare_symbols (s1, s2)
- struct symbol **s1, **s2;
-{
- /* Names that are less should come first. */
- 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));
-}
+/* The BFD for this file -- only good while we're actively reading
+ symbols into a psymtab or a symtab. */
-static void
-sort_syms ()
-{
- register struct symtab *s;
- register int i, nbl;
- register struct blockvector *bv;
- register struct block *b;
+static bfd *symfile_bfd;
- for (s = symtab_list; s; 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);
- }
- }
-}
-\f
-/* This is the symbol-file command. Read the file, analyze its symbols,
- and add a struct symtab to symtab_list. */
+/* Read a symbol file, after initialization by coff_symfile_init. */
+/* FIXME! Addr and Mainline are not used yet -- this will not work for
+ shared libraries or add_file! */
+/* ARGSUSED */
void
-symbol_file_command (name)
- char *name;
+coff_symfile_read (sf, addr, mainline)
+ struct sym_fns *sf;
+ CORE_ADDR addr;
+ int mainline;
{
+ struct coff_symfile_info *info = (struct coff_symfile_info *)sf->sym_private;
+ bfd *abfd = sf->sym_bfd;
+ char *name = bfd_get_filename (abfd);
int desc;
+ register int val;
int num_symbols;
- int num_sections;
int symtab_offset;
- extern void close ();
- register int val;
- struct cleanup *old_chain;
-
- dont_repeat ();
-
- if (name == 0)
- {
- if (symtab_list && !query ("Discard symbol table? ", 0))
- error ("Not confirmed.");
- if (symfile)
- free (symfile);
- symfile = 0;
- free_all_symtabs ();
- return;
- }
+ int stringtab_offset;
- name = tilde_expand (name);
- make_cleanup (free, name);
+ symfile_bfd = abfd; /* Kludge for swap routines */
- if (symtab_list && !query ("Load new symbol table from \"%s\"? ", name))
- error ("Not confirmed.");
-
- if (symfile)
- free (symfile);
- symfile = 0;
-
- {
- char *absolute_name;
-
- desc = openp (getenv ("PATH"), 1, name, O_RDONLY, 0, &absolute_name);
- if (desc < 0)
- perror_with_name (name);
- else
- name = absolute_name;
- }
-
- old_chain = make_cleanup (close, desc);
- make_cleanup (free_current_contents, &name);
-
- if ((num_symbols = read_file_hdr (desc, &file_hdr)) < 0)
- error ("File \"%s\" not in executable format.", name);
-
- /* If an a.out header is present, read it in. If not (e.g. a .o file)
- deal with its absence. */
- if (file_hdr.f_opthdr == 0
- || read_aout_hdr (desc, &aout_hdr, file_hdr.f_opthdr) < 0)
- {
- /* We will not actually be able to run code, since backtraces would
- fly off the bottom of the stack (there is no way to reliably
- detect bottom of stack), but that's fine since the kernel won't
- run something without an a.out header anyway. Passive examination
- of .o files is one place this might make sense. */
- /* ~0 will not be in any file. */
- aout_hdr.entry = ~0;
- /* set the startup file to be an empty range. */
- startup_file_start = 0;
- startup_file_end = 0;
- }
-
- if (num_symbols == 0)
- {
- free_all_symtabs ();
- error ("%s does not have a symbol-table.\n", name);
- }
-
- printf ("Reading symbol data from %s...", name);
- fflush (stdout);
-
- /* Throw away the old symbol table. */
-
- free_all_symtabs ();
- free_all_psymtabs (); /* Make sure that partial_symtab_list */
- /* is 0 also. */
-
- num_sections = file_hdr.f_nscns;
- symtab_offset = file_hdr.f_symptr;
-
- if (read_section_hdr (desc, _TEXT, &text_hdr, num_sections) < 0)
- error ("\"%s\": can't read text section header", name);
+/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */
+ desc = fileno ((FILE *)(abfd->iostream)); /* File descriptor */
+ num_symbols = bfd_get_symcount (abfd); /* How many syms */
+ symtab_offset = obj_sym_filepos (abfd); /* Symbol table file offset */
+ stringtab_offset = symtab_offset + num_symbols * SYMESZ; /* String tab */
+/* End of warning */
/* Read the line number table, all at once. */
+ info->min_lineno_offset = 0;
+ info->max_lineno_offset = 0;
+ bfd_map_over_sections (abfd, find_linenos, info);
- val = init_lineno (desc, text_hdr.s_lnnoptr, text_hdr.s_nlnno);
+ val = init_lineno (desc, info->min_lineno_offset,
+ info->max_lineno_offset - info->min_lineno_offset);
if (val < 0)
error ("\"%s\": error reading line numbers\n", name);
/* Now read the string table, all at once. */
- val = init_stringtab (desc, symtab_offset + num_symbols * SYMESZ);
+ val = init_stringtab (desc, stringtab_offset);
if (val < 0)
{
- free_all_symtabs ();
+ free_all_symtabs (); /* FIXME blows whole symtab */
printf ("\"%s\": can't get string table", name);
fflush (stdout);
return;
if (val < 0)
perror_with_name (name);
- init_misc_functions ();
+ init_misc_bunches ();
make_cleanup (discard_misc_bunches, 0);
/* Now that the executable file is positioned at symbol table,
/* Sort symbols alphabetically within each block. */
- sort_syms ();
+ sort_all_symtab_syms ();
- /* Go over the misc functions and install them in vector. */
+ /* Go over the misc symbol bunches and install them in vector. */
- condense_misc_bunches ();
-
- /* Don't allow char * to have a typename (else would get caddr_t.) */
-
- TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0;
+ condense_misc_bunches (!mainline);
/* Make a default for file to list. */
- select_source_symtab (0);
-
- symfile = savestring (name, strlen (name));
-
- do_cleanups (old_chain);
-
- printf ("done.\n");
- fflush (stdout);
+ select_source_symtab (0); /* FIXME, this might be too slow, see dbxread */
}
-/* Return name of file symbols were loaded from, or 0 if none.. */
-
-char *
-get_sym_file ()
+void
+coff_new_init ()
{
- return symfile;
+ /* There seems to be nothing to do except free_all_symtabs and set
+ symfile to zero, which is done by our caller. */
}
\f
/* 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; /* 1 if syment only, 2 if syment + auxent */
+ int c_nsyms; /* 1 if syment only, 2 if syment + auxent, etc */
long c_value;
int c_sclass;
int c_secnum;
register struct context_stack *new;
struct coff_symbol coff_symbol;
register struct coff_symbol *cs = &coff_symbol;
- static SYMENT main_sym;
- static AUXENT main_aux;
+ static struct internal_syment main_sym;
+ static union internal_auxent main_aux;
struct coff_symbol fcn_cs_saved;
- static SYMENT fcn_sym_saved;
- static AUXENT fcn_aux_saved;
+ static struct internal_syment fcn_sym_saved;
+ static union internal_auxent fcn_aux_saved;
+ /* A .file is open. */
+ int in_source_file = 0;
int num_object_files = 0;
int next_file_symnum = -1;
- char *filestring;
+
+ /* Name of the current file. */
+ char *filestring = "";
int depth;
int fcn_first_line;
int fcn_last_line;
last_source_file = 0;
bzero (opaque_type_chain, sizeof opaque_type_chain);
+ if (type_vector) /* Get rid of previous one */
+ free (type_vector);
type_vector_length = 160;
type_vector = (struct typevector *)
xmalloc (sizeof (struct typevector)
QUIT; /* Make this command interruptable. */
read_one_sym (cs, &main_sym, &main_aux);
+#ifdef SEM
+ temp_sem_val = cs->c_name[0] << 24 | cs->c_name[1] << 16 |
+ cs->c_name[2] << 8 | cs->c_name[3];
+ if (int_sem_val == temp_sem_val)
+ last_coffsem = (int) strtol (cs->c_name+4, (char **) NULL, 10);
+#endif
+
if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE)
{
- CORE_ADDR last_file_end = cur_src_end_addr;
-
if (last_source_file)
end_symtab ();
}
/* Special case for file with type declarations only, no text. */
- if (!last_source_file && cs->c_type != T_NULL && cs->c_secnum == N_DEBUG)
+ if (!last_source_file && SDB_TYPE (cs->c_type)
+ && cs->c_secnum == N_DEBUG)
complete_symtab (filestring, 0, 0);
/* Typedefs should not be treated as symbol definitions. */
end_symtab ();
start_symtab ();
}
- num_object_files++;
+ in_source_file = 1;
break;
case C_STAT:
if (cs->c_name[0] == '.') {
if (strcmp (cs->c_name, _TEXT) == 0) {
- if (num_object_files == 1) {
+ if (++num_object_files == 1) {
/* last address of startup file */
first_object_file_end = cs->c_value +
main_aux.x_scn.x_scnlen;
}
- /* for some reason the old code didn't do
- * this if this section entry had
- * main_aux.x_scn.x_nlinno equal to 0
- */
- complete_symtab (filestring, cs->c_value,
- main_aux.x_scn.x_scnlen);
+ /* Check for in_source_file deals with case of
+ a file with debugging symbols
+ followed by a later file with no symbols. */
+ if (in_source_file)
+ complete_symtab (filestring, cs->c_value,
+ main_aux.x_scn.x_scnlen);
+ in_source_file = 0;
}
/* flush rest of '.' symbols */
break;
}
+ else if (!SDB_TYPE (cs->c_type)
+ && cs->c_name[0] == 'L'
+ && (strncmp (cs->c_name, "LI%", 3) == 0
+ || strncmp (cs->c_name, "LF%", 3) == 0
+ || strncmp (cs->c_name,"LC%",3) == 0
+ || strncmp (cs->c_name,"LP%",3) == 0
+ || strncmp (cs->c_name,"LPB%",4) == 0
+ || strncmp (cs->c_name,"LBB%",4) == 0
+ || strncmp (cs->c_name,"LBE%",4) == 0
+ || strncmp (cs->c_name,"LPBX%",5) == 0))
+ /* At least on a 3b1, gcc generates swbeg and string labels
+ that look like this. Ignore them. */
+ break;
/* fall in for static symbols that don't start with '.' */
case C_EXT:
if (cs->c_sclass == C_EXT &&
cs->c_secnum == N_ABS &&
strcmp (cs->c_name, _ETEXT) == 0)
end_of_text_addr = cs->c_value;
- if (cs->c_type == T_NULL) {
+ if (!SDB_TYPE (cs->c_type)) {
if (cs->c_secnum <= 1) { /* text or abs */
record_misc_function (cs->c_name, cs->c_value);
break;
case C_FCN:
if (strcmp (cs->c_name, ".bf") == 0)
{
-#if 0
- /* Don't do this; we want all functions to be on the
- mfl now. */
- unrecord_misc_function ();
-#endif
-
within_function = 1;
/* value contains address of first non-init type code */
*/
/* { main_aux.x_sym.x_misc.x_lnsz.x_lnno
contains number of lines to '}' */
+ new = context_stack;
+ if (new == 0)
+ {
+ complain (&ef_complaint, cs->c_symnum);
+ within_function = 0;
+ break;
+ }
fcn_last_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno;
enter_linenos (fcn_line_ptr, fcn_first_line, fcn_last_line);
- new = context_stack;
- if (new == 0)
- error ("Invalid symbol data; .bf/.ef/.bb/.eb symbol mismatch, at symbol %d.",
- symnum);
-
finish_block (new->name, &local_symbols, new->old_blocks,
new->start_addr,
+#if defined (FUNCTION_EPILOGUE_SIZE)
+ /* This macro should be defined only on
+ machines where the
+ fcn_aux_saved.x_sym.x_misc.x_fsize
+ field is always zero.
+ So use the .bf record information that
+ points to the epilogue and add the size
+ of the epilogue. */
+ cs->c_value + FUNCTION_EPILOGUE_SIZE
+#else
fcn_cs_saved.c_value +
- fcn_aux_saved.x_sym.x_misc.x_fsize);
+ fcn_aux_saved.x_sym.x_misc.x_fsize
+#endif
+ );
context_stack = 0;
within_function = 0;
free (new);
free (new);
}
break;
+#ifdef TDESC
+ case C_VERSION:
+#if 0
+ /* This isn't used currently. */
+ if (strcmp (cs->c_name, ".coffsyn") == 0)
+ last_coffsyn = cs->c_value;
+ else
+#endif /* 0 */
+ if ((strcmp (cs->c_name, ".coffsem") == 0) &&
+ (cs->c_value != 0))
+ last_coffsem = cs->c_value;
+ break;
+#endif /* TDESC */
default:
+#ifdef TDESC
+ if ((strcmp (cs->c_name, ".coffsem") == 0) &&
+ (cs->c_value != 0))
+ last_coffsem = cs->c_value;
+ else
+#endif
(void) process_coff_symbol (cs, &main_aux);
break;
}
\f
/* Routines for reading headers and symbols from executable. */
+#ifdef FIXME
+/* Move these XXXMAGIC symbol defns into BFD! */
+
/* Read COFF file header, check magic number,
and return number of symbols. */
read_file_hdr (chan, file_hdr)
#endif
#ifdef CLIPPERMAGIC
case CLIPPERMAGIC:
+#endif
+#if defined (MC68KWRMAGIC) \
+ && (!defined (MC68MAGIC) || MC68KWRMAGIC != MC68MAGIC)
+ case MC68KWRMAGIC:
+#endif
+#ifdef MC68KROMAGIC
+ case MC68KROMAGIC:
+ case MC68KPGMAGIC:
+#endif
+#ifdef MC88DGMAGIC
+ case MC88DGMAGIC:
+#endif
+#ifdef MC88MAGIC
+ case MC88MAGIC:
#endif
+#ifdef I960ROMAGIC
+ case I960ROMAGIC: /* Intel 960 */
+#endif
+#ifdef I960RWMAGIC
+ case I960RWMAGIC: /* Intel 960 */
+#endif
return file_hdr->f_nsyms;
default:
#endif
}
}
+#endif
-read_aout_hdr (chan, aout_hdr, size)
- int chan;
- AOUTHDR *aout_hdr;
- int size;
-{
- lseek (chan, (long)FILHSZ, 0);
- if (size != sizeof (AOUTHDR))
- return -1;
- if (myread (chan, (char *)aout_hdr, size) != size)
- return -1;
- return 0;
-}
-
-read_section_hdr (chan, section_name, section_hdr, nsects)
- register int chan;
- register char *section_name;
- SCNHDR *section_hdr;
- register int nsects;
-{
- register int i;
-
- if (lseek (chan, FILHSZ + sizeof (AOUTHDR), 0) < 0)
- return -1;
-
- for (i = 0; i < nsects; i++)
- {
- if (myread (chan, (char *)section_hdr, SCNHSZ) < 0)
- return -1;
- if (strncmp (section_hdr->s_name, section_name, 8) == 0)
- return 0;
- }
- return -1;
-}
+/* Read the next symbol, swap it, and return it in both internal_syment
+ form, and coff_symbol form. Also return its first auxent, if any,
+ in internal_auxent form, and skip any other auxents. */
+static void
read_one_sym (cs, sym, aux)
register struct coff_symbol *cs;
- register SYMENT *sym;
- register AUXENT *aux;
+ register struct internal_syment *sym;
+ register union internal_auxent *aux;
{
+ struct external_syment temp_sym[1];
+ union external_auxent temp_aux[1];
+ int i;
+
cs->c_symnum = symnum;
- fread ((char *)sym, SYMESZ, 1, nlist_stream_global);
+ fread ((char *)temp_sym, SYMESZ, 1, nlist_stream_global);
+ bfd_coff_swap_sym_in (symfile_bfd, temp_sym, sym);
cs->c_nsyms = (sym->n_numaux & 0xff) + 1;
- if (cs->c_nsyms == 2)
+ if (cs->c_nsyms >= 2)
{
- /* doc for coff says there is either no aux entry or just one */
- fread ((char *)aux, AUXESZ, 1, nlist_stream_global);
+ fread ((char *)temp_aux, AUXESZ, 1, nlist_stream_global);
+ bfd_coff_swap_aux_in (symfile_bfd, temp_aux, sym->n_type, sym->n_sclass, aux);
+ /* If more than one aux entry, read past it (only the first aux
+ is important). */
+ for (i = 2; i < cs->c_nsyms; i++)
+ fread ((char *)temp_aux, AUXESZ, 1, nlist_stream_global);
}
- else if (cs->c_nsyms > 2)
- error ("more than one aux symbol table entry at symnum=%d\n", symnum);
-
cs->c_name = getsymname (sym);
cs->c_value = sym->n_value;
cs->c_sclass = (sym->n_sclass & 0xff);
cs->c_secnum = sym->n_scnum;
cs->c_type = (unsigned) sym->n_type;
+ if (!SDB_TYPE (cs->c_type))
+ cs->c_type = 0;
symnum += cs->c_nsyms;
}
int chan;
long offset;
{
- long buffer;
+ long length;
int val;
+ unsigned char lengthbuf[4];
if (stringtab)
{
if (lseek (chan, offset, 0) < 0)
return -1;
- val = myread (chan, (char *)&buffer, sizeof buffer);
+ val = myread (chan, (char *)lengthbuf, sizeof lengthbuf);
+ length = bfd_h_get_32 (symfile_bfd, lengthbuf);
/* If no string table is needed, then the file may end immediately
after the symbols. Just return with `stringtab' set to null. */
- if (val != sizeof buffer || buffer == 0)
+ if (val != sizeof length || length < sizeof length)
return 0;
- stringtab = (char *) xmalloc (buffer);
+ stringtab = (char *) xmalloc (length);
if (stringtab == NULL)
return -1;
- bcopy (&buffer, stringtab, sizeof buffer);
+ bcopy (&length, stringtab, sizeof length);
+ if (length == sizeof length) /* Empty table -- just the count */
+ return 0;
- val = myread (chan, stringtab + sizeof buffer, buffer - sizeof buffer);
- if (val != buffer - sizeof buffer || stringtab[buffer - 1] != '\0')
+ val = myread (chan, stringtab + sizeof length, length - sizeof length);
+ if (val != length - sizeof length || stringtab[length - 1] != '\0')
return -1;
return 0;
static char *
getsymname (symbol_entry)
- SYMENT *symbol_entry;
+ struct internal_syment *symbol_entry;
{
static char buffer[SYMNMLEN+1];
char *result;
- if (symbol_entry->n_zeroes == 0)
+ if (symbol_entry->_n._n_n._n_zeroes == 0)
{
- result = stringtab + symbol_entry->n_offset;
+ result = stringtab + symbol_entry->_n._n_n._n_offset;
}
else
{
- strncpy (buffer, symbol_entry->n_name, SYMNMLEN);
+ strncpy (buffer, symbol_entry->_n._n_name, SYMNMLEN);
buffer[SYMNMLEN] = '\0';
result = buffer;
}
static char *
getfilename (aux_entry)
- AUXENT *aux_entry;
+ union internal_auxent *aux_entry;
{
static char buffer[BUFSIZ];
register char *temp;
extern char *rindex ();
#ifndef COFF_NO_LONG_FILE_NAMES
- if (aux_entry->x_file.x_foff != 0)
- strcpy (buffer, stringtab + aux_entry->x_file.x_foff);
+#if defined (x_zeroes)
+ /* Data General. */
+ if (aux_entry->x_zeroes == 0)
+ strcpy (buffer, stringtab + aux_entry->x_offset);
+#else /* no x_zeroes */
+ if (aux_entry->x_file.x_n.x_zeroes == 0)
+ strcpy (buffer, stringtab + aux_entry->x_file.x_n.x_offset);
+#endif /* no x_zeroes */
else
-#endif
+#endif /* COFF_NO_LONG_FILE_NAMES */
{
+#if defined (x_name)
+ /* Data General. */
+ strncpy (buffer, aux_entry->x_name, FILNMLEN);
+#else
strncpy (buffer, aux_entry->x_file.x_fname, FILNMLEN);
+#endif
buffer[FILNMLEN] = '\0';
}
result = buffer;
result = temp + 1;
return (result);
}
-
+\f
/* Support for line number handling */
static char *linetab = NULL;
static long linetab_offset;
-static int linetab_count;
+static unsigned long linetab_size;
+/* Read in all the line numbers for fast lookups later. Leave them in
+ external (unswapped) format in memory; we'll swap them as we enter
+ them into GDB's data structures. */
+
static int
-init_lineno (chan, offset, count)
+init_lineno (chan, offset, size)
int chan;
long offset;
- int count;
+ int size;
{
int val;
+ linetab_offset = offset;
+ linetab_size = size;
+
+ if (size == 0)
+ return 0;
+
if (lseek (chan, offset, 0) < 0)
return -1;
- if (linetab)
- free (linetab);
- linetab = (char *) xmalloc (count * LINESZ);
+ linetab = (char *) xmalloc (size);
- val = myread (chan, linetab, count * LINESZ);
- if (val != count * LINESZ)
+ val = myread (chan, linetab, size);
+ if (val != size)
return -1;
- linetab_offset = offset;
- linetab_count = count;
+ make_cleanup (free, linetab); /* Be sure it gets de-allocated. */
return 0;
}
+#if !defined (L_LNNO32)
+#define L_LNNO32(lp) ((lp)->l_lnno)
+#endif
+
static void
enter_linenos (file_offset, first_line, last_line)
long file_offset;
register int first_line;
register int last_line;
{
- register char *rawptr = &linetab[file_offset - linetab_offset];
- struct lineno lptr;
+ register char *rawptr;
+ struct internal_lineno lptr;
+
+ if (file_offset < linetab_offset)
+ {
+ complain (&lineno_complaint, file_offset);
+ if (file_offset > linetab_size) /* Too big to be an offset? */
+ return;
+ file_offset += linetab_offset; /* Try reading at that linetab offset */
+ }
+
+ rawptr = &linetab[file_offset - linetab_offset];
/* skip first line entry for each function */
rawptr += LINESZ;
/* line numbers start at one for the first line of the function */
first_line--;
- /* Bcopy since occaisionally rawptr isn't pointing at long
- boundaries. */
- for (bcopy (rawptr, &lptr, LINESZ);
- lptr.l_lnno && lptr.l_lnno <= last_line;
- rawptr += LINESZ, bcopy (rawptr, &lptr, LINESZ))
- {
- record_line (first_line + lptr.l_lnno, lptr.l_addr.l_paddr);
- }
+ for (;;) {
+ bfd_coff_swap_lineno_in (symfile_bfd, (LINENO *)rawptr, &lptr);
+ rawptr += LINESZ;
+ if (L_LNNO32 (&lptr) && L_LNNO32 (&lptr) <= last_line)
+ record_line (first_line + L_LNNO32 (&lptr), lptr.l_addr.l_paddr);
+ else
+ break;
+ }
}
\f
static int
register int i;
/* Go through the per-file symbols only */
- b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1);
+ b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
for (i = BLOCK_NSYMS (b) - 1; i >= 0; i--)
{
register struct symbol *real_sym;
!strcmp (name + 1, SYMBOL_NAME (sym) + 1))
{
if (prev)
- SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym);
+ SYMBOL_VALUE_CHAIN (prev) = SYMBOL_VALUE_CHAIN (sym);
else
- opaque_type_chain[hash]
- = (struct symbol *) SYMBOL_VALUE (sym);
+ opaque_type_chain[hash] = SYMBOL_VALUE_CHAIN (sym);
patch_type (SYMBOL_TYPE (sym), SYMBOL_TYPE (real_sym));
if (prev)
- sym = (struct symbol *) SYMBOL_VALUE (prev);
+ sym = SYMBOL_VALUE_CHAIN (prev);
else
sym = opaque_type_chain[hash];
}
else
{
prev = sym;
- sym = (struct symbol *) SYMBOL_VALUE (sym);
+ sym = SYMBOL_VALUE_CHAIN (sym);
}
}
}
}
}
\f
+#if defined (clipper)
+#define BELIEVE_PCC_PROMOTION 1
+#endif
+
static struct symbol *
process_coff_symbol (cs, aux)
register struct coff_symbol *cs;
- register AUXENT *aux;
+ register union internal_auxent *aux;
{
register struct symbol *sym
= (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol));
char *name;
- char *dot;
#ifdef NAMES_HAVE_UNDERSCORE
int offset = 1;
#else
case C_EXT:
SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE_ADDRESS (sym) = (CORE_ADDR) cs->c_value;
add_symbol_to_list (sym, &global_symbols);
break;
case C_STAT:
SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE_ADDRESS (sym) = (CORE_ADDR) cs->c_value;
if (within_function) {
/* Static symbol of local scope */
add_symbol_to_list (sym, &local_symbols);
case C_ARG:
SYMBOL_CLASS (sym) = LOC_ARG;
add_symbol_to_list (sym, &local_symbols);
-#ifndef clipper
+#if !defined (BELIEVE_PCC_PROMOTION)
/* If PCC says a parameter is a short or a char,
it is really an int. */
if (SYMBOL_TYPE (sym) == builtin_type_char
case C_REGPARM:
SYMBOL_CLASS (sym) = LOC_REGPARM;
add_symbol_to_list (sym, &local_symbols);
-#ifndef clipper
+#if !defined (BELIEVE_PCC_PROMOTION)
/* If PCC says a parameter is a short or a char,
it is really an int. */
if (SYMBOL_TYPE (sym) == builtin_type_char
{
register int i = hashname (SYMBOL_NAME (sym));
- SYMBOL_VALUE (sym) = (int) opaque_type_chain[i];
+ SYMBOL_VALUE_CHAIN (sym) = opaque_type_chain[i];
opaque_type_chain[i] = sym;
}
add_symbol_to_list (sym, &file_symbols);
decode_type (cs, c_type, aux)
register struct coff_symbol *cs;
unsigned int c_type;
- register AUXENT *aux;
+ register union internal_auxent *aux;
{
register struct type *type = 0;
- register int n;
unsigned int new_c_type;
if (c_type & ~N_BTMASK)
/* Define an array type. */
/* auxent refers to array, not base type */
- if (aux->x_sym.x_tagndx == 0)
+ if (aux->x_sym.x_tagndx.l == 0)
cs->c_nsyms = 1;
/* shift the indices down */
}
/* Reference to existing type */
- if (cs->c_nsyms > 1 && aux->x_sym.x_tagndx != 0)
+ if (cs->c_nsyms > 1 && aux->x_sym.x_tagndx.l != 0)
{
- type = coff_alloc_type (aux->x_sym.x_tagndx);
+ type = coff_alloc_type (aux->x_sym.x_tagndx.l);
return type;
}
decode_function_type (cs, c_type, aux)
register struct coff_symbol *cs;
unsigned int c_type;
- register AUXENT *aux;
+ register union internal_auxent *aux;
{
- if (aux->x_sym.x_tagndx == 0)
+ if (aux->x_sym.x_tagndx.l == 0)
cs->c_nsyms = 1; /* auxent refers to function, not base type */
- return decode_type (cs, DECREF (cs->c_type), aux);
+ return decode_type (cs, DECREF (c_type), aux);
}
\f
/* basic C types */
decode_base_type (cs, c_type, aux)
register struct coff_symbol *cs;
unsigned int c_type;
- register AUXENT *aux;
+ register union internal_auxent *aux;
{
struct type *type;
/* shows up with "void (*foo)();" structure members */
return builtin_type_void;
+#if 0
+/* DGUX actually defines both T_ARG and T_VOID to the same value. */
+#ifdef T_ARG
case T_ARG:
- /* shouldn't show up here */
- break;
+ /* Shows up in DGUX, I think. Not sure where. */
+ return builtin_type_void; /* shouldn't show up here */
+#endif
+#endif /* 0 */
+
+#ifdef T_VOID
+ case T_VOID:
+ /* Intel 960 COFF has this symbol and meaning. */
+ return builtin_type_void;
+#endif
case T_CHAR:
return builtin_type_char;
#endif
struct coff_symbol member_sym;
register struct coff_symbol *ms = &member_sym;
- SYMENT sub_sym;
- AUXENT sub_aux;
+ struct internal_syment sub_sym;
+ union internal_auxent sub_aux;
int done = 0;
type = coff_alloc_type (index);
/* Read a definition of an enumeration type,
and create and return a suitable type object.
Also defines the symbols that represent the values of the type. */
+/* Currently assumes it's sizeof (int) and doesn't use length. */
+/* ARGSUSED */
static struct type *
read_enum_type (index, length, lastsym)
int index;
register struct symbol *sym;
register struct type *type;
int nsyms = 0;
+ int done = 0;
struct pending **symlist;
struct coff_symbol member_sym;
register struct coff_symbol *ms = &member_sym;
- SYMENT sub_sym;
- AUXENT sub_aux;
+ struct internal_syment sub_sym;
+ union internal_auxent sub_aux;
struct pending *osyms, *syms;
register int n;
char *name;
symlist = &file_symbols;
osyms = *symlist;
- while (symnum < lastsym && symnum < nlist_nsyms_global)
+ while (!done && symnum < lastsym && symnum < nlist_nsyms_global)
{
read_one_sym (ms, &sub_sym, &sub_aux);
name = ms->c_name;
break;
case C_EOS:
+ /* Sometimes the linker (on 386/ix 2.0.2 at least) screws
+ up the count of how many symbols to read. So stop
+ on .eos. */
+ done = 1;
break;
}
}
/* Now fill in the fields of the type-structure. */
+ /* FIXME: Should be sizeof (int) on target, not host. */
TYPE_LENGTH (type) = sizeof (int);
TYPE_CODE (type) = TYPE_CODE_ENUM;
TYPE_NFIELDS (type) = nsyms;
return type;
}
-/* This function is really horrible, but to avoid it, there would need
- to be more filling in of forward references. THIS SHOULD BE MOVED
- OUT OF COFFREAD.C AND DBXREAD.C TO SOME PLACE WHERE IT CAN BE SHARED. */
-int
-fill_in_vptr_fieldno (type)
- struct type *type;
-{
- if (TYPE_VPTR_FIELDNO (type) < 0)
- TYPE_VPTR_FIELDNO (type) =
- fill_in_vptr_fieldno (TYPE_BASECLASS (type, 1));
- return TYPE_VPTR_FIELDNO (type);
-}
-
-/* partial symbol tables are not implemented in coff, therefore
- block_for_pc() (and others) will never decide to call this. */
+/* Register our ability to parse symbols for coff BFD files */
-extern struct symtab *
-psymtab_to_symtab ()
+static struct sym_fns coff_sym_fns =
{
- fatal ("error: Someone called psymtab_to_symtab\n");
-}
-
-/* These will stay zero all the time */
-struct psymbol_allocation_list global_psymbols, static_psymbols;
+ /* This assumes that 88kbcs implies TDESC and TDESC implies 88kbcs.
+ If that's not true, this can be relaxed, but if it is true,
+ it will just cause users grief if we try to read the wrong kind
+ of symbol file. */
+#if defined (TDESC)
+ "m88kbcs", 8,
+#else /* not TDESC */
+ "coff", 4,
+#endif /* not TDESC */
+ coff_new_init, coff_symfile_init, coff_symfile_read,
+};
-_initialize_coff ()
+void
+_initialize_coffread ()
{
- symfile = 0;
-
- bzero (&global_psymbols, sizeof (global_psymbols));
- bzero (&static_psymbols, sizeof (static_psymbols));
-
- add_com ("symbol-file", class_files, symbol_file_command,
- "Load symbol table (in coff format) from executable file FILE.");
+ add_symtab_fns(&coff_sym_fns);
}
-
-
-#endif /* COFF_FORMAT */
-