]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/vms-lib.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / bfd / vms-lib.c
1 /* BFD back-end for VMS archive files.
2
3 Copyright (C) 2010-2021 Free Software Foundation, Inc.
4 Written by Tristan Gingold <gingold@adacore.com>, AdaCore.
5
6 This file is part of BFD, the Binary File Descriptor library.
7
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.
12
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.
17
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. */
22
23 #include "sysdep.h"
24 #include "bfd.h"
25 #include "libbfd.h"
26 #include "safe-ctype.h"
27 #include "bfdver.h"
28 #include "libiberty.h"
29 #include "vms.h"
30 #include "vms/lbr.h"
31 #include "vms/dcx.h"
32
33 /* The standard VMS disk block size. */
34 #ifndef VMS_BLOCK_SIZE
35 #define VMS_BLOCK_SIZE 512
36 #endif
37
38 /* Maximum key length (which is also the maximum symbol length in archive). */
39 #define MAX_KEYLEN 128
40 #define MAX_EKEYLEN 1024
41
42 /* DCX Submaps. */
43
44 struct dcxsbm_desc
45 {
46 unsigned char min_char;
47 unsigned char max_char;
48 unsigned char *flags;
49 unsigned char *nodes;
50 unsigned short *next;
51 };
52
53 /* Kind of library. Used to filter in archive_p. */
54
55 enum vms_lib_kind
56 {
57 vms_lib_vax,
58 vms_lib_alpha,
59 vms_lib_ia64,
60 vms_lib_txt
61 };
62
63 /* Back-end private data. */
64
65 struct lib_tdata
66 {
67 /* Standard tdata for an archive. But we don't use many fields. */
68 struct artdata artdata;
69
70 /* Major version. */
71 unsigned char ver;
72
73 /* Type of the archive. */
74 unsigned char type;
75
76 /* Kind of archive. Summary of its type. */
77 enum vms_lib_kind kind;
78
79 /* Total size of the mhd (element header). */
80 unsigned int mhd_size;
81
82 /* Creation date. */
83 unsigned int credat_lo;
84 unsigned int credat_hi;
85
86 /* Vector of modules (archive elements), already sorted. */
87 unsigned int nbr_modules;
88 struct carsym *modules;
89 bfd **cache;
90
91 /* DCX (decompression) data. */
92 unsigned int nbr_dcxsbm;
93 struct dcxsbm_desc *dcxsbm;
94 };
95
96 #define bfd_libdata(bfd) ((struct lib_tdata *)((bfd)->tdata.any))
97
98 /* End-Of-Text pattern. This is a special record to mark the end of file. */
99
100 static const unsigned char eotdesc[] = { 0x03, 0x00, 0x77, 0x00, 0x77, 0x00 };
101
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
110 freed. */
111
112 struct carsym_mem
113 {
114 /* The table of content. */
115 struct carsym *idx;
116
117 /* Number of entries used in the table. */
118 unsigned int nbr;
119
120 /* Maximum number of entries. */
121 unsigned int max;
122
123 /* Do not allocate more that this number of entries. */
124 unsigned int limit;
125
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;
129 };
130
131 /* Simply add a name to the index. */
132
133 static bfd_boolean
134 vms_add_index (struct carsym_mem *cs, char *name,
135 unsigned int idx_vbn, unsigned int idx_off)
136 {
137 if (cs->nbr == cs->max)
138 {
139 struct carsym *n;
140 size_t amt;
141
142 if (cs->max > -33u / 2 || cs->max >= cs->limit)
143 {
144 bfd_set_error (bfd_error_file_too_big);
145 return FALSE;
146 }
147 cs->max = 2 * cs->max + 32;
148 if (cs->max > cs->limit)
149 cs->max = cs->limit;
150 if (_bfd_mul_overflow (cs->max, sizeof (struct carsym), &amt))
151 {
152 bfd_set_error (bfd_error_file_too_big);
153 return FALSE;
154 }
155
156 if (!cs->realloced)
157 {
158 n = bfd_malloc (amt);
159 if (n == NULL)
160 return FALSE;
161 memcpy (n, cs->idx, cs->nbr * sizeof (struct carsym));
162 /* And unfortunately we can't free cs->idx. */
163 }
164 else
165 {
166 n = bfd_realloc_or_free (cs->idx, amt);
167 if (n == NULL)
168 return FALSE;
169 }
170 cs->idx = n;
171 cs->realloced = TRUE;
172 }
173 cs->idx[cs->nbr].file_offset = (idx_vbn - 1) * VMS_BLOCK_SIZE + idx_off;
174 cs->idx[cs->nbr].name = name;
175 cs->nbr++;
176 return TRUE;
177 }
178
179 /* Follow all member of a lns list (pointed by RFA) and add indexes for
180 NAME. Return FALSE in case of error. */
181
182 static bfd_boolean
183 vms_add_indexes_from_list (bfd *abfd, struct carsym_mem *cs, char *name,
184 struct vms_rfa *rfa)
185 {
186 struct vms_lns lns;
187 unsigned int vbn;
188 file_ptr off;
189
190 while (1)
191 {
192 vbn = bfd_getl32 (rfa->vbn);
193 if (vbn == 0)
194 return TRUE;
195
196 /* Read the LHS. */
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))
200 return FALSE;
201
202 if (!vms_add_index (cs, name,
203 bfd_getl32 (lns.modrfa.vbn),
204 bfd_getl16 (lns.modrfa.offset)))
205 return FALSE;
206
207 rfa = &lns.nxtrfa;
208 }
209 }
210
211 /* Read block VBN from ABFD and store it into BLK. Return FALSE in case of error. */
212
213 static bfd_boolean
214 vms_read_block (bfd *abfd, unsigned int vbn, void *blk)
215 {
216 file_ptr off;
217
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)
221 return FALSE;
222
223 return TRUE;
224 }
225
226 /* Write the content of BLK to block VBN of ABFD. Return FALSE in case of error. */
227
228 static bfd_boolean
229 vms_write_block (bfd *abfd, unsigned int vbn, void *blk)
230 {
231 file_ptr off;
232
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)
236 return FALSE;
237
238 return TRUE;
239 }
240
241 /* Read index block VBN and put the entry in **IDX (which is updated).
242 If the entry is indirect, recurse. */
243
244 static bfd_boolean
245 vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym_mem *cs,
246 unsigned int recur_count)
247 {
248 struct vms_indexdef indexdef;
249 file_ptr off;
250 unsigned char *p;
251 unsigned char *endp;
252 unsigned int n;
253
254 if (recur_count == 100)
255 {
256 bfd_set_error (bfd_error_bad_value);
257 return FALSE;
258 }
259
260 /* Read the index block. */
261 BFD_ASSERT (sizeof (indexdef) == VMS_BLOCK_SIZE);
262 if (!vms_read_block (abfd, vbn, &indexdef))
263 return FALSE;
264
265 /* Traverse it. */
266 p = &indexdef.keys[0];
267 n = bfd_getl16 (indexdef.used);
268 if (n > sizeof (indexdef.keys))
269 return FALSE;
270 endp = p + n;
271 while (p < endp)
272 {
273 unsigned int idx_vbn;
274 unsigned int idx_off;
275 unsigned int keylen;
276 unsigned char *keyname;
277 unsigned int flags;
278
279 /* Extract key length. */
280 if (bfd_libdata (abfd)->ver == LBR_MAJORID
281 && offsetof (struct vms_idx, keyname) <= (size_t) (endp - p))
282 {
283 struct vms_idx *ridx = (struct vms_idx *)p;
284
285 idx_vbn = bfd_getl32 (ridx->rfa.vbn);
286 idx_off = bfd_getl16 (ridx->rfa.offset);
287
288 keylen = ridx->keylen;
289 flags = 0;
290 keyname = ridx->keyname;
291 }
292 else if (bfd_libdata (abfd)->ver == LBR_ELFMAJORID
293 && offsetof (struct vms_elfidx, keyname) <= (size_t) (endp - p))
294 {
295 struct vms_elfidx *ridx = (struct vms_elfidx *)p;
296
297 idx_vbn = bfd_getl32 (ridx->rfa.vbn);
298 idx_off = bfd_getl16 (ridx->rfa.offset);
299
300 keylen = bfd_getl16 (ridx->keylen);
301 flags = ridx->flags;
302 keyname = ridx->keyname;
303 }
304 else
305 return FALSE;
306
307 /* Illegal value. */
308 if (idx_vbn == 0)
309 return FALSE;
310
311 /* Point to the next index entry. */
312 p = keyname + keylen;
313 if (p > endp)
314 return FALSE;
315
316 if (idx_off == RFADEF__C_INDEX)
317 {
318 /* Indirect entry. Recurse. */
319 if (!vms_traverse_index (abfd, idx_vbn, cs, recur_count + 1))
320 return FALSE;
321 }
322 else
323 {
324 /* Add a new entry. */
325 char *name;
326
327 if (flags & ELFIDX__SYMESC)
328 {
329 /* Extended key name. */
330 unsigned int noff = 0;
331 unsigned int koff;
332 unsigned int kvbn;
333 struct vms_kbn *kbn;
334 unsigned char kblk[VMS_BLOCK_SIZE];
335
336 /* Sanity check. */
337 if (keylen != sizeof (struct vms_kbn))
338 return FALSE;
339
340 kbn = (struct vms_kbn *)keyname;
341 keylen = bfd_getl16 (kbn->keylen);
342
343 name = bfd_alloc (abfd, keylen + 1);
344 if (name == NULL)
345 return FALSE;
346 kvbn = bfd_getl32 (kbn->rfa.vbn);
347 koff = bfd_getl16 (kbn->rfa.offset);
348
349 /* Read the key, chunk by chunk. */
350 do
351 {
352 unsigned int klen;
353
354 if (!vms_read_block (abfd, kvbn, kblk))
355 return FALSE;
356 if (koff > sizeof (kblk) - sizeof (struct vms_kbn))
357 return FALSE;
358 kbn = (struct vms_kbn *)(kblk + koff);
359 klen = bfd_getl16 (kbn->keylen);
360 if (klen > sizeof (kblk) - koff)
361 return FALSE;
362 kvbn = bfd_getl32 (kbn->rfa.vbn);
363 koff = bfd_getl16 (kbn->rfa.offset);
364
365 if (noff + klen > keylen)
366 return FALSE;
367 memcpy (name + noff, kbn + 1, klen);
368 noff += klen;
369 }
370 while (kvbn != 0);
371
372 /* Sanity check. */
373 if (noff != keylen)
374 return FALSE;
375 }
376 else
377 {
378 /* Usual key name. */
379 name = bfd_alloc (abfd, keylen + 1);
380 if (name == NULL)
381 return FALSE;
382
383 memcpy (name, keyname, keylen);
384 }
385 name[keylen] = 0;
386
387 if (flags & ELFIDX__LISTRFA)
388 {
389 struct vms_lhs lhs;
390
391 /* Read the LHS. */
392 off = (idx_vbn - 1) * VMS_BLOCK_SIZE + idx_off;
393 if (bfd_seek (abfd, off, SEEK_SET) != 0
394 || bfd_bread (&lhs, sizeof (lhs), abfd) != sizeof (lhs))
395 return FALSE;
396
397 /* These extra entries may cause reallocation of CS. */
398 if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.ng_g_rfa))
399 return FALSE;
400 if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.ng_wk_rfa))
401 return FALSE;
402 if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.g_g_rfa))
403 return FALSE;
404 if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.g_wk_rfa))
405 return FALSE;
406 }
407 else
408 {
409 if (!vms_add_index (cs, name, idx_vbn, idx_off))
410 return FALSE;
411 }
412 }
413 }
414
415 return TRUE;
416 }
417
418 /* Read index #IDX, which must have NBREL entries. */
419
420 static struct carsym *
421 vms_lib_read_index (bfd *abfd, int idx, unsigned int *nbrel)
422 {
423 struct vms_idd idd;
424 unsigned int flags;
425 unsigned int vbn;
426 ufile_ptr filesize;
427 size_t amt;
428 struct carsym *csbuf;
429 struct carsym_mem csm;
430
431 /* Read index desription. */
432 if (bfd_seek (abfd, LHD_IDXDESC + idx * IDD_LENGTH, SEEK_SET) != 0
433 || bfd_bread (&idd, sizeof (idd), abfd) != sizeof (idd))
434 return NULL;
435
436 /* Sanity checks. */
437 flags = bfd_getl16 (idd.flags);
438 if (!(flags & IDD__FLAGS_ASCII)
439 || !(flags & IDD__FLAGS_VARLENIDX))
440 return NULL;
441
442 filesize = bfd_get_file_size (abfd);
443 csm.nbr = 0;
444 csm.max = *nbrel;
445 csm.limit = -1u;
446 csm.realloced = FALSE;
447 if (filesize != 0)
448 {
449 /* Put an upper bound based on a file full of single char keys.
450 This is to prevent fuzzed binary silliness. It is easily
451 possible to set up loops over file blocks that add syms
452 without end. */
453 if (filesize / (sizeof (struct vms_rfa) + 2) <= -1u)
454 csm.limit = filesize / (sizeof (struct vms_rfa) + 2);
455 }
456 if (csm.max > csm.limit)
457 csm.max = csm.limit;
458 if (_bfd_mul_overflow (csm.max, sizeof (struct carsym), &amt))
459 return NULL;
460 csm.idx = csbuf = bfd_alloc (abfd, amt);
461 if (csm.idx == NULL)
462 return NULL;
463
464 /* Note: if the index is empty, there is no block to traverse. */
465 vbn = bfd_getl32 (idd.vbn);
466 if (vbn != 0 && !vms_traverse_index (abfd, vbn, &csm, 0))
467 {
468 if (csm.realloced)
469 free (csm.idx);
470
471 /* Note: in case of error, we can free what was allocated on the
472 BFD's objalloc. */
473 bfd_release (abfd, csbuf);
474 return NULL;
475 }
476
477 if (csm.realloced)
478 {
479 /* There are more entries than the first estimate. Allocate on
480 the BFD's objalloc. */
481 csbuf = bfd_alloc (abfd, csm.nbr * sizeof (struct carsym));
482 if (csbuf == NULL)
483 return NULL;
484 memcpy (csbuf, csm.idx, csm.nbr * sizeof (struct carsym));
485 free (csm.idx);
486 csm.idx = csbuf;
487 }
488 *nbrel = csm.nbr;
489 return csm.idx;
490 }
491
492 /* Standard function. */
493
494 static bfd_cleanup
495 _bfd_vms_lib_archive_p (bfd *abfd, enum vms_lib_kind kind)
496 {
497 struct vms_lhd lhd;
498 unsigned int sanity;
499 unsigned int majorid;
500 struct lib_tdata *tdata_hold;
501 struct lib_tdata *tdata;
502 unsigned int dcxvbn;
503 unsigned int nbr_ent;
504
505 /* Read header. */
506 if (bfd_bread (&lhd, sizeof (lhd), abfd) != sizeof (lhd))
507 {
508 if (bfd_get_error () != bfd_error_system_call)
509 bfd_set_error (bfd_error_wrong_format);
510 return NULL;
511 }
512
513 /* Check sanity (= magic) number. */
514 sanity = bfd_getl32 (lhd.sanity);
515 if (!(sanity == LHD_SANEID3
516 || sanity == LHD_SANEID6
517 || sanity == LHD_SANEID_DCX))
518 {
519 bfd_set_error (bfd_error_wrong_format);
520 return NULL;
521 }
522 majorid = bfd_getl32 (lhd.majorid);
523
524 /* Check archive kind. */
525 switch (kind)
526 {
527 case vms_lib_alpha:
528 if ((lhd.type != LBR__C_TYP_EOBJ && lhd.type != LBR__C_TYP_ESHSTB)
529 || majorid != LBR_MAJORID
530 || lhd.nindex != 2)
531 {
532 bfd_set_error (bfd_error_wrong_format);
533 return NULL;
534 }
535 break;
536 case vms_lib_ia64:
537 if ((lhd.type != LBR__C_TYP_IOBJ && lhd.type != LBR__C_TYP_ISHSTB)
538 || majorid != LBR_ELFMAJORID
539 || lhd.nindex != 2)
540 {
541 bfd_set_error (bfd_error_wrong_format);
542 return NULL;
543 }
544 break;
545 case vms_lib_txt:
546 if ((lhd.type != LBR__C_TYP_TXT
547 && lhd.type != LBR__C_TYP_MLB
548 && lhd.type != LBR__C_TYP_HLP)
549 || majorid != LBR_MAJORID
550 || lhd.nindex != 1)
551 {
552 bfd_set_error (bfd_error_wrong_format);
553 return NULL;
554 }
555 break;
556 default:
557 abort ();
558 }
559
560 /* Allocate and initialize private data. */
561 tdata_hold = bfd_libdata (abfd);
562 tdata = (struct lib_tdata *) bfd_zalloc (abfd, sizeof (struct lib_tdata));
563 if (tdata == NULL)
564 return NULL;
565 abfd->tdata.any = (void *)tdata;
566 tdata->ver = majorid;
567 tdata->mhd_size = MHD__C_USRDAT + lhd.mhdusz;
568 tdata->type = lhd.type;
569 tdata->kind = kind;
570 tdata->credat_lo = bfd_getl32 (lhd.credat + 0);
571 tdata->credat_hi = bfd_getl32 (lhd.credat + 4);
572
573 /* Read indexes. */
574 tdata->nbr_modules = bfd_getl32 (lhd.modcnt);
575 tdata->artdata.symdef_count = bfd_getl32 (lhd.idxcnt) - tdata->nbr_modules;
576 nbr_ent = tdata->nbr_modules;
577 tdata->modules = vms_lib_read_index (abfd, 0, &nbr_ent);
578 if (tdata->modules == NULL || nbr_ent != tdata->nbr_modules)
579 goto err;
580 if (lhd.nindex == 2)
581 {
582 nbr_ent = tdata->artdata.symdef_count;
583 tdata->artdata.symdefs = vms_lib_read_index (abfd, 1, &nbr_ent);
584 if (tdata->artdata.symdefs == NULL)
585 goto err;
586 /* Only IA64 archives may have more entries in the index that what
587 was declared. */
588 if (nbr_ent != tdata->artdata.symdef_count
589 && kind != vms_lib_ia64)
590 goto err;
591 tdata->artdata.symdef_count = nbr_ent;
592 }
593 tdata->cache = bfd_zalloc (abfd, sizeof (bfd *) * tdata->nbr_modules);
594 if (tdata->cache == NULL)
595 goto err;
596
597 /* Read DCX submaps. */
598 dcxvbn = bfd_getl32 (lhd.dcxmapvbn);
599 if (dcxvbn != 0)
600 {
601 unsigned char buf_reclen[4];
602 unsigned int reclen;
603 unsigned char *buf;
604 struct vms_dcxmap *map;
605 unsigned int sbm_off;
606 unsigned int i;
607
608 if (bfd_seek (abfd, (dcxvbn - 1) * VMS_BLOCK_SIZE, SEEK_SET) != 0
609 || bfd_bread (buf_reclen, sizeof (buf_reclen), abfd)
610 != sizeof (buf_reclen))
611 goto err;
612 reclen = bfd_getl32 (buf_reclen);
613 if (reclen < sizeof (struct vms_dcxmap))
614 goto err;
615 buf = _bfd_malloc_and_read (abfd, reclen, reclen);
616 if (buf == NULL)
617 goto err;
618 map = (struct vms_dcxmap *)buf;
619 tdata->nbr_dcxsbm = bfd_getl16 (map->nsubs);
620 sbm_off = bfd_getl16 (map->sub0);
621 tdata->dcxsbm = (struct dcxsbm_desc *)bfd_alloc
622 (abfd, tdata->nbr_dcxsbm * sizeof (struct dcxsbm_desc));
623 for (i = 0; i < tdata->nbr_dcxsbm; i++)
624 {
625 struct vms_dcxsbm *sbm;
626 struct dcxsbm_desc *sbmdesc = &tdata->dcxsbm[i];
627 unsigned int sbm_len;
628 unsigned int sbm_sz;
629 unsigned int off;
630 unsigned char *buf1;
631 unsigned int l, j;
632
633 if (sbm_off > reclen
634 || reclen - sbm_off < sizeof (struct vms_dcxsbm))
635 {
636 err_free_buf:
637 free (buf);
638 goto err;
639 }
640 sbm = (struct vms_dcxsbm *) (buf + sbm_off);
641 sbm_sz = bfd_getl16 (sbm->size);
642 sbm_off += sbm_sz;
643 if (sbm_off > reclen)
644 goto err_free_buf;
645
646 sbmdesc->min_char = sbm->min_char;
647 BFD_ASSERT (sbmdesc->min_char == 0);
648 sbmdesc->max_char = sbm->max_char;
649 sbm_len = sbmdesc->max_char - sbmdesc->min_char + 1;
650 l = (2 * sbm_len + 7) / 8;
651 if (sbm_sz < sizeof (struct vms_dcxsbm) + l + sbm_len
652 || (tdata->nbr_dcxsbm > 1
653 && sbm_sz < sizeof (struct vms_dcxsbm) + l + 3 * sbm_len))
654 goto err_free_buf;
655 sbmdesc->flags = (unsigned char *)bfd_alloc (abfd, l);
656 off = bfd_getl16 (sbm->flags);
657 if (off > sbm_sz
658 || sbm_sz - off < l)
659 goto err_free_buf;
660 memcpy (sbmdesc->flags, (bfd_byte *) sbm + off, l);
661 sbmdesc->nodes = (unsigned char *)bfd_alloc (abfd, 2 * sbm_len);
662 off = bfd_getl16 (sbm->nodes);
663 if (off > sbm_sz
664 || sbm_sz - off < 2 * sbm_len)
665 goto err_free_buf;
666 memcpy (sbmdesc->nodes, (bfd_byte *) sbm + off, 2 * sbm_len);
667 off = bfd_getl16 (sbm->next);
668 if (off != 0)
669 {
670 if (off > sbm_sz
671 || sbm_sz - off < 2 * sbm_len)
672 goto err_free_buf;
673 /* Read the 'next' array. */
674 sbmdesc->next = (unsigned short *) bfd_alloc (abfd, 2 * sbm_len);
675 buf1 = (bfd_byte *) sbm + off;
676 for (j = 0; j < sbm_len; j++)
677 sbmdesc->next[j] = bfd_getl16 (buf1 + j * 2);
678 }
679 else
680 {
681 /* There is no next array if there is only one submap. */
682 BFD_ASSERT (tdata->nbr_dcxsbm == 1);
683 sbmdesc->next = NULL;
684 }
685 }
686 free (buf);
687 }
688 else
689 {
690 tdata->nbr_dcxsbm = 0;
691 }
692
693 /* The map is always present. Also mark shared image library. */
694 abfd->has_armap = TRUE;
695 if (tdata->type == LBR__C_TYP_ESHSTB || tdata->type == LBR__C_TYP_ISHSTB)
696 abfd->is_thin_archive = TRUE;
697
698 return _bfd_no_cleanup;
699
700 err:
701 bfd_release (abfd, tdata);
702 abfd->tdata.any = (void *)tdata_hold;
703 return NULL;
704 }
705
706 /* Standard function for alpha libraries. */
707
708 bfd_cleanup
709 _bfd_vms_lib_alpha_archive_p (bfd *abfd)
710 {
711 return _bfd_vms_lib_archive_p (abfd, vms_lib_alpha);
712 }
713
714 /* Standard function for ia64 libraries. */
715
716 bfd_cleanup
717 _bfd_vms_lib_ia64_archive_p (bfd *abfd)
718 {
719 return _bfd_vms_lib_archive_p (abfd, vms_lib_ia64);
720 }
721
722 /* Standard function for text libraries. */
723
724 static bfd_cleanup
725 _bfd_vms_lib_txt_archive_p (bfd *abfd)
726 {
727 return _bfd_vms_lib_archive_p (abfd, vms_lib_txt);
728 }
729
730 /* Standard bfd function. */
731
732 static bfd_boolean
733 _bfd_vms_lib_mkarchive (bfd *abfd, enum vms_lib_kind kind)
734 {
735 struct lib_tdata *tdata;
736
737 tdata = (struct lib_tdata *) bfd_zalloc (abfd, sizeof (struct lib_tdata));
738 if (tdata == NULL)
739 return FALSE;
740
741 abfd->tdata.any = (void *)tdata;
742 vms_get_time (&tdata->credat_hi, &tdata->credat_lo);
743
744 tdata->kind = kind;
745 switch (kind)
746 {
747 case vms_lib_alpha:
748 tdata->ver = LBR_MAJORID;
749 tdata->mhd_size = offsetof (struct vms_mhd, pad1);
750 tdata->type = LBR__C_TYP_EOBJ;
751 break;
752 case vms_lib_ia64:
753 tdata->ver = LBR_ELFMAJORID;
754 tdata->mhd_size = sizeof (struct vms_mhd);
755 tdata->type = LBR__C_TYP_IOBJ;
756 break;
757 default:
758 abort ();
759 }
760
761 tdata->nbr_modules = 0;
762 tdata->artdata.symdef_count = 0;
763 tdata->modules = NULL;
764 tdata->artdata.symdefs = NULL;
765 tdata->cache = NULL;
766
767 return TRUE;
768 }
769
770 bfd_boolean
771 _bfd_vms_lib_alpha_mkarchive (bfd *abfd)
772 {
773 return _bfd_vms_lib_mkarchive (abfd, vms_lib_alpha);
774 }
775
776 bfd_boolean
777 _bfd_vms_lib_ia64_mkarchive (bfd *abfd)
778 {
779 return _bfd_vms_lib_mkarchive (abfd, vms_lib_ia64);
780 }
781
782 /* Find NAME in the symbol index. Return the index. */
783
784 symindex
785 _bfd_vms_lib_find_symbol (bfd *abfd, const char *name)
786 {
787 struct lib_tdata *tdata = bfd_libdata (abfd);
788 carsym *syms = tdata->artdata.symdefs;
789 int lo, hi;
790
791 /* Open-coded binary search for speed. */
792 lo = 0;
793 hi = tdata->artdata.symdef_count - 1;
794
795 while (lo <= hi)
796 {
797 int mid = lo + (hi - lo) / 2;
798 int diff;
799
800 diff = (char)(name[0] - syms[mid].name[0]);
801 if (diff == 0)
802 diff = strcmp (name, syms[mid].name);
803 if (diff == 0)
804 return mid;
805 else if (diff < 0)
806 hi = mid - 1;
807 else
808 lo = mid + 1;
809 }
810 return BFD_NO_MORE_SYMBOLS;
811 }
812
813 /* IO vector for archive member. Need that because members are not linearly
814 stored in archives. */
815
816 struct vms_lib_iovec
817 {
818 /* Current offset. */
819 ufile_ptr where;
820
821 /* Length of the module, when known. */
822 ufile_ptr file_len;
823
824 /* Current position in the record from bfd_bread point of view (ie, after
825 decompression). 0 means that no data byte have been read, -2 and -1
826 are reserved for the length word. */
827 int rec_pos;
828 #define REC_POS_NL -4
829 #define REC_POS_PAD -3
830 #define REC_POS_LEN0 -2
831 #define REC_POS_LEN1 -1
832
833 /* Record length. */
834 unsigned short rec_len;
835 /* Number of bytes to read in the current record. */
836 unsigned short rec_rem;
837 /* Offset of the next block. */
838 file_ptr next_block;
839 /* Current *data* offset in the data block. */
840 unsigned short blk_off;
841
842 /* Offset of the first block. Extracted from the index. */
843 file_ptr first_block;
844
845 /* Initial next_block. Extracted when the MHD is read. */
846 file_ptr init_next_block;
847 /* Initial blk_off, once the MHD is read. */
848 unsigned short init_blk_off;
849
850 /* Used to store any 3 byte record, which could be the EOF pattern. */
851 unsigned char pattern[4];
852
853 /* DCX. */
854 struct dcxsbm_desc *dcxsbms;
855 /* Current submap. */
856 struct dcxsbm_desc *dcx_sbm;
857 /* Current offset in the submap. */
858 unsigned int dcx_offset;
859 int dcx_pos;
860
861 /* Compressed buffer. */
862 unsigned char *dcx_buf;
863 /* Size of the buffer. Used to resize. */
864 unsigned int dcx_max;
865 /* Number of valid bytes in the buffer. */
866 unsigned int dcx_rlen;
867 };
868
869 /* Return the current position. */
870
871 static file_ptr
872 vms_lib_btell (struct bfd *abfd)
873 {
874 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
875 return vec->where;
876 }
877
878 /* Read the header of the next data block if all bytes of the current block
879 have been read. */
880
881 static bfd_boolean
882 vms_lib_read_block (struct bfd *abfd)
883 {
884 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
885
886 if (vec->blk_off == DATA__LENGTH)
887 {
888 unsigned char hdr[DATA__DATA];
889
890 /* Read next block. */
891 if (bfd_seek (abfd->my_archive, vec->next_block, SEEK_SET) != 0)
892 return FALSE;
893 if (bfd_bread (hdr, sizeof (hdr), abfd->my_archive) != sizeof (hdr))
894 return FALSE;
895 vec->next_block = (bfd_getl32 (hdr + 2) - 1) * VMS_BLOCK_SIZE;
896 vec->blk_off = sizeof (hdr);
897 }
898 return TRUE;
899 }
900
901 /* Read NBYTES from ABFD into BUF if not NULL. If BUF is NULL, bytes are
902 not stored. Read linearly from the library, but handle blocks. This
903 function does not handle records nor EOF. */
904
905 static file_ptr
906 vms_lib_bread_raw (struct bfd *abfd, unsigned char *buf, file_ptr nbytes)
907 {
908 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
909 file_ptr res;
910
911 res = 0;
912 while (nbytes > 0)
913 {
914 unsigned int l;
915
916 /* Be sure the current data block is read. */
917 if (!vms_lib_read_block (abfd))
918 return -1;
919
920 /* Do not read past the data block, do not read more than requested. */
921 l = DATA__LENGTH - vec->blk_off;
922 if (l > nbytes)
923 l = nbytes;
924 if (l == 0)
925 return 0;
926 if (buf != NULL)
927 {
928 /* Really read into BUF. */
929 if (bfd_bread (buf, l, abfd->my_archive) != l)
930 return -1;
931 }
932 else
933 {
934 /* Make as if we are reading. */
935 if (bfd_seek (abfd->my_archive, l, SEEK_CUR) != 0)
936 return -1;
937 }
938
939 if (buf != NULL)
940 buf += l;
941 vec->blk_off += l;
942 nbytes -= l;
943 res += l;
944 }
945 return res;
946 }
947
948 /* Decompress NBYTES from VEC. Store the bytes into BUF if not NULL. */
949
950 static file_ptr
951 vms_lib_dcx (struct vms_lib_iovec *vec, unsigned char *buf, file_ptr nbytes)
952 {
953 struct dcxsbm_desc *sbm;
954 unsigned int i;
955 unsigned int offset;
956 unsigned int j;
957 file_ptr res = 0;
958
959 /* The loop below expect to deliver at least one byte. */
960 if (nbytes == 0)
961 return 0;
962
963 /* Get the current state. */
964 sbm = vec->dcx_sbm;
965 offset = vec->dcx_offset;
966 j = vec->dcx_pos & 7;
967
968 for (i = vec->dcx_pos >> 3; i < vec->dcx_rlen; i++)
969 {
970 unsigned char b = vec->dcx_buf[i];
971
972 for (; j < 8; j++)
973 {
974 if (b & (1 << j))
975 offset++;
976 if (!(sbm->flags[offset >> 3] & (1 << (offset & 7))))
977 {
978 unsigned int n_offset = sbm->nodes[offset];
979 if (n_offset == 0)
980 {
981 /* End of buffer. Stay where we are. */
982 vec->dcx_pos = (i << 3) + j;
983 if (b & (1 << j))
984 offset--;
985 vec->dcx_offset = offset;
986 vec->dcx_sbm = sbm;
987 return res;
988 }
989 offset = 2 * n_offset;
990 }
991 else
992 {
993 unsigned char v = sbm->nodes[offset];
994
995 if (sbm->next != NULL)
996 sbm = vec->dcxsbms + sbm->next[v];
997 offset = 0;
998 res++;
999
1000 if (buf)
1001 {
1002 *buf++ = v;
1003 nbytes--;
1004
1005 if (nbytes == 0)
1006 {
1007 vec->dcx_pos = (i << 3) + j + 1;
1008 vec->dcx_offset = offset;
1009 vec->dcx_sbm = sbm;
1010
1011 return res;
1012 }
1013 }
1014 }
1015 }
1016 j = 0;
1017 }
1018 return -1;
1019 }
1020
1021 /* Standard IOVEC function. */
1022
1023 static file_ptr
1024 vms_lib_bread (struct bfd *abfd, void *vbuf, file_ptr nbytes)
1025 {
1026 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
1027 file_ptr res;
1028 file_ptr chunk;
1029 unsigned char *buf = (unsigned char *)vbuf;
1030
1031 /* Do not read past the end. */
1032 if (vec->where >= vec->file_len)
1033 return 0;
1034
1035 res = 0;
1036 while (nbytes > 0)
1037 {
1038 if (vec->rec_rem == 0)
1039 {
1040 unsigned char blen[2];
1041
1042 /* Read record length. */
1043 if (vms_lib_bread_raw (abfd, blen, sizeof (blen)) != sizeof (blen))
1044 return -1;
1045 vec->rec_len = bfd_getl16 (blen);
1046 if (bfd_libdata (abfd->my_archive)->kind == vms_lib_txt)
1047 {
1048 /* Discard record size and align byte. */
1049 vec->rec_pos = 0;
1050 vec->rec_rem = vec->rec_len;
1051 }
1052 else
1053 {
1054 /* Prepend record size. */
1055 vec->rec_pos = REC_POS_LEN0;
1056 vec->rec_rem = (vec->rec_len + 1) & ~1; /* With align byte. */
1057 }
1058 if (vec->rec_len == 3)
1059 {
1060 /* Possibly end of file. Check the pattern. */
1061 if (vms_lib_bread_raw (abfd, vec->pattern, 4) != 4)
1062 return -1;
1063 if (!memcmp (vec->pattern, eotdesc + 2, 3))
1064 {
1065 /* This is really an EOF. */
1066 vec->where += res;
1067 vec->file_len = vec->where;
1068 return res;
1069 }
1070 }
1071
1072 if (vec->dcxsbms != NULL)
1073 {
1074 /* This is a compressed member. */
1075 unsigned int len;
1076 file_ptr elen;
1077
1078 /* Be sure there is enough room for the expansion. */
1079 len = (vec->rec_len + 1) & ~1;
1080 if (len > vec->dcx_max)
1081 {
1082 while (len > vec->dcx_max)
1083 vec->dcx_max *= 2;
1084 vec->dcx_buf = bfd_alloc (abfd, vec->dcx_max);
1085 if (vec->dcx_buf == NULL)
1086 return -1;
1087 }
1088
1089 /* Read the compressed record. */
1090 vec->dcx_rlen = len;
1091 if (vec->rec_len == 3)
1092 {
1093 /* Already read. */
1094 memcpy (vec->dcx_buf, vec->pattern, 3);
1095 }
1096 else
1097 {
1098 elen = vms_lib_bread_raw (abfd, vec->dcx_buf, len);
1099 if (elen != len)
1100 return -1;
1101 }
1102
1103 /* Dummy expansion to get the expanded length. */
1104 vec->dcx_offset = 0;
1105 vec->dcx_sbm = vec->dcxsbms;
1106 vec->dcx_pos = 0;
1107 elen = vms_lib_dcx (vec, NULL, 0x10000);
1108 if (elen < 0)
1109 return -1;
1110 vec->rec_len = elen;
1111 vec->rec_rem = elen;
1112
1113 /* Reset the state. */
1114 vec->dcx_offset = 0;
1115 vec->dcx_sbm = vec->dcxsbms;
1116 vec->dcx_pos = 0;
1117 }
1118 }
1119 if (vec->rec_pos < 0)
1120 {
1121 unsigned char c;
1122 switch (vec->rec_pos)
1123 {
1124 case REC_POS_LEN0:
1125 c = vec->rec_len & 0xff;
1126 vec->rec_pos = REC_POS_LEN1;
1127 break;
1128 case REC_POS_LEN1:
1129 c = (vec->rec_len >> 8) & 0xff;
1130 vec->rec_pos = 0;
1131 break;
1132 case REC_POS_PAD:
1133 c = 0;
1134 vec->rec_rem = 0;
1135 break;
1136 case REC_POS_NL:
1137 c = '\n';
1138 vec->rec_rem = 0;
1139 break;
1140 default:
1141 abort ();
1142 }
1143 if (buf != NULL)
1144 {
1145 *buf = c;
1146 buf++;
1147 }
1148 nbytes--;
1149 res++;
1150 continue;
1151 }
1152
1153 if (nbytes > vec->rec_rem)
1154 chunk = vec->rec_rem;
1155 else
1156 chunk = nbytes;
1157
1158 if (vec->dcxsbms != NULL)
1159 {
1160 /* Optimize the stat() case: no need to decompress again as we
1161 know the length. */
1162 if (!(buf == NULL && chunk == vec->rec_rem))
1163 chunk = vms_lib_dcx (vec, buf, chunk);
1164 }
1165 else
1166 {
1167 if (vec->rec_len == 3)
1168 {
1169 if (buf != NULL)
1170 memcpy (buf, vec->pattern + vec->rec_pos, chunk);
1171 }
1172 else
1173 chunk = vms_lib_bread_raw (abfd, buf, chunk);
1174 }
1175 if (chunk < 0)
1176 return -1;
1177 res += chunk;
1178 if (buf != NULL)
1179 buf += chunk;
1180 nbytes -= chunk;
1181 vec->rec_pos += chunk;
1182 vec->rec_rem -= chunk;
1183
1184 if (vec->rec_rem == 0)
1185 {
1186 /* End of record reached. */
1187 if (bfd_libdata (abfd->my_archive)->kind == vms_lib_txt)
1188 {
1189 if ((vec->rec_len & 1) == 1
1190 && vec->rec_len != 3
1191 && vec->dcxsbms == NULL)
1192 {
1193 /* Eat the pad byte. */
1194 unsigned char pad;
1195 if (vms_lib_bread_raw (abfd, &pad, 1) != 1)
1196 return -1;
1197 }
1198 vec->rec_pos = REC_POS_NL;
1199 vec->rec_rem = 1;
1200 }
1201 else
1202 {
1203 if ((vec->rec_len & 1) == 1 && vec->dcxsbms != NULL)
1204 {
1205 vec->rec_pos = REC_POS_PAD;
1206 vec->rec_rem = 1;
1207 }
1208 }
1209 }
1210 }
1211 vec->where += res;
1212 return res;
1213 }
1214
1215 /* Standard function, but we currently only handle the rewind case. */
1216
1217 static int
1218 vms_lib_bseek (struct bfd *abfd, file_ptr offset, int whence)
1219 {
1220 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
1221
1222 if (whence == SEEK_SET && offset == 0)
1223 {
1224 vec->where = 0;
1225 vec->rec_rem = 0;
1226 vec->dcx_pos = -1;
1227 vec->blk_off = vec->init_blk_off;
1228 vec->next_block = vec->init_next_block;
1229
1230 if (bfd_seek (abfd->my_archive, vec->first_block, SEEK_SET) != 0)
1231 return -1;
1232 }
1233 else
1234 abort ();
1235 return 0;
1236 }
1237
1238 static file_ptr
1239 vms_lib_bwrite (struct bfd *abfd ATTRIBUTE_UNUSED,
1240 const void *where ATTRIBUTE_UNUSED,
1241 file_ptr nbytes ATTRIBUTE_UNUSED)
1242 {
1243 return -1;
1244 }
1245
1246 static int
1247 vms_lib_bclose (struct bfd *abfd)
1248 {
1249 abfd->iostream = NULL;
1250 return 0;
1251 }
1252
1253 static int
1254 vms_lib_bflush (struct bfd *abfd ATTRIBUTE_UNUSED)
1255 {
1256 return 0;
1257 }
1258
1259 static int
1260 vms_lib_bstat (struct bfd *abfd ATTRIBUTE_UNUSED,
1261 struct stat *sb ATTRIBUTE_UNUSED)
1262 {
1263 /* Not supported. */
1264 return 0;
1265 }
1266
1267 static void *
1268 vms_lib_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED,
1269 void *addr ATTRIBUTE_UNUSED,
1270 bfd_size_type len ATTRIBUTE_UNUSED,
1271 int prot ATTRIBUTE_UNUSED,
1272 int flags ATTRIBUTE_UNUSED,
1273 file_ptr offset ATTRIBUTE_UNUSED,
1274 void **map_addr ATTRIBUTE_UNUSED,
1275 bfd_size_type *map_len ATTRIBUTE_UNUSED)
1276 {
1277 return (void *) -1;
1278 }
1279
1280 static const struct bfd_iovec vms_lib_iovec = {
1281 &vms_lib_bread, &vms_lib_bwrite, &vms_lib_btell, &vms_lib_bseek,
1282 &vms_lib_bclose, &vms_lib_bflush, &vms_lib_bstat, &vms_lib_bmmap
1283 };
1284
1285 /* Open a library module. FILEPOS is the position of the module header. */
1286
1287 static bfd_boolean
1288 vms_lib_bopen (bfd *el, file_ptr filepos)
1289 {
1290 struct vms_lib_iovec *vec;
1291 unsigned char buf[256];
1292 struct vms_mhd *mhd;
1293 struct lib_tdata *tdata = bfd_libdata (el->my_archive);
1294 unsigned int len;
1295
1296 /* Allocate and initialized the iovec. */
1297 vec = bfd_zalloc (el, sizeof (*vec));
1298 if (vec == NULL)
1299 return FALSE;
1300
1301 el->iostream = vec;
1302 el->iovec = &vms_lib_iovec;
1303
1304 /* File length is not known. */
1305 vec->file_len = -1;
1306
1307 /* Read the first data block. */
1308 vec->next_block = filepos & ~(VMS_BLOCK_SIZE - 1);
1309 vec->blk_off = DATA__LENGTH;
1310 if (!vms_lib_read_block (el))
1311 return FALSE;
1312
1313 /* Prepare to read the first record. */
1314 vec->blk_off = filepos & (VMS_BLOCK_SIZE - 1);
1315 vec->rec_rem = 0;
1316 if (bfd_seek (el->my_archive, filepos, SEEK_SET) != 0)
1317 return FALSE;
1318
1319 /* Read Record length + MHD + align byte. */
1320 len = tdata->mhd_size;
1321 if (vms_lib_bread_raw (el, buf, 2) != 2)
1322 return FALSE;
1323 if (bfd_getl16 (buf) != len)
1324 return FALSE;
1325 len = (len + 1) & ~1;
1326 BFD_ASSERT (len <= sizeof (buf));
1327 if (vms_lib_bread_raw (el, buf, len) != len)
1328 return FALSE;
1329
1330 /* Get info from mhd. */
1331 mhd = (struct vms_mhd *)buf;
1332 /* Check id. */
1333 if (mhd->id != MHD__C_MHDID)
1334 return FALSE;
1335 if (len >= MHD__C_MHDLEN + 1)
1336 el->selective_search = (mhd->objstat & MHD__M_SELSRC) ? 1 : 0;
1337 el->mtime = vms_rawtime_to_time_t (mhd->datim);
1338 el->mtime_set = TRUE;
1339
1340 /* Reinit the iovec so that seek() will point to the first record after
1341 the mhd. */
1342 vec->where = 0;
1343 vec->init_blk_off = vec->blk_off;
1344 vec->init_next_block = vec->next_block;
1345 vec->first_block = bfd_tell (el->my_archive);
1346 vec->dcxsbms = bfd_libdata (el->my_archive)->dcxsbm;
1347
1348 if (vec->dcxsbms != NULL)
1349 {
1350 /* Handle DCX. */
1351 vec->dcx_max = 10 * 1024;
1352 vec->dcx_buf = bfd_alloc (el, vec->dcx_max);
1353 vec->dcx_pos = -1;
1354 if (vec->dcx_buf == NULL)
1355 return -1;
1356 }
1357 return TRUE;
1358 }
1359
1360 /* Get member MODIDX. Return NULL in case of error. */
1361
1362 static bfd *
1363 _bfd_vms_lib_get_module (bfd *abfd, unsigned int modidx)
1364 {
1365 struct lib_tdata *tdata = bfd_libdata (abfd);
1366 bfd *res;
1367 file_ptr file_off;
1368 const char *name;
1369 char *newname;
1370 size_t namelen;
1371
1372 /* Sanity check. */
1373 if (modidx >= tdata->nbr_modules)
1374 return NULL;
1375
1376 /* Already loaded. */
1377 if (tdata->cache[modidx])
1378 return tdata->cache[modidx];
1379
1380 /* Build it. */
1381 file_off = tdata->modules[modidx].file_offset;
1382 if (tdata->type != LBR__C_TYP_IOBJ)
1383 {
1384 res = _bfd_create_empty_archive_element_shell (abfd);
1385 if (res == NULL)
1386 return NULL;
1387
1388 /* Special reader to deal with data blocks. */
1389 if (!vms_lib_bopen (res, file_off))
1390 return NULL;
1391 }
1392 else
1393 {
1394 char buf[256];
1395 struct vms_mhd *mhd;
1396 struct areltdata *arelt;
1397
1398 /* Sanity check. The MHD must be big enough to contain module size. */
1399 if (tdata->mhd_size < offsetof (struct vms_mhd, modsize) + 4)
1400 return NULL;
1401
1402 /* Read the MHD now. */
1403 if (bfd_seek (abfd, file_off, SEEK_SET) != 0)
1404 return NULL;
1405 if (bfd_bread (buf, tdata->mhd_size, abfd) != tdata->mhd_size)
1406 return NULL;
1407
1408 mhd = (struct vms_mhd *) buf;
1409 if (mhd->id != MHD__C_MHDID)
1410 return NULL;
1411
1412 res = _bfd_create_empty_archive_element_shell (abfd);
1413 if (res == NULL)
1414 return NULL;
1415 arelt = bfd_zmalloc (sizeof (*arelt));
1416 if (arelt == NULL)
1417 {
1418 bfd_close (res);
1419 return NULL;
1420 }
1421 res->arelt_data = arelt;
1422
1423 /* Get info from mhd. */
1424 if (tdata->mhd_size >= offsetof (struct vms_mhd, objstat) + 1)
1425 res->selective_search = (mhd->objstat & MHD__M_SELSRC) ? 1 : 0;
1426 res->mtime = vms_rawtime_to_time_t (mhd->datim);
1427 res->mtime_set = TRUE;
1428
1429 arelt->parsed_size = bfd_getl32 (mhd->modsize);
1430
1431 /* No need for a special reader as members are stored linearly.
1432 Just skip the MHD. */
1433 res->origin = file_off + tdata->mhd_size;
1434 }
1435
1436 /* Set filename. */
1437 name = tdata->modules[modidx].name;
1438 namelen = strlen (name);
1439 newname = bfd_malloc (namelen + 4 + 1);
1440 if (newname == NULL)
1441 {
1442 bfd_close (res);
1443 return NULL;
1444 }
1445 strcpy (newname, name);
1446 switch (tdata->type)
1447 {
1448 case LBR__C_TYP_IOBJ:
1449 case LBR__C_TYP_EOBJ:
1450 /* For object archives, append .obj to mimic standard behaviour. */
1451 strcpy (newname + namelen, ".obj");
1452 break;
1453 default:
1454 break;
1455 }
1456 bfd_set_filename (res, newname);
1457 free (newname);
1458 if (bfd_get_filename (res) == NULL)
1459 {
1460 bfd_close (res);
1461 return NULL;
1462 }
1463
1464 tdata->cache[modidx] = res;
1465
1466 return res;
1467 }
1468
1469 /* Standard function: get member at IDX. */
1470
1471 bfd *
1472 _bfd_vms_lib_get_elt_at_index (bfd *abfd, symindex symidx)
1473 {
1474 struct lib_tdata *tdata = bfd_libdata (abfd);
1475 file_ptr file_off;
1476 unsigned int modidx;
1477
1478 /* Check symidx. */
1479 if (symidx > tdata->artdata.symdef_count)
1480 return NULL;
1481 file_off = tdata->artdata.symdefs[symidx].file_offset;
1482
1483 /* Linear-scan. */
1484 for (modidx = 0; modidx < tdata->nbr_modules; modidx++)
1485 {
1486 if (tdata->modules[modidx].file_offset == file_off)
1487 break;
1488 }
1489 if (modidx >= tdata->nbr_modules)
1490 return NULL;
1491
1492 return _bfd_vms_lib_get_module (abfd, modidx);
1493 }
1494
1495 /* Elements of an imagelib are stubs. You can get the real image with this
1496 function. */
1497
1498 bfd *
1499 _bfd_vms_lib_get_imagelib_file (bfd *el)
1500 {
1501 bfd *archive = el->my_archive;
1502 const char *modname = bfd_get_filename (el);
1503 int modlen = strlen (modname);
1504 char *filename;
1505 int j;
1506 bfd *res;
1507
1508 /* Convert module name to lower case and append '.exe'. */
1509 filename = bfd_alloc (el, modlen + 5);
1510 if (filename == NULL)
1511 return NULL;
1512 for (j = 0; j < modlen; j++)
1513 if (ISALPHA (modname[j]))
1514 filename[j] = TOLOWER (modname[j]);
1515 else
1516 filename[j] = modname[j];
1517 memcpy (filename + modlen, ".exe", 5);
1518
1519 filename = _bfd_append_relative_path (archive, filename);
1520 if (filename == NULL)
1521 return NULL;
1522 res = bfd_openr (filename, NULL);
1523
1524 if (res == NULL)
1525 {
1526 /* xgettext:c-format */
1527 _bfd_error_handler(_("could not open shared image '%s' from '%s'"),
1528 filename, bfd_get_filename (archive));
1529 bfd_release (archive, filename);
1530 return NULL;
1531 }
1532
1533 /* FIXME: put it in a cache ? */
1534 return res;
1535 }
1536
1537 /* Standard function. */
1538
1539 bfd *
1540 _bfd_vms_lib_openr_next_archived_file (bfd *archive,
1541 bfd *last_file)
1542 {
1543 unsigned int idx;
1544 bfd *res;
1545
1546 if (!last_file)
1547 idx = 0;
1548 else
1549 idx = last_file->proxy_origin + 1;
1550
1551 if (idx >= bfd_libdata (archive)->nbr_modules)
1552 {
1553 bfd_set_error (bfd_error_no_more_archived_files);
1554 return NULL;
1555 }
1556
1557 res = _bfd_vms_lib_get_module (archive, idx);
1558 if (res == NULL)
1559 return res;
1560 res->proxy_origin = idx;
1561 return res;
1562 }
1563
1564 /* Standard function. Just compute the length. */
1565
1566 int
1567 _bfd_vms_lib_generic_stat_arch_elt (bfd *abfd, struct stat *st)
1568 {
1569 struct lib_tdata *tdata;
1570
1571 /* Sanity check. */
1572 if (abfd->my_archive == NULL)
1573 {
1574 bfd_set_error (bfd_error_invalid_operation);
1575 return -1;
1576 }
1577
1578 tdata = bfd_libdata (abfd->my_archive);
1579 if (tdata->type != LBR__C_TYP_IOBJ)
1580 {
1581 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
1582
1583 if (vec->file_len == (ufile_ptr)-1)
1584 {
1585 if (vms_lib_bseek (abfd, 0, SEEK_SET) != 0)
1586 return -1;
1587
1588 /* Compute length. */
1589 while (vms_lib_bread (abfd, NULL, 1 << 20) > 0)
1590 ;
1591 }
1592 st->st_size = vec->file_len;
1593 }
1594 else
1595 {
1596 st->st_size = ((struct areltdata *)abfd->arelt_data)->parsed_size;
1597 }
1598
1599 if (abfd->mtime_set)
1600 st->st_mtime = abfd->mtime;
1601 else
1602 st->st_mtime = 0;
1603 st->st_uid = 0;
1604 st->st_gid = 0;
1605 st->st_mode = 0644;
1606
1607 return 0;
1608 }
1609
1610 /* Internal representation of an index entry. */
1611
1612 struct lib_index
1613 {
1614 /* Corresponding archive member. */
1615 bfd *abfd;
1616
1617 /* Number of reference to this entry. */
1618 unsigned int ref;
1619
1620 /* Length of the key. */
1621 unsigned short namlen;
1622
1623 /* Key. */
1624 const char *name;
1625 };
1626
1627 /* Used to sort index entries. */
1628
1629 static int
1630 lib_index_cmp (const void *lv, const void *rv)
1631 {
1632 const struct lib_index *l = lv;
1633 const struct lib_index *r = rv;
1634
1635 return strcmp (l->name, r->name);
1636 }
1637
1638 /* Maximum number of index blocks level. */
1639
1640 #define MAX_LEVEL 10
1641
1642 /* Get the size of an index entry. */
1643
1644 static unsigned int
1645 get_idxlen (struct lib_index *idx, bfd_boolean is_elfidx)
1646 {
1647 if (is_elfidx)
1648 {
1649 /* 9 is the size of struct vms_elfidx without keyname. */
1650 if (idx->namlen > MAX_KEYLEN)
1651 return 9 + sizeof (struct vms_kbn);
1652 else
1653 return 9 + idx->namlen;
1654 }
1655 else
1656 {
1657 /* 7 is the size of struct vms_idx without keyname. */
1658 return 7 + idx->namlen;
1659 }
1660 }
1661
1662 /* Write the index composed by NBR symbols contained in IDX.
1663 VBN is the first vbn to be used, and will contain on return the last vbn.
1664 Can be called with ABFD set to NULL just to size the index.
1665 If not null, TOPVBN will be assigned to the vbn of the root index tree.
1666 IS_ELFIDX is true for elfidx (ie ia64) indexes layout.
1667 Return TRUE on success. */
1668
1669 static bfd_boolean
1670 vms_write_index (bfd *abfd,
1671 struct lib_index *idx, unsigned int nbr, unsigned int *vbn,
1672 unsigned int *topvbn, bfd_boolean is_elfidx)
1673 {
1674 /* The index is organized as a tree. This function implements a naive
1675 algorithm to balance the tree: it fills the leaves, and create a new
1676 branch when all upper leaves and branches are full. We only keep in
1677 memory a path to the current leaf. */
1678 unsigned int i;
1679 int j;
1680 int level;
1681 /* Disk blocks for the current path. */
1682 struct vms_indexdef *rblk[MAX_LEVEL];
1683 /* Info on the current blocks. */
1684 struct idxblk
1685 {
1686 unsigned int vbn; /* VBN of the block. */
1687 /* The last entry is identified so that it could be copied to the
1688 parent block. */
1689 unsigned short len; /* Length up to the last entry. */
1690 unsigned short lastlen; /* Length of the last entry. */
1691 } blk[MAX_LEVEL];
1692
1693 /* The kbn blocks are used to store long symbol names. */
1694 unsigned int kbn_sz = 0; /* Number of bytes available in the kbn block. */
1695 unsigned int kbn_vbn = 0; /* VBN of the kbn block. */
1696 unsigned char *kbn_blk = NULL; /* Contents of the kbn block. */
1697
1698 if (nbr == 0)
1699 {
1700 /* No entries. Very easy to handle. */
1701 if (topvbn != NULL)
1702 *topvbn = 0;
1703 return TRUE;
1704 }
1705
1706 if (abfd == NULL)
1707 {
1708 /* Sort the index the first time this function is called. */
1709 qsort (idx, nbr, sizeof (struct lib_index), lib_index_cmp);
1710 }
1711
1712 /* Allocate first index block. */
1713 level = 1;
1714 if (abfd != NULL)
1715 rblk[0] = bfd_zmalloc (sizeof (struct vms_indexdef));
1716 blk[0].vbn = (*vbn)++;
1717 blk[0].len = 0;
1718 blk[0].lastlen = 0;
1719
1720 for (i = 0; i < nbr; i++, idx++)
1721 {
1722 unsigned int idxlen;
1723 int flush = 0;
1724 unsigned int key_vbn = 0;
1725 unsigned int key_off = 0;
1726
1727 idxlen = get_idxlen (idx, is_elfidx);
1728
1729 if (is_elfidx && idx->namlen > MAX_KEYLEN)
1730 {
1731 /* If the key (ie name) is too long, write it in the kbn block. */
1732 unsigned int kl = idx->namlen;
1733 unsigned int kl_chunk;
1734 const char *key = idx->name;
1735
1736 /* Write the key in the kbn, chunk after chunk. */
1737 do
1738 {
1739 if (kbn_sz < sizeof (struct vms_kbn))
1740 {
1741 /* Not enough room in the kbn block. */
1742 if (abfd != NULL)
1743 {
1744 /* Write it to the disk (if there is one). */
1745 if (kbn_vbn != 0)
1746 {
1747 if (!vms_write_block (abfd, kbn_vbn, kbn_blk))
1748 return FALSE;
1749 }
1750 else
1751 {
1752 kbn_blk = bfd_malloc (VMS_BLOCK_SIZE);
1753 if (kbn_blk == NULL)
1754 return FALSE;
1755 }
1756 *(unsigned short *)kbn_blk = 0;
1757 }
1758 /* Allocate a new block for the keys. */
1759 kbn_vbn = (*vbn)++;
1760 kbn_sz = VMS_BLOCK_SIZE - 2;
1761 }
1762 /* Size of the chunk written to the current key block. */
1763 if (kl + sizeof (struct vms_kbn) > kbn_sz)
1764 kl_chunk = kbn_sz - sizeof (struct vms_kbn);
1765 else
1766 kl_chunk = kl;
1767
1768 if (kbn_blk != NULL)
1769 {
1770 struct vms_kbn *kbn;
1771
1772 kbn = (struct vms_kbn *)(kbn_blk + VMS_BLOCK_SIZE - kbn_sz);
1773
1774 if (key_vbn == 0)
1775 {
1776 /* Save the rfa of the first chunk. */
1777 key_vbn = kbn_vbn;
1778 key_off = VMS_BLOCK_SIZE - kbn_sz;
1779 }
1780
1781 bfd_putl16 (kl_chunk, kbn->keylen);
1782 if (kl_chunk == kl)
1783 {
1784 /* No next chunk. */
1785 bfd_putl32 (0, kbn->rfa.vbn);
1786 bfd_putl16 (0, kbn->rfa.offset);
1787 }
1788 else
1789 {
1790 /* Next chunk will be at the start of the next block. */
1791 bfd_putl32 (*vbn, kbn->rfa.vbn);
1792 bfd_putl16 (2, kbn->rfa.offset);
1793 }
1794 memcpy ((char *)(kbn + 1), key, kl_chunk);
1795 key += kl_chunk;
1796 }
1797 kl -= kl_chunk;
1798 kl_chunk = (kl_chunk + 1) & ~1; /* Always align. */
1799 kbn_sz -= kl_chunk + sizeof (struct vms_kbn);
1800 }
1801 while (kl > 0);
1802 }
1803
1804 /* Check if a block might overflow. In this case we will flush this
1805 block and all the blocks below it. */
1806 for (j = 0; j < level; j++)
1807 if (blk[j].len + blk[j].lastlen + idxlen > INDEXDEF__BLKSIZ)
1808 flush = j + 1;
1809
1810 for (j = 0; j < level; j++)
1811 {
1812 if (j < flush)
1813 {
1814 /* There is not enough room to write the new entry in this
1815 block or in a parent block. */
1816
1817 if (j + 1 == level)
1818 {
1819 BFD_ASSERT (level < MAX_LEVEL);
1820
1821 /* Need to create a parent. */
1822 if (abfd != NULL)
1823 {
1824 rblk[level] = bfd_zmalloc (sizeof (struct vms_indexdef));
1825 bfd_putl32 (*vbn, rblk[j]->parent);
1826 }
1827 blk[level].vbn = (*vbn)++;
1828 blk[level].len = 0;
1829 blk[level].lastlen = blk[j].lastlen;
1830
1831 level++;
1832 }
1833
1834 /* Update parent block: write the last entry from the current
1835 block. */
1836 if (abfd != NULL)
1837 {
1838 struct vms_rfa *rfa;
1839
1840 /* Pointer to the last entry in parent block. */
1841 rfa = (struct vms_rfa *)(rblk[j + 1]->keys + blk[j + 1].len);
1842
1843 /* Copy the whole entry. */
1844 BFD_ASSERT (blk[j + 1].lastlen == blk[j].lastlen);
1845 memcpy (rfa, rblk[j]->keys + blk[j].len, blk[j].lastlen);
1846 /* Fix the entry (which in always the first field of an
1847 entry. */
1848 bfd_putl32 (blk[j].vbn, rfa->vbn);
1849 bfd_putl16 (RFADEF__C_INDEX, rfa->offset);
1850 }
1851
1852 if (j + 1 == flush)
1853 {
1854 /* And allocate it. Do it only on the block that won't be
1855 flushed (so that the parent of the parent can be
1856 updated too). */
1857 blk[j + 1].len += blk[j + 1].lastlen;
1858 blk[j + 1].lastlen = 0;
1859 }
1860
1861 /* Write this block on the disk. */
1862 if (abfd != NULL)
1863 {
1864 bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used);
1865 if (!vms_write_block (abfd, blk[j].vbn, rblk[j]))
1866 return FALSE;
1867 }
1868
1869 /* Reset this block. */
1870 blk[j].len = 0;
1871 blk[j].lastlen = 0;
1872 blk[j].vbn = (*vbn)++;
1873 }
1874
1875 /* Append it to the block. */
1876 if (j == 0)
1877 {
1878 /* Keep the previous last entry. */
1879 blk[j].len += blk[j].lastlen;
1880
1881 if (abfd != NULL)
1882 {
1883 struct vms_rfa *rfa;
1884
1885 rfa = (struct vms_rfa *)(rblk[j]->keys + blk[j].len);
1886 bfd_putl32 ((idx->abfd->proxy_origin / VMS_BLOCK_SIZE) + 1,
1887 rfa->vbn);
1888 bfd_putl16
1889 ((idx->abfd->proxy_origin % VMS_BLOCK_SIZE)
1890 + (is_elfidx ? 0 : DATA__DATA),
1891 rfa->offset);
1892
1893 if (is_elfidx)
1894 {
1895 /* Use elfidx format. */
1896 struct vms_elfidx *en = (struct vms_elfidx *)rfa;
1897
1898 en->flags = 0;
1899 if (key_vbn != 0)
1900 {
1901 /* Long symbol name. */
1902 struct vms_kbn *k = (struct vms_kbn *)(en->keyname);
1903 bfd_putl16 (sizeof (struct vms_kbn), en->keylen);
1904 bfd_putl16 (idx->namlen, k->keylen);
1905 bfd_putl32 (key_vbn, k->rfa.vbn);
1906 bfd_putl16 (key_off, k->rfa.offset);
1907 en->flags |= ELFIDX__SYMESC;
1908 }
1909 else
1910 {
1911 bfd_putl16 (idx->namlen, en->keylen);
1912 memcpy (en->keyname, idx->name, idx->namlen);
1913 }
1914 }
1915 else
1916 {
1917 /* Use idx format. */
1918 struct vms_idx *en = (struct vms_idx *)rfa;
1919 en->keylen = idx->namlen;
1920 memcpy (en->keyname, idx->name, idx->namlen);
1921 }
1922 }
1923 }
1924 /* The last added key can now be the last one all blocks in the
1925 path. */
1926 blk[j].lastlen = idxlen;
1927 }
1928 }
1929
1930 /* Save VBN of the root. */
1931 if (topvbn != NULL)
1932 *topvbn = blk[level - 1].vbn;
1933
1934 if (abfd == NULL)
1935 return TRUE;
1936
1937 /* Flush. */
1938 for (j = 1; j < level; j++)
1939 {
1940 /* Update parent block: write the new entry. */
1941 unsigned char *en;
1942 unsigned char *par;
1943 struct vms_rfa *rfa;
1944
1945 en = rblk[j - 1]->keys + blk[j - 1].len;
1946 par = rblk[j]->keys + blk[j].len;
1947 BFD_ASSERT (blk[j].lastlen == blk[j - 1].lastlen);
1948 memcpy (par, en, blk[j - 1].lastlen);
1949 rfa = (struct vms_rfa *)par;
1950 bfd_putl32 (blk[j - 1].vbn, rfa->vbn);
1951 bfd_putl16 (RFADEF__C_INDEX, rfa->offset);
1952 }
1953
1954 for (j = 0; j < level; j++)
1955 {
1956 /* Write this block on the disk. */
1957 bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used);
1958 if (!vms_write_block (abfd, blk[j].vbn, rblk[j]))
1959 return FALSE;
1960
1961 free (rblk[j]);
1962 }
1963
1964 /* Write the last kbn (if any). */
1965 if (kbn_vbn != 0)
1966 {
1967 if (!vms_write_block (abfd, kbn_vbn, kbn_blk))
1968 return FALSE;
1969 free (kbn_blk);
1970 }
1971
1972 return TRUE;
1973 }
1974
1975 /* Append data to the data block DATA. Force write if PAD is true. */
1976
1977 static bfd_boolean
1978 vms_write_data_block (bfd *arch, struct vms_datadef *data, file_ptr *off,
1979 const unsigned char *buf, unsigned int len, int pad)
1980 {
1981 while (len > 0 || pad)
1982 {
1983 unsigned int doff = *off & (VMS_BLOCK_SIZE - 1);
1984 unsigned int remlen = (DATA__LENGTH - DATA__DATA) - doff;
1985 unsigned int l;
1986
1987 l = (len > remlen) ? remlen : len;
1988 memcpy (data->data + doff, buf, l);
1989 buf += l;
1990 len -= l;
1991 doff += l;
1992 *off += l;
1993
1994 if (doff == (DATA__LENGTH - DATA__DATA) || (len == 0 && pad))
1995 {
1996 data->recs = 0;
1997 data->fill_1 = 0;
1998 bfd_putl32 ((*off / VMS_BLOCK_SIZE) + 2, data->link);
1999
2000 if (bfd_bwrite (data, sizeof (*data), arch) != sizeof (*data))
2001 return FALSE;
2002
2003 *off += DATA__LENGTH - doff;
2004
2005 if (len == 0)
2006 break;
2007 }
2008 }
2009 return TRUE;
2010 }
2011
2012 /* Build the symbols index. */
2013
2014 static bfd_boolean
2015 _bfd_vms_lib_build_map (unsigned int nbr_modules,
2016 struct lib_index *modules,
2017 unsigned int *res_cnt,
2018 struct lib_index **res)
2019 {
2020 unsigned int i;
2021 asymbol **syms = NULL;
2022 long syms_max = 0;
2023 struct lib_index *map = NULL;
2024 unsigned int map_max = 1024; /* Fine initial default. */
2025 unsigned int map_count = 0;
2026
2027 map = (struct lib_index *) bfd_malloc (map_max * sizeof (struct lib_index));
2028 if (map == NULL)
2029 goto error_return;
2030
2031 /* Gather symbols. */
2032 for (i = 0; i < nbr_modules; i++)
2033 {
2034 long storage;
2035 long symcount;
2036 long src_count;
2037 bfd *current = modules[i].abfd;
2038
2039 if ((bfd_get_file_flags (current) & HAS_SYMS) == 0)
2040 continue;
2041
2042 storage = bfd_get_symtab_upper_bound (current);
2043 if (storage < 0)
2044 goto error_return;
2045
2046 if (storage != 0)
2047 {
2048 if (storage > syms_max)
2049 {
2050 free (syms);
2051 syms_max = storage;
2052 syms = (asymbol **) bfd_malloc (syms_max);
2053 if (syms == NULL)
2054 goto error_return;
2055 }
2056 symcount = bfd_canonicalize_symtab (current, syms);
2057 if (symcount < 0)
2058 goto error_return;
2059
2060 /* Now map over all the symbols, picking out the ones we
2061 want. */
2062 for (src_count = 0; src_count < symcount; src_count++)
2063 {
2064 flagword flags = (syms[src_count])->flags;
2065 asection *sec = syms[src_count]->section;
2066
2067 if ((flags & BSF_GLOBAL
2068 || flags & BSF_WEAK
2069 || flags & BSF_INDIRECT
2070 || bfd_is_com_section (sec))
2071 && ! bfd_is_und_section (sec))
2072 {
2073 struct lib_index *new_map;
2074
2075 /* This symbol will go into the archive header. */
2076 if (map_count == map_max)
2077 {
2078 map_max *= 2;
2079 new_map = (struct lib_index *)
2080 bfd_realloc (map, map_max * sizeof (struct lib_index));
2081 if (new_map == NULL)
2082 goto error_return;
2083 map = new_map;
2084 }
2085
2086 map[map_count].abfd = current;
2087 map[map_count].namlen = strlen (syms[src_count]->name);
2088 map[map_count].name = syms[src_count]->name;
2089 map_count++;
2090 modules[i].ref++;
2091 }
2092 }
2093 }
2094 }
2095
2096 *res_cnt = map_count;
2097 *res = map;
2098 return TRUE;
2099
2100 error_return:
2101 free (syms);
2102 free (map);
2103 return FALSE;
2104 }
2105
2106 /* Do the hard work: write an archive on the disk. */
2107
2108 bfd_boolean
2109 _bfd_vms_lib_write_archive_contents (bfd *arch)
2110 {
2111 bfd *current;
2112 unsigned int nbr_modules;
2113 struct lib_index *modules;
2114 unsigned int nbr_symbols;
2115 struct lib_index *symbols;
2116 struct lib_tdata *tdata = bfd_libdata (arch);
2117 unsigned int i;
2118 file_ptr off;
2119 unsigned int nbr_mod_iblk;
2120 unsigned int nbr_sym_iblk;
2121 unsigned int vbn;
2122 unsigned int mod_idx_vbn;
2123 unsigned int sym_idx_vbn;
2124 bfd_boolean is_elfidx = tdata->kind == vms_lib_ia64;
2125 unsigned int max_keylen = is_elfidx ? MAX_EKEYLEN : MAX_KEYLEN;
2126
2127 /* Count the number of modules (and do a first sanity check). */
2128 nbr_modules = 0;
2129 for (current = arch->archive_head;
2130 current != NULL;
2131 current = current->archive_next)
2132 {
2133 /* This check is checking the bfds for the objects we're reading
2134 from (which are usually either an object file or archive on
2135 disk), not the archive entries we're writing to. We don't
2136 actually create bfds for the archive members, we just copy
2137 them byte-wise when we write out the archive. */
2138 if (bfd_write_p (current) || !bfd_check_format (current, bfd_object))
2139 {
2140 bfd_set_error (bfd_error_invalid_operation);
2141 goto input_err;
2142 }
2143
2144 nbr_modules++;
2145 }
2146
2147 /* Build the modules list. */
2148 BFD_ASSERT (tdata->modules == NULL);
2149 modules = bfd_alloc (arch, nbr_modules * sizeof (struct lib_index));
2150 if (modules == NULL)
2151 return FALSE;
2152
2153 for (current = arch->archive_head, i = 0;
2154 current != NULL;
2155 current = current->archive_next, i++)
2156 {
2157 unsigned int nl;
2158
2159 modules[i].abfd = current;
2160 modules[i].name = vms_get_module_name (bfd_get_filename (current), FALSE);
2161 modules[i].ref = 1;
2162
2163 /* FIXME: silently truncate long names ? */
2164 nl = strlen (modules[i].name);
2165 modules[i].namlen = (nl > max_keylen ? max_keylen : nl);
2166 }
2167
2168 /* Create the module index. */
2169 vbn = 0;
2170 if (!vms_write_index (NULL, modules, nbr_modules, &vbn, NULL, is_elfidx))
2171 return FALSE;
2172 nbr_mod_iblk = vbn;
2173
2174 /* Create symbol index. */
2175 if (!_bfd_vms_lib_build_map (nbr_modules, modules, &nbr_symbols, &symbols))
2176 return FALSE;
2177
2178 vbn = 0;
2179 if (!vms_write_index (NULL, symbols, nbr_symbols, &vbn, NULL, is_elfidx))
2180 return FALSE;
2181 nbr_sym_iblk = vbn;
2182
2183 /* Write modules and remember their position. */
2184 off = (1 + nbr_mod_iblk + nbr_sym_iblk) * VMS_BLOCK_SIZE;
2185
2186 if (bfd_seek (arch, off, SEEK_SET) != 0)
2187 return FALSE;
2188
2189 for (i = 0; i < nbr_modules; i++)
2190 {
2191 struct vms_datadef data;
2192 unsigned char blk[VMS_BLOCK_SIZE];
2193 struct vms_mhd *mhd;
2194 unsigned int sz;
2195
2196 current = modules[i].abfd;
2197 current->proxy_origin = off;
2198
2199 if (is_elfidx)
2200 sz = 0;
2201 else
2202 {
2203 /* Write the MHD as a record (ie, size first). */
2204 sz = 2;
2205 bfd_putl16 (tdata->mhd_size, blk);
2206 }
2207 mhd = (struct vms_mhd *)(blk + sz);
2208 memset (mhd, 0, sizeof (struct vms_mhd));
2209 mhd->lbrflag = 0;
2210 mhd->id = MHD__C_MHDID;
2211 mhd->objidlng = 4;
2212 memcpy (mhd->objid, "V1.0", 4);
2213 bfd_putl32 (modules[i].ref, mhd->refcnt);
2214 /* FIXME: datim. */
2215
2216 sz += tdata->mhd_size;
2217 sz = (sz + 1) & ~1;
2218
2219 /* Rewind the member to be put into the archive. */
2220 if (bfd_seek (current, 0, SEEK_SET) != 0)
2221 goto input_err;
2222
2223 /* Copy the member into the archive. */
2224 if (is_elfidx)
2225 {
2226 unsigned int modsize = 0;
2227 bfd_size_type amt;
2228 file_ptr off_hdr = off;
2229
2230 /* Read to complete the first block. */
2231 amt = bfd_bread (blk + sz, VMS_BLOCK_SIZE - sz, current);
2232 if (amt == (bfd_size_type)-1)
2233 goto input_err;
2234 modsize = amt;
2235 if (amt < VMS_BLOCK_SIZE - sz)
2236 {
2237 /* The member size is less than a block. Pad the block. */
2238 memset (blk + sz + amt, 0, VMS_BLOCK_SIZE - sz - amt);
2239 }
2240 bfd_putl32 (modsize, mhd->modsize);
2241
2242 /* Write the first block (which contains an mhd). */
2243 if (bfd_bwrite (blk, VMS_BLOCK_SIZE, arch) != VMS_BLOCK_SIZE)
2244 goto input_err;
2245 off += VMS_BLOCK_SIZE;
2246
2247 if (amt == VMS_BLOCK_SIZE - sz)
2248 {
2249 /* Copy the remaining. */
2250 char buffer[DEFAULT_BUFFERSIZE];
2251
2252 while (1)
2253 {
2254 amt = bfd_bread (buffer, sizeof (buffer), current);
2255 if (amt == (bfd_size_type)-1)
2256 goto input_err;
2257 if (amt == 0)
2258 break;
2259 modsize += amt;
2260 if (amt != sizeof (buffer))
2261 {
2262 /* Clear the padding. */
2263 memset (buffer + amt, 0, sizeof (buffer) - amt);
2264 amt = (amt + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1);
2265 }
2266 if (bfd_bwrite (buffer, amt, arch) != amt)
2267 goto input_err;
2268 off += amt;
2269 }
2270
2271 /* Now that the size is known, write the first block (again). */
2272 bfd_putl32 (modsize, mhd->modsize);
2273 if (bfd_seek (arch, off_hdr, SEEK_SET) != 0
2274 || bfd_bwrite (blk, VMS_BLOCK_SIZE, arch) != VMS_BLOCK_SIZE)
2275 goto input_err;
2276 if (bfd_seek (arch, off, SEEK_SET) != 0)
2277 goto input_err;
2278 }
2279 }
2280 else
2281 {
2282 /* Write the MHD. */
2283 if (vms_write_data_block (arch, &data, &off, blk, sz, 0) < 0)
2284 goto input_err;
2285
2286 /* Write the member. */
2287 while (1)
2288 {
2289 sz = bfd_bread (blk, sizeof (blk), current);
2290 if (sz == 0)
2291 break;
2292 if (vms_write_data_block (arch, &data, &off, blk, sz, 0) < 0)
2293 goto input_err;
2294 }
2295
2296 /* Write the end of module marker. */
2297 if (vms_write_data_block (arch, &data, &off,
2298 eotdesc, sizeof (eotdesc), 1) < 0)
2299 goto input_err;
2300 }
2301 }
2302
2303 /* Write the indexes. */
2304 vbn = 2;
2305 if (!vms_write_index (arch, modules, nbr_modules, &vbn, &mod_idx_vbn,
2306 is_elfidx))
2307 return FALSE;
2308 if (!vms_write_index (arch, symbols, nbr_symbols, &vbn, &sym_idx_vbn,
2309 is_elfidx))
2310 return FALSE;
2311
2312 /* Write libary header. */
2313 {
2314 unsigned char blk[VMS_BLOCK_SIZE];
2315 struct vms_lhd *lhd = (struct vms_lhd *)blk;
2316 struct vms_idd *idd = (struct vms_idd *)(blk + sizeof (*lhd));
2317 unsigned int idd_flags;
2318 unsigned int saneid;
2319
2320 memset (blk, 0, sizeof (blk));
2321
2322 lhd->type = tdata->type;
2323 lhd->nindex = 2;
2324 switch (tdata->kind)
2325 {
2326 case vms_lib_alpha:
2327 saneid = LHD_SANEID3;
2328 break;
2329 case vms_lib_ia64:
2330 saneid = LHD_SANEID6;
2331 break;
2332 default:
2333 abort ();
2334 }
2335 bfd_putl32 (saneid, lhd->sanity);
2336 bfd_putl16 (tdata->ver, lhd->majorid);
2337 bfd_putl16 (0, lhd->minorid);
2338 snprintf ((char *)lhd->lbrver + 1, sizeof (lhd->lbrver) - 1,
2339 "GNU ar %u.%u.%u",
2340 (unsigned)(BFD_VERSION / 100000000UL),
2341 (unsigned)(BFD_VERSION / 1000000UL) % 100,
2342 (unsigned)(BFD_VERSION / 10000UL) % 100);
2343 lhd->lbrver[sizeof (lhd->lbrver) - 1] = 0;
2344 lhd->lbrver[0] = strlen ((char *)lhd->lbrver + 1);
2345
2346 bfd_putl32 (tdata->credat_lo, lhd->credat + 0);
2347 bfd_putl32 (tdata->credat_hi, lhd->credat + 4);
2348 vms_raw_get_time (lhd->updtim);
2349
2350 lhd->mhdusz = tdata->mhd_size - MHD__C_USRDAT;
2351
2352 bfd_putl32 (nbr_modules + nbr_symbols, lhd->idxcnt);
2353 bfd_putl32 (nbr_modules, lhd->modcnt);
2354 bfd_putl32 (nbr_modules, lhd->modhdrs);
2355
2356 /* Number of blocks for index. */
2357 bfd_putl32 (nbr_mod_iblk + nbr_sym_iblk, lhd->idxblks);
2358 bfd_putl32 (vbn - 1, lhd->hipreal);
2359 bfd_putl32 (vbn - 1, lhd->hiprusd);
2360
2361 /* VBN of the next free block. */
2362 bfd_putl32 ((off / VMS_BLOCK_SIZE) + 1, lhd->nextvbn);
2363 bfd_putl32 ((off / VMS_BLOCK_SIZE) + 1, lhd->nextrfa + 0);
2364 bfd_putl16 (0, lhd->nextrfa + 4);
2365
2366 /* First index (modules name). */
2367 idd_flags = IDD__FLAGS_ASCII | IDD__FLAGS_VARLENIDX
2368 | IDD__FLAGS_NOCASECMP | IDD__FLAGS_NOCASENTR;
2369 bfd_putl16 (idd_flags, idd->flags);
2370 bfd_putl16 (max_keylen + 1, idd->keylen);
2371 bfd_putl16 (mod_idx_vbn, idd->vbn);
2372 idd++;
2373
2374 /* Second index (symbols name). */
2375 bfd_putl16 (idd_flags, idd->flags);
2376 bfd_putl16 (max_keylen + 1, idd->keylen);
2377 bfd_putl16 (sym_idx_vbn, idd->vbn);
2378 idd++;
2379
2380 if (!vms_write_block (arch, 1, blk))
2381 return FALSE;
2382 }
2383
2384 return TRUE;
2385
2386 input_err:
2387 bfd_set_input_error (current, bfd_get_error ());
2388 return FALSE;
2389 }
2390
2391 /* Add a target for text library. This costs almost nothing and is useful to
2392 read VMS library on the host. */
2393
2394 const bfd_target alpha_vms_lib_txt_vec =
2395 {
2396 "vms-libtxt", /* Name. */
2397 bfd_target_unknown_flavour,
2398 BFD_ENDIAN_UNKNOWN, /* byteorder */
2399 BFD_ENDIAN_UNKNOWN, /* header_byteorder */
2400 0, /* Object flags. */
2401 0, /* Sect flags. */
2402 0, /* symbol_leading_char. */
2403 ' ', /* ar_pad_char. */
2404 15, /* ar_max_namelen. */
2405 0, /* match priority. */
2406 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
2407 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
2408 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
2409 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
2410 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
2411 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
2412 { /* bfd_check_format. */
2413 _bfd_dummy_target,
2414 _bfd_dummy_target,
2415 _bfd_vms_lib_txt_archive_p,
2416 _bfd_dummy_target
2417 },
2418 { /* bfd_set_format. */
2419 _bfd_bool_bfd_false_error,
2420 _bfd_bool_bfd_false_error,
2421 _bfd_bool_bfd_false_error,
2422 _bfd_bool_bfd_false_error
2423 },
2424 { /* bfd_write_contents. */
2425 _bfd_bool_bfd_false_error,
2426 _bfd_bool_bfd_false_error,
2427 _bfd_bool_bfd_false_error,
2428 _bfd_bool_bfd_false_error
2429 },
2430 BFD_JUMP_TABLE_GENERIC (_bfd_generic),
2431 BFD_JUMP_TABLE_COPY (_bfd_generic),
2432 BFD_JUMP_TABLE_CORE (_bfd_nocore),
2433 BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib),
2434 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
2435 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
2436 BFD_JUMP_TABLE_WRITE (_bfd_nowrite),
2437 BFD_JUMP_TABLE_LINK (_bfd_nolink),
2438 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
2439
2440 NULL,
2441
2442 NULL
2443 };