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