* ld.h (QUAD_SIZE): Define.

* ldgram.y (QUAD): New token.
	(length): Handle it.
	* ldlex.l: Return QUAD.
	* lexsup.c (keywords): Add QUAD.
	* ldwrite.c (build_link_order): Handle QUAD.
	* ldlang.c (print_data_statement): Handle QUAD.
	(lang_size_sections): Likewise.
	(lang_do_assignments): Likewise.
	* ldexp.c (exp_print_token): Add QUAD to table.
	* ld.texinfo: Describe QUAD.
This commit is contained in:
Ian Lance Taylor 1994-01-06 19:38:36 +00:00
parent 45dc9be388
commit c477527cbb
4 changed files with 284 additions and 386 deletions

View file

@ -1607,10 +1607,13 @@ same value as @code{abs2}.
@kindex SHORT(@var{expression}) @kindex SHORT(@var{expression})
@itemx LONG(@var{expression}) @itemx LONG(@var{expression})
@kindex LONG(@var{expression}) @kindex LONG(@var{expression})
@itemx QUAD(@var{expression})
@kindex QUAD(@var{expression})
@cindex direct output @cindex direct output
By including one of these three statements in a section definition, you By including one of these four statements in a section definition, you
can explicitly place one, two, or four bytes (respectively) at the can explicitly place one, two, four, or eight bytes (respectively) at
current address of that section. the current address of that section. @code{QUAD} is only supported when
using a 64 bit host or target.
@ifclear SingleFormat @ifclear SingleFormat
Multiple-byte quantities are represented in whatever byte order is Multiple-byte quantities are represented in whatever byte order is
@ -1822,10 +1825,8 @@ Options}.
@cindex naming the output file @cindex naming the output file
Use this command to name the link output file @var{filename}. The Use this command to name the link output file @var{filename}. The
effect of @code{OUTPUT(@var{filename})} is identical to the effect of effect of @code{OUTPUT(@var{filename})} is identical to the effect of
@w{@samp{-o @var{filename}}}, and whichever is encountered last @w{@samp{-o @var{filename}}}, which overrides it. You can use this
(@samp{-T} or @samp{-o} will control the name actually used to name the command to supply a default output-file name other than @code{a.out}.
output file. In particular, you can use this command to supply a
default output-file name other than @code{a.out}.
@ifclear SingleFormat @ifclear SingleFormat
@item OUTPUT_ARCH ( @var{bfdname} ) @item OUTPUT_ARCH ( @var{bfdname} )

View file

@ -107,7 +107,7 @@ static int error_index;
%right UNARY %right UNARY
%token END %token END
%left <token> '(' %left <token> '('
%token <token> ALIGN_K BLOCK LONG SHORT BYTE %token <token> ALIGN_K BLOCK QUAD LONG SHORT BYTE
%token SECTIONS %token SECTIONS
%token '{' '}' %token '{' '}'
%token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH %token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
@ -635,7 +635,9 @@ statement_list_opt:
; ;
length: length:
LONG QUAD
{ $$ = $1; }
| LONG
{ $$ = $1; } { $$ = $1; }
| SHORT | SHORT
{ $$ = $1; } { $$ = $1; }
@ -897,10 +899,10 @@ memspec_opt:
%% %%
void void
yyerror(arg) yyerror(arg)
char *arg; const char *arg;
{ {
if (error_index> 0 && error_index < ERROR_NAME_MAX) if (error_index > 0 && error_index < ERROR_NAME_MAX)
einfo("%P%F: %S syntax error in %s\n",error_names[error_index-1]); einfo("%P%F: %S %s in %s\n", arg, error_names[error_index-1]);
else else
einfo("%P%F: %S syntax error\n"); einfo("%P%F: %S %s\n", arg);
} }

View file

@ -19,21 +19,18 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "bfd.h" #include "bfd.h"
#include "sysdep.h" #include "sysdep.h"
#include "bfdlink.h"
#include "ld.h" #include "ld.h"
#include "ldsym.h"
#include "ldmain.h" #include "ldmain.h"
#include "ldgram.h" #include "ldgram.h"
#include "ldwarn.h"
#include "ldexp.h" #include "ldexp.h"
#include "ldlang.h" #include "ldlang.h"
#include "ldemul.h" #include "ldemul.h"
#include "ldlex.h" #include "ldlex.h"
#include "ldmisc.h" #include "ldmisc.h"
#include "ldindr.h"
#include "ldctor.h" #include "ldctor.h"
#include "ldfile.h" #include "ldfile.h"
#include "relax.h"
/* FORWARDS */ /* FORWARDS */
static void print_statements PARAMS ((void)); static void print_statements PARAMS ((void));
@ -100,7 +97,6 @@ static void open_input_bfds PARAMS ((lang_statement_union_type *statement));
static void lang_reasonable_defaults PARAMS ((void)); static void lang_reasonable_defaults PARAMS ((void));
static void lang_place_undefineds PARAMS ((void)); static void lang_place_undefineds PARAMS ((void));
static void lang_create_output_section_statements PARAMS ((void)); static void lang_create_output_section_statements PARAMS ((void));
static void lang_init_script_file PARAMS ((void));
static void map_input_to_output_sections static void map_input_to_output_sections
PARAMS ((lang_statement_union_type *s, PARAMS ((lang_statement_union_type *s,
const char *target, const char *target,
@ -129,21 +125,21 @@ static bfd_vma insert_pad PARAMS ((lang_statement_union_type **this_ptr,
static bfd_vma size_input_section static bfd_vma size_input_section
PARAMS ((lang_statement_union_type **this_ptr, PARAMS ((lang_statement_union_type **this_ptr,
lang_output_section_statement_type *output_section_statement, lang_output_section_statement_type *output_section_statement,
unsigned short fill, bfd_vma dot, boolean relax)); fill_type fill, bfd_vma dot, boolean relax));
static bfd_vma lang_size_sections static bfd_vma lang_size_sections
PARAMS ((lang_statement_union_type *s, PARAMS ((lang_statement_union_type *s,
lang_output_section_statement_type *output_section_statement, lang_output_section_statement_type *output_section_statement,
lang_statement_union_type **prev, unsigned short fill, lang_statement_union_type **prev, fill_type fill,
bfd_vma dot, boolean relax)); bfd_vma dot, boolean relax));
static bfd_vma lang_do_assignments static bfd_vma lang_do_assignments
PARAMS ((lang_statement_union_type * s, PARAMS ((lang_statement_union_type * s,
lang_output_section_statement_type *output_section_statement, lang_output_section_statement_type *output_section_statement,
unsigned short fill, fill_type fill,
bfd_vma dot)); bfd_vma dot));
static void lang_relocate_globals PARAMS ((void));
static void lang_finish PARAMS ((void)); static void lang_finish PARAMS ((void));
static void lang_check PARAMS ((void)); static void lang_check PARAMS ((void));
static void lang_common PARAMS ((void)); static void lang_common PARAMS ((void));
static boolean lang_one_common PARAMS ((struct bfd_link_hash_entry *, PTR));
static void lang_place_orphans PARAMS ((void)); static void lang_place_orphans PARAMS ((void));
static int topower PARAMS ((int)); static int topower PARAMS ((int));
static void reset_memory_regions PARAMS ((void)); static void reset_memory_regions PARAMS ((void));
@ -152,13 +148,11 @@ static void reset_memory_regions PARAMS ((void));
boolean relaxing; boolean relaxing;
lang_output_section_statement_type *abs_output_section; lang_output_section_statement_type *abs_output_section;
lang_statement_list_type *stat_ptr = &statement_list; lang_statement_list_type *stat_ptr = &statement_list;
lang_input_statement_type *script_file = 0;
lang_statement_list_type file_chain = lang_statement_list_type file_chain =
{0}; {0};
CONST char *entry_symbol = 0; CONST char *entry_symbol = 0;
bfd_size_type largest_section = 0; bfd_size_type largest_section = 0;
boolean lang_has_input_file = false; boolean lang_has_input_file = false;
lang_output_section_statement_type *create_object_symbols = 0;
boolean had_output_filename = false; boolean had_output_filename = false;
boolean lang_float_flag = false; boolean lang_float_flag = false;
boolean delete_output_file_on_failure = false; boolean delete_output_file_on_failure = false;
@ -220,7 +214,7 @@ print_section (name)
static void static void
lang_for_each_statement_worker (func, s) lang_for_each_statement_worker (func, s)
void (*func) (lang_statement_union_type *); void (*func) PARAMS ((lang_statement_union_type *));
lang_statement_union_type *s; lang_statement_union_type *s;
{ {
for (; s != (lang_statement_union_type *) NULL; s = s->next) for (; s != (lang_statement_union_type *) NULL; s = s->next)
@ -261,7 +255,7 @@ lang_for_each_statement_worker (func, s)
void void
lang_for_each_statement (func) lang_for_each_statement (func)
void (*func) (lang_statement_union_type *); void (*func) PARAMS ((lang_statement_union_type *));
{ {
lang_for_each_statement_worker (func, lang_for_each_statement_worker (func,
statement_list.head); statement_list.head);
@ -408,18 +402,6 @@ lang_add_input_file (name, file_type, target)
return new_afile (name, file_type, target); return new_afile (name, file_type, target);
} }
void
lang_add_keepsyms_file (filename)
CONST char *filename;
{
if (keepsyms_file != 0)
info_msg ("%X%P: error: duplicated keep-symbols-file value\n");
keepsyms_file = filename;
if (strip_symbols != STRIP_NONE)
info_msg ("%P: `-keep-only-symbols-file' overrides `-s' and `-S'\n");
strip_symbols = STRIP_SOME;
}
/* Build enough state so that the parser can build its tree */ /* Build enough state so that the parser can build its tree */
void void
lang_init () lang_init ()
@ -778,27 +760,38 @@ lookup_name (name)
search = (lang_input_statement_type *) search->next_real_file) search = (lang_input_statement_type *) search->next_real_file)
{ {
if (search->filename == (char *) NULL && name == (char *) NULL) if (search->filename == (char *) NULL && name == (char *) NULL)
{ return search;
return search; if (search->filename != (char *) NULL
} && name != (char *) NULL
if (search->filename != (char *) NULL && name != (char *) NULL) && strcmp (search->filename, name) == 0)
{ break;
if (strcmp (search->filename, name) == 0)
{
ldmain_open_file_read_symbol (search);
return search;
}
}
} }
/* There isn't an afile entry for this file yet, this must be if (search == (lang_input_statement_type *) NULL)
because the name has only appeared inside a load script and not {
on the command line */ /* There isn't an afile entry for this file yet, this must be
search = new_afile (name, lang_input_file_is_file_enum, default_target); because the name has only appeared inside a load script and
ldmain_open_file_read_symbol (search); not on the command line */
search = new_afile (name, lang_input_file_is_file_enum, default_target);
}
ldfile_open_file (search);
if (bfd_check_format (search->the_bfd, bfd_object))
ldlang_add_file (search);
else if (bfd_check_format (search->the_bfd, bfd_archive))
{
/* There is nothing to do here; the add_symbols routine will
call ldlang_add_file (via the add_archive_element callback)
for each element of the archive which is used. */
}
else
einfo ("%F%B: file not recognized: %E\n", search->the_bfd);
if (bfd_link_add_symbols (search->the_bfd, &link_info) == false)
einfo ("%F%B: could not read symbols: %E\n", search->the_bfd);
return search; return search;
} }
static void static void
@ -820,8 +813,6 @@ wild (s, section, file, target, output)
{ {
wild_section (s, section, f, output); wild_section (s, section, f, output);
} }
/* Once more for the script file */
wild_section(s, section, script_file, output);
} }
else else
{ {
@ -877,6 +868,10 @@ open_output (name)
ldfile_output_machine)) ldfile_output_machine))
einfo ("%P%F:%s: can not set architecture: %E\n", name); einfo ("%P%F:%s: can not set architecture: %E\n", name);
link_info.hash = bfd_link_hash_table_create (output);
if (link_info.hash == (struct bfd_link_hash_table *) NULL)
einfo ("%P%F: can not create link hash table: %E\n");
bfd_set_gp_size (output, g_switch_value); bfd_set_gp_size (output, g_switch_value);
return output; return output;
} }
@ -890,10 +885,11 @@ ldlang_open_output (statement)
{ {
switch (statement->header.type) switch (statement->header.type)
{ {
case lang_output_statement_enum: case lang_output_statement_enum:
ASSERT (output_bfd == (bfd *) NULL);
output_bfd = open_output (statement->output_statement.name); output_bfd = open_output (statement->output_statement.name);
ldemul_set_output_arch (); ldemul_set_output_arch ();
if (config.magic_demand_paged && !config.relocateable_output) if (config.magic_demand_paged && !link_info.relocateable)
output_bfd->flags |= D_PAGED; output_bfd->flags |= D_PAGED;
else else
output_bfd->flags &= ~D_PAGED; output_bfd->flags &= ~D_PAGED;
@ -999,19 +995,23 @@ ldlang_add_undef (name)
static void static void
lang_place_undefineds () lang_place_undefineds ()
{ {
ldlang_undef_chain_list_type *ptr = ldlang_undef_chain_list_head; ldlang_undef_chain_list_type *ptr;
while (ptr != (ldlang_undef_chain_list_type *) NULL) for (ptr = ldlang_undef_chain_list_head;
ptr != (ldlang_undef_chain_list_type *) NULL;
ptr = ptr->next)
{ {
asymbol *def; struct bfd_link_hash_entry *h;
asymbol **def_ptr = (asymbol **) stat_alloc ((bfd_size_type) (sizeof (asymbol **)));
def = (asymbol *) bfd_make_empty_symbol (script_file->the_bfd); h = bfd_link_hash_lookup (link_info.hash, ptr->name, true, false, true);
*def_ptr = def; if (h == (struct bfd_link_hash_entry *) NULL)
def->name = ptr->name; einfo ("%P%F: bfd_link_hash_lookup failed: %E");
def->section = &bfd_und_section; if (h->type == bfd_link_hash_new)
enter_global_ref (def_ptr, ptr->name); {
ptr = ptr->next; h->type = bfd_link_hash_undefined;
h->u.undef.abfd = NULL;
bfd_link_add_undef (link_info.hash, h);
}
} }
} }
@ -1036,28 +1036,6 @@ lang_create_output_section_statements ()
} }
static void
lang_init_script_file ()
{
script_file = lang_add_input_file ("command line",
lang_input_file_is_fake_enum,
(char *) NULL);
script_file->the_bfd = bfd_create ("command line", output_bfd);
script_file->symbol_count = 0;
script_file->the_bfd->sections = 0;
/* The user data of a bfd points to the input statement attatched */
script_file->the_bfd->usrdata = (void *)script_file;
script_file->common_section =
bfd_make_section(script_file->the_bfd,"COMMON");
abs_output_section =
lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME);
abs_output_section->bfd_section = &bfd_abs_section;
}
/* Open input files and attatch to output sections */ /* Open input files and attatch to output sections */
static void static void
map_input_to_output_sections (s, target, output_section_statement) map_input_to_output_sections (s, target, output_section_statement)
@ -1119,7 +1097,6 @@ map_input_to_output_sections (s, target, output_section_statement)
break; break;
case lang_input_statement_enum: case lang_input_statement_enum:
/* A standard input statement, has no wildcards */ /* A standard input statement, has no wildcards */
/* ldmain_open_file_read_symbol(&s->input_statement);*/
break; break;
} }
} }
@ -1370,6 +1347,10 @@ print_data_statement (data)
fprintf (config.map_file, "LONG "); fprintf (config.map_file, "LONG ");
print_dot += LONG_SIZE; print_dot += LONG_SIZE;
break; break;
case QUAD:
fprintf (config.map_file, "QUAD ");
print_dot += QUAD_SIZE;
break;
} }
exp_print_tree (data->exp); exp_print_tree (data->exp);
@ -1547,7 +1528,7 @@ static bfd_vma
size_input_section (this_ptr, output_section_statement, fill, dot, relax) size_input_section (this_ptr, output_section_statement, fill, dot, relax)
lang_statement_union_type ** this_ptr; lang_statement_union_type ** this_ptr;
lang_output_section_statement_type * output_section_statement; lang_output_section_statement_type * output_section_statement;
unsigned short fill; fill_type fill;
bfd_vma dot; bfd_vma dot;
boolean relax; boolean relax;
{ {
@ -1607,7 +1588,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
lang_statement_union_type * s; lang_statement_union_type * s;
lang_output_section_statement_type * output_section_statement; lang_output_section_statement_type * output_section_statement;
lang_statement_union_type ** prev; lang_statement_union_type ** prev;
unsigned short fill; fill_type fill;
bfd_vma dot; bfd_vma dot;
boolean relax; boolean relax;
{ {
@ -1731,6 +1712,9 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
switch (s->data_statement.type) switch (s->data_statement.type)
{ {
case QUAD:
size = QUAD_SIZE;
break;
case LONG: case LONG:
size = LONG_SIZE; size = LONG_SIZE;
break; break;
@ -1758,7 +1742,8 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
break; break;
case lang_object_symbols_statement_enum: case lang_object_symbols_statement_enum:
create_object_symbols = output_section_statement; link_info.create_object_symbols_section =
output_section_statement->bfd_section;
break; break;
case lang_output_statement_enum: case lang_output_statement_enum:
case lang_target_statement_enum: case lang_target_statement_enum:
@ -1766,12 +1751,18 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
case lang_input_section_enum: case lang_input_section_enum:
if (relax) if (relax)
{ {
lang_input_section_type *is;
asection *i;
relaxing = true; relaxing = true;
if( relax_section (prev)) is = &(*prev)->input_section;
had_relax = true; i = is->section;
relaxing = false;
if (bfd_relax_section (i->owner, i, &link_info, is->ifile->asymbols))
had_relax = true;
relaxing = false;
} }
else { else {
(*prev)->input_section.section->_cooked_size = (*prev)->input_section.section->_cooked_size =
@ -1842,7 +1833,7 @@ static bfd_vma
lang_do_assignments (s, output_section_statement, fill, dot) lang_do_assignments (s, output_section_statement, fill, dot)
lang_statement_union_type * s; lang_statement_union_type * s;
lang_output_section_statement_type * output_section_statement; lang_output_section_statement_type * output_section_statement;
unsigned short fill; fill_type fill;
bfd_vma dot; bfd_vma dot;
{ {
for (; s != (lang_statement_union_type *) NULL; s = s->next) for (; s != (lang_statement_union_type *) NULL; s = s->next)
@ -1894,6 +1885,9 @@ lang_do_assignments (s, output_section_statement, fill, dot)
} }
switch (s->data_statement.type) switch (s->data_statement.type)
{ {
case QUAD:
dot += QUAD_SIZE;
break;
case LONG: case LONG:
dot += LONG_SIZE; dot += LONG_SIZE;
break; break;
@ -1942,110 +1936,56 @@ lang_do_assignments (s, output_section_statement, fill, dot)
return dot; return dot;
} }
static void
lang_relocate_globals ()
{
/*
Each ldsym_type maintains a chain of pointers to asymbols which
references the definition. Replace each pointer to the referenence
with a pointer to only one place, preferably the definition. If
the defintion isn't available then the common symbol, and if
there isn't one of them then choose one reference.
*/
FOR_EACH_LDSYM (lgs)
{
asymbol *it;
/* Skip indirect symbols. */
if (lgs->flags & SYM_INDIRECT)
continue;
if (lgs->sdefs_chain)
{
it = *(lgs->sdefs_chain);
}
else if (lgs->scoms_chain != (asymbol **) NULL)
{
it = *(lgs->scoms_chain);
}
else if (lgs->srefs_chain != (asymbol **) NULL)
{
it = *(lgs->srefs_chain);
}
else
{
/* This can happen when the command line asked for a symbol to
be -u */
it = (asymbol *) NULL;
}
if (it != (asymbol *) NULL)
{
asymbol **prev = 0;
asymbol **ptr = lgs->srefs_chain;;
if (lgs->flags & SYM_WARNING)
{
produce_warnings (lgs, it);
}
while (ptr != (asymbol **) NULL
&& ptr != prev)
{
asymbol *ref = *ptr;
prev = ptr;
*ptr = it;
ptr = (asymbol **) (ref->udata);
}
}
}
}
static void static void
lang_finish () lang_finish ()
{ {
ldsym_type *lgs; struct bfd_link_hash_entry *h;
int warn = config.relocateable_output != true; boolean warn = link_info.relocateable ? false : true;
if (entry_symbol == (char *) NULL) if (entry_symbol == (char *) NULL)
{ {
/* No entry has been specified, look for start, but don't warn */ /* No entry has been specified. Look for start, but don't warn
entry_symbol = "start"; if we don't find it. */
warn =0; entry_symbol = "start";
} warn = false;
lgs = ldsym_get_soft (entry_symbol); }
if (lgs && lgs->sdefs_chain)
{
asymbol *sy = *(lgs->sdefs_chain);
/* We can set the entry address*/ h = bfd_link_hash_lookup (link_info.hash, entry_symbol, false, false, true);
bfd_set_start_address (output_bfd, if (h != (struct bfd_link_hash_entry *) NULL
outside_symbol_address (sy)); && h->type == bfd_link_hash_defined)
{
bfd_vma val;
} val = (h->u.def.value
+ bfd_get_section_vma (output_bfd,
h->u.def.section->output_section)
+ h->u.def.section->output_offset);
if (! bfd_set_start_address (output_bfd, val))
einfo ("%P%F:%s: can't set start address\n", entry_symbol);
}
else else
{
/* Cannot find anything reasonable,
use the first address in the text section
*/
asection *ts = bfd_get_section_by_name (output_bfd, ".text");
if (ts)
{ {
if (warn) asection *ts;
einfo ("%P: warning: cannot find entry symbol %s, defaulting to %V\n",
entry_symbol, ts->vma);
bfd_set_start_address (output_bfd, ts->vma); /* Can't find the entry symbol. Use the first address in the
text section. */
ts = bfd_get_section_by_name (output_bfd, ".text");
if (ts != (asection *) NULL)
{
if (warn)
einfo ("%P: warning: cannot find entry symbol %s; defaulting to %V\n",
entry_symbol, bfd_get_section_vma (output_bfd, ts));
if (! bfd_set_start_address (output_bfd,
bfd_get_section_vma (output_bfd, ts)))
einfo ("%P%F: can't set start address\n");
}
else
{
if (warn)
einfo ("%P: warning: cannot find entry symbol %s; not setting start address\n",
entry_symbol);
}
} }
else
{
if (warn)
einfo ("%P: warning: cannot find entry symbol %s, not setting start address\n",
entry_symbol);
}
}
} }
/* By now we know the target architecture, and we may have an */ /* By now we know the target architecture, and we may have an */
@ -2083,7 +2023,7 @@ lang_check ()
else else
{ {
info_msg ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n", einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n",
bfd_printable_name (input_bfd), input_bfd, bfd_printable_name (input_bfd), input_bfd,
bfd_printable_name (output_bfd)); bfd_printable_name (output_bfd));
@ -2097,137 +2037,100 @@ lang_check ()
} }
} }
/* /* Look through all the global common symbols and attach them to the
* run through all the global common symbols and tie them correct section. The -sort-common command line switch may be used
* to the output section requested. to roughly sort the entries by size. */
*
As an experiment we do this 4 times, once for all the byte sizes,
then all the two bytes, all the four bytes and then everything else
*/
static void static void
lang_common () lang_common ()
{ {
ldsym_type *lgs; if (link_info.relocateable
size_t power; && ! command_line.force_common_definition)
return;
if (config.relocateable_output == false || if (! config.sort_common)
command_line.force_common_definition == true) bfd_link_hash_traverse (link_info.hash, lang_one_common, (PTR) NULL);
else
{ {
for (power = 1; (config.sort_common == true && power == 1) || (power <= 16); power <<= 1) unsigned int power;
{
for (lgs = symbol_head;
lgs != (ldsym_type *) NULL;
lgs = lgs->next)
{
asymbol *com;
unsigned int power_of_two;
size_t size;
size_t align;
if (lgs->scoms_chain != (asymbol **) NULL) for (power = 1; power <= 16; power <<= 1)
{ bfd_link_hash_traverse (link_info.hash, lang_one_common,
com = *(lgs->scoms_chain); (PTR) &power);
size = com->value; }
switch (size) }
{
case 0:
case 1:
align = 1;
power_of_two = 0;
break;
case 2:
power_of_two = 1;
align = 2;
break;
case 3:
case 4:
power_of_two = 2;
align = 4;
break;
case 5:
case 6:
case 7:
case 8:
power_of_two = 3;
align = 8;
break;
default:
power_of_two = 4;
align = 16;
break;
}
if (config.sort_common == false || align == power)
{
bfd *symbfd;
/* Change from a common symbol into a definition of /* Place one common symbol in the correct section. */
a symbol */
lgs->sdefs_chain = lgs->scoms_chain;
lgs->scoms_chain = (asymbol **) NULL;
commons_pending--;
/* Point to the correct common section */ static boolean
symbfd = bfd_asymbol_bfd (com); lang_one_common (h, info)
if (com->section == &bfd_com_section) struct bfd_link_hash_entry *h;
com->section = PTR info;
((lang_input_statement_type *) symbfd->usrdata) {
->common_section; unsigned int power_of_two;
else bfd_vma size;
{ size_t align;
CONST char *name; asection *section;
asection *newsec;
name = bfd_get_section_name (symbfd, if (h->type != bfd_link_hash_common)
com->section); return true;
newsec = bfd_get_section_by_name (symbfd,
name);
/* This section should have been created by
enter_file_symbols if it did not already
exist. */
if (newsec == (asection *) NULL)
einfo ("%P%F: no output section %s\n", name);
com->section = newsec;
}
/* Fix the size of the common section */ size = h->u.c.size;
switch (size)
com->section->_raw_size = {
ALIGN_N (com->section->_raw_size, case 0:
/* The coercion here is important, see ld.h. */ case 1:
(bfd_vma) align); power_of_two = 0;
align = 1;
/* Remember if this is the biggest alignment ever seen */ break;
if (power_of_two > com->section->alignment_power) case 2:
{ power_of_two = 1;
com->section->alignment_power = power_of_two; align = 2;
} break;
case 3:
/* Symbol stops being common and starts being global, but case 4:
we remember that it was common once. */ power_of_two = 2;
align = 4;
com->flags = BSF_EXPORT | BSF_GLOBAL | BSF_OLD_COMMON; break;
com->value = com->section->_raw_size; case 5:
case 6:
if (write_map && config.map_file) case 7:
{ case 8:
fprintf (config.map_file, "Allocating common %s: %x at %x %s\n", power_of_two = 3;
lgs->name, align = 8;
(unsigned) size, break;
(unsigned) com->value, default:
bfd_asymbol_bfd(com)->filename); power_of_two = 4;
} align = 16;
break;
com->section->_raw_size += size;
}
}
}
}
} }
if (config.sort_common && align != *(unsigned int *) info)
return true;
section = h->u.c.section;
/* Increase the size of the section. */
section->_raw_size = ALIGN_N (section->_raw_size, align);
/* Adjust the alignment if necessary. */
if (power_of_two > section->alignment_power)
section->alignment_power = power_of_two;
/* Change the symbol from common to defined. */
h->type = bfd_link_hash_defined;
h->u.def.section = section;
h->u.def.value = section->_raw_size;
/* Increase the size of the section. */
section->_raw_size += size;
if (write_map && config.map_file != NULL)
fprintf (config.map_file, "Allocating common %s: %lx at %lx %s\n",
h->root.string, (unsigned long) size,
(unsigned long) h->u.def.value, section->owner->filename);
return true;
} }
/* /*
@ -2262,8 +2165,8 @@ lang_place_orphans ()
/* This is a lonely common section which must /* This is a lonely common section which must
have come from an archive. We attatch to the have come from an archive. We attatch to the
section with the wildcard */ section with the wildcard */
if (config.relocateable_output != true if (! link_info.relocateable
&& command_line.force_common_definition == false) && ! command_line.force_common_definition)
{ {
if (default_common_section == if (default_common_section ==
(lang_output_section_statement_type *) NULL) (lang_output_section_statement_type *) NULL)
@ -2378,10 +2281,17 @@ void
ldlang_add_file (entry) ldlang_add_file (entry)
lang_input_statement_type * entry; lang_input_statement_type * entry;
{ {
lang_statement_append (&file_chain, lang_statement_append (&file_chain,
(lang_statement_union_type *) entry, (lang_statement_union_type *) entry,
&entry->next); &entry->next);
/* The BFD linker needs to have a list of all input BFDs involved in
a link. */
ASSERT (entry->the_bfd->link_next == (bfd *) NULL);
ASSERT (entry->the_bfd != output_bfd);
entry->the_bfd->link_next = link_info.input_bfds;
link_info.input_bfds = entry->the_bfd;
entry->the_bfd->usrdata = (PTR) entry;
} }
void void
@ -2488,27 +2398,6 @@ reset_memory_regions ()
} }
} }
asymbol *
create_symbol (name, flags, section)
CONST char *name;
flagword flags;
asection * section;
{
asymbol **def_ptr = (asymbol **) stat_alloc ((bfd_size_type) (sizeof (asymbol **)));
/* Add this definition to script file */
asymbol *def = (asymbol *) bfd_make_empty_symbol (script_file->the_bfd);
def->name = buystring (name);
def->udata = 0;
def->flags = flags;
def->section = section;
*def_ptr = def;
enter_global_ref (def_ptr, name);
return def;
}
void void
lang_process () lang_process ()
{ {
@ -2522,9 +2411,6 @@ lang_process ()
ldemul_create_output_section_statements (); ldemul_create_output_section_statements ();
/* Create a dummy bfd for the script */
lang_init_script_file ();
/* Add to the hash table all undefineds on the command line */ /* Add to the hash table all undefineds on the command line */
lang_place_undefineds (); lang_place_undefineds ();
@ -2532,10 +2418,13 @@ lang_process ()
current_target = default_target; current_target = default_target;
lang_for_each_statement (open_input_bfds); lang_for_each_statement (open_input_bfds);
/* Build all sets based on the information gathered from the input
files. */
ldctor_build_sets ();
/* Run through the contours of the script and attatch input sections /* Run through the contours of the script and attatch input sections
to the correct output sections to the correct output sections
*/ */
find_constructors ();
map_input_to_output_sections (statement_list.head, (char *) NULL, map_input_to_output_sections (statement_list.head, (char *) NULL,
(lang_output_section_statement_type *) NULL); (lang_output_section_statement_type *) NULL);
@ -2576,9 +2465,6 @@ lang_process ()
(lang_output_section_statement_type *) NULL, (lang_output_section_statement_type *) NULL,
&(statement_list.head), 0, (bfd_vma) 0, false); &(statement_list.head), 0, (bfd_vma) 0, false);
/* Move the global symbols around so the second pass of relaxing
can see them. */
lang_relocate_globals ();
reset_memory_regions (); reset_memory_regions ();
@ -2587,7 +2473,7 @@ lang_process ()
lang_do_assignments (statement_list.head, lang_do_assignments (statement_list.head,
abs_output_section, abs_output_section,
0, (bfd_vma) 0); (fill_type) 0, (bfd_vma) 0);
/* Perform another relax pass - this time we know where the /* Perform another relax pass - this time we know where the
globals are, so can make better guess. */ globals are, so can make better guess. */
@ -2612,11 +2498,7 @@ lang_process ()
lang_do_assignments (statement_list.head, lang_do_assignments (statement_list.head,
abs_output_section, abs_output_section,
0, (bfd_vma) 0); (fill_type) 0, (bfd_vma) 0);
/* Move the global symbols around */
lang_relocate_globals ();
/* Make sure that we're not mixing architectures */ /* Make sure that we're not mixing architectures */
@ -2794,25 +2676,30 @@ lang_leave_output_section_statement (fill, memspec)
If the symbol already exists, then do nothing. If the symbol already exists, then do nothing.
*/ */
void void
lang_abs_symbol_at_beginning_of (section, name) lang_abs_symbol_at_beginning_of (secname, name)
CONST char *section; const char *secname;
CONST char *name; const char *name;
{ {
if (ldsym_undefined (name)) struct bfd_link_hash_entry *h;
{
asection *s = bfd_get_section_by_name (output_bfd, section);
asymbol *def = create_symbol (name,
BSF_GLOBAL | BSF_EXPORT,
&bfd_abs_section);
if (s != (asection *) NULL) h = bfd_link_hash_lookup (link_info.hash, name, true, true, true);
{ if (h == (struct bfd_link_hash_entry *) NULL)
def->value = s->vma; einfo ("%P%F: bfd_link_hash_lookup failed: %E\n");
}
if (h->type == bfd_link_hash_new
|| h->type == bfd_link_hash_undefined)
{
asection *sec;
h->type = bfd_link_hash_defined;
sec = bfd_get_section_by_name (output_bfd, secname);
if (sec == (asection *) NULL)
h->u.def.value = 0;
else else
{ h->u.def.value = bfd_get_section_vma (output_bfd, sec);
def->value = 0;
} h->u.def.section = &bfd_abs_section;
} }
} }
@ -2823,27 +2710,31 @@ lang_abs_symbol_at_beginning_of (section, name)
If the symbol already exists, then do nothing. If the symbol already exists, then do nothing.
*/ */
void void
lang_abs_symbol_at_end_of (section, name) lang_abs_symbol_at_end_of (secname, name)
CONST char *section; const char *secname;
CONST char *name; const char *name;
{ {
if (ldsym_undefined (name)) struct bfd_link_hash_entry *h;
h = bfd_link_hash_lookup (link_info.hash, name, true, true, true);
if (h == (struct bfd_link_hash_entry *) NULL)
einfo ("%P%F: bfd_link_hash_lookup failed: %E\n");
if (h->type == bfd_link_hash_new
|| h->type == bfd_link_hash_undefined)
{ {
asection *s = bfd_get_section_by_name (output_bfd, section); asection *sec;
/* Add a symbol called _end */ h->type = bfd_link_hash_defined;
asymbol *def = create_symbol (name,
BSF_GLOBAL | BSF_EXPORT,
&bfd_abs_section);
if (s != (asection *) NULL) sec = bfd_get_section_by_name (output_bfd, secname);
{ if (sec == (asection *) NULL)
def->value = s->vma + s->_raw_size; h->u.def.value = 0;
}
else else
{ h->u.def.value = (bfd_get_section_vma (output_bfd, sec)
def->value = 0; + bfd_section_size (output_bfd, sec));
}
h->u.def.section = &bfd_abs_section;
} }
} }

View file

@ -1,6 +1,6 @@
%{ %{
/* Copyright (C) 1991 Free Software Foundation, Inc. /* Copyright (C) 1991, 1993 Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker. This file is part of GLD, the Gnu Linker.
@ -27,6 +27,7 @@ This was written by steve chamberlain
#include <ansidecl.h> #include <ansidecl.h>
#include <stdio.h> #include <stdio.h>
#include "bfd.h" #include "bfd.h"
#include "sysdep.h"
#include "ld.h" #include "ld.h"
#include "ldgram.h" #include "ldgram.h"
#include "ldmisc.h" #include "ldmisc.h"
@ -112,6 +113,8 @@ NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~]
<COMMAND>"-n" { return OPTION_n; } <COMMAND>"-n" { return OPTION_n; }
<COMMAND>"-N" { return OPTION_N; } <COMMAND>"-N" { return OPTION_N; }
<COMMAND>"-r" { return OPTION_r; } <COMMAND>"-r" { return OPTION_r; }
<COMMAND>"-stats" { return OPTION_stats; }
<COMMAND>"-no-keep-memory" { return OPTION_no_keep_memory; }
<COMMAND>"-relax" { return OPTION_relax; } <COMMAND>"-relax" { return OPTION_relax; }
<COMMAND>"-i" { return OPTION_r; } <COMMAND>"-i" { return OPTION_r; }
<COMMAND>"-Ur" { return OPTION_Ur; } <COMMAND>"-Ur" { return OPTION_Ur; }
@ -329,6 +332,7 @@ NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~]
<BOTH,SCRIPT>"HLL" { RTOKEN(HLL);} <BOTH,SCRIPT>"HLL" { RTOKEN(HLL);}
<BOTH,SCRIPT>"SYSLIB" { RTOKEN(SYSLIB);} <BOTH,SCRIPT>"SYSLIB" { RTOKEN(SYSLIB);}
<BOTH,SCRIPT>"FLOAT" { RTOKEN(FLOAT);} <BOTH,SCRIPT>"FLOAT" { RTOKEN(FLOAT);}
<BOTH,SCRIPT>"QUAD" { RTOKEN( QUAD);}
<BOTH,SCRIPT>"LONG" { RTOKEN( LONG);} <BOTH,SCRIPT>"LONG" { RTOKEN( LONG);}
<BOTH,SCRIPT>"SHORT" { RTOKEN( SHORT);} <BOTH,SCRIPT>"SHORT" { RTOKEN( SHORT);}
<BOTH,SCRIPT>"BYTE" { RTOKEN( BYTE);} <BOTH,SCRIPT>"BYTE" { RTOKEN( BYTE);}