]> granicus.if.org Git - strace/commitdiff
ARM: fix sigreturn decoding
authorDenys Vlasenko <dvlasenk@redhat.com>
Wed, 17 Jul 2013 15:26:56 +0000 (17:26 +0200)
committerDenys Vlasenko <dvlasenk@redhat.com>
Wed, 17 Jul 2013 15:26:56 +0000 (17:26 +0200)
Decoding of test/sigreturn testcase:
Was:
sigreturn() (mask [QUIT TRAP ABRT BUS SEGV USR2 PIPE STKFLT STOP XCPU VTALRM PROF WINCH IO PWR RTMIN]) = 0
Now:
sigreturn() (mask [CHLD RT_1 RT_3 RT_31 RT_32]) = 0

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
signal.c

index e433306f9fd7b1ba4c2c68045ddecb2c7a17fb9a..4e35274cc925f94e513e618ebd7368a908f7a048 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -84,51 +84,6 @@ struct sigcontext {
 };
 # endif /* M68K */
 #endif /* !HAVE_ASM_SIGCONTEXT_H */
-#if defined(I386) || defined(X86_64)
-struct i386_sigcontext_struct {
-       uint16_t gs, __gsh;
-       uint16_t fs, __fsh;
-       uint16_t es, __esh;
-       uint16_t ds, __dsh;
-       uint32_t edi;
-       uint32_t esi;
-       uint32_t ebp;
-       uint32_t esp;
-       uint32_t ebx;
-       uint32_t edx;
-       uint32_t ecx;
-       uint32_t eax;
-       uint32_t trapno;
-       uint32_t err;
-       uint32_t eip;
-       uint16_t cs, __csh;
-       uint32_t eflags;
-       uint32_t esp_at_signal;
-       uint16_t ss, __ssh;
-       uint32_t i387;
-       uint32_t oldmask;
-       uint32_t cr2;
-};
-struct i386_fpstate {
-       uint32_t cw;
-       uint32_t sw;
-       uint32_t tag;
-       uint32_t ipoff;
-       uint32_t cssel;
-       uint32_t dataoff;
-       uint32_t datasel;
-       uint8_t  st[8][10]; /* 8*10 bytes: FP regs */
-       uint16_t status;
-       uint16_t magic;
-       uint32_t fxsr_env[6];
-       uint32_t mxcsr;
-       uint32_t reserved;
-       uint8_t  stx[8][16]; /* 8*16 bytes: FP regs, each padded to 16 bytes */
-       uint8_t  xmm[8][16]; /* 8 XMM regs */
-       uint32_t padding1[44];
-       uint32_t padding2[12]; /* union with struct _fpx_sw_bytes */
-};
-#endif
 
 #ifndef NSIG
 # warning: NSIG is not defined, using 32
@@ -829,12 +784,54 @@ sys_sigreturn(struct tcb *tcp)
 {
 #if defined(ARM)
        if (entering(tcp)) {
-               struct sigcontext_struct sc;
+               struct arm_sigcontext {
+                       unsigned long trap_no;
+                       unsigned long error_code;
+                       unsigned long oldmask;
+                       unsigned long arm_r0;
+                       unsigned long arm_r1;
+                       unsigned long arm_r2;
+                       unsigned long arm_r3;
+                       unsigned long arm_r4;
+                       unsigned long arm_r5;
+                       unsigned long arm_r6;
+                       unsigned long arm_r7;
+                       unsigned long arm_r8;
+                       unsigned long arm_r9;
+                       unsigned long arm_r10;
+                       unsigned long arm_fp;
+                       unsigned long arm_ip;
+                       unsigned long arm_sp;
+                       unsigned long arm_lr;
+                       unsigned long arm_pc;
+                       unsigned long arm_cpsr;
+                       unsigned long fault_address;
+               };
+               struct arm_ucontext {
+                       unsigned long uc_flags;
+                       unsigned long uc_link;  /* struct ucontext* */
+                       /* The next three members comprise stack_t struct: */
+                       unsigned long ss_sp;    /* void*   */
+                       unsigned long ss_flags; /* int     */
+                       unsigned long ss_size;  /* size_t  */
+                       struct arm_sigcontext sc;
+                       /* These two members are sigset_t: */
+                       unsigned long uc_sigmask[2];
+                       /* more fields follow, which we aren't interested in */
+               };
+               struct arm_ucontext uc;
                sigset_t sigm;
-               if (umove(tcp, arm_regs.ARM_sp, &sc) < 0)
+               if (umove(tcp, arm_regs.ARM_sp, &uc) < 0)
                        return 0;
-               long_to_sigset(sc.oldmask, &sigm);
-               tprints(sprintsigmask(") (mask ", &sigm, 0));
+               /* Kernel fills out uc.sc.oldmask too when it sets up signal stack,
+                * but for sigmask restore, sigreturn syscall uses uc.uc_sigmask instead.
+                *  long_to_sigset(uc.sc.oldmask, &sigm);
+                *  tprints(sprintsigmask(") (mask ", &sigm, 0));
+                */
+               sigemptyset(&sigm);
+               ((uint32_t*)&sigm)[0] = uc.uc_sigmask[0];
+               ((uint32_t*)&sigm)[1] = uc.uc_sigmask[1];
+               tprints(sprintsigmask(") (mask ", &sigm, /*rt:*/ 1));
        }
 #elif defined(S390) || defined(S390X)
        if (entering(tcp)) {
@@ -852,6 +849,49 @@ sys_sigreturn(struct tcb *tcp)
                return 0;
 # endif
        if (entering(tcp)) {
+               struct i386_sigcontext_struct {
+                       uint16_t gs, __gsh;
+                       uint16_t fs, __fsh;
+                       uint16_t es, __esh;
+                       uint16_t ds, __dsh;
+                       uint32_t edi;
+                       uint32_t esi;
+                       uint32_t ebp;
+                       uint32_t esp;
+                       uint32_t ebx;
+                       uint32_t edx;
+                       uint32_t ecx;
+                       uint32_t eax;
+                       uint32_t trapno;
+                       uint32_t err;
+                       uint32_t eip;
+                       uint16_t cs, __csh;
+                       uint32_t eflags;
+                       uint32_t esp_at_signal;
+                       uint16_t ss, __ssh;
+                       uint32_t i387;
+                       uint32_t oldmask;
+                       uint32_t cr2;
+               };
+               struct i386_fpstate {
+                       uint32_t cw;
+                       uint32_t sw;
+                       uint32_t tag;
+                       uint32_t ipoff;
+                       uint32_t cssel;
+                       uint32_t dataoff;
+                       uint32_t datasel;
+                       uint8_t  st[8][10]; /* 8*10 bytes: FP regs */
+                       uint16_t status;
+                       uint16_t magic;
+                       uint32_t fxsr_env[6];
+                       uint32_t mxcsr;
+                       uint32_t reserved;
+                       uint8_t  stx[8][16]; /* 8*16 bytes: FP regs, each padded to 16 bytes */
+                       uint8_t  xmm[8][16]; /* 8 XMM regs */
+                       uint32_t padding1[44];
+                       uint32_t padding2[12]; /* union with struct _fpx_sw_bytes */
+               };
                struct {
                        struct i386_sigcontext_struct sc;
                        struct i386_fpstate fp;