1 /* obj-evax.c - EVAX (openVMS/Alpha) object file format.
2    Copyright (C) 1996-2014 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 
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 
obj_read_begin_hook()45 void obj_read_begin_hook () {}
46 
47 /* Handle the weak specific pseudo-op.  */
48 
49 static void
s_evax_weak(int ignore ATTRIBUTE_UNUSED)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
evax_symbol_new_hook(symbolS * sym)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
evax_frob_symbol(symbolS * sym,int * punt)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
evax_frob_file_before_adjust(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
evax_frob_file_before_fix(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 *
evax_shorten_name(char * id)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
crc32(unsigned char * buf,int len)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 *
encode_32(unsigned int value)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 *
encode_16(unsigned int value)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
decode_16(const char * string)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 *
shorten_identifier(char * name)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
is_truncated_identifier(char * id)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