Guys,

I've been digging in gcc internals and succeeded in implementing stuff
that allows us to write code such as
        int main(int argc, char *argv[])
                __attribute__((__exception_handler__(handler)));
to indicate that handler is the exception handler for function main.

The patch is attached, it only affects four files in gcc.

What this gcc patch does is to generate an additional couple of lines of
assembler code for those functions that have an exception handler.

Attached is an example in C and the assembler code generated for it. In
the arm-wince-mingw32ce world, only patches to gcc are required, no
changes to any runtime are needed. (I need to look into the cegcc
environment, things are slightly different there because a default
exception handler is in place there.)

Comments are welcome as always.

Pedro, is it ok to commit this to SVN ?

        Danny
-- 
Danny Backx ; danny.backx - at - scarlet.be ; http://danny.backx.info
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

struct _DISPATCHER_CONTEXT;
void handler(struct _EXCEPTION_RECORD *ExceptionRecord,
		void *EstablisherFrame,
		struct _CONTEXT *ContextRecord,
		struct _DISPATCHER_CONTEXT *DispatcherContext)
{
	MessageBoxW(0, L"Crash Handler", L"WinCE Exception", 0);
	exit(0);
}

int main(int argc, char *argv[])
	__attribute__((__exception_handler__(handler)));

int main(int argc, char *argv[])
{
	int	*i;

	i = 0;
	*i = 1;
	MessageBoxW(0, L"Main", L"Survived", 0);
	exit(0);
}
        .file   "syntax.c"
        .section .rdata
        .align  0
.LC0:
        .ascii  "C\000r\000a\000s\000h\000 \000H\000a\000n\000d\000l"
        .ascii  "\000e\000r\000\000\000"
        .align  0
.LC1:
        .ascii  "W\000i\000n\000C\000E\000 \000E\000x\000c\000e\000p"
        .ascii  "\000t\000i\000o\000n\000\000\000"
        .text
        .align  0
        .global handler
        .def    handler;        .scl    2;      .type   32;     .endef
