This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB 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]

[rfa] frame address size incorrect if address size != ptr size


Hi,

while analyzing some problem in XStormy16, I came across a weird effect.
Even though the dwarf2 frame unwinder is suppose to be preferred over
the xstormy16 unwinder, the code almost always called the
xstormy16_frame_prev_register function, rather than the
dwarf2_frame_prev_register function.

Debugging turned up that the "address_range" entry in almost all fde's
was incorrect, so the dwarf2_frame_find_fde function almost never found
a matching fde.

More debugging then pointed to the decode_frame_entry_1 function.  The
storage size of address_range is supposed to be cie->addr_size.

cie->addr_size is computed like this:

  /* The target address size.  For .eh_frame FDEs this is considered
     equal to the size of a target pointer.  For .dwarf_frame FDEs, 
     this is supposed to be the target address size from the associated
     CU header.  FIXME: We do not have a good way to determine the 
     latter.  Always use the target pointer size for now.  */
  cie->addr_size = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;

  [...]

  if (cie->version >= 4)
    {
      /* FIXME: check that this is the same as from the CU header.  */
      cie->addr_size = read_1_byte (unit->abfd, buf);
      ++buf;
      cie->segment_size = read_1_byte (unit->abfd, buf);
      ++buf;
    }
  else
    {
      cie->addr_size = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;
      cie->segment_size = 0;
    }
		  
This is not helpful for .dwarf_frame sections in case cie->version < 4.

The address size of a target is not necessarily the size of a pointer.
And that's exactly the problem in the XStormy16 case.  The target is
very size sensitive.  The address range of the CPU is potentially 32
bit, so the address size for the target is 32 bit.  However, the
pointer size for this target is deliberately set to 16 bit, which
allows for smaller code, and also pointers fit into a single 16 bit
register.

The effect is that the above statements set cie->addr_size to 2, because
that's the size of a pointer.  But the address size is 4 byte and the
debug info has to use the address size to be able to cover the entire
address space of the target.  Consequentially GCC emits debug info
using the address size of the XStormy16 target, 4 bytes.

Therefore I propose the below patch.  It continues to compute addr_size
from gdbarch_ptr_bit for .eh_frame sections, but uses gdbarch_addr_bit
in case of .dwarf_frame sections.

Tested with XStormy16.  Now the dwarf2 unwinder is actually preferred over
the "manual" xstormy16 unwinder, because the dwarf2_frame_find_fde
function actually finds matching FDEs now.

Ok to apply?

Thanks,
Corinna


	* dwarf2-frame.c (decode_frame_entry_1): If addr_size isn't available
	in CIE, use address size rather than pointer size when decoding
	.dwarf_frame info.


Index: dwarf2-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v
retrieving revision 1.114
diff -u -p -r1.114 dwarf2-frame.c
--- dwarf2-frame.c	7 Jul 2010 17:26:38 -0000	1.114
+++ dwarf2-frame.c	26 Jul 2010 14:49:34 -0000
@@ -1736,8 +1736,12 @@ decode_frame_entry_1 (struct comp_unit *
 	 equal to the size of a target pointer.  For .dwarf_frame FDEs, 
 	 this is supposed to be the target address size from the associated
 	 CU header.  FIXME: We do not have a good way to determine the 
-	 latter.  Always use the target pointer size for now.  */
-      cie->addr_size = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;
+	 latter.  Always use the target address size for .dwarf_frame
+	 sections for now.  */
+      if (eh_frame_p)
+	cie->addr_size = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;
+      else
+	cie->addr_size = gdbarch_addr_bit (gdbarch) / TARGET_CHAR_BIT;
 
       /* We'll determine the final value later, but we need to
 	 initialize it conservatively.  */
@@ -1779,7 +1783,10 @@ decode_frame_entry_1 (struct comp_unit *
 	}
       else
 	{
-	  cie->addr_size = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;
+	  if (eh_frame_p)
+	    cie->addr_size = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;
+	  else
+	    cie->addr_size = gdbarch_addr_bit (gdbarch) / TARGET_CHAR_BIT;
 	  cie->segment_size = 0;
 	}
 


-- 
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat


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