From: Zoran Zaric <zoran.zaric@amd.com>
To: <gdb-patches@sourceware.org>
Subject: [PATCH v4 06/28] Add read method to location description classes
Date: Fri, 5 Nov 2021 11:38:27 +0000 [thread overview]
Message-ID: <20211105113849.118800-7-zoran.zaric@amd.com> (raw)
In-Reply-To: <20211105113849.118800-1-zoran.zaric@amd.com>
From: Zoran Zaric <Zoran.Zaric@amd.com>
After adding the interface for register and memory location access, a
new method for reading from any location derived from a dwarf_location
class, can now be defined.
In the case of implicit pointer location description the existing
indirect_synthetic_pointer interface requiers a type of the pointer
to be specified, so for a generic read interface the only type that
makes sense is the DWARF generic type. This means that the existing
address_type method of a dwarf_expr_context class needs to be exposed
outside of that class.
gdb/ChangeLog:
* dwarf2/expr.c (dwarf_location::read): New method.
(dwarf_undefined::read): New method.
(dwarf_memory::read): New method.
(dwarf_register::read): New method.
(dwarf_implicit::read): New method.
(dwarf_implicit_pointer::read): New method.
(dwarf_composite::read): New method.
(dwarf_expr_context::address_type): Change to use the new
address_type function.
(address_type): New function.
---
gdb/dwarf2/expr.c | 305 ++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 284 insertions(+), 21 deletions(-)
diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index e9e5e55ca61..f2349208412 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -279,6 +279,36 @@ write_to_memory (CORE_ADDR address, const gdb_byte *buffer,
length, buffer);
}
+/* Return the type used for DWARF operations where the type is
+ generic in the DWARF spec, the ARCH is a target architecture
+ of the type and ADDR_SIZE is expected size of the address.
+ Only certain sizes are supported. */
+
+static type *
+address_type (gdbarch *arch, int addr_size)
+{
+ dwarf_gdbarch_types *types
+ = (dwarf_gdbarch_types *) gdbarch_data (arch, dwarf_arch_cookie);
+ int ndx;
+
+ if (addr_size == 2)
+ ndx = 0;
+ else if (addr_size == 4)
+ ndx = 1;
+ else if (addr_size == 8)
+ ndx = 2;
+ else
+ error (_("Unsupported address size in DWARF expressions: %d bits"),
+ HOST_CHAR_BIT * addr_size);
+
+ if (types->dw_types[ndx] == nullptr)
+ types->dw_types[ndx]
+ = arch_integer_type (arch, HOST_CHAR_BIT * addr_size,
+ 0, "<signed DWARF address type>");
+
+ return types->dw_types[ndx];
+}
+
class dwarf_location;
class dwarf_value;
@@ -340,6 +370,27 @@ class dwarf_location : public dwarf_entry
ill_formed_expression ();
}
+ /* Read contents from the described location.
+
+ The read operation is performed in the context of a FRAME.
+ BIT_SIZE is the number of bits to read. The data read is copied
+ to the caller-managed buffer BUF. BIG_ENDIAN defines the
+ endianness of the target. BITS_TO_SKIP is a bit offset into the
+ location and BUF_BIT_OFFSET is buffer BUF's bit offset.
+ LOCATION_BIT_LIMIT is a maximum number of bits that location can
+ hold, where value zero signifies that there is no such
+ restriction.
+
+ Note that some location types can be read without a FRAME context.
+
+ If the location is optimized out or unavailable, the OPTIMIZED and
+ UNAVAILABLE outputs are set accordingly. */
+ virtual void read (frame_info *frame, gdb_byte *buf,
+ int buf_bit_offset, size_t bit_size,
+ LONGEST bits_to_skip, size_t location_bit_limit,
+ bool big_endian, int *optimized,
+ int *unavailable) const = 0;
+
protected:
/* Architecture of the location. */
gdbarch *m_arch;
@@ -422,6 +473,14 @@ class dwarf_undefined final : public dwarf_location
dwarf_undefined (gdbarch *arch)
: dwarf_location (arch, 0)
{}
+
+ void read (frame_info *frame, gdb_byte *buf, int buf_bit_offset,
+ size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit,
+ bool big_endian, int *optimized, int *unavailable) const override
+ {
+ *unavailable = 0;
+ *optimized = 1;
+ }
};
class dwarf_memory final : public dwarf_location
@@ -438,6 +497,11 @@ class dwarf_memory final : public dwarf_location
dwarf_value_up to_value (struct type *type) const override;
+ void read (frame_info *frame, gdb_byte *buf, int buf_bit_offset,
+ size_t bit_size, LONGEST bits_to_skip,
+ size_t location_bit_limit, bool big_endian,
+ int *optimized, int *unavailable) const override;
+
private:
/* True if the location belongs to a stack memory region. */
bool m_stack;
@@ -464,6 +528,46 @@ dwarf_memory::to_value (struct type *type) const
return make_unique<dwarf_value> (m_offset, type);
}
+void
+dwarf_memory::read (frame_info *frame, gdb_byte *buf,
+ int buf_bit_offset, size_t bit_size,
+ LONGEST bits_to_skip, size_t location_bit_limit,
+ bool big_endian, int *optimized, int *unavailable) const
+{
+ LONGEST total_bits_to_skip = bits_to_skip;
+ CORE_ADDR start_address
+ = m_offset + (m_bit_suboffset + total_bits_to_skip) / HOST_CHAR_BIT;
+ gdb::byte_vector temp_buf;
+
+ *optimized = 0;
+ total_bits_to_skip += m_bit_suboffset;
+
+ if (total_bits_to_skip % HOST_CHAR_BIT == 0
+ && bit_size % HOST_CHAR_BIT == 0
+ && buf_bit_offset % HOST_CHAR_BIT == 0)
+ {
+ /* Everything is byte-aligned, no buffer needed. */
+ read_from_memory (start_address,
+ buf + buf_bit_offset / HOST_CHAR_BIT,
+ bit_size / HOST_CHAR_BIT, m_stack, unavailable);
+ }
+ else
+ {
+ LONGEST this_size = bits_to_bytes (total_bits_to_skip, bit_size);
+ temp_buf.resize (this_size);
+
+ /* Can only read from memory on byte granularity so an
+ additional buffer is required. */
+ read_from_memory (start_address, temp_buf.data (), this_size,
+ m_stack, unavailable);
+
+ if (!*unavailable)
+ copy_bitwise (buf, buf_bit_offset, temp_buf.data (),
+ total_bits_to_skip % HOST_CHAR_BIT,
+ bit_size, big_endian);
+ }
+}
+
/* Register location description entry. */
class dwarf_register final : public dwarf_location
@@ -473,11 +577,56 @@ class dwarf_register final : public dwarf_location
: dwarf_location (arch, offset), m_regnum (regnum)
{}
+ void read (frame_info *frame, gdb_byte *buf, int buf_bit_offset,
+ size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit,
+ bool big_endian, int *optimized, int *unavailable) const override;
+
private:
/* DWARF register number. */
unsigned int m_regnum;
};
+void
+dwarf_register::read (frame_info *frame, gdb_byte *buf,
+ int buf_bit_offset, size_t bit_size,
+ LONGEST bits_to_skip, size_t location_bit_limit,
+ bool big_endian, int *optimized, int *unavailable) const
+{
+ LONGEST total_bits_to_skip = bits_to_skip;
+ size_t read_bit_limit = location_bit_limit;
+ gdbarch *frame_arch = get_frame_arch (frame);
+ int reg = dwarf_reg_to_regnum_or_error (frame_arch, m_regnum);
+ ULONGEST reg_bits = HOST_CHAR_BIT * register_size (frame_arch, reg);
+ gdb::byte_vector temp_buf;
+
+ if (big_endian)
+ {
+ if (!read_bit_limit || reg_bits <= read_bit_limit)
+ read_bit_limit = bit_size;
+
+ total_bits_to_skip += reg_bits - (m_offset * HOST_CHAR_BIT
+ + m_bit_suboffset + read_bit_limit);
+ }
+ else
+ total_bits_to_skip += m_offset * HOST_CHAR_BIT + m_bit_suboffset;
+
+ LONGEST this_size = bits_to_bytes (total_bits_to_skip, bit_size);
+ temp_buf.resize (this_size);
+
+ if (frame == nullptr)
+ internal_error (__FILE__, __LINE__, _("invalid frame information"));
+
+ /* Can only read from a register on byte granularity so an
+ additional buffer is required. */
+ read_from_register (frame, reg, total_bits_to_skip / HOST_CHAR_BIT,
+ temp_buf, optimized, unavailable);
+
+ /* Only copy data if valid. */
+ if (!*optimized && !*unavailable)
+ copy_bitwise (buf, buf_bit_offset, temp_buf.data (),
+ total_bits_to_skip % HOST_CHAR_BIT, bit_size, big_endian);
+}
+
/* Implicit location description entry. Describes a location
description not found on the target but instead saved in a
gdb-allocated buffer. */
@@ -493,6 +642,10 @@ class dwarf_implicit final : public dwarf_location
m_byte_order (byte_order)
{}
+ void read (frame_info *frame, gdb_byte *buf, int buf_bit_offset,
+ size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit,
+ bool big_endian, int *optimized, int *unavailable) const override;
+
private:
/* Implicit location contents as a stream of bytes in target byte-order. */
gdb::byte_vector m_contents;
@@ -501,6 +654,45 @@ class dwarf_implicit final : public dwarf_location
bfd_endian m_byte_order;
};
+void
+dwarf_implicit::read (frame_info *frame, gdb_byte *buf,
+ int buf_bit_offset, size_t bit_size,
+ LONGEST bits_to_skip, size_t location_bit_limit,
+ bool big_endian, int *optimized, int *unavailable) const
+{
+ ULONGEST implicit_bit_size = HOST_CHAR_BIT * m_contents.size ();
+ LONGEST total_bits_to_skip = bits_to_skip;
+ size_t read_bit_limit = location_bit_limit;
+
+ *optimized = 0;
+ *unavailable = 0;
+
+ /* Cut off at the end of the implicit value. */
+ if (m_byte_order == BFD_ENDIAN_BIG)
+ {
+ if (!read_bit_limit || read_bit_limit > implicit_bit_size)
+ read_bit_limit = bit_size;
+
+ total_bits_to_skip
+ += implicit_bit_size - (m_offset * HOST_CHAR_BIT
+ + m_bit_suboffset + read_bit_limit);
+ }
+ else
+ total_bits_to_skip += m_offset * HOST_CHAR_BIT + m_bit_suboffset;
+
+ if (total_bits_to_skip >= implicit_bit_size)
+ {
+ *unavailable = 1;
+ return;
+ }
+
+ if (bit_size > implicit_bit_size - total_bits_to_skip)
+ bit_size = implicit_bit_size - total_bits_to_skip;
+
+ copy_bitwise (buf, buf_bit_offset, m_contents.data (),
+ total_bits_to_skip, bit_size, big_endian);
+}
+
/* Implicit pointer location description entry. */
class dwarf_implicit_pointer final : public dwarf_location
@@ -516,6 +708,10 @@ class dwarf_implicit_pointer final : public dwarf_location
m_addr_size (addr_size), m_die_offset (die_offset)
{}
+ void read (frame_info *frame, gdb_byte *buf, int buf_bit_offset,
+ size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit,
+ bool big_endian, int *optimized, int *unavailable) const override;
+
private:
/* Per object file data of the implicit pointer. */
dwarf2_per_objfile *m_per_objfile;
@@ -530,6 +726,44 @@ class dwarf_implicit_pointer final : public dwarf_location
sect_offset m_die_offset;
};
+void
+dwarf_implicit_pointer::read (frame_info *frame, gdb_byte *buf,
+ int buf_bit_offset, size_t bit_size,
+ LONGEST bits_to_skip, size_t location_bit_limit,
+ bool big_endian, int *optimized,
+ int *unavailable) const
+{
+ frame_info *actual_frame = frame;
+ LONGEST total_bits_to_skip = bits_to_skip + m_bit_suboffset;
+
+ if (actual_frame == nullptr)
+ actual_frame = get_selected_frame (_("No frame selected."));
+
+ struct type *type
+ = address_type (get_frame_arch (actual_frame), m_addr_size);
+
+ struct value *value
+ = indirect_synthetic_pointer (m_die_offset, m_offset, m_per_cu,
+ m_per_objfile, actual_frame, type);
+
+ gdb_byte *value_contents = value_contents_raw (value).data ()
+ + total_bits_to_skip / HOST_CHAR_BIT;
+
+ if (total_bits_to_skip % HOST_CHAR_BIT == 0
+ && bit_size % HOST_CHAR_BIT == 0
+ && buf_bit_offset % HOST_CHAR_BIT == 0)
+ {
+ memcpy (buf + buf_bit_offset / HOST_CHAR_BIT,
+ value_contents, bit_size / HOST_CHAR_BIT);
+ }
+ else
+ {
+ copy_bitwise (buf, buf_bit_offset, value_contents,
+ total_bits_to_skip % HOST_CHAR_BIT,
+ bit_size, big_endian);
+ }
+}
+
/* Composite location description entry. */
class dwarf_composite final : public dwarf_location
@@ -545,6 +779,10 @@ class dwarf_composite final : public dwarf_location
m_pieces.emplace_back (std::move (location), bit_size);
}
+ void read (frame_info *frame, gdb_byte *buf, int buf_bit_offset,
+ size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit,
+ bool big_endian, int *optimized, int *unavailable) const override;
+
private:
/* Composite piece that contains a piece location
description and it's size. */
@@ -566,6 +804,50 @@ class dwarf_composite final : public dwarf_location
std::vector<piece> m_pieces;
};
+void
+dwarf_composite::read (frame_info *frame, gdb_byte *buf,
+ int buf_bit_offset, size_t bit_size,
+ LONGEST bits_to_skip, size_t location_bit_limit,
+ bool big_endian, int *optimized, int *unavailable) const
+{
+ unsigned int pieces_num = m_pieces.size ();
+ LONGEST total_bits_to_skip = bits_to_skip;
+ unsigned int i;
+
+ total_bits_to_skip += m_offset * HOST_CHAR_BIT + m_bit_suboffset;
+
+ /* Skip pieces covered by the read offset. */
+ for (i = 0; i < pieces_num; i++)
+ {
+ LONGEST piece_bit_size = m_pieces[i].size;
+
+ if (total_bits_to_skip < piece_bit_size)
+ break;
+
+ total_bits_to_skip -= piece_bit_size;
+ }
+
+ for (; i < pieces_num; i++)
+ {
+ LONGEST piece_bit_size = m_pieces[i].size;
+ LONGEST actual_bit_size = piece_bit_size;
+
+ if (actual_bit_size > bit_size)
+ actual_bit_size = bit_size;
+
+ m_pieces[i].location->read (frame, buf, buf_bit_offset,
+ actual_bit_size, total_bits_to_skip,
+ piece_bit_size, big_endian,
+ optimized, unavailable);
+
+ if (bit_size == actual_bit_size || *optimized || *unavailable)
+ break;
+
+ buf_bit_offset += actual_bit_size;
+ bit_size -= actual_bit_size;
+ }
+}
+
struct piece_closure
{
/* Reference count. */
@@ -1181,27 +1463,8 @@ sect_variable_value (sect_offset sect_off,
struct type *
dwarf_expr_context::address_type () const
{
- gdbarch *arch = this->m_per_objfile->objfile->arch ();
- dwarf_gdbarch_types *types
- = (dwarf_gdbarch_types *) gdbarch_data (arch, dwarf_arch_cookie);
- int ndx;
-
- if (this->m_addr_size == 2)
- ndx = 0;
- else if (this->m_addr_size == 4)
- ndx = 1;
- else if (this->m_addr_size == 8)
- ndx = 2;
- else
- error (_("Unsupported address size in DWARF expressions: %d bits"),
- 8 * this->m_addr_size);
-
- if (types->dw_types[ndx] == NULL)
- types->dw_types[ndx]
- = arch_integer_type (arch, 8 * this->m_addr_size,
- 0, "<signed DWARF address type>");
-
- return types->dw_types[ndx];
+ return ::address_type (this->m_per_objfile->objfile->arch (),
+ this->m_addr_size);
}
/* Create a new context for the expression evaluator. */
--
2.17.1
next prev parent reply other threads:[~2021-11-05 11:39 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-05 11:38 [PATCH v4 00/28] Allow location description on the DWARF stack Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 01/28] Add new register access interface to expr.c Zoran Zaric
2021-12-14 20:34 ` Tom Tromey
2021-11-05 11:38 ` [PATCH v4 02/28] Add new memory " Zoran Zaric
2021-12-14 20:42 ` Tom Tromey
2021-11-05 11:38 ` [PATCH v4 03/28] Add new classes that model DWARF stack element Zoran Zaric
2021-12-14 21:10 ` Tom Tromey
2022-01-12 10:23 ` Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 04/28] Add to_location method to dwarf_value class Zoran Zaric
2021-12-14 21:16 ` Tom Tromey
2022-01-12 10:51 ` Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 05/28] Add to_value method to dwarf_location class Zoran Zaric
2021-12-14 21:34 ` Tom Tromey
2022-01-12 12:14 ` Zoran Zaric
2022-01-12 18:42 ` Zoran Zaric
2021-11-05 11:38 ` Zoran Zaric [this message]
2021-11-05 11:38 ` [PATCH v4 07/28] Add write method to location description classes Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 08/28] Add deref " Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 09/28] Add read_from_gdb_value method to dwarf_location Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 10/28] Add write_to_gdb_value " Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 11/28] Add is_implicit_ptr_at " Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 12/28] Add indirect_implicit_ptr to dwarf_location class Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 13/28] Add is_optimized_out " Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 14/28] Add new computed struct value callback interface Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 15/28] Add to_gdb_value method to DWARF entry class Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 16/28] Change DWARF stack to use new dwarf_entry classes Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 17/28] Remove old computed struct value callbacks Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 18/28] Comments cleanup between expr.h and expr.c Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 19/28] Remove dwarf_expr_context from expr.h interface Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 20/28] Move read_addr_from_reg function to frame.c Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 21/28] Add frame info check to DW_OP_reg operations Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 22/28] Remove DWARF expression composition check Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 23/28] Add support for any location description in CFI Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 24/28] Add DWARF operations for byte and bit offset Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 25/28] Add support for DW_OP_LLVM_undefined operation Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 26/28] Add support for nested composite locations Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 27/28] Add DW_OP_LLVM_extend DWARF operation Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 28/28] Add DW_OP_LLVM_select_bit_piece " Zoran Zaric
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211105113849.118800-7-zoran.zaric@amd.com \
--to=zoran.zaric@amd.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).