bfd/
authorTristan Gingold <gingold@adacore.com>
Fri, 30 Apr 2010 12:44:51 +0000 (12:44 +0000)
committerTristan Gingold <gingold@adacore.com>
Fri, 30 Apr 2010 12:44:51 +0000 (12:44 +0000)
2010-04-30  Tristan Gingold  <gingold@adacore.com>

* vms-lib.c (vms_read_block): New function.
(vms_traverse_index): Use vms_read_block.  Handle long key names.

include/vms/
2010-04-30  Tristan Gingold  <gingold@adacore.com>

* lbr.h (struct vms_kbn): New structure.

bfd/ChangeLog
bfd/vms-lib.c
include/vms/ChangeLog
include/vms/lbr.h

index a66fc32aefcbafe18456508eb6d63ffed498446c..e3a1e53f7acbcfe57a6779c8bc0ed5c68a0ac439 100644 (file)
@@ -1,3 +1,8 @@
+2010-04-30  Tristan Gingold  <gingold@adacore.com>
+
+       * vms-lib.c (vms_read_block): New function.
+       (vms_traverse_index): Use vms_read_block.  Handle long key names.
+
 2010-04-30  Tristan Gingold  <gingold@adacore.com>
 
        * vms-lib.c (struct lib_tdata): Field artdata added, fields nbr_syms
index fcfdf0fd932a325d127823ae21194245a57ec823..bd5ecb79a4cf246ec222c5f95010ebc826d86118 100644 (file)
@@ -186,6 +186,22 @@ vms_add_indexes_from_list (bfd *abfd, struct carsym_mem *cs, char *name,
     }
 }
 
+/* Read block VBN from ABFD and store it into BLK.  */
+
+static bfd_boolean
+vms_read_block (bfd *abfd, unsigned int vbn, void *blk)
+{
+  file_ptr off;
+
+  /* Read the index block.  */
+  off = (vbn - 1) * VMS_BLOCK_SIZE;
+  if (bfd_seek (abfd, off, SEEK_SET) != 0
+      || bfd_bread (blk, VMS_BLOCK_SIZE, abfd) != VMS_BLOCK_SIZE)
+    return FALSE;
+
+  return TRUE;
+}
+
 /* Read index block VBN and put the entry in **IDX (which is updated).
    If the entry is indirect, recurse.  */
 
@@ -198,9 +214,8 @@ vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym_mem *cs)
   unsigned char *endp;
 
   /* Read the index block.  */
-  off = (vbn - 1) * VMS_BLOCK_SIZE;
-  if (bfd_seek (abfd, off, SEEK_SET) != 0
-      || bfd_bread (&indexdef, sizeof (indexdef), abfd) != sizeof (indexdef))
+  BFD_ASSERT (sizeof (indexdef) == VMS_BLOCK_SIZE);
+  if (!vms_read_block (abfd, vbn, &indexdef))
     return FALSE;
 
   /* Traverse it.  */
@@ -244,10 +259,6 @@ vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym_mem *cs)
       if (idx_vbn == 0)
         return FALSE;
 
-      /* Long symbol names are not yet supported.  */
-      if (flags & ELFIDX__SYMESC)
-        return FALSE;
-
       if (idx_off == RFADEF__C_INDEX)
         {
           /* Indirect entry.  Recurse.  */
@@ -259,10 +270,58 @@ vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym_mem *cs)
           /* Add a new entry.  */
           char *name;
 
-          name = bfd_alloc (abfd, keylen + 1);
-          if (name == NULL)
-            return FALSE;
-          memcpy (name, keyname, keylen);
+          if (flags & ELFIDX__SYMESC)
+            {
+              /* Extended key name.  */
+              unsigned int noff = 0;
+              unsigned int koff;
+              unsigned int kvbn;
+              struct vms_kbn *kbn;
+              unsigned char kblk[VMS_BLOCK_SIZE];
+
+              /* Sanity check.  */
+              if (keylen != sizeof (struct vms_kbn))
+                return FALSE;
+
+              kbn = (struct vms_kbn *)keyname;
+              keylen = bfd_getl16 (kbn->keylen);
+
+              name = bfd_alloc (abfd, keylen + 1);
+              if (name == NULL)
+                return FALSE;
+              kvbn = bfd_getl32 (kbn->rfa.vbn);
+              koff = bfd_getl16 (kbn->rfa.offset);
+
+              /* Read the key, chunk by chunk.  */
+              do
+                {
+                  unsigned int klen;
+
+                  if (!vms_read_block (abfd, kvbn, kblk))
+                    return FALSE;
+                  kbn = (struct vms_kbn *)(kblk + koff);
+                  klen = bfd_getl16 (kbn->keylen);
+                  kvbn = bfd_getl32 (kbn->rfa.vbn);
+                  koff = bfd_getl16 (kbn->rfa.offset);
+
+                  memcpy (name + noff, kbn + 1, klen);
+                  noff += klen;
+                }
+              while (kvbn != 0);
+
+              /* Sanity check.  */
+              if (noff != keylen)
+                return FALSE;
+            }
+          else
+            {
+              /* Usual key name.  */
+              name = bfd_alloc (abfd, keylen + 1);
+              if (name == NULL)
+                return FALSE;
+
+              memcpy (name, keyname, keylen);
+            }
           name[keylen] = 0;
 
           if (flags & ELFIDX__LISTRFA)
index b7114d3cf6e9e09bbc114802bb56a91edc697e02..823520f220be48f1b22eb5e9a32ff8ec7585927c 100644 (file)
@@ -1,3 +1,7 @@
+2010-04-30  Tristan Gingold  <gingold@adacore.com>
+
+       * lbr.h (struct vms_kbn): New structure.
+
 2010-04-30  Tristan Gingold  <gingold@adacore.com>
 
        * lbr.h (LBR__C_TYP_ISHSTB): Added.
index 7d6f597cb076f6a1a5359f55705ebc08d85ea50d..91186ee371feda3a25b0c39b41d47bba5e3af6d1 100644 (file)
@@ -255,6 +255,19 @@ struct vms_datadef
 #define DATA__LENGTH 512
 #define DATA__DATA 6
 
+/* Key name block.  This is used for keys longer than 128 bytes.  */
+
+struct vms_kbn
+{
+  /* Length of the key chunk.  */
+  unsigned char keylen[2];
+
+  /* RFA of the next chunk.  */
+  struct vms_rfa rfa;
+
+  /* Followed by the key chunk.  */
+};
+
 /* Module header.  */
 struct vms_mhd
 {
This page took 0.028126 seconds and 4 git commands to generate.