From 7e49a4b3969b940d0165515374f81c0307965d45 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Fri, 28 Aug 2009 09:04:52 +0000 Subject: [PATCH] collect2.c (DO_COLLECT_EXPORT_LIST): New internal macro, always defined. * collect2.c (DO_COLLECT_EXPORT_LIST): New internal macro, always defined. Reflect definition or absence of such for COLLECT_EXPORT_LIST. Readability helper. (scanfilter): New enum, to help control what symbols are to be considered or ignored by scan_prog_file. (enum pass): Rename as "scanpass", moved together with scanfilter prior to scan_prog_file's prototype. (scan_prog_file): Accept and honor scanpass and scanfilter arguments. Group prototype with the scanpass/scanfilter definitions, factorize head comments for the several implementations at the prototype. (main): Reorganize the first pass link control to let AIX drag only the needed frame tables in executables. Prevent frame tables collection during the scan aimed at static ctors. Pre-link and scan for frame tables later to compensate. * doc/tm.texi (ASM_OUTPUT_DWARF_TABLE_REF): New macro. A C statement to issue assembly directives that create a reference to the given DWARF table identifier label from the current function section. * dwarf2out.c (switch_to_eh_frame_section): Add a BACK argument to differentiate first time section entry. Only emit a .data tables start identifier label the first time around. (switch_to_frame_table_section): New function. Helper for output_call_frame_info to switch possibly BACK into the eh_frame or the debug_frame section depending on FOR_EH. (output_call_frame_info): Use helper to first enter the proper frame section. (output_fde): Use ASM_OUTPUT_DWARF_TABLE_REF when defined to emit a link to the frame table start label from each function section. * config/rs6000/rs6000.c (rs6000_aix_asm_output_dwarf_table_ref): New function. Implementation of ASM_OUTPUT_DWARF_TABLE_REF. * config/rs6000/rs6000-protos.h: Declare it. * config/rs6000/aix.h (ASM_OUTPUT_DWARF_TABLE_REF): Define. From-SVN: r151157 --- gcc/ChangeLog | 36 +++++ gcc/collect2.c | 224 ++++++++++++++++++++---------- gcc/config/rs6000/aix.h | 6 + gcc/config/rs6000/rs6000-protos.h | 2 + gcc/config/rs6000/rs6000.c | 9 ++ gcc/doc/tm.texi | 7 + gcc/dwarf2out.c | 63 ++++++--- 7 files changed, 258 insertions(+), 89 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index de1e1c5f6e7..c53d9c8ef82 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,39 @@ +2009-08-28 Olivier Hainque + + * collect2.c (DO_COLLECT_EXPORT_LIST): New internal macro, + always defined. Reflect definition or absence of such for + COLLECT_EXPORT_LIST. Readability helper. + (scanfilter): New enum, to help control what symbols + are to be considered or ignored by scan_prog_file. + (enum pass): Rename as "scanpass", moved together with scanfilter + prior to scan_prog_file's prototype. + (scan_prog_file): Accept and honor scanpass and scanfilter arguments. + Group prototype with the scanpass/scanfilter definitions, factorize + head comments for the several implementations at the prototype. + (main): Reorganize the first pass link control to let AIX + drag only the needed frame tables in executables. Prevent + frame tables collection during the scan aimed at static ctors. + Pre-link and scan for frame tables later to compensate. + * doc/tm.texi (ASM_OUTPUT_DWARF_TABLE_REF): New macro. + A C statement to issue assembly directives that create a reference + to the given DWARF table identifier label from the current function + section. + * dwarf2out.c (switch_to_eh_frame_section): Add a BACK argument + to differentiate first time section entry. Only emit a .data + tables start identifier label the first time around. + (switch_to_frame_table_section): New function. Helper for + output_call_frame_info to switch possibly BACK into the eh_frame + or the debug_frame section depending on FOR_EH. + (output_call_frame_info): Use helper to first enter the proper + frame section. + (output_fde): Use ASM_OUTPUT_DWARF_TABLE_REF when defined to + emit a link to the frame table start label from each function + section. + * config/rs6000/rs6000.c (rs6000_aix_asm_output_dwarf_table_ref): + New function. Implementation of ASM_OUTPUT_DWARF_TABLE_REF. + * config/rs6000/rs6000-protos.h: Declare it. + * config/rs6000/aix.h (ASM_OUTPUT_DWARF_TABLE_REF): Define. + 2009-08-27 Kaz Kojima * config/sh/sh.c (split_branches): Check the result of diff --git a/gcc/collect2.c b/gcc/collect2.c index aed4c675860..b235f2bda84 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -145,6 +145,15 @@ int do_collecting = 1; int do_collecting = 0; #endif +/* Cook up an always defined indication of whether we proceed the + "EXPORT_LIST" way. */ + +#ifdef COLLECT_EXPORT_LIST +#define DO_COLLECT_EXPORT_LIST 1 +#else +#define DO_COLLECT_EXPORT_LIST 0 +#endif + /* Nonzero if we should suppress the automatic demangling of identifiers in linker error messages. Set from COLLECT_NO_DEMANGLE. */ int no_demangle; @@ -165,15 +174,6 @@ struct head int number; }; -/* Enumeration giving which pass this is for scanning the program file. */ - -enum pass { - PASS_FIRST, /* without constructors */ - PASS_OBJ, /* individual objects */ - PASS_LIB, /* looking for shared libraries */ - PASS_SECOND /* with constructors linked in */ -}; - int vflag; /* true if -v */ static int rflag; /* true if -r */ static int strip_flag; /* true if -s */ @@ -288,7 +288,6 @@ static void write_c_file_stat (FILE *, const char *); #ifndef LD_INIT_SWITCH static void write_c_file_glob (FILE *, const char *); #endif -static void scan_prog_file (const char *, enum pass); #ifdef SCAN_LIBRARIES static void scan_libraries (const char *); #endif @@ -303,6 +302,50 @@ static void write_aix_file (FILE *, struct id *); static char *resolve_lib_name (const char *); #endif static char *extract_string (const char **); + +/* Enumerations describing which pass this is for scanning the + program file ... */ + +typedef enum { + PASS_FIRST, /* without constructors */ + PASS_OBJ, /* individual objects */ + PASS_LIB, /* looking for shared libraries */ + PASS_SECOND /* with constructors linked in */ +} scanpass; + +/* ... and which kinds of symbols are to be considered. */ + +enum scanfilter_masks { + SCAN_NOTHING = 0, + + SCAN_CTOR = 1 << SYM_CTOR, + SCAN_DTOR = 1 << SYM_DTOR, + SCAN_INIT = 1 << SYM_INIT, + SCAN_FINI = 1 << SYM_FINI, + SCAN_DWEH = 1 << SYM_DWEH, + SCAN_ALL = ~0 +}; + +/* This type is used for parameters and variables which hold + combinations of the flags in enum scanfilter_masks. */ +typedef int scanfilter; + +/* Scan the name list of the loaded program for the symbols g++ uses for + static constructors and destructors. + + The SCANPASS argument tells which collect processing pass this is for and + the SCANFILTER argument tells which kinds of symbols to consider in this + pass. Symbols of a special kind not in the filter mask are considered as + regular ones. + + The constructor table begins at __CTOR_LIST__ and contains a count of the + number of pointers (or -1 if the constructors are built in a separate + section by the linker), followed by the pointers to the constructor + functions, terminated with a null pointer. The destructor table has the + same format, and begins at __DTOR_LIST__. */ + +static void scan_prog_file (const char *, scanpass, scanfilter); + /* Delete tempfiles and exit function. */ @@ -831,6 +874,15 @@ main (int argc, char **argv) const char **c_ptr; char **ld1_argv; const char **ld1; + + /* The kinds of symbols we will have to consider when scanning the + outcome of a first pass link. This is ALL to start with, then might + be adjusted before getting to the first pass link per se, typically on + AIX where we perform an early scan of objects and libraries to fetch + the list of global ctors/dtors and make sure they are not garbage + collected. */ + scanfilter ld1_filter = SCAN_ALL; + char **ld2_argv; const char **ld2; char **object_lst; @@ -1279,19 +1331,31 @@ main (int argc, char **argv) } /* The AIX linker will discard static constructors in object files if - nothing else in the file is referenced, so look at them first. */ - { - const char **export_object_lst - = CONST_CAST2 (const char **, char **, object_lst); - - while (export_object_lst < object) - scan_prog_file (*export_object_lst++, PASS_OBJ); - } + nothing else in the file is referenced, so look at them first. Unless + we are building a shared object, ignore the eh frame tables, as we + would otherwise reference them all, hence drag all the corresponding + objects even if nothing else is referenced. */ { + const char **export_object_lst + = CONST_CAST2 (const char **, char **, object_lst); + struct id *list = libs.first; + /* Compute the filter to use from the current one, do scan, then adjust + the "current" filter to remove what we just included here. This will + control whether we need a first pass link later on or not, and what + will remain to be scanned there. */ + + scanfilter this_filter + = shared_obj ? ld1_filter : (ld1_filter & ~SCAN_DWEH); + + while (export_object_lst < object) + scan_prog_file (*export_object_lst++, PASS_OBJ, this_filter); + for (; list; list = list->next) - scan_prog_file (list->name, PASS_FIRST); + scan_prog_file (list->name, PASS_FIRST, this_filter); + + ld1_filter = ld1_filter & ~this_filter; } if (exports.first) @@ -1362,42 +1426,45 @@ main (int argc, char **argv) } /* Load the program, searching all libraries and attempting to provide - undefined symbols from repository information. */ + undefined symbols from repository information. + + If -r or they will be run via some other method, do not build the + constructor or destructor list, just return now. */ + { + bool early_exit + = rflag || (! DO_COLLECT_EXPORT_LIST && ! do_collecting); - /* On AIX we do this later. */ -#ifndef COLLECT_EXPORT_LIST - do_tlink (ld1_argv, object_lst); -#endif + /* Perform the first pass link now, if we're about to exit or if we need + to scan for things we haven't collected yet before pursuing further. - /* If -r or they will be run via some other method, do not build the - constructor or destructor list, just return now. */ - if (rflag -#ifndef COLLECT_EXPORT_LIST - || ! do_collecting -#endif - ) - { -#ifdef COLLECT_EXPORT_LIST - /* Do the link we avoided above if we are exiting. */ + On AIX, the latter typically includes nothing for shared objects or + frame tables for an executable, out of what the required early scan on + objects and libraries has performed above. In the !shared_obj case, we + expect the relevant tables to be dragged together with their associated + functions from precise cross reference insertions by the compiler. */ + + if (early_exit || ld1_filter != SCAN_NOTHING) do_tlink (ld1_argv, object_lst); - - /* But make sure we delete the export file we may have created. */ - if (export_file != 0 && export_file[0]) - maybe_unlink (export_file); + + if (early_exit) + { +#ifdef COLLECT_EXPORT_LIST + /* Make sure we delete the export file we may have created. */ + if (export_file != 0 && export_file[0]) + maybe_unlink (export_file); #endif - maybe_unlink (c_file); - maybe_unlink (o_file); - return 0; - } + maybe_unlink (c_file); + maybe_unlink (o_file); + return 0; + } + } - /* Examine the namelist with nm and search it for static constructors - and destructors to call. - Write the constructor and destructor tables to a .s file and reload. */ + /* Unless we have done it all already, examine the namelist and search for + static constructors and destructors to call. Write the constructor and + destructor tables to a .s file and reload. */ - /* On AIX we already scanned for global constructors/destructors. */ -#ifndef COLLECT_EXPORT_LIST - scan_prog_file (output_file, PASS_FIRST); -#endif + if (ld1_filter != SCAN_NOTHING) + scan_prog_file (output_file, PASS_FIRST, ld1_filter); #ifdef SCAN_LIBRARIES scan_libraries (output_file); @@ -1410,6 +1477,9 @@ main (int argc, char **argv) notice ("%d frame table(s) found\n", frame_tables.number); } + /* If the scan exposed nothing of special interest, there's no need to + generate the glue code and relink so return now. */ + if (constructors.number == 0 && destructors.number == 0 && frame_tables.number == 0 #if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST) @@ -1420,10 +1490,11 @@ main (int argc, char **argv) #endif ) { -#ifdef COLLECT_EXPORT_LIST - /* Do tlink without additional code generation. */ - do_tlink (ld1_argv, object_lst); -#endif + /* Do tlink without additional code generation now if we didn't + do it earlier for scanning purposes. */ + if (ld1_filter == SCAN_NOTHING) + do_tlink (ld1_argv, object_lst); + /* Strip now if it was requested on the command line. */ if (strip_flag) { @@ -1523,7 +1594,7 @@ main (int argc, char **argv) /* Let scan_prog_file do any final mods (OSF/rose needs this for constructors/destructors in shared libraries. */ - scan_prog_file (output_file, PASS_SECOND); + scan_prog_file (output_file, PASS_SECOND, SCAN_ALL); #endif maybe_unlink (c_file); @@ -2097,16 +2168,11 @@ write_aix_file (FILE *stream, struct id *list) #ifdef OBJECT_FORMAT_NONE /* Generic version to scan the name list of the loaded program for - the symbols g++ uses for static constructors and destructors. - - The constructor table begins at __CTOR_LIST__ and contains a count - of the number of pointers (or -1 if the constructors are built in a - separate section by the linker), followed by the pointers to the - constructor functions, terminated with a null pointer. The - destructor table has the same format, and begins at __DTOR_LIST__. */ + the symbols g++ uses for static constructors and destructors. */ static void -scan_prog_file (const char *prog_name, enum pass which_pass) +scan_prog_file (const char *prog_name, scanpass which_pass, + scanfilter filter) { void (*int_handler) (int); #ifdef SIGQUIT @@ -2185,7 +2251,8 @@ scan_prog_file (const char *prog_name, enum pass which_pass) char *name, *end; /* If it contains a constructor or destructor name, add the name - to the appropriate list. */ + to the appropriate list unless this is a kind of symbol we're + not supposed to even consider. */ for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++) if (ch == ' ' && p[1] == 'U' && p[2] == ' ') @@ -2206,16 +2273,22 @@ scan_prog_file (const char *prog_name, enum pass which_pass) switch (is_ctor_dtor (name)) { case SYM_CTOR: + if (! (filter & SCAN_CTOR)) + break; if (which_pass != PASS_LIB) add_to_list (&constructors, name); break; case SYM_DTOR: + if (! (filter & SCAN_DTOR)) + break; if (which_pass != PASS_LIB) add_to_list (&destructors, name); break; case SYM_INIT: + if (! (filter & SCAN_INIT)) + break; if (which_pass != PASS_LIB) fatal ("init function found in object %s", prog_name); #ifndef LD_INIT_SWITCH @@ -2224,6 +2297,8 @@ scan_prog_file (const char *prog_name, enum pass which_pass) break; case SYM_FINI: + if (! (filter & SCAN_FINI)) + break; if (which_pass != PASS_LIB) fatal ("fini function found in object %s", prog_name); #ifndef LD_FINI_SWITCH @@ -2232,6 +2307,8 @@ scan_prog_file (const char *prog_name, enum pass which_pass) break; case SYM_DWEH: + if (! (filter & SCAN_DWEH)) + break; if (which_pass != PASS_LIB) add_to_list (&frame_tables, name); break; @@ -2488,16 +2565,11 @@ extern char *ldgetname (LDFILE *, GCC_SYMENT *); #endif /* COFF version to scan the name list of the loaded program for - the symbols g++ uses for static constructors and destructors. - - The constructor table begins at __CTOR_LIST__ and contains a count - of the number of pointers (or -1 if the constructors are built in a - separate section by the linker), followed by the pointers to the - constructor functions, terminated with a null pointer. The - destructor table has the same format, and begins at __DTOR_LIST__. */ + the symbols g++ uses for static constructors and destructors. */ static void -scan_prog_file (const char *prog_name, enum pass which_pass) +scan_prog_file (const char *prog_name, scanpass which_pass, + scanfilter filter) { LDFILE *ldptr = NULL; int sym_index, sym_count; @@ -2561,6 +2633,8 @@ scan_prog_file (const char *prog_name, enum pass which_pass) switch (is_ctor_dtor (name)) { case SYM_CTOR: + if (! (filter & SCAN_CTOR)) + break; if (! is_shared) add_to_list (&constructors, name); #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH) @@ -2570,6 +2644,8 @@ scan_prog_file (const char *prog_name, enum pass which_pass) break; case SYM_DTOR: + if (! (filter & SCAN_DTOR)) + break; if (! is_shared) add_to_list (&destructors, name); #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH) @@ -2580,6 +2656,8 @@ scan_prog_file (const char *prog_name, enum pass which_pass) #ifdef COLLECT_EXPORT_LIST case SYM_INIT: + if (! (filter & SCAN_INIT)) + break; #ifndef LD_INIT_SWITCH if (is_shared) add_to_list (&constructors, name); @@ -2587,6 +2665,8 @@ scan_prog_file (const char *prog_name, enum pass which_pass) break; case SYM_FINI: + if (! (filter & SCAN_FINI)) + break; #ifndef LD_INIT_SWITCH if (is_shared) add_to_list (&destructors, name); @@ -2595,6 +2675,8 @@ scan_prog_file (const char *prog_name, enum pass which_pass) #endif case SYM_DWEH: + if (! (filter & SCAN_DWEH)) + break; if (! is_shared) add_to_list (&frame_tables, name); #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH) diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h index 44015a348b7..4676110b44e 100644 --- a/gcc/config/rs6000/aix.h +++ b/gcc/config/rs6000/aix.h @@ -43,6 +43,12 @@ collect has a chance to see them, so scan the object files directly. */ #define COLLECT_EXPORT_LIST +/* Issue assembly directives that create a reference to the given DWARF table + identifier label from the current function section. This is defined to + ensure we drag frame frame tables associated with needed function bodies in + a link with garbage collection activated. */ +#define ASM_OUTPUT_DWARF_TABLE_REF rs6000_aix_asm_output_dwarf_table_ref + /* Handle #pragma weak and #pragma pack. */ #define HANDLE_SYSV_PRAGMA 1 diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 96f215be9e3..6e6bb9e3891 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -179,6 +179,8 @@ extern int rs6000_memory_move_cost (enum machine_mode, enum reg_class, int); extern bool rs6000_tls_referenced_p (rtx); extern void rs6000_conditional_register_usage (void); +extern void rs6000_aix_asm_output_dwarf_table_ref (char *); + /* Declare functions in rs6000-c.c */ extern void rs6000_pragma_longcall (struct cpp_reader *); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index cb64d28f4c9..8e31cbbe7a6 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -17612,6 +17612,15 @@ create_TOC_reference (rtx symbol) gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol), UNSPEC_TOCREL))); } +/* Issue assembly directives that create a reference to the given DWARF + FRAME_TABLE_LABEL from the current function section. */ +void +rs6000_aix_asm_output_dwarf_table_ref (char * frame_table_label) +{ + fprintf (asm_out_file, "\t.ref %s\n", + TARGET_STRIP_NAME_ENCODING (frame_table_label)); +} + /* If _Unwind_* has been called from within the same module, toc register is not guaranteed to be saved to 40(1) on function entry. Save it there in that case. */ diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 818df81a4d3..f236a7d1c1b 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -9159,6 +9159,13 @@ A C statement to issue assembly directives that create a self-relative reference to the given @var{label}, using an integer of the given @var{size}. @end defmac +@defmac ASM_OUTPUT_DWARF_TABLE_REF (@var{label}) +A C statement to issue assembly directives that create a reference to +the DWARF table identifier @var{label} from the current section. This +is used on some systems to avoid garbage collecting a DWARF table which +is referenced by a function. +@end defmac + @deftypefn {Target Hook} void TARGET_ASM_OUTPUT_DWARF_DTPREL (FILE *@var{FILE}, int @var{size}, rtx @var{x}) If defined, this target hook is a function which outputs a DTP-relative reference to the given TLS symbol of the specified size. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index ad956f83324..04f875870c3 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -2932,12 +2932,12 @@ dw_cfi_oprnd2_desc (enum dwarf_call_frame_info cfi) #if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO) -/* Switch to eh_frame_section. If we don't have an eh_frame_section, - switch to the data section instead, and write out a synthetic label - for collect2. */ +/* Switch [BACK] to eh_frame_section. If we don't have an eh_frame_section, + switch to the data section instead, and write out a synthetic start label + for collect2 the first time around. */ static void -switch_to_eh_frame_section (void) +switch_to_eh_frame_section (bool back) { tree label; @@ -2980,11 +2980,15 @@ switch_to_eh_frame_section (void) /* We have no special eh_frame section. Put the information in the data section and emit special labels to guide collect2. */ switch_to_section (data_section); - label = get_file_function_name ("F"); - ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE)); - targetm.asm_out.globalize_label (asm_out_file, - IDENTIFIER_POINTER (label)); - ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label)); + + if (!back) + { + label = get_file_function_name ("F"); + ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE)); + targetm.asm_out.globalize_label (asm_out_file, + IDENTIFIER_POINTER (label)); + ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label)); + } } } @@ -3534,6 +3538,20 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second, output_cfi (cfi, fde, for_eh); } + /* If we are to emit a ref/link from function bodies to their frame tables, + do it now. This is typically performed to make sure that tables + associated with functions are dragged with them and not discarded in + garbage collecting links. We need to do this on a per function basis to + cope with -ffunction-sections. */ + +#ifdef ASM_OUTPUT_DWARF_TABLE_REF + /* Switch to the function section, emit the ref to the tables, and + switch *back* into the table section. */ + switch_to_section (function_section (fde->decl)); + ASM_OUTPUT_DWARF_TABLE_REF (section_start_label); + switch_to_frame_table_section (for_eh, true); +#endif + /* Pad the FDE out to an address sized boundary. */ ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE))); @@ -3543,6 +3561,22 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second, } +/* Switch [BACK] to the eh or debug frame table section, depending on + FOR_EH. */ +static void +switch_to_frame_table_section (int for_eh, bool back) +{ + if (for_eh) + switch_to_eh_frame_section (back); + else + { + if (!debug_frame_section) + debug_frame_section = get_section (DEBUG_FRAME_SECTION, + SECTION_DEBUG, NULL); + switch_to_section (debug_frame_section); + } +} + /* Output the call frame information used to record information that relates to calculating the frame pointer, and records the location of saved registers. */ @@ -3613,15 +3647,8 @@ output_call_frame_info (int for_eh) if (flag_debug_asm) app_enable (); - if (for_eh) - switch_to_eh_frame_section (); - else - { - if (!debug_frame_section) - debug_frame_section = get_section (DEBUG_FRAME_SECTION, - SECTION_DEBUG, NULL); - switch_to_section (debug_frame_section); - } + /* Switch to the proper frame section, first time. */ + switch_to_frame_table_section (for_eh, false); ASM_GENERATE_INTERNAL_LABEL (section_start_label, FRAME_BEGIN_LABEL, for_eh); ASM_OUTPUT_LABEL (asm_out_file, section_start_label);