* 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
8 changed files with 620 additions and 99 deletions
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>
|
Tue Jun 23 15:17:27 1998 Ian Lance Taylor <ian@cygnus.com>
|
||||||
|
|
||||||
* Makefile.am (install-data-local): Make ldscripts subdirectory.
|
* 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
|
/* Name of shared object for whose symbol table this shared object
|
||||||
is an auxiliary filter. From the --auxiliary option. */
|
is an auxiliary filter. From the --auxiliary option. */
|
||||||
char **auxiliary_filters;
|
char **auxiliary_filters;
|
||||||
|
|
||||||
|
/* Remove unreferenced sections? */
|
||||||
|
boolean gc_sections;
|
||||||
} args_type;
|
} args_type;
|
||||||
|
|
||||||
extern args_type command_line;
|
extern args_type command_line;
|
||||||
|
@ -153,6 +156,12 @@ typedef struct
|
||||||
/* If true, doing a dynamic link. */
|
/* If true, doing a dynamic link. */
|
||||||
boolean 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. */
|
/* If true, build constructors. */
|
||||||
boolean 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
|
MIPS ECOFF which supports putting large and small objects into different
|
||||||
sections. This is ignored for other object file formats.
|
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
|
@cindex runtime library name
|
||||||
@kindex -h@var{name}
|
@kindex -h@var{name}
|
||||||
@kindex -soname=@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.
|
instructions in the output object file.
|
||||||
|
|
||||||
On some platforms these link time global optimizations may make symbolic
|
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.
|
the case for the Matsushita MN10200 and MN10300 family of processors.
|
||||||
|
@end ifset
|
||||||
|
|
||||||
@ifset GENERIC
|
@ifset GENERIC
|
||||||
On platforms where this is not supported, @samp{--relax} is accepted,
|
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 Basics:: Input section basics
|
||||||
* Input Section Wildcards:: Input section wildcard patterns
|
* Input Section Wildcards:: Input section wildcard patterns
|
||||||
* Input Section Common:: Input section for common symbols
|
* Input Section Common:: Input section for common symbols
|
||||||
|
* Input Section Keep:: Input section and garbage collection
|
||||||
* Input Section Example:: Input section example
|
* Input Section Example:: Input section example
|
||||||
@end menu
|
@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
|
notation is now considered obsolete. It is equivalent to
|
||||||
@samp{*(COMMON)}.
|
@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
|
@node Input Section Example
|
||||||
@subsubsection Input section example
|
@subsubsection Input section example
|
||||||
The following example is a complete linker script. It tells the linker
|
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
|
section command, such as a symbol assignment, then the output section
|
||||||
will always be created, even if there are no matching input sections.
|
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
|
The special output section name @samp{/DISCARD/} may be used to discard
|
||||||
input sections. Any input sections which are assigned to an output
|
input sections. Any input sections which are assigned to an output
|
||||||
section named @samp{/DISCARD/} are not included in the output file.
|
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.
|
/* 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).
|
Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
|
||||||
|
|
||||||
This file is part of GNU ld.
|
This file is part of GNU ld.
|
||||||
|
@ -47,15 +48,14 @@ static enum section_type sectype;
|
||||||
|
|
||||||
lang_memory_region_type *region;
|
lang_memory_region_type *region;
|
||||||
|
|
||||||
|
struct wildcard_spec current_file;
|
||||||
char *current_file;
|
|
||||||
boolean ldgram_want_filename = true;
|
boolean ldgram_want_filename = true;
|
||||||
boolean had_script = false;
|
boolean had_script = false;
|
||||||
boolean force_make_executable = false;
|
boolean force_make_executable = false;
|
||||||
|
|
||||||
boolean ldgram_in_script = false;
|
boolean ldgram_in_script = false;
|
||||||
boolean ldgram_had_equals = false;
|
boolean ldgram_had_equals = false;
|
||||||
|
boolean ldgram_had_keep = false;
|
||||||
|
|
||||||
#define ERROR_NAME_MAX 20
|
#define ERROR_NAME_MAX 20
|
||||||
static char *error_names[ERROR_NAME_MAX];
|
static char *error_names[ERROR_NAME_MAX];
|
||||||
|
@ -66,6 +66,8 @@ static int error_index;
|
||||||
%union {
|
%union {
|
||||||
bfd_vma integer;
|
bfd_vma integer;
|
||||||
char *name;
|
char *name;
|
||||||
|
const char *cname;
|
||||||
|
struct wildcard_spec wildcard;
|
||||||
int token;
|
int token;
|
||||||
union etree_union *etree;
|
union etree_union *etree;
|
||||||
struct phdr_info
|
struct phdr_info
|
||||||
|
@ -76,16 +78,25 @@ static int error_index;
|
||||||
union etree_union *flags;
|
union etree_union *flags;
|
||||||
} phdr;
|
} phdr;
|
||||||
struct lang_nocrossref *nocrossref;
|
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> exp opt_exp_with_type mustbe_exp opt_at phdr_type phdr_val
|
||||||
|
%type <etree> opt_exp_without_type
|
||||||
%type <integer> fill_opt
|
%type <integer> fill_opt
|
||||||
%type <name> memspec_opt casesymlist
|
%type <name> memspec_opt casesymlist
|
||||||
|
%type <cname> wildcard_name
|
||||||
|
%type <wildcard> wildcard_spec
|
||||||
%token <integer> INT
|
%token <integer> INT
|
||||||
%token <name> NAME LNAME
|
%token <name> NAME LNAME
|
||||||
%type <integer> length
|
%type <integer> length
|
||||||
%type <phdr> phdr_qualifiers
|
%type <phdr> phdr_qualifiers
|
||||||
%type <nocrossref> nocrossref_list
|
%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> PLUSEQ MINUSEQ MULTEQ DIVEQ '=' LSHIFTEQ RSHIFTEQ ANDEQ OREQ
|
||||||
%right <token> '?' ':'
|
%right <token> '?' ':'
|
||||||
|
@ -104,8 +115,8 @@ static int error_index;
|
||||||
%right UNARY
|
%right UNARY
|
||||||
%token END
|
%token END
|
||||||
%left <token> '('
|
%left <token> '('
|
||||||
%token <token> ALIGN_K BLOCK BIND QUAD LONG SHORT BYTE
|
%token <token> ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE
|
||||||
%token SECTIONS PHDRS
|
%token SECTIONS PHDRS SORT
|
||||||
%token '{' '}'
|
%token '{' '}'
|
||||||
%token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
|
%token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
|
||||||
%token SIZEOF_HEADERS
|
%token SIZEOF_HEADERS
|
||||||
|
@ -113,7 +124,8 @@ static int error_index;
|
||||||
%token MEMORY DEFSYMEND
|
%token MEMORY DEFSYMEND
|
||||||
%token NOLOAD DSECT COPY INFO OVERLAY
|
%token NOLOAD DSECT COPY INFO OVERLAY
|
||||||
%token NAME LNAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY
|
%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 STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS
|
||||||
%token ORIGIN FILL
|
%token ORIGIN FILL
|
||||||
%token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
|
%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 CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD
|
||||||
%token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
|
%token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
|
||||||
%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
|
%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:
|
file:
|
||||||
INPUT_SCRIPT script_file
|
INPUT_SCRIPT script_file
|
||||||
| INPUT_MRI_SCRIPT mri_script_file
|
| INPUT_MRI_SCRIPT mri_script_file
|
||||||
|
| INPUT_VERSION_SCRIPT version_script_file
|
||||||
| INPUT_DEFSYM defsym_expr
|
| INPUT_DEFSYM defsym_expr
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -148,7 +167,7 @@ defsym_expr:
|
||||||
mri_script_file:
|
mri_script_file:
|
||||||
{
|
{
|
||||||
ldlex_mri_script ();
|
ldlex_mri_script ();
|
||||||
PUSH_ERROR ("MRI style script");
|
PUSH_ERROR (_("MRI style script"));
|
||||||
}
|
}
|
||||||
mri_script_lines
|
mri_script_lines
|
||||||
{
|
{
|
||||||
|
@ -167,7 +186,7 @@ mri_script_command:
|
||||||
CHIP exp
|
CHIP exp
|
||||||
| CHIP exp ',' exp
|
| CHIP exp ',' exp
|
||||||
| NAME {
|
| 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 {
|
| LIST {
|
||||||
config.map_filename = "-";
|
config.map_filename = "-";
|
||||||
|
@ -276,6 +295,7 @@ ifile_p1:
|
||||||
| low_level_library
|
| low_level_library
|
||||||
| floating_point_support
|
| floating_point_support
|
||||||
| statement_anywhere
|
| statement_anywhere
|
||||||
|
| version
|
||||||
| ';'
|
| ';'
|
||||||
| TARGET_K '(' NAME ')'
|
| TARGET_K '(' NAME ')'
|
||||||
{ lang_add_target($3); }
|
{ lang_add_target($3); }
|
||||||
|
@ -346,49 +366,79 @@ statement_anywhere:
|
||||||
|
|
||||||
/* The '*' and '?' cases are there because the lexer returns them as
|
/* The '*' and '?' cases are there because the lexer returns them as
|
||||||
separate tokens rather than as NAME. */
|
separate tokens rather than as NAME. */
|
||||||
file_NAME_list:
|
wildcard_name:
|
||||||
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 '?'
|
wildcard_spec:
|
||||||
{ lang_add_wild ("?", current_file); }
|
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:
|
input_section_spec:
|
||||||
NAME
|
input_section_spec_no_keep
|
||||||
{
|
| KEEP '('
|
||||||
lang_add_wild((char *)NULL, $1);
|
{ ldgram_had_keep = true; }
|
||||||
}
|
input_section_spec_no_keep ')'
|
||||||
| '['
|
{ ldgram_had_keep = false; }
|
||||||
{
|
|
||||||
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 ')'
|
|
||||||
;
|
;
|
||||||
|
|
||||||
statement:
|
statement:
|
||||||
|
@ -432,6 +482,8 @@ statement_list_opt:
|
||||||
length:
|
length:
|
||||||
QUAD
|
QUAD
|
||||||
{ $$ = $1; }
|
{ $$ = $1; }
|
||||||
|
| SQUAD
|
||||||
|
{ $$ = $1; }
|
||||||
| LONG
|
| LONG
|
||||||
{ $$ = $1; }
|
{ $$ = $1; }
|
||||||
| SHORT
|
| SHORT
|
||||||
|
@ -523,7 +575,9 @@ memory_spec: NAME
|
||||||
region->origin =
|
region->origin =
|
||||||
exp_get_vma($3, 0L,"origin", lang_first_phase_enum);
|
exp_get_vma($3, 0L,"origin", lang_first_phase_enum);
|
||||||
}
|
}
|
||||||
; length_spec:
|
;
|
||||||
|
|
||||||
|
length_spec:
|
||||||
LENGTH '=' mustbe_exp
|
LENGTH '=' mustbe_exp
|
||||||
{ region->length = exp_get_vma($3,
|
{ region->length = exp_get_vma($3,
|
||||||
~((bfd_vma)0),
|
~((bfd_vma)0),
|
||||||
|
@ -535,7 +589,7 @@ memory_spec: NAME
|
||||||
attributes_opt:
|
attributes_opt:
|
||||||
'(' NAME ')'
|
'(' NAME ')'
|
||||||
{
|
{
|
||||||
lang_set_flags(®ion->flags, $2);
|
lang_set_flags(region, $2);
|
||||||
}
|
}
|
||||||
|
|
|
|
||||||
|
|
||||||
|
@ -678,6 +732,10 @@ exp :
|
||||||
{ $$ = exp_unop(ALIGN_K,$3); }
|
{ $$ = exp_unop(ALIGN_K,$3); }
|
||||||
| NAME
|
| NAME
|
||||||
{ $$ = exp_nameop(NAME,$1); }
|
{ $$ = 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 (); }
|
'}' { ldlex_popstate (); ldlex_expression (); }
|
||||||
memspec_opt phdr_opt fill_opt
|
memspec_opt phdr_opt fill_opt
|
||||||
{
|
{
|
||||||
ldlex_popstate();
|
ldlex_popstate ();
|
||||||
lang_leave_output_section_statement($13, $11);
|
lang_leave_output_section_statement ($13, $11, $12);
|
||||||
}
|
}
|
||||||
opt_comma
|
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
|
| /* The GROUP case is just enough to support the gcc
|
||||||
svr3.ifile script. It is not intended to be full
|
svr3.ifile script. It is not intended to be full
|
||||||
support. I'm not even sure what GROUP is supposed
|
support. I'm not even sure what GROUP is supposed
|
||||||
|
@ -727,6 +802,7 @@ type:
|
||||||
atype:
|
atype:
|
||||||
'(' type ')'
|
'(' type ')'
|
||||||
| /* EMPTY */ { sectype = normal_section; }
|
| /* EMPTY */ { sectype = normal_section; }
|
||||||
|
| '(' ')' { sectype = normal_section; }
|
||||||
;
|
;
|
||||||
|
|
||||||
opt_exp_with_type:
|
opt_exp_with_type:
|
||||||
|
@ -741,6 +817,18 @@ opt_exp_with_type:
|
||||||
{ $$ = $3; }
|
{ $$ = $3; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
opt_exp_without_type:
|
||||||
|
exp ':' { $$ = $1; }
|
||||||
|
| ':' { $$ = (etree_type *) NULL; }
|
||||||
|
;
|
||||||
|
|
||||||
|
opt_nocrossrefs:
|
||||||
|
/* empty */
|
||||||
|
{ $$ = 0; }
|
||||||
|
| NOCROSSREFS
|
||||||
|
{ $$ = 1; }
|
||||||
|
;
|
||||||
|
|
||||||
memspec_opt:
|
memspec_opt:
|
||||||
'>' NAME
|
'>' NAME
|
||||||
{ $$ = $2; }
|
{ $$ = $2; }
|
||||||
|
@ -749,12 +837,40 @@ memspec_opt:
|
||||||
|
|
||||||
phdr_opt:
|
phdr_opt:
|
||||||
/* empty */
|
/* empty */
|
||||||
|
{
|
||||||
|
$$ = NULL;
|
||||||
|
}
|
||||||
| phdr_opt ':' NAME
|
| 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:
|
||||||
PHDRS '{' phdr_list '}'
|
PHDRS '{' phdr_list '}'
|
||||||
;
|
;
|
||||||
|
@ -819,7 +935,7 @@ phdr_qualifiers:
|
||||||
else if (strcmp ($1, "FLAGS") == 0 && $2 != NULL)
|
else if (strcmp ($1, "FLAGS") == 0 && $2 != NULL)
|
||||||
$$.flags = $2;
|
$$.flags = $2;
|
||||||
else
|
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
|
| 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
|
void
|
||||||
yyerror(arg)
|
yyerror(arg)
|
||||||
const char *arg;
|
const char *arg;
|
||||||
{
|
{
|
||||||
if (ldfile_assumed_script)
|
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);
|
ldfile_input_filename);
|
||||||
if (error_index > 0 && error_index < ERROR_NAME_MAX)
|
if (error_index > 0 && error_index < ERROR_NAME_MAX)
|
||||||
einfo ("%P%F:%S: %s in %s\n", arg, error_names[error_index-1]);
|
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 lang_set_startof PARAMS ((void));
|
||||||
static void reset_memory_regions PARAMS ((void));
|
static void reset_memory_regions PARAMS ((void));
|
||||||
static void lang_record_phdrs 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 */
|
/* EXPORTS */
|
||||||
lang_output_section_statement_type *abs_output_section;
|
lang_output_section_statement_type *abs_output_section;
|
||||||
|
@ -1056,6 +1067,11 @@ wild_section (ptr, section, file, output)
|
||||||
{
|
{
|
||||||
lang_statement_union_type *before;
|
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);
|
before = wild_sort (ptr, file, s);
|
||||||
|
|
||||||
/* Here BEFORE points to the lang_input_section which
|
/* Here BEFORE points to the lang_input_section which
|
||||||
|
@ -2792,7 +2808,7 @@ lang_finish ()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bfd_vma val;
|
bfd_vma val;
|
||||||
char *send;
|
CONST char *send;
|
||||||
|
|
||||||
/* We couldn't find the entry symbol. Try parsing it as a
|
/* We couldn't find the entry symbol. Try parsing it as a
|
||||||
number. */
|
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
|
void
|
||||||
lang_process ()
|
lang_process ()
|
||||||
{
|
{
|
||||||
|
@ -3363,6 +3565,10 @@ lang_process ()
|
||||||
files. */
|
files. */
|
||||||
ldctor_build_sets ();
|
ldctor_build_sets ();
|
||||||
|
|
||||||
|
/* Remove unreferenced sections if asked to. */
|
||||||
|
if (command_line.gc_sections)
|
||||||
|
lang_gc_sections ();
|
||||||
|
|
||||||
/* Size up the common data */
|
/* Size up the common data */
|
||||||
lang_common ();
|
lang_common ();
|
||||||
|
|
||||||
|
@ -3443,11 +3649,13 @@ lang_process ()
|
||||||
/* EXPORTED TO YACC */
|
/* EXPORTED TO YACC */
|
||||||
|
|
||||||
void
|
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;
|
const char *const section_name;
|
||||||
boolean sections_sorted;
|
boolean sections_sorted;
|
||||||
const char *const filename;
|
const char *const filename;
|
||||||
boolean filenames_sorted;
|
boolean filenames_sorted;
|
||||||
|
boolean keep_sections;
|
||||||
{
|
{
|
||||||
lang_wild_statement_type *new = new_stat (lang_wild_statement,
|
lang_wild_statement_type *new = new_stat (lang_wild_statement,
|
||||||
stat_ptr);
|
stat_ptr);
|
||||||
|
@ -3464,6 +3672,7 @@ lang_add_wild (section_name, sections_sorted, filename, filenames_sorted)
|
||||||
new->sections_sorted = sections_sorted;
|
new->sections_sorted = sections_sorted;
|
||||||
new->filename = filename;
|
new->filename = filename;
|
||||||
new->filenames_sorted = filenames_sorted;
|
new->filenames_sorted = filenames_sorted;
|
||||||
|
new->keep_sections = keep_sections;
|
||||||
lang_list_init (&new->children);
|
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.
|
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.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with GLD; see the file COPYING. If not, write to
|
along with GLD; see the file COPYING. If not, write to the Free
|
||||||
the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
02111-1307, USA. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This was written by steve chamberlain
|
This was written by steve chamberlain
|
||||||
|
@ -48,9 +50,6 @@ This was written by steve chamberlain
|
||||||
yylex and yyparse (indirectly) both check this. */
|
yylex and yyparse (indirectly) both check this. */
|
||||||
input_type parser_input;
|
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.
|
/* Line number in the current input file.
|
||||||
(FIXME Actually, it doesn't appear to get reset for each file?) */
|
(FIXME Actually, it doesn't appear to get reset for each file?) */
|
||||||
unsigned int lineno = 1;
|
unsigned int lineno = 1;
|
||||||
|
@ -115,7 +114,7 @@ WHITE [ \t\n\r]+
|
||||||
NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~]
|
NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~]
|
||||||
|
|
||||||
V_TAG [.$_a-zA-Z][._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 SCRIPT
|
||||||
%s EXPRESSION
|
%s EXPRESSION
|
||||||
|
@ -179,17 +178,18 @@ V_IDENTIFIER [*?$_a-zA-Z][*?_a-zA-Z0-9]*
|
||||||
ibase);
|
ibase);
|
||||||
return INT;
|
return INT;
|
||||||
}
|
}
|
||||||
<SCRIPT,DEFSYMEXP,MRI,BOTH,EXPRESSION>"$"?"0x"?([0-9A-Fa-f])+(M|K|m|k)? {
|
<SCRIPT,DEFSYMEXP,MRI,BOTH,EXPRESSION>((("$"|"0x")([0-9A-Fa-f])+)|(([0-9])+))(M|K|m|k)? {
|
||||||
yylval.integer = bfd_scan_vma (yytext, 0,
|
char *s = yytext;
|
||||||
hex_mode);
|
|
||||||
if (yytext[yyleng-1]=='M'
|
if (*s == '$')
|
||||||
|| yytext[yyleng-1] == 'm') {
|
++s;
|
||||||
yylval.integer *= 1024*1024;
|
yylval.integer = bfd_scan_vma (s, 0, 0);
|
||||||
}
|
if (yytext[yyleng-1] == 'M'
|
||||||
if (yytext[yyleng-1]=='K'
|
|| yytext[yyleng-1] == 'm')
|
||||||
|| yytext[yyleng-1]=='k') {
|
yylval.integer *= 1024 * 1024;
|
||||||
yylval.integer *= 1024;
|
if (yytext[yyleng-1] == 'K'
|
||||||
}
|
|| yytext[yyleng-1]=='k')
|
||||||
|
yylval.integer *= 1024;
|
||||||
return INT;
|
return INT;
|
||||||
}
|
}
|
||||||
<BOTH,SCRIPT,EXPRESSION,MRI>"]" { RTOKEN(']');}
|
<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,EXPRESSION,MRI>";" { RTOKEN(';');}
|
||||||
<BOTH,SCRIPT>"MEMORY" { RTOKEN(MEMORY);}
|
<BOTH,SCRIPT>"MEMORY" { RTOKEN(MEMORY);}
|
||||||
<BOTH,SCRIPT>"ORIGIN" { RTOKEN(ORIGIN);}
|
<BOTH,SCRIPT>"ORIGIN" { RTOKEN(ORIGIN);}
|
||||||
<BOTH,SCRIPT>"VERSION" { RTOKEN(VERSION);}
|
<BOTH,SCRIPT>"VERSION" { RTOKEN(VERSIONK);}
|
||||||
<EXPRESSION,BOTH,SCRIPT>"BLOCK" { RTOKEN(BLOCK);}
|
<EXPRESSION,BOTH,SCRIPT>"BLOCK" { RTOKEN(BLOCK);}
|
||||||
<EXPRESSION,BOTH,SCRIPT>"BIND" { RTOKEN(BIND);}
|
<EXPRESSION,BOTH,SCRIPT>"BIND" { RTOKEN(BIND);}
|
||||||
<BOTH,SCRIPT>"LENGTH" { RTOKEN(LENGTH);}
|
<BOTH,SCRIPT>"LENGTH" { RTOKEN(LENGTH);}
|
||||||
|
@ -272,6 +272,7 @@ V_IDENTIFIER [*?$_a-zA-Z][*?_a-zA-Z0-9]*
|
||||||
<BOTH,SCRIPT>"NOFLOAT" { RTOKEN(NOFLOAT);}
|
<BOTH,SCRIPT>"NOFLOAT" { RTOKEN(NOFLOAT);}
|
||||||
<EXPRESSION,BOTH,SCRIPT>"NOCROSSREFS" { RTOKEN(NOCROSSREFS);}
|
<EXPRESSION,BOTH,SCRIPT>"NOCROSSREFS" { RTOKEN(NOCROSSREFS);}
|
||||||
<BOTH,SCRIPT>"OVERLAY" { RTOKEN(OVERLAY); }
|
<BOTH,SCRIPT>"OVERLAY" { RTOKEN(OVERLAY); }
|
||||||
|
<BOTH,SCRIPT>"SORT" { RTOKEN(SORT); }
|
||||||
<EXPRESSION,BOTH,SCRIPT>"NOLOAD" { RTOKEN(NOLOAD);}
|
<EXPRESSION,BOTH,SCRIPT>"NOLOAD" { RTOKEN(NOLOAD);}
|
||||||
<EXPRESSION,BOTH,SCRIPT>"DSECT" { RTOKEN(DSECT);}
|
<EXPRESSION,BOTH,SCRIPT>"DSECT" { RTOKEN(DSECT);}
|
||||||
<EXPRESSION,BOTH,SCRIPT>"COPY" { RTOKEN(COPY);}
|
<EXPRESSION,BOTH,SCRIPT>"COPY" { RTOKEN(COPY);}
|
||||||
|
@ -285,9 +286,9 @@ V_IDENTIFIER [*?$_a-zA-Z][*?_a-zA-Z0-9]*
|
||||||
<BOTH,SCRIPT>"PHDRS" { RTOKEN (PHDRS); }
|
<BOTH,SCRIPT>"PHDRS" { RTOKEN (PHDRS); }
|
||||||
<EXPRESSION,BOTH,SCRIPT>"AT" { RTOKEN(AT);}
|
<EXPRESSION,BOTH,SCRIPT>"AT" { RTOKEN(AT);}
|
||||||
<EXPRESSION,BOTH,SCRIPT>"PROVIDE" { RTOKEN(PROVIDE); }
|
<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>"\n" { ++ lineno; RTOKEN(NEWLINE); }
|
||||||
<MRI>"\r" { ++ lineno; RTOKEN(NEWLINE); }
|
|
||||||
<MRI>"*".* { /* Mri comment line */ }
|
<MRI>"*".* { /* Mri comment line */ }
|
||||||
<MRI>";".* { /* Mri comment line */ }
|
<MRI>";".* { /* Mri comment line */ }
|
||||||
<MRI>"END" { RTOKEN(ENDWORD); }
|
<MRI>"END" { RTOKEN(ENDWORD); }
|
||||||
|
@ -342,7 +343,22 @@ V_IDENTIFIER [*?$_a-zA-Z][*?_a-zA-Z0-9]*
|
||||||
yylval.name = buystring (yytext + 2);
|
yylval.name = buystring (yytext + 2);
|
||||||
return LNAME;
|
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>"\""[^\"]*"\"" {
|
<EXPRESSION,BOTH,SCRIPT>"\""[^\"]*"\"" {
|
||||||
/* No matter the state, quotes
|
/* No matter the state, quotes
|
||||||
|
@ -352,8 +368,7 @@ V_IDENTIFIER [*?$_a-zA-Z][*?_a-zA-Z0-9]*
|
||||||
return NAME;
|
return NAME;
|
||||||
}
|
}
|
||||||
<BOTH,SCRIPT,EXPRESSION>"\n" { lineno++;}
|
<BOTH,SCRIPT,EXPRESSION>"\n" { lineno++;}
|
||||||
<BOTH,SCRIPT,EXPRESSION>"\r" { lineno++;}
|
<MRI,BOTH,SCRIPT,EXPRESSION>[ \t\r]+ { }
|
||||||
<MRI,BOTH,SCRIPT,EXPRESSION>[ \t]
|
|
||||||
|
|
||||||
<VERS_NODE,VERS_SCRIPT>[:,;] { return *yytext; }
|
<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>"{" { BEGIN(VERS_NODE); return *yytext; }
|
||||||
<VERS_SCRIPT,VERS_NODE>"}" { BEGIN(VERS_SCRIPT); 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>#.* { /* 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>> {
|
<<EOF>> {
|
||||||
include_stack_ptr--;
|
include_stack_ptr--;
|
||||||
|
@ -580,7 +595,7 @@ comment ()
|
||||||
c = input();
|
c = input();
|
||||||
while (c != '*' && c != EOF)
|
while (c != '*' && c != EOF)
|
||||||
{
|
{
|
||||||
if (c == '\n' || c == '\r')
|
if (c == '\n')
|
||||||
lineno++;
|
lineno++;
|
||||||
c = input();
|
c = input();
|
||||||
}
|
}
|
||||||
|
@ -594,7 +609,7 @@ comment ()
|
||||||
break; /* found the end */
|
break; /* found the end */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == '\n' || c == '\r')
|
if (c == '\n')
|
||||||
lineno++;
|
lineno++;
|
||||||
|
|
||||||
if (c == EOF)
|
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_WHOLE_ARCHIVE (OPTION_SPLIT_BY_FILE + 1)
|
||||||
#define OPTION_WRAP (OPTION_WHOLE_ARCHIVE + 1)
|
#define OPTION_WRAP (OPTION_WHOLE_ARCHIVE + 1)
|
||||||
#define OPTION_FORCE_EXE_SUFFIX (OPTION_WRAP + 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
|
/* The long options. This structure is used for both the option
|
||||||
parsing and the help text. */
|
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 },
|
'F', N_("SHLIB"), N_("Filter for shared object symbol table"), TWO_DASHES },
|
||||||
{ {NULL, no_argument, NULL, '\0'},
|
{ {NULL, no_argument, NULL, '\0'},
|
||||||
'g', NULL, N_("Ignored"), ONE_DASH },
|
'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'},
|
{ {"gpsize", required_argument, NULL, 'G'},
|
||||||
'G', N_("SIZE"), N_("Small data size (if no size, same as --shared)"),
|
'G', N_("SIZE"), N_("Small data size (if no size, same as --shared)"),
|
||||||
TWO_DASHES },
|
TWO_DASHES },
|
||||||
|
@ -575,6 +583,9 @@ parse_args (argc, argv)
|
||||||
case 'g':
|
case 'g':
|
||||||
/* Ignore. */
|
/* Ignore. */
|
||||||
break;
|
break;
|
||||||
|
case OPTION_GC_SECTIONS:
|
||||||
|
command_line.gc_sections = true;
|
||||||
|
break;
|
||||||
case OPTION_HELP:
|
case OPTION_HELP:
|
||||||
help ();
|
help ();
|
||||||
xexit (0);
|
xexit (0);
|
||||||
|
@ -604,6 +615,9 @@ parse_args (argc, argv)
|
||||||
config.magic_demand_paged = false;
|
config.magic_demand_paged = false;
|
||||||
config.dynamic_link = false;
|
config.dynamic_link = false;
|
||||||
break;
|
break;
|
||||||
|
case OPTION_NO_GC_SECTIONS:
|
||||||
|
command_line.gc_sections = false;
|
||||||
|
break;
|
||||||
case OPTION_NO_KEEP_MEMORY:
|
case OPTION_NO_KEEP_MEMORY:
|
||||||
link_info.keep_memory = false;
|
link_info.keep_memory = false;
|
||||||
break;
|
break;
|
||||||
|
@ -701,7 +715,10 @@ parse_args (argc, argv)
|
||||||
link_info.strip = strip_all;
|
link_info.strip = strip_all;
|
||||||
break;
|
break;
|
||||||
case OPTION_SHARED:
|
case OPTION_SHARED:
|
||||||
link_info.shared = true;
|
if (config.has_shared)
|
||||||
|
link_info.shared = true;
|
||||||
|
else
|
||||||
|
einfo (_("%P%F: -shared not supported\n"));
|
||||||
break;
|
break;
|
||||||
case 'h': /* Used on Solaris. */
|
case 'h': /* Used on Solaris. */
|
||||||
case OPTION_SONAME:
|
case OPTION_SONAME:
|
||||||
|
|
|
@ -56,11 +56,23 @@ SECTIONS
|
||||||
.gnu.version_d ${RELOCATING-0} : { *(.gnu.version_d) }
|
.gnu.version_d ${RELOCATING-0} : { *(.gnu.version_d) }
|
||||||
.gnu.version_r ${RELOCATING-0} : { *(.gnu.version_r) }
|
.gnu.version_r ${RELOCATING-0} : { *(.gnu.version_r) }
|
||||||
.rela.text ${RELOCATING-0} :
|
.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 ${RELOCATING-0} :
|
||||||
{ *(.rela.data) *(.rela.gnu.linkonce.d*) }
|
{
|
||||||
|
*(.rela.data)
|
||||||
|
${RELOCATING+*(.rela.data.*)}
|
||||||
|
${RELOCATING+*(.rela.gnu.linkonce.d*)}
|
||||||
|
}
|
||||||
.rela.rodata ${RELOCATING-0} :
|
.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.got ${RELOCATING-0} : { *(.rela.got) }
|
||||||
.rela.got1 ${RELOCATING-0} : { *(.rela.got1) }
|
.rela.got1 ${RELOCATING-0} : { *(.rela.got1) }
|
||||||
.rela.got2 ${RELOCATING-0} : { *(.rela.got2) }
|
.rela.got2 ${RELOCATING-0} : { *(.rela.got2) }
|
||||||
|
@ -78,13 +90,19 @@ SECTIONS
|
||||||
{
|
{
|
||||||
${RELOCATING+${TEXT_START_SYMBOLS}}
|
${RELOCATING+${TEXT_START_SYMBOLS}}
|
||||||
*(.text)
|
*(.text)
|
||||||
|
${RELOCATING+*(.text.*)}
|
||||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||||
*(.gnu.warning)
|
*(.gnu.warning)
|
||||||
*(.gnu.linkonce.t*)
|
${RELOCATING+*(.gnu.linkonce.t*)}
|
||||||
} =${NOP-0}
|
} =${NOP-0}
|
||||||
.init ${RELOCATING-0} : { *(.init) } =${NOP-0}
|
.init ${RELOCATING-0} : { KEEP (*(.init)) } =${NOP-0}
|
||||||
.fini ${RELOCATING-0} : { *(.fini) } =${NOP-0}
|
.fini ${RELOCATING-0} : { KEEP (*(.fini)) } =${NOP-0}
|
||||||
.rodata ${RELOCATING-0} : { *(.rodata) *(.gnu.linkonce.r*) }
|
.rodata ${RELOCATING-0} :
|
||||||
|
{
|
||||||
|
*(.rodata)
|
||||||
|
${RELOCATING+*(.rodata.*)}
|
||||||
|
${RELOCATING+*(.gnu.linkonce.r*)}
|
||||||
|
}
|
||||||
.rodata1 ${RELOCATING-0} : { *(.rodata1) }
|
.rodata1 ${RELOCATING-0} : { *(.rodata1) }
|
||||||
${RELOCATING+_etext = .;}
|
${RELOCATING+_etext = .;}
|
||||||
${RELOCATING+PROVIDE (etext = .);}
|
${RELOCATING+PROVIDE (etext = .);}
|
||||||
|
@ -112,7 +130,8 @@ SECTIONS
|
||||||
{
|
{
|
||||||
${RELOCATING+${DATA_START_SYMBOLS}}
|
${RELOCATING+${DATA_START_SYMBOLS}}
|
||||||
*(.data)
|
*(.data)
|
||||||
*(.gnu.linkonce.d*)
|
${RELOCATING+*(.data.*)}
|
||||||
|
${RELOCATING+*(.gnu.linkonce.d*)}
|
||||||
${CONSTRUCTING+CONSTRUCTORS}
|
${CONSTRUCTING+CONSTRUCTORS}
|
||||||
}
|
}
|
||||||
.data1 ${RELOCATING-0} : { *(.data1) }
|
.data1 ${RELOCATING-0} : { *(.data1) }
|
||||||
|
@ -139,16 +158,16 @@ SECTIONS
|
||||||
wildcard. The wildcard also means that it
|
wildcard. The wildcard also means that it
|
||||||
doesn't matter which directory crtbegin.o
|
doesn't matter which directory crtbegin.o
|
||||||
is in. */
|
is in. */
|
||||||
*crtbegin.o(.ctors)
|
KEEP (*crtbegin.o(.ctors))
|
||||||
*(SORT(.ctors.*))
|
KEEP (*(SORT(.ctors.*)))
|
||||||
*(.ctors) }
|
KEEP (*(.ctors)) }
|
||||||
${RELOCATING+PROVIDE (__CTOR_END__ = .);}
|
${RELOCATING+PROVIDE (__CTOR_END__ = .);}
|
||||||
|
|
||||||
${RELOCATING+PROVIDE (__DTOR_LIST__ = .);}
|
${RELOCATING+PROVIDE (__DTOR_LIST__ = .);}
|
||||||
.dtors ${RELOCATING-0} : {
|
.dtors ${RELOCATING-0} : {
|
||||||
*crtbegin.o(.dtors)
|
KEEP (*crtbegin.o(.dtors))
|
||||||
*(SORT(.dtors.*))
|
KEEP (*(SORT(.dtors.*)))
|
||||||
*(.dtors) }
|
KEEP (*(.dtors)) }
|
||||||
${RELOCATING+PROVIDE (__DTOR_END__ = .);}
|
${RELOCATING+PROVIDE (__DTOR_END__ = .);}
|
||||||
|
|
||||||
${RELOCATING+PROVIDE (_FIXUP_START_ = .);}
|
${RELOCATING+PROVIDE (_FIXUP_START_ = .);}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue