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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.2/] [bfd/] [vms-lib.c] - Blame information for rev 330

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 330 jeremybenn
/* 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, void *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 *buf, 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
 
960
  /* Do not read past the end.  */
961
  if (vec->where >= vec->file_len)
962
    return 0;
963
 
964
  res = 0;
965
  while (nbytes > 0)
966
    {
967
      if (vec->rec_rem == 0)
968
        {
969
          unsigned char blen[2];
970
 
971
          /* Read record length.  */
972
          if (vms_lib_bread_raw (abfd, &blen, sizeof (blen)) != sizeof (blen))
973
            return -1;
974
          vec->rec_len = bfd_getl16 (blen);
975
          if (bfd_libdata (abfd->my_archive)->kind == vms_lib_txt)
976
            {
977
              /* Discard record size and align byte.  */
978
              vec->rec_pos = 0;
979
              vec->rec_rem = vec->rec_len;
980
            }
981
          else
982
            {
983
              /* Prepend record size.  */
984
              vec->rec_pos = REC_POS_LEN0;
985
              vec->rec_rem = (vec->rec_len + 1) & ~1;   /* With align byte.  */
986
            }
987
          if (vec->rec_len == 3)
988
            {
989
              /* Possibly end of file.  Check the pattern.  */
990
              if (vms_lib_bread_raw (abfd, vec->pattern, 4) != 4)
991
                return -1;
992
              if (!memcmp (vec->pattern, eotdesc + 2, 3))
993
                {
994
                  /* This is really an EOF.  */
995
                  vec->where += res;
996
                  vec->file_len = vec->where;
997
                  return res;
998
                }
999
            }
1000
 
1001
          if (vec->dcxsbms != NULL)
1002
            {
1003
              /* This is a compressed member.  */
1004
              unsigned int len;
1005
              file_ptr elen;
1006
 
1007
              /* Be sure there is enough room for the expansion.  */
1008
              len = (vec->rec_len + 1) & ~1;
1009
              if (len > vec->dcx_max)
1010
                {
1011
                  while (len > vec->dcx_max)
1012
                    vec->dcx_max *= 2;
1013
                  vec->dcx_buf = bfd_alloc (abfd, vec->dcx_max);
1014
                  if (vec->dcx_buf == NULL)
1015
                    return -1;
1016
                }
1017
 
1018
              /* Read the compressed record.  */
1019
              vec->dcx_rlen = len;
1020
              if (vec->rec_len == 3)
1021
                {
1022
                  /* Already read.  */
1023
                  memcpy (vec->dcx_buf, vec->pattern, 3);
1024
                }
1025
              else
1026
                {
1027
                  elen = vms_lib_bread_raw (abfd, vec->dcx_buf, len);
1028
                  if (elen != len)
1029
                    return -1;
1030
                }
1031
 
1032
              /* Dummy expansion to get the expanded length.  */
1033
              vec->dcx_offset = 0;
1034
              vec->dcx_sbm = vec->dcxsbms;
1035
              vec->dcx_pos = 0;
1036
              elen = vms_lib_dcx (vec, NULL, 0x10000);
1037
              if (elen < 0)
1038
                return -1;
1039
              vec->rec_len = elen;
1040
              vec->rec_rem = elen;
1041
 
1042
              /* Reset the state.  */
1043
              vec->dcx_offset = 0;
1044
              vec->dcx_sbm = vec->dcxsbms;
1045
              vec->dcx_pos = 0;
1046
            }
1047
        }
1048
      if (vec->rec_pos < 0)
1049
        {
1050
          unsigned char c;
1051
          switch (vec->rec_pos)
1052
            {
1053
            case REC_POS_LEN0:
1054
              c = vec->rec_len & 0xff;
1055
              vec->rec_pos = REC_POS_LEN1;
1056
              break;
1057
            case REC_POS_LEN1:
1058
              c = (vec->rec_len >> 8) & 0xff;
1059
              vec->rec_pos = 0;
1060
              break;
1061
            case REC_POS_PAD:
1062
              c = 0;
1063
              vec->rec_rem = 0;
1064
              break;
1065
            case REC_POS_NL:
1066
              c = '\n';
1067
              vec->rec_rem = 0;
1068
              break;
1069
            default:
1070
              abort ();
1071
            }
1072
          if (buf != NULL)
1073
            {
1074
              *(unsigned char *)buf = c;
1075
              buf++;
1076
            }
1077
          nbytes--;
1078
          res++;
1079
          continue;
1080
        }
1081
 
1082
      if (nbytes > vec->rec_rem)
1083
        chunk = vec->rec_rem;
1084
      else
1085
        chunk = nbytes;
1086
 
1087
      if (vec->dcxsbms != NULL)
1088
        {
1089
          /* Optimize the stat() case: no need to decompress again as we
1090
             know the length.  */
1091
          if (!(buf == NULL && chunk == vec->rec_rem))
1092
            chunk = vms_lib_dcx (vec, buf, chunk);
1093
        }
1094
      else
1095
        {
1096
          if (vec->rec_len == 3)
1097
            {
1098
              if (buf != NULL)
1099
                memcpy (buf, vec->pattern + vec->rec_pos, chunk);
1100
            }
1101
          else
1102
            chunk = vms_lib_bread_raw (abfd, buf, chunk);
1103
        }
1104
      if (chunk < 0)
1105
        return -1;
1106
      res += chunk;
1107
      if (buf != NULL)
1108
        buf += chunk;
1109
      nbytes -= chunk;
1110
      vec->rec_pos += chunk;
1111
      vec->rec_rem -= chunk;
1112
 
1113
      if (vec->rec_rem == 0)
1114
        {
1115
          /* End of record reached.  */
1116
          if (bfd_libdata (abfd->my_archive)->kind == vms_lib_txt)
1117
            {
1118
              if ((vec->rec_len & 1) == 1
1119
                  && vec->rec_len != 3
1120
                  && vec->dcxsbms == NULL)
1121
                {
1122
                  /* Eat the pad byte.  */
1123
                  unsigned char pad;
1124
                  if (vms_lib_bread_raw (abfd, &pad, 1) != 1)
1125
                    return -1;
1126
                }
1127
              vec->rec_pos = REC_POS_NL;
1128
              vec->rec_rem = 1;
1129
            }
1130
          else
1131
            {
1132
              if ((vec->rec_len & 1) == 1 && vec->dcxsbms != NULL)
1133
                {
1134
                  vec->rec_pos = REC_POS_PAD;
1135
                  vec->rec_rem = 1;
1136
                }
1137
            }
1138
        }
1139
    }
