dwarf2 EH support

From-SVN: r15255
This commit is contained in:
Jason Merrill 1997-09-10 14:00:28 -04:00
parent 0680d17043
commit 0021b564f4
23 changed files with 1210 additions and 164 deletions

View File

@ -2849,7 +2849,7 @@ init_decl_processing ()
tree traditional_ptr_type_node;
/* Data types of memcpy and strlen. */
tree memcpy_ftype, memset_ftype, strlen_ftype;
tree void_ftype_any;
tree void_ftype_any, ptr_ftype_void, ptr_ftype_ptr;
int wchar_type_size;
tree temp;
tree array_domain_type;
@ -3165,6 +3165,11 @@ init_decl_processing ()
sizetype,
endlink))));
ptr_ftype_void = build_function_type (ptr_type_node, endlink);
ptr_ftype_ptr
= build_function_type (ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node, endlink));
builtin_function ("__builtin_constant_p", default_function_type,
BUILT_IN_CONSTANT_P, NULL_PTR);
@ -3186,6 +3191,36 @@ init_decl_processing ()
build_function_type (ptr_type_node, NULL_TREE),
BUILT_IN_AGGREGATE_INCOMING_ADDRESS, NULL_PTR);
/* Hooks for the DWARF 2 __throw routine. */
builtin_function ("__builtin_unwind_init",
build_function_type (void_type_node, endlink),
BUILT_IN_UNWIND_INIT, NULL_PTR);
builtin_function ("__builtin_fp", ptr_ftype_void, BUILT_IN_FP, NULL_PTR);
builtin_function ("__builtin_sp", ptr_ftype_void, BUILT_IN_SP, NULL_PTR);
builtin_function ("__builtin_dwarf_fp_regnum",
build_function_type (unsigned_type_node, endlink),
BUILT_IN_DWARF_FP_REGNUM, NULL_PTR);
builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
BUILT_IN_FROB_RETURN_ADDR, NULL_PTR);
builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
BUILT_IN_EXTRACT_RETURN_ADDR, NULL_PTR);
builtin_function ("__builtin_set_return_addr_reg",
build_function_type (void_type_node,
tree_cons (NULL_TREE,
ptr_type_node,
endlink)),
BUILT_IN_SET_RETURN_ADDR_REG, NULL_PTR);
builtin_function ("__builtin_eh_stub", ptr_ftype_void,
BUILT_IN_EH_STUB, NULL_PTR);
builtin_function
("__builtin_set_eh_regs",
build_function_type (void_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE,
type_for_mode (ptr_mode, 0),
endlink))),
BUILT_IN_SET_EH_REGS, NULL_PTR);
builtin_function ("__builtin_alloca",
build_function_type (ptr_type_node,
tree_cons (NULL_TREE,

View File

@ -239,6 +239,7 @@ static char *initname, *fininame; /* names of init and fini funcs */
static struct head constructors; /* list of constructors found */
static struct head destructors; /* list of destructors found */
static struct head exports; /* list of exported symbols */
static struct head frame_tables; /* list of frame unwind info tables */
struct obstack temporary_obstack;
struct obstack permanent_obstack;
@ -599,13 +600,16 @@ is_ctor_dtor (s)
#ifdef NO_DOT_IN_LABEL
{ "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 },
{ "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 },
{ "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 },
#else
{ "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 },
{ "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 },
{ "GLOBAL_.F.", sizeof ("GLOBAL_.F.")-1, 5, 0 },
#endif
#else
{ "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 },
{ "GLOBAL_$D$", sizeof ("GLOBAL_$D$")-1, 2, 0 },
{ "GLOBAL_$F$", sizeof ("GLOBAL_$F$")-1, 5, 0 },
#endif
{ "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 },
{ "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 },
@ -993,6 +997,7 @@ main (argc, argv)
num_c_args++;
}
obstack_free (&temporary_obstack, temporary_firstobj);
++num_c_args;
c_ptr = c_argv = (char **) xcalloc (sizeof (char *), num_c_args);
@ -1288,6 +1293,7 @@ main (argc, argv)
shared_obj = 1;
}
obstack_free (&temporary_obstack, temporary_firstobj);
*c_ptr++ = "-fno-exceptions";
#ifdef COLLECT_EXPORT_LIST
/* The AIX linker will discard static constructors in object files if
@ -1396,7 +1402,8 @@ main (argc, argv)
}
if (constructors.number == 0 && destructors.number == 0
#ifdef LDD_SUFFIX
&& frame_tables.number == 0
#ifdef SCAN_LIBRARIES
/* If we will be running these functions ourselves, we want to emit
stubs into the shared library so that we don't have to relink
dependent programs when we add static objects. */
@ -1690,6 +1697,7 @@ write_c_file_stat (stream, name)
char *name;
{
char *prefix, *p, *q;
int frames = (frame_tables.number > 0);
/* Figure out name of output_file, stripping off .so version. */
p = rindex (output_file, '/');
@ -1743,15 +1751,38 @@ write_c_file_stat (stream, name)
fprintf (stream, "static int count;\n");
fprintf (stream, "typedef void entry_pt();\n");
write_list_with_asm (stream, "extern entry_pt ", constructors.first);
if (frames)
{
write_list_with_asm (stream, "extern void *", frame_tables.first);
fprintf (stream, "\tstatic void *frame_table[] = {\n");
write_list (stream, "\t\t&", frame_tables.first);
fprintf (stream, "\t0\n};\n");
fprintf (stream, "extern void __register_frame_table (void *);\n");
fprintf (stream, "extern void __deregister_frame (void *);\n");
fprintf (stream, "static void reg_frame () {\n");
fprintf (stream, "\t__register_frame_table (frame_table);\n");
fprintf (stream, "\t}\n");
fprintf (stream, "static void dereg_frame () {\n");
fprintf (stream, "\t__deregister_frame (frame_table);\n");
fprintf (stream, "\t}\n");
}
fprintf (stream, "void %s() {\n", initname);
if (constructors.number > 0)
if (constructors.number > 0 || frames)
{
fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
write_list (stream, "\t\t", constructors.first);
if (frames)
fprintf (stream, "\treg_frame,\n");
fprintf (stream, "\t};\n");
fprintf (stream, "\tentry_pt **p;\n");
fprintf (stream, "\tif (count++ != 0) return;\n");
fprintf (stream, "\tp = ctors + %d;\n", constructors.number);
fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames);
fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
}
else
@ -1759,16 +1790,18 @@ write_c_file_stat (stream, name)
fprintf (stream, "}\n");
write_list_with_asm (stream, "extern entry_pt ", destructors.first);
fprintf (stream, "void %s() {\n", fininame);
if (destructors.number > 0)
if (destructors.number > 0 || frames)
{
fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
write_list (stream, "\t\t", destructors.first);
if (frames)
fprintf (stream, "\tdereg_frame,\n");
fprintf (stream, "\t};\n");
fprintf (stream, "\tentry_pt **p;\n");
fprintf (stream, "\tif (--count != 0) return;\n");
fprintf (stream, "\tp = dtors;\n");
fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
destructors.number);
destructors.number + frames);
}
fprintf (stream, "}\n");
@ -1788,20 +1821,46 @@ write_c_file_glob (stream, name)
{
/* Write the tables as C code */
int frames = (frame_tables.number > 0);
fprintf (stream, "typedef void entry_pt();\n\n");
write_list_with_asm (stream, "extern entry_pt ", constructors.first);
if (frames)
{
write_list_with_asm (stream, "extern void *", frame_tables.first);
fprintf (stream, "\tstatic void *frame_table[] = {\n");
write_list (stream, "\t\t&", frame_tables.first);
fprintf (stream, "\t0\n};\n");
fprintf (stream, "extern void __register_frame_table (void *);\n");
fprintf (stream, "extern void __deregister_frame (void *);\n");
fprintf (stream, "static void reg_frame () {\n");
fprintf (stream, "\t__register_frame_table (frame_table);\n");
fprintf (stream, "\t}\n");
fprintf (stream, "static void dereg_frame () {\n");
fprintf (stream, "\t__deregister_frame (frame_table);\n");
fprintf (stream, "\t}\n");
}
fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number);
fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames);
write_list (stream, "\t", constructors.first);
if (frames)
fprintf (stream, "\treg_frame,\n");
fprintf (stream, "\t0\n};\n\n");
write_list_with_asm (stream, "extern entry_pt ", destructors.first);
fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number);
fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames);
write_list (stream, "\t", destructors.first);
if (frames)
fprintf (stream, "\tdereg_frame,\n");
fprintf (stream, "\t0\n};\n\n");
fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
@ -1985,6 +2044,10 @@ scan_prog_file (prog_name, which_pass)
#endif
break;
case 5:
if (which_pass != PASS_LIB)
add_to_list (&frame_tables, name);
default: /* not a constructor or destructor */
continue;
}

View File

@ -1866,6 +1866,7 @@ function_prologue (file, size)
int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
|| current_function_uses_const_pool);
long tsize = get_frame_size ();
int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset;
/* pic references don't explicitly mention pic_offset_table_rtx */
if (TARGET_SCHEDULE_PROLOGUE)
@ -1881,13 +1882,34 @@ function_prologue (file, size)
if (frame_pointer_needed)
{
output_asm_insn ("push%L1 %1", xops);
if (dwarf2out_do_frame ())
{
char *l = (char *) dwarf2out_cfi_label ();
cfa_store_offset += 4;
cfa_offset = cfa_store_offset;
dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, -cfa_store_offset);
}
output_asm_insn (AS2 (mov%L0,%0,%1), xops);
if (dwarf2out_do_frame ())
dwarf2out_def_cfa ("", FRAME_POINTER_REGNUM, cfa_offset);
}
if (tsize == 0)
;
else if (! TARGET_STACK_PROBE || tsize < CHECK_STACK_LIMIT)
output_asm_insn (AS2 (sub%L0,%2,%0), xops);
{
output_asm_insn (AS2 (sub%L0,%2,%0), xops);
if (dwarf2out_do_frame ())
{
cfa_store_offset += tsize;
if (! frame_pointer_needed)
{
cfa_offset = cfa_store_offset;
dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);
}
}
}
else
{
xops[3] = gen_rtx (REG, SImode, 0);
@ -1913,6 +1935,17 @@ function_prologue (file, size)
{
xops[0] = gen_rtx (REG, SImode, regno);
output_asm_insn ("push%L0 %0", xops);
if (dwarf2out_do_frame ())
{
char *l = (char *) dwarf2out_cfi_label ();
cfa_store_offset += 4;
if (! frame_pointer_needed)
{
cfa_offset = cfa_store_offset;
dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
}
dwarf2out_reg_save (l, regno, -cfa_store_offset);
}
}
if (pic_reg_used && TARGET_DEEP_BRANCH_PREDICTION)

View File

@ -249,6 +249,10 @@ Boston, MA 02111-1307, USA. */
(TARGET_LONG64 ? ".section\t.dtors,1,2,0,8" : ".section\t.dtors,1,2,0,4")
#endif /* defined (CRT_BEGIN) || defined (CRT_END) */
/* dwarf2out will handle padding this data properly. We definitely don't
want it 8-byte aligned on n32. */
#define EH_FRAME_SECTION_ASM_OP ".section\t.eh_frame,1,2,0,1"
/* A default list of other sections which we might be "in" at any given
time. For targets that use additional sections (e.g. .tdesc) you
should override this definition in the target-specific file which
@ -538,5 +542,5 @@ do { \
%{!static: \
%{!shared: %{!non_shared: %{!call_shared: -call_shared -no_unresolved}}}} \
%{rpath} -init __do_global_ctors -fini __do_global_dtors \
%{shared:-hidden_symbol __do_global_ctors,__do_global_dtors} \
%{shared:-hidden_symbol __do_global_ctors,__do_global_dtors,__EH_FRAME_BEGIN__} \
-_SYSTYPE_SVR4 %{mabi=32: -32}%{mabi=n32: -n32}%{mabi=64: -64} %{!mabi*: -n32}"

View File

@ -5241,6 +5241,9 @@ function_prologue (file, size)
sp_str, sp_str, tsize);
fprintf (file, "\t.cprestore %d\n", current_frame_info.args_size);
}
if (dwarf2out_do_frame ())
dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, tsize);
}
}

View File

@ -948,12 +948,11 @@ while (0)
#define DBX_REGISTER_NUMBER(REGNO) mips_dbx_regno[ (REGNO) ]
/* The mapping from gcc register number to DWARF 2 CFA column number.
This mapping does not allow for tracking DBX register 0, since column 0
is used for the frame address, but since register 0 is fixed this is
not really a problem. */
This mapping does not allow for tracking register 0, since SGI's broken
dwarf reader thinks column 0 is used for the frame address, but since
register 0 is fixed this is not a problem. */
#define DWARF_FRAME_REGNUM(REG) \
(REG == GP_REG_FIRST + 31 ? DWARF_FRAME_RETURN_COLUMN \
: DBX_REGISTER_NUMBER (REG))
(REG == GP_REG_FIRST + 31 ? DWARF_FRAME_RETURN_COLUMN : REG)
/* The DWARF 2 CFA column which tracks the return address. */
#define DWARF_FRAME_RETURN_COLUMN (FP_REG_LAST + 1)

View File

@ -2910,10 +2910,8 @@ save_regs (file, low, high, base, offset, n_regs, real_offset)
{
fprintf (file, "\tstx %s,[%s+%d]\n",
reg_names[i], base, offset + 4 * n_regs);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
dwarf2out_reg_save ("", i, real_offset + 4 * n_regs);
#endif
n_regs += 2;
}
}
@ -2927,34 +2925,28 @@ save_regs (file, low, high, base, offset, n_regs, real_offset)
{
fprintf (file, "\tstd %s,[%s+%d]\n",
reg_names[i], base, offset + 4 * n_regs);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
{
char *l = (char *) dwarf2out_cfi_label ();
dwarf2out_reg_save (l, i, real_offset + 4 * n_regs);
dwarf2out_reg_save (l, i+1, real_offset + 4 * n_regs + 4);
}
#endif
n_regs += 2;
}
else
{
fprintf (file, "\tst %s,[%s+%d]\n",
reg_names[i], base, offset + 4 * n_regs);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
dwarf2out_reg_save ("", i, real_offset + 4 * n_regs);
#endif
n_regs += 2;
}
else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
{
fprintf (file, "\tst %s,[%s+%d]\n",
reg_names[i+1], base, offset + 4 * n_regs + 4);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
dwarf2out_reg_save ("", i + 1, real_offset + 4 * n_regs + 4);
#endif
n_regs += 2;
}
}
@ -3196,8 +3188,7 @@ output_function_prologue (file, size, leaf_function)
}
}
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG && actual_fsize)
if (dwarf2out_do_frame () && actual_fsize)
{
char *label = (char *) dwarf2out_cfi_label ();
@ -3217,7 +3208,6 @@ output_function_prologue (file, size, leaf_function)
dwarf2out_return_reg (label, 31);
}
}
#endif
/* If doing anything with PIC, do it now. */
if (! flag_pic)
@ -4739,15 +4729,13 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op, doublewo
fprintf (file, "\t%s %s,[%s+%d]\n",
doubleword_op, reg_names[regno],
base_reg, offset);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
{
char *l = (char *) dwarf2out_cfi_label ();
dwarf2out_reg_save (l, regno, offset + base_offset);
dwarf2out_reg_save
(l, regno+1, offset+base_offset + UNITS_PER_WORD);
}
#endif
}
else
fprintf (file, "\t%s [%s+%d],%s\n",
@ -4764,10 +4752,8 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op, doublewo
fprintf (file, "\t%s %s,[%s+%d]\n",
word_op, reg_names[regno],
base_reg, offset);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
dwarf2out_reg_save ("", regno, offset + base_offset);
#endif
}
else
fprintf (file, "\t%s [%s+%d],%s\n",
@ -4790,10 +4776,8 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op, doublewo
fprintf (file, "\t%s %s,[%s+%d]\n",
word_op, reg_names[regno],
base_reg, offset);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
dwarf2out_reg_save ("", regno, offset + base_offset);
#endif
}
else
fprintf (file, "\t%s [%s+%d],%s\n",
@ -4891,8 +4875,7 @@ sparc_flat_output_function_prologue (file, size)
reg_offset += 4;
}
}
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
{
char *l = (char *) dwarf2out_cfi_label ();
if (gmask & FRAME_POINTER_MASK)
@ -4904,15 +4887,12 @@ sparc_flat_output_function_prologue (file, size)
else
dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size);
}
#endif
if (gmask & RETURN_ADDR_MASK)
{
fprintf (file, "\tst %s,[%s+%d]\n",
reg_names[RETURN_ADDR_REGNUM], sp_str, reg_offset);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
dwarf2out_return_save ("", reg_offset - size);
#endif
reg_offset += 4;
}
sparc_flat_save_restore (file, sp_str, reg_offset,
@ -4951,8 +4931,7 @@ sparc_flat_output_function_prologue (file, size)
offset += 4;
}
}
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
{
char *l = (char *) dwarf2out_cfi_label ();
if (gmask & FRAME_POINTER_MASK)
@ -4964,17 +4943,14 @@ sparc_flat_output_function_prologue (file, size)
else
dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size1);
}
#endif
if (gmask & RETURN_ADDR_MASK)
{
fprintf (file, "\tst %s,[%s+%d]\n",
reg_names[RETURN_ADDR_REGNUM], sp_str, offset);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
/* offset - size1 == reg_offset - size
if reg_offset were updated above like offset. */
dwarf2out_return_save ("", offset - size1);
#endif
offset += 4;
}
sparc_flat_save_restore (file, sp_str, offset,
@ -4983,11 +4959,9 @@ sparc_flat_output_function_prologue (file, size)
"st", "std", -size1);
fprintf (file, "\tset %d,%s\n\tsub %s,%s,%s\n",
size - size1, t1_str, sp_str, t1_str, sp_str);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
if (! (gmask & FRAME_POINTER_MASK))
dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, size);
#endif
}
}

