/* bcjtest.c — filtro BCJ x86 standalone (E8/E9 rel32 <-> abs) p/ medir prêmio. * Uso: bcjtest -e in out (rel -> abs, posição = offset global, base 0) * bcjtest -d in out (abs -> rel, inverso exato) * Só transforma opcode completo (5 bytes) dentro do buffer. */ #include #include #include #include static void x86_fwd(uint8_t *b, size_t n){ for(size_t i=0;i+5<=n;i++){ if(b[i]==0xE8||b[i]==0xE9){ uint32_t rel=b[i+1]|((uint32_t)b[i+2]<<8)|((uint32_t)b[i+3]<<16)|((uint32_t)b[i+4]<<24); uint32_t abs=(uint32_t)(i+rel+5); b[i+1]=(uint8_t)abs; b[i+2]=(uint8_t)(abs>>8); b[i+3]=(uint8_t)(abs>>16); b[i+4]=(uint8_t)(abs>>24); i+=4; } } } static void x86_inv(uint8_t *b, size_t n){ for(size_t i=0;i+5<=n;i++){ if(b[i]==0xE8||b[i]==0xE9){ uint32_t abs=b[i+1]|((uint32_t)b[i+2]<<8)|((uint32_t)b[i+3]<<16)|((uint32_t)b[i+4]<<24); uint32_t rel=abs-(uint32_t)(i+5); b[i+1]=(uint8_t)rel; b[i+2]=(uint8_t)(rel>>8); b[i+3]=(uint8_t)(rel>>16); b[i+4]=(uint8_t)(rel>>24); i+=4; } } } static uint8_t *slurp(const char *p,size_t *n){ FILE *f=fopen(p,"rb"); if(!f) return NULL; fseek(f,0,SEEK_END); long nb=ftell(f); fseek(f,0,SEEK_SET); if(nb<=0){ fclose(f); return NULL; } uint8_t *b=malloc(nb); if(fread(b,1,nb,f)!=(size_t)nb){ fclose(f); free(b); return NULL; } fclose(f); *n=nb; return b; } int main(int argc,char**argv){ if(argc!=4){ printf("Uso: %s -e|-d entrada saida\n",argv[0]); return 1; } size_t n=0; uint8_t *b=slurp(argv[2],&n); if(!b){ printf("open fail\n"); return 1; } /* conta E8/E9 p/ diagnóstico */ size_t cnt=0; for(size_t i=0;i+5<=n;i++) if(b[i]==0xE8||b[i]==0xE9){ cnt++; i+=4; } if(strcmp(argv[1],"-e")==0) x86_fwd(b,n); else x86_inv(b,n); FILE *f=fopen(argv[3],"wb"); if(!f){ printf("create fail\n"); free(b); return 1; } fwrite(b,1,n,f); fclose(f); free(b); printf("BCJ %s: %zu bytes, %zu opcodes E8/E9\n",argv[1],n,cnt); return 0; }