[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#230050: getcontext doesn't report alternate stack correctly



Package: libc6
Version: 2.2.5-11.5

This is a followup to Debian bug 136249.  Herbert Xu suggested that I
refile the getcontext part of that bug against libc6.

The problem is that getcontext does not fill in the correct
information when it is executed on the alternate stack.  A sample
program illustrating the problem is shown below.

I am using this kernel:

$ uname -a
Linux penguin 2.4.18-bf2.4 #1 Son Apr 14 09:53:28 CEST 2002 i686 unknown unknown GNU/Linux

When I compile and run the following program, it outputs this:

handler context's    : stack_base=(nil) stack_size=0 flags=0
it should be         : stack_base=0x80499c0 stack_size=2000 flags=1

The program works correctly on Solaris 8, i.e. the "handler's context"
line contains the same numbers as the "it should be" line.


#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
#include <unistd.h>
#include <string.h>

stack_t st;

unsigned
use_up_all_the_stack (char const *p)
{
  char array[2048];
  array[0] = 1;
  return *p + use_up_all_the_stack (array);
}

/* Storage for the alternate signal stack.  */
static union
{
  char buffer[SIGSTKSZ];

  /* These other members are for proper alignment.  There's no
     standard way to guarantee stack alignment, but this seems enough
     in practice.  */
  long double ld;
  long l;
  void *p;
} alternate_signal_stack;

void
segv_handler (int signo, siginfo_t *info, void *context)
{
  ucontext_t handler_context;
  char buf[1024];

  if (getcontext (&handler_context) != 0)
    abort ();

  sprintf (buf,
	   ("handler context's    : stack_base=%p stack_size=%lx flags=%d\n"
	    "it should be         : stack_base=%p stack_size=%lx flags=%d\n"),
	   handler_context.uc_stack.ss_sp,
	   (unsigned long) handler_context.uc_stack.ss_size,
	   handler_context.uc_stack.ss_flags,
	   st.ss_sp, (unsigned long) st.ss_size, SS_ONSTACK);
  write (STDERR_FILENO, buf, strlen (buf));

  _exit (0);
}

int
main (void)
{
  struct sigaction act;
  int r;
  st.ss_flags = 0;
  st.ss_sp = alternate_signal_stack.buffer;
  st.ss_size = sizeof alternate_signal_stack.buffer;
  r = sigaltstack (&st, 0);
  if (r != 0)
    abort ();
  act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
  act.sa_sigaction = segv_handler;
  if (sigemptyset (&act.sa_mask) != 0)
    abort ();
  if (sigaction (SIGSEGV, &act, 0) != 0)
    abort ();
  return use_up_all_the_stack ("");
}



Reply to: