* defs.h (extract_signed_integer, extract_unsigned_integer,
[deliverable/binutils-gdb.git] / gdb / dwarf2loc.c
index 81b2f8701abc90642b360f18f6094072843a27bd..7a54f436ab53c6a901aff143a0b825c6fb8b84d6 100644 (file)
@@ -1,6 +1,6 @@
 /* DWARF 2 location expression support for GDB.
 
-   Copyright (C) 2003, 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
 
    Contributed by Daniel Jacobowitz, MontaVista Software, Inc.
 
 #include "regcache.h"
 #include "objfiles.h"
 #include "exceptions.h"
+#include "block.h"
 
 #include "elf/dwarf2.h"
 #include "dwarf2expr.h"
 #include "dwarf2loc.h"
 
 #include "gdb_string.h"
+#include "gdb_assert.h"
 
 /* A helper function for dealing with location lists.  Given a
    symbol baton (BATON) and a pc value (PC), find the appropriate
@@ -53,11 +55,14 @@ find_location_expression (struct dwarf2_loclist_baton *baton,
   CORE_ADDR low, high;
   gdb_byte *loc_ptr, *buf_end;
   int length;
-  unsigned int addr_size = gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT;
+  struct objfile *objfile = dwarf2_per_cu_objfile (baton->per_cu);
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  unsigned int addr_size = dwarf2_per_cu_addr_size (baton->per_cu);
   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,
-                                   SECT_OFF_TEXT (baton->objfile));
+  CORE_ADDR base_offset = ANOFFSET (objfile->section_offsets,
+                                   SECT_OFF_TEXT (objfile));
   CORE_ADDR base_address = baton->base_address + base_offset;
 
   loc_ptr = baton->data;
@@ -65,10 +70,10 @@ find_location_expression (struct dwarf2_loclist_baton *baton,
 
   while (1)
     {
-      low = dwarf2_read_address (loc_ptr, buf_end, &length);
-      loc_ptr += length;
-      high = dwarf2_read_address (loc_ptr, buf_end, &length);
-      loc_ptr += length;
+      low = dwarf2_read_address (gdbarch, loc_ptr, buf_end, addr_size);
+      loc_ptr += addr_size;
+      high = dwarf2_read_address (gdbarch, loc_ptr, buf_end, addr_size);
+      loc_ptr += addr_size;
 
       /* An end-of-list entry.  */
       if (low == 0 && high == 0)
@@ -85,7 +90,7 @@ find_location_expression (struct dwarf2_loclist_baton *baton,
       low += base_address;
       high += base_address;
 
-      length = extract_unsigned_integer (loc_ptr, 2);
+      length = extract_unsigned_integer (loc_ptr, 2, byte_order);
       loc_ptr += 2;
 
       if (pc >= low && pc < high)
@@ -114,11 +119,12 @@ static CORE_ADDR
 dwarf_expr_read_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;
 
-  regnum = gdbarch_dwarf2_reg_to_regnum (current_gdbarch, dwarf_regnum);
-  result = address_from_register (builtin_type_void_data_ptr,
+  regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_regnum);
+  result = address_from_register (builtin_type (gdbarch)->builtin_data_ptr,
                                  regnum, debaton->frame);
   return result;
 }
@@ -143,9 +149,19 @@ dwarf_expr_frame_base (void *baton, gdb_byte **start, size_t * length)
   struct symbol *framefunc;
   struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
 
-  framefunc = get_frame_function (debaton->frame);
+  /* Use block_linkage_function, which returns a real (not inlined)
+     function, instead of get_frame_function, which may return an
+     inlined function.  */
+  framefunc = block_linkage_function (get_frame_block (debaton->frame, NULL));
+
+  /* If we found a frame-relative symbol then it was certainly within
+     some function associated with a frame. If we can't find the frame,
+     something has gone wrong.  */
+  gdb_assert (framefunc != NULL);
 
-  if (SYMBOL_OPS (framefunc) == &dwarf2_loclist_funcs)
+  if (SYMBOL_LOCATION_BATON (framefunc) == NULL)
+    *start = NULL;
+  else if (SYMBOL_COMPUTED_OPS (framefunc) == &dwarf2_loclist_funcs)
     {
       struct dwarf2_loclist_baton *symbaton;
       struct frame_info *frame = debaton->frame;
@@ -158,8 +174,13 @@ dwarf_expr_frame_base (void *baton, gdb_byte **start, size_t * length)
     {
       struct dwarf2_locexpr_baton *symbaton;
       symbaton = SYMBOL_LOCATION_BATON (framefunc);
-      *length = symbaton->size;
-      *start = symbaton->data;
+      if (symbaton != NULL)
+       {
+         *length = symbaton->size;
+         *start = symbaton->data;
+       }
+      else
+       *start = NULL;
     }
 
   if (*start == NULL)
@@ -183,9 +204,8 @@ dwarf_expr_tls_address (void *baton, CORE_ADDR offset)
 static struct value *
 dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
                          gdb_byte *data, unsigned short size,
-                         struct objfile *objfile)
+                         struct dwarf2_per_cu_data *per_cu)
 {
-  struct gdbarch *arch = get_frame_arch (frame);
   struct value *retval;
   struct dwarf_expr_baton baton;
   struct dwarf_expr_context *ctx;
@@ -199,9 +219,11 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
     }
 
   baton.frame = frame;