1140
  vec->where += res;
1141
  return res;
1142
}
1143
 
1144
/* Standard function, but we currently only handle the rewind case.  */
1145
 
1146
static int
1147
vms_lib_bseek (struct bfd *abfd, file_ptr offset, int whence)
1148
{
1149
  struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
1150
 
1151
  if (whence == SEEK_SET && offset == 0)
1152
    {
1153
      vec->where = 0;
1154
      vec->rec_rem = 0;
1155
      vec->dcx_pos = -1;
1156
      vec->blk_off = vec->init_blk_off;
1157
      vec->next_block = vec->init_next_block;
1158
 
1159
      if (bfd_seek (abfd->my_archive, vec->first_block, SEEK_SET) != 0)
1160
        return -1;
1161
    }
1162
  else
1163
    abort ();
1164
  return 0;
1165
}
1166
 
1167
static file_ptr
1168
vms_lib_bwrite (struct bfd *abfd ATTRIBUTE_UNUSED,
1169
              const void *where ATTRIBUTE_UNUSED,
1170
              file_ptr nbytes ATTRIBUTE_UNUSED)
1171
{
1172
  return -1;
1173
}
1174
 
1175
static int
1176
vms_lib_bclose (struct bfd *abfd)
1177
{
1178
  abfd->iostream = NULL;
1179
  return 0;
1180
}
1181
 
1182
static int
1183
vms_lib_bflush (struct bfd *abfd ATTRIBUTE_UNUSED)
1184
{
1185
  return 0;
1186
}
1187
 
1188
static int
1189
vms_lib_bstat (struct bfd *abfd ATTRIBUTE_UNUSED,
1190
               struct stat *sb ATTRIBUTE_UNUSED)
1191
{
1192
  /* Not supported.  */
1193
  return 0;
1194
}
1195
 
1196
static void *
1197
vms_lib_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED,
1198
              void *addr ATTRIBUTE_UNUSED,
1199
              bfd_size_type len ATTRIBUTE_UNUSED,
1200
              int prot ATTRIBUTE_UNUSED,
1201
              int flags ATTRIBUTE_UNUSED,
1202
              file_ptr offset ATTRIBUTE_UNUSED)
1203
{
1204
  return (void *) -1;
1205
}
1206
 
1207
static const struct bfd_iovec vms_lib_iovec = {
1208
  &vms_lib_bread, &vms_lib_bwrite, &vms_lib_btell, &vms_lib_bseek,
1209
  &vms_lib_bclose, &vms_lib_bflush, &vms_lib_bstat, &vms_lib_bmmap
1210
};
1211
 
1212
/* Open a library module.  FILEPOS is the position of the module header.  */
1213
 
1214
static bfd_boolean
1215
vms_lib_bopen (bfd *el, file_ptr filepos)
1216
{
1217
  struct vms_lib_iovec *vec;
1218
  char buf[256];
1219
  struct vms_mhd *mhd;
1220
  struct lib_tdata *tdata = bfd_libdata (el->my_archive);
1221
  unsigned int len;
1222
 
1223
  /* Allocate and initialized the iovec.  */
1224
  vec = bfd_zalloc (el, sizeof (*vec));
1225
  if (vec == NULL)
1226
    return FALSE;
1227
 
1228
  el->iostream = vec;
1229
  el->iovec = &vms_lib_iovec;
1230
 
1231
  /* File length is not known.  */
1232
  vec->file_len = -1;
1233
 
1234
  /* Read the first data block.  */
1235
  vec->next_block = filepos & ~(VMS_BLOCK_SIZE - 1);
1236
  vec->blk_off = DATA__LENGTH;
1237
  if (!vms_lib_read_block (el))
1238
    return FALSE;
1239
 
1240
  /* Prepare to read the first record.  */
1241
  vec->blk_off = filepos & (VMS_BLOCK_SIZE - 1);
1242
  vec->rec_rem = 0;
1243
  if (bfd_seek (el->my_archive, filepos, SEEK_SET) != 0)
1244
    return FALSE;
1245
 
1246
  /* Read Record length + MHD + align byte.  */
1247
  len = tdata->mhd_size;
1248
  if (vms_lib_bread_raw (el, buf, 2) != 2)
1249
    return FALSE;
1250
  if (bfd_getl16 (buf) != len)
1251
    return FALSE;
1252
  len = (len + 1) & ~1;
1253
  BFD_ASSERT (len <= sizeof (buf));
1254
  if (vms_lib_bread_raw (el, buf, len) != len)
1255
    return FALSE;
1256
 
1257
  /* Get info from mhd.  */
1258
  mhd = (struct vms_mhd *)buf;
1259
  /* Check id.  */
1260
  if (mhd->id != MHD__C_MHDID)
1261
    return FALSE;
1262
  if (len >= MHD__C_MHDLEN + 1)
1263
    el->selective_search = (mhd->objstat & MHD__M_SELSRC) ? 1 : 0;
1264
  el->mtime = vms_rawtime_to_time_t (mhd->datim);
1265
  el->mtime_set = TRUE;
1266
 
1267
  /* Reinit the iovec so that seek() will point to the first record after
1268
     the mhd.  */
1269
  vec->where = 0;
1270
  vec->init_blk_off = vec->blk_off;
1271
  vec->init_next_block = vec->next_block;
1272
  vec->first_block = bfd_tell (el->my_archive);
1273
  vec->dcxsbms = bfd_libdata (el->my_archive)->dcxsbm;
1274
 
1275
  if (vec->dcxsbms != NULL)
1276
    {
1277
      /* Handle DCX.  */
1278
      vec->dcx_max = 10 * 1024;
1279
      vec->dcx_buf = bfd_alloc (el, vec->dcx_max);
1280
      vec->dcx_pos = -1;
1281
      if (vec->dcx_buf == NULL)
1282
        return -1;
1283
    }
1284
  return TRUE;
1285
}
1286
 
1287
/* Get member MODIDX.  Return NULL in case of error.  */
1288
 
