Hi,
I am trying to use the sigsetjmp/siglongjmp mechanism on an ARM qnx660 target.
I am getting strange errors, where the siglongjmp is trying to return to corrupted addresses.
I disassembled the sigsetjmp/siglongjmp implementation and believe that it is broken. My analysis of the implementation
follows:
LOAD:00020288 sigsetjmp
[0] LOAD:00020288 STMFD SP!, {R4,LR}
LOAD:0002028C MOV R4, R0
LOAD:00020290 BL j___sigjmp_prolog
LOAD:00020294 MOV R0, R4 ; env
LOAD:00020298 BL _setjmp
[1] LOAD:0002029C LDMFD SP!, {R4,PC}
LOAD:00032808 _setjmp ; CODE XREF: j_procmgr_event_notify_add+8j
LOAD:00032808 ; j__FXp_addx+8j ...
[2] LOAD:00032808 STMIA R0, {R4-R11,SP,LR}
LOAD:0003280C STMFD SP!, {R0,LR}
LOAD:00032810 BL sub_4B5A8
LOAD:00032814 LDMFD SP!, {R1,LR}
LOAD:00032818 TEQ R0, #0
LOAD:0003281C STRNE R0, [R1,#0x24]
LOAD:00032820 MOV R0, #0
LOAD:00032824 RET
LOAD:0004B5A8 sub_4B5A8 ; CODE XREF: _setjmp+8p
LOAD:0004B5A8 LDR R2, =(dword_8F978 - 0x4B5B8)
LOAD:0004B5AC LDR R3, =(_GLOBAL_OFFSET_TABLE_ - 0x4B5BC)
LOAD:0004B5B0 ADD R2, PC, R2 ; dword_8F978
LOAD:0004B5B4 ADD R3, PC, R3 ; _GLOBAL_OFFSET_TABLE_
LOAD:0004B5B8 LDR R2, [R2,#(dword_8F994 - 0x8F978)]
LOAD:0004B5BC CMP R2, #0
LOAD:0004B5C0 BLT loc_4B5CC
LOAD:0004B5C4 MOV R0, #0
[3] LOAD:0004B5C8 BX LR
LOAD:0004B5CC ; ---------------------------------------------------------------------------
LOAD:0004B5CC
LOAD:0004B5CC loc_4B5CC ; CODE XREF: sub_4B5A8+18j
LOAD:0004B5CC LDR R2, =(off_8E0B8 - 0x8D000)
LOAD:0004B5D0 LDR R3, [R3,R2] ; off_8E0B8
LOAD:0004B5D4 LDR R3, [R3]
LOAD:0004B5D8 LDR R3, [R3]
LOAD:0004B5DC LDR R3, [R3,#0x38]
LOAD:0004B5E0 LDR R3, [R3,#4]
LOAD:0004B5E4 LDR R2, [R3,#4]
LOAD:0004B5E8 SUB R1, R2, #1
LOAD:0004B5EC STR R1, [R0]
LOAD:0004B5F0 LDR R0, [R3,R2,LSL#3]
LOAD:0004B5F4 BX LR
LOAD:0004B5F4 ; End of function sub_4B5A8
At [0] the original R4 and LR are saved on the stack. These values are used both to return from the sigsetjmp function
at [1] and as the
storage for the R4 and longjmp target PC as we'll see in a minute.
sigsetjmp then calls __sigjmp_prolog (which just saves sigmask in the env) and then calls _setjmp.
At [2] _setjmp saves register R4-R11, the SP (which points to our saved R4 and LR) and the current LR (which is [1])
into the env (R0).
It then calls sub_4b5a8, which does nothing except set R0 to 0 and return at [3].
_setjmp then checks if R0 is non-zero, but this check fails so the store is skipped. Then R0 is set to 0 and we return
to sigsetjmp at [1].
sigsetjmp now pops the R4 and LR values from the stack into R4 and PC, thereby returning to the sigsetjmp callsite.
_BUT_ this also releases
the two stack slots that are pointed to by the SP saved in the env, which are used by...
View Full Message