[v2] Add regression tests for ctf reading

Message ID 20211122213353.2456208-1-guillermo.e.martinez@oracle.com
State New
Headers
Series [v2] Add regression tests for ctf reading |

Commit Message

Guillermo E. Martinez Nov. 22, 2021, 9:33 p.m. UTC
  Hello libabigail team,

This patch includes regression tests v2 for CTF.

The change from v1 is disable CTF test alias, because
currently is is not supported.

Dependencies/limitations:

* It was worked on the top of the following patches:
 https://sourceware.org/pipermail/libabigail/2021q4/003853.html

* Some CTF tests were *disabled* because it generates the XML ABI
corpus with *same information* but the XML nodes *are not* always
in the *same order*, so using diff command fails. Details here:
https://sourceware.org/pipermail/libabigail/2021q4/003824.html

Comments will be appreciated.

Thanks in advanced!,
Guillermo

This patch implements some regression tests for ctf reading.
Since the code share a lot of functionalities already used
in the readi-dwarf test, a library was built and test common
harness were moved to a common location. So input files for
test-read-{dwarf,ctf}.cc now are located in:
tests/data/test-read-common directory, ABIs description are
stored in the same location but in a separate file, one for
each binary debugging information: (e.g, test4-ctf.so.abi
and test4-dwarf.so.abi)

	* tests/test-read-ctf.cc: New ctf reading regression test.
	* tests/test-read-common.cc: New library to be used with
	test-read-{ctf,dwarf}.cc.
	* tests/test-read-common.h: Likewise.
	* tests/test-annotate.cc (in_out_specs): Adjust path for input files.
	* tests/Makefile.am: Build new tests/test-read-ctf.cc file.
	Add libtestreadcommon.a test library and use it for test-read-{ctf,dwarf}.
	* tests/test-read-dwarf.cc: Adapt test to use libtestreadcommon.a in
	test-read-common.{cc,h}.
	* tests/data/test-annotate/test3.so.abi: Adjust ELF input path file
	location to ./tests/data/test-read-common.
	* tests/data/test-annotate/test4.so.abi: Likewise.
	* tests/data/test-read-common/PR26261: Move test harness to
	test-read-common directory.
	* tests/data/test-read-common/PR27700: Likewise.
	* tests/data/test-read-common/test-PR26568-*: Likewise.
	* tests/data/test-read-common/test3*: Likewise.
	* tests/data/test-read-common/test4*: Likewise.
	* tests/data/test-read-common/crti*: Helper object to export
	_init and _fini sysmbols.
	* tests/data/test-read-ctf/test-ambiguous-struct-A.c: New testcase.
	* tests/data/test-read-ctf/test-ambiguous-struct-B.c: Likewise.
	* tests/data/test-read-ctf/test-conflicting-type-syms-a.c: Likewise.
	* tests/data/test-read-ctf/test-conflicting-type-syms-b.c: Likewise.
	* tests/data/test-read-ctf/test-enum-ctf.c: Likewise.
	* tests/data/test-read-ctf/test-enum-many-ctf.c: Likewise.
	* tests/data/test-read-ctf/test-enum-symbol-ctf.c: Likewise.
	* tests/data/test-read-ctf/test-struct-iteration-ctf.c: Likewise.
	* tests/data/test-read-ctf/test0.c: Likewise.
	* tests/data/test-read-ctf/test1.c: Likewise.
	* tests/data/test-read-ctf/test2.c: Likewise.
	* tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi:
	Testcase expected result.
	* tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi: Likewise.
	* tests/data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi: Likewise.
	* tests/data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi: Likewise.
	* tests/data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi: Likewise.
	* tests/data/test-read-ctf/test-enum-ctf.o.abi: Likewise.
	* tests/data/test-read-ctf/test-enum-many-ctf.o.hash.abi: Likewise.
	* tests/data/test-read-ctf/test-enum-symbol-ctf.o.hash.abi: Likewise.
	* tests/data/test-read-ctf/test-struct-iteration-ctf.o.abi: Likewise.
	* tests/data/test-read-ctf/test0: Likewise.
	* tests/data/test-read-ctf/test0.abi: Likewise.
	* tests/data/test-read-ctf/test0.hash.abi: Likewise.
	* tests/data/test-read-ctf/test1.so: Likewise.
	* tests/data/test-read-ctf/test1.so.abi: Likewise.
	* tests/data/test-read-ctf/test1.so.hash.abi: Likewise.
	* tests/data/test-read-ctf/test2.so: Likewise.
	* tests/data/test-read-ctf/test2.so.abi: Likewise.
	* tests/data/test-read-ctf/test2.so.hash.abi: Likewise.

Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
---
 tests/Makefile.am                             |  24 +-
 tests/data/test-annotate/test3.so.abi         |   4 +-
 tests/data/test-annotate/test4.so.abi         |  10 +-
 .../data/test-read-common/PR26261/PR26261-exe | Bin 0 -> 19008 bytes
 .../PR26261/PR26261-exe-ctf.abi               |  58 +++
 .../PR26261/PR26261-exe-dwarf.abi}            |  52 ++-
 .../PR26261/PR26261-main.c                    |   0
 .../PR26261/PR26261-obja.c                    |   0
 .../PR26261/PR26261-obja.h                    |   0
 .../PR26261/PR26261-objb.c                    |   0
 .../PR26261/PR26261-objb.h                    |   0
 .../PR27700/include-dir/priv.h                |   0
 .../PR27700/include-dir/pub.h                 |   0
 .../PR27700/pub-incdir/inc.h                  |   0
 .../PR27700/test-PR27700-ctf.abi              |  22 ++
 .../PR27700/test-PR27700-dwarf.abi}           |   8 +-
 .../PR27700/test-PR27700.c                    |   2 +
 tests/data/test-read-common/crti.c            |  22 ++
 .../test-read-common/test-PR26568-1-ctf.o.abi |  56 +++
 .../test-PR26568-1-dwarf.o.abi}               |  20 +-
 .../test-PR26568-1.c                          |   3 +
 .../test-read-common/test-PR26568-2-ctf.o.abi |  39 ++
 .../test-PR26568-2-dwarf.o.abi}               |  18 +-
 .../test-PR26568-2.c                          |   3 +
 .../test3-alias-1-dwarf.so.hash.abi}          |   6 +-
 .../test3-alias-1.suppr                       |   0
 .../test3-alias-2-dwarf.so.hash.abi}          |   6 +-
 .../test3-alias-2.suppr                       |   0
 .../test3-alias-3-dwarf.so.hash.abi}          |   6 +-
 .../test3-alias-3.suppr                       |   0
 .../test3-alias-4-dwarf.so.hash.abi}          |   2 +-
 .../test3-alias-4.suppr                       |   0
 tests/data/test-read-common/test3-ctf.so.abi  |  12 +
 .../test-read-common/test3-ctf.so.hash.abi    |  12 +
 .../test3-dwarf.so.abi}                       |   6 +-
 .../test3-dwarf.so.hash.abi}                  |   6 +-
 tests/data/test-read-common/test3.c           |  26 ++
 tests/data/test-read-common/test3.so          | Bin 0 -> 14824 bytes
 tests/data/test-read-common/test4-ctf.so.abi  |  14 +
 .../test-read-common/test4-ctf.so.hash.abi    |  14 +
 .../test4-dwarf.so.abi}                       |  12 +-
 .../test4-dwarf.so.hash.abi}                  |  12 +-
 tests/data/test-read-common/test4.c           |  11 +
 tests/data/test-read-common/test4.so          | Bin 0 -> 16560 bytes
 tests/data/test-read-ctf/test-alias.c         |  15 +
 tests/data/test-read-ctf/test-alias.o.abi     |  19 +
 .../test-read-ctf/test-ambiguous-struct-A.c   |   8 +
 .../test-ambiguous-struct-A.o.hash.abi        |  36 ++
 .../test-read-ctf/test-ambiguous-struct-B.c   |   5 +
 .../test-ambiguous-struct-B.o.hash.abi        |  23 ++
 .../test-conflicting-type-syms-a.c            |   5 +
 .../test-conflicting-type-syms-a.o.hash.abi   |  14 +
 .../test-conflicting-type-syms-b.c            |   5 +
 .../test-conflicting-type-syms-b.o.hash.abi   |  13 +
 tests/data/test-read-ctf/test-enum-ctf.c      |   8 +
 tests/data/test-read-ctf/test-enum-ctf.o.abi  |  24 ++
 tests/data/test-read-ctf/test-enum-many-ctf.c |  10 +
 .../test-enum-many-ctf.o.hash.abi             |  69 ++++
 .../data/test-read-ctf/test-enum-symbol-ctf.c |   1 +
 .../test-enum-symbol-ctf.o.hash.abi           |  16 +
 .../test-read-ctf/test-struct-iteration-ctf.c |  28 ++
 .../test-struct-iteration-ctf.o.abi           |  96 +++++
 tests/data/test-read-ctf/test0                | Bin 0 -> 16656 bytes
 tests/data/test-read-ctf/test0.abi            |  54 +++
 tests/data/test-read-ctf/test0.c              |  32 ++
 tests/data/test-read-ctf/test0.hash.abi       |  54 +++
 tests/data/test-read-ctf/test1.c              |  25 ++
 tests/data/test-read-ctf/test1.so             | Bin 0 -> 15592 bytes
 tests/data/test-read-ctf/test1.so.abi         |  23 ++
 tests/data/test-read-ctf/test1.so.hash.abi    |  23 ++
 tests/data/test-read-ctf/test2.c              |  19 +
 tests/data/test-read-ctf/test2.so             | Bin 0 -> 15616 bytes
 tests/data/test-read-ctf/test2.so.abi         |  25 ++
 tests/data/test-read-ctf/test2.so.hash.abi    |  25 ++
 tests/data/test-read-dwarf/PR26261/Makefile   |  21 -
 .../data/test-read-dwarf/PR26261/PR26261-exe  | Bin 10976 -> 0 bytes
 .../test-read-dwarf/PR27700/test-PR27700.o    | Bin 3248 -> 0 bytes
 tests/data/test-read-dwarf/test-PR26568-1.o   | Bin 2864 -> 0 bytes
 tests/data/test-read-dwarf/test-PR26568-2.o   | Bin 2824 -> 0 bytes
 tests/data/test-read-dwarf/test3.c            |  11 -
 tests/data/test-read-dwarf/test3.so           | Bin 8851 -> 0 bytes
 tests/data/test-read-dwarf/test4.c            |  14 -
 tests/data/test-read-dwarf/test4.so           | Bin 3364 -> 0 bytes
 tests/test-annotate.cc                        |   4 +-
 tests/test-read-common.cc                     | 184 +++++++++
 tests/test-read-common.h                      | 148 +++++++
 tests/test-read-ctf.cc                        | 290 ++++++++++++++
 tests/test-read-dwarf.cc                      | 362 +++++++-----------
 88 files changed, 1829 insertions(+), 366 deletions(-)
 create mode 100755 tests/data/test-read-common/PR26261/PR26261-exe
 create mode 100644 tests/data/test-read-common/PR26261/PR26261-exe-ctf.abi
 rename tests/data/{test-read-dwarf/PR26261/PR26261-exe.abi => test-read-common/PR26261/PR26261-exe-dwarf.abi} (53%)
 rename tests/data/{test-read-dwarf => test-read-common}/PR26261/PR26261-main.c (100%)
 rename tests/data/{test-read-dwarf => test-read-common}/PR26261/PR26261-obja.c (100%)
 rename tests/data/{test-read-dwarf => test-read-common}/PR26261/PR26261-obja.h (100%)
 rename tests/data/{test-read-dwarf => test-read-common}/PR26261/PR26261-objb.c (100%)
 rename tests/data/{test-read-dwarf => test-read-common}/PR26261/PR26261-objb.h (100%)
 rename tests/data/{test-read-dwarf => test-read-common}/PR27700/include-dir/priv.h (100%)
 rename tests/data/{test-read-dwarf => test-read-common}/PR27700/include-dir/pub.h (100%)
 rename tests/data/{test-read-dwarf => test-read-common}/PR27700/pub-incdir/inc.h (100%)
 create mode 100644 tests/data/test-read-common/PR27700/test-PR27700-ctf.abi
 rename tests/data/{test-read-dwarf/PR27700/test-PR27700.abi => test-read-common/PR27700/test-PR27700-dwarf.abi} (60%)
 rename tests/data/{test-read-dwarf => test-read-common}/PR27700/test-PR27700.c (55%)
 create mode 100644 tests/data/test-read-common/crti.c
 create mode 100644 tests/data/test-read-common/test-PR26568-1-ctf.o.abi
 rename tests/data/{test-read-dwarf/test-PR26568-1.o.abi => test-read-common/test-PR26568-1-dwarf.o.abi} (58%)
 rename tests/data/{test-read-dwarf => test-read-common}/test-PR26568-1.c (61%)
 create mode 100644 tests/data/test-read-common/test-PR26568-2-ctf.o.abi
 rename tests/data/{test-read-dwarf/test-PR26568-2.o.abi => test-read-common/test-PR26568-2-dwarf.o.abi} (59%)
 rename tests/data/{test-read-dwarf => test-read-common}/test-PR26568-2.c (56%)
 rename tests/data/{test-read-dwarf/test3-alias-1.so.hash.abi => test-read-common/test3-alias-1-dwarf.so.hash.abi} (57%)
 rename tests/data/{test-read-dwarf => test-read-common}/test3-alias-1.suppr (100%)
 rename tests/data/{test-read-dwarf/test3-alias-2.so.hash.abi => test-read-common/test3-alias-2-dwarf.so.hash.abi} (73%)
 rename tests/data/{test-read-dwarf => test-read-common}/test3-alias-2.suppr (100%)
 rename tests/data/{test-read-dwarf/test3-alias-3.so.hash.abi => test-read-common/test3-alias-3-dwarf.so.hash.abi} (57%)
 rename tests/data/{test-read-dwarf => test-read-common}/test3-alias-3.suppr (100%)
 rename tests/data/{test-read-dwarf/test3-alias-4.so.hash.abi => test-read-common/test3-alias-4-dwarf.so.hash.abi} (74%)
 rename tests/data/{test-read-dwarf => test-read-common}/test3-alias-4.suppr (100%)
 create mode 100644 tests/data/test-read-common/test3-ctf.so.abi
 create mode 100644 tests/data/test-read-common/test3-ctf.so.hash.abi
 rename tests/data/{test-read-dwarf/test3.so.abi => test-read-common/test3-dwarf.so.abi} (75%)
 rename tests/data/{test-read-dwarf/test3.so.hash.abi => test-read-common/test3-dwarf.so.hash.abi} (75%)
 create mode 100644 tests/data/test-read-common/test3.c
 create mode 100755 tests/data/test-read-common/test3.so
 create mode 100644 tests/data/test-read-common/test4-ctf.so.abi
 create mode 100644 tests/data/test-read-common/test4-ctf.so.hash.abi
 rename tests/data/{test-read-dwarf/test4.so.abi => test-read-common/test4-dwarf.so.abi} (56%)
 rename tests/data/{test-read-dwarf/test4.so.hash.abi => test-read-common/test4-dwarf.so.hash.abi} (55%)
 create mode 100644 tests/data/test-read-common/test4.c
 create mode 100755 tests/data/test-read-common/test4.so
 create mode 100644 tests/data/test-read-ctf/test-alias.c
 create mode 100644 tests/data/test-read-ctf/test-alias.o.abi
 create mode 100644 tests/data/test-read-ctf/test-ambiguous-struct-A.c
 create mode 100644 tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi
 create mode 100644 tests/data/test-read-ctf/test-ambiguous-struct-B.c
 create mode 100644 tests/data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi
 create mode 100644 tests/data/test-read-ctf/test-conflicting-type-syms-a.c
 create mode 100644 tests/data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi
 create mode 100644 tests/data/test-read-ctf/test-conflicting-type-syms-b.c
 create mode 100644 tests/data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi
 create mode 100644 tests/data/test-read-ctf/test-enum-ctf.c
 create mode 100644 tests/data/test-read-ctf/test-enum-ctf.o.abi
 create mode 100644 tests/data/test-read-ctf/test-enum-many-ctf.c
 create mode 100644 tests/data/test-read-ctf/test-enum-many-ctf.o.hash.abi
 create mode 100644 tests/data/test-read-ctf/test-enum-symbol-ctf.c
 create mode 100644 tests/data/test-read-ctf/test-enum-symbol-ctf.o.hash.abi
 create mode 100644 tests/data/test-read-ctf/test-struct-iteration-ctf.c
 create mode 100644 tests/data/test-read-ctf/test-struct-iteration-ctf.o.abi
 create mode 100755 tests/data/test-read-ctf/test0
 create mode 100644 tests/data/test-read-ctf/test0.abi
 create mode 100644 tests/data/test-read-ctf/test0.c
 create mode 100644 tests/data/test-read-ctf/test0.hash.abi
 create mode 100644 tests/data/test-read-ctf/test1.c
 create mode 100755 tests/data/test-read-ctf/test1.so
 create mode 100644 tests/data/test-read-ctf/test1.so.abi
 create mode 100644 tests/data/test-read-ctf/test1.so.hash.abi
 create mode 100644 tests/data/test-read-ctf/test2.c
 create mode 100755 tests/data/test-read-ctf/test2.so
 create mode 100644 tests/data/test-read-ctf/test2.so.abi
 create mode 100644 tests/data/test-read-ctf/test2.so.hash.abi
 delete mode 100644 tests/data/test-read-dwarf/PR26261/Makefile
 delete mode 100755 tests/data/test-read-dwarf/PR26261/PR26261-exe
 delete mode 100644 tests/data/test-read-dwarf/PR27700/test-PR27700.o
 delete mode 100644 tests/data/test-read-dwarf/test-PR26568-1.o
 delete mode 100644 tests/data/test-read-dwarf/test-PR26568-2.o
 delete mode 100644 tests/data/test-read-dwarf/test3.c
 delete mode 100755 tests/data/test-read-dwarf/test3.so
 delete mode 100644 tests/data/test-read-dwarf/test4.c
 delete mode 100755 tests/data/test-read-dwarf/test4.so
 create mode 100644 tests/test-read-common.cc
 create mode 100644 tests/test-read-common.h
 create mode 100644 tests/test-read-ctf.cc
  

Comments

Jose E. Marchesi Nov. 23, 2021, 3:48 p.m. UTC | #1
I have a couple of general comments/questions regarding libabigail
testing and DWARF/CTF.

1) The usage of diff in the testsuite puzzles me.  I would have expected
   to find at least two kinds of tests in the testsuite:

   a) Tests testing the frontend/readers, which can assume the XML
      reader and comparison algorithm works properly.

   b) Tests testing the comparison algorithm, which can assume the
      frontend/readers work properly.

   This way no external comparison (like diffing) would be necessary.
   Is this not the case?

2) I am surprised by the fact the CTF reader seems to be working as good
   as the DWARF reader re. the testsuite.  Not buying it.  I think that
   the testsuite skips .cc tests when testing CTF support.

   So I wonder... to what extent are C features (not C++) tested using
   .cc files?  If we want good coverage for both DWARF and CTF (and
   eventually BTF or other formats not supporting C++) then we would
   need to turn these .cc files into .c files...

> Hello libabigail team,
>
> This patch includes regression tests v2 for CTF.
>
> The change from v1 is disable CTF test alias, because
> currently is is not supported.
>
> Dependencies/limitations:
>
> * It was worked on the top of the following patches:
>  https://sourceware.org/pipermail/libabigail/2021q4/003853.html
>
> * Some CTF tests were *disabled* because it generates the XML ABI
> corpus with *same information* but the XML nodes *are not* always
> in the *same order*, so using diff command fails. Details here:
> https://sourceware.org/pipermail/libabigail/2021q4/003824.html
>
> Comments will be appreciated.
>
> Thanks in advanced!,
> Guillermo
>
> This patch implements some regression tests for ctf reading.
> Since the code share a lot of functionalities already used
> in the readi-dwarf test, a library was built and test common
> harness were moved to a common location. So input files for
> test-read-{dwarf,ctf}.cc now are located in:
> tests/data/test-read-common directory, ABIs description are
> stored in the same location but in a separate file, one for
> each binary debugging information: (e.g, test4-ctf.so.abi
> and test4-dwarf.so.abi)
>
> 	* tests/test-read-ctf.cc: New ctf reading regression test.
> 	* tests/test-read-common.cc: New library to be used with
> 	test-read-{ctf,dwarf}.cc.
> 	* tests/test-read-common.h: Likewise.
> 	* tests/test-annotate.cc (in_out_specs): Adjust path for input files.
> 	* tests/Makefile.am: Build new tests/test-read-ctf.cc file.
> 	Add libtestreadcommon.a test library and use it for test-read-{ctf,dwarf}.
> 	* tests/test-read-dwarf.cc: Adapt test to use libtestreadcommon.a in
> 	test-read-common.{cc,h}.
> 	* tests/data/test-annotate/test3.so.abi: Adjust ELF input path file
> 	location to ./tests/data/test-read-common.
> 	* tests/data/test-annotate/test4.so.abi: Likewise.
> 	* tests/data/test-read-common/PR26261: Move test harness to
> 	test-read-common directory.
> 	* tests/data/test-read-common/PR27700: Likewise.
> 	* tests/data/test-read-common/test-PR26568-*: Likewise.
> 	* tests/data/test-read-common/test3*: Likewise.
> 	* tests/data/test-read-common/test4*: Likewise.
> 	* tests/data/test-read-common/crti*: Helper object to export
> 	_init and _fini sysmbols.
> 	* tests/data/test-read-ctf/test-ambiguous-struct-A.c: New testcase.
> 	* tests/data/test-read-ctf/test-ambiguous-struct-B.c: Likewise.
> 	* tests/data/test-read-ctf/test-conflicting-type-syms-a.c: Likewise.
> 	* tests/data/test-read-ctf/test-conflicting-type-syms-b.c: Likewise.
> 	* tests/data/test-read-ctf/test-enum-ctf.c: Likewise.
> 	* tests/data/test-read-ctf/test-enum-many-ctf.c: Likewise.
> 	* tests/data/test-read-ctf/test-enum-symbol-ctf.c: Likewise.
> 	* tests/data/test-read-ctf/test-struct-iteration-ctf.c: Likewise.
> 	* tests/data/test-read-ctf/test0.c: Likewise.
> 	* tests/data/test-read-ctf/test1.c: Likewise.
> 	* tests/data/test-read-ctf/test2.c: Likewise.
> 	* tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi:
> 	Testcase expected result.
> 	* tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi: Likewise.
> 	* tests/data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi: Likewise.
> 	* tests/data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi: Likewise.
> 	* tests/data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi: Likewise.
> 	* tests/data/test-read-ctf/test-enum-ctf.o.abi: Likewise.
> 	* tests/data/test-read-ctf/test-enum-many-ctf.o.hash.abi: Likewise.
> 	* tests/data/test-read-ctf/test-enum-symbol-ctf.o.hash.abi: Likewise.
> 	* tests/data/test-read-ctf/test-struct-iteration-ctf.o.abi: Likewise.
> 	* tests/data/test-read-ctf/test0: Likewise.
> 	* tests/data/test-read-ctf/test0.abi: Likewise.
> 	* tests/data/test-read-ctf/test0.hash.abi: Likewise.
> 	* tests/data/test-read-ctf/test1.so: Likewise.
> 	* tests/data/test-read-ctf/test1.so.abi: Likewise.
> 	* tests/data/test-read-ctf/test1.so.hash.abi: Likewise.
> 	* tests/data/test-read-ctf/test2.so: Likewise.
> 	* tests/data/test-read-ctf/test2.so.abi: Likewise.
> 	* tests/data/test-read-ctf/test2.so.hash.abi: Likewise.
>
> Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
> ---
>  tests/Makefile.am                             |  24 +-
>  tests/data/test-annotate/test3.so.abi         |   4 +-
>  tests/data/test-annotate/test4.so.abi         |  10 +-
>  .../data/test-read-common/PR26261/PR26261-exe | Bin 0 -> 19008 bytes
>  .../PR26261/PR26261-exe-ctf.abi               |  58 +++
>  .../PR26261/PR26261-exe-dwarf.abi}            |  52 ++-
>  .../PR26261/PR26261-main.c                    |   0
>  .../PR26261/PR26261-obja.c                    |   0
>  .../PR26261/PR26261-obja.h                    |   0
>  .../PR26261/PR26261-objb.c                    |   0
>  .../PR26261/PR26261-objb.h                    |   0
>  .../PR27700/include-dir/priv.h                |   0
>  .../PR27700/include-dir/pub.h                 |   0
>  .../PR27700/pub-incdir/inc.h                  |   0
>  .../PR27700/test-PR27700-ctf.abi              |  22 ++
>  .../PR27700/test-PR27700-dwarf.abi}           |   8 +-
>  .../PR27700/test-PR27700.c                    |   2 +
>  tests/data/test-read-common/crti.c            |  22 ++
>  .../test-read-common/test-PR26568-1-ctf.o.abi |  56 +++
>  .../test-PR26568-1-dwarf.o.abi}               |  20 +-
>  .../test-PR26568-1.c                          |   3 +
>  .../test-read-common/test-PR26568-2-ctf.o.abi |  39 ++
>  .../test-PR26568-2-dwarf.o.abi}               |  18 +-
>  .../test-PR26568-2.c                          |   3 +
>  .../test3-alias-1-dwarf.so.hash.abi}          |   6 +-
>  .../test3-alias-1.suppr                       |   0
>  .../test3-alias-2-dwarf.so.hash.abi}          |   6 +-
>  .../test3-alias-2.suppr                       |   0
>  .../test3-alias-3-dwarf.so.hash.abi}          |   6 +-
>  .../test3-alias-3.suppr                       |   0
>  .../test3-alias-4-dwarf.so.hash.abi}          |   2 +-
>  .../test3-alias-4.suppr                       |   0
>  tests/data/test-read-common/test3-ctf.so.abi  |  12 +
>  .../test-read-common/test3-ctf.so.hash.abi    |  12 +
>  .../test3-dwarf.so.abi}                       |   6 +-
>  .../test3-dwarf.so.hash.abi}                  |   6 +-
>  tests/data/test-read-common/test3.c           |  26 ++
>  tests/data/test-read-common/test3.so          | Bin 0 -> 14824 bytes
>  tests/data/test-read-common/test4-ctf.so.abi  |  14 +
>  .../test-read-common/test4-ctf.so.hash.abi    |  14 +
>  .../test4-dwarf.so.abi}                       |  12 +-
>  .../test4-dwarf.so.hash.abi}                  |  12 +-
>  tests/data/test-read-common/test4.c           |  11 +
>  tests/data/test-read-common/test4.so          | Bin 0 -> 16560 bytes
>  tests/data/test-read-ctf/test-alias.c         |  15 +
>  tests/data/test-read-ctf/test-alias.o.abi     |  19 +
>  .../test-read-ctf/test-ambiguous-struct-A.c   |   8 +
>  .../test-ambiguous-struct-A.o.hash.abi        |  36 ++
>  .../test-read-ctf/test-ambiguous-struct-B.c   |   5 +
>  .../test-ambiguous-struct-B.o.hash.abi        |  23 ++
>  .../test-conflicting-type-syms-a.c            |   5 +
>  .../test-conflicting-type-syms-a.o.hash.abi   |  14 +
>  .../test-conflicting-type-syms-b.c            |   5 +
>  .../test-conflicting-type-syms-b.o.hash.abi   |  13 +
>  tests/data/test-read-ctf/test-enum-ctf.c      |   8 +
>  tests/data/test-read-ctf/test-enum-ctf.o.abi  |  24 ++
>  tests/data/test-read-ctf/test-enum-many-ctf.c |  10 +
>  .../test-enum-many-ctf.o.hash.abi             |  69 ++++
>  .../data/test-read-ctf/test-enum-symbol-ctf.c |   1 +
>  .../test-enum-symbol-ctf.o.hash.abi           |  16 +
>  .../test-read-ctf/test-struct-iteration-ctf.c |  28 ++
>  .../test-struct-iteration-ctf.o.abi           |  96 +++++
>  tests/data/test-read-ctf/test0                | Bin 0 -> 16656 bytes
>  tests/data/test-read-ctf/test0.abi            |  54 +++
>  tests/data/test-read-ctf/test0.c              |  32 ++
>  tests/data/test-read-ctf/test0.hash.abi       |  54 +++
>  tests/data/test-read-ctf/test1.c              |  25 ++
>  tests/data/test-read-ctf/test1.so             | Bin 0 -> 15592 bytes
>  tests/data/test-read-ctf/test1.so.abi         |  23 ++
>  tests/data/test-read-ctf/test1.so.hash.abi    |  23 ++
>  tests/data/test-read-ctf/test2.c              |  19 +
>  tests/data/test-read-ctf/test2.so             | Bin 0 -> 15616 bytes
>  tests/data/test-read-ctf/test2.so.abi         |  25 ++
>  tests/data/test-read-ctf/test2.so.hash.abi    |  25 ++
>  tests/data/test-read-dwarf/PR26261/Makefile   |  21 -
>  .../data/test-read-dwarf/PR26261/PR26261-exe  | Bin 10976 -> 0 bytes
>  .../test-read-dwarf/PR27700/test-PR27700.o    | Bin 3248 -> 0 bytes
>  tests/data/test-read-dwarf/test-PR26568-1.o   | Bin 2864 -> 0 bytes
>  tests/data/test-read-dwarf/test-PR26568-2.o   | Bin 2824 -> 0 bytes
>  tests/data/test-read-dwarf/test3.c            |  11 -
>  tests/data/test-read-dwarf/test3.so           | Bin 8851 -> 0 bytes
>  tests/data/test-read-dwarf/test4.c            |  14 -
>  tests/data/test-read-dwarf/test4.so           | Bin 3364 -> 0 bytes
>  tests/test-annotate.cc                        |   4 +-
>  tests/test-read-common.cc                     | 184 +++++++++
>  tests/test-read-common.h                      | 148 +++++++
>  tests/test-read-ctf.cc                        | 290 ++++++++++++++
>  tests/test-read-dwarf.cc                      | 362 +++++++-----------
>  88 files changed, 1829 insertions(+), 366 deletions(-)
>  create mode 100755 tests/data/test-read-common/PR26261/PR26261-exe
>  create mode 100644 tests/data/test-read-common/PR26261/PR26261-exe-ctf.abi
>  rename tests/data/{test-read-dwarf/PR26261/PR26261-exe.abi => test-read-common/PR26261/PR26261-exe-dwarf.abi} (53%)
>  rename tests/data/{test-read-dwarf => test-read-common}/PR26261/PR26261-main.c (100%)
>  rename tests/data/{test-read-dwarf => test-read-common}/PR26261/PR26261-obja.c (100%)
>  rename tests/data/{test-read-dwarf => test-read-common}/PR26261/PR26261-obja.h (100%)
>  rename tests/data/{test-read-dwarf => test-read-common}/PR26261/PR26261-objb.c (100%)
>  rename tests/data/{test-read-dwarf => test-read-common}/PR26261/PR26261-objb.h (100%)
>  rename tests/data/{test-read-dwarf => test-read-common}/PR27700/include-dir/priv.h (100%)
>  rename tests/data/{test-read-dwarf => test-read-common}/PR27700/include-dir/pub.h (100%)
>  rename tests/data/{test-read-dwarf => test-read-common}/PR27700/pub-incdir/inc.h (100%)
>  create mode 100644 tests/data/test-read-common/PR27700/test-PR27700-ctf.abi
>  rename tests/data/{test-read-dwarf/PR27700/test-PR27700.abi => test-read-common/PR27700/test-PR27700-dwarf.abi} (60%)
>  rename tests/data/{test-read-dwarf => test-read-common}/PR27700/test-PR27700.c (55%)
>  create mode 100644 tests/data/test-read-common/crti.c
>  create mode 100644 tests/data/test-read-common/test-PR26568-1-ctf.o.abi
>  rename tests/data/{test-read-dwarf/test-PR26568-1.o.abi => test-read-common/test-PR26568-1-dwarf.o.abi} (58%)
>  rename tests/data/{test-read-dwarf => test-read-common}/test-PR26568-1.c (61%)
>  create mode 100644 tests/data/test-read-common/test-PR26568-2-ctf.o.abi
>  rename tests/data/{test-read-dwarf/test-PR26568-2.o.abi => test-read-common/test-PR26568-2-dwarf.o.abi} (59%)
>  rename tests/data/{test-read-dwarf => test-read-common}/test-PR26568-2.c (56%)
>  rename tests/data/{test-read-dwarf/test3-alias-1.so.hash.abi => test-read-common/test3-alias-1-dwarf.so.hash.abi} (57%)
>  rename tests/data/{test-read-dwarf => test-read-common}/test3-alias-1.suppr (100%)
>  rename tests/data/{test-read-dwarf/test3-alias-2.so.hash.abi => test-read-common/test3-alias-2-dwarf.so.hash.abi} (73%)
>  rename tests/data/{test-read-dwarf => test-read-common}/test3-alias-2.suppr (100%)
>  rename tests/data/{test-read-dwarf/test3-alias-3.so.hash.abi => test-read-common/test3-alias-3-dwarf.so.hash.abi} (57%)
>  rename tests/data/{test-read-dwarf => test-read-common}/test3-alias-3.suppr (100%)
>  rename tests/data/{test-read-dwarf/test3-alias-4.so.hash.abi => test-read-common/test3-alias-4-dwarf.so.hash.abi} (74%)
>  rename tests/data/{test-read-dwarf => test-read-common}/test3-alias-4.suppr (100%)
>  create mode 100644 tests/data/test-read-common/test3-ctf.so.abi
>  create mode 100644 tests/data/test-read-common/test3-ctf.so.hash.abi
>  rename tests/data/{test-read-dwarf/test3.so.abi => test-read-common/test3-dwarf.so.abi} (75%)
>  rename tests/data/{test-read-dwarf/test3.so.hash.abi => test-read-common/test3-dwarf.so.hash.abi} (75%)
>  create mode 100644 tests/data/test-read-common/test3.c
>  create mode 100755 tests/data/test-read-common/test3.so
>  create mode 100644 tests/data/test-read-common/test4-ctf.so.abi
>  create mode 100644 tests/data/test-read-common/test4-ctf.so.hash.abi
>  rename tests/data/{test-read-dwarf/test4.so.abi => test-read-common/test4-dwarf.so.abi} (56%)
>  rename tests/data/{test-read-dwarf/test4.so.hash.abi => test-read-common/test4-dwarf.so.hash.abi} (55%)
>  create mode 100644 tests/data/test-read-common/test4.c
>  create mode 100755 tests/data/test-read-common/test4.so
>  create mode 100644 tests/data/test-read-ctf/test-alias.c
>  create mode 100644 tests/data/test-read-ctf/test-alias.o.abi
>  create mode 100644 tests/data/test-read-ctf/test-ambiguous-struct-A.c
>  create mode 100644 tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi
>  create mode 100644 tests/data/test-read-ctf/test-ambiguous-struct-B.c
>  create mode 100644 tests/data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi
>  create mode 100644 tests/data/test-read-ctf/test-conflicting-type-syms-a.c
>  create mode 100644 tests/data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi
>  create mode 100644 tests/data/test-read-ctf/test-conflicting-type-syms-b.c
>  create mode 100644 tests/data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi
>  create mode 100644 tests/data/test-read-ctf/test-enum-ctf.c
>  create mode 100644 tests/data/test-read-ctf/test-enum-ctf.o.abi
>  create mode 100644 tests/data/test-read-ctf/test-enum-many-ctf.c
>  create mode 100644 tests/data/test-read-ctf/test-enum-many-ctf.o.hash.abi
>  create mode 100644 tests/data/test-read-ctf/test-enum-symbol-ctf.c
>  create mode 100644 tests/data/test-read-ctf/test-enum-symbol-ctf.o.hash.abi
>  create mode 100644 tests/data/test-read-ctf/test-struct-iteration-ctf.c
>  create mode 100644 tests/data/test-read-ctf/test-struct-iteration-ctf.o.abi
>  create mode 100755 tests/data/test-read-ctf/test0
>  create mode 100644 tests/data/test-read-ctf/test0.abi
>  create mode 100644 tests/data/test-read-ctf/test0.c
>  create mode 100644 tests/data/test-read-ctf/test0.hash.abi
>  create mode 100644 tests/data/test-read-ctf/test1.c
>  create mode 100755 tests/data/test-read-ctf/test1.so
>  create mode 100644 tests/data/test-read-ctf/test1.so.abi
>  create mode 100644 tests/data/test-read-ctf/test1.so.hash.abi
>  create mode 100644 tests/data/test-read-ctf/test2.c
>  create mode 100755 tests/data/test-read-ctf/test2.so
>  create mode 100644 tests/data/test-read-ctf/test2.so.abi
>  create mode 100644 tests/data/test-read-ctf/test2.so.hash.abi
>  delete mode 100644 tests/data/test-read-dwarf/PR26261/Makefile
>  delete mode 100755 tests/data/test-read-dwarf/PR26261/PR26261-exe
>  delete mode 100644 tests/data/test-read-dwarf/PR27700/test-PR27700.o
>  delete mode 100644 tests/data/test-read-dwarf/test-PR26568-1.o
>  delete mode 100644 tests/data/test-read-dwarf/test-PR26568-2.o
>  delete mode 100644 tests/data/test-read-dwarf/test3.c
>  delete mode 100755 tests/data/test-read-dwarf/test3.so
>  delete mode 100644 tests/data/test-read-dwarf/test4.c
>  delete mode 100755 tests/data/test-read-dwarf/test4.so
>  create mode 100644 tests/test-read-common.cc
>  create mode 100644 tests/test-read-common.h
>  create mode 100644 tests/test-read-ctf.cc
>
> diff --git a/tests/Makefile.am b/tests/Makefile.am
> index e3855aea..17e2d4b4 100644
> --- a/tests/Makefile.am
> +++ b/tests/Makefile.am
> @@ -25,6 +25,10 @@ runtestdifffilter		\
>  runtestreaddwarf	        \
>  runtestcanonicalizetypes.sh
>  
> +if CTF_READER
> +TESTS += runtestreadctf
> +endif
> +
>  # rather cheap tests
>  TESTS+=				\
>  runtestabicompat		\
> @@ -72,7 +76,7 @@ runtestcanonicalizetypes.output.final.txt
>  
>  noinst_PROGRAMS= $(TESTS) testirwalker testdiff2 printdifftree
>  noinst_SCRIPTS = mockfedabipkgdiff
> -noinst_LTLIBRARIES = libtestutils.la libcatch.la
> +noinst_LTLIBRARIES = libtestutils.la libtestreadcommon.la libcatch.la
>  
>  libtestutils_la_SOURCES=	\
>  test-utils.h 			\
> @@ -82,15 +86,31 @@ libtestutils_la_CXXFLAGS=		\
>  -DABIGAIL_SRC_DIR=\"${abs_top_srcdir}\"  	\
>  -DABIGAIL_BUILD_DIR=\"${abs_top_builddir}\"
>  
> +libtestreadcommon_la_SOURCES=	\
> +test-read-common.h 		\
> +test-read-common.cc
> +
> +libtestreadcommon_la_CXXFLAGS=			\
> +-DABIGAIL_SRC_DIR=\"${abs_top_srcdir}\"  	\
> +-DABIGAIL_BUILD_DIR=\"${abs_top_builddir}\"
> +
>  libcatch_la_SOURCES = lib/catch.cc lib/catch.hpp
>  
>  runtestreadwrite_SOURCES=test-read-write.cc
>  runtestreadwrite_LDADD=libtestutils.la $(top_builddir)/src/libabigail.la
>  
>  runtestreaddwarf_SOURCES=test-read-dwarf.cc
> -runtestreaddwarf_LDADD=libtestutils.la $(top_builddir)/src/libabigail.la
> +runtestreaddwarf_LDADD=libtestreadcommon.la libtestutils.la	\
> +		       $(top_builddir)/src/libabigail.la
>  runtestreaddwarf_LDFLAGS=-pthread
>  
> +if CTF_READER
> +runtestreadctf_SOURCES=test-read-ctf.cc
> +runtestreadctf_LDADD=libtestreadcommon.la libtestutils.la	\
> +		     $(top_builddir)/src/libabigail.la
> +runtestreadctf_LDFLAGS=-pthread
> +endif
> +
>  runtestannotate_SOURCES=test-annotate.cc
>  runtestannotate_LDADD=libtestutils.la $(top_builddir)/src/libabigail.la
>  
> diff --git a/tests/data/test-annotate/test3.so.abi b/tests/data/test-annotate/test3.so.abi
> index c4911724..320d886a 100644
> --- a/tests/data/test-annotate/test3.so.abi
> +++ b/tests/data/test-annotate/test3.so.abi
> @@ -16,9 +16,9 @@
>      <!-- foo__ -->
>      <elf-symbol name='foo__' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
>    </elf-function-symbols>
> -  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf' language='LANG_C89'>
> +  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
>      <!-- void __foo() -->
> -    <function-decl name='__foo' mangled-name='__foo' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test3.c' line='8' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
> +    <function-decl name='__foo' mangled-name='__foo' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test3.c' line='23' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
>        <!-- void -->
>        <return type-id='type-id-1'/>
>      </function-decl>
> diff --git a/tests/data/test-annotate/test4.so.abi b/tests/data/test-annotate/test4.so.abi
> index c3550e35..7913e324 100644
> --- a/tests/data/test-annotate/test4.so.abi
> +++ b/tests/data/test-annotate/test4.so.abi
> @@ -6,7 +6,7 @@
>      <!-- cpy -->
>      <elf-symbol name='cpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
>    </elf-function-symbols>
> -  <abi-instr address-size='64' path='test4.c' comp-dir-path='/home/mark/src/tests' language='LANG_C89'>
> +  <abi-instr address-size='64' path='test4.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C99'>
>      <!-- char -->
>      <type-decl name='char' size-in-bits='8' id='type-id-1'/>
>      <!-- unsigned int -->
> @@ -22,13 +22,13 @@
>      <!-- const char* restrict -->
>      <qualified-type-def type-id='type-id-6' restrict='yes' id='type-id-7'/>
>      <!-- char* cpy(char* restrict, const char* restrict, unsigned int) -->
> -    <function-decl name='cpy' mangled-name='cpy' filepath='/home/mark/src/tests/test4.c' line='2' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cpy'>
> +    <function-decl name='cpy' mangled-name='cpy' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cpy'>
>        <!-- parameter of type 'char* restrict' -->
> -      <parameter type-id='type-id-4' name='s1' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
> +      <parameter type-id='type-id-4' name='s1' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
>        <!-- parameter of type 'const char* restrict' -->
> -      <parameter type-id='type-id-7' name='s2' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
> +      <parameter type-id='type-id-7' name='s2' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
>        <!-- parameter of type 'unsigned int' -->
> -      <parameter type-id='type-id-2' name='n' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
> +      <parameter type-id='type-id-2' name='n' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
>        <!-- char* -->
>        <return type-id='type-id-3'/>
>      </function-decl>
> diff --git a/tests/data/test-read-common/PR26261/PR26261-exe b/tests/data/test-read-common/PR26261/PR26261-exe
> new file mode 100755
> index 0000000000000000000000000000000000000000..939e8071509f568b3628fc0ca6c3434a2de62cb6
> GIT binary patch
> literal 19008
> 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
>
> literal 0
> HcmV?d00001
>
> diff --git a/tests/data/test-read-common/PR26261/PR26261-exe-ctf.abi b/tests/data/test-read-common/PR26261/PR26261-exe-ctf.abi
> new file mode 100644
> index 00000000..cb2e2f13
> --- /dev/null
> +++ b/tests/data/test-read-common/PR26261/PR26261-exe-ctf.abi
> @@ -0,0 +1,58 @@
> +<abi-corpus version='2.1' path='data/test-read-common/PR26261/PR26261-exe'>
> +  <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='_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 address-size='64' language='LANG_C'>
> +    <type-decl name='char' size-in-bits='8' alignment-in-bits='8' id='type-id-1'/>
> +    <class-decl name='SA' size-in-bits='192' alignment-in-bits='32' is-struct='yes' visibility='default' id='type-id-2'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='m1' type-id='type-id-3' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='64'>
> +        <var-decl name='m2' type-id='type-id-4' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='128'>
> +        <var-decl name='m3' type-id='type-id-5' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <class-decl name='SB' size-in-bits='128' alignment-in-bits='32' is-struct='yes' visibility='default' id='type-id-6'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='m1' type-id='type-id-3' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='64'>
> +        <var-decl name='m2' type-id='type-id-7' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-3'/>
> +    <typedef-decl name='fn_ptr_type_a2_t' type-id='type-id-8' id='type-id-5'/>
> +    <typedef-decl name='fn_ptr_type_a_t' type-id='type-id-8' id='type-id-4'/>
> +    <typedef-decl name='fn_ptr_type_b_t' type-id='type-id-9' id='type-id-7'/>
> +    <pointer-type-def type-id='type-id-2' size-in-bits='64' alignment-in-bits='64' id='type-id-10'/>
> +    <pointer-type-def type-id='type-id-6' size-in-bits='64' alignment-in-bits='64' id='type-id-11'/>
> +    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-12'/>
> +    <pointer-type-def type-id='type-id-12' size-in-bits='64' alignment-in-bits='64' id='type-id-13'/>
> +    <pointer-type-def type-id='type-id-14' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
> +    <pointer-type-def type-id='type-id-15' size-in-bits='64' alignment-in-bits='64' id='type-id-9'/>
> +    <function-type size-in-bits='64' alignment-in-bits='8' id='type-id-14'>
> +      <parameter type-id='type-id-3'/>
> +      <parameter type-id='type-id-3'/>
> +      <return type-id='type-id-16'/>
> +    </function-type>
> +    <function-type size-in-bits='64' alignment-in-bits='8' id='type-id-15'>
> +      <parameter type-id='type-id-3'/>
> +      <parameter type-id='type-id-3'/>
> +      <parameter type-id='type-id-1'/>
> +      <return type-id='type-id-16'/>
> +    </function-type>
> +    <type-decl name='void' id='type-id-16'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-exe.abi b/tests/data/test-read-common/PR26261/PR26261-exe-dwarf.abi
> similarity index 53%
> rename from tests/data/test-read-dwarf/PR26261/PR26261-exe.abi
> rename to tests/data/test-read-common/PR26261/PR26261-exe-dwarf.abi
> index a24f3a44..cd631bf1 100644
> --- a/tests/data/test-read-dwarf/PR26261/PR26261-exe.abi
> +++ b/tests/data/test-read-common/PR26261/PR26261-exe-dwarf.abi
> @@ -1,12 +1,10 @@
> -<abi-corpus version='2.1' path='data/test-read-dwarf/PR26261/PR26261-exe'>
> +<abi-corpus version='2.1' path='data/test-read-common/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'/>
> @@ -16,18 +14,18 @@
>    <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 address-size='64' path='PR26261-main.c' comp-dir-path='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261' language='LANG_C89'>
> +  <abi-instr address-size='64' path='PR26261-main.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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'/>
> +    <function-decl name='wrapped_call' mangled-name='wrapped_call' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-main.c' line='18' column='1'/>
> +      <parameter type-id='type-id-5' name='a' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-main.c' line='19' column='1'/>
> +      <parameter type-id='type-id-5' name='b' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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'/>
> +    <function-decl name='main' mangled-name='main' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-main.c' line='27' column='1'/>
> +      <parameter type-id='type-id-3' name='argv' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-main.c' line='27' column='1'/>
>        <return type-id='type-id-5'/>
>      </function-decl>
>      <function-type size-in-bits='64' id='type-id-7'>
> @@ -36,44 +34,44 @@
>        <return type-id='type-id-6'/>
>      </function-type>
>    </abi-instr>
> -  <abi-instr address-size='64' path='PR26261-obja.c' comp-dir-path='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261' language='LANG_C89'>
> +  <abi-instr address-size='64' path='PR26261-obja.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261' language='LANG_C89'>
>      <type-decl name='int' size-in-bits='32' id='type-id-5'/>
> -    <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'/>
> -    <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-10'>
> +    <typedef-decl name='fn_ptr_type_a_t' type-id='type-id-4' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-obja.h' line='3' column='1' id='type-id-9'/>
> +    <class-decl name='SA' size-in-bits='192' is-struct='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-obja.h' line='5' column='1' id='type-id-10'>
>        <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'/>
> +        <var-decl name='m1' type-id='type-id-5' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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'/>
> +        <var-decl name='m2' type-id='type-id-8' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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'/>
> +        <var-decl name='m3' type-id='type-id-9' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-obja.h' line='9' column='1'/>
>        </data-member>
>      </class-decl>
>      <pointer-type-def type-id='type-id-10' size-in-bits='64' id='type-id-11'/>
>      <pointer-type-def type-id='type-id-7' 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-11' name='s' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-obja.c' line='4' column='1'/>
> +    <function-decl name='fun_obja' mangled-name='fun_obja' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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-11' name='s' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-obja.c' line='4' column='1'/>
>        <return type-id='type-id-6'/>
>      </function-decl>
>      <type-decl name='void' id='type-id-6'/>
>    </abi-instr>
> -  <abi-instr address-size='64' path='PR26261-objb.c' comp-dir-path='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261' language='LANG_C89'>
> +  <abi-instr address-size='64' path='PR26261-objb.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261' language='LANG_C89'>
>      <type-decl name='char' size-in-bits='8' id='type-id-1'/>
> -    <typedef-decl name='fn_ptr_type_b_t' type-id='type-id-12' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-objb.h' line='1' column='1' id='type-id-13'/>
> -    <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-14'>
> +    <typedef-decl name='fn_ptr_type_b_t' type-id='type-id-12' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-objb.h' line='1' column='1' id='type-id-13'/>
> +    <class-decl name='SB' size-in-bits='128' is-struct='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-objb.h' line='3' column='1' id='type-id-14'>
>        <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'/>
> +        <var-decl name='m1' type-id='type-id-5' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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'/>
> +        <var-decl name='m2' type-id='type-id-13' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-objb.h' line='6' column='1'/>
>        </data-member>
>      </class-decl>
>      <pointer-type-def type-id='type-id-14' size-in-bits='64' id='type-id-15'/>
>      <pointer-type-def type-id='type-id-16' size-in-bits='64' id='type-id-12'/>
> -    <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'/>
> +    <function-decl name='fun_objb' mangled-name='fun_objb' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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/byby/oracle/src/libabigail/tests/data/test-read-common/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'>
> diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-main.c b/tests/data/test-read-common/PR26261/PR26261-main.c
> similarity index 100%
> rename from tests/data/test-read-dwarf/PR26261/PR26261-main.c
> rename to tests/data/test-read-common/PR26261/PR26261-main.c
> diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-obja.c b/tests/data/test-read-common/PR26261/PR26261-obja.c
> similarity index 100%
> rename from tests/data/test-read-dwarf/PR26261/PR26261-obja.c
> rename to tests/data/test-read-common/PR26261/PR26261-obja.c
> diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-obja.h b/tests/data/test-read-common/PR26261/PR26261-obja.h
> similarity index 100%
> rename from tests/data/test-read-dwarf/PR26261/PR26261-obja.h
> rename to tests/data/test-read-common/PR26261/PR26261-obja.h
> diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-objb.c b/tests/data/test-read-common/PR26261/PR26261-objb.c
> similarity index 100%
> rename from tests/data/test-read-dwarf/PR26261/PR26261-objb.c
> rename to tests/data/test-read-common/PR26261/PR26261-objb.c
> diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-objb.h b/tests/data/test-read-common/PR26261/PR26261-objb.h
> similarity index 100%
> rename from tests/data/test-read-dwarf/PR26261/PR26261-objb.h
> rename to tests/data/test-read-common/PR26261/PR26261-objb.h
> diff --git a/tests/data/test-read-dwarf/PR27700/include-dir/priv.h b/tests/data/test-read-common/PR27700/include-dir/priv.h
> similarity index 100%
> rename from tests/data/test-read-dwarf/PR27700/include-dir/priv.h
> rename to tests/data/test-read-common/PR27700/include-dir/priv.h
> diff --git a/tests/data/test-read-dwarf/PR27700/include-dir/pub.h b/tests/data/test-read-common/PR27700/include-dir/pub.h
> similarity index 100%
> rename from tests/data/test-read-dwarf/PR27700/include-dir/pub.h
> rename to tests/data/test-read-common/PR27700/include-dir/pub.h
> diff --git a/tests/data/test-read-dwarf/PR27700/pub-incdir/inc.h b/tests/data/test-read-common/PR27700/pub-incdir/inc.h
> similarity index 100%
> rename from tests/data/test-read-dwarf/PR27700/pub-incdir/inc.h
> rename to tests/data/test-read-common/PR27700/pub-incdir/inc.h
> diff --git a/tests/data/test-read-common/PR27700/test-PR27700-ctf.abi b/tests/data/test-read-common/PR27700/test-PR27700-ctf.abi
> new file mode 100644
> index 00000000..62df1017
> --- /dev/null
> +++ b/tests/data/test-read-common/PR27700/test-PR27700-ctf.abi
> @@ -0,0 +1,22 @@
> +<abi-corpus version='2.1' path='data/test-read-common/PR27700/test-PR27700.o'>
> +  <elf-function-symbols>
> +    <elf-symbol name='foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-function-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='811c9dc5'/>
> +    <enum-decl name='foo' linkage-name='foo' id='022218d8'>
> +      <underlying-type type-id='811c9dc5'/>
> +      <enumerator name='foo_e0' value='0'/>
> +      <enumerator name='foo_e1' value='1'/>
> +      <enumerator name='foo_e2' value='2'/>
> +      <enumerator name='foo_e3' value='3'/>
> +    </enum-decl>
> +    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
> +    <pointer-type-def type-id='022218d8' size-in-bits='64' alignment-in-bits='64' id='8750e847'/>
> +    <function-decl name='foo' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
> +      <parameter type-id='8750e847'/>
> +      <return type-id='48b5725f'/>
> +    </function-decl>
> +    <type-decl name='void' id='48b5725f'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-dwarf/PR27700/test-PR27700.abi b/tests/data/test-read-common/PR27700/test-PR27700-dwarf.abi
> similarity index 60%
> rename from tests/data/test-read-dwarf/PR27700/test-PR27700.abi
> rename to tests/data/test-read-common/PR27700/test-PR27700-dwarf.abi
> index e593f79f..fff6ff74 100644
> --- a/tests/data/test-read-dwarf/PR27700/test-PR27700.abi
> +++ b/tests/data/test-read-common/PR27700/test-PR27700-dwarf.abi
> @@ -1,15 +1,15 @@
> -<abi-corpus version='2.1' path='data/test-read-dwarf/PR27700/test-PR27700.o'>
> +<abi-corpus version='2.1' path='data/test-read-common/PR27700/test-PR27700.o'>
>    <elf-function-symbols>
>      <elf-symbol name='foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
>    </elf-function-symbols>
> -  <abi-instr address-size='64' path='test-PR27700.c' comp-dir-path='/home/dodji/git/libabigail/PR27700/tests/data/test-read-dwarf/PR27700' language='LANG_C11'>
> +  <abi-instr address-size='64' path='test-PR27700.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR27700' language='LANG_C11'>
>      <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
>      <enum-decl name='foo' filepath='include-dir/priv.h' line='1' column='1' id='022218d8'>
>        <underlying-type type-id='9cac1fee'/>
>      </enum-decl>
>      <pointer-type-def type-id='022218d8' size-in-bits='64' id='8750e847'/>
> -    <function-decl name='foo' mangled-name='foo' filepath='/home/dodji/git/libabigail/PR27700/tests/data/test-read-dwarf/PR27700/test-PR27700.c' line='4' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
> -      <parameter type-id='8750e847' name='c' filepath='/home/dodji/git/libabigail/PR27700/tests/data/test-read-dwarf/PR27700/test-PR27700.c' line='4' column='1'/>
> +    <function-decl name='foo' mangled-name='foo' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR27700/test-PR27700.c' line='4' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
> +      <parameter type-id='8750e847' name='c' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR27700/test-PR27700.c' line='4' column='1'/>
>        <return type-id='48b5725f'/>
>      </function-decl>
>      <type-decl name='void' id='48b5725f'/>
> diff --git a/tests/data/test-read-dwarf/PR27700/test-PR27700.c b/tests/data/test-read-common/PR27700/test-PR27700.c
> similarity index 55%
> rename from tests/data/test-read-dwarf/PR27700/test-PR27700.c
> rename to tests/data/test-read-common/PR27700/test-PR27700.c
> index b44a3226..a16a0bb7 100644
> --- a/tests/data/test-read-dwarf/PR27700/test-PR27700.c
> +++ b/tests/data/test-read-common/PR27700/test-PR27700.c
> @@ -1,5 +1,7 @@
>  #include "include-dir/priv.h"
>  
> +/* gcc -I. -gctf -gdwarf -c -o test-PR27700.o test-PR27700.c */
> +
>  void
>  foo(enum foo* c __attribute__((unused)))
>  {
> diff --git a/tests/data/test-read-common/crti.c b/tests/data/test-read-common/crti.c
> new file mode 100644
> index 00000000..47dc4e47
> --- /dev/null
> +++ b/tests/data/test-read-common/crti.c
> @@ -0,0 +1,22 @@
> +/*
> + * gcc -c -std=c89 -mtune=generic -march=x86-64 crti.c
> + *
> + * NOTE: linking with _old_ crti.o exposes _init and _fini as
> + *       global symbols, the newer versions don't.
> + *
> + * 0000000000000000 g     F .init  0000000000000000 .hidden _init
> + * 0000000000000000 g     F .fini  0000000000000000 .hidden _fini
> + *
> + * So this is a dummy c-runtime object.
> + *
> + */
> +
> +void __attribute__((visibility("default")))
> +_init(void)
> +{
> +}
> +
> +void __attribute__((visibility("default")))
> +_fini(void)
> +{
> +}
> diff --git a/tests/data/test-read-common/test-PR26568-1-ctf.o.abi b/tests/data/test-read-common/test-PR26568-1-ctf.o.abi
> new file mode 100644
> index 00000000..d62474ec
> --- /dev/null
> +++ b/tests/data/test-read-common/test-PR26568-1-ctf.o.abi
> @@ -0,0 +1,56 @@
> +<abi-corpus version='2.1' path='data/test-read-common/test-PR26568-1.o'>
> +  <elf-function-symbols>
> +    <elf-symbol name='fun' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-function-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <class-decl name='A' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='type-id-1'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='' type-id='type-id-2' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='' type-id='type-id-3' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='x' type-id='type-id-4' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='' type-id='type-id-5' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='y' type-id='type-id-6' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='x' type-id='type-id-4' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-5'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='y' type-id='type-id-6' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-4'/>
> +    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
> +    <union-decl name='' size-in-bits='64' is-anonymous='yes' visibility='default' id='type-id-2'>
> +      <data-member access='public'>
> +        <var-decl name='' type-id='type-id-3' visibility='default'/>
> +      </data-member>
> +      <data-member access='public'>
> +        <var-decl name='x' type-id='type-id-4' visibility='default'/>
> +      </data-member>
> +      <data-member access='public'>
> +        <var-decl name='' type-id='type-id-5' visibility='default'/>
> +      </data-member>
> +      <data-member access='public'>
> +        <var-decl name='y' type-id='type-id-6' visibility='default'/>
> +      </data-member>
> +    </union-decl>
> +    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
> +    <function-decl name='fun' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
> +      <parameter type-id='type-id-7'/>
> +      <return type-id='type-id-8'/>
> +    </function-decl>
> +    <type-decl name='void' id='type-id-8'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-dwarf/test-PR26568-1.o.abi b/tests/data/test-read-common/test-PR26568-1-dwarf.o.abi
> similarity index 58%
> rename from tests/data/test-read-dwarf/test-PR26568-1.o.abi
> rename to tests/data/test-read-common/test-PR26568-1-dwarf.o.abi
> index 5c891200..046d2d45 100644
> --- a/tests/data/test-read-dwarf/test-PR26568-1.o.abi
> +++ b/tests/data/test-read-common/test-PR26568-1-dwarf.o.abi
> @@ -1,16 +1,16 @@
> -<abi-corpus version='2.1' path='data/test-read-dwarf/test-PR26568-1.o'>
> +<abi-corpus version='2.1' path='data/test-read-common/test-PR26568-1.o'>
>    <elf-function-symbols>
>      <elf-symbol name='fun' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
>    </elf-function-symbols>
> -  <abi-instr address-size='64' path='test-PR26568-1.c' comp-dir-path='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf' language='LANG_C89'>
> +  <abi-instr address-size='64' path='test-PR26568-1.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
>      <type-decl name='int' size-in-bits='32' id='type-id-1'/>
>      <type-decl name='long int' size-in-bits='64' id='type-id-2'/>
> -    <class-decl name='A' size-in-bits='64' is-struct='yes' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='1' column='1' id='type-id-3'>
> +    <class-decl name='A' size-in-bits='64' is-struct='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='4' column='1' id='type-id-3'>
>        <data-member access='public' layout-offset-in-bits='0'>
>          <var-decl name='' type-id='type-id-4' visibility='default'/>
>        </data-member>
>      </class-decl>
> -    <union-decl name='__anonymous_union__' size-in-bits='64' is-anonymous='yes' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='2' column='1' id='type-id-4'>
> +    <union-decl name='__anonymous_union__' size-in-bits='64' is-anonymous='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='5' column='1' id='type-id-4'>
>        <data-member access='public'>
>          <var-decl name='' type-id='type-id-5' visibility='default'/>
>        </data-member>
> @@ -18,19 +18,19 @@
>          <var-decl name='' type-id='type-id-6' visibility='default'/>
>        </data-member>
>      </union-decl>
> -    <class-decl name='__anonymous_struct__' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='3' column='1' id='type-id-5'>
> +    <class-decl name='__anonymous_struct__' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='6' column='1' id='type-id-5'>
>        <data-member access='public' layout-offset-in-bits='0'>
> -        <var-decl name='x' type-id='type-id-1' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='4' column='1'/>
> +        <var-decl name='x' type-id='type-id-1' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='7' column='1'/>
>        </data-member>
>      </class-decl>
> -    <class-decl name='__anonymous_struct__1' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='6' column='1' id='type-id-6'>
> +    <class-decl name='__anonymous_struct__1' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='9' column='1' id='type-id-6'>
>        <data-member access='public' layout-offset-in-bits='0'>
> -        <var-decl name='y' type-id='type-id-2' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='7' column='1'/>
> +        <var-decl name='y' type-id='type-id-2' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='10' column='1'/>
>        </data-member>
>      </class-decl>
>      <pointer-type-def type-id='type-id-3' size-in-bits='64' id='type-id-7'/>
> -    <function-decl name='fun' mangled-name='fun' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='12' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fun'>
> -      <parameter type-id='type-id-7' name='a' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='12' column='1'/>
> +    <function-decl name='fun' mangled-name='fun' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='15' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fun'>
> +      <parameter type-id='type-id-7' name='a' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='15' column='1'/>
>        <return type-id='type-id-8'/>
>      </function-decl>
>      <type-decl name='void' id='type-id-8'/>
> diff --git a/tests/data/test-read-dwarf/test-PR26568-1.c b/tests/data/test-read-common/test-PR26568-1.c
> similarity index 61%
> rename from tests/data/test-read-dwarf/test-PR26568-1.c
> rename to tests/data/test-read-common/test-PR26568-1.c
> index 6eec3558..a551ac7c 100644
> --- a/tests/data/test-read-dwarf/test-PR26568-1.c
> +++ b/tests/data/test-read-common/test-PR26568-1.c
> @@ -1,3 +1,6 @@
> +/* gcc -std=c89 -gctf -g -mtune=generic -march=x86-64 -c \
> + *     -o test-PR26568-1.o test-PR26568-1.c */
> +
>  struct A {
>    union {
>      struct {
> diff --git a/tests/data/test-read-common/test-PR26568-2-ctf.o.abi b/tests/data/test-read-common/test-PR26568-2-ctf.o.abi
> new file mode 100644
> index 00000000..a934d15b
> --- /dev/null
> +++ b/tests/data/test-read-common/test-PR26568-2-ctf.o.abi
> @@ -0,0 +1,39 @@
> +<abi-corpus version='2.1' path='data/test-read-common/test-PR26568-2.o'>
> +  <elf-function-symbols>
> +    <elf-symbol name='fun' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-function-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-1'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='x' type-id='type-id-2' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='y' type-id='type-id-4' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-2'/>
> +    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-4'/>
> +    <union-decl name='A' size-in-bits='64' visibility='default' id='type-id-5'>
> +      <data-member access='public'>
> +        <var-decl name='' type-id='type-id-1' visibility='default'/>
> +      </data-member>
> +      <data-member access='public'>
> +        <var-decl name='x' type-id='type-id-2' visibility='default'/>
> +      </data-member>
> +      <data-member access='public'>
> +        <var-decl name='' type-id='type-id-3' visibility='default'/>
> +      </data-member>
> +      <data-member access='public'>
> +        <var-decl name='y' type-id='type-id-4' visibility='default'/>
> +      </data-member>
> +    </union-decl>
> +    <pointer-type-def type-id='type-id-5' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
> +    <function-decl name='fun' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
> +      <parameter type-id='type-id-6'/>
> +      <return type-id='type-id-7'/>
> +    </function-decl>
> +    <type-decl name='void' id='type-id-7'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-dwarf/test-PR26568-2.o.abi b/tests/data/test-read-common/test-PR26568-2-dwarf.o.abi
> similarity index 59%
> rename from tests/data/test-read-dwarf/test-PR26568-2.o.abi
> rename to tests/data/test-read-common/test-PR26568-2-dwarf.o.abi
> index cdb0243a..5240cee3 100644
> --- a/tests/data/test-read-dwarf/test-PR26568-2.o.abi
> +++ b/tests/data/test-read-common/test-PR26568-2-dwarf.o.abi
> @@ -1,11 +1,11 @@
> -<abi-corpus version='2.1' path='data/test-read-dwarf/test-PR26568-2.o'>
> +<abi-corpus version='2.1' path='data/test-read-common/test-PR26568-2.o'>
>    <elf-function-symbols>
>      <elf-symbol name='fun' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
>    </elf-function-symbols>
> -  <abi-instr address-size='64' path='test-PR26568-2.c' comp-dir-path='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf' language='LANG_C89'>
> +  <abi-instr address-size='64' path='test-PR26568-2.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
>      <type-decl name='int' size-in-bits='32' id='type-id-1'/>
>      <type-decl name='long int' size-in-bits='64' id='type-id-2'/>
> -    <union-decl name='A' size-in-bits='64' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-2.c' line='1' column='1' id='type-id-3'>
> +    <union-decl name='A' size-in-bits='64' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-2.c' line='4' column='1' id='type-id-3'>
>        <data-member access='public'>
>          <var-decl name='' type-id='type-id-4' visibility='default'/>
>        </data-member>
> @@ -13,19 +13,19 @@
>          <var-decl name='' type-id='type-id-5' visibility='default'/>
>        </data-member>
>      </union-decl>
> -    <class-decl name='__anonymous_struct__' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-2.c' line='2' column='1' id='type-id-4'>
> +    <class-decl name='__anonymous_struct__' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-2.c' line='5' column='1' id='type-id-4'>
>        <data-member access='public' layout-offset-in-bits='0'>
> -        <var-decl name='x' type-id='type-id-1' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-2.c' line='3' column='1'/>
> +        <var-decl name='x' type-id='type-id-1' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-2.c' line='6' column='1'/>
>        </data-member>
>      </class-decl>
> -    <class-decl name='__anonymous_struct__1' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-2.c' line='5' column='1' id='type-id-5'>
> +    <class-decl name='__anonymous_struct__1' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-2.c' line='8' column='1' id='type-id-5'>
>        <data-member access='public' layout-offset-in-bits='0'>
> -        <var-decl name='y' type-id='type-id-2' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-2.c' line='6' column='1'/>
> +        <var-decl name='y' type-id='type-id-2' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-2.c' line='9' column='1'/>
>        </data-member>
>      </class-decl>
>      <pointer-type-def type-id='type-id-3' size-in-bits='64' id='type-id-6'/>
> -    <function-decl name='fun' mangled-name='fun' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-2.c' line='10' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fun'>
> -      <parameter type-id='type-id-6' name='a' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-2.c' line='10' column='1'/>
> +    <function-decl name='fun' mangled-name='fun' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-2.c' line='13' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fun'>
> +      <parameter type-id='type-id-6' name='a' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-2.c' line='13' column='1'/>
>        <return type-id='type-id-7'/>
>      </function-decl>
>      <type-decl name='void' id='type-id-7'/>
> diff --git a/tests/data/test-read-dwarf/test-PR26568-2.c b/tests/data/test-read-common/test-PR26568-2.c
> similarity index 56%
> rename from tests/data/test-read-dwarf/test-PR26568-2.c
> rename to tests/data/test-read-common/test-PR26568-2.c
> index 656e8eea..6a439746 100644
> --- a/tests/data/test-read-dwarf/test-PR26568-2.c
> +++ b/tests/data/test-read-common/test-PR26568-2.c
> @@ -1,3 +1,6 @@
> +/* gcc -std=c89 -gctf -g -mtune=generic -march=x86-64 -c \
> + *     -o test-PR26568-2.o test-PR26568-2.c */
> +
>  union A {
>    struct {
>      int x;
> diff --git a/tests/data/test-read-dwarf/test3-alias-1.so.hash.abi b/tests/data/test-read-common/test3-alias-1-dwarf.so.hash.abi
> similarity index 57%
> rename from tests/data/test-read-dwarf/test3-alias-1.so.hash.abi
> rename to tests/data/test-read-common/test3-alias-1-dwarf.so.hash.abi
> index 02795ad0..b3a4801a 100644
> --- a/tests/data/test-read-dwarf/test3-alias-1.so.hash.abi
> +++ b/tests/data/test-read-common/test3-alias-1-dwarf.so.hash.abi
> @@ -1,12 +1,12 @@
> -<abi-corpus version='2.1' path='data/test-read-dwarf/test3.so' soname='test3.so.1'>
> +<abi-corpus version='2.1' path='data/test-read-common/test3.so' soname='test3.so.1'>
>    <elf-needed>
>      <dependency name='libc.so.6'/>
>    </elf-needed>
>    <elf-function-symbols>
>      <elf-symbol name='__foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
>    </elf-function-symbols>
> -  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf' language='LANG_C89'>
> -    <function-decl name='__foo' mangled-name='__foo' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test3.c' line='8' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
> +  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
> +    <function-decl name='__foo' mangled-name='__foo' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test3.c' line='23' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
>        <return type-id='48b5725f'/>
>      </function-decl>
>      <type-decl name='void' id='48b5725f'/>
> diff --git a/tests/data/test-read-dwarf/test3-alias-1.suppr b/tests/data/test-read-common/test3-alias-1.suppr
> similarity index 100%
> rename from tests/data/test-read-dwarf/test3-alias-1.suppr
> rename to tests/data/test-read-common/test3-alias-1.suppr
> diff --git a/tests/data/test-read-dwarf/test3-alias-2.so.hash.abi b/tests/data/test-read-common/test3-alias-2-dwarf.so.hash.abi
> similarity index 73%
> rename from tests/data/test-read-dwarf/test3-alias-2.so.hash.abi
> rename to tests/data/test-read-common/test3-alias-2-dwarf.so.hash.abi
> index 775a9a97..07a7f2c4 100644
> --- a/tests/data/test-read-dwarf/test3-alias-2.so.hash.abi
> +++ b/tests/data/test-read-common/test3-alias-2-dwarf.so.hash.abi
> @@ -1,4 +1,4 @@
> -<abi-corpus version='2.1' path='data/test-read-dwarf/test3.so' soname='test3.so.1'>
> +<abi-corpus version='2.1' path='data/test-read-common/test3.so' soname='test3.so.1'>
>    <elf-needed>
>      <dependency name='libc.so.6'/>
>    </elf-needed>
> @@ -9,8 +9,8 @@
>      <elf-symbol name='foo' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
>      <elf-symbol name='foo__' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
>    </elf-function-symbols>
> -  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf' language='LANG_C89'>
> -    <function-decl name='__foo' mangled-name='__foo' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test3.c' line='8' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
> +  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
> +    <function-decl name='__foo' mangled-name='__foo' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test3.c' line='23' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
>        <return type-id='48b5725f'/>
>      </function-decl>
>      <type-decl name='void' id='48b5725f'/>
> diff --git a/tests/data/test-read-dwarf/test3-alias-2.suppr b/tests/data/test-read-common/test3-alias-2.suppr
> similarity index 100%
> rename from tests/data/test-read-dwarf/test3-alias-2.suppr
> rename to tests/data/test-read-common/test3-alias-2.suppr
> diff --git a/tests/data/test-read-dwarf/test3-alias-3.so.hash.abi b/tests/data/test-read-common/test3-alias-3-dwarf.so.hash.abi
> similarity index 57%
> rename from tests/data/test-read-dwarf/test3-alias-3.so.hash.abi
> rename to tests/data/test-read-common/test3-alias-3-dwarf.so.hash.abi
> index 6c604948..7908bdb8 100644
> --- a/tests/data/test-read-dwarf/test3-alias-3.so.hash.abi
> +++ b/tests/data/test-read-common/test3-alias-3-dwarf.so.hash.abi
> @@ -1,12 +1,12 @@
> -<abi-corpus version='2.1' path='data/test-read-dwarf/test3.so' soname='test3.so.1'>
> +<abi-corpus version='2.1' path='data/test-read-common/test3.so' soname='test3.so.1'>
>    <elf-needed>
>      <dependency name='libc.so.6'/>
>    </elf-needed>
>    <elf-function-symbols>
>      <elf-symbol name='foo' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
>    </elf-function-symbols>
> -  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf' language='LANG_C89'>
> -    <function-decl name='__foo' mangled-name='__foo' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test3.c' line='8' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
> +  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
> +    <function-decl name='__foo' mangled-name='__foo' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test3.c' line='23' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
>        <return type-id='48b5725f'/>
>      </function-decl>
>      <type-decl name='void' id='48b5725f'/>
> diff --git a/tests/data/test-read-dwarf/test3-alias-3.suppr b/tests/data/test-read-common/test3-alias-3.suppr
> similarity index 100%
> rename from tests/data/test-read-dwarf/test3-alias-3.suppr
> rename to tests/data/test-read-common/test3-alias-3.suppr
> diff --git a/tests/data/test-read-dwarf/test3-alias-4.so.hash.abi b/tests/data/test-read-common/test3-alias-4-dwarf.so.hash.abi
> similarity index 74%
> rename from tests/data/test-read-dwarf/test3-alias-4.so.hash.abi
> rename to tests/data/test-read-common/test3-alias-4-dwarf.so.hash.abi
> index 912c710c..22a56fa5 100644
> --- a/tests/data/test-read-dwarf/test3-alias-4.so.hash.abi
> +++ b/tests/data/test-read-common/test3-alias-4-dwarf.so.hash.abi
> @@ -1,4 +1,4 @@
> -<abi-corpus version='2.1' path='data/test-read-dwarf/test3.so' soname='test3.so.1'>
> +<abi-corpus version='2.1' path='data/test-read-common/test3.so' soname='test3.so.1'>
>    <elf-needed>
>      <dependency name='libc.so.6'/>
>    </elf-needed>
> diff --git a/tests/data/test-read-dwarf/test3-alias-4.suppr b/tests/data/test-read-common/test3-alias-4.suppr
> similarity index 100%
> rename from tests/data/test-read-dwarf/test3-alias-4.suppr
> rename to tests/data/test-read-common/test3-alias-4.suppr
> diff --git a/tests/data/test-read-common/test3-ctf.so.abi b/tests/data/test-read-common/test3-ctf.so.abi
> new file mode 100644
> index 00000000..9d55fec5
> --- /dev/null
> +++ b/tests/data/test-read-common/test3-ctf.so.abi
> @@ -0,0 +1,12 @@
> +<abi-corpus version='2.1' path='data/test-read-common/test3.so'>
> +  <elf-function-symbols>
> +    <elf-symbol name='__foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='__foo__' 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='foo' type='func-type' binding='weak-binding' visibility='default-visibility' alias='foo__,__foo__,__foo' is-defined='yes'/>
> +    <elf-symbol name='foo__' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-function-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-common/test3-ctf.so.hash.abi b/tests/data/test-read-common/test3-ctf.so.hash.abi
> new file mode 100644
> index 00000000..9d55fec5
> --- /dev/null
> +++ b/tests/data/test-read-common/test3-ctf.so.hash.abi
> @@ -0,0 +1,12 @@
> +<abi-corpus version='2.1' path='data/test-read-common/test3.so'>
> +  <elf-function-symbols>
> +    <elf-symbol name='__foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='__foo__' 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='foo' type='func-type' binding='weak-binding' visibility='default-visibility' alias='foo__,__foo__,__foo' is-defined='yes'/>
> +    <elf-symbol name='foo__' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-function-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-dwarf/test3.so.abi b/tests/data/test-read-common/test3-dwarf.so.abi
> similarity index 75%
> rename from tests/data/test-read-dwarf/test3.so.abi
> rename to tests/data/test-read-common/test3-dwarf.so.abi
> index 04032c74..a9bf781f 100644
> --- a/tests/data/test-read-dwarf/test3.so.abi
> +++ b/tests/data/test-read-common/test3-dwarf.so.abi
> @@ -1,4 +1,4 @@
> -<abi-corpus version='2.1' path='data/test-read-dwarf/test3.so' soname='test3.so.1'>
> +<abi-corpus version='2.1' path='data/test-read-common/test3.so' soname='test3.so.1'>
>    <elf-needed>
>      <dependency name='libc.so.6'/>
>    </elf-needed>
> @@ -10,8 +10,8 @@
>      <elf-symbol name='foo' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
>      <elf-symbol name='foo__' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
>    </elf-function-symbols>
> -  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf' language='LANG_C89'>
> -    <function-decl name='__foo' mangled-name='__foo' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test3.c' line='8' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
> +  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
> +    <function-decl name='__foo' mangled-name='__foo' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test3.c' line='23' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
>        <return type-id='type-id-1'/>
>      </function-decl>
>      <type-decl name='void' id='type-id-1'/>
> diff --git a/tests/data/test-read-dwarf/test3.so.hash.abi b/tests/data/test-read-common/test3-dwarf.so.hash.abi
> similarity index 75%
> rename from tests/data/test-read-dwarf/test3.so.hash.abi
> rename to tests/data/test-read-common/test3-dwarf.so.hash.abi
> index ea9ddc02..f429b22f 100644
> --- a/tests/data/test-read-dwarf/test3.so.hash.abi
> +++ b/tests/data/test-read-common/test3-dwarf.so.hash.abi
> @@ -1,4 +1,4 @@
> -<abi-corpus version='2.1' path='data/test-read-dwarf/test3.so' soname='test3.so.1'>
> +<abi-corpus version='2.1' path='data/test-read-common/test3.so' soname='test3.so.1'>
>    <elf-needed>
>      <dependency name='libc.so.6'/>
>    </elf-needed>
> @@ -10,8 +10,8 @@
>      <elf-symbol name='foo' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
>      <elf-symbol name='foo__' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
>    </elf-function-symbols>
> -  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf' language='LANG_C89'>
> -    <function-decl name='__foo' mangled-name='__foo' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test3.c' line='8' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
> +  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
> +    <function-decl name='__foo' mangled-name='__foo' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test3.c' line='23' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
>        <return type-id='48b5725f'/>
>      </function-decl>
>      <type-decl name='void' id='48b5725f'/>
> diff --git a/tests/data/test-read-common/test3.c b/tests/data/test-read-common/test3.c
> new file mode 100644
> index 00000000..0d8e7f87
> --- /dev/null
> +++ b/tests/data/test-read-common/test3.c
> @@ -0,0 +1,26 @@
> +/*
> + * Test file for creating multiple alias for a symbol
> + *
> + * NOTE: linking with _old_ crti.o exposes _init and _fini as
> + *       global symbols, the newer versions don't.
> + *
> + * 0000000000000000 g     F .init  0000000000000000 .hidden _init
> + * 0000000000000000 g     F .fini  0000000000000000 .hidden _fini
> + *
> + * This test is looking for those symbols which are not experted.
> + * So it's linked with dummy crti.o to avoid false positives.
> + *
> + * gcc -std=c89 -shared -gctf -g -mtune=generic -march=x86-64 -fPIC \
> + *     -nostartfiles -Wl,-soname=test3.so.1 -o test3.so test3.c crti.o
> + *
> + */
> +
> +void __foo(void);
> +void foo(void) __attribute__((weak, alias("__foo")));
> +void foo__(void) __attribute__((weak, alias("__foo")));
> +void __foo__(void) __attribute__((alias("__foo")));
> +
> +void __foo(void)
> +{
> +
> +}
> diff --git a/tests/data/test-read-common/test3.so b/tests/data/test-read-common/test3.so
> new file mode 100755
> index 0000000000000000000000000000000000000000..3dfb69e998b5d91dcadc283974557ec294e2c074
> GIT binary patch
> literal 14824
> zcmeHOPiz!b7=N?d(n4V={{&K!P7FjK?(DW;!yhZHrKQ9|um+<>GtTbLb~kos$nF$d
> z5+f&4q9z<YcpxEB;?a{FOiVbNG<q;zlnWO<0491dv3|dq@7s>U6s*L=!~2rAzxTfP
> zeeb>b%{Om$cfNUld}<<N7)m6oUQjD7rAD~p=3%jb?ugnzpF7m{(6(cx>!I40*+?a*
> zdZRYx=tPy<N!$^c(Htx>zi>X2^$A>JwV;fP`PQMYzy>E0C<iUb^JU0vEq>iREY|p_
> zbr#u9Q2buG8&v*{-#PXxn$f^X+{^O`hI5eaW%3J;kNY17OpBV9b^b#>g;s<^7ZqT9
> zUaSZ4Aa+z$;2w6+p}>Ccw<>eFV<e1N^uzCJYq6(#rM3CiM-Orxw?AL_`MZ0$&+h+{
> zqpnp2<35cU`GBw{$a*Si`pu-@O7>j|d-y@090zd=eJ){-<4Chtwq5o8=+m~9UH9sN
> zva1AYwq7b*E#Deaf!hiWp*ldLXweL41~dbj0nLDBKr^5j&<tn>Gy`j6;QZv(yVu^j
> z{dZW~5ZYQZpc&8%Xa+O`ngPv#W<WEb8PE)91~dbjf&V!Jcz$Y9!L!#>XV24fR^w~v
> z@SGBo;day_eP8zYUTWa^>C(OB<q^W~3Ew9Ck?=AhWP1e4xHPSd`Cg-MV^{Yz8gvio
> zQ5MNIeC9fu>%Ed0+qCXQGT^@F3H?X(ze)YCuF_9kS~LTi0nLDBKr^5j&<tn>Gy|Fe
> z&46Y=Gw=`t@;kSWdn9RiAGbF$O5X1#vE#g6{8olsKr%APZ+|ZP!0X(`?`p^*elU|r
> z&hs7a-w>%)k+Fwy7vp~or^d#PnfvLN{{eGg&?;I*bFer#FhIrJ@6KOvoArk41<vdN
> z^(-wVS~TaXCo-FpD;+0Ar!qogV;eP$VKGVZ%z!9k=elGbweg8Ewix?z+j_G7ef?XE
> ztzEr4X&sh2u{)bP)^oh)XwNgdp&r?FX*UfqNu^VDtAiNMF#gDG0^lrDp-O*v!ZSvH
> zW^*Q7Px#SksP!3{I=j=D%4Es-qF=9YUiO^#j_1GY;V%+%?8wo_aAoEj!JOv~&$u2D
> zSf-}aEZ2tTj|}C94x9Oza!{pDGv5j-!{wtzGhaP-dQ25+e#0%47D@{Rzv+}`-9oEb
> zE>QNjQ>xE6_1OZ_zgvZh6F6Zt-*lZyzU(&|zQ?KIWjfAu!C`l(2g}J`<h!ToVV9=I
> zsUxzKlJ_TINCNJW*)Q)MgiZQD)THIR<8_j>{CNELla_yPt)f4+%J?I!m+MyY``bj7
> zn?c<wEBoZ@XGhNv`?gKz)*hd<C#FZwjN6kZr&p5k!!&$O&<_*yfBmULHj4H?Wi(+Z
> z*bz_=_$c_d>?JC=cIYfzo**QVjUbFiYCjcLo+Jjspg2Uw6vnNxS__T9DG>(E2y0TC
> z@#d_W)2b<}vfz<fgh5kTfjb{4%ku-*g3*PhPg_8+pe(m$SDQ}5wQChJlUC^HH0ot#
> zAr5J$ph{3BwOg8-v7M&l&A2UT*1f7Pb*EHnx)-H2TlZY4(;}q`wT<?ZOFs>PErz$<
> z_I@q<w(P&WO^0U=v&#OC`@`?c%f9$u=ZYZW7LxRjv`X!x3ifvKzrz*5n{0^r5DADJ
> zh};MARL9ujFZUBcSwDOr5>`=5spnWHVJDlNVEa8Qc1ZdkCq1qqnO~V~$e5g8*3VYz
> zELAY3_{%;ah^r(n!n^43pKsj%H8biFoEJmJ<os3A<Jjf=wD&K0e~AxR<`sYJcM#mv
> zVUj#fQQ&?P7ap#C9<V;q#qEX;MXeigWs2>4DLS|u<OL<ym7MFtRs7#z$I}=rCQ1K~
> zsV}L6`3?3*e8wed`zduMb+BJz|EaihitQJyOCIMQeibVG(iIy+<`VpB75@*|AKzBu
> zB7Sj{*p1sQvA@ZN_@aY2llYPA7x&qA?8OGSKNvM8Vmef1UQutMN}B%<96#TPA!E}2
> EFPZjRv;Y7A
>
> literal 0
> HcmV?d00001
>
> diff --git a/tests/data/test-read-common/test4-ctf.so.abi b/tests/data/test-read-common/test4-ctf.so.abi
> new file mode 100644
> index 00000000..b8e0ead3
> --- /dev/null
> +++ b/tests/data/test-read-common/test4-ctf.so.abi
> @@ -0,0 +1,14 @@
> +<abi-corpus version='2.1' path='data/test-read-common/test4.so'>
> +  <elf-function-symbols>
> +    <elf-symbol name='cpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-function-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <type-decl name='char' size-in-bits='8' alignment-in-bits='8' id='type-id-1'/>
> +    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-2'/>
> +    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-3'/>
> +    <qualified-type-def type-id='type-id-3' restrict='yes' id='type-id-4'/>
> +    <qualified-type-def type-id='type-id-1' const='yes' id='type-id-5'/>
> +    <pointer-type-def type-id='type-id-5' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
> +    <qualified-type-def type-id='type-id-6' restrict='yes' id='type-id-7'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-common/test4-ctf.so.hash.abi b/tests/data/test-read-common/test4-ctf.so.hash.abi
> new file mode 100644
> index 00000000..dbe34d9c
> --- /dev/null
> +++ b/tests/data/test-read-common/test4-ctf.so.hash.abi
> @@ -0,0 +1,14 @@
> +<abi-corpus version='2.1' path='data/test-read-common/test4.so'>
> +  <elf-function-symbols>
> +    <elf-symbol name='cpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-function-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <type-decl name='char' size-in-bits='8' alignment-in-bits='8' id='a84c031d'/>
> +    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
> +    <pointer-type-def type-id='a84c031d' size-in-bits='64' alignment-in-bits='64' id='26a90f95'/>
> +    <qualified-type-def type-id='26a90f95' restrict='yes' id='266fe297'/>
> +    <qualified-type-def type-id='a84c031d' const='yes' id='9b45d938'/>
> +    <pointer-type-def type-id='9b45d938' size-in-bits='64' alignment-in-bits='64' id='80f4b756'/>
> +    <qualified-type-def type-id='80f4b756' restrict='yes' id='9d26089a'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-dwarf/test4.so.abi b/tests/data/test-read-common/test4-dwarf.so.abi
> similarity index 56%
> rename from tests/data/test-read-dwarf/test4.so.abi
> rename to tests/data/test-read-common/test4-dwarf.so.abi
> index 71f64da3..c38fff66 100644
> --- a/tests/data/test-read-dwarf/test4.so.abi
> +++ b/tests/data/test-read-common/test4-dwarf.so.abi
> @@ -1,11 +1,11 @@
> -<abi-corpus version='2.1' path='data/test-read-dwarf/test4.so'>
> +<abi-corpus version='2.1' path='data/test-read-common/test4.so'>
>    <elf-needed>
>      <dependency name='libc.so.6'/>
>    </elf-needed>
>    <elf-function-symbols>
>      <elf-symbol name='cpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
>    </elf-function-symbols>
> -  <abi-instr address-size='64' path='test4.c' comp-dir-path='/home/mark/src/tests' language='LANG_C89'>
> +  <abi-instr address-size='64' path='test4.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C99'>
>      <type-decl name='char' size-in-bits='8' id='type-id-1'/>
>      <type-decl name='unsigned int' size-in-bits='32' id='type-id-2'/>
>      <pointer-type-def type-id='type-id-1' size-in-bits='64' id='type-id-3'/>
> @@ -13,10 +13,10 @@
>      <qualified-type-def type-id='type-id-1' const='yes' id='type-id-5'/>
>      <pointer-type-def type-id='type-id-5' size-in-bits='64' id='type-id-6'/>
>      <qualified-type-def type-id='type-id-6' restrict='yes' id='type-id-7'/>
> -    <function-decl name='cpy' mangled-name='cpy' filepath='/home/mark/src/tests/test4.c' line='2' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cpy'>
> -      <parameter type-id='type-id-4' name='s1' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
> -      <parameter type-id='type-id-7' name='s2' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
> -      <parameter type-id='type-id-2' name='n' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
> +    <function-decl name='cpy' mangled-name='cpy' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cpy'>
> +      <parameter type-id='type-id-4' name='s1' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
> +      <parameter type-id='type-id-7' name='s2' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
> +      <parameter type-id='type-id-2' name='n' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
>        <return type-id='type-id-3'/>
>      </function-decl>
>    </abi-instr>
> diff --git a/tests/data/test-read-dwarf/test4.so.hash.abi b/tests/data/test-read-common/test4-dwarf.so.hash.abi
> similarity index 55%
> rename from tests/data/test-read-dwarf/test4.so.hash.abi
> rename to tests/data/test-read-common/test4-dwarf.so.hash.abi
> index 471ff895..7223f5eb 100644
> --- a/tests/data/test-read-dwarf/test4.so.hash.abi
> +++ b/tests/data/test-read-common/test4-dwarf.so.hash.abi
> @@ -1,11 +1,11 @@
> -<abi-corpus version='2.1' path='data/test-read-dwarf/test4.so'>
> +<abi-corpus version='2.1' path='data/test-read-common/test4.so'>
>    <elf-needed>
>      <dependency name='libc.so.6'/>
>    </elf-needed>
>    <elf-function-symbols>
>      <elf-symbol name='cpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
>    </elf-function-symbols>
> -  <abi-instr address-size='64' path='test4.c' comp-dir-path='/home/mark/src/tests' language='LANG_C89'>
> +  <abi-instr address-size='64' path='test4.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C99'>
>      <type-decl name='char' size-in-bits='8' id='a84c031d'/>
>      <type-decl name='unsigned int' size-in-bits='32' id='f0981eeb'/>
>      <pointer-type-def type-id='a84c031d' size-in-bits='64' id='26a90f95'/>
> @@ -13,10 +13,10 @@
>      <qualified-type-def type-id='a84c031d' const='yes' id='9b45d938'/>
>      <pointer-type-def type-id='9b45d938' size-in-bits='64' id='80f4b756'/>
>      <qualified-type-def type-id='80f4b756' restrict='yes' id='9d26089a'/>
> -    <function-decl name='cpy' mangled-name='cpy' filepath='/home/mark/src/tests/test4.c' line='2' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cpy'>
> -      <parameter type-id='266fe297' name='s1' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
> -      <parameter type-id='9d26089a' name='s2' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
> -      <parameter type-id='f0981eeb' name='n' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
> +    <function-decl name='cpy' mangled-name='cpy' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cpy'>
> +      <parameter type-id='266fe297' name='s1' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
> +      <parameter type-id='9d26089a' name='s2' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
> +      <parameter type-id='f0981eeb' name='n' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
>        <return type-id='26a90f95'/>
>      </function-decl>
>    </abi-instr>
> diff --git a/tests/data/test-read-common/test4.c b/tests/data/test-read-common/test4.c
> new file mode 100644
> index 00000000..ad274022
> --- /dev/null
> +++ b/tests/data/test-read-common/test4.c
> @@ -0,0 +1,11 @@
> +// gcc -shared -gctf -gdwarf-3 -mtune=generic -march=x86-64 -std=c99 -fPIC -o test4.so test4.c
> +
> +char *
> +cpy (char * restrict s1, const char * restrict s2, unsigned int n)
> +{
> +  char *t1 = s1;
> +  const char *t2 = s2;
> +  while(n-- > 0)
> +    *t1++ = *t2++;
> +  return s1;
> +}
> diff --git a/tests/data/test-read-common/test4.so b/tests/data/test-read-common/test4.so
> new file mode 100755
> index 0000000000000000000000000000000000000000..0394bf5cc4404c29b1627258d9b11319035bd671
> GIT binary patch
> literal 16560
> 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
> Ww9?1oO`$gaIeKwITIB=ySn+Q+OAa^y
>
> literal 0
> HcmV?d00001
>
> diff --git a/tests/data/test-read-ctf/test-alias.c b/tests/data/test-read-ctf/test-alias.c
> new file mode 100644
> index 00000000..1b497a18
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-alias.c
> @@ -0,0 +1,15 @@
> +
> +// function aliases
> +
> +void main_func(void);
> +void alias_func(void) __attribute__((weak, alias("main_func")));
> +
> +void main_func(void)
> +{
> +
> +}
> +
> +// variables aliases
> +
> +int main_var;
> +extern int alias_var __attribute__((weak, alias("main_var")));
> diff --git a/tests/data/test-read-ctf/test-alias.o.abi b/tests/data/test-read-ctf/test-alias.o.abi
> new file mode 100644
> index 00000000..1fe61b8f
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-alias.o.abi
> @@ -0,0 +1,19 @@
> +<abi-corpus version='2.1' path='data/test-read-ctf/test-alias.o'>
> +  <elf-function-symbols>
> +    <elf-symbol name='alias_func' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='main_func' type='func-type' binding='global-binding' visibility='default-visibility' alias='alias_func,main_var,alias_var' is-defined='yes'/>
> +  </elf-function-symbols>
> +  <elf-variable-symbols>
> +    <elf-symbol name='alias_var' size='4' type='object-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='main_var' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-variable-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='95e97e5e'/>
> +    <function-decl name='main_func' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
> +      <return type-id='48b5725f'/>
> +    </function-decl>
> +    <var-decl name='alias_var' type-id='95e97e5e' mangled-name='alias_var' visibility='default'/>
> +    <var-decl name='main_var' type-id='95e97e5e' mangled-name='main_var' visibility='default'/>
> +    <type-decl name='void' id='48b5725f'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-ctf/test-ambiguous-struct-A.c b/tests/data/test-read-ctf/test-ambiguous-struct-A.c
> new file mode 100644
> index 00000000..67047c44
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-ambiguous-struct-A.c
> @@ -0,0 +1,8 @@
> +struct A;
> +struct B { struct A *a; };
> +struct A { struct B b; long foo; long bar; struct B b2; };
> +
> +typedef struct A a_array[50];
> +a_array *foo __attribute__((__used__));
> +
> +static struct A a __attribute ((__used__));
> diff --git a/tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi b/tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi
> new file mode 100644
> index 00000000..922a1daf
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi
> @@ -0,0 +1,36 @@
> +<abi-corpus version='2.1' path='data/test-read-ctf/test-ambiguous-struct-A.o'>
> +  <elf-variable-symbols>
> +    <elf-symbol name='foo' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-variable-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <array-type-def dimensions='1' type-id='3ed987a4' size-in-bits='12800' alignment-in-bits='64' id='e022be37'>
> +      <subrange length='50' type-id='7359adad' id='3c1860ce'/>
> +    </array-type-def>
> +    <class-decl name='A' size-in-bits='256' alignment-in-bits='64' is-struct='yes' visibility='default' id='3ed987a4'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='b' type-id='41d98c5d' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='64'>
> +        <var-decl name='foo' type-id='bd54fe1a' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='128'>
> +        <var-decl name='bar' type-id='bd54fe1a' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='192'>
> +        <var-decl name='b2' type-id='41d98c5d' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <class-decl name='B' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='41d98c5d'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='a' type-id='84d5ac12' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='bd54fe1a'/>
> +    <typedef-decl name='a_array' type-id='e022be37' id='1c12b755'/>
> +    <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='7359adad'/>
> +    <pointer-type-def type-id='3ed987a4' size-in-bits='64' alignment-in-bits='64' id='84d5ac12'/>
> +    <pointer-type-def type-id='1c12b755' size-in-bits='64' alignment-in-bits='64' id='55cd64e8'/>
> +    <var-decl name='a' type-id='3ed987a4' mangled-name='a' visibility='default'/>
> +    <var-decl name='foo' type-id='55cd64e8' mangled-name='foo' visibility='default'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-ctf/test-ambiguous-struct-B.c b/tests/data/test-read-ctf/test-ambiguous-struct-B.c
> new file mode 100644
> index 00000000..95a93469
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-ambiguous-struct-B.c
> @@ -0,0 +1,5 @@
> +struct A;
> +struct B { struct A *a; };
> +struct A { struct B b; int foo; struct B b2; };
> +
> +static struct A a __attribute__((__used__));
> diff --git a/tests/data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi b/tests/data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi
> new file mode 100644
> index 00000000..28291eb5
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi
> @@ -0,0 +1,23 @@
> +<abi-corpus version='2.1' path='data/test-read-ctf/test-ambiguous-struct-B.o'>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <class-decl name='A' size-in-bits='192' alignment-in-bits='64' is-struct='yes' visibility='default' id='3ed987a4'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='b' type-id='41d98c5d' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='64'>
> +        <var-decl name='foo' type-id='95e97e5e' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='128'>
> +        <var-decl name='b2' type-id='41d98c5d' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <class-decl name='B' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='41d98c5d'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='a' type-id='84d5ac12' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='95e97e5e'/>
> +    <pointer-type-def type-id='3ed987a4' size-in-bits='64' alignment-in-bits='64' id='84d5ac12'/>
> +    <var-decl name='a' type-id='3ed987a4' mangled-name='a' visibility='default'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-ctf/test-conflicting-type-syms-a.c b/tests/data/test-read-ctf/test-conflicting-type-syms-a.c
> new file mode 100644
> index 00000000..65414877
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-conflicting-type-syms-a.c
> @@ -0,0 +1,5 @@
> +typedef long a_t;
> +typedef long b_t;
> +
> +a_t *a;
> +b_t ignore2;
> diff --git a/tests/data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi b/tests/data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi
> new file mode 100644
> index 00000000..03dd56b3
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi
> @@ -0,0 +1,14 @@
> +<abi-corpus version='2.1' path='data/test-read-ctf/test-conflicting-type-syms-a.o'>
> +  <elf-variable-symbols>
> +    <elf-symbol name='a' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='ignore2' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-variable-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='bd54fe1a'/>
> +    <typedef-decl name='a_t' type-id='bd54fe1a' id='40acc204'/>
> +    <typedef-decl name='b_t' type-id='bd54fe1a' id='b3d2db81'/>
> +    <pointer-type-def type-id='40acc204' size-in-bits='64' alignment-in-bits='64' id='c6fd4117'/>
> +    <var-decl name='a' type-id='c6fd4117' mangled-name='a' visibility='default'/>
> +    <var-decl name='ignore2' type-id='b3d2db81' mangled-name='ignore2' visibility='default'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-ctf/test-conflicting-type-syms-b.c b/tests/data/test-read-ctf/test-conflicting-type-syms-b.c
> new file mode 100644
> index 00000000..e458021e
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-conflicting-type-syms-b.c
> @@ -0,0 +1,5 @@
> +typedef long a_t;
> +typedef long b_t;
> +
> +a_t b;
> +b_t ignore1;
> diff --git a/tests/data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi b/tests/data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi
> new file mode 100644
> index 00000000..35bcac7a
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi
> @@ -0,0 +1,13 @@
> +<abi-corpus version='2.1' path='data/test-read-ctf/test-conflicting-type-syms-b.o'>
> +  <elf-variable-symbols>
> +    <elf-symbol name='b' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='ignore1' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-variable-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='bd54fe1a'/>
> +    <typedef-decl name='a_t' type-id='bd54fe1a' id='40acc204'/>
> +    <typedef-decl name='b_t' type-id='bd54fe1a' id='b3d2db81'/>
> +    <var-decl name='b' type-id='40acc204' mangled-name='b' visibility='default'/>
> +    <var-decl name='ignore1' type-id='b3d2db81' mangled-name='ignore1' visibility='default'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-ctf/test-enum-ctf.c b/tests/data/test-read-ctf/test-enum-ctf.c
> new file mode 100644
> index 00000000..aa60d727
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-enum-ctf.c
> @@ -0,0 +1,8 @@
> +/* Looked up item by item. */
> +enum e { ENUMSAMPLE_1 = 0, ENUMSAMPLE_2 = 1 };
> +
> +/* Looked up via both sorts of iterator in turn.  */
> +enum ie { IENUMSAMPLE_1 = -10, IENUMSAMPLE_2, IENUMSAMPLE_3 };
> +
> +enum e foo;
> +enum ie bar;
> diff --git a/tests/data/test-read-ctf/test-enum-ctf.o.abi b/tests/data/test-read-ctf/test-enum-ctf.o.abi
> new file mode 100644
> index 00000000..f36f3fad
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-enum-ctf.o.abi
> @@ -0,0 +1,24 @@
> +<abi-corpus version='2.1' path='data/test-read-ctf/test-enum-ctf.o'>
> +  <elf-variable-symbols>
> +    <elf-symbol name='bar' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='foo' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-variable-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='type-id-1'/>
> +    <enum-decl name='e' linkage-name='e' id='type-id-2'>
> +      <underlying-type type-id='type-id-1'/>
> +      <enumerator name='ENUMSAMPLE_1' value='0'/>
> +      <enumerator name='ENUMSAMPLE_2' value='1'/>
> +    </enum-decl>
> +    <enum-decl name='ie' linkage-name='ie' id='type-id-3'>
> +      <underlying-type type-id='type-id-1'/>
> +      <enumerator name='IENUMSAMPLE_1' value='-10'/>
> +      <enumerator name='IENUMSAMPLE_2' value='-9'/>
> +      <enumerator name='IENUMSAMPLE_3' value='-8'/>
> +    </enum-decl>
> +    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-4'/>
> +    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-5'/>
> +    <var-decl name='foo' type-id='type-id-2' mangled-name='foo' visibility='default'/>
> +    <var-decl name='bar' type-id='type-id-3' mangled-name='bar' visibility='default'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-ctf/test-enum-many-ctf.c b/tests/data/test-read-ctf/test-enum-many-ctf.c
> new file mode 100644
> index 00000000..f2297d72
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-enum-many-ctf.c
> @@ -0,0 +1,10 @@
> +/* Looked up item by item. */
> +enum e { ENUMSAMPLE_1 = 0, ENUMSAMPLE_2 = 1 };
> +
> +/* Looked up via both sorts of iterator in turn.  */
> +enum ie { IE_0 = -10, IE_1, IE_2, IE_3, IE_4, IE_5, IE_6, IE_7, IE_8, IE_9, IE_A, IE_B, IE_C, IE_D, IE_E, IE_F,
> +	  IE_10, IE_11, IE_12, IE_13, IE_14, IE_15, IE_16, IE_17, IE_18, IE_19, IE_1A, IE_1B, IE_1C, IE_1D, IE_1E, IE_1F,
> +	  IE_20, IE_21, IE_22, IE_23, IE_24, IE_25, IE_26, IE_27, IE_28, IE_29, IE_2A, IE_2B, IE_2C, IE_2D, IE_2E, IE_2F};
> +
> +enum e foo;
> +enum ie bar;
> diff --git a/tests/data/test-read-ctf/test-enum-many-ctf.o.hash.abi b/tests/data/test-read-ctf/test-enum-many-ctf.o.hash.abi
> new file mode 100644
> index 00000000..67a958a7
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-enum-many-ctf.o.hash.abi
> @@ -0,0 +1,69 @@
> +<abi-corpus version='2.1' path='data/test-read-ctf/test-enum-many-ctf.o'>
> +  <elf-variable-symbols>
> +    <elf-symbol name='bar' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='foo' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-variable-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='811c9dc5'/>
> +    <enum-decl name='e' linkage-name='e' id='a6c2eddf'>
> +      <underlying-type type-id='811c9dc5'/>
> +      <enumerator name='ENUMSAMPLE_1' value='0'/>
> +      <enumerator name='ENUMSAMPLE_2' value='1'/>
> +    </enum-decl>
> +    <enum-decl name='ie' linkage-name='ie' id='1ee696ca'>
> +      <underlying-type type-id='811c9dc5'/>
> +      <enumerator name='IE_0' value='-10'/>
> +      <enumerator name='IE_1' value='-9'/>
> +      <enumerator name='IE_2' value='-8'/>
> +      <enumerator name='IE_3' value='-7'/>
> +      <enumerator name='IE_4' value='-6'/>
> +      <enumerator name='IE_5' value='-5'/>
> +      <enumerator name='IE_6' value='-4'/>
> +      <enumerator name='IE_7' value='-3'/>
> +      <enumerator name='IE_8' value='-2'/>
> +      <enumerator name='IE_9' value='-1'/>
> +      <enumerator name='IE_A' value='0'/>
> +      <enumerator name='IE_B' value='1'/>
> +      <enumerator name='IE_C' value='2'/>
> +      <enumerator name='IE_D' value='3'/>
> +      <enumerator name='IE_E' value='4'/>
> +      <enumerator name='IE_F' value='5'/>
> +      <enumerator name='IE_10' value='6'/>
> +      <enumerator name='IE_11' value='7'/>
> +      <enumerator name='IE_12' value='8'/>
> +      <enumerator name='IE_13' value='9'/>
> +      <enumerator name='IE_14' value='10'/>
> +      <enumerator name='IE_15' value='11'/>
> +      <enumerator name='IE_16' value='12'/>
> +      <enumerator name='IE_17' value='13'/>
> +      <enumerator name='IE_18' value='14'/>
> +      <enumerator name='IE_19' value='15'/>
> +      <enumerator name='IE_1A' value='16'/>
> +      <enumerator name='IE_1B' value='17'/>
> +      <enumerator name='IE_1C' value='18'/>
> +      <enumerator name='IE_1D' value='19'/>
> +      <enumerator name='IE_1E' value='20'/>
> +      <enumerator name='IE_1F' value='21'/>
> +      <enumerator name='IE_20' value='22'/>
> +      <enumerator name='IE_21' value='23'/>
> +      <enumerator name='IE_22' value='24'/>
> +      <enumerator name='IE_23' value='25'/>
> +      <enumerator name='IE_24' value='26'/>
> +      <enumerator name='IE_25' value='27'/>
> +      <enumerator name='IE_26' value='28'/>
> +      <enumerator name='IE_27' value='29'/>
> +      <enumerator name='IE_28' value='30'/>
> +      <enumerator name='IE_29' value='31'/>
> +      <enumerator name='IE_2A' value='32'/>
> +      <enumerator name='IE_2B' value='33'/>
> +      <enumerator name='IE_2C' value='34'/>
> +      <enumerator name='IE_2D' value='35'/>
> +      <enumerator name='IE_2E' value='36'/>
> +      <enumerator name='IE_2F' value='37'/>
> +    </enum-decl>
> +    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='95e97e5e'/>
> +    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
> +    <var-decl name='foo' type-id='a6c2eddf' mangled-name='foo' visibility='default'/>
> +    <var-decl name='bar' type-id='1ee696ca' mangled-name='bar' visibility='default'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-ctf/test-enum-symbol-ctf.c b/tests/data/test-read-ctf/test-enum-symbol-ctf.c
> new file mode 100644
> index 00000000..f7f99c67
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-enum-symbol-ctf.c
> @@ -0,0 +1 @@
> +enum {red1, green1, blue1} primary1;
> diff --git a/tests/data/test-read-ctf/test-enum-symbol-ctf.o.hash.abi b/tests/data/test-read-ctf/test-enum-symbol-ctf.o.hash.abi
> new file mode 100644
> index 00000000..fea6eb8b
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-enum-symbol-ctf.o.hash.abi
> @@ -0,0 +1,16 @@
> +<abi-corpus version='2.1' path='data/test-read-ctf/test-enum-symbol-ctf.o'>
> +  <elf-variable-symbols>
> +    <elf-symbol name='primary1' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-variable-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='811c9dc5'/>
> +    <enum-decl name='' is-anonymous='yes' id='08f5ca17'>
> +      <underlying-type type-id='811c9dc5'/>
> +      <enumerator name='red1' value='0'/>
> +      <enumerator name='green1' value='1'/>
> +      <enumerator name='blue1' value='2'/>
> +    </enum-decl>
> +    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
> +    <var-decl name='primary1' type-id='08f5ca17' mangled-name='primary1' visibility='default'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-ctf/test-struct-iteration-ctf.c b/tests/data/test-read-ctf/test-struct-iteration-ctf.c
> new file mode 100644
> index 00000000..7df67ada
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-struct-iteration-ctf.c
> @@ -0,0 +1,28 @@
> +#include <unistd.h>
> +
> +struct foo_t
> +{
> +  int foo;
> +  size_t bar;
> +  const char *baz;
> +  struct foo_t *self;
> +  union
> +  {
> +    double should_not_appear;
> +    char *nor_should_this;
> +  } named;
> +  struct
> +  {
> +    long unnamed_sub_member;
> +    union
> +    {
> +      double one_more_level;
> +      long yes_really_one_more;
> +    };
> +  };
> +  struct {};		/* Empty ones */
> +  union {};
> +  int after_the_end;
> +};
> +
> +struct foo_t used;
> diff --git a/tests/data/test-read-ctf/test-struct-iteration-ctf.o.abi b/tests/data/test-read-ctf/test-struct-iteration-ctf.o.abi
> new file mode 100644
> index 00000000..72e0bdc3
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test-struct-iteration-ctf.o.abi
> @@ -0,0 +1,96 @@
> +<abi-corpus version='2.1' path='data/test-read-ctf/test-struct-iteration-ctf.o'>
> +  <elf-variable-symbols>
> +    <elf-symbol name='used' size='64' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-variable-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <type-decl name='char' size-in-bits='8' alignment-in-bits='8' id='type-id-1'/>
> +    <class-decl name='' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-2'/>
> +    <class-decl name='' size-in-bits='128' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='unnamed_sub_member' type-id='type-id-4' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='64'>
> +        <var-decl name='' type-id='type-id-5' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='one_more_level' type-id='type-id-6' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='yes_really_one_more' type-id='type-id-4' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <class-decl name='foo_t' size-in-bits='512' alignment-in-bits='32' is-struct='yes' visibility='default' id='type-id-7'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='foo' type-id='type-id-8' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='64'>
> +        <var-decl name='bar' type-id='type-id-9' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='128'>
> +        <var-decl name='baz' type-id='type-id-10' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='192'>
> +        <var-decl name='self' type-id='type-id-11' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='256'>
> +        <var-decl name='named' type-id='type-id-12' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='64'>
> +        <var-decl name='' type-id='type-id-3' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='unnamed_sub_member' type-id='type-id-4' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='64'>
> +        <var-decl name='' type-id='type-id-5' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='one_more_level' type-id='type-id-6' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='yes_really_one_more' type-id='type-id-4' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='64'>
> +        <var-decl name='' type-id='type-id-2' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='64'>
> +        <var-decl name='' type-id='type-id-13' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='448'>
> +        <var-decl name='after_the_end' type-id='type-id-8' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <type-decl name='double' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
> +    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-8'/>
> +    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-4'/>
> +    <type-decl name='short int' size-in-bits='16' alignment-in-bits='16' id='type-id-14'/>
> +    <type-decl name='signed char' size-in-bits='8' alignment-in-bits='8' id='type-id-15'/>
> +    <typedef-decl name='size_t' type-id='type-id-16' id='type-id-9'/>
> +    <union-decl name='' size-in-bits='64' is-anonymous='yes' visibility='default' id='type-id-12'>
> +      <data-member access='public'>
> +        <var-decl name='should_not_appear' type-id='type-id-6' visibility='default'/>
> +      </data-member>
> +      <data-member access='public'>
> +        <var-decl name='nor_should_this' type-id='type-id-17' visibility='default'/>
> +      </data-member>
> +    </union-decl>
> +    <union-decl name='' is-anonymous='yes' visibility='default' id='type-id-13'/>
> +    <union-decl name='' size-in-bits='64' is-anonymous='yes' visibility='default' id='type-id-5'>
> +      <data-member access='public'>
> +        <var-decl name='one_more_level' type-id='type-id-6' visibility='default'/>
> +      </data-member>
> +      <data-member access='public'>
> +        <var-decl name='yes_really_one_more' type-id='type-id-4' visibility='default'/>
> +      </data-member>
> +    </union-decl>
> +    <type-decl name='unsigned char' size-in-bits='8' alignment-in-bits='8' id='type-id-18'/>
> +    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-19'/>
> +    <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='type-id-16'/>
> +    <type-decl name='unsigned short int' size-in-bits='16' alignment-in-bits='16' id='type-id-20'/>
> +    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-17'/>
> +    <qualified-type-def type-id='type-id-1' const='yes' id='type-id-21'/>
> +    <pointer-type-def type-id='type-id-21' size-in-bits='64' alignment-in-bits='64' id='type-id-10'/>
> +    <pointer-type-def type-id='type-id-7' size-in-bits='64' alignment-in-bits='64' id='type-id-11'/>
> +    <var-decl name='used' type-id='type-id-7' mangled-name='used' visibility='default'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-ctf/test0 b/tests/data/test-read-ctf/test0
> new file mode 100755
> index 0000000000000000000000000000000000000000..aca7fbacdfff7ad2caf0142390710373a8da72a1
> GIT binary patch
> literal 16656
> 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
>
> literal 0
> HcmV?d00001
>
> diff --git a/tests/data/test-read-ctf/test0.abi b/tests/data/test-read-ctf/test0.abi
> new file mode 100644
> index 00000000..50ca26f4
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test0.abi
> @@ -0,0 +1,54 @@
> +<abi-corpus version='2.1' path='data/test-read-ctf/test0'>
> +  <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='_start' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='foo_1' 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-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-symbol name='status' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='test_array' size='40' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='test_const' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='test_float' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='test_pointer' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='test_restrict' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='test_volatile' size='2' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-variable-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <type-decl name='' is-anonymous='yes' size-in-bits='1' alignment-in-bits='8' id='type-id-1'/>
> +    <type-decl name='char' size-in-bits='8' alignment-in-bits='8' id='type-id-2'/>
> +    <class-decl name='S' size-in-bits='32' alignment-in-bits='32' is-struct='yes' visibility='default' id='type-id-3'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='m0' type-id='type-id-4' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <class-decl name='' size-in-bits='32' alignment-in-bits='8' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-5'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='status0' type-id='type-id-1' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='1'>
> +        <var-decl name='status1' type-id='type-id-1' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <type-decl name='float' size-in-bits='32' alignment-in-bits='32' id='type-id-6'/>
> +    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-4'/>
> +    <array-type-def dimensions='1' type-id='type-id-4' size-in-bits='320' alignment-in-bits='32' id='type-id-7'>
> +      <subrange length='10' type-id='type-id-8' id='type-id-9'/>
> +    </array-type-def>
> +    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-10'/>
> +    <type-decl name='short int' size-in-bits='16' alignment-in-bits='16' id='type-id-11'/>
> +    <type-decl name='signed char' size-in-bits='8' alignment-in-bits='8' id='type-id-12'/>
> +    <type-decl name='unsigned char' size-in-bits='8' alignment-in-bits='8' id='type-id-13'/>
> +    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-14'/>
> +    <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
> +    <type-decl name='unsigned short int' size-in-bits='16' alignment-in-bits='16' id='type-id-15'/>
> +    <pointer-type-def type-id='type-id-3' size-in-bits='64' alignment-in-bits='64' id='type-id-16'/>
> +    <pointer-type-def type-id='type-id-2' size-in-bits='64' alignment-in-bits='64' id='type-id-17'/>
> +    <qualified-type-def type-id='type-id-3' const='yes' id='type-id-18'/>
> +    <pointer-type-def type-id='type-id-10' size-in-bits='64' alignment-in-bits='64' id='type-id-19'/>
> +    <qualified-type-def type-id='type-id-19' restrict='yes' id='type-id-20'/>
> +    <qualified-type-def type-id='type-id-11' volatile='yes' id='type-id-21'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-ctf/test0.c b/tests/data/test-read-ctf/test0.c
> new file mode 100644
> index 00000000..eb702312
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test0.c
> @@ -0,0 +1,32 @@
> +
> +#include <stdio.h>
> +
> +char* test_pointer = NULL;
> +int test_array[10] = {0};
> +volatile short test_volatile = 1;
> +float test_float = 0.0;
> +
> +struct {
> +  unsigned int status0 : 1;
> +  unsigned int status1 : 1;
> +} status;
> +
> +
> +struct S
> +{
> +  int m0;
> +};
> +
> +const struct S test_const;
> +long* restrict test_restrict;
> +
> +int
> +foo_1(struct S* s)
> +{
> +  return s->m0;
> +}
> +
> +int main()
> +{
> +
> +}
> diff --git a/tests/data/test-read-ctf/test0.hash.abi b/tests/data/test-read-ctf/test0.hash.abi
> new file mode 100644
> index 00000000..b58520ab
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test0.hash.abi
> @@ -0,0 +1,54 @@
> +<abi-corpus version='2.1' path='data/test-read-ctf/test0'>
> +  <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='_start' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='foo_1' 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-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-symbol name='status' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='test_array' size='40' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='test_const' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='test_float' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='test_pointer' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='test_restrict' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='test_volatile' size='2' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-variable-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <type-decl name='' is-anonymous='yes' size-in-bits='1' alignment-in-bits='8' id='811c9dc5'/>
> +    <type-decl name='char' size-in-bits='8' alignment-in-bits='8' id='a84c031d'/>
> +    <class-decl name='S' size-in-bits='32' alignment-in-bits='32' is-struct='yes' visibility='default' id='50d9a3fa'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='m0' type-id='95e97e5e' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <class-decl name='' size-in-bits='32' alignment-in-bits='8' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f72'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='status0' type-id='811c9dc5' visibility='default'/>
> +      </data-member>
> +      <data-member access='public' layout-offset-in-bits='1'>
> +        <var-decl name='status1' type-id='811c9dc5' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <type-decl name='float' size-in-bits='32' alignment-in-bits='32' id='a6c45d85'/>
> +    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='95e97e5e'/>
> +    <array-type-def dimensions='1' type-id='95e97e5e' size-in-bits='320' alignment-in-bits='32' id='b7bd1749'>
> +      <subrange length='10' type-id='7359adad' id='487da03a'/>
> +    </array-type-def>
> +    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='bd54fe1a'/>
> +    <type-decl name='short int' size-in-bits='16' alignment-in-bits='16' id='a2185560'/>
> +    <type-decl name='signed char' size-in-bits='8' alignment-in-bits='8' id='28577a57'/>
> +    <type-decl name='unsigned char' size-in-bits='8' alignment-in-bits='8' id='002ac4a6'/>
> +    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
> +    <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='7359adad'/>
> +    <type-decl name='unsigned short int' size-in-bits='16' alignment-in-bits='16' id='8efea9e5'/>
> +    <pointer-type-def type-id='50d9a3fa' size-in-bits='64' alignment-in-bits='64' id='fd01f598'/>
> +    <pointer-type-def type-id='a84c031d' size-in-bits='64' alignment-in-bits='64' id='26a90f95'/>
> +    <qualified-type-def type-id='50d9a3fa' const='yes' id='0fb3b55d'/>
> +    <pointer-type-def type-id='bd54fe1a' size-in-bits='64' alignment-in-bits='64' id='3ccc2590'/>
> +    <qualified-type-def type-id='3ccc2590' restrict='yes' id='af4b1b38'/>
> +    <qualified-type-def type-id='a2185560' volatile='yes' id='ec67e496'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-ctf/test1.c b/tests/data/test-read-ctf/test1.c
> new file mode 100644
> index 00000000..3a5bac49
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test1.c
> @@ -0,0 +1,25 @@
> +enum opaque_enum;
> +struct opaque_struct;
> +
> +typedef enum opaque_enum opaque_enum;
> +typedef struct opaque_struct opaque_struct;
> +
> +void
> +fn(opaque_struct *, opaque_enum *e);
> +
> +enum opaque_enum
> +{
> +  e0,
> +  e1
> +};
> +
> +struct opaque_struct
> +{
> +  opaque_enum m0;
> +};
> +
> +void
> +fn(opaque_struct * s, opaque_enum *e)
> +{
> +  s->m0 = *e;
> +}
> diff --git a/tests/data/test-read-ctf/test1.so b/tests/data/test-read-ctf/test1.so
> new file mode 100755
> index 0000000000000000000000000000000000000000..df5ef8d38fa53081007cab96424e3d60b512751f
> GIT binary patch
> literal 15592
> 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
> I@1C^(7v)NDpa1{>
>
> literal 0
> HcmV?d00001
>
> diff --git a/tests/data/test-read-ctf/test1.so.abi b/tests/data/test-read-ctf/test1.so.abi
> new file mode 100644
> index 00000000..5b3caf63
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test1.so.abi
> @@ -0,0 +1,23 @@
> +<abi-corpus version='2.1' path='data/test-read-ctf/test1.so'>
> +  <elf-function-symbols>
> +    <elf-symbol name='fn' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-function-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='type-id-1'/>
> +    <class-decl name='opaque_struct' size-in-bits='32' alignment-in-bits='32' is-struct='yes' visibility='default' id='type-id-2'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='m0' type-id='type-id-3' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <enum-decl name='opaque_enum' linkage-name='opaque_enum' id='type-id-4'>
> +      <underlying-type type-id='type-id-1'/>
> +      <enumerator name='e0' value='0'/>
> +      <enumerator name='e1' value='1'/>
> +    </enum-decl>
> +    <typedef-decl name='opaque_enum' type-id='type-id-4' id='type-id-3'/>
> +    <typedef-decl name='opaque_struct' type-id='type-id-2' id='type-id-5'/>
> +    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-6'/>
> +    <pointer-type-def type-id='type-id-3' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
> +    <pointer-type-def type-id='type-id-5' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-ctf/test1.so.hash.abi b/tests/data/test-read-ctf/test1.so.hash.abi
> new file mode 100644
> index 00000000..8019cb54
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test1.so.hash.abi
> @@ -0,0 +1,23 @@
> +<abi-corpus version='2.1' path='data/test-read-ctf/test1.so'>
> +  <elf-function-symbols>
> +    <elf-symbol name='fn' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-function-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='811c9dc5'/>
> +    <class-decl name='opaque_struct' size-in-bits='32' alignment-in-bits='32' is-struct='yes' visibility='default' id='6cde5052'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='m0' type-id='99fcd3a5' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <enum-decl name='opaque_enum' linkage-name='opaque_enum' id='55763a91'>
> +      <underlying-type type-id='811c9dc5'/>
> +      <enumerator name='e0' value='0'/>
> +      <enumerator name='e1' value='1'/>
> +    </enum-decl>
> +    <typedef-decl name='opaque_enum' type-id='55763a91' id='99fcd3a5'/>
> +    <typedef-decl name='opaque_struct' type-id='6cde5052' id='dae69ca1'/>
> +    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
> +    <pointer-type-def type-id='99fcd3a5' size-in-bits='64' alignment-in-bits='64' id='0e0526e0'/>
> +    <pointer-type-def type-id='dae69ca1' size-in-bits='64' alignment-in-bits='64' id='3f6e71d0'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-ctf/test2.c b/tests/data/test-read-ctf/test2.c
> new file mode 100644
> index 00000000..b04490a8
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test2.c
> @@ -0,0 +1,19 @@
> +struct S0
> +{
> +  void* m0;
> +};
> +
> +typedef const void* POINTER;
> +
> +struct S1
> +{
> +  POINTER m0;
> +};
> +
> +void foo(struct S0* a __attribute__((unused)))
> +{
> +}
> +
> +void bar(struct S1* a __attribute__((unused)))
> +{
> +}
> diff --git a/tests/data/test-read-ctf/test2.so b/tests/data/test-read-ctf/test2.so
> new file mode 100755
> index 0000000000000000000000000000000000000000..d9c07517527553d99951c2129da2f2ae6c1bce03
> GIT binary patch
> literal 15616
> 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
> U6x%k4_vJZDAzn&WN_;y0Q+>X1e*gdg
>
> literal 0
> HcmV?d00001
>
> diff --git a/tests/data/test-read-ctf/test2.so.abi b/tests/data/test-read-ctf/test2.so.abi
> new file mode 100644
> index 00000000..eb6aff3e
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test2.so.abi
> @@ -0,0 +1,25 @@
> +<abi-corpus version='2.1' path='data/test-read-ctf/test2.so'>
> +  <elf-function-symbols>
> +    <elf-symbol name='bar' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-function-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <class-decl name='S0' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='type-id-1'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='m0' type-id='type-id-2' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <class-decl name='S1' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='type-id-3'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='m0' type-id='type-id-4' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <typedef-decl name='POINTER' type-id='type-id-5' id='type-id-4'/>
> +    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
> +    <pointer-type-def type-id='type-id-3' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
> +    <qualified-type-def type-id='type-id-8' const='yes' id='type-id-9'/>
> +    <pointer-type-def type-id='type-id-9' size-in-bits='64' alignment-in-bits='64' id='type-id-5'/>
> +    <pointer-type-def type-id='type-id-8' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
> +    <type-decl name='void' id='type-id-8'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-ctf/test2.so.hash.abi b/tests/data/test-read-ctf/test2.so.hash.abi
> new file mode 100644
> index 00000000..6e57333b
> --- /dev/null
> +++ b/tests/data/test-read-ctf/test2.so.hash.abi
> @@ -0,0 +1,25 @@
> +<abi-corpus version='2.1' path='data/test-read-ctf/test2.so'>
> +  <elf-function-symbols>
> +    <elf-symbol name='bar' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +    <elf-symbol name='foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
> +  </elf-function-symbols>
> +  <abi-instr address-size='64' language='LANG_C'>
> +    <class-decl name='S0' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='109cd6fe'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='m0' type-id='eaa32e2f' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <class-decl name='S1' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='119cd891'>
> +      <data-member access='public' layout-offset-in-bits='0'>
> +        <var-decl name='m0' type-id='8a34a235' visibility='default'/>
> +      </data-member>
> +    </class-decl>
> +    <typedef-decl name='POINTER' type-id='6e97a70c' id='8a34a235'/>
> +    <pointer-type-def type-id='109cd6fe' size-in-bits='64' alignment-in-bits='64' id='842ea234'/>
> +    <pointer-type-def type-id='119cd891' size-in-bits='64' alignment-in-bits='64' id='5e30a4f9'/>
> +    <qualified-type-def type-id='48b5725f' const='yes' id='8581546e'/>
> +    <pointer-type-def type-id='8581546e' size-in-bits='64' alignment-in-bits='64' id='6e97a70c'/>
> +    <pointer-type-def type-id='48b5725f' size-in-bits='64' alignment-in-bits='64' id='eaa32e2f'/>
> +    <type-decl name='void' id='48b5725f'/>
> +  </abi-instr>
> +</abi-corpus>
> diff --git a/tests/data/test-read-dwarf/PR26261/Makefile b/tests/data/test-read-dwarf/PR26261/Makefile
> deleted file mode 100644
> index f66fa38a..00000000
> --- a/tests/data/test-read-dwarf/PR26261/Makefile
> +++ /dev/null
> @@ -1,21 +0,0 @@
> -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
> deleted file mode 100755
> index 564a4247643942bbfd91c0e75653dffe80ce5851..0000000000000000000000000000000000000000
> GIT binary patch
> literal 0
> HcmV?d00001
>
> literal 10976
> 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
>
> diff --git a/tests/data/test-read-dwarf/PR27700/test-PR27700.o b/tests/data/test-read-dwarf/PR27700/test-PR27700.o
> deleted file mode 100644
> index 3f084d2132f0f43a683769ea91e9733fc599700a..0000000000000000000000000000000000000000
> GIT binary patch
> literal 0
> HcmV?d00001
>
> literal 3248
> zcmb_e&2Jl35TCbe$1dAAAFfJ6in1V}DZ*<zg{A~0xCHVczM`N=Ac3s4_t{>s*VTGc
> zLJ^`85>f>cL2!d365@u0#6N(zapR7-AaUhZi37~+&T}@e8x;Yg_|433X5P%3_py2Z
> zxfeDJAwZFUH8|1~3h-^=NN&Vp1I|Dh_O@>Qwsq^h+lO!b@Cm|s5Jj>YG~7=^nyi#!
> zc7{VJ<X%I_5EI0bwDFh}WW=%wxm=t)PZ1(Fu1?J+zWf-YC)#M6BFXr)2Zf@85{N}G
> zOXtzim=O<`%9gn>zc3?a3)A-km^on<*DTB0F0WWmSx;J`43K*WENjg&OSlwAJUwR?
> z6WfJ33TvFZF-Kk#c~FM!vT+WeFoj{;Xo1J507?yUA7Y6HRqPmG;br7`^u2^!2=QlW
> zk{GQKe<&;@lc8>)JY}MgB9RwxYV2|L1H;6a{b1yG1L@g*5W(h4d-i&L*{;`}np3lv
> zYD;zcvln;KVatu!P^n$CD}!i1kgHu8$k1=2>W1y!>cN%EmCKLYl`dfWoAOe^Y6+_+
> zYzeBp;Xqcsq4%a=?fOx*@3-8R-*x?db!T^JdAU}rMsgI5s-7FUu~-SE>s7qB-LRuv
> zfLto<@3jA?N&TSR-}hw2^Fuv>mhW2VUw3){o9pW<_9Axf;y-8`@5UMC;>IqBgK05;
> zx==jCEj*7n{fOc-aJ4l3p|L(Wv4IW=oH^17$iW|fWf^gkvtTg!<mpBeEm?#&D+@;N
> zi4*YDBarei;Z#aH63r7%y$Pp}oKlhrc<nOCgsBV^Z!k>Wflnhco9fT_-f4SHZwZmw
> zgL_a;uUgGaIIT|UvnUf0PQMLOkj^G-jI#>&u|PXEzNjca$~euTY9Q!p3a7kH);Bf0
> z!}^OFK4AS74S$vO*EO6~z+)eiUZ?5_)tP4>V$^3M-T%P^9`|97^+z=P3)X8I{x$1Q
> zX!!T6uW0y>tUt?Kug7MbdY|q;IHPw4k=sHZg$eH|DUt^fIP_A1(;AJy31#1PJlWds
> zHvOP8L|ZJotyU<nA2Yk58+7IIkiH*C6@n?0NN_XO+rz;?;#=(m!$>;#?o>vR+kT5D
> zmc3>tbO(|b@*mke##4{fzN+aOER639>*SlJ2T&nQe^H)KJEdej{sP+Qy#L$yI>zdA
> zQaY9YGg4Bd`_lKBUcE-jCl>i|+Z-^1Ao;1gi68lxR&mtlB*QPU6(D4;nC`oS1|1{c
> z9R}5XI4PdinN`2d8>-@|etNC-`aQ(5^50}oy&LEjlkQ9JQC9vP&VR^pl%L)&J^wYt
> zXiilpiZT7ni6R9sSNRox7xAq4O}^Ye-6j5`6XMH!AggzY|D5ABH+V)r(Cnb<R{q~`
> z{IRzPu`Q0jq8yp4{weq?6tepNEB9ZWQ|do`HC4RAsUAHyLU5Dw_qbsC&e7LckEcD&
> eTI%mq6q5QsDADdbYgAWO{B5rPI~B-W@891PcJreE
>
> diff --git a/tests/data/test-read-dwarf/test-PR26568-1.o b/tests/data/test-read-dwarf/test-PR26568-1.o
> deleted file mode 100644
> index 9249e16d4d52b4556b1cf071cc504d2a71204619..0000000000000000000000000000000000000000
> GIT binary patch
> literal 0
> HcmV?d00001
>
> literal 2864
> zcmbtV&2Jl35TCctADe9KIx)~j;jl<lZKUoxNfTp=Qd~lbD^L|h>IJDv*Y?_8u-Dak
> z11<=0pddwnR3s!oLU4csHxLI7TtMOg{{VkN&xl(k4luL(p1pqAs8V^7-^~1GelzpF
> z*6&_@<t2?Vkb}Wxm|7AAxSgBo^+>Hl8J6Hi<LG|l=$!|R53fG>J;F(A{H*75*$mfM
> z<EV7=w;$1wiJW?r`&faqku#pO4C8fF`50J+6y#>Io*#myv)rp_@;kutqyS{~EQy@X
> zv=C+9qG^{P{R-%ey^q?QLpIEJ4t-z?k&crr$-ev^EyF<<DcUDJSkNgKutj#ZST=ZZ
> zrMSqJ@}<-0Ei=QoWISiEGPY3wu9I=CTr;rAr@=5T8(hb(gj&STPA3@o0$f9)US?dM
> z=9wduGR)iT`Q<p}xn(L@Kl9lO%T&t9PD*KK02WSRDar&FsAXyvuxw(;)g_=veGz93
> z&f(11Kg9yh(b?mHFbLgIXzlH9RJW=%Yu#?e+_^YC8r)#-eXW-@4OzR_Z<ssgrd_kQ
> z%#F46t+ndLMf3c=+cq0c7~|H(XID*Y5FYyOcGvaYz-yuD1g+loxK_2Qo2J!;N^dxD
> zEA3(XHLue3!b;z3I!&+Zc>PMp8@r<lH8rZVozRI?D{!5*)qc|nI?x~bU6by`@y2&|
> zb}pIcvB}kk_ZTnpu~-0mYaiIS#8wva`aRs1ClRL~jc8M^6iXjyJB8dW42a>>8L4>X
> z|Nb}4$x~k#Zm>8?mBZ1KHn@0Hs*gkBu_l}x@(F9Ia+sSM35^3@%9O#Okb+YGc;Qn9
> zhsmp(c$ZLHO6<er!X7(JdbaqE1am&26C^Veo?OKuIdMq*<Jg49g_L+h*vmrFxlL|7
> z>Z<~$_~d!tOyE@auCPB6Qq7a>KPzHLlun4>JOMWaPCX|31bcL65IRkiVGzrn)IxV0
> zf=zD-?B-|$cHs6MyX`g)y9b`%8KN)Jon|v|-<WYbf#Y}GSxVpYT}i<bV7G>Yfs60Z
> z_J^Ts<Eyhqq0@R@ByxKPoxmBmqVfMJR*+A7EB8~Ts|#gvkAzLJ$?+5#gsCs;r1n%k
> zeLCqLJSu-()JHKhWc{CJ(74wmL?3+mE3GF%)W3`WU*T7Q)4d`{-dX(Dh{iU~>YB*0
> zBEWB>sOhA}?x9P?DEb!xu1%?trpCUEXj=chY)q7V>Yu(=YX5D-)SSfpOMneB5<`tW
> zKwnz@&qaN?PgI}YwOao+Vw6+%iE1>S5s&dJ2?#0cOZhh9Y5YG0-+l=HuHY+Sz|{*W
> z0%Tno|ApYsd^-@+1-~W(g_P@;@TaJx?cWb6`$zu<k}vm_`cZ3B?z*VICmN>jH~q_~
> hd^(e~rQV~aa6A!<$*iuQ@}}|s5dD8MVaAHe{|}8}$8i7v
>
> diff --git a/tests/data/test-read-dwarf/test-PR26568-2.o b/tests/data/test-read-dwarf/test-PR26568-2.o
> deleted file mode 100644
> index cc94708c9cb10e2f0f5e51aed7e7a713767caaf8..0000000000000000000000000000000000000000
> GIT binary patch
> literal 0
> HcmV?d00001
>
> literal 2824
> zcmbtVQHvW@6h3!mlT3CtF`KB}WqlaI(k^r++wE?Mm9433-4sh%7W$x2)=6@cj3$#Z
> znXRc(6clk0L_rZnw9p4%efCN4q2P}YU-|=lEBK)2%-owy?oKJ_fw}kG@0{<PbMM?U
> z^TCyCuW5{d6b6@Iwvs47Gdt58k=lR?l;KA6_+j(-?xW^sR~|ixaMGH;7`bd_LDyLG
> zxODTk`)F8*j7AjuM1s?iF&?x9rZrI2C%|-4kh_ra{17yQW!}W4eg{~V6o8D8p(%SA
> z490Gwma}QtBhcs``M?%QC6PJU_xEs>chN+O_GKRy4Hq?F%j|TqV(P`U;xa4eN~h3T
> zVWxS}e92@L%v%86pvBcn-NdS10Moo=>IRk})FPI0is{CTlPkbgq#6!;c{L`VS*75O
> zm2X~IrJ(uDG^n-$u=o@PB?g?M;;1aZ1PPJ*NI;SLDvlbQ!I81Qiv=8`*NSJ&AmroF
> z-apu^ZP)7drqhnO`8Yf-^gR3MN28)?$U5P>cm0O7Yi&7oXWQD`IKRD7+q__%J>VUy
> z>4q_GUwCodvWMZ3&v$y<=YiM8r5m*SJCl0Nu5DR%532pqkXJjS&f8wK=Y`dQ*K%84
> z&-Dh?t~cT1DrFv5J8tMksvU5*V|U(lgDwn4e$S#i0DHT;7p=2c)B2N3!ks-GZxz^k
> z2f!vJwziZrzQ8ki4sm)&q7%JbEPbNw7P4=lLky>mNX4uC*FR}SJ+*W2bj5pAIXYU>
> zL>JAX+H^=XVZx|GF0q=aI^<`Igr)=D-W1WHkb+YEc&}4Lhouu}8If}09HzJR#I>UC
> z#C8!8s7<9#kc><??P8fg6gf*gMgg7?ip1X#>s2w+dz)T&)Yk=0{>k@!Gl5gyuf_VV
> znAJG4W{Q&$J~WktuKI612Db!GH74r>XMATEx-Fc;AfEeD3;84jhx!Ga)_4p~zz43=
> z;jN?Iq33r;Xp3~W)e89SIkOwMevi*n2A<C)1yg|29u0>ad(QDkA$PFl>~ZL}-w}a$
> z|F9dlLoN#cpVJ!h>8#{=%5V*#Oz)9clW$U<#|2?(M?J1Ql~3PIx(EN2e_rIrX-;JR
> zpXSiG)+9t<d-_E-k|63I#{W(DRp4~52$FXee;JYN;Hd723`+w1Jo1_is_#CURE)g8
> z6X3>-8fmKU>xib+-^j#7$*211Yo*rTK}?NF%-;prq(wqh-$S&e<-aBJ%X6aq)YoeM
> zTZmCiStqKIltnZCAOSJU{BnLD@ihL=g6}+m|FPgJZt%z4$6#iac_s3#;H&O`3ZO0>
> z#Vq$P;jd6hJHJm;&X4{Ek}uDd>QQr3>=n^a`=Vg_e$!t@<<mP+dk-P#Q&A|-#?y3E
> T_fK)t`1eHp_ovKQQThJ@<ln>C
>
> diff --git a/tests/data/test-read-dwarf/test3.c b/tests/data/test-read-dwarf/test3.c
> deleted file mode 100644
> index 2808db4b..00000000
> --- a/tests/data/test-read-dwarf/test3.c
> +++ /dev/null
> @@ -1,11 +0,0 @@
> -// Test file for creating multiple alias for a symbol
> -
> -void __foo(void);
> -void foo(void) __attribute__((weak, alias("__foo")));
> -void foo__(void) __attribute__((weak, alias("__foo")));
> -void __foo__(void) __attribute__((alias("__foo")));
> -
> -void __foo(void)
> -{
> -
> -}
> diff --git a/tests/data/test-read-dwarf/test3.so b/tests/data/test-read-dwarf/test3.so
> deleted file mode 100755
> index 4c426fc3c202d2f2dd027ffd8825ccfea36b2a09..0000000000000000000000000000000000000000
> GIT binary patch
> literal 0
> HcmV?d00001
>
> literal 8851
> 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
> NGxzm*6T@y2`@a>G9{B(O
>
> diff --git a/tests/data/test-read-dwarf/test4.c b/tests/data/test-read-dwarf/test4.c
> deleted file mode 100644
> index 7f0abaa1..00000000
> --- a/tests/data/test-read-dwarf/test4.c
> +++ /dev/null
> @@ -1,14 +0,0 @@
> -// Test file for restrict (needs to be compiled by a GCC that actually emits
> -// DW_TAG_restrict_type. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59051
> -//
> -// gcc -gdwarf-3 -std=c99 -shared -nostartfiles -o test4.so test4.c
> -
> -char *
> -cpy (char * restrict s1, const char * restrict s2, unsigned int n)
> -{
> -  char *t1 = s1;
> -  const char *t2 = s2;
> -  while(n-- > 0)
> -    *t1++ = *t2++;
> -  return s1;
> -}
> diff --git a/tests/data/test-read-dwarf/test4.so b/tests/data/test-read-dwarf/test4.so
> deleted file mode 100755
> index 3be3f0d644190425cbb2a08ed7b4f1d164c13ef1..0000000000000000000000000000000000000000
> GIT binary patch
> literal 0
> HcmV?d00001
>
> literal 3364
> zcmcImPiP!v6n`_b|JqG9o1{u1Dx+wdh?yj9NYj?oP0~#_x@}TzARc6#-JR?%W+!20
> zViQq%s7hlABqHiTu!08#!HX0H4*_pIdGgf5UIIcd@mBN@-<$c~c6PF>i1@*L?|r}b
> zdvCsZ-}k-wZe;T_vLpdF1ug)MGO~|kgkd`-6cia4hbZ>lkn*_EN2WtsUBqDtpn4p7
> z2Zdz3F8eskU9?f#^?K@5Por@E#xLP{0nG2Yr3mUDi}{4*F~MU=TxwU*FYxI;_&0r8
> z*c6oHN0MT-%aNE4GTJu<BV<BE%3n_azbf3jP^KXccNA41zIdh${&*W4imMy2TrCte
> zXGI$W-7Fcd0lHpr9NlpZ+eOGK0W9P;_i~%>{+8QZt8Xsc&)v?Vnth0}j&lFOlc+t+
> zZOu!$%>_gk_H$b=p?-P4>u%4j^zH2Zt@#7=dw+NBSMq)RXPl4Jr<|ue(l>s4aB%Pf
> zN?sS~?N>lrPfL9r@x(R~o<JKt>&WwRFquk!AWwJ3<UBI`7-(+fpVxJff(P*9BEP)W
> zw}kzuPlJ;}CWSmM<o_)$O;4Xw`!8Kt7*I#Gkzs9EJvBTsIy^QquJ)VjtEOG8nU-rT
> z4*+G!{|JB2^N!)25uWJ}2+-~XNJz9hr0d=Q8e45gq=aBuqWvJr(nmPp$V`wv_h7{t
> zLB<!v-dR+fQ#km_8_X*f>fd{MKH?%PLSf{cO2kE0^c!#R21FB|p%#;3H&Dch5+_qM
> z@g4TQEfRkWb&$HH=Tf~%CDoVemU^T#u9~b#FLo%2bIJ3`lO40Y1ZR$ZI@KZd;%7#|
> zx6Jm+xS)~IreU-TlF3=5#hyjw0!GCbp8-M=Cp-ZY_)Zy~qBl!_raH0rN+#|R30%{0
> zN3|kN3*d;%$vL)n^X5?E$9pf!GSY`CD>ZYdX4r2IId*Y~d>mM_oNC!JOKR0}0hd^v
> z{)aVI2W#${Wloe$3m3kKL&GjsCf3Kt2FFI#!E))kVJ{7yRtFuoG*LWzwlTM2#jpW1
> zXQSpC1(dGs%L;21!>NE)+OUw~OV<X?HP>Cx%!<Bb8#Pm}ln~>Q$1-ZwB51{x8f`*E
> z%)(k(H*CWyn+^}F*3t^=MxkJvZ}DikYMHF#MEnf?$G#8!sn+t|<#W!GP6;)(^Z$YC
> z!qaG@GtPFd11z`685^A(;;=v0gMokzRp7e9lIsZBsEIP;53nB*7}ueUm<Y@8Y36xz
> zfHT6M=ilx>$NaE=Hst@c2*h%n9fjoYXLt@3{_hdS|MR+tvr8a0zw$iFAOANO(MCBL
> zCQ_i?5f0A>Fj6^xER6sbq}~($;kfL_+|@Sze+d7dm?&h}|D87ecSWKpez1l8KSW~~
> zBmN0-ftU<Bx8Qyvu<&=5h5vhP{P~^TXy>&FQXdHaFM}ZJ?8h*TdG9es@)z+VO$%ch
> zu^xPQ|M2-af>^8f*E`UF?V>Llefa$iLkmU0*>W8SniZTepYLW|X`J6?{P2B@><U&M
> zK5xzZ81VUN#^a6i(TsCef+)qO>>O?ih~$P$idV@(APyA}$qbnk=nNtL`bOaQgF^-c
> zTH!Q93GbhES#5HmwI)2=`VnY#kEJ@@>K=Q#4Ni5b6~FNd)GxkvW%BauH0YP|b5oOf
> ceQsvv)$BF>+T>I|t9#d7zU0!yHh9zh3+<yQu>b%7
>
> diff --git a/tests/test-annotate.cc b/tests/test-annotate.cc
> index bc4ce852..174de483 100644
> --- a/tests/test-annotate.cc
> +++ b/tests/test-annotate.cc
> @@ -42,12 +42,12 @@ InOutSpec in_out_specs[] =
>      "output/test-annotate/test2.so.abi"
>    },
>    {
> -    "data/test-read-dwarf/test3.so",
> +    "data/test-read-common/test3.so",
>      "data/test-annotate/test3.so.abi",
>      "output/test-annotate/test3.so.abi"
>    },
>    {
> -    "data/test-read-dwarf/test4.so",
> +    "data/test-read-common/test4.so",
>      "data/test-annotate/test4.so.abi",
>      "output/test-annotate/test4.so.abi"
>    },
> diff --git a/tests/test-read-common.cc b/tests/test-read-common.cc
> new file mode 100644
> index 00000000..431a660e
> --- /dev/null
> +++ b/tests/test-read-common.cc
> @@ -0,0 +1,184 @@
> +// -*- Mode: C++ -*-
> +//
> +
> +#include <fstream>
> +#include <cstring>
> +#include "test-read-common.h"
> +
> +using std::ofstream;
> +using std::cerr;
> +using std::dynamic_pointer_cast;
> +
> +using abigail::tools_utils::emit_prefix;
> +using abigail::tests::get_build_dir;
> +using abigail::xml_writer::write_context_sptr;
> +using abigail::xml_writer::create_write_context;
> +using abigail::xml_writer::write_corpus;
> +
> +namespace abigail
> +{
> +namespace tests
> +{
> +namespace read_common
> +{
> +
> +test_task::test_task(const InOutSpec &s,
> +                     string& a_out_abi_base,
> +                     string& a_in_elf_base,
> +                     string& a_in_abi_base)
> +    : is_ok(true),
> +      spec(s),
> +      out_abi_base(a_out_abi_base),
> +      in_elf_base(a_in_elf_base),
> +      in_abi_base(a_in_abi_base)
> +  {}
> +
> +bool
> +test_task::serialize_corpus(const string& out_abi_path,
> +                            corpus_sptr corp)
> +{
> +  ofstream of(out_abi_path.c_str(), std::ios_base::trunc);
> +  if (!of.is_open())
> +    {
> +       error_message = string("failed to read ") + out_abi_path + "\n";
> +       return false;
> +    }
> +
> +  write_context_sptr write_ctxt
> +      = create_write_context(corp->get_environment(), of);
> +  set_type_id_style(*write_ctxt, spec.type_id_style);
> +  is_ok = write_corpus(*write_ctxt, corp, /*indent=*/0);
> +  of.close();
> +
> +  return true;
> +}
> +
> +bool
> +test_task::run_abidw(const string& extargs)
> +{
> +  string abidw = string(get_build_dir()) + "/tools/abidw";
> +  string drop_private_types;
> +  if (!in_public_headers_path.empty())
> +    drop_private_types += "--headers-dir " + in_public_headers_path +
> +      " --drop-private-types";
> +  string cmd = abidw + " " + drop_private_types + " --abidiff " + extargs +
> +   in_elf_path;
> +  if (system(cmd.c_str()))
> +    {
> +      error_message = string("ABIs differ:\n")
> +        + in_elf_path
> +        + "\nand:\n"
> +        + out_abi_path
> +        + "\n";
> +
> +      return false;
> +    }
> +
> +  return true;
> +}
> +
> +bool
> +test_task::run_diff()
> +{
> +  set_in_abi_path();
> +  string cmd = "diff -u " + in_abi_path + " " + out_abi_path;
> +  if (system(cmd.c_str()))
> +    {
> +      error_message = string("ABIs differ:\n")
> +        + in_abi_path
> +        + "\nand:\n"
> +        + out_abi_path
> +        + "\n";
> +
> +      return false;
> +    }
> +
> +  return true;
> +}
> +
> +void
> +display_usage(const string& prog_name, ostream& out)
> +{
> +  emit_prefix(prog_name, out)
> +    << "usage: " << prog_name << " [options]\n"
> +    << " where options can be: \n"
> +    << "  --help|-h  display this message\n"
> +    << "  --no-parallel execute testsuite is a sigle thread\n"
> +  ;
> +}
> +
> +bool
> +parse_command_line(int argc, char* argv[], options& opts)
> +{
> +  for (int i = 1; i < argc; ++i)
> +    {
> +      if (!strcmp(argv[i], "--no-parallel"))
> +        opts.parallel = false;
> +      else if (!strcmp(argv[i], "--help")
> +               || !strcmp(argv[i], "--h"))
> +        return false;
> +      else
> +        {
> +          if (strlen(argv[i]) >= 2 && argv[i][0] == '-' && argv[i][1] == '-')
> +            opts.wrong_option = argv[i];
> +          return false;
> +        }
> +    }
> +
> +  return true;
> +}
> +
> +bool
> +run_tests(const size_t num_tests, const InOutSpec* specs,
> +          const options& opts, create_new_test new_test)
> +{
> +  size_t num_workers = (opts.parallel
> +                        ? std::min(abigail::workers::get_number_of_threads(),
> +                                   num_tests)
> +                        : 1);
> +  abigail::workers::queue task_queue(num_workers);
> +  bool is_ok = true;
> +
> +  string out_abi_base = string(get_build_dir()) + "/tests/";
> +  string in_elf_base  = string(abigail::tests::get_src_dir()) + "/tests/";
> +  string in_abi_base = in_elf_base;
> +
> +  for (const InOutSpec *s = specs; s->in_elf_path; ++s)
> +    {
> +      test_task_sptr t(new_test(s, out_abi_base,
> +                                in_elf_base,
> +                                in_abi_base));
> +      ABG_ASSERT(task_queue.schedule_task(t));
> +    }
> +
> +  /// Wait for all worker threads to finish their job, and wind down.
> +  task_queue.wait_for_workers_to_complete();
> +
> +  // Now walk the results and print whatever error messages need to be
> +  // printed.
> +
> +  const vector<abigail::workers::task_sptr>& completed_tasks =
> +    task_queue.get_completed_tasks();
> +
> +  ABG_ASSERT(completed_tasks.size() == num_tests);
> +
> +  for (vector<abigail::workers::task_sptr>::const_iterator ti =
> +         completed_tasks.begin();
> +       ti != completed_tasks.end();
> +       ++ti)
> +    {
> +      test_task_sptr t = dynamic_pointer_cast<test_task>(*ti);
> +      if (!t->is_ok)
> +        {
> +          is_ok = false;
> +          if (!t->error_message.empty())
> +            cerr << t->error_message << '\n';
> +        }
> +    }
> +
> +  return !is_ok;
> +}
> +
> +}//end namespace read_common
> +}//end namespace tests
> +}//end namespace abigail
> diff --git a/tests/test-read-common.h b/tests/test-read-common.h
> new file mode 100644
> index 00000000..784f41f5
> --- /dev/null
> +++ b/tests/test-read-common.h
> @@ -0,0 +1,148 @@
> +#ifndef __TEST_READ_COMMON_H__
> +#define __TEST_READ_COMMON_H__
> +
> +#include <string>
> +#include "abg-ir.h"
> +#include "abg-corpus.h"
> +#include "abg-workers.h"
> +#include "abg-writer.h"
> +#include "test-utils.h"
> +#include "abg-tools-utils.h"
> +
> +using std::string;
> +
> +using abigail::xml_writer::type_id_style_kind;
> +using abigail::ir::corpus_sptr;
> +
> +namespace abigail
> +{
> +namespace tests
> +{
> +namespace read_common
> +{
> +
> +/// This is an aggregate that specifies where a test shall get its
> +/// input from, and where it shall write its ouput to.
> +struct InOutSpec
> +{
> +  const char* in_elf_path;
> +  const char* in_suppr_spec_path;
> +  const char* in_public_headers_path;
> +  type_id_style_kind type_id_style;
> +  const char* in_abi_path;
> +  const char* out_abi_path;
> +};// end struct InOutSpec
> +
> +/// The task that peforms the tests.
> +struct test_task : public abigail::workers::task
> +{
> +  bool is_ok;
> +  InOutSpec spec;
> +  string error_message;
> +  string out_abi_base;
> +  string in_elf_base;
> +  string in_abi_base;
> +
> +  string in_elf_path;
> +  string in_abi_path;
> +  string in_suppr_spec_path;
> +  string in_public_headers_path;
> +  string out_abi_path;
> +
> +  void
> +  set_in_elf_path()
> +  {
> +    in_elf_path = in_elf_base + spec.in_elf_path;
> +  }
> +
> +  void
> +  set_in_suppr_spec_path()
> +  {
> +    if (spec.in_suppr_spec_path)
> +      in_suppr_spec_path = in_elf_base + spec.in_suppr_spec_path;
> +    else
> +      in_suppr_spec_path.clear();
> +  }
> +
> +  void
> +  set_in_public_headers_path()
> +  {
> +    if (spec.in_public_headers_path)
> +      in_public_headers_path = spec.in_public_headers_path;
> +    if (!in_public_headers_path.empty())
> +      in_public_headers_path = in_elf_base + spec.in_public_headers_path;
> +  }
> +
> +  bool
> +  set_out_abi_path()
> +  {
> +    out_abi_path = out_abi_base + spec.out_abi_path;
> +    if (!abigail::tools_utils::ensure_parent_dir_created(out_abi_path))
> +      {
> +          error_message =
> +            string("Could not create parent directory for ") + out_abi_path;
> +          return false;
> +      }
> +    return true;
> +  }
> +
> +  void
> +  set_in_abi_path()
> +  {
> +    in_abi_path = in_abi_base + spec.in_abi_path;
> +  }
> +
> +  test_task(const InOutSpec &s,
> +            string& a_out_abi_base,
> +            string& a_in_elf_base,
> +            string& a_in_abi_base);
> +  bool
> +  serialize_corpus(const string& out_abi_path,
> +                   corpus_sptr corp);
> +  bool
> +  run_abidw(const string& extargs = "");
> +
> +  bool
> +  run_diff();
> +
> +  virtual
> +  ~test_task()
> +  {}
> +
> +}; // end struct test_task
> +
> +typedef shared_ptr<test_task> test_task_sptr;
> +
> +struct options
> +{
> +  string        wrong_option;
> +  bool          parallel;
> +
> +  options()
> +    : parallel(true)
> +  {}
> +
> +  ~options()
> +  {
> +  }
> +};
> +
> +void
> +display_usage(const string& prog_name, ostream& out);
> +
> +bool
> +parse_command_line(int argc, char* argv[], options& opts);
> +
> +typedef test_task* (*create_new_test)(const InOutSpec* s,
> +                                      string& a_out_abi_base,
> +                                      string& a_in_elf_base,
> +                                      string& a_in_abi_base);
> +bool
> +run_tests(const size_t num_test, const InOutSpec* specs,
> +          const options& opts, create_new_test new_test);
> +
> +}//end namespace read_common
> +}//end namespace tests
> +}//end namespace abigail
> +
> +#endif //__TEST_READ_COMMON_H__
> diff --git a/tests/test-read-ctf.cc b/tests/test-read-ctf.cc
> new file mode 100644
> index 00000000..e54cc3db
> --- /dev/null
> +++ b/tests/test-read-ctf.cc
> @@ -0,0 +1,290 @@
> +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
> +// -*- Mode: C++ -*-
> +//
> +// Copyright (C) 2021 Oracle, Inc.
> +//
> +// Author: Guillermo E. Martinez
> +
> +/// @file read ELF binaries containing CTF, save them in XML corpus
> +/// files and diff the corpus files against reference XML corpus
> +/// files.
> +
> +#include <cstdlib>
> +#include <fstream>
> +#include <iostream>
> +#include <memory>
> +#include <string>
> +#include <vector>
> +#include "abg-ctf-reader.h"
> +#include "test-read-common.h"
> +
> +using std::string;
> +using std::cerr;
> +
> +using abigail::tests::read_common::InOutSpec;
> +using abigail::tests::read_common::test_task;
> +using abigail::tests::read_common::display_usage;
> +using abigail::tests::read_common::options;
> +
> +using abigail::ctf_reader::read_context_sptr;
> +using abigail::ctf_reader::create_read_context;
> +using abigail::xml_writer::SEQUENCE_TYPE_ID_STYLE;
> +using abigail::xml_writer::HASH_TYPE_ID_STYLE;
> +using abigail::tools_utils::emit_prefix;
> +
> +static InOutSpec in_out_specs[] =
> +{
> +  {
> +    "data/test-read-ctf/test0",
> +    "",
> +    "",
> +    SEQUENCE_TYPE_ID_STYLE,
> +    "data/test-read-ctf/test0.abi",
> +    "output/test-read-ctf/test0.abi"
> +  },
> +  {
> +    "data/test-read-ctf/test0",
> +    "",
> +    "",
> +    HASH_TYPE_ID_STYLE,
> +    "data/test-read-ctf/test0.hash.abi",
> +    "output/test-read-ctf/test0.hash.abi"
> +  },
> +  {
> +    "data/test-read-ctf/test1.so",
> +    "",
> +    "",
> +    SEQUENCE_TYPE_ID_STYLE,
> +    "data/test-read-ctf/test1.so.abi",
> +    "output/test-read-ctf/test1.so.abi"
> +  },
> +  {
> +    "data/test-read-ctf/test1.so",
> +    "",
> +    "",
> +    HASH_TYPE_ID_STYLE,
> +    "data/test-read-ctf/test1.so.hash.abi",
> +    "output/test-read-ctf/test1.so.hash.abi"
> +  },
> +  {
> +    "data/test-read-ctf/test2.so",
> +    "",
> +    "",
> +    SEQUENCE_TYPE_ID_STYLE,
> +    "data/test-read-ctf/test2.so.abi",
> +    "output/test-read-ctf/test2.so.abi"
> +  },
> +  {
> +    "data/test-read-ctf/test2.so",
> +    "",
> +    "",
> +    HASH_TYPE_ID_STYLE,
> +    "data/test-read-ctf/test2.so.hash.abi",
> +    "output/test-read-ctf/test2.so.hash.abi"
> +  },
> +  {
> +    "data/test-read-common/test3.so",
> +    "",
> +    "",
> +    SEQUENCE_TYPE_ID_STYLE,
> +    "data/test-read-common/test3-ctf.so.abi",
> +    "output/test-read-common/test3-ctf.so.abi"
> +  },
> +  {
> +    "data/test-read-common/test3.so",
> +    "",
> +    "",
> +    HASH_TYPE_ID_STYLE,
> +    "data/test-read-common/test3-ctf.so.hash.abi",
> +    "output/test-read-common/test3-ctf.so.hash.abi"
> +  },
> +  {
> +    "data/test-read-ctf/test-enum-many-ctf.o",
> +    "",
> +    "",
> +    HASH_TYPE_ID_STYLE,
> +    "data/test-read-ctf/test-enum-many-ctf.o.hash.abi",
> +    "output/test-read-ctf/test-enum-many-ctf.o.hash.abi"
> +  },
> +  {
> +    "data/test-read-ctf/test-ambiguous-struct-A.o",
> +    "",
> +    "",
> +    HASH_TYPE_ID_STYLE,
> +    "data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi",
> +    "output/test-read-ctf/test-ambiguous-struct-A.o.hash.abi"
> +  },
> +  {
> +    "data/test-read-ctf/test-ambiguous-struct-B.o",
> +    "",
> +    "",
> +    HASH_TYPE_ID_STYLE,
> +    "data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi",
> +    "output/test-read-ctf/test-ambiguous-struct-B.o.hash.abi"
> +  },
> +  {
> +    "data/test-read-ctf/test-conflicting-type-syms-a.o",
> +    "",
> +    "",
> +    HASH_TYPE_ID_STYLE,
> +    "data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi",
> +    "output/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi"
> +  },
> +  {
> +    "data/test-read-ctf/test-conflicting-type-syms-b.o",
> +    "",
> +    "",
> +    HASH_TYPE_ID_STYLE,
> +    "data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi",
> +    "output/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi"
> +  },
> +  {
> +    "data/test-read-common/test4.so",
> +    "",
> +    "",
> +    SEQUENCE_TYPE_ID_STYLE,
> +    "data/test-read-common/test4-ctf.so.abi",
> +    "output/test-read-common/test4-ctf.so.abi"
> +  },
> +  {
> +    "data/test-read-common/test4.so",
> +    "",
> +    "",
> +    HASH_TYPE_ID_STYLE,
> +    "data/test-read-common/test4-ctf.so.hash.abi",
> +    "output/test-read-common/test4-ctf.so.hash.abi"
> +  },
> +  {
> +    "data/test-read-ctf/test-enum-ctf.o",
> +    "",
> +    "",
> +    SEQUENCE_TYPE_ID_STYLE,
> +    "data/test-read-ctf/test-enum-ctf.o.abi",
> +    "output/test-read-ctf/test-enum-ctf.o.abi"
> +  },
> +  {
> +    "data/test-read-ctf/test-enum-symbol-ctf.o",
> +    "",
> +    "",
> +    HASH_TYPE_ID_STYLE,
> +    "data/test-read-ctf/test-enum-symbol-ctf.o.hash.abi",
> +    "output/test-read-ctf/test-enum-symbol-ctf.o.hash.abi"
> +  },
> +  {
> +    "data/test-read-common/PR27700/test-PR27700.o",
> +    "",
> +    "data/test-read-common/PR27700/pub-incdir",
> +    HASH_TYPE_ID_STYLE,
> +    "data/test-read-common/PR27700/test-PR27700-ctf.abi",
> +    "output/test-read-common/PR27700/test-PR27700-ctf.abi",
> +  },
> +  // This should be the last entry.
> +  {NULL, NULL, NULL, SEQUENCE_TYPE_ID_STYLE, NULL, NULL}
> +};
> +
> +/// The task that peforms the tests.
> +struct test_task_ctf : public test_task
> +{
> +  test_task_ctf(const InOutSpec &s,
> +                string& a_out_abi_base,
> +                string& a_in_elf_base,
> +                string& a_in_abi_base);
> +  virtual void
> +  perform();
> +
> +  virtual
> +  ~test_task_ctf()
> +  {}
> +};
> +
> +test_task_ctf::test_task_ctf(const InOutSpec &s,
> +                             string& a_out_abi_base,
> +                             string& a_in_elf_base,
> +                             string& a_in_abi_base)
> +        : test_task(s, a_out_abi_base, a_in_elf_base, a_in_abi_base)
> +  {}
> +
> +/// The actual test.
> +///
> +/// This reads the corpus into memory, saves it to disk, loads it
> +/// again and compares the new in-memory representation against the
> +void
> +test_task_ctf::perform()
> +{
> +  abigail::ir::environment_sptr env;
> +
> +  set_in_elf_path();
> +  set_in_suppr_spec_path();
> +
> +  env.reset(new abigail::ir::environment);
> +  abigail::elf_reader::status status =
> +    abigail::elf_reader::STATUS_UNKNOWN;
> +  ABG_ASSERT(abigail::tools_utils::file_exists(in_elf_path));
> +
> +  read_context_sptr ctxt = create_read_context(in_elf_path,
> +                                               env.get());
> +  ABG_ASSERT(ctxt);
> +
> +  corpus_sptr corp = read_corpus(ctxt.get(), status);
> +  // if there is no output and no input, assume that we do not care about the
> +  // actual read result, just that it succeeded.
> +  if (!spec.in_abi_path && !spec.out_abi_path)
> +    {
> +        // Phew! we made it here and we did not crash! yay!
> +        return;
> +    }
> +  if (!corp)
> +    {
> +        error_message = string("failed to read ") + in_elf_path  + "\n";
> +        is_ok = false;
> +        return;
> +    }
> +  corp->set_path(spec.in_elf_path);
> +  // Do not take architecture names in comparison so that these
> +  // test input binaries can come from whatever arch the
> +  // programmer likes.
> +  corp->set_architecture_name("");
> +
> +  if (!(is_ok = set_out_abi_path()))
> +      return;
> +
> +  if (!(is_ok = serialize_corpus(out_abi_path, corp)))
> +       return;
> +
> +  if (!(is_ok = run_abidw("--ctf ")))
> +    return;
> +
> +  if (!(is_ok = run_diff()))
> +      return;
> +}
> +
> +static test_task*
> +new_task(const InOutSpec* s, string& a_out_abi_base,
> +         string& a_in_elf_base, string& a_in_abi_base)
> +{
> +  return new test_task_ctf(*s, a_in_abi_base,
> +                           a_in_elf_base, a_in_abi_base);
> +}
> +
> +int
> +main(int argc, char *argv[])
> +{
> +  options opts;
> +  if (!parse_command_line(argc, argv, opts))
> +    {
> +      if (!opts.wrong_option.empty())
> +        emit_prefix(argv[0], cerr)
> +          << "unrecognized option: " << opts.wrong_option << "\n";
> +        display_usage(argv[0], cerr);
> +      return 1;
> +    }
> +
> +  /// Create a task queue.  The max number of worker threads of the
> +  /// queue is the number of the concurrent threads supported by the
> +  /// processor of the machine this code runs on.  But if
> +  /// --no-parallel was provided then the number of worker threads
> +  /// equals 1.
> +  const size_t num_tests = sizeof(in_out_specs) / sizeof (InOutSpec) - 1;
> +
> +  return run_tests(num_tests, in_out_specs, opts, new_task);
> +}
> diff --git a/tests/test-read-dwarf.cc b/tests/test-read-dwarf.cc
> index 585aca5e..b84fcaf0 100644
> --- a/tests/test-read-dwarf.cc
> +++ b/tests/test-read-dwarf.cc
> @@ -15,45 +15,27 @@
>  #include <memory>
>  #include <string>
>  #include <vector>
> -#include "abg-ir.h"
> +#include "test-read-common.h"
>  #include "abg-dwarf-reader.h"
> -#include "abg-workers.h"
> -#include "abg-writer.h"
> -#include "abg-tools-utils.h"
> -#include "test-utils.h"
>  
>  using std::vector;
>  using std::string;
> -using std::ofstream;
>  using std::cerr;
> -using std::dynamic_pointer_cast;
> -using abigail::tests::get_build_dir;
> +
> +using abigail::tests::read_common::InOutSpec;
> +using abigail::tests::read_common::test_task;
> +using abigail::tests::read_common::display_usage;
> +using abigail::tests::read_common::options;
> +
>  using abigail::dwarf_reader::read_corpus_from_elf;
>  using abigail::dwarf_reader::read_context;
>  using abigail::dwarf_reader::read_context_sptr;
>  using abigail::dwarf_reader::create_read_context;
>  using abigail::xml_writer::SEQUENCE_TYPE_ID_STYLE;
>  using abigail::xml_writer::HASH_TYPE_ID_STYLE;
> -using abigail::xml_writer::create_write_context;
> -using abigail::xml_writer::set_type_id_style;
> -using abigail::xml_writer::type_id_style_kind;
> -using abigail::xml_writer::write_context_sptr;
> -using abigail::xml_writer::write_corpus;
> -
> -/// This is an aggregate that specifies where a test shall get its
> -/// input from, and where it shall write its ouput to.
> -struct InOutSpec
> -{
> -  const char* in_elf_path;
> -  const char* in_suppr_spec_path;
> -  const char* in_public_headers_path;
> -  type_id_style_kind type_id_style;
> -  const char* in_abi_path;
> -  const char* out_abi_path;
> -};// end struct InOutSpec
> -
> +using abigail::tools_utils::emit_prefix;
>  
> -InOutSpec in_out_specs[] =
> +static InOutSpec in_out_specs[] =
>  {
>    {
>      "data/test-read-dwarf/test0",
> @@ -104,56 +86,56 @@ InOutSpec in_out_specs[] =
>      "output/test-read-dwarf/test2.so.hash.abi"
>    },
>    {
> -    "data/test-read-dwarf/test3.so",
> +    "data/test-read-common/test3.so",
>      "",
>      "",
>      SEQUENCE_TYPE_ID_STYLE,
> -    "data/test-read-dwarf/test3.so.abi",
> -    "output/test-read-dwarf/test3.so.abi"
> +    "data/test-read-common/test3-dwarf.so.abi",
> +    "output/test-read-common/test3-dwarf.so.abi"
>    },
>    {
> -    "data/test-read-dwarf/test3.so",
> +    "data/test-read-common/test3.so",
>      "",
>      "",
>      HASH_TYPE_ID_STYLE,
> -    "data/test-read-dwarf/test3.so.hash.abi",
> -    "output/test-read-dwarf/test3.so.hash.abi"
> +    "data/test-read-common/test3-dwarf.so.hash.abi",
> +    "output/test-read-common/test3-dwarf.so.hash.abi"
>    },
>    // suppress all except the main symbol of a group of aliases
>    {
> -    "data/test-read-dwarf/test3.so",
> -    "data/test-read-dwarf/test3-alias-1.suppr",
> +    "data/test-read-common/test3.so",
> +    "data/test-read-common/test3-alias-1.suppr",
>      "",
>      HASH_TYPE_ID_STYLE,
> -    "data/test-read-dwarf/test3-alias-1.so.hash.abi",
> -    "output/test-read-dwarf/test3-alias-1.so.hash.abi"
> +    "data/test-read-common/test3-alias-1-dwarf.so.hash.abi",
> +    "output/test-read-common/test3-alias-1-dwarf.so.hash.abi"
>    },
>    // suppress the main symbol of a group of aliases
>    {
> -    "data/test-read-dwarf/test3.so",
> -    "data/test-read-dwarf/test3-alias-2.suppr",
> +    "data/test-read-common/test3.so",
> +    "data/test-read-common/test3-alias-2.suppr",
>      "",
>      HASH_TYPE_ID_STYLE,
> -    "data/test-read-dwarf/test3-alias-2.so.hash.abi",
> -    "output/test-read-dwarf/test3-alias-2.so.hash.abi"
> +    "data/test-read-common/test3-alias-2-dwarf.so.hash.abi",
> +    "output/test-read-common/test3-alias-2-dwarf.so.hash.abi"
>    },
>    // suppress all except one non main symbol of a group of aliases
>    {
> -    "data/test-read-dwarf/test3.so",
> -    "data/test-read-dwarf/test3-alias-3.suppr",
> +    "data/test-read-common/test3.so",
> +    "data/test-read-common/test3-alias-3.suppr",
>      "",
>      HASH_TYPE_ID_STYLE,
> -    "data/test-read-dwarf/test3-alias-3.so.hash.abi",
> -    "output/test-read-dwarf/test3-alias-3.so.hash.abi"
> +    "data/test-read-common/test3-alias-3-dwarf.so.hash.abi",
> +    "output/test-read-common/test3-alias-3-dwarf.so.hash.abi"
>    },
>    // suppress all symbols of a group of aliases
>    {
> -    "data/test-read-dwarf/test3.so",
> -    "data/test-read-dwarf/test3-alias-4.suppr",
> +    "data/test-read-common/test3.so",
> +    "data/test-read-common/test3-alias-4.suppr",
>      "",
>      HASH_TYPE_ID_STYLE,
> -    "data/test-read-dwarf/test3-alias-4.so.hash.abi",
> -    "output/test-read-dwarf/test3-alias-4.so.hash.abi"
> +    "data/test-read-common/test3-alias-4-dwarf.so.hash.abi",
> +    "output/test-read-common/test3-alias-4-dwarf.so.hash.abi"
>    },
>    // suppress the main symbols with alias (function+variable) in .o file
>    {
> @@ -165,20 +147,20 @@ InOutSpec in_out_specs[] =
>      "output/test-read-dwarf/test-suppressed-alias.o.abi",
>    },
>    {
> -    "data/test-read-dwarf/test4.so",
> +    "data/test-read-common/test4.so",
>      "",
>      "",
>      SEQUENCE_TYPE_ID_STYLE,
> -    "data/test-read-dwarf/test4.so.abi",
> -    "output/test-read-dwarf/test4.so.abi"
> +    "data/test-read-common/test4-dwarf.so.abi",
> +    "output/test-read-common/test4-dwarf.so.abi"
>    },
>    {
> -    "data/test-read-dwarf/test4.so",
> +    "data/test-read-common/test4.so",
>      "",
>      "",
>      HASH_TYPE_ID_STYLE,
> -    "data/test-read-dwarf/test4.so.hash.abi",
> -    "output/test-read-dwarf/test4.so.hash.abi"
> +    "data/test-read-common/test4-dwarf.so.hash.abi",
> +    "output/test-read-common/test4-dwarf.so.hash.abi"
>    },
>    {
>      "data/test-read-dwarf/test5.o",
> @@ -449,28 +431,28 @@ InOutSpec in_out_specs[] =
>      NULL,
>    },
>    {
> -    "data/test-read-dwarf/PR26261/PR26261-exe",
> +    "data/test-read-common/PR26261/PR26261-exe",
>      "",
>      "",
>      SEQUENCE_TYPE_ID_STYLE,
> -    "data/test-read-dwarf/PR26261/PR26261-exe.abi",
> -    "output/test-read-dwarf/PR26261/PR26261-exe.abi",
> +    "data/test-read-common/PR26261/PR26261-exe-dwarf.abi",
> +    "output/test-read-common/PR26261/PR26261-exe-dwarf.abi",
>    },
>    {
> -    "data/test-read-dwarf/test-PR26568-1.o",
> +    "data/test-read-common/test-PR26568-1.o",
>      "",
>      "",
>      SEQUENCE_TYPE_ID_STYLE,
> -    "data/test-read-dwarf/test-PR26568-1.o.abi",
> -    "output/test-read-dwarf/test-PR26568-1.o.abi",
> +    "data/test-read-common/test-PR26568-1-dwarf.o.abi",
> +    "output/test-read-common/test-PR26568-1-dwarf.o.abi",
>    },
>    {
> -    "data/test-read-dwarf/test-PR26568-2.o",
> +    "data/test-read-common/test-PR26568-2.o",
>      "",
>      "",
>      SEQUENCE_TYPE_ID_STYLE,
> -    "data/test-read-dwarf/test-PR26568-2.o.abi",
> -    "output/test-read-dwarf/test-PR26568-2.o.abi",
> +    "data/test-read-common/test-PR26568-2-dwarf.o.abi",
> +    "output/test-read-common/test-PR26568-2-dwarf.o.abi",
>    },
>    {
>      "data/test-read-dwarf/test-libandroid.so",
> @@ -481,12 +463,12 @@ InOutSpec in_out_specs[] =
>      "output/test-read-dwarf/test-libandroid.so.abi",
>    },
>    {
> -    "data/test-read-dwarf/PR27700/test-PR27700.o",
> +    "data/test-read-common/PR27700/test-PR27700.o",
>      "",
> -    "data/test-read-dwarf/PR27700/pub-incdir",
> +    "data/test-read-common/PR27700/pub-incdir",
>      HASH_TYPE_ID_STYLE,
> -    "data/test-read-dwarf/PR27700/test-PR27700.abi",
> -    "output/test-read-dwarf/PR27700/test-PR27700.abi",
> +    "data/test-read-common/PR27700/test-PR27700-dwarf.abi",
> +    "output/test-read-common/PR27700/test-PR27700-dwarf.abi",
>    },
>    {
>      "data/test-read-dwarf/test-libaaudio.so",
> @@ -553,146 +535,107 @@ set_suppressions_from_headers(read_context& read_ctxt, const string& path)
>  }
>  
>  /// The task that peforms the tests.
> -struct test_task : public abigail::workers::task
> +struct test_task_dwarf : public test_task
>  {
> -  bool is_ok;
> -  InOutSpec spec;
> -  string error_message;
> -  string out_abi_base;
> -  string in_elf_base;
> -  string in_abi_base;
> +  test_task_dwarf(const InOutSpec &s,
> +                string& a_out_abi_base,
> +                string& a_in_elf_base,
> +                string& a_in_abi_base);
> +  virtual void
> +  perform();
>  
> -  test_task(const InOutSpec &s,
> -	    string& a_out_abi_base,
> -	    string& a_in_elf_base,
> -	    string& a_in_abi_base)
> -    : is_ok(true),
> -      spec(s),
> -      out_abi_base(a_out_abi_base),
> -      in_elf_base(a_in_elf_base),
> -      in_abi_base(a_in_abi_base)
> +  virtual
> +  ~test_task_dwarf()
>    {}
> +};
>  
> -  /// The actual test.
> -  ///
> -  /// This reads the corpus into memory, saves it to disk, loads it
> -  /// again and compares the new in-memory representation against the
> -  /// saved one.
> -  virtual void
> -  perform()
> -  {
> -    string in_elf_path, in_abi_path, in_suppr_spec_path, in_public_headers_path,
> -      out_abi_path;
> -    abigail::ir::environment_sptr env;
> +/// The task that peforms the tests.
> +test_task_dwarf::test_task_dwarf(const InOutSpec &s,
> +                             string& a_out_abi_base,
> +                             string& a_in_elf_base,
> +                             string& a_in_abi_base)
> +        : test_task(s, a_out_abi_base, a_in_elf_base, a_in_abi_base)
> +  {}
>  
> -    in_elf_path = in_elf_base + spec.in_elf_path;
> -    if (spec.in_suppr_spec_path)
> -      in_suppr_spec_path = in_elf_base + spec.in_suppr_spec_path;
> -    else
> -      in_suppr_spec_path.clear();
> +void
> +test_task_dwarf::perform()
> +{
> +  abigail::ir::environment_sptr env;
>  
> -    if (spec.in_public_headers_path)
> -      in_public_headers_path = spec.in_public_headers_path;
> -    if (!in_public_headers_path.empty())
> -      in_public_headers_path = in_elf_base + spec.in_public_headers_path;
> +  set_in_elf_path();
> +  set_in_suppr_spec_path();
> +  set_in_public_headers_path();
>  
> -    env.reset(new abigail::ir::environment);
> -    abigail::elf_reader::status status =
> +  env.reset(new abigail::ir::environment);
> +  abigail::elf_reader::status status =
>      abigail::elf_reader::STATUS_UNKNOWN;
> -    vector<char**> di_roots;
> -    ABG_ASSERT(abigail::tools_utils::file_exists(in_elf_path));
> -    read_context_sptr ctxt = create_read_context(in_elf_path,
> -						 di_roots,
> -						 env.get());
> -    ABG_ASSERT(ctxt);
> -    if (!in_suppr_spec_path.empty())
> -      set_suppressions(*ctxt, in_suppr_spec_path);
> -
> -    if (!in_public_headers_path.empty())
> -      set_suppressions_from_headers(*ctxt, in_public_headers_path);
> +  vector<char**> di_roots;
> +  ABG_ASSERT(abigail::tools_utils::file_exists(in_elf_path));
> +  read_context_sptr ctxt = create_read_context(in_elf_path,
> +                                               di_roots,
> +                                               env.get());
> +  ABG_ASSERT(ctxt);
> +  if (!in_suppr_spec_path.empty())
> +    set_suppressions(*ctxt, in_suppr_spec_path);
> +
> +  if (!in_public_headers_path.empty())
> +    set_suppressions_from_headers(*ctxt, in_public_headers_path);
> +
> +  abigail::corpus_sptr corp = read_corpus_from_elf(*ctxt, status);
> +  // if there is no output and no input, assume that we do not care about the
> +  // actual read result, just that it succeeded.
> +  if (!spec.in_abi_path && !spec.out_abi_path)
> +    {
> +      // Phew! we made it here and we did not crash! yay!
> +      return;
> +    }
> +  if (!corp)
> +    {
> +      error_message = string("failed to read ") + in_elf_path  + "\n";
> +      is_ok = false;
> +      return;
> +    }
> +  corp->set_path(spec.in_elf_path);
> +  // Do not take architecture names in comparison so that these
> +  // test input binaries can come from whatever arch the
> +  // programmer likes.
> +  corp->set_architecture_name("");
>  
> -    abigail::corpus_sptr corp = read_corpus_from_elf(*ctxt, status);
> -    // if there is no output and no input, assume that we do not care about the
> -    // actual read result, just that it succeeded.
> -    if (!spec.in_abi_path && !spec.out_abi_path)
> -      {
> -	// Phew! we made it here and we did not crash! yay!
> -	return;
> -      }
> -    if (!corp)
> -      {
> -	error_message = string("failed to read ") + in_elf_path  + "\n";
> -	is_ok = false;
> -	return;
> -      }
> -    corp->set_path(spec.in_elf_path);
> -    // Do not take architecture names in comparison so that these
> -    // test input binaries can come from whatever arch the
> -    // programmer likes.
> -    corp->set_architecture_name("");
> +  if (!(is_ok = set_out_abi_path()))
> +      return;
>  
> -    out_abi_path = out_abi_base + spec.out_abi_path;
> -    if (!abigail::tools_utils::ensure_parent_dir_created(out_abi_path))
> -      {
> -	error_message =
> -	  string("Could not create parent directory for ") + out_abi_path;
> -	is_ok = false;
> -	return;
> -      }
> +  if (!(is_ok = serialize_corpus(out_abi_path, corp)))
> +       return;
>  
> -    ofstream of(out_abi_path.c_str(), std::ios_base::trunc);
> -    if (!of.is_open())
> -      {
> -	error_message = string("failed to read ") + out_abi_path + "\n";
> -	is_ok = false;
> -	return;
> -      }
> -    write_context_sptr write_ctxt
> -	= create_write_context(corp->get_environment(), of);
> -    set_type_id_style(*write_ctxt, spec.type_id_style);
> -    is_ok = write_corpus(*write_ctxt, corp, /*indent=*/0);
> -    of.close();
> +  if (!(is_ok = run_abidw()))
> +    return;
>  
> -    string abidw = string(get_build_dir()) + "/tools/abidw";
> -    string drop_private_types;
> -    if (!in_public_headers_path.empty())
> -      drop_private_types += "--headers-dir " + in_public_headers_path +
> -	" --drop-private-types";
> -    string cmd = abidw + " " + drop_private_types + " --abidiff " + in_elf_path;
> -    if (system(cmd.c_str()))
> -      {
> -	error_message = string("ABIs differ:\n")
> -	  + in_elf_path
> -	  + "\nand:\n"
> -	  + out_abi_path
> -	  + "\n";
> -	is_ok = false;
> -      }
> +  if (!(is_ok = run_diff()))
> +      return;
> +}
>  
> -    in_abi_path = in_abi_base + spec.in_abi_path;
> -    cmd = "diff -u " + in_abi_path + " " + out_abi_path;
> -    if (system(cmd.c_str()))
> -      is_ok = false;
> -  }
> -}; // end struct test_task
>  
> -typedef shared_ptr<test_task> test_task_sptr;
> +static test_task*
> +new_task(const InOutSpec* s, string& a_out_abi_base,
> +         string& a_in_elf_base, string& a_in_abi_base)
> +{
> +  return new test_task_dwarf(*s, a_in_abi_base,
> +                             a_in_elf_base, a_in_abi_base);
> +}
>  
>  int
>  main(int argc, char *argv[])
>  {
>    bool no_parallel = false;
>  
> -  if (argc == 2)
> +  options opts;
> +  if (!parse_command_line(argc, argv, opts))
>      {
> -      if (argv[1] == string("--no-parallel"))
> -	no_parallel = true;
> -      else
> -	{
> -	  cerr << "unrecognized option\n";
> -	  cerr << "usage: " << argv[0] << " [--no-parallel]\n" ;
> -	  return 1;
> -	}
> +      if (!opts.wrong_option.empty())
> +        emit_prefix(argv[0], cerr)
> +          << "unrecognized option: " << opts.wrong_option << "\n";
> +        display_usage(argv[0], cerr);
> +      return 1;
>      }
>  
>    /// Create a task queue.  The max number of worker threads of the
> @@ -701,49 +644,6 @@ main(int argc, char *argv[])
>    /// --no-parallel was provided then the number of worker threads
>    /// equals 1.
>    const size_t num_tests = sizeof(in_out_specs) / sizeof (InOutSpec) - 1;
> -  size_t num_workers = (no_parallel
> -			? 1
> -			: std::min(abigail::workers::get_number_of_threads(),
> -				   num_tests));
> -  abigail::workers::queue task_queue(num_workers);
> -  bool is_ok = true;
> -
> -  string out_abi_base = string(get_build_dir()) + "/tests/";
> -  string in_elf_base  = string(abigail::tests::get_src_dir()) + "/tests/";
> -  string in_abi_base = in_elf_base;
> -
> -  for (InOutSpec *s = in_out_specs; s->in_elf_path; ++s)
> -    {
> -      test_task_sptr t(new test_task(*s, out_abi_base,
> -				     in_elf_base,
> -				     in_abi_base));
> -      ABG_ASSERT(task_queue.schedule_task(t));
> -    }
> -
> -  /// Wait for all worker threads to finish their job, and wind down.
> -  task_queue.wait_for_workers_to_complete();
> -
> -  // Now walk the results and print whatever error messages need to be
> -  // printed.
> -
> -  const vector<abigail::workers::task_sptr>& completed_tasks =
> -    task_queue.get_completed_tasks();
> -
> -  ABG_ASSERT(completed_tasks.size() == num_tests);
> -
> -  for (vector<abigail::workers::task_sptr>::const_iterator ti =
> -	 completed_tasks.begin();
> -       ti != completed_tasks.end();
> -       ++ti)
> -    {
> -      test_task_sptr t = dynamic_pointer_cast<test_task>(*ti);
> -      if (!t->is_ok)
> -	{
> -	  is_ok = false;
> -	  if (!t->error_message.empty())
> -	    cerr << t->error_message << '\n';
> -	}
> -    }
>  
> -  return !is_ok;
> +  return run_tests(num_tests, in_out_specs, opts, new_task);
>  }
  
Guillermo E. Martinez Nov. 23, 2021, 6:54 p.m. UTC | #2
On Tuesday, November 23, 2021 9:48:35 AM CST Jose E. Marchesi wrote:

Hello Jose/everybody

Thanks for your comments!, answers below:

The following items summarise steps currently implemented in
the testsuite for DWARF and CTF readers:

1) Create corpus using the ELF input file, e.g:
      *src*/libabigail/tests/data/test-read-ctf/test0
     - In this step the SUTs are: *the front-end and readers*.

2) Serialize the corpus object to XML ABI description in output
    directory:
     *build*/libabigail_x86_64/tests/output/test-read-ctf/test0.abi
     - SUT: *writter* using write_corpus function (it doesn't
     use libxml (IMHO something to change if we want to use in the
     future properties, name space, etc).

3) Spawn *abidw* tool with ELF input file using --abidiff argument, e.g:
     abidw --abidiff  --ctf *src*/libabigail/tests/data/test-read-ctf/test0

    Internally abiw works as follow:
     
   3.1) Create corpus from ELF input file, e.g:
            *src*/libabigail/tests/data/test-read-ctf/test0
    - In this step SUTs: *DWARF/CTF frond-end readers*

   3.2) Serialize the (*first*) corpus object to XML ABI description in 
          *temp* directory:
             /tmp/libbigail-xyz
    - SUTs: ABI writter,

   3.3) Build a (*second*) corpus from this temporary file (*same file!*):
        - SUTs: *XML reader*.

   3.4) Compute the corpus differences
              compute_diff(corp, corp2 ..)
     - SUTs: *comparison algorithm* (diff_context/corpus diff)

       if there are differences return 1 otherwise return 0.

4) The return value is read by test-read-ctf and if it's 1 test
    is marked as *FAILED*

5) Use a external *diff command* to compare the XML abi input file with
    the file outputted in the step 2. The return code of the diff command
    is used to mark the test as SUCCESS or FAILED

So, the abidw doesn't use the expected XML file used in the testsuite, so
if there are changes on the input ELF or in the libabigail subsystems (readers,
writer, corpus, etc) we could get false negatives, because it is working with
itself result as an incoming file, instead of use an expected file.

I think that we should use the ABI XML reader from the expected file (e.g:
tests/data/test-read-ctf/test0.abi) to build the corpus to be compared
with the corpus built with ELF input file (e.g: tests/data/test-read-ctf/test0)
and in this way replace the external abidw and diff command calls, this also
helps to avoid false positives when XML ABIs files has the same nodes but not
in the same order.

What do you think?

So, my answer below: 

> I have a couple of general comments/questions regarding libabigail
> testing and DWARF/CTF.
> 
> 1) The usage of diff in the testsuite puzzles me.  I would have expected
>    to find at least two kinds of tests in the testsuite:
> 
>    a) Tests testing the frontend/readers, which can assume the XML
>       reader and comparison algorithm works properly.
       Done in steps 1, 3.1.

>    b) Tests testing the comparison algorithm, which can assume the
>       frontend/readers work properly.
       Done by abidw in step: 3.4  
> 
>    This way no external comparison (like diffing) would be necessary.
>    Is this not the case?
       Yes, agree.
> 
> 2) I am surprised by the fact the CTF reader seems to be working as good
>    as the DWARF reader re. the testsuite.  Not buying it.  I think that
>    the testsuite skips .cc tests when testing CTF support.
       Correct, cc files are skipped, just I collected the C test used in dwarf test reader,
       and the test used by libctf, validating the expected result, so the functionality
       tested in libctf is also tested in libabigail. (except aliases symbols).

>    So I wonder... to what extent are C features (not C++) tested using
>    .cc files?  If we want good coverage for both DWARF and CTF (and
>    eventually BTF or other formats not supporting C++) then we would
>    need to turn these .cc files into .c files...
      sure, I can "translate" C++ test's data and add it to CTF testsuite.
> 
> > Hello libabigail team,
> >
> > This patch includes regression tests v2 for CTF.
> >
> > The change from v1 is disable CTF test alias, because
> > currently is is not supported.
> >
> > Dependencies/limitations:
> >
> > * It was worked on the top of the following patches:
> >  https://sourceware.org/pipermail/libabigail/2021q4/003853.html
> >
> > * Some CTF tests were *disabled* because it generates the XML ABI
> > corpus with *same information* but the XML nodes *are not* always
> > in the *same order*, so using diff command fails. Details here:
> > https://sourceware.org/pipermail/libabigail/2021q4/003824.html
> >
[...]

Sincerely,
Guillermo
  
Dodji Seketeli Nov. 24, 2021, 4:36 p.m. UTC | #3
Hello,

[...]

Thanks for working on this.  Nice patch, by the way!  I like its
direction.

I have a few comments and I believe that when they are addressed, we'll
be able to apply the patch.

[...]

> Dependencies/limitations:
> 
> * It was worked on the top of the following patches:
>  https://sourceware.org/pipermail/libabigail/2021q4/003853.html
> 
> * Some CTF tests were *disabled* because it generates the XML ABI
> corpus with *same information* but the XML nodes *are not* always
> in the *same order*, so using diff command fails. Details here:
> https://sourceware.org/pipermail/libabigail/2021q4/003824.html

In those cases where the abixml file generated from CTF is different
from the one generated from DWARF, I think we should have two
different reference abixml files to diff against.  No CTF test should
be disabled, I think.

So:

This:

   {
     "data/test-read-dwarf/test0",
     "",
     "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test0.abi",
     "output/test-read-dwarf/test0.abi"
   },

would be changed into:

   {
     "data/test-read-common/test0",
     "",
     "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-dwarf/test0.abi",
     "output/test-read-dwarf/test0.abi"
   },

For the DWARF test entry in test-read-dwarf.cc, and it would be
changed into:

   {
     "data/test-read-common/test0",
     "",
     "",
     SEQUENCE_TYPE_ID_STYLE,
     "data/test-read-ctf/test0.abi",
     "output/test-read-ctf/test0.abi"
   },

for the CTF test netry in test-read-ctf.cc.

By the way, I am seeing entries like this in test-read-ctf.cc:

> +    "data/test-read-common/test3.so",
> +    "",
> +    "",
> +    SEQUENCE_TYPE_ID_STYLE,
> +    "data/test-read-common/test3-ctf.so.abi",
> +    "output/test-read-common/test3-ctf.so.abi"

Here this entry does exactly what I am suggesting, even if
test3-ctf.so.abi is stored in data/test-read-common.

So where exactly is the CTF test disabled?

[...]


> diff --git a/tests/test-read-common.cc b/tests/test-read-common.cc

[...]

> +
> +namespace abigail
> +{
> +namespace tests
> +{
> +namespace read_common
> +{

Because this file now contains an API definition that is to be used be
some tests, every single function of the file should be documented
using doxygen comments, just like we have in src/abg-*.cc files.

For instance:

> +
> +test_task::test_task(const InOutSpec &s,
> +                     string& a_out_abi_base,
> +                     string& a_in_elf_base,
> +                     string& a_in_abi_base)

This function should be fully doxygen-documented.

> +    : is_ok(true),
> +      spec(s),
> +      out_abi_base(a_out_abi_base),
> +      in_elf_base(a_in_elf_base),
> +      in_abi_base(a_in_abi_base)
> +  {}
> +
> +bool
> +test_task::serialize_corpus(const string& out_abi_path,
> +                            corpus_sptr corp)

Likewise.

> +{
> +  ofstream of(out_abi_path.c_str(), std::ios_base::trunc);
> +  if (!of.is_open())
> +    {
> +       error_message = string("failed to read ") + out_abi_path + "\n";
> +       return false;
> +    }
> +
> +  write_context_sptr write_ctxt
> +      = create_write_context(corp->get_environment(), of);
> +  set_type_id_style(*write_ctxt, spec.type_id_style);
> +  is_ok = write_corpus(*write_ctxt, corp, /*indent=*/0);
> +  of.close();
> +
> +  return true;
> +}
> +
> +bool
> +test_task::run_abidw(const string& extargs)

Likewise.

> +{
> +  string abidw = string(get_build_dir()) + "/tools/abidw";
> +  string drop_private_types;
> +  if (!in_public_headers_path.empty())
> +    drop_private_types += "--headers-dir " + in_public_headers_path +
> +      " --drop-private-types";
> +  string cmd = abidw + " " + drop_private_types + " --abidiff " + extargs +
> +   in_elf_path;
> +  if (system(cmd.c_str()))
> +    {
> +      error_message = string("ABIs differ:\n")
> +        + in_elf_path
> +        + "\nand:\n"
> +        + out_abi_path
> +        + "\n";
> +
> +      return false;
> +    }
> +
> +  return true;
> +}
> +
> +bool
> +test_task::run_diff()

Likewise.

> +{
> +  set_in_abi_path();
> +  string cmd = "diff -u " + in_abi_path + " " + out_abi_path;
> +  if (system(cmd.c_str()))
> +    {
> +      error_message = string("ABIs differ:\n")
> +        + in_abi_path
> +        + "\nand:\n"
> +        + out_abi_path
> +        + "\n";
> +
> +      return false;
> +    }
> +
> +  return true;
> +}
> +
> +void
> +display_usage(const string& prog_name, ostream& out)

Likewise.

> +{
> +  emit_prefix(prog_name, out)
> +    << "usage: " << prog_name << " [options]\n"
> +    << " where options can be: \n"
> +    << "  --help|-h  display this message\n"
> +    << "  --no-parallel execute testsuite is a sigle thread\n"
> +  ;
> +}
> +
> +bool
> +parse_command_line(int argc, char* argv[], options& opts)

Likewise.

> +{
> +  for (int i = 1; i < argc; ++i)
> +    {
> +      if (!strcmp(argv[i], "--no-parallel"))
> +        opts.parallel = false;
> +      else if (!strcmp(argv[i], "--help")
> +               || !strcmp(argv[i], "--h"))
> +        return false;
> +      else
> +        {
> +          if (strlen(argv[i]) >= 2 && argv[i][0] == '-' && argv[i][1] == '-')
> +            opts.wrong_option = argv[i];
> +          return false;
> +        }
> +    }
> +
> +  return true;
> +}
> +
> +bool
> +run_tests(const size_t num_tests, const InOutSpec* specs,
> +          const options& opts, create_new_test new_test)

Likewise.

> +{

[...]


> diff --git a/tests/test-read-common.h b/tests/test-read-common.h

[...]

> +/// This is an aggregate that specifies where a test shall get its
> +/// input from, and where it shall write its ouput to.
> +struct InOutSpec
> +{
> +  const char* in_elf_path;
> +  const char* in_suppr_spec_path;
> +  const char* in_public_headers_path;
> +  type_id_style_kind type_id_style;
> +  const char* in_abi_path;
> +  const char* out_abi_path;
> +};// end struct InOutSpec
> +
> +/// The task that peforms the tests.
> +struct test_task : public abigail::workers::task
> +{
> +  bool is_ok;
> +  InOutSpec spec;
> +  string error_message;
> +  string out_abi_base;
> +  string in_elf_base;
> +  string in_abi_base;
> +
> +  string in_elf_path;
> +  string in_abi_path;
> +  string in_suppr_spec_path;
> +  string in_public_headers_path;
> +  string out_abi_path;
> +
> +  void
> +  set_in_elf_path()

Please doxygen-document this function.

> +  {
> +    in_elf_path = in_elf_base + spec.in_elf_path;
> +  }
> +
> +  void
> +  set_in_suppr_spec_path()

Likewise.

> +  {
> +    if (spec.in_suppr_spec_path)
> +      in_suppr_spec_path = in_elf_base + spec.in_suppr_spec_path;
> +    else
> +      in_suppr_spec_path.clear();
> +  }
> +
> +  void
> +  set_in_public_headers_path()

Likewise.

> +  {
> +    if (spec.in_public_headers_path)
> +      in_public_headers_path = spec.in_public_headers_path;
> +    if (!in_public_headers_path.empty())
> +      in_public_headers_path = in_elf_base + spec.in_public_headers_path;
> +  }
> +
> +  bool
> +  set_out_abi_path()

Likewise.

> +  {
> +    out_abi_path = out_abi_base + spec.out_abi_path;
> +    if (!abigail::tools_utils::ensure_parent_dir_created(out_abi_path))
> +      {
> +          error_message =
> +            string("Could not create parent directory for ") + out_abi_path;
> +          return false;
> +      }
> +    return true;
> +  }
> +
> +  void
> +  set_in_abi_path()

Likewise.

> +  {
> +    in_abi_path = in_abi_base + spec.in_abi_path;
> +  }
> +

[...]

> +  test_task(const InOutSpec &s,
> +            string& a_out_abi_base,
> +            string& a_in_elf_base,
> +            string& a_in_abi_base);
> +  bool
> +  serialize_corpus(const string& out_abi_path,
> +                   corpus_sptr corp);
> +  bool
> +  run_abidw(const string& extargs = "");
> +
> +  bool
> +  run_diff();
> +
> +  virtual
> +  ~test_task()
> +  {}
> +
> +}; // end struct test_task
> +
> +typedef shared_ptr<test_task> test_task_sptr;
> +
> +struct options
> +{

Please doxygen-document this struct.

> +  string        wrong_option;
> +  bool          parallel;
> +
> +  options()
> +    : parallel(true)
> +  {}
> +
> +  ~options()
> +  {
> +  }
> +};

[...]

> diff --git a/tests/test-read-ctf.cc b/tests/test-read-ctf.cc

[...]


> +test_task_ctf::test_task_ctf(const InOutSpec &s,
> +                             string& a_out_abi_base,
> +                             string& a_in_elf_base,
> +                             string& a_in_abi_base)

Please doxygen-document this function.

> +        : test_task(s, a_out_abi_base, a_in_elf_base, a_in_abi_base)
> +  {}
> +

[...]

> +static test_task*
> +new_task(const InOutSpec* s, string& a_out_abi_base,
> +         string& a_in_elf_base, string& a_in_abi_base)

Please doxygen-document this function.

> +{
> +  return new test_task_ctf(*s, a_in_abi_base,

This 'a_in_abi_base' should be a_out_abi_base.

> +                           a_in_elf_base, a_in_abi_base);
> +}

[...]


> diff --git a/tests/test-read-dwarf.cc b/tests/test-read-dwarf.cc

[...]


> +static test_task*
> +new_task(const InOutSpec* s, string& a_out_abi_base,
> +         string& a_in_elf_base, string& a_in_abi_base)

Please doxygen-document this function.

> +{
> +  return new test_task_dwarf(*s, a_in_abi_base,

This 'a_in_abi_base' should be a_out_abi_base.

> +                             a_in_elf_base, a_in_abi_base);
> +}
>  
>  int
>  main(int argc, char *argv[])
>  {
>    bool no_parallel = false;

This variable is not unused.


Thanks for working on this.  It's really appreciated!

[...]

Cheers,
  
Guillermo E. Martinez Nov. 24, 2021, 6:52 p.m. UTC | #4
Hello Dodji,

Thanks for your comments!!

> On Wednesday, November 24, 2021 10:36:02 AM CST Dodji Seketeli wrote:
> Hello,
> 
> [...]
> 
> Thanks for working on this.  Nice patch, by the way!  I like its
> direction.
good to know it :-)
 
> I have a few comments and I believe that when they are addressed, we'll
> be able to apply the patch.
> 
> [...]
> 
> > Dependencies/limitations:
> > 
> > * It was worked on the top of the following patches:
> >  https://sourceware.org/pipermail/libabigail/2021q4/003853.html
> > 
> > * Some CTF tests were *disabled* because it generates the XML ABI
> > corpus with *same information* but the XML nodes *are not* always
> > in the *same order*, so using diff command fails. Details here:
> > https://sourceware.org/pipermail/libabigail/2021q4/003824.html
> 
> In those cases where the abixml file generated from CTF is different
> from the one generated from DWARF, I think we should have two
> different reference abixml files to diff against.  No CTF test should
> be disabled, I think.
> 
> So:
> 
> This:
> 
>    {
>      "data/test-read-dwarf/test0",
>      "",
>      "",
>      SEQUENCE_TYPE_ID_STYLE,
>      "data/test-read-dwarf/test0.abi",
>      "output/test-read-dwarf/test0.abi"
>    },
> 
> would be changed into:
> 
>    {
>      "data/test-read-common/test0",
>      "",
>      "",
>      SEQUENCE_TYPE_ID_STYLE,
>      "data/test-read-dwarf/test0.abi",
>      "output/test-read-dwarf/test0.abi"
>    },
> 
> For the DWARF test entry in test-read-dwarf.cc, and it would be
> changed into:
> 
>    {
>      "data/test-read-common/test0",
>      "",
>      "",
>      SEQUENCE_TYPE_ID_STYLE,
>      "data/test-read-ctf/test0.abi",
>      "output/test-read-ctf/test0.abi"
>    },
> 
> for the CTF test netry in test-read-ctf.cc.
> 
> By the way, I am seeing entries like this in test-read-ctf.cc:
> 
> > +    "data/test-read-common/test3.so",
> > +    "",
> > +    "",
> > +    SEQUENCE_TYPE_ID_STYLE,
> > +    "data/test-read-common/test3-ctf.so.abi",
> > +    "output/test-read-common/test3-ctf.so.abi"
> 
> Here this entry does exactly what I am suggesting, even if
> test3-ctf.so.abi is stored in data/test-read-common.
perfect, then I'll move the expected abixml file to accurate directory
and I'll remove the suffix depending of which reader we are testing,
instead of store it in common directory.
> So where exactly is the CTF test disabled?
I remove those test entries, so the possible problem detected using external diff
command in CTF is, for instance, in: test-read-common/test-PR26568-1-ctf.o.abi,
the first time that runtestreadctf is executed an abixml file  is generated:

...
    <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
      <data-member access='public' layout-offset-in-bits='0'>
        <var-decl name='x' type-id='type-id-4' visibility='default'/>
      </data-member>
    </class-decl>
    <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-5'>
      <data-member access='public' layout-offset-in-bits='0'>
        <var-decl name='y' type-id='type-id-6' visibility='default'/>
      </data-member>
    </class-decl>

and this is second execution:
...
    <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-5'>
      <data-member access='public' layout-offset-in-bits='0'>
        <var-decl name='y' type-id='type-id-6' visibility='default'/>
      </data-member>
    </class-decl>
    <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
      <data-member access='public' layout-offset-in-bits='0'>
        <var-decl name='x' type-id='type-id-4' visibility='default'/>
      </data-member>
    </class-decl>

As we can see both abixml files  have *same nodes information* but the nodes
are in a different order, so the test should be marked as passed, however using
the external diff command the test fails. so my question is should we rely in diff
command to compare the corpus of the ELF input files (abixml files)?

https://sourceware.org/pipermail/libabigail/2021q4/003885.html

> [...]
> 
> 
> > diff --git a/tests/test-read-common.cc b/tests/test-read-common.cc
> 
> [...]
> 
> > +
> > +namespace abigail
> > +{
> > +namespace tests
> > +{
> > +namespace read_common
> > +{
> 
> Because this file now contains an API definition that is to be used be
> some tests, every single function of the file should be documented
> using doxygen comments, just like we have in src/abg-*.cc files.
Ok, will wok on in in the next patch version.
> For instance:
> 
> > +
> > +test_task::test_task(const InOutSpec &s,
> > +                     string& a_out_abi_base,
> > +                     string& a_in_elf_base,
> > +                     string& a_in_abi_base)
> 
> This function should be fully doxygen-documented.
> 
> > +    : is_ok(true),
> > +      spec(s),
> > +      out_abi_base(a_out_abi_base),
> > +      in_elf_base(a_in_elf_base),
> > +      in_abi_base(a_in_abi_base)
> > +  {}
> > +
> > +bool
> > +test_task::serialize_corpus(const string& out_abi_path,
> > +                            corpus_sptr corp)
> 
> Likewise.
Ok,
> > +{
> > +  ofstream of(out_abi_path.c_str(), std::ios_base::trunc);
> > +  if (!of.is_open())
> > +    {
> > +       error_message = string("failed to read ") + out_abi_path + "\n";
> > +       return false;
> > +    }
> > +
> > +  write_context_sptr write_ctxt
> > +      = create_write_context(corp->get_environment(), of);
> > +  set_type_id_style(*write_ctxt, spec.type_id_style);
> > +  is_ok = write_corpus(*write_ctxt, corp, /*indent=*/0);
> > +  of.close();
> > +
> > +  return true;
> > +}
> > +
> > +bool
> > +test_task::run_abidw(const string& extargs)
> 
> Likewise.
Ok, 
> > +{
> > +  string abidw = string(get_build_dir()) + "/tools/abidw";
> > +  string drop_private_types;
> > +  if (!in_public_headers_path.empty())
> > +    drop_private_types += "--headers-dir " + in_public_headers_path +
> > +      " --drop-private-types";
> > +  string cmd = abidw + " " + drop_private_types + " --abidiff " + extargs +
> > +   in_elf_path;
> > +  if (system(cmd.c_str()))
> > +    {
> > +      error_message = string("ABIs differ:\n")
> > +        + in_elf_path
> > +        + "\nand:\n"
> > +        + out_abi_path
> > +        + "\n";
> > +
> > +      return false;
> > +    }
> > +
> > +  return true;
> > +}
> > +
> > +bool
> > +test_task::run_diff()
> 
> Likewise.
Ok,
> > +{
> > +  set_in_abi_path();
> > +  string cmd = "diff -u " + in_abi_path + " " + out_abi_path;
> > +  if (system(cmd.c_str()))
> > +    {
> > +      error_message = string("ABIs differ:\n")
> > +        + in_abi_path
> > +        + "\nand:\n"
> > +        + out_abi_path
> > +        + "\n";
> > +
> > +      return false;
> > +    }
> > +
> > +  return true;
> > +}
> > +
> > +void
> > +display_usage(const string& prog_name, ostream& out)
> 
> Likewise.
Ok,
> > +{
> > +  emit_prefix(prog_name, out)
> > +    << "usage: " << prog_name << " [options]\n"
> > +    << " where options can be: \n"
> > +    << "  --help|-h  display this message\n"
> > +    << "  --no-parallel execute testsuite is a sigle thread\n"
> > +  ;
> > +}
> > +
> > +bool
> > +parse_command_line(int argc, char* argv[], options& opts)
> 
> Likewise.
Ok,
> > +{
> > +  for (int i = 1; i < argc; ++i)
> > +    {
> > +      if (!strcmp(argv[i], "--no-parallel"))
> > +        opts.parallel = false;
> > +      else if (!strcmp(argv[i], "--help")
> > +               || !strcmp(argv[i], "--h"))
> > +        return false;
> > +      else
> > +        {
> > +          if (strlen(argv[i]) >= 2 && argv[i][0] == '-' && argv[i][1] == '-')
> > +            opts.wrong_option = argv[i];
> > +          return false;
> > +        }
> > +    }
> > +
> > +  return true;
> > +}
> > +
> > +bool
> > +run_tests(const size_t num_tests, const InOutSpec* specs,
> > +          const options& opts, create_new_test new_test)
> 
> Likewise.
Ok,
> > +{
> 
> [...]
> 
> 
> > diff --git a/tests/test-read-common.h b/tests/test-read-common.h
> 
> [...]
> 
> > +/// This is an aggregate that specifies where a test shall get its
> > +/// input from, and where it shall write its ouput to.
> > +struct InOutSpec
> > +{
> > +  const char* in_elf_path;
> > +  const char* in_suppr_spec_path;
> > +  const char* in_public_headers_path;
> > +  type_id_style_kind type_id_style;
> > +  const char* in_abi_path;
> > +  const char* out_abi_path;
> > +};// end struct InOutSpec
> > +
> > +/// The task that peforms the tests.
> > +struct test_task : public abigail::workers::task
> > +{
> > +  bool is_ok;
> > +  InOutSpec spec;
> > +  string error_message;
> > +  string out_abi_base;
> > +  string in_elf_base;
> > +  string in_abi_base;
> > +
> > +  string in_elf_path;
> > +  string in_abi_path;
> > +  string in_suppr_spec_path;
> > +  string in_public_headers_path;
> > +  string out_abi_path;
> > +
> > +  void
> > +  set_in_elf_path()
> 
> Please doxygen-document this function.
> 
> > +  {
> > +    in_elf_path = in_elf_base + spec.in_elf_path;
> > +  }
> > +
> > +  void
> > +  set_in_suppr_spec_path()
> 
> Likewise.
Ok,
> > +  {
> > +    if (spec.in_suppr_spec_path)
> > +      in_suppr_spec_path = in_elf_base + spec.in_suppr_spec_path;
> > +    else
> > +      in_suppr_spec_path.clear();
> > +  }
> > +
> > +  void
> > +  set_in_public_headers_path()
> 
> Likewise.
Ok, 
> > +  {
> > +    if (spec.in_public_headers_path)
> > +      in_public_headers_path = spec.in_public_headers_path;
> > +    if (!in_public_headers_path.empty())
> > +      in_public_headers_path = in_elf_base + spec.in_public_headers_path;
> > +  }
> > +
> > +  bool
> > +  set_out_abi_path()
> 
> Likewise.
Ok, 
> > +  {
> > +    out_abi_path = out_abi_base + spec.out_abi_path;
> > +    if (!abigail::tools_utils::ensure_parent_dir_created(out_abi_path))
> > +      {
> > +          error_message =
> > +            string("Could not create parent directory for ") + out_abi_path;
> > +          return false;
> > +      }
> > +    return true;
> > +  }
> > +
> > +  void
> > +  set_in_abi_path()
> 
> Likewise.
Ok,
> > +  {
> > +    in_abi_path = in_abi_base + spec.in_abi_path;
> > +  }
> > +
> 
> [...]
> 
> > +  test_task(const InOutSpec &s,
> > +            string& a_out_abi_base,
> > +            string& a_in_elf_base,
> > +            string& a_in_abi_base);
> > +  bool
> > +  serialize_corpus(const string& out_abi_path,
> > +                   corpus_sptr corp);
> > +  bool
> > +  run_abidw(const string& extargs = "");
> > +
> > +  bool
> > +  run_diff();
> > +
> > +  virtual
> > +  ~test_task()
> > +  {}
> > +
> > +}; // end struct test_task
> > +
> > +typedef shared_ptr<test_task> test_task_sptr;
> > +
> > +struct options
> > +{
> 
> Please doxygen-document this struct.
Ok,
> > +  string        wrong_option;
> > +  bool          parallel;
> > +
> > +  options()
> > +    : parallel(true)
> > +  {}
> > +
> > +  ~options()
> > +  {
> > +  }
> > +};
> 
> [...]
> 
> > diff --git a/tests/test-read-ctf.cc b/tests/test-read-ctf.cc
> 
> [...]
> 
> 
> > +test_task_ctf::test_task_ctf(const InOutSpec &s,
> > +                             string& a_out_abi_base,
> > +                             string& a_in_elf_base,
> > +                             string& a_in_abi_base)
> 
> Please doxygen-document this function.
Ok,
> > +        : test_task(s, a_out_abi_base, a_in_elf_base, a_in_abi_base)
> > +  {}
> > +
> 
> [...]
> 
> > +static test_task*
> > +new_task(const InOutSpec* s, string& a_out_abi_base,
> > +         string& a_in_elf_base, string& a_in_abi_base)
> 
> Please doxygen-document this function.
Ok,
> > +{
> > +  return new test_task_ctf(*s, a_in_abi_base,
>
> This 'a_in_abi_base' should be a_out_abi_base.
Ok, sorry .. thanks! .. will be fixed in the next patch.
> > +                           a_in_elf_base, a_in_abi_base);
> > +}
> 
> [...]
> 
> 
> > diff --git a/tests/test-read-dwarf.cc b/tests/test-read-dwarf.cc
> 
> [...]
> 
> 
> > +static test_task*
> > +new_task(const InOutSpec* s, string& a_out_abi_base,
> > +         string& a_in_elf_base, string& a_in_abi_base)
> 
> Please doxygen-document this function.
Ok,
> > +{
> > +  return new test_task_dwarf(*s, a_in_abi_base,
> 
> This 'a_in_abi_base' should be a_out_abi_base.
agree, it will be fixed in the next patch.
> > +                             a_in_elf_base, a_in_abi_base);
> > +}
> >  
> >  int
> >  main(int argc, char *argv[])
> >  {
> >    bool no_parallel = false;
will be removed in the next patch.
> This variable is not unused.
> 
> 
> Thanks for working on this.  It's really appreciated!
> 
> [...]
> 
> Cheers,
Thanks again,
Guillermo
  
Ben Woodard Nov. 24, 2021, 7:09 p.m. UTC | #5
> On Nov 24, 2021, at 8:36 AM, Dodji Seketeli <dodji@seketeli.org> wrote:
> 
> Hello,
> 
> [...]
> 
> Thanks for working on this.  Nice patch, by the way!  I like its
> direction.
> 
> I have a few comments and I believe that when they are addressed, we'll
> be able to apply the patch.
> 
> [...]
> 
>> Dependencies/limitations:
>> 
>> * It was worked on the top of the following patches:
>> https://sourceware.org/pipermail/libabigail/2021q4/003853.html
>> 
>> * Some CTF tests were *disabled* because it generates the XML ABI
>> corpus with *same information* but the XML nodes *are not* always
>> in the *same order*, so using diff command fails. Details here:
>> https://sourceware.org/pipermail/libabigail/2021q4/003824.html
> 
> In those cases where the abixml file generated from CTF is different
> from the one generated from DWARF, I think we should have two
> different reference abixml files to diff against.  No CTF test should
> be disabled, I think.

Here is a somewhat deeper question that I think needs to be considered. I’ve generally referred to it as “DWARF Idioms” but this email makes me think that it is even larger than that. 

For my work, I need libabigail to generate an abstract notion of the ABI corpus. How it constructs that abstract notion of the ABI needs to be independent of the producer. Think of it this way, say we take the same compiler and have it compile the same library producing both CTF and DWARF, the ABI of the library doesn’t change. Since it is literally the same object, the program text is same. Therefore the ABI is unquestionably the the same. Any difference reported by libabigail therefore is a problem with libabigail. It is not taking the source material and abstracting it enough into the ABI artifacts to separate the artifacts from the implementation. 

So I kind of believe that we need to look more deeply into WHY the CTF and DWARF are not comparing as equivalent and begin the process of filing the compiler bugs when we need to, and doing what is necessary to abstract the ABI from the source material that libabigail used to construct its IR of the ABI corpus from.

So, I must say that I disagree with both dodji’s approach here and to a lesser extent Guillermo’s approach of disabling the tests. I think that the tests where the CTF doesn’t match the DWARF should be investigated and when necessary marked “xfail” with a note citing their individual cause. 

I think that what we need to work towards is:
abidw produces the same output (or more precisely libabigail produces the same IR) whether you compile with -gdwarf-3 -gdwarf-4 -gdwarf-5 -gsplit-dwarf -gctf
also for the most part the ABI should not change between compiler versions. There may be a few cases that we need to look into where the compiler actually breaks ABI and of course libabigail should flag those but I would assert that libabigail needs to abstract its IR of the ABI enough that compiler version changes that don’t actually change the ABI of the ELF object are not reported as ABI breaks. It currently does pretty well at this at the moment.
Then once that foundation is built, being able to abstract the ABI IR enough that differences in toolchains e.g. LLVM vs GCC are not flagged as changes in the object’s ABI. This is important to provide people with a tool that will allow them to mix toolchains within a project to achieve optimal code.

-ben

> 
> So:
> 
> This:
> 
>   {
>     "data/test-read-dwarf/test0",
>     "",
>     "",
>     SEQUENCE_TYPE_ID_STYLE,
>     "data/test-read-dwarf/test0.abi",
>     "output/test-read-dwarf/test0.abi"
>   },
> 
> would be changed into:
> 
>   {
>     "data/test-read-common/test0",
>     "",
>     "",
>     SEQUENCE_TYPE_ID_STYLE,
>     "data/test-read-dwarf/test0.abi",
>     "output/test-read-dwarf/test0.abi"
>   },
> 
> For the DWARF test entry in test-read-dwarf.cc, and it would be
> changed into:
> 
>   {
>     "data/test-read-common/test0",
>     "",
>     "",
>     SEQUENCE_TYPE_ID_STYLE,
>     "data/test-read-ctf/test0.abi",
>     "output/test-read-ctf/test0.abi"
>   },
> 
> for the CTF test netry in test-read-ctf.cc.
> 
> By the way, I am seeing entries like this in test-read-ctf.cc:
> 
>> +    "data/test-read-common/test3.so",
>> +    "",
>> +    "",
>> +    SEQUENCE_TYPE_ID_STYLE,
>> +    "data/test-read-common/test3-ctf.so.abi",
>> +    "output/test-read-common/test3-ctf.so.abi"
> 
> Here this entry does exactly what I am suggesting, even if
> test3-ctf.so.abi is stored in data/test-read-common.
> 
> So where exactly is the CTF test disabled?
> 
> [...]
> 
> 
>> diff --git a/tests/test-read-common.cc b/tests/test-read-common.cc
> 
> [...]
> 
>> +
>> +namespace abigail
>> +{
>> +namespace tests
>> +{
>> +namespace read_common
>> +{
> 
> Because this file now contains an API definition that is to be used be
> some tests, every single function of the file should be documented
> using doxygen comments, just like we have in src/abg-*.cc files.
> 
> For instance:
> 
>> +
>> +test_task::test_task(const InOutSpec &s,
>> +                     string& a_out_abi_base,
>> +                     string& a_in_elf_base,
>> +                     string& a_in_abi_base)
> 
> This function should be fully doxygen-documented.
> 
>> +    : is_ok(true),
>> +      spec(s),
>> +      out_abi_base(a_out_abi_base),
>> +      in_elf_base(a_in_elf_base),
>> +      in_abi_base(a_in_abi_base)
>> +  {}
>> +
>> +bool
>> +test_task::serialize_corpus(const string& out_abi_path,
>> +                            corpus_sptr corp)
> 
> Likewise.
> 
>> +{
>> +  ofstream of(out_abi_path.c_str(), std::ios_base::trunc);
>> +  if (!of.is_open())
>> +    {
>> +       error_message = string("failed to read ") + out_abi_path + "\n";
>> +       return false;
>> +    }
>> +
>> +  write_context_sptr write_ctxt
>> +      = create_write_context(corp->get_environment(), of);
>> +  set_type_id_style(*write_ctxt, spec.type_id_style);
>> +  is_ok = write_corpus(*write_ctxt, corp, /*indent=*/0);
>> +  of.close();
>> +
>> +  return true;
>> +}
>> +
>> +bool
>> +test_task::run_abidw(const string& extargs)
> 
> Likewise.
> 
>> +{
>> +  string abidw = string(get_build_dir()) + "/tools/abidw";
>> +  string drop_private_types;
>> +  if (!in_public_headers_path.empty())
>> +    drop_private_types += "--headers-dir " + in_public_headers_path +
>> +      " --drop-private-types";
>> +  string cmd = abidw + " " + drop_private_types + " --abidiff " + extargs +
>> +   in_elf_path;
>> +  if (system(cmd.c_str()))
>> +    {
>> +      error_message = string("ABIs differ:\n")
>> +        + in_elf_path
>> +        + "\nand:\n"
>> +        + out_abi_path
>> +        + "\n";
>> +
>> +      return false;
>> +    }
>> +
>> +  return true;
>> +}
>> +
>> +bool
>> +test_task::run_diff()
> 
> Likewise.
> 
>> +{
>> +  set_in_abi_path();
>> +  string cmd = "diff -u " + in_abi_path + " " + out_abi_path;
>> +  if (system(cmd.c_str()))
>> +    {
>> +      error_message = string("ABIs differ:\n")
>> +        + in_abi_path
>> +        + "\nand:\n"
>> +        + out_abi_path
>> +        + "\n";
>> +
>> +      return false;
>> +    }
>> +
>> +  return true;
>> +}
>> +
>> +void
>> +display_usage(const string& prog_name, ostream& out)
> 
> Likewise.
> 
>> +{
>> +  emit_prefix(prog_name, out)
>> +    << "usage: " << prog_name << " [options]\n"
>> +    << " where options can be: \n"
>> +    << "  --help|-h  display this message\n"
>> +    << "  --no-parallel execute testsuite is a sigle thread\n"
>> +  ;
>> +}
>> +
>> +bool
>> +parse_command_line(int argc, char* argv[], options& opts)
> 
> Likewise.
> 
>> +{
>> +  for (int i = 1; i < argc; ++i)
>> +    {
>> +      if (!strcmp(argv[i], "--no-parallel"))
>> +        opts.parallel = false;
>> +      else if (!strcmp(argv[i], "--help")
>> +               || !strcmp(argv[i], "--h"))
>> +        return false;
>> +      else
>> +        {
>> +          if (strlen(argv[i]) >= 2 && argv[i][0] == '-' && argv[i][1] == '-')
>> +            opts.wrong_option = argv[i];
>> +          return false;
>> +        }
>> +    }
>> +
>> +  return true;
>> +}
>> +
>> +bool
>> +run_tests(const size_t num_tests, const InOutSpec* specs,
>> +          const options& opts, create_new_test new_test)
> 
> Likewise.
> 
>> +{
> 
> [...]
> 
> 
>> diff --git a/tests/test-read-common.h b/tests/test-read-common.h
> 
> [...]
> 
>> +/// This is an aggregate that specifies where a test shall get its
>> +/// input from, and where it shall write its ouput to.
>> +struct InOutSpec
>> +{
>> +  const char* in_elf_path;
>> +  const char* in_suppr_spec_path;
>> +  const char* in_public_headers_path;
>> +  type_id_style_kind type_id_style;
>> +  const char* in_abi_path;
>> +  const char* out_abi_path;
>> +};// end struct InOutSpec
>> +
>> +/// The task that peforms the tests.
>> +struct test_task : public abigail::workers::task
>> +{
>> +  bool is_ok;
>> +  InOutSpec spec;
>> +  string error_message;
>> +  string out_abi_base;
>> +  string in_elf_base;
>> +  string in_abi_base;
>> +
>> +  string in_elf_path;
>> +  string in_abi_path;
>> +  string in_suppr_spec_path;
>> +  string in_public_headers_path;
>> +  string out_abi_path;
>> +
>> +  void
>> +  set_in_elf_path()
> 
> Please doxygen-document this function.
> 
>> +  {
>> +    in_elf_path = in_elf_base + spec.in_elf_path;
>> +  }
>> +
>> +  void
>> +  set_in_suppr_spec_path()
> 
> Likewise.
> 
>> +  {
>> +    if (spec.in_suppr_spec_path)
>> +      in_suppr_spec_path = in_elf_base + spec.in_suppr_spec_path;
>> +    else
>> +      in_suppr_spec_path.clear();
>> +  }
>> +
>> +  void
>> +  set_in_public_headers_path()
> 
> Likewise.
> 
>> +  {
>> +    if (spec.in_public_headers_path)
>> +      in_public_headers_path = spec.in_public_headers_path;
>> +    if (!in_public_headers_path.empty())
>> +      in_public_headers_path = in_elf_base + spec.in_public_headers_path;
>> +  }
>> +
>> +  bool
>> +  set_out_abi_path()
> 
> Likewise.
> 
>> +  {
>> +    out_abi_path = out_abi_base + spec.out_abi_path;
>> +    if (!abigail::tools_utils::ensure_parent_dir_created(out_abi_path))
>> +      {
>> +          error_message =
>> +            string("Could not create parent directory for ") + out_abi_path;
>> +          return false;
>> +      }
>> +    return true;
>> +  }
>> +
>> +  void
>> +  set_in_abi_path()
> 
> Likewise.
> 
>> +  {
>> +    in_abi_path = in_abi_base + spec.in_abi_path;
>> +  }
>> +
> 
> [...]
> 
>> +  test_task(const InOutSpec &s,
>> +            string& a_out_abi_base,
>> +            string& a_in_elf_base,
>> +            string& a_in_abi_base);
>> +  bool
>> +  serialize_corpus(const string& out_abi_path,
>> +                   corpus_sptr corp);
>> +  bool
>> +  run_abidw(const string& extargs = "");
>> +
>> +  bool
>> +  run_diff();
>> +
>> +  virtual
>> +  ~test_task()
>> +  {}
>> +
>> +}; // end struct test_task
>> +
>> +typedef shared_ptr<test_task> test_task_sptr;
>> +
>> +struct options
>> +{
> 
> Please doxygen-document this struct.
> 
>> +  string        wrong_option;
>> +  bool          parallel;
>> +
>> +  options()
>> +    : parallel(true)
>> +  {}
>> +
>> +  ~options()
>> +  {
>> +  }
>> +};
> 
> [...]
> 
>> diff --git a/tests/test-read-ctf.cc b/tests/test-read-ctf.cc
> 
> [...]
> 
> 
>> +test_task_ctf::test_task_ctf(const InOutSpec &s,
>> +                             string& a_out_abi_base,
>> +                             string& a_in_elf_base,
>> +                             string& a_in_abi_base)
> 
> Please doxygen-document this function.
> 
>> +        : test_task(s, a_out_abi_base, a_in_elf_base, a_in_abi_base)
>> +  {}
>> +
> 
> [...]
> 
>> +static test_task*
>> +new_task(const InOutSpec* s, string& a_out_abi_base,
>> +         string& a_in_elf_base, string& a_in_abi_base)
> 
> Please doxygen-document this function.
> 
>> +{
>> +  return new test_task_ctf(*s, a_in_abi_base,
> 
> This 'a_in_abi_base' should be a_out_abi_base.
> 
>> +                           a_in_elf_base, a_in_abi_base);
>> +}
> 
> [...]
> 
> 
>> diff --git a/tests/test-read-dwarf.cc b/tests/test-read-dwarf.cc
> 
> [...]
> 
> 
>> +static test_task*
>> +new_task(const InOutSpec* s, string& a_out_abi_base,
>> +         string& a_in_elf_base, string& a_in_abi_base)
> 
> Please doxygen-document this function.
> 
>> +{
>> +  return new test_task_dwarf(*s, a_in_abi_base,
> 
> This 'a_in_abi_base' should be a_out_abi_base.
> 
>> +                             a_in_elf_base, a_in_abi_base);
>> +}
>> 
>> int
>> main(int argc, char *argv[])
>> {
>>   bool no_parallel = false;
> 
> This variable is not unused.
> 
> 
> Thanks for working on this.  It's really appreciated!
> 
> [...]
> 
> Cheers,
> 
> -- 
> 		Dodji
>
  
Ben Woodard Nov. 25, 2021, 12:13 a.m. UTC | #6
> On Nov 24, 2021, at 11:09 AM, Ben Woodard <woodard@redhat.com> wrote:
> 
> 
> 
>> On Nov 24, 2021, at 8:36 AM, Dodji Seketeli <dodji@seketeli.org> wrote:
>> 
>> Hello,
>> 
>> [...]
>> 
>> Thanks for working on this.  Nice patch, by the way!  I like its
>> direction.
>> 
>> I have a few comments and I believe that when they are addressed, we'll
>> be able to apply the patch.
>> 
>> [...]
>> 
>>> Dependencies/limitations:
>>> 
>>> * It was worked on the top of the following patches:
>>> https://sourceware.org/pipermail/libabigail/2021q4/003853.html
>>> 
>>> * Some CTF tests were *disabled* because it generates the XML ABI
>>> corpus with *same information* but the XML nodes *are not* always
>>> in the *same order*, so using diff command fails. Details here:
>>> https://sourceware.org/pipermail/libabigail/2021q4/003824.html
>> 
>> In those cases where the abixml file generated from CTF is different
>> from the one generated from DWARF, I think we should have two
>> different reference abixml files to diff against.  No CTF test should
>> be disabled, I think.
> 
> Here is a somewhat deeper question that I think needs to be considered. I’ve generally referred to it as “DWARF Idioms” but this email makes me think that it is even larger than that. 
> 
> For my work, I need libabigail to generate an abstract notion of the ABI corpus. How it constructs that abstract notion of the ABI needs to be independent of the producer. Think of it this way, say we take the same compiler and have it compile the same library producing both CTF and DWARF, the ABI of the library doesn’t change. Since it is literally the same object, the program text is same. Therefore the ABI is unquestionably the the same. Any difference reported by libabigail therefore is a problem with libabigail. It is not taking the source material and abstracting it enough into the ABI artifacts to separate the artifacts from the implementation. 
> 
> So I kind of believe that we need to look more deeply into WHY the CTF and DWARF are not comparing as equivalent and begin the process of filing the compiler bugs when we need to, and doing what is necessary to abstract the ABI from the source material that libabigail used to construct its IR of the ABI corpus from.
> 
> So, I must say that I disagree with both dodji’s approach here and to a lesser extent Guillermo’s approach of disabling the tests. I think that the tests where the CTF doesn’t match the DWARF should be investigated and when necessary marked “xfail” with a note citing their individual cause. 
> 
> I think that what we need to work towards is:
> abidw produces the same output (or more precisely libabigail produces the same IR) whether you compile with -gdwarf-3 -gdwarf-4 -gdwarf-5 -gsplit-dwarf -gctf
> also for the most part the ABI should not change between compiler versions. There may be a few cases that we need to look into where the compiler actually breaks ABI and of course libabigail should flag those but I would assert that libabigail needs to abstract its IR of the ABI enough that compiler version changes that don’t actually change the ABI of the ELF object are not reported as ABI breaks. It currently does pretty well at this at the moment.

> Then once that foundation is built, being able to abstract the ABI IR enough that differences in toolchains e.g. LLVM vs GCC are not flagged as changes in the object’s ABI. This is important to provide people with a tool that will allow them to mix toolchains within a project to achieve optimal code.

Here is the problem:
$ head -5 ../../gcc-clang 
Functions changes summary: 9 Removed (157 filtered out), 1070 Changed (1068 filtered out), 123 Added (369 filtered out) functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
Function symbols changes summary: 151 Removed, 33 Added function symbols not referenced by debug info
Variable symbols changes summary: 1 Removed, 66 Added variable symbols not referenced by debug info

<snip 5000 lines of supposed changes>

yet:
$ LD_LIBRARY_PATH=../lib/:$LD_LIBRARY_PATH ./abidw --abidiff /usr/lib64/libstdc++.so.6.0.29 
Downloading from https://debuginfod.fedoraproject.org/ 5377772
Downloading from https://debuginfod.fedoraproject.org/ 32828914
Functions changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added function
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
$ LD_LIBRARY_PATH=../../l5/lib/:$LD_LIBRARY_PATH ./abidw --abidiff /usr/lib64/libstdc++.so.6.0.29 
Functions changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added function
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
$ cd ../../l5/bin
[ben@alien bin]$ LD_LIBRARY_PATH=../lib/:$LD_LIBRARY_PATH ./abidw --abidiff /usr/lib64/libstdc++.so.6.0.29 
Functions changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added function
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

[ben@alien bin]$ LD_LIBRARY_PATH=../../g5/lib/:$LD_LIBRARY_PATH ./abidw --abidiff /usr/lib64/libstdc++.so.6.0.29 
Functions changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added function
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable


where the l5 directory contains a clang++ build of libabigail and g5 contains a gcc build of it. (that one change that is filtered out is something I’ve already reported).

So obviously the gcc built version of abidw is able to run with the clang++ built version of the libabigail version of the library and vice versa. The libraries are ABI compatible. Good work compiler authors. So why does libabigail report 5000 lines worth of differences between them? We are starting to get to a point where we need to start classifying these thousands of differences and see how many of them are compiler errors and how many of them we can find a way to abstract away enough in the IR to avoid the errors presented.

As you guys introduce CTF, if we allow it to diverge from the IR that we get when processing DWARF, then the abixml doesn’t actually represent the ELF file’s ABI, it is much more limited than that because it is filtered through the compiler’s idiomatic way of expressing the features which are part of the ABI.

It shouldn’t matter where we get the information describing the file’s ABI, if the information is complete, then it shouldn’t matter what source it came from.

-ben


> 
> -ben
> 
>> 
>> So:
>> 
>> This:
>> 
>>  {
>>    "data/test-read-dwarf/test0",
>>    "",
>>    "",
>>    SEQUENCE_TYPE_ID_STYLE,
>>    "data/test-read-dwarf/test0.abi",
>>    "output/test-read-dwarf/test0.abi"
>>  },
>> 
>> would be changed into:
>> 
>>  {
>>    "data/test-read-common/test0",
>>    "",
>>    "",
>>    SEQUENCE_TYPE_ID_STYLE,
>>    "data/test-read-dwarf/test0.abi",
>>    "output/test-read-dwarf/test0.abi"
>>  },
>> 
>> For the DWARF test entry in test-read-dwarf.cc, and it would be
>> changed into:
>> 
>>  {
>>    "data/test-read-common/test0",
>>    "",
>>    "",
>>    SEQUENCE_TYPE_ID_STYLE,
>>    "data/test-read-ctf/test0.abi",
>>    "output/test-read-ctf/test0.abi"
>>  },
>> 
>> for the CTF test netry in test-read-ctf.cc.
>> 
>> By the way, I am seeing entries like this in test-read-ctf.cc:
>> 
>>> +    "data/test-read-common/test3.so",
>>> +    "",
>>> +    "",
>>> +    SEQUENCE_TYPE_ID_STYLE,
>>> +    "data/test-read-common/test3-ctf.so.abi",
>>> +    "output/test-read-common/test3-ctf.so.abi"
>> 
>> Here this entry does exactly what I am suggesting, even if
>> test3-ctf.so.abi is stored in data/test-read-common.
>> 
>> So where exactly is the CTF test disabled?
>> 
>> [...]
>> 
>> 
>>> diff --git a/tests/test-read-common.cc b/tests/test-read-common.cc
>> 
>> [...]
>> 
>>> +
>>> +namespace abigail
>>> +{
>>> +namespace tests
>>> +{
>>> +namespace read_common
>>> +{
>> 
>> Because this file now contains an API definition that is to be used be
>> some tests, every single function of the file should be documented
>> using doxygen comments, just like we have in src/abg-*.cc files.
>> 
>> For instance:
>> 
>>> +
>>> +test_task::test_task(const InOutSpec &s,
>>> +                     string& a_out_abi_base,
>>> +                     string& a_in_elf_base,
>>> +                     string& a_in_abi_base)
>> 
>> This function should be fully doxygen-documented.
>> 
>>> +    : is_ok(true),
>>> +      spec(s),
>>> +      out_abi_base(a_out_abi_base),
>>> +      in_elf_base(a_in_elf_base),
>>> +      in_abi_base(a_in_abi_base)
>>> +  {}
>>> +
>>> +bool
>>> +test_task::serialize_corpus(const string& out_abi_path,
>>> +                            corpus_sptr corp)
>> 
>> Likewise.
>> 
>>> +{
>>> +  ofstream of(out_abi_path.c_str(), std::ios_base::trunc);
>>> +  if (!of.is_open())
>>> +    {
>>> +       error_message = string("failed to read ") + out_abi_path + "\n";
>>> +       return false;
>>> +    }
>>> +
>>> +  write_context_sptr write_ctxt
>>> +      = create_write_context(corp->get_environment(), of);
>>> +  set_type_id_style(*write_ctxt, spec.type_id_style);
>>> +  is_ok = write_corpus(*write_ctxt, corp, /*indent=*/0);
>>> +  of.close();
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +bool
>>> +test_task::run_abidw(const string& extargs)
>> 
>> Likewise.
>> 
>>> +{
>>> +  string abidw = string(get_build_dir()) + "/tools/abidw";
>>> +  string drop_private_types;
>>> +  if (!in_public_headers_path.empty())
>>> +    drop_private_types += "--headers-dir " + in_public_headers_path +
>>> +      " --drop-private-types";
>>> +  string cmd = abidw + " " + drop_private_types + " --abidiff " + extargs +
>>> +   in_elf_path;
>>> +  if (system(cmd.c_str()))
>>> +    {
>>> +      error_message = string("ABIs differ:\n")
>>> +        + in_elf_path
>>> +        + "\nand:\n"
>>> +        + out_abi_path
>>> +        + "\n";
>>> +
>>> +      return false;
>>> +    }
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +bool
>>> +test_task::run_diff()
>> 
>> Likewise.
>> 
>>> +{
>>> +  set_in_abi_path();
>>> +  string cmd = "diff -u " + in_abi_path + " " + out_abi_path;
>>> +  if (system(cmd.c_str()))
>>> +    {
>>> +      error_message = string("ABIs differ:\n")
>>> +        + in_abi_path
>>> +        + "\nand:\n"
>>> +        + out_abi_path
>>> +        + "\n";
>>> +
>>> +      return false;
>>> +    }
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +void
>>> +display_usage(const string& prog_name, ostream& out)
>> 
>> Likewise.
>> 
>>> +{
>>> +  emit_prefix(prog_name, out)
>>> +    << "usage: " << prog_name << " [options]\n"
>>> +    << " where options can be: \n"
>>> +    << "  --help|-h  display this message\n"
>>> +    << "  --no-parallel execute testsuite is a sigle thread\n"
>>> +  ;
>>> +}
>>> +
>>> +bool
>>> +parse_command_line(int argc, char* argv[], options& opts)
>> 
>> Likewise.
>> 
>>> +{
>>> +  for (int i = 1; i < argc; ++i)
>>> +    {
>>> +      if (!strcmp(argv[i], "--no-parallel"))
>>> +        opts.parallel = false;
>>> +      else if (!strcmp(argv[i], "--help")
>>> +               || !strcmp(argv[i], "--h"))
>>> +        return false;
>>> +      else
>>> +        {
>>> +          if (strlen(argv[i]) >= 2 && argv[i][0] == '-' && argv[i][1] == '-')
>>> +            opts.wrong_option = argv[i];
>>> +          return false;
>>> +        }
>>> +    }
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +bool
>>> +run_tests(const size_t num_tests, const InOutSpec* specs,
>>> +          const options& opts, create_new_test new_test)
>> 
>> Likewise.
>> 
>>> +{
>> 
>> [...]
>> 
>> 
>>> diff --git a/tests/test-read-common.h b/tests/test-read-common.h
>> 
>> [...]
>> 
>>> +/// This is an aggregate that specifies where a test shall get its
>>> +/// input from, and where it shall write its ouput to.
>>> +struct InOutSpec
>>> +{
>>> +  const char* in_elf_path;
>>> +  const char* in_suppr_spec_path;
>>> +  const char* in_public_headers_path;
>>> +  type_id_style_kind type_id_style;
>>> +  const char* in_abi_path;
>>> +  const char* out_abi_path;
>>> +};// end struct InOutSpec
>>> +
>>> +/// The task that peforms the tests.
>>> +struct test_task : public abigail::workers::task
>>> +{
>>> +  bool is_ok;
>>> +  InOutSpec spec;
>>> +  string error_message;
>>> +  string out_abi_base;
>>> +  string in_elf_base;
>>> +  string in_abi_base;
>>> +
>>> +  string in_elf_path;
>>> +  string in_abi_path;
>>> +  string in_suppr_spec_path;
>>> +  string in_public_headers_path;
>>> +  string out_abi_path;
>>> +
>>> +  void
>>> +  set_in_elf_path()
>> 
>> Please doxygen-document this function.
>> 
>>> +  {
>>> +    in_elf_path = in_elf_base + spec.in_elf_path;
>>> +  }
>>> +
>>> +  void
>>> +  set_in_suppr_spec_path()
>> 
>> Likewise.
>> 
>>> +  {
>>> +    if (spec.in_suppr_spec_path)
>>> +      in_suppr_spec_path = in_elf_base + spec.in_suppr_spec_path;
>>> +    else
>>> +      in_suppr_spec_path.clear();
>>> +  }
>>> +
>>> +  void
>>> +  set_in_public_headers_path()
>> 
>> Likewise.
>> 
>>> +  {
>>> +    if (spec.in_public_headers_path)
>>> +      in_public_headers_path = spec.in_public_headers_path;
>>> +    if (!in_public_headers_path.empty())
>>> +      in_public_headers_path = in_elf_base + spec.in_public_headers_path;
>>> +  }
>>> +
>>> +  bool
>>> +  set_out_abi_path()
>> 
>> Likewise.
>> 
>>> +  {
>>> +    out_abi_path = out_abi_base + spec.out_abi_path;
>>> +    if (!abigail::tools_utils::ensure_parent_dir_created(out_abi_path))
>>> +      {
>>> +          error_message =
>>> +            string("Could not create parent directory for ") + out_abi_path;
>>> +          return false;
>>> +      }
>>> +    return true;
>>> +  }
>>> +
>>> +  void
>>> +  set_in_abi_path()
>> 
>> Likewise.
>> 
>>> +  {
>>> +    in_abi_path = in_abi_base + spec.in_abi_path;
>>> +  }
>>> +
>> 
>> [...]
>> 
>>> +  test_task(const InOutSpec &s,
>>> +            string& a_out_abi_base,
>>> +            string& a_in_elf_base,
>>> +            string& a_in_abi_base);
>>> +  bool
>>> +  serialize_corpus(const string& out_abi_path,
>>> +                   corpus_sptr corp);
>>> +  bool
>>> +  run_abidw(const string& extargs = "");
>>> +
>>> +  bool
>>> +  run_diff();
>>> +
>>> +  virtual
>>> +  ~test_task()
>>> +  {}
>>> +
>>> +}; // end struct test_task
>>> +
>>> +typedef shared_ptr<test_task> test_task_sptr;
>>> +
>>> +struct options
>>> +{
>> 
>> Please doxygen-document this struct.
>> 
>>> +  string        wrong_option;
>>> +  bool          parallel;
>>> +
>>> +  options()
>>> +    : parallel(true)
>>> +  {}
>>> +
>>> +  ~options()
>>> +  {
>>> +  }
>>> +};
>> 
>> [...]
>> 
>>> diff --git a/tests/test-read-ctf.cc b/tests/test-read-ctf.cc
>> 
>> [...]
>> 
>> 
>>> +test_task_ctf::test_task_ctf(const InOutSpec &s,
>>> +                             string& a_out_abi_base,
>>> +                             string& a_in_elf_base,
>>> +                             string& a_in_abi_base)
>> 
>> Please doxygen-document this function.
>> 
>>> +        : test_task(s, a_out_abi_base, a_in_elf_base, a_in_abi_base)
>>> +  {}
>>> +
>> 
>> [...]
>> 
>>> +static test_task*
>>> +new_task(const InOutSpec* s, string& a_out_abi_base,
>>> +         string& a_in_elf_base, string& a_in_abi_base)
>> 
>> Please doxygen-document this function.
>> 
>>> +{
>>> +  return new test_task_ctf(*s, a_in_abi_base,
>> 
>> This 'a_in_abi_base' should be a_out_abi_base.
>> 
>>> +                           a_in_elf_base, a_in_abi_base);
>>> +}
>> 
>> [...]
>> 
>> 
>>> diff --git a/tests/test-read-dwarf.cc b/tests/test-read-dwarf.cc
>> 
>> [...]
>> 
>> 
>>> +static test_task*
>>> +new_task(const InOutSpec* s, string& a_out_abi_base,
>>> +         string& a_in_elf_base, string& a_in_abi_base)
>> 
>> Please doxygen-document this function.
>> 
>>> +{
>>> +  return new test_task_dwarf(*s, a_in_abi_base,
>> 
>> This 'a_in_abi_base' should be a_out_abi_base.
>> 
>>> +                             a_in_elf_base, a_in_abi_base);
>>> +}
>>> 
>>> int
>>> main(int argc, char *argv[])
>>> {
>>>  bool no_parallel = false;
>> 
>> This variable is not unused.
>> 
>> 
>> Thanks for working on this.  It's really appreciated!
>> 
>> [...]
>> 
>> Cheers,
>> 
>> -- 
>> 		Dodji
  
Jose E. Marchesi Nov. 25, 2021, 6:50 a.m. UTC | #7
>> On Nov 24, 2021, at 8:36 AM, Dodji Seketeli <dodji@seketeli.org> wrote:
>> 
>> Hello,
>> 
>> [...]
>> 
>> Thanks for working on this.  Nice patch, by the way!  I like its
>> direction.
>> 
>> I have a few comments and I believe that when they are addressed, we'll
>> be able to apply the patch.
>> 
>> [...]
>> 
>>> Dependencies/limitations:
>>> 
>>> * It was worked on the top of the following patches:
>>> https://sourceware.org/pipermail/libabigail/2021q4/003853.html
>>> 
>>> * Some CTF tests were *disabled* because it generates the XML ABI
>>> corpus with *same information* but the XML nodes *are not* always
>>> in the *same order*, so using diff command fails. Details here:
>>> https://sourceware.org/pipermail/libabigail/2021q4/003824.html
>> 
>> In those cases where the abixml file generated from CTF is different
>> from the one generated from DWARF, I think we should have two
>> different reference abixml files to diff against.  No CTF test should
>> be disabled, I think.
>
> Here is a somewhat deeper question that I think needs to be
> considered. I’ve generally referred to it as “DWARF Idioms” but this
> email makes me think that it is even larger than that.
>
> For my work, I need libabigail to generate an abstract notion of the
> ABI corpus. How it constructs that abstract notion of the ABI needs to
> be independent of the producer. Think of it this way, say we take the
> same compiler and have it compile the same library producing both CTF
> and DWARF, the ABI of the library doesn’t change. Since it is
> literally the same object, the program text is same. Therefore the ABI
> is unquestionably the the same. Any difference reported by libabigail
> therefore is a problem with libabigail. It is not taking the source
> material and abstracting it enough into the ABI artifacts to separate
> the artifacts from the implementation.
>
> So I kind of believe that we need to look more deeply into WHY the CTF
> and DWARF are not comparing as equivalent and begin the process of
> filing the compiler bugs when we need to, and doing what is necessary
> to abstract the ABI from the source material that libabigail used to
> construct its IR of the ABI corpus from.
>
> So, I must say that I disagree with both dodji’s approach here and to
> a lesser extent Guillermo’s approach of disabling the tests. I think
> that the tests where the CTF doesn’t match the DWARF should be
> investigated and when necessary marked “xfail” with a note citing
> their individual cause.
>
> I think that what we need to work towards is:
> abidw produces the same output (or more precisely libabigail produces
> the same IR) whether you compile with -gdwarf-3 -gdwarf-4 -gdwarf-5
> -gsplit-dwarf -gctf
> also for the most part the ABI should not change between compiler
> versions. There may be a few cases that we need to look into where the
> compiler actually breaks ABI and of course libabigail should flag
> those but I would assert that libabigail needs to abstract its IR of
> the ABI enough that compiler version changes that don’t actually
> change the ABI of the ELF object are not reported as ABI breaks. It
> currently does pretty well at this at the moment.
> Then once that foundation is built, being able to abstract the ABI IR
> enough that differences in toolchains e.g. LLVM vs GCC are not flagged
> as changes in the object’s ABI. This is important to provide people
> with a tool that will allow them to mix toolchains within a project to
> achieve optimal code.

I'm so glad you are raising these concerns.

I agree with you that ideally abidw should produce "same output" (read
equivalent output ABI-wise) regardless of the origin of the ABI
corpus... but then:

Is the relative order of the <*-decl > nodes in the ABI XML part of the
ABI?

Is the location information (present in DWARF, not present in CTF nor
BTF) part of the ABI?

Are the names assigned to internally-generated types (such as the
underlying type of an enumerator) part of the ABI?

Are the newlines and blank spaces after XML marks part of the ABI?

I am no expert in ABI analysis, but I would say the answers in all these
cases is `no'.  The internal libabigail ABI comparison algorithms would
not be impacted by these things, right?

It seems to me that the main problems here are that ABI XML, as it is,
conveys way too much information (useful, no doubt, but superfluous
ABI-wise) and that `diff' is used to perform a textual comparison of
these files.

Textual comparison would work if we defined a "canonicalized" version of
ABI XML.  Translating from ABI XML to canonical ABI XML would involve:

1) Strip _everything_ that is not strictly part of the ABI (such as
   location information, anonymous type names, etc).

2) Sort the XML elements in a predefined way.  Whatever sort criteria is
   used, it would need to be defined only by ABI-constituent elements,
   such as the names of non-anonymous types.  And of course the criteria
   itself must not change.

The only reason you could operate with ABI XML files heavily annotated
with non-ABI determining information (such as the loc info and
superfluous and arbitrary names) is having an unique source for the ABI
info.  That's no longer the case: we are using CTF, the Google chaps are
using BTF.

The above considered, I think we have three options now:

a) To define that canonical ABI XML and write an abistrip tool that does
   the translation, maybe add --canonical options to the tools that
   generate ABI XML.  Then use `diff' in the testsuite.

   or

b) To use an external ABI comparison tool in the testsuite, non-textual,
   that consumes ABI XML.

   or

c) To use the "internal" approach I already suggested in another email,
   having two different sets of tests: one set to test the front-ends
   that assume the libabigail comparison algorithm works properly,
   another set to test the comparison algorithm that uses either
   hand-written input files or assumes the front-ends work properly.

I personally think (c) would be best.
  
Giuliano Procida Nov. 25, 2021, 9:34 a.m. UTC | #8
Hi Ben.

On Wed, 24 Nov 2021 at 19:10, Ben Woodard via Libabigail
<libabigail@sourceware.org> wrote:
>
>
>
> > On Nov 24, 2021, at 8:36 AM, Dodji Seketeli <dodji@seketeli.org> wrote:
> >
> > Hello,
> >
> > [...]
> >
> > Thanks for working on this.  Nice patch, by the way!  I like its
> > direction.
> >
> > I have a few comments and I believe that when they are addressed, we'll
> > be able to apply the patch.
> >
> > [...]
> >
> >> Dependencies/limitations:
> >>
> >> * It was worked on the top of the following patches:
> >> https://sourceware.org/pipermail/libabigail/2021q4/003853.html
> >>
> >> * Some CTF tests were *disabled* because it generates the XML ABI
> >> corpus with *same information* but the XML nodes *are not* always
> >> in the *same order*, so using diff command fails. Details here:
> >> https://sourceware.org/pipermail/libabigail/2021q4/003824.html
> >
> > In those cases where the abixml file generated from CTF is different
> > from the one generated from DWARF, I think we should have two
> > different reference abixml files to diff against.  No CTF test should
> > be disabled, I think.
>
> Here is a somewhat deeper question that I think needs to be considered. I’ve generally referred to it as “DWARF Idioms” but this email makes me think that it is even larger than that.
>
> For my work, I need libabigail to generate an abstract notion of the ABI corpus. How it constructs that abstract notion of the ABI needs to be independent of the producer. Think of it this way, say we take the same compiler and have it compile the same library producing both CTF and DWARF, the ABI of the library doesn’t change. Since it is literally the same object, the program text is same. Therefore the ABI is unquestionably the the same. Any difference reported by libabigail therefore is a problem with libabigail. It is not taking the source material and abstracting it enough into the ABI artifacts to separate the artifacts from the implementation.
>
> So I kind of believe that we need to look more deeply into WHY the CTF and DWARF are not comparing as equivalent and begin the process of filing the compiler bugs when we need to, and doing what is necessary to abstract the ABI from the source material that libabigail used to construct its IR of the ABI corpus from.
>
> So, I must say that I disagree with both dodji’s approach here and to a lesser extent Guillermo’s approach of disabling the tests. I think that the tests where the CTF doesn’t match the DWARF should be investigated and when necessary marked “xfail” with a note citing their individual cause.
>
> I think that what we need to work towards is:
> abidw produces the same output (or more precisely libabigail produces the same IR) whether you compile with -gdwarf-3 -gdwarf-4 -gdwarf-5 -gsplit-dwarf -gctf
> also for the most part the ABI should not change between compiler versions. There may be a few cases that we need to look into where the compiler actually breaks ABI and of course libabigail should flag those but I would assert that libabigail needs to abstract its IR of the ABI enough that compiler version changes that don’t actually change the ABI of the ELF object are not reported as ABI breaks. It currently does pretty well at this at the moment.
> Then once that foundation is built, being able to abstract the ABI IR enough that differences in toolchains e.g. LLVM vs GCC are not flagged as changes in the object’s ABI. This is important to provide people with a tool that will allow them to mix toolchains within a project to achieve optimal code.
>

This almost sounds like a hierarchy of needs:

ABI tools produce identical output for identical inputs no matter
which platform they run or which compiler / library was used to build
them.
- we have seen libabigail hash table trouble when built with Clang
- we don't support BTF byte sex conversion (the format is I think target-endian)

each platform / compiler / optimisation / LTO / DWARF combination
generates object code that appears ABI-stable (varying just the ABI
tooling)
...
each platform's object code is ABI-equivalent (varying all the other things)

And then do the same for C++, Rust etc.

So far I've seen apparent ABI issues due to all the above things,
except possibly -Olevel, and seen bugs fixed in LLVM, elfutils,
dwarves and libabigail.

It would be useful to prioritise your needs. Which stability axes
bring most value? At a rough guess, we'd want varying optimisation
levels and LTO to be least likely things to cause ABI differences,
maybe then DWARF version, followed by compiler then standard library?

It would also be useful to try to limit the combinations that will be
supported (nothing too old or obscure, for example). Is anyone still
using DWARF 3?

Giuliano.

> -ben
>
> >
> > So:
> >
> > This:
> >
> >   {
> >     "data/test-read-dwarf/test0",
> >     "",
> >     "",
> >     SEQUENCE_TYPE_ID_STYLE,
> >     "data/test-read-dwarf/test0.abi",
> >     "output/test-read-dwarf/test0.abi"
> >   },
> >
> > would be changed into:
> >
> >   {
> >     "data/test-read-common/test0",
> >     "",
> >     "",
> >     SEQUENCE_TYPE_ID_STYLE,
> >     "data/test-read-dwarf/test0.abi",
> >     "output/test-read-dwarf/test0.abi"
> >   },
> >
> > For the DWARF test entry in test-read-dwarf.cc, and it would be
> > changed into:
> >
> >   {
> >     "data/test-read-common/test0",
> >     "",
> >     "",
> >     SEQUENCE_TYPE_ID_STYLE,
> >     "data/test-read-ctf/test0.abi",
> >     "output/test-read-ctf/test0.abi"
> >   },
> >
> > for the CTF test netry in test-read-ctf.cc.
> >
> > By the way, I am seeing entries like this in test-read-ctf.cc:
> >
> >> +    "data/test-read-common/test3.so",
> >> +    "",
> >> +    "",
> >> +    SEQUENCE_TYPE_ID_STYLE,
> >> +    "data/test-read-common/test3-ctf.so.abi",
> >> +    "output/test-read-common/test3-ctf.so.abi"
> >
> > Here this entry does exactly what I am suggesting, even if
> > test3-ctf.so.abi is stored in data/test-read-common.
> >
> > So where exactly is the CTF test disabled?
> >
> > [...]
> >
> >
> >> diff --git a/tests/test-read-common.cc b/tests/test-read-common.cc
> >
> > [...]
> >
> >> +
> >> +namespace abigail
> >> +{
> >> +namespace tests
> >> +{
> >> +namespace read_common
> >> +{
> >
> > Because this file now contains an API definition that is to be used be
> > some tests, every single function of the file should be documented
> > using doxygen comments, just like we have in src/abg-*.cc files.
> >
> > For instance:
> >
> >> +
> >> +test_task::test_task(const InOutSpec &s,
> >> +                     string& a_out_abi_base,
> >> +                     string& a_in_elf_base,
> >> +                     string& a_in_abi_base)
> >
> > This function should be fully doxygen-documented.
> >
> >> +    : is_ok(true),
> >> +      spec(s),
> >> +      out_abi_base(a_out_abi_base),
> >> +      in_elf_base(a_in_elf_base),
> >> +      in_abi_base(a_in_abi_base)
> >> +  {}
> >> +
> >> +bool
> >> +test_task::serialize_corpus(const string& out_abi_path,
> >> +                            corpus_sptr corp)
> >
> > Likewise.
> >
> >> +{
> >> +  ofstream of(out_abi_path.c_str(), std::ios_base::trunc);
> >> +  if (!of.is_open())
> >> +    {
> >> +       error_message = string("failed to read ") + out_abi_path + "\n";
> >> +       return false;
> >> +    }
> >> +
> >> +  write_context_sptr write_ctxt
> >> +      = create_write_context(corp->get_environment(), of);
> >> +  set_type_id_style(*write_ctxt, spec.type_id_style);
> >> +  is_ok = write_corpus(*write_ctxt, corp, /*indent=*/0);
> >> +  of.close();
> >> +
> >> +  return true;
> >> +}
> >> +
> >> +bool
> >> +test_task::run_abidw(const string& extargs)
> >
> > Likewise.
> >
> >> +{
> >> +  string abidw = string(get_build_dir()) + "/tools/abidw";
> >> +  string drop_private_types;
> >> +  if (!in_public_headers_path.empty())
> >> +    drop_private_types += "--headers-dir " + in_public_headers_path +
> >> +      " --drop-private-types";
> >> +  string cmd = abidw + " " + drop_private_types + " --abidiff " + extargs +
> >> +   in_elf_path;
> >> +  if (system(cmd.c_str()))
> >> +    {
> >> +      error_message = string("ABIs differ:\n")
> >> +        + in_elf_path
> >> +        + "\nand:\n"
> >> +        + out_abi_path
> >> +        + "\n";
> >> +
> >> +      return false;
> >> +    }
> >> +
> >> +  return true;
> >> +}
> >> +
> >> +bool
> >> +test_task::run_diff()
> >
> > Likewise.
> >
> >> +{
> >> +  set_in_abi_path();
> >> +  string cmd = "diff -u " + in_abi_path + " " + out_abi_path;
> >> +  if (system(cmd.c_str()))
> >> +    {
> >> +      error_message = string("ABIs differ:\n")
> >> +        + in_abi_path
> >> +        + "\nand:\n"
> >> +        + out_abi_path
> >> +        + "\n";
> >> +
> >> +      return false;
> >> +    }
> >> +
> >> +  return true;
> >> +}
> >> +
> >> +void
> >> +display_usage(const string& prog_name, ostream& out)
> >
> > Likewise.
> >
> >> +{
> >> +  emit_prefix(prog_name, out)
> >> +    << "usage: " << prog_name << " [options]\n"
> >> +    << " where options can be: \n"
> >> +    << "  --help|-h  display this message\n"
> >> +    << "  --no-parallel execute testsuite is a sigle thread\n"
> >> +  ;
> >> +}
> >> +
> >> +bool
> >> +parse_command_line(int argc, char* argv[], options& opts)
> >
> > Likewise.
> >
> >> +{
> >> +  for (int i = 1; i < argc; ++i)
> >> +    {
> >> +      if (!strcmp(argv[i], "--no-parallel"))
> >> +        opts.parallel = false;
> >> +      else if (!strcmp(argv[i], "--help")
> >> +               || !strcmp(argv[i], "--h"))
> >> +        return false;
> >> +      else
> >> +        {
> >> +          if (strlen(argv[i]) >= 2 && argv[i][0] == '-' && argv[i][1] == '-')
> >> +            opts.wrong_option = argv[i];
> >> +          return false;
> >> +        }
> >> +    }
> >> +
> >> +  return true;
> >> +}
> >> +
> >> +bool
> >> +run_tests(const size_t num_tests, const InOutSpec* specs,
> >> +          const options& opts, create_new_test new_test)
> >
> > Likewise.
> >
> >> +{
> >
> > [...]
> >
> >
> >> diff --git a/tests/test-read-common.h b/tests/test-read-common.h
> >
> > [...]
> >
> >> +/// This is an aggregate that specifies where a test shall get its
> >> +/// input from, and where it shall write its ouput to.
> >> +struct InOutSpec
> >> +{
> >> +  const char* in_elf_path;
> >> +  const char* in_suppr_spec_path;
> >> +  const char* in_public_headers_path;
> >> +  type_id_style_kind type_id_style;
> >> +  const char* in_abi_path;
> >> +  const char* out_abi_path;
> >> +};// end struct InOutSpec
> >> +
> >> +/// The task that peforms the tests.
> >> +struct test_task : public abigail::workers::task
> >> +{
> >> +  bool is_ok;
> >> +  InOutSpec spec;
> >> +  string error_message;
> >> +  string out_abi_base;
> >> +  string in_elf_base;
> >> +  string in_abi_base;
> >> +
> >> +  string in_elf_path;
> >> +  string in_abi_path;
> >> +  string in_suppr_spec_path;
> >> +  string in_public_headers_path;
> >> +  string out_abi_path;
> >> +
> >> +  void
> >> +  set_in_elf_path()
> >
> > Please doxygen-document this function.
> >
> >> +  {
> >> +    in_elf_path = in_elf_base + spec.in_elf_path;
> >> +  }
> >> +
> >> +  void
> >> +  set_in_suppr_spec_path()
> >
> > Likewise.
> >
> >> +  {
> >> +    if (spec.in_suppr_spec_path)
> >> +      in_suppr_spec_path = in_elf_base + spec.in_suppr_spec_path;
> >> +    else
> >> +      in_suppr_spec_path.clear();
> >> +  }
> >> +
> >> +  void
> >> +  set_in_public_headers_path()
> >
> > Likewise.
> >
> >> +  {
> >> +    if (spec.in_public_headers_path)
> >> +      in_public_headers_path = spec.in_public_headers_path;
> >> +    if (!in_public_headers_path.empty())
> >> +      in_public_headers_path = in_elf_base + spec.in_public_headers_path;
> >> +  }
> >> +
> >> +  bool
> >> +  set_out_abi_path()
> >
> > Likewise.
> >
> >> +  {
> >> +    out_abi_path = out_abi_base + spec.out_abi_path;
> >> +    if (!abigail::tools_utils::ensure_parent_dir_created(out_abi_path))
> >> +      {
> >> +          error_message =
> >> +            string("Could not create parent directory for ") + out_abi_path;
> >> +          return false;
> >> +      }
> >> +    return true;
> >> +  }
> >> +
> >> +  void
> >> +  set_in_abi_path()
> >
> > Likewise.
> >
> >> +  {
> >> +    in_abi_path = in_abi_base + spec.in_abi_path;
> >> +  }
> >> +
> >
> > [...]
> >
> >> +  test_task(const InOutSpec &s,
> >> +            string& a_out_abi_base,
> >> +            string& a_in_elf_base,
> >> +            string& a_in_abi_base);
> >> +  bool
> >> +  serialize_corpus(const string& out_abi_path,
> >> +                   corpus_sptr corp);
> >> +  bool
> >> +  run_abidw(const string& extargs = "");
> >> +
> >> +  bool
> >> +  run_diff();
> >> +
> >> +  virtual
> >> +  ~test_task()
> >> +  {}
> >> +
> >> +}; // end struct test_task
> >> +
> >> +typedef shared_ptr<test_task> test_task_sptr;
> >> +
> >> +struct options
> >> +{
> >
> > Please doxygen-document this struct.
> >
> >> +  string        wrong_option;
> >> +  bool          parallel;
> >> +
> >> +  options()
> >> +    : parallel(true)
> >> +  {}
> >> +
> >> +  ~options()
> >> +  {
> >> +  }
> >> +};
> >
> > [...]
> >
> >> diff --git a/tests/test-read-ctf.cc b/tests/test-read-ctf.cc
> >
> > [...]
> >
> >
> >> +test_task_ctf::test_task_ctf(const InOutSpec &s,
> >> +                             string& a_out_abi_base,
> >> +                             string& a_in_elf_base,
> >> +                             string& a_in_abi_base)
> >
> > Please doxygen-document this function.
> >
> >> +        : test_task(s, a_out_abi_base, a_in_elf_base, a_in_abi_base)
> >> +  {}
> >> +
> >
> > [...]
> >
> >> +static test_task*
> >> +new_task(const InOutSpec* s, string& a_out_abi_base,
> >> +         string& a_in_elf_base, string& a_in_abi_base)
> >
> > Please doxygen-document this function.
> >
> >> +{
> >> +  return new test_task_ctf(*s, a_in_abi_base,
> >
> > This 'a_in_abi_base' should be a_out_abi_base.
> >
> >> +                           a_in_elf_base, a_in_abi_base);
> >> +}
> >
> > [...]
> >
> >
> >> diff --git a/tests/test-read-dwarf.cc b/tests/test-read-dwarf.cc
> >
> > [...]
> >
> >
> >> +static test_task*
> >> +new_task(const InOutSpec* s, string& a_out_abi_base,
> >> +         string& a_in_elf_base, string& a_in_abi_base)
> >
> > Please doxygen-document this function.
> >
> >> +{
> >> +  return new test_task_dwarf(*s, a_in_abi_base,
> >
> > This 'a_in_abi_base' should be a_out_abi_base.
> >
> >> +                             a_in_elf_base, a_in_abi_base);
> >> +}
> >>
> >> int
> >> main(int argc, char *argv[])
> >> {
> >>   bool no_parallel = false;
> >
> > This variable is not unused.
> >
> >
> > Thanks for working on this.  It's really appreciated!
> >
> > [...]
> >
> > Cheers,
> >
> > --
> >               Dodji
> >
>
  
Giuliano Procida Nov. 25, 2021, 9:47 a.m. UTC | #9
Hi Jose.

On Thu, 25 Nov 2021 at 06:50, Jose E. Marchesi via Libabigail
<libabigail@sourceware.org> wrote:
>
>
> >> On Nov 24, 2021, at 8:36 AM, Dodji Seketeli <dodji@seketeli.org> wrote:
> >>
> >> Hello,
> >>
> >> [...]
> >>
> >> Thanks for working on this.  Nice patch, by the way!  I like its
> >> direction.
> >>
> >> I have a few comments and I believe that when they are addressed, we'll
> >> be able to apply the patch.
> >>
> >> [...]
> >>
> >>> Dependencies/limitations:
> >>>
> >>> * It was worked on the top of the following patches:
> >>> https://sourceware.org/pipermail/libabigail/2021q4/003853.html
> >>>
> >>> * Some CTF tests were *disabled* because it generates the XML ABI
> >>> corpus with *same information* but the XML nodes *are not* always
> >>> in the *same order*, so using diff command fails. Details here:
> >>> https://sourceware.org/pipermail/libabigail/2021q4/003824.html
> >>
> >> In those cases where the abixml file generated from CTF is different
> >> from the one generated from DWARF, I think we should have two
> >> different reference abixml files to diff against.  No CTF test should
> >> be disabled, I think.
> >
> > Here is a somewhat deeper question that I think needs to be
> > considered. I’ve generally referred to it as “DWARF Idioms” but this
> > email makes me think that it is even larger than that.
> >
> > For my work, I need libabigail to generate an abstract notion of the
> > ABI corpus. How it constructs that abstract notion of the ABI needs to
> > be independent of the producer. Think of it this way, say we take the
> > same compiler and have it compile the same library producing both CTF
> > and DWARF, the ABI of the library doesn’t change. Since it is
> > literally the same object, the program text is same. Therefore the ABI
> > is unquestionably the the same. Any difference reported by libabigail
> > therefore is a problem with libabigail. It is not taking the source
> > material and abstracting it enough into the ABI artifacts to separate
> > the artifacts from the implementation.
> >
> > So I kind of believe that we need to look more deeply into WHY the CTF
> > and DWARF are not comparing as equivalent and begin the process of
> > filing the compiler bugs when we need to, and doing what is necessary
> > to abstract the ABI from the source material that libabigail used to
> > construct its IR of the ABI corpus from.
> >
> > So, I must say that I disagree with both dodji’s approach here and to
> > a lesser extent Guillermo’s approach of disabling the tests. I think
> > that the tests where the CTF doesn’t match the DWARF should be
> > investigated and when necessary marked “xfail” with a note citing
> > their individual cause.
> >
> > I think that what we need to work towards is:
> > abidw produces the same output (or more precisely libabigail produces
> > the same IR) whether you compile with -gdwarf-3 -gdwarf-4 -gdwarf-5
> > -gsplit-dwarf -gctf
> > also for the most part the ABI should not change between compiler
> > versions. There may be a few cases that we need to look into where the
> > compiler actually breaks ABI and of course libabigail should flag
> > those but I would assert that libabigail needs to abstract its IR of
> > the ABI enough that compiler version changes that don’t actually
> > change the ABI of the ELF object are not reported as ABI breaks. It
> > currently does pretty well at this at the moment.
> > Then once that foundation is built, being able to abstract the ABI IR
> > enough that differences in toolchains e.g. LLVM vs GCC are not flagged
> > as changes in the object’s ABI. This is important to provide people
> > with a tool that will allow them to mix toolchains within a project to
> > achieve optimal code.
>
> I'm so glad you are raising these concerns.
>
> I agree with you that ideally abidw should produce "same output" (read
> equivalent output ABI-wise) regardless of the origin of the ABI
> corpus... but then:
>
> Is the relative order of the <*-decl > nodes in the ABI XML part of the
> ABI?
>

No. And abidiff really doesn't care, unless there are duplicates in
the data or bugs in the code.

> Is the location information (present in DWARF, not present in CTF nor
> BTF) part of the ABI?
>

No. I'm pretty sure abidiff doesn't care.

There are some subtle source-level issues here, but not ABI ones.

struct {} x;
struct {} y;

x and y have different (unique) types. I spent a while, a long while
ago, worrying about this, but I think it's a non-issue. Just treat
them as having the same type.

> Are the names assigned to internally-generated types (such as the
> underlying type of an enumerator) part of the ABI?
>

They should not be, but can result in ABI diff reports. abidiff does
distinguish two levels of difference and has different exit codes. So,
at the very least, this should not be an incompatible diff.

More significantly, for C++, the size, signedness and identity of the
enum-underlying are both under user control and (I believe) can
influence which overloads of functions get called via implicit
conversion. This is an API (compile-time) rather than an ABI
(run-time) issue.

> Are the newlines and blank spaces after XML marks part of the ABI?
>

No.

> I am no expert in ABI analysis, but I would say the answers in all these
> cases is `no'.  The internal libabigail ABI comparison algorithms would
> not be impacted by these things, right?
>

Ideally not.

> It seems to me that the main problems here are that ABI XML, as it is,
> conveys way too much information (useful, no doubt, but superfluous
> ABI-wise) and that `diff' is used to perform a textual comparison of
> these files.
>
> Textual comparison would work if we defined a "canonicalized" version of
> ABI XML.  Translating from ABI XML to canonical ABI XML would involve:
>

0) First having completely stable type ids. --type-id-style hash goes
some way towards this.

> 1) Strip _everything_ that is not strictly part of the ABI (such as
>    location information, anonymous type names, etc).
>

and function parameter names.

You also missed out:

- remove all elements unreachable from the symbol "roots"
- resolve duplicate elements (we tend to get quite a lot)

But if *really* you only care about ABIs and not APIs, we should be
stripping member names and just leaving offsets. I don't think we
should do this!

abidw --no-show-locs strips out source location information.

> 2) Sort the XML elements in a predefined way.  Whatever sort criteria is
>    used, it would need to be defined only by ABI-constituent elements,
>    such as the names of non-anonymous types.  And of course the criteria
>    itself must not change.
>

I've written a tool that does 2) as best as it can and does some of 1).

As yet, it cannot strip function names (we think we get spurious XML
diffs with them due to Clang LTO), but that would be trivial to add.
It can strip column, line or all location information, but we haven't
yet enabled this.

> The only reason you could operate with ABI XML files heavily annotated
> with non-ABI determining information (such as the loc info and
> superfluous and arbitrary names) is having an unique source for the ABI
> info.  That's no longer the case: we are using CTF, the Google chaps are
> using BTF.
>

As mentioned, we haven't yet dared strip source information
completely, it is probably worth keeping at least the file path to
assist in tracking down ABI breaks.

We are not really using BTF, but the code to read it is working and
tested. Unfortunately, BTF format / pahole -J:

- don't do C++
- don't handle global variables properly (implementation)
- model arithmetic types poorly (has improved in the last year)
- have fixed (32-bit mostly) size limits for various things
- flatten multidimensional arrays (implementation choice, not format limitation)

So even on our test suite of small cases, BTF and ABI XML diff reports
for the same code can be very different.

> The above considered, I think we have three options now:
>
> a) To define that canonical ABI XML and write an abistrip tool that does
>    the translation, maybe add --canonical options to the tools that
>    generate ABI XML.  Then use `diff' in the testsuite.
>

There are other abidw options that can sometimes affect XML output
(load all types, etc.). "Canonical" would have to be defined to
include the "right" set of options. However, the very existence of
these options suggests there may not be a unique "right" set.

It's also more than an external tool can do alone, due to type ids, as
mentioned above. And you might spend more time than you like looking
at IR vs XML issues.

One other thing I have considered to help make ABI representations
"more" canonical, is to resolve all typedefs during post-processing.
This has various advantages and disadvantages and I've not yet looked
at the idea in more detail.

>    or
>
> b) To use an external ABI comparison tool in the testsuite, non-textual,
>    that consumes ABI XML.
>

This is the current approach for abidw round-trip and fixed-input
tests within the existing libabigail test suite.

There is no standard for ABI diff output and there's not even
agreement as to what constitutes an ABI difference. abidiff supports
different opinions with arguments like --harmless and different output
formats with arguments like --leaf-changes-only.

We have a separate tool that can diff ABI XML, but it only understands
the C subset. This may be useful for cross-checking where CTF is
involved. There are no knobs (yet?) to control whether something is a
difference or not.

>    or
>
> c) To use the "internal" approach I already suggested in another email,
>    having two different sets of tests: one set to test the front-ends
>    that assume the libabigail comparison algorithm works properly,
>    another set to test the comparison algorithm that uses either
>    hand-written input files or assumes the front-ends work properly.
>

libabigail's IR and XML are not in 1-1 correspondence, perhaps mostly
due to historical reasons, and this affects our confidence w.r.t.
testing. The XML writer does quite a bit of work in determining what
to output and when to output it and the XML reader knows how to merge
definitions of structs that are spread across multiple elements.

Matthias and I discussed this over a year ago when we put together the
tests for the (then) BTF reader and diff tool our intern was working
on. We decided the best thing to do was to take small pairs of files
and compile them with a fixed compiler version and default options to
produce object files.

For XML: Extract ABIs. Then ABI-compare all 4 ways ({.o,.xml}^2).
Verify all outputs (XML and reports) against stored copies (a single
ABI and diff).
For BTF: Extract ABIs. Dump ABI as text. ABI-compare 1 way. Verify all
text outputs against stored copies.

At the time we noticed that using Clang instead of GCC gave different
results for some cases. Since then, we have found bugs in Clang, lack
of DWARF 5 support in various places etc.

> I personally think (c) would be best.

I agree, but it may not be easy to do "properly".

Doing this with multiple compilers, optimisation levels, LTO flavours,
DWARF versions will result in an explosion of cases. Then there is
varying target architecture to properly exercise the toolchains. We
haven't tried any of this, except when debugging problems.

If you would like a nice example that breaks even the 4-way abidiff
comparisons, see
https://sourceware.org/pipermail/libabigail/2020q4/002992.html.

I'm going to spend some time today tidying up our test cases (raw .c
and .cc inputs) for external publication.

A big advantage of small test cases is that it is much easier to spot
when the XML is wrong vs the diff is wrong.

Regards,
Giuliano.
  
Dodji Seketeli Nov. 25, 2021, 10:40 a.m. UTC | #10
Guillermo Martinez via Libabigail <libabigail@sourceware.org> a écrit:

[...]

> On Tuesday, November 23, 2021 9:48:35 AM CST Jose E. Marchesi wrote:
>
> Hello Jose/everybody
>
> Thanks for your comments!, answers below:
>
> The following items summarise steps currently implemented in
> the testsuite for DWARF and CTF readers:
>
> 1) Create corpus using the ELF input file, e.g:
>       *src*/libabigail/tests/data/test-read-ctf/test0
>      - In this step the SUTs are: *the front-end and readers*.
>
> 2) Serialize the corpus object to XML ABI description in output
>     directory:
>      *build*/libabigail_x86_64/tests/output/test-read-ctf/test0.abi
>      - SUT: *writter* using write_corpus function

Right.

> (it doesn't use libxml (IMHO something to change if we want to use in
> the future properties, name space, etc).

I am not sure about this, but hey, the future will tell :-)

>
> 3) Spawn *abidw* tool with ELF input file using --abidiff argument, e.g:
>      abidw --abidiff  --ctf *src*/libabigail/tests/data/test-read-ctf/test0
>
>     Internally abiw works as follow:
>      
>    3.1) Create corpus from ELF input file, e.g:
>             *src*/libabigail/tests/data/test-read-ctf/test0
>     - In this step SUTs: *DWARF/CTF frond-end readers*
>
>    3.2) Serialize the (*first*) corpus object to XML ABI description in 
>           *temp* directory:
>              /tmp/libbigail-xyz
>     - SUTs: ABI writter,
>
>    3.3) Build a (*second*) corpus from this temporary file (*same file!*):
>         - SUTs: *XML reader*.
>
>    3.4) Compute the corpus differences
>               compute_diff(corp, corp2 ..)
>      - SUTs: *comparison algorithm* (diff_context/corpus diff)
>
>        if there are differences return 1 otherwise return 0.
>

Right.

> 4) The return value is read by test-read-ctf and if it's 1 test
>     is marked as *FAILED*
>
> 5) Use a external *diff command* to compare the XML abi input file with
>     the file outputted in the step 2. The return code of the diff command
>     is used to mark the test as SUCCESS or FAILED
>
> So, the abidw doesn't use the expected XML file used in the testsuite, so
> if there are changes on the input ELF or in the libabigail subsystems (readers,
> writer, corpus, etc) we could get false negatives, because it is working with
> itself result as an incoming file, instead of use an expected file.

Actually, this won't be a false negative.  It's a true negative. because
what we want to see with abidw --abidiff is that the abixml file that is
emitted has the same *ABI* as the incoming ELF file.  In other words, we
want to see if the DWARF/CTF, the in-memory IR, and the abixml are all
coherent, so to speak.  The exact output details of the XML itself
(things like spaces or order of type definitions etc) don't matter to us
at that point.  We want those insignificant details of the abixml format
to be able to fluctuate without having the fundamentals of ABI
compatibility in general to be impacted.

However, regardless of abidw --abidiff (which cares about stability of
the ABI representation across DWARF/CTF, in-memory IR and abixml), the
test-read-dwarf.cc harness also wants to detect minutes changes to the
abixml that is emitted by abidw.  This is so that developers are forced
to inspect abixml changes that are due to source code modification of
libabigail before submitting their changes.

This is why we use "diff" to compare the emitted abixml against the
expected/reference one If the emitted one is different because of a new
source code change, but the ABI is stable, we'll just accept that new
change and promote the new abidw output as being the new
reference/expected output.

> I think that we should use the ABI XML reader from the expected file (e.g:
> tests/data/test-read-ctf/test0.abi) to build the corpus to be compared
> with the corpus built with ELF input file (e.g: tests/data/test-read-ctf/test0)
> and in this way replace the external abidw and diff command calls,

Heh.  This is exactly what abidw --abidiff does.  And we want to use
abidw too to, so that the *tool* is tested too.
this also

But as I have explained above, we also want to use 'diff' for a
different level of testing.

[...]

> helps to avoid false positives when XML ABIs files has the same nodes but not
> in the same order.


[...]


On Tuesday, November 23, 2021 9:48:35 AM CST Jose E. Marchesi wrote

>> 2) I am surprised by the fact the CTF reader seems to be working as good
>>    as the DWARF reader re. the testsuite.

Well, we don't know that ;-)

To know that, it's needed to *inspect* the result of abidw --ctf on the
binaries and compare it to what we see in the source code of the binary.

We can also introduce new ctf binaries for abidiff-based tests and
compare their output to their DWARF counter part.

There are going to be differences, I am quite sure of that.  But at
least we'll see what they are.  I am not afraid, though.  I think the
CTF support is super cleanly done.  If there are issues, we'll tackle
them.

This testing work is a critical part of that work.  Many thanks to
Guillermo for handling it!

[...]

Cheers,
  
Guillermo E. Martinez Nov. 25, 2021, 9:03 p.m. UTC | #11
On Thursday, November 25, 2021 4:40:29 AM CST Dodji Seketeli wrote:
> Guillermo Martinez via Libabigail <libabigail@sourceware.org> a écrit:
> 
> [...]
> 
> > On Tuesday, November 23, 2021 9:48:35 AM CST Jose E. Marchesi wrote:
> >
> > Hello Jose/everybody
> >
> > Thanks for your comments!, answers below:
> >
> > The following items summarise steps currently implemented in
> > the testsuite for DWARF and CTF readers:
> >
> > 1) Create corpus using the ELF input file, e.g:
> >       *src*/libabigail/tests/data/test-read-ctf/test0
> >      - In this step the SUTs are: *the front-end and readers*.
> >
> > 2) Serialize the corpus object to XML ABI description in output
> >     directory:
> >      *build*/libabigail_x86_64/tests/output/test-read-ctf/test0.abi
> >      - SUT: *writter* using write_corpus function
> 
> Right.
> 
> > (it doesn't use libxml (IMHO something to change if we want to use in
> > the future properties, name space, etc).
> 
> I am not sure about this, but hey, the future will tell :-)
> 
> >
> > 3) Spawn *abidw* tool with ELF input file using --abidiff argument, e.g:
> >      abidw --abidiff  --ctf *src*/libabigail/tests/data/test-read-ctf/test0
> >
> >     Internally abiw works as follow:
> >      
> >    3.1) Create corpus from ELF input file, e.g:
> >             *src*/libabigail/tests/data/test-read-ctf/test0
> >     - In this step SUTs: *DWARF/CTF frond-end readers*
> >
> >    3.2) Serialize the (*first*) corpus object to XML ABI description in 
> >           *temp* directory:
> >              /tmp/libbigail-xyz
> >     - SUTs: ABI writter,
> >
> >    3.3) Build a (*second*) corpus from this temporary file (*same file!*):
> >         - SUTs: *XML reader*.
> >
> >    3.4) Compute the corpus differences
> >               compute_diff(corp, corp2 ..)
> >      - SUTs: *comparison algorithm* (diff_context/corpus diff)
> >
> >        if there are differences return 1 otherwise return 0.
> >
> 
> Right.
> 
> > 4) The return value is read by test-read-ctf and if it's 1 test
> >     is marked as *FAILED*
> >
> > 5) Use a external *diff command* to compare the XML abi input file with
> >     the file outputted in the step 2. The return code of the diff command
> >     is used to mark the test as SUCCESS or FAILED
> >
> > So, the abidw doesn't use the expected XML file used in the testsuite, so
> > if there are changes on the input ELF or in the libabigail subsystems (readers,
> > writer, corpus, etc) we could get false negatives, because it is working with
> > itself result as an incoming file, instead of use an expected file.
> 
> Actually, this won't be a false negative.  It's a true negative. because
> what we want to see with abidw --abidiff is that the abixml file that is
> emitted has the same *ABI* as the incoming ELF file.  In other words, we
> want to see if the DWARF/CTF, the in-memory IR, and the abixml are all
> coherent, so to speak.  The exact output details of the XML itself
> (things like spaces or order of type definitions etc) don't matter to us
> at that point.  We want those insignificant details of the abixml format
> to be able to fluctuate without having the fundamentals of ABI
> compatibility in general to be impacted.
hmm, in order to probe my assumption of the use of abidw --abidiff in test-read-*
to protect against false negatives I've commented in src/abg-dwarf-reader.cc
the call to ctxt.load_elf_properties, simulating a broken feature(no elf-needed node
in abixml) in dwarf_reader::read_corpus_from_elf so the /tmp/abixml hasn't 
elf-needed node:

<abi-corpus version='2.1' path='/home/byby/oracle/src/libabigail-upstream/tests/data/test-read-dwarf/test0'>
  <elf-function-symbols>
    <elf-symbol name='_ZN3ns03barEiz' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
 ....

after that, as we already know this /tmp/abixml is used to built the second corpus used
by compute_diff function, and as you can guess: no differences will be found. So regressions could
not be detected, because we don't used the expected abixml file: test0.abi, is there where the elf-needed
node was written for example: in a previous version of libabigail.

  <elf-needed>
    <dependency name='libstdc++.so.6'/>
    <dependency name='libm.so.6'/>
    <dependency name='libgcc_s.so.1'/>
    <dependency name='libc.so.6'/>
  </elf-needed>

> However, regardless of abidw --abidiff (which cares about stability of
> the ABI representation across DWARF/CTF, in-memory IR and abixml), the
> test-read-dwarf.cc harness also wants to detect minutes changes to the
> abixml that is emitted by abidw. 
hmm, /tmp/abixml is not used by test-read-dwarf.cc.
> This is so that developers are forced
> to inspect abixml changes that are due to source code modification of
> libabigail before submitting their changes.
 Ok, agree.
> This is why we use "diff" to compare the emitted abixml against the
> expected/reference one If the emitted one is different because of a new
> source code change, but the ABI is stable, we'll just accept that new
> change and promote the new abidw output as being the new
> reference/expected output.
Yes, but those differences found by "diff" could be there and it doesn't mean
changes in the libabigail source code nor differences between the abixml
file generated from the ELF input object and the expected abixml file. 
I found weird behaviour running CTF testsuite (test-PR26568-1-ctf.o.abi):

https://sourceware.org/pipermail/libabigail/2021q4/003893.html

> > I think that we should use the ABI XML reader from the expected file (e.g:
> > tests/data/test-read-ctf/test0.abi) to build the corpus to be compared
> > with the corpus built with ELF input file (e.g: tests/data/test-read-ctf/test0)
> > and in this way replace the external abidw and diff command calls,
> 
> Heh.  This is exactly what abidw --abidiff does.  And we want to use
> abidw too to, so that the *tool* is tested too.
> this also
> 
> But as I have explained above, we also want to use 'diff' for a
> different level of testing.
> 
> [...]
> 
> > helps to avoid false positives when XML ABIs files has the same nodes but not
> > in the same order.
> 
> 
> [...]
> 
> 
> On Tuesday, November 23, 2021 9:48:35 AM CST Jose E. Marchesi wrote
> 
> >> 2) I am surprised by the fact the CTF reader seems to be working as good
> >>    as the DWARF reader re. the testsuite.
> 
> Well, we don't know that ;-)
> 
> To know that, it's needed to *inspect* the result of abidw --ctf on the
> binaries and compare it to what we see in the source code of the binary.
This is exactly what I did :-)  and also I execute abidw  using same source
code but compiled with -g option and comparing common information
in the nodes: elf-symbol, *-decl, function-type, data-member, etc. and
common nodes properties: name, path, size*, id, etc. in ~19 test sent in
patch v2 they looks good! (those files now are the expected result for
CTF testsuite). 

The pending work (in which I'm doing progress) is translate the valid CTF
testcases from tests/data/test-read-dwarf/*cc files to c files and add to
testusite, also I'm planning to extract other test from the CTF specs:
   http://www.esperi.org.uk/~oranix/ctf/ctf-spec.pdf

> We can also introduce new ctf binaries for abidiff-based tests and
> compare their output to their DWARF counter part.
Ok,
> There are going to be differences, I am quite sure of that.  But at
> least we'll see what they are.  I am not afraid, though.  I think the
> CTF support is super cleanly done.  If there are issues, we'll tackle
> them.
> 
> This testing work is a critical part of that work.  Many thanks to
> Guillermo for handling it!
No, thanks to you Dodji for your comments, they are very useful to follow the
right direction in the CTF test harness! :-).  
> [...]
> 
> Cheers,

Guillermo
  
Ben Woodard Nov. 25, 2021, 9:56 p.m. UTC | #12
> On Nov 25, 2021, at 1:34 AM, Giuliano Procida <gprocida@google.com> wrote:
> 
> Hi Ben.
> 
>> On Wed, 24 Nov 2021 at 19:10, Ben Woodard via Libabigail
>> <libabigail@sourceware.org> wrote:
>> 
>> 
>> 
>>>> On Nov 24, 2021, at 8:36 AM, Dodji Seketeli <dodji@seketeli.org> wrote:
>>> 
>>> Hello,
>>> 
>>> [...]
>>> 
>>> Thanks for working on this.  Nice patch, by the way!  I like its
>>> direction.
>>> 
>>> I have a few comments and I believe that when they are addressed, we'll
>>> be able to apply the patch.
>>> 
>>> [...]
>>> 
>>>> Dependencies/limitations:
>>>> 
>>>> * It was worked on the top of the following patches:
>>>> https://sourceware.org/pipermail/libabigail/2021q4/003853.html
>>>> 
>>>> * Some CTF tests were *disabled* because it generates the XML ABI
>>>> corpus with *same information* but the XML nodes *are not* always
>>>> in the *same order*, so using diff command fails. Details here:
>>>> https://sourceware.org/pipermail/libabigail/2021q4/003824.html
>>> 
>>> In those cases where the abixml file generated from CTF is different
>>> from the one generated from DWARF, I think we should have two
>>> different reference abixml files to diff against.  No CTF test should
>>> be disabled, I think.
>> 
>> Here is a somewhat deeper question that I think needs to be considered. I’ve generally referred to it as “DWARF Idioms” but this email makes me think that it is even larger than that.
>> 
>> For my work, I need libabigail to generate an abstract notion of the ABI corpus. How it constructs that abstract notion of the ABI needs to be independent of the producer. Think of it this way, say we take the same compiler and have it compile the same library producing both CTF and DWARF, the ABI of the library doesn’t change. Since it is literally the same object, the program text is same. Therefore the ABI is unquestionably the the same. Any difference reported by libabigail therefore is a problem with libabigail. It is not taking the source material and abstracting it enough into the ABI artifacts to separate the artifacts from the implementation.
>> 
>> So I kind of believe that we need to look more deeply into WHY the CTF and DWARF are not comparing as equivalent and begin the process of filing the compiler bugs when we need to, and doing what is necessary to abstract the ABI from the source material that libabigail used to construct its IR of the ABI corpus from.
>> 
>> So, I must say that I disagree with both dodji’s approach here and to a lesser extent Guillermo’s approach of disabling the tests. I think that the tests where the CTF doesn’t match the DWARF should be investigated and when necessary marked “xfail” with a note citing their individual cause.
>> 
>> I think that what we need to work towards is:
>> abidw produces the same output (or more precisely libabigail produces the same IR) whether you compile with -gdwarf-3 -gdwarf-4 -gdwarf-5 -gsplit-dwarf -gctf
>> also for the most part the ABI should not change between compiler versions. There may be a few cases that we need to look into where the compiler actually breaks ABI and of course libabigail should flag those but I would assert that libabigail needs to abstract its IR of the ABI enough that compiler version changes that don’t actually change the ABI of the ELF object are not reported as ABI breaks. It currently does pretty well at this at the moment.
>> Then once that foundation is built, being able to abstract the ABI IR enough that differences in toolchains e.g. LLVM vs GCC are not flagged as changes in the object’s ABI. This is important to provide people with a tool that will allow them to mix toolchains within a project to achieve optimal code.
>> 
> 
> This almost sounds like a hierarchy of needs:
> 
> ABI tools produce identical output for identical inputs no matter
> which platform
Obviously since the platform specific ABI is different between different platforms, I expect changes between ABI there. When you talk about platform independence it sort of sounds like you are thinking of the ABI changes caused by API changes or library implementation changes. I’m not as concerned with those.
> they run or which compiler / library was used to build
> them.
> - we have seen libabigail hash table trouble when built with Clang

Just as a note, I have not observed this.
I have observed a couple of cases where libabigail has problems with aarch64 binaries but I haven’t checked that those continue to occur with our latest 2.1  branch. 
> - we don't support BTF byte sex conversion (the format is I think target-endian)
Yeah this doesn’t concern me.
> 
> each platform / compiler / optimisation / LTO / DWARF combination
> generates object code that appears ABI-stable (varying just the ABI
> tooling)
This is where it starts getting interesting to me. 
Within each platform:
Due to all the testing that I’ve done already and fed back to Dodji pretty much every DWARF combination already works. Yea! I put a lot of work into making sure that this does work and continues to work. That is why I want to hold that line for CTF. If the ABI of the ELF doesn’t change, I don’t want libabigail to report that it is different just because the information about the ABI was gleaned from CTF rather than from DWARF.

I need to know if some compiler flag or compile time option changes the ABI of the resulting binary so that I know if they can be mixed and matched. One of the first things I learned working on this a couple of decades ago was that there was no way within the normal library versioning system to represent different compile time options and handling micro architectural optimizations is an art that most library authors and their build systems don’t handle very gracefully. An obvious example could be if a parameter is in some way is defined at compile time to be the microarchitecture’s largest vector type. Then the API implicitly changes at compile time leading to an ABI break.

When optimization changes the ABI, I want to know about that. For normal libraries, so far it seems like the various optimizations do not really change the exported ABI. I do see it a lot more on object files before they are linked into exported interfaces.

LTO with libraries is interesting. So far, I haven’t tested it as extensively as it needs to be, but with the testing that I have done, I haven’t seen any problems with the OS provided system libraries.

The big problem that Dodji and I have not yet worked out how to solve is comparing the DWARF produced by one compiler to the DWARF produced by another compiler. The problem used to be much bigger but really by the time we land this functionality, there really only be two compilers that I care about LLVM and GCC. I used to have to worry about intel, IBM’s XL series, and other compilers like Portland Group’s but those have kind of fallen away. This is where I strongly believe that the libabigail’s corpus, the IR, should be enough of an abstraction of the ELF file’s ABI that the idioms that show up in different compiler’s DWARF idioms should be masked away. I feel like CTF because it is just a different representation of the same information as found in DWARF should be the same way. I think that the kinds of changes to the underlying data structures of libabigail’s IR that would allow CTF’s representation and DWARF’s representation to evaluate as the same are the same kinds of changes which when expanded could allow different compiler’s DWARF idioms to evaluate the same. 

This idea is not new. It kind of is at the historic root of libabigail. Before Dodji even came work at Red Hat, I was talking about this problem with Benjamin DeKosnik and he kind of pointed me back to Uli Drepper who had a tool which compared DWARF to DWARF. The big problem with that approach though was that it was too sensitive to changes in the compilers. Even bug fix releases of a particular compiler would disrupt the comparison algorithm in Uli’s old tool. The brilliance of Dodji’s approach which has gotten it this far is the IR. The conversion from DWARF to the IR where the comparison is actually done abstracts the ABI information enough that you can compare ELF across compiler versions. Unfortunately, the IR still contains enough artifacts of the original datasource, and there are enough unrecognized bugs or implementation differences in the compilers that comparisons between compilers still isn’t possible.

Making the IR the same or at least comparable whether the data source happens to be CTF or DWARF sounds like first step in finding and resolving the places where the idioms of the original data source creep into the IR making it a reflection of the compiler’s specific implementation rather than a representation of the ABI of the object being looked at.
> ...
> each platform's object code is ABI-equivalent (varying all the other things)
> 
> And then do the same for C++, Rust etc.

I work in HPC. The range that I really end up worrying about really is limited to C, C++, and Fortran. C really isn’t a problem. Most of the interesting challenges end up being with C++ but we do have some Fortran issues out there.

> 
> So far I've seen apparent ABI issues due to all the above things,
> except possibly -Olevel, and seen bugs fixed in LLVM, elfutils,
> dwarves and libabigail.
> 
I also think that we will also find a few places where the various ABI standards need to be tightened up.

> It would be useful to prioritise your needs. Which stability axes
> bring most value? At a rough guess, we'd want varying optimisation
> levels and LTO to be least likely things to cause ABI differences,
> maybe then DWARF version, followed by compiler then standard library?
> 
> It would also be useful to try to limit the combinations that will be
> supported (nothing too old or obscure, for example). Is anyone still
> using DWARF 3?

I think that Dodji and I (mostly Dodji — I filed lots of bugs) have worked out the issues with different DWARF levels along the way. That doesn’t seem to be a problem.

-ben

> 
> Giuliano.
> 
>> -ben
>> 
>>> 
>>> So:
>>> 
>>> This:
>>> 
>>>  {
>>>    "data/test-read-dwarf/test0",
>>>    "",
>>>    "",
>>>    SEQUENCE_TYPE_ID_STYLE,
>>>    "data/test-read-dwarf/test0.abi",
>>>    "output/test-read-dwarf/test0.abi"
>>>  },
>>> 
>>> would be changed into:
>>> 
>>>  {
>>>    "data/test-read-common/test0",
>>>    "",
>>>    "",
>>>    SEQUENCE_TYPE_ID_STYLE,
>>>    "data/test-read-dwarf/test0.abi",
>>>    "output/test-read-dwarf/test0.abi"
>>>  },
>>> 
>>> For the DWARF test entry in test-read-dwarf.cc, and it would be
>>> changed into:
>>> 
>>>  {
>>>    "data/test-read-common/test0",
>>>    "",
>>>    "",
>>>    SEQUENCE_TYPE_ID_STYLE,
>>>    "data/test-read-ctf/test0.abi",
>>>    "output/test-read-ctf/test0.abi"
>>>  },
>>> 
>>> for the CTF test netry in test-read-ctf.cc.
>>> 
>>> By the way, I am seeing entries like this in test-read-ctf.cc:
>>> 
>>>> +    "data/test-read-common/test3.so",
>>>> +    "",
>>>> +    "",
>>>> +    SEQUENCE_TYPE_ID_STYLE,
>>>> +    "data/test-read-common/test3-ctf.so.abi",
>>>> +    "output/test-read-common/test3-ctf.so.abi"
>>> 
>>> Here this entry does exactly what I am suggesting, even if
>>> test3-ctf.so.abi is stored in data/test-read-common.
>>> 
>>> So where exactly is the CTF test disabled?
>>> 
>>> [...]
>>> 
>>> 
>>>> diff --git a/tests/test-read-common.cc b/tests/test-read-common.cc
>>> 
>>> [...]
>>> 
>>>> +
>>>> +namespace abigail
>>>> +{
>>>> +namespace tests
>>>> +{
>>>> +namespace read_common
>>>> +{
>>> 
>>> Because this file now contains an API definition that is to be used be
>>> some tests, every single function of the file should be documented
>>> using doxygen comments, just like we have in src/abg-*.cc files.
>>> 
>>> For instance:
>>> 
>>>> +
>>>> +test_task::test_task(const InOutSpec &s,
>>>> +                     string& a_out_abi_base,
>>>> +                     string& a_in_elf_base,
>>>> +                     string& a_in_abi_base)
>>> 
>>> This function should be fully doxygen-documented.
>>> 
>>>> +    : is_ok(true),
>>>> +      spec(s),
>>>> +      out_abi_base(a_out_abi_base),
>>>> +      in_elf_base(a_in_elf_base),
>>>> +      in_abi_base(a_in_abi_base)
>>>> +  {}
>>>> +
>>>> +bool
>>>> +test_task::serialize_corpus(const string& out_abi_path,
>>>> +                            corpus_sptr corp)
>>> 
>>> Likewise.
>>> 
>>>> +{
>>>> +  ofstream of(out_abi_path.c_str(), std::ios_base::trunc);
>>>> +  if (!of.is_open())
>>>> +    {
>>>> +       error_message = string("failed to read ") + out_abi_path + "\n";
>>>> +       return false;
>>>> +    }
>>>> +
>>>> +  write_context_sptr write_ctxt
>>>> +      = create_write_context(corp->get_environment(), of);
>>>> +  set_type_id_style(*write_ctxt, spec.type_id_style);
>>>> +  is_ok = write_corpus(*write_ctxt, corp, /*indent=*/0);
>>>> +  of.close();
>>>> +
>>>> +  return true;
>>>> +}
>>>> +
>>>> +bool
>>>> +test_task::run_abidw(const string& extargs)
>>> 
>>> Likewise.
>>> 
>>>> +{
>>>> +  string abidw = string(get_build_dir()) + "/tools/abidw";
>>>> +  string drop_private_types;
>>>> +  if (!in_public_headers_path.empty())
>>>> +    drop_private_types += "--headers-dir " + in_public_headers_path +
>>>> +      " --drop-private-types";
>>>> +  string cmd = abidw + " " + drop_private_types + " --abidiff " + extargs +
>>>> +   in_elf_path;
>>>> +  if (system(cmd.c_str()))
>>>> +    {
>>>> +      error_message = string("ABIs differ:\n")
>>>> +        + in_elf_path
>>>> +        + "\nand:\n"
>>>> +        + out_abi_path
>>>> +        + "\n";
>>>> +
>>>> +      return false;
>>>> +    }
>>>> +
>>>> +  return true;
>>>> +}
>>>> +
>>>> +bool
>>>> +test_task::run_diff()
>>> 
>>> Likewise.
>>> 
>>>> +{
>>>> +  set_in_abi_path();
>>>> +  string cmd = "diff -u " + in_abi_path + " " + out_abi_path;
>>>> +  if (system(cmd.c_str()))
>>>> +    {
>>>> +      error_message = string("ABIs differ:\n")
>>>> +        + in_abi_path
>>>> +        + "\nand:\n"
>>>> +        + out_abi_path
>>>> +        + "\n";
>>>> +
>>>> +      return false;
>>>> +    }
>>>> +
>>>> +  return true;
>>>> +}
>>>> +
>>>> +void
>>>> +display_usage(const string& prog_name, ostream& out)
>>> 
>>> Likewise.
>>> 
>>>> +{
>>>> +  emit_prefix(prog_name, out)
>>>> +    << "usage: " << prog_name << " [options]\n"
>>>> +    << " where options can be: \n"
>>>> +    << "  --help|-h  display this message\n"
>>>> +    << "  --no-parallel execute testsuite is a sigle thread\n"
>>>> +  ;
>>>> +}
>>>> +
>>>> +bool
>>>> +parse_command_line(int argc, char* argv[], options& opts)
>>> 
>>> Likewise.
>>> 
>>>> +{
>>>> +  for (int i = 1; i < argc; ++i)
>>>> +    {
>>>> +      if (!strcmp(argv[i], "--no-parallel"))
>>>> +        opts.parallel = false;
>>>> +      else if (!strcmp(argv[i], "--help")
>>>> +               || !strcmp(argv[i], "--h"))
>>>> +        return false;
>>>> +      else
>>>> +        {
>>>> +          if (strlen(argv[i]) >= 2 && argv[i][0] == '-' && argv[i][1] == '-')
>>>> +            opts.wrong_option = argv[i];
>>>> +          return false;
>>>> +        }
>>>> +    }
>>>> +
>>>> +  return true;
>>>> +}
>>>> +
>>>> +bool
>>>> +run_tests(const size_t num_tests, const InOutSpec* specs,
>>>> +          const options& opts, create_new_test new_test)
>>> 
>>> Likewise.
>>> 
>>>> +{
>>> 
>>> [...]
>>> 
>>> 
>>>> diff --git a/tests/test-read-common.h b/tests/test-read-common.h
>>> 
>>> [...]
>>> 
>>>> +/// This is an aggregate that specifies where a test shall get its
>>>> +/// input from, and where it shall write its ouput to.
>>>> +struct InOutSpec
>>>> +{
>>>> +  const char* in_elf_path;
>>>> +  const char* in_suppr_spec_path;
>>>> +  const char* in_public_headers_path;
>>>> +  type_id_style_kind type_id_style;
>>>> +  const char* in_abi_path;
>>>> +  const char* out_abi_path;
>>>> +};// end struct InOutSpec
>>>> +
>>>> +/// The task that peforms the tests.
>>>> +struct test_task : public abigail::workers::task
>>>> +{
>>>> +  bool is_ok;
>>>> +  InOutSpec spec;
>>>> +  string error_message;
>>>> +  string out_abi_base;
>>>> +  string in_elf_base;
>>>> +  string in_abi_base;
>>>> +
>>>> +  string in_elf_path;
>>>> +  string in_abi_path;
>>>> +  string in_suppr_spec_path;
>>>> +  string in_public_headers_path;
>>>> +  string out_abi_path;
>>>> +
>>>> +  void
>>>> +  set_in_elf_path()
>>> 
>>> Please doxygen-document this function.
>>> 
>>>> +  {
>>>> +    in_elf_path = in_elf_base + spec.in_elf_path;
>>>> +  }
>>>> +
>>>> +  void
>>>> +  set_in_suppr_spec_path()
>>> 
>>> Likewise.
>>> 
>>>> +  {
>>>> +    if (spec.in_suppr_spec_path)
>>>> +      in_suppr_spec_path = in_elf_base + spec.in_suppr_spec_path;
>>>> +    else
>>>> +      in_suppr_spec_path.clear();
>>>> +  }
>>>> +
>>>> +  void
>>>> +  set_in_public_headers_path()
>>> 
>>> Likewise.
>>> 
>>>> +  {
>>>> +    if (spec.in_public_headers_path)
>>>> +      in_public_headers_path = spec.in_public_headers_path;
>>>> +    if (!in_public_headers_path.empty())
>>>> +      in_public_headers_path = in_elf_base + spec.in_public_headers_path;
>>>> +  }
>>>> +
>>>> +  bool
>>>> +  set_out_abi_path()
>>> 
>>> Likewise.
>>> 
>>>> +  {
>>>> +    out_abi_path = out_abi_base + spec.out_abi_path;
>>>> +    if (!abigail::tools_utils::ensure_parent_dir_created(out_abi_path))
>>>> +      {
>>>> +          error_message =
>>>> +            string("Could not create parent directory for ") + out_abi_path;
>>>> +          return false;
>>>> +      }
>>>> +    return true;
>>>> +  }
>>>> +
>>>> +  void
>>>> +  set_in_abi_path()
>>> 
>>> Likewise.
>>> 
>>>> +  {
>>>> +    in_abi_path = in_abi_base + spec.in_abi_path;
>>>> +  }
>>>> +
>>> 
>>> [...]
>>> 
>>>> +  test_task(const InOutSpec &s,
>>>> +            string& a_out_abi_base,
>>>> +            string& a_in_elf_base,
>>>> +            string& a_in_abi_base);
>>>> +  bool
>>>> +  serialize_corpus(const string& out_abi_path,
>>>> +                   corpus_sptr corp);
>>>> +  bool
>>>> +  run_abidw(const string& extargs = "");
>>>> +
>>>> +  bool
>>>> +  run_diff();
>>>> +
>>>> +  virtual
>>>> +  ~test_task()
>>>> +  {}
>>>> +
>>>> +}; // end struct test_task
>>>> +
>>>> +typedef shared_ptr<test_task> test_task_sptr;
>>>> +
>>>> +struct options
>>>> +{
>>> 
>>> Please doxygen-document this struct.
>>> 
>>>> +  string        wrong_option;
>>>> +  bool          parallel;
>>>> +
>>>> +  options()
>>>> +    : parallel(true)
>>>> +  {}
>>>> +
>>>> +  ~options()
>>>> +  {
>>>> +  }
>>>> +};
>>> 
>>> [...]
>>> 
>>>> diff --git a/tests/test-read-ctf.cc b/tests/test-read-ctf.cc
>>> 
>>> [...]
>>> 
>>> 
>>>> +test_task_ctf::test_task_ctf(const InOutSpec &s,
>>>> +                             string& a_out_abi_base,
>>>> +                             string& a_in_elf_base,
>>>> +                             string& a_in_abi_base)
>>> 
>>> Please doxygen-document this function.
>>> 
>>>> +        : test_task(s, a_out_abi_base, a_in_elf_base, a_in_abi_base)
>>>> +  {}
>>>> +
>>> 
>>> [...]
>>> 
>>>> +static test_task*
>>>> +new_task(const InOutSpec* s, string& a_out_abi_base,
>>>> +         string& a_in_elf_base, string& a_in_abi_base)
>>> 
>>> Please doxygen-document this function.
>>> 
>>>> +{
>>>> +  return new test_task_ctf(*s, a_in_abi_base,
>>> 
>>> This 'a_in_abi_base' should be a_out_abi_base.
>>> 
>>>> +                           a_in_elf_base, a_in_abi_base);
>>>> +}
>>> 
>>> [...]
>>> 
>>> 
>>>> diff --git a/tests/test-read-dwarf.cc b/tests/test-read-dwarf.cc
>>> 
>>> [...]
>>> 
>>> 
>>>> +static test_task*
>>>> +new_task(const InOutSpec* s, string& a_out_abi_base,
>>>> +         string& a_in_elf_base, string& a_in_abi_base)
>>> 
>>> Please doxygen-document this function.
>>> 
>>>> +{
>>>> +  return new test_task_dwarf(*s, a_in_abi_base,
>>> 
>>> This 'a_in_abi_base' should be a_out_abi_base.
>>> 
>>>> +                             a_in_elf_base, a_in_abi_base);
>>>> +}
>>>> 
>>>> int
>>>> main(int argc, char *argv[])
>>>> {
>>>>  bool no_parallel = false;
>>> 
>>> This variable is not unused.
>>> 
>>> 
>>> Thanks for working on this.  It's really appreciated!
>>> 
>>> [...]
>>> 
>>> Cheers,
>>> 
>>> --
>>>              Dodji
>>> 
>> 
>
  
Dodji Seketeli Nov. 26, 2021, 10:02 a.m. UTC | #13
Hey,

Dodji Seketeli <dodji@seketeli.net> a écrit:

>> Actually, this won't be a false negative.  It's a true negative. because
>> what we want to see with abidw --abidiff is that the abixml file that is
>> emitted has the same *ABI* as the incoming ELF file.  In other words, we
>> want to see if the DWARF/CTF, the in-memory IR, and the abixml are all
>> coherent, so to speak.  The exact output details of the XML itself
>> (things like spaces or order of type definitions etc) don't matter to us
>> at that point.  We want those insignificant details of the abixml format
>> to be able to fluctuate without having the fundamentals of ABI
>> compatibility in general to be impacted.

Guillermo Martinez <guillermo.e.martinez@oracle.com> a écrit:

> hmm, in order to probe my assumption of the use of abidw --abidiff in test-read-*
> to protect against false negatives I've commented in src/abg-dwarf-reader.cc
> the call to ctxt.load_elf_properties, simulating a broken feature(no elf-needed node
> in abixml) in dwarf_reader::read_corpus_from_elf so the /tmp/abixml hasn't 
> elf-needed node:
>
> <abi-corpus version='2.1' path='/home/byby/oracle/src/libabigail-upstream/tests/data/test-read-dwarf/test0'>
>   <elf-function-symbols>
>     <elf-symbol name='_ZN3ns03barEiz' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
>  ....
>
> after that, as we already know this /tmp/abixml is used to built the second corpus used
> by compute_diff function, and as you can guess: no differences will be found. So regressions could
> not be detected, because we don't used the expected abixml file: test0.abi, is there where the elf-needed
> node was written for example: in a previous version of libabigail.
>
>   <elf-needed>
>     <dependency name='libstdc++.so.6'/>
>     <dependency name='libm.so.6'/>
>     <dependency name='libgcc_s.so.1'/>
>     <dependency name='libc.so.6'/>
>   </elf-needed>

I don't think your experiment invalidates what I was trying to say.
Sorry if was not clear :-(

In your experiment above, the ELF/DWARF reader doesn't load these
elf-needed properties.  So the resulting in-memory IR won't represent
those properties.  So the serialization of that IR into abixml won't
represent those properties either.  So comparing the ABI of the
serialized abixml against the ABI of the input binary (none of which
have the elf-needed properties) won't show any ABI change.  That is
expected.  On the contrary, you are showing that the in-memory IR
resulting from the reading of the ELF/DWARF matches the in-memory IR
resulting from the abixml.  And that is precisely what "abidw --abidiff"
is designed to ensure.

Said otherwise, the intent of the "abidw --abidiff" command is to verify
that the in-memory IR built from the input binary is congruent with the
in-memory IR built from its serialized abixml form.

In other words, if we 'abidiff' the in-memory representation of the
DWARF against the in-memory representation of the abixml coming from the
DWARF, we should get the empty set.  We are trying to ensure that there
is no "unintended information loss" between WHAT WE SEE from the ELF
binary and what we see from the abixml representation.

I hope this helps.  But if I am still missing something, please do not
hesitate to educate me.

Thanks!

[...]

Cheers,
  
Dodji Seketeli Nov. 26, 2021, 10:27 a.m. UTC | #14
Hello,

[...]

On Nov 24, 2021, at 8:36 AM, Dodji Seketeli <dodji@seketeli.org> wrote:

>> In those cases where the abixml file generated from CTF is different
>> from the one generated from DWARF, I think we should have two
>> different reference abixml files to diff against.  No CTF test should
>> be disabled, I think.

Ben Woodard <woodard@redhat.com> a écrit:


> Here is a somewhat deeper question that I think needs to be
> considered. I’ve generally referred to it as “DWARF Idioms” but this
> email makes me think that it is even larger than that.
>
> For my work, I need libabigail to generate an abstract notion of the
> ABI corpus. How it constructs that abstract notion of the ABI needs to
> be independent of the producer. Think of it this way, say we take the
> same compiler and have it compile the same library producing both CTF
> and DWARF, the ABI of the library doesn’t change. Since it is
> literally the same object, the program text is same. Therefore the ABI
> is unquestionably the the same. Any difference reported by libabigail
> therefore is a problem with libabigail.

In theory, I think what you say makes total sense.

In practice however, there seems to be some annoying limits to what we
can do right now.

For instance, right now, CTF doesn't include source location (file name,
line numbers) information.

So by default, the output details of abidiff will be different at least
because in one case it shows line information and in other other it
doesn't.  Of course we can work harder to avoid showing line information
in all abidiff tests, but then it means that the particular feature of
handling line information coming from DWARF won't be tested.

So yeah, there are details like that.  I am not sure how much of these
we have, but if I've found one, I can't say they aren't others.

Of course, the "general representation" (whatever that means) of the ABI
represented by DWARF or CTF should not be different.  But the exact
textual output of abidiff or abidw is not necessarily going to be the
same, "a priori".

> It is not taking the source material and abstracting it enough into
> the ABI artifacts to separate the artifacts from the implementation.

Right.  I'd argue that the problem wasn't "apparent" when we had only
DWARF to care about.  Now it is.  So, I think now we are starting to
have the means to see the issue, rather than just speculate in the
abstract.  So for cases where it makes sense, I think the "abstraction
level" of the IR can be ameliorated.

> So I kind of believe that we need to look more deeply into WHY the CTF
> and DWARF are not comparing as equivalent and begin the process of
> filing the compiler bugs when we need to, and doing what is necessary
> to abstract the ABI from the source material that libabigail used to
p> construct its IR of the ABI corpus from.

Agreed.

> So, I must say that I disagree with both dodji’s approach here and to
> a lesser extent Guillermo’s approach of disabling the tests. I think
> that the tests where the CTF doesn’t match the DWARF should be
> investigated and when necessary marked “xfail” with a note citing
> their individual cause.

Well, lemme quote what I said:

On Nov 24, 2021, at 8:36 AM, Dodji Seketeli <dodji@seketeli.org> wrote:

>> In those cases where the abixml file generated from CTF is different
>> from the one generated from DWARF, I think we should have two
>> different reference abixml files to diff against.  No CTF test should
>> be disabled, I think.

I said explicitly that no test should be disabled.

Incidentally, by providing the two abixml files (DWARF and CTF) at least
we can see what the change are and later work on reducing those changes
if it makes sense.

> I think that what we need to work towards is: abidw produces the same
> output (or more precisely libabigail produces the same IR) whether you
> compile with -gdwarf-3 -gdwarf-4 -gdwarf-5 -gsplit-dwarf -gctf also
> for the most part the ABI should not change between compiler
> versions. There may be a few cases that we need to look into where the
> compiler actually breaks ABI and of course libabigail should flag
> those but I would assert that libabigail needs to abstract its IR of
> the ABI enough that compiler version changes that don’t actually
> change the ABI of the ELF object are not reported as ABI breaks. It
> currently does pretty well at this at the moment.  Then once that
> foundation is built, being able to abstract the ABI IR enough that
> differences in toolchains e.g. LLVM vs GCC are not flagged as changes
> in the object’s ABI. This is important to provide people with a tool
> that will allow them to mix toolchains within a project to achieve
> optimal code.

In an ideal world, of course.  I am not opposed to trying our best ;-)

Cheers,
  
Dodji Seketeli Nov. 26, 2021, 11:23 a.m. UTC | #15
Hello,

[...]

On Nov 24, 2021, at 8:36 AM, Dodji Seketeli <dodji@seketeli.org> wrote

>> So where exactly is the CTF test disabled?

Guillermo Martinez <guillermo.e.martinez@oracle.com> a écrit:

> I remove those test entries, so the possible problem detected using external diff
> command in CTF is, for instance, in: test-read-common/test-PR26568-1-ctf.o.abi,
> the first time that runtestreadctf is executed an abixml file  is generated:
>
> ...
>     <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
>       <data-member access='public' layout-offset-in-bits='0'>
>         <var-decl name='x' type-id='type-id-4' visibility='default'/>
>       </data-member>
>     </class-decl>
>     <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-5'>
>       <data-member access='public' layout-offset-in-bits='0'>
>         <var-decl name='y' type-id='type-id-6' visibility='default'/>
>       </data-member>
>     </class-decl>
>
> and this is second execution:
> ...
>     <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-5'>
>       <data-member access='public' layout-offset-in-bits='0'>
>         <var-decl name='y' type-id='type-id-6' visibility='default'/>
>       </data-member>
>     </class-decl>
>     <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
>       <data-member access='public' layout-offset-in-bits='0'>
>         <var-decl name='x' type-id='type-id-4' visibility='default'/>
>       </data-member>
>     </class-decl>
>
> As we can see both abixml files  have *same nodes information* but the nodes
> are in a different order, so the test should be marked as passed, however using
> the external diff command the test fails. so my question is should we rely in diff
> command to compare the corpus of the ELF input files (abixml files)?

So, you see here, this is exactly why we use the diff tool IN ADDITION
to abidiff (which only look for ABI changes).

Here, you see that two invocations of abidw is yielding possibly two
*DIFFERENT* abixml files.  They are different because some struct type
definition come out in different order.

Why?

This is because we have two struct types that have the same (empty) name
and yet they are different.  The abixml writer sorts types using their
names, somehow.  So some times, one type comes first; some times, it's
the other.

Let's look at the issue a bit deeper.

These are anonymous struct.

For various reasons, we need to designate types in the Libabigail
system.  So every single type needs to be given a name.  Even anonymous
types.

Most of the time, in C, anonymous types are named using typedefs.  E.g:

typedef struct
{
  int x;
} struct_name;

"typedef struct_name" is the 'naming typedef' of the struct type.  It's
used to name it.  That's how it's designated to be later used.

The libabigail IR has the decl_base::set_naming_typedef() function to
set naming typedefs on 

If you look at the code of the dwarf reader, in the function
build_typedef_type, near the end, you'll see that it uses the
set_naming_typedef method to set the naming typedef of the underlying
anonymous class (or struct) it sees.

Once you've done that, the struct will be represented in the abixml file
as having the name "struct_name".  And your problem will be solved, I
think.

There are other techniques used in the dwarf-reader to handle anonymous
types that are not named by a typedef.  But those are super rare,
especially in C.  So I hope that using naming typedef should be good
enough for a start, in practise.

It's precisely to detect cases like this that the "diff" tool is used.

I hope this helps.

[...]

Cheers,
  
Jose E. Marchesi Nov. 26, 2021, 1:01 p.m. UTC | #16
> Hello,
>
> [...]
>
> On Nov 24, 2021, at 8:36 AM, Dodji Seketeli <dodji@seketeli.org> wrote
>
>>> So where exactly is the CTF test disabled?
>
> Guillermo Martinez <guillermo.e.martinez@oracle.com> a écrit:
>
>> I remove those test entries, so the possible problem detected using external diff
>> command in CTF is, for instance, in: test-read-common/test-PR26568-1-ctf.o.abi,
>> the first time that runtestreadctf is executed an abixml file  is generated:
>>
>> ...
>>     <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
>>       <data-member access='public' layout-offset-in-bits='0'>
>>         <var-decl name='x' type-id='type-id-4' visibility='default'/>
>>       </data-member>
>>     </class-decl>
>>     <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-5'>
>>       <data-member access='public' layout-offset-in-bits='0'>
>>         <var-decl name='y' type-id='type-id-6' visibility='default'/>
>>       </data-member>
>>     </class-decl>
>>
>> and this is second execution:
>> ...
>>     <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-5'>
>>       <data-member access='public' layout-offset-in-bits='0'>
>>         <var-decl name='y' type-id='type-id-6' visibility='default'/>
>>       </data-member>
>>     </class-decl>
>>     <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
>>       <data-member access='public' layout-offset-in-bits='0'>
>>         <var-decl name='x' type-id='type-id-4' visibility='default'/>
>>       </data-member>
>>     </class-decl>
>>
>> As we can see both abixml files  have *same nodes information* but the nodes
>> are in a different order, so the test should be marked as passed, however using
>> the external diff command the test fails. so my question is should we rely in diff
>> command to compare the corpus of the ELF input files (abixml files)?
>
> So, you see here, this is exactly why we use the diff tool IN ADDITION
> to abidiff (which only look for ABI changes).
>
> Here, you see that two invocations of abidw is yielding possibly two
> *DIFFERENT* abixml files.  They are different because some struct type
> definition come out in different order.
>
> Why?
>
> This is because we have two struct types that have the same (empty) name
> and yet they are different.  The abixml writer sorts types using their
> names, somehow.  So some times, one type comes first; some times, it's
> the other.
>
> Let's look at the issue a bit deeper.
>
> These are anonymous struct.
>
> For various reasons, we need to designate types in the Libabigail
> system.  So every single type needs to be given a name.  Even anonymous
> types.
>
> Most of the time, in C, anonymous types are named using typedefs.  E.g:
>
> typedef struct
> {
>   int x;
> } struct_name;
>
> "typedef struct_name" is the 'naming typedef' of the struct type.  It's
> used to name it.  That's how it's designated to be later used.
>
> The libabigail IR has the decl_base::set_naming_typedef() function to
> set naming typedefs on 
>
> If you look at the code of the dwarf reader, in the function
> build_typedef_type, near the end, you'll see that it uses the
> set_naming_typedef method to set the naming typedef of the underlying
> anonymous class (or struct) it sees.
>
> Once you've done that, the struct will be represented in the abixml file
> as having the name "struct_name".  And your problem will be solved, I
> think.
>
> There are other techniques used in the dwarf-reader to handle anonymous
> types that are not named by a typedef.  But those are super rare,
> especially in C.  So I hope that using naming typedef should be good
> enough for a start, in practise.

Hmm, we are actually using set_naming_typedef:

static typedef_decl_sptr
process_ctf_typedef(read_context *ctxt,
                    corpus_sptr corp,
                    translation_unit_sptr tunit,
                    ctf_dict_t *ctf_dictionary,
                    ctf_id_t ctf_type)
{
  typedef_decl_sptr result;

  ctf_id_t ctf_utype = ctf_type_reference(ctf_dictionary, ctf_type);
  if (ctf_utype == CTF_ERR)
    return result;

  const char *typedef_name = ctf_type_name_raw(ctf_dictionary, ctf_type);
  type_base_sptr utype = lookup_type(ctxt, corp, tunit,
                                     ctf_dictionary, ctf_utype);

  if (!utype)
    return result;

  result.reset(new typedef_decl(typedef_name, utype, location(),
                                typedef_name /* mangled_name */));

  /* If this typedef "names" an anonymous type, reflect this fact in
     the underlying type.  In C enum, struct and union types can be
     anonymous.  */
  if (is_anonymous_type(utype)
      && (is_enum_type(utype) || is_class_or_union_type(utype)))
    {
      decl_base_sptr decl = is_decl(utype);
      ABG_ASSERT(decl);
      decl->set_naming_typedef(result);
    }

  return result;
}
  
Guillermo E. Martinez Nov. 26, 2021, 1:37 p.m. UTC | #17
On Friday, November 26, 2021 5:23:28 AM CST Dodji Seketeli wrote:
> Hello,
> 
> [...]
> 
> On Nov 24, 2021, at 8:36 AM, Dodji Seketeli <dodji@seketeli.org> wrote
> 
> >> So where exactly is the CTF test disabled?
> 
> Guillermo Martinez <guillermo.e.martinez@oracle.com> a écrit:
> 
> > I remove those test entries, so the possible problem detected using external diff
> > command in CTF is, for instance, in: test-read-common/test-PR26568-1-ctf.o.abi,
> > the first time that runtestreadctf is executed an abixml file  is generated:
> >
> > ...
> >     <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
> >       <data-member access='public' layout-offset-in-bits='0'>
> >         <var-decl name='x' type-id='type-id-4' visibility='default'/>
> >       </data-member>
> >     </class-decl>
> >     <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-5'>
> >       <data-member access='public' layout-offset-in-bits='0'>
> >         <var-decl name='y' type-id='type-id-6' visibility='default'/>
> >       </data-member>
> >     </class-decl>
> >
> > and this is second execution:
> > ...
> >     <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-5'>
> >       <data-member access='public' layout-offset-in-bits='0'>
> >         <var-decl name='y' type-id='type-id-6' visibility='default'/>
> >       </data-member>
> >     </class-decl>
> >     <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
> >       <data-member access='public' layout-offset-in-bits='0'>
> >         <var-decl name='x' type-id='type-id-4' visibility='default'/>
> >       </data-member>
> >     </class-decl>
> >
> > As we can see both abixml files  have *same nodes information* but the nodes
> > are in a different order, so the test should be marked as passed, however using
> > the external diff command the test fails. so my question is should we rely in diff
> > command to compare the corpus of the ELF input files (abixml files)?
> 
> So, you see here, this is exactly why we use the diff tool IN ADDITION
> to abidiff (which only look for ABI changes).
> 
> Here, you see that two invocations of abidw is yielding possibly two
> *DIFFERENT* abixml files.  They are different because some struct type
> definition come out in different order.
OK, but they represent the same ABI, because the nodes order is not
relevant here .. Is that correct?

> Why?
> 
> This is because we have two struct types that have the same (empty) name
> and yet they are different.  The abixml writer sorts types using their
> names, somehow.  So some times, one type comes first; some times, it's
> the other.
OK.
> Let's look at the issue a bit deeper.
> 
> These are anonymous struct.
> 
> For various reasons, we need to designate types in the Libabigail
> system.  So every single type needs to be given a name.  Even anonymous
> types.
> 
> Most of the time, in C, anonymous types are named using typedefs.  E.g:
> 
> typedef struct
> {
>   int x;
> } struct_name;
> 
> "typedef struct_name" is the 'naming typedef' of the struct type.  It's
> used to name it.  That's how it's designated to be later used.
> 
> The libabigail IR has the decl_base::set_naming_typedef() function to
> set naming typedefs on 
> 
> If you look at the code of the dwarf reader, in the function
> build_typedef_type, near the end, you'll see that it uses the
> set_naming_typedef method to set the naming typedef of the underlying
> anonymous class (or struct) it sees.
> 
> Once you've done that, the struct will be represented in the abixml file
> as having the name "struct_name".  And your problem will be solved, I
> think.
> 
> There are other techniques used in the dwarf-reader to handle anonymous
> types that are not named by a typedef.  But those are super rare,
> especially in C.  So I hope that using naming typedef should be good
> enough for a start, in practise.
> 
> It's precisely to detect cases like this that the "diff" tool is used.
So, is correct mark this test as failed as the current ctf/dwarf test harness does?

I'll isolate the scenario using anonymous types as you explained above :-).
Thanks so much for your hints!!
  
> I hope this helps.
> 
> [...]
> 
> Cheers,
  
Ben Woodard Dec. 1, 2021, 2:13 a.m. UTC | #18
Sorry, I didn’t mean to jump into a thread, stir up controversy and then disappear.
American holiday, with guests, I’m the main cook… then other duties got in the way of me getting back to this.

> On Nov 26, 2021, at 2:27 AM, Dodji Seketeli <dodji@seketeli.org> wrote:
> 
> Hello,
> 
> [...]
> 
> On Nov 24, 2021, at 8:36 AM, Dodji Seketeli <dodji@seketeli.org> wrote:
> 
>>> In those cases where the abixml file generated from CTF is different
>>> from the one generated from DWARF, I think we should have two
>>> different reference abixml files to diff against.  No CTF test should
>>> be disabled, I think.
> 
> Ben Woodard <woodard@redhat.com> a écrit:
> 
> 
>> Here is a somewhat deeper question that I think needs to be
>> considered. I’ve generally referred to it as “DWARF Idioms” but this
>> email makes me think that it is even larger than that.
>> 
>> For my work, I need libabigail to generate an abstract notion of the
>> ABI corpus. How it constructs that abstract notion of the ABI needs to
>> be independent of the producer. Think of it this way, say we take the
>> same compiler and have it compile the same library producing both CTF
>> and DWARF, the ABI of the library doesn’t change. Since it is
>> literally the same object, the program text is same. Therefore the ABI
>> is unquestionably the the same. Any difference reported by libabigail
>> therefore is a problem with libabigail.
> 
> In theory, I think what you say makes total sense.
> 
> In practice however, there seems to be some annoying limits to what we
> can do right now.
> 
> For instance, right now, CTF doesn't include source location (file name,
> line numbers) information.
> 
> So by default, the output details of abidiff will be different at least
> because in one case it shows line information and in other other it
> doesn't.  

The characteristic of where something was declared isn’t an ABI artifact. It is something that is recorded in the IR for later so that it can be printed later to help locate the error. In the case where it is unknown for one producer but known for another producer, the location of the declaration doesn’t have to be emitted when it is not known. We are not textually diffing the abixml files from abidw. However, when comparing two corpora loaded into libabigail’s IR, the fact that one has a decl file and a decl line while the other doesn’t shouldn’t be flagged as a difference.

> Of course we can work harder to avoid showing line information
> in all abidiff tests, but then it means that the particular feature of
> handling line information coming from DWARF won't be tested.
> 
> So yeah, there are details like that.  I am not sure how much of these
> we have, but if I've found one, I can't say they aren't others.
> 
> Of course, the "general representation" (whatever that means) of the ABI
> represented by DWARF or CTF should not be different.  But the exact
> textual output of abidiff or abidw is not necessarily going to be the
> same, "a priori".
> 
>> It is not taking the source material and abstracting it enough into
>> the ABI artifacts to separate the artifacts from the implementation.
> 
> Right.  I'd argue that the problem wasn't "apparent" when we had only
> DWARF to care about.  Now it is.  So, I think now we are starting to
> have the means to see the issue, rather than just speculate in the
> abstract.  

There has always been the problem of comparing DWARF from different toolchains. I’d argue that is an even harder nut to crack but we need to get on it.

Just compile libabigail with clang++ and g++ and then do an abidiff of the resulting libabigai.so.0.0.0’s to see what I mean. I think that some of that difference is compiler bugs but other things we need to deal with in libabigail.  I really don’t have a lot of great ideas on how to deal with that. I think that in some cases recording type synonyms and then having a secondary when types don’t match to see if a type is a synonym of another type may fix some of the problems. It would be great if we could put our heads together on this and brainstorm how to make this work.

> So for cases where it makes sense, I think the "abstraction
> level" of the IR can be ameliorated.
> 
>> So I kind of believe that we need to look more deeply into WHY the CTF
>> and DWARF are not comparing as equivalent and begin the process of
>> filing the compiler bugs when we need to, and doing what is necessary
>> to abstract the ABI from the source material that libabigail used to
> p> construct its IR of the ABI corpus from.
> 
> Agreed.
> 
>> So, I must say that I disagree with both dodji’s approach here and to
>> a lesser extent Guillermo’s approach of disabling the tests. I think
>> that the tests where the CTF doesn’t match the DWARF should be
>> investigated and when necessary marked “xfail” with a note citing
>> their individual cause.
> 
> Well, lemme quote what I said:
> 
> On Nov 24, 2021, at 8:36 AM, Dodji Seketeli <dodji@seketeli.org> wrote:
> 
>>> In those cases where the abixml file generated from CTF is different
>>> from the one generated from DWARF, I think we should have two
>>> different reference abixml files to diff against.  No CTF test should
>>> be disabled, I think.
> 
> I said explicitly that no test should be disabled.
> 
> Incidentally, by providing the two abixml files (DWARF and CTF) at least
> we can see what the change are and later work on reducing those changes
> if it makes sense.
> 
>> I think that what we need to work towards is: abidw produces the same
>> output (or more precisely libabigail produces the same IR) whether you
>> compile with -gdwarf-3 -gdwarf-4 -gdwarf-5 -gsplit-dwarf -gctf also
>> for the most part the ABI should not change between compiler
>> versions. There may be a few cases that we need to look into where the
>> compiler actually breaks ABI and of course libabigail should flag
>> those but I would assert that libabigail needs to abstract its IR of
>> the ABI enough that compiler version changes that don’t actually
>> change the ABI of the ELF object are not reported as ABI breaks. It
>> currently does pretty well at this at the moment.  Then once that
>> foundation is built, being able to abstract the ABI IR enough that
>> differences in toolchains e.g. LLVM vs GCC are not flagged as changes
>> in the object’s ABI. This is important to provide people with a tool
>> that will allow them to mix toolchains within a project to achieve
>> optimal code.
> 
> In an ideal world, of course.  I am not opposed to trying our best ;-)
> 
> Cheers,
> 
> -- 
> 		Dodji
>
  
Ben Woodard Dec. 1, 2021, 3:18 a.m. UTC | #19
sorry it is taking me so long to get back to you. American Thanksgiving holiday.

> On Nov 24, 2021, at 10:50 PM, Jose E. Marchesi <jose.marchesi@oracle.com> wrote:
> 
>>> 
>>> On Nov 24, 2021, at 8:36 AM, Dodji Seketeli <dodji@seketeli.org> wrote:
>>> 
>>> Hello,
>>> 
>>> [...]
>>> 
>>> Thanks for working on this.  Nice patch, by the way!  I like its
>>> direction.
>>> 
>>> I have a few comments and I believe that when they are addressed, we'll
>>> be able to apply the patch.
>>> 
>>> [...]
>>> 
>>>> Dependencies/limitations:
>>>> 
>>>> * It was worked on the top of the following patches:
>>>> https://sourceware.org/pipermail/libabigail/2021q4/003853.html
>>>> 
>>>> * Some CTF tests were *disabled* because it generates the XML ABI
>>>> corpus with *same information* but the XML nodes *are not* always
>>>> in the *same order*, so using diff command fails. Details here:
>>>> https://sourceware.org/pipermail/libabigail/2021q4/003824.html
>>> 
>>> In those cases where the abixml file generated from CTF is different
>>> from the one generated from DWARF, I think we should have two
>>> different reference abixml files to diff against.  No CTF test should
>>> be disabled, I think.
>> 
>> Here is a somewhat deeper question that I think needs to be
>> considered. I’ve generally referred to it as “DWARF Idioms” but this
>> email makes me think that it is even larger than that.
>> 
>> For my work, I need libabigail to generate an abstract notion of the
>> ABI corpus. How it constructs that abstract notion of the ABI needs to
>> be independent of the producer. Think of it this way, say we take the
>> same compiler and have it compile the same library producing both CTF
>> and DWARF, the ABI of the library doesn’t change. Since it is
>> literally the same object, the program text is same. Therefore the ABI
>> is unquestionably the the same. Any difference reported by libabigail
>> therefore is a problem with libabigail. It is not taking the source
>> material and abstracting it enough into the ABI artifacts to separate
>> the artifacts from the implementation.
>> 
>> So I kind of believe that we need to look more deeply into WHY the CTF
>> and DWARF are not comparing as equivalent and begin the process of
>> filing the compiler bugs when we need to, and doing what is necessary
>> to abstract the ABI from the source material that libabigail used to
>> construct its IR of the ABI corpus from.
>> 
>> So, I must say that I disagree with both dodji’s approach here and to
>> a lesser extent Guillermo’s approach of disabling the tests. I think
>> that the tests where the CTF doesn’t match the DWARF should be
>> investigated and when necessary marked “xfail” with a note citing
>> their individual cause.
>> 
>> I think that what we need to work towards is:
>> abidw produces the same output (or more precisely libabigail produces
>> the same IR) whether you compile with -gdwarf-3 -gdwarf-4 -gdwarf-5
>> -gsplit-dwarf -gctf
>> also for the most part the ABI should not change between compiler
>> versions. There may be a few cases that we need to look into where the
>> compiler actually breaks ABI and of course libabigail should flag
>> those but I would assert that libabigail needs to abstract its IR of
>> the ABI enough that compiler version changes that don’t actually
>> change the ABI of the ELF object are not reported as ABI breaks. It
>> currently does pretty well at this at the moment.
>> Then once that foundation is built, being able to abstract the ABI IR
>> enough that differences in toolchains e.g. LLVM vs GCC are not flagged
>> as changes in the object’s ABI. This is important to provide people
>> with a tool that will allow them to mix toolchains within a project to
>> achieve optimal code.
> 
> I'm so glad you are raising these concerns.
> 
> I agree with you that ideally abidw should produce "same output" (read
> equivalent output ABI-wise) regardless of the origin of the ABI
> corpus... but then:

I’m not sure it should be the same output. I think that textual diffing of the output probably won’t work especially for the stuff that I have been working on. However, I do believe that the comparison of the corpora once they are loaded into the IR should be the same. Even if anonymous types do not come out in the same order or one debug format is read vs another, I think that they should compare the same in the IR.

> 
> Is the relative order of the <*-decl > nodes in the ABI XML part of the
> ABI?

Not really worried about that as long as the IR’s compare.
> 
> Is the location information (present in DWARF, not present in CTF nor
> BTF) part of the ABI?

Yeah there is ancillary information that is useful to have when printing differences but it should not be part of the ABI artifact comparison. For example. Say I add a comment to a source file. The decl line will change but the ABI of the ELF will not. I argue that the comparison of the ABI should be that they are the same. 
> 
> Are the names assigned to internally-generated types (such as the
> underlying type of an enumerator) part of the ABI?

To me that seems like an implementation detail of the library. It is something of course that an ABI checker needs to get correct even though it is difficult. If someone adds a new enum type but it is not exported, it may still get assigned an anonymous enum in the type system and that may jiggle the type numbering but the difference engine shouldn’t flag it as an ABI change. Dodji tracked down and fixed a huge number of these bugs for me over the years.
> 
> Are the newlines and blank spaces after XML marks part of the ABI?
Comparison needs to be done once the ABIXML is loaded into the IR.

> 
> I am no expert in ABI analysis, but I would say the answers in all these
> cases is `no'.  The internal libabigail ABI comparison algorithms would
> not be impacted by these things, right?
> 
> It seems to me that the main problems here are that ABI XML, as it is,
> conveys way too much information (useful, no doubt, but superfluous
> ABI-wise) and that `diff' is used to perform a textual comparison of
> these files.

I agree. I would not do textual comparison.
One thing that I think makes this task well suited to XML rather than something more regularly structured is that the XML is allows additional attributes such as the aforementioned decl file and decl line which then can be ignored when doing ABI comparison. 
> 
> Textual comparison would work if we defined a "canonicalized" version of
> ABI XML.  Translating from ABI XML to canonical ABI XML would involve:
> 
> 1) Strip _everything_ that is not strictly part of the ABI (such as
>   location information, anonymous type names, etc).
> 
> 2) Sort the XML elements in a predefined way.  Whatever sort criteria is
>   used, it would need to be defined only by ABI-constituent elements,
>   such as the names of non-anonymous types.  And of course the criteria
>   itself must not change.
> 
> The only reason you could operate with ABI XML files heavily annotated
> with non-ABI determining information (such as the loc info and
> superfluous and arbitrary names) is having an unique source for the ABI
> info.  That's no longer the case: we are using CTF, the Google chaps are
> using BTF.
> 
> The above considered, I think we have three options now:
> 
> a) To define that canonical ABI XML and write an abistrip tool that does
>   the translation, maybe add --canonical options to the tools that
>   generate ABI XML.  Then use `diff' in the testsuite.
> 
>   or
> 
> b) To use an external ABI comparison tool in the testsuite, non-textual,
>   that consumes ABI XML.
> 
This would be my preference.
All comparisons should be done at the level of the IR.
>   or
> 
> c) To use the "internal" approach I already suggested in another email,
>   having two different sets of tests: one set to test the front-ends
>   that assume the libabigail comparison algorithm works properly,
>   another set to test the comparison algorithm that uses either
>   hand-written input files or assumes the front-ends work properly.

I kind of agree in principle however, I don’t want to write those tests and I am pretty certain Dodji doesn’t want to write tests that way plus if he started refactoring that way, I would begin nagging him about all the other problems that I have found that need attention first. ;-) I generally feel like I’m breaking his back as is.

> 
> I personally think (c) would be best.
  

Patch

diff --git a/tests/Makefile.am b/tests/Makefile.am
index e3855aea..17e2d4b4 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -25,6 +25,10 @@  runtestdifffilter		\
 runtestreaddwarf	        \
 runtestcanonicalizetypes.sh
 
+if CTF_READER
+TESTS += runtestreadctf
+endif
+
 # rather cheap tests
 TESTS+=				\
 runtestabicompat		\
@@ -72,7 +76,7 @@  runtestcanonicalizetypes.output.final.txt
 
 noinst_PROGRAMS= $(TESTS) testirwalker testdiff2 printdifftree
 noinst_SCRIPTS = mockfedabipkgdiff
-noinst_LTLIBRARIES = libtestutils.la libcatch.la
+noinst_LTLIBRARIES = libtestutils.la libtestreadcommon.la libcatch.la
 
 libtestutils_la_SOURCES=	\
 test-utils.h 			\
@@ -82,15 +86,31 @@  libtestutils_la_CXXFLAGS=		\
 -DABIGAIL_SRC_DIR=\"${abs_top_srcdir}\"  	\
 -DABIGAIL_BUILD_DIR=\"${abs_top_builddir}\"
 
+libtestreadcommon_la_SOURCES=	\
+test-read-common.h 		\
+test-read-common.cc
+
+libtestreadcommon_la_CXXFLAGS=			\
+-DABIGAIL_SRC_DIR=\"${abs_top_srcdir}\"  	\
+-DABIGAIL_BUILD_DIR=\"${abs_top_builddir}\"
+
 libcatch_la_SOURCES = lib/catch.cc lib/catch.hpp
 
 runtestreadwrite_SOURCES=test-read-write.cc
 runtestreadwrite_LDADD=libtestutils.la $(top_builddir)/src/libabigail.la
 
 runtestreaddwarf_SOURCES=test-read-dwarf.cc
-runtestreaddwarf_LDADD=libtestutils.la $(top_builddir)/src/libabigail.la
+runtestreaddwarf_LDADD=libtestreadcommon.la libtestutils.la	\
+		       $(top_builddir)/src/libabigail.la
 runtestreaddwarf_LDFLAGS=-pthread
 
+if CTF_READER
+runtestreadctf_SOURCES=test-read-ctf.cc
+runtestreadctf_LDADD=libtestreadcommon.la libtestutils.la	\
+		     $(top_builddir)/src/libabigail.la
+runtestreadctf_LDFLAGS=-pthread
+endif
+
 runtestannotate_SOURCES=test-annotate.cc
 runtestannotate_LDADD=libtestutils.la $(top_builddir)/src/libabigail.la
 
diff --git a/tests/data/test-annotate/test3.so.abi b/tests/data/test-annotate/test3.so.abi
index c4911724..320d886a 100644
--- a/tests/data/test-annotate/test3.so.abi
+++ b/tests/data/test-annotate/test3.so.abi
@@ -16,9 +16,9 @@ 
     <!-- foo__ -->
     <elf-symbol name='foo__' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
-  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf' language='LANG_C89'>
+  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
     <!-- void __foo() -->
-    <function-decl name='__foo' mangled-name='__foo' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test3.c' line='8' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
+    <function-decl name='__foo' mangled-name='__foo' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test3.c' line='23' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
       <!-- void -->
       <return type-id='type-id-1'/>
     </function-decl>
diff --git a/tests/data/test-annotate/test4.so.abi b/tests/data/test-annotate/test4.so.abi
index c3550e35..7913e324 100644
--- a/tests/data/test-annotate/test4.so.abi
+++ b/tests/data/test-annotate/test4.so.abi
@@ -6,7 +6,7 @@ 
     <!-- cpy -->
     <elf-symbol name='cpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
-  <abi-instr address-size='64' path='test4.c' comp-dir-path='/home/mark/src/tests' language='LANG_C89'>
+  <abi-instr address-size='64' path='test4.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C99'>
     <!-- char -->
     <type-decl name='char' size-in-bits='8' id='type-id-1'/>
     <!-- unsigned int -->
@@ -22,13 +22,13 @@ 
     <!-- const char* restrict -->
     <qualified-type-def type-id='type-id-6' restrict='yes' id='type-id-7'/>
     <!-- char* cpy(char* restrict, const char* restrict, unsigned int) -->
-    <function-decl name='cpy' mangled-name='cpy' filepath='/home/mark/src/tests/test4.c' line='2' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cpy'>
+    <function-decl name='cpy' mangled-name='cpy' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cpy'>
       <!-- parameter of type 'char* restrict' -->
-      <parameter type-id='type-id-4' name='s1' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
+      <parameter type-id='type-id-4' name='s1' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
       <!-- parameter of type 'const char* restrict' -->
-      <parameter type-id='type-id-7' name='s2' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
+      <parameter type-id='type-id-7' name='s2' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
       <!-- parameter of type 'unsigned int' -->
-      <parameter type-id='type-id-2' name='n' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
+      <parameter type-id='type-id-2' name='n' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
       <!-- char* -->
       <return type-id='type-id-3'/>
     </function-decl>
diff --git a/tests/data/test-read-common/PR26261/PR26261-exe b/tests/data/test-read-common/PR26261/PR26261-exe
new file mode 100755
index 0000000000000000000000000000000000000000..939e8071509f568b3628fc0ca6c3434a2de62cb6
GIT binary patch
literal 19008
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

literal 0
HcmV?d00001

diff --git a/tests/data/test-read-common/PR26261/PR26261-exe-ctf.abi b/tests/data/test-read-common/PR26261/PR26261-exe-ctf.abi
new file mode 100644
index 00000000..cb2e2f13
--- /dev/null
+++ b/tests/data/test-read-common/PR26261/PR26261-exe-ctf.abi
@@ -0,0 +1,58 @@ 
+<abi-corpus version='2.1' path='data/test-read-common/PR26261/PR26261-exe'>
+  <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='_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 address-size='64' language='LANG_C'>
+    <type-decl name='char' size-in-bits='8' alignment-in-bits='8' id='type-id-1'/>
+    <class-decl name='SA' size-in-bits='192' alignment-in-bits='32' is-struct='yes' visibility='default' id='type-id-2'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='m1' type-id='type-id-3' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='64'>
+        <var-decl name='m2' type-id='type-id-4' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='128'>
+        <var-decl name='m3' type-id='type-id-5' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <class-decl name='SB' size-in-bits='128' alignment-in-bits='32' is-struct='yes' visibility='default' id='type-id-6'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='m1' type-id='type-id-3' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='64'>
+        <var-decl name='m2' type-id='type-id-7' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-3'/>
+    <typedef-decl name='fn_ptr_type_a2_t' type-id='type-id-8' id='type-id-5'/>
+    <typedef-decl name='fn_ptr_type_a_t' type-id='type-id-8' id='type-id-4'/>
+    <typedef-decl name='fn_ptr_type_b_t' type-id='type-id-9' id='type-id-7'/>
+    <pointer-type-def type-id='type-id-2' size-in-bits='64' alignment-in-bits='64' id='type-id-10'/>
+    <pointer-type-def type-id='type-id-6' size-in-bits='64' alignment-in-bits='64' id='type-id-11'/>
+    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-12'/>
+    <pointer-type-def type-id='type-id-12' size-in-bits='64' alignment-in-bits='64' id='type-id-13'/>
+    <pointer-type-def type-id='type-id-14' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
+    <pointer-type-def type-id='type-id-15' size-in-bits='64' alignment-in-bits='64' id='type-id-9'/>
+    <function-type size-in-bits='64' alignment-in-bits='8' id='type-id-14'>
+      <parameter type-id='type-id-3'/>
+      <parameter type-id='type-id-3'/>
+      <return type-id='type-id-16'/>
+    </function-type>
+    <function-type size-in-bits='64' alignment-in-bits='8' id='type-id-15'>
+      <parameter type-id='type-id-3'/>
+      <parameter type-id='type-id-3'/>
+      <parameter type-id='type-id-1'/>
+      <return type-id='type-id-16'/>
+    </function-type>
+    <type-decl name='void' id='type-id-16'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-exe.abi b/tests/data/test-read-common/PR26261/PR26261-exe-dwarf.abi
similarity index 53%
rename from tests/data/test-read-dwarf/PR26261/PR26261-exe.abi
rename to tests/data/test-read-common/PR26261/PR26261-exe-dwarf.abi
index a24f3a44..cd631bf1 100644
--- a/tests/data/test-read-dwarf/PR26261/PR26261-exe.abi
+++ b/tests/data/test-read-common/PR26261/PR26261-exe-dwarf.abi
@@ -1,12 +1,10 @@ 
-<abi-corpus version='2.1' path='data/test-read-dwarf/PR26261/PR26261-exe'>
+<abi-corpus version='2.1' path='data/test-read-common/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'/>
@@ -16,18 +14,18 @@ 
   <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 address-size='64' path='PR26261-main.c' comp-dir-path='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261' language='LANG_C89'>
+  <abi-instr address-size='64' path='PR26261-main.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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'/>
+    <function-decl name='wrapped_call' mangled-name='wrapped_call' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-main.c' line='18' column='1'/>
+      <parameter type-id='type-id-5' name='a' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-main.c' line='19' column='1'/>
+      <parameter type-id='type-id-5' name='b' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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'/>
+    <function-decl name='main' mangled-name='main' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-main.c' line='27' column='1'/>
+      <parameter type-id='type-id-3' name='argv' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-main.c' line='27' column='1'/>
       <return type-id='type-id-5'/>
     </function-decl>
     <function-type size-in-bits='64' id='type-id-7'>
@@ -36,44 +34,44 @@ 
       <return type-id='type-id-6'/>
     </function-type>
   </abi-instr>
-  <abi-instr address-size='64' path='PR26261-obja.c' comp-dir-path='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261' language='LANG_C89'>
+  <abi-instr address-size='64' path='PR26261-obja.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261' language='LANG_C89'>
     <type-decl name='int' size-in-bits='32' id='type-id-5'/>
-    <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'/>
-    <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-10'>
+    <typedef-decl name='fn_ptr_type_a_t' type-id='type-id-4' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-obja.h' line='3' column='1' id='type-id-9'/>
+    <class-decl name='SA' size-in-bits='192' is-struct='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-obja.h' line='5' column='1' id='type-id-10'>
       <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'/>
+        <var-decl name='m1' type-id='type-id-5' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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'/>
+        <var-decl name='m2' type-id='type-id-8' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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'/>
+        <var-decl name='m3' type-id='type-id-9' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-obja.h' line='9' column='1'/>
       </data-member>
     </class-decl>
     <pointer-type-def type-id='type-id-10' size-in-bits='64' id='type-id-11'/>
     <pointer-type-def type-id='type-id-7' 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-11' name='s' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-obja.c' line='4' column='1'/>
+    <function-decl name='fun_obja' mangled-name='fun_obja' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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-11' name='s' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-obja.c' line='4' column='1'/>
       <return type-id='type-id-6'/>
     </function-decl>
     <type-decl name='void' id='type-id-6'/>
   </abi-instr>
-  <abi-instr address-size='64' path='PR26261-objb.c' comp-dir-path='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261' language='LANG_C89'>
+  <abi-instr address-size='64' path='PR26261-objb.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261' language='LANG_C89'>
     <type-decl name='char' size-in-bits='8' id='type-id-1'/>
-    <typedef-decl name='fn_ptr_type_b_t' type-id='type-id-12' filepath='/home/dodji/git/libabigail/patches/tests/data/test-read-dwarf/PR26261/PR26261-objb.h' line='1' column='1' id='type-id-13'/>
-    <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-14'>
+    <typedef-decl name='fn_ptr_type_b_t' type-id='type-id-12' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-objb.h' line='1' column='1' id='type-id-13'/>
+    <class-decl name='SB' size-in-bits='128' is-struct='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-objb.h' line='3' column='1' id='type-id-14'>
       <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'/>
+        <var-decl name='m1' type-id='type-id-5' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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'/>
+        <var-decl name='m2' type-id='type-id-13' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR26261/PR26261-objb.h' line='6' column='1'/>
       </data-member>
     </class-decl>
     <pointer-type-def type-id='type-id-14' size-in-bits='64' id='type-id-15'/>
     <pointer-type-def type-id='type-id-16' size-in-bits='64' id='type-id-12'/>
-    <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'/>
+    <function-decl name='fun_objb' mangled-name='fun_objb' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/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/byby/oracle/src/libabigail/tests/data/test-read-common/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'>
diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-main.c b/tests/data/test-read-common/PR26261/PR26261-main.c
similarity index 100%
rename from tests/data/test-read-dwarf/PR26261/PR26261-main.c
rename to tests/data/test-read-common/PR26261/PR26261-main.c
diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-obja.c b/tests/data/test-read-common/PR26261/PR26261-obja.c
similarity index 100%
rename from tests/data/test-read-dwarf/PR26261/PR26261-obja.c
rename to tests/data/test-read-common/PR26261/PR26261-obja.c
diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-obja.h b/tests/data/test-read-common/PR26261/PR26261-obja.h
similarity index 100%
rename from tests/data/test-read-dwarf/PR26261/PR26261-obja.h
rename to tests/data/test-read-common/PR26261/PR26261-obja.h
diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-objb.c b/tests/data/test-read-common/PR26261/PR26261-objb.c
similarity index 100%
rename from tests/data/test-read-dwarf/PR26261/PR26261-objb.c
rename to tests/data/test-read-common/PR26261/PR26261-objb.c
diff --git a/tests/data/test-read-dwarf/PR26261/PR26261-objb.h b/tests/data/test-read-common/PR26261/PR26261-objb.h
similarity index 100%
rename from tests/data/test-read-dwarf/PR26261/PR26261-objb.h
rename to tests/data/test-read-common/PR26261/PR26261-objb.h
diff --git a/tests/data/test-read-dwarf/PR27700/include-dir/priv.h b/tests/data/test-read-common/PR27700/include-dir/priv.h
similarity index 100%
rename from tests/data/test-read-dwarf/PR27700/include-dir/priv.h
rename to tests/data/test-read-common/PR27700/include-dir/priv.h
diff --git a/tests/data/test-read-dwarf/PR27700/include-dir/pub.h b/tests/data/test-read-common/PR27700/include-dir/pub.h
similarity index 100%
rename from tests/data/test-read-dwarf/PR27700/include-dir/pub.h
rename to tests/data/test-read-common/PR27700/include-dir/pub.h
diff --git a/tests/data/test-read-dwarf/PR27700/pub-incdir/inc.h b/tests/data/test-read-common/PR27700/pub-incdir/inc.h
similarity index 100%
rename from tests/data/test-read-dwarf/PR27700/pub-incdir/inc.h
rename to tests/data/test-read-common/PR27700/pub-incdir/inc.h
diff --git a/tests/data/test-read-common/PR27700/test-PR27700-ctf.abi b/tests/data/test-read-common/PR27700/test-PR27700-ctf.abi
new file mode 100644
index 00000000..62df1017
--- /dev/null
+++ b/tests/data/test-read-common/PR27700/test-PR27700-ctf.abi
@@ -0,0 +1,22 @@ 
+<abi-corpus version='2.1' path='data/test-read-common/PR27700/test-PR27700.o'>
+  <elf-function-symbols>
+    <elf-symbol name='foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='811c9dc5'/>
+    <enum-decl name='foo' linkage-name='foo' id='022218d8'>
+      <underlying-type type-id='811c9dc5'/>
+      <enumerator name='foo_e0' value='0'/>
+      <enumerator name='foo_e1' value='1'/>
+      <enumerator name='foo_e2' value='2'/>
+      <enumerator name='foo_e3' value='3'/>
+    </enum-decl>
+    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
+    <pointer-type-def type-id='022218d8' size-in-bits='64' alignment-in-bits='64' id='8750e847'/>
+    <function-decl name='foo' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+      <parameter type-id='8750e847'/>
+      <return type-id='48b5725f'/>
+    </function-decl>
+    <type-decl name='void' id='48b5725f'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-dwarf/PR27700/test-PR27700.abi b/tests/data/test-read-common/PR27700/test-PR27700-dwarf.abi
similarity index 60%
rename from tests/data/test-read-dwarf/PR27700/test-PR27700.abi
rename to tests/data/test-read-common/PR27700/test-PR27700-dwarf.abi
index e593f79f..fff6ff74 100644
--- a/tests/data/test-read-dwarf/PR27700/test-PR27700.abi
+++ b/tests/data/test-read-common/PR27700/test-PR27700-dwarf.abi
@@ -1,15 +1,15 @@ 
-<abi-corpus version='2.1' path='data/test-read-dwarf/PR27700/test-PR27700.o'>
+<abi-corpus version='2.1' path='data/test-read-common/PR27700/test-PR27700.o'>
   <elf-function-symbols>
     <elf-symbol name='foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
-  <abi-instr address-size='64' path='test-PR27700.c' comp-dir-path='/home/dodji/git/libabigail/PR27700/tests/data/test-read-dwarf/PR27700' language='LANG_C11'>
+  <abi-instr address-size='64' path='test-PR27700.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR27700' language='LANG_C11'>
     <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
     <enum-decl name='foo' filepath='include-dir/priv.h' line='1' column='1' id='022218d8'>
       <underlying-type type-id='9cac1fee'/>
     </enum-decl>
     <pointer-type-def type-id='022218d8' size-in-bits='64' id='8750e847'/>
-    <function-decl name='foo' mangled-name='foo' filepath='/home/dodji/git/libabigail/PR27700/tests/data/test-read-dwarf/PR27700/test-PR27700.c' line='4' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
-      <parameter type-id='8750e847' name='c' filepath='/home/dodji/git/libabigail/PR27700/tests/data/test-read-dwarf/PR27700/test-PR27700.c' line='4' column='1'/>
+    <function-decl name='foo' mangled-name='foo' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR27700/test-PR27700.c' line='4' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
+      <parameter type-id='8750e847' name='c' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/PR27700/test-PR27700.c' line='4' column='1'/>
       <return type-id='48b5725f'/>
     </function-decl>
     <type-decl name='void' id='48b5725f'/>
diff --git a/tests/data/test-read-dwarf/PR27700/test-PR27700.c b/tests/data/test-read-common/PR27700/test-PR27700.c
similarity index 55%
rename from tests/data/test-read-dwarf/PR27700/test-PR27700.c
rename to tests/data/test-read-common/PR27700/test-PR27700.c
index b44a3226..a16a0bb7 100644
--- a/tests/data/test-read-dwarf/PR27700/test-PR27700.c
+++ b/tests/data/test-read-common/PR27700/test-PR27700.c
@@ -1,5 +1,7 @@ 
 #include "include-dir/priv.h"
 
+/* gcc -I. -gctf -gdwarf -c -o test-PR27700.o test-PR27700.c */
+
 void
 foo(enum foo* c __attribute__((unused)))
 {
diff --git a/tests/data/test-read-common/crti.c b/tests/data/test-read-common/crti.c
new file mode 100644
index 00000000..47dc4e47
--- /dev/null
+++ b/tests/data/test-read-common/crti.c
@@ -0,0 +1,22 @@ 
+/*
+ * gcc -c -std=c89 -mtune=generic -march=x86-64 crti.c
+ *
+ * NOTE: linking with _old_ crti.o exposes _init and _fini as
+ *       global symbols, the newer versions don't.
+ *
+ * 0000000000000000 g     F .init  0000000000000000 .hidden _init
+ * 0000000000000000 g     F .fini  0000000000000000 .hidden _fini
+ *
+ * So this is a dummy c-runtime object.
+ *
+ */
+
+void __attribute__((visibility("default")))
+_init(void)
+{
+}
+
+void __attribute__((visibility("default")))
+_fini(void)
+{
+}
diff --git a/tests/data/test-read-common/test-PR26568-1-ctf.o.abi b/tests/data/test-read-common/test-PR26568-1-ctf.o.abi
new file mode 100644
index 00000000..d62474ec
--- /dev/null
+++ b/tests/data/test-read-common/test-PR26568-1-ctf.o.abi
@@ -0,0 +1,56 @@ 
+<abi-corpus version='2.1' path='data/test-read-common/test-PR26568-1.o'>
+  <elf-function-symbols>
+    <elf-symbol name='fun' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <class-decl name='A' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='type-id-1'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='' type-id='type-id-2' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='' type-id='type-id-3' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='x' type-id='type-id-4' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='' type-id='type-id-5' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='y' type-id='type-id-6' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='x' type-id='type-id-4' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-5'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='y' type-id='type-id-6' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-4'/>
+    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
+    <union-decl name='' size-in-bits='64' is-anonymous='yes' visibility='default' id='type-id-2'>
+      <data-member access='public'>
+        <var-decl name='' type-id='type-id-3' visibility='default'/>
+      </data-member>
+      <data-member access='public'>
+        <var-decl name='x' type-id='type-id-4' visibility='default'/>
+      </data-member>
+      <data-member access='public'>
+        <var-decl name='' type-id='type-id-5' visibility='default'/>
+      </data-member>
+      <data-member access='public'>
+        <var-decl name='y' type-id='type-id-6' visibility='default'/>
+      </data-member>
+    </union-decl>
+    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
+    <function-decl name='fun' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+      <parameter type-id='type-id-7'/>
+      <return type-id='type-id-8'/>
+    </function-decl>
+    <type-decl name='void' id='type-id-8'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-dwarf/test-PR26568-1.o.abi b/tests/data/test-read-common/test-PR26568-1-dwarf.o.abi
similarity index 58%
rename from tests/data/test-read-dwarf/test-PR26568-1.o.abi
rename to tests/data/test-read-common/test-PR26568-1-dwarf.o.abi
index 5c891200..046d2d45 100644
--- a/tests/data/test-read-dwarf/test-PR26568-1.o.abi
+++ b/tests/data/test-read-common/test-PR26568-1-dwarf.o.abi
@@ -1,16 +1,16 @@ 
-<abi-corpus version='2.1' path='data/test-read-dwarf/test-PR26568-1.o'>
+<abi-corpus version='2.1' path='data/test-read-common/test-PR26568-1.o'>
   <elf-function-symbols>
     <elf-symbol name='fun' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
-  <abi-instr address-size='64' path='test-PR26568-1.c' comp-dir-path='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf' language='LANG_C89'>
+  <abi-instr address-size='64' path='test-PR26568-1.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
     <type-decl name='int' size-in-bits='32' id='type-id-1'/>
     <type-decl name='long int' size-in-bits='64' id='type-id-2'/>
-    <class-decl name='A' size-in-bits='64' is-struct='yes' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='1' column='1' id='type-id-3'>
+    <class-decl name='A' size-in-bits='64' is-struct='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='4' column='1' id='type-id-3'>
       <data-member access='public' layout-offset-in-bits='0'>
         <var-decl name='' type-id='type-id-4' visibility='default'/>
       </data-member>
     </class-decl>
-    <union-decl name='__anonymous_union__' size-in-bits='64' is-anonymous='yes' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='2' column='1' id='type-id-4'>
+    <union-decl name='__anonymous_union__' size-in-bits='64' is-anonymous='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='5' column='1' id='type-id-4'>
       <data-member access='public'>
         <var-decl name='' type-id='type-id-5' visibility='default'/>
       </data-member>
@@ -18,19 +18,19 @@ 
         <var-decl name='' type-id='type-id-6' visibility='default'/>
       </data-member>
     </union-decl>
-    <class-decl name='__anonymous_struct__' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='3' column='1' id='type-id-5'>
+    <class-decl name='__anonymous_struct__' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='6' column='1' id='type-id-5'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='x' type-id='type-id-1' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='4' column='1'/>
+        <var-decl name='x' type-id='type-id-1' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='7' column='1'/>
       </data-member>
     </class-decl>
-    <class-decl name='__anonymous_struct__1' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='6' column='1' id='type-id-6'>
+    <class-decl name='__anonymous_struct__1' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='9' column='1' id='type-id-6'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='y' type-id='type-id-2' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='7' column='1'/>
+        <var-decl name='y' type-id='type-id-2' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='10' column='1'/>
       </data-member>
     </class-decl>
     <pointer-type-def type-id='type-id-3' size-in-bits='64' id='type-id-7'/>
-    <function-decl name='fun' mangled-name='fun' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='12' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fun'>
-      <parameter type-id='type-id-7' name='a' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-1.c' line='12' column='1'/>
+    <function-decl name='fun' mangled-name='fun' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='15' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fun'>
+      <parameter type-id='type-id-7' name='a' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-1.c' line='15' column='1'/>
       <return type-id='type-id-8'/>
     </function-decl>
     <type-decl name='void' id='type-id-8'/>
diff --git a/tests/data/test-read-dwarf/test-PR26568-1.c b/tests/data/test-read-common/test-PR26568-1.c
similarity index 61%
rename from tests/data/test-read-dwarf/test-PR26568-1.c
rename to tests/data/test-read-common/test-PR26568-1.c
index 6eec3558..a551ac7c 100644
--- a/tests/data/test-read-dwarf/test-PR26568-1.c
+++ b/tests/data/test-read-common/test-PR26568-1.c
@@ -1,3 +1,6 @@ 
+/* gcc -std=c89 -gctf -g -mtune=generic -march=x86-64 -c \
+ *     -o test-PR26568-1.o test-PR26568-1.c */
+
 struct A {
   union {
     struct {
diff --git a/tests/data/test-read-common/test-PR26568-2-ctf.o.abi b/tests/data/test-read-common/test-PR26568-2-ctf.o.abi
new file mode 100644
index 00000000..a934d15b
--- /dev/null
+++ b/tests/data/test-read-common/test-PR26568-2-ctf.o.abi
@@ -0,0 +1,39 @@ 
+<abi-corpus version='2.1' path='data/test-read-common/test-PR26568-2.o'>
+  <elf-function-symbols>
+    <elf-symbol name='fun' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <class-decl name='' size-in-bits='32' alignment-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-1'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='x' type-id='type-id-2' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <class-decl name='' size-in-bits='64' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='y' type-id='type-id-4' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-2'/>
+    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-4'/>
+    <union-decl name='A' size-in-bits='64' visibility='default' id='type-id-5'>
+      <data-member access='public'>
+        <var-decl name='' type-id='type-id-1' visibility='default'/>
+      </data-member>
+      <data-member access='public'>
+        <var-decl name='x' type-id='type-id-2' visibility='default'/>
+      </data-member>
+      <data-member access='public'>
+        <var-decl name='' type-id='type-id-3' visibility='default'/>
+      </data-member>
+      <data-member access='public'>
+        <var-decl name='y' type-id='type-id-4' visibility='default'/>
+      </data-member>
+    </union-decl>
+    <pointer-type-def type-id='type-id-5' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
+    <function-decl name='fun' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+      <parameter type-id='type-id-6'/>
+      <return type-id='type-id-7'/>
+    </function-decl>
+    <type-decl name='void' id='type-id-7'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-dwarf/test-PR26568-2.o.abi b/tests/data/test-read-common/test-PR26568-2-dwarf.o.abi
similarity index 59%
rename from tests/data/test-read-dwarf/test-PR26568-2.o.abi
rename to tests/data/test-read-common/test-PR26568-2-dwarf.o.abi
index cdb0243a..5240cee3 100644
--- a/tests/data/test-read-dwarf/test-PR26568-2.o.abi
+++ b/tests/data/test-read-common/test-PR26568-2-dwarf.o.abi
@@ -1,11 +1,11 @@ 
-<abi-corpus version='2.1' path='data/test-read-dwarf/test-PR26568-2.o'>
+<abi-corpus version='2.1' path='data/test-read-common/test-PR26568-2.o'>
   <elf-function-symbols>
     <elf-symbol name='fun' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
-  <abi-instr address-size='64' path='test-PR26568-2.c' comp-dir-path='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf' language='LANG_C89'>
+  <abi-instr address-size='64' path='test-PR26568-2.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
     <type-decl name='int' size-in-bits='32' id='type-id-1'/>
     <type-decl name='long int' size-in-bits='64' id='type-id-2'/>
-    <union-decl name='A' size-in-bits='64' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-2.c' line='1' column='1' id='type-id-3'>
+    <union-decl name='A' size-in-bits='64' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-2.c' line='4' column='1' id='type-id-3'>
       <data-member access='public'>
         <var-decl name='' type-id='type-id-4' visibility='default'/>
       </data-member>
@@ -13,19 +13,19 @@ 
         <var-decl name='' type-id='type-id-5' visibility='default'/>
       </data-member>
     </union-decl>
-    <class-decl name='__anonymous_struct__' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-2.c' line='2' column='1' id='type-id-4'>
+    <class-decl name='__anonymous_struct__' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-2.c' line='5' column='1' id='type-id-4'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='x' type-id='type-id-1' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-2.c' line='3' column='1'/>
+        <var-decl name='x' type-id='type-id-1' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-2.c' line='6' column='1'/>
       </data-member>
     </class-decl>
-    <class-decl name='__anonymous_struct__1' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-2.c' line='5' column='1' id='type-id-5'>
+    <class-decl name='__anonymous_struct__1' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-2.c' line='8' column='1' id='type-id-5'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='y' type-id='type-id-2' visibility='default' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-2.c' line='6' column='1'/>
+        <var-decl name='y' type-id='type-id-2' visibility='default' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-2.c' line='9' column='1'/>
       </data-member>
     </class-decl>
     <pointer-type-def type-id='type-id-3' size-in-bits='64' id='type-id-6'/>
-    <function-decl name='fun' mangled-name='fun' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-2.c' line='10' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fun'>
-      <parameter type-id='type-id-6' name='a' filepath='/home/dodji/git/libabigail/fixes/tests/data/test-read-dwarf/test-PR26568-2.c' line='10' column='1'/>
+    <function-decl name='fun' mangled-name='fun' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-2.c' line='13' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fun'>
+      <parameter type-id='type-id-6' name='a' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test-PR26568-2.c' line='13' column='1'/>
       <return type-id='type-id-7'/>
     </function-decl>
     <type-decl name='void' id='type-id-7'/>
diff --git a/tests/data/test-read-dwarf/test-PR26568-2.c b/tests/data/test-read-common/test-PR26568-2.c
similarity index 56%
rename from tests/data/test-read-dwarf/test-PR26568-2.c
rename to tests/data/test-read-common/test-PR26568-2.c
index 656e8eea..6a439746 100644
--- a/tests/data/test-read-dwarf/test-PR26568-2.c
+++ b/tests/data/test-read-common/test-PR26568-2.c
@@ -1,3 +1,6 @@ 
+/* gcc -std=c89 -gctf -g -mtune=generic -march=x86-64 -c \
+ *     -o test-PR26568-2.o test-PR26568-2.c */
+
 union A {
   struct {
     int x;
diff --git a/tests/data/test-read-dwarf/test3-alias-1.so.hash.abi b/tests/data/test-read-common/test3-alias-1-dwarf.so.hash.abi
similarity index 57%
rename from tests/data/test-read-dwarf/test3-alias-1.so.hash.abi
rename to tests/data/test-read-common/test3-alias-1-dwarf.so.hash.abi
index 02795ad0..b3a4801a 100644
--- a/tests/data/test-read-dwarf/test3-alias-1.so.hash.abi
+++ b/tests/data/test-read-common/test3-alias-1-dwarf.so.hash.abi
@@ -1,12 +1,12 @@ 
-<abi-corpus version='2.1' path='data/test-read-dwarf/test3.so' soname='test3.so.1'>
+<abi-corpus version='2.1' path='data/test-read-common/test3.so' soname='test3.so.1'>
   <elf-needed>
     <dependency name='libc.so.6'/>
   </elf-needed>
   <elf-function-symbols>
     <elf-symbol name='__foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
-  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf' language='LANG_C89'>
-    <function-decl name='__foo' mangled-name='__foo' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test3.c' line='8' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
+  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
+    <function-decl name='__foo' mangled-name='__foo' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test3.c' line='23' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
       <return type-id='48b5725f'/>
     </function-decl>
     <type-decl name='void' id='48b5725f'/>
diff --git a/tests/data/test-read-dwarf/test3-alias-1.suppr b/tests/data/test-read-common/test3-alias-1.suppr
similarity index 100%
rename from tests/data/test-read-dwarf/test3-alias-1.suppr
rename to tests/data/test-read-common/test3-alias-1.suppr
diff --git a/tests/data/test-read-dwarf/test3-alias-2.so.hash.abi b/tests/data/test-read-common/test3-alias-2-dwarf.so.hash.abi
similarity index 73%
rename from tests/data/test-read-dwarf/test3-alias-2.so.hash.abi
rename to tests/data/test-read-common/test3-alias-2-dwarf.so.hash.abi
index 775a9a97..07a7f2c4 100644
--- a/tests/data/test-read-dwarf/test3-alias-2.so.hash.abi
+++ b/tests/data/test-read-common/test3-alias-2-dwarf.so.hash.abi
@@ -1,4 +1,4 @@ 
-<abi-corpus version='2.1' path='data/test-read-dwarf/test3.so' soname='test3.so.1'>
+<abi-corpus version='2.1' path='data/test-read-common/test3.so' soname='test3.so.1'>
   <elf-needed>
     <dependency name='libc.so.6'/>
   </elf-needed>
@@ -9,8 +9,8 @@ 
     <elf-symbol name='foo' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
     <elf-symbol name='foo__' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
-  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf' language='LANG_C89'>
-    <function-decl name='__foo' mangled-name='__foo' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test3.c' line='8' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
+  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
+    <function-decl name='__foo' mangled-name='__foo' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test3.c' line='23' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
       <return type-id='48b5725f'/>
     </function-decl>
     <type-decl name='void' id='48b5725f'/>
diff --git a/tests/data/test-read-dwarf/test3-alias-2.suppr b/tests/data/test-read-common/test3-alias-2.suppr
similarity index 100%
rename from tests/data/test-read-dwarf/test3-alias-2.suppr
rename to tests/data/test-read-common/test3-alias-2.suppr
diff --git a/tests/data/test-read-dwarf/test3-alias-3.so.hash.abi b/tests/data/test-read-common/test3-alias-3-dwarf.so.hash.abi
similarity index 57%
rename from tests/data/test-read-dwarf/test3-alias-3.so.hash.abi
rename to tests/data/test-read-common/test3-alias-3-dwarf.so.hash.abi
index 6c604948..7908bdb8 100644
--- a/tests/data/test-read-dwarf/test3-alias-3.so.hash.abi
+++ b/tests/data/test-read-common/test3-alias-3-dwarf.so.hash.abi
@@ -1,12 +1,12 @@ 
-<abi-corpus version='2.1' path='data/test-read-dwarf/test3.so' soname='test3.so.1'>
+<abi-corpus version='2.1' path='data/test-read-common/test3.so' soname='test3.so.1'>
   <elf-needed>
     <dependency name='libc.so.6'/>
   </elf-needed>
   <elf-function-symbols>
     <elf-symbol name='foo' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
-  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf' language='LANG_C89'>
-    <function-decl name='__foo' mangled-name='__foo' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test3.c' line='8' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
+  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
+    <function-decl name='__foo' mangled-name='__foo' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test3.c' line='23' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
       <return type-id='48b5725f'/>
     </function-decl>
     <type-decl name='void' id='48b5725f'/>
diff --git a/tests/data/test-read-dwarf/test3-alias-3.suppr b/tests/data/test-read-common/test3-alias-3.suppr
similarity index 100%
rename from tests/data/test-read-dwarf/test3-alias-3.suppr
rename to tests/data/test-read-common/test3-alias-3.suppr
diff --git a/tests/data/test-read-dwarf/test3-alias-4.so.hash.abi b/tests/data/test-read-common/test3-alias-4-dwarf.so.hash.abi
similarity index 74%
rename from tests/data/test-read-dwarf/test3-alias-4.so.hash.abi
rename to tests/data/test-read-common/test3-alias-4-dwarf.so.hash.abi
index 912c710c..22a56fa5 100644
--- a/tests/data/test-read-dwarf/test3-alias-4.so.hash.abi
+++ b/tests/data/test-read-common/test3-alias-4-dwarf.so.hash.abi
@@ -1,4 +1,4 @@ 
-<abi-corpus version='2.1' path='data/test-read-dwarf/test3.so' soname='test3.so.1'>
+<abi-corpus version='2.1' path='data/test-read-common/test3.so' soname='test3.so.1'>
   <elf-needed>
     <dependency name='libc.so.6'/>
   </elf-needed>
diff --git a/tests/data/test-read-dwarf/test3-alias-4.suppr b/tests/data/test-read-common/test3-alias-4.suppr
similarity index 100%
rename from tests/data/test-read-dwarf/test3-alias-4.suppr
rename to tests/data/test-read-common/test3-alias-4.suppr
diff --git a/tests/data/test-read-common/test3-ctf.so.abi b/tests/data/test-read-common/test3-ctf.so.abi
new file mode 100644
index 00000000..9d55fec5
--- /dev/null
+++ b/tests/data/test-read-common/test3-ctf.so.abi
@@ -0,0 +1,12 @@ 
+<abi-corpus version='2.1' path='data/test-read-common/test3.so'>
+  <elf-function-symbols>
+    <elf-symbol name='__foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='__foo__' 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='foo' type='func-type' binding='weak-binding' visibility='default-visibility' alias='foo__,__foo__,__foo' is-defined='yes'/>
+    <elf-symbol name='foo__' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-common/test3-ctf.so.hash.abi b/tests/data/test-read-common/test3-ctf.so.hash.abi
new file mode 100644
index 00000000..9d55fec5
--- /dev/null
+++ b/tests/data/test-read-common/test3-ctf.so.hash.abi
@@ -0,0 +1,12 @@ 
+<abi-corpus version='2.1' path='data/test-read-common/test3.so'>
+  <elf-function-symbols>
+    <elf-symbol name='__foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='__foo__' 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='foo' type='func-type' binding='weak-binding' visibility='default-visibility' alias='foo__,__foo__,__foo' is-defined='yes'/>
+    <elf-symbol name='foo__' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-dwarf/test3.so.abi b/tests/data/test-read-common/test3-dwarf.so.abi
similarity index 75%
rename from tests/data/test-read-dwarf/test3.so.abi
rename to tests/data/test-read-common/test3-dwarf.so.abi
index 04032c74..a9bf781f 100644
--- a/tests/data/test-read-dwarf/test3.so.abi
+++ b/tests/data/test-read-common/test3-dwarf.so.abi
@@ -1,4 +1,4 @@ 
-<abi-corpus version='2.1' path='data/test-read-dwarf/test3.so' soname='test3.so.1'>
+<abi-corpus version='2.1' path='data/test-read-common/test3.so' soname='test3.so.1'>
   <elf-needed>
     <dependency name='libc.so.6'/>
   </elf-needed>
@@ -10,8 +10,8 @@ 
     <elf-symbol name='foo' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
     <elf-symbol name='foo__' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
-  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf' language='LANG_C89'>
-    <function-decl name='__foo' mangled-name='__foo' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test3.c' line='8' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
+  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
+    <function-decl name='__foo' mangled-name='__foo' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test3.c' line='23' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
       <return type-id='type-id-1'/>
     </function-decl>
     <type-decl name='void' id='type-id-1'/>
diff --git a/tests/data/test-read-dwarf/test3.so.hash.abi b/tests/data/test-read-common/test3-dwarf.so.hash.abi
similarity index 75%
rename from tests/data/test-read-dwarf/test3.so.hash.abi
rename to tests/data/test-read-common/test3-dwarf.so.hash.abi
index ea9ddc02..f429b22f 100644
--- a/tests/data/test-read-dwarf/test3.so.hash.abi
+++ b/tests/data/test-read-common/test3-dwarf.so.hash.abi
@@ -1,4 +1,4 @@ 
-<abi-corpus version='2.1' path='data/test-read-dwarf/test3.so' soname='test3.so.1'>
+<abi-corpus version='2.1' path='data/test-read-common/test3.so' soname='test3.so.1'>
   <elf-needed>
     <dependency name='libc.so.6'/>
   </elf-needed>
@@ -10,8 +10,8 @@ 
     <elf-symbol name='foo' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
     <elf-symbol name='foo__' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
-  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf' language='LANG_C89'>
-    <function-decl name='__foo' mangled-name='__foo' filepath='/home/skumari/Tasks/source_repo/dodji/libabigail/tests/data/test-read-dwarf/test3.c' line='8' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
+  <abi-instr address-size='64' path='test3.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C89'>
+    <function-decl name='__foo' mangled-name='__foo' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test3.c' line='23' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='__foo'>
       <return type-id='48b5725f'/>
     </function-decl>
     <type-decl name='void' id='48b5725f'/>
diff --git a/tests/data/test-read-common/test3.c b/tests/data/test-read-common/test3.c
new file mode 100644
index 00000000..0d8e7f87
--- /dev/null
+++ b/tests/data/test-read-common/test3.c
@@ -0,0 +1,26 @@ 
+/*
+ * Test file for creating multiple alias for a symbol
+ *
+ * NOTE: linking with _old_ crti.o exposes _init and _fini as
+ *       global symbols, the newer versions don't.
+ *
+ * 0000000000000000 g     F .init  0000000000000000 .hidden _init
+ * 0000000000000000 g     F .fini  0000000000000000 .hidden _fini
+ *
+ * This test is looking for those symbols which are not experted.
+ * So it's linked with dummy crti.o to avoid false positives.
+ *
+ * gcc -std=c89 -shared -gctf -g -mtune=generic -march=x86-64 -fPIC \
+ *     -nostartfiles -Wl,-soname=test3.so.1 -o test3.so test3.c crti.o
+ *
+ */
+
+void __foo(void);
+void foo(void) __attribute__((weak, alias("__foo")));
+void foo__(void) __attribute__((weak, alias("__foo")));
+void __foo__(void) __attribute__((alias("__foo")));
+
+void __foo(void)
+{
+
+}
diff --git a/tests/data/test-read-common/test3.so b/tests/data/test-read-common/test3.so
new file mode 100755
index 0000000000000000000000000000000000000000..3dfb69e998b5d91dcadc283974557ec294e2c074
GIT binary patch
literal 14824
zcmeHOPiz!b7=N?d(n4V={{&K!P7FjK?(DW;!yhZHrKQ9|um+<>GtTbLb~kos$nF$d
z5+f&4q9z<YcpxEB;?a{FOiVbNG<q;zlnWO<0491dv3|dq@7s>U6s*L=!~2rAzxTfP
zeeb>b%{Om$cfNUld}<<N7)m6oUQjD7rAD~p=3%jb?ugnzpF7m{(6(cx>!I40*+?a*
zdZRYx=tPy<N!$^c(Htx>zi>X2^$A>JwV;fP`PQMYzy>E0C<iUb^JU0vEq>iREY|p_
zbr#u9Q2buG8&v*{-#PXxn$f^X+{^O`hI5eaW%3J;kNY17OpBV9b^b#>g;s<^7ZqT9
zUaSZ4Aa+z$;2w6+p}>Ccw<>eFV<e1N^uzCJYq6(#rM3CiM-Orxw?AL_`MZ0$&+h+{
zqpnp2<35cU`GBw{$a*Si`pu-@O7>j|d-y@090zd=eJ){-<4Chtwq5o8=+m~9UH9sN
zva1AYwq7b*E#Deaf!hiWp*ldLXweL41~dbj0nLDBKr^5j&<tn>Gy`j6;QZv(yVu^j
z{dZW~5ZYQZpc&8%Xa+O`ngPv#W<WEb8PE)91~dbjf&V!Jcz$Y9!L!#>XV24fR^w~v
z@SGBo;day_eP8zYUTWa^>C(OB<q^W~3Ew9Ck?=AhWP1e4xHPSd`Cg-MV^{Yz8gvio
zQ5MNIeC9fu>%Ed0+qCXQGT^@F3H?X(ze)YCuF_9kS~LTi0nLDBKr^5j&<tn>Gy|Fe
z&46Y=Gw=`t@;kSWdn9RiAGbF$O5X1#vE#g6{8olsKr%APZ+|ZP!0X(`?`p^*elU|r
z&hs7a-w>%)k+Fwy7vp~or^d#PnfvLN{{eGg&?;I*bFer#FhIrJ@6KOvoArk41<vdN
z^(-wVS~TaXCo-FpD;+0Ar!qogV;eP$VKGVZ%z!9k=elGbweg8Ewix?z+j_G7ef?XE
ztzEr4X&sh2u{)bP)^oh)XwNgdp&r?FX*UfqNu^VDtAiNMF#gDG0^lrDp-O*v!ZSvH
zW^*Q7Px#SksP!3{I=j=D%4Es-qF=9YUiO^#j_1GY;V%+%?8wo_aAoEj!JOv~&$u2D
zSf-}aEZ2tTj|}C94x9Oza!{pDGv5j-!{wtzGhaP-dQ25+e#0%47D@{Rzv+}`-9oEb
zE>QNjQ>xE6_1OZ_zgvZh6F6Zt-*lZyzU(&|zQ?KIWjfAu!C`l(2g}J`<h!ToVV9=I
zsUxzKlJ_TINCNJW*)Q)MgiZQD)THIR<8_j>{CNELla_yPt)f4+%J?I!m+MyY``bj7
zn?c<wEBoZ@XGhNv`?gKz)*hd<C#FZwjN6kZr&p5k!!&$O&<_*yfBmULHj4H?Wi(+Z
z*bz_=_$c_d>?JC=cIYfzo**QVjUbFiYCjcLo+Jjspg2Uw6vnNxS__T9DG>(E2y0TC
z@#d_W)2b<}vfz<fgh5kTfjb{4%ku-*g3*PhPg_8+pe(m$SDQ}5wQChJlUC^HH0ot#
zAr5J$ph{3BwOg8-v7M&l&A2UT*1f7Pb*EHnx)-H2TlZY4(;}q`wT<?ZOFs>PErz$<
z_I@q<w(P&WO^0U=v&#OC`@`?c%f9$u=ZYZW7LxRjv`X!x3ifvKzrz*5n{0^r5DADJ
zh};MARL9ujFZUBcSwDOr5>`=5spnWHVJDlNVEa8Qc1ZdkCq1qqnO~V~$e5g8*3VYz
zELAY3_{%;ah^r(n!n^43pKsj%H8biFoEJmJ<os3A<Jjf=wD&K0e~AxR<`sYJcM#mv
zVUj#fQQ&?P7ap#C9<V;q#qEX;MXeigWs2>4DLS|u<OL<ym7MFtRs7#z$I}=rCQ1K~
zsV}L6`3?3*e8wed`zduMb+BJz|EaihitQJyOCIMQeibVG(iIy+<`VpB75@*|AKzBu
zB7Sj{*p1sQvA@ZN_@aY2llYPA7x&qA?8OGSKNvM8Vmef1UQutMN}B%<96#TPA!E}2
EFPZjRv;Y7A

literal 0
HcmV?d00001

diff --git a/tests/data/test-read-common/test4-ctf.so.abi b/tests/data/test-read-common/test4-ctf.so.abi
new file mode 100644
index 00000000..b8e0ead3
--- /dev/null
+++ b/tests/data/test-read-common/test4-ctf.so.abi
@@ -0,0 +1,14 @@ 
+<abi-corpus version='2.1' path='data/test-read-common/test4.so'>
+  <elf-function-symbols>
+    <elf-symbol name='cpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='char' size-in-bits='8' alignment-in-bits='8' id='type-id-1'/>
+    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-2'/>
+    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-3'/>
+    <qualified-type-def type-id='type-id-3' restrict='yes' id='type-id-4'/>
+    <qualified-type-def type-id='type-id-1' const='yes' id='type-id-5'/>
+    <pointer-type-def type-id='type-id-5' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
+    <qualified-type-def type-id='type-id-6' restrict='yes' id='type-id-7'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-common/test4-ctf.so.hash.abi b/tests/data/test-read-common/test4-ctf.so.hash.abi
new file mode 100644
index 00000000..dbe34d9c
--- /dev/null
+++ b/tests/data/test-read-common/test4-ctf.so.hash.abi
@@ -0,0 +1,14 @@ 
+<abi-corpus version='2.1' path='data/test-read-common/test4.so'>
+  <elf-function-symbols>
+    <elf-symbol name='cpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='char' size-in-bits='8' alignment-in-bits='8' id='a84c031d'/>
+    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
+    <pointer-type-def type-id='a84c031d' size-in-bits='64' alignment-in-bits='64' id='26a90f95'/>
+    <qualified-type-def type-id='26a90f95' restrict='yes' id='266fe297'/>
+    <qualified-type-def type-id='a84c031d' const='yes' id='9b45d938'/>
+    <pointer-type-def type-id='9b45d938' size-in-bits='64' alignment-in-bits='64' id='80f4b756'/>
+    <qualified-type-def type-id='80f4b756' restrict='yes' id='9d26089a'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-dwarf/test4.so.abi b/tests/data/test-read-common/test4-dwarf.so.abi
similarity index 56%
rename from tests/data/test-read-dwarf/test4.so.abi
rename to tests/data/test-read-common/test4-dwarf.so.abi
index 71f64da3..c38fff66 100644
--- a/tests/data/test-read-dwarf/test4.so.abi
+++ b/tests/data/test-read-common/test4-dwarf.so.abi
@@ -1,11 +1,11 @@ 
-<abi-corpus version='2.1' path='data/test-read-dwarf/test4.so'>
+<abi-corpus version='2.1' path='data/test-read-common/test4.so'>
   <elf-needed>
     <dependency name='libc.so.6'/>
   </elf-needed>
   <elf-function-symbols>
     <elf-symbol name='cpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
-  <abi-instr address-size='64' path='test4.c' comp-dir-path='/home/mark/src/tests' language='LANG_C89'>
+  <abi-instr address-size='64' path='test4.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C99'>
     <type-decl name='char' size-in-bits='8' id='type-id-1'/>
     <type-decl name='unsigned int' size-in-bits='32' id='type-id-2'/>
     <pointer-type-def type-id='type-id-1' size-in-bits='64' id='type-id-3'/>
@@ -13,10 +13,10 @@ 
     <qualified-type-def type-id='type-id-1' const='yes' id='type-id-5'/>
     <pointer-type-def type-id='type-id-5' size-in-bits='64' id='type-id-6'/>
     <qualified-type-def type-id='type-id-6' restrict='yes' id='type-id-7'/>
-    <function-decl name='cpy' mangled-name='cpy' filepath='/home/mark/src/tests/test4.c' line='2' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cpy'>
-      <parameter type-id='type-id-4' name='s1' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
-      <parameter type-id='type-id-7' name='s2' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
-      <parameter type-id='type-id-2' name='n' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
+    <function-decl name='cpy' mangled-name='cpy' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cpy'>
+      <parameter type-id='type-id-4' name='s1' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
+      <parameter type-id='type-id-7' name='s2' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
+      <parameter type-id='type-id-2' name='n' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
       <return type-id='type-id-3'/>
     </function-decl>
   </abi-instr>
diff --git a/tests/data/test-read-dwarf/test4.so.hash.abi b/tests/data/test-read-common/test4-dwarf.so.hash.abi
similarity index 55%
rename from tests/data/test-read-dwarf/test4.so.hash.abi
rename to tests/data/test-read-common/test4-dwarf.so.hash.abi
index 471ff895..7223f5eb 100644
--- a/tests/data/test-read-dwarf/test4.so.hash.abi
+++ b/tests/data/test-read-common/test4-dwarf.so.hash.abi
@@ -1,11 +1,11 @@ 
-<abi-corpus version='2.1' path='data/test-read-dwarf/test4.so'>
+<abi-corpus version='2.1' path='data/test-read-common/test4.so'>
   <elf-needed>
     <dependency name='libc.so.6'/>
   </elf-needed>
   <elf-function-symbols>
     <elf-symbol name='cpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
   </elf-function-symbols>
-  <abi-instr address-size='64' path='test4.c' comp-dir-path='/home/mark/src/tests' language='LANG_C89'>
+  <abi-instr address-size='64' path='test4.c' comp-dir-path='/home/byby/oracle/src/libabigail/tests/data/test-read-common' language='LANG_C99'>
     <type-decl name='char' size-in-bits='8' id='a84c031d'/>
     <type-decl name='unsigned int' size-in-bits='32' id='f0981eeb'/>
     <pointer-type-def type-id='a84c031d' size-in-bits='64' id='26a90f95'/>
@@ -13,10 +13,10 @@ 
     <qualified-type-def type-id='a84c031d' const='yes' id='9b45d938'/>
     <pointer-type-def type-id='9b45d938' size-in-bits='64' id='80f4b756'/>
     <qualified-type-def type-id='80f4b756' restrict='yes' id='9d26089a'/>
-    <function-decl name='cpy' mangled-name='cpy' filepath='/home/mark/src/tests/test4.c' line='2' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cpy'>
-      <parameter type-id='266fe297' name='s1' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
-      <parameter type-id='9d26089a' name='s2' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
-      <parameter type-id='f0981eeb' name='n' filepath='/home/mark/src/tests/test4.c' line='2' column='1'/>
+    <function-decl name='cpy' mangled-name='cpy' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cpy'>
+      <parameter type-id='266fe297' name='s1' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
+      <parameter type-id='9d26089a' name='s2' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
+      <parameter type-id='f0981eeb' name='n' filepath='/home/byby/oracle/src/libabigail/tests/data/test-read-common/test4.c' line='4' column='1'/>
       <return type-id='26a90f95'/>
     </function-decl>
   </abi-instr>
diff --git a/tests/data/test-read-common/test4.c b/tests/data/test-read-common/test4.c
new file mode 100644
index 00000000..ad274022
--- /dev/null
+++ b/tests/data/test-read-common/test4.c
@@ -0,0 +1,11 @@ 
+// gcc -shared -gctf -gdwarf-3 -mtune=generic -march=x86-64 -std=c99 -fPIC -o test4.so test4.c
+
+char *
+cpy (char * restrict s1, const char * restrict s2, unsigned int n)
+{
+  char *t1 = s1;
+  const char *t2 = s2;
+  while(n-- > 0)
+    *t1++ = *t2++;
+  return s1;
+}
diff --git a/tests/data/test-read-common/test4.so b/tests/data/test-read-common/test4.so
new file mode 100755
index 0000000000000000000000000000000000000000..0394bf5cc4404c29b1627258d9b11319035bd671
GIT binary patch
literal 16560
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
Ww9?1oO`$gaIeKwITIB=ySn+Q+OAa^y

literal 0
HcmV?d00001

diff --git a/tests/data/test-read-ctf/test-alias.c b/tests/data/test-read-ctf/test-alias.c
new file mode 100644
index 00000000..1b497a18
--- /dev/null
+++ b/tests/data/test-read-ctf/test-alias.c
@@ -0,0 +1,15 @@ 
+
+// function aliases
+
+void main_func(void);
+void alias_func(void) __attribute__((weak, alias("main_func")));
+
+void main_func(void)
+{
+
+}
+
+// variables aliases
+
+int main_var;
+extern int alias_var __attribute__((weak, alias("main_var")));
diff --git a/tests/data/test-read-ctf/test-alias.o.abi b/tests/data/test-read-ctf/test-alias.o.abi
new file mode 100644
index 00000000..1fe61b8f
--- /dev/null
+++ b/tests/data/test-read-ctf/test-alias.o.abi
@@ -0,0 +1,19 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test-alias.o'>
+  <elf-function-symbols>
+    <elf-symbol name='alias_func' type='func-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='main_func' type='func-type' binding='global-binding' visibility='default-visibility' alias='alias_func,main_var,alias_var' is-defined='yes'/>
+  </elf-function-symbols>
+  <elf-variable-symbols>
+    <elf-symbol name='alias_var' size='4' type='object-type' binding='weak-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='main_var' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='95e97e5e'/>
+    <function-decl name='main_func' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+      <return type-id='48b5725f'/>
+    </function-decl>
+    <var-decl name='alias_var' type-id='95e97e5e' mangled-name='alias_var' visibility='default'/>
+    <var-decl name='main_var' type-id='95e97e5e' mangled-name='main_var' visibility='default'/>
+    <type-decl name='void' id='48b5725f'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-ambiguous-struct-A.c b/tests/data/test-read-ctf/test-ambiguous-struct-A.c
new file mode 100644
index 00000000..67047c44
--- /dev/null
+++ b/tests/data/test-read-ctf/test-ambiguous-struct-A.c
@@ -0,0 +1,8 @@ 
+struct A;
+struct B { struct A *a; };
+struct A { struct B b; long foo; long bar; struct B b2; };
+
+typedef struct A a_array[50];
+a_array *foo __attribute__((__used__));
+
+static struct A a __attribute ((__used__));
diff --git a/tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi b/tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi
new file mode 100644
index 00000000..922a1daf
--- /dev/null
+++ b/tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi
@@ -0,0 +1,36 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test-ambiguous-struct-A.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='foo' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <array-type-def dimensions='1' type-id='3ed987a4' size-in-bits='12800' alignment-in-bits='64' id='e022be37'>
+      <subrange length='50' type-id='7359adad' id='3c1860ce'/>
+    </array-type-def>
+    <class-decl name='A' size-in-bits='256' alignment-in-bits='64' is-struct='yes' visibility='default' id='3ed987a4'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='b' type-id='41d98c5d' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='64'>
+        <var-decl name='foo' type-id='bd54fe1a' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='128'>
+        <var-decl name='bar' type-id='bd54fe1a' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='192'>
+        <var-decl name='b2' type-id='41d98c5d' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <class-decl name='B' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='41d98c5d'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='a' type-id='84d5ac12' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='bd54fe1a'/>
+    <typedef-decl name='a_array' type-id='e022be37' id='1c12b755'/>
+    <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='7359adad'/>
+    <pointer-type-def type-id='3ed987a4' size-in-bits='64' alignment-in-bits='64' id='84d5ac12'/>
+    <pointer-type-def type-id='1c12b755' size-in-bits='64' alignment-in-bits='64' id='55cd64e8'/>
+    <var-decl name='a' type-id='3ed987a4' mangled-name='a' visibility='default'/>
+    <var-decl name='foo' type-id='55cd64e8' mangled-name='foo' visibility='default'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-ambiguous-struct-B.c b/tests/data/test-read-ctf/test-ambiguous-struct-B.c
new file mode 100644
index 00000000..95a93469
--- /dev/null
+++ b/tests/data/test-read-ctf/test-ambiguous-struct-B.c
@@ -0,0 +1,5 @@ 
+struct A;
+struct B { struct A *a; };
+struct A { struct B b; int foo; struct B b2; };
+
+static struct A a __attribute__((__used__));
diff --git a/tests/data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi b/tests/data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi
new file mode 100644
index 00000000..28291eb5
--- /dev/null
+++ b/tests/data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi
@@ -0,0 +1,23 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test-ambiguous-struct-B.o'>
+  <abi-instr address-size='64' language='LANG_C'>
+    <class-decl name='A' size-in-bits='192' alignment-in-bits='64' is-struct='yes' visibility='default' id='3ed987a4'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='b' type-id='41d98c5d' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='64'>
+        <var-decl name='foo' type-id='95e97e5e' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='128'>
+        <var-decl name='b2' type-id='41d98c5d' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <class-decl name='B' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='41d98c5d'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='a' type-id='84d5ac12' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='95e97e5e'/>
+    <pointer-type-def type-id='3ed987a4' size-in-bits='64' alignment-in-bits='64' id='84d5ac12'/>
+    <var-decl name='a' type-id='3ed987a4' mangled-name='a' visibility='default'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-conflicting-type-syms-a.c b/tests/data/test-read-ctf/test-conflicting-type-syms-a.c
new file mode 100644
index 00000000..65414877
--- /dev/null
+++ b/tests/data/test-read-ctf/test-conflicting-type-syms-a.c
@@ -0,0 +1,5 @@ 
+typedef long a_t;
+typedef long b_t;
+
+a_t *a;
+b_t ignore2;
diff --git a/tests/data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi b/tests/data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi
new file mode 100644
index 00000000..03dd56b3
--- /dev/null
+++ b/tests/data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi
@@ -0,0 +1,14 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test-conflicting-type-syms-a.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='a' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='ignore2' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='bd54fe1a'/>
+    <typedef-decl name='a_t' type-id='bd54fe1a' id='40acc204'/>
+    <typedef-decl name='b_t' type-id='bd54fe1a' id='b3d2db81'/>
+    <pointer-type-def type-id='40acc204' size-in-bits='64' alignment-in-bits='64' id='c6fd4117'/>
+    <var-decl name='a' type-id='c6fd4117' mangled-name='a' visibility='default'/>
+    <var-decl name='ignore2' type-id='b3d2db81' mangled-name='ignore2' visibility='default'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-conflicting-type-syms-b.c b/tests/data/test-read-ctf/test-conflicting-type-syms-b.c
new file mode 100644
index 00000000..e458021e
--- /dev/null
+++ b/tests/data/test-read-ctf/test-conflicting-type-syms-b.c
@@ -0,0 +1,5 @@ 
+typedef long a_t;
+typedef long b_t;
+
+a_t b;
+b_t ignore1;
diff --git a/tests/data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi b/tests/data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi
new file mode 100644
index 00000000..35bcac7a
--- /dev/null
+++ b/tests/data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi
@@ -0,0 +1,13 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test-conflicting-type-syms-b.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='b' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='ignore1' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='bd54fe1a'/>
+    <typedef-decl name='a_t' type-id='bd54fe1a' id='40acc204'/>
+    <typedef-decl name='b_t' type-id='bd54fe1a' id='b3d2db81'/>
+    <var-decl name='b' type-id='40acc204' mangled-name='b' visibility='default'/>
+    <var-decl name='ignore1' type-id='b3d2db81' mangled-name='ignore1' visibility='default'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-enum-ctf.c b/tests/data/test-read-ctf/test-enum-ctf.c
new file mode 100644
index 00000000..aa60d727
--- /dev/null
+++ b/tests/data/test-read-ctf/test-enum-ctf.c
@@ -0,0 +1,8 @@ 
+/* Looked up item by item. */
+enum e { ENUMSAMPLE_1 = 0, ENUMSAMPLE_2 = 1 };
+
+/* Looked up via both sorts of iterator in turn.  */
+enum ie { IENUMSAMPLE_1 = -10, IENUMSAMPLE_2, IENUMSAMPLE_3 };
+
+enum e foo;
+enum ie bar;
diff --git a/tests/data/test-read-ctf/test-enum-ctf.o.abi b/tests/data/test-read-ctf/test-enum-ctf.o.abi
new file mode 100644
index 00000000..f36f3fad
--- /dev/null
+++ b/tests/data/test-read-ctf/test-enum-ctf.o.abi
@@ -0,0 +1,24 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test-enum-ctf.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='bar' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='foo' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='type-id-1'/>
+    <enum-decl name='e' linkage-name='e' id='type-id-2'>
+      <underlying-type type-id='type-id-1'/>
+      <enumerator name='ENUMSAMPLE_1' value='0'/>
+      <enumerator name='ENUMSAMPLE_2' value='1'/>
+    </enum-decl>
+    <enum-decl name='ie' linkage-name='ie' id='type-id-3'>
+      <underlying-type type-id='type-id-1'/>
+      <enumerator name='IENUMSAMPLE_1' value='-10'/>
+      <enumerator name='IENUMSAMPLE_2' value='-9'/>
+      <enumerator name='IENUMSAMPLE_3' value='-8'/>
+    </enum-decl>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-4'/>
+    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-5'/>
+    <var-decl name='foo' type-id='type-id-2' mangled-name='foo' visibility='default'/>
+    <var-decl name='bar' type-id='type-id-3' mangled-name='bar' visibility='default'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-enum-many-ctf.c b/tests/data/test-read-ctf/test-enum-many-ctf.c
new file mode 100644
index 00000000..f2297d72
--- /dev/null
+++ b/tests/data/test-read-ctf/test-enum-many-ctf.c
@@ -0,0 +1,10 @@ 
+/* Looked up item by item. */
+enum e { ENUMSAMPLE_1 = 0, ENUMSAMPLE_2 = 1 };
+
+/* Looked up via both sorts of iterator in turn.  */
+enum ie { IE_0 = -10, IE_1, IE_2, IE_3, IE_4, IE_5, IE_6, IE_7, IE_8, IE_9, IE_A, IE_B, IE_C, IE_D, IE_E, IE_F,
+	  IE_10, IE_11, IE_12, IE_13, IE_14, IE_15, IE_16, IE_17, IE_18, IE_19, IE_1A, IE_1B, IE_1C, IE_1D, IE_1E, IE_1F,
+	  IE_20, IE_21, IE_22, IE_23, IE_24, IE_25, IE_26, IE_27, IE_28, IE_29, IE_2A, IE_2B, IE_2C, IE_2D, IE_2E, IE_2F};
+
+enum e foo;
+enum ie bar;
diff --git a/tests/data/test-read-ctf/test-enum-many-ctf.o.hash.abi b/tests/data/test-read-ctf/test-enum-many-ctf.o.hash.abi
new file mode 100644
index 00000000..67a958a7
--- /dev/null
+++ b/tests/data/test-read-ctf/test-enum-many-ctf.o.hash.abi
@@ -0,0 +1,69 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test-enum-many-ctf.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='bar' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='foo' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='811c9dc5'/>
+    <enum-decl name='e' linkage-name='e' id='a6c2eddf'>
+      <underlying-type type-id='811c9dc5'/>
+      <enumerator name='ENUMSAMPLE_1' value='0'/>
+      <enumerator name='ENUMSAMPLE_2' value='1'/>
+    </enum-decl>
+    <enum-decl name='ie' linkage-name='ie' id='1ee696ca'>
+      <underlying-type type-id='811c9dc5'/>
+      <enumerator name='IE_0' value='-10'/>
+      <enumerator name='IE_1' value='-9'/>
+      <enumerator name='IE_2' value='-8'/>
+      <enumerator name='IE_3' value='-7'/>
+      <enumerator name='IE_4' value='-6'/>
+      <enumerator name='IE_5' value='-5'/>
+      <enumerator name='IE_6' value='-4'/>
+      <enumerator name='IE_7' value='-3'/>
+      <enumerator name='IE_8' value='-2'/>
+      <enumerator name='IE_9' value='-1'/>
+      <enumerator name='IE_A' value='0'/>
+      <enumerator name='IE_B' value='1'/>
+      <enumerator name='IE_C' value='2'/>
+      <enumerator name='IE_D' value='3'/>
+      <enumerator name='IE_E' value='4'/>
+      <enumerator name='IE_F' value='5'/>
+      <enumerator name='IE_10' value='6'/>
+      <enumerator name='IE_11' value='7'/>
+      <enumerator name='IE_12' value='8'/>
+      <enumerator name='IE_13' value='9'/>
+      <enumerator name='IE_14' value='10'/>
+      <enumerator name='IE_15' value='11'/>
+      <enumerator name='IE_16' value='12'/>
+      <enumerator name='IE_17' value='13'/>
+      <enumerator name='IE_18' value='14'/>
+      <enumerator name='IE_19' value='15'/>
+      <enumerator name='IE_1A' value='16'/>
+      <enumerator name='IE_1B' value='17'/>
+      <enumerator name='IE_1C' value='18'/>
+      <enumerator name='IE_1D' value='19'/>
+      <enumerator name='IE_1E' value='20'/>
+      <enumerator name='IE_1F' value='21'/>
+      <enumerator name='IE_20' value='22'/>
+      <enumerator name='IE_21' value='23'/>
+      <enumerator name='IE_22' value='24'/>
+      <enumerator name='IE_23' value='25'/>
+      <enumerator name='IE_24' value='26'/>
+      <enumerator name='IE_25' value='27'/>
+      <enumerator name='IE_26' value='28'/>
+      <enumerator name='IE_27' value='29'/>
+      <enumerator name='IE_28' value='30'/>
+      <enumerator name='IE_29' value='31'/>
+      <enumerator name='IE_2A' value='32'/>
+      <enumerator name='IE_2B' value='33'/>
+      <enumerator name='IE_2C' value='34'/>
+      <enumerator name='IE_2D' value='35'/>
+      <enumerator name='IE_2E' value='36'/>
+      <enumerator name='IE_2F' value='37'/>
+    </enum-decl>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='95e97e5e'/>
+    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
+    <var-decl name='foo' type-id='a6c2eddf' mangled-name='foo' visibility='default'/>
+    <var-decl name='bar' type-id='1ee696ca' mangled-name='bar' visibility='default'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-enum-symbol-ctf.c b/tests/data/test-read-ctf/test-enum-symbol-ctf.c
new file mode 100644
index 00000000..f7f99c67
--- /dev/null
+++ b/tests/data/test-read-ctf/test-enum-symbol-ctf.c
@@ -0,0 +1 @@ 
+enum {red1, green1, blue1} primary1;
diff --git a/tests/data/test-read-ctf/test-enum-symbol-ctf.o.hash.abi b/tests/data/test-read-ctf/test-enum-symbol-ctf.o.hash.abi
new file mode 100644
index 00000000..fea6eb8b
--- /dev/null
+++ b/tests/data/test-read-ctf/test-enum-symbol-ctf.o.hash.abi
@@ -0,0 +1,16 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test-enum-symbol-ctf.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='primary1' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='811c9dc5'/>
+    <enum-decl name='' is-anonymous='yes' id='08f5ca17'>
+      <underlying-type type-id='811c9dc5'/>
+      <enumerator name='red1' value='0'/>
+      <enumerator name='green1' value='1'/>
+      <enumerator name='blue1' value='2'/>
+    </enum-decl>
+    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
+    <var-decl name='primary1' type-id='08f5ca17' mangled-name='primary1' visibility='default'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-struct-iteration-ctf.c b/tests/data/test-read-ctf/test-struct-iteration-ctf.c
new file mode 100644
index 00000000..7df67ada
--- /dev/null
+++ b/tests/data/test-read-ctf/test-struct-iteration-ctf.c
@@ -0,0 +1,28 @@ 
+#include <unistd.h>
+
+struct foo_t
+{
+  int foo;
+  size_t bar;
+  const char *baz;
+  struct foo_t *self;
+  union
+  {
+    double should_not_appear;
+    char *nor_should_this;
+  } named;
+  struct
+  {
+    long unnamed_sub_member;
+    union
+    {
+      double one_more_level;
+      long yes_really_one_more;
+    };
+  };
+  struct {};		/* Empty ones */
+  union {};
+  int after_the_end;
+};
+
+struct foo_t used;
diff --git a/tests/data/test-read-ctf/test-struct-iteration-ctf.o.abi b/tests/data/test-read-ctf/test-struct-iteration-ctf.o.abi
new file mode 100644
index 00000000..72e0bdc3
--- /dev/null
+++ b/tests/data/test-read-ctf/test-struct-iteration-ctf.o.abi
@@ -0,0 +1,96 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test-struct-iteration-ctf.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='used' size='64' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='char' size-in-bits='8' alignment-in-bits='8' id='type-id-1'/>
+    <class-decl name='' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-2'/>
+    <class-decl name='' size-in-bits='128' alignment-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-3'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='unnamed_sub_member' type-id='type-id-4' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='64'>
+        <var-decl name='' type-id='type-id-5' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='one_more_level' type-id='type-id-6' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='yes_really_one_more' type-id='type-id-4' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <class-decl name='foo_t' size-in-bits='512' alignment-in-bits='32' is-struct='yes' visibility='default' id='type-id-7'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='foo' type-id='type-id-8' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='64'>
+        <var-decl name='bar' type-id='type-id-9' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='128'>
+        <var-decl name='baz' type-id='type-id-10' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='192'>
+        <var-decl name='self' type-id='type-id-11' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='256'>
+        <var-decl name='named' type-id='type-id-12' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='64'>
+        <var-decl name='' type-id='type-id-3' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='unnamed_sub_member' type-id='type-id-4' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='64'>
+        <var-decl name='' type-id='type-id-5' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='one_more_level' type-id='type-id-6' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='yes_really_one_more' type-id='type-id-4' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='64'>
+        <var-decl name='' type-id='type-id-2' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='64'>
+        <var-decl name='' type-id='type-id-13' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='448'>
+        <var-decl name='after_the_end' type-id='type-id-8' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <type-decl name='double' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-8'/>
+    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-4'/>
+    <type-decl name='short int' size-in-bits='16' alignment-in-bits='16' id='type-id-14'/>
+    <type-decl name='signed char' size-in-bits='8' alignment-in-bits='8' id='type-id-15'/>
+    <typedef-decl name='size_t' type-id='type-id-16' id='type-id-9'/>
+    <union-decl name='' size-in-bits='64' is-anonymous='yes' visibility='default' id='type-id-12'>
+      <data-member access='public'>
+        <var-decl name='should_not_appear' type-id='type-id-6' visibility='default'/>
+      </data-member>
+      <data-member access='public'>
+        <var-decl name='nor_should_this' type-id='type-id-17' visibility='default'/>
+      </data-member>
+    </union-decl>
+    <union-decl name='' is-anonymous='yes' visibility='default' id='type-id-13'/>
+    <union-decl name='' size-in-bits='64' is-anonymous='yes' visibility='default' id='type-id-5'>
+      <data-member access='public'>
+        <var-decl name='one_more_level' type-id='type-id-6' visibility='default'/>
+      </data-member>
+      <data-member access='public'>
+        <var-decl name='yes_really_one_more' type-id='type-id-4' visibility='default'/>
+      </data-member>
+    </union-decl>
+    <type-decl name='unsigned char' size-in-bits='8' alignment-in-bits='8' id='type-id-18'/>
+    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-19'/>
+    <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='type-id-16'/>
+    <type-decl name='unsigned short int' size-in-bits='16' alignment-in-bits='16' id='type-id-20'/>
+    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-17'/>
+    <qualified-type-def type-id='type-id-1' const='yes' id='type-id-21'/>
+    <pointer-type-def type-id='type-id-21' size-in-bits='64' alignment-in-bits='64' id='type-id-10'/>
+    <pointer-type-def type-id='type-id-7' size-in-bits='64' alignment-in-bits='64' id='type-id-11'/>
+    <var-decl name='used' type-id='type-id-7' mangled-name='used' visibility='default'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test0 b/tests/data/test-read-ctf/test0
new file mode 100755
index 0000000000000000000000000000000000000000..aca7fbacdfff7ad2caf0142390710373a8da72a1
GIT binary patch
literal 16656
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

literal 0
HcmV?d00001

diff --git a/tests/data/test-read-ctf/test0.abi b/tests/data/test-read-ctf/test0.abi
new file mode 100644
index 00000000..50ca26f4
--- /dev/null
+++ b/tests/data/test-read-ctf/test0.abi
@@ -0,0 +1,54 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test0'>
+  <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='_start' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='foo_1' 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-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-symbol name='status' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='test_array' size='40' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='test_const' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='test_float' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='test_pointer' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='test_restrict' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='test_volatile' size='2' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='' is-anonymous='yes' size-in-bits='1' alignment-in-bits='8' id='type-id-1'/>
+    <type-decl name='char' size-in-bits='8' alignment-in-bits='8' id='type-id-2'/>
+    <class-decl name='S' size-in-bits='32' alignment-in-bits='32' is-struct='yes' visibility='default' id='type-id-3'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='m0' type-id='type-id-4' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <class-decl name='' size-in-bits='32' alignment-in-bits='8' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-5'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='status0' type-id='type-id-1' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='1'>
+        <var-decl name='status1' type-id='type-id-1' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <type-decl name='float' size-in-bits='32' alignment-in-bits='32' id='type-id-6'/>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-4'/>
+    <array-type-def dimensions='1' type-id='type-id-4' size-in-bits='320' alignment-in-bits='32' id='type-id-7'>
+      <subrange length='10' type-id='type-id-8' id='type-id-9'/>
+    </array-type-def>
+    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-10'/>
+    <type-decl name='short int' size-in-bits='16' alignment-in-bits='16' id='type-id-11'/>
+    <type-decl name='signed char' size-in-bits='8' alignment-in-bits='8' id='type-id-12'/>
+    <type-decl name='unsigned char' size-in-bits='8' alignment-in-bits='8' id='type-id-13'/>
+    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-14'/>
+    <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
+    <type-decl name='unsigned short int' size-in-bits='16' alignment-in-bits='16' id='type-id-15'/>
+    <pointer-type-def type-id='type-id-3' size-in-bits='64' alignment-in-bits='64' id='type-id-16'/>
+    <pointer-type-def type-id='type-id-2' size-in-bits='64' alignment-in-bits='64' id='type-id-17'/>
+    <qualified-type-def type-id='type-id-3' const='yes' id='type-id-18'/>
+    <pointer-type-def type-id='type-id-10' size-in-bits='64' alignment-in-bits='64' id='type-id-19'/>
+    <qualified-type-def type-id='type-id-19' restrict='yes' id='type-id-20'/>
+    <qualified-type-def type-id='type-id-11' volatile='yes' id='type-id-21'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test0.c b/tests/data/test-read-ctf/test0.c
new file mode 100644
index 00000000..eb702312
--- /dev/null
+++ b/tests/data/test-read-ctf/test0.c
@@ -0,0 +1,32 @@ 
+
+#include <stdio.h>
+
+char* test_pointer = NULL;
+int test_array[10] = {0};
+volatile short test_volatile = 1;
+float test_float = 0.0;
+
+struct {
+  unsigned int status0 : 1;
+  unsigned int status1 : 1;
+} status;
+
+
+struct S
+{
+  int m0;
+};
+
+const struct S test_const;
+long* restrict test_restrict;
+
+int
+foo_1(struct S* s)
+{
+  return s->m0;
+}
+
+int main()
+{
+
+}
diff --git a/tests/data/test-read-ctf/test0.hash.abi b/tests/data/test-read-ctf/test0.hash.abi
new file mode 100644
index 00000000..b58520ab
--- /dev/null
+++ b/tests/data/test-read-ctf/test0.hash.abi
@@ -0,0 +1,54 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test0'>
+  <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='_start' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='foo_1' 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-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-symbol name='status' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='test_array' size='40' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='test_const' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='test_float' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='test_pointer' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='test_restrict' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='test_volatile' size='2' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='' is-anonymous='yes' size-in-bits='1' alignment-in-bits='8' id='811c9dc5'/>
+    <type-decl name='char' size-in-bits='8' alignment-in-bits='8' id='a84c031d'/>
+    <class-decl name='S' size-in-bits='32' alignment-in-bits='32' is-struct='yes' visibility='default' id='50d9a3fa'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='m0' type-id='95e97e5e' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <class-decl name='' size-in-bits='32' alignment-in-bits='8' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f72'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='status0' type-id='811c9dc5' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='1'>
+        <var-decl name='status1' type-id='811c9dc5' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <type-decl name='float' size-in-bits='32' alignment-in-bits='32' id='a6c45d85'/>
+    <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='95e97e5e'/>
+    <array-type-def dimensions='1' type-id='95e97e5e' size-in-bits='320' alignment-in-bits='32' id='b7bd1749'>
+      <subrange length='10' type-id='7359adad' id='487da03a'/>
+    </array-type-def>
+    <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='bd54fe1a'/>
+    <type-decl name='short int' size-in-bits='16' alignment-in-bits='16' id='a2185560'/>
+    <type-decl name='signed char' size-in-bits='8' alignment-in-bits='8' id='28577a57'/>
+    <type-decl name='unsigned char' size-in-bits='8' alignment-in-bits='8' id='002ac4a6'/>
+    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
+    <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='7359adad'/>
+    <type-decl name='unsigned short int' size-in-bits='16' alignment-in-bits='16' id='8efea9e5'/>
+    <pointer-type-def type-id='50d9a3fa' size-in-bits='64' alignment-in-bits='64' id='fd01f598'/>
+    <pointer-type-def type-id='a84c031d' size-in-bits='64' alignment-in-bits='64' id='26a90f95'/>
+    <qualified-type-def type-id='50d9a3fa' const='yes' id='0fb3b55d'/>
+    <pointer-type-def type-id='bd54fe1a' size-in-bits='64' alignment-in-bits='64' id='3ccc2590'/>
+    <qualified-type-def type-id='3ccc2590' restrict='yes' id='af4b1b38'/>
+    <qualified-type-def type-id='a2185560' volatile='yes' id='ec67e496'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test1.c b/tests/data/test-read-ctf/test1.c
new file mode 100644
index 00000000..3a5bac49
--- /dev/null
+++ b/tests/data/test-read-ctf/test1.c
@@ -0,0 +1,25 @@ 
+enum opaque_enum;
+struct opaque_struct;
+
+typedef enum opaque_enum opaque_enum;
+typedef struct opaque_struct opaque_struct;
+
+void
+fn(opaque_struct *, opaque_enum *e);
+
+enum opaque_enum
+{
+  e0,
+  e1
+};
+
+struct opaque_struct
+{
+  opaque_enum m0;
+};
+
+void
+fn(opaque_struct * s, opaque_enum *e)
+{
+  s->m0 = *e;
+}
diff --git a/tests/data/test-read-ctf/test1.so b/tests/data/test-read-ctf/test1.so
new file mode 100755
index 0000000000000000000000000000000000000000..df5ef8d38fa53081007cab96424e3d60b512751f
GIT binary patch
literal 15592
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
I@1C^(7v)NDpa1{>

literal 0
HcmV?d00001

diff --git a/tests/data/test-read-ctf/test1.so.abi b/tests/data/test-read-ctf/test1.so.abi
new file mode 100644
index 00000000..5b3caf63
--- /dev/null
+++ b/tests/data/test-read-ctf/test1.so.abi
@@ -0,0 +1,23 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test1.so'>
+  <elf-function-symbols>
+    <elf-symbol name='fn' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='type-id-1'/>
+    <class-decl name='opaque_struct' size-in-bits='32' alignment-in-bits='32' is-struct='yes' visibility='default' id='type-id-2'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='m0' type-id='type-id-3' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <enum-decl name='opaque_enum' linkage-name='opaque_enum' id='type-id-4'>
+      <underlying-type type-id='type-id-1'/>
+      <enumerator name='e0' value='0'/>
+      <enumerator name='e1' value='1'/>
+    </enum-decl>
+    <typedef-decl name='opaque_enum' type-id='type-id-4' id='type-id-3'/>
+    <typedef-decl name='opaque_struct' type-id='type-id-2' id='type-id-5'/>
+    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='type-id-6'/>
+    <pointer-type-def type-id='type-id-3' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
+    <pointer-type-def type-id='type-id-5' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test1.so.hash.abi b/tests/data/test-read-ctf/test1.so.hash.abi
new file mode 100644
index 00000000..8019cb54
--- /dev/null
+++ b/tests/data/test-read-ctf/test1.so.hash.abi
@@ -0,0 +1,23 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test1.so'>
+  <elf-function-symbols>
+    <elf-symbol name='fn' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <type-decl name='' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='811c9dc5'/>
+    <class-decl name='opaque_struct' size-in-bits='32' alignment-in-bits='32' is-struct='yes' visibility='default' id='6cde5052'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='m0' type-id='99fcd3a5' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <enum-decl name='opaque_enum' linkage-name='opaque_enum' id='55763a91'>
+      <underlying-type type-id='811c9dc5'/>
+      <enumerator name='e0' value='0'/>
+      <enumerator name='e1' value='1'/>
+    </enum-decl>
+    <typedef-decl name='opaque_enum' type-id='55763a91' id='99fcd3a5'/>
+    <typedef-decl name='opaque_struct' type-id='6cde5052' id='dae69ca1'/>
+    <type-decl name='unsigned int' size-in-bits='32' alignment-in-bits='32' id='f0981eeb'/>
+    <pointer-type-def type-id='99fcd3a5' size-in-bits='64' alignment-in-bits='64' id='0e0526e0'/>
+    <pointer-type-def type-id='dae69ca1' size-in-bits='64' alignment-in-bits='64' id='3f6e71d0'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test2.c b/tests/data/test-read-ctf/test2.c
new file mode 100644
index 00000000..b04490a8
--- /dev/null
+++ b/tests/data/test-read-ctf/test2.c
@@ -0,0 +1,19 @@ 
+struct S0
+{
+  void* m0;
+};
+
+typedef const void* POINTER;
+
+struct S1
+{
+  POINTER m0;
+};
+
+void foo(struct S0* a __attribute__((unused)))
+{
+}
+
+void bar(struct S1* a __attribute__((unused)))
+{
+}
diff --git a/tests/data/test-read-ctf/test2.so b/tests/data/test-read-ctf/test2.so
new file mode 100755
index 0000000000000000000000000000000000000000..d9c07517527553d99951c2129da2f2ae6c1bce03
GIT binary patch
literal 15616
zcmeHOZD<_F8J;^^u@WaIxrtL(F3H9uV4HaFq{OLPLwu5a@;Q-YN0y->HJiP=mF~iw
zR_v}^Db%#oZLu(J{ilEW0r^!7{SiVS7z)LSi`_yBO8@i&N<v72XaZ5bS|x;R-gjo6
z(`s`Hp|qtxX3XyUJ@3pjvwI`&%y&zpBiT$wpllKkiZw}yqBayCfCuXih;F*?6n)Zn
z^P1^1+;MFL6}`%Zb96DQ<upB`8vzPCt7VlI2UD@+y-i=#B4{%12C@}w<xqHVJzdfH
zRy9RjmfSe5sN;${4)iJQ58AD&6~|wXYM<B6d$k`ZFnomKINuj7fNw(Q+o*p_x}Bit
z<|azCg)Yv?Jla9593S|x%vkWn<HmZ9**ruyBCKQiH;<p&x)`3@%F0fK+iP_&aDAQh
zj87;12<dmxl`fBx;!9$ysBcpiG~}e#pGxV4<4m{w87GX~AaWex9Gx6<YF^+?H^RsZ
zCdY=G{){*2R+^r&b+$OwdDoe0%(%_Qlb)FJeNk}((QH(zcIev=h$Ev%hlZU2d%)h$
z?aIi1S$S9OWX&mJF`jdMjT;&5X=N6eub5wBx*rGhe1!fct=~~pfzU&K<&e_zSTW`(
z%LzS?G0I9p&+`LiHK9+=8Q2Xq2p9wm0tNwtfI+|@U=T0}7zF<R5GbF0tGj%@>+g9X
z%0IjkW#gst+23_vZ8tRD|0<c{dtRe^&z(i$ULbDj;>q&j>lE8tzR>koj$JIRme140
z^g`D)R(-v+8r@5EFDUy8*;mNEQa*cTMMSqs@xu0>OY5KGr8hGd|8P}TYf&BF|4g;p
zeO7UnJxk^1S2vXxUnoESk3;3mQu!s$tZTlHa&A|_%jCUGmSxJhETTS{^ZZFtU84+^
zbh;k@Nv3|U=Z=p!ea~}UTgcG!+!X?3ZVy$qM1T7;I6cI_#{A;-<@Y~{<K=(R?ONAg
zNR^=~PF+P6%lqRvCRz4o@yzOaR!Gd(q1=YsFa`mGfI+|@U=T0}7z7Lg1_6VBLBJqj
z5csbkklDHEAb(@!Z+O;99G8g}h|Ur{^-dh0BU&eVi71!b6cL#xCq!nxH?#BRE!`LC
zL*m_}|0-QeZ^yCxhMDUf$?bTkXY04Szb6j$9o&20-STrS#~-HaGWp@#B#AQiTSWgz
zx#c(8!Cdc;vctFBFhU8m{X0Z2Z(t{rDFy+9fI+|@U=T0}7z7Lg1_6VBLBJsJA4CBA
zPO;Avdq{cjDwmrTX>Vk`Maz-im--bgV?XOoE#q&&J}qNkEB{T&1@`t{Q@u&`gHK|g
z?FB8%J>{&>n^k$AE0=F-`%Ov|p{Cd$yhF?FJ+4Ki;JwjYE@=bWaY?BKZPJwm@$^Ml
zw&$Gorw_qW22S+ntCS;c|4_^Ayt=;s6~R9CbUy4CJ~BM~4Quz2@soS3{sFsS7p#H8
zKz~17)^2Zp)(aXfZzgh^d(su8WbXfF@lKpl%lVR}{n`hx@mV|Mh_e1CDg9kqkNJoC
zzD7(&Y!_BhX@K{z)b|R^CuJ4l31YZ@%xCCNOaGqserxD|N=&ErZ`7|}%6f9*_ZDhc
zqn+ycHJP)72A&gmKSNB0{?`TL0sU{Kew#>--*xFgPn`u%MgK;G>j6Hnz9IFu3Q>ec
z(T|B_`Ke3cpQR34>s_UE2kATQyWh2ef4}xm@5kT2f&Vem@9L0ORD&pt=BB3Xs#x2$
z??f%9${Y7X+TUOEo$01uahpyp@`KQE=jKJ#Z_PHn$gA0f&K|s(zu~w+;4U~c!Gi@c
z6}T<Wsm--o3lx%&9P*6Txkg?X4N!v|XJle<tmKr&5A)Fiu9CBbzEgK+YJ8&L@T22{
zV@HQcOOKdSD(isq;R#aF;RA#o89g>MIO-f5897m!bS4LfMoUy7C;r?M3w#J6b-;no
zCdfk$U*I4^F?np^-Iq7>Ln#Xl#=639#pHFFWIl<(Z%2N^K1>(I^s&z)baCM~-lXK@
z!4c+AZ7!?yd>=^gIez=|6HR3=zv;*6O4o}wKACcOdy~)YTo30@lpGSmj$a3nulp@8
zUs<Ru<o&>{HobfpRP%J6!>u%?-9|IdLmcL7ZsbaKU*Ng5ebs16N<8+*j~yMKEKP_L
z1#zNZv<l+1->3;;hYPL9tq_d@MeE?EXXfm>8`gzgTbLm?MWaC2Y&q=(VZ)zUCpcsa
zyr#<m!j`kao^3|<v>ypO^5*F-=bY`;^@Oe0C<KxUQ8QP0f~Wf2R-;PE{D^C$rch6X
zT?s>B)3d|xd}5-h1epIGdnbkQNVZ2AjHU%$Eq)&{f>;Oe`r)7S8;UTj13-6g5U<tZ
z9%6WgA|C4m&`a8p^YLs!e*E6=BOSL5@mP0&Vx2)QvS7wR=Ho!TMnF8)1)zB3(0}-W
z4pBU>IUr-*0cz<)>Go^2d>Yw?c&u~UR68Pny8n-no%_^&>hOD^>6djp2*wTav&1Ch
zEgc7n>fjF<)J??~v;h?DMLc9sUI!%eV;ur|kd29w62&aplJWTc2F3aiRiyi`)*Ea1
z3rl-y%HL*^B_00*GID;5U%^t|pubRJ`;LA?@nd3mj$wSUF2^~-v_E9fpHXa2A|C6k
z12!qCz)wkQGW5S91J51g$9e|mEuYeWqu+?b_<Iz~E{MnZwpa3`q+-eY+70obPm?Jb
zFN)f?peUYmt!?)Q@%&4djK?}{hmMC|Ivz5w<Jbr7w~ESQZ4l47lI1E1tkdpo6XN%_
zHHtwz=!>KVpLE@OzmiHRV@i~<n0v|i<GMk!+Q@(R@wY$V0bKd{K;M(`R|b^yL@HrQ
U6x%k4_vJZDAzn&WN_;y0Q+>X1e*gdg

literal 0
HcmV?d00001

diff --git a/tests/data/test-read-ctf/test2.so.abi b/tests/data/test-read-ctf/test2.so.abi
new file mode 100644
index 00000000..eb6aff3e
--- /dev/null
+++ b/tests/data/test-read-ctf/test2.so.abi
@@ -0,0 +1,25 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test2.so'>
+  <elf-function-symbols>
+    <elf-symbol name='bar' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <class-decl name='S0' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='type-id-1'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='m0' type-id='type-id-2' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <class-decl name='S1' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='type-id-3'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='m0' type-id='type-id-4' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <typedef-decl name='POINTER' type-id='type-id-5' id='type-id-4'/>
+    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
+    <pointer-type-def type-id='type-id-3' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
+    <qualified-type-def type-id='type-id-8' const='yes' id='type-id-9'/>
+    <pointer-type-def type-id='type-id-9' size-in-bits='64' alignment-in-bits='64' id='type-id-5'/>
+    <pointer-type-def type-id='type-id-8' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
+    <type-decl name='void' id='type-id-8'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test2.so.hash.abi b/tests/data/test-read-ctf/test2.so.hash.abi
new file mode 100644
index 00000000..6e57333b
--- /dev/null
+++ b/tests/data/test-read-ctf/test2.so.hash.abi
@@ -0,0 +1,25 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test2.so'>
+  <elf-function-symbols>
+    <elf-symbol name='bar' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <class-decl name='S0' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='109cd6fe'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='m0' type-id='eaa32e2f' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <class-decl name='S1' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='119cd891'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='m0' type-id='8a34a235' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <typedef-decl name='POINTER' type-id='6e97a70c' id='8a34a235'/>
+    <pointer-type-def type-id='109cd6fe' size-in-bits='64' alignment-in-bits='64' id='842ea234'/>
+    <pointer-type-def type-id='119cd891' size-in-bits='64' alignment-in-bits='64' id='5e30a4f9'/>
+    <qualified-type-def type-id='48b5725f' const='yes' id='8581546e'/>
+    <pointer-type-def type-id='8581546e' size-in-bits='64' alignment-in-bits='64' id='6e97a70c'/>
+    <pointer-type-def type-id='48b5725f' size-in-bits='64' alignment-in-bits='64' id='eaa32e2f'/>
+    <type-decl name='void' id='48b5725f'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-dwarf/PR26261/Makefile b/tests/data/test-read-dwarf/PR26261/Makefile
deleted file mode 100644
index f66fa38a..00000000
--- a/tests/data/test-read-dwarf/PR26261/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@ 
-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
deleted file mode 100755
index 564a4247643942bbfd91c0e75653dffe80ce5851..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 10976
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

diff --git a/tests/data/test-read-dwarf/PR27700/test-PR27700.o b/tests/data/test-read-dwarf/PR27700/test-PR27700.o
deleted file mode 100644
index 3f084d2132f0f43a683769ea91e9733fc599700a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3248
zcmb_e&2Jl35TCbe$1dAAAFfJ6in1V}DZ*<zg{A~0xCHVczM`N=Ac3s4_t{>s*VTGc
zLJ^`85>f>cL2!d365@u0#6N(zapR7-AaUhZi37~+&T}@e8x;Yg_|433X5P%3_py2Z
zxfeDJAwZFUH8|1~3h-^=NN&Vp1I|Dh_O@>Qwsq^h+lO!b@Cm|s5Jj>YG~7=^nyi#!
zc7{VJ<X%I_5EI0bwDFh}WW=%wxm=t)PZ1(Fu1?J+zWf-YC)#M6BFXr)2Zf@85{N}G
zOXtzim=O<`%9gn>zc3?a3)A-km^on<*DTB0F0WWmSx;J`43K*WENjg&OSlwAJUwR?
z6WfJ33TvFZF-Kk#c~FM!vT+WeFoj{;Xo1J507?yUA7Y6HRqPmG;br7`^u2^!2=QlW
zk{GQKe<&;@lc8>)JY}MgB9RwxYV2|L1H;6a{b1yG1L@g*5W(h4d-i&L*{;`}np3lv
zYD;zcvln;KVatu!P^n$CD}!i1kgHu8$k1=2>W1y!>cN%EmCKLYl`dfWoAOe^Y6+_+
zYzeBp;Xqcsq4%a=?fOx*@3-8R-*x?db!T^JdAU}rMsgI5s-7FUu~-SE>s7qB-LRuv
zfLto<@3jA?N&TSR-}hw2^Fuv>mhW2VUw3){o9pW<_9Axf;y-8`@5UMC;>IqBgK05;
zx==jCEj*7n{fOc-aJ4l3p|L(Wv4IW=oH^17$iW|fWf^gkvtTg!<mpBeEm?#&D+@;N
zi4*YDBarei;Z#aH63r7%y$Pp}oKlhrc<nOCgsBV^Z!k>Wflnhco9fT_-f4SHZwZmw
zgL_a;uUgGaIIT|UvnUf0PQMLOkj^G-jI#>&u|PXEzNjca$~euTY9Q!p3a7kH);Bf0
z!}^OFK4AS74S$vO*EO6~z+)eiUZ?5_)tP4>V$^3M-T%P^9`|97^+z=P3)X8I{x$1Q
zX!!T6uW0y>tUt?Kug7MbdY|q;IHPw4k=sHZg$eH|DUt^fIP_A1(;AJy31#1PJlWds
zHvOP8L|ZJotyU<nA2Yk58+7IIkiH*C6@n?0NN_XO+rz;?;#=(m!$>;#?o>vR+kT5D
zmc3>tbO(|b@*mke##4{fzN+aOER639>*SlJ2T&nQe^H)KJEdej{sP+Qy#L$yI>zdA
zQaY9YGg4Bd`_lKBUcE-jCl>i|+Z-^1Ao;1gi68lxR&mtlB*QPU6(D4;nC`oS1|1{c
z9R}5XI4PdinN`2d8>-@|etNC-`aQ(5^50}oy&LEjlkQ9JQC9vP&VR^pl%L)&J^wYt
zXiilpiZT7ni6R9sSNRox7xAq4O}^Ye-6j5`6XMH!AggzY|D5ABH+V)r(Cnb<R{q~`
z{IRzPu`Q0jq8yp4{weq?6tepNEB9ZWQ|do`HC4RAsUAHyLU5Dw_qbsC&e7LckEcD&
eTI%mq6q5QsDADdbYgAWO{B5rPI~B-W@891PcJreE

diff --git a/tests/data/test-read-dwarf/test-PR26568-1.o b/tests/data/test-read-dwarf/test-PR26568-1.o
deleted file mode 100644
index 9249e16d4d52b4556b1cf071cc504d2a71204619..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2864
zcmbtV&2Jl35TCctADe9KIx)~j;jl<lZKUoxNfTp=Qd~lbD^L|h>IJDv*Y?_8u-Dak
z11<=0pddwnR3s!oLU4csHxLI7TtMOg{{VkN&xl(k4luL(p1pqAs8V^7-^~1GelzpF
z*6&_@<t2?Vkb}Wxm|7AAxSgBo^+>Hl8J6Hi<LG|l=$!|R53fG>J;F(A{H*75*$mfM
z<EV7=w;$1wiJW?r`&faqku#pO4C8fF`50J+6y#>Io*#myv)rp_@;kutqyS{~EQy@X
zv=C+9qG^{P{R-%ey^q?QLpIEJ4t-z?k&crr$-ev^EyF<<DcUDJSkNgKutj#ZST=ZZ
zrMSqJ@}<-0Ei=QoWISiEGPY3wu9I=CTr;rAr@=5T8(hb(gj&STPA3@o0$f9)US?dM
z=9wduGR)iT`Q<p}xn(L@Kl9lO%T&t9PD*KK02WSRDar&FsAXyvuxw(;)g_=veGz93
z&f(11Kg9yh(b?mHFbLgIXzlH9RJW=%Yu#?e+_^YC8r)#-eXW-@4OzR_Z<ssgrd_kQ
z%#F46t+ndLMf3c=+cq0c7~|H(XID*Y5FYyOcGvaYz-yuD1g+loxK_2Qo2J!;N^dxD
zEA3(XHLue3!b;z3I!&+Zc>PMp8@r<lH8rZVozRI?D{!5*)qc|nI?x~bU6by`@y2&|
zb}pIcvB}kk_ZTnpu~-0mYaiIS#8wva`aRs1ClRL~jc8M^6iXjyJB8dW42a>>8L4>X
z|Nb}4$x~k#Zm>8?mBZ1KHn@0Hs*gkBu_l}x@(F9Ia+sSM35^3@%9O#Okb+YGc;Qn9
zhsmp(c$ZLHO6<er!X7(JdbaqE1am&26C^Veo?OKuIdMq*<Jg49g_L+h*vmrFxlL|7
z>Z<~$_~d!tOyE@auCPB6Qq7a>KPzHLlun4>JOMWaPCX|31bcL65IRkiVGzrn)IxV0
zf=zD-?B-|$cHs6MyX`g)y9b`%8KN)Jon|v|-<WYbf#Y}GSxVpYT}i<bV7G>Yfs60Z
z_J^Ts<Eyhqq0@R@ByxKPoxmBmqVfMJR*+A7EB8~Ts|#gvkAzLJ$?+5#gsCs;r1n%k
zeLCqLJSu-()JHKhWc{CJ(74wmL?3+mE3GF%)W3`WU*T7Q)4d`{-dX(Dh{iU~>YB*0
zBEWB>sOhA}?x9P?DEb!xu1%?trpCUEXj=chY)q7V>Yu(=YX5D-)SSfpOMneB5<`tW
zKwnz@&qaN?PgI}YwOao+Vw6+%iE1>S5s&dJ2?#0cOZhh9Y5YG0-+l=HuHY+Sz|{*W
z0%Tno|ApYsd^-@+1-~W(g_P@;@TaJx?cWb6`$zu<k}vm_`cZ3B?z*VICmN>jH~q_~
hd^(e~rQV~aa6A!<$*iuQ@}}|s5dD8MVaAHe{|}8}$8i7v

diff --git a/tests/data/test-read-dwarf/test-PR26568-2.o b/tests/data/test-read-dwarf/test-PR26568-2.o
deleted file mode 100644
index cc94708c9cb10e2f0f5e51aed7e7a713767caaf8..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2824
zcmbtVQHvW@6h3!mlT3CtF`KB}WqlaI(k^r++wE?Mm9433-4sh%7W$x2)=6@cj3$#Z
znXRc(6clk0L_rZnw9p4%efCN4q2P}YU-|=lEBK)2%-owy?oKJ_fw}kG@0{<PbMM?U
z^TCyCuW5{d6b6@Iwvs47Gdt58k=lR?l;KA6_+j(-?xW^sR~|ixaMGH;7`bd_LDyLG
zxODTk`)F8*j7AjuM1s?iF&?x9rZrI2C%|-4kh_ra{17yQW!}W4eg{~V6o8D8p(%SA
z490Gwma}QtBhcs``M?%QC6PJU_xEs>chN+O_GKRy4Hq?F%j|TqV(P`U;xa4eN~h3T
zVWxS}e92@L%v%86pvBcn-NdS10Moo=>IRk})FPI0is{CTlPkbgq#6!;c{L`VS*75O
zm2X~IrJ(uDG^n-$u=o@PB?g?M;;1aZ1PPJ*NI;SLDvlbQ!I81Qiv=8`*NSJ&AmroF
z-apu^ZP)7drqhnO`8Yf-^gR3MN28)?$U5P>cm0O7Yi&7oXWQD`IKRD7+q__%J>VUy
z>4q_GUwCodvWMZ3&v$y<=YiM8r5m*SJCl0Nu5DR%532pqkXJjS&f8wK=Y`dQ*K%84
z&-Dh?t~cT1DrFv5J8tMksvU5*V|U(lgDwn4e$S#i0DHT;7p=2c)B2N3!ks-GZxz^k
z2f!vJwziZrzQ8ki4sm)&q7%JbEPbNw7P4=lLky>mNX4uC*FR}SJ+*W2bj5pAIXYU>
zL>JAX+H^=XVZx|GF0q=aI^<`Igr)=D-W1WHkb+YEc&}4Lhouu}8If}09HzJR#I>UC
z#C8!8s7<9#kc><??P8fg6gf*gMgg7?ip1X#>s2w+dz)T&)Yk=0{>k@!Gl5gyuf_VV
znAJG4W{Q&$J~WktuKI612Db!GH74r>XMATEx-Fc;AfEeD3;84jhx!Ga)_4p~zz43=
z;jN?Iq33r;Xp3~W)e89SIkOwMevi*n2A<C)1yg|29u0>ad(QDkA$PFl>~ZL}-w}a$
z|F9dlLoN#cpVJ!h>8#{=%5V*#Oz)9clW$U<#|2?(M?J1Ql~3PIx(EN2e_rIrX-;JR
zpXSiG)+9t<d-_E-k|63I#{W(DRp4~52$FXee;JYN;Hd723`+w1Jo1_is_#CURE)g8
z6X3>-8fmKU>xib+-^j#7$*211Yo*rTK}?NF%-;prq(wqh-$S&e<-aBJ%X6aq)YoeM
zTZmCiStqKIltnZCAOSJU{BnLD@ihL=g6}+m|FPgJZt%z4$6#iac_s3#;H&O`3ZO0>
z#Vq$P;jd6hJHJm;&X4{Ek}uDd>QQr3>=n^a`=Vg_e$!t@<<mP+dk-P#Q&A|-#?y3E
T_fK)t`1eHp_ovKQQThJ@<ln>C

diff --git a/tests/data/test-read-dwarf/test3.c b/tests/data/test-read-dwarf/test3.c
deleted file mode 100644
index 2808db4b..00000000
--- a/tests/data/test-read-dwarf/test3.c
+++ /dev/null
@@ -1,11 +0,0 @@ 
-// Test file for creating multiple alias for a symbol
-
-void __foo(void);
-void foo(void) __attribute__((weak, alias("__foo")));
-void foo__(void) __attribute__((weak, alias("__foo")));
-void __foo__(void) __attribute__((alias("__foo")));
-
-void __foo(void)
-{
-
-}
diff --git a/tests/data/test-read-dwarf/test3.so b/tests/data/test-read-dwarf/test3.so
deleted file mode 100755
index 4c426fc3c202d2f2dd027ffd8825ccfea36b2a09..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 8851
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
NGxzm*6T@y2`@a>G9{B(O

diff --git a/tests/data/test-read-dwarf/test4.c b/tests/data/test-read-dwarf/test4.c
deleted file mode 100644
index 7f0abaa1..00000000
--- a/tests/data/test-read-dwarf/test4.c
+++ /dev/null
@@ -1,14 +0,0 @@ 
-// Test file for restrict (needs to be compiled by a GCC that actually emits
-// DW_TAG_restrict_type. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59051
-//
-// gcc -gdwarf-3 -std=c99 -shared -nostartfiles -o test4.so test4.c
-
-char *
-cpy (char * restrict s1, const char * restrict s2, unsigned int n)
-{
-  char *t1 = s1;
-  const char *t2 = s2;
-  while(n-- > 0)
-    *t1++ = *t2++;
-  return s1;
-}
diff --git a/tests/data/test-read-dwarf/test4.so b/tests/data/test-read-dwarf/test4.so
deleted file mode 100755
index 3be3f0d644190425cbb2a08ed7b4f1d164c13ef1..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3364
zcmcImPiP!v6n`_b|JqG9o1{u1Dx+wdh?yj9NYj?oP0~#_x@}TzARc6#-JR?%W+!20
zViQq%s7hlABqHiTu!08#!HX0H4*_pIdGgf5UIIcd@mBN@-<$c~c6PF>i1@*L?|r}b
zdvCsZ-}k-wZe;T_vLpdF1ug)MGO~|kgkd`-6cia4hbZ>lkn*_EN2WtsUBqDtpn4p7
z2Zdz3F8eskU9?f#^?K@5Por@E#xLP{0nG2Yr3mUDi}{4*F~MU=TxwU*FYxI;_&0r8
z*c6oHN0MT-%aNE4GTJu<BV<BE%3n_azbf3jP^KXccNA41zIdh${&*W4imMy2TrCte
zXGI$W-7Fcd0lHpr9NlpZ+eOGK0W9P;_i~%>{+8QZt8Xsc&)v?Vnth0}j&lFOlc+t+
zZOu!$%>_gk_H$b=p?-P4>u%4j^zH2Zt@#7=dw+NBSMq)RXPl4Jr<|ue(l>s4aB%Pf
zN?sS~?N>lrPfL9r@x(R~o<JKt>&WwRFquk!AWwJ3<UBI`7-(+fpVxJff(P*9BEP)W
zw}kzuPlJ;}CWSmM<o_)$O;4Xw`!8Kt7*I#Gkzs9EJvBTsIy^QquJ)VjtEOG8nU-rT
z4*+G!{|JB2^N!)25uWJ}2+-~XNJz9hr0d=Q8e45gq=aBuqWvJr(nmPp$V`wv_h7{t
zLB<!v-dR+fQ#km_8_X*f>fd{MKH?%PLSf{cO2kE0^c!#R21FB|p%#;3H&Dch5+_qM
z@g4TQEfRkWb&$HH=Tf~%CDoVemU^T#u9~b#FLo%2bIJ3`lO40Y1ZR$ZI@KZd;%7#|
zx6Jm+xS)~IreU-TlF3=5#hyjw0!GCbp8-M=Cp-ZY_)Zy~qBl!_raH0rN+#|R30%{0
zN3|kN3*d;%$vL)n^X5?E$9pf!GSY`CD>ZYdX4r2IId*Y~d>mM_oNC!JOKR0}0hd^v
z{)aVI2W#${Wloe$3m3kKL&GjsCf3Kt2FFI#!E))kVJ{7yRtFuoG*LWzwlTM2#jpW1
zXQSpC1(dGs%L;21!>NE)+OUw~OV<X?HP>Cx%!<Bb8#Pm}ln~>Q$1-ZwB51{x8f`*E
z%)(k(H*CWyn+^}F*3t^=MxkJvZ}DikYMHF#MEnf?$G#8!sn+t|<#W!GP6;)(^Z$YC
z!qaG@GtPFd11z`685^A(;;=v0gMokzRp7e9lIsZBsEIP;53nB*7}ueUm<Y@8Y36xz
zfHT6M=ilx>$NaE=Hst@c2*h%n9fjoYXLt@3{_hdS|MR+tvr8a0zw$iFAOANO(MCBL
zCQ_i?5f0A>Fj6^xER6sbq}~($;kfL_+|@Sze+d7dm?&h}|D87ecSWKpez1l8KSW~~
zBmN0-ftU<Bx8Qyvu<&=5h5vhP{P~^TXy>&FQXdHaFM}ZJ?8h*TdG9es@)z+VO$%ch
zu^xPQ|M2-af>^8f*E`UF?V>Llefa$iLkmU0*>W8SniZTepYLW|X`J6?{P2B@><U&M
zK5xzZ81VUN#^a6i(TsCef+)qO>>O?ih~$P$idV@(APyA}$qbnk=nNtL`bOaQgF^-c
zTH!Q93GbhES#5HmwI)2=`VnY#kEJ@@>K=Q#4Ni5b6~FNd)GxkvW%BauH0YP|b5oOf
ceQsvv)$BF>+T>I|t9#d7zU0!yHh9zh3+<yQu>b%7

diff --git a/tests/test-annotate.cc b/tests/test-annotate.cc
index bc4ce852..174de483 100644
--- a/tests/test-annotate.cc
+++ b/tests/test-annotate.cc
@@ -42,12 +42,12 @@  InOutSpec in_out_specs[] =
     "output/test-annotate/test2.so.abi"
   },
   {
-    "data/test-read-dwarf/test3.so",
+    "data/test-read-common/test3.so",
     "data/test-annotate/test3.so.abi",
     "output/test-annotate/test3.so.abi"
   },
   {
-    "data/test-read-dwarf/test4.so",
+    "data/test-read-common/test4.so",
     "data/test-annotate/test4.so.abi",
     "output/test-annotate/test4.so.abi"
   },
diff --git a/tests/test-read-common.cc b/tests/test-read-common.cc
new file mode 100644
index 00000000..431a660e
--- /dev/null
+++ b/tests/test-read-common.cc
@@ -0,0 +1,184 @@ 
+// -*- Mode: C++ -*-
+//
+
+#include <fstream>
+#include <cstring>
+#include "test-read-common.h"
+
+using std::ofstream;
+using std::cerr;
+using std::dynamic_pointer_cast;
+
+using abigail::tools_utils::emit_prefix;
+using abigail::tests::get_build_dir;
+using abigail::xml_writer::write_context_sptr;
+using abigail::xml_writer::create_write_context;
+using abigail::xml_writer::write_corpus;
+
+namespace abigail
+{
+namespace tests
+{
+namespace read_common
+{
+
+test_task::test_task(const InOutSpec &s,
+                     string& a_out_abi_base,
+                     string& a_in_elf_base,
+                     string& a_in_abi_base)
+    : is_ok(true),
+      spec(s),
+      out_abi_base(a_out_abi_base),
+      in_elf_base(a_in_elf_base),
+      in_abi_base(a_in_abi_base)
+  {}
+
+bool
+test_task::serialize_corpus(const string& out_abi_path,
+                            corpus_sptr corp)
+{
+  ofstream of(out_abi_path.c_str(), std::ios_base::trunc);
+  if (!of.is_open())
+    {
+       error_message = string("failed to read ") + out_abi_path + "\n";
+       return false;
+    }
+
+  write_context_sptr write_ctxt
+      = create_write_context(corp->get_environment(), of);
+  set_type_id_style(*write_ctxt, spec.type_id_style);
+  is_ok = write_corpus(*write_ctxt, corp, /*indent=*/0);
+  of.close();
+
+  return true;
+}
+
+bool
+test_task::run_abidw(const string& extargs)
+{
+  string abidw = string(get_build_dir()) + "/tools/abidw";
+  string drop_private_types;
+  if (!in_public_headers_path.empty())
+    drop_private_types += "--headers-dir " + in_public_headers_path +
+      " --drop-private-types";
+  string cmd = abidw + " " + drop_private_types + " --abidiff " + extargs +
+   in_elf_path;
+  if (system(cmd.c_str()))
+    {
+      error_message = string("ABIs differ:\n")
+        + in_elf_path
+        + "\nand:\n"
+        + out_abi_path
+        + "\n";
+
+      return false;
+    }
+
+  return true;
+}
+
+bool
+test_task::run_diff()
+{
+  set_in_abi_path();
+  string cmd = "diff -u " + in_abi_path + " " + out_abi_path;
+  if (system(cmd.c_str()))
+    {
+      error_message = string("ABIs differ:\n")
+        + in_abi_path
+        + "\nand:\n"
+        + out_abi_path
+        + "\n";
+
+      return false;
+    }
+
+  return true;
+}
+
+void
+display_usage(const string& prog_name, ostream& out)
+{
+  emit_prefix(prog_name, out)
+    << "usage: " << prog_name << " [options]\n"
+    << " where options can be: \n"
+    << "  --help|-h  display this message\n"
+    << "  --no-parallel execute testsuite is a sigle thread\n"
+  ;
+}
+
+bool
+parse_command_line(int argc, char* argv[], options& opts)
+{
+  for (int i = 1; i < argc; ++i)
+    {
+      if (!strcmp(argv[i], "--no-parallel"))
+        opts.parallel = false;
+      else if (!strcmp(argv[i], "--help")
+               || !strcmp(argv[i], "--h"))
+        return false;
+      else
+        {
+          if (strlen(argv[i]) >= 2 && argv[i][0] == '-' && argv[i][1] == '-')
+            opts.wrong_option = argv[i];
+          return false;
+        }
+    }
+
+  return true;
+}
+
+bool
+run_tests(const size_t num_tests, const InOutSpec* specs,
+          const options& opts, create_new_test new_test)
+{
+  size_t num_workers = (opts.parallel
+                        ? std::min(abigail::workers::get_number_of_threads(),
+                                   num_tests)
+                        : 1);
+  abigail::workers::queue task_queue(num_workers);
+  bool is_ok = true;
+
+  string out_abi_base = string(get_build_dir()) + "/tests/";
+  string in_elf_base  = string(abigail::tests::get_src_dir()) + "/tests/";
+  string in_abi_base = in_elf_base;
+
+  for (const InOutSpec *s = specs; s->in_elf_path; ++s)
+    {
+      test_task_sptr t(new_test(s, out_abi_base,
+                                in_elf_base,
+                                in_abi_base));
+      ABG_ASSERT(task_queue.schedule_task(t));
+    }
+
+  /// Wait for all worker threads to finish their job, and wind down.
+  task_queue.wait_for_workers_to_complete();
+
+  // Now walk the results and print whatever error messages need to be
+  // printed.
+
+  const vector<abigail::workers::task_sptr>& completed_tasks =
+    task_queue.get_completed_tasks();
+
+  ABG_ASSERT(completed_tasks.size() == num_tests);
+
+  for (vector<abigail::workers::task_sptr>::const_iterator ti =
+         completed_tasks.begin();
+       ti != completed_tasks.end();
+       ++ti)
+    {
+      test_task_sptr t = dynamic_pointer_cast<test_task>(*ti);
+      if (!t->is_ok)
+        {
+          is_ok = false;
+          if (!t->error_message.empty())
+            cerr << t->error_message << '\n';
+        }
+    }
+
+  return !is_ok;
+}
+
+}//end namespace read_common
+}//end namespace tests
+}//end namespace abigail
diff --git a/tests/test-read-common.h b/tests/test-read-common.h
new file mode 100644
index 00000000..784f41f5
--- /dev/null
+++ b/tests/test-read-common.h
@@ -0,0 +1,148 @@ 
+#ifndef __TEST_READ_COMMON_H__
+#define __TEST_READ_COMMON_H__
+
+#include <string>
+#include "abg-ir.h"
+#include "abg-corpus.h"
+#include "abg-workers.h"
+#include "abg-writer.h"
+#include "test-utils.h"
+#include "abg-tools-utils.h"
+
+using std::string;
+
+using abigail::xml_writer::type_id_style_kind;
+using abigail::ir::corpus_sptr;
+
+namespace abigail
+{
+namespace tests
+{
+namespace read_common
+{
+
+/// This is an aggregate that specifies where a test shall get its
+/// input from, and where it shall write its ouput to.
+struct InOutSpec
+{
+  const char* in_elf_path;
+  const char* in_suppr_spec_path;
+  const char* in_public_headers_path;
+  type_id_style_kind type_id_style;
+  const char* in_abi_path;
+  const char* out_abi_path;
+};// end struct InOutSpec
+
+/// The task that peforms the tests.
+struct test_task : public abigail::workers::task
+{
+  bool is_ok;
+  InOutSpec spec;
+  string error_message;
+  string out_abi_base;
+  string in_elf_base;
+  string in_abi_base;
+
+  string in_elf_path;
+  string in_abi_path;
+  string in_suppr_spec_path;
+  string in_public_headers_path;
+  string out_abi_path;
+
+  void
+  set_in_elf_path()
+  {
+    in_elf_path = in_elf_base + spec.in_elf_path;
+  }
+
+  void
+  set_in_suppr_spec_path()
+  {
+    if (spec.in_suppr_spec_path)
+      in_suppr_spec_path = in_elf_base + spec.in_suppr_spec_path;
+    else
+      in_suppr_spec_path.clear();
+  }
+
+  void
+  set_in_public_headers_path()
+  {
+    if (spec.in_public_headers_path)
+      in_public_headers_path = spec.in_public_headers_path;
+    if (!in_public_headers_path.empty())
+      in_public_headers_path = in_elf_base + spec.in_public_headers_path;
+  }
+
+  bool
+  set_out_abi_path()
+  {
+    out_abi_path = out_abi_base + spec.out_abi_path;
+    if (!abigail::tools_utils::ensure_parent_dir_created(out_abi_path))
+      {
+          error_message =
+            string("Could not create parent directory for ") + out_abi_path;
+          return false;
+      }
+    return true;
+  }
+
+  void
+  set_in_abi_path()
+  {
+    in_abi_path = in_abi_base + spec.in_abi_path;
+  }
+
+  test_task(const InOutSpec &s,
+            string& a_out_abi_base,
+            string& a_in_elf_base,
+            string& a_in_abi_base);
+  bool
+  serialize_corpus(const string& out_abi_path,
+                   corpus_sptr corp);
+  bool
+  run_abidw(const string& extargs = "");
+
+  bool
+  run_diff();
+
+  virtual
+  ~test_task()
+  {}
+
+}; // end struct test_task
+
+typedef shared_ptr<test_task> test_task_sptr;
+
+struct options
+{
+  string        wrong_option;
+  bool          parallel;
+
+  options()
+    : parallel(true)
+  {}
+
+  ~options()
+  {
+  }
+};
+
+void
+display_usage(const string& prog_name, ostream& out);
+
+bool
+parse_command_line(int argc, char* argv[], options& opts);
+
+typedef test_task* (*create_new_test)(const InOutSpec* s,
+                                      string& a_out_abi_base,
+                                      string& a_in_elf_base,
+                                      string& a_in_abi_base);
+bool
+run_tests(const size_t num_test, const InOutSpec* specs,
+          const options& opts, create_new_test new_test);
+
+}//end namespace read_common
+}//end namespace tests
+}//end namespace abigail
+
+#endif //__TEST_READ_COMMON_H__
diff --git a/tests/test-read-ctf.cc b/tests/test-read-ctf.cc
new file mode 100644
index 00000000..e54cc3db
--- /dev/null
+++ b/tests/test-read-ctf.cc
@@ -0,0 +1,290 @@ 
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+// -*- Mode: C++ -*-
+//
+// Copyright (C) 2021 Oracle, Inc.
+//
+// Author: Guillermo E. Martinez
+
+/// @file read ELF binaries containing CTF, save them in XML corpus
+/// files and diff the corpus files against reference XML corpus
+/// files.
+
+#include <cstdlib>
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <vector>
+#include "abg-ctf-reader.h"
+#include "test-read-common.h"
+
+using std::string;
+using std::cerr;
+
+using abigail::tests::read_common::InOutSpec;
+using abigail::tests::read_common::test_task;
+using abigail::tests::read_common::display_usage;
+using abigail::tests::read_common::options;
+
+using abigail::ctf_reader::read_context_sptr;
+using abigail::ctf_reader::create_read_context;
+using abigail::xml_writer::SEQUENCE_TYPE_ID_STYLE;
+using abigail::xml_writer::HASH_TYPE_ID_STYLE;
+using abigail::tools_utils::emit_prefix;
+
+static InOutSpec in_out_specs[] =
+{
+  {
+    "data/test-read-ctf/test0",
+    "",
+    "",
+    SEQUENCE_TYPE_ID_STYLE,
+    "data/test-read-ctf/test0.abi",
+    "output/test-read-ctf/test0.abi"
+  },
+  {
+    "data/test-read-ctf/test0",
+    "",
+    "",
+    HASH_TYPE_ID_STYLE,
+    "data/test-read-ctf/test0.hash.abi",
+    "output/test-read-ctf/test0.hash.abi"
+  },
+  {
+    "data/test-read-ctf/test1.so",
+    "",
+    "",
+    SEQUENCE_TYPE_ID_STYLE,
+    "data/test-read-ctf/test1.so.abi",
+    "output/test-read-ctf/test1.so.abi"
+  },
+  {
+    "data/test-read-ctf/test1.so",
+    "",
+    "",
+    HASH_TYPE_ID_STYLE,
+    "data/test-read-ctf/test1.so.hash.abi",
+    "output/test-read-ctf/test1.so.hash.abi"
+  },
+  {
+    "data/test-read-ctf/test2.so",
+    "",
+    "",
+    SEQUENCE_TYPE_ID_STYLE,
+    "data/test-read-ctf/test2.so.abi",
+    "output/test-read-ctf/test2.so.abi"
+  },
+  {
+    "data/test-read-ctf/test2.so",
+    "",
+    "",
+    HASH_TYPE_ID_STYLE,
+    "data/test-read-ctf/test2.so.hash.abi",
+    "output/test-read-ctf/test2.so.hash.abi"
+  },
+  {
+    "data/test-read-common/test3.so",
+    "",
+    "",
+    SEQUENCE_TYPE_ID_STYLE,
+    "data/test-read-common/test3-ctf.so.abi",
+    "output/test-read-common/test3-ctf.so.abi"
+  },
+  {
+    "data/test-read-common/test3.so",
+    "",
+    "",
+    HASH_TYPE_ID_STYLE,
+    "data/test-read-common/test3-ctf.so.hash.abi",
+    "output/test-read-common/test3-ctf.so.hash.abi"
+  },
+  {
+    "data/test-read-ctf/test-enum-many-ctf.o",
+    "",
+    "",
+    HASH_TYPE_ID_STYLE,
+    "data/test-read-ctf/test-enum-many-ctf.o.hash.abi",
+    "output/test-read-ctf/test-enum-many-ctf.o.hash.abi"
+  },
+  {
+    "data/test-read-ctf/test-ambiguous-struct-A.o",
+    "",
+    "",
+    HASH_TYPE_ID_STYLE,
+    "data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi",
+    "output/test-read-ctf/test-ambiguous-struct-A.o.hash.abi"
+  },
+  {
+    "data/test-read-ctf/test-ambiguous-struct-B.o",
+    "",
+    "",
+    HASH_TYPE_ID_STYLE,
+    "data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi",
+    "output/test-read-ctf/test-ambiguous-struct-B.o.hash.abi"
+  },
+  {
+    "data/test-read-ctf/test-conflicting-type-syms-a.o",
+    "",
+    "",
+    HASH_TYPE_ID_STYLE,
+    "data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi",
+    "output/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi"
+  },
+  {
+    "data/test-read-ctf/test-conflicting-type-syms-b.o",
+    "",
+    "",
+    HASH_TYPE_ID_STYLE,
+    "data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi",
+    "output/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi"
+  },
+  {
+    "data/test-read-common/test4.so",
+    "",
+    "",
+    SEQUENCE_TYPE_ID_STYLE,
+    "data/test-read-common/test4-ctf.so.abi",
+    "output/test-read-common/test4-ctf.so.abi"
+  },
+  {
+    "data/test-read-common/test4.so",
+    "",
+    "",
+    HASH_TYPE_ID_STYLE,
+    "data/test-read-common/test4-ctf.so.hash.abi",
+    "output/test-read-common/test4-ctf.so.hash.abi"
+  },
+  {
+    "data/test-read-ctf/test-enum-ctf.o",
+    "",
+    "",
+    SEQUENCE_TYPE_ID_STYLE,
+    "data/test-read-ctf/test-enum-ctf.o.abi",
+    "output/test-read-ctf/test-enum-ctf.o.abi"
+  },
+  {
+    "data/test-read-ctf/test-enum-symbol-ctf.o",
+    "",
+    "",
+    HASH_TYPE_ID_STYLE,
+    "data/test-read-ctf/test-enum-symbol-ctf.o.hash.abi",
+    "output/test-read-ctf/test-enum-symbol-ctf.o.hash.abi"
+  },
+  {
+    "data/test-read-common/PR27700/test-PR27700.o",
+    "",
+    "data/test-read-common/PR27700/pub-incdir",
+    HASH_TYPE_ID_STYLE,
+    "data/test-read-common/PR27700/test-PR27700-ctf.abi",
+    "output/test-read-common/PR27700/test-PR27700-ctf.abi",
+  },
+  // This should be the last entry.
+  {NULL, NULL, NULL, SEQUENCE_TYPE_ID_STYLE, NULL, NULL}
+};
+
+/// The task that peforms the tests.
+struct test_task_ctf : public test_task
+{
+  test_task_ctf(const InOutSpec &s,
+                string& a_out_abi_base,
+                string& a_in_elf_base,
+                string& a_in_abi_base);
+  virtual void
+  perform();
+
+  virtual
+  ~test_task_ctf()
+  {}
+};
+
+test_task_ctf::test_task_ctf(const InOutSpec &s,
+                             string& a_out_abi_base,
+                             string& a_in_elf_base,
+                             string& a_in_abi_base)
+        : test_task(s, a_out_abi_base, a_in_elf_base, a_in_abi_base)
+  {}
+
+/// The actual test.
+///
+/// This reads the corpus into memory, saves it to disk, loads it
+/// again and compares the new in-memory representation against the
+void
+test_task_ctf::perform()
+{
+  abigail::ir::environment_sptr env;
+
+  set_in_elf_path();
+  set_in_suppr_spec_path();
+
+  env.reset(new abigail::ir::environment);
+  abigail::elf_reader::status status =
+    abigail::elf_reader::STATUS_UNKNOWN;
+  ABG_ASSERT(abigail::tools_utils::file_exists(in_elf_path));
+
+  read_context_sptr ctxt = create_read_context(in_elf_path,
+                                               env.get());
+  ABG_ASSERT(ctxt);
+
+  corpus_sptr corp = read_corpus(ctxt.get(), status);
+  // if there is no output and no input, assume that we do not care about the
+  // actual read result, just that it succeeded.
+  if (!spec.in_abi_path && !spec.out_abi_path)
+    {
+        // Phew! we made it here and we did not crash! yay!
+        return;
+    }
+  if (!corp)
+    {
+        error_message = string("failed to read ") + in_elf_path  + "\n";
+        is_ok = false;
+        return;
+    }
+  corp->set_path(spec.in_elf_path);
+  // Do not take architecture names in comparison so that these
+  // test input binaries can come from whatever arch the
+  // programmer likes.
+  corp->set_architecture_name("");
+
+  if (!(is_ok = set_out_abi_path()))
+      return;
+
+  if (!(is_ok = serialize_corpus(out_abi_path, corp)))
+       return;
+
+  if (!(is_ok = run_abidw("--ctf ")))
+    return;
+
+  if (!(is_ok = run_diff()))
+      return;
+}
+
+static test_task*
+new_task(const InOutSpec* s, string& a_out_abi_base,
+         string& a_in_elf_base, string& a_in_abi_base)
+{
+  return new test_task_ctf(*s, a_in_abi_base,
+                           a_in_elf_base, a_in_abi_base);
+}
+
+int
+main(int argc, char *argv[])
+{
+  options opts;
+  if (!parse_command_line(argc, argv, opts))
+    {
+      if (!opts.wrong_option.empty())
+        emit_prefix(argv[0], cerr)
+          << "unrecognized option: " << opts.wrong_option << "\n";
+        display_usage(argv[0], cerr);
+      return 1;
+    }
+
+  /// Create a task queue.  The max number of worker threads of the
+  /// queue is the number of the concurrent threads supported by the
+  /// processor of the machine this code runs on.  But if
+  /// --no-parallel was provided then the number of worker threads
+  /// equals 1.
+  const size_t num_tests = sizeof(in_out_specs) / sizeof (InOutSpec) - 1;
+
+  return run_tests(num_tests, in_out_specs, opts, new_task);
+}
diff --git a/tests/test-read-dwarf.cc b/tests/test-read-dwarf.cc
index 585aca5e..b84fcaf0 100644
--- a/tests/test-read-dwarf.cc
+++ b/tests/test-read-dwarf.cc
@@ -15,45 +15,27 @@ 
 #include <memory>
 #include <string>
 #include <vector>
-#include "abg-ir.h"
+#include "test-read-common.h"
 #include "abg-dwarf-reader.h"
-#include "abg-workers.h"
-#include "abg-writer.h"
-#include "abg-tools-utils.h"
-#include "test-utils.h"
 
 using std::vector;
 using std::string;
-using std::ofstream;
 using std::cerr;
-using std::dynamic_pointer_cast;
-using abigail::tests::get_build_dir;
+
+using abigail::tests::read_common::InOutSpec;
+using abigail::tests::read_common::test_task;
+using abigail::tests::read_common::display_usage;
+using abigail::tests::read_common::options;
+
 using abigail::dwarf_reader::read_corpus_from_elf;
 using abigail::dwarf_reader::read_context;
 using abigail::dwarf_reader::read_context_sptr;
 using abigail::dwarf_reader::create_read_context;
 using abigail::xml_writer::SEQUENCE_TYPE_ID_STYLE;
 using abigail::xml_writer::HASH_TYPE_ID_STYLE;
-using abigail::xml_writer::create_write_context;
-using abigail::xml_writer::set_type_id_style;
-using abigail::xml_writer::type_id_style_kind;
-using abigail::xml_writer::write_context_sptr;
-using abigail::xml_writer::write_corpus;
-
-/// This is an aggregate that specifies where a test shall get its
-/// input from, and where it shall write its ouput to.
-struct InOutSpec
-{
-  const char* in_elf_path;
-  const char* in_suppr_spec_path;
-  const char* in_public_headers_path;
-  type_id_style_kind type_id_style;
-  const char* in_abi_path;
-  const char* out_abi_path;
-};// end struct InOutSpec
-
+using abigail::tools_utils::emit_prefix;
 
-InOutSpec in_out_specs[] =
+static InOutSpec in_out_specs[] =
 {
   {
     "data/test-read-dwarf/test0",
@@ -104,56 +86,56 @@  InOutSpec in_out_specs[] =
     "output/test-read-dwarf/test2.so.hash.abi"
   },
   {
-    "data/test-read-dwarf/test3.so",
+    "data/test-read-common/test3.so",
     "",
     "",
     SEQUENCE_TYPE_ID_STYLE,
-    "data/test-read-dwarf/test3.so.abi",
-    "output/test-read-dwarf/test3.so.abi"
+    "data/test-read-common/test3-dwarf.so.abi",
+    "output/test-read-common/test3-dwarf.so.abi"
   },
   {
-    "data/test-read-dwarf/test3.so",
+    "data/test-read-common/test3.so",
     "",
     "",
     HASH_TYPE_ID_STYLE,
-    "data/test-read-dwarf/test3.so.hash.abi",
-    "output/test-read-dwarf/test3.so.hash.abi"
+    "data/test-read-common/test3-dwarf.so.hash.abi",
+    "output/test-read-common/test3-dwarf.so.hash.abi"
   },
   // suppress all except the main symbol of a group of aliases
   {
-    "data/test-read-dwarf/test3.so",
-    "data/test-read-dwarf/test3-alias-1.suppr",
+    "data/test-read-common/test3.so",
+    "data/test-read-common/test3-alias-1.suppr",
     "",
     HASH_TYPE_ID_STYLE,
-    "data/test-read-dwarf/test3-alias-1.so.hash.abi",
-    "output/test-read-dwarf/test3-alias-1.so.hash.abi"
+    "data/test-read-common/test3-alias-1-dwarf.so.hash.abi",
+    "output/test-read-common/test3-alias-1-dwarf.so.hash.abi"
   },
   // suppress the main symbol of a group of aliases
   {
-    "data/test-read-dwarf/test3.so",
-    "data/test-read-dwarf/test3-alias-2.suppr",
+    "data/test-read-common/test3.so",
+    "data/test-read-common/test3-alias-2.suppr",
     "",
     HASH_TYPE_ID_STYLE,
-    "data/test-read-dwarf/test3-alias-2.so.hash.abi",
-    "output/test-read-dwarf/test3-alias-2.so.hash.abi"
+    "data/test-read-common/test3-alias-2-dwarf.so.hash.abi",
+    "output/test-read-common/test3-alias-2-dwarf.so.hash.abi"
   },
   // suppress all except one non main symbol of a group of aliases
   {
-    "data/test-read-dwarf/test3.so",
-    "data/test-read-dwarf/test3-alias-3.suppr",
+    "data/test-read-common/test3.so",
+    "data/test-read-common/test3-alias-3.suppr",
     "",
     HASH_TYPE_ID_STYLE,
-    "data/test-read-dwarf/test3-alias-3.so.hash.abi",
-    "output/test-read-dwarf/test3-alias-3.so.hash.abi"
+    "data/test-read-common/test3-alias-3-dwarf.so.hash.abi",
+    "output/test-read-common/test3-alias-3-dwarf.so.hash.abi"
   },
   // suppress all symbols of a group of aliases
   {
-    "data/test-read-dwarf/test3.so",
-    "data/test-read-dwarf/test3-alias-4.suppr",
+    "data/test-read-common/test3.so",
+    "data/test-read-common/test3-alias-4.suppr",
     "",
     HASH_TYPE_ID_STYLE,
-    "data/test-read-dwarf/test3-alias-4.so.hash.abi",
-    "output/test-read-dwarf/test3-alias-4.so.hash.abi"
+    "data/test-read-common/test3-alias-4-dwarf.so.hash.abi",
+    "output/test-read-common/test3-alias-4-dwarf.so.hash.abi"
   },
   // suppress the main symbols with alias (function+variable) in .o file
   {
@@ -165,20 +147,20 @@  InOutSpec in_out_specs[] =
     "output/test-read-dwarf/test-suppressed-alias.o.abi",
   },
   {
-    "data/test-read-dwarf/test4.so",
+    "data/test-read-common/test4.so",
     "",
     "",
     SEQUENCE_TYPE_ID_STYLE,
-    "data/test-read-dwarf/test4.so.abi",
-    "output/test-read-dwarf/test4.so.abi"
+    "data/test-read-common/test4-dwarf.so.abi",
+    "output/test-read-common/test4-dwarf.so.abi"
   },
   {
-    "data/test-read-dwarf/test4.so",
+    "data/test-read-common/test4.so",
     "",
     "",
     HASH_TYPE_ID_STYLE,
-    "data/test-read-dwarf/test4.so.hash.abi",
-    "output/test-read-dwarf/test4.so.hash.abi"
+    "data/test-read-common/test4-dwarf.so.hash.abi",
+    "output/test-read-common/test4-dwarf.so.hash.abi"
   },
   {
     "data/test-read-dwarf/test5.o",
@@ -449,28 +431,28 @@  InOutSpec in_out_specs[] =
     NULL,
   },
   {
-    "data/test-read-dwarf/PR26261/PR26261-exe",
+    "data/test-read-common/PR26261/PR26261-exe",
     "",
     "",
     SEQUENCE_TYPE_ID_STYLE,
-    "data/test-read-dwarf/PR26261/PR26261-exe.abi",
-    "output/test-read-dwarf/PR26261/PR26261-exe.abi",
+    "data/test-read-common/PR26261/PR26261-exe-dwarf.abi",
+    "output/test-read-common/PR26261/PR26261-exe-dwarf.abi",
   },
   {
-    "data/test-read-dwarf/test-PR26568-1.o",
+    "data/test-read-common/test-PR26568-1.o",
     "",
     "",
     SEQUENCE_TYPE_ID_STYLE,
-    "data/test-read-dwarf/test-PR26568-1.o.abi",
-    "output/test-read-dwarf/test-PR26568-1.o.abi",
+    "data/test-read-common/test-PR26568-1-dwarf.o.abi",
+    "output/test-read-common/test-PR26568-1-dwarf.o.abi",
   },
   {
-    "data/test-read-dwarf/test-PR26568-2.o",
+    "data/test-read-common/test-PR26568-2.o",
     "",
     "",
     SEQUENCE_TYPE_ID_STYLE,
-    "data/test-read-dwarf/test-PR26568-2.o.abi",
-    "output/test-read-dwarf/test-PR26568-2.o.abi",
+    "data/test-read-common/test-PR26568-2-dwarf.o.abi",
+    "output/test-read-common/test-PR26568-2-dwarf.o.abi",
   },
   {
     "data/test-read-dwarf/test-libandroid.so",
@@ -481,12 +463,12 @@  InOutSpec in_out_specs[] =
     "output/test-read-dwarf/test-libandroid.so.abi",
   },
   {
-    "data/test-read-dwarf/PR27700/test-PR27700.o",
+    "data/test-read-common/PR27700/test-PR27700.o",
     "",
-    "data/test-read-dwarf/PR27700/pub-incdir",
+    "data/test-read-common/PR27700/pub-incdir",
     HASH_TYPE_ID_STYLE,
-    "data/test-read-dwarf/PR27700/test-PR27700.abi",
-    "output/test-read-dwarf/PR27700/test-PR27700.abi",
+    "data/test-read-common/PR27700/test-PR27700-dwarf.abi",
+    "output/test-read-common/PR27700/test-PR27700-dwarf.abi",
   },
   {
     "data/test-read-dwarf/test-libaaudio.so",
@@ -553,146 +535,107 @@  set_suppressions_from_headers(read_context& read_ctxt, const string& path)
 }
 
 /// The task that peforms the tests.
-struct test_task : public abigail::workers::task
+struct test_task_dwarf : public test_task
 {
-  bool is_ok;
-  InOutSpec spec;
-  string error_message;
-  string out_abi_base;
-  string in_elf_base;
-  string in_abi_base;
+  test_task_dwarf(const InOutSpec &s,
+                string& a_out_abi_base,
+                string& a_in_elf_base,
+                string& a_in_abi_base);
+  virtual void
+  perform();
 
-  test_task(const InOutSpec &s,
-	    string& a_out_abi_base,
-	    string& a_in_elf_base,
-	    string& a_in_abi_base)
-    : is_ok(true),
-      spec(s),
-      out_abi_base(a_out_abi_base),
-      in_elf_base(a_in_elf_base),
-      in_abi_base(a_in_abi_base)
+  virtual
+  ~test_task_dwarf()
   {}
+};
 
-  /// The actual test.
-  ///
-  /// This reads the corpus into memory, saves it to disk, loads it
-  /// again and compares the new in-memory representation against the
-  /// saved one.
-  virtual void
-  perform()
-  {
-    string in_elf_path, in_abi_path, in_suppr_spec_path, in_public_headers_path,
-      out_abi_path;
-    abigail::ir::environment_sptr env;
+/// The task that peforms the tests.
+test_task_dwarf::test_task_dwarf(const InOutSpec &s,
+                             string& a_out_abi_base,
+                             string& a_in_elf_base,
+                             string& a_in_abi_base)
+        : test_task(s, a_out_abi_base, a_in_elf_base, a_in_abi_base)
+  {}
 
-    in_elf_path = in_elf_base + spec.in_elf_path;
-    if (spec.in_suppr_spec_path)
-      in_suppr_spec_path = in_elf_base + spec.in_suppr_spec_path;
-    else
-      in_suppr_spec_path.clear();
+void
+test_task_dwarf::perform()
+{
+  abigail::ir::environment_sptr env;
 
-    if (spec.in_public_headers_path)
-      in_public_headers_path = spec.in_public_headers_path;
-    if (!in_public_headers_path.empty())
-      in_public_headers_path = in_elf_base + spec.in_public_headers_path;
+  set_in_elf_path();
+  set_in_suppr_spec_path();
+  set_in_public_headers_path();
 
-    env.reset(new abigail::ir::environment);
-    abigail::elf_reader::status status =
+  env.reset(new abigail::ir::environment);
+  abigail::elf_reader::status status =
     abigail::elf_reader::STATUS_UNKNOWN;
-    vector<char**> di_roots;
-    ABG_ASSERT(abigail::tools_utils::file_exists(in_elf_path));
-    read_context_sptr ctxt = create_read_context(in_elf_path,
-						 di_roots,
-						 env.get());
-    ABG_ASSERT(ctxt);
-    if (!in_suppr_spec_path.empty())
-      set_suppressions(*ctxt, in_suppr_spec_path);
-
-    if (!in_public_headers_path.empty())
-      set_suppressions_from_headers(*ctxt, in_public_headers_path);
+  vector<char**> di_roots;
+  ABG_ASSERT(abigail::tools_utils::file_exists(in_elf_path));
+  read_context_sptr ctxt = create_read_context(in_elf_path,
+                                               di_roots,
+                                               env.get());
+  ABG_ASSERT(ctxt);
+  if (!in_suppr_spec_path.empty())
+    set_suppressions(*ctxt, in_suppr_spec_path);
+
+  if (!in_public_headers_path.empty())
+    set_suppressions_from_headers(*ctxt, in_public_headers_path);
+
+  abigail::corpus_sptr corp = read_corpus_from_elf(*ctxt, status);
+  // if there is no output and no input, assume that we do not care about the
+  // actual read result, just that it succeeded.
+  if (!spec.in_abi_path && !spec.out_abi_path)
+    {
+      // Phew! we made it here and we did not crash! yay!
+      return;
+    }
+  if (!corp)
+    {
+      error_message = string("failed to read ") + in_elf_path  + "\n";
+      is_ok = false;
+      return;
+    }
+  corp->set_path(spec.in_elf_path);
+  // Do not take architecture names in comparison so that these
+  // test input binaries can come from whatever arch the
+  // programmer likes.
+  corp->set_architecture_name("");
 
-    abigail::corpus_sptr corp = read_corpus_from_elf(*ctxt, status);
-    // if there is no output and no input, assume that we do not care about the
-    // actual read result, just that it succeeded.
-    if (!spec.in_abi_path && !spec.out_abi_path)
-      {
-	// Phew! we made it here and we did not crash! yay!
-	return;
-      }
-    if (!corp)
-      {
-	error_message = string("failed to read ") + in_elf_path  + "\n";
-	is_ok = false;
-	return;
-      }
-    corp->set_path(spec.in_elf_path);
-    // Do not take architecture names in comparison so that these
-    // test input binaries can come from whatever arch the
-    // programmer likes.
-    corp->set_architecture_name("");
+  if (!(is_ok = set_out_abi_path()))
+      return;
 
-    out_abi_path = out_abi_base + spec.out_abi_path;
-    if (!abigail::tools_utils::ensure_parent_dir_created(out_abi_path))
-      {
-	error_message =
-	  string("Could not create parent directory for ") + out_abi_path;
-	is_ok = false;
-	return;
-      }
+  if (!(is_ok = serialize_corpus(out_abi_path, corp)))
+       return;
 
-    ofstream of(out_abi_path.c_str(), std::ios_base::trunc);
-    if (!of.is_open())
-      {
-	error_message = string("failed to read ") + out_abi_path + "\n";
-	is_ok = false;
-	return;
-      }
-    write_context_sptr write_ctxt
-	= create_write_context(corp->get_environment(), of);
-    set_type_id_style(*write_ctxt, spec.type_id_style);
-    is_ok = write_corpus(*write_ctxt, corp, /*indent=*/0);
-    of.close();
+  if (!(is_ok = run_abidw()))
+    return;
 
-    string abidw = string(get_build_dir()) + "/tools/abidw";
-    string drop_private_types;
-    if (!in_public_headers_path.empty())
-      drop_private_types += "--headers-dir " + in_public_headers_path +
-	" --drop-private-types";
-    string cmd = abidw + " " + drop_private_types + " --abidiff " + in_elf_path;
-    if (system(cmd.c_str()))
-      {
-	error_message = string("ABIs differ:\n")
-	  + in_elf_path
-	  + "\nand:\n"
-	  + out_abi_path
-	  + "\n";
-	is_ok = false;
-      }
+  if (!(is_ok = run_diff()))
+      return;
+}
 
-    in_abi_path = in_abi_base + spec.in_abi_path;
-    cmd = "diff -u " + in_abi_path + " " + out_abi_path;
-    if (system(cmd.c_str()))
-      is_ok = false;
-  }
-}; // end struct test_task
 
-typedef shared_ptr<test_task> test_task_sptr;
+static test_task*
+new_task(const InOutSpec* s, string& a_out_abi_base,
+         string& a_in_elf_base, string& a_in_abi_base)
+{
+  return new test_task_dwarf(*s, a_in_abi_base,
+                             a_in_elf_base, a_in_abi_base);
+}
 
 int
 main(int argc, char *argv[])
 {
   bool no_parallel = false;
 
-  if (argc == 2)
+  options opts;
+  if (!parse_command_line(argc, argv, opts))
     {
-      if (argv[1] == string("--no-parallel"))
-	no_parallel = true;
-      else
-	{
-	  cerr << "unrecognized option\n";
-	  cerr << "usage: " << argv[0] << " [--no-parallel]\n" ;
-	  return 1;
-	}
+      if (!opts.wrong_option.empty())
+        emit_prefix(argv[0], cerr)
+          << "unrecognized option: " << opts.wrong_option << "\n";
+        display_usage(argv[0], cerr);
+      return 1;
     }
 
   /// Create a task queue.  The max number of worker threads of the
@@ -701,49 +644,6 @@  main(int argc, char *argv[])
   /// --no-parallel was provided then the number of worker threads
   /// equals 1.
   const size_t num_tests = sizeof(in_out_specs) / sizeof (InOutSpec) - 1;
-  size_t num_workers = (no_parallel
-			? 1
-			: std::min(abigail::workers::get_number_of_threads(),
-				   num_tests));
-  abigail::workers::queue task_queue(num_workers);
-  bool is_ok = true;
-
-  string out_abi_base = string(get_build_dir()) + "/tests/";
-  string in_elf_base  = string(abigail::tests::get_src_dir()) + "/tests/";
-  string in_abi_base = in_elf_base;
-
-  for (InOutSpec *s = in_out_specs; s->in_elf_path; ++s)
-    {
-      test_task_sptr t(new test_task(*s, out_abi_base,
-				     in_elf_base,
-				     in_abi_base));
-      ABG_ASSERT(task_queue.schedule_task(t));
-    }
-
-  /// Wait for all worker threads to finish their job, and wind down.
-  task_queue.wait_for_workers_to_complete();
-
-  // Now walk the results and print whatever error messages need to be
-  // printed.
-
-  const vector<abigail::workers::task_sptr>& completed_tasks =
-    task_queue.get_completed_tasks();
-
-  ABG_ASSERT(completed_tasks.size() == num_tests);
-
-  for (vector<abigail::workers::task_sptr>::const_iterator ti =
-	 completed_tasks.begin();
-       ti != completed_tasks.end();
-       ++ti)
-    {
-      test_task_sptr t = dynamic_pointer_cast<test_task>(*ti);
-      if (!t->is_ok)
-	{
-	  is_ok = false;
-	  if (!t->error_message.empty())
-	    cerr << t->error_message << '\n';
-	}
-    }
 
-  return !is_ok;
+  return run_tests(num_tests, in_out_specs, opts, new_task);
 }