1289
static bfd *
1290
_bfd_vms_lib_get_module (bfd *abfd, unsigned int modidx)
1291
{
1292
  struct lib_tdata *tdata = bfd_libdata (abfd);
1293
  bfd *res;
1294
  file_ptr file_off;
1295
 
1296
  /* Sanity check.  */
1297
  if (modidx >= tdata->nbr_modules)
1298
    return NULL;
1299
 
1300
  /* Already loaded.  */
1301
  if (tdata->cache[modidx])
1302
    return tdata->cache[modidx];
1303
 
1304
  /* Build it.  */
1305
  file_off = tdata->modules[modidx].file_offset;
1306
  if (tdata->type != LBR__C_TYP_IOBJ)
1307
    {
1308
      res = _bfd_create_empty_archive_element_shell (abfd);
1309
      if (res == NULL)
1310
        return NULL;
1311
 
1312
      /* Special reader to deal with data blocks.  */
1313
      if (!vms_lib_bopen (res, file_off))
1314
        return NULL;
1315
    }
1316
  else
1317
    {
1318
      char buf[256];
1319
      struct vms_mhd *mhd;
1320
      struct areltdata *arelt;
1321
 
1322
      /* Sanity check.  The MHD must be big enough to contain module size.  */
1323
      if (tdata->mhd_size < offsetof (struct vms_mhd, modsize) + 4)
1324
        return NULL;
1325
 
1326
      /* Read the MHD now.  */
1327
      if (bfd_seek (abfd, file_off, SEEK_SET) != 0)
1328
        return NULL;
1329
      if (bfd_bread (buf, tdata->mhd_size, abfd) != tdata->mhd_size)
1330
        return NULL;
1331
 
1332
      res = _bfd_create_empty_archive_element_shell (abfd);
1333
      if (res == NULL)
1334
        return NULL;
1335
      arelt = bfd_zalloc (res, sizeof (*arelt));
1336
      if (arelt == NULL)
1337
        return NULL;
1338
      res->arelt_data = arelt;
1339
 
1340
      /* Get info from mhd.  */
1341
      mhd = (struct vms_mhd *)buf;
1342
      if (mhd->id != MHD__C_MHDID)
1343
        return NULL;
1344
      if (tdata->mhd_size >= offsetof (struct vms_mhd, objstat) + 1)
1345
        res->selective_search = (mhd->objstat & MHD__M_SELSRC) ? 1 : 0;
1346
      res->mtime = vms_rawtime_to_time_t (mhd->datim);
1347
      res->mtime_set = TRUE;
1348
 
1349
      arelt->parsed_size = bfd_getl32 (mhd->modsize);
1350
 
1351
      /* No need for a special reader as members are stored linearly.
1352
         Just skip the MHD.  */
1353
      res->origin = file_off + tdata->mhd_size;
1354
    }
1355
 
1356
  res->filename = tdata->modules[modidx].name;
1357
 
1358
  tdata->cache[modidx] = res;
1359
 
1360
  return res;
1361
}
1362
 
1363
/* Standard function: get member at IDX.  */
1364
 
1365
bfd *
1366
_bfd_vms_lib_get_elt_at_index (bfd *abfd, symindex symidx)
1367
{
1368
  struct lib_tdata *tdata = bfd_libdata (abfd);
1369
  file_ptr file_off;
1370
  unsigned int modidx;
1371
 
1372
  /* Check symidx.  */
1373
  if (symidx > tdata->artdata.symdef_count)
1374
    return NULL;
1375
  file_off = tdata->artdata.symdefs[symidx].file_offset;
1376
 
1377
  /* Linear-scan.  */
1378
  for (modidx = 0; modidx < tdata->nbr_modules; modidx++)
1379
    {
1380
      if (tdata->modules[modidx].file_offset == file_off)
1381
        break;
1382
    }
1383
  if (modidx >= tdata->nbr_modules)
1384
    return NULL;
1385
 
1386
  return _bfd_vms_lib_get_module (abfd, modidx);
1387
}
1388
 
1389
/* Elements of an imagelib are stubs.  You can get the real image with this
1390
   function.  */
1391
 
1392
bfd *
1393
_bfd_vms_lib_get_imagelib_file (bfd *el)
1394
{
1395
  bfd *archive = el->my_archive;
1396
  const char *modname = el->filename;
1397
  int modlen = strlen (modname);
1398
  char *filename;
1399
  int j;
1400
  bfd *res;
1401
 
1402
  /* Convert module name to lower case and append '.exe'.  */
1403
  filename = bfd_alloc (el, modlen + 5);
1404
  if (filename == NULL)
1405
    return NULL;
1406
  for (j = 0; j < modlen; j++)
1407
    if (ISALPHA (modname[j]))
1408
      filename[j] = TOLOWER (modname[j]);
1409
    else
1410
      filename[j] = modname[j];
1411
  memcpy (filename + modlen, ".exe", 5);
1412
 
1413
  filename = _bfd_append_relative_path (archive, filename);
1414
  if (filename == NULL)
1415
    return NULL;
1416
  res = bfd_openr (filename, NULL);
1417
 
1418
  if (res == NULL)
1419
    {
1420
      (*_bfd_error_handler)(_("could not open shared image '%s' from '%s'"),
1421
                            filename, archive->filename);
1422
      bfd_release (archive, filename);
1423
      return NULL;
1424
    }
1425
 
1426
  /* FIXME: put it in a cache ?  */
1427
  return res;
1428
}
1429
 
1430
/* Standard function.  */
1431
 
1432
bfd *
1433
_bfd_vms_lib_openr_next_archived_file (bfd *archive,
1434
                                       bfd *last_file)
1435
{
1436
  unsigned int idx;
1437
  bfd *res;
1438
 
1439
  if (!last_file)
1440
    idx = 0;
1441
  else
1442
    idx = last_file->proxy_origin + 1;
1443
 
1444
  if (idx >= bfd_libdata (archive)->nbr_modules)
1445
    {
1446
      bfd_set_error (bfd_error_no_more_archived_files);
1447
      return NULL;
1448
    }
1449
 
1450
  res = _bfd_vms_lib_get_module (archive, idx);
1451
  if (res == NULL)
1452
    return res;
1453
  res->proxy_origin = idx;
1454
  return res;
1455
}
1456
 
1457
/* Standard function.  Just compute the length.  */
1458
 
1459
int
1460
_bfd_vms_lib_generic_stat_arch_elt (bfd *abfd, struct stat *st)
1461
{
1462
  struct lib_tdata *tdata;
1463
 
1464
  /* Sanity check.  */
1465
  if (abfd->my_archive == NULL)
1466
    {
1467
      bfd_set_error (bfd_error_invalid_operation);
1468
      return -1;
1469
    }
1470
 
1471
  tdata = bfd_libdata (abfd->my_archive);
1472
  if (tdata->type != LBR__C_TYP_IOBJ)
1473
    {
1474
      struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream;
1475
 
1476
      if (vec->file_len == (ufile_ptr)-1)
1477
        {
1478
          if (vms_lib_bseek (abfd, 0, SEEK_SET) != 0)
1479
            return -1;
1480
 
1481
          /* Compute length.  */
1482
          while (vms_lib_bread (abfd, NULL, 1 << 20) > 0)
1483
            ;
1484
        }
1485
      st->st_size = vec->file_len;
1486
    }
1487
  else
1488
    {
1489
      st->st_size = ((struct areltdata *)abfd->arelt_data)->parsed_size;
1490
    }
1491
 
1492
  if (abfd->mtime_set)
1493
    st->st_mtime = abfd->mtime;
1494
  else
1495
    st->st_mtime = 0;
1496
  st->st_uid = 0;
1497
  st->st_gid = 0;
1498
  st->st_mode = 0644;
1499
 
1500
  return 0;
1501
}
1502
 
