OSDN Git Service

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