libctf: properly handle ctf_add_type of forwards and self-reffing structs
authorNick Alcock <nick.alcock@oracle.com>
Wed, 7 Aug 2019 17:01:08 +0000 (18:01 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Thu, 3 Oct 2019 16:04:56 +0000 (17:04 +0100)
commit99dc3ebdfff927b30db58117d7bd80586e273669
tree8d96f1ae0a335ee1485e9faaaf2a570422347183
parent676c3ecbad6e9c41b906b0f882ef2ce23f49976a
libctf: properly handle ctf_add_type of forwards and self-reffing structs

The code to handle structures (and unions) that refer to themselves in
ctf_add_type is extremely dodgy.  It works by looking through the list
of not-yet-committed types for a structure with the same name as the
structure in question and assuming, if it finds it, that this must be a
reference to the same type.  This is a linear search that gets ever
slower as the dictionary grows, requiring you to call ctf_update at
intervals to keep performance tolerable: but if you do that, you run
into the problem that if a forward declared before the ctf_update is
changed to a structure afterwards, ctf_update explodes.

The last commit fixed most of this: this commit can use it, adding a new
ctf_add_processing hash that tracks source type IDs that are currently
being processed and uses it to avoid infinite recursion rather than the
dynamic type list: we split ctf_add_type into a ctf_add_type_internal,
so that ctf_add_type itself can become a wrapper that empties out this
being-processed hash once the entire recursive type addition is over.
Structure additions themselves avoid adding their dependent types
quite so much by checking the type mapping and avoiding re-adding types
we already know we have added.

We also add support for adding forwards to dictionaries that already
contain the thing they are a forward to: we just silently return the
original type.

v4: return existing struct/union/enum types properly, rather than using
    an uninitialized variable: shrinks sizes of CTF sections back down
    to roughly where they were in v1/v2 of this patch series.
v5: fix tabdamage.

libctf/
* ctf-impl.h (ctf_file_t) <ctf_add_processing>: New.
* ctf-open.c (ctf_file_close): Free it.
* ctf-create.c (ctf_serialize): Adjust.
(membcmp): When reporting a conflict due to an error, report the
error.
(ctf_add_type): Turn into a ctf_add_processing wrapper.  Rename to...
(ctf_add_type_internal): ... this.  Hand back types we are already
in the middle of adding immediately.  Hand back structs/unions with
the same number of members immediately.  Do not walk the dynamic
list.  Call ctf_add_type_internal, not ctf_add_type.  Handle
forwards promoted to other types and the inverse case identically.
Add structs to the mapping as soon as we intern them, before they
gain any members.
libctf/ChangeLog
libctf/ctf-create.c
libctf/ctf-impl.h
libctf/ctf-open.c