Оболочка системного вызова ASM C - PullRequest
2 голосов
/ 01 февраля 2011

Может кто-нибудь объяснить этот фрагмент кода мне?Также, пожалуйста, дайте мне ссылку / URL, где я могу узнать больше об этом?Этот код используется в качестве оболочки для переопределения «extern int errno» в нашей библиотеке.Может кто-нибудь объяснить мне эту функцию и сказать, зачем нужна оболочка в некоторых системных вызовах?Которые также называются WeakSYSCALLS?

#define ASM_ARGS_1      ASM_ARGS_0, "r" (_a1)
#define ASM_ARGS_2      ASM_ARGS_1, "r" (_a2)
#define ASM_ARGS_3      ASM_ARGS_2, "r" (_a3)
#define LOADREGS_5(a1, a2, a3, a4, a5)          \
register int _v1 asm ("v1") = (int) (a5);     \
LOADREGS_4 (a1, a2, a3, a4)

#define LOADREGS_6(a1, a2, a3, a4, a5, a6)      \

register int _v2 asm ("v2") = (int) (a6);     \

LOADREGS_5 (a1, a2, a3, a4, a5)

#define MYLIBC_SYSCALL(name, nargs, args...)               \
({                                                        \

    unsigned int retval;                              \

    {                                                 \

    register int _a1 asm ("r0"), _nargs asm ("r7");   \
    LOADREGS_##nargs(args)                            \
    _nargs = __NR_##name;                             \
    asm volatile (                                    \
            "swi    0x0"                              \
            :"=r"(_a1)                                \
            :"r"(_nargs) ASM_ARGS_##nargs             \
            : "memory" );                             \

      retval = _a1;                                     \
    }                                                 \

    if ( retval >= 0xfffff001 )     {                 \
            errno = -retval;                          \
            retval = (unsigned int)-1;                      \
    }                                                 \
    (int) retval;                                     \
})

Ответы [ 2 ]

5 голосов
/ 01 февраля 2011

Выполнение «системного вызова» означает запуск ядра для выполнения специальной операции.Поскольку ядро ​​работает в другом адресном пространстве, это нельзя сделать простым вызовом функции.

В зависимости от операционной системы и аппаратной платформы системный вызов может быть вызван, например, путем запуска прерывания,call gate, SYSENTER или несколько других методов.

В любом случае, однако, вы не можете просто передать ядру ряд параметров так, как вы бы поступили с вызовом функции C.Вы можете , однако, поместите значения параметров в определенные регистры.То, какие это регистры, и как их содержимое интерпретируется ядром, опять-таки зависит от рассматриваемой ОС.

Поскольку вы не можете ни получить доступ к конкретным регистрам, ни вызвать какой-либо из методов запуска ядра, упомянутых выше,в простом C-коде вам доступны оболочки syscall , которые называются подобными функциям C, а затем помещают параметры в регистры и запускают ядро ​​с помощью кода ASM.

То, что вы видите выше, является такой оболочкой системного вызова.Вы видите часть, где он помещает количество аргументов в регистр r7, сами аргументы в соответствующие регистры (LOADREGS_*), затем выполняет триггер (swi 0x0, который, как я думаю , является программным прерыванием).- Я не очень разбираюсь в платформе ARM) и получаю «возвращаемое значение» из регистра A1.

0 голосов
/ 01 февраля 2011

Системные вызовы не могут установить errno напрямую, вместо этого они возвращают отрицательное значение. errno фактически должен быть макросом, который оценивается как lvalue .

Этот код обновляет вашу копию errno, а не копию библиотеки C.

...