[Bug ipa/103080] New: LTO alters the ordering of static constructors/destructors in pass_ipa_cdtor_merge.

iains at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Thu Nov 4 13:48:28 GMT 2021


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103080

            Bug ID: 103080
           Summary: LTO alters the ordering of static
                    constructors/destructors in pass_ipa_cdtor_merge.
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: ipa
          Assignee: unassigned at gcc dot gnu.org
          Reporter: iains at gcc dot gnu.org
                CC: marxin at gcc dot gnu.org
  Target Milestone: ---

consider the following :
--------
#include <stdio.h>

/* Define USE_PRIO to to test that.*/

#ifdef USE_PRIO
#define PRIO_CTOR constructor(12345)
#define PRIO_DTOR destructor(12345)
#else
#define PRIO_CTOR constructor
#define PRIO_DTOR destructor
#endif

__attribute__((constructor))
static void
startup ()
{
  fprintf(stderr, "startup\n");
}

__attribute__((destructor))
static void
shutdown ()
{
  fprintf(stderr, "shutdown\n");
}

__attribute__((PRIO_CTOR))
static void
startup1 ()
{
  fprintf(stderr, "startup1\n");
}

__attribute__((PRIO_CTOR))
static void
startup2 ()
{
  fprintf(stderr, "startup2\n");
}

__attribute__((PRIO_DTOR))
static void
shutdown1 ()
{
  fprintf(stderr, "shutdown1\n");
}

__attribute__((destructor))
static void
shutdown2 ()
{
  fprintf(stderr, "shutdown2\n");
}

int main ()
{
  printf ("42\n");
  return 0;
}

====

This initial output is (to the best of my knowledge, although we do not
document it well enough) the correct behaviour.  Essentially, we execute the
static constructors in order of declaration and the destructors in the reverse
order.  This is the most reasonable ordering from the user's perspective and
more-or-less follows what C++ does (although the static DTORs are not tied to
their CTORs - they *can* be placed together in the source to make it readable).

$ ./gcc/xgcc -Bgcc ~/ctor-dtor.c -o ct 
$ ./ct
startup
startup1
startup2
42
shutdown2
shutdown1
shutdown

-----

$ ./gcc/xgcc -Bgcc ~/ctor-dtor.c -o ct -flto
$ ./ct
startup2
startup1
startup
42
shutdown
shutdown1
shutdown2

This is not (IMO at least) correct - at the very least the program behaviour
will be different with/without LTO.

I suspect that the logic is inverted in ipa.c:compare_ctor / compare_dtor. 
There is a comment that this is intended to make it more likely that library
CTORs will run early - but ISTM that if that is needed then an alternate
mechanism must be used.

=======
similar issues when priority is in use
NOTE that the different DTOR ordering *is* intentional as can be seen from the
source above.

$ ./gcc/xgcc -Bgcc ~/ctor-dtor.c -o ct -DUSE_PRIO
$ ./ct
startup1
startup2
startup
42
shutdown2
shutdown
shutdown1
---
$ ./gcc/xgcc -Bgcc ~/ctor-dtor.c -o ct -DUSE_PRIO -flto
$ ./ct
startup2
startup1
startup
42
shutdown
shutdown2
shutdown1
======


More information about the Gcc-bugs mailing list