在x86_64 Linux系统中,ioctl系统调用的用户空间封装器定义在哪里?

6

出于好奇,我一直想知道在x86_64 Linux上,ioctl系统调用的用户空间包装器是在哪里定义的。我的第一个想法是glibc - 经过检查我在Fedora 24上安装的版本的暴露符号后,我可以看到(除非我做错了什么)libc将ioctl符号公开为“W”,这意味着它是一个具有默认实现的弱符号。 glibc源代码树中misc / ioctl.c中的默认实现似乎只是一个存根,仅将errno设置为ENOSYS并返回-1。

尽管如此,ioctl可行(当然,否则我的系统就无法使用)。我知道它可能在某个文件中的汇编代码中,并以某种方式进行汇编和链接,从而覆盖了glibc公开的弱符号。我还知道,应用程序可以通过系统调用直接调用ioctl,无论是通过glibc系统调用包装器还是直接使用汇编语言。

话虽如此,鉴于我正观察的库源代码(libdrm)包括标准的ioctl头文件/usr/include/sys/ioctl.h,并且似乎也不包含我可以看到的自己的包装器实现,我想知道我应该去哪里找。

这是我深入了解GNU / Linux系统最低层的推动之一。谢谢任何提示,并为此之前的问题道歉,但如果确实有,请告诉我答案。

更新:我忽略了上面提到的虚拟vdso库映射到内核中 - 我只能在其中找到以下内容:

0000000000000a00 W clock_gettime
0000000000000db0 W getcpu
0000000000000c40 W gettimeofday
0000000000000000 A LINUX_2.6
0000000000000d90 W time
0000000000000a00 T __vdso_clock_gettime
0000000000000db0 T __vdso_getcpu
0000000000000c40 T __vdso_gettimeofday
0000000000000d90 T __vdso_time

更新:看起来我对glibc默认定义只是一个存根的说法是错误的。正如评论中nos指出的那样,反汇编显示它正在执行真正的系统调用。我已经发布了一篇答案来反映这一点。


ldd和nm是我一直在使用的工具。话虽如此,我可能没有正确地使用nm——除了libc中的弱符号外,我找不到这个符号的任何其他地方。 - PhilPotter1987
2
如果您查看glibc中ioctl的汇编,例如 objdump -D /lib64/libc.so.6 ,您会发现它确实执行了实际的系统调用 - 它不是来自misc/ioctl.c的实现。它的定义很可能是作为glibc构建过程的一部分自动生成的,很可能sysdeps/unix/make-syscalls.sh是其中的一部分。 - nos
是的,你说得对 - 我会回答这个问题,但会提到你的名字。非常感谢这个提示。 - PhilPotter1987
1个回答

0

正如nos在我的原始问题的评论中提到的那样,它实际上是在libc中定义的,在我的情况下如下:

00000000000f8ce0 <ioctl>:
   f8ce0:       b8 10 00 00 00          mov    $0x10,%eax
   f8ce5:       0f 05                   syscall
   f8ce7:       48 3d 01 f0 ff ff       cmp    $0xfffffffffffff001,%rax
   f8ced:       73 01                   jae    f8cf0 <ioctl+0x10>
   f8cef:       c3                      retq
   f8cf0:       48 8b 0d 71 31 2c 00    mov    0x2c3171(%rip),%rcx        # 3bbe68 <_DYNAMIC+0x308>
   f8cf7:       f7 d8                   neg    %eax
   f8cf9:       64 89 01                mov    %eax,%fs:(%rcx)
   f8cfc:       48 83 c8 ff             or     $0xffffffffffffffff,%rax
   f8d00:       c3                      retq
   f8d01:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
   f8d08:       00 00 00
   f8d0b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

这里显然是在进行系统调用 - 正如nos所说,它必须是自动生成的,这就是为什么我在glibc源代码树中找不到它的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接