This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Handle DWARF4 .debug_frame (and .eh_frame)


Hi!

DWARF4 not only adds a field into the middle of .debug_line header,
but also adds two new fields into the middle of CIE.  While I don't expect
GCC (nor gas) to emit version 4 CIEs any time soon, the following
patch should handle it.

Ok to commit?

2010-04-02  Jakub Jelinek  <jakub@redhat.com>

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/elf-eh-frame.c.jj	2009-12-11 14:42:02.000000000 +0100
+++ bfd/elf-eh-frame.c	2010-04-02 10:33:08.000000000 +0200
@@ -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 <jakub@redhat.com>.
 
@@ -636,7 +636,9 @@ _bfd_elf_parse_eh_frame (bfd *abfd, stru
 	  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, stru
 	      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)
--- binutils/dwarf.c.jj	2010-04-01 14:26:40.000000000 +0200
+++ binutils/dwarf.c	2010-04-02 11:04:46.000000000 +0200
@@ -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_secti
   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_secti
       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_secti
 	  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_secti
 		      (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_secti
 	{
 	  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_secti
 	      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_secti
 	      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_secti
 	  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_secti
 	      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_secti
 	frame_display_row (fc, &need_col_headers, &max_regs);
 
       start = block_end;
+      eh_addr_size = saved_eh_addr_size;
     }
 
   printf ("\n");

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]