* ldlang.h: add new field "loadable" to output_section_statement.

* ldlang.c (lang_output_section_statement_lookup): initilize new
	field. (wild_doit): if new field is not set, then stop output
	section from being loadable.
	(lang_enter_output_section_statement): set the field from the
	NOLOAD keyword
	* ldgram.y: new synax for NOLOAD. Removes a shift/reduce too.
	* h8300hms.sc-sh, h8300hms.em: get -r right.
This commit is contained in:
Steve Chamberlain 1992-08-07 19:34:59 +00:00
parent f6492282df
commit ae475b39b2
5 changed files with 339 additions and 264 deletions

View File

@ -1,3 +1,14 @@
Fri Aug 7 12:31:10 1992 Steve Chamberlain (sac@thepub.cygnus.com)
* ldlang.h: add new field "loadable" to output_section_statement.
* ldlang.c (lang_output_section_statement_lookup): initilize new
field. (wild_doit): if new field is not set, then stop output
section from being loadable.
(lang_enter_output_section_statement): set the field from the
NOLOAD keyword
* ldgram.y: new synax for NOLOAD. Removes a shift/reduce too.
* h8300hms.sc-sh, h8300hms.em: get -r right.
Thu Aug 6 18:35:21 1992 Per Bothner (bothner@rtl.cygnus.com)
* ldint.texinfo: New internals manual (beginnings thereof).

View File

@ -53,10 +53,10 @@ static char *h8300hms_script =
#include "h8300hms.x"
;
static char *h8300hms_script_option_Ur =
#include "h8300hms.x"
#include "h8300hms.xu"
;
static char *h8300hms_script_option_r =
#include "h8300hms.x"
#include "h8300hms.xr"
;
static char *h8300hms_get_script()

View File

@ -16,23 +16,23 @@ SECTIONS
{
*(.text)
*(.strings)
_etext = .;
${RELOCATING+ _etext = . ; }
} ${RELOCATING+ > ram}
.data :
{
*(.data)
_edata = .;
${RELOCATING+ _edata = . ; }
} ${RELOCATING+ > ram}
.bss :
{
${RELOCATING+ _bss_start = .};
${RELOCATING+ _bss_start = . ;}
*(.bss)
*(COMMON)
${RELOCATING+ _end = .};
${RELOCATING+ _end = . ; }
} ${RELOCATING+ >ram}
.stack :
{
_stack = .;
${RELOCATING+ _stack = . ; }
*(.stack)
} ${RELOCATING+ > topram}
}

View File

@ -299,7 +299,7 @@ command_line_option:
{ lang_add_input_file($1,lang_input_file_is_file_enum,
(char *)NULL); }
| OPTION_c filename
{ ldfile_open_command_file($2); } mri_script_file END { ldlex_command()};
{ ldfile_open_command_file($2); } mri_script_file END { ldlex_command();}
| OPTION_Tfile
{ ldfile_open_command_file($1); } script_file
@ -327,7 +327,7 @@ END { ldlex_command();}
lang_add_assignment(exp_assop($4,$3,$5));
}
| '-' NAME
{ info("%P%F Unrecognised option -%s\n", $2); }
{ info("%P%F Unrecognized option -%s\n", $2); }
| '{' script_file '}'
;
@ -747,6 +747,8 @@ exp :
{ $$ = exp_nameop(SIZEOF,$3); }
| ADDR '(' NAME ')'
{ $$ = exp_nameop(ADDR,$3); }
| ABSOLUTE '(' exp ')'
{ $$ = exp_unop(ABSOLUTE, $3); }
| ALIGN_K '(' exp ')'
{ $$ = exp_unop(ALIGN_K,$3); }
| NAME
@ -772,11 +774,11 @@ opt_comma
;
opt_type:
'(' NOLOAD ')' { $$ = SEC_NO_FLAGS; }
| '(' DSECT ')' { $$ = 0; }
| '(' COPY ')' { $$ = 0; }
| '(' INFO ')' { $$ = 0; }
| '(' OVERLAY ')' { $$ = 0; }
NOLOAD { $$ = SEC_NEVER_LOAD; }
| DSECT { $$ = 0; }
| COPY { $$ = 0; }
| INFO { $$ = 0; }
| OVERLAY { $$ = 0; }
| { $$ = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; }
;

