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;
}
Aprenda a Gerenciar Permissões de Arquivos no Linux
Como transformar um áudio em vídeo com efeito de forma de onda (wave form)
Como aprovar Pull Requests em seu repositório Github via linha de comando
Visualizar arquivos em formato markdown (ex.: README.md) pelo terminal
Dando - teoricamente - um gás no Gnome-Shell do Arch Linux
Como instalar o Google Cloud CLI no Ubuntu/Debian
Mantenha seu Sistema Leve e Rápido com a Limpeza do APT!
Procurando vídeos de YouTube pelo terminal e assistindo via mpv (2025)
Gestão de Ambiente em uma rede Linux (1)
Zorin OS - Virtual Box não consigo abrir maquinas virtuais (1)
O que você está ouvindo agora? [2] (180)