View File

@ -25,3 +25,6 @@ Boston, MA 02111-1307, USA. */
#define DBX_USE_BINCL
#include "sparc/sparc.h"
/* The Sun as doesn't like unaligned data. */
#define DWARF2_UNWIND_INFO 0

View File

@ -91,6 +91,7 @@ Boston, MA 02111-1307, USA. */
#define STRING_ASM_OP ".asciz"
#define COMMON_ASM_OP ".common"
#define SKIP_ASM_OP ".skip"
#define UNALIGNED_DOUBLE_INT_ASM_OP ".uaxword"
#define UNALIGNED_INT_ASM_OP ".uaword"
#define UNALIGNED_SHORT_ASM_OP ".uahalf"
#define PUSHSECTION_ASM_OP ".pushsection"
@ -179,6 +180,8 @@ do { ASM_OUTPUT_ALIGN ((FILE), Pmode == SImode ? 2 : 3); \
#define CTORS_SECTION_ASM_OP ".section\t\".ctors\",#alloc,#write"
#undef DTORS_SECTION_ASM_OP
#define DTORS_SECTION_ASM_OP ".section\t\".dtors\",#alloc,#write"
#undef EH_FRAME_SECTION_ASM_OP
#define EH_FRAME_SECTION_ASM_OP ".section\t\".eh_frame\",#alloc,#write"
/* A C statement to output something to the assembler file to switch to section
NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or

View File

@ -2934,7 +2934,7 @@ finish_file ()
rest_of_decl_compilation (TREE_VALUE (vars), 0, 1, 1);
vars = static_aggregates;
if (static_ctors || vars || exception_table_p ())
if (static_ctors || vars || register_exception_table_p ())
needs_messing_up = 1;
if (static_dtors)
needs_cleaning = 1;
@ -3033,7 +3033,7 @@ finish_file ()
push_momentary ();
expand_start_bindings (0);
if (exception_table_p ())
if (register_exception_table_p ())
register_exception_table ();
while (vars)

View File

@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "except.h"
#include "function.h"
#include "defaults.h"
rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
@ -609,7 +610,8 @@ do_unwind (inner_throw_label)
rtx inner_throw_label;
{
#if defined (SPARC_STACK_ALIGN) /* was sparc */
/* This doesn't work for the flat model sparc, I bet. */
/* This doesn't work for the flat model sparc, nor does it need to
as the default unwinder is only used to unwind non-flat frames. */
tree fcall;
tree params;
rtx next_pc;
@ -704,6 +706,7 @@ do_unwind (inner_throw_label)
void
expand_builtin_throw ()
{
#ifndef DWARF2_UNWIND_INFO
tree fcall;
tree params;
rtx handler;
@ -897,6 +900,7 @@ expand_builtin_throw ()
pop_momentary ();
finish_function (lineno, 0, 0);
#endif /* DWARF2_UNWIND_INFO */
}
@ -1149,7 +1153,6 @@ expand_throw (exp)
expand_expr (object, const0_rtx, VOIDmode, 0);
end_anon_func ();
mark_addressable (cleanup);
}
if (cleanup == empty_fndecl)

