Support for DW_OP_addrx and DW_FORM_addrx tags

Message ID CAH=Am=6aLScyTBFjNHdBg4KrjkiXrsw1oz7eJE1bhEcbYQdvzA@mail.gmail.com
State New, archived
Headers

Commit Message

Terekhov, Mikhail via Gdb-patches April 4, 2019, 12:50 a.m. UTC
  DW_OP_addrx is the new name of DW_OP_GNU_addr_index, and DW_FORM_addrx
is the name of DW_FORM_addr_index in the Dwarf 5 standard. This is a small
step towards supporting Dwarf 5 in gdb.

Note: I could not find any tests specifically for *_GNU_addr_index, and
I did not add any new tests, please advise.

gdb/ChangeLog:
2019-04-03  Ali Tamur  <tamur@google.com>

        * dwarf2-frame.c(dwarf_expr_executor::get_addr_index): Update
comment
        * dwarf2expr.c(dwarf_expr_context::execute_stack_op): Add
DW_OP_addrx
        * dwarf2expr.h(dwarf_expr_context::offset): Update comment
        (dwarf_expr_context::get_addr_index): Likewise
        * dwarf2loc.c(dwarf_evaluate_loc_desc::get_addr_index): Likewise
        (symbol_needs_eval_context::get_addr_index): Likewise
        (disassemble_dwarf_expression): Add DW_OP_addrx
        * dwarf2read.c(attr_value_as_address): Add DW_FORM_addrx
        (read_cutu_die_from_dwo): Update comment
        (skip_one_die): Add DW_FORM_addrx
        (read_attribute_value): Likewise
        (var_decode_location): Add DW_OP_addrx
        (dwarf2_const_value_attr): Add DW_FORM_addrx
        (dump_die_shallow): Likewise
        (dwarf2_fetch_constant_bytes): Likewise
        (decode_locdesc): Add DW_OP_addrx
        (skip_form_bytes): Add DW_FORM_addrx
---
       if (attr)
