This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc 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]

{make,set,swap}context broken on powerpc32


Hi!

The following testcase crashes on powerpc32 with CVS glibc (but glibc 2.5 as
well) and 2.6.18 kernel, when glibc is configured for 2.6.0+ kernel
(i.e. __ASSUME_SWAPCONTEXT_SYSCALL).  The problem is in clobberring r2 (== TLS)
register.
One thing is that swapcontext syscall restores r2 (for 32-bit processes)
from the saved registers.  As it is used by swapcontext and setcontext
syscalls, that in itself is a problem - can't you getcontext in one
thread and setcontext in another one?
Additionally, it seems makecontext call doesn't preserve any registers
that getcontext saved, as it overwrites uc_mcontext.uc_regs pointer
(on this testcase getcontext created context has
uc_mcontext.uc_regs pointing to uc_reg_space + 12 while makecontext
resets that to uc_mcontext.uc_regs).
The combination of those two problems causes the failure of this testcase,
but I think for both the problems we can construct a testcase separately.

For makecontext, I wonder if we just shouldn't memmove the register values
around if we change the pointer.  For the swapcontext/setcontext, there
is a bigger problem, either we change the kernel not to restore r2,
or we could e.g. compare the saved r2 with the current r2, if equal to what
we do ATM, otherwise copy the whole ucontext_t into a temporary, change
r2 in it and only then do the swapcontext syscall.

#define _XOPEN_SOURCE 600
#include <stdlib.h>
#include <stdio.h>
#include <ucontext.h>

ucontext_t oucp, ucp;
char st1[8192];
__thread int thr;

void
cf (int i)
{
  if (i != 78 || thr != 94)
    {
      printf ("i %d thr %d\n", i, thr);
      exit (1);
    }
  exit (0);
}

int
main (void)
{
  if (getcontext (&oucp) != 0 || getcontext (&ucp) != 0)
    {
      puts ("getcontext failed");
      return 1;
    }
  thr = 94;
  ucp.uc_link = &oucp;
  ucp.uc_stack.ss_sp = st1;
  ucp.uc_stack.ss_size = sizeof st1;
  makecontext (&ucp, (void (*) ()) cf, 1, 78);
  if (setcontext (&ucp) != 0)
    {
      puts ("setcontext failed");
      return 1;
    }
  return 0;
}

	Jakub


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