aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
authorTimothy Wall <twall@alum.mit.edu>2000-02-16 18:53:32 +0000
committerTimothy Wall <twall@alum.mit.edu>2000-02-16 18:53:32 +0000
commit562d3460fb28a90014290ac99c543f1085676a26 (patch)
tree58dc7ce8264e61d1142039093a28c5ba36e24898 /ld
parenta4f419971fc5444ee68a8e318a81464c8d8e51c3 (diff)
downloadfsf-binutils-gdb-562d3460fb28a90014290ac99c543f1085676a26.zip
fsf-binutils-gdb-562d3460fb28a90014290ac99c543f1085676a26.tar.gz
fsf-binutils-gdb-562d3460fb28a90014290ac99c543f1085676a26.tar.bz2
Add LMA memory region functionality.
Diffstat (limited to 'ld')
-rw-r--r--ld/ChangeLog21
-rw-r--r--ld/emultempl/armelf.em3
-rw-r--r--ld/emultempl/elf32.em3
-rw-r--r--ld/emultempl/pe.em3
-rw-r--r--ld/ld.texinfo9
-rw-r--r--ld/ldgram.y14
-rw-r--r--ld/ldlang.c123
-rw-r--r--ld/ldlang.h7
-rw-r--r--ld/mri.c3
9 files changed, 139 insertions, 47 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 1ceee7a..da28575 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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>
* ldlang.c (lang_check_section_addresses): Use bytes instead of
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index 345b12c..f6d5ef4 100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -942,7 +942,8 @@ gld${EMULATION_NAME}_place_orphan (file, s)
wild_doit (&os->children, s, os, file);
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;
if (*ps == '\0' && config.build_constructors)
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index f2ff4d8..78676e1 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -1024,7 +1024,8 @@ gld${EMULATION_NAME}_place_orphan (file, s)
wild_doit (&os->children, s, os, file);
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;
if (*ps == '\0' && config.build_constructors)
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 1ebc091..0112c46 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -1146,7 +1146,8 @@ gld_${EMULATION_NAME}_place_orphan (file, s)
lang_leave_output_section_statement
((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. */
if (place != NULL)
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index a786dd2..8ecdef2 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -2127,7 +2127,7 @@ The full description of an output section looks like this:
@var{output-section-command}
@var{output-section-command}
@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 smallexample
@@ -2632,7 +2632,7 @@ like this:
@var{output-section-command}
@var{output-section-command}
@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 smallexample
We've already described @var{section}, @var{address}, and
@@ -2686,6 +2686,7 @@ SECTIONS @{
@node Output Section LMA
@subsubsection Output section LMA
+@kindex AT>@var{lma_region}
@kindex AT(@var{lma})
@cindex 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
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 initialized data in ROM
diff --git a/ld/ldgram.y b/ld/ldgram.y
index 73ee4952..7189812 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -92,6 +92,7 @@ static int error_index;
%type <integer> fill_opt
%type <name_list> exclude_name_list
%type <name> memspec_opt casesymlist
+%type <name> memspec_at_opt
%type <cname> wildcard_name
%type <wildcard> wildcard_spec
%token <integer> INT
@@ -799,6 +800,11 @@ exp :
;
+memspec_at_opt:
+ AT '>' NAME { $$ = $3; }
+ | { $$ = "*default*"; }
+ ;
+
opt_at:
AT '(' exp ')' { $$ = $3; }
| { $$ = 0; }
@@ -815,10 +821,10 @@ section: NAME { ldlex_expression(); }
}
statement_list_opt
'}' { ldlex_popstate (); ldlex_expression (); }
- memspec_opt phdr_opt fill_opt
+ memspec_opt memspec_at_opt phdr_opt fill_opt
{
ldlex_popstate ();
- lang_leave_output_section_statement ($13, $11, $12);
+ lang_leave_output_section_statement ($14, $11, $13, $12);
}
opt_comma
| OVERLAY
@@ -832,10 +838,10 @@ section: NAME { ldlex_expression(); }
overlay_section
'}'
{ ldlex_popstate (); ldlex_expression (); }
- memspec_opt phdr_opt fill_opt
+ memspec_opt memspec_at_opt phdr_opt fill_opt
{
ldlex_popstate ();
- lang_leave_overlay ($14, $12, $13);
+ lang_leave_overlay ($15, $12, $14, $13);
}
opt_comma
| /* The GROUP case is just enough to support the gcc
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 6913a38..a514ea0 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -682,6 +682,7 @@ lang_output_section_statement_lookup (name)
lookup = (lang_output_section_statement_type *)
new_stat (lang_output_section_statement, stat_ptr);
lookup->region = (lang_memory_region_type *) NULL;
+ lookup->lma_region = (lang_memory_region_type *) NULL;
lookup->fill = 0;
lookup->block_value = 1;
lookup->name = name;
@@ -2695,6 +2696,43 @@ _("%X%P: section %s [%V -> %V] overlaps section %s [%V -> %V]\n"),
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. */
bfd_vma
@@ -2853,37 +2891,35 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
{
os->region->current = dot;
- /* 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 VMA is non-zero,
- 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 (os->addr_tree != (etree_type *) NULL)
- {
- einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"),
- os->region->current,
- os->bfd_section->owner,
- os->bfd_section->name,
- os->region->name);
- }
- else
- {
- 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 = os->region->origin;
- }
+ /* Make sure the new address is within the region. */
+ os_region_check (os, os->region, os->addr_tree,
+ os->bfd_section->vma);
+
+ /* if there's no load address specified, use the run region as
+ the load region */
+ if (os->lma_region == NULL && os->load_base == NULL)
+ os->lma_region = os->region;
+
+ if (os->lma_region != NULL)
+ {
+ if (os->load_base != NULL)
+ {
+ einfo (_("%X%P: use an absolute load address or a load memory region, not both\n"));
+ }
+ else
+ {
+ /* don't allocate twice */
+ if (os->lma_region != os->region)
+ {
+ /* set load_base, which will be handled later */
+ 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;
@@ -4259,13 +4295,22 @@ lang_float (maybe)
}
void
-lang_leave_output_section_statement (fill, memspec, phdrs)
+lang_leave_output_section_statement (fill, memspec, phdrs, lma_memspec)
bfd_vma fill;
const char *memspec;
struct lang_output_section_phdr_list *phdrs;
+ const char *lma_memspec;
{
current_section->fill = fill;
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;
stat_ptr = &statement_list;
}
@@ -4644,7 +4689,8 @@ lang_leave_overlay_section (fill, phdrs)
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. */
@@ -4674,12 +4720,14 @@ lang_leave_overlay_section (fill, phdrs)
looks through all the sections in the overlay and sets them. */
void
-lang_leave_overlay (fill, memspec, phdrs)
+lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
bfd_vma fill;
const char *memspec;
struct lang_output_section_phdr_list *phdrs;
+ const char *lma_memspec;
{
lang_memory_region_type *region;
+ lang_memory_region_type *lma_region;
struct overlay_list *l;
struct lang_nocrossref *nocrossref;
@@ -4688,6 +4736,11 @@ lang_leave_overlay (fill, memspec, phdrs)
else
region = lang_memory_region_lookup (memspec);
+ if (lma_memspec == NULL)
+ lma_region = NULL;
+ else
+ lma_region = lang_memory_region_lookup (lma_memspec);
+
nocrossref = NULL;
l = overlay_list;
@@ -4699,6 +4752,8 @@ lang_leave_overlay (fill, memspec, phdrs)
l->os->fill = fill;
if (region != NULL && l->os->region == NULL)
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)
l->os->phdrs = phdrs;
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 41ef5ba..068cd96 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -136,6 +136,7 @@ typedef struct lang_output_section_statement_struct
flagword flags; /* Or together of all input sections */
enum section_type sectype;
struct memory_region_struct *region;
+ struct memory_region_struct *lma_region;
size_t block_value;
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_float PARAMS ((enum bfd_boolean));
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_beginning_of PARAMS ((const char *,
const char *));
@@ -475,7 +477,8 @@ extern void lang_enter_overlay_section PARAMS ((const char *));
extern void lang_leave_overlay_section
PARAMS ((bfd_vma, struct lang_output_section_phdr_list *));
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;
diff --git a/ld/mri.c b/ld/mri.c
index 54aaea2..d39186c 100644
--- a/ld/mri.c
+++ b/ld/mri.c
@@ -266,7 +266,8 @@ mri_draw_tree ()
}
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;
}