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. */
32 /*-----------------------------------------------------------------------------*/
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 identation level. Indentation is performed
53 _bfd_vms_debug (int level, char *format, ...)
55 static int min_level = -1;
56 static FILE *output = NULL;
59 int abslvl = (level > 0)?level:-level;
63 if ((eptr = getenv("VMS_DEBUG")) != NULL)
65 min_level = atoi(eptr);
73 if (abslvl > min_level)
77 fprintf (output, " ");
78 va_start(args, format);
79 vfprintf (output, format, args);
86 #else /* not __STDC__ */
89 _bfd_vms_debug (level, format, a1, a2, a3, a4, a5, a6)
92 long a1; long a2; long a3;
93 long a4; long a5; long a6;
95 static int min_level = -1;
96 static FILE *output = NULL;
101 if ((eptr = getenv("VMS_DEBUG")) != NULL)
103 min_level = atoi(eptr);
111 if (level > min_level)
115 fprintf (output, " ");
116 fprintf (output, format, a1, a2, a3, a4, a5, a6);
121 #endif /* __STDC__ */
124 hex dump 'size' bytes starting at 'ptr' */
127 _bfd_hexdump (level, ptr, size, offset)
133 unsigned char *lptr = ptr;
140 vms_debug (level, "%08lx:", start);
141 vms_debug (-level, " %02x", *ptr++);
146 while ((count%16) != 0)
148 vms_debug (-level, " ");
154 vms_debug (-level, " ");
157 vms_debug (-level, "%c", (*lptr < 32)?'.':*lptr);
160 vms_debug (-level, "\n");
164 vms_debug (-level, "\n");
172 These are needed when reading an object file. */
174 /* allocate new vms_hash_entry
175 keep the symbol name and a pointer to the bfd symbol in the table */
177 struct bfd_hash_entry *
178 _bfd_vms_hash_newfunc (entry, table, string)
179 struct bfd_hash_entry *entry;
180 struct bfd_hash_table *table;
183 vms_symbol_entry *ret;
186 vms_debug (5, "_bfd_vms_hash_newfunc(%p, %p, %s)\n", entry, table, string);
189 if (entry == (struct bfd_hash_entry *)NULL)
191 ret = (vms_symbol_entry *)
192 bfd_hash_allocate (table, sizeof (vms_symbol_entry));
193 if (ret == (vms_symbol_entry *) NULL)
195 bfd_set_error (bfd_error_no_memory);
196 return (struct bfd_hash_entry *)NULL;
198 entry = (struct bfd_hash_entry *) ret;
201 /* Call the allocation method of the base class. */
203 ret = (vms_symbol_entry *) bfd_hash_newfunc (entry, table, string);
205 vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret);
208 ret->symbol = (asymbol *)NULL;
210 return (struct bfd_hash_entry *)ret;
213 /* object file input functions */
215 /* Return type and length from record header (buf) on Alpha. */
218 _bfd_vms_get_header_values (abfd, buf, type, length)
219 bfd *abfd ATTRIBUTE_UNUSED;
225 *type = bfd_getl16 (buf);
228 *length = bfd_getl16 (buf);
231 vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0));
237 /* Get next record from object file to vms_buf
238 set PRIV(buf_size) and return it
240 this is a little tricky since it should be portable.
242 the openVMS object file has 'variable length' which means that
243 read() returns data in chunks of (hopefully) correct and expected
244 size. The linker (and other tools on vms) depend on that. Unix doesn't
245 know about 'formatted' files, so reading and writing such an object
246 file in a unix environment is not trivial.
248 With the tool 'file' (available on all vms ftp sites), one
249 can view and change the attributes of a file. Changing from
250 'variable length' to 'fixed length, 512 bytes' reveals the
251 record length at the first 2 bytes of every record. The same
252 happens during the transfer of object files from vms to unix,
253 at least with ucx, dec's implementation of tcp/ip.
255 The vms format repeats the length at bytes 2 & 3 of every record.
257 On the first call (file_format == FF_UNKNOWN) we check if
258 the first and the third byte pair (!) of the record match.
259 If they do it's an object file in an unix environment or with
260 wrong attributes (FF_FOREIGN), else we should be in a vms
261 environment where read() returns the record size (FF_NATIVE).
263 reading is always done in 2 steps.
264 first just the record header is read and the length extracted
266 then the read buffer is adjusted and the remaining bytes are
269 all file i/o is always done on even file positions */
272 _bfd_vms_get_record (abfd)
275 int test_len, test_start, remaining;
276 unsigned char *vms_buf;
279 vms_debug (8, "_bfd_vms_get_record\n");
282 /* minimum is 6 bytes on Alpha
283 (2 bytes length, 2 bytes record id, 2 bytes length repeated)
285 on VAX there's no length information in the record
286 so start with OBJ_S_C_MAXRECSIZ */
288 if (PRIV (buf_size) == 0)
292 PRIV (vms_buf) = (unsigned char *) malloc (OBJ_S_C_MAXRECSIZ);
293 PRIV (buf_size) = OBJ_S_C_MAXRECSIZ;
294 PRIV (file_format) = FF_VAX;
297 PRIV (vms_buf) = (unsigned char *) malloc (6);
300 vms_buf = PRIV (vms_buf);
304 bfd_set_error (bfd_error_no_memory);
308 switch (PRIV (file_format))
312 test_len = 6; /* probe 6 bytes */
313 test_start = 2; /* where the record starts */
328 /* skip odd alignment byte */
330 if (bfd_tell (abfd) & 1)
332 if (bfd_read (PRIV (vms_buf), 1, 1, abfd) != 1)
334 bfd_set_error (bfd_error_file_truncated);
339 /* read the record header on Alpha. */
342 && (bfd_read (PRIV (vms_buf), 1, test_len, abfd)
343 != (bfd_size_type) test_len))
345 bfd_set_error (bfd_error_file_truncated);
349 /* check file format on first call */
351 if (PRIV (file_format) == FF_UNKNOWN)
352 { /* record length repeats ? */
353 if ( (vms_buf[0] == vms_buf[4])
354 && (vms_buf[1] == vms_buf[5]))
356 PRIV (file_format) = FF_FOREIGN; /* Y: foreign environment */
361 PRIV (file_format) = FF_NATIVE; /* N: native environment */
368 PRIV (rec_length) = bfd_read (vms_buf, 1, PRIV (buf_size), abfd);
369 if (PRIV (rec_length) <= 0)
371 bfd_set_error (bfd_error_file_truncated);
374 PRIV (vms_rec) = vms_buf;
378 /* extract vms record length */
380 _bfd_vms_get_header_values (abfd, vms_buf+test_start, NULL,
383 if (PRIV (rec_length) <= 0)
385 bfd_set_error (bfd_error_file_truncated);
389 /* that's what the linker manual says */
391 if (PRIV (rec_length) > EOBJ_S_C_MAXRECSIZ)
393 bfd_set_error (bfd_error_file_truncated);
397 /* adjust the buffer */
399 if (PRIV (rec_length) > PRIV (buf_size))
401 PRIV (vms_buf) = (unsigned char *) realloc (vms_buf, PRIV (rec_length));
402 vms_buf = PRIV (vms_buf);
405 bfd_set_error (bfd_error_no_memory);
408 PRIV (buf_size) = PRIV (rec_length);
411 /* read the remaining record */
413 remaining = PRIV (rec_length) - test_len + test_start;
416 vms_debug (10, "bfd_read remaining %d\n", remaining);
418 if (bfd_read (vms_buf + test_len, 1, remaining, abfd) !=
419 (bfd_size_type) remaining)
421 bfd_set_error (bfd_error_file_truncated);
424 PRIV (vms_rec) = vms_buf + test_start;
428 vms_debug (11, "bfd_read rec_length %d\n", PRIV (rec_length));
431 return PRIV (rec_length);
434 /* get next vms record from file
435 update vms_rec and rec_length to new (remaining) values */
438 _bfd_vms_next_record (abfd)
442 vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
443 PRIV (rec_length), PRIV (rec_size));
446 if (PRIV (rec_length) > 0)
448 PRIV (vms_rec) += PRIV (rec_size);
452 if (_bfd_vms_get_record (abfd) <= 0)
456 if (!PRIV (vms_rec) || !PRIV (vms_buf)
457 || PRIV (vms_rec) >= (PRIV (vms_buf) + PRIV (buf_size)))
462 PRIV (rec_type) = *(PRIV (vms_rec));
463 PRIV (rec_size) = PRIV (rec_length);
467 _bfd_vms_get_header_values (abfd, PRIV (vms_rec), &PRIV (rec_type),
470 PRIV (rec_length) -= PRIV (rec_size);
473 vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
474 PRIV (vms_rec), PRIV (rec_size), PRIV (rec_length),
478 return PRIV (rec_type);
481 /* Copy sized string (string with fixed length) to new allocated area
482 size is string length (size of record) */
485 _bfd_vms_save_sized_string (str, size)
489 char *newstr = bfd_malloc (size + 1);
493 strncpy (newstr, (char *)str, size);
499 /* Copy counted string (string with length at first byte) to new allocated area
500 ptr points to length byte on entry */
503 _bfd_vms_save_counted_string (ptr)
508 return _bfd_vms_save_sized_string (ptr, len);
511 /* stack routines for vms ETIR commands */
513 /* Push value and section index */
516 _bfd_vms_push (abfd, val, psect)
521 static int last_psect;
524 vms_debug (4, "<push %016lx(%d) at %d>\n", val, psect, PRIV (stackptr));
530 PRIV (stack[PRIV (stackptr)]).value = val;
531 PRIV (stack[PRIV (stackptr)]).psect = last_psect;
533 if (PRIV (stackptr) >= STACKSIZE)
535 bfd_set_error (bfd_error_bad_value);
536 (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr));
542 /* Pop value and section index */
545 _bfd_vms_pop (abfd, psect)
551 if (PRIV (stackptr) == 0)
553 bfd_set_error (bfd_error_bad_value);
554 (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
558 value = PRIV (stack[PRIV (stackptr)]).value;
559 if ((psect != NULL) && (PRIV (stack[PRIV (stackptr)]).psect >= 0))
560 *psect = PRIV (stack[PRIV (stackptr)]).psect;
563 vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV (stack[PRIV (stackptr)]).psect);
569 /* object file output functions */
571 /* GAS tends to write sections in little chunks (bfd_set_section_contents)
572 which we can't use directly. So we save the little chunks in linked
573 lists (one per section) and write them later. */
575 /* Add a new vms_section structure to vms_section_table
576 - forward chaining - */
579 add_new_contents (abfd, section)
583 vms_section *sptr, *newptr;
585 sptr = PRIV (vms_section_table)[section->index];
589 newptr = (vms_section *) bfd_malloc (sizeof (vms_section));
590 if (newptr == (vms_section *) NULL)
592 newptr->contents = (unsigned char *) bfd_alloc (abfd, (int)section->_raw_size);
593 if (newptr->contents == (unsigned char *)NULL)
596 newptr->size = section->_raw_size;
598 PRIV (vms_section_table)[section->index] = newptr;
602 /* Save section data & offset to an vms_section structure
603 vms_section_table[] holds the vms_section chain */
606 _bfd_save_vms_section (abfd, section, data, offset, count)
615 if (section->index >= VMS_SECTION_COUNT)
617 bfd_set_error (bfd_error_nonrepresentable_section);
620 if (count == (bfd_size_type)0)
622 sptr = add_new_contents (abfd, section);
625 memcpy (sptr->contents + offset, data, (size_t) count);
630 /* Get vms_section pointer to saved contents for section # index */
633 _bfd_get_vms_section (abfd, index)
637 if (index >= VMS_SECTION_COUNT)
639 bfd_set_error (bfd_error_nonrepresentable_section);
642 return PRIV (vms_section_table)[index];
645 /* Object output routines */
647 /* Begin new record or record header
648 write 2 bytes rectype
649 write 2 bytes record length (filled in at flush)
650 write 2 bytes header type (ommitted if rechead == -1) */
653 _bfd_vms_output_begin (abfd, rectype, rechead)
659 vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype,
663 _bfd_vms_output_short (abfd,rectype);
665 /* save current output position to fill in lenght later */
667 if (PRIV (push_level) > 0)
668 PRIV (length_pos) = PRIV (output_size);
671 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
675 _bfd_vms_output_short (abfd,0); /* placeholder for length */
678 _bfd_vms_output_short (abfd,rechead);
683 /* Set record/subrecord alignment */
686 _bfd_vms_output_alignment (abfd, alignto)
691 vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto);
694 PRIV (output_alignment) = alignto;
698 /* Prepare for subrecord fields */
701 _bfd_vms_output_push (abfd)
705 vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV (output_size));
709 PRIV (pushed_size) = PRIV (output_size);
713 /* End of subrecord fields */
716 _bfd_vms_output_pop (abfd)
720 vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV (pushed_size));
723 _bfd_vms_output_flush (abfd);
724 PRIV (length_pos) = 2;
727 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV (length_pos));
730 PRIV (pushed_size) = 0;
735 /* Flush unwritten output, ends current record */
738 _bfd_vms_output_flush (abfd)
741 int real_size = PRIV (output_size);
746 vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
747 real_size, PRIV (pushed_size), PRIV (length_pos));
750 if (PRIV (push_level) > 0)
751 length = real_size - PRIV (pushed_size);
757 aligncount = (PRIV (output_alignment)
758 - (length % PRIV (output_alignment))) % PRIV (output_alignment);
761 vms_debug (6, "align: adding %d bytes\n", aligncount);
764 while (aligncount-- > 0)
766 PRIV (output_buf)[real_size++] = 0;
768 /* this is why I *love* vms: inconsistency :-}
769 alignment is added to the subrecord length
770 but not to the record length */
771 if (PRIV (push_level) > 0)
776 /* put length to buffer */
777 PRIV (output_size) = PRIV (length_pos);
778 _bfd_vms_output_short (abfd, (unsigned int)length);
780 if (PRIV (push_level) == 0)
783 /* write length first, see FF_FOREIGN in the input routines */
784 fwrite (PRIV (output_buf)+2, 2, 1, (FILE *)abfd->iostream);
786 fwrite (PRIV (output_buf), real_size, 1, (FILE *)abfd->iostream);
788 PRIV (output_size) = 0;
792 PRIV (output_size) = real_size;
793 PRIV (pushed_size) = PRIV (output_size);
799 /* End record output */
802 _bfd_vms_output_end (abfd)
806 vms_debug (6, "_bfd_vms_output_end\n");
809 _bfd_vms_output_flush (abfd);
814 /* check remaining buffer size
816 return what's left. */
819 _bfd_vms_output_check (abfd, size)
824 vms_debug (6, "_bfd_vms_output_check(%d)\n", size);
827 return (MAX_OUTREC_SIZE - (PRIV (output_size) + size + MIN_OUTREC_LUFT));
830 /* Output byte (8 bit) value */
833 _bfd_vms_output_byte (abfd, value)
838 vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value);
841 bfd_put_8 (abfd, value & 0xff, PRIV (output_buf) + PRIV (output_size));
842 PRIV (output_size) += 1;
846 /* Output short (16 bit) value */
849 _bfd_vms_output_short (abfd, value)
854 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
857 bfd_put_16 (abfd, value & 0xffff, PRIV (output_buf) + PRIV (output_size));
858 PRIV (output_size) += 2;
862 /* Output long (32 bit) value */
865 _bfd_vms_output_long (abfd, value)
870 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
873 bfd_put_32 (abfd, value, PRIV (output_buf) + PRIV (output_size));
874 PRIV (output_size) += 4;
878 /* Output quad (64 bit) value */
881 _bfd_vms_output_quad (abfd, value)
886 vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value);
889 bfd_put_64(abfd, value, PRIV (output_buf) + PRIV (output_size));
890 PRIV (output_size) += 8;
894 /* Output c-string as counted string */
897 _bfd_vms_output_counted (abfd, value)
904 vms_debug (6, "_bfd_vms_output_counted(%s)\n", value);
907 len = strlen (value);
910 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
915 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
918 _bfd_vms_output_byte (abfd, len & 0xff);
919 _bfd_vms_output_dump (abfd, (unsigned char *)value, len);
922 /* Output character area */
925 _bfd_vms_output_dump (abfd, data, length)
931 vms_debug (6, "_bfd_vms_output_dump(%d)\n", length);
937 memcpy (PRIV (output_buf) + PRIV (output_size), data, length);
938 PRIV (output_size) += length;
943 /* Output count bytes of value */
946 _bfd_vms_output_fill (abfd, value, count)
952 vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count);
957 memset (PRIV (output_buf) + PRIV (output_size), value, count);
958 PRIV (output_size) += count;
963 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
969 register const unsigned char *p = (unsigned char *) ptr;
970 register const unsigned char *end = p + strlen (ptr);
971 register unsigned char c;
972 register int hash = 0;
977 hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
982 /* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
985 _bfd_vms_length_hash_symbol (abfd, in, maxlen)
993 const char *old_name;
995 static char outbuf[EOBJ_S_C_SYMSIZ+1];
999 vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
1002 if (maxlen > EOBJ_S_C_SYMSIZ)
1003 maxlen = EOBJ_S_C_SYMSIZ;
1005 new_name = out; /* save this for later. */
1007 /* We may need to truncate the symbol, save the hash for later. */
1009 in_len = strlen (in);
1011 result = (in_len > maxlen) ? hash_string (in) : 0;
1015 /* Do the length checking. */
1017 if (in_len <= maxlen)
1023 if (PRIV (flag_hash_long_names))
1029 strncpy (out, in, i);
1033 if ((in_len > maxlen)
1034 && PRIV (flag_hash_long_names))
1035 sprintf (out, "_%08lx", result);
1040 vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
1044 && PRIV (flag_hash_long_names)
1045 && PRIV (flag_show_after_trunc))
1046 printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
1051 /* Allocate and initialize a new symbol. */
1054 new_symbol (abfd, name)
1061 _bfd_vms_debug (7, "new_symbol %s\n", name);
1064 symbol = _bfd_vms_make_empty_symbol (abfd);
1067 symbol->name = name;
1068 symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
1073 /* Allocate and enter a new private symbol. */
1076 _bfd_vms_enter_symbol (abfd, name)
1080 vms_symbol_entry *entry;
1083 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name);
1086 entry = (vms_symbol_entry *)
1087 bfd_hash_lookup (PRIV (vms_symbol_table), name, false, false);
1091 _bfd_vms_debug (8, "creating hash entry for %s\n", name);
1093 entry = (vms_symbol_entry *)bfd_hash_lookup (PRIV (vms_symbol_table), name, true, false);
1097 symbol = new_symbol (abfd, name);
1100 entry->symbol = symbol;
1101 PRIV (gsd_sym_count)++;
1108 (*_bfd_error_handler) (_("failed to enter %s"), name);
1113 _bfd_vms_debug (8, "found hash entry for %s\n", name);
1118 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);