1 /* obj-evax.c - EVAX (openVMS/Alpha) object file format.
2 Copyright (C) 1996-2018 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.
7 This file is part of GAS, the GNU Assembler
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)
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.
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. */
24 #define OBJ_HEADER "obj-evax.h"
30 #include "struc-symbol.h"
31 #include "safe-ctype.h"
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 *);
39 const pseudo_typeS obj_pseudo_table
[] =
41 { "weak", s_evax_weak
, 0},
43 }; /* obj_pseudo_table */
45 void obj_read_begin_hook () {}
47 /* Handle the weak specific pseudo-op. */
50 s_evax_weak (int ignore ATTRIBUTE_UNUSED
)
59 stop
= mri_comment_field (&stopc
);
63 c
= get_symbol_name (&name
);
64 symbolP
= symbol_find_or_make (name
);
65 (void) restore_line_pointer (c
);
72 if (*input_line_pointer
== '\n')
79 mri_comment_end (stop
, stopc
);
81 demand_empty_rest_of_line ();
85 evax_symbol_new_hook (symbolS
*sym
)
87 struct evax_private_udata_struct
*udata
;
89 udata
= XNEW (struct evax_private_udata_struct
);
91 udata
->bsym
= symbol_get_bfdsym (sym
);
93 udata
->origname
= xstrdup (S_GET_NAME (sym
));
95 symbol_get_bfdsym(sym
)->udata
.p
= (PTR
) udata
;
99 evax_frob_symbol (symbolS
*sym
, int *punt
)
101 const char *symname
= S_GET_NAME (sym
);
102 int symlen
= strlen (symname
);
103 asymbol
*symbol
= symbol_get_bfdsym (sym
);
106 && strcmp (symname
+ symlen
- 4, "..en") == 0
107 && S_GET_SEGMENT (sym
) == undefined_section
)
109 symbol_clear_used_in_reloc (sym
);
113 else if ((symbol
->flags
& BSF_GLOBAL
) && (symbol
->flags
& BSF_FUNCTION
))
115 struct evax_private_udata_struct
*udata
116 = (struct evax_private_udata_struct
*)symbol
->udata
.p
;
118 /* Fix up equates of function definitions. */
119 while (udata
->enbsym
== NULL
)
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
;
127 as_bad (_("no entry symbol for global function '%s'"), symname
);
130 symbol
= symbol_get_bfdsym (sym
);
132 = ((struct evax_private_udata_struct
*)symbol
->udata
.p
)->enbsym
;
138 evax_frob_file_before_adjust (void)
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;
146 subseg_set (alpha_link_section
, 0);
147 seginfo
= seg_info (alpha_link_section
);
149 /* Handle .linkage fixups. */
150 for (l
= alpha_linkage_fixup_root
; l
!= NULL
; l
= l
->next
)
152 if (S_GET_SEGMENT (l
->fixp
->fx_addsy
) == alpha_link_section
)
154 /* The symbol is defined in the file. The linkage entry decays to
157 fixS
*fixpentry
, *fixppdesc
, *fixtail
;
159 fixtail
= seginfo
->fix_tail
;
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
);
166 fixpentry
= fix_new (l
->fixp
->fx_frag
, l
->fixp
->fx_where
, 8,
167 entry_sym
, l
->fixp
->fx_offset
, 0,
169 fixppdesc
= fix_new (l
->fixp
->fx_frag
, l
->fixp
->fx_where
+ 8, 8,
170 l
->fixp
->fx_addsy
, l
->fixp
->fx_offset
, 0,
172 l
->fixp
->fx_size
= 0;
173 l
->fixp
->fx_done
= 1;
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
)
179 fixppdesc
->fx_next
= l
->fixp
->fx_next
;
180 l
->fixp
->fx_next
= fixpentry
;
181 fixtail
->fx_next
= 0;
182 seginfo
->fix_tail
= fixtail
;
187 /* Assign a linkage index. */
188 ((struct evax_private_udata_struct
*)
189 symbol_get_bfdsym (l
->label
)->udata
.p
)->lkindex
= linkage_index
;
191 l
->fixp
->fx_addnumber
= linkage_index
;
197 subseg_set (current_section
, current_subsec
);
201 evax_frob_file_before_fix (void)
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). */
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
);
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 crunching 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
226 static char *shorten_identifier (char *);
227 static int is_truncated_identifier (char *);
230 evax_shorten_name (char *id
)
232 int prefix_dotdot
= 0;
234 int len
= strlen (id
);
235 int suffix_dotdot
= len
;
239 /* This test may be too conservative. */
240 if (len
<= MAX_LABEL_LENGTH
)
246 /* Check for ..xx suffix and save it. */
247 if (strncmp (&id
[len
-4], "..", 2) == 0)
249 suffix_dotdot
= len
- 4;
250 strncpy (suffix
, &id
[len
-4], 4);
254 /* Check for $<nnn>.. prefix and save it. */
255 if ((id
[0] == '$') && ISDIGIT (id
[1]))
259 for (i
=2; i
< len
; i
++)
261 if (!ISDIGIT (id
[i
]))
263 if (id
[i
] == '.' && id
[i
+1] == '.')
266 strncpy (prefix
, id
, prefix_dotdot
);
267 prefix
[prefix_dotdot
] = 0;
274 /* We only need worry about crunching the base symbol. */
275 base_id
= xmemdup0 (&id
[prefix_dotdot
], suffix_dotdot
- prefix_dotdot
);
277 if (strlen (base_id
) > MAX_LABEL_LENGTH
)
282 strcpy (new_id
, base_id
);
285 strcpy (new_id
, shorten_identifier (new_id
));
287 /* Prepend back the prefix if there was one. */
290 memmove (&new_id
[prefix_dotdot
], new_id
, strlen (new_id
) + 1);
291 strncpy (new_id
, prefix
, prefix_dotdot
);
294 /* Append back the suffix if there was one. */
296 strcat (new_id
, suffix
);
298 /* Save it on the heap and return. */
299 return_id
= xstrdup (new_id
);
307 /* The code below implements a mechanism for truncating long
308 identifiers to an arbitrary length (set by MAX_LABEL_LENGTH).
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
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
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.
326 These three strings are then concatenated together (along with an _h
327 which further designates that the name was truncated):
329 "original_identifier"_haaaaabbbccc
332 bbb = length of original identifier
333 ccc = sum of 32-bit CRC characters
335 The resulting identifier will be MAX_LABEL_LENGTH characters long.
340 /* Table used to convert an integer into a string. */
342 static 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', '_'};
349 /* The number of codings in the above table. */
350 static const int number_of_codings
= sizeof (codings
) / sizeof (char);
352 /* Table used by decode_16 () to convert an encoded string back into
354 static char decodings
[256];
356 /* Table used by the crc32 function to calculate the checksum. */
357 static unsigned int crc32_table
[256] = {0, 0};
359 /* Given a string in BUF, calculate a 32-bit CRC for it.
361 This is used as a reasonably unique hash for the given string. */
364 crc32 (unsigned char *buf
, int len
)
366 unsigned int crc
= 0xffffffff;
368 if (! crc32_table
[1])
370 /* Initialize the CRC table and the decoding table. */
374 for (i
= 0; i
< 256; i
++)
376 for (c
= i
<< 24, j
= 8; j
> 0; --j
)
377 c
= c
& 0x80000000 ? (c
<< 1) ^ 0x04c11db7 : (c
<< 1);
381 for (i
= 0; i
< number_of_codings
; i
++)
382 decodings
[codings
[i
] & 255] = i
;
387 crc
= (crc
<< 8) ^ crc32_table
[(crc
>> 24) ^ *buf
];
393 /* Encode the lower 32 bits of VALUE as a 5-character string. */
396 encode_32 (unsigned int value
)
402 for(x
= 0; x
< 5; x
++)
404 res
[x
] = codings
[value
% number_of_codings
];
405 value
= value
/ number_of_codings
;
410 /* Encode the lower 16 bits of VALUE as a 3-character string. */
413 encode_16 (unsigned int value
)
419 for(x
= 0; x
< 3; x
++)
421 res
[x
] = codings
[value
% number_of_codings
];
422 value
= value
/ number_of_codings
;
427 /* Convert the encoded string obtained from encode_16 () back into a
431 decode_16 (const char *string
)
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]];
438 /* ID_SUFFIX_LENGTH is used to determine how many characters in the
439 suffix of the identifier are to be preserved, if any. */
441 #ifndef ID_SUFFIX_LENGTH
442 #define ID_SUFFIX_LENGTH(ID) (0)
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. */
450 static char newname
[MAX_LABEL_LENGTH
+ 1];
453 shorten_identifier (char *name
)
455 int crc
, len
, sum
, x
, final_len
;
457 int suffix_length
= ID_SUFFIX_LENGTH (name
);
459 if ((len
= strlen (name
)) <= MAX_LABEL_LENGTH
)
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
);
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. */
473 strncpy (newname
+ MAX_LABEL_LENGTH
- suffix_length
,
474 name
+ len
- 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
))
485 /* Determine whether or not ID is a truncated identifier, and return a
486 non-zero value if it is. */
489 is_truncated_identifier (char *id
)
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
)
498 /* Start scanning backwards for a _h. */
499 len
= len
- 3 - 3 - 5 - 2;
503 if (ptr
[0] == '_' && ptr
[1] == 'h')
505 /* Now see if the sum encoded in the identifier matches. */
508 for (x
= 0; x
< 5; x
++)
510 /* If it matches, this is probably a truncated identifier. */
511 if (sum
== decode_16 (ptr
+ 5 + 2 + 3))
519 /* end of obj-evax.c */