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