This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
eh info and unaligned dynamic relocations
- To: gcc-patches at gcc dot gnu dot org
- Subject: eh info and unaligned dynamic relocations
- From: Richard Henderson <rth at redhat dot com>
- Date: Tue, 5 Jun 2001 14:21:10 -0700
- Cc: mark at codesourcery dot com, oldham at codesourcery dot com, "Jeffrey A. Law" <law at redhat dot com>
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)