ce66a27678f05cabdbf71d87d9d889eaee42f4ec
[platform/upstream/binutils.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 }