Add LMA memory region functionality.

This commit is contained in:
Timothy Wall 2000-02-16 18:53:32 +00:00
parent a4f419971f
commit 562d3460fb
9 changed files with 138 additions and 46 deletions

View file

@ -1,3 +1,24 @@
2000-02-16 Timothy Wall <twall@cygnus.com>
* mri.c (mri_draw_tree): Add default LMA region argument to call
to lang_leave_output_section_statement.
* ldlang.h: Update prototypes with LMA region arguments.
* ldlang.c (lang_size_sections): Encapsulate region bounds
checking in os_check_region call.
(os_check_region): New function.
(lang_output_section_statement_lookup): Initialize lma_region.
(lang_leave_output_section_statement): Add LMA region argument.
(lang_leave_overlay): Ditto.
* ldgram.y: Handle LMA region syntax.
* ld.texinfo (Output Section Description): Describe LMA region usage.
* emultempl/armelf.em (gld$place_orphan): Add default value for
lma region in call to lang_leave_output_statement.
* emultempl/elf32.em (gld$place_orphan): Add default value for
lma region in call to lang_leave_output_statement.
* emultempl/pe.em (gld$place_orphan): Add default value for
lma region in call to lang_leave_output_statement.
2000-02-04 Timothy Wall <twall@redhat.com> 2000-02-04 Timothy Wall <twall@redhat.com>
* ldlang.c (lang_check_section_addresses): Use bytes instead of * ldlang.c (lang_check_section_addresses): Use bytes instead of

View file

@ -942,7 +942,8 @@ gld${EMULATION_NAME}_place_orphan (file, s)
wild_doit (&os->children, s, os, file); wild_doit (&os->children, s, os, file);
lang_leave_output_section_statement lang_leave_output_section_statement
((bfd_vma) 0, "*default*", (struct lang_output_section_phdr_list *) NULL); ((bfd_vma) 0, "*default*", (struct lang_output_section_phdr_list *) NULL,
"*default*");
stat_ptr = &add; stat_ptr = &add;
if (*ps == '\0' && config.build_constructors) if (*ps == '\0' && config.build_constructors)

View file

@ -1024,7 +1024,8 @@ gld${EMULATION_NAME}_place_orphan (file, s)
wild_doit (&os->children, s, os, file); wild_doit (&os->children, s, os, file);
lang_leave_output_section_statement lang_leave_output_section_statement
((bfd_vma) 0, "*default*", (struct lang_output_section_phdr_list *) NULL); ((bfd_vma) 0, "*default*", (struct lang_output_section_phdr_list *) NULL,
"*default*");
stat_ptr = &add; stat_ptr = &add;
if (*ps == '\0' && config.build_constructors) if (*ps == '\0' && config.build_constructors)

View file

@ -1146,7 +1146,8 @@ gld_${EMULATION_NAME}_place_orphan (file, s)
lang_leave_output_section_statement lang_leave_output_section_statement
((bfd_vma) 0, "*default*", ((bfd_vma) 0, "*default*",
(struct lang_output_section_phdr_list *) NULL); (struct lang_output_section_phdr_list *) NULL,
"*default*");
/* Now stick the new statement list right after PLACE. */ /* Now stick the new statement list right after PLACE. */
if (place != NULL) if (place != NULL)

View file

