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