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
This commit is contained in:
parent
72129a2509
commit
7e49a4b396
7 changed files with 258 additions and 89 deletions
|
@ -1,3 +1,39 @@
|
|||
2009-08-28 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.
|
||||
(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 <kkojima@gcc.gnu.org>
|
||||
|
||||
* config/sh/sh.c (split_branches): Check the result of
|
||||
|
|
224
gcc/collect2.c
224
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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue