This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


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

eh info and unaligned dynamic relocations


I've committed the following in order to solve problems with some
systems that (1) don't have relocations appropriate to eliminating
dynamic relocations in the exception info entirely and (2) whose
dynamic linkers don't handle unaligned reloactions.

In particular, Tru64, but I suspect that Irix and perhaps HPUX is
in the same boat.  Would folks with these systems find out if you're
getting unaligned access faults, possibly fixed up by the kernel?

This patch extends the unwind info ABI by adding a new format code.


r~


        * dwarf2.h (DW_EH_PE_aligned): New.
        * dwarf2asm.c (eh_data_format_name): Name it.
        (dw2_asm_output_encoded_addr_rtx): Align for it.
        * dwarf2out.c (output_call_frame_info): Handle it for personality
        routine and LSDA pointers.

        * unwind-pe.h (DW_EH_PE_aligned): New.
        (base_of_encoded_value): Handle it.
        (read_encoded_value_with_base): Likewise.
        * unwind-dw2-fde.c (base_from_object): Likewise.
        (get_cie_encoding): Likewise.

        * config/alpha/elf.h: Remove ecoff commentary.
        * config/alpha/osf.h (ASM_PREFERRED_EH_DATA_FORMAT): New.

Index: gcc/dwarf2.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2.h,v
retrieving revision 1.16.6.1
diff -c -p -d -r1.16.6.1 dwarf2.h
*** dwarf2.h	2001/05/13 07:09:52	1.16.6.1
--- dwarf2.h	2001/06/05 20:59:38
*************** enum dwarf_macinfo_record_type
*** 580,584 ****
--- 580,585 ----
  #define DW_EH_PE_textrel	0x20
  #define DW_EH_PE_datarel	0x30
  #define DW_EH_PE_funcrel	0x40
+ #define DW_EH_PE_aligned	0x50
  
  #define DW_EH_PE_indirect	0x80
Index: gcc/dwarf2asm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2asm.c,v
retrieving revision 1.6.2.3
diff -c -p -d -r1.6.2.3 dwarf2asm.c
*** dwarf2asm.c	2001/05/16 22:44:50	1.6.2.3
--- dwarf2asm.c	2001/06/05 20:59:38
*************** eh_data_format_name (format)
*** 490,495 ****
--- 490,496 ----
  
    S(DW_EH_PE_absptr, "absolute")
    S(DW_EH_PE_omit, "omit")
+   S(DW_EH_PE_aligned, "aligned absolute")
  
    S(DW_EH_PE_uleb128, "uleb128")
    S(DW_EH_PE_udata2, "udata2")
*************** dw2_asm_output_encoded_addr_rtx VPARAMS 
*** 946,951 ****
--- 947,958 ----
  #endif
  
    size = size_of_encoded_value (encoding);
+ 
+   if (encoding == DW_EH_PE_aligned)
+     {
+       assemble_align (POINTER_SIZE);
+       encoding = DW_EH_PE_absptr;
+     }
  
    /* NULL is _always_ represented as a plain zero.  */
    if (addr == const0_rtx)
Index: gcc/dwarf2out.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2out.c,v
retrieving revision 1.242.2.19
diff -c -p -d -r1.242.2.19 dwarf2out.c
*** dwarf2out.c	2001/05/31 01:12:56	1.242.2.19
--- dwarf2out.c	2001/06/05 20:59:39
*************** output_call_frame_info (for_eh)
*** 1820,1825 ****
--- 1820,1847 ----
  	  augmentation[0] = 'z';
            *p = '\0';
  	}
+ 
+       /* Ug.  Some platforms can't do unaligned dynamic relocations at all.  */
+       if (eh_personality_libfunc && per_encoding == DW_EH_PE_aligned)
+ 	{
+ 	  int offset = (  4		/* Length */
+ 			+ 4		/* CIE Id */
+ 			+ 1		/* CIE version */
+ 			+ strlen (augmentation) + 1	/* Augmentation */
+ 			+ size_of_uleb128 (1)		/* Code alignment */
+ 			+ size_of_sleb128 (DWARF_CIE_DATA_ALIGNMENT)
+ 			+ 1		/* RA column */
+ 			+ 1		/* Augmentation size */
+ 			+ 1		/* Personality encoding */ );
+ 	  int pad = -offset & (PTR_SIZE - 1);
+ 
+ 	  augmentation_size += pad;
+ 
+ 	  /* Augmentations should be small, so there's scarce need to
+ 	     iterate for a solution.  Die if we exceed one uleb128 byte.  */
+ 	  if (size_of_uleb128 (augmentation_size) != 1)
+ 	    abort ();
+ 	}
      }
    dw2_asm_output_nstring (augmentation, -1, "CIE Augmentation");
  