1503
/* Internal representation of an index entry.  */
1504
 
1505
struct lib_index
1506
{
1507
  /* Corresponding archive member.  */
1508
  bfd *abfd;
1509
 
1510
  /* Number of reference to this entry.  */
1511
  unsigned int ref;
1512
 
1513
  /* Length of the key.  */
1514
  unsigned short namlen;
1515
 
1516
  /* Key.  */
1517
  const char *name;
1518
};
1519
 
1520
/* Used to sort index entries.  */
1521
 
1522
static int
1523
lib_index_cmp (const void *lv, const void *rv)
1524
{
1525
  const struct lib_index *l = lv;
1526
  const struct lib_index *r = rv;
1527
 
1528
  return strcmp (l->name, r->name);
1529
}
1530
 
1531
/* Maximum number of index blocks level.  */
1532
 
1533
#define MAX_LEVEL 10
1534
 
1535
/* Get the size of an index entry.  */
1536
 
1537
static unsigned int
1538
get_idxlen (struct lib_index *idx, bfd_boolean is_elfidx)
1539
{
1540
  if (is_elfidx)
1541
    {
1542
      if (idx->namlen > MAX_KEYLEN)
1543
        return 9 + sizeof (struct vms_rfa);
1544
      else
1545
        return 9 + idx->namlen;
1546
    }
1547
  else
1548
    return 7 + idx->namlen;
1549
}
1550
 
1551
/* Write the index.  VBN is the first vbn to be used, and will contain
1552
   on return the last vbn.
1553
   Return TRUE on success.  */
1554
 
1555
static bfd_boolean
1556
vms_write_index (bfd *abfd,
1557
                 struct lib_index *idx, unsigned int nbr, unsigned int *vbn,
1558
                 unsigned int *topvbn, bfd_boolean is_elfidx)
1559
{
1560
  unsigned int i;
1561
  int j;
1562
  int level;
1563
  struct vms_indexdef *rblk[MAX_LEVEL];
1564
  struct idxblk
1565
  {
1566
    unsigned int vbn;
1567
    unsigned short len;
1568
    unsigned short lastlen;
1569
  } blk[MAX_LEVEL];
1570
 
1571
  /* The kbn blocks are used to store long symbol names.  */
1572
  unsigned int kbn_sz = 0;        /* Number of bytes availble in the kbn block.  */
1573
  unsigned int kbn_vbn = 0;       /* VBN of the kbn block.  */
1574
  unsigned char *kbn_blk = NULL; /* Contents of the kbn block.  */
1575
 
1576
  if (nbr == 0)
1577
    {
1578
      /* No entries.  Very easy to handle.  */
1579
      if (topvbn != NULL)
1580
        *topvbn = 0;
1581
      return TRUE;
1582
    }
1583
 
1584
  if (abfd == NULL)
1585
    {
1586
      /* Sort the index the first time this function is called.  */
1587
      qsort (idx, nbr, sizeof (struct lib_index), lib_index_cmp);
1588
    }
1589
 
1590
  /* Allocate first index block.  */
1591
  level = 1;
1592
  if (abfd != NULL)
1593
    rblk[0] = bfd_malloc (sizeof (struct vms_indexdef));
1594
  blk[0].vbn = (*vbn)++;
1595
  blk[0].len = 0;
1596
  blk[0].lastlen = 0;
1597
 
1598
  for (i = 0; i < nbr; i++, idx++)
1599
    {
1600
      unsigned int idxlen;
1601
      int flush = 0;
1602
      unsigned int key_vbn = 0;
1603
      unsigned int key_off = 0;
1604
 
1605
      idxlen = get_idxlen (idx, is_elfidx);
1606
 
1607
      if (is_elfidx && idx->namlen >= MAX_KEYLEN)
1608
        {
1609
          /* If the name is too long, write it in the kbn block.  */
1610
          unsigned int kl = idx->namlen;
1611
          unsigned int kl_chunk;
1612
          const char *key = idx->name;
1613
 
1614
          /* Write the name in the kbn, chunk after chunk.  */
1615
          do
1616
            {
1617
              if (kbn_sz < sizeof (struct vms_kbn))
1618
                {
1619
                  /* Not enough room in the kbn block.  */
1620
                  if (abfd != NULL)
1621
                    {
1622
                      /* Write it to the disk (if there is one).  */
1623
                      if (kbn_vbn != 0)
1624
                        {
1625
                          if (vms_write_block (abfd, kbn_vbn, kbn_blk) != TRUE)
1626
                            return FALSE;
1627
                        }
1628
                      else
1629
                        {
1630
                          kbn_blk = bfd_malloc (VMS_BLOCK_SIZE);
1631
                          if (kbn_blk == NULL)
1632
                            return FALSE;
1633
                        }
1634
                      *(unsigned short *)kbn_blk = 0;
1635
                    }
1636
                  kbn_vbn = (*vbn)++;
1637
                  kbn_sz = VMS_BLOCK_SIZE - 2;
1638
                }
1639
              if (kl + sizeof (struct vms_kbn) > kbn_sz)
1640
                kl_chunk = kbn_sz - sizeof (struct vms_kbn);
1641
              else
1642
                kl_chunk = kl;
1643
 
1644
              if (kbn_blk != NULL)
1645
                {
1646
                  struct vms_kbn *kbn;
1647
 
1648
                  kbn = (struct vms_kbn *)(kbn_blk + VMS_BLOCK_SIZE - kbn_sz);
1649
 
1650
                  if (key_vbn == 0)
1651
                    {
1652
                      /* Save the rfa of the first chunk.  */
1653
                      key_vbn = kbn_vbn;
1654
                      key_off = VMS_BLOCK_SIZE - kbn_sz;
1655
                    }
1656
 
1657
                  bfd_putl16 (kl_chunk, kbn->keylen);
1658
                  if (kl_chunk == kl)
1659
                    {
1660
                      /* No next chunk.  */
1661
                      bfd_putl32 (0, kbn->rfa.vbn);
1662
                      bfd_putl16 (0, kbn->rfa.offset);
1663
                    }
1664
                  else
1665
                    {
1666
                      /* Next chunk will be at the start of the next block.  */
1667
                      bfd_putl32 (*vbn, kbn->rfa.vbn);
1668
                      bfd_putl16 (2, kbn->rfa.offset);
1669
                    }
1670
                  memcpy ((char *)(kbn + 1), key, kl_chunk);
1671
                  key += kl_chunk;
1672
                }
1673
              kl -= kl_chunk;
1674
              kl_chunk = (kl_chunk + 1) & ~1;     /* Always align.  */
1675
              kbn_sz -= kl_chunk + sizeof (struct vms_kbn);
1676
            }
1677
          while (kl > 0);
1678
        }
1679
 
1680
      /* Check if a block might overflow.  In this case we will flush this
1681
         block and all the blocks below it.  */
1682
      for (j = 0; j < level; j++)
1683
        if (blk[j].len + blk[j].lastlen + idxlen > INDEXDEF__BLKSIZ)
1684
          flush = j + 1;
1685
 
1686
      for (j = 0; j < level; j++)
1687
        {
1688
          if (j < flush)
1689
            {
1690
              /* There is not enough room to write the new entry in this
1691
                 block or in a parent block.  */
1692
 
1693
              if (j + 1 == level)
1694
                {
1695
                  BFD_ASSERT (level < MAX_LEVEL);
1696
 
1697
                  /* Need to create a parent.  */
1698
                  if (abfd != NULL)
1699
                    {
1700
                      rblk[level] = bfd_malloc (sizeof (struct vms_indexdef));
1701
                      bfd_putl32 (*vbn, rblk[j]->parent);
1702
                    }
1703
                  blk[level].vbn = (*vbn)++;
1704
                  blk[level].len = 0;
1705
                  blk[level].lastlen = 0;
1706
 
1707
                  level++;
1708
                }
1709
 
1710
              /* Update parent block: write the new entry.  */
1711
              if (abfd != NULL)
1712
                {
1713
                  struct vms_rfa *rfa;
1714
 
1715
                  /* Copy the whole entry.  */
1716
                  memcpy (rblk[j + 1]->keys + blk[j + 1].len,
1717
                          rblk[j]->keys + blk[j].len,
1718
                          blk[j].lastlen);
1719
                  /* Fix the entry (which in always the first field of an entry.  */
1720
                  rfa = (struct vms_rfa *)(rblk[j + 1]->keys + blk[j + 1].len);
1721
                  bfd_putl32 (blk[j].vbn, rfa->vbn);
1722
                  bfd_putl16 (RFADEF__C_INDEX, rfa->offset);
1723
                }
1724
 
1725
              if (j + 1 == flush)
1726
                {
1727
                  /* And allocate it.  Do it only on the block that won't be
1728
                     flushed (so that the parent of the parent can be
1729
                     updated too).  */
1730
                  blk[j + 1].len += blk[j].lastlen;
1731
                  blk[j + 1].lastlen = 0;
1732
                }
1733
 
1734
              /* Write this block on the disk.  */
1735
              if (abfd != NULL)
1736
                {
1737
                  bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used);
1738
                  if (vms_write_block (abfd, blk[j].vbn, rblk[j]) != TRUE)
1739
                    return FALSE;
1740
                }
1741
 
1742
              /* Reset this block.  */
1743
              blk[j].len = 0;
1744
              blk[j].lastlen = 0;
1745
              blk[j].vbn = (*vbn)++;
1746
            }
1747
 
1748
          /* Append it to the block.  */
1749
          if (j == 0)
1750
            {
1751
              blk[j].len += blk[j].lastlen;
1752
 
1753
              if (abfd != NULL)
1754
                {
1755
                  struct vms_rfa *rfa;
1756
 
1757
                  rfa = (struct vms_rfa *)(rblk[j]->keys + blk[j].len);
1758
                  bfd_putl32 ((idx->abfd->proxy_origin / VMS_BLOCK_SIZE) + 1,
1759
                              rfa->vbn);
1760
                  bfd_putl16
1761
                    ((idx->abfd->proxy_origin % VMS_BLOCK_SIZE)
1762
                     + (is_elfidx ? 0 : DATA__DATA),
1763
                     rfa->offset);
1764
 
1765
                  if (is_elfidx)
1766
                    {
1767
                      /* Use elfidx format.  */
1768
                      struct vms_elfidx *en = (struct vms_elfidx *)rfa;
1769
 
1770
                      en->flags = 0;
1771
                      if (key_vbn != 0)
1772
                        {
1773
                          /* Long symbol name.  */
1774
                          struct vms_kbn *k = (struct vms_kbn *)(en->keyname);
1775
                          bfd_putl16 (sizeof (struct vms_kbn), en->keylen);
1776
                          bfd_putl16 (idx->namlen, k->keylen);
1777
                          bfd_putl32 (key_vbn, k->rfa.vbn);
1778
                          bfd_putl16 (key_off, k->rfa.offset);
1779
                          en->flags |= ELFIDX__SYMESC;
1780
                        }
1781
                      else
1782
                        {
1783
                          bfd_putl16 (idx->namlen, en->keylen);
1784
                          memcpy (en->keyname, idx->name, idx->namlen);
1785
                        }
1786
                    }
1787
                  else
1788
                    {
1789
                      /* Use idx format.  */
1790
                      struct vms_idx *en = (struct vms_idx *)rfa;
1791
                      en->keylen = idx->namlen;
1792
                      memcpy (en->keyname, idx->name, idx->namlen);
1793
                    }
1794
                }
1795
            }
1796
 
1797
          blk[j].lastlen = idxlen;
1798
        }
1799
    }
1800
 
1801
  if (topvbn != NULL)
1802
    *topvbn = blk[level - 1].vbn;
1803
 
1804
  if (abfd == NULL)
1805
    return TRUE;
1806
 
1807
  /* Flush.  */
1808
  for (j = 0; j < level; j++)
1809
    {
1810
      if (j > 0)
1811
        {
1812
          /* Update parent block: write the new entry.  */
1813
          unsigned char *en;
1814
          unsigned char *par;
1815
          struct vms_rfa *rfa;
1816
 
1817
          en = rblk[j - 1]->keys + blk[j - 1].len;
1818
          par = rblk[j]->keys + blk[j].len;
1819
          memcpy (par, en, blk[j - 1].lastlen);
1820
          rfa = (struct vms_rfa *)par;
1821
          bfd_putl32 (blk[j - 1].vbn, rfa->vbn);
1822
          bfd_putl16 (RFADEF__C_INDEX, rfa->offset);
1823
        }
1824
 
1825
      /* Write this block on the disk.  */
1826
      bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used);
1827
      if (vms_write_block (abfd, blk[j].vbn, rblk[j]) != TRUE)
1828
        return FALSE;
1829
 
1830
      free (rblk[j]);
1831
    }
1832
 
1833
  if (kbn_vbn != 0)
1834
    {
1835
      if (vms_write_block (abfd, kbn_vbn, kbn_blk) != TRUE)
1836
        return FALSE;
1837
    }
1838
 
1839
  return TRUE;
1840
}
1841
 
1842
/* Append data to the data block DATA.  Force write if PAD is true.  */
1843
 
1844
static bfd_boolean
1845
vms_write_data_block (bfd *arch, struct vms_datadef *data, file_ptr *off,
1846
                      const unsigned char *buf, unsigned int len, int pad)
1847
{
1848
  while (len > 0 || pad)
1849
    {
1850
      unsigned int doff = *off & (VMS_BLOCK_SIZE - 1);
1851
      unsigned int remlen = (DATA__LENGTH - DATA__DATA) - doff;
1852
      unsigned int l;
1853
 
1854
      l = (len > remlen) ? remlen : len;
1855
      memcpy (data->data + doff, buf, l);
1856
      buf += l;
1857
      len -= l;
1858
      doff += l;
1859
      *off += l;
1860
 
1861
      if (doff == (DATA__LENGTH - DATA__DATA) || (len == 0 && pad))
1862
        {
1863
          data->recs = 0;
1864
          data->fill_1 = 0;
1865
          bfd_putl32 ((*off / VMS_BLOCK_SIZE) + 2, data->link);
1866
 
1867
          if (bfd_bwrite (data, sizeof (*data), arch) != sizeof (*data))
1868
            return FALSE;
1869
 
1870
          *off += DATA__LENGTH - doff;
1871
 
1872
          if (len == 0)
1873
            break;
1874
        }
1875
    }
1876
  return TRUE;
1877
}
1878
 
1879
/* Build the symbols index.  */
1880
 
1881
static bfd_boolean
1882
_bfd_vms_lib_build_map (unsigned int nbr_modules,
1883
                        struct lib_index *modules,
1884
                        unsigned int *res_cnt,
1885
                        struct lib_index **res)
1886
{
1887
  unsigned int i;
1888
  asymbol **syms = NULL;
1889
  long syms_max = 0;
1890
  struct lib_index *map = NULL;
1891
  unsigned int map_max = 1024;          /* Fine initial default.  */
1892
  unsigned int map_count = 0;
1893
 
1894
  map = (struct lib_index *) bfd_malloc (map_max * sizeof (struct lib_index));
1895
  if (map == NULL)
1896
    goto error_return;
1897
 
1898
  /* Gather symbols.  */
1899
  for (i = 0; i < nbr_modules; i++)
1900
    {
1901
      long storage;
1902
      long symcount;
1903
      long src_count;
1904
      bfd *current = modules[i].abfd;
1905
 
1906
      if ((bfd_get_file_flags (current) & HAS_SYMS) == 0)
1907
        continue;
1908
 
1909
      storage = bfd_get_symtab_upper_bound (current);
1910
      if (storage < 0)
1911
        goto error_return;
1912
 
1913
      if (storage != 0)
1914
        {
1915
          if (storage > syms_max)
1916
            {
1917
              if (syms_max > 0)
1918
                free (syms);
1919
              syms_max = storage;
1920
              syms = (asymbol **) bfd_malloc (syms_max);
1921
              if (syms == NULL)
1922
                goto error_return;
1923
            }
1924
          symcount = bfd_canonicalize_symtab (current, syms);
1925
          if (symcount < 0)
1926
            goto error_return;
1927
 
1928
          /* Now map over all the symbols, picking out the ones we
1929
             want.  */
1930
          for (src_count = 0; src_count < symcount; src_count++)
1931
            {
1932
              flagword flags = (syms[src_count])->flags;
1933
              asection *sec = syms[src_count]->section;
1934
 
1935
              if ((flags & BSF_GLOBAL
1936
                   || flags & BSF_WEAK
1937
                   || flags & BSF_INDIRECT
1938
                   || bfd_is_com_section (sec))
1939
                  && ! bfd_is_und_section (sec))
1940
                {
1941
                  struct lib_index *new_map;
1942
 
1943
                  /* This symbol will go into the archive header.  */
1944
                  if (map_count == map_max)
1945
                    {
1946
                      map_max *= 2;
1947
                      new_map = (struct lib_index *)
1948
                        bfd_realloc (map, map_max * sizeof (struct lib_index));
1949
                      if (new_map == NULL)
1950
                        goto error_return;
1951
                      map = new_map;
1952
                    }
1953
 
1954
                  map[map_count].abfd = current;
1955
                  map[map_count].namlen = strlen (syms[src_count]->name);
1956
                  map[map_count].name = syms[src_count]->name;
1957
                  map_count++;
1958
                  modules[i].ref++;
1959
                }
1960
            }
1961
        }
1962
    }
1963
 
1964
  *res_cnt = map_count;
1965
  *res = map;
1966
  return TRUE;
1967
 
1968
 error_return:
1969
  if (syms_max > 0)
1970
    free (syms);
1971
  if (map != NULL)
1972
    free (map);
1973
  return FALSE;
1974
}
1975
 
1976
/* Do the hard work: write an archive on the disk.  */
1977
 
1978
bfd_boolean
1979
_bfd_vms_lib_write_archive_contents (bfd *arch)
1980
{
1981
  bfd *current;
1982
  unsigned int nbr_modules;
1983
  struct lib_index *modules;
1984
  unsigned int nbr_symbols;
1985
  struct lib_index *symbols;
1986
  struct lib_tdata *tdata = bfd_libdata (arch);
1987
  unsigned int i;
1988
  file_ptr off;
1989
  unsigned int nbr_mod_iblk;
1990
  unsigned int nbr_sym_iblk;
1991
  unsigned int vbn;
1992
  unsigned int mod_idx_vbn;
1993
  unsigned int sym_idx_vbn;
1994
  bfd_boolean is_elfidx = tdata->kind == vms_lib_ia64;
1995
 
1996
  /* Count the number of modules (and do a first sanity check).  */
1997
  nbr_modules = 0;
1998
  for (current = arch->archive_head;
1999
       current != NULL;
2000
       current = current->archive_next)
2001
    {
2002
      /* This check is checking the bfds for the objects we're reading
2003
         from (which are usually either an object file or archive on
2004
         disk), not the archive entries we're writing to.  We don't
2005
         actually create bfds for the archive members, we just copy
2006
         them byte-wise when we write out the archive.  */
2007
      if (bfd_write_p (current) || !bfd_check_format (current, bfd_object))
2008
        {
2009
          bfd_set_error (bfd_error_invalid_operation);
2010
          goto input_err;
2011
        }
2012
 
2013
      nbr_modules++;
2014
    }
2015
 
2016
  /* Build the modules list.  */
2017
  BFD_ASSERT (tdata->modules == NULL);
2018
  modules = bfd_alloc (arch, nbr_modules * sizeof (struct lib_index));
2019
  if (modules == NULL)
2020
    return FALSE;
2021
 
2022
  for (current = arch->archive_head, i = 0;
2023
       current != NULL;
2024
       current = current->archive_next, i++)
2025
    {
2026
      int nl;
2027
 
2028
      modules[i].abfd = current;
2029
      modules[i].name = vms_get_module_name (current->filename, FALSE);
2030
      modules[i].ref = 1;
2031
 
2032
      /* FIXME: silently truncate long names ?  */
2033
      nl = strlen (modules[i].name);
2034
      modules[i].namlen = (nl > MAX_KEYLEN ? MAX_KEYLEN : nl);
2035
    }
2036
 
2037
  /* Create the module index.  */
2038
  vbn = 0;
2039
  if (!vms_write_index (NULL, modules, nbr_modules, &vbn, NULL, is_elfidx))
2040
    return FALSE;
2041
  nbr_mod_iblk = vbn;
2042
 
2043
  /* Create symbol index.  */
2044
  if (!_bfd_vms_lib_build_map (nbr_modules, modules, &nbr_symbols, &symbols))
2045
    return FALSE;
2046
 
2047
  vbn = 0;
2048
  if (!vms_write_index (NULL, symbols, nbr_symbols, &vbn, NULL, is_elfidx))
2049
    return FALSE;
2050
  nbr_sym_iblk = vbn;
2051
 
2052
  /* Write modules and remember their position.  */
2053
  off = (1 + nbr_mod_iblk + nbr_sym_iblk) * VMS_BLOCK_SIZE;
2054
 
2055
  if (bfd_seek (arch, off, SEEK_SET) != 0)
2056
    return FALSE;
2057
 
2058
  for (i = 0; i < nbr_modules; i++)
2059
    {
2060
      struct vms_datadef data;
2061
      unsigned char blk[VMS_BLOCK_SIZE];
2062
      struct vms_mhd *mhd;
2063
      unsigned int sz;
2064
 
2065
      current = modules[i].abfd;
2066
      current->proxy_origin = off;
2067
 
2068
      if (is_elfidx)
2069
        sz = 0;
2070
      else
2071
        {
2072
          /* Write the MHD as a record (ie, size first).  */
2073
          sz = 2;
2074
          bfd_putl16 (tdata->mhd_size, blk);
2075
        }
2076
      mhd = (struct vms_mhd *)(blk + sz);
2077
      memset (mhd, 0, sizeof (struct vms_mhd));
2078
      mhd->lbrflag = 0;
2079
      mhd->id = MHD__C_MHDID;
2080
      mhd->objidlng = 4;
2081
      memcpy (mhd->objid, "V1.0", 4);
2082
      bfd_putl32 (modules[i].ref, mhd->refcnt);
2083
      /* FIXME: datim.  */
2084
 
2085
      sz += tdata->mhd_size;
2086
      sz = (sz + 1) & ~1;
2087
 
2088
      /* Rewind the member to be put into the archive.  */
2089
      if (bfd_seek (current, 0, SEEK_SET) != 0)
2090
        goto input_err;
2091
 
2092
      /* Copy the member into the archive.  */
2093
      if (is_elfidx)
2094
        {
2095
          unsigned int modsize = 0;
2096
          bfd_size_type amt;
2097
          file_ptr off_hdr = off;
2098
 
2099
          /* Read to complete the first block.  */
2100
          amt = bfd_bread (blk + sz, VMS_BLOCK_SIZE - sz, current);
2101
          if (amt == (bfd_size_type)-1)
2102
            goto input_err;
2103
          modsize = amt;
2104
          if (amt < VMS_BLOCK_SIZE - sz)
2105
            {
2106
              /* The member size is less than a block.  Pad the block.  */
2107
              memset (blk + sz + amt, 0, VMS_BLOCK_SIZE - sz - amt);
2108
            }
2109
          bfd_putl32 (modsize, mhd->modsize);
2110
 
2111
          /* Write the first block (which contains an mhd).  */
2112
          if (bfd_bwrite (blk, VMS_BLOCK_SIZE, arch) != VMS_BLOCK_SIZE)
2113
            goto input_err;
2114
          off += VMS_BLOCK_SIZE;
2115
 
2116
          if (amt == VMS_BLOCK_SIZE - sz)
2117
            {
2118
              /* Copy the remaining.  */
2119
              char buffer[DEFAULT_BUFFERSIZE];
2120
 
2121
              while (1)
2122
                {
2123
                  amt = bfd_bread (buffer, sizeof (buffer), current);
2124
                  if (amt == (bfd_size_type)-1)
2125
                    goto input_err;
2126
                  if (amt == 0)
2127
                    break;
2128
                  modsize += amt;
2129
                  if (amt != sizeof (buffer))
2130
                    {
2131
                      /* Clear the padding.  */
2132
                      memset (buffer + amt, 0, sizeof (buffer) - amt);
2133
                      amt = (amt + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1);
2134
                    }
2135
                  if (bfd_bwrite (buffer, amt, arch) != amt)
2136
                    goto input_err;
2137
                  off += amt;
2138
                }
2139
 
2140
              /* Now that the size is known, write the first block (again).  */
2141
              bfd_putl32 (modsize, mhd->modsize);
2142
              if (bfd_seek (arch, off_hdr, SEEK_SET) != 0
2143
                  || bfd_bwrite (blk, VMS_BLOCK_SIZE, arch) != VMS_BLOCK_SIZE)
2144
                goto input_err;
2145
              if (bfd_seek (arch, off, SEEK_SET) != 0)
2146
                goto input_err;
2147
            }
2148
        }
2149
      else
2150
        {
2151
          /* Write the MHD.  */
2152
          if (vms_write_data_block (arch, &data, &off, blk, sz, 0) < 0)
2153
            goto input_err;
2154
 
2155
          /* Write the member.  */
2156
          while (1)
2157
            {
2158
              sz = bfd_bread (blk, sizeof (blk), current);
2159
              if (sz == 0)
2160
                break;
2161
              if (vms_write_data_block (arch, &data, &off, blk, sz, 0) < 0)
2162
                goto input_err;
2163
            }
2164
 
2165
          /* Write the end of module marker.  */
2166
          if (vms_write_data_block (arch, &data, &off,
2167
                                    eotdesc, sizeof (eotdesc), 1) < 0)
2168
            goto input_err;
2169
        }
2170
    }
2171
 
2172
  /* Write the indexes.  */
2173
  vbn = 2;
2174
  if (vms_write_index (arch, modules, nbr_modules, &vbn, &mod_idx_vbn,
2175
                       is_elfidx) != TRUE)
2176
    return FALSE;
2177
  if (vms_write_index (arch, symbols, nbr_symbols, &vbn, &sym_idx_vbn,
2178
                       is_elfidx) != TRUE)
2179
    return FALSE;
2180
 
2181
  /* Write libary header.  */
2182
  {
2183
    unsigned char blk[VMS_BLOCK_SIZE];
2184
    struct vms_lhd *lhd = (struct vms_lhd *)blk;
2185
    struct vms_idd *idd = (struct vms_idd *)(blk + sizeof (*lhd));
2186
    unsigned int idd_flags;
2187
    unsigned int saneid;
2188
 
2189
    memset (blk, 0, sizeof (blk));
2190
 
2191
    lhd->type = tdata->type;
2192
    lhd->nindex = 2;
2193
    switch (tdata->kind)
2194
      {
2195
      case vms_lib_alpha:
2196
        saneid = LHD_SANEID3;
2197
        break;
2198
      case vms_lib_ia64:
2199
        saneid = LHD_SANEID6;
2200
        break;
2201
      default:
2202
        abort ();
2203
      }
2204
    bfd_putl32 (saneid, lhd->sanity);
2205
    bfd_putl16 (tdata->ver, lhd->majorid);
2206
    bfd_putl16 (0, lhd->minorid);
2207
    snprintf ((char *)lhd->lbrver + 1, sizeof (lhd->lbrver) - 1,
2208
              "GNU ar %u.%u.%u",
2209
              (unsigned)(BFD_VERSION / 100000000UL),
2210
              (unsigned)(BFD_VERSION / 1000000UL) % 100,
2211
              (unsigned)(BFD_VERSION / 10000UL) % 100);
2212
    lhd->lbrver[sizeof (lhd->lbrver) - 1] = 0;
2213
    lhd->lbrver[0] = strlen ((char *)lhd->lbrver + 1);
2214
 
2215
    bfd_putl32 (tdata->credat_lo, lhd->credat + 0);
2216
    bfd_putl32 (tdata->credat_hi, lhd->credat + 4);
2217
    vms_raw_get_time (lhd->updtim);
2218
 
2219
    lhd->mhdusz = tdata->mhd_size - MHD__C_USRDAT;
2220
 
2221
    bfd_putl32 (nbr_modules + nbr_symbols, lhd->idxcnt);
2222
    bfd_putl32 (nbr_modules, lhd->modcnt);
2223
    bfd_putl32 (nbr_modules, lhd->modhdrs);
2224
 
2225
    bfd_putl32 (vbn - 1, lhd->hipreal);
2226
    bfd_putl32 (vbn - 1, lhd->hiprusd);
2227
 
2228
    /* First index (modules name).  */
2229
    idd_flags = IDD__FLAGS_ASCII | IDD__FLAGS_VARLENIDX
2230
      | IDD__FLAGS_NOCASECMP | IDD__FLAGS_NOCASENTR;
2231
    bfd_putl16 (idd_flags, idd->flags);
2232
    bfd_putl16 (MAX_KEYLEN, idd->keylen);
2233
    bfd_putl16 (mod_idx_vbn, idd->vbn);
2234
    idd++;
2235
 
2236
    /* Second index (symbols name).  */
2237
    bfd_putl16 (idd_flags, idd->flags);
2238
    bfd_putl16 (MAX_KEYLEN, idd->keylen);
2239
    bfd_putl16 (sym_idx_vbn, idd->vbn);
2240
    idd++;
2241
 
2242
    if (vms_write_block (arch, 1, blk) != TRUE)
2243
      return FALSE;
2244
  }
2245
 
2246
  return TRUE;
2247
 
2248
 input_err:
2249
  bfd_set_error (bfd_error_on_input, current, bfd_get_error ());
2250
  return FALSE;
2251
}
2252
 
