/* DWARF 2 debugging format support for GDB.
- Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
#include "bcache.h"
#include <fcntl.h>
#include "gdb_string.h"
+#include "gdb_assert.h"
#include <sys/types.h>
#ifndef DWARF2_REG_TO_REGNUM
static file_ptr dwarf_loc_offset;
static file_ptr dwarf_macinfo_offset;
static file_ptr dwarf_str_offset;
+file_ptr dwarf_frame_offset;
+file_ptr dwarf_eh_frame_offset;
static unsigned int dwarf_info_size;
static unsigned int dwarf_abbrev_size;
static unsigned int dwarf_loc_size;
static unsigned int dwarf_macinfo_size;
static unsigned int dwarf_str_size;
+unsigned int dwarf_frame_size;
+unsigned int dwarf_eh_frame_size;
/* names of the debugging sections */
#define LOC_SECTION ".debug_loc"
#define MACINFO_SECTION ".debug_macinfo"
#define STR_SECTION ".debug_str"
+#define FRAME_SECTION ".debug_frame"
+#define EH_FRAME_SECTION ".eh_frame"
/* local data types */
u;
};
+struct function_range
+{
+ const char *name;
+ CORE_ADDR lowpc, highpc;
+ int seen_line;
+ struct function_range *next;
+};
+
+static struct function_range *cu_first_fn, *cu_last_fn, *cu_cached_fn;
+
/* Get at parts of an attribute structure */
#define DW_STRING(attr) ((attr)->u.str)
static char *dwarf_info_buffer;
static char *dwarf_abbrev_buffer;
static char *dwarf_line_buffer;
+static char *dwarf_str_buffer;
/* A zeroed version of a partial die for initialization purposes. */
static struct partial_die_info zeroed_partial_die;
/* Pointer to start of dwarf line buffer for the objfile. */
char *dwarf_line_buffer;
+
+ /* Pointer to start of dwarf string buffer for the objfile. */
+
+ char *dwarf_str_buffer;
+
+ /* Size of dwarf string section for the objfile. */
+
+ unsigned int dwarf_str_size;
};
#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
#define DWARF_ABBREV_BUFFER(p) (PST_PRIVATE(p)->dwarf_abbrev_buffer)
#define DWARF_ABBREV_SIZE(p) (PST_PRIVATE(p)->dwarf_abbrev_size)
#define DWARF_LINE_BUFFER(p) (PST_PRIVATE(p)->dwarf_line_buffer)
+#define DWARF_STR_BUFFER(p) (PST_PRIVATE(p)->dwarf_str_buffer)
+#define DWARF_STR_SIZE(p) (PST_PRIVATE(p)->dwarf_str_size)
/* Maintain an array of referenced fundamental types for the current
compilation unit being read. For DWARF version 1, we have to construct
int nfnfields;
};
-/* FIXME: Kludge to mark a varargs function type for C++ member function
- argument processing. */
-#define TYPE_FLAG_VARARGS (1 << 10)
-
-/* Dwarf2 has no clean way to discern C++ static and non-static member
- functions. G++ helps GDB by marking the first parameter for non-static
- member functions (which is the this pointer) as artificial.
- We pass this information between dwarf2_add_member_fn and
- read_subroutine_type via TYPE_FIELD_ARTIFICIAL. */
-#define TYPE_FIELD_ARTIFICIAL TYPE_FIELD_BITPOS
-
/* Various complaints about symbol reading that don't abort the process */
static struct complaint dwarf2_const_ignored =
{
"unsupported const value attribute form: '%s'", 0, 0
};
-
-/* Externals references. */
-extern int info_verbose; /* From main.c; nonzero => verbose */
+static struct complaint dwarf2_misplaced_line_number =
+{
+ "misplaced first line number at 0x%lx for '%s'", 0, 0
+};
/* local function prototypes */
static void psymtab_to_symtab_1 (struct partial_symtab *);
-static char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int);
+char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int);
static void dwarf2_read_abbrevs (bfd *, unsigned int);
static char *read_attribute (struct attribute *, struct attr_abbrev *,
bfd *, char *, const struct comp_unit_head *);
+static char *read_attribute_value (struct attribute *, unsigned,
+ bfd *, char *, const struct comp_unit_head *);
+
static unsigned int read_1_byte (bfd *, char *);
static int read_1_signed_byte (bfd *, char *);
static char *read_string (bfd *, char *, unsigned int *);
+static char *read_indirect_string (bfd *, char *, const struct comp_unit_head *,
+ unsigned int *);
+
static unsigned long read_unsigned_leb128 (bfd *, char *, unsigned int *);
static long read_signed_leb128 (bfd *, char *, unsigned int *);
static struct die_info *dwarf_alloc_die (void);
+static void initialize_cu_func_list (void);
+
+static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR);
+
/* Try to locate the sections we need for DWARF 2 debugging
information and return true if we have enough to do something. */
dwarf2_has_info (bfd *abfd)
{
dwarf_info_offset = dwarf_abbrev_offset = dwarf_line_offset = 0;
+ dwarf_str_offset = 0;
+ dwarf_frame_offset = dwarf_eh_frame_offset = 0;
bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
if (dwarf_info_offset && dwarf_abbrev_offset)
{
dwarf_str_offset = sectp->filepos;
dwarf_str_size = bfd_get_section_size_before_reloc (sectp);
}
+ else if (STREQ (sectp->name, FRAME_SECTION))
+ {
+ dwarf_frame_offset = sectp->filepos;
+ dwarf_frame_size = bfd_get_section_size_before_reloc (sectp);
+ }
+ else if (STREQ (sectp->name, EH_FRAME_SECTION))
+ {
+ dwarf_eh_frame_offset = sectp->filepos;
+ dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp);
+ }
}
/* Build a partial symbol table. */
dwarf_line_offset,
dwarf_line_size);
+ if (dwarf_str_offset)
+ dwarf_str_buffer = dwarf2_read_section (objfile,
+ dwarf_str_offset,
+ dwarf_str_size);
+ else
+ dwarf_str_buffer = NULL;
+
if (mainline
|| (objfile->global_psymbols.size == 0
&& objfile->static_psymbols.size == 0))
DWARF_ABBREV_BUFFER (pst) = dwarf_abbrev_buffer;
DWARF_ABBREV_SIZE (pst) = dwarf_abbrev_size;
DWARF_LINE_BUFFER (pst) = dwarf_line_buffer;
+ DWARF_STR_BUFFER (pst) = dwarf_str_buffer;
+ DWARF_STR_SIZE (pst) = dwarf_str_size;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
/* Store the function that reads in the rest of the symbol table */
dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER (pst);
dwarf_abbrev_size = DWARF_ABBREV_SIZE (pst);
dwarf_line_buffer = DWARF_LINE_BUFFER (pst);
+ dwarf_str_buffer = DWARF_STR_BUFFER (pst);
+ dwarf_str_size = DWARF_STR_SIZE (pst);
baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
cu_header_offset = offset;
info_ptr = dwarf_info_buffer + offset;
}
}
+static void
+initialize_cu_func_list (void)
+{
+ cu_first_fn = cu_last_fn = cu_cached_fn = NULL;
+}
+
static void
read_file_scope (struct die_info *die, struct objfile *objfile,
const struct comp_unit_head *cu_header)
start_symtab (name, comp_dir, lowpc);
record_debugformat ("DWARF 2");
- /* Decode line number information if present. */
- attr = dwarf_attr (die, DW_AT_stmt_list);
- if (attr)
- {
- line_offset = DW_UNSND (attr);
- dwarf_decode_lines (line_offset, comp_dir, abfd, cu_header);
- }
+ initialize_cu_func_list ();
/* Process all dies in compilation unit. */
if (die->has_children)
child_die = sibling_die (child_die);
}
}
+
+ /* Decode line number information if present. */
+ attr = dwarf_attr (die, DW_AT_stmt_list);
+ if (attr)
+ {
+ line_offset = DW_UNSND (attr);
+ dwarf_decode_lines (line_offset, comp_dir, abfd, cu_header);
+ }
+}
+
+static void
+add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc)
+{
+ struct function_range *thisfn;
+
+ thisfn = (struct function_range *)
+ obstack_alloc (&dwarf2_tmp_obstack, sizeof (struct function_range));
+ thisfn->name = name;
+ thisfn->lowpc = lowpc;
+ thisfn->highpc = highpc;
+ thisfn->seen_line = 0;
+ thisfn->next = NULL;
+
+ if (cu_last_fn == NULL)
+ cu_first_fn = thisfn;
+ else
+ cu_last_fn->next = thisfn;
+
+ cu_last_fn = thisfn;
}
static void
lowpc += baseaddr;
highpc += baseaddr;
+ /* Record the function range for dwarf_decode_lines. */
+ add_to_cu_func_list (name, lowpc, highpc);
+
if (objfile->ei.entry_point >= lowpc &&
objfile->ei.entry_point < highpc)
{
arg_types[iparams] = TYPE_FIELD_TYPE (die->type, iparams);
/* Set last entry in argument type vector. */
- if (TYPE_FLAGS (die->type) & TYPE_FLAG_VARARGS)
+ if (TYPE_VARARGS (die->type))
arg_types[nparams] = NULL;
else
arg_types[nparams] = dwarf2_fundamental_type (objfile, FT_VOID);
}
}
+ /* Check for artificial methods. */
+ attr = dwarf_attr (die, DW_AT_artificial);
+ if (attr && DW_UNSND (attr) != 0)
+ fnp->is_artificial = 1;
+
/* Get index in virtual function table if it is a virtual member function. */
attr = dwarf_attr (die, DW_AT_vtable_elem_location);
if (attr)
TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
}
- die->type = type;
+ finish_cv_type (die->type);
}
/* Given a pointer to a die which begins an enumeration, process all
else if (attr->form == DW_FORM_udata
|| attr->form == DW_FORM_data1
|| attr->form == DW_FORM_data2
- || attr->form == DW_FORM_data4)
+ || attr->form == DW_FORM_data4
+ || attr->form == DW_FORM_data8)
{
low = DW_UNSND (attr);
}
else if (attr->form == DW_FORM_udata
|| attr->form == DW_FORM_data1
|| attr->form == DW_FORM_data2
- || attr->form == DW_FORM_data4)
+ || attr->form == DW_FORM_data4
+ || attr->form == DW_FORM_data8)
{
high = DW_UNSND (attr);
}
while (ndim-- > 0)
type = create_array_type (NULL, type, range_types[ndim]);
+ /* Understand Dwarf2 support for vector types (like they occur on
+ the PowerPC w/ AltiVec). Gcc just adds another attribute to the
+ array type. This is not part of the Dwarf2/3 standard yet, but a
+ custom vendor extension. The main difference between a regular
+ array and the vector variant is that vectors are passed by value
+ to functions. */
+ attr = dwarf_attr (die, DW_AT_GNU_vector);
+ if (attr)
+ TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
+
do_cleanups (back_to);
/* Install the type in the die. */
}
else
{
- length = 1;
+ /* check for the DW_AT_byte_size attribute */
+ attr = dwarf_attr (die, DW_AT_byte_size);
+ if (attr)
+ {
+ length = DW_UNSND (attr);
+ }
+ else
+ {
+ length = 1;
+ }
}
index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
range_type = create_range_type (NULL, index_type, 1, length);
- char_type = dwarf2_fundamental_type (objfile, FT_CHAR);
- type = create_string_type (char_type, range_type);
+ if (cu_language == language_fortran)
+ {
+ /* Need to create a unique string type for bounds
+ information */
+ type = create_string_type (0, range_type);
+ }
+ else
+ {
+ char_type = dwarf2_fundamental_type (objfile, FT_CHAR);
+ type = create_string_type (char_type, range_type);
+ }
die->type = type;
}
read_typedef (struct die_info *die, struct objfile *objfile,
const struct comp_unit_head *cu_header)
{
- struct type *type;
+ struct attribute *attr;
+ char *name = NULL;
if (!die->type)
{
- struct attribute *attr;
- struct type *xtype;
-
- xtype = die_type (die, objfile, cu_header);
-
- type = alloc_type (objfile);
- TYPE_CODE (type) = TYPE_CODE_TYPEDEF;
- TYPE_FLAGS (type) |= TYPE_FLAG_TARGET_STUB;
- TYPE_TARGET_TYPE (type) = xtype;
attr = dwarf_attr (die, DW_AT_name);
if (attr && DW_STRING (attr))
- TYPE_NAME (type) = obsavestring (DW_STRING (attr),
- strlen (DW_STRING (attr)),
- &objfile->type_obstack);
-
- die->type = type;
+ {
+ name = DW_STRING (attr);
+ }
+ die->type = init_type (TYPE_CODE_TYPEDEF, 0, TYPE_FLAG_TARGET_STUB, name, objfile);
+ TYPE_TARGET_TYPE (die->type) = die_type (die, objfile, cu_header);
}
}
if (attr && DW_STRING (attr))
{
enum type_code code = TYPE_CODE_INT;
- int is_unsigned = 0;
+ int type_flags = 0;
switch (encoding)
{
case DW_ATE_address:
/* Turn DW_ATE_address into a void * pointer. */
code = TYPE_CODE_PTR;
- is_unsigned = 1;
+ type_flags |= TYPE_FLAG_UNSIGNED;
break;
case DW_ATE_boolean:
code = TYPE_CODE_BOOL;
- is_unsigned = 1;
+ type_flags |= TYPE_FLAG_UNSIGNED;
break;
case DW_ATE_complex_float:
code = TYPE_CODE_COMPLEX;
break;
case DW_ATE_unsigned:
case DW_ATE_unsigned_char:
- is_unsigned = 1;
+ type_flags |= TYPE_FLAG_UNSIGNED;
break;
default:
complain (&dwarf2_unsupported_at_encoding,
dwarf_type_encoding_name (encoding));
break;
}
- type = init_type (code, size, is_unsigned, DW_STRING (attr), objfile);
+ type = init_type (code, size, type_flags, DW_STRING (attr), objfile);
if (encoding == DW_ATE_address)
TYPE_TARGET_TYPE (type) = dwarf2_fundamental_type (objfile, FT_VOID);
+ else if (encoding == DW_ATE_complex_float)
+ {
+ if (size == 32)
+ TYPE_TARGET_TYPE (type)
+ = dwarf2_fundamental_type (objfile, FT_EXT_PREC_FLOAT);
+ else if (size == 16)
+ TYPE_TARGET_TYPE (type)
+ = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT);
+ else if (size == 8)
+ TYPE_TARGET_TYPE (type)
+ = dwarf2_fundamental_type (objfile, FT_FLOAT);
+ }
}
else
{
/* Read the contents of the section at OFFSET and of size SIZE from the
object file specified by OBJFILE into the psymbol_obstack and return it. */
-static char *
+char *
dwarf2_read_section (struct objfile *objfile, file_ptr offset,
unsigned int size)
{
buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size);
if ((bfd_seek (abfd, offset, SEEK_SET) != 0) ||
- (bfd_read (buf, size, 1, abfd) != size))
+ (bfd_bread (buf, size, abfd) != size))
{
buf = NULL;
error ("Dwarf Error: Can't read DWARF data from '%s'",
return info_ptr;
}
-/* Read an attribute described by an abbreviated attribute. */
+/* Read an attribute value described by an attribute form. */
static char *
-read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
+read_attribute_value (struct attribute *attr, unsigned form,
bfd *abfd, char *info_ptr,
const struct comp_unit_head *cu_header)
{
unsigned int bytes_read;
struct dwarf_block *blk;
- attr->name = abbrev->name;
- attr->form = abbrev->form;
- switch (abbrev->form)
+ attr->form = form;
+ switch (form)
{
case DW_FORM_addr:
case DW_FORM_ref_addr:
DW_STRING (attr) = read_string (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
+ case DW_FORM_strp:
+ DW_STRING (attr) = read_indirect_string (abfd, info_ptr, cu_header,
+ &bytes_read);
+ info_ptr += bytes_read;
+ break;
case DW_FORM_block:
blk = dwarf_alloc_block ();
blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
- case DW_FORM_strp:
case DW_FORM_indirect:
+ form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ info_ptr = read_attribute_value (attr, form, abfd, info_ptr, cu_header);
+ break;
default:
error ("Dwarf Error: Cannot handle %s in DWARF reader.",
- dwarf_form_name (abbrev->form));
+ dwarf_form_name (form));
}
return info_ptr;
}
+/* Read an attribute described by an abbreviated attribute. */
+
+static char *
+read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
+ bfd *abfd, char *info_ptr,
+ const struct comp_unit_head *cu_header)
+{
+ attr->name = abbrev->name;
+ return read_attribute_value (attr, abbrev->form, abfd, info_ptr, cu_header);
+}
+
/* read dwarf information from a buffer */
static unsigned int
/* If the size of a host char is 8 bits, we can return a pointer
to the buffer, otherwise we have to copy the data to a buffer
allocated on the temporary obstack. */
-#if HOST_CHAR_BIT == 8
+ gdb_assert (HOST_CHAR_BIT == 8);
return buf;
-#else
- char *ret;
- unsigned int i;
-
- ret = obstack_alloc (&dwarf2_tmp_obstack, size);
- for (i = 0; i < size; ++i)
- {
- ret[i] = bfd_get_8 (abfd, (bfd_byte *) buf);
- buf++;
- }
- return ret;
-#endif
}
static char *
/* If the size of a host char is 8 bits, we can return a pointer
to the string, otherwise we have to copy the string to a buffer
allocated on the temporary obstack. */
-#if HOST_CHAR_BIT == 8
+ gdb_assert (HOST_CHAR_BIT == 8);
if (*buf == '\0')
{
*bytes_read_ptr = 1;
}
*bytes_read_ptr = strlen (buf) + 1;
return buf;
-#else
- int byte;
- unsigned int i = 0;
+}
- while ((byte = bfd_get_8 (abfd, (bfd_byte *) buf)) != 0)
+static char *
+read_indirect_string (bfd *abfd, char *buf,
+ const struct comp_unit_head *cu_header,
+ unsigned int *bytes_read_ptr)
+{
+ LONGEST str_offset = read_offset (abfd, buf, cu_header,
+ (int *) bytes_read_ptr);
+
+ if (dwarf_str_buffer == NULL)
{
- obstack_1grow (&dwarf2_tmp_obstack, byte);
- i++;
- buf++;
+ error ("DW_FORM_strp used without .debug_str section");
+ return NULL;
}
- if (i == 0)
+ if (str_offset >= dwarf_str_size)
{
- *bytes_read_ptr = 1;
+ error ("DW_FORM_strp pointing outside of .debug_str section");
return NULL;
}
- obstack_1grow (&dwarf2_tmp_obstack, '\0');
- *bytes_read_ptr = i + 1;
- return obstack_finish (&dwarf2_tmp_obstack);
-#endif
+ gdb_assert (HOST_CHAR_BIT == 8);
+ if (dwarf_str_buffer[str_offset] == '\0')
+ return NULL;
+ return dwarf_str_buffer + str_offset;
}
static unsigned long
break;
case DW_LANG_Fortran77:
case DW_LANG_Fortran90:
+ case DW_LANG_Fortran95:
cu_language = language_fortran;
break;
case DW_LANG_Mips_Assembler:
char **dirs;
};
+/* This function exists to work around a bug in certain compilers
+ (particularly GCC 2.95), in which the first line number marker of a
+ function does not show up until after the prologue, right before
+ the second line number marker. This function shifts ADDRESS down
+ to the beginning of the function if necessary, and is called on
+ addresses passed to record_line. */
+
+static CORE_ADDR
+check_cu_functions (CORE_ADDR address)
+{
+ struct function_range *fn;
+
+ /* Find the function_range containing address. */
+ if (!cu_first_fn)
+ return address;
+
+ if (!cu_cached_fn)
+ cu_cached_fn = cu_first_fn;
+
+ fn = cu_cached_fn;
+ while (fn)
+ if (fn->lowpc <= address && fn->highpc > address)
+ goto found;
+ else
+ fn = fn->next;
+
+ fn = cu_first_fn;
+ while (fn && fn != cu_cached_fn)
+ if (fn->lowpc <= address && fn->highpc > address)
+ goto found;
+ else
+ fn = fn->next;
+
+ return address;
+
+ found:
+ if (fn->seen_line)
+ return address;
+ if (address != fn->lowpc)
+ complain (&dwarf2_misplaced_line_number,
+ (unsigned long) address, fn->name);
+ fn->seen_line = 1;
+ return fn->lowpc;
+}
+
static void
dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
const struct comp_unit_head *cu_header)
{
op_code = read_1_byte (abfd, line_ptr);
line_ptr += 1;
- switch (op_code)
+
+ if (op_code >= lh.opcode_base)
+ { /* Special operand. */
+ adj_opcode = op_code - lh.opcode_base;
+ address += (adj_opcode / lh.line_range)
+ * lh.minimum_instruction_length;
+ line += lh.line_base + (adj_opcode % lh.line_range);
+ /* append row to matrix using current values */
+ address = check_cu_functions (address);
+ record_line (current_subfile, line, address);
+ basic_block = 1;
+ }
+ else switch (op_code)
{
case DW_LNS_extended_op:
line_ptr += 1; /* ignore length */
{
case DW_LNE_end_sequence:
end_sequence = 1;
- /* Don't call record_line here. The end_sequence
- instruction provides the address of the first byte
- *after* the last line in the sequence; it's not the
- address of any real source line. However, the GDB
- linetable structure only records the starts of lines,
- not the ends. This is a weakness of GDB. */
+ record_line (current_subfile, 0, address);
break;
case DW_LNE_set_address:
address = read_address (abfd, line_ptr, cu_header, &bytes_read);
}
break;
case DW_LNS_copy:
+ address = check_cu_functions (address);
record_line (current_subfile, line, address);
basic_block = 0;
break;
address += read_2_bytes (abfd, line_ptr);
line_ptr += 2;
break;
- default: /* special operand */
- adj_opcode = op_code - lh.opcode_base;
- address += (adj_opcode / lh.line_range)
- * lh.minimum_instruction_length;
- line += lh.line_base + (adj_opcode % lh.line_range);
- /* append row to matrix using current values */
- record_line (current_subfile, line, address);
- basic_block = 1;
+ default:
+ { /* Unknown standard opcode, ignore it. */
+ int i;
+ for (i = 0; i < lh.standard_opcode_lengths[op_code]; i++)
+ {
+ (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ }
+ }
}
}
}
return "DW_AT_body_begin";
case DW_AT_body_end:
return "DW_AT_body_end";
+ case DW_AT_GNU_vector:
+ return "DW_AT_GNU_vector";
default:
return "DW_AT_<unknown>";
}
return "DW_CFA_def_cfa_register";
case DW_CFA_def_cfa_offset:
return "DW_CFA_def_cfa_offset";
+
+ /* DWARF 3 */
+ case DW_CFA_def_cfa_expression:
+ return "DW_CFA_def_cfa_expression";
+ case DW_CFA_expression:
+ return "DW_CFA_expression";
+ case DW_CFA_offset_extended_sf:
+ return "DW_CFA_offset_extended_sf";
+ case DW_CFA_def_cfa_sf:
+ return "DW_CFA_def_cfa_sf";
+ case DW_CFA_def_cfa_offset_sf:
+ return "DW_CFA_def_cfa_offset_sf";
+
/* SGI/MIPS specific */
case DW_CFA_MIPS_advance_loc8:
return "DW_CFA_MIPS_advance_loc8";
+
+ /* GNU extensions */
+ case DW_CFA_GNU_window_save:
+ return "DW_CFA_GNU_window_save";
+ case DW_CFA_GNU_args_size:
+ return "DW_CFA_GNU_args_size";
+ case DW_CFA_GNU_negative_offset_extended:
+ return "DW_CFA_GNU_negative_offset_extended";
+
default:
return "DW_CFA_<unknown>";
}
{
unsigned int i;
- fprintf (stderr, "Die: %s (abbrev = %d, offset = %d)\n",
+ fprintf_unfiltered (gdb_stderr, "Die: %s (abbrev = %d, offset = %d)\n",
dwarf_tag_name (die->tag), die->abbrev, die->offset);
- fprintf (stderr, "\thas children: %s\n",
+ fprintf_unfiltered (gdb_stderr, "\thas children: %s\n",
dwarf_bool_name (die->has_children));
- fprintf (stderr, "\tattributes:\n");
+ fprintf_unfiltered (gdb_stderr, "\tattributes:\n");
for (i = 0; i < die->num_attrs; ++i)
{
- fprintf (stderr, "\t\t%s (%s) ",
+ fprintf_unfiltered (gdb_stderr, "\t\t%s (%s) ",
dwarf_attr_name (die->attrs[i].name),
dwarf_form_name (die->attrs[i].form));
switch (die->attrs[i].form)
{
case DW_FORM_ref_addr:
case DW_FORM_addr:
- fprintf (stderr, "address: ");
+ fprintf_unfiltered (gdb_stderr, "address: ");
print_address_numeric (DW_ADDR (&die->attrs[i]), 1, gdb_stderr);
break;
case DW_FORM_block2:
case DW_FORM_block4:
case DW_FORM_block:
case DW_FORM_block1:
- fprintf (stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
+ fprintf_unfiltered (gdb_stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
break;
case DW_FORM_data1:
case DW_FORM_data2:
case DW_FORM_ref4:
case DW_FORM_udata:
case DW_FORM_sdata:
- fprintf (stderr, "constant: %ld", DW_UNSND (&die->attrs[i]));
+ fprintf_unfiltered (gdb_stderr, "constant: %ld", DW_UNSND (&die->attrs[i]));
break;
case DW_FORM_string:
- fprintf (stderr, "string: \"%s\"",
+ case DW_FORM_strp:
+ fprintf_unfiltered (gdb_stderr, "string: \"%s\"",
DW_STRING (&die->attrs[i])
? DW_STRING (&die->attrs[i]) : "");
break;
case DW_FORM_flag:
if (DW_UNSND (&die->attrs[i]))
- fprintf (stderr, "flag: TRUE");
+ fprintf_unfiltered (gdb_stderr, "flag: TRUE");
else
- fprintf (stderr, "flag: FALSE");
+ fprintf_unfiltered (gdb_stderr, "flag: FALSE");
+ break;
+ case DW_FORM_indirect:
+ /* the reader will have reduced the indirect form to
+ the "base form" so this form should not occur */
+ fprintf_unfiltered (gdb_stderr, "unexpected attribute form: DW_FORM_indirect");
break;
- case DW_FORM_strp: /* we do not support separate string
- section yet */
- case DW_FORM_indirect: /* we do not handle indirect yet */
default:
- fprintf (stderr, "unsupported attribute form: %d.",
+ fprintf_unfiltered (gdb_stderr, "unsupported attribute form: %d.",
die->attrs[i].form);
}
- fprintf (stderr, "\n");
+ fprintf_unfiltered (gdb_stderr, "\n");
}
}
op = data[i++];
switch (op)
{
+ case DW_OP_lit0:
+ case DW_OP_lit1:
+ case DW_OP_lit2:
+ case DW_OP_lit3:
+ case DW_OP_lit4:
+ case DW_OP_lit5:
+ case DW_OP_lit6:
+ case DW_OP_lit7:
+ case DW_OP_lit8:
+ case DW_OP_lit9:
+ case DW_OP_lit10:
+ case DW_OP_lit11:
+ case DW_OP_lit12:
+ case DW_OP_lit13:
+ case DW_OP_lit14:
+ case DW_OP_lit15:
+ case DW_OP_lit16:
+ case DW_OP_lit17:
+ case DW_OP_lit18:
+ case DW_OP_lit19:
+ case DW_OP_lit20:
+ case DW_OP_lit21:
+ case DW_OP_lit22:
+ case DW_OP_lit23:
+ case DW_OP_lit24:
+ case DW_OP_lit25:
+ case DW_OP_lit26:
+ case DW_OP_lit27:
+ case DW_OP_lit28:
+ case DW_OP_lit29:
+ case DW_OP_lit30:
+ case DW_OP_lit31:
+ stack[++stacki] = op - DW_OP_lit0;
+ break;
+
case DW_OP_reg0:
case DW_OP_reg1:
case DW_OP_reg2:
i += bytes_read;
break;
+ case DW_OP_dup:
+ stack[stacki + 1] = stack[stacki];
+ stacki++;
+ break;
+
case DW_OP_plus:
stack[stacki - 1] += stack[stacki];
stacki--;
break;
case DW_OP_minus:
- stack[stacki - 1] = stack[stacki] - stack[stacki - 1];
+ stack[stacki - 1] -= stack[stacki];
stacki--;
break;