Browse Source

* 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.
gdb-4_18-branch
Ian Lance Taylor 30 years ago
parent
commit
5735ac9e57
  1. 10
      ld/ChangeLog
  2. 2
      ld/NEWS
  3. 8
      ld/ld.texinfo
  4. 350
      ld/ldexp.c
  5. 4
      ld/ldgram.y
  6. 1
      ld/ldlang.c
  7. 1
      ld/ldlex.l

10
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.

2
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.

8
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})

350
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

4
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 ')'

1
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;

1
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);}

Loading…
Cancel
Save