2010-04-01 Tristan Gingold <gingold@adacore.com>
[binutils.git] / bfd / vms-misc.c
blob96463243b23f8cc037c2f3a5d360d4fc632bc3b7
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.
6 Miscellaneous functions.
8 Written by Klaus K"ampf (kkaempf@rmi.de)
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.
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.
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. */
25 #if __STDC__
26 #include <stdarg.h>
27 #endif
29 #include "sysdep.h"
30 #include "bfd.h"
31 #include "bfdlink.h"
32 #include "libbfd.h"
33 #include "safe-ctype.h"
35 #include "vms.h"
37 #define MIN(a,b) ((a) < (b) ? (a) : (b))
39 static int hash_string PARAMS ((const char *));
40 static asymbol *new_symbol PARAMS ((bfd *, char *));
41 static void maybe_adjust_record_pointer_for_object PARAMS ((bfd *));
42 static int vms_get_remaining_object_record PARAMS ((bfd *, int ));
43 static int vms_get_remaining_image_record PARAMS ((bfd *, int ));
45 #if VMS_DEBUG
46 /* Debug functions. */
48 /* Debug function for all vms extensions evaluates environment
49 variable VMS_DEBUG for a numerical value on the first call all
50 error levels below this value are printed:
52 Levels:
53 1 toplevel bfd calls (functions from the bfd vector)
54 2 functions called by bfd calls
55 ...
56 9 almost everything
58 Level is also indentation level. Indentation is performed
59 if level > 0. */
61 void
62 _bfd_vms_debug (int level, char *format, ...)
64 static int min_level = -1;
65 static FILE *output = NULL;
66 char *eptr;
67 va_list args;
68 int abslvl = (level > 0) ? level : - level;
70 if (min_level == -1)
72 if ((eptr = getenv ("VMS_DEBUG")) != NULL)
74 min_level = atoi (eptr);
75 output = stderr;
77 else
78 min_level = 0;
80 if (output == NULL)
81 return;
82 if (abslvl > min_level)
83 return;
85 while (--level>0)
86 fprintf (output, " ");
87 va_start (args, format);
88 vfprintf (output, format, args);
89 fflush (output);
90 va_end (args);
93 /* A debug function
94 hex dump 'size' bytes starting at 'ptr'. */
96 void
97 _bfd_hexdump (int level,
98 unsigned char *ptr,
99 int size,
100 int offset)
102 unsigned char *lptr = ptr;
103 int count = 0;
104 long start = offset;
106 while (size-- > 0)
108 if ((count%16) == 0)
109 vms_debug (level, "%08lx:", start);
110 vms_debug (-level, " %02x", *ptr++);
111 count++;
112 start++;
113 if (size == 0)
115 while ((count%16) != 0)
117 vms_debug (-level, " ");
118 count++;
121 if ((count%16) == 0)
123 vms_debug (-level, " ");
124 while (lptr < ptr)
126 vms_debug (-level, "%c", (*lptr < 32)?'.':*lptr);
127 lptr++;
129 vms_debug (-level, "\n");
132 if ((count%16) != 0)
133 vms_debug (-level, "\n");
135 #endif
137 /* Hash functions
139 These are needed when reading an object file. */
141 /* Allocate new vms_hash_entry
142 keep the symbol name and a pointer to the bfd symbol in the table. */
144 struct bfd_hash_entry *
145 _bfd_vms_hash_newfunc (struct bfd_hash_entry *entry,
146 struct bfd_hash_table *table,
147 const char *string)
149 vms_symbol_entry *ret;
151 #if VMS_DEBUG
152 vms_debug (5, "_bfd_vms_hash_newfunc (%p, %p, %s)\n", entry, table, string);
153 #endif
155 if (entry == NULL)
157 ret = (vms_symbol_entry *)
158 bfd_hash_allocate (table, sizeof (vms_symbol_entry));
159 if (ret == NULL)
161 bfd_set_error (bfd_error_no_memory);
162 return NULL;
164 entry = (struct bfd_hash_entry *) ret;
167 /* Call the allocation method of the base class. */
168 ret = (vms_symbol_entry *) bfd_hash_newfunc (entry, table, string);
169 #if VMS_DEBUG
170 vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret);
171 #endif
173 ret->symbol = NULL;
175 return (struct bfd_hash_entry *)ret;
178 /* Object file input functions. */
180 /* Return type and size from record header (buf) on Alpha. */
182 void
183 _bfd_vms_get_header_values (bfd * abfd ATTRIBUTE_UNUSED,
184 unsigned char *buf,
185 int *type,
186 int *size)
188 if (type)
189 *type = bfd_getl16 (buf);
191 if (size)
192 *size = bfd_getl16 (buf+2);
194 #if VMS_DEBUG
195 vms_debug (10, "_bfd_vms_get_header_values type %x, size %x\n",
196 type ? *type : 0, size ? *size : 0);
197 #endif
200 /* Get next record from object file to vms_buf.
201 Set PRIV(buf_size) and return it
203 This is a little tricky since it should be portable.
205 The openVMS object file has 'variable length' which means that
206 read() returns data in chunks of (hopefully) correct and expected
207 size. The linker (and other tools on VMS) depend on that. Unix
208 doesn't know about 'formatted' files, so reading and writing such
209 an object file in a Unix environment is not trivial.
211 With the tool 'file' (available on all VMS FTP sites), one
212 can view and change the attributes of a file. Changing from
213 'variable length' to 'fixed length, 512 bytes' reveals the
214 record size at the first 2 bytes of every record. The same
215 may happen during the transfer of object files from VMS to Unix,
216 at least with UCX, the DEC implementation of TCP/IP.
218 The VMS format repeats the size at bytes 2 & 3 of every record.
220 On the first call (file_format == FF_UNKNOWN) we check if
221 the first and the third byte pair (!) of the record match.
222 If they do it's an object file in an Unix environment or with
223 wrong attributes (FF_FOREIGN), else we should be in a VMS
224 environment where read() returns the record size (FF_NATIVE).
226 Reading is always done in 2 steps:
227 1. first just the record header is read and the size extracted,
228 2. then the read buffer is adjusted and the remaining bytes are
229 read in.
231 All file I/O is done on even file positions. */
233 #define VMS_OBJECT_ADJUSTMENT 2
235 static void
236 maybe_adjust_record_pointer_for_object (bfd *abfd)
238 /* Set the file format once for all on the first invocation. */
239 if (PRIV (file_format) == FF_UNKNOWN)
241 if (PRIV (vms_rec)[0] == PRIV (vms_rec)[4]
242 && PRIV (vms_rec)[1] == PRIV (vms_rec)[5])
243 PRIV (file_format) = FF_FOREIGN;
244 else
245 PRIV (file_format) = FF_NATIVE;
248 /* The adjustment is needed only in an Unix environment. */
249 if (PRIV (file_format) == FF_FOREIGN)
250 PRIV (vms_rec) += VMS_OBJECT_ADJUSTMENT;
253 /* Get first record from file and return the file type. */
256 _bfd_vms_get_first_record (bfd *abfd)
258 unsigned int test_len;
260 #if VMS_DEBUG
261 vms_debug (8, "_bfd_vms_get_first_record\n");
262 #endif
264 if (PRIV (is_vax))
265 test_len = 0;
266 else
267 /* Minimum is 6 bytes for objects (2 bytes size, 2 bytes record id,
268 2 bytes size repeated) and 12 bytes for images (4 bytes major id,
269 4 bytes minor id, 4 bytes length). */
270 test_len = 12;
272 /* Size the main buffer. */
273 if (PRIV (buf_size) == 0)
275 /* On VAX there's no size information in the record, so
276 start with OBJ_S_C_MAXRECSIZ. */
277 bfd_size_type amt = (test_len ? test_len : OBJ_S_C_MAXRECSIZ);
278 PRIV (vms_buf) = (unsigned char *) bfd_malloc (amt);
279 PRIV (buf_size) = amt;
282 /* Initialize the record pointer. */
283 PRIV (vms_rec) = PRIV (vms_buf);
285 /* We only support modules on VAX. */
286 if (PRIV (is_vax))
288 if (vms_get_remaining_object_record (abfd, test_len) <= 0)
289 return FT_UNKNOWN;
291 #if VMS_DEBUG
292 vms_debug (2, "file type is VAX module\n");
293 #endif
295 return FT_MODULE;
298 if (bfd_bread (PRIV (vms_buf), test_len, abfd) != test_len)
300 bfd_set_error (bfd_error_file_truncated);
301 return FT_UNKNOWN;
304 /* Is it an image? */
305 if ((bfd_getl32 (PRIV (vms_rec)) == EIHD_S_K_MAJORID)
306 && (bfd_getl32 (PRIV (vms_rec) + 4) == EIHD_S_K_MINORID))
308 if (vms_get_remaining_image_record (abfd, test_len) <= 0)
309 return FT_UNKNOWN;
311 #if VMS_DEBUG
312 vms_debug (2, "file type is image\n");
313 #endif
315 return FT_IMAGE;
318 /* Assume it's a module and adjust record pointer if necessary. */
319 maybe_adjust_record_pointer_for_object (abfd);
321 /* But is it really a module? */
322 if (bfd_getl16 (PRIV (vms_rec)) <= EOBJ_S_C_MAXRECTYP
323 && bfd_getl16 (PRIV (vms_rec) + 2) <= EOBJ_S_C_MAXRECSIZ)
325 if (vms_get_remaining_object_record (abfd, test_len) <= 0)
326 return FT_UNKNOWN;
328 #if VMS_DEBUG
329 vms_debug (2, "file type is module\n");
330 #endif
332 return FT_MODULE;
335 #if VMS_DEBUG
336 vms_debug (2, "file type is unknown\n");
337 #endif
339 return FT_UNKNOWN;
342 /* Implement step #1 of the object record reading procedure.
343 Return the record type or -1 on failure. */
346 _bfd_vms_get_object_record (bfd *abfd)
348 unsigned int test_len;
349 int type;
351 #if VMS_DEBUG
352 vms_debug (8, "_bfd_vms_get_obj_record\n");
353 #endif
355 if (PRIV (is_vax))
356 test_len = 0;
357 else
359 int off = 0;
361 /* See _bfd_vms_get_first_record. */
362 test_len = 6;
364 /* Skip odd alignment byte. */
365 if (bfd_tell (abfd) & 1)
367 if (bfd_bread (PRIV (vms_buf), 1, abfd) != 1)
369 bfd_set_error (bfd_error_file_truncated);
370 return -1;
372 /* Alignment byte may be present or not. This is not easy to
373 detect but all object record types are not 0 (on Alpha VMS).
374 We also hope that pad byte is 0. */
375 if (PRIV (vms_buf)[0])
376 off = 1;
379 /* Read the record header */
380 if (bfd_bread (PRIV (vms_buf) + off, test_len - off, abfd)
381 != test_len - off)
383 bfd_set_error (bfd_error_file_truncated);
384 return -1;
387 /* Reset the record pointer. */
388 PRIV (vms_rec) = PRIV (vms_buf);
389 maybe_adjust_record_pointer_for_object (abfd);
392 if (vms_get_remaining_object_record (abfd, test_len) <= 0)
393 return -1;
395 if (PRIV (is_vax))
396 type = PRIV (vms_rec) [0];
397 else
398 type = bfd_getl16 (PRIV (vms_rec));
400 #if VMS_DEBUG
401 vms_debug (8, "_bfd_vms_get_obj_record: rec %p, size %d, type %d\n",
402 PRIV (vms_rec), PRIV (rec_size), type);
403 #endif
405 return type;
408 /* Implement step #2 of the object record reading procedure.
409 Return the size of the record or 0 on failure. */
411 static int
412 vms_get_remaining_object_record (bfd *abfd, int read_so_far)
414 #if VMS_DEBUG
415 vms_debug (8, "vms_get_remaining_obj_record\n");
416 #endif
418 if (PRIV (is_vax))
420 if (read_so_far != 0)
421 abort ();
423 PRIV (rec_size) = bfd_bread (PRIV (vms_buf), PRIV (buf_size), abfd);
425 if (PRIV (rec_size) <= 0)
427 bfd_set_error (bfd_error_file_truncated);
428 return 0;
431 /* Reset the record pointer. */
432 PRIV (vms_rec) = PRIV (vms_buf);
434 else
436 unsigned int to_read;
438 /* Extract record size. */
439 PRIV (rec_size) = bfd_getl16 (PRIV (vms_rec) + 2);
441 if (PRIV (rec_size) <= 0)
443 bfd_set_error (bfd_error_file_truncated);
444 return 0;
447 /* That's what the linker manual says. */
448 if (PRIV (rec_size) > EOBJ_S_C_MAXRECSIZ)
450 bfd_set_error (bfd_error_file_truncated);
451 return 0;
454 /* Take into account object adjustment. */
455 to_read = PRIV (rec_size);
456 if (PRIV (file_format) == FF_FOREIGN)
457 to_read += VMS_OBJECT_ADJUSTMENT;
459 /* Adjust the buffer. */
460 if (to_read > PRIV (buf_size))
462 PRIV (vms_buf)
463 = (unsigned char *) bfd_realloc (PRIV (vms_buf), to_read);
464 if (PRIV (vms_buf) == NULL)
465 return 0;
466 PRIV (buf_size) = to_read;
469 /* Read the remaining record. */
470 to_read -= read_so_far;
472 #if VMS_DEBUG
473 vms_debug (8, "vms_get_remaining_obj_record: to_read %d\n", to_read);
474 #endif
476 if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read)
478 bfd_set_error (bfd_error_file_truncated);
479 return 0;
482 /* Reset the record pointer. */
483 PRIV (vms_rec) = PRIV (vms_buf);
484 maybe_adjust_record_pointer_for_object (abfd);
487 #if VMS_DEBUG
488 vms_debug (8, "vms_get_remaining_obj_record: size %d\n", PRIV (rec_size));
489 #endif
491 return PRIV (rec_size);
494 /* Implement step #2 of the record reading procedure for images.
495 Return the size of the record or 0 on failure. */
497 static int
498 vms_get_remaining_image_record (bfd *abfd, int read_so_far)
500 unsigned int to_read;
501 int remaining;
503 /* Extract record size. */
504 PRIV (rec_size) = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_SIZE);
506 if (PRIV (rec_size) > PRIV (buf_size))
508 PRIV (vms_buf) = bfd_realloc (PRIV (vms_buf), PRIV (rec_size));
510 if (PRIV (vms_buf) == NULL)
512 bfd_set_error (bfd_error_no_memory);
513 return 0;
516 PRIV (buf_size) = PRIV (rec_size);
519 /* Read the remaining record. */
520 remaining = PRIV (rec_size) - read_so_far;
521 to_read = MIN (VMS_BLOCK_SIZE - read_so_far, remaining);
523 while (remaining > 0)
525 if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read)
527 bfd_set_error (bfd_error_file_truncated);
528 return 0;
531 read_so_far += to_read;
532 remaining -= to_read;
534 /* Eat trailing 0xff's. */
535 if (remaining > 0)
536 while (PRIV (vms_buf) [read_so_far - 1] == 0xff)
537 read_so_far--;
539 to_read = MIN (VMS_BLOCK_SIZE, remaining);
542 /* Reset the record pointer. */
543 PRIV (vms_rec) = PRIV (vms_buf);
545 return PRIV (rec_size);
548 /* Copy sized string (string with fixed size) to new allocated area
549 size is string size (size of record) */
551 char *
552 _bfd_vms_save_sized_string (unsigned char *str, int size)
554 char *newstr = bfd_malloc ((bfd_size_type) size + 1);
556 if (newstr == NULL)
557 return NULL;
558 strncpy (newstr, (char *) str, (size_t) size);
559 newstr[size] = 0;
561 return newstr;
564 /* Copy counted string (string with size at first byte) to new allocated area
565 ptr points to size byte on entry */
567 char *
568 _bfd_vms_save_counted_string (unsigned char *ptr)
570 int len = *ptr++;
572 return _bfd_vms_save_sized_string (ptr, len);
575 /* Stack routines for vms ETIR commands. */
577 /* Push value and section index. */
579 void
580 _bfd_vms_push (bfd * abfd, uquad val, int psect)
582 static int last_psect;
584 #if VMS_DEBUG
585 vms_debug (4, "<push %016lx (%d) at %d>\n", val, psect, PRIV (stackptr));
586 #endif
588 if (psect >= 0)
589 last_psect = psect;
591 PRIV (stack[PRIV (stackptr)]).value = val;
592 PRIV (stack[PRIV (stackptr)]).psect = last_psect;
593 PRIV (stackptr)++;
594 if (PRIV (stackptr) >= STACKSIZE)
596 bfd_set_error (bfd_error_bad_value);
597 (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr));
598 exit (1);
602 /* Pop value and section index. */
604 uquad
605 _bfd_vms_pop (bfd * abfd, int *psect)
607 uquad value;
609 if (PRIV (stackptr) == 0)
611 bfd_set_error (bfd_error_bad_value);
612 (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
613 exit (1);
615 PRIV (stackptr)--;
616 value = PRIV (stack[PRIV (stackptr)]).value;
617 if ((psect != NULL) && (PRIV (stack[PRIV (stackptr)]).psect >= 0))
618 *psect = PRIV (stack[PRIV (stackptr)]).psect;
620 #if VMS_DEBUG
621 vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV (stack[PRIV (stackptr)]).psect);
622 #endif
624 return value;
627 /* Object output routines. */
629 /* Begin new record or record header
630 write 2 bytes rectype
631 write 2 bytes record length (filled in at flush)
632 write 2 bytes header type (ommitted if rechead == -1). */
634 void
635 _bfd_vms_output_begin (bfd * abfd, int rectype, int rechead)
637 #if VMS_DEBUG
638 vms_debug (6, "_bfd_vms_output_begin (type %d, head %d)\n", rectype,
639 rechead);
640 #endif
642 _bfd_vms_output_short (abfd, (unsigned int) rectype);
644 /* Save current output position to fill in length later. */
646 if (PRIV (push_level) > 0)
647 PRIV (length_pos) = PRIV (output_size);
649 #if VMS_DEBUG
650 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
651 PRIV (length_pos));
652 #endif
654 /* Placeholder for length. */
655 _bfd_vms_output_short (abfd, 0);
657 if (rechead != -1)
658 _bfd_vms_output_short (abfd, (unsigned int) rechead);
661 /* Set record/subrecord alignment. */
663 void
664 _bfd_vms_output_alignment (bfd * abfd, int alignto)
666 #if VMS_DEBUG
667 vms_debug (6, "_bfd_vms_output_alignment (%d)\n", alignto);
668 #endif
670 PRIV (output_alignment) = alignto;
673 /* Prepare for subrecord fields. */
675 void
676 _bfd_vms_output_push (bfd * abfd)
678 #if VMS_DEBUG
679 vms_debug (6, "vms_output_push (pushed_size = %d)\n", PRIV (output_size));
680 #endif
682 PRIV (push_level)++;
683 PRIV (pushed_size) = PRIV (output_size);
686 /* End of subrecord fields. */
688 void
689 _bfd_vms_output_pop (bfd * abfd)
691 #if VMS_DEBUG
692 vms_debug (6, "vms_output_pop (pushed_size = %d)\n", PRIV (pushed_size));
693 #endif
695 _bfd_vms_output_flush (abfd);
696 PRIV (length_pos) = 2;
698 #if VMS_DEBUG
699 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV (length_pos));
700 #endif
702 PRIV (pushed_size) = 0;
703 PRIV (push_level)--;
706 /* Flush unwritten output, ends current record. */
708 void
709 _bfd_vms_output_flush (bfd * abfd)
711 int real_size = PRIV (output_size);
712 int aligncount;
713 int length;
715 #if VMS_DEBUG
716 vms_debug (6, "_bfd_vms_output_flush (real_size = %d, pushed_size %d at lenpos %d)\n",
717 real_size, PRIV (pushed_size), PRIV (length_pos));
718 #endif
720 if (PRIV (push_level) > 0)
721 length = real_size - PRIV (pushed_size);
722 else
723 length = real_size;
725 if (length == 0)
726 return;
727 aligncount = (PRIV (output_alignment)
728 - (length % PRIV (output_alignment))) % PRIV (output_alignment);
730 #if VMS_DEBUG
731 vms_debug (6, "align: adding %d bytes\n", aligncount);
732 #endif
734 while (aligncount-- > 0)
736 PRIV (output_buf)[real_size++] = 0;
737 length++;
740 /* Put length to buffer. */
741 PRIV (output_size) = PRIV (length_pos);
742 _bfd_vms_output_short (abfd, (unsigned int) length);
744 if (PRIV (push_level) == 0)
746 /* File is open in undefined (UDF) format on VMS, but ultimately will be
747 converted to variable length (VAR) format. VAR format has a length
748 word first which must be explicitly output in UDF format. */
749 bfd_bwrite (PRIV (output_buf) + 2, 2, abfd);
750 bfd_bwrite (PRIV (output_buf), (size_t) real_size, abfd);
751 PRIV (output_size) = 0;
753 else
755 PRIV (output_size) = real_size;
756 PRIV (pushed_size) = PRIV (output_size);
760 /* End record output. */
762 void
763 _bfd_vms_output_end (bfd * abfd)
765 #if VMS_DEBUG
766 vms_debug (6, "_bfd_vms_output_end\n");
767 #endif
769 _bfd_vms_output_flush (abfd);
772 /* Check remaining buffer size
774 Return what's left. */
777 _bfd_vms_output_check (bfd * abfd, int size)
779 #if VMS_DEBUG
780 vms_debug (6, "_bfd_vms_output_check (%d)\n", size);
781 #endif
783 return (MAX_OUTREC_SIZE - (PRIV (output_size) + size + MIN_OUTREC_LUFT));
786 /* Output byte (8 bit) value. */
788 void
789 _bfd_vms_output_byte (bfd * abfd, unsigned int value)
791 #if VMS_DEBUG
792 vms_debug (6, "_bfd_vms_output_byte (%02x)\n", value);
793 #endif
795 bfd_put_8 (abfd, value & 0xff, PRIV (output_buf) + PRIV (output_size));
796 PRIV (output_size) += 1;
799 /* Output short (16 bit) value. */
801 void
802 _bfd_vms_output_short (bfd * abfd, unsigned int value)
804 #if VMS_DEBUG
805 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
806 #endif
808 bfd_put_16 (abfd, (bfd_vma) value & 0xffff,
809 PRIV (output_buf) + PRIV (output_size));
810 PRIV (output_size) += 2;
813 /* Output long (32 bit) value. */
815 void
816 _bfd_vms_output_long (bfd * abfd, unsigned long value)
818 #if VMS_DEBUG
819 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
820 #endif
822 bfd_put_32 (abfd, (bfd_vma) value, PRIV (output_buf) + PRIV (output_size));
823 PRIV (output_size) += 4;
826 /* Output quad (64 bit) value. */
828 void
829 _bfd_vms_output_quad (bfd * abfd, uquad value)
831 #if VMS_DEBUG
832 vms_debug (6, "_bfd_vms_output_quad (%016lx)\n", value);
833 #endif
835 bfd_put_64(abfd, value, PRIV (output_buf) + PRIV (output_size));
836 PRIV (output_size) += 8;
839 /* Output c-string as counted string. */
841 void
842 _bfd_vms_output_counted (bfd * abfd, char *value)
844 int len;
846 #if VMS_DEBUG
847 vms_debug (6, "_bfd_vms_output_counted (%s)\n", value);
848 #endif
850 len = strlen (value);
851 if (len == 0)
853 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
854 return;
856 if (len > 255)
858 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
859 return;
861 _bfd_vms_output_byte (abfd, (unsigned int) len & 0xff);
862 _bfd_vms_output_dump (abfd, (unsigned char *) value, len);
865 /* Output character area. */
867 void
868 _bfd_vms_output_dump (bfd * abfd,
869 unsigned char *data,
870 int length)
872 #if VMS_DEBUG
873 vms_debug (6, "_bfd_vms_output_dump (%d)\n", length);
874 #endif
876 if (length == 0)
877 return;
879 memcpy (PRIV (output_buf) + PRIV (output_size), data, (size_t) length);
880 PRIV (output_size) += length;
883 /* Output count bytes of value. */
885 void
886 _bfd_vms_output_fill (bfd * abfd,
887 int value,
888 int count)
890 #if VMS_DEBUG
891 vms_debug (6, "_bfd_vms_output_fill (val %02x times %d)\n", value, count);
892 #endif
894 if (count == 0)
895 return;
896 memset (PRIV (output_buf) + PRIV (output_size), value, (size_t) count);
897 PRIV (output_size) += count;
900 /* This hash routine borrowed from GNU-EMACS, and strengthened slightly. ERY. */
902 static int
903 hash_string (const char *ptr)
905 const unsigned char *p = (unsigned char *) ptr;
906 const unsigned char *end = p + strlen (ptr);
907 unsigned char c;
908 int hash = 0;
910 while (p != end)
912 c = *p++;
913 hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
915 return hash;
918 /* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
920 char *
921 _bfd_vms_length_hash_symbol (bfd * abfd, const char *in, int maxlen)
923 unsigned long result;
924 int in_len;
925 char *new_name;
926 const char *old_name;
927 int i;
928 static char outbuf[EOBJ_S_C_SYMSIZ+1];
929 char *out = outbuf;
931 #if VMS_DEBUG
932 vms_debug (4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
933 #endif
935 if (maxlen > EOBJ_S_C_SYMSIZ)
936 maxlen = EOBJ_S_C_SYMSIZ;
938 /* Save this for later. */
939 new_name = out;
941 /* We may need to truncate the symbol, save the hash for later. */
942 in_len = strlen (in);
944 result = (in_len > maxlen) ? hash_string (in) : 0;
946 old_name = in;
948 /* Do the length checking. */
949 if (in_len <= maxlen)
950 i = in_len;
951 else
953 if (PRIV (flag_hash_long_names))
954 i = maxlen-9;
955 else
956 i = maxlen;
959 strncpy (out, in, (size_t) i);
960 in += i;
961 out += i;
963 if ((in_len > maxlen)
964 && PRIV (flag_hash_long_names))
965 sprintf (out, "_%08lx", result);
966 else
967 *out = 0;
969 #if VMS_DEBUG
970 vms_debug (4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
971 #endif
973 if (in_len > maxlen
974 && PRIV (flag_hash_long_names)
975 && PRIV (flag_show_after_trunc))
976 printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
978 return outbuf;
981 /* Allocate and initialize a new symbol. */
983 static asymbol *
984 new_symbol (bfd * abfd, char *name)
986 asymbol *symbol;
988 #if VMS_DEBUG
989 _bfd_vms_debug (7, "new_symbol %s\n", name);
990 #endif
992 symbol = bfd_make_empty_symbol (abfd);
993 if (symbol == 0)
994 return symbol;
995 symbol->name = name;
996 symbol->section = (asection *)(unsigned long)-1;
998 return symbol;
1001 /* Allocate and enter a new private symbol. */
1003 vms_symbol_entry *
1004 _bfd_vms_enter_symbol (bfd * abfd, char *name)
1006 vms_symbol_entry *entry;
1008 #if VMS_DEBUG
1009 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name);
1010 #endif
1012 entry = (vms_symbol_entry *)
1013 bfd_hash_lookup (PRIV (vms_symbol_table), name, FALSE, FALSE);
1014 if (entry == 0)
1016 #if VMS_DEBUG
1017 _bfd_vms_debug (8, "creating hash entry for %s\n", name);
1018 #endif
1019 entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
1020 name, TRUE, FALSE);
1021 if (entry != 0)
1023 asymbol *symbol;
1024 symbol = new_symbol (abfd, name);
1025 if (symbol != 0)
1027 entry->symbol = symbol;
1028 PRIV (gsd_sym_count)++;
1029 abfd->symcount++;
1031 else
1032 entry = 0;
1034 else
1035 (*_bfd_error_handler) (_("failed to enter %s"), name);
1037 else
1039 #if VMS_DEBUG
1040 _bfd_vms_debug (8, "found hash entry for %s\n", name);
1041 #endif
1044 #if VMS_DEBUG
1045 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
1046 #endif
1047 return entry;
1050 /* Create module name from filename (ie, extract the basename and convert it
1051 in upper cases). Works on both VMS and UNIX pathes.
1052 The result has to be free(). */
1054 char *
1055 vms_get_module_name (const char *filename, bfd_boolean upcase)
1057 char *fname, *fptr;
1058 const char *fout;
1060 /* Strip VMS path. */
1061 fout = strrchr (filename, ']');
1062 if (fout == NULL)
1063 fout = strchr (filename, ':');
1064 if (fout != NULL)
1065 fout++;
1066 else
1067 fout = filename;
1069 /* Strip UNIX path. */
1070 fptr = strrchr (fout, '/');
1071 if (fptr != NULL)
1072 fout = fptr + 1;
1074 fname = strdup (fout);
1076 /* Strip suffix. */
1077 fptr = strrchr (fname, '.');
1078 if (fptr != 0)
1079 *fptr = 0;
1081 /* Convert to upper case and truncate at 31 characters.
1082 (VMS object file format restricts module name length to 31). */
1083 fptr = fname;
1084 for (fptr = fname; *fptr != 0; fptr++)
1086 if (*fptr == ';' || (fptr - fname) >= 31)
1088 *fptr = 0;
1089 break;
1091 if (upcase)
1092 *fptr = TOUPPER (*fptr);
1094 return fname;
1097 /* Convert a raw VMS time to a unix time. */
1099 time_t
1100 vms_time_to_time_t (unsigned int hi, unsigned int lo)
1102 const unsigned int off = 3506716800U;
1103 const unsigned int factor = 10000000;
1104 unsigned int tmp;
1105 unsigned int rlo;
1106 int i;
1108 /* First convert to seconds. */
1109 tmp = hi % factor;
1110 hi = hi / factor;
1111 rlo = 0;
1112 for (i = 0; i < 4; i++)
1114 tmp = (tmp << 8) | (lo >> 24);
1115 lo <<= 8;
1117 rlo = (rlo << 8) | (tmp / factor);
1118 tmp %= factor;
1120 lo = rlo;
1122 /* Return 0 in case of overflow. */
1123 if (lo > off && hi > 1)
1124 return 0;
1126 return lo - off;
1129 /* Convert a raw (stored in a buffer) VMS time to a unix time. */
1131 time_t
1132 vms_rawtime_to_time_t (unsigned char *buf)
1134 unsigned int hi = bfd_getl32 (buf + 4);
1135 unsigned int lo = bfd_getl32 (buf + 0);
1137 return vms_time_to_time_t (hi, lo);