Enviado em 06/10/2018 - 11:51h
Olá Pessoal !!!
//-------------------------------------------------------------------
//
// Jit com chamada dinamica ( .so ) ... usa SDL1.x como exemplo.
//
// Testado somente em 64 BITS.
//
// A Funcao ( emit_call_direct(ASM *a)) eh baseado neste projeto:
//
// https://github.com/skeeto/dynamic-function-benchmark
//
// ARQUIVO:
// jit64.c
//
// COMPILE:
// gcc jit64.c -o jit64 -ldl -Wall
//
// BY: Francisco - gokernel@hotmail.com
//
//-------------------------------------------------------------------
#ifdef WIN32
#include <windows.h>
#endif
#ifdef __linux__
#include <unistd.h>
#include <sys/mman.h> // to: mprotect()
#include <dlfcn.h> // to: dlopen(), dlsym(), ... in file: cs_library.c
#endif
#include <stdio.h>
#include <stdlib.h>
#define MMAP_ANON 0x20
#define UCHAR unsigned char
typedef struct {
UCHAR *p;
UCHAR *code;
}ASM;
void *init = NULL;
void *delay = NULL;
void *quit = NULL;
void libopen (void) {
#ifdef __linux__
void *lib = dlopen ("libSDL.so", RTLD_NOW);
if (lib) {
printf ("Library SDL Loaded\n");
init = dlsym (lib, "SDL_Init");
delay = dlsym (lib, "SDL_Delay");
quit = dlsym (lib, "SDL_Quit");
if (init) {
printf ("SDL_Init loaded ...\n");
}
if (delay) {
printf ("SDL_Delay loaded ...\n");
}
if (quit) {
printf ("SDL_Quit loaded ...\n");
}
}
else printf ("libSDL.so Not Found\n");
#endif
}
ASM * asm_new (unsigned int size) {
ASM *a = (ASM*)malloc(sizeof(ASM));
#ifdef WIN32
if (a && (a->code=(UCHAR*)malloc(size)) != NULL) {
a->p = a->code;
return a;
}
#endif
#ifdef __linux__
if (a && (a->code = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MMAP_ANON, -1, 0)) != MAP_FAILED) {
a->p = a->code;
return a;
}
#endif
return NULL;
}
int set_executable (void *ptr, unsigned int size) {
#ifdef WIN32
unsigned long old_protect;
if (!VirtualProtect(ptr, size, PAGE_EXECUTE_READWRITE, &old_protect)) {
printf ("ERROR: asm_set_executable() ... NOT FOUND - VirtualProtect()\n");
return 1; // erro
}
#endif
#ifdef __linux__
unsigned long start, end, PageSize;
PageSize = sysconf (_SC_PAGESIZE);
start = (unsigned long)ptr & ~(PageSize - 1);
end = (unsigned long)ptr + size;
end = (end + PageSize - 1) & ~(PageSize - 1);
if (mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) {
printf ("ERROR: asm_set_executable() ... NOT FOUND - mprotec()\n");
return 1; // erro
}
#endif
return 0; // no erro
}
void asm_get_addr (ASM *a, void *ptr) { ///: 32/64 BITS OK
*(void**)a->p = ptr;
a->p += 4; // ! OK
}
void g2 (ASM *a, UCHAR c1, UCHAR c2) {
a->p[0] = c1;
a->p[1] = c2;
a->p += 2;
}
void g3 (ASM *a, UCHAR c1, UCHAR c2, UCHAR c3) {
a->p[0] = c1;
a->p[1] = c2;
a->p[2] = c3;
a->p += 3;
}
void g4 (ASM *a, UCHAR c1, UCHAR c2, UCHAR c3, UCHAR c4) {
a->p[0] = c1;
a->p[1] = c2;
a->p[2] = c3;
a->p[3] = c4;
a->p += 4;
}
void emit_sub_esp (ASM *a, char c) { // 32/64 BITS OK
#if defined(__x86_64__)
g4(a,0x48,0x83,0xec,(char)c); // 48 83 ec 08 sub $0x8,%rsp
#else
g3(a,0x83,0xec,(char)c); // 83 ec 08 sub $0x8,%esp
#endif
}
void emit_begin (ASM *a) { //: 32/64 BITS OK
#if defined(__x86_64__)
// 55 : push %rbp
// 48 89 e5 : mov %rsp,%rbp
//-----------------------------
a->p[0] = 0x55;
a->p[1] = 0x48;
a->p[2] = 0x89;
a->p[3] = 0xe5;
a->p += 4;
emit_sub_esp (a,16);
#else
// 55 : push %ebp
// 89 e5 : mov %esp,%ebp
//-----------------------------
a->p[0] = 0x55;
a->p[1] = 0x89;
a->p[2] = 0xe5;
a->p += 3;
emit_sub_esp (a,100);
#endif
}
void emit_end (ASM *a) { ///: 32/64 BITS OK
#if defined(__x86_64__)
a->p[0] = 0xc9; // c9 : leaveq
a->p[1] = 0xc3; // c3 : retq
a->p += 2;
#else
a->p[0] = 0xc9; // c9 : leave
a->p[1] = 0xc3; // c3 : ret
a->p += 2;
#endif
}
void emit_call (ASM *a, void *func) {
//
// b8 7a 13 40 00 mov $0x40137a,%eax
// ff d0 call *%eax
//
*a->p++ = 0xb8; asm_get_addr(a, func); // %eax
g2(a,0xff,0xd0); // %eax
}
void emit_call_direct (ASM *a, void *func) {
#ifdef __linux__
#if defined(__x86_64__)
//
// Codigo baseado neste projeto:
//
// https://github.com/skeeto/dynamic-function-benchmark
//
//uintptr_t rel = (uintptr_t)func - (uintptr_t)a->p - 5;
*a->p++ = 0xe8;
*(long*)a->p = (void*)func - (void*)a->p - 4;
a->p += 4;
#endif
#endif
}
void hello (int i) {
printf ("\nFunction Hello World: %d\n\n", i);
}
void execute (void) {
ASM *a;
if ((a = asm_new (1000)) != NULL) {
libopen ();
if (init && delay && quit) {
emit_begin(a);
// funcao argumento 1:
// mov $32 %edi
g2(a,0xbf,0x20); g3(a,0x00,0x00,0x00);
emit_call_direct (a, init);
// funcao argumento 1:
// mov $32 %edi
g2 (a,0xbf,0x20); g3(a,0x00,0x00,0x00);
emit_call (a, hello);
// funcao argumento 1:
// bf b8 0b 00 00 mov $3000,%edi
g2(a,0xbf,0xb8); g3(a,0x0b,0x00,0x00);
emit_call_direct (a, delay);
emit_call_direct (a, quit);
emit_end(a);
if (set_executable(a, (a->p - a->code))==0) {
( (void(*)(void)) a->code ) ();
printf ("\nExiting Whith Sucess !!!\n");
}
}
}
}
int main (void) {
execute ();
return 0;
}
Servidor de Backup com Ubuntu Server 24.04 LTS, RAID e Duplicati (Dell PowerEdge T420)
Visualizar câmeras IP ONVIF no Linux sem necessidade de instalar aplicativos
Atualizar Debian Online de uma Versão para outra
Dica para encontrar diversos jogos Indies criativos
Instalando Discord no Debian 13
Instalar driver Nvidia no Debian 13
Redimensionando, espelhando, convertendo e rotacionando imagens com script
Software livre - será que eu estou tão errado assim? (11)
Boot do PosRog so funciona em notebook (1)