1 /* vms-misc.c -- Miscellaneous functions for VAX (openVMS/VAX) and
2 EVAX (openVMS/Alpha) files.
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001
4 Free Software Foundation, Inc.
6 Written by Klaus K"ampf (kkaempf@rmi.de)
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
33 /*-----------------------------------------------------------------------------*/
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
43 1 toplevel bfd calls (functions from the bfd vector)
44 2 functions called by bfd calls
48 level is also identation level. Indentation is performed
54 _bfd_vms_debug (int level
, char *format
, ...)
56 static int min_level
= -1;
57 static FILE *output
= NULL
;
60 int abslvl
= (level
> 0)?level
:-level
;
64 if ((eptr
= getenv("VMS_DEBUG")) != NULL
)
66 min_level
= atoi(eptr
);
74 if (abslvl
> min_level
)
78 fprintf (output
, " ");
79 va_start(args
, format
);
80 vfprintf (output
, format
, args
);
87 #else /* not __STDC__ */
90 _bfd_vms_debug (level
, format
, a1
, a2
, a3
, a4
, a5
, a6
)
93 long a1
; long a2
; long a3
;
94 long a4
; long a5
; long a6
;
96 static int min_level
= -1;
97 static FILE *output
= NULL
;
102 if ((eptr
= getenv("VMS_DEBUG")) != NULL
)
104 min_level
= atoi(eptr
);
112 if (level
> min_level
)
116 fprintf (output
, " ");
117 fprintf (output
, format
, a1
, a2
, a3
, a4
, a5
, a6
);
122 #endif /* __STDC__ */
125 hex dump 'size' bytes starting at 'ptr' */
128 _bfd_hexdump (level
, ptr
, size
, offset
)
134 unsigned char *lptr
= ptr
;
141 vms_debug (level
, "%08lx:", start
);
142 vms_debug (-level
, " %02x", *ptr
++);
147 while ((count
%16) != 0)
149 vms_debug (-level
, " ");
155 vms_debug (-level
, " ");
158 vms_debug (-level
, "%c", (*lptr
< 32)?'.':*lptr
);
161 vms_debug (-level
, "\n");
165 vms_debug (-level
, "\n");
173 These are needed when reading an object file. */
175 /* allocate new vms_hash_entry
176 keep the symbol name and a pointer to the bfd symbol in the table */
178 struct bfd_hash_entry
*
179 _bfd_vms_hash_newfunc (entry
, table
, string
)
180 struct bfd_hash_entry
*entry
;
181 struct bfd_hash_table
*table
;
184 vms_symbol_entry
*ret
;
187 vms_debug (5, "_bfd_vms_hash_newfunc(%p, %p, %s)\n", entry
, table
, string
);
190 if (entry
== (struct bfd_hash_entry
*)NULL
)
192 ret
= (vms_symbol_entry
*)
193 bfd_hash_allocate (table
, sizeof (vms_symbol_entry
));
194 if (ret
== (vms_symbol_entry
*) NULL
)
196 bfd_set_error (bfd_error_no_memory
);
197 return (struct bfd_hash_entry
*)NULL
;
199 entry
= (struct bfd_hash_entry
*) ret
;
202 /* Call the allocation method of the base class. */
204 ret
= (vms_symbol_entry
*) bfd_hash_newfunc (entry
, table
, string
);
206 vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret
);
209 ret
->symbol
= (asymbol
*)NULL
;
211 return (struct bfd_hash_entry
*)ret
;
214 /* object file input functions */
216 /* Return type and length from record header (buf) on Alpha. */
219 _bfd_vms_get_header_values (abfd
, buf
, type
, length
)
220 bfd
*abfd ATTRIBUTE_UNUSED
;
226 *type
= bfd_getl16 (buf
);
229 *length
= bfd_getl16 (buf
);
232 vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type
?*type
:0), (length
?*length
:0));
238 /* Get next record from object file to vms_buf
239 set PRIV(buf_size) and return it
241 this is a little tricky since it should be portable.
243 the openVMS object file has 'variable length' which means that
244 read() returns data in chunks of (hopefully) correct and expected
245 size. The linker (and other tools on vms) depend on that. Unix doesn't
246 know about 'formatted' files, so reading and writing such an object
247 file in a unix environment is not trivial.
249 With the tool 'file' (available on all vms ftp sites), one
250 can view and change the attributes of a file. Changing from
251 'variable length' to 'fixed length, 512 bytes' reveals the
252 record length at the first 2 bytes of every record. The same
253 happens during the transfer of object files from vms to unix,
254 at least with ucx, dec's implementation of tcp/ip.
256 The vms format repeats the length at bytes 2 & 3 of every record.
258 On the first call (file_format == FF_UNKNOWN) we check if
259 the first and the third byte pair (!) of the record match.
260 If they do it's an object file in an unix environment or with
261 wrong attributes (FF_FOREIGN), else we should be in a vms
262 environment where read() returns the record size (FF_NATIVE).
264 reading is always done in 2 steps.
265 first just the record header is read and the length extracted
267 then the read buffer is adjusted and the remaining bytes are
270 all file i/o is always done on even file positions */
273 _bfd_vms_get_record (abfd
)
276 int test_len
, test_start
, remaining
;
277 unsigned char *vms_buf
;
280 vms_debug (8, "_bfd_vms_get_record\n");
283 /* minimum is 6 bytes on Alpha
284 (2 bytes length, 2 bytes record id, 2 bytes length repeated)
286 on VAX there's no length information in the record
287 so start with OBJ_S_C_MAXRECSIZ */
289 if (PRIV (buf_size
) == 0)
293 PRIV (vms_buf
) = (unsigned char *) malloc (OBJ_S_C_MAXRECSIZ
);
294 PRIV (buf_size
) = OBJ_S_C_MAXRECSIZ
;
295 PRIV (file_format
) = FF_VAX
;
298 PRIV (vms_buf
) = (unsigned char *) malloc (6);
301 vms_buf
= PRIV (vms_buf
);
305 bfd_set_error (bfd_error_no_memory
);
309 switch (PRIV (file_format
))
313 test_len
= 6; /* probe 6 bytes */
314 test_start
= 2; /* where the record starts */
329 /* skip odd alignment byte */
331 if (bfd_tell (abfd
) & 1)
333 if (bfd_read (PRIV (vms_buf
), 1, 1, abfd
) != 1)
335 bfd_set_error (bfd_error_file_truncated
);
340 /* read the record header on Alpha. */
343 && (bfd_read (PRIV (vms_buf
), 1, test_len
, abfd
)
344 != (bfd_size_type
) test_len
))
346 bfd_set_error (bfd_error_file_truncated
);
350 /* check file format on first call */
352 if (PRIV (file_format
) == FF_UNKNOWN
)
353 { /* record length repeats ? */
354 if ( (vms_buf
[0] == vms_buf
[4])
355 && (vms_buf
[1] == vms_buf
[5]))
357 PRIV (file_format
) = FF_FOREIGN
; /* Y: foreign environment */
362 PRIV (file_format
) = FF_NATIVE
; /* N: native environment */
369 PRIV (rec_length
) = bfd_read (vms_buf
, 1, PRIV (buf_size
), abfd
);
370 if (PRIV (rec_length
) <= 0)
372 bfd_set_error (bfd_error_file_truncated
);
375 PRIV (vms_rec
) = vms_buf
;
379 /* extract vms record length */
381 _bfd_vms_get_header_values (abfd
, vms_buf
+test_start
, NULL
,
384 if (PRIV (rec_length
) <= 0)
386 bfd_set_error (bfd_error_file_truncated
);
390 /* that's what the linker manual says */
392 if (PRIV (rec_length
) > EOBJ_S_C_MAXRECSIZ
)
394 bfd_set_error (bfd_error_file_truncated
);
398 /* adjust the buffer */
400 if (PRIV (rec_length
) > PRIV (buf_size
))
402 PRIV (vms_buf
) = (unsigned char *) realloc (vms_buf
, PRIV (rec_length
));
403 vms_buf
= PRIV (vms_buf
);
406 bfd_set_error (bfd_error_no_memory
);
409 PRIV (buf_size
) = PRIV (rec_length
);
412 /* read the remaining record */
414 remaining
= PRIV (rec_length
) - test_len
+ test_start
;
417 vms_debug (10, "bfd_read remaining %d\n", remaining
);
419 if (bfd_read (vms_buf
+ test_len
, 1, remaining
, abfd
) !=
420 (bfd_size_type
) remaining
)
422 bfd_set_error (bfd_error_file_truncated
);
425 PRIV (vms_rec
) = vms_buf
+ test_start
;
429 vms_debug (11, "bfd_read rec_length %d\n", PRIV (rec_length
));
432 return PRIV (rec_length
);
435 /* get next vms record from file
436 update vms_rec and rec_length to new (remaining) values */
439 _bfd_vms_next_record (abfd
)
443 vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
444 PRIV (rec_length
), PRIV (rec_size
));
447 if (PRIV (rec_length
) > 0)
449 PRIV (vms_rec
) += PRIV (rec_size
);
453 if (_bfd_vms_get_record (abfd
) <= 0)
457 if (!PRIV (vms_rec
) || !PRIV (vms_buf
)
458 || PRIV (vms_rec
) >= (PRIV (vms_buf
) + PRIV (buf_size
)))
463 PRIV (rec_type
) = *(PRIV (vms_rec
));
464 PRIV (rec_size
) = PRIV (rec_length
);
468 _bfd_vms_get_header_values (abfd
, PRIV (vms_rec
), &PRIV (rec_type
),
471 PRIV (rec_length
) -= PRIV (rec_size
);
474 vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
475 PRIV (vms_rec
), PRIV (rec_size
), PRIV (rec_length
),
479 return PRIV (rec_type
);
482 /* Copy sized string (string with fixed length) to new allocated area
483 size is string length (size of record) */
486 _bfd_vms_save_sized_string (str
, size
)
490 char *newstr
= bfd_malloc (size
+ 1);
494 strncpy (newstr
, (char *)str
, size
);
500 /* Copy counted string (string with length at first byte) to new allocated area
501 ptr points to length byte on entry */
504 _bfd_vms_save_counted_string (ptr
)
509 return _bfd_vms_save_sized_string (ptr
, len
);
512 /* stack routines for vms ETIR commands */
514 /* Push value and section index */
517 _bfd_vms_push (abfd
, val
, psect
)
522 static int last_psect
;
525 vms_debug (4, "<push %016lx(%d) at %d>\n", val
, psect
, PRIV (stackptr
));
531 PRIV (stack
[PRIV (stackptr
)]).value
= val
;
532 PRIV (stack
[PRIV (stackptr
)]).psect
= last_psect
;
534 if (PRIV (stackptr
) >= STACKSIZE
)
536 bfd_set_error (bfd_error_bad_value
);
537 (*_bfd_error_handler
) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr
));
543 /* Pop value and section index */
546 _bfd_vms_pop (abfd
, psect
)
552 if (PRIV (stackptr
) == 0)
554 bfd_set_error (bfd_error_bad_value
);
555 (*_bfd_error_handler
) (_("Stack underflow in _bfd_vms_pop"));
559 value
= PRIV (stack
[PRIV (stackptr
)]).value
;
560 if ((psect
!= NULL
) && (PRIV (stack
[PRIV (stackptr
)]).psect
>= 0))
561 *psect
= PRIV (stack
[PRIV (stackptr
)]).psect
;
564 vms_debug (4, "<pop %016lx(%d)>\n", value
, PRIV (stack
[PRIV (stackptr
)]).psect
);
570 /* object file output functions */
572 /* GAS tends to write sections in little chunks (bfd_set_section_contents)
573 which we can't use directly. So we save the little chunks in linked
574 lists (one per section) and write them later. */
576 /* Add a new vms_section structure to vms_section_table
577 - forward chaining - */
580 add_new_contents (abfd
, section
)
584 vms_section
*sptr
, *newptr
;
586 sptr
= PRIV (vms_section_table
)[section
->index
];
590 newptr
= (vms_section
*) bfd_malloc (sizeof (vms_section
));
591 if (newptr
== (vms_section
*) NULL
)
593 newptr
->contents
= (unsigned char *) bfd_alloc (abfd
, (int)section
->_raw_size
);
594 if (newptr
->contents
== (unsigned char *)NULL
)
597 newptr
->size
= section
->_raw_size
;
599 PRIV (vms_section_table
)[section
->index
] = newptr
;
603 /* Save section data & offset to an vms_section structure
604 vms_section_table[] holds the vms_section chain */
607 _bfd_save_vms_section (abfd
, section
, data
, offset
, count
)
616 if (section
->index
>= VMS_SECTION_COUNT
)
618 bfd_set_error (bfd_error_nonrepresentable_section
);
621 if (count
== (bfd_size_type
)0)
623 sptr
= add_new_contents (abfd
, section
);
626 memcpy (sptr
->contents
+ offset
, data
, (size_t) count
);
631 /* Get vms_section pointer to saved contents for section # index */
634 _bfd_get_vms_section (abfd
, index
)
638 if (index
>= VMS_SECTION_COUNT
)
640 bfd_set_error (bfd_error_nonrepresentable_section
);
643 return PRIV (vms_section_table
)[index
];
646 /* Object output routines */
648 /* Begin new record or record header
649 write 2 bytes rectype
650 write 2 bytes record length (filled in at flush)
651 write 2 bytes header type (ommitted if rechead == -1) */
654 _bfd_vms_output_begin (abfd
, rectype
, rechead
)
660 vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype
,
664 _bfd_vms_output_short (abfd
,rectype
);
666 /* save current output position to fill in lenght later */
668 if (PRIV (push_level
) > 0)
669 PRIV (length_pos
) = PRIV (output_size
);
672 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
676 _bfd_vms_output_short (abfd
,0); /* placeholder for length */
679 _bfd_vms_output_short (abfd
,rechead
);
684 /* Set record/subrecord alignment */
687 _bfd_vms_output_alignment (abfd
, alignto
)
692 vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto
);
695 PRIV (output_alignment
) = alignto
;
699 /* Prepare for subrecord fields */
702 _bfd_vms_output_push (abfd
)
706 vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV (output_size
));
710 PRIV (pushed_size
) = PRIV (output_size
);
714 /* End of subrecord fields */
717 _bfd_vms_output_pop (abfd
)
721 vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV (pushed_size
));
724 _bfd_vms_output_flush (abfd
);
725 PRIV (length_pos
) = 2;
728 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV (length_pos
));
731 PRIV (pushed_size
) = 0;
736 /* Flush unwritten output, ends current record */
739 _bfd_vms_output_flush (abfd
)
742 int real_size
= PRIV (output_size
);
747 vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
748 real_size
, PRIV (pushed_size
), PRIV (length_pos
));
751 if (PRIV (push_level
) > 0)
752 length
= real_size
- PRIV (pushed_size
);
758 aligncount
= (PRIV (output_alignment
)
759 - (length
% PRIV (output_alignment
))) % PRIV (output_alignment
);
762 vms_debug (6, "align: adding %d bytes\n", aligncount
);
765 while (aligncount
-- > 0)
767 PRIV (output_buf
)[real_size
++] = 0;
769 /* this is why I *love* vms: inconsistency :-}
770 alignment is added to the subrecord length
771 but not to the record length */
772 if (PRIV (push_level
) > 0)
777 /* put length to buffer */
778 PRIV (output_size
) = PRIV (length_pos
);
779 _bfd_vms_output_short (abfd
, (unsigned int)length
);
781 if (PRIV (push_level
) == 0)
784 /* write length first, see FF_FOREIGN in the input routines */
785 fwrite (PRIV (output_buf
)+2, 2, 1, (FILE *)abfd
->iostream
);
787 fwrite (PRIV (output_buf
), real_size
, 1, (FILE *)abfd
->iostream
);
789 PRIV (output_size
) = 0;
793 PRIV (output_size
) = real_size
;
794 PRIV (pushed_size
) = PRIV (output_size
);
800 /* End record output */
803 _bfd_vms_output_end (abfd
)
807 vms_debug (6, "_bfd_vms_output_end\n");
810 _bfd_vms_output_flush (abfd
);
815 /* check remaining buffer size
817 return what's left. */
820 _bfd_vms_output_check (abfd
, size
)
825 vms_debug (6, "_bfd_vms_output_check(%d)\n", size
);
828 return (MAX_OUTREC_SIZE
- (PRIV (output_size
) + size
+ MIN_OUTREC_LUFT
));
831 /* Output byte (8 bit) value */
834 _bfd_vms_output_byte (abfd
, value
)
839 vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value
);
842 bfd_put_8 (abfd
, value
& 0xff, PRIV (output_buf
) + PRIV (output_size
));
843 PRIV (output_size
) += 1;
847 /* Output short (16 bit) value */
850 _bfd_vms_output_short (abfd
, value
)
855 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value
);
858 bfd_put_16 (abfd
, value
& 0xffff, PRIV (output_buf
) + PRIV (output_size
));
859 PRIV (output_size
) += 2;
863 /* Output long (32 bit) value */
866 _bfd_vms_output_long (abfd
, value
)
871 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value
);
874 bfd_put_32 (abfd
, value
, PRIV (output_buf
) + PRIV (output_size
));
875 PRIV (output_size
) += 4;
879 /* Output quad (64 bit) value */
882 _bfd_vms_output_quad (abfd
, value
)
887 vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value
);
890 bfd_put_64(abfd
, value
, PRIV (output_buf
) + PRIV (output_size
));
891 PRIV (output_size
) += 8;
895 /* Output c-string as counted string */
898 _bfd_vms_output_counted (abfd
, value
)
905 vms_debug (6, "_bfd_vms_output_counted(%s)\n", value
);
908 len
= strlen (value
);
911 (*_bfd_error_handler
) (_("_bfd_vms_output_counted called with zero bytes"));
916 (*_bfd_error_handler
) (_("_bfd_vms_output_counted called with too many bytes"));
919 _bfd_vms_output_byte (abfd
, len
& 0xff);
920 _bfd_vms_output_dump (abfd
, (unsigned char *)value
, len
);
923 /* Output character area */
926 _bfd_vms_output_dump (abfd
, data
, length
)
932 vms_debug (6, "_bfd_vms_output_dump(%d)\n", length
);
938 memcpy (PRIV (output_buf
) + PRIV (output_size
), data
, length
);
939 PRIV (output_size
) += length
;
944 /* Output count bytes of value */
947 _bfd_vms_output_fill (abfd
, value
, count
)
953 vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value
, count
);
958 memset (PRIV (output_buf
) + PRIV (output_size
), value
, count
);
959 PRIV (output_size
) += count
;
964 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
970 register const unsigned char *p
= (unsigned char *) ptr
;
971 register const unsigned char *end
= p
+ strlen (ptr
);
972 register unsigned char c
;
973 register int hash
= 0;
978 hash
= ((hash
<< 3) + (hash
<< 15) + (hash
>> 28) + c
);
983 /* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
986 _bfd_vms_length_hash_symbol (abfd
, in
, maxlen
)
994 const char *old_name
;
996 static char outbuf
[EOBJ_S_C_SYMSIZ
+1];
1000 vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in
);
1003 if (maxlen
> EOBJ_S_C_SYMSIZ
)
1004 maxlen
= EOBJ_S_C_SYMSIZ
;
1006 new_name
= out
; /* save this for later. */
1008 /* We may need to truncate the symbol, save the hash for later. */
1010 in_len
= strlen (in
);
1012 result
= (in_len
> maxlen
) ? hash_string (in
) : 0;
1016 /* Do the length checking. */
1018 if (in_len
<= maxlen
)
1024 if (PRIV (flag_hash_long_names
))
1030 strncpy (out
, in
, i
);
1034 if ((in_len
> maxlen
)
1035 && PRIV (flag_hash_long_names
))
1036 sprintf (out
, "_%08lx", result
);
1041 vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf
), outbuf
);
1045 && PRIV (flag_hash_long_names
)
1046 && PRIV (flag_show_after_trunc
))
1047 printf (_("Symbol %s replaced by %s\n"), old_name
, new_name
);
1052 /* Allocate and initialize a new symbol. */
1055 new_symbol (abfd
, name
)
1062 _bfd_vms_debug (7, "new_symbol %s\n", name
);
1065 symbol
= _bfd_vms_make_empty_symbol (abfd
);
1068 symbol
->name
= name
;
1069 symbol
->section
= bfd_make_section (abfd
, BFD_UND_SECTION_NAME
);
1074 /* Allocate and enter a new private symbol. */
1077 _bfd_vms_enter_symbol (abfd
, name
)
1081 vms_symbol_entry
*entry
;
1084 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name
);
1087 entry
= (vms_symbol_entry
*)
1088 bfd_hash_lookup (PRIV (vms_symbol_table
), name
, false, false);
1092 _bfd_vms_debug (8, "creating hash entry for %s\n", name
);
1094 entry
= (vms_symbol_entry
*)bfd_hash_lookup (PRIV (vms_symbol_table
), name
, true, false);
1098 symbol
= new_symbol (abfd
, name
);
1101 entry
->symbol
= symbol
;
1102 PRIV (gsd_sym_count
)++;
1109 (*_bfd_error_handler
) (_("failed to enter %s"), name
);
1114 _bfd_vms_debug (8, "found hash entry for %s\n", name
);
1119 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry
, entry
->symbol
);