]> sourceware.org Git - libabigail.git/commitdiff
ctf-reader: Fix representation of multidimensional arrays
authorGuillermo E. Martinez <guillermo.e.martinez@oracle.com>
Thu, 17 Nov 2022 03:43:04 +0000 (21:43 -0600)
committerDodji Seketeli <dodji@redhat.com>
Wed, 30 Nov 2022 09:39:51 +0000 (10:39 +0100)
To build an IR for multidimensional array the CTF front-end iterates
over the element types recursively.

So, consider the array definition:

  char a[2][3][4][5];

It's represented as

  'char[2][3][4] a[5]'

instead of:

  'char a[2][3][4][5]'

It always considers multidimensional arrays as unidimensional creating
a `array-type-def' node for each dimension:

  <array-type-def dimensions='1' type-id='type-id-1' ... >
    <subrange length='2' type-id='type-id-3' id='type-id-4'/>
  </array-type-def>
  <array-type-def dimensions='1' type-id='type-id-2' ... >
    <subrange length='3' type-id='type-id-3' id='type-id-6'/>
  </array-type-def>
  ...

Instead of:

  <array-type-def dimensions='4' type-id='type-id-1' ... >
     <subrange length='2' type-id='type-id-3' id='type-id-4'/>
     <subrange length='3' type-id='type-id-3' id='type-id-5'/>
     ...
  </array-type-def>

Fixed thus.

* src/abg-ctf-reader.cc (+build_array_ctf_range): New definition.
* tests/data/Makefile.am: Add new testcase.
* tests/data/test-read-ctf/test-array-mdimension.abi: New testcase.
* tests/data/test-read-ctf/test-array-mdimension.c: Likewise.
* tests/data/test-read-ctf/test-array-mdimension.o: Likewise.
* tests/data/test-read-ctf/test9.o.abi: Adjust.
* tests/test-read-ctf.cc: Update testsuite.

Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
src/abg-ctf-reader.cc
tests/data/Makefile.am
tests/data/test-read-ctf/test-array-mdimension.abi [new file with mode: 0644]
tests/data/test-read-ctf/test-array-mdimension.c [new file with mode: 0644]
tests/data/test-read-ctf/test-array-mdimension.o [new file with mode: 0644]
tests/data/test-read-ctf/test9.o.abi
tests/test-read-ctf.cc

index c48e61a46af123e47fd9f1fe7e25db8a44fcc551..b4b957d243e818e7f220fb32c47b67c0e968bf28 100644 (file)
@@ -1163,6 +1163,57 @@ process_ctf_union_type(reader *rdr,
   return result;
 }
 
+/// Build and return an array subrange.
+///
+/// @param rdr the read context.
+///
+/// @param ctf_dictionary the CTF dictionary where @ref index
+/// will be found.
+///
+/// @param index the CTF type ID for the array index.
+///
+/// @param nelems the elements number of the array.
+///
+/// @return a shared pointer to subrange built.
+static array_type_def::subrange_sptr
+build_array_ctf_range(reader *rdr, ctf_dict_t *dic,
+                      ctf_id_t index, uint64_t nelems)
+{
+  bool is_infinite = false;
+  corpus_sptr corp = rdr->corpus();
+  translation_unit_sptr tunit = rdr->cur_transl_unit();
+  array_type_def::subrange_sptr subrange;
+  array_type_def::subrange_type::bound_value lower_bound;
+  array_type_def::subrange_type::bound_value upper_bound;
+
+  type_base_sptr index_type = rdr->build_type(dic, index);
+  if (!index_type)
+    return nullptr;
+
+  lower_bound.set_unsigned(0); /* CTF supports C only.  */
+  upper_bound.set_unsigned(nelems > 0 ? nelems - 1 : 0U);
+
+  /* for VLAs number of array elements is 0 */
+  if (upper_bound.get_unsigned_value() == 0)
+    is_infinite = true;
+
+  subrange.reset(new array_type_def::subrange_type(rdr->env(),
+                                                   "",
+                                                   lower_bound,
+                                                   upper_bound,
+                                                   index_type,
+                                                   location(),
+                                                   translation_unit::LANG_C));
+  if (!subrange)
+    return nullptr;
+
+  subrange->is_infinite(is_infinite);
+  add_decl_to_scope(subrange, tunit->get_global_scope());
+  canonicalize(subrange);
+
+  return subrange;
+}
+
 /// Build and return an array type libabigail IR.
 ///
 /// @param rdr the read context.
@@ -1181,7 +1232,6 @@ process_ctf_array_type(reader *rdr,
   translation_unit_sptr tunit = rdr->cur_transl_unit();
   array_type_def_sptr result;
   ctf_arinfo_t ctf_ainfo;
-  bool is_infinite = false;
 
   /* First, get the information about the CTF array.  */
   if (static_cast<ctf_id_t>(ctf_array_info(ctf_dictionary,
@@ -1192,6 +1242,26 @@ process_ctf_array_type(reader *rdr,
   ctf_id_t ctf_element_type = ctf_ainfo.ctr_contents;
   ctf_id_t ctf_index_type = ctf_ainfo.ctr_index;
   uint64_t nelems = ctf_ainfo.ctr_nelems;
+  array_type_def::subrange_sptr subrange;
+  array_type_def::subranges_type subranges;
+
+  int type_array_kind = ctf_type_kind(ctf_dictionary, ctf_element_type);
+  while (type_array_kind == CTF_K_ARRAY)
+    {
+      if (static_cast<ctf_id_t>(ctf_array_info(ctf_dictionary,
+                                               ctf_element_type,
+                                               &ctf_ainfo)) == CTF_ERR)
+        return result;
+
+      subrange = build_array_ctf_range(rdr, ctf_dictionary,
+                                       ctf_ainfo.ctr_index,
+                                       ctf_ainfo.ctr_nelems);
+      subranges.push_back(subrange);
+      ctf_element_type = ctf_ainfo.ctr_contents;
+      type_array_kind = ctf_type_kind(ctf_dictionary, ctf_element_type);
+    }
+
+  std::reverse(subranges.begin(), subranges.end());
 
   /* Make sure the element type is generated.  */
   type_base_sptr element_type = rdr->build_type(ctf_dictionary,
@@ -1210,33 +1280,8 @@ process_ctf_array_type(reader *rdr,
   if (result)
     return result;
 
-  /* The number of elements of the array determines the IR subranges
-     type to build.  */
-  array_type_def::subranges_type subranges;
-  array_type_def::subrange_sptr subrange;
-  array_type_def::subrange_type::bound_value lower_bound;
-  array_type_def::subrange_type::bound_value upper_bound;
-
-  lower_bound.set_unsigned(0); /* CTF supports C only.  */
-  upper_bound.set_unsigned(nelems > 0 ? nelems - 1 : 0U);
-
-  /* for VLAs number of array elements is 0 */
-  if (upper_bound.get_unsigned_value() == 0)
-    is_infinite = true;
-
-  subrange.reset(new array_type_def::subrange_type(rdr->env(),
-                                                   "",
-                                                   lower_bound,
-                                                   upper_bound,
-                                                   index_type,
-                                                   location(),
-                                                   translation_unit::LANG_C));
-  if (!subrange)
-    return result;
-
-  subrange->is_infinite(is_infinite);
-  add_decl_to_scope(subrange, tunit->get_global_scope());
-  canonicalize(subrange);
+  subrange = build_array_ctf_range(rdr, ctf_dictionary,
+                                   ctf_index_type, nelems);
   subranges.push_back(subrange);
 
   /* Finally build the IR for the array type and return it.  */
index 8d4a2b8f71821e6ce034d38995df1ce5030b671a..d04ecf3f94d4996156251ef9aa84c4f86610f5fb 100644 (file)
@@ -713,6 +713,9 @@ test-read-ctf/test-bitfield-enum.o  \
 test-read-ctf/test-const-array.abi     \
 test-read-ctf/test-const-array.c       \
 test-read-ctf/test-const-array.o       \
+test-read-ctf/test-array-mdimension.abi        \
+test-read-ctf/test-array-mdimension.c  \
+test-read-ctf/test-array-mdimension.o  \
 \
 test-annotate/test0.abi                        \
 test-annotate/test1.abi                        \
diff --git a/tests/data/test-read-ctf/test-array-mdimension.abi b/tests/data/test-read-ctf/test-array-mdimension.abi
new file mode 100644 (file)
index 0000000..177284d
--- /dev/null
@@ -0,0 +1,16 @@
+<abi-corpus version='2.1' path='data/test-read-ctf/test-array-mdimension.o'>
+  <elf-variable-symbols>
+    <elf-symbol name='a' size='120' 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' id='type-id-1'/>
+    <array-type-def dimensions='4' type-id='type-id-1' size-in-bits='960' id='type-id-2'>
+      <subrange length='2' type-id='type-id-3' id='type-id-4'/>
+      <subrange length='3' type-id='type-id-3' id='type-id-5'/>
+      <subrange length='4' type-id='type-id-3' id='type-id-6'/>
+      <subrange length='5' type-id='type-id-3' id='type-id-7'/>
+    </array-type-def>
+    <type-decl name='unsigned long int' size-in-bits='64' id='type-id-3'/>
+    <var-decl name='a' type-id='type-id-2' mangled-name='a' visibility='default' elf-symbol-id='a'/>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-read-ctf/test-array-mdimension.c b/tests/data/test-read-ctf/test-array-mdimension.c
new file mode 100644 (file)
index 0000000..317fc58
--- /dev/null
@@ -0,0 +1,2 @@
+/* gcc -gctf -c test-array-mdimension.c -o test-array-mdimension.o */
+char a[2][3][4][5];
diff --git a/tests/data/test-read-ctf/test-array-mdimension.o b/tests/data/test-read-ctf/test-array-mdimension.o
new file mode 100644 (file)
index 0000000..5b392d8
Binary files /dev/null and b/tests/data/test-read-ctf/test-array-mdimension.o differ
index 331bfc7094c2afc33ef64204005ec142a9c35903..9f5a74662101c79668d196ee1703dbecf0cfe441 100644 (file)
       <subrange length='infinite' type-id='type-id-4' id='type-id-7'/>
     </array-type-def>
     <type-decl name='double' size-in-bits='64' id='type-id-8'/>
-    <array-type-def dimensions='1' type-id='type-id-8' size-in-bits='320' id='type-id-9'>
+    <array-type-def dimensions='2' type-id='type-id-8' size-in-bits='960' id='type-id-9'>
       <subrange length='5' type-id='type-id-4' id='type-id-10'/>
+      <subrange length='3' type-id='type-id-4' id='type-id-11'/>
     </array-type-def>
-    <array-type-def dimensions='1' type-id='type-id-9' size-in-bits='960' id='type-id-11'>
-      <subrange length='3' type-id='type-id-4' id='type-id-12'/>
+    <type-decl name='int' size-in-bits='32' id='type-id-12'/>
+    <array-type-def dimensions='1' type-id='type-id-13' size-in-bits='256' alignment-in-bits='64' id='type-id-14'>
+      <subrange length='4' type-id='type-id-4' id='type-id-15'/>
     </array-type-def>
-    <type-decl name='int' size-in-bits='32' id='type-id-13'/>
-    <array-type-def dimensions='1' type-id='type-id-14' size-in-bits='256' alignment-in-bits='64' id='type-id-15'>
-      <subrange length='4' type-id='type-id-4' id='type-id-16'/>
+    <array-type-def dimensions='1' type-id='type-id-16' size-in-bits='640' alignment-in-bits='64' id='type-id-17'>
+      <subrange length='10' type-id='type-id-4' id='type-id-18'/>
     </array-type-def>
-    <array-type-def dimensions='1' type-id='type-id-17' size-in-bits='640' alignment-in-bits='64' id='type-id-18'>
-      <subrange length='10' type-id='type-id-4' id='type-id-19'/>
-    </array-type-def>
-    <array-type-def dimensions='1' type-id='type-id-13' size-in-bits='160' id='type-id-20'>
+    <array-type-def dimensions='1' type-id='type-id-12' size-in-bits='160' id='type-id-19'>
       <subrange length='5' type-id='type-id-4' id='type-id-10'/>
     </array-type-def>
-    <class-decl name='S' size-in-bits='2304' is-struct='yes' visibility='default' id='type-id-21'>
+    <class-decl name='S' size-in-bits='2304' is-struct='yes' visibility='default' id='type-id-20'>
       <data-member access='public' layout-offset-in-bits='0'>
-        <var-decl name='a' type-id='type-id-20' visibility='default'/>
+        <var-decl name='a' type-id='type-id-19' visibility='default'/>
       </data-member>
       <data-member access='public' layout-offset-in-bits='192'>
         <var-decl name='b' type-id='type-id-3' visibility='default'/>
       </data-member>
       <data-member access='public' layout-offset-in-bits='640'>
-        <var-decl name='c' type-id='type-id-11' visibility='default'/>
+        <var-decl name='c' type-id='type-id-9' visibility='default'/>
       </data-member>
       <data-member access='public' layout-offset-in-bits='1600'>
-        <var-decl name='d' type-id='type-id-18' visibility='default'/>
+        <var-decl name='d' type-id='type-id-17' visibility='default'/>
       </data-member>
       <data-member access='public' layout-offset-in-bits='2240'>
         <var-decl name='e' type-id='type-id-6' visibility='default'/>
       </data-member>
     </class-decl>
     <type-decl name='unsigned long int' size-in-bits='64' id='type-id-4'/>
-    <pointer-type-def type-id='type-id-21' size-in-bits='64' alignment-in-bits='64' id='type-id-22'/>
+    <pointer-type-def type-id='type-id-20' size-in-bits='64' alignment-in-bits='64' id='type-id-21'/>
     <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
-    <pointer-type-def type-id='type-id-13' size-in-bits='64' alignment-in-bits='64' id='type-id-14'/>
-    <pointer-type-def type-id='type-id-15' size-in-bits='64' alignment-in-bits='64' id='type-id-17'/>
+    <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-16'/>
     <function-decl name='foo' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
-      <parameter type-id='type-id-22'/>
-      <return type-id='type-id-13'/>
+      <parameter type-id='type-id-21'/>
+      <return type-id='type-id-12'/>
     </function-decl>
   </abi-instr>
 </abi-corpus>
index f2d529e27b6424bf3be547f6cbb77873815c3dbd..f3d461181e8da24b01c4b693f281082b251aa3fc 100644 (file)
@@ -372,6 +372,15 @@ static InOutSpec in_out_specs[] =
     "output/test-read-ctf/test-const-array.abi",
     "--ctf",
   },
+  {
+    "data/test-read-ctf/test-array-mdimension.o",
+    "",
+    "",
+    SEQUENCE_TYPE_ID_STYLE,
+    "data/test-read-ctf/test-array-mdimension.abi",
+    "output/test-read-ctf/test-array-mdimension.abi",
+    "--ctf",
+  },
   // This should be the last entry.
   {NULL, NULL, NULL, SEQUENCE_TYPE_ID_STYLE, NULL, NULL, NULL}
 };
This page took 0.048912 seconds and 5 git commands to generate.