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