1 /* BFD back-end for VMS archive files.
3 Copyright (C) 2010-2024 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_read (&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_read (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_write (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_read (&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_read (&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
));
487 memcpy (csbuf
, csm
.idx
, csm
.nbr
* sizeof (struct carsym
));
495 /* Standard function. */
498 _bfd_vms_lib_archive_p (bfd
*abfd
, enum vms_lib_kind kind
)
502 unsigned int majorid
;
503 struct lib_tdata
*tdata_hold
;
504 struct lib_tdata
*tdata
;
506 unsigned int nbr_ent
;
509 if (bfd_read (&lhd
, sizeof (lhd
), abfd
) != sizeof (lhd
))
511 if (bfd_get_error () != bfd_error_system_call
)
512 bfd_set_error (bfd_error_wrong_format
);
516 /* Check sanity (= magic) number. */
517 sanity
= bfd_getl32 (lhd
.sanity
);
518 if (!(sanity
== LHD_SANEID3
519 || sanity
== LHD_SANEID6
520 || sanity
== LHD_SANEID_DCX
))
522 bfd_set_error (bfd_error_wrong_format
);
525 majorid
= bfd_getl32 (lhd
.majorid
);
527 /* Check archive kind. */
531 if ((lhd
.type
!= LBR__C_TYP_EOBJ
&& lhd
.type
!= LBR__C_TYP_ESHSTB
)
532 || majorid
!= LBR_MAJORID
535 bfd_set_error (bfd_error_wrong_format
);
540 if ((lhd
.type
!= LBR__C_TYP_IOBJ
&& lhd
.type
!= LBR__C_TYP_ISHSTB
)
541 || majorid
!= LBR_ELFMAJORID
544 bfd_set_error (bfd_error_wrong_format
);
549 if ((lhd
.type
!= LBR__C_TYP_TXT
550 && lhd
.type
!= LBR__C_TYP_MLB
551 && lhd
.type
!= LBR__C_TYP_HLP
)
552 || majorid
!= LBR_MAJORID
555 bfd_set_error (bfd_error_wrong_format
);
563 /* Allocate and initialize private data. */
564 tdata_hold
= bfd_libdata (abfd
);
565 tdata
= (struct lib_tdata
*) bfd_zalloc (abfd
, sizeof (struct lib_tdata
));
568 abfd
->tdata
.any
= (void *)tdata
;
569 tdata
->ver
= majorid
;
570 tdata
->mhd_size
= MHD__C_USRDAT
+ lhd
.mhdusz
;
571 tdata
->type
= lhd
.type
;
573 tdata
->credat_lo
= bfd_getl32 (lhd
.credat
+ 0);
574 tdata
->credat_hi
= bfd_getl32 (lhd
.credat
+ 4);
577 tdata
->nbr_modules
= bfd_getl32 (lhd
.modcnt
);
578 tdata
->artdata
.symdef_count
= bfd_getl32 (lhd
.idxcnt
) - tdata
->nbr_modules
;
579 nbr_ent
= tdata
->nbr_modules
;
580 tdata
->modules
= vms_lib_read_index (abfd
, 0, &nbr_ent
);
581 if (tdata
->modules
== NULL
|| nbr_ent
!= tdata
->nbr_modules
)
585 nbr_ent
= tdata
->artdata
.symdef_count
;
586 tdata
->artdata
.symdefs
= vms_lib_read_index (abfd
, 1, &nbr_ent
);
587 if (tdata
->artdata
.symdefs
== NULL
)
589 /* Only IA64 archives may have more entries in the index that what
591 if (nbr_ent
!= tdata
->artdata
.symdef_count
592 && kind
!= vms_lib_ia64
)
594 tdata
->artdata
.symdef_count
= nbr_ent
;
596 tdata
->cache
= bfd_zalloc (abfd
, sizeof (bfd
*) * tdata
->nbr_modules
);
597 if (tdata
->cache
== NULL
)
600 /* Read DCX submaps. */
601 dcxvbn
= bfd_getl32 (lhd
.dcxmapvbn
);
604 unsigned char buf_reclen
[4];
607 struct vms_dcxmap
*map
;
608 unsigned int sbm_off
;
611 if (bfd_seek (abfd
, (dcxvbn
- 1) * VMS_BLOCK_SIZE
, SEEK_SET
) != 0
612 || bfd_read (buf_reclen
, sizeof (buf_reclen
), abfd
)
613 != sizeof (buf_reclen
))
615 reclen
= bfd_getl32 (buf_reclen
);
616 if (reclen
< sizeof (struct vms_dcxmap
))
618 buf
= _bfd_malloc_and_read (abfd
, reclen
, reclen
);
621 map
= (struct vms_dcxmap
*)buf
;
622 tdata
->nbr_dcxsbm
= bfd_getl16 (map
->nsubs
);
623 sbm_off
= bfd_getl16 (map
->sub0
);
624 tdata
->dcxsbm
= (struct dcxsbm_desc
*)bfd_alloc
625 (abfd
, tdata
->nbr_dcxsbm
* sizeof (struct dcxsbm_desc
));
626 for (i
= 0; i
< tdata
->nbr_dcxsbm
; i
++)
628 struct vms_dcxsbm
*sbm
;
629 struct dcxsbm_desc
*sbmdesc
= &tdata
->dcxsbm
[i
];
630 unsigned int sbm_len
;
637 || reclen
- sbm_off
< sizeof (struct vms_dcxsbm
))
643 sbm
= (struct vms_dcxsbm
*) (buf
+ sbm_off
);
644 sbm_sz
= bfd_getl16 (sbm
->size
);
646 if (sbm_off
> reclen
)
649 sbmdesc
->min_char
= sbm
->min_char
;
650 BFD_ASSERT (sbmdesc
->min_char
== 0);
651 sbmdesc
->max_char
= sbm
->max_char
;
652 sbm_len
= sbmdesc
->max_char
- sbmdesc
->min_char
+ 1;
653 l
= (2 * sbm_len
+ 7) / 8;
654 if (sbm_sz
< sizeof (struct vms_dcxsbm
) + l
+ sbm_len
655 || (tdata
->nbr_dcxsbm
> 1
656 && sbm_sz
< sizeof (struct vms_dcxsbm
) + l
+ 3 * sbm_len
))
658 sbmdesc
->flags
= (unsigned char *)bfd_alloc (abfd
, l
);
659 off
= bfd_getl16 (sbm
->flags
);
663 memcpy (sbmdesc
->flags
, (bfd_byte
*) sbm
+ off
, l
);
664 sbmdesc
->nodes
= (unsigned char *)bfd_alloc (abfd
, 2 * sbm_len
);
665 off
= bfd_getl16 (sbm
->nodes
);
667 || sbm_sz
- off
< 2 * sbm_len
)
669 memcpy (sbmdesc
->nodes
, (bfd_byte
*) sbm
+ off
, 2 * sbm_len
);
670 off
= bfd_getl16 (sbm
->next
);
674 || sbm_sz
- off
< 2 * sbm_len
)
676 /* Read the 'next' array. */
677 sbmdesc
->next
= (unsigned short *) bfd_alloc (abfd
, 2 * sbm_len
);
678 buf1
= (bfd_byte
*) sbm
+ off
;
679 for (j
= 0; j
< sbm_len
; j
++)
680 sbmdesc
->next
[j
] = bfd_getl16 (buf1
+ j
* 2);
684 /* There is no next array if there is only one submap. */
685 BFD_ASSERT (tdata
->nbr_dcxsbm
== 1);
686 sbmdesc
->next
= NULL
;
693 tdata
->nbr_dcxsbm
= 0;
696 /* The map is always present. Also mark shared image library. */
697 abfd
->has_armap
= true;
698 if (tdata
->type
== LBR__C_TYP_ESHSTB
|| tdata
->type
== LBR__C_TYP_ISHSTB
)
699 abfd
->is_thin_archive
= true;
701 return _bfd_no_cleanup
;
704 bfd_release (abfd
, tdata
);
705 abfd
->tdata
.any
= (void *)tdata_hold
;
709 /* Standard function for alpha libraries. */
712 _bfd_vms_lib_alpha_archive_p (bfd
*abfd
)
714 return _bfd_vms_lib_archive_p (abfd
, vms_lib_alpha
);
717 /* Standard function for ia64 libraries. */
720 _bfd_vms_lib_ia64_archive_p (bfd
*abfd
)
722 return _bfd_vms_lib_archive_p (abfd
, vms_lib_ia64
);
725 /* Standard function for text libraries. */
728 _bfd_vms_lib_txt_archive_p (bfd
*abfd
)
730 return _bfd_vms_lib_archive_p (abfd
, vms_lib_txt
);
733 /* Standard bfd function. */
736 _bfd_vms_lib_mkarchive (bfd
*abfd
, enum vms_lib_kind kind
)
738 struct lib_tdata
*tdata
;
740 tdata
= (struct lib_tdata
*) bfd_zalloc (abfd
, sizeof (struct lib_tdata
));
744 abfd
->tdata
.any
= (void *)tdata
;
745 vms_get_time (&tdata
->credat_hi
, &tdata
->credat_lo
);
751 tdata
->ver
= LBR_MAJORID
;
752 tdata
->mhd_size
= offsetof (struct vms_mhd
, pad1
);
753 tdata
->type
= LBR__C_TYP_EOBJ
;
756 tdata
->ver
= LBR_ELFMAJORID
;
757 tdata
->mhd_size
= sizeof (struct vms_mhd
);
758 tdata
->type
= LBR__C_TYP_IOBJ
;
764 tdata
->nbr_modules
= 0;
765 tdata
->artdata
.symdef_count
= 0;
766 tdata
->modules
= NULL
;
767 tdata
->artdata
.symdefs
= NULL
;
774 _bfd_vms_lib_alpha_mkarchive (bfd
*abfd
)
776 return _bfd_vms_lib_mkarchive (abfd
, vms_lib_alpha
);
780 _bfd_vms_lib_ia64_mkarchive (bfd
*abfd
)
782 return _bfd_vms_lib_mkarchive (abfd
, vms_lib_ia64
);
785 /* Find NAME in the symbol index. Return the index. */
788 _bfd_vms_lib_find_symbol (bfd
*abfd
, const char *name
)
790 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
791 carsym
*syms
= tdata
->artdata
.symdefs
;
794 /* Open-coded binary search for speed. */
796 hi
= tdata
->artdata
.symdef_count
- 1;
800 int mid
= lo
+ (hi
- lo
) / 2;
803 diff
= (char)(name
[0] - syms
[mid
].name
[0]);
805 diff
= strcmp (name
, syms
[mid
].name
);
813 return BFD_NO_MORE_SYMBOLS
;
816 /* IO vector for archive member. Need that because members are not linearly
817 stored in archives. */
821 /* Current offset. */
824 /* Length of the module, when known. */
827 /* Current position in the record from bfd_read point of view (ie, after
828 decompression). 0 means that no data byte have been read, -2 and -1
829 are reserved for the length word. */
831 #define REC_POS_NL -4
832 #define REC_POS_PAD -3
833 #define REC_POS_LEN0 -2
834 #define REC_POS_LEN1 -1
837 unsigned short rec_len
;
838 /* Number of bytes to read in the current record. */
839 unsigned short rec_rem
;
840 /* Offset of the next block. */
842 /* Current *data* offset in the data block. */
843 unsigned short blk_off
;
845 /* Offset of the first block. Extracted from the index. */
846 file_ptr first_block
;
848 /* Initial next_block. Extracted when the MHD is read. */
849 file_ptr init_next_block
;
850 /* Initial blk_off, once the MHD is read. */
851 unsigned short init_blk_off
;
853 /* Used to store any 3 byte record, which could be the EOF pattern. */
854 unsigned char pattern
[4];
857 struct dcxsbm_desc
*dcxsbms
;
858 /* Current submap. */
859 struct dcxsbm_desc
*dcx_sbm
;
860 /* Current offset in the submap. */
861 unsigned int dcx_offset
;
864 /* Compressed buffer. */
865 unsigned char *dcx_buf
;
866 /* Size of the buffer. Used to resize. */
867 unsigned int dcx_max
;
868 /* Number of valid bytes in the buffer. */
869 unsigned int dcx_rlen
;
872 /* Return the current position. */
875 vms_lib_btell (struct bfd
*abfd
)
877 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
881 /* Read the header of the next data block if all bytes of the current block
885 vms_lib_read_block (struct bfd
*abfd
)
887 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
889 if (vec
->blk_off
== DATA__LENGTH
)
891 unsigned char hdr
[DATA__DATA
];
893 /* Read next block. */
894 if (bfd_seek (abfd
->my_archive
, vec
->next_block
, SEEK_SET
) != 0)
896 if (bfd_read (hdr
, sizeof (hdr
), abfd
->my_archive
) != sizeof (hdr
))
898 vec
->next_block
= (bfd_getl32 (hdr
+ 2) - 1) * VMS_BLOCK_SIZE
;
899 vec
->blk_off
= sizeof (hdr
);
904 /* Read NBYTES from ABFD into BUF if not NULL. If BUF is NULL, bytes are
905 not stored. Read linearly from the library, but handle blocks. This
906 function does not handle records nor EOF. */
909 vms_lib_bread_raw (struct bfd
*abfd
, unsigned char *buf
, file_ptr nbytes
)
911 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
919 /* Be sure the current data block is read. */
920 if (!vms_lib_read_block (abfd
))
923 /* Do not read past the data block, do not read more than requested. */
924 l
= DATA__LENGTH
- vec
->blk_off
;
931 /* Really read into BUF. */
932 if (bfd_read (buf
, l
, abfd
->my_archive
) != l
)
937 /* Make as if we are reading. */
938 if (bfd_seek (abfd
->my_archive
, l
, SEEK_CUR
) != 0)
951 /* Decompress NBYTES from VEC. Store the bytes into BUF if not NULL. */
954 vms_lib_dcx (struct vms_lib_iovec
*vec
, unsigned char *buf
, file_ptr nbytes
)
956 struct dcxsbm_desc
*sbm
;
962 /* The loop below expect to deliver at least one byte. */
966 /* Get the current state. */
968 offset
= vec
->dcx_offset
;
969 j
= vec
->dcx_pos
& 7;
971 for (i
= vec
->dcx_pos
>> 3; i
< vec
->dcx_rlen
; i
++)
973 unsigned char b
= vec
->dcx_buf
[i
];
979 if (!(sbm
->flags
[offset
>> 3] & (1 << (offset
& 7))))
981 unsigned int n_offset
= sbm
->nodes
[offset
];
984 /* End of buffer. Stay where we are. */
985 vec
->dcx_pos
= (i
<< 3) + j
;
988 vec
->dcx_offset
= offset
;
992 offset
= 2 * n_offset
;
996 unsigned char v
= sbm
->nodes
[offset
];
998 if (sbm
->next
!= NULL
)
999 sbm
= vec
->dcxsbms
+ sbm
->next
[v
];
1010 vec
->dcx_pos
= (i
<< 3) + j
+ 1;
1011 vec
->dcx_offset
= offset
;
1024 /* Standard IOVEC function. */
1027 vms_lib_bread (struct bfd
*abfd
, void *vbuf
, file_ptr nbytes
)
1029 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1032 unsigned char *buf
= (unsigned char *)vbuf
;
1034 /* Do not read past the end. */
1035 if (vec
->where
>= vec
->file_len
)
1041 if (vec
->rec_rem
== 0)
1043 unsigned char blen
[2];
1045 /* Read record length. */
1046 if (vms_lib_bread_raw (abfd
, blen
, sizeof (blen
)) != sizeof (blen
))
1048 vec
->rec_len
= bfd_getl16 (blen
);
1049 if (bfd_libdata (abfd
->my_archive
)->kind
== vms_lib_txt
)
1051 /* Discard record size and align byte. */
1053 vec
->rec_rem
= vec
->rec_len
;
1057 /* Prepend record size. */
1058 vec
->rec_pos
= REC_POS_LEN0
;
1059 vec
->rec_rem
= (vec
->rec_len
+ 1) & ~1; /* With align byte. */
1061 if (vec
->rec_len
== 3)
1063 /* Possibly end of file. Check the pattern. */
1064 if (vms_lib_bread_raw (abfd
, vec
->pattern
, 4) != 4)
1066 if (!memcmp (vec
->pattern
, eotdesc
+ 2, 3))
1068 /* This is really an EOF. */
1070 vec
->file_len
= vec
->where
;
1075 if (vec
->dcxsbms
!= NULL
)
1077 /* This is a compressed member. */
1081 /* Be sure there is enough room for the expansion. */
1082 len
= (vec
->rec_len
+ 1) & ~1;
1083 if (len
> vec
->dcx_max
)
1085 while (len
> vec
->dcx_max
)
1087 vec
->dcx_buf
= bfd_alloc (abfd
, vec
->dcx_max
);
1088 if (vec
->dcx_buf
== NULL
)
1092 /* Read the compressed record. */
1093 vec
->dcx_rlen
= len
;
1094 if (vec
->rec_len
== 3)
1097 memcpy (vec
->dcx_buf
, vec
->pattern
, 3);
1101 elen
= vms_lib_bread_raw (abfd
, vec
->dcx_buf
, len
);
1106 /* Dummy expansion to get the expanded length. */
1107 vec
->dcx_offset
= 0;
1108 vec
->dcx_sbm
= vec
->dcxsbms
;
1110 elen
= vms_lib_dcx (vec
, NULL
, 0x10000);
1113 vec
->rec_len
= elen
;
1114 vec
->rec_rem
= elen
;
1116 /* Reset the state. */
1117 vec
->dcx_offset
= 0;
1118 vec
->dcx_sbm
= vec
->dcxsbms
;
1122 if (vec
->rec_pos
< 0)
1125 switch (vec
->rec_pos
)
1128 c
= vec
->rec_len
& 0xff;
1129 vec
->rec_pos
= REC_POS_LEN1
;
1132 c
= (vec
->rec_len
>> 8) & 0xff;
1156 if (nbytes
> vec
->rec_rem
)
1157 chunk
= vec
->rec_rem
;
1161 if (vec
->dcxsbms
!= NULL
)
1163 /* Optimize the stat() case: no need to decompress again as we
1165 if (!(buf
== NULL
&& chunk
== vec
->rec_rem
))
1166 chunk
= vms_lib_dcx (vec
, buf
, chunk
);
1170 if (vec
->rec_len
== 3)
1173 memcpy (buf
, vec
->pattern
+ vec
->rec_pos
, chunk
);
1176 chunk
= vms_lib_bread_raw (abfd
, buf
, chunk
);
1184 vec
->rec_pos
+= chunk
;
1185 vec
->rec_rem
-= chunk
;
1187 if (vec
->rec_rem
== 0)
1189 /* End of record reached. */
1190 if (bfd_libdata (abfd
->my_archive
)->kind
== vms_lib_txt
)
1192 if ((vec
->rec_len
& 1) == 1
1193 && vec
->rec_len
!= 3
1194 && vec
->dcxsbms
== NULL
)
1196 /* Eat the pad byte. */
1198 if (vms_lib_bread_raw (abfd
, &pad
, 1) != 1)
1201 vec
->rec_pos
= REC_POS_NL
;
1206 if ((vec
->rec_len
& 1) == 1 && vec
->dcxsbms
!= NULL
)
1208 vec
->rec_pos
= REC_POS_PAD
;
1218 /* Standard function, but we currently only handle the rewind case. */
1221 vms_lib_bseek (struct bfd
*abfd
, file_ptr offset
, int whence
)
1223 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1225 if (whence
== SEEK_SET
&& offset
== 0)
1230 vec
->blk_off
= vec
->init_blk_off
;
1231 vec
->next_block
= vec
->init_next_block
;
1233 if (bfd_seek (abfd
->my_archive
, vec
->first_block
, SEEK_SET
) != 0)
1242 vms_lib_bwrite (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1243 const void *where ATTRIBUTE_UNUSED
,
1244 file_ptr nbytes ATTRIBUTE_UNUSED
)
1250 vms_lib_bclose (struct bfd
*abfd
)
1252 abfd
->iostream
= NULL
;
1257 vms_lib_bflush (struct bfd
*abfd ATTRIBUTE_UNUSED
)
1263 vms_lib_bstat (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1264 struct stat
*sb ATTRIBUTE_UNUSED
)
1266 /* Not supported. */
1271 vms_lib_bmmap (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1272 void *addr ATTRIBUTE_UNUSED
,
1273 size_t len ATTRIBUTE_UNUSED
,
1274 int prot ATTRIBUTE_UNUSED
,
1275 int flags ATTRIBUTE_UNUSED
,
1276 file_ptr offset ATTRIBUTE_UNUSED
,
1277 void **map_addr ATTRIBUTE_UNUSED
,
1278 size_t *map_len ATTRIBUTE_UNUSED
)
1283 static const struct bfd_iovec vms_lib_iovec
= {
1284 &vms_lib_bread
, &vms_lib_bwrite
, &vms_lib_btell
, &vms_lib_bseek
,
1285 &vms_lib_bclose
, &vms_lib_bflush
, &vms_lib_bstat
, &vms_lib_bmmap
1288 /* Open a library module. FILEPOS is the position of the module header. */
1291 vms_lib_bopen (bfd
*el
, file_ptr filepos
)
1293 struct vms_lib_iovec
*vec
;
1294 unsigned char buf
[256];
1295 struct vms_mhd
*mhd
;
1296 struct lib_tdata
*tdata
= bfd_libdata (el
->my_archive
);
1299 /* Allocate and initialized the iovec. */
1300 vec
= bfd_zalloc (el
, sizeof (*vec
));
1305 el
->iovec
= &vms_lib_iovec
;
1307 /* File length is not known. */
1310 /* Read the first data block. */
1311 vec
->next_block
= filepos
& ~(VMS_BLOCK_SIZE
- 1);
1312 vec
->blk_off
= DATA__LENGTH
;
1313 if (!vms_lib_read_block (el
))
1316 /* Prepare to read the first record. */
1317 vec
->blk_off
= filepos
& (VMS_BLOCK_SIZE
- 1);
1319 if (bfd_seek (el
->my_archive
, filepos
, SEEK_SET
) != 0)
1322 /* Read Record length + MHD + align byte. */
1323 len
= tdata
->mhd_size
;
1324 if (vms_lib_bread_raw (el
, buf
, 2) != 2)
1326 if (bfd_getl16 (buf
) != len
)
1328 len
= (len
+ 1) & ~1;
1329 BFD_ASSERT (len
<= sizeof (buf
));
1330 if (vms_lib_bread_raw (el
, buf
, len
) != len
)
1333 /* Get info from mhd. */
1334 mhd
= (struct vms_mhd
*)buf
;
1336 if (mhd
->id
!= MHD__C_MHDID
)
1338 if (len
>= MHD__C_MHDLEN
+ 1)
1339 el
->selective_search
= (mhd
->objstat
& MHD__M_SELSRC
) ? 1 : 0;
1340 el
->mtime
= vms_rawtime_to_time_t (mhd
->datim
);
1341 el
->mtime_set
= true;
1343 /* Reinit the iovec so that seek() will point to the first record after
1346 vec
->init_blk_off
= vec
->blk_off
;
1347 vec
->init_next_block
= vec
->next_block
;
1348 vec
->first_block
= bfd_tell (el
->my_archive
);
1349 vec
->dcxsbms
= bfd_libdata (el
->my_archive
)->dcxsbm
;
1351 if (vec
->dcxsbms
!= NULL
)
1354 vec
->dcx_max
= 10 * 1024;
1355 vec
->dcx_buf
= bfd_alloc (el
, vec
->dcx_max
);
1357 if (vec
->dcx_buf
== NULL
)
1363 /* Get member MODIDX. Return NULL in case of error. */
1366 _bfd_vms_lib_get_module (bfd
*abfd
, unsigned int modidx
)
1368 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
1376 if (modidx
>= tdata
->nbr_modules
)
1379 /* Already loaded. */
1380 if (tdata
->cache
[modidx
])
1381 return tdata
->cache
[modidx
];
1384 file_off
= tdata
->modules
[modidx
].file_offset
;
1385 if (tdata
->type
!= LBR__C_TYP_IOBJ
)
1387 res
= _bfd_create_empty_archive_element_shell (abfd
);
1391 /* Special reader to deal with data blocks. */
1392 if (!vms_lib_bopen (res
, file_off
))
1398 struct vms_mhd
*mhd
;
1399 struct areltdata
*arelt
;
1401 /* Sanity check. The MHD must be big enough to contain module size. */
1402 if (tdata
->mhd_size
< offsetof (struct vms_mhd
, modsize
) + 4)
1405 /* Read the MHD now. */
1406 if (bfd_seek (abfd
, file_off
, SEEK_SET
) != 0)
1408 if (bfd_read (buf
, tdata
->mhd_size
, abfd
) != tdata
->mhd_size
)
1411 mhd
= (struct vms_mhd
*) buf
;
1412 if (mhd
->id
!= MHD__C_MHDID
)
1415 res
= _bfd_create_empty_archive_element_shell (abfd
);
1418 arelt
= bfd_zmalloc (sizeof (*arelt
));
1424 res
->arelt_data
= arelt
;
1426 /* Get info from mhd. */
1427 if (tdata
->mhd_size
>= offsetof (struct vms_mhd
, objstat
) + 1)
1428 res
->selective_search
= (mhd
->objstat
& MHD__M_SELSRC
) ? 1 : 0;
1429 res
->mtime
= vms_rawtime_to_time_t (mhd
->datim
);
1430 res
->mtime_set
= true;
1432 arelt
->parsed_size
= bfd_getl32 (mhd
->modsize
);
1434 /* No need for a special reader as members are stored linearly.
1435 Just skip the MHD. */
1436 res
->origin
= file_off
+ tdata
->mhd_size
;
1440 name
= tdata
->modules
[modidx
].name
;
1441 namelen
= strlen (name
);
1442 newname
= bfd_malloc (namelen
+ 4 + 1);
1443 if (newname
== NULL
)
1448 strcpy (newname
, name
);
1449 switch (tdata
->type
)
1451 case LBR__C_TYP_IOBJ
:
1452 case LBR__C_TYP_EOBJ
:
1453 /* For object archives, append .obj to mimic standard behaviour. */
1454 strcpy (newname
+ namelen
, ".obj");
1459 bfd_set_filename (res
, newname
);
1461 if (bfd_get_filename (res
) == NULL
)
1467 tdata
->cache
[modidx
] = res
;
1472 /* Standard function: get member at IDX. */
1475 _bfd_vms_lib_get_elt_at_index (bfd
*abfd
, symindex symidx
)
1477 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
1479 unsigned int modidx
;
1482 if (symidx
> tdata
->artdata
.symdef_count
)
1484 file_off
= tdata
->artdata
.symdefs
[symidx
].file_offset
;
1487 for (modidx
= 0; modidx
< tdata
->nbr_modules
; modidx
++)
1489 if (tdata
->modules
[modidx
].file_offset
== file_off
)
1492 if (modidx
>= tdata
->nbr_modules
)
1495 return _bfd_vms_lib_get_module (abfd
, modidx
);
1498 /* Elements of an imagelib are stubs. You can get the real image with this
1502 _bfd_vms_lib_get_imagelib_file (bfd
*el
)
1504 bfd
*archive
= el
->my_archive
;
1505 const char *modname
= bfd_get_filename (el
);
1506 int modlen
= strlen (modname
);
1511 /* Convert module name to lower case and append '.exe'. */
1512 filename
= bfd_alloc (el
, modlen
+ 5);
1513 if (filename
== NULL
)
1515 for (j
= 0; j
< modlen
; j
++)
1516 if (ISALPHA (modname
[j
]))
1517 filename
[j
] = TOLOWER (modname
[j
]);
1519 filename
[j
] = modname
[j
];
1520 memcpy (filename
+ modlen
, ".exe", 5);
1522 filename
= _bfd_append_relative_path (archive
, filename
);
1523 if (filename
== NULL
)
1525 res
= bfd_openr (filename
, NULL
);
1529 /* xgettext:c-format */
1530 _bfd_error_handler(_("could not open shared image '%s' from '%s'"),
1531 filename
, bfd_get_filename (archive
));
1532 bfd_release (archive
, filename
);
1536 /* FIXME: put it in a cache ? */
1540 /* Standard function. */
1543 _bfd_vms_lib_openr_next_archived_file (bfd
*archive
,
1552 idx
= last_file
->proxy_origin
+ 1;
1554 if (idx
>= bfd_libdata (archive
)->nbr_modules
)
1556 bfd_set_error (bfd_error_no_more_archived_files
);
1560 res
= _bfd_vms_lib_get_module (archive
, idx
);
1563 res
->proxy_origin
= idx
;
1567 /* Standard function. Just compute the length. */
1570 _bfd_vms_lib_generic_stat_arch_elt (bfd
*abfd
, struct stat
*st
)
1572 struct lib_tdata
*tdata
;
1575 if (abfd
->my_archive
== NULL
)
1577 bfd_set_error (bfd_error_invalid_operation
);
1581 tdata
= bfd_libdata (abfd
->my_archive
);
1582 if (tdata
->type
!= LBR__C_TYP_IOBJ
)
1584 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1586 if (vec
->file_len
== (ufile_ptr
)-1)
1588 if (vms_lib_bseek (abfd
, 0, SEEK_SET
) != 0)
1591 /* Compute length. */
1592 while (vms_lib_bread (abfd
, NULL
, 1 << 20) > 0)
1595 st
->st_size
= vec
->file_len
;
1599 st
->st_size
= ((struct areltdata
*)abfd
->arelt_data
)->parsed_size
;
1602 if (abfd
->mtime_set
)
1603 st
->st_mtime
= abfd
->mtime
;
1613 /* Internal representation of an index entry. */
1617 /* Corresponding archive member. */
1620 /* Number of reference to this entry. */
1623 /* Length of the key. */
1624 unsigned short namlen
;
1630 /* Used to sort index entries. */
1633 lib_index_cmp (const void *lv
, const void *rv
)
1635 const struct lib_index
*l
= lv
;
1636 const struct lib_index
*r
= rv
;
1638 return strcmp (l
->name
, r
->name
);
1641 /* Maximum number of index blocks level. */
1643 #define MAX_LEVEL 10
1645 /* Get the size of an index entry. */
1648 get_idxlen (struct lib_index
*idx
, bool is_elfidx
)
1652 /* 9 is the size of struct vms_elfidx without keyname. */
1653 if (idx
->namlen
> MAX_KEYLEN
)
1654 return 9 + sizeof (struct vms_kbn
);
1656 return 9 + idx
->namlen
;
1660 /* 7 is the size of struct vms_idx without keyname. */
1661 return 7 + idx
->namlen
;
1665 /* Write the index composed by NBR symbols contained in IDX.
1666 VBN is the first vbn to be used, and will contain on return the last vbn.
1667 Can be called with ABFD set to NULL just to size the index.
1668 If not null, TOPVBN will be assigned to the vbn of the root index tree.
1669 IS_ELFIDX is true for elfidx (ie ia64) indexes layout.
1670 Return TRUE on success. */
1673 vms_write_index (bfd
*abfd
,
1674 struct lib_index
*idx
, unsigned int nbr
, unsigned int *vbn
,
1675 unsigned int *topvbn
, bool is_elfidx
)
1677 /* The index is organized as a tree. This function implements a naive
1678 algorithm to balance the tree: it fills the leaves, and create a new
1679 branch when all upper leaves and branches are full. We only keep in
1680 memory a path to the current leaf. */
1684 /* Disk blocks for the current path. */
1685 struct vms_indexdef
*rblk
[MAX_LEVEL
];
1686 /* Info on the current blocks. */
1689 unsigned int vbn
; /* VBN of the block. */
1690 /* The last entry is identified so that it could be copied to the
1692 unsigned short len
; /* Length up to the last entry. */
1693 unsigned short lastlen
; /* Length of the last entry. */
1696 /* The kbn blocks are used to store long symbol names. */
1697 unsigned int kbn_sz
= 0; /* Number of bytes available in the kbn block. */
1698 unsigned int kbn_vbn
= 0; /* VBN of the kbn block. */
1699 unsigned char *kbn_blk
= NULL
; /* Contents of the kbn block. */
1703 /* No entries. Very easy to handle. */
1711 /* Sort the index the first time this function is called. */
1712 qsort (idx
, nbr
, sizeof (struct lib_index
), lib_index_cmp
);
1715 /* Allocate first index block. */
1718 rblk
[0] = bfd_zmalloc (sizeof (struct vms_indexdef
));
1719 blk
[0].vbn
= (*vbn
)++;
1723 for (i
= 0; i
< nbr
; i
++, idx
++)
1725 unsigned int idxlen
;
1727 unsigned int key_vbn
= 0;
1728 unsigned int key_off
= 0;
1730 idxlen
= get_idxlen (idx
, is_elfidx
);
1732 if (is_elfidx
&& idx
->namlen
> MAX_KEYLEN
)
1734 /* If the key (ie name) is too long, write it in the kbn block. */
1735 unsigned int kl
= idx
->namlen
;
1736 unsigned int kl_chunk
;
1737 const char *key
= idx
->name
;
1739 /* Write the key in the kbn, chunk after chunk. */
1742 if (kbn_sz
< sizeof (struct vms_kbn
))
1744 /* Not enough room in the kbn block. */
1747 /* Write it to the disk (if there is one). */
1750 if (!vms_write_block (abfd
, kbn_vbn
, kbn_blk
))
1755 kbn_blk
= bfd_malloc (VMS_BLOCK_SIZE
);
1756 if (kbn_blk
== NULL
)
1759 *(unsigned short *)kbn_blk
= 0;
1761 /* Allocate a new block for the keys. */
1763 kbn_sz
= VMS_BLOCK_SIZE
- 2;
1765 /* Size of the chunk written to the current key block. */
1766 if (kl
+ sizeof (struct vms_kbn
) > kbn_sz
)
1767 kl_chunk
= kbn_sz
- sizeof (struct vms_kbn
);
1771 if (kbn_blk
!= NULL
)
1773 struct vms_kbn
*kbn
;
1775 kbn
= (struct vms_kbn
*)(kbn_blk
+ VMS_BLOCK_SIZE
- kbn_sz
);
1779 /* Save the rfa of the first chunk. */
1781 key_off
= VMS_BLOCK_SIZE
- kbn_sz
;
1784 bfd_putl16 (kl_chunk
, kbn
->keylen
);
1787 /* No next chunk. */
1788 bfd_putl32 (0, kbn
->rfa
.vbn
);
1789 bfd_putl16 (0, kbn
->rfa
.offset
);
1793 /* Next chunk will be at the start of the next block. */
1794 bfd_putl32 (*vbn
, kbn
->rfa
.vbn
);
1795 bfd_putl16 (2, kbn
->rfa
.offset
);
1797 memcpy ((char *)(kbn
+ 1), key
, kl_chunk
);
1801 kl_chunk
= (kl_chunk
+ 1) & ~1; /* Always align. */
1802 kbn_sz
-= kl_chunk
+ sizeof (struct vms_kbn
);
1807 /* Check if a block might overflow. In this case we will flush this
1808 block and all the blocks below it. */
1809 for (j
= 0; j
< level
; j
++)
1810 if (blk
[j
].len
+ blk
[j
].lastlen
+ idxlen
> INDEXDEF__BLKSIZ
)
1813 for (j
= 0; j
< level
; j
++)
1817 /* There is not enough room to write the new entry in this
1818 block or in a parent block. */
1822 BFD_ASSERT (level
< MAX_LEVEL
);
1824 /* Need to create a parent. */
1827 rblk
[level
] = bfd_zmalloc (sizeof (struct vms_indexdef
));
1828 bfd_putl32 (*vbn
, rblk
[j
]->parent
);
1830 blk
[level
].vbn
= (*vbn
)++;
1832 blk
[level
].lastlen
= blk
[j
].lastlen
;
1837 /* Update parent block: write the last entry from the current
1841 struct vms_rfa
*rfa
;
1843 /* Pointer to the last entry in parent block. */
1844 rfa
= (struct vms_rfa
*)(rblk
[j
+ 1]->keys
+ blk
[j
+ 1].len
);
1846 /* Copy the whole entry. */
1847 BFD_ASSERT (blk
[j
+ 1].lastlen
== blk
[j
].lastlen
);
1848 memcpy (rfa
, rblk
[j
]->keys
+ blk
[j
].len
, blk
[j
].lastlen
);
1849 /* Fix the entry (which in always the first field of an
1851 bfd_putl32 (blk
[j
].vbn
, rfa
->vbn
);
1852 bfd_putl16 (RFADEF__C_INDEX
, rfa
->offset
);
1857 /* And allocate it. Do it only on the block that won't be
1858 flushed (so that the parent of the parent can be
1860 blk
[j
+ 1].len
+= blk
[j
+ 1].lastlen
;
1861 blk
[j
+ 1].lastlen
= 0;
1864 /* Write this block on the disk. */
1867 bfd_putl16 (blk
[j
].len
+ blk
[j
].lastlen
, rblk
[j
]->used
);
1868 if (!vms_write_block (abfd
, blk
[j
].vbn
, rblk
[j
]))
1872 /* Reset this block. */
1875 blk
[j
].vbn
= (*vbn
)++;
1878 /* Append it to the block. */
1881 /* Keep the previous last entry. */
1882 blk
[j
].len
+= blk
[j
].lastlen
;
1886 struct vms_rfa
*rfa
;
1888 rfa
= (struct vms_rfa
*)(rblk
[j
]->keys
+ blk
[j
].len
);
1889 bfd_putl32 ((idx
->abfd
->proxy_origin
/ VMS_BLOCK_SIZE
) + 1,
1892 ((idx
->abfd
->proxy_origin
% VMS_BLOCK_SIZE
)
1893 + (is_elfidx
? 0 : DATA__DATA
),
1898 /* Use elfidx format. */
1899 struct vms_elfidx
*en
= (struct vms_elfidx
*)rfa
;
1904 /* Long symbol name. */
1905 struct vms_kbn
*k
= (struct vms_kbn
*)(en
->keyname
);
1906 bfd_putl16 (sizeof (struct vms_kbn
), en
->keylen
);
1907 bfd_putl16 (idx
->namlen
, k
->keylen
);
1908 bfd_putl32 (key_vbn
, k
->rfa
.vbn
);
1909 bfd_putl16 (key_off
, k
->rfa
.offset
);
1910 en
->flags
|= ELFIDX__SYMESC
;
1914 bfd_putl16 (idx
->namlen
, en
->keylen
);
1915 memcpy (en
->keyname
, idx
->name
, idx
->namlen
);
1920 /* Use idx format. */
1921 struct vms_idx
*en
= (struct vms_idx
*)rfa
;
1922 en
->keylen
= idx
->namlen
;
1923 memcpy (en
->keyname
, idx
->name
, idx
->namlen
);
1927 /* The last added key can now be the last one all blocks in the
1929 blk
[j
].lastlen
= idxlen
;
1933 /* Save VBN of the root. */
1935 *topvbn
= blk
[level
- 1].vbn
;
1941 for (j
= 1; j
< level
; j
++)
1943 /* Update parent block: write the new entry. */
1946 struct vms_rfa
*rfa
;
1948 en
= rblk
[j
- 1]->keys
+ blk
[j
- 1].len
;
1949 par
= rblk
[j
]->keys
+ blk
[j
].len
;
1950 BFD_ASSERT (blk
[j
].lastlen
== blk
[j
- 1].lastlen
);
1951 memcpy (par
, en
, blk
[j
- 1].lastlen
);
1952 rfa
= (struct vms_rfa
*)par
;
1953 bfd_putl32 (blk
[j
- 1].vbn
, rfa
->vbn
);
1954 bfd_putl16 (RFADEF__C_INDEX
, rfa
->offset
);
1957 for (j
= 0; j
< level
; j
++)
1959 /* Write this block on the disk. */
1960 bfd_putl16 (blk
[j
].len
+ blk
[j
].lastlen
, rblk
[j
]->used
);
1961 if (!vms_write_block (abfd
, blk
[j
].vbn
, rblk
[j
]))
1968 /* Write the last kbn (if any). */
1971 if (!vms_write_block (abfd
, kbn_vbn
, kbn_blk
))
1981 for (j
= 0; j
< level
; j
++)
1988 /* Append data to the data block DATA. Force write if PAD is true. */
1991 vms_write_data_block (bfd
*arch
, struct vms_datadef
*data
, file_ptr
*off
,
1992 const unsigned char *buf
, unsigned int len
, int pad
)
1994 while (len
> 0 || pad
)
1996 unsigned int doff
= *off
& (VMS_BLOCK_SIZE
- 1);
1997 unsigned int remlen
= (DATA__LENGTH
- DATA__DATA
) - doff
;
2000 l
= (len
> remlen
) ? remlen
: len
;
2001 memcpy (data
->data
+ doff
, buf
, l
);
2007 if (doff
== (DATA__LENGTH
- DATA__DATA
) || (len
== 0 && pad
))
2011 bfd_putl32 ((*off
/ VMS_BLOCK_SIZE
) + 2, data
->link
);
2013 if (bfd_write (data
, sizeof (*data
), arch
) != sizeof (*data
))
2016 *off
+= DATA__LENGTH
- doff
;
2025 /* Build the symbols index. */
2028 _bfd_vms_lib_build_map (unsigned int nbr_modules
,
2029 struct lib_index
*modules
,
2030 unsigned int *res_cnt
,
2031 struct lib_index
**res
)
2034 asymbol
**syms
= NULL
;
2036 struct lib_index
*map
= NULL
;
2037 unsigned int map_max
= 1024; /* Fine initial default. */
2038 unsigned int map_count
= 0;
2040 map
= (struct lib_index
*) bfd_malloc (map_max
* sizeof (struct lib_index
));
2044 /* Gather symbols. */
2045 for (i
= 0; i
< nbr_modules
; i
++)
2050 bfd
*current
= modules
[i
].abfd
;
2052 if ((bfd_get_file_flags (current
) & HAS_SYMS
) == 0)
2055 storage
= bfd_get_symtab_upper_bound (current
);
2061 if (storage
> syms_max
)
2065 syms
= (asymbol
**) bfd_malloc (syms_max
);
2069 symcount
= bfd_canonicalize_symtab (current
, syms
);
2073 /* Now map over all the symbols, picking out the ones we
2075 for (src_count
= 0; src_count
< symcount
; src_count
++)
2077 flagword flags
= (syms
[src_count
])->flags
;
2078 asection
*sec
= syms
[src_count
]->section
;
2080 if ((flags
& BSF_GLOBAL
2082 || flags
& BSF_INDIRECT
2083 || bfd_is_com_section (sec
))
2084 && ! bfd_is_und_section (sec
))
2086 struct lib_index
*new_map
;
2088 /* This symbol will go into the archive header. */
2089 if (map_count
== map_max
)
2092 new_map
= (struct lib_index
*)
2093 bfd_realloc (map
, map_max
* sizeof (struct lib_index
));
2094 if (new_map
== NULL
)
2099 map
[map_count
].abfd
= current
;
2100 map
[map_count
].namlen
= strlen (syms
[src_count
]->name
);
2101 map
[map_count
].name
= syms
[src_count
]->name
;
2109 *res_cnt
= map_count
;
2120 /* Do the hard work: write an archive on the disk. */
2123 _bfd_vms_lib_write_archive_contents (bfd
*arch
)
2126 unsigned int nbr_modules
;
2127 struct lib_index
*modules
;
2128 unsigned int nbr_symbols
;
2129 struct lib_index
*symbols
= NULL
;
2130 struct lib_tdata
*tdata
= bfd_libdata (arch
);
2133 unsigned int nbr_mod_iblk
;
2134 unsigned int nbr_sym_iblk
;
2136 unsigned int mod_idx_vbn
;
2137 unsigned int sym_idx_vbn
;
2138 bool is_elfidx
= tdata
->kind
== vms_lib_ia64
;
2139 unsigned int max_keylen
= is_elfidx
? MAX_EKEYLEN
: MAX_KEYLEN
;
2141 /* Count the number of modules (and do a first sanity check). */
2143 for (current
= arch
->archive_head
;
2145 current
= current
->archive_next
)
2147 /* This check is checking the bfds for the objects we're reading
2148 from (which are usually either an object file or archive on
2149 disk), not the archive entries we're writing to. We don't
2150 actually create bfds for the archive members, we just copy
2151 them byte-wise when we write out the archive. */
2152 if (bfd_write_p (current
) || !bfd_check_format (current
, bfd_object
))
2154 bfd_set_error (bfd_error_invalid_operation
);
2161 /* Build the modules list. */
2162 BFD_ASSERT (tdata
->modules
== NULL
);
2163 modules
= bfd_alloc (arch
, nbr_modules
* sizeof (struct lib_index
));
2164 if (modules
== NULL
)
2167 for (current
= arch
->archive_head
, i
= 0;
2169 current
= current
->archive_next
, i
++)
2173 modules
[i
].abfd
= current
;
2174 modules
[i
].name
= vms_get_module_name (bfd_get_filename (current
), false);
2177 /* FIXME: silently truncate long names ? */
2178 nl
= strlen (modules
[i
].name
);
2179 modules
[i
].namlen
= (nl
> max_keylen
? max_keylen
: nl
);
2182 /* Create the module index. */
2184 if (!vms_write_index (NULL
, modules
, nbr_modules
, &vbn
, NULL
, is_elfidx
))
2188 /* Create symbol index. */
2189 if (!_bfd_vms_lib_build_map (nbr_modules
, modules
, &nbr_symbols
, &symbols
))
2193 if (!vms_write_index (NULL
, symbols
, nbr_symbols
, &vbn
, NULL
, is_elfidx
))
2197 /* Write modules and remember their position. */
2198 off
= (1 + nbr_mod_iblk
+ nbr_sym_iblk
) * VMS_BLOCK_SIZE
;
2200 if (bfd_seek (arch
, off
, SEEK_SET
) != 0)
2203 for (i
= 0; i
< nbr_modules
; i
++)
2205 struct vms_datadef data
;
2206 unsigned char blk
[VMS_BLOCK_SIZE
];
2207 struct vms_mhd
*mhd
;
2210 current
= modules
[i
].abfd
;
2211 current
->proxy_origin
= off
;
2217 /* Write the MHD as a record (ie, size first). */
2219 bfd_putl16 (tdata
->mhd_size
, blk
);
2221 mhd
= (struct vms_mhd
*)(blk
+ sz
);
2222 memset (mhd
, 0, sizeof (struct vms_mhd
));
2224 mhd
->id
= MHD__C_MHDID
;
2226 memcpy (mhd
->objid
, "V1.0", 4);
2227 bfd_putl32 (modules
[i
].ref
, mhd
->refcnt
);
2230 sz
+= tdata
->mhd_size
;
2233 /* Rewind the member to be put into the archive. */
2234 if (bfd_seek (current
, 0, SEEK_SET
) != 0)
2237 /* Copy the member into the archive. */
2240 unsigned int modsize
= 0;
2242 file_ptr off_hdr
= off
;
2244 /* Read to complete the first block. */
2245 amt
= bfd_read (blk
+ sz
, VMS_BLOCK_SIZE
- sz
, current
);
2246 if (amt
== (bfd_size_type
)-1)
2249 if (amt
< VMS_BLOCK_SIZE
- sz
)
2251 /* The member size is less than a block. Pad the block. */
2252 memset (blk
+ sz
+ amt
, 0, VMS_BLOCK_SIZE
- sz
- amt
);
2254 bfd_putl32 (modsize
, mhd
->modsize
);
2256 /* Write the first block (which contains an mhd). */
2257 if (bfd_write (blk
, VMS_BLOCK_SIZE
, arch
) != VMS_BLOCK_SIZE
)
2259 off
+= VMS_BLOCK_SIZE
;
2261 if (amt
== VMS_BLOCK_SIZE
- sz
)
2263 /* Copy the remaining. */
2264 char buffer
[8 * 1024];
2268 amt
= bfd_read (buffer
, sizeof (buffer
), current
);
2269 if (amt
== (bfd_size_type
)-1)
2274 if (amt
!= sizeof (buffer
))
2276 /* Clear the padding. */
2277 memset (buffer
+ amt
, 0, sizeof (buffer
) - amt
);
2278 amt
= (amt
+ VMS_BLOCK_SIZE
) & ~(VMS_BLOCK_SIZE
- 1);
2280 if (bfd_write (buffer
, amt
, arch
) != amt
)
2285 /* Now that the size is known, write the first block (again). */
2286 bfd_putl32 (modsize
, mhd
->modsize
);
2287 if (bfd_seek (arch
, off_hdr
, SEEK_SET
) != 0
2288 || bfd_write (blk
, VMS_BLOCK_SIZE
, arch
) != VMS_BLOCK_SIZE
)
2290 if (bfd_seek (arch
, off
, SEEK_SET
) != 0)
2296 /* Write the MHD. */
2297 if (!vms_write_data_block (arch
, &data
, &off
, blk
, sz
, 0))
2300 /* Write the member. */
2303 sz
= bfd_read (blk
, sizeof (blk
), current
);
2306 if (!vms_write_data_block (arch
, &data
, &off
, blk
, sz
, 0))
2310 /* Write the end of module marker. */
2311 if (!vms_write_data_block (arch
, &data
, &off
,
2312 eotdesc
, sizeof (eotdesc
), 1))
2317 /* Write the indexes. */
2319 if (!vms_write_index (arch
, modules
, nbr_modules
, &vbn
, &mod_idx_vbn
,
2322 if (!vms_write_index (arch
, symbols
, nbr_symbols
, &vbn
, &sym_idx_vbn
,
2326 /* Write libary header. */
2328 unsigned char blk
[VMS_BLOCK_SIZE
];
2329 struct vms_lhd
*lhd
= (struct vms_lhd
*)blk
;
2330 struct vms_idd
*idd
= (struct vms_idd
*)(blk
+ sizeof (*lhd
));
2331 unsigned int idd_flags
;
2332 unsigned int saneid
;
2334 memset (blk
, 0, sizeof (blk
));
2336 lhd
->type
= tdata
->type
;
2338 switch (tdata
->kind
)
2341 saneid
= LHD_SANEID3
;
2344 saneid
= LHD_SANEID6
;
2349 bfd_putl32 (saneid
, lhd
->sanity
);
2350 bfd_putl16 (tdata
->ver
, lhd
->majorid
);
2351 bfd_putl16 (0, lhd
->minorid
);
2352 snprintf ((char *)lhd
->lbrver
+ 1, sizeof (lhd
->lbrver
) - 1,
2354 (unsigned)(BFD_VERSION
/ 100000000UL),
2355 (unsigned)(BFD_VERSION
/ 1000000UL) % 100,
2356 (unsigned)(BFD_VERSION
/ 10000UL) % 100);
2357 lhd
->lbrver
[sizeof (lhd
->lbrver
) - 1] = 0;
2358 lhd
->lbrver
[0] = strlen ((char *)lhd
->lbrver
+ 1);
2360 bfd_putl32 (tdata
->credat_lo
, lhd
->credat
+ 0);
2361 bfd_putl32 (tdata
->credat_hi
, lhd
->credat
+ 4);
2362 vms_raw_get_time (lhd
->updtim
);
2364 lhd
->mhdusz
= tdata
->mhd_size
- MHD__C_USRDAT
;
2366 bfd_putl32 (nbr_modules
+ nbr_symbols
, lhd
->idxcnt
);
2367 bfd_putl32 (nbr_modules
, lhd
->modcnt
);
2368 bfd_putl32 (nbr_modules
, lhd
->modhdrs
);
2370 /* Number of blocks for index. */
2371 bfd_putl32 (nbr_mod_iblk
+ nbr_sym_iblk
, lhd
->idxblks
);
2372 bfd_putl32 (vbn
- 1, lhd
->hipreal
);
2373 bfd_putl32 (vbn
- 1, lhd
->hiprusd
);
2375 /* VBN of the next free block. */
2376 bfd_putl32 ((off
/ VMS_BLOCK_SIZE
) + 1, lhd
->nextvbn
);
2377 bfd_putl32 ((off
/ VMS_BLOCK_SIZE
) + 1, lhd
->nextrfa
+ 0);
2378 bfd_putl16 (0, lhd
->nextrfa
+ 4);
2380 /* First index (modules name). */
2381 idd_flags
= IDD__FLAGS_ASCII
| IDD__FLAGS_VARLENIDX
2382 | IDD__FLAGS_NOCASECMP
| IDD__FLAGS_NOCASENTR
;
2383 bfd_putl16 (idd_flags
, idd
->flags
);
2384 bfd_putl16 (max_keylen
+ 1, idd
->keylen
);
2385 bfd_putl16 (mod_idx_vbn
, idd
->vbn
);
2388 /* Second index (symbols name). */
2389 bfd_putl16 (idd_flags
, idd
->flags
);
2390 bfd_putl16 (max_keylen
+ 1, idd
->keylen
);
2391 bfd_putl16 (sym_idx_vbn
, idd
->vbn
);
2394 if (!vms_write_block (arch
, 1, blk
))
2402 bfd_set_input_error (current
, bfd_get_error ());
2408 /* Add a target for text library. This costs almost nothing and is useful to
2409 read VMS library on the host. */
2411 const bfd_target alpha_vms_lib_txt_vec
=
2413 "vms-libtxt", /* Name. */
2414 bfd_target_unknown_flavour
,
2415 BFD_ENDIAN_UNKNOWN
, /* byteorder */
2416 BFD_ENDIAN_UNKNOWN
, /* header_byteorder */
2417 0, /* Object flags. */
2418 0, /* Sect flags. */
2419 0, /* symbol_leading_char. */
2420 ' ', /* ar_pad_char. */
2421 15, /* ar_max_namelen. */
2422 0, /* match priority. */
2423 TARGET_KEEP_UNUSED_SECTION_SYMBOLS
, /* keep unused section symbols. */
2424 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
2425 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
2426 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
,
2427 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
2428 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
2429 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
,
2430 { /* bfd_check_format. */
2433 _bfd_vms_lib_txt_archive_p
,
2436 { /* bfd_set_format. */
2437 _bfd_bool_bfd_false_error
,
2438 _bfd_bool_bfd_false_error
,
2439 _bfd_bool_bfd_false_error
,
2440 _bfd_bool_bfd_false_error
2442 { /* bfd_write_contents. */
2443 _bfd_bool_bfd_false_error
,
2444 _bfd_bool_bfd_false_error
,
2445 _bfd_bool_bfd_false_error
,
2446 _bfd_bool_bfd_false_error
2448 BFD_JUMP_TABLE_GENERIC (_bfd_generic
),
2449 BFD_JUMP_TABLE_COPY (_bfd_generic
),
2450 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
2451 BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib
),
2452 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols
),
2453 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs
),
2454 BFD_JUMP_TABLE_WRITE (_bfd_nowrite
),
2455 BFD_JUMP_TABLE_LINK (_bfd_nolink
),
2456 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),