Opened 9 years ago

Closed 9 years ago

#9437 closed Patches (fixed)

[PATCH] Unable to catch exceptions on iOS and Windows Phone 8

Reported by: Evgeny Shapovalov <johncapfull@…> Owned by: olli
Milestone: To Be Determined Component: context
Version: Boost Development Trunk Severity: Problem
Keywords: Cc:

Description

Abstract

  1. jump_arm_aapcs_pe_armasm.asm fails to compile using armasm from MSVS 2012 with error A2193: "This instruction generates unpredictable behavior";
  2. Throwing an exception inside custom context leads to crash with "Unhandled exception ..." error despite of try/catch block under Windows Phone 8;
  3. Same as above, but not stable to reproduce for iOS.

Attached patch for current boost trunk will fix all issues descrbed above.

Rationale

  1. Armasm assembling fails on following instruction
stmia   a1, {r4-r11,sp-lr}

This occurs because

"In the Microsoft ARM assembler, THUMB indicates that a CODE section contains Thumb code, and is the default for CODE sections" http:msdn.microsoft.com/en-us/library/vstudio/hh916385.aspx

AFAIK in THUMB mode stmia/ldmia cannot be done for SP and PC.

Fix: To be able to compile in both ARM and THUMB mode, SP register can be saved separately as following:

    stmia   a1, {r4-r11,lr}           ; save V1-V8,LR
    str     sp, [a1,#0x24]            ; save SP separately

The same is done for ldmia. Note that I reordered SP and LR to avoid saving LR separately.

  1. In Windows Phohe 8 throwing an exception leads to crash in all cases. It seems that Windows use current StackBase and StackLimit pointers from TIB to locate exception handler for thread. The same should occur for x86_64 under Win32, but it is already handled inside jump_x86_64_ms_pe_masm.asm by saving and loading stack base/limit.

Fix: Similar to x86_64. Get TIB inside jump_fcontext and save/load StackBase and StackLimit for current thread. Do not need to modify fcontext structure because StackLimit can be easily calculated from stack base and size.

  1. Throwing an exception in iOS crashes application when it is done after switching context back, leaving enclosed try/catch block, and jumping into custom context again. It happens because "ARM uses setjump/longjump based C++ exceptions" in clang.

And, "With SJLJ based exceptions any function that has a catch clause or needs to do any clean up when an exception propagates through it, needs to call _Unwind_SjLj_Register() at the start of the function and _Unwind_SjLj_Unregister() at the end." https:www.opensource.apple.com/source/libunwind/libunwind-35.3/src/Unwind-sjlj.c http:llvm.org/docs/ExceptionHandling.html#setjmp-longjmp-exception-handling

Fix: To locate current exception handler list, libunwind stores top exception handler using pthread_setspecific(PTK_LIBC_DYLD_Unwind_SjLj_Key). So unwind key should be saved/restored at every context switch. Which is done inside jump_arm_aapcs_macho_gas.S. This has required to add additional field inside fcontext_t for ARM under iOS.

Sample code (how to reproduce for both WP8 and iOS)

    void routine(intptr_t) {
        try {
            ctx::jump_fcontext(fc, &fcm, 0);
	    throw std::exception(); // Unhandled exception crash here 
        } catch(std::exception) {
            std::cout << "exception caught" << std::endl;
        }
        ctx::jump_fcontext(fc, &fcm, 0);
    }
    
    int main() {
    	// allocate context here...
    
        try {
            ctx::jump_fcontext(&fcm, fc, 0);
        } catch (...) {
        }
        ctx::jump_fcontext(&fcm, fc, 0);
    }

PS. Sorry for links, I was unable to pass anti-spam check without changing them.

Attachments (2)

boost-trunk-context-throw-wp8-ios.patch (10.1 KB ) - added by Evgeny Shapovalov <johncapfull@…> 9 years ago.
patch with fixes
how-to-reproduce.cpp (2.2 KB ) - added by Evgeny Shapovalov <johncapfull@…> 9 years ago.
Full source code to reproduce described issues

Download all attachments as: .zip

Change History (8)

by Evgeny Shapovalov <johncapfull@…>, 9 years ago

patch with fixes

by Evgeny Shapovalov <johncapfull@…>, 9 years ago

Attachment: how-to-reproduce.cpp added

Full source code to reproduce described issues

comment:1 by olli, 9 years ago

Resolution: invalid
Status: newclosed

1.) ABI used by IOS is different from AAPCS + IOS is not supported (yet). 2.) Windows on ARM is not supported

comment:2 by Evgeny Shapovalov <johncapfull@…>, 9 years ago

ABI used by IOS is different from AAPCS

Exactly

IOS is not supported

Is there any blockers to add support for iOS and Windows on ARM? There are already some ARM stubs in trunk for MACHO and MASM.

jump_arm_aapcs_pe_armasm.asm
jump_arm_aapcs_macho_gas.S

The only useful platforms for them are WP and iOS. AFAIK.

in reply to:  2 comment:3 by olli, 9 years ago

Replying to Evgeny Shapovalov <johncapfull@…>:

IOS is not supported

Is there any blockers to add support for iOS and Windows on ARM? There are already some ARM stubs in trunk for MACHO and MASM.

I'm working on iOS port but I've not enough time.

The Windows CE/ARM port was reported to work while throwing/catching exceptions will not work. To enable SEH on ARM it requires PDATA structure for the functions in the asm-files in order to set up the exception handlers. MASM has had a special macro for this purpose. The assembler-tool armasm (used for Windows CE/ARM) doesn't. I've to figure out how to setup the PDATA structure (http://msdn.microsoft.com/en-us/library/aa448751.aspx).

comment:4 by Evgeny Shapovalov <johncapfull@…>, 9 years ago

To enable SEH on ARM it requires PDATA structure for the functions in the asm-files in order to set up the exception handlers

PDATA in non-throwing function is needed only for unwinding. Since exception cannot be thrown out of context function, there is no need to use pdata in asm.

All throwing functions will already have compiler-generated PDATA with associated exception handlers. The reason for non-working exceptions is invalid TEB state in context functions.

See description and patch attached as proposed way to fix this.

comment:5 by olli, 9 years ago

Resolution: invalid
Status: closedreopened

comment:6 by olli, 9 years ago

Resolution: fixed
Status: reopenedclosed
Note: See TracTickets for help on using tickets.