Home | History | Annotate | Download | only in config
      1 /* obj-evax.c - EVAX (openVMS/Alpha) object file format.
      2    Copyright (C) 1996-2014 Free Software Foundation, Inc.
      3    Contributed by Klaus Kmpf (kkaempf (at) progis.de) of
      4      proGIS Software, Aachen, Germany.
      5    Extensively enhanced by Douglas Rupp of AdaCore.
      6 
      7    This file is part of GAS, the GNU Assembler
      8 
      9    GAS is free software; you can redistribute it and/or modify
     10    it under the terms of the GNU General Public License as published by
     11    the Free Software Foundation; either version 3, or (at your option)
     12    any later version.
     13 
     14    GAS is distributed in the hope that it will be useful,
     15    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17    GNU General Public License for more details.
     18 
     19    You should have received a copy of the GNU General Public License
     20    along with GAS; see the file COPYING.  If not, write to
     21    the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
     22    MA 02110-1301, USA.  */
     23 
     24 #define OBJ_HEADER "obj-evax.h"
     25 
     26 #include "as.h"
     27 #include "bfd.h"
     28 #include "vms.h"
     29 #include "subsegs.h"
     30 #include "struc-symbol.h"
     31 #include "safe-ctype.h"
     32 
     33 static void s_evax_weak (int);
     34 static unsigned int crc32 (unsigned char *, int);
     35 static char *encode_32 (unsigned int);
     36 static char *encode_16 (unsigned int);
     37 static int decode_16 (const char *);
     38 
     39 const pseudo_typeS obj_pseudo_table[] =
     40 {
     41   { "weak", s_evax_weak, 0},
     42   {0, 0, 0},
     43 };				/* obj_pseudo_table */
     44 
     45 void obj_read_begin_hook () {}
     46 
     47 /* Handle the weak specific pseudo-op.  */
     48 
     49 static void
     50 s_evax_weak (int ignore ATTRIBUTE_UNUSED)
     51 {
     52   char *name;
     53   int c;
     54   symbolS *symbolP;
     55   char *stop = NULL;
     56   char stopc;
     57 
     58   if (flag_mri)
     59     stop = mri_comment_field (&stopc);
     60 
     61   do
     62     {
     63       name = input_line_pointer;
     64       c = get_symbol_end ();
     65       symbolP = symbol_find_or_make (name);
     66       *input_line_pointer = c;
     67       SKIP_WHITESPACE ();
     68       S_SET_WEAK (symbolP);
     69       if (c == ',')
     70 	{
     71 	  input_line_pointer++;
     72 	  SKIP_WHITESPACE ();
     73 	  if (*input_line_pointer == '\n')
     74 	    c = '\n';
     75 	}
     76     }
     77   while (c == ',');
     78 
     79   if (flag_mri)
     80     mri_comment_end (stop, stopc);
     81 
     82   demand_empty_rest_of_line ();
     83 }
     84 
     85 void
     86 evax_symbol_new_hook (symbolS *sym)
     87 {
     88   struct evax_private_udata_struct *udata;
     89 
     90   udata = (struct evax_private_udata_struct *)
     91     xmalloc (sizeof (struct evax_private_udata_struct));
     92 
     93   udata->bsym = symbol_get_bfdsym (sym);
     94   udata->enbsym = NULL;
     95   udata->origname = xstrdup (S_GET_NAME (sym));
     96   udata->lkindex = 0;
     97   symbol_get_bfdsym(sym)->udata.p = (PTR) udata;
     98 }
     99 
    100 void
    101 evax_frob_symbol (symbolS *sym, int *punt)
    102 {
    103   const char *symname = S_GET_NAME (sym);
    104   int symlen = strlen (symname);
    105   asymbol *symbol = symbol_get_bfdsym (sym);
    106 
    107   if (symlen > 4
    108       && strcmp (symname + symlen - 4, "..en") == 0
    109       && S_GET_SEGMENT (sym) == undefined_section)
    110     {
    111       symbol_clear_used_in_reloc (sym);
    112       *punt = 1;
    113     }
    114 
    115   else if ((symbol->flags & BSF_GLOBAL) && (symbol->flags & BSF_FUNCTION))
    116     {
    117       struct evax_private_udata_struct *udata
    118 	= (struct evax_private_udata_struct *)symbol->udata.p;
    119 
    120       /* Fix up equates of function definitions.  */
    121       while (udata->enbsym == NULL)
    122 	{
    123 	  /* ??? Equates have been resolved at this point so their
    124 	     expression is O_constant; but they previously were
    125 	     O_symbol and we hope the equated symbol is still there.  */
    126 	  sym = symbol_get_value_expression (sym)->X_add_symbol;
    127 	  if (sym == NULL)
    128             {
    129               as_bad (_("no entry symbol for global function '%s'"), symname);
    130               return;
    131             }
    132 	  symbol = symbol_get_bfdsym (sym);
    133 	  udata->enbsym
    134 	    = ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym;
    135 	}
    136     }
    137 }
    138 
    139 void
    140 evax_frob_file_before_adjust (void)
    141 {
    142   struct alpha_linkage_fixups *l;
    143   segT current_section = now_seg;
    144   int current_subsec = now_subseg;
    145   segment_info_type *seginfo;
    146   int linkage_index = 1;
    147 
    148   subseg_set (alpha_link_section, 0);
    149   seginfo = seg_info (alpha_link_section);
    150 
    151   /* Handle .linkage fixups.  */
    152   for (l = alpha_linkage_fixup_root; l != NULL; l = l->next)
    153     {
    154       if (S_GET_SEGMENT (l->fixp->fx_addsy) == alpha_link_section)
    155 	{
    156           /* The symbol is defined in the file.  The linkage entry decays to
    157              two relocs.  */
    158 	  symbolS *entry_sym;
    159 	  fixS *fixpentry, *fixppdesc, *fixtail;
    160 
    161 	  fixtail = seginfo->fix_tail;
    162 
    163 	  /* Replace the linkage with the local symbols */
    164 	  entry_sym = symbol_find
    165 	    (((struct evax_private_udata_struct *)symbol_get_bfdsym (l->fixp->fx_addsy)->udata.p)->enbsym->name);
    166 	  if (!entry_sym)
    167 	    abort ();
    168 	  fixpentry = fix_new (l->fixp->fx_frag, l->fixp->fx_where, 8,
    169 			       entry_sym, l->fixp->fx_offset, 0,
    170 			       BFD_RELOC_64);
    171 	  fixppdesc = fix_new (l->fixp->fx_frag, l->fixp->fx_where + 8, 8,
    172 			       l->fixp->fx_addsy, l->fixp->fx_offset, 0,
    173 			       BFD_RELOC_64);
    174 	  l->fixp->fx_size = 0;
    175 	  l->fixp->fx_done = 1;
    176 
    177 	  /* If not already at the tail, splice the new fixups into
    178 	     the chain right after the one we are nulling out */
    179 	  if (fixtail != l->fixp)
    180 	    {
    181 	      fixppdesc->fx_next = l->fixp->fx_next;
    182 	      l->fixp->fx_next = fixpentry;
    183 	      fixtail->fx_next = 0;
    184 	      seginfo->fix_tail = fixtail;
    185 	    }
    186 	}
    187       else
    188 	{
    189           /* Assign a linkage index.  */
    190 	  ((struct evax_private_udata_struct *)
    191 	   symbol_get_bfdsym (l->label)->udata.p)->lkindex = linkage_index;
    192 
    193 	  l->fixp->fx_addnumber = linkage_index;
    194 
    195 	  linkage_index += 2;
    196 	}
    197     }
    198 
    199   subseg_set (current_section, current_subsec);
    200 }
    201 
    202 void
    203 evax_frob_file_before_fix (void)
    204 {
    205   /* Now that the fixups are done earlier, we need to transfer the values
    206      into the BFD symbols before calling fix_segment (ideally should not
    207      be done also later).  */
    208   if (symbol_rootP)
    209     {
    210       symbolS *symp;
    211 
    212       /* Set the value into the BFD symbol.  Up til now the value
    213 	 has only been kept in the gas symbolS struct.  */
    214       for (symp = symbol_rootP; symp; symp = symbol_next (symp))
    215 	symbol_get_bfdsym (symp)->value = S_GET_VALUE (symp);
    216     }
    217 }
    218 
    219 /* The length is computed from the maximum allowable length of 64 less the
    220    4 character ..xx extension that must be preserved (removed before
    221    krunching and appended back on afterwards).  The $<nnn>.. prefix is
    222    also removed and prepened back on, but doesn't enter into the length
    223    computation because symbols with that prefix are always resolved
    224    by the assembler and will never appear in the symbol table. At least
    225    I hope that's true, TBD.  */
    226 #define MAX_LABEL_LENGTH 60
    227 
    228 static char *shorten_identifier (char *);
    229 static int is_truncated_identifier (char *);
    230 
    231 char *
    232 evax_shorten_name (char *id)
    233 {
    234   int prefix_dotdot = 0;
    235   char prefix [64];
    236   int len = strlen (id);
    237   int suffix_dotdot = len;
    238   char suffix [64];
    239   char *base_id;
    240 
    241   /* This test may be too conservative.  */
    242   if (len <= MAX_LABEL_LENGTH)
    243     return id;
    244 
    245   suffix [0] = 0;
    246   prefix [0] = 0;
    247 
    248   /* Check for ..xx suffix and save it.  */
    249   if (strncmp (&id[len-4], "..", 2) == 0)
    250     {
    251       suffix_dotdot = len - 4;
    252       strncpy (suffix, &id[len-4], 4);
    253       suffix [4] = 0;
    254     }
    255 
    256   /* Check for $<nnn>.. prefix and save it.  */
    257   if ((id[0] == '$') && ISDIGIT (id[1]))
    258     {
    259       int i;
    260 
    261       for (i=2; i < len; i++)
    262         {
    263 	  if (!ISDIGIT (id[i]))
    264             {
    265 	      if (id[i] == '.' && id [i+1] == '.')
    266                  {
    267                    prefix_dotdot = i+2;
    268                    strncpy (prefix, id, prefix_dotdot);
    269                    prefix [prefix_dotdot] = 0;
    270                  }
    271                break;
    272             }
    273         }
    274     }
    275 
    276   /* We only need worry about krunching the base symbol.  */
    277   base_id = xmalloc (suffix_dotdot - prefix_dotdot + 1);
    278   strncpy (base_id, &id[prefix_dotdot], suffix_dotdot - prefix_dotdot);
    279   base_id [suffix_dotdot - prefix_dotdot] = 0;
    280 
    281   if (strlen (base_id) > MAX_LABEL_LENGTH)
    282     {
    283       char new_id [4096];
    284       char *return_id;
    285 
    286       strcpy (new_id, base_id);
    287 
    288       /* Shorten it.  */
    289       strcpy (new_id, shorten_identifier (new_id));
    290 
    291       /* Prepend back the prefix if there was one.  */
    292       if (prefix_dotdot)
    293         {
    294           memmove (&new_id [prefix_dotdot], new_id, strlen (new_id) + 1);
    295           strncpy (new_id, prefix, prefix_dotdot);
    296         }
    297 
    298       /* Append back the suffix if there was one.  */
    299       if (strlen (suffix))
    300 	strcat (new_id, suffix);
    301 
    302       /* Save it on the heap and return.  */
    303       return_id = xmalloc (strlen (new_id) + 1);
    304       strcpy (return_id, new_id);
    305 
    306       return return_id;
    307     }
    308   else
    309     return id;
    310 }
    311 
    312 /* The code below implements a mechanism for truncating long
    313    identifiers to an arbitrary length (set by MAX_LABEL_LENGTH).
    314 
    315    It attempts to make each truncated identifier unique by replacing
    316    part of the identifier with an encoded 32-bit CRC and an associated
    317    checksum (the checksum is used as a way to determine that the name
    318    was truncated).
    319 
    320    Note that both a portion of the start and of the end of the
    321    identifier may be kept.  The macro ID_SUFFIX_LENGTH will return the
    322    number of characters in the suffix of the identifier that should be
    323    kept.
    324 
    325    The portion of the identifier that is going to be removed is
    326    checksummed.  The checksum is then encoded as a 5-character string,
    327    the characters of which are then summed.  This sum is then encoded
    328    as a 3-character string.  Finally, the original length of the
    329    identifier is encoded as a 3-character string.
    330 
    331    These three strings are then concatenated together (along with an _h
    332    which further designates that the name was truncated):
    333 
    334    "original_identifier"_haaaaabbbccc
    335 
    336    aaaaa = 32-bit CRC
    337    bbb = length of original identifier
    338    ccc = sum of 32-bit CRC characters
    339 
    340    The resulting identifier will be MAX_LABEL_LENGTH characters long.
    341 
    342    */
    343 
    344 
    345 /* Table used to convert an integer into a string.  */
    346 
    347 static const char codings[] = {
    348   'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
    349   'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    350   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
    351   'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
    352   '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_'};
    353 
    354 /* The number of codings in the above table.  */
    355 static const int number_of_codings = sizeof (codings) / sizeof (char);
    356 
    357 /* Table used by decode_16 () to convert an encoded string back into
    358    an integer.  */
    359 static char decodings[256];
    360 
    361 /* Table used by the crc32 function to calcuate the checksum.  */
    362 static unsigned int crc32_table[256] = {0, 0};
    363 
    364 /* Given a string in BUF, calculate a 32-bit CRC for it.
    365 
    366    This is used as a reasonably unique hash for the given string.  */
    367 
    368 static unsigned int
    369 crc32 (unsigned char *buf, int len)
    370 {
    371   unsigned int crc = 0xffffffff;
    372 
    373   if (! crc32_table[1])
    374     {
    375       /* Initialize the CRC table and the decoding table. */
    376       int i, j;
    377       unsigned int c;
    378 
    379       for (i = 0; i < 256; i++)
    380 	{
    381 	  for (c = i << 24, j = 8; j > 0; --j)
    382 	    c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
    383 	  crc32_table[i] = c;
    384 	  decodings[i] = 0;
    385 	}
    386       for (i = 0; i < number_of_codings; i++)
    387 	decodings[codings[i] & 255] = i;
    388     }
    389 
    390   while (len--)
    391     {
    392       crc = (crc << 8) ^ crc32_table[(crc >> 24) ^ *buf];
    393       buf++;
    394     }
    395   return crc;
    396 }
    397 
    398 /* Encode the lower 32 bits of VALUE as a 5-character string.  */
    399 
    400 static char *
    401 encode_32 (unsigned int value)
    402 {
    403   static char res[6];
    404   int x;
    405 
    406   res[5] = 0;
    407   for(x = 0; x < 5; x++)
    408     {
    409       res[x] = codings[value % number_of_codings];
    410       value = value / number_of_codings;
    411     }
    412   return res;
    413 }
    414 
    415 /* Encode the lower 16 bits of VALUE as a 3-character string.  */
    416 
    417 static char *
    418 encode_16 (unsigned int value)
    419 {
    420   static char res[4];
    421   int x;
    422 
    423   res[3] = 0;
    424   for(x = 0; x < 3; x++)
    425     {
    426       res[x] = codings[value % number_of_codings];
    427       value = value / number_of_codings;
    428     }
    429   return res;
    430 }
    431 
    432 /* Convert the encoded string obtained from encode_16 () back into a
    433    16-bit integer.  */
    434 
    435 static int
    436 decode_16 (const char *string)
    437 {
    438   return decodings[(int) string[2]] * number_of_codings * number_of_codings
    439     + decodings[(int) string[1]] * number_of_codings
    440     + decodings[(int) string[0]];
    441 }
    442 
    443 /* ID_SUFFIX_LENGTH is used to determine how many characters in the
    444    suffix of the identifier are to be preserved, if any.  */
    445 
    446 #ifndef ID_SUFFIX_LENGTH
    447 #define ID_SUFFIX_LENGTH(ID) (0)
    448 #endif
    449 
    450 /* Return a reasonably-unique version of NAME that is less than or
    451    equal to MAX_LABEL_LENGTH characters long.  The string returned from
    452    this function may be a copy of NAME; the function will never
    453    actually modify the contents of NAME.  */
    454 
    455 static char newname[MAX_LABEL_LENGTH + 1];
    456 
    457 static char *
    458 shorten_identifier (char *name)
    459 {
    460   int crc, len, sum, x, final_len;
    461   char *crc_chars;
    462   int suffix_length = ID_SUFFIX_LENGTH (name);
    463 
    464   if ((len = strlen (name)) <= MAX_LABEL_LENGTH)
    465     return name;
    466 
    467   final_len = MAX_LABEL_LENGTH - 2 - 5 - 3 - 3 - suffix_length;
    468   crc = crc32 ((unsigned char *)name + final_len,
    469 	       len - final_len - suffix_length);
    470   crc_chars = encode_32 (crc);
    471   sum = 0;
    472   for (x = 0; x < 5; x++)
    473     sum += crc_chars [x];
    474   strncpy (newname, name, final_len);
    475   newname [MAX_LABEL_LENGTH] = 0;
    476   /* Now append the suffix of the original identifier, if any.  */
    477   if (suffix_length)
    478   strncpy (newname + MAX_LABEL_LENGTH - suffix_length,
    479 	   name + len - suffix_length,
    480 	   suffix_length);
    481   strncpy (newname + final_len, "_h", 2);
    482   strncpy (newname + final_len + 2 , crc_chars, 5);
    483   strncpy (newname + final_len + 2 + 5, encode_16 (len), 3);
    484   strncpy (newname + final_len + 2 + 5 + 3, encode_16 (sum), 3);
    485   if (!is_truncated_identifier (newname))
    486     abort ();
    487   return newname;
    488 }
    489 
    490 /* Determine whether or not ID is a truncated identifier, and return a
    491    non-zero value if it is.  */
    492 
    493 static int
    494 is_truncated_identifier (char *id)
    495 {
    496   char *ptr;
    497   int len = strlen (id);
    498   /* If it's not exactly MAX_LABEL_LENGTH characters long, it can't be
    499      a truncated identifier.  */
    500   if (len != MAX_LABEL_LENGTH)
    501     return 0;
    502 
    503   /* Start scanning backwards for a _h.  */
    504   len = len - 3 - 3 - 5 - 2;
    505   ptr = id + len;
    506   while (ptr >= id)
    507     {
    508       if (ptr[0] == '_' && ptr[1] == 'h')
    509 	{
    510 	  /* Now see if the sum encoded in the identifer matches.  */
    511 	  int x, sum;
    512 	  sum = 0;
    513 	  for (x = 0; x < 5; x++)
    514 	    sum += ptr[x + 2];
    515 	  /* If it matches, this is probably a truncated identifier.  */
    516 	  if (sum == decode_16 (ptr + 5 + 2 + 3))
    517 	    return 1;
    518 	}
    519       ptr--;
    520     }
    521   return 0;
    522 }
    523 
    524 /* end of obj-evax.c */
    525