aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog9
-rw-r--r--ld/NEWS3
-rw-r--r--ld/ld.texinfo18
-rw-r--r--ld/ldexp.c54
-rw-r--r--ld/ldgram.y102
-rw-r--r--ld/ldlex.l96
-rw-r--r--ld/testsuite/ChangeLog8
-rw-r--r--ld/testsuite/ld-scripts/memory.t39
-rw-r--r--ld/testsuite/ld-scripts/script.exp110
9 files changed, 287 insertions, 152 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 68292f5..85ed0cf 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,12 @@
+2004-11-19 Jon Beniston <jon@beniston.com>
+
+ * ld/ldlex.l: Allow ORIGIN and LENGTH in EXPRESSION.
+ * ld/ldgram.y: Add ORIGIN and LENGTH expressions.
+ * ld/ldexp.c (fold_name): Implement LENGTH() and ORIGIN() functions
+ which return the length and origin of a memory.
+ * ld/ld.texinfo: Document LENGTH() and ORIGIN() functions.
+ * NEWS: Mention support for ORIGIN and LENGTH operators.
+
2004-11-17 Daniel Jacobowitz <dan@codesourcery.com>
* emultempl/armelf.em (arm_elf_set_bfd_for_interworking): Don't use
diff --git a/ld/NEWS b/ld/NEWS
index 8196f44..42a0e09 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
-*- text -*-
+* New linker script functions: ORIGIN() and LENGTH() which return information
+ about a specified memory region.
+
* Port to MAXQ processor contributed by HCL Tech.
* Added SEGMENT_START to the linker script language to permit the user to
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index e2a971b..ab78ece 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -3886,6 +3886,16 @@ the next available address within the memory region. If the combined
output sections directed to a memory region are too large for the
region, the linker will issue an error message.
+It is possible to access the origin and length of a memory in an
+expression via the @code{ORIGIN(@var{memory})} and
+@code{LENGTH(@var{memory})} functions:
+
+@smallexample
+@group
+ _fstack = ORIGIN(ram) + LENGTH(ram) - 4;
+@end group
+@end smallexample
+
@node PHDRS
@section PHDRS Command
@kindex PHDRS
@@ -4661,6 +4671,10 @@ SECTIONS @{ @dots{}
@end group
@end smallexample
+@item LENGTH(@var{memory})
+@kindex LENGTH(@var{memory})
+Return the length of the memory region named @var{memory}.
+
@item LOADADDR(@var{section})
@kindex LOADADDR(@var{section})
@cindex section load address in expression
@@ -4685,6 +4699,10 @@ This function is closely related to @code{ALIGN(@var{exp})}; unless you
use the @code{MEMORY} command to define discontinuous memory for the
output file, the two functions are equivalent.
+@item ORIGIN(@var{memory})
+@kindex ORIGIN(@var{memory})
+Return the origin of the memory region named @var{memory}.
+
@item SEGMENT_START(@var{segment}, @var{default})
@kindex SEGMENT_START(@var{segment}, @var{default})
Return the base address of the named @var{segment}. If an explicit
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 103b615..ebf988e 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -4,22 +4,22 @@
Free Software Foundation, Inc.
Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
-This file is part of GLD, the Gnu Linker.
+ This file is part of GLD, the Gnu Linker.
-GLD is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+ GLD is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-GLD is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GLD is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-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, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+ 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, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/* This module is in charge of working out the contents of expressions.
@@ -105,6 +105,8 @@ exp_print_token (token_code_type code, int infix_p)
{ DATA_SEGMENT_ALIGN, "DATA_SEGMENT_ALIGN" },
{ DATA_SEGMENT_RELRO_END, "DATA_SEGMENT_RELRO_END" },
{ DATA_SEGMENT_END, "DATA_SEGMENT_END" },
+ { ORIGIN, "ORIGIN" },
+ { LENGTH, "LENGTH" },
{ SEGMENT_START, "SEGMENT_START" }
};
unsigned int idx;
@@ -645,6 +647,32 @@ fold_name (etree_type *tree,
}
break;
+ case LENGTH:
+ {
+ lang_memory_region_type *mem;
+
+ mem = lang_memory_region_lookup (tree->name.name, FALSE);
+ if (mem != NULL)
+ result = new_abs (mem->length);
+ else
+ einfo (_("%F%S: undefined MEMORY region `%s' referenced in expression\n"),
+ tree->name.name);
+ }
+ break;
+
+ case ORIGIN:
+ {
+ lang_memory_region_type *mem;
+
+ mem = lang_memory_region_lookup (tree->name.name, FALSE);
+ if (mem != NULL)
+ result = new_abs (mem->origin);
+ else
+ einfo (_("%F%S: undefined MEMORY region `%s' referenced in expression\n"),
+ tree->name.name);
+ }
+ break;
+
default:
FAIL ();
break;
diff --git a/ld/ldgram.y b/ld/ldgram.y
index 13e4ca6..49f274d 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -1,23 +1,23 @@
/* A YACC grammar to parse a superset of the AT&T linker scripting language.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
-This file is part of GNU ld.
+ This file is part of GNU ld.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
%{
/*
@@ -762,88 +762,88 @@ nocrossref_list:
}
;
-mustbe_exp: { ldlex_expression(); }
+mustbe_exp: { ldlex_expression (); }
exp
- { ldlex_popstate(); $$=$2;}
+ { ldlex_popstate (); $$=$2;}
;
exp :
'-' exp %prec UNARY
- { $$ = exp_unop('-', $2); }
+ { $$ = exp_unop ('-', $2); }
| '(' exp ')'
{ $$ = $2; }
| NEXT '(' exp ')' %prec UNARY
- { $$ = exp_unop((int) $1,$3); }
+ { $$ = exp_unop ((int) $1,$3); }
| '!' exp %prec UNARY
- { $$ = exp_unop('!', $2); }
+ { $$ = exp_unop ('!', $2); }
| '+' exp %prec UNARY
{ $$ = $2; }
| '~' exp %prec UNARY
- { $$ = exp_unop('~', $2);}
+ { $$ = exp_unop ('~', $2);}
| exp '*' exp
- { $$ = exp_binop('*', $1, $3); }
+ { $$ = exp_binop ('*', $1, $3); }
| exp '/' exp
- { $$ = exp_binop('/', $1, $3); }
+ { $$ = exp_binop ('/', $1, $3); }
| exp '%' exp
- { $$ = exp_binop('%', $1, $3); }
+ { $$ = exp_binop ('%', $1, $3); }
| exp '+' exp
- { $$ = exp_binop('+', $1, $3); }
+ { $$ = exp_binop ('+', $1, $3); }
| exp '-' exp
- { $$ = exp_binop('-' , $1, $3); }
+ { $$ = exp_binop ('-' , $1, $3); }
| exp LSHIFT exp
- { $$ = exp_binop(LSHIFT , $1, $3); }
+ { $$ = exp_binop (LSHIFT , $1, $3); }
| exp RSHIFT exp
- { $$ = exp_binop(RSHIFT , $1, $3); }
+ { $$ = exp_binop (RSHIFT , $1, $3); }
| exp EQ exp
- { $$ = exp_binop(EQ , $1, $3); }
+ { $$ = exp_binop (EQ , $1, $3); }
| exp NE exp
- { $$ = exp_binop(NE , $1, $3); }
+ { $$ = exp_binop (NE , $1, $3); }
| exp LE exp
- { $$ = exp_binop(LE , $1, $3); }
+ { $$ = exp_binop (LE , $1, $3); }
| exp GE exp
- { $$ = exp_binop(GE , $1, $3); }
+ { $$ = exp_binop (GE , $1, $3); }
| exp '<' exp
- { $$ = exp_binop('<' , $1, $3); }
+ { $$ = exp_binop ('<' , $1, $3); }
| exp '>' exp
- { $$ = exp_binop('>' , $1, $3); }
+ { $$ = exp_binop ('>' , $1, $3); }
| exp '&' exp
- { $$ = exp_binop('&' , $1, $3); }
+ { $$ = exp_binop ('&' , $1, $3); }
| exp '^' exp
- { $$ = exp_binop('^' , $1, $3); }
+ { $$ = exp_binop ('^' , $1, $3); }
| exp '|' exp
- { $$ = exp_binop('|' , $1, $3); }
+ { $$ = exp_binop ('|' , $1, $3); }
| exp '?' exp ':' exp
- { $$ = exp_trinop('?' , $1, $3, $5); }
+ { $$ = exp_trinop ('?' , $1, $3, $5); }
| exp ANDAND exp
- { $$ = exp_binop(ANDAND , $1, $3); }
+ { $$ = exp_binop (ANDAND , $1, $3); }
| exp OROR exp
- { $$ = exp_binop(OROR , $1, $3); }
+ { $$ = exp_binop (OROR , $1, $3); }
| DEFINED '(' NAME ')'
- { $$ = exp_nameop(DEFINED, $3); }
+ { $$ = exp_nameop (DEFINED, $3); }
| INT
{ $$ = exp_bigintop ($1.integer, $1.str); }
| SIZEOF_HEADERS
- { $$ = exp_nameop(SIZEOF_HEADERS,0); }
+ { $$ = exp_nameop (SIZEOF_HEADERS,0); }
| SIZEOF '(' NAME ')'
- { $$ = exp_nameop(SIZEOF,$3); }
+ { $$ = exp_nameop (SIZEOF,$3); }
| ADDR '(' NAME ')'
- { $$ = exp_nameop(ADDR,$3); }
+ { $$ = exp_nameop (ADDR,$3); }
| LOADADDR '(' NAME ')'
- { $$ = exp_nameop(LOADADDR,$3); }
+ { $$ = exp_nameop (LOADADDR,$3); }
| ABSOLUTE '(' exp ')'
- { $$ = exp_unop(ABSOLUTE, $3); }
+ { $$ = exp_unop (ABSOLUTE, $3); }
| ALIGN_K '(' exp ')'
- { $$ = exp_unop(ALIGN_K,$3); }
+ { $$ = exp_unop (ALIGN_K,$3); }
| ALIGN_K '(' exp ',' exp ')'
- { $$ = exp_binop(ALIGN_K,$3,$5); }
+ { $$ = exp_binop (ALIGN_K,$3,$5); }
| DATA_SEGMENT_ALIGN '(' exp ',' exp ')'
{ $$ = exp_binop (DATA_SEGMENT_ALIGN, $3, $5); }
| DATA_SEGMENT_RELRO_END '(' exp ',' exp ')'
{ $$ = exp_binop (DATA_SEGMENT_RELRO_END, $5, $3); }
| DATA_SEGMENT_END '(' exp ')'
- { $$ = exp_unop(DATA_SEGMENT_END, $3); }
+ { $$ = exp_unop (DATA_SEGMENT_END, $3); }
| SEGMENT_START '(' NAME ',' exp ')'
{ /* The operands to the expression node are
placed in the opposite order from the way
@@ -854,15 +854,19 @@ exp :
$5,
exp_nameop (NAME, $3)); }
| BLOCK '(' exp ')'
- { $$ = exp_unop(ALIGN_K,$3); }
+ { $$ = exp_unop (ALIGN_K,$3); }
| NAME
- { $$ = exp_nameop(NAME,$1); }
+ { $$ = exp_nameop (NAME,$1); }
| MAX_K '(' exp ',' exp ')'
{ $$ = exp_binop (MAX_K, $3, $5 ); }
| MIN_K '(' exp ',' exp ')'
{ $$ = exp_binop (MIN_K, $3, $5 ); }
| ASSERT_K '(' exp ',' NAME ')'
{ $$ = exp_assert ($3, $5); }
+ | ORIGIN '(' NAME ')'
+ { $$ = exp_nameop (ORIGIN, $3); }
+ | LENGTH '(' NAME ')'
+ { $$ = exp_nameop (LENGTH, $3); }
;
diff --git a/ld/ldlex.l b/ld/ldlex.l
index 0ace6ec..d49c085 100644
--- a/ld/ldlex.l
+++ b/ld/ldlex.l
@@ -1,24 +1,24 @@
%{
/* Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
-This file is part of GLD, the Gnu Linker.
+ This file is part of GLD, the Gnu Linker.
-GLD is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+ GLD is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-GLD is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GLD is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-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, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+ 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, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/*
This was written by steve chamberlain
@@ -234,60 +234,60 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
<BOTH,SCRIPT,EXPRESSION,MRI>"/" { RTOKEN('/');}
<BOTH,SCRIPT,EXPRESSION,MRI>"%" { RTOKEN('%');}
<BOTH,SCRIPT,EXPRESSION,MRI>"<" { RTOKEN('<');}
-<BOTH,SCRIPT,EXPRESSION,MRI>"=" { RTOKEN('=');}
-<BOTH,SCRIPT,EXPRESSION,MRI>"}" { RTOKEN('}') ; }
-<BOTH,SCRIPT,EXPRESSION,MRI>"{" { RTOKEN('{'); }
-<BOTH,SCRIPT,EXPRESSION,MRI>")" { RTOKEN(')');}
-<BOTH,SCRIPT,EXPRESSION,MRI>"(" { RTOKEN('(');}
+<BOTH,SCRIPT,EXPRESSION,MRI>"=" { RTOKEN('=');}
+<BOTH,SCRIPT,EXPRESSION,MRI>"}" { RTOKEN('}') ; }
+<BOTH,SCRIPT,EXPRESSION,MRI>"{" { RTOKEN('{'); }
+<BOTH,SCRIPT,EXPRESSION,MRI>")" { RTOKEN(')');}
+<BOTH,SCRIPT,EXPRESSION,MRI>"(" { RTOKEN('(');}
<BOTH,SCRIPT,EXPRESSION,MRI>":" { RTOKEN(':'); }
<BOTH,SCRIPT,EXPRESSION,MRI>";" { RTOKEN(';');}
-<BOTH,SCRIPT>"MEMORY" { RTOKEN(MEMORY);}
-<BOTH,SCRIPT>"ORIGIN" { RTOKEN(ORIGIN);}
-<BOTH,SCRIPT>"VERSION" { RTOKEN(VERSIONK);}
+<BOTH,SCRIPT>"MEMORY" { RTOKEN(MEMORY);}
+<BOTH,SCRIPT,EXPRESSION>"ORIGIN" { RTOKEN(ORIGIN);}
+<BOTH,SCRIPT>"VERSION" { RTOKEN(VERSIONK);}
<EXPRESSION,BOTH,SCRIPT>"BLOCK" { RTOKEN(BLOCK);}
<EXPRESSION,BOTH,SCRIPT>"BIND" { RTOKEN(BIND);}
-<BOTH,SCRIPT>"LENGTH" { RTOKEN(LENGTH);}
-<EXPRESSION,BOTH,SCRIPT>"ALIGN" { RTOKEN(ALIGN_K);}
+<BOTH,SCRIPT,EXPRESSION>"LENGTH" { RTOKEN(LENGTH);}
+<EXPRESSION,BOTH,SCRIPT>"ALIGN" { RTOKEN(ALIGN_K);}
<EXPRESSION,BOTH,SCRIPT>"DATA_SEGMENT_ALIGN" { RTOKEN(DATA_SEGMENT_ALIGN);}
<EXPRESSION,BOTH,SCRIPT>"DATA_SEGMENT_RELRO_END" { RTOKEN(DATA_SEGMENT_RELRO_END);}
<EXPRESSION,BOTH,SCRIPT>"DATA_SEGMENT_END" { RTOKEN(DATA_SEGMENT_END);}
-<EXPRESSION,BOTH,SCRIPT>"ADDR" { RTOKEN(ADDR);}
-<EXPRESSION,BOTH,SCRIPT>"LOADADDR" { RTOKEN(LOADADDR);}
+<EXPRESSION,BOTH,SCRIPT>"ADDR" { RTOKEN(ADDR);}
+<EXPRESSION,BOTH,SCRIPT>"LOADADDR" { RTOKEN(LOADADDR);}
<EXPRESSION,BOTH>"MAX" { RTOKEN(MAX_K); }
<EXPRESSION,BOTH>"MIN" { RTOKEN(MIN_K); }
<EXPRESSION,BOTH>"ASSERT" { RTOKEN(ASSERT_K); }
<BOTH,SCRIPT>"ENTRY" { RTOKEN(ENTRY);}
<BOTH,SCRIPT,MRI>"EXTERN" { RTOKEN(EXTERN);}
-<EXPRESSION,BOTH,SCRIPT>"NEXT" { RTOKEN(NEXT);}
+<EXPRESSION,BOTH,SCRIPT>"NEXT" { RTOKEN(NEXT);}
<EXPRESSION,BOTH,SCRIPT>"sizeof_headers" { RTOKEN(SIZEOF_HEADERS);}
<EXPRESSION,BOTH,SCRIPT>"SIZEOF_HEADERS" { RTOKEN(SIZEOF_HEADERS);}
<EXPRESSION,BOTH,SCRIPT>"SEGMENT_START" { RTOKEN(SEGMENT_START);}
<BOTH,SCRIPT>"MAP" { RTOKEN(MAP);}
-<EXPRESSION,BOTH,SCRIPT>"SIZEOF" { RTOKEN(SIZEOF);}
-<BOTH,SCRIPT>"TARGET" { RTOKEN(TARGET_K);}
+<EXPRESSION,BOTH,SCRIPT>"SIZEOF" { RTOKEN(SIZEOF);}
+<BOTH,SCRIPT>"TARGET" { RTOKEN(TARGET_K);}
<BOTH,SCRIPT>"SEARCH_DIR" { RTOKEN(SEARCH_DIR);}
-<BOTH,SCRIPT>"OUTPUT" { RTOKEN(OUTPUT);}
+<BOTH,SCRIPT>"OUTPUT" { RTOKEN(OUTPUT);}
<BOTH,SCRIPT>"INPUT" { RTOKEN(INPUT);}
<EXPRESSION,BOTH,SCRIPT>"GROUP" { RTOKEN(GROUP);}
-<EXPRESSION,BOTH,SCRIPT>"DEFINED" { RTOKEN(DEFINED);}
+<EXPRESSION,BOTH,SCRIPT>"DEFINED" { RTOKEN(DEFINED);}
<BOTH,SCRIPT>"CREATE_OBJECT_SYMBOLS" { RTOKEN(CREATE_OBJECT_SYMBOLS);}
<BOTH,SCRIPT>"CONSTRUCTORS" { RTOKEN( CONSTRUCTORS);}
-<BOTH,SCRIPT>"FORCE_COMMON_ALLOCATION" { RTOKEN(FORCE_COMMON_ALLOCATION);}
+<BOTH,SCRIPT>"FORCE_COMMON_ALLOCATION" { RTOKEN(FORCE_COMMON_ALLOCATION);}
<BOTH,SCRIPT>"INHIBIT_COMMON_ALLOCATION" { RTOKEN(INHIBIT_COMMON_ALLOCATION);}
-<BOTH,SCRIPT>"SECTIONS" { RTOKEN(SECTIONS);}
+<BOTH,SCRIPT>"SECTIONS" { RTOKEN(SECTIONS);}
<BOTH,SCRIPT>"FILL" { RTOKEN(FILL);}
-<BOTH,SCRIPT>"STARTUP" { RTOKEN(STARTUP);}
+<BOTH,SCRIPT>"STARTUP" { RTOKEN(STARTUP);}
<BOTH,SCRIPT>"OUTPUT_FORMAT" { RTOKEN(OUTPUT_FORMAT);}
<BOTH,SCRIPT>"OUTPUT_ARCH" { RTOKEN( OUTPUT_ARCH);}
<BOTH,SCRIPT>"HLL" { RTOKEN(HLL);}
-<BOTH,SCRIPT>"SYSLIB" { RTOKEN(SYSLIB);}
+<BOTH,SCRIPT>"SYSLIB" { RTOKEN(SYSLIB);}
<BOTH,SCRIPT>"FLOAT" { RTOKEN(FLOAT);}
<BOTH,SCRIPT>"QUAD" { RTOKEN( QUAD);}
<BOTH,SCRIPT>"SQUAD" { RTOKEN( SQUAD);}
<BOTH,SCRIPT>"LONG" { RTOKEN( LONG);}
<BOTH,SCRIPT>"SHORT" { RTOKEN( SHORT);}
<BOTH,SCRIPT>"BYTE" { RTOKEN( BYTE);}
-<BOTH,SCRIPT>"NOFLOAT" { RTOKEN(NOFLOAT);}
+<BOTH,SCRIPT>"NOFLOAT" { RTOKEN(NOFLOAT);}
<EXPRESSION,BOTH,SCRIPT>"NOCROSSREFS" { RTOKEN(NOCROSSREFS);}
<BOTH,SCRIPT>"OVERLAY" { RTOKEN(OVERLAY); }
<BOTH,SCRIPT>"SORT_BY_NAME" { RTOKEN(SORT_BY_NAME); }
@@ -306,22 +306,22 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
<BOTH,SCRIPT>"len" { RTOKEN( LENGTH);}
<BOTH,SCRIPT>"INCLUDE" { RTOKEN(INCLUDE);}
<BOTH,SCRIPT>"PHDRS" { RTOKEN (PHDRS); }
-<EXPRESSION,BOTH,SCRIPT>"AT" { RTOKEN(AT);}
-<EXPRESSION,BOTH,SCRIPT>"SUBALIGN" { RTOKEN(SUBALIGN);}
-<EXPRESSION,BOTH,SCRIPT>"PROVIDE" { RTOKEN(PROVIDE); }
+<EXPRESSION,BOTH,SCRIPT>"AT" { RTOKEN(AT);}
+<EXPRESSION,BOTH,SCRIPT>"SUBALIGN" { RTOKEN(SUBALIGN);}
+<EXPRESSION,BOTH,SCRIPT>"PROVIDE" { RTOKEN(PROVIDE); }
<EXPRESSION,BOTH,SCRIPT>"KEEP" { RTOKEN(KEEP); }
-<EXPRESSION,BOTH,SCRIPT>"EXCLUDE_FILE" { RTOKEN(EXCLUDE_FILE); }
+<EXPRESSION,BOTH,SCRIPT>"EXCLUDE_FILE" { RTOKEN(EXCLUDE_FILE); }
<MRI>"#".*\n? { ++ lineno; }
<MRI>"\n" { ++ lineno; RTOKEN(NEWLINE); }
<MRI>"*".* { /* Mri comment line */ }
<MRI>";".* { /* Mri comment line */ }
<MRI>"END" { RTOKEN(ENDWORD); }
-<MRI>"ALIGNMOD" { RTOKEN(ALIGNMOD);}
-<MRI>"ALIGN" { RTOKEN(ALIGN_K);}
+<MRI>"ALIGNMOD" { RTOKEN(ALIGNMOD);}
+<MRI>"ALIGN" { RTOKEN(ALIGN_K);}
<MRI>"CHIP" { RTOKEN(CHIP); }
<MRI>"BASE" { RTOKEN(BASE); }
-<MRI>"ALIAS" { RTOKEN(ALIAS); }
-<MRI>"TRUNCATE" { RTOKEN(TRUNCATE); }
+<MRI>"ALIAS" { RTOKEN(ALIAS); }
+<MRI>"TRUNCATE" { RTOKEN(TRUNCATE); }
<MRI>"LOAD" { RTOKEN(LOAD); }
<MRI>"PUBLIC" { RTOKEN(PUBLIC); }
<MRI>"ORDER" { RTOKEN(ORDER); }
@@ -333,12 +333,12 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
<MRI>"SECT" { RTOKEN(SECT); }
<EXPRESSION,BOTH,SCRIPT,MRI>"ABSOLUTE" { RTOKEN(ABSOLUTE); }
<MRI>"end" { RTOKEN(ENDWORD); }
-<MRI>"alignmod" { RTOKEN(ALIGNMOD);}
-<MRI>"align" { RTOKEN(ALIGN_K);}
+<MRI>"alignmod" { RTOKEN(ALIGNMOD);}
+<MRI>"align" { RTOKEN(ALIGN_K);}
<MRI>"chip" { RTOKEN(CHIP); }
<MRI>"base" { RTOKEN(BASE); }
-<MRI>"alias" { RTOKEN(ALIAS); }
-<MRI>"truncate" { RTOKEN(TRUNCATE); }
+<MRI>"alias" { RTOKEN(ALIAS); }
+<MRI>"truncate" { RTOKEN(TRUNCATE); }
<MRI>"load" { RTOKEN(LOAD); }
<MRI>"public" { RTOKEN(PUBLIC); }
<MRI>"order" { RTOKEN(ORDER); }
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index ee6081d..c54dd11 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2004-11-19 Nick Clifton <nickc@redhat.com>
+
+ * ld-scripts/script.exp: Add test of memory linker script.
+ Reorganise code to remove unnecessary indentation.
+ Fix target tests to avoid using --image-base with *-nto targets.
+ * ld-scripts/memory.t: New linker script to test the MEMORY
+ section and the ORIGIN and LENGTH operators.
+
2004-11-17 Daniel Jacobowitz <dan@codesourcery.com>
* ld-arm/mixed-app.d, ld-arm/mixed-app.r, ld-arm/mixed-app.s,
diff --git a/ld/testsuite/ld-scripts/memory.t b/ld/testsuite/ld-scripts/memory.t
new file mode 100644
index 0000000..8a73c58
--- /dev/null
+++ b/ld/testsuite/ld-scripts/memory.t
@@ -0,0 +1,39 @@
+MEMORY
+{
+ TEXTMEM (ARX) : ORIGIN = 0x100, LENGTH = 32K
+ DATAMEM (AW) : org = 0x1000, l = (64 * 1024)
+}
+
+SECTIONS
+{
+ . = 0;
+ .text :
+ {
+ /* The value returned by the ORIGIN operator is a constant.
+ However it is being assigned to a symbol declared within
+ a section. Therefore the symbol is section-relative and
+ its value will include the offset of that section from
+ the start of memory. ie the declaration:
+ text_start = ORIGIN (TEXTMEM);
+ here will result in text_start having a value of 0x200.
+ Hence we need to subtract the absolute value of the
+ location counter at this point in order to give text_start
+ a value that is truely absolute, and which coincidentally
+ will allow the tests in script.exp to work. */
+
+ text_start = ORIGIN(TEXTMEM) - ABSOLUTE (.);
+ *(.text)
+ *(.pr)
+ text_end = .;
+ } > TEXTMEM
+
+ data_start = ORIGIN (DATAMEM);
+ .data :
+ {
+ *(.data)
+ *(.rw)
+ data_end = .;
+ } >DATAMEM
+
+ fred = ORIGIN(DATAMEM) + LENGTH(DATAMEM);
+}
diff --git a/ld/testsuite/ld-scripts/script.exp b/ld/testsuite/ld-scripts/script.exp
index 96cf04b..866d128 100644
--- a/ld/testsuite/ld-scripts/script.exp
+++ b/ld/testsuite/ld-scripts/script.exp
@@ -1,6 +1,6 @@
# Test basic linker script functionality
# By Ian Lance Taylor, Cygnus Support
-# Copyright 2001
+# Copyright 2001, 2004
# Free Software Foundation, Inc.
#
# This file is free software; you can redistribute it and/or modify
@@ -31,47 +31,63 @@ proc check_script { } {
if ![ld_nm $nm "" tmpdir/script] {
unresolved $testname
+ return
+ }
+
+ if {![info exists nm_output(text_start)] \
+ || ![info exists nm_output(text_end)] \
+ || ![info exists nm_output(data_start)] \
+ || ![info exists nm_output(data_end)]} {
+ send_log "bad output from nm\n"
+ verbose "bad output from nm"
+ fail $testname
+ return
+ }
+
+ set passes 1
+ set text_end 0x104
+ set data_end 0x1004
+
+ if [istarget *c4x*-*-*] then {
+ set text_end 0x101
+ set data_end 0x1001
+ }
+
+ if [istarget *c54x*-*-*] then {
+ set text_end 0x102
+ set data_end 0x1002
+ }
+
+ if {$nm_output(text_start) != 0x100} {
+ send_log "text_start == $nm_output(text_start)\n"
+ verbose "text_start == $nm_output(text_start)"
+ set passes 0
+ }
+
+ if {$nm_output(text_end) < $text_end \
+ || $nm_output(text_end) > 0x110} {
+ send_log "text_end == $nm_output(text_end)\n"
+ verbose "text_end == $nm_output(text_end)"
+ set passes 0
+ }
+
+ if {$nm_output(data_start) != 0x1000} {
+ send_log "data_start == $nm_output(data_start)\n"
+ verbose "data_start == $nm_output(data_start)"
+ set passes 0
+ }
+
+ if {$nm_output(data_end) < $data_end \
+ || $nm_output(data_end) > 0x1010} {
+ send_log "data_end == $nm_output(data_end)\n"
+ verbose "data_end == $nm_output(data_end)"
+ set passes 0
+ }
+
+ if { $passes } {
+ pass $testname
} else {
- if {![info exists nm_output(text_start)] \
- || ![info exists nm_output(text_end)] \
- || ![info exists nm_output(data_start)] \
- || ![info exists nm_output(data_end)]} {
- send_log "bad output from nm\n"
- verbose "bad output from nm"
- fail $testname
- } else {
- set text_end 0x104
- set data_end 0x1004
- if [istarget *c4x*-*-*] then {
- set text_end 0x101
- set data_end 0x1001
- }
- if [istarget *c54x*-*-*] then {
- set text_end 0x102
- set data_end 0x1002
- }
- if {$nm_output(text_start) != 0x100} {
- send_log "text_start == $nm_output(text_start)\n"
- verbose "text_start == $nm_output(text_start)"
- fail $testname
- } else { if {$nm_output(text_end) < $text_end \
- || $nm_output(text_end) > 0x110} {
- send_log "text_end == $nm_output(text_end)\n"
- verbose "text_end == $nm_output(text_end)"
- fail $testname
- } else { if {$nm_output(data_start) != 0x1000} {
- send_log "data_start == $nm_output(data_start)\n"
- verbose "data_start == $nm_output(data_start)"
- fail $testname
- } else { if {$nm_output(data_end) < $data_end \
- || $nm_output(data_end) > 0x1010} {
- send_log "data_end == $nm_output(data_end)\n"
- verbose "data_end == $nm_output(data_end)"
- fail $testname
- } else {
- pass $testname
- } } } }
- }
+ fail $testname
}
}
@@ -81,7 +97,7 @@ if {[istarget "*-*-pe*"] \
|| [istarget "*-*-cygwin*"] \
|| [istarget "*-*-mingw32*"] \
|| [istarget "*-*-winnt*"] \
- || [istarget "*-*-nt*"] \
+ || [istarget "*-*-nt"] \
|| [istarget "*-*-interix*"] } then {
set flags "--image-base 0"
}
@@ -99,3 +115,13 @@ if ![ld_simple_link $ld tmpdir/script "$flags -c $srcdir/$subdir/scriptm.t"] {
} else {
check_script
}
+
+set testname "MEMORY"
+
+if ![ld_simple_link $ld tmpdir/script "$flags -T $srcdir/$subdir/memory.t tmpdir/script.o"] {
+ fail $testname
+} else {
+ check_script
+}
+
+