@ -2127,7 +2127,7 @@ The full description of an output section looks like this:
@var{output-section-command} @var{output-section-command}
@var{output-section-command} @var{output-section-command}
@dots{} @dots{}
@} [>@var{region}] [:@var{phdr} :@var{phdr} @dots{}] [=@var{fillexp}] @} [>@var{region}] [AT>@var{lma_region}] [:@var{phdr} :@var{phdr} @dots{}] [=@var{fillexp}]
@end group @end group
@end smallexample @end smallexample
@ -2632,7 +2632,7 @@ like this:
@var{output-section-command} @var{output-section-command}
@var{output-section-command} @var{output-section-command}
@dots{} @dots{}
@} [>@var{region}] [:@var{phdr} :@var{phdr} @dots{}] [=@var{fillexp}] @} [>@var{region}] [AT>@var{lma_region}] [:@var{phdr} :@var{phdr} @dots{}] [=@var{fillexp}]
@end group @end group
@end smallexample @end smallexample
We've already described @var{section}, @var{address}, and We've already described @var{section}, @var{address}, and
@ -2686,6 +2686,7 @@ SECTIONS @{
@node Output Section LMA @node Output Section LMA
@subsubsection Output section LMA @subsubsection Output section LMA
@kindex AT>@var{lma_region}
@kindex AT(@var{lma}) @kindex AT(@var{lma})
@cindex load address @cindex load address
@cindex section load address @cindex section load address
@ -2696,7 +2697,9 @@ Address}).
The linker will normally set the LMA equal to the VMA. You can change The linker will normally set the LMA equal to the VMA. You can change
that by using the @code{AT} keyword. The expression @var{lma} that that by using the @code{AT} keyword. The expression @var{lma} that
follows the @code{AT} keyword specifies the load address of the section. follows the @code{AT} keyword specifies the load address of the
section. Alternatively, with @samp{AT>@var{lma_region}} expression,
you may specify a memory region for the section's load address. @xref{MEMORY}.
@cindex ROM initialized data @cindex ROM initialized data
@cindex initialized data in ROM @cindex initialized data in ROM

View file

