gdb: Better support for dynamic properties with negative values
[deliverable/binutils-gdb.git] / gdb / dwarf2loc.c
index 12951f546f88de331501207a1d4ac44cafad7a36..63643cb45d54a8abc4a0bc8a2d3b6c3d1fd51c70 100644 (file)
 #include "dwarf2.h"
 #include "dwarf2expr.h"
 #include "dwarf2loc.h"
+#include "dwarf2read.h"
 #include "dwarf2-frame.h"
 #include "compile/compile.h"
-#include "common/selftest.h"
+#include "gdbsupport/selftest.h"
 #include <algorithm>
 #include <vector>
 #include <unordered_set>
-#include "common/underlying.h"
-#include "common/byte-vector.h"
+#include "gdbsupport/underlying.h"
+#include "gdbsupport/byte-vector.h"
 
 extern int dwarf_always_disassemble;
 
@@ -636,7 +637,7 @@ class dwarf_evaluate_loc_desc : public dwarf_expr_context
   }
 
   /* Callback function for dwarf2_evaluate_loc_desc.
-     Fetch the address indexed by DW_OP_GNU_addr_index.  */
+     Fetch the address indexed by DW_OP_addrx or DW_OP_GNU_addr_index.  */
 
   CORE_ADDR get_addr_index (unsigned int index) override
   {
@@ -1209,7 +1210,7 @@ call_site_find_chain (struct gdbarch *gdbarch, CORE_ADDR caller_pc,
          return NULL;
        }
       else
-       throw_exception (e);
+       throw;
     }
 
   return retval;
@@ -2185,7 +2186,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
          return allocate_optimized_out_value (subobj_type);
        }
       else
-       throw_exception (ex);
+       throw;
     }
 
   if (ctx.pieces.size () > 0)
@@ -2397,7 +2398,7 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
          return 0;
        }
       else
-       throw_exception (ex);
+       throw;
     }
 
   switch (ctx.location)
@@ -2424,14 +2425,14 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
 
 /* See dwarf2loc.h.  */
 
-int
+bool
 dwarf2_evaluate_property (const struct dynamic_prop *prop,
                          struct frame_info *frame,
                          struct property_addr_info *addr_stack,
                          CORE_ADDR *value)
 {
   if (prop == NULL)
-    return 0;
+    return false;
 
   if (frame == NULL && has_stack_frames ())
     frame = get_selected_frame (NULL);
@@ -2442,18 +2443,41 @@ dwarf2_evaluate_property (const struct dynamic_prop *prop,
       {
        const struct dwarf2_property_baton *baton
          = (const struct dwarf2_property_baton *) prop->data.baton;
+       gdb_assert (baton->property_type != NULL);
 
        if (dwarf2_locexpr_baton_eval (&baton->locexpr, frame,
                                       addr_stack ? addr_stack->addr : 0,
                                       value))
          {
-           if (baton->referenced_type)
+           if (baton->locexpr.is_reference)
              {
-               struct value *val = value_at (baton->referenced_type, *value);
-
+               struct value *val = value_at (baton->property_type, *value);
                *value = value_as_address (val);
              }
-           return 1;
+           else
+             {
+               gdb_assert (baton->property_type != NULL);
+
+               struct type *type = check_typedef (baton->property_type);
+               if (TYPE_LENGTH (type) < sizeof (CORE_ADDR)
+                   && !TYPE_UNSIGNED (type))
+                 {
+                   /* If we have a valid return candidate and it's value
+                      is signed, we have to sign-extend the value because
+                      CORE_ADDR on 64bit machine has 8 bytes but address
+                      size of an 32bit application is bytes.  */
+                   const int addr_size
+                     = (dwarf2_per_cu_addr_size (baton->locexpr.per_cu)
+                        * TARGET_CHAR_BIT);
+                   const CORE_ADDR neg_mask
+                     = (~((CORE_ADDR) 0) <<  (addr_size - 1));
+
+                   /* Check if signed bit is set and sign-extend values.  */
+                   if (*value & neg_mask)
+                     *value |= neg_mask;
+                 }
+             }
+           return true;
          }
       }
       break;
@@ -2470,12 +2494,12 @@ dwarf2_evaluate_property (const struct dynamic_prop *prop,
        data = dwarf2_find_location_expression (&baton->loclist, &size, pc);
        if (data != NULL)
          {
-           val = dwarf2_evaluate_loc_desc (baton->referenced_type, frame, data,
+           val = dwarf2_evaluate_loc_desc (baton->property_type, frame, data,
                                            size, baton->loclist.per_cu);
            if (!value_optimized_out (val))
              {
                *value = value_as_address (val);
-               return 1;
+               return true;
              }
          }
       }
@@ -2483,7 +2507,7 @@ dwarf2_evaluate_property (const struct dynamic_prop *prop,
 
     case PROP_CONST:
       *value = prop->data.const_val;
-      return 1;
+      return true;
 
     case PROP_ADDR_OFFSET:
       {
@@ -2493,8 +2517,12 @@ dwarf2_evaluate_property (const struct dynamic_prop *prop,
        struct value *val;
 
        for (pinfo = addr_stack; pinfo != NULL; pinfo = pinfo->next)
-         if (pinfo->type == baton->referenced_type)
-           break;
+         {
+           /* This approach lets us avoid checking the qualifiers.  */
+           if (TYPE_MAIN_TYPE (pinfo->type)
+               == TYPE_MAIN_TYPE (baton->property_type))
+             break;
+         }
        if (pinfo == NULL)
          error (_("cannot find reference address for offset property"));
        if (pinfo->valaddr != NULL)
@@ -2505,11 +2533,11 @@ dwarf2_evaluate_property (const struct dynamic_prop *prop,
          val = value_at (baton->offset_info.type,
                          pinfo->addr + baton->offset_info.offset);
        *value = value_as_address (val);
-       return 1;
+       return true;
       }
     }
 
-  return 0;
+  return false;
 }
 
 /* See dwarf2loc.h.  */
@@ -2642,7 +2670,7 @@ class symbol_needs_eval_context : public dwarf_expr_context
     push_address (0, 0);
   }
 
-  /* DW_OP_GNU_addr_index doesn't require a frame.  */
+  /* DW_OP_addrx and DW_OP_GNU_addr_index doesn't require a frame.  */
 
    CORE_ADDR get_addr_index (unsigned int index) override
    {
@@ -4086,6 +4114,7 @@ disassemble_dwarf_expression (struct ui_file *stream,
          fprintf_filtered (stream, " offset %s", phex_nz (ul, 4));
          break;
 
+       case DW_OP_addrx:
        case DW_OP_GNU_addr_index:
          data = safe_read_uleb128 (data, end, &ul);
          ul = dwarf2_read_addr_index (per_cu, ul);
This page took 0.026846 seconds and 4 git commands to generate.