【问题标题】:IOMobileFramebufferGetLayerDefaultSurface does not work on ios7 retinaIOMobileFramebufferGetLayerDefaultSurface 在 ios7 视网膜上不起作用
【发布时间】:2014-02-19 03:53:43
【问题描述】:

我想从后台服务捕获屏幕截图。在 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);

}

在retina IOMobileFramebufferGetLayerDefaultSurface(connect, 0, &m_screenSurfaceRef) 上运行时崩溃。

崩溃信息:

线程#1:tid = 0x1dfe9, 0x000000018ea2c270 IOMobileFramebufferIOMobileFramebufferGetLayerDefaultSurface + 4, queue = 'com.apple.main-thread, stop reason = EXC_BAD_ACCESS (code=1, address=0x5e06dc28) frame #0: 0x000000018ea2c270 IOMobileFramebufferIOMobileFramebufferGetLayerDefaultSurface + 4

【问题讨论】:

  • 似乎在 64 位 + 视网膜上崩溃,而不仅仅是视网膜。你看到的一样吗?
  • @nevyn 谢谢,我构建了 32 位应用,效果很好。
  • 这是一个不幸但也许可以接受的解决方法。但是,我在下面提供的答案要好得多。请问你愿意接受吗?

标签: ios7 frameworks screen-capture retina


【解决方案1】:

这是 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 到 io_connect_t,这是 typedef'd 到 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找到。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-22
    • 1970-01-01
    • 2013-10-02
    相关资源
    最近更新 更多