1 /* vms-misc.c -- Miscellaneous functions for VAX (openVMS/VAX) and 2 EVAX (openVMS/Alpha) files. 3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 4 Free Software Foundation, Inc. 5 6 Written by Klaus K"ampf (kkaempf@rmi.de) 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 21 22 #if __STDC__ 23 #include <stdarg.h> 24 #endif 25 26 #include "bfd.h" 27 #include "sysdep.h" 28 #include "bfdlink.h" 29 #include "libbfd.h" 30 31 #include "vms.h" 32 33 static vms_section *add_new_contents PARAMS ((bfd *, sec_ptr)); 34 static int hash_string PARAMS ((const char *)); 35 static asymbol *new_symbol PARAMS ((bfd *, char *)); 36 37 /*-----------------------------------------------------------------------------*/ 38 #if VMS_DEBUG 39 /* debug functions */ 40 41 /* debug function for all vms extensions 42 evaluates environment variable VMS_DEBUG for a 43 numerical value on the first call 44 all error levels below this value are printed 45 46 levels: 47 1 toplevel bfd calls (functions from the bfd vector) 48 2 functions called by bfd calls 49 ... 50 9 almost everything 51 52 level is also indentation level. Indentation is performed 53 if level > 0 54 */ 55 56 #if __STDC__ 57 void 58 _bfd_vms_debug (int level, char *format, ...) 59 { 60 static int min_level = -1; 61 static FILE *output = NULL; 62 char *eptr; 63 va_list args; 64 int abslvl = (level > 0)?level:-level; 65 66 if (min_level == -1) 67 { 68 if ((eptr = getenv("VMS_DEBUG")) != NULL) 69 { 70 min_level = atoi(eptr); 71 output = stderr; 72 } 73 else 74 min_level = 0; 75 } 76 if (output == NULL) 77 return; 78 if (abslvl > min_level) 79 return; 80 81 while (--level>0) 82 fprintf (output, " "); 83 va_start(args, format); 84 vfprintf (output, format, args); 85 fflush(output); 86 va_end(args); 87 88 return; 89 } 90 91 #else /* not __STDC__ */ 92 93 void 94 _bfd_vms_debug (level, format, a1, a2, a3, a4, a5, a6) 95 int level; 96 char *format; 97 long a1; long a2; long a3; 98 long a4; long a5; long a6; 99 { 100 static int min_level = -1; 101 static FILE *output = NULL; 102 char *eptr; 103 104 if (min_level == -1) 105 { 106 if ((eptr = getenv("VMS_DEBUG")) != NULL) 107 { 108 min_level = atoi(eptr); 109 output = stderr; 110 } 111 else 112 min_level = 0; 113 } 114 if (output == NULL) 115 return; 116 if (level > min_level) 117 return; 118 119 while (--level>0) 120 fprintf (output, " "); 121 fprintf (output, format, a1, a2, a3, a4, a5, a6); 122 fflush(output); 123 124 return; 125 } 126 #endif /* __STDC__ */ 127 128 /* a debug function 129 hex dump 'size' bytes starting at 'ptr' */ 130 131 void 132 _bfd_hexdump (level, ptr, size, offset) 133 int level; 134 unsigned char *ptr; 135 int size; 136 int offset; 137 { 138 unsigned char *lptr = ptr; 139 int count = 0; 140 long start = offset; 141 142 while (size-- > 0) 143 { 144 if ((count%16) == 0) 145 vms_debug (level, "%08lx:", start); 146 vms_debug (-level, " %02x", *ptr++); 147 count++; 148 start++; 149 if (size == 0) 150 { 151 while ((count%16) != 0) 152 { 153 vms_debug (-level, " "); 154 count++; 155 } 156 } 157 if ((count%16) == 0) 158 { 159 vms_debug (-level, " "); 160 while (lptr < ptr) 161 { 162 vms_debug (-level, "%c", (*lptr < 32)?'.':*lptr); 163 lptr++; 164 } 165 vms_debug (-level, "\n"); 166 } 167 } 168 if ((count%16) != 0) 169 vms_debug (-level, "\n"); 170 171 return; 172 } 173 #endif 174 175 /* hash functions 176 177 These are needed when reading an object file. */ 178 179 /* allocate new vms_hash_entry 180 keep the symbol name and a pointer to the bfd symbol in the table */ 181 182 struct bfd_hash_entry * 183 _bfd_vms_hash_newfunc (entry, table, string) 184 struct bfd_hash_entry *entry; 185 struct bfd_hash_table *table; 186 const char *string; 187 { 188 vms_symbol_entry *ret; 189 190 #if VMS_DEBUG 191 vms_debug (5, "_bfd_vms_hash_newfunc(%p, %p, %s)\n", entry, table, string); 192 #endif 193 194 if (entry == (struct bfd_hash_entry *)NULL) 195 { 196 ret = (vms_symbol_entry *) 197 bfd_hash_allocate (table, sizeof (vms_symbol_entry)); 198 if (ret == (vms_symbol_entry *) NULL) 199 { 200 bfd_set_error (bfd_error_no_memory); 201 return (struct bfd_hash_entry *)NULL; 202 } 203 entry = (struct bfd_hash_entry *) ret; 204 } 205 206 /* Call the allocation method of the base class. */ 207 208 ret = (vms_symbol_entry *) bfd_hash_newfunc (entry, table, string); 209 #if VMS_DEBUG 210 vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret); 211 #endif 212 213 ret->symbol = (asymbol *)NULL; 214 215 return (struct bfd_hash_entry *)ret; 216 } 217 218 /* object file input functions */ 219 220 /* Return type and length from record header (buf) on Alpha. */ 221 222 void 223 _bfd_vms_get_header_values (abfd, buf, type, length) 224 bfd *abfd ATTRIBUTE_UNUSED; 225 unsigned char *buf; 226 int *type; 227 int *length; 228 { 229 if (type != 0) 230 *type = bfd_getl16 (buf); 231 buf += 2; 232 if (length != 0) 233 *length = bfd_getl16 (buf); 234 235 #if VMS_DEBUG 236 vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0)); 237 #endif 238 239 return; 240 } 241 242 /* Get next record from object file to vms_buf 243 set PRIV(buf_size) and return it 244 245 this is a little tricky since it should be portable. 246 247 the openVMS object file has 'variable length' which means that 248 read() returns data in chunks of (hopefully) correct and expected 249 size. The linker (and other tools on vms) depend on that. Unix doesn't 250 know about 'formatted' files, so reading and writing such an object 251 file in a unix environment is not trivial. 252 253 With the tool 'file' (available on all vms ftp sites), one 254 can view and change the attributes of a file. Changing from 255 'variable length' to 'fixed length, 512 bytes' reveals the 256 record length at the first 2 bytes of every record. The same 257 happens during the transfer of object files from vms to unix, 258 at least with ucx, dec's implementation of tcp/ip. 259 260 The vms format repeats the length at bytes 2 & 3 of every record. 261 262 On the first call (file_format == FF_UNKNOWN) we check if 263 the first and the third byte pair (!) of the record match. 264 If they do it's an object file in an unix environment or with 265 wrong attributes (FF_FOREIGN), else we should be in a vms 266 environment where read() returns the record size (FF_NATIVE). 267 268 reading is always done in 2 steps. 269 first just the record header is read and the length extracted 270 by get_header_values 271 then the read buffer is adjusted and the remaining bytes are 272 read in. 273 274 all file i/o is always done on even file positions */ 275 276 int 277 _bfd_vms_get_record (abfd) 278 bfd *abfd; 279 { 280 int test_len, test_start, remaining; 281 unsigned char *vms_buf; 282 283 #if VMS_DEBUG 284 vms_debug (8, "_bfd_vms_get_record\n"); 285 #endif 286 287 /* minimum is 6 bytes on Alpha 288 (2 bytes length, 2 bytes record id, 2 bytes length repeated) 289 290 on VAX there's no length information in the record 291 so start with OBJ_S_C_MAXRECSIZ */ 292 293 if (PRIV (buf_size) == 0) 294 { 295 bfd_size_type amt; 296 297 if (PRIV (is_vax)) 298 { 299 amt = OBJ_S_C_MAXRECSIZ; 300 PRIV (file_format) = FF_VAX; 301 } 302 else 303 amt = 6; 304 PRIV (vms_buf) = (unsigned char *) bfd_malloc (amt); 305 PRIV (buf_size) = amt; 306 } 307 308 vms_buf = PRIV (vms_buf); 309 310 if (vms_buf == 0) 311 return -1; 312 313 switch (PRIV (file_format)) 314 { 315 case FF_UNKNOWN: 316 case FF_FOREIGN: 317 test_len = 6; /* probe 6 bytes */ 318 test_start = 2; /* where the record starts */ 319 break; 320 321 case FF_NATIVE: 322 test_len = 4; 323 test_start = 0; 324 break; 325 326 default: 327 case FF_VAX: 328 test_len = 0; 329 test_start = 0; 330 break; 331 } 332 333 /* skip odd alignment byte */ 334 335 if (bfd_tell (abfd) & 1) 336 { 337 if (bfd_bread (PRIV (vms_buf), (bfd_size_type) 1, abfd) != 1) 338 { 339 bfd_set_error (bfd_error_file_truncated); 340 return 0; 341 } 342 } 343 344 /* read the record header on Alpha. */ 345 346 if ((test_len != 0) 347 && (bfd_bread (PRIV (vms_buf), (bfd_size_type) test_len, abfd) 348 != (bfd_size_type) test_len)) 349 { 350 bfd_set_error (bfd_error_file_truncated); 351 return 0; 352 } 353 354 /* check file format on first call */ 355 356 if (PRIV (file_format) == FF_UNKNOWN) 357 { /* record length repeats ? */ 358 if (vms_buf[0] == vms_buf[4] 359 && vms_buf[1] == vms_buf[5]) 360 { 361 PRIV (file_format) = FF_FOREIGN; /* Y: foreign environment */ 362 test_start = 2; 363 } 364 else 365 { 366 PRIV (file_format) = FF_NATIVE; /* N: native environment */ 367 test_start = 0; 368 } 369 } 370 371 if (PRIV (is_vax)) 372 { 373 PRIV (rec_length) = bfd_bread (vms_buf, (bfd_size_type) PRIV (buf_size), 374 abfd); 375 if (PRIV (rec_length) <= 0) 376 { 377 bfd_set_error (bfd_error_file_truncated); 378 return 0; 379 } 380 PRIV (vms_rec) = vms_buf; 381 } 382 else /* Alpha */ 383 { 384 /* extract vms record length */ 385 386 _bfd_vms_get_header_values (abfd, vms_buf + test_start, NULL, 387 &PRIV (rec_length)); 388 389 if (PRIV (rec_length) <= 0) 390 { 391 bfd_set_error (bfd_error_file_truncated); 392 return 0; 393 } 394 395 /* that's what the linker manual says */ 396 397 if (PRIV (rec_length) > EOBJ_S_C_MAXRECSIZ) 398 { 399 bfd_set_error (bfd_error_file_truncated); 400 return 0; 401 } 402 403 /* adjust the buffer */ 404 405 if (PRIV (rec_length) > PRIV (buf_size)) 406 { 407 PRIV (vms_buf) = ((unsigned char *) 408 bfd_realloc (vms_buf, 409 (bfd_size_type) PRIV (rec_length))); 410 vms_buf = PRIV (vms_buf); 411 if (vms_buf == 0) 412 return -1; 413 PRIV (buf_size) = PRIV (rec_length); 414 } 415 416 /* read the remaining record */ 417 418 remaining = PRIV (rec_length) - test_len + test_start; 419 420 #if VMS_DEBUG 421 vms_debug (10, "bfd_bread remaining %d\n", remaining); 422 #endif 423 if (bfd_bread (vms_buf + test_len, (bfd_size_type) remaining, abfd) != 424 (bfd_size_type) remaining) 425 { 426 bfd_set_error (bfd_error_file_truncated); 427 return 0; 428 } 429 PRIV (vms_rec) = vms_buf + test_start; 430 } 431 432 #if VMS_DEBUG 433 vms_debug (11, "bfd_bread rec_length %d\n", PRIV (rec_length)); 434 #endif 435 436 return PRIV (rec_length); 437 } 438 439 /* get next vms record from file 440 update vms_rec and rec_length to new (remaining) values */ 441 442 int 443 _bfd_vms_next_record (abfd) 444 bfd *abfd; 445 { 446 #if VMS_DEBUG 447 vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n", 448 PRIV (rec_length), PRIV (rec_size)); 449 #endif 450 451 if (PRIV (rec_length) > 0) 452 { 453 PRIV (vms_rec) += PRIV (rec_size); 454 } 455 else 456 { 457 if (_bfd_vms_get_record (abfd) <= 0) 458 return -1; 459 } 460 461 if (!PRIV (vms_rec) || !PRIV (vms_buf) 462 || PRIV (vms_rec) >= (PRIV (vms_buf) + PRIV (buf_size))) 463 return -1; 464 465 if (PRIV (is_vax)) 466 { 467 PRIV (rec_type) = *(PRIV (vms_rec)); 468 PRIV (rec_size) = PRIV (rec_length); 469 } 470 else 471 { 472 _bfd_vms_get_header_values (abfd, PRIV (vms_rec), &PRIV (rec_type), 473 &PRIV (rec_size)); 474 } 475 PRIV (rec_length) -= PRIV (rec_size); 476 477 #if VMS_DEBUG 478 vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n", 479 PRIV (vms_rec), PRIV (rec_size), PRIV (rec_length), 480 PRIV (rec_type)); 481 #endif 482 483 return PRIV (rec_type); 484 } 485 486 /* Copy sized string (string with fixed length) to new allocated area 487 size is string length (size of record) */ 488 489 char * 490 _bfd_vms_save_sized_string (str, size) 491 unsigned char *str; 492 int size; 493 { 494 char *newstr = bfd_malloc ((bfd_size_type) size + 1); 495 496 if (newstr == NULL) 497 return 0; 498 strncpy (newstr, (char *) str, (size_t) size); 499 newstr[size] = 0; 500 501 return newstr; 502 } 503 504 /* Copy counted string (string with length at first byte) to new allocated area 505 ptr points to length byte on entry */ 506 507 char * 508 _bfd_vms_save_counted_string (ptr) 509 unsigned char *ptr; 510 { 511 int len = *ptr++; 512 513 return _bfd_vms_save_sized_string (ptr, len); 514 } 515 516 /* stack routines for vms ETIR commands */ 517 518 /* Push value and section index */ 519 520 void 521 _bfd_vms_push (abfd, val, psect) 522 bfd *abfd; 523 uquad val; 524 int psect; 525 { 526 static int last_psect; 527 528 #if VMS_DEBUG 529 vms_debug (4, "<push %016lx(%d) at %d>\n", val, psect, PRIV (stackptr)); 530 #endif 531 532 if (psect >= 0) 533 last_psect = psect; 534 535 PRIV (stack[PRIV (stackptr)]).value = val; 536 PRIV (stack[PRIV (stackptr)]).psect = last_psect; 537 PRIV (stackptr)++; 538 if (PRIV (stackptr) >= STACKSIZE) 539 { 540 bfd_set_error (bfd_error_bad_value); 541 (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr)); 542 exit (1); 543 } 544 return; 545 } 546 547 /* Pop value and section index */ 548 549 uquad 550 _bfd_vms_pop (abfd, psect) 551 bfd *abfd; 552 int *psect; 553 { 554 uquad value; 555 556 if (PRIV (stackptr) == 0) 557 { 558 bfd_set_error (bfd_error_bad_value); 559 (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop")); 560 exit (1); 561 } 562 PRIV (stackptr)--; 563 value = PRIV (stack[PRIV (stackptr)]).value; 564 if ((psect != NULL) && (PRIV (stack[PRIV (stackptr)]).psect >= 0)) 565 *psect = PRIV (stack[PRIV (stackptr)]).psect; 566 567 #if VMS_DEBUG 568 vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV (stack[PRIV (stackptr)]).psect); 569 #endif 570 571 return value; 572 } 573 574 /* object file output functions */ 575 576 /* GAS tends to write sections in little chunks (bfd_set_section_contents) 577 which we can't use directly. So we save the little chunks in linked 578 lists (one per section) and write them later. */ 579 580 /* Add a new vms_section structure to vms_section_table 581 - forward chaining - */ 582 583 static vms_section * 584 add_new_contents (abfd, section) 585 bfd *abfd; 586 sec_ptr section; 587 { 588 vms_section *sptr, *newptr; 589 590 sptr = PRIV (vms_section_table)[section->index]; 591 if (sptr != NULL) 592 return sptr; 593 594 newptr = (vms_section *) bfd_alloc (abfd, 595 (bfd_size_type) sizeof (vms_section)); 596 if (newptr == (vms_section *) NULL) 597 return NULL; 598 newptr->contents = (unsigned char *) bfd_alloc (abfd, section->_raw_size); 599 if (newptr->contents == (unsigned char *) NULL) 600 return NULL; 601 newptr->offset = 0; 602 newptr->size = section->_raw_size; 603 newptr->next = 0; 604 PRIV (vms_section_table)[section->index] = newptr; 605 return newptr; 606 } 607 608 /* Save section data & offset to a vms_section structure 609 vms_section_table[] holds the vms_section chain. */ 610 611 bfd_boolean 612 _bfd_save_vms_section (abfd, section, data, offset, count) 613 bfd *abfd; 614 sec_ptr section; 615 const PTR data; 616 file_ptr offset; 617 bfd_size_type count; 618 { 619 vms_section *sptr; 620 621 if (section->index >= VMS_SECTION_COUNT) 622 { 623 bfd_set_error (bfd_error_nonrepresentable_section); 624 return FALSE; 625 } 626 if (count == (bfd_size_type)0) 627 return TRUE; 628 sptr = add_new_contents (abfd, section); 629 if (sptr == NULL) 630 return FALSE; 631 memcpy (sptr->contents + offset, data, (size_t) count); 632 633 return TRUE; 634 } 635 636 /* Get vms_section pointer to saved contents for section # index */ 637 638 vms_section * 639 _bfd_get_vms_section (abfd, index) 640 bfd *abfd; 641 int index; 642 { 643 if (index >= VMS_SECTION_COUNT) 644 { 645 bfd_set_error (bfd_error_nonrepresentable_section); 646 return NULL; 647 } 648 return PRIV (vms_section_table)[index]; 649 } 650 651 /* Object output routines */ 652 653 /* Begin new record or record header 654 write 2 bytes rectype 655 write 2 bytes record length (filled in at flush) 656 write 2 bytes header type (ommitted if rechead == -1) */ 657 658 void 659 _bfd_vms_output_begin (abfd, rectype, rechead) 660 bfd *abfd; 661 int rectype; 662 int rechead; 663 { 664 #if VMS_DEBUG 665 vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype, 666 rechead); 667 #endif 668 669 _bfd_vms_output_short (abfd, (unsigned int) rectype); 670 671 /* save current output position to fill in length later */ 672 673 if (PRIV (push_level) > 0) 674 PRIV (length_pos) = PRIV (output_size); 675 676 #if VMS_DEBUG 677 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n", 678 PRIV (length_pos)); 679 #endif 680 681 _bfd_vms_output_short (abfd, 0); /* placeholder for length */ 682 683 if (rechead != -1) 684 _bfd_vms_output_short (abfd, (unsigned int) rechead); 685 686 return; 687 } 688 689 /* Set record/subrecord alignment */ 690 691 void 692 _bfd_vms_output_alignment (abfd, alignto) 693 bfd *abfd; 694 int alignto; 695 { 696 #if VMS_DEBUG 697 vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto); 698 #endif 699 700 PRIV (output_alignment) = alignto; 701 return; 702 } 703 704 /* Prepare for subrecord fields */ 705 706 void 707 _bfd_vms_output_push (abfd) 708 bfd *abfd; 709 { 710 #if VMS_DEBUG 711 vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV (output_size)); 712 #endif 713 714 PRIV (push_level)++; 715 PRIV (pushed_size) = PRIV (output_size); 716 return; 717 } 718 719 /* End of subrecord fields */ 720 721 void 722 _bfd_vms_output_pop (abfd) 723 bfd *abfd; 724 { 725 #if VMS_DEBUG 726 vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV (pushed_size)); 727 #endif 728 729 _bfd_vms_output_flush (abfd); 730 PRIV (length_pos) = 2; 731 732 #if VMS_DEBUG 733 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV (length_pos)); 734 #endif 735 736 PRIV (pushed_size) = 0; 737 PRIV (push_level)--; 738 return; 739 } 740 741 /* Flush unwritten output, ends current record */ 742 743 void 744 _bfd_vms_output_flush (abfd) 745 bfd *abfd; 746 { 747 int real_size = PRIV (output_size); 748 int aligncount; 749 int length; 750 751 #if VMS_DEBUG 752 vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n", 753 real_size, PRIV (pushed_size), PRIV (length_pos)); 754 #endif 755 756 if (PRIV (push_level) > 0) 757 length = real_size - PRIV (pushed_size); 758 else 759 length = real_size; 760 761 if (length == 0) 762 return; 763 aligncount = (PRIV (output_alignment) 764 - (length % PRIV (output_alignment))) % PRIV (output_alignment); 765 766 #if VMS_DEBUG 767 vms_debug (6, "align: adding %d bytes\n", aligncount); 768 #endif 769 770 while (aligncount-- > 0) 771 { 772 PRIV (output_buf)[real_size++] = 0; 773 #if 0 774 /* this is why I *love* vms: inconsistency :-} 775 alignment is added to the subrecord length 776 but not to the record length */ 777 if (PRIV (push_level) > 0) 778 #endif 779 length++; 780 } 781 782 /* put length to buffer */ 783 PRIV (output_size) = PRIV (length_pos); 784 _bfd_vms_output_short (abfd, (unsigned int) length); 785 786 if (PRIV (push_level) == 0) 787 { 788 #ifndef VMS 789 /* write length first, see FF_FOREIGN in the input routines */ 790 fwrite (PRIV (output_buf) + 2, 2, 1, (FILE *) abfd->iostream); 791 #endif 792 fwrite (PRIV (output_buf), (size_t) real_size, 1, 793 (FILE *) abfd->iostream); 794 795 PRIV (output_size) = 0; 796 } 797 else 798 { 799 PRIV (output_size) = real_size; 800 PRIV (pushed_size) = PRIV (output_size); 801 } 802 803 return; 804 } 805 806 /* End record output */ 807 808 void 809 _bfd_vms_output_end (abfd) 810 bfd *abfd; 811 { 812 #if VMS_DEBUG 813 vms_debug (6, "_bfd_vms_output_end\n"); 814 #endif 815 816 _bfd_vms_output_flush (abfd); 817 818 return; 819 } 820 821 /* check remaining buffer size 822 823 return what's left. */ 824 825 int 826 _bfd_vms_output_check (abfd, size) 827 bfd *abfd; 828 int size; 829 { 830 #if VMS_DEBUG 831 vms_debug (6, "_bfd_vms_output_check(%d)\n", size); 832 #endif 833 834 return (MAX_OUTREC_SIZE - (PRIV (output_size) + size + MIN_OUTREC_LUFT)); 835 } 836 837 /* Output byte (8 bit) value */ 838 839 void 840 _bfd_vms_output_byte (abfd, value) 841 bfd *abfd; 842 unsigned int value; 843 { 844 #if VMS_DEBUG 845 vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value); 846 #endif 847 848 bfd_put_8 (abfd, value & 0xff, PRIV (output_buf) + PRIV (output_size)); 849 PRIV (output_size) += 1; 850 return; 851 } 852 853 /* Output short (16 bit) value */ 854 855 void 856 _bfd_vms_output_short (abfd, value) 857 bfd *abfd; 858 unsigned int value; 859 { 860 #if VMS_DEBUG 861 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value); 862 #endif 863 864 bfd_put_16 (abfd, (bfd_vma) value & 0xffff, 865 PRIV (output_buf) + PRIV (output_size)); 866 PRIV (output_size) += 2; 867 return; 868 } 869 870 /* Output long (32 bit) value */ 871 872 void 873 _bfd_vms_output_long (abfd, value) 874 bfd *abfd; 875 unsigned long value; 876 { 877 #if VMS_DEBUG 878 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value); 879 #endif 880 881 bfd_put_32 (abfd, (bfd_vma) value, PRIV (output_buf) + PRIV (output_size)); 882 PRIV (output_size) += 4; 883 return; 884 } 885 886 /* Output quad (64 bit) value */ 887 888 void 889 _bfd_vms_output_quad (abfd, value) 890 bfd *abfd; 891 uquad value; 892 { 893 #if VMS_DEBUG 894 vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value); 895 #endif 896 897 bfd_put_64(abfd, value, PRIV (output_buf) + PRIV (output_size)); 898 PRIV (output_size) += 8; 899 return; 900 } 901 902 /* Output c-string as counted string */ 903 904 void 905 _bfd_vms_output_counted (abfd, value) 906 bfd *abfd; 907 char *value; 908 { 909 int len; 910 911 #if VMS_DEBUG 912 vms_debug (6, "_bfd_vms_output_counted(%s)\n", value); 913 #endif 914 915 len = strlen (value); 916 if (len == 0) 917 { 918 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes")); 919 return; 920 } 921 if (len > 255) 922 { 923 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes")); 924 return; 925 } 926 _bfd_vms_output_byte (abfd, (unsigned int) len & 0xff); 927 _bfd_vms_output_dump (abfd, (unsigned char *)value, len); 928 } 929 930 /* Output character area */ 931 932 void 933 _bfd_vms_output_dump (abfd, data, length) 934 bfd *abfd; 935 unsigned char *data; 936 int length; 937 { 938 #if VMS_DEBUG 939 vms_debug (6, "_bfd_vms_output_dump(%d)\n", length); 940 #endif 941 942 if (length == 0) 943 return; 944 945 memcpy (PRIV (output_buf) + PRIV (output_size), data, (size_t) length); 946 PRIV (output_size) += length; 947 948 return; 949 } 950 951 /* Output count bytes of value */ 952 953 void 954 _bfd_vms_output_fill (abfd, value, count) 955 bfd *abfd; 956 int value; 957 int count; 958 { 959 #if VMS_DEBUG 960 vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count); 961 #endif 962 963 if (count == 0) 964 return; 965 memset (PRIV (output_buf) + PRIV (output_size), value, (size_t) count); 966 PRIV (output_size) += count; 967 968 return; 969 } 970 971 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/ 972 973 static int 974 hash_string (ptr) 975 const char *ptr; 976 { 977 register const unsigned char *p = (unsigned char *) ptr; 978 register const unsigned char *end = p + strlen (ptr); 979 register unsigned char c; 980 register int hash = 0; 981 982 while (p != end) 983 { 984 c = *p++; 985 hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c); 986 } 987 return hash; 988 } 989 990 /* Generate a length-hashed VMS symbol name (limited to maxlen chars). */ 991 992 char * 993 _bfd_vms_length_hash_symbol (abfd, in, maxlen) 994 bfd *abfd; 995 const char *in; 996 int maxlen; 997 { 998 long int result; 999 int in_len; 1000 char *new_name; 1001 const char *old_name; 1002 int i; 1003 static char outbuf[EOBJ_S_C_SYMSIZ+1]; 1004 char *out = outbuf; 1005 1006 #if VMS_DEBUG 1007 vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in); 1008 #endif 1009 1010 if (maxlen > EOBJ_S_C_SYMSIZ) 1011 maxlen = EOBJ_S_C_SYMSIZ; 1012 1013 new_name = out; /* save this for later. */ 1014 1015 /* We may need to truncate the symbol, save the hash for later. */ 1016 1017 in_len = strlen (in); 1018 1019 result = (in_len > maxlen) ? hash_string (in) : 0; 1020 1021 old_name = in; 1022 1023 /* Do the length checking. */ 1024 1025 if (in_len <= maxlen) 1026 { 1027 i = in_len; 1028 } 1029 else 1030 { 1031 if (PRIV (flag_hash_long_names)) 1032 i = maxlen-9; 1033 else 1034 i = maxlen; 1035 } 1036 1037 strncpy (out, in, (size_t) i); 1038 in += i; 1039 out += i; 1040 1041 if ((in_len > maxlen) 1042 && PRIV (flag_hash_long_names)) 1043 sprintf (out, "_%08lx", result); 1044 else 1045 *out = 0; 1046 1047 #if VMS_DEBUG 1048 vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf); 1049 #endif 1050 1051 if (in_len > maxlen 1052 && PRIV (flag_hash_long_names) 1053 && PRIV (flag_show_after_trunc)) 1054 printf (_("Symbol %s replaced by %s\n"), old_name, new_name); 1055 1056 return outbuf; 1057 } 1058 1059 /* Allocate and initialize a new symbol. */ 1060 1061 static asymbol * 1062 new_symbol (abfd, name) 1063 bfd *abfd; 1064 char *name; 1065 { 1066 asymbol *symbol; 1067 1068 #if VMS_DEBUG 1069 _bfd_vms_debug (7, "new_symbol %s\n", name); 1070 #endif 1071 1072 symbol = bfd_make_empty_symbol (abfd); 1073 if (symbol == 0) 1074 return symbol; 1075 symbol->name = name; 1076 symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME); 1077 1078 return symbol; 1079 } 1080 1081 /* Allocate and enter a new private symbol. */ 1082 1083 vms_symbol_entry * 1084 _bfd_vms_enter_symbol (abfd, name) 1085 bfd *abfd; 1086 char *name; 1087 { 1088 vms_symbol_entry *entry; 1089 1090 #if VMS_DEBUG 1091 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name); 1092 #endif 1093 1094 entry = (vms_symbol_entry *) 1095 bfd_hash_lookup (PRIV (vms_symbol_table), name, FALSE, FALSE); 1096 if (entry == 0) 1097 { 1098 #if VMS_DEBUG 1099 _bfd_vms_debug (8, "creating hash entry for %s\n", name); 1100 #endif 1101 entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table), 1102 name, TRUE, FALSE); 1103 if (entry != 0) 1104 { 1105 asymbol *symbol; 1106 symbol = new_symbol (abfd, name); 1107 if (symbol != 0) 1108 { 1109 entry->symbol = symbol; 1110 PRIV (gsd_sym_count)++; 1111 abfd->symcount++; 1112 } 1113 else 1114 entry = 0; 1115 } 1116 else 1117 (*_bfd_error_handler) (_("failed to enter %s"), name); 1118 } 1119 else 1120 { 1121 #if VMS_DEBUG 1122 _bfd_vms_debug (8, "found hash entry for %s\n", name); 1123 #endif 1124 } 1125 1126 #if VMS_DEBUG 1127 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol); 1128 #endif 1129 return entry; 1130 } 1131