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_mem csm
;
421 /* Read index desription. */
422 if (bfd_seek (abfd
, LHD_IDXDESC
+ idx
* IDD_LENGTH
, SEEK_SET
) != 0
423 || bfd_bread (&idd
, sizeof (idd
), abfd
) != sizeof (idd
))
427 flags
= bfd_getl16 (idd
.flags
);
428 if (!(flags
& IDD__FLAGS_ASCII
)
429 || !(flags
& IDD__FLAGS_VARLENIDX
))
432 filesize
= bfd_get_file_size (abfd
);
436 csm
.realloced
= FALSE
;
439 /* Put an upper bound based on a file full of single char keys.
440 This is to prevent fuzzed binary silliness. It is easily
441 possible to set up loops over file blocks that add syms
443 if (filesize
/ (sizeof (struct vms_rfa
) + 2) <= -1u)
444 csm
.limit
= filesize
/ (sizeof (struct vms_rfa
) + 2);
446 if (csm
.max
> csm
.limit
)
448 if (_bfd_mul_overflow (csm
.max
, sizeof (struct carsym
), &amt
))
450 csm
.idx
= bfd_alloc (abfd
, amt
);
454 /* Note: if the index is empty, there is no block to traverse. */
455 vbn
= bfd_getl32 (idd
.vbn
);
456 if (vbn
!= 0 && !vms_traverse_index (abfd
, vbn
, &csm
))
458 if (csm
.realloced
&& csm
.idx
!= NULL
)
461 /* Note: in case of error, we can free what was allocated on the
463 bfd_release (abfd
, csm
.idx
);
469 /* There are more entries than the first estimate. Allocate on
470 the BFD's objalloc. */
471 struct carsym
*csbuf
;
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
))
627 sbm
= (struct vms_dcxsbm
*) (buf
+ sbm_off
);
628 sbm_sz
= bfd_getl16 (sbm
->size
);
630 if (sbm_off
> reclen
)
633 sbmdesc
->min_char
= sbm
->min_char
;
634 BFD_ASSERT (sbmdesc
->min_char
== 0);
635 sbmdesc
->max_char
= sbm
->max_char
;
636 sbm_len
= sbmdesc
->max_char
- sbmdesc
->min_char
+ 1;
637 l
= (2 * sbm_len
+ 7) / 8;
638 if (sbm_sz
< sizeof (struct vms_dcxsbm
) + l
+ sbm_len
639 || (tdata
->nbr_dcxsbm
> 1
640 && sbm_sz
< sizeof (struct vms_dcxsbm
) + l
+ 3 * sbm_len
))
642 sbmdesc
->flags
= (unsigned char *)bfd_alloc (abfd
, l
);
643 off
= bfd_getl16 (sbm
->flags
);
647 memcpy (sbmdesc
->flags
, (bfd_byte
*) sbm
+ off
, l
);
648 sbmdesc
->nodes
= (unsigned char *)bfd_alloc (abfd
, 2 * sbm_len
);
649 off
= bfd_getl16 (sbm
->nodes
);
651 || sbm_sz
- off
< 2 * sbm_len
)
653 memcpy (sbmdesc
->nodes
, (bfd_byte
*) sbm
+ off
, 2 * sbm_len
);
654 off
= bfd_getl16 (sbm
->next
);
658 || sbm_sz
- off
< 2 * sbm_len
)
660 /* Read the 'next' array. */
661 sbmdesc
->next
= (unsigned short *) bfd_alloc (abfd
, 2 * sbm_len
);
662 buf1
= (bfd_byte
*) sbm
+ off
;
663 for (j
= 0; j
< sbm_len
; j
++)
664 sbmdesc
->next
[j
] = bfd_getl16 (buf1
+ j
* 2);
668 /* There is no next array if there is only one submap. */
669 BFD_ASSERT (tdata
->nbr_dcxsbm
== 1);
670 sbmdesc
->next
= NULL
;
677 tdata
->nbr_dcxsbm
= 0;
680 /* The map is always present. Also mark shared image library. */
681 abfd
->has_armap
= TRUE
;
682 if (tdata
->type
== LBR__C_TYP_ESHSTB
|| tdata
->type
== LBR__C_TYP_ISHSTB
)
683 abfd
->is_thin_archive
= TRUE
;
688 bfd_release (abfd
, tdata
);
689 abfd
->tdata
.any
= (void *)tdata_hold
;
693 /* Standard function for alpha libraries. */
696 _bfd_vms_lib_alpha_archive_p (bfd
*abfd
)
698 return _bfd_vms_lib_archive_p (abfd
, vms_lib_alpha
);
701 /* Standard function for ia64 libraries. */
704 _bfd_vms_lib_ia64_archive_p (bfd
*abfd
)
706 return _bfd_vms_lib_archive_p (abfd
, vms_lib_ia64
);
709 /* Standard function for text libraries. */
711 static const bfd_target
*
712 _bfd_vms_lib_txt_archive_p (bfd
*abfd
)
714 return _bfd_vms_lib_archive_p (abfd
, vms_lib_txt
);
717 /* Standard bfd function. */
720 _bfd_vms_lib_mkarchive (bfd
*abfd
, enum vms_lib_kind kind
)
722 struct lib_tdata
*tdata
;
724 tdata
= (struct lib_tdata
*) bfd_zalloc (abfd
, sizeof (struct lib_tdata
));
728 abfd
->tdata
.any
= (void *)tdata
;
729 vms_get_time (&tdata
->credat_hi
, &tdata
->credat_lo
);
735 tdata
->ver
= LBR_MAJORID
;
736 tdata
->mhd_size
= offsetof (struct vms_mhd
, pad1
);
737 tdata
->type
= LBR__C_TYP_EOBJ
;
740 tdata
->ver
= LBR_ELFMAJORID
;
741 tdata
->mhd_size
= sizeof (struct vms_mhd
);
742 tdata
->type
= LBR__C_TYP_IOBJ
;
748 tdata
->nbr_modules
= 0;
749 tdata
->artdata
.symdef_count
= 0;
750 tdata
->modules
= NULL
;
751 tdata
->artdata
.symdefs
= NULL
;
758 _bfd_vms_lib_alpha_mkarchive (bfd
*abfd
)
760 return _bfd_vms_lib_mkarchive (abfd
, vms_lib_alpha
);
764 _bfd_vms_lib_ia64_mkarchive (bfd
*abfd
)
766 return _bfd_vms_lib_mkarchive (abfd
, vms_lib_ia64
);
769 /* Find NAME in the symbol index. Return the index. */
772 _bfd_vms_lib_find_symbol (bfd
*abfd
, const char *name
)
774 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
775 carsym
*syms
= tdata
->artdata
.symdefs
;
778 /* Open-coded binary search for speed. */
780 hi
= tdata
->artdata
.symdef_count
- 1;
784 int mid
= lo
+ (hi
- lo
) / 2;
787 diff
= (char)(name
[0] - syms
[mid
].name
[0]);
789 diff
= strcmp (name
, syms
[mid
].name
);
797 return BFD_NO_MORE_SYMBOLS
;
800 /* IO vector for archive member. Need that because members are not linearly
801 stored in archives. */
805 /* Current offset. */
808 /* Length of the module, when known. */
811 /* Current position in the record from bfd_bread point of view (ie, after
812 decompression). 0 means that no data byte have been read, -2 and -1
813 are reserved for the length word. */
815 #define REC_POS_NL -4
816 #define REC_POS_PAD -3
817 #define REC_POS_LEN0 -2
818 #define REC_POS_LEN1 -1
821 unsigned short rec_len
;
822 /* Number of bytes to read in the current record. */
823 unsigned short rec_rem
;
824 /* Offset of the next block. */
826 /* Current *data* offset in the data block. */
827 unsigned short blk_off
;
829 /* Offset of the first block. Extracted from the index. */
830 file_ptr first_block
;
832 /* Initial next_block. Extracted when the MHD is read. */
833 file_ptr init_next_block
;
834 /* Initial blk_off, once the MHD is read. */
835 unsigned short init_blk_off
;
837 /* Used to store any 3 byte record, which could be the EOF pattern. */
838 unsigned char pattern
[4];
841 struct dcxsbm_desc
*dcxsbms
;
842 /* Current submap. */
843 struct dcxsbm_desc
*dcx_sbm
;
844 /* Current offset in the submap. */
845 unsigned int dcx_offset
;
848 /* Compressed buffer. */
849 unsigned char *dcx_buf
;
850 /* Size of the buffer. Used to resize. */
851 unsigned int dcx_max
;
852 /* Number of valid bytes in the buffer. */
853 unsigned int dcx_rlen
;
856 /* Return the current position. */
859 vms_lib_btell (struct bfd
*abfd
)
861 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
865 /* Read the header of the next data block if all bytes of the current block
869 vms_lib_read_block (struct bfd
*abfd
)
871 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
873 if (vec
->blk_off
== DATA__LENGTH
)
875 unsigned char hdr
[DATA__DATA
];
877 /* Read next block. */
878 if (bfd_seek (abfd
->my_archive
, vec
->next_block
, SEEK_SET
) != 0)
880 if (bfd_bread (hdr
, sizeof (hdr
), abfd
->my_archive
) != sizeof (hdr
))
882 vec
->next_block
= (bfd_getl32 (hdr
+ 2) - 1) * VMS_BLOCK_SIZE
;
883 vec
->blk_off
= sizeof (hdr
);
888 /* Read NBYTES from ABFD into BUF if not NULL. If BUF is NULL, bytes are
889 not stored. Read linearly from the library, but handle blocks. This
890 function does not handle records nor EOF. */
893 vms_lib_bread_raw (struct bfd
*abfd
, unsigned char *buf
, file_ptr nbytes
)
895 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
903 /* Be sure the current data block is read. */
904 if (!vms_lib_read_block (abfd
))
907 /* Do not read past the data block, do not read more than requested. */
908 l
= DATA__LENGTH
- vec
->blk_off
;
915 /* Really read into BUF. */
916 if (bfd_bread (buf
, l
, abfd
->my_archive
) != l
)
921 /* Make as if we are reading. */
922 if (bfd_seek (abfd
->my_archive
, l
, SEEK_CUR
) != 0)
935 /* Decompress NBYTES from VEC. Store the bytes into BUF if not NULL. */
938 vms_lib_dcx (struct vms_lib_iovec
*vec
, unsigned char *buf
, file_ptr nbytes
)
940 struct dcxsbm_desc
*sbm
;
946 /* The loop below expect to deliver at least one byte. */
950 /* Get the current state. */
952 offset
= vec
->dcx_offset
;
953 j
= vec
->dcx_pos
& 7;
955 for (i
= vec
->dcx_pos
>> 3; i
< vec
->dcx_rlen
; i
++)
957 unsigned char b
= vec
->dcx_buf
[i
];
963 if (!(sbm
->flags
[offset
>> 3] & (1 << (offset
& 7))))
965 unsigned int n_offset
= sbm
->nodes
[offset
];
968 /* End of buffer. Stay where we are. */
969 vec
->dcx_pos
= (i
<< 3) + j
;
972 vec
->dcx_offset
= offset
;
976 offset
= 2 * n_offset
;
980 unsigned char v
= sbm
->nodes
[offset
];
982 if (sbm
->next
!= NULL
)
983 sbm
= vec
->dcxsbms
+ sbm
->next
[v
];
994 vec
->dcx_pos
= (i
<< 3) + j
+ 1;
995 vec
->dcx_offset
= offset
;
1008 /* Standard IOVEC function. */
1011 vms_lib_bread (struct bfd
*abfd
, void *vbuf
, file_ptr nbytes
)
1013 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1016 unsigned char *buf
= (unsigned char *)vbuf
;
1018 /* Do not read past the end. */
1019 if (vec
->where
>= vec
->file_len
)
1025 if (vec
->rec_rem
== 0)
1027 unsigned char blen
[2];
1029 /* Read record length. */
1030 if (vms_lib_bread_raw (abfd
, blen
, sizeof (blen
)) != sizeof (blen
))
1032 vec
->rec_len
= bfd_getl16 (blen
);
1033 if (bfd_libdata (abfd
->my_archive
)->kind
== vms_lib_txt
)
1035 /* Discard record size and align byte. */
1037 vec
->rec_rem
= vec
->rec_len
;
1041 /* Prepend record size. */
1042 vec
->rec_pos
= REC_POS_LEN0
;
1043 vec
->rec_rem
= (vec
->rec_len
+ 1) & ~1; /* With align byte. */
1045 if (vec
->rec_len
== 3)
1047 /* Possibly end of file. Check the pattern. */
1048 if (vms_lib_bread_raw (abfd
, vec
->pattern
, 4) != 4)
1050 if (!memcmp (vec
->pattern
, eotdesc
+ 2, 3))
1052 /* This is really an EOF. */
1054 vec
->file_len
= vec
->where
;
1059 if (vec
->dcxsbms
!= NULL
)
1061 /* This is a compressed member. */
1065 /* Be sure there is enough room for the expansion. */
1066 len
= (vec
->rec_len
+ 1) & ~1;
1067 if (len
> vec
->dcx_max
)
1069 while (len
> vec
->dcx_max
)
1071 vec
->dcx_buf
= bfd_alloc (abfd
, vec
->dcx_max
);
1072 if (vec
->dcx_buf
== NULL
)
1076 /* Read the compressed record. */
1077 vec
->dcx_rlen
= len
;
1078 if (vec
->rec_len
== 3)
1081 memcpy (vec
->dcx_buf
, vec
->pattern
, 3);
1085 elen
= vms_lib_bread_raw (abfd
, vec
->dcx_buf
, len
);
1090 /* Dummy expansion to get the expanded length. */
1091 vec
->dcx_offset
= 0;
1092 vec
->dcx_sbm
= vec
->dcxsbms
;
1094 elen
= vms_lib_dcx (vec
, NULL
, 0x10000);
1097 vec
->rec_len
= elen
;
1098 vec
->rec_rem
= elen
;
1100 /* Reset the state. */
1101 vec
->dcx_offset
= 0;
1102 vec
->dcx_sbm
= vec
->dcxsbms
;
1106 if (vec
->rec_pos
< 0)
1109 switch (vec
->rec_pos
)
1112 c
= vec
->rec_len
& 0xff;
1113 vec
->rec_pos
= REC_POS_LEN1
;
1116 c
= (vec
->rec_len
>> 8) & 0xff;
1140 if (nbytes
> vec
->rec_rem
)
1141 chunk
= vec
->rec_rem
;
1145 if (vec
->dcxsbms
!= NULL
)
1147 /* Optimize the stat() case: no need to decompress again as we
1149 if (!(buf
== NULL
&& chunk
== vec
->rec_rem
))
1150 chunk
= vms_lib_dcx (vec
, buf
, chunk
);
1154 if (vec
->rec_len
== 3)
1157 memcpy (buf
, vec
->pattern
+ vec
->rec_pos
, chunk
);
1160 chunk
= vms_lib_bread_raw (abfd
, buf
, chunk
);
1168 vec
->rec_pos
+= chunk
;
1169 vec
->rec_rem
-= chunk
;
1171 if (vec
->rec_rem
== 0)
1173 /* End of record reached. */
1174 if (bfd_libdata (abfd
->my_archive
)->kind
== vms_lib_txt
)
1176 if ((vec
->rec_len
& 1) == 1
1177 && vec
->rec_len
!= 3
1178 && vec
->dcxsbms
== NULL
)
1180 /* Eat the pad byte. */
1182 if (vms_lib_bread_raw (abfd
, &pad
, 1) != 1)
1185 vec
->rec_pos
= REC_POS_NL
;
1190 if ((vec
->rec_len
& 1) == 1 && vec
->dcxsbms
!= NULL
)
1192 vec
->rec_pos
= REC_POS_PAD
;
1202 /* Standard function, but we currently only handle the rewind case. */
1205 vms_lib_bseek (struct bfd
*abfd
, file_ptr offset
, int whence
)
1207 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1209 if (whence
== SEEK_SET
&& offset
== 0)
1214 vec
->blk_off
= vec
->init_blk_off
;
1215 vec
->next_block
= vec
->init_next_block
;
1217 if (bfd_seek (abfd
->my_archive
, vec
->first_block
, SEEK_SET
) != 0)
1226 vms_lib_bwrite (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1227 const void *where ATTRIBUTE_UNUSED
,
1228 file_ptr nbytes ATTRIBUTE_UNUSED
)
1234 vms_lib_bclose (struct bfd
*abfd
)
1236 abfd
->iostream
= NULL
;
1241 vms_lib_bflush (struct bfd
*abfd ATTRIBUTE_UNUSED
)
1247 vms_lib_bstat (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1248 struct stat
*sb ATTRIBUTE_UNUSED
)
1250 /* Not supported. */
1255 vms_lib_bmmap (struct bfd
*abfd ATTRIBUTE_UNUSED
,
1256 void *addr ATTRIBUTE_UNUSED
,
1257 bfd_size_type len ATTRIBUTE_UNUSED
,
1258 int prot ATTRIBUTE_UNUSED
,
1259 int flags ATTRIBUTE_UNUSED
,
1260 file_ptr offset ATTRIBUTE_UNUSED
,
1261 void **map_addr ATTRIBUTE_UNUSED
,
1262 bfd_size_type
*map_len ATTRIBUTE_UNUSED
)
1267 static const struct bfd_iovec vms_lib_iovec
= {
1268 &vms_lib_bread
, &vms_lib_bwrite
, &vms_lib_btell
, &vms_lib_bseek
,
1269 &vms_lib_bclose
, &vms_lib_bflush
, &vms_lib_bstat
, &vms_lib_bmmap
1272 /* Open a library module. FILEPOS is the position of the module header. */
1275 vms_lib_bopen (bfd
*el
, file_ptr filepos
)
1277 struct vms_lib_iovec
*vec
;
1278 unsigned char buf
[256];
1279 struct vms_mhd
*mhd
;
1280 struct lib_tdata
*tdata
= bfd_libdata (el
->my_archive
);
1283 /* Allocate and initialized the iovec. */
1284 vec
= bfd_zalloc (el
, sizeof (*vec
));
1289 el
->iovec
= &vms_lib_iovec
;
1291 /* File length is not known. */
1294 /* Read the first data block. */
1295 vec
->next_block
= filepos
& ~(VMS_BLOCK_SIZE
- 1);
1296 vec
->blk_off
= DATA__LENGTH
;
1297 if (!vms_lib_read_block (el
))
1300 /* Prepare to read the first record. */
1301 vec
->blk_off
= filepos
& (VMS_BLOCK_SIZE
- 1);
1303 if (bfd_seek (el
->my_archive
, filepos
, SEEK_SET
) != 0)
1306 /* Read Record length + MHD + align byte. */
1307 len
= tdata
->mhd_size
;
1308 if (vms_lib_bread_raw (el
, buf
, 2) != 2)
1310 if (bfd_getl16 (buf
) != len
)
1312 len
= (len
+ 1) & ~1;
1313 BFD_ASSERT (len
<= sizeof (buf
));
1314 if (vms_lib_bread_raw (el
, buf
, len
) != len
)
1317 /* Get info from mhd. */
1318 mhd
= (struct vms_mhd
*)buf
;
1320 if (mhd
->id
!= MHD__C_MHDID
)
1322 if (len
>= MHD__C_MHDLEN
+ 1)
1323 el
->selective_search
= (mhd
->objstat
& MHD__M_SELSRC
) ? 1 : 0;
1324 el
->mtime
= vms_rawtime_to_time_t (mhd
->datim
);
1325 el
->mtime_set
= TRUE
;
1327 /* Reinit the iovec so that seek() will point to the first record after
1330 vec
->init_blk_off
= vec
->blk_off
;
1331 vec
->init_next_block
= vec
->next_block
;
1332 vec
->first_block
= bfd_tell (el
->my_archive
);
1333 vec
->dcxsbms
= bfd_libdata (el
->my_archive
)->dcxsbm
;
1335 if (vec
->dcxsbms
!= NULL
)
1338 vec
->dcx_max
= 10 * 1024;
1339 vec
->dcx_buf
= bfd_alloc (el
, vec
->dcx_max
);
1341 if (vec
->dcx_buf
== NULL
)
1347 /* Get member MODIDX. Return NULL in case of error. */
1350 _bfd_vms_lib_get_module (bfd
*abfd
, unsigned int modidx
)
1352 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
1360 if (modidx
>= tdata
->nbr_modules
)
1363 /* Already loaded. */
1364 if (tdata
->cache
[modidx
])
1365 return tdata
->cache
[modidx
];
1368 file_off
= tdata
->modules
[modidx
].file_offset
;
1369 if (tdata
->type
!= LBR__C_TYP_IOBJ
)
1371 res
= _bfd_create_empty_archive_element_shell (abfd
);
1375 /* Special reader to deal with data blocks. */
1376 if (!vms_lib_bopen (res
, file_off
))
1382 struct vms_mhd
*mhd
;
1383 struct areltdata
*arelt
;
1385 /* Sanity check. The MHD must be big enough to contain module size. */
1386 if (tdata
->mhd_size
< offsetof (struct vms_mhd
, modsize
) + 4)
1389 /* Read the MHD now. */
1390 if (bfd_seek (abfd
, file_off
, SEEK_SET
) != 0)
1392 if (bfd_bread (buf
, tdata
->mhd_size
, abfd
) != tdata
->mhd_size
)
1395 mhd
= (struct vms_mhd
*) buf
;
1396 if (mhd
->id
!= MHD__C_MHDID
)
1399 res
= _bfd_create_empty_archive_element_shell (abfd
);
1402 arelt
= bfd_zmalloc (sizeof (*arelt
));
1408 res
->arelt_data
= arelt
;
1410 /* Get info from mhd. */
1411 if (tdata
->mhd_size
>= offsetof (struct vms_mhd
, objstat
) + 1)
1412 res
->selective_search
= (mhd
->objstat
& MHD__M_SELSRC
) ? 1 : 0;
1413 res
->mtime
= vms_rawtime_to_time_t (mhd
->datim
);
1414 res
->mtime_set
= TRUE
;
1416 arelt
->parsed_size
= bfd_getl32 (mhd
->modsize
);
1418 /* No need for a special reader as members are stored linearly.
1419 Just skip the MHD. */
1420 res
->origin
= file_off
+ tdata
->mhd_size
;
1424 name
= tdata
->modules
[modidx
].name
;
1425 namelen
= strlen (name
);
1426 newname
= bfd_malloc (namelen
+ 4 + 1);
1427 if (newname
== NULL
)
1432 strcpy (newname
, name
);
1433 switch (tdata
->type
)
1435 case LBR__C_TYP_IOBJ
:
1436 case LBR__C_TYP_EOBJ
:
1437 /* For object archives, append .obj to mimic standard behaviour. */
1438 strcpy (newname
+ namelen
, ".obj");
1443 bfd_set_filename (res
, newname
);
1445 tdata
->cache
[modidx
] = res
;
1450 /* Standard function: get member at IDX. */
1453 _bfd_vms_lib_get_elt_at_index (bfd
*abfd
, symindex symidx
)
1455 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
1457 unsigned int modidx
;
1460 if (symidx
> tdata
->artdata
.symdef_count
)
1462 file_off
= tdata
->artdata
.symdefs
[symidx
].file_offset
;
1465 for (modidx
= 0; modidx
< tdata
->nbr_modules
; modidx
++)
1467 if (tdata
->modules
[modidx
].file_offset
== file_off
)
1470 if (modidx
>= tdata
->nbr_modules
)
1473 return _bfd_vms_lib_get_module (abfd
, modidx
);
1476 /* Elements of an imagelib are stubs. You can get the real image with this
1480 _bfd_vms_lib_get_imagelib_file (bfd
*el
)
1482 bfd
*archive
= el
->my_archive
;
1483 const char *modname
= el
->filename
;
1484 int modlen
= strlen (modname
);
1489 /* Convert module name to lower case and append '.exe'. */
1490 filename
= bfd_alloc (el
, modlen
+ 5);
1491 if (filename
== NULL
)
1493 for (j
= 0; j
< modlen
; j
++)
1494 if (ISALPHA (modname
[j
]))
1495 filename
[j
] = TOLOWER (modname
[j
]);
1497 filename
[j
] = modname
[j
];
1498 memcpy (filename
+ modlen
, ".exe", 5);
1500 filename
= _bfd_append_relative_path (archive
, filename
);
1501 if (filename
== NULL
)
1503 res
= bfd_openr (filename
, NULL
);
1507 /* xgettext:c-format */
1508 _bfd_error_handler(_("could not open shared image '%s' from '%s'"),
1509 filename
, archive
->filename
);
1510 bfd_release (archive
, filename
);
1514 /* FIXME: put it in a cache ? */
1518 /* Standard function. */
1521 _bfd_vms_lib_openr_next_archived_file (bfd
*archive
,
1530 idx
= last_file
->proxy_origin
+ 1;
1532 if (idx
>= bfd_libdata (archive
)->nbr_modules
)
1534 bfd_set_error (bfd_error_no_more_archived_files
);
1538 res
= _bfd_vms_lib_get_module (archive
, idx
);
1541 res
->proxy_origin
= idx
;
1545 /* Standard function. Just compute the length. */
1548 _bfd_vms_lib_generic_stat_arch_elt (bfd
*abfd
, struct stat
*st
)
1550 struct lib_tdata
*tdata
;
1553 if (abfd
->my_archive
== NULL
)
1555 bfd_set_error (bfd_error_invalid_operation
);
1559 tdata
= bfd_libdata (abfd
->my_archive
);
1560 if (tdata
->type
!= LBR__C_TYP_IOBJ
)
1562 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1564 if (vec
->file_len
== (ufile_ptr
)-1)
1566 if (vms_lib_bseek (abfd
, 0, SEEK_SET
) != 0)
1569 /* Compute length. */
1570 while (vms_lib_bread (abfd
, NULL
, 1 << 20) > 0)
1573 st
->st_size
= vec
->file_len
;
1577 st
->st_size
= ((struct areltdata
*)abfd
->arelt_data
)->parsed_size
;
1580 if (abfd
->mtime_set
)
1581 st
->st_mtime
= abfd
->mtime
;
1591 /* Internal representation of an index entry. */
1595 /* Corresponding archive member. */
1598 /* Number of reference to this entry. */
1601 /* Length of the key. */
1602 unsigned short namlen
;
1608 /* Used to sort index entries. */
1611 lib_index_cmp (const void *lv
, const void *rv
)
1613 const struct lib_index
*l
= lv
;
1614 const struct lib_index
*r
= rv
;
1616 return strcmp (l
->name
, r
->name
);
1619 /* Maximum number of index blocks level. */
1621 #define MAX_LEVEL 10
1623 /* Get the size of an index entry. */
1626 get_idxlen (struct lib_index
*idx
, bfd_boolean is_elfidx
)
1630 /* 9 is the size of struct vms_elfidx without keyname. */
1631 if (idx
->namlen
> MAX_KEYLEN
)
1632 return 9 + sizeof (struct vms_kbn
);
1634 return 9 + idx
->namlen
;
1638 /* 7 is the size of struct vms_idx without keyname. */
1639 return 7 + idx
->namlen
;
1643 /* Write the index composed by NBR symbols contained in IDX.
1644 VBN is the first vbn to be used, and will contain on return the last vbn.
1645 Can be called with ABFD set to NULL just to size the index.
1646 If not null, TOPVBN will be assigned to the vbn of the root index tree.
1647 IS_ELFIDX is true for elfidx (ie ia64) indexes layout.
1648 Return TRUE on success. */
1651 vms_write_index (bfd
*abfd
,
1652 struct lib_index
*idx
, unsigned int nbr
, unsigned int *vbn
,
1653 unsigned int *topvbn
, bfd_boolean is_elfidx
)
1655 /* The index is organized as a tree. This function implements a naive
1656 algorithm to balance the tree: it fills the leaves, and create a new
1657 branch when all upper leaves and branches are full. We only keep in
1658 memory a path to the current leaf. */
1662 /* Disk blocks for the current path. */
1663 struct vms_indexdef
*rblk
[MAX_LEVEL
];
1664 /* Info on the current blocks. */
1667 unsigned int vbn
; /* VBN of the block. */
1668 /* The last entry is identified so that it could be copied to the
1670 unsigned short len
; /* Length up to the last entry. */
1671 unsigned short lastlen
; /* Length of the last entry. */
1674 /* The kbn blocks are used to store long symbol names. */
1675 unsigned int kbn_sz
= 0; /* Number of bytes available in the kbn block. */
1676 unsigned int kbn_vbn
= 0; /* VBN of the kbn block. */
1677 unsigned char *kbn_blk
= NULL
; /* Contents of the kbn block. */
1681 /* No entries. Very easy to handle. */
1689 /* Sort the index the first time this function is called. */
1690 qsort (idx
, nbr
, sizeof (struct lib_index
), lib_index_cmp
);
1693 /* Allocate first index block. */
1696 rblk
[0] = bfd_zmalloc (sizeof (struct vms_indexdef
));
1697 blk
[0].vbn
= (*vbn
)++;
1701 for (i
= 0; i
< nbr
; i
++, idx
++)
1703 unsigned int idxlen
;
1705 unsigned int key_vbn
= 0;
1706 unsigned int key_off
= 0;
1708 idxlen
= get_idxlen (idx
, is_elfidx
);
1710 if (is_elfidx
&& idx
->namlen
> MAX_KEYLEN
)
1712 /* If the key (ie name) is too long, write it in the kbn block. */
1713 unsigned int kl
= idx
->namlen
;
1714 unsigned int kl_chunk
;
1715 const char *key
= idx
->name
;
1717 /* Write the key in the kbn, chunk after chunk. */
1720 if (kbn_sz
< sizeof (struct vms_kbn
))
1722 /* Not enough room in the kbn block. */
1725 /* Write it to the disk (if there is one). */
1728 if (!vms_write_block (abfd
, kbn_vbn
, kbn_blk
))
1733 kbn_blk
= bfd_malloc (VMS_BLOCK_SIZE
);
1734 if (kbn_blk
== NULL
)
1737 *(unsigned short *)kbn_blk
= 0;
1739 /* Allocate a new block for the keys. */
1741 kbn_sz
= VMS_BLOCK_SIZE
- 2;
1743 /* Size of the chunk written to the current key block. */
1744 if (kl
+ sizeof (struct vms_kbn
) > kbn_sz
)
1745 kl_chunk
= kbn_sz
- sizeof (struct vms_kbn
);
1749 if (kbn_blk
!= NULL
)
1751 struct vms_kbn
*kbn
;
1753 kbn
= (struct vms_kbn
*)(kbn_blk
+ VMS_BLOCK_SIZE
- kbn_sz
);
1757 /* Save the rfa of the first chunk. */
1759 key_off
= VMS_BLOCK_SIZE
- kbn_sz
;
1762 bfd_putl16 (kl_chunk
, kbn
->keylen
);
1765 /* No next chunk. */
1766 bfd_putl32 (0, kbn
->rfa
.vbn
);
1767 bfd_putl16 (0, kbn
->rfa
.offset
);
1771 /* Next chunk will be at the start of the next block. */
1772 bfd_putl32 (*vbn
, kbn
->rfa
.vbn
);
1773 bfd_putl16 (2, kbn
->rfa
.offset
);
1775 memcpy ((char *)(kbn
+ 1), key
, kl_chunk
);
1779 kl_chunk
= (kl_chunk
+ 1) & ~1; /* Always align. */
1780 kbn_sz
-= kl_chunk
+ sizeof (struct vms_kbn
);
1785 /* Check if a block might overflow. In this case we will flush this
1786 block and all the blocks below it. */
1787 for (j
= 0; j
< level
; j
++)
1788 if (blk
[j
].len
+ blk
[j
].lastlen
+ idxlen
> INDEXDEF__BLKSIZ
)
1791 for (j
= 0; j
< level
; j
++)
1795 /* There is not enough room to write the new entry in this
1796 block or in a parent block. */
1800 BFD_ASSERT (level
< MAX_LEVEL
);
1802 /* Need to create a parent. */
1805 rblk
[level
] = bfd_zmalloc (sizeof (struct vms_indexdef
));
1806 bfd_putl32 (*vbn
, rblk
[j
]->parent
);
1808 blk
[level
].vbn
= (*vbn
)++;
1810 blk
[level
].lastlen
= blk
[j
].lastlen
;
1815 /* Update parent block: write the last entry from the current
1819 struct vms_rfa
*rfa
;
1821 /* Pointer to the last entry in parent block. */
1822 rfa
= (struct vms_rfa
*)(rblk
[j
+ 1]->keys
+ blk
[j
+ 1].len
);
1824 /* Copy the whole entry. */
1825 BFD_ASSERT (blk
[j
+ 1].lastlen
== blk
[j
].lastlen
);
1826 memcpy (rfa
, rblk
[j
]->keys
+ blk
[j
].len
, blk
[j
].lastlen
);
1827 /* Fix the entry (which in always the first field of an
1829 bfd_putl32 (blk
[j
].vbn
, rfa
->vbn
);
1830 bfd_putl16 (RFADEF__C_INDEX
, rfa
->offset
);
1835 /* And allocate it. Do it only on the block that won't be
1836 flushed (so that the parent of the parent can be
1838 blk
[j
+ 1].len
+= blk
[j
+ 1].lastlen
;
1839 blk
[j
+ 1].lastlen
= 0;
1842 /* Write this block on the disk. */
1845 bfd_putl16 (blk
[j
].len
+ blk
[j
].lastlen
, rblk
[j
]->used
);
1846 if (!vms_write_block (abfd
, blk
[j
].vbn
, rblk
[j
]))
1850 /* Reset this block. */
1853 blk
[j
].vbn
= (*vbn
)++;
1856 /* Append it to the block. */
1859 /* Keep the previous last entry. */
1860 blk
[j
].len
+= blk
[j
].lastlen
;
1864 struct vms_rfa
*rfa
;
1866 rfa
= (struct vms_rfa
*)(rblk
[j
]->keys
+ blk
[j
].len
);
1867 bfd_putl32 ((idx
->abfd
->proxy_origin
/ VMS_BLOCK_SIZE
) + 1,
1870 ((idx
->abfd
->proxy_origin
% VMS_BLOCK_SIZE
)
1871 + (is_elfidx
? 0 : DATA__DATA
),
1876 /* Use elfidx format. */
1877 struct vms_elfidx
*en
= (struct vms_elfidx
*)rfa
;
1882 /* Long symbol name. */
1883 struct vms_kbn
*k
= (struct vms_kbn
*)(en
->keyname
);
1884 bfd_putl16 (sizeof (struct vms_kbn
), en
->keylen
);
1885 bfd_putl16 (idx
->namlen
, k
->keylen
);
1886 bfd_putl32 (key_vbn
, k
->rfa
.vbn
);
1887 bfd_putl16 (key_off
, k
->rfa
.offset
);
1888 en
->flags
|= ELFIDX__SYMESC
;
1892 bfd_putl16 (idx
->namlen
, en
->keylen
);
1893 memcpy (en
->keyname
, idx
->name
, idx
->namlen
);
1898 /* Use idx format. */
1899 struct vms_idx
*en
= (struct vms_idx
*)rfa
;
1900 en
->keylen
= idx
->namlen
;
1901 memcpy (en
->keyname
, idx
->name
, idx
->namlen
);
1905 /* The last added key can now be the last one all blocks in the
1907 blk
[j
].lastlen
= idxlen
;
1911 /* Save VBN of the root. */
1913 *topvbn
= blk
[level
- 1].vbn
;
1919 for (j
= 1; j
< level
; j
++)
1921 /* Update parent block: write the new entry. */
1924 struct vms_rfa
*rfa
;
1926 en
= rblk
[j
- 1]->keys
+ blk
[j
- 1].len
;
1927 par
= rblk
[j
]->keys
+ blk
[j
].len
;
1928 BFD_ASSERT (blk
[j
].lastlen
== blk
[j
- 1].lastlen
);
1929 memcpy (par
, en
, blk
[j
- 1].lastlen
);
1930 rfa
= (struct vms_rfa
*)par
;
1931 bfd_putl32 (blk
[j
- 1].vbn
, rfa
->vbn
);
1932 bfd_putl16 (RFADEF__C_INDEX
, rfa
->offset
);
1935 for (j
= 0; j
< level
; j
++)
1937 /* Write this block on the disk. */
1938 bfd_putl16 (blk
[j
].len
+ blk
[j
].lastlen
, rblk
[j
]->used
);
1939 if (!vms_write_block (abfd
, blk
[j
].vbn
, rblk
[j
]))
1945 /* Write the last kbn (if any). */
1948 if (!vms_write_block (abfd
, kbn_vbn
, kbn_blk
))
1956 /* Append data to the data block DATA. Force write if PAD is true. */
1959 vms_write_data_block (bfd
*arch
, struct vms_datadef
*data
, file_ptr
*off
,
1960 const unsigned char *buf
, unsigned int len
, int pad
)
1962 while (len
> 0 || pad
)
1964 unsigned int doff
= *off
& (VMS_BLOCK_SIZE
- 1);
1965 unsigned int remlen
= (DATA__LENGTH
- DATA__DATA
) - doff
;
1968 l
= (len
> remlen
) ? remlen
: len
;
1969 memcpy (data
->data
+ doff
, buf
, l
);
1975 if (doff
== (DATA__LENGTH
- DATA__DATA
) || (len
== 0 && pad
))
1979 bfd_putl32 ((*off
/ VMS_BLOCK_SIZE
) + 2, data
->link
);
1981 if (bfd_bwrite (data
, sizeof (*data
), arch
) != sizeof (*data
))
1984 *off
+= DATA__LENGTH
- doff
;
1993 /* Build the symbols index. */
1996 _bfd_vms_lib_build_map (unsigned int nbr_modules
,
1997 struct lib_index
*modules
,
1998 unsigned int *res_cnt
,
1999 struct lib_index
**res
)
2002 asymbol
**syms
= NULL
;
2004 struct lib_index
*map
= NULL
;
2005 unsigned int map_max
= 1024; /* Fine initial default. */
2006 unsigned int map_count
= 0;
2008 map
= (struct lib_index
*) bfd_malloc (map_max
* sizeof (struct lib_index
));
2012 /* Gather symbols. */
2013 for (i
= 0; i
< nbr_modules
; i
++)
2018 bfd
*current
= modules
[i
].abfd
;
2020 if ((bfd_get_file_flags (current
) & HAS_SYMS
) == 0)
2023 storage
= bfd_get_symtab_upper_bound (current
);
2029 if (storage
> syms_max
)
2034 syms
= (asymbol
**) bfd_malloc (syms_max
);
2038 symcount
= bfd_canonicalize_symtab (current
, syms
);
2042 /* Now map over all the symbols, picking out the ones we
2044 for (src_count
= 0; src_count
< symcount
; src_count
++)
2046 flagword flags
= (syms
[src_count
])->flags
;
2047 asection
*sec
= syms
[src_count
]->section
;
2049 if ((flags
& BSF_GLOBAL
2051 || flags
& BSF_INDIRECT
2052 || bfd_is_com_section (sec
))
2053 && ! bfd_is_und_section (sec
))
2055 struct lib_index
*new_map
;
2057 /* This symbol will go into the archive header. */
2058 if (map_count
== map_max
)
2061 new_map
= (struct lib_index
*)
2062 bfd_realloc (map
, map_max
* sizeof (struct lib_index
));
2063 if (new_map
== NULL
)
2068 map
[map_count
].abfd
= current
;
2069 map
[map_count
].namlen
= strlen (syms
[src_count
]->name
);
2070 map
[map_count
].name
= syms
[src_count
]->name
;
2078 *res_cnt
= map_count
;
2090 /* Do the hard work: write an archive on the disk. */
2093 _bfd_vms_lib_write_archive_contents (bfd
*arch
)
2096 unsigned int nbr_modules
;
2097 struct lib_index
*modules
;
2098 unsigned int nbr_symbols
;
2099 struct lib_index
*symbols
;
2100 struct lib_tdata
*tdata
= bfd_libdata (arch
);
2103 unsigned int nbr_mod_iblk
;
2104 unsigned int nbr_sym_iblk
;
2106 unsigned int mod_idx_vbn
;
2107 unsigned int sym_idx_vbn
;
2108 bfd_boolean is_elfidx
= tdata
->kind
== vms_lib_ia64
;
2109 unsigned int max_keylen
= is_elfidx
? MAX_EKEYLEN
: MAX_KEYLEN
;
2111 /* Count the number of modules (and do a first sanity check). */
2113 for (current
= arch
->archive_head
;
2115 current
= current
->archive_next
)
2117 /* This check is checking the bfds for the objects we're reading
2118 from (which are usually either an object file or archive on
2119 disk), not the archive entries we're writing to. We don't
2120 actually create bfds for the archive members, we just copy
2121 them byte-wise when we write out the archive. */
2122 if (bfd_write_p (current
) || !bfd_check_format (current
, bfd_object
))
2124 bfd_set_error (bfd_error_invalid_operation
);
2131 /* Build the modules list. */
2132 BFD_ASSERT (tdata
->modules
== NULL
);
2133 modules
= bfd_alloc (arch
, nbr_modules
* sizeof (struct lib_index
));
2134 if (modules
== NULL
)
2137 for (current
= arch
->archive_head
, i
= 0;
2139 current
= current
->archive_next
, i
++)
2143 modules
[i
].abfd
= current
;
2144 modules
[i
].name
= vms_get_module_name (current
->filename
, FALSE
);
2147 /* FIXME: silently truncate long names ? */
2148 nl
= strlen (modules
[i
].name
);
2149 modules
[i
].namlen
= (nl
> max_keylen
? max_keylen
: nl
);
2152 /* Create the module index. */
2154 if (!vms_write_index (NULL
, modules
, nbr_modules
, &vbn
, NULL
, is_elfidx
))
2158 /* Create symbol index. */
2159 if (!_bfd_vms_lib_build_map (nbr_modules
, modules
, &nbr_symbols
, &symbols
))
2163 if (!vms_write_index (NULL
, symbols
, nbr_symbols
, &vbn
, NULL
, is_elfidx
))
2167 /* Write modules and remember their position. */
2168 off
= (1 + nbr_mod_iblk
+ nbr_sym_iblk
) * VMS_BLOCK_SIZE
;
2170 if (bfd_seek (arch
, off
, SEEK_SET
) != 0)
2173 for (i
= 0; i
< nbr_modules
; i
++)
2175 struct vms_datadef data
;
2176 unsigned char blk
[VMS_BLOCK_SIZE
];
2177 struct vms_mhd
*mhd
;
2180 current
= modules
[i
].abfd
;
2181 current
->proxy_origin
= off
;
2187 /* Write the MHD as a record (ie, size first). */
2189 bfd_putl16 (tdata
->mhd_size
, blk
);
2191 mhd
= (struct vms_mhd
*)(blk
+ sz
);
2192 memset (mhd
, 0, sizeof (struct vms_mhd
));
2194 mhd
->id
= MHD__C_MHDID
;
2196 memcpy (mhd
->objid
, "V1.0", 4);
2197 bfd_putl32 (modules
[i
].ref
, mhd
->refcnt
);
2200 sz
+= tdata
->mhd_size
;
2203 /* Rewind the member to be put into the archive. */
2204 if (bfd_seek (current
, 0, SEEK_SET
) != 0)
2207 /* Copy the member into the archive. */
2210 unsigned int modsize
= 0;
2212 file_ptr off_hdr
= off
;
2214 /* Read to complete the first block. */
2215 amt
= bfd_bread (blk
+ sz
, VMS_BLOCK_SIZE
- sz
, current
);
2216 if (amt
== (bfd_size_type
)-1)
2219 if (amt
< VMS_BLOCK_SIZE
- sz
)
2221 /* The member size is less than a block. Pad the block. */
2222 memset (blk
+ sz
+ amt
, 0, VMS_BLOCK_SIZE
- sz
- amt
);
2224 bfd_putl32 (modsize
, mhd
->modsize
);
2226 /* Write the first block (which contains an mhd). */
2227 if (bfd_bwrite (blk
, VMS_BLOCK_SIZE
, arch
) != VMS_BLOCK_SIZE
)
2229 off
+= VMS_BLOCK_SIZE
;
2231 if (amt
== VMS_BLOCK_SIZE
- sz
)
2233 /* Copy the remaining. */
2234 char buffer
[DEFAULT_BUFFERSIZE
];
2238 amt
= bfd_bread (buffer
, sizeof (buffer
), current
);
2239 if (amt
== (bfd_size_type
)-1)
2244 if (amt
!= sizeof (buffer
))
2246 /* Clear the padding. */
2247 memset (buffer
+ amt
, 0, sizeof (buffer
) - amt
);
2248 amt
= (amt
+ VMS_BLOCK_SIZE
) & ~(VMS_BLOCK_SIZE
- 1);
2250 if (bfd_bwrite (buffer
, amt
, arch
) != amt
)
2255 /* Now that the size is known, write the first block (again). */
2256 bfd_putl32 (modsize
, mhd
->modsize
);
2257 if (bfd_seek (arch
, off_hdr
, SEEK_SET
) != 0
2258 || bfd_bwrite (blk
, VMS_BLOCK_SIZE
, arch
) != VMS_BLOCK_SIZE
)
2260 if (bfd_seek (arch
, off
, SEEK_SET
) != 0)
2266 /* Write the MHD. */
2267 if (vms_write_data_block (arch
, &data
, &off
, blk
, sz
, 0) < 0)
2270 /* Write the member. */
2273 sz
= bfd_bread (blk
, sizeof (blk
), current
);
2276 if (vms_write_data_block (arch
, &data
, &off
, blk
, sz
, 0) < 0)
2280 /* Write the end of module marker. */
2281 if (vms_write_data_block (arch
, &data
, &off
,
2282 eotdesc
, sizeof (eotdesc
), 1) < 0)
2287 /* Write the indexes. */
2289 if (!vms_write_index (arch
, modules
, nbr_modules
, &vbn
, &mod_idx_vbn
,
2292 if (!vms_write_index (arch
, symbols
, nbr_symbols
, &vbn
, &sym_idx_vbn
,
2296 /* Write libary header. */
2298 unsigned char blk
[VMS_BLOCK_SIZE
];
2299 struct vms_lhd
*lhd
= (struct vms_lhd
*)blk
;
2300 struct vms_idd
*idd
= (struct vms_idd
*)(blk
+ sizeof (*lhd
));
2301 unsigned int idd_flags
;
2302 unsigned int saneid
;
2304 memset (blk
, 0, sizeof (blk
));
2306 lhd
->type
= tdata
->type
;
2308 switch (tdata
->kind
)
2311 saneid
= LHD_SANEID3
;
2314 saneid
= LHD_SANEID6
;
2319 bfd_putl32 (saneid
, lhd
->sanity
);
2320 bfd_putl16 (tdata
->ver
, lhd
->majorid
);
2321 bfd_putl16 (0, lhd
->minorid
);
2322 snprintf ((char *)lhd
->lbrver
+ 1, sizeof (lhd
->lbrver
) - 1,
2324 (unsigned)(BFD_VERSION
/ 100000000UL),
2325 (unsigned)(BFD_VERSION
/ 1000000UL) % 100,
2326 (unsigned)(BFD_VERSION
/ 10000UL) % 100);
2327 lhd
->lbrver
[sizeof (lhd
->lbrver
) - 1] = 0;
2328 lhd
->lbrver
[0] = strlen ((char *)lhd
->lbrver
+ 1);
2330 bfd_putl32 (tdata
->credat_lo
, lhd
->credat
+ 0);
2331 bfd_putl32 (tdata
->credat_hi
, lhd
->credat
+ 4);
2332 vms_raw_get_time (lhd
->updtim
);
2334 lhd
->mhdusz
= tdata
->mhd_size
- MHD__C_USRDAT
;
2336 bfd_putl32 (nbr_modules
+ nbr_symbols
, lhd
->idxcnt
);
2337 bfd_putl32 (nbr_modules
, lhd
->modcnt
);
2338 bfd_putl32 (nbr_modules
, lhd
->modhdrs
);
2340 /* Number of blocks for index. */
2341 bfd_putl32 (nbr_mod_iblk
+ nbr_sym_iblk
, lhd
->idxblks
);
2342 bfd_putl32 (vbn
- 1, lhd
->hipreal
);
2343 bfd_putl32 (vbn
- 1, lhd
->hiprusd
);
2345 /* VBN of the next free block. */
2346 bfd_putl32 ((off
/ VMS_BLOCK_SIZE
) + 1, lhd
->nextvbn
);
2347 bfd_putl32 ((off
/ VMS_BLOCK_SIZE
) + 1, lhd
->nextrfa
+ 0);
2348 bfd_putl16 (0, lhd
->nextrfa
+ 4);
2350 /* First index (modules name). */
2351 idd_flags
= IDD__FLAGS_ASCII
| IDD__FLAGS_VARLENIDX
2352 | IDD__FLAGS_NOCASECMP
| IDD__FLAGS_NOCASENTR
;
2353 bfd_putl16 (idd_flags
, idd
->flags
);
2354 bfd_putl16 (max_keylen
+ 1, idd
->keylen
);
2355 bfd_putl16 (mod_idx_vbn
, idd
->vbn
);
2358 /* Second index (symbols name). */
2359 bfd_putl16 (idd_flags
, idd
->flags
);
2360 bfd_putl16 (max_keylen
+ 1, idd
->keylen
);
2361 bfd_putl16 (sym_idx_vbn
, idd
->vbn
);
2364 if (!vms_write_block (arch
, 1, blk
))
2371 bfd_set_input_error (current
, bfd_get_error ());
2375 /* Add a target for text library. This costs almost nothing and is useful to
2376 read VMS library on the host. */
2378 const bfd_target alpha_vms_lib_txt_vec
=
2380 "vms-libtxt", /* Name. */
2381 bfd_target_unknown_flavour
,
2382 BFD_ENDIAN_UNKNOWN
, /* byteorder */
2383 BFD_ENDIAN_UNKNOWN
, /* header_byteorder */
2384 0, /* Object flags. */
2385 0, /* Sect flags. */
2386 0, /* symbol_leading_char. */
2387 ' ', /* ar_pad_char. */
2388 15, /* ar_max_namelen. */
2389 0, /* match priority. */
2390 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
2391 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
2392 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
,
2393 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
2394 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
2395 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
,
2396 { /* bfd_check_format. */
2399 _bfd_vms_lib_txt_archive_p
,
2402 { /* bfd_set_format. */
2403 _bfd_bool_bfd_false_error
,
2404 _bfd_bool_bfd_false_error
,
2405 _bfd_bool_bfd_false_error
,
2406 _bfd_bool_bfd_false_error
2408 { /* bfd_write_contents. */
2409 _bfd_bool_bfd_false_error
,
2410 _bfd_bool_bfd_false_error
,
2411 _bfd_bool_bfd_false_error
,
2412 _bfd_bool_bfd_false_error
2414 BFD_JUMP_TABLE_GENERIC (_bfd_generic
),
2415 BFD_JUMP_TABLE_COPY (_bfd_generic
),
2416 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
2417 BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib
),
2418 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols
),
2419 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs
),
2420 BFD_JUMP_TABLE_WRITE (_bfd_nowrite
),
2421 BFD_JUMP_TABLE_LINK (_bfd_nolink
),
2422 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),