1 /* evax-misc.c -- Miscellaneous functions for ALPHA EVAX (openVMS/AXP) files.
2 Copyright 1996 Free Software Foundation, Inc.
3 Written by Klaus Kämpf (kkaempf@progis.de)
4 of proGIS Softwareentwicklung, Aachen, Germany
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
33 /*-----------------------------------------------------------------------------*/
37 /* debug function for all evax extensions
38 evaluates environment variable EVAX_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_evax_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("EVAX_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_evax_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("EVAX_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 evax_debug (level
, "%08lx:", start
);
143 evax_debug (-level
, " %02x", *ptr
++);
148 while ((count
%16) != 0)
150 evax_debug (-level
, " ");
156 evax_debug (-level
, " ");
159 evax_debug (-level
, "%c", (*lptr
< 32)?'.':*lptr
);
162 evax_debug (-level
, "\n");
166 evax_debug (-level
, "\n");
175 These are needed when reading an object file. */
177 /* allocate new evax_hash_entry
178 keep the symbol name and a pointer to the bfd symbol in the table */
180 struct bfd_hash_entry
*
181 _bfd_evax_hash_newfunc (entry
, table
, string
)
182 struct bfd_hash_entry
*entry
;
183 struct bfd_hash_table
*table
;
186 evax_symbol_entry
*ret
= (evax_symbol_entry
*)entry
;
189 evax_debug (5, "_bfd_evax_hash_newfunc(%p, %p, %s)\n", entry
, table
, string
);
192 if (ret
== (evax_symbol_entry
*)NULL
)
193 ret
= ((evax_symbol_entry
*) bfd_hash_allocate (table
, sizeof (evax_symbol_entry
)));
194 if (ret
== (evax_symbol_entry
*)NULL
)
196 bfd_set_error (bfd_error_no_memory
);
197 return (struct bfd_hash_entry
*)NULL
;
199 ret
= (evax_symbol_entry
*) bfd_hash_newfunc ((struct bfd_hash_entry
*)ret
, table
, string
);
201 ret
->symbol
= (asymbol
*)NULL
;
203 return (struct bfd_hash_entry
*)ret
;
207 /* object file input functions */
209 /* Return type and length from record header (buf) */
212 _bfd_evax_get_header_values (abfd
, buf
, type
, length
)
219 *type
= bfd_getl16 (buf
);
222 *length
= bfd_getl16 (buf
);
228 /* Get next record from object file to evax_buf
229 set PRIV(buf_size) and return it
231 this is a little tricky since it should be portable.
233 the openVMS/AXP object file has 'variable length' which means that
234 read() returns data in chunks of (hopefully) correct and expected
235 size. The linker (and other tools on vms) depend on that. Unix doesn't
236 know about 'formatted' files, so reading and writing such an object
237 file in a unix environment is not trivial.
239 With the tool 'file' (available on all vms ftp sites), one
240 can view and change the attributes of a file. Changing from
241 'variable length' to 'fixed length, 512 bytes' reveals the
242 record length at the first 2 bytes of every record. The same
243 happens during the transfer of object files from vms to unix,
244 at least with ucx, dec's implementation of tcp/ip.
246 The EVAX format repeats the length at bytes 2 & 3 of every record.
248 On the first call (file_format == FF_UNKNOWN) we check if
249 the first and the third byte pair (!) of the record match.
250 If they do it's an object file in an unix environment or with
251 wrong attributes (FF_FOREIGN), else we should be in a vms
252 environment where read() returns the record size (FF_NATIVE).
254 reading is always done in 2 steps.
255 first just the record header is read and the length extracted
257 then the read buffer is adjusted and the remaining bytes are
260 all file i/o is always done on even file positions */
263 _bfd_evax_get_record (abfd
)
266 int test_len
, test_start
, remaining
;
267 unsigned char *evax_buf
;
270 evax_debug (8, "_bfd_evax_get_record\n");
273 /* minimum is 6 bytes
274 (2 bytes length, 2 bytes record id, 2 bytes length repeated) */
276 if (PRIV(buf_size
) == 0)
278 PRIV(evax_buf
) = (unsigned char *) malloc (6);
280 evax_debug (9, "PRIV(evax_buf) %p\n", PRIV(evax_buf
));
284 evax_buf
= PRIV(evax_buf
);
289 evax_debug (9, "can't alloc evax_buf\n");
291 bfd_set_error (bfd_error_no_memory
);
295 switch (PRIV(file_format
))
299 test_len
= 6; /* probe 6 bytes */
300 test_start
= 2; /* where the record starts */
309 /* skip odd alignment byte */
311 if (PRIV(file_format
) == FF_FOREIGN
)
314 if (bfd_tell (abfd
) & 1)
317 evax_debug (10, "skip odd\n");
319 if (bfd_read (PRIV(evax_buf
), 1, 1, abfd
) != 1)
322 evax_debug (9, "skip odd failed\n");
324 bfd_set_error (bfd_error_file_truncated
);
331 /* read the record header */
333 if (bfd_read (PRIV(evax_buf
), 1, test_len
, abfd
) != test_len
)
336 evax_debug (9, "can't bfd_read test %d bytes\n", test_len
);
338 bfd_set_error (bfd_error_file_truncated
);
342 /* check file format on first call */
344 if (PRIV(file_format
) == FF_UNKNOWN
)
345 { /* record length repeats ? */
346 if ( (evax_buf
[0] == evax_buf
[4])
347 && (evax_buf
[1] == evax_buf
[5]))
349 PRIV(file_format
) = FF_FOREIGN
; /* Y: foreign environment */
354 PRIV(file_format
) = FF_NATIVE
; /* N: native environment */
358 evax_debug (10, "File format is %s\n", (PRIV(file_format
) == FF_FOREIGN
)?"foreign":"native");
362 /* extract evax record length */
364 _bfd_evax_get_header_values (abfd
, evax_buf
+test_start
, NULL
,
367 if (PRIV(rec_length
) <= 0)
369 bfd_set_error (bfd_error_file_truncated
);
373 /* that's what the linker manual says */
375 if (PRIV(rec_length
) > EOBJ_S_C_MAXRECSIZ
)
377 bfd_set_error (bfd_error_file_truncated
);
381 /* adjust the buffer */
383 if (PRIV(rec_length
) > PRIV(buf_size
))
385 PRIV(evax_buf
) = (unsigned char *) realloc (evax_buf
, PRIV(rec_length
));
387 evax_debug (3, "adjusted the buffer (%p) from %d to %d\n", PRIV(evax_buf
), PRIV(buf_size
), PRIV(rec_length
));
389 evax_buf
= PRIV(evax_buf
);
393 evax_debug (9, "can't realloc evax_buf to %d bytes\n", PRIV(rec_length
));
395 bfd_set_error (bfd_error_no_memory
);
398 PRIV(buf_size
) = PRIV(rec_length
);
401 /* read the remaining record */
403 remaining
= PRIV(rec_length
) - test_len
+ test_start
;
405 if (bfd_read (evax_buf
+ test_len
, 1, remaining
, abfd
) != remaining
)
408 evax_debug (9, "can't bfd_read remaining %d bytes\n", remaining
);
410 bfd_set_error (bfd_error_file_truncated
);
414 PRIV(evax_rec
) = evax_buf
+ test_start
;
416 return PRIV(rec_length
);
420 /* get next EVAX record from file
421 update evax_rec and rec_length to new (remaining) values */
424 _bfd_evax_next_record (abfd
)
428 evax_debug (8, "_bfd_evax_next_record (len %d, size %d)\n",
429 PRIV(rec_length
), PRIV(rec_size
));
432 if (PRIV(rec_length
) > 0)
434 PRIV(evax_rec
) += PRIV(rec_size
);
438 if (_bfd_evax_get_record (abfd
) <= 0)
441 _bfd_evax_get_header_values (abfd
, PRIV(evax_rec
), &PRIV(rec_type
),
443 PRIV(rec_length
) -= PRIV(rec_size
);
446 evax_debug (8, "_bfd_evax_next_record: rec %p, size %d, length %d, type %d\n",
447 PRIV(evax_rec
), PRIV(rec_size
), PRIV(rec_length
),
451 return PRIV(rec_type
);
456 /* Copy sized string (string with fixed length) to new allocated area
457 size is string length (size of record) */
460 _bfd_evax_save_sized_string (str
, size
)
464 char *newstr
= bfd_malloc (size
+ 1);
468 strncpy (newstr
, str
, size
);
474 /* Copy counted string (string with length at first byte) to new allocated area
475 ptr points to length byte on entry */
478 _bfd_evax_save_counted_string (ptr
)
483 return _bfd_evax_save_sized_string (ptr
, len
);
487 /* stack routines for EVAX ETIR commands */
489 /* Push value and section index */
492 _bfd_evax_push (abfd
, val
, psect
)
497 static int last_psect
;
500 evax_debug (4, "<push %016lx(%d) at %d>\n", val
, psect
, PRIV(stackptr
));
506 PRIV(stack
[PRIV(stackptr
)]).value
= val
;
507 PRIV(stack
[PRIV(stackptr
)]).psect
= last_psect
;
509 if (PRIV(stackptr
) >= STACKSIZE
)
511 bfd_set_error (bfd_error_bad_value
);
518 /* Pop value and section index */
521 _bfd_evax_pop (abfd
, psect
)
527 if (PRIV(stackptr
) == 0)
529 bfd_set_error (bfd_error_bad_value
);
533 value
= PRIV(stack
[PRIV(stackptr
)]).value
;
534 if ((psect
!= NULL
) && (PRIV(stack
[PRIV(stackptr
)]).psect
>= 0))
535 *psect
= PRIV(stack
[PRIV(stackptr
)]).psect
;
538 evax_debug (4, "<pop %016lx(%d)>\n", value
, PRIV(stack
[PRIV(stackptr
)]).psect
);
545 /* object file output functions */
547 /* GAS tends to write sections in little chunks (bfd_set_section_contents)
548 which we can't use directly. So we save the little chunks in linked
549 lists (one per section) and write them later. */
551 /* Add a new evax_section structure to evax_section_table
552 - forward chaining - */
554 static evax_section
*
555 add_new_contents (abfd
, section
)
559 evax_section
*sptr
, *newptr
;
561 newptr
= (evax_section
*) bfd_zalloc (abfd
, sizeof (evax_section
));
562 if (newptr
== (evax_section
*)NULL
)
564 bfd_set_error (bfd_error_no_memory
);
567 sptr
= PRIV(evax_section_table
)[section
->index
];
570 PRIV(evax_section_table
)[section
->index
] = (evax_section
*)newptr
;
574 while (sptr
->next
!= NULL
)
582 /* Save section data & offset to an evax_section structure
583 evax_section_table[] holds the evax_section chain */
586 _bfd_save_evax_section (abfd
, section
, data
, offset
, count
)
595 if (section
->index
>= EVAX_SECTION_COUNT
)
597 bfd_set_error (bfd_error_nonrepresentable_section
);
600 if (count
== (bfd_size_type
)0)
602 sptr
= add_new_contents (abfd
, section
);
605 sptr
->contents
= (unsigned char *) bfd_alloc (abfd
, (int)count
);
606 if (sptr
->contents
== (unsigned char *)NULL
)
608 bfd_set_error (bfd_error_no_memory
);
611 memcpy (sptr
->contents
, data
, (int)count
);
612 sptr
->offset
= (bfd_vma
)offset
;
616 evax_debug (6, "_bfd_save_evax_section sptr = %08lx\n", sptr
);
617 _bfd_hexdump (6, data
, count
, (int)offset
);
624 /* Get evax_section pointer to saved contents for section # index */
627 _bfd_get_evax_section (abfd
, index
)
631 if (index
>= EVAX_SECTION_COUNT
)
633 bfd_set_error (bfd_error_nonrepresentable_section
);
636 return PRIV(evax_section_table
)[index
];
640 /* Object output routines */
642 /* Begin new record or record header
643 write 2 bytes rectype
644 write 2 bytes record length (filled in at flush)
645 write 2 bytes header type (ommitted if rechead == -1) */
648 _bfd_evax_output_begin (abfd
, rectype
, rechead
)
654 evax_debug (6, "_bfd_evax_output_begin(type %d, head %d)\n", rectype
,
658 _bfd_evax_output_short (abfd
,rectype
);
660 /* save current output position to fill in lenght later */
662 if (PRIV(push_level
) > 0)
663 PRIV(length_pos
) = PRIV(output_size
);
666 evax_debug (6, "_bfd_evax_output_begin: length_pos = %d\n",
670 _bfd_evax_output_short (abfd
,0); /* placeholder for length */
673 _bfd_evax_output_short (abfd
,rechead
);
679 /* Set record/subrecord alignment */
682 _bfd_evax_output_alignment (abfd
, alignto
)
687 evax_debug (6, "_bfd_evax_output_alignment(%d)\n", alignto
);
690 PRIV(output_alignment
) = alignto
;
695 /* Prepare for subrecord fields */
698 _bfd_evax_output_push (abfd
)
702 evax_debug (6, "evax_output_push(pushed_size = %d)\n", PRIV(output_size
));
706 PRIV(pushed_size
) = PRIV(output_size
);
711 /* End of subrecord fields */
714 _bfd_evax_output_pop (abfd
)
718 evax_debug (6, "evax_output_pop(pushed_size = %d)\n", PRIV(pushed_size
));
721 _bfd_evax_output_flush (abfd
);
722 PRIV(length_pos
) = 2;
725 evax_debug (6, "evax_output_pop: length_pos = %d\n", PRIV(length_pos
));
728 PRIV(pushed_size
) = 0;
734 /* Flush unwritten output, ends current record */
737 _bfd_evax_output_flush (abfd
)
740 int real_size
= PRIV(output_size
);
745 evax_debug (6, "_bfd_evax_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
746 real_size
, PRIV(pushed_size
), PRIV(length_pos
));
749 if (PRIV(push_level
) > 0)
750 length
= real_size
- PRIV(pushed_size
);
756 aligncount
= (PRIV(output_alignment
)
757 - (length
% PRIV(output_alignment
))) % PRIV(output_alignment
);
760 evax_debug (6, "align: adding %d bytes\n", aligncount
);
763 while(aligncount
-- > 0)
765 PRIV(output_buf
)[real_size
++] = 0;
767 /* this is why I *love* vms: inconsistency :-}
768 alignment is added to the subrecord length
769 but not to the record length */
770 if (PRIV(push_level
) > 0)
775 /* put length to buffer */
776 PRIV(output_size
) = PRIV(length_pos
);
777 _bfd_evax_output_short (abfd
, (unsigned int)length
);
779 if (PRIV(push_level
) == 0)
782 /* write length first, see FF_FOREIGN in the input routines */
783 fwrite (PRIV(output_buf
)+2, 2, 1, (FILE *)abfd
->iostream
);
785 fwrite (PRIV(output_buf
), real_size
, 1, (FILE *)abfd
->iostream
);
787 PRIV(output_size
) = 0;
791 PRIV(output_size
) = real_size
;
792 PRIV(pushed_size
) = PRIV(output_size
);
799 /* End record output */
802 _bfd_evax_output_end (abfd
)
806 evax_debug (6, "_bfd_evax_output_end\n");
809 _bfd_evax_output_flush (abfd
);
815 /* check remaining buffer size
817 return what's left. */
820 _bfd_evax_output_check (abfd
, size
)
825 evax_debug (6, "_bfd_evax_output_check(%d)\n", size
);
828 return (MAX_OUTREC_SIZE
- (PRIV(output_size
) + size
+ MIN_OUTREC_LUFT
));
832 /* Output byte (8 bit) value */
835 _bfd_evax_output_byte (abfd
, value
)
840 evax_debug (6, "_bfd_evax_output_byte(%02x)\n", value
);
843 bfd_put_8 (abfd
, value
& 0xff, PRIV(output_buf
) + PRIV(output_size
));
844 PRIV(output_size
) += 1;
849 /* Output short (16 bit) value */
852 _bfd_evax_output_short (abfd
, value
)
857 evax_debug (6, "_bfd_evax_output_short (%04x)\n", value
);
860 bfd_put_16 (abfd
, value
& 0xffff, PRIV(output_buf
) + PRIV(output_size
));
861 PRIV(output_size
) += 2;
866 /* Output long (32 bit) value */
869 _bfd_evax_output_long (abfd
, value
)
874 evax_debug (6, "_bfd_evax_output_long (%08lx)\n", value
);
877 bfd_put_32 (abfd
, value
, PRIV(output_buf
) + PRIV(output_size
));
878 PRIV(output_size
) += 4;
883 /* Output quad (64 bit) value */
886 _bfd_evax_output_quad (abfd
, value
)
891 evax_debug (6, "_bfd_evax_output_quad(%016lx)\n", value
);
894 bfd_put_64(abfd
, value
, PRIV(output_buf
) + PRIV(output_size
));
895 PRIV(output_size
) += 8;
900 /* Output c-string as counted string */
903 _bfd_evax_output_counted (abfd
, value
)
910 evax_debug (6, "_bfd_evax_output_counted(%s)\n", value
);
913 len
= strlen (value
);
916 (*_bfd_error_handler
) ("_bfd_evax_output_counted called with zero bytes");
921 (*_bfd_error_handler
) ("_bfd_evax_output_counted called with too many bytes");
924 _bfd_evax_output_byte (abfd
, len
& 0xff);
925 _bfd_evax_output_dump (abfd
, (unsigned char *)value
, len
);
929 /* Output character area */
932 _bfd_evax_output_dump (abfd
, data
, length
)
938 evax_debug (6, "_bfd_evax_output_dump(%d)\n", length
);
944 memcpy (PRIV(output_buf
) + PRIV(output_size
), data
, length
);
945 PRIV(output_size
) += length
;
951 /* Output count bytes of value */
954 _bfd_evax_output_fill (abfd
, value
, count
)
960 evax_debug (6, "_bfd_evax_output_fill(val %02x times %d)\n", value
, count
);
965 memset (PRIV(output_buf
) + PRIV(output_size
), value
, count
);
966 PRIV(output_size
) += count
;
971 /*-----------------------------------------------------------------------------*/
973 /* Return basename (stripped of directory information) of filename */
976 _bfd_evax_basename (name
)
982 evax_debug (6, "_bfd_evax_basename %s -> ", name
);
986 /* assume unix host */
987 ptr
= strrchr (name
, '.');
990 ptr
= strrchr (name
, '/');
996 /* assume vms host */
997 ptr
= strrchr (name
, '.');
1005 ptr
= strrchr (name
, ']');
1010 ptr
= strrchr (name
, ':');
1020 evax_debug (6, "%s\n", ptr
);
1027 /* Manufacure a VMS like time on a unix based system.
1028 stolen from obj-vms.c */
1031 _bfd_get_vms_time_string ()
1033 static char tbuf
[18];
1035 #include <sys/types.h>
1041 pnt
= ctime (&timeb
);
1047 sprintf (tbuf
, "%2s-%3s-%s %s", pnt
+ 8, pnt
+ 4, pnt
+ 20, pnt
+ 11);
1049 #include <starlet.h>
1055 Descriptor
.Size
= 17;
1056 Descriptor
.Ptr
= tbuf
;
1057 sys$
asctim (0, &Descriptor
, 0, 0);
1058 #endif /* not VMS */
1061 evax_debug (6, "vmstimestring:'%s'\n", tbuf
);