[patch] fix collect2 not to drag every object with eh tables on aix

Olivier Hainque hainque@adacore.com
Wed Jul 8 20:50:00 GMT 2009


Olivier Hainque wrote:
> This is a recap and resubmission of a patch suggested a while ago

 I managed to truncate the attachement in the previous message.
 Here it is again.

 Thanks in advance,

 Olivier
 
> 2009-07-06  Olivier Hainque  <hainque@adacore.com>
> 
> 	* 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. 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.


-------------- next part --------------
Index: gcc/collect2.c
===================================================================
*** gcc/collect2.c	(revision 148649)
--- gcc/collect2.c	(working copy)
*************** int do_collecting = 1;
*** 145,150 ****
--- 145,161 ----
  int do_collecting = 0;
  #endif
  
+ /* Cook up an always defined indication of whether we proceed the
+    "EXPORT_LIST" way, much simpler to include in conditional expression
+    and helping readability by preventing the systematic need of #ifdef
+    conditionals.  */
+ 
+ #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;
*************** struct head
*** 165,179 ****
    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 */
--- 176,181 ----
*************** static void write_c_file_stat (FILE *, c
*** 288,294 ****
  #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
--- 290,295 ----
*************** static void write_aix_file (FILE *, stru
*** 303,308 ****
--- 304,349 ----
  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.  */
+ 
+ typedef enum {
+   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
+ } 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.  */
  
*************** main (int argc, char **argv)
*** 831,836 ****
--- 872,886 ----
    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;
*************** main (int argc, char **argv)
*** 1279,1297 ****
      }
  
    /* 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);
!   }
    {
      struct id *list = libs.first;
  
      for (; list; list = list->next)
!       scan_prog_file (list->name, PASS_FIRST);
    }
  
    if (exports.first)
--- 1329,1359 ----
      }
  
    /* The AIX linker will discard static constructors in object files if
!      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, this_filter);
!     
!     ld1_filter = (scanfilter) (ld1_filter & ~this_filter);
    }
  
    if (exports.first)
*************** main (int argc, char **argv)
*** 1362,1403 ****
      }
  
    /* Load the program, searching all libraries and attempting to provide
!      undefined symbols from repository information.  */
  
!   /* On AIX we do this later.  */
! #ifndef COLLECT_EXPORT_LIST
!   do_tlink (ld1_argv, object_lst);
! #endif
  
!   /* 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.  */
        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);
  #endif
!       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.  */
! 
!   /* On AIX we already scanned for global constructors/destructors.  */
! #ifndef COLLECT_EXPORT_LIST
!   scan_prog_file (output_file, PASS_FIRST);
! #endif
  
  #ifdef SCAN_LIBRARIES
    scan_libraries (output_file);
--- 1424,1468 ----
      }
  
    /* Load the program, searching all libraries and attempting to provide
!      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);
  
!     /* 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.
  
!        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);
!     
!     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;
!       }
!   }
  
!   /* 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.  */
! 
!   if (ld1_filter != SCAN_NOTHING)
!     scan_prog_file (output_file, PASS_FIRST, ld1_filter);
  
  #ifdef SCAN_LIBRARIES
    scan_libraries (output_file);
*************** main (int argc, char **argv)
*** 1410,1415 ****
--- 1475,1483 ----
        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)
