Blame elf/nodelete.c

Packit 6c4009
#include <dlfcn.h>
Packit 6c4009
#include <setjmp.h>
Packit 6c4009
#include <signal.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
Packit 6c4009
Packit 6c4009
static sigjmp_buf jmpbuf;
Packit 6c4009
Packit 6c4009
Packit 6c4009
int fini_ran;
Packit 6c4009
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
__attribute__ ((noreturn))
Packit 6c4009
handler (int sig)
Packit 6c4009
{
Packit 6c4009
  siglongjmp (jmpbuf, 1);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
do_test (void)
Packit 6c4009
{
Packit 6c4009
  /* We are testing the two possibilities to mark an object as not deletable:
Packit 6c4009
     - marked on the linker commandline with `-z nodelete'
Packit 6c4009
     - with the RTLD_NODELETE flag at dlopen()-time.
Packit 6c4009
Packit 6c4009
     The test we are performing should be safe.  We are loading the objects,
Packit 6c4009
     get the address of variables in the respective object, unload the object
Packit 6c4009
     and then try to read the variable.  If the object is unloaded this
Packit 6c4009
     should lead to an segmentation fault.  */
Packit 6c4009
  int result = 0;
Packit 6c4009
  void *p;
Packit 6c4009
  struct sigaction sa;
Packit 6c4009
Packit 6c4009
  sa.sa_handler = handler;
Packit 6c4009
  sigfillset (&sa.sa_mask);
Packit 6c4009
  sa.sa_flags = SA_RESTART;
Packit 6c4009
Packit 6c4009
  if (sigaction (SIGSEGV, &sa, NULL) == -1)
Packit 6c4009
    printf ("cannot install signal handler: %m\n");
Packit 6c4009
Packit 6c4009
  p = dlopen ("nodelmod1.so", RTLD_LAZY);
Packit 6c4009
  if (p == NULL)
Packit 6c4009
    {
Packit 6c4009
      printf ("failed to load \"nodelmod1.so\": %s\n", dlerror ());
Packit 6c4009
      result = 1;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      int *varp;
Packit 6c4009
Packit 6c4009
      puts ("succeeded loading \"nodelmod1.so\"");
Packit 6c4009
Packit 6c4009
      varp = dlsym (p, "var1");
Packit 6c4009
      if (varp == NULL)
Packit 6c4009
	{
Packit 6c4009
	  puts ("failed to get address of \"var1\" in \"nodelmod1.so\"");
Packit 6c4009
	  result = 1;
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  *varp = 20000720;
Packit 6c4009
Packit 6c4009
	  /* Now close the object.  */
Packit 6c4009
	  fini_ran = 0;
Packit 6c4009
	  if (dlclose (p) != 0)
Packit 6c4009
	    {
Packit 6c4009
	      puts ("failed to close \"nodelmod1.so\"");
Packit 6c4009
	      result = 1;
Packit 6c4009
	    }
Packit 6c4009
	  else if (! sigsetjmp (jmpbuf, 1))
Packit 6c4009
	    {
Packit 6c4009
	      /* Access the variable again.  */
Packit 6c4009
	      if (*varp != 20000720)
Packit 6c4009
		{
Packit 6c4009
		  puts ("\"var1\" value not correct");
Packit 6c4009
		  result = 1;
Packit 6c4009
		}
Packit 6c4009
	      else if (fini_ran != 0)
Packit 6c4009
		{
Packit 6c4009
		  puts ("destructor of \"nodelmod1.so\" ran");
Packit 6c4009
		  result = 1;
Packit 6c4009
		}
Packit 6c4009
	      else
Packit 6c4009
		puts ("-z nodelete test succeeded");
Packit 6c4009
	    }
Packit 6c4009
	  else
Packit 6c4009
	    {
Packit 6c4009
	      /* We caught an segmentation fault.  */
Packit 6c4009
	      puts ("\"nodelmod1.so\" got deleted");
Packit 6c4009
	      result = 1;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  p = dlopen ("nodelmod2.so", RTLD_LAZY | RTLD_NODELETE);
Packit 6c4009
  if (p == NULL)
Packit 6c4009
    {
Packit 6c4009
      printf ("failed to load \"nodelmod2.so\": %s\n", dlerror ());
Packit 6c4009
      result = 1;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      int *varp;
Packit 6c4009
Packit 6c4009
      puts ("succeeded loading \"nodelmod2.so\"");
Packit 6c4009
Packit 6c4009
      varp = dlsym (p, "var2");
Packit 6c4009
      if (varp == NULL)
Packit 6c4009
	{
Packit 6c4009
	  puts ("failed to get address of \"var2\" in \"nodelmod2.so\"");
Packit 6c4009
	  result = 1;
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  *varp = 42;
Packit 6c4009
Packit 6c4009
	  /* Now close the object.  */
Packit 6c4009
	  fini_ran = 0;
Packit 6c4009
	  if (dlclose (p) != 0)
Packit 6c4009
	    {
Packit 6c4009
	      puts ("failed to close \"nodelmod2.so\"");
Packit 6c4009
	      result = 1;
Packit 6c4009
	    }
Packit 6c4009
	  else if (! sigsetjmp (jmpbuf, 1))
Packit 6c4009
	    {
Packit 6c4009
	      /* Access the variable again.  */
Packit 6c4009
	      if (*varp != 42)
Packit 6c4009
		{
Packit 6c4009
		  puts ("\"var2\" value not correct");
Packit 6c4009
		  result = 1;
Packit 6c4009
		}
Packit 6c4009
	      else if (fini_ran != 0)
Packit 6c4009
		{
Packit 6c4009
		  puts ("destructor of \"nodelmod2.so\" ran");
Packit 6c4009
		  result = 1;
Packit 6c4009
		}
Packit 6c4009
	      else
Packit 6c4009
		puts ("RTLD_NODELETE test succeeded");
Packit 6c4009
	    }
Packit 6c4009
	  else
Packit 6c4009
	    {
Packit 6c4009
	      /* We caught an segmentation fault.  */
Packit 6c4009
	      puts ("\"nodelmod2.so\" got deleted");
Packit 6c4009
	      result = 1;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  p = dlopen ("nodelmod3.so", RTLD_LAZY);
Packit 6c4009
  if (p == NULL)
Packit 6c4009
    {
Packit 6c4009
      printf ("failed to load \"nodelmod3.so\": %s\n", dlerror ());
Packit 6c4009
      result = 1;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      int *(*fctp) (void);
Packit 6c4009
Packit 6c4009
      puts ("succeeded loading \"nodelmod3.so\"");
Packit 6c4009
Packit 6c4009
      fctp = dlsym (p, "addr");
Packit 6c4009
      if (fctp == NULL)
Packit 6c4009
	{
Packit 6c4009
	  puts ("failed to get address of \"addr\" in \"nodelmod3.so\"");
Packit 6c4009
	  result = 1;
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  int *varp = fctp ();
Packit 6c4009
Packit 6c4009
	  *varp = -1;
Packit 6c4009
Packit 6c4009
	  /* Now close the object.  */
Packit 6c4009
	  fini_ran = 0;
Packit 6c4009
	  if (dlclose (p) != 0)
Packit 6c4009
	    {
Packit 6c4009
	      puts ("failed to close \"nodelmod3.so\"");
Packit 6c4009
	      result = 1;
Packit 6c4009
	    }
Packit 6c4009
	  else if (! sigsetjmp (jmpbuf, 1))
Packit 6c4009
	    {
Packit 6c4009
	      /* Access the variable again.  */
Packit 6c4009
	      if (*varp != -1)
Packit 6c4009
		{
Packit 6c4009
		  puts ("\"var_in_mod4\" value not correct");
Packit 6c4009
		  result = 1;
Packit 6c4009
		}
Packit 6c4009
	      else if (fini_ran != 0)
Packit 6c4009
		{
Packit 6c4009
		  puts ("destructor of \"nodelmod4.so\" ran");
Packit 6c4009
		  result = 1;
Packit 6c4009
		}
Packit 6c4009
	      else
Packit 6c4009
		puts ("-z nodelete in dependency succeeded");
Packit 6c4009
	    }
Packit 6c4009
	  else
Packit 6c4009
	    {
Packit 6c4009
	      /* We caught an segmentation fault.  */
Packit 6c4009
	      puts ("\"nodelmod4.so\" got deleted");
Packit 6c4009
	      result = 1;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#include <support/test-driver.c>