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