[2/5] ctf-front-end: Fix size and name for underlying types

Message ID 20221117034305.184864-3-guillermo.e.martinez@oracle.com
State New
Headers
Series CTF front-end Bug Fixing and improvement |

Commit Message

Guillermo E. Martinez Nov. 17, 2022, 3:43 a.m. UTC
  It fixed an incorrect representation in size and name for underlying
enum and struct types when it has a bitfield members:

    struct foo
    {
      unsigned bar : 2;
      unsigned baz : 1;
    };

  <type-decl name='' is-anonymous='yes' size-in-bits='2' id='type-id-1'/>

So, `name' empty property, no showing the right enumerator's type and size
in bits:

  <type-decl name='unsigned char' size-in-bits='8' id='type-id-4'/>

	* src/abg-ctf-reader.cc (process_ctf_{base_type,enum_type}):
	Look at ctf refence type to build the underlying type if present.
	* tests/data/Makefile.am: New test cases.
	* tests/data/test-read-ctf/PR27700/test-PR27700.abi: New test input.
	* tests/data/test-read-ctf/test-bitfield-enum.abi: Likewise.
	* tests/data/test-read-ctf/test-bitfield-enum.c: Likewise.
	* tests/data/test-read-ctf/test-bitfield-enum.o: Likewise.
	* tests/data/test-read-ctf/test-bitfield.abi: Likewise.
	* tests/data/test-read-ctf/test-bitfield.c: Likewise.
	* tests/data/test-read-ctf/test-bitfield.o: Likewise.
	* tests/data/test-read-ctf/test-enum-many.o.hash.abi: Adjust.
	* tests/data/test-read-ctf/test-enum-symbol.o.hash.abi: Likewise.
	* tests/data/test-read-ctf/test-enum.o.abi: 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.abi: Likewise.
	* tests/data/test-read-ctf/test1.so.hash.abi: Likewise.
	* tests/data/test-read-ctf/test5.o.abi: Likewise.
	* tests/test-read-ctf.cc: Update test suite.

Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
---
 src/abg-ctf-reader.cc                         |  31 +++++++----
 tests/data/Makefile.am                        |   6 +++
 .../test-read-ctf/PR27700/test-PR27700.abi    |   4 +-
 .../data/test-read-ctf/test-bitfield-enum.abi |  18 +++++++
 tests/data/test-read-ctf/test-bitfield-enum.c |  12 +++++
 tests/data/test-read-ctf/test-bitfield-enum.o | Bin 0 -> 1336 bytes
 tests/data/test-read-ctf/test-bitfield.abi    |  28 ++++++++++
 tests/data/test-read-ctf/test-bitfield.c      |  15 ++++++
 tests/data/test-read-ctf/test-bitfield.o      | Bin 0 -> 1488 bytes
 .../test-read-ctf/test-enum-many.o.hash.abi   |   6 +--
 .../test-read-ctf/test-enum-symbol.o.hash.abi |   4 +-
 tests/data/test-read-ctf/test-enum.o.abi      |  10 ++--
 tests/data/test-read-ctf/test0.abi            |  48 +++++++++---------
 tests/data/test-read-ctf/test0.hash.abi       |  10 ++--
 tests/data/test-read-ctf/test1.so.abi         |   8 +--
 tests/data/test-read-ctf/test1.so.hash.abi    |   4 +-
 tests/data/test-read-ctf/test5.o.abi          |  12 ++---
 tests/test-read-ctf.cc                        |  18 +++++++
 18 files changed, 171 insertions(+), 63 deletions(-)
 create mode 100644 tests/data/test-read-ctf/test-bitfield-enum.abi
 create mode 100644 tests/data/test-read-ctf/test-bitfield-enum.c
 create mode 100644 tests/data/test-read-ctf/test-bitfield-enum.o
 create mode 100644 tests/data/test-read-ctf/test-bitfield.abi
 create mode 100644 tests/data/test-read-ctf/test-bitfield.c
 create mode 100644 tests/data/test-read-ctf/test-bitfield.o

new file mode 100644
index 00000000..4231ba3e
index 116325f9..9119525b 100644
  

Comments

Dodji Seketeli Nov. 29, 2022, 11:53 a.m. UTC | #1
Hello Guillermo,

"Guillermo E. Martinez via Libabigail" <libabigail@sourceware.org> a
écrit:

> It fixed an incorrect representation in size and name for underlying
> enum and struct types when it has a bitfield members:
>
>     struct foo
>     {
>       unsigned bar : 2;
>       unsigned baz : 1;
>     };
>
>   <type-decl name='' is-anonymous='yes' size-in-bits='2' id='type-id-1'/>
>
> So, `name' empty property, no showing the right enumerator's type and size
> in bits:
>
>   <type-decl name='unsigned char' size-in-bits='8' id='type-id-4'/>

Hmmh, I think here, the name should be "unsigned int", because "unsigned
bar" implicitly means 'unsigned int bar".  And the size-in-bits should
be set to 32.

I have thus changed the introductory paragraphs of this commit log to
the following:

    This patch fixes an incorrect representation in size and name of the
    underlying type of enums as well as underlying types of bitfield data
    members types.

    For instance, consider this struct.

        struct foo
        {
          unsigned bar : 2;
          unsigned baz : 1;
        };

    The data members bar and baz have an underlying type that is "unsigned
    int".  Yet, the CTF front-end represents the underlying type of these
    data members as:

      <type-decl name='' is-anonymous='yes' size-in-bits='2' id='type-id-1'/>

    The name property is empty, and it should be "unsigned int".

    The size in bit is '2', but it should be the size of the underlying
    "unsigned int", in bits, which is 32.

    In other words, the underlying type of bar and baz should be:

      <type-decl name='unsigned int' size-in-bits='32' id='type-id-4'/>

    Note that today, libabigail doesn't represent the bitfield properties
    of the data member.  Those bitfield properties are properties of the
    data member, not of their type.  This is a known "Not Yet Implemented"
    feature request that has been filed upstream at
    https://sourceware.org/bugzilla/show_bug.cgi?id=27334.

    Similarly, the underlying type of enums is not properly represented by
    the CTF front-end.

    Fixed thus.

It's a little bit more verbose, but hopefully, that should give a little
bit more context for future code maintenance.

>
> 	* src/abg-ctf-reader.cc (process_ctf_{base_type,enum_type}):
> 	Look at ctf refence type to build the underlying type if present.
> 	* tests/data/Makefile.am: New test cases.
> 	* tests/data/test-read-ctf/PR27700/test-PR27700.abi: New test input.
> 	* tests/data/test-read-ctf/test-bitfield-enum.abi: Likewise.
> 	* tests/data/test-read-ctf/test-bitfield-enum.c: Likewise.
> 	* tests/data/test-read-ctf/test-bitfield-enum.o: Likewise.
> 	* tests/data/test-read-ctf/test-bitfield.abi: Likewise.
> 	* tests/data/test-read-ctf/test-bitfield.c: Likewise.
> 	* tests/data/test-read-ctf/test-bitfield.o: Likewise.
> 	* tests/data/test-read-ctf/test-enum-many.o.hash.abi: Adjust.
> 	* tests/data/test-read-ctf/test-enum-symbol.o.hash.abi: Likewise.
> 	* tests/data/test-read-ctf/test-enum.o.abi: 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.abi: Likewise.
> 	* tests/data/test-read-ctf/test1.so.hash.abi: Likewise.
> 	* tests/data/test-read-ctf/test5.o.abi: Likewise.
> 	* tests/test-read-ctf.cc: Update test suite.
>
> Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>

Applied to the master branch with the change above.  Please find below
the actual patch that got applied.

Many thanks!

[...]

From 217f579bf788a11643c0066a7dc8aa76faa5a05d Mon Sep 17 00:00:00 2001
From: "Guillermo E. Martinez" <guillermo.e.martinez@oracle.com>
Date: Wed, 16 Nov 2022 21:43:02 -0600
Subject: [PATCH] ctf-reader: Fix size and name for underlying types

This patch fixes an incorrect representation in size and name of the
underlying type of enums as well as underlying types of bitfield data
members types.

For instance, consider this struct.

    struct foo
    {
      unsigned bar : 2;
      unsigned baz : 1;
    };

The data members bar and baz have an underlying type that is "unsigned
int".  Yet, the CTF front-end represents the underlying type of these
data members as:

  <type-decl name='' is-anonymous='yes' size-in-bits='2' id='type-id-1'/>

The name property is empty, and it should be "unsigned int".

The size in bit is '2', but it should be the size of the underlying
"unsigned int", in bits, which is 32.

In other words, the underlying type of bar and baz should be:

  <type-decl name='unsigned int' size-in-bits='32' id='type-id-4'/>

Note that today, libabigail doesn't represent the bitfield properties
of the data member.  Those bitfield properties are properties of the
data member, not of their type.  This is a known "Not Yet Implemented"
feature request that has been filed upstream at
https://sourceware.org/bugzilla/show_bug.cgi?id=27334.

Similarly, the underlying type of enums is not properly represented by
the CTF front-end.

