Как точка входа 32-битной таблицы системных вызовов отображается на SYSCALL_DEFINE в x86_64 - PullRequest
1 голос
/ 20 января 2020

Я копаю глубже в системные вызовы,

Добавлен системный вызов в syscall_32.tbl и syscall_64.tbl

syscall_32.tbl

434     i386    hello           sys_hello           __ia32_sys_hello

syscall_64. tbl

434 common  hello           __x64_sys_hello

Определение:

SYSCALL_DEFINE0(hello) {
    pr_info("%s\n", __func__);
    pr_info("Hello, world!\n");
    return 0;
 }

Код пространства пользователя:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/syscall.h>
#include <string.h>
int main(void)
{
    long return_value = syscall(434);

    printf("return value from syscall: %ld, erron:%d\n", return_value, errno);
    return 0;
}

Когда я запускаю этот код пространства пользователя на x86_64, я получаю следующий вывод в dmesg

$ gcc userspace.c -o userspace

[  800.837360] __x64_sys_hello
[  800.837361] Hello, world!

Но когда я компилирую его для 32-битной системы, я получаю

$ gcc userspace.c -o userspace -m32

[  838.979286] __x64_sys_hello
[  838.979286] Hello, world!

Как получается, что точка входа в syscall_32.tbl (__ia32_sys_hello) отображается на __x64_sys_hello?

1 Ответ

4 голосов
/ 20 января 2020

В 64-разрядном ядре SYSCALL_DEFINE0 определяет точки входа compat (32-разрядные) и другие ABI (например, x32 для x86_64) как псевдонимы для реальной 64-разрядной функции. Он не определяет (и не имеет возможности определить; это не так, как работает препроцессор) нескольких функций, созданных из одного тела, появляющегося после ) оценки макроса. Таким образом, __func__ расширяется до имени фактической функции, в которой записано __func__, а не имени псевдонима.

Для SYSCALL_DEFINEx с x> 0 это более сложно, так как аргументы должны быть преобразованным, и я верю, что вовлечены оболочки.

Вы можете найти всех магов c в arch/x86/include/asm/syscall_wrapper.h (под деревом ядра верхнего уровня).

Если вы действительно хотите / должны иметь отдельные функции, я считаю, что есть способ пропустить магию c и сделать это. Но это усложняет поддержку вашего кода, так как он может сломаться, когда механизмы, стоящие за магией c, сломаются. Вероятно, предпочтительнее проверить, является ли вызывающий (текущий) процесс пользовательского пространства 32-разрядным или 64-разрядным, и в соответствии с этим действуют по-другому.

...