This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

SPARC: nested static initialization


Hi,

we've run into an issue with ld.bfd on SPARC (Solaris 10 and 11) with
nested static initialization when using shared libraries.

Given the touchy subject of static initialization I thought it'd be
better to check here before filing a bug report.

The attached small test case calls a global function during static
initialization in a shared library. After the function address is
resolved but before the function is actually being called, the global
initialization from main executable is triggered and registers used to
hold function arguments get clobbered. The test case fails only for
64-bit, but the nested initialization also happens for 32-bit.

Basically with ld.bfd the initialization sequence is something like

  init_shared
    -> func@plt
  init_main
    -> func

while with the Solaris linker and on x86_64 the shared lib
initialization is completed before the one from main is starting:

  init_shared
    -> func@plt
    -> func
  init_main

Unfortunately the gold linker is currently not available on the
affected platforms.

This problem is present in binutils-2.25.1 but the regression seems to
have occurred between 2.21 and 2.23.2. It may be related to the
presence of INIT_ARRAY section (which is present for 2.23.2 and
later).

The observed behavior was independent of the gcc version tested
(between 4.6 and 5.2).

Is this a bug in ld.bfd on SPARC or is this undefined behavior?

Using either of '-z now' or '-z initfirst' when building shared
libraries seems to avoid the issue (at least for the particular issue
we encountered). Neither seems a good / satisfactory solution for
larger scale projects and when mixing in third party libraries. Any
comments regarding the potential drawbacks (if any) for either use
would be greatly appreciated.

Many thanks in advance,
Erik.

Attachment: Makefile
Description: Binary data

bool equals42(double x) {
  return 42. == x;
}

void killjoy(double) { }

static bool init_main() {
  killjoy(11.);
  return true;
}

static bool done_main = init_main();

int main(int, char **) { return 0; }
bool equals42(double x) {
  return 42. == x;
}

static bool init_shared_1() {
  return true;
}

static bool init_shared_2() {
  if (!equals42(42.)) __builtin_abort();
  return true;
}

static bool done_shared_1 = init_shared_1();
static bool done_shared_2 = init_shared_2();

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]