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