View File

@ -16,10 +16,6 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* $Id$
*
*/
#include "bfd.h"
#include "sysdep.h"
@ -459,6 +455,7 @@ DEFUN (lang_output_section_statement_lookup, (name),
lookup->next = (lang_statement_union_type *) NULL;
lookup->bfd_section = (asection *) NULL;
lookup->processed = false;
lookup->loadable = 1;
lookup->addr_tree = (etree_type *) NULL;
lang_list_init (&lookup->children);
@ -485,7 +482,7 @@ DEFUN (print_flags, (ignore_flags),
if (flags->flag_loadable)
fprintf (outfile, "L");
#endif
fprintf (config.map_file, ")");
fprintf (config.map_file, ")");
}
void
@ -497,7 +494,9 @@ DEFUN_VOID (lang_map)
#ifdef HOST_64_BIT
fprintf (config.map_file, "name\t\torigin\t\tlength\t\tattributes\n");
#else
fprintf (config.map_file, "name\t\torigin length\t\tattributes\n");
fprintf (config.map_file,
"name\t\torigin length r_size c_size is attributes\n");
#endif
for (m = lang_memory_region_list;
m != (lang_memory_region_type *) NULL;
@ -508,6 +507,12 @@ DEFUN_VOID (lang_map)
print_space ();
print_address (m->length);
print_space ();
print_address (m->old_length);
print_space();
print_address (m->current - m->origin);
print_space();
if (m->old_length)
fprintf(config.map_file," %2d%% ", ( m->current - m->origin) * 100 / m->old_length);
print_flags (&m->flags);
fprintf (config.map_file, "\n");
}
@ -540,7 +545,7 @@ DEFUN (init_os, (s),
output_bfd->xvec->name, s->name);
}
s->bfd_section->output_section = s->bfd_section;
/* s->bfd_section->flags = s->flags;*/
/* s->bfd_section->flags = s->flags;*/
/* We initialize an output sections output offset to minus its own */
/* vma to allow us to output a section through itself */
@ -571,25 +576,30 @@ DEFUN (wild_doit, (ptr, section, output, file),
lang_input_statement_type * file)
{
if (output->bfd_section == (asection *) NULL)
{
init_os (output);
}
{
init_os (output);
}
if (section != (asection *) NULL
&& section->output_section == (asection *) NULL)
{
/* Add a section reference to the list */
lang_input_section_type *new = new_stat (lang_input_section, ptr);
{
/* Add a section reference to the list */
lang_input_section_type *new = new_stat (lang_input_section, ptr);
new->section = section;
new->ifile = file;
section->output_section = output->bfd_section;
section->output_section->flags |= section->flags;
if (section->alignment_power > output->bfd_section->alignment_power)
{
output->bfd_section->alignment_power = section->alignment_power;
}
new->section = section;
new->ifile = file;
section->output_section = output->bfd_section;
section->output_section->flags |= section->flags;
if (!output->loadable)
{
/* Turn of load flag */
output->bfd_section->flags &= ~SEC_LOAD;
}
if (section->alignment_power > output->bfd_section->alignment_power)
{
output->bfd_section->alignment_power = section->alignment_power;
}
}
}
static asection *
@ -721,30 +731,30 @@ DEFUN (open_output, (name),
bfd *output;
if (output_target == (char *) NULL)
{
if (current_target != (char *) NULL)
output_target = current_target;
else
output_target = default_target;
}
{
if (current_target != (char *) NULL)
output_target = current_target;
else
output_target = default_target;
}
output = bfd_openw (name, output_target);
output_filename = name;
if (output == (bfd *) NULL)
{
if (bfd_error == invalid_target)
{
einfo ("%P%F target %s not found\n", output_target);
if (bfd_error == invalid_target)
{
einfo ("%P%F target %s not found\n", output_target);
}
einfo ("%P%F problem opening output file %s, %E", name);
}
einfo ("%P%F problem opening output file %s, %E", name);
}
/* output->flags |= D_PAGED;*/
bfd_set_format (output, bfd_object);
bfd_set_arch_mach(output,
ldfile_output_architecture,
ldfile_output_machine);
bfd_set_arch_mach (output,
ldfile_output_architecture,
ldfile_output_machine);
return output;
}
@ -1009,7 +1019,9 @@ DEFUN (print_output_section_statement, (output_section_statement),
print_space ();
print_address (section->vma);
print_space ();
print_size (bfd_get_section_size_before_reloc (section));
print_size (section->_raw_size);
print_space();
print_size(section->_cooked_size);
print_space ();
print_alignment (section->alignment_power);
print_space ();
@ -1112,7 +1124,9 @@ DEFUN (print_input_section, (in),
{
print_address (i->output_section->vma + i->output_offset);
fprintf (config.map_file, " ");
print_size (size);
print_size (i->_raw_size);
fprintf (config.map_file, " ");
print_size(i->_cooked_size);
fprintf (config.map_file, " ");
print_alignment (i->alignment_power);
fprintf (config.map_file, " ");
@ -1141,20 +1155,20 @@ DEFUN (print_input_section, (in),
/* Find all the symbols in this file defined in this section */
if (in->ifile->symbol_count)
{
asymbol **p;
if (in->ifile->symbol_count)
{
asymbol **p;
for (p = in->ifile->asymbols; *p; p++)
{
asymbol *q = *p;
for (p = in->ifile->asymbols; *p; p++)
{
asymbol *q = *p;
if (bfd_get_section (q) == i && q->flags & BSF_GLOBAL)
{
print_symbol (q);
}
}
}
if (bfd_get_section (q) == i && q->flags & BSF_GLOBAL)
{
print_symbol (q);
}
}
}
}
else
{
@ -1382,11 +1396,13 @@ DEFUN (insert_pad, (this_ptr, fill, power, output_section_statement, dot),
/* Work out how much this section will move the dot point */
static bfd_vma
DEFUN (size_input_section, (this_ptr, output_section_statement, fill, dot),
DEFUN (size_input_section, (this_ptr, output_section_statement, fill,
dot, relax),
lang_statement_union_type ** this_ptr AND
lang_output_section_statement_type * output_section_statement AND
unsigned short fill AND
bfd_vma dot)
bfd_vma dot AND
boolean relax)
{
lang_input_section_type *is = &((*this_ptr)->input_section);
asection *i = is->section;
@ -1410,10 +1426,17 @@ DEFUN (size_input_section, (this_ptr, output_section_statement, fill, dot),
i->output_offset = dot - output_section_statement->bfd_section->vma;
/* Mark how big the output section must be to contain this now */
dot += bfd_get_section_size_before_reloc (i);
output_section_statement->bfd_section->_raw_size =
dot - output_section_statement->bfd_section->vma;
/* Mark how big the output section must be to contain this now
*/
if (relax)
{
dot += i->_cooked_size;
}
else
{
dot += i->_raw_size;
}
output_section_statement->bfd_section->_raw_size = dot - output_section_statement->bfd_section->vma;
}
else
{
@ -1441,213 +1464,219 @@ DEFUN (lang_size_sections, (s, output_section_statement, prev, fill,
{
/* Size up the sections from their constituent parts */
for (; s != (lang_statement_union_type *) NULL; s = s->next)
{
switch (s->header.type)
{
switch (s->header.type)
{
case lang_output_section_statement_enum:
{
bfd_vma after;
lang_output_section_statement_type *os = &s->output_section_statement;
case lang_output_section_statement_enum:
{
bfd_vma after;
lang_output_section_statement_type *os = &s->output_section_statement;
if (os->bfd_section == &bfd_abs_section)
{
/* No matter what happens, an abs section starts at zero */
bfd_set_section_vma (0, os->bfd_section, 0);
}
else
{
if (os->addr_tree == (etree_type *) NULL)
{
/* No address specified for this section, get one
from the region specification
*/
if (os->region == (lang_memory_region_type *) NULL)
{
os->region = lang_memory_region_lookup ("*default*");
}
dot = os->region->current;
}
else
{
etree_value_type r;
if (os->bfd_section == &bfd_abs_section)
{
/* No matter what happens, an abs section starts at zero */
bfd_set_section_vma (0, os->bfd_section, 0);
}
else
{
if (os->addr_tree == (etree_type *) NULL)
{
/* No address specified for this section, get one
from the region specification
*/
if (os->region == (lang_memory_region_type *) NULL)
{
os->region = lang_memory_region_lookup ("*default*");
}
dot = os->region->current;
}
else
{
etree_value_type r;
r = exp_fold_tree (os->addr_tree,
abs_output_section,
lang_allocating_phase_enum,
dot, &dot);
if (r.valid == false)
{
einfo ("%F%S: non constant address expression for section %s\n",
os->name);
}
dot = r.value;
}
/* The section starts here */
/* First, align to what the section needs */
r = exp_fold_tree (os->addr_tree,
abs_output_section,
lang_allocating_phase_enum,
dot, &dot);
if (r.valid == false)
{
einfo ("%F%S: non constant address expression for section %s\n",
os->name);
}
dot = r.value;
}
/* The section starts here */
/* First, align to what the section needs */
dot = align_power (dot, os->bfd_section->alignment_power);
bfd_set_section_vma (0, os->bfd_section, dot);
}
dot = align_power (dot, os->bfd_section->alignment_power);
bfd_set_section_vma (0, os->bfd_section, dot);
}
os->bfd_section->output_offset = 0;
os->bfd_section->output_offset = 0;
(void) lang_size_sections (os->children.head, os, &os->children.head,
os->fill, dot, relax);
/* Ignore the size of the input sections, use the vma and size to */
/* align against */
(void) lang_size_sections (os->children.head, os, &os->children.head,
os->fill, dot, relax);
/* Ignore the size of the input sections, use the vma and size to */
/* align against */
after = ALIGN (os->bfd_section->vma +
os->bfd_section->_raw_size,
os->block_value);
after = ALIGN (os->bfd_section->vma +
os->bfd_section->_raw_size,
os->block_value);
os->bfd_section->_raw_size = after - os->bfd_section->vma;
dot = os->bfd_section->vma + os->bfd_section->_raw_size;
os->processed = true;
os->bfd_section->_raw_size = after - os->bfd_section->vma;
dot = os->bfd_section->vma + os->bfd_section->_raw_size;
os->processed = true;
/* Replace into region ? */
if (os->addr_tree == (etree_type *) NULL
&& os->region != (lang_memory_region_type *) NULL)
{
os->region->current = dot;
/* Make sure this isn't silly */
if (os->region->current >
os->region->origin +
os->region->length)
{
einfo ("%X%P: Region %s is full (%B section %s)\n",
os->region->name,
os->bfd_section->owner,
os->bfd_section->name);
/* Reset the region pointer */
os->region->current = 0;
/* Replace into region ? */
if (os->addr_tree == (etree_type *) NULL
&& os->region != (lang_memory_region_type *) NULL)
{
os->region->current = dot;
/* Make sure this isn't silly */
if (os->region->current >
os->region->origin +
os->region->length)
{
einfo ("%X%P: Region %s is full (%B section %s)\n",
os->region->name,
os->bfd_section->owner,
os->bfd_section->name);
/* Reset the region pointer */
os->region->current = 0;
}
}
}
}
}
}
break;
case lang_constructors_statement_enum:
dot = lang_size_sections (constructor_list.head,
output_section_statement,
&s->wild_statement.children.head,
fill,
dot, relax);
break;
break;
case lang_constructors_statement_enum:
dot = lang_size_sections (constructor_list.head,
output_section_statement,
&s->wild_statement.children.head,
fill,
dot, relax);
break;
case lang_data_statement_enum:
{
unsigned int size = 0;
case lang_data_statement_enum:
{
unsigned int size = 0;
s->data_statement.output_vma = dot - output_section_statement->bfd_section->vma;
s->data_statement.output_section =
output_section_statement->bfd_section;
s->data_statement.output_vma = dot - output_section_statement->bfd_section->vma;
s->data_statement.output_section =
output_section_statement->bfd_section;
switch (s->data_statement.type)
{
case LONG:
size = LONG_SIZE;
break;
case SHORT:
size = SHORT_SIZE;
break;
case BYTE:
size = BYTE_SIZE;
break;
switch (s->data_statement.type)
{
case LONG:
size = LONG_SIZE;
break;
case SHORT:
size = SHORT_SIZE;
break;
case BYTE:
size = BYTE_SIZE;
break;
}
dot += size;
output_section_statement->bfd_section->_raw_size += size;
}
break;
}
dot += size;
output_section_statement->bfd_section->_raw_size += size;
}
break;
case lang_wild_statement_enum:
case lang_wild_statement_enum:
dot = lang_size_sections (s->wild_statement.children.head,
output_section_statement,
&s->wild_statement.children.head,
dot = lang_size_sections (s->wild_statement.children.head,
output_section_statement,
&s->wild_statement.children.head,
fill, dot, relax);
fill, dot, relax);
break;
break;
case lang_object_symbols_statement_enum:
create_object_symbols = output_section_statement;
break;
case lang_output_statement_enum:
case lang_target_statement_enum:
break;
case lang_input_section_enum:
if (relax)
{
relaxing = true;
case lang_object_symbols_statement_enum:
create_object_symbols = output_section_statement;
break;
case lang_output_statement_enum:
case lang_target_statement_enum:
break;
case lang_input_section_enum:
if (relax)
{
relaxing = true;
had_relax = had_relax || relax_section (prev);
relaxing = false;
if( relax_section (prev))
had_relax = true;
relaxing = false;
}
}
else {
(*prev)->input_section.section->_cooked_size =
(*prev)->input_section.section->_raw_size ;
dot = size_input_section (prev,
output_section_statement,
output_section_statement->fill, dot);
break;
case lang_input_statement_enum:
break;
case lang_fill_statement_enum:
s->fill_statement.output_section = output_section_statement->bfd_section;
}
dot = size_input_section (prev,
output_section_statement,
output_section_statement->fill,
dot, relax);
break;
case lang_input_statement_enum:
break;
case lang_fill_statement_enum:
s->fill_statement.output_section = output_section_statement->bfd_section;
fill = s->fill_statement.fill;
break;
case lang_assignment_statement_enum:
{
bfd_vma newdot = dot;
fill = s->fill_statement.fill;
break;
case lang_assignment_statement_enum:
{
bfd_vma newdot = dot;
exp_fold_tree (s->assignment_statement.exp,
output_section_statement,
lang_allocating_phase_enum,
dot,
&newdot);
exp_fold_tree (s->assignment_statement.exp,
output_section_statement,
lang_allocating_phase_enum,
dot,
&newdot);
if (newdot != dot && !relax)
/* We've been moved ! so insert a pad */
{
lang_statement_union_type *new =
(lang_statement_union_type *)
stat_alloc ((bfd_size_type) (sizeof (lang_padding_statement_type)));
if (newdot != dot && !relax)
/* We've been moved ! so insert a pad */
{
lang_statement_union_type *new =
(lang_statement_union_type *)
stat_alloc ((bfd_size_type) (sizeof (lang_padding_statement_type)));
/* Link into existing chain */
new->header.next = *prev;
*prev = new;
new->header.type = lang_padding_statement_enum;
new->padding_statement.output_section =
output_section_statement->bfd_section;
new->padding_statement.output_offset =
dot - output_section_statement->bfd_section->vma;
new->padding_statement.fill = fill;
new->padding_statement.size = newdot - dot;
output_section_statement->bfd_section->_raw_size +=
new->padding_statement.size;
dot = newdot;
}
}
/* Link into existing chain */
new->header.next = *prev;
*prev = new;
new->header.type = lang_padding_statement_enum;
new->padding_statement.output_section =
output_section_statement->bfd_section;
new->padding_statement.output_offset =
dot - output_section_statement->bfd_section->vma;
new->padding_statement.fill = fill;
new->padding_statement.size = newdot - dot;
output_section_statement->bfd_section->_raw_size +=
new->padding_statement.size;
dot = newdot;
}
}
break;
default:
FAIL ();
break;
/* This can only get here when relaxing is turned on */
case lang_padding_statement_enum:
break;
default:
FAIL ();
break;
/* This can only get here when relaxing is turned on */
case lang_padding_statement_enum:
case lang_address_statement_enum:
break;
}
prev = &s->header.next;
case lang_address_statement_enum:
break;
}
prev = &s->header.next;
}
return dot;
}
@ -2202,6 +2231,10 @@ DEFUN (lang_enter_output_section_statement,
address_exp;
}
os->flags = flags;
if (flags & SEC_NEVER_LOAD)
os->loadable = 0;
else
os->loadable = 1;
os->block_value = block_value;
stat_ptr = &os->children;
@ -2228,11 +2261,13 @@ DEFUN_VOID (reset_memory_regions)
p != (lang_memory_region_type *) NULL;
p = p->next)
{
p->old_length = p->current - p->origin;
p->current = p->origin;
}
}
asymbol *
DEFUN (create_symbol, (name, flags, section),
CONST char *name AND
@ -2301,38 +2336,65 @@ DEFUN_VOID (lang_process)
ldemul_before_allocation ();
/* Size up the sections */
lang_size_sections (statement_list.head,
abs_output_section,
&(statement_list.head), 0, (bfd_vma) 0, false);
#if 0
had_relax = true;
while (had_relax)
{
had_relax = false;
lang_size_sections (statement_list.head,
(lang_output_section_statement_type *) NULL,
&(statement_list.head), 0, (bfd_vma) 0, true);
/* FIXME. Until the code in relax is fixed so that it only reads in
stuff once, we cant iterate since there is no way for the linker to
know what has been patched and what hasn't */
break;
}
#endif
/* Now run around and relax if we can */
if (command_line.relax)
{
reset_memory_regions ();
/* Move the global symbols around */
lang_relocate_globals ();
had_relax = true;
while (had_relax)
{
had_relax = false;
lang_size_sections (statement_list.head,
(lang_output_section_statement_type *) NULL,
&(statement_list.head), 0, (bfd_vma) 0, true);
/* FIXME. Until the code in relax is fixed so that it only reads in
stuff once, we cant iterate since there is no way for the linker to
know what has been patched and what hasn't */
break;
}
/* First time round is a trial run to get the 'worst case' addresses of the
objects if there was no relaxing */
lang_size_sections (statement_list.head,
(lang_output_section_statement_type *) NULL,
&(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 ();
/* Do all the assignments, now that we know the final restingplaces
of all the symbols */
lang_do_assignments (statement_list.head,
abs_output_section,
0, (bfd_vma) 0);
/* Perform another relax pass - this time we know where the
globals are, so can make better guess */
lang_size_sections (statement_list.head,
(lang_output_section_statement_type *) NULL,
&(statement_list.head), 0, (bfd_vma) 0, true);
}
else
{
/* Size up the sections */
lang_size_sections (statement_list.head,
abs_output_section,
&(statement_list.head), 0, (bfd_vma) 0, false);
}