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