/* dwarf.c -- display DWARF contents of a BFD binary file
- Copyright (C) 2005-2017 Free Software Foundation, Inc.
+ Copyright (C) 2005-2020 Free Software Foundation, Inc.
This file is part of GNU Binutils.
#include "dwarf.h"
#include "gdb/gdb-index.h"
#include "filenames.h"
+#include "safe-ctype.h"
#include <assert.h>
+#ifdef HAVE_LIBDEBUGINFOD
+#include <elfutils/debuginfod.h>
+#endif
+
#undef MAX
#undef MIN
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
static const char *regname (unsigned int regno, int row);
+static const char *regname_internal_by_table_only (unsigned int regno);
static int have_frame_base;
static int need_base_address;
that the .debug_info section could not be loaded/parsed. */
#define DEBUG_INFO_UNAVAILABLE (unsigned int) -1
+/* A .debug_info section can contain multiple links to separate
+ DWO object files. We use these structures to record these links. */
+typedef enum dwo_type
+{
+ DWO_NAME,
+ DWO_DIR,
+ DWO_ID
+} dwo_type;
+
+typedef struct dwo_info
+{
+ dwo_type type;
+ const char * value;
+ struct dwo_info * next;
+} dwo_info;
+
+static dwo_info * first_dwo_info = NULL;
+static bfd_boolean need_dwo_info;
+
+separate_info * first_separate_info = NULL;
+
unsigned int eh_addr_size;
int do_debug_info;
static unsigned int shndx_pool_size = 0;
static unsigned int shndx_pool_used = 0;
-/* Pointer to a separate file containing extra debug information. */
-static void * separate_debug_file = NULL;
-static const char * separate_debug_filename = NULL;
-
/* For version 2 package files, each set contains an array of section offsets
and an array of section sizes, giving the offset and size of the
contribution from a CU or TU within one of the debug sections.
struct cu_tu_set
{
- uint64_t signature;
- dwarf_vma section_offsets[DW_SECT_MAX];
- size_t section_sizes[DW_SECT_MAX];
+ uint64_t signature;
+ dwarf_vma section_offsets[DW_SECT_MAX];
+ size_t section_sizes[DW_SECT_MAX];
};
static int cu_count = 0;
static bfd_boolean load_cu_tu_indexes (void *);
+/* An array that indicates for a given level of CU nesting whether
+ the latest DW_AT_type seen for that level was a signed type or
+ an unsigned type. */
+#define MAX_CU_NESTING (1 << 8)
+static bfd_boolean level_type_signed[MAX_CU_NESTING];
+
/* Values for do_debug_lines. */
#define FLAG_DEBUG_LINES_RAW 1
#define FLAG_DEBUG_LINES_DECODED 2
/* Read in a LEB128 encoded value starting at address DATA.
If SIGN is true, return a signed LEB128 value.
If LENGTH_RETURN is not NULL, return in it the number of bytes read.
+ If STATUS_RETURN in not NULL, return with bit 0 (LSB) set if the
+ terminating byte was not found and with bit 1 set if the value
+ overflows a dwarf_vma.
No bytes will be read at address END or beyond. */
dwarf_vma
read_leb128 (unsigned char *data,
- unsigned int *length_return,
+ const unsigned char *const end,
bfd_boolean sign,
- const unsigned char * const end)
+ unsigned int *length_return,
+ int *status_return)
{
dwarf_vma result = 0;
unsigned int num_read = 0;
unsigned int shift = 0;
- unsigned char byte = 0;
+ int status = 1;
while (data < end)
{
- byte = *data++;
+ unsigned char byte = *data++;
num_read++;
- result |= ((dwarf_vma) (byte & 0x7f)) << shift;
+ if (shift < sizeof (result) * 8)
+ {
+ result |= ((dwarf_vma) (byte & 0x7f)) << shift;
+ if ((result >> shift) != (byte & 0x7f))
+ /* Overflow. */
+ status |= 2;
+ shift += 7;
+ }
+ else if ((byte & 0x7f) != 0)
+ status |= 2;
- shift += 7;
if ((byte & 0x80) == 0)
- break;
-
- /* PR 17512: file: 0ca183b8.
- FIXME: Should we signal this error somehow ? */
- if (shift >= sizeof (result) * 8)
- break;
+ {
+ status &= ~1;
+ if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40))
+ result |= -((dwarf_vma) 1 << shift);
+ break;
+ }
}
if (length_return != NULL)
*length_return = num_read;
-
- if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40))
- result |= -((dwarf_vma) 1 << shift);
+ if (status_return != NULL)
+ *status_return = status;
return result;
}
-/* Create a signed version to avoid painful typecasts. */
-static inline dwarf_signed_vma
-read_sleb128 (unsigned char * data,
- unsigned int * length_return,
- const unsigned char * const end)
-{
- return (dwarf_signed_vma) read_leb128 (data, length_return, TRUE, end);
-}
-
-static inline dwarf_vma
-read_uleb128 (unsigned char * data,
- unsigned int * length_return,
- const unsigned char * const end)
-{
- return read_leb128 (data, length_return, FALSE, end);
-}
-
-#define SKIP_ULEB() read_uleb128 (start, & length_return, end); start += length_return
-#define SKIP_SLEB() read_sleb128 (start, & length_return, end); start += length_return
-
-#define READ_ULEB(var) \
- do \
- { \
- dwarf_vma _val; \
- \
- (var) = _val = read_uleb128 (start, &length_return, end); \
- if ((var) != _val) \
- error (_("Internal error: %s:%d: LEB value (%s) " \
- "too large for containing variable\n"), \
- __FILE__, __LINE__, dwarf_vmatoa ("u", _val)); \
- start += length_return; \
- } \
- while (0)
-
-#define READ_SLEB(var) \
- do \
- { \
- dwarf_signed_vma _val; \
- \
- (var) = _val = read_sleb128 (start, &length_return, end); \
- if ((var) != _val) \
- error (_("Internal error: %s:%d: LEB value (%s) " \
- "too large for containing variable\n"), \
- __FILE__, __LINE__, dwarf_vmatoa ("d", _val)); \
- start += length_return; \
- } \
- while (0)
-
+/* Read AMOUNT bytes from PTR and store them in VAL as an unsigned value.
+ Checks to make sure that the read will not reach or pass END
+ and that VAL is big enough to hold AMOUNT bytes. */
#define SAFE_BYTE_GET(VAL, PTR, AMOUNT, END) \
do \
{ \
} \
while (0)
+/* Like SAFE_BYTE_GET, but also increments PTR by AMOUNT. */
#define SAFE_BYTE_GET_AND_INC(VAL, PTR, AMOUNT, END) \
do \
{ \
} \
while (0)
+/* Like SAFE_BYTE_GET, but reads a signed value. */
#define SAFE_SIGNED_BYTE_GET(VAL, PTR, AMOUNT, END) \
do \
{ \
} \
while (0)
+/* Like SAFE_SIGNED_BYTE_GET, but also increments PTR by AMOUNT. */
#define SAFE_SIGNED_BYTE_GET_AND_INC(VAL, PTR, AMOUNT, END) \
do \
{ \
/* Handled an extend line op.
Returns the number of bytes read. */
-static int
+static size_t
process_extended_line_op (unsigned char * data,
int is_stmt,
unsigned char * end)
{
unsigned char op_code;
- unsigned int bytes_read;
- unsigned int len;
+ size_t len, header_len;
unsigned char *name;
unsigned char *orig_data = data;
- dwarf_vma adr;
+ dwarf_vma adr, val;
- len = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ READ_ULEB (len, data, end);
+ header_len = data - orig_data;
- if (len == 0 || data == end || len > (uintptr_t) (end - data))
+ if (len == 0 || data == end || len > (size_t) (end - data))
{
warn (_("Badly formed extended line op encountered!\n"));
- return bytes_read;
+ return header_len;
}
- len += bytes_read;
op_code = *data++;
printf (_(" Extended opcode %d: "), op_code);
case DW_LNE_set_address:
/* PR 17512: file: 002-100480-0.004. */
- if (len - bytes_read - 1 > 8)
+ if (len - 1 > 8)
{
- warn (_("Length (%d) of DW_LNE_set_address op is too long\n"),
- len - bytes_read - 1);
+ warn (_("Length (%lu) of DW_LNE_set_address op is too long\n"),
+ (unsigned long) len - 1);
adr = 0;
}
else
- SAFE_BYTE_GET (adr, data, len - bytes_read - 1, end);
+ SAFE_BYTE_GET (adr, data, len - 1, end);
printf (_("set Address to 0x%s\n"), dwarf_vmatoa ("x", adr));
state_machine_regs.address = adr;
state_machine_regs.view = 0;
name = data;
l = strnlen ((char *) data, end - data);
- data += len + 1;
- printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end)));
- data += bytes_read;
- printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end)));
- data += bytes_read;
- printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end)));
- data += bytes_read;
+ data += l + 1;
+ READ_ULEB (val, data, end);
+ printf ("%s\t", dwarf_vmatoa ("u", val));
+ READ_ULEB (val, data, end);
+ printf ("%s\t", dwarf_vmatoa ("u", val));
+ READ_ULEB (val, data, end);
+ printf ("%s\t", dwarf_vmatoa ("u", val));
printf ("%.*s\n\n", (int) l, name);
}
- if (((unsigned int) (data - orig_data) != len) || data == end)
+ if (((size_t) (data - orig_data) != len + header_len) || data == end)
warn (_("DW_LNE_define_file: Bad opcode length\n"));
break;
case DW_LNE_set_discriminator:
- printf (_("set Discriminator to %s\n"),
- dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end)));
+ READ_ULEB (val, data, end);
+ printf (_("set Discriminator to %s\n"), dwarf_vmatoa ("u", val));
break;
/* HP extensions. */
break;
case DW_LNE_HP_source_file_correlation:
{
- unsigned char *edata = data + len - bytes_read - 1;
+ unsigned char *edata = data + len - 1;
printf ("DW_LNE_HP_source_file_correlation\n");
{
unsigned int opc;
- opc = read_uleb128 (data, & bytes_read, edata);
- data += bytes_read;
+ READ_ULEB (opc, data, edata);
switch (opc)
{
printf (" DW_LNE_HP_SFC_formfeed\n");
break;
case DW_LNE_HP_SFC_set_listing_line:
+ READ_ULEB (val, data, edata);
printf (" DW_LNE_HP_SFC_set_listing_line (%s)\n",
- dwarf_vmatoa ("u",
- read_uleb128 (data, & bytes_read, edata)));
- data += bytes_read;
+ dwarf_vmatoa ("u", val));
break;
case DW_LNE_HP_SFC_associate:
printf (" DW_LNE_HP_SFC_associate ");
- printf ("(%s",
- dwarf_vmatoa ("u",
- read_uleb128 (data, & bytes_read, edata)));
- data += bytes_read;
- printf (",%s",
- dwarf_vmatoa ("u",
- read_uleb128 (data, & bytes_read, edata)));
- data += bytes_read;
- printf (",%s)\n",
- dwarf_vmatoa ("u",
- read_uleb128 (data, & bytes_read, edata)));
- data += bytes_read;
+ READ_ULEB (val, data, edata);
+ printf ("(%s", dwarf_vmatoa ("u", val));
+ READ_ULEB (val, data, edata);
+ printf (",%s", dwarf_vmatoa ("u", val));
+ READ_ULEB (val, data, edata);
+ printf (",%s)\n", dwarf_vmatoa ("u", val));
break;
default:
printf (_(" UNKNOWN DW_LNE_HP_SFC opcode (%u)\n"), opc);
default:
{
- unsigned int rlen = len - bytes_read - 1;
+ unsigned int rlen = len - 1;
if (op_code >= DW_LNE_lo_user
/* The test against DW_LNW_hi_user is redundant due to
break;
}
- return len;
+ return len + header_len;
}
static const unsigned char *
static const char *
fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set,
- dwarf_vma offset_size, int dwo)
+ dwarf_vma offset_size, bfd_boolean dwo)
{
enum dwarf_section_display_enum str_sec_idx = dwo ? str_dwo : str;
enum dwarf_section_display_enum idx_sec_idx = dwo ? str_index_dwo : str_index;
while (start < end)
{
- unsigned int bytes_read;
unsigned long entry;
unsigned long tag;
unsigned long attribute;
int children;
- entry = read_uleb128 (start, & bytes_read, end);
- start += bytes_read;
+ READ_ULEB (entry, start, end);
/* A single zero is supposed to end the section according
to the standard. If there's more, then signal that to
if (entry == 0)
return start;
- tag = read_uleb128 (start, & bytes_read, end);
- start += bytes_read;
+ READ_ULEB (tag, start, end);
if (start == end)
return NULL;
/* Initialize it due to a false compiler warning. */
bfd_signed_vma implicit_const = -1;
- attribute = read_uleb128 (start, & bytes_read, end);
- start += bytes_read;
+ READ_ULEB (attribute, start, end);
if (start == end)
break;
- form = read_uleb128 (start, & bytes_read, end);
- start += bytes_read;
+ READ_ULEB (form, start, end);
if (start == end)
break;
if (form == DW_FORM_implicit_const)
{
- implicit_const = read_sleb128 (start, & bytes_read, end);
- start += bytes_read;
+ READ_SLEB (implicit_const, start, end);
if (start == end)
break;
}
struct dwarf_section * section)
{
unsigned op;
- unsigned int bytes_read;
dwarf_vma uvalue;
dwarf_signed_vma svalue;
unsigned char *end = data + length;
printf ("%ld", (long) svalue);
break;
case DW_OP_constu:
- printf ("DW_OP_constu: %s",
- dwarf_vmatoa ("u", read_uleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
+ printf ("DW_OP_constu: %s", dwarf_vmatoa ("u", uvalue));
break;
case DW_OP_consts:
- printf ("DW_OP_consts: %s",
- dwarf_vmatoa ("d", read_sleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ READ_SLEB (svalue, data, end);
+ printf ("DW_OP_consts: %s", dwarf_vmatoa ("d", svalue));
break;
case DW_OP_dup:
printf ("DW_OP_dup");
printf ("DW_OP_plus");
break;
case DW_OP_plus_uconst:
- printf ("DW_OP_plus_uconst: %s",
- dwarf_vmatoa ("u", read_uleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
+ printf ("DW_OP_plus_uconst: %s", dwarf_vmatoa ("u", uvalue));
break;
case DW_OP_shl:
printf ("DW_OP_shl");
case DW_OP_breg29:
case DW_OP_breg30:
case DW_OP_breg31:
- printf ("DW_OP_breg%d (%s): %s",
- op - DW_OP_breg0,
- regname (op - DW_OP_breg0, 1),
- dwarf_vmatoa ("d", read_sleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ READ_SLEB (svalue, data, end);
+ printf ("DW_OP_breg%d (%s): %s", op - DW_OP_breg0,
+ regname (op - DW_OP_breg0, 1), dwarf_vmatoa ("d", svalue));
break;
case DW_OP_regx:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf ("DW_OP_regx: %s (%s)",
dwarf_vmatoa ("u", uvalue), regname (uvalue, 1));
break;
case DW_OP_fbreg:
need_frame_base = 1;
- printf ("DW_OP_fbreg: %s",
- dwarf_vmatoa ("d", read_sleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ READ_SLEB (svalue, data, end);
+ printf ("DW_OP_fbreg: %s", dwarf_vmatoa ("d", svalue));
break;
case DW_OP_bregx:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
+ READ_SLEB (svalue, data, end);
printf ("DW_OP_bregx: %s (%s) %s",
dwarf_vmatoa ("u", uvalue), regname (uvalue, 1),
- dwarf_vmatoa ("d", read_sleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ dwarf_vmatoa ("d", svalue));
break;
case DW_OP_piece:
- printf ("DW_OP_piece: %s",
- dwarf_vmatoa ("u", read_uleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
+ printf ("DW_OP_piece: %s", dwarf_vmatoa ("u", uvalue));
break;
case DW_OP_deref_size:
SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
printf ("DW_OP_push_object_address");
break;
case DW_OP_call2:
- /* XXX: Strictly speaking for 64-bit DWARF3 files
+ /* FIXME: Strictly speaking for 64-bit DWARF3 files
this ought to be an 8-byte wide computation. */
SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 2, end);
printf ("DW_OP_call2: <0x%s>",
dwarf_vmatoa ("x", svalue + cu_offset));
break;
case DW_OP_call4:
- /* XXX: Strictly speaking for 64-bit DWARF3 files
+ /* FIXME: Strictly speaking for 64-bit DWARF3 files
this ought to be an 8-byte wide computation. */
SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 4, end);
printf ("DW_OP_call4: <0x%s>",
dwarf_vmatoa ("x", svalue + cu_offset));
break;
case DW_OP_call_ref:
- /* XXX: Strictly speaking for 64-bit DWARF3 files
+ /* FIXME: Strictly speaking for 64-bit DWARF3 files
this ought to be an 8-byte wide computation. */
if (dwarf_version == -1)
{
break;
case DW_OP_bit_piece:
printf ("DW_OP_bit_piece: ");
- printf (_("size: %s "),
- dwarf_vmatoa ("u", read_uleb128 (data, &bytes_read, end)));
- data += bytes_read;
- printf (_("offset: %s "),
- dwarf_vmatoa ("u", read_uleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
+ printf (_("size: %s "), dwarf_vmatoa ("u", uvalue));
+ READ_ULEB (uvalue, data, end);
+ printf (_("offset: %s "), dwarf_vmatoa ("u", uvalue));
break;
/* DWARF 4 extensions. */
case DW_OP_implicit_value:
printf ("DW_OP_implicit_value");
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
data = display_block (data, uvalue, end, ' ');
break;
break;
case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
- /* XXX: Strictly speaking for 64-bit DWARF3 files
+ /* FIXME: Strictly speaking for 64-bit DWARF3 files
this ought to be an 8-byte wide computation. */
if (dwarf_version == -1)
{
{
SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
}
+ READ_SLEB (svalue, data, end);
printf ("%s: <0x%s> %s",
(op == DW_OP_implicit_pointer
? "DW_OP_implicit_pointer" : "DW_OP_GNU_implicit_pointer"),
dwarf_vmatoa ("x", uvalue),
- dwarf_vmatoa ("d", read_sleb128 (data,
- &bytes_read, end)));
- data += bytes_read;
+ dwarf_vmatoa ("d", svalue));
break;
case DW_OP_entry_value:
case DW_OP_GNU_entry_value:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
/* PR 17531: file: 0cc9cd00. */
if (uvalue > (dwarf_vma) (end - data))
uvalue = end - data;
break;
case DW_OP_const_type:
case DW_OP_GNU_const_type:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf ("%s: <0x%s> ",
(op == DW_OP_const_type ? "DW_OP_const_type"
: "DW_OP_GNU_const_type"),
break;
case DW_OP_regval_type:
case DW_OP_GNU_regval_type:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf ("%s: %s (%s)",
(op == DW_OP_regval_type ? "DW_OP_regval_type"
: "DW_OP_GNU_regval_type"),
dwarf_vmatoa ("u", uvalue), regname (uvalue, 1));
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf (" <0x%s>", dwarf_vmatoa ("x", cu_offset + uvalue));
break;
case DW_OP_deref_type:
(op == DW_OP_deref_type ? "DW_OP_deref_type"
: "DW_OP_GNU_deref_type"),
(long) uvalue);
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf (" <0x%s>", dwarf_vmatoa ("x", cu_offset + uvalue));
break;
case DW_OP_convert:
case DW_OP_GNU_convert:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf ("%s <0x%s>",
(op == DW_OP_convert ? "DW_OP_convert" : "DW_OP_GNU_convert"),
dwarf_vmatoa ("x", uvalue ? cu_offset + uvalue : 0));
break;
case DW_OP_reinterpret:
case DW_OP_GNU_reinterpret:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf ("%s <0x%s>",
(op == DW_OP_reinterpret ? "DW_OP_reinterpret"
: "DW_OP_GNU_reinterpret"),
dwarf_vmatoa ("x", cu_offset + uvalue));
break;
case DW_OP_GNU_addr_index:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf ("DW_OP_GNU_addr_index <0x%s>", dwarf_vmatoa ("x", uvalue));
break;
case DW_OP_GNU_const_index:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf ("DW_OP_GNU_const_index <0x%s>", dwarf_vmatoa ("x", uvalue));
break;
+ case DW_OP_GNU_variable_value:
+ /* FIXME: Strictly speaking for 64-bit DWARF3 files
+ this ought to be an 8-byte wide computation. */
+ if (dwarf_version == -1)
+ {
+ printf (_("(DW_OP_GNU_variable_value in frame info)"));
+ /* No way to tell where the next op is, so just bail. */
+ return need_frame_base;
+ }
+ if (dwarf_version == 2)
+ {
+ SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
+ }
+ else
+ {
+ SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+ }
+ printf ("DW_OP_GNU_variable_value: <0x%s>", dwarf_vmatoa ("x", uvalue));
+ break;
/* HP extensions. */
case DW_OP_HP_is_value:
static const char *
fetch_alt_indirect_string (dwarf_vma offset)
{
- struct dwarf_section * section;
- const char * ret;
+ separate_info * i;
if (! do_follow_links)
return "";
- if (separate_debug_file == NULL)
- return _("<following link not possible>");
+ if (first_separate_info == NULL)
+ return _("<no links available>");
+
+ for (i = first_separate_info; i != NULL; i = i->next)
+ {
+ struct dwarf_section * section;
+ const char * ret;
- if (! load_debug_section (separate_debug_str, separate_debug_file))
- return _("<could not load separate string section>");
+ if (! load_debug_section (separate_debug_str, i->handle))
+ continue;
- section = &debug_displays [separate_debug_str].section;
- if (section->start == NULL)
- return _("<no .debug_str section>");
+ section = &debug_displays [separate_debug_str].section;
- if (offset >= section->size)
+ if (section->start == NULL)
+ continue;
+
+ if (offset >= section->size)
+ continue;
+
+ ret = (const char *) (section->start + offset);
+ /* Unfortunately we cannot rely upon the .debug_str section ending with a
+ NUL byte. Since our caller is expecting to receive a well formed C
+ string we test for the lack of a terminating byte here. */
+ if (strnlen ((const char *) ret, section->size - offset)
+ == section->size - offset)
+ return _("<no NUL byte at end of alt .debug_str section>");
+
+ return ret;
+ }
+
+ warn (_("DW_FORM_GNU_strp_alt offset (%s) too big or no string sections available\n"),
+ dwarf_vmatoa ("x", offset));
+ return _("<offset is too big>");
+}
+
+static const char *
+get_AT_name (unsigned long attribute)
+{
+ const char *name;
+
+ if (attribute == 0)
+ return "DW_AT value: 0";
+
+ /* One value is shared by the MIPS and HP extensions: */
+ if (attribute == DW_AT_MIPS_fde)
+ return "DW_AT_MIPS_fde or DW_AT_HP_unmodifiable";
+
+ name = get_DW_AT_name (attribute);
+
+ if (name == NULL)
{
- warn (_("DW_FORM_GNU_strp_alt offset too big: %s\n"), dwarf_vmatoa ("x", offset));
- return _("<offset is too big>");
+ static char buffer[100];
+
+ snprintf (buffer, sizeof (buffer), _("Unknown AT value: %lx"),
+ attribute);
+ return buffer;
}
- ret = (const char *) (section->start + offset);
- /* Unfortunately we cannot rely upon the .debug_str section ending with a
- NUL byte. Since our caller is expecting to receive a well formed C
- string we test for the lack of a terminating byte here. */
- if (strnlen ((const char *) ret, section->size - offset)
- == section->size - offset)
- return _("<no NUL byte at end of .debug_str section>");
+ return name;
+}
- return ret;
+static void
+add_dwo_info (const char * field, dwo_type type)
+{
+ dwo_info * dwinfo = xmalloc (sizeof * dwinfo);
+
+ dwinfo->type = type;
+ dwinfo->value = field;
+ dwinfo->next = first_dwo_info;
+ first_dwo_info = dwinfo;
}
-
+
+static void
+add_dwo_name (const char * name)
+{
+ add_dwo_info (name, DWO_NAME);
+}
+
+static void
+add_dwo_dir (const char * dir)
+{
+ add_dwo_info (dir, DWO_DIR);
+}
+
+static void
+add_dwo_id (const char * id)
+{
+ add_dwo_info (id, DWO_ID);
+}
+
+static void
+free_dwo_info (void)
+{
+ dwo_info * dwinfo;
+ dwo_info * next;
+
+ for (dwinfo = first_dwo_info; dwinfo != NULL; dwinfo = next)
+ {
+ next = dwinfo->next;
+ free (dwinfo);
+ }
+ first_dwo_info = NULL;
+}
+
+/* Ensure that START + UVALUE is less than END.
+ Return an adjusted UVALUE if necessary to ensure this relationship. */
+
+static inline dwarf_vma
+check_uvalue (const unsigned char * start,
+ dwarf_vma uvalue,
+ const unsigned char * end)
+{
+ dwarf_vma max_uvalue = end - start;
+
+ /* See PR 17512: file: 008-103549-0.001:0.1.
+ and PR 24829 for examples of where these tests are triggered. */
+ if (uvalue > max_uvalue)
+ {
+ warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
+ uvalue = max_uvalue;
+ }
+
+ return uvalue;
+}
+
+static unsigned char *
+skip_attr_bytes (unsigned long form,
+ unsigned char * data,
+ unsigned const char * end,
+ dwarf_vma pointer_size,
+ dwarf_vma offset_size,
+ int dwarf_version,
+ dwarf_vma * value_return)
+{
+ dwarf_signed_vma svalue;
+ dwarf_vma uvalue = 0;
+
+ * value_return = 0;
+
+ switch (form)
+ {
+ case DW_FORM_ref_addr:
+ if (dwarf_version == 2)
+ SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
+ else if (dwarf_version == 3 || dwarf_version == 4)
+ SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+ else
+ return NULL;
+ break;
+
+ case DW_FORM_addr:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
+ break;
+
+ case DW_FORM_strp:
+ case DW_FORM_line_strp:
+ case DW_FORM_sec_offset:
+ case DW_FORM_GNU_ref_alt:
+ case DW_FORM_GNU_strp_alt:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+ break;
+
+ case DW_FORM_flag_present:
+ uvalue = 1;
+ break;
+
+ case DW_FORM_ref1:
+ case DW_FORM_flag:
+ case DW_FORM_data1:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
+ break;
+
+ case DW_FORM_ref2:
+ case DW_FORM_data2:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
+ break;
+
+ case DW_FORM_ref4:
+ case DW_FORM_data4:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
+ break;
+
+ case DW_FORM_sdata:
+ READ_SLEB (svalue, data, end);
+ uvalue = svalue;
+ break;
+
+ case DW_FORM_ref_udata:
+ case DW_FORM_udata:
+ case DW_FORM_GNU_str_index:
+ case DW_FORM_GNU_addr_index:
+ READ_ULEB (uvalue, data, end);
+ break;
+
+ case DW_FORM_ref8:
+ case DW_FORM_data8:
+ data += 8;
+ break;
+
+ case DW_FORM_data16:
+ data += 16;
+ break;
+
+ case DW_FORM_string:
+ data += strnlen ((char *) data, end - data) + 1;
+ break;
+
+ case DW_FORM_block:
+ case DW_FORM_exprloc:
+ READ_ULEB (uvalue, data, end);
+ break;
+
+ case DW_FORM_block1:
+ SAFE_BYTE_GET (uvalue, data, 1, end);
+ data += 1 + uvalue;
+ break;
+
+ case DW_FORM_block2:
+ SAFE_BYTE_GET (uvalue, data, 2, end);
+ data += 2 + uvalue;
+ break;
+
+ case DW_FORM_block4:
+ SAFE_BYTE_GET (uvalue, data, 4, end);
+ data += 4 + uvalue;
+ break;
+
+ case DW_FORM_ref_sig8:
+ data += 8;
+ break;
+
+ case DW_FORM_indirect:
+ /* FIXME: Handle this form. */
+ default:
+ return NULL;
+ }
+
+ * value_return = uvalue;
+ if (data > end)
+ data = (unsigned char *) end;
+ return data;
+}
+
+/* Return IS_SIGNED set to TRUE if the type at
+ DATA can be determined to be a signed type. */
+
+static void
+get_type_signedness (unsigned char * start,
+ unsigned char * data,
+ unsigned const char * end,
+ dwarf_vma pointer_size,
+ dwarf_vma offset_size,
+ int dwarf_version,
+ bfd_boolean * is_signed,
+ bfd_boolean is_nested)
+{
+ unsigned long abbrev_number;
+ abbrev_entry * entry;
+ abbrev_attr * attr;
+
+ * is_signed = FALSE;
+
+ READ_ULEB (abbrev_number, data, end);
+
+ for (entry = first_abbrev;
+ entry != NULL && entry->entry != abbrev_number;
+ entry = entry->next)
+ continue;
+
+ if (entry == NULL)
+ /* FIXME: Issue a warning ? */
+ return;
+
+ for (attr = entry->first_attr;
+ attr != NULL && attr->attribute;
+ attr = attr->next)
+ {
+ dwarf_vma uvalue = 0;
+
+ data = skip_attr_bytes (attr->form, data, end, pointer_size,
+ offset_size, dwarf_version, & uvalue);
+ if (data == NULL)
+ return;
+
+ switch (attr->attribute)
+ {
+#if 0 /* FIXME: It would be nice to print the name of the type,
+ but this would mean updating a lot of binutils tests. */
+ case DW_AT_name:
+ if (attr->form == DW_FORM_strp)
+ printf ("%s", fetch_indirect_string (uvalue));
+ break;
+#endif
+ case DW_AT_type:
+ /* Recurse. */
+ if (is_nested)
+ {
+ /* FIXME: Warn - or is this expected ?
+ NB/ We need to avoid infinite recursion. */
+ return;
+ }
+ if (uvalue >= (size_t) (end - start))
+ return;
+ get_type_signedness (start, start + uvalue, end, pointer_size,
+ offset_size, dwarf_version, is_signed, TRUE);
+ break;
+
+ case DW_AT_encoding:
+ /* Determine signness. */
+ switch (uvalue)
+ {
+ case DW_ATE_address:
+ /* FIXME - some architectures have signed addresses. */
+ case DW_ATE_boolean:
+ case DW_ATE_unsigned:
+ case DW_ATE_unsigned_char:
+ case DW_ATE_unsigned_fixed:
+ * is_signed = FALSE;
+ break;
+
+ default:
+ case DW_ATE_complex_float:
+ case DW_ATE_float:
+ case DW_ATE_signed:
+ case DW_ATE_signed_char:
+ case DW_ATE_imaginary_float:
+ case DW_ATE_decimal_float:
+ case DW_ATE_signed_fixed:
+ * is_signed = TRUE;
+ break;
+ }
+ break;
+ }
+ }
+}
+
+static void
+read_and_print_leb128 (unsigned char * data,
+ unsigned int * bytes_read,
+ unsigned const char * end,
+ bfd_boolean is_signed)
+{
+ int status;
+ dwarf_vma val = read_leb128 (data, end, is_signed, bytes_read, &status);
+ if (status != 0)
+ report_leb_status (status);
+ else
+ printf ("%s", dwarf_vmatoa (is_signed ? "d" : "u", val));
+}
+
+static void
+display_discr_list (unsigned long form,
+ dwarf_vma uvalue,
+ unsigned char * data,
+ unsigned const char * end,
+ int level)
+{
+ if (uvalue == 0)
+ {
+ printf ("[default]");
+ return;
+ }
+
+ switch (form)
+ {
+ case DW_FORM_block:
+ case DW_FORM_block1:
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ /* Move data pointer back to the start of the byte array. */
+ data -= uvalue;
+ break;
+ default:
+ printf ("<corrupt>\n");
+ warn (_("corrupt discr_list - not using a block form\n"));
+ return;
+ }
+
+ if (uvalue < 2)
+ {
+ printf ("<corrupt>\n");
+ warn (_("corrupt discr_list - block not long enough\n"));
+ return;
+ }
+
+ bfd_boolean is_signed =
+ (level > 0 && level <= MAX_CU_NESTING)
+ ? level_type_signed [level - 1] : FALSE;
+
+ printf ("(");
+ while (uvalue)
+ {
+ unsigned char discriminant;
+ unsigned int bytes_read;
+
+ SAFE_BYTE_GET (discriminant, data, 1, end);
+ -- uvalue;
+ data ++;
+
+ assert (uvalue > 0);
+ switch (discriminant)
+ {
+ case DW_DSC_label:
+ printf ("label ");
+ read_and_print_leb128 (data, & bytes_read, end, is_signed);
+ assert (bytes_read <= uvalue && bytes_read > 0);
+ uvalue -= bytes_read;
+ data += bytes_read;
+ break;
+
+ case DW_DSC_range:
+ printf ("range ");
+ read_and_print_leb128 (data, & bytes_read, end, is_signed);
+ assert (bytes_read <= uvalue && bytes_read > 0);
+ uvalue -= bytes_read;
+ data += bytes_read;
+
+ printf ("..");
+ read_and_print_leb128 (data, & bytes_read, end, is_signed);
+ assert (bytes_read <= uvalue && bytes_read > 0);
+ uvalue -= bytes_read;
+ data += bytes_read;
+ break;
+
+ default:
+ printf ("<corrupt>\n");
+ warn (_("corrupt discr_list - unrecognised discriminant byte %#x\n"),
+ discriminant);
+ return;
+ }
+
+ if (uvalue)
+ printf (", ");
+ }
+
+ if (is_signed)
+ printf (")(signed)");
+ else
+ printf (")(unsigned)");
+}
+
static unsigned char *
read_and_display_attr_value (unsigned long attribute,
unsigned long form,
dwarf_signed_vma implicit_const,
+ unsigned char * start,
unsigned char * data,
unsigned char * end,
dwarf_vma cu_offset,
int do_loc,
struct dwarf_section * section,
struct cu_tu_set * this_set,
- char delimiter)
+ char delimiter,
+ int level)
{
- dwarf_vma uvalue = 0;
- unsigned char *block_start = NULL;
- unsigned char * orig_data = data;
- unsigned int bytes_read;
+ dwarf_signed_vma svalue;
+ dwarf_vma uvalue = 0;
+ unsigned char * block_start = NULL;
+ unsigned char * orig_data = data;
if (data > end || (data == end && form != DW_FORM_flag_present))
{
break;
case DW_FORM_sdata:
- uvalue = read_sleb128 (data, & bytes_read, end);
- data += bytes_read;
+ READ_SLEB (svalue, data, end);
+ uvalue = svalue;
break;
case DW_FORM_GNU_str_index:
- uvalue = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- break;
-
case DW_FORM_ref_udata:
case DW_FORM_udata:
- uvalue = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ case DW_FORM_GNU_addr_index:
+ READ_ULEB (uvalue, data, end);
break;
case DW_FORM_indirect:
- form = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ READ_ULEB (form, data, end);
if (!do_loc)
printf ("%c%s", delimiter, get_FORM_name (form));
if (form == DW_FORM_implicit_const)
- {
- implicit_const = read_sleb128 (data, & bytes_read, end);
- data += bytes_read;
- }
- return read_and_display_attr_value (attribute, form, implicit_const, data,
- end, cu_offset, pointer_size,
+ READ_SLEB (implicit_const, data, end);
+ return read_and_display_attr_value (attribute, form, implicit_const,
+ start, data, end,
+ cu_offset, pointer_size,
offset_size, dwarf_version,
debug_info_p, do_loc,
- section, this_set, delimiter);
- case DW_FORM_GNU_addr_index:
- uvalue = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- break;
+ section, this_set, delimiter, level);
}
switch (form)
data += 16;
break;
- case DW_FORM_string:
- if (!do_loc)
- printf ("%c%.*s", delimiter, (int) (end - data), data);
- data += strnlen ((char *) data, end - data) + 1;
- break;
-
- case DW_FORM_block:
- case DW_FORM_exprloc:
- uvalue = read_uleb128 (data, & bytes_read, end);
- block_start = data + bytes_read;
- if (block_start >= end)
- {
- warn (_("Block ends prematurely\n"));
- uvalue = 0;
- block_start = end;
- }
- /* FIXME: Testing "(block_start + uvalue) < block_start" miscompiles with
- gcc 4.8.3 running on an x86_64 host in 32-bit mode. So we pre-compute
- block_start + uvalue here. */
- data = block_start + uvalue;
- /* PR 17512: file: 008-103549-0.001:0.1. */
- if (block_start + uvalue > end || data < block_start)
- {
- warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
- uvalue = end - block_start;
- }
- if (do_loc)
- data = block_start + uvalue;
- else
- data = display_block (block_start, uvalue, end, delimiter);
- break;
-
- case DW_FORM_block1:
- SAFE_BYTE_GET (uvalue, data, 1, end);
- block_start = data + 1;
- if (block_start >= end)
- {
- warn (_("Block ends prematurely\n"));
- uvalue = 0;
- block_start = end;
- }
- data = block_start + uvalue;
- if (block_start + uvalue > end || data < block_start)
- {
- warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
- uvalue = end - block_start;
- }
- if (do_loc)
- data = block_start + uvalue;
- else
- data = display_block (block_start, uvalue, end, delimiter);
+ case DW_FORM_string:
+ if (!do_loc)
+ printf ("%c%.*s", delimiter, (int) (end - data), data);
+ data += strnlen ((char *) data, end - data) + 1;
break;
- case DW_FORM_block2:
- SAFE_BYTE_GET (uvalue, data, 2, end);
- block_start = data + 2;
+ case DW_FORM_block:
+ case DW_FORM_exprloc:
+ READ_ULEB (uvalue, data, end);
+ do_block:
+ block_start = data;
if (block_start >= end)
{
warn (_("Block ends prematurely\n"));
uvalue = 0;
block_start = end;
}
- data = block_start + uvalue;
- if (block_start + uvalue > end || data < block_start)
- {
- warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
- uvalue = end - block_start;
- }
+
+ uvalue = check_uvalue (block_start, uvalue, end);
+
if (do_loc)
data = block_start + uvalue;
else
data = display_block (block_start, uvalue, end, delimiter);
break;
+ case DW_FORM_block1:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
+ goto do_block;
+
+ case DW_FORM_block2:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
+ goto do_block;
+
case DW_FORM_block4:
- SAFE_BYTE_GET (uvalue, data, 4, end);
- block_start = data + 4;
- /* PR 17512: file: 3371-3907-0.004. */
- if (block_start >= end)
- {
- warn (_("Block ends prematurely\n"));
- uvalue = 0;
- block_start = end;
- }
- data = block_start + uvalue;
- if (block_start + uvalue > end
- /* PR 17531: file: 5b5f0592. */
- || data < block_start)
- {
- warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
- uvalue = end - block_start;
- }
- if (do_loc)
- data = block_start + uvalue;
- else
- data = display_block (block_start, uvalue, end, delimiter);
- break;
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
+ goto do_block;
case DW_FORM_strp:
if (!do_loc)
case DW_FORM_GNU_str_index:
if (!do_loc)
{
- const char *suffix = strrchr (section->name, '.');
- int dwo = (suffix && strcmp (suffix, ".dwo") == 0) ? 1 : 0;
+ const char * suffix = strrchr (section->name, '.');
+ bfd_boolean dwo = (suffix && strcmp (suffix, ".dwo") == 0) ? TRUE : FALSE;
printf (_("%c(indexed string: 0x%s): %s"), delimiter,
dwarf_vmatoa ("x", uvalue),
debug_info_p->have_frame_base [num] = have_frame_base;
if (attribute != DW_AT_GNU_locviews)
{
- debug_info_p->loc_offsets [num] = uvalue;
- debug_info_p->num_loc_offsets++;
- assert (debug_info_p->num_loc_offsets
- - debug_info_p->num_loc_views <= 1);
+ /* Corrupt DWARF info can produce more offsets than views.
+ See PR 23062 for an example. */
+ if (debug_info_p->num_loc_offsets
+ > debug_info_p->num_loc_views)
+ warn (_("More location offset attributes than DW_AT_GNU_locview attributes\n"));
+ else
+ {
+ debug_info_p->loc_offsets [num] = uvalue;
+ debug_info_p->num_loc_offsets++;
+ }
}
else
{
assert (debug_info_p->num_loc_views <= num);
num = debug_info_p->num_loc_views;
- debug_info_p->loc_views [num] = uvalue;
- debug_info_p->num_loc_views++;
- assert (debug_info_p->num_loc_views
- - debug_info_p->num_loc_offsets <= 1);
+ if (num > debug_info_p->num_loc_offsets)
+ warn (_("More DW_AT_GNU_locview attributes than location offset attributes\n"));
+ else
+ {
+ debug_info_p->loc_views [num] = uvalue;
+ debug_info_p->num_loc_views++;
+ }
}
}
break;
}
break;
+ case DW_AT_GNU_dwo_name:
+ case DW_AT_dwo_name:
+ if (need_dwo_info)
+ switch (form)
+ {
+ case DW_FORM_strp:
+ add_dwo_name ((const char *) fetch_indirect_string (uvalue));
+ break;
+ case DW_FORM_GNU_str_index:
+ add_dwo_name (fetch_indexed_string (uvalue, this_set, offset_size, FALSE));
+ break;
+ case DW_FORM_string:
+ add_dwo_name ((const char *) orig_data);
+ break;
+ default:
+ warn (_("Unsupported form (%s) for attribute %s\n"),
+ get_FORM_name (form), get_AT_name (attribute));
+ break;
+ }
+ break;
+
+ case DW_AT_comp_dir:
+ /* FIXME: Also extract a build-id in a CU/TU. */
+ if (need_dwo_info)
+ switch (form)
+ {
+ case DW_FORM_strp:
+ add_dwo_dir ((const char *) fetch_indirect_string (uvalue));
+ break;
+ case DW_FORM_line_strp:
+ add_dwo_dir ((const char *) fetch_indirect_line_string (uvalue));
+ break;
+ case DW_FORM_GNU_str_index:
+ add_dwo_dir (fetch_indexed_string (uvalue, this_set, offset_size, FALSE));
+ break;
+ case DW_FORM_string:
+ add_dwo_dir ((const char *) orig_data);
+ break;
+ default:
+ warn (_("Unsupported form (%s) for attribute %s\n"),
+ get_FORM_name (form), get_AT_name (attribute));
+ break;
+ }
+ break;
+
+ case DW_AT_GNU_dwo_id:
+ if (need_dwo_info)
+ switch (form)
+ {
+ case DW_FORM_data8:
+ /* FIXME: Record the length of the ID as well ? */
+ add_dwo_id ((const char *) (data - 8));
+ break;
+ default:
+ warn (_("Unsupported form (%s) for attribute %s\n"),
+ get_FORM_name (form), get_AT_name (attribute));
+ break;
+ }
+ break;
+
default:
break;
}
/* For some attributes we can display further information. */
switch (attribute)
{
+ case DW_AT_type:
+ if (level >= 0 && level < MAX_CU_NESTING
+ && uvalue < (size_t) (end - start))
+ {
+ bfd_boolean is_signed = FALSE;
+
+ get_type_signedness (start, start + uvalue, end, pointer_size,
+ offset_size, dwarf_version, & is_signed, FALSE);
+ level_type_signed[level] = is_signed;
+ }
+ break;
+
case DW_AT_inline:
printf ("\t");
switch (uvalue)
/* DWARF 4 values. */
case DW_LANG_Python: printf ("(Python)"); break;
/* DWARF 5 values. */
+ case DW_LANG_OpenCL: printf ("(OpenCL)"); break;
case DW_LANG_Go: printf ("(Go)"); break;
+ case DW_LANG_Modula3: printf ("(Modula 3)"); break;
+ case DW_LANG_Haskell: printf ("(Haskell)"); break;
+ case DW_LANG_C_plus_plus_03: printf ("(C++03)"); break;
case DW_LANG_C_plus_plus_11: printf ("(C++11)"); break;
+ case DW_LANG_OCaml: printf ("(OCaml)"); break;
+ case DW_LANG_Rust: printf ("(Rust)"); break;
case DW_LANG_C11: printf ("(C11)"); break;
+ case DW_LANG_Swift: printf ("(Swift)"); break;
+ case DW_LANG_Julia: printf ("(Julia)"); break;
+ case DW_LANG_Dylan: printf ("(Dylan)"); break;
case DW_LANG_C_plus_plus_14: printf ("(C++14)"); break;
case DW_LANG_Fortran03: printf ("(Fortran 03)"); break;
case DW_LANG_Fortran08: printf ("(Fortran 08)"); break;
+ case DW_LANG_RenderScript: printf ("(RenderScript)"); break;
/* MIPS extension. */
case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break;
/* UPC extension. */
case DW_AT_discr_list:
printf ("\t");
- switch (uvalue)
- {
- case DW_DSC_label: printf (_("(label)")); break;
- case DW_DSC_range: printf (_("(range)")); break;
- default: printf (_("(unrecognised)")); break;
- }
+ display_discr_list (form, uvalue, data, end, level);
break;
case DW_AT_frame_base:
}
break;
+ case DW_AT_data_bit_offset:
+ case DW_AT_byte_size:
+ case DW_AT_bit_size:
+ case DW_AT_string_length_byte_size:
+ case DW_AT_string_length_bit_size:
+ case DW_AT_bit_stride:
+ if (form == DW_FORM_exprloc)
+ {
+ printf ("\t(");
+ (void) decode_location_expression (block_start, pointer_size,
+ offset_size, dwarf_version,
+ uvalue, cu_offset, section);
+ printf (")");
+ }
+ break;
+
case DW_AT_import:
{
if (form == DW_FORM_ref_sig8
else
{
unsigned long abbrev_number;
- abbrev_entry * entry;
+ abbrev_entry *entry;
+ unsigned char *p = section->start + uvalue;
- abbrev_number = read_uleb128 (section->start + uvalue, NULL, end);
+ READ_ULEB (abbrev_number, p, end);
printf (_("\t[Abbrev Number: %ld"), abbrev_number);
/* Don't look up abbrev for DW_FORM_ref_addr, as it very often will
return data;
}
-static const char *
-get_AT_name (unsigned long attribute)
-{
- const char *name;
-
- if (attribute == 0)
- return "DW_AT value: 0";
-
- /* One value is shared by the MIPS and HP extensions: */
- if (attribute == DW_AT_MIPS_fde)
- return "DW_AT_MIPS_fde or DW_AT_HP_unmodifiable";
-
- name = get_DW_AT_name (attribute);
-
- if (name == NULL)
- {
- static char buffer[100];
-
- snprintf (buffer, sizeof (buffer), _("Unknown AT value: %lx"),
- attribute);
- return buffer;
- }
-
- return name;
-}
-
static unsigned char *
read_and_display_attr (unsigned long attribute,
unsigned long form,
dwarf_signed_vma implicit_const,
+ unsigned char * start,
unsigned char * data,
unsigned char * end,
dwarf_vma cu_offset,
debug_info * debug_info_p,
int do_loc,
struct dwarf_section * section,
- struct cu_tu_set * this_set)
+ struct cu_tu_set * this_set,
+ int level)
{
if (!do_loc)
printf (" %-18s:", get_AT_name (attribute));
- data = read_and_display_attr_value (attribute, form, implicit_const, data, end,
+ data = read_and_display_attr_value (attribute, form, implicit_const,
+ start, data, end,
cu_offset, pointer_size, offset_size,
dwarf_version, debug_info_p,
- do_loc, section, this_set, ' ');
+ do_loc, section, this_set, ' ', level);
if (!do_loc)
printf ("\n");
return data;
}
/* Like load_debug_section, but if the ordinary call fails, and we are
- following debug links, and we have been able to load a separate debug
- info file, then attempt to load the requested section from the separate
- file. */
+ following debug links, then attempt to load the requested section
+ from one of the separate debug info files. */
static bfd_boolean
load_debug_section_with_follow (enum dwarf_section_display_enum sec_enum,
- void * data)
+ void * handle)
{
- if (load_debug_section (sec_enum, data))
+ if (load_debug_section (sec_enum, handle))
{
- if (data == separate_debug_file)
- debug_displays[sec_enum].section.filename = separate_debug_filename;
-
- /* FIXME: We should check to see if there is a separate debug info file
- that also contains this section, and if so, issue a warning. */
+ if (debug_displays[sec_enum].section.filename == NULL)
+ {
+ /* See if we can associate a filename with this section. */
+ separate_info * i;
+
+ for (i = first_separate_info; i != NULL; i = i->next)
+ if (i->handle == handle)
+ {
+ debug_displays[sec_enum].section.filename = i->filename;
+ break;
+ }
+ }
+
return TRUE;
}
- if (do_follow_links && separate_debug_file != NULL)
- if (load_debug_section (sec_enum, separate_debug_file))
- {
- debug_displays[sec_enum].section.filename = separate_debug_filename;
- return TRUE;
- }
+ if (do_follow_links)
+ {
+ separate_info * i;
+
+ for (i = first_separate_info; i != NULL; i = i->next)
+ {
+ if (load_debug_section (sec_enum, i->handle))
+ {
+ debug_displays[sec_enum].section.filename = i->filename;
+
+ /* FIXME: We should check to see if any of the remaining debug info
+ files also contain this section, and, umm, do something about it. */
+ return TRUE;
+ }
+ }
+ }
return FALSE;
}
}
}
-/* Process the contents of a .debug_info section. If do_loc is non-zero
- then we are scanning for location lists and we do not want to display
- anything to the user. If do_types is non-zero, we are processing
- a .debug_types section instead of a .debug_info section. */
+/* Process the contents of a .debug_info section.
+ If do_loc is TRUE then we are scanning for location lists and dwo tags
+ and we do not want to display anything to the user.
+ If do_types is TRUE, we are processing a .debug_types section instead of
+ a .debug_info section.
+ The information displayed is restricted by the values in DWARF_START_DIE
+ and DWARF_CUTOFF_LEVEL.
+ Returns TRUE upon success. Otherwise an error or warning message is
+ printed and FALSE is returned. */
-static int
-process_debug_info (struct dwarf_section *section,
- void *file,
- enum dwarf_section_display_enum abbrev_sec,
- int do_loc,
- int do_types)
+static bfd_boolean
+process_debug_info (struct dwarf_section * section,
+ void * file,
+ enum dwarf_section_display_enum abbrev_sec,
+ bfd_boolean do_loc,
+ bfd_boolean do_types)
{
unsigned char *start = section->start;
unsigned char *end = start + section->size;
{
warn (_("Reserved length value (0x%s) found in section %s\n"),
dwarf_vmatoa ("x", length), section->name);
- return 0;
+ return FALSE;
}
else
section_begin += length + 4;
{
warn (_("Corrupt unit length (0x%s) found in section %s\n"),
dwarf_vmatoa ("x", length), section->name);
- return 0;
+ return FALSE;
}
}
if (num_units == 0)
{
error (_("No comp units in %s section ?\n"), section->name);
- return 0;
+ return FALSE;
}
/* Then allocate an array to hold the information. */
error (_("Not enough memory for a debug info array of %u entries\n"),
num_units);
alloc_num_debug_info_entries = num_debug_info_entries = 0;
- return 0;
+ return FALSE;
}
+
/* PR 17531: file: 92ca3797.
We cannot rely upon the debug_information array being initialised
before it is used. A corrupt file could easily contain references
{
warn (_("Unable to locate %s section!\n"),
debug_displays [abbrev_sec].section.uncompressed_name);
- return 0;
+ return FALSE;
}
if (!do_loc && dwarf_start_die == 0)
saved_level = -1;
while (tags < start)
{
- unsigned int bytes_read;
unsigned long abbrev_number;
unsigned long die_offset;
abbrev_entry *entry;
die_offset = tags - section_begin;
- abbrev_number = read_uleb128 (tags, & bytes_read, start);
- tags += bytes_read;
+ READ_ULEB (abbrev_number, tags, start);
/* A null DIE marks the end of a list of siblings or it may also be
a section padding. */
}
}
if (dwarf_start_die != 0 && level < saved_level)
- return 1;
+ return TRUE;
continue;
}
}
warn (_("DIE at offset 0x%lx refers to abbreviation number %lu which does not exist\n"),
die_offset, abbrev_number);
- return 0;
+ return FALSE;
}
if (!do_loc && do_printing)
need_base_address = 0;
break;
case DW_TAG_compile_unit:
- need_base_address = 1;
+ need_base_address = 1;
+ need_dwo_info = do_loc;
break;
case DW_TAG_entry_point:
case DW_TAG_subprogram:
if (! do_loc && do_printing)
/* Show the offset from where the tag was extracted. */
printf (" <%lx>", (unsigned long)(tags - section_begin));
-
tags = read_and_display_attr (attr->attribute,
attr->form,
attr->implicit_const,
+ section_begin,
tags,
end,
cu_offset,
debug_info_p,
do_loc || ! do_printing,
section,
- this_set);
+ this_set,
+ level);
}
/* If a locview attribute appears before a location one,
if (!do_loc)
printf ("\n");
- return 1;
+ return TRUE;
}
/* Locate and scan the .debug_info section in the file and record the pointer
(void) load_cu_tu_indexes (file);
if (load_debug_section_with_follow (info, file)
- && process_debug_info (&debug_displays [info].section, file, abbrev, 1, 0))
+ && process_debug_info (&debug_displays [info].section, file, abbrev, TRUE, FALSE))
return num_debug_info_entries;
if (load_debug_section_with_follow (info_dwo, file)
&& process_debug_info (&debug_displays [info_dwo].section, file,
- abbrev_dwo, 1, 0))
+ abbrev_dwo, TRUE, FALSE))
return num_debug_info_entries;
num_debug_info_entries = DEBUG_INFO_UNAVAILABLE;
unsigned char * end,
const DWARF2_Internal_LineInfo * linfo,
struct dwarf_section * section,
- const char * what)
+ bfd_boolean is_dir)
{
unsigned char *format_start, format_count, *format, formati;
dwarf_vma data_count, datai;
- unsigned int bytes_read, namepass, last_entry = 0;
+ unsigned int namepass, last_entry = 0;
SAFE_BYTE_GET_AND_INC (format_count, data, 1, end);
format_start = data;
for (formati = 0; formati < format_count; formati++)
{
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ SKIP_ULEB (data, end);
+ SKIP_ULEB (data, end);
if (data == end)
{
- warn (_("Corrupt %s format table entry\n"), what);
+ if (is_dir)
+ warn (_("Corrupt directory format table entry\n"));
+ else
+ warn (_("Corrupt file name format table entry\n"));
return data;
}
}
- data_count = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ READ_ULEB (data_count, data, end);
if (data == end)
{
- warn (_("Corrupt %s list\n"), what);
+ if (is_dir)
+ warn (_("Corrupt directory list\n"));
+ else
+ warn (_("Corrupt file name list\n"));
return data;
}
if (data_count == 0)
{
- printf (_("\n The %s Table is empty.\n"), what);
+ if (is_dir)
+ printf (_("\n The Directory Table is empty.\n"));
+ else
+ printf (_("\n The File Name Table is empty.\n"));
return data;
}
- printf (_("\n The %s Table (offset 0x%lx):\n"), what,
- (long)(data - start));
+ if (is_dir)
+ printf (_("\n The Directory Table (offset 0x%lx):\n"),
+ (long) (data - start));
+ else
+ printf (_("\n The File Name Table (offset 0x%lx):\n"),
+ (long) (data - start));
printf (_(" Entry"));
/* Delay displaying name as the last entry for better screen layout. */
{
dwarf_vma content_type;
- content_type = read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
+ READ_ULEB (content_type, format, end);
if ((content_type == DW_LNCT_path) == (namepass == 1))
switch (content_type)
{
printf (_("\t(Unknown format content type %s)"),
dwarf_vmatoa ("u", content_type));
}
- read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
+ SKIP_ULEB (format, end);
}
}
putchar ('\n');
{
dwarf_vma content_type, form;
- content_type = read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
- form = read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
- data = read_and_display_attr_value (0, form, 0, data, end, 0, 0,
- linfo->li_offset_size,
+ READ_ULEB (content_type, format, end);
+ READ_ULEB (form, format, end);
+ data = read_and_display_attr_value (0, form, 0, start, data, end,
+ 0, 0, linfo->li_offset_size,
linfo->li_version, NULL,
((content_type == DW_LNCT_path) != (namepass == 1)),
- section, NULL, '\t');
+ section, NULL, '\t', -1);
}
}
if (data == end)
{
- warn (_("Corrupt %s entries list\n"), what);
+ if (is_dir)
+ warn (_("Corrupt directory entries list\n"));
+ else
+ warn (_("Corrupt file name entries list\n"));
return data;
}
putchar ('\n');
load_debug_section_with_follow (line_str, file);
data = display_formatted_table (data, start, end, &linfo, section,
- _("Directory"));
+ TRUE);
data = display_formatted_table (data, start, end, &linfo, section,
- _("File name"));
+ FALSE);
}
else
{
while (data < end && *data != 0)
{
unsigned char *name;
- unsigned int bytes_read;
+ dwarf_vma val;
printf (" %d\t", ++state_machine_regs.last_file_entry);
name = data;
data += strnlen ((char *) data, end - data) + 1;
- printf ("%s\t",
- dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end)));
- data += bytes_read;
- printf ("%s\t",
- dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end)));
- data += bytes_read;
- printf ("%s\t",
- dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end)));
- data += bytes_read;
+ READ_ULEB (val, data, end);
+ printf ("%s\t", dwarf_vmatoa ("u", val));
+ READ_ULEB (val, data, end);
+ printf ("%s\t", dwarf_vmatoa ("u", val));
+ READ_ULEB (val, data, end);
+ printf ("%s\t", dwarf_vmatoa ("u", val));
printf ("%.*s\n", (int)(end - name), name);
if (data == end)
unsigned char op_code;
dwarf_signed_vma adv;
dwarf_vma uladv;
- unsigned int bytes_read;
printf (" [0x%08lx]", (long)(data - start));
putchar ('\n');
state_machine_regs.view++;
}
- else switch (op_code)
- {
- case DW_LNS_extended_op:
- data += process_extended_line_op (data, linfo.li_default_is_stmt, end);
- break;
-
- case DW_LNS_copy:
- printf (_(" Copy"));
- if (verbose_view || state_machine_regs.view)
- printf (_(" (view %u)\n"), state_machine_regs.view);
- else
- putchar ('\n');
- state_machine_regs.view++;
- break;
-
- case DW_LNS_advance_pc:
- uladv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- if (linfo.li_max_ops_per_insn == 1)
- {
- uladv *= linfo.li_min_insn_length;
- state_machine_regs.address += uladv;
- if (uladv)
- state_machine_regs.view = 0;
- printf (_(" Advance PC by %s to 0x%s%s\n"),
- dwarf_vmatoa ("u", uladv),
- dwarf_vmatoa ("x", state_machine_regs.address),
- verbose_view && uladv
- ? _(" (reset view)") : "");
- }
- else
- {
- unsigned addrdelta
- = ((state_machine_regs.op_index + uladv)
- / linfo.li_max_ops_per_insn)
- * linfo.li_min_insn_length;
- state_machine_regs.address
- += addrdelta;
- state_machine_regs.op_index
- = (state_machine_regs.op_index + uladv)
- % linfo.li_max_ops_per_insn;
- if (addrdelta)
- state_machine_regs.view = 0;
- printf (_(" Advance PC by %s to 0x%s[%d]%s\n"),
- dwarf_vmatoa ("u", uladv),
- dwarf_vmatoa ("x", state_machine_regs.address),
- state_machine_regs.op_index,
- verbose_view && addrdelta
- ? _(" (reset view)") : "");
- }
- break;
-
- case DW_LNS_advance_line:
- adv = read_sleb128 (data, & bytes_read, end);
- data += bytes_read;
- state_machine_regs.line += adv;
- printf (_(" Advance Line by %s to %d\n"),
- dwarf_vmatoa ("d", adv),
- state_machine_regs.line);
- break;
-
- case DW_LNS_set_file:
- adv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- printf (_(" Set File Name to entry %s in the File Name Table\n"),
- dwarf_vmatoa ("d", adv));
- state_machine_regs.file = adv;
- break;
-
- case DW_LNS_set_column:
- uladv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- printf (_(" Set column to %s\n"),
- dwarf_vmatoa ("u", uladv));
- state_machine_regs.column = uladv;
- break;
-
- case DW_LNS_negate_stmt:
- adv = state_machine_regs.is_stmt;
- adv = ! adv;
- printf (_(" Set is_stmt to %s\n"), dwarf_vmatoa ("d", adv));
- state_machine_regs.is_stmt = adv;
- break;
-
- case DW_LNS_set_basic_block:
- printf (_(" Set basic block\n"));
- state_machine_regs.basic_block = 1;
- break;
-
- case DW_LNS_const_add_pc:
- uladv = ((255 - linfo.li_opcode_base) / linfo.li_line_range);
- if (linfo.li_max_ops_per_insn)
- {
- uladv *= linfo.li_min_insn_length;
- state_machine_regs.address += uladv;
- if (uladv)
- state_machine_regs.view = 0;
- printf (_(" Advance PC by constant %s to 0x%s%s\n"),
- dwarf_vmatoa ("u", uladv),
- dwarf_vmatoa ("x", state_machine_regs.address),
- verbose_view && uladv
- ? _(" (reset view)") : "");
- }
- else
- {
- unsigned addrdelta
- = ((state_machine_regs.op_index + uladv)
- / linfo.li_max_ops_per_insn)
- * linfo.li_min_insn_length;
- state_machine_regs.address
- += addrdelta;
- state_machine_regs.op_index
- = (state_machine_regs.op_index + uladv)
- % linfo.li_max_ops_per_insn;
- if (addrdelta)
- state_machine_regs.view = 0;
- printf (_(" Advance PC by constant %s to 0x%s[%d]%s\n"),
- dwarf_vmatoa ("u", uladv),
- dwarf_vmatoa ("x", state_machine_regs.address),
- state_machine_regs.op_index,
- verbose_view && addrdelta
- ? _(" (reset view)") : "");
- }
- break;
-
- case DW_LNS_fixed_advance_pc:
- SAFE_BYTE_GET_AND_INC (uladv, data, 2, end);
- state_machine_regs.address += uladv;
- state_machine_regs.op_index = 0;
- printf (_(" Advance PC by fixed size amount %s to 0x%s\n"),
- dwarf_vmatoa ("u", uladv),
- dwarf_vmatoa ("x", state_machine_regs.address));
- /* Do NOT reset view. */
- break;
-
- case DW_LNS_set_prologue_end:
- printf (_(" Set prologue_end to true\n"));
- break;
-
- case DW_LNS_set_epilogue_begin:
- printf (_(" Set epilogue_begin to true\n"));
- break;
-
- case DW_LNS_set_isa:
- uladv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- printf (_(" Set ISA to %s\n"), dwarf_vmatoa ("u", uladv));
- break;
-
- default:
- printf (_(" Unknown opcode %d with operands: "), op_code);
-
- if (standard_opcodes != NULL)
- for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
- {
- printf ("0x%s%s", dwarf_vmatoa ("x", read_uleb128 (data,
- &bytes_read, end)),
- i == 1 ? "" : ", ");
- data += bytes_read;
- }
- putchar ('\n');
- break;
- }
+ else
+ switch (op_code)
+ {
+ case DW_LNS_extended_op:
+ data += process_extended_line_op (data,
+ linfo.li_default_is_stmt,
+ end);
+ break;
+
+ case DW_LNS_copy:
+ printf (_(" Copy"));
+ if (verbose_view || state_machine_regs.view)
+ printf (_(" (view %u)\n"), state_machine_regs.view);
+ else
+ putchar ('\n');
+ state_machine_regs.view++;
+ break;
+
+ case DW_LNS_advance_pc:
+ READ_ULEB (uladv, data, end);
+ if (linfo.li_max_ops_per_insn == 1)
+ {
+ uladv *= linfo.li_min_insn_length;
+ state_machine_regs.address += uladv;
+ if (uladv)
+ state_machine_regs.view = 0;
+ printf (_(" Advance PC by %s to 0x%s%s\n"),
+ dwarf_vmatoa ("u", uladv),
+ dwarf_vmatoa ("x", state_machine_regs.address),
+ verbose_view && uladv
+ ? _(" (reset view)") : "");
+ }
+ else
+ {
+ unsigned addrdelta
+ = ((state_machine_regs.op_index + uladv)
+ / linfo.li_max_ops_per_insn)
+ * linfo.li_min_insn_length;
+ state_machine_regs.address
+ += addrdelta;
+ state_machine_regs.op_index
+ = (state_machine_regs.op_index + uladv)
+ % linfo.li_max_ops_per_insn;
+ if (addrdelta)
+ state_machine_regs.view = 0;
+ printf (_(" Advance PC by %s to 0x%s[%d]%s\n"),
+ dwarf_vmatoa ("u", uladv),
+ dwarf_vmatoa ("x", state_machine_regs.address),
+ state_machine_regs.op_index,
+ verbose_view && addrdelta
+ ? _(" (reset view)") : "");
+ }
+ break;
+
+ case DW_LNS_advance_line:
+ READ_SLEB (adv, data, end);
+ state_machine_regs.line += adv;
+ printf (_(" Advance Line by %s to %d\n"),
+ dwarf_vmatoa ("d", adv),
+ state_machine_regs.line);
+ break;
+
+ case DW_LNS_set_file:
+ READ_ULEB (uladv, data, end);
+ printf (_(" Set File Name to entry %s in the File Name Table\n"),
+ dwarf_vmatoa ("u", uladv));
+ state_machine_regs.file = uladv;
+ break;
+
+ case DW_LNS_set_column:
+ READ_ULEB (uladv, data, end);
+ printf (_(" Set column to %s\n"),
+ dwarf_vmatoa ("u", uladv));
+ state_machine_regs.column = uladv;
+ break;
+
+ case DW_LNS_negate_stmt:
+ adv = state_machine_regs.is_stmt;
+ adv = ! adv;
+ printf (_(" Set is_stmt to %s\n"), dwarf_vmatoa ("d", adv));
+ state_machine_regs.is_stmt = adv;
+ break;
+
+ case DW_LNS_set_basic_block:
+ printf (_(" Set basic block\n"));
+ state_machine_regs.basic_block = 1;
+ break;
+
+ case DW_LNS_const_add_pc:
+ uladv = ((255 - linfo.li_opcode_base) / linfo.li_line_range);
+ if (linfo.li_max_ops_per_insn)
+ {
+ uladv *= linfo.li_min_insn_length;
+ state_machine_regs.address += uladv;
+ if (uladv)
+ state_machine_regs.view = 0;
+ printf (_(" Advance PC by constant %s to 0x%s%s\n"),
+ dwarf_vmatoa ("u", uladv),
+ dwarf_vmatoa ("x", state_machine_regs.address),
+ verbose_view && uladv
+ ? _(" (reset view)") : "");
+ }
+ else
+ {
+ unsigned addrdelta
+ = ((state_machine_regs.op_index + uladv)
+ / linfo.li_max_ops_per_insn)
+ * linfo.li_min_insn_length;
+ state_machine_regs.address
+ += addrdelta;
+ state_machine_regs.op_index
+ = (state_machine_regs.op_index + uladv)
+ % linfo.li_max_ops_per_insn;
+ if (addrdelta)
+ state_machine_regs.view = 0;
+ printf (_(" Advance PC by constant %s to 0x%s[%d]%s\n"),
+ dwarf_vmatoa ("u", uladv),
+ dwarf_vmatoa ("x", state_machine_regs.address),
+ state_machine_regs.op_index,
+ verbose_view && addrdelta
+ ? _(" (reset view)") : "");
+ }
+ break;
+
+ case DW_LNS_fixed_advance_pc:
+ SAFE_BYTE_GET_AND_INC (uladv, data, 2, end);
+ state_machine_regs.address += uladv;
+ state_machine_regs.op_index = 0;
+ printf (_(" Advance PC by fixed size amount %s to 0x%s\n"),
+ dwarf_vmatoa ("u", uladv),
+ dwarf_vmatoa ("x", state_machine_regs.address));
+ /* Do NOT reset view. */
+ break;
+
+ case DW_LNS_set_prologue_end:
+ printf (_(" Set prologue_end to true\n"));
+ break;
+
+ case DW_LNS_set_epilogue_begin:
+ printf (_(" Set epilogue_begin to true\n"));
+ break;
+
+ case DW_LNS_set_isa:
+ READ_ULEB (uladv, data, end);
+ printf (_(" Set ISA to %s\n"), dwarf_vmatoa ("u", uladv));
+ break;
+
+ default:
+ printf (_(" Unknown opcode %d with operands: "), op_code);
+
+ if (standard_opcodes != NULL)
+ for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
+ {
+ READ_ULEB (uladv, data, end);
+ printf ("0x%s%s", dwarf_vmatoa ("x", uladv),
+ i == 1 ? "" : ", ");
+ }
+ putchar ('\n');
+ break;
+ }
}
putchar ('\n');
}
static int
display_debug_lines_decoded (struct dwarf_section * section,
+ unsigned char * start,
unsigned char * data,
unsigned char * end,
void * fileptr)
{
unsigned char *format_start, format_count, *format;
dwarf_vma formati, entryi;
- unsigned int bytes_read;
load_debug_section_with_follow (line_str, fileptr);
format_start = data;
for (formati = 0; formati < format_count; formati++)
{
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ SKIP_ULEB (data, end);
+ SKIP_ULEB (data, end);
}
- n_directories = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ READ_ULEB (n_directories, data, end);
if (data == end)
{
warn (_("Corrupt directories list\n"));
dwarf_vma content_type, form;
dwarf_vma uvalue;
- content_type = read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
- form = read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
+ READ_ULEB (content_type, format, end);
+ READ_ULEB (form, format, end);
if (data == end)
{
warn (_("Corrupt directories list\n"));
}
break;
}
- data = read_and_display_attr_value (0, form, 0, data, end,
- 0, 0,
+ data = read_and_display_attr_value (0, form, 0, start,
+ data, end, 0, 0,
linfo.li_offset_size,
linfo.li_version,
NULL, 1, section,
- NULL, '\t');
+ NULL, '\t', -1);
}
if (data == end)
{
format_start = data;
for (formati = 0; formati < format_count; formati++)
{
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ SKIP_ULEB (data, end);
+ SKIP_ULEB (data, end);
}
- n_files = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ READ_ULEB (n_files, data, end);
if (data == end)
{
warn (_("Corrupt file name list\n"));
{
dwarf_vma content_type, form;
dwarf_vma uvalue;
+ unsigned char *tmp;
- content_type = read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
- form = read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
+ READ_ULEB (content_type, format, end);
+ READ_ULEB (form, format, end);
if (data == end)
{
warn (_("Corrupt file name list\n"));
end);
break;
case DW_FORM_udata:
- file->directory_index = read_uleb128 (data, NULL,
- end);
+ tmp = data;
+ READ_ULEB (file->directory_index, tmp, end);
break;
}
break;
}
- data = read_and_display_attr_value (0, form, 0, data, end,
- 0, 0,
+ data = read_and_display_attr_value (0, form, 0, start,
+ data, end, 0, 0,
linfo.li_offset_size,
linfo.li_version,
NULL, 1, section,
- NULL, '\t');
+ NULL, '\t', -1);
}
if (data == end)
{
while (data < end && *data != 0)
{
- unsigned int bytes_read;
-
- /* Skip Name, directory index, last modification time and length
- of file. */
+ /* Skip Name, directory index, last modification
+ time and length of file. */
data += strnlen ((char *) data, end - data) + 1;
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
-
+ SKIP_ULEB (data, end);
+ SKIP_ULEB (data, end);
+ SKIP_ULEB (data, end);
n_files++;
}
i = 0;
while (*ptr_file_name_table != 0)
{
- unsigned int bytes_read;
-
file_table[i].name = ptr_file_name_table;
ptr_file_name_table += strnlen ((char *) ptr_file_name_table,
end - ptr_file_name_table) + 1;
/* We are not interested in directory, time or size. */
- file_table[i].directory_index = read_uleb128 (ptr_file_name_table,
- & bytes_read, end);
- ptr_file_name_table += bytes_read;
- file_table[i].modification_date = read_uleb128 (ptr_file_name_table,
- & bytes_read, end);
- ptr_file_name_table += bytes_read;
- file_table[i].length = read_uleb128 (ptr_file_name_table, & bytes_read, end);
- ptr_file_name_table += bytes_read;
+ READ_ULEB (file_table[i].directory_index,
+ ptr_file_name_table, end);
+ READ_ULEB (file_table[i].modification_date,
+ ptr_file_name_table, end);
+ READ_ULEB (file_table[i].length,
+ ptr_file_name_table, end);
i++;
}
i = 0;
printf ("%s:\n", file_table[0].name);
}
- printf (_("File name Line number Starting address View\n"));
+ printf (_("File name Line number Starting address View Stmt\n"));
saved_linfo = linfo;
}
int xop;
int adv;
unsigned long int uladv;
- unsigned int bytes_read;
int is_special_opcode = 0;
op_code = *data++;
is_special_opcode = 1;
/* Increment view after printing this row. */
}
- else switch (op_code)
- {
- case DW_LNS_extended_op:
- {
- unsigned int ext_op_code_len;
- unsigned char ext_op_code;
- unsigned char *op_code_data = data;
-
- ext_op_code_len = read_uleb128 (op_code_data, &bytes_read,
- end_of_sequence);
- op_code_data += bytes_read;
-
- if (ext_op_code_len == 0)
- {
- warn (_("Badly formed extended line op encountered!\n"));
- break;
- }
- ext_op_code_len += bytes_read;
- ext_op_code = *op_code_data++;
- xop = ext_op_code;
- xop = -xop;
-
- switch (ext_op_code)
- {
- case DW_LNE_end_sequence:
- /* Reset stuff after printing this row. */
- break;
- case DW_LNE_set_address:
- SAFE_BYTE_GET_AND_INC (state_machine_regs.address,
- op_code_data,
- ext_op_code_len - bytes_read - 1,
- end);
- state_machine_regs.op_index = 0;
- state_machine_regs.view = 0;
- break;
- case DW_LNE_define_file:
- {
- file_table = (File_Entry *) xrealloc
- (file_table, (n_files + 1) * sizeof (File_Entry));
-
- ++state_machine_regs.last_file_entry;
- /* Source file name. */
- file_table[n_files].name = op_code_data;
- op_code_data += strlen ((char *) op_code_data) + 1;
- /* Directory index. */
- file_table[n_files].directory_index =
- read_uleb128 (op_code_data, & bytes_read,
- end_of_sequence);
- op_code_data += bytes_read;
- /* Last modification time. */
- file_table[n_files].modification_date =
- read_uleb128 (op_code_data, & bytes_read,
- end_of_sequence);
- op_code_data += bytes_read;
- /* File length. */
- file_table[n_files].length =
- read_uleb128 (op_code_data, & bytes_read,
- end_of_sequence);
-
- n_files++;
- break;
- }
- case DW_LNE_set_discriminator:
- case DW_LNE_HP_set_sequence:
- /* Simply ignored. */
- break;
-
- default:
- printf (_("UNKNOWN (%u): length %d\n"),
- ext_op_code, ext_op_code_len - bytes_read);
- break;
- }
- data += ext_op_code_len;
- break;
- }
- case DW_LNS_copy:
- /* Increment view after printing this row. */
- break;
-
- case DW_LNS_advance_pc:
- uladv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- if (linfo.li_max_ops_per_insn == 1)
- {
- uladv *= linfo.li_min_insn_length;
- state_machine_regs.address += uladv;
- if (uladv)
- state_machine_regs.view = 0;
- }
- else
- {
- unsigned addrdelta
- = ((state_machine_regs.op_index + uladv)
- / linfo.li_max_ops_per_insn)
- * linfo.li_min_insn_length;
- state_machine_regs.address
- += addrdelta;
- state_machine_regs.op_index
- = (state_machine_regs.op_index + uladv)
- % linfo.li_max_ops_per_insn;
- if (addrdelta)
- state_machine_regs.view = 0;
- }
- break;
-
- case DW_LNS_advance_line:
- adv = read_sleb128 (data, & bytes_read, end);
- data += bytes_read;
- state_machine_regs.line += adv;
- break;
-
- case DW_LNS_set_file:
- adv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- state_machine_regs.file = adv;
-
- {
- unsigned file = state_machine_regs.file - 1;
- unsigned dir;
-
- if (file_table == NULL || n_files == 0)
- printf (_("\n [Use file table entry %d]\n"), file);
- /* PR 20439 */
- else if (file >= n_files)
- {
- warn (_("file index %u > number of files %u\n"), file + 1, n_files);
- printf (_("\n <over large file table index %u>"), file);
- }
- else if ((dir = file_table[file].directory_index) == 0)
- /* If directory index is 0, that means current directory. */
- printf ("\n./%s:[++]\n", file_table[file].name);
- else if (directory_table == NULL || n_directories == 0)
- printf (_("\n [Use file %s in directory table entry %d]\n"),
- file_table[file].name, dir);
- /* PR 20439 */
- else if (dir > n_directories)
- {
- warn (_("directory index %u > number of directories %s\n"),
- dir, dwarf_vmatoa ("u", n_directories));
- printf (_("\n <over large directory table entry %u>\n"), dir);
- }
- else
- printf ("\n%s/%s:\n",
- /* The directory index starts counting at 1. */
- directory_table[dir - 1], file_table[file].name);
- }
- break;
-
- case DW_LNS_set_column:
- uladv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- state_machine_regs.column = uladv;
- break;
-
- case DW_LNS_negate_stmt:
- adv = state_machine_regs.is_stmt;
- adv = ! adv;
- state_machine_regs.is_stmt = adv;
- break;
-
- case DW_LNS_set_basic_block:
- state_machine_regs.basic_block = 1;
- break;
-
- case DW_LNS_const_add_pc:
- uladv = ((255 - linfo.li_opcode_base) / linfo.li_line_range);
- if (linfo.li_max_ops_per_insn == 1)
- {
- uladv *= linfo.li_min_insn_length;
- state_machine_regs.address += uladv;
- if (uladv)
- state_machine_regs.view = 0;
- }
- else
- {
- unsigned addrdelta
- = ((state_machine_regs.op_index + uladv)
- / linfo.li_max_ops_per_insn)
- * linfo.li_min_insn_length;
- state_machine_regs.address
- += addrdelta;
- state_machine_regs.op_index
- = (state_machine_regs.op_index + uladv)
- % linfo.li_max_ops_per_insn;
- if (addrdelta)
- state_machine_regs.view = 0;
- }
- break;
-
- case DW_LNS_fixed_advance_pc:
- SAFE_BYTE_GET_AND_INC (uladv, data, 2, end);
- state_machine_regs.address += uladv;
- state_machine_regs.op_index = 0;
- /* Do NOT reset view. */
- break;
-
- case DW_LNS_set_prologue_end:
- break;
-
- case DW_LNS_set_epilogue_begin:
- break;
-
- case DW_LNS_set_isa:
- uladv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- printf (_(" Set ISA to %lu\n"), uladv);
- break;
-
- default:
- printf (_(" Unknown opcode %d with operands: "), op_code);
-
- if (standard_opcodes != NULL)
- for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
- {
- printf ("0x%s%s", dwarf_vmatoa ("x", read_uleb128 (data,
- &bytes_read, end)),
- i == 1 ? "" : ", ");
- data += bytes_read;
- }
- putchar ('\n');
- break;
- }
+ else
+ switch (op_code)
+ {
+ case DW_LNS_extended_op:
+ {
+ unsigned int ext_op_code_len;
+ unsigned char ext_op_code;
+ unsigned char *op_code_end;
+ unsigned char *op_code_data = data;
+
+ READ_ULEB (ext_op_code_len, op_code_data, end_of_sequence);
+ op_code_end = op_code_data + ext_op_code_len;
+ if (ext_op_code_len == 0 || op_code_end > end_of_sequence)
+ {
+ warn (_("Badly formed extended line op encountered!\n"));
+ break;
+ }
+ ext_op_code = *op_code_data++;
+ xop = ext_op_code;
+ xop = -xop;
+
+ switch (ext_op_code)
+ {
+ case DW_LNE_end_sequence:
+ /* Reset stuff after printing this row. */
+ break;
+ case DW_LNE_set_address:
+ SAFE_BYTE_GET_AND_INC (state_machine_regs.address,
+ op_code_data,
+ op_code_end - op_code_data,
+ op_code_end);
+ state_machine_regs.op_index = 0;
+ state_machine_regs.view = 0;
+ break;
+ case DW_LNE_define_file:
+ file_table = (File_Entry *) xrealloc
+ (file_table, (n_files + 1) * sizeof (File_Entry));
+
+ ++state_machine_regs.last_file_entry;
+ /* Source file name. */
+ file_table[n_files].name = op_code_data;
+ op_code_data += strlen ((char *) op_code_data) + 1;
+ /* Directory index. */
+ READ_ULEB (file_table[n_files].directory_index,
+ op_code_data, op_code_end);
+ /* Last modification time. */
+ READ_ULEB (file_table[n_files].modification_date,
+ op_code_data, op_code_end);
+ /* File length. */
+ READ_ULEB (file_table[n_files].length,
+ op_code_data, op_code_end);
+ n_files++;
+ break;
+
+ case DW_LNE_set_discriminator:
+ case DW_LNE_HP_set_sequence:
+ /* Simply ignored. */
+ break;
+
+ default:
+ printf (_("UNKNOWN (%u): length %ld\n"),
+ ext_op_code, (long int) (op_code_data - data));
+ break;
+ }
+ data = op_code_end;
+ break;
+ }
+ case DW_LNS_copy:
+ /* Increment view after printing this row. */
+ break;
+
+ case DW_LNS_advance_pc:
+ READ_ULEB (uladv, data, end);
+ if (linfo.li_max_ops_per_insn == 1)
+ {
+ uladv *= linfo.li_min_insn_length;
+ state_machine_regs.address += uladv;
+ if (uladv)
+ state_machine_regs.view = 0;
+ }
+ else
+ {
+ unsigned addrdelta
+ = ((state_machine_regs.op_index + uladv)
+ / linfo.li_max_ops_per_insn)
+ * linfo.li_min_insn_length;
+ state_machine_regs.address
+ += addrdelta;
+ state_machine_regs.op_index
+ = (state_machine_regs.op_index + uladv)
+ % linfo.li_max_ops_per_insn;
+ if (addrdelta)
+ state_machine_regs.view = 0;
+ }
+ break;
+
+ case DW_LNS_advance_line:
+ READ_SLEB (adv, data, end);
+ state_machine_regs.line += adv;
+ break;
+
+ case DW_LNS_set_file:
+ READ_ULEB (uladv, data, end);
+ state_machine_regs.file = uladv;
+
+ {
+ unsigned file = state_machine_regs.file - 1;
+ unsigned dir;
+
+ if (file_table == NULL || n_files == 0)
+ printf (_("\n [Use file table entry %d]\n"), file);
+ /* PR 20439 */
+ else if (file >= n_files)
+ {
+ warn (_("file index %u > number of files %u\n"), file + 1, n_files);
+ printf (_("\n <over large file table index %u>"), file);
+ }
+ else if ((dir = file_table[file].directory_index) == 0)
+ /* If directory index is 0, that means current directory. */
+ printf ("\n./%s:[++]\n", file_table[file].name);
+ else if (directory_table == NULL || n_directories == 0)
+ printf (_("\n [Use file %s in directory table entry %d]\n"),
+ file_table[file].name, dir);
+ /* PR 20439 */
+ else if (dir > n_directories)
+ {
+ warn (_("directory index %u > number of directories %s\n"),
+ dir, dwarf_vmatoa ("u", n_directories));
+ printf (_("\n <over large directory table entry %u>\n"), dir);
+ }
+ else
+ printf ("\n%s/%s:\n",
+ /* The directory index starts counting at 1. */
+ directory_table[dir - 1], file_table[file].name);
+ }
+ break;
+
+ case DW_LNS_set_column:
+ READ_ULEB (uladv, data, end);
+ state_machine_regs.column = uladv;
+ break;
+
+ case DW_LNS_negate_stmt:
+ adv = state_machine_regs.is_stmt;
+ adv = ! adv;
+ state_machine_regs.is_stmt = adv;
+ break;
+
+ case DW_LNS_set_basic_block:
+ state_machine_regs.basic_block = 1;
+ break;
+
+ case DW_LNS_const_add_pc:
+ uladv = ((255 - linfo.li_opcode_base) / linfo.li_line_range);
+ if (linfo.li_max_ops_per_insn == 1)
+ {
+ uladv *= linfo.li_min_insn_length;
+ state_machine_regs.address += uladv;
+ if (uladv)
+ state_machine_regs.view = 0;
+ }
+ else
+ {
+ unsigned addrdelta
+ = ((state_machine_regs.op_index + uladv)
+ / linfo.li_max_ops_per_insn)
+ * linfo.li_min_insn_length;
+ state_machine_regs.address
+ += addrdelta;
+ state_machine_regs.op_index
+ = (state_machine_regs.op_index + uladv)
+ % linfo.li_max_ops_per_insn;
+ if (addrdelta)
+ state_machine_regs.view = 0;
+ }
+ break;
+
+ case DW_LNS_fixed_advance_pc:
+ SAFE_BYTE_GET_AND_INC (uladv, data, 2, end);
+ state_machine_regs.address += uladv;
+ state_machine_regs.op_index = 0;
+ /* Do NOT reset view. */
+ break;
+
+ case DW_LNS_set_prologue_end:
+ break;
+
+ case DW_LNS_set_epilogue_begin:
+ break;
+
+ case DW_LNS_set_isa:
+ READ_ULEB (uladv, data, end);
+ printf (_(" Set ISA to %lu\n"), uladv);
+ break;
+
+ default:
+ printf (_(" Unknown opcode %d with operands: "), op_code);
+
+ if (standard_opcodes != NULL)
+ for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
+ {
+ dwarf_vma val;
+
+ READ_ULEB (val, data, end);
+ printf ("0x%s%s", dwarf_vmatoa ("x", val),
+ i == 1 ? "" : ", ");
+ }
+ putchar ('\n');
+ break;
+ }
/* Only Special opcodes, DW_LNS_copy and DW_LNE_end_sequence adds a row
to the DWARF address/line matrix. */
}
if (state_machine_regs.view)
- printf (" %6u\n", state_machine_regs.view);
+ printf (" %6u", state_machine_regs.view);
else
- putchar ('\n');
+ printf (" ");
+
+ if (state_machine_regs.is_stmt)
+ printf (" x");
+
+ putchar ('\n');
state_machine_regs.view++;
if (xop == -DW_LNE_end_sequence)
retValRaw = display_debug_lines_raw (section, data, end, file);
if (do_debug_lines & FLAG_DEBUG_LINES_DECODED)
- retValDecoded = display_debug_lines_decoded (section, data, end, file);
+ retValDecoded = display_debug_lines_decoded (section, data, data, end, file);
if (!retValRaw || !retValDecoded)
return 0;
unsigned char *start = section->start;
unsigned char *end = start + section->size;
unsigned char *curr = start;
- unsigned int bytes_read;
enum dwarf_macinfo_record_type op;
introduce (section, FALSE);
{
unsigned int filenum;
- lineno = read_uleb128 (curr, & bytes_read, end);
- curr += bytes_read;
- filenum = read_uleb128 (curr, & bytes_read, end);
- curr += bytes_read;
-
+ READ_ULEB (lineno, curr, end);
+ READ_ULEB (filenum, curr, end);
printf (_(" DW_MACINFO_start_file - lineno: %d filenum: %d\n"),
lineno, filenum);
}
break;
case DW_MACINFO_define:
- lineno = read_uleb128 (curr, & bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (lineno, curr, end);
string = curr;
curr += strnlen ((char *) string, end - string) + 1;
printf (_(" DW_MACINFO_define - lineno : %d macro : %s\n"),
break;
case DW_MACINFO_undef:
- lineno = read_uleb128 (curr, & bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (lineno, curr, end);
string = curr;
curr += strnlen ((char *) string, end - string) + 1;
printf (_(" DW_MACINFO_undef - lineno : %d macro : %s\n"),
{
unsigned int constant;
- constant = read_uleb128 (curr, & bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (constant, curr, end);
string = curr;
curr += strnlen ((char *) string, end - string) + 1;
printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %s\n"),
struct dwarf_section *section = &debug_displays [line].section;
unsigned char *hdrptr, *dirtable, *file_name;
unsigned int offset_size, initial_length_size;
- unsigned int version, opcode_base, bytes_read;
+ unsigned int version, opcode_base;
dwarf_vma length, diridx;
const unsigned char * end;
for (; hdrptr < end && *hdrptr != '\0' && fileidx > 1; fileidx--)
{
hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1;
- read_uleb128 (hdrptr, &bytes_read, end);
- hdrptr += bytes_read;
- read_uleb128 (hdrptr, &bytes_read, end);
- hdrptr += bytes_read;
- read_uleb128 (hdrptr, &bytes_read, end);
- hdrptr += bytes_read;
+ SKIP_ULEB (hdrptr, end);
+ SKIP_ULEB (hdrptr, end);
+ SKIP_ULEB (hdrptr, end);
}
if (hdrptr >= end || *hdrptr == '\0')
return NULL;
hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1;
if (hdrptr >= end)
return NULL;
- diridx = read_uleb128 (hdrptr, &bytes_read, end);
+ READ_ULEB (diridx, hdrptr, end);
if (diridx == 0)
return file_name;
for (; dirtable < end && *dirtable != '\0' && diridx > 1; diridx--)
unsigned char *end = start + section->size;
unsigned char *curr = start;
unsigned char *extended_op_buf[256];
- unsigned int bytes_read;
load_debug_section_with_follow (str, file);
load_debug_section_with_follow (line, file);
{
SAFE_BYTE_GET_AND_INC (op, curr, 1, end);
extended_ops[op] = curr;
- nargs = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (nargs, curr, end);
if (nargs == 0)
printf (_(" DW_MACRO_%02x has no arguments\n"), op);
else
unsigned int filenum;
unsigned char *file_name = NULL, *dir_name = NULL;
- lineno = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
- filenum = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (lineno, curr, end);
+ READ_ULEB (filenum, curr, end);
if ((flags & 2) == 0)
error (_("DW_MACRO_start_file used, but no .debug_line offset provided.\n"));
break;
case DW_MACRO_define:
- lineno = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (lineno, curr, end);
string = curr;
curr += strnlen ((char *) string, end - string) + 1;
printf (_(" DW_MACRO_define - lineno : %d macro : %s\n"),
break;
case DW_MACRO_undef:
- lineno = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (lineno, curr, end);
string = curr;
curr += strnlen ((char *) string, end - string) + 1;
printf (_(" DW_MACRO_undef - lineno : %d macro : %s\n"),
break;
case DW_MACRO_define_strp:
- lineno = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (lineno, curr, end);
SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
string = fetch_indirect_string (offset);
printf (_(" DW_MACRO_define_strp - lineno : %d macro : %s\n"),
break;
case DW_MACRO_undef_strp:
- lineno = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (lineno, curr, end);
SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
string = fetch_indirect_string (offset);
printf (_(" DW_MACRO_undef_strp - lineno : %d macro : %s\n"),
break;
case DW_MACRO_define_sup:
- lineno = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (lineno, curr, end);
SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
printf (_(" DW_MACRO_define_sup - lineno : %d macro offset : 0x%lx\n"),
lineno, (unsigned long) offset);
break;
case DW_MACRO_undef_sup:
- lineno = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (lineno, curr, end);
SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
printf (_(" DW_MACRO_undef_sup - lineno : %d macro offset : 0x%lx\n"),
lineno, (unsigned long) offset);
/* Skip over unhandled opcodes. */
dwarf_vma nargs, n;
unsigned char *desc = extended_ops[op];
- nargs = read_uleb128 (desc, &bytes_read, end);
- desc += bytes_read;
+ READ_ULEB (nargs, desc, end);
if (nargs == 0)
{
printf (_(" DW_MACRO_%02x\n"), op);
SAFE_BYTE_GET_AND_INC (val, desc, 1, end);
curr
= read_and_display_attr_value (0, val, 0,
- curr, end, 0, 0, offset_size,
+ start, curr, end, 0, 0, offset_size,
version, NULL, 0, NULL,
- NULL, ' ');
+ NULL, ' ', -1);
if (n != nargs - 1)
printf (",");
}
dwarf_vma off = vstart - section->start;
dwarf_vma vbegin, vend;
- unsigned int bytes_read;
- vbegin = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ READ_ULEB (vbegin, vstart, section_end);
if (vstart == section_end)
- {
- vstart -= bytes_read;
- break;
- }
-
- vend = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ break;
+ READ_ULEB (vend, vstart, section_end);
printf (" %8.8lx ", (unsigned long) off);
print_dwarf_view (vbegin, pointer_size, 1);
if (vstart)
{
- unsigned int bytes_read;
-
off = offset + (vstart - *start_ptr);
- vbegin = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ READ_ULEB (vbegin, vstart, section_end);
print_dwarf_view (vbegin, pointer_size, 1);
- vend = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ READ_ULEB (vend, vstart, section_end);
print_dwarf_view (vend, pointer_size, 1);
printf (_("views at %8.8lx for:\n %*s "),
unsigned int pointer_size;
unsigned int offset_size;
int dwarf_version;
- unsigned int bytes_read;
/* Initialize it due to a false compiler warning. */
dwarf_vma begin = -1, vbegin = -1;
{
off = offset + (vstart - *start_ptr);
- vbegin = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ READ_ULEB (vbegin, vstart, section_end);
print_dwarf_view (vbegin, pointer_size, 1);
- vend = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ READ_ULEB (vend, vstart, section_end);
print_dwarf_view (vend, pointer_size, 1);
printf (_("views at %8.8lx for:\n %*s "),
printf (_("<End of list>\n"));
break;
case DW_LLE_offset_pair:
- begin = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
- end = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (begin, start, section_end);
+ READ_ULEB (end, start, section_end);
break;
case DW_LLE_base_address:
SAFE_BYTE_GET_AND_INC (base_address, start, pointer_size,
case DW_LLE_view_pair:
if (vstart)
printf (_("View pair entry in loclist with locviews attribute\n"));
- vbegin = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (vbegin, start, section_end);
print_dwarf_view (vbegin, pointer_size, 1);
- vend = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (vend, start, section_end);
print_dwarf_view (vend, pointer_size, 1);
printf (_("views for:\n"));
break;
}
- length = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (length, start, section_end);
print_dwarf_vma (begin + base_address, pointer_size);
print_dwarf_vma (end + base_address, pointer_size);
unsigned short length;
int need_frame_base;
unsigned int idx;
- unsigned int bytes_read;
if (debug_info_entry >= num_debug_info_entries)
{
dwarf_vma view;
dwarf_vma off = offset + (vstart - *start_ptr);
- view = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ READ_ULEB (view, vstart, section_end);
print_dwarf_view (view, 8, 1);
- view = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ READ_ULEB (view, vstart, section_end);
print_dwarf_view (view, 8, 1);
printf (_("views at %8.8lx for:\n %*s "),
printf (_("<End of list>\n"));
return;
case 1: /* A base-address entry. */
- idx = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (idx, start, section_end);
print_addr_index (idx, 8);
printf ("%*s", 9 + (vstart ? 2 * 6 : 0), "");
printf (_("(base address selection entry)\n"));
continue;
case 2: /* A start/end entry. */
- idx = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (idx, start, section_end);
print_addr_index (idx, 8);
- idx = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (idx, start, section_end);
print_addr_index (idx, 8);
break;
case 3: /* A start/length entry. */
- idx = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (idx, start, section_end);
print_addr_index (idx, 8);
SAFE_BYTE_GET_AND_INC (idx, start, 4, section_end);
printf ("%08x ", idx);
unsigned char *next = start, *vnext = vstart;
unsigned int *array = NULL;
const char *suffix = strrchr (section->name, '.');
- int is_dwo = 0;
+ bfd_boolean is_dwo = FALSE;
int is_loclists = strstr (section->name, "debug_loclists") != NULL;
dwarf_vma expected_start = 0;
if (suffix && strcmp (suffix, ".dwo") == 0)
- is_dwo = 1;
+ is_dwo = TRUE;
bytes = section->size;
static int
display_debug_info (struct dwarf_section *section, void *file)
{
- return process_debug_info (section, file, section->abbrev_sec, 0, 0);
+ return process_debug_info (section, file, section->abbrev_sec, FALSE, FALSE);
}
static int
display_debug_types (struct dwarf_section *section, void *file)
{
- return process_debug_info (section, file, section->abbrev_sec, 0, 1);
+ return process_debug_info (section, file, section->abbrev_sec, FALSE, TRUE);
}
static int
display_trace_info (struct dwarf_section *section, void *file)
{
- return process_debug_info (section, file, section->abbrev_sec, 0, 0);
+ return process_debug_info (section, file, section->abbrev_sec, FALSE, TRUE);
}
static int
static int
comp_addr_base (const void * v0, const void * v1)
{
- debug_info * info0 = (debug_info *) v0;
- debug_info * info1 = (debug_info *) v1;
+ debug_info *info0 = *(debug_info **) v0;
+ debug_info *info1 = *(debug_info **) v1;
return info0->addr_base - info1->addr_base;
}
}
/* Display the .debug_str_offsets and .debug_str_offsets.dwo sections. */
+
static int
display_debug_str_offsets (struct dwarf_section *section,
void *file ATTRIBUTE_UNUSED)
break;
SAFE_SIGNED_BYTE_GET_AND_INC (end, start, pointer_size, finish);
+
printf (" %8.8lx ", offset);
if (begin == 0 && end == 0)
enum dwarf_range_list_entry rlet;
/* Initialize it due to a false compiler warning. */
dwarf_vma begin = -1, length, end = -1;
- unsigned int bytes_read;
if (start + 1 > finish)
{
break;
case DW_RLE_start_length:
SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, finish);
- length = read_uleb128 (start, &bytes_read, finish);
- start += bytes_read;
+ READ_ULEB (length, start, finish);
end = begin + length;
break;
case DW_RLE_offset_pair:
- begin = read_uleb128 (start, &bytes_read, finish);
- start += bytes_read;
- end = read_uleb128 (start, &bytes_read, finish);
- start += bytes_read;
+ READ_ULEB (begin, start, finish);
+ READ_ULEB (end, start, finish);
break;
case DW_RLE_start_end:
SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, finish);
/* PR 17512: file: 001-101485-0.001:0.1. */
if (pointer_size < 2 || pointer_size > 8)
{
- warn (_("Corrupt pointer size (%d) in debug entry at offset %8.8lx\n"),
- pointer_size, (unsigned long) offset);
+ warn (_("Corrupt pointer size (%d) in debug entry at offset %8.8lx\n"),
+ pointer_size, (unsigned long) offset);
+ continue;
+ }
+
+ if (next < section_begin || next >= finish)
+ {
+ warn (_("Corrupt offset (%#8.8lx) in range entry %u\n"),
+ (unsigned long) offset, i);
continue;
}
(unsigned long) (next - section_begin), section->name);
}
}
+
start = next;
last_start = next;
}
Frame_Chunk;
+typedef const char *(*dwarf_regname_lookup_ftype) (unsigned int);
+static dwarf_regname_lookup_ftype dwarf_regnames_lookup_func;
static const char *const *dwarf_regnames;
static unsigned int dwarf_regnames_count;
+
/* A marker for a col_type that means this column was never referenced
in the frame info. */
#define DW_CFA_unreferenced (-1)
if (reg < (unsigned int) fc->ncols)
return 0;
- if (dwarf_regnames_count
+ if (dwarf_regnames_count > 0
&& reg > dwarf_regnames_count)
return -1;
return -1;
/* PR 17512: file: 2844a11d. */
- if (fc->ncols > 1024)
+ if (fc->ncols > 1024 && dwarf_regnames_count == 0)
{
error (_("Unfeasibly large register number: %u\n"), reg);
fc->ncols = 0;
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* 93 - 100 */
};
-void
+static void
init_dwarf_regnames_i386 (void)
{
dwarf_regnames = dwarf_regnames_i386;
dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_i386);
+ dwarf_regnames_lookup_func = regname_internal_by_table_only;
}
-void
+static void
init_dwarf_regnames_iamcu (void)
{
dwarf_regnames = dwarf_regnames_iamcu;
dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_iamcu);
+ dwarf_regnames_lookup_func = regname_internal_by_table_only;
}
static const char *const dwarf_regnames_x86_64[] =
"k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"
};
-void
+static void
init_dwarf_regnames_x86_64 (void)
{
dwarf_regnames = dwarf_regnames_x86_64;
dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_x86_64);
+ dwarf_regnames_lookup_func = regname_internal_by_table_only;
}
static const char *const dwarf_regnames_aarch64[] =
"x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
"x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp",
NULL, "elr", NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, "vg", "ffr",
+ "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7",
+ "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
"v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
"v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
+ "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7",
+ "z8", "z9", "z10", "z11", "z12", "z13", "z14", "z15",
+ "z16", "z17", "z18", "z19", "z20", "z21", "z22", "z23",
+ "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31",
};
-void
+static void
init_dwarf_regnames_aarch64 (void)
{
dwarf_regnames = dwarf_regnames_aarch64;
dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_aarch64);
+ dwarf_regnames_lookup_func = regname_internal_by_table_only;
}
static const char *const dwarf_regnames_s390[] =
"v24", "v26", "v28", "v30", "v25", "v27", "v29", "v31",
};
-void
+static void
init_dwarf_regnames_s390 (void)
{
dwarf_regnames = dwarf_regnames_s390;
dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_s390);
+ dwarf_regnames_lookup_func = regname_internal_by_table_only;
+}
+
+static const char *const dwarf_regnames_riscv[] =
+{
+ "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", /* 0 - 7 */
+ "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", /* 8 - 15 */
+ "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", /* 16 - 23 */
+ "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", /* 24 - 31 */
+ "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", /* 32 - 39 */
+ "fs0", "fs1", /* 40 - 41 */
+ "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", "fa6", "fa7", /* 42 - 49 */
+ "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", "fs8", "fs9", /* 50 - 57 */
+ "fs10", "fs11", /* 58 - 59 */
+ "ft8", "ft9", "ft10", "ft11" /* 60 - 63 */
+};
+
+/* A RISC-V replacement for REGNAME_INTERNAL_BY_TABLE_ONLY which handles
+ the large number of CSRs. */
+
+static const char *
+regname_internal_riscv (unsigned int regno)
+{
+ const char *name = NULL;
+
+ /* Lookup in the table first, this covers GPR and FPR. */
+ if (regno < ARRAY_SIZE (dwarf_regnames_riscv))
+ name = dwarf_regnames_riscv [regno];
+ else if (regno >= 4096 && regno <= 8191)
+ {
+ /* This might be a CSR, these live in a sparse number space from 4096
+ to 8191 These numbers are defined in the RISC-V ELF ABI
+ document. */
+ switch (regno)
+ {
+#define DECLARE_CSR(NAME,VALUE) case VALUE + 4096: name = #NAME; break;
+#include "opcode/riscv-opc.h"
+#undef DECLARE_CSR
+
+ default:
+ {
+ static char csr_name[10];
+ snprintf (csr_name, sizeof (csr_name), "csr%d", (regno - 4096));
+ name = csr_name;
+ }
+ break;
+ }
+ }
+
+ return name;
+}
+
+static void
+init_dwarf_regnames_riscv (void)
+{
+ dwarf_regnames = NULL;
+ dwarf_regnames_count = 8192;
+ dwarf_regnames_lookup_func = regname_internal_riscv;
}
void
-init_dwarf_regnames (unsigned int e_machine)
+init_dwarf_regnames_by_elf_machine_code (unsigned int e_machine)
{
+ dwarf_regnames_lookup_func = NULL;
+
switch (e_machine)
{
case EM_386:
init_dwarf_regnames_s390 ();
break;
+ case EM_RISCV:
+ init_dwarf_regnames_riscv ();
+ break;
+
default:
break;
}
}
-static const char *
-regname (unsigned int regno, int row)
+/* Initialize the DWARF register name lookup state based on the
+ architecture and specific machine type of a BFD. */
+
+void
+init_dwarf_regnames_by_bfd_arch_and_mach (enum bfd_architecture arch,
+ unsigned long mach)
{
- static char reg[64];
+ dwarf_regnames_lookup_func = NULL;
+
+ switch (arch)
+ {
+ case bfd_arch_i386:
+ switch (mach)
+ {
+ case bfd_mach_x86_64:
+ case bfd_mach_x86_64_intel_syntax:
+ case bfd_mach_x86_64_nacl:
+ case bfd_mach_x64_32:
+ case bfd_mach_x64_32_intel_syntax:
+ case bfd_mach_x64_32_nacl:
+ init_dwarf_regnames_x86_64 ();
+ break;
+
+ default:
+ init_dwarf_regnames_i386 ();
+ break;
+ }
+ break;
+
+ case bfd_arch_iamcu:
+ init_dwarf_regnames_iamcu ();
+ break;
+
+ case bfd_arch_aarch64:
+ init_dwarf_regnames_aarch64();
+ break;
+
+ case bfd_arch_s390:
+ init_dwarf_regnames_s390 ();
+ break;
+
+ case bfd_arch_riscv:
+ init_dwarf_regnames_riscv ();
+ break;
- if (dwarf_regnames
+ default:
+ break;
+ }
+}
+
+static const char *
+regname_internal_by_table_only (unsigned int regno)
+{
+ if (dwarf_regnames != NULL
&& regno < dwarf_regnames_count
&& dwarf_regnames [regno] != NULL)
+ return dwarf_regnames [regno];
+
+ return NULL;
+}
+
+static const char *
+regname (unsigned int regno, int name_only_p)
+{
+ static char reg[64];
+
+ const char *name = NULL;
+
+ if (dwarf_regnames_lookup_func != NULL)
+ name = dwarf_regnames_lookup_func (regno);
+
+ if (name != NULL)
{
- if (row)
- return dwarf_regnames [regno];
- snprintf (reg, sizeof (reg), "r%d (%s)", regno,
- dwarf_regnames [regno]);
+ if (name_only_p)
+ return name;
+ snprintf (reg, sizeof (reg), "r%d (%s)", regno, name);
}
else
snprintf (reg, sizeof (reg), "r%d", regno);
{
int version;
Frame_Chunk *fc;
- unsigned int length_return;
unsigned char *augmentation_data = NULL;
bfd_size_type augmentation_data_len = 0;
if (start == end)
{
warn (_("No terminator for augmentation name\n"));
- return start;
+ goto fail;
}
if (strcmp (fc->augmentation, "eh") == 0)
if (fc->ptr_size < 1 || fc->ptr_size > 8)
{
warn (_("Invalid pointer size (%d) in CIE data\n"), fc->ptr_size);
- return end;
+ goto fail;
}
GET (fc->segment_size, 1);
if (fc->segment_size > 8 || fc->segment_size + fc->ptr_size > 8)
{
warn (_("Invalid segment size (%d) in CIE data\n"), fc->segment_size);
- return end;
+ goto fail;
}
eh_addr_size = fc->ptr_size;
fc->ptr_size = eh_addr_size;
fc->segment_size = 0;
}
- READ_ULEB (fc->code_factor);
- READ_SLEB (fc->data_factor);
+
+ READ_ULEB (fc->code_factor, start, end);
+ READ_SLEB (fc->data_factor, start, end);
+
if (version == 1)
{
GET (fc->ra, 1);
}
else
{
- READ_ULEB (fc->ra);
+ READ_ULEB (fc->ra, start, end);
}
if (fc->augmentation[0] == 'z')
{
- READ_ULEB (augmentation_data_len);
+ READ_ULEB (augmentation_data_len, start, end);
augmentation_data = start;
/* PR 17512: file: 11042-2589-0.004. */
if (augmentation_data_len > (bfd_size_type) (end - start))
warn (_("Augmentation data too long: 0x%s, expected at most %#lx\n"),
dwarf_vmatoa ("x", augmentation_data_len),
(unsigned long) (end - start));
- return end;
+ goto fail;
}
start += augmentation_data_len;
}
fc->fde_encoding = *q++;
else if (*p == 'S')
;
+ else if (*p == 'B')
+ ;
else
break;
p++;
*p_aug = augmentation_data;
}
return start;
+
+ fail:
+ free (fc->col_offset);
+ free (fc->col_type);
+ free (fc);
+ return end;
}
-/* Prints out the contents on the augmentation data array.
- If do_wide is not enabled, then formats the output to fit into 80 columns. */
+/* Prints out the contents on the DATA array formatted as unsigned bytes.
+ If do_wide is not enabled, then formats the output to fit into 80 columns.
+ PRINTED contains the number of characters already written to the current
+ output line. */
static void
-display_augmentation_data (const unsigned char * data, const bfd_size_type len)
+display_data (bfd_size_type printed,
+ const unsigned char * data,
+ const bfd_size_type len)
{
- bfd_size_type i;
-
- i = printf (_(" Augmentation data: "));
-
- if (do_wide || len < ((80 - i) / 3))
- for (i = 0; i < len; ++i)
- printf (" %02x", data[i]);
+ if (do_wide || len < ((80 - printed) / 3))
+ for (printed = 0; printed < len; ++printed)
+ printf (" %02x", data[printed]);
else
{
- for (i = 0; i < len; ++i)
+ for (printed = 0; printed < len; ++printed)
{
- if (i % (80 / 3) == 0)
+ if (printed % (80 / 3) == 0)
putchar ('\n');
- printf (" %02x", data[i]);
+ printf (" %02x", data[printed]);
}
}
- putchar ('\n');
+}
+
+/* Prints out the contents on the augmentation data array.
+ If do_wide is not enabled, then formats the output to fit into 80 columns. */
+
+static void
+display_augmentation_data (const unsigned char * data, const bfd_size_type len)
+{
+ bfd_size_type i;
+
+ i = printf (_(" Augmentation data: "));
+ display_data (i, data, len);
}
static int
unsigned char *start = section->start;
unsigned char *end = start + section->size;
unsigned char *section_start = start;
- Frame_Chunk *chunks = 0, *forward_refs = 0;
- Frame_Chunk *remembered_state = 0;
+ Frame_Chunk *chunks = NULL, *forward_refs = NULL;
+ Frame_Chunk *remembered_state = NULL;
Frame_Chunk *rs;
- int is_eh = strcmp (section->name, ".eh_frame") == 0;
- unsigned int length_return;
+ bfd_boolean is_eh = strcmp (section->name, ".eh_frame") == 0;
unsigned int max_regs = 0;
const char *bad_reg = _("bad register: ");
unsigned int saved_eh_addr_size = eh_addr_size;
if (cie->augmentation[0] == 'z')
{
- READ_ULEB (augmentation_data_len);
+ READ_ULEB (augmentation_data_len, start, end);
augmentation_data = start;
- start += augmentation_data_len;
/* PR 17512 file: 722-8446-0.004 and PR 22386. */
- if (start >= end
- || ((bfd_signed_vma) augmentation_data_len) < 0
- || augmentation_data > start)
+ if (augmentation_data_len > (bfd_size_type) (end - start))
{
- warn (_("Corrupt augmentation data length: 0x%s\n"),
- dwarf_vmatoa ("x", augmentation_data_len));
+ warn (_("Augmentation data too long: 0x%s, "
+ "expected at most %#lx\n"),
+ dwarf_vmatoa ("x", augmentation_data_len),
+ (unsigned long) (end - start));
start = end;
augmentation_data = NULL;
augmentation_data_len = 0;
}
+ start += augmentation_data_len;
}
printf ("\n%08lx %s %s FDE cie=%08lx pc=",
case DW_CFA_advance_loc:
break;
case DW_CFA_offset:
- SKIP_ULEB ();
+ SKIP_ULEB (start, end);
if (frame_need_space (fc, opa) >= 0)
fc->col_type[opa] = DW_CFA_undefined;
break;
break;
case DW_CFA_offset_extended:
case DW_CFA_val_offset:
- READ_ULEB (reg);
- SKIP_ULEB ();
+ READ_ULEB (reg, start, end);
+ SKIP_ULEB (start, end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_restore_extended:
- READ_ULEB (reg);
+ READ_ULEB (reg, start, end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_undefined:
- READ_ULEB (reg);
+ READ_ULEB (reg, start, end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_same_value:
- READ_ULEB (reg);
+ READ_ULEB (reg, start, end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_register:
- READ_ULEB (reg);
- SKIP_ULEB ();
+ READ_ULEB (reg, start, end);
+ SKIP_ULEB (start, end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_def_cfa:
- SKIP_ULEB ();
- SKIP_ULEB ();
+ SKIP_ULEB (start, end);
+ SKIP_ULEB (start, end);
break;
case DW_CFA_def_cfa_register:
- SKIP_ULEB ();
+ SKIP_ULEB (start, end);
break;
case DW_CFA_def_cfa_offset:
- SKIP_ULEB ();
+ SKIP_ULEB (start, end);
break;
case DW_CFA_def_cfa_expression:
- READ_ULEB (temp);
+ READ_ULEB (temp, start, end);
new_start = start + temp;
if (new_start < start)
{
break;
case DW_CFA_expression:
case DW_CFA_val_expression:
- READ_ULEB (reg);
- READ_ULEB (temp);
+ READ_ULEB (reg, start, end);
+ READ_ULEB (temp, start, end);
new_start = start + temp;
if (new_start < start)
{
break;
case DW_CFA_offset_extended_sf:
case DW_CFA_val_offset_sf:
- READ_ULEB (reg);
- SKIP_SLEB ();
+ READ_ULEB (reg, start, end);
+ SKIP_SLEB (start, end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_def_cfa_sf:
- SKIP_ULEB ();
- SKIP_SLEB ();
+ SKIP_ULEB (start, end);
+ SKIP_SLEB (start, end);
break;
case DW_CFA_def_cfa_offset_sf:
- SKIP_SLEB ();
+ SKIP_SLEB (start, end);
break;
case DW_CFA_MIPS_advance_loc8:
start += 8;
break;
case DW_CFA_GNU_args_size:
- SKIP_ULEB ();
+ SKIP_ULEB (start, end);
break;
case DW_CFA_GNU_negative_offset_extended:
- READ_ULEB (reg);
- SKIP_ULEB ();
+ READ_ULEB (reg, start, end);
+ SKIP_ULEB (start, end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
break;
case DW_CFA_offset:
- READ_ULEB (roffs);
+ READ_ULEB (roffs, start, end);
if (opa >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_offset_extended:
- READ_ULEB (reg);
- READ_ULEB (roffs);
+ READ_ULEB (reg, start, end);
+ READ_ULEB (roffs, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_val_offset:
- READ_ULEB (reg);
- READ_ULEB (roffs);
+ READ_ULEB (reg, start, end);
+ READ_ULEB (roffs, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_restore_extended:
- READ_ULEB (reg);
+ READ_ULEB (reg, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_undefined:
- READ_ULEB (reg);
+ READ_ULEB (reg, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_same_value:
- READ_ULEB (reg);
+ READ_ULEB (reg, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_register:
- READ_ULEB (reg);
- READ_ULEB (roffs);
+ READ_ULEB (reg, start, end);
+ READ_ULEB (roffs, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_def_cfa:
- READ_ULEB (fc->cfa_reg);
- READ_ULEB (fc->cfa_offset);
+ READ_ULEB (fc->cfa_reg, start, end);
+ READ_ULEB (fc->cfa_offset, start, end);
fc->cfa_exp = 0;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa: %s ofs %d\n",
break;
case DW_CFA_def_cfa_register:
- READ_ULEB (fc->cfa_reg);
+ READ_ULEB (fc->cfa_reg, start, end);
fc->cfa_exp = 0;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_register: %s\n",
break;
case DW_CFA_def_cfa_offset:
- READ_ULEB (fc->cfa_offset);
+ READ_ULEB (fc->cfa_offset, start, end);
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_offset: %d\n", (int) fc->cfa_offset);
break;
break;
case DW_CFA_def_cfa_expression:
- READ_ULEB (ul);
+ READ_ULEB (ul, start, end);
if (start >= block_end || ul > (unsigned long) (block_end - start))
{
printf (_(" DW_CFA_def_cfa_expression: <corrupt len %lu>\n"), ul);
break;
case DW_CFA_expression:
- READ_ULEB (reg);
- READ_ULEB (ul);
+ READ_ULEB (reg, start, end);
+ READ_ULEB (ul, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
/* PR 17512: file: 069-133014-0.006. */
break;
case DW_CFA_val_expression:
- READ_ULEB (reg);
- READ_ULEB (ul);
+ READ_ULEB (reg, start, end);
+ READ_ULEB (ul, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
tmp = start + ul;
break;
case DW_CFA_offset_extended_sf:
- READ_ULEB (reg);
- READ_SLEB (l);
+ READ_ULEB (reg, start, end);
+ READ_SLEB (l, start, end);
if (frame_need_space (fc, reg) < 0)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_val_offset_sf:
- READ_ULEB (reg);
- READ_SLEB (l);
+ READ_ULEB (reg, start, end);
+ READ_SLEB (l, start, end);
if (frame_need_space (fc, reg) < 0)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_def_cfa_sf:
- READ_ULEB (fc->cfa_reg);
- READ_ULEB (fc->cfa_offset);
+ READ_ULEB (fc->cfa_reg, start, end);
+ READ_ULEB (fc->cfa_offset, start, end);
fc->cfa_offset = fc->cfa_offset * fc->data_factor;
fc->cfa_exp = 0;
if (! do_debug_frames_interp)
break;
case DW_CFA_def_cfa_offset_sf:
- READ_ULEB (fc->cfa_offset);
+ READ_ULEB (fc->cfa_offset, start, end);
fc->cfa_offset *= fc->data_factor;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_offset_sf: %d\n", (int) fc->cfa_offset);
break;
case DW_CFA_GNU_args_size:
- READ_ULEB (ul);
+ READ_ULEB (ul, start, end);
if (! do_debug_frames_interp)
printf (" DW_CFA_GNU_args_size: %ld\n", ul);
break;
case DW_CFA_GNU_negative_offset_extended:
- READ_ULEB (reg);
- READ_SLEB (l);
+ READ_ULEB (reg, start, end);
+ READ_SLEB (l, start, end);
l = - l;
if (frame_need_space (fc, reg) < 0)
reg_prefix = bad_reg;
printf ("\n");
+ while (remembered_state != NULL)
+ {
+ rs = remembered_state;
+ remembered_state = rs->next;
+ free (rs->col_type);
+ free (rs->col_offset);
+ rs->next = NULL; /* Paranoia. */
+ free (rs);
+ }
+
+ while (chunks != NULL)
+ {
+ rs = chunks;
+ chunks = rs->next;
+ free (rs->col_type);
+ free (rs->col_offset);
+ rs->next = NULL; /* Paranoia. */
+ free (rs);
+ }
+
+ while (forward_refs != NULL)
+ {
+ rs = forward_refs;
+ forward_refs = rs->next;
+ free (rs->col_type);
+ free (rs->col_offset);
+ rs->next = NULL; /* Paranoia. */
+ free (rs);
+ }
+
return 1;
}
uint32_t augmentation_string_size;
unsigned int i;
unsigned long sec_off;
+ bfd_boolean augmentation_printable;
+ const char *augmentation_string;
unit_start = hdrptr;
augmentation_string_size);
augmentation_string_size += (-augmentation_string_size) & 3;
}
+
printf (_("Augmentation string:"));
+
+ augmentation_printable = TRUE;
+ augmentation_string = (const char *) hdrptr;
+
for (i = 0; i < augmentation_string_size; i++)
{
unsigned char uc;
SAFE_BYTE_GET_AND_INC (uc, hdrptr, 1, unit_end);
printf (" %02x", uc);
+
+ if (uc != 0 && !ISPRINT (uc))
+ augmentation_printable = FALSE;
+ }
+
+ if (augmentation_printable)
+ {
+ printf (" (\"");
+ for (i = 0;
+ i < augmentation_string_size && augmentation_string[i];
+ ++i)
+ putchar (augmentation_string[i]);
+ printf ("\")");
}
- putchar ('\n');
putchar ('\n');
printf (_("CU table:\n"));
unsigned char *abbrevptr = abbrev_table;
for (;;)
{
- unsigned int bytes_read;
- const dwarf_vma abbrev_tag = read_uleb128 (abbrevptr, &bytes_read,
- abbrev_table_end);
- abbrevptr += bytes_read;
+ dwarf_vma abbrev_tag;
+
+ READ_ULEB (abbrev_tag, abbrevptr, abbrev_table_end);
if (abbrev_tag == 0)
break;
if (abbrev_lookup_used == abbrev_lookup_allocated)
entry->abbrev_lookup_ptr = abbrevptr;
/* Skip DWARF tag. */
- read_uleb128 (abbrevptr, &bytes_read, abbrev_table_end);
- abbrevptr += bytes_read;
+ SKIP_ULEB (abbrevptr, abbrev_table_end);
for (;;)
{
- const dwarf_vma xindex = read_uleb128 (abbrevptr,
- &bytes_read,
- abbrev_table_end);
- abbrevptr += bytes_read;
- const dwarf_vma form = read_uleb128 (abbrevptr, &bytes_read,
- abbrev_table_end);
- abbrevptr += bytes_read;
+ dwarf_vma xindex, form;
+
+ READ_ULEB (xindex, abbrevptr, abbrev_table_end);
+ READ_ULEB (form, abbrevptr, abbrev_table_end);
if (xindex == 0 && form == 0)
break;
}
dwarf_vma second_abbrev_tag = -1;
for (;;)
{
- unsigned int bytes_read;
- const dwarf_vma abbrev_tag = read_uleb128 (entryptr, &bytes_read,
- unit_end);
- entryptr += bytes_read;
+ dwarf_vma abbrev_tag;
+ dwarf_vma dwarf_tag;
+ const struct abbrev_lookup_entry *entry;
+
+ READ_ULEB (abbrev_tag, entryptr, unit_end);
if (tagno == -1)
{
second_abbrev_tag = abbrev_tag;
(tagno == 0 && second_abbrev_tag == 0 ? " " : "\n\t"),
(unsigned long) abbrev_tag);
- const struct abbrev_lookup_entry *entry;
for (entry = abbrev_lookup;
entry < abbrev_lookup + abbrev_lookup_used;
entry++)
break;
}
abbrevptr = entry->abbrev_lookup_ptr;
- const dwarf_vma dwarf_tag = read_uleb128 (abbrevptr, &bytes_read,
- abbrev_table_end);
- abbrevptr += bytes_read;
+ READ_ULEB (dwarf_tag, abbrevptr, abbrev_table_end);
if (tagno >= 0)
printf (" %s", get_TAG_name (dwarf_tag));
for (;;)
{
- const dwarf_vma xindex = read_uleb128 (abbrevptr,
- &bytes_read,
- abbrev_table_end);
- abbrevptr += bytes_read;
- const dwarf_vma form = read_uleb128 (abbrevptr, &bytes_read,
- abbrev_table_end);
- abbrevptr += bytes_read;
+ dwarf_vma xindex, form;
+
+ READ_ULEB (xindex, abbrevptr, abbrev_table_end);
+ READ_ULEB (form, abbrevptr, abbrev_table_end);
if (xindex == 0 && form == 0)
break;
if (tagno >= 0)
printf (" %s", get_IDX_name (xindex));
- entryptr = read_and_display_attr_value (0, form, 0, entryptr,
- unit_end, 0, 0,
- offset_size,
+ entryptr = read_and_display_attr_value (0, form, 0,
+ unit_start, entryptr, unit_end,
+ 0, 0, offset_size,
dwarf_version, NULL,
(tagno < 0), NULL,
- NULL, '=');
+ NULL, '=', -1);
}
++tagno;
}
}
static int
-display_debug_links (struct dwarf_section * section,
- void * file ATTRIBUTE_UNUSED)
+display_debug_links (struct dwarf_section * section,
+ void * file ATTRIBUTE_UNUSED)
{
const unsigned char * filename;
unsigned int filelen;
}
printed = printf (_(" Build-ID (%#lx bytes):"), (long) build_id_len);
-
- if (do_wide || build_id_len < ((80 - printed) / 3))
- for (printed = 0; printed < build_id_len; ++printed)
- printf (" %02x", build_id[printed]);
- else
- {
- for (printed = 0; printed < build_id_len; ++printed)
- {
- if (printed % (80 / 3) == 0)
- putchar ('\n');
- printf (" %02x", build_id[printed]);
- }
- }
+ display_data (printed, build_id, build_id_len);
putchar ('\n');
}
SAFE_BYTE_GET (nslots, phdr + 12, 4, limit);
phash = phdr + 16;
- pindex = phash + nslots * 8;
- ppool = pindex + nslots * 4;
-
- /* PR 17531: file: 45d69832. */
- if (pindex < phash || ppool < phdr || (pindex == phash && nslots != 0))
- {
- warn (ngettext ("Section %s is too small for %d slot\n",
- "Section %s is too small for %d slots\n",
- nslots),
- section->name, nslots);
- return 0;
- }
+ pindex = phash + (size_t) nslots * 8;
+ ppool = pindex + (size_t) nslots * 4;
if (do_display)
{
introduce (section, FALSE);
- printf (_(" Version: %d\n"), version);
+ printf (_(" Version: %u\n"), version);
if (version >= 2)
- printf (_(" Number of columns: %d\n"), ncols);
- printf (_(" Number of used entries: %d\n"), nused);
- printf (_(" Number of slots: %d\n\n"), nslots);
+ printf (_(" Number of columns: %u\n"), ncols);
+ printf (_(" Number of used entries: %u\n"), nused);
+ printf (_(" Number of slots: %u\n\n"), nslots);
}
- if (ppool > limit || ppool < phdr)
+ /* PR 17531: file: 45d69832. */
+ if ((size_t) nslots * 8 / 8 != nslots
+ || phash < phdr || phash > limit
+ || pindex < phash || pindex > limit
+ || ppool < pindex || ppool > limit)
{
- warn (_("Section %s too small for %d hash table entries\n"),
+ warn (ngettext ("Section %s is too small for %u slot\n",
+ "Section %s is too small for %u slots\n",
+ nslots),
section->name, nslots);
return 0;
}
unsigned int dw_sect;
unsigned char *ph = phash;
unsigned char *pi = pindex;
- unsigned char *poffsets = ppool + ncols * 4;
- unsigned char *psizes = poffsets + nused * ncols * 4;
- unsigned char *pend = psizes + nused * ncols * 4;
+ unsigned char *poffsets = ppool + (size_t) ncols * 4;
+ unsigned char *psizes = poffsets + (size_t) nused * ncols * 4;
+ unsigned char *pend = psizes + (size_t) nused * ncols * 4;
bfd_boolean is_tu_index;
struct cu_tu_set *this_set = NULL;
unsigned int row;
is_tu_index = strcmp (section->name, ".debug_tu_index") == 0;
/* PR 17531: file: 0dd159bf.
- Check for wraparound with an overlarge ncols value. */
- if (poffsets < ppool || (unsigned int) ((poffsets - ppool) / 4) != ncols)
- {
- warn (_("Overlarge number of columns: %x\n"), ncols);
- return 0;
- }
-
- if (pend > limit)
+ Check for integer overflow (can occur when size_t is 32-bit)
+ with overlarge ncols or nused values. */
+ if (ncols > 0
+ && ((size_t) ncols * 4 / 4 != ncols
+ || (size_t) nused * ncols * 4 / ((size_t) ncols * 4) != nused
+ || poffsets < ppool || poffsets > limit
+ || psizes < poffsets || psizes > limit
+ || pend < psizes || pend > limit))
{
warn (_("Section %s too small for offset and size tables\n"),
section->name);
}
if (!do_display)
- memcpy (&this_set[row - 1].signature, ph, sizeof (uint64_t));
+ {
+ size_t num_copy = sizeof (uint64_t);
+
+ /* PR 23064: Beware of buffer overflow. */
+ if (ph + num_copy < limit)
+ memcpy (&this_set[row - 1].signature, ph, num_copy);
+ else
+ {
+ warn (_("Signature (%p) extends beyond end of space in section\n"), ph);
+ return 0;
+ }
+ }
prow = poffsets + (row - 1) * ncols * 4;
/* PR 17531: file: b8ce60a8. */
The CRC value is stored after the filename, aligned up to 4 bytes. */
name = (const char *) section->start;
+
crc_offset = strnlen (name, section->size) + 1;
crc_offset = (crc_offset + 3) & ~3;
if (crc_offset + 4 > section->size)
return name;
}
+static void
+add_separate_debug_file (const char * filename, void * handle)
+{
+ separate_info * i = xmalloc (sizeof * i);
+
+ i->filename = filename;
+ i->handle = handle;
+ i->next = first_separate_info;
+ first_separate_info = i;
+}
+
+#if HAVE_LIBDEBUGINFOD
+/* Query debuginfod servers for the target debuglink or debugaltlink
+ file. If successful, store the path of the file in filename and
+ return TRUE, otherwise return FALSE. */
+
+static bfd_boolean
+debuginfod_fetch_separate_debug_info (struct dwarf_section * section,
+ char ** filename,
+ void * file)
+{
+ size_t build_id_len;
+ unsigned char * build_id;
+
+ if (strcmp (section->uncompressed_name, ".gnu_debuglink") == 0)
+ {
+ /* Get the build-id of file. */
+ build_id = get_build_id (file);
+ build_id_len = 0;
+ }
+ else if (strcmp (section->uncompressed_name, ".gnu_debugaltlink") == 0)
+ {
+ /* Get the build-id of the debugaltlink file. */
+ unsigned int filelen;
+
+ filelen = strnlen ((const char *)section->start, section->size);
+ if (filelen == section->size)
+ /* Corrupt debugaltlink. */
+ return FALSE;
+
+ build_id = section->start + filelen + 1;
+ build_id_len = section->size - (filelen + 1);
+
+ if (build_id_len == 0)
+ return FALSE;
+ }
+ else
+ return FALSE;
+
+ if (build_id)
+ {
+ int fd;
+ debuginfod_client * client;
+
+ client = debuginfod_begin ();
+ if (client == NULL)
+ return FALSE;
+
+ /* Query debuginfod servers for the target file. If found its path
+ will be stored in filename. */
+ fd = debuginfod_find_debuginfo (client, build_id, build_id_len, filename);
+ debuginfod_end (client);
+
+ /* Only free build_id if we allocated space for a hex string
+ in get_build_id (). */
+ if (build_id_len == 0)
+ free (build_id);
+
+ if (fd >= 0)
+ {
+ /* File successfully retrieved. Close fd since we want to
+ use open_debug_file () on filename instead. */
+ close (fd);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+#endif
+
static void *
load_separate_debug_info (const char * main_filename,
- struct dwarf_section * link,
+ struct dwarf_section * xlink,
parse_func_type parse_func,
check_func_type check_func,
- void * func_data)
+ void * func_data,
+ void * file ATTRIBUTE_UNUSED)
{
const char * separate_filename;
- char * debugfile;
+ char * debug_filename;
char * canon_dir;
size_t canon_dirlen;
size_t dirlen;
- if ((separate_filename = parse_func (link, func_data)) == NULL)
+ if ((separate_filename = parse_func (xlink, func_data)) == NULL)
{
warn (_("Corrupt debuglink section: %s\n"),
- link->name ? link->name : link->uncompressed_name);
+ xlink->name ? xlink->name : xlink->uncompressed_name);
return FALSE;
}
#define EXTRA_DEBUG_ROOT2 "/usr/lib/debug/usr"
#endif
- debugfile = (char *) malloc (strlen (DEBUGDIR) + 1
- + canon_dirlen
- + strlen (".debug/")
+ debug_filename = (char *) malloc (strlen (DEBUGDIR) + 1
+ + canon_dirlen
+ + strlen (".debug/")
#ifdef EXTRA_DEBUG_ROOT1
- + strlen (EXTRA_DEBUG_ROOT1)
+ + strlen (EXTRA_DEBUG_ROOT1)
#endif
#ifdef EXTRA_DEBUG_ROOT2
- + strlen (EXTRA_DEBUG_ROOT2)
+ + strlen (EXTRA_DEBUG_ROOT2)
#endif
- + strlen (separate_filename)
- + 1);
- if (debugfile == NULL)
+ + strlen (separate_filename)
+ + 1);
+ if (debug_filename == NULL)
{
warn (_("Out of memory"));
+ free (canon_dir);
return NULL;
}
/* First try in the current directory. */
- sprintf (debugfile, "%s", separate_filename);
- if (check_func (debugfile, func_data))
+ sprintf (debug_filename, "%s", separate_filename);
+ if (check_func (debug_filename, func_data))
goto found;
/* Then try in a subdirectory called .debug. */
- sprintf (debugfile, ".debug/%s", separate_filename);
- if (check_func (debugfile, func_data))
+ sprintf (debug_filename, ".debug/%s", separate_filename);
+ if (check_func (debug_filename, func_data))
goto found;
/* Then try in the same directory as the original file. */
- sprintf (debugfile, "%s%s", canon_dir, separate_filename);
- if (check_func (debugfile, func_data))
+ sprintf (debug_filename, "%s%s", canon_dir, separate_filename);
+ if (check_func (debug_filename, func_data))
goto found;
/* And the .debug subdirectory of that directory. */
- sprintf (debugfile, "%s.debug/%s", canon_dir, separate_filename);
- if (check_func (debugfile, func_data))
+ sprintf (debug_filename, "%s.debug/%s", canon_dir, separate_filename);
+ if (check_func (debug_filename, func_data))
goto found;
#ifdef EXTRA_DEBUG_ROOT1
/* Try the first extra debug file root. */
- sprintf (debugfile, "%s/%s", EXTRA_DEBUG_ROOT1, separate_filename);
- if (check_func (debugfile, func_data))
+ sprintf (debug_filename, "%s/%s", EXTRA_DEBUG_ROOT1, separate_filename);
+ if (check_func (debug_filename, func_data))
+ goto found;
+
+ /* Try the first extra debug file root. */
+ sprintf (debug_filename, "%s/%s/%s", EXTRA_DEBUG_ROOT1, canon_dir, separate_filename);
+ if (check_func (debug_filename, func_data))
goto found;
#endif
#ifdef EXTRA_DEBUG_ROOT2
/* Try the second extra debug file root. */
- sprintf (debugfile, "%s/%s", EXTRA_DEBUG_ROOT2, separate_filename);
- if (check_func (debugfile, func_data))
+ sprintf (debug_filename, "%s/%s", EXTRA_DEBUG_ROOT2, separate_filename);
+ if (check_func (debug_filename, func_data))
goto found;
#endif
- /* Then try in the global debugfile directory. */
- strcpy (debugfile, DEBUGDIR);
+ /* Then try in the global debug_filename directory. */
+ strcpy (debug_filename, DEBUGDIR);
dirlen = strlen (DEBUGDIR) - 1;
if (dirlen > 0 && DEBUGDIR[dirlen] != '/')
- strcat (debugfile, "/");
- strcat (debugfile, (const char *) separate_filename);
+ strcat (debug_filename, "/");
+ strcat (debug_filename, (const char *) separate_filename);
- if (check_func (debugfile, func_data))
+ if (check_func (debug_filename, func_data))
goto found;
+#if HAVE_LIBDEBUGINFOD
+ {
+ char * tmp_filename;
+
+ if (debuginfod_fetch_separate_debug_info (xlink,
+ & tmp_filename,
+ file))
+ {
+ /* File successfully downloaded from server, replace
+ debug_filename with the file's path. */
+ free (debug_filename);
+ debug_filename = tmp_filename;
+ goto found;
+ }
+ }
+#endif
+
/* Failed to find the file. */
warn (_("could not find separate debug file '%s'\n"), separate_filename);
- warn (_("tried: %s\n"), debugfile);
+ warn (_("tried: %s\n"), debug_filename);
#ifdef EXTRA_DEBUG_ROOT2
- sprintf (debugfile, "%s/%s", EXTRA_DEBUG_ROOT2, separate_filename);
- warn (_("tried: %s\n"), debugfile);
+ sprintf (debug_filename, "%s/%s", EXTRA_DEBUG_ROOT2, separate_filename);
+ warn (_("tried: %s\n"), debug_filename);
#endif
#ifdef EXTRA_DEBUG_ROOT1
- sprintf (debugfile, "%s/%s", EXTRA_DEBUG_ROOT1, separate_filename);
- warn (_("tried: %s\n"), debugfile);
+ sprintf (debug_filename, "%s/%s/%s", EXTRA_DEBUG_ROOT1, canon_dir, separate_filename);
+ warn (_("tried: %s\n"), debug_filename);
+
+ sprintf (debug_filename, "%s/%s", EXTRA_DEBUG_ROOT1, separate_filename);
+ warn (_("tried: %s\n"), debug_filename);
#endif
- sprintf (debugfile, "%s.debug/%s", canon_dir, separate_filename);
- warn (_("tried: %s\n"), debugfile);
+ sprintf (debug_filename, "%s.debug/%s", canon_dir, separate_filename);
+ warn (_("tried: %s\n"), debug_filename);
+
+ sprintf (debug_filename, "%s%s", canon_dir, separate_filename);
+ warn (_("tried: %s\n"), debug_filename);
+
+ sprintf (debug_filename, ".debug/%s", separate_filename);
+ warn (_("tried: %s\n"), debug_filename);
- sprintf (debugfile, "%s%s", canon_dir, separate_filename);
- warn (_("tried: %s\n"), debugfile);
+ sprintf (debug_filename, "%s", separate_filename);
+ warn (_("tried: %s\n"), debug_filename);
- sprintf (debugfile, ".debug/%s", separate_filename);
- warn (_("tried: %s\n"), debugfile);
+#if HAVE_LIBDEBUGINFOD
+ {
+ char *urls = getenv (DEBUGINFOD_URLS_ENV_VAR);
+ if (urls == NULL)
+ urls = "";
- sprintf (debugfile, "%s", separate_filename);
- warn (_("tried: %s\n"), debugfile);
+ warn (_("tried: DEBUGINFOD_URLS=%s\n"), urls);
+ }
+#endif
free (canon_dir);
- free (debugfile);
+ free (debug_filename);
return NULL;
found:
free (canon_dir);
+ void * debug_handle;
+
/* Now open the file.... */
- if ((separate_debug_file = open_debug_file (debugfile)) == NULL)
+ if ((debug_handle = open_debug_file (debug_filename)) == NULL)
{
- warn (_("failed to open separate debug file: %s\n"), debugfile);
- free (debugfile);
+ warn (_("failed to open separate debug file: %s\n"), debug_filename);
+ free (debug_filename);
return FALSE;
}
/* FIXME: We do not check to see if there are any other separate debug info
files that would also match. */
- printf (_("%s: Found separate debug info file: %s\n\n"), main_filename, debugfile);
- separate_debug_filename = debugfile;
+ printf (_("%s: Found separate debug info file: %s\n\n"), main_filename, debug_filename);
+ add_separate_debug_file (debug_filename, debug_handle);
- /* Do not free debugfile - it might be referenced inside
+ /* Do not free debug_filename - it might be referenced inside
the structure returned by open_debug_file(). */
- return separate_debug_file;
+ return debug_handle;
}
-/* Load a separate debug info file, if it exists.
- Returns the data pointer that is the result of calling open_debug_file
- on the separate debug info file. */
+/* Attempt to load a separate dwarf object file. */
-void *
-load_separate_debug_file (void * file, const char * filename)
+static void *
+load_dwo_file (const char * main_filename, const char * name, const char * dir, const char * id ATTRIBUTE_UNUSED)
+{
+ char * separate_filename;
+ void * separate_handle;
+
+ /* FIXME: Skip adding / if dwo_dir ends in /. */
+ separate_filename = concat (dir, "/", name, NULL);
+ if (separate_filename == NULL)
+ {
+ warn (_("Out of memory allocating dwo filename\n"));
+ return NULL;
+ }
+
+ if ((separate_handle = open_debug_file (separate_filename)) == NULL)
+ {
+ warn (_("Unable to load dwo file: %s\n"), separate_filename);
+ free (separate_filename);
+ return NULL;
+ }
+
+ /* FIXME: We should check the dwo_id. */
+
+ printf (_("%s: Found separate debug object file: %s\n\n"), main_filename, separate_filename);
+ add_separate_debug_file (separate_filename, separate_handle);
+ /* Note - separate_filename will be freed in free_debug_memory(). */
+ return separate_handle;
+}
+
+/* Load the separate debug info file(s) attached to FILE, if any exist.
+ Returns TRUE if any were found, FALSE otherwise.
+ If TRUE is returned then the linked list starting at first_separate_info
+ will be populated with open file handles. */
+
+bfd_boolean
+load_separate_debug_files (void * file, const char * filename)
{
+ /* Skip this operation if we are not interested in debug links. */
+ if (! do_follow_links && ! do_debug_links)
+ return FALSE;
+
+ /* See if there are any dwo links. */
+ if (load_debug_section (str, file)
+ && load_debug_section (abbrev, file)
+ && load_debug_section (info, file))
+ {
+ free_dwo_info ();
+
+ if (process_debug_info (& debug_displays[info].section, file, abbrev, TRUE, FALSE))
+ {
+ bfd_boolean introduced = FALSE;
+ dwo_info * dwinfo;
+ const char * dir = NULL;
+ const char * id = NULL;
+
+ for (dwinfo = first_dwo_info; dwinfo != NULL; dwinfo = dwinfo->next)
+ {
+ switch (dwinfo->type)
+ {
+ case DWO_NAME:
+ if (do_debug_links)
+ {
+ if (! introduced)
+ {
+ printf (_("The %s section contains link(s) to dwo file(s):\n\n"),
+ debug_displays [info].section.uncompressed_name);
+ introduced = TRUE;
+ }
+
+ printf (_(" Name: %s\n"), dwinfo->value);
+ printf (_(" Directory: %s\n"), dir ? dir : _("<not-found>"));
+ if (id != NULL)
+ display_data (printf (_(" ID: ")), (unsigned char *) id, 8);
+ else
+ printf (_(" ID: <unknown>\n"));
+ printf ("\n\n");
+ }
+
+ if (do_follow_links)
+ load_dwo_file (filename, dwinfo->value, dir, id);
+ break;
+
+ case DWO_DIR:
+ dir = dwinfo->value;
+ break;
+
+ case DWO_ID:
+ id = dwinfo->value;
+ break;
+
+ default:
+ error (_("Unexpected DWO INFO type"));
+ break;
+ }
+ }
+ }
+ }
+
if (! do_follow_links)
- return NULL;
+ /* The other debug links will be displayed by display_debug_links()
+ so we do not need to do any further processing here. */
+ return FALSE;
/* FIXME: We do not check for the presence of both link sections in the same file. */
/* FIXME: We do not check the separate debug info file to see if it too contains debuglinks. */
/* FIXME: We do not check for the presence of multiple, same-name debuglink sections. */
+ /* FIXME: We do not check for the presence of a dwo link as well as a debuglink. */
- /* We try the alt version first as that is blessed by the DWARF5 standard. */
if (load_debug_section (gnu_debugaltlink, file))
{
Build_id_data * build_id_data;
- return load_separate_debug_info (filename,
- & debug_displays[gnu_debugaltlink].section,
- parse_gnu_debugaltlink,
- check_gnu_debugaltlink,
- & build_id_data);
+ load_separate_debug_info (filename,
+ & debug_displays[gnu_debugaltlink].section,
+ parse_gnu_debugaltlink,
+ check_gnu_debugaltlink,
+ & build_id_data,
+ file);
}
if (load_debug_section (gnu_debuglink, file))
{
unsigned long crc32;
- return load_separate_debug_info (filename,
- & debug_displays[gnu_debuglink].section,
- parse_gnu_debuglink,
- check_gnu_debuglink,
- & crc32);
+ load_separate_debug_info (filename,
+ & debug_displays[gnu_debuglink].section,
+ parse_gnu_debuglink,
+ check_gnu_debuglink,
+ & crc32,
+ file);
}
+ if (first_separate_info != NULL)
+ return TRUE;
+
do_follow_links = 0;
- return NULL;
+ return FALSE;
}
void
alloc_num_debug_info_entries = num_debug_info_entries = 0;
}
- if (separate_debug_file != NULL)
- {
- close_debug_file (separate_debug_file);
- separate_debug_file = NULL;
+ separate_info * d;
+ separate_info * next;
- free ((void *) separate_debug_filename);
- separate_debug_filename = NULL;
+ for (d = first_separate_info; d != NULL; d = next)
+ {
+ close_debug_file (d->handle);
+ free ((void *) d->filename);
+ next = d->next;
+ free ((void *) d);
}
+ first_separate_info = NULL;
+
+ free_dwo_info ();
}
void