- /* Call the allocation method of the base class. */
-
- ret = (vms_symbol_entry *) bfd_hash_newfunc (entry, table, string);
-#if VMS_DEBUG
- vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret);
-#endif
-
- ret->symbol = (asymbol *)NULL;
-
- return (struct bfd_hash_entry *)ret;
-}
-
-\f
-/* object file input functions */
-
-/* Return type and length from record header (buf) on Alpha. */
-
-void
-_bfd_vms_get_header_values (abfd, buf, type, length)
- bfd *abfd;
- unsigned char *buf;
- int *type;
- int *length;
-{
- if (type != 0)
- *type = bfd_getl16 (buf);
- buf += 2;
- if (length != 0)
- *length = bfd_getl16 (buf);
-
-#if VMS_DEBUG
- vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0));
-#endif
-
-
- return;
-}
-
-
-/* Get next record from object file to vms_buf
- set PRIV(buf_size) and return it
-
- this is a little tricky since it should be portable.
-
- the openVMS object file has 'variable length' which means that
- read() returns data in chunks of (hopefully) correct and expected
- size. The linker (and other tools on vms) depend on that. Unix doesn't
- know about 'formatted' files, so reading and writing such an object
- file in a unix environment is not trivial.
-
- With the tool 'file' (available on all vms ftp sites), one
- can view and change the attributes of a file. Changing from
- 'variable length' to 'fixed length, 512 bytes' reveals the
- record length at the first 2 bytes of every record. The same
- happens during the transfer of object files from vms to unix,
- at least with ucx, dec's implementation of tcp/ip.
-
- The vms format repeats the length at bytes 2 & 3 of every record.
-
- On the first call (file_format == FF_UNKNOWN) we check if
- the first and the third byte pair (!) of the record match.
- If they do it's an object file in an unix environment or with
- wrong attributes (FF_FOREIGN), else we should be in a vms
- environment where read() returns the record size (FF_NATIVE).
-
- reading is always done in 2 steps.
- first just the record header is read and the length extracted
- by get_header_values
- then the read buffer is adjusted and the remaining bytes are
- read in.
-
- all file i/o is always done on even file positions */
-
-int
-_bfd_vms_get_record (abfd)
- bfd *abfd;
-{
- int test_len, test_start, remaining;
- unsigned char *vms_buf;
-
-#if VMS_DEBUG
- vms_debug (8, "_bfd_vms_get_record\n");
-#endif
-
- /* minimum is 6 bytes on Alpha
- (2 bytes length, 2 bytes record id, 2 bytes length repeated)
-
- on VAX there's no length information in the record
- so start with OBJ_S_C_MAXRECSIZ */
-
- if (PRIV(buf_size) == 0)
- {
- if (PRIV(is_vax))
- {
- PRIV(vms_buf) = (unsigned char *) malloc (OBJ_S_C_MAXRECSIZ);
- PRIV(buf_size) = OBJ_S_C_MAXRECSIZ;
- PRIV(file_format) = FF_VAX;
- }
- else
- PRIV(vms_buf) = (unsigned char *) malloc (6);
- }
-
- vms_buf = PRIV(vms_buf);
-
- if (vms_buf == 0)
- {
- bfd_set_error (bfd_error_no_memory);
- return -1;
- }
-
- switch (PRIV(file_format))
- {
- case FF_UNKNOWN:
- case FF_FOREIGN:
- test_len = 6; /* probe 6 bytes */
- test_start = 2; /* where the record starts */
- break;
-
- case FF_NATIVE:
- test_len = 4;
- test_start = 0;
- break;
-
- case FF_VAX:
- test_len = 0;
- test_start = 0;
- break;
- }
-
- /* skip odd alignment byte */
-
- if (bfd_tell (abfd) & 1)
- {
- if (bfd_read (PRIV(vms_buf), 1, 1, abfd) != 1)
- {
- bfd_set_error (bfd_error_file_truncated);
- return 0;
- }
- }
-
- /* read the record header on Alpha. */
-
- if ((test_len != 0)
- && (bfd_read (PRIV(vms_buf), 1, test_len, abfd) != test_len))
- {
- bfd_set_error (bfd_error_file_truncated);
- return 0;
- }
-
- /* check file format on first call */
-
- if (PRIV(file_format) == FF_UNKNOWN)
- { /* record length repeats ? */
- if ( (vms_buf[0] == vms_buf[4])
- && (vms_buf[1] == vms_buf[5]))
- {
- PRIV(file_format) = FF_FOREIGN; /* Y: foreign environment */
- test_start = 2;
- }
- else
- {
- PRIV(file_format) = FF_NATIVE; /* N: native environment */
- test_start = 0;
- }
- }
-
- if (PRIV(is_vax))
- {
- PRIV(rec_length) = bfd_read (vms_buf, 1, PRIV(buf_size), abfd);
- if (PRIV(rec_length) <= 0)
- {
- bfd_set_error (bfd_error_file_truncated);
- return 0;
- }
- PRIV(vms_rec) = vms_buf;
- }
- else /* Alpha */
- {
- /* extract vms record length */
-
- _bfd_vms_get_header_values (abfd, vms_buf+test_start, NULL,
- &PRIV(rec_length));
-
- if (PRIV(rec_length) <= 0)
- {
- bfd_set_error (bfd_error_file_truncated);
- return 0;
- }
-
- /* that's what the linker manual says */
-
- if (PRIV(rec_length) > EOBJ_S_C_MAXRECSIZ)
- {
- bfd_set_error (bfd_error_file_truncated);
- return 0;
- }
-
- /* adjust the buffer */
-
- if (PRIV(rec_length) > PRIV(buf_size))
- {
- PRIV(vms_buf) = (unsigned char *) realloc (vms_buf, PRIV(rec_length));
- vms_buf = PRIV(vms_buf);
- if (vms_buf == 0)
- {
- bfd_set_error (bfd_error_no_memory);
- return -1;
- }
- PRIV(buf_size) = PRIV(rec_length);
- }
-
- /* read the remaining record */
-
- remaining = PRIV(rec_length) - test_len + test_start;
-
-#if VMS_DEBUG
- vms_debug (10, "bfd_read remaining %d\n", remaining);
-#endif
- if (bfd_read (vms_buf + test_len, 1, remaining, abfd) != remaining)
- {
- bfd_set_error (bfd_error_file_truncated);
- return 0;
- }
- PRIV(vms_rec) = vms_buf + test_start;
- }
-
-#if VMS_DEBUG
- vms_debug (11, "bfd_read rec_length %d\n", PRIV(rec_length));
-#endif
-
- return PRIV(rec_length);
-}
-
-
-/* get next vms record from file
- update vms_rec and rec_length to new (remaining) values */
-
-int
-_bfd_vms_next_record (abfd)
- bfd *abfd;
-{
-#if VMS_DEBUG
- vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
- PRIV(rec_length), PRIV(rec_size));
-#endif
-
- if (PRIV(rec_length) > 0)
- {
- PRIV(vms_rec) += PRIV(rec_size);
- }
- else
- {
- if (_bfd_vms_get_record (abfd) <= 0)
- return -1;
- }
-
- if (PRIV(is_vax))
- {
- PRIV(rec_type) = *(PRIV(vms_rec));
- PRIV(rec_size) = PRIV(rec_length);
- }
- else
- {
- _bfd_vms_get_header_values (abfd, PRIV(vms_rec), &PRIV(rec_type),
- &PRIV(rec_size));
- }
- PRIV(rec_length) -= PRIV(rec_size);
-
-#if VMS_DEBUG
- vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
- PRIV(vms_rec), PRIV(rec_size), PRIV(rec_length),
- PRIV(rec_type));
-#endif
-
- return PRIV(rec_type);
-}
-
-
-\f
-/* Copy sized string (string with fixed length) to new allocated area
- size is string length (size of record) */