Fixed thus.

	* src/abg-ctf-reader.cc (process_ctf_{base_type,enum_type}):
	Look at ctf refence type to build the underlying type if present.
	* tests/data/Makefile.am: New test cases.
	* tests/data/test-read-ctf/PR27700/test-PR27700.abi: New test input.
	* tests/data/test-read-ctf/test-bitfield-enum.abi: Likewise.
	* tests/data/test-read-ctf/test-bitfield-enum.c: Likewise.
	* tests/data/test-read-ctf/test-bitfield-enum.o: Likewise.
	* tests/data/test-read-ctf/test-bitfield.abi: Likewise.
	* tests/data/test-read-ctf/test-bitfield.c: Likewise.
	* tests/data/test-read-ctf/test-bitfield.o: Likewise.
	* tests/data/test-read-ctf/test-enum-many.o.hash.abi: Adjust.
	* tests/data/test-read-ctf/test-enum-symbol.o.hash.abi: Likewise.
	* tests/data/test-read-ctf/test-enum.o.abi: 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.abi: Likewise.
	* tests/data/test-read-ctf/test1.so.hash.abi: Likewise.
	* tests/data/test-read-ctf/test5.o.abi: Likewise.
	* tests/test-read-ctf.cc: Update test suite.

Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
---
 src/abg-ctf-reader.cc | 31 +++++++++++++++++++++----------
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/src/abg-ctf-reader.cc b/src/abg-ctf-reader.cc
index cbc5cbca..d000556b 100644
--- a/src/abg-ctf-reader.cc
+++ b/src/abg-ctf-reader.cc
@@ -783,15 +783,17 @@ process_ctf_base_type(reader *rdr,
   translation_unit_sptr tunit = rdr->cur_transl_unit();
   type_decl_sptr result;
 
-  const char *type_name = ctf_type_name_raw(ctf_dictionary, ctf_type);
+  ctf_id_t ctf_ref = ctf_type_reference(ctf_dictionary, ctf_type);
+  const char *type_name = ctf_type_name_raw(ctf_dictionary,
+                                            (ctf_ref != CTF_ERR) ? ctf_ref : ctf_type);
 
   /* Get the type encoding and extract some useful properties of
      the type from it.  In case of any error, just ignore the
      type.  */
   ctf_encoding_t type_encoding;
   if (ctf_type_encoding(ctf_dictionary,
-                         ctf_type,
-                         &type_encoding))
+                        (ctf_ref != CTF_ERR) ? ctf_ref : ctf_type,
+                        &type_encoding))
     return result;
 
   /* Create the IR type corresponding to the CTF type.  */
