[BACK]Return to vms-lib.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils.old / dist / bfd

Annotation of src/external/gpl3/binutils.old/dist/bfd/vms-lib.c, Revision 1.1.1.2

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

CVSweb <webmaster@jp.NetBSD.org>