Index: bfd/vms-lib.c |
diff --git a/bfd/vms-lib.c b/bfd/vms-lib.c |
index b325d7411bb8816d30cf7e4bdef424c48e49ff82..fa23b788e2509f6caa7303ccd34bba80fdfe436a 100644 |
--- a/bfd/vms-lib.c |
+++ b/bfd/vms-lib.c |
@@ -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; |
@@ -1295,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) |
@@ -1356,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; |
@@ -1567,15 +1587,23 @@ 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. */ |
@@ -1614,7 +1642,7 @@ 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 key (ie name) is too long, write it in the kbn block. */ |
unsigned int kl = idx->namlen; |
@@ -1693,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++) |
{ |
@@ -1714,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); |
} |
@@ -1740,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; |
} |
@@ -1761,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) |
@@ -1805,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; |
@@ -1827,6 +1860,7 @@ vms_write_index (bfd *abfd, |
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); |
@@ -1848,6 +1882,7 @@ vms_write_index (bfd *abfd, |
{ |
if (vms_write_block (abfd, kbn_vbn, kbn_blk) != TRUE) |
return FALSE; |
+ free (kbn_blk); |
} |
return TRUE; |
@@ -2006,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; |
@@ -2037,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); |
@@ -2045,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. */ |
@@ -2236,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++; |
@@ -2303,5 +2346,5 @@ const bfd_target vms_lib_txt_vec = |
NULL, |
- (PTR) 0 |
+ NULL |
}; |