@@ -9367,6 +9369,7 @@ skip_one_die (const struct die_reader_specs *reader,
const gdb_byte *info_ptr,
  case DW_FORM_block4:
    info_ptr += 4 + read_4_bytes (abfd, info_ptr);
    break;
+ case DW_FORM_addrx:
  case DW_FORM_sdata:
  case DW_FORM_udata:
  case DW_FORM_ref_udata:
@@ -19217,6 +19220,7 @@ read_attribute_value (const struct die_reader_specs
*reader,
     case DW_FORM_implicit_const:
       DW_SND (attr) = implicit_const;
       break;
+    case DW_FORM_addrx:
     case DW_FORM_GNU_addr_index:
       if (reader->dwo_file == NULL)
  {
@@ -21298,13 +21302,14 @@ var_decode_location (struct attribute *attr,
struct symbol *sym,

   /* Handle one degenerate form of location expression specially, to
      preserve GDB's previous behavior when section offsets are
-     specified.  If this is just a DW_OP_addr or DW_OP_GNU_addr_index
-     then mark this symbol as LOC_STATIC.  */
+     specified.  If this is just a DW_OP_addr, DW_OP_addrx or
+     DW_OP_GNU_addr_index then mark this symbol as LOC_STATIC.  */

   if (attr_form_is_block (attr)
       && ((DW_BLOCK (attr)->data[0] == DW_OP_addr
     && DW_BLOCK (attr)->size == 1 + cu_header->addr_size)
-   || (DW_BLOCK (attr)->data[0] == DW_OP_GNU_addr_index
+   || ((DW_BLOCK (attr)->data[0] == DW_OP_GNU_addr_index
+        || DW_BLOCK (attr)->data[0] == DW_OP_addrx)
        && (DW_BLOCK (attr)->size
    == 1 + leb128_size (&DW_BLOCK (attr)->data[1])))))
     {
@@ -21801,6 +21806,7 @@ dwarf2_const_value_attr (const struct attribute
*attr, struct type *type,
   switch (attr->form)
     {
     case DW_FORM_addr:
+    case DW_FORM_addrx:
     case DW_FORM_GNU_addr_index:
       {
  gdb_byte *data;
@@ -22777,6 +22783,7 @@ dump_die_shallow (struct ui_file *f, int indent,
struct die_info *die)
       switch (die->attrs[i].form)
  {
  case DW_FORM_addr:
+ case DW_FORM_addrx:
  case DW_FORM_GNU_addr_index:
    fprintf_unfiltered (f, "address: ");
    fputs_filtered (hex_string (DW_ADDR (&die->attrs[i])), f);
@@ -23246,6 +23253,7 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
   switch (attr->form)
     {
     case DW_FORM_addr:
+    case DW_FORM_addrx:
     case DW_FORM_GNU_addr_index:
       {
  gdb_byte *tem;
@@ -23850,6 +23858,7 @@ decode_locdesc (struct dwarf_block *blk, struct
dwarf2_cu *cu)
  case DW_OP_GNU_uninit:
    break;

+ case DW_OP_addrx:
  case DW_OP_GNU_addr_index:
  case DW_OP_GNU_const_index:
    stack[++stacki] = read_addr_index_from_leb128 (cu, &data[i],
@@ -24220,6 +24229,7 @@ skip_form_bytes (bfd *abfd, const gdb_byte *bytes,
const gdb_byte *buffer_end,
       bytes += 4 + read_4_bytes (abfd, bytes);
       break;

+    case DW_FORM_addrx:
     case DW_FORM_sdata:
     case DW_FORM_udata:
     case DW_FORM_GNU_addr_index:
  

Comments

Terekhov, Mikhail via Gdb-patches April 8, 2019, 8:04 p.m. UTC | #1
Friendly ping.

On Wed, Apr 3, 2019 at 5:50 PM Ali Tamur <tamur@google.com> wrote:

>
> DW_OP_addrx is the new name of DW_OP_GNU_addr_index, and DW_FORM_addrx
> is the name of DW_FORM_addr_index in the Dwarf 5 standard. This is a small
> step towards supporting Dwarf 5 in gdb.
>
> Note: I could not find any tests specifically for *_GNU_addr_index, and
> I did not add any new tests, please advise.
>
> gdb/ChangeLog:
> 2019-04-03  Ali Tamur  <tamur@google.com>
>
>         * dwarf2-frame.c(dwarf_expr_executor::get_addr_index): Update
> comment
>         * dwarf2expr.c(dwarf_expr_context::execute_stack_op): Add
> DW_OP_addrx
>         * dwarf2expr.h(dwarf_expr_context::offset): Update comment
>         (dwarf_expr_context::get_addr_index): Likewise
>         * dwarf2loc.c(dwarf_evaluate_loc_desc::get_addr_index): Likewise
>         (symbol_needs_eval_context::get_addr_index): Likewise
>         (disassemble_dwarf_expression): Add DW_OP_addrx
>         * dwarf2read.c(attr_value_as_address): Add DW_FORM_addrx
>         (read_cutu_die_from_dwo): Update comment
>         (skip_one_die): Add DW_FORM_addrx
>         (read_attribute_value): Likewise
>         (var_decode_location): Add DW_OP_addrx
>         (dwarf2_const_value_attr): Add DW_FORM_addrx
>         (dump_die_shallow): Likewise
>         (dwarf2_fetch_constant_bytes): Likewise
>         (decode_locdesc): Add DW_OP_addrx
>         (skip_form_bytes): Add DW_FORM_addrx
> ---
> diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
> index 178ac44ecb..8223050d2c 100644
> --- a/gdb/dwarf2-frame.c
> +++ b/gdb/dwarf2-frame.c
> @@ -290,7 +290,7 @@ class dwarf_expr_executor : public dwarf_expr_context
>
>    CORE_ADDR get_addr_index (unsigned int index) override
>    {
> -    invalid ("DW_OP_GNU_addr_index");
> +    invalid ("DW_OP_addrx or DW_OP_GNU_addr_index");
>    }
>
>   private:
> diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c
> index e412e182c0..3bd9abc440 100644
> --- a/gdb/dwarf2expr.c
> +++ b/gdb/dwarf2expr.c
> @@ -634,6 +634,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte
> *op_ptr,
>     result_val = value_from_ulongest (address_type, result);
>     break;
>
> + case DW_OP_addrx:
>   case DW_OP_GNU_addr_index:
>     op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
>     result = this->get_addr_index (uoffset);
> diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h
> index c7cbf32d5e..4f6231faea 100644
> --- a/gdb/dwarf2expr.h
> +++ b/gdb/dwarf2expr.h
> @@ -139,7 +139,8 @@ 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 and DW_OP_GNU_addr_index
> arguments.  */
> +  /* Offset used to relocate DW_OP_addr, DW_OP_addrx, and
> DW_OP_GNU_addr_index
> +     arguments.  */
>    CORE_ADDR offset;
>
>    /* The current depth of dwarf expression recursion, via DW_OP_call*,
> @@ -242,7 +243,7 @@ struct dwarf_expr_context
>      union call_site_parameter_u kind_u,
>      int deref_size) = 0;
>
> -  /* Return the address indexed by DW_OP_GNU_addr_index.
> +  /* Return the address indexed by DW_OP_addrx or DW_OP_GNU_addr_index.
>       This can throw an exception if the index is out of range.  */
>    virtual CORE_ADDR get_addr_index (unsigned int index) = 0;
>
> diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
> index 29d289b4d0..01d8cbfc63 100644
> --- a/gdb/dwarf2loc.c
> +++ b/gdb/dwarf2loc.c
> @@ -636,7 +636,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
>    {
> @@ -2645,7 +2645,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
>     {
> @@ -4089,6 +4089,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);
> diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
> index 658c86264b..1aac47174d 100644
> --- a/gdb/dwarf2read.c
> +++ b/gdb/dwarf2read.c
> @@ -2134,7 +2134,8 @@ attr_value_as_address (struct attribute *attr)
>  {
>    CORE_ADDR addr;
>
> -  if (attr->form != DW_FORM_addr && attr->form != DW_FORM_GNU_addr_index)
> +  if (attr->form != DW_FORM_addr && attr->form != DW_FORM_addrx
> +      && attr->form != DW_FORM_GNU_addr_index)
>      {
>        /* Aside from a few clearly defined exceptions, attributes that
>   contain an address must always be in DW_FORM_addr form.
> @@ -7230,7 +7231,8 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data
> *this_cu,
>        comp_dir = dwarf2_attr (stub_comp_unit_die, DW_AT_comp_dir, cu);
>
>        /* There should be a DW_AT_addr_base attribute here (if needed).
> - We need the value before we can process DW_FORM_GNU_addr_index.  */
> + We need the value before we can process DW_FORM_GNU_addr_index or
> +         DW_FORM_addrx.  */
>        cu->addr_base = 0;
>        attr = dwarf2_attr (stub_comp_unit_die, DW_AT_GNU_addr_base, cu);
>        if (attr)
> @@ -9367,6 +9369,7 @@ skip_one_die (const struct die_reader_specs *reader,
> const gdb_byte *info_ptr,
>   case DW_FORM_block4:
>     info_ptr += 4 + read_4_bytes (abfd, info_ptr);
>     break;
> + case DW_FORM_addrx:
>   case DW_FORM_sdata:
>   case DW_FORM_udata:
>   case DW_FORM_ref_udata:
> @@ -19217,6 +19220,7 @@ read_attribute_value (const struct
> die_reader_specs *reader,
>      case DW_FORM_implicit_const:
>        DW_SND (attr) = implicit_const;
>        break;
> +    case DW_FORM_addrx:
>      case DW_FORM_GNU_addr_index:
>        if (reader->dwo_file == NULL)
>   {
> @@ -21298,13 +21302,14 @@ var_decode_location (struct attribute *attr,
> struct symbol *sym,
>
>    /* Handle one degenerate form of location expression specially, to
>       preserve GDB's previous behavior when section offsets are
> -     specified.  If this is just a DW_OP_addr or DW_OP_GNU_addr_index
> -     then mark this symbol as LOC_STATIC.  */
> +     specified.  If this is just a DW_OP_addr, DW_OP_addrx or
> +     DW_OP_GNU_addr_index then mark this symbol as LOC_STATIC.  */
>
>    if (attr_form_is_block (attr)
>        && ((DW_BLOCK (attr)->data[0] == DW_OP_addr
>      && DW_BLOCK (attr)->size == 1 + cu_header->addr_size)
> -   || (DW_BLOCK (attr)->data[0] == DW_OP_GNU_addr_index
> +   || ((DW_BLOCK (attr)->data[0] == DW_OP_GNU_addr_index
> +        || DW_BLOCK (attr)->data[0] == DW_OP_addrx)
>         && (DW_BLOCK (attr)->size
>     == 1 + leb128_size (&DW_BLOCK (attr)->data[1])))))
>      {
> @@ -21801,6 +21806,7 @@ dwarf2_const_value_attr (const struct attribute
> *attr, struct type *type,
>    switch (attr->form)
>      {
>      case DW_FORM_addr:
> +    case DW_FORM_addrx:
>      case DW_FORM_GNU_addr_index:
>        {
>   gdb_byte *data;
> @@ -22777,6 +22783,7 @@ dump_die_shallow (struct ui_file *f, int indent,
> struct die_info *die)
>        switch (die->attrs[i].form)
>   {
>   case DW_FORM_addr:
> + case DW_FORM_addrx:
>   case DW_FORM_GNU_addr_index:
>     fprintf_unfiltered (f, "address: ");
>     fputs_filtered (hex_string (DW_ADDR (&die->attrs[i])), f);
> @@ -23246,6 +23253,7 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
>    switch (attr->form)
>      {
>      case DW_FORM_addr:
> +    case DW_FORM_addrx:
>      case DW_FORM_GNU_addr_index:
>        {
>   gdb_byte *tem;
> @@ -23850,6 +23858,7 @@ decode_locdesc (struct dwarf_block *blk, struct
> dwarf2_cu *cu)
>   case DW_OP_GNU_uninit:
>     break;
>
> + case DW_OP_addrx:
>   case DW_OP_GNU_addr_index:
>   case DW_OP_GNU_const_index:
>     stack[++stacki] = read_addr_index_from_leb128 (cu, &data[i],
> @@ -24220,6 +24229,7 @@ skip_form_bytes (bfd *abfd, const gdb_byte *bytes,
> const gdb_byte *buffer_end,
>        bytes += 4 + read_4_bytes (abfd, bytes);
>        break;
>
> +    case DW_FORM_addrx:
>      case DW_FORM_sdata:
>      case DW_FORM_udata:
>      case DW_FORM_GNU_addr_index:
>
>
  
Tom Tromey April 8, 2019, 8:27 p.m. UTC | #2
>>>>> "Ali" == Ali Tamur via gdb-patches <gdb-patches@sourceware.org> writes:

Ali> DW_OP_addrx is the new name of DW_OP_GNU_addr_index, and DW_FORM_addrx
Ali> is the name of DW_FORM_addr_index in the Dwarf 5 standard. This is a small
Ali> step towards supporting Dwarf 5 in gdb.

Thanks for doing this.

The patch seemed to be a bit mangled by some mailer somewhere.  However,
it looks fine to me.

Do you have commit access to gdb?  If not, contact me off-list to set up
write-after-approval permission.

Ali> Note: I could not find any tests specifically for *_GNU_addr_index, and
Ali> I did not add any new tests, please advise.

I think this stuff was previously tested by using the script
gdb/contrib/cc-with-tweaks.sh.  Also see gdb/testsuite/boards/cc-with-tweaks.exp
and maybe gdb/testsuite/boards/fission.exp (?).

Tom
  

Patch

diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index 178ac44ecb..8223050d2c 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -290,7 +290,7 @@  class dwarf_expr_executor : public dwarf_expr_context

   CORE_ADDR get_addr_index (unsigned int index) override
   {
-    invalid ("DW_OP_GNU_addr_index");
+    invalid ("DW_OP_addrx or DW_OP_GNU_addr_index");
   }

  private:
diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c
index e412e182c0..3bd9abc440 100644
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -634,6 +634,7 @@  dwarf_expr_context::execute_stack_op (const gdb_byte
*op_ptr,
    result_val = value_from_ulongest (address_type, result);
    break;

+ case DW_OP_addrx:
  case DW_OP_GNU_addr_index:
    op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
    result = this->get_addr_index (uoffset);
diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h
index c7cbf32d5e..4f6231faea 100644
--- a/gdb/dwarf2expr.h
+++ b/gdb/dwarf2expr.h
@@ -139,7 +139,8 @@  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 and DW_OP_GNU_addr_index
arguments.  */
+  /* Offset used to relocate DW_OP_addr, DW_OP_addrx, and
DW_OP_GNU_addr_index
+     arguments.  */
   CORE_ADDR offset;

   /* The current depth of dwarf expression recursion, via DW_OP_call*,
@@ -242,7 +243,7 @@  struct dwarf_expr_context
     union call_site_parameter_u kind_u,
     int deref_size) = 0;

-  /* Return the address indexed by DW_OP_GNU_addr_index.
+  /* Return the address indexed by DW_OP_addrx or DW_OP_GNU_addr_index.
      This can throw an exception if the index is out of range.  */
   virtual CORE_ADDR get_addr_index (unsigned int index) = 0;

diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 29d289b4d0..01d8cbfc63 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -636,7 +636,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
   {
@@ -2645,7 +2645,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
    {
@@ -4089,6 +4089,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);
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 658c86264b..1aac47174d 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -2134,7 +2134,8 @@  attr_value_as_address (struct attribute *attr)
 {
   CORE_ADDR addr;

-  if (attr->form != DW_FORM_addr && attr->form != DW_FORM_GNU_addr_index)
+  if (attr->form != DW_FORM_addr && attr->form != DW_FORM_addrx
+      && attr->form != DW_FORM_GNU_addr_index)
     {
       /* Aside from a few clearly defined exceptions, attributes that
  contain an address must always be in DW_FORM_addr form.
@@ -7230,7 +7231,8 @@  read_cutu_die_from_dwo (struct dwarf2_per_cu_data
*this_cu,
       comp_dir = dwarf2_attr (stub_comp_unit_die, DW_AT_comp_dir, cu);

       /* There should be a DW_AT_addr_base attribute here (if needed).
- We need the value before we can process DW_FORM_GNU_addr_index.  */
+ We need the value before we can process DW_FORM_GNU_addr_index or
+         DW_FORM_addrx.  */
       cu->addr_base = 0;
       attr = dwarf2_attr (stub_comp_unit_die, DW_AT_GNU_addr_base, cu);