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 (reclen
);
574 if (bfd_bread (buf
, reclen
, abfd
) != reclen
)
579 map
= (struct vms_dcxmap
*)buf
;
580 tdata
->nbr_dcxsbm
= bfd_getl16 (map
->nsubs
);
581 sbm_off
= bfd_getl16 (map
->sub0
);
582 tdata
->dcxsbm
= (struct dcxsbm_desc
*)bfd_alloc
583 (abfd
, tdata
->nbr_dcxsbm
* sizeof (struct dcxsbm_desc
));
584 for (i
= 0; i
< tdata
->nbr_dcxsbm
; i
++)
586 struct vms_dcxsbm
*sbm
= (struct vms_dcxsbm
*) (buf
+ sbm_off
);
587 struct dcxsbm_desc
*sbmdesc
= &tdata
->dcxsbm
[i
];
588 unsigned int sbm_len
;
591 unsigned char *data
= (unsigned char *)sbm
;
595 sbm_sz
= bfd_getl16 (sbm
->size
);
597 BFD_ASSERT (sbm_off
<= reclen
);
599 sbmdesc
->min_char
= sbm
->min_char
;
600 BFD_ASSERT (sbmdesc
->min_char
== 0);
601 sbmdesc
->max_char
= sbm
->max_char
;
602 sbm_len
= sbmdesc
->max_char
- sbmdesc
->min_char
+ 1;
603 l
= (2 * sbm_len
+ 7) / 8;
605 (sbm_sz
>= sizeof (struct vms_dcxsbm
) + l
+ 3 * sbm_len
606 || (tdata
->nbr_dcxsbm
== 1
607 && sbm_sz
>= sizeof (struct vms_dcxsbm
) + l
+ sbm_len
));
608 sbmdesc
->flags
= (unsigned char *)bfd_alloc (abfd
, l
);
609 memcpy (sbmdesc
->flags
, data
+ bfd_getl16 (sbm
->flags
), l
);
610 sbmdesc
->nodes
= (unsigned char *)bfd_alloc (abfd
, 2 * sbm_len
);
611 memcpy (sbmdesc
->nodes
, data
+ bfd_getl16 (sbm
->nodes
), 2 * sbm_len
);
612 off
= bfd_getl16 (sbm
->next
);
615 /* Read the 'next' array. */
616 sbmdesc
->next
= (unsigned short *)bfd_alloc
617 (abfd
, sbm_len
* sizeof (unsigned short));
619 for (j
= 0; j
< sbm_len
; j
++)
620 sbmdesc
->next
[j
] = bfd_getl16 (buf1
+ j
* 2);
624 /* There is no next array if there is only one submap. */
625 BFD_ASSERT (tdata
->nbr_dcxsbm
== 1);
626 sbmdesc
->next
= NULL
;
633 tdata
->nbr_dcxsbm
= 0;
636 /* The map is always present. Also mark shared image library. */
637 abfd
->has_armap
= TRUE
;
638 if (tdata
->type
== LBR__C_TYP_ESHSTB
|| tdata
->type
== LBR__C_TYP_ISHSTB
)
639 abfd
->is_thin_archive
= TRUE
;
644 bfd_release (abfd
, tdata
);
645 abfd
->tdata
.any
= (void *)tdata_hold
;
649 /* Standard function for alpha libraries. */
652 _bfd_vms_lib_alpha_archive_p (bfd
*abfd
)
654 return _bfd_vms_lib_archive_p (abfd
, vms_lib_alpha
);
657 /* Standard function for ia64 libraries. */
660 _bfd_vms_lib_ia64_archive_p (bfd
*abfd
)
662 return _bfd_vms_lib_archive_p (abfd
, vms_lib_ia64
);
665 /* Standard function for text libraries. */
667 static const bfd_target
*
668 _bfd_vms_lib_txt_archive_p (bfd
*abfd
)
670 return _bfd_vms_lib_archive_p (abfd
, vms_lib_txt
);
673 /* Standard bfd function. */
676 _bfd_vms_lib_mkarchive (bfd
*abfd
, enum vms_lib_kind kind
)
678 struct lib_tdata
*tdata
;
680 tdata
= (struct lib_tdata
*) bfd_zalloc (abfd
, sizeof (struct lib_tdata
));
684 abfd
->tdata
.any
= (void *)tdata
;
685 vms_get_time (&tdata
->credat_hi
, &tdata
->credat_lo
);
691 tdata
->ver
= LBR_MAJORID
;
692 tdata
->mhd_size
= offsetof (struct vms_mhd
, pad1
);
693 tdata
->type
= LBR__C_TYP_EOBJ
;
696 tdata
->ver
= LBR_ELFMAJORID
;
697 tdata
->mhd_size
= sizeof (struct vms_mhd
);
698 tdata
->type
= LBR__C_TYP_IOBJ
;
704 tdata
->nbr_modules
= 0;
705 tdata
->artdata
.symdef_count
= 0;
706 tdata
->modules
= NULL
;
707 tdata
->artdata
.symdefs
= NULL
;
714 _bfd_vms_lib_alpha_mkarchive (bfd
*abfd
)
716 return _bfd_vms_lib_mkarchive (abfd
, vms_lib_alpha
);
720 _bfd_vms_lib_ia64_mkarchive (bfd
*abfd
)
722 return _bfd_vms_lib_mkarchive (abfd
, vms_lib_ia64
);
725 /* Find NAME in the symbol index. Return the index. */
728 _bfd_vms_lib_find_symbol (bfd
*abfd
, const char *name
)
730 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
731 carsym
*syms
= tdata
->artdata
.symdefs
;
734 /* Open-coded binary search for speed. */
736 hi
= tdata
->artdata
.symdef_count
- 1;
740 int mid
= lo
+ (hi
- lo
) / 2;
743 diff
= (char)(name
[0] - syms
[mid
].name
[0]);
745 diff
= strcmp (name
, syms
[mid
].name
);
753 return BFD_NO_MORE_SYMBOLS
;
756 /* IO vector for archive member. Need that because members are not linearly
757 stored in archives. */
761 /* Current offset. */
764 /* Length of the module, when known. */
767 /* Current position in the record from bfd_bread point of view (ie, after
768 decompression). 0 means that no data byte have been read, -2 and -1
769 are reserved for the length word. */
771 #define REC_POS_NL -4
772 #define REC_POS_PAD -3
773 #define REC_POS_LEN0 -2
774 #define REC_POS_LEN1 -1
777 unsigned short rec_len
;
778 /* Number of bytes to read in the current record. */
779 unsigned short rec_rem
;
780 /* Offset of the next block. */
782 /* Current *data* offset in the data block. */
783 unsigned short blk_off
;
785 /* Offset of the first block. Extracted from the index. */
786 file_ptr first_block
;
788 /* Initial next_block. Extracted when the MHD is read. */
789 file_ptr init_next_block
;
790 /* Initial blk_off, once the MHD is read. */
791 unsigned short init_blk_off
;
793 /* Used to store any 3 byte record, which could be the EOF pattern. */
794 unsigned char pattern
[4];
797 struct dcxsbm_desc
*dcxsbms
;
798 /* Current submap. */
799 struct dcxsbm_desc
*dcx_sbm
;
800 /* Current offset in the submap. */
801 unsigned int dcx_offset
;
804 /* Compressed buffer. */
805 unsigned char *dcx_buf
;
806 /* Size of the buffer. Used to resize. */
807 unsigned int dcx_max
;
808 /* Number of valid bytes in the buffer. */
809 unsigned int dcx_rlen
;
812 /* Return the current position. */
815 vms_lib_btell (struct bfd
*abfd
)
817 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
821 /* Read the header of the next data block if all bytes of the current block
825 vms_lib_read_block (struct bfd
*abfd
)
827 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
829 if (vec
->blk_off
== DATA__LENGTH
)
831 unsigned char hdr
[DATA__DATA
];
833 /* Read next block. */
834 if (bfd_seek (abfd
->my_archive
, vec
->next_block
, SEEK_SET
) != 0)
836 if (bfd_bread (hdr
, sizeof (hdr
), abfd
->my_archive
) != sizeof (hdr
))
838 vec
->next_block
= (bfd_getl32 (hdr
+ 2) - 1) * VMS_BLOCK_SIZE
;
839 vec
->blk_off
= sizeof (hdr
);
844 /* Read NBYTES from ABFD into BUF if not NULL. If BUF is NULL, bytes are
845 not stored. Read linearly from the library, but handle blocks. This
846 function does not handle records nor EOF. */
849 vms_lib_bread_raw (struct bfd
*abfd
, unsigned char *buf
, file_ptr nbytes
)
851 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
859 /* Be sure the current data block is read. */
860 if (!vms_lib_read_block (abfd
))
863 /* Do not read past the data block, do not read more than requested. */
864 l
= DATA__LENGTH
- vec
->blk_off
;
871 /* Really read into BUF. */
872 if (bfd_bread (buf
, l
, abfd
->my_archive
) != l
)
877 /* Make as if we are reading. */
878 if (bfd_seek (abfd
->my_archive
, l
, SEEK_CUR
) != 0)
891 /* Decompress NBYTES from VEC. Store the bytes into BUF if not NULL. */
894 vms_lib_dcx (struct vms_lib_iovec
*vec
, unsigned char *buf
, file_ptr nbytes
)
896 struct dcxsbm_desc
*sbm
;
902 /* The loop below expect to deliver at least one byte. */
906 /* Get the current state. */
908 offset
= vec
->dcx_offset
;
909 j
= vec
->dcx_pos
& 7;
911 for (i
= vec
->dcx_pos
>> 3; i
< vec
->dcx_rlen
; i
++)
913 unsigned char b
= vec
->dcx_buf
[i
];
919 if (!(sbm
->flags
[offset
>> 3] & (1 << (offset
& 7))))
921 unsigned int n_offset
= sbm
->nodes
[offset
];
924 /* End of buffer. Stay where we are. */
925 vec
->dcx_pos
= (i
<< 3) + j
;
928 vec
->dcx_offset
= offset
;
932 offset
= 2 * n_offset
;
936 unsigned char v
= sbm
->nodes
[offset
];
938 if (sbm
->next
!= NULL
)
939 sbm
= vec
->dcxsbms
+ sbm
->next
[v
];
950 vec
->dcx_pos
= (i
<< 3) + j
+ 1;
951 vec
->dcx_offset
= offset
;
964 /* Standard IOVEC function. */
967 vms_lib_bread (struct bfd
*abfd
, void *vbuf
, file_ptr nbytes
)
969 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
972 unsigned char *buf
= (unsigned char *)vbuf
;
974 /* Do not read past the end. */
975 if (vec
->where
>= vec
->file_len
)
981 if (vec
->rec_rem
== 0)
983 unsigned char blen
[2];
985 /* Read record length. */
986 if (vms_lib_bread_raw (abfd
, blen
, sizeof (blen
)) != sizeof (blen
))
988 vec
->rec_len
= bfd_getl16 (blen
);
989 if (bfd_libdata (abfd
->my_archive
)->kind
== vms_lib_txt
)
991 /* Discard record size and align byte. */
993 vec
->rec_rem
= vec
->rec_len
;
997 /* Prepend record size. */
998 vec
->rec_pos
= REC_POS_LEN0
;
999 vec
->rec_rem
= (vec
->rec_len
+ 1) & ~1; /* With align byte. */
1001 if (vec
->rec_len
== 3)
1003 /* Possibly end of file. Check the pattern. */
1004 if (vms_lib_bread_raw (abfd
, vec
->pattern
, 4) != 4)
1006 if (!memcmp (vec
->pattern
, eotdesc
+ 2, 3))
1008 /* This is really an EOF. */
1010 vec
->file_len
= vec
->where
;
1015 if (vec
->dcxsbms
!= NULL
)
1017 /* This is a compressed member. */
1021 /* Be sure there is enough room for the expansion. */
1022 len
= (vec
->rec_len
+ 1) & ~1;
1023 if (len
> vec
->dcx_max
)
1025 while (len
> vec
->dcx_max
)
1027 vec
->dcx_buf
= bfd_alloc (abfd
, vec
->dcx_max
);
1028 if (vec
->dcx_buf
== NULL
)
1032 /* Read the compressed record. */
1033 vec
->dcx_rlen
= len
;
1034 if (vec
->rec_len
== 3)
1037 memcpy (vec
->dcx_buf
, vec
->pattern
, 3);
1041 elen
= vms_lib_bread_raw (abfd
, vec
->dcx_buf
, len
);
1046 /* Dummy expansion to get the expanded length. */
1047 vec
->dcx_offset
= 0;
1048 vec
->dcx_sbm
= vec
->dcxsbms
;
1050 elen
= vms_lib_dcx (vec
, NULL
, 0x10000);
1053 vec
->rec_len
= elen
;
1054 vec
->rec_rem
= elen
;
1056 /* Reset the state. */
1057 vec
->dcx_offset
= 0;
1058 vec
->dcx_sbm
= vec
->dcxsbms
;
1062 if (vec
->rec_pos
< 0)
1065 switch (vec
->rec_pos
)
1068 c
= vec
->rec_len
& 0xff;
1069 vec
->rec_pos
= REC_POS_LEN1
;
1072 c
= (vec
->rec_len
>> 8) & 0xff;
1096 if (nbytes
> vec
->rec_rem
)
1097 chunk
= vec
->rec_rem
;
1101 if (vec
->dcxsbms
!= NULL
)
1103 /* Optimize the stat() case: no need to decompress again as we
1105 if (!(buf
== NULL
&& chunk
== vec
->rec_rem
))
1106 chunk
= vms_lib_dcx (vec
, buf
, chunk
);
1110 if (vec
->rec_len
== 3)
1113 memcpy (buf
, vec
->pattern
+ vec
->rec_pos
, chunk
);
1116 chunk
= vms_lib_bread_raw (abfd
, buf
, chunk
);
1124 vec
->rec_pos
+= chunk
;
1125 vec
->rec_rem
-= chunk
;
1127 if (vec
->rec_rem
== 0)
1129 /* End of record reached. */
1130 if (bfd_libdata (abfd
->my_archive
)->kind
== vms_lib_txt
)
1132 if ((vec
->rec_len
& 1) == 1
1133 && vec
->rec_len
!= 3
1134 && vec
->dcxsbms
== NULL
)
1136 /* Eat the pad byte. */
1138 if (vms_lib_bread_raw (abfd
, &pad
, 1) != 1)
1141 vec
->rec_pos
= REC_POS_NL
;
1146 if ((vec
->rec_len
& 1) == 1 && vec
->dcxsbms
!= NULL
)
1148 vec
->rec_pos
= REC_POS_PAD
;
1158 /* Standard function, but we currently only handle the rewind case. */
1161 vms_lib_bseek (struct bfd
*abfd
, file_ptr offset
, int whence
)
1163 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1165 if (whence
== SEEK_SET
&& offset
== 0)
1170 vec
->blk_off
= vec
->init_blk_off
;
1171 vec
->next_block
= vec
->init_next_block
;
1173 if (bfd_seek (abfd
->my_archive
, vec
->first_block
, SEEK_SET
) != 0)
1182 vms_lib_bwrite (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1183 const void *where ATTRIBUTE_UNUSED
,
1184 file_ptr nbytes ATTRIBUTE_UNUSED
)
1190 vms_lib_bclose (struct bfd
*abfd
)
1192 abfd
->iostream
= NULL
;
1197 vms_lib_bflush (struct bfd
*abfd ATTRIBUTE_UNUSED
)
1203 vms_lib_bstat (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1204 struct stat
*sb ATTRIBUTE_UNUSED
)
1206 /* Not supported. */
1211 vms_lib_bmmap (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1212 void *addr ATTRIBUTE_UNUSED
,
1213 bfd_size_type len ATTRIBUTE_UNUSED
,
1214 int prot ATTRIBUTE_UNUSED
,
1215 int flags ATTRIBUTE_UNUSED
,
1216 file_ptr offset ATTRIBUTE_UNUSED
,
1217 void **map_addr ATTRIBUTE_UNUSED
,
1218 bfd_size_type
*map_len ATTRIBUTE_UNUSED
)
1223 static const struct bfd_iovec vms_lib_iovec
= {
1224 &vms_lib_bread
, &vms_lib_bwrite
, &vms_lib_btell
, &vms_lib_bseek
,
1225 &vms_lib_bclose
, &vms_lib_bflush
, &vms_lib_bstat
, &vms_lib_bmmap
1228 /* Open a library module. FILEPOS is the position of the module header. */
1231 vms_lib_bopen (bfd
*el
, file_ptr filepos
)
1233 struct vms_lib_iovec
*vec
;
1234 unsigned char buf
[256];
1235 struct vms_mhd
*mhd
;
1236 struct lib_tdata
*tdata
= bfd_libdata (el
->my_archive
);
1239 /* Allocate and initialized the iovec. */
1240 vec
= bfd_zalloc (el
, sizeof (*vec
));
1245 el
->iovec
= &vms_lib_iovec
;
1247 /* File length is not known. */
1250 /* Read the first data block. */
1251 vec
->next_block
= filepos
& ~(VMS_BLOCK_SIZE
- 1);
1252 vec
->blk_off
= DATA__LENGTH
;
1253 if (!vms_lib_read_block (el
))
1256 /* Prepare to read the first record. */
1257 vec
->blk_off
= filepos
& (VMS_BLOCK_SIZE
- 1);
1259 if (bfd_seek (el
->my_archive
, filepos
, SEEK_SET
) != 0)
1262 /* Read Record length + MHD + align byte. */
1263 len
= tdata
->mhd_size
;
1264 if (vms_lib_bread_raw (el
, buf
, 2) != 2)
1266 if (bfd_getl16 (buf
) != len
)
1268 len
= (len
+ 1) & ~1;
1269 BFD_ASSERT (len
<= sizeof (buf
));
1270 if (vms_lib_bread_raw (el
, buf
, len
) != len
)
1273 /* Get info from mhd. */
1274 mhd
= (struct vms_mhd
*)buf
;
1276 if (mhd
->id
!= MHD__C_MHDID
)
1278 if (len
>= MHD__C_MHDLEN
+ 1)
1279 el
->selective_search
= (mhd
->objstat
& MHD__M_SELSRC
) ? 1 : 0;
1280 el
->mtime
= vms_rawtime_to_time_t (mhd
->datim
);
1281 el
->mtime_set
= TRUE
;
1283 /* Reinit the iovec so that seek() will point to the first record after
1286 vec
->init_blk_off
= vec
->blk_off
;
1287 vec
->init_next_block
= vec
->next_block
;
1288 vec
->first_block
= bfd_tell (el
->my_archive
);
1289 vec
->dcxsbms
= bfd_libdata (el
->my_archive
)->dcxsbm
;
1291 if (vec
->dcxsbms
!= NULL
)
1294 vec
->dcx_max
= 10 * 1024;
1295 vec
->dcx_buf
= bfd_alloc (el
, vec
->dcx_max
);
1297 if (vec
->dcx_buf
== NULL
)
1303 /* Get member MODIDX. Return NULL in case of error. */
1306 _bfd_vms_lib_get_module (bfd
*abfd
, unsigned int modidx
)
1308 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
1316 if (modidx
>= tdata
->nbr_modules
)
1319 /* Already loaded. */
1320 if (tdata
->cache
[modidx
])
1321 return tdata
->cache
[modidx
];
1324 file_off
= tdata
->modules
[modidx
].file_offset
;
1325 if (tdata
->type
!= LBR__C_TYP_IOBJ
)
1327 res
= _bfd_create_empty_archive_element_shell (abfd
);
1331 /* Special reader to deal with data blocks. */
1332 if (!vms_lib_bopen (res
, file_off
))
1338 struct vms_mhd
*mhd
;
1339 struct areltdata
*arelt
;
1341 /* Sanity check. The MHD must be big enough to contain module size. */
1342 if (tdata
->mhd_size
< offsetof (struct vms_mhd
, modsize
) + 4)
1345 /* Read the MHD now. */
1346 if (bfd_seek (abfd
, file_off
, SEEK_SET
) != 0)
1348 if (bfd_bread (buf
, tdata
->mhd_size
, abfd
) != tdata
->mhd_size
)
1351 mhd
= (struct vms_mhd
*) buf
;
1352 if (mhd
->id
!= MHD__C_MHDID
)
1355 res
= _bfd_create_empty_archive_element_shell (abfd
);
1358 arelt
= bfd_zmalloc (sizeof (*arelt
));
1364 res
->arelt_data
= arelt
;
1366 /* Get info from mhd. */
1367 if (tdata
->mhd_size
>= offsetof (struct vms_mhd
, objstat
) + 1)
1368 res
->selective_search
= (mhd
->objstat
& MHD__M_SELSRC
) ? 1 : 0;
1369 res
->mtime
= vms_rawtime_to_time_t (mhd
->datim
);
1370 res
->mtime_set
= TRUE
;
1372 arelt
->parsed_size
= bfd_getl32 (mhd
->modsize
);
1374 /* No need for a special reader as members are stored linearly.
1375 Just skip the MHD. */
1376 res
->origin
= file_off
+ tdata
->mhd_size
;
1380 name
= tdata
->modules
[modidx
].name
;
1381 namelen
= strlen (name
);
1382 newname
= bfd_malloc (namelen
+ 4 + 1);
1383 if (newname
== NULL
)
1388 strcpy (newname
, name
);
1389 switch (tdata
->type
)
1391 case LBR__C_TYP_IOBJ
:
1392 case LBR__C_TYP_EOBJ
:
1393 /* For object archives, append .obj to mimic standard behaviour. */
1394 strcpy (newname
+ namelen
, ".obj");
1399 bfd_set_filename (res
, newname
);
1401 tdata
->cache
[modidx
] = res
;
1406 /* Standard function: get member at IDX. */
1409 _bfd_vms_lib_get_elt_at_index (bfd
*abfd
, symindex symidx
)
1411 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
1413 unsigned int modidx
;
1416 if (symidx
> tdata
->artdata
.symdef_count
)
1418 file_off
= tdata
->artdata
.symdefs
[symidx
].file_offset
;
1421 for (modidx
= 0; modidx
< tdata
->nbr_modules
; modidx
++)
1423 if (tdata
->modules
[modidx
].file_offset
== file_off
)
1426 if (modidx
>= tdata
->nbr_modules
)
1429 return _bfd_vms_lib_get_module (abfd
, modidx
);
1432 /* Elements of an imagelib are stubs. You can get the real image with this
1436 _bfd_vms_lib_get_imagelib_file (bfd
*el
)
1438 bfd
*archive
= el
->my_archive
;
1439 const char *modname
= el
->filename
;
1440 int modlen
= strlen (modname
);
1445 /* Convert module name to lower case and append '.exe'. */
1446 filename
= bfd_alloc (el
, modlen
+ 5);
1447 if (filename
== NULL
)
1449 for (j
= 0; j
< modlen
; j
++)
1450 if (ISALPHA (modname
[j
]))
1451 filename
[j
] = TOLOWER (modname
[j
]);
1453 filename
[j
] = modname
[j
];
1454 memcpy (filename
+ modlen
, ".exe", 5);
1456 filename
= _bfd_append_relative_path (archive
, filename
);
1457 if (filename
== NULL
)
1459 res
= bfd_openr (filename
, NULL
);
1463 /* xgettext:c-format */
1464 _bfd_error_handler(_("could not open shared image '%s' from '%s'"),
1465 filename
, archive
->filename
);
1466 bfd_release (archive
, filename
);
1470 /* FIXME: put it in a cache ? */
1474 /* Standard function. */
1477 _bfd_vms_lib_openr_next_archived_file (bfd
*archive
,
1486 idx
= last_file
->proxy_origin
+ 1;
1488 if (idx
>= bfd_libdata (archive
)->nbr_modules
)
1490 bfd_set_error (bfd_error_no_more_archived_files
);
1494 res
= _bfd_vms_lib_get_module (archive
, idx
);
1497 res
->proxy_origin
= idx
;
1501 /* Standard function. Just compute the length. */
1504 _bfd_vms_lib_generic_stat_arch_elt (bfd
*abfd
, struct stat
*st
)
1506 struct lib_tdata
*tdata
;
1509 if (abfd
->my_archive
== NULL
)
1511 bfd_set_error (bfd_error_invalid_operation
);
1515 tdata
= bfd_libdata (abfd
->my_archive
);
1516 if (tdata
->type
!= LBR__C_TYP_IOBJ
)
1518 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1520 if (vec
->file_len
== (ufile_ptr
)-1)
1522 if (vms_lib_bseek (abfd
, 0, SEEK_SET
) != 0)
1525 /* Compute length. */
1526 while (vms_lib_bread (abfd
, NULL
, 1 << 20) > 0)
1529 st
->st_size
= vec
->file_len
;
1533 st
->st_size
= ((struct areltdata
*)abfd
->arelt_data
)->parsed_size
;
1536 if (abfd
->mtime_set
)
1537 st
->st_mtime
= abfd
->mtime
;
1547 /* Internal representation of an index entry. */
1551 /* Corresponding archive member. */
1554 /* Number of reference to this entry. */
1557 /* Length of the key. */
1558 unsigned short namlen
;
1564 /* Used to sort index entries. */
1567 lib_index_cmp (const void *lv
, const void *rv
)
1569 const struct lib_index
*l
= lv
;
1570 const struct lib_index
*r
= rv
;
1572 return strcmp (l
->name
, r
->name
);
1575 /* Maximum number of index blocks level. */
1577 #define MAX_LEVEL 10
1579 /* Get the size of an index entry. */
1582 get_idxlen (struct lib_index
*idx
, bfd_boolean is_elfidx
)
1586 /* 9 is the size of struct vms_elfidx without keyname. */
1587 if (idx
->namlen
> MAX_KEYLEN
)
1588 return 9 + sizeof (struct vms_kbn
);
1590 return 9 + idx
->namlen
;
1594 /* 7 is the size of struct vms_idx without keyname. */
1595 return 7 + idx
->namlen
;
1599 /* Write the index composed by NBR symbols contained in IDX.
1600 VBN is the first vbn to be used, and will contain on return the last vbn.
1601 Can be called with ABFD set to NULL just to size the index.
1602 If not null, TOPVBN will be assigned to the vbn of the root index tree.
1603 IS_ELFIDX is true for elfidx (ie ia64) indexes layout.
1604 Return TRUE on success. */
1607 vms_write_index (bfd
*abfd
,
1608 struct lib_index
*idx
, unsigned int nbr
, unsigned int *vbn
,
1609 unsigned int *topvbn
, bfd_boolean is_elfidx
)
1611 /* The index is organized as a tree. This function implements a naive
1612 algorithm to balance the tree: it fills the leaves, and create a new
1613 branch when all upper leaves and branches are full. We only keep in
1614 memory a path to the current leaf. */
1618 /* Disk blocks for the current path. */
1619 struct vms_indexdef
*rblk
[MAX_LEVEL
];
1620 /* Info on the current blocks. */
1623 unsigned int vbn
; /* VBN of the block. */
1624 /* The last entry is identified so that it could be copied to the
1626 unsigned short len
; /* Length up to the last entry. */
1627 unsigned short lastlen
; /* Length of the last entry. */
1630 /* The kbn blocks are used to store long symbol names. */
1631 unsigned int kbn_sz
= 0; /* Number of bytes available in the kbn block. */
1632 unsigned int kbn_vbn
= 0; /* VBN of the kbn block. */
1633 unsigned char *kbn_blk
= NULL
; /* Contents of the kbn block. */
1637 /* No entries. Very easy to handle. */
1645 /* Sort the index the first time this function is called. */
1646 qsort (idx
, nbr
, sizeof (struct lib_index
), lib_index_cmp
);
1649 /* Allocate first index block. */
1652 rblk
[0] = bfd_zmalloc (sizeof (struct vms_indexdef
));
1653 blk
[0].vbn
= (*vbn
)++;
1657 for (i
= 0; i
< nbr
; i
++, idx
++)
1659 unsigned int idxlen
;
1661 unsigned int key_vbn
= 0;
1662 unsigned int key_off
= 0;
1664 idxlen
= get_idxlen (idx
, is_elfidx
);
1666 if (is_elfidx
&& idx
->namlen
> MAX_KEYLEN
)
1668 /* If the key (ie name) is too long, write it in the kbn block. */
1669 unsigned int kl
= idx
->namlen
;
1670 unsigned int kl_chunk
;
1671 const char *key
= idx
->name
;
1673 /* Write the key in the kbn, chunk after chunk. */
1676 if (kbn_sz
< sizeof (struct vms_kbn
))
1678 /* Not enough room in the kbn block. */
1681 /* Write it to the disk (if there is one). */
1684 if (!vms_write_block (abfd
, kbn_vbn
, kbn_blk
))
1689 kbn_blk
= bfd_malloc (VMS_BLOCK_SIZE
);
1690 if (kbn_blk
== NULL
)
1693 *(unsigned short *)kbn_blk
= 0;
1695 /* Allocate a new block for the keys. */
1697 kbn_sz
= VMS_BLOCK_SIZE
- 2;
1699 /* Size of the chunk written to the current key block. */
1700 if (kl
+ sizeof (struct vms_kbn
) > kbn_sz
)
1701 kl_chunk
= kbn_sz
- sizeof (struct vms_kbn
);
1705 if (kbn_blk
!= NULL
)
1707 struct vms_kbn
*kbn
;
1709 kbn
= (struct vms_kbn
*)(kbn_blk
+ VMS_BLOCK_SIZE
- kbn_sz
);
1713 /* Save the rfa of the first chunk. */
1715 key_off
= VMS_BLOCK_SIZE
- kbn_sz
;
1718 bfd_putl16 (kl_chunk
, kbn
->keylen
);
1721 /* No next chunk. */
1722 bfd_putl32 (0, kbn
->rfa
.vbn
);
1723 bfd_putl16 (0, kbn
->rfa
.offset
);
1727 /* Next chunk will be at the start of the next block. */
1728 bfd_putl32 (*vbn
, kbn
->rfa
.vbn
);
1729 bfd_putl16 (2, kbn
->rfa
.offset
);
1731 memcpy ((char *)(kbn
+ 1), key
, kl_chunk
);
1735 kl_chunk
= (kl_chunk
+ 1) & ~1; /* Always align. */
1736 kbn_sz
-= kl_chunk
+ sizeof (struct vms_kbn
);
1741 /* Check if a block might overflow. In this case we will flush this
1742 block and all the blocks below it. */
1743 for (j
= 0; j
< level
; j
++)
1744 if (blk
[j
].len
+ blk
[j
].lastlen
+ idxlen
> INDEXDEF__BLKSIZ
)
1747 for (j
= 0; j
< level
; j
++)
1751 /* There is not enough room to write the new entry in this
1752 block or in a parent block. */
1756 BFD_ASSERT (level
< MAX_LEVEL
);
1758 /* Need to create a parent. */
1761 rblk
[level
] = bfd_zmalloc (sizeof (struct vms_indexdef
));
1762 bfd_putl32 (*vbn
, rblk
[j
]->parent
);
1764 blk
[level
].vbn
= (*vbn
)++;
1766 blk
[level
].lastlen
= blk
[j
].lastlen
;
1771 /* Update parent block: write the last entry from the current
1775 struct vms_rfa
*rfa
;
1777 /* Pointer to the last entry in parent block. */
1778 rfa
= (struct vms_rfa
*)(rblk
[j
+ 1]->keys
+ blk
[j
+ 1].len
);
1780 /* Copy the whole entry. */
1781 BFD_ASSERT (blk
[j
+ 1].lastlen
== blk
[j
].lastlen
);
1782 memcpy (rfa
, rblk
[j
]->keys
+ blk
[j
].len
, blk
[j
].lastlen
);
1783 /* Fix the entry (which in always the first field of an
1785 bfd_putl32 (blk
[j
].vbn
, rfa
->vbn
);
1786 bfd_putl16 (RFADEF__C_INDEX
, rfa
->offset
);
1791 /* And allocate it. Do it only on the block that won't be
1792 flushed (so that the parent of the parent can be
1794 blk
[j
+ 1].len
+= blk
[j
+ 1].lastlen
;
1795 blk
[j
+ 1].lastlen
= 0;
1798 /* Write this block on the disk. */
1801 bfd_putl16 (blk
[j
].len
+ blk
[j
].lastlen
, rblk
[j
]->used
);
1802 if (!vms_write_block (abfd
, blk
[j
].vbn
, rblk
[j
]))
1806 /* Reset this block. */
1809 blk
[j
].vbn
= (*vbn
)++;
1812 /* Append it to the block. */
1815 /* Keep the previous last entry. */
1816 blk
[j
].len
+= blk
[j
].lastlen
;
1820 struct vms_rfa
*rfa
;
1822 rfa
= (struct vms_rfa
*)(rblk
[j
]->keys
+ blk
[j
].len
);
1823 bfd_putl32 ((idx
->abfd
->proxy_origin
/ VMS_BLOCK_SIZE
) + 1,
1826 ((idx
->abfd
->proxy_origin
% VMS_BLOCK_SIZE
)
1827 + (is_elfidx
? 0 : DATA__DATA
),
1832 /* Use elfidx format. */
1833 struct vms_elfidx
*en
= (struct vms_elfidx
*)rfa
;
1838 /* Long symbol name. */
1839 struct vms_kbn
*k
= (struct vms_kbn
*)(en
->keyname
);
1840 bfd_putl16 (sizeof (struct vms_kbn
), en
->keylen
);
1841 bfd_putl16 (idx
->namlen
, k
->keylen
);
1842 bfd_putl32 (key_vbn
, k
->rfa
.vbn
);
1843 bfd_putl16 (key_off
, k
->rfa
.offset
);
1844 en
->flags
|= ELFIDX__SYMESC
;
1848 bfd_putl16 (idx
->namlen
, en
->keylen
);
1849 memcpy (en
->keyname
, idx
->name
, idx
->namlen
);
1854 /* Use idx format. */
1855 struct vms_idx
*en
= (struct vms_idx
*)rfa
;
1856 en
->keylen
= idx
->namlen
;
1857 memcpy (en
->keyname
, idx
->name
, idx
->namlen
);
1861 /* The last added key can now be the last one all blocks in the
1863 blk
[j
].lastlen
= idxlen
;
1867 /* Save VBN of the root. */
1869 *topvbn
= blk
[level
- 1].vbn
;
1875 for (j
= 1; j
< level
; j
++)
1877 /* Update parent block: write the new entry. */
1880 struct vms_rfa
*rfa
;
1882 en
= rblk
[j
- 1]->keys
+ blk
[j
- 1].len
;
1883 par
= rblk
[j
]->keys
+ blk
[j
].len
;
1884 BFD_ASSERT (blk
[j
].lastlen
== blk
[j
- 1].lastlen
);
1885 memcpy (par
, en
, blk
[j
- 1].lastlen
);
1886 rfa
= (struct vms_rfa
*)par
;
1887 bfd_putl32 (blk
[j
- 1].vbn
, rfa
->vbn
);
1888 bfd_putl16 (RFADEF__C_INDEX
, rfa
->offset
);
1891 for (j
= 0; j
< level
; j
++)
1893 /* Write this block on the disk. */
1894 bfd_putl16 (blk
[j
].len
+ blk
[j
].lastlen
, rblk
[j
]->used
);
1895 if (!vms_write_block (abfd
, blk
[j
].vbn
, rblk
[j
]))
1901 /* Write the last kbn (if any). */
1904 if (!vms_write_block (abfd
, kbn_vbn
, kbn_blk
))
1912 /* Append data to the data block DATA. Force write if PAD is true. */
1915 vms_write_data_block (bfd
*arch
, struct vms_datadef
*data
, file_ptr
*off
,
1916 const unsigned char *buf
, unsigned int len
, int pad
)
1918 while (len
> 0 || pad
)
1920 unsigned int doff
= *off
& (VMS_BLOCK_SIZE
- 1);
1921 unsigned int remlen
= (DATA__LENGTH
- DATA__DATA
) - doff
;
1924 l
= (len
> remlen
) ? remlen
: len
;
1925 memcpy (data
->data
+ doff
, buf
, l
);
1931 if (doff
== (DATA__LENGTH
- DATA__DATA
) || (len
== 0 && pad
))
1935 bfd_putl32 ((*off
/ VMS_BLOCK_SIZE
) + 2, data
->link
);
1937 if (bfd_bwrite (data
, sizeof (*data
), arch
) != sizeof (*data
))
1940 *off
+= DATA__LENGTH
- doff
;
1949 /* Build the symbols index. */
1952 _bfd_vms_lib_build_map (unsigned int nbr_modules
,
1953 struct lib_index
*modules
,
1954 unsigned int *res_cnt
,
1955 struct lib_index
**res
)
1958 asymbol
**syms
= NULL
;
1960 struct lib_index
*map
= NULL
;
1961 unsigned int map_max
= 1024; /* Fine initial default. */
1962 unsigned int map_count
= 0;
1964 map
= (struct lib_index
*) bfd_malloc (map_max
* sizeof (struct lib_index
));
1968 /* Gather symbols. */
1969 for (i
= 0; i
< nbr_modules
; i
++)
1974 bfd
*current
= modules
[i
].abfd
;
1976 if ((bfd_get_file_flags (current
) & HAS_SYMS
) == 0)
1979 storage
= bfd_get_symtab_upper_bound (current
);
1985 if (storage
> syms_max
)
1990 syms
= (asymbol
**) bfd_malloc (syms_max
);
1994 symcount
= bfd_canonicalize_symtab (current
, syms
);
1998 /* Now map over all the symbols, picking out the ones we
2000 for (src_count
= 0; src_count
< symcount
; src_count
++)
2002 flagword flags
= (syms
[src_count
])->flags
;
2003 asection
*sec
= syms
[src_count
]->section
;
2005 if ((flags
& BSF_GLOBAL
2007 || flags
& BSF_INDIRECT
2008 || bfd_is_com_section (sec
))
2009 && ! bfd_is_und_section (sec
))
2011 struct lib_index
*new_map
;
2013 /* This symbol will go into the archive header. */
2014 if (map_count
== map_max
)
2017 new_map
= (struct lib_index
*)
2018 bfd_realloc (map
, map_max
* sizeof (struct lib_index
));
2019 if (new_map
== NULL
)
2024 map
[map_count
].abfd
= current
;
2025 map
[map_count
].namlen
= strlen (syms
[src_count
]->name
);
2026 map
[map_count
].name
= syms
[src_count
]->name
;
2034 *res_cnt
= map_count
;
2046 /* Do the hard work: write an archive on the disk. */
2049 _bfd_vms_lib_write_archive_contents (bfd
*arch
)
2052 unsigned int nbr_modules
;
2053 struct lib_index
*modules
;
2054 unsigned int nbr_symbols
;
2055 struct lib_index
*symbols
;
2056 struct lib_tdata
*tdata
= bfd_libdata (arch
);
2059 unsigned int nbr_mod_iblk
;
2060 unsigned int nbr_sym_iblk
;
2062 unsigned int mod_idx_vbn
;
2063 unsigned int sym_idx_vbn
;
2064 bfd_boolean is_elfidx
= tdata
->kind
== vms_lib_ia64
;
2065 unsigned int max_keylen
= is_elfidx
? MAX_EKEYLEN
: MAX_KEYLEN
;
2067 /* Count the number of modules (and do a first sanity check). */
2069 for (current
= arch
->archive_head
;
2071 current
= current
->archive_next
)
2073 /* This check is checking the bfds for the objects we're reading
2074 from (which are usually either an object file or archive on
2075 disk), not the archive entries we're writing to. We don't
2076 actually create bfds for the archive members, we just copy
2077 them byte-wise when we write out the archive. */
2078 if (bfd_write_p (current
) || !bfd_check_format (current
, bfd_object
))
2080 bfd_set_error (bfd_error_invalid_operation
);
2087 /* Build the modules list. */
2088 BFD_ASSERT (tdata
->modules
== NULL
);
2089 modules
= bfd_alloc (arch
, nbr_modules
* sizeof (struct lib_index
));
2090 if (modules
== NULL
)
2093 for (current
= arch
->archive_head
, i
= 0;
2095 current
= current
->archive_next
, i
++)
2099 modules
[i
].abfd
= current
;
2100 modules
[i
].name
= vms_get_module_name (current
->filename
, FALSE
);
2103 /* FIXME: silently truncate long names ? */
2104 nl
= strlen (modules
[i
].name
);
2105 modules
[i
].namlen
= (nl
> max_keylen
? max_keylen
: nl
);
2108 /* Create the module index. */
2110 if (!vms_write_index (NULL
, modules
, nbr_modules
, &vbn
, NULL
, is_elfidx
))
2114 /* Create symbol index. */
2115 if (!_bfd_vms_lib_build_map (nbr_modules
, modules
, &nbr_symbols
, &symbols
))
2119 if (!vms_write_index (NULL
, symbols
, nbr_symbols
, &vbn
, NULL
, is_elfidx
))
2123 /* Write modules and remember their position. */
2124 off
= (1 + nbr_mod_iblk
+ nbr_sym_iblk
) * VMS_BLOCK_SIZE
;
2126 if (bfd_seek (arch
, off
, SEEK_SET
) != 0)
2129 for (i
= 0; i
< nbr_modules
; i
++)
2131 struct vms_datadef data
;
2132 unsigned char blk
[VMS_BLOCK_SIZE
];
2133 struct vms_mhd
*mhd
;
2136 current
= modules
[i
].abfd
;
2137 current
->proxy_origin
= off
;
2143 /* Write the MHD as a record (ie, size first). */
2145 bfd_putl16 (tdata
->mhd_size
, blk
);
2147 mhd
= (struct vms_mhd
*)(blk
+ sz
);
2148 memset (mhd
, 0, sizeof (struct vms_mhd
));
2150 mhd
->id
= MHD__C_MHDID
;
2152 memcpy (mhd
->objid
, "V1.0", 4);
2153 bfd_putl32 (modules
[i
].ref
, mhd
->refcnt
);
2156 sz
+= tdata
->mhd_size
;
2159 /* Rewind the member to be put into the archive. */
2160 if (bfd_seek (current
, 0, SEEK_SET
) != 0)
2163 /* Copy the member into the archive. */
2166 unsigned int modsize
= 0;
2168 file_ptr off_hdr
= off
;
2170 /* Read to complete the first block. */
2171 amt
= bfd_bread (blk
+ sz
, VMS_BLOCK_SIZE
- sz
, current
);
2172 if (amt
== (bfd_size_type
)-1)
2175 if (amt
< VMS_BLOCK_SIZE
- sz
)
2177 /* The member size is less than a block. Pad the block. */
2178 memset (blk
+ sz
+ amt
, 0, VMS_BLOCK_SIZE
- sz
- amt
);
2180 bfd_putl32 (modsize
, mhd
->modsize
);
2182 /* Write the first block (which contains an mhd). */
2183 if (bfd_bwrite (blk
, VMS_BLOCK_SIZE
, arch
) != VMS_BLOCK_SIZE
)
2185 off
+= VMS_BLOCK_SIZE
;
2187 if (amt
== VMS_BLOCK_SIZE
- sz
)
2189 /* Copy the remaining. */
2190 char buffer
[DEFAULT_BUFFERSIZE
];
2194 amt
= bfd_bread (buffer
, sizeof (buffer
), current
);
2195 if (amt
== (bfd_size_type
)-1)
2200 if (amt
!= sizeof (buffer
))
2202 /* Clear the padding. */
2203 memset (buffer
+ amt
, 0, sizeof (buffer
) - amt
);
2204 amt
= (amt
+ VMS_BLOCK_SIZE
) & ~(VMS_BLOCK_SIZE
- 1);
2206 if (bfd_bwrite (buffer
, amt
, arch
) != amt
)
2211 /* Now that the size is known, write the first block (again). */
2212 bfd_putl32 (modsize
, mhd
->modsize
);
2213 if (bfd_seek (arch
, off_hdr
, SEEK_SET
) != 0
2214 || bfd_bwrite (blk
, VMS_BLOCK_SIZE
, arch
) != VMS_BLOCK_SIZE
)
2216 if (bfd_seek (arch
, off
, SEEK_SET
) != 0)
2222 /* Write the MHD. */
2223 if (vms_write_data_block (arch
, &data
, &off
, blk
, sz
, 0) < 0)
2226 /* Write the member. */
2229 sz
= bfd_bread (blk
, sizeof (blk
), current
);
2232 if (vms_write_data_block (arch
, &data
, &off
, blk
, sz
, 0) < 0)
2236 /* Write the end of module marker. */
2237 if (vms_write_data_block (arch
, &data
, &off
,
2238 eotdesc
, sizeof (eotdesc
), 1) < 0)
2243 /* Write the indexes. */
2245 if (!vms_write_index (arch
, modules
, nbr_modules
, &vbn
, &mod_idx_vbn
,
2248 if (!vms_write_index (arch
, symbols
, nbr_symbols
, &vbn
, &sym_idx_vbn
,
2252 /* Write libary header. */
2254 unsigned char blk
[VMS_BLOCK_SIZE
];
2255 struct vms_lhd
*lhd
= (struct vms_lhd
*)blk
;
2256 struct vms_idd
*idd
= (struct vms_idd
*)(blk
+ sizeof (*lhd
));
2257 unsigned int idd_flags
;
2258 unsigned int saneid
;
2260 memset (blk
, 0, sizeof (blk
));
2262 lhd
->type
= tdata
->type
;
2264 switch (tdata
->kind
)
2267 saneid
= LHD_SANEID3
;
2270 saneid
= LHD_SANEID6
;
2275 bfd_putl32 (saneid
, lhd
->sanity
);
2276 bfd_putl16 (tdata
->ver
, lhd
->majorid
);
2277 bfd_putl16 (0, lhd
->minorid
);
2278 snprintf ((char *)lhd
->lbrver
+ 1, sizeof (lhd
->lbrver
) - 1,
2280 (unsigned)(BFD_VERSION
/ 100000000UL),
2281 (unsigned)(BFD_VERSION
/ 1000000UL) % 100,
2282 (unsigned)(BFD_VERSION
/ 10000UL) % 100);
2283 lhd
->lbrver
[sizeof (lhd
->lbrver
) - 1] = 0;
2284 lhd
->lbrver
[0] = strlen ((char *)lhd
->lbrver
+ 1);
2286 bfd_putl32 (tdata
->credat_lo
, lhd
->credat
+ 0);
2287 bfd_putl32 (tdata
->credat_hi
, lhd
->credat
+ 4);
2288 vms_raw_get_time (lhd
->updtim
);
2290 lhd
->mhdusz
= tdata
->mhd_size
- MHD__C_USRDAT
;
2292 bfd_putl32 (nbr_modules
+ nbr_symbols
, lhd
->idxcnt
);
2293 bfd_putl32 (nbr_modules
, lhd
->modcnt
);
2294 bfd_putl32 (nbr_modules
, lhd
->modhdrs
);
2296 /* Number of blocks for index. */
2297 bfd_putl32 (nbr_mod_iblk
+ nbr_sym_iblk
, lhd
->idxblks
);
2298 bfd_putl32 (vbn
- 1, lhd
->hipreal
);
2299 bfd_putl32 (vbn
- 1, lhd
->hiprusd
);
2301 /* VBN of the next free block. */
2302 bfd_putl32 ((off
/ VMS_BLOCK_SIZE
) + 1, lhd
->nextvbn
);
2303 bfd_putl32 ((off
/ VMS_BLOCK_SIZE
) + 1, lhd
->nextrfa
+ 0);
2304 bfd_putl16 (0, lhd
->nextrfa
+ 4);
2306 /* First index (modules name). */
2307 idd_flags
= IDD__FLAGS_ASCII
| IDD__FLAGS_VARLENIDX
2308 | IDD__FLAGS_NOCASECMP
| IDD__FLAGS_NOCASENTR
;
2309 bfd_putl16 (idd_flags
, idd
->flags
);
2310 bfd_putl16 (max_keylen
+ 1, idd
->keylen
);
2311 bfd_putl16 (mod_idx_vbn
, idd
->vbn
);
2314 /* Second index (symbols name). */
2315 bfd_putl16 (idd_flags
, idd
->flags
);
2316 bfd_putl16 (max_keylen
+ 1, idd
->keylen
);
2317 bfd_putl16 (sym_idx_vbn
, idd
->vbn
);
2320 if (!vms_write_block (arch
, 1, blk
))
2327 bfd_set_input_error (current
, bfd_get_error ());
2331 /* Add a target for text library. This costs almost nothing and is useful to
2332 read VMS library on the host. */
2334 const bfd_target alpha_vms_lib_txt_vec
=
2336 "vms-libtxt", /* Name. */
2337 bfd_target_unknown_flavour
,
2338 BFD_ENDIAN_UNKNOWN
, /* byteorder */
2339 BFD_ENDIAN_UNKNOWN
, /* header_byteorder */
2340 0, /* Object flags. */
2341 0, /* Sect flags. */
2342 0, /* symbol_leading_char. */
2343 ' ', /* ar_pad_char. */
2344 15, /* ar_max_namelen. */
2345 0, /* match priority. */
2346 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
2347 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
2348 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
,
2349 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
2350 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
2351 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
,
2352 { /* bfd_check_format. */
2355 _bfd_vms_lib_txt_archive_p
,
2358 { /* bfd_set_format. */
2359 _bfd_bool_bfd_false_error
,
2360 _bfd_bool_bfd_false_error
,
2361 _bfd_bool_bfd_false_error
,
2362 _bfd_bool_bfd_false_error
2364 { /* bfd_write_contents. */
2365 _bfd_bool_bfd_false_error
,
2366 _bfd_bool_bfd_false_error
,
2367 _bfd_bool_bfd_false_error
,
2368 _bfd_bool_bfd_false_error
2370 BFD_JUMP_TABLE_GENERIC (_bfd_generic
),
2371 BFD_JUMP_TABLE_COPY (_bfd_generic
),
2372 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
2373 BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib
),
2374 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols
),
2375 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs
),
2376 BFD_JUMP_TABLE_WRITE (_bfd_nowrite
),
2377 BFD_JUMP_TABLE_LINK (_bfd_nolink
),
2378 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),