View File

@ -1185,29 +1185,28 @@ arrays. Exception specifications are now handled. Thrown objects are
now cleaned up all the time. We can now tell if we have an active
exception being thrown or not (__eh_type != 0). We use this to call
terminate if someone does a throw; without there being an active
exception object. uncaught_exception () works.
exception object. uncaught_exception () works. Exception handling
should work right if you optimize. Exception handling should work with
-fpic or -fPIC.
The below points out some flaws in g++'s exception handling, as it now
stands.
Only exact type matching or reference matching of throw types works when
-fno-rtti is used. Only works on a SPARC (like Suns), SPARClite, i386,
arm, rs6000, PowerPC, Alpha, mips, VAX, m68k and z8k machines. Partial
support is in for all other machines, but a stack unwinder called
__unwind_function has to be written, and added to libgcc2 for them. The
new EH code doesn't rely upon the __unwind_function for C++ code,
instead it creates per function unwinders right inside the function,
unfortunately, on many platforms the definition of RETURN_ADDR_RTX in
the tm.h file for the machine port is wrong. The HPPA has a brain dead
abi that prevents exception handling from just working. See below for
details on __unwind_function. Don't expect exception handling to work
right if you optimize, in fact the compiler will probably core dump.
RTL_EXPRs for EH cond variables for && and || exprs should probably be
wrapped in UNSAVE_EXPRs, and RTL_EXPRs tweaked so that they can be
unsaved, and the UNSAVE_EXPR code should be in the backend, or
alternatively, UNSAVE_EXPR should be ripped out and exactly one
finalization allowed to be expanded by the backend. I talked with
kenner about this, and we have to allow multiple expansions.
-fno-rtti is used. Only works on a SPARC (like Suns) (both -mflat and
-mno-flat models work), SPARClite, Hitachi SH, i386, arm, rs6000,
PowerPC, Alpha, mips, VAX, m68k and z8k machines. SPARC v9 may not
work. HPPA is mostly done, but throwing between a shared library and
user code doesn't yet work. Some targets have support for data-driven
unwinding. Partial support is in for all other machines, but a stack
unwinder called __unwind_function has to be written, and added to
libgcc2 for them. The new EH code doesn't rely upon the
__unwind_function for C++ code, instead it creates per function
unwinders right inside the function, unfortunately, on many platforms
the definition of RETURN_ADDR_RTX in the tm.h file for the machine port
is wrong. See below for details on __unwind_function. RTL_EXPRs for EH
cond variables for && and || exprs should probably be wrapped in
UNSAVE_EXPRs, and RTL_EXPRs tweaked so that they can be unsaved.
We only do pointer conversions on exception matching a la 15.3 p2 case
3: `A handler with type T, const T, T&, or const T& is a match for a
@ -1397,6 +1396,33 @@ things: first, a way to figure out where the frame pointer was stored,
and second, a functional @code{__builtin_return_address} implementation
for except.c to be able to use it.
Or just support DWARF 2 unwind info.
@subsection New Backend Exception Support
This subsection discusses various aspects of the design of the
data-driven model being implemented for the exception handling backend.
The goal is to generate enough data during the compilation of user code,
such that we can dynamically unwind through functions at run time with a
single routine (@code{__throw}) that lives in libgcc.a, built by the
compiler, and dispatch into associated exception handlers.
This information is generated by the DWARF 2 debugging backend, and
includes all of the information __throw needs to unwind an arbitrary
frame. It specifies where all of the saved registers and the return
address can be found at any point in the function.
Major disadvantages when enabling exceptions are:
@itemize @bullet
@item
Code that uses caller saved registers, can't, when flow can be
transfered into that code from an exception handler. In high performace
code this should not usually be true, so the effects should be minimal.
@end itemize
@subsection Backend Exception Support
The backend must be extended to fully support exceptions. Right now

View File

@ -52,6 +52,7 @@ Boston, MA 02111-1307, USA. */
do not apply. */
#include "tm.h"
#include "defaults.h"
/* Provide default definitions for the pseudo-ops used to switch to the
.ctors and .dtors sections.
@ -75,6 +76,9 @@ Boston, MA 02111-1307, USA. */
#ifndef DTORS_SECTION_ASM_OP
#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\""
#endif
#if !defined (EH_FRAME_SECTION_ASM_OP) && defined (DWARF2_UNWIND_INFO) && defined(ASM_OUTPUT_SECTION_NAME)
#define EH_FRAME_SECTION_ASM_OP ".section\t.eh_frame,\"aw\""
#endif
#ifdef OBJECT_FORMAT_ELF
@ -118,6 +122,7 @@ typedef void (*func_ptr) (void);
the list we left off processing, and we resume at that point,
should we be re-invoked. */
static char __EH_FRAME_BEGIN__[];
static func_ptr __DTOR_LIST__[];
static void
__do_global_dtors_aux ()
@ -128,6 +133,10 @@ __do_global_dtors_aux ()
p++;
(*(p-1)) ();
}
#ifdef EH_FRAME_SECTION_ASM_OP
__deregister_frame (__EH_FRAME_BEGIN__);
#endif
}
/* Stick a call to __do_global_dtors_aux into the .fini section. */
@ -143,6 +152,29 @@ fini_dummy ()
asm (TEXT_SECTION_ASM_OP);
}
#ifdef EH_FRAME_SECTION_ASM_OP
/* Stick a call to __register_frame into the .init section. For some reason
calls with no arguments work more reliably in .init, so stick the call
in another function. */
static void
frame_dummy ()
{
__register_frame (__EH_FRAME_BEGIN__);
}
static void
init_dummy ()
{
asm (INIT_SECTION_ASM_OP);
frame_dummy ();
#ifdef FORCE_INIT_SECTION_ALIGN
FORCE_INIT_SECTION_ALIGN;
#endif
asm (TEXT_SECTION_ASM_OP);
}
#endif /* EH_FRAME_SECTION_ASM_OP */
#else /* OBJECT_FORMAT_ELF */
/* The function __do_global_ctors_aux is compiled twice (once in crtbegin.o
@ -200,7 +232,9 @@ __do_global_ctors_aux () /* prologue goes in .init section */
#ifdef HAS_INIT_SECTION
/* This case is used by the Irix 6 port, which supports named sections but
not an SVR4-style .fini section. __do_global_dtors can be non-static
in this case because the -fini switch to ld binds strongly. */
in this case because we protect it with -hidden_symbol. */
static char __EH_FRAME_BEGIN__[];
static func_ptr __DTOR_LIST__[];
void
__do_global_dtors ()
@ -208,6 +242,10 @@ __do_global_dtors ()
func_ptr *p;
for (p = __DTOR_LIST__ + 1; *p; p++)
(*p) ();
#ifdef EH_FRAME_SECTION_ASM_OP
__deregister_frame (__EH_FRAME_BEGIN__);
#endif
}
#endif
@ -244,6 +282,17 @@ asm (DTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
STATIC func_ptr __DTOR_LIST__[1] = { (func_ptr) (-1) };
#endif
#ifdef EH_FRAME_SECTION_ASM_OP
/* Stick a label at the beginning of the frame unwind info so we can register
and deregister it with the exception handling library code. */
asm (EH_FRAME_SECTION_ASM_OP);
#ifdef INIT_SECTION_ASM_OP
STATIC
#endif
char __EH_FRAME_BEGIN__[] = { };
#endif /* EH_FRAME_SECTION_ASM_OP */
#endif /* defined(CRT_BEGIN) */
#ifdef CRT_END
@ -327,12 +376,16 @@ __do_global_ctors_aux () /* prologue goes in .text section */
#ifdef HAS_INIT_SECTION
/* This case is used by the Irix 6 port, which supports named sections but
not an SVR4-style .init section. __do_global_ctors can be non-static
in this case because the -init switch to ld binds strongly. */
in this case because we protect it with -hidden_symbol. */
extern char __EH_FRAME_BEGIN__[];
static func_ptr __CTOR_END__[];
void
__do_global_ctors ()
{
func_ptr *p;
#ifdef EH_FRAME_SECTION_ASM_OP
__register_frame (__EH_FRAME_BEGIN__);
#endif
for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
(*p) ();
}
@ -363,4 +416,13 @@ asm (DTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
STATIC func_ptr __DTOR_END__[1] = { (func_ptr) 0 };
#endif
#ifdef EH_FRAME_SECTION_ASM_OP
/* Terminate the frame unwind info section with a 4byte 0 as a sentinel;
this would be the 'length' field in a real FDE. */
typedef unsigned int ui32 __attribute__ ((mode (SI)));
asm (EH_FRAME_SECTION_ASM_OP);
STATIC ui32 __FRAME_END__[] = { 0 };
#endif /* EH_FRAME_SECTION */
#endif /* defined(CRT_END) */

View File

@ -136,6 +136,6 @@ do { fprintf (FILE, "\t%s\t", ASM_LONG); \
/* If we have a definition of INCOMING_RETURN_ADDR_RTX, assume that
the rest of the DWARF 2 frame unwind support is also provided. */
#ifdef INCOMING_RETURN_ADDR_RTX
#define DWARF2_UNWIND_INFO
#if !defined (DWARF2_UNWIND_INFO) && defined (INCOMING_RETURN_ADDR_RTX)
#define DWARF2_UNWIND_INFO 1
#endif

View File

@ -496,7 +496,8 @@ enum dwarf_call_frame_info
DW_CFA_MIPS_advance_loc8 = 0x1d,
/* GNU extensions */
DW_CFA_GNU_window_save = 0x2d
DW_CFA_GNU_window_save = 0x2d,
DW_CFA_GNU_args_size = 0x2e
};
#define DW_CIE_ID 0xffffffff

View File

@ -20,19 +20,15 @@ You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "defaults.h"
/* The first part of this file deals with the DWARF 2 frame unwind
information, which is also used by the GCC efficient exception handling
mechanism. The second part, controlled only by an #ifdef
DWARF2_DEBUGGING_INFO, deals with the other DWARF 2 debugging
information. */
#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
#include "config.h"
#include "defaults.h"
#include <stdio.h>
#include <setjmp.h>
#include "dwarf2.h"
#include "tree.h"
#include "flags.h"
@ -48,6 +44,21 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* #define NDEBUG 1 */
#include "assert.h"
/* Decide whether we want to emit frame unwind information for the current
translation unit. */
int
dwarf2out_do_frame ()
{
return (write_symbols == DWARF2_DEBUG
#ifdef DWARF2_UNWIND_INFO
|| (flag_exceptions && ! exceptions_via_longjmp)
#endif
);
}
#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
#ifndef __GNUC__
#define inline
#endif
@ -191,6 +202,7 @@ static unsigned reg_number PROTO((rtx));
Theses may be overridden in the tm.h file (if necessary) for a particular
assembler. */
#ifdef OBJECT_FORMAT_ELF
#ifndef UNALIGNED_SHORT_ASM_OP
#define UNALIGNED_SHORT_ASM_OP ".2byte"
#endif
@ -200,20 +212,12 @@ static unsigned reg_number PROTO((rtx));
#ifndef UNALIGNED_DOUBLE_INT_ASM_OP
#define UNALIGNED_DOUBLE_INT_ASM_OP ".8byte"
#endif
#endif /* OBJECT_FORMAT_ELF */
#ifndef ASM_BYTE_OP
#define ASM_BYTE_OP ".byte"
#endif
#ifndef UNALIGNED_OFFSET_ASM_OP
#define UNALIGNED_OFFSET_ASM_OP \
(DWARF_OFFSET_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
#endif
#ifndef UNALIGNED_WORD_ASM_OP
#define UNALIGNED_WORD_ASM_OP \
(PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
#endif
/* Data and reference forms for relocatable data. */
#define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4)
#define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4)
@ -238,9 +242,6 @@ static unsigned reg_number PROTO((rtx));
#ifndef FRAME_SECTION
#define FRAME_SECTION ".debug_frame"
#endif
#if !defined (EH_FRAME_SECTION) && defined (ASM_OUTPUT_SECTION_NAME)
#define EH_FRAME_SECTION ".eh_frame"
#endif
#ifndef FUNC_BEGIN_LABEL
#define FUNC_BEGIN_LABEL "LFB"
@ -262,6 +263,23 @@ static unsigned reg_number PROTO((rtx));
fprintf ((FILE), SECTION_FORMAT, SECTION_ASM_OP, SECTION)
#endif
#ifndef ASM_OUTPUT_DWARF_DATA1
#define ASM_OUTPUT_DWARF_DATA1(FILE,VALUE) \
fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, VALUE)
#endif
#ifdef UNALIGNED_INT_ASM_OP
#ifndef UNALIGNED_OFFSET_ASM_OP
#define UNALIGNED_OFFSET_ASM_OP \
(DWARF_OFFSET_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
#endif
#ifndef UNALIGNED_WORD_ASM_OP
#define UNALIGNED_WORD_ASM_OP \
(PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
#endif
#ifndef ASM_OUTPUT_DWARF_DELTA2
#define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2) \
do { fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP); \
@ -317,11 +335,6 @@ static unsigned reg_number PROTO((rtx));
} while (0)
#endif
#ifndef ASM_OUTPUT_DWARF_DATA1
#define ASM_OUTPUT_DWARF_DATA1(FILE,VALUE) \
fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, VALUE)
#endif
#ifndef ASM_OUTPUT_DWARF_DATA2
#define ASM_OUTPUT_DWARF_DATA2(FILE,VALUE) \
fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, (unsigned) VALUE)
@ -360,6 +373,43 @@ static unsigned reg_number PROTO((rtx));
} while (0)
#endif
#else /* UNALIGNED_INT_ASM_OP */
/* We don't have unaligned support, let's hope the normal output works for
.debug_frame. */
#define ASM_OUTPUT_DWARF_ADDR(FILE,LABEL) \
assemble_integer (gen_rtx (SYMBOL_REF, Pmode, LABEL), PTR_SIZE, 1)
#define ASM_OUTPUT_DWARF_OFFSET(FILE,LABEL) \
assemble_integer (gen_rtx (SYMBOL_REF, SImode, LABEL), 4, 1)
#define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2) \
assemble_integer (gen_rtx (MINUS, HImode, \
gen_rtx (SYMBOL_REF, Pmode, LABEL1), \
gen_rtx (SYMBOL_REF, Pmode, LABEL2)), \
2, 1)
#define ASM_OUTPUT_DWARF_DELTA4(FILE,LABEL1,LABEL2) \
assemble_integer (gen_rtx (MINUS, SImode, \
gen_rtx (SYMBOL_REF, Pmode, LABEL1), \
gen_rtx (SYMBOL_REF, Pmode, LABEL2)), \
4, 1)
#define ASM_OUTPUT_DWARF_ADDR_DELTA(FILE,LABEL1,LABEL2) \
assemble_integer (gen_rtx (MINUS, Pmode, \
gen_rtx (SYMBOL_REF, Pmode, LABEL1), \
gen_rtx (SYMBOL_REF, Pmode, LABEL2)), \
PTR_SIZE, 1)
#define ASM_OUTPUT_DWARF_DELTA(FILE,LABEL1,LABEL2) \
ASM_OUTPUT_DWARF_DELTA4 (FILE,LABEL1,LABEL2)
#define ASM_OUTPUT_DWARF_DATA4(FILE,VALUE) \
assemble_integer (GEN_INT (VALUE), 4, 1)
#endif /* UNALIGNED_INT_ASM_OP */
/* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
newline is produced. When flag_verbose_asm is asserted, we add commnetary
at the end of the line, so we must avoid output of a newline here. */
@ -404,6 +454,14 @@ static unsigned reg_number PROTO((rtx));
#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
#endif
/* Hook used by __throw. */
rtx
expand_builtin_dwarf_fp_regnum ()
{
return GEN_INT (DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM));
}
/* The offset from the incoming value of %sp to the top of the stack frame
for the current function. */
#ifndef INCOMING_FRAME_SP_OFFSET
@ -497,6 +555,8 @@ dwarf_cfi_name (cfi_opc)
/* GNU extensions */
case DW_CFA_GNU_window_save:
return "DW_CFA_GNU_window_save";
case DW_CFA_GNU_args_size:
return "DW_CFA_GNU_args_size";
default:
return "DW_CFA_<unknown>";
@ -638,6 +698,9 @@ static long cfa_offset;
static unsigned cfa_store_reg;
static long cfa_store_offset;
/* The running total of the size of arguments pushed onto the stack. */
static long args_size;
/* Entry point to update the canonical frame address (CFA).
LABEL is passed to add_fde_cfi. The value of CFA is now to be
calculated from REG+OFFSET. */
@ -743,6 +806,20 @@ dwarf2out_window_save (label)
add_fde_cfi (label, cfi);
}
/* Add a CFI to update the running total of the size of arguments
pushed onto the stack. */
void
dwarf2out_args_size (label, size)
char *label;
long size;
{
register dw_cfi_ref cfi = new_cfi ();
cfi->dw_cfi_opc = DW_CFA_GNU_args_size;
cfi->dw_cfi_oprnd1.dw_cfi_offset = size;
add_fde_cfi (label, cfi);
}
/* Entry point for saving a register to the stack. REG is the GCC register
number. LABEL and OFFSET are passed to reg_save. */
@ -828,6 +905,67 @@ initial_return_save (rtl)
reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa_offset);
}
/* Check INSN to see if it looks like a push or a stack adjustment, and
make a note of it if it does. EH uses this information to find out how
much extra space it needs to pop off the stack. */
static void
dwarf2out_stack_adjust (insn)
rtx insn;
{
rtx src, dest;
enum rtx_code code;
long offset;
char *label;
if (GET_CODE (insn) != SET)
return;
src = SET_SRC (insn);
dest = SET_DEST (insn);
if (dest == stack_pointer_rtx)
{
/* (set (reg sp) (plus (reg sp) (const_int))) */
code = GET_CODE (src);
if (! (code == PLUS || code == MINUS)
|| XEXP (src, 0) != stack_pointer_rtx
|| GET_CODE (XEXP (src, 1)) != CONST_INT)
return;
offset = INTVAL (XEXP (src, 1));
}
else if (GET_CODE (dest) == MEM)
{
/* (set (mem (pre_dec (reg sp))) (foo)) */
src = XEXP (dest, 0);
code = GET_CODE (src);
if (! (code == PRE_DEC || code == PRE_INC)
|| XEXP (src, 0) != stack_pointer_rtx)
return;
offset = GET_MODE_SIZE (GET_MODE (dest));
}
else
return;
if (code == PLUS || code == PRE_INC)
offset = -offset;
if (cfa_reg == STACK_POINTER_REGNUM)
cfa_offset += offset;
#ifndef STACK_GROWS_DOWNWARD
offset = -offset;
#endif
args_size += offset;
if (args_size < 0)
args_size = 0;
label = dwarf2out_cfi_label ();
dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
dwarf2out_args_size (label, args_size);
}
/* Record call frame debugging information for INSN, which either
sets SP or FP (adjusting how we calculate the frame address) or saves a
register to the stack. If INSN is NULL_RTX, initialize our state. */
@ -857,6 +995,12 @@ dwarf2out_frame_debug (insn)
return;
}
if (! RTX_FRAME_RELATED_P (insn))
{
dwarf2out_stack_adjust (PATTERN (insn));
return;
}
label = dwarf2out_cfi_label ();
insn = PATTERN (insn);
@ -903,13 +1047,21 @@ dwarf2out_frame_debug (insn)
abort ();
}
if (XEXP (src, 0) == hard_frame_pointer_rtx)
{
/* Restoring SP from FP in the epilogue. */
assert (cfa_reg == HARD_FRAME_POINTER_REGNUM);
cfa_reg = STACK_POINTER_REGNUM;
}
else
assert (XEXP (src, 0) == stack_pointer_rtx);
if (GET_CODE (src) == PLUS)
offset = -offset;
if (cfa_reg == STACK_POINTER_REGNUM)
cfa_offset += offset;
if (cfa_store_reg == STACK_POINTER_REGNUM)
cfa_store_offset += offset;
assert (XEXP (src, 0) == stack_pointer_rtx);
}
else
{
@ -953,7 +1105,7 @@ dwarf2out_frame_debug (insn)
case PRE_INC:
case PRE_DEC:
offset = GET_MODE_SIZE (GET_MODE (dest));
if (GET_CODE (src) == PRE_INC)
if (GET_CODE (XEXP (dest, 0)) == PRE_INC)
offset = -offset;
assert (REGNO (XEXP (XEXP (dest, 0), 0)) == STACK_POINTER_REGNUM);
@ -1196,12 +1348,29 @@ output_cfi (cfi, fde)
break;
case DW_CFA_GNU_window_save:
break;
case DW_CFA_GNU_args_size:
output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset);
fputc ('\n', asm_out_file);
break;
default:
break;
}
}
}
#if !defined (EH_FRAME_SECTION)
#if defined (EH_FRAME_SECTION_ASM_OP)
#define EH_FRAME_SECTION() eh_frame_section();
#else
#if defined (ASM_OUTPUT_SECTION_NAME)
#define EH_FRAME_SECTION() \
do { \
named_section (NULL_TREE, ".eh_frame", 0); \
} while (0)
#endif
#endif
#endif
/* Output the call frame information used to used to record information
that relates to calculating the frame pointer, and records the
location of saved registers. */
@ -1231,9 +1400,13 @@ output_call_frame_info (for_eh)
if (for_eh)
{
#ifdef EH_FRAME_SECTION
ASM_OUTPUT_SECTION_NAME (asm_out_file, NULL_TREE, EH_FRAME_SECTION, 0);
EH_FRAME_SECTION ();
#else
tree label = (tree) get_file_function_name ('F');
data_section ();
ASM_GLOBALIZE_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
#endif
assemble_label ("__FRAME_BEGIN__");
}
@ -1272,9 +1445,9 @@ output_call_frame_info (for_eh)
fputc ('\n', asm_out_file);
if (eh_ptr)
{
/* The "z" augmentation was defined by SGI; the FDE contains a pointer
/* The FDE contains a pointer
to the exception region info for the frame. */
ASM_OUTPUT_DWARF_STRING (asm_out_file, "z");
ASM_OUTPUT_DWARF_STRING (asm_out_file, "e");
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s CIE Augmentation", ASM_COMMENT_START);
}
@ -1302,14 +1475,6 @@ output_call_frame_info (for_eh)
fprintf (asm_out_file, "\t%s CIE RA Column", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
if (eh_ptr)
{
output_uleb128 (0);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s CIE augmentation fields length",
ASM_COMMENT_START);
fputc ('\n', asm_out_file);
}
for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
output_cfi (cfi, NULL);
@ -1355,19 +1520,9 @@ output_call_frame_info (for_eh)
fputc ('\n', asm_out_file);
if (eh_ptr)
{
output_uleb128 (PTR_SIZE);
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s FDE augmentation fields length",
ASM_COMMENT_START);
fputc ('\n', asm_out_file);
/* For now, a pointer to the translation unit's info will do.
??? Eventually this should point to the function's info. */
if (exception_table_p ())
ASM_OUTPUT_DWARF_ADDR (asm_out_file, "__EXCEPTION_TABLE__");
else
ASM_OUTPUT_DWARF_ADDR_DATA (asm_out_file, 0);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, "__EXCEPTION_TABLE__");
if (flag_verbose_asm)
fprintf (asm_out_file, "\t%s pointer to exception region info",
ASM_COMMENT_START);
@ -1399,16 +1554,6 @@ output_call_frame_info (for_eh)
#endif
}
/* Decide whether we want to emit frame unwind information for the current
translation unit. */
int
dwarf2out_do_frame ()
{
return (write_symbols == DWARF2_DEBUG
|| (flag_exceptions && ! exceptions_via_longjmp));
}
/* Output a marker (i.e. a label) for the beginning of a function, before
the prologue. */
@ -1443,6 +1588,8 @@ dwarf2out_begin_prologue ()
fde->dw_fde_current_label = NULL;
fde->dw_fde_end = NULL;
fde->dw_fde_cfi = NULL;
args_size = 0;
}
/* Output a marker (i.e. a label) for the absolute end of the generated code
@ -9142,10 +9289,6 @@ dwarf2out_init (asm_out_file, main_input_filename)
gen_compile_unit_die (main_input_filename);
ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
/* Initialize the frame unwind information. Eventually this should be
called from compile_file instead. */
dwarf2out_frame_init ();
}
/* Output stuff that dwarf requires at the end of every file,
@ -9202,10 +9345,6 @@ dwarf2out_finish ()
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BSS_END_LABEL, 0);
#endif
/* Output the frame unwind information. Eventually this should be called
from compile_file instead. */
dwarf2out_frame_finish ();
/* Output the source line correspondence table. */
if (line_info_table_in_use > 1 || separate_line_info_table_in_use)
{

View File

@ -281,3 +281,15 @@ extern int protect_cleanup_actions_with_terminate;
#ifdef TREE_CODE
extern tree protect_with_terminate PROTO((tree));
#endif
/* Various hooks for the DWARF 2 __throw routine. */
void expand_builtin_unwind_init PROTO((void));
rtx expand_builtin_dwarf_fp_regnum PROTO((void));
rtx expand_builtin_eh_stub PROTO((void));
#ifdef TREE_CODE
rtx expand_builtin_frob_return_addr PROTO((tree));
rtx expand_builtin_extract_return_addr PROTO((tree));
void expand_builtin_set_return_addr_reg PROTO((tree));
void expand_builtin_set_eh_regs PROTO((tree, tree));
#endif

View File

@ -955,9 +955,9 @@ final_start_function (first, file, optimize)
last_linenum = high_block_linenum = high_function_linenum
= NOTE_LINE_NUMBER (first);
#ifdef DWARF2_DEBUGGING_INFO
#if defined (DWARF2_UNWIND_INFO)
/* Output DWARF definition of the function. */
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
dwarf2out_begin_prologue ();
#endif
@ -992,6 +992,11 @@ final_start_function (first, file, optimize)
profile_function (file);
#endif /* PROFILE_BEFORE_PROLOGUE */
#if defined (DWARF2_UNWIND_INFO) && defined (HAVE_prologue)
if (dwarf2out_do_frame ())
dwarf2out_frame_debug (NULL_RTX);
#endif
#ifdef FUNCTION_PROLOGUE
/* First output the function prologue: code to set up the stack frame. */
FUNCTION_PROLOGUE (file, get_frame_size ());
@ -1142,8 +1147,8 @@ final_end_function (first, file, optimize)
dwarfout_end_epilogue ();
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
#if defined (DWARF2_UNWIND_INFO)
if (dwarf2out_do_frame ())
dwarf2out_end_epilogue ();
#endif
@ -1265,11 +1270,6 @@ final (first, file, optimize, prescan)
last_ignored_compare = 0;
new_block = 1;
#if defined (DWARF2_DEBUGGING_INFO) && defined (HAVE_prologue)
if (write_symbols == DWARF2_DEBUG)
dwarf2out_frame_debug (NULL_RTX);
#endif
check_exception_handler_labels ();
/* Make a map indicating which line numbers appear in this function.
@ -2171,12 +2171,21 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
output_asm_insn (template, recog_operand);
#if defined (DWARF2_DEBUGGING_INFO) && defined (HAVE_prologue)
#if defined (DWARF2_UNWIND_INFO)
#if !defined (ACCUMULATE_OUTGOING_ARGS)
/* If we push arguments, we need to check all insns for stack
adjustments. */
if (dwarf2out_do_frame ())
dwarf2out_frame_debug (insn);
#else
#if defined (HAVE_prologue)
/* If this insn is part of the prologue, emit DWARF v2
call frame info. */
if (write_symbols == DWARF2_DEBUG && RTX_FRAME_RELATED_P (insn))
if (RTX_FRAME_RELATED_P (insn) && dwarf2out_do_frame ())
dwarf2out_frame_debug (insn);
#endif
#endif
#endif
#if 0
/* It's not at all clear why we did this and doing so interferes

607
gcc/frame.c Normal file
View File

@ -0,0 +1,607 @@
/* Subroutines needed for unwinding stack frames for exception handling. */
/* Compile this one with gcc. */
/* Copyright (C) 1997 Free Software Foundation, Inc.
Contributed by Jason Merrill <jason@cygnus.com>.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* As a special exception, if you link this library with other files,
some of which are compiled with GCC, to produce an executable,
this library does not by itself cause the resulting executable
to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why
the executable file might be covered by the GNU General Public License. */
/* It is incorrect to include config.h here, because this file is being
compiled for the target, and hence definitions concerning only the host
do not apply. */
#include "tconfig.h"
#include "defaults.h"
#ifdef DWARF2_UNWIND_INFO
#include "dwarf2.h"
#include "frame.h"
#include <stddef.h>
/* Don't use `fancy_abort' here even if config.h says to use it. */
#ifdef abort
#undef abort
#endif
/* Some types used by the DWARF 2 spec. */
typedef unsigned int uword __attribute__ ((mode (SI)));
typedef unsigned int uaddr __attribute__ ((mode (pointer)));
typedef int saddr __attribute__ ((mode (pointer)));
typedef unsigned char ubyte;
/* The first few fields of a CIE. The CIE_id field is 0xffffffff for a CIE,
to distinguish it from a valid FDE. FDEs are aligned to an addressing
unit boundary, but the fields within are unaligned. */
struct dwarf_cie {
uword length;
uaddr CIE_id;
ubyte version;
char augmentation[0];
} __attribute__ ((packed, aligned (__alignof__ (void *))));
/* The first few fields of an FDE. */
struct dwarf_fde {
uword length;
struct dwarf_cie* CIE_pointer;
void* pc_begin;
uaddr pc_range;
} __attribute__ ((packed, aligned (__alignof__ (void *))));
typedef struct dwarf_fde fde;
/* The representation for an "object" to be searched for frame unwind info.
For targets with named sections, one object is an executable or shared
library; for other targets, one object is one translation unit. */
struct object {
void *pc_begin;
void *pc_end;
fde *fde_begin;
fde ** fde_array;
size_t count;
struct object *next;
};
static struct object *objects;
/* The information we care about from a CIE. */
struct cie_info {
char *augmentation;
int code_align;
int data_align;
unsigned ra_regno;
};
/* The current unwind state, plus a saved copy for DW_CFA_remember_state. */
struct frame_state_internal
{
struct frame_state s;
struct frame_state_internal *saved_state;
};
/* Decode the unsigned LEB128 constant at BUF into the variable pointed to
by R, and return the new value of BUF. */
static void *
decode_uleb128 (unsigned char *buf, unsigned *r)
{
unsigned shift = 0;
unsigned result = 0;
while (1)
{
unsigned byte = *buf++;
result |= (byte & 0x7f) << shift;
if ((byte & 0x80) == 0)
break;
shift += 7;
}
*r = result;
return buf;
}
/* Decode the signed LEB128 constant at BUF into the variable pointed to
by R, and return the new value of BUF. */
static void *
decode_sleb128 (unsigned char *buf, int *r)
{
unsigned shift = 0;
unsigned result = 0;
unsigned byte;
while (1)
{
byte = *buf++;
result |= (byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
break;
}
if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0)
result |= - (1 << shift);
*r = result;
return buf;
}
/* Read unaligned data from the instruction buffer. */
union unaligned {
void *p;
unsigned b2 __attribute__ ((mode (HI)));
unsigned b4 __attribute__ ((mode (SI)));
unsigned b8 __attribute__ ((mode (DI)));
} __attribute__ ((packed));
static inline void *
read_pointer (void *p)
{ union unaligned *up = p; return up->p; }
static inline unsigned
read_1byte (void *p)
{ return *(unsigned char *)p; }
static inline unsigned
read_2byte (void *p)
{ union unaligned *up = p; return up->b2; }
static inline unsigned
read_4byte (void *p)
{ union unaligned *up = p; return up->b4; }
static inline unsigned long
read_8byte (void *p)
{ union unaligned *up = p; return up->b8; }
/* Ordering function for FDEs. Functions can't overlap, so we just compare
their starting addresses. */
static inline saddr
fde_compare (fde *x, fde *y)
{
return (saddr)x->pc_begin - (saddr)y->pc_begin;
}
/* Return the address of the FDE after P. */
static inline fde *
next_fde (fde *p)
{
return (fde *)(((char *)p) + p->length + sizeof (p->length));
}
/* One iteration of an insertion sort, for adding new FDEs to the array.
Usually the new FDE will go in at the end, so we can expect close to
O(n) performance. If this turns out to be overly optimistic, we can have
the linker sort the FDEs so we don't have to do it at run time. */
static void
fde_insert (fde **array, size_t i, fde *this_fde)
{
array[i] = this_fde;
for (; i > 0 && fde_compare (array[i], array[i-1]) < 0; --i)
{
this_fde = array[i];
array[i] = array[i-1];
array[i-1] = this_fde;
}
}
static size_t
count_fdes (fde *this_fde)
{
size_t count;
for (count = 0; this_fde->length != 0; this_fde = next_fde (this_fde))
{
/* Skip CIEs. */
if ((uaddr)(this_fde->CIE_pointer) == (uaddr)-1)
continue;
++count;
}
return count;
}
static void
add_fdes (fde *this_fde, fde **array, size_t *i_ptr,
void **beg_ptr, void **end_ptr)
{
size_t i = *i_ptr;
void *pc_begin = *beg_ptr;
void *pc_end = *end_ptr;
for (; this_fde->length != 0; this_fde = next_fde (this_fde))
{
/* Skip CIEs. */
if ((uaddr)(this_fde->CIE_pointer) == (uaddr)-1)
continue;
fde_insert (array, i++, this_fde);
if (this_fde->pc_begin < pc_begin)
pc_begin = this_fde->pc_begin;
if (this_fde->pc_begin + this_fde->pc_range > pc_end)
pc_end = this_fde->pc_begin + this_fde->pc_range;
}
*i_ptr = i;
*beg_ptr = pc_begin;
*end_ptr = pc_end;
}
/* Set up a sorted array of pointers to FDEs for a loaded object. We
count up the entries before allocating the array because it's likely to
be faster. */
static void
frame_init (struct object* ob)
{
fde *this_fde;
size_t count;
fde **array;
void *pc_begin, *pc_end;
if (ob->fde_array)
{
fde **p = ob->fde_array;
for (count = 0; *p; ++p)
count += count_fdes (*p);
}
else
count = count_fdes (ob->fde_begin);
ob->count = count;
array = (fde **) malloc (sizeof (fde *) * count);
pc_begin = (void*)(uaddr)-1;
pc_end = 0;
count = 0;
if (ob->fde_array)
{
fde **p = ob->fde_array;
for (; *p; ++p)
add_fdes (*p, array, &count, &pc_begin, &pc_end);
}
else
add_fdes (ob->fde_begin, array, &count, &pc_begin, &pc_end);
ob->fde_array = array;
ob->pc_begin = pc_begin;
ob->pc_end = pc_end;
}
/* Return a pointer to the FDE for the function containing PC. */
static fde *
find_fde (void *pc)
{
struct object *ob;
size_t lo, hi;
for (ob = objects; ob; ob = ob->next)
{
if (ob->pc_begin == 0)
frame_init (ob);
if (pc >= ob->pc_begin && pc < ob->pc_end)
break;
}
if (ob == 0)
return 0;
/* Standard binary search algorithm. */
for (lo = 0, hi = ob->count; lo < hi; )
{
size_t i = (lo + hi) / 2;
fde *f = ob->fde_array[i];
if (pc < f->pc_begin)
hi = i;
else if (pc > f->pc_begin + f->pc_range)
lo = i + 1;
else
return f;
}
return 0;
}
/* Extract any interesting information from the CIE for the translation
unit F belongs to. */
static void *
extract_cie_info (fde *f, struct cie_info *c)
{
void *p;
int i;
c->augmentation = f->CIE_pointer->augmentation;
if (strcmp (c->augmentation, "") != 0
&& strcmp (c->augmentation, "e") != 0
&& c->augmentation[0] != 'z')
return 0;
p = c->augmentation + strlen (c->augmentation) + 1;
p = decode_uleb128 (p, &c->code_align);
p = decode_sleb128 (p, &c->data_align);
c->ra_regno = *(unsigned char *)p++;
/* If the augmentation starts with 'z', we now see the length of the
augmentation fields. */
if (c->augmentation[0] == 'z')
{
p = decode_uleb128 (p, &i);
p += i;
}
return p;
}
/* Decode one instruction's worth of of DWARF 2 call frame information.
Used by __frame_state_for. Takes pointers P to the instruction to
decode, STATE to the current register unwind information, INFO to the
current CIE information, and PC to the current PC value. Returns a
pointer to the next instruction. */
static void *
execute_cfa_insn (void *p, struct frame_state_internal *state,
struct cie_info *info, void **pc)
{
unsigned insn = *(unsigned char *)p++;
unsigned reg;
int offset;
if (insn & DW_CFA_advance_loc)
*pc += ((insn & 0x3f) * info->code_align);
else if (insn & DW_CFA_offset)
{
reg = (insn & 0x3f);
p = decode_uleb128 (p, &offset);
offset *= info->data_align;
state->s.saved[reg] = REG_SAVED_OFFSET;
state->s.reg_or_offset[reg] = offset;
}
else if (insn & DW_CFA_restore)
{
reg = (insn & 0x3f);
state->s.saved[reg] = REG_UNSAVED;
}
else switch (insn)
{
case DW_CFA_set_loc:
*pc = read_pointer (p);
p += sizeof (void *);
break;
case DW_CFA_advance_loc1:
*pc += read_1byte (p);
p += 1;
break;
case DW_CFA_advance_loc2:
*pc += read_2byte (p);
p += 2;
break;
case DW_CFA_advance_loc4:
*pc += read_4byte (p);
p += 4;
break;
case DW_CFA_offset_extended:
p = decode_uleb128 (p, &reg);
p = decode_uleb128 (p, &offset);
offset *= info->data_align;
state->s.saved[reg] = REG_SAVED_OFFSET;
state->s.reg_or_offset[reg] = offset;
break;
case DW_CFA_restore_extended:
p = decode_uleb128 (p, &reg);
state->s.saved[reg] = REG_UNSAVED;
break;
case DW_CFA_undefined:
case DW_CFA_same_value:
case DW_CFA_nop:
break;
case DW_CFA_register:
{
unsigned reg2;
p = decode_uleb128 (p, &reg);
p = decode_uleb128 (p, &reg2);
state->s.saved[reg] = REG_SAVED_REG;
state->s.reg_or_offset[reg] = reg2;
}
break;
case DW_CFA_def_cfa:
p = decode_uleb128 (p, &reg);
p = decode_uleb128 (p, &offset);
state->s.cfa_reg = reg;
state->s.cfa_offset = offset;
break;
case DW_CFA_def_cfa_register:
p = decode_uleb128 (p, &reg);
state->s.cfa_reg = reg;
break;
case DW_CFA_def_cfa_offset:
p = decode_uleb128 (p, &offset);
state->s.cfa_offset = offset;
break;
case DW_CFA_remember_state:
{
struct frame_state_internal *save =
(struct frame_state_internal *)
malloc (sizeof (struct frame_state_internal));
memcpy (save, state, sizeof (struct frame_state_internal));
state->saved_state = save;
}
break;
case DW_CFA_restore_state:
{
struct frame_state_internal *save = state->saved_state;
memcpy (state, save, sizeof (struct frame_state_internal));
free (save);
}
break;
/* FIXME: Hardcoded for SPARC register window configuration. */
case DW_CFA_GNU_window_save:
for (reg = 16; reg < 32; ++reg)
{
state->s.saved[reg] = REG_SAVED_OFFSET;
state->s.reg_or_offset[reg] = (reg - 16) * sizeof (void *);
}
break;
case DW_CFA_GNU_args_size:
p = decode_uleb128 (p, &offset);
state->s.args_size = offset;
break;
default:
abort ();
}
return p;
}
/* Called from crtbegin.o to register the unwind info for an object. */
void
__register_frame (void *begin)
{
struct object *ob = (struct object *) malloc (sizeof (struct object));
ob->fde_begin = begin;
ob->pc_begin = ob->pc_end = 0;
ob->fde_array = 0;
ob->count = 0;
ob->next = objects;
objects = ob;
}
/* Similar, but BEGIN is actually a pointer to a table of unwind entries
for different translation units. Called from the file generated by
collect2. */
void
__register_frame_table (void *begin)
{
struct object *ob = (struct object *) malloc (sizeof (struct object));
ob->fde_begin = begin;
ob->fde_array = begin;
ob->pc_begin = ob->pc_end = 0;
ob->count = 0;
ob->next = objects;
objects = ob;
}
/* Called from crtend.o to deregister the unwind info for an object. */
void
__deregister_frame (void *begin)
{
struct object **p = &objects;
while (*p)
{
if ((*p)->fde_begin == begin)
{
struct object *ob = *p;
*p = (*p)->next;
if (ob->fde_array)
free (ob->fde_array);
free (ob);
return;
}
p = &((*p)->next);
}
abort ();
}
/* Called from __throw to find the registers to restore for a given
PC_TARGET. The caller should allocate a local variable of `struct
frame_state' (declared in frame.h) and pass its address to STATE_IN. */
struct frame_state *
__frame_state_for (void *pc_target, struct frame_state *state_in)
{
fde *f;
void *insn, *end, *pc;
struct cie_info info;
struct frame_state_internal state;
f = find_fde (pc_target);
if (f == 0)
return 0;
insn = extract_cie_info (f, &info);
if (insn == 0)
return 0;
memset (&state, 0, sizeof (state));
state.s.retaddr_column = info.ra_regno;
/* First decode all the insns in the CIE. */
end = next_fde ((fde*) f->CIE_pointer);
while (insn < end)
insn = execute_cfa_insn (insn, &state, &info, 0);
insn = ((fde *)f) + 1;
if (info.augmentation[0] == 'z')
{
int i;
insn = decode_uleb128 (insn, &i);
insn += i;
}
else if (strcmp (info.augmentation, "e") == 0)
{
state.s.eh_ptr = read_pointer (insn);
insn += sizeof (void *);
}
/* Then the insns in the FDE up to our target PC. */
end = next_fde (f);
pc = f->pc_begin;
while (insn < end && pc < pc_target)
insn = execute_cfa_insn (insn, &state, &info, &pc);
memcpy (state_in, &state.s, sizeof (state.s));
return state_in;
}
#endif /* DWARF2_UNWIND_INFO */

View File

@ -5987,6 +5987,26 @@ A C expression to output text to mark the end of an exception region.
This macro need not be defined on most platforms.
@findex EXCEPTION_SECTION
@item EXCEPTION_SECTION ()
A C expression to switch to the section in which the main
exception table is to be placed (@pxref{Sections}). The default is a
section named @code{.gcc_except_table} on machines that support named
sections via @code{ASM_OUTPUT_SECTION_NAME}, otherwise if @samp{-fpic}
or @samp{-fPIC} is in effect, the @code{data_section}, otherwise the
@code{readonly_data_section}.
@findex EH_FRAME_SECTION_ASM_OP
@item EH_FRAME_SECTION_ASM_OP
If defined, a C string constant for the assembler operation to switch to
the section for exception handling frame unwind information. If not
defined, GNU CC will provide a default definition if the target supports
named sections. @file{crtstuff.c} uses this macro to switch to the
appropriate section.
You should define this symbol if your target supports DWARF 2 frame
unwind information and the default definition does not work.
@findex OMIT_EH_TABLE
@item OMIT_EH_TABLE ()
A C expression that is nonzero if the normal exception table output
@ -6011,6 +6031,23 @@ for details on when to define this, and how.
@item MASK_RETURN_ADDR
An rtx used to mask the return address found via RETURN_ADDR_RTX, so
that it does not contain any extraneous set bits in it.
@findex DWARF2_UNWIND_INFO
@item DWARF2_UNWIND_INFO
Define this macro to 0 if your target supports DWARF 2 frame unwind
information, but it does not yet work with exception handling.
Otherwise, if your target supports this information (if it defines
@samp{INCOMING_RETURN_ADDR_RTX} and either @samp{UNALIGNED_INT_ASM_OP}
or @samp{OBJECT_FORMAT_ELF}), GCC will provide a default definition of
1.
If this macro is defined to 1, the DWARF 2 unwinder will be the default
exception handling mechanism; otherwise, setjmp/longjmp will be used by
default.
If this macro is defined to anything, the DWARF 2 unwinder will be used
instead of inline unwinders and __unwind_function in the non-setjmp case.
@end table
@node Alignment Output

