[PATCH v2 38/42] Add comp_unit_head to dwarf2_per_cu_data

Simon Marchi
2020-05-12T21:17:51Z

From: Simon Marchi <simon.marchi@polymtl.ca>

The per_cu_header_read_in function allows obtaining a filled
comp_unit_head object for a given dwarf2_per_cu_data object. If a
dwarf2_cu object exists for this dwarf2_per_cu_data, then it just
returns a pointer to the comp_unit_head from that dwarf2_cu. Otherwise,
it reads the header into a temporary buffer provided by the caller, and
returns a pointer to that.

Since the dwarf2_per_cu_data::cu link is going to be removed
(dwarf2_per_cu_data will become objfile-independent while dwarf2_cu
stays objfile-dependent), we cannot rely anymore on returning the header
from the dwarf2_cu object.

The not too complex solution implemented by this patch is to keep a copy
of the header in the dwarf2_per_cu_data object, independent from the
copy in dwarf2_cu. The new copy is only used in the addr_size,
offset_size and ref_addr_size methods of dwarf2_per_cu_data.

There's nothing intrinsic to the comp_unit_head object that prevents it
to be shared between two dwarf2_cu objects (belonging to different
objfiles) representing the same CU. In other words, I think we could
eventually get rid of the copy in dwarf2_cu to only keep the one in
dwarf2_per_cu_data. It is not trivial, however, so I have decided not
to do it for the moment.

gdb/ChangeLog:

* dwarf2/read.h (struct dwarf2_per_cu_data) <m_header,
m_header_read_in>: New fields.
<get_header>: New method.
* dwarf2/read.c (per_cu_header_read_in): Remove.
(dwarf2_per_cu_data::get_header): New.
(dwarf2_per_cu_data::addr_size): Update.
(dwarf2_per_cu_data::offset_size): Update.
(dwarf2_per_cu_data::ref_addr_size): Update.
---
gdb/dwarf2/read.c | 52 ++++++++++++++++-------------------------------
gdb/dwarf2/read.h | 19 +++++++++++++++++
2 files changed, 37 insertions(+), 34 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index ad4eae3fe60..dc72b6320a8 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -23295,26 +23295,23 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
}
}

-/* Return comp_unit_head for PER_CU, either already available in PER_CU->CU
- (CU_HEADERP is unused in such case) or prepare a temporary copy at
- CU_HEADERP first. */
+/* See read.h. */

-static const struct comp_unit_head *
-per_cu_header_read_in (struct comp_unit_head *cu_headerp,
- const struct dwarf2_per_cu_data *per_cu)
+const comp_unit_head *
+dwarf2_per_cu_data::get_header () const
{
- const gdb_byte *info_ptr;
-
- if (per_cu->cu)
- return &per_cu->cu->header;
+ if (!m_header_read_in)
+ {
+ const gdb_byte *info_ptr
+ = this->section->buffer + to_underlying (this->sect_off);

- info_ptr = per_cu->section->buffer + to_underlying (per_cu->sect_off);
+ memset (&m_header, 0, sizeof (m_header));

- memset (cu_headerp, 0, sizeof (*cu_headerp));
- read_comp_unit_head (cu_headerp, info_ptr, per_cu->section,
- rcuh_kind::COMPILE);
+ read_comp_unit_head (&m_header, info_ptr, this->section,
+ rcuh_kind::COMPILE);
+ }

- return cu_headerp;
+ return &m_header;
}

/* See read.h. */
@@ -23322,12 +23319,7 @@ per_cu_header_read_in (struct comp_unit_head *cu_headerp,
int
dwarf2_per_cu_data::addr_size () const
{
- struct comp_unit_head cu_header_local;
- const struct comp_unit_head *cu_headerp;
-
- cu_headerp = per_cu_header_read_in (&cu_header_local, this);
-
- return cu_headerp->addr_size;
+ return this->get_header ()->addr_size;
}

/* See read.h. */
@@ -23335,12 +23327,7 @@ dwarf2_per_cu_data::addr_size () const
int
dwarf2_per_cu_data::offset_size () const
{
- struct comp_unit_head cu_header_local;
- const struct comp_unit_head *cu_headerp;
-
- cu_headerp = per_cu_header_read_in (&cu_header_local, this);
-
- return cu_headerp->offset_size;
+ return this->get_header ()->offset_size;
}

/* See read.h. */
@@ -23348,15 +23335,12 @@ dwarf2_per_cu_data::offset_size () const
int
dwarf2_per_cu_data::ref_addr_size () const
{
- struct comp_unit_head cu_header_local;
- const struct comp_unit_head *cu_headerp;
-
- cu_headerp = per_cu_header_read_in (&cu_header_local, this);
+ const comp_unit_head *header = this->get_header ();

- if (cu_headerp->version == 2)
- return cu_headerp->addr_size;
+ if (header->version == 2)
+ return header->addr_size;
else
- return cu_headerp->offset_size;
+ return header->offset_size;
}

/* See read.h. */
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index 3500b0e7ba9..b75be312217 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -22,6 +22,7 @@

#include <queue>
#include <unordered_map>
+#include "dwarf2/comp-unit.h"
#include "dwarf2/index-cache.h"
#include "dwarf2/section.h"
#include "filename-seen-cache.h"
@@ -468,6 +469,21 @@ struct dwarf2_per_cu_data
/* Backlink to the owner of this. */
dwarf2_per_bfd *per_bfd;

+ /* DWARF header of this CU. Note that dwarf2_cu reads its own version of the
+ header, which may differ from this one, since it may pass rcuh_kind::TYPE
+ to read_comp_unit_head, whereas for dwarf2_per_cu_data we always pass
+ rcuh_kind::COMPILE.
+
+ Don't access this field directly, use the get_header method instead. It
+ should be private, but we can't make it private at the moment. */
+ mutable comp_unit_head m_header;
+
+ /* True if HEADER has been read in.
+
+ Don't access this field directly. It should be private, but we can't make
+ it private at the moment. */
+ mutable bool m_header_read_in;
+
/* When dwarf2_per_bfd::using_index is true, the 'quick' field
is active. Otherwise, the 'psymtab' field is active. */
union
@@ -537,6 +553,9 @@ struct dwarf2_per_cu_data
imported_symtabs = nullptr;
}

+ /* Get the header of this per_cu, reading it if necessary. */
+ const comp_unit_head *get_header () const;
+
/* Return the address size given in the compilation unit header for
this CU. */
int addr_size () const;
--
2.26.2