2

バックグラウンド サービスからスクリーンショットをキャプチャしたい。ios6 と ios7 では正常に動作しますが、ios7 retina ではクラッシュします。

これは私のコードです

{

IOMobileFramebufferConnection connect;
        kern_return_t result;
        m_screenSurfaceRef = NULL;

        io_service_t framebufferService = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleH1CLCD"));
        if(!framebufferService)
            framebufferService = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleM2CLCD"));
        if(!framebufferService)
            framebufferService = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleCLCD"));

#pragma unused(result)
        result = IOMobileFramebufferOpen(framebufferService, mach_task_self(), 0, &connect);

        result = IOMobileFramebufferGetLayerDefaultSurface(connect, 0, &m_screenSurfaceRef);

}

Retina IOMobileFramebufferGetLayerDefaultSurface(connect, 0, &m_screenSurfaceRef) で実行するとクラッシュしました。

クラッシュ情報:

スレッド #1: tid = 0x1dfe9, 0x000000018ea2c270 IOMobileFramebuffer IOMobileFramebufferGetLayerDefaultSurface + 4, queue = 'com.apple.main-thread, stop reason = EXC_BAD_ACCESS (code=1, address=0x5e06dc28) frame #0: 0x000000018ea2c270 IOMobileFramebufferIOMobileFramebufferGetLayerDefaultSurface + 4

4

1 に答える 1

4

これは、IOMobileFramebuffer.h のリバース エンジニアリングに伴う 64 ビットの問題です。のプロトタイプ

IOMobileFramebufferReturn IOMobileFramebufferGetLayerDefaultSurface(IOMobileFramebufferConnection connection, int surface, CoreSurfaceBufferRef *ptr);

... IOMobileFramebufferConnection の typedef が正しくないため、正しくありません。IOMobileFramebufferGetLayerDefaultSurface の逆アセンブルと部分的な逆コンパイルを見ると、次のようになります。

IOMobileFramebufferReturn IOMobileFramebufferGetLayerDefaultSurface(Connection *connection, int surface, IOSurfaceRef *ptr)
{
    if(connection) {                       // 0x18f95026c:  cbz    x0, 0x18f95027c
            long tmp = connection->unk2;   // 0x18f950270:  ldr    x3, [x0, #552] // <== Crash!
            if(tmp) {                      // 0x18f950274:  cbz    x3, 0x18f95027c
                    goto tmp;              // 0x18f950278:  br     x3
            }
   }
   //0x18f95027c:  movn   w0, #8191, lsl #16
   //0x18f950280:  movk   w0, #706
   //0x18f950284:  ret    lr

}

最初のパラメーターが逆参照されていることがわかります。つまり、ポインターのサイズにする必要があります。逆のヘッダーでは、IOMobileFramebufferConnection は io_connect_t に typedef され、これは io_object_t に typedef されます。Int はたまたま 32 ビットではポインター サイズですが、64 ビット未満ではないため、ポインターの最初の 32 ビットをこの関数に送信することになり、明らかにクラッシュします。

私の解決策は、次のように void* に typedef を再設定することでした。

typedef void *IOMobileFramebufferConnection;

完全に修正されたヘッダーはhttps://gist.github.com/nevyn/9486278にあります。

于 2014-03-11T14:05:20.367 に答える