*************** output_call_frame_info (for_eh)
*** 1909,1916 ****
  	{
  	  if (any_lsda_needed)
  	    {
! 	      dw2_asm_output_data_uleb128 (
! 		size_of_encoded_value (lsda_encoding), "Augmentation size");
  
  	      if (fde->uses_eh_lsda)
  	        {
--- 1931,1952 ----
  	{
  	  if (any_lsda_needed)
  	    {
! 	      int size = size_of_encoded_value (lsda_encoding);
! 
! 	      if (lsda_encoding == DW_EH_PE_aligned)
! 		{
! 		  int offset = (  4		/* Length */
! 				+ 4		/* CIE offset */
! 				+ 2 * size_of_encoded_value (fde_encoding)
! 				+ 1		/* Augmentation size */ );
! 		  int pad = -offset & (PTR_SIZE - 1);
! 
! 		  size += pad;
! 		  if (size_of_uleb128 (size) != 1)
! 		    abort ();
! 		}
! 
! 	      dw2_asm_output_data_uleb128 (size, "Augmentation size");
  
  	      if (fde->uses_eh_lsda)
  	        {
*************** output_call_frame_info (for_eh)
*** 1921,1928 ****
  		 	"Language Specific Data Area");
  	        }
  	      else
! 	        dw2_asm_output_data (size_of_encoded_value (lsda_encoding),
! 				     0, "Language Specific Data Area (none)");
  	    }
  	  else
  	    dw2_asm_output_data_uleb128 (0, "Augmentation size");
--- 1957,1968 ----
  		 	"Language Specific Data Area");
  	        }
  	      else
! 		{
! 		  if (lsda_encoding == DW_EH_PE_aligned)
! 		    ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
! 		  dw2_asm_output_data (size_of_encoded_value (lsda_encoding),
! 				       0, "Language Specific Data Area (none)");
! 		}
  	    }
  	  else
  	    dw2_asm_output_data_uleb128 (0, "Augmentation size");
