Общая функция C / C ++ для выполнения системных вызовов в PowerPC - PullRequest
0 голосов
/ 10 января 2019

Я хочу написать C/C++ функцию для выполнения syscall, которая принимает значение syscall в качестве аргумента, а также необязательные дополнительные аргументы.

void execute_system_call(short value, const int *arguments, int argument_count) {
    // TODO: Use arguments
    asm volatile (
    "li 0, %0\n\t"
    "sc\n\t"
    :
    : "i"(0x1337) // TODO: Use variable
    );
}

Компиляция кода с переменной C в виде syscall значение вместо жесткого кодирования приводит к следующей ошибке компиляции (так что это то, что уже не работает должным образом):

assembly.cpp: In function 'void execute_system_call(short int, const int*, int)':
assembly.cpp:62:3: warning: asm operand 0 probably doesn't match constraints
  );
   ^
assembly.cpp:62:3: error: impossible constraint in 'asm'
make[1]: *** [assembly.o] Error 1
make: *** [build] Error 2

Кроме того, мне также нужно передать аргументы в соответствующие регистры. В PowerPC это обычно будет r3, r4, ..., что также кажется проблематичным, поскольку я не хочу явно указывать это и оставлять вместо этого присвоение регистра в соответствии с соглашениями о вызовах для компилятора. Возможно, последнее невозможно, поэтому я должен написать это больше как следующий псевдокод:

lis 3, $arguments[0]@h # Load higher 16-bit
ori 3, 3, $arguments[0]@l # Load lower 16-bit
lis 4, $arguments[1]@h
ori 4, 4, $arguments[1]@l
lis 5, $arguments[2]@h
ori 5, 5, $arguments[2]@l
...
li 0, $value
sc

Обратите внимание, что все в порядке, если предполагается, что argument_count всегда будет, например, 8 и не обязательно должен быть переменным, поэтому сигнатура метода также может быть

void execute_system_call(short value, const int *arguments)

Как это можно сделать?

1 Ответ

0 голосов
/ 14 января 2019

Если ваш измененный код выглядит следующим образом:

void execute_system_call(short value, const int *arguments, int argument_count) {
    // TODO: Use arguments
    asm volatile (
    "li 0, %0\n\t"
    "sc\n\t"
    :
    : "i"(value)
    );
}

- тогда вы просите gcc передать переменную value как немедленную (поскольку вы все еще используете "i" в качестве ограничения). Поскольку value является переменной, а не немедленной, это не сработает, что является причиной ошибки, которую вы видите там.

Вместо этого вам нужно будет использовать ограничение ввода "r", чтобы сослаться на значение регистра:

void execute_system_call(short value, const int *arguments, int argument_count) {
    // TODO: Use arguments
    asm volatile (
    "li 0, %0\n\t"
    "sc\n\t"
    :
    : "r"(value)
    );
}

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

Итак, мы, вероятно, хотим mr («регистр перемещения»), а не li:

void execute_system_call(short value, const int *arguments, int argument_count) {
    // TODO: Use arguments
    asm volatile (
    "mr 0, %0\n\t"
    "sc\n\t"
    :
    : "r"(value)
    );
}

Это должно выполнить инструкцию sc с r0, содержащей value.

Однако это еще не совсем завершено. Поскольку ваш системный вызов, вероятно, что-то возвращает, вам также необходимо описать это в выходных ограничениях встроенного asm. Способ сохранения возвращаемого значения будет зависеть от ABI системы, с которой вы работаете.

Также, в зависимости от вашего системного вызова ABI, инструкция sc может изменять другие регистры и / или память. Вы также должны были бы перечислить их в константах clobber оператора asm.

Тогда у нас есть входные аргументы. Реальная реализация этого будет зависеть от вызова функции ABI вашей программы и системного вызова ABI кода супервизора.

Если они довольно похожи, вы можете обнаружить, что гораздо проще реализовать execute_system_call в качестве фактического ASM, чем C-with-inline-ASM. Таким образом, вам не нужно распаковывать аргументы из C во встроенный ASM. В противном случае вам нужно будет создать похожий код для размещения элементов массива arguments в определенных регистрах.

И, как проверка работоспособности, разве ваша платформа не обеспечивает функцию syscall? Это звучит именно то, что вы ищете здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...