1 /* obj-evax.c - EVAX (openVMS/Alpha) object file format.
2    Copyright (C) 1996-2021 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 
obj_read_begin_hook()40 void obj_read_begin_hook () {}
41 
42 /* Handle the weak specific pseudo-op.  */
43 
44 static void
s_evax_weak(int ignore ATTRIBUTE_UNUSED)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
evax_symbol_new_hook(symbolS * sym)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 = (PTR) udata;
91 }
92 
93 void
evax_frob_symbol(symbolS * sym,int * punt)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
evax_frob_file_before_adjust(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
evax_frob_file_before_fix(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 *
evax_shorten_name(char * id)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
crc32(unsigned char * buf,int len)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 *
encode_32(unsigned int value)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 *
encode_16(unsigned int value)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
decode_16(const unsigned char * string)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 *
shorten_identifier(char * name)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
is_truncated_identifier(char * id)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 */
512