2

我想从后台服务捕获屏幕截图。它在 ios6 和 ios7 下工作正常,但在 ios7 视网膜下崩溃。

这是我的代码

{

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);

}

在视网膜上运行时 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是typedef'd to io_connect_t,也就是typedef'd to io_object_t,即mach_port_t,即__darwin_mach_port_t,即__darwin_natural_t,即unsigned int!Int 恰好在 32 位上是指针大小的,但不在 64 位以下,所以我们最终只是将指针的前 32 位发送到这个函数中,这显然会崩溃。

我的解决方案是将 typedef 重新设置为 void* ,如下所示:

typedef void *IOMobileFramebufferConnection;

完整的更正标题可以在https://gist.github.com/nevyn/9486278找到。

于 2014-03-11T14:05:20.367 回答