1 /* BFD back-end for VMS archive files.
3 Copyright (C) 2010-2020 Free Software Foundation, Inc.
4 Written by Tristan Gingold <gingold@adacore.com>, AdaCore.
6 This file is part of BFD, the Binary File Descriptor library.
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. */
26 #include "safe-ctype.h"
28 #include "libiberty.h"
33 /* The standard VMS disk block size. */
34 #ifndef VMS_BLOCK_SIZE
35 #define VMS_BLOCK_SIZE 512
38 /* Maximum key length (which is also the maximum symbol length in archive). */
39 #define MAX_KEYLEN 128
40 #define MAX_EKEYLEN 1024
46 unsigned char min_char
;
47 unsigned char max_char
;
53 /* Kind of library. Used to filter in archive_p. */
63 /* Back-end private data. */
67 /* Standard tdata for an archive. But we don't use many fields. */
68 struct artdata artdata
;
73 /* Type of the archive. */
76 /* Kind of archive. Summary of its type. */
77 enum vms_lib_kind kind
;
79 /* Total size of the mhd (element header). */
80 unsigned int mhd_size
;
83 unsigned int credat_lo
;
84 unsigned int credat_hi
;
86 /* Vector of modules (archive elements), already sorted. */
87 unsigned int nbr_modules
;
88 struct carsym
*modules
;
91 /* DCX (decompression) data. */
92 unsigned int nbr_dcxsbm
;
93 struct dcxsbm_desc
*dcxsbm
;
96 #define bfd_libdata(bfd) ((struct lib_tdata *)((bfd)->tdata.any))
98 /* End-Of-Text pattern. This is a special record to mark the end of file. */
100 static const unsigned char eotdesc
[] = { 0x03, 0x00, 0x77, 0x00, 0x77, 0x00 };
102 /* Describe the current state of carsym entries while building the archive
103 table of content. Things are simple with Alpha archives as the number
104 of entries is known, but with IA64 archives a entry can make a reference
105 to severals members. Therefore we must be able to extend the table on the
106 fly, but it should be allocated on the bfd - which doesn't support realloc.
107 To reduce the overhead, the table is initially allocated in the BFD's
108 objalloc and extended if necessary on the heap. In the later case, it
109 is finally copied to the BFD's objalloc so that it will automatically be
114 /* The table of content. */
117 /* Number of entries used in the table. */
120 /* Maximum number of entries. */
123 /* If true, the table was reallocated on the heap. If false, it is still
124 in the BFD's objalloc. */
125 bfd_boolean realloced
;
128 /* Simply add a name to the index. */
131 vms_add_index (struct carsym_mem
*cs
, char *name
,
132 unsigned int idx_vbn
, unsigned int idx_off
)
134 if (cs
->nbr
== cs
->max
)
139 if (cs
->max
> -33u / 2)
141 bfd_set_error (bfd_error_file_too_big
);
144 cs
->max
= 2 * cs
->max
+ 32;
145 if (_bfd_mul_overflow (cs
->max
, sizeof (struct carsym
), &amt
))
147 bfd_set_error (bfd_error_file_too_big
);
153 n
= bfd_malloc (amt
);
156 memcpy (n
, cs
->idx
, cs
->nbr
* sizeof (struct carsym
));
157 /* And unfortunately we can't free cs->idx. */
161 n
= bfd_realloc_or_free (cs
->idx
, amt
);
166 cs
->realloced
= TRUE
;
168 cs
->idx
[cs
->nbr
].file_offset
= (idx_vbn
- 1) * VMS_BLOCK_SIZE
+ idx_off
;
169 cs
->idx
[cs
->nbr
].name
= name
;
174 /* Follow all member of a lns list (pointed by RFA) and add indexes for
175 NAME. Return FALSE in case of error. */
178 vms_add_indexes_from_list (bfd
*abfd
, struct carsym_mem
*cs
, char *name
,
187 vbn
= bfd_getl32 (rfa
->vbn
);
192 off
= (vbn
- 1) * VMS_BLOCK_SIZE
+ bfd_getl16 (rfa
->offset
);
193 if (bfd_seek (abfd
, off
, SEEK_SET
) != 0
194 || bfd_bread (&lns
, sizeof (lns
), abfd
) != sizeof (lns
))
197 if (!vms_add_index (cs
, name
,
198 bfd_getl32 (lns
.modrfa
.vbn
),
199 bfd_getl16 (lns
.modrfa
.offset
)))
206 /* Read block VBN from ABFD and store it into BLK. Return FALSE in case of error. */
209 vms_read_block (bfd
*abfd
, unsigned int vbn
, void *blk
)
213 off
= (vbn
- 1) * VMS_BLOCK_SIZE
;
214 if (bfd_seek (abfd
, off
, SEEK_SET
) != 0
215 || bfd_bread (blk
, VMS_BLOCK_SIZE
, abfd
) != VMS_BLOCK_SIZE
)
221 /* Write the content of BLK to block VBN of ABFD. Return FALSE in case of error. */
224 vms_write_block (bfd
*abfd
, unsigned int vbn
, void *blk
)
228 off
= (vbn
- 1) * VMS_BLOCK_SIZE
;
229 if (bfd_seek (abfd
, off
, SEEK_SET
) != 0
230 || bfd_bwrite (blk
, VMS_BLOCK_SIZE
, abfd
) != VMS_BLOCK_SIZE
)
236 /* Read index block VBN and put the entry in **IDX (which is updated).
237 If the entry is indirect, recurse. */
240 vms_traverse_index (bfd
*abfd
, unsigned int vbn
, struct carsym_mem
*cs
)
242 struct vms_indexdef indexdef
;
247 /* Read the index block. */
248 BFD_ASSERT (sizeof (indexdef
) == VMS_BLOCK_SIZE
);
249 if (!vms_read_block (abfd
, vbn
, &indexdef
))
253 p
= &indexdef
.keys
[0];
254 endp
= p
+ bfd_getl16 (indexdef
.used
);
257 unsigned int idx_vbn
;
258 unsigned int idx_off
;
260 unsigned char *keyname
;
263 /* Extract key length. */
264 if (bfd_libdata (abfd
)->ver
== LBR_MAJORID
)
266 struct vms_idx
*ridx
= (struct vms_idx
*)p
;
268 idx_vbn
= bfd_getl32 (ridx
->rfa
.vbn
);
269 idx_off
= bfd_getl16 (ridx
->rfa
.offset
);
271 keylen
= ridx
->keylen
;
273 keyname
= ridx
->keyname
;
275 else if (bfd_libdata (abfd
)->ver
== LBR_ELFMAJORID
)
277 struct vms_elfidx
*ridx
= (struct vms_elfidx
*)p
;
279 idx_vbn
= bfd_getl32 (ridx
->rfa
.vbn
);
280 idx_off
= bfd_getl16 (ridx
->rfa
.offset
);
282 keylen
= bfd_getl16 (ridx
->keylen
);
284 keyname
= ridx
->keyname
;
293 /* Point to the next index entry. */
294 p
= keyname
+ keylen
;
296 if (idx_off
== RFADEF__C_INDEX
)
298 /* Indirect entry. Recurse. */
299 if (!vms_traverse_index (abfd
, idx_vbn
, cs
))
304 /* Add a new entry. */
307 if (flags
& ELFIDX__SYMESC
)
309 /* Extended key name. */
310 unsigned int noff
= 0;
314 unsigned char kblk
[VMS_BLOCK_SIZE
];
317 if (keylen
!= sizeof (struct vms_kbn
))
320 kbn
= (struct vms_kbn
*)keyname
;
321 keylen
= bfd_getl16 (kbn
->keylen
);
323 name
= bfd_alloc (abfd
, keylen
+ 1);
326 kvbn
= bfd_getl32 (kbn
->rfa
.vbn
);
327 koff
= bfd_getl16 (kbn
->rfa
.offset
);
329 /* Read the key, chunk by chunk. */
334 if (!vms_read_block (abfd
, kvbn
, kblk
))
336 kbn
= (struct vms_kbn
*)(kblk
+ koff
);
337 klen
= bfd_getl16 (kbn
->keylen
);
338 kvbn
= bfd_getl32 (kbn
->rfa
.vbn
);
339 koff
= bfd_getl16 (kbn
->rfa
.offset
);
341 memcpy (name
+ noff
, kbn
+ 1, klen
);
352 /* Usual key name. */
353 name
= bfd_alloc (abfd
, keylen
+ 1);
357 memcpy (name
, keyname
, keylen
);
361 if (flags
& ELFIDX__LISTRFA
)
366 off
= (idx_vbn
- 1) * VMS_BLOCK_SIZE
+ idx_off
;
367 if (bfd_seek (abfd
, off
, SEEK_SET
) != 0
368 || bfd_bread (&lhs
, sizeof (lhs
), abfd
) != sizeof (lhs
))
371 /* FIXME: this adds extra entries that were not accounted. */
372 if (!vms_add_indexes_from_list (abfd
, cs
, name
, &lhs
.ng_g_rfa
))
374 if (!vms_add_indexes_from_list (abfd
, cs
, name
, &lhs
.ng_wk_rfa
))
376 if (!vms_add_indexes_from_list (abfd
, cs
, name
, &lhs
.g_g_rfa
))
378 if (!vms_add_indexes_from_list (abfd
, cs
, name
, &lhs
.g_wk_rfa
))
383 if (!vms_add_index (cs
, name
, idx_vbn
, idx_off
))
392 /* Read index #IDX, which must have NBREL entries. */
394 static struct carsym
*
395 vms_lib_read_index (bfd
*abfd
, int idx
, unsigned int *nbrel
)
400 struct carsym
*csbuf
;
401 struct carsym_mem csm
;
403 /* Read index desription. */
404 if (bfd_seek (abfd
, LHD_IDXDESC
+ idx
* IDD_LENGTH
, SEEK_SET
) != 0
405 || bfd_bread (&idd
, sizeof (idd
), abfd
) != sizeof (idd
))
409 flags
= bfd_getl16 (idd
.flags
);
410 if (!(flags
& IDD__FLAGS_ASCII
)
411 || !(flags
& IDD__FLAGS_VARLENIDX
))
414 csbuf
= bfd_alloc (abfd
, *nbrel
* sizeof (struct carsym
));
420 csm
.realloced
= FALSE
;
423 /* Note: if the index is empty, there is no block to traverse. */
424 vbn
= bfd_getl32 (idd
.vbn
);
425 if (vbn
!= 0 && !vms_traverse_index (abfd
, vbn
, &csm
))
427 if (csm
.realloced
&& csm
.idx
!= NULL
)
430 /* Note: in case of error, we can free what was allocated on the
432 bfd_release (abfd
, csbuf
);
438 /* There are more entries than the first estimate. Allocate on
439 the BFD's objalloc. */
440 csbuf
= bfd_alloc (abfd
, csm
.nbr
* sizeof (struct carsym
));
443 memcpy (csbuf
, csm
.idx
, csm
.nbr
* sizeof (struct carsym
));
450 /* Standard function. */
452 static const bfd_target
*
453 _bfd_vms_lib_archive_p (bfd
*abfd
, enum vms_lib_kind kind
)
457 unsigned int majorid
;
458 struct lib_tdata
*tdata_hold
;
459 struct lib_tdata
*tdata
;
461 unsigned int nbr_ent
;
464 if (bfd_bread (&lhd
, sizeof (lhd
), abfd
) != sizeof (lhd
))
466 if (bfd_get_error () != bfd_error_system_call
)
467 bfd_set_error (bfd_error_wrong_format
);
471 /* Check sanity (= magic) number. */
472 sanity
= bfd_getl32 (lhd
.sanity
);
473 if (!(sanity
== LHD_SANEID3
474 || sanity
== LHD_SANEID6
475 || sanity
== LHD_SANEID_DCX
))
477 bfd_set_error (bfd_error_wrong_format
);
480 majorid
= bfd_getl32 (lhd
.majorid
);
482 /* Check archive kind. */
486 if ((lhd
.type
!= LBR__C_TYP_EOBJ
&& lhd
.type
!= LBR__C_TYP_ESHSTB
)
487 || majorid
!= LBR_MAJORID
490 bfd_set_error (bfd_error_wrong_format
);
495 if ((lhd
.type
!= LBR__C_TYP_IOBJ
&& lhd
.type
!= LBR__C_TYP_ISHSTB
)
496 || majorid
!= LBR_ELFMAJORID
499 bfd_set_error (bfd_error_wrong_format
);
504 if ((lhd
.type
!= LBR__C_TYP_TXT
505 && lhd
.type
!= LBR__C_TYP_MLB
506 && lhd
.type
!= LBR__C_TYP_HLP
)
507 || majorid
!= LBR_MAJORID
510 bfd_set_error (bfd_error_wrong_format
);
518 /* Allocate and initialize private data. */
519 tdata_hold
= bfd_libdata (abfd
);
520 tdata
= (struct lib_tdata
*) bfd_zalloc (abfd
, sizeof (struct lib_tdata
));
523 abfd
->tdata
.any
= (void *)tdata
;
524 tdata
->ver
= majorid
;
525 tdata
->mhd_size
= MHD__C_USRDAT
+ lhd
.mhdusz
;
526 tdata
->type
= lhd
.type
;
528 tdata
->credat_lo
= bfd_getl32 (lhd
.credat
+ 0);
529 tdata
->credat_hi
= bfd_getl32 (lhd
.credat
+ 4);
532 tdata
->nbr_modules
= bfd_getl32 (lhd
.modcnt
);
533 tdata
->artdata
.symdef_count
= bfd_getl32 (lhd
.idxcnt
) - tdata
->nbr_modules
;
534 nbr_ent
= tdata
->nbr_modules
;
535 tdata
->modules
= vms_lib_read_index (abfd
, 0, &nbr_ent
);
536 if (tdata
->modules
== NULL
|| nbr_ent
!= tdata
->nbr_modules
)
540 nbr_ent
= tdata
->artdata
.symdef_count
;
541 tdata
->artdata
.symdefs
= vms_lib_read_index (abfd
, 1, &nbr_ent
);
542 if (tdata
->artdata
.symdefs
== NULL
)
544 /* Only IA64 archives may have more entries in the index that what
546 if (nbr_ent
!= tdata
->artdata
.symdef_count
547 && kind
!= vms_lib_ia64
)
549 tdata
->artdata
.symdef_count
= nbr_ent
;
551 tdata
->cache
= bfd_zalloc (abfd
, sizeof (bfd
*) * tdata
->nbr_modules
);
552 if (tdata
->cache
== NULL
)
555 /* Read DCX submaps. */
556 dcxvbn
= bfd_getl32 (lhd
.dcxmapvbn
);
559 unsigned char buf_reclen
[4];
562 struct vms_dcxmap
*map
;
563 unsigned int sbm_off
;
566 if (bfd_seek (abfd
, (dcxvbn
- 1) * VMS_BLOCK_SIZE
, SEEK_SET
) != 0
567 || bfd_bread (buf_reclen
, sizeof (buf_reclen
), abfd
)
568 != sizeof (buf_reclen
))
570 reclen
= bfd_getl32 (buf_reclen
);
571 buf
= _bfd_malloc_and_read (abfd
, reclen
, reclen
);
574 map
= (struct vms_dcxmap
*)buf
;
575 tdata
->nbr_dcxsbm
= bfd_getl16 (map
->nsubs
);
576 sbm_off
= bfd_getl16 (map
->sub0
);
577 tdata
->dcxsbm
= (struct dcxsbm_desc
*)bfd_alloc
578 (abfd
, tdata
->nbr_dcxsbm
* sizeof (struct dcxsbm_desc
));
579 for (i
= 0; i
< tdata
->nbr_dcxsbm
; i
++)
581 struct vms_dcxsbm
*sbm
= (struct vms_dcxsbm
*) (buf
+ sbm_off
);
582 struct dcxsbm_desc
*sbmdesc
= &tdata
->dcxsbm
[i
];
583 unsigned int sbm_len
;
586 unsigned char *data
= (unsigned char *)sbm
;
590 sbm_sz
= bfd_getl16 (sbm
->size
);
592 BFD_ASSERT (sbm_off
<= reclen
);
594 sbmdesc
->min_char
= sbm
->min_char
;
595 BFD_ASSERT (sbmdesc
->min_char
== 0);
596 sbmdesc
->max_char
= sbm
->max_char
;
597 sbm_len
= sbmdesc
->max_char
- sbmdesc
->min_char
+ 1;
598 l
= (2 * sbm_len
+ 7) / 8;
600 (sbm_sz
>= sizeof (struct vms_dcxsbm
) + l
+ 3 * sbm_len
601 || (tdata
->nbr_dcxsbm
== 1
602 && sbm_sz
>= sizeof (struct vms_dcxsbm
) + l
+ sbm_len
));
603 sbmdesc
->flags
= (unsigned char *)bfd_alloc (abfd
, l
);
604 memcpy (sbmdesc
->flags
, data
+ bfd_getl16 (sbm
->flags
), l
);
605 sbmdesc
->nodes
= (unsigned char *)bfd_alloc (abfd
, 2 * sbm_len
);
606 memcpy (sbmdesc
->nodes
, data
+ bfd_getl16 (sbm
->nodes
), 2 * sbm_len
);
607 off
= bfd_getl16 (sbm
->next
);
610 /* Read the 'next' array. */
611 sbmdesc
->next
= (unsigned short *)bfd_alloc
612 (abfd
, sbm_len
* sizeof (unsigned short));
614 for (j
= 0; j
< sbm_len
; j
++)
615 sbmdesc
->next
[j
] = bfd_getl16 (buf1
+ j
* 2);
619 /* There is no next array if there is only one submap. */
620 BFD_ASSERT (tdata
->nbr_dcxsbm
== 1);
621 sbmdesc
->next
= NULL
;
628 tdata
->nbr_dcxsbm
= 0;
631 /* The map is always present. Also mark shared image library. */
632 abfd
->has_armap
= TRUE
;
633 if (tdata
->type
== LBR__C_TYP_ESHSTB
|| tdata
->type
== LBR__C_TYP_ISHSTB
)
634 abfd
->is_thin_archive
= TRUE
;
639 bfd_release (abfd
, tdata
);
640 abfd
->tdata
.any
= (void *)tdata_hold
;
644 /* Standard function for alpha libraries. */
647 _bfd_vms_lib_alpha_archive_p (bfd
*abfd
)
649 return _bfd_vms_lib_archive_p (abfd
, vms_lib_alpha
);
652 /* Standard function for ia64 libraries. */
655 _bfd_vms_lib_ia64_archive_p (bfd
*abfd
)
657 return _bfd_vms_lib_archive_p (abfd
, vms_lib_ia64
);
660 /* Standard function for text libraries. */
662 static const bfd_target
*
663 _bfd_vms_lib_txt_archive_p (bfd
*abfd
)
665 return _bfd_vms_lib_archive_p (abfd
, vms_lib_txt
);
668 /* Standard bfd function. */
671 _bfd_vms_lib_mkarchive (bfd
*abfd
, enum vms_lib_kind kind
)
673 struct lib_tdata
*tdata
;
675 tdata
= (struct lib_tdata
*) bfd_zalloc (abfd
, sizeof (struct lib_tdata
));
679 abfd
->tdata
.any
= (void *)tdata
;
680 vms_get_time (&tdata
->credat_hi
, &tdata
->credat_lo
);
686 tdata
->ver
= LBR_MAJORID
;
687 tdata
->mhd_size
= offsetof (struct vms_mhd
, pad1
);
688 tdata
->type
= LBR__C_TYP_EOBJ
;
691 tdata
->ver
= LBR_ELFMAJORID
;
692 tdata
->mhd_size
= sizeof (struct vms_mhd
);
693 tdata
->type
= LBR__C_TYP_IOBJ
;
699 tdata
->nbr_modules
= 0;
700 tdata
->artdata
.symdef_count
= 0;
701 tdata
->modules
= NULL
;
702 tdata
->artdata
.symdefs
= NULL
;
709 _bfd_vms_lib_alpha_mkarchive (bfd
*abfd
)
711 return _bfd_vms_lib_mkarchive (abfd
, vms_lib_alpha
);
715 _bfd_vms_lib_ia64_mkarchive (bfd
*abfd
)
717 return _bfd_vms_lib_mkarchive (abfd
, vms_lib_ia64
);
720 /* Find NAME in the symbol index. Return the index. */
723 _bfd_vms_lib_find_symbol (bfd
*abfd
, const char *name
)
725 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
726 carsym
*syms
= tdata
->artdata
.symdefs
;
729 /* Open-coded binary search for speed. */
731 hi
= tdata
->artdata
.symdef_count
- 1;
735 int mid
= lo
+ (hi
- lo
) / 2;
738 diff
= (char)(name
[0] - syms
[mid
].name
[0]);
740 diff
= strcmp (name
, syms
[mid
].name
);
748 return BFD_NO_MORE_SYMBOLS
;
751 /* IO vector for archive member. Need that because members are not linearly
752 stored in archives. */
756 /* Current offset. */
759 /* Length of the module, when known. */
762 /* Current position in the record from bfd_bread point of view (ie, after
763 decompression). 0 means that no data byte have been read, -2 and -1
764 are reserved for the length word. */
766 #define REC_POS_NL -4
767 #define REC_POS_PAD -3
768 #define REC_POS_LEN0 -2
769 #define REC_POS_LEN1 -1
772 unsigned short rec_len
;
773 /* Number of bytes to read in the current record. */
774 unsigned short rec_rem
;
775 /* Offset of the next block. */
777 /* Current *data* offset in the data block. */
778 unsigned short blk_off
;
780 /* Offset of the first block. Extracted from the index. */
781 file_ptr first_block
;
783 /* Initial next_block. Extracted when the MHD is read. */
784 file_ptr init_next_block
;
785 /* Initial blk_off, once the MHD is read. */
786 unsigned short init_blk_off
;
788 /* Used to store any 3 byte record, which could be the EOF pattern. */
789 unsigned char pattern
[4];
792 struct dcxsbm_desc
*dcxsbms
;
793 /* Current submap. */
794 struct dcxsbm_desc
*dcx_sbm
;
795 /* Current offset in the submap. */
796 unsigned int dcx_offset
;
799 /* Compressed buffer. */
800 unsigned char *dcx_buf
;
801 /* Size of the buffer. Used to resize. */
802 unsigned int dcx_max
;
803 /* Number of valid bytes in the buffer. */
804 unsigned int dcx_rlen
;
807 /* Return the current position. */
810 vms_lib_btell (struct bfd
*abfd
)
812 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
816 /* Read the header of the next data block if all bytes of the current block
820 vms_lib_read_block (struct bfd
*abfd
)
822 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
824 if (vec
->blk_off
== DATA__LENGTH
)
826 unsigned char hdr
[DATA__DATA
];
828 /* Read next block. */
829 if (bfd_seek (abfd
->my_archive
, vec
->next_block
, SEEK_SET
) != 0)
831 if (bfd_bread (hdr
, sizeof (hdr
), abfd
->my_archive
) != sizeof (hdr
))
833 vec
->next_block
= (bfd_getl32 (hdr
+ 2) - 1) * VMS_BLOCK_SIZE
;
834 vec
->blk_off
= sizeof (hdr
);
839 /* Read NBYTES from ABFD into BUF if not NULL. If BUF is NULL, bytes are
840 not stored. Read linearly from the library, but handle blocks. This
841 function does not handle records nor EOF. */
844 vms_lib_bread_raw (struct bfd
*abfd
, unsigned char *buf
, file_ptr nbytes
)
846 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
854 /* Be sure the current data block is read. */
855 if (!vms_lib_read_block (abfd
))
858 /* Do not read past the data block, do not read more than requested. */
859 l
= DATA__LENGTH
- vec
->blk_off
;
866 /* Really read into BUF. */
867 if (bfd_bread (buf
, l
, abfd
->my_archive
) != l
)
872 /* Make as if we are reading. */
873 if (bfd_seek (abfd
->my_archive
, l
, SEEK_CUR
) != 0)
886 /* Decompress NBYTES from VEC. Store the bytes into BUF if not NULL. */
889 vms_lib_dcx (struct vms_lib_iovec
*vec
, unsigned char *buf
, file_ptr nbytes
)
891 struct dcxsbm_desc
*sbm
;
897 /* The loop below expect to deliver at least one byte. */
901 /* Get the current state. */
903 offset
= vec
->dcx_offset
;
904 j
= vec
->dcx_pos
& 7;
906 for (i
= vec
->dcx_pos
>> 3; i
< vec
->dcx_rlen
; i
++)
908 unsigned char b
= vec
->dcx_buf
[i
];
914 if (!(sbm
->flags
[offset
>> 3] & (1 << (offset
& 7))))
916 unsigned int n_offset
= sbm
->nodes
[offset
];
919 /* End of buffer. Stay where we are. */
920 vec
->dcx_pos
= (i
<< 3) + j
;
923 vec
->dcx_offset
= offset
;
927 offset
= 2 * n_offset
;
931 unsigned char v
= sbm
->nodes
[offset
];
933 if (sbm
->next
!= NULL
)
934 sbm
= vec
->dcxsbms
+ sbm
->next
[v
];
945 vec
->dcx_pos
= (i
<< 3) + j
+ 1;
946 vec
->dcx_offset
= offset
;
959 /* Standard IOVEC function. */
962 vms_lib_bread (struct bfd
*abfd
, void *vbuf
, file_ptr nbytes
)
964 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
967 unsigned char *buf
= (unsigned char *)vbuf
;
969 /* Do not read past the end. */
970 if (vec
->where
>= vec
->file_len
)
976 if (vec
->rec_rem
== 0)
978 unsigned char blen
[2];
980 /* Read record length. */
981 if (vms_lib_bread_raw (abfd
, blen
, sizeof (blen
)) != sizeof (blen
))
983 vec
->rec_len
= bfd_getl16 (blen
);
984 if (bfd_libdata (abfd
->my_archive
)->kind
== vms_lib_txt
)
986 /* Discard record size and align byte. */
988 vec
->rec_rem
= vec
->rec_len
;
992 /* Prepend record size. */
993 vec
->rec_pos
= REC_POS_LEN0
;
994 vec
->rec_rem
= (vec
->rec_len
+ 1) & ~1; /* With align byte. */
996 if (vec
->rec_len
== 3)
998 /* Possibly end of file. Check the pattern. */
999 if (vms_lib_bread_raw (abfd
, vec
->pattern
, 4) != 4)
1001 if (!memcmp (vec
->pattern
, eotdesc
+ 2, 3))
1003 /* This is really an EOF. */
1005 vec
->file_len
= vec
->where
;
1010 if (vec
->dcxsbms
!= NULL
)
1012 /* This is a compressed member. */
1016 /* Be sure there is enough room for the expansion. */
1017 len
= (vec
->rec_len
+ 1) & ~1;
1018 if (len
> vec
->dcx_max
)
1020 while (len
> vec
->dcx_max
)
1022 vec
->dcx_buf
= bfd_alloc (abfd
, vec
->dcx_max
);
1023 if (vec
->dcx_buf
== NULL
)
1027 /* Read the compressed record. */
1028 vec
->dcx_rlen
= len
;
1029 if (vec
->rec_len
== 3)
1032 memcpy (vec
->dcx_buf
, vec
->pattern
, 3);
1036 elen
= vms_lib_bread_raw (abfd
, vec
->dcx_buf
, len
);
1041 /* Dummy expansion to get the expanded length. */
1042 vec
->dcx_offset
= 0;
1043 vec
->dcx_sbm
= vec
->dcxsbms
;
1045 elen
= vms_lib_dcx (vec
, NULL
, 0x10000);
1048 vec
->rec_len
= elen
;
1049 vec
->rec_rem
= elen
;
1051 /* Reset the state. */
1052 vec
->dcx_offset
= 0;
1053 vec
->dcx_sbm
= vec
->dcxsbms
;
1057 if (vec
->rec_pos
< 0)
1060 switch (vec
->rec_pos
)
1063 c
= vec
->rec_len
& 0xff;
1064 vec
->rec_pos
= REC_POS_LEN1
;
1067 c
= (vec
->rec_len
>> 8) & 0xff;
1091 if (nbytes
> vec
->rec_rem
)
1092 chunk
= vec
->rec_rem
;
1096 if (vec
->dcxsbms
!= NULL
)
1098 /* Optimize the stat() case: no need to decompress again as we
1100 if (!(buf
== NULL
&& chunk
== vec
->rec_rem
))
1101 chunk
= vms_lib_dcx (vec
, buf
, chunk
);
1105 if (vec
->rec_len
== 3)
1108 memcpy (buf
, vec
->pattern
+ vec
->rec_pos
, chunk
);
1111 chunk
= vms_lib_bread_raw (abfd
, buf
, chunk
);
1119 vec
->rec_pos
+= chunk
;
1120 vec
->rec_rem
-= chunk
;
1122 if (vec
->rec_rem
== 0)
1124 /* End of record reached. */
1125 if (bfd_libdata (abfd
->my_archive
)->kind
== vms_lib_txt
)
1127 if ((vec
->rec_len
& 1) == 1
1128 && vec
->rec_len
!= 3
1129 && vec
->dcxsbms
== NULL
)
1131 /* Eat the pad byte. */
1133 if (vms_lib_bread_raw (abfd
, &pad
, 1) != 1)
1136 vec
->rec_pos
= REC_POS_NL
;
1141 if ((vec
->rec_len
& 1) == 1 && vec
->dcxsbms
!= NULL
)
1143 vec
->rec_pos
= REC_POS_PAD
;
1153 /* Standard function, but we currently only handle the rewind case. */
1156 vms_lib_bseek (struct bfd
*abfd
, file_ptr offset
, int whence
)
1158 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1160 if (whence
== SEEK_SET
&& offset
== 0)
1165 vec
->blk_off
= vec
->init_blk_off
;
1166 vec
->next_block
= vec
->init_next_block
;
1168 if (bfd_seek (abfd
->my_archive
, vec
->first_block
, SEEK_SET
) != 0)
1177 vms_lib_bwrite (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1178 const void *where ATTRIBUTE_UNUSED
,
1179 file_ptr nbytes ATTRIBUTE_UNUSED
)
1185 vms_lib_bclose (struct bfd
*abfd
)
1187 abfd
->iostream
= NULL
;
1192 vms_lib_bflush (struct bfd
*abfd ATTRIBUTE_UNUSED
)
1198 vms_lib_bstat (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1199 struct stat
*sb ATTRIBUTE_UNUSED
)
1201 /* Not supported. */
1206 vms_lib_bmmap (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1207 void *addr ATTRIBUTE_UNUSED
,
1208 bfd_size_type len ATTRIBUTE_UNUSED
,
1209 int prot ATTRIBUTE_UNUSED
,
1210 int flags ATTRIBUTE_UNUSED
,
1211 file_ptr offset ATTRIBUTE_UNUSED
,
1212 void **map_addr ATTRIBUTE_UNUSED
,
1213 bfd_size_type
*map_len ATTRIBUTE_UNUSED
)
1218 static const struct bfd_iovec vms_lib_iovec
= {
1219 &vms_lib_bread
, &vms_lib_bwrite
, &vms_lib_btell
, &vms_lib_bseek
,
1220 &vms_lib_bclose
, &vms_lib_bflush
, &vms_lib_bstat
, &vms_lib_bmmap
1223 /* Open a library module. FILEPOS is the position of the module header. */
1226 vms_lib_bopen (bfd
*el
, file_ptr filepos
)
1228 struct vms_lib_iovec
*vec
;
1229 unsigned char buf
[256];
1230 struct vms_mhd
*mhd
;
1231 struct lib_tdata
*tdata
= bfd_libdata (el
->my_archive
);
1234 /* Allocate and initialized the iovec. */
1235 vec
= bfd_zalloc (el
, sizeof (*vec
));
1240 el
->iovec
= &vms_lib_iovec
;
1242 /* File length is not known. */
1245 /* Read the first data block. */
1246 vec
->next_block
= filepos
& ~(VMS_BLOCK_SIZE
- 1);
1247 vec
->blk_off
= DATA__LENGTH
;
1248 if (!vms_lib_read_block (el
))
1251 /* Prepare to read the first record. */
1252 vec
->blk_off
= filepos
& (VMS_BLOCK_SIZE
- 1);
1254 if (bfd_seek (el
->my_archive
, filepos
, SEEK_SET
) != 0)
1257 /* Read Record length + MHD + align byte. */
1258 len
= tdata
->mhd_size
;
1259 if (vms_lib_bread_raw (el
, buf
, 2) != 2)
1261 if (bfd_getl16 (buf
) != len
)
1263 len
= (len
+ 1) & ~1;
1264 BFD_ASSERT (len
<= sizeof (buf
));
1265 if (vms_lib_bread_raw (el
, buf
, len
) != len
)
1268 /* Get info from mhd. */
1269 mhd
= (struct vms_mhd
*)buf
;
1271 if (mhd
->id
!= MHD__C_MHDID
)
1273 if (len
>= MHD__C_MHDLEN
+ 1)
1274 el
->selective_search
= (mhd
->objstat
& MHD__M_SELSRC
) ? 1 : 0;
1275 el
->mtime
= vms_rawtime_to_time_t (mhd
->datim
);
1276 el
->mtime_set
= TRUE
;
1278 /* Reinit the iovec so that seek() will point to the first record after
1281 vec
->init_blk_off
= vec
->blk_off
;
1282 vec
->init_next_block
= vec
->next_block
;
1283 vec
->first_block
= bfd_tell (el
->my_archive
);
1284 vec
->dcxsbms
= bfd_libdata (el
->my_archive
)->dcxsbm
;
1286 if (vec
->dcxsbms
!= NULL
)
1289 vec
->dcx_max
= 10 * 1024;
1290 vec
->dcx_buf
= bfd_alloc (el
, vec
->dcx_max
);
1292 if (vec
->dcx_buf
== NULL
)
1298 /* Get member MODIDX. Return NULL in case of error. */
1301 _bfd_vms_lib_get_module (bfd
*abfd
, unsigned int modidx
)
1303 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
1311 if (modidx
>= tdata
->nbr_modules
)
1314 /* Already loaded. */
1315 if (tdata
->cache
[modidx
])
1316 return tdata
->cache
[modidx
];
1319 file_off
= tdata
->modules
[modidx
].file_offset
;
1320 if (tdata
->type
!= LBR__C_TYP_IOBJ
)
1322 res
= _bfd_create_empty_archive_element_shell (abfd
);
1326 /* Special reader to deal with data blocks. */
1327 if (!vms_lib_bopen (res
, file_off
))
1333 struct vms_mhd
*mhd
;
1334 struct areltdata
*arelt
;
1336 /* Sanity check. The MHD must be big enough to contain module size. */
1337 if (tdata
->mhd_size
< offsetof (struct vms_mhd
, modsize
) + 4)
1340 /* Read the MHD now. */
1341 if (bfd_seek (abfd
, file_off
, SEEK_SET
) != 0)
1343 if (bfd_bread (buf
, tdata
->mhd_size
, abfd
) != tdata
->mhd_size
)
1346 mhd
= (struct vms_mhd
*) buf
;
1347 if (mhd
->id
!= MHD__C_MHDID
)
1350 res
= _bfd_create_empty_archive_element_shell (abfd
);
1353 arelt
= bfd_zmalloc (sizeof (*arelt
));
1359 res
->arelt_data
= arelt
;
1361 /* Get info from mhd. */
1362 if (tdata
->mhd_size
>= offsetof (struct vms_mhd
, objstat
) + 1)
1363 res
->selective_search
= (mhd
->objstat
& MHD__M_SELSRC
) ? 1 : 0;
1364 res
->mtime
= vms_rawtime_to_time_t (mhd
->datim
);
1365 res
->mtime_set
= TRUE
;
1367 arelt
->parsed_size
= bfd_getl32 (mhd
->modsize
);
1369 /* No need for a special reader as members are stored linearly.
1370 Just skip the MHD. */
1371 res
->origin
= file_off
+ tdata
->mhd_size
;
1375 name
= tdata
->modules
[modidx
].name
;
1376 namelen
= strlen (name
);
1377 newname
= bfd_malloc (namelen
+ 4 + 1);
1378 if (newname
== NULL
)
1383 strcpy (newname
, name
);
1384 switch (tdata
->type
)
1386 case LBR__C_TYP_IOBJ
:
1387 case LBR__C_TYP_EOBJ
:
1388 /* For object archives, append .obj to mimic standard behaviour. */
1389 strcpy (newname
+ namelen
, ".obj");
1394 bfd_set_filename (res
, newname
);
1396 tdata
->cache
[modidx
] = res
;
1401 /* Standard function: get member at IDX. */
1404 _bfd_vms_lib_get_elt_at_index (bfd
*abfd
, symindex symidx
)
1406 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
1408 unsigned int modidx
;
1411 if (symidx
> tdata
->artdata
.symdef_count
)
1413 file_off
= tdata
->artdata
.symdefs
[symidx
].file_offset
;
1416 for (modidx
= 0; modidx
< tdata
->nbr_modules
; modidx
++)
1418 if (tdata
->modules
[modidx
].file_offset
== file_off
)
1421 if (modidx
>= tdata
->nbr_modules
)
1424 return _bfd_vms_lib_get_module (abfd
, modidx
);
1427 /* Elements of an imagelib are stubs. You can get the real image with this
1431 _bfd_vms_lib_get_imagelib_file (bfd
*el
)
1433 bfd
*archive
= el
->my_archive
;
1434 const char *modname
= el
->filename
;
1435 int modlen
= strlen (modname
);
1440 /* Convert module name to lower case and append '.exe'. */
1441 filename
= bfd_alloc (el
, modlen
+ 5);
1442 if (filename
== NULL
)
1444 for (j
= 0; j
< modlen
; j
++)
1445 if (ISALPHA (modname
[j
]))
1446 filename
[j
] = TOLOWER (modname
[j
]);
1448 filename
[j
] = modname
[j
];
1449 memcpy (filename
+ modlen
, ".exe", 5);
1451 filename
= _bfd_append_relative_path (archive
, filename
);
1452 if (filename
== NULL
)
1454 res
= bfd_openr (filename
, NULL
);
1458 /* xgettext:c-format */
1459 _bfd_error_handler(_("could not open shared image '%s' from '%s'"),
1460 filename
, archive
->filename
);
1461 bfd_release (archive
, filename
);
1465 /* FIXME: put it in a cache ? */
1469 /* Standard function. */
1472 _bfd_vms_lib_openr_next_archived_file (bfd
*archive
,
1481 idx
= last_file
->proxy_origin
+ 1;
1483 if (idx
>= bfd_libdata (archive
)->nbr_modules
)
1485 bfd_set_error (bfd_error_no_more_archived_files
);
1489 res
= _bfd_vms_lib_get_module (archive
, idx
);
1492 res
->proxy_origin
= idx
;
1496 /* Standard function. Just compute the length. */
1499 _bfd_vms_lib_generic_stat_arch_elt (bfd
*abfd
, struct stat
*st
)
1501 struct lib_tdata
*tdata
;
1504 if (abfd
->my_archive
== NULL
)
1506 bfd_set_error (bfd_error_invalid_operation
);
1510 tdata
= bfd_libdata (abfd
->my_archive
);
1511 if (tdata
->type
!= LBR__C_TYP_IOBJ
)
1513 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1515 if (vec
->file_len
== (ufile_ptr
)-1)
1517 if (vms_lib_bseek (abfd
, 0, SEEK_SET
) != 0)
1520 /* Compute length. */
1521 while (vms_lib_bread (abfd
, NULL
, 1 << 20) > 0)
1524 st
->st_size
= vec
->file_len
;
1528 st
->st_size
= ((struct areltdata
*)abfd
->arelt_data
)->parsed_size
;
1531 if (abfd
->mtime_set
)
1532 st
->st_mtime
= abfd
->mtime
;
1542 /* Internal representation of an index entry. */
1546 /* Corresponding archive member. */
1549 /* Number of reference to this entry. */
1552 /* Length of the key. */
1553 unsigned short namlen
;
1559 /* Used to sort index entries. */
1562 lib_index_cmp (const void *lv
, const void *rv
)
1564 const struct lib_index
*l
= lv
;
1565 const struct lib_index
*r
= rv
;
1567 return strcmp (l
->name
, r
->name
);
1570 /* Maximum number of index blocks level. */
1572 #define MAX_LEVEL 10
1574 /* Get the size of an index entry. */
1577 get_idxlen (struct lib_index
*idx
, bfd_boolean is_elfidx
)
1581 /* 9 is the size of struct vms_elfidx without keyname. */
1582 if (idx
->namlen
> MAX_KEYLEN
)
1583 return 9 + sizeof (struct vms_kbn
);
1585 return 9 + idx
->namlen
;
1589 /* 7 is the size of struct vms_idx without keyname. */
1590 return 7 + idx
->namlen
;
1594 /* Write the index composed by NBR symbols contained in IDX.
1595 VBN is the first vbn to be used, and will contain on return the last vbn.
1596 Can be called with ABFD set to NULL just to size the index.
1597 If not null, TOPVBN will be assigned to the vbn of the root index tree.
1598 IS_ELFIDX is true for elfidx (ie ia64) indexes layout.
1599 Return TRUE on success. */
1602 vms_write_index (bfd
*abfd
,
1603 struct lib_index
*idx
, unsigned int nbr
, unsigned int *vbn
,
1604 unsigned int *topvbn
, bfd_boolean is_elfidx
)
1606 /* The index is organized as a tree. This function implements a naive
1607 algorithm to balance the tree: it fills the leaves, and create a new
1608 branch when all upper leaves and branches are full. We only keep in
1609 memory a path to the current leaf. */
1613 /* Disk blocks for the current path. */
1614 struct vms_indexdef
*rblk
[MAX_LEVEL
];
1615 /* Info on the current blocks. */
1618 unsigned int vbn
; /* VBN of the block. */
1619 /* The last entry is identified so that it could be copied to the
1621 unsigned short len
; /* Length up to the last entry. */
1622 unsigned short lastlen
; /* Length of the last entry. */
1625 /* The kbn blocks are used to store long symbol names. */
1626 unsigned int kbn_sz
= 0; /* Number of bytes available in the kbn block. */
1627 unsigned int kbn_vbn
= 0; /* VBN of the kbn block. */
1628 unsigned char *kbn_blk
= NULL
; /* Contents of the kbn block. */
1632 /* No entries. Very easy to handle. */
1640 /* Sort the index the first time this function is called. */
1641 qsort (idx
, nbr
, sizeof (struct lib_index
), lib_index_cmp
);
1644 /* Allocate first index block. */
1647 rblk
[0] = bfd_zmalloc (sizeof (struct vms_indexdef
));
1648 blk
[0].vbn
= (*vbn
)++;
1652 for (i
= 0; i
< nbr
; i
++, idx
++)
1654 unsigned int idxlen
;
1656 unsigned int key_vbn
= 0;
1657 unsigned int key_off
= 0;
1659 idxlen
= get_idxlen (idx
, is_elfidx
);
1661 if (is_elfidx
&& idx
->namlen
> MAX_KEYLEN
)
1663 /* If the key (ie name) is too long, write it in the kbn block. */
1664 unsigned int kl
= idx
->namlen
;
1665 unsigned int kl_chunk
;
1666 const char *key
= idx
->name
;
1668 /* Write the key in the kbn, chunk after chunk. */
1671 if (kbn_sz
< sizeof (struct vms_kbn
))
1673 /* Not enough room in the kbn block. */
1676 /* Write it to the disk (if there is one). */
1679 if (!vms_write_block (abfd
, kbn_vbn
, kbn_blk
))
1684 kbn_blk
= bfd_malloc (VMS_BLOCK_SIZE
);
1685 if (kbn_blk
== NULL
)
1688 *(unsigned short *)kbn_blk
= 0;
1690 /* Allocate a new block for the keys. */
1692 kbn_sz
= VMS_BLOCK_SIZE
- 2;
1694 /* Size of the chunk written to the current key block. */
1695 if (kl
+ sizeof (struct vms_kbn
) > kbn_sz
)
1696 kl_chunk
= kbn_sz
- sizeof (struct vms_kbn
);
1700 if (kbn_blk
!= NULL
)
1702 struct vms_kbn
*kbn
;
1704 kbn
= (struct vms_kbn
*)(kbn_blk
+ VMS_BLOCK_SIZE
- kbn_sz
);
1708 /* Save the rfa of the first chunk. */
1710 key_off
= VMS_BLOCK_SIZE
- kbn_sz
;
1713 bfd_putl16 (kl_chunk
, kbn
->keylen
);
1716 /* No next chunk. */
1717 bfd_putl32 (0, kbn
->rfa
.vbn
);
1718 bfd_putl16 (0, kbn
->rfa
.offset
);
1722 /* Next chunk will be at the start of the next block. */
1723 bfd_putl32 (*vbn
, kbn
->rfa
.vbn
);
1724 bfd_putl16 (2, kbn
->rfa
.offset
);
1726 memcpy ((char *)(kbn
+ 1), key
, kl_chunk
);
1730 kl_chunk
= (kl_chunk
+ 1) & ~1; /* Always align. */
1731 kbn_sz
-= kl_chunk
+ sizeof (struct vms_kbn
);
1736 /* Check if a block might overflow. In this case we will flush this
1737 block and all the blocks below it. */
1738 for (j
= 0; j
< level
; j
++)
1739 if (blk
[j
].len
+ blk
[j
].lastlen
+ idxlen
> INDEXDEF__BLKSIZ
)
1742 for (j
= 0; j
< level
; j
++)
1746 /* There is not enough room to write the new entry in this
1747 block or in a parent block. */
1751 BFD_ASSERT (level
< MAX_LEVEL
);
1753 /* Need to create a parent. */
1756 rblk
[level
] = bfd_zmalloc (sizeof (struct vms_indexdef
));
1757 bfd_putl32 (*vbn
, rblk
[j
]->parent
);
1759 blk
[level
].vbn
= (*vbn
)++;
1761 blk
[level
].lastlen
= blk
[j
].lastlen
;
1766 /* Update parent block: write the last entry from the current
1770 struct vms_rfa
*rfa
;
1772 /* Pointer to the last entry in parent block. */
1773 rfa
= (struct vms_rfa
*)(rblk
[j
+ 1]->keys
+ blk
[j
+ 1].len
);
1775 /* Copy the whole entry. */
1776 BFD_ASSERT (blk
[j
+ 1].lastlen
== blk
[j
].lastlen
);
1777 memcpy (rfa
, rblk
[j
]->keys
+ blk
[j
].len
, blk
[j
].lastlen
);
1778 /* Fix the entry (which in always the first field of an
1780 bfd_putl32 (blk
[j
].vbn
, rfa
->vbn
);
1781 bfd_putl16 (RFADEF__C_INDEX
, rfa
->offset
);
1786 /* And allocate it. Do it only on the block that won't be
1787 flushed (so that the parent of the parent can be
1789 blk
[j
+ 1].len
+= blk
[j
+ 1].lastlen
;
1790 blk
[j
+ 1].lastlen
= 0;
1793 /* Write this block on the disk. */
1796 bfd_putl16 (blk
[j
].len
+ blk
[j
].lastlen
, rblk
[j
]->used
);
1797 if (!vms_write_block (abfd
, blk
[j
].vbn
, rblk
[j
]))
1801 /* Reset this block. */
1804 blk
[j
].vbn
= (*vbn
)++;
1807 /* Append it to the block. */
1810 /* Keep the previous last entry. */
1811 blk
[j
].len
+= blk
[j
].lastlen
;
1815 struct vms_rfa
*rfa
;
1817 rfa
= (struct vms_rfa
*)(rblk
[j
]->keys
+ blk
[j
].len
);
1818 bfd_putl32 ((idx
->abfd
->proxy_origin
/ VMS_BLOCK_SIZE
) + 1,
1821 ((idx
->abfd
->proxy_origin
% VMS_BLOCK_SIZE
)
1822 + (is_elfidx
? 0 : DATA__DATA
),
1827 /* Use elfidx format. */
1828 struct vms_elfidx
*en
= (struct vms_elfidx
*)rfa
;
1833 /* Long symbol name. */
1834 struct vms_kbn
*k
= (struct vms_kbn
*)(en
->keyname
);
1835 bfd_putl16 (sizeof (struct vms_kbn
), en
->keylen
);
1836 bfd_putl16 (idx
->namlen
, k
->keylen
);
1837 bfd_putl32 (key_vbn
, k
->rfa
.vbn
);
1838 bfd_putl16 (key_off
, k
->rfa
.offset
);
1839 en
->flags
|= ELFIDX__SYMESC
;
1843 bfd_putl16 (idx
->namlen
, en
->keylen
);
1844 memcpy (en
->keyname
, idx
->name
, idx
->namlen
);
1849 /* Use idx format. */
1850 struct vms_idx
*en
= (struct vms_idx
*)rfa
;
1851 en
->keylen
= idx
->namlen
;
1852 memcpy (en
->keyname
, idx
->name
, idx
->namlen
);
1856 /* The last added key can now be the last one all blocks in the
1858 blk
[j
].lastlen
= idxlen
;
1862 /* Save VBN of the root. */
1864 *topvbn
= blk
[level
- 1].vbn
;
1870 for (j
= 1; j
< level
; j
++)
1872 /* Update parent block: write the new entry. */
1875 struct vms_rfa
*rfa
;
1877 en
= rblk
[j
- 1]->keys
+ blk
[j
- 1].len
;
1878 par
= rblk
[j
]->keys
+ blk
[j
].len
;
1879 BFD_ASSERT (blk
[j
].lastlen
== blk
[j
- 1].lastlen
);
1880 memcpy (par
, en
, blk
[j
- 1].lastlen
);
1881 rfa
= (struct vms_rfa
*)par
;
1882 bfd_putl32 (blk
[j
- 1].vbn
, rfa
->vbn
);
1883 bfd_putl16 (RFADEF__C_INDEX
, rfa
->offset
);
1886 for (j
= 0; j
< level
; j
++)
1888 /* Write this block on the disk. */
1889 bfd_putl16 (blk
[j
].len
+ blk
[j
].lastlen
, rblk
[j
]->used
);
1890 if (!vms_write_block (abfd
, blk
[j
].vbn
, rblk
[j
]))
1896 /* Write the last kbn (if any). */
1899 if (!vms_write_block (abfd
, kbn_vbn
, kbn_blk
))
1907 /* Append data to the data block DATA. Force write if PAD is true. */
1910 vms_write_data_block (bfd
*arch
, struct vms_datadef
*data
, file_ptr
*off
,
1911 const unsigned char *buf
, unsigned int len
, int pad
)
1913 while (len
> 0 || pad
)
1915 unsigned int doff
= *off
& (VMS_BLOCK_SIZE
- 1);
1916 unsigned int remlen
= (DATA__LENGTH
- DATA__DATA
) - doff
;
1919 l
= (len
> remlen
) ? remlen
: len
;
1920 memcpy (data
->data
+ doff
, buf
, l
);
1926 if (doff
== (DATA__LENGTH
- DATA__DATA
) || (len
== 0 && pad
))
1930 bfd_putl32 ((*off
/ VMS_BLOCK_SIZE
) + 2, data
->link
);
1932 if (bfd_bwrite (data
, sizeof (*data
), arch
) != sizeof (*data
))
1935 *off
+= DATA__LENGTH
- doff
;
1944 /* Build the symbols index. */
1947 _bfd_vms_lib_build_map (unsigned int nbr_modules
,
1948 struct lib_index
*modules
,
1949 unsigned int *res_cnt
,
1950 struct lib_index
**res
)
1953 asymbol
**syms
= NULL
;
1955 struct lib_index
*map
= NULL
;
1956 unsigned int map_max
= 1024; /* Fine initial default. */
1957 unsigned int map_count
= 0;
1959 map
= (struct lib_index
*) bfd_malloc (map_max
* sizeof (struct lib_index
));
1963 /* Gather symbols. */
1964 for (i
= 0; i
< nbr_modules
; i
++)
1969 bfd
*current
= modules
[i
].abfd
;
1971 if ((bfd_get_file_flags (current
) & HAS_SYMS
) == 0)
1974 storage
= bfd_get_symtab_upper_bound (current
);
1980 if (storage
> syms_max
)
1985 syms
= (asymbol
**) bfd_malloc (syms_max
);
1989 symcount
= bfd_canonicalize_symtab (current
, syms
);
1993 /* Now map over all the symbols, picking out the ones we
1995 for (src_count
= 0; src_count
< symcount
; src_count
++)
1997 flagword flags
= (syms
[src_count
])->flags
;
1998 asection
*sec
= syms
[src_count
]->section
;
2000 if ((flags
& BSF_GLOBAL
2002 || flags
& BSF_INDIRECT
2003 || bfd_is_com_section (sec
))
2004 && ! bfd_is_und_section (sec
))
2006 struct lib_index
*new_map
;
2008 /* This symbol will go into the archive header. */
2009 if (map_count
== map_max
)
2012 new_map
= (struct lib_index
*)
2013 bfd_realloc (map
, map_max
* sizeof (struct lib_index
));
2014 if (new_map
== NULL
)
2019 map
[map_count
].abfd
= current
;
2020 map
[map_count
].namlen
= strlen (syms
[src_count
]->name
);
2021 map
[map_count
].name
= syms
[src_count
]->name
;
2029 *res_cnt
= map_count
;
2041 /* Do the hard work: write an archive on the disk. */
2044 _bfd_vms_lib_write_archive_contents (bfd
*arch
)
2047 unsigned int nbr_modules
;
2048 struct lib_index
*modules
;
2049 unsigned int nbr_symbols
;
2050 struct lib_index
*symbols
;
2051 struct lib_tdata
*tdata
= bfd_libdata (arch
);
2054 unsigned int nbr_mod_iblk
;
2055 unsigned int nbr_sym_iblk
;
2057 unsigned int mod_idx_vbn
;
2058 unsigned int sym_idx_vbn
;
2059 bfd_boolean is_elfidx
= tdata
->kind
== vms_lib_ia64
;
2060 unsigned int max_keylen
= is_elfidx
? MAX_EKEYLEN
: MAX_KEYLEN
;
2062 /* Count the number of modules (and do a first sanity check). */
2064 for (current
= arch
->archive_head
;
2066 current
= current
->archive_next
)
2068 /* This check is checking the bfds for the objects we're reading
2069 from (which are usually either an object file or archive on
2070 disk), not the archive entries we're writing to. We don't
2071 actually create bfds for the archive members, we just copy
2072 them byte-wise when we write out the archive. */
2073 if (bfd_write_p (current
) || !bfd_check_format (current
, bfd_object
))
2075 bfd_set_error (bfd_error_invalid_operation
);
2082 /* Build the modules list. */
2083 BFD_ASSERT (tdata
->modules
== NULL
);
2084 modules
= bfd_alloc (arch
, nbr_modules
* sizeof (struct lib_index
));
2085 if (modules
== NULL
)
2088 for (current
= arch
->archive_head
, i
= 0;
2090 current
= current
->archive_next
, i
++)
2094 modules
[i
].abfd
= current
;
2095 modules
[i
].name
= vms_get_module_name (current
->filename
, FALSE
);
2098 /* FIXME: silently truncate long names ? */
2099 nl
= strlen (modules
[i
].name
);
2100 modules
[i
].namlen
= (nl
> max_keylen
? max_keylen
: nl
);
2103 /* Create the module index. */
2105 if (!vms_write_index (NULL
, modules
, nbr_modules
, &vbn
, NULL
, is_elfidx
))
2109 /* Create symbol index. */
2110 if (!_bfd_vms_lib_build_map (nbr_modules
, modules
, &nbr_symbols
, &symbols
))
2114 if (!vms_write_index (NULL
, symbols
, nbr_symbols
, &vbn
, NULL
, is_elfidx
))
2118 /* Write modules and remember their position. */
2119 off
= (1 + nbr_mod_iblk
+ nbr_sym_iblk
) * VMS_BLOCK_SIZE
;
2121 if (bfd_seek (arch
, off
, SEEK_SET
) != 0)
2124 for (i
= 0; i
< nbr_modules
; i
++)
2126 struct vms_datadef data
;
2127 unsigned char blk
[VMS_BLOCK_SIZE
];
2128 struct vms_mhd
*mhd
;
2131 current
= modules
[i
].abfd
;
2132 current
->proxy_origin
= off
;
2138 /* Write the MHD as a record (ie, size first). */
2140 bfd_putl16 (tdata
->mhd_size
, blk
);
2142 mhd
= (struct vms_mhd
*)(blk
+ sz
);
2143 memset (mhd
, 0, sizeof (struct vms_mhd
));
2145 mhd
->id
= MHD__C_MHDID
;
2147 memcpy (mhd
->objid
, "V1.0", 4);
2148 bfd_putl32 (modules
[i
].ref
, mhd
->refcnt
);
2151 sz
+= tdata
->mhd_size
;
2154 /* Rewind the member to be put into the archive. */
2155 if (bfd_seek (current
, 0, SEEK_SET
) != 0)
2158 /* Copy the member into the archive. */
2161 unsigned int modsize
= 0;
2163 file_ptr off_hdr
= off
;
2165 /* Read to complete the first block. */
2166 amt
= bfd_bread (blk
+ sz
, VMS_BLOCK_SIZE
- sz
, current
);
2167 if (amt
== (bfd_size_type
)-1)
2170 if (amt
< VMS_BLOCK_SIZE
- sz
)
2172 /* The member size is less than a block. Pad the block. */
2173 memset (blk
+ sz
+ amt
, 0, VMS_BLOCK_SIZE
- sz
- amt
);
2175 bfd_putl32 (modsize
, mhd
->modsize
);
2177 /* Write the first block (which contains an mhd). */
2178 if (bfd_bwrite (blk
, VMS_BLOCK_SIZE
, arch
) != VMS_BLOCK_SIZE
)
2180 off
+= VMS_BLOCK_SIZE
;
2182 if (amt
== VMS_BLOCK_SIZE
- sz
)
2184 /* Copy the remaining. */
2185 char buffer
[DEFAULT_BUFFERSIZE
];
2189 amt
= bfd_bread (buffer
, sizeof (buffer
), current
);
2190 if (amt
== (bfd_size_type
)-1)
2195 if (amt
!= sizeof (buffer
))
2197 /* Clear the padding. */
2198 memset (buffer
+ amt
, 0, sizeof (buffer
) - amt
);
2199 amt
= (amt
+ VMS_BLOCK_SIZE
) & ~(VMS_BLOCK_SIZE
- 1);
2201 if (bfd_bwrite (buffer
, amt
, arch
) != amt
)
2206 /* Now that the size is known, write the first block (again). */
2207 bfd_putl32 (modsize
, mhd
->modsize
);
2208 if (bfd_seek (arch
, off_hdr
, SEEK_SET
) != 0
2209 || bfd_bwrite (blk
, VMS_BLOCK_SIZE
, arch
) != VMS_BLOCK_SIZE
)
2211 if (bfd_seek (arch
, off
, SEEK_SET
) != 0)
2217 /* Write the MHD. */
2218 if (vms_write_data_block (arch
, &data
, &off
, blk
, sz
, 0) < 0)
2221 /* Write the member. */
2224 sz
= bfd_bread (blk
, sizeof (blk
), current
);
2227 if (vms_write_data_block (arch
, &data
, &off
, blk
, sz
, 0) < 0)
2231 /* Write the end of module marker. */
2232 if (vms_write_data_block (arch
, &data
, &off
,
2233 eotdesc
, sizeof (eotdesc
), 1) < 0)
2238 /* Write the indexes. */
2240 if (!vms_write_index (arch
, modules
, nbr_modules
, &vbn
, &mod_idx_vbn
,
2243 if (!vms_write_index (arch
, symbols
, nbr_symbols
, &vbn
, &sym_idx_vbn
,
2247 /* Write libary header. */
2249 unsigned char blk
[VMS_BLOCK_SIZE
];
2250 struct vms_lhd
*lhd
= (struct vms_lhd
*)blk
;
2251 struct vms_idd
*idd
= (struct vms_idd
*)(blk
+ sizeof (*lhd
));
2252 unsigned int idd_flags
;
2253 unsigned int saneid
;
2255 memset (blk
, 0, sizeof (blk
));
2257 lhd
->type
= tdata
->type
;
2259 switch (tdata
->kind
)
2262 saneid
= LHD_SANEID3
;
2265 saneid
= LHD_SANEID6
;
2270 bfd_putl32 (saneid
, lhd
->sanity
);
2271 bfd_putl16 (tdata
->ver
, lhd
->majorid
);
2272 bfd_putl16 (0, lhd
->minorid
);
2273 snprintf ((char *)lhd
->lbrver
+ 1, sizeof (lhd
->lbrver
) - 1,
2275 (unsigned)(BFD_VERSION
/ 100000000UL),
2276 (unsigned)(BFD_VERSION
/ 1000000UL) % 100,
2277 (unsigned)(BFD_VERSION
/ 10000UL) % 100);
2278 lhd
->lbrver
[sizeof (lhd
->lbrver
) - 1] = 0;
2279 lhd
->lbrver
[0] = strlen ((char *)lhd
->lbrver
+ 1);
2281 bfd_putl32 (tdata
->credat_lo
, lhd
->credat
+ 0);
2282 bfd_putl32 (tdata
->credat_hi
, lhd
->credat
+ 4);
2283 vms_raw_get_time (lhd
->updtim
);
2285 lhd
->mhdusz
= tdata
->mhd_size
- MHD__C_USRDAT
;
2287 bfd_putl32 (nbr_modules
+ nbr_symbols
, lhd
->idxcnt
);
2288 bfd_putl32 (nbr_modules
, lhd
->modcnt
);
2289 bfd_putl32 (nbr_modules
, lhd
->modhdrs
);
2291 /* Number of blocks for index. */
2292 bfd_putl32 (nbr_mod_iblk
+ nbr_sym_iblk
, lhd
->idxblks
);
2293 bfd_putl32 (vbn
- 1, lhd
->hipreal
);
2294 bfd_putl32 (vbn
- 1, lhd
->hiprusd
);
2296 /* VBN of the next free block. */
2297 bfd_putl32 ((off
/ VMS_BLOCK_SIZE
) + 1, lhd
->nextvbn
);
2298 bfd_putl32 ((off
/ VMS_BLOCK_SIZE
) + 1, lhd
->nextrfa
+ 0);
2299 bfd_putl16 (0, lhd
->nextrfa
+ 4);
2301 /* First index (modules name). */
2302 idd_flags
= IDD__FLAGS_ASCII
| IDD__FLAGS_VARLENIDX
2303 | IDD__FLAGS_NOCASECMP
| IDD__FLAGS_NOCASENTR
;
2304 bfd_putl16 (idd_flags
, idd
->flags
);
2305 bfd_putl16 (max_keylen
+ 1, idd
->keylen
);
2306 bfd_putl16 (mod_idx_vbn
, idd
->vbn
);
2309 /* Second index (symbols name). */
2310 bfd_putl16 (idd_flags
, idd
->flags
);
2311 bfd_putl16 (max_keylen
+ 1, idd
->keylen
);
2312 bfd_putl16 (sym_idx_vbn
, idd
->vbn
);
2315 if (!vms_write_block (arch
, 1, blk
))
2322 bfd_set_input_error (current
, bfd_get_error ());
2326 /* Add a target for text library. This costs almost nothing and is useful to
2327 read VMS library on the host. */
2329 const bfd_target alpha_vms_lib_txt_vec
=
2331 "vms-libtxt", /* Name. */
2332 bfd_target_unknown_flavour
,
2333 BFD_ENDIAN_UNKNOWN
, /* byteorder */
2334 BFD_ENDIAN_UNKNOWN
, /* header_byteorder */
2335 0, /* Object flags. */
2336 0, /* Sect flags. */
2337 0, /* symbol_leading_char. */
2338 ' ', /* ar_pad_char. */
2339 15, /* ar_max_namelen. */
2340 0, /* match priority. */
2341 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
2342 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
2343 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
,
2344 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
2345 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
2346 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
,
2347 { /* bfd_check_format. */
2350 _bfd_vms_lib_txt_archive_p
,
2353 { /* bfd_set_format. */
2354 _bfd_bool_bfd_false_error
,
2355 _bfd_bool_bfd_false_error
,
2356 _bfd_bool_bfd_false_error
,
2357 _bfd_bool_bfd_false_error
2359 { /* bfd_write_contents. */
2360 _bfd_bool_bfd_false_error
,
2361 _bfd_bool_bfd_false_error
,
2362 _bfd_bool_bfd_false_error
,
2363 _bfd_bool_bfd_false_error
2365 BFD_JUMP_TABLE_GENERIC (_bfd_generic
),
2366 BFD_JUMP_TABLE_COPY (_bfd_generic
),
2367 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
2368 BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib
),
2369 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols
),
2370 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs
),
2371 BFD_JUMP_TABLE_WRITE (_bfd_nowrite
),
2372 BFD_JUMP_TABLE_LINK (_bfd_nolink
),
2373 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),