1 /* vms-misc.c -- Miscellaneous functions for VAX (openVMS/VAX) and
2 EVAX (openVMS/Alpha) files.
3 Copyright 1996, 1997, 1998, 1999 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
;
201 entry
= (struct bfd_hash_entry
*) ret
;
204 /* Call the allocation method of the base class. */
206 ret
= (vms_symbol_entry
*) bfd_hash_newfunc (entry
, table
, string
);
208 vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret
);
211 ret
->symbol
= (asymbol
*)NULL
;
213 return (struct bfd_hash_entry
*)ret
;
217 /* object file input functions */
219 /* Return type and length from record header (buf) on Alpha. */
222 _bfd_vms_get_header_values (abfd
, buf
, type
, length
)
223 bfd
*abfd ATTRIBUTE_UNUSED
;
229 *type
= bfd_getl16 (buf
);
232 *length
= bfd_getl16 (buf
);
235 vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type
?*type
:0), (length
?*length
:0));
243 /* Get next record from object file to vms_buf
244 set PRIV(buf_size) and return it
246 this is a little tricky since it should be portable.
248 the openVMS object file has 'variable length' which means that
249 read() returns data in chunks of (hopefully) correct and expected
250 size. The linker (and other tools on vms) depend on that. Unix doesn't
251 know about 'formatted' files, so reading and writing such an object
252 file in a unix environment is not trivial.
254 With the tool 'file' (available on all vms ftp sites), one
255 can view and change the attributes of a file. Changing from
256 'variable length' to 'fixed length, 512 bytes' reveals the
257 record length at the first 2 bytes of every record. The same
258 happens during the transfer of object files from vms to unix,
259 at least with ucx, dec's implementation of tcp/ip.
261 The vms format repeats the length at bytes 2 & 3 of every record.
263 On the first call (file_format == FF_UNKNOWN) we check if
264 the first and the third byte pair (!) of the record match.
265 If they do it's an object file in an unix environment or with
266 wrong attributes (FF_FOREIGN), else we should be in a vms
267 environment where read() returns the record size (FF_NATIVE).
269 reading is always done in 2 steps.
270 first just the record header is read and the length extracted
272 then the read buffer is adjusted and the remaining bytes are
275 all file i/o is always done on even file positions */
278 _bfd_vms_get_record (abfd
)
281 int test_len
, test_start
, remaining
;
282 unsigned char *vms_buf
;
285 vms_debug (8, "_bfd_vms_get_record\n");
288 /* minimum is 6 bytes on Alpha
289 (2 bytes length, 2 bytes record id, 2 bytes length repeated)
291 on VAX there's no length information in the record
292 so start with OBJ_S_C_MAXRECSIZ */
294 if (PRIV(buf_size
) == 0)
298 PRIV(vms_buf
) = (unsigned char *) malloc (OBJ_S_C_MAXRECSIZ
);
299 PRIV(buf_size
) = OBJ_S_C_MAXRECSIZ
;
300 PRIV(file_format
) = FF_VAX
;
303 PRIV(vms_buf
) = (unsigned char *) malloc (6);
306 vms_buf
= PRIV(vms_buf
);
310 bfd_set_error (bfd_error_no_memory
);
314 switch (PRIV(file_format
))
318 test_len
= 6; /* probe 6 bytes */
319 test_start
= 2; /* where the record starts */
334 /* skip odd alignment byte */
336 if (bfd_tell (abfd
) & 1)
338 if (bfd_read (PRIV(vms_buf
), 1, 1, abfd
) != 1)
340 bfd_set_error (bfd_error_file_truncated
);
345 /* read the record header on Alpha. */
348 && (bfd_read (PRIV(vms_buf
), 1, test_len
, abfd
)
349 != (bfd_size_type
) test_len
))
351 bfd_set_error (bfd_error_file_truncated
);
355 /* check file format on first call */
357 if (PRIV(file_format
) == FF_UNKNOWN
)
358 { /* record length repeats ? */
359 if ( (vms_buf
[0] == vms_buf
[4])
360 && (vms_buf
[1] == vms_buf
[5]))
362 PRIV(file_format
) = FF_FOREIGN
; /* Y: foreign environment */
367 PRIV(file_format
) = FF_NATIVE
; /* N: native environment */
374 PRIV(rec_length
) = bfd_read (vms_buf
, 1, PRIV(buf_size
), abfd
);
375 if (PRIV(rec_length
) <= 0)
377 bfd_set_error (bfd_error_file_truncated
);
380 PRIV(vms_rec
) = vms_buf
;
384 /* extract vms record length */
386 _bfd_vms_get_header_values (abfd
, vms_buf
+test_start
, NULL
,
389 if (PRIV(rec_length
) <= 0)
391 bfd_set_error (bfd_error_file_truncated
);
395 /* that's what the linker manual says */
397 if (PRIV(rec_length
) > EOBJ_S_C_MAXRECSIZ
)
399 bfd_set_error (bfd_error_file_truncated
);
403 /* adjust the buffer */
405 if (PRIV(rec_length
) > PRIV(buf_size
))
407 PRIV(vms_buf
) = (unsigned char *) realloc (vms_buf
, PRIV(rec_length
));
408 vms_buf
= PRIV(vms_buf
);
411 bfd_set_error (bfd_error_no_memory
);
414 PRIV(buf_size
) = PRIV(rec_length
);
417 /* read the remaining record */
419 remaining
= PRIV(rec_length
) - test_len
+ test_start
;
422 vms_debug (10, "bfd_read remaining %d\n", remaining
);
424 if (bfd_read (vms_buf
+ test_len
, 1, remaining
, abfd
) !=
425 (bfd_size_type
) remaining
)
427 bfd_set_error (bfd_error_file_truncated
);
430 PRIV(vms_rec
) = vms_buf
+ test_start
;
434 vms_debug (11, "bfd_read rec_length %d\n", PRIV(rec_length
));
437 return PRIV(rec_length
);
441 /* get next vms record from file
442 update vms_rec and rec_length to new (remaining) values */
445 _bfd_vms_next_record (abfd
)
449 vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
450 PRIV(rec_length
), PRIV(rec_size
));
453 if (PRIV(rec_length
) > 0)
455 PRIV(vms_rec
) += PRIV(rec_size
);
459 if (_bfd_vms_get_record (abfd
) <= 0)
468 PRIV(rec_type
) = *(PRIV(vms_rec
));
469 PRIV(rec_size
) = PRIV(rec_length
);
473 _bfd_vms_get_header_values (abfd
, PRIV(vms_rec
), &PRIV(rec_type
),
476 PRIV(rec_length
) -= PRIV(rec_size
);
479 vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
480 PRIV(vms_rec
), PRIV(rec_size
), PRIV(rec_length
),
484 return PRIV(rec_type
);
489 /* Copy sized string (string with fixed length) to new allocated area
490 size is string length (size of record) */
493 _bfd_vms_save_sized_string (str
, size
)
497 char *newstr
= bfd_malloc (size
+ 1);
501 strncpy (newstr
, (char *)str
, size
);
507 /* Copy counted string (string with length at first byte) to new allocated area
508 ptr points to length byte on entry */
511 _bfd_vms_save_counted_string (ptr
)
516 return _bfd_vms_save_sized_string (ptr
, len
);
520 /* stack routines for vms ETIR commands */
522 /* Push value and section index */
525 _bfd_vms_push (abfd
, val
, psect
)
530 static int last_psect
;
533 vms_debug (4, "<push %016lx(%d) at %d>\n", val
, psect
, PRIV(stackptr
));
539 PRIV(stack
[PRIV(stackptr
)]).value
= val
;
540 PRIV(stack
[PRIV(stackptr
)]).psect
= last_psect
;
542 if (PRIV(stackptr
) >= STACKSIZE
)
544 bfd_set_error (bfd_error_bad_value
);
545 (*_bfd_error_handler
) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV(stackptr
));
552 /* Pop value and section index */
555 _bfd_vms_pop (abfd
, psect
)
561 if (PRIV(stackptr
) == 0)
563 bfd_set_error (bfd_error_bad_value
);
564 (*_bfd_error_handler
) (_("Stack underflow in _bfd_vms_pop"));
568 value
= PRIV(stack
[PRIV(stackptr
)]).value
;
569 if ((psect
!= NULL
) && (PRIV(stack
[PRIV(stackptr
)]).psect
>= 0))
570 *psect
= PRIV(stack
[PRIV(stackptr
)]).psect
;
573 vms_debug (4, "<pop %016lx(%d)>\n", value
, PRIV(stack
[PRIV(stackptr
)]).psect
);
580 /* object file output functions */
582 /* GAS tends to write sections in little chunks (bfd_set_section_contents)
583 which we can't use directly. So we save the little chunks in linked
584 lists (one per section) and write them later. */
586 /* Add a new vms_section structure to vms_section_table
587 - forward chaining - */
590 add_new_contents (abfd
, section
)
594 vms_section
*sptr
, *newptr
;
596 sptr
= PRIV(vms_section_table
)[section
->index
];
600 newptr
= (vms_section
*) bfd_malloc (sizeof (vms_section
));
601 if (newptr
== (vms_section
*) NULL
)
603 newptr
->contents
= (unsigned char *) bfd_alloc (abfd
, (int)section
->_raw_size
);
604 if (newptr
->contents
== (unsigned char *)NULL
)
607 newptr
->size
= section
->_raw_size
;
609 PRIV(vms_section_table
)[section
->index
] = newptr
;
614 /* Save section data & offset to an vms_section structure
615 vms_section_table[] holds the vms_section chain */
618 _bfd_save_vms_section (abfd
, section
, data
, offset
, count
)
627 if (section
->index
>= VMS_SECTION_COUNT
)
629 bfd_set_error (bfd_error_nonrepresentable_section
);
632 if (count
== (bfd_size_type
)0)
634 sptr
= add_new_contents (abfd
, section
);
637 memcpy (sptr
->contents
+ offset
, data
, (size_t) count
);
643 /* Get vms_section pointer to saved contents for section # index */
646 _bfd_get_vms_section (abfd
, index
)
650 if (index
>= VMS_SECTION_COUNT
)
652 bfd_set_error (bfd_error_nonrepresentable_section
);
655 return PRIV(vms_section_table
)[index
];
659 /* Object output routines */
661 /* Begin new record or record header
662 write 2 bytes rectype
663 write 2 bytes record length (filled in at flush)
664 write 2 bytes header type (ommitted if rechead == -1) */
667 _bfd_vms_output_begin (abfd
, rectype
, rechead
)
673 vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype
,
677 _bfd_vms_output_short (abfd
,rectype
);
679 /* save current output position to fill in lenght later */
681 if (PRIV(push_level
) > 0)
682 PRIV(length_pos
) = PRIV(output_size
);
685 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
689 _bfd_vms_output_short (abfd
,0); /* placeholder for length */
692 _bfd_vms_output_short (abfd
,rechead
);
698 /* Set record/subrecord alignment */
701 _bfd_vms_output_alignment (abfd
, alignto
)
706 vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto
);
709 PRIV(output_alignment
) = alignto
;
714 /* Prepare for subrecord fields */
717 _bfd_vms_output_push (abfd
)
721 vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV(output_size
));
725 PRIV(pushed_size
) = PRIV(output_size
);
730 /* End of subrecord fields */
733 _bfd_vms_output_pop (abfd
)
737 vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV(pushed_size
));
740 _bfd_vms_output_flush (abfd
);
741 PRIV(length_pos
) = 2;
744 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV(length_pos
));
747 PRIV(pushed_size
) = 0;
753 /* Flush unwritten output, ends current record */
756 _bfd_vms_output_flush (abfd
)
759 int real_size
= PRIV(output_size
);
764 vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
765 real_size
, PRIV(pushed_size
), PRIV(length_pos
));
768 if (PRIV(push_level
) > 0)
769 length
= real_size
- PRIV(pushed_size
);
775 aligncount
= (PRIV(output_alignment
)
776 - (length
% PRIV(output_alignment
))) % PRIV(output_alignment
);
779 vms_debug (6, "align: adding %d bytes\n", aligncount
);
782 while(aligncount
-- > 0)
784 PRIV(output_buf
)[real_size
++] = 0;
786 /* this is why I *love* vms: inconsistency :-}
787 alignment is added to the subrecord length
788 but not to the record length */
789 if (PRIV(push_level
) > 0)
794 /* put length to buffer */
795 PRIV(output_size
) = PRIV(length_pos
);
796 _bfd_vms_output_short (abfd
, (unsigned int)length
);
798 if (PRIV(push_level
) == 0)
801 /* write length first, see FF_FOREIGN in the input routines */
802 fwrite (PRIV(output_buf
)+2, 2, 1, (FILE *)abfd
->iostream
);
804 fwrite (PRIV(output_buf
), real_size
, 1, (FILE *)abfd
->iostream
);
806 PRIV(output_size
) = 0;
810 PRIV(output_size
) = real_size
;
811 PRIV(pushed_size
) = PRIV(output_size
);
818 /* End record output */
821 _bfd_vms_output_end (abfd
)
825 vms_debug (6, "_bfd_vms_output_end\n");
828 _bfd_vms_output_flush (abfd
);
834 /* check remaining buffer size
836 return what's left. */
839 _bfd_vms_output_check (abfd
, size
)
844 vms_debug (6, "_bfd_vms_output_check(%d)\n", size
);
847 return (MAX_OUTREC_SIZE
- (PRIV(output_size
) + size
+ MIN_OUTREC_LUFT
));
851 /* Output byte (8 bit) value */
854 _bfd_vms_output_byte (abfd
, value
)
859 vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value
);
862 bfd_put_8 (abfd
, value
& 0xff, PRIV(output_buf
) + PRIV(output_size
));
863 PRIV(output_size
) += 1;
868 /* Output short (16 bit) value */
871 _bfd_vms_output_short (abfd
, value
)
876 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value
);
879 bfd_put_16 (abfd
, value
& 0xffff, PRIV(output_buf
) + PRIV(output_size
));
880 PRIV(output_size
) += 2;
885 /* Output long (32 bit) value */
888 _bfd_vms_output_long (abfd
, value
)
893 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value
);
896 bfd_put_32 (abfd
, value
, PRIV(output_buf
) + PRIV(output_size
));
897 PRIV(output_size
) += 4;
902 /* Output quad (64 bit) value */
905 _bfd_vms_output_quad (abfd
, value
)
910 vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value
);
913 bfd_put_64(abfd
, value
, PRIV(output_buf
) + PRIV(output_size
));
914 PRIV(output_size
) += 8;
919 /* Output c-string as counted string */
922 _bfd_vms_output_counted (abfd
, value
)
929 vms_debug (6, "_bfd_vms_output_counted(%s)\n", value
);
932 len
= strlen (value
);
935 (*_bfd_error_handler
) (_("_bfd_vms_output_counted called with zero bytes"));
940 (*_bfd_error_handler
) (_("_bfd_vms_output_counted called with too many bytes"));
943 _bfd_vms_output_byte (abfd
, len
& 0xff);
944 _bfd_vms_output_dump (abfd
, (unsigned char *)value
, len
);
948 /* Output character area */
951 _bfd_vms_output_dump (abfd
, data
, length
)
957 vms_debug (6, "_bfd_vms_output_dump(%d)\n", length
);
963 memcpy (PRIV(output_buf
) + PRIV(output_size
), data
, length
);
964 PRIV(output_size
) += length
;
970 /* Output count bytes of value */
973 _bfd_vms_output_fill (abfd
, value
, count
)
979 vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value
, count
);
984 memset (PRIV(output_buf
) + PRIV(output_size
), value
, count
);
985 PRIV(output_size
) += count
;
990 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
996 register const unsigned char *p
= (unsigned char *) ptr
;
997 register const unsigned char *end
= p
+ strlen (ptr
);
998 register unsigned char c
;
999 register int hash
= 0;
1004 hash
= ((hash
<< 3) + (hash
<< 15) + (hash
>> 28) + c
);
1009 /* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
1012 _bfd_vms_length_hash_symbol (abfd
, in
, maxlen
)
1020 const char *old_name
;
1022 static char outbuf
[EOBJ_S_C_SYMSIZ
+1];
1026 vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in
);
1029 if (maxlen
> EOBJ_S_C_SYMSIZ
)
1030 maxlen
= EOBJ_S_C_SYMSIZ
;
1032 new_name
= out
; /* save this for later. */
1034 /* We may need to truncate the symbol, save the hash for later. */
1036 in_len
= strlen (in
);
1038 result
= (in_len
> maxlen
) ? hash_string (in
) : 0;
1042 /* Do the length checking. */
1044 if (in_len
<= maxlen
)
1050 if (PRIV(flag_hash_long_names
))
1056 strncpy (out
, in
, i
);
1060 if ((in_len
> maxlen
)
1061 && PRIV(flag_hash_long_names
))
1062 sprintf (out
, "_%08lx", result
);
1067 vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf
), outbuf
);
1071 && PRIV(flag_hash_long_names
)
1072 && PRIV(flag_show_after_trunc
))
1073 printf (_("Symbol %s replaced by %s\n"), old_name
, new_name
);
1079 /* Allocate and initialize a new symbol. */
1082 new_symbol (abfd
, name
)
1089 _bfd_vms_debug (7, "new_symbol %s\n", name
);
1092 symbol
= _bfd_vms_make_empty_symbol (abfd
);
1095 symbol
->name
= name
;
1096 symbol
->section
= bfd_make_section (abfd
, BFD_UND_SECTION_NAME
);
1102 /* Allocate and enter a new private symbol. */
1105 _bfd_vms_enter_symbol (abfd
, name
)
1109 vms_symbol_entry
*entry
;
1112 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name
);
1115 entry
= (vms_symbol_entry
*)
1116 bfd_hash_lookup (PRIV(vms_symbol_table
), name
, false, false);
1120 _bfd_vms_debug (8, "creating hash entry for %s\n", name
);
1122 entry
= (vms_symbol_entry
*)bfd_hash_lookup (PRIV(vms_symbol_table
), name
, true, false);
1126 symbol
= new_symbol (abfd
, name
);
1129 entry
->symbol
= symbol
;
1130 PRIV(gsd_sym_count
)++;
1137 (*_bfd_error_handler
) (_("failed to enter %s"), name
);
1142 _bfd_vms_debug (8, "found hash entry for %s\n", name
);
1147 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry
, entry
->symbol
);