> The result has been bootstrapped by Eric (thanks for this and debugging > why a first version caused some regressions on Solaris 8) and myself on > Solaris 8, 9, 10 and 11, and I've performed quite a bit of software > archaeology (i.e. stared at old libc.so.1 and libthread.so.1 patches) to > make sure noting got missed in the process.
All EH-related tests fail with a recent upgrade on Solaris 10. Interestingly, the old implementation keeps working with the upgrade. It seems that the __sighndlr case has been over-simplified: /* Look for the __sighndlr pattern. */ else if ( *(unsigned int *)(pc-(4*5)) == sighndlr_pattern[0] && *(unsigned int *)(pc-(4*4)) == sighndlr_pattern[1] && *(unsigned int *)(pc-(4*3)) == sighndlr_pattern[2] && *(unsigned int *)(pc-(4*2)) == sighndlr_pattern[3] && *(unsigned int *)(pc-(4*1)) == sighndlr_pattern[4] && *(unsigned int *)(pc-(4*0)) == sighndlr_pattern[5] && *(unsigned int *)(pc+(4*1)) == sighndlr_pattern[6] ) { /* We have observed different calling frames among different versions of the operating system, so that we need to discriminate using the upper frame. We look for the return address of the caller frame (there is an offset of 15 words between the frame address and the place where this return address is stored) in order to do some more pattern matching. */ unsigned int cuh_pattern = *(unsigned int *)(*(unsigned int *)(this_cfa + 15*4) - 4); if (cuh_pattern == 0xd407a04c) { /* This matches the call_user_handler pattern for Solaris 10. There are 2 cases so we look for the return address of the caller's caller frame in order to do more pattern matching. */ unsigned int sah_pattern = *(unsigned int *)(*(unsigned int *)(this_cfa + 96 + 15*4) - 4); if (sah_pattern == 0x92100019) /* This is the same setup as for Solaris 9, see below. */ regs_off = 96 + 96 + 96 + 160; else /* We need to move up three frames (the kernel frame, the call_user_handler frame, the __sighndlr frame). Two of them have the minimum stack frame size (kernel and __sighndlr frames) of 96 bytes, and there is another with a stack frame of 160 bytes (the call_user_handler frame). The ucontext_t structure is after this offset. */ regs_off = 96 + 96 + 160; } else if (cuh_pattern == 0x9410001a || cuh_pattern == 0x9410001b) /* This matches the call_user_handler pattern for Solaris 9 and for Solaris 8 running inside Solaris Containers respectively. We need to move up four frames (the kernel frame, the signal frame, the call_user_handler frame, the __sighndlr frame). Three of them have the minimum stack frame size (kernel, signal, and __sighndlr frames) of 96 bytes, and there is another with a stack frame of 160 bytes (the call_user_handler frame). The ucontext_t structure is after this offset. */ regs_off = 96 + 96 + 96 + 160; else /* We need to move up three frames (the kernel frame, the sigacthandler frame, and the __sighndlr frame). Two of them have the minimum stack frame size (kernel and __sighndlr frames) of 96 bytes, and there is another with a stack frame of 216 bytes (the sigacthandler frame). The ucontext_t structure is after this offset. */ regs_off = 96 + 96 + 216; } to if(/* Solaris 8+ - multi-threaded ---------------------------- <__sighndlr>: save %sp, -96, %sp <__sighndlr+4>: mov %i0, %o0 <__sighndlr+8>: mov %i1, %o1 <__sighndlr+12>: call %i3 <__sighndlr+16>: mov %i2, %o2 <__sighndlr+20>: ret <--- PC <__sighndlr+24>: restore */ pc[-5] == 0x9de3bfa0 && pc[-4] == 0x90100018 && pc[-3] == 0x92100019 && pc[-2] == 0x9fc6c000 && pc[-1] == 0x9410001a && pc[ 0] == 0x81c7e008 && pc[ 1] == 0x81e80000) { if (/* Solaris 8 /usr/lib/libthread.so.1 ---------------------------------- <sigacthandler+1796>: mov %i0, %o0 */ savpc[-1] == 0x90100018) { /* We need to move up two frames: <signal handler> <-- context->cfa __sighndlr sigacthandler <kernel> */ *nframes = 2; } else /* Solaris 8 /usr/lib/lwp/libthread.so.1, Solaris 9+ -------------------------------------------------- */ { /* We need to move up three frames: <signal handler> <-- context->cfa __sighndlr call_user_handler sigacthandler <kernel> */ *nframes = 3; } return 1; } In particular, the old fallback case (2 frames) has been changed (to 3 frames), The upgrade seems to have reverted to 2 frames because of a sibling call. -- Eric Botcazou