2016-12-20 19 views
6

У меня (из любопытства) было интересно, где оболочка пользовательского пространства для системного вызова ioctl определена на x86_64 Linux. Моя первая мысль была glibc - после проверки открытых символов в установленной версии на моем блоке Fedora 24, я вижу, что (если я не ошибаюсь) libc предоставляет символ ioctl как «W», что означает, что это слабый символ с реализация по умолчанию. Реализация по умолчанию в дереве источников glibc на misc/ioctl.c, по-видимому, является заглушкой, хотя и просто устанавливает errno в ENOSYS и возвращает -1.Где оболочка userpace для системного вызова ioctl определена на x86_64 Linux?

Тем не менее, ioctl работает (очевидно, или моя система не очень удобна для использования). Я знаю, что это, вероятно, код сборки где-то в файле, который каким-то образом собран и связан, тем самым перекрывая слабый символ, открытый glibc. Я также знаю, что приложения вполне можно напрямую вызвать ioctl, используя системный вызов, либо через оболочку glibc syscall, либо непосредственно с помощью сборки.

При этом, учитывая исходный код библиотеки, который я случайно наблюдал (libdrm), включает стандартный заголовок ioctl /usr/include/sys/ioctl.h и, похоже, не содержит собственной реализации оболочки, которая Я тоже вижу, мне интересно, куда я должен смотреть.

Это часть моего толчка, чтобы глубже понять нижние уровни системы GNU/Linux. Спасибо за любые указатели и извинения, если это было задано раньше, но я не вижу никакого ответа, если он есть.

UPDATE: я забыл упомянуть выше, но я также проверил виртуальную библиотеку 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 

UPDATE: Казалось бы, я был неправильно о определение glibc по умолчанию является заглушкой. Как указывалось в комментариях, демонстрация показывает, что он выполняет реальный системный вызов. Я написал ответ, чтобы отразить это.

+0

ldd и nm - инструменты, которые я использовал. Тем не менее, я не могу правильно использовать nm - я не могу найти этот символ где угодно, кроме слабого в libc. – PhilPotter1987

+2

Если вы посмотрите на сборку для ioctl в glibc, например 'objdump -D/lib64/libc.so.6', вы обнаружите, что она выполняет фактический syscall - это не реализация из misc/ioctl.c. Его определение, вероятно, автогенерируется как часть процесса сборки glibc, вероятно, sysdeps/unix/make-syscalls.sh является его частью. – nos

+0

Да, вы правы - я отвечу на этот вопрос, но назову ваше имя. Большое спасибо за подсказку. – PhilPotter1987

ответ

0

Как н.у.к., упомянутые в комментарии к моему первоначальному вопросу, это действительно на самом деле определяется в 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) 

Это явно делает системный вызов здесь - как говорит н.у.к., его должен быть автогенерирован, поэтому я не мог найти его прямо в дереве источников glibc.