1 /* BFD back-end for VMS archive files.
3 Copyright 2010 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"
32 /* The standard VMS disk block size. */
33 #ifndef VMS_BLOCK_SIZE
34 #define VMS_BLOCK_SIZE 512
37 /* Maximum key length (which is also the maximum symbol length in archive). */
38 #define MAX_KEYLEN 129
44 unsigned char min_char
;
45 unsigned char max_char
;
51 /* Kind of library. Used to filter in archive_p. */
61 /* Back-end private data. */
68 /* Type of the archive. */
71 /* Kind of archive. Summary of its type. */
72 enum vms_lib_kind kind
;
74 /* Total size of the mhd (element header). */
75 unsigned int mhd_size
;
77 /* Vector of modules (archive elements), already sorted. */
78 unsigned int nbr_modules
;
79 struct carsym
*modules
;
82 /* Vector of symbols (archive map), already sorted. */
83 unsigned int nbr_syms
;
86 /* DCX (decompression) data. */
87 unsigned int nbr_dcxsbm
;
88 struct dcxsbm_desc
*dcxsbm
;
91 #define bfd_libdata(bfd) ((struct lib_tdata *)((bfd)->tdata.any))
93 /* End-Of-Text pattern. This is a special record to mark the end of file. */
95 static const unsigned char eotdesc
[] = { 0x03, 0x00, 0x77, 0x00, 0x77, 0x00 };
97 /* Read index block VBN and put the entry in **IDX (which is updated).
98 If the entry is indirect, recurse. */
101 vms_traverse_index (bfd
*abfd
, unsigned int vbn
, struct carsym
**idx
)
103 struct vms_indexdef indexdef
;
108 /* Read the index block. */
109 off
= (vbn
- 1) * VMS_BLOCK_SIZE
;
110 if (bfd_seek (abfd
, off
, SEEK_SET
) != 0
111 || bfd_bread (&indexdef
, sizeof (indexdef
), abfd
) != sizeof (indexdef
))
115 used
= bfd_getl16 (indexdef
.used
);
116 for (i
= 0; i
< used
;)
118 unsigned int idx_vbn
;
119 unsigned int idx_off
;
121 unsigned char *keyname
;
122 unsigned char *ridx
= (unsigned char *)&indexdef
.keys
[i
];
125 idx_vbn
= bfd_getl32 (ridx
);
126 idx_off
= bfd_getl16 (ridx
+ 4);
132 /* Extract key length. */
133 if (bfd_libdata (abfd
)->ver
== 3)
138 else if (bfd_libdata (abfd
)->ver
== 4)
140 keylen
= bfd_getl16 (ridx
+ 6);
146 keyname
= ridx
+ len
;
149 if (idx_off
== RFADEF__C_INDEX
)
151 /* Indirect entry. Recurse. */
152 if (!vms_traverse_index (abfd
, idx_vbn
, idx
))
157 /* Add a new entry. */
160 name
= bfd_alloc (abfd
, keylen
+ 1);
163 memcpy (name
, keyname
, keylen
);
165 (*idx
)->file_offset
= (idx_vbn
- 1) * VMS_BLOCK_SIZE
+ idx_off
;
174 /* Read index #IDX, which must have NBREL entries. */
176 static struct carsym
*
177 vms_lib_read_index (bfd
*abfd
, int idx
, unsigned int nbrel
)
185 /* Read index desription. */
186 if (bfd_seek (abfd
, LHD_IDXDESC
+ idx
* IDD_LENGTH
, SEEK_SET
) != 0
187 || bfd_bread (&idd
, sizeof (idd
), abfd
) != sizeof (idd
))
191 flags
= bfd_getl16 (idd
.flags
);
192 if (!(flags
& IDD__FLAGS_ASCII
)
193 || !(flags
& IDD__FLAGS_VARLENIDX
))
196 res
= bfd_alloc (abfd
, nbrel
* sizeof (struct carsym
));
202 /* Note: if the index is empty, there is no block to traverse. */
203 vbn
= bfd_getl32 (idd
.vbn
);
204 if (vbn
!= 0 && !vms_traverse_index (abfd
, vbn
, &el
))
206 bfd_release (abfd
, res
);
210 if ((unsigned int)(el
- res
) != nbrel
)
212 /* Inconsistency between the number of modules declared and the number
213 of modules found in the index. */
214 bfd_release (abfd
, res
);
220 /* Standard function. */
222 static const bfd_target
*
223 _bfd_vms_lib_archive_p (bfd
*abfd
, enum vms_lib_kind kind
)
227 struct lib_tdata
*tdata_hold
;
228 struct lib_tdata
*tdata
;
232 if (bfd_bread (&lhd
, sizeof (lhd
), abfd
) != sizeof (lhd
))
234 if (bfd_get_error () != bfd_error_system_call
)
235 bfd_set_error (bfd_error_wrong_format
);
239 /* Check sanity (= magic) number. */
240 sanity
= bfd_getl32 (lhd
.sanity
);
241 if (!(sanity
== LHD_SANEID3
242 || sanity
== LHD_SANEID4
243 || sanity
== LHD_SANEID_DCX
))
245 bfd_set_error (bfd_error_wrong_format
);
249 /* Check archive kind. */
253 if ((lhd
.type
!= LBR__C_TYP_EOBJ
&& lhd
.type
!= LBR__C_TYP_ESHSTB
)
254 || bfd_getl32 (lhd
.majorid
) != 3
257 bfd_set_error (bfd_error_wrong_format
);
262 if ((lhd
.type
!= LBR__C_TYP_TXT
263 && lhd
.type
!= LBR__C_TYP_MLB
264 && lhd
.type
!= LBR__C_TYP_HLP
)
265 || bfd_getl32 (lhd
.majorid
) != 3
268 bfd_set_error (bfd_error_wrong_format
);
276 /* Allocate and initialize private data. */
277 tdata_hold
= bfd_libdata (abfd
);
278 tdata
= (struct lib_tdata
*) bfd_zalloc (abfd
, sizeof (struct lib_tdata
));
281 abfd
->tdata
.any
= (void *)tdata
;
282 tdata
->ver
= bfd_getl32 (lhd
.majorid
);
283 tdata
->mhd_size
= MHD__C_USRDAT
+ lhd
.mhdusz
;
284 tdata
->type
= lhd
.type
;
288 tdata
->nbr_modules
= bfd_getl32 (lhd
.modcnt
);
289 tdata
->nbr_syms
= bfd_getl32 (lhd
.idxcnt
) - tdata
->nbr_modules
;
290 tdata
->modules
= vms_lib_read_index (abfd
, 0, tdata
->nbr_modules
);
291 if (tdata
->modules
== NULL
)
295 tdata
->syms
= vms_lib_read_index (abfd
, 1, tdata
->nbr_syms
);
296 if (tdata
->syms
== NULL
)
299 tdata
->cache
= bfd_zalloc (abfd
, sizeof (bfd
*) * tdata
->nbr_modules
);
300 if (tdata
->cache
== NULL
)
303 /* Read DCX submaps. */
304 dcxvbn
= bfd_getl32 (lhd
.dcxmapvbn
);
307 unsigned char buf_reclen
[4];
310 struct vms_dcxmap
*map
;
311 unsigned int sbm_off
;
314 if (bfd_seek (abfd
, (dcxvbn
- 1) * VMS_BLOCK_SIZE
, SEEK_SET
) != 0
315 || bfd_bread (buf_reclen
, sizeof (buf_reclen
), abfd
)
316 != sizeof (buf_reclen
))
318 reclen
= bfd_getl32 (buf_reclen
);
319 buf
= bfd_malloc (reclen
);
322 if (bfd_bread (buf
, reclen
, abfd
) != reclen
)
327 map
= (struct vms_dcxmap
*)buf
;
328 tdata
->nbr_dcxsbm
= bfd_getl16 (map
->nsubs
);
329 sbm_off
= bfd_getl16 (map
->sub0
);
330 tdata
->dcxsbm
= (struct dcxsbm_desc
*)bfd_alloc
331 (abfd
, tdata
->nbr_dcxsbm
* sizeof (struct dcxsbm_desc
));
332 for (i
= 0; i
< tdata
->nbr_dcxsbm
; i
++)
334 struct vms_dcxsbm
*sbm
= (struct vms_dcxsbm
*) (buf
+ sbm_off
);
335 struct dcxsbm_desc
*sbmdesc
= &tdata
->dcxsbm
[i
];
336 unsigned int sbm_len
;
338 unsigned char *data
= (unsigned char *)sbm
;
342 sbm_sz
= bfd_getl16 (sbm
->size
);
344 BFD_ASSERT (sbm_off
<= reclen
);
346 sbmdesc
->min_char
= sbm
->min_char
;
347 BFD_ASSERT (sbmdesc
->min_char
== 0);
348 sbmdesc
->max_char
= sbm
->max_char
;
349 sbm_len
= sbmdesc
->max_char
- sbmdesc
->min_char
+ 1;
350 l
= (2 * sbm_len
+ 7) / 8;
351 BFD_ASSERT (sbm_sz
>= sizeof (struct vms_dcxsbm
) + l
+ 3 * sbm_len
);
352 sbmdesc
->flags
= (unsigned char *)bfd_alloc (abfd
, l
);
353 memcpy (sbmdesc
->flags
, data
+ bfd_getl16 (sbm
->flags
), l
);
354 sbmdesc
->nodes
= (unsigned char *)bfd_alloc (abfd
, 2 * sbm_len
);
355 memcpy (sbmdesc
->nodes
, data
+ bfd_getl16 (sbm
->nodes
), 2 * sbm_len
);
356 sbmdesc
->next
= (unsigned short *)bfd_alloc
357 (abfd
, sbm_len
* sizeof (unsigned short));
358 buf1
= data
+ bfd_getl16 (sbm
->next
);
359 for (j
= 0; j
< sbm_len
; j
++)
360 sbmdesc
->next
[j
] = bfd_getl16 (buf1
+ j
* 2);
366 tdata
->nbr_dcxsbm
= 0;
369 /* The map is always present. Also mark shared image library. */
370 abfd
->has_armap
= TRUE
;
371 if (tdata
->type
== LBR__C_TYP_ESHSTB
)
372 abfd
->is_thin_archive
= TRUE
;
377 bfd_release (abfd
, tdata
);
378 abfd
->tdata
.any
= (void *)tdata_hold
;;
382 /* Standard function for alpha libraries. */
385 _bfd_vms_lib_alpha_archive_p (bfd
*abfd
)
387 return _bfd_vms_lib_archive_p (abfd
, vms_lib_alpha
);
390 /* Standard function for text libraries. */
392 static const bfd_target
*
393 _bfd_vms_lib_txt_archive_p (bfd
*abfd
)
395 return _bfd_vms_lib_archive_p (abfd
, vms_lib_txt
);
398 /* Standard bfd function. */
401 _bfd_vms_lib_mkarchive (bfd
*abfd
)
403 struct lib_tdata
*tdata
;
405 tdata
= (struct lib_tdata
*) bfd_zalloc (abfd
, sizeof (struct lib_tdata
));
409 abfd
->tdata
.any
= (void *)tdata
;
411 tdata
->mhd_size
= sizeof (struct vms_mhd
);
412 tdata
->type
= LBR__C_TYP_EOBJ
;
414 tdata
->nbr_modules
= 0;
416 tdata
->modules
= NULL
;
423 /* Find NAME in the symbol index. Return the index. */
426 _bfd_vms_lib_find_symbol (bfd
*abfd
, const char *name
)
428 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
431 /* Open-coded binary search for speed. */
433 hi
= tdata
->nbr_syms
- 1;
437 int mid
= lo
+ (hi
- lo
) / 2;
440 diff
= (char)(name
[0] - tdata
->syms
[mid
].name
[0]);
442 diff
= strcmp (name
, tdata
->syms
[mid
].name
);
444 return tdata
->syms
[mid
].file_offset
;
453 /* IO vector for archive member. Need that because members are not linearly
454 stored in archives. */
458 /* Current offset. */
461 /* Length of the module, when known. */
464 /* Current position in the record from bfd_bread point of view (ie, after
465 decompression). 0 means that no data byte have been read, -2 and -1
466 are reserved for the length word. */
468 #define REC_POS_NL -4
469 #define REC_POS_PAD -3
470 #define REC_POS_LEN0 -2
471 #define REC_POS_LEN1 -1
474 unsigned short rec_len
;
475 /* Number of bytes to read in the current record. */
476 unsigned short rec_rem
;
477 /* Offset of the next block. */
479 /* Current *data* offset in the data block. */
480 unsigned short blk_off
;
482 /* Offset of the first block. Extracted from the index. */
483 file_ptr first_block
;
485 /* Initial next_block. Extracted when the MHD is read. */
486 file_ptr init_next_block
;
487 /* Initial blk_off, once the MHD is read. */
488 unsigned short init_blk_off
;
490 /* Used to store any 3 byte record, which could be the EOF pattern. */
491 unsigned char pattern
[4];
494 struct dcxsbm_desc
*dcxsbms
;
495 /* Current submap. */
496 struct dcxsbm_desc
*dcx_sbm
;
497 /* Current offset in the submap. */
498 unsigned int dcx_offset
;
501 /* Compressed buffer. */
502 unsigned char *dcx_buf
;
503 /* Size of the buffer. Used to resize. */
504 unsigned int dcx_max
;
505 /* Number of valid bytes in the buffer. */
506 unsigned int dcx_rlen
;
509 /* Return the current position. */
512 vms_lib_btell (struct bfd
*abfd
)
514 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
518 /* Read the header of the next data block if all bytes of the current block
522 vms_lib_read_block (struct bfd
*abfd
)
524 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
526 if (vec
->blk_off
== DATA__LENGTH
)
528 unsigned char hdr
[DATA__DATA
];
530 /* Read next block. */
531 if (bfd_seek (abfd
->my_archive
, vec
->next_block
, SEEK_SET
) != 0)
533 if (bfd_bread (hdr
, sizeof (hdr
), abfd
->my_archive
) != sizeof (hdr
))
535 vec
->next_block
= (bfd_getl32 (hdr
+ 2) - 1) * VMS_BLOCK_SIZE
;
536 vec
->blk_off
= sizeof (hdr
);
541 /* Read NBYTES from ABFD into BUF if not NULL. If BUF is NULL, bytes are
542 not stored. Read linearly from the library, but handle blocks. This
543 function does not handle records nor EOF. */
546 vms_lib_bread_raw (struct bfd
*abfd
, void *buf
, file_ptr nbytes
)
548 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
556 /* Be sure the current data block is read. */
557 if (!vms_lib_read_block (abfd
))
560 l
= DATA__LENGTH
- vec
->blk_off
;
567 if (bfd_bread (buf
, l
, abfd
->my_archive
) != l
)
572 if (bfd_seek (abfd
->my_archive
, l
, SEEK_CUR
) != 0)
585 /* Decompress NBYTES from VEC. Store the bytes into BUF if not NULL. */
588 vms_lib_dcx (struct vms_lib_iovec
*vec
, unsigned char *buf
, file_ptr nbytes
)
590 struct dcxsbm_desc
*sbm
;
596 /* The loop below expect to deliver at least one byte. */
600 /* Get the current state. */
602 offset
= vec
->dcx_offset
;
603 j
= vec
->dcx_pos
& 7;
605 for (i
= vec
->dcx_pos
>> 3; i
< vec
->dcx_rlen
; i
++)
607 unsigned char b
= vec
->dcx_buf
[i
];
613 if (!(sbm
->flags
[offset
>> 3] & (1 << (offset
& 7))))
615 unsigned int n_offset
= sbm
->nodes
[offset
];
618 /* End of buffer. Stay where we are. */
619 vec
->dcx_pos
= (i
<< 3) + j
;
622 vec
->dcx_offset
= offset
;
626 offset
= 2 * n_offset
;
630 unsigned char v
= sbm
->nodes
[offset
];
632 sbm
= vec
->dcxsbms
+ sbm
->next
[v
];
643 vec
->dcx_pos
= (i
<< 3) + j
+ 1;
644 vec
->dcx_offset
= offset
;
657 /* Standard IOVEC function. */
660 vms_lib_bread (struct bfd
*abfd
, void *buf
, file_ptr nbytes
)
662 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
666 /* Do not read past the end. */
667 if (vec
->where
>= vec
->file_len
)
673 if (vec
->rec_rem
== 0)
675 unsigned char blen
[2];
677 /* Read record length. */
678 if (vms_lib_bread_raw (abfd
, &blen
, sizeof (blen
)) != sizeof (blen
))
680 vec
->rec_len
= bfd_getl16 (blen
);
681 if (bfd_libdata (abfd
->my_archive
)->kind
== vms_lib_txt
)
683 /* Discard record size and align byte. */
685 vec
->rec_rem
= vec
->rec_len
;
689 /* Prepend record size. */
690 vec
->rec_pos
= REC_POS_LEN0
;
691 vec
->rec_rem
= (vec
->rec_len
+ 1) & ~1; /* With align byte. */
693 if (vec
->rec_len
== 3)
695 /* Possibly end of file. Check the pattern. */
696 if (vms_lib_bread_raw (abfd
, vec
->pattern
, 4) != 4)
698 if (!memcmp (vec
->pattern
, eotdesc
+ 2, 3))
700 /* This is really an EOF. */
702 vec
->file_len
= vec
->where
;
707 if (vec
->dcxsbms
!= NULL
)
709 /* This is a compressed member. */
713 /* Be sure there is enough room for the expansion. */
714 len
= (vec
->rec_len
+ 1) & ~1;
715 if (len
> vec
->dcx_max
)
717 while (len
> vec
->dcx_max
)
719 vec
->dcx_buf
= bfd_alloc (abfd
, vec
->dcx_max
);
720 if (vec
->dcx_buf
== NULL
)
724 /* Read the compressed record. */
726 if (vec
->rec_len
== 3)
729 memcpy (vec
->dcx_buf
, vec
->pattern
, 3);
733 elen
= vms_lib_bread_raw (abfd
, vec
->dcx_buf
, len
);
738 /* Dummy expansion to get the expanded length. */
740 vec
->dcx_sbm
= vec
->dcxsbms
;
742 elen
= vms_lib_dcx (vec
, NULL
, 0x10000);
748 /* Reset the state. */
750 vec
->dcx_sbm
= vec
->dcxsbms
;
754 if (vec
->rec_pos
< 0)
757 switch (vec
->rec_pos
)
760 c
= vec
->rec_len
& 0xff;
761 vec
->rec_pos
= REC_POS_LEN1
;
764 c
= (vec
->rec_len
>> 8) & 0xff;
780 *(unsigned char *)buf
= c
;
788 if (nbytes
> vec
->rec_rem
)
789 chunk
= vec
->rec_rem
;
793 if (vec
->dcxsbms
!= NULL
)
795 /* Optimize the stat() case: no need to decompress again as we
797 if (!(buf
== NULL
&& chunk
== vec
->rec_rem
))
798 chunk
= vms_lib_dcx (vec
, buf
, chunk
);
802 if (vec
->rec_len
== 3)
805 memcpy (buf
, vec
->pattern
+ vec
->rec_pos
, chunk
);
808 chunk
= vms_lib_bread_raw (abfd
, buf
, chunk
);
816 vec
->rec_pos
+= chunk
;
817 vec
->rec_rem
-= chunk
;
819 if (vec
->rec_rem
== 0)
821 if (bfd_libdata (abfd
->my_archive
)->kind
== vms_lib_txt
)
823 if ((vec
->rec_len
& 1) == 1
825 && vec
->dcxsbms
== NULL
)
827 /* Eat the pad byte. */
829 if (vms_lib_bread_raw (abfd
, &pad
, 1) != 1)
832 vec
->rec_pos
= REC_POS_NL
;
837 if ((vec
->rec_len
& 1) == 1 && vec
->dcxsbms
!= NULL
)
839 vec
->rec_pos
= REC_POS_PAD
;
849 /* Standard function, but we currently only handle the rewind case. */
852 vms_lib_bseek (struct bfd
*abfd
, file_ptr offset
, int whence
)
854 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
856 if (whence
== SEEK_SET
&& offset
== 0)
861 vec
->blk_off
= vec
->init_blk_off
;
862 vec
->next_block
= vec
->init_next_block
;
864 if (bfd_seek (abfd
->my_archive
, vec
->first_block
, SEEK_SET
) != 0)
873 vms_lib_bwrite (struct bfd
*abfd ATTRIBUTE_UNUSED
,
874 const void *where ATTRIBUTE_UNUSED
,
875 file_ptr nbytes ATTRIBUTE_UNUSED
)
881 vms_lib_bclose (struct bfd
*abfd
)
883 abfd
->iostream
= NULL
;
888 vms_lib_bflush (struct bfd
*abfd ATTRIBUTE_UNUSED
)
894 vms_lib_bstat (struct bfd
*abfd ATTRIBUTE_UNUSED
,
895 struct stat
*sb ATTRIBUTE_UNUSED
)
902 vms_lib_bmmap (struct bfd
*abfd ATTRIBUTE_UNUSED
,
903 void *addr ATTRIBUTE_UNUSED
,
904 bfd_size_type len ATTRIBUTE_UNUSED
,
905 int prot ATTRIBUTE_UNUSED
,
906 int flags ATTRIBUTE_UNUSED
,
907 file_ptr offset ATTRIBUTE_UNUSED
)
912 static const struct bfd_iovec vms_lib_iovec
= {
913 &vms_lib_bread
, &vms_lib_bwrite
, &vms_lib_btell
, &vms_lib_bseek
,
914 &vms_lib_bclose
, &vms_lib_bflush
, &vms_lib_bstat
, &vms_lib_bmmap
917 /* Open a library module. FILEPOS is the position of the module header. */
920 vms_lib_bopen (bfd
*el
, file_ptr filepos
)
922 struct vms_lib_iovec
*vec
;
925 struct lib_tdata
*tdata
= bfd_libdata (el
->my_archive
);
928 /* Allocate and initialized the iovec. */
929 vec
= bfd_zalloc (el
, sizeof (*vec
));
934 el
->iovec
= &vms_lib_iovec
;
936 /* File length is not known. */
939 /* Read the first data block. */
940 vec
->next_block
= filepos
& ~(VMS_BLOCK_SIZE
- 1);
941 vec
->blk_off
= DATA__LENGTH
;
942 if (!vms_lib_read_block (el
))
945 /* Prepare to read the first record. */
946 vec
->blk_off
= filepos
& (VMS_BLOCK_SIZE
- 1);
948 if (bfd_seek (el
->my_archive
, filepos
, SEEK_SET
) != 0)
951 /* Read Record length + MHD + align byte. */
952 len
= tdata
->mhd_size
;
953 if (vms_lib_bread_raw (el
, buf
, 2) != 2)
955 if (bfd_getl16 (buf
) != len
)
957 len
= (len
+ 1) & ~1;
958 BFD_ASSERT (len
<= sizeof (buf
));
959 if (vms_lib_bread_raw (el
, buf
, len
) != len
)
962 /* Get info from mhd. */
963 mhd
= (struct vms_mhd
*)buf
;
964 if (len
>= sizeof (struct vms_mhd
))
965 el
->selective_search
= (mhd
->objstat
& MHD__M_SELSRC
) ? 1 : 0;
966 el
->mtime
= vms_rawtime_to_time_t (mhd
->datim
);
967 el
->mtime_set
= TRUE
;
969 /* Reinit the iovec so that seek() will point to the first record after
972 vec
->init_blk_off
= vec
->blk_off
;
973 vec
->init_next_block
= vec
->next_block
;
974 vec
->first_block
= bfd_tell (el
->my_archive
);
975 vec
->dcxsbms
= bfd_libdata (el
->my_archive
)->dcxsbm
;
977 if (vec
->dcxsbms
!= NULL
)
980 vec
->dcx_max
= 10 * 1024;
981 vec
->dcx_buf
= bfd_alloc (el
, vec
->dcx_max
);
983 if (vec
->dcx_buf
== NULL
)
989 /* Standard function: get member at IDX. */
992 _bfd_vms_lib_get_elt_at_index (bfd
*abfd
, symindex idx
)
994 struct lib_tdata
*tdata
= bfd_libdata (abfd
);
999 for (i
= 0; i
< tdata
->nbr_modules
; i
++)
1001 if (tdata
->modules
[i
].file_offset
== (file_ptr
)idx
)
1005 /* Invalid index. */
1006 if (i
>= tdata
->nbr_modules
)
1009 /* Already loaded. */
1010 if (tdata
->cache
[i
])
1011 return tdata
->cache
[i
];
1014 res
= _bfd_create_empty_archive_element_shell (abfd
);
1015 if (!vms_lib_bopen (res
, idx
))
1017 res
->filename
= tdata
->modules
[i
].name
;
1019 tdata
->cache
[i
] = res
;
1024 /* Elements of an imagelib are stubs. You can get the real image with this
1028 _bfd_vms_lib_get_imagelib_file (bfd
*el
)
1030 bfd
*archive
= el
->my_archive
;
1031 const char *modname
= el
->filename
;
1032 int modlen
= strlen (modname
);
1037 /* Convert module name to lower case and append '.exe'. */
1038 filename
= bfd_alloc (el
, modlen
+ 5);
1039 if (filename
== NULL
)
1041 for (j
= 0; j
< modlen
; j
++)
1042 if (ISALPHA (modname
[j
]))
1043 filename
[j
] = TOLOWER (modname
[j
]);
1045 filename
[j
] = modname
[j
];
1046 memcpy (filename
+ modlen
, ".exe", 5);
1048 filename
= _bfd_append_relative_path (archive
, filename
);
1049 if (filename
== NULL
)
1051 res
= bfd_openr (filename
, NULL
);
1055 (*_bfd_error_handler
)(_("could not open shared image '%s' from '%s'"),
1056 filename
, archive
->filename
);
1057 bfd_release (archive
, filename
);
1061 /* FIXME: put it in a cache ? */
1065 /* Standard function. */
1068 _bfd_vms_lib_openr_next_archived_file (bfd
*archive
,
1077 idx
= last_file
->proxy_origin
+ 1;
1079 if (idx
>= bfd_libdata (archive
)->nbr_modules
)
1081 bfd_set_error (bfd_error_no_more_archived_files
);
1085 res
= _bfd_vms_lib_get_elt_at_index
1086 (archive
, bfd_libdata (archive
)->modules
[idx
].file_offset
);
1089 res
->proxy_origin
= idx
;
1093 /* Standard function. Just compute the length. */
1096 _bfd_vms_lib_generic_stat_arch_elt (bfd
*abfd
, struct stat
*st
)
1098 struct vms_lib_iovec
*vec
= (struct vms_lib_iovec
*) abfd
->iostream
;
1100 if (abfd
->my_archive
== NULL
)
1102 bfd_set_error (bfd_error_invalid_operation
);
1106 if (vec
->file_len
== (ufile_ptr
)-1)
1108 if (vms_lib_bseek (abfd
, 0, SEEK_SET
) != 0)
1111 /* Compute length. */
1112 while (vms_lib_bread (abfd
, NULL
, 1 << 20) > 0)
1116 st
->st_size
= vec
->file_len
;
1117 if (abfd
->mtime_set
)
1118 st
->st_mtime
= abfd
->mtime
;
1128 /* Internal representation of an index entry. */
1132 /* Corresponding archive member. */
1135 /* Number of reference to this entry. */
1138 /* Length of the key. */
1139 unsigned short namlen
;
1145 /* Used to sort index entries. */
1148 vms_index_cmp (const void *lv
, const void *rv
)
1150 const struct vms_index
*l
= lv
;
1151 const struct vms_index
*r
= rv
;
1153 return strcmp (l
->name
, r
->name
);
1156 /* Maximum number of index blocks level. */
1158 #define MAX_LEVEL 10
1160 /* Get the size of an index entry. */
1163 get_idxlen (struct vms_index
*idx
)
1165 return 7 + idx
->namlen
;
1168 /* Write the index. VBN is the first vbn to be used, and will contain
1169 on return the last vbn.
1170 Return TRUE on success. */
1173 vms_write_index (bfd
*abfd
,
1174 struct vms_index
*idx
, unsigned int nbr
, unsigned int *vbn
,
1175 unsigned int *topvbn
)
1180 struct vms_indexdef
*rblk
[MAX_LEVEL
];
1185 unsigned short lastlen
;
1197 /* Sort the index the first time this function is called. */
1198 qsort (idx
, nbr
, sizeof (struct vms_index
), vms_index_cmp
);
1201 /* Allocate first index block. */
1204 rblk
[0] = bfd_malloc (sizeof (struct vms_indexdef
));
1205 blk
[0].vbn
= (*vbn
)++;
1209 for (i
= 0; i
< nbr
; i
++, idx
++)
1211 unsigned int idxlen
= get_idxlen (idx
);
1212 struct vms_idxdef
*en
;
1215 /* Check if a block might overflow. In this case we will flush this
1216 block and all the blocks below it. */
1217 for (j
= 0; j
< level
; j
++)
1218 if (blk
[j
].len
+ blk
[j
].lastlen
+ idxlen
> INDEXDEF__BLKSIZ
)
1221 for (j
= 0; j
< level
; j
++)
1225 /* There is not enough room to write the new entry in this
1226 block or in a parent block. */
1230 BFD_ASSERT (level
< MAX_LEVEL
);
1232 /* Need to create a parent. */
1235 rblk
[level
] = bfd_malloc (sizeof (struct vms_indexdef
));
1236 bfd_putl32 (*vbn
, rblk
[j
]->parent
);
1238 blk
[level
].vbn
= (*vbn
)++;
1240 blk
[level
].lastlen
= 0;
1245 /* Update parent block: write the new entry. */
1248 en
= (struct vms_idxdef
*)(rblk
[j
]->keys
+ blk
[j
].len
);
1249 memcpy (rblk
[j
+ 1]->keys
+ blk
[j
+ 1].len
, en
,
1251 en
= (struct vms_idxdef
*)
1252 (rblk
[j
+ 1]->keys
+ blk
[j
+ 1].len
);
1253 bfd_putl32 (blk
[j
].vbn
, en
->vbn
);
1254 bfd_putl16 (RFADEF__C_INDEX
, en
->offset
);
1259 /* And allocate it. Do it only on the block that won't be
1260 flushed (so that the parent of the parent can be
1262 blk
[j
+ 1].len
+= blk
[j
].lastlen
;
1263 blk
[j
+ 1].lastlen
= 0;
1266 /* Write this block on the disk. */
1269 bfd_putl16 (blk
[j
].len
+ blk
[j
].lastlen
, rblk
[j
]->used
);
1270 if (bfd_seek (abfd
, (blk
[j
].vbn
- 1) * VMS_BLOCK_SIZE
,
1273 if (bfd_bwrite (rblk
[j
], sizeof (struct vms_indexdef
), abfd
)
1274 != sizeof (struct vms_indexdef
))
1278 /* Reset this block. */
1281 blk
[j
].vbn
= (*vbn
)++;
1284 /* Append it to the block. */
1287 blk
[j
].len
+= blk
[j
].lastlen
;
1291 en
= (struct vms_idxdef
*)(rblk
[j
]->keys
+ blk
[j
].len
);
1292 bfd_putl32 ((idx
->abfd
->proxy_origin
/ VMS_BLOCK_SIZE
) + 1,
1295 ((idx
->abfd
->proxy_origin
% VMS_BLOCK_SIZE
) + DATA__DATA
,
1297 en
->keylen
= idx
->namlen
;
1298 memcpy (en
->keyname
, idx
->name
, idx
->namlen
);
1302 blk
[j
].lastlen
= idxlen
;
1307 *topvbn
= blk
[level
- 1].vbn
;
1313 for (j
= 0; j
< level
; j
++)
1317 /* Update parent block: write the new entry. */
1318 struct vms_idxdef
*en
;
1319 struct vms_idxdef
*par
;
1321 en
= (struct vms_idxdef
*)(rblk
[j
- 1]->keys
+ blk
[j
- 1].len
);
1322 par
= (struct vms_idxdef
*)(rblk
[j
]->keys
+ blk
[j
].len
);
1323 memcpy (par
, en
, blk
[j
- 1].lastlen
);
1324 bfd_putl32 (blk
[j
- 1].vbn
, par
->vbn
);
1325 bfd_putl16 (RFADEF__C_INDEX
, par
->offset
);
1328 /* Write this block on the disk. */
1329 bfd_putl16 (blk
[j
].len
+ blk
[j
].lastlen
, rblk
[j
]->used
);
1330 if (bfd_seek (abfd
, (blk
[j
].vbn
- 1) * VMS_BLOCK_SIZE
,
1333 if (bfd_bwrite (rblk
[j
], sizeof (struct vms_indexdef
), abfd
)
1334 != sizeof (struct vms_indexdef
))
1343 /* Append data to the data block DATA. Force write if PAD is true. */
1346 vms_write_data_block (bfd
*arch
, struct vms_datadef
*data
, file_ptr
*off
,
1347 const unsigned char *buf
, unsigned int len
, int pad
)
1349 while (len
> 0 || pad
)
1351 unsigned int doff
= *off
& (VMS_BLOCK_SIZE
- 1);
1352 unsigned int remlen
= (DATA__LENGTH
- DATA__DATA
) - doff
;
1355 l
= (len
> remlen
) ? remlen
: len
;
1356 memcpy (data
->data
+ doff
, buf
, l
);
1362 if (doff
== (DATA__LENGTH
- DATA__DATA
) || (len
== 0 && pad
))
1366 bfd_putl32 ((*off
/ VMS_BLOCK_SIZE
) + 2, data
->link
);
1368 if (bfd_bwrite (data
, sizeof (*data
), arch
) != sizeof (*data
))
1371 *off
+= DATA__LENGTH
- doff
;
1380 /* Build the symbols index. */
1383 _bfd_vms_lib_build_map (unsigned int nbr_modules
,
1384 struct vms_index
*modules
,
1385 unsigned int *res_cnt
,
1386 struct vms_index
**res
)
1389 asymbol
**syms
= NULL
;
1391 struct vms_index
*map
= NULL
;
1392 unsigned int map_max
= 1024; /* Fine initial default. */
1393 unsigned int map_count
= 0;
1395 map
= (struct vms_index
*) bfd_malloc (map_max
* sizeof (struct vms_index
));
1399 /* Gather symbols. */
1400 for (i
= 0; i
< nbr_modules
; i
++)
1405 bfd
*current
= modules
[i
].abfd
;
1407 if ((bfd_get_file_flags (current
) & HAS_SYMS
) == 0)
1410 storage
= bfd_get_symtab_upper_bound (current
);
1416 if (storage
> syms_max
)
1421 syms
= (asymbol
**) bfd_malloc (syms_max
);
1425 symcount
= bfd_canonicalize_symtab (current
, syms
);
1429 /* Now map over all the symbols, picking out the ones we
1431 for (src_count
= 0; src_count
< symcount
; src_count
++)
1433 flagword flags
= (syms
[src_count
])->flags
;
1434 asection
*sec
= syms
[src_count
]->section
;
1436 if ((flags
& BSF_GLOBAL
1438 || flags
& BSF_INDIRECT
1439 || bfd_is_com_section (sec
))
1440 && ! bfd_is_und_section (sec
))
1442 struct vms_index
*new_map
;
1444 /* This symbol will go into the archive header. */
1445 if (map_count
== map_max
)
1448 new_map
= (struct vms_index
*)
1449 bfd_realloc (map
, map_max
* sizeof (struct vms_index
));
1450 if (new_map
== NULL
)
1455 map
[map_count
].abfd
= current
;
1456 /* FIXME: check length. */
1457 map
[map_count
].namlen
= strlen (syms
[src_count
]->name
);
1458 map
[map_count
].name
= syms
[src_count
]->name
;
1466 *res_cnt
= map_count
;
1478 /* Do the hard work: write an archive on the disk. */
1481 _bfd_vms_lib_write_archive_contents (bfd
*arch
)
1484 unsigned int nbr_modules
;
1485 struct vms_index
*modules
;
1486 unsigned int nbr_symbols
;
1487 struct vms_index
*symbols
;
1488 struct lib_tdata
*tdata
= bfd_libdata (arch
);
1491 unsigned int nbr_mod_iblk
;
1492 unsigned int nbr_sym_iblk
;
1494 unsigned int mod_idx_vbn
;
1495 unsigned int sym_idx_vbn
;
1497 /* Count the number of modules (and do a first sanity check). */
1499 for (current
= arch
->archive_head
;
1501 current
= current
->archive_next
)
1503 /* This check is checking the bfds for the objects we're reading
1504 from (which are usually either an object file or archive on
1505 disk), not the archive entries we're writing to. We don't
1506 actually create bfds for the archive members, we just copy
1507 them byte-wise when we write out the archive. */
1508 if (bfd_write_p (current
) || !bfd_check_format (current
, bfd_object
))
1510 bfd_set_error (bfd_error_invalid_operation
);
1517 /* Build the modules list. */
1518 BFD_ASSERT (tdata
->modules
== NULL
);
1519 modules
= bfd_alloc (arch
, nbr_modules
* sizeof (struct vms_index
));
1520 if (modules
== NULL
)
1523 for (current
= arch
->archive_head
, i
= 0;
1525 current
= current
->archive_next
, i
++)
1529 modules
[i
].abfd
= current
;
1530 modules
[i
].name
= vms_get_module_name (current
->filename
, FALSE
);
1533 /* FIXME: silently truncate long names ? */
1534 nl
= strlen (modules
[i
].name
);
1535 modules
[i
].namlen
= (nl
> MAX_KEYLEN
? MAX_KEYLEN
: nl
);
1538 /* Create the module index. */
1540 if (!vms_write_index (NULL
, modules
, nbr_modules
, &vbn
, NULL
))
1544 /* Create symbol index. */
1545 if (!_bfd_vms_lib_build_map (nbr_modules
, modules
, &nbr_symbols
, &symbols
))
1549 if (!vms_write_index (NULL
, symbols
, nbr_symbols
, &vbn
, NULL
))
1553 /* Write modules and remember their position. */
1554 off
= (1 + nbr_mod_iblk
+ nbr_sym_iblk
) * VMS_BLOCK_SIZE
;
1556 if (bfd_seek (arch
, off
, SEEK_SET
) != 0)
1559 for (i
= 0; i
< nbr_modules
; i
++)
1561 struct vms_datadef data
;
1562 unsigned char blk
[VMS_BLOCK_SIZE
];
1563 struct vms_mhd
*mhd
;
1566 current
= modules
[i
].abfd
;
1567 current
->proxy_origin
= off
;
1569 bfd_putl16 (sizeof (struct vms_mhd
), blk
);
1570 mhd
= (struct vms_mhd
*)(blk
+ 2);
1571 memset (mhd
, 0, sizeof (struct vms_mhd
));
1573 mhd
->id
= MHD__C_MHDID
;
1575 memcpy (mhd
->objid
, "V1.0", 4);
1576 bfd_putl32 (modules
[i
].ref
, mhd
->refcnt
);
1579 sz
= (2 + sizeof (struct vms_mhd
) + 1) & ~1;
1580 if (vms_write_data_block (arch
, &data
, &off
, blk
, sz
, 0) < 0)
1583 if (bfd_seek (current
, 0, SEEK_SET
) != 0)
1588 sz
= bfd_bread (blk
, sizeof (blk
), current
);
1591 if (vms_write_data_block (arch
, &data
, &off
, blk
, sz
, 0) < 0)
1594 if (vms_write_data_block (arch
, &data
, &off
,
1595 eotdesc
, sizeof (eotdesc
), 1) < 0)
1599 /* Write the indexes. */
1601 if (vms_write_index (arch
, modules
, nbr_modules
, &vbn
, &mod_idx_vbn
) != TRUE
)
1603 if (vms_write_index (arch
, symbols
, nbr_symbols
, &vbn
, &sym_idx_vbn
) != TRUE
)
1606 /* Write libary header. */
1608 unsigned char blk
[VMS_BLOCK_SIZE
];
1609 struct vms_lhd
*lhd
= (struct vms_lhd
*)blk
;
1610 struct vms_idd
*idd
= (struct vms_idd
*)(blk
+ sizeof (*lhd
));
1611 unsigned int idd_flags
;
1613 memset (blk
, 0, sizeof (blk
));
1615 lhd
->type
= LBR__C_TYP_EOBJ
;
1617 bfd_putl32 (LHD_SANEID3
, lhd
->sanity
);
1618 bfd_putl16 (3, lhd
->majorid
);
1619 bfd_putl16 (0, lhd
->minorid
);
1620 snprintf ((char *)lhd
->lbrver
+ 1, sizeof (lhd
->lbrver
) - 1,
1622 (unsigned)(BFD_VERSION
/ 100000000UL),
1623 (unsigned)(BFD_VERSION
/ 1000000UL) % 100,
1624 (unsigned)(BFD_VERSION
/ 10000UL) % 100);
1625 lhd
->lbrver
[sizeof (lhd
->lbrver
) - 1] = 0;
1626 lhd
->lbrver
[0] = strlen ((char *)lhd
->lbrver
+ 1);
1629 bfd_putl64 (0, lhd
->credat
);
1630 bfd_putl64 (0, lhd
->updtim
);
1632 lhd
->mhdusz
= sizeof (struct vms_mhd
) - MHD__C_USRDAT
;
1634 bfd_putl32 (nbr_modules
+ nbr_symbols
, lhd
->idxcnt
);
1635 bfd_putl32 (nbr_modules
, lhd
->modcnt
);
1636 bfd_putl32 (nbr_modules
, lhd
->modhdrs
);
1638 bfd_putl32 (vbn
- 1, lhd
->hipreal
);
1639 bfd_putl32 (vbn
- 1, lhd
->hiprusd
);
1641 /* First index (modules name). */
1642 idd_flags
= IDD__FLAGS_ASCII
| IDD__FLAGS_VARLENIDX
1643 | IDD__FLAGS_NOCASECMP
| IDD__FLAGS_NOCASENTR
;
1644 bfd_putl16 (idd_flags
, idd
->flags
);
1645 bfd_putl16 (MAX_KEYLEN
, idd
->keylen
);
1646 bfd_putl16 (mod_idx_vbn
, idd
->vbn
);
1649 /* Second index (symbols name). */
1650 bfd_putl16 (idd_flags
, idd
->flags
);
1651 bfd_putl16 (MAX_KEYLEN
, idd
->keylen
);
1652 bfd_putl16 (sym_idx_vbn
, idd
->vbn
);
1655 if (bfd_seek (arch
, 0, SEEK_SET
) != 0)
1657 if (bfd_bwrite (blk
, sizeof (blk
), arch
) != sizeof (blk
))
1664 bfd_set_error (bfd_error_on_input
, current
, bfd_get_error ());
1668 /* Add a target for text library. This costs almost nothing and is useful to
1669 read VMS library on the host. */
1671 const bfd_target vms_lib_txt_vec
=
1673 "vms-libtxt", /* Name. */
1674 bfd_target_unknown_flavour
,
1675 BFD_ENDIAN_UNKNOWN
, /* byteorder */
1676 BFD_ENDIAN_UNKNOWN
, /* header_byteorder */
1677 0, /* Object flags. */
1678 0, /* Sect flags. */
1679 0, /* symbol_leading_char. */
1680 ' ', /* ar_pad_char. */
1681 15, /* ar_max_namelen. */
1682 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
1683 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
1684 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
,
1685 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
1686 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
1687 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
,
1689 {_bfd_dummy_target
, _bfd_dummy_target
, /* bfd_check_format. */
1690 _bfd_vms_lib_txt_archive_p
, _bfd_dummy_target
},
1691 {bfd_false
, bfd_false
, bfd_false
, bfd_false
}, /* bfd_set_format. */
1692 {bfd_false
, bfd_false
, bfd_false
, bfd_false
}, /* bfd_write_contents. */
1694 BFD_JUMP_TABLE_GENERIC (_bfd_generic
),
1695 BFD_JUMP_TABLE_COPY (_bfd_generic
),
1696 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
1697 BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib
),
1698 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols
),
1699 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs
),
1700 BFD_JUMP_TABLE_WRITE (_bfd_nowrite
),
1701 BFD_JUMP_TABLE_LINK (_bfd_nolink
),
1702 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),