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