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]

[RFC] Extend result of dwarf2-frame.c:read_encoded_value


Hi,

when I use a gdb configured with 64 bits bfd on a 32 bits target (on Darwin),
the FDE ranges are not correct:

* the initial_location is coded as pcrel + udata4.
* the udata4 value is negative (about 0xffff0000).

The final result was 0x00000001_0006e999.  As addresses are 32 bits, no
pc could be in the range.

My approach is simply to bit extend the result of the decoding before returning
it.

I'd like to know if this approach is correct and if so, if the patch is.

Tristan.

2008-12-05  Tristan Gingold  <gingold@adacore.com>

	* dwarf2-frame.c (read_encoded_value): Extend result from a word
	of ptr_len bytes to CORE_ADDR.


RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v
retrieving revision 1.86
diff -c -r1.86 dwarf2-frame.c
*** dwarf2-frame.c	5 Sep 2008 11:40:53 -0000	1.86
--- dwarf2-frame.c	5 Dec 2008 11:12:50 -0000
***************
*** 1371,1376 ****
--- 1371,1377 ----
  {
    ptrdiff_t offset;
    CORE_ADDR base;
+   CORE_ADDR res;
  
    /* GCC currently doesn't generate DW_EH_PE_indirect encodings for
       FDE's.  */
***************
*** 1425,1460 ****
  	ULONGEST value;
  	gdb_byte *end_buf = buf + (sizeof (value) + 1) * 8 / 7;
  	*bytes_read_ptr += read_uleb128 (buf, end_buf, &value) - buf;
! 	return base + value;
        }
      case DW_EH_PE_udata2:
        *bytes_read_ptr += 2;
!       return (base + bfd_get_16 (unit->abfd, (bfd_byte *) buf));
      case DW_EH_PE_udata4:
        *bytes_read_ptr += 4;
!       return (base + bfd_get_32 (unit->abfd, (bfd_byte *) buf));
      case DW_EH_PE_udata8:
        *bytes_read_ptr += 8;
!       return (base + bfd_get_64 (unit->abfd, (bfd_byte *) buf));
      case DW_EH_PE_sleb128:
        {
  	LONGEST value;
  	gdb_byte *end_buf = buf + (sizeof (value) + 1) * 8 / 7;
  	*bytes_read_ptr += read_sleb128 (buf, end_buf, &value) - buf;
! 	return base + value;
        }
      case DW_EH_PE_sdata2:
        *bytes_read_ptr += 2;
!       return (base + bfd_get_signed_16 (unit->abfd, (bfd_byte *) buf));
      case DW_EH_PE_sdata4:
        *bytes_read_ptr += 4;
!       return (base + bfd_get_signed_32 (unit->abfd, (bfd_byte *) buf));
      case DW_EH_PE_sdata8:
        *bytes_read_ptr += 8;
!       return (base + bfd_get_signed_64 (unit->abfd, (bfd_byte *) buf));
      default:
        internal_error (__FILE__, __LINE__, _("Invalid or unsupported encoding"));
      }
  }
  
  
--- 1426,1480 ----
  	ULONGEST value;
  	gdb_byte *end_buf = buf + (sizeof (value) + 1) * 8 / 7;
  	*bytes_read_ptr += read_uleb128 (buf, end_buf, &value) - buf;
! 	res = base + value;
        }
+       break;
      case DW_EH_PE_udata2:
        *bytes_read_ptr += 2;
!       res = base + bfd_get_16 (unit->abfd, (bfd_byte *) buf);
!       break;
      case DW_EH_PE_udata4:
        *bytes_read_ptr += 4;
!       res = base + bfd_get_32 (unit->abfd, (bfd_byte *) buf);
!       break;
      case DW_EH_PE_udata8:
        *bytes_read_ptr += 8;
!       res = base + bfd_get_64 (unit->abfd, (bfd_byte *) buf);
!       break;
      case DW_EH_PE_sleb128:
        {
  	LONGEST value;
  	gdb_byte *end_buf = buf + (sizeof (value) + 1) * 8 / 7;
  	*bytes_read_ptr += read_sleb128 (buf, end_buf, &value) - buf;
! 	res = base + value;
        }
+       break;
      case DW_EH_PE_sdata2:
        *bytes_read_ptr += 2;
!       res = base + bfd_get_signed_16 (unit->abfd, (bfd_byte *) buf);
!       break;
      case DW_EH_PE_sdata4:
        *bytes_read_ptr += 4;
!       res = base + bfd_get_signed_32 (unit->abfd, (bfd_byte *) buf);
!       break;
      case DW_EH_PE_sdata8:
        *bytes_read_ptr += 8;
!       res = base + bfd_get_signed_64 (unit->abfd, (bfd_byte *) buf);
!       break;
      default:
        internal_error (__FILE__, __LINE__, _("Invalid or unsupported encoding"));
      }
+ 
+   /* Set the bits that are beyond the address bits.  */
+   if (ptr_len < sizeof (CORE_ADDR))
+     {
+       CORE_ADDR mask = (((CORE_ADDR)1) << (8 * ptr_len)) - 1;
+       res &= mask;
+       if ((res & (((CORE_ADDR)1) << (8 * ptr_len - 1)))
+ 	  && bfd_get_sign_extend_vma (unit->abfd))
+ 	res |= ~mask;
+     }
+   return res;
  }
  
  


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