/*
gcc -W -Wall -Os -fPIC -Wl,-init,constructor1_init -shared -o constructor1.so constructor1.c &&
gcc -W -Wall -Os -o constructor0 constructor0.c -ldl &&
./constructor0
*/

#include <stdio.h>
#include <dlfcn.h>

#define SECTION( S ) __attribute__ ((section ( S )))

#pragma GCC diagnostic ignored "-Wunused-variable"

__asm__(".section .init \n call init0extern \n .section .text\n");
extern void init0extern(void) {
  printf ("init0extern\n");
}

static void ctor0static(void) {
   printf("ctor0static -- SHOULDN'T BE CALLED!\n");
}
static void (*ctor0static_ptr)(void) SECTION(".ctors") =ctor0static; // won't be called.

static void ctor0extern(void) {
   printf("ctor0extern\n");
}
/*extern*/ void (*ctor0extern_ptr)(void) SECTION(".ctors") =ctor0extern;

__attribute__((constructor (110)))
static void constructor0static110() {
  printf("constructor0static110\n");
}

__attribute__((constructor (130)))
static void constructor0static130() {
  printf("constructor0static130\n");
}

__attribute__((constructor (120)))
extern void constructor0extern120() {
  printf("constructor0extern120\n");
}

typedef void thunk(void);

static void constructor0static(void) {
  printf("constructor0static\n");
}
thunk* constructor0static_ptr = constructor0static;

extern int main (int argc, char** argv) {
  (void)argc; (void)argv;
  printf("Hello, World!\n");
  (*constructor0static_ptr)();
  void* dl = dlopen("./constructor1.so", RTLD_LOCAL|RTLD_NOW); // RTLD_GLOBAL|RTLD_NOW
  printf("dl = %p\n", dl);
  if (!dl) {
    printf("dlerror(): %s\n", dlerror());
  }
  thunk* c1 = (thunk*) dlsym(dl, "constructor1");
  printf("constructor1 = %p\n", c1);
  if (c1) {
    (*c1)();
  } else {
    printf("dlerror(): %s\n", dlerror());
  }
  return 0;
}
