Coverage Report

Created: 2026-03-10 08:46

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