diff options
-rw-r--r-- | gdb/ChangeLog | 22 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/doc/gdb.texinfo | 25 | ||||
-rw-r--r-- | gdb/dwarf2expr.h | 2 | ||||
-rw-r--r-- | gdb/dwarf2loc.c | 424 | ||||
-rw-r--r-- | gdb/dwarf2loc.h | 3 | ||||
-rw-r--r-- | gdb/dwarf2read.c | 75 |
7 files changed, 482 insertions, 74 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7cd0030..6c28c9e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,25 @@ +2010-06-02 Tom Tromey <tromey@redhat.com> + + * dwarf2loc.h (dwarf2_per_cu_data): Declare. + * dwarf2read.c (dwarf_stack_op_name): No longer static. Return + type is const. Add 'def' argument. Add missing operators, remove + unhandled ones. + (decode_locdesc): Update. + (dwarf2_always_disassemble): New global. + (show_dwarf2_always_disassemble): New function. + (_initialize_dwarf2_read): Add always-disassemble. + (dwarf2_per_cu_offset_size): New function. + * dwarf2loc.c (dwarf2_always_disassemble): Declare. + (piece_end_p): New function. + (locexpr_describe_location_piece): Replace 'size' argument with + 'end'. Use piece_end_p. Rewrite recognition of TLS. Recognize + some constants. Remove errors. + (disassemble_dwarf_expression): New function. + (locexpr_describe_location_1): Use disassemble_dwarf_expression. + Add 'offset_size' argument. + (loclist_describe_location): Change output formatting. + * dwarf2expr.h (dwarf_stack_op_name): Declare. + 2010-06-02 Sami Wagiaalla <swagiaal@redhat.com> * cp-support.c (make_symbol_overload_list_adl_namespace): Handle diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 4ffe455..73e226d 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2010-06-02 Tom Tromey <tromey@redhat.com> + + * gdb.texinfo (Maintenance Commands): Document maint set dwarf2 + always-disassemble. + 2010-06-01 Pedro Alves <pedro@codesourcery.com> * gdb.texinfo (Set Tracepoints): Mention tracepoints support in diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 178ef68..37278c8 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -29979,6 +29979,31 @@ that symbol is described. The type chain produced by this command is a recursive definition of the data type as stored in @value{GDBN}'s data structures, including its flags and contained types. +@kindex maint set dwarf2 always-disassemble +@kindex maint show dwarf2 always-disassemble +@item maint set dwarf2 always-disassemble +@item maint show dwarf2 always-disassemble +Control the behavior of @code{info address} when using DWARF debugging +information. + +The default is @code{off}, which means that @value{GDBN} should try to +describe a variable's location in an easily readable format. When +@code{on}, @value{GDBN} will instead display the DWARF location +expression in an assembly-like format. Note that some locations are +too complex for @value{GDBN} to describe simply; in this case you will +always see the disassembly form. + +Here is an example of the resulting disassembly: + +@smallexample +(gdb) info addr argc +Symbol "argc" is a complex DWARF expression: + 1: DW_OP_fbreg 0 +@end smallexample + +For more information on these expressions, see +@uref{http://www.dwarfstd.org/, the DWARF standard}. + @kindex maint set dwarf2 max-cache-age @kindex maint show dwarf2 max-cache-age @item maint set dwarf2 max-cache-age diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h index a0f4554..8ebbf87 100644 --- a/gdb/dwarf2expr.h +++ b/gdb/dwarf2expr.h @@ -208,4 +208,6 @@ const gdb_byte *read_sleb128 (const gdb_byte *buf, const gdb_byte *buf_end, CORE_ADDR dwarf2_read_address (struct gdbarch *gdbarch, const gdb_byte *buf, const gdb_byte *buf_end, int addr_size); +const char *dwarf_stack_op_name (unsigned int, int); + #endif /* dwarf2expr.h */ diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 79d2277..30464ff 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -42,6 +42,8 @@ #include "gdb_string.h" #include "gdb_assert.h" +extern int dwarf2_always_disassemble; + static void dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc, const gdb_byte **start, size_t *length); @@ -1291,13 +1293,24 @@ locexpr_read_needs_frame (struct symbol *symbol) dlbaton->per_cu); } -/* Describe a single piece of a location, returning an updated - position in the bytecode sequence. */ +/* Return true if DATA points to the end of a piece. END is one past + the last byte in the expression. */ + +static int +piece_end_p (const gdb_byte *data, const gdb_byte *end) +{ + return data == end || data[0] == DW_OP_piece || data[0] == DW_OP_bit_piece; +} + +/* Nicely describe a single piece of a location, returning an updated + position in the bytecode sequence. This function cannot recognize + all locations; if a location is not recognized, it simply returns + DATA. */ static const gdb_byte * locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, CORE_ADDR addr, struct objfile *objfile, - const gdb_byte *data, int size, + const gdb_byte *data, const gdb_byte *end, unsigned int addr_size) { struct gdbarch *gdbarch = get_objfile_arch (objfile); @@ -1314,7 +1327,7 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, { ULONGEST reg; - data = read_uleb128 (data + 1, data + size, ®); + data = read_uleb128 (data + 1, end, ®); regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, reg); fprintf_filtered (stream, _("a variable in $%s"), gdbarch_register_name (gdbarch, regno)); @@ -1325,10 +1338,15 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, struct symbol *framefunc; int frame_reg = 0; LONGEST frame_offset; - const gdb_byte *base_data; + const gdb_byte *base_data, *new_data; size_t base_size; LONGEST base_offset = 0; + new_data = read_sleb128 (data + 1, end, &frame_offset); + if (!piece_end_p (new_data, end)) + return data; + data = new_data; + b = block_for_pc (addr); if (!b) @@ -1372,19 +1390,18 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, frame_reg); - data = read_sleb128 (data + 1, data + size, &frame_offset); - fprintf_filtered (stream, _("a variable at frame base reg $%s offset %s+%s"), gdbarch_register_name (gdbarch, regno), plongest (base_offset), plongest (frame_offset)); } - else if (data[0] >= DW_OP_breg0 && data[0] <= DW_OP_breg31) + else if (data[0] >= DW_OP_breg0 && data[0] <= DW_OP_breg31 + && piece_end_p (data, end)) { LONGEST offset; regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, data[0] - DW_OP_breg0); - data = read_sleb128 (data + 1, data + size, &offset); + data = read_sleb128 (data + 1, end, &offset); fprintf_filtered (stream, _("a variable at offset %s from base reg $%s"), @@ -1404,13 +1421,14 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, The operand represents the offset at which the variable is within the thread local storage. */ - else if (size > 1 - && data[size - 1] == DW_OP_GNU_push_tls_address - && data[0] == DW_OP_addr) + else if (data + 1 + addr_size < end + && data[0] == DW_OP_addr + && data[1 + addr_size] == DW_OP_GNU_push_tls_address + && piece_end_p (data + 2 + addr_size, end)) { CORE_ADDR offset = dwarf2_read_address (gdbarch, data + 1, - data + size - 1, + end, addr_size); fprintf_filtered (stream, @@ -1420,9 +1438,275 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, data += 1 + addr_size + 1; } - else - fprintf_filtered (stream, - _("a variable with complex or multiple locations (DWARF2)")); + else if (data[0] >= DW_OP_lit0 + && data[0] <= DW_OP_lit31 + && data + 1 < end + && data[1] == DW_OP_stack_value) + { + fprintf_filtered (stream, _("the constant %d"), data[0] - DW_OP_lit0); + data += 2; + } + + return data; +} + +/* Disassemble an expression, stopping at the end of a piece or at the + end of the expression. Returns a pointer to the next unread byte + in the input expression. If ALL is nonzero, then this function + will keep going until it reaches the end of the expression. */ + +static const gdb_byte * +disassemble_dwarf_expression (struct ui_file *stream, + struct gdbarch *arch, unsigned int addr_size, + int offset_size, + const gdb_byte *data, const gdb_byte *end, + int all) +{ + const gdb_byte *start = data; + + fprintf_filtered (stream, _("a complex DWARF expression:\n")); + + while (data < end + && (all + || (data[0] != DW_OP_piece && data[0] != DW_OP_bit_piece))) + { + enum dwarf_location_atom op = *data++; + CORE_ADDR addr; + ULONGEST ul; + LONGEST l; + const char *name; + + name = dwarf_stack_op_name (op, 0); + + if (!name) + error (_("Unrecognized DWARF opcode 0x%02x at %ld"), + op, (long) (data - start)); + fprintf_filtered (stream, " % 4ld: %s", (long) (data - start), name); + + switch (op) + { + case DW_OP_addr: + addr = dwarf2_read_address (arch, data, end, addr_size); + data += addr_size; + fprintf_filtered (stream, " %s", paddress (arch, addr)); + break; + + case DW_OP_const1u: + ul = extract_unsigned_integer (data, 1, gdbarch_byte_order (arch)); + data += 1; + fprintf_filtered (stream, " %s", pulongest (ul)); + break; + case DW_OP_const1s: + l = extract_signed_integer (data, 1, gdbarch_byte_order (arch)); + data += 1; + fprintf_filtered (stream, " %s", plongest (l)); + break; + case DW_OP_const2u: + ul = extract_unsigned_integer (data, 2, gdbarch_byte_order (arch)); + data += 2; + fprintf_filtered (stream, " %s", pulongest (ul)); + break; + case DW_OP_const2s: + l = extract_signed_integer (data, 2, gdbarch_byte_order (arch)); + data += 2; + fprintf_filtered (stream, " %s", plongest (l)); + break; + case DW_OP_const4u: + ul = extract_unsigned_integer (data, 4, gdbarch_byte_order (arch)); + data += 4; + fprintf_filtered (stream, " %s", pulongest (ul)); + break; + case DW_OP_const4s: + l = extract_signed_integer (data, 4, gdbarch_byte_order (arch)); + data += 4; + fprintf_filtered (stream, " %s", plongest (l)); + break; + case DW_OP_const8u: + ul = extract_unsigned_integer (data, 8, gdbarch_byte_order (arch)); + data += 8; + fprintf_filtered (stream, " %s", pulongest (ul)); + break; + case DW_OP_const8s: + l = extract_signed_integer (data, 8, gdbarch_byte_order (arch)); + data += 8; + fprintf_filtered (stream, " %s", plongest (l)); + break; + case DW_OP_constu: + data = read_uleb128 (data, end, &ul); + fprintf_filtered (stream, " %s", pulongest (ul)); + break; + case DW_OP_consts: + data = read_sleb128 (data, end, &ul); + fprintf_filtered (stream, " %s", plongest (l)); + break; + + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: + fprintf_filtered (stream, " [$%s]", + gdbarch_register_name (arch, op - DW_OP_reg0)); + break; + + case DW_OP_regx: + data = read_uleb128 (data, end, &ul); + fprintf_filtered (stream, " %s [$%s]", pulongest (ul), + gdbarch_register_name (arch, (int) ul)); + break; + + case DW_OP_implicit_value: + data = read_uleb128 (data, end, &ul); + data += ul; + fprintf_filtered (stream, " %s", pulongest (ul)); + break; + + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + data = read_sleb128 (data, end, &ul); + fprintf_filtered (stream, " %s [$%s]", pulongest (ul), + gdbarch_register_name (arch, op - DW_OP_breg0)); + break; + + case DW_OP_bregx: + { + ULONGEST offset; + + data = read_uleb128 (data, end, &ul); + data = read_sleb128 (data, end, &offset); + fprintf_filtered (stream, " register %s [$%s] offset %s", + pulongest (ul), + gdbarch_register_name (arch, (int) ul), + pulongest (offset)); + } + break; + + case DW_OP_fbreg: + data = read_sleb128 (data, end, &ul); + fprintf_filtered (stream, " %s", pulongest (ul)); + break; + + case DW_OP_xderef_size: + case DW_OP_deref_size: + case DW_OP_pick: + fprintf_filtered (stream, " %d", *data); + ++data; + break; + + case DW_OP_plus_uconst: + data = read_uleb128 (data, end, &ul); + fprintf_filtered (stream, " %s", pulongest (ul)); + break; + + case DW_OP_skip: + l = extract_signed_integer (data, 2, gdbarch_byte_order (arch)); + data += 2; + fprintf_filtered (stream, " to %ld", + (long) (data + l - start)); + break; + + case DW_OP_bra: + l = extract_signed_integer (data, 2, gdbarch_byte_order (arch)); + data += 2; + fprintf_filtered (stream, " %ld", + (long) (data + l - start)); + break; + + case DW_OP_call2: + ul = extract_unsigned_integer (data, 2, gdbarch_byte_order (arch)); + data += 2; + fprintf_filtered (stream, " offset %s", phex_nz (ul, 2)); + break; + + case DW_OP_call4: + ul = extract_unsigned_integer (data, 4, gdbarch_byte_order (arch)); + data += 4; + fprintf_filtered (stream, " offset %s", phex_nz (ul, 4)); + break; + + case DW_OP_call_ref: + ul = extract_unsigned_integer (data, offset_size, + gdbarch_byte_order (arch)); + data += offset_size; + fprintf_filtered (stream, " offset %s", phex_nz (ul, offset_size)); + break; + + case DW_OP_piece: + data = read_uleb128 (data, end, &ul); + fprintf_filtered (stream, " %s (bytes)", pulongest (ul)); + break; + + case DW_OP_bit_piece: + { + ULONGEST offset; + + data = read_uleb128 (data, end, &ul); + data = read_uleb128 (data, end, &offset); + fprintf_filtered (stream, " size %s offset %s (bits)", + pulongest (ul), pulongest (offset)); + } + break; + } + + fprintf_filtered (stream, "\n"); + } return data; } @@ -1434,40 +1718,78 @@ static void locexpr_describe_location_1 (struct symbol *symbol, CORE_ADDR addr, struct ui_file *stream, const gdb_byte *data, int size, - struct objfile *objfile, unsigned int addr_size) + struct objfile *objfile, unsigned int addr_size, + int offset_size) { const gdb_byte *end = data + size; - int piece_done = 0, first_piece = 1, bad = 0; + int first_piece = 1, bad = 0; - /* A multi-piece description consists of multiple sequences of bytes - each followed by DW_OP_piece + length of piece. */ while (data < end) { - if (!piece_done) - { - if (first_piece) - first_piece = 0; - else - fprintf_filtered (stream, _(", and ")); + const gdb_byte *here = data; + int disassemble = 1; + + if (first_piece) + first_piece = 0; + else + fprintf_filtered (stream, _(", and ")); + if (!dwarf2_always_disassemble) + { data = locexpr_describe_location_piece (symbol, stream, addr, objfile, - data, size, addr_size); - piece_done = 1; + data, end, addr_size); + /* If we printed anything, or if we have an empty piece, + then don't disassemble. */ + if (data != here + || data[0] == DW_OP_piece + || data[0] == DW_OP_bit_piece) + disassemble = 0; } - else if (data[0] == DW_OP_piece) + if (disassemble) + data = disassemble_dwarf_expression (stream, get_objfile_arch (objfile), + addr_size, offset_size, data, end, + dwarf2_always_disassemble); + + if (data < end) { - ULONGEST bytes; + int empty = data == here; - data = read_uleb128 (data + 1, end, &bytes); + if (disassemble) + fprintf_filtered (stream, " "); + if (data[0] == DW_OP_piece) + { + ULONGEST bytes; - fprintf_filtered (stream, _(" [%s-byte piece]"), pulongest (bytes)); + data = read_uleb128 (data + 1, end, &bytes); - piece_done = 0; - } - else - { - bad = 1; - break; + if (empty) + fprintf_filtered (stream, _("an empty %s-byte piece"), + pulongest (bytes)); + else + fprintf_filtered (stream, _(" [%s-byte piece]"), + pulongest (bytes)); + } + else if (data[0] == DW_OP_bit_piece) + { + ULONGEST bits, offset; + + data = read_uleb128 (data + 1, end, &bits); + data = read_uleb128 (data, end, &offset); + + if (empty) + fprintf_filtered (stream, + _("an empty %s-bit piece"), + pulongest (bits)); + else + fprintf_filtered (stream, + _(" [%s-bit piece, offset %s bits]"), + pulongest (bits), pulongest (offset)); + } + else + { + bad = 1; + break; + } } } @@ -1486,9 +1808,10 @@ locexpr_describe_location (struct symbol *symbol, CORE_ADDR addr, struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); struct objfile *objfile = dwarf2_per_cu_objfile (dlbaton->per_cu); unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu); + int offset_size = dwarf2_per_cu_offset_size (dlbaton->per_cu); locexpr_describe_location_1 (symbol, addr, stream, dlbaton->data, dlbaton->size, - objfile, addr_size); + objfile, addr_size, offset_size); } /* Describe the location of SYMBOL as an agent value in VALUE, generating @@ -1572,6 +1895,7 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr, struct gdbarch *gdbarch = get_objfile_arch (objfile); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu); + int offset_size = dwarf2_per_cu_offset_size (dlbaton->per_cu); CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); /* Adjust base_address for relocatable objects. */ CORE_ADDR base_offset = ANOFFSET (objfile->section_offsets, @@ -1581,7 +1905,7 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr, loc_ptr = dlbaton->data; buf_end = dlbaton->data + dlbaton->size; - fprintf_filtered (stream, _("multi-location (")); + fprintf_filtered (stream, _("multi-location:\n")); /* Iterate through locations until we run out. */ while (1) @@ -1598,7 +1922,7 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr, { base_address = dwarf2_read_address (gdbarch, loc_ptr, buf_end, addr_size); - fprintf_filtered (stream, _("[base address %s]"), + fprintf_filtered (stream, _(" Base address %s"), paddress (gdbarch, base_address)); loc_ptr += addr_size; continue; @@ -1609,11 +1933,7 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr, /* An end-of-list entry. */ if (low == 0 && high == 0) - { - /* Indicate the end of the list, for readability. */ - fprintf_filtered (stream, _(")")); - return; - } + break; /* Otherwise, a location expression entry. */ low += base_address; @@ -1622,20 +1942,16 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr, length = extract_unsigned_integer (loc_ptr, 2, byte_order); loc_ptr += 2; - /* Separate the different locations with a semicolon. */ - if (first) - first = 0; - else - fprintf_filtered (stream, _("; ")); - /* (It would improve readability to print only the minimum necessary digits of the second number of the range.) */ - fprintf_filtered (stream, _("range %s-%s, "), + fprintf_filtered (stream, _(" Range %s-%s: "), paddress (gdbarch, low), paddress (gdbarch, high)); /* Now describe this particular location. */ locexpr_describe_location_1 (symbol, low, stream, loc_ptr, length, - objfile, addr_size); + objfile, addr_size, offset_size); + + fprintf_filtered (stream, "\n"); loc_ptr += length; } diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h index d246e7c..4938241 100644 --- a/gdb/dwarf2loc.h +++ b/gdb/dwarf2loc.h @@ -34,6 +34,9 @@ struct objfile *dwarf2_per_cu_objfile (struct dwarf2_per_cu_data *cu); /* Return the address size given in the compilation unit header for CU. */ CORE_ADDR dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *cu); +/* Return the offset size given in the compilation unit header for CU. */ +int dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *cu); + /* The symbol location baton types used by the DWARF-2 reader (i.e. SYMBOL_LOCATION_BATON for a LOC_COMPUTED symbol). "struct dwarf2_locexpr_baton" is for a symbol with a single location diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index da89573..b05b99a 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -1002,8 +1002,6 @@ static char *dwarf_attr_name (unsigned int); static char *dwarf_form_name (unsigned int); -static char *dwarf_stack_op_name (unsigned int); - static char *dwarf_bool_name (unsigned int); static char *dwarf_type_encoding_name (unsigned int); @@ -9890,8 +9888,8 @@ dwarf_form_name (unsigned form) /* Convert a DWARF stack opcode into its string name. */ -static char * -dwarf_stack_op_name (unsigned op) +const char * +dwarf_stack_op_name (unsigned op, int def) { switch (op) { @@ -10194,32 +10192,24 @@ dwarf_stack_op_name (unsigned op) return "DW_OP_call4"; case DW_OP_call_ref: return "DW_OP_call_ref"; - /* GNU extensions. */ case DW_OP_form_tls_address: return "DW_OP_form_tls_address"; case DW_OP_call_frame_cfa: return "DW_OP_call_frame_cfa"; case DW_OP_bit_piece: return "DW_OP_bit_piece"; + /* DWARF 4 extensions. */ + case DW_OP_implicit_value: + return "DW_OP_implicit_value"; + case DW_OP_stack_value: + return "DW_OP_stack_value"; + /* GNU extensions. */ case DW_OP_GNU_push_tls_address: return "DW_OP_GNU_push_tls_address"; case DW_OP_GNU_uninit: return "DW_OP_GNU_uninit"; - /* HP extensions. */ - case DW_OP_HP_is_value: - return "DW_OP_HP_is_value"; - case DW_OP_HP_fltconst4: - return "DW_OP_HP_fltconst4"; - case DW_OP_HP_fltconst8: - return "DW_OP_HP_fltconst8"; - case DW_OP_HP_mod_range: - return "DW_OP_HP_mod_range"; - case DW_OP_HP_unmod_range: - return "DW_OP_HP_unmod_range"; - case DW_OP_HP_tls: - return "DW_OP_HP_tls"; default: - return "OP_<unknown>"; + return def ? "OP_<unknown>" : NULL; } } @@ -11060,7 +11050,7 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu) default: complaint (&symfile_complaints, _("unsupported stack op: '%s'"), - dwarf_stack_op_name (op)); + dwarf_stack_op_name (op, 1)); return (stack[stacki]); } } @@ -11787,6 +11777,28 @@ dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu) } } +/* Return the offset size given in the compilation unit header for CU. */ + +int +dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *per_cu) +{ + if (per_cu->cu) + return per_cu->cu->header.offset_size; + else + { + /* If the CU is not currently read in, we re-read its header. */ + struct objfile *objfile = per_cu->psymtab->objfile; + struct dwarf2_per_objfile *per_objfile + = objfile_data (objfile, dwarf2_objfile_data_key); + gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset; + struct comp_unit_head cu_header; + + memset (&cu_header, 0, sizeof cu_header); + read_comp_unit_head (&cu_header, info_ptr, objfile->obfd); + return cu_header.offset_size; + } +} + /* Locate the .debug_info compilation unit from CU's objfile which contains the DIE at OFFSET. Raises an error on failure. */ @@ -12241,6 +12253,17 @@ dwarf2_per_objfile_free (struct objfile *objfile, void *d) munmap_section_buffer (&data->eh_frame); } +int dwarf2_always_disassemble; + +static void +show_dwarf2_always_disassemble (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("\ +Whether to always disassemble DWARF expressions is %s.\n"), + value); +} + void _initialize_dwarf2_read (void); void @@ -12273,6 +12296,18 @@ caching, which can slow down startup."), &set_dwarf2_cmdlist, &show_dwarf2_cmdlist); + add_setshow_boolean_cmd ("always-disassemble", class_obscure, + &dwarf2_always_disassemble, _("\ +Set whether `info address' always disassembles DWARF expressions."), _("\ +Show whether `info address' always disassembles DWARF expressions."), _("\ +When enabled, DWARF expressions are always printed in an assembly-like\n\ +syntax. When disabled, expressions will be printed in a more\n\ +conversational style, when possible."), + NULL, + show_dwarf2_always_disassemble, + &set_dwarf2_cmdlist, + &show_dwarf2_cmdlist); + add_setshow_zinteger_cmd ("dwarf2-die", no_class, &dwarf2_die_debug, _("\ Set debugging of the dwarf2 DIE reader."), _("\ Show debugging of the dwarf2 DIE reader."), _("\ |