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