summaryrefslogtreecommitdiff
path: root/gdb/dwarf2read.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r--gdb/dwarf2read.c66
1 files changed, 55 insertions, 11 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index cf5206631ec..35be19d7f8e 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -302,13 +302,28 @@ static struct partial_die_info zeroed_partial_die;
in buildsym.c. */
static struct pending **list_in_scope = &file_symbols;
-/* FIXME: The following variables pass additional information from
- decode_locdesc to the caller. */
-static int optimized_out; /* Kludge to identify optimized out variables */
-static int isreg; /* Kludge to identify register variables */
-static int offreg; /* Kludge to identify basereg references */
-static int basereg; /* Which base register is it relative to? */
-static int islocal; /* Kludge to identify local variables */
+/* FIXME: decode_locdesc sets these variables to describe the location
+ to the caller. These ought to be a structure or something. If
+ none of the flags are set, the object lives at the address returned
+ by decode_locdesc. */
+
+static int optimized_out; /* No ops in location in expression,
+ so object was optimized out. */
+static int isreg; /* Object lives in register.
+ decode_locdesc's return value is
+ the register number. */
+static int offreg; /* Object's address is the sum of the
+ register specified by basereg, plus
+ the offset returned. */
+static int basereg; /* See `offreg'. */
+static int isderef; /* Value described by flags above is
+ the address of a pointer to the object. */
+static int islocal; /* Variable is at the returned offset
+ from the frame start, but there's
+ no identified frame pointer for
+ this function, so we can't say
+ which register it's relative to;
+ use LOC_LOCAL. */
/* DW_AT_frame_base values for the current function.
frame_base_reg is -1 if DW_AT_frame_base is missing, otherwise it
@@ -464,6 +479,10 @@ static struct complaint dwarf2_unsupported_stack_op =
{
"unsupported stack op: '%s'", 0, 0
};
+static struct complaint dwarf2_complex_location_expr =
+{
+ "location expression too complex", 0, 0
+};
static struct complaint dwarf2_unsupported_tag =
{
"unsupported tag: '%s'", 0, 0
@@ -1595,7 +1614,9 @@ read_func_scope (die, objfile)
if (attr)
{
CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile);
- if (isreg)
+ if (isderef)
+ complain (&dwarf2_unsupported_at_frame_base, name);
+ else if (isreg)
frame_base_reg = addr;
else if (offreg)
{
@@ -3922,7 +3943,12 @@ dwarf_decode_lines (offset, comp_dir, abfd)
{
case DW_LNE_end_sequence:
end_sequence = 1;
- record_line (current_subfile, line, address);
+ /* 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. */
break;
case DW_LNE_set_address:
address = read_address (abfd, line_ptr) + baseaddr;
@@ -4238,8 +4264,17 @@ new_symbol (die, type, objfile)
}
else if (offreg)
{
- SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
- SYMBOL_BASEREG (sym) = basereg;
+ if (isderef)
+ {
+ if (basereg != frame_base_reg)
+ complain (&dwarf2_complex_location_expr);
+ SYMBOL_CLASS (sym) = LOC_REF_ARG;
+ }
+ else
+ {
+ SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
+ SYMBOL_BASEREG (sym) = basereg;
+ }
}
else
{
@@ -5643,6 +5678,7 @@ decode_locdesc (blk, objfile)
stack[stacki] = 0;
isreg = 0;
offreg = 0;
+ isderef = 0;
islocal = 0;
optimized_out = 1;
@@ -5816,6 +5852,14 @@ decode_locdesc (blk, objfile)
stacki--;
break;
+ case DW_OP_deref:
+ isderef = 1;
+ /* If we're not the last op, then we definitely can't encode
+ this using GDB's address_class enum. */
+ if (i < size)
+ complain (&dwarf2_complex_location_expr);
+ break;
+
default:
complain (&dwarf2_unsupported_stack_op, dwarf_stack_op_name(op));
return (stack[stacki]);