1 /* BFD back-end for VMS archive files.
3 Copyright (C) 2010-2020 Free Software Foundation, Inc.
4 Written by Tristan Gingold <gingold@adacore.com>, AdaCore.
6 This file is part of BFD, the Binary File Descriptor library.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
26 #include "safe-ctype.h"
28 #include "libiberty.h"
33 /* The standard VMS disk block size. */
34 #ifndef VMS_BLOCK_SIZE
35 #define VMS_BLOCK_SIZE 512
38 /* Maximum key length (which is also the maximum symbol length in archive). */
39 #define MAX_KEYLEN 128
40 #define MAX_EKEYLEN 1024
46 unsigned char min_char
;
47 unsigned char max_char
;
53 /* Kind of library. Used to filter in archive_p. */
63 /* Back-end private data. */
67 /* Standard tdata for an archive. But we don't use many fields. */
68 struct artdata artdata
;
73 /* Type of the archive. */
76 /* Kind of archive. Summary of its type. */
77 enum vms_lib_kind kind
;
79 /* Total size of the mhd (element header). */
80 unsigned int mhd_size
;
83 unsigned int credat_lo
;
84 unsigned int credat_hi
;
86 /* Vector of modules (archive elements), already sorted. */
87 unsigned int nbr_modules
;
88 struct carsym
*modules
;
91 /* DCX (decompression) data. */
92 unsigned int nbr_dcxsbm
;
93 struct dcxsbm_desc
*dcxsbm
;
96 #define bfd_libdata(bfd) ((struct lib_tdata *)((bfd)->tdata.any))
98 /* End-Of-Text pattern. This is a special record to mark the end of file. */
100 static const unsigned char eotdesc
[] = { 0x03, 0x00, 0x77, 0x00, 0x77, 0x00 };
102 /* Describe the current state of carsym entries while building the archive
103 table of content. Things are simple with Alpha archives as the number
104 of entries is known, but with IA64 archives a entry can make a reference
105 to severals members. Therefore we must be able to extend the table on the
106 fly, but it should be allocated on the bfd - which doesn't support realloc.
107 To reduce the overhead, the table is initially allocated in the BFD's
108 objalloc and extended if necessary on the heap. In the later case, it
109 is finally copied to the BFD's objalloc so that it will automatically be
114 /* The table of content. */
117 /* Number of entries used in the table. */
120 /* Maximum number of entries. */
123 /* 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. */
128 bfd_boolean realloced
;
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
)
247 struct vms_indexdef indexdef
;
253 /* Read the index block. */
254 BFD_ASSERT (sizeof (indexdef
) == VMS_BLOCK_SIZE
);
255 if (!vms_read_block (abfd
, vbn
, &indexdef
))
259 p
= &indexdef
.keys
[0];
260 n
= bfd_getl16 (indexdef
.used
);
261 if (n
> sizeof (indexdef
.keys
))
266 unsigned int idx_vbn
;
267 unsigned int idx_off
;
269 unsigned char *keyname
;
272 /* Extract key length. */
273 if (bfd_libdata (abfd
)->ver
== LBR_MAJORID
)
275 struct vms_idx
*ridx
= (struct vms_idx
*)p
;
277 idx_vbn
= bfd_getl32 (ridx
->rfa
.vbn
);
278 idx_off
= bfd_getl16 (ridx
->rfa
.offset
);
280 keylen
= ridx
->keylen
;
282 keyname
= ridx
->keyname
;
284 else if (bfd_libdata (abfd
)->ver
== LBR_ELFMAJORID
)
286 struct vms_elfidx
*ridx
= (struct vms_elfidx
*)p
;
288 idx_vbn
= bfd_getl32 (ridx
->rfa
.vbn
);
289 idx_off
= bfd_getl16 (ridx
->rfa
.offset
);
291 keylen
= bfd_getl16 (ridx
->keylen
);
293 keyname
= ridx
->keyname
;
302 /* Point to the next index entry. */
303 p
= keyname
+ keylen
;
307 if (idx_off
== RFADEF__C_INDEX
)
309 /* Indirect entry. Recurse. */
310 if (!vms_traverse_index (abfd
, idx_vbn
, cs
))
315 /* Add a new entry. */
318 if (flags
& ELFIDX__SYMESC
)
320 /* Extended key name. */
321 unsigned int noff
= 0;
325 unsigned char kblk
[VMS_BLOCK_SIZE
];
328 if (keylen
!= sizeof (struct vms_kbn
))
331 kbn
= (struct vms_kbn
*)keyname
;
332 keylen
= bfd_getl16 (kbn
->keylen
);
334 name
= bfd_alloc (abfd
, keylen
+ 1);
337 kvbn
= bfd_getl32 (kbn
->rfa
.vbn
);
338 koff
= bfd_getl16 (kbn
->rfa
.offset
);
340 /* Read the key, chunk by chunk. */
345 if (!vms_read_block (abfd
, kvbn
, kblk
))
347 if (koff
> sizeof (kblk
) - sizeof (struct vms_kbn
))
349 kbn
= (struct vms_kbn
*)(kblk
+ koff
);
350 klen
= bfd_getl16 (kbn
->keylen
);
351 if (klen
> sizeof (kblk
) - koff
)
353 kvbn
= bfd_getl32 (kbn
->rfa
.vbn
);
354 koff
= bfd_getl16 (kbn
->rfa
.offset
);
356 if (noff
+ klen
> keylen
)
358 memcpy (name
+ noff
, kbn
+ 1, klen
);
369 /* Usual key name. */
370 name
= bfd_alloc (abfd
, keylen
+ 1);
374 memcpy (name
, keyname
, keylen
);
378 if (flags
& ELFIDX__LISTRFA
)
383 off
= (idx_vbn
- 1) * VMS_BLOCK_SIZE
+ idx_off
;
384 if (bfd_seek (abfd
, off
, SEEK_SET
) != 0
385 || bfd_bread (&lhs
, sizeof (lhs
), abfd
) != sizeof (lhs
))
388 /* These extra entries may cause reallocation of CS. */
389 if (!vms_add_indexes_from_list (abfd
, cs
, name
, &lhs
.ng_g_rfa
))
391 if (!vms_add_indexes_from_list (abfd
, cs
, name
, &lhs
.ng_wk_rfa
))
393 if (!vms_add_indexes_from_list (abfd
, cs
, name
, &lhs
.g_g_rfa
))
395 if (!vms_add_indexes_from_list (abfd
, cs
, name
, &lhs
.g_wk_rfa
))
400 if (!vms_add_index (cs
, name
, idx_vbn
, idx_off
))
409 /* Read index #IDX, which must have NBREL entries. */
411 static struct carsym
*
412 vms_lib_read_index (bfd
*abfd
, int idx
, unsigned int *nbrel
)
419 struct carsym
*csbuf
;
420 struct carsym_mem csm
;
422 /* Read index desription. */
423 if (bfd_seek (abfd
, LHD_IDXDESC
+ idx
* IDD_LENGTH
, SEEK_SET
) != 0
424 || bfd_bread (&idd
, sizeof (idd
), abfd
) != sizeof (idd
))
428 flags
= bfd_getl16 (idd
.flags
);
429 if (!(flags
& IDD__FLAGS_ASCII
)
430 || !(flags
& IDD__FLAGS_VARLENIDX
))
433 filesize
= bfd_get_file_size (abfd
);
437 csm
.realloced
= FALSE
;
440 /* Put an upper bound based on a file full of single char keys.
441 This is to prevent fuzzed binary silliness. It is easily
442 possible to set up loops over file blocks that add syms
444 if (filesize
/ (sizeof (struct vms_rfa
) + 2) <= -1u)
445 csm
.limit
= filesize
/ (sizeof (struct vms_rfa
) + 2);
447 if (csm
.max
> csm
.limit
)
449 if (_bfd_mul_overflow (csm
.max
, sizeof (struct carsym
), &amt
))
451 csm
.idx
= csbuf
= bfd_alloc (abfd
, amt
);
455 /* Note: if the index is empty, there is no block to traverse. */
456 vbn
= bfd_getl32 (idd
.vbn
);
457 if (vbn
!= 0 && !vms_traverse_index (abfd
, vbn
, &csm
))
462 /* Note: in case of error, we can free what was allocated on the
464 bfd_release (abfd
, csbuf
);
470 /* There are more entries than the first estimate. Allocate on
471 the BFD's objalloc. */
472 csbuf
= bfd_alloc (abfd
, csm
.nbr
* sizeof (struct carsym
));
475 memcpy (csbuf
, csm
.idx
, csm
.nbr
* sizeof (struct carsym
));
483 /* Standard function. */
485 static const bfd_target
*
486 _bfd_vms_lib_archive_p (bfd
*abfd
, enum vms_lib_kind kind
)
490 unsigned int majorid
;
491 struct lib_tdata
*tdata_hold
;
492 struct lib_tdata
*tdata
;
494 unsigned int nbr_ent
;
497 if (bfd_bread (&lhd
, sizeof (lhd
), abfd
) != sizeof (lhd
))
499 if (bfd_get_error () != bfd_error_system_call
)
500 bfd_set_error (bfd_error_wrong_format
);
504 /* Check sanity (= magic) number. */
505 sanity
= bfd_getl32 (lhd
.sanity
);
506 if (!(sanity
== LHD_SANEID3
507 || sanity
== LHD_SANEID6
508 || sanity
== LHD_SANEID_DCX
))
510 bfd_set_error (bfd_error_wrong_format
);
513 majorid
= bfd_getl32 (lhd
.majorid
);
515 /* Check archive kind. */
519 if ((lhd
.type
!= LBR__C_TYP_EOBJ
&& lhd
.type
!= LBR__C_TYP_ESHSTB
)
520 || majorid
!= LBR_MAJORID
523 bfd_set_error (bfd_error_wrong_format
);
528 if ((lhd
.type
!= LBR__C_TYP_IOBJ
&& lhd
.type
!= LBR__C_TYP_ISHSTB
)
529 || majorid
!= LBR_ELFMAJORID
532 bfd_set_error (bfd_error_wrong_format
);
537 if ((lhd
.type
!= LBR__C_TYP_TXT
538 && lhd
.type
!= LBR__C_TYP_MLB
539 && lhd
.type
!= LBR__C_TYP_HLP
)
540 || majorid
!= LBR_MAJORID
543 bfd_set_error (bfd_error_wrong_format
);
551 /* Allocate and initialize private data. */
552 tdata_hold
= bfd_libdata (abfd
);
553 tdata
= (struct lib_tdata
*) bfd_zalloc (abfd
, sizeof (struct lib_tdata
));
556 abfd
->tdata
.any
= (void *)tdata
;
557 tdata
->ver
= majorid
;
558 tdata
->mhd_size
= MHD__C_USRDAT
+ lhd
.mhdusz
;
559 tdata
->type
= lhd
.type
;
561 tdata
->credat_lo
= bfd_getl32 (lhd
.credat
+ 0);
562 tdata
->credat_hi
= bfd_getl32 (lhd
.credat
+ 4);
565 tdata
->nbr_modules
= bfd_getl32 (lhd
.modcnt
);
566 tdata
->artdata
.symdef_count
= bfd_getl32 (lhd
.idxcnt
) - tdata
->nbr_modules
;
567 nbr_ent
= tdata
->nbr_modules
;
568 tdata
->modules
= vms_lib_read_index (abfd
, 0, &nbr_ent
);
569 if (tdata
->modules
== NULL
|| nbr_ent
!= tdata
->nbr_modules
)
573 nbr_ent
= tdata
->artdata
.symdef_count
;
574 tdata
->artdata
.symdefs
= vms_lib_read_index (abfd
, 1, &nbr_ent
);
575 if (tdata
->artdata
.symdefs
== NULL
)
577 /* Only IA64 archives may have more entries in the index that what
579 if (nbr_ent
!= tdata
->artdata
.symdef_count
580 && kind
!= vms_lib_ia64
)
582 tdata
->artdata
.symdef_count
= nbr_ent
;
584 tdata
->cache
= bfd_zalloc (abfd
, sizeof (bfd
*) * tdata
->nbr_modules
);
585 if (tdata
->cache
== NULL
)
588 /* Read DCX submaps. */
589 dcxvbn
= bfd_getl32 (lhd
.dcxmapvbn
);
592 unsigned char buf_reclen
[4];
595 struct vms_dcxmap
*map
;
596 unsigned int sbm_off
;
599 if (bfd_seek (abfd
, (dcxvbn
- 1) * VMS_BLOCK_SIZE
, SEEK_SET
) != 0
600 || bfd_bread (buf_reclen
, sizeof (buf_reclen
), abfd
)
601 != sizeof (buf_reclen
))
603 reclen
= bfd_getl32 (buf_reclen
);
604 if (reclen
< sizeof (struct vms_dcxmap
))
606 buf
= _bfd_malloc_and_read (abfd
, reclen
, reclen
);
609 map
= (struct vms_dcxmap
*)buf
;
610 tdata
->nbr_dcxsbm
= bfd_getl16 (map
->nsubs
);
611 sbm_off
= bfd_getl16 (map
->sub0
);
612 tdata
->dcxsbm
= (struct dcxsbm_desc
*)bfd_alloc
613 (abfd
, tdata
->nbr_dcxsbm
* sizeof (struct dcxsbm_desc
));
614 for (i
= 0; i
< tdata
->nbr_dcxsbm
; i
++)
616 struct vms_dcxsbm
*sbm
;
617 struct dcxsbm_desc
*sbmdesc
= &tdata
->dcxsbm
[i
];
618 unsigned int sbm_len
;
625 || reclen
- sbm_off
< sizeof (struct vms_dcxsbm
))
631 sbm
= (struct vms_dcxsbm
*) (buf
+ sbm_off
);
632 sbm_sz
= bfd_getl16 (sbm
->size
);
634 if (sbm_off
> reclen
)
637 sbmdesc
->min_char
= sbm
->min_char
;
638 BFD_ASSERT (sbmdesc
->min_char
== 0);
639 sbmdesc
->max_char
= sbm
->max_char
;
640 sbm_len
= sbmdesc
->max_char
- sbmdesc
->min_char
+ 1;
641 l
= (2 * sbm_len
+ 7) / 8;
642 if (sbm_sz
< sizeof (struct vms_dcxsbm
) + l
+ sbm_len
643 || (tdata
->nbr_dcxsbm
> 1
644 && sbm_sz
< sizeof (struct vms_dcxsbm
) + l
+ 3 * sbm_len
))
646 sbmdesc
->flags
= (unsigned char *)bfd_alloc (abfd
, l
);
647 off
= bfd_getl16 (sbm
->flags
);
651 memcpy (sbmdesc
->flags
, (bfd_byte
*) sbm
+ off
, l
);
652 sbmdesc
->nodes
= (unsigned char *)bfd_alloc (abfd
, 2 * sbm_len
);
653 off
= bfd_getl16 (sbm
->nodes
);
655 || sbm_sz
- off
< 2 * sbm_len
)
657 memcpy (sbmdesc
->nodes
, (bfd_byte
*) sbm
+ off
, 2 * sbm_len
);
658 off
= bfd_getl16 (sbm
->next
);
662 || sbm_sz
- off
< 2 * sbm_len
)
664 /* Read the 'next' array. */
665 sbmdesc
->next
= (unsigned short *) bfd_alloc (abfd
, 2 * sbm_len
);
666 buf1
= (bfd_byte
*) sbm
+ off
;
667 for (j
= 0; j
< sbm_len
; j
++)
668 sbmdesc
->next
[j
] = bfd_getl16 (buf1
+ j
* 2);
672 /* There is no next array if there is only one submap. */
673 BFD_ASSERT (tdata
->nbr_dcxsbm
== 1);
674 sbmdesc
->next
= NULL
;
681 tdata
->nbr_dcxsbm
= 0;
684 /* The map is always present. Also mark shared image library. */
685 abfd
->has_armap
= TRUE
;
686 if (tdata
->type
== LBR__C_TYP_ESHSTB
|| tdata
->type
== LBR__C_TYP_ISHSTB
)
687 abfd
->is_thin_archive
= TRUE
;
692 bfd_release (abfd
, tdata
);
693 abfd
->tdata
.any
= (void *)tdata_hold
;
697 /* Standard function for alpha libraries. */
700 _bfd_vms_lib_alpha_archive_p (bfd
*abfd
)
702 return _bfd_vms_lib_archive_p (abfd
, vms_lib_alpha
);
705 /* Standard function for ia64 libraries. */
708 _bfd_vms_lib_ia64_archive_p (bfd
*abfd
)
710 return _bfd_vms_lib_archive_p (abfd
, vms_lib_ia64
);
713 /* Standard function for text libraries. */
715 static const bfd_target
*
716 _bfd_vms_lib_txt_archive_p (bfd
*abfd
)
718 return _bfd_vms_lib_archive_p (abfd
, vms_lib_txt
);
721 /* Standard bfd function. */
724 _bfd_vms_lib_mkarchive (bfd
*abfd
, enum vms_lib_kind kind
)
726 struct lib_tdata
*tdata
;
728 tdata
= (struct lib_tdata
*) bfd_zalloc (abfd
, sizeof (struct lib_tdata
));
732 abfd
->tdata
.any
= (void *)tdata
;
733 vms_get_time (&tdata
->credat_hi
, &tdata
->credat_lo
);
739 tdata
->ver
= LBR_MAJORID
;
740 tdata
->mhd_size
= offsetof (struct vms_mhd
, pad1
);
741 tdata
->type
= LBR__C_TYP_EOBJ
;
744 tdata
->ver
= LBR_ELFMAJORID
;
745 tdata
->mhd_size
= sizeof (struct vms_mhd
);
746 tdata
->type
= LBR__C_TYP_IOBJ
;
752 tdata
->nbr_modules
= 0;
753 tdata
->artdata
.symdef_count
= 0;
754 tdata
->modules
= NULL
;
755 tdata
->artdata
.symdefs
= NULL
;
762 _bfd_vms_lib_alpha_mkarchive (bfd
*abfd
)
764 return _bfd_vms_lib_mkarchive (abfd
, vms_lib_alpha
);
768 _bfd_vms_lib_ia64_mkarchive (bfd
*abfd
)
770 return _bfd_vms_lib_mkarchive (abfd
, vms_lib_ia64
);
773 /* Find NAME in the symbol index. Return the index. */
776 _bfd_vms_lib_find_symbol (bfd
*abfd
, const char *name
)
778 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
779 carsym
*syms
= tdata
->artdata
.symdefs
;
782 /* Open-coded binary search for speed. */
784 hi
= tdata
->artdata
.symdef_count
- 1;
788 int mid
= lo
+ (hi
- lo
) / 2;
791 diff
= (char)(name
[0] - syms
[mid
].name
[0]);
793 diff
= strcmp (name
, syms
[mid
].name
);
801 return BFD_NO_MORE_SYMBOLS
;
804 /* IO vector for archive member. Need that because members are not linearly
805 stored in archives. */
809 /* Current offset. */
812 /* Length of the module, when known. */
815 /* Current position in the record from bfd_bread point of view (ie, after
816 decompression). 0 means that no data byte have been read, -2 and -1
817 are reserved for the length word. */
819 #define REC_POS_NL -4
820 #define REC_POS_PAD -3
821 #define REC_POS_LEN0 -2
822 #define REC_POS_LEN1 -1
825 unsigned short rec_len
;
826 /* Number of bytes to read in the current record. */
827 unsigned short rec_rem
;
828 /* Offset of the next block. */
830 /* Current *data* offset in the data block. */
831 unsigned short blk_off
;
833 /* Offset of the first block. Extracted from the index. */
834 file_ptr first_block
;
836 /* Initial next_block. Extracted when the MHD is read. */
837 file_ptr init_next_block
;
838 /* Initial blk_off, once the MHD is read. */
839 unsigned short init_blk_off
;
841 /* Used to store any 3 byte record, which could be the EOF pattern. */
842 unsigned char pattern
[4];
845 struct dcxsbm_desc
*dcxsbms
;
846 /* Current submap. */
847 struct dcxsbm_desc
*dcx_sbm
;
848 /* Current offset in the submap. */
849 unsigned int dcx_offset
;
852 /* Compressed buffer. */
853 unsigned char *dcx_buf
;
854 /* Size of the buffer. Used to resize. */
855 unsigned int dcx_max
;
856 /* Number of valid bytes in the buffer. */
857 unsigned int dcx_rlen
;
860 /* Return the current position. */
863 vms_lib_btell (struct bfd
*abfd
)
865 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
869 /* Read the header of the next data block if all bytes of the current block
873 vms_lib_read_block (struct bfd
*abfd
)
875 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
877 if (vec
->blk_off
== DATA__LENGTH
)
879 unsigned char hdr
[DATA__DATA
];
881 /* Read next block. */
882 if (bfd_seek (abfd
->my_archive
, vec
->next_block
, SEEK_SET
) != 0)
884 if (bfd_bread (hdr
, sizeof (hdr
), abfd
->my_archive
) != sizeof (hdr
))
886 vec
->next_block
= (bfd_getl32 (hdr
+ 2) - 1) * VMS_BLOCK_SIZE
;
887 vec
->blk_off
= sizeof (hdr
);
892 /* Read NBYTES from ABFD into BUF if not NULL. If BUF is NULL, bytes are
893 not stored. Read linearly from the library, but handle blocks. This
894 function does not handle records nor EOF. */
897 vms_lib_bread_raw (struct bfd
*abfd
, unsigned char *buf
, file_ptr nbytes
)
899 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
907 /* Be sure the current data block is read. */
908 if (!vms_lib_read_block (abfd
))
911 /* Do not read past the data block, do not read more than requested. */
912 l
= DATA__LENGTH
- vec
->blk_off
;
919 /* Really read into BUF. */
920 if (bfd_bread (buf
, l
, abfd
->my_archive
) != l
)
925 /* Make as if we are reading. */
926 if (bfd_seek (abfd
->my_archive
, l
, SEEK_CUR
) != 0)
939 /* Decompress NBYTES from VEC. Store the bytes into BUF if not NULL. */
942 vms_lib_dcx (struct vms_lib_iovec
*vec
, unsigned char *buf
, file_ptr nbytes
)
944 struct dcxsbm_desc
*sbm
;
950 /* The loop below expect to deliver at least one byte. */
954 /* Get the current state. */
956 offset
= vec
->dcx_offset
;
957 j
= vec
->dcx_pos
& 7;
959 for (i
= vec
->dcx_pos
>> 3; i
< vec
->dcx_rlen
; i
++)
961 unsigned char b
= vec
->dcx_buf
[i
];
967 if (!(sbm
->flags
[offset
>> 3] & (1 << (offset
& 7))))
969 unsigned int n_offset
= sbm
->nodes
[offset
];
972 /* End of buffer. Stay where we are. */
973 vec
->dcx_pos
= (i
<< 3) + j
;
976 vec
->dcx_offset
= offset
;
980 offset
= 2 * n_offset
;
984 unsigned char v
= sbm
->nodes
[offset
];
986 if (sbm
->next
!= NULL
)
987 sbm
= vec
->dcxsbms
+ sbm
->next
[v
];
998 vec
->dcx_pos
= (i
<< 3) + j
+ 1;
999 vec
->dcx_offset
= offset
;
1012 /* Standard IOVEC function. */
1015 vms_lib_bread (struct bfd
*abfd
, void *vbuf
, file_ptr nbytes
)
1017 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1020 unsigned char *buf
= (unsigned char *)vbuf
;
1022 /* Do not read past the end. */
1023 if (vec
->where
>= vec
->file_len
)
1029 if (vec
->rec_rem
== 0)
1031 unsigned char blen
[2];
1033 /* Read record length. */
1034 if (vms_lib_bread_raw (abfd
, blen
, sizeof (blen
)) != sizeof (blen
))
1036 vec
->rec_len
= bfd_getl16 (blen
);
1037 if (bfd_libdata (abfd
->my_archive
)->kind
== vms_lib_txt
)
1039 /* Discard record size and align byte. */
1041 vec
->rec_rem
= vec
->rec_len
;
1045 /* Prepend record size. */
1046 vec
->rec_pos
= REC_POS_LEN0
;
1047 vec
->rec_rem
= (vec
->rec_len
+ 1) & ~1; /* With align byte. */
1049 if (vec
->rec_len
== 3)
1051 /* Possibly end of file. Check the pattern. */
1052 if (vms_lib_bread_raw (abfd
, vec
->pattern
, 4) != 4)
1054 if (!memcmp (vec
->pattern
, eotdesc
+ 2, 3))
1056 /* This is really an EOF. */
1058 vec
->file_len
= vec
->where
;
1063 if (vec
->dcxsbms
!= NULL
)
1065 /* This is a compressed member. */
1069 /* Be sure there is enough room for the expansion. */
1070 len
= (vec
->rec_len
+ 1) & ~1;
1071 if (len
> vec
->dcx_max
)
1073 while (len
> vec
->dcx_max
)
1075 vec
->dcx_buf
= bfd_alloc (abfd
, vec
->dcx_max
);
1076 if (vec
->dcx_buf
== NULL
)
1080 /* Read the compressed record. */
1081 vec
->dcx_rlen
= len
;
1082 if (vec
->rec_len
== 3)
1085 memcpy (vec
->dcx_buf
, vec
->pattern
, 3);
1089 elen
= vms_lib_bread_raw (abfd
, vec
->dcx_buf
, len
);
1094 /* Dummy expansion to get the expanded length. */
1095 vec
->dcx_offset
= 0;
1096 vec
->dcx_sbm
= vec
->dcxsbms
;
1098 elen
= vms_lib_dcx (vec
, NULL
, 0x10000);
1101 vec
->rec_len
= elen
;
1102 vec
->rec_rem
= elen
;
1104 /* Reset the state. */
1105 vec
->dcx_offset
= 0;
1106 vec
->dcx_sbm
= vec
->dcxsbms
;
1110 if (vec
->rec_pos
< 0)
1113 switch (vec
->rec_pos
)
1116 c
= vec
->rec_len
& 0xff;
1117 vec
->rec_pos
= REC_POS_LEN1
;
1120 c
= (vec
->rec_len
>> 8) & 0xff;
1144 if (nbytes
> vec
->rec_rem
)
1145 chunk
= vec
->rec_rem
;
1149 if (vec
->dcxsbms
!= NULL
)
1151 /* Optimize the stat() case: no need to decompress again as we
1153 if (!(buf
== NULL
&& chunk
== vec
->rec_rem
))
1154 chunk
= vms_lib_dcx (vec
, buf
, chunk
);
1158 if (vec
->rec_len
== 3)
1161 memcpy (buf
, vec
->pattern
+ vec
->rec_pos
, chunk
);
1164 chunk
= vms_lib_bread_raw (abfd
, buf
, chunk
);
1172 vec
->rec_pos
+= chunk
;
1173 vec
->rec_rem
-= chunk
;
1175 if (vec
->rec_rem
== 0)
1177 /* End of record reached. */
1178 if (bfd_libdata (abfd
->my_archive
)->kind
== vms_lib_txt
)
1180 if ((vec
->rec_len
& 1) == 1
1181 && vec
->rec_len
!= 3
1182 && vec
->dcxsbms
== NULL
)
1184 /* Eat the pad byte. */
1186 if (vms_lib_bread_raw (abfd
, &pad
, 1) != 1)
1189 vec
->rec_pos
= REC_POS_NL
;
1194 if ((vec
->rec_len
& 1) == 1 && vec
->dcxsbms
!= NULL
)
1196 vec
->rec_pos
= REC_POS_PAD
;
1206 /* Standard function, but we currently only handle the rewind case. */
1209 vms_lib_bseek (struct bfd
*abfd
, file_ptr offset
, int whence
)
1211 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1213 if (whence
== SEEK_SET
&& offset
== 0)
1218 vec
->blk_off
= vec
->init_blk_off
;
1219 vec
->next_block
= vec
->init_next_block
;
1221 if (bfd_seek (abfd
->my_archive
, vec
->first_block
, SEEK_SET
) != 0)
1230 vms_lib_bwrite (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1231 const void *where ATTRIBUTE_UNUSED
,
1232 file_ptr nbytes ATTRIBUTE_UNUSED
)
1238 vms_lib_bclose (struct bfd
*abfd
)
1240 abfd
->iostream
= NULL
;
1245 vms_lib_bflush (struct bfd
*abfd ATTRIBUTE_UNUSED
)
1251 vms_lib_bstat (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1252 struct stat
*sb ATTRIBUTE_UNUSED
)
1254 /* Not supported. */
1259 vms_lib_bmmap (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1260 void *addr ATTRIBUTE_UNUSED
,
1261 bfd_size_type len ATTRIBUTE_UNUSED
,
1262 int prot ATTRIBUTE_UNUSED
,
1263 int flags ATTRIBUTE_UNUSED
,
1264 file_ptr offset ATTRIBUTE_UNUSED
,
1265 void **map_addr ATTRIBUTE_UNUSED
,
1266 bfd_size_type
*map_len ATTRIBUTE_UNUSED
)
1271 static const struct bfd_iovec vms_lib_iovec
= {
1272 &vms_lib_bread
, &vms_lib_bwrite
, &vms_lib_btell
, &vms_lib_bseek
,
1273 &vms_lib_bclose
, &vms_lib_bflush
, &vms_lib_bstat
, &vms_lib_bmmap
1276 /* Open a library module. FILEPOS is the position of the module header. */
1279 vms_lib_bopen (bfd
*el
, file_ptr filepos
)
1281 struct vms_lib_iovec
*vec
;
1282 unsigned char buf
[256];
1283 struct vms_mhd
*mhd
;
1284 struct lib_tdata
*tdata
= bfd_libdata (el
->my_archive
);
1287 /* Allocate and initialized the iovec. */
1288 vec
= bfd_zalloc (el
, sizeof (*vec
));
1293 el
->iovec
= &vms_lib_iovec
;
1295 /* File length is not known. */
1298 /* Read the first data block. */
1299 vec
->next_block
= filepos
& ~(VMS_BLOCK_SIZE
- 1);
1300 vec
->blk_off
= DATA__LENGTH
;
1301 if (!vms_lib_read_block (el
))
1304 /* Prepare to read the first record. */
1305 vec
->blk_off
= filepos
& (VMS_BLOCK_SIZE
- 1);
1307 if (bfd_seek (el
->my_archive
, filepos
, SEEK_SET
) != 0)
1310 /* Read Record length + MHD + align byte. */
1311 len
= tdata
->mhd_size
;
1312 if (vms_lib_bread_raw (el
, buf
, 2) != 2)
1314 if (bfd_getl16 (buf
) != len
)
1316 len
= (len
+ 1) & ~1;
1317 BFD_ASSERT (len
<= sizeof (buf
));
1318 if (vms_lib_bread_raw (el
, buf
, len
) != len
)
1321 /* Get info from mhd. */
1322 mhd
= (struct vms_mhd
*)buf
;
1324 if (mhd
->id
!= MHD__C_MHDID
)
1326 if (len
>= MHD__C_MHDLEN
+ 1)
1327 el
->selective_search
= (mhd
->objstat
& MHD__M_SELSRC
) ? 1 : 0;
1328 el
->mtime
= vms_rawtime_to_time_t (mhd
->datim
);
1329 el
->mtime_set
= TRUE
;
1331 /* Reinit the iovec so that seek() will point to the first record after
1334 vec
->init_blk_off
= vec
->blk_off
;
1335 vec
->init_next_block
= vec
->next_block
;
1336 vec
->first_block
= bfd_tell (el
->my_archive
);
1337 vec
->dcxsbms
= bfd_libdata (el
->my_archive
)->dcxsbm
;
1339 if (vec
->dcxsbms
!= NULL
)
1342 vec
->dcx_max
= 10 * 1024;
1343 vec
->dcx_buf
= bfd_alloc (el
, vec
->dcx_max
);
1345 if (vec
->dcx_buf
== NULL
)
1351 /* Get member MODIDX. Return NULL in case of error. */
1354 _bfd_vms_lib_get_module (bfd
*abfd
, unsigned int modidx
)
1356 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
1364 if (modidx
>= tdata
->nbr_modules
)
1367 /* Already loaded. */
1368 if (tdata
->cache
[modidx
])
1369 return tdata
->cache
[modidx
];
1372 file_off
= tdata
->modules
[modidx
].file_offset
;
1373 if (tdata
->type
!= LBR__C_TYP_IOBJ
)
1375 res
= _bfd_create_empty_archive_element_shell (abfd
);
1379 /* Special reader to deal with data blocks. */
1380 if (!vms_lib_bopen (res
, file_off
))
1386 struct vms_mhd
*mhd
;
1387 struct areltdata
*arelt
;
1389 /* Sanity check. The MHD must be big enough to contain module size. */
1390 if (tdata
->mhd_size
< offsetof (struct vms_mhd
, modsize
) + 4)
1393 /* Read the MHD now. */
1394 if (bfd_seek (abfd
, file_off
, SEEK_SET
) != 0)
1396 if (bfd_bread (buf
, tdata
->mhd_size
, abfd
) != tdata
->mhd_size
)
1399 mhd
= (struct vms_mhd
*) buf
;
1400 if (mhd
->id
!= MHD__C_MHDID
)
1403 res
= _bfd_create_empty_archive_element_shell (abfd
);
1406 arelt
= bfd_zmalloc (sizeof (*arelt
));
1412 res
->arelt_data
= arelt
;
1414 /* Get info from mhd. */
1415 if (tdata
->mhd_size
>= offsetof (struct vms_mhd
, objstat
) + 1)
1416 res
->selective_search
= (mhd
->objstat
& MHD__M_SELSRC
) ? 1 : 0;
1417 res
->mtime
= vms_rawtime_to_time_t (mhd
->datim
);
1418 res
->mtime_set
= TRUE
;
1420 arelt
->parsed_size
= bfd_getl32 (mhd
->modsize
);
1422 /* No need for a special reader as members are stored linearly.
1423 Just skip the MHD. */
1424 res
->origin
= file_off
+ tdata
->mhd_size
;
1428 name
= tdata
->modules
[modidx
].name
;
1429 namelen
= strlen (name
);
1430 newname
= bfd_malloc (namelen
+ 4 + 1);
1431 if (newname
== NULL
)
1436 strcpy (newname
, name
);
1437 switch (tdata
->type
)
1439 case LBR__C_TYP_IOBJ
:
1440 case LBR__C_TYP_EOBJ
:
1441 /* For object archives, append .obj to mimic standard behaviour. */
1442 strcpy (newname
+ namelen
, ".obj");
1447 bfd_set_filename (res
, newname
);
1449 tdata
->cache
[modidx
] = res
;
1454 /* Standard function: get member at IDX. */
1457 _bfd_vms_lib_get_elt_at_index (bfd
*abfd
, symindex symidx
)
1459 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
1461 unsigned int modidx
;
1464 if (symidx
> tdata
->artdata
.symdef_count
)
1466 file_off
= tdata
->artdata
.symdefs
[symidx
].file_offset
;
1469 for (modidx
= 0; modidx
< tdata
->nbr_modules
; modidx
++)
1471 if (tdata
->modules
[modidx
].file_offset
== file_off
)
1474 if (modidx
>= tdata
->nbr_modules
)
1477 return _bfd_vms_lib_get_module (abfd
, modidx
);
1480 /* Elements of an imagelib are stubs. You can get the real image with this
1484 _bfd_vms_lib_get_imagelib_file (bfd
*el
)
1486 bfd
*archive
= el
->my_archive
;
1487 const char *modname
= el
->filename
;
1488 int modlen
= strlen (modname
);
1493 /* Convert module name to lower case and append '.exe'. */
1494 filename
= bfd_alloc (el
, modlen
+ 5);
1495 if (filename
== NULL
)
1497 for (j
= 0; j
< modlen
; j
++)
1498 if (ISALPHA (modname
[j
]))
1499 filename
[j
] = TOLOWER (modname
[j
]);
1501 filename
[j
] = modname
[j
];
1502 memcpy (filename
+ modlen
, ".exe", 5);
1504 filename
= _bfd_append_relative_path (archive
, filename
);
1505 if (filename
== NULL
)
1507 res
= bfd_openr (filename
, NULL
);
1511 /* xgettext:c-format */
1512 _bfd_error_handler(_("could not open shared image '%s' from '%s'"),
1513 filename
, archive
->filename
);
1514 bfd_release (archive
, filename
);
1518 /* FIXME: put it in a cache ? */
1522 /* Standard function. */
1525 _bfd_vms_lib_openr_next_archived_file (bfd
*archive
,
1534 idx
= last_file
->proxy_origin
+ 1;
1536 if (idx
>= bfd_libdata (archive
)->nbr_modules
)
1538 bfd_set_error (bfd_error_no_more_archived_files
);
1542 res
= _bfd_vms_lib_get_module (archive
, idx
);
1545 res
->proxy_origin
= idx
;
1549 /* Standard function. Just compute the length. */
1552 _bfd_vms_lib_generic_stat_arch_elt (bfd
*abfd
, struct stat
*st
)
1554 struct lib_tdata
*tdata
;
1557 if (abfd
->my_archive
== NULL
)
1559 bfd_set_error (bfd_error_invalid_operation
);
1563 tdata
= bfd_libdata (abfd
->my_archive
);
1564 if (tdata
->type
!= LBR__C_TYP_IOBJ
)
1566 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1568 if (vec
->file_len
== (ufile_ptr
)-1)
1570 if (vms_lib_bseek (abfd
, 0, SEEK_SET
) != 0)
1573 /* Compute length. */
1574 while (vms_lib_bread (abfd
, NULL
, 1 << 20) > 0)
1577 st
->st_size
= vec
->file_len
;
1581 st
->st_size
= ((struct areltdata
*)abfd
->arelt_data
)->parsed_size
;
1584 if (abfd
->mtime_set
)
1585 st
->st_mtime
= abfd
->mtime
;
1595 /* Internal representation of an index entry. */
1599 /* Corresponding archive member. */
1602 /* Number of reference to this entry. */
1605 /* Length of the key. */
1606 unsigned short namlen
;
1612 /* Used to sort index entries. */
1615 lib_index_cmp (const void *lv
, const void *rv
)
1617 const struct lib_index
*l
= lv
;
1618 const struct lib_index
*r
= rv
;
1620 return strcmp (l
->name
, r
->name
);
1623 /* Maximum number of index blocks level. */
1625 #define MAX_LEVEL 10
1627 /* Get the size of an index entry. */
1630 get_idxlen (struct lib_index
*idx
, bfd_boolean is_elfidx
)
1634 /* 9 is the size of struct vms_elfidx without keyname. */
1635 if (idx
->namlen
> MAX_KEYLEN
)
1636 return 9 + sizeof (struct vms_kbn
);
1638 return 9 + idx
->namlen
;
1642 /* 7 is the size of struct vms_idx without keyname. */
1643 return 7 + idx
->namlen
;
1647 /* Write the index composed by NBR symbols contained in IDX.
1648 VBN is the first vbn to be used, and will contain on return the last vbn.
1649 Can be called with ABFD set to NULL just to size the index.
1650 If not null, TOPVBN will be assigned to the vbn of the root index tree.
1651 IS_ELFIDX is true for elfidx (ie ia64) indexes layout.
1652 Return TRUE on success. */
1655 vms_write_index (bfd
*abfd
,
1656 struct lib_index
*idx
, unsigned int nbr
, unsigned int *vbn
,
1657 unsigned int *topvbn
, bfd_boolean is_elfidx
)
1659 /* The index is organized as a tree. This function implements a naive
1660 algorithm to balance the tree: it fills the leaves, and create a new
1661 branch when all upper leaves and branches are full. We only keep in
1662 memory a path to the current leaf. */
1666 /* Disk blocks for the current path. */
1667 struct vms_indexdef
*rblk
[MAX_LEVEL
];
1668 /* Info on the current blocks. */
1671 unsigned int vbn
; /* VBN of the block. */
1672 /* The last entry is identified so that it could be copied to the
1674 unsigned short len
; /* Length up to the last entry. */
1675 unsigned short lastlen
; /* Length of the last entry. */
1678 /* The kbn blocks are used to store long symbol names. */
1679 unsigned int kbn_sz
= 0; /* Number of bytes available in the kbn block. */
1680 unsigned int kbn_vbn
= 0; /* VBN of the kbn block. */
1681 unsigned char *kbn_blk
= NULL
; /* Contents of the kbn block. */
1685 /* No entries. Very easy to handle. */
1693 /* Sort the index the first time this function is called. */
1694 qsort (idx
, nbr
, sizeof (struct lib_index
), lib_index_cmp
);
1697 /* Allocate first index block. */
1700 rblk
[0] = bfd_zmalloc (sizeof (struct vms_indexdef
));
1701 blk
[0].vbn
= (*vbn
)++;
1705 for (i
= 0; i
< nbr
; i
++, idx
++)
1707 unsigned int idxlen
;
1709 unsigned int key_vbn
= 0;
1710 unsigned int key_off
= 0;
1712 idxlen
= get_idxlen (idx
, is_elfidx
);
1714 if (is_elfidx
&& idx
->namlen
> MAX_KEYLEN
)
1716 /* If the key (ie name) is too long, write it in the kbn block. */
1717 unsigned int kl
= idx
->namlen
;
1718 unsigned int kl_chunk
;
1719 const char *key
= idx
->name
;
1721 /* Write the key in the kbn, chunk after chunk. */
1724 if (kbn_sz
< sizeof (struct vms_kbn
))
1726 /* Not enough room in the kbn block. */
1729 /* Write it to the disk (if there is one). */
1732 if (!vms_write_block (abfd
, kbn_vbn
, kbn_blk
))
1737 kbn_blk
= bfd_malloc (VMS_BLOCK_SIZE
);
1738 if (kbn_blk
== NULL
)
1741 *(unsigned short *)kbn_blk
= 0;
1743 /* Allocate a new block for the keys. */
1745 kbn_sz
= VMS_BLOCK_SIZE
- 2;
1747 /* Size of the chunk written to the current key block. */
1748 if (kl
+ sizeof (struct vms_kbn
) > kbn_sz
)
1749 kl_chunk
= kbn_sz
- sizeof (struct vms_kbn
);
1753 if (kbn_blk
!= NULL
)
1755 struct vms_kbn
*kbn
;
1757 kbn
= (struct vms_kbn
*)(kbn_blk
+ VMS_BLOCK_SIZE
- kbn_sz
);
1761 /* Save the rfa of the first chunk. */
1763 key_off
= VMS_BLOCK_SIZE
- kbn_sz
;
1766 bfd_putl16 (kl_chunk
, kbn
->keylen
);
1769 /* No next chunk. */
1770 bfd_putl32 (0, kbn
->rfa
.vbn
);
1771 bfd_putl16 (0, kbn
->rfa
.offset
);
1775 /* Next chunk will be at the start of the next block. */
1776 bfd_putl32 (*vbn
, kbn
->rfa
.vbn
);
1777 bfd_putl16 (2, kbn
->rfa
.offset
);
1779 memcpy ((char *)(kbn
+ 1), key
, kl_chunk
);
1783 kl_chunk
= (kl_chunk
+ 1) & ~1; /* Always align. */
1784 kbn_sz
-= kl_chunk
+ sizeof (struct vms_kbn
);
1789 /* Check if a block might overflow. In this case we will flush this
1790 block and all the blocks below it. */
1791 for (j
= 0; j
< level
; j
++)
1792 if (blk
[j
].len
+ blk
[j
].lastlen
+ idxlen
> INDEXDEF__BLKSIZ
)
1795 for (j
= 0; j
< level
; j
++)
1799 /* There is not enough room to write the new entry in this
1800 block or in a parent block. */
1804 BFD_ASSERT (level
< MAX_LEVEL
);
1806 /* Need to create a parent. */
1809 rblk
[level
] = bfd_zmalloc (sizeof (struct vms_indexdef
));
1810 bfd_putl32 (*vbn
, rblk
[j
]->parent
);
1812 blk
[level
].vbn
= (*vbn
)++;
1814 blk
[level
].lastlen
= blk
[j
].lastlen
;
1819 /* Update parent block: write the last entry from the current
1823 struct vms_rfa
*rfa
;
1825 /* Pointer to the last entry in parent block. */
1826 rfa
= (struct vms_rfa
*)(rblk
[j
+ 1]->keys
+ blk
[j
+ 1].len
);
1828 /* Copy the whole entry. */
1829 BFD_ASSERT (blk
[j
+ 1].lastlen
== blk
[j
].lastlen
);
1830 memcpy (rfa
, rblk
[j
]->keys
+ blk
[j
].len
, blk
[j
].lastlen
);
1831 /* Fix the entry (which in always the first field of an
1833 bfd_putl32 (blk
[j
].vbn
, rfa
->vbn
);
1834 bfd_putl16 (RFADEF__C_INDEX
, rfa
->offset
);
1839 /* And allocate it. Do it only on the block that won't be
1840 flushed (so that the parent of the parent can be
1842 blk
[j
+ 1].len
+= blk
[j
+ 1].lastlen
;
1843 blk
[j
+ 1].lastlen
= 0;
1846 /* Write this block on the disk. */
1849 bfd_putl16 (blk
[j
].len
+ blk
[j
].lastlen
, rblk
[j
]->used
);
1850 if (!vms_write_block (abfd
, blk
[j
].vbn
, rblk
[j
]))
1854 /* Reset this block. */
1857 blk
[j
].vbn
= (*vbn
)++;
1860 /* Append it to the block. */
1863 /* Keep the previous last entry. */
1864 blk
[j
].len
+= blk
[j
].lastlen
;
1868 struct vms_rfa
*rfa
;
1870 rfa
= (struct vms_rfa
*)(rblk
[j
]->keys
+ blk
[j
].len
);
1871 bfd_putl32 ((idx
->abfd
->proxy_origin
/ VMS_BLOCK_SIZE
) + 1,
1874 ((idx
->abfd
->proxy_origin
% VMS_BLOCK_SIZE
)
1875 + (is_elfidx
? 0 : DATA__DATA
),
1880 /* Use elfidx format. */
1881 struct vms_elfidx
*en
= (struct vms_elfidx
*)rfa
;
1886 /* Long symbol name. */
1887 struct vms_kbn
*k
= (struct vms_kbn
*)(en
->keyname
);
1888 bfd_putl16 (sizeof (struct vms_kbn
), en
->keylen
);
1889 bfd_putl16 (idx
->namlen
, k
->keylen
);
1890 bfd_putl32 (key_vbn
, k
->rfa
.vbn
);
1891 bfd_putl16 (key_off
, k
->rfa
.offset
);
1892 en
->flags
|= ELFIDX__SYMESC
;
1896 bfd_putl16 (idx
->namlen
, en
->keylen
);
1897 memcpy (en
->keyname
, idx
->name
, idx
->namlen
);
1902 /* Use idx format. */
1903 struct vms_idx
*en
= (struct vms_idx
*)rfa
;
1904 en
->keylen
= idx
->namlen
;
1905 memcpy (en
->keyname
, idx
->name
, idx
->namlen
);
1909 /* The last added key can now be the last one all blocks in the
1911 blk
[j
].lastlen
= idxlen
;
1915 /* Save VBN of the root. */
1917 *topvbn
= blk
[level
- 1].vbn
;
1923 for (j
= 1; j
< level
; j
++)
1925 /* Update parent block: write the new entry. */
1928 struct vms_rfa
*rfa
;
1930 en
= rblk
[j
- 1]->keys
+ blk
[j
- 1].len
;
1931 par
= rblk
[j
]->keys
+ blk
[j
].len
;
1932 BFD_ASSERT (blk
[j
].lastlen
== blk
[j
- 1].lastlen
);
1933 memcpy (par
, en
, blk
[j
- 1].lastlen
);
1934 rfa
= (struct vms_rfa
*)par
;
1935 bfd_putl32 (blk
[j
- 1].vbn
, rfa
->vbn
);
1936 bfd_putl16 (RFADEF__C_INDEX
, rfa
->offset
);
1939 for (j
= 0; j
< level
; j
++)
1941 /* Write this block on the disk. */
1942 bfd_putl16 (blk
[j
].len
+ blk
[j
].lastlen
, rblk
[j
]->used
);
1943 if (!vms_write_block (abfd
, blk
[j
].vbn
, rblk
[j
]))
1949 /* Write the last kbn (if any). */
1952 if (!vms_write_block (abfd
, kbn_vbn
, kbn_blk
))
1960 /* Append data to the data block DATA. Force write if PAD is true. */
1963 vms_write_data_block (bfd
*arch
, struct vms_datadef
*data
, file_ptr
*off
,
1964 const unsigned char *buf
, unsigned int len
, int pad
)
1966 while (len
> 0 || pad
)
1968 unsigned int doff
= *off
& (VMS_BLOCK_SIZE
- 1);
1969 unsigned int remlen
= (DATA__LENGTH
- DATA__DATA
) - doff
;
1972 l
= (len
> remlen
) ? remlen
: len
;
1973 memcpy (data
->data
+ doff
, buf
, l
);
1979 if (doff
== (DATA__LENGTH
- DATA__DATA
) || (len
== 0 && pad
))
1983 bfd_putl32 ((*off
/ VMS_BLOCK_SIZE
) + 2, data
->link
);
1985 if (bfd_bwrite (data
, sizeof (*data
), arch
) != sizeof (*data
))
1988 *off
+= DATA__LENGTH
- doff
;
1997 /* Build the symbols index. */
2000 _bfd_vms_lib_build_map (unsigned int nbr_modules
,
2001 struct lib_index
*modules
,
2002 unsigned int *res_cnt
,
2003 struct lib_index
**res
)
2006 asymbol
**syms
= NULL
;
2008 struct lib_index
*map
= NULL
;
2009 unsigned int map_max
= 1024; /* Fine initial default. */
2010 unsigned int map_count
= 0;
2012 map
= (struct lib_index
*) bfd_malloc (map_max
* sizeof (struct lib_index
));
2016 /* Gather symbols. */
2017 for (i
= 0; i
< nbr_modules
; i
++)
2022 bfd
*current
= modules
[i
].abfd
;
2024 if ((bfd_get_file_flags (current
) & HAS_SYMS
) == 0)
2027 storage
= bfd_get_symtab_upper_bound (current
);
2033 if (storage
> syms_max
)
2038 syms
= (asymbol
**) bfd_malloc (syms_max
);
2042 symcount
= bfd_canonicalize_symtab (current
, syms
);
2046 /* Now map over all the symbols, picking out the ones we
2048 for (src_count
= 0; src_count
< symcount
; src_count
++)
2050 flagword flags
= (syms
[src_count
])->flags
;
2051 asection
*sec
= syms
[src_count
]->section
;
2053 if ((flags
& BSF_GLOBAL
2055 || flags
& BSF_INDIRECT
2056 || bfd_is_com_section (sec
))
2057 && ! bfd_is_und_section (sec
))
2059 struct lib_index
*new_map
;
2061 /* This symbol will go into the archive header. */
2062 if (map_count
== map_max
)
2065 new_map
= (struct lib_index
*)
2066 bfd_realloc (map
, map_max
* sizeof (struct lib_index
));
2067 if (new_map
== NULL
)
2072 map
[map_count
].abfd
= current
;
2073 map
[map_count
].namlen
= strlen (syms
[src_count
]->name
);
2074 map
[map_count
].name
= syms
[src_count
]->name
;
2082 *res_cnt
= map_count
;
2094 /* Do the hard work: write an archive on the disk. */
2097 _bfd_vms_lib_write_archive_contents (bfd
*arch
)
2100 unsigned int nbr_modules
;
2101 struct lib_index
*modules
;
2102 unsigned int nbr_symbols
;
2103 struct lib_index
*symbols
;
2104 struct lib_tdata
*tdata
= bfd_libdata (arch
);
2107 unsigned int nbr_mod_iblk
;
2108 unsigned int nbr_sym_iblk
;
2110 unsigned int mod_idx_vbn
;
2111 unsigned int sym_idx_vbn
;
2112 bfd_boolean is_elfidx
= tdata
->kind
== vms_lib_ia64
;
2113 unsigned int max_keylen
= is_elfidx
? MAX_EKEYLEN
: MAX_KEYLEN
;
2115 /* Count the number of modules (and do a first sanity check). */
2117 for (current
= arch
->archive_head
;
2119 current
= current
->archive_next
)
2121 /* This check is checking the bfds for the objects we're reading
2122 from (which are usually either an object file or archive on
2123 disk), not the archive entries we're writing to. We don't
2124 actually create bfds for the archive members, we just copy
2125 them byte-wise when we write out the archive. */
2126 if (bfd_write_p (current
) || !bfd_check_format (current
, bfd_object
))
2128 bfd_set_error (bfd_error_invalid_operation
);
2135 /* Build the modules list. */
2136 BFD_ASSERT (tdata
->modules
== NULL
);
2137 modules
= bfd_alloc (arch
, nbr_modules
* sizeof (struct lib_index
));
2138 if (modules
== NULL
)
2141 for (current
= arch
->archive_head
, i
= 0;
2143 current
= current
->archive_next
, i
++)
2147 modules
[i
].abfd
= current
;
2148 modules
[i
].name
= vms_get_module_name (current
->filename
, FALSE
);
2151 /* FIXME: silently truncate long names ? */
2152 nl
= strlen (modules
[i
].name
);
2153 modules
[i
].namlen
= (nl
> max_keylen
? max_keylen
: nl
);
2156 /* Create the module index. */
2158 if (!vms_write_index (NULL
, modules
, nbr_modules
, &vbn
, NULL
, is_elfidx
))
2162 /* Create symbol index. */
2163 if (!_bfd_vms_lib_build_map (nbr_modules
, modules
, &nbr_symbols
, &symbols
))
2167 if (!vms_write_index (NULL
, symbols
, nbr_symbols
, &vbn
, NULL
, is_elfidx
))
2171 /* Write modules and remember their position. */
2172 off
= (1 + nbr_mod_iblk
+ nbr_sym_iblk
) * VMS_BLOCK_SIZE
;
2174 if (bfd_seek (arch
, off
, SEEK_SET
) != 0)
2177 for (i
= 0; i
< nbr_modules
; i
++)
2179 struct vms_datadef data
;
2180 unsigned char blk
[VMS_BLOCK_SIZE
];
2181 struct vms_mhd
*mhd
;
2184 current
= modules
[i
].abfd
;
2185 current
->proxy_origin
= off
;
2191 /* Write the MHD as a record (ie, size first). */
2193 bfd_putl16 (tdata
->mhd_size
, blk
);
2195 mhd
= (struct vms_mhd
*)(blk
+ sz
);
2196 memset (mhd
, 0, sizeof (struct vms_mhd
));
2198 mhd
->id
= MHD__C_MHDID
;
2200 memcpy (mhd
->objid
, "V1.0", 4);
2201 bfd_putl32 (modules
[i
].ref
, mhd
->refcnt
);
2204 sz
+= tdata
->mhd_size
;
2207 /* Rewind the member to be put into the archive. */
2208 if (bfd_seek (current
, 0, SEEK_SET
) != 0)
2211 /* Copy the member into the archive. */
2214 unsigned int modsize
= 0;
2216 file_ptr off_hdr
= off
;
2218 /* Read to complete the first block. */
2219 amt
= bfd_bread (blk
+ sz
, VMS_BLOCK_SIZE
- sz
, current
);
2220 if (amt
== (bfd_size_type
)-1)
2223 if (amt
< VMS_BLOCK_SIZE
- sz
)
2225 /* The member size is less than a block. Pad the block. */
2226 memset (blk
+ sz
+ amt
, 0, VMS_BLOCK_SIZE
- sz
- amt
);
2228 bfd_putl32 (modsize
, mhd
->modsize
);
2230 /* Write the first block (which contains an mhd). */
2231 if (bfd_bwrite (blk
, VMS_BLOCK_SIZE
, arch
) != VMS_BLOCK_SIZE
)
2233 off
+= VMS_BLOCK_SIZE
;
2235 if (amt
== VMS_BLOCK_SIZE
- sz
)
2237 /* Copy the remaining. */
2238 char buffer
[DEFAULT_BUFFERSIZE
];
2242 amt
= bfd_bread (buffer
, sizeof (buffer
), current
);
2243 if (amt
== (bfd_size_type
)-1)
2248 if (amt
!= sizeof (buffer
))
2250 /* Clear the padding. */
2251 memset (buffer
+ amt
, 0, sizeof (buffer
) - amt
);
2252 amt
= (amt
+ VMS_BLOCK_SIZE
) & ~(VMS_BLOCK_SIZE
- 1);
2254 if (bfd_bwrite (buffer
, amt
, arch
) != amt
)
2259 /* Now that the size is known, write the first block (again). */
2260 bfd_putl32 (modsize
, mhd
->modsize
);
2261 if (bfd_seek (arch
, off_hdr
, SEEK_SET
) != 0
2262 || bfd_bwrite (blk
, VMS_BLOCK_SIZE
, arch
) != VMS_BLOCK_SIZE
)
2264 if (bfd_seek (arch
, off
, SEEK_SET
) != 0)
2270 /* Write the MHD. */
2271 if (vms_write_data_block (arch
, &data
, &off
, blk
, sz
, 0) < 0)
2274 /* Write the member. */
2277 sz
= bfd_bread (blk
, sizeof (blk
), current
);
2280 if (vms_write_data_block (arch
, &data
, &off
, blk
, sz
, 0) < 0)
2284 /* Write the end of module marker. */
2285 if (vms_write_data_block (arch
, &data
, &off
,
2286 eotdesc
, sizeof (eotdesc
), 1) < 0)
2291 /* Write the indexes. */
2293 if (!vms_write_index (arch
, modules
, nbr_modules
, &vbn
, &mod_idx_vbn
,
2296 if (!vms_write_index (arch
, symbols
, nbr_symbols
, &vbn
, &sym_idx_vbn
,
2300 /* Write libary header. */
2302 unsigned char blk
[VMS_BLOCK_SIZE
];
2303 struct vms_lhd
*lhd
= (struct vms_lhd
*)blk
;
2304 struct vms_idd
*idd
= (struct vms_idd
*)(blk
+ sizeof (*lhd
));
2305 unsigned int idd_flags
;
2306 unsigned int saneid
;
2308 memset (blk
, 0, sizeof (blk
));
2310 lhd
->type
= tdata
->type
;
2312 switch (tdata
->kind
)
2315 saneid
= LHD_SANEID3
;
2318 saneid
= LHD_SANEID6
;
2323 bfd_putl32 (saneid
, lhd
->sanity
);
2324 bfd_putl16 (tdata
->ver
, lhd
->majorid
);
2325 bfd_putl16 (0, lhd
->minorid
);
2326 snprintf ((char *)lhd
->lbrver
+ 1, sizeof (lhd
->lbrver
) - 1,
2328 (unsigned)(BFD_VERSION
/ 100000000UL),
2329 (unsigned)(BFD_VERSION
/ 1000000UL) % 100,
2330 (unsigned)(BFD_VERSION
/ 10000UL) % 100);
2331 lhd
->lbrver
[sizeof (lhd
->lbrver
) - 1] = 0;
2332 lhd
->lbrver
[0] = strlen ((char *)lhd
->lbrver
+ 1);
2334 bfd_putl32 (tdata
->credat_lo
, lhd
->credat
+ 0);
2335 bfd_putl32 (tdata
->credat_hi
, lhd
->credat
+ 4);
2336 vms_raw_get_time (lhd
->updtim
);
2338 lhd
->mhdusz
= tdata
->mhd_size
- MHD__C_USRDAT
;
2340 bfd_putl32 (nbr_modules
+ nbr_symbols
, lhd
->idxcnt
);
2341 bfd_putl32 (nbr_modules
, lhd
->modcnt
);
2342 bfd_putl32 (nbr_modules
, lhd
->modhdrs
);
2344 /* Number of blocks for index. */
2345 bfd_putl32 (nbr_mod_iblk
+ nbr_sym_iblk
, lhd
->idxblks
);
2346 bfd_putl32 (vbn
- 1, lhd
->hipreal
);
2347 bfd_putl32 (vbn
- 1, lhd
->hiprusd
);
2349 /* VBN of the next free block. */
2350 bfd_putl32 ((off
/ VMS_BLOCK_SIZE
) + 1, lhd
->nextvbn
);
2351 bfd_putl32 ((off
/ VMS_BLOCK_SIZE
) + 1, lhd
->nextrfa
+ 0);
2352 bfd_putl16 (0, lhd
->nextrfa
+ 4);
2354 /* First index (modules name). */
2355 idd_flags
= IDD__FLAGS_ASCII
| IDD__FLAGS_VARLENIDX
2356 | IDD__FLAGS_NOCASECMP
| IDD__FLAGS_NOCASENTR
;
2357 bfd_putl16 (idd_flags
, idd
->flags
);
2358 bfd_putl16 (max_keylen
+ 1, idd
->keylen
);
2359 bfd_putl16 (mod_idx_vbn
, idd
->vbn
);
2362 /* Second index (symbols name). */
2363 bfd_putl16 (idd_flags
, idd
->flags
);
2364 bfd_putl16 (max_keylen
+ 1, idd
->keylen
);
2365 bfd_putl16 (sym_idx_vbn
, idd
->vbn
);
2368 if (!vms_write_block (arch
, 1, blk
))
2375 bfd_set_input_error (current
, bfd_get_error ());
2379 /* Add a target for text library. This costs almost nothing and is useful to
2380 read VMS library on the host. */
2382 const bfd_target alpha_vms_lib_txt_vec
=
2384 "vms-libtxt", /* Name. */
2385 bfd_target_unknown_flavour
,
2386 BFD_ENDIAN_UNKNOWN
, /* byteorder */
2387 BFD_ENDIAN_UNKNOWN
, /* header_byteorder */
2388 0, /* Object flags. */
2389 0, /* Sect flags. */
2390 0, /* symbol_leading_char. */
2391 ' ', /* ar_pad_char. */
2392 15, /* ar_max_namelen. */
2393 0, /* match priority. */
2394 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
2395 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
2396 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
,
2397 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
2398 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
2399 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
,
2400 { /* bfd_check_format. */
2403 _bfd_vms_lib_txt_archive_p
,
2406 { /* bfd_set_format. */
2407 _bfd_bool_bfd_false_error
,
2408 _bfd_bool_bfd_false_error
,
2409 _bfd_bool_bfd_false_error
,
2410 _bfd_bool_bfd_false_error
2412 { /* bfd_write_contents. */
2413 _bfd_bool_bfd_false_error
,
2414 _bfd_bool_bfd_false_error
,
2415 _bfd_bool_bfd_false_error
,
2416 _bfd_bool_bfd_false_error
2418 BFD_JUMP_TABLE_GENERIC (_bfd_generic
),
2419 BFD_JUMP_TABLE_COPY (_bfd_generic
),
2420 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
2421 BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib
),
2422 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols
),
2423 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs
),
2424 BFD_JUMP_TABLE_WRITE (_bfd_nowrite
),
2425 BFD_JUMP_TABLE_LINK (_bfd_nolink
),
2426 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),