bfd/
[deliverable/binutils-gdb.git] / gdb / dwarf2loc.c
index 00b21968b42ec8d96223094510fc4473d2e7de62..1b29dc9a0b0dc1be92c5e4ae5348caee46c012eb 100644 (file)
@@ -1,6 +1,6 @@
 /* DWARF 2 location expression support for GDB.
 
-   Copyright 2003, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2005 Free Software Foundation, Inc.
 
    Contributed by Daniel Jacobowitz, MontaVista Software, Inc.
 
@@ -18,8 +18,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "defs.h"
 #include "ui-out.h"
    For now, only return the first matching location expression; there
    can be more than one in the list.  */
 
-static char *
+static gdb_byte *
 find_location_expression (struct dwarf2_loclist_baton *baton,
                          size_t *locexpr_length, CORE_ADDR pc)
 {
   CORE_ADDR low, high;
-  char *loc_ptr, *buf_end;
-  unsigned int addr_size = TARGET_ADDR_BIT / TARGET_CHAR_BIT, length;
+  gdb_byte *loc_ptr, *buf_end;
+  int length;
+  unsigned int addr_size = TARGET_ADDR_BIT / TARGET_CHAR_BIT;
   CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
   /* Adjust base_address for relocatable objects.  */
   CORE_ADDR base_offset = ANOFFSET (baton->objfile->section_offsets,
@@ -113,35 +114,25 @@ struct dwarf_expr_baton
 
 /* Helper functions for dwarf2_evaluate_loc_desc.  */
 
-/* Using the frame specified in BATON, read register REGNUM.  The lval
-   type will be returned in LVALP, and for lval_memory the register
-   save address will be returned in ADDRP.  */
+/* Using the frame specified in BATON, return the value of register
+   REGNUM, treated as a pointer.  */
 static CORE_ADDR
 dwarf_expr_read_reg (void *baton, int dwarf_regnum)
 {
   struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-  CORE_ADDR result, save_addr;
-  enum lval_type lval_type;
-  char *buf;
-  int optimized, regnum, realnum, regsize;
+  CORE_ADDR result;
+  int regnum;
 
   regnum = DWARF2_REG_TO_REGNUM (dwarf_regnum);
-  regsize = register_size (current_gdbarch, regnum);
-  buf = (char *) alloca (regsize);
-
-  frame_register (debaton->frame, regnum, &optimized, &lval_type, &save_addr,
-                 &realnum, buf);
-  /* NOTE: cagney/2003-05-22: This extract is assuming that a DWARF 2
-     address is always unsigned.  That may or may not be true.  */
-  result = extract_unsigned_integer (buf, regsize);
-
+  result = address_from_register (builtin_type_void_data_ptr,
+                                 regnum, debaton->frame);
   return result;
 }
 
 /* Read memory at ADDR (length LEN) into BUF.  */
 
 static void
-dwarf_expr_read_mem (void *baton, char *buf, CORE_ADDR addr, size_t len)
+dwarf_expr_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
 {
   read_memory (addr, buf, len);
 }
@@ -150,7 +141,7 @@ dwarf_expr_read_mem (void *baton, char *buf, CORE_ADDR addr, size_t len)
    describing the frame base.  Return a pointer to it in START and
    its length in LENGTH.  */
 static void
-dwarf_expr_frame_base (void *baton, unsigned char **start, size_t * length)
+dwarf_expr_frame_base (void *baton, gdb_byte **start, size_t * length)
 {
   /* FIXME: cagney/2003-03-26: This code should be using
      get_frame_base_address(), and then implement a dwarf2 specific
@@ -163,9 +154,11 @@ dwarf_expr_frame_base (void *baton, unsigned char **start, size_t * length)
   if (SYMBOL_OPS (framefunc) == &dwarf2_loclist_funcs)
     {
       struct dwarf2_loclist_baton *symbaton;
+      struct frame_info *frame = debaton->frame;
+
       symbaton = SYMBOL_LOCATION_BATON (framefunc);
       *start = find_location_expression (symbaton, length,
-                                        get_frame_pc (debaton->frame));
+                                        get_frame_address_in_block (frame));
     }
   else
     {
@@ -186,90 +179,8 @@ static CORE_ADDR
 dwarf_expr_tls_address (void *baton, CORE_ADDR offset)
 {
   struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-  volatile CORE_ADDR addr = 0;
-
-  if (target_get_thread_local_address_p ()
-      && gdbarch_fetch_tls_load_module_address_p (current_gdbarch))
-    {
-      ptid_t ptid = inferior_ptid;
-      struct objfile *objfile = debaton->objfile;
-      volatile struct gdb_exception ex;
-
-      TRY_CATCH (ex, RETURN_MASK_ALL)
-       {
-         CORE_ADDR lm_addr;
-         
-         /* Fetch the load module address for this objfile.  */
-         lm_addr = gdbarch_fetch_tls_load_module_address (current_gdbarch,
-                                                          objfile);
-         /* If it's 0, throw the appropriate exception.  */
-         if (lm_addr == 0)
-           {
-             struct gdb_exception e
-               = { RETURN_ERROR, TLS_LOAD_MODULE_NOT_FOUND_ERROR, 0 };
-
-             throw_exception (e);
-           }
-
-         addr = target_get_thread_local_address (ptid, lm_addr, offset);
-       }
-      /* If an error occurred, print TLS related messages here.  Otherwise,
-         throw the error to some higher catcher.  */
-      if (ex.reason < 0)
-       {
-         int objfile_is_library = (objfile->flags & OBJF_SHARED);
-
-         switch (ex.error)
-           {
-           case TLS_NO_LIBRARY_SUPPORT_ERROR:
-             error (_("Cannot find thread-local variables in this thread library."));
-             break;
-           case TLS_LOAD_MODULE_NOT_FOUND_ERROR:
-             if (objfile_is_library)
-               error (_("Cannot find shared library `%s' in dynamic"
-                        " linker's load module list"), objfile->name);
-             else
-               error (_("Cannot find executable file `%s' in dynamic"
-                        " linker's load module list"), objfile->name);
-             break;
-           case TLS_NOT_ALLOCATED_YET_ERROR:
-             if (objfile_is_library)
-               error (_("The inferior has not yet allocated storage for"
-                        " thread-local variables in\n"
-                        "the shared library `%s'\n"
-                        "for %s"),
-                      objfile->name, target_pid_to_str (ptid));
-             else
-               error (_("The inferior has not yet allocated storage for"
-                        " thread-local variables in\n"
-                        "the executable `%s'\n"
-                        "for %s"),
-                      objfile->name, target_pid_to_str (ptid));
-             break;
-           case TLS_GENERIC_ERROR:
-             if (objfile_is_library)
-               error (_("Cannot find thread-local storage for %s, "
-                        "shared library %s:\n%s"),
-                      target_pid_to_str (ptid),
-                      objfile->name, ex.message);
-             else
-               error (_("Cannot find thread-local storage for %s, "
-                        "executable file %s:\n%s"),
-                      target_pid_to_str (ptid),
-                      objfile->name, ex.message);
-             break;
-           default:
-             throw_exception (ex);
-             break;
-           }
-       }
-    }
-  /* It wouldn't be wrong here to try a gdbarch method, too; finding
-     TLS is an ABI-specific thing.  But we don't do that yet.  */
-  else
-    error (_("Cannot find thread-local variables on this target"));
 
-  return addr;
+  return target_translate_tls_address (debaton->objfile, offset);
 }
 
 /* Evaluate a location description, starting at DATA and with length
@@ -277,7 +188,7 @@ dwarf_expr_tls_address (void *baton, CORE_ADDR offset)
    of FRAME.  */
 static struct value *
 dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
