Add gdbarch callback to provide formats for debug info float types
[deliverable/binutils-gdb.git] / gdb / dwarf2loc.c
index ba6ed42447ef91ff9179297aacff4999b36ccf0a..946ddf8b6e94d8a4908d237ec8cf12ead2d8ff41 100644 (file)
@@ -255,9 +255,15 @@ dwarf2_find_location_expression (struct dwarf2_loclist_baton *baton,
        }
 
       /* Otherwise, a location expression entry.
-        If the entry is from a DWO, don't add base address: the entry is
-        from .debug_addr which has absolute addresses.  */
-      if (! baton->from_dwo)
+        If the entry is from a DWO, don't add base address: the entry is from
+        .debug_addr which already has the DWARF "base address".  We still add
+        base_offset in case we're debugging a PIE executable.  */
+      if (baton->from_dwo)
+       {
+         low += base_offset;
+         high += base_offset;
+       }
+      else
        {
          low += base_address;
          high += base_address;
@@ -1759,7 +1765,7 @@ read_pieced_value (struct value *v)
            struct gdbarch *arch = get_frame_arch (frame);
            int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, p->v.regno);
            int optim, unavail;
-           int reg_offset = source_offset;
+           LONGEST reg_offset = source_offset;
 
            if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
                && this_size < register_size (arch, gdb_regnum))
@@ -2010,7 +2016,7 @@ write_pieced_value (struct value *to, struct value *from)
    a synthetic pointer.  */
 
 static int
-check_pieced_synthetic_pointer (const struct value *value, int bit_offset,
+check_pieced_synthetic_pointer (const struct value *value, LONGEST bit_offset,
                                int bit_length)
 {
   struct piece_closure *c
@@ -2055,6 +2061,66 @@ get_frame_address_in_block_wrapper (void *baton)
   return get_frame_address_in_block ((struct frame_info *) baton);
 }
 
+/* Fetch a DW_AT_const_value through a synthetic pointer.  */
+
+static struct value *
+fetch_const_value_from_synthetic_pointer (sect_offset die, LONGEST byte_offset,
+                                         struct dwarf2_per_cu_data *per_cu,
+                                         struct type *type)
+{
+  struct value *result = NULL;
+  struct obstack temp_obstack;
+  struct cleanup *cleanup;
+  const gdb_byte *bytes;
+  LONGEST len;
+
+  obstack_init (&temp_obstack);
+  cleanup = make_cleanup_obstack_free (&temp_obstack);
+  bytes = dwarf2_fetch_constant_bytes (die, per_cu, &temp_obstack, &len);
+
+  if (bytes != NULL)
+    {
+      if (byte_offset >= 0
+         && byte_offset + TYPE_LENGTH (TYPE_TARGET_TYPE (type)) <= len)
+       {
+         bytes += byte_offset;
+         result = value_from_contents (TYPE_TARGET_TYPE (type), bytes);
+       }
+      else
+       invalid_synthetic_pointer ();
+    }
+  else
+    result = allocate_optimized_out_value (TYPE_TARGET_TYPE (type));
+
+  do_cleanups (cleanup);
+
+  return result;
+}
+
+/* Fetch the value pointed to by a synthetic pointer.  */
+
+static struct value *
+indirect_synthetic_pointer (sect_offset die, LONGEST byte_offset,
+                           struct dwarf2_per_cu_data *per_cu,
+                           struct frame_info *frame, struct type *type)
+{
+  /* Fetch the location expression of the DIE we're pointing to.  */
+  struct dwarf2_locexpr_baton baton
+    = dwarf2_fetch_die_loc_sect_off (die, per_cu,
+                                    get_frame_address_in_block_wrapper, frame);
+
+  /* If pointed-to DIE has a DW_AT_location, evaluate it and return the
+     resulting value.  Otherwise, it may have a DW_AT_const_value instead,
+     or it may've been optimized out.  */
+  if (baton.data != NULL)
+    return dwarf2_evaluate_loc_desc_full (TYPE_TARGET_TYPE (type), frame,
+                                         baton.data, baton.size, baton.per_cu,
+                                         byte_offset);
+  else
+    return fetch_const_value_from_synthetic_pointer (die, byte_offset, per_cu,
+                                                    type);
+}
+
 /* An implementation of an lval_funcs method to indirect through a
    pointer.  This handles the synthetic pointer case when needed.  */
 
@@ -2066,7 +2132,8 @@ indirect_pieced_value (struct value *value)
   struct type *type;
   struct frame_info *frame;
   struct dwarf2_locexpr_baton baton;
-  int i, bit_offset, bit_length;
+  int i, bit_length;
+  LONGEST bit_offset;
   struct dwarf_expr_piece *piece = NULL;
   LONGEST byte_offset;
   enum bfd_endian byte_order;
@@ -2109,6 +2176,7 @@ indirect_pieced_value (struct value *value)
       break;
     }
 
