Bug 26261 - Fix logic for canonicalizing DW_TAG_subroutine_type DIEs

Message ID 873654f465.fsf@redhat.com
State New
Headers
Series Bug 26261 - Fix logic for canonicalizing DW_TAG_subroutine_type DIEs |

Commit Message

Dodji Seketeli Aug. 3, 2020, 9:51 a.m. UTC
  Hello,

In the function compare_dies, the handling of DW_TAG_subroutine_type
was unfinished.

This DIE represents function types pointed-to by function pointer.  It
doesn't represent the type of a "real" function type like the
abigail::ir::function_type would.  The represent more an interface to
a function, which a pointer can point to or which can be used to issue
a call.

So intended idea is that compare_dies compares two DIEs of the
DW_TAG_subroutine_type and DW_TAG_subprogram kind (the later
represents real function definitions) among other kinds, structurally,
but by trying to optimize for speed, for the purpose of canonicalizing
DIEs even before type canonicalization happens at the libabigail IR
level.  This is critical to save space (and time) by doing DIE
de-duplication on huge binaries.

This patch finishes to implement the comparison for
DW_TAG_subroutine_type and comes with a carefully crafted test case
that hits that code path.

	* src/abg-dwarf-reader.cc (compare_dies): Get out early if we are
	are in the middle of a potential recursive comparison of function
	types.  Likewise if we detect that the two function types have
	different textual representations, linkage names, or have a the
	same textual representation, linkage names and are defined in the
	same translation unit.
	* tests/data/test-read-dwarf/PR26261/PR26261-exe: New test binary
	input file.
	* tests/data/test-read-dwarf/PR26261/PR26261-exe.abi: New
	reference test output file.
	* tests/data/test-read-dwarf/PR26261/PR26261-main.c: Source code
	of the binary above.
	* tests/data/test-read-dwarf/PR26261/PR26261-obj{a,b}.{c,h}:
	Likewise.
	* tests/data/test-read-dwarf/PR26261/Makefile: Makefile to
	build the exe out of the source files.
	* tests/data/Makefile.am: Add the new test input files to source
	distribution.
	* tests/test-read-dwarf.cc (in_out_spec): Add the binary test
	input above to the test harness.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>

Applied to master.

---
 src/abg-dwarf-reader.cc                            | 132 ++++++++++++---------
 tests/data/Makefile.am                             |   8 ++
 tests/data/test-read-dwarf/PR26261/Makefile        |  21 ++++
 tests/data/test-read-dwarf/PR26261/PR26261-exe     | Bin 0 -> 10976 bytes
 tests/data/test-read-dwarf/PR26261/PR26261-exe.abi |  86 ++++++++++++++
 tests/data/test-read-dwarf/PR26261/PR26261-main.c  |  40 +++++++
 tests/data/test-read-dwarf/PR26261/PR26261-obja.c  |   6 +
 tests/data/test-read-dwarf/PR26261/PR26261-obja.h  |  12 ++
 tests/data/test-read-dwarf/PR26261/PR26261-objb.c  |   6 +
 tests/data/test-read-dwarf/PR26261/PR26261-objb.h  |   9 ++
 tests/test-read-dwarf.cc                           |   7 ++
 11 files changed, 273 insertions(+), 54 deletions(-)
 create mode 100644 tests/data/test-read-dwarf/PR26261/Makefile
 create mode 100755 tests/data/test-read-dwarf/PR26261/PR26261-exe
 create mode 100644 tests/data/test-read-dwarf/PR26261/PR26261-exe.abi
 create mode 100644 tests/data/test-read-dwarf/PR26261/PR26261-main.c
 create mode 100644 tests/data/test-read-dwarf/PR26261/PR26261-obja.c
 create mode 100644 tests/data/test-read-dwarf/PR26261/PR26261-obja.h
 create mode 100644 tests/data/test-read-dwarf/PR26261/PR26261-objb.c
 create mode 100644 tests/data/test-read-dwarf/PR26261/PR26261-objb.h
  

Patch

diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
index 533c2dc..1184cbf 100644
--- a/src/abg-dwarf-reader.cc
+++ b/src/abg-dwarf-reader.cc
@@ -11874,76 +11874,100 @@  compare_dies(const read_context& ctxt,
 	     != aggregates_being_compared.end())
 	    || (aggregates_being_compared.find(rn)
 		!= aggregates_being_compared.end()))
