This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
[PATCH] LMA memory regions
- To: binutils at sourceware dot cygnus dot com
- Subject: [PATCH] LMA memory regions
- From: Timothy Wall <twall at domesolutions dot com>
- Date: Wed, 16 Feb 2000 13:28:47 -0500
- CC: nickc at cygnus dot com
- Organization: Dome Solutions
This patch adds functionality for assigning sections to load-time memory
regions analagous to the existing function for assigning to run-time
memory regions.
(This is a stripped-down version of a previous patch)
T.
Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/ld/ChangeLog,v
retrieving revision 1.134
diff -d -c -p -r1.134 ChangeLog
*** ChangeLog 2000/02/09 14:42:47 1.134
--- ChangeLog 2000/02/16 18:22:07
***************
*** 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
Index: ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.10
diff -d -c -p -r1.10 ld.texinfo
*** ld.texinfo 2000/01/07 19:46:04 1.10
--- ld.texinfo 2000/02/16 18:22:08
*************** The full description of an output sectio
*** 2127,2133 ****
@var{output-section-command}
@var{output-section-command}
@dots{}
! @} [>@var{region}] [:@var{phdr} :@var{phdr} @dots{}] [=@var{fillexp}]
@end group
@end smallexample
--- 2127,2133 ----
@var{output-section-command}
@var{output-section-command}
@dots{}
! @} [>@var{region}] [AT>@var{lma_region}] [:@var{phdr} :@var{phdr} @dots{}] [=@var{fillexp}]
@end group
@end smallexample
*************** like this:
*** 2632,2638 ****
@var{output-section-command}
@var{output-section-command}
@dots{}
! @} [>@var{region}] [:@var{phdr} :@var{phdr} @dots{}] [=@var{fillexp}]
@end group
@end smallexample
We've already described @var{section}, @var{address}, and
--- 2632,2638 ----
@var{output-section-command}
@var{output-section-command}
@dots{}
! @} [>@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
*************** SECTIONS @{
*** 2686,2691 ****
--- 2686,2692 ----
@node Output Section LMA
@subsubsection Output section LMA
+ @kindex AT>@var{lma_region}
@kindex AT(@var{lma})
@cindex load address
@cindex section load address
*************** Address}).
*** 2696,2702 ****
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.
@cindex ROM initialized data
@cindex initialized data in ROM
--- 2697,2705 ----
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. 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
Index: ldgram.y
===================================================================
RCS file: /cvs/src/src/ld/ldgram.y,v
retrieving revision 1.3
diff -d -c -p -r1.3 ldgram.y
*** ldgram.y 2000/01/05 14:12:23 1.3
--- ldgram.y 2000/02/16 18:22:08
*************** static int error_index;
*** 92,97 ****
--- 92,98 ----
%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
*************** memory_spec_list:
*** 611,624 ****
| memory_spec_list ',' memory_spec
|
;
-
! memory_spec: NAME
! { region = lang_memory_region_lookup($1); }
! attributes_opt ':'
! origin_spec opt_comma length_spec
! ; origin_spec:
ORIGIN '=' mustbe_exp
{ region->current =
region->origin =
--- 612,636 ----
| memory_spec_list ',' memory_spec
|
;
! memory_spec:
! NAME {
! region = lang_memory_region_lookup($1);
! region->page = current_mempage;
! }
! attributes_opt ':' origin_spec opt_comma length_spec
! | PAGE INT ':' NAME
! {
! current_mempage = $2;
! if (($2 & 0xFF) != $2)
! einfo (_("%P%F:%S: page number %d out of range\n"), $2);
! region = lang_memory_region_lookup($4);
! region->page = current_mempage;
! }
! attributes_opt ':' origin_spec opt_comma length_spec
! ;
! origin_spec:
ORIGIN '=' mustbe_exp
{ region->current =
region->origin =
*************** exp :
*** 799,804 ****
--- 811,821 ----
;
+ memspec_at_opt:
+ AT '>' NAME { $$ = $3; }
+ | { $$ = "*default*"; }
+ ;
+
opt_at:
AT '(' exp ')' { $$ = $3; }
| { $$ = 0; }
*************** section: NAME { ldlex_expression(); }
*** 815,824 ****
}
statement_list_opt
'}' { ldlex_popstate (); ldlex_expression (); }
! memspec_opt phdr_opt fill_opt
{
ldlex_popstate ();
! lang_leave_output_section_statement ($13, $11, $12);
}
opt_comma
| OVERLAY
--- 832,841 ----
}
statement_list_opt
'}' { ldlex_popstate (); ldlex_expression (); }
! memspec_opt memspec_at_opt phdr_opt fill_opt
{
ldlex_popstate ();
! lang_leave_output_section_statement ($14, $11, $13, $12);
}
opt_comma
| OVERLAY
*************** section: NAME { ldlex_expression(); }
*** 832,841 ****
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
--- 849,858 ----
overlay_section
'}'
{ ldlex_popstate (); ldlex_expression (); }
! memspec_opt memspec_at_opt phdr_opt fill_opt
{
ldlex_popstate ();
! lang_leave_overlay ($15, $12, $14, $13);
}
opt_comma
| /* The GROUP case is just enough to support the gcc
Index: ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.22
diff -d -c -p -r1.22 ldlang.c
*** ldlang.c 2000/02/09 14:42:48 1.22
--- ldlang.c 2000/02/16 18:22:08
*************** lang_output_section_statement_lookup (na
*** 682,687 ****
--- 682,688 ----
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;
*************** _("%X%P: section %s [%V -> %V] overlaps
*** 2695,2700 ****
--- 2696,2738 ----
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
*************** lang_size_sections (s, output_section_st
*** 2853,2889 ****
{
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;
! }
}
}
break;
--- 2891,2925 ----
{
os->region->current = dot;
! /* 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;
*************** lang_float (maybe)
*** 4259,4271 ****
}
void
! lang_leave_output_section_statement (fill, memspec, phdrs)
bfd_vma fill;
const char *memspec;
struct lang_output_section_phdr_list *phdrs;
{
current_section->fill = fill;
current_section->region = lang_memory_region_lookup (memspec);
current_section->phdrs = phdrs;
stat_ptr = &statement_list;
}
--- 4295,4316 ----
}
void
! 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;
}
*************** lang_leave_overlay_section (fill, phdrs)
*** 4644,4650 ****
name = current_section->name;
! lang_leave_output_section_statement (fill, "*default*", phdrs);
/* Define the magic symbols. */
--- 4689,4696 ----
name = current_section->name;
! lang_leave_output_section_statement (fill, "*default*",
! phdrs, "*default*");
/* Define the magic symbols. */
*************** lang_leave_overlay_section (fill, phdrs)
*** 4674,4685 ****
looks through all the sections in the overlay and sets them. */
void
! lang_leave_overlay (fill, memspec, phdrs)
bfd_vma fill;
const char *memspec;
struct lang_output_section_phdr_list *phdrs;
{
lang_memory_region_type *region;
struct overlay_list *l;
struct lang_nocrossref *nocrossref;
--- 4720,4733 ----
looks through all the sections in the overlay and sets them. */
void
! 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;
*************** lang_leave_overlay (fill, memspec, phdrs
*** 4688,4693 ****
--- 4736,4746 ----
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;
*************** lang_leave_overlay (fill, memspec, phdrs
*** 4699,4704 ****
--- 4752,4759 ----
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;
Index: ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.3
diff -d -c -p -r1.3 ldlang.h
*** ldlang.h 2000/01/05 14:12:23 1.3
--- ldlang.h 2000/02/16 18:22:08
*************** typedef struct lang_output_section_state
*** 136,141 ****
--- 136,142 ----
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;
*************** extern void lang_add_attribute PARAMS ((
*** 409,415 ****
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 *));
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 *));
--- 410,417 ----
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 *,
! 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 *));
*************** extern void lang_enter_overlay_section P
*** 475,481 ****
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 *));
extern struct bfd_elf_version_tree *lang_elf_version_info;
--- 477,484 ----
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 *,
! const char *));
extern struct bfd_elf_version_tree *lang_elf_version_info;
Index: mri.c
===================================================================
RCS file: /cvs/src/src/ld/mri.c,v
retrieving revision 1.1.1.1
diff -d -c -p -r1.1.1.1 mri.c
*** mri.c 1999/05/03 07:29:07 1.1.1.1
--- mri.c 2000/02/16 18:22:09
*************** mri_draw_tree ()
*** 266,272 ****
}
lang_leave_output_section_statement
! (0, "*default*", (struct lang_output_section_phdr_list *) NULL);
p = p->next;
}
--- 266,273 ----
}
lang_leave_output_section_statement
! (0, "*default*", (struct lang_output_section_phdr_list *) NULL,
! "*default*");
p = p->next;
}
Index: emultempl/armelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/armelf.em,v
retrieving revision 1.12
diff -d -c -p -r1.12 armelf.em
*** armelf.em 2000/01/22 23:22:17 1.12
--- armelf.em 2000/02/16 18:22:09
*************** gld${EMULATION_NAME}_place_orphan (file,
*** 942,948 ****
wild_doit (&os->children, s, os, file);
lang_leave_output_section_statement
! ((bfd_vma) 0, "*default*", (struct lang_output_section_phdr_list *) NULL);
stat_ptr = &add;
if (*ps == '\0' && config.build_constructors)
--- 942,949 ----
wild_doit (&os->children, s, os, file);
lang_leave_output_section_statement
! ((bfd_vma) 0, "*default*", (struct lang_output_section_phdr_list *) NULL,
! "*default*");
stat_ptr = &add;
if (*ps == '\0' && config.build_constructors)
Index: emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.10
diff -d -c -p -r1.10 elf32.em
*** elf32.em 1999/11/04 06:45:07 1.10
--- elf32.em 2000/02/16 18:22:09
*************** gld${EMULATION_NAME}_place_orphan (file,
*** 1024,1030 ****
wild_doit (&os->children, s, os, file);
lang_leave_output_section_statement
! ((bfd_vma) 0, "*default*", (struct lang_output_section_phdr_list *) NULL);
stat_ptr = &add;
if (*ps == '\0' && config.build_constructors)
--- 1024,1031 ----
wild_doit (&os->children, s, os, file);
lang_leave_output_section_statement
! ((bfd_vma) 0, "*default*", (struct lang_output_section_phdr_list *) NULL,
! "*default*");
stat_ptr = &add;
if (*ps == '\0' && config.build_constructors)
Index: emultempl/pe.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/pe.em,v
retrieving revision 1.17
diff -d -c -p -r1.17 pe.em
*** pe.em 2000/01/04 23:48:31 1.17
--- pe.em 2000/02/16 18:22:09
*************** gld_${EMULATION_NAME}_place_orphan (file
*** 1146,1152 ****
lang_leave_output_section_statement
((bfd_vma) 0, "*default*",
! (struct lang_output_section_phdr_list *) NULL);
/* Now stick the new statement list right after PLACE. */
if (place != NULL)
--- 1146,1153 ----
lang_leave_output_section_statement
((bfd_vma) 0, "*default*",
! (struct lang_output_section_phdr_list *) NULL,
! "*default*");
/* Now stick the new statement list right after PLACE. */
if (place != NULL)