mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-25 05:00:01 +00:00
* 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.
This commit is contained in:
parent
10a14e3639
commit
5735ac9e57
10
ld/ChangeLog
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
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.
|
||||
|
@ -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})
|
||||
|
360
ld/ldexp.c
360
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)
|
||||
{
|
||||
case etree_value:
|
||||
result = new_rel(tree->value.value, current_section);
|
||||
result.valid = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
switch (tree->type.node_class)
|
||||
{
|
||||
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 etree_unary:
|
||||
result = exp_fold_tree (tree->unary.child,
|
||||
current_section,
|
||||
allocation_done, dot, dotp);
|
||||
if (result.valid)
|
||||
{
|
||||
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)
|
||||
switch (tree->type.node_code)
|
||||
{
|
||||
result.value += result.section->bfd_section->vma;
|
||||
result.section = abs_output_section;
|
||||
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;
|
||||
}
|
||||
else
|
||||
}
|
||||
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);
|
||||
break;
|
||||
|
||||
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.valid = false;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
break;
|
||||
default:
|
||||
einfo("%F%S need more of these %d\n",tree->type.node_class );
|
||||
|
||||
case etree_name:
|
||||
result = fold_name (tree, current_section, allocation_done, dot);
|
||||
break;
|
||||
|
||||
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
|
||||
|
@ -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 ')'
|
||||
|
@ -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;
|
||||
|
@ -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…
Reference in New Issue
Block a user