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 2007 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 3 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,
21 MA 02110-1301, USA. */
35 /* Debug functions. */
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 indentation level. Indentation is performed
52 _bfd_vms_debug (int level
, char *format
, ...)
54 static int min_level
= -1;
55 static FILE *output
= NULL
;
58 int abslvl
= (level
> 0) ? level
: - level
;
62 if ((eptr
= getenv ("VMS_DEBUG")) != NULL
)
64 min_level
= atoi (eptr
);
72 if (abslvl
> min_level
)
76 fprintf (output
, " ");
77 va_start (args
, format
);
78 vfprintf (output
, format
, args
);
84 hex dump 'size' bytes starting at 'ptr'. */
87 _bfd_hexdump (int level
,
92 unsigned char *lptr
= ptr
;
99 vms_debug (level
, "%08lx:", start
);
100 vms_debug (-level
, " %02x", *ptr
++);
105 while ((count
%16) != 0)
107 vms_debug (-level
, " ");
113 vms_debug (-level
, " ");
116 vms_debug (-level
, "%c", (*lptr
< 32)?'.':*lptr
);
119 vms_debug (-level
, "\n");
123 vms_debug (-level
, "\n");
129 These are needed when reading an object file. */
131 /* Allocate new vms_hash_entry
132 keep the symbol name and a pointer to the bfd symbol in the table. */
134 struct bfd_hash_entry
*
135 _bfd_vms_hash_newfunc (struct bfd_hash_entry
*entry
,
136 struct bfd_hash_table
*table
,
139 vms_symbol_entry
*ret
;
142 vms_debug (5, "_bfd_vms_hash_newfunc (%p, %p, %s)\n", entry
, table
, string
);
147 ret
= (vms_symbol_entry
*)
148 bfd_hash_allocate (table
, sizeof (vms_symbol_entry
));
151 bfd_set_error (bfd_error_no_memory
);
154 entry
= (struct bfd_hash_entry
*) ret
;
157 /* Call the allocation method of the base class. */
158 ret
= (vms_symbol_entry
*) bfd_hash_newfunc (entry
, table
, string
);
160 vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret
);
165 return (struct bfd_hash_entry
*)ret
;
168 /* Object file input functions. */
170 /* Return type and length from record header (buf) on Alpha. */
173 _bfd_vms_get_header_values (bfd
* abfd ATTRIBUTE_UNUSED
,
179 *type
= bfd_getl16 (buf
);
182 *length
= bfd_getl16 (buf
);
185 vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type
?*type
:0), (length
?*length
:0));
189 /* Get next record from object file to vms_buf.
190 Set PRIV(buf_size) and return it
192 This is a little tricky since it should be portable.
194 The openVMS object file has 'variable length' which means that
195 read() returns data in chunks of (hopefully) correct and expected
196 size. The linker (and other tools on vms) depend on that. Unix doesn't
197 know about 'formatted' files, so reading and writing such an object
198 file in a unix environment is not trivial.
200 With the tool 'file' (available on all vms ftp sites), one
201 can view and change the attributes of a file. Changing from
202 'variable length' to 'fixed length, 512 bytes' reveals the
203 record length at the first 2 bytes of every record. The same
204 happens during the transfer of object files from vms to unix,
205 at least with ucx, dec's implementation of tcp/ip.
207 The vms format repeats the length at bytes 2 & 3 of every record.
209 On the first call (file_format == FF_UNKNOWN) we check if
210 the first and the third byte pair (!) of the record match.
211 If they do it's an object file in an unix environment or with
212 wrong attributes (FF_FOREIGN), else we should be in a vms
213 environment where read() returns the record size (FF_NATIVE).
215 Reading is always done in 2 steps.
216 First just the record header is read and the length extracted
217 by get_header_values,
218 then the read buffer is adjusted and the remaining bytes are
221 All file i/o is always done on even file positions. */
224 _bfd_vms_get_record (bfd
* abfd
)
226 int test_len
, test_start
, remaining
;
227 unsigned char *vms_buf
;
230 vms_debug (8, "_bfd_vms_get_record\n");
233 /* Minimum is 6 bytes on Alpha
234 (2 bytes length, 2 bytes record id, 2 bytes length repeated)
236 On the VAX there's no length information in the record
237 so start with OBJ_S_C_MAXRECSIZ. */
239 if (PRIV (buf_size
) == 0)
245 amt
= OBJ_S_C_MAXRECSIZ
;
246 PRIV (file_format
) = FF_VAX
;
250 PRIV (vms_buf
) = bfd_malloc (amt
);
251 PRIV (buf_size
) = amt
;
254 vms_buf
= PRIV (vms_buf
);
259 switch (PRIV (file_format
))
263 test_len
= 6; /* Probe 6 bytes. */
264 test_start
= 2; /* Where the record starts. */
279 /* Skip odd alignment byte. */
281 if (bfd_tell (abfd
) & 1)
283 if (bfd_bread (PRIV (vms_buf
), (bfd_size_type
) 1, abfd
) != 1)
285 bfd_set_error (bfd_error_file_truncated
);
290 /* Read the record header on Alpha. */
292 && (bfd_bread (PRIV (vms_buf
), (bfd_size_type
) test_len
, abfd
)
293 != (bfd_size_type
) test_len
))
295 bfd_set_error (bfd_error_file_truncated
);
299 /* Check file format on first call. */
300 if (PRIV (file_format
) == FF_UNKNOWN
)
301 { /* Record length repeats ? */
302 if (vms_buf
[0] == vms_buf
[4]
303 && vms_buf
[1] == vms_buf
[5])
305 PRIV (file_format
) = FF_FOREIGN
; /* Y: foreign environment. */
310 PRIV (file_format
) = FF_NATIVE
; /* N: native environment. */
317 PRIV (rec_length
) = bfd_bread (vms_buf
, (bfd_size_type
) PRIV (buf_size
),
319 if (PRIV (rec_length
) <= 0)
321 bfd_set_error (bfd_error_file_truncated
);
324 PRIV (vms_rec
) = vms_buf
;
329 /* Extract vms record length. */
331 _bfd_vms_get_header_values (abfd
, vms_buf
+ test_start
, NULL
,
332 & PRIV (rec_length
));
334 if (PRIV (rec_length
) <= 0)
336 bfd_set_error (bfd_error_file_truncated
);
340 /* That's what the linker manual says. */
342 if (PRIV (rec_length
) > EOBJ_S_C_MAXRECSIZ
)
344 bfd_set_error (bfd_error_file_truncated
);
348 /* Adjust the buffer. */
350 if (PRIV (rec_length
) > PRIV (buf_size
))
352 PRIV (vms_buf
) = bfd_realloc (vms_buf
,
353 (bfd_size_type
) PRIV (rec_length
));
354 vms_buf
= PRIV (vms_buf
);
357 PRIV (buf_size
) = PRIV (rec_length
);
360 /* Read the remaining record. */
361 remaining
= PRIV (rec_length
) - test_len
+ test_start
;
364 vms_debug (10, "bfd_bread remaining %d\n", remaining
);
366 if (bfd_bread (vms_buf
+ test_len
, (bfd_size_type
) remaining
, abfd
) !=
367 (bfd_size_type
) remaining
)
369 bfd_set_error (bfd_error_file_truncated
);
372 PRIV (vms_rec
) = vms_buf
+ test_start
;
376 vms_debug (11, "bfd_bread rec_length %d\n", PRIV (rec_length
));
379 return PRIV (rec_length
);
382 /* Get next vms record from file
383 update vms_rec and rec_length to new (remaining) values. */
386 _bfd_vms_next_record (bfd
* abfd
)
389 vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
390 PRIV (rec_length
), PRIV (rec_size
));
393 if (PRIV (rec_length
) > 0)
394 PRIV (vms_rec
) += PRIV (rec_size
);
397 if (_bfd_vms_get_record (abfd
) <= 0)
401 if (!PRIV (vms_rec
) || !PRIV (vms_buf
)
402 || PRIV (vms_rec
) >= (PRIV (vms_buf
) + PRIV (buf_size
)))
407 PRIV (rec_type
) = *(PRIV (vms_rec
));
408 PRIV (rec_size
) = PRIV (rec_length
);
411 _bfd_vms_get_header_values (abfd
, PRIV (vms_rec
), &PRIV (rec_type
),
414 PRIV (rec_length
) -= PRIV (rec_size
);
417 vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
418 PRIV (vms_rec
), PRIV (rec_size
), PRIV (rec_length
),
422 return PRIV (rec_type
);
425 /* Copy sized string (string with fixed length) to new allocated area
426 size is string length (size of record) */
429 _bfd_vms_save_sized_string (unsigned char *str
, int size
)
431 char *newstr
= bfd_malloc ((bfd_size_type
) size
+ 1);
435 strncpy (newstr
, (char *) str
, (size_t) size
);
441 /* Copy counted string (string with length at first byte) to new allocated area
442 ptr points to length byte on entry */
445 _bfd_vms_save_counted_string (unsigned char *ptr
)
449 return _bfd_vms_save_sized_string (ptr
, len
);
452 /* Stack routines for vms ETIR commands. */
454 /* Push value and section index. */
457 _bfd_vms_push (bfd
* abfd
, uquad val
, int psect
)
459 static int last_psect
;
462 vms_debug (4, "<push %016lx (%d) at %d>\n", val
, psect
, PRIV (stackptr
));
468 PRIV (stack
[PRIV (stackptr
)]).value
= val
;
469 PRIV (stack
[PRIV (stackptr
)]).psect
= last_psect
;
471 if (PRIV (stackptr
) >= STACKSIZE
)
473 bfd_set_error (bfd_error_bad_value
);
474 (*_bfd_error_handler
) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr
));
479 /* Pop value and section index. */
482 _bfd_vms_pop (bfd
* abfd
, int *psect
)
486 if (PRIV (stackptr
) == 0)
488 bfd_set_error (bfd_error_bad_value
);
489 (*_bfd_error_handler
) (_("Stack underflow in _bfd_vms_pop"));
493 value
= PRIV (stack
[PRIV (stackptr
)]).value
;
494 if ((psect
!= NULL
) && (PRIV (stack
[PRIV (stackptr
)]).psect
>= 0))
495 *psect
= PRIV (stack
[PRIV (stackptr
)]).psect
;
498 vms_debug (4, "<pop %016lx(%d)>\n", value
, PRIV (stack
[PRIV (stackptr
)]).psect
);
504 /* Object file output functions. */
506 /* GAS tends to write sections in little chunks (bfd_set_section_contents)
507 which we can't use directly. So we save the little chunks in linked
508 lists (one per section) and write them later. */
510 /* Add a new vms_section structure to vms_section_table
511 - forward chaining -. */
514 add_new_contents (bfd
* abfd
, sec_ptr section
)
516 vms_section
*sptr
, *newptr
;
518 sptr
= PRIV (vms_section_table
)[section
->index
];
522 newptr
= bfd_alloc (abfd
, (bfd_size_type
) sizeof (vms_section
));
525 newptr
->contents
= bfd_alloc (abfd
, section
->size
);
526 if (newptr
->contents
== NULL
)
529 newptr
->size
= section
->size
;
531 PRIV (vms_section_table
)[section
->index
] = newptr
;
535 /* Save section data & offset to a vms_section structure
536 vms_section_table[] holds the vms_section chain. */
539 _bfd_save_vms_section (bfd
* abfd
,
547 if (section
->index
>= VMS_SECTION_COUNT
)
549 bfd_set_error (bfd_error_nonrepresentable_section
);
552 if (count
== (bfd_size_type
)0)
554 sptr
= add_new_contents (abfd
, section
);
557 memcpy (sptr
->contents
+ offset
, data
, (size_t) count
);
562 /* Get vms_section pointer to saved contents for section # index */
565 _bfd_get_vms_section (bfd
* abfd
, int index
)
567 if (index
>= VMS_SECTION_COUNT
)
569 bfd_set_error (bfd_error_nonrepresentable_section
);
572 return PRIV (vms_section_table
)[index
];
575 /* Object output routines. */
577 /* Begin new record or record header
578 write 2 bytes rectype
579 write 2 bytes record length (filled in at flush)
580 write 2 bytes header type (ommitted if rechead == -1). */
583 _bfd_vms_output_begin (bfd
* abfd
, int rectype
, int rechead
)
586 vms_debug (6, "_bfd_vms_output_begin (type %d, head %d)\n", rectype
,
590 _bfd_vms_output_short (abfd
, (unsigned int) rectype
);
592 /* Save current output position to fill in length later. */
594 if (PRIV (push_level
) > 0)
595 PRIV (length_pos
) = PRIV (output_size
);
598 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
602 /* Placeholder for length. */
603 _bfd_vms_output_short (abfd
, 0);
606 _bfd_vms_output_short (abfd
, (unsigned int) rechead
);
609 /* Set record/subrecord alignment. */
612 _bfd_vms_output_alignment (bfd
* abfd
, int alignto
)
615 vms_debug (6, "_bfd_vms_output_alignment (%d)\n", alignto
);
618 PRIV (output_alignment
) = alignto
;
621 /* Prepare for subrecord fields. */
624 _bfd_vms_output_push (bfd
* abfd
)
627 vms_debug (6, "vms_output_push (pushed_size = %d)\n", PRIV (output_size
));
631 PRIV (pushed_size
) = PRIV (output_size
);
634 /* End of subrecord fields. */
637 _bfd_vms_output_pop (bfd
* abfd
)
640 vms_debug (6, "vms_output_pop (pushed_size = %d)\n", PRIV (pushed_size
));
643 _bfd_vms_output_flush (abfd
);
644 PRIV (length_pos
) = 2;
647 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV (length_pos
));
650 PRIV (pushed_size
) = 0;
654 /* Flush unwritten output, ends current record. */
657 _bfd_vms_output_flush (bfd
* abfd
)
659 int real_size
= PRIV (output_size
);
664 vms_debug (6, "_bfd_vms_output_flush (real_size = %d, pushed_size %d at lenpos %d)\n",
665 real_size
, PRIV (pushed_size
), PRIV (length_pos
));
668 if (PRIV (push_level
) > 0)
669 length
= real_size
- PRIV (pushed_size
);
675 aligncount
= (PRIV (output_alignment
)
676 - (length
% PRIV (output_alignment
))) % PRIV (output_alignment
);
679 vms_debug (6, "align: adding %d bytes\n", aligncount
);
682 while (aligncount
-- > 0)
684 PRIV (output_buf
)[real_size
++] = 0;
688 /* Put length to buffer. */
689 PRIV (output_size
) = PRIV (length_pos
);
690 _bfd_vms_output_short (abfd
, (unsigned int) length
);
692 if (PRIV (push_level
) == 0)
696 /* Write length first, see FF_FOREIGN in the input routines. */
697 || fwrite (PRIV (output_buf
) + 2, 2, 1,
698 (FILE *) abfd
->iostream
) != 1
701 && fwrite (PRIV (output_buf
), (size_t) real_size
, 1,
702 (FILE *) abfd
->iostream
) != 1))
703 /* FIXME: Return error status. */
706 PRIV (output_size
) = 0;
710 PRIV (output_size
) = real_size
;
711 PRIV (pushed_size
) = PRIV (output_size
);
715 /* End record output. */
718 _bfd_vms_output_end (bfd
* abfd
)
721 vms_debug (6, "_bfd_vms_output_end\n");
724 _bfd_vms_output_flush (abfd
);
727 /* Check remaining buffer size
729 Return what's left. */
732 _bfd_vms_output_check (bfd
* abfd
, int size
)
735 vms_debug (6, "_bfd_vms_output_check (%d)\n", size
);
738 return (MAX_OUTREC_SIZE
- (PRIV (output_size
) + size
+ MIN_OUTREC_LUFT
));
741 /* Output byte (8 bit) value. */
744 _bfd_vms_output_byte (bfd
* abfd
, unsigned int value
)
747 vms_debug (6, "_bfd_vms_output_byte (%02x)\n", value
);
750 bfd_put_8 (abfd
, value
& 0xff, PRIV (output_buf
) + PRIV (output_size
));
751 PRIV (output_size
) += 1;
754 /* Output short (16 bit) value. */
757 _bfd_vms_output_short (bfd
* abfd
, unsigned int value
)
760 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value
);
763 bfd_put_16 (abfd
, (bfd_vma
) value
& 0xffff,
764 PRIV (output_buf
) + PRIV (output_size
));
765 PRIV (output_size
) += 2;
768 /* Output long (32 bit) value. */
771 _bfd_vms_output_long (bfd
* abfd
, unsigned long value
)
774 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value
);
777 bfd_put_32 (abfd
, (bfd_vma
) value
, PRIV (output_buf
) + PRIV (output_size
));
778 PRIV (output_size
) += 4;
781 /* Output quad (64 bit) value. */
784 _bfd_vms_output_quad (bfd
* abfd
, uquad value
)
787 vms_debug (6, "_bfd_vms_output_quad (%016lx)\n", value
);
790 bfd_put_64(abfd
, value
, PRIV (output_buf
) + PRIV (output_size
));
791 PRIV (output_size
) += 8;
794 /* Output c-string as counted string. */
797 _bfd_vms_output_counted (bfd
* abfd
, char *value
)
802 vms_debug (6, "_bfd_vms_output_counted (%s)\n", value
);
805 len
= strlen (value
);
808 (*_bfd_error_handler
) (_("_bfd_vms_output_counted called with zero bytes"));
813 (*_bfd_error_handler
) (_("_bfd_vms_output_counted called with too many bytes"));
816 _bfd_vms_output_byte (abfd
, (unsigned int) len
& 0xff);
817 _bfd_vms_output_dump (abfd
, (unsigned char *) value
, len
);
820 /* Output character area. */
823 _bfd_vms_output_dump (bfd
* abfd
,
828 vms_debug (6, "_bfd_vms_output_dump (%d)\n", length
);
834 memcpy (PRIV (output_buf
) + PRIV (output_size
), data
, (size_t) length
);
835 PRIV (output_size
) += length
;
838 /* Output count bytes of value. */
841 _bfd_vms_output_fill (bfd
* abfd
,
846 vms_debug (6, "_bfd_vms_output_fill (val %02x times %d)\n", value
, count
);
851 memset (PRIV (output_buf
) + PRIV (output_size
), value
, (size_t) count
);
852 PRIV (output_size
) += count
;
855 /* This hash routine borrowed from GNU-EMACS, and strengthened slightly. ERY. */
858 hash_string (const char *ptr
)
860 const unsigned char *p
= (unsigned char *) ptr
;
861 const unsigned char *end
= p
+ strlen (ptr
);
868 hash
= ((hash
<< 3) + (hash
<< 15) + (hash
>> 28) + c
);
873 /* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
876 _bfd_vms_length_hash_symbol (bfd
* abfd
, const char *in
, int maxlen
)
881 const char *old_name
;
883 static char outbuf
[EOBJ_S_C_SYMSIZ
+1];
887 vms_debug (4, "_bfd_vms_length_hash_symbol \"%s\"\n", in
);
890 if (maxlen
> EOBJ_S_C_SYMSIZ
)
891 maxlen
= EOBJ_S_C_SYMSIZ
;
893 /* Save this for later. */
896 /* We may need to truncate the symbol, save the hash for later. */
897 in_len
= strlen (in
);
899 result
= (in_len
> maxlen
) ? hash_string (in
) : 0;
903 /* Do the length checking. */
904 if (in_len
<= maxlen
)
908 if (PRIV (flag_hash_long_names
))
914 strncpy (out
, in
, (size_t) i
);
918 if ((in_len
> maxlen
)
919 && PRIV (flag_hash_long_names
))
920 sprintf (out
, "_%08lx", result
);
925 vms_debug (4, "--> [%d]\"%s\"\n", strlen (outbuf
), outbuf
);
929 && PRIV (flag_hash_long_names
)
930 && PRIV (flag_show_after_trunc
))
931 printf (_("Symbol %s replaced by %s\n"), old_name
, new_name
);
936 /* Allocate and initialize a new symbol. */
939 new_symbol (bfd
* abfd
, char *name
)
944 _bfd_vms_debug (7, "new_symbol %s\n", name
);
947 symbol
= bfd_make_empty_symbol (abfd
);
951 symbol
->section
= bfd_make_section (abfd
, BFD_UND_SECTION_NAME
);
956 /* Allocate and enter a new private symbol. */
959 _bfd_vms_enter_symbol (bfd
* abfd
, char *name
)
961 vms_symbol_entry
*entry
;
964 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name
);
967 entry
= (vms_symbol_entry
*)
968 bfd_hash_lookup (PRIV (vms_symbol_table
), name
, FALSE
, FALSE
);
972 _bfd_vms_debug (8, "creating hash entry for %s\n", name
);
974 entry
= (vms_symbol_entry
*) bfd_hash_lookup (PRIV (vms_symbol_table
),
979 symbol
= new_symbol (abfd
, name
);
982 entry
->symbol
= symbol
;
983 PRIV (gsd_sym_count
)++;
990 (*_bfd_error_handler
) (_("failed to enter %s"), name
);
995 _bfd_vms_debug (8, "found hash entry for %s\n", name
);
1000 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry
, entry
->symbol
);