Если вам просто нужно протестировать, попробуйте это вместо этого, это magic ...
const unsigned char code[2] = {0xc9, 0xc3};
^^^^^
Ключевое слово const
заставляет компилятор поместить его в const
раздел (предупреждение! это детали реализации!), который находится в том же сегменте, что и раздел text
.Весь сегмент должен быть исполняемым.Вероятно, это более переносимо:
__attribute__((section("text"))
const unsigned char code[2] = {0xc9, 0xc3};
И вы всегда можете сделать это в файле сборки,
.text
.globl code
code:
.byte 0xc9
.byte 0xc3
Однако: Если выЧтобы изменить код во время выполнения, вам нужно использовать mprotect
.По умолчанию в памяти нет отображений с разрешениями на запись и выполнение.
Вот пример:
#include <stdlib.h>
#include <sys/mman.h>
#include <err.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
unsigned char *p = malloc(4);
int r;
// This is x86_64 code
p[0] = 0x8d;
p[1] = 0x47;
p[2] = 0x01;
p[3] = 0xc3;
// This is hackish, and in production you should do better.
// Casting 4095 to uintptr_t is actually necessary on 64-bit.
r = mprotect((void *) ((uintptr_t) p & ~(uintptr_t) 4095), 4096,
PROT_READ | PROT_WRITE | PROT_EXEC);
if (r)
err(1, "mprotect");
// f(x) = x + 1
int (*f)(int) = (int (*)(int)) p;
return f(1);
}
В спецификации mprotect
указано, что его поведение не определено, если памятьизначально не был сопоставлен с mmap
, но вы тестируете, а не отправляете, так что просто знайте, что он прекрасно работает на OS X, потому что OS X malloc
использует mmap
за кулисами (исключительно, я думаю).