aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog10
-rw-r--r--ld/NEWS2
-rw-r--r--ld/ld.texinfo8
-rw-r--r--ld/ldexp.c350
-rw-r--r--ld/ldgram.y4
-rw-r--r--ld/ldlang.c1
-rw-r--r--ld/ldlex.l1
7 files changed, 212 insertions, 164 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 706579f..d14446b 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,13 @@
+Fri Aug 2 14:57:49 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * ldgram.y (LOADADDR): New terminal.
+ (exp): Handle LOADADDR.
+ * ldlex.l: Recognize LOADADDR.
+ * ldexp.c (exp_print_token): Add LOADADDR.
+ (fold_name): Implement LOADADDR.
+ * ldlang.c (exp_init_os): Treat LOADADDR like ADDR.
+ * ld.texinfo (Arithmetic Functions): Document LOADADDR.
+
Thu Aug 1 12:52:19 1996 Ian Lance Taylor <ian@cygnus.com>
* ld.h (check_nocrossrefs): Declare.
diff --git a/ld/NEWS b/ld/NEWS
index ea11db2..b82f9cc 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -7,6 +7,8 @@ Changes since version 2.7:
* The NOCROSSREFS command was added to the linker script language.
+* The LOADADDR expression was added to the linker script language.
+
Changes since version 2.6:
* New option --cref to print out a cross reference table.
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 99450f6..d279d31 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -1582,6 +1582,14 @@ SECTIONS@{ @dots{}
@end group
@end smallexample
+@kindex LOADADDR(@var{section})
+@cindex section load address
+@item LOADADDR(@var{section})
+Return the absolute load address of the named @var{section}. This is
+normally the same as @code{ADDR}, but it may be different if the
+@code{AT} keyword is used in the section definition (@pxref{Section
+Options}).
+
@kindex ALIGN(@var{exp})
@cindex rounding up location counter
@item ALIGN(@var{exp})
diff --git a/ld/ldexp.c b/ld/ldexp.c
index ae457e5..0581517 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -1,5 +1,5 @@
/* This module handles expression trees.
-Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
Written by Steve Chamberlain of Cygnus Support (sac@cygnus.com).
This file is part of GLD, the Gnu Linker.
@@ -99,6 +99,7 @@ exp_print_token (code)
{ NEXT,"NEXT" },
{ SIZEOF,"SIZEOF" },
{ ADDR,"ADDR" },
+ { LOADADDR,"LOADADDR" },
{ MEMORY,"MEMORY" },
{ DEFINED,"DEFINED" },
{ TARGET_K,"TARGET" },
@@ -146,15 +147,13 @@ new_abs (value)
static void
check (os, name, op)
lang_output_section_statement_type *os;
- CONST char *name;
- CONST char *op;
+ const char *name;
+ const char *op;
{
- if (os == (lang_output_section_statement_type *)NULL) {
- einfo("%F%P: %s uses undefined section %s\n", op, name);
- }
- if (os->processed == false) {
- einfo("%F%P: %s forward reference of section %s\n",op, name);
- }
+ if (os == NULL)
+ einfo ("%F%P: %s uses undefined section %s\n", op, name);
+ if (! os->processed)
+ einfo ("%F%P: %s forward reference of section %s\n", op, name);
}
etree_type *
@@ -401,27 +400,47 @@ fold_name (tree, current_section, allocation_done, dot)
break;
case ADDR:
+ if (allocation_done != lang_first_phase_enum)
+ {
+ lang_output_section_statement_type *os;
- if (allocation_done != lang_first_phase_enum) {
- lang_output_section_statement_type *os =
- lang_output_section_find(tree->name.name);
- check(os,tree->name.name,"ADDR");
- result = new_rel((bfd_vma)0, os);
- }
- else {
- result = invalid();
- }
+ os = lang_output_section_find (tree->name.name);
+ check (os, tree->name.name, "ADDR");
+ result = new_rel (0, os);
+ }
+ else
+ result = invalid ();
break;
+
+ case LOADADDR:
+ if (allocation_done != lang_first_phase_enum)
+ {
+ lang_output_section_statement_type *os;
+
+ os = lang_output_section_find (tree->name.name);
+ check (os, tree->name.name, "LOADADDR");
+ if (os->load_base == NULL)
+ result = new_rel (0, os);
+ else
+ result = exp_fold_tree_no_dot (os->load_base,
+ abs_output_section,
+ allocation_done);
+ }
+ else
+ result = invalid ();
+ break;
+
case SIZEOF:
- if(allocation_done != lang_first_phase_enum) {
- lang_output_section_statement_type *os =
- lang_output_section_find(tree->name.name);
- check(os,tree->name.name,"SIZEOF");
- result = new_abs((bfd_vma)(os->bfd_section->_raw_size));
- }
- else {
- result = invalid();
- }
+ if (allocation_done != lang_first_phase_enum)
+ {
+ lang_output_section_statement_type *os;
+
+ os = lang_output_section_find (tree->name.name);
+ check (os, tree->name.name, "SIZEOF");
+ result = new_abs (os->bfd_section->_raw_size);
+ }
+ else
+ result = invalid ();
break;
default:
@@ -441,15 +460,18 @@ exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
{
etree_value_type result;
- if (tree == (etree_type *)NULL) {
- result.valid = false;
- }
- else {
- switch (tree->type.node_class)
+ if (tree == NULL)
+ {
+ result.valid = false;
+ return result;
+ }
+
+ switch (tree->type.node_class)
{
- case etree_value:
- result = new_rel(tree->value.value, current_section);
+ case etree_value:
+ result = new_rel (tree->value.value, current_section);
break;
+
case etree_rel:
if (allocation_done != lang_final_phase_enum)
result.valid = false;
@@ -459,114 +481,121 @@ exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
+ tree->rel.section->output_offset),
current_section);
break;
- case etree_unary:
- result = exp_fold_tree(tree->unary.child,
- current_section,
- allocation_done, dot, dotp);
- if (result.valid == true)
- {
- switch(tree->type.node_code)
- {
- case ALIGN_K:
- if (allocation_done != lang_first_phase_enum) {
- result = new_rel_from_section(ALIGN_N(dot,
- result.value) ,
- current_section);
- }
- else {
- result.valid = false;
- }
- break;
- case ABSOLUTE:
- if (allocation_done != lang_first_phase_enum && result.valid)
- {
- result.value += result.section->bfd_section->vma;
- result.section = abs_output_section;
- }
- else
+ case etree_unary:
+ result = exp_fold_tree (tree->unary.child,
+ current_section,
+ allocation_done, dot, dotp);
+ if (result.valid)
+ {
+ switch (tree->type.node_code)
{
- result.valid = false;
+ case ALIGN_K:
+ if (allocation_done != lang_first_phase_enum)
+ result = new_rel_from_section (ALIGN_N (dot, result.value),
+ current_section);
+ else
+ result.valid = false;
+ break;
+
+ case ABSOLUTE:
+ if (allocation_done != lang_first_phase_enum && result.valid)
+ {
+ result.value += result.section->bfd_section->vma;
+ result.section = abs_output_section;
+ }
+ else
+ result.valid = false;
+ break;
+
+ case '~':
+ make_abs (&result);
+ result.value = ~result.value;
+ break;
+
+ case '!':
+ make_abs (&result);
+ result.value = !result.value;
+ break;
+
+ case '-':
+ make_abs (&result);
+ result.value = -result.value;
+ break;
+
+ case NEXT:
+ /* Return next place aligned to value. */
+ if (allocation_done == lang_allocating_phase_enum)
+ {
+ make_abs (&result);
+ result.value = ALIGN_N (dot, result.value);
+ }
+ else
+ result.valid = false;
+ break;
+
+ default:
+ FAIL ();
+ break;
}
- break;
- case '~':
- make_abs(&result);
- result.value = ~result.value;
- break;
- case '!':
- make_abs(&result);
- result.value = !result.value;
- break;
- case '-':
- make_abs(&result);
- result.value = -result.value;
- break;
- case NEXT:
- if (allocation_done ==lang_allocating_phase_enum) {
- make_abs(&result);
- result.value = ALIGN_N(dot, result.value);
- }
- else {
- /* Return next place aligned to value */
- result.valid = false;
- }
- break;
- default:
- FAIL();
}
- }
-
break;
- case etree_trinary:
-
- result = exp_fold_tree(tree->trinary.cond,
- current_section,
- allocation_done, dot, dotp);
- if (result.valid) {
- result = exp_fold_tree(result.value ?
- tree->trinary.lhs:tree->trinary.rhs,
- current_section,
- allocation_done, dot, dotp);
- }
+ case etree_trinary:
+ result = exp_fold_tree (tree->trinary.cond, current_section,
+ allocation_done, dot, dotp);
+ if (result.valid)
+ result = exp_fold_tree ((result.value
+ ? tree->trinary.lhs
+ : tree->trinary.rhs),
+ current_section,
+ allocation_done, dot, dotp);
break;
- case etree_binary:
- result = fold_binary(tree, current_section, allocation_done,
- dot, dotp);
+
+ case etree_binary:
+ result = fold_binary (tree, current_section, allocation_done,
+ dot, dotp);
break;
- case etree_assign:
- case etree_provide:
- if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0) {
- /* Assignment to dot can only be done during allocation */
- if (tree->type.node_class == etree_provide)
- einfo ("%F%S can not PROVIDE assignment to location counter\n");
- if (allocation_done == lang_allocating_phase_enum
- || (allocation_done == lang_final_phase_enum
- && current_section == abs_output_section)) {
- result = exp_fold_tree(tree->assign.src,
- current_section,
- lang_allocating_phase_enum, dot, dotp);
- if (result.valid == false) {
- einfo("%F%S invalid assignment to location counter\n");
- }
- else {
- if (current_section ==
- (lang_output_section_statement_type *)NULL) {
- einfo("%F%S assignment to location counter invalid outside of SECTION\n");
- }
- else {
- bfd_vma nextdot =result.value +
- current_section->bfd_section->vma;
- if (nextdot < dot && current_section != abs_output_section) {
- einfo("%F%S cannot move location counter backwards (from %V to %V)\n", dot, nextdot);
- }
- else {
- *dotp = nextdot;
- }
+
+ case etree_assign:
+ case etree_provide:
+ if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0)
+ {
+ /* Assignment to dot can only be done during allocation */
+ if (tree->type.node_class == etree_provide)
+ einfo ("%F%S can not PROVIDE assignment to location counter\n");
+ if (allocation_done == lang_allocating_phase_enum
+ || (allocation_done == lang_final_phase_enum
+ && current_section == abs_output_section))
+ {
+ result = exp_fold_tree (tree->assign.src,
+ current_section,
+ lang_allocating_phase_enum, dot,
+ dotp);
+ if (! result.valid)
+ einfo ("%F%S invalid assignment to location counter\n");
+ else
+ {
+ if (current_section == NULL)
+ einfo ("%F%S assignment to location counter invalid outside of SECTION\n");
+ else
+ {
+ bfd_vma nextdot;
+
+ nextdot = (result.value
+ + current_section->bfd_section->vma);
+ if (nextdot < dot
+ && current_section != abs_output_section)
+ {
+ einfo ("%F%S cannot move location counter backwards (from %V to %V)\n",
+ dot, nextdot);
+ }
+ else
+ *dotp = nextdot;
+ }
+ }
}
- }
}
- }
else
{
result = exp_fold_tree (tree->assign.src,
@@ -574,12 +603,15 @@ exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
dot, dotp);
if (result.valid)
{
+ boolean create;
struct bfd_link_hash_entry *h;
+ if (tree->type.node_class == etree_assign)
+ create = true;
+ else
+ create = false;
h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
- (tree->type.node_class == etree_assign
- ? true : false),
- false, false);
+ create, false, false);
if (h == (struct bfd_link_hash_entry *) NULL)
{
if (tree->type.node_class == etree_assign)
@@ -591,7 +623,7 @@ exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
&& h->type != bfd_link_hash_common)
{
/* Do nothing. The symbol was defined by some
- object. */
+ object. */
}
else
{
@@ -602,21 +634,21 @@ exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
h->u.def.section = result.section->bfd_section;
}
}
- }
+ }
break;
- case etree_name:
- result = fold_name(tree, current_section, allocation_done, dot);
+
+ case etree_name:
+ result = fold_name (tree, current_section, allocation_done, dot);
break;
- default:
- einfo("%F%S need more of these %d\n",tree->type.node_class );
+ default:
+ FAIL ();
+ break;
}
- }
return result;
}
-
static etree_value_type
exp_fold_tree_no_dot (tree, current_section, allocation_done)
etree_type *tree;
@@ -774,14 +806,12 @@ exp_print_tree (tree)
{
switch (tree->type.node_class) {
case etree_value:
- print_address(tree->value.value);
+ minfo ("0x%v", tree->value.value);
return;
case etree_rel:
if (tree->rel.section->owner != NULL)
- fprintf (config.map_file, "%s:",
- bfd_get_filename (tree->rel.section->owner));
- fprintf (config.map_file, "%s+", tree->rel.section->name);
- print_address (tree->rel.value);
+ minfo ("%B:", tree->rel.section->owner);
+ minfo ("%s+0x%v", tree->rel.section->name, tree->rel.value);
return;
case etree_assign:
#if 0
@@ -793,7 +823,7 @@ exp_print_tree (tree)
fprintf(config.map_file,"%s (UNDEFINED)",tree->assign.dst->name);
}
#endif
- fprintf(config.map_file,"%s ",tree->assign.dst);
+ fprintf(config.map_file,"%s",tree->assign.dst);
exp_print_token(tree->type.node_code);
exp_print_tree(tree->assign.src);
break;
@@ -846,30 +876,24 @@ exp_print_tree (tree)
}
}
-
-
-
bfd_vma
exp_get_vma (tree, def, name, allocation_done)
etree_type *tree;
- bfd_vma def;
+ bfd_vma def;
char *name;
lang_phase_type allocation_done;
{
etree_value_type r;
- if (tree != (etree_type *)NULL) {
- r = exp_fold_tree_no_dot(tree,
- abs_output_section,
- allocation_done);
- if (r.valid == false && name) {
- einfo("%F%S nonconstant expression for %s\n",name);
+ if (tree != NULL)
+ {
+ r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+ if (! r.valid && name != NULL)
+ einfo ("%F%S nonconstant expression for %s\n", name);
+ return r.value;
}
- return r.value;
- }
- else {
+ else
return def;
- }
}
int
diff --git a/ld/ldgram.y b/ld/ldgram.y
index 1f16baa..d9a6bff 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -113,7 +113,7 @@ static int error_index;
%token MEMORY DEFSYMEND
%token NOLOAD DSECT COPY INFO OVERLAY
%token NAME LNAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY
-%token <integer> SIZEOF NEXT ADDR
+%token <integer> SIZEOF NEXT ADDR LOADADDR
%token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS
%token ORIGIN FILL
%token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
@@ -668,6 +668,8 @@ exp :
{ $$ = exp_nameop(SIZEOF,$3); }
| ADDR '(' NAME ')'
{ $$ = exp_nameop(ADDR,$3); }
+ | LOADADDR '(' NAME ')'
+ { $$ = exp_nameop(LOADADDR,$3); }
| ABSOLUTE '(' exp ')'
{ $$ = exp_unop(ABSOLUTE, $3); }
| ALIGN_K '(' exp ')'
diff --git a/ld/ldlang.c b/ld/ldlang.c
index b7a0493..60f191f 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -618,6 +618,7 @@ exp_init_os (exp)
switch (exp->type.node_code)
{
case ADDR:
+ case LOADADDR:
case SIZEOF:
{
lang_output_section_statement_type *os;
diff --git a/ld/ldlex.l b/ld/ldlex.l
index 796ff9d..681988d 100644
--- a/ld/ldlex.l
+++ b/ld/ldlex.l
@@ -228,6 +228,7 @@ NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~]
<BOTH,SCRIPT>"LENGTH" { RTOKEN(LENGTH);}
<EXPRESSION,BOTH,SCRIPT>"ALIGN" { RTOKEN(ALIGN_K);}
<EXPRESSION,BOTH,SCRIPT>"ADDR" { RTOKEN(ADDR);}
+<EXPRESSION,BOTH,SCRIPT>"LOADADDR" { RTOKEN(LOADADDR);}
<BOTH,SCRIPT>"ENTRY" { RTOKEN(ENTRY);}
<EXPRESSION,BOTH,SCRIPT>"NEXT" { RTOKEN(NEXT);}
<EXPRESSION,BOTH,SCRIPT>"sizeof_headers" { RTOKEN(SIZEOF_HEADERS);}