-                         unsigned char *data, unsigned short size,
+                         gdb_byte *data, unsigned short size,
                          struct objfile *objfile)
 {
   struct gdbarch *arch = get_frame_arch (frame);
@@ -305,11 +216,28 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
   dwarf_expr_eval (ctx, data, size);
   if (ctx->num_pieces > 0)
     {
-      /* We haven't implemented splicing together pieces from
-         arbitrary sources yet.  */
-      error (_("The value of variable '%s' is distributed across several\n"
-             "locations, and GDB cannot access its value.\n"),
-             SYMBOL_NATURAL_NAME (var));
+      int i;
+      long offset = 0;
+      bfd_byte *contents;
+
+      retval = allocate_value (SYMBOL_TYPE (var));
+      contents = value_contents_raw (retval);
+      for (i = 0; i < ctx->num_pieces; i++)
+       {
+         struct dwarf_expr_piece *p = &ctx->pieces[i];
+         if (p->in_reg)
+           {
+             bfd_byte regval[MAX_REGISTER_SIZE];
+             int gdb_regnum = DWARF2_REG_TO_REGNUM (p->value);
+             get_frame_register (frame, gdb_regnum, regval);
+             memcpy (contents + offset, regval, p->size);
+           }
+         else /* In memory?  */
+           {
+             read_memory (p->value, contents + offset, p->size);
+           }
+         offset += p->size;
+       }
     }
   else if (ctx->in_reg)
     {
@@ -354,16 +282,16 @@ needs_frame_read_reg (void *baton, int regnum)
 
 /* Reads from memory do not require a frame.  */
 static void
-needs_frame_read_mem (void *baton, char *buf, CORE_ADDR addr, size_t len)
+needs_frame_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, unsigned char **start, size_t * length)
+needs_frame_frame_base (void *baton, gdb_byte **start, size_t * length)
 {
-  static char lit0 = DW_OP_lit0;
+  static gdb_byte lit0 = DW_OP_lit0;
   struct needs_frame_baton *nf_baton = baton;
 
   *start = &lit0;
@@ -385,7 +313,7 @@ needs_frame_tls_address (void *baton, CORE_ADDR offset)
    requires a frame to evaluate.  */
 
 static int
-dwarf2_loc_desc_needs_frame (unsigned char *data, unsigned short size)
+dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size)
 {
   struct needs_frame_baton baton;
   struct dwarf_expr_context *ctx;
@@ -421,8 +349,8 @@ dwarf2_loc_desc_needs_frame (unsigned char *data, unsigned short size)
 }
 
 static void
-dwarf2_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax,
-                          struct axs_value * value, unsigned char *data,
+dwarf2_tracepoint_var_ref (struct symbol *symbol, struct agent_expr *ax,
+                          struct axs_value *value, gdb_byte *data,
                           int size)
 {
   if (size == 0)
@@ -449,7 +377,7 @@ dwarf2_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax,
         as above.  */
       int frame_reg;
       LONGEST frame_offset;
-      unsigned char *buf_end;
+      gdb_byte *buf_end;
 
       buf_end = read_sleb128 (data + 1, data + size, &frame_offset);
       if (buf_end != data + size)
@@ -461,13 +389,30 @@ dwarf2_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax,
       ax_const_l (ax, frame_offset);
       ax_simple (ax, aop_add);
 
-      ax_const_l (ax, frame_offset);
+      value->kind = axs_lvalue_memory;
+    }
+  else if (data[0] >= DW_OP_breg0
+          && data[0] <= DW_OP_breg31)
+    {
+      unsigned int reg;
+      LONGEST offset;
+      gdb_byte *buf_end;
+
+      reg = data[0] - DW_OP_breg0;
+      buf_end = read_sleb128 (data + 1, data + size, &offset);
+      if (buf_end != data + size)
+       error (_("Unexpected opcode after DW_OP_breg%u for symbol \"%s\"."),
+              reg, SYMBOL_PRINT_NAME (symbol));
+
+      ax_reg (ax, reg);
+      ax_const_l (ax, offset);
       ax_simple (ax, aop_add);
+
       value->kind = axs_lvalue_memory;
     }
   else
-    error (_("Unsupported DWARF opcode in the location of \"%s\"."),
-          SYMBOL_PRINT_NAME (symbol));
+    error (_("Unsupported DWARF opcode 0x%x in the location of \"%s\"."),
+          data[0], SYMBOL_PRINT_NAME (symbol));
 }
 \f
 /* Return the value of SYMBOL in FRAME using the DWARF-2 expression
@@ -579,11 +524,12 @@ loclist_read_variable (struct symbol *symbol, struct frame_info *frame)
 {
   struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
   struct value *val;
-  unsigned char *data;
+  gdb_byte *data;
   size_t size;
 
   data = find_location_expression (dlbaton, &size,
-                                  frame ? get_frame_pc (frame) : 0);
+                                  frame ? get_frame_address_in_block (frame)
+                                  : 0);
   if (data == NULL)
     {
       val = allocate_value (SYMBOL_TYPE (symbol));
@@ -626,7 +572,7 @@ loclist_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax,
                            struct axs_value * value)
 {
   struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
-  unsigned char *data;
+  gdb_byte *data;
   size_t size;
 
   data = find_location_expression (dlbaton, &size, ax->scope);
This page took 0.027761 seconds and 4 git commands to generate.