/* Read coff symbol tables and convert to internal format, for GDB.
- 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
+ Contributed by David D. Johnson, Brown University (ddj@cs.brown.edu).
Copyright (C) 1987-1991 Free Software Foundation, Inc.
This file is part of GDB.
#include "symfile.h"
#if defined (TDESC)
-/* Need to get C_VERSION and friends. */
-#include <a.out.h>
-#else /* not TDESC */
-#include <intel-coff.h>
+/* Need to get C_VERSION and friends. FIXME, should be in internalcoff.h */
+#include "m88k-bcs.h"
#endif /* not TDESC */
#include <obstack.h>
#define SDB_TYPE(type) (BTYPE(type) | (type & N_TMASK))
+/*
+ * Convert from an sdb register number to an internal gdb register number.
+ * This should be defined in tm.h, if REGISTER_NAMES is not set up
+ * to map one to one onto the sdb register numbers.
+ */
+#ifndef SDB_REG_TO_REGNUM
+# define SDB_REG_TO_REGNUM(value) (value)
+#endif
+
/* Name of source file whose symbol data we are now processing.
This comes from a symbol named ".file". */
/* Core address of the end of the first object file. */
static CORE_ADDR first_object_file_end;
-/* End of the text segment of the executable file,
- as found in the symbol _etext. */
-
-static CORE_ADDR end_of_text_addr;
-
/* The addresses of the symbol table stream and number of symbols
of the object file we are reading (as copied into core). */
static int line_vector_length;
+/* Pointers to scratch storage, used for reading raw symbols and auxents. */
+
+static char *temp_sym;
+static char *temp_aux;
+
+/* Local variables that hold the shift and mask values for the
+ COFF file that we are currently reading. These come back to us
+ from BFD, and are referenced by their macro names, as well as
+ internally to the BTYPE, ISPTR, ISFCN, ISARY, ISTAG, and DECREF
+ macros from ../internalcoff.h . */
+
+static unsigned local_n_btmask;
+static unsigned local_n_btshft;
+static unsigned local_n_tmask;
+static unsigned local_n_tshift;
+
+#define N_BTMASK local_n_btmask
+#define N_BTSHFT local_n_btshft
+#define N_TMASK local_n_tmask
+#define N_TSHIFT local_n_tshift
+
+/* Local variables that hold the sizes in the file of various COFF structures.
+ (We only need to know this to read them from the file -- BFD will then
+ translate the data in them, into `internal_xxx' structs in the right
+ byte order, alignment, etc.) */
+
+static unsigned local_linesz;
+static unsigned local_symesz;
+static unsigned local_auxesz;
+
+
#ifdef TDESC
#include "tdesc.h"
#define SEM
int within_function;
+#if 0
+/* The type of the function we are currently reading in. This is
+ used by define_symbol to record the type of arguments to a function. */
+
+struct type *in_function_type;
+#endif
+
/* List of blocks already made (lexical contexts already closed).
This is used at the end to make the blockvector. */
blockvector = make_blockvector ();
/* Now create the symtab object for this source file. */
- symtab = (struct symtab *) xmalloc (sizeof (struct symtab));
- symtab->free_ptr = 0;
+ symtab = allocate_symtab (last_source_file);
/* Fill in its components. */
symtab->blockvector = blockvector;
symtab->free_code = free_linetable;
+ symtab->free_ptr = 0;
symtab->filename = last_source_file;
symtab->dirname = NULL;
lv = line_vector;
symtab->linetable = (struct linetable *)
xrealloc (lv, (sizeof (struct linetable)
+ lv->nitems * sizeof (struct linetable_entry)));
- symtab->nlines = 0;
- symtab->line_charpos = 0;
-
- symtab->language = language_unknown;
- symtab->fullname = NULL;
#ifdef TDESC
symtab->coffsem = last_coffsem;
file_ptr max_lineno_offset; /* 1+last byte of line#s in file */
};
+static int text_bfd_scnum;
+
void
coff_symfile_init (sf)
struct sym_fns *sf;
{
+ asection *section;
bfd *abfd = sf->sym_bfd;
/* Allocate struct to keep track of the symfile */
startup_file_start = 0;
startup_file_end = 0;
}
+ /* Save the section number for the text section */
+ if (section = bfd_get_section_by_name(abfd,".text"))
+ text_bfd_scnum = section->index;
+ else
+ text_bfd_scnum = -1;
}
/* This function is called for every section; it finds the outer limits
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;
+ size = count * local_linesz;
info = (struct coff_symfile_info *)vpinfo;
/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */
{
struct coff_symfile_info *info = (struct coff_symfile_info *)sf->sym_private;
bfd *abfd = sf->sym_bfd;
+ coff_data_type *cdata = coff_data (abfd);
char *name = bfd_get_filename (abfd);
int desc;
register int val;
symfile_bfd = abfd; /* Kludge for swap routines */
/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */
- desc = fileno ((FILE *)(abfd->iostream)); /* File descriptor */
+ 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 */
+ symtab_offset = cdata->sym_filepos; /* Symbol table file offset */
+ stringtab_offset = symtab_offset + /* String table file offset */
+ num_symbols * cdata->local_symesz;
+
+ /* Set a few file-statics that give us specific information about
+ the particular COFF file format we're reading. */
+ local_linesz = cdata->local_linesz;
+ local_n_btmask = cdata->local_n_btmask;
+ local_n_btshft = cdata->local_n_btshft;
+ local_n_tmask = cdata->local_n_tmask;
+ local_n_tshift = cdata->local_n_tshift;
+ local_linesz = cdata->local_linesz;
+ local_symesz = cdata->local_symesz;
+ local_auxesz = cdata->local_auxesz;
+
+ /* Allocate space for raw symbol and aux entries, based on their
+ space requirements as reported by BFD. */
+ temp_sym = (char *) xmalloc
+ (cdata->local_symesz + cdata->local_auxesz);
+ temp_aux = temp_sym + cdata->local_symesz;
+ make_cleanup (free_current_contents, &temp_sym);
/* End of warning */
/* Read the line number table, all at once. */
case C_STAT:
if (cs->c_name[0] == '.') {
- if (strcmp (cs->c_name, _TEXT) == 0) {
+ if (strcmp (cs->c_name, ".text") == 0) {
+ /* FIXME: don't wire in ".text" as section name
+ or symbol name! */
if (++num_object_files == 1) {
/* last address of startup file */
first_object_file_end = cs->c_value +
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 (!SDB_TYPE (cs->c_type)) {
- if (cs->c_secnum <= 1) { /* text or abs */
+ /* FIXME: This is BOGUS Will Robinson!
+ Coff should provide the SEC_CODE flag for executable sections,
+ then if we could look up sections by section number we
+ could see if the flags indicate SEC_CODE. If so, then
+ record this symbol as a miscellaneous function. But why
+ are absolute syms recorded as functions, anyway? */
+ if (cs->c_secnum <= text_bfd_scnum+1) {/* text or abs */
record_misc_function (cs->c_name, cs->c_value);
break;
} else {
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 *)temp_sym, SYMESZ, 1, nlist_stream_global);
- bfd_coff_swap_sym_in (symfile_bfd, temp_sym, sym);
+ fread (temp_sym, local_symesz, 1, nlist_stream_global);
+ bfd_coff_swap_sym_in (symfile_bfd, temp_sym, (char *)sym);
cs->c_nsyms = (sym->n_numaux & 0xff) + 1;
if (cs->c_nsyms >= 2)
{
- 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);
+ fread (temp_aux, local_auxesz, 1, nlist_stream_global);
+ bfd_coff_swap_aux_in (symfile_bfd, temp_aux, sym->n_type, sym->n_sclass,
+ (char *)aux);
/* If more than one aux entry, read past it (only the first aux
is important). */
for (i = 2; i < cs->c_nsyms; i++)
- fread ((char *)temp_aux, AUXESZ, 1, nlist_stream_global);
+ fread (temp_aux, local_auxesz, 1, nlist_stream_global);
}
cs->c_name = getsymname (sym);
cs->c_value = sym->n_value;
rawptr = &linetab[file_offset - linetab_offset];
/* skip first line entry for each function */
- rawptr += LINESZ;
+ rawptr += local_linesz;
/* line numbers start at one for the first line of the function */
first_line--;
for (;;) {
- bfd_coff_swap_lineno_in (symfile_bfd, (LINENO *)rawptr, &lptr);
- rawptr += LINESZ;
+ bfd_coff_swap_lineno_in (symfile_bfd, rawptr, &lptr);
+ rawptr += local_linesz;
if (L_LNNO32 (&lptr) && L_LNNO32 (&lptr) <= last_line)
record_line (first_line + L_LNNO32 (&lptr), lptr.l_addr.l_paddr);
else
if (ISFCN (cs->c_type))
{
- SYMBOL_TYPE (sym) =
- lookup_function_type (decode_function_type (cs, cs->c_type, aux));
+#if 0
+ /* FIXME: This has NOT been tested. The DBX version has.. */
+ /* Generate a template for the type of this function. The
+ types of the arguments will be added as we read the symbol
+ table. */
+ struct type *new = (struct type *)
+ obstack_alloc (symbol_obstack, sizeof (struct type));
+
+ bcopy(lookup_function_type (decode_function_type (cs, cs->c_type, aux)),
+ new, sizeof(struct type));
+ SYMBOL_TYPE (sym) = new;
+ in_function_type = SYMBOL_TYPE(sym);
+#else
+ SYMBOL_TYPE(sym) =
+ lookup_function_type (decode_function_type (cs, cs->c_type, aux));
+#endif
+
SYMBOL_CLASS (sym) = LOC_BLOCK;
if (cs->c_sclass == C_STAT)
add_symbol_to_list (sym, &file_symbols);
}
break;
+#ifdef C_GLBLREG /* AMD coff */
+ case C_GLBLREG:
+#endif
case C_REG:
SYMBOL_CLASS (sym) = LOC_REGISTER;
+ SYMBOL_VALUE (sym) = SDB_REG_TO_REGNUM(cs->c_value);
add_symbol_to_list (sym, &local_symbols);
break;
case C_ARG:
SYMBOL_CLASS (sym) = LOC_ARG;
+#if 0
+ /* FIXME: This has not bee tested. */
+ /* Add parameter to function. */
+ add_param_to_type(&in_function_type,sym);
+#endif
add_symbol_to_list (sym, &local_symbols);
#if !defined (BELIEVE_PCC_PROMOTION)
/* If PCC says a parameter is a short or a char,
case C_REGPARM:
SYMBOL_CLASS (sym) = LOC_REGPARM;
+ SYMBOL_VALUE (sym) = SDB_REG_TO_REGNUM(cs->c_value);
add_symbol_to_list (sym, &local_symbols);
#if !defined (BELIEVE_PCC_PROMOTION)
/* If PCC says a parameter is a short or a char,
TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (syms->symbol);
TYPE_FIELD_BITSIZE (type, n) = 0;
}
+ /* Is this Modula-2's BOOLEAN type? Flag it as such if so. */
+ if(TYPE_NFIELDS(type) == 2 &&
+ ((!strcmp(TYPE_FIELD_NAME(type,0),"TRUE") &&
+ !strcmp(TYPE_FIELD_NAME(type,1),"FALSE")) ||
+ (!strcmp(TYPE_FIELD_NAME(type,1),"TRUE") &&
+ !strcmp(TYPE_FIELD_NAME(type,0),"FALSE"))))
+ TYPE_CODE(type) = TYPE_CODE_BOOL;
return type;
}
/* Show command. Display a warning if the language set
does not match the frame. */
void
-show_language_command (str, from_tty)
- char *str;
+show_language_command (ignore, from_tty)
+ char *ignore;
int from_tty;
{
enum language flang; /* The language of the current frame */
/* Set command. Change the current working language. */
void
-set_language_command (str, from_tty)
- char *str;
+set_language_command (ignore, from_tty)
+ char *ignore;
int from_tty;
{
int i;
/* Show command. Display a warning if the type setting does
not match the current language. */
void
-show_type_command(str, from_tty)
- char *str;
+show_type_command(ignore, from_tty)
+ char *ignore;
int from_tty;
{
if (type_check != current_language->la_type_check)
/* Set command. Change the setting for type checking. */
void
-set_type_command(str, from_tty)
- char *str;
+set_type_command(ignore, from_tty)
+ char *ignore;
int from_tty;
{
if (!strcmp(type,"on"))
return;
}
set_type_str();
- show_type_command();
+ show_type_command((char *)NULL, from_tty);
}
/* Show command. Display a warning if the range setting does
not match the current language. */
void
-show_range_command(str, from_tty)
- char *str;
+show_range_command(ignore, from_tty)
+ char *ignore;
int from_tty;
{
/* Set command. Change the setting for range checking. */
void
-set_range_command(str, from_tty)
- char *str;
+set_range_command(ignore, from_tty)
+ char *ignore;
int from_tty;
{
if (!strcmp(range,"on"))
return;
}
set_range_str();
- show_range_command();
+ show_range_command((char *)0, from_tty);
}
/* Set the status of range and type checking based on
static void
set_type_range()
{
- char *rtmp, *ttmp;
if (range_mode == range_mode_auto)
range_check = current_language->la_range_check;
void
set_lang_str()
{
- char *tmp, *prefix = "";
+ char *prefix = "";
free (language);
if (language_mode == language_mode_auto)
language_info ()
{
printf("Current Language: %s\n",language);
- show_language_command();
+ show_language_command((char *)0, 1);
printf("Type checking: %s\n",type);
- show_type_command();
+ show_type_command((char *)0, 1);
printf("Range checking: %s\n",range);
- show_range_command();
+ show_range_command((char *)0, 1);
}
\f
/* Return the result of a binary operation. */
{
int l1,l2,size,uns;
- l1=TYPE_LENGTH(VALUE_TYPE(v1));
- l2=TYPE_LENGTH(VALUE_TYPE(v2));
- size = l1 > l2 ? l1 : l2;
- uns = TYPE_UNSIGNED(VALUE_TYPE(v1)) || TYPE_UNSIGNED(VALUE_TYPE(v2));
+ l1 = TYPE_LENGTH(VALUE_TYPE(v1));
+ l2 = TYPE_LENGTH(VALUE_TYPE(v2));
switch(current_language->la_language)
{
return l1 > l2 ? VALUE_TYPE(v1) : VALUE_TYPE(v2);
break;
}
+ abort();
+ return (struct type *)0; /* For lint */
}
\f
/* This page contains functions that return format strings for
struct cmd_list_element *showchecklist = NULL;
static void
-set_check (arg, from_tty)
- char *arg;
+set_check (ignore, from_tty)
+ char *ignore;
int from_tty;
{
printf(
extern void qsort ();
extern char *getenv ();
+extern char *rindex ();
/* Functions this file defines */
static bfd *symfile_open();
psymtab_to_symtab (pst)
register struct partial_symtab *pst;
{
- register struct symtab *result;
-
/* If it's been looked up before, return it. */
if (pst->symtab)
return pst->symtab;
dont_repeat ();
- if (!query ("add symbol table from file \"%s\" at text_addr = 0x%x\n",
- name, text_addr))
+ if (!query ("add symbol table from file \"%s\" at text_addr = %s?\n",
+ name, local_hex_string (text_addr)))
error ("Not confirmed.");
symbol_file_add (name, 0, text_addr, 0);
p->counter = 0;
}
\f
+/* allocate_symtab:
+
+ Allocate and partly initialize a new symbol table. Return a pointer
+ to it. error() if no space.
+
+ Caller must set these fields:
+ LINETABLE(symtab)
+ symtab->blockvector
+ symtab->typevector
+ symtab->dirname
+ symtab->free_code
+ symtab->free_ptr
+ initialize any EXTRA_SYMTAB_INFO
+ possibly free_named_symtabs (symtab->filename);
+ symtab->next = symtab_list;
+ symtab_list = symtab;
+ */
+
+struct symtab *
+allocate_symtab(name)
+ char *name;
+{
+ register struct symtab *symtab;
+ char *c;
+
+ symtab = (struct symtab *) xmalloc (sizeof (struct symtab));
+ bzero (symtab, sizeof (*symtab));
+ symtab->filename = name;
+ symtab->fullname = NULL;
+ symtab->nlines = 0;
+ symtab->line_charpos = 0;
+ symtab->version = 0;
+ symtab->language = language_unknown; /* default */
+
+ c = rindex (name, '.');
+
+ if (!c) {
+ ; /* Don't know language of file. */
+ } else if(!strcmp(c,".mod")) {
+ symtab->language = language_m2;
+ } else if(!strcmp(c,".c") || !strcmp(c,".cc")) {
+ symtab->language = language_c;
+ }
+
+ return symtab;
+}
+\f
/* clear_symtab_users_once:
This function is run after symbol reading, or from a cleanup.
free_symtab (s);
}
else
- /* It is still possible that some breakpoints will be affected
- even though no symtab was found, since the file might have
- been compiled without debugging, and hence not be associated
- with a symtab. In order to handle this correctly, we would need
- to keep a list of text address ranges for undebuggable files.
- For now, we do nothing, since this is a fairly obscure case. */
- ;
+ {
+ /* It is still possible that some breakpoints will be affected
+ even though no symtab was found, since the file might have
+ been compiled without debugging, and hence not be associated
+ with a symtab. In order to handle this correctly, we would need
+ to keep a list of text address ranges for undebuggable files.
+ For now, we do nothing, since this is a fairly obscure case. */
+ ;
+ }
/* FIXME, what about the misc function vector? */
return blewit;