Я хотел бы вызвать код ARM / ARM64 ASM из C ++. Код ASM содержит системный вызов и перемещение во внешнюю функцию.
Архитектура ARM здесь не так важна, я просто хочу понять, как концептуально решить мою проблему.
У меня есть следующий системный вызов ASM (вывод из objdump -d
), который вызывается из общей библиотеки:
198: d28009e8 mov x8, #0x4f // #79
19c: d4000001 svc #0x0
1a0: b140041f cmn x0, #0x1, lsl #12
1a4: da809400 cneg x0, x0, hi
1a8: 54000008 b.hi 0 <__set_errno_internal>
1ac: d65f03c0 ret
Этот фрагмент кода вызывает fstatat64
системный вызов и устанавливает errno
с помощью внешней __set_errno_internal
функции.
readelf -r
показывает следующее перемещение для функции __set_errno_internal
:
00000000000001a8 R_AARCH64_CONDBR19 __set_errno_internal
Я хочу вызвать этот фрагмент кода из C ++, поэтому я преобразовал его в буфер:
unsigned char machine_code[] __attribute__((section(".text"))) =
"\xe8\x09\x80\xd2"
"\x01\x00\x00\xd4"
"\x1f\x04\x40\xb1"
"\x00\x94\x80\xda"
"\x08\x00\x00\x54" // Here we have mentioned relocation
"\xc0\x03\x5f\xd6";
РЕДАКТИРОВАТЬ: важная деталь - я решил использовать буфер (не встроенную сборку и т. Д.), Потому что я хочу выполнить дополнительную обработку этого буфера (например, функцию дешифрования строкового литерала как механизма защиты программного обеспечения, но это не важно здесь) перед этим оценивается как машинный код.
После этого буфер может быть приведен к функции и вызван напрямую для выполнения машинного кода. Очевидно, есть проблема с перемещением, она не исправлена автоматически, и я должен исправить это вручную. Но во время выполнения я не могу этого сделать, потому что раздел .text
доступен только для чтения и исполняется.
Хотя я почти полностью контролирую исходный код, я не должен отключать защиту стека и другие функции, чтобы сделать этот раздел доступным для записи (не спрашивайте, почему). Таким образом, кажется, что исправление перемещения должно выполняться как-то на этапе соединения. Насколько мне известно, разделяемая библиотека содержит относительные смещения (для аналогичных вызовов внешних функций) после того, как компоновщик фиксирует перемещения, и двоичный файл * .so должен содержать правильные смещения (без необходимости работы по перемещению во время выполнения), поэтому исправление этого machine_code
буфер во время связывания должен быть возможен.
Я использую компилятор Clang 7, созданный вручную, и у меня есть полный контроль над проходами LLVM, поэтому я подумал, что возможно написать какой-то проход LLVM, который выполняется во время соединения. Хотя, похоже, в конце вызывается ld
, поэтому, возможно, пропуски LLVM здесь не помогут (здесь не эксперт).
Различные идеи будут оценены также.
Как видите, проблема довольно сложная. Может быть, у вас есть какие-то направления / идеи, как это решить? Спасибо!