make dwarf_expr_frame_base_1 public
[deliverable/binutils-gdb.git] / gdb / dwarf2loc.c
index e91b764065d1b4d09c0af858c55e88c0cd95c3ed..3a62869ba30f06866b31efe6831b6ff101d6f8dd 100644 (file)
@@ -30,7 +30,6 @@
 #include "ax-gdb.h"
 #include "regcache.h"
 #include "objfiles.h"
-#include "exceptions.h"
 #include "block.h"
 #include "gdbcmd.h"
 
 #include "dwarf2loc.h"
 #include "dwarf2-frame.h"
 
-#include <string.h>
-#include "gdb_assert.h"
-
 extern int dwarf2_always_disassemble;
 
-static void dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc,
-                                    const gdb_byte **start, size_t *length);
-
 static const struct dwarf_expr_context_funcs dwarf_expr_ctx_funcs;
 
 static struct value *dwarf2_evaluate_loc_desc_full (struct type *type,
@@ -277,7 +270,7 @@ dwarf2_find_location_expression (struct dwarf2_loclist_baton *baton,
          /* This is entry PC record present only at entry point
             of a function.  Verify it is really the function entry point.  */
 
-         struct block *pc_block = block_for_pc (pc);
+         const struct block *pc_block = block_for_pc (pc);
          struct symbol *pc_func = NULL;
 
          if (pc_block)
@@ -306,6 +299,7 @@ struct dwarf_expr_baton
 {
   struct frame_info *frame;
   struct dwarf2_per_cu_data *per_cu;
+  CORE_ADDR obj_address;
 };
 
 /* Helper functions for dwarf2_evaluate_loc_desc.  */
@@ -317,13 +311,9 @@ dwarf_expr_read_addr_from_reg (void *baton, int dwarf_regnum)
 {
   struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
   struct gdbarch *gdbarch = get_frame_arch (debaton->frame);
-  CORE_ADDR result;
-  int regnum;
+  int regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_regnum);
 
-  regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_regnum);
-  result = address_from_register (builtin_type (gdbarch)->builtin_data_ptr,
-                                 regnum, debaton->frame);
-  return result;
+  return address_from_register (regnum, debaton->frame);
 }
 
 /* Implement struct dwarf_expr_context_funcs' "get_reg_value" callback.  */
@@ -357,7 +347,7 @@ dwarf_expr_frame_base (void *baton, const gdb_byte **start, size_t * length)
      this_base method.  */
   struct symbol *framefunc;
   struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-  struct block *bl = get_frame_block (debaton->frame, NULL);
+  const struct block *bl = get_frame_block (debaton->frame, NULL);
 
   if (bl == NULL)
     error (_("frame address is not available."));
@@ -372,9 +362,9 @@ dwarf_expr_frame_base (void *baton, const gdb_byte **start, size_t * length)
      something has gone wrong.  */
   gdb_assert (framefunc != NULL);
 