@ -92,6 +92,7 @@ static int error_index;
%type <integer> fill_opt %type <integer> fill_opt
%type <name_list> exclude_name_list %type <name_list> exclude_name_list
%type <name> memspec_opt casesymlist %type <name> memspec_opt casesymlist
%type <name> memspec_at_opt
%type <cname> wildcard_name %type <cname> wildcard_name
%type <wildcard> wildcard_spec %type <wildcard> wildcard_spec
%token <integer> INT %token <integer> INT
@ -799,6 +800,11 @@ exp :
; ;
memspec_at_opt:
AT '>' NAME { $$ = $3; }
| { $$ = "*default*"; }
;
opt_at: opt_at:
AT '(' exp ')' { $$ = $3; } AT '(' exp ')' { $$ = $3; }
| { $$ = 0; } | { $$ = 0; }
@ -815,10 +821,10 @@ section: NAME { ldlex_expression(); }
} }
statement_list_opt statement_list_opt
'}' { ldlex_popstate (); ldlex_expression (); } '}' { ldlex_popstate (); ldlex_expression (); }
memspec_opt phdr_opt fill_opt memspec_opt memspec_at_opt phdr_opt fill_opt
{ {
ldlex_popstate (); ldlex_popstate ();
lang_leave_output_section_statement ($13, $11, $12); lang_leave_output_section_statement ($14, $11, $13, $12);
} }
opt_comma opt_comma
| OVERLAY | OVERLAY
@ -832,10 +838,10 @@ section: NAME { ldlex_expression(); }
overlay_section overlay_section
'}' '}'
{ ldlex_popstate (); ldlex_expression (); } { ldlex_popstate (); ldlex_expression (); }
memspec_opt phdr_opt fill_opt memspec_opt memspec_at_opt phdr_opt fill_opt
{ {
ldlex_popstate (); ldlex_popstate ();
lang_leave_overlay ($14, $12, $13); lang_leave_overlay ($15, $12, $14, $13);
} }
opt_comma opt_comma
| /* The GROUP case is just enough to support the gcc | /* The GROUP case is just enough to support the gcc

View file

@ -682,6 +682,7 @@ lang_output_section_statement_lookup (name)
lookup = (lang_output_section_statement_type *) lookup = (lang_output_section_statement_type *)
new_stat (lang_output_section_statement, stat_ptr); new_stat (lang_output_section_statement, stat_ptr);
lookup->region = (lang_memory_region_type *) NULL; lookup->region = (lang_memory_region_type *) NULL;
lookup->lma_region = (lang_memory_region_type *) NULL;
lookup->fill = 0; lookup->fill = 0;
lookup->block_value = 1; lookup->block_value = 1;
lookup->name = name; lookup->name = name;
@ -2695,6 +2696,43 @@ _("%X%P: section %s [%V -> %V] overlaps section %s [%V -> %V]\n"),
static boolean relax_again; static boolean relax_again;
/* Make sure the new address is within the region. We explicitly permit the
current address to be at the exact end of the region when the address is
non-zero, in case the region is at the end of addressable memory and the
calculation wraps around. */
static void
os_region_check (os, region, tree, base)
lang_output_section_statement_type *os;
struct memory_region_struct *region;
etree_type *tree;
bfd_vma base;
{
if ((region->current < region->origin
|| (region->current - region->origin > region->length))
&& ((region->current != region->origin + region->length)
|| base == 0))
{
if (tree != (etree_type *) NULL)
{
einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"),
region->current,
os->bfd_section->owner,
os->bfd_section->name,
region->name);
}
else
{
einfo (_("%X%P: region %s is full (%B section %s)\n"),
region->name,
os->bfd_section->owner,
os->bfd_section->name);
}
/* Reset the region pointer. */
region->current = region->origin;
}
}
/* Set the sizes for all the output sections. */ /* Set the sizes for all the output sections. */
bfd_vma bfd_vma
@ -2853,37 +2891,35 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
{ {
os->region->current = dot; os->region->current = dot;
/* Make sure the new address is within the region. We /* Make sure the new address is within the region. */
explicitly permit the current address to be at the os_region_check (os, os->region, os->addr_tree,
exact end of the region when the VMA is non-zero, os->bfd_section->vma);
in case the region is at the end of addressable
memory and the calculation wraps around. */
if ((os->region->current < os->region->origin
|| (os->region->current - os->region->origin
> os->region->length))
&& ((os->region->current
!= os->region->origin + os->region->length)
|| os->bfd_section->vma == 0))
{ /* if there's no load address specified, use the run region as
if (os->addr_tree != (etree_type *) NULL) the load region */
{ if (os->lma_region == NULL && os->load_base == NULL)
einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"), os->lma_region = os->region;
os->region->current,
os->bfd_section->owner, if (os->lma_region != NULL)
os->bfd_section->name, {
os->region->name); if (os->load_base != NULL)
} {
else einfo (_("%X%P: use an absolute load address or a load memory region, not both\n"));
{ }
einfo (_("%X%P: region %s is full (%B section %s)\n"), else
os->region->name, {
os->bfd_section->owner, /* don't allocate twice */
os->bfd_section->name); if (os->lma_region != os->region)
} {
/* Reset the region pointer. */ /* set load_base, which will be handled later */
os->region->current = os->region->origin; os->load_base = exp_intop (os->lma_region->current);
} os->lma_region->current +=
os->bfd_section->_raw_size / opb;
os_region_check (os, os->lma_region, NULL,
os->bfd_section->lma);
}
}
}
} }
} }
break; break;
@ -4259,13 +4295,22 @@ lang_float (maybe)
} }
void void
lang_leave_output_section_statement (fill, memspec, phdrs) lang_leave_output_section_statement (fill, memspec, phdrs, lma_memspec)
bfd_vma fill; bfd_vma fill;
const char *memspec; const char *memspec;
struct lang_output_section_phdr_list *phdrs; struct lang_output_section_phdr_list *phdrs;
const char *lma_memspec;
{ {
current_section->fill = fill; current_section->fill = fill;
current_section->region = lang_memory_region_lookup (memspec); current_section->region = lang_memory_region_lookup (memspec);
if (strcmp (lma_memspec, "*default*") != 0)
{
current_section->lma_region = lang_memory_region_lookup (lma_memspec);
/* if no runtime region has been given, but the load region has been,
use the load region */
if (strcmp (memspec, "*default*") == 0)
current_section->region = lang_memory_region_lookup (lma_memspec);
}
current_section->phdrs = phdrs; current_section->phdrs = phdrs;
stat_ptr = &statement_list; stat_ptr = &statement_list;
} }
@ -4644,7 +4689,8 @@ lang_leave_overlay_section (fill, phdrs)
name = current_section->name; name = current_section->name;
lang_leave_output_section_statement (fill, "*default*", phdrs); lang_leave_output_section_statement (fill, "*default*",
phdrs, "*default*");
/* Define the magic symbols. */ /* Define the magic symbols. */
@ -4674,12 +4720,14 @@ lang_leave_overlay_section (fill, phdrs)
looks through all the sections in the overlay and sets them. */ looks through all the sections in the overlay and sets them. */
void void
lang_leave_overlay (fill, memspec, phdrs) lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
bfd_vma fill; bfd_vma fill;
const char *memspec; const char *memspec;
struct lang_output_section_phdr_list *phdrs; struct lang_output_section_phdr_list *phdrs;
const char *lma_memspec;
{ {
lang_memory_region_type *region; lang_memory_region_type *region;
lang_memory_region_type *lma_region;
struct overlay_list *l; struct overlay_list *l;
struct lang_nocrossref *nocrossref; struct lang_nocrossref *nocrossref;
@ -4688,6 +4736,11 @@ lang_leave_overlay (fill, memspec, phdrs)
else else
region = lang_memory_region_lookup (memspec); region = lang_memory_region_lookup (memspec);
if (lma_memspec == NULL)
lma_region = NULL;
else
lma_region = lang_memory_region_lookup (lma_memspec);
nocrossref = NULL; nocrossref = NULL;
l = overlay_list; l = overlay_list;
@ -4699,6 +4752,8 @@ lang_leave_overlay (fill, memspec, phdrs)
l->os->fill = fill; l->os->fill = fill;
if (region != NULL && l->os->region == NULL) if (region != NULL && l->os->region == NULL)
l->os->region = region; l->os->region = region;
if (lma_region != NULL && l->os->lma_region == NULL)
l->os->lma_region = lma_region;
if (phdrs != NULL && l->os->phdrs == NULL) if (phdrs != NULL && l->os->phdrs == NULL)
l->os->phdrs = phdrs; l->os->phdrs = phdrs;

View file

@ -136,6 +136,7 @@ typedef struct lang_output_section_statement_struct
flagword flags; /* Or together of all input sections */ flagword flags; /* Or together of all input sections */
enum section_type sectype; enum section_type sectype;
struct memory_region_struct *region; struct memory_region_struct *region;
struct memory_region_struct *lma_region;
size_t block_value; size_t block_value;
fill_type fill; fill_type fill;
@ -409,7 +410,8 @@ extern void lang_add_attribute PARAMS ((enum statement_enum));
extern void lang_startup PARAMS ((const char *)); extern void lang_startup PARAMS ((const char *));
extern void lang_float PARAMS ((enum bfd_boolean)); extern void lang_float PARAMS ((enum bfd_boolean));
extern void lang_leave_output_section_statement extern void lang_leave_output_section_statement
PARAMS ((bfd_vma, const char *, struct lang_output_section_phdr_list *)); PARAMS ((bfd_vma, const char *, struct lang_output_section_phdr_list *,
const char *));
extern void lang_abs_symbol_at_end_of PARAMS ((const char *, const char *)); extern void lang_abs_symbol_at_end_of PARAMS ((const char *, const char *));
extern void lang_abs_symbol_at_beginning_of PARAMS ((const char *, extern void lang_abs_symbol_at_beginning_of PARAMS ((const char *,
const char *)); const char *));
@ -475,7 +477,8 @@ extern void lang_enter_overlay_section PARAMS ((const char *));
extern void lang_leave_overlay_section extern void lang_leave_overlay_section
PARAMS ((bfd_vma, struct lang_output_section_phdr_list *)); PARAMS ((bfd_vma, struct lang_output_section_phdr_list *));
extern void lang_leave_overlay extern void lang_leave_overlay
PARAMS ((bfd_vma, const char *, struct lang_output_section_phdr_list *)); PARAMS ((bfd_vma, const char *, struct lang_output_section_phdr_list *,
const char *));
extern struct bfd_elf_version_tree *lang_elf_version_info; extern struct bfd_elf_version_tree *lang_elf_version_info;

View file

@ -266,7 +266,8 @@ mri_draw_tree ()
} }
lang_leave_output_section_statement lang_leave_output_section_statement
(0, "*default*", (struct lang_output_section_phdr_list *) NULL); (0, "*default*", (struct lang_output_section_phdr_list *) NULL,
"*default*");
p = p->next; p = p->next;
} }