-	  result = true;
+	  {
+	    result = true;
+	    break;
+	  }
 	else if (l_tag == DW_TAG_subroutine_type)
 	  {
-	    // The string reprs of l and r are already equal. Now
-	    // let's just check if they both come from the same TU.
+	    // So, we are looking at types that are pointed to by a
+	    // function pointer.  These are not real concrete function
+	    // types, rather, they denote interfaces of functions.
+	    //
+	    // If the textual representations are different, then
+	    // obviously they are different DIEs.
+	    if (ln != rn)
+	      {
+		result = false;
+		break;
+	      }
+
+	    // So if their textual representation are the same and
+	    // they come from the same TU, then they represent the
+	    // same DIE.
 	    bool from_the_same_tu = false;
 	    if (compare_dies_cu_decl_file(l, r, from_the_same_tu)
 		&& from_the_same_tu)
-	      result = true;
-	  }
-	else
-	  {
-	    if (!fn_die_equal_by_linkage_name(ctxt, l, r))
 	      {
-		result = false;
+		result = true;
 		break;
 	      }
+	  }
 
-	    if (!ctxt.die_is_in_c(l) && !ctxt.die_is_in_c(r))
+	if (l_tag == DW_TAG_subprogram
+	    && !fn_die_equal_by_linkage_name(ctxt, l, r))
+	  {
+	    result = false;
+	    break;
+	  }
+	else if (l_tag == DW_TAG_subprogram
+		 && ctxt.die_is_in_c(l) && ctxt.die_is_in_c(r)
+		 /*&& fn_die_equal_by_linkage_name(ctxt, l, r)*/)
+	  {
+	    result = true;
+	    break;
+	  }
+	else if (!ctxt.die_is_in_c(l) && !ctxt.die_is_in_c(r))
+	  {
+	    // In C, we cannot have two different functions with the
+	    // same linkage name in a given binary.  But here we are
+	    // looking at DIEs that don't originate from C.  So we
+	    // need to compare return types and parameter types.
+	    Dwarf_Die l_return_type, r_return_type;
+	    bool l_return_type_is_void = !die_die_attribute(l, DW_AT_type,
+							    l_return_type);
+	    bool r_return_type_is_void = !die_die_attribute(r, DW_AT_type,
+							    r_return_type);
+	    if (l_return_type_is_void != r_return_type_is_void
+		|| (!l_return_type_is_void
+		    && !compare_dies(ctxt,
+				     &l_return_type, &r_return_type,
+				     aggregates_being_compared,
+				     update_canonical_dies_on_the_fly)))
+	      result = false;
+	    else
 	      {
-		// In C, we cannot have two different functions with the
-		// same linkage name in a given binary.  But here we are
-		// looking at DIEs that don't originate from C.  So we
-		// need to compare return types and parameter types.
-		Dwarf_Die l_return_type, r_return_type;
-		bool l_return_type_is_void = !die_die_attribute(l, DW_AT_type,
-								l_return_type);
-		bool r_return_type_is_void = !die_die_attribute(r, DW_AT_type,
-								r_return_type);
-		if (l_return_type_is_void != r_return_type_is_void
-		    || (!l_return_type_is_void
-			&& !compare_dies(ctxt,
-					 &l_return_type, &r_return_type,
-					 aggregates_being_compared,
-					 update_canonical_dies_on_the_fly)))
-		  result = false;
-		else
-		  {
-		    Dwarf_Die l_child, r_child;
-		    bool found_l_child, found_r_child;
-		    for (found_l_child = dwarf_child(const_cast<Dwarf_Die*>(l),
+		Dwarf_Die l_child, r_child;
+		bool found_l_child, found_r_child;
+		for (found_l_child = dwarf_child(const_cast<Dwarf_Die*>(l),
+						 &l_child) == 0,
+		       found_r_child = dwarf_child(const_cast<Dwarf_Die*>(r),
+						   &r_child) == 0;
+		     found_l_child && found_r_child;
+		     found_l_child = dwarf_siblingof(&l_child,
 						     &l_child) == 0,
-			   found_r_child = dwarf_child(const_cast<Dwarf_Die*>(r),
-						       &r_child) == 0;
-			 found_l_child && found_r_child;
-			 found_l_child = dwarf_siblingof(&l_child,
-							 &l_child) == 0,
-			   found_r_child = dwarf_siblingof(&r_child,
-							   &r_child)==0)
+		       found_r_child = dwarf_siblingof(&r_child,
+						       &r_child)==0)
+		  {
+		    int l_child_tag = dwarf_tag(&l_child);
+		    int r_child_tag = dwarf_tag(&r_child);
+		    if (l_child_tag != r_child_tag
+			|| (l_child_tag == DW_TAG_formal_parameter
+			    && !compare_dies(ctxt, &l_child, &r_child,
+					     aggregates_being_compared,
+					     update_canonical_dies_on_the_fly)))
 		      {
-			int l_child_tag = dwarf_tag(&l_child);
-			int r_child_tag = dwarf_tag(&r_child);
-			if (l_child_tag != r_child_tag
-			    || (l_child_tag == DW_TAG_formal_parameter
-				&& !compare_dies(ctxt, &l_child, &r_child,
-						 aggregates_being_compared,
-						 update_canonical_dies_on_the_fly)))
-			  {
-			    result = false;
-			    break;
-			  }
+			result = false;
+			break;
 		      }
-		    if (found_l_child != found_r_child)
-		      result = false;
 		  }
+		if (found_l_child != found_r_child)
+		  result = false;
 	      }
-
-	    aggregates_being_compared.erase(ln);
-	    aggregates_being_compared.erase(rn);
 	  }
+
+	aggregates_being_compared.erase(ln);
+	aggregates_being_compared.erase(rn);
       }
       break;
 
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index ea94f0b..e59331e 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -496,6 +496,14 @@  test-read-dwarf/PR25042-libgdbm-clang-dwarf5.so.6.0.0.abi \
 test-read-dwarf/test25-bogus-binary.elf \
 test-read-dwarf/test26-bogus-binary.elf \
 test-read-dwarf/test27-bogus-binary.elf \
+test-read-dwarf/PR26261/Makefile \
+test-read-dwarf/PR26261/PR26261-exe.abi \
+test-read-dwarf/PR26261/PR26261-obja.c \
+test-read-dwarf/PR26261/PR26261-objb.c \
+test-read-dwarf/PR26261/PR26261-exe \
+test-read-dwarf/PR26261/PR26261-main.c \
+test-read-dwarf/PR26261/PR26261-obja.h \
+test-read-dwarf/PR26261/PR26261-objb.h \
 \
 test-annotate/test0.abi			\
 test-annotate/test1.abi			\
diff --git a/tests/data/test-read-dwarf/PR26261/Makefile b/tests/data/test-read-dwarf/PR26261/Makefile
new file mode 100644
index 0000000..f66fa38
--- /dev/null
+++ b/tests/data/test-read-dwarf/PR26261/Makefile
@@ -0,0 +1,21 @@ 
+SRCS	= PR26261-obja.c PR26261-objb.c PR26261-main.c
+EXE	= PR26261-exe
+OBJS	= $(SRCS:.c=.o)
+CFLAGS	= -Wall -g
+
+all: $(EXE)
+
+%.o: %.c
+	$(CC) $(CFLAGS) -c $<
+
+$(EXE): $(OBJS)
+	gcc -fPIC $(OBJS) -o $@
+
+cleanobjs:
+	rm -rf $(OBJS)
+
+cleanexe:
+	rm $(EXE)
+
+clean: cleanobjs
+	rm -rf *~ 
diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-exe b/tests/data/test-read-dwarf/PR26261/PR26261-exe
new file mode 100755
index 0000000000000000000000000000000000000000..564a4247643942bbfd91c0e75653dffe80ce5851
GIT binary patch
literal 10976
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

literal 0
HcmV?d00001

diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-exe.abi b/tests/data/test-read-dwarf/PR26261/PR26261-exe.abi
new file mode 100644
index 0000000..02c032b
--- /dev/null
+++ b/tests/data/test-read-dwarf/PR26261/PR26261-exe.abi
@@ -0,0 +1,86 @@ 
+<abi-corpus path='data/test-read-dwarf/PR26261/PR26261-exe'>
+  <elf-needed>
+    <dependency name='libc.so.6'/>
+  </elf-needed>
+  <elf-function-symbols>
+    <elf-symbol name='__libc_csu_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='__libc_csu_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='_start' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='fun_obja' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='fun_objb' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='main' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='wrapped_call' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <elf-variable-symbols>
+    <elf-symbol name='_IO_stdin_used' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr version='1.0' address-size='64' path='PR26261-main.c' comp-dir-path='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261' language='LANG_C89'>
+    <pointer-type-def type-id='type-id-1' size-in-bits='64' id='type-id-2'/>
+    <pointer-type-def type-id='type-id-2' size-in-bits='64' id='type-id-3'/>
+    <function-decl name='wrapped_call' mangled-name='wrapped_call' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-main.c' line='18' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='wrapped_call'>
+      <parameter type-id='type-id-4' name='fun' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-main.c' line='18' column='1'/>
+      <parameter type-id='type-id-5' name='a' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-main.c' line='19' column='1'/>
+      <parameter type-id='type-id-5' name='b' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-main.c' line='20' column='1'/>
+      <return type-id='type-id-6'/>
+    </function-decl>
+    <function-decl name='main' mangled-name='main' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-main.c' line='27' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='main'>
+      <parameter type-id='type-id-5' name='argc' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-main.c' line='27' column='1'/>
+      <parameter type-id='type-id-3' name='argv' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-main.c' line='27' column='1'/>
+      <return type-id='type-id-5'/>
+    </function-decl>
+  </abi-instr>
+  <abi-instr version='1.0' address-size='64' path='PR26261-obja.c' comp-dir-path='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261' language='LANG_C89'>
+    <type-decl name='int' size-in-bits='32' id='type-id-5'/>
+    <type-decl name='void' id='type-id-6'/>
+    <class-decl name='SA' size-in-bits='192' is-struct='yes' visibility='default' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-obja.h' line='5' column='1' id='type-id-7'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='m1' type-id='type-id-5' visibility='default' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-obja.h' line='7' column='1'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='64'>
+        <var-decl name='m2' type-id='type-id-8' visibility='default' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-obja.h' line='8' column='1'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='128'>
+        <var-decl name='m3' type-id='type-id-9' visibility='default' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-obja.h' line='9' column='1'/>
+      </data-member>
+    </class-decl>
+    <typedef-decl name='fn_ptr_type_a_t' type-id='type-id-4' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-obja.h' line='1' column='1' id='type-id-8'/>
+    <typedef-decl name='fn_ptr_type_a2_t' type-id='type-id-4' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-obja.h' line='3' column='1' id='type-id-9'/>
+    <pointer-type-def type-id='type-id-7' size-in-bits='64' id='type-id-10'/>
+    <pointer-type-def type-id='type-id-11' size-in-bits='64' id='type-id-4'/>
+    <function-decl name='fun_obja' mangled-name='fun_obja' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-obja.c' line='4' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fun_obja'>
+      <parameter type-id='type-id-10' name='s' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-obja.c' line='4' column='1'/>
+      <return type-id='type-id-6'/>
+    </function-decl>
+    <function-type size-in-bits='64' id='type-id-11'>
+      <parameter type-id='type-id-5'/>
+      <parameter type-id='type-id-5'/>
+      <return type-id='type-id-6'/>
+    </function-type>
+  </abi-instr>
+  <abi-instr version='1.0' address-size='64' path='PR26261-objb.c' comp-dir-path='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261' language='LANG_C89'>
+    <type-decl name='char' size-in-bits='8' id='type-id-1'/>
+    <class-decl name='SB' size-in-bits='128' is-struct='yes' visibility='default' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-objb.h' line='3' column='1' id='type-id-12'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='m1' type-id='type-id-5' visibility='default' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-objb.h' line='5' column='1'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='64'>
+        <var-decl name='m2' type-id='type-id-13' visibility='default' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-objb.h' line='6' column='1'/>
+      </data-member>
+    </class-decl>
+    <typedef-decl name='fn_ptr_type_b_t' type-id='type-id-14' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-objb.h' line='1' column='1' id='type-id-13'/>
+    <pointer-type-def type-id='type-id-12' size-in-bits='64' id='type-id-15'/>
+    <pointer-type-def type-id='type-id-16' size-in-bits='64' id='type-id-14'/>
+    <function-decl name='fun_objb' mangled-name='fun_objb' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-objb.c' line='4' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fun_objb'>
+      <parameter type-id='type-id-15' name='s' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-objb.c' line='4' column='1'/>
+      <return type-id='type-id-6'/>
+    </function-decl>
+    <function-type size-in-bits='64' id='type-id-16'>
+      <parameter type-id='type-id-5'/>
+      <parameter type-id='type-id-5'/>
+      <parameter type-id='type-id-1'/>
+      <return type-id='type-id-6'/>
+    </function-type>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-main.c b/tests/data/test-read-dwarf/PR26261/PR26261-main.c
new file mode 100644
index 0000000..60ea256
--- /dev/null
+++ b/tests/data/test-read-dwarf/PR26261/PR26261-main.c
@@ -0,0 +1,40 @@ 
+/**
+ *
+ * In this test case, we want the first parameter of the function
+ * wrapped_call to be represented in the output abixml by a pointer to
+ * the same function type as the one pointed to by the types
+ * fn_ptr_type_a_t and fn_ptr_type_b_t.
+ *
+ * This means that we want the function type pointed by these three
+ * function pointer to be the same, as a result of the
+ * canonicalization of the DIEs that represent these three function
+ * types.
+ *
+ */
+#include "PR26261-obja.h"
+#include "PR26261-objb.h"
+
+void
+wrapped_call(void (*fun)(int, int),
+	     int a,
+	     int b)
+{
+  if (fun)
+    fun(a, b);
+}
+
+int
+main(int argc, char ** argv)
+{
+  struct SA sa = {0, 0, 0};
+  struct SB sb = {0, 0};
+
+  sa.m1 = 0;
+  sb.m1 = 0;
+
+  fun_obja(&sa);
+  fun_objb(&sb);
+  wrapped_call(sa.m2, sa.m1, sb.m1);
+
+  return 0;
+}
diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-obja.c b/tests/data/test-read-dwarf/PR26261/PR26261-obja.c
new file mode 100644
index 0000000..04d6d00
--- /dev/null
+++ b/tests/data/test-read-dwarf/PR26261/PR26261-obja.c
@@ -0,0 +1,6 @@ 
+#include "PR26261-obja.h"
+
+void
+fun_obja(struct SA* s __attribute__((unused)))
+{
+}
diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-obja.h b/tests/data/test-read-dwarf/PR26261/PR26261-obja.h
new file mode 100644
index 0000000..b6ca8f4
--- /dev/null
+++ b/tests/data/test-read-dwarf/PR26261/PR26261-obja.h
@@ -0,0 +1,12 @@ 
+typedef void (*fn_ptr_type_a_t)(int, int);
+
+typedef void (*fn_ptr_type_a2_t)(int, int);
+
+struct SA
+{
+  int m1;
+  fn_ptr_type_a_t m2;
+  fn_ptr_type_a2_t m3;
+};
+
+void fun_obja(struct SA*);
diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-objb.c b/tests/data/test-read-dwarf/PR26261/PR26261-objb.c
new file mode 100644
index 0000000..49e26bf
--- /dev/null
+++ b/tests/data/test-read-dwarf/PR26261/PR26261-objb.c
@@ -0,0 +1,6 @@ 
+#include "PR26261-objb.h"
+
+void
+fun_objb(struct SB* s __attribute__((unused)))
+{
+}
diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-objb.h b/tests/data/test-read-dwarf/PR26261/PR26261-objb.h
new file mode 100644
index 0000000..92f92ca
--- /dev/null
+++ b/tests/data/test-read-dwarf/PR26261/PR26261-objb.h
@@ -0,0 +1,9 @@ 
+typedef void (*fn_ptr_type_b_t)(int, int, char);
+
+struct SB
+{
+  int m1;
+  fn_ptr_type_b_t m2;
+};
+
+void fun_objb(struct SB*);
diff --git a/tests/test-read-dwarf.cc b/tests/test-read-dwarf.cc
index 8502f82..3f93d6d 100644
--- a/tests/test-read-dwarf.cc
+++ b/tests/test-read-dwarf.cc
@@ -373,6 +373,13 @@  InOutSpec in_out_specs[] =
     NULL,
     NULL,
   },
+  {
+    "data/test-read-dwarf/PR26261/PR26261-exe",
+    "",
+    SEQUENCE_TYPE_ID_STYLE,
+    "data/test-read-dwarf/PR26261/PR26261-exe.abi",
+    "output/test-read-dwarf/PR26261/PR26261-exe.abi",
+  },
   // This should be the last entry.
   {NULL, NULL, SEQUENCE_TYPE_ID_STYLE, NULL, NULL}
 };