-  dwarf_expr_frame_base_1 (framefunc,
-                          get_frame_address_in_block (debaton->frame),
-                          start, length);
+  func_get_frame_base_dwarf_block (framefunc,
+                                  get_frame_address_in_block (debaton->frame),
+                                  start, length);
 }
 
 /* Implement find_frame_base_location method for LOC_BLOCK functions using
@@ -418,9 +408,11 @@ const struct symbol_block_ops dwarf2_block_frame_base_loclist_funcs =
   loclist_find_frame_base_location
 };
 
-static void
-dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc,
-                        const gdb_byte **start, size_t *length)
+/* See dwarf2loc.h.  */
+
+void
+func_get_frame_base_dwarf_block (struct symbol *framefunc, CORE_ADDR pc,
+                                const gdb_byte **start, size_t *length)
 {
   if (SYMBOL_BLOCK_OPS (framefunc) != NULL)
     {
@@ -1213,6 +1205,7 @@ dwarf_expr_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
 
   baton_local.frame = caller_frame;
   baton_local.per_cu = caller_per_cu;
+  baton_local.obj_address = 0;
 
   saved_ctx.gdbarch = ctx->gdbarch;
   saved_ctx.addr_size = ctx->addr_size;
@@ -1242,6 +1235,22 @@ dwarf_expr_get_addr_index (void *baton, unsigned int index)
   return dwarf2_read_addr_index (debaton->per_cu, index);
 }
 
+/* Callback function for get_object_address. Return the address of the VLA
+   object.  */
+
+static CORE_ADDR
+dwarf_expr_get_obj_addr (void *baton)
+{
+  struct dwarf_expr_baton *debaton = baton;
+
+  gdb_assert (debaton != NULL);
+
+  if (debaton->obj_address == 0)
+    error (_("Location address is not set."));
+
+  return debaton->obj_address;
+}
+
 /* VALUE must be of type lval_computed with entry_data_value_funcs.  Perform
    the indirect method on it, that is use its stored target value, the sole
    purpose of entry_data_value_funcs..  */
@@ -1289,8 +1298,6 @@ static const struct lval_funcs entry_data_value_funcs =
 {
   NULL,        /* read */
   NULL,        /* write */
-  NULL,        /* check_validity */
-  NULL,        /* check_any_valid */
   NULL,        /* indirect */
   entry_data_value_coerce_ref,
   NULL,        /* check_synthetic_pointer */
@@ -1316,7 +1323,6 @@ value_of_dwarf_reg_entry (struct type *type, struct frame_info *frame,
   struct value *outer_val, *target_val, *val;
   struct call_site_parameter *parameter;
   struct dwarf2_per_cu_data *caller_per_cu;
-  CORE_ADDR addr;
 
   parameter = dwarf_expr_reg_to_entry_parameter (frame, kind, kind_u,
                                                 &caller_per_cu);
@@ -1339,14 +1345,6 @@ value_of_dwarf_reg_entry (struct type *type, struct frame_info *frame,
                                               target_type, caller_frame,
                                               caller_per_cu);
 
-  /* value_as_address dereferences TYPE_CODE_REF.  */
-  addr = extract_typed_address (value_contents (outer_val), checked_type);
-
-  /* The target entry value has artificial address of the entry value
-     reference.  */
-  VALUE_LVAL (target_val) = lval_memory;
-  set_value_address (target_val, addr);
-
   release_value (target_val);
   val = allocate_computed_value (type, &entry_data_value_funcs,
                                 target_val /* closure */);
@@ -1684,21 +1682,21 @@ read_pieced_value (struct value *v)
          {
            struct gdbarch *arch = get_frame_arch (frame);
            int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.regno);
-           int reg_offset = source_offset;
-
-           if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
-               && this_size < register_size (arch, gdb_regnum))
-             {
-               /* Big-endian, and we want less than full size.  */
-               reg_offset = register_size (arch, gdb_regnum) - this_size;
-               /* We want the lower-order THIS_SIZE_BITS of the bytes
-                  we extract from the register.  */
-               source_offset_bits += 8 * this_size - this_size_bits;
-             }
 
            if (gdb_regnum != -1)
              {
                int optim, unavail;
+               int reg_offset = source_offset;
+
+               if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
+                   && this_size < register_size (arch, gdb_regnum))
+                 {
+                   /* Big-endian, and we want less than full size.  */
+                   reg_offset = register_size (arch, gdb_regnum) - this_size;
+                   /* We want the lower-order THIS_SIZE_BITS of the bytes
+                      we extract from the register.  */
+                   source_offset_bits += 8 * this_size - this_size_bits;
+                }
 
                if (!get_frame_register_bytes (frame, gdb_regnum, reg_offset,
                                               this_size, buffer,
@@ -1708,7 +1706,7 @@ read_pieced_value (struct value *v)
                    memset (buffer, 0, this_size);
 
                    if (optim)
-                     set_value_optimized_out (v, 1);
+                     mark_value_bits_optimized_out (v, offset, this_size_bits);
                    if (unavail)
                      mark_value_bits_unavailable (v, offset, this_size_bits);
                  }
@@ -1768,7 +1766,7 @@ read_pieced_value (struct value *v)
          break;
 
        case DWARF_VALUE_OPTIMIZED_OUT:
-         set_value_optimized_out (v, 1);
+         mark_value_bits_optimized_out (v, offset, this_size_bits);
          break;
 
        default:
@@ -1806,7 +1804,7 @@ write_pieced_value (struct value *to, struct value *from)
 
   if (frame == NULL)
     {
-      set_value_optimized_out (to, 1);
+      mark_value_bytes_optimized_out (to, 0, TYPE_LENGTH (value_type (to)));
       return;
     }
 
@@ -1876,15 +1874,18 @@ write_pieced_value (struct value *to, struct value *from)
          {
            struct gdbarch *arch = get_frame_arch (frame);
            int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.regno);
-           int reg_offset = dest_offset;
-
-           if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
-               && this_size <= register_size (arch, gdb_regnum))
-             /* Big-endian, and we want less than full size.  */
-             reg_offset = register_size (arch, gdb_regnum) - this_size;
 
            if (gdb_regnum != -1)
              {
+               int reg_offset = dest_offset;
+
+               if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
+                   && this_size <= register_size (arch, gdb_regnum))
+                 {
+                   /* Big-endian, and we want less than full size.  */
+                   reg_offset = register_size (arch, gdb_regnum) - this_size;
+                 }
+
                if (need_bitwise)
                  {
                    int optim, unavail;
@@ -1938,7 +1939,7 @@ write_pieced_value (struct value *to, struct value *from)
                        source_buffer, this_size);
          break;
        default:
-         set_value_optimized_out (to, 1);
+         mark_value_bytes_optimized_out (to, 0, TYPE_LENGTH (value_type (to)));
          break;
        }
       offset += this_size_bits;
@@ -1947,24 +1948,16 @@ write_pieced_value (struct value *to, struct value *from)
   do_cleanups (cleanup);
 }
 
