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