/* DWARF 2 debugging format support for GDB.
- Copyright 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
Inc. with support from Florida State University (under contract
#include "defs.h"
#include "bfd.h"
+#include "elf-bfd.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "symfile.h"
/* The data in a compilation unit header looks like this. */
struct comp_unit_head
{
- int length;
+ unsigned int length;
short version;
- int abbrev_offset;
+ unsigned int abbrev_offset;
unsigned char addr_size;
};
whatever scope is currently getting read. */
static int address_size;
+/* Some elf32 object file formats while linked for a 32 bit address
+ space contain debug information that has assumed 64 bit
+ addresses. Eg 64 bit MIPS target produced by GCC/GAS/LD where the
+ symbol table contains 32bit address values while its .debug_info
+ section contains 64 bit address values.
+ ADDRESS_SIGNIFICANT_SIZE specifies the number significant bits in
+ the ADDRESS_SIZE bytes read from the file */
+static int address_significant_size;
+
/* Externals references. */
extern int info_verbose; /* From main.c; nonzero => verbose */
int comp_unit_has_pc_info;
CORE_ADDR lowpc, highpc;
+ /* Number of bytes of any addresses that are signficant */
+ address_significant_size = get_elf_backend_data (abfd)->s->arch_size / 8;
+
info_ptr = dwarf_info_buffer;
abbrev_ptr = dwarf_abbrev_buffer;
error ("Dwarf Error: wrong version in compilation unit header.");
return;
}
+ if (cu_header.abbrev_offset >= dwarf_abbrev_size)
+ {
+ error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6).",
+ (long) cu_header.abbrev_offset,
+ (long) (beg_of_comp_unit - dwarf_info_buffer));
+ return;
+ }
+ if (beg_of_comp_unit + cu_header.length + 4
+ > dwarf_info_buffer + dwarf_info_size)
+ {
+ error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0).",
+ (long) cu_header.length,
+ (long) (beg_of_comp_unit - dwarf_info_buffer));
+ return;
+ }
+ if (address_size < address_significant_size)
+ {
+ error ("Dwarf Error: bad address size (%ld) in compilation unit header (offset 0x%lx + 11).",
+ (long) cu_header.addr_size,
+ (long) (beg_of_comp_unit - dwarf_info_buffer));
+ }
/* Read the abbrevs for this compilation unit into a table */
dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
/* Store the function that reads in the rest of the symbol table */
pst->read_symtab = dwarf2_psymtab_to_symtab;
- /* Read the rest of the partial symbols from this comp unit */
- info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc);
-
- /* If the compilation unit didn't have an explicit address range,
- then use the information extracted from its child dies. */
- if (!comp_unit_has_pc_info)
+ /* Check if comp unit has_children.
+ If so, read the rest of the partial symbols from this comp unit.
+ If not, there's no more debug_info for this comp unit. */
+ if (comp_unit_die.has_children)
{
- comp_unit_die.lowpc = lowpc;
- comp_unit_die.highpc = highpc;
- }
+ info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc);
+
+ /* If the compilation unit didn't have an explicit address range,
+ then use the information extracted from its child dies. */
+ if (!comp_unit_has_pc_info)
+ {
+ comp_unit_die.lowpc = lowpc;
+ comp_unit_die.highpc = highpc;
+ }
+ }
pst->textlow = comp_unit_die.lowpc + baseaddr;
pst->texthigh = comp_unit_die.highpc + baseaddr;
{
bfd *abfd = objfile->obfd;
struct partial_die_info pdi;
- int nesting_level = 1; /* we've already read in comp_unit_die */
- int has_pc_info;
+ /* This function is called after we've read in the comp_unit_die in
+ order to read its children. We start the nesting level at 1 since
+ we have pushed 1 level down in order to read the comp unit's children.
+ The comp unit itself is at level 0, so we stop reading when we pop
+ back to that level. */
+
+ int nesting_level = 1;
+ int has_pc_info;
+
*lowpc = ((CORE_ADDR) -1);
*highpc = ((CORE_ADDR) 0);
case DW_TAG_subprogram:
if (pdi->is_external)
{
- prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
- mst_text, objfile);
+ /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
+ mst_text, objfile);*/
add_psymbol_to_list (pdi->name, strlen (pdi->name),
VAR_NAMESPACE, LOC_BLOCK,
&objfile->global_psymbols,
}
else
{
- prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
- mst_file_text, objfile);
+ /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
+ mst_file_text, objfile);*/
add_psymbol_to_list (pdi->name, strlen (pdi->name),
VAR_NAMESPACE, LOC_BLOCK,
&objfile->static_psymbols,
if (pdi->locdesc == NULL)
return;
addr = decode_locdesc (pdi->locdesc, objfile);
- prim_record_minimal_symbol (pdi->name, addr + baseaddr,
- mst_file_data, objfile);
+ /*prim_record_minimal_symbol (pdi->name, addr + baseaddr,
+ mst_file_data, objfile);*/
add_psymbol_to_list (pdi->name, strlen (pdi->name),
VAR_NAMESPACE, LOC_STATIC,
&objfile->static_psymbols,
back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
buildsym_init ();
- make_cleanup (really_free_pendings, NULL);
+ make_cleanup ((make_cleanup_func) really_free_pendings, NULL);
/* read in the comp_unit header */
cu_header.length = read_4_bytes (abfd, info_ptr);
dies = read_comp_unit (info_ptr, abfd);
- make_cleanup (free_die_list, dies);
+ make_cleanup ((make_cleanup_func) free_die_list, dies);
/* Do line number decoding in read_file_scope () */
process_die (dies, objfile);
set_cu_language (DW_UNSND (attr));
}
+ /* We assume that we're processing GCC output. */
+ processing_gcc_compilation = 2;
#if 0
/* FIXME:Do something here. */
if (dip->at_producer != NULL)
attr = dwarf_attr (die, DW_AT_bit_size);
if (attr)
{
- fp->bitsize = DW_UNSND (attr);
+ FIELD_BITSIZE (*fp) = DW_UNSND (attr);
}
else
{
- fp->bitsize = 0;
+ FIELD_BITSIZE (*fp) = 0;
}
/* Get bit offset of field. */
attr = dwarf_attr (die, DW_AT_data_member_location);
if (attr)
{
- fp->bitpos =
+ FIELD_BITPOS (*fp) =
decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
}
else
- fp->bitpos = 0;
+ FIELD_BITPOS (*fp) = 0;
attr = dwarf_attr (die, DW_AT_bit_offset);
if (attr)
{
anonymous object to the MSB of the field. We don't
have to do anything special since we don't need to
know the size of the anonymous object. */
- fp->bitpos += DW_UNSND (attr);
+ FIELD_BITPOS (*fp) += DW_UNSND (attr);
}
else
{
bit field. */
anonymous_size = TYPE_LENGTH (fp->type);
}
- fp->bitpos +=
- anonymous_size * bits_per_byte - bit_offset - fp->bitsize;
+ FIELD_BITPOS (*fp) += anonymous_size * bits_per_byte
+ - bit_offset - FIELD_BITSIZE (*fp);
}
}
complain (&dwarf2_bad_static_member_name, physname);
}
- fp->bitpos = -1;
- fp->bitsize = (long) obsavestring (physname, strlen (physname),
- &objfile->type_obstack);
- fp->type = die_type (die, objfile);
- fp->name = obsavestring (fieldname, strlen (fieldname),
+ SET_FIELD_PHYSNAME (*fp, obsavestring (physname, strlen (physname),
+ &objfile->type_obstack));
+ FIELD_TYPE (*fp) = die_type (die, objfile);
+ FIELD_NAME (*fp) = obsavestring (fieldname, strlen (fieldname),
&objfile->type_obstack);
}
else if (die->tag == DW_TAG_inheritance)
/* C++ base class field. */
attr = dwarf_attr (die, DW_AT_data_member_location);
if (attr)
- fp->bitpos = decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
- fp->bitsize = 0;
- fp->type = die_type (die, objfile);
- fp->name = type_name_no_tag (fp->type);
+ FIELD_BITPOS (*fp) = decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
+ FIELD_BITSIZE (*fp) = 0;
+ FIELD_TYPE (*fp) = die_type (die, objfile);
+ FIELD_NAME (*fp) = type_name_no_tag (fp->type);
fip->nbaseclasses++;
}
}
(fip->nfnfields + DW_FIELD_ALLOC_CHUNK)
* sizeof (struct fnfieldlist));
if (fip->nfnfields == 0)
- make_cleanup (free_current_contents, &fip->fnfieldlists);
+ make_cleanup ((make_cleanup_func) free_current_contents,
+ &fip->fnfieldlists);
}
flp = &fip->fnfieldlists[fip->nfnfields];
flp->name = fieldname;
* sizeof (struct field));
}
- fields[num_fields].name = SYMBOL_NAME (sym);
- fields[num_fields].type = NULL;
- fields[num_fields].bitpos = SYMBOL_VALUE (sym);
- fields[num_fields].bitsize = 0;
+ FIELD_NAME (fields[num_fields]) = SYMBOL_NAME (sym);
+ FIELD_TYPE (fields[num_fields]) = NULL;
+ FIELD_BITPOS (fields[num_fields]) = SYMBOL_VALUE (sym);
+ FIELD_BITSIZE (fields[num_fields]) = 0;
num_fields++;
}
/* Default bounds to an array with unspecified length. */
low = 0;
high = -1;
- if (cu_language == DW_LANG_Fortran77
- || cu_language == DW_LANG_Fortran90)
+ if (cu_language == language_fortran)
{
/* FORTRAN implies a lower bound of 1, if not given. */
low = 1;
xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK)
* sizeof (struct type *));
if (ndim == 0)
- make_cleanup (free_current_contents, &range_types);
+ make_cleanup ((make_cleanup_func) free_current_contents,
+ &range_types);
}
range_types[ndim++] = create_range_type (NULL, index_type, low, high);
}
}
type = die_type (die, objfile);
ftype = lookup_function_type (type);
+
+ /* All functions in C++ have prototypes. */
attr = dwarf_attr (die, DW_AT_prototyped);
- if (attr && (DW_UNSND (attr) != 0))
+ if ((attr && (DW_UNSND (attr) != 0))
+ || cu_language == language_cplus)
TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;
if (die->has_children)
{
CORE_ADDR retval = 0;
- if (address_size == 4)
+ switch (address_size)
{
+ case 4:
retval = bfd_get_32 (abfd, (bfd_byte *) buf);
- } else { /* *THE* alternative is 8, right? */
+ break;
+ case 8:
retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+ break;
+ default:
+ /* *THE* alternative is 8, right? */
+ abort ();
+ }
+ /* If the address being read is larger than the address that is
+ applicable for the object file format then mask it down to the
+ correct size. Take care to avoid unnecessary shift or shift
+ overflow */
+ if (address_size > address_significant_size
+ && address_significant_size < sizeof (CORE_ADDR))
+ {
+ CORE_ADDR mask = ((CORE_ADDR) 0) - 1;
+ retval &= ~(mask << (address_significant_size * 8));
}
return retval;
}
{
case DW_LANG_C89:
case DW_LANG_C:
- case DW_LANG_Fortran77:
cu_language = language_c;
break;
case DW_LANG_C_plus_plus:
cu_language = language_cplus;
break;
+ case DW_LANG_Fortran77:
+ case DW_LANG_Fortran90:
+ cu_language = language_fortran;
+ break;
case DW_LANG_Mips_Assembler:
cu_language = language_asm;
break;
case DW_LANG_Ada83:
case DW_LANG_Cobol74:
case DW_LANG_Cobol85:
-#if 0
- case DW_LANG_Fortran77: /* moved up top for now */
-#endif
- case DW_LANG_Fortran90:
case DW_LANG_Pascal83:
case DW_LANG_Modula2:
default:
line_ptr += 1;
lh.standard_opcode_lengths = (unsigned char *)
xmalloc (lh.opcode_base * sizeof (unsigned char));
- back_to = make_cleanup (free_current_contents, &lh.standard_opcode_lengths);
+ back_to = make_cleanup ((make_cleanup_func) free_current_contents,
+ &lh.standard_opcode_lengths);
lh.standard_opcode_lengths[0] = 1;
for (i = 1; i < lh.opcode_base; ++i)
xrealloc (dirs.dirs,
(dirs.num_dirs + DIR_ALLOC_CHUNK) * sizeof (char *));
if (dirs.num_dirs == 0)
- make_cleanup (free_current_contents, &dirs.dirs);
+ make_cleanup ((make_cleanup_func) free_current_contents, &dirs.dirs);
}
dirs.dirs[dirs.num_dirs++] = cur_dir;
}
(files.num_files + FILE_ALLOC_CHUNK)
* sizeof (struct fileinfo));
if (files.num_files == 0)
- make_cleanup (free_current_contents, &files.files);
+ make_cleanup ((make_cleanup_func) free_current_contents,
+ &files.files);
}
files.files[files.num_files].name = cur_file;
files.files[files.num_files].dir =
while (line_ptr < line_end)
{
/* state machine registers */
- unsigned int address = 0;
+ CORE_ADDR address = 0;
unsigned int file = 1;
unsigned int line = 1;
unsigned int column = 0;
(files.num_files + FILE_ALLOC_CHUNK)
* sizeof (struct fileinfo));
if (files.num_files == 0)
- make_cleanup (free_current_contents, &files.files);
+ make_cleanup ((make_cleanup_func) free_current_contents,
+ &files.files);
}
files.files[files.num_files].name = cur_file;
files.files[files.num_files].dir =
}
static char *
-dwarf_bool_name (bool)
- unsigned bool;
+dwarf_bool_name (mybool)
+ unsigned mybool;
{
- if (bool)
+ if (mybool)
return "TRUE";
else
return "FALSE";
case DW_FORM_ref_addr:
case DW_FORM_addr:
fprintf (stderr, "address: ");
- print_address_numeric (DW_ADDR (&die->attrs[i]), 1, stderr);
+ print_address_numeric (DW_ADDR (&die->attrs[i]), 1, gdb_stderr);
break;
case DW_FORM_block2:
case DW_FORM_block4: