diff options
author | Ian Lance Taylor <ian@airs.com> | 1996-08-02 19:01:58 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1996-08-02 19:01:58 +0000 |
commit | 5735ac9e57fe37d7984e6f71d551f9b0ebd87721 (patch) | |
tree | 4971d92383158bd9e10a126d93be8b9406c40fe6 /ld/ldexp.c | |
parent | 10a14e3639d6b655afd296809ec4102e1ba26b7f (diff) | |
download | gdb-5735ac9e57fe37d7984e6f71d551f9b0ebd87721.zip gdb-5735ac9e57fe37d7984e6f71d551f9b0ebd87721.tar.gz gdb-5735ac9e57fe37d7984e6f71d551f9b0ebd87721.tar.bz2 |
* 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.
Diffstat (limited to 'ld/ldexp.c')
-rw-r--r-- | ld/ldexp.c | 350 |
1 files changed, 187 insertions, 163 deletions
@@ -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 |