* readelf.c (do_debug_frames_interp): New.

(byte_get_little_endian): If BFD64, always read entire 8-byte fields.
        (byte_get_big_endian): Likewise.
        (parse_args) ['F']: Set do_debug_frames_interp.
        (Frame_Chunk): Make data_factor signed, add fde_encoding.
        (frame_display_row): Don't trunc pc_begin to int.
        (size_of_encoded_value): New.
        (display_debug_frames): Handle 64-bit targets.  Print raw data
        unless do_debug_frames_interp.
        (debug_displays): Remove duplicate .debug_frame.
This commit is contained in:
Richard Henderson 2001-05-16 16:20:26 +00:00
parent 7ee44f7484
commit 31b6fca668
2 changed files with 205 additions and 115 deletions

View file

@ -1,3 +1,16 @@
2001-05-16 Richard Henderson <rth@redhat.com>
* readelf.c (do_debug_frames_interp): New.
(byte_get_little_endian): If BFD64, always read entire 8-byte fields.
(byte_get_big_endian): Likewise.
(parse_args) ['F']: Set do_debug_frames_interp.
(Frame_Chunk): Make data_factor signed, add fde_encoding.
(frame_display_row): Don't trunc pc_begin to int.
(size_of_encoded_value): New.
(display_debug_frames): Handle 64-bit targets. Print raw data
unless do_debug_frames_interp.
(debug_displays): Remove duplicate .debug_frame.
2001-05-15 Ralf Baechle <ralf@gnu.org>
* readelf.c: Replace uses of EM_MIPS_RS4_BE with EM_MIPS_RS3_LE.

View file

