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