X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fvms-lib.c;h=8aa0e9a7f4009f5836df35095dc60d3f69468095;hb=95830fd17d6ae253d8f6c2595188cadd59058799;hp=6ab78eab6138bba5f1cda983b5b67f3d32509ec2;hpb=dd7f9124e97e5a72beba9b34a7ff5e384b9c159d;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/vms-lib.c b/bfd/vms-lib.c index 6ab78eab61..8aa0e9a7f4 100644 --- a/bfd/vms-lib.c +++ b/bfd/vms-lib.c @@ -1,6 +1,6 @@ /* BFD back-end for VMS archive files. - Copyright 2010 Free Software Foundation, Inc. + Copyright 2010, 2011, 2012 Free Software Foundation, Inc. Written by Tristan Gingold , AdaCore. This file is part of BFD, the Binary File Descriptor library. @@ -35,7 +35,8 @@ #endif /* Maximum key length (which is also the maximum symbol length in archive). */ -#define MAX_KEYLEN 129 +#define MAX_KEYLEN 128 +#define MAX_EKEYLEN 1024 /* DCX Submaps. */ @@ -277,6 +278,9 @@ vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym_mem *cs) if (idx_vbn == 0) return FALSE; + /* Point to the next index entry. */ + p = keyname + keylen; + if (idx_off == RFADEF__C_INDEX) { /* Indirect entry. Recurse. */ @@ -368,9 +372,6 @@ vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym_mem *cs) return FALSE; } } - - /* Point to the next index entry. */ - p = keyname + keylen; } return TRUE; @@ -629,7 +630,7 @@ _bfd_vms_lib_archive_p (bfd *abfd, enum vms_lib_kind kind) err: bfd_release (abfd, tdata); - abfd->tdata.any = (void *)tdata_hold;; + abfd->tdata.any = (void *)tdata_hold; return NULL; } @@ -1173,11 +1174,11 @@ vms_lib_bwrite (struct bfd *abfd ATTRIBUTE_UNUSED, return -1; } -static int +static bfd_boolean vms_lib_bclose (struct bfd *abfd) { abfd->iostream = NULL; - return 0; + return TRUE; } static int @@ -1196,11 +1197,13 @@ vms_lib_bstat (struct bfd *abfd ATTRIBUTE_UNUSED, static void * vms_lib_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED, - void *addr ATTRIBUTE_UNUSED, - bfd_size_type len ATTRIBUTE_UNUSED, - int prot ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, - file_ptr offset ATTRIBUTE_UNUSED) + void *addr ATTRIBUTE_UNUSED, + bfd_size_type len ATTRIBUTE_UNUSED, + int prot ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + file_ptr offset ATTRIBUTE_UNUSED, + void **map_addr ATTRIBUTE_UNUSED, + bfd_size_type *map_len ATTRIBUTE_UNUSED) { return (void *) -1; } @@ -1293,6 +1296,7 @@ _bfd_vms_lib_get_module (bfd *abfd, unsigned int modidx) struct lib_tdata *tdata = bfd_libdata (abfd); bfd *res; file_ptr file_off; + char *name; /* Sanity check. */ if (modidx >= tdata->nbr_modules) @@ -1333,7 +1337,7 @@ _bfd_vms_lib_get_module (bfd *abfd, unsigned int modidx) res = _bfd_create_empty_archive_element_shell (abfd); if (res == NULL) return NULL; - arelt = bfd_zalloc (res, sizeof (*arelt)); + arelt = bfd_zmalloc (sizeof (*arelt)); if (arelt == NULL) return NULL; res->arelt_data = arelt; @@ -1354,7 +1358,25 @@ _bfd_vms_lib_get_module (bfd *abfd, unsigned int modidx) res->origin = file_off + tdata->mhd_size; } - res->filename = tdata->modules[modidx].name; + /* Set filename. */ + name = tdata->modules[modidx].name; + switch (tdata->type) + { + case LBR__C_TYP_IOBJ: + case LBR__C_TYP_EOBJ: + /* For object archives, append .obj to mimic standard behaviour. */ + { + size_t namelen = strlen (name); + char *name1 = bfd_alloc (res, namelen + 4 + 1); + memcpy (name1, name, namelen); + strcpy (name1 + namelen, ".obj"); + name = name1; + } + break; + default: + break; + } + res->filename = name; tdata->cache[modidx] = res; @@ -1540,17 +1562,24 @@ get_idxlen (struct lib_index *idx, bfd_boolean is_elfidx) { if (is_elfidx) { + /* 9 is the size of struct vms_elfidx without keyname. */ if (idx->namlen > MAX_KEYLEN) - return 9 + sizeof (struct vms_rfa); + return 9 + sizeof (struct vms_kbn); else return 9 + idx->namlen; } else - return 7 + idx->namlen; + { + /* 7 is the size of struct vms_idx without keyname. */ + return 7 + idx->namlen; + } } -/* Write the index. VBN is the first vbn to be used, and will contain - on return the last vbn. +/* Write the index composed by NBR symbols contained in IDX. + VBN is the first vbn to be used, and will contain on return the last vbn. + Can be called with ABFD set to NULL just to size the index. + If not null, TOPVBN will be assigned to the vbn of the root index tree. + IS_ELFIDX is true for elfidx (ie ia64) indexes layout. Return TRUE on success. */ static bfd_boolean @@ -1558,20 +1587,28 @@ vms_write_index (bfd *abfd, struct lib_index *idx, unsigned int nbr, unsigned int *vbn, unsigned int *topvbn, bfd_boolean is_elfidx) { + /* The index is organized as a tree. This function implements a naive + algorithm to balance the tree: it fills the leaves, and create a new + branch when all upper leaves and branches are full. We only keep in + memory a path to the current leaf. */ unsigned int i; int j; int level; + /* Disk blocks for the current path. */ struct vms_indexdef *rblk[MAX_LEVEL]; + /* Info on the current blocks. */ struct idxblk { - unsigned int vbn; - unsigned short len; - unsigned short lastlen; + unsigned int vbn; /* VBN of the block. */ + /* The last entry is identified so that it could be copied to the + parent block. */ + unsigned short len; /* Length up to the last entry. */ + unsigned short lastlen; /* Length of the last entry. */ } blk[MAX_LEVEL]; /* The kbn blocks are used to store long symbol names. */ - unsigned int kbn_sz = 0; /* Number of bytes availble in the kbn block. */ - unsigned int kbn_vbn = 0; /* VBN of the kbn block. */ + unsigned int kbn_sz = 0; /* Number of bytes available in the kbn block. */ + unsigned int kbn_vbn = 0; /* VBN of the kbn block. */ unsigned char *kbn_blk = NULL; /* Contents of the kbn block. */ if (nbr == 0) @@ -1605,14 +1642,14 @@ vms_write_index (bfd *abfd, idxlen = get_idxlen (idx, is_elfidx); - if (is_elfidx && idx->namlen >= MAX_KEYLEN) + if (is_elfidx && idx->namlen > MAX_KEYLEN) { - /* If the name is too long, write it in the kbn block. */ + /* If the key (ie name) is too long, write it in the kbn block. */ unsigned int kl = idx->namlen; unsigned int kl_chunk; const char *key = idx->name; - /* Write the name in the kbn, chunk after chunk. */ + /* Write the key in the kbn, chunk after chunk. */ do { if (kbn_sz < sizeof (struct vms_kbn)) @@ -1634,9 +1671,11 @@ vms_write_index (bfd *abfd, } *(unsigned short *)kbn_blk = 0; } + /* Allocate a new block for the keys. */ kbn_vbn = (*vbn)++; kbn_sz = VMS_BLOCK_SIZE - 2; } + /* Size of the chunk written to the current key block. */ if (kl + sizeof (struct vms_kbn) > kbn_sz) kl_chunk = kbn_sz - sizeof (struct vms_kbn); else @@ -1682,7 +1721,7 @@ vms_write_index (bfd *abfd, block and all the blocks below it. */ for (j = 0; j < level; j++) if (blk[j].len + blk[j].lastlen + idxlen > INDEXDEF__BLKSIZ) - flush = j + 1; + flush = j + 1; for (j = 0; j < level; j++) { @@ -1703,23 +1742,25 @@ vms_write_index (bfd *abfd, } blk[level].vbn = (*vbn)++; blk[level].len = 0; - blk[level].lastlen = 0; + blk[level].lastlen = blk[j].lastlen; level++; } - /* Update parent block: write the new entry. */ + /* Update parent block: write the last entry from the current + block. */ if (abfd != NULL) { struct vms_rfa *rfa; + /* Pointer to the last entry in parent block. */ + rfa = (struct vms_rfa *)(rblk[j + 1]->keys + blk[j + 1].len); + /* Copy the whole entry. */ - memcpy (rblk[j + 1]->keys + blk[j + 1].len, - rblk[j]->keys + blk[j].len, - blk[j].lastlen); + BFD_ASSERT (blk[j + 1].lastlen == blk[j].lastlen); + memcpy (rfa, rblk[j]->keys + blk[j].len, blk[j].lastlen); /* Fix the entry (which in always the first field of an entry. */ - rfa = (struct vms_rfa *)(rblk[j + 1]->keys + blk[j + 1].len); bfd_putl32 (blk[j].vbn, rfa->vbn); bfd_putl16 (RFADEF__C_INDEX, rfa->offset); } @@ -1729,7 +1770,7 @@ vms_write_index (bfd *abfd, /* And allocate it. Do it only on the block that won't be flushed (so that the parent of the parent can be updated too). */ - blk[j + 1].len += blk[j].lastlen; + blk[j + 1].len += blk[j + 1].lastlen; blk[j + 1].lastlen = 0; } @@ -1750,6 +1791,7 @@ vms_write_index (bfd *abfd, /* Append it to the block. */ if (j == 0) { + /* Keep the previous last entry. */ blk[j].len += blk[j].lastlen; if (abfd != NULL) @@ -1794,12 +1836,14 @@ vms_write_index (bfd *abfd, memcpy (en->keyname, idx->name, idx->namlen); } } - } - - blk[j].lastlen = idxlen; + } + /* The last added key can now be the last one all blocks in the + path. */ + blk[j].lastlen = idxlen; } } + /* Save VBN of the root. */ if (topvbn != NULL) *topvbn = blk[level - 1].vbn; @@ -1807,23 +1851,24 @@ vms_write_index (bfd *abfd, return TRUE; /* Flush. */ - for (j = level - 1; j >= 0; j--) + for (j = 1; j < level; j++) { - if (j > 0) - { - /* Update parent block: write the new entry. */ - unsigned char *en; - unsigned char *par; - struct vms_rfa *rfa; - - en = rblk[j - 1]->keys + blk[j - 1].len; - par = rblk[j]->keys + blk[j].len; - memcpy (par, en, blk[j - 1].lastlen); - rfa = (struct vms_rfa *)par; - bfd_putl32 (blk[j - 1].vbn, rfa->vbn); - bfd_putl16 (RFADEF__C_INDEX, rfa->offset); - } + /* Update parent block: write the new entry. */ + unsigned char *en; + unsigned char *par; + struct vms_rfa *rfa; + + en = rblk[j - 1]->keys + blk[j - 1].len; + par = rblk[j]->keys + blk[j].len; + BFD_ASSERT (blk[j].lastlen == blk[j - 1].lastlen); + memcpy (par, en, blk[j - 1].lastlen); + rfa = (struct vms_rfa *)par; + bfd_putl32 (blk[j - 1].vbn, rfa->vbn); + bfd_putl16 (RFADEF__C_INDEX, rfa->offset); + } + for (j = 0; j < level; j++) + { /* Write this block on the disk. */ bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used); if (vms_write_block (abfd, blk[j].vbn, rblk[j]) != TRUE) @@ -1832,10 +1877,12 @@ vms_write_index (bfd *abfd, free (rblk[j]); } + /* Write the last kbn (if any). */ if (kbn_vbn != 0) { if (vms_write_block (abfd, kbn_vbn, kbn_blk) != TRUE) return FALSE; + free (kbn_blk); } return TRUE; @@ -1994,6 +2041,7 @@ _bfd_vms_lib_write_archive_contents (bfd *arch) unsigned int mod_idx_vbn; unsigned int sym_idx_vbn; bfd_boolean is_elfidx = tdata->kind == vms_lib_ia64; + unsigned int max_keylen = is_elfidx ? MAX_EKEYLEN : MAX_KEYLEN; /* Count the number of modules (and do a first sanity check). */ nbr_modules = 0; @@ -2025,7 +2073,7 @@ _bfd_vms_lib_write_archive_contents (bfd *arch) current != NULL; current = current->archive_next, i++) { - int nl; + unsigned int nl; modules[i].abfd = current; modules[i].name = vms_get_module_name (current->filename, FALSE); @@ -2033,7 +2081,7 @@ _bfd_vms_lib_write_archive_contents (bfd *arch) /* FIXME: silently truncate long names ? */ nl = strlen (modules[i].name); - modules[i].namlen = (nl > MAX_KEYLEN ? MAX_KEYLEN : nl); + modules[i].namlen = (nl > max_keylen ? max_keylen : nl); } /* Create the module index. */ @@ -2224,20 +2272,27 @@ _bfd_vms_lib_write_archive_contents (bfd *arch) bfd_putl32 (nbr_modules, lhd->modcnt); bfd_putl32 (nbr_modules, lhd->modhdrs); + /* Number of blocks for index. */ + bfd_putl32 (nbr_mod_iblk + nbr_sym_iblk, lhd->idxblks); bfd_putl32 (vbn - 1, lhd->hipreal); bfd_putl32 (vbn - 1, lhd->hiprusd); + /* VBN of the next free block. */ + bfd_putl32 ((off / VMS_BLOCK_SIZE) + 1, lhd->nextvbn); + bfd_putl32 ((off / VMS_BLOCK_SIZE) + 1, lhd->nextrfa + 0); + bfd_putl16 (0, lhd->nextrfa + 4); + /* First index (modules name). */ idd_flags = IDD__FLAGS_ASCII | IDD__FLAGS_VARLENIDX | IDD__FLAGS_NOCASECMP | IDD__FLAGS_NOCASENTR; bfd_putl16 (idd_flags, idd->flags); - bfd_putl16 (MAX_KEYLEN, idd->keylen); + bfd_putl16 (max_keylen + 1, idd->keylen); bfd_putl16 (mod_idx_vbn, idd->vbn); idd++; /* Second index (symbols name). */ bfd_putl16 (idd_flags, idd->flags); - bfd_putl16 (MAX_KEYLEN, idd->keylen); + bfd_putl16 (max_keylen + 1, idd->keylen); bfd_putl16 (sym_idx_vbn, idd->vbn); idd++; @@ -2266,6 +2321,7 @@ const bfd_target vms_lib_txt_vec = 0, /* symbol_leading_char. */ ' ', /* ar_pad_char. */ 15, /* ar_max_namelen. */ + 0, /* match priority. */ bfd_getl64, bfd_getl_signed_64, bfd_putl64, bfd_getl32, bfd_getl_signed_32, bfd_putl32, bfd_getl16, bfd_getl_signed_16, bfd_putl16, @@ -2290,5 +2346,5 @@ const bfd_target vms_lib_txt_vec = NULL, - (PTR) 0 + NULL };