PATCH: dwarf2 EH for Darwin, revised

Stan Shebs shebs@apple.com
Thu Sep 12 09:38:00 GMT 2002


Here is the all-singing all-dancing version of the Darwin EH bits
that takes jason and rth comments into account, adding a target hook
for zero-termination of frame info, but leaving the dwarf2asm macros
to be hookified later.  Bootstrapped and tested on powerpc-apple-darwin
and i686-pc-linux, no regressions.

OK for trunk now?

Stan

2002-09-09  Stan Shebs  <shebs@apple.com>

    * target.h (struct gcc_target): New field
    terminate_dw2_eh_frame_info.
    * target-def.h (TARGET_TERMINATE_DW2_EH_FRAME_INFO): Define.
    (TARGET_INITIALIZER): Add it.
    * dwarf2out.c (output_call_frame_info): Use target hook.
    * dwarf2asm.c (dw2_asm_output_delta): Use macro
    ASM_OUTPUT_DWARF_DELTA if defined.
    * doc/tm.texi (TARGET_TERMINATE_DW2_EH_FRAME_INFO): Document.
    (ASM_OUTPUT_DWARF_DELTA): Ditto.
    (ASM_OUTPUT_DWARF_OFFSET): Ditto.
    (ASM_OUTPUT_DWARF_PCREL): Ditto.
    * config.gcc (i[34567]86-*-darwin*): Define extra_parts.
    (powerpc-*-darwin*): Ditto.
    * crtstuff.c [OBJECT_FORMAT_MACHO]: Update the Mach-O bits
    to work correctly for Darwin.
    * config/darwin.h (OBJECT_FORMAT_MACHO): Define.
    (STARTFILE_SPEC): Add crtbegin.o.
    (ENDFILE_SPEC): Define.
    (EXTRA_SECTION_FUNCTIONS): Put gcc_except_tab in data segment.
    (ASM_PREFERRED_EH_DATA_FORMAT): Handle more cases.
    (ASM_OUTPUT_DWARF_DELTA): Define.
    (TARGET_TERMINATE_DW2_EH_FRAME_INFO): Define.
    * config/darwin.c (darwin_asm_output_dwarf_delta): New function.

(patch also attached in case of mail manglement - first day with
Moz 1.1 on OS X)

Index: config.gcc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config.gcc,v
retrieving revision 1.244
diff -p -r1.244 config.gcc
*** config.gcc    3 Sep 2002 20:21:32 -0000    1.244
--- config.gcc    12 Sep 2002 13:01:05 -0000
*************** i[34567]86-*-darwin*)
*** 980,985 ****
--- 980,986 ----
      target_gtfiles="\$(srcdir)/config/darwin.c"
      c_target_objs="darwin-c.o"
      cxx_target_objs="darwin-c.o"
+     extra_parts="crtbegin.o crtend.o"
      # Darwin linker does collect2 functionality
      use_collect2=no
      ;;
*************** powerpc-*-darwin*)
*** 1946,1951 ****
--- 1947,1953 ----
      target_gtfiles="\$(srcdir)/config/darwin.c"
      c_target_objs="darwin-c.o"
      cxx_target_objs="darwin-c.o"
+     extra_parts="crtbegin.o crtend.o"
      # Darwin linker does collect2 functionality
      use_collect2=no
      extra_headers=altivec.h
Index: crtstuff.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/crtstuff.c,v
retrieving revision 1.56
diff -p -r1.56 crtstuff.c
*** crtstuff.c    4 Jun 2002 02:55:28 -0000    1.56
--- crtstuff.c    12 Sep 2002 13:01:06 -0000
*************** __do_global_ctors (void)
*** 545,608 ****
 
  #else  /* OBJECT_FORMAT_MACHO */
 
! /* For Mach-O format executables, we assume that the system's runtime is
!    smart enough to handle constructors and destructors, but doesn't have
!    an init section (if it can't even handle constructors/destructors
!    you should be using INVOKE__main, not crtstuff). All we need to do
!    is install/deinstall the frame information for exceptions. We do this
!    by putting a constructor in crtbegin.o and a destructor in crtend.o.
!
!    crtend.o also puts in the terminating zero in the frame information
!    segment.  */
!
! /* The crtstuff for other object formats use the symbol __EH_FRAME_BEGIN__
!    to figure out the start of the exception frame, but here we use
!    getsectbynamefromheader to find this value. Either method would work,
!    but this method avoids creating any global symbols, which seems
!    cleaner.  */
!
! #include <mach-o/ldsyms.h>
! extern const struct section *
!   getsectbynamefromheader (const struct mach_header *,
!                const char *, const char *);
 
  #ifdef CRT_BEGIN
 
