public inbox for libabigail@sourceware.org
 help / color / mirror / Atom feed
From: "Mark J. Wielaard" <mark@klomp.org>
To: libabigail@sourceware.org
Cc: Mark Wielaard <mark@klomp.org>
Subject: [PATCH] dwarf-reader: Workaround libdw dwarf_location_expression bug
Date: Wed, 15 Dec 2021 17:00:21 +0100	[thread overview]
Message-ID: <20211215160021.24200-1-mark@klomp.org> (raw)

From: Mark Wielaard <mark@klomp.org>

elfutils libdw before 0.184 would not correctly handle a
DW_AT_data_member_location when encoded as a DW_FORM_implicit const
in dwarf_location_expression.

Work around this by first trying to read a data_member_location as a
constant value and only try to get it as a DWARF expression if that

	* src/abg-dwarf-reader.cc (die_constant_data_member_location):
	New function.
	(die_member_offset): Use die_constant_data_member_location
	before calling die_location_expr and eval_quickly.

Signed-off-by: Mark Wielaard <mark@klomp.org>
---
 src/abg-dwarf-reader.cc | 72 +++++++++++++++++++++++++++++++++--------
 1 file changed, 58 insertions(+), 14 deletions(-)

https://code.wildebeest.org/git/user/mjw/libabigail/commit/?h=data_member_location

diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index ec92f3f8..3f716944 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -8693,6 +8693,37 @@ read_and_convert_DW_at_bit_offset(const Dwarf_Die* die,
   return true;
 }
 
+/// Get the value of the DW_AT_data_member_location of the given DIE
+/// attribute as an constant.
+///
+/// @param die the DIE to read the attribute from.
+///
+/// @param offset the attribute as a constant value.  This is set iff
+/// the function returns true.
+///
+/// @return true if the attribute exists and has a constant value.  In
+/// that case the offset is set to the value.
+static bool
+die_constant_data_member_location(const Dwarf_Die *die,
+				  int64_t& offset)
+{
+  if (!die)
+    return false;
+
+  Dwarf_Attribute attr;
+  if (!dwarf_attr(const_cast<Dwarf_Die*>(die),
+		  DW_AT_data_member_location,
+		  &attr))
+    return false;
+
+  Dwarf_Word val;
+  if (dwarf_formudata(&attr, &val) != 0)
+    return false;
+
+  offset = val;
+  return true;
+}
+
 /// Get the offset of a struct/class member as represented by the
 /// value of the DW_AT_data_member_location attribute.
 ///
@@ -8758,21 +8789,34 @@ die_member_offset(const read_context& ctxt,
       return true;
     }
 
-  // Otherwise, let's see if the DW_AT_data_member_location attribute and,
-  // optionally, the DW_AT_bit_offset attributes are present.
-  if (!die_location_expr(die, DW_AT_data_member_location, &expr, &expr_len))
-    return false;
-
-  // The DW_AT_data_member_location attribute is present.
-  // Let's evaluate it and get its constant
-  // sub-expression and return that one.
-  if (!eval_quickly(expr, expr_len, offset))
-    {
-      bool is_tls_address = false;
-      if (!eval_last_constant_dwarf_sub_expr(expr, expr_len,
-					     offset, is_tls_address,
-					     ctxt.dwarf_expr_eval_ctxt()))
+  // First try to read DW_AT_data_member_location as a plain constant.
+  // We do this because the generic method using die_location_expr
+  // might hit a bug in elfutils libdw dwarf_location_expression only
+  // fixed in elfutils 0.184+. The bug only triggers if the attribute
+  // is expressed as a (DWARF 5) DW_FORM_implicit_constant. But we
+  // handle all constants here because that is more consistent (and
+  // slightly faster in the general case where the attribute isn't a
+  // full DWARF expression).
+  if (!die_constant_data_member_location(die, offset))
+    {
+      // Otherwise, let's see if the DW_AT_data_member_location
+      // attribute and, optionally, the DW_AT_bit_offset attributes
+      // are present.
+      if (!die_location_expr(die, DW_AT_data_member_location,
+			     &expr, &expr_len))
 	return false;
+
+      // The DW_AT_data_member_location attribute is present.  Let's
+      // evaluate it and get its constant sub-expression and return
+      // that one.
+      if (!eval_quickly(expr, expr_len, offset))
+	{
+	  bool is_tls_address = false;
+	  if (!eval_last_constant_dwarf_sub_expr(expr, expr_len,
+						 offset, is_tls_address,
+						 ctxt.dwarf_expr_eval_ctxt()))
+	    return false;
+	}
     }
   offset *= 8;
 
-- 
2.18.4


         reply	other threads:[~2021-12-15 16:00 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-14 15:55 Buildbot failure in Wildebeest Builder on whole buildset buildbot
2021-12-15 13:01 ` Mark Wielaard
2021-12-15 16:00   ` Mark J. Wielaard [this message]
2021-12-15 18:56     ` [PATCH] dwarf-reader: Workaround libdw dwarf_location_expression bug Giuliano Procida
2021-12-15 19:25       ` Mark J. Wielaard
2021-12-15 19:47     ` Thomas Schwinge
2021-12-17 18:47     ` Dodji Seketeli

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=20211215160021.24200-1-mark@klomp.org \
    --to=mark@klomp.org \
    --cc=libabigail@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).