From 099c8b17ace8e7a35a53993bf8cf211b955d29a8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 5 Jun 2001 18:57:49 -0700 Subject: [PATCH] dwarf2.h (DW_EH_PE_aligned): New. * 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. From-SVN: r42926 --- gcc/ChangeLog | 21 +++++- gcc/config/alpha/elf.h | 2 - gcc/config/alpha/osf.h | 14 ++++ gcc/dwarf2.h | 1 + gcc/dwarf2asm.c | 7 ++ gcc/dwarf2out.c | 48 +++++++++++- gcc/unwind-dw2-fde.c | 8 +- gcc/unwind-pe.h | 161 ++++++++++++++++++++++------------------- 8 files changed, 179 insertions(+), 83 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5c342bdd316..0dc127dad57 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2001-06-05 Richard Henderson + + * 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. + 2001-06-05 David O'Brien * config.gcc, config/i386/bsd386.h: Do not directly include @@ -327,7 +344,7 @@ Sat Jun 2 06:53:50 2001 Richard Kenner * README: Update references to installation instructions. 2001-06-01 Laurent Guerby - Gerald Pfeifer + Gerald Pfeifer * doc/install.texi: Define srcdir when sources come from CVS. Significantly improve markup. Wrap overly long lines @@ -481,7 +498,7 @@ Thu May 31 19:09:53 CEST 2001 Jan Hubicka 2001-05-27 Kaveh R. Ghazi - * fixinc/fixtests.c: Declare entries in ENV_TABLE. + * fixinc/fixtests.c: Declare entries in ENV_TABLE. 2001-05-27 Bruce Korb diff --git a/gcc/config/alpha/elf.h b/gcc/config/alpha/elf.h index fd0874eee94..78642e678df 100644 --- a/gcc/config/alpha/elf.h +++ b/gcc/config/alpha/elf.h @@ -686,8 +686,6 @@ void FN () \ #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. diff --git a/gcc/config/alpha/osf.h b/gcc/config/alpha/osf.h index 1d1109b3c2f..b6e80d02bbf 100644 --- a/gcc/config/alpha/osf.h +++ b/gcc/config/alpha/osf.h @@ -153,3 +153,17 @@ __enable_execute_stack (addr) \ #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) diff --git a/gcc/dwarf2.h b/gcc/dwarf2.h index e6148a36766..800bda2dc01 100644 --- a/gcc/dwarf2.h +++ b/gcc/dwarf2.h @@ -580,5 +580,6 @@ enum dwarf_macinfo_record_type #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 diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c index 98b557202a8..15ae68dd212 100644 --- a/gcc/dwarf2asm.c +++ b/gcc/dwarf2asm.c @@ -490,6 +490,7 @@ eh_data_format_name (format) 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") @@ -947,6 +948,12 @@ dw2_asm_output_encoded_addr_rtx VPARAMS ((int encoding, 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) assemble_integer (addr, size, 1); diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index d72ecc2c347..5d561840e6a 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -1820,6 +1820,28 @@ output_call_frame_info (for_eh) 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"); @@ -1909,8 +1931,22 @@ output_call_frame_info (for_eh) { if (any_lsda_needed) { - dw2_asm_output_data_uleb128 ( - size_of_encoded_value (lsda_encoding), "Augmentation size"); + 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) { @@ -1921,8 +1957,12 @@ output_call_frame_info (for_eh) "Language Specific Data Area"); } else - dw2_asm_output_data (size_of_encoded_value (lsda_encoding), - 0, "Language Specific Data Area (none)"); + { + 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"); diff --git a/gcc/unwind-dw2-fde.c b/gcc/unwind-dw2-fde.c index c486f50b176..6da2c7384fd 100644 --- a/gcc/unwind-dw2-fde.c +++ b/gcc/unwind-dw2-fde.c @@ -233,6 +233,7 @@ base_from_object (unsigned char encoding, struct object *ob) { case DW_EH_PE_absptr: case DW_EH_PE_pcrel: + case DW_EH_PE_aligned: return 0; case DW_EH_PE_textrel: @@ -270,7 +271,12 @@ get_cie_encoding (struct dwarf_cie *cie) return *p; /* Personality encoding and pointer. */ else if (*aug == 'P') - p = read_encoded_value_with_base (*p & 0xF, 0, p + 1, &dummy); + { + /* ??? 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++; diff --git a/gcc/unwind-pe.h b/gcc/unwind-pe.h index 264aa1821d8..e952b7f83e4 100644 --- a/gcc/unwind-pe.h +++ b/gcc/unwind-pe.h @@ -40,12 +40,13 @@ #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 + This is only defined for fixed-size encodings, and so does not include leb128. */ static unsigned int @@ -69,7 +70,7 @@ size_of_encoded_value (unsigned char encoding) } /* Given an encoding and an _Unwind_Context, return the base to which - the encoding is relative. This base may then be passed to + 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. */ @@ -83,6 +84,7 @@ base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context) { case DW_EH_PE_absptr: case DW_EH_PE_pcrel: + case DW_EH_PE_aligned: return 0; case DW_EH_PE_textrel: @@ -117,83 +119,94 @@ read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base, union unaligned *u = (union unaligned *) p; _Unwind_Ptr result; - switch (encoding & 0x0f) + if (encoding == DW_EH_PE_aligned) { - 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 + _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: { - byte = *p++; - result |= (_Unwind_Ptr)(byte & 0x7f) << shift; - shift += 7; + unsigned int shift = 0; + unsigned char byte; + + result = 0; + do + { + byte = *p++; + result |= (_Unwind_Ptr)(byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); } - while (byte & 0x80); - } - break; - - case DW_EH_PE_sleb128: - { - unsigned int shift = 0; - unsigned char byte; + break; - result = 0; - do + case DW_EH_PE_sleb128: { - byte = *p++; - result |= (_Unwind_Ptr)(byte & 0x7f) << shift; - shift += 7; + 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); } - 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; + 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; @@ -207,7 +220,7 @@ static inline const unsigned char * read_encoded_value (struct _Unwind_Context *context, unsigned char encoding, const unsigned char *p, _Unwind_Ptr *val) { - return read_encoded_value_with_base (encoding, + return read_encoded_value_with_base (encoding, base_of_encoded_value (encoding, context), p, val); } -- 2.30.2