tui: Simplify tui_alloc_content
[deliverable/binutils-gdb.git] / gdb / ada-lang.c
index 6947d76f819a5104e545d490750d7c1f91e90adc..fff48623b180c8275f78054210452e47230a7644 100644 (file)
@@ -2383,9 +2383,12 @@ has_negatives (struct type *type)
 }
 
 /* With SRC being a buffer containing BIT_SIZE bits of data at BIT_OFFSET,
-   unpack that data into UNPACKED. UNPACKED_LEN is the size in bytes of
+   unpack that data into UNPACKED.  UNPACKED_LEN is the size in bytes of
    the unpacked buffer.
 
+   The size of the unpacked buffer (UNPACKED_LEN) is expected to be large
+   enough to contain at least BIT_OFFSET bits.  If not, an error is raised.
+
    IS_BIG_ENDIAN is nonzero if the data is stored in big endian mode,
    zero otherwise.
 
@@ -2417,6 +2420,12 @@ ada_unpack_from_contents (const gdb_byte *src, int bit_offset, int bit_size,
      the indices move.  */
   int delta = is_big_endian ? -1 : 1;
 
+  /* Make sure that unpacked is large enough to receive the BIT_SIZE
+     bits from SRC.  .*/
+  if ((bit_size + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT > unpacked_len)
+    error (_("Cannot unpack %d bits into buffer of %d bytes"),
+          bit_size, unpacked_len);
+
   srcBitsLeft = bit_size;
   src_bytes_left = src_len;
   unpacked_bytes_left = unpacked_len;
@@ -2516,40 +2525,71 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr,
                                 struct type *type)
 {
   struct value *v;
-  gdb_byte *src;                /* First byte containing data to unpack */
-  int src_len = (bit_size + bit_offset + HOST_CHAR_BIT - 1) / 8;
+  const gdb_byte *src;                /* First byte containing data to unpack */
   gdb_byte *unpacked;
-  int is_scalar;
+  const int is_scalar = is_scalar_type (type);
+  const int is_big_endian = gdbarch_bits_big_endian (get_type_arch (type));
+  gdb_byte *staging = NULL;
+  int staging_len = 0;
+  struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
 
   type = ada_check_typedef (type);
 
+  if (obj == NULL)
+    src = valaddr + offset;
+  else
+    src = value_contents (obj) + offset;
+
+  if (is_dynamic_type (type))
+    {
+      /* The length of TYPE might by dynamic, so we need to resolve
+        TYPE in order to know its actual size, which we then use
+        to create the contents buffer of the value we return.
+        The difficulty is that the data containing our object is
+        packed, and therefore maybe not at a byte boundary.  So, what
+        we do, is unpack the data into a byte-aligned buffer, and then
+        use that buffer as our object's value for resolving the type.  */
+      staging_len = (bit_size + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
+      staging = (gdb_byte *) malloc (staging_len);
+      make_cleanup (xfree, staging);
+
+      ada_unpack_from_contents (src, bit_offset, bit_size,
+                               staging, staging_len,
+                               is_big_endian, has_negatives (type),
+                               is_scalar);
+      type = resolve_dynamic_type (type, staging, 0);
+      if (TYPE_LENGTH (type) < (bit_size + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT)
+       {
+         /* This happens when the length of the object is dynamic,
+            and is actually smaller than the space reserved for it.
+            For instance, in an array of variant records, the bit_size
+            we're given is the array stride, which is constant and
+            normally equal to the maximum size of its element.
+            But, in reality, each element only actually spans a portion
+            of that stride.  */
+         bit_size = TYPE_LENGTH (type) * HOST_CHAR_BIT;
+       }
+    }
+
   if (obj == NULL)
     {
       v = allocate_value (type);
-      src = (gdb_byte *) valaddr + offset;
+      src = valaddr + offset;
     }
   else if (VALUE_LVAL (obj) == lval_memory && value_lazy (obj))
     {
+      int src_len = (bit_size + bit_offset + HOST_CHAR_BIT - 1) / 8;
+      gdb_byte *buf;
+
       v = value_at (type, value_address (obj) + offset);
-      type = value_type (v);
-      if (TYPE_LENGTH (type) * HOST_CHAR_BIT < bit_size)
-       {
-         /* This can happen in the case of an array of dynamic objects,
-            where the size of each element changes from element to element.
-            In that case, we're initially given the array stride, but
-            after resolving the element type, we find that its size is
-            less than this stride.  In that case, adjust bit_size to
-            match TYPE's length, and recompute LEN accordingly.  */
-         bit_size = TYPE_LENGTH (type) * HOST_CHAR_BIT;
-         src_len = TYPE_LENGTH (type) + (bit_offset + HOST_CHAR_BIT - 1) / 8;
-       }
-      src = alloca (src_len);
-      read_memory (value_address (v), src, src_len);
+      buf = (gdb_byte *) alloca (src_len);
+      read_memory (value_address (v), buf, src_len);
+      src = buf;
     }
   else
     {
       v = allocate_value (type);
-      src = (gdb_byte *) value_contents (obj) + offset;
+      src = value_contents (obj) + offset;
     }
 
   if (obj != NULL)
@@ -2572,34 +2612,28 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr,
     }
   else
     set_value_bitsize (v, bit_size);
-  unpacked = (gdb_byte *) value_contents (v);
+  unpacked = value_contents_writeable (v);
 
   if (bit_size == 0)
     {
       memset (unpacked, 0, TYPE_LENGTH (type));
+      do_cleanups (old_chain);
       return v;
     }
 
-  switch (TYPE_CODE (type))
+  if (staging != NULL && staging_len == TYPE_LENGTH (type))
     {
-    case TYPE_CODE_ARRAY:
-    case TYPE_CODE_UNION:
-    case TYPE_CODE_STRUCT:
-      is_scalar = 0;
-      break;
-    default:
-      is_scalar = 1;
-      break;
+      /* Small short-cut: If we've unpacked the data into a buffer
+        of the same size as TYPE's length, then we can reuse that,
+        instead of doing the unpacking again.  */
+      memcpy (unpacked, staging, staging_len);
     }
+  else
+    ada_unpack_from_contents (src, bit_offset, bit_size,
+                             unpacked, TYPE_LENGTH (type),
+                             is_big_endian, has_negatives (type), is_scalar);
 
-  ada_unpack_from_contents (src, bit_offset, bit_size,
-                           unpacked, TYPE_LENGTH (type),
-                           gdbarch_bits_big_endian (get_type_arch (type)),
-                           has_negatives (type), is_scalar);
-
-  if (is_dynamic_type (value_type (v)))
-    v = value_from_contents_and_address (value_type (v), value_contents (v),
-                                        0);
+  do_cleanups (old_chain);
   return v;
 }
 
@@ -9396,7 +9430,7 @@ ada_enum_name (const char *name)
 {
   static char *result;
   static size_t result_len = 0;
-  char *tmp;
+  const char *tmp;
 
   /* First, unqualify the enumeration name:
      1. Search for the last '.' character.  If we find one, then skip
This page took 0.029273 seconds and 4 git commands to generate.