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