+  gdb_assert (piece != NULL);
   frame = get_selected_frame (_("No frame selected."));
 
   /* This is an offset requested by GDB, such as value subscripts.
@@ -2126,43 +2194,40 @@ indirect_pieced_value (struct value *value)
                                        TYPE_LENGTH (type), byte_order);
   byte_offset += piece->v.ptr.offset;
 
-  gdb_assert (piece);
-  baton
-    = dwarf2_fetch_die_loc_sect_off (piece->v.ptr.die, c->per_cu,
-                                    get_frame_address_in_block_wrapper,
-                                    frame);
+  return indirect_synthetic_pointer (piece->v.ptr.die, byte_offset, c->per_cu,
+                                    frame, type);
+}
 
-  if (baton.data != NULL)
-    return dwarf2_evaluate_loc_desc_full (TYPE_TARGET_TYPE (type), frame,
-                                         baton.data, baton.size, baton.per_cu,
-                                         byte_offset);
+/* Implementation of the coerce_ref method of lval_funcs for synthetic C++
+   references.  */
 
-  {
-    struct obstack temp_obstack;
-    struct cleanup *cleanup;
-    const gdb_byte *bytes;
-    LONGEST len;
-    struct value *result;
-
-    obstack_init (&temp_obstack);
-    cleanup = make_cleanup_obstack_free (&temp_obstack);
-
-    bytes = dwarf2_fetch_constant_bytes (piece->v.ptr.die, c->per_cu,
-                                        &temp_obstack, &len);
-    if (bytes == NULL)
-      result = allocate_optimized_out_value (TYPE_TARGET_TYPE (type));
-    else
-      {
-       if (byte_offset < 0
-           || byte_offset + TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > len)
-         invalid_synthetic_pointer ();
-       bytes += byte_offset;
-       result = value_from_contents (TYPE_TARGET_TYPE (type), bytes);
-      }
+static struct value *
+coerce_pieced_ref (const struct value *value)
+{
+  struct type *type = check_typedef (value_type (value));
 
-    do_cleanups (cleanup);
-    return result;
-  }
+  if (value_bits_synthetic_pointer (value, value_embedded_offset (value),
+                                   TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+    {
+      const struct piece_closure *closure
+       = (struct piece_closure *) value_computed_closure (value);
+      struct frame_info *frame
+       = get_selected_frame (_("No frame selected."));
+
+      /* gdb represents synthetic pointers as pieced values with a single
+        piece.  */
+      gdb_assert (closure != NULL);
+      gdb_assert (closure->n_pieces == 1);
+
+      return indirect_synthetic_pointer (closure->pieces->v.ptr.die,
+                                        closure->pieces->v.ptr.offset,
+                                        closure->per_cu, frame, type);
+    }
+  else
+    {
+      /* Else: not a synthetic reference; do nothing.  */
+      return NULL;
+    }
 }
 
 static void *
@@ -2200,7 +2265,7 @@ static const struct lval_funcs pieced_value_funcs = {
   read_pieced_value,
   write_pieced_value,
   indirect_pieced_value,
-  NULL,        /* coerce_ref */
+  coerce_pieced_ref,
   check_pieced_synthetic_pointer,
   copy_pieced_value_closure,
   free_pieced_value_closure
@@ -2661,21 +2726,21 @@ dwarf2_compile_property_to_c (struct ui_file *stream,
 }
 
 \f
-/* Helper functions and baton for dwarf2_loc_desc_needs_frame.  */
+/* Helper functions and baton for dwarf2_loc_desc_get_symbol_read_needs.  */
 
-struct needs_frame_baton
+struct symbol_needs_baton
 {
-  int needs_frame;
+  enum symbol_needs_kind needs;
   struct dwarf2_per_cu_data *per_cu;
 };
 
 /* Reads from registers do require a frame.  */
 static CORE_ADDR
-needs_frame_read_addr_from_reg (void *baton, int regnum)
+symbol_needs_read_addr_from_reg (void *baton, int regnum)
 {
-  struct needs_frame_baton *nf_baton = (struct needs_frame_baton *) baton;
+  struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
 
-  nf_baton->needs_frame = 1;
+  nf_baton->needs = SYMBOL_NEEDS_FRAME;
   return 1;
 }
 
@@ -2683,61 +2748,64 @@ needs_frame_read_addr_from_reg (void *baton, int regnum)
    Reads from registers do require a frame.  */
 
 static struct value *
-needs_frame_get_reg_value (void *baton, struct type *type, int regnum)
+symbol_needs_get_reg_value (void *baton, struct type *type, int regnum)
 {
-  struct needs_frame_baton *nf_baton = (struct needs_frame_baton *) baton;
+  struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
 
-  nf_baton->needs_frame = 1;
+  nf_baton->needs = SYMBOL_NEEDS_FRAME;
   return value_zero (type, not_lval);
 }
 
 /* Reads from memory do not require a frame.  */
 static void
-needs_frame_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
+symbol_needs_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
 {
   memset (buf, 0, len);
 }
 
 /* Frame-relative accesses do require a frame.  */
 static void
-needs_frame_frame_base (void *baton, const gdb_byte **start, size_t * length)
+symbol_needs_frame_base (void *baton, const gdb_byte **start, size_t * length)
 {
   static gdb_byte lit0 = DW_OP_lit0;
-  struct needs_frame_baton *nf_baton = (struct needs_frame_baton *) baton;
+  struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
 
   *start = &lit0;
   *length = 1;
 
-  nf_baton->needs_frame = 1;
+  nf_baton->needs = SYMBOL_NEEDS_FRAME;
 }
 
 /* CFA accesses require a frame.  */
 
 static CORE_ADDR
-needs_frame_frame_cfa (void *baton)
+symbol_needs_frame_cfa (void *baton)
 {
-  struct needs_frame_baton *nf_baton = (struct needs_frame_baton *) baton;
+  struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
 
-  nf_baton->needs_frame = 1;
+  nf_baton->needs = SYMBOL_NEEDS_FRAME;
   return 1;
 }
 
-/* Thread-local accesses do require a frame.  */
+/* Thread-local accesses require registers, but not a frame.  */
 static CORE_ADDR
-needs_frame_tls_address (void *baton, CORE_ADDR offset)
+symbol_needs_tls_address (void *baton, CORE_ADDR offset)
 {
-  struct needs_frame_baton *nf_baton = (struct needs_frame_baton *) baton;
+  struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
 
-  nf_baton->needs_frame = 1;
+  if (nf_baton->needs <= SYMBOL_NEEDS_REGISTERS)
+    nf_baton->needs = SYMBOL_NEEDS_REGISTERS;
   return 1;
 }
 
-/* Helper interface of per_cu_dwarf_call for dwarf2_loc_desc_needs_frame.  */
+/* Helper interface of per_cu_dwarf_call for
+   dwarf2_loc_desc_get_symbol_read_needs.  */
 
 static void
-needs_frame_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset)
+symbol_needs_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset)
 {
-  struct needs_frame_baton *nf_baton = (struct needs_frame_baton *) ctx->baton;
+  struct symbol_needs_baton *nf_baton =
+    (struct symbol_needs_baton *) ctx->baton;
 
   per_cu_dwarf_call (ctx, die_offset, nf_baton->per_cu,
                     ctx->funcs->get_frame_pc, ctx->baton);
@@ -2750,9 +2818,10 @@ needs_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
                             enum call_site_parameter_kind kind,
                             union call_site_parameter_u kind_u, int deref_size)
 {
-  struct needs_frame_baton *nf_baton = (struct needs_frame_baton *) ctx->baton;
+  struct symbol_needs_baton *nf_baton =
+    (struct symbol_needs_baton *) ctx->baton;
 
-  nf_baton->needs_frame = 1;
+  nf_baton->needs = SYMBOL_NEEDS_FRAME;
 
   /* The expression may require some stub values on DWARF stack.  */
   dwarf_expr_push_address (ctx, 0, 0);
@@ -2776,38 +2845,39 @@ needs_get_obj_addr (void *baton)
   return 1;
 }
 
-/* Virtual method table for dwarf2_loc_desc_needs_frame below.  */
+/* Virtual method table for dwarf2_loc_desc_get_symbol_read_needs
+   below.  */
 
-static const struct dwarf_expr_context_funcs needs_frame_ctx_funcs =
+static const struct dwarf_expr_context_funcs symbol_needs_ctx_funcs =
 {
-  needs_frame_read_addr_from_reg,
-  needs_frame_get_reg_value,
-  needs_frame_read_mem,
-  needs_frame_frame_base,
-  needs_frame_frame_cfa,
-  needs_frame_frame_cfa,       /* get_frame_pc */
-  needs_frame_tls_address,
-  needs_frame_dwarf_call,
+  symbol_needs_read_addr_from_reg,
+  symbol_needs_get_reg_value,
+  symbol_needs_read_mem,
+  symbol_needs_frame_base,
+  symbol_needs_frame_cfa,
+  symbol_needs_frame_cfa,      /* get_frame_pc */
+  symbol_needs_tls_address,
+  symbol_needs_dwarf_call,
   NULL,                                /* get_base_type */
   needs_dwarf_reg_entry_value,
   needs_get_addr_index,
   needs_get_obj_addr
 };
 
-/* Return non-zero iff the location expression at DATA (length SIZE)
-   requires a frame to evaluate.  */
+/* Compute the correct symbol_needs_kind value for the location
+   expression at DATA (length SIZE).  */
 
-static int
-dwarf2_loc_desc_needs_frame (const gdb_byte *data, size_t size,
-                            struct dwarf2_per_cu_data *per_cu)
+static enum symbol_needs_kind
+dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
+                                      struct dwarf2_per_cu_data *per_cu)
 {
-  struct needs_frame_baton baton;
+  struct symbol_needs_baton baton;
   struct dwarf_expr_context *ctx;
   int in_reg;
   struct cleanup *old_chain;
   struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
 
-  baton.needs_frame = 0;
+  baton.needs = SYMBOL_NEEDS_NONE;
   baton.per_cu = per_cu;
 
   ctx = new_dwarf_expr_context ();
@@ -2819,7 +2889,7 @@ dwarf2_loc_desc_needs_frame (const gdb_byte *data, size_t size,
   ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
   ctx->offset = dwarf2_per_cu_text_offset (per_cu);
   ctx->baton = &baton;
-  ctx->funcs = &needs_frame_ctx_funcs;
+  ctx->funcs = &symbol_needs_ctx_funcs;
 
   dwarf_expr_eval (ctx, data, size);
 
@@ -2838,7 +2908,9 @@ dwarf2_loc_desc_needs_frame (const gdb_byte *data, size_t size,
 
   do_cleanups (old_chain);
 
-  return baton.needs_frame || in_reg;
+  if (in_reg)
+    baton.needs = SYMBOL_NEEDS_FRAME;
+  return baton.needs;
 }
 
 /* A helper function that throws an unimplemented error mentioning a
@@ -3499,6 +3571,7 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
          break;
 
        case DW_OP_GNU_push_tls_address:
+       case DW_OP_form_tls_address:
          unimplemented (op);
          break;
 
@@ -3671,15 +3744,17 @@ locexpr_read_variable_at_entry (struct symbol *symbol, struct frame_info *frame)
                                     dlbaton->size);
 }
 
-/* Return non-zero iff we need a frame to evaluate SYMBOL.  */
-static int
-locexpr_read_needs_frame (struct symbol *symbol)
+/* Implementation of get_symbol_read_needs from
+   symbol_computed_ops.  */
+
+static enum symbol_needs_kind
+locexpr_get_symbol_read_needs (struct symbol *symbol)
 {
   struct dwarf2_locexpr_baton *dlbaton
     = (struct dwarf2_locexpr_baton *) SYMBOL_LOCATION_BATON (symbol);
 
-  return dwarf2_loc_desc_needs_frame (dlbaton->data, dlbaton->size,
-                                     dlbaton->per_cu);
+  return dwarf2_loc_desc_get_symbol_read_needs (dlbaton->data, dlbaton->size,
+                                               dlbaton->per_cu);
 }
 
 /* Return true if DATA points to the end of a piece.  END is one past
@@ -3833,7 +3908,8 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
           && (data[0] == DW_OP_addr
               || (addr_size == 4 && data[0] == DW_OP_const4u)
               || (addr_size == 8 && data[0] == DW_OP_const8u))
-          && data[1 + addr_size] == DW_OP_GNU_push_tls_address
+          && (data[1 + addr_size] == DW_OP_GNU_push_tls_address
+              || data[1 + addr_size] == DW_OP_form_tls_address)
           && piece_end_p (data + 2 + addr_size, end))
     {
       ULONGEST offset;
@@ -3856,7 +3932,8 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
           && data + 1 + (leb128_size = skip_leb128 (data + 1, end)) < end
           && data[0] == DW_OP_GNU_const_index
           && leb128_size > 0
-          && data[1 + leb128_size] == DW_OP_GNU_push_tls_address
+          && (data[1 + leb128_size] == DW_OP_GNU_push_tls_address
+              || data[1 + leb128_size] == DW_OP_form_tls_address)
           && piece_end_p (data + 2 + leb128_size, end))
     {
       uint64_t offset;
@@ -4408,7 +4485,7 @@ locexpr_generate_c_location (struct symbol *sym, struct ui_file *stream,
 const struct symbol_computed_ops dwarf2_locexpr_funcs = {
   locexpr_read_variable,
   locexpr_read_variable_at_entry,
-  locexpr_read_needs_frame,
+  locexpr_get_symbol_read_needs,
   locexpr_describe_location,
   0,   /* location_has_loclist */
   locexpr_tracepoint_var_ref,
@@ -4465,9 +4542,11 @@ loclist_read_variable_at_entry (struct symbol *symbol, struct frame_info *frame)
   return value_of_dwarf_block_entry (SYMBOL_TYPE (symbol), frame, data, size);
 }
 
-/* Return non-zero iff we need a frame to evaluate SYMBOL.  */
-static int
-loclist_read_needs_frame (struct symbol *symbol)
+/* Implementation of get_symbol_read_needs from
+   symbol_computed_ops.  */
+
+static enum symbol_needs_kind
+loclist_symbol_needs (struct symbol *symbol)
 {
   /* If there's a location list, then assume we need to have a frame
      to choose the appropriate location expression.  With tracking of
@@ -4475,7 +4554,7 @@ loclist_read_needs_frame (struct symbol *symbol)
      is disabled in GCC at the moment until we figure out how to
      represent it.  */
 
-  return 1;
+  return SYMBOL_NEEDS_FRAME;
 }
 
 /* Print a natural-language description of SYMBOL to STREAM.  This
@@ -4619,7 +4698,7 @@ loclist_generate_c_location (struct symbol *sym, struct ui_file *stream,
 const struct symbol_computed_ops dwarf2_loclist_funcs = {
   loclist_read_variable,
   loclist_read_variable_at_entry,
-  loclist_read_needs_frame,
+  loclist_symbol_needs,
   loclist_describe_location,
   1,   /* location_has_loclist */
   loclist_tracepoint_var_ref,
This page took 0.03312 seconds and 4 git commands to generate.