#include <fcntl.h> /* For open(3) */
#include <iostream>
+#include <memory>
#include "ctf-api.h"
{
namespace ctf_reader
{
+using std::dynamic_pointer_cast;
class read_context
{
if (!utype)
return result;
+ result = dynamic_pointer_cast<typedef_decl>(ctxt->lookup_type(ctf_type));
+ if (result)
+ return result;
+
result.reset(new typedef_decl(typedef_name, utype, location(),
typedef_name /* mangled_name */));
decl->set_naming_typedef(result);
}
+ if (result)
+ {
+ add_decl_to_scope(result, tunit->get_global_scope());
+ ctxt->add_type(ctf_type, result);
+ }
+
return result;
}
static type_decl_sptr
process_ctf_base_type(read_context *ctxt,
corpus_sptr corp,
+ translation_unit_sptr tunit,
ctf_dict_t *ctf_dictionary,
ctf_id_t ctf_type)
{
}
+ if (result)
+ {
+ add_decl_to_scope(result, tunit->get_global_scope());
+ ctxt->add_type(ctf_type, result);
+ }
+
return result;
}
function_parms.push_back(parm);
}
+ result = dynamic_pointer_cast<function_type>(ctxt->lookup_type(ctf_type));
+ if (result)
+ return result;
/* Ok now the function type itself. */
result.reset(new function_type(ret_type,
tunit->get_address_size(),
ctf_type_align(ctf_dictionary, ctf_type)));
- tunit->bind_function_type_life_time(result);
- result->set_is_artificial(true);
+ if (result)
+ {
+ tunit->bind_function_type_life_time(result);
+ result->set_is_artificial(true);
+ decl_base_sptr function_type_decl = get_type_declaration(result);
+ add_decl_to_scope(function_type_decl, tunit->get_global_scope());
+ ctxt->add_type(ctf_type, result);
+ }
+
return result;
}
refer to this struct, we have to make it available in the cache
at this point even if the members haven't been added to the IR
node yet. */
+ add_decl_to_scope(result, tunit->get_global_scope());
ctxt->add_type(ctf_type, result);
/* Now add the struct members as specified in the CTF type description.
refer to this union, we have to make it available in the cache
at this point even if the members haven't been added to the IR
node yet. */
+ add_decl_to_scope(result, tunit->get_global_scope());
ctxt->add_type(ctf_type, result);
/* Now add the union members as specified in the CTF type description.
if (!index_type)
return result;
+ result = dynamic_pointer_cast<array_type_def>(ctxt->lookup_type(ctf_type));
+ if (result)
+ return result;
+
/* The number of elements of the array determines the IR subranges
type to build. */
array_type_def::subranges_type subranges;
/* Finally build the IR for the array type and return it. */
result.reset(new array_type_def(element_type, subranges, location()));
+ if (result)
+ {
+ decl_base_sptr array_type_decl = get_type_declaration(result);
+ add_decl_to_scope(array_type_decl, tunit->get_global_scope());
+ ctxt->add_type(ctf_type, result);
+ }
+
return result;
}
ABG_ASSERT_NOT_REACHED;
result.reset(new qualified_type_def(utype, qualifiers, location()));
+
+ if (result)
+ {
+ decl_base_sptr qualified_type_decl = get_type_declaration(result);
+ add_decl_to_scope(qualified_type_decl, tunit->get_global_scope());
+ ctxt->add_type(ctf_type, result);
+ }
+
return result;
}
if (!target_type)
return result;
+ result = dynamic_pointer_cast<pointer_type_def>(ctxt->lookup_type(ctf_type));
+ if (result)
+ return result;
+
result.reset(new pointer_type_def(target_type,
ctf_type_size(ctf_dictionary, ctf_type) * 8,
ctf_type_align(ctf_dictionary, ctf_type) * 8,
location()));
+ if (result)
+ {
+ add_decl_to_scope(result, tunit->get_global_scope());
+ ctxt->add_type(ctf_type, result);
+ }
+
return result;
}
const char *enum_name = ctf_type_name_raw(ctf_dictionary, ctf_type);
result.reset(new enum_type_decl(enum_name, location(),
utype, enms, enum_name));
+ if (result)
+ {
+ add_decl_to_scope(result, tunit->get_global_scope());
+ ctxt->add_type(ctf_type, result);
+ }
+
return result;
}
int type_kind = ctf_type_kind(ctf_dictionary, ctf_type);
type_base_sptr result;
+ if ((result = ctxt->lookup_type(ctf_type)))
+ return result;
+
switch (type_kind)
{
case CTF_K_INTEGER:
case CTF_K_FLOAT:
{
type_decl_sptr type_decl
- = process_ctf_base_type(ctxt, corp, ctf_dictionary, ctf_type);
-
- if (type_decl)
- {
- add_decl_to_scope(type_decl, tunit->get_global_scope());
- result = is_type(type_decl);
- }
+ = process_ctf_base_type(ctxt, corp, tunit, ctf_dictionary, ctf_type);
+ result = is_type(type_decl);
break;
}
case CTF_K_TYPEDEF:
{
typedef_decl_sptr typedef_decl
= process_ctf_typedef(ctxt, corp, tunit, ctf_dictionary, ctf_type);
-
- if (typedef_decl)
- {
- add_decl_to_scope(typedef_decl, tunit->get_global_scope());
- result = is_type(typedef_decl);
- }
+ result = is_type(typedef_decl);
break;
}
case CTF_K_POINTER:
{
pointer_type_def_sptr pointer_type
= process_ctf_pointer_type(ctxt, corp, tunit, ctf_dictionary, ctf_type);
-
- if (pointer_type)
- {
- add_decl_to_scope(pointer_type, tunit->get_global_scope());
- result = pointer_type;
- }
+ result = pointer_type;
break;
}
case CTF_K_CONST:
{
type_base_sptr qualified_type
= process_ctf_qualified_type(ctxt, corp, tunit, ctf_dictionary, ctf_type);
-
- if (qualified_type)
- {
- decl_base_sptr qualified_type_decl = get_type_declaration(qualified_type);
-
- add_decl_to_scope(qualified_type_decl, tunit->get_global_scope());
- result = qualified_type;
- }
+ result = qualified_type;
break;
}
case CTF_K_ARRAY:
{
array_type_def_sptr array_type
= process_ctf_array_type(ctxt, corp, tunit, ctf_dictionary, ctf_type);
-
- if (array_type)
- {
- decl_base_sptr array_type_decl = get_type_declaration(array_type);
-
- add_decl_to_scope(array_type_decl, tunit->get_global_scope());
- result = array_type;
- }
+ result = array_type;
break;
}
case CTF_K_ENUM:
{
enum_type_decl_sptr enum_type
= process_ctf_enum_type(ctxt, tunit, ctf_dictionary, ctf_type);
-
- if (enum_type)
- {
- add_decl_to_scope(enum_type, tunit->get_global_scope());
- result = enum_type;
- }
-
+ result = enum_type;
break;
}
case CTF_K_FUNCTION:
{
function_type_sptr function_type
= process_ctf_function_type(ctxt, corp, tunit, ctf_dictionary, ctf_type);
-
- if (function_type)
- {
- decl_base_sptr function_type_decl = get_type_declaration(function_type);
-
- add_decl_to_scope(function_type_decl, tunit->get_global_scope());
- result = function_type;
- }
+ result = function_type;
break;
}
case CTF_K_STRUCT:
{
class_decl_sptr struct_decl
= process_ctf_struct_type(ctxt, corp, tunit, ctf_dictionary, ctf_type);
-
- if (struct_decl)
- {
- add_decl_to_scope(struct_decl, tunit->get_global_scope());
- result = is_type(struct_decl);
- }
+ result = is_type(struct_decl);
break;
}
case CTF_K_UNION:
{
union_decl_sptr union_decl
= process_ctf_union_type(ctxt, corp, tunit, ctf_dictionary, ctf_type);
-
- if (union_decl)
- {
- add_decl_to_scope(union_decl, tunit->get_global_scope());
- result = is_type(union_decl);
- }
+ result = is_type(union_decl);
break;
}
case CTF_K_UNKNOWN:
break;
}
- if (result)
- ctxt->add_type(ctf_type, result);
- else
+ if (!result)
fprintf(stderr, "NOT PROCESSED TYPE %lu\n", ctf_type);
return result;
test-read-ctf/test-struct-iteration.o.abi \
test-read-ctf/PR27700/test-PR27700.abi \
test-read-ctf/PR26261/PR26261-exe.abi \
+test-read-ctf/test-callback.c \
+test-read-ctf/test-callback.abi \
+test-read-ctf/test-callback.o \
+test-read-ctf/test-array-of-pointers.c \
+test-read-ctf/test-array-of-pointers.o \
+test-read-ctf/test-array-of-pointers.abi \
+test-read-ctf/test-functions-declaration.abi \
+test-read-ctf/test-functions-declaration.c \
+test-read-ctf/test-functions-declaration.o \
+test-read-ctf/test-forward-type-decl.abi \
+test-read-ctf/test-forward-type-decl.o \
+test-read-ctf/test-forward-type-decl.c \
+test-read-ctf/test-list-struct.c \
+test-read-ctf/test-list-struct.o \
+test-read-ctf/test-list-struct.abi \
+test-read-ctf/test-callback2.c \
+test-read-ctf/test-callback2.o \
+test-read-ctf/test-callback2.abi \
\
test-annotate/test0.abi \
test-annotate/test1.abi \
--- /dev/null
+<abi-corpus version='2.1' path='data/test-read-ctf/test-array-of-pointers.o'>
+ <elf-variable-symbols>
+ <elf-symbol name='t' 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'>
+ <class-decl name='cgroup' size-in-bits='256' 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='s1' type-id='type-id-2' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='css_set' size-in-bits='256' 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='s0' type-id='type-id-2' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='state' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='type-id-4'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='cg' type-id='type-id-5' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='task' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='type-id-6'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='s' type-id='type-id-7' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <array-type-def dimensions='1' type-id='type-id-8' size-in-bits='256' alignment-in-bits='64' id='type-id-2'>
+ <subrange length='4' type-id='type-id-9' id='type-id-10'/>
+ </array-type-def>
+ <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='type-id-9'/>
+ <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-5'/>
+ <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-4' size-in-bits='64' alignment-in-bits='64' id='type-id-8'/>
+ <pointer-type-def type-id='type-id-6' size-in-bits='64' alignment-in-bits='64' id='type-id-11'/>
+ <var-decl name='t' type-id='type-id-11' mangled-name='t' visibility='default'/>
+ </abi-instr>
+</abi-corpus>
--- /dev/null
+/* Test a array of pointer definition as struct member
+ * gcc -gctf -c test-array-of-pointers.c -o test-array-of-pointer.o
+ */
+struct task {
+ struct css_set *s;
+};
+
+struct state {
+ struct cgroup *cg;
+};
+
+struct css_set {
+ struct state *s0[4];
+};
+
+struct cgroup {
+ struct state *s1[4];
+};
+
+struct task *t;
--- /dev/null
+<abi-corpus version='2.1' path='data/test-read-ctf/test-callback.o'>
+ <elf-function-symbols>
+ <elf-symbol name='assign' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='f2' 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='test' 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='fn1' type-id='type-id-2' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-3'/>
+ <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-4'/>
+ <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-5'/>
+ <pointer-type-def type-id='type-id-6' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
+ <function-decl name='assign' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+ <return type-id='type-id-7'/>
+ </function-decl>
+ <function-decl name='f2' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+ <parameter type-id='type-id-3'/>
+ <parameter type-id='type-id-4'/>
+ <return type-id='type-id-7'/>
+ </function-decl>
+ <function-type size-in-bits='64' alignment-in-bits='8' id='type-id-6'>
+ <parameter type-id='type-id-3'/>
+ <parameter type-id='type-id-4'/>
+ <return type-id='type-id-7'/>
+ </function-type>
+ <type-decl name='void' id='type-id-7'/>
+ </abi-instr>
+</abi-corpus>
--- /dev/null
+/* Test a simple callback as a struct member
+ * gcc -gctf -c test-callback.c -o test-callback.o
+ */
+struct test {
+ void (*fn1)(int, long);
+};
+
+void f2(int a, long b)
+{
+}
+
+void assign()
+{
+ struct test *tt;
+ tt->fn1 = f2;
+}
--- /dev/null
+<abi-corpus version='2.1' path='data/test-read-ctf/test-callback2.o'>
+ <elf-variable-symbols>
+ <elf-symbol name='s0' 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'>
+ <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='mem_fun' type-id='type-id-2' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-3'/>
+ <pointer-type-def type-id='type-id-4' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
+ <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-5'/>
+ <var-decl name='s0' type-id='type-id-5' mangled-name='s0' visibility='default'/>
+ <function-type size-in-bits='64' alignment-in-bits='8' id='type-id-4'>
+ <parameter type-id='type-id-5'/>
+ <return type-id='type-id-3'/>
+ </function-type>
+ </abi-instr>
+</abi-corpus>
--- /dev/null
+/* Test a simple callback as a struct member
+ * that takes a pointer to a struct parent as
+ * argument
+ * gcc -gctf -c test-callback2.c -o test-callback2.o
+ */
+struct s0
+{
+ int (*mem_fun)(struct s0 *);
+};
+
+struct s0 *s0;
--- /dev/null
+<abi-corpus version='2.1' path='data/test-read-ctf/test-forward-type-decl.o'>
+ <elf-variable-symbols>
+ <elf-symbol name='addr' 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'>
+ <class-decl name='address_space' size-in-bits='128' 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='rb_root' type-id='type-id-2' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='page' type-id='type-id-3' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='page' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='type-id-4'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='mapping' type-id='type-id-5' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='rb_node' size-in-bits='64' alignment-in-bits='64' is-struct='yes' visibility='default' id='type-id-6'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='rb_left' type-id='type-id-2' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <pointer-type-def type-id='type-id-1' size-in-bits='64' alignment-in-bits='64' id='type-id-5'/>
+ <pointer-type-def type-id='type-id-4' size-in-bits='64' alignment-in-bits='64' id='type-id-3'/>
+ <pointer-type-def type-id='type-id-6' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
+ <var-decl name='addr' type-id='type-id-5' mangled-name='addr' visibility='default'/>
+ </abi-instr>
+</abi-corpus>
--- /dev/null
+/* Test a forward type declaration as a struct member
+ * to exercise circular dependencies.
+ * gcc -gctf -c test-forward-type-decl.c -o \
+ * test-forward-type-decl.o
+ */
+typedef struct page *page_t;
+
+struct rb_node {
+ struct rb_node *rb_left;
+};
+
+struct address_space;
+
+struct page {
+ struct address_space *mapping;
+};
+
+struct address_space {
+ struct rb_node *rb_root;
+ struct page *page;
+};
+
+struct address_space *addr;
--- /dev/null
+<abi-corpus version='2.1' path='data/test-read-ctf/test-functions-declaration.o'>
+ <elf-function-symbols>
+ <elf-symbol name='attribute_container_add_device' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='attribute_container_device_trigger' 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='int' size-in-bits='32' alignment-in-bits='32' id='type-id-1'/>
+ <type-decl name='long int' size-in-bits='64' alignment-in-bits='64' id='type-id-2'/>
+ <pointer-type-def type-id='type-id-3' size-in-bits='64' alignment-in-bits='64' id='type-id-4'/>
+ <function-decl name='attribute_container_add_device' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+ <parameter type-id='type-id-4'/>
+ <return type-id='type-id-5'/>
+ </function-decl>
+ <function-decl name='attribute_container_device_trigger' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8'>
+ <parameter type-id='type-id-4'/>
+ <return type-id='type-id-5'/>
+ </function-decl>
+ <function-type size-in-bits='64' alignment-in-bits='8' id='type-id-3'>
+ <parameter type-id='type-id-1'/>
+ <parameter type-id='type-id-2'/>
+ <return type-id='type-id-5'/>
+ </function-type>
+ <type-decl name='void' id='type-id-5'/>
+ </abi-instr>
+</abi-corpus>
--- /dev/null
+/* Test declaring twice a function pinter a struct member
+ * gcc -gctf -c test-functions-declaration.c -o \
+ * test-functions-declaration.o
+ */
+void
+attribute_container_add_device(
+ void (*fn1)(int, long))
+{
+}
+
+void
+attribute_container_device_trigger(
+ void (*fn2)(int , long))
+{
+
+}
--- /dev/null
+<abi-corpus version='2.1' path='data/test-read-ctf/test-list-struct.o'>
+ <elf-variable-symbols>
+ <elf-symbol name='n1' size='16' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='n2' size='16' 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='rb_node_b' size-in-bits='128' 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='this' type-id='type-id-2' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='a' type-id='type-id-3' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <type-decl name='int' 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-2'/>
+ <var-decl name='n1' type-id='type-id-1' mangled-name='n1' visibility='default'/>
+ <var-decl name='n2' type-id='type-id-1' mangled-name='n2' visibility='default'/>
+ </abi-instr>
+</abi-corpus>
--- /dev/null
+/* Test a ADT where a struct member is a pointer to
+ * itself.
+ * gcc -gctf -c test-callback.c -o test-callback.o
+ */
+
+struct rb_node_b {
+ struct rb_node_b *this;
+ int a;
+};
+
+struct rb_node_b n1, n2;
"data/test-read-ctf/PR27700/test-PR27700.abi",
"output/test-read-ctf/PR27700/test-PR27700.abi",
},
+ {
+ "data/test-read-ctf/test-callback.o",
+ "",
+ "",
+ SEQUENCE_TYPE_ID_STYLE,
+ "data/test-read-ctf/test-callback.abi",
+ "output/test-read-ctf/test-callback.abi",
+ },
+ {
+ "data/test-read-ctf/test-array-of-pointers.o",
+ "",
+ "",
+ SEQUENCE_TYPE_ID_STYLE,
+ "data/test-read-ctf/test-array-of-pointers.abi",
+ "output/test-read-ctf/test-array-of-pointers.abi",
+ },
+ {
+ "data/test-read-ctf/test-functions-declaration.o",
+ "",
+ "",
+ SEQUENCE_TYPE_ID_STYLE,
+ "data/test-read-ctf/test-functions-declaration.abi",
+ "output/test-read-ctf/test-functions-declaration.abi",
+ },
+ {
+ "data/test-read-ctf/test-forward-type-decl.o",
+ "",
+ "",
+ SEQUENCE_TYPE_ID_STYLE,
+ "data/test-read-ctf/test-forward-type-decl.abi",
+ "output/test-read-ctf/test-forward-type-decl.abi",
+ },
+ {
+ "data/test-read-ctf/test-list-struct.o",
+ "",
+ "",
+ SEQUENCE_TYPE_ID_STYLE,
+ "data/test-read-ctf/test-list-struct.abi",
+ "output/test-read-ctf/test-list-struct.abi",
+ },
+ {
+ "data/test-read-ctf/test-callback2.o",
+ "",
+ "",
+ SEQUENCE_TYPE_ID_STYLE,
+ "data/test-read-ctf/test-callback2.abi",
+ "output/test-read-ctf/test-callback2.abi",
+ },
// This should be the last entry.
{NULL, NULL, NULL, SEQUENCE_TYPE_ID_STYLE, NULL, NULL}
};