2012-04-17 Tristan Gingold <gingold@adacore.com>
authorTristan Gingold <gingold@adacore.com>
Tue, 17 Apr 2012 10:28:19 +0000 (10:28 +0000)
committerTristan Gingold <gingold@adacore.com>
Tue, 17 Apr 2012 10:28:19 +0000 (10:28 +0000)
* vms-lib.c (MAX_EKEYLEN): Define.
(MAX_KEYLEN): Fix value.
(vms_write_index): Add comments and fix indentation.
Adjust comparaison.  Add assertions.  Free kbn_blk.
(_bfd_vms_lib_write_archive_contents): Use MAX_EKEYLEN.
Compense MAX_KEYLEN adjustment.

bfd/ChangeLog
bfd/vms-lib.c

index 32e6601..da0ebee 100644 (file)
@@ -1,3 +1,12 @@
+2012-04-17  Tristan Gingold  <gingold@adacore.com>
+
+       * vms-lib.c (MAX_EKEYLEN): Define.
+       (MAX_KEYLEN): Fix value.
+       (vms_write_index): Add comments and fix indentation.
+       Adjust comparaison.  Add assertions.  Free kbn_blk.
+       (_bfd_vms_lib_write_archive_contents): Use MAX_EKEYLEN.
+       Compense MAX_KEYLEN adjustment.
+
 2012-04-16  Maciej W. Rozycki  <macro@linux-mips.org>
 
        * elfxx-mips.c (mips16_stub_symndx): Handle n64 compound relocs.
index cc62d11..7869695 100644 (file)
@@ -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.  */
 
@@ -1567,15 +1568,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 +1623,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 +1702,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 +1723,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 +1751,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 +1772,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 +1817,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 +1841,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 +1863,7 @@ vms_write_index (bfd *abfd,
     {
       if (vms_write_block (abfd, kbn_vbn, kbn_blk) != TRUE)
         return FALSE;
+      free (kbn_blk);
     }
 
   return TRUE;
@@ -2006,7 +2022,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 ? 1025 : MAX_KEYLEN;
+  unsigned int max_keylen = is_elfidx ? MAX_EKEYLEN : MAX_KEYLEN;
 
   /* Count the number of modules (and do a first sanity check).  */
   nbr_modules = 0;
@@ -2251,13 +2267,13 @@ _bfd_vms_lib_write_archive_contents (bfd *arch)
     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++;