Update copyright notices
[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, 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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 }
This page took 0.052943 seconds and 4 git commands to generate.