1 /* vms-misc.c -- Miscellaneous functions for VAX (openVMS/VAX) and
2 EVAX (openVMS/Alpha) files.
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
34 /* Debug functions. */
36 /* Debug function for all vms extensions
37 evaluates environment variable VMS_DEBUG for a
38 numerical value on the first call
39 all error levels below this value are printed
42 1 toplevel bfd calls (functions from the bfd vector)
43 2 functions called by bfd calls
47 level is also indentation level. Indentation is performed
51 _bfd_vms_debug (int level
, char *format
, ...)
53 static int min_level
= -1;
54 static FILE *output
= NULL
;
57 int abslvl
= (level
> 0) ? level
: - level
;
61 if ((eptr
= getenv ("VMS_DEBUG")) != NULL
)
63 min_level
= atoi (eptr
);
71 if (abslvl
> min_level
)
75 fprintf (output
, " ");
76 va_start (args
, format
);
77 vfprintf (output
, format
, args
);
83 hex dump 'size' bytes starting at 'ptr'. */
86 _bfd_hexdump (int level
,
91 unsigned char *lptr
= ptr
;
98 vms_debug (level
, "%08lx:", start
);
99 vms_debug (-level
, " %02x", *ptr
++);
104 while ((count
%16) != 0)
106 vms_debug (-level
, " ");
112 vms_debug (-level
, " ");
115 vms_debug (-level
, "%c", (*lptr
< 32)?'.':*lptr
);
118 vms_debug (-level
, "\n");
122 vms_debug (-level
, "\n");
128 These are needed when reading an object file. */
130 /* Allocate new vms_hash_entry
131 keep the symbol name and a pointer to the bfd symbol in the table. */
133 struct bfd_hash_entry
*
134 _bfd_vms_hash_newfunc (struct bfd_hash_entry
*entry
,
135 struct bfd_hash_table
*table
,
138 vms_symbol_entry
*ret
;
141 vms_debug (5, "_bfd_vms_hash_newfunc (%p, %p, %s)\n", entry
, table
, string
);
146 ret
= (vms_symbol_entry
*)
147 bfd_hash_allocate (table
, sizeof (vms_symbol_entry
));
150 bfd_set_error (bfd_error_no_memory
);
153 entry
= (struct bfd_hash_entry
*) ret
;
156 /* Call the allocation method of the base class. */
157 ret
= (vms_symbol_entry
*) bfd_hash_newfunc (entry
, table
, string
);
159 vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret
);
164 return (struct bfd_hash_entry
*)ret
;
167 /* Object file input functions. */
169 /* Return type and length from record header (buf) on Alpha. */
172 _bfd_vms_get_header_values (bfd
* abfd ATTRIBUTE_UNUSED
,
178 *type
= bfd_getl16 (buf
);
181 *length
= bfd_getl16 (buf
);
184 vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type
?*type
:0), (length
?*length
:0));
188 /* Get next record from object file to vms_buf.
189 Set PRIV(buf_size) and return it
191 This is a little tricky since it should be portable.
193 The openVMS object file has 'variable length' which means that
194 read() returns data in chunks of (hopefully) correct and expected
195 size. The linker (and other tools on vms) depend on that. Unix doesn't
196 know about 'formatted' files, so reading and writing such an object
197 file in a unix environment is not trivial.
199 With the tool 'file' (available on all vms ftp sites), one
200 can view and change the attributes of a file. Changing from
201 'variable length' to 'fixed length, 512 bytes' reveals the
202 record length at the first 2 bytes of every record. The same
203 happens during the transfer of object files from vms to unix,
204 at least with ucx, dec's implementation of tcp/ip.
206 The vms format repeats the length at bytes 2 & 3 of every record.
208 On the first call (file_format == FF_UNKNOWN) we check if
209 the first and the third byte pair (!) of the record match.
210 If they do it's an object file in an unix environment or with
211 wrong attributes (FF_FOREIGN), else we should be in a vms
212 environment where read() returns the record size (FF_NATIVE).
214 Reading is always done in 2 steps.
215 First just the record header is read and the length extracted
216 by get_header_values,
217 then the read buffer is adjusted and the remaining bytes are
220 All file i/o is always done on even file positions. */
223 _bfd_vms_get_record (bfd
* abfd
)
225 int test_len
, test_start
, remaining
;
226 unsigned char *vms_buf
;
229 vms_debug (8, "_bfd_vms_get_record\n");
232 /* Minimum is 6 bytes on Alpha
233 (2 bytes length, 2 bytes record id, 2 bytes length repeated)
235 On the VAX there's no length information in the record
236 so start with OBJ_S_C_MAXRECSIZ. */
238 if (PRIV (buf_size
) == 0)
244 amt
= OBJ_S_C_MAXRECSIZ
;
245 PRIV (file_format
) = FF_VAX
;
249 PRIV (vms_buf
) = bfd_malloc (amt
);
250 PRIV (buf_size
) = amt
;
253 vms_buf
= PRIV (vms_buf
);
258 switch (PRIV (file_format
))
262 test_len
= 6; /* Probe 6 bytes. */
263 test_start
= 2; /* Where the record starts. */
278 /* Skip odd alignment byte. */
280 if (bfd_tell (abfd
) & 1)
282 if (bfd_bread (PRIV (vms_buf
), (bfd_size_type
) 1, abfd
) != 1)
284 bfd_set_error (bfd_error_file_truncated
);
289 /* Read the record header on Alpha. */
291 && (bfd_bread (PRIV (vms_buf
), (bfd_size_type
) test_len
, abfd
)
292 != (bfd_size_type
) test_len
))
294 bfd_set_error (bfd_error_file_truncated
);
298 /* Check file format on first call. */
299 if (PRIV (file_format
) == FF_UNKNOWN
)
300 { /* Record length repeats ? */
301 if (vms_buf
[0] == vms_buf
[4]
302 && vms_buf
[1] == vms_buf
[5])
304 PRIV (file_format
) = FF_FOREIGN
; /* Y: foreign environment. */
309 PRIV (file_format
) = FF_NATIVE
; /* N: native environment. */
316 PRIV (rec_length
) = bfd_bread (vms_buf
, (bfd_size_type
) PRIV (buf_size
),
318 if (PRIV (rec_length
) <= 0)
320 bfd_set_error (bfd_error_file_truncated
);
323 PRIV (vms_rec
) = vms_buf
;
328 /* Extract vms record length. */
330 _bfd_vms_get_header_values (abfd
, vms_buf
+ test_start
, NULL
,
331 & PRIV (rec_length
));
333 if (PRIV (rec_length
) <= 0)
335 bfd_set_error (bfd_error_file_truncated
);
339 /* That's what the linker manual says. */
341 if (PRIV (rec_length
) > EOBJ_S_C_MAXRECSIZ
)
343 bfd_set_error (bfd_error_file_truncated
);
347 /* Adjust the buffer. */
349 if (PRIV (rec_length
) > PRIV (buf_size
))
351 PRIV (vms_buf
) = bfd_realloc (vms_buf
,
352 (bfd_size_type
) PRIV (rec_length
));
353 vms_buf
= PRIV (vms_buf
);
356 PRIV (buf_size
) = PRIV (rec_length
);
359 /* Read the remaining record. */
360 remaining
= PRIV (rec_length
) - test_len
+ test_start
;
363 vms_debug (10, "bfd_bread remaining %d\n", remaining
);
365 if (bfd_bread (vms_buf
+ test_len
, (bfd_size_type
) remaining
, abfd
) !=
366 (bfd_size_type
) remaining
)
368 bfd_set_error (bfd_error_file_truncated
);
371 PRIV (vms_rec
) = vms_buf
+ test_start
;
375 vms_debug (11, "bfd_bread rec_length %d\n", PRIV (rec_length
));
378 return PRIV (rec_length
);
381 /* Get next vms record from file
382 update vms_rec and rec_length to new (remaining) values. */
385 _bfd_vms_next_record (bfd
* abfd
)
388 vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
389 PRIV (rec_length
), PRIV (rec_size
));
392 if (PRIV (rec_length
) > 0)
393 PRIV (vms_rec
) += PRIV (rec_size
);
396 if (_bfd_vms_get_record (abfd
) <= 0)
400 if (!PRIV (vms_rec
) || !PRIV (vms_buf
)
401 || PRIV (vms_rec
) >= (PRIV (vms_buf
) + PRIV (buf_size
)))
406 PRIV (rec_type
) = *(PRIV (vms_rec
));
407 PRIV (rec_size
) = PRIV (rec_length
);
410 _bfd_vms_get_header_values (abfd
, PRIV (vms_rec
), &PRIV (rec_type
),
413 PRIV (rec_length
) -= PRIV (rec_size
);
416 vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
417 PRIV (vms_rec
), PRIV (rec_size
), PRIV (rec_length
),
421 return PRIV (rec_type
);
424 /* Copy sized string (string with fixed length) to new allocated area
425 size is string length (size of record) */
428 _bfd_vms_save_sized_string (unsigned char *str
, int size
)
430 char *newstr
= bfd_malloc ((bfd_size_type
) size
+ 1);
434 strncpy (newstr
, (char *) str
, (size_t) size
);
440 /* Copy counted string (string with length at first byte) to new allocated area
441 ptr points to length byte on entry */
444 _bfd_vms_save_counted_string (unsigned char *ptr
)
448 return _bfd_vms_save_sized_string (ptr
, len
);
451 /* Stack routines for vms ETIR commands. */
453 /* Push value and section index. */
456 _bfd_vms_push (bfd
* abfd
, uquad val
, int psect
)
458 static int last_psect
;
461 vms_debug (4, "<push %016lx (%d) at %d>\n", val
, psect
, PRIV (stackptr
));
467 PRIV (stack
[PRIV (stackptr
)]).value
= val
;
468 PRIV (stack
[PRIV (stackptr
)]).psect
= last_psect
;
470 if (PRIV (stackptr
) >= STACKSIZE
)
472 bfd_set_error (bfd_error_bad_value
);
473 (*_bfd_error_handler
) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr
));
478 /* Pop value and section index. */
481 _bfd_vms_pop (bfd
* abfd
, int *psect
)
485 if (PRIV (stackptr
) == 0)
487 bfd_set_error (bfd_error_bad_value
);
488 (*_bfd_error_handler
) (_("Stack underflow in _bfd_vms_pop"));
492 value
= PRIV (stack
[PRIV (stackptr
)]).value
;
493 if ((psect
!= NULL
) && (PRIV (stack
[PRIV (stackptr
)]).psect
>= 0))
494 *psect
= PRIV (stack
[PRIV (stackptr
)]).psect
;
497 vms_debug (4, "<pop %016lx(%d)>\n", value
, PRIV (stack
[PRIV (stackptr
)]).psect
);
503 /* Object file output functions. */
505 /* GAS tends to write sections in little chunks (bfd_set_section_contents)
506 which we can't use directly. So we save the little chunks in linked
507 lists (one per section) and write them later. */
509 /* Add a new vms_section structure to vms_section_table
510 - forward chaining -. */
513 add_new_contents (bfd
* abfd
, sec_ptr section
)
515 vms_section
*sptr
, *newptr
;
517 sptr
= PRIV (vms_section_table
)[section
->index
];
521 newptr
= bfd_alloc (abfd
, (bfd_size_type
) sizeof (vms_section
));
524 newptr
->contents
= bfd_alloc (abfd
, section
->size
);
525 if (newptr
->contents
== NULL
)
528 newptr
->size
= section
->size
;
530 PRIV (vms_section_table
)[section
->index
] = newptr
;
534 /* Save section data & offset to a vms_section structure
535 vms_section_table[] holds the vms_section chain. */
538 _bfd_save_vms_section (bfd
* abfd
,
546 if (section
->index
>= VMS_SECTION_COUNT
)
548 bfd_set_error (bfd_error_nonrepresentable_section
);
551 if (count
== (bfd_size_type
)0)
553 sptr
= add_new_contents (abfd
, section
);
556 memcpy (sptr
->contents
+ offset
, data
, (size_t) count
);
561 /* Get vms_section pointer to saved contents for section # index */
564 _bfd_get_vms_section (bfd
* abfd
, int index
)
566 if (index
>= VMS_SECTION_COUNT
)
568 bfd_set_error (bfd_error_nonrepresentable_section
);
571 return PRIV (vms_section_table
)[index
];
574 /* Object output routines. */
576 /* Begin new record or record header
577 write 2 bytes rectype
578 write 2 bytes record length (filled in at flush)
579 write 2 bytes header type (ommitted if rechead == -1). */
582 _bfd_vms_output_begin (bfd
* abfd
, int rectype
, int rechead
)
585 vms_debug (6, "_bfd_vms_output_begin (type %d, head %d)\n", rectype
,
589 _bfd_vms_output_short (abfd
, (unsigned int) rectype
);
591 /* Save current output position to fill in length later. */
593 if (PRIV (push_level
) > 0)
594 PRIV (length_pos
) = PRIV (output_size
);
597 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
601 /* Placeholder for length. */
602 _bfd_vms_output_short (abfd
, 0);
605 _bfd_vms_output_short (abfd
, (unsigned int) rechead
);
608 /* Set record/subrecord alignment. */
611 _bfd_vms_output_alignment (bfd
* abfd
, int alignto
)
614 vms_debug (6, "_bfd_vms_output_alignment (%d)\n", alignto
);
617 PRIV (output_alignment
) = alignto
;
620 /* Prepare for subrecord fields. */
623 _bfd_vms_output_push (bfd
* abfd
)
626 vms_debug (6, "vms_output_push (pushed_size = %d)\n", PRIV (output_size
));
630 PRIV (pushed_size
) = PRIV (output_size
);
633 /* End of subrecord fields. */
636 _bfd_vms_output_pop (bfd
* abfd
)
639 vms_debug (6, "vms_output_pop (pushed_size = %d)\n", PRIV (pushed_size
));
642 _bfd_vms_output_flush (abfd
);
643 PRIV (length_pos
) = 2;
646 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV (length_pos
));
649 PRIV (pushed_size
) = 0;
653 /* Flush unwritten output, ends current record. */
656 _bfd_vms_output_flush (bfd
* abfd
)
658 int real_size
= PRIV (output_size
);
663 vms_debug (6, "_bfd_vms_output_flush (real_size = %d, pushed_size %d at lenpos %d)\n",
664 real_size
, PRIV (pushed_size
), PRIV (length_pos
));
667 if (PRIV (push_level
) > 0)
668 length
= real_size
- PRIV (pushed_size
);
674 aligncount
= (PRIV (output_alignment
)
675 - (length
% PRIV (output_alignment
))) % PRIV (output_alignment
);
678 vms_debug (6, "align: adding %d bytes\n", aligncount
);
681 while (aligncount
-- > 0)
683 PRIV (output_buf
)[real_size
++] = 0;
687 /* Put length to buffer. */
688 PRIV (output_size
) = PRIV (length_pos
);
689 _bfd_vms_output_short (abfd
, (unsigned int) length
);
691 if (PRIV (push_level
) == 0)
694 /* Write length first, see FF_FOREIGN in the input routines. */
695 fwrite (PRIV (output_buf
) + 2, 2, 1, (FILE *) abfd
->iostream
);
697 fwrite (PRIV (output_buf
), (size_t) real_size
, 1,
698 (FILE *) abfd
->iostream
);
700 PRIV (output_size
) = 0;
704 PRIV (output_size
) = real_size
;
705 PRIV (pushed_size
) = PRIV (output_size
);
709 /* End record output. */
712 _bfd_vms_output_end (bfd
* abfd
)
715 vms_debug (6, "_bfd_vms_output_end\n");
718 _bfd_vms_output_flush (abfd
);
721 /* Check remaining buffer size
723 Return what's left. */
726 _bfd_vms_output_check (bfd
* abfd
, int size
)
729 vms_debug (6, "_bfd_vms_output_check (%d)\n", size
);
732 return (MAX_OUTREC_SIZE
- (PRIV (output_size
) + size
+ MIN_OUTREC_LUFT
));
735 /* Output byte (8 bit) value. */
738 _bfd_vms_output_byte (bfd
* abfd
, unsigned int value
)
741 vms_debug (6, "_bfd_vms_output_byte (%02x)\n", value
);
744 bfd_put_8 (abfd
, value
& 0xff, PRIV (output_buf
) + PRIV (output_size
));
745 PRIV (output_size
) += 1;
748 /* Output short (16 bit) value. */
751 _bfd_vms_output_short (bfd
* abfd
, unsigned int value
)
754 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value
);
757 bfd_put_16 (abfd
, (bfd_vma
) value
& 0xffff,
758 PRIV (output_buf
) + PRIV (output_size
));
759 PRIV (output_size
) += 2;
762 /* Output long (32 bit) value. */
765 _bfd_vms_output_long (bfd
* abfd
, unsigned long value
)
768 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value
);
771 bfd_put_32 (abfd
, (bfd_vma
) value
, PRIV (output_buf
) + PRIV (output_size
));
772 PRIV (output_size
) += 4;
775 /* Output quad (64 bit) value. */
778 _bfd_vms_output_quad (bfd
* abfd
, uquad value
)
781 vms_debug (6, "_bfd_vms_output_quad (%016lx)\n", value
);
784 bfd_put_64(abfd
, value
, PRIV (output_buf
) + PRIV (output_size
));
785 PRIV (output_size
) += 8;
788 /* Output c-string as counted string. */
791 _bfd_vms_output_counted (bfd
* abfd
, char *value
)
796 vms_debug (6, "_bfd_vms_output_counted (%s)\n", value
);
799 len
= strlen (value
);
802 (*_bfd_error_handler
) (_("_bfd_vms_output_counted called with zero bytes"));
807 (*_bfd_error_handler
) (_("_bfd_vms_output_counted called with too many bytes"));
810 _bfd_vms_output_byte (abfd
, (unsigned int) len
& 0xff);
811 _bfd_vms_output_dump (abfd
, (unsigned char *) value
, len
);
814 /* Output character area. */
817 _bfd_vms_output_dump (bfd
* abfd
,
822 vms_debug (6, "_bfd_vms_output_dump (%d)\n", length
);
828 memcpy (PRIV (output_buf
) + PRIV (output_size
), data
, (size_t) length
);
829 PRIV (output_size
) += length
;
832 /* Output count bytes of value. */
835 _bfd_vms_output_fill (bfd
* abfd
,
840 vms_debug (6, "_bfd_vms_output_fill (val %02x times %d)\n", value
, count
);
845 memset (PRIV (output_buf
) + PRIV (output_size
), value
, (size_t) count
);
846 PRIV (output_size
) += count
;
849 /* This hash routine borrowed from GNU-EMACS, and strengthened slightly. ERY. */
852 hash_string (const char *ptr
)
854 const unsigned char *p
= (unsigned char *) ptr
;
855 const unsigned char *end
= p
+ strlen (ptr
);
862 hash
= ((hash
<< 3) + (hash
<< 15) + (hash
>> 28) + c
);
867 /* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
870 _bfd_vms_length_hash_symbol (bfd
* abfd
, const char *in
, int maxlen
)
875 const char *old_name
;
877 static char outbuf
[EOBJ_S_C_SYMSIZ
+1];
881 vms_debug (4, "_bfd_vms_length_hash_symbol \"%s\"\n", in
);
884 if (maxlen
> EOBJ_S_C_SYMSIZ
)
885 maxlen
= EOBJ_S_C_SYMSIZ
;
887 /* Save this for later. */
890 /* We may need to truncate the symbol, save the hash for later. */
891 in_len
= strlen (in
);
893 result
= (in_len
> maxlen
) ? hash_string (in
) : 0;
897 /* Do the length checking. */
898 if (in_len
<= maxlen
)
902 if (PRIV (flag_hash_long_names
))
908 strncpy (out
, in
, (size_t) i
);
912 if ((in_len
> maxlen
)
913 && PRIV (flag_hash_long_names
))
914 sprintf (out
, "_%08lx", result
);
919 vms_debug (4, "--> [%d]\"%s\"\n", strlen (outbuf
), outbuf
);
923 && PRIV (flag_hash_long_names
)
924 && PRIV (flag_show_after_trunc
))
925 printf (_("Symbol %s replaced by %s\n"), old_name
, new_name
);
930 /* Allocate and initialize a new symbol. */
933 new_symbol (bfd
* abfd
, char *name
)
938 _bfd_vms_debug (7, "new_symbol %s\n", name
);
941 symbol
= bfd_make_empty_symbol (abfd
);
945 symbol
->section
= bfd_make_section (abfd
, BFD_UND_SECTION_NAME
);
950 /* Allocate and enter a new private symbol. */
953 _bfd_vms_enter_symbol (bfd
* abfd
, char *name
)
955 vms_symbol_entry
*entry
;
958 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name
);
961 entry
= (vms_symbol_entry
*)
962 bfd_hash_lookup (PRIV (vms_symbol_table
), name
, FALSE
, FALSE
);
966 _bfd_vms_debug (8, "creating hash entry for %s\n", name
);
968 entry
= (vms_symbol_entry
*) bfd_hash_lookup (PRIV (vms_symbol_table
),
973 symbol
= new_symbol (abfd
, name
);
976 entry
->symbol
= symbol
;
977 PRIV (gsd_sym_count
)++;
984 (*_bfd_error_handler
) (_("failed to enter %s"), name
);
989 _bfd_vms_debug (8, "found hash entry for %s\n", name
);
994 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry
, entry
->symbol
);