diff options
-rw-r--r-- | ld/ChangeLog | 10 | ||||
-rw-r--r-- | ld/NEWS | 2 | ||||
-rw-r--r-- | ld/ld.texinfo | 8 | ||||
-rw-r--r-- | ld/ldexp.c | 350 | ||||
-rw-r--r-- | ld/ldgram.y | 4 | ||||
-rw-r--r-- | ld/ldlang.c | 1 | ||||
-rw-r--r-- | ld/ldlex.l | 1 |
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. @@ -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}) @@ -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; @@ -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);} |