2253
/* Add a target for text library.  This costs almost nothing and is useful to
2254
   read VMS library on the host.  */
2255
 
2256
const bfd_target vms_lib_txt_vec =
2257
{
2258
  "vms-libtxt",                 /* Name.  */
2259
  bfd_target_unknown_flavour,
2260
  BFD_ENDIAN_UNKNOWN,           /* byteorder */
2261
  BFD_ENDIAN_UNKNOWN,           /* header_byteorder */
2262
  0,                             /* Object flags.  */
2263
  0,                             /* Sect flags.  */
2264
  0,                             /* symbol_leading_char.  */
2265
  ' ',                          /* ar_pad_char.  */
2266
  15,                           /* ar_max_namelen.  */
2267
  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
2268
  bfd_getl32, bfd_getl_signed_32, bfd_putl32,
2269
  bfd_getl16, bfd_getl_signed_16, bfd_putl16,
2270
  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
2271
  bfd_getl32, bfd_getl_signed_32, bfd_putl32,
2272
  bfd_getl16, bfd_getl_signed_16, bfd_putl16,
2273
 
2274
  {_bfd_dummy_target, _bfd_dummy_target,        /* bfd_check_format.  */
2275
   _bfd_vms_lib_txt_archive_p, _bfd_dummy_target},
2276
  {bfd_false, bfd_false, bfd_false, bfd_false}, /* bfd_set_format.  */
2277
  {bfd_false, bfd_false, bfd_false, bfd_false}, /* bfd_write_contents.  */
2278
 
2279
  BFD_JUMP_TABLE_GENERIC (_bfd_generic),
2280
  BFD_JUMP_TABLE_COPY (_bfd_generic),
2281
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
2282
  BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib),
2283
  BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
2284
  BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
2285
  BFD_JUMP_TABLE_WRITE (_bfd_nowrite),
2286
  BFD_JUMP_TABLE_LINK (_bfd_nolink),
2287
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
2288
 
2289
  NULL,
2290
 
2291
  (PTR) 0
2292
};

powered by: WebSVN 2.1.0

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