handler:
        @ args = 0, pretend = 0, frame = 16
        @ frame_needed = 1, uses_anonymous_args = 0
        mov     ip, sp
        stmfd   sp!, {fp, ip, lr, pc}
        sub     fp, ip, #4
        sub     sp, sp, #16
        str     r0, [fp, #-16]
        str     r1, [fp, #-20]
        str     r2, [fp, #-24]
        str     r3, [fp, #-28]
        mov     r0, #0
        ldr     r1, .L3
        ldr     r2, .L3+4
        mov     r3, #0
        bl      MessageBoxW
        mov     r0, #0
        bl      exit
.L4:
        .align  0
.L3:
        .word   .LC0
        .word   .LC1
        .def    __gccmain;      .scl    2;      .type   32;     .endef
        .section .rdata
        .align  0
.LC2:
        .ascii  "M\000a\000i\000n\000\000\000"
        .align  0
.LC3:
        .ascii  "S\000u\000r\000v\000i\000v\000e\000d\000\000\000"
        .text
        .align  0
        .global main
@ main has exception handler handler
        .section .pdata
        .word main
        .word 0xc0000002 | ((((_cegcc_main_end - main) / 4) & 0x3ffffff) << 8) 
/* _cegcc_main size */
        .text
@       .global _cegcc_main_data
_cegcc_main_data:
        .word handler /* _cegcc_main_handler */
        .word 0 /* _cegcc_main_handler_data */
        .def    main;   .scl    2;      .type   32;     .endef
main:
        @ args = 0, pretend = 0, frame = 12
        @ frame_needed = 1, uses_anonymous_args = 0
        mov     ip, sp
        stmfd   sp!, {fp, ip, lr, pc}
        sub     fp, ip, #4
        sub     sp, sp, #12
        str     r0, [fp, #-20]
        str     r1, [fp, #-24]
        bl      __gccmain
        mov     r3, #0
        str     r3, [fp, #-16]
        ldr     r2, [fp, #-16]
        mov     r3, #1
        str     r3, [r2, #0]
        mov     r0, #0
        ldr     r1, .L7
        ldr     r2, .L7+4
        mov     r3, #0
        bl      MessageBoxW
        mov     r0, #0
        bl      exit
.L8:
        .align  0
.L7:
        .word   .LC2
        .word   .LC3
_cegcc_main_end:
        .def    exit;   .scl    2;      .type   32;     .endef
        .def    MessageBoxW;    .scl    2;      .type   32;     .endef
Index: gcc/gcc/c-common.c
===================================================================
--- gcc/gcc/c-common.c	(revision 1020)
+++ gcc/gcc/c-common.c	(working copy)
@@ -505,6 +505,8 @@
 static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
 static tree handle_always_inline_attribute (tree *, tree, tree, int,
 					    bool *);
+static tree handle_exception_handler_attribute (tree *, tree, tree, int,
+					    bool *);
 static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
 static tree handle_used_attribute (tree *, tree, tree, int, bool *);
 static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
@@ -633,6 +635,8 @@
 			      handle_cleanup_attribute },
   { "warn_unused_result",     0, 0, false, true, true,
 			      handle_warn_unused_result_attribute },
+  { "exception_handler",      1, 1, true,  false, false,
+			      handle_exception_handler_attribute },
   { "sentinel",               0, 1, false, true, true,
 			      handle_sentinel_attribute },
   { NULL,                     0, 0, false, false, false, NULL }
@@ -4216,6 +4220,59 @@
   return NULL_TREE;
 }
 
+/*
+ * Handle a "exception_handler" attribute.
+ *
+ * One argument is required : the name of a function to call in case of exceptions.
+ * Example syntax :
+ *
+ * int main(int argc, char *argv[])
+ *         __attribute__((__exception_handler__(handler)));
+ */
+
+static tree
+handle_exception_handler_attribute (tree *node, tree name,
+				tree args,
+				int ARG_UNUSED (flags),
+				bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) == FUNCTION_DECL)
+    {
+	    /*
+	     * We need to pass the name of the exception handler. The
+	     * right code then gets generated from config/arm/mingw32.h
+	     * or similar, the assembler and linker will do the hard work.
+	     *
+	     * FIX ME We don't support passing data to the exception handler.
+	     *
+	     * This should be possible though, by using an additional argument
+	     * which needs to fit in the dword (e.g. a pointer) and storing that
+	     * in the right field as we do with the exception handler.
+	     */
+
+	    /* Handle mode attribute, handle_section_attribute, .. use args */
+	tree id = TREE_VALUE (args);
+	tree attr = NULL_TREE;
+
+	const char *x = IDENTIFIER_POINTER(id);
+
+#if 1
+	attr = tree_cons (get_identifier ("exception_handler"), args, attr);
+#else
+	/* Works too */
+	attr = tree_cons (get_identifier ("exception_handler"),
+			build_string(strlen(x), x), attr);
+#endif
+    }
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "flatten" attribute; arguments as in
    struct attribute_spec.handler.  */
 
Index: gcc/gcc/config/arm/arm.c
===================================================================
--- gcc/gcc/config/arm/arm.c	(revision 1020)
+++ gcc/gcc/config/arm/arm.c	(working copy)
@@ -15553,4 +15553,31 @@
   return (insn_flags & FL_THUMB) == FL_THUMB;
 }
 
+/*
+ * called from
+ * #define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL)
+ */
+char *
+arm_exception_handler(FILE *fp, char *name, tree decl)
+{
+	tree	attr, a2;
+
+	attr = DECL_ATTRIBUTES(decl);
+	if (! attr)
+		return NULL;
+	a2 = lookup_attribute("__exception_handler__", attr);
+	if (! a2)
+		return NULL;
+	if (a2) {
+#if 0
+		fprintf(stderr, "Receive (arm_exception_handler) : \n");
+		debug_tree(a2);
+		fprintf(stderr, "IP(TV(TV(a2))) %s\n", IDENTIFIER_POINTER(TREE_VALUE(TREE_VALUE(a2))));
+#endif
+		return IDENTIFIER_POINTER(TREE_VALUE(TREE_VALUE(a2)));
+	}
+	/* FIX ME */
+	return NULL;
+}
+
 #include "gt-arm.h"
Index: gcc/gcc/config/arm/mingw32.h
===================================================================
--- gcc/gcc/config/arm/mingw32.h	(revision 1020)
+++ gcc/gcc/config/arm/mingw32.h	(working copy)
@@ -93,3 +93,55 @@
 						         \
   putc ('\"', asm_file);			         \
 } while (0)
+
+/*
+ * An ARM specific header for function declarations.
+ *
+ * This one is needed for exception handlers : the entry in the pdata section
+ * needs to know the size of the function for which we handle exceptions.
+ */
+#undef ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL)				\
+  do										\
+    {										\
+	char *eh;								\
+	eh = arm_exception_handler(STREAM, NAME, DECL);				\
+	if (eh) {								\
+		asm_fprintf (STREAM, "%@ %s has exception handler %s\n",	\
+				NAME, eh);					\
+		asm_fprintf (STREAM, "\t.section .pdata\n");			\
+		asm_fprintf (STREAM, "\t.word %s\n", NAME);			\
+		asm_fprintf (STREAM, "\t.word 0xc0000002 | "			\
+			"((((_cegcc_%s_end - %s) / 4) & 0x3ffffff) << 8) "	\
+			"/* _cegcc_%s size */\n", NAME, NAME, NAME);		\
+		asm_fprintf (STREAM, "\t.text\n");				\
+		asm_fprintf (STREAM, "@\t.global _cegcc_%s_data\n", NAME);	\
+		asm_fprintf (STREAM, "_cegcc_%s_data:\n", NAME);		\
+		asm_fprintf (STREAM, "\t.word %s /* _cegcc_%s_handler */\n",	\
+			eh, NAME);						\
+		asm_fprintf (STREAM, "\t.word 0 "				\
+			"/* _cegcc_%s_handler_data */\n", NAME);		\
+	}									\
+    if (arm_pe_dllexport_name_p (NAME))						\
+      arm_pe_record_exported_symbol (NAME, 0);					\
+    if (write_symbols != SDB_DEBUG)						\
+      arm_pe_declare_function_type (STREAM, NAME, TREE_PUBLIC (DECL));		\
+    ARM_DECLARE_FUNCTION_NAME (STREAM, NAME, DECL);				\
+    if (TARGET_THUMB)								\
+      fprintf (STREAM, "\t.code 16\n");						\
+    ASM_OUTPUT_LABEL (STREAM, NAME);						\
+    }										\
+    while (0)
+
+/*
+ * An ARM specific trailer for function declarations.
+ *
+ * This one is needed for exception handlers : the entry in the pdata section
+ * needs to know the size of the function for which we handle exceptions.
+ */
+#undef  ASM_DECLARE_FUNCTION_SIZE
+#define ASM_DECLARE_FUNCTION_SIZE(STREAM, NAME, DECL)			\
+    {									\
+	if (arm_exception_handler(STREAM, NAME, DECL))			\
+		asm_fprintf (STREAM, "_cegcc_%s_end:\n", NAME);		\
+    }
Index: gcc/gcc/config/arm/wince-cegcc.h
===================================================================
--- gcc/gcc/config/arm/wince-cegcc.h	(revision 1020)
+++ gcc/gcc/config/arm/wince-cegcc.h	(working copy)
@@ -64,3 +64,55 @@
   %{static:-Bstatic} %{!static:-Bdynamic} \
   %{shared|mdll: -e DllMainCRTStartup} \
   "
+
+/*
+ * An ARM specific header for function declarations.
+ *
+ * This one is needed for exception handlers : the entry in the pdata section
+ * needs to know the size of the function for which we handle exceptions.
+ */
+#undef ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL)				\
+  do										\
+    {										\
+	char *eh;								\
+	eh = arm_exception_handler(STREAM, NAME, DECL);				\
+	if (eh) {								\
+		asm_fprintf (STREAM, "%@ %s has exception handler %s\n",	\
+				NAME, eh);					\
+		asm_fprintf (STREAM, "\t.section .pdata\n");			\
+		asm_fprintf (STREAM, "\t.word %s\n", NAME);			\
+		asm_fprintf (STREAM, "\t.word 0xc0000002 | "			\
+			"((((_cegcc_%s_end - %s) / 4) & 0x3ffffff) << 8) "	\
+			"/* _cegcc_%s size */\n", NAME, NAME, NAME);		\
+		asm_fprintf (STREAM, "\t.text\n");				\
+		asm_fprintf (STREAM, "\t.global _cegcc_%s_data\n", NAME);	\
+		asm_fprintf (STREAM, "_cegcc_%s_data:\n", NAME);		\
+		asm_fprintf (STREAM, "\t.word %s /* _cegcc_%s_handler */\n",	\
+			eh, NAME);						\
+		asm_fprintf (STREAM, "\t.word 0 "				\
+			"/* _cegcc_%s_handler_data */\n", NAME);		\
+	}									\
+    if (arm_pe_dllexport_name_p (NAME))						\
+      arm_pe_record_exported_symbol (NAME, 0);					\
+    if (write_symbols != SDB_DEBUG)						\
+      arm_pe_declare_function_type (STREAM, NAME, TREE_PUBLIC (DECL));		\
+    ARM_DECLARE_FUNCTION_NAME (STREAM, NAME, DECL);				\
+    if (TARGET_THUMB)								\
+      fprintf (STREAM, "\t.code 16\n");						\
+    ASM_OUTPUT_LABEL (STREAM, NAME);						\
+    }										\
+    while (0)
+
+/*
+ * An ARM specific trailer for function declarations.
+ *
+ * This one is needed for exception handlers : the entry in the pdata section
+ * needs to know the size of the function for which we handle exceptions.
+ */
+#undef  ASM_DECLARE_FUNCTION_SIZE
+#define ASM_DECLARE_FUNCTION_SIZE(STREAM, NAME, DECL)			\
+    {									\
+	if (arm_exception_handler(STREAM, NAME, DECL))			\
+		asm_fprintf (STREAM, "_cegcc_%s_end:\n", NAME);		\
+    }

Attachment: signature.asc
Description: This is a digitally signed message part

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
Cegcc-devel mailing list
Cegcc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/cegcc-devel

Reply via email to