1 /* BFD back-end for VMS archive files.
3 Copyright (C) 2010-2023 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 /* Do not allocate more that this number of entries. */
126 /* If true, the table was reallocated on the heap. If false, it is still
127 in the BFD's objalloc. */
131 /* Simply add a name to the index. */
134 vms_add_index (struct carsym_mem
*cs
, char *name
,
135 unsigned int idx_vbn
, unsigned int idx_off
)
137 if (cs
->nbr
== cs
->max
)
142 if (cs
->max
> -33u / 2 || cs
->max
>= cs
->limit
)
144 bfd_set_error (bfd_error_file_too_big
);
147 cs
->max
= 2 * cs
->max
+ 32;
148 if (cs
->max
> cs
->limit
)
150 if (_bfd_mul_overflow (cs
->max
, sizeof (struct carsym
), &amt
))
152 bfd_set_error (bfd_error_file_too_big
);
158 n
= bfd_malloc (amt
);
161 memcpy (n
, cs
->idx
, cs
->nbr
* sizeof (struct carsym
));
162 /* And unfortunately we can't free cs->idx. */
166 n
= bfd_realloc_or_free (cs
->idx
, amt
);
171 cs
->realloced
= true;
173 cs
->idx
[cs
->nbr
].file_offset
= (idx_vbn
- 1) * VMS_BLOCK_SIZE
+ idx_off
;
174 cs
->idx
[cs
->nbr
].name
= name
;
179 /* Follow all member of a lns list (pointed by RFA) and add indexes for
180 NAME. Return FALSE in case of error. */
183 vms_add_indexes_from_list (bfd
*abfd
, struct carsym_mem
*cs
, char *name
,
192 vbn
= bfd_getl32 (rfa
->vbn
);
197 off
= (vbn
- 1) * VMS_BLOCK_SIZE
+ bfd_getl16 (rfa
->offset
);
198 if (bfd_seek (abfd
, off
, SEEK_SET
) != 0
199 || bfd_bread (&lns
, sizeof (lns
), abfd
) != sizeof (lns
))
202 if (!vms_add_index (cs
, name
,
203 bfd_getl32 (lns
.modrfa
.vbn
),
204 bfd_getl16 (lns
.modrfa
.offset
)))
211 /* Read block VBN from ABFD and store it into BLK. Return FALSE in case of error. */
214 vms_read_block (bfd
*abfd
, unsigned int vbn
, void *blk
)
218 off
= (vbn
- 1) * VMS_BLOCK_SIZE
;
219 if (bfd_seek (abfd
, off
, SEEK_SET
) != 0
220 || bfd_bread (blk
, VMS_BLOCK_SIZE
, abfd
) != VMS_BLOCK_SIZE
)
226 /* Write the content of BLK to block VBN of ABFD. Return FALSE in case of error. */
229 vms_write_block (bfd
*abfd
, unsigned int vbn
, void *blk
)
233 off
= (vbn
- 1) * VMS_BLOCK_SIZE
;
234 if (bfd_seek (abfd
, off
, SEEK_SET
) != 0
235 || bfd_bwrite (blk
, VMS_BLOCK_SIZE
, abfd
) != VMS_BLOCK_SIZE
)
241 /* Read index block VBN and put the entry in **IDX (which is updated).
242 If the entry is indirect, recurse. */
245 vms_traverse_index (bfd
*abfd
, unsigned int vbn
, struct carsym_mem
*cs
,
246 unsigned int recur_count
)
248 struct vms_indexdef indexdef
;
254 if (recur_count
== 100)
256 bfd_set_error (bfd_error_bad_value
);
260 /* Read the index block. */
261 BFD_ASSERT (sizeof (indexdef
) == VMS_BLOCK_SIZE
);
262 if (!vms_read_block (abfd
, vbn
, &indexdef
))
266 p
= &indexdef
.keys
[0];
267 n
= bfd_getl16 (indexdef
.used
);
268 if (n
> sizeof (indexdef
.keys
))
273 unsigned int idx_vbn
;
274 unsigned int idx_off
;
276 unsigned char *keyname
;
279 /* Extract key length. */
280 if (bfd_libdata (abfd
)->ver
== LBR_MAJORID
281 && offsetof (struct vms_idx
, keyname
) <= (size_t) (endp
- p
))
283 struct vms_idx
*ridx
= (struct vms_idx
*)p
;
285 idx_vbn
= bfd_getl32 (ridx
->rfa
.vbn
);
286 idx_off
= bfd_getl16 (ridx
->rfa
.offset
);
288 keylen
= ridx
->keylen
;
290 keyname
= ridx
->keyname
;
292 else if (bfd_libdata (abfd
)->ver
== LBR_ELFMAJORID
293 && offsetof (struct vms_elfidx
, keyname
) <= (size_t) (endp
- p
))
295 struct vms_elfidx
*ridx
= (struct vms_elfidx
*)p
;
297 idx_vbn
= bfd_getl32 (ridx
->rfa
.vbn
);
298 idx_off
= bfd_getl16 (ridx
->rfa
.offset
);
300 keylen
= bfd_getl16 (ridx
->keylen
);
302 keyname
= ridx
->keyname
;
311 /* Point to the next index entry. */
312 p
= keyname
+ keylen
;
316 if (idx_off
== RFADEF__C_INDEX
)
318 /* Indirect entry. Recurse. */
319 if (!vms_traverse_index (abfd
, idx_vbn
, cs
, recur_count
+ 1))
324 /* Add a new entry. */
327 if (flags
& ELFIDX__SYMESC
)
329 /* Extended key name. */
330 unsigned int noff
= 0;
334 unsigned char kblk
[VMS_BLOCK_SIZE
];
337 if (keylen
!= sizeof (struct vms_kbn
))
340 kbn
= (struct vms_kbn
*)keyname
;
341 keylen
= bfd_getl16 (kbn
->keylen
);
343 name
= bfd_alloc (abfd
, keylen
+ 1);
346 kvbn
= bfd_getl32 (kbn
->rfa
.vbn
);
347 koff
= bfd_getl16 (kbn
->rfa
.offset
);
349 /* Read the key, chunk by chunk. */
354 if (!vms_read_block (abfd
, kvbn
, kblk
))
356 if (koff
> sizeof (kblk
) - sizeof (struct vms_kbn
))
358 kbn
= (struct vms_kbn
*)(kblk
+ koff
);
359 klen
= bfd_getl16 (kbn
->keylen
);
360 if (klen
> sizeof (kblk
) - sizeof (struct vms_kbn
) - koff
)
362 kvbn
= bfd_getl32 (kbn
->rfa
.vbn
);
363 koff
= bfd_getl16 (kbn
->rfa
.offset
);
365 if (noff
+ klen
> keylen
)
367 memcpy (name
+ noff
, kbn
+ 1, klen
);
378 /* Usual key name. */
379 name
= bfd_alloc (abfd
, keylen
+ 1);
383 memcpy (name
, keyname
, keylen
);
387 if (flags
& ELFIDX__LISTRFA
)
392 off
= (idx_vbn
- 1) * VMS_BLOCK_SIZE
+ idx_off
;
393 if (bfd_seek (abfd
, off
, SEEK_SET
) != 0
394 || bfd_bread (&lhs
, sizeof (lhs
), abfd
) != sizeof (lhs
))
397 /* These extra entries may cause reallocation of CS. */
398 if (!vms_add_indexes_from_list (abfd
, cs
, name
, &lhs
.ng_g_rfa
))
400 if (!vms_add_indexes_from_list (abfd
, cs
, name
, &lhs
.ng_wk_rfa
))
402 if (!vms_add_indexes_from_list (abfd
, cs
, name
, &lhs
.g_g_rfa
))
404 if (!vms_add_indexes_from_list (abfd
, cs
, name
, &lhs
.g_wk_rfa
))
409 if (!vms_add_index (cs
, name
, idx_vbn
, idx_off
))
418 /* Read index #IDX, which must have NBREL entries. */
420 static struct carsym
*
421 vms_lib_read_index (bfd
*abfd
, int idx
, unsigned int *nbrel
)
428 struct carsym
*csbuf
;
429 struct carsym_mem csm
;
431 /* Read index desription. */
432 if (bfd_seek (abfd
, LHD_IDXDESC
+ idx
* IDD_LENGTH
, SEEK_SET
) != 0
433 || bfd_bread (&idd
, sizeof (idd
), abfd
) != sizeof (idd
))
437 flags
= bfd_getl16 (idd
.flags
);
438 if (!(flags
& IDD__FLAGS_ASCII
)
439 || !(flags
& IDD__FLAGS_VARLENIDX
))
442 filesize
= bfd_get_file_size (abfd
);
446 csm
.realloced
= false;
449 /* Put an upper bound based on a file full of single char keys.
450 This is to prevent fuzzed binary silliness. It is easily
451 possible to set up loops over file blocks that add syms
453 if (filesize
/ (sizeof (struct vms_rfa
) + 2) <= -1u)
454 csm
.limit
= filesize
/ (sizeof (struct vms_rfa
) + 2);
456 if (csm
.max
> csm
.limit
)
458 if (_bfd_mul_overflow (csm
.max
, sizeof (struct carsym
), &amt
))
460 csm
.idx
= csbuf
= bfd_alloc (abfd
, amt
);
464 /* Note: if the index is empty, there is no block to traverse. */
465 vbn
= bfd_getl32 (idd
.vbn
);
466 if (vbn
!= 0 && !vms_traverse_index (abfd
, vbn
, &csm
, 0))
471 /* Note: in case of error, we can free what was allocated on the
473 bfd_release (abfd
, csbuf
);
479 /* There are more entries than the first estimate. Allocate on
480 the BFD's objalloc. */
481 csbuf
= bfd_alloc (abfd
, csm
.nbr
* sizeof (struct carsym
));
484 memcpy (csbuf
, csm
.idx
, csm
.nbr
* sizeof (struct carsym
));
492 /* Standard function. */
495 _bfd_vms_lib_archive_p (bfd
*abfd
, enum vms_lib_kind kind
)
499 unsigned int majorid
;
500 struct lib_tdata
*tdata_hold
;
501 struct lib_tdata
*tdata
;
503 unsigned int nbr_ent
;
506 if (bfd_bread (&lhd
, sizeof (lhd
), abfd
) != sizeof (lhd
))
508 if (bfd_get_error () != bfd_error_system_call
)
509 bfd_set_error (bfd_error_wrong_format
);
513 /* Check sanity (= magic) number. */
514 sanity
= bfd_getl32 (lhd
.sanity
);
515 if (!(sanity
== LHD_SANEID3
516 || sanity
== LHD_SANEID6
517 || sanity
== LHD_SANEID_DCX
))
519 bfd_set_error (bfd_error_wrong_format
);
522 majorid
= bfd_getl32 (lhd
.majorid
);
524 /* Check archive kind. */
528 if ((lhd
.type
!= LBR__C_TYP_EOBJ
&& lhd
.type
!= LBR__C_TYP_ESHSTB
)
529 || majorid
!= LBR_MAJORID
532 bfd_set_error (bfd_error_wrong_format
);
537 if ((lhd
.type
!= LBR__C_TYP_IOBJ
&& lhd
.type
!= LBR__C_TYP_ISHSTB
)
538 || majorid
!= LBR_ELFMAJORID
541 bfd_set_error (bfd_error_wrong_format
);
546 if ((lhd
.type
!= LBR__C_TYP_TXT
547 && lhd
.type
!= LBR__C_TYP_MLB
548 && lhd
.type
!= LBR__C_TYP_HLP
)
549 || majorid
!= LBR_MAJORID
552 bfd_set_error (bfd_error_wrong_format
);
560 /* Allocate and initialize private data. */
561 tdata_hold
= bfd_libdata (abfd
);
562 tdata
= (struct lib_tdata
*) bfd_zalloc (abfd
, sizeof (struct lib_tdata
));
565 abfd
->tdata
.any
= (void *)tdata
;
566 tdata
->ver
= majorid
;
567 tdata
->mhd_size
= MHD__C_USRDAT
+ lhd
.mhdusz
;
568 tdata
->type
= lhd
.type
;
570 tdata
->credat_lo
= bfd_getl32 (lhd
.credat
+ 0);
571 tdata
->credat_hi
= bfd_getl32 (lhd
.credat
+ 4);
574 tdata
->nbr_modules
= bfd_getl32 (lhd
.modcnt
);
575 tdata
->artdata
.symdef_count
= bfd_getl32 (lhd
.idxcnt
) - tdata
->nbr_modules
;
576 nbr_ent
= tdata
->nbr_modules
;
577 tdata
->modules
= vms_lib_read_index (abfd
, 0, &nbr_ent
);
578 if (tdata
->modules
== NULL
|| nbr_ent
!= tdata
->nbr_modules
)
582 nbr_ent
= tdata
->artdata
.symdef_count
;
583 tdata
->artdata
.symdefs
= vms_lib_read_index (abfd
, 1, &nbr_ent
);
584 if (tdata
->artdata
.symdefs
== NULL
)
586 /* Only IA64 archives may have more entries in the index that what
588 if (nbr_ent
!= tdata
->artdata
.symdef_count
589 && kind
!= vms_lib_ia64
)
591 tdata
->artdata
.symdef_count
= nbr_ent
;
593 tdata
->cache
= bfd_zalloc (abfd
, sizeof (bfd
*) * tdata
->nbr_modules
);
594 if (tdata
->cache
== NULL
)
597 /* Read DCX submaps. */
598 dcxvbn
= bfd_getl32 (lhd
.dcxmapvbn
);
601 unsigned char buf_reclen
[4];
604 struct vms_dcxmap
*map
;
605 unsigned int sbm_off
;
608 if (bfd_seek (abfd
, (dcxvbn
- 1) * VMS_BLOCK_SIZE
, SEEK_SET
) != 0
609 || bfd_bread (buf_reclen
, sizeof (buf_reclen
), abfd
)
610 != sizeof (buf_reclen
))
612 reclen
= bfd_getl32 (buf_reclen
);
613 if (reclen
< sizeof (struct vms_dcxmap
))
615 buf
= _bfd_malloc_and_read (abfd
, reclen
, reclen
);
618 map
= (struct vms_dcxmap
*)buf
;
619 tdata
->nbr_dcxsbm
= bfd_getl16 (map
->nsubs
);
620 sbm_off
= bfd_getl16 (map
->sub0
);
621 tdata
->dcxsbm
= (struct dcxsbm_desc
*)bfd_alloc
622 (abfd
, tdata
->nbr_dcxsbm
* sizeof (struct dcxsbm_desc
));
623 for (i
= 0; i
< tdata
->nbr_dcxsbm
; i
++)
625 struct vms_dcxsbm
*sbm
;
626 struct dcxsbm_desc
*sbmdesc
= &tdata
->dcxsbm
[i
];
627 unsigned int sbm_len
;
634 || reclen
- sbm_off
< sizeof (struct vms_dcxsbm
))
640 sbm
= (struct vms_dcxsbm
*) (buf
+ sbm_off
);
641 sbm_sz
= bfd_getl16 (sbm
->size
);
643 if (sbm_off
> reclen
)
646 sbmdesc
->min_char
= sbm
->min_char
;
647 BFD_ASSERT (sbmdesc
->min_char
== 0);
648 sbmdesc
->max_char
= sbm
->max_char
;
649 sbm_len
= sbmdesc
->max_char
- sbmdesc
->min_char
+ 1;
650 l
= (2 * sbm_len
+ 7) / 8;
651 if (sbm_sz
< sizeof (struct vms_dcxsbm
) + l
+ sbm_len
652 || (tdata
->nbr_dcxsbm
> 1
653 && sbm_sz
< sizeof (struct vms_dcxsbm
) + l
+ 3 * sbm_len
))
655 sbmdesc
->flags
= (unsigned char *)bfd_alloc (abfd
, l
);
656 off
= bfd_getl16 (sbm
->flags
);
660 memcpy (sbmdesc
->flags
, (bfd_byte
*) sbm
+ off
, l
);
661 sbmdesc
->nodes
= (unsigned char *)bfd_alloc (abfd
, 2 * sbm_len
);
662 off
= bfd_getl16 (sbm
->nodes
);
664 || sbm_sz
- off
< 2 * sbm_len
)
666 memcpy (sbmdesc
->nodes
, (bfd_byte
*) sbm
+ off
, 2 * sbm_len
);
667 off
= bfd_getl16 (sbm
->next
);
671 || sbm_sz
- off
< 2 * sbm_len
)
673 /* Read the 'next' array. */
674 sbmdesc
->next
= (unsigned short *) bfd_alloc (abfd
, 2 * sbm_len
);
675 buf1
= (bfd_byte
*) sbm
+ off
;
676 for (j
= 0; j
< sbm_len
; j
++)
677 sbmdesc
->next
[j
] = bfd_getl16 (buf1
+ j
* 2);
681 /* There is no next array if there is only one submap. */
682 BFD_ASSERT (tdata
->nbr_dcxsbm
== 1);
683 sbmdesc
->next
= NULL
;
690 tdata
->nbr_dcxsbm
= 0;
693 /* The map is always present. Also mark shared image library. */
694 abfd
->has_armap
= true;
695 if (tdata
->type
== LBR__C_TYP_ESHSTB
|| tdata
->type
== LBR__C_TYP_ISHSTB
)
696 abfd
->is_thin_archive
= true;
698 return _bfd_no_cleanup
;
701 bfd_release (abfd
, tdata
);
702 abfd
->tdata
.any
= (void *)tdata_hold
;
706 /* Standard function for alpha libraries. */
709 _bfd_vms_lib_alpha_archive_p (bfd
*abfd
)
711 return _bfd_vms_lib_archive_p (abfd
, vms_lib_alpha
);
714 /* Standard function for ia64 libraries. */
717 _bfd_vms_lib_ia64_archive_p (bfd
*abfd
)
719 return _bfd_vms_lib_archive_p (abfd
, vms_lib_ia64
);
722 /* Standard function for text libraries. */
725 _bfd_vms_lib_txt_archive_p (bfd
*abfd
)
727 return _bfd_vms_lib_archive_p (abfd
, vms_lib_txt
);
730 /* Standard bfd function. */
733 _bfd_vms_lib_mkarchive (bfd
*abfd
, enum vms_lib_kind kind
)
735 struct lib_tdata
*tdata
;
737 tdata
= (struct lib_tdata
*) bfd_zalloc (abfd
, sizeof (struct lib_tdata
));
741 abfd
->tdata
.any
= (void *)tdata
;
742 vms_get_time (&tdata
->credat_hi
, &tdata
->credat_lo
);
748 tdata
->ver
= LBR_MAJORID
;
749 tdata
->mhd_size
= offsetof (struct vms_mhd
, pad1
);
750 tdata
->type
= LBR__C_TYP_EOBJ
;
753 tdata
->ver
= LBR_ELFMAJORID
;
754 tdata
->mhd_size
= sizeof (struct vms_mhd
);
755 tdata
->type
= LBR__C_TYP_IOBJ
;
761 tdata
->nbr_modules
= 0;
762 tdata
->artdata
.symdef_count
= 0;
763 tdata
->modules
= NULL
;
764 tdata
->artdata
.symdefs
= NULL
;
771 _bfd_vms_lib_alpha_mkarchive (bfd
*abfd
)
773 return _bfd_vms_lib_mkarchive (abfd
, vms_lib_alpha
);
777 _bfd_vms_lib_ia64_mkarchive (bfd
*abfd
)
779 return _bfd_vms_lib_mkarchive (abfd
, vms_lib_ia64
);
782 /* Find NAME in the symbol index. Return the index. */
785 _bfd_vms_lib_find_symbol (bfd
*abfd
, const char *name
)
787 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
788 carsym
*syms
= tdata
->artdata
.symdefs
;
791 /* Open-coded binary search for speed. */
793 hi
= tdata
->artdata
.symdef_count
- 1;
797 int mid
= lo
+ (hi
- lo
) / 2;
800 diff
= (char)(name
[0] - syms
[mid
].name
[0]);
802 diff
= strcmp (name
, syms
[mid
].name
);
810 return BFD_NO_MORE_SYMBOLS
;
813 /* IO vector for archive member. Need that because members are not linearly
814 stored in archives. */
818 /* Current offset. */
821 /* Length of the module, when known. */
824 /* Current position in the record from bfd_bread point of view (ie, after
825 decompression). 0 means that no data byte have been read, -2 and -1
826 are reserved for the length word. */
828 #define REC_POS_NL -4
829 #define REC_POS_PAD -3
830 #define REC_POS_LEN0 -2
831 #define REC_POS_LEN1 -1
834 unsigned short rec_len
;
835 /* Number of bytes to read in the current record. */
836 unsigned short rec_rem
;
837 /* Offset of the next block. */
839 /* Current *data* offset in the data block. */
840 unsigned short blk_off
;
842 /* Offset of the first block. Extracted from the index. */
843 file_ptr first_block
;
845 /* Initial next_block. Extracted when the MHD is read. */
846 file_ptr init_next_block
;
847 /* Initial blk_off, once the MHD is read. */
848 unsigned short init_blk_off
;
850 /* Used to store any 3 byte record, which could be the EOF pattern. */
851 unsigned char pattern
[4];
854 struct dcxsbm_desc
*dcxsbms
;
855 /* Current submap. */
856 struct dcxsbm_desc
*dcx_sbm
;
857 /* Current offset in the submap. */
858 unsigned int dcx_offset
;
861 /* Compressed buffer. */
862 unsigned char *dcx_buf
;
863 /* Size of the buffer. Used to resize. */
864 unsigned int dcx_max
;
865 /* Number of valid bytes in the buffer. */
866 unsigned int dcx_rlen
;
869 /* Return the current position. */
872 vms_lib_btell (struct bfd
*abfd
)
874 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
878 /* Read the header of the next data block if all bytes of the current block
882 vms_lib_read_block (struct bfd
*abfd
)
884 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
886 if (vec
->blk_off
== DATA__LENGTH
)
888 unsigned char hdr
[DATA__DATA
];
890 /* Read next block. */
891 if (bfd_seek (abfd
->my_archive
, vec
->next_block
, SEEK_SET
) != 0)
893 if (bfd_bread (hdr
, sizeof (hdr
), abfd
->my_archive
) != sizeof (hdr
))
895 vec
->next_block
= (bfd_getl32 (hdr
+ 2) - 1) * VMS_BLOCK_SIZE
;
896 vec
->blk_off
= sizeof (hdr
);
901 /* Read NBYTES from ABFD into BUF if not NULL. If BUF is NULL, bytes are
902 not stored. Read linearly from the library, but handle blocks. This
903 function does not handle records nor EOF. */
906 vms_lib_bread_raw (struct bfd
*abfd
, unsigned char *buf
, file_ptr nbytes
)
908 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
916 /* Be sure the current data block is read. */
917 if (!vms_lib_read_block (abfd
))
920 /* Do not read past the data block, do not read more than requested. */
921 l
= DATA__LENGTH
- vec
->blk_off
;
928 /* Really read into BUF. */
929 if (bfd_bread (buf
, l
, abfd
->my_archive
) != l
)
934 /* Make as if we are reading. */
935 if (bfd_seek (abfd
->my_archive
, l
, SEEK_CUR
) != 0)
948 /* Decompress NBYTES from VEC. Store the bytes into BUF if not NULL. */
951 vms_lib_dcx (struct vms_lib_iovec
*vec
, unsigned char *buf
, file_ptr nbytes
)
953 struct dcxsbm_desc
*sbm
;
959 /* The loop below expect to deliver at least one byte. */
963 /* Get the current state. */
965 offset
= vec
->dcx_offset
;
966 j
= vec
->dcx_pos
& 7;
968 for (i
= vec
->dcx_pos
>> 3; i
< vec
->dcx_rlen
; i
++)
970 unsigned char b
= vec
->dcx_buf
[i
];
976 if (!(sbm
->flags
[offset
>> 3] & (1 << (offset
& 7))))
978 unsigned int n_offset
= sbm
->nodes
[offset
];
981 /* End of buffer. Stay where we are. */
982 vec
->dcx_pos
= (i
<< 3) + j
;
985 vec
->dcx_offset
= offset
;
989 offset
= 2 * n_offset
;
993 unsigned char v
= sbm
->nodes
[offset
];
995 if (sbm
->next
!= NULL
)
996 sbm
= vec
->dcxsbms
+ sbm
->next
[v
];
1007 vec
->dcx_pos
= (i
<< 3) + j
+ 1;
1008 vec
->dcx_offset
= offset
;
1021 /* Standard IOVEC function. */
1024 vms_lib_bread (struct bfd
*abfd
, void *vbuf
, file_ptr nbytes
)
1026 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1029 unsigned char *buf
= (unsigned char *)vbuf
;
1031 /* Do not read past the end. */
1032 if (vec
->where
>= vec
->file_len
)
1038 if (vec
->rec_rem
== 0)
1040 unsigned char blen
[2];
1042 /* Read record length. */
1043 if (vms_lib_bread_raw (abfd
, blen
, sizeof (blen
)) != sizeof (blen
))
1045 vec
->rec_len
= bfd_getl16 (blen
);
1046 if (bfd_libdata (abfd
->my_archive
)->kind
== vms_lib_txt
)
1048 /* Discard record size and align byte. */
1050 vec
->rec_rem
= vec
->rec_len
;
1054 /* Prepend record size. */
1055 vec
->rec_pos
= REC_POS_LEN0
;
1056 vec
->rec_rem
= (vec
->rec_len
+ 1) & ~1; /* With align byte. */
1058 if (vec
->rec_len
== 3)
1060 /* Possibly end of file. Check the pattern. */
1061 if (vms_lib_bread_raw (abfd
, vec
->pattern
, 4) != 4)
1063 if (!memcmp (vec
->pattern
, eotdesc
+ 2, 3))
1065 /* This is really an EOF. */
1067 vec
->file_len
= vec
->where
;
1072 if (vec
->dcxsbms
!= NULL
)
1074 /* This is a compressed member. */
1078 /* Be sure there is enough room for the expansion. */
1079 len
= (vec
->rec_len
+ 1) & ~1;
1080 if (len
> vec
->dcx_max
)
1082 while (len
> vec
->dcx_max
)
1084 vec
->dcx_buf
= bfd_alloc (abfd
, vec
->dcx_max
);
1085 if (vec
->dcx_buf
== NULL
)
1089 /* Read the compressed record. */
1090 vec
->dcx_rlen
= len
;
1091 if (vec
->rec_len
== 3)
1094 memcpy (vec
->dcx_buf
, vec
->pattern
, 3);
1098 elen
= vms_lib_bread_raw (abfd
, vec
->dcx_buf
, len
);
1103 /* Dummy expansion to get the expanded length. */
1104 vec
->dcx_offset
= 0;
1105 vec
->dcx_sbm
= vec
->dcxsbms
;
1107 elen
= vms_lib_dcx (vec
, NULL
, 0x10000);
1110 vec
->rec_len
= elen
;
1111 vec
->rec_rem
= elen
;
1113 /* Reset the state. */
1114 vec
->dcx_offset
= 0;
1115 vec
->dcx_sbm
= vec
->dcxsbms
;
1119 if (vec
->rec_pos
< 0)
1122 switch (vec
->rec_pos
)
1125 c
= vec
->rec_len
& 0xff;
1126 vec
->rec_pos
= REC_POS_LEN1
;
1129 c
= (vec
->rec_len
>> 8) & 0xff;
1153 if (nbytes
> vec
->rec_rem
)
1154 chunk
= vec
->rec_rem
;
1158 if (vec
->dcxsbms
!= NULL
)
1160 /* Optimize the stat() case: no need to decompress again as we
1162 if (!(buf
== NULL
&& chunk
== vec
->rec_rem
))
1163 chunk
= vms_lib_dcx (vec
, buf
, chunk
);
1167 if (vec
->rec_len
== 3)
1170 memcpy (buf
, vec
->pattern
+ vec
->rec_pos
, chunk
);
1173 chunk
= vms_lib_bread_raw (abfd
, buf
, chunk
);
1181 vec
->rec_pos
+= chunk
;
1182 vec
->rec_rem
-= chunk
;
1184 if (vec
->rec_rem
== 0)
1186 /* End of record reached. */
1187 if (bfd_libdata (abfd
->my_archive
)->kind
== vms_lib_txt
)
1189 if ((vec
->rec_len
& 1) == 1
1190 && vec
->rec_len
!= 3
1191 && vec
->dcxsbms
== NULL
)
1193 /* Eat the pad byte. */
1195 if (vms_lib_bread_raw (abfd
, &pad
, 1) != 1)
1198 vec
->rec_pos
= REC_POS_NL
;
1203 if ((vec
->rec_len
& 1) == 1 && vec
->dcxsbms
!= NULL
)
1205 vec
->rec_pos
= REC_POS_PAD
;
1215 /* Standard function, but we currently only handle the rewind case. */
1218 vms_lib_bseek (struct bfd
*abfd
, file_ptr offset
, int whence
)
1220 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1222 if (whence
== SEEK_SET
&& offset
== 0)
1227 vec
->blk_off
= vec
->init_blk_off
;
1228 vec
->next_block
= vec
->init_next_block
;
1230 if (bfd_seek (abfd
->my_archive
, vec
->first_block
, SEEK_SET
) != 0)
1239 vms_lib_bwrite (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1240 const void *where ATTRIBUTE_UNUSED
,
1241 file_ptr nbytes ATTRIBUTE_UNUSED
)
1247 vms_lib_bclose (struct bfd
*abfd
)
1249 abfd
->iostream
= NULL
;
1254 vms_lib_bflush (struct bfd
*abfd ATTRIBUTE_UNUSED
)
1260 vms_lib_bstat (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1261 struct stat
*sb ATTRIBUTE_UNUSED
)
1263 /* Not supported. */
1268 vms_lib_bmmap (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1269 void *addr ATTRIBUTE_UNUSED
,
1270 bfd_size_type len ATTRIBUTE_UNUSED
,
1271 int prot ATTRIBUTE_UNUSED
,
1272 int flags ATTRIBUTE_UNUSED
,
1273 file_ptr offset ATTRIBUTE_UNUSED
,
1274 void **map_addr ATTRIBUTE_UNUSED
,
1275 bfd_size_type
*map_len ATTRIBUTE_UNUSED
)
1280 static const struct bfd_iovec vms_lib_iovec
= {
1281 &vms_lib_bread
, &vms_lib_bwrite
, &vms_lib_btell
, &vms_lib_bseek
,
1282 &vms_lib_bclose
, &vms_lib_bflush
, &vms_lib_bstat
, &vms_lib_bmmap
1285 /* Open a library module. FILEPOS is the position of the module header. */
1288 vms_lib_bopen (bfd
*el
, file_ptr filepos
)
1290 struct vms_lib_iovec
*vec
;
1291 unsigned char buf
[256];
1292 struct vms_mhd
*mhd
;
1293 struct lib_tdata
*tdata
= bfd_libdata (el
->my_archive
);
1296 /* Allocate and initialized the iovec. */
1297 vec
= bfd_zalloc (el
, sizeof (*vec
));
1302 el
->iovec
= &vms_lib_iovec
;
1304 /* File length is not known. */
1307 /* Read the first data block. */
1308 vec
->next_block
= filepos
& ~(VMS_BLOCK_SIZE
- 1);
1309 vec
->blk_off
= DATA__LENGTH
;
1310 if (!vms_lib_read_block (el
))
1313 /* Prepare to read the first record. */
1314 vec
->blk_off
= filepos
& (VMS_BLOCK_SIZE
- 1);
1316 if (bfd_seek (el
->my_archive
, filepos
, SEEK_SET
) != 0)
1319 /* Read Record length + MHD + align byte. */
1320 len
= tdata
->mhd_size
;
1321 if (vms_lib_bread_raw (el
, buf
, 2) != 2)
1323 if (bfd_getl16 (buf
) != len
)
1325 len
= (len
+ 1) & ~1;
1326 BFD_ASSERT (len
<= sizeof (buf
));
1327 if (vms_lib_bread_raw (el
, buf
, len
) != len
)
1330 /* Get info from mhd. */
1331 mhd
= (struct vms_mhd
*)buf
;
1333 if (mhd
->id
!= MHD__C_MHDID
)
1335 if (len
>= MHD__C_MHDLEN
+ 1)
1336 el
->selective_search
= (mhd
->objstat
& MHD__M_SELSRC
) ? 1 : 0;
1337 el
->mtime
= vms_rawtime_to_time_t (mhd
->datim
);
1338 el
->mtime_set
= true;
1340 /* Reinit the iovec so that seek() will point to the first record after
1343 vec
->init_blk_off
= vec
->blk_off
;
1344 vec
->init_next_block
= vec
->next_block
;
1345 vec
->first_block
= bfd_tell (el
->my_archive
);
1346 vec
->dcxsbms
= bfd_libdata (el
->my_archive
)->dcxsbm
;
1348 if (vec
->dcxsbms
!= NULL
)
1351 vec
->dcx_max
= 10 * 1024;
1352 vec
->dcx_buf
= bfd_alloc (el
, vec
->dcx_max
);
1354 if (vec
->dcx_buf
== NULL
)
1360 /* Get member MODIDX. Return NULL in case of error. */
1363 _bfd_vms_lib_get_module (bfd
*abfd
, unsigned int modidx
)
1365 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
1373 if (modidx
>= tdata
->nbr_modules
)
1376 /* Already loaded. */
1377 if (tdata
->cache
[modidx
])
1378 return tdata
->cache
[modidx
];
1381 file_off
= tdata
->modules
[modidx
].file_offset
;
1382 if (tdata
->type
!= LBR__C_TYP_IOBJ
)
1384 res
= _bfd_create_empty_archive_element_shell (abfd
);
1388 /* Special reader to deal with data blocks. */
1389 if (!vms_lib_bopen (res
, file_off
))
1395 struct vms_mhd
*mhd
;
1396 struct areltdata
*arelt
;
1398 /* Sanity check. The MHD must be big enough to contain module size. */
1399 if (tdata
->mhd_size
< offsetof (struct vms_mhd
, modsize
) + 4)
1402 /* Read the MHD now. */
1403 if (bfd_seek (abfd
, file_off
, SEEK_SET
) != 0)
1405 if (bfd_bread (buf
, tdata
->mhd_size
, abfd
) != tdata
->mhd_size
)
1408 mhd
= (struct vms_mhd
*) buf
;
1409 if (mhd
->id
!= MHD__C_MHDID
)
1412 res
= _bfd_create_empty_archive_element_shell (abfd
);
1415 arelt
= bfd_zmalloc (sizeof (*arelt
));
1421 res
->arelt_data
= arelt
;
1423 /* Get info from mhd. */
1424 if (tdata
->mhd_size
>= offsetof (struct vms_mhd
, objstat
) + 1)
1425 res
->selective_search
= (mhd
->objstat
& MHD__M_SELSRC
) ? 1 : 0;
1426 res
->mtime
= vms_rawtime_to_time_t (mhd
->datim
);
1427 res
->mtime_set
= true;
1429 arelt
->parsed_size
= bfd_getl32 (mhd
->modsize
);
1431 /* No need for a special reader as members are stored linearly.
1432 Just skip the MHD. */
1433 res
->origin
= file_off
+ tdata
->mhd_size
;
1437 name
= tdata
->modules
[modidx
].name
;
1438 namelen
= strlen (name
);
1439 newname
= bfd_malloc (namelen
+ 4 + 1);
1440 if (newname
== NULL
)
1445 strcpy (newname
, name
);
1446 switch (tdata
->type
)
1448 case LBR__C_TYP_IOBJ
:
1449 case LBR__C_TYP_EOBJ
:
1450 /* For object archives, append .obj to mimic standard behaviour. */
1451 strcpy (newname
+ namelen
, ".obj");
1456 bfd_set_filename (res
, newname
);
1458 if (bfd_get_filename (res
) == NULL
)
1464 tdata
->cache
[modidx
] = res
;
1469 /* Standard function: get member at IDX. */
1472 _bfd_vms_lib_get_elt_at_index (bfd
*abfd
, symindex symidx
)
1474 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
1476 unsigned int modidx
;
1479 if (symidx
> tdata
->artdata
.symdef_count
)
1481 file_off
= tdata
->artdata
.symdefs
[symidx
].file_offset
;
1484 for (modidx
= 0; modidx
< tdata
->nbr_modules
; modidx
++)
1486 if (tdata
->modules
[modidx
].file_offset
== file_off
)
1489 if (modidx
>= tdata
->nbr_modules
)
1492 return _bfd_vms_lib_get_module (abfd
, modidx
);
1495 /* Elements of an imagelib are stubs. You can get the real image with this
1499 _bfd_vms_lib_get_imagelib_file (bfd
*el
)
1501 bfd
*archive
= el
->my_archive
;
1502 const char *modname
= bfd_get_filename (el
);
1503 int modlen
= strlen (modname
);
1508 /* Convert module name to lower case and append '.exe'. */
1509 filename
= bfd_alloc (el
, modlen
+ 5);
1510 if (filename
== NULL
)
1512 for (j
= 0; j
< modlen
; j
++)
1513 if (ISALPHA (modname
[j
]))
1514 filename
[j
] = TOLOWER (modname
[j
]);
1516 filename
[j
] = modname
[j
];
1517 memcpy (filename
+ modlen
, ".exe", 5);
1519 filename
= _bfd_append_relative_path (archive
, filename
);
1520 if (filename
== NULL
)
1522 res
= bfd_openr (filename
, NULL
);
1526 /* xgettext:c-format */
1527 _bfd_error_handler(_("could not open shared image '%s' from '%s'"),
1528 filename
, bfd_get_filename (archive
));
1529 bfd_release (archive
, filename
);
1533 /* FIXME: put it in a cache ? */
1537 /* Standard function. */
1540 _bfd_vms_lib_openr_next_archived_file (bfd
*archive
,
1549 idx
= last_file
->proxy_origin
+ 1;
1551 if (idx
>= bfd_libdata (archive
)->nbr_modules
)
1553 bfd_set_error (bfd_error_no_more_archived_files
);
1557 res
= _bfd_vms_lib_get_module (archive
, idx
);
1560 res
->proxy_origin
= idx
;
1564 /* Standard function. Just compute the length. */
1567 _bfd_vms_lib_generic_stat_arch_elt (bfd
*abfd
, struct stat
*st
)
1569 struct lib_tdata
*tdata
;
1572 if (abfd
->my_archive
== NULL
)
1574 bfd_set_error (bfd_error_invalid_operation
);
1578 tdata
= bfd_libdata (abfd
->my_archive
);
1579 if (tdata
->type
!= LBR__C_TYP_IOBJ
)
1581 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1583 if (vec
->file_len
== (ufile_ptr
)-1)
1585 if (vms_lib_bseek (abfd
, 0, SEEK_SET
) != 0)
1588 /* Compute length. */
1589 while (vms_lib_bread (abfd
, NULL
, 1 << 20) > 0)
1592 st
->st_size
= vec
->file_len
;
1596 st
->st_size
= ((struct areltdata
*)abfd
->arelt_data
)->parsed_size
;
1599 if (abfd
->mtime_set
)
1600 st
->st_mtime
= abfd
->mtime
;
1610 /* Internal representation of an index entry. */
1614 /* Corresponding archive member. */
1617 /* Number of reference to this entry. */
1620 /* Length of the key. */
1621 unsigned short namlen
;
1627 /* Used to sort index entries. */
1630 lib_index_cmp (const void *lv
, const void *rv
)
1632 const struct lib_index
*l
= lv
;
1633 const struct lib_index
*r
= rv
;
1635 return strcmp (l
->name
, r
->name
);
1638 /* Maximum number of index blocks level. */
1640 #define MAX_LEVEL 10
1642 /* Get the size of an index entry. */
1645 get_idxlen (struct lib_index
*idx
, bool is_elfidx
)
1649 /* 9 is the size of struct vms_elfidx without keyname. */
1650 if (idx
->namlen
> MAX_KEYLEN
)
1651 return 9 + sizeof (struct vms_kbn
);
1653 return 9 + idx
->namlen
;
1657 /* 7 is the size of struct vms_idx without keyname. */
1658 return 7 + idx
->namlen
;
1662 /* Write the index composed by NBR symbols contained in IDX.
1663 VBN is the first vbn to be used, and will contain on return the last vbn.
1664 Can be called with ABFD set to NULL just to size the index.
1665 If not null, TOPVBN will be assigned to the vbn of the root index tree.
1666 IS_ELFIDX is true for elfidx (ie ia64) indexes layout.
1667 Return TRUE on success. */
1670 vms_write_index (bfd
*abfd
,
1671 struct lib_index
*idx
, unsigned int nbr
, unsigned int *vbn
,
1672 unsigned int *topvbn
, bool is_elfidx
)
1674 /* The index is organized as a tree. This function implements a naive
1675 algorithm to balance the tree: it fills the leaves, and create a new
1676 branch when all upper leaves and branches are full. We only keep in
1677 memory a path to the current leaf. */
1681 /* Disk blocks for the current path. */
1682 struct vms_indexdef
*rblk
[MAX_LEVEL
];
1683 /* Info on the current blocks. */
1686 unsigned int vbn
; /* VBN of the block. */
1687 /* The last entry is identified so that it could be copied to the
1689 unsigned short len
; /* Length up to the last entry. */
1690 unsigned short lastlen
; /* Length of the last entry. */
1693 /* The kbn blocks are used to store long symbol names. */
1694 unsigned int kbn_sz
= 0; /* Number of bytes available in the kbn block. */
1695 unsigned int kbn_vbn
= 0; /* VBN of the kbn block. */
1696 unsigned char *kbn_blk
= NULL
; /* Contents of the kbn block. */
1700 /* No entries. Very easy to handle. */
1708 /* Sort the index the first time this function is called. */
1709 qsort (idx
, nbr
, sizeof (struct lib_index
), lib_index_cmp
);
1712 /* Allocate first index block. */
1715 rblk
[0] = bfd_zmalloc (sizeof (struct vms_indexdef
));
1716 blk
[0].vbn
= (*vbn
)++;
1720 for (i
= 0; i
< nbr
; i
++, idx
++)
1722 unsigned int idxlen
;
1724 unsigned int key_vbn
= 0;
1725 unsigned int key_off
= 0;
1727 idxlen
= get_idxlen (idx
, is_elfidx
);
1729 if (is_elfidx
&& idx
->namlen
> MAX_KEYLEN
)
1731 /* If the key (ie name) is too long, write it in the kbn block. */
1732 unsigned int kl
= idx
->namlen
;
1733 unsigned int kl_chunk
;
1734 const char *key
= idx
->name
;
1736 /* Write the key in the kbn, chunk after chunk. */
1739 if (kbn_sz
< sizeof (struct vms_kbn
))
1741 /* Not enough room in the kbn block. */
1744 /* Write it to the disk (if there is one). */
1747 if (!vms_write_block (abfd
, kbn_vbn
, kbn_blk
))
1752 kbn_blk
= bfd_malloc (VMS_BLOCK_SIZE
);
1753 if (kbn_blk
== NULL
)
1756 *(unsigned short *)kbn_blk
= 0;
1758 /* Allocate a new block for the keys. */
1760 kbn_sz
= VMS_BLOCK_SIZE
- 2;
1762 /* Size of the chunk written to the current key block. */
1763 if (kl
+ sizeof (struct vms_kbn
) > kbn_sz
)
1764 kl_chunk
= kbn_sz
- sizeof (struct vms_kbn
);
1768 if (kbn_blk
!= NULL
)
1770 struct vms_kbn
*kbn
;
1772 kbn
= (struct vms_kbn
*)(kbn_blk
+ VMS_BLOCK_SIZE
- kbn_sz
);
1776 /* Save the rfa of the first chunk. */
1778 key_off
= VMS_BLOCK_SIZE
- kbn_sz
;
1781 bfd_putl16 (kl_chunk
, kbn
->keylen
);
1784 /* No next chunk. */
1785 bfd_putl32 (0, kbn
->rfa
.vbn
);
1786 bfd_putl16 (0, kbn
->rfa
.offset
);
1790 /* Next chunk will be at the start of the next block. */
1791 bfd_putl32 (*vbn
, kbn
->rfa
.vbn
);
1792 bfd_putl16 (2, kbn
->rfa
.offset
);
1794 memcpy ((char *)(kbn
+ 1), key
, kl_chunk
);
1798 kl_chunk
= (kl_chunk
+ 1) & ~1; /* Always align. */
1799 kbn_sz
-= kl_chunk
+ sizeof (struct vms_kbn
);
1804 /* Check if a block might overflow. In this case we will flush this
1805 block and all the blocks below it. */
1806 for (j
= 0; j
< level
; j
++)
1807 if (blk
[j
].len
+ blk
[j
].lastlen
+ idxlen
> INDEXDEF__BLKSIZ
)
1810 for (j
= 0; j
< level
; j
++)
1814 /* There is not enough room to write the new entry in this
1815 block or in a parent block. */
1819 BFD_ASSERT (level
< MAX_LEVEL
);
1821 /* Need to create a parent. */
1824 rblk
[level
] = bfd_zmalloc (sizeof (struct vms_indexdef
));
1825 bfd_putl32 (*vbn
, rblk
[j
]->parent
);
1827 blk
[level
].vbn
= (*vbn
)++;
1829 blk
[level
].lastlen
= blk
[j
].lastlen
;
1834 /* Update parent block: write the last entry from the current
1838 struct vms_rfa
*rfa
;
1840 /* Pointer to the last entry in parent block. */
1841 rfa
= (struct vms_rfa
*)(rblk
[j
+ 1]->keys
+ blk
[j
+ 1].len
);
1843 /* Copy the whole entry. */
1844 BFD_ASSERT (blk
[j
+ 1].lastlen
== blk
[j
].lastlen
);
1845 memcpy (rfa
, rblk
[j
]->keys
+ blk
[j
].len
, blk
[j
].lastlen
);
1846 /* Fix the entry (which in always the first field of an
1848 bfd_putl32 (blk
[j
].vbn
, rfa
->vbn
);
1849 bfd_putl16 (RFADEF__C_INDEX
, rfa
->offset
);
1854 /* And allocate it. Do it only on the block that won't be
1855 flushed (so that the parent of the parent can be
1857 blk
[j
+ 1].len
+= blk
[j
+ 1].lastlen
;
1858 blk
[j
+ 1].lastlen
= 0;
1861 /* Write this block on the disk. */
1864 bfd_putl16 (blk
[j
].len
+ blk
[j
].lastlen
, rblk
[j
]->used
);
1865 if (!vms_write_block (abfd
, blk
[j
].vbn
, rblk
[j
]))
1869 /* Reset this block. */
1872 blk
[j
].vbn
= (*vbn
)++;
1875 /* Append it to the block. */
1878 /* Keep the previous last entry. */
1879 blk
[j
].len
+= blk
[j
].lastlen
;
1883 struct vms_rfa
*rfa
;
1885 rfa
= (struct vms_rfa
*)(rblk
[j
]->keys
+ blk
[j
].len
);
1886 bfd_putl32 ((idx
->abfd
->proxy_origin
/ VMS_BLOCK_SIZE
) + 1,
1889 ((idx
->abfd
->proxy_origin
% VMS_BLOCK_SIZE
)
1890 + (is_elfidx
? 0 : DATA__DATA
),
1895 /* Use elfidx format. */
1896 struct vms_elfidx
*en
= (struct vms_elfidx
*)rfa
;
1901 /* Long symbol name. */
1902 struct vms_kbn
*k
= (struct vms_kbn
*)(en
->keyname
);
1903 bfd_putl16 (sizeof (struct vms_kbn
), en
->keylen
);
1904 bfd_putl16 (idx
->namlen
, k
->keylen
);
1905 bfd_putl32 (key_vbn
, k
->rfa
.vbn
);
1906 bfd_putl16 (key_off
, k
->rfa
.offset
);
1907 en
->flags
|= ELFIDX__SYMESC
;
1911 bfd_putl16 (idx
->namlen
, en
->keylen
);
1912 memcpy (en
->keyname
, idx
->name
, idx
->namlen
);
1917 /* Use idx format. */
1918 struct vms_idx
*en
= (struct vms_idx
*)rfa
;
1919 en
->keylen
= idx
->namlen
;
1920 memcpy (en
->keyname
, idx
->name
, idx
->namlen
);
1924 /* The last added key can now be the last one all blocks in the
1926 blk
[j
].lastlen
= idxlen
;
1930 /* Save VBN of the root. */
1932 *topvbn
= blk
[level
- 1].vbn
;
1938 for (j
= 1; j
< level
; j
++)
1940 /* Update parent block: write the new entry. */
1943 struct vms_rfa
*rfa
;
1945 en
= rblk
[j
- 1]->keys
+ blk
[j
- 1].len
;
1946 par
= rblk
[j
]->keys
+ blk
[j
].len
;
1947 BFD_ASSERT (blk
[j
].lastlen
== blk
[j
- 1].lastlen
);
1948 memcpy (par
, en
, blk
[j
- 1].lastlen
);
1949 rfa
= (struct vms_rfa
*)par
;
1950 bfd_putl32 (blk
[j
- 1].vbn
, rfa
->vbn
);
1951 bfd_putl16 (RFADEF__C_INDEX
, rfa
->offset
);
1954 for (j
= 0; j
< level
; j
++)
1956 /* Write this block on the disk. */
1957 bfd_putl16 (blk
[j
].len
+ blk
[j
].lastlen
, rblk
[j
]->used
);
1958 if (!vms_write_block (abfd
, blk
[j
].vbn
, rblk
[j
]))
1964 /* Write the last kbn (if any). */
1967 if (!vms_write_block (abfd
, kbn_vbn
, kbn_blk
))
1975 /* Append data to the data block DATA. Force write if PAD is true. */
1978 vms_write_data_block (bfd
*arch
, struct vms_datadef
*data
, file_ptr
*off
,
1979 const unsigned char *buf
, unsigned int len
, int pad
)
1981 while (len
> 0 || pad
)
1983 unsigned int doff
= *off
& (VMS_BLOCK_SIZE
- 1);
1984 unsigned int remlen
= (DATA__LENGTH
- DATA__DATA
) - doff
;
1987 l
= (len
> remlen
) ? remlen
: len
;
1988 memcpy (data
->data
+ doff
, buf
, l
);
1994 if (doff
== (DATA__LENGTH
- DATA__DATA
) || (len
== 0 && pad
))
1998 bfd_putl32 ((*off
/ VMS_BLOCK_SIZE
) + 2, data
->link
);
2000 if (bfd_bwrite (data
, sizeof (*data
), arch
) != sizeof (*data
))
2003 *off
+= DATA__LENGTH
- doff
;
2012 /* Build the symbols index. */
2015 _bfd_vms_lib_build_map (unsigned int nbr_modules
,
2016 struct lib_index
*modules
,
2017 unsigned int *res_cnt
,
2018 struct lib_index
**res
)
2021 asymbol
**syms
= NULL
;
2023 struct lib_index
*map
= NULL
;
2024 unsigned int map_max
= 1024; /* Fine initial default. */
2025 unsigned int map_count
= 0;
2027 map
= (struct lib_index
*) bfd_malloc (map_max
* sizeof (struct lib_index
));
2031 /* Gather symbols. */
2032 for (i
= 0; i
< nbr_modules
; i
++)
2037 bfd
*current
= modules
[i
].abfd
;
2039 if ((bfd_get_file_flags (current
) & HAS_SYMS
) == 0)
2042 storage
= bfd_get_symtab_upper_bound (current
);
2048 if (storage
> syms_max
)
2052 syms
= (asymbol
**) bfd_malloc (syms_max
);
2056 symcount
= bfd_canonicalize_symtab (current
, syms
);
2060 /* Now map over all the symbols, picking out the ones we
2062 for (src_count
= 0; src_count
< symcount
; src_count
++)
2064 flagword flags
= (syms
[src_count
])->flags
;
2065 asection
*sec
= syms
[src_count
]->section
;
2067 if ((flags
& BSF_GLOBAL
2069 || flags
& BSF_INDIRECT
2070 || bfd_is_com_section (sec
))
2071 && ! bfd_is_und_section (sec
))
2073 struct lib_index
*new_map
;
2075 /* This symbol will go into the archive header. */
2076 if (map_count
== map_max
)
2079 new_map
= (struct lib_index
*)
2080 bfd_realloc (map
, map_max
* sizeof (struct lib_index
));
2081 if (new_map
== NULL
)
2086 map
[map_count
].abfd
= current
;
2087 map
[map_count
].namlen
= strlen (syms
[src_count
]->name
);
2088 map
[map_count
].name
= syms
[src_count
]->name
;
2096 *res_cnt
= map_count
;
2106 /* Do the hard work: write an archive on the disk. */
2109 _bfd_vms_lib_write_archive_contents (bfd
*arch
)
2112 unsigned int nbr_modules
;
2113 struct lib_index
*modules
;
2114 unsigned int nbr_symbols
;
2115 struct lib_index
*symbols
;
2116 struct lib_tdata
*tdata
= bfd_libdata (arch
);
2119 unsigned int nbr_mod_iblk
;
2120 unsigned int nbr_sym_iblk
;
2122 unsigned int mod_idx_vbn
;
2123 unsigned int sym_idx_vbn
;
2124 bool is_elfidx
= tdata
->kind
== vms_lib_ia64
;
2125 unsigned int max_keylen
= is_elfidx
? MAX_EKEYLEN
: MAX_KEYLEN
;
2127 /* Count the number of modules (and do a first sanity check). */
2129 for (current
= arch
->archive_head
;
2131 current
= current
->archive_next
)
2133 /* This check is checking the bfds for the objects we're reading
2134 from (which are usually either an object file or archive on
2135 disk), not the archive entries we're writing to. We don't
2136 actually create bfds for the archive members, we just copy
2137 them byte-wise when we write out the archive. */
2138 if (bfd_write_p (current
) || !bfd_check_format (current
, bfd_object
))
2140 bfd_set_error (bfd_error_invalid_operation
);
2147 /* Build the modules list. */
2148 BFD_ASSERT (tdata
->modules
== NULL
);
2149 modules
= bfd_alloc (arch
, nbr_modules
* sizeof (struct lib_index
));
2150 if (modules
== NULL
)
2153 for (current
= arch
->archive_head
, i
= 0;
2155 current
= current
->archive_next
, i
++)
2159 modules
[i
].abfd
= current
;
2160 modules
[i
].name
= vms_get_module_name (bfd_get_filename (current
), false);
2163 /* FIXME: silently truncate long names ? */
2164 nl
= strlen (modules
[i
].name
);
2165 modules
[i
].namlen
= (nl
> max_keylen
? max_keylen
: nl
);
2168 /* Create the module index. */
2170 if (!vms_write_index (NULL
, modules
, nbr_modules
, &vbn
, NULL
, is_elfidx
))
2174 /* Create symbol index. */
2175 if (!_bfd_vms_lib_build_map (nbr_modules
, modules
, &nbr_symbols
, &symbols
))
2179 if (!vms_write_index (NULL
, symbols
, nbr_symbols
, &vbn
, NULL
, is_elfidx
))
2183 /* Write modules and remember their position. */
2184 off
= (1 + nbr_mod_iblk
+ nbr_sym_iblk
) * VMS_BLOCK_SIZE
;
2186 if (bfd_seek (arch
, off
, SEEK_SET
) != 0)
2189 for (i
= 0; i
< nbr_modules
; i
++)
2191 struct vms_datadef data
;
2192 unsigned char blk
[VMS_BLOCK_SIZE
];
2193 struct vms_mhd
*mhd
;
2196 current
= modules
[i
].abfd
;
2197 current
->proxy_origin
= off
;
2203 /* Write the MHD as a record (ie, size first). */
2205 bfd_putl16 (tdata
->mhd_size
, blk
);
2207 mhd
= (struct vms_mhd
*)(blk
+ sz
);
2208 memset (mhd
, 0, sizeof (struct vms_mhd
));
2210 mhd
->id
= MHD__C_MHDID
;
2212 memcpy (mhd
->objid
, "V1.0", 4);
2213 bfd_putl32 (modules
[i
].ref
, mhd
->refcnt
);
2216 sz
+= tdata
->mhd_size
;
2219 /* Rewind the member to be put into the archive. */
2220 if (bfd_seek (current
, 0, SEEK_SET
) != 0)
2223 /* Copy the member into the archive. */
2226 unsigned int modsize
= 0;
2228 file_ptr off_hdr
= off
;
2230 /* Read to complete the first block. */
2231 amt
= bfd_bread (blk
+ sz
, VMS_BLOCK_SIZE
- sz
, current
);
2232 if (amt
== (bfd_size_type
)-1)
2235 if (amt
< VMS_BLOCK_SIZE
- sz
)
2237 /* The member size is less than a block. Pad the block. */
2238 memset (blk
+ sz
+ amt
, 0, VMS_BLOCK_SIZE
- sz
- amt
);
2240 bfd_putl32 (modsize
, mhd
->modsize
);
2242 /* Write the first block (which contains an mhd). */
2243 if (bfd_bwrite (blk
, VMS_BLOCK_SIZE
, arch
) != VMS_BLOCK_SIZE
)
2245 off
+= VMS_BLOCK_SIZE
;
2247 if (amt
== VMS_BLOCK_SIZE
- sz
)
2249 /* Copy the remaining. */
2250 char buffer
[DEFAULT_BUFFERSIZE
];
2254 amt
= bfd_bread (buffer
, sizeof (buffer
), current
);
2255 if (amt
== (bfd_size_type
)-1)
2260 if (amt
!= sizeof (buffer
))
2262 /* Clear the padding. */
2263 memset (buffer
+ amt
, 0, sizeof (buffer
) - amt
);
2264 amt
= (amt
+ VMS_BLOCK_SIZE
) & ~(VMS_BLOCK_SIZE
- 1);
2266 if (bfd_bwrite (buffer
, amt
, arch
) != amt
)
2271 /* Now that the size is known, write the first block (again). */
2272 bfd_putl32 (modsize
, mhd
->modsize
);
2273 if (bfd_seek (arch
, off_hdr
, SEEK_SET
) != 0
2274 || bfd_bwrite (blk
, VMS_BLOCK_SIZE
, arch
) != VMS_BLOCK_SIZE
)
2276 if (bfd_seek (arch
, off
, SEEK_SET
) != 0)
2282 /* Write the MHD. */
2283 if (!vms_write_data_block (arch
, &data
, &off
, blk
, sz
, 0))
2286 /* Write the member. */
2289 sz
= bfd_bread (blk
, sizeof (blk
), current
);
2292 if (!vms_write_data_block (arch
, &data
, &off
, blk
, sz
, 0))
2296 /* Write the end of module marker. */
2297 if (!vms_write_data_block (arch
, &data
, &off
,
2298 eotdesc
, sizeof (eotdesc
), 1))
2303 /* Write the indexes. */
2305 if (!vms_write_index (arch
, modules
, nbr_modules
, &vbn
, &mod_idx_vbn
,
2308 if (!vms_write_index (arch
, symbols
, nbr_symbols
, &vbn
, &sym_idx_vbn
,
2312 /* Write libary header. */
2314 unsigned char blk
[VMS_BLOCK_SIZE
];
2315 struct vms_lhd
*lhd
= (struct vms_lhd
*)blk
;
2316 struct vms_idd
*idd
= (struct vms_idd
*)(blk
+ sizeof (*lhd
));
2317 unsigned int idd_flags
;
2318 unsigned int saneid
;
2320 memset (blk
, 0, sizeof (blk
));
2322 lhd
->type
= tdata
->type
;
2324 switch (tdata
->kind
)
2327 saneid
= LHD_SANEID3
;
2330 saneid
= LHD_SANEID6
;
2335 bfd_putl32 (saneid
, lhd
->sanity
);
2336 bfd_putl16 (tdata
->ver
, lhd
->majorid
);
2337 bfd_putl16 (0, lhd
->minorid
);
2338 snprintf ((char *)lhd
->lbrver
+ 1, sizeof (lhd
->lbrver
) - 1,
2340 (unsigned)(BFD_VERSION
/ 100000000UL),
2341 (unsigned)(BFD_VERSION
/ 1000000UL) % 100,
2342 (unsigned)(BFD_VERSION
/ 10000UL) % 100);
2343 lhd
->lbrver
[sizeof (lhd
->lbrver
) - 1] = 0;
2344 lhd
->lbrver
[0] = strlen ((char *)lhd
->lbrver
+ 1);
2346 bfd_putl32 (tdata
->credat_lo
, lhd
->credat
+ 0);
2347 bfd_putl32 (tdata
->credat_hi
, lhd
->credat
+ 4);
2348 vms_raw_get_time (lhd
->updtim
);
2350 lhd
->mhdusz
= tdata
->mhd_size
- MHD__C_USRDAT
;
2352 bfd_putl32 (nbr_modules
+ nbr_symbols
, lhd
->idxcnt
);
2353 bfd_putl32 (nbr_modules
, lhd
->modcnt
);
2354 bfd_putl32 (nbr_modules
, lhd
->modhdrs
);
2356 /* Number of blocks for index. */
2357 bfd_putl32 (nbr_mod_iblk
+ nbr_sym_iblk
, lhd
->idxblks
);
2358 bfd_putl32 (vbn
- 1, lhd
->hipreal
);
2359 bfd_putl32 (vbn
- 1, lhd
->hiprusd
);
2361 /* VBN of the next free block. */
2362 bfd_putl32 ((off
/ VMS_BLOCK_SIZE
) + 1, lhd
->nextvbn
);
2363 bfd_putl32 ((off
/ VMS_BLOCK_SIZE
) + 1, lhd
->nextrfa
+ 0);
2364 bfd_putl16 (0, lhd
->nextrfa
+ 4);
2366 /* First index (modules name). */
2367 idd_flags
= IDD__FLAGS_ASCII
| IDD__FLAGS_VARLENIDX
2368 | IDD__FLAGS_NOCASECMP
| IDD__FLAGS_NOCASENTR
;
2369 bfd_putl16 (idd_flags
, idd
->flags
);
2370 bfd_putl16 (max_keylen
+ 1, idd
->keylen
);
2371 bfd_putl16 (mod_idx_vbn
, idd
->vbn
);
2374 /* Second index (symbols name). */
2375 bfd_putl16 (idd_flags
, idd
->flags
);
2376 bfd_putl16 (max_keylen
+ 1, idd
->keylen
);
2377 bfd_putl16 (sym_idx_vbn
, idd
->vbn
);
2380 if (!vms_write_block (arch
, 1, blk
))
2387 bfd_set_input_error (current
, bfd_get_error ());
2391 /* Add a target for text library. This costs almost nothing and is useful to
2392 read VMS library on the host. */
2394 const bfd_target alpha_vms_lib_txt_vec
=
2396 "vms-libtxt", /* Name. */
2397 bfd_target_unknown_flavour
,
2398 BFD_ENDIAN_UNKNOWN
, /* byteorder */
2399 BFD_ENDIAN_UNKNOWN
, /* header_byteorder */
2400 0, /* Object flags. */
2401 0, /* Sect flags. */
2402 0, /* symbol_leading_char. */
2403 ' ', /* ar_pad_char. */
2404 15, /* ar_max_namelen. */
2405 0, /* match priority. */
2406 TARGET_KEEP_UNUSED_SECTION_SYMBOLS
, /* keep unused section symbols. */
2407 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
2408 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
2409 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
,
2410 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
2411 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
2412 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
,
2413 { /* bfd_check_format. */
2416 _bfd_vms_lib_txt_archive_p
,
2419 { /* bfd_set_format. */
2420 _bfd_bool_bfd_false_error
,
2421 _bfd_bool_bfd_false_error
,
2422 _bfd_bool_bfd_false_error
,
2423 _bfd_bool_bfd_false_error
2425 { /* bfd_write_contents. */
2426 _bfd_bool_bfd_false_error
,
2427 _bfd_bool_bfd_false_error
,
2428 _bfd_bool_bfd_false_error
,
2429 _bfd_bool_bfd_false_error
2431 BFD_JUMP_TABLE_GENERIC (_bfd_generic
),
2432 BFD_JUMP_TABLE_COPY (_bfd_generic
),
2433 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
2434 BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib
),
2435 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols
),
2436 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs
),
2437 BFD_JUMP_TABLE_WRITE (_bfd_nowrite
),
2438 BFD_JUMP_TABLE_LINK (_bfd_nolink
),
2439 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),