Index: gcc/unwind-dw2-fde.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/unwind-dw2-fde.c,v
retrieving revision 1.2.2.4
diff -c -p -d -r1.2.2.4 unwind-dw2-fde.c
*** unwind-dw2-fde.c	2001/05/23 01:26:59	1.2.2.4
--- unwind-dw2-fde.c	2001/06/05 20:59:39
*************** base_from_object (unsigned char encoding
*** 233,238 ****
--- 233,239 ----
      {
      case DW_EH_PE_absptr:
      case DW_EH_PE_pcrel:
+     case DW_EH_PE_aligned:
        return 0;
  
      case DW_EH_PE_textrel:
*************** get_cie_encoding (struct dwarf_cie *cie)
*** 270,276 ****
  	return *p;
        /* Personality encoding and pointer.  */
        else if (*aug == 'P')
! 	p = read_encoded_value_with_base (*p & 0xF, 0, p + 1, &dummy);
        /* LSDA encoding.  */
        else if (*aug == 'L')
  	p++;
--- 271,282 ----
  	return *p;
        /* Personality encoding and pointer.  */
        else if (*aug == 'P')
! 	{
! 	  /* ??? Avoid dereferencing indirect pointers, since we're
! 	     faking the base address.  Gotta keep DW_EH_PE_aligned
! 	     intact, however.  */
! 	  p = read_encoded_value_with_base (*p & 0x7F, 0, p + 1, &dummy);
! 	}
        /* LSDA encoding.  */
        else if (*aug == 'L')
  	p++;
Index: gcc/unwind-pe.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/unwind-pe.h,v
retrieving revision 1.2.2.2
diff -c -p -d -r1.2.2.2 unwind-pe.h
*** unwind-pe.h	2001/05/16 19:29:55	1.2.2.2
--- unwind-pe.h	2001/06/05 20:59:39
***************
*** 40,51 ****
  #define DW_EH_PE_textrel        0x20
  #define DW_EH_PE_datarel        0x30
  #define DW_EH_PE_funcrel        0x40
  
  #define DW_EH_PE_indirect	0x80
  
  
  /* Given an encoding, return the number of bytes the format occupies.
!    This is only defined for fixed-size encodings, and so does not 
     include leb128.  */
  
  static unsigned int
--- 40,52 ----
  #define DW_EH_PE_textrel        0x20
  #define DW_EH_PE_datarel        0x30
  #define DW_EH_PE_funcrel        0x40
+ #define DW_EH_PE_aligned        0x50
  
  #define DW_EH_PE_indirect	0x80
  
  
  /* Given an encoding, return the number of bytes the format occupies.
!    This is only defined for fixed-size encodings, and so does not
     include leb128.  */
  
  static unsigned int
*************** size_of_encoded_value (unsigned char enc
*** 69,75 ****
  }
  
  /* Given an encoding and an _Unwind_Context, return the base to which
!    the encoding is relative.  This base may then be passed to 
     read_encoded_value_with_base for use when the _Unwind_Context is
     not available.  */
  
--- 70,76 ----
  }
  
  /* Given an encoding and an _Unwind_Context, return the base to which
!    the encoding is relative.  This base may then be passed to
     read_encoded_value_with_base for use when the _Unwind_Context is
     not available.  */
  
*************** base_of_encoded_value (unsigned char enc
*** 83,88 ****
--- 84,90 ----
      {
      case DW_EH_PE_absptr:
      case DW_EH_PE_pcrel:
+     case DW_EH_PE_aligned:
        return 0;
  
      case DW_EH_PE_textrel:
*************** read_encoded_value_with_base (unsigned c
*** 117,199 ****
    union unaligned *u = (union unaligned *) p;
    _Unwind_Ptr result;
  
!   switch (encoding & 0x0f)
      {
!     case DW_EH_PE_absptr:
!       result = (_Unwind_Ptr) u->ptr;
!       p += sizeof (void *);
!       break;
! 
!     case DW_EH_PE_uleb128:
!       {
! 	unsigned int shift = 0;
! 	unsigned char byte;
  
! 	result = 0;
! 	do
  	  {
! 	    byte = *p++;
! 	    result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
! 	    shift += 7;
! 	  }
! 	while (byte & 0x80);
!       }
!       break;
  
!     case DW_EH_PE_sleb128:
!       {
! 	unsigned int shift = 0;
! 	unsigned char byte;
  
! 	result = 0;
! 	do
  	  {
! 	    byte = *p++;
! 	    result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
! 	    shift += 7;
! 	  }
! 	while (byte & 0x80);
  
! 	if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
! 	  result |= -(1L << shift);
!       }
!       break;
  
!     case DW_EH_PE_udata2:
!       result = u->u2;
!       p += 2;
!       break;
!     case DW_EH_PE_udata4:
!       result = u->u4;
!       p += 4;
!       break;
!     case DW_EH_PE_udata8:
!       result = u->u8;
!       p += 8;
!       break;
  
!     case DW_EH_PE_sdata2:
!       result = u->s2;
!       p += 2;
!       break;
!     case DW_EH_PE_sdata4:
!       result = u->s4;
!       p += 4;
!       break;
!     case DW_EH_PE_sdata8:
!       result = u->s8;
!       p += 8;
!       break;
  
!     default:
!       abort ();
!     }
  
!   if (result != 0)
!     {
!       result += ((encoding & 0x70) == DW_EH_PE_pcrel ? (_Unwind_Ptr)u : base);
!       if (encoding & DW_EH_PE_indirect)
! 	result = *(_Unwind_Ptr *)result;
      }
  
    *val = result;
--- 119,212 ----
    union unaligned *u = (union unaligned *) p;
    _Unwind_Ptr result;
  
!   if (encoding == DW_EH_PE_aligned)
      {
!       _Unwind_Ptr a = (_Unwind_Ptr)p;
!       a = (a + sizeof (void *) - 1) & - sizeof(void *);
!       result = *(_Unwind_Ptr *) a;
!       p = (const unsigned char *)(a + sizeof (void *));
!     }
!   else
!     {
!       switch (encoding & 0x0f)
! 	{
! 	case DW_EH_PE_absptr:
! 	  result = (_Unwind_Ptr) u->ptr;
! 	  p += sizeof (void *);
! 	  break;
  
! 	case DW_EH_PE_uleb128:
  	  {
! 	    unsigned int shift = 0;
! 	    unsigned char byte;
  
! 	    result = 0;
! 	    do
! 	      {
! 		byte = *p++;
! 		result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
! 		shift += 7;
! 	      }
! 	    while (byte & 0x80);
! 	  }
! 	  break;
  
! 	case DW_EH_PE_sleb128:
  	  {
! 	    unsigned int shift = 0;
! 	    unsigned char byte;
  
! 	    result = 0;
! 	    do
! 	      {
! 		byte = *p++;
! 		result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
! 		shift += 7;
! 	      }
! 	    while (byte & 0x80);
  
! 	    if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
! 	      result |= -(1L << shift);
! 	  }
! 	  break;
  
! 	case DW_EH_PE_udata2:
! 	  result = u->u2;
! 	  p += 2;
! 	  break;
! 	case DW_EH_PE_udata4:
! 	  result = u->u4;
! 	  p += 4;
! 	  break;
! 	case DW_EH_PE_udata8:
! 	  result = u->u8;
! 	  p += 8;
! 	  break;
  
! 	case DW_EH_PE_sdata2:
! 	  result = u->s2;
! 	  p += 2;
! 	  break;
! 	case DW_EH_PE_sdata4:
! 	  result = u->s4;
! 	  p += 4;
! 	  break;
! 	case DW_EH_PE_sdata8:
! 	  result = u->s8;
! 	  p += 8;
! 	  break;
  
! 	default:
! 	  abort ();
! 	}
! 
!       if (result != 0)
! 	{
! 	  result += ((encoding & 0x70) == DW_EH_PE_pcrel
! 		     ? (_Unwind_Ptr)u : base);
! 	  if (encoding & DW_EH_PE_indirect)
! 	    result = *(_Unwind_Ptr *)result;
! 	}
      }
  
    *val = result;
*************** static inline const unsigned char *
*** 207,213 ****
  read_encoded_value (struct _Unwind_Context *context, unsigned char encoding,
  		    const unsigned char *p, _Unwind_Ptr *val)
  {
!   return read_encoded_value_with_base (encoding, 
  		base_of_encoded_value (encoding, context),
  		p, val);
  }
--- 220,226 ----
  read_encoded_value (struct _Unwind_Context *context, unsigned char encoding,
  		    const unsigned char *p, _Unwind_Ptr *val)
  {
!   return read_encoded_value_with_base (encoding,
  		base_of_encoded_value (encoding, context),
  		p, val);
  }
Index: gcc/config/alpha/elf.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/elf.h,v
retrieving revision 1.35.4.2
diff -c -p -d -r1.35.4.2 elf.h
*** elf.h	2001/05/13 07:10:06	1.35.4.2
--- elf.h	2001/06/05 20:59:39
*************** void FN ()					\
*** 686,693 ****
  #undef UNALIGNED_INT_ASM_OP
  #undef UNALIGNED_DOUBLE_INT_ASM_OP
  
- /* ??? This should be possible for ECOFF as well, since the relocations
-    exist.  But the assembler doesn't seem to create them.  */
  /* Select a format to encode pointers in exception handling data.  CODE
     is 0 for data, 1 for code labels, 2 for function pointers.  GLOBAL is
     true if the symbol may be affected by dynamic relocations.
--- 686,691 ----
Index: gcc/config/alpha/osf.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/osf.h,v
retrieving revision 1.15
diff -c -p -d -r1.15 osf.h
*** osf.h	2001/01/13 12:34:02	1.15
--- osf.h	2001/06/05 20:59:39
*************** __enable_execute_stack (addr)						\
*** 153,155 ****
--- 153,169 ----
  #define HAS_INIT_SECTION
  #define LD_INIT_SWITCH "-init"
  #define LD_FINI_SWITCH "-fini"
+ 
+ /* Select a format to encode pointers in exception handling data.  CODE
+    is 0 for data, 1 for code labels, 2 for function pointers.  GLOBAL is
+    true if the symbol may be affected by dynamic relocations.
+    
+    We really ought to be using the SREL32 relocations that ECOFF has,
+    but no version of the native assembler supports creating such things,
+    and Compaq has no plans to rectify this.  Worse, the dynamic loader
+    cannot handle unaligned relocations, so we have to make sure that
+    things get padded appropriately.  */
+ #define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL)			     \
+   (TARGET_GAS								     \
+    ? (((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4) \
+    : DW_EH_PE_aligned)


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