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