diff options
-rw-r--r-- | binutils/ChangeLog | 7 | ||||
-rw-r--r-- | binutils/dwarf.c | 260 |
2 files changed, 177 insertions, 90 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index c9423f7..e601e61 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,5 +1,12 @@ 2009-03-19 H.J. Lu <hongjiu.lu@intel.com> + * dwarf.c (dwarf_regnames): Moved before frame_need_space. + (dwarf_regnames_count): Likewise. + (frame_need_space): Return int. + (display_debug_frames): Check invalid registers. + +2009-03-19 H.J. Lu <hongjiu.lu@intel.com> + * readelf.c (debug_apply_relocations): Check relocations against STT_SECTION symbol. diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 2eca61e..d5dbb78 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -3621,17 +3621,27 @@ typedef struct Frame_Chunk } 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)); @@ -3643,6 +3653,7 @@ frame_need_space (Frame_Chunk *fc, int reg) fc->col_offset[prev] = 0; prev++; } + return 1; } static const char *const dwarf_regnames_i386[] = @@ -3684,9 +3695,6 @@ static const char *const dwarf_regnames_x86_64[] = "mxcsr", "fcw", "fsw" }; -static const char *const *dwarf_regnames; -static unsigned int dwarf_regnames_count; - void init_dwarf_regnames (unsigned int e_machine) { @@ -3816,6 +3824,7 @@ display_debug_frames (struct dwarf_section *section, int is_eh = strcmp (section->name, ".eh_frame") == 0; unsigned int length_return; int max_regs = 0; + const char *bad_reg = _("bad register: "); printf (_("Contents of the %s section:\n"), section->name); @@ -4089,12 +4098,12 @@ display_debug_frames (struct dwarf_section *section, 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; @@ -4111,28 +4120,29 @@ display_debug_frames (struct dwarf_section *section, 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 (); @@ -4152,14 +4162,14 @@ display_debug_frames (struct dwarf_section *section, 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 (); @@ -4175,9 +4185,9 @@ display_debug_frames (struct dwarf_section *section, 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; } @@ -4194,6 +4204,7 @@ display_debug_frames (struct dwarf_section *section, unsigned long ul, reg, roffs; long l, ofs; dwarf_vma vma; + const char *reg_prefix = ""; op = *start++; opa = op & 0x3f; @@ -4216,18 +4227,31 @@ display_debug_frames (struct dwarf_section *section, 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: @@ -4278,59 +4302,94 @@ display_debug_frames (struct dwarf_section *section, 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: @@ -4409,53 +4468,69 @@ display_debug_frames (struct dwarf_section *section, 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, 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)); + 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: @@ -4500,12 +4575,17 @@ display_debug_frames (struct dwarf_section *section, 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: |