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