@@ -1357,7 +1359,10 @@ process_ctf_enum_type(reader *rdr,
 {
   translation_unit_sptr tunit = rdr->cur_transl_unit();
   enum_type_decl_sptr result;
-  std::string enum_name = ctf_type_name_raw(ctf_dictionary, ctf_type);
+  ctf_id_t ctf_ref = ctf_type_reference(ctf_dictionary, ctf_type);
+  std::string enum_name = ctf_type_name_raw(ctf_dictionary,
+                                            (ctf_ref != CTF_ERR)
+                                              ? ctf_ref : ctf_type);
 
   if (!enum_name.empty())
     if (corpus_sptr corp = rdr->should_reuse_type_from_corpus_group())
@@ -1367,18 +1372,24 @@ process_ctf_enum_type(reader *rdr,
   /* Build a signed integral type for the type of the enumerators, aka
      the underlying type.  The size of the enumerators in bytes is
      specified in the CTF enumeration type.  */
-  size_t utype_size_in_bits = ctf_type_size(ctf_dictionary, ctf_type) * 8;
-  type_decl_sptr utype;
+  size_t utype_size_in_bits = ctf_type_size(ctf_dictionary,
+                                            (ctf_ref != CTF_ERR)
+                                              ? ctf_ref : ctf_type) * 8;
+  string underlying_type_name =
+        build_internal_underlying_enum_type_name(enum_name, true,
+                                                 utype_size_in_bits);
 
+  type_decl_sptr utype;
   utype.reset(new type_decl(rdr->env(),
-                              "",
-                              utype_size_in_bits,
-                              utype_size_in_bits,
-                              location()));
+                            underlying_type_name,
+                            utype_size_in_bits,
+                            utype_size_in_bits,
+                            location()));
   utype->set_is_anonymous(true);
   utype->set_is_artificial(true);
   if (!utype)
     return result;
+
   add_decl_to_scope(utype, tunit->get_global_scope());
   canonicalize(utype);
  
Dodji Seketeli Nov. 29, 2022, 1:59 p.m. UTC | #2
Hello Guillermo,

When applying the patch "ctf-front-end: Fix size and name for underlying
types", the patch wouldn't apply cleanly, so I had to edit it.

I screwed up and forgot to apply the tests part of the patch.

Please find below the testing part that I forgot to apply.

Could you please review it and sign it off?

Thank you and sorry for my mistake.

Cheers,

From 454c88e6b5381e4376a6062e18dbe888d0eb5e72 Mon Sep 17 00:00:00 2001
From: Dodji Seketeli <dodji@redhat.com>
Date: Tue, 29 Nov 2022 13:42:43 +0100
Subject: [PATCH] test-read-ctf: Update tests for fixing size and name for
 underlying types

When applying the previous commit the testing bit felt through the
crack.  Oops.  Fixed thus.

Here is the link to the initial post:
https://inbox.sourceware.org/libabigail/871qpmou3k.fsf@seketeli.org/T/#m5f37b419e580a2a4ea9d91a9394382d886358809

	* src/abg-ctf-reader.cc (process_ctf_{base_type,enum_type}):
	Look at ctf refence type to build the underlying type if present.
	* tests/data/Makefile.am: New test cases.
	* tests/data/test-read-ctf/PR27700/test-PR27700.abi: New test input.
	* tests/data/test-read-ctf/test-bitfield-enum.abi: Likewise.
	* tests/data/test-read-ctf/test-bitfield-enum.c: Likewise.
	* tests/data/test-read-ctf/test-bitfield-enum.o: Likewise.
	* tests/data/test-read-ctf/test-bitfield.abi: Likewise.
	* tests/data/test-read-ctf/test-bitfield.c: Likewise.
	* tests/data/test-read-ctf/test-bitfield.o: Likewise.
	* tests/data/test-read-ctf/test-enum-many.o.hash.abi: Adjust.
	* tests/data/test-read-ctf/test-enum-symbol.o.hash.abi: Likewise.
	* tests/data/test-read-ctf/test-enum.o.abi: 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.abi: Likewise.
	* tests/data/test-read-ctf/test1.so.hash.abi: Likewise.
	* tests/data/test-read-ctf/test5.o.abi: Likewise.
	* tests/test-read-ctf.cc: Update test suite.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
---
 tests/data/Makefile.am                        |   6 +++
 .../test-read-ctf/PR27700/test-PR27700.abi    |   4 +-
 .../data/test-read-ctf/test-bitfield-enum.abi |  18 +++++++
 tests/data/test-read-ctf/test-bitfield-enum.c |  12 +++++
 tests/data/test-read-ctf/test-bitfield-enum.o | Bin 0 -> 1336 bytes
 tests/data/test-read-ctf/test-bitfield.abi    |  28 ++++++++++
 tests/data/test-read-ctf/test-bitfield.c      |  15 ++++++
 tests/data/test-read-ctf/test-bitfield.o      | Bin 0 -> 1488 bytes
 .../test-read-ctf/test-enum-many.o.hash.abi   |   6 +--
 .../test-read-ctf/test-enum-symbol.o.hash.abi |   4 +-
 tests/data/test-read-ctf/test-enum.o.abi      |  10 ++--
 tests/data/test-read-ctf/test0.abi            |  48 +++++++++---------
 tests/data/test-read-ctf/test0.hash.abi       |  10 ++--
 tests/data/test-read-ctf/test1.so.abi         |   8 +--
 tests/data/test-read-ctf/test1.so.hash.abi    |   4 +-
 tests/data/test-read-ctf/test5.o.abi          |  12 ++---
 tests/test-read-ctf.cc                        |  18 +++++++
 17 files changed, 150 insertions(+), 53 deletions(-)
 create mode 100644 tests/data/test-read-ctf/test-bitfield-enum.abi
 create mode 100644 tests/data/test-read-ctf/test-bitfield-enum.c
 create mode 100644 tests/data/test-read-ctf/test-bitfield-enum.o
 create mode 100644 tests/data/test-read-ctf/test-bitfield.abi
 create mode 100644 tests/data/test-read-ctf/test-bitfield.c
 create mode 100644 tests/data/test-read-ctf/test-bitfield.o

diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index 4b6e9305..b89a4dd8 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -704,6 +704,12 @@ test-read-ctf/test-linux-module.ko		\
 test-read-ctf/test-fallback.abi		\
 test-read-ctf/test-fallback.c		\
 test-read-ctf/test-fallback.o		\
+test-read-ctf/test-bitfield.abi		\
+test-read-ctf/test-bitfield.c		\
+test-read-ctf/test-bitfield.o		\
+test-read-ctf/test-bitfield-enum.abi	\
+test-read-ctf/test-bitfield-enum.c	\
+test-read-ctf/test-bitfield-enum.o	\
 \
 test-annotate/test0.abi			\
 test-annotate/test1.abi			\
diff --git a/tests/data/test-read-ctf/PR27700/test-PR27700.abi b/tests/data/test-read-ctf/PR27700/test-PR27700.abi
index 4f34eb8a..1a7c229e 100644
--- a/tests/data/test-read-ctf/PR27700/test-PR27700.abi
+++ b/tests/data/test-read-ctf/PR27700/test-PR27700.abi
@@ -3,14 +3,14 @@
     <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'/>
+      <underlying-type type-id='9cac1fee'/>
       <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='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
     <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' elf-symbol-id='foo'>
       <parameter type-id='8750e847'/>
diff --git a/tests/data/test-read-ctf/test-bitfield-enum.abi b/tests/data/test-read-ctf/test-bitfield-enum.abi
new file mode 100644
index 00000000..b95f1781
--- /dev/null
+++ b/tests/data/test-read-ctf/test-bitfield-enum.abi
@@ -0,0 +1,18 @@
+<abi-corpus version='2.1' path='data/test-read-ctf/test-bitfield-enum.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='e' 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'>
+    <enum-decl name='event_kind' linkage-name='event_kind' id='type-id-1'>
+      <underlying-type type-id='type-id-2'/>
+      <enumerator name='NO_EVENT' value='0'/>
+    </enum-decl>
+    <class-decl name='input' size-in-bits='32' is-struct='yes' visibility='default' id='type-id-3'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='kind' type-id='type-id-1' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='type-id-2'/>
+    <var-decl name='e' type-id='type-id-3' mangled-name='e' visibility='default' elf-symbol-id='e'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-bitfield-enum.c b/tests/data/test-read-ctf/test-bitfield-enum.c
new file mode 100644
index 00000000..502ec06a
--- /dev/null
+++ b/tests/data/test-read-ctf/test-bitfield-enum.c
@@ -0,0 +1,12 @@
+/* gcc -gctf -c test-bitfield-enum.c -o test-bitfield-enum.o */
+enum event_kind
+{
+  NO_EVENT,
+};
+
+struct input
+{
+  enum event_kind kind : 16;
+};
+
+struct input e;
diff --git a/tests/data/test-read-ctf/test-bitfield-enum.o b/tests/data/test-read-ctf/test-bitfield-enum.o
new file mode 100644
index 0000000000000000000000000000000000000000..2c532f50c724f7bf4327b7c36699a432ca08eab1
GIT binary patch
literal 1336
zcmbVL&2G~`5T1lkeh>7}s)CE@g;e0R6E4sLvQ&j4gu(@SLuGAm(^c(tWN#ojAvp0!
z9C;I-0bT%R?A>IwlnWz$p1<!~?~LqElUL9Cy&hQW!86!owhFN9Z{nm46SxI8;n$DB
zx)W_EFu<5_-QW)T_lPfuD~Qm5VtOB9pZK>CWILVPqFR91M<C}e<wFD+#m1h{CFmRg
ze3SSfls>(XDu?Oo)5*zX`UV!NkuxRoKq?JV%@-P4f`I6}Dn*p8(p6N|JS#-h)LB%>
zl&5mWWf3azG18*ZO_X!Z+c2yJ&%;cgby+I)nG{7H3biO%25@|IbQlber*98}(PI{~
zI2gy{@n{r34TfSl7qu+$io7^zuZ#~n=T(eR27Ty#cjm*{y1bjws{Z!WAHdJwerFd8
z+wJDN&iZT`EcEX$09dmsHBZs&y7T8Y(qgHB(Jp|cO#=+~fRC!AnSiNE3x+d<jpo^f
z$!BW8=5>XW>y>}E|H<#6h-TgL#EF;N)Zg2EY*3B9Ki3jBabjQp0DJUp|4YB#uQ|id
zA7R};lc)(j(00A1m%<1+REvr1*oh%NbZQh@z4eDq&82>}1h;qz_a)Y@A?Uwz?W@uI
y_o7|7Ml@eb{clG9!jNwmp4IO;b$|D5%N%NXhQ6NP=Gz!trr$IAca~_pzm`9z|8lDU

literal 0
HcmV?d00001

diff --git a/tests/data/test-read-ctf/test-bitfield.abi b/tests/data/test-read-ctf/test-bitfield.abi
new file mode 100644
index 00000000..4231ba3e
--- /dev/null
+++ b/tests/data/test-read-ctf/test-bitfield.abi
@@ -0,0 +1,28 @@
+<abi-corpus version='2.1' path='data/test-read-ctf/test-bitfield.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='f' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='fb' size='1' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <class-decl name='foo' size-in-bits='32' is-struct='yes' visibility='default' id='type-id-1'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='bar' type-id='type-id-2' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='2'>
+        <var-decl name='baz' type-id='type-id-2' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <class-decl name='foobar' size-in-bits='8' is-struct='yes' visibility='default' id='type-id-3'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='bar' type-id='type-id-4' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='2'>
+        <var-decl name='baz' type-id='type-id-4' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <type-decl name='unsigned char' size-in-bits='8' id='type-id-4'/>
+    <type-decl name='unsigned int' size-in-bits='32' id='type-id-2'/>
+    <var-decl name='f' type-id='type-id-1' mangled-name='f' visibility='default' elf-symbol-id='f'/>
+    <var-decl name='fb' type-id='type-id-3' mangled-name='fb' visibility='default' elf-symbol-id='fb'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-bitfield.c b/tests/data/test-read-ctf/test-bitfield.c
new file mode 100644
index 00000000..7d76d2f4
--- /dev/null
+++ b/tests/data/test-read-ctf/test-bitfield.c
@@ -0,0 +1,15 @@
+/* gcc -gctf -c test-bitfield.c -o test-bitfield.o */
+struct foo
+{
+  unsigned bar : 2;
+  unsigned baz : 1;
+};
+
+struct foobar 
+{
+  unsigned char bar : 2;
+  unsigned char baz : 1;
+};
+
+struct foo f;
+struct foobar fb;
diff --git a/tests/data/test-read-ctf/test-bitfield.o b/tests/data/test-read-ctf/test-bitfield.o
new file mode 100644
index 0000000000000000000000000000000000000000..c23c8188d880587f2ba78b8b852cdb067607e4b6
GIT binary patch
literal 1488
zcmbVM&2G~`5FVEh3S3$$Arvm|iB=FhNe{FYLXj${gb+85NZ8IMu}JL7-in3`cOC%o
z6g&e@fw=Ju@B%QOcgI<lp93S!&dm4CjCUs8zJ2uc@kS7kNI(y19SKUbb!qL78+T0C
z=^B0i+Sw51fjDe8t!}Y}hOA#$-?3h1#W#*v?^~5vIBweOFn5C$g3sS%#m9gnkEIJg
zglFUseawa0YdKgzJ;V2q7n>To!uG)6&AoRG-bD`2A&r_o-G&p09E`K4Wl85nozDt2
z3G+fznpCWBK)`LeY~B!-q-jd=yj-d{U8SqItdeY@;=0P>MV=;UK1=dNzfiAZt!iDz
zlSC(t+pknI>1TRsqBPgjTrDP1Ms#{|avbiRK6}0&4iBP1Gzdq7(P%gv9EE%8;!IWf
zQWZK`?3+=|PD2i`S1#kBgHPD4NMK{^<X-~5L*IV*Iok|uH@~7`r1y@+C2sp;*1j{+
z6kDRGUM+Q!velKbbMdsg&=g@g6s2`d5if?1a*0VPDoU*)o~&Q%BztA!S#chnRVD93
zulyVTUwoU(FoXF!S@#&P-Cw+RUW@Ls1?D`rh8Z{K?}uN1hg0zO{#I|_P1{KJF2Fr@
z{GQ;(I9T3$q!-eVbASzy?8s-Ec-O(;O1;=)2Xj+{_Q|>Ex?a#H?BG57>6;et?}c5t
yf_wP2;14bM5&_FqRzOmJ3m^+{fA_#Y*n0dAb4BJB4DaMm^&f5h3rV!rum1@|M0T$L

literal 0
HcmV?d00001

diff --git a/tests/data/test-read-ctf/test-enum-many.o.hash.abi b/tests/data/test-read-ctf/test-enum-many.o.hash.abi
index 116325f9..9119525b 100644
--- a/tests/data/test-read-ctf/test-enum-many.o.hash.abi
+++ b/tests/data/test-read-ctf/test-enum-many.o.hash.abi
@@ -4,14 +4,13 @@
     <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'/>
+      <underlying-type type-id='9cac1fee'/>
       <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'/>
+      <underlying-type type-id='9cac1fee'/>
       <enumerator name='IE_0' value='-10'/>
       <enumerator name='IE_1' value='-9'/>
       <enumerator name='IE_2' value='-8'/>
@@ -61,6 +60,7 @@
       <enumerator name='IE_2E' value='36'/>
       <enumerator name='IE_2F' value='37'/>
     </enum-decl>
+    <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
     <var-decl name='foo' type-id='a6c2eddf' mangled-name='foo' visibility='default' elf-symbol-id='foo'/>
     <var-decl name='bar' type-id='1ee696ca' mangled-name='bar' visibility='default' elf-symbol-id='bar'/>
   </abi-instr>
diff --git a/tests/data/test-read-ctf/test-enum-symbol.o.hash.abi b/tests/data/test-read-ctf/test-enum-symbol.o.hash.abi
index f4911bc4..da68828c 100644
--- a/tests/data/test-read-ctf/test-enum-symbol.o.hash.abi
+++ b/tests/data/test-read-ctf/test-enum-symbol.o.hash.abi
@@ -3,13 +3,13 @@
     <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'/>
+      <underlying-type type-id='9cac1fee'/>
       <enumerator name='red1' value='0'/>
       <enumerator name='green1' value='1'/>
       <enumerator name='blue1' value='2'/>
     </enum-decl>
+    <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
     <var-decl name='primary1' type-id='08f5ca17' mangled-name='primary1' visibility='default' elf-symbol-id='primary1'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test-enum.o.abi b/tests/data/test-read-ctf/test-enum.o.abi
index bd3a55be..e13ebdd0 100644
--- a/tests/data/test-read-ctf/test-enum.o.abi
+++ b/tests/data/test-read-ctf/test-enum.o.abi
@@ -4,19 +4,19 @@
     <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'/>
+    <enum-decl name='e' linkage-name='e' id='type-id-1'>
+      <underlying-type type-id='type-id-2'/>
       <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'/>
+      <underlying-type type-id='type-id-2'/>
       <enumerator name='IENUMSAMPLE_1' value='-10'/>
       <enumerator name='IENUMSAMPLE_2' value='-9'/>
       <enumerator name='IENUMSAMPLE_3' value='-8'/>
     </enum-decl>
-    <var-decl name='foo' type-id='type-id-2' mangled-name='foo' visibility='default' elf-symbol-id='foo'/>
+    <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='type-id-2'/>
+    <var-decl name='foo' type-id='type-id-1' mangled-name='foo' visibility='default' elf-symbol-id='foo'/>
     <var-decl name='bar' type-id='type-id-3' mangled-name='bar' visibility='default' elf-symbol-id='bar'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test0.abi b/tests/data/test-read-ctf/test0.abi
index 05430067..60d3cf1e 100644
--- a/tests/data/test-read-ctf/test0.abi
+++ b/tests/data/test-read-ctf/test0.abi
@@ -20,47 +20,47 @@
     <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' id='type-id-1'/>
-    <type-decl name='char' size-in-bits='8' id='type-id-2'/>
-    <type-decl name='float' size-in-bits='32' id='type-id-3'/>
-    <type-decl name='int' size-in-bits='32' id='type-id-4'/>
-    <array-type-def dimensions='1' type-id='type-id-4' size-in-bits='320' id='type-id-5'>
-      <subrange length='10' type-id='type-id-6' id='type-id-7'/>
+    <type-decl name='char' size-in-bits='8' id='type-id-1'/>
+    <type-decl name='float' size-in-bits='32' id='type-id-2'/>
+    <type-decl name='int' size-in-bits='32' id='type-id-3'/>
+    <array-type-def dimensions='1' type-id='type-id-3' size-in-bits='320' id='type-id-4'>
+      <subrange length='10' type-id='type-id-5' id='type-id-6'/>
     </array-type-def>
-    <type-decl name='long int' size-in-bits='64' id='type-id-8'/>
-    <type-decl name='short int' size-in-bits='16' id='type-id-9'/>
-    <class-decl name='S' size-in-bits='32' is-struct='yes' visibility='default' id='type-id-10'>
+    <type-decl name='long int' size-in-bits='64' id='type-id-7'/>
+    <type-decl name='short int' size-in-bits='16' id='type-id-8'/>
+    <class-decl name='S' size-in-bits='32' is-struct='yes' visibility='default' id='type-id-9'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='m0' type-id='type-id-4' visibility='default'/>
+        <var-decl name='m0' type-id='type-id-3' visibility='default'/>
       </data-member>
     </class-decl>
-    <class-decl name='' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-11'>
+    <class-decl name='' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-10'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='status0' type-id='type-id-1' visibility='default'/>
+        <var-decl name='status0' type-id='type-id-11' visibility='default'/>
       </data-member>
       <data-member access='public' layout-offset-in-bits='1'>
-        <var-decl name='status1' type-id='type-id-1' visibility='default'/>
+        <var-decl name='status1' type-id='type-id-11' visibility='default'/>
       </data-member>
     </class-decl>
-    <type-decl name='unsigned long int' size-in-bits='64' id='type-id-6'/>
-    <pointer-type-def type-id='type-id-10' size-in-bits='64' alignment-in-bits='64' id='type-id-12'/>
-    <pointer-type-def type-id='type-id-2' size-in-bits='64' alignment-in-bits='64' id='type-id-13'/>
-    <qualified-type-def type-id='type-id-10' const='yes' id='type-id-14'/>
-    <pointer-type-def type-id='type-id-8' size-in-bits='64' alignment-in-bits='64' id='type-id-15'/>
+    <type-decl name='unsigned int' size-in-bits='32' id='type-id-11'/>
+    <type-decl name='unsigned long int' size-in-bits='64' id='type-id-5'/>
+    <pointer-type-def type-id='type-id-9' size-in-bits='64' alignment-in-bits='64' id='type-id-12'/>
+    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-13'/>
+    <qualified-type-def type-id='type-id-9' const='yes' id='type-id-14'/>
+    <pointer-type-def type-id='type-id-7' size-in-bits='64' alignment-in-bits='64' id='type-id-15'/>
     <qualified-type-def type-id='type-id-15' restrict='yes' id='type-id-16'/>
-    <qualified-type-def type-id='type-id-9' volatile='yes' id='type-id-17'/>
-    <var-decl name='status' type-id='type-id-11' mangled-name='status' visibility='default' elf-symbol-id='status'/>
+    <qualified-type-def type-id='type-id-8' volatile='yes' id='type-id-17'/>
+    <var-decl name='status' type-id='type-id-10' mangled-name='status' visibility='default' elf-symbol-id='status'/>
     <var-decl name='test_pointer' type-id='type-id-13' mangled-name='test_pointer' visibility='default' elf-symbol-id='test_pointer'/>
     <var-decl name='test_const' type-id='type-id-14' mangled-name='test_const' visibility='default' elf-symbol-id='test_const'/>
-    <var-decl name='test_float' type-id='type-id-3' mangled-name='test_float' visibility='default' elf-symbol-id='test_float'/>
+    <var-decl name='test_float' type-id='type-id-2' mangled-name='test_float' visibility='default' elf-symbol-id='test_float'/>
     <function-decl name='foo_1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo_1'>
       <parameter type-id='type-id-12'/>
-      <return type-id='type-id-4'/>
+      <return type-id='type-id-3'/>
     </function-decl>
     <function-decl name='main' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='main'>
-      <return type-id='type-id-4'/>
+      <return type-id='type-id-3'/>
     </function-decl>
-    <var-decl name='test_array' type-id='type-id-5' mangled-name='test_array' visibility='default' elf-symbol-id='test_array'/>
+    <var-decl name='test_array' type-id='type-id-4' mangled-name='test_array' visibility='default' elf-symbol-id='test_array'/>
     <var-decl name='test_restrict' type-id='type-id-16' mangled-name='test_restrict' visibility='default' elf-symbol-id='test_restrict'/>
     <var-decl name='test_volatile' type-id='type-id-17' mangled-name='test_volatile' visibility='default' elf-symbol-id='test_volatile'/>
   </abi-instr>
diff --git a/tests/data/test-read-ctf/test0.hash.abi b/tests/data/test-read-ctf/test0.hash.abi
index 4aa9a93c..76dd581e 100644
--- a/tests/data/test-read-ctf/test0.hash.abi
+++ b/tests/data/test-read-ctf/test0.hash.abi
@@ -20,7 +20,6 @@
     <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' id='811c9dc5'/>
     <type-decl name='char' size-in-bits='8' id='a84c031d'/>
     <type-decl name='float' size-in-bits='32' id='a6c45d85'/>
     <type-decl name='int' size-in-bits='32' id='95e97e5e'/>
@@ -34,14 +33,15 @@
         <var-decl name='m0' type-id='95e97e5e' visibility='default'/>
       </data-member>
     </class-decl>
-    <class-decl name='' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='b91ffdee'>
+    <class-decl name='' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='000d9e42'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='status0' type-id='811c9dc5' visibility='default'/>
+        <var-decl name='status0' type-id='f0981eec' visibility='default'/>
       </data-member>
       <data-member access='public' layout-offset-in-bits='1'>
-        <var-decl name='status1' type-id='811c9dc5' visibility='default'/>
+        <var-decl name='status1' type-id='f0981eec' visibility='default'/>
       </data-member>
     </class-decl>
+    <type-decl name='unsigned int' size-in-bits='32' id='f0981eec'/>
     <type-decl name='unsigned long int' size-in-bits='64' id='f0981eeb'/>
     <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'/>
@@ -49,7 +49,7 @@
     <pointer-type-def type-id='95e97e5f' size-in-bits='64' alignment-in-bits='64' id='7292109c'/>
     <qualified-type-def type-id='7292109c' restrict='yes' id='6942f6a4'/>
     <qualified-type-def type-id='95e97e60' volatile='yes' id='e024ff18'/>
-    <var-decl name='status' type-id='b91ffdee' mangled-name='status' visibility='default' elf-symbol-id='status'/>
+    <var-decl name='status' type-id='000d9e42' mangled-name='status' visibility='default' elf-symbol-id='status'/>
     <var-decl name='test_pointer' type-id='26a90f95' mangled-name='test_pointer' visibility='default' elf-symbol-id='test_pointer'/>
     <var-decl name='test_const' type-id='0fb3b55d' mangled-name='test_const' visibility='default' elf-symbol-id='test_const'/>
     <var-decl name='test_float' type-id='a6c45d85' mangled-name='test_float' visibility='default' elf-symbol-id='test_float'/>
diff --git a/tests/data/test-read-ctf/test1.so.abi b/tests/data/test-read-ctf/test1.so.abi
index 822b57a5..2ecd5826 100644
--- a/tests/data/test-read-ctf/test1.so.abi
+++ b/tests/data/test-read-ctf/test1.so.abi
@@ -6,9 +6,8 @@
     <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'/>
-    <enum-decl name='opaque_enum' linkage-name='opaque_enum' id='type-id-2'>
-      <underlying-type type-id='type-id-1'/>
+    <enum-decl name='opaque_enum' linkage-name='opaque_enum' id='type-id-1'>
+      <underlying-type type-id='type-id-2'/>
       <enumerator name='e0' value='0'/>
       <enumerator name='e1' value='1'/>
     </enum-decl>
@@ -17,8 +16,9 @@
         <var-decl name='m0' type-id='type-id-4' visibility='default'/>
       </data-member>
     </class-decl>
-    <typedef-decl name='opaque_enum' type-id='type-id-2' id='type-id-4'/>
+    <typedef-decl name='opaque_enum' type-id='type-id-1' id='type-id-4'/>
     <typedef-decl name='opaque_struct' type-id='type-id-3' id='type-id-5'/>
+    <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='type-id-2'/>
     <pointer-type-def type-id='type-id-4' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
     <pointer-type-def type-id='type-id-5' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
     <function-decl name='fn' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fn'>
diff --git a/tests/data/test-read-ctf/test1.so.hash.abi b/tests/data/test-read-ctf/test1.so.hash.abi
index b3ace158..4f8633dd 100644
--- a/tests/data/test-read-ctf/test1.so.hash.abi
+++ b/tests/data/test-read-ctf/test1.so.hash.abi
@@ -6,9 +6,8 @@
     <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'/>
     <enum-decl name='opaque_enum' linkage-name='opaque_enum' id='55763a91'>
-      <underlying-type type-id='811c9dc5'/>
+      <underlying-type type-id='9cac1fee'/>
       <enumerator name='e0' value='0'/>
       <enumerator name='e1' value='1'/>
     </enum-decl>
@@ -19,6 +18,7 @@
     </class-decl>
     <typedef-decl name='opaque_enum' type-id='55763a91' id='99fcd3a5'/>
     <typedef-decl name='opaque_struct' type-id='6cde5052' id='dae69ca1'/>
+    <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
     <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'/>
     <function-decl name='fn' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fn'>
diff --git a/tests/data/test-read-ctf/test5.o.abi b/tests/data/test-read-ctf/test5.o.abi
index 6d72d7ab..814aff7f 100644
--- a/tests/data/test-read-ctf/test5.o.abi
+++ b/tests/data/test-read-ctf/test5.o.abi
@@ -7,10 +7,9 @@
     <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='type-id-1'/>
-    <type-decl name='char' size-in-bits='8' id='type-id-2'/>
-    <enum-decl name='E' linkage-name='E' id='type-id-3'>
-      <underlying-type type-id='type-id-1'/>
+    <type-decl name='char' size-in-bits='8' id='type-id-1'/>
+    <enum-decl name='E' linkage-name='E' id='type-id-2'>
+      <underlying-type type-id='type-id-3'/>
       <enumerator name='e0' value='0'/>
       <enumerator name='e1' value='1'/>
     </enum-decl>
@@ -18,7 +17,8 @@
     <type-decl name='long int' size-in-bits='64' id='type-id-5'/>
     <type-decl name='long long int' size-in-bits='64' id='type-id-6'/>
     <typedef-decl name='long_long' type-id='type-id-6' id='type-id-7'/>
-    <pointer-type-def type-id='type-id-2' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
+    <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='type-id-3'/>
+    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
     <qualified-type-def type-id='type-id-4' const='yes' id='type-id-9'/>
     <qualified-type-def type-id='type-id-5' const='yes' id='type-id-10'/>
     <qualified-type-def type-id='type-id-10' volatile='yes' id='type-id-11'/>
@@ -37,7 +37,7 @@
       <return type-id='type-id-12'/>
     </function-decl>
     <function-decl name='bar2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='bar2'>
-      <parameter type-id='type-id-3'/>
+      <parameter type-id='type-id-2'/>
       <return type-id='type-id-12'/>
     </function-decl>
     <function-decl name='baz' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='baz'>
diff --git a/tests/test-read-ctf.cc b/tests/test-read-ctf.cc
index 043032ff..a0b399fc 100644
--- a/tests/test-read-ctf.cc
+++ b/tests/test-read-ctf.cc
@@ -345,6 +345,24 @@ static InOutSpec in_out_specs[] =
     "output/test-read-ctf/test-fallback.abi",
     NULL,
   },
+  {
+    "data/test-read-ctf/test-bitfield.o",
+    "",
+    "",
+    SEQUENCE_TYPE_ID_STYLE,
+    "data/test-read-ctf/test-bitfield.abi",
+    "output/test-read-ctf/test-bitfield.abi",
+    "--ctf",
+  },
+  {
+    "data/test-read-ctf/test-bitfield-enum.o",
+    "",
+    "",
+    SEQUENCE_TYPE_ID_STYLE,
+    "data/test-read-ctf/test-bitfield-enum.abi",
+    "output/test-read-ctf/test-bitfield-enum.abi",
+    "--ctf",
+   },
   // This should be the last entry.
   {NULL, NULL, NULL, SEQUENCE_TYPE_ID_STYLE, NULL, NULL, NULL}
 };
  
Guillermo E. Martinez Nov. 29, 2022, 6:53 p.m. UTC | #3
On 29/11/22 5:53, Dodji Seketeli wrote:
> Hello Guillermo,
> 
> "Guillermo E. Martinez via Libabigail" <libabigail@sourceware.org> a
> écrit:
> 
>> It fixed an incorrect representation in size and name for underlying
>> enum and struct types when it has a bitfield members:
>>
>>      struct foo
>>      {
>>        unsigned bar : 2;
>>        unsigned baz : 1;
>>      };
>>
>>    <type-decl name='' is-anonymous='yes' size-in-bits='2' id='type-id-1'/>
>>
>> So, `name' empty property, no showing the right enumerator's type and size
>> in bits:
>>
>>    <type-decl name='unsigned char' size-in-bits='8' id='type-id-4'/>
> 
> Hmmh, I think here, the name should be "unsigned int", because "unsigned
> bar" implicitly means 'unsigned int bar".  And the size-in-bits should
> be set to 32.
> 

Oh. Sorry, that's right.

> I have thus changed the introductory paragraphs of this commit log to
> the following:
> 
>      This patch fixes an incorrect representation in size and name of the
>      underlying type of enums as well as underlying types of bitfield data
>      members types.
> 
>      For instance, consider this struct.
> 
>          struct foo
>          {
>            unsigned bar : 2;
>            unsigned baz : 1;
>          };
> 
>      The data members bar and baz have an underlying type that is "unsigned
>      int".  Yet, the CTF front-end represents the underlying type of these
>      data members as:
> 
>        <type-decl name='' is-anonymous='yes' size-in-bits='2' id='type-id-1'/>
> 
>      The name property is empty, and it should be "unsigned int".
> 
>      The size in bit is '2', but it should be the size of the underlying
>      "unsigned int", in bits, which is 32.
> 
>      In other words, the underlying type of bar and baz should be:
> 
>        <type-decl name='unsigned int' size-in-bits='32' id='type-id-4'/>
> 
>      Note that today, libabigail doesn't represent the bitfield properties
>      of the data member.  Those bitfield properties are properties of the
>      data member, not of their type.  This is a known "Not Yet Implemented"
>      feature request that has been filed upstream at
>      https://sourceware.org/bugzilla/show_bug.cgi?id=27334.
> 
>      Similarly, the underlying type of enums is not properly represented by
>      the CTF front-end.
> 
>      Fixed thus.
> 
> It's a little bit more verbose, but hopefully, that should give a little
> bit more context for future code maintenance.
>

Totally agree. Thanks Dodji.

>>[...]

Kind regards,
guillermo
  

Patch

diff --git a/src/abg-ctf-reader.cc b/src/abg-ctf-reader.cc
index 9c41edf4..feafc91d 100644
--- a/src/abg-ctf-reader.cc
+++ b/src/abg-ctf-reader.cc
@@ -788,15 +788,17 @@  process_ctf_base_type(reader *rdr,
   translation_unit_sptr tunit = rdr->cur_transl_unit();
   type_decl_sptr result;
 
-  const char *type_name = ctf_type_name_raw(ctf_dictionary, ctf_type);
+  ctf_id_t ctf_ref = ctf_type_reference(ctf_dictionary, ctf_type);
+  const char *type_name = ctf_type_name_raw(ctf_dictionary,
+                                            (ctf_ref != CTF_ERR) ? ctf_ref : ctf_type);
 
   /* Get the type encoding and extract some useful properties of
      the type from it.  In case of any error, just ignore the
      type.  */
   ctf_encoding_t type_encoding;
   if (ctf_type_encoding(ctf_dictionary,
-                         ctf_type,
-                         &type_encoding))
+                        (ctf_ref != CTF_ERR) ? ctf_ref : ctf_type,
+                        &type_encoding))
     return result;
 
   /* Create the IR type corresponding to the CTF type.  */
@@ -1369,7 +1371,10 @@  process_ctf_enum_type(reader *rdr,
 {
   translation_unit_sptr tunit = rdr->cur_transl_unit();
   enum_type_decl_sptr result;
-  std::string enum_name = ctf_type_name_raw(ctf_dictionary, ctf_type);
+  ctf_id_t ctf_ref = ctf_type_reference(ctf_dictionary, ctf_type);
+  std::string enum_name = ctf_type_name_raw(ctf_dictionary,
+                                            (ctf_ref != CTF_ERR)
+                                              ? ctf_ref : ctf_type);
 
   if (!enum_name.empty())
     if (corpus_sptr corp = rdr->should_reuse_type_from_corpus_group())
@@ -1379,18 +1384,24 @@  process_ctf_enum_type(reader *rdr,
   /* Build a signed integral type for the type of the enumerators, aka
      the underlying type.  The size of the enumerators in bytes is
      specified in the CTF enumeration type.  */
-  size_t utype_size_in_bits = ctf_type_size(ctf_dictionary, ctf_type) * 8;
-  type_decl_sptr utype;
+  size_t utype_size_in_bits = ctf_type_size(ctf_dictionary,
+                                            (ctf_ref != CTF_ERR)
+                                              ? ctf_ref : ctf_type) * 8;
+  string underlying_type_name =
+        build_internal_underlying_enum_type_name(enum_name, true,
+                                                 utype_size_in_bits);
 
+  type_decl_sptr utype;
   utype.reset(new type_decl(rdr->env(),
-                              "",
-                              utype_size_in_bits,
-                              utype_size_in_bits,
-                              location()));
+                            underlying_type_name,
+                            utype_size_in_bits,
+                            utype_size_in_bits,
+                            location()));
   utype->set_is_anonymous(true);
   utype->set_is_artificial(true);
   if (!utype)
     return result;
+
   add_decl_to_scope(utype, tunit->get_global_scope());
   canonicalize(utype);
 
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index 4b6e9305..b89a4dd8 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -704,6 +704,12 @@  test-read-ctf/test-linux-module.ko		\
 test-read-ctf/test-fallback.abi		\
 test-read-ctf/test-fallback.c		\
 test-read-ctf/test-fallback.o		\
+test-read-ctf/test-bitfield.abi		\
+test-read-ctf/test-bitfield.c		\
+test-read-ctf/test-bitfield.o		\
+test-read-ctf/test-bitfield-enum.abi	\
+test-read-ctf/test-bitfield-enum.c	\
+test-read-ctf/test-bitfield-enum.o	\
 \
 test-annotate/test0.abi			\
 test-annotate/test1.abi			\
diff --git a/tests/data/test-read-ctf/PR27700/test-PR27700.abi b/tests/data/test-read-ctf/PR27700/test-PR27700.abi
index 4f34eb8a..1a7c229e 100644
--- a/tests/data/test-read-ctf/PR27700/test-PR27700.abi
+++ b/tests/data/test-read-ctf/PR27700/test-PR27700.abi
@@ -3,14 +3,14 @@ 
     <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'/>
+      <underlying-type type-id='9cac1fee'/>
       <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='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
     <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' elf-symbol-id='foo'>
       <parameter type-id='8750e847'/>
diff --git a/tests/data/test-read-ctf/test-bitfield-enum.abi b/tests/data/test-read-ctf/test-bitfield-enum.abi
new file mode 100644
index 00000000..b95f1781
--- /dev/null
+++ b/tests/data/test-read-ctf/test-bitfield-enum.abi
@@ -0,0 +1,18 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test-bitfield-enum.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='e' 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'>
+    <enum-decl name='event_kind' linkage-name='event_kind' id='type-id-1'>
+      <underlying-type type-id='type-id-2'/>
+      <enumerator name='NO_EVENT' value='0'/>
+    </enum-decl>
+    <class-decl name='input' size-in-bits='32' is-struct='yes' visibility='default' id='type-id-3'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='kind' type-id='type-id-1' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='type-id-2'/>
+    <var-decl name='e' type-id='type-id-3' mangled-name='e' visibility='default' elf-symbol-id='e'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-bitfield-enum.c b/tests/data/test-read-ctf/test-bitfield-enum.c
new file mode 100644
index 00000000..502ec06a
--- /dev/null
+++ b/tests/data/test-read-ctf/test-bitfield-enum.c
@@ -0,0 +1,12 @@ 
+/* gcc -gctf -c test-bitfield-enum.c -o test-bitfield-enum.o */
+enum event_kind
+{
+  NO_EVENT,
+};
+
+struct input
+{
+  enum event_kind kind : 16;
+};
+
+struct input e;
diff --git a/tests/data/test-read-ctf/test-bitfield-enum.o b/tests/data/test-read-ctf/test-bitfield-enum.o
new file mode 100644
index 0000000000000000000000000000000000000000..2c532f50c724f7bf4327b7c36699a432ca08eab1
GIT binary patch
literal 1336
zcmbVL&2G~`5T1lkeh>7}s)CE@g;e0R6E4sLvQ&j4gu(@SLuGAm(^c(tWN#ojAvp0!
z9C;I-0bT%R?A>IwlnWz$p1<!~?~LqElUL9Cy&hQW!86!owhFN9Z{nm46SxI8;n$DB
zx)W_EFu<5_-QW)T_lPfuD~Qm5VtOB9pZK>CWILVPqFR91M<C}e<wFD+#m1h{CFmRg
ze3SSfls>(XDu?Oo)5*zX`UV!NkuxRoKq?JV%@-P4f`I6}Dn*p8(p6N|JS#-h)LB%>
zl&5mWWf3azG18*ZO_X!Z+c2yJ&%;cgby+I)nG{7H3biO%25@|IbQlber*98}(PI{~
zI2gy{@n{r34TfSl7qu+$io7^zuZ#~n=T(eR27Ty#cjm*{y1bjws{Z!WAHdJwerFd8
z+wJDN&iZT`EcEX$09dmsHBZs&y7T8Y(qgHB(Jp|cO#=+~fRC!AnSiNE3x+d<jpo^f
z$!BW8=5>XW>y>}E|H<#6h-TgL#EF;N)Zg2EY*3B9Ki3jBabjQp0DJUp|4YB#uQ|id
zA7R};lc)(j(00A1m%<1+REvr1*oh%NbZQh@z4eDq&82>}1h;qz_a)Y@A?Uwz?W@uI
y_o7|7Ml@eb{clG9!jNwmp4IO;b$|D5%N%NXhQ6NP=Gz!trr$IAca~_pzm`9z|8lDU

literal 0
HcmV?d00001

diff --git a/tests/data/test-read-ctf/test-bitfield.abi b/tests/data/test-read-ctf/test-bitfield.abi
--- /dev/null
+++ b/tests/data/test-read-ctf/test-bitfield.abi
@@ -0,0 +1,28 @@ 
+<abi-corpus version='2.1' path='data/test-read-ctf/test-bitfield.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='f' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='fb' size='1' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-variable-symbols>
+  <abi-instr address-size='64' language='LANG_C'>
+    <class-decl name='foo' size-in-bits='32' is-struct='yes' visibility='default' id='type-id-1'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='bar' type-id='type-id-2' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='2'>
+        <var-decl name='baz' type-id='type-id-2' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <class-decl name='foobar' size-in-bits='8' is-struct='yes' visibility='default' id='type-id-3'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='bar' type-id='type-id-4' visibility='default'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='2'>
+        <var-decl name='baz' type-id='type-id-4' visibility='default'/>
+      </data-member>
+    </class-decl>
+    <type-decl name='unsigned char' size-in-bits='8' id='type-id-4'/>
+    <type-decl name='unsigned int' size-in-bits='32' id='type-id-2'/>
+    <var-decl name='f' type-id='type-id-1' mangled-name='f' visibility='default' elf-symbol-id='f'/>
+    <var-decl name='fb' type-id='type-id-3' mangled-name='fb' visibility='default' elf-symbol-id='fb'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-bitfield.c b/tests/data/test-read-ctf/test-bitfield.c
new file mode 100644
index 00000000..7d76d2f4
--- /dev/null
+++ b/tests/data/test-read-ctf/test-bitfield.c
@@ -0,0 +1,15 @@ 
+/* gcc -gctf -c test-bitfield.c -o test-bitfield.o */
+struct foo
+{
+  unsigned bar : 2;
+  unsigned baz : 1;
+};
+
+struct foobar 
+{
+  unsigned char bar : 2;
+  unsigned char baz : 1;
+};
+
+struct foo f;
+struct foobar fb;
diff --git a/tests/data/test-read-ctf/test-bitfield.o b/tests/data/test-read-ctf/test-bitfield.o
new file mode 100644
index 0000000000000000000000000000000000000000..c23c8188d880587f2ba78b8b852cdb067607e4b6
GIT binary patch
literal 1488
zcmbVM&2G~`5FVEh3S3$$Arvm|iB=FhNe{FYLXj${gb+85NZ8IMu}JL7-in3`cOC%o
z6g&e@fw=Ju@B%QOcgI<lp93S!&dm4CjCUs8zJ2uc@kS7kNI(y19SKUbb!qL78+T0C
z=^B0i+Sw51fjDe8t!}Y}hOA#$-?3h1#W#*v?^~5vIBweOFn5C$g3sS%#m9gnkEIJg
zglFUseawa0YdKgzJ;V2q7n>To!uG)6&AoRG-bD`2A&r_o-G&p09E`K4Wl85nozDt2
z3G+fznpCWBK)`LeY~B!-q-jd=yj-d{U8SqItdeY@;=0P>MV=;UK1=dNzfiAZt!iDz
zlSC(t+pknI>1TRsqBPgjTrDP1Ms#{|avbiRK6}0&4iBP1Gzdq7(P%gv9EE%8;!IWf
zQWZK`?3+=|PD2i`S1#kBgHPD4NMK{^<X-~5L*IV*Iok|uH@~7`r1y@+C2sp;*1j{+
z6kDRGUM+Q!velKbbMdsg&=g@g6s2`d5if?1a*0VPDoU*)o~&Q%BztA!S#chnRVD93
zulyVTUwoU(FoXF!S@#&P-Cw+RUW@Ls1?D`rh8Z{K?}uN1hg0zO{#I|_P1{KJF2Fr@
z{GQ;(I9T3$q!-eVbASzy?8s-Ec-O(;O1;=)2Xj+{_Q|>Ex?a#H?BG57>6;et?}c5t
yf_wP2;14bM5&_FqRzOmJ3m^+{fA_#Y*n0dAb4BJB4DaMm^&f5h3rV!rum1@|M0T$L

literal 0
HcmV?d00001

diff --git a/tests/data/test-read-ctf/test-enum-many.o.hash.abi b/tests/data/test-read-ctf/test-enum-many.o.hash.abi
--- a/tests/data/test-read-ctf/test-enum-many.o.hash.abi
+++ b/tests/data/test-read-ctf/test-enum-many.o.hash.abi
@@ -4,14 +4,13 @@ 
     <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'/>
+      <underlying-type type-id='9cac1fee'/>
       <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'/>
+      <underlying-type type-id='9cac1fee'/>
       <enumerator name='IE_0' value='-10'/>
       <enumerator name='IE_1' value='-9'/>
       <enumerator name='IE_2' value='-8'/>
@@ -61,6 +60,7 @@ 
       <enumerator name='IE_2E' value='36'/>
       <enumerator name='IE_2F' value='37'/>
     </enum-decl>
+    <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
     <var-decl name='foo' type-id='a6c2eddf' mangled-name='foo' visibility='default' elf-symbol-id='foo'/>
     <var-decl name='bar' type-id='1ee696ca' mangled-name='bar' visibility='default' elf-symbol-id='bar'/>
   </abi-instr>
diff --git a/tests/data/test-read-ctf/test-enum-symbol.o.hash.abi b/tests/data/test-read-ctf/test-enum-symbol.o.hash.abi
index f4911bc4..da68828c 100644
--- a/tests/data/test-read-ctf/test-enum-symbol.o.hash.abi
+++ b/tests/data/test-read-ctf/test-enum-symbol.o.hash.abi
@@ -3,13 +3,13 @@ 
     <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'/>
+      <underlying-type type-id='9cac1fee'/>
       <enumerator name='red1' value='0'/>
       <enumerator name='green1' value='1'/>
       <enumerator name='blue1' value='2'/>
     </enum-decl>
+    <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
     <var-decl name='primary1' type-id='08f5ca17' mangled-name='primary1' visibility='default' elf-symbol-id='primary1'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test-enum.o.abi b/tests/data/test-read-ctf/test-enum.o.abi
index bd3a55be..e13ebdd0 100644
--- a/tests/data/test-read-ctf/test-enum.o.abi
+++ b/tests/data/test-read-ctf/test-enum.o.abi
@@ -4,19 +4,19 @@ 
     <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'/>
+    <enum-decl name='e' linkage-name='e' id='type-id-1'>
+      <underlying-type type-id='type-id-2'/>
       <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'/>
+      <underlying-type type-id='type-id-2'/>
       <enumerator name='IENUMSAMPLE_1' value='-10'/>
       <enumerator name='IENUMSAMPLE_2' value='-9'/>
       <enumerator name='IENUMSAMPLE_3' value='-8'/>
     </enum-decl>
-    <var-decl name='foo' type-id='type-id-2' mangled-name='foo' visibility='default' elf-symbol-id='foo'/>
+    <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='type-id-2'/>
+    <var-decl name='foo' type-id='type-id-1' mangled-name='foo' visibility='default' elf-symbol-id='foo'/>
     <var-decl name='bar' type-id='type-id-3' mangled-name='bar' visibility='default' elf-symbol-id='bar'/>
   </abi-instr>
 </abi-corpus>
diff --git a/tests/data/test-read-ctf/test0.abi b/tests/data/test-read-ctf/test0.abi
index 05430067..60d3cf1e 100644
--- a/tests/data/test-read-ctf/test0.abi
+++ b/tests/data/test-read-ctf/test0.abi
@@ -20,47 +20,47 @@ 
     <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' id='type-id-1'/>
-    <type-decl name='char' size-in-bits='8' id='type-id-2'/>
-    <type-decl name='float' size-in-bits='32' id='type-id-3'/>
-    <type-decl name='int' size-in-bits='32' id='type-id-4'/>
-    <array-type-def dimensions='1' type-id='type-id-4' size-in-bits='320' id='type-id-5'>
-      <subrange length='10' type-id='type-id-6' id='type-id-7'/>
+    <type-decl name='char' size-in-bits='8' id='type-id-1'/>
+    <type-decl name='float' size-in-bits='32' id='type-id-2'/>
+    <type-decl name='int' size-in-bits='32' id='type-id-3'/>
+    <array-type-def dimensions='1' type-id='type-id-3' size-in-bits='320' id='type-id-4'>
+      <subrange length='10' type-id='type-id-5' id='type-id-6'/>
     </array-type-def>
-    <type-decl name='long int' size-in-bits='64' id='type-id-8'/>
-    <type-decl name='short int' size-in-bits='16' id='type-id-9'/>
-    <class-decl name='S' size-in-bits='32' is-struct='yes' visibility='default' id='type-id-10'>
+    <type-decl name='long int' size-in-bits='64' id='type-id-7'/>
+    <type-decl name='short int' size-in-bits='16' id='type-id-8'/>
+    <class-decl name='S' size-in-bits='32' is-struct='yes' visibility='default' id='type-id-9'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='m0' type-id='type-id-4' visibility='default'/>
+        <var-decl name='m0' type-id='type-id-3' visibility='default'/>
       </data-member>
     </class-decl>
-    <class-decl name='' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-11'>
+    <class-decl name='' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='type-id-10'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='status0' type-id='type-id-1' visibility='default'/>
+        <var-decl name='status0' type-id='type-id-11' visibility='default'/>
       </data-member>
       <data-member access='public' layout-offset-in-bits='1'>
-        <var-decl name='status1' type-id='type-id-1' visibility='default'/>
+        <var-decl name='status1' type-id='type-id-11' visibility='default'/>
       </data-member>
     </class-decl>
-    <type-decl name='unsigned long int' size-in-bits='64' id='type-id-6'/>
-    <pointer-type-def type-id='type-id-10' size-in-bits='64' alignment-in-bits='64' id='type-id-12'/>
-    <pointer-type-def type-id='type-id-2' size-in-bits='64' alignment-in-bits='64' id='type-id-13'/>
-    <qualified-type-def type-id='type-id-10' const='yes' id='type-id-14'/>
-    <pointer-type-def type-id='type-id-8' size-in-bits='64' alignment-in-bits='64' id='type-id-15'/>
+    <type-decl name='unsigned int' size-in-bits='32' id='type-id-11'/>
+    <type-decl name='unsigned long int' size-in-bits='64' id='type-id-5'/>
+    <pointer-type-def type-id='type-id-9' size-in-bits='64' alignment-in-bits='64' id='type-id-12'/>
+    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-13'/>
+    <qualified-type-def type-id='type-id-9' const='yes' id='type-id-14'/>
+    <pointer-type-def type-id='type-id-7' size-in-bits='64' alignment-in-bits='64' id='type-id-15'/>
     <qualified-type-def type-id='type-id-15' restrict='yes' id='type-id-16'/>
-    <qualified-type-def type-id='type-id-9' volatile='yes' id='type-id-17'/>
-    <var-decl name='status' type-id='type-id-11' mangled-name='status' visibility='default' elf-symbol-id='status'/>
+    <qualified-type-def type-id='type-id-8' volatile='yes' id='type-id-17'/>
+    <var-decl name='status' type-id='type-id-10' mangled-name='status' visibility='default' elf-symbol-id='status'/>
     <var-decl name='test_pointer' type-id='type-id-13' mangled-name='test_pointer' visibility='default' elf-symbol-id='test_pointer'/>
     <var-decl name='test_const' type-id='type-id-14' mangled-name='test_const' visibility='default' elf-symbol-id='test_const'/>
-    <var-decl name='test_float' type-id='type-id-3' mangled-name='test_float' visibility='default' elf-symbol-id='test_float'/>
+    <var-decl name='test_float' type-id='type-id-2' mangled-name='test_float' visibility='default' elf-symbol-id='test_float'/>
     <function-decl name='foo_1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo_1'>
       <parameter type-id='type-id-12'/>
-      <return type-id='type-id-4'/>
+      <return type-id='type-id-3'/>
     </function-decl>
     <function-decl name='main' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='main'>
-      <return type-id='type-id-4'/>
+      <return type-id='type-id-3'/>
     </function-decl>
-    <var-decl name='test_array' type-id='type-id-5' mangled-name='test_array' visibility='default' elf-symbol-id='test_array'/>
+    <var-decl name='test_array' type-id='type-id-4' mangled-name='test_array' visibility='default' elf-symbol-id='test_array'/>
     <var-decl name='test_restrict' type-id='type-id-16' mangled-name='test_restrict' visibility='default' elf-symbol-id='test_restrict'/>
     <var-decl name='test_volatile' type-id='type-id-17' mangled-name='test_volatile' visibility='default' elf-symbol-id='test_volatile'/>
   </abi-instr>
diff --git a/tests/data/test-read-ctf/test0.hash.abi b/tests/data/test-read-ctf/test0.hash.abi
index 4aa9a93c..76dd581e 100644
--- a/tests/data/test-read-ctf/test0.hash.abi
+++ b/tests/data/test-read-ctf/test0.hash.abi
@@ -20,7 +20,6 @@ 
     <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' id='811c9dc5'/>
     <type-decl name='char' size-in-bits='8' id='a84c031d'/>
     <type-decl name='float' size-in-bits='32' id='a6c45d85'/>
     <type-decl name='int' size-in-bits='32' id='95e97e5e'/>
@@ -34,14 +33,15 @@ 
         <var-decl name='m0' type-id='95e97e5e' visibility='default'/>
       </data-member>
     </class-decl>
-    <class-decl name='' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='b91ffdee'>
+    <class-decl name='' size-in-bits='32' is-struct='yes' is-anonymous='yes' visibility='default' id='000d9e42'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='status0' type-id='811c9dc5' visibility='default'/>
+        <var-decl name='status0' type-id='f0981eec' visibility='default'/>
       </data-member>
       <data-member access='public' layout-offset-in-bits='1'>
-        <var-decl name='status1' type-id='811c9dc5' visibility='default'/>
+        <var-decl name='status1' type-id='f0981eec' visibility='default'/>
       </data-member>
     </class-decl>
+    <type-decl name='unsigned int' size-in-bits='32' id='f0981eec'/>
     <type-decl name='unsigned long int' size-in-bits='64' id='f0981eeb'/>
     <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'/>
@@ -49,7 +49,7 @@ 
     <pointer-type-def type-id='95e97e5f' size-in-bits='64' alignment-in-bits='64' id='7292109c'/>
     <qualified-type-def type-id='7292109c' restrict='yes' id='6942f6a4'/>
     <qualified-type-def type-id='95e97e60' volatile='yes' id='e024ff18'/>
-    <var-decl name='status' type-id='b91ffdee' mangled-name='status' visibility='default' elf-symbol-id='status'/>
+    <var-decl name='status' type-id='000d9e42' mangled-name='status' visibility='default' elf-symbol-id='status'/>
     <var-decl name='test_pointer' type-id='26a90f95' mangled-name='test_pointer' visibility='default' elf-symbol-id='test_pointer'/>
     <var-decl name='test_const' type-id='0fb3b55d' mangled-name='test_const' visibility='default' elf-symbol-id='test_const'/>
     <var-decl name='test_float' type-id='a6c45d85' mangled-name='test_float' visibility='default' elf-symbol-id='test_float'/>
diff --git a/tests/data/test-read-ctf/test1.so.abi b/tests/data/test-read-ctf/test1.so.abi
index 822b57a5..2ecd5826 100644
--- a/tests/data/test-read-ctf/test1.so.abi
+++ b/tests/data/test-read-ctf/test1.so.abi
@@ -6,9 +6,8 @@ 
     <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'/>
-    <enum-decl name='opaque_enum' linkage-name='opaque_enum' id='type-id-2'>
-      <underlying-type type-id='type-id-1'/>
+    <enum-decl name='opaque_enum' linkage-name='opaque_enum' id='type-id-1'>
+      <underlying-type type-id='type-id-2'/>
       <enumerator name='e0' value='0'/>
       <enumerator name='e1' value='1'/>
     </enum-decl>
@@ -17,8 +16,9 @@ 
         <var-decl name='m0' type-id='type-id-4' visibility='default'/>
       </data-member>
     </class-decl>
-    <typedef-decl name='opaque_enum' type-id='type-id-2' id='type-id-4'/>
+    <typedef-decl name='opaque_enum' type-id='type-id-1' id='type-id-4'/>
     <typedef-decl name='opaque_struct' type-id='type-id-3' id='type-id-5'/>
+    <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='type-id-2'/>
     <pointer-type-def type-id='type-id-4' size-in-bits='64' alignment-in-bits='64' id='type-id-6'/>
     <pointer-type-def type-id='type-id-5' size-in-bits='64' alignment-in-bits='64' id='type-id-7'/>
     <function-decl name='fn' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fn'>
diff --git a/tests/data/test-read-ctf/test1.so.hash.abi b/tests/data/test-read-ctf/test1.so.hash.abi
index b3ace158..4f8633dd 100644
--- a/tests/data/test-read-ctf/test1.so.hash.abi
+++ b/tests/data/test-read-ctf/test1.so.hash.abi
@@ -6,9 +6,8 @@ 
     <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'/>
     <enum-decl name='opaque_enum' linkage-name='opaque_enum' id='55763a91'>
-      <underlying-type type-id='811c9dc5'/>
+      <underlying-type type-id='9cac1fee'/>
       <enumerator name='e0' value='0'/>
       <enumerator name='e1' value='1'/>
     </enum-decl>
@@ -19,6 +18,7 @@ 
     </class-decl>
     <typedef-decl name='opaque_enum' type-id='55763a91' id='99fcd3a5'/>
     <typedef-decl name='opaque_struct' type-id='6cde5052' id='dae69ca1'/>
+    <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
     <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'/>
     <function-decl name='fn' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fn'>
diff --git a/tests/data/test-read-ctf/test5.o.abi b/tests/data/test-read-ctf/test5.o.abi
index 6d72d7ab..814aff7f 100644
--- a/tests/data/test-read-ctf/test5.o.abi
+++ b/tests/data/test-read-ctf/test5.o.abi
@@ -7,10 +7,9 @@ 
     <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='type-id-1'/>
-    <type-decl name='char' size-in-bits='8' id='type-id-2'/>
-    <enum-decl name='E' linkage-name='E' id='type-id-3'>
-      <underlying-type type-id='type-id-1'/>
+    <type-decl name='char' size-in-bits='8' id='type-id-1'/>
+    <enum-decl name='E' linkage-name='E' id='type-id-2'>
+      <underlying-type type-id='type-id-3'/>
       <enumerator name='e0' value='0'/>
       <enumerator name='e1' value='1'/>
     </enum-decl>
@@ -18,7 +17,8 @@ 
     <type-decl name='long int' size-in-bits='64' id='type-id-5'/>
     <type-decl name='long long int' size-in-bits='64' id='type-id-6'/>
     <typedef-decl name='long_long' type-id='type-id-6' id='type-id-7'/>
-    <pointer-type-def type-id='type-id-2' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
+    <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='type-id-3'/>
+    <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
     <qualified-type-def type-id='type-id-4' const='yes' id='type-id-9'/>
     <qualified-type-def type-id='type-id-5' const='yes' id='type-id-10'/>
     <qualified-type-def type-id='type-id-10' volatile='yes' id='type-id-11'/>
@@ -37,7 +37,7 @@ 
       <return type-id='type-id-12'/>
     </function-decl>
     <function-decl name='bar2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='bar2'>
-      <parameter type-id='type-id-3'/>
+      <parameter type-id='type-id-2'/>
       <return type-id='type-id-12'/>
     </function-decl>
     <function-decl name='baz' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='baz'>
diff --git a/tests/test-read-ctf.cc b/tests/test-read-ctf.cc
index 14e63ef0..5d0e7435 100644
--- a/tests/test-read-ctf.cc
+++ b/tests/test-read-ctf.cc
@@ -345,6 +345,24 @@  static InOutSpec in_out_specs[] =
     "output/test-read-ctf/test-fallback.abi",
     NULL,
   },
+  {
+    "data/test-read-ctf/test-bitfield.o",
+    "",
+    "",
+    SEQUENCE_TYPE_ID_STYLE,
+    "data/test-read-ctf/test-bitfield.abi",
+    "output/test-read-ctf/test-bitfield.abi",
+    "--ctf",
+  },
+  {
+    "data/test-read-ctf/test-bitfield-enum.o",
+    "",
+    "",
+    SEQUENCE_TYPE_ID_STYLE,
+    "data/test-read-ctf/test-bitfield-enum.abi",
+    "output/test-read-ctf/test-bitfield-enum.abi",
+    "--ctf",
+   },
   // This should be the last entry.
   {NULL, NULL, NULL, SEQUENCE_TYPE_ID_STYLE, NULL, NULL}
 };