View File

@ -2463,6 +2463,10 @@ compile_file (name)
if (write_symbols == DWARF_DEBUG)
TIMEVAR (symout_time, dwarfout_init (asm_out_file, main_input_filename));
#endif
#ifdef DWARF2_UNWIND_INFO
if (dwarf2out_do_frame ())
dwarf2out_frame_init ();
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
TIMEVAR (symout_time, dwarf2out_init (asm_out_file, main_input_filename));
@ -2597,8 +2601,7 @@ compile_file (name)
/* Now that all possible functions have been output, we can dump
the exception table. */
if (exception_table_p ())
output_exception_table ();
output_exception_table ();
for (i = 0; i < len; i++)
{
@ -2713,6 +2716,11 @@ compile_file (name)
});
#endif
#ifdef DWARF2_UNWIND_INFO
if (dwarf2out_do_frame ())
dwarf2out_frame_finish ();
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
TIMEVAR (symout_time,

View File

@ -101,6 +101,16 @@ enum built_in_function
BUILT_IN_SETJMP,
BUILT_IN_LONGJMP,
/* Various hooks for the DWARF 2 __throw routine. */
BUILT_IN_FP, BUILT_IN_SP,
BUILT_IN_UNWIND_INIT,
BUILT_IN_DWARF_FP_REGNUM,
BUILT_IN_FROB_RETURN_ADDR,
BUILT_IN_EXTRACT_RETURN_ADDR,
BUILT_IN_SET_RETURN_ADDR_REG,
BUILT_IN_EH_STUB,
BUILT_IN_SET_EH_REGS,
/* C++ extensions */
BUILT_IN_NEW,
BUILT_IN_VEC_NEW,

View File

@ -170,6 +170,9 @@ static enum in_section { no_section, in_text, in_data, in_named
#ifdef BSS_SECTION_ASM_OP
, in_bss
#endif
#ifdef EH_FRAME_SECTION_ASM_OP
, in_eh_frame
#endif
#ifdef EXTRA_SECTIONS
, EXTRA_SECTIONS
#endif
@ -401,6 +404,18 @@ asm_output_aligned_bss (file, decl, name, size, align)
#endif /* BSS_SECTION_ASM_OP */
#ifdef EH_FRAME_SECTION_ASM_OP
void
eh_frame_section ()
{
if (in_section != in_eh_frame)
{
fprintf (asm_out_file, "%s\n", EH_FRAME_SECTION_ASM_OP);
in_section = in_eh_frame;
}
}
#endif
/* Switch to the section for function DECL.
If DECL is NULL_TREE, switch to the text section.
@ -461,15 +476,15 @@ variable_section (decl, reloc)
void
exception_section ()
{
#if defined (EXCEPTION_SECTION)
EXCEPTION_SECTION ();
#else
#ifdef ASM_OUTPUT_SECTION_NAME
named_section (NULL_TREE, ".gcc_except_table", 0);
#else
if (flag_pic)
data_section ();
else
#if defined (EXCEPTION_SECTION)
EXCEPTION_SECTION ();
#else
readonly_data_section ();
#endif
#endif