! static void __reg_frame_ctor (void) __attribute__ ((constructor));
 
  static void
! __reg_frame_ctor (void)
  {
!   static struct object object;
!   const struct section *eh_frame;
!
!   eh_frame = getsectbynamefromheader (&_mh_execute_header,
!                       "__TEXT", "__eh_frame");
!   __register_frame_info ((void *) eh_frame->addr, &object);
! }
 
! #elif defined(CRT_END)
 
! static void __dereg_frame_dtor (void) __attribute__ ((destructor));
 
  static void
! __dereg_frame_dtor (void)
  {
!   const struct section *eh_frame;
 
!   eh_frame = getsectbynamefromheader (&_mh_execute_header,
!                       "__TEXT", "__eh_frame");
!   __deregister_frame_info ((void *) eh_frame->addr);
  }
 
! /* Terminate the frame section with a final zero.  */
! STATIC int __FRAME_END__[]
!      __attribute__ ((unused, mode(SI), section(EH_FRAME_SECTION_NAME),
!              aligned(4)))
!      = { 0 };
 
  #else /* ! CRT_BEGIN && ! CRT_END */
  #error "One of CRT_BEGIN or CRT_END must be defined."
  #endif
 
! #endif /* OBJECT_FORMAT_MACHO */
--- 545,624 ----
 
  #else  /* OBJECT_FORMAT_MACHO */
 
! /* Crt stuff for Mach-O (NeXT and Darwin).
!
!    The theory of this is that each dynamically-loadable module,
!    including the main program itself, must have been positioned by
!    dyld before any frame info can be registered.  So we set up the
!    registration functions as dyld hooks, using a "preregistration"
!    function that is called directly from the system crt1.o.  */
 
  #ifdef CRT_BEGIN
 
! /* Homemade decls substituting for getsect.h and dyld.h, so cross
!    compilation works.  */
! struct mach_header;
! extern char *getsectdatafromheader (struct mach_header *, const char *,
!                     const char *, unsigned long *);
! extern void _dyld_register_func_for_add_image
!   (void (*) (struct mach_header *, unsigned long));
! extern void _dyld_register_func_for_remove_image
!   (void (*) (struct mach_header *, unsigned long));
!
! extern void __darwin_gcc3_preregister_frame_info (void);
 
  static void
! unwind_dyld_add_image_hook (struct mach_header *mh,
!                 unsigned long vm_slide)
  {
!   unsigned long sz;
!   char *fde;
 
!   fde = getsectdatafromheader (mh, "__TEXT", "__eh_frame", &sz);
!   if (fde)
!     {
!       struct object *ob = (struct object *) malloc (sizeof (struct 
object));
 
!       __register_frame_info (fde + vm_slide, ob);
!     }
! }
 
  static void
! unwind_dyld_remove_image_hook (struct mach_header *mh,
!                    unsigned long vm_slide)
  {
!   unsigned long sz;
!   char *fde;
!
!   fde = getsectdatafromheader (mh, "__TEXT", "__eh_frame", &sz);
 
!   if (fde)
!     __deregister_frame_info (fde + vm_slide);
  }
 
! /* Call this routine from the system crt1.o.  The call is standard in
!    Darwin 6.x (Mac OS X 10.2) and later; for earlier systems, you
!    would need to modify crt.c in the Csu project.  (This isn't great,
!    but other alternatives run afoul of linker semantics.  This
!    function is declared as common and tested before being called, so
!    that programs compiled by older GCCs still link and run.)  */
!
! void
! __darwin_gcc3_preregister_frame_info ()
! {
!   _dyld_register_func_for_add_image (unwind_dyld_add_image_hook);
!   _dyld_register_func_for_remove_image (unwind_dyld_remove_image_hook);
! }
!
! #elif defined(CRT_END) /* ! CRT_BEGIN */
!
! /* Install a single zero word at the end of the __eh_frame section.  */
!
! asm (".section __TEXT,__eh_frame");
! asm (".long 0");
 
  #else /* ! CRT_BEGIN && ! CRT_END */
  #error "One of CRT_BEGIN or CRT_END must be defined."
  #endif
 
