Hi,

because of popular demand we switched the Ada compiler to ZCX, i.e. table-
driven EH scheme, on ARM/Linux, only to discover that GCC doesn't generate 
correct EH tables, which means that the Ada compiler cannot catch exceptions.

See also the earlier message posted by Tristan:
  http://gcc.gnu.org/ml/gcc/2013-12/msg00157.html

The problem is the discrepancy between the declared encoding and the actual 
encoding of the TType.  The latter is specified by the EABI: symbols must be 
relocated with an R_ARM_TARGET2 relocation, as visible in the assembly:

.LLSDACSE0:
        .byte   0x1     @ Action record table
        .byte   0
        .align  2
        .word   _ZTIi(TARGET2)

R_ARM_TARGET2 means DW_EH_PE_pcrel | DW_EH_PE_indirect in DWARF parlance on 
Linux, but the declared TType encoding is different:

.LLSDA0:
        .byte   0xff    @ @LPStart format (omit)
        .byte   0       @ @TType format (absolute)
        .uleb128 .LLSDATT0-.LLSDATTD0   @ @TType base offset

i.e. it's the DW_EH_PE_absptr default.

This works in C++ because of the _GLIBCXX_OVERRIDE_TTYPE_ENCODING kludge, 
which overrides the declared encoding during the parsing of the EH table:

  // Find @TType, the base of the handler and exception spec type data.
  info->ttype_encoding = *p++;
  if (info->ttype_encoding != DW_EH_PE_omit)
    {
#if _GLIBCXX_OVERRIDE_TTYPE_ENCODING
      /* Older ARM EABI toolchains set this value incorrectly, so use a
         hardcoded OS-specific format.  */
      info->ttype_encoding = _GLIBCXX_OVERRIDE_TTYPE_ENCODING;
#endif
      p = read_uleb128 (p, &tmp);
      info->TType = p + tmp;
    }
  else
    info->TType = 0;

This comes from http://gcc.gnu.org/ml/gcc-patches/2011-09/msg00765.html

Note that the above comment suggests that Paul's intent was to fix the bogus 
declared encoding in newer toolchains, but he didn't because of a misplaced 
#endif as spotted by Tristan.  Hence the attached patch, which aligns the 
declared encoding with the actual encoding and yields the correct:

.LLSDA0:
        .byte   0xff    @ @LPStart format (omit)
        .byte   0x90    @ @TType format (indirect pcrel)
        .uleb128 .LLSDATT0-.LLSDATTD0   @ @TType base offset

which fixes the Ada failures in the process.  It was kindly tested by Bernd 
Edlinger on armv7l-unknown-linux-gnueabihf (all languages) with no regressions 
so we would like to have it for 4.9.x.


2014-04-25  Douglas B Rupp  <r...@adacore.com>

        PR target/60504
        * config/arm/arm.h (ASM_PREFERRED_EH_DATA_FORMAT): Expose from
        ARM_TARGET2_DWARF_FORMAT.



2014-04-25  Eric Botcazou  <ebotca...@adacore.com>

        * gnat.dg/test_raise_from_pure.adb: UnXFAIL for ARM.


-- 
Eric Botcazou
extern void foo ();

int bar ()
{
  try {
    foo ();
  }
  catch (int) {
    return 1;
  }

  return 0;
}
Index: config/arm/arm.h
===================================================================
--- config/arm/arm.h	(revision 208763)
+++ config/arm/arm.h	(working copy)
@@ -937,13 +937,13 @@ extern int arm_arch_crc;
 
 #ifndef ARM_TARGET2_DWARF_FORMAT
 #define ARM_TARGET2_DWARF_FORMAT DW_EH_PE_pcrel
+#endif
 
 /* ttype entries (the only interesting data references used)
    use TARGET2 relocations.  */
 #define ASM_PREFERRED_EH_DATA_FORMAT(code, data) \
   (((code) == 0 && (data) == 1 && ARM_UNWIND_INFO) ? ARM_TARGET2_DWARF_FORMAT \
 			       : DW_EH_PE_absptr)
-#endif
 
 /* The native (Norcroft) Pascal compiler for the ARM passes the static chain
    as an invisible last argument (possible since varargs don't exist in
Index: testsuite/gnat.dg/test_raise_from_pure.adb
===================================================================
--- testsuite/gnat.dg/test_raise_from_pure.adb	(revision 208763)
+++ testsuite/gnat.dg/test_raise_from_pure.adb	(working copy)
@@ -1,4 +1,4 @@
--- { dg-do run { xfail arm*-*-* } }
+-- { dg-do run }
 -- { dg-options "-O2" }
 
 -- This is an optimization test and its failure is only a missed optimization.

Reply via email to