-/* A helper function that checks bit validity in a pieced value.
-   CHECK_FOR indicates the kind of validity checking.
-   DWARF_VALUE_MEMORY means to check whether any bit is valid.
-   DWARF_VALUE_OPTIMIZED_OUT means to check whether any bit is
-   optimized out.
-   DWARF_VALUE_IMPLICIT_POINTER means to check whether the bits are an
-   implicit pointer.  */
+/* An implementation of an lval_funcs method to see whether a value is
+   a synthetic pointer.  */
 
 static int
-check_pieced_value_bits (const struct value *value, int bit_offset,
-                        int bit_length,
-                        enum dwarf_value_location check_for)
+check_pieced_synthetic_pointer (const struct value *value, int bit_offset,
+                               int bit_length)
 {
   struct piece_closure *c
     = (struct piece_closure *) value_computed_closure (value);
   int i;
-  int validity = (check_for == DWARF_VALUE_MEMORY
-                 || check_for == DWARF_VALUE_IMPLICIT_POINTER);
 
   bit_offset += 8 * value_offset (value);
   if (value_bitsize (value))
@@ -1989,52 +1982,11 @@ check_pieced_value_bits (const struct value *value, int bit_offset,
       else
        bit_length -= this_size_bits;
 
-      if (check_for == DWARF_VALUE_IMPLICIT_POINTER)
-       {
-         if (p->location != DWARF_VALUE_IMPLICIT_POINTER)
-           return 0;
-       }
-      else if (p->location == DWARF_VALUE_OPTIMIZED_OUT
-              || p->location == DWARF_VALUE_IMPLICIT_POINTER)
-       {
-         if (validity)
-           return 0;
-       }
-      else
-       {
-         if (!validity)
-           return 1;
-       }
+      if (p->location != DWARF_VALUE_IMPLICIT_POINTER)
+       return 0;
     }
 
-  return validity;
-}
-
-static int
-check_pieced_value_validity (const struct value *value, int bit_offset,
-                            int bit_length)
-{
-  return check_pieced_value_bits (value, bit_offset, bit_length,
-                                 DWARF_VALUE_MEMORY);
-}
-
-static int
-check_pieced_value_invalid (const struct value *value)
-{
-  return check_pieced_value_bits (value, 0,
-                                 8 * TYPE_LENGTH (value_type (value)),
-                                 DWARF_VALUE_OPTIMIZED_OUT);
-}
-
-/* An implementation of an lval_funcs method to see whether a value is
-   a synthetic pointer.  */
-
-static int
-check_pieced_synthetic_pointer (const struct value *value, int bit_offset,
-                               int bit_length)
-{
-  return check_pieced_value_bits (value, bit_offset, bit_length,
-                                 DWARF_VALUE_IMPLICIT_POINTER);
+  return 1;
 }
 
 /* A wrapper function for get_frame_address_in_block.  */
@@ -2183,8 +2135,6 @@ free_pieced_value_closure (struct value *v)
 static const struct lval_funcs pieced_value_funcs = {
   read_pieced_value,
   write_pieced_value,
-  check_pieced_value_validity,
-  check_pieced_value_invalid,
   indirect_pieced_value,
   NULL,        /* coerce_ref */
   check_pieced_synthetic_pointer,
@@ -2206,7 +2156,8 @@ static const struct dwarf_expr_context_funcs dwarf_expr_ctx_funcs =
   dwarf_expr_dwarf_call,
   dwarf_expr_get_base_type,
   dwarf_expr_push_dwarf_reg_entry_value,
-  dwarf_expr_get_addr_index
+  dwarf_expr_get_addr_index,
+  dwarf_expr_get_obj_addr
 };
 
 /* Evaluate a location description, starting at DATA and with length
@@ -2235,6 +2186,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 
   baton.frame = frame;
   baton.per_cu = per_cu;
+  baton.obj_address = 0;
 
   ctx = new_dwarf_expr_context ();
   old_chain = make_cleanup_free_dwarf_expr_context (ctx);
@@ -2312,6 +2264,8 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
           retval = value_from_register (type, gdb_regnum, frame);
           if (value_optimized_out (retval))
             {
+              struct value *tmp;
+
               /* This means the register has undefined value / was
                  not saved.  As we're computing the location of some
                  variable etc. in the program, not a value for
@@ -2319,7 +2273,9 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
                  generic optimized out value instead, so that we show
                  <optimized out> instead of <not saved>.  */
               do_cleanups (value_chain);