! #endif  /* OBJECT_FORMAT_MACHO  */
Index: dwarf2asm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2asm.c,v
retrieving revision 1.27
diff -p -r1.27 dwarf2asm.c
*** dwarf2asm.c    4 Jun 2002 07:07:22 -0000    1.27
--- dwarf2asm.c    12 Sep 2002 13:01:06 -0000
*************** dw2_asm_output_delta VPARAMS ((int size,
*** 104,114 ****
    VA_FIXEDARG (ap, const char *, lab2);
    VA_FIXEDARG (ap, const char *, comment);
 
    dw2_assemble_integer (size,
              gen_rtx_MINUS (Pmode,
                         gen_rtx_SYMBOL_REF (Pmode, lab1),
                         gen_rtx_SYMBOL_REF (Pmode, lab2)));
!
    if (flag_debug_asm && comment)
      {
        fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
--- 104,117 ----
    VA_FIXEDARG (ap, const char *, lab2);
    VA_FIXEDARG (ap, const char *, comment);
 
+ #ifdef ASM_OUTPUT_DWARF_DELTA
+   ASM_OUTPUT_DWARF_DELTA (asm_out_file, size, lab1, lab2);
+ #else
    dw2_assemble_integer (size,
              gen_rtx_MINUS (Pmode,
                         gen_rtx_SYMBOL_REF (Pmode, lab1),
                         gen_rtx_SYMBOL_REF (Pmode, lab2)));
! #endif
    if (flag_debug_asm && comment)
      {
        fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2out.c,v
retrieving revision 1.385
diff -p -r1.385 dwarf2out.c
*** dwarf2out.c    8 Sep 2002 18:36:53 -0000    1.385
--- dwarf2out.c    12 Sep 2002 13:01:12 -0000
*************** output_call_frame_info (for_eh)
*** 2043,2052 ****
        ASM_OUTPUT_LABEL (asm_out_file, l2);
      }
 
! #ifndef EH_FRAME_SECTION_NAME
!   if (for_eh)
      dw2_asm_output_data (4, 0, "End of Table");
- #endif
  #ifdef MIPS_DEBUGGING_INFO
    /* Work around Irix 6 assembler bug whereby labels at the end of a 
section
       get a value of 0.  Putting .align 0 after the label fixes it.  */
--- 2043,2050 ----
        ASM_OUTPUT_LABEL (asm_out_file, l2);
      }
 
!   if (for_eh && targetm.terminate_dw2_eh_frame_info)
      dw2_asm_output_data (4, 0, "End of Table");
  #ifdef MIPS_DEBUGGING_INFO
    /* Work around Irix 6 assembler bug whereby labels at the end of a 
section
       get a value of 0.  Putting .align 0 after the label fixes it.  */
Index: target-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target-def.h,v
retrieving revision 1.33
diff -p -r1.33 target-def.h
*** target-def.h    8 Sep 2002 09:30:20 -0000    1.33
--- target-def.h    12 Sep 2002 13:01:12 -0000
*************** Foundation, 59 Temple Place - Suite 330,
*** 126,131 ****
--- 126,139 ----
  #define TARGET_HAVE_SRODATA_SECTION false
  #endif
 
+ #ifndef TARGET_TERMINATE_DW2_EH_FRAME_INFO
+ #ifdef EH_FRAME_SECTION_NAME
+ #define TARGET_TERMINATE_DW2_EH_FRAME_INFO false
+ #else
+ #define TARGET_TERMINATE_DW2_EH_FRAME_INFO true
+ #endif
+ #endif
+
  #ifndef TARGET_ASM_EXCEPTION_SECTION
  #define TARGET_ASM_EXCEPTION_SECTION default_exception_section
  #endif
*************** Foundation, 59 Temple Place - Suite 330,
*** 266,272 ****
    TARGET_HAVE_NAMED_SECTIONS,            \
    TARGET_HAVE_CTORS_DTORS,            \
    TARGET_HAVE_TLS,                \
!   TARGET_HAVE_SRODATA_SECTION            \
  }
 
  #include "hooks.h"
--- 274,281 ----
    TARGET_HAVE_NAMED_SECTIONS,            \
    TARGET_HAVE_CTORS_DTORS,            \
    TARGET_HAVE_TLS,                \
!   TARGET_HAVE_SRODATA_SECTION,            \
!   TARGET_TERMINATE_DW2_EH_FRAME_INFO        \
  }
 
  #include "hooks.h"
