OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [vms-lib.c] - Blame information for rev 139

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.