-              retval = allocate_optimized_out_value (type);
+              tmp = allocate_value (type);
+              value_contents_copy (tmp, 0, retval, 0, TYPE_LENGTH (type));
+              retval = tmp;
             }
          }
          break;
@@ -2432,6 +2388,127 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame,
   return dwarf2_evaluate_loc_desc_full (type, frame, data, size, per_cu, 0);
 }
 
+/* Evaluates a dwarf expression and stores the result in VAL, expecting
+   that the dwarf expression only produces a single CORE_ADDR.  ADDR is a
+   context (location of a variable) and might be needed to evaluate the
+   location expression.
+   Returns 1 on success, 0 otherwise.   */
+
+static int
+dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
+                          CORE_ADDR addr,
+                          CORE_ADDR *valp)
+{
+  struct dwarf_expr_context *ctx;
+  struct dwarf_expr_baton baton;
+  struct objfile *objfile;
+  struct cleanup *cleanup;
+
+  if (dlbaton == NULL || dlbaton->size == 0)
+    return 0;
+
+  ctx = new_dwarf_expr_context ();
+  cleanup = make_cleanup_free_dwarf_expr_context (ctx);
+
+  baton.frame = get_selected_frame (NULL);
+  baton.per_cu = dlbaton->per_cu;
+  baton.obj_address = addr;
+
+  objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
+
+  ctx->gdbarch = get_objfile_arch (objfile);
+  ctx->addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
+  ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (dlbaton->per_cu);
+  ctx->offset = dwarf2_per_cu_text_offset (dlbaton->per_cu);
+  ctx->funcs = &dwarf_expr_ctx_funcs;
+  ctx->baton = &baton;
+
+  dwarf_expr_eval (ctx, dlbaton->data, dlbaton->size);
+
+  switch (ctx->location)
+    {
+    case DWARF_VALUE_REGISTER:
+    case DWARF_VALUE_MEMORY:
+    case DWARF_VALUE_STACK:
+      *valp = dwarf_expr_fetch_address (ctx, 0);
+      if (ctx->location == DWARF_VALUE_REGISTER)
+       *valp = dwarf_expr_read_addr_from_reg (&baton, *valp);
+      do_cleanups (cleanup);
+      return 1;
+    case DWARF_VALUE_LITERAL:
+      *valp = extract_signed_integer (ctx->data, ctx->len,
+                                     gdbarch_byte_order (ctx->gdbarch));
+      do_cleanups (cleanup);
+      return 1;
+      /* Unsupported dwarf values.  */
+    case DWARF_VALUE_OPTIMIZED_OUT:
+    case DWARF_VALUE_IMPLICIT_POINTER:
+      break;
+    }
+
+  do_cleanups (cleanup);
+  return 0;
+}
+
+/* See dwarf2loc.h.  */
+
+int
+dwarf2_evaluate_property (const struct dynamic_prop *prop,
+                         CORE_ADDR address, CORE_ADDR *value)
+{
+  if (prop == NULL)
+    return 0;
+
+  switch (prop->kind)
+    {
+    case PROP_LOCEXPR:
+      {
+       const struct dwarf2_property_baton *baton = prop->data.baton;
+
+       if (dwarf2_locexpr_baton_eval (&baton->locexpr, address, value))
+         {
+           if (baton->referenced_type)
+             {
+               struct value *val = value_at (baton->referenced_type, *value);
+
+               *value = value_as_address (val);
+             }
+           return 1;
+         }
+      }
+      break;
+
+    case PROP_LOCLIST:
+      {
+       struct dwarf2_property_baton *baton = prop->data.baton;
+       struct frame_info *frame = get_selected_frame (NULL);
+       CORE_ADDR pc = get_frame_address_in_block (frame);
+       const gdb_byte *data;
+       struct value *val;
+       size_t size;
+
+       data = dwarf2_find_location_expression (&baton->loclist, &size, pc);
+       if (data != NULL)
+         {
+           val = dwarf2_evaluate_loc_desc (baton->referenced_type, frame, data,
+                                           size, baton->loclist.per_cu);
+           if (!value_optimized_out (val))
+             {
+               *value = value_as_address (val);
+               return 1;
+             }
+         }
+      }
+      break;
+
+    case PROP_CONST:
+      *value = prop->data.const_val;
+      return 1;
+    }
+
+  return 0;
+}
+
 \f
 /* Helper functions and baton for dwarf2_loc_desc_needs_frame.  */
 
