bfd/
[platform/upstream/binutils.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 };