1 /* vms-misc.c -- Miscellaneous functions for VAX (openVMS/VAX) and
2 EVAX (openVMS/Alpha) files.
3 Copyright 1996, 1997, 1998 Free Software Foundation, Inc.
5 Written by Klaus K"ampf (kkaempf@rmi.de)
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 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
)
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__ */
126 hex dump 'size' bytes starting at 'ptr' */
129 _bfd_hexdump (level
, ptr
, size
, offset
)
135 unsigned char *lptr
= ptr
;
142 vms_debug (level
, "%08lx:", start
);
143 vms_debug (-level
, " %02x", *ptr
++);
148 while ((count
%16) != 0)
150 vms_debug (-level
, " ");
156 vms_debug (-level
, " ");
159 vms_debug (-level
, "%c", (*lptr
< 32)?'.':*lptr
);
162 vms_debug (-level
, "\n");
166 vms_debug (-level
, "\n");
175 These are needed when reading an object file. */
177 /* allocate new vms_hash_entry
178 keep the symbol name and a pointer to the bfd symbol in the table */
180 struct bfd_hash_entry
*
181 _bfd_vms_hash_newfunc (entry
, table
, string
)
182 struct bfd_hash_entry
*entry
;
183 struct bfd_hash_table
*table
;
186 vms_symbol_entry
*ret
;
189 vms_debug (5, "_bfd_vms_hash_newfunc(%p, %p, %s)\n", entry
, table
, string
);
192 if (entry
== (struct bfd_hash_entry
*)NULL
)
194 ret
= (vms_symbol_entry
*)
195 bfd_hash_allocate (table
, sizeof (vms_symbol_entry
));
196 if (ret
== (vms_symbol_entry
*) NULL
)
198 bfd_set_error (bfd_error_no_memory
);
199 return (struct bfd_hash_entry
*)NULL
;
203 /* Call the allocation method of the base class. */
205 ret
= (vms_symbol_entry
*) bfd_hash_newfunc ((struct bfd_hash_entry
*)ret
, table
, string
);
207 vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret
);
210 ret
->symbol
= (asymbol
*)NULL
;
212 return (struct bfd_hash_entry
*)ret
;
216 /* object file input functions */
218 /* Return type and length from record header (buf) on Alpha. */
221 _bfd_vms_get_header_values (abfd
, buf
, type
, length
)
228 *type
= bfd_getl16 (buf
);
231 *length
= bfd_getl16 (buf
);
234 vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type
?*type
:0), (length
?*length
:0));
242 /* Get next record from object file to vms_buf
243 set PRIV(buf_size) and return it
245 this is a little tricky since it should be portable.
247 the openVMS object file has 'variable length' which means that
248 read() returns data in chunks of (hopefully) correct and expected
249 size. The linker (and other tools on vms) depend on that. Unix doesn't
250 know about 'formatted' files, so reading and writing such an object
251 file in a unix environment is not trivial.
253 With the tool 'file' (available on all vms ftp sites), one
254 can view and change the attributes of a file. Changing from
255 'variable length' to 'fixed length, 512 bytes' reveals the
256 record length at the first 2 bytes of every record. The same
257 happens during the transfer of object files from vms to unix,
258 at least with ucx, dec's implementation of tcp/ip.
260 The vms format repeats the length at bytes 2 & 3 of every record.
262 On the first call (file_format == FF_UNKNOWN) we check if
263 the first and the third byte pair (!) of the record match.
264 If they do it's an object file in an unix environment or with
265 wrong attributes (FF_FOREIGN), else we should be in a vms
266 environment where read() returns the record size (FF_NATIVE).
268 reading is always done in 2 steps.
269 first just the record header is read and the length extracted
271 then the read buffer is adjusted and the remaining bytes are
274 all file i/o is always done on even file positions */
277 _bfd_vms_get_record (abfd
)
280 int test_len
, test_start
, remaining
;
281 unsigned char *vms_buf
;
284 vms_debug (8, "_bfd_vms_get_record\n");
287 /* minimum is 6 bytes on Alpha
288 (2 bytes length, 2 bytes record id, 2 bytes length repeated)
290 on VAX there's no length information in the record
291 so start with OBJ_S_C_MAXRECSIZ */
293 if (PRIV(buf_size
) == 0)
297 PRIV(vms_buf
) = (unsigned char *) malloc (OBJ_S_C_MAXRECSIZ
);
298 PRIV(buf_size
) = OBJ_S_C_MAXRECSIZ
;
299 PRIV(file_format
) = FF_VAX
;
302 PRIV(vms_buf
) = (unsigned char *) malloc (6);
305 vms_buf
= PRIV(vms_buf
);
309 bfd_set_error (bfd_error_no_memory
);
313 switch (PRIV(file_format
))
317 test_len
= 6; /* probe 6 bytes */
318 test_start
= 2; /* where the record starts */
332 /* skip odd alignment byte */
334 if (bfd_tell (abfd
) & 1)
336 if (bfd_read (PRIV(vms_buf
), 1, 1, abfd
) != 1)
338 bfd_set_error (bfd_error_file_truncated
);
343 /* read the record header on Alpha. */
346 && (bfd_read (PRIV(vms_buf
), 1, test_len
, abfd
) != test_len
))
348 bfd_set_error (bfd_error_file_truncated
);
352 /* check file format on first call */
354 if (PRIV(file_format
) == FF_UNKNOWN
)
355 { /* record length repeats ? */
356 if ( (vms_buf
[0] == vms_buf
[4])
357 && (vms_buf
[1] == vms_buf
[5]))
359 PRIV(file_format
) = FF_FOREIGN
; /* Y: foreign environment */
364 PRIV(file_format
) = FF_NATIVE
; /* N: native environment */
371 PRIV(rec_length
) = bfd_read (vms_buf
, 1, PRIV(buf_size
), abfd
);
372 if (PRIV(rec_length
) <= 0)
374 bfd_set_error (bfd_error_file_truncated
);
377 PRIV(vms_rec
) = vms_buf
;
381 /* extract vms record length */
383 _bfd_vms_get_header_values (abfd
, vms_buf
+test_start
, NULL
,
386 if (PRIV(rec_length
) <= 0)
388 bfd_set_error (bfd_error_file_truncated
);
392 /* that's what the linker manual says */
394 if (PRIV(rec_length
) > EOBJ_S_C_MAXRECSIZ
)
396 bfd_set_error (bfd_error_file_truncated
);
400 /* adjust the buffer */
402 if (PRIV(rec_length
) > PRIV(buf_size
))
404 PRIV(vms_buf
) = (unsigned char *) realloc (vms_buf
, PRIV(rec_length
));
405 vms_buf
= PRIV(vms_buf
);
408 bfd_set_error (bfd_error_no_memory
);
411 PRIV(buf_size
) = PRIV(rec_length
);
414 /* read the remaining record */
416 remaining
= PRIV(rec_length
) - test_len
+ test_start
;
419 vms_debug (10, "bfd_read remaining %d\n", remaining
);
421 if (bfd_read (vms_buf
+ test_len
, 1, remaining
, abfd
) != remaining
)
423 bfd_set_error (bfd_error_file_truncated
);
426 PRIV(vms_rec
) = vms_buf
+ test_start
;
430 vms_debug (11, "bfd_read rec_length %d\n", PRIV(rec_length
));
433 return PRIV(rec_length
);
437 /* get next vms record from file
438 update vms_rec and rec_length to new (remaining) values */
441 _bfd_vms_next_record (abfd
)
445 vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
446 PRIV(rec_length
), PRIV(rec_size
));
449 if (PRIV(rec_length
) > 0)
451 PRIV(vms_rec
) += PRIV(rec_size
);
455 if (_bfd_vms_get_record (abfd
) <= 0)
461 PRIV(rec_type
) = *(PRIV(vms_rec
));
462 PRIV(rec_size
) = PRIV(rec_length
);
466 _bfd_vms_get_header_values (abfd
, PRIV(vms_rec
), &PRIV(rec_type
),
469 PRIV(rec_length
) -= PRIV(rec_size
);
472 vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
473 PRIV(vms_rec
), PRIV(rec_size
), PRIV(rec_length
),
477 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
);
513 /* stack routines for vms ETIR commands */
515 /* Push value and section index */
518 _bfd_vms_push (abfd
, val
, psect
)
523 static int last_psect
;
526 vms_debug (4, "<push %016lx(%d) at %d>\n", val
, psect
, PRIV(stackptr
));
532 PRIV(stack
[PRIV(stackptr
)]).value
= val
;
533 PRIV(stack
[PRIV(stackptr
)]).psect
= last_psect
;
535 if (PRIV(stackptr
) >= STACKSIZE
)
537 bfd_set_error (bfd_error_bad_value
);
538 (*_bfd_error_handler
) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV(stackptr
));
545 /* Pop value and section index */
548 _bfd_vms_pop (abfd
, psect
)
554 if (PRIV(stackptr
) == 0)
556 bfd_set_error (bfd_error_bad_value
);
557 (*_bfd_error_handler
) (_("Stack underflow in _bfd_vms_pop"));
561 value
= PRIV(stack
[PRIV(stackptr
)]).value
;
562 if ((psect
!= NULL
) && (PRIV(stack
[PRIV(stackptr
)]).psect
>= 0))
563 *psect
= PRIV(stack
[PRIV(stackptr
)]).psect
;
566 vms_debug (4, "<pop %016lx(%d)>\n", value
, PRIV(stack
[PRIV(stackptr
)]).psect
);
573 /* object file output functions */
575 /* GAS tends to write sections in little chunks (bfd_set_section_contents)
576 which we can't use directly. So we save the little chunks in linked
577 lists (one per section) and write them later. */
579 /* Add a new vms_section structure to vms_section_table
580 - forward chaining - */
583 add_new_contents (abfd
, section
)
587 vms_section
*sptr
, *newptr
;
589 sptr
= PRIV(vms_section_table
)[section
->index
];
593 newptr
= (vms_section
*) bfd_malloc (sizeof (vms_section
));
594 if (newptr
== (vms_section
*) NULL
)
596 newptr
->contents
= (unsigned char *) bfd_alloc (abfd
, (int)section
->_raw_size
);
597 if (newptr
->contents
== (unsigned char *)NULL
)
600 newptr
->size
= section
->_raw_size
;
602 PRIV(vms_section_table
)[section
->index
] = newptr
;
607 /* Save section data & offset to an vms_section structure
608 vms_section_table[] holds the vms_section chain */
611 _bfd_save_vms_section (abfd
, section
, data
, offset
, count
)
620 if (section
->index
>= VMS_SECTION_COUNT
)
622 bfd_set_error (bfd_error_nonrepresentable_section
);
625 if (count
== (bfd_size_type
)0)
627 sptr
= add_new_contents (abfd
, section
);
630 memcpy (sptr
->contents
+ offset
, data
, (size_t) count
);
636 /* Get vms_section pointer to saved contents for section # index */
639 _bfd_get_vms_section (abfd
, index
)
643 if (index
>= VMS_SECTION_COUNT
)
645 bfd_set_error (bfd_error_nonrepresentable_section
);
648 return PRIV(vms_section_table
)[index
];
652 /* Object output routines */
654 /* Begin new record or record header
655 write 2 bytes rectype
656 write 2 bytes record length (filled in at flush)
657 write 2 bytes header type (ommitted if rechead == -1) */
660 _bfd_vms_output_begin (abfd
, rectype
, rechead
)
666 vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype
,
670 _bfd_vms_output_short (abfd
,rectype
);
672 /* save current output position to fill in lenght later */
674 if (PRIV(push_level
) > 0)
675 PRIV(length_pos
) = PRIV(output_size
);
678 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
682 _bfd_vms_output_short (abfd
,0); /* placeholder for length */
685 _bfd_vms_output_short (abfd
,rechead
);
691 /* Set record/subrecord alignment */
694 _bfd_vms_output_alignment (abfd
, alignto
)
699 vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto
);
702 PRIV(output_alignment
) = alignto
;
707 /* Prepare for subrecord fields */
710 _bfd_vms_output_push (abfd
)
714 vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV(output_size
));
718 PRIV(pushed_size
) = PRIV(output_size
);
723 /* End of subrecord fields */
726 _bfd_vms_output_pop (abfd
)
730 vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV(pushed_size
));
733 _bfd_vms_output_flush (abfd
);
734 PRIV(length_pos
) = 2;
737 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV(length_pos
));
740 PRIV(pushed_size
) = 0;
746 /* Flush unwritten output, ends current record */
749 _bfd_vms_output_flush (abfd
)
752 int real_size
= PRIV(output_size
);
757 vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
758 real_size
, PRIV(pushed_size
), PRIV(length_pos
));
761 if (PRIV(push_level
) > 0)
762 length
= real_size
- PRIV(pushed_size
);
768 aligncount
= (PRIV(output_alignment
)
769 - (length
% PRIV(output_alignment
))) % PRIV(output_alignment
);
772 vms_debug (6, "align: adding %d bytes\n", aligncount
);
775 while(aligncount
-- > 0)
777 PRIV(output_buf
)[real_size
++] = 0;
779 /* this is why I *love* vms: inconsistency :-}
780 alignment is added to the subrecord length
781 but not to the record length */
782 if (PRIV(push_level
) > 0)
787 /* put length to buffer */
788 PRIV(output_size
) = PRIV(length_pos
);
789 _bfd_vms_output_short (abfd
, (unsigned int)length
);
791 if (PRIV(push_level
) == 0)
794 /* write length first, see FF_FOREIGN in the input routines */
795 fwrite (PRIV(output_buf
)+2, 2, 1, (FILE *)abfd
->iostream
);
797 fwrite (PRIV(output_buf
), real_size
, 1, (FILE *)abfd
->iostream
);
799 PRIV(output_size
) = 0;
803 PRIV(output_size
) = real_size
;
804 PRIV(pushed_size
) = PRIV(output_size
);
811 /* End record output */
814 _bfd_vms_output_end (abfd
)
818 vms_debug (6, "_bfd_vms_output_end\n");
821 _bfd_vms_output_flush (abfd
);
827 /* check remaining buffer size
829 return what's left. */
832 _bfd_vms_output_check (abfd
, size
)
837 vms_debug (6, "_bfd_vms_output_check(%d)\n", size
);
840 return (MAX_OUTREC_SIZE
- (PRIV(output_size
) + size
+ MIN_OUTREC_LUFT
));
844 /* Output byte (8 bit) value */
847 _bfd_vms_output_byte (abfd
, value
)
852 vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value
);
855 bfd_put_8 (abfd
, value
& 0xff, PRIV(output_buf
) + PRIV(output_size
));
856 PRIV(output_size
) += 1;
861 /* Output short (16 bit) value */
864 _bfd_vms_output_short (abfd
, value
)
869 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value
);
872 bfd_put_16 (abfd
, value
& 0xffff, PRIV(output_buf
) + PRIV(output_size
));
873 PRIV(output_size
) += 2;
878 /* Output long (32 bit) value */
881 _bfd_vms_output_long (abfd
, value
)
886 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value
);
889 bfd_put_32 (abfd
, value
, PRIV(output_buf
) + PRIV(output_size
));
890 PRIV(output_size
) += 4;
895 /* Output quad (64 bit) value */
898 _bfd_vms_output_quad (abfd
, value
)
903 vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value
);
906 bfd_put_64(abfd
, value
, PRIV(output_buf
) + PRIV(output_size
));
907 PRIV(output_size
) += 8;
912 /* Output c-string as counted string */
915 _bfd_vms_output_counted (abfd
, value
)
922 vms_debug (6, "_bfd_vms_output_counted(%s)\n", value
);
925 len
= strlen (value
);
928 (*_bfd_error_handler
) (_("_bfd_vms_output_counted called with zero bytes"));
933 (*_bfd_error_handler
) (_("_bfd_vms_output_counted called with too many bytes"));
936 _bfd_vms_output_byte (abfd
, len
& 0xff);
937 _bfd_vms_output_dump (abfd
, (unsigned char *)value
, len
);
941 /* Output character area */
944 _bfd_vms_output_dump (abfd
, data
, length
)
950 vms_debug (6, "_bfd_vms_output_dump(%d)\n", length
);
956 memcpy (PRIV(output_buf
) + PRIV(output_size
), data
, length
);
957 PRIV(output_size
) += length
;
963 /* Output count bytes of value */
966 _bfd_vms_output_fill (abfd
, value
, count
)
972 vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value
, count
);
977 memset (PRIV(output_buf
) + PRIV(output_size
), value
, count
);
978 PRIV(output_size
) += count
;
983 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
989 register const unsigned char *p
= (unsigned char *) ptr
;
990 register const unsigned char *end
= p
+ strlen (ptr
);
991 register unsigned char c
;
992 register int hash
= 0;
997 hash
= ((hash
<< 3) + (hash
<< 15) + (hash
>> 28) + c
);
1002 /* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
1005 _bfd_vms_length_hash_symbol (abfd
, in
, maxlen
)
1015 const char *old_name
;
1017 static char outbuf
[EOBJ_S_C_SYMSIZ
+1];
1021 vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in
);
1024 if (maxlen
> EOBJ_S_C_SYMSIZ
)
1025 maxlen
= EOBJ_S_C_SYMSIZ
;
1027 new_name
= out
; /* save this for later. */
1029 /* We may need to truncate the symbol, save the hash for later. */
1031 in_len
= strlen (in
);
1033 result
= (in_len
> maxlen
) ? hash_string (in
) : 0;
1037 /* Do the length checking. */
1039 if (in_len
<= maxlen
)
1045 if (PRIV(flag_hash_long_names
))
1051 strncpy (out
, in
, i
);
1055 if ((in_len
> maxlen
)
1056 && PRIV(flag_hash_long_names
))
1057 sprintf (out
, "_%08x", result
);
1062 vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf
), outbuf
);
1066 && PRIV(flag_hash_long_names
)
1067 && PRIV(flag_show_after_trunc
))
1068 printf (_("Symbol %s replaced by %s\n"), old_name
, new_name
);
1074 /* Allocate and initialize a new symbol. */
1077 new_symbol (abfd
, name
)
1084 _bfd_vms_debug (7, "new_symbol %s\n", name
);
1087 symbol
= _bfd_vms_make_empty_symbol (abfd
);
1090 symbol
->name
= name
;
1091 symbol
->section
= bfd_make_section (abfd
, BFD_UND_SECTION_NAME
);
1097 /* Allocate and enter a new private symbol. */
1100 _bfd_vms_enter_symbol (abfd
, name
)
1104 vms_symbol_entry
*entry
;
1107 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name
);
1110 entry
= (vms_symbol_entry
*)
1111 bfd_hash_lookup (PRIV(vms_symbol_table
), name
, false, false);
1115 _bfd_vms_debug (8, "creating hash entry for %s\n", name
);
1117 entry
= (vms_symbol_entry
*)bfd_hash_lookup (PRIV(vms_symbol_table
), name
, true, false);
1121 symbol
= new_symbol (abfd
, name
);
1124 entry
->symbol
= symbol
;
1125 PRIV(gsd_sym_count
)++;
1132 (*_bfd_error_handler
) (_("failed to enter %s"), name
);
1137 _bfd_vms_debug (8, "found hash entry for %s\n", name
);
1142 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry
, entry
->symbol
);