xcode 如何建立一个既适用于大苏尔和 Monterey 的DEXT

de90aj5v  于 2023-05-19  发布在  其他
关注(0)|答案(2)|浏览(166)

在我们的DriverKit扩展开发中,我们面临着一个难题。我们想建立和调试 Monterey 。这意味着我们需要使用Xcode 13。我们也需要支持大苏尔。不幸的是,我们还不能用Xcode 13构建一个在Big Sur上工作的DEXT。
我们将DRIVERKIT_DEPLOYMENT_TARGET设置为19(可能的最小值)。DEXT在Big Sur上加载正常,但每当用户客户端连接时,DEXT进程就会因Assert失败而崩溃,如下所示:

Crashed Thread:        0  Dispatch queue: Root

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Application Specific Information:
dyld2 mode
abort() called

Thread 0 Crashed:: Dispatch queue: Root
0   libsystem_kernel.dylib          0x0000000104bfb3a4 __pthread_kill + 8
1   libsystem_pthread.dylib         0x0000000104de6844 pthread_kill + 272
2   libsystem_c.dylib               0x0000000104b98f24 abort + 124
3   com.apple.DriverKit             0x00000001048b12b4 __assert_rtn + 92
4   com.apple.DriverKit             0x00000001048b151c OSMetaClassBase::QueueForObject(unsigned long long) (.cold.2) + 44
5   com.apple.DriverKit             0x0000000104893068 OSMetaClassBase::QueueForObject(unsigned long long) + 176
6   com.apple.DriverKit             0x0000000104893780 OSMetaClassBase::Invoke(IORPC) + 412
7   com.apple.DriverKit             0x000000010489425c Server(void*, mach_msg_header_t*, mach_msg_header_t*) + 512
8   com.apple.DriverKit             0x00000001048959c8 uiomachchannel(void*, dispatch_mach_reason_t, dispatch_mach_msg_s*, int) + 156
9   libdispatch.dylib               0x0000000104a43b90 _dispatch_mach_msg_invoke + 476
10  libdispatch.dylib               0x0000000104a313ec _dispatch_lane_serial_drain + 308
11  libdispatch.dylib               0x0000000104a448f4 _dispatch_mach_invoke + 464
12  libdispatch.dylib               0x0000000104a313ec _dispatch_lane_serial_drain + 308
13  libdispatch.dylib               0x0000000104a32154 _dispatch_lane_invoke + 456
14  libdispatch.dylib               0x0000000104a33408 _dispatch_workloop_invoke + 1680
15  libdispatch.dylib               0x0000000104a3c9f0 _dispatch_workloop_worker_thread + 764
16  libsystem_pthread.dylib         0x0000000104de75e0 _pthread_wqthread + 276
17  libsystem_pthread.dylib         0x0000000104dee7fc start_wqthread + 8

我在苹果开发者论坛上看到过类似的问题,建议似乎是“升级到 Monterey ”,这没有多大帮助。
我无法找到任何有意义的Assert消息。我试着在XNU源中挖掘以找到失败的Assert,但没有任何运气。
有没有人能够用Xcode 13构建一个在Big Sur上工作的DEXT?任何关于尝试什么的建议都是非常受欢迎的。

s5a0g9ez

s5a0g9ez1#

我们面临着同样的问题,苹果建议为Monterey和BigSur做一个单独的版本,或者做两个版本并修改安装程序以基于相应的操作系统安装。

jvlzgdj9

jvlzgdj92#

这花了我一年多的时间,但我终于找到了这种行为的根本原因和可接受的解决方案。
(从我的Angular 来看,另一个答案中提到的两个不同的kext根本没有帮助,因为首先使用较新的SDK和Xcode版本的一个关键原因是Apple缺乏对Xcode本身的向后兼容性-你仍然必须在Xcode 12上构建Big Sur版本,它不会在Monterey上运行,更不用说Ventura了。

表面原因

在DriverKit 21 SDK中,Apple注解了IOUserClient::ExternalMethod函数,以便在专用的命名调度队列上运行。(QUEUENAME(IOUserClientQueueExternalMethod))根据文档,这个队列一开始是对象的默认队列,但当然可以设置为其他队列。
但是,这可能仅适用于macOS 12和更高版本,因为在旧的DriverKit SDK和内核源代码中没有引用该名称的队列。这可以解释为什么当Assert失败时会发生崩溃,因为队列查找必须导致非空队列指针。(崩溃堆栈跟踪中的OSMetaClassBase::QueueForObject。)

解决方案

解决方法实际上看起来非常简单!使用受影响的SDK进行构建时,请确保显式设置了命名队列,至少在受影响的macOS版本上是这样。在initStart期间,您需要在dext中所有IOUserClient子类的每个示例上执行此操作:

IODispatchQueue* default_queue = nullptr;
kern_return_t res = uc->CopyDispatchQueue(kIOServiceDefaultQueueName, &default_queue);
if (res == KERN_SUCCESS && default_queue != nullptr)
{
    res = uc->SetDispatchQueue(kIOUserClientQueueNameExternalMethod, default_queue);
}
OSSafeReleaseNULL(default_queue);

请注意,kIOUserClientQueueNameExternalMethod仅在受影响的SDK版本上定义,因此您可以使用#ifdef kIOUserClientQueueNameExternalMethod在构建时检查是否需要修复。
我已经在我的dext和kext辅助函数的开源库中添加了一个辅助函数,只需要在initStart期间调用它,并为您整理它。

相关问题