Back to index

cell-binutils  2.17cvs20070401
ldexp.c
Go to the documentation of this file.
00001 /* This module handles expression trees.
00002    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
00003    2001, 2002, 2003, 2004, 2005, 2006, 2007
00004    Free Software Foundation, Inc.
00005    Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
00006 
00007    This file is part of GLD, the Gnu Linker.
00008 
00009    GLD is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2, or (at your option)
00012    any later version.
00013 
00014    GLD is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with GLD; see the file COPYING.  If not, write to the Free
00021    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00022    02110-1301, USA.  */
00023 
00024 /* This module is in charge of working out the contents of expressions.
00025 
00026    It has to keep track of the relative/absness of a symbol etc. This
00027    is done by keeping all values in a struct (an etree_value_type)
00028    which contains a value, a section to which it is relative and a
00029    valid bit.  */
00030 
00031 #include "bfd.h"
00032 #include "sysdep.h"
00033 #include "bfdlink.h"
00034 
00035 #include "ld.h"
00036 #include "ldmain.h"
00037 #include "ldmisc.h"
00038 #include "ldexp.h"
00039 #include <ldgram.h>
00040 #include "ldlang.h"
00041 #include "libiberty.h"
00042 #include "safe-ctype.h"
00043 
00044 static void exp_fold_tree_1 (etree_type *);
00045 static void exp_fold_tree_no_dot (etree_type *);
00046 static bfd_vma align_n (bfd_vma, bfd_vma);
00047 
00048 segment_type *segments;
00049 
00050 struct ldexp_control expld;
00051 
00052 /* Print the string representation of the given token.  Surround it
00053    with spaces if INFIX_P is TRUE.  */
00054 
00055 static void
00056 exp_print_token (token_code_type code, int infix_p)
00057 {
00058   static const struct
00059   {
00060     token_code_type code;
00061     char * name;
00062   }
00063   table[] =
00064   {
00065     { INT, "int" },
00066     { NAME, "NAME" },
00067     { PLUSEQ, "+=" },
00068     { MINUSEQ, "-=" },
00069     { MULTEQ, "*=" },
00070     { DIVEQ, "/=" },
00071     { LSHIFTEQ, "<<=" },
00072     { RSHIFTEQ, ">>=" },
00073     { ANDEQ, "&=" },
00074     { OREQ, "|=" },
00075     { OROR, "||" },
00076     { ANDAND, "&&" },
00077     { EQ, "==" },
00078     { NE, "!=" },
00079     { LE, "<=" },
00080     { GE, ">=" },
00081     { LSHIFT, "<<" },
00082     { RSHIFT, ">>" },
00083     { ALIGN_K, "ALIGN" },
00084     { BLOCK, "BLOCK" },
00085     { QUAD, "QUAD" },
00086     { SQUAD, "SQUAD" },
00087     { LONG, "LONG" },
00088     { SHORT, "SHORT" },
00089     { BYTE, "BYTE" },
00090     { SECTIONS, "SECTIONS" },
00091     { SIZEOF_HEADERS, "SIZEOF_HEADERS" },
00092     { MEMORY, "MEMORY" },
00093     { DEFINED, "DEFINED" },
00094     { TARGET_K, "TARGET" },
00095     { SEARCH_DIR, "SEARCH_DIR" },
00096     { MAP, "MAP" },
00097     { ENTRY, "ENTRY" },
00098     { NEXT, "NEXT" },
00099     { SIZEOF, "SIZEOF" },
00100     { ADDR, "ADDR" },
00101     { LOADADDR, "LOADADDR" },
00102     { CONSTANT, "CONSTANT" },
00103     { MAX_K, "MAX_K" },
00104     { REL, "relocatable" },
00105     { DATA_SEGMENT_ALIGN, "DATA_SEGMENT_ALIGN" },
00106     { DATA_SEGMENT_RELRO_END, "DATA_SEGMENT_RELRO_END" },
00107     { DATA_SEGMENT_END, "DATA_SEGMENT_END" },
00108     { ORIGIN, "ORIGIN" },
00109     { LENGTH, "LENGTH" },
00110     { SEGMENT_START, "SEGMENT_START" }
00111   };
00112   unsigned int idx;
00113 
00114   for (idx = 0; idx < ARRAY_SIZE (table); idx++)
00115     if (table[idx].code == code)
00116       break;
00117 
00118   if (infix_p)
00119     fputc (' ', config.map_file);
00120 
00121   if (idx < ARRAY_SIZE (table))
00122     fputs (table[idx].name, config.map_file);
00123   else if (code < 127)
00124     fputc (code, config.map_file);
00125   else
00126     fprintf (config.map_file, "<code %d>", code);
00127 
00128   if (infix_p)
00129     fputc (' ', config.map_file);
00130 }
00131 
00132 static void
00133 make_abs (void)
00134 {
00135   expld.result.value += expld.result.section->vma;
00136   expld.result.section = bfd_abs_section_ptr;
00137 }
00138 
00139 static void
00140 new_abs (bfd_vma value)
00141 {
00142   expld.result.valid_p = TRUE;
00143   expld.result.section = bfd_abs_section_ptr;
00144   expld.result.value = value;
00145   expld.result.str = NULL;
00146 }
00147 
00148 etree_type *
00149 exp_intop (bfd_vma value)
00150 {
00151   etree_type *new = stat_alloc (sizeof (new->value));
00152   new->type.node_code = INT;
00153   new->value.value = value;
00154   new->value.str = NULL;
00155   new->type.node_class = etree_value;
00156   return new;
00157 }
00158 
00159 etree_type *
00160 exp_bigintop (bfd_vma value, char *str)
00161 {
00162   etree_type *new = stat_alloc (sizeof (new->value));
00163   new->type.node_code = INT;
00164   new->value.value = value;
00165   new->value.str = str;
00166   new->type.node_class = etree_value;
00167   return new;
00168 }
00169 
00170 /* Build an expression representing an unnamed relocatable value.  */
00171 
00172 etree_type *
00173 exp_relop (asection *section, bfd_vma value)
00174 {
00175   etree_type *new = stat_alloc (sizeof (new->rel));
00176   new->type.node_code = REL;
00177   new->type.node_class = etree_rel;
00178   new->rel.section = section;
00179   new->rel.value = value;
00180   return new;
00181 }
00182 
00183 static void
00184 new_rel (bfd_vma value, char *str, asection *section)
00185 {
00186   expld.result.valid_p = TRUE;
00187   expld.result.value = value;
00188   expld.result.str = str;
00189   expld.result.section = section;
00190 }
00191 
00192 static void
00193 new_rel_from_abs (bfd_vma value)
00194 {
00195   expld.result.valid_p = TRUE;
00196   expld.result.value = value - expld.section->vma;
00197   expld.result.str = NULL;
00198   expld.result.section = expld.section;
00199 }
00200 
00201 static void
00202 fold_unary (etree_type *tree)
00203 {
00204   exp_fold_tree_1 (tree->unary.child);
00205   if (expld.result.valid_p)
00206     {
00207       switch (tree->type.node_code)
00208        {
00209        case ALIGN_K:
00210          if (expld.phase != lang_first_phase_enum)
00211            new_rel_from_abs (align_n (expld.dot, expld.result.value));
00212          else
00213            expld.result.valid_p = FALSE;
00214          break;
00215 
00216        case ABSOLUTE:
00217          make_abs ();
00218          break;
00219 
00220        case '~':
00221          make_abs ();
00222          expld.result.value = ~expld.result.value;
00223          break;
00224 
00225        case '!':
00226          make_abs ();
00227          expld.result.value = !expld.result.value;
00228          break;
00229 
00230        case '-':
00231          make_abs ();
00232          expld.result.value = -expld.result.value;
00233          break;
00234 
00235        case NEXT:
00236          /* Return next place aligned to value.  */
00237          if (expld.phase != lang_first_phase_enum)
00238            {
00239              make_abs ();
00240              expld.result.value = align_n (expld.dot, expld.result.value);
00241            }
00242          else
00243            expld.result.valid_p = FALSE;
00244          break;
00245 
00246        case DATA_SEGMENT_END:
00247          if (expld.phase != lang_first_phase_enum
00248              && expld.section == bfd_abs_section_ptr
00249              && (expld.dataseg.phase == exp_dataseg_align_seen
00250                 || expld.dataseg.phase == exp_dataseg_relro_seen
00251                 || expld.dataseg.phase == exp_dataseg_adjust
00252                 || expld.dataseg.phase == exp_dataseg_relro_adjust
00253                 || expld.phase == lang_final_phase_enum))
00254            {
00255              if (expld.dataseg.phase == exp_dataseg_align_seen
00256                 || expld.dataseg.phase == exp_dataseg_relro_seen)
00257               {
00258                 expld.dataseg.phase = exp_dataseg_end_seen;
00259                 expld.dataseg.end = expld.result.value;
00260               }
00261            }
00262          else
00263            expld.result.valid_p = FALSE;
00264          break;
00265 
00266        default:
00267          FAIL ();
00268          break;
00269        }
00270     }
00271 }
00272 
00273 static void
00274 fold_binary (etree_type *tree)
00275 {
00276   exp_fold_tree_1 (tree->binary.lhs);
00277 
00278   /* The SEGMENT_START operator is special because its first
00279      operand is a string, not the name of a symbol.  */
00280   if (expld.result.valid_p && tree->type.node_code == SEGMENT_START)
00281     {
00282       const char *segment_name;
00283       segment_type *seg;
00284       /* Check to see if the user has overridden the default
00285         value.  */
00286       segment_name = tree->binary.rhs->name.name;
00287       for (seg = segments; seg; seg = seg->next) 
00288        if (strcmp (seg->name, segment_name) == 0)
00289          {
00290            seg->used = TRUE;
00291            expld.result.value = seg->value;
00292            expld.result.str = NULL;
00293            expld.result.section = NULL;
00294            break;
00295          }
00296     }
00297   else if (expld.result.valid_p)
00298     {
00299       etree_value_type lhs = expld.result;
00300 
00301       exp_fold_tree_1 (tree->binary.rhs);
00302       if (expld.result.valid_p)
00303        {
00304          /* If the values are from different sections, or this is an
00305             absolute expression, make both the source arguments
00306             absolute.  However, adding or subtracting an absolute
00307             value from a relative value is meaningful, and is an
00308             exception.  */
00309          if (expld.section != bfd_abs_section_ptr
00310              && lhs.section == bfd_abs_section_ptr
00311              && tree->type.node_code == '+')
00312            {
00313              /* Keep the section of the rhs term.  */
00314              expld.result.value = lhs.value + expld.result.value;
00315              return;
00316            }
00317          else if (expld.section != bfd_abs_section_ptr
00318              && expld.result.section == bfd_abs_section_ptr
00319              && (tree->type.node_code == '+'
00320                 || tree->type.node_code == '-'))
00321            {
00322              /* Keep the section of the lhs term.  */
00323              expld.result.section = lhs.section;
00324            }
00325          else if (expld.result.section != lhs.section
00326                  || expld.section == bfd_abs_section_ptr)
00327            {
00328              make_abs ();
00329              lhs.value += lhs.section->vma;
00330            }
00331 
00332          switch (tree->type.node_code)
00333            {
00334            case '%':
00335              if (expld.result.value != 0)
00336               expld.result.value = ((bfd_signed_vma) lhs.value
00337                                   % (bfd_signed_vma) expld.result.value);
00338              else if (expld.phase != lang_mark_phase_enum)
00339               einfo (_("%F%S %% by zero\n"));
00340              break;
00341 
00342            case '/':
00343              if (expld.result.value != 0)
00344               expld.result.value = ((bfd_signed_vma) lhs.value
00345                                   / (bfd_signed_vma) expld.result.value);
00346              else if (expld.phase != lang_mark_phase_enum)
00347               einfo (_("%F%S / by zero\n"));
00348              break;
00349 
00350 #define BOP(x, y) \
00351            case x:                                             \
00352              expld.result.value = lhs.value y expld.result.value;     \
00353              break;
00354 
00355              BOP ('+', +);
00356              BOP ('*', *);
00357              BOP ('-', -);
00358              BOP (LSHIFT, <<);
00359              BOP (RSHIFT, >>);
00360              BOP (EQ, ==);
00361              BOP (NE, !=);
00362              BOP ('<', <);
00363              BOP ('>', >);
00364              BOP (LE, <=);
00365              BOP (GE, >=);
00366              BOP ('&', &);
00367              BOP ('^', ^);
00368              BOP ('|', |);
00369              BOP (ANDAND, &&);
00370              BOP (OROR, ||);
00371 
00372            case MAX_K:
00373              if (lhs.value > expld.result.value)
00374               expld.result.value = lhs.value;
00375              break;
00376 
00377            case MIN_K:
00378              if (lhs.value < expld.result.value)
00379               expld.result.value = lhs.value;
00380              break;
00381 
00382            case ALIGN_K:
00383              expld.result.value = align_n (lhs.value, expld.result.value);
00384              break;
00385 
00386            case DATA_SEGMENT_ALIGN:
00387              if (expld.phase != lang_first_phase_enum
00388                 && expld.section == bfd_abs_section_ptr
00389                 && (expld.dataseg.phase == exp_dataseg_none
00390                     || expld.dataseg.phase == exp_dataseg_adjust
00391                     || expld.dataseg.phase == exp_dataseg_relro_adjust
00392                     || expld.phase == lang_final_phase_enum))
00393               {
00394                 bfd_vma maxpage = lhs.value;
00395                 bfd_vma commonpage = expld.result.value;
00396 
00397                 expld.result.value = align_n (expld.dot, maxpage);
00398                 if (expld.dataseg.phase == exp_dataseg_relro_adjust)
00399                   expld.result.value = expld.dataseg.base;
00400                 else if (expld.dataseg.phase != exp_dataseg_adjust)
00401                   {
00402                     expld.result.value += expld.dot & (maxpage - 1);
00403                     if (expld.phase == lang_allocating_phase_enum)
00404                      {
00405                        expld.dataseg.phase = exp_dataseg_align_seen;
00406                        expld.dataseg.min_base = align_n (expld.dot, maxpage);
00407                        expld.dataseg.base = expld.result.value;
00408                        expld.dataseg.pagesize = commonpage;
00409                        expld.dataseg.maxpagesize = maxpage;
00410                        expld.dataseg.relro_end = 0;
00411                      }
00412                   }
00413                 else if (commonpage < maxpage)
00414                   expld.result.value += ((expld.dot + commonpage - 1)
00415                                       & (maxpage - commonpage));
00416               }
00417              else
00418               expld.result.valid_p = FALSE;
00419              break;
00420 
00421            case DATA_SEGMENT_RELRO_END:
00422              if (expld.phase != lang_first_phase_enum
00423                 && (expld.dataseg.phase == exp_dataseg_align_seen
00424                     || expld.dataseg.phase == exp_dataseg_adjust
00425                     || expld.dataseg.phase == exp_dataseg_relro_adjust
00426                     || expld.phase == lang_final_phase_enum))
00427               {
00428                 if (expld.dataseg.phase == exp_dataseg_align_seen
00429                     || expld.dataseg.phase == exp_dataseg_relro_adjust)
00430                   expld.dataseg.relro_end = lhs.value + expld.result.value;
00431 
00432                 if (expld.dataseg.phase == exp_dataseg_relro_adjust
00433                     && (expld.dataseg.relro_end
00434                        & (expld.dataseg.pagesize - 1)))
00435                   {
00436                     expld.dataseg.relro_end += expld.dataseg.pagesize - 1;
00437                     expld.dataseg.relro_end &= ~(expld.dataseg.pagesize - 1);
00438                     expld.result.value = (expld.dataseg.relro_end
00439                                        - expld.result.value);
00440                   }
00441                 else
00442                   expld.result.value = lhs.value;
00443 
00444                 if (expld.dataseg.phase == exp_dataseg_align_seen)
00445                   expld.dataseg.phase = exp_dataseg_relro_seen;
00446               }
00447              else
00448               expld.result.valid_p = FALSE;
00449              break;
00450 
00451            default:
00452              FAIL ();
00453            }
00454        }
00455       else
00456        expld.result.valid_p = FALSE;
00457     }
00458 }
00459 
00460 static void
00461 fold_trinary (etree_type *tree)
00462 {
00463   exp_fold_tree_1 (tree->trinary.cond);
00464   if (expld.result.valid_p)
00465     exp_fold_tree_1 (expld.result.value
00466                    ? tree->trinary.lhs
00467                    : tree->trinary.rhs);
00468 }
00469 
00470 static void
00471 fold_name (etree_type *tree)
00472 {
00473   memset (&expld.result, 0, sizeof (expld.result));
00474 
00475   switch (tree->type.node_code)
00476     {
00477     case SIZEOF_HEADERS:
00478       if (expld.phase != lang_first_phase_enum)
00479        {
00480          bfd_vma hdr_size = 0;
00481          /* Don't find the real header size if only marking sections;
00482             The bfd function may cache incorrect data.  */
00483          if (expld.phase != lang_mark_phase_enum)
00484            hdr_size = bfd_sizeof_headers (output_bfd, &link_info);
00485          new_abs (hdr_size);
00486        }
00487       break;
00488 
00489     case DEFINED:
00490       if (expld.phase == lang_first_phase_enum)
00491        lang_track_definedness (tree->name.name);
00492       else
00493        {
00494          struct bfd_link_hash_entry *h;
00495          int def_iteration
00496            = lang_symbol_definition_iteration (tree->name.name);
00497 
00498          h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
00499                                        tree->name.name,
00500                                        FALSE, FALSE, TRUE);
00501          expld.result.value = (h != NULL
00502                             && (h->type == bfd_link_hash_defined
00503                                 || h->type == bfd_link_hash_defweak
00504                                 || h->type == bfd_link_hash_common)
00505                             && (def_iteration == lang_statement_iteration
00506                                 || def_iteration == -1));
00507          expld.result.section = bfd_abs_section_ptr;
00508          expld.result.valid_p = TRUE;
00509        }
00510       break;
00511 
00512     case NAME:
00513       if (expld.phase == lang_first_phase_enum)
00514        ;
00515       else if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
00516        new_rel_from_abs (expld.dot);
00517       else
00518        {
00519          struct bfd_link_hash_entry *h;
00520 
00521          h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
00522                                        tree->name.name,
00523                                        TRUE, FALSE, TRUE);
00524          if (!h)
00525            einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
00526          else if (h->type == bfd_link_hash_defined
00527                  || h->type == bfd_link_hash_defweak)
00528            {
00529              if (bfd_is_abs_section (h->u.def.section))
00530               new_abs (h->u.def.value);
00531              else
00532               {
00533                 asection *output_section;
00534 
00535                 output_section = h->u.def.section->output_section;
00536                 if (output_section == NULL)
00537                   {
00538                     if (expld.phase != lang_mark_phase_enum)
00539                      einfo (_("%X%S: unresolvable symbol `%s'"
00540                              " referenced in expression\n"),
00541                             tree->name.name);
00542                   }
00543                 else
00544                   new_rel (h->u.def.value + h->u.def.section->output_offset,
00545                           NULL, output_section);
00546               }
00547            }
00548          else if (expld.phase == lang_final_phase_enum
00549                  || expld.assigning_to_dot)
00550            einfo (_("%F%S: undefined symbol `%s' referenced in expression\n"),
00551                  tree->name.name);
00552          else if (h->type == bfd_link_hash_new)
00553            {
00554              h->type = bfd_link_hash_undefined;
00555              h->u.undef.abfd = NULL;
00556              if (h->u.undef.next == NULL && h != link_info.hash->undefs_tail)
00557               bfd_link_add_undef (link_info.hash, h);
00558            }
00559        }
00560       break;
00561 
00562     case ADDR:
00563       if (expld.phase != lang_first_phase_enum)
00564        {
00565          lang_output_section_statement_type *os;
00566 
00567          os = lang_output_section_find (tree->name.name);
00568          if (os == NULL)
00569            {
00570              if (expld.phase == lang_final_phase_enum)
00571               einfo (_("%F%S: undefined section `%s' referenced in expression\n"),
00572                      tree->name.name);
00573            }
00574          else if (os->processed_vma)
00575            new_rel (0, NULL, os->bfd_section);
00576        }
00577       break;
00578 
00579     case LOADADDR:
00580       if (expld.phase != lang_first_phase_enum)
00581        {
00582          lang_output_section_statement_type *os;
00583 
00584          os = lang_output_section_find (tree->name.name);
00585          if (os == NULL)
00586            {
00587              if (expld.phase == lang_final_phase_enum)
00588               einfo (_("%F%S: undefined section `%s' referenced in expression\n"),
00589                      tree->name.name);
00590            }
00591          else if (os->processed_lma)
00592            {
00593              if (os->load_base == NULL)
00594               new_abs (os->bfd_section->lma);
00595              else
00596               {
00597                 exp_fold_tree_1 (os->load_base);
00598                 make_abs ();
00599               }
00600            }
00601        }
00602       break;
00603 
00604     case SIZEOF:
00605       if (expld.phase != lang_first_phase_enum)
00606        {
00607          int opb = bfd_octets_per_byte (output_bfd);
00608          lang_output_section_statement_type *os;
00609 
00610          os = lang_output_section_find (tree->name.name);
00611          if (os == NULL)
00612            {
00613              if (expld.phase == lang_final_phase_enum)
00614               einfo (_("%F%S: undefined section `%s' referenced in expression\n"),
00615                      tree->name.name);
00616              new_abs (0);
00617            }
00618          else if (os->processed_vma)
00619            new_abs (os->bfd_section->size / opb);
00620        }
00621       break;
00622 
00623     case LENGTH:
00624       {
00625         lang_memory_region_type *mem;
00626         
00627         mem = lang_memory_region_lookup (tree->name.name, FALSE);  
00628         if (mem != NULL) 
00629           new_abs (mem->length);
00630         else          
00631           einfo (_("%F%S: undefined MEMORY region `%s'"
00632                  " referenced in expression\n"), tree->name.name);
00633       }
00634       break;
00635 
00636     case ORIGIN:
00637       {
00638         lang_memory_region_type *mem;
00639         
00640         mem = lang_memory_region_lookup (tree->name.name, FALSE);  
00641         if (mem != NULL) 
00642           new_abs (mem->origin);
00643         else          
00644           einfo (_("%F%S: undefined MEMORY region `%s'"
00645                  " referenced in expression\n"), tree->name.name);
00646       }
00647       break;
00648 
00649     case CONSTANT:
00650       if (strcmp (tree->name.name, "MAXPAGESIZE") == 0)
00651        new_abs (bfd_emul_get_maxpagesize (default_target));
00652       else if (strcmp (tree->name.name, "COMMONPAGESIZE") == 0)
00653        new_abs (bfd_emul_get_commonpagesize (default_target));
00654       else
00655        einfo (_("%F%S: unknown constant `%s' referenced in expression\n"),
00656               tree->name.name);
00657       break;
00658 
00659     default:
00660       FAIL ();
00661       break;
00662     }
00663 }
00664 
00665 static void
00666 exp_fold_tree_1 (etree_type *tree)
00667 {
00668   if (tree == NULL)
00669     {
00670       memset (&expld.result, 0, sizeof (expld.result));
00671       return;
00672     }
00673 
00674   switch (tree->type.node_class)
00675     {
00676     case etree_value:
00677       new_rel (tree->value.value, tree->value.str, expld.section);
00678       break;
00679 
00680     case etree_rel:
00681       if (expld.phase != lang_first_phase_enum)
00682        {
00683          asection *output_section = tree->rel.section->output_section;
00684          new_rel (tree->rel.value + tree->rel.section->output_offset,
00685                  NULL, output_section);
00686        }
00687       else
00688        memset (&expld.result, 0, sizeof (expld.result));
00689       break;
00690 
00691     case etree_assert:
00692       exp_fold_tree_1 (tree->assert_s.child);
00693       if (expld.phase == lang_final_phase_enum && !expld.result.value)
00694        einfo ("%X%P: %s\n", tree->assert_s.message);
00695       break;
00696 
00697     case etree_unary:
00698       fold_unary (tree);
00699       break;
00700 
00701     case etree_binary:
00702       fold_binary (tree);
00703       break;
00704 
00705     case etree_trinary:
00706       fold_trinary (tree);
00707       break;
00708 
00709     case etree_assign:
00710     case etree_provide:
00711     case etree_provided:
00712       if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0)
00713        {
00714          /* Assignment to dot can only be done during allocation.  */
00715          if (tree->type.node_class != etree_assign)
00716            einfo (_("%F%S can not PROVIDE assignment to location counter\n"));
00717          if (expld.phase == lang_mark_phase_enum
00718              || expld.phase == lang_allocating_phase_enum
00719              || (expld.phase == lang_final_phase_enum
00720                 && expld.section == bfd_abs_section_ptr))
00721            {
00722              /* Notify the folder that this is an assignment to dot.  */
00723              expld.assigning_to_dot = TRUE;
00724              exp_fold_tree_1 (tree->assign.src);
00725              expld.assigning_to_dot = FALSE;
00726 
00727              if (!expld.result.valid_p)
00728               {
00729                 if (expld.phase != lang_mark_phase_enum)
00730                   einfo (_("%F%S invalid assignment to location counter\n"));
00731               }
00732              else if (expld.dotp == NULL)
00733               einfo (_("%F%S assignment to location counter"
00734                       " invalid outside of SECTION\n"));
00735              else
00736               {
00737                 bfd_vma nextdot;
00738 
00739                 nextdot = expld.result.value + expld.section->vma;
00740                 if (nextdot < expld.dot
00741                     && expld.section != bfd_abs_section_ptr)
00742                   einfo (_("%F%S cannot move location counter backwards"
00743                           " (from %V to %V)\n"), expld.dot, nextdot);
00744                 else
00745                   {
00746                     expld.dot = nextdot;
00747                     *expld.dotp = nextdot;
00748                   }
00749               }
00750            }
00751          else
00752            memset (&expld.result, 0, sizeof (expld.result));
00753        }
00754       else
00755        {
00756          struct bfd_link_hash_entry *h = NULL;
00757 
00758          if (tree->type.node_class == etree_provide)
00759            {
00760              h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
00761                                    FALSE, FALSE, TRUE);
00762              if (h == NULL
00763                 || (h->type != bfd_link_hash_new
00764                     && h->type != bfd_link_hash_undefined
00765                     && h->type != bfd_link_hash_common))
00766               {
00767                 /* Do nothing.  The symbol was never referenced, or was
00768                    defined by some object.  */
00769                 break;
00770               }
00771            }
00772 
00773          exp_fold_tree_1 (tree->assign.src);
00774          if (expld.result.valid_p)
00775            {
00776              if (h == NULL)
00777               {
00778                 h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
00779                                        TRUE, FALSE, TRUE);
00780                 if (h == NULL)
00781                   einfo (_("%P%F:%s: hash creation failed\n"),
00782                         tree->assign.dst);
00783               }
00784 
00785              /* FIXME: Should we worry if the symbol is already
00786                defined?  */
00787              lang_update_definedness (tree->assign.dst, h);
00788              h->type = bfd_link_hash_defined;
00789              h->u.def.value = expld.result.value;
00790              h->u.def.section = expld.result.section;
00791              if (tree->type.node_class == etree_provide)
00792               tree->type.node_class = etree_provided;
00793            }
00794        }
00795       break;
00796 
00797     case etree_name:
00798       fold_name (tree);
00799       break;
00800 
00801     default:
00802       FAIL ();
00803       memset (&expld.result, 0, sizeof (expld.result));
00804       break;
00805     }
00806 }
00807 
00808 void
00809 exp_fold_tree (etree_type *tree, asection *current_section, bfd_vma *dotp)
00810 {
00811   expld.dot = *dotp;
00812   expld.dotp = dotp;
00813   expld.section = current_section;
00814   exp_fold_tree_1 (tree);
00815 }
00816 
00817 static void
00818 exp_fold_tree_no_dot (etree_type *tree)
00819 {
00820   expld.dot = 0;
00821   expld.dotp = NULL;
00822   expld.section = bfd_abs_section_ptr;
00823   exp_fold_tree_1 (tree);
00824 }
00825 
00826 etree_type *
00827 exp_binop (int code, etree_type *lhs, etree_type *rhs)
00828 {
00829   etree_type value, *new;
00830 
00831   value.type.node_code = code;
00832   value.binary.lhs = lhs;
00833   value.binary.rhs = rhs;
00834   value.type.node_class = etree_binary;
00835   exp_fold_tree_no_dot (&value);
00836   if (expld.result.valid_p)
00837     return exp_intop (expld.result.value);
00838 
00839   new = stat_alloc (sizeof (new->binary));
00840   memcpy (new, &value, sizeof (new->binary));
00841   return new;
00842 }
00843 
00844 etree_type *
00845 exp_trinop (int code, etree_type *cond, etree_type *lhs, etree_type *rhs)
00846 {
00847   etree_type value, *new;
00848 
00849   value.type.node_code = code;
00850   value.trinary.lhs = lhs;
00851   value.trinary.cond = cond;
00852   value.trinary.rhs = rhs;
00853   value.type.node_class = etree_trinary;
00854   exp_fold_tree_no_dot (&value);
00855   if (expld.result.valid_p)
00856     return exp_intop (expld.result.value);
00857 
00858   new = stat_alloc (sizeof (new->trinary));
00859   memcpy (new, &value, sizeof (new->trinary));
00860   return new;
00861 }
00862 
00863 etree_type *
00864 exp_unop (int code, etree_type *child)
00865 {
00866   etree_type value, *new;
00867 
00868   value.unary.type.node_code = code;
00869   value.unary.child = child;
00870   value.unary.type.node_class = etree_unary;
00871   exp_fold_tree_no_dot (&value);
00872   if (expld.result.valid_p)
00873     return exp_intop (expld.result.value);
00874 
00875   new = stat_alloc (sizeof (new->unary));
00876   memcpy (new, &value, sizeof (new->unary));
00877   return new;
00878 }
00879 
00880 etree_type *
00881 exp_nameop (int code, const char *name)
00882 {
00883   etree_type value, *new;
00884 
00885   value.name.type.node_code = code;
00886   value.name.name = name;
00887   value.name.type.node_class = etree_name;
00888 
00889   exp_fold_tree_no_dot (&value);
00890   if (expld.result.valid_p)
00891     return exp_intop (expld.result.value);
00892 
00893   new = stat_alloc (sizeof (new->name));
00894   memcpy (new, &value, sizeof (new->name));
00895   return new;
00896 
00897 }
00898 
00899 etree_type *
00900 exp_assop (int code, const char *dst, etree_type *src)
00901 {
00902   etree_type *new;
00903 
00904   new = stat_alloc (sizeof (new->assign));
00905   new->type.node_code = code;
00906   new->type.node_class = etree_assign;
00907   new->assign.src = src;
00908   new->assign.dst = dst;
00909   return new;
00910 }
00911 
00912 /* Handle PROVIDE.  */
00913 
00914 etree_type *
00915 exp_provide (const char *dst, etree_type *src, bfd_boolean hidden)
00916 {
00917   etree_type *n;
00918 
00919   n = stat_alloc (sizeof (n->assign));
00920   n->assign.type.node_code = '=';
00921   n->assign.type.node_class = etree_provide;
00922   n->assign.src = src;
00923   n->assign.dst = dst;
00924   n->assign.hidden = hidden;
00925   return n;
00926 }
00927 
00928 /* Handle ASSERT.  */
00929 
00930 etree_type *
00931 exp_assert (etree_type *exp, const char *message)
00932 {
00933   etree_type *n;
00934 
00935   n = stat_alloc (sizeof (n->assert_s));
00936   n->assert_s.type.node_code = '!';
00937   n->assert_s.type.node_class = etree_assert;
00938   n->assert_s.child = exp;
00939   n->assert_s.message = message;
00940   return n;
00941 }
00942 
00943 void
00944 exp_print_tree (etree_type *tree)
00945 {
00946   if (config.map_file == NULL)
00947     config.map_file = stderr;
00948 
00949   if (tree == NULL)
00950     {
00951       minfo ("NULL TREE\n");
00952       return;
00953     }
00954 
00955   switch (tree->type.node_class)
00956     {
00957     case etree_value:
00958       minfo ("0x%v", tree->value.value);
00959       return;
00960     case etree_rel:
00961       if (tree->rel.section->owner != NULL)
00962        minfo ("%B:", tree->rel.section->owner);
00963       minfo ("%s+0x%v", tree->rel.section->name, tree->rel.value);
00964       return;
00965     case etree_assign:
00966       fprintf (config.map_file, "%s", tree->assign.dst);
00967       exp_print_token (tree->type.node_code, TRUE);
00968       exp_print_tree (tree->assign.src);
00969       break;
00970     case etree_provide:
00971     case etree_provided:
00972       fprintf (config.map_file, "PROVIDE (%s, ", tree->assign.dst);
00973       exp_print_tree (tree->assign.src);
00974       fprintf (config.map_file, ")");
00975       break;
00976     case etree_binary:
00977       fprintf (config.map_file, "(");
00978       exp_print_tree (tree->binary.lhs);
00979       exp_print_token (tree->type.node_code, TRUE);
00980       exp_print_tree (tree->binary.rhs);
00981       fprintf (config.map_file, ")");
00982       break;
00983     case etree_trinary:
00984       exp_print_tree (tree->trinary.cond);
00985       fprintf (config.map_file, "?");
00986       exp_print_tree (tree->trinary.lhs);
00987       fprintf (config.map_file, ":");
00988       exp_print_tree (tree->trinary.rhs);
00989       break;
00990     case etree_unary:
00991       exp_print_token (tree->unary.type.node_code, FALSE);
00992       if (tree->unary.child)
00993        {
00994          fprintf (config.map_file, " (");
00995          exp_print_tree (tree->unary.child);
00996          fprintf (config.map_file, ")");
00997        }
00998       break;
00999 
01000     case etree_assert:
01001       fprintf (config.map_file, "ASSERT (");
01002       exp_print_tree (tree->assert_s.child);
01003       fprintf (config.map_file, ", %s)", tree->assert_s.message);
01004       break;
01005 
01006     case etree_name:
01007       if (tree->type.node_code == NAME)
01008        {
01009          fprintf (config.map_file, "%s", tree->name.name);
01010        }
01011       else
01012        {
01013          exp_print_token (tree->type.node_code, FALSE);
01014          if (tree->name.name)
01015            fprintf (config.map_file, " (%s)", tree->name.name);
01016        }
01017       break;
01018     default:
01019       FAIL ();
01020       break;
01021     }
01022 }
01023 
01024 bfd_vma
01025 exp_get_vma (etree_type *tree, bfd_vma def, char *name)
01026 {
01027   if (tree != NULL)
01028     {
01029       exp_fold_tree_no_dot (tree);
01030       if (expld.result.valid_p)
01031        return expld.result.value;
01032       else if (name != NULL && expld.phase != lang_mark_phase_enum)
01033        einfo (_("%F%S nonconstant expression for %s\n"), name);
01034     }
01035   return def;
01036 }
01037 
01038 int
01039 exp_get_value_int (etree_type *tree, int def, char *name)
01040 {
01041   return exp_get_vma (tree, def, name);
01042 }
01043 
01044 fill_type *
01045 exp_get_fill (etree_type *tree, fill_type *def, char *name)
01046 {
01047   fill_type *fill;
01048   size_t len;
01049   unsigned int val;
01050 
01051   if (tree == NULL)
01052     return def;
01053 
01054   exp_fold_tree_no_dot (tree);
01055   if (!expld.result.valid_p)
01056     {
01057       if (name != NULL && expld.phase != lang_mark_phase_enum)
01058        einfo (_("%F%S nonconstant expression for %s\n"), name);
01059       return def;
01060     }
01061 
01062   if (expld.result.str != NULL && (len = strlen (expld.result.str)) != 0)
01063     {
01064       unsigned char *dst;
01065       unsigned char *s;
01066       fill = xmalloc ((len + 1) / 2 + sizeof (*fill) - 1);
01067       fill->size = (len + 1) / 2;
01068       dst = fill->data;
01069       s = (unsigned char *) expld.result.str;
01070       val = 0;
01071       do
01072        {
01073          unsigned int digit;
01074 
01075          digit = *s++ - '0';
01076          if (digit > 9)
01077            digit = (digit - 'A' + '0' + 10) & 0xf;
01078          val <<= 4;
01079          val += digit;
01080          --len;
01081          if ((len & 1) == 0)
01082            {
01083              *dst++ = val;
01084              val = 0;
01085            }
01086        }
01087       while (len != 0);
01088     }
01089   else
01090     {
01091       fill = xmalloc (4 + sizeof (*fill) - 1);
01092       val = expld.result.value;
01093       fill->data[0] = (val >> 24) & 0xff;
01094       fill->data[1] = (val >> 16) & 0xff;
01095       fill->data[2] = (val >>  8) & 0xff;
01096       fill->data[3] = (val >>  0) & 0xff;
01097       fill->size = 4;
01098     }
01099   return fill;
01100 }
01101 
01102 bfd_vma
01103 exp_get_abs_int (etree_type *tree, int def, char *name)
01104 {
01105   if (tree != NULL)
01106     {
01107       exp_fold_tree_no_dot (tree);
01108 
01109       if (expld.result.valid_p)
01110        {
01111          expld.result.value += expld.result.section->vma;
01112          return expld.result.value;
01113        }
01114       else if (name != NULL && expld.phase != lang_mark_phase_enum)
01115        einfo (_("%F%S nonconstant expression for %s\n"), name);
01116     }
01117   return def;
01118 }
01119 
01120 static bfd_vma
01121 align_n (bfd_vma value, bfd_vma align)
01122 {
01123   if (align <= 1)
01124     return value;
01125 
01126   value = (value + align - 1) / align;
01127   return value * align;
01128 }