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]

Re: {make,set,swap}context broken on powerpc32


On Wed, Dec 13, 2006 at 01:43:31PM +1100, Paul Mackerras wrote:
> I find it hard to see how that could be happening, because the kernel
> code explicitly preserves r2.  In arch/powerpc/kernel/signal_32.c,
> sys_swapcontext calls do_setcontext with `sig' == 0, which calls
> restore_user_regs with the same `sig' argument, which then does this:
> 
> 	/*
> 	 * restore general registers but not including MSR or SOFTE. Also
> 	 * take care of keeping r2 (TLS) intact if not a signal
> 	 */
> 	if (!sig)
> 		save_r2 = (unsigned int)regs->gpr[2];
> 	err = restore_general_regs(regs, sr);
> 	err |= __get_user(msr, &sr->mc_gregs[PT_MSR]);
> 	if (!sig)
> 		regs->gpr[2] = (unsigned long) save_r2;
> 
> The 64-bit sys_swapcontext (in signal_64.c) similarly avoids modifying
> r13, using a slightly different mechanism.
> 
> That's assuming that glibc is in fact using the sys_swapcontext system
> call.  If it's using sys_rt_sigreturn instead, then yes that will
> restore r2 from the saved registers.
> 
> Could you strace your test program and see whether it is using
> sys_swapcontext or sys_rt_sigreturn?

It uses sys_swapcontext to fill it up (i.e. in getcontext calls)
and apparently sys_rt_sigreturn in setcontext (sorry I haven't noticed that),
will look why:

strace /tmp/e2
execve("/tmp/e2", ["/tmp/e2"], [/* 26 vars */]) = 0
brk(0)                                  = 0x10020000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=135453, ...}) = 0
mmap(NULL, 135453, PROT_READ, MAP_PRIVATE, 3, 0) = 0xf7fc0000
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\24\0\0\0\1\17H\340"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1793784, ...}) = 0
mmap(0xf470000, 1520028, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xf470000
mmap(0xf5d0000, 131072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x160000) = 0xf5d0000
close(3)                                = 0
mprotect(0xf5d0000, 65536, PROT_READ)   = 0
mprotect(0xffe0000, 65536, PROT_READ)   = 0
munmap(0xf7fc0000, 135453)              = 0
swapcontext(0x1001319c, 0)              = 0
swapcontext(0x10010cfc, 0)              = 0
rt_sigreturn(0x10010cfc)                = 78
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++

uc_mcontext.uc_regs pointer the swapcontext call creates is not
aligned though:
p ucp
$1 = {uc_flags = 0, uc_link = 0x0, uc_stack = {ss_sp = 0x0, ss_flags = 0, ss_size = 0}, uc_pad = {0, 0, 0, 0, 0, 0, 0},
  uc_mcontext = {regs = 0x10010dbc, uc_regs = 0x10010dbc}, uc_sigmask = {__val = {0 <repeats 32 times>}},
  uc_reg_space = ... }

and makecontext realigns it:

$2 = {uc_flags = 0, uc_link = 0x1001319c, uc_stack = {ss_sp = 0x1001119c, ss_flags = 0, ss_size = 8192}, uc_pad = {0, 0, 0, 0, 0, 0, 0},
  uc_mcontext = {regs = 0x10010db0, uc_regs = 0x10010db0}, uc_sigmask = {__val = {0 <repeats 32 times>}},
  uc_reg_space = ... }

thus loosing content of all registers from getcontext except those which it
explicitly overrode.

	Jakub


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