* dwarf2expr.c (execute_stack_op): Handle DW_OP_GNU_const_index.
authorDoug Evans <dje@google.com>
Tue, 19 Jun 2012 00:37:18 +0000 (00:37 +0000)
committerDoug Evans <dje@google.com>
Tue, 19 Jun 2012 00:37:18 +0000 (00:37 +0000)
Adjust address for DW_OP_GNU_addr_index.
* dwarf2expr.h (dwarf_expr_context): Update comment.
* dwarf2loc.c (locexpr_describe_location_piece): New arg per_cu,
all callers updated.  Handle TLS vars described with
DW_OP_GNU_const_index.
(disassemble_dwarf_expression): Handle DW_OP_GNU_addr_index
and DW_OP_GNU_const_index.
* dwarf2read.c (decode_locdesc): Handle DW_OP_GNU_addr_index.

gdb/ChangeLog
gdb/dwarf2expr.c
gdb/dwarf2expr.h
gdb/dwarf2loc.c
gdb/dwarf2read.c

index 821c8d0b91115ee0bb263e57e559165fab1a5b51..78208b7331c66c9b40837502a96a033066ae73c0 100644 (file)
@@ -1,5 +1,15 @@
 2012-06-18  Doug Evans  <dje@google.com>
 
+       * dwarf2expr.c (execute_stack_op): Handle DW_OP_GNU_const_index.
+       Adjust address for DW_OP_GNU_addr_index.
+       * dwarf2expr.h (dwarf_expr_context): Update comment.
+       * dwarf2loc.c (locexpr_describe_location_piece): New arg per_cu,
+       all callers updated.  Handle TLS vars described with
+       DW_OP_GNU_const_index.
+       (disassemble_dwarf_expression): Handle DW_OP_GNU_addr_index
+       and DW_OP_GNU_const_index.
+       * dwarf2read.c (decode_locdesc): Handle DW_OP_GNU_addr_index.
+
        * block.c (find_block_in_blockvector): Make explicit the fact that we
        ignore GLOBAL_BLOCK.
 
index 40ce608731851e886396671911841c3216520340..214b371e569f083bdf9cf98a3cca120e299a4f58 100644 (file)
@@ -725,6 +725,12 @@ execute_stack_op (struct dwarf_expr_context *ctx,
          break;
 
        case DW_OP_GNU_addr_index:
+         op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
+         result = (ctx->funcs->get_addr_index) (ctx->baton, uoffset);
+         result += ctx->offset;
+         result_val = value_from_ulongest (address_type, result);
+         break;
+       case DW_OP_GNU_const_index:
          op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
          result = (ctx->funcs->get_addr_index) (ctx->baton, uoffset);
          result_val = value_from_ulongest (address_type, result);
index da3a5bb054ac5faa8b81eeed0d417e7084e3efe1..db49b9c5cebca1f9bbb2c9085fdd6e08083c0f41 100644 (file)
@@ -158,7 +158,7 @@ struct dwarf_expr_context
      context and operations depending on DW_FORM_ref_addr are not allowed.  */
   int ref_addr_size;
 
-  /* Offset used to relocate DW_OP_addr argument.  */
+  /* Offset used to relocate DW_OP_addr and DW_OP_GNU_addr_index arguments.  */
   CORE_ADDR offset;
 
   /* An opaque argument provided by the caller, which will be passed
index 54dc5ad435b60b74b2975502ceab7c7d0558ddf1..6feeab607c8762a99831d07619557f28d91382a5 100644 (file)
@@ -3293,10 +3293,12 @@ locexpr_regname (struct gdbarch *gdbarch, int dwarf_regnum)
 static const gdb_byte *
 locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
                                 CORE_ADDR addr, struct objfile *objfile,
+                                struct dwarf2_per_cu_data *per_cu,
                                 const gdb_byte *data, const gdb_byte *end,
                                 unsigned int addr_size)
 {
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  size_t leb128_size;
 
   if (data[0] >= DW_OP_reg0 && data[0] <= DW_OP_reg31)
     {
@@ -3416,6 +3418,29 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
 
       data += 1 + addr_size + 1;
     }
+
+  /* With -gsplit-dwarf a TLS variable can also look like this:
+     DW_AT_location    : 3 byte block: fc 4 e0
+                        (DW_OP_GNU_const_index: 4;
+                        DW_OP_GNU_push_tls_address)  */
+  else if (data + 3 <= end
+          && 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
+          && piece_end_p (data + 2 + leb128_size, end))
+    {
+      ULONGEST offset;
+
+      data = safe_read_uleb128 (data + 1, end, &offset);
+      offset = dwarf2_read_addr_index (per_cu, offset);
+      fprintf_filtered (stream, 
+                       _("a thread-local variable at offset 0x%s "
+                         "in the thread-local storage for `%s'"),
+                       phex_nz (offset, addr_size), objfile->name);
+      ++data;
+    }
+
   else if (data[0] >= DW_OP_lit0
           && data[0] <= DW_OP_lit31
           && data + 1 < end
@@ -3771,6 +3796,17 @@ disassemble_dwarf_expression (struct ui_file *stream,
                                        all, per_cu);
          data += ul;
          continue;
+
+       case DW_OP_GNU_addr_index:
+         data = safe_read_uleb128 (data, end, &ul);
+         ul = dwarf2_read_addr_index (per_cu, ul);
+         fprintf_filtered (stream, " 0x%s", phex_nz (ul, addr_size));
+         break;
+       case DW_OP_GNU_const_index:
+         data = safe_read_uleb128 (data, end, &ul);
+         ul = dwarf2_read_addr_index (per_cu, ul);
+         fprintf_filtered (stream, " %s", pulongest (ul));
+         break;
        }
 
       fprintf_filtered (stream, "\n");
@@ -3805,7 +3841,7 @@ locexpr_describe_location_1 (struct symbol *symbol, CORE_ADDR addr,
       if (!dwarf2_always_disassemble)
        {
          data = locexpr_describe_location_piece (symbol, stream,
-                                                 addr, objfile,
+                                                 addr, objfile, per_cu,
                                                  data, end, addr_size);
          /* If we printed anything, or if we have an empty piece,
             then don't disassemble.  */
index 7ac125a20816ac2e109d72c6dcb95076c111a1af..097ee7fbf8826303d53ab92ca75b2edfa18b2150 100644 (file)
@@ -15512,6 +15512,7 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
          break;
 
        case DW_OP_GNU_addr_index:
+       case DW_OP_GNU_const_index:
          stack[++stacki] = read_addr_index_from_leb128 (cu, &data[i],
                                                         &bytes_read);
          i += bytes_read;