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