@@ -2539,6 +2616,15 @@ needs_get_addr_index (void *baton, unsigned int index)
   return 1;
 }
 
+/* DW_OP_push_object_address has a frame already passed through.  */
+
+static CORE_ADDR
+needs_get_obj_addr (void *baton)
+{
+  /* Nothing to do.  */
+  return 1;
+}
+
 /* Virtual method table for dwarf2_loc_desc_needs_frame below.  */
 
 static const struct dwarf_expr_context_funcs needs_frame_ctx_funcs =
@@ -2553,7 +2639,8 @@ static const struct dwarf_expr_context_funcs needs_frame_ctx_funcs =
   needs_frame_dwarf_call,
   NULL,                                /* get_base_type */
   needs_dwarf_reg_entry_value,
-  needs_get_addr_index
+  needs_get_addr_index,
+  needs_get_obj_addr
 };
 
 /* Return non-zero iff the location expression at DATA (length SIZE)
@@ -2973,7 +3060,7 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
          {
            const gdb_byte *datastart;
            size_t datalen;
-           struct block *b;
+           const struct block *b;
            struct symbol *framefunc;
 
            b = block_for_pc (expr->scope);
@@ -2986,8 +3073,8 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
            if (!framefunc)
              error (_("No function found for block"));
 
-           dwarf_expr_frame_base_1 (framefunc, expr->scope,
-                                    &datastart, &datalen);
+           func_get_frame_base_dwarf_block (framefunc, expr->scope,
+                                            &datastart, &datalen);
 
            op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
            dwarf2_compile_expr_to_ax (expr, loc, arch, addr_size, datastart,
@@ -3194,14 +3281,44 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
          break;
 
        case DW_OP_call_frame_cfa:
-         dwarf2_compile_cfa_to_ax (expr, loc, arch, expr->scope, per_cu);
-         loc->kind = axs_lvalue_memory;
+         {
+           int regnum;
+           CORE_ADDR text_offset;
+           LONGEST off;
+           const gdb_byte *cfa_start, *cfa_end;
+
+           if (dwarf2_fetch_cfa_info (arch, expr->scope, per_cu,
+                                      &regnum, &off,
+                                      &text_offset, &cfa_start, &cfa_end))
+             {
+               /* Register.  */
+               ax_reg (expr, regnum);
+               if (off != 0)
+                 {
+                   ax_const_l (expr, off);
+                   ax_simple (expr, aop_add);
+                 }
+             }
+           else
+             {
+               /* Another expression.  */
+               ax_const_l (expr, text_offset);
+               dwarf2_compile_expr_to_ax (expr, loc, arch, addr_size,
+                                          cfa_start, cfa_end, per_cu);
+             }
+
+           loc->kind = axs_lvalue_memory;
+         }
          break;
 
        case DW_OP_GNU_push_tls_address:
          unimplemented (op);
          break;
 
+       case DW_OP_push_object_address:
+         unimplemented (op);
+         break;
+
        case DW_OP_skip:
          offset = extract_signed_integer (op_ptr, 2, byte_order);
          op_ptr += 2;
@@ -3428,7 +3545,7 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
     }
   else if (data[0] == DW_OP_fbreg)
     {
-      struct block *b;
+      const struct block *b;
       struct symbol *framefunc;
       int frame_reg = 0;
       int64_t frame_offset;
@@ -3453,7 +3570,7 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
        error (_("No function found for block for symbol \"%s\"."),
               SYMBOL_PRINT_NAME (symbol));
 
-      dwarf_expr_frame_base_1 (framefunc, addr, &base_data, &base_size);
+      func_get_frame_base_dwarf_block (framefunc, addr, &base_data, &base_size);
 
       if (base_data[0] >= DW_OP_breg0 && base_data[0] <= DW_OP_breg31)
        {
@@ -4204,6 +4321,9 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr,
       low += base_address;
       high += base_address;
 
+      low = gdbarch_adjust_dwarf2_addr (gdbarch, low);
+      high = gdbarch_adjust_dwarf2_addr (gdbarch, high);
+
       length = extract_unsigned_integer (loc_ptr, 2, byte_order);
       loc_ptr += 2;
 
This page took 0.062414 seconds and 4 git commands to generate.