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]
Other format: [Raw text]

PATCH RFC: dwarf2 EH for Darwin


This patch enables dwarf2-based exception support for Darwin. While
the patch is mostly non-controversial, there are two changes to
generic code that I would like to get feedback on.

The first is the macro ASM_OUTPUT_DWARF_DELTA, which seems like
it probably ought to be a target hook, even though it only needs
a non-default value for the one target.

The second is the TERMINATE_EH_FRAME_INFO, which looks kludgy to
me, but I'm not clear on how this ought to be done. The crux of
the problem is that EH_FRAME_SECTION_NAME should not be set for
Darwin, because it enables ELFish bits we don't really want.
Perhaps the zero-termination choice ought to be a generic target
hook too?

In any case, here's the patch. As is, it bootstraps on Darwin, and
knocks off a couple hundred G++ testsuite fails.

Stan

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

* 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.
* dwarf2asm.c (dw2_asm_output_delta): Use macro
ASM_OUTPUT_DWARF_DELTA if defined.
* dwarf2out.c (output_call_frame_info): Use
TERMINATE_EH_FRAME_INFO to control output of terminating zero.
* 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.
(TERMINATE_EH_FRAME_INFO): Define.
* config/darwin.c (darwin_asm_output_dwarf_delta): New function.

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 9 Sep 2002 23:02:27 -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 9 Sep 2002 23:02:28 -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 9 Sep 2002 23:02:28 -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 9 Sep 2002 23:02:33 -0000
*************** output_call_frame_info (for_eh)
*** 2043,2049 ****
--- 2043,2056 ----
ASM_OUTPUT_LABEL (asm_out_file, l2);
}

+ #ifndef TERMINATE_EH_FRAME_INFO
+ #define TERMINATE_EH_FRAME_INFO 0
#ifndef EH_FRAME_SECTION_NAME
+ #define TERMINATE_EH_FRAME_INFO 1
+ #endif
+ #endif
+
+ #if TERMINATE_EH_FRAME_INFO
if (for_eh)
dw2_asm_output_data (4, 0, "End of Table");
#endif
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 9 Sep 2002 23:02:35 -0000
*************** darwin_globalize_label (stream, name)
*** 1294,1298 ****
--- 1294,1322 ----
default_globalize_label (stream, name);
}

+ /* Output a difference of two labels that is relocatable. */
+
+ static int 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,", 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", 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 9 Sep 2002 23:02:35 -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 TERMINATE_EH_FRAME_INFO 0

#define DARWIN_REGISTER_TARGET_PRAGMAS(PFILE) \
do { \



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