* ld.h (args_type): Add gc_sections.
* ldgram.y (ldgram_had_keep, KEEP): New. (input_section_spec_no_keep): Rename from old input_section_spec. (input_section_spec): New. Recognize KEEP. * ldlang.c (wild_section): Handle keep sections. (lang_gc_wild_section, lang_gc_wild_file, lang_gc_wild): New. (lang_gc_sections_1, lang_gc_sections): New. (lang_process): Invoke lang_gc_sections. (lang_add_wild): Add keep argument. Update all callers. * ldlang.h (lang_wild_statement_struct): Add keep_sections. * ldlex.l (KEEP): Match it. * ldmain.c (main): Error on -r and --gc-sections. * lexsup.c: Add --gc-sections. * scripttempl/elf.sc: Merge .text.* etc sections appropriately. Mark startup sections with KEEP. * scripttempl/elfppc.sc: Likewise. * ld.texinfo: Update for --gc-sections and KEEP.
This commit is contained in:
parent
5ea0771f4c
commit
71b012a810
27
ld/ChangeLog
27
ld/ChangeLog
@ -1,3 +1,30 @@
|
||||
Wed Jul 1 19:40:34 1998 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
* ld.h (args_type): Add gc_sections.
|
||||
* ldgram.y (ldgram_had_keep, KEEP): New.
|
||||
(input_section_spec_no_keep): Rename from old input_section_spec.
|
||||
(input_section_spec): New. Recognize KEEP.
|
||||
* ldlang.c (wild_section): Handle keep sections.
|
||||
(lang_gc_wild_section, lang_gc_wild_file, lang_gc_wild): New.
|
||||
(lang_gc_sections_1, lang_gc_sections): New.
|
||||
(lang_process): Invoke lang_gc_sections.
|
||||
(lang_add_wild): Add keep argument. Update all callers.
|
||||
* ldlang.h (lang_wild_statement_struct): Add keep_sections.
|
||||
* ldlex.l (KEEP): Match it.
|
||||
* ldmain.c (main): Error on -r and --gc-sections.
|
||||
* lexsup.c: Add --gc-sections.
|
||||
|
||||
* scripttempl/elf.sc: Merge .text.* etc sections appropriately.
|
||||
Mark startup sections with KEEP.
|
||||
* scripttempl/elfppc.sc: Likewise.
|
||||
|
||||
* ld.texinfo: Update for --gc-sections and KEEP.
|
||||
|
||||
Wed Jul 1 15:21:20 1998 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
From Peter Jordan <pjordan@chla.usc.edu>:
|
||||
* scripttempl/i386go32.sc: Correct constructor handling for -u.
|
||||
|
||||
Tue Jun 23 15:17:27 1998 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
* Makefile.am (install-data-local): Make ldscripts subdirectory.
|
||||
|
9
ld/ld.h
9
ld/ld.h
@ -138,6 +138,9 @@ typedef struct
|
||||
/* Name of shared object for whose symbol table this shared object
|
||||
is an auxiliary filter. From the --auxiliary option. */
|
||||
char **auxiliary_filters;
|
||||
|
||||
/* Remove unreferenced sections? */
|
||||
boolean gc_sections;
|
||||
} args_type;
|
||||
|
||||
extern args_type command_line;
|
||||
@ -153,6 +156,12 @@ typedef struct
|
||||
/* If true, doing a dynamic link. */
|
||||
boolean dynamic_link;
|
||||
|
||||
/* If true, -shared is supported. */
|
||||
/* ??? A better way to do this is perhaps to define this in the
|
||||
ld_emulation_xfer_struct since this is really a target dependent
|
||||
parameter. */
|
||||
boolean has_shared;
|
||||
|
||||
/* If true, build constructors. */
|
||||
boolean build_constructors;
|
||||
|
||||
|
@ -414,6 +414,13 @@ Set the maximum size of objects to be optimized using the GP register to
|
||||
MIPS ECOFF which supports putting large and small objects into different
|
||||
sections. This is ignored for other object file formats.
|
||||
|
||||
@kindex --gc-sections
|
||||
@cindex garbage collection
|
||||
@item --gc-sections
|
||||
Enable garbage collection of unused input sections. It is ignored on
|
||||
targets that do not support this option. This option is not compatible
|
||||
with @samp{-r}, nor should it be used with dynamic linking.
|
||||
|
||||
@cindex runtime library name
|
||||
@kindex -h@var{name}
|
||||
@kindex -soname=@var{name}
|
||||
@ -877,8 +884,11 @@ in the program, such as relaxing address modes and synthesizing new
|
||||
instructions in the output object file.
|
||||
|
||||
On some platforms these link time global optimizations may make symbolic
|
||||
debugging of the resulting executable impossible. This is known to be
|
||||
debugging of the resulting executable impossible.
|
||||
@ifset GENERIC
|
||||
This is known to be
|
||||
the case for the Matsushita MN10200 and MN10300 family of processors.
|
||||
@end ifset
|
||||
|
||||
@ifset GENERIC
|
||||
On platforms where this is not supported, @samp{--relax} is accepted,
|
||||
@ -1963,6 +1973,7 @@ map the input files into your memory layout.
|
||||
* Input Section Basics:: Input section basics
|
||||
* Input Section Wildcards:: Input section wildcard patterns
|
||||
* Input Section Common:: Input section for common symbols
|
||||
* Input Section Keep:: Input section and garbage collection
|
||||
* Input Section Example:: Input section example
|
||||
@end menu
|
||||
|
||||
@ -2131,6 +2142,16 @@ You will sometimes see @samp{[COMMON]} in old linker scripts. This
|
||||
notation is now considered obsolete. It is equivalent to
|
||||
@samp{*(COMMON)}.
|
||||
|
||||
@node Input Section Keep
|
||||
@subsubsection Input section and garbage collection
|
||||
@cindex KEEP
|
||||
@cindex garbage collection
|
||||
When link-time garbage collection is in use (@samp{--gc-sections}),
|
||||
it is often useful to mark sections that should not be eliminated.
|
||||
This is accomplished by surrounding an input section's wildcard entry
|
||||
with @code{KEEP()}, as in @code{KEEP(*(.init))} or
|
||||
@code{KEEP(SORT(*)(.ctors))}.
|
||||
|
||||
@node Input Section Example
|
||||
@subsubsection Input section example
|
||||
The following example is a complete linker script. It tells the linker
|
||||
@ -2319,6 +2340,7 @@ If you use anything other than an input section description as an output
|
||||
section command, such as a symbol assignment, then the output section
|
||||
will always be created, even if there are no matching input sections.
|
||||
|
||||
@cindex /DISCARD/
|
||||
The special output section name @samp{/DISCARD/} may be used to discard
|
||||
input sections. Any input sections which are assigned to an output
|
||||
section named @samp{/DISCARD/} are not included in the output file.
|
||||
|
309
ld/ldgram.y
309
ld/ldgram.y
@ -1,5 +1,6 @@
|
||||
/* A YACC grammer to parse a superset of the AT&T linker scripting languaue.
|
||||
Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998
|
||||
Free Software Foundation, Inc.
|
||||
Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
|
||||
|
||||
This file is part of GNU ld.
|
||||
@ -47,15 +48,14 @@ static enum section_type sectype;
|
||||
|
||||
lang_memory_region_type *region;
|
||||
|
||||
|
||||
char *current_file;
|
||||
struct wildcard_spec current_file;
|
||||
boolean ldgram_want_filename = true;
|
||||
boolean had_script = false;
|
||||
boolean force_make_executable = false;
|
||||
|
||||
boolean ldgram_in_script = false;
|
||||
boolean ldgram_had_equals = false;
|
||||
|
||||
boolean ldgram_had_keep = false;
|
||||
|
||||
#define ERROR_NAME_MAX 20
|
||||
static char *error_names[ERROR_NAME_MAX];
|
||||
@ -66,6 +66,8 @@ static int error_index;
|
||||
%union {
|
||||
bfd_vma integer;
|
||||
char *name;
|
||||
const char *cname;
|
||||
struct wildcard_spec wildcard;
|
||||
int token;
|
||||
union etree_union *etree;
|
||||
struct phdr_info
|
||||
@ -76,16 +78,25 @@ static int error_index;
|
||||
union etree_union *flags;
|
||||
} phdr;
|
||||
struct lang_nocrossref *nocrossref;
|
||||
struct lang_output_section_phdr_list *section_phdr;
|
||||
struct bfd_elf_version_deps *deflist;
|
||||
struct bfd_elf_version_expr *versyms;
|
||||
struct bfd_elf_version_tree *versnode;
|
||||
}
|
||||
|
||||
%type <etree> exp opt_exp_with_type mustbe_exp opt_at phdr_type phdr_val
|
||||
%type <etree> opt_exp_without_type
|
||||
%type <integer> fill_opt
|
||||
%type <name> memspec_opt casesymlist
|
||||
%type <cname> wildcard_name
|
||||
%type <wildcard> wildcard_spec
|
||||
%token <integer> INT
|
||||
%token <name> NAME LNAME
|
||||
%type <integer> length
|
||||
%type <phdr> phdr_qualifiers
|
||||
%type <nocrossref> nocrossref_list
|
||||
%type <section_phdr> phdr_opt
|
||||
%type <integer> opt_nocrossrefs
|
||||
|
||||
%right <token> PLUSEQ MINUSEQ MULTEQ DIVEQ '=' LSHIFTEQ RSHIFTEQ ANDEQ OREQ
|
||||
%right <token> '?' ':'
|
||||
@ -104,8 +115,8 @@ static int error_index;
|
||||
%right UNARY
|
||||
%token END
|
||||
%left <token> '('
|
||||
%token <token> ALIGN_K BLOCK BIND QUAD LONG SHORT BYTE
|
||||
%token SECTIONS PHDRS
|
||||
%token <token> ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE
|
||||
%token SECTIONS PHDRS SORT
|
||||
%token '{' '}'
|
||||
%token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
|
||||
%token SIZEOF_HEADERS
|
||||
@ -113,7 +124,8 @@ static int error_index;
|
||||
%token MEMORY DEFSYMEND
|
||||
%token NOLOAD DSECT COPY INFO OVERLAY
|
||||
%token NAME LNAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY
|
||||
%token <integer> SIZEOF NEXT ADDR LOADADDR
|
||||
%token <integer> NEXT
|
||||
%token SIZEOF ADDR LOADADDR MAX MIN
|
||||
%token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS
|
||||
%token ORIGIN FILL
|
||||
%token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
|
||||
@ -123,12 +135,19 @@ static int error_index;
|
||||
%token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD
|
||||
%token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
|
||||
%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
|
||||
%token <name> VERS_TAG VERS_IDENTIFIER
|
||||
%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
|
||||
%token KEEP
|
||||
%type <versyms> vers_defns
|
||||
%type <versnode> vers_tag
|
||||
%type <deflist> verdep
|
||||
|
||||
%%
|
||||
|
||||
file:
|
||||
INPUT_SCRIPT script_file
|
||||
| INPUT_MRI_SCRIPT mri_script_file
|
||||
| INPUT_VERSION_SCRIPT version_script_file
|
||||
| INPUT_DEFSYM defsym_expr
|
||||
;
|
||||
|
||||
@ -148,7 +167,7 @@ defsym_expr:
|
||||
mri_script_file:
|
||||
{
|
||||
ldlex_mri_script ();
|
||||
PUSH_ERROR ("MRI style script");
|
||||
PUSH_ERROR (_("MRI style script"));
|
||||
}
|
||||
mri_script_lines
|
||||
{
|
||||
@ -167,7 +186,7 @@ mri_script_command:
|
||||
CHIP exp
|
||||
| CHIP exp ',' exp
|
||||
| NAME {
|
||||
einfo("%P%F: unrecognised keyword in MRI style script '%s'\n",$1);
|
||||
einfo(_("%P%F: unrecognised keyword in MRI style script '%s'\n"),$1);
|
||||
}
|
||||
| LIST {
|
||||
config.map_filename = "-";
|
||||
@ -276,6 +295,7 @@ ifile_p1:
|
||||
| low_level_library
|
||||
| floating_point_support
|
||||
| statement_anywhere
|
||||
| version
|
||||
| ';'
|
||||
| TARGET_K '(' NAME ')'
|
||||
{ lang_add_target($3); }
|
||||
@ -346,49 +366,79 @@ statement_anywhere:
|
||||
|
||||
/* The '*' and '?' cases are there because the lexer returns them as
|
||||
separate tokens rather than as NAME. */
|
||||
file_NAME_list:
|
||||
wildcard_name:
|
||||
NAME
|
||||
{ lang_add_wild ($1, current_file); }
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| '*'
|
||||
{ lang_add_wild ("*", current_file); }
|
||||
{
|
||||
$$ = "*";
|
||||
}
|
||||
| '?'
|
||||
{ lang_add_wild ("?", current_file); }
|
||||
| file_NAME_list opt_comma NAME
|
||||
{ lang_add_wild ($3, current_file); }
|
||||
| file_NAME_list opt_comma '*'
|
||||
{ lang_add_wild ("*", current_file); }
|
||||
| file_NAME_list opt_comma '?'
|
||||
{ lang_add_wild ("?", current_file); }
|
||||
{
|
||||
$$ = "?";
|
||||
}
|
||||
;
|
||||
|
||||
wildcard_spec:
|
||||
wildcard_name
|
||||
{
|
||||
$$.name = $1;
|
||||
$$.sorted = false;
|
||||
}
|
||||
| SORT '(' wildcard_name ')'
|
||||
{
|
||||
$$.name = $3;
|
||||
$$.sorted = true;
|
||||
}
|
||||
;
|
||||
|
||||
file_NAME_list:
|
||||
wildcard_spec
|
||||
{
|
||||
lang_add_wild ($1.name, $1.sorted,
|
||||
current_file.name,
|
||||
current_file.sorted,
|
||||
ldgram_had_keep);
|
||||
}
|
||||
| file_NAME_list opt_comma wildcard_spec
|
||||
{
|
||||
lang_add_wild ($3.name, $3.sorted,
|
||||
current_file.name,
|
||||
current_file.sorted,
|
||||
ldgram_had_keep);
|
||||
}
|
||||
;
|
||||
|
||||
input_section_spec_no_keep:
|
||||
NAME
|
||||
{
|
||||
lang_add_wild (NULL, false, $1, false,
|
||||
ldgram_had_keep);
|
||||
}
|
||||
| '['
|
||||
{
|
||||
current_file.name = NULL;
|
||||
current_file.sorted = false;
|
||||
}
|
||||
file_NAME_list ']'
|
||||
| wildcard_spec
|
||||
{
|
||||
current_file = $1;
|
||||
/* '*' matches any file name. */
|
||||
if (strcmp (current_file.name, "*") == 0)
|
||||
current_file.name = NULL;
|
||||
}
|
||||
'(' file_NAME_list ')'
|
||||
;
|
||||
|
||||
input_section_spec:
|
||||
NAME
|
||||
{
|
||||
lang_add_wild((char *)NULL, $1);
|
||||
}
|
||||
| '['
|
||||
{
|
||||
current_file = (char *)NULL;
|
||||
}
|
||||
file_NAME_list
|
||||
']'
|
||||
| NAME
|
||||
{
|
||||
current_file = $1;
|
||||
}
|
||||
'(' file_NAME_list ')'
|
||||
| '?'
|
||||
/* This case is needed because the lexer returns a
|
||||
single question mark as '?' rather than NAME. */
|
||||
{
|
||||
current_file = "?";
|
||||
}
|
||||
'(' file_NAME_list ')'
|
||||
| '*'
|
||||
{
|
||||
current_file = (char *)NULL;
|
||||
}
|
||||
'(' file_NAME_list ')'
|
||||
input_section_spec_no_keep
|
||||
| KEEP '('
|
||||
{ ldgram_had_keep = true; }
|
||||
input_section_spec_no_keep ')'
|
||||
{ ldgram_had_keep = false; }
|
||||
;
|
||||
|
||||
statement:
|
||||
@ -432,6 +482,8 @@ statement_list_opt:
|
||||
length:
|
||||
QUAD
|
||||
{ $$ = $1; }
|
||||
| SQUAD
|
||||
{ $$ = $1; }
|
||||
| LONG
|
||||
{ $$ = $1; }
|
||||
| SHORT
|
||||
@ -523,7 +575,9 @@ memory_spec: NAME
|
||||
region->origin =
|
||||
exp_get_vma($3, 0L,"origin", lang_first_phase_enum);
|
||||
}
|
||||
; length_spec:
|
||||
;
|
||||
|
||||
length_spec:
|
||||
LENGTH '=' mustbe_exp
|
||||
{ region->length = exp_get_vma($3,
|
||||
~((bfd_vma)0),
|
||||
@ -535,7 +589,7 @@ memory_spec: NAME
|
||||
attributes_opt:
|
||||
'(' NAME ')'
|
||||
{
|
||||
lang_set_flags(®ion->flags, $2);
|
||||
lang_set_flags(region, $2);
|
||||
}
|
||||
|
|
||||
|
||||
@ -678,6 +732,10 @@ exp :
|
||||
{ $$ = exp_unop(ALIGN_K,$3); }
|
||||
| NAME
|
||||
{ $$ = exp_nameop(NAME,$1); }
|
||||
| MAX '(' exp ',' exp ')'
|
||||
{ $$ = exp_binop (MAX, $3, $5 ); }
|
||||
| MIN '(' exp ',' exp ')'
|
||||
{ $$ = exp_binop (MIN, $3, $5 ); }
|
||||
;
|
||||
|
||||
|
||||
@ -699,10 +757,27 @@ section: NAME { ldlex_expression(); }
|
||||
'}' { ldlex_popstate (); ldlex_expression (); }
|
||||
memspec_opt phdr_opt fill_opt
|
||||
{
|
||||
ldlex_popstate();
|
||||
lang_leave_output_section_statement($13, $11);
|
||||
ldlex_popstate ();
|
||||
lang_leave_output_section_statement ($13, $11, $12);
|
||||
}
|
||||
opt_comma
|
||||
| OVERLAY
|
||||
{ ldlex_expression (); }
|
||||
opt_exp_without_type opt_nocrossrefs opt_at
|
||||
{ ldlex_popstate (); ldlex_script (); }
|
||||
'{'
|
||||
{
|
||||
lang_enter_overlay ($3, $5, (int) $4);
|
||||
}
|
||||
overlay_section
|
||||
'}'
|
||||
{ ldlex_popstate (); ldlex_expression (); }
|
||||
memspec_opt phdr_opt fill_opt
|
||||
{
|
||||
ldlex_popstate ();
|
||||
lang_leave_overlay ($14, $12, $13);
|
||||
}
|
||||
opt_comma
|
||||
| /* The GROUP case is just enough to support the gcc
|
||||
svr3.ifile script. It is not intended to be full
|
||||
support. I'm not even sure what GROUP is supposed
|
||||
@ -727,6 +802,7 @@ type:
|
||||
atype:
|
||||
'(' type ')'
|
||||
| /* EMPTY */ { sectype = normal_section; }
|
||||
| '(' ')' { sectype = normal_section; }
|
||||
;
|
||||
|
||||
opt_exp_with_type:
|
||||
@ -741,6 +817,18 @@ opt_exp_with_type:
|
||||
{ $$ = $3; }
|
||||
;
|
||||
|
||||
opt_exp_without_type:
|
||||
exp ':' { $$ = $1; }
|
||||
| ':' { $$ = (etree_type *) NULL; }
|
||||
;
|
||||
|
||||
opt_nocrossrefs:
|
||||
/* empty */
|
||||
{ $$ = 0; }
|
||||
| NOCROSSREFS
|
||||
{ $$ = 1; }
|
||||
;
|
||||
|
||||
memspec_opt:
|
||||
'>' NAME
|
||||
{ $$ = $2; }
|
||||
@ -749,12 +837,40 @@ memspec_opt:
|
||||
|
||||
phdr_opt:
|
||||
/* empty */
|
||||
{
|
||||
$$ = NULL;
|
||||
}
|
||||
| phdr_opt ':' NAME
|
||||
{
|
||||
lang_section_in_phdr ($3);
|
||||
struct lang_output_section_phdr_list *n;
|
||||
|
||||
n = ((struct lang_output_section_phdr_list *)
|
||||
xmalloc (sizeof *n));
|
||||
n->name = $3;
|
||||
n->used = false;
|
||||
n->next = $1;
|
||||
$$ = n;
|
||||
}
|
||||
;
|
||||
|
||||
overlay_section:
|
||||
/* empty */
|
||||
| overlay_section
|
||||
NAME
|
||||
{
|
||||
ldlex_script ();
|
||||
lang_enter_overlay_section ($2);
|
||||
}
|
||||
'{' statement_list_opt '}'
|
||||
{ ldlex_popstate (); ldlex_expression (); }
|
||||
phdr_opt fill_opt
|
||||
{
|
||||
ldlex_popstate ();
|
||||
lang_leave_overlay_section ($9, $8);
|
||||
}
|
||||
opt_comma
|
||||
;
|
||||
|
||||
phdrs:
|
||||
PHDRS '{' phdr_list '}'
|
||||
;
|
||||
@ -819,7 +935,7 @@ phdr_qualifiers:
|
||||
else if (strcmp ($1, "FLAGS") == 0 && $2 != NULL)
|
||||
$$.flags = $2;
|
||||
else
|
||||
einfo ("%X%P:%S: PHDRS syntax error at `%s'\n", $1);
|
||||
einfo (_("%X%P:%S: PHDRS syntax error at `%s'\n"), $1);
|
||||
}
|
||||
| AT '(' exp ')' phdr_qualifiers
|
||||
{
|
||||
@ -839,13 +955,100 @@ phdr_val:
|
||||
}
|
||||
;
|
||||
|
||||
/* This syntax is used within an external version script file. */
|
||||
|
||||
version_script_file:
|
||||
{
|
||||
ldlex_version_file ();
|
||||
PUSH_ERROR (_("VERSION script"));
|
||||
}
|
||||
vers_nodes
|
||||
{
|
||||
ldlex_popstate ();
|
||||
POP_ERROR ();
|
||||
}
|
||||
;
|
||||
|
||||
/* This is used within a normal linker script file. */
|
||||
|
||||
version:
|
||||
{
|
||||
ldlex_version_script ();
|
||||
}
|
||||
VERSIONK '{' vers_nodes '}'
|
||||
{
|
||||
ldlex_popstate ();
|
||||
}
|
||||
;
|
||||
|
||||
vers_nodes:
|
||||
vers_node
|
||||
| vers_nodes vers_node
|
||||
;
|
||||
|
||||
vers_node:
|
||||
VERS_TAG '{' vers_tag '}' ';'
|
||||
{
|
||||
lang_register_vers_node ($1, $3, NULL);
|
||||
}
|
||||
| VERS_TAG '{' vers_tag '}' verdep ';'
|
||||
{
|
||||
lang_register_vers_node ($1, $3, $5);
|
||||
}
|
||||
;
|
||||
|
||||
verdep:
|
||||
VERS_TAG
|
||||
{
|
||||
$$ = lang_add_vers_depend (NULL, $1);
|
||||
}
|
||||
| verdep VERS_TAG
|
||||
{
|
||||
$$ = lang_add_vers_depend ($1, $2);
|
||||
}
|
||||
;
|
||||
|
||||
vers_tag:
|
||||
/* empty */
|
||||
{
|
||||
$$ = lang_new_vers_node (NULL, NULL);
|
||||
}
|
||||
| vers_defns ';'
|
||||
{
|
||||
$$ = lang_new_vers_node ($1, NULL);
|
||||
}
|
||||
| GLOBAL ':' vers_defns ';'
|
||||
{
|
||||
$$ = lang_new_vers_node ($3, NULL);
|
||||
}
|
||||
| LOCAL ':' vers_defns ';'
|
||||
{
|
||||
$$ = lang_new_vers_node (NULL, $3);
|
||||
}
|
||||
| GLOBAL ':' vers_defns ';' LOCAL ':' vers_defns ';'
|
||||
{
|
||||
$$ = lang_new_vers_node ($3, $7);
|
||||
}
|
||||
;
|
||||
|
||||
vers_defns:
|
||||
VERS_IDENTIFIER
|
||||
{
|
||||
$$ = lang_new_vers_regex (NULL, $1);
|
||||
}
|
||||
| vers_defns ';' VERS_IDENTIFIER
|
||||
{
|
||||
$$ = lang_new_vers_regex ($1, $3);
|
||||
}
|
||||
;
|
||||
|
||||
%%
|
||||
void
|
||||
yyerror(arg)
|
||||
const char *arg;
|
||||
{
|
||||
if (ldfile_assumed_script)
|
||||
einfo ("%P:%s: file format not recognized; treating as linker script\n",
|
||||
einfo (_("%P:%s: file format not recognized; treating as linker script\n"),
|
||||
ldfile_input_filename);
|
||||
if (error_index > 0 && error_index < ERROR_NAME_MAX)
|
||||
einfo ("%P%F:%S: %s in %s\n", arg, error_names[error_index-1]);
|
||||
|
213
ld/ldlang.c
213
ld/ldlang.c
@ -141,6 +141,17 @@ static int topower PARAMS ((int));
|
||||
static void lang_set_startof PARAMS ((void));
|
||||
static void reset_memory_regions PARAMS ((void));
|
||||
static void lang_record_phdrs PARAMS ((void));
|
||||
static void lang_gc_wild_section
|
||||
PARAMS ((lang_wild_statement_type *, const char *,
|
||||
lang_input_statement_type *));
|
||||
static void lang_gc_wild_file
|
||||
PARAMS ((lang_wild_statement_type *, const char *,
|
||||
lang_input_statement_type *));
|
||||
static void lang_gc_wild
|
||||
PARAMS ((lang_wild_statement_type *, const char *, const char *));
|
||||
static void lang_gc_sections_1 PARAMS ((lang_statement_union_type *));
|
||||
static void lang_gc_sections PARAMS ((void));
|
||||
|
||||
|
||||
/* EXPORTS */
|
||||
lang_output_section_statement_type *abs_output_section;
|
||||
@ -1056,6 +1067,11 @@ wild_section (ptr, section, file, output)
|
||||
{
|
||||
lang_statement_union_type *before;
|
||||
|
||||
/* If the wild pattern was marked KEEP, the member sections
|
||||
should be as well. */
|
||||
if (ptr->keep_sections)
|
||||
s->flags |= SEC_KEEP;
|
||||
|
||||
before = wild_sort (ptr, file, s);
|
||||
|
||||
/* Here BEFORE points to the lang_input_section which
|
||||
@ -2792,7 +2808,7 @@ lang_finish ()
|
||||
else
|
||||
{
|
||||
bfd_vma val;
|
||||
char *send;
|
||||
CONST char *send;
|
||||
|
||||
/* We couldn't find the entry symbol. Try parsing it as a
|
||||
number. */
|
||||
@ -3333,6 +3349,192 @@ reset_memory_regions ()
|
||||
}
|
||||
}
|
||||
|
||||
/* ??? At some point this traversal for GC should share code with the
|
||||
traversal for manipulating the output file. */
|
||||
|
||||
/* Expand a wild statement for a particular FILE, marking its sections KEEP
|
||||
as needed. SECTION may be NULL, in which case it is a wild card. */
|
||||
|
||||
static void
|
||||
lang_gc_wild_section (ptr, section, file)
|
||||
lang_wild_statement_type *ptr;
|
||||
const char *section;
|
||||
lang_input_statement_type *file;
|
||||
{
|
||||
if (file->just_syms_flag == false)
|
||||
{
|
||||
register asection *s;
|
||||
boolean wildcard;
|
||||
|
||||
if (section == NULL)
|
||||
wildcard = false;
|
||||
else
|
||||
wildcard = wildcardp (section);
|
||||
|
||||
for (s = file->the_bfd->sections; s != NULL; s = s->next)
|
||||
{
|
||||
boolean match;
|
||||
|
||||
if (section == NULL)
|
||||
match = true;
|
||||
else
|
||||
{
|
||||
const char *name;
|
||||
|
||||
name = bfd_get_section_name (file->the_bfd, s);
|
||||
if (wildcard)
|
||||
match = fnmatch (section, name, 0) == 0 ? true : false;
|
||||
else
|
||||
match = strcmp (section, name) == 0 ? true : false;
|
||||
}
|
||||
|
||||
if (match)
|
||||
{
|
||||
/* If the wild pattern was marked KEEP, the member sections
|
||||
should be as well. */
|
||||
if (ptr->keep_sections)
|
||||
s->flags |= SEC_KEEP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle a wild statement for a single file F. */
|
||||
|
||||
static void
|
||||
lang_gc_wild_file (s, section, f)
|
||||
lang_wild_statement_type *s;
|
||||
const char *section;
|
||||
lang_input_statement_type *f;
|
||||
{
|
||||
if (f->the_bfd == NULL
|
||||
|| ! bfd_check_format (f->the_bfd, bfd_archive))
|
||||
lang_gc_wild_section (s, section, f);
|
||||
else
|
||||
{
|
||||
bfd *member;
|
||||
|
||||
/* This is an archive file. We must map each member of the
|
||||
archive separately. */
|
||||
member = bfd_openr_next_archived_file (f->the_bfd, (bfd *) NULL);
|
||||
while (member != NULL)
|
||||
{
|
||||
/* When lookup_name is called, it will call the add_symbols
|
||||
entry point for the archive. For each element of the
|
||||
archive which is included, BFD will call ldlang_add_file,
|
||||
which will set the usrdata field of the member to the
|
||||
lang_input_statement. */
|
||||
if (member->usrdata != NULL)
|
||||
{
|
||||
lang_gc_wild_section (s, section,
|
||||
(lang_input_statement_type *) member->usrdata);
|
||||
}
|
||||
|
||||
member = bfd_openr_next_archived_file (f->the_bfd, member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle a wild statement, marking it against GC. SECTION or FILE or both
|
||||
may be NULL, indicating that it is a wildcard. */
|
||||
|
||||
static void
|
||||
lang_gc_wild (s, section, file)
|
||||
lang_wild_statement_type *s;
|
||||
const char *section;
|
||||
const char *file;
|
||||
{
|
||||
lang_input_statement_type *f;
|
||||
|
||||
if (file == (char *) NULL)
|
||||
{
|
||||
/* Perform the iteration over all files in the list */
|
||||
for (f = (lang_input_statement_type *) file_chain.head;
|
||||
f != (lang_input_statement_type *) NULL;
|
||||
f = (lang_input_statement_type *) f->next)
|
||||
{
|
||||
lang_gc_wild_file (s, section, f);
|
||||
}
|
||||
}
|
||||
else if (wildcardp (file))
|
||||
{
|
||||
for (f = (lang_input_statement_type *) file_chain.head;
|
||||
f != (lang_input_statement_type *) NULL;
|
||||
f = (lang_input_statement_type *) f->next)
|
||||
{
|
||||
if (fnmatch (file, f->filename, FNM_FILE_NAME) == 0)
|
||||
lang_gc_wild_file (s, section, f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Perform the iteration over a single file */
|
||||
f = lookup_name (file);
|
||||
lang_gc_wild_file (s, section, f);
|
||||
}
|
||||
}
|
||||
|
||||
/* Iterate over sections marking them against GC. */
|
||||
|
||||
static void
|
||||
lang_gc_sections_1 (s)
|
||||
lang_statement_union_type * s;
|
||||
{
|
||||
for (; s != (lang_statement_union_type *) NULL; s = s->next)
|
||||
{
|
||||
switch (s->header.type)
|
||||
{
|
||||
case lang_wild_statement_enum:
|
||||
lang_gc_wild (&s->wild_statement,
|
||||
s->wild_statement.section_name,
|
||||
s->wild_statement.filename);
|
||||
break;
|
||||
case lang_constructors_statement_enum:
|
||||
lang_gc_sections_1 (constructor_list.head);
|
||||
break;
|
||||
case lang_output_section_statement_enum:
|
||||
lang_gc_sections_1 (s->output_section_statement.children.head);
|
||||
break;
|
||||
case lang_group_statement_enum:
|
||||
lang_gc_sections_1 (s->group_statement.children.head);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lang_gc_sections ()
|
||||
{
|
||||
struct bfd_link_hash_entry *h;
|
||||
ldlang_undef_chain_list_type *ulist, fake_list_start;
|
||||
|
||||
/* Keep all sections so marked in the link script. */
|
||||
|
||||
lang_gc_sections_1 (statement_list.head);
|
||||
|
||||
/* Keep all sections containing symbols undefined on the command-line.
|
||||
Handle the entry symbol at the same time. */
|
||||
|
||||
fake_list_start.next = ldlang_undef_chain_list_head;
|
||||
fake_list_start.name = entry_symbol;
|
||||
|
||||
for (ulist = &fake_list_start; ulist; ulist = ulist->next)
|
||||
{
|
||||
h = bfd_link_hash_lookup (link_info.hash, ulist->name,
|
||||
false, false, false);
|
||||
|
||||
if (h != (struct bfd_link_hash_entry *) NULL
|
||||
&& (h->type == bfd_link_hash_defined
|
||||
|| h->type == bfd_link_hash_defweak)
|
||||
&& ! bfd_is_abs_section (h->u.def.section))
|
||||
{
|
||||
h->u.def.section->flags |= SEC_KEEP;
|
||||
}
|
||||
}
|
||||
|
||||
bfd_gc_sections (output_bfd, &link_info);
|
||||
}
|
||||
|
||||
void
|
||||
lang_process ()
|
||||
{
|
||||
@ -3363,6 +3565,10 @@ lang_process ()
|
||||
files. */
|
||||
ldctor_build_sets ();
|
||||
|
||||
/* Remove unreferenced sections if asked to. */
|
||||
if (command_line.gc_sections)
|
||||
lang_gc_sections ();
|
||||
|
||||
/* Size up the common data */
|
||||
lang_common ();
|
||||
|
||||
@ -3443,11 +3649,13 @@ lang_process ()
|
||||
/* EXPORTED TO YACC */
|
||||
|
||||
void
|
||||
lang_add_wild (section_name, sections_sorted, filename, filenames_sorted)
|
||||
lang_add_wild (section_name, sections_sorted, filename, filenames_sorted,
|
||||
keep_sections)
|
||||
const char *const section_name;
|
||||
boolean sections_sorted;
|
||||
const char *const filename;
|
||||
boolean filenames_sorted;
|
||||
boolean keep_sections;
|
||||
{
|
||||
lang_wild_statement_type *new = new_stat (lang_wild_statement,
|
||||
stat_ptr);
|
||||
@ -3464,6 +3672,7 @@ lang_add_wild (section_name, sections_sorted, filename, filenames_sorted)
|
||||
new->sections_sorted = sections_sorted;
|
||||
new->filename = filename;
|
||||
new->filenames_sorted = filenames_sorted;
|
||||
new->keep_sections = keep_sections;
|
||||
lang_list_init (&new->children);
|
||||
}
|
||||
|
||||
|
71
ld/ldlex.l
71
ld/ldlex.l
@ -1,6 +1,7 @@
|
||||
%{
|
||||
|
||||
/* Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GLD, the Gnu Linker.
|
||||
|
||||
@ -15,8 +16,9 @@ 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 GLD; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
along with GLD; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
|
||||
/*
|
||||
This was written by steve chamberlain
|
||||
@ -48,9 +50,6 @@ This was written by steve chamberlain
|
||||
yylex and yyparse (indirectly) both check this. */
|
||||
input_type parser_input;
|
||||
|
||||
/* Radix to use for bfd_scan_vma -- 0 (default to base 10) or 16. */
|
||||
int hex_mode;
|
||||
|
||||
/* Line number in the current input file.
|
||||
(FIXME Actually, it doesn't appear to get reset for each file?) */
|
||||
unsigned int lineno = 1;
|
||||
@ -115,7 +114,7 @@ WHITE [ \t\n\r]+
|
||||
NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~]
|
||||
|
||||
V_TAG [.$_a-zA-Z][._a-zA-Z0-9]*
|
||||
V_IDENTIFIER [*?$_a-zA-Z][*?_a-zA-Z0-9]*
|
||||
V_IDENTIFIER [*?.$_a-zA-Z][*?_a-zA-Z0-9]*
|
||||
|
||||
%s SCRIPT
|
||||
%s EXPRESSION
|
||||
@ -179,17 +178,18 @@ V_IDENTIFIER [*?$_a-zA-Z][*?_a-zA-Z0-9]*
|
||||
ibase);
|
||||
return INT;
|
||||
}
|
||||
<SCRIPT,DEFSYMEXP,MRI,BOTH,EXPRESSION>"$"?"0x"?([0-9A-Fa-f])+(M|K|m|k)? {
|
||||
yylval.integer = bfd_scan_vma (yytext, 0,
|
||||
hex_mode);
|
||||
if (yytext[yyleng-1]=='M'
|
||||
|| yytext[yyleng-1] == 'm') {
|
||||
yylval.integer *= 1024*1024;
|
||||
}
|
||||
if (yytext[yyleng-1]=='K'
|
||||
|| yytext[yyleng-1]=='k') {
|
||||
yylval.integer *= 1024;
|
||||
}
|
||||
<SCRIPT,DEFSYMEXP,MRI,BOTH,EXPRESSION>((("$"|"0x")([0-9A-Fa-f])+)|(([0-9])+))(M|K|m|k)? {
|
||||
char *s = yytext;
|
||||
|
||||
if (*s == '$')
|
||||
++s;
|
||||
yylval.integer = bfd_scan_vma (s, 0, 0);
|
||||
if (yytext[yyleng-1] == 'M'
|
||||
|| yytext[yyleng-1] == 'm')
|
||||
yylval.integer *= 1024 * 1024;
|
||||
if (yytext[yyleng-1] == 'K'
|
||||
|| yytext[yyleng-1]=='k')
|
||||
yylval.integer *= 1024;
|
||||
return INT;
|
||||
}
|
||||
<BOTH,SCRIPT,EXPRESSION,MRI>"]" { RTOKEN(']');}
|
||||
@ -232,7 +232,7 @@ V_IDENTIFIER [*?$_a-zA-Z][*?_a-zA-Z0-9]*
|
||||
<BOTH,SCRIPT,EXPRESSION,MRI>";" { RTOKEN(';');}
|
||||
<BOTH,SCRIPT>"MEMORY" { RTOKEN(MEMORY);}
|
||||
<BOTH,SCRIPT>"ORIGIN" { RTOKEN(ORIGIN);}
|
||||
<BOTH,SCRIPT>"VERSION" { RTOKEN(VERSION);}
|
||||
<BOTH,SCRIPT>"VERSION" { RTOKEN(VERSIONK);}
|
||||
<EXPRESSION,BOTH,SCRIPT>"BLOCK" { RTOKEN(BLOCK);}
|
||||
<EXPRESSION,BOTH,SCRIPT>"BIND" { RTOKEN(BIND);}
|
||||
<BOTH,SCRIPT>"LENGTH" { RTOKEN(LENGTH);}
|
||||
@ -272,6 +272,7 @@ V_IDENTIFIER [*?$_a-zA-Z][*?_a-zA-Z0-9]*
|
||||
<BOTH,SCRIPT>"NOFLOAT" { RTOKEN(NOFLOAT);}
|
||||
<EXPRESSION,BOTH,SCRIPT>"NOCROSSREFS" { RTOKEN(NOCROSSREFS);}
|
||||
<BOTH,SCRIPT>"OVERLAY" { RTOKEN(OVERLAY); }
|
||||
<BOTH,SCRIPT>"SORT" { RTOKEN(SORT); }
|
||||
<EXPRESSION,BOTH,SCRIPT>"NOLOAD" { RTOKEN(NOLOAD);}
|
||||
<EXPRESSION,BOTH,SCRIPT>"DSECT" { RTOKEN(DSECT);}
|
||||
<EXPRESSION,BOTH,SCRIPT>"COPY" { RTOKEN(COPY);}
|
||||
@ -285,9 +286,9 @@ V_IDENTIFIER [*?$_a-zA-Z][*?_a-zA-Z0-9]*
|
||||
<BOTH,SCRIPT>"PHDRS" { RTOKEN (PHDRS); }
|
||||
<EXPRESSION,BOTH,SCRIPT>"AT" { RTOKEN(AT);}
|
||||
<EXPRESSION,BOTH,SCRIPT>"PROVIDE" { RTOKEN(PROVIDE); }
|
||||
<MRI>"#".*\n?\r? { ++ lineno; }
|
||||
<EXPRESSION,BOTH,SCRIPT>"KEEP" { RTOKEN(KEEP); }
|
||||
<MRI>"#".*\n? { ++ lineno; }
|
||||
<MRI>"\n" { ++ lineno; RTOKEN(NEWLINE); }
|
||||
<MRI>"\r" { ++ lineno; RTOKEN(NEWLINE); }
|
||||
<MRI>"*".* { /* Mri comment line */ }
|
||||
<MRI>";".* { /* Mri comment line */ }
|
||||
<MRI>"END" { RTOKEN(ENDWORD); }
|
||||
@ -342,7 +343,22 @@ V_IDENTIFIER [*?$_a-zA-Z][*?_a-zA-Z0-9]*
|
||||
yylval.name = buystring (yytext + 2);
|
||||
return LNAME;
|
||||
}
|
||||
<SCRIPT>{WILDCHAR}* { yylval.name = buystring(yytext); return NAME; }
|
||||
<SCRIPT>{WILDCHAR}* {
|
||||
/* Annoyingly, this pattern can match comments, and we have
|
||||
longest match issues to consider. So if the first two
|
||||
characters are a comment opening, put the input back and
|
||||
try again. */
|
||||
if (yytext[0] == '/' && yytext[1] == '*')
|
||||
{
|
||||
yyless(2);
|
||||
comment ();
|
||||
}
|
||||
else
|
||||
{
|
||||
yylval.name = buystring(yytext);
|
||||
return NAME;
|
||||
}
|
||||
}
|
||||
|
||||
<EXPRESSION,BOTH,SCRIPT>"\""[^\"]*"\"" {
|
||||
/* No matter the state, quotes
|
||||
@ -352,8 +368,7 @@ V_IDENTIFIER [*?$_a-zA-Z][*?_a-zA-Z0-9]*
|
||||
return NAME;
|
||||
}
|
||||
<BOTH,SCRIPT,EXPRESSION>"\n" { lineno++;}
|
||||
<BOTH,SCRIPT,EXPRESSION>"\r" { lineno++;}
|
||||
<MRI,BOTH,SCRIPT,EXPRESSION>[ \t]
|
||||
<MRI,BOTH,SCRIPT,EXPRESSION>[ \t\r]+ { }
|
||||
|
||||
<VERS_NODE,VERS_SCRIPT>[:,;] { return *yytext; }
|
||||
|
||||
@ -372,11 +387,11 @@ V_IDENTIFIER [*?$_a-zA-Z][*?_a-zA-Z0-9]*
|
||||
<VERS_SCRIPT>"{" { BEGIN(VERS_NODE); return *yytext; }
|
||||
<VERS_SCRIPT,VERS_NODE>"}" { BEGIN(VERS_SCRIPT); return *yytext; }
|
||||
|
||||
<VERS_START,VERS_NODE,VERS_SCRIPT>[\n\r] { lineno++; }
|
||||
<VERS_START,VERS_NODE,VERS_SCRIPT>[\n] { lineno++; }
|
||||
|
||||
<VERS_START,VERS_NODE,VERS_SCRIPT>#.* { /* Eat up comments */ }
|
||||
|
||||
<VERS_START,VERS_NODE,VERS_SCRIPT>[ \t]+ { /* Eat up whitespace */ }
|
||||
<VERS_START,VERS_NODE,VERS_SCRIPT>[ \t\r]+ { /* Eat up whitespace */ }
|
||||
|
||||
<<EOF>> {
|
||||
include_stack_ptr--;
|
||||
@ -580,7 +595,7 @@ comment ()
|
||||
c = input();
|
||||
while (c != '*' && c != EOF)
|
||||
{
|
||||
if (c == '\n' || c == '\r')
|
||||
if (c == '\n')
|
||||
lineno++;
|
||||
c = input();
|
||||
}
|
||||
@ -594,7 +609,7 @@ comment ()
|
||||
break; /* found the end */
|
||||
}
|
||||
|
||||
if (c == '\n' || c == '\r')
|
||||
if (c == '\n')
|
||||
lineno++;
|
||||
|
||||
if (c == EOF)
|
||||
|
19
ld/lexsup.c
19
ld/lexsup.c
@ -111,6 +111,8 @@ int parsing_defsym = 0;
|
||||
#define OPTION_WHOLE_ARCHIVE (OPTION_SPLIT_BY_FILE + 1)
|
||||
#define OPTION_WRAP (OPTION_WHOLE_ARCHIVE + 1)
|
||||
#define OPTION_FORCE_EXE_SUFFIX (OPTION_WRAP + 1)
|
||||
#define OPTION_GC_SECTIONS (OPTION_FORCE_EXE_SUFFIX + 1)
|
||||
#define OPTION_NO_GC_SECTIONS (OPTION_GC_SECTIONS + 1)
|
||||
|
||||
/* The long options. This structure is used for both the option
|
||||
parsing and the help text. */
|
||||
@ -163,6 +165,12 @@ static const struct ld_option ld_options[] =
|
||||
'F', N_("SHLIB"), N_("Filter for shared object symbol table"), TWO_DASHES },
|
||||
{ {NULL, no_argument, NULL, '\0'},
|
||||
'g', NULL, N_("Ignored"), ONE_DASH },
|
||||
{ {"gc-sections", no_argument, NULL, OPTION_GC_SECTIONS},
|
||||
'\0', NULL, N_("Remove unused sections on certain targets"),
|
||||
TWO_DASHES },
|
||||
{ {"no-gc-sections", no_argument, NULL, OPTION_NO_GC_SECTIONS},
|
||||
'\0', NULL, N_("(Don't) Remove unused sections on certain targets"),
|
||||
TWO_DASHES },
|
||||
{ {"gpsize", required_argument, NULL, 'G'},
|
||||
'G', N_("SIZE"), N_("Small data size (if no size, same as --shared)"),
|
||||
TWO_DASHES },
|
||||
@ -575,6 +583,9 @@ parse_args (argc, argv)
|
||||
case 'g':
|
||||
/* Ignore. */
|
||||
break;
|
||||
case OPTION_GC_SECTIONS:
|
||||
command_line.gc_sections = true;
|
||||
break;
|
||||
case OPTION_HELP:
|
||||
help ();
|
||||
xexit (0);
|
||||
@ -604,6 +615,9 @@ parse_args (argc, argv)
|
||||
config.magic_demand_paged = false;
|
||||
config.dynamic_link = false;
|
||||
break;
|
||||
case OPTION_NO_GC_SECTIONS:
|
||||
command_line.gc_sections = false;
|
||||
break;
|
||||
case OPTION_NO_KEEP_MEMORY:
|
||||
link_info.keep_memory = false;
|
||||
break;
|
||||
@ -701,7 +715,10 @@ parse_args (argc, argv)
|
||||
link_info.strip = strip_all;
|
||||
break;
|
||||
case OPTION_SHARED:
|
||||
link_info.shared = true;
|
||||
if (config.has_shared)
|
||||
link_info.shared = true;
|
||||
else
|
||||
einfo (_("%P%F: -shared not supported\n"));
|
||||
break;
|
||||
case 'h': /* Used on Solaris. */
|
||||
case OPTION_SONAME:
|
||||
|
@ -56,11 +56,23 @@ SECTIONS
|
||||
.gnu.version_d ${RELOCATING-0} : { *(.gnu.version_d) }
|
||||
.gnu.version_r ${RELOCATING-0} : { *(.gnu.version_r) }
|
||||
.rela.text ${RELOCATING-0} :
|
||||
{ *(.rela.text) *(.rela.gnu.linkonce.t*) }
|
||||
{
|
||||
*(.rela.text)
|
||||
${RELOCATING+*(.rela.text.*)}
|
||||
${RELOCATING+*(.rela.gnu.linkonce.t*)}
|
||||
}
|
||||
.rela.data ${RELOCATING-0} :
|
||||
{ *(.rela.data) *(.rela.gnu.linkonce.d*) }
|
||||
{
|
||||
*(.rela.data)
|
||||
${RELOCATING+*(.rela.data.*)}
|
||||
${RELOCATING+*(.rela.gnu.linkonce.d*)}
|
||||
}
|
||||
.rela.rodata ${RELOCATING-0} :
|
||||
{ *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
|
||||
{
|
||||
*(.rela.rodata)
|
||||
${RELOCATING+*(.rela.rodata.*)}
|
||||
${RELOCATING+*(.rela.gnu.linkonce.r*)}
|
||||
}
|
||||
.rela.got ${RELOCATING-0} : { *(.rela.got) }
|
||||
.rela.got1 ${RELOCATING-0} : { *(.rela.got1) }
|
||||
.rela.got2 ${RELOCATING-0} : { *(.rela.got2) }
|
||||
@ -78,13 +90,19 @@ SECTIONS
|
||||
{
|
||||
${RELOCATING+${TEXT_START_SYMBOLS}}
|
||||
*(.text)
|
||||
${RELOCATING+*(.text.*)}
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
*(.gnu.linkonce.t*)
|
||||
${RELOCATING+*(.gnu.linkonce.t*)}
|
||||
} =${NOP-0}
|
||||
.init ${RELOCATING-0} : { *(.init) } =${NOP-0}
|
||||
.fini ${RELOCATING-0} : { *(.fini) } =${NOP-0}
|
||||
.rodata ${RELOCATING-0} : { *(.rodata) *(.gnu.linkonce.r*) }
|
||||
.init ${RELOCATING-0} : { KEEP (*(.init)) } =${NOP-0}
|
||||
.fini ${RELOCATING-0} : { KEEP (*(.fini)) } =${NOP-0}
|
||||
.rodata ${RELOCATING-0} :
|
||||
{
|
||||
*(.rodata)
|
||||
${RELOCATING+*(.rodata.*)}
|
||||
${RELOCATING+*(.gnu.linkonce.r*)}
|
||||
}
|
||||
.rodata1 ${RELOCATING-0} : { *(.rodata1) }
|
||||
${RELOCATING+_etext = .;}
|
||||
${RELOCATING+PROVIDE (etext = .);}
|
||||
@ -112,7 +130,8 @@ SECTIONS
|
||||
{
|
||||
${RELOCATING+${DATA_START_SYMBOLS}}
|
||||
*(.data)
|
||||
*(.gnu.linkonce.d*)
|
||||
${RELOCATING+*(.data.*)}
|
||||
${RELOCATING+*(.gnu.linkonce.d*)}
|
||||
${CONSTRUCTING+CONSTRUCTORS}
|
||||
}
|
||||
.data1 ${RELOCATING-0} : { *(.data1) }
|
||||
@ -139,16 +158,16 @@ SECTIONS
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
*crtbegin.o(.ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors) }
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors)) }
|
||||
${RELOCATING+PROVIDE (__CTOR_END__ = .);}
|
||||
|
||||
${RELOCATING+PROVIDE (__DTOR_LIST__ = .);}
|
||||
.dtors ${RELOCATING-0} : {
|
||||
*crtbegin.o(.dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors) }
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors)) }
|
||||
${RELOCATING+PROVIDE (__DTOR_END__ = .);}
|
||||
|
||||
${RELOCATING+PROVIDE (_FIXUP_START_ = .);}
|
||||
|
Loading…
Reference in New Issue
Block a user