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