Index: target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.35
diff -p -r1.35 target.h
*** target.h    7 Sep 2002 00:19:26 -0000    1.35
--- target.h    12 Sep 2002 13:01:12 -0000
*************** struct gcc_target
*** 269,274 ****
--- 269,277 ----
 
    /* True if a small readonly data section is supported.  */
    bool have_srodata_section;
+
+   /* True if EH frame info sections should be zero-terminated.  */
+   bool terminate_dw2_eh_frame_info;
  };
 
  extern struct gcc_target targetm;
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.165
diff -p -r1.165 tm.texi
*** doc/tm.texi    9 Sep 2002 20:04:32 -0000    1.165
--- doc/tm.texi    12 Sep 2002 13:01:22 -0000
*************** is a function that outputs a standard GA
*** 7501,7506 ****
--- 7501,7513 ----
  directive followed by a synthetic label.
  @end deftypefn
 
+ @deftypevar {Target Hook} bool TARGET_TERMINATE_DW2_EH_FRAME_INFO
+ Contains the value true if the target should add a zero word onto the
+ end of a Dwarf-2 frame info section when used for exception handling.
+ Default value is false if @code{EH_FRAME_SECTION_NAME} is defined, and
+ true otherwise.
+ @end deftypevar
+
  @node Alignment Output
  @subsection Assembler Commands for Alignment
 
*************** to indicate the beginning of the text se
*** 8033,8038 ****
--- 8040,8061 ----
  Define this macro to be a nonzero value if the assembler can generate 
Dwarf 2
  line debug info sections.  This will result in much more compact line 
number
  tables, and hence is desirable if it works.
+
+ @findex ASM_OUTPUT_DWARF_DELTA
+ @item ASM_OUTPUT_DWARF_DELTA (@var{stream}, @var{size}, @var{label1}, 
@var{label2})
+ A C statement to issue assembly directives that create a difference
+ between the two given labels, using an integer of the given size.
+
+ @findex ASM_OUTPUT_DWARF_OFFSET
+ @item ASM_OUTPUT_DWARF_OFFSET (@var{stream}, @var{size}, @var{label})
+ A C statement to issue assembly directives that create a
+ section-relative reference to the given label, using an integer of the
+ given size.
+
+ @findex ASM_OUTPUT_DWARF_PCREL
+ @item ASM_OUTPUT_DWARF_PCREL (@var{stream}, @var{size}, @var{label})
+ A C statement to issue assembly directives that create a self-relative
+ reference to the given label, using an integer of the given size.
 
  @findex PUT_SDB_@dots{}
  @item PUT_SDB_@dots{}
Index: config/darwin.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/darwin.c,v
retrieving revision 1.26
diff -p -r1.26 darwin.c
*** config/darwin.c    21 Aug 2002 02:41:46 -0000    1.26
--- config/darwin.c    12 Sep 2002 13:01:23 -0000
*************** darwin_globalize_label (stream, name)
*** 1294,1298 ****
--- 1294,1327 ----
      default_globalize_label (stream, name);
  }
 
+ /* Output a difference of two labels that will be an assembly time
+    constant if the two labels are local.  (.long lab1-lab2 will be
+    very different if lab1 is at the boundary between two sections; it
+    will be relocated according to the second section, not the first,
+    so one ends up with a difference between labels in different
+    sections, which is bad in the dwarf2 eh context for instance.)  */
+
+ static int darwin_dwarf_label_counter;
+
+ void
+ darwin_asm_output_dwarf_delta (file, size, lab1, lab2)
+      FILE *file;
+      int size ATTRIBUTE_UNUSED;
+      const char *lab1, *lab2;
+ {
+   const char *p = lab1 + (lab1[0] == '*');
+   int islocaldiff = (p[0] == 'L');
+
+   if (islocaldiff)
+     fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
+   else
+     fprintf (file, "\t%s\t", ".long");
+   assemble_name (file, lab1);
+   fprintf (file, "-");
+   assemble_name (file, lab2);
+   if (islocaldiff)
+     fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
+ }
+
  #include "gt-darwin.h"
 
