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