Возможно ли выполнить массив чисел как функцию?

Короче говоря, у меня есть массив целых чисел, который представляет секцию .text двоичного файла ELF с одной функцией. Я хочу выполнить эту функцию. Я выполнил эту команду до попытки выполнить команду:

mprotect(function, sHeader.sh_size, PROT_EXEC | PROT_READ | PROT_WRITE);

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

int (*fp)(int, int) = (int (*)(int, int))getFunc("t.o");
int a = 2;
int b = 3;
cout << fp(a, b) << "\n";

но он все еще segfaults, когда я пытаюсь запустить его:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000603010 in ?? ()

я что-то пропустил?

objdump функции, которую я пытаюсь выполнить:

0000000000000000 <mult>:
mult():
0:   55                      push   %rbp
1:   48 89 e5                mov    %rsp,%rbp
4:   89 7d fc                mov    %edi,-0x4(%rbp)
7:   89 75 f8                mov    %esi,-0x8(%rbp)
a:   8b 45 fc                mov    -0x4(%rbp),%eax
d:   0f af 45 f8             imul   -0x8(%rbp),%eax
11:   5d                      pop    %rbp
12:   c3                      retq

2

Решение

ELF объектный файл содержит перемещение информация, и очень вероятно, его .text раздел содержит код для перемещения, поэтому код не будет работать как есть. Использовать objdump а также readelf команды, чтобы исследовать это. Если вы действительно хотите загрузить его так, как вы это делаете, вам следует обработать информацию о перемещении, которая является сложной, специфичной для процессора и утомительной. Если вы действительно хотите потратить недели на это, изучите x86-64 ABI. Но используя dlopen из .so затем dlsym намного проще (потому что dlopen делает переезд после того, как mmapсегменты от t.so), увидеть ниже.

X86-64 ABI раньше был на http://x86-64.org/documentation/abi.pdf но этот сайт не работает сегодня

Что такое getFunc? Как вы делаете перемещение внутри вашего t.o? Почему ты не можешь иметь t.so общий объект (например, скомпилированный с gcc -Wall -fPIC -O -shared t.c -o t.so) затем загрузите его, используя dlopen (3) а также dlsym(3) например

typedef int functionsig_t (int, int);
void* dlh = dlopen("./t.so", RTLD_NOW);
if (!dlh) {
fprintf(stderr, "dlopen t.so failed with %s\n", dlerror());
exit(EXIT_FAILURE);
};
functionsig_t* fp = (functionsig_t*) dlsym(dlh, "myfunc");
if (!fp) {
fprintf(stderr, "dlsym myfunc failed with %s\n", dlerror());
exit(EXIT_FAILURE),
}
// now you can call fp
int res = (*fp) (1,2);

Однажды fp фреймы стека вызовов, использующие любую функцию в t.so вы можете dlclose(dlh); которые бы munmap сегменты от t.so, Вы могли бы избежать звонка dlclose (это обычно приводит к незначительной утечке адресного пространства процесса; см. файл /proc/1234/maps для процесса pid 1234), особенно если вы этого не сделаете dlopen большое количество общих объектов.

Если t.so плагин вызывает функции из вашей основной программы, вы хотите, чтобы эта основная программа была связана с -rdynamic возможность ld или же gcc

Если t.so был скомпилирован из какого-то источника C ++, он должен объявить

 extern "C" int myfunc(int,int);

потому что название искажения сделано g++

мой manydl.c Программа показывает, что вы можете сделать много сотен тысяч dlopen-с в процессе Linux. Он работает путем генерации «случайного» кода на C, компилируя его в несколько .so, а также dlopenчто .so файл, а затем повторяя это много раз.

Если вы не хотите бремя компиляции .c или же .cc код в .so плагин, вы могли бы рассмотреть оперативную генерацию кода в памяти, используя LLVM, asmjit, libjit, GNU молнии так далее…

3

Другие решения

Вам не хватает переезда. Двоичный файл не содержит абсолютных адресов, но смещений.

Когда двоичный файл загружен, ОС перемещает указатели функций (и все другие символы), добавляя адрес выделенного сегмента к смещениям в двоичном файле.

2

По вопросам рекламы [email protected]