int do_debug_macinfo;
int do_debug_str;
int do_debug_loc;
+int do_wide;
+
+/* Values for do_debug_lines. */
+#define FLAG_DEBUG_LINES_RAW 1
+#define FLAG_DEBUG_LINES_DECODED 2
dwarf_vma (*byte_get) (unsigned char *, int);
}
}
+static int
+size_of_encoded_value (int encoding)
+{
+ switch (encoding & 0x7)
+ {
+ default: /* ??? */
+ case 0: return eh_addr_size;
+ case 2: return 2;
+ case 3: return 4;
+ case 4: return 8;
+ }
+}
+
+static dwarf_vma
+get_encoded_value (unsigned char *data, int encoding)
+{
+ int size = size_of_encoded_value (encoding);
+
+ if (encoding & DW_EH_PE_signed)
+ return byte_get_signed (data, size);
+ else
+ return byte_get (data, size);
+}
+
/* Print a dwarf_vma value (typically an address, offset or length) in
hexadecimal format, followed by a space. The length of the value (and
hence the precision displayed) is determined by the byte_size parameter. */
snprintf (buff, sizeof (buff), "%16.16lx ", val);
#endif
- printf (buff + (byte_size == 4 ? 8 : 0));
+ fputs (buff + (byte_size == 4 ? 8 : 0), stdout);
}
static unsigned long int
printf (_("%s\n\n"), name);
break;
+ case DW_LNE_set_discriminator:
+ printf (_("set Discriminator to %lu\n"),
+ read_leb128 (data, & bytes_read, 0));
+ break;
+
/* HP extensions. */
case DW_LNE_HP_negate_is_UV_update:
- printf ("DW_LNE_HP_negate_is_UV_update");
+ printf ("DW_LNE_HP_negate_is_UV_update\n");
break;
case DW_LNE_HP_push_context:
- printf ("DW_LNE_HP_push_context");
+ printf ("DW_LNE_HP_push_context\n");
break;
case DW_LNE_HP_pop_context:
- printf ("DW_LNE_HP_pop_context");
+ printf ("DW_LNE_HP_pop_context\n");
break;
case DW_LNE_HP_set_file_line_column:
- printf ("DW_LNE_HP_set_file_line_column");
+ printf ("DW_LNE_HP_set_file_line_column\n");
break;
case DW_LNE_HP_set_routine_name:
- printf ("DW_LNE_HP_set_routine_name");
+ printf ("DW_LNE_HP_set_routine_name\n");
break;
case DW_LNE_HP_set_sequence:
- printf ("DW_LNE_HP_set_sequence");
+ printf ("DW_LNE_HP_set_sequence\n");
break;
case DW_LNE_HP_negate_post_semantics:
- printf ("DW_LNE_HP_negate_post_semantics");
+ printf ("DW_LNE_HP_negate_post_semantics\n");
break;
case DW_LNE_HP_negate_function_exit:
- printf ("DW_LNE_HP_negate_function_exit");
+ printf ("DW_LNE_HP_negate_function_exit\n");
break;
case DW_LNE_HP_negate_front_end_logical:
- printf ("DW_LNE_HP_negate_front_end_logical");
+ printf ("DW_LNE_HP_negate_front_end_logical\n");
break;
case DW_LNE_HP_define_proc:
- printf ("DW_LNE_HP_define_proc");
+ printf ("DW_LNE_HP_define_proc\n");
break;
default:
decode_location_expression (unsigned char * data,
unsigned int pointer_size,
unsigned long length,
- unsigned long cu_offset)
+ unsigned long cu_offset,
+ struct dwarf_section * section)
{
unsigned op;
unsigned int bytes_read;
printf ("DW_OP_GNU_uninit");
/* FIXME: Is there data associated with this OP ? */
break;
+ case DW_OP_GNU_encoded_addr:
+ {
+ int encoding;
+ dwarf_vma addr;
+
+ encoding = *data++;
+ addr = get_encoded_value (data, encoding);
+ if ((encoding & 0x70) == DW_EH_PE_pcrel)
+ addr += section->address + (data - section->start);
+ data += size_of_encoded_value (encoding);
+
+ printf ("DW_OP_GNU_encoded_addr: fmt:%02x addr:", encoding);
+ print_dwarf_vma (addr, pointer_size);
+ }
+ break;
/* HP extensions. */
case DW_OP_HP_is_value:
need_frame_base = decode_location_expression (block_start,
pointer_size,
uvalue,
- cu_offset);
+ cu_offset, section);
printf (")");
if (need_frame_base && !have_frame_base)
printf (_(" [without DW_AT_frame_base]"));
if (uvalue >= section->size)
warn (_("Offset %lx used as value for DW_AT_import attribute of DIE at offset %lx is too big.\n"),
- uvalue, (long int)(orig_data - section->start));
+ uvalue, (unsigned long) (orig_data - section->start));
else
{
unsigned long abbrev_number;
if (!do_loc)
{
- printf (_("The section %s contains:\n\n"), section->name);
+ printf (_("Contents of the %s section:\n\n"), section->name);
load_debug_section (str, file);
}
}
static int
-display_debug_lines (struct dwarf_section *section, void *file)
+display_debug_lines_raw (struct dwarf_section *section,
+ unsigned char *data,
+ unsigned char *end)
{
unsigned char *start = section->start;
- unsigned char *data = start;
- unsigned char *end = start + section->size;
- printf (_("\nDump of debug contents of section %s:\n\n"),
- section->name);
-
- if (load_debug_info (file) == 0)
- {
- warn (_("Unable to load/parse the .debug_info section, so cannot interpret the %s section.\n"),
- section->name);
- return 0;
- }
+ printf (_("Raw dump of debug contents of section %s:\n\n"),
+ section->name);
while (data < end)
{
if (info.li_length + initial_length_size > section->size)
{
warn
- (_("The line info appears to be corrupt - the section is too small\n"));
+ (_("The information in section %s appears to be corrupt - the section is too small\n"),
+ section->name);
return 0;
}
return 1;
}
+typedef struct
+{
+ unsigned char *name;
+ unsigned int directory_index;
+ unsigned int modification_date;
+ unsigned int length;
+} File_Entry;
+
+/* Output a decoded representation of the .debug_line section. */
+
+static int
+display_debug_lines_decoded (struct dwarf_section *section,
+ unsigned char *data,
+ unsigned char *end)
+{
+ printf (_("Decoded dump of debug contents of section %s:\n\n"),
+ section->name);
+
+ while (data < end)
+ {
+ /* This loop amounts to one iteration per compilation unit. */
+ DWARF2_Internal_LineInfo info;
+ unsigned char *standard_opcodes;
+ unsigned char *end_of_sequence;
+ unsigned char *hdrptr;
+ int initial_length_size;
+ int offset_size;
+ int i;
+ File_Entry *file_table = NULL;
+ unsigned char **directory_table = NULL;
+ unsigned int prev_line = 0;
+
+ hdrptr = data;
+
+ /* Extract information from the Line Number Program Header.
+ (section 6.2.4 in the Dwarf3 doc). */
+
+ /* Get the length of this CU's line number information block. */
+ info.li_length = byte_get (hdrptr, 4);
+ hdrptr += 4;
+
+ if (info.li_length == 0xffffffff)
+ {
+ /* This section is 64-bit DWARF 3. */
+ info.li_length = byte_get (hdrptr, 8);
+ hdrptr += 8;
+ offset_size = 8;
+ initial_length_size = 12;
+ }
+ else
+ {
+ offset_size = 4;
+ initial_length_size = 4;
+ }
+
+ if (info.li_length + initial_length_size > section->size)
+ {
+ warn (_("The line info appears to be corrupt - "
+ "the section is too small\n"));
+ return 0;
+ }
+
+ /* Get this CU's Line Number Block version number. */
+ info.li_version = byte_get (hdrptr, 2);
+ hdrptr += 2;
+ if (info.li_version != 2 && info.li_version != 3)
+ {
+ warn (_("Only DWARF version 2 and 3 line info is currently "
+ "supported.\n"));
+ return 0;
+ }
+
+ info.li_prologue_length = byte_get (hdrptr, offset_size);
+ hdrptr += offset_size;
+ info.li_min_insn_length = byte_get (hdrptr, 1);
+ hdrptr++;
+ info.li_default_is_stmt = byte_get (hdrptr, 1);
+ hdrptr++;
+ info.li_line_base = byte_get (hdrptr, 1);
+ hdrptr++;
+ info.li_line_range = byte_get (hdrptr, 1);
+ hdrptr++;
+ info.li_opcode_base = byte_get (hdrptr, 1);
+ hdrptr++;
+
+ /* Sign extend the line base field. */
+ info.li_line_base <<= 24;
+ info.li_line_base >>= 24;
+
+ /* Find the end of this CU's Line Number Information Block. */
+ end_of_sequence = data + info.li_length + initial_length_size;
+
+ reset_state_machine (info.li_default_is_stmt);
+
+ /* Save a pointer to the contents of the Opcodes table. */
+ standard_opcodes = hdrptr;
+
+ /* Traverse the Directory table just to count entries. */
+ data = standard_opcodes + info.li_opcode_base - 1;
+ if (*data != 0)
+ {
+ unsigned int n_directories = 0;
+ unsigned char *ptr_directory_table = data;
+ int i;
+
+ while (*data != 0)
+ {
+ data += strlen ((char *) data) + 1;
+ n_directories++;
+ }
+
+ /* Go through the directory table again to save the directories. */
+ directory_table = xmalloc (n_directories * sizeof (unsigned char *));
+
+ i = 0;
+ while (*ptr_directory_table != 0)
+ {
+ directory_table[i] = ptr_directory_table;
+ ptr_directory_table += strlen ((char *) ptr_directory_table) + 1;
+ i++;
+ }
+ }
+ /* Skip the NUL at the end of the table. */
+ data++;
+
+ /* Traverse the File Name table just to count the entries. */
+ if (*data != 0)
+ {
+ unsigned int n_files = 0;
+ unsigned char *ptr_file_name_table = data;
+ int i;
+
+ while (*data != 0)
+ {
+ unsigned int bytes_read;
+
+ /* Skip Name, directory index, last modification time and length
+ of file. */
+ data += strlen ((char *) data) + 1;
+ read_leb128 (data, & bytes_read, 0);
+ data += bytes_read;
+ read_leb128 (data, & bytes_read, 0);
+ data += bytes_read;
+ read_leb128 (data, & bytes_read, 0);
+ data += bytes_read;
+
+ n_files++;
+ }
+
+ /* Go through the file table again to save the strings. */
+ file_table = xmalloc (n_files * sizeof (File_Entry));
+
+ i = 0;
+ while (*ptr_file_name_table != 0)
+ {
+ unsigned int bytes_read;
+
+ file_table[i].name = ptr_file_name_table;
+ ptr_file_name_table += strlen ((char *) ptr_file_name_table) + 1;
+
+ /* We are not interested in directory, time or size. */
+ file_table[i].directory_index = read_leb128 (ptr_file_name_table,
+ & bytes_read, 0);
+ ptr_file_name_table += bytes_read;
+ file_table[i].modification_date = read_leb128 (ptr_file_name_table,
+ & bytes_read, 0);
+ ptr_file_name_table += bytes_read;
+ file_table[i].length = read_leb128 (ptr_file_name_table, & bytes_read, 0);
+ ptr_file_name_table += bytes_read;
+ i++;
+ }
+ i = 0;
+
+ /* Print the Compilation Unit's name and a header. */
+ if (directory_table == NULL)
+ {
+ printf (_("CU: %s:\n"), file_table[0].name);
+ printf (_("File name Line number Starting address\n"));
+ }
+ else
+ {
+ if (do_wide || strlen ((char *) directory_table[0]) < 76)
+ {
+ printf (_("CU: %s/%s:\n"), directory_table[0],
+ file_table[0].name);
+ }
+ else
+ {
+ printf (_("%s:\n"), file_table[0].name);
+ }
+ printf (_("File name Line number Starting address\n"));
+ }
+ }
+
+ /* Skip the NUL at the end of the table. */
+ data++;
+
+ /* This loop iterates through the Dwarf Line Number Program. */
+ while (data < end_of_sequence)
+ {
+ unsigned char op_code;
+ int adv;
+ unsigned long int uladv;
+ unsigned int bytes_read;
+ int is_special_opcode = 0;
+
+ op_code = *data++;
+ prev_line = state_machine_regs.line;
+
+ if (op_code >= info.li_opcode_base)
+ {
+ op_code -= info.li_opcode_base;
+ uladv = (op_code / info.li_line_range) * info.li_min_insn_length;
+ state_machine_regs.address += uladv;
+
+ adv = (op_code % info.li_line_range) + info.li_line_base;
+ state_machine_regs.line += adv;
+ is_special_opcode = 1;
+ }
+ else switch (op_code)
+ {
+ case DW_LNS_extended_op:
+ {
+ unsigned int ext_op_code_len;
+ unsigned int bytes_read;
+ unsigned char ext_op_code;
+ unsigned char *op_code_data = data;
+
+ ext_op_code_len = read_leb128 (op_code_data, &bytes_read, 0);
+ 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++;
+
+ switch (ext_op_code)
+ {
+ case DW_LNE_end_sequence:
+ reset_state_machine (info.li_default_is_stmt);
+ break;
+ case DW_LNE_set_address:
+ state_machine_regs.address =
+ byte_get (op_code_data, ext_op_code_len - bytes_read - 1);
+ break;
+ case DW_LNE_define_file:
+ {
+ unsigned int dir_index = 0;
+
+ ++state_machine_regs.last_file_entry;
+ op_code_data += strlen ((char *) op_code_data) + 1;
+ dir_index = read_leb128 (op_code_data, & bytes_read, 0);
+ op_code_data += bytes_read;
+ read_leb128 (op_code_data, & bytes_read, 0);
+ op_code_data += bytes_read;
+ read_leb128 (op_code_data, & bytes_read, 0);
+
+ printf (_("%s:\n"), directory_table[dir_index]);
+ break;
+ }
+ default:
+ printf (_("UNKNOWN: length %d\n"), ext_op_code_len - bytes_read);
+ break;
+ }
+ data += ext_op_code_len;
+ break;
+ }
+ case DW_LNS_copy:
+ break;
+
+ case DW_LNS_advance_pc:
+ uladv = read_leb128 (data, & bytes_read, 0);
+ uladv *= info.li_min_insn_length;
+ data += bytes_read;
+ state_machine_regs.address += uladv;
+ break;
+
+ case DW_LNS_advance_line:
+ adv = read_leb128 (data, & bytes_read, 1);
+ data += bytes_read;
+ state_machine_regs.line += adv;
+ break;
+
+ case DW_LNS_set_file:
+ adv = read_leb128 (data, & bytes_read, 0);
+ data += bytes_read;
+ state_machine_regs.file = adv;
+ if (file_table[state_machine_regs.file - 1].directory_index == 0)
+ {
+ /* If directory index is 0, that means current directory. */
+ printf (_("\n./%s:[++]\n"),
+ file_table[state_machine_regs.file - 1].name);
+ }
+ else
+ {
+ /* The directory index starts counting at 1. */
+ printf (_("\n%s/%s:\n"),
+ directory_table[file_table[state_machine_regs.file - 1].directory_index - 1],
+ file_table[state_machine_regs.file - 1].name);
+ }
+ break;
+
+ case DW_LNS_set_column:
+ uladv = read_leb128 (data, & bytes_read, 0);
+ 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 - info.li_opcode_base) / info.li_line_range)
+ * info.li_min_insn_length);
+ state_machine_regs.address += uladv;
+ break;
+
+ case DW_LNS_fixed_advance_pc:
+ uladv = byte_get (data, 2);
+ data += 2;
+ state_machine_regs.address += uladv;
+ break;
+
+ case DW_LNS_set_prologue_end:
+ break;
+
+ case DW_LNS_set_epilogue_begin:
+ break;
+
+ case DW_LNS_set_isa:
+ uladv = read_leb128 (data, & bytes_read, 0);
+ data += bytes_read;
+ printf (_(" Set ISA to %lu\n"), uladv);
+ break;
+
+ default:
+ printf (_(" Unknown opcode %d with operands: "), op_code);
+
+ for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
+ {
+ printf ("0x%lx%s", read_leb128 (data, &bytes_read, 0),
+ i == 1 ? "" : ", ");
+ data += bytes_read;
+ }
+ putchar ('\n');
+ break;
+ }
+
+ /* Only Special opcodes, DW_LNS_copy and DW_LNE_end_sequence adds a row
+ to the DWARF address/line matrix. */
+ if ((is_special_opcode) || (op_code == DW_LNE_end_sequence)
+ || (op_code == DW_LNS_copy))
+ {
+ const unsigned int MAX_FILENAME_LENGTH = 35;
+ char *fileName = (char *)file_table[state_machine_regs.file - 1].name;
+ char *newFileName = NULL;
+ size_t fileNameLength = strlen (fileName);
+
+ if ((fileNameLength > MAX_FILENAME_LENGTH) && (!do_wide))
+ {
+ newFileName = xmalloc (MAX_FILENAME_LENGTH + 1);
+ /* Truncate file name */
+ strncpy (newFileName,
+ fileName + fileNameLength - MAX_FILENAME_LENGTH,
+ MAX_FILENAME_LENGTH + 1);
+ }
+ else
+ {
+ newFileName = xmalloc (fileNameLength + 1);
+ strncpy (newFileName, fileName, fileNameLength + 1);
+ }
+
+ if (!do_wide || (fileNameLength <= MAX_FILENAME_LENGTH))
+ {
+ printf (_("%-35s %11d %#18lx\n"), newFileName,
+ state_machine_regs.line, state_machine_regs.address);
+ }
+ else
+ {
+ printf (_("%s %11d %#18lx\n"), newFileName,
+ state_machine_regs.line, state_machine_regs.address);
+ }
+
+ if (op_code == DW_LNE_end_sequence)
+ printf ("\n");
+
+ free (newFileName);
+ }
+ }
+ free (file_table);
+ file_table = NULL;
+ free (directory_table);
+ directory_table = NULL;
+ putchar ('\n');
+ }
+
+ return 1;
+}
+
+static int
+display_debug_lines (struct dwarf_section *section, void *file)
+{
+ unsigned char *data = section->start;
+ unsigned char *end = data + section->size;
+ int retValRaw = 1;
+ int retValDecoded = 1;
+
+ if (load_debug_info (file) == 0)
+ {
+ warn (_("Unable to load/parse the .debug_info section, so cannot interpret the %s section.\n"),
+ section->name);
+ return 0;
+ }
+
+ if (do_debug_lines & FLAG_DEBUG_LINES_RAW)
+ retValRaw = display_debug_lines_raw (section, data, end);
+
+ if (do_debug_lines & FLAG_DEBUG_LINES_DECODED)
+ retValDecoded = display_debug_lines_decoded (section, data, end);
+
+ if (!retValRaw || !retValDecoded)
+ return 0;
+
+ return 1;
+}
+
static debug_info *
find_debug_info_for_offset (unsigned long offset)
{
if (offset != 0)
{
data += offset_size;
- printf (" %-6ld\t\t%s\n", offset, data);
+ printf (" %-6lx\t%s\n", offset, data);
data += strlen ((char *) data) + 1;
}
}
{
if (start < next)
warn (_("There is a hole [0x%lx - 0x%lx] in .debug_loc section.\n"),
- (long)(start - section_begin), (long)(next - section_begin));
+ (unsigned long) (start - section_begin),
+ (unsigned long) (next - section_begin));
else if (start > next)
warn (_("There is an overlap [0x%lx - 0x%lx] in .debug_loc section.\n"),
- (long)(start - section_begin), (long)(next - section_begin));
+ (unsigned long) (start - section_begin),
+ (unsigned long) (next - section_begin));
}
start = next;
need_frame_base = decode_location_expression (start,
pointer_size,
length,
- cu_offset);
+ cu_offset, section);
putchar (')');
if (need_frame_base && !has_frame_base)
if (start < section_end)
warn (_("There are %ld unused bytes at the end of section %s\n"),
(long) (section_end - start), section->name);
+ putchar ('\n');
return 1;
}
unsigned char *start = section->start;
unsigned char *end = start + section->size;
- printf (_("The section %s contains:\n\n"), section->name);
+ printf (_("Contents of the %s section:\n\n"), section->name);
/* It does not matter if this load fails,
we test for that later on. */
ranges += address_size;
+ printf (" ");
print_dwarf_vma (address, address_size);
print_dwarf_vma (length, address_size);
putchar ('\n');
{
if (start < next)
warn (_("There is a hole [0x%lx - 0x%lx] in %s section.\n"),
- (long)(start - section_begin),
- (long)(next - section_begin), section->name);
+ (unsigned long) (start - section_begin),
+ (unsigned long) (next - section_begin), section->name);
else if (start > next)
warn (_("There is an overlap [0x%lx - 0x%lx] in %s section.\n"),
- (long)(start - section_begin),
- (long)(next - section_begin), section->name);
+ (unsigned long) (start - section_begin),
+ (unsigned long) (next - section_begin), section->name);
}
start = next;
break;
}
- print_dwarf_vma (begin, pointer_size);
- print_dwarf_vma (end, pointer_size);
-
/* Check base address specifiers. */
if (begin == (dwarf_vma) -1 && end != (dwarf_vma) -1)
{
base_address = end;
+ print_dwarf_vma (begin, pointer_size);
+ print_dwarf_vma (end, pointer_size);
printf ("(base address)\n");
continue;
}
+ print_dwarf_vma (begin + base_address, pointer_size);
+ print_dwarf_vma (end + base_address, pointer_size);
+
if (begin == end)
fputs (_("(start == end)"), stdout);
else if (begin > end)
}
Frame_Chunk;
+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)
-static void
-frame_need_space (Frame_Chunk *fc, int reg)
+/* Return 0 if not more space is needed, 1 if more space is needed,
+ -1 for invalid reg. */
+
+static int
+frame_need_space (Frame_Chunk *fc, unsigned int reg)
{
int prev = fc->ncols;
- if (reg < fc->ncols)
- return;
+ if (reg < (unsigned int) fc->ncols)
+ return 0;
+
+ if (dwarf_regnames_count
+ && reg > dwarf_regnames_count)
+ return -1;
fc->ncols = reg + 1;
fc->col_type = xcrealloc (fc->col_type, fc->ncols, sizeof (short int));
fc->col_offset[prev] = 0;
prev++;
}
+ return 1;
}
static const char *const dwarf_regnames_i386[] =
"mm4", "mm5", "mm6", "mm7",
"fcw", "fsw", "mxcsr",
"es", "cs", "ss", "ds", "fs", "gs", NULL, NULL,
- "tr", "ldtr",
- NULL, NULL, NULL,
- "ymm0", "ymm1", "ymm2", "ymm3",
- "ymm4", "ymm5", "ymm6", "ymm7"
+ "tr", "ldtr"
};
static const char *const dwarf_regnames_x86_64[] =
"es", "cs", "ss", "ds", "fs", "gs", NULL, NULL,
"fs.base", "gs.base", NULL, NULL,
"tr", "ldtr",
- "mxcsr", "fcw", "fsw",
- NULL, NULL, NULL,
- "ymm0", "ymm1", "ymm2", "ymm3",
- "ymm4", "ymm5", "ymm6", "ymm7",
- "ymm8", "ymm9", "ymm10", "ymm11",
- "ymm12", "ymm13", "ymm14", "ymm15"
+ "mxcsr", "fcw", "fsw"
};
-static const char *const *dwarf_regnames;
-static unsigned int dwarf_regnames_count;
-
void
init_dwarf_regnames (unsigned int e_machine)
{
printf ("\n");
}
-static int
-size_of_encoded_value (int encoding)
-{
- switch (encoding & 0x7)
- {
- default: /* ??? */
- case 0: return eh_addr_size;
- case 2: return 2;
- case 3: return 4;
- case 4: return 8;
- }
-}
-
-static dwarf_vma
-get_encoded_value (unsigned char *data, int encoding)
-{
- int size = size_of_encoded_value (encoding);
-
- if (encoding & DW_EH_PE_signed)
- return byte_get_signed (data, size);
- else
- return byte_get (data, size);
-}
-
#define GET(N) byte_get (start, N); start += N
#define LEB() read_leb128 (start, & length_return, 0); start += length_return
#define SLEB() read_leb128 (start, & length_return, 1); start += length_return
int is_eh = strcmp (section->name, ".eh_frame") == 0;
unsigned int length_return;
int max_regs = 0;
+ const char *bad_reg = _("bad register: ");
- printf (_("The section %s contains:\n"), section->name);
+ printf (_("Contents of the %s section:\n"), section->name);
while (start < end)
{
break;
case DW_CFA_offset:
LEB ();
- frame_need_space (fc, opa);
- fc->col_type[opa] = DW_CFA_undefined;
+ if (frame_need_space (fc, opa) >= 0)
+ fc->col_type[opa] = DW_CFA_undefined;
break;
case DW_CFA_restore:
- frame_need_space (fc, opa);
- fc->col_type[opa] = DW_CFA_undefined;
+ if (frame_need_space (fc, opa) >= 0)
+ fc->col_type[opa] = DW_CFA_undefined;
break;
case DW_CFA_set_loc:
start += encoded_ptr_size;
case DW_CFA_offset_extended:
case DW_CFA_val_offset:
reg = LEB (); LEB ();
- frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_restore_extended:
reg = LEB ();
frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_undefined:
reg = LEB ();
- frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_same_value:
reg = LEB ();
- frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_register:
reg = LEB (); LEB ();
- frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_def_cfa:
LEB (); LEB ();
reg = LEB ();
tmp = LEB ();
start += tmp;
- frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_offset_extended_sf:
case DW_CFA_val_offset_sf:
reg = LEB (); SLEB ();
- frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_def_cfa_sf:
LEB (); SLEB ();
break;
case DW_CFA_GNU_negative_offset_extended:
reg = LEB (); LEB ();
- frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
-
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
+ break;
default:
break;
}
unsigned long ul, reg, roffs;
long l, ofs;
dwarf_vma vma;
+ const char *reg_prefix = "";
op = *start++;
opa = op & 0x3f;
case DW_CFA_offset:
roffs = LEB ();
- if (! do_debug_frames_interp)
- printf (" DW_CFA_offset: %s at cfa%+ld\n",
- regname (opa, 0), roffs * fc->data_factor);
- fc->col_type[opa] = DW_CFA_offset;
- fc->col_offset[opa] = roffs * fc->data_factor;
+ if (opa >= (unsigned int) fc->ncols)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
+ printf (" DW_CFA_offset: %s%s at cfa%+ld\n",
+ reg_prefix, regname (opa, 0),
+ roffs * fc->data_factor);
+ if (*reg_prefix == '\0')
+ {
+ fc->col_type[opa] = DW_CFA_offset;
+ fc->col_offset[opa] = roffs * fc->data_factor;
+ }
break;
case DW_CFA_restore:
- if (! do_debug_frames_interp)
- printf (" DW_CFA_restore: %s\n", regname (opa, 0));
- fc->col_type[opa] = cie->col_type[opa];
- fc->col_offset[opa] = cie->col_offset[opa];
+ if (opa >= (unsigned int) cie->ncols
+ || opa >= (unsigned int) fc->ncols)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
+ printf (" DW_CFA_restore: %s%s\n",
+ reg_prefix, regname (opa, 0));
+ if (*reg_prefix == '\0')
+ {
+ fc->col_type[opa] = cie->col_type[opa];
+ fc->col_offset[opa] = cie->col_offset[opa];
+ }
break;
case DW_CFA_set_loc:
case DW_CFA_offset_extended:
reg = LEB ();
roffs = LEB ();
- if (! do_debug_frames_interp)
- printf (" DW_CFA_offset_extended: %s at cfa%+ld\n",
- regname (reg, 0), roffs * fc->data_factor);
- fc->col_type[reg] = DW_CFA_offset;
- fc->col_offset[reg] = roffs * fc->data_factor;
+ if (reg >= (unsigned int) fc->ncols)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
+ printf (" DW_CFA_offset_extended: %s%s at cfa%+ld\n",
+ reg_prefix, regname (reg, 0),
+ roffs * fc->data_factor);
+ if (*reg_prefix == '\0')
+ {
+ fc->col_type[reg] = DW_CFA_offset;
+ fc->col_offset[reg] = roffs * fc->data_factor;
+ }
break;
case DW_CFA_val_offset:
reg = LEB ();
roffs = LEB ();
- if (! do_debug_frames_interp)
- printf (" DW_CFA_val_offset: %s at cfa%+ld\n",
- regname (reg, 0), roffs * fc->data_factor);
- fc->col_type[reg] = DW_CFA_val_offset;
- fc->col_offset[reg] = roffs * fc->data_factor;
+ if (reg >= (unsigned int) fc->ncols)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
+ printf (" DW_CFA_val_offset: %s%s at cfa%+ld\n",
+ reg_prefix, regname (reg, 0),
+ roffs * fc->data_factor);
+ if (*reg_prefix == '\0')
+ {
+ fc->col_type[reg] = DW_CFA_val_offset;
+ fc->col_offset[reg] = roffs * fc->data_factor;
+ }
break;
case DW_CFA_restore_extended:
reg = LEB ();
- if (! do_debug_frames_interp)
- printf (" DW_CFA_restore_extended: %s\n",
- regname (reg, 0));
- fc->col_type[reg] = cie->col_type[reg];
- fc->col_offset[reg] = cie->col_offset[reg];
+ if (reg >= (unsigned int) cie->ncols
+ || reg >= (unsigned int) fc->ncols)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
+ printf (" DW_CFA_restore_extended: %s%s\n",
+ reg_prefix, regname (reg, 0));
+ if (*reg_prefix == '\0')
+ {
+ fc->col_type[reg] = cie->col_type[reg];
+ fc->col_offset[reg] = cie->col_offset[reg];
+ }
break;
case DW_CFA_undefined:
reg = LEB ();
- if (! do_debug_frames_interp)
- printf (" DW_CFA_undefined: %s\n", regname (reg, 0));
- fc->col_type[reg] = DW_CFA_undefined;
- fc->col_offset[reg] = 0;
+ if (reg >= (unsigned int) fc->ncols)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
+ printf (" DW_CFA_undefined: %s%s\n",
+ reg_prefix, regname (reg, 0));
+ if (*reg_prefix == '\0')
+ {
+ fc->col_type[reg] = DW_CFA_undefined;
+ fc->col_offset[reg] = 0;
+ }
break;
case DW_CFA_same_value:
reg = LEB ();
- if (! do_debug_frames_interp)
- printf (" DW_CFA_same_value: %s\n", regname (reg, 0));
- fc->col_type[reg] = DW_CFA_same_value;
- fc->col_offset[reg] = 0;
+ if (reg >= (unsigned int) fc->ncols)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
+ printf (" DW_CFA_same_value: %s%s\n",
+ reg_prefix, regname (reg, 0));
+ if (*reg_prefix == '\0')
+ {
+ fc->col_type[reg] = DW_CFA_same_value;
+ fc->col_offset[reg] = 0;
+ }
break;
case DW_CFA_register:
reg = LEB ();
roffs = LEB ();
- if (! do_debug_frames_interp)
+ if (reg >= (unsigned int) fc->ncols)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
{
- printf (" DW_CFA_register: %s in ",
- regname (reg, 0));
+ printf (" DW_CFA_register: %s%s in ",
+ reg_prefix, regname (reg, 0));
puts (regname (roffs, 0));
}
- fc->col_type[reg] = DW_CFA_register;
- fc->col_offset[reg] = roffs;
+ if (*reg_prefix == '\0')
+ {
+ fc->col_type[reg] = DW_CFA_register;
+ fc->col_offset[reg] = roffs;
+ }
break;
case DW_CFA_remember_state:
if (! do_debug_frames_interp)
{
printf (" DW_CFA_def_cfa_expression (");
- decode_location_expression (start, eh_addr_size, ul, 0);
+ decode_location_expression (start, eh_addr_size, ul, 0,
+ section);
printf (")\n");
}
fc->cfa_exp = 1;
case DW_CFA_expression:
reg = LEB ();
ul = LEB ();
- if (! do_debug_frames_interp)
+ if (reg >= (unsigned int) fc->ncols)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
{
- printf (" DW_CFA_expression: %s (",
- regname (reg, 0));
+ printf (" DW_CFA_expression: %s%s (",
+ reg_prefix, regname (reg, 0));
decode_location_expression (start, eh_addr_size,
- ul, 0);
+ ul, 0, section);
printf (")\n");
}
- fc->col_type[reg] = DW_CFA_expression;
+ if (*reg_prefix == '\0')
+ fc->col_type[reg] = DW_CFA_expression;
start += ul;
break;
case DW_CFA_val_expression:
reg = LEB ();
ul = LEB ();
- if (! do_debug_frames_interp)
+ if (reg >= (unsigned int) fc->ncols)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
{
- printf (" DW_CFA_val_expression: %s (",
- regname (reg, 0));
- decode_location_expression (start, eh_addr_size, ul, 0);
+ printf (" DW_CFA_val_expression: %s%s (",
+ reg_prefix, regname (reg, 0));
+ decode_location_expression (start, eh_addr_size, ul, 0,
+ section);
printf (")\n");
}
- fc->col_type[reg] = DW_CFA_val_expression;
+ if (*reg_prefix == '\0')
+ fc->col_type[reg] = DW_CFA_val_expression;
start += ul;
break;
case DW_CFA_offset_extended_sf:
reg = LEB ();
l = SLEB ();
- frame_need_space (fc, reg);
- if (! do_debug_frames_interp)
- printf (" DW_CFA_offset_extended_sf: %s at cfa%+ld\n",
- regname (reg, 0), l * fc->data_factor);
- fc->col_type[reg] = DW_CFA_offset;
- fc->col_offset[reg] = l * fc->data_factor;
+ if (frame_need_space (fc, reg) < 0)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
+ printf (" DW_CFA_offset_extended_sf: %s%s at cfa%+ld\n",
+ reg_prefix, regname (reg, 0),
+ l * fc->data_factor);
+ if (*reg_prefix == '\0')
+ {
+ fc->col_type[reg] = DW_CFA_offset;
+ fc->col_offset[reg] = l * fc->data_factor;
+ }
break;
case DW_CFA_val_offset_sf:
reg = LEB ();
l = SLEB ();
- frame_need_space (fc, reg);
- if (! do_debug_frames_interp)
- printf (" DW_CFA_val_offset_sf: %s at cfa%+ld\n",
- regname (reg, 0), l * fc->data_factor);
- fc->col_type[reg] = DW_CFA_val_offset;
- fc->col_offset[reg] = l * fc->data_factor;
+ if (frame_need_space (fc, reg) < 0)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
+ printf (" DW_CFA_val_offset_sf: %s%s at cfa%+ld\n",
+ reg_prefix, regname (reg, 0),
+ l * fc->data_factor);
+ if (*reg_prefix == '\0')
+ {
+ fc->col_type[reg] = DW_CFA_val_offset;
+ fc->col_offset[reg] = l * fc->data_factor;
+ }
break;
case DW_CFA_def_cfa_sf:
case DW_CFA_GNU_negative_offset_extended:
reg = LEB ();
l = - LEB ();
- frame_need_space (fc, reg);
- if (! do_debug_frames_interp)
- printf (" DW_CFA_GNU_negative_offset_extended: %s at cfa%+ld\n",
- regname (reg, 0), l * fc->data_factor);
- fc->col_type[reg] = DW_CFA_offset;
- fc->col_offset[reg] = l * fc->data_factor;
+ if (frame_need_space (fc, reg) < 0)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
+ printf (" DW_CFA_GNU_negative_offset_extended: %s%s at cfa%+ld\n",
+ reg_prefix, regname (reg, 0),
+ l * fc->data_factor);
+ if (*reg_prefix == '\0')
+ {
+ fc->col_type[reg] = DW_CFA_offset;
+ fc->col_offset[reg] = l * fc->data_factor;
+ }
break;
default:
}
}
+void
+dwarf_select_sections_by_names (const char *names)
+{
+ typedef struct
+ {
+ const char * option;
+ int * variable;
+ int val;
+ }
+ debug_dump_long_opts;
+
+ static const debug_dump_long_opts opts_table [] =
+ {
+ /* Please keep this table alpha- sorted. */
+ { "Ranges", & do_debug_ranges, 1 },
+ { "abbrev", & do_debug_abbrevs, 1 },
+ { "aranges", & do_debug_aranges, 1 },
+ { "frames", & do_debug_frames, 1 },
+ { "frames-interp", & do_debug_frames_interp, 1 },
+ { "info", & do_debug_info, 1 },
+ { "line", & do_debug_lines, FLAG_DEBUG_LINES_RAW }, /* For backwards compatibility. */
+ { "rawline", & do_debug_lines, FLAG_DEBUG_LINES_RAW },
+ { "decodedline", & do_debug_lines, FLAG_DEBUG_LINES_DECODED },
+ { "loc", & do_debug_loc, 1 },
+ { "macro", & do_debug_macinfo, 1 },
+ { "pubnames", & do_debug_pubnames, 1 },
+ /* This entry is for compatability
+ with earlier versions of readelf. */
+ { "ranges", & do_debug_aranges, 1 },
+ { "str", & do_debug_str, 1 },
+ { NULL, NULL, 0 }
+ };
+
+ const char *p;
+
+ p = names;
+ while (*p)
+ {
+ const debug_dump_long_opts * entry;
+
+ for (entry = opts_table; entry->option; entry++)
+ {
+ size_t len = strlen (entry->option);
+
+ if (strncmp (p, entry->option, len) == 0
+ && (p[len] == ',' || p[len] == '\0'))
+ {
+ * entry->variable |= entry->val;
+
+ /* The --debug-dump=frames-interp option also
+ enables the --debug-dump=frames option. */
+ if (do_debug_frames_interp)
+ do_debug_frames = 1;
+
+ p += len;
+ break;
+ }
+ }
+
+ if (entry->option == NULL)
+ {
+ warn (_("Unrecognized debug option '%s'\n"), p);
+ p = strchr (p, ',');
+ if (p == NULL)
+ break;
+ }
+
+ if (*p == ',')
+ p++;
+ }
+}
+
+void
+dwarf_select_sections_by_letters (const char *letters)
+{
+ unsigned int index = 0;
+
+ while (letters[index])
+ switch (letters[index++])
+ {
+ case 'i':
+ do_debug_info = 1;
+ break;
+
+ case 'a':
+ do_debug_abbrevs = 1;
+ break;
+
+ case 'l':
+ do_debug_lines |= FLAG_DEBUG_LINES_RAW;
+ break;
+
+ case 'L':
+ do_debug_lines |= FLAG_DEBUG_LINES_DECODED;
+ break;
+
+ case 'p':
+ do_debug_pubnames = 1;
+ break;
+
+ case 'r':
+ do_debug_aranges = 1;
+ break;
+
+ case 'R':
+ do_debug_ranges = 1;
+ break;
+
+ case 'F':
+ do_debug_frames_interp = 1;
+ case 'f':
+ do_debug_frames = 1;
+ break;
+
+ case 'm':
+ do_debug_macinfo = 1;
+ break;
+
+ case 's':
+ do_debug_str = 1;
+ break;
+
+ case 'o':
+ do_debug_loc = 1;
+ break;
+
+ default:
+ warn (_("Unrecognized debug option '%s'\n"), optarg);
+ break;
+ }
+}
+
+void
+dwarf_select_sections_all (void)
+{
+ do_debug_info = 1;
+ do_debug_abbrevs = 1;
+ do_debug_lines = FLAG_DEBUG_LINES_RAW;
+ do_debug_pubnames = 1;
+ do_debug_aranges = 1;
+ do_debug_ranges = 1;
+ do_debug_frames = 1;
+ do_debug_macinfo = 1;
+ do_debug_str = 1;
+ do_debug_loc = 1;
+}
+
struct dwarf_section_display debug_displays[] =
{
- { { ".debug_abbrev", NULL, 0, 0 },
- display_debug_abbrev, 0, 0 },
- { { ".debug_aranges", NULL, 0, 0 },
- display_debug_aranges, 0, 0 },
- { { ".debug_frame", NULL, 0, 0 },
- display_debug_frames, 1, 0 },
- { { ".debug_info", NULL, 0, 0 },
- display_debug_info, 1, 0 },
- { { ".debug_line", NULL, 0, 0 },
- display_debug_lines, 0, 0 },
- { { ".debug_pubnames", NULL, 0, 0 },
- display_debug_pubnames, 0, 0 },
- { { ".eh_frame", NULL, 0, 0 },
- display_debug_frames, 1, 1 },
- { { ".debug_macinfo", NULL, 0, 0 },
- display_debug_macinfo, 0, 0 },
- { { ".debug_str", NULL, 0, 0 },
- display_debug_str, 0, 0 },
- { { ".debug_loc", NULL, 0, 0 },
- display_debug_loc, 0, 0 },
- { { ".debug_pubtypes", NULL, 0, 0 },
- display_debug_pubnames, 0, 0 },
- { { ".debug_ranges", NULL, 0, 0 },
- display_debug_ranges, 0, 0 },
- { { ".debug_static_func", NULL, 0, 0 },
- display_debug_not_supported, 0, 0 },
- { { ".debug_static_vars", NULL, 0, 0 },
- display_debug_not_supported, 0, 0 },
- { { ".debug_types", NULL, 0, 0 },
- display_debug_not_supported, 0, 0 },
- { { ".debug_weaknames", NULL, 0, 0 },
- display_debug_not_supported, 0, 0 }
+ { { ".debug_abbrev", ".zdebug_abbrev", NULL, NULL, 0, 0 },
+ display_debug_abbrev, &do_debug_abbrevs, 0, 0 },
+ { { ".debug_aranges", ".zdebug_aranges", NULL, NULL, 0, 0 },
+ display_debug_aranges, &do_debug_aranges, 1, 0 },
+ { { ".debug_frame", ".zdebug_frame", NULL, NULL, 0, 0 },
+ display_debug_frames, &do_debug_frames, 1, 0 },
+ { { ".debug_info", ".zdebug_info", NULL, NULL, 0, 0 },
+ display_debug_info, &do_debug_info, 1, 0 },
+ { { ".debug_line", ".zdebug_line", NULL, NULL, 0, 0 },
+ display_debug_lines, &do_debug_lines, 1, 0 },
+ { { ".debug_pubnames", ".zdebug_pubnames", NULL, NULL, 0, 0 },
+ display_debug_pubnames, &do_debug_pubnames, 0, 0 },
+ { { ".eh_frame", "", NULL, NULL, 0, 0 },
+ display_debug_frames, &do_debug_frames, 1, 1 },
+ { { ".debug_macinfo", ".zdebug_macinfo", NULL, NULL, 0, 0 },
+ display_debug_macinfo, &do_debug_macinfo, 0, 0 },
+ { { ".debug_str", ".zdebug_str", NULL, NULL, 0, 0 },
+ display_debug_str, &do_debug_str, 0, 0 },
+ { { ".debug_loc", ".zdebug_loc", NULL, NULL, 0, 0 },
+ display_debug_loc, &do_debug_loc, 1, 0 },
+ { { ".debug_pubtypes", ".zdebug_pubtypes", NULL, NULL, 0, 0 },
+ display_debug_pubnames, &do_debug_pubnames, 0, 0 },
+ { { ".debug_ranges", ".zdebug_ranges", NULL, NULL, 0, 0 },
+ display_debug_ranges, &do_debug_ranges, 1, 0 },
+ { { ".debug_static_func", ".zdebug_static_func", NULL, NULL, 0, 0 },
+ display_debug_not_supported, NULL, 0, 0 },
+ { { ".debug_static_vars", ".zdebug_static_vars", NULL, NULL, 0, 0 },
+ display_debug_not_supported, NULL, 0, 0 },
+ { { ".debug_types", ".zdebug_types", NULL, NULL, 0, 0 },
+ display_debug_not_supported, NULL, 0, 0 },
+ { { ".debug_weaknames", ".zdebug_weaknames", NULL, NULL, 0, 0 },
+ display_debug_not_supported, NULL, 0, 0 }
};