*************** main (int argc, char **argv)
*** 1420,1429 ****
  #endif
        )
      {
! #ifdef COLLECT_EXPORT_LIST
!       /* Do tlink without additional code generation.  */
!       do_tlink (ld1_argv, object_lst);
! #endif
        /* Strip now if it was requested on the command line.  */
        if (strip_flag)
  	{
--- 1488,1498 ----
  #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)
  	{
*************** main (int argc, char **argv)
*** 1523,1529 ****
  
    /* 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);
  #endif
  
    maybe_unlink (c_file);
--- 1592,1598 ----
  
    /* 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_ALL);
  #endif
  
    maybe_unlink (c_file);
*************** write_aix_file (FILE *stream, struct id 
*** 2097,2112 ****
  #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__.  */
  
  static void
! scan_prog_file (const char *prog_name, enum pass which_pass)
  {
    void (*int_handler) (int);
  #ifdef SIGQUIT
--- 2166,2176 ----
  #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.  */
  
  static void
! scan_prog_file (const char *prog_name, scanpass which_pass,
! 		scanfilter filter)
  {
    void (*int_handler) (int);
  #ifdef SIGQUIT
*************** scan_prog_file (const char *prog_name, e
*** 2185,2191 ****
        char *name, *end;
  
        /* If it contains a constructor or destructor name, add the name
! 	 to the appropriate list.  */
  
        for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
  	if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
--- 2249,2256 ----
        char *name, *end;
  
        /* If it contains a constructor or destructor name, add the name
! 	 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] == ' ')
*************** scan_prog_file (const char *prog_name, e
*** 2206,2221 ****
--- 2271,2292 ----
        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
*************** scan_prog_file (const char *prog_name, e
*** 2224,2229 ****
--- 2295,2302 ----
  	  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
*************** scan_prog_file (const char *prog_name, e
*** 2232,2237 ****
--- 2305,2312 ----
  	  break;
  
  	case SYM_DWEH:
+ 	  if (! (filter & SCAN_DWEH))
+ 	    break;
  	  if (which_pass != PASS_LIB)
  	    add_to_list (&frame_tables, name);
  	  break;
*************** extern char *ldgetname (LDFILE *, GCC_SY
*** 2488,2503 ****
  #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__.  */
  
  static void
! scan_prog_file (const char *prog_name, enum pass which_pass)
  {
    LDFILE *ldptr = NULL;
    int sym_index, sym_count;
--- 2563,2573 ----
  #endif
  
  /* COFF version to scan the name list of the loaded program for
!    the symbols g++ uses for static constructors and destructors.  */
  
  static void
! scan_prog_file (const char *prog_name, scanpass which_pass,
! 		scanfilter filter)
  {
    LDFILE *ldptr = NULL;
    int sym_index, sym_count;
*************** scan_prog_file (const char *prog_name, e
*** 2561,2566 ****
--- 2631,2638 ----
  		      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)
*************** scan_prog_file (const char *prog_name, e
*** 2570,2575 ****
--- 2642,2649 ----
  			  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)
*************** scan_prog_file (const char *prog_name, e
*** 2580,2585 ****
--- 2654,2661 ----
  
  #ifdef COLLECT_EXPORT_LIST
  			case SYM_INIT:
+ 			  if (! (filter & SCAN_INIT))
+ 			    break;
  #ifndef LD_INIT_SWITCH
  			  if (is_shared)
  			    add_to_list (&constructors, name);
*************** scan_prog_file (const char *prog_name, e
*** 2587,2592 ****
--- 2663,2670 ----
  			  break;
  
  			case SYM_FINI:
+ 			  if (! (filter & SCAN_FINI))
+ 			    break;
  #ifndef LD_INIT_SWITCH
  			  if (is_shared)
  			    add_to_list (&destructors, name);
*************** scan_prog_file (const char *prog_name, e
*** 2595,2600 ****
--- 2673,2680 ----
  #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)
Index: gcc/doc/tm.texi
===================================================================
*** gcc/doc/tm.texi	(revision 148541)
--- gcc/doc/tm.texi	(working copy)
*************** A C statement to issue assembly directiv
*** 9136,9141 ****
--- 9136,9147 ----
  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 given DWARF table identifier @var{label} from the current function
+ section.
+ @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.
Index: gcc/dwarf2out.c
===================================================================
*** gcc/dwarf2out.c	(revision 148541)
--- gcc/dwarf2out.c	(working copy)
*************** dw_cfi_oprnd2_desc (enum dwarf_call_fram
*** 2891,2902 ****
  
  #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.  */
  
  static void
! switch_to_eh_frame_section (void)
  {
    tree label;
  
--- 2891,2902 ----
  
  #if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
  
! /* 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 (bool back)
  {
    tree label;
  
*************** switch_to_eh_frame_section (void)
*** 2939,2949 ****
        /* 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));
      }
  }
  
--- 2939,2953 ----
        /* 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);
! 
!       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));
! 	}
      }
  }
  
*************** output_cfi_directive (dw_cfi_ref cfi)
*** 3189,3194 ****
--- 3193,3214 ----
      }
  }
  
+ /* 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.  */
*************** output_call_frame_info (int for_eh)
*** 3259,3273 ****
    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);
!     }
  
    ASM_GENERATE_INTERNAL_LABEL (section_start_label, FRAME_BEGIN_LABEL, for_eh);
    ASM_OUTPUT_LABEL (asm_out_file, section_start_label);
--- 3279,3286 ----
    if (flag_debug_asm)
      app_enable ();
  
!   /* 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);
*************** output_call_frame_info (int for_eh)
*** 3542,3547 ****
--- 3555,3574 ----
        for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next)
  	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, which we need do 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)));
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
*** gcc/config/rs6000/rs6000-protos.h	(revision 148541)
--- gcc/config/rs6000/rs6000-protos.h	(working copy)
*************** extern bool rs6000_tls_referenced_p (rtx
*** 171,176 ****
--- 171,178 ----
  extern int rs6000_hard_regno_nregs (int, enum machine_mode);
  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 *);
Index: gcc/config/rs6000/aix.h
===================================================================
*** gcc/config/rs6000/aix.h	(revision 148541)
--- gcc/config/rs6000/aix.h	(working copy)
***************
*** 43,48 ****
--- 43,54 ----
     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
  
Index: gcc/config/rs6000/rs6000.c
===================================================================
*** gcc/config/rs6000/rs6000.c	(revision 148541)
--- gcc/config/rs6000/rs6000.c	(working copy)
*************** create_TOC_reference (rtx symbol)
*** 15479,15484 ****
--- 15479,15493 ----
  	       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.  */


More information about the Gcc-patches mailing list