Index: config/darwin.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/darwin.h,v
retrieving revision 1.38
diff -p -r1.38 darwin.h
*** config/darwin.h    3 Sep 2002 20:09:18 -0000    1.38
--- config/darwin.h    12 Sep 2002 13:01:23 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 35,40 ****
--- 35,46 ----
     leave it undefined and expect system builders to set configure args
     correctly.  */
 
+ /* One of Darwin's NeXT legacies is the Mach-O format, which is partly
+    like a.out and partly like COFF, with additional features like
+    multi-architecture binary support.  */
+
+ #define OBJECT_FORMAT_MACHO
+
  /* Suppress g++ attempt to link in the math library automatically.
     (Some Darwin versions have a libm, but they seem to cause problems
     for C++ executables.)  */
*************** Boston, MA 02111-1307, USA.  */
*** 92,99 ****
 
  #undef    STARTFILE_SPEC
  #define STARTFILE_SPEC  \
!   "%{pg:%{static:-lgcrt0.o}%{!static:-lgcrt1.o}} \
!     %{!pg:%{static:-lcrt0.o}%{!static:-lcrt1.o}}"
 
  #undef    DOLLARS_IN_IDENTIFIERS
  #define DOLLARS_IN_IDENTIFIERS 2
--- 98,109 ----
 
  #undef    STARTFILE_SPEC
  #define STARTFILE_SPEC  \
!   "%{pg:%{static:-lgcrt0.o}%{!static:-lgcrt1.o -lcrtbegin.o}} \
!     %{!pg:%{static:-lcrt0.o}%{!static:-lcrt1.o -lcrtbegin.o}}"
!
! #undef    ENDFILE_SPEC
! #define ENDFILE_SPEC \
!   "-lcrtend.o"
 
  #undef    DOLLARS_IN_IDENTIFIERS
  #define DOLLARS_IN_IDENTIFIERS 2
*************** SECTION_FUNCTION (machopic_picsymbol_stu
*** 425,431 ****
          ".picsymbol_stub", 0)              \
  SECTION_FUNCTION (darwin_exception_section,        \
          in_darwin_exception,            \
!         ".section __TEXT,__gcc_except_tab", 0)    \
  SECTION_FUNCTION (darwin_eh_frame_section,        \
          in_darwin_eh_frame,            \
          ".section __TEXT,__eh_frame", 0)    \
--- 435,441 ----
          ".picsymbol_stub", 0)              \
  SECTION_FUNCTION (darwin_exception_section,        \
          in_darwin_exception,            \
!         ".section __DATA,__gcc_except_tab", 0)    \
  SECTION_FUNCTION (darwin_eh_frame_section,        \
          in_darwin_eh_frame,            \
          ".section __TEXT,__eh_frame", 0)    \
*************** enum machopic_addr_class {
*** 597,603 ****
   
  #undef ASM_PREFERRED_EH_DATA_FORMAT
  #define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL)  \
!   (((CODE) == 1 || (GLOBAL) == 0) ? DW_EH_PE_pcrel : DW_EH_PE_absptr)
 
  #define DARWIN_REGISTER_TARGET_PRAGMAS(PFILE)                \
    do {                                    \
--- 607,620 ----
   
  #undef ASM_PREFERRED_EH_DATA_FORMAT
  #define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL)  \
!   (((CODE) == 2 && (GLOBAL) == 1) \
!    ? (DW_EH_PE_pcrel | DW_EH_PE_indirect) : \
!      ((CODE) == 1 || (GLOBAL) == 0) ? DW_EH_PE_pcrel : DW_EH_PE_absptr)
!
! #define ASM_OUTPUT_DWARF_DELTA(FILE,SIZE,LABEL1,LABEL2)  \
!   darwin_asm_output_dwarf_delta (FILE, SIZE, LABEL1, LABEL2)
!
! #define TARGET_TERMINATE_DW2_EH_FRAME_INFO false
 
  #define DARWIN_REGISTER_TARGET_PRAGMAS(PFILE)                \
    do {                                    \

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: eh-patch
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20020912/e056bce6/attachment.ksh>


More information about the Gcc-patches mailing list