qemu 中不支持的 ioctl 调用

Unsupported ioctl call in qemu

嗯。我为 android 交叉编译了 qemu,当我对 运行 程序使用用户模式时,它显示存在不支持的 ioctl 调用。例如,我 运行:

./qemu-aarch64 /system/bin/wificond  

它给了我

Unsupported ioctl: cmd=0xffffffffc0046209
Unsupported ioctl: cmd=0x40046205
Binder driver could not be opened.  Terminating.

所以我想我可能想要做的是手动添加该 ioctl 调用。但问题是我只知道 cmd 号,我怎么知道我应该添加什么?谢谢!

您需要做的第一件事是弄清楚它是哪个ioctl。遗憾的是,这有点尴尬。例如,一种方法是使用本机 strace 来跟踪二进制文件,并希望它为您打印 ioctl 符号。或者您可以查看内核头文件。通常 ioctls 是使用 include/uapi/asm-generic/ioctl.h 中的 _IOC 宏定义的,它从一组字段构造它们,因此您必须尝试通过猜测和 grep 从数字中找出正确的。这里0xc0046209的'type'为0x62,即ASCII'b',数字为0x09,即

#define BINDER_VERSION  _IOWR('b', 9, struct binder_version)

(实际上我们或许可以从无法打开活页夹驱动程序的错误消息中猜到)。

所以你在这里需要做的是在 Android 活页夹 API ioctls 的 QEMU 仿真中实现。希望您的主机系统也是 Android,因为非 Android 主机内核不会有绑定器设备。

添加额外的 ioctl 的难度在很大程度上取决于它们的参数是什么,因为参数需要从来宾的数据布局转换为主机的。如果 ioctl 参数是简单类型,那么主要是在 linux-user/ioctls.h 中提供 IOCTL() 行并在 linux-user/syscall_defs.h 中定义 TARGET_IOCTLNAME —— 例如上游 QEMU 提交 d6d6d6fe17fa它添加了 RND* ioctl。当参数是由基本类型组成的结构时,事情并没有复杂多少——例如提交 21992cb6794a5f8。在最坏的情况下,您需要提供自定义函数来转换参数,如提交 2b74f621f1c780 中的 TIOCGPTPEER 所示。