-  baton.objfile = objfile;
+  baton.objfile = dwarf2_per_cu_objfile (per_cu);
 
   ctx = new_dwarf_expr_context ();
+  ctx->gdbarch = get_objfile_arch (baton.objfile);
+  ctx->addr_size = dwarf2_per_cu_addr_size (per_cu);
   ctx->baton = &baton;
   ctx->read_reg = dwarf_expr_read_reg;
   ctx->read_mem = dwarf_expr_read_mem;
@@ -222,9 +244,9 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
          struct dwarf_expr_piece *p = &ctx->pieces[i];
          if (p->in_reg)
            {
+             struct gdbarch *arch = get_frame_arch (frame);
              bfd_byte regval[MAX_REGISTER_SIZE];
-             int gdb_regnum = gdbarch_dwarf2_reg_to_regnum
-                                (current_gdbarch, p->value);
+             int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->value);
              get_frame_register (frame, gdb_regnum, regval);
              memcpy (contents + offset, regval, p->size);
            }
@@ -237,9 +259,9 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
     }
   else if (ctx->in_reg)
     {
+      struct gdbarch *arch = get_frame_arch (frame);
       CORE_ADDR dwarf_regnum = dwarf_expr_fetch (ctx, 0);
-      int gdb_regnum = gdbarch_dwarf2_reg_to_regnum
-                        (current_gdbarch, dwarf_regnum);
+      int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, dwarf_regnum);
       retval = value_from_register (SYMBOL_TYPE (var), gdb_regnum, frame);
     }
   else
@@ -249,7 +271,7 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
       retval = allocate_value (SYMBOL_TYPE (var));
       VALUE_LVAL (retval) = lval_memory;
       set_value_lazy (retval, 1);
-      VALUE_ADDRESS (retval) = address;
+      set_value_address (retval, address);
     }
 
   set_value_initialized (retval, ctx->initialized);
@@ -312,7 +334,8 @@ needs_frame_tls_address (void *baton, CORE_ADDR offset)
    requires a frame to evaluate.  */
 
 static int
-dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size)
+dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
+                            struct dwarf2_per_cu_data *per_cu)
 {
   struct needs_frame_baton baton;
   struct dwarf_expr_context *ctx;
@@ -321,6 +344,8 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size)
   baton.needs_frame = 0;
 
   ctx = new_dwarf_expr_context ();
+  ctx->gdbarch = get_objfile_arch (dwarf2_per_cu_objfile (per_cu));
+  ctx->addr_size = dwarf2_per_cu_addr_size (per_cu);
   ctx->baton = &baton;
   ctx->read_reg = needs_frame_read_reg;
   ctx->read_mem = needs_frame_read_mem;
@@ -348,9 +373,9 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size)
 }
 
 static void
