From 31b6fca668a517baff6e56246980ecafd1824d1f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 16 May 2001 16:20:26 +0000 Subject: [PATCH] * 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. --- binutils/ChangeLog | 13 ++ binutils/readelf.c | 307 ++++++++++++++++++++++++++++----------------- 2 files changed, 205 insertions(+), 115 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 33af926694c..5ce9f2c195e 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,16 @@ +2001-05-16 Richard Henderson + + * 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 * readelf.c: Replace uses of EM_MIPS_RS4_BE with EM_MIPS_RS3_LE. diff --git a/binutils/readelf.c b/binutils/readelf.c index 2f03f4a919c..e8cf75eb65a 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -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 */ - fc->augmentation = start; - - while (* start) - start++; + version = *start++; - start++; /* skip past NUL */ + fc->augmentation = start; + 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 }, -- 2.30.2