mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-27 09:38:57 +00:00
gdb
* 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. gdb/doc * gdb.texinfo (Maintenance Commands): Document maint set dwarf2 always-disassemble.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
432
gdb/dwarf2loc.c
432
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;
|
||||
|
||||
data = locexpr_describe_location_piece (symbol, stream, addr, objfile,
|
||||
data, size, addr_size);
|
||||
piece_done = 1;
|
||||
}
|
||||
else if (data[0] == DW_OP_piece)
|
||||
{
|
||||
ULONGEST bytes;
|
||||
|
||||
data = read_uleb128 (data + 1, end, &bytes);
|
||||
|
||||
fprintf_filtered (stream, _(" [%s-byte piece]"), pulongest (bytes));
|
||||
|
||||
piece_done = 0;
|
||||
}
|
||||
if (first_piece)
|
||||
first_piece = 0;
|
||||
else
|
||||
fprintf_filtered (stream, _(", and "));
|
||||
|
||||
if (!dwarf2_always_disassemble)
|
||||
{
|
||||
bad = 1;
|
||||
break;
|
||||
data = locexpr_describe_location_piece (symbol, stream, addr, objfile,
|
||||
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;
|
||||
}
|
||||
if (disassemble)
|
||||
data = disassemble_dwarf_expression (stream, get_objfile_arch (objfile),
|
||||
addr_size, offset_size, data, end,
|
||||
dwarf2_always_disassemble);
|
||||
|
||||
if (data < end)
|
||||
{
|
||||
int empty = data == here;
|
||||
|
||||
if (disassemble)
|
||||
fprintf_filtered (stream, " ");
|
||||
if (data[0] == DW_OP_piece)
|
||||
{
|
||||
ULONGEST bytes;
|
||||
|
||||
data = read_uleb128 (data + 1, end, &bytes);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."), _("\
|
||||
|
||||
Reference in New Issue
Block a user