-dwarf2_tracepoint_var_ref (struct symbol *symbol, struct agent_expr *ax,
-                          struct axs_value *value, gdb_byte *data,
-                          int size)
+dwarf2_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
+                          struct agent_expr *ax, struct axs_value *value,
+                          gdb_byte *data, int size)
 {
   if (size == 0)
     error (_("Symbol \"%s\" has been optimized out."),
@@ -383,7 +408,7 @@ dwarf2_tracepoint_var_ref (struct symbol *symbol, struct agent_expr *ax,
        error (_("Unexpected opcode after DW_OP_fbreg for symbol \"%s\"."),
               SYMBOL_PRINT_NAME (symbol));
 
-      gdbarch_virtual_frame_pointer (current_gdbarch, 
+      gdbarch_virtual_frame_pointer (gdbarch,
                                     ax->scope, &frame_reg, &frame_offset);
       ax_reg (ax, frame_reg);
       ax_const_l (ax, frame_offset);
@@ -423,7 +448,7 @@ locexpr_read_variable (struct symbol *symbol, struct frame_info *frame)
   struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
   struct value *val;
   val = dwarf2_evaluate_loc_desc (symbol, frame, dlbaton->data, dlbaton->size,
-                                 dlbaton->objfile);
+                                 dlbaton->per_cu);
 
   return val;
 }
@@ -433,7 +458,8 @@ static int
 locexpr_read_needs_frame (struct symbol *symbol)
 {
   struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
-  return dwarf2_loc_desc_needs_frame (dlbaton->data, dlbaton->size);
+  return dwarf2_loc_desc_needs_frame (dlbaton->data, dlbaton->size,
+                                     dlbaton->per_cu);
 }
 
 /* Print a natural-language description of SYMBOL to STREAM.  */
@@ -442,16 +468,19 @@ locexpr_describe_location (struct symbol *symbol, struct ui_file *stream)
 {
   /* FIXME: be more extensive.  */
   struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
+  int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
 
   if (dlbaton->size == 1
       && dlbaton->data[0] >= DW_OP_reg0
       && dlbaton->data[0] <= DW_OP_reg31)
     {
-      int regno = gdbarch_dwarf2_reg_to_regnum
-                   (current_gdbarch, dlbaton->data[0] - DW_OP_reg0);
+      struct objfile *objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
+      struct gdbarch *gdbarch = get_objfile_arch (objfile);
+      int regno = gdbarch_dwarf2_reg_to_regnum (gdbarch,
+                                               dlbaton->data[0] - DW_OP_reg0);
       fprintf_filtered (stream,
                        "a variable in register %s",
-                       gdbarch_register_name (current_gdbarch, regno));
+                       gdbarch_register_name (gdbarch, regno));
       return 1;
     }
 
@@ -471,14 +500,16 @@ locexpr_describe_location (struct symbol *symbol, struct ui_file *stream)
       && dlbaton->data[dlbaton->size - 1] == DW_OP_GNU_push_tls_address)
     if (dlbaton->data[0] == DW_OP_addr)
       {
-       int bytes_read;
-       CORE_ADDR offset = dwarf2_read_address (&dlbaton->data[1],
+       struct objfile *objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
+       struct gdbarch *gdbarch = get_objfile_arch (objfile);
+       CORE_ADDR offset = dwarf2_read_address (gdbarch,
+                                               &dlbaton->data[1],
                                                &dlbaton->data[dlbaton->size - 1],
-                                               &bytes_read);
+                                               addr_size);
        fprintf_filtered (stream, 
                          "a thread-local variable at offset %s in the "
                          "thread-local storage for `%s'",
-                         paddr_nz (offset), dlbaton->objfile->name);
+                         paddress (gdbarch, offset), objfile->name);
        return 1;
       }
   
@@ -498,17 +529,18 @@ locexpr_describe_location (struct symbol *symbol, struct ui_file *stream)
    against.  When there is one this function should be revisited.  */
 
 static void
-locexpr_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax,
-                           struct axs_value * value)
+locexpr_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
+                           struct agent_expr *ax, struct axs_value *value)
 {
   struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
 
-  dwarf2_tracepoint_var_ref (symbol, ax, value, dlbaton->data, dlbaton->size);
+  dwarf2_tracepoint_var_ref (symbol, gdbarch, ax, value,
+                            dlbaton->data, dlbaton->size);
 }
 
 /* The set of location functions used with the DWARF-2 expression
    evaluator.  */
-const struct symbol_ops dwarf2_locexpr_funcs = {
+const struct symbol_computed_ops dwarf2_locexpr_funcs = {
   locexpr_read_variable,
   locexpr_read_needs_frame,
   locexpr_describe_location,
@@ -540,7 +572,7 @@ loclist_read_variable (struct symbol *symbol, struct frame_info *frame)
     }
   else
     val = dwarf2_evaluate_loc_desc (symbol, frame, data, size,
-                                   dlbaton->objfile);
+                                   dlbaton->per_cu);
 
   return val;
 }
@@ -570,8 +602,8 @@ loclist_describe_location (struct symbol *symbol, struct ui_file *stream)
 /* Describe the location of SYMBOL as an agent value in VALUE, generating
    any necessary bytecode in AX.  */
 static void
-loclist_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax,
-                           struct axs_value * value)
+loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
+                           struct agent_expr *ax, struct axs_value *value)
 {
   struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
   gdb_byte *data;
@@ -581,12 +613,12 @@ loclist_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax,
   if (data == NULL)
     error (_("Variable \"%s\" is not available."), SYMBOL_NATURAL_NAME (symbol));
 
-  dwarf2_tracepoint_var_ref (symbol, ax, value, data, size);
+  dwarf2_tracepoint_var_ref (symbol, gdbarch, ax, value, data, size);
 }
 
 /* The set of location functions used with the DWARF-2 expression
    evaluator and location lists.  */
-const struct symbol_ops dwarf2_loclist_funcs = {
+const struct symbol_computed_ops dwarf2_loclist_funcs = {
   loclist_read_variable,
   loclist_read_needs_frame,
   loclist_describe_location,
This page took 0.034252 seconds and 4 git commands to generate.