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