@ -118,6 +118,7 @@ int do_debug_lines;
int do_debug_pubnames;
int do_debug_aranges;
int do_debug_frames;
int do_debug_frames_interp;
int do_arch;
int do_notes;
int is_32bit_elf;
@ -376,11 +377,13 @@ byte_get_little_endian (field, size)
return ((unsigned int) (field [0]))
| (((unsigned int) (field [1])) << 8);
#ifndef BFD64
case 8:
/* We want to extract data from an 8 byte wide field and
place it into a 4 byte wide field. Since this is a little
endian source we can juts use the 4 byte extraction code. */
/* Fall through. */
#endif
case 4:
return ((unsigned long) (field [0]))
| (((unsigned long) (field [1])) << 8)
@ -388,6 +391,7 @@ byte_get_little_endian (field, size)
| (((unsigned long) (field [3])) << 24);
#ifdef BFD64
case 8:
case -8:
/* This is a special case, generated by the BYTE_GET8 macro.
It means that we are loading an 8 byte value from a field
@ -516,6 +520,7 @@ byte_get_big_endian (field, size)
| (((unsigned long) (field [1])) << 16)
| (((unsigned long) (field [0])) << 24);
#ifndef BFD64
case 8:
/* Although we are extracing data from an 8 byte wide field, we
are returning only 4 bytes of data. */
@ -523,8 +528,8 @@ byte_get_big_endian (field, size)
| (((unsigned long) (field [6])) << 8)
| (((unsigned long) (field [5])) << 16)
| (((unsigned long) (field [4])) << 24);
#ifdef BFD64
#else
case 8:
case -8:
/* This is a special case, generated by the BYTE_GET8 macro.
It means that we are loading an 8 byte value from a field
@ -2164,8 +2169,9 @@ parse_args (argc, argv)
do_debug_aranges = 1;
break;
case 'f':
case 'F':
do_debug_frames_interp = 1;
case 'f':
do_debug_frames = 1;
break;
@ -2895,7 +2901,8 @@ process_section_headers (file)
dynamic_strings, char *, "dynamic strings");
}
else if ((do_debugging || do_debug_info || do_debug_abbrevs
|| do_debug_lines || do_debug_pubnames || do_debug_aranges || do_debug_frames)
|| do_debug_lines || do_debug_pubnames || do_debug_aranges
|| do_debug_frames)
&& strncmp (name, ".debug_", 7) == 0)
{
name += 7;
@ -6991,12 +6998,13 @@ typedef struct Frame_Chunk
int * col_offset;
char * augmentation;
unsigned int code_factor;
unsigned int data_factor;
int data_factor;
unsigned long pc_begin;
unsigned long pc_range;
int cfa_reg;
int cfa_offset;
int ra;
unsigned char fde_encoding;
}
Frame_Chunk;
@ -7058,7 +7066,7 @@ frame_display_row (fc, need_col_headers, max_regs)
printf ("\n");
}
printf ("%08x ", (unsigned int) fc->pc_begin);
printf ("%08lx ", fc->pc_begin);
sprintf (tmp, "r%d%+d", fc->cfa_reg, fc->cfa_offset);
printf ("%-8s ", tmp);
@ -7090,6 +7098,20 @@ frame_display_row (fc, need_col_headers, max_regs)
printf ("\n");
}
static int
size_of_encoded_value (encoding)
int encoding;
{
switch (encoding & 0x7)
{
default: /* ??? */
case 0: return is_32bit_elf ? 4 : 8;
case 2: return 2;
case 3: return 4;
case 4: return 8;
}
}
#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
@ -7108,6 +7130,7 @@ display_debug_frames (section, start, file)
int is_eh = (strcmp (SECTION_NAME (section), ".eh_frame") == 0);
int length_return;
int max_regs = 0;
int addr_size = is_32bit_elf ? 4 : 8;
printf (_("The section %s contains:\n"), SECTION_NAME (section));
@ -7120,6 +7143,9 @@ display_debug_frames (section, start, file)
Frame_Chunk * fc;
Frame_Chunk * cie;
int need_col_headers = 1;
unsigned char * augmentation_data = NULL;
unsigned long augmentation_data_len = 0;
int encoded_ptr_size = addr_size;
saved_start = start;
length = byte_get (start, 4); start += 4;
@ -7130,10 +7156,10 @@ display_debug_frames (section, start, file)
block_end = saved_start + length + 4;
cie_id = byte_get (start, 4); start += 4;
printf ("\n%08x %08lx %08lx ", saved_start - section_start, length, cie_id);
if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID))
{
int version;
fc = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
memset (fc, 0, sizeof (Frame_Chunk));
@ -7145,27 +7171,23 @@ display_debug_frames (section, start, file)
fc->col_offset = (int *) xmalloc (sizeof (int));
frame_need_space (fc, max_regs-1);
start ++; /* version */
version = *start++;
fc->augmentation = start;
while (* start)
start++;
start++; /* skip past NUL */
start = strchr (start, '\0') + 1;
if (fc->augmentation[0] == 'z')
{
int xtra;
fc->code_factor = LEB ();
fc->data_factor = SLEB ();
fc->ra = byte_get (start, 1); start += 1;
xtra = LEB ();
printf ("skipping %d extra bytes\n", xtra);
start += xtra;
augmentation_data_len = LEB ();
augmentation_data = start;
start += augmentation_data_len;
}
else if (strcmp (fc->augmentation, "eh") == 0)
{
start += 4;
start += addr_size;
fc->code_factor = LEB ();
fc->data_factor = SLEB ();
fc->ra = byte_get (start, 1); start += 1;
@ -7177,8 +7199,55 @@ display_debug_frames (section, start, file)
fc->ra = byte_get (start, 1); start += 1;
}
cie = fc;
printf ("CIE \"%s\" cf=%d df=%d ra=%d\n",
fc->augmentation, fc->code_factor, fc->data_factor, fc->ra);
if (do_debug_frames_interp)
printf ("\n%08lx %08lx %08lx CIE \"%s\" cf=%d df=%d ra=%d\n",
saved_start - section_start, length, cie_id,
fc->augmentation, fc->code_factor, fc->data_factor,
fc->ra);
else
{
printf ("\n%08lx %08lx %08lx CIE\n",
saved_start - section_start, length, cie_id);
printf (" Version: %d\n", version);
printf (" Augmentation: \"%s\"\n", fc->augmentation);
printf (" Code alignment factor: %u\n", fc->code_factor);
printf (" Data alignment factor: %d\n", fc->data_factor);
printf (" Return address column: %d\n", fc->ra);
if (augmentation_data_len)
{
unsigned long i;
printf (" Augmentation data: ");
for (i = 0; i < augmentation_data_len; ++i)
printf (" %02x", augmentation_data[i]);
putchar ('\n');
}
putchar ('\n');
}
if (augmentation_data_len)
{
unsigned char *p, *q;
p = fc->augmentation + 1;
q = augmentation_data;
while (1)
{
if (*p == 'L')
*q++;
else if (*p == 'P')
q += 1 + size_of_encoded_value (*q);
else if (*p == 'R')
fc->fde_encoding = *q++;
else
break;
p++;
}
if (fc->fde_encoding)
encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
}
frame_need_space (fc, fc->ra);
}
@ -7186,19 +7255,21 @@ display_debug_frames (section, start, file)
{
unsigned char * look_for;
static Frame_Chunk fde_fc;
int size;
fc = & fde_fc;
memset (fc, 0, sizeof (Frame_Chunk));
look_for = is_eh ? start-4-cie_id : (unsigned char *) cie_id;
look_for = is_eh ? start - 4 - cie_id : section_start + cie_id;
fc->pc_begin = byte_get (start, 4); start += 4;
fc->pc_range = byte_get (start, 4); start += 4;
for (cie=chunks; cie ; cie = cie->next)
if (cie->chunk_start == look_for)
break;
for (cie=chunks; cie && (cie->chunk_start != look_for); cie = cie->next);
if (!cie)
{
warn ("Invalid CIE pointer %08x in FDE at %08x\n", cie_id, saved_start);
warn ("Invalid CIE pointer %08lx in FDE at %08lx\n",
cie_id, saved_start);
start = block_end;
fc->ncols = 0;
fc->col_type = (short int *) xmalloc (sizeof (short int));
@ -7206,6 +7277,7 @@ display_debug_frames (section, start, file)
frame_need_space (fc, max_regs - 1);
cie = fc;
fc->augmentation = "";
fc->fde_encoding = 0;
}
else
{
@ -7221,25 +7293,43 @@ display_debug_frames (section, start, file)
fc->cfa_offset = cie->cfa_offset;
fc->ra = cie->ra;
frame_need_space (fc, max_regs-1);
fc->fde_encoding = cie->fde_encoding;
}
if (fc->fde_encoding)
encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
fc->pc_begin = byte_get (start, encoded_ptr_size);
start += encoded_ptr_size;
fc->pc_range = byte_get (start, encoded_ptr_size);
start += encoded_ptr_size;
if (cie->augmentation[0] == 'z')
{
unsigned long l = LEB ();
start += l;
augmentation_data_len = LEB ();
augmentation_data = start;
start += augmentation_data_len;
}
printf ("FDE cie=%08x pc=%08lx..%08lx\n",
cie->chunk_start-section_start, fc->pc_begin,
printf ("\n%08lx %08lx %08lx FDE cie=%08x pc=%08lx..%08lx\n",
saved_start - section_start, length, cie_id,
cie->chunk_start - section_start, fc->pc_begin,
fc->pc_begin + fc->pc_range);
if (! do_debug_frames_interp && augmentation_data_len)
{
unsigned long i;
printf (" Augmentation data: ");
for (i = 0; i < augmentation_data_len; ++i)
printf (" %02x", augmentation_data[i]);
putchar ('\n');
putchar ('\n');
}
}
/* At this point, fc is the current chunk, cie (if any) is set, and we're
about to interpret instructions for the chunk. */
/* This exists for readelf maintainers. */
#define FDEBUG 0
if (do_debug_frames_interp)
{
/* Start by making a pass over the chunk, allocating storage
and taking note of what registers are used. */
@ -7272,7 +7362,7 @@ display_debug_frames (section, start, file)
fc->col_type[opa] = DW_CFA_undefined;
break;
case DW_CFA_set_loc:
start += sizeof (vma);
start += encoded_ptr_size;
break;
case DW_CFA_advance_loc1:
start += 1;
@ -7358,103 +7448,104 @@ display_debug_frames (section, start, file)
switch (op)
{
case DW_CFA_advance_loc:
frame_display_row (fc, &need_col_headers, &max_regs);
#if FDEBUG
printf (" DW_CFA_advance_loc: %08x = %08x + %d*%d\n",
fc->pc_begin + opa * fc->code_factor, fc->pc_begin, opa, fc->code_factor);
#endif
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
printf (" DW_CFA_advance_loc: %d to %08lx\n",
opa * fc->code_factor,
fc->pc_begin + opa * fc->code_factor);
fc->pc_begin += opa * fc->code_factor;
break;
case DW_CFA_offset:
roffs = LEB ();
#if FDEBUG
printf (" DW_CFA_offset: r%d = cfa[%d*%d]\n", opa, roffs, fc->data_factor);
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_offset: r%d at cfa%+d\n",
opa, roffs * fc->data_factor);
fc->col_type[opa] = DW_CFA_offset;
fc->col_offset[opa] = roffs * fc->data_factor;
break;
case DW_CFA_restore:
#if FDEBUG
printf (" DW_CFA_restore: r%d\n", opa);
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_restore: r%d\n", opa);
fc->col_type[opa] = cie->col_type[opa];
fc->col_offset[opa] = cie->col_offset[opa];
break;
case DW_CFA_set_loc:
frame_display_row (fc, &need_col_headers, &max_regs);
vma = byte_get (start, sizeof (vma)); start += sizeof (vma);
#if FDEBUG
printf (" DW_CFA_set_loc: %08x\n", vma);
#endif
vma = byte_get (start, encoded_ptr_size);
start += encoded_ptr_size;
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
printf (" DW_CFA_set_loc: %08x\n", vma);
fc->pc_begin = vma;
break;
case DW_CFA_advance_loc1:
frame_display_row (fc, &need_col_headers, &max_regs);
ofs = byte_get (start, 1); start += 1;
#if FDEBUG
printf (" DW_CFA_advance_loc1: %08x = %08x + %d*%d\n",
fc->pc_begin + ofs * fc->code_factor, fc->pc_begin, ofs, fc->code_factor);
#endif
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
printf (" DW_CFA_advance_loc1: %d to %08lx\n",
ofs * fc->code_factor,
fc->pc_begin + ofs * fc->code_factor);
fc->pc_begin += ofs * fc->code_factor;
break;
case DW_CFA_advance_loc2:
frame_display_row (fc, &need_col_headers, &max_regs);
ofs = byte_get (start, 2); start += 2;
#if FDEBUG
printf (" DW_CFA_advance_loc2: %08x = %08x + %d*%d\n",
fc->pc_begin + ofs * fc->code_factor, fc->pc_begin, ofs, fc->code_factor);
#endif
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
printf (" DW_CFA_advance_loc2: %d to %08lx\n",
ofs * fc->code_factor,
fc->pc_begin + ofs * fc->code_factor);
fc->pc_begin += ofs * fc->code_factor;
break;
case DW_CFA_advance_loc4:
frame_display_row (fc, &need_col_headers, &max_regs);
ofs = byte_get (start, 4); start += 4;
#if FDEBUG
printf (" DW_CFA_advance_loc4: %08x = %08x + %d*%d\n",
fc->pc_begin + ofs * fc->code_factor, fc->pc_begin, ofs, fc->code_factor);
#endif
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
printf (" DW_CFA_advance_loc4: %d to %08lx\n",
ofs * fc->code_factor,
fc->pc_begin + ofs * fc->code_factor);
fc->pc_begin += ofs * fc->code_factor;
break;
case DW_CFA_offset_extended:
reg = LEB ();
roffs = LEB ();
#if FDEBUG
printf (" DW_CFA_offset_extended: r%d = cfa[%d*%d]\n", reg, roffs, fc->data_factor);
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_offset_extended: r%d at cfa%+d\n",
reg, roffs * fc->data_factor);
fc->col_type[reg] = DW_CFA_offset;
fc->col_offset[reg] = roffs * fc->data_factor;
break;
case DW_CFA_restore_extended:
reg = LEB ();
#if FDEBUG
printf (" DW_CFA_restore_extended: r%d\n", reg);
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_restore_extended: r%d\n", reg);
fc->col_type[reg] = cie->col_type[reg];
fc->col_offset[reg] = cie->col_offset[reg];
break;
case DW_CFA_undefined:
reg = LEB ();
#if FDEBUG
printf (" DW_CFA_undefined: r%d\n", reg);
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_undefined: r%d\n", reg);
fc->col_type[reg] = DW_CFA_undefined;
fc->col_offset[reg] = 0;
break;
case DW_CFA_same_value:
reg = LEB ();
#if FDEBUG
printf (" DW_CFA_same_value: r%d\n", reg);
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_same_value: r%d\n", reg);
fc->col_type[reg] = DW_CFA_same_value;
fc->col_offset[reg] = 0;
break;
@ -7462,17 +7553,15 @@ display_debug_frames (section, start, file)
case DW_CFA_register:
reg = LEB ();
roffs = LEB ();
#if FDEBUG
printf (" DW_CFA_register: r%d\n", reg);
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_register: r%d\n", reg);
fc->col_type[reg] = DW_CFA_register;
fc->col_offset[reg] = roffs;
break;
case DW_CFA_remember_state:
#if FDEBUG
printf (" DW_CFA_remember_state\n");
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_remember_state\n");
rs = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
rs->ncols = fc->ncols;
rs->col_type = (short int *) xmalloc (rs->ncols * sizeof (short int));
@ -7484,9 +7573,8 @@ display_debug_frames (section, start, file)
break;
case DW_CFA_restore_state:
#if FDEBUG
printf (" DW_CFA_restore_state\n");
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_restore_state\n");
rs = remembered_state;
remembered_state = rs->next;
frame_need_space (fc, rs->ncols-1);
@ -7500,60 +7588,49 @@ display_debug_frames (section, start, file)
case DW_CFA_def_cfa:
fc->cfa_reg = LEB ();
fc->cfa_offset = LEB ();
#if FDEBUG
printf (" DW_CFA_def_cfa: reg %d ofs %d\n", fc->cfa_reg, fc->cfa_offset);
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa: r%d ofs %d\n",
fc->cfa_reg, fc->cfa_offset);
break;
case DW_CFA_def_cfa_register:
fc->cfa_reg = LEB ();
#if FDEBUG
printf (" DW_CFA_def_cfa_reg: %d\n", fc->cfa_reg);
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_reg: r%d\n", fc->cfa_reg);
break;
case DW_CFA_def_cfa_offset:
fc->cfa_offset = LEB ();
#if FDEBUG
printf (" DW_CFA_def_cfa_offset: %d\n", fc->cfa_offset);
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_offset: %d\n", fc->cfa_offset);
break;
case DW_CFA_nop:
#if FDEBUG
printf (" DW_CFA_nop\n");
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_nop\n");
break;
#ifndef DW_CFA_GNU_window_save
#define DW_CFA_GNU_window_save 0x2d
#endif
case DW_CFA_GNU_window_save:
#if FDEBUG
printf (" DW_CFA_GNU_window_save\n");
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_GNU_window_save\n");
break;
#ifndef DW_CFA_GNU_args_size
#define DW_CFA_GNU_args_size 0x2e
#endif
case DW_CFA_GNU_args_size:
ul = LEB ();
#if FDEBUG
printf (" DW_CFA_GNU_args_size: %d\n", ul);
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_GNU_args_size: %d\n", ul);
break;
#ifndef DW_CFA_GNU_negative_offset_extended
#define DW_CFA_GNU_negative_offset_extended 0x2f
#endif
case DW_CFA_GNU_negative_offset_extended:
reg = LEB ();
l = - LEB ();
frame_need_space (fc, reg);
#if FDEBUG
printf (" DW_CFA_GNU_negative_offset_extended: r%d = cfa[%d*%d]\n", reg, l, fc->data_factor);
#endif
if (! do_debug_frames_interp)
printf (" DW_CFA_GNU_negative_offset_extended: r%d at cfa%+d\n",
reg, l * fc->data_factor);
fc->col_type[reg] = DW_CFA_offset;
fc->col_offset[reg] = l * fc->data_factor;
break;
@ -7564,7 +7641,8 @@ display_debug_frames (section, start, file)
}
}
frame_display_row (fc, &need_col_headers, &max_regs);
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
start = block_end;
}
@ -7627,7 +7705,6 @@ debug_displays[] =
{ ".debug_frame", display_debug_frames, NULL },
{ ".eh_frame", display_debug_frames, NULL },
{ ".debug_macinfo", display_debug_not_supported, NULL },
{ ".debug_frame", display_debug_not_supported, NULL },
{ ".debug_str", display_debug_not_supported, NULL },
{ ".debug_static_func", display_debug_not_supported, NULL },
{ ".debug_static_vars", display_debug_not_supported, NULL },