bfd/
[deliverable/binutils-gdb.git] / bfd / vms-lib.c
1 /* BFD back-end for VMS archive files.
2
3 Copyright 2010 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 "vms.h"
29 #include "vms/lbr.h"
30 #include "vms/dcx.h"
31
32 /* The standard VMS disk block size. */
33 #ifndef VMS_BLOCK_SIZE
34 #define VMS_BLOCK_SIZE 512
35 #endif
36
37 /* Maximum key length (which is also the maximum symbol length in archive). */
38 #define MAX_KEYLEN 129
39
40 /* DCX Submaps. */
41
42 struct dcxsbm_desc
43 {
44 unsigned char min_char;
45 unsigned char max_char;
46 unsigned char *flags;
47 unsigned char *nodes;
48 unsigned short *next;
49 };
50
51 /* Kind of library. Used to filter in archive_p. */
52
53 enum vms_lib_kind
54 {
55 vms_lib_vax,
56 vms_lib_alpha,
57 vms_lib_ia64,
58 vms_lib_txt
59 };
60
61 /* Back-end private data. */
62
63 struct lib_tdata
64 {
65 /* Standard tdata for an archive. But we don't use many fields. */
66 struct artdata artdata;
67
68 /* Major version. */
69 unsigned char ver;
70
71 /* Type of the archive. */
72 unsigned char type;
73
74 /* Kind of archive. Summary of its type. */
75 enum vms_lib_kind kind;
76
77 /* Total size of the mhd (element header). */
78 unsigned int mhd_size;
79
80 /* Vector of modules (archive elements), already sorted. */
81 unsigned int nbr_modules;
82 struct carsym *modules;
83 bfd **cache;
84
85 /* DCX (decompression) data. */
86 unsigned int nbr_dcxsbm;
87 struct dcxsbm_desc *dcxsbm;
88 };
89
90 #define bfd_libdata(bfd) ((struct lib_tdata *)((bfd)->tdata.any))
91
92 /* End-Of-Text pattern. This is a special record to mark the end of file. */
93
94 static const unsigned char eotdesc[] = { 0x03, 0x00, 0x77, 0x00, 0x77, 0x00 };
95
96 /* Describe the current state of carsym entries while building the archive
97 table of content. Things are simple with Alpha archives as the number
98 of entries is known, but with IA64 archives a entry can make a reference
99 to severals members. Therefore we must be able to extend the table on the
100 fly, but it should be allocated on the bfd - which doesn't support realloc.
101 To reduce the overhead, the table is initially allocated in the BFD's
102 objalloc and extended if necessary on the heap. In the later case, it
103 is finally copied to the BFD's objalloc so that it will automatically be
104 freed. */
105
106 struct carsym_mem
107 {
108 /* The table of content. */
109 struct carsym *idx;
110
111 /* Number of entries used in the table. */
112 unsigned int nbr;
113
114 /* Maximum number of entries. */
115 unsigned int max;
116
117 /* If true, the table was reallocated on the heap. If false, it is still
118 in the BFD's objalloc. */
119 bfd_boolean realloced;
120 };
121
122 /* Simply add a name to the index. */
123
124 static bfd_boolean
125 vms_add_index (struct carsym_mem *cs, char *name,
126 unsigned int idx_vbn, unsigned int idx_off)
127 {
128 if (cs->nbr == cs->max)
129 {
130 struct carsym *n;
131
132 cs->max = 2 * cs->max + 32;
133
134 if (!cs->realloced)
135 {
136 n = bfd_malloc2 (cs->max, sizeof (struct carsym));
137 if (n == NULL)
138 return FALSE;
139 memcpy (n, cs->idx, cs->nbr * sizeof (struct carsym));
140 /* And unfortunately we can't free cs->idx. */
141 }
142 else
143 {
144 n = bfd_realloc_or_free (cs->idx, cs->nbr * sizeof (struct carsym));
145 if (n == NULL)
146 return FALSE;
147 }
148 cs->idx = n;
149 cs->realloced = TRUE;
150 }
151 cs->idx[cs->nbr].file_offset = (idx_vbn - 1) * VMS_BLOCK_SIZE + idx_off;
152 cs->idx[cs->nbr].name = name;
153 cs->nbr++;
154 return TRUE;
155 }
156
157 /* Follow all member of a lns list (pointed by RFA) and add indexes for
158 NAME. Return FALSE in case of error. */
159
160 static bfd_boolean
161 vms_add_indexes_from_list (bfd *abfd, struct carsym_mem *cs, char *name,
162 struct vms_rfa *rfa)
163 {
164 struct vms_lns lns;
165 unsigned int vbn;
166 file_ptr off;
167
168 while (1)
169 {
170 vbn = bfd_getl32 (rfa->vbn);
171 if (vbn == 0)
172 return TRUE;
173
174 /* Read the LHS. */
175 off = (vbn - 1) * VMS_BLOCK_SIZE + bfd_getl16 (rfa->offset);
176 if (bfd_seek (abfd, off, SEEK_SET) != 0
177 || bfd_bread (&lns, sizeof (lns), abfd) != sizeof (lns))
178 return FALSE;
179
180 if (!vms_add_index (cs, name,
181 bfd_getl32 (lns.modrfa.vbn),
182 bfd_getl16 (lns.modrfa.offset)))
183 return FALSE;
184
185 rfa = &lns.nxtrfa;
186 }
187 }
188
189 /* Read index block VBN and put the entry in **IDX (which is updated).
190 If the entry is indirect, recurse. */
191
192 static bfd_boolean
193 vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym_mem *cs)
194 {
195 struct vms_indexdef indexdef;
196 file_ptr off;
197 unsigned char *p;
198 unsigned char *endp;
199
200 /* Read the index block. */
201 off = (vbn - 1) * VMS_BLOCK_SIZE;
202 if (bfd_seek (abfd, off, SEEK_SET) != 0
203 || bfd_bread (&indexdef, sizeof (indexdef), abfd) != sizeof (indexdef))
204 return FALSE;
205
206 /* Traverse it. */
207 p = &indexdef.keys[0];
208 endp = p + bfd_getl16 (indexdef.used);
209 while (p < endp)
210 {
211 unsigned int idx_vbn;
212 unsigned int idx_off;
213 unsigned int keylen;
214 unsigned char *keyname;
215 unsigned int flags;
216
217 /* Extract key length. */
218 if (bfd_libdata (abfd)->ver == LBR_MAJORID)
219 {
220 struct vms_idx *ridx = (struct vms_idx *)p;
221
222 idx_vbn = bfd_getl32 (ridx->rfa.vbn);
223 idx_off = bfd_getl16 (ridx->rfa.offset);
224
225 keylen = ridx->keylen;
226 flags = 0;
227 keyname = ridx->keyname;
228 }
229 else if (bfd_libdata (abfd)->ver == LBR_ELFMAJORID)
230 {
231 struct vms_elfidx *ridx = (struct vms_elfidx *)p;
232
233 idx_vbn = bfd_getl32 (ridx->rfa.vbn);
234 idx_off = bfd_getl16 (ridx->rfa.offset);
235
236 keylen = bfd_getl16 (ridx->keylen);
237 flags = ridx->flags;
238 keyname = ridx->keyname;
239 }
240 else
241 return FALSE;
242
243 /* Illegal value. */
244 if (idx_vbn == 0)
245 return FALSE;
246
247 /* Long symbol names are not yet supported. */
248 if (flags & ELFIDX__SYMESC)
249 return FALSE;
250
251 if (idx_off == RFADEF__C_INDEX)
252 {
253 /* Indirect entry. Recurse. */
254 if (!vms_traverse_index (abfd, idx_vbn, cs))
255 return FALSE;
256 }
257 else
258 {
259 /* Add a new entry. */
260 char *name;
261
262 name = bfd_alloc (abfd, keylen + 1);
263 if (name == NULL)
264 return FALSE;
265 memcpy (name, keyname, keylen);
266 name[keylen] = 0;
267
268 if (flags & ELFIDX__LISTRFA)
269 {
270 struct vms_lhs lhs;
271
272 /* Read the LHS. */
273 off = (idx_vbn - 1) * VMS_BLOCK_SIZE + idx_off;
274 if (bfd_seek (abfd, off, SEEK_SET) != 0
275 || bfd_bread (&lhs, sizeof (lhs), abfd) != sizeof (lhs))
276 return FALSE;
277
278 /* FIXME: this adds extra entries that were not accounted. */
279 if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.ng_g_rfa))
280 return FALSE;
281 if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.ng_wk_rfa))
282 return FALSE;
283 if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.g_g_rfa))
284 return FALSE;
285 if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.g_wk_rfa))
286 return FALSE;
287 }
288 else
289 {
290 if (!vms_add_index (cs, name, idx_vbn, idx_off))
291 return FALSE;
292 }
293 }
294
295 /* Point to the next index entry. */
296 p = keyname + keylen;
297 }
298
299 return TRUE;
300 }
301
302 /* Read index #IDX, which must have NBREL entries. */
303
304 static struct carsym *
305 vms_lib_read_index (bfd *abfd, int idx, unsigned int *nbrel)
306 {
307 struct vms_idd idd;
308 unsigned int flags;
309 unsigned int vbn;
310 struct carsym *csbuf;
311 struct carsym_mem csm;
312
313 /* Read index desription. */
314 if (bfd_seek (abfd, LHD_IDXDESC + idx * IDD_LENGTH, SEEK_SET) != 0
315 || bfd_bread (&idd, sizeof (idd), abfd) != sizeof (idd))
316 return NULL;
317
318 /* Sanity checks. */
319 flags = bfd_getl16 (idd.flags);
320 if (!(flags & IDD__FLAGS_ASCII)
321 || !(flags & IDD__FLAGS_VARLENIDX))
322 return NULL;
323
324 csbuf = bfd_alloc (abfd, *nbrel * sizeof (struct carsym));
325 if (csbuf == NULL)
326 return NULL;
327
328 csm.max = *nbrel;
329 csm.nbr = 0;
330 csm.realloced = FALSE;
331 csm.idx = csbuf;
332
333 /* Note: if the index is empty, there is no block to traverse. */
334 vbn = bfd_getl32 (idd.vbn);
335 if (vbn != 0 && !vms_traverse_index (abfd, vbn, &csm))
336 {
337 if (csm.realloced && csm.idx != NULL)
338 free (csm.idx);
339
340 /* Note: in case of error, we can free what was allocated on the
341 BFD's objalloc. */
342 bfd_release (abfd, csbuf);
343 return NULL;
344 }
345
346 if (csm.realloced)
347 {
348 /* There are more entries than the first estimate. Allocate on
349 the BFD's objalloc. */
350 csbuf = bfd_alloc (abfd, csm.nbr * sizeof (struct carsym));
351 if (csbuf == NULL)
352 return NULL;
353 memcpy (csbuf, csm.idx, csm.nbr * sizeof (struct carsym));
354 free (csm.idx);
355 *nbrel = csm.nbr;
356 }
357 return csbuf;
358 }
359
360 /* Standard function. */
361
362 static const bfd_target *
363 _bfd_vms_lib_archive_p (bfd *abfd, enum vms_lib_kind kind)
364 {
365 struct vms_lhd lhd;
366 unsigned int sanity;
367 struct lib_tdata *tdata_hold;
368 struct lib_tdata *tdata;
369 unsigned int dcxvbn;
370 unsigned int nbr_ent;
371
372 /* Read header. */
373 if (bfd_bread (&lhd, sizeof (lhd), abfd) != sizeof (lhd))
374 {
375 if (bfd_get_error () != bfd_error_system_call)
376 bfd_set_error (bfd_error_wrong_format);
377 return NULL;
378 }
379
380 /* Check sanity (= magic) number. */
381 sanity = bfd_getl32 (lhd.sanity);
382 if (!(sanity == LHD_SANEID3
383 || sanity == LHD_SANEID6
384 || sanity == LHD_SANEID_DCX))
385 {
386 bfd_set_error (bfd_error_wrong_format);
387 return NULL;
388 }
389
390 /* Check archive kind. */
391 switch (kind)
392 {
393 case vms_lib_alpha:
394 if ((lhd.type != LBR__C_TYP_EOBJ && lhd.type != LBR__C_TYP_ESHSTB)
395 || bfd_getl32 (lhd.majorid) != 3
396 || lhd.nindex != 2)
397 {
398 bfd_set_error (bfd_error_wrong_format);
399 return NULL;
400 }
401 break;
402 case vms_lib_ia64:
403 if ((lhd.type != LBR__C_TYP_IOBJ && lhd.type != LBR__C_TYP_ISHSTB)
404 || bfd_getl32 (lhd.majorid) != 6
405 || lhd.nindex != 2)
406 {
407 bfd_set_error (bfd_error_wrong_format);
408 return NULL;
409 }
410 break;
411 case vms_lib_txt:
412 if ((lhd.type != LBR__C_TYP_TXT
413 && lhd.type != LBR__C_TYP_MLB
414 && lhd.type != LBR__C_TYP_HLP)
415 || bfd_getl32 (lhd.majorid) != 3
416 || lhd.nindex != 1)
417 {
418 bfd_set_error (bfd_error_wrong_format);
419 return NULL;
420 }
421 break;
422 default:
423 abort ();
424 }
425
426 /* Allocate and initialize private data. */
427 tdata_hold = bfd_libdata (abfd);
428 tdata = (struct lib_tdata *) bfd_zalloc (abfd, sizeof (struct lib_tdata));
429 if (tdata == NULL)
430 return NULL;
431 abfd->tdata.any = (void *)tdata;
432 tdata->ver = bfd_getl32 (lhd.majorid);
433 tdata->mhd_size = MHD__C_USRDAT + lhd.mhdusz;
434 tdata->type = lhd.type;
435 tdata->kind = kind;
436
437 /* Read indexes. */
438 tdata->nbr_modules = bfd_getl32 (lhd.modcnt);
439 tdata->artdata.symdef_count = bfd_getl32 (lhd.idxcnt) - tdata->nbr_modules;
440 nbr_ent = tdata->nbr_modules;
441 tdata->modules = vms_lib_read_index (abfd, 0, &nbr_ent);
442 if (tdata->modules == NULL || nbr_ent != tdata->nbr_modules)
443 goto err;
444 if (lhd.nindex == 2)
445 {
446 nbr_ent = tdata->artdata.symdef_count;
447 tdata->artdata.symdefs = vms_lib_read_index (abfd, 1, &nbr_ent);
448 if (tdata->artdata.symdefs == NULL)
449 goto err;
450 /* Only IA64 archives may have more entries in the index that what
451 was declared. */
452 if (nbr_ent != tdata->artdata.symdef_count
453 && kind != vms_lib_ia64)
454 goto err;
455 tdata->artdata.symdef_count = nbr_ent;
456 }
457 tdata->cache = bfd_zalloc (abfd, sizeof (bfd *) * tdata->nbr_modules);
458 if (tdata->cache == NULL)
459 goto err;
460
461 /* Read DCX submaps. */
462 dcxvbn = bfd_getl32 (lhd.dcxmapvbn);
463 if (dcxvbn != 0)
464 {
465 unsigned char buf_reclen[4];
466 unsigned int reclen;
467 unsigned char *buf;
468 struct vms_dcxmap *map;
469 unsigned int sbm_off;
470 unsigned int i;
471
472 if (bfd_seek (abfd, (dcxvbn - 1) * VMS_BLOCK_SIZE, SEEK_SET) != 0
473 || bfd_bread (buf_reclen, sizeof (buf_reclen), abfd)
474 != sizeof (buf_reclen))
475 goto err;
476 reclen = bfd_getl32 (buf_reclen);
477 buf = bfd_malloc (reclen);
478 if (buf == NULL)
479 goto err;
480 if (bfd_bread (buf, reclen, abfd) != reclen)
481 {
482 free (buf);
483 goto err;
484 }
485 map = (struct vms_dcxmap *)buf;
486 tdata->nbr_dcxsbm = bfd_getl16 (map->nsubs);
487 sbm_off = bfd_getl16 (map->sub0);
488 tdata->dcxsbm = (struct dcxsbm_desc *)bfd_alloc
489 (abfd, tdata->nbr_dcxsbm * sizeof (struct dcxsbm_desc));
490 for (i = 0; i < tdata->nbr_dcxsbm; i++)
491 {
492 struct vms_dcxsbm *sbm = (struct vms_dcxsbm *) (buf + sbm_off);
493 struct dcxsbm_desc *sbmdesc = &tdata->dcxsbm[i];
494 unsigned int sbm_len;
495 unsigned int sbm_sz;
496 unsigned char *data = (unsigned char *)sbm;
497 unsigned char *buf1;
498 unsigned int l, j;
499
500 sbm_sz = bfd_getl16 (sbm->size);
501 sbm_off += sbm_sz;
502 BFD_ASSERT (sbm_off <= reclen);
503
504 sbmdesc->min_char = sbm->min_char;
505 BFD_ASSERT (sbmdesc->min_char == 0);
506 sbmdesc->max_char = sbm->max_char;
507 sbm_len = sbmdesc->max_char - sbmdesc->min_char + 1;
508 l = (2 * sbm_len + 7) / 8;
509 BFD_ASSERT (sbm_sz >= sizeof (struct vms_dcxsbm) + l + 3 * sbm_len);
510 sbmdesc->flags = (unsigned char *)bfd_alloc (abfd, l);
511 memcpy (sbmdesc->flags, data + bfd_getl16 (sbm->flags), l);
512 sbmdesc->nodes = (unsigned char *)bfd_alloc (abfd, 2 * sbm_len);
513 memcpy (sbmdesc->nodes, data + bfd_getl16 (sbm->nodes), 2 * sbm_len);
514 sbmdesc->next = (unsigned short *)bfd_alloc
515 (abfd, sbm_len * sizeof (unsigned short));
516 buf1 = data + bfd_getl16 (sbm->next);
517 for (j = 0; j < sbm_len; j++)
518 sbmdesc->next[j] = bfd_getl16 (buf1 + j * 2);
519 }
520 free (buf);
521 }
522 else
523 {
524 tdata->nbr_dcxsbm = 0;
525 }
526
527 /* The map is always present. Also mark shared image library. */
528 abfd->has_armap = TRUE;
529 if (tdata->type == LBR__C_TYP_ESHSTB || tdata->type == LBR__C_TYP_ISHSTB)
530 abfd->is_thin_archive = TRUE;
531
532 return abfd->xvec;
533
534 err:
535 bfd_release (abfd, tdata);
536 abfd->tdata.any = (void *)tdata_hold;;
537 return NULL;
538 }
539
540 /* Standard function for alpha libraries. */
541
542 const bfd_target *
543 _bfd_vms_lib_alpha_archive_p (bfd *abfd)
544 {
545 return _bfd_vms_lib_archive_p (abfd, vms_lib_alpha);
546 }
547
548 /* Standard function for text libraries. */
549
550 static const bfd_target *
551 _bfd_vms_lib_txt_archive_p (bfd *abfd)
552 {
553 return _bfd_vms_lib_archive_p (abfd, vms_lib_txt);
554 }
555
556 /* Standard bfd function. */
557
558 bfd_boolean
559 _bfd_vms_lib_mkarchive (bfd *abfd)
560 {
561 struct lib_tdata *tdata;
562
563 tdata = (struct lib_tdata *) bfd_zalloc (abfd, sizeof (struct lib_tdata));
564 if (tdata == NULL)
565 return FALSE;
566
567 abfd->tdata.any = (void *)tdata;
568 tdata->ver = 3;
569 tdata->mhd_size = sizeof (struct vms_mhd);
570 tdata->type = LBR__C_TYP_EOBJ;
571
572 tdata->nbr_modules = 0;
573 tdata->artdata.symdef_count = 0;
574 tdata->modules = NULL;
575 tdata->artdata.symdefs = NULL;
576 tdata->cache = NULL;
577
578 return TRUE;
579 }
580
581 /* Find NAME in the symbol index. Return the index. */
582
583 symindex
584 _bfd_vms_lib_find_symbol (bfd *abfd, const char *name)
585 {
586 struct lib_tdata *tdata = bfd_libdata (abfd);
587 carsym *syms = tdata->artdata.symdefs;
588 int lo, hi;
589
590 /* Open-coded binary search for speed. */
591 lo = 0;
592 hi = tdata->artdata.symdef_count - 1;
593
594 while (lo <= hi)
595 {
596 int mid = lo + (hi - lo) / 2;
597 int diff;
598
599 diff = (char)(name[0] - syms[mid].name[0]);
600 if (diff == 0)
601 diff = strcmp (name, syms[mid].name);
602 if (diff == 0)
603 return mid;
604 else if (diff < 0)
605 hi = mid - 1;
606 else
607 lo = mid + 1;
608 }
609 return BFD_NO_MORE_SYMBOLS;
610 }
611
612 /* IO vector for archive member. Need that because members are not linearly
613 stored in archives. */
614
615 struct vms_lib_iovec
616 {
617 /* Current offset. */
618 ufile_ptr where;
619
620 /* Length of the module, when known. */
621 ufile_ptr file_len;
622
623 /* Current position in the record from bfd_bread point of view (ie, after
624 decompression). 0 means that no data byte have been read, -2 and -1
625 are reserved for the length word. */
626 int rec_pos;
627 #define REC_POS_NL -4
628 #define REC_POS_PAD -3
629 #define REC_POS_LEN0 -2
630 #define REC_POS_LEN1 -1
631
632 /* Record length. */
633 unsigned short rec_len;
634 /* Number of bytes to read in the current record. */
635 unsigned short rec_rem;
636 /* Offset of the next block. */
637 file_ptr next_block;
638 /* Current *data* offset in the data block. */
639 unsigned short blk_off;
640
641 /* Offset of the first block. Extracted from the index. */
642 file_ptr first_block;
643
644 /* Initial next_block. Extracted when the MHD is read. */
645 file_ptr init_next_block;
646 /* Initial blk_off, once the MHD is read. */
647 unsigned short init_blk_off;
648
649 /* Used to store any 3 byte record, which could be the EOF pattern. */
650 unsigned char pattern[4];
651
652 /* DCX. */
653 struct dcxsbm_desc *dcxsbms;
654 /* Current submap. */
655 struct dcxsbm_desc *dcx_sbm;
656 /* Current offset in the submap. */
657 unsigned int dcx_offset;
658 int dcx_pos;
659
660 /* Compressed buffer. */
661 unsigned char *dcx_buf;
662 /* Size of the buffer. Used to resize. */
663 unsigned int dcx_max;
664 /* Number of valid bytes in the buffer. */
665 unsigned int dcx_rlen;
666 };
667
668 /* Return the current position. */
669
670 static file_ptr
671 vms_lib_btell (struct bfd *abfd)
672 {
673 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
674 return vec->where;
675 }
676
677 /* Read the header of the next data block if all bytes of the current block
678 have been read. */
679
680 static bfd_boolean
681 vms_lib_read_block (struct bfd *abfd)
682 {
683 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
684
685 if (vec->blk_off == DATA__LENGTH)
686 {
687 unsigned char hdr[DATA__DATA];
688
689 /* Read next block. */
690 if (bfd_seek (abfd->my_archive, vec->next_block, SEEK_SET) != 0)
691 return FALSE;
692 if (bfd_bread (hdr, sizeof (hdr), abfd->my_archive) != sizeof (hdr))
693 return FALSE;
694 vec->next_block = (bfd_getl32 (hdr + 2) - 1) * VMS_BLOCK_SIZE;
695 vec->blk_off = sizeof (hdr);
696 }
697 return TRUE;
698 }
699
700 /* Read NBYTES from ABFD into BUF if not NULL. If BUF is NULL, bytes are
701 not stored. Read linearly from the library, but handle blocks. This
702 function does not handle records nor EOF. */
703
704 static file_ptr
705 vms_lib_bread_raw (struct bfd *abfd, void *buf, file_ptr nbytes)
706 {
707 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
708 file_ptr res;
709
710 res = 0;
711 while (nbytes > 0)
712 {
713 unsigned int l;
714
715 /* Be sure the current data block is read. */
716 if (!vms_lib_read_block (abfd))
717 return -1;
718
719 /* Do not read past the data block, do not read more than requested. */
720 l = DATA__LENGTH - vec->blk_off;
721 if (l > nbytes)
722 l = nbytes;
723 if (l == 0)
724 return 0;
725 if (buf != NULL)
726 {
727 /* Really read into BUF. */
728 if (bfd_bread (buf, l, abfd->my_archive) != l)
729 return -1;
730 }
731 else
732 {
733 /* Make as if we are reading. */
734 if (bfd_seek (abfd->my_archive, l, SEEK_CUR) != 0)
735 return -1;
736 }
737
738 if (buf != NULL)
739 buf += l;
740 vec->blk_off += l;
741 nbytes -= l;
742 res += l;
743 }
744 return res;
745 }
746
747 /* Decompress NBYTES from VEC. Store the bytes into BUF if not NULL. */
748
749 static file_ptr
750 vms_lib_dcx (struct vms_lib_iovec *vec, unsigned char *buf, file_ptr nbytes)
751 {
752 struct dcxsbm_desc *sbm;
753 unsigned int i;
754 unsigned int offset;
755 unsigned int j;
756 file_ptr res = 0;
757
758 /* The loop below expect to deliver at least one byte. */
759 if (nbytes == 0)
760 return 0;
761
762 /* Get the current state. */
763 sbm = vec->dcx_sbm;
764 offset = vec->dcx_offset;
765 j = vec->dcx_pos & 7;
766
767 for (i = vec->dcx_pos >> 3; i < vec->dcx_rlen; i++)
768 {
769 unsigned char b = vec->dcx_buf[i];
770
771 for (; j < 8; j++)
772 {
773 if (b & (1 << j))
774 offset++;
775 if (!(sbm->flags[offset >> 3] & (1 << (offset & 7))))
776 {
777 unsigned int n_offset = sbm->nodes[offset];
778 if (n_offset == 0)
779 {
780 /* End of buffer. Stay where we are. */
781 vec->dcx_pos = (i << 3) + j;
782 if (b & (1 << j))
783 offset--;
784 vec->dcx_offset = offset;
785 vec->dcx_sbm = sbm;
786 return res;
787 }
788 offset = 2 * n_offset;
789 }
790 else
791 {
792 unsigned char v = sbm->nodes[offset];
793
794 sbm = vec->dcxsbms + sbm->next[v];
795 offset = 0;
796 res++;
797
798 if (buf)
799 {
800 *buf++ = v;
801 nbytes--;
802
803 if (nbytes == 0)
804 {
805 vec->dcx_pos = (i << 3) + j + 1;
806 vec->dcx_offset = offset;
807 vec->dcx_sbm = sbm;
808
809 return res;
810 }
811 }
812 }
813 }
814 j = 0;
815 }
816 return -1;
817 }
818
819 /* Standard IOVEC function. */
820
821 static file_ptr
822 vms_lib_bread (struct bfd *abfd, void *buf, file_ptr nbytes)
823 {
824 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
825 file_ptr res;
826 file_ptr chunk;
827
828 /* Do not read past the end. */
829 if (vec->where >= vec->file_len)
830 return 0;
831
832 res = 0;
833 while (nbytes > 0)
834 {
835 if (vec->rec_rem == 0)
836 {
837 unsigned char blen[2];
838
839 /* Read record length. */
840 if (vms_lib_bread_raw (abfd, &blen, sizeof (blen)) != sizeof (blen))
841 return -1;
842 vec->rec_len = bfd_getl16 (blen);
843 if (bfd_libdata (abfd->my_archive)->kind == vms_lib_txt)
844 {
845 /* Discard record size and align byte. */
846 vec->rec_pos = 0;
847 vec->rec_rem = vec->rec_len;
848 }
849 else
850 {
851 /* Prepend record size. */
852 vec->rec_pos = REC_POS_LEN0;
853 vec->rec_rem = (vec->rec_len + 1) & ~1; /* With align byte. */
854 }
855 if (vec->rec_len == 3)
856 {
857 /* Possibly end of file. Check the pattern. */
858 if (vms_lib_bread_raw (abfd, vec->pattern, 4) != 4)
859 return -1;
860 if (!memcmp (vec->pattern, eotdesc + 2, 3))
861 {
862 /* This is really an EOF. */
863 vec->where += res;
864 vec->file_len = vec->where;
865 return res;
866 }
867 }
868
869 if (vec->dcxsbms != NULL)
870 {
871 /* This is a compressed member. */
872 unsigned int len;
873 file_ptr elen;
874
875 /* Be sure there is enough room for the expansion. */
876 len = (vec->rec_len + 1) & ~1;
877 if (len > vec->dcx_max)
878 {
879 while (len > vec->dcx_max)
880 vec->dcx_max *= 2;
881 vec->dcx_buf = bfd_alloc (abfd, vec->dcx_max);
882 if (vec->dcx_buf == NULL)
883 return -1;
884 }
885
886 /* Read the compressed record. */
887 vec->dcx_rlen = len;
888 if (vec->rec_len == 3)
889 {
890 /* Already read. */
891 memcpy (vec->dcx_buf, vec->pattern, 3);
892 }
893 else
894 {
895 elen = vms_lib_bread_raw (abfd, vec->dcx_buf, len);
896 if (elen != len)
897 return -1;
898 }
899
900 /* Dummy expansion to get the expanded length. */
901 vec->dcx_offset = 0;
902 vec->dcx_sbm = vec->dcxsbms;
903 vec->dcx_pos = 0;
904 elen = vms_lib_dcx (vec, NULL, 0x10000);
905 if (elen < 0)
906 return -1;
907 vec->rec_len = elen;
908 vec->rec_rem = elen;
909
910 /* Reset the state. */
911 vec->dcx_offset = 0;
912 vec->dcx_sbm = vec->dcxsbms;
913 vec->dcx_pos = 0;
914 }
915 }
916 if (vec->rec_pos < 0)
917 {
918 unsigned char c;
919 switch (vec->rec_pos)
920 {
921 case REC_POS_LEN0:
922 c = vec->rec_len & 0xff;
923 vec->rec_pos = REC_POS_LEN1;
924 break;
925 case REC_POS_LEN1:
926 c = (vec->rec_len >> 8) & 0xff;
927 vec->rec_pos = 0;
928 break;
929 case REC_POS_PAD:
930 c = 0;
931 vec->rec_rem = 0;
932 break;
933 case REC_POS_NL:
934 c = '\n';
935 vec->rec_rem = 0;
936 break;
937 default:
938 abort ();
939 }
940 if (buf != NULL)
941 {
942 *(unsigned char *)buf = c;
943 buf++;
944 }
945 nbytes--;
946 res++;
947 continue;
948 }
949
950 if (nbytes > vec->rec_rem)
951 chunk = vec->rec_rem;
952 else
953 chunk = nbytes;
954
955 if (vec->dcxsbms != NULL)
956 {
957 /* Optimize the stat() case: no need to decompress again as we
958 know the length. */
959 if (!(buf == NULL && chunk == vec->rec_rem))
960 chunk = vms_lib_dcx (vec, buf, chunk);
961 }
962 else
963 {
964 if (vec->rec_len == 3)
965 {
966 if (buf != NULL)
967 memcpy (buf, vec->pattern + vec->rec_pos, chunk);
968 }
969 else
970 chunk = vms_lib_bread_raw (abfd, buf, chunk);
971 }
972 if (chunk < 0)
973 return -1;
974 res += chunk;
975 if (buf != NULL)
976 buf += chunk;
977 nbytes -= chunk;
978 vec->rec_pos += chunk;
979 vec->rec_rem -= chunk;
980
981 if (vec->rec_rem == 0)
982 {
983 /* End of record reached. */
984 if (bfd_libdata (abfd->my_archive)->kind == vms_lib_txt)
985 {
986 if ((vec->rec_len & 1) == 1
987 && vec->rec_len != 3
988 && vec->dcxsbms == NULL)
989 {
990 /* Eat the pad byte. */
991 unsigned char pad;
992 if (vms_lib_bread_raw (abfd, &pad, 1) != 1)
993 return -1;
994 }
995 vec->rec_pos = REC_POS_NL;
996 vec->rec_rem = 1;
997 }
998 else
999 {
1000 if ((vec->rec_len & 1) == 1 && vec->dcxsbms != NULL)
1001 {
1002 vec->rec_pos = REC_POS_PAD;
1003 vec->rec_rem = 1;
1004 }
1005 }
1006 }
1007 }
1008 vec->where += res;
1009 return res;
1010 }
1011
1012 /* Standard function, but we currently only handle the rewind case. */
1013
1014 static int
1015 vms_lib_bseek (struct bfd *abfd, file_ptr offset, int whence)
1016 {
1017 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
1018
1019 if (whence == SEEK_SET && offset == 0)
1020 {
1021 vec->where = 0;
1022 vec->rec_rem = 0;
1023 vec->dcx_pos = -1;
1024 vec->blk_off = vec->init_blk_off;
1025 vec->next_block = vec->init_next_block;
1026
1027 if (bfd_seek (abfd->my_archive, vec->first_block, SEEK_SET) != 0)
1028 return -1;
1029 }
1030 else
1031 abort ();
1032 return 0;
1033 }
1034
1035 static file_ptr
1036 vms_lib_bwrite (struct bfd *abfd ATTRIBUTE_UNUSED,
1037 const void *where ATTRIBUTE_UNUSED,
1038 file_ptr nbytes ATTRIBUTE_UNUSED)
1039 {
1040 return -1;
1041 }
1042
1043 static int
1044 vms_lib_bclose (struct bfd *abfd)
1045 {
1046 abfd->iostream = NULL;
1047 return 0;
1048 }
1049
1050 static int
1051 vms_lib_bflush (struct bfd *abfd ATTRIBUTE_UNUSED)
1052 {
1053 return 0;
1054 }
1055
1056 static int
1057 vms_lib_bstat (struct bfd *abfd ATTRIBUTE_UNUSED,
1058 struct stat *sb ATTRIBUTE_UNUSED)
1059 {
1060 /* Not supported. */
1061 return 0;
1062 }
1063
1064 static void *
1065 vms_lib_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED,
1066 void *addr ATTRIBUTE_UNUSED,
1067 bfd_size_type len ATTRIBUTE_UNUSED,
1068 int prot ATTRIBUTE_UNUSED,
1069 int flags ATTRIBUTE_UNUSED,
1070 file_ptr offset ATTRIBUTE_UNUSED)
1071 {
1072 return (void *) -1;
1073 }
1074
1075 static const struct bfd_iovec vms_lib_iovec = {
1076 &vms_lib_bread, &vms_lib_bwrite, &vms_lib_btell, &vms_lib_bseek,
1077 &vms_lib_bclose, &vms_lib_bflush, &vms_lib_bstat, &vms_lib_bmmap
1078 };
1079
1080 /* Open a library module. FILEPOS is the position of the module header. */
1081
1082 static bfd_boolean
1083 vms_lib_bopen (bfd *el, file_ptr filepos)
1084 {
1085 struct vms_lib_iovec *vec;
1086 char buf[256];
1087 struct vms_mhd *mhd;
1088 struct lib_tdata *tdata = bfd_libdata (el->my_archive);
1089 unsigned int len;
1090
1091 /* Allocate and initialized the iovec. */
1092 vec = bfd_zalloc (el, sizeof (*vec));
1093 if (vec == NULL)
1094 return FALSE;
1095
1096 el->iostream = vec;
1097 el->iovec = &vms_lib_iovec;
1098
1099 /* File length is not known. */
1100 vec->file_len = -1;
1101
1102 /* Read the first data block. */
1103 vec->next_block = filepos & ~(VMS_BLOCK_SIZE - 1);
1104 vec->blk_off = DATA__LENGTH;
1105 if (!vms_lib_read_block (el))
1106 return FALSE;
1107
1108 /* Prepare to read the first record. */
1109 vec->blk_off = filepos & (VMS_BLOCK_SIZE - 1);
1110 vec->rec_rem = 0;
1111 if (bfd_seek (el->my_archive, filepos, SEEK_SET) != 0)
1112 return FALSE;
1113
1114 /* Read Record length + MHD + align byte. */
1115 len = tdata->mhd_size;
1116 if (vms_lib_bread_raw (el, buf, 2) != 2)
1117 return FALSE;
1118 if (bfd_getl16 (buf) != len)
1119 return FALSE;
1120 len = (len + 1) & ~1;
1121 BFD_ASSERT (len <= sizeof (buf));
1122 if (vms_lib_bread_raw (el, buf, len) != len)
1123 return FALSE;
1124
1125 /* Get info from mhd. */
1126 mhd = (struct vms_mhd *)buf;
1127 /* Check id. */
1128 if (mhd->id != MHD__C_MHDID)
1129 return FALSE;
1130 if (len >= sizeof (struct vms_mhd))
1131 el->selective_search = (mhd->objstat & MHD__M_SELSRC) ? 1 : 0;
1132 el->mtime = vms_rawtime_to_time_t (mhd->datim);
1133 el->mtime_set = TRUE;
1134
1135 /* Reinit the iovec so that seek() will point to the first record after
1136 the mhd. */
1137 vec->where = 0;
1138 vec->init_blk_off = vec->blk_off;
1139 vec->init_next_block = vec->next_block;
1140 vec->first_block = bfd_tell (el->my_archive);
1141 vec->dcxsbms = bfd_libdata (el->my_archive)->dcxsbm;
1142
1143 if (vec->dcxsbms != NULL)
1144 {
1145 /* Handle DCX. */
1146 vec->dcx_max = 10 * 1024;
1147 vec->dcx_buf = bfd_alloc (el, vec->dcx_max);
1148 vec->dcx_pos = -1;
1149 if (vec->dcx_buf == NULL)
1150 return -1;
1151 }
1152 return TRUE;
1153 }
1154
1155 /* Get member MODIDX. Return NULL in case of error. */
1156
1157 static bfd *
1158 _bfd_vms_lib_get_module (bfd *abfd, unsigned int modidx)
1159 {
1160 struct lib_tdata *tdata = bfd_libdata (abfd);
1161 bfd *res;
1162 file_ptr file_off;
1163
1164 /* Sanity check. */
1165 if (modidx >= tdata->nbr_modules)
1166 return NULL;
1167
1168 /* Already loaded. */
1169 if (tdata->cache[modidx])
1170 return tdata->cache[modidx];
1171
1172 /* Build it. */
1173 file_off = tdata->modules[modidx].file_offset;
1174 if (tdata->type != LBR__C_TYP_IOBJ)
1175 {
1176 res = _bfd_create_empty_archive_element_shell (abfd);
1177 if (res == NULL)
1178 return NULL;
1179
1180 /* Special reader to deal with data blocks. */
1181 if (!vms_lib_bopen (res, file_off))
1182 return NULL;
1183 }
1184 else
1185 {
1186 char buf[256];
1187 struct vms_mhd *mhd;
1188 struct areltdata *arelt;
1189
1190 /* Sanity check. The MHD must be big enough to contain module size. */
1191 if (tdata->mhd_size < offsetof (struct vms_mhd, modsize) + 4)
1192 return NULL;
1193
1194 /* Read the MHD now. */
1195 if (bfd_seek (abfd, file_off, SEEK_SET) != 0)
1196 return NULL;
1197 if (bfd_bread (buf, tdata->mhd_size, abfd) != tdata->mhd_size)
1198 return NULL;
1199
1200 res = _bfd_create_empty_archive_element_shell (abfd);
1201 if (res == NULL)
1202 return NULL;
1203 arelt = bfd_zalloc (res, sizeof (*arelt));
1204 if (arelt == NULL)
1205 return NULL;
1206 res->arelt_data = arelt;
1207
1208 /* Get info from mhd. */
1209 mhd = (struct vms_mhd *)buf;
1210 if (mhd->id != MHD__C_MHDID)
1211 return NULL;
1212 if (tdata->mhd_size >= offsetof (struct vms_mhd, objstat) + 1)
1213 res->selective_search = (mhd->objstat & MHD__M_SELSRC) ? 1 : 0;
1214 res->mtime = vms_rawtime_to_time_t (mhd->datim);
1215 res->mtime_set = TRUE;
1216
1217 arelt->parsed_size = bfd_getl32 (mhd->modsize);
1218
1219 /* No need for a special reader as members are stored linearly.
1220 Just skip the MHD. */
1221 res->origin = file_off + tdata->mhd_size;
1222 }
1223
1224 res->filename = tdata->modules[modidx].name;
1225
1226 tdata->cache[modidx] = res;
1227
1228 return res;
1229 }
1230
1231 /* Standard function: get member at IDX. */
1232
1233 bfd *
1234 _bfd_vms_lib_get_elt_at_index (bfd *abfd, symindex symidx)
1235 {
1236 struct lib_tdata *tdata = bfd_libdata (abfd);
1237 file_ptr file_off;
1238 unsigned int modidx;
1239
1240 /* Check symidx. */
1241 if (symidx > tdata->artdata.symdef_count)
1242 return NULL;
1243 file_off = tdata->artdata.symdefs[symidx].file_offset;
1244
1245 /* Linear-scan. */
1246 for (modidx = 0; modidx < tdata->nbr_modules; modidx++)
1247 {
1248 if (tdata->modules[modidx].file_offset == file_off)
1249 break;
1250 }
1251 if (modidx >= tdata->nbr_modules)
1252 return NULL;
1253
1254 return _bfd_vms_lib_get_module (abfd, modidx);
1255 }
1256
1257 /* Elements of an imagelib are stubs. You can get the real image with this
1258 function. */
1259
1260 bfd *
1261 _bfd_vms_lib_get_imagelib_file (bfd *el)
1262 {
1263 bfd *archive = el->my_archive;
1264 const char *modname = el->filename;
1265 int modlen = strlen (modname);
1266 char *filename;
1267 int j;
1268 bfd *res;
1269
1270 /* Convert module name to lower case and append '.exe'. */
1271 filename = bfd_alloc (el, modlen + 5);
1272 if (filename == NULL)
1273 return NULL;
1274 for (j = 0; j < modlen; j++)
1275 if (ISALPHA (modname[j]))
1276 filename[j] = TOLOWER (modname[j]);
1277 else
1278 filename[j] = modname[j];
1279 memcpy (filename + modlen, ".exe", 5);
1280
1281 filename = _bfd_append_relative_path (archive, filename);
1282 if (filename == NULL)
1283 return NULL;
1284 res = bfd_openr (filename, NULL);
1285
1286 if (res == NULL)
1287 {
1288 (*_bfd_error_handler)(_("could not open shared image '%s' from '%s'"),
1289 filename, archive->filename);
1290 bfd_release (archive, filename);
1291 return NULL;
1292 }
1293
1294 /* FIXME: put it in a cache ? */
1295 return res;
1296 }
1297
1298 /* Standard function. */
1299
1300 bfd *
1301 _bfd_vms_lib_openr_next_archived_file (bfd *archive,
1302 bfd *last_file)
1303 {
1304 unsigned int idx;
1305 bfd *res;
1306
1307 if (!last_file)
1308 idx = 0;
1309 else
1310 idx = last_file->proxy_origin + 1;
1311
1312 if (idx >= bfd_libdata (archive)->nbr_modules)
1313 {
1314 bfd_set_error (bfd_error_no_more_archived_files);
1315 return NULL;
1316 }
1317
1318 res = _bfd_vms_lib_get_module (archive, idx);
1319 if (res == NULL)
1320 return res;
1321 res->proxy_origin = idx;
1322 return res;
1323 }
1324
1325 /* Standard function. Just compute the length. */
1326
1327 int
1328 _bfd_vms_lib_generic_stat_arch_elt (bfd *abfd, struct stat *st)
1329 {
1330 struct lib_tdata *tdata;
1331
1332 /* Sanity check. */
1333 if (abfd->my_archive == NULL)
1334 {
1335 bfd_set_error (bfd_error_invalid_operation);
1336 return -1;
1337 }
1338
1339 tdata = bfd_libdata (abfd->my_archive);
1340 if (tdata->type != LBR__C_TYP_IOBJ)
1341 {
1342 struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
1343
1344 if (vec->file_len == (ufile_ptr)-1)
1345 {
1346 if (vms_lib_bseek (abfd, 0, SEEK_SET) != 0)
1347 return -1;
1348
1349 /* Compute length. */
1350 while (vms_lib_bread (abfd, NULL, 1 << 20) > 0)
1351 ;
1352 }
1353 st->st_size = vec->file_len;
1354 }
1355 else
1356 {
1357 st->st_size = ((struct areltdata *)abfd->arelt_data)->parsed_size;
1358 }
1359
1360 if (abfd->mtime_set)
1361 st->st_mtime = abfd->mtime;
1362 else
1363 st->st_mtime = 0;
1364 st->st_uid = 0;
1365 st->st_gid = 0;
1366 st->st_mode = 0644;
1367
1368 return 0;
1369 }
1370
1371 /* Internal representation of an index entry. */
1372
1373 struct vms_index
1374 {
1375 /* Corresponding archive member. */
1376 bfd *abfd;
1377
1378 /* Number of reference to this entry. */
1379 unsigned int ref;
1380
1381 /* Length of the key. */
1382 unsigned short namlen;
1383
1384 /* Key. */
1385 const char *name;
1386 };
1387
1388 /* Used to sort index entries. */
1389
1390 static int
1391 vms_index_cmp (const void *lv, const void *rv)
1392 {
1393 const struct vms_index *l = lv;
1394 const struct vms_index *r = rv;
1395
1396 return strcmp (l->name, r->name);
1397 }
1398
1399 /* Maximum number of index blocks level. */
1400
1401 #define MAX_LEVEL 10
1402
1403 /* Get the size of an index entry. */
1404
1405 static unsigned int
1406 get_idxlen (struct vms_index *idx)
1407 {
1408 return 7 + idx->namlen;
1409 }
1410
1411 /* Write the index. VBN is the first vbn to be used, and will contain
1412 on return the last vbn.
1413 Return TRUE on success. */
1414
1415 static bfd_boolean
1416 vms_write_index (bfd *abfd,
1417 struct vms_index *idx, unsigned int nbr, unsigned int *vbn,
1418 unsigned int *topvbn)
1419 {
1420 unsigned int i;
1421 int j;
1422 int level;
1423 struct vms_indexdef *rblk[MAX_LEVEL];
1424 struct idxblk
1425 {
1426 unsigned int vbn;
1427 unsigned short len;
1428 unsigned short lastlen;
1429 } blk[MAX_LEVEL];
1430
1431 if (nbr == 0)
1432 {
1433 if (topvbn != NULL)
1434 *topvbn = 0;
1435 return TRUE;
1436 }
1437
1438 if (abfd == NULL)
1439 {
1440 /* Sort the index the first time this function is called. */
1441 qsort (idx, nbr, sizeof (struct vms_index), vms_index_cmp);
1442 }
1443
1444 /* Allocate first index block. */
1445 level = 1;
1446 if (abfd != NULL)
1447 rblk[0] = bfd_malloc (sizeof (struct vms_indexdef));
1448 blk[0].vbn = (*vbn)++;
1449 blk[0].len = 0;
1450 blk[0].lastlen = 0;
1451
1452 for (i = 0; i < nbr; i++, idx++)
1453 {
1454 unsigned int idxlen = get_idxlen (idx);
1455 struct vms_idx *en;
1456 int flush = 0;
1457
1458 /* Check if a block might overflow. In this case we will flush this
1459 block and all the blocks below it. */
1460 for (j = 0; j < level; j++)
1461 if (blk[j].len + blk[j].lastlen + idxlen > INDEXDEF__BLKSIZ)
1462 flush = j + 1;
1463
1464 for (j = 0; j < level; j++)
1465 {
1466 if (j < flush)
1467 {
1468 /* There is not enough room to write the new entry in this
1469 block or in a parent block. */
1470
1471 if (j + 1 == level)
1472 {
1473 BFD_ASSERT (level < MAX_LEVEL);
1474
1475 /* Need to create a parent. */
1476 if (abfd != NULL)
1477 {
1478 rblk[level] = bfd_malloc (sizeof (struct vms_indexdef));
1479 bfd_putl32 (*vbn, rblk[j]->parent);
1480 }
1481 blk[level].vbn = (*vbn)++;
1482 blk[level].len = 0;
1483 blk[level].lastlen = 0;
1484
1485 level++;
1486 }
1487
1488 /* Update parent block: write the new entry. */
1489 if (abfd != NULL)
1490 {
1491 en = (struct vms_idx *)(rblk[j]->keys + blk[j].len);
1492 memcpy (rblk[j + 1]->keys + blk[j + 1].len, en,
1493 blk[j].lastlen);
1494 en = (struct vms_idx *)(rblk[j + 1]->keys + blk[j + 1].len);
1495 bfd_putl32 (blk[j].vbn, en->rfa.vbn);
1496 bfd_putl16 (RFADEF__C_INDEX, en->rfa.offset);
1497 }
1498
1499 if (j + 1 == flush)
1500 {
1501 /* And allocate it. Do it only on the block that won't be
1502 flushed (so that the parent of the parent can be
1503 updated too). */
1504 blk[j + 1].len += blk[j].lastlen;
1505 blk[j + 1].lastlen = 0;
1506 }
1507
1508 /* Write this block on the disk. */
1509 if (abfd != NULL)
1510 {
1511 bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used);
1512 if (bfd_seek (abfd, (blk[j].vbn - 1) * VMS_BLOCK_SIZE,
1513 SEEK_SET) != 0)
1514 return FALSE;
1515 if (bfd_bwrite (rblk[j], sizeof (struct vms_indexdef), abfd)
1516 != sizeof (struct vms_indexdef))
1517 return FALSE;
1518 }
1519
1520 /* Reset this block. */
1521 blk[j].len = 0;
1522 blk[j].lastlen = 0;
1523 blk[j].vbn = (*vbn)++;
1524 }
1525
1526 /* Append it to the block. */
1527 if (j == 0)
1528 {
1529 blk[j].len += blk[j].lastlen;
1530
1531 if (abfd != NULL)
1532 {
1533 en = (struct vms_idx *)(rblk[j]->keys + blk[j].len);
1534 bfd_putl32 ((idx->abfd->proxy_origin / VMS_BLOCK_SIZE) + 1,
1535 en->rfa.vbn);
1536 bfd_putl16
1537 ((idx->abfd->proxy_origin % VMS_BLOCK_SIZE) + DATA__DATA,
1538 en->rfa.offset);
1539 en->keylen = idx->namlen;
1540 memcpy (en->keyname, idx->name, idx->namlen);
1541 }
1542 }
1543
1544 blk[j].lastlen = idxlen;
1545 }
1546 }
1547
1548 if (topvbn != NULL)
1549 *topvbn = blk[level - 1].vbn;
1550
1551 if (abfd == NULL)
1552 return TRUE;
1553
1554 /* Flush. */
1555 for (j = 0; j < level; j++)
1556 {
1557 if (j > 0)
1558 {
1559 /* Update parent block: write the new entry. */
1560 struct vms_idx *en;
1561 struct vms_idx *par;
1562
1563 en = (struct vms_idx *)(rblk[j - 1]->keys + blk[j - 1].len);
1564 par = (struct vms_idx *)(rblk[j]->keys + blk[j].len);
1565 memcpy (par, en, blk[j - 1].lastlen);
1566 bfd_putl32 (blk[j - 1].vbn, par->rfa.vbn);
1567 bfd_putl16 (RFADEF__C_INDEX, par->rfa.offset);
1568 }
1569
1570 /* Write this block on the disk. */
1571 bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used);
1572 if (bfd_seek (abfd, (blk[j].vbn - 1) * VMS_BLOCK_SIZE,
1573 SEEK_SET) != 0)
1574 return FALSE;
1575 if (bfd_bwrite (rblk[j], sizeof (struct vms_indexdef), abfd)
1576 != sizeof (struct vms_indexdef))
1577 return FALSE;
1578
1579 free (rblk[j]);
1580 }
1581
1582 return TRUE;
1583 }
1584
1585 /* Append data to the data block DATA. Force write if PAD is true. */
1586
1587 static bfd_boolean
1588 vms_write_data_block (bfd *arch, struct vms_datadef *data, file_ptr *off,
1589 const unsigned char *buf, unsigned int len, int pad)
1590 {
1591 while (len > 0 || pad)
1592 {
1593 unsigned int doff = *off & (VMS_BLOCK_SIZE - 1);
1594 unsigned int remlen = (DATA__LENGTH - DATA__DATA) - doff;
1595 unsigned int l;
1596
1597 l = (len > remlen) ? remlen : len;
1598 memcpy (data->data + doff, buf, l);
1599 buf += l;
1600 len -= l;
1601 doff += l;
1602 *off += l;
1603
1604 if (doff == (DATA__LENGTH - DATA__DATA) || (len == 0 && pad))
1605 {
1606 data->recs = 0;
1607 data->fill_1 = 0;
1608 bfd_putl32 ((*off / VMS_BLOCK_SIZE) + 2, data->link);
1609
1610 if (bfd_bwrite (data, sizeof (*data), arch) != sizeof (*data))
1611 return FALSE;
1612
1613 *off += DATA__LENGTH - doff;
1614
1615 if (len == 0)
1616 break;
1617 }
1618 }
1619 return TRUE;
1620 }
1621
1622 /* Build the symbols index. */
1623
1624 static bfd_boolean
1625 _bfd_vms_lib_build_map (unsigned int nbr_modules,
1626 struct vms_index *modules,
1627 unsigned int *res_cnt,
1628 struct vms_index **res)
1629 {
1630 unsigned int i;
1631 asymbol **syms = NULL;
1632 long syms_max = 0;
1633 struct vms_index *map = NULL;
1634 unsigned int map_max = 1024; /* Fine initial default. */
1635 unsigned int map_count = 0;
1636
1637 map = (struct vms_index *) bfd_malloc (map_max * sizeof (struct vms_index));
1638 if (map == NULL)
1639 goto error_return;
1640
1641 /* Gather symbols. */
1642 for (i = 0; i < nbr_modules; i++)
1643 {
1644 long storage;
1645 long symcount;
1646 long src_count;
1647 bfd *current = modules[i].abfd;
1648
1649 if ((bfd_get_file_flags (current) & HAS_SYMS) == 0)
1650 continue;
1651
1652 storage = bfd_get_symtab_upper_bound (current);
1653 if (storage < 0)
1654 goto error_return;
1655
1656 if (storage != 0)
1657 {
1658 if (storage > syms_max)
1659 {
1660 if (syms_max > 0)
1661 free (syms);
1662 syms_max = storage;
1663 syms = (asymbol **) bfd_malloc (syms_max);
1664 if (syms == NULL)
1665 goto error_return;
1666 }
1667 symcount = bfd_canonicalize_symtab (current, syms);
1668 if (symcount < 0)
1669 goto error_return;
1670
1671 /* Now map over all the symbols, picking out the ones we
1672 want. */
1673 for (src_count = 0; src_count < symcount; src_count++)
1674 {
1675 flagword flags = (syms[src_count])->flags;
1676 asection *sec = syms[src_count]->section;
1677
1678 if ((flags & BSF_GLOBAL
1679 || flags & BSF_WEAK
1680 || flags & BSF_INDIRECT
1681 || bfd_is_com_section (sec))
1682 && ! bfd_is_und_section (sec))
1683 {
1684 struct vms_index *new_map;
1685
1686 /* This symbol will go into the archive header. */
1687 if (map_count == map_max)
1688 {
1689 map_max *= 2;
1690 new_map = (struct vms_index *)
1691 bfd_realloc (map, map_max * sizeof (struct vms_index));
1692 if (new_map == NULL)
1693 goto error_return;
1694 map = new_map;
1695 }
1696
1697 map[map_count].abfd = current;
1698 /* FIXME: check length. */
1699 map[map_count].namlen = strlen (syms[src_count]->name);
1700 map[map_count].name = syms[src_count]->name;
1701 map_count++;
1702 modules[i].ref++;
1703 }
1704 }
1705 }
1706 }
1707
1708 *res_cnt = map_count;
1709 *res = map;
1710 return TRUE;
1711
1712 error_return:
1713 if (syms_max > 0)
1714 free (syms);
1715 if (map != NULL)
1716 free (map);
1717 return FALSE;
1718 }
1719
1720 /* Do the hard work: write an archive on the disk. */
1721
1722 bfd_boolean
1723 _bfd_vms_lib_write_archive_contents (bfd *arch)
1724 {
1725 bfd *current;
1726 unsigned int nbr_modules;
1727 struct vms_index *modules;
1728 unsigned int nbr_symbols;
1729 struct vms_index *symbols;
1730 struct lib_tdata *tdata = bfd_libdata (arch);
1731 unsigned int i;
1732 file_ptr off;
1733 unsigned int nbr_mod_iblk;
1734 unsigned int nbr_sym_iblk;
1735 unsigned int vbn;
1736 unsigned int mod_idx_vbn;
1737 unsigned int sym_idx_vbn;
1738
1739 /* Count the number of modules (and do a first sanity check). */
1740 nbr_modules = 0;
1741 for (current = arch->archive_head;
1742 current != NULL;
1743 current = current->archive_next)
1744 {
1745 /* This check is checking the bfds for the objects we're reading
1746 from (which are usually either an object file or archive on
1747 disk), not the archive entries we're writing to. We don't
1748 actually create bfds for the archive members, we just copy
1749 them byte-wise when we write out the archive. */
1750 if (bfd_write_p (current) || !bfd_check_format (current, bfd_object))
1751 {
1752 bfd_set_error (bfd_error_invalid_operation);
1753 goto input_err;
1754 }
1755
1756 nbr_modules++;
1757 }
1758
1759 /* Build the modules list. */
1760 BFD_ASSERT (tdata->modules == NULL);
1761 modules = bfd_alloc (arch, nbr_modules * sizeof (struct vms_index));
1762 if (modules == NULL)
1763 return FALSE;
1764
1765 for (current = arch->archive_head, i = 0;
1766 current != NULL;
1767 current = current->archive_next, i++)
1768 {
1769 int nl;
1770
1771 modules[i].abfd = current;
1772 modules[i].name = vms_get_module_name (current->filename, FALSE);
1773 modules[i].ref = 1;
1774
1775 /* FIXME: silently truncate long names ? */
1776 nl = strlen (modules[i].name);
1777 modules[i].namlen = (nl > MAX_KEYLEN ? MAX_KEYLEN : nl);
1778 }
1779
1780 /* Create the module index. */
1781 vbn = 0;
1782 if (!vms_write_index (NULL, modules, nbr_modules, &vbn, NULL))
1783 return FALSE;
1784 nbr_mod_iblk = vbn;
1785
1786 /* Create symbol index. */
1787 if (!_bfd_vms_lib_build_map (nbr_modules, modules, &nbr_symbols, &symbols))
1788 return FALSE;
1789
1790 vbn = 0;
1791 if (!vms_write_index (NULL, symbols, nbr_symbols, &vbn, NULL))
1792 return FALSE;
1793 nbr_sym_iblk = vbn;
1794
1795 /* Write modules and remember their position. */
1796 off = (1 + nbr_mod_iblk + nbr_sym_iblk) * VMS_BLOCK_SIZE;
1797
1798 if (bfd_seek (arch, off, SEEK_SET) != 0)
1799 return FALSE;
1800
1801 for (i = 0; i < nbr_modules; i++)
1802 {
1803 struct vms_datadef data;
1804 unsigned char blk[VMS_BLOCK_SIZE];
1805 struct vms_mhd *mhd;
1806 unsigned int sz;
1807
1808 current = modules[i].abfd;
1809 current->proxy_origin = off;
1810
1811 bfd_putl16 (sizeof (struct vms_mhd), blk);
1812 mhd = (struct vms_mhd *)(blk + 2);
1813 memset (mhd, 0, sizeof (struct vms_mhd));
1814 mhd->lbrflag = 0;
1815 mhd->id = MHD__C_MHDID;
1816 mhd->objidlng = 4;
1817 memcpy (mhd->objid, "V1.0", 4);
1818 bfd_putl32 (modules[i].ref, mhd->refcnt);
1819 /* FIXME: datim. */
1820
1821 sz = (2 + sizeof (struct vms_mhd) + 1) & ~1;
1822 if (vms_write_data_block (arch, &data, &off, blk, sz, 0) < 0)
1823 goto input_err;
1824
1825 if (bfd_seek (current, 0, SEEK_SET) != 0)
1826 goto input_err;
1827
1828 while (1)
1829 {
1830 sz = bfd_bread (blk, sizeof (blk), current);
1831 if (sz == 0)
1832 break;
1833 if (vms_write_data_block (arch, &data, &off, blk, sz, 0) < 0)
1834 goto input_err;
1835 }
1836 if (vms_write_data_block (arch, &data, &off,
1837 eotdesc, sizeof (eotdesc), 1) < 0)
1838 goto input_err;
1839 }
1840
1841 /* Write the indexes. */
1842 vbn = 2;
1843 if (vms_write_index (arch, modules, nbr_modules, &vbn, &mod_idx_vbn) != TRUE)
1844 return FALSE;
1845 if (vms_write_index (arch, symbols, nbr_symbols, &vbn, &sym_idx_vbn) != TRUE)
1846 return FALSE;
1847
1848 /* Write libary header. */
1849 {
1850 unsigned char blk[VMS_BLOCK_SIZE];
1851 struct vms_lhd *lhd = (struct vms_lhd *)blk;
1852 struct vms_idd *idd = (struct vms_idd *)(blk + sizeof (*lhd));
1853 unsigned int idd_flags;
1854
1855 memset (blk, 0, sizeof (blk));
1856
1857 lhd->type = LBR__C_TYP_EOBJ;
1858 lhd->nindex = 2;
1859 bfd_putl32 (LHD_SANEID3, lhd->sanity);
1860 bfd_putl16 (3, lhd->majorid);
1861 bfd_putl16 (0, lhd->minorid);
1862 snprintf ((char *)lhd->lbrver + 1, sizeof (lhd->lbrver) - 1,
1863 "GNU ar %u.%u.%u",
1864 (unsigned)(BFD_VERSION / 100000000UL),
1865 (unsigned)(BFD_VERSION / 1000000UL) % 100,
1866 (unsigned)(BFD_VERSION / 10000UL) % 100);
1867 lhd->lbrver[sizeof (lhd->lbrver) - 1] = 0;
1868 lhd->lbrver[0] = strlen ((char *)lhd->lbrver + 1);
1869
1870 /* FIXME. */
1871 bfd_putl64 (0, lhd->credat);
1872 bfd_putl64 (0, lhd->updtim);
1873
1874 lhd->mhdusz = sizeof (struct vms_mhd) - MHD__C_USRDAT;
1875
1876 bfd_putl32 (nbr_modules + nbr_symbols, lhd->idxcnt);
1877 bfd_putl32 (nbr_modules, lhd->modcnt);
1878 bfd_putl32 (nbr_modules, lhd->modhdrs);
1879
1880 bfd_putl32 (vbn - 1, lhd->hipreal);
1881 bfd_putl32 (vbn - 1, lhd->hiprusd);
1882
1883 /* First index (modules name). */
1884 idd_flags = IDD__FLAGS_ASCII | IDD__FLAGS_VARLENIDX
1885 | IDD__FLAGS_NOCASECMP | IDD__FLAGS_NOCASENTR;
1886 bfd_putl16 (idd_flags, idd->flags);
1887 bfd_putl16 (MAX_KEYLEN, idd->keylen);
1888 bfd_putl16 (mod_idx_vbn, idd->vbn);
1889 idd++;
1890
1891 /* Second index (symbols name). */
1892 bfd_putl16 (idd_flags, idd->flags);
1893 bfd_putl16 (MAX_KEYLEN, idd->keylen);
1894 bfd_putl16 (sym_idx_vbn, idd->vbn);
1895 idd++;
1896
1897 if (bfd_seek (arch, 0, SEEK_SET) != 0)
1898 return FALSE;
1899 if (bfd_bwrite (blk, sizeof (blk), arch) != sizeof (blk))
1900 return FALSE;
1901 }
1902
1903 return TRUE;
1904
1905 input_err:
1906 bfd_set_error (bfd_error_on_input, current, bfd_get_error ());
1907 return FALSE;
1908 }
1909
1910 /* Add a target for text library. This costs almost nothing and is useful to
1911 read VMS library on the host. */
1912
1913 const bfd_target vms_lib_txt_vec =
1914 {
1915 "vms-libtxt", /* Name. */
1916 bfd_target_unknown_flavour,
1917 BFD_ENDIAN_UNKNOWN, /* byteorder */
1918 BFD_ENDIAN_UNKNOWN, /* header_byteorder */
1919 0, /* Object flags. */
1920 0, /* Sect flags. */
1921 0, /* symbol_leading_char. */
1922 ' ', /* ar_pad_char. */
1923 15, /* ar_max_namelen. */
1924 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1925 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1926 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
1927 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1928 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1929 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
1930
1931 {_bfd_dummy_target, _bfd_dummy_target, /* bfd_check_format. */
1932 _bfd_vms_lib_txt_archive_p, _bfd_dummy_target},
1933 {bfd_false, bfd_false, bfd_false, bfd_false}, /* bfd_set_format. */
1934 {bfd_false, bfd_false, bfd_false, bfd_false}, /* bfd_write_contents. */
1935
1936 BFD_JUMP_TABLE_GENERIC (_bfd_generic),
1937 BFD_JUMP_TABLE_COPY (_bfd_generic),
1938 BFD_JUMP_TABLE_CORE (_bfd_nocore),
1939 BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib),
1940 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
1941 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1942 BFD_JUMP_TABLE_WRITE (_bfd_nowrite),
1943 BFD_JUMP_TABLE_LINK (_bfd_nolink),
1944 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1945
1946 NULL,
1947
1948 (PTR) 0
1949 };
This page took 0.070574 seconds and 4 git commands to generate.