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 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
51void
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
86void
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
134struct 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
172void
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
223int
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 (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
385int
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
428char *
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
444char *
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
456void
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
481uquad
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
513static vms_section *
514add_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
538bfd_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
564vms_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
582void
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
611void
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
623void
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
636void
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
656void
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#ifndef VMS
695	/* Write length first, see FF_FOREIGN in the input routines.  */
696      fwrite (PRIV (output_buf) + 2, 2, 1, (FILE *) abfd->iostream);
697#endif
698      fwrite (PRIV (output_buf), (size_t) real_size, 1,
699	      (FILE *) abfd->iostream);
700
701      PRIV (output_size) = 0;
702    }
703  else
704    {
705      PRIV (output_size) = real_size;
706      PRIV (pushed_size) = PRIV (output_size);
707    }
708}
709
710/* End record output.   */
711
712void
713_bfd_vms_output_end (bfd * abfd)
714{
715#if VMS_DEBUG
716  vms_debug (6, "_bfd_vms_output_end\n");
717#endif
718
719  _bfd_vms_output_flush (abfd);
720}
721
722/* Check remaining buffer size
723
724   Return what's left.  */
725
726int
727_bfd_vms_output_check (bfd * abfd, int size)
728{
729#if VMS_DEBUG
730  vms_debug (6, "_bfd_vms_output_check (%d)\n", size);
731#endif
732
733  return (MAX_OUTREC_SIZE - (PRIV (output_size) + size + MIN_OUTREC_LUFT));
734}
735
736/* Output byte (8 bit) value.  */
737
738void
739_bfd_vms_output_byte (bfd * abfd, unsigned int value)
740{
741#if VMS_DEBUG
742  vms_debug (6, "_bfd_vms_output_byte (%02x)\n", value);
743#endif
744
745  bfd_put_8 (abfd, value & 0xff, PRIV (output_buf) + PRIV (output_size));
746  PRIV (output_size) += 1;
747}
748
749/* Output short (16 bit) value.  */
750
751void
752_bfd_vms_output_short (bfd * abfd, unsigned int value)
753{
754#if VMS_DEBUG
755  vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
756#endif
757
758  bfd_put_16 (abfd, (bfd_vma) value & 0xffff,
759	      PRIV (output_buf) + PRIV (output_size));
760  PRIV (output_size) += 2;
761}
762
763/* Output long (32 bit) value.  */
764
765void
766_bfd_vms_output_long (bfd * abfd, unsigned long value)
767{
768#if VMS_DEBUG
769  vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
770#endif
771
772  bfd_put_32 (abfd, (bfd_vma) value, PRIV (output_buf) + PRIV (output_size));
773  PRIV (output_size) += 4;
774}
775
776/* Output quad (64 bit) value.  */
777
778void
779_bfd_vms_output_quad (bfd * abfd, uquad value)
780{
781#if VMS_DEBUG
782  vms_debug (6, "_bfd_vms_output_quad (%016lx)\n", value);
783#endif
784
785  bfd_put_64(abfd, value, PRIV (output_buf) + PRIV (output_size));
786  PRIV (output_size) += 8;
787}
788
789/* Output c-string as counted string.  */
790
791void
792_bfd_vms_output_counted (bfd * abfd, char *value)
793{
794  int len;
795
796#if VMS_DEBUG
797  vms_debug (6, "_bfd_vms_output_counted (%s)\n", value);
798#endif
799
800  len = strlen (value);
801  if (len == 0)
802    {
803      (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
804      return;
805    }
806  if (len > 255)
807    {
808      (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
809      return;
810    }
811  _bfd_vms_output_byte (abfd, (unsigned int) len & 0xff);
812  _bfd_vms_output_dump (abfd, (unsigned char *) value, len);
813}
814
815/* Output character area.  */
816
817void
818_bfd_vms_output_dump (bfd * abfd,
819		      unsigned char *data,
820		      int length)
821{
822#if VMS_DEBUG
823  vms_debug (6, "_bfd_vms_output_dump (%d)\n", length);
824#endif
825
826  if (length == 0)
827    return;
828
829  memcpy (PRIV (output_buf) + PRIV (output_size), data, (size_t) length);
830  PRIV (output_size) += length;
831}
832
833/* Output count bytes of value.  */
834
835void
836_bfd_vms_output_fill (bfd * abfd,
837		      int value,
838		      int count)
839{
840#if VMS_DEBUG
841  vms_debug (6, "_bfd_vms_output_fill (val %02x times %d)\n", value, count);
842#endif
843
844  if (count == 0)
845    return;
846  memset (PRIV (output_buf) + PRIV (output_size), value, (size_t) count);
847  PRIV (output_size) += count;
848}
849
850/* This hash routine borrowed from GNU-EMACS, and strengthened slightly.  ERY.  */
851
852static int
853hash_string (const char *ptr)
854{
855  const unsigned char *p = (unsigned char *) ptr;
856  const unsigned char *end = p + strlen (ptr);
857  unsigned char c;
858  int hash = 0;
859
860  while (p != end)
861    {
862      c = *p++;
863      hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
864    }
865  return hash;
866}
867
868/* Generate a length-hashed VMS symbol name (limited to maxlen chars).  */
869
870char *
871_bfd_vms_length_hash_symbol (bfd * abfd, const char *in, int maxlen)
872{
873  long int result;
874  int in_len;
875  char *new_name;
876  const char *old_name;
877  int i;
878  static char outbuf[EOBJ_S_C_SYMSIZ+1];
879  char *out = outbuf;
880
881#if VMS_DEBUG
882  vms_debug (4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
883#endif
884
885  if (maxlen > EOBJ_S_C_SYMSIZ)
886    maxlen = EOBJ_S_C_SYMSIZ;
887
888  /* Save this for later.  */
889  new_name = out;
890
891  /* We may need to truncate the symbol, save the hash for later.  */
892  in_len = strlen (in);
893
894  result = (in_len > maxlen) ? hash_string (in) : 0;
895
896  old_name = in;
897
898  /* Do the length checking.  */
899  if (in_len <= maxlen)
900    i = in_len;
901  else
902    {
903      if (PRIV (flag_hash_long_names))
904	i = maxlen-9;
905      else
906	i = maxlen;
907    }
908
909  strncpy (out, in, (size_t) i);
910  in += i;
911  out += i;
912
913  if ((in_len > maxlen)
914      && PRIV (flag_hash_long_names))
915    sprintf (out, "_%08lx", result);
916  else
917    *out = 0;
918
919#if VMS_DEBUG
920  vms_debug (4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
921#endif
922
923  if (in_len > maxlen
924	&& PRIV (flag_hash_long_names)
925	&& PRIV (flag_show_after_trunc))
926    printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
927
928  return outbuf;
929}
930
931/* Allocate and initialize a new symbol.  */
932
933static asymbol *
934new_symbol (bfd * abfd, char *name)
935{
936  asymbol *symbol;
937
938#if VMS_DEBUG
939  _bfd_vms_debug (7,  "new_symbol %s\n", name);
940#endif
941
942  symbol = bfd_make_empty_symbol (abfd);
943  if (symbol == 0)
944    return symbol;
945  symbol->name = name;
946  symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
947
948  return symbol;
949}
950
951/* Allocate and enter a new private symbol.  */
952
953vms_symbol_entry *
954_bfd_vms_enter_symbol (bfd * abfd, char *name)
955{
956  vms_symbol_entry *entry;
957
958#if VMS_DEBUG
959  _bfd_vms_debug (6,  "_bfd_vms_enter_symbol %s\n", name);
960#endif
961
962  entry = (vms_symbol_entry *)
963	  bfd_hash_lookup (PRIV (vms_symbol_table), name, FALSE, FALSE);
964  if (entry == 0)
965    {
966#if VMS_DEBUG
967      _bfd_vms_debug (8,  "creating hash entry for %s\n", name);
968#endif
969      entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
970						    name, TRUE, FALSE);
971      if (entry != 0)
972	{
973	  asymbol *symbol;
974	  symbol = new_symbol (abfd, name);
975	  if (symbol != 0)
976	    {
977	      entry->symbol = symbol;
978	      PRIV (gsd_sym_count)++;
979	      abfd->symcount++;
980	    }
981	  else
982	    entry = 0;
983	}
984      else
985	(*_bfd_error_handler) (_("failed to enter %s"), name);
986    }
987  else
988    {
989#if VMS_DEBUG
990      _bfd_vms_debug (8,  "found hash entry for %s\n", name);
991#endif
992    }
993
994#if VMS_DEBUG
995  _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
996#endif
997  return entry;
998}
999