From 604282a73114a629e84ed6b81d0a22ed65c3d33e Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 5 Apr 2010 19:32:06 +0000 Subject: [PATCH] bfd/ * elf-eh-frame.c (_bfd_elf_parse_eh_frame): Handle CIE version 4 provided that it has the expected address size and zero segment length. binutils/ * dwarf.c (struct Frame_Chunk): Add ptr_size and segment_size fields. (display_debug_frames): Handle CIE version 4. --- bfd/ChangeLog | 4 +++ bfd/elf-eh-frame.c | 13 ++++++-- binutils/ChangeLog | 4 +++ binutils/dwarf.c | 91 ++++++++++++++++++++++++++++++------------------------ 4 files changed, 70 insertions(+), 42 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 33139c3..95f411e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,9 @@ 2010-04-05 Jakub Jelinek + * elf-eh-frame.c (_bfd_elf_parse_eh_frame): Handle CIE version 4 + provided that it has the expected address size and zero segment + length. + * dwarf2.c (struct line_head): Add maximum_ops_per_insn field. (struct line_info): Add op_index field, change end_sequence type to unsigned char. diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c index 37c9255..c948df2 100644 --- a/bfd/elf-eh-frame.c +++ b/bfd/elf-eh-frame.c @@ -1,5 +1,5 @@ /* .eh_frame section optimization. - Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Written by Jakub Jelinek . @@ -636,7 +636,9 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info, REQUIRE (read_byte (&buf, end, &cie->version)); /* Cannot handle unknown versions. */ - REQUIRE (cie->version == 1 || cie->version == 3); + REQUIRE (cie->version == 1 + || cie->version == 3 + || cie->version == 4); REQUIRE (strlen ((char *) buf) < sizeof (cie->augmentation)); strcpy (cie->augmentation, (char *) buf); @@ -651,6 +653,13 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info, REQUIRE (skip_bytes (&buf, end, ptr_size)); SKIP_RELOCS (buf); } + if (cie->version >= 4) + { + REQUIRE (buf + 1 < end); + REQUIRE (buf[0] == ptr_size); + REQUIRE (buf[1] == 0); + buf += 2; + } REQUIRE (read_uleb128 (&buf, end, &cie->code_align)); REQUIRE (read_sleb128 (&buf, end, &cie->data_align)); if (cie->version == 1) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 385586b..999760d 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,5 +1,9 @@ 2010-04-05 Jakub Jelinek + * dwarf.c (struct Frame_Chunk): Add ptr_size and segment_size + fields. + (display_debug_frames): Handle CIE version 4. + * dwarf.c (struct State_Machine_Registers): Add op_index field, change end_sequence type to unsigned char. (reset_state_machine): Clear op_index. diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 6e49cac..094fd27 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -3906,6 +3906,8 @@ typedef struct Frame_Chunk int ra; unsigned char fde_encoding; unsigned char cfa_exp; + unsigned char ptr_size; + unsigned char segment_size; } Frame_Chunk; @@ -4114,6 +4116,7 @@ display_debug_frames (struct dwarf_section *section, unsigned int length_return; int max_regs = 0; const char *bad_reg = _("bad register: "); + int saved_eh_addr_size = eh_addr_size; printf (_("Contents of the %s section:\n"), section->name); @@ -4128,7 +4131,7 @@ display_debug_frames (struct dwarf_section *section, int need_col_headers = 1; unsigned char *augmentation_data = NULL; unsigned long augmentation_data_len = 0; - int encoded_ptr_size = eh_addr_size; + int encoded_ptr_size = saved_eh_addr_size; int offset_size; int initial_length_size; @@ -4184,48 +4187,36 @@ display_debug_frames (struct dwarf_section *section, fc->augmentation = (char *) start; start = (unsigned char *) strchr ((char *) start, '\0') + 1; - if (fc->augmentation[0] == 'z') + if (strcmp (fc->augmentation, "eh") == 0) + start += eh_addr_size; + + if (version >= 4) { - fc->code_factor = LEB (); - fc->data_factor = SLEB (); - if (version == 1) - { - fc->ra = GET (1); - } - else - { - fc->ra = LEB (); - } - augmentation_data_len = LEB (); - augmentation_data = start; - start += augmentation_data_len; + fc->ptr_size = GET (1); + fc->segment_size = GET (1); + eh_addr_size = fc->ptr_size; } - else if (strcmp (fc->augmentation, "eh") == 0) + else { - start += eh_addr_size; - fc->code_factor = LEB (); - fc->data_factor = SLEB (); - if (version == 1) - { - fc->ra = GET (1); - } - else - { - fc->ra = LEB (); - } + fc->ptr_size = eh_addr_size; + fc->segment_size = 0; + } + fc->code_factor = LEB (); + fc->data_factor = SLEB (); + if (version == 1) + { + fc->ra = GET (1); } else { - fc->code_factor = LEB (); - fc->data_factor = SLEB (); - if (version == 1) - { - fc->ra = GET (1); - } - else - { - fc->ra = LEB (); - } + fc->ra = LEB (); + } + + if (fc->augmentation[0] == 'z') + { + augmentation_data_len = LEB (); + augmentation_data = start; + start += augmentation_data_len; } cie = fc; @@ -4240,6 +4231,11 @@ display_debug_frames (struct dwarf_section *section, (unsigned long)(saved_start - section_start), length, cie_id); printf (" Version: %d\n", version); printf (" Augmentation: \"%s\"\n", fc->augmentation); + if (version >= 4) + { + printf (" Pointer Size: %u\n", fc->ptr_size); + printf (" Segment Size: %u\n", fc->segment_size); + } 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); @@ -4286,6 +4282,7 @@ display_debug_frames (struct dwarf_section *section, { unsigned char *look_for; static Frame_Chunk fde_fc; + unsigned long segment_selector; fc = & fde_fc; memset (fc, 0, sizeof (Frame_Chunk)); @@ -4307,6 +4304,8 @@ display_debug_frames (struct dwarf_section *section, cie = fc; fc->augmentation = ""; fc->fde_encoding = 0; + fc->ptr_size = eh_addr_size; + fc->segment_size = 0; } else { @@ -4316,6 +4315,9 @@ display_debug_frames (struct dwarf_section *section, memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int)); memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int)); fc->augmentation = cie->augmentation; + fc->ptr_size = cie->ptr_size; + eh_addr_size = cie->ptr_size; + fc->segment_size = cie->segment_size; fc->code_factor = cie->code_factor; fc->data_factor = cie->data_factor; fc->cfa_reg = cie->cfa_reg; @@ -4328,6 +4330,12 @@ display_debug_frames (struct dwarf_section *section, if (fc->fde_encoding) encoded_ptr_size = size_of_encoded_value (fc->fde_encoding); + segment_selector = 0; + if (fc->segment_size) + { + segment_selector = byte_get (start, fc->segment_size); + start += fc->segment_size; + } fc->pc_begin = get_encoded_value (start, fc->fde_encoding); if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel) fc->pc_begin += section->address + (start - section_start); @@ -4342,10 +4350,12 @@ display_debug_frames (struct dwarf_section *section, start += augmentation_data_len; } - printf ("\n%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n", + printf ("\n%08lx %08lx %08lx FDE cie=%08lx pc=", (unsigned long)(saved_start - section_start), length, cie_id, - (unsigned long)(cie->chunk_start - section_start), - fc->pc_begin, fc->pc_begin + fc->pc_range); + (unsigned long)(cie->chunk_start - section_start)); + if (fc->segment_size) + printf ("%04lx:", segment_selector); + printf ("%08lx..%08lx\n", fc->pc_begin, fc->pc_begin + fc->pc_range); if (! do_debug_frames_interp && augmentation_data_len) { unsigned long i; @@ -4893,6 +4903,7 @@ display_debug_frames (struct dwarf_section *section, frame_display_row (fc, &need_col_headers, &max_regs); start = block_end; + eh_addr_size = saved_eh_addr_size; } printf ("\n"); -- 2.7.4