Box86源码剖析
Box86
前文回顾
源码阅读
Run()
跳转系统调用函数实现:x86Syscall(emu);
总结
动态指令翻译的过程
举例说明:
底层调用库接口使用流程
Box86
前文回顾
在前面的代码阅读过程中,我们已经成功找到了真正去翻译程序并执行的入口函数 Run(),具体内容可以参考下面链接:
Box86源码剖析(一)
Box86源码剖析(二)
前面看到的内容概况下来如下:
源码阅读
Run()
从前面,我们看到 Box86 的真正进行指令翻译和执行的入口在于 x86run.c 文件中的 Run() 函数,该函数的实现太长,这里就取前半部分看一下:
int Run(x86emu_t *emu, int step) { uint8_t opcode; uint8_t nextop; reg32_t *oped; uint8_t tmp8u, tmp8u2; int8_t tmp8s; uint16_t tmp16u, tmp16u2; int16_t tmp16s; uint32_t tmp32u, tmp32u2, tmp32u3; int32_t tmp32s, tmp32s2; uint64_t tmp64u; int64_t tmp64s; uintptr_t ip; double d; float f; int64_t ll; sse_regs_t *opex, eax1; mmx_regs_t *opem, eam1; if(emu->quit) return 0; //ref opcode: http://ref.x86asm.net/geek32.html#xA1 printf_log(LOG_DEBUG, "Run X86 (%p), EIP=%p, Stack=%p\n", emu, (void*)R_EIP, emu->context->stack); #define F8 *(uint8_t*)(ip++) #define F8S *(int8_t*)(ip++) #define F16 *(uint16_t*)(ip+=2, ip-2) #define F32 *(uint32_t*)(ip+=4, ip-4) #define F32S *(int32_t*)(ip+=4, ip-4) #define PK(a) *(uint8_t*)(ip+a) #ifdef DYNAREC #define STEP if(step) goto stepout; #else #define STEP #endif static const void* baseopcodes[256] ={ &&_0x00_0, &&_0x00_1, &&_0x00_2, &&_0x00_3, &&_0x00_4, &&_0x00_5, &&_0x06, &&_0x07, //0x00-0x07 &&_0x08_0, &&_0x08_1, &&_0x08_2, &&_0x08_3, &&_0x08_4, &&_0x08_5, &&_0x0E, &&_0x0F, //0x08-0x0F &&_0x10_0, &&_0x10_1, &&_0x10_2, &&_0x10_3, &&_0x10_4, &&_0x10_5, &&_0x16, &&_0x17, //0x10-0x17 &&_0x18_0, &&_0x18_1, &&_0x18_2, &&_0x18_3, &&_0x18_4, &&_0x18_5, &&_0x1E, &&_0x1F, //0x18-0x1F &&_0x20_0, &&_0x20_1, &&_0x20_2, &&_0x20_3, &&_0x20_4, &&_0x20_5, &&_0x26, &&_0x27, //0x20-0x27 &&_0x28_0, &&_0x28_1, &&_0x28_2, &&_0x28_3, &&_0x28_4, &&_0x28_5, &&_0x2E, &&_0x2F, //0x28-0x2F &&_0x30_0, &&_0x30_1, &&_0x30_2, &&_0x30_3, &&_0x30_4, &&_0x30_5, &&_0x36, &&_0x37, //0x30-0x37 &&_0x38, &&_0x39, &&_0x3A, &&_0x3B, &&_0x3C, &&_0x3D, &&_0x3E, &&_0x3F, //0x38-0x3F &&_0x40, &&_0x41, &&_0x42, &&_0x43, &&_0x44, &&_0x45, &&_0x46, &&_0x47, &&_0x48, &&_0x49, &&_0x4A, &&_0x4B, &&_0x4C, &&_0x4D, &&_0x4E, &&_0x4F, &&_0x50, &&_0x51, &&_0x52, &&_0x53, &&_0x54, &&_0x55, &&_0x56, &&_0x57, &&_0x58, &&_0x59, &&_0x5A, &&_0x5B, &&_0x5C, &&_0x5D, &&_0x5E, &&_0x5F, &&_0x60, &&_0x61, &&_0x62, &&_0x63, &&_0x64, &&_0x65, &&_0x66, &&_0x67, &&_0x68, &&_0x69, &&_0x6A, &&_0x6B, &&_0x6C, &&_0x6D, &&_0x6E, &&_0x6F, //0x68-0x6F &&_0x70_0, &&_0x70_1, &&_0x70_2, &&_0x70_3, &&_0x70_4, &&_0x70_5, &&_0x70_6, &&_0x70_7, //0x70-0x77 &&_0x70_8, &&_0x70_9, &&_0x70_A, &&_0x70_B, &&_0x70_C, &&_0x70_D, &&_0x70_E, &&_0x70_F, //0x78-0x7F &&_0x80, &&_0x81, &&_0x82, &&_0x83, &&_0x84, &&_0x85, &&_0x86, &&_0x87, &&_0x88, &&_0x89, &&_0x8A, &&_0x8B, &&_0x8C, &&_0x8D, &&_0x8E, &&_0x8F, &&_0x90, &&_0x91, &&_0x92, &&_0x93, &&_0x94, &&_0x95, &&_0x96, &&_0x97, &&_0x98, &&_0x99, &&_default, &&_0x9B, &&_0x9C, &&_0x9D, &&_0x9E, &&_0x9F, &&_0xA0, &&_0xA1, &&_0xA2, &&_0xA3, &&_0xA4, &&_0xA5, &&_0xA6, &&_0xA7, &&_0xA8, &&_0xA9, &&_0xAA, &&_0xAB, &&_0xAC, &&_0xAD, &&_0xAE, &&_0xAF, &&_0xB0, &&_0xB1, &&_0xB2, &&_0xB3, &&_0xB4, &&_0xB5, &&_0xB6, &&_0xB7, &&_0xB8, &&_0xB9, &&_0xBA, &&_0xBB, &&_0xBC, &&_0xBD, &&_0xBE, &&_0xBF, &&_0xC0, &&_0xC1, &&_0xC2, &&_0xC3, &&_0xC4, &&_0xC5, &&_0xC6, &&_0xC7, &&_0xC8, &&_0xC9, &&_default, &&_0xCB, &&_0xCC, &&_0xCD, &&_default, &&_0xCF, //0xC8-0xCF &&_0xD0, &&_0xD1, &&_0xD2, &&_0xD3, &&_0xD4, &&_0xD5, &&_0xD6, &&_0xD7, &&_0xD8, &&_0xD9, &&_0xDA, &&_0xDB, &&_0xDC, &&_0xDD, &&_0xDE, &&_0xDF, &&_0xE0, &&_0xE1, &&_0xE2, &&_0xE3, &&_0xE4, &&_0xE5, &&_0xE6, &&_0xE7, &&_0xE8, &&_0xE9, &&_default, &&_0xEB, &&_0xEC, &&_0xED, &&_default, &&_default, &&_0xF0, &&_0xF1, &&_0xF2, &&_0xF3, &&_default, &&_0xF5, &&_0xF6, &&_0xF7, &&_0xF8, &&_0xF9, &&_0xFA, &&_0xFB, &&_0xFC, &&_0xFD, &&_0xFE, &&_0xFF }; static const void* opcodes0f[256] = { &&_0f_0x00, &&_0f_0x01, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07 &&_default, &&_default, &&_default, &&_0f_0x0B, &&_default ,&&_default, &&_default, &&_default, //0x08-0x0F &&_0f_0x10, &&_0f_0x11, &&_0f_0x12, &&_0f_0x13, &&_0f_0x14, &&_0f_0x15, &&_0f_0x16, &&_0f_0x17, //0x10-0x17 &&_0f_0x18, &&_default, &&_0f_0x1A, &&_0f_0x1B, &&_default ,&&_default, &&_default, &&_0f_0x1F, //0x18-0x1F &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x20-0x27 &&_0f_0x28, &&_0f_0x29, &&_0f_0x2A, &&_0f_0x2B, &&_0f_0x2C, &&_0f_0x2D, &&_0f_0x2E, &&_0f_0x2F, &&_default, &&_0f_0x31, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x30-0x37 &&_0f_0x38, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x38-0x3F &&_0f_0x40_0, &&_0f_0x40_1, &&_0f_0x40_2, &&_0f_0x40_3, &&_0f_0x40_4, &&_0f_0x40_5, &&_0f_0x40_6, &&_0f_0x40_7, &&_0f_0x40_8, &&_0f_0x40_9, &&_0f_0x40_A, &&_0f_0x40_B, &&_0f_0x40_C, &&_0f_0x40_D, &&_0f_0x40_E, &&_0f_0x40_F, &&_0f_0x50, &&_0f_0x51, &&_0f_0x52, &&_0f_0x53, &&_0f_0x54, &&_0f_0x55, &&_0f_0x56, &&_0f_0x57, //0x50-0x57 &&_0f_0x58, &&_0f_0x59, &&_0f_0x5A, &&_0f_0x5B, &&_0f_0x5C, &&_0f_0x5D, &&_0f_0x5E, &&_0f_0x5F, &&_0f_0x60, &&_0f_0x61, &&_0f_0x62, &&_0f_0x63, &&_0f_0x64 ,&&_0f_0x65, &&_0f_0x66, &&_0f_0x67, //0x60-0x67 &&_0f_0x68, &&_0f_0x69, &&_0f_0x6A, &&_0f_0x6B, &&_default ,&&_default, &&_0f_0x6E, &&_0f_0x6F, //0x68-0x6F &&_0f_0x70, &&_0f_0x71, &&_0f_0x72, &&_0f_0x73, &&_0f_0x74 ,&&_0f_0x75, &&_0f_0x76, &&_0f_0x77, //0x70-0x77 &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_0f_0x7E, &&_0f_0x7F, //0x78-0x7F &&_0f_0x80_0, &&_0f_0x80_1, &&_0f_0x80_2, &&_0f_0x80_3, &&_0f_0x80_4, &&_0f_0x80_5, &&_0f_0x80_6, &&_0f_0x80_7, &&_0f_0x80_8, &&_0f_0x80_9, &&_0f_0x80_A, &&_0f_0x80_B, &&_0f_0x80_C, &&_0f_0x80_D, &&_0f_0x80_E, &&_0f_0x80_F, &&_0f_0x90_0, &&_0f_0x90_1, &&_0f_0x90_2, &&_0f_0x90_3, &&_0f_0x90_4, &&_0f_0x90_5, &&_0f_0x90_6, &&_0f_0x90_7, &&_0f_0x90_8, &&_0f_0x90_9, &&_0f_0x90_A, &&_0f_0x90_B, &&_0f_0x90_C, &&_0f_0x90_D, &&_0f_0x90_E, &&_0f_0x90_F, &&_0f_0xA0, &&_0f_0xA1, &&_0f_0xA2, &&_0f_0xA3, &&_0f_0xA4, &&_0f_0xA5, &&_default, &&_default, //0xA0-0xA7 &&_0f_0xA8, &&_0f_0xA9, &&_default, &&_0f_0xAB, &&_0f_0xAC, &&_0f_0xAD, &&_0f_0xAE, &&_0f_0xAF, &&_0f_0xB0, &&_0f_0xB1, &&_default, &&_0f_0xB3, &&_default, &&_default, &&_0f_0xB6, &&_0f_0xB7, &&_default, &&_default, &&_0f_0xBA, &&_0f_0xBB, &&_0f_0xBC, &&_0f_0xBD, &&_0f_0xBE, &&_0f_0xBF, &&_0f_0xC0, &&_0f_0xC1, &&_0f_0xC2, &&_0f_0xC3, &&_0f_0xC4, &&_0f_0xC5, &&_0f_0xC6, &&_0f_0xC7, &&_0f_0xC8, &&_0f_0xC9, &&_0f_0xCA, &&_0f_0xCB, &&_0f_0xCC, &&_0f_0xCD, &&_0f_0xCE, &&_0f_0xCF, //0xC8-0xCF &&_default, &&_0f_0xD1, &&_0f_0xD2, &&_0f_0xD3, &&_0f_0xD4 ,&&_0f_0xD5, &&_default, &&_0f_0xD7, //0xD0-0xD7 &&_0f_0xD8, &&_0f_0xD9, &&_default, &&_0f_0xDB, &&_0f_0xDC ,&&_0f_0xDD, &&_default, &&_0f_0xDF, //0xD8-0xDF &&_0f_0xE0, &&_0f_0xE1, &&_0f_0xE2, &&_0f_0xE3, &&_0f_0xE4 ,&&_0f_0xE5, &&_default, &&_0f_0xE7, //0xE0-0xE7 &&_0f_0xE8, &&_0f_0xE9, &&_0f_0xEA, &&_0f_0xEB, &&_0f_0xEC ,&&_0f_0xED, &&_0f_0xEE, &&_0f_0xEF, //0xE8-0xEF &&_default, &&_0f_0xF1, &&_0f_0xF2, &&_0f_0xF3, &&_0f_0xF4 ,&&_0f_0xF5, &&_0f_0xF6, &&_0f_0xF7, //0xF0-0xF7 &&_0f_0xF8, &&_0f_0xF9, &&_0f_0xFA, &&_default, &&_0f_0xFC ,&&_0f_0xFD, &&_0f_0xFE, &&_default //0xF8-0xFF }; static const void* opcodes66[256] = { &&_default, &&_66_0x00_1, &&_default, &&_66_0x00_3, &&_default ,&&_66_0x00_5, &&_66_0x06, &&_66_0x07, //0x00-0x07 &&_default, &&_66_0x08_1, &&_default, &&_66_0x08_3, &&_default ,&&_66_0x08_5, &&_default, &&_66_0x0F, //0x08-0x0F &&_default, &&_66_0x10_1, &&_default, &&_66_0x10_3, &&_default ,&&_66_0x10_5, &&_default, &&_default, //0x10-0x17 &&_default, &&_66_0x18_1, &&_default, &&_66_0x18_3, &&_default ,&&_66_0x18_5, &&_default, &&_default, //0x18-0x1F &&_default, &&_66_0x20_1, &&_default, &&_66_0x20_3, &&_default ,&&_66_0x20_5, &&_66_0x26, &&_default, //0x20-0x27 &&_default, &&_66_0x28_1, &&_default, &&_66_0x28_3, &&_default ,&&_66_0x28_5, &&_66_0x2E, &&_default, //0x28-0x2F &&_default, &&_66_0x30_1, &&_default, &&_66_0x30_3, &&_default ,&&_66_0x30_5, &&_66_0x36, &&_default, //0x30-0x37 &&_default, &&_66_0x39, &&_default, &&_66_0x3B, &&_default, &&_66_0x3D, &&_default, &&_default, //0x38-0x3F &&_66_0x40, &&_66_0x41, &&_66_0x42, &&_66_0x43, &&_66_0x44, &&_66_0x45, &&_66_0x46, &&_66_0x47, &&_66_0x48, &&_66_0x49, &&_66_0x4A, &&_66_0x4B, &&_66_0x4C, &&_66_0x4D, &&_66_0x4E, &&_66_0x4F, &&_66_0x50, &&_66_0x51, &&_66_0x52, &&_66_0x53, &&_66_0x54, &&_66_0x55, &&_66_0x56, &&_66_0x57, //0x50-0x57 &&_66_0x58, &&_66_0x59, &&_66_0x5A, &&_66_0x5B, &&_66_0x5C, &&_66_0x5D, &&_66_0x5E, &&_66_0x5F, //0x58-0x5F &&_66_0x60, &&_66_0x61, &&_default, &&_default, &&_default ,&&_default, &&_66_0x66, &&_default, //0x60-0x67 &&_66_0x68, &&_66_0x69, &&_66_0x6A, &&_66_0x6B, &&_default, &&_default, &&_default, &&_default, //0x68-0x6F &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x70-0x77 &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x78-0x7F &&_default, &&_66_0x81, &&_default, &&_66_0x83, &&_default, &&_66_0x85, &&_default, &&_66_0x87, &&_default, &&_66_0x89, &&_default, &&_66_0x8B, &&_66_0x8C, &&_default, &&_66_0x8E, &&_66_0x8F, &&_66_0x90, &&_66_0x91, &&_66_0x92, &&_66_0x93, &&_66_0x94, &&_66_0x95, &&_66_0x96, &&_66_0x97, &&_66_0x98, &&_66_0x99, &&_default, &&_default, &&_66_0x9C, &&_66_0x9D, &&_default, &&_default, //0x98-0x9F &&_default, &&_66_0xA1, &&_default, &&_66_0xA3, &&_default, &&_66_0xA5, &&_default, &&_66_0xA7, &&_default, &&_66_0xA9, &&_default, &&_66_0xAB, &&_default, &&_66_0xAD, &&_default, &&_66_0xAF, //0xA8-0xAF &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xB0-0xB7 &&_66_0xB8, &&_66_0xB9, &&_66_0xBA, &&_66_0xBB, &&_66_0xBC, &&_66_0xBD, &&_66_0xBE, &&_66_0xBF, &&_default, &&_66_0xC1, &&_default, &&_default, &&_default, &&_default, &&_default, &&_66_0xC7, &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xC8-0xCF &&_default, &&_66_0xD1, &&_default, &&_66_0xD3, &&_default, &&_default, &&_default, &&_default, //0xD0-0xD7 &&_default, &&_66_0xD9, &&_default, &&_default, &&_default ,&&_66_0xDD, &&_default, &&_default, //0xD8-0xDF &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xE0-0xE7 &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xE8-0xEF &&_default, &&_default, &&_66_0xF2, &&_66_0xF3, &&_default, &&_default, &&_default, &&_66_0xF7, &&_66_0xF8, &&_66_0xF9, &&_default, &&_default, &&_default, &&_default, &&_default, &&_66_0xFF }; x86emurun: ip = R_EIP; // UnpackFlags(emu); #ifdef HAVE_TRACE _trace: __builtin_prefetch((void*)ip, 0, 0); emu->prev2_ip = emu->prev_ip; emu->prev_ip = R_EIP; R_EIP=ip; if(my_context->dec && ( (trace_end == 0) || ((ip >= trace_start) && (ip < trace_end))) ) PrintTrace(emu, ip, 0); #define NEXT goto _trace #else #define NEXT goto *baseopcodes[(R_EIP=ip, opcode=F8)] #endif #include "modrm.h" opcode = F8; goto *baseopcodes[opcode]; #define GO(B, OP) \ _##B##_0: \ nextop = F8; \ GET_EB; \ EB->byte[0] = OP##8(emu, EB->byte[0], GB); \ NEXT; \ _##B##_1: \ nextop = F8; \ GET_ED; \ ED->dword[0] = OP##32(emu, ED->dword[0], GD.dword[0]); \ NEXT; \ _##B##_2: \ nextop = F8; \ GET_EB; \ GB = OP##8(emu, GB, EB->byte[0]); \ NEXT; \ _##B##_3: \ nextop = F8; \ GET_ED; \ GD.dword[0] = OP##32(emu, GD.dword[0], ED->dword[0]); \ NEXT; \ _##B##_4: \ R_AL = OP##8(emu, R_AL, F8); \ NEXT; \ _##B##_5: \ R_EAX = OP##32(emu, R_EAX, F32); \ NEXT; GO(0x00, add) /* ADD 0x00 -> 0x05 */ GO(0x08, or) /* OR 0x08 -> 0x0D */ GO(0x10, adc) /* ADC 0x10 -> 0x15 */ GO(0x18, sbb) /* SBB 0x18 -> 0x1D */ GO(0x20, and) /* AND 0x20 -> 0x25 */ GO(0x28, sub) /* SUB 0x28 -> 0x2D */ GO(0x30, xor) /* XOR 0x30 -> 0x35 */ //GO(0x38, cmp) /* CMP 0x38 -> 0x3D */ avoid affectation #undef GO _0x38: nextop = F8; GET_EB; cmp8(emu, EB->byte[0], GB); NEXT;
在代码里,能看到开头声明了两个静态数组 baseopcodes[] 和 opcodes0f[] 以及 opcodes66[] ,其内容如下:
static const void* baseopcodes[256] ={ &&_0x00_0, &&_0x00_1, &&_0x00_2, &&_0x00_3, &&_0x00_4, &&_0x00_5, &&_0x06, &&_0x07, //0x00-0x07 &&_0x08_0, &&_0x08_1, &&_0x08_2, &&_0x08_3, &&_0x08_4, &&_0x08_5, &&_0x0E, &&_0x0F, //0x08-0x0F &&_0x10_0, &&_0x10_1, &&_0x10_2, &&_0x10_3, &&_0x10_4, &&_0x10_5, &&_0x16, &&_0x17, //0x10-0x17 &&_0x18_0, &&_0x18_1, &&_0x18_2, &&_0x18_3, &&_0x18_4, &&_0x18_5, &&_0x1E, &&_0x1F, //0x18-0x1F &&_0x20_0, &&_0x20_1, &&_0x20_2, &&_0x20_3, &&_0x20_4, &&_0x20_5, &&_0x26, &&_0x27, //0x20-0x27 &&_0x28_0, &&_0x28_1, &&_0x28_2, &&_0x28_3, &&_0x28_4, &&_0x28_5, &&_0x2E, &&_0x2F, //0x28-0x2F &&_0x30_0, &&_0x30_1, &&_0x30_2, &&_0x30_3, &&_0x30_4, &&_0x30_5, &&_0x36, &&_0x37, //0x30-0x37 &&_0x38, &&_0x39, &&_0x3A, &&_0x3B, &&_0x3C, &&_0x3D, &&_0x3E, &&_0x3F, //0x38-0x3F &&_0x40, &&_0x41, &&_0x42, &&_0x43, &&_0x44, &&_0x45, &&_0x46, &&_0x47, &&_0x48, &&_0x49, &&_0x4A, &&_0x4B, &&_0x4C, &&_0x4D, &&_0x4E, &&_0x4F, &&_0x50, &&_0x51, &&_0x52, &&_0x53, &&_0x54, &&_0x55, &&_0x56, &&_0x57, &&_0x58, &&_0x59, &&_0x5A, &&_0x5B, &&_0x5C, &&_0x5D, &&_0x5E, &&_0x5F, &&_0x60, &&_0x61, &&_0x62, &&_0x63, &&_0x64, &&_0x65, &&_0x66, &&_0x67, &&_0x68, &&_0x69, &&_0x6A, &&_0x6B, &&_0x6C, &&_0x6D, &&_0x6E, &&_0x6F, //0x68-0x6F &&_0x70_0, &&_0x70_1, &&_0x70_2, &&_0x70_3, &&_0x70_4, &&_0x70_5, &&_0x70_6, &&_0x70_7, //0x70-0x77 &&_0x70_8, &&_0x70_9, &&_0x70_A, &&_0x70_B, &&_0x70_C, &&_0x70_D, &&_0x70_E, &&_0x70_F, //0x78-0x7F &&_0x80, &&_0x81, &&_0x82, &&_0x83, &&_0x84, &&_0x85, &&_0x86, &&_0x87, &&_0x88, &&_0x89, &&_0x8A, &&_0x8B, &&_0x8C, &&_0x8D, &&_0x8E, &&_0x8F, &&_0x90, &&_0x91, &&_0x92, &&_0x93, &&_0x94, &&_0x95, &&_0x96, &&_0x97, &&_0x98, &&_0x99, &&_default, &&_0x9B, &&_0x9C, &&_0x9D, &&_0x9E, &&_0x9F, &&_0xA0, &&_0xA1, &&_0xA2, &&_0xA3, &&_0xA4, &&_0xA5, &&_0xA6, &&_0xA7, &&_0xA8, &&_0xA9, &&_0xAA, &&_0xAB, &&_0xAC, &&_0xAD, &&_0xAE, &&_0xAF, &&_0xB0, &&_0xB1, &&_0xB2, &&_0xB3, &&_0xB4, &&_0xB5, &&_0xB6, &&_0xB7, &&_0xB8, &&_0xB9, &&_0xBA, &&_0xBB, &&_0xBC, &&_0xBD, &&_0xBE, &&_0xBF, &&_0xC0, &&_0xC1, &&_0xC2, &&_0xC3, &&_0xC4, &&_0xC5, &&_0xC6, &&_0xC7, &&_0xC8, &&_0xC9, &&_default, &&_0xCB, &&_0xCC, &&_0xCD, &&_default, &&_0xCF, //0xC8-0xCF &&_0xD0, &&_0xD1, &&_0xD2, &&_0xD3, &&_0xD4, &&_0xD5, &&_0xD6, &&_0xD7, &&_0xD8, &&_0xD9, &&_0xDA, &&_0xDB, &&_0xDC, &&_0xDD, &&_0xDE, &&_0xDF, &&_0xE0, &&_0xE1, &&_0xE2, &&_0xE3, &&_0xE4, &&_0xE5, &&_0xE6, &&_0xE7, &&_0xE8, &&_0xE9, &&_default, &&_0xEB, &&_0xEC, &&_0xED, &&_default, &&_default, &&_0xF0, &&_0xF1, &&_0xF2, &&_0xF3, &&_default, &&_0xF5, &&_0xF6, &&_0xF7, &&_0xF8, &&_0xF9, &&_0xFA, &&_0xFB, &&_0xFC, &&_0xFD, &&_0xFE, &&_0xFF }; static const void* opcodes0f[256] = { &&_0f_0x00, &&_0f_0x01, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07 &&_default, &&_default, &&_default, &&_0f_0x0B, &&_default ,&&_default, &&_default, &&_default, //0x08-0x0F &&_0f_0x10, &&_0f_0x11, &&_0f_0x12, &&_0f_0x13, &&_0f_0x14, &&_0f_0x15, &&_0f_0x16, &&_0f_0x17, //0x10-0x17 &&_0f_0x18, &&_default, &&_0f_0x1A, &&_0f_0x1B, &&_default ,&&_default, &&_default, &&_0f_0x1F, //0x18-0x1F &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x20-0x27 &&_0f_0x28, &&_0f_0x29, &&_0f_0x2A, &&_0f_0x2B, &&_0f_0x2C, &&_0f_0x2D, &&_0f_0x2E, &&_0f_0x2F, &&_default, &&_0f_0x31, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x30-0x37 &&_0f_0x38, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x38-0x3F &&_0f_0x40_0, &&_0f_0x40_1, &&_0f_0x40_2, &&_0f_0x40_3, &&_0f_0x40_4, &&_0f_0x40_5, &&_0f_0x40_6, &&_0f_0x40_7, &&_0f_0x40_8, &&_0f_0x40_9, &&_0f_0x40_A, &&_0f_0x40_B, &&_0f_0x40_C, &&_0f_0x40_D, &&_0f_0x40_E, &&_0f_0x40_F, &&_0f_0x50, &&_0f_0x51, &&_0f_0x52, &&_0f_0x53, &&_0f_0x54, &&_0f_0x55, &&_0f_0x56, &&_0f_0x57, //0x50-0x57 &&_0f_0x58, &&_0f_0x59, &&_0f_0x5A, &&_0f_0x5B, &&_0f_0x5C, &&_0f_0x5D, &&_0f_0x5E, &&_0f_0x5F, &&_0f_0x60, &&_0f_0x61, &&_0f_0x62, &&_0f_0x63, &&_0f_0x64 ,&&_0f_0x65, &&_0f_0x66, &&_0f_0x67, //0x60-0x67 &&_0f_0x68, &&_0f_0x69, &&_0f_0x6A, &&_0f_0x6B, &&_default ,&&_default, &&_0f_0x6E, &&_0f_0x6F, //0x68-0x6F &&_0f_0x70, &&_0f_0x71, &&_0f_0x72, &&_0f_0x73, &&_0f_0x74 ,&&_0f_0x75, &&_0f_0x76, &&_0f_0x77, //0x70-0x77 &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_0f_0x7E, &&_0f_0x7F, //0x78-0x7F &&_0f_0x80_0, &&_0f_0x80_1, &&_0f_0x80_2, &&_0f_0x80_3, &&_0f_0x80_4, &&_0f_0x80_5, &&_0f_0x80_6, &&_0f_0x80_7, &&_0f_0x80_8, &&_0f_0x80_9, &&_0f_0x80_A, &&_0f_0x80_B, &&_0f_0x80_C, &&_0f_0x80_D, &&_0f_0x80_E, &&_0f_0x80_F, &&_0f_0x90_0, &&_0f_0x90_1, &&_0f_0x90_2, &&_0f_0x90_3, &&_0f_0x90_4, &&_0f_0x90_5, &&_0f_0x90_6, &&_0f_0x90_7, &&_0f_0x90_8, &&_0f_0x90_9, &&_0f_0x90_A, &&_0f_0x90_B, &&_0f_0x90_C, &&_0f_0x90_D, &&_0f_0x90_E, &&_0f_0x90_F, &&_0f_0xA0, &&_0f_0xA1, &&_0f_0xA2, &&_0f_0xA3, &&_0f_0xA4, &&_0f_0xA5, &&_default, &&_default, //0xA0-0xA7 &&_0f_0xA8, &&_0f_0xA9, &&_default, &&_0f_0xAB, &&_0f_0xAC, &&_0f_0xAD, &&_0f_0xAE, &&_0f_0xAF, &&_0f_0xB0, &&_0f_0xB1, &&_default, &&_0f_0xB3, &&_default, &&_default, &&_0f_0xB6, &&_0f_0xB7, &&_default, &&_default, &&_0f_0xBA, &&_0f_0xBB, &&_0f_0xBC, &&_0f_0xBD, &&_0f_0xBE, &&_0f_0xBF, &&_0f_0xC0, &&_0f_0xC1, &&_0f_0xC2, &&_0f_0xC3, &&_0f_0xC4, &&_0f_0xC5, &&_0f_0xC6, &&_0f_0xC7, &&_0f_0xC8, &&_0f_0xC9, &&_0f_0xCA, &&_0f_0xCB, &&_0f_0xCC, &&_0f_0xCD, &&_0f_0xCE, &&_0f_0xCF, //0xC8-0xCF &&_default, &&_0f_0xD1, &&_0f_0xD2, &&_0f_0xD3, &&_0f_0xD4 ,&&_0f_0xD5, &&_default, &&_0f_0xD7, //0xD0-0xD7 &&_0f_0xD8, &&_0f_0xD9, &&_default, &&_0f_0xDB, &&_0f_0xDC ,&&_0f_0xDD, &&_default, &&_0f_0xDF, //0xD8-0xDF &&_0f_0xE0, &&_0f_0xE1, &&_0f_0xE2, &&_0f_0xE3, &&_0f_0xE4 ,&&_0f_0xE5, &&_default, &&_0f_0xE7, //0xE0-0xE7 &&_0f_0xE8, &&_0f_0xE9, &&_0f_0xEA, &&_0f_0xEB, &&_0f_0xEC ,&&_0f_0xED, &&_0f_0xEE, &&_0f_0xEF, //0xE8-0xEF &&_default, &&_0f_0xF1, &&_0f_0xF2, &&_0f_0xF3, &&_0f_0xF4 ,&&_0f_0xF5, &&_0f_0xF6, &&_0f_0xF7, //0xF0-0xF7 &&_0f_0xF8, &&_0f_0xF9, &&_0f_0xFA, &&_default, &&_0f_0xFC ,&&_0f_0xFD, &&_0f_0xFE, &&_default //0xF8-0xFF }; static const void* opcodes66[256] = { &&_default, &&_66_0x00_1, &&_default, &&_66_0x00_3, &&_default ,&&_66_0x00_5, &&_66_0x06, &&_66_0x07, //0x00-0x07 &&_default, &&_66_0x08_1, &&_default, &&_66_0x08_3, &&_default ,&&_66_0x08_5, &&_default, &&_66_0x0F, //0x08-0x0F &&_default, &&_66_0x10_1, &&_default, &&_66_0x10_3, &&_default ,&&_66_0x10_5, &&_default, &&_default, //0x10-0x17 &&_default, &&_66_0x18_1, &&_default, &&_66_0x18_3, &&_default ,&&_66_0x18_5, &&_default, &&_default, //0x18-0x1F &&_default, &&_66_0x20_1, &&_default, &&_66_0x20_3, &&_default ,&&_66_0x20_5, &&_66_0x26, &&_default, //0x20-0x27 &&_default, &&_66_0x28_1, &&_default, &&_66_0x28_3, &&_default ,&&_66_0x28_5, &&_66_0x2E, &&_default, //0x28-0x2F &&_default, &&_66_0x30_1, &&_default, &&_66_0x30_3, &&_default ,&&_66_0x30_5, &&_66_0x36, &&_default, //0x30-0x37 &&_default, &&_66_0x39, &&_default, &&_66_0x3B, &&_default, &&_66_0x3D, &&_default, &&_default, //0x38-0x3F &&_66_0x40, &&_66_0x41, &&_66_0x42, &&_66_0x43, &&_66_0x44, &&_66_0x45, &&_66_0x46, &&_66_0x47, &&_66_0x48, &&_66_0x49, &&_66_0x4A, &&_66_0x4B, &&_66_0x4C, &&_66_0x4D, &&_66_0x4E, &&_66_0x4F, &&_66_0x50, &&_66_0x51, &&_66_0x52, &&_66_0x53, &&_66_0x54, &&_66_0x55, &&_66_0x56, &&_66_0x57, //0x50-0x57 &&_66_0x58, &&_66_0x59, &&_66_0x5A, &&_66_0x5B, &&_66_0x5C, &&_66_0x5D, &&_66_0x5E, &&_66_0x5F, //0x58-0x5F &&_66_0x60, &&_66_0x61, &&_default, &&_default, &&_default ,&&_default, &&_66_0x66, &&_default, //0x60-0x67 &&_66_0x68, &&_66_0x69, &&_66_0x6A, &&_66_0x6B, &&_default, &&_default, &&_default, &&_default, //0x68-0x6F &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x70-0x77 &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x78-0x7F &&_default, &&_66_0x81, &&_default, &&_66_0x83, &&_default, &&_66_0x85, &&_default, &&_66_0x87, &&_default, &&_66_0x89, &&_default, &&_66_0x8B, &&_66_0x8C, &&_default, &&_66_0x8E, &&_66_0x8F, &&_66_0x90, &&_66_0x91, &&_66_0x92, &&_66_0x93, &&_66_0x94, &&_66_0x95, &&_66_0x96, &&_66_0x97, &&_66_0x98, &&_66_0x99, &&_default, &&_default, &&_66_0x9C, &&_66_0x9D, &&_default, &&_default, //0x98-0x9F &&_default, &&_66_0xA1, &&_default, &&_66_0xA3, &&_default, &&_66_0xA5, &&_default, &&_66_0xA7, &&_default, &&_66_0xA9, &&_default, &&_66_0xAB, &&_default, &&_66_0xAD, &&_default, &&_66_0xAF, //0xA8-0xAF &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xB0-0xB7 &&_66_0xB8, &&_66_0xB9, &&_66_0xBA, &&_66_0xBB, &&_66_0xBC, &&_66_0xBD, &&_66_0xBE, &&_66_0xBF, &&_default, &&_66_0xC1, &&_default, &&_default, &&_default, &&_default, &&_default, &&_66_0xC7, &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xC8-0xCF &&_default, &&_66_0xD1, &&_default, &&_66_0xD3, &&_default, &&_default, &&_default, &&_default, //0xD0-0xD7 &&_default, &&_66_0xD9, &&_default, &&_default, &&_default ,&&_66_0xDD, &&_default, &&_default, //0xD8-0xDF &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xE0-0xE7 &&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xE8-0xEF &&_default, &&_default, &&_66_0xF2, &&_66_0xF3, &&_default, &&_default, &&_default, &&_66_0xF7, &&_66_0xF8, &&_66_0xF9, &&_default, &&_default, &&_default, &&_default, &&_default, &&_66_0xFF };
这些静态数组变量中存放的都是以 && 开头的成员,而在 C 语言中 && 是表明后面跟随的东西是一个标号,具体可参考:
X86指令解析
所以在后面用到的其中一个用法是:
#define F8 *(uint8_t*)(ip++) opcode = F8; goto *baseopcodes[opcode];
这里的 ip 其实就是作为指令地址存在,每次取指后都会自动加一指向下一行指令,而当前取出的指令的第一个字节( *(uint8_t*) )会赋值给 opcode ,然后调用 goto 语句跳转到 *baseopcodes[opcode] 对应的标号下去执行。
比如,如果 ip 第一个字节的数据取出来是 0xF8 ,则会对应跳转到下面部分去执行,这是一个清除进位标志的操作( CLC )
_0xF8: /* CLC *///清除进位标志位 CHECK_FLAGS(emu); CLEAR_FLAG(F_CF); NEXT;
跳转系统调用函数实现:x86Syscall(emu);
通过对 Run() 函数的简单理解,已经基本明白了 Box86 是如何去翻译 x86 可执行程序的了。Box86 将 x86 可执行程序的二进制读取进来,根据 x86 二进制指令格式进行解析,将其分析成对应的操作动作去工作。但是在 Linux 下,除了基本的内存读写操作、加减数据等等基本操作外,还会遇到调用系统调用函数的部分。具体流程可以参考下面这篇文章
Linux内核:基于int指令的经典系统调用过程分析
在 Box86 中,同样的,当指令解析到 int 0x80 这条指令的时候,就会跳转到自己的 x86Syscall(emu); 去执行对应的系统调用,具体如下:
_0xCD: /* INT Ib */ nextop = F8; if(nextop == 0x80) { emu->old_ip = R_EIP; R_EIP = ip; x86Syscall(emu); ip = R_EIP; if(emu->quit) goto fini; } else { int tid = GetTID(); printf_log(LOG_NONE, "%04d|%p: Ignoring Unsupported Int %02Xh\n", tid, (void*)ip, nextop); emu->old_ip = R_EIP; R_EIP = ip; emu->quit = 1; emu->error |= ERR_UNIMPL; goto fini; } NEXT;
而 x86Syscall(emu); 函数的具体实现如下,将可以用当前环境的操作还是调用当前环境的函数去实现,而会导致环境不一致的情况时就调用自己封装的对应函数去实现。
void EXPORT x86Syscall(x86emu_t *emu) { RESET_FLAGS(emu); uint32_t s = R_EAX; printf_log(LOG_DEBUG, "%p: Calling syscall 0x%02X (%d) %p %p %p %p %p", (void*)R_EIP, s, s, (void*)R_EBX, (void*)R_ECX, (void*)R_EDX, (void*)R_ESI, (void*)R_EDI); // check wrapper first int cnt = sizeof(syscallwrap) / sizeof(scwrap_t); for (int i=0; i<cnt; i++) { if(syscallwrap[i].x86s == s) { int sc = syscallwrap[i].nats; switch(syscallwrap[i].nbpars) { case 0: *(int32_t*)&R_EAX = syscall(sc); break; case 1: *(int32_t*)&R_EAX = syscall(sc, R_EBX); break; case 2: if(s==33) {printf_log(LOG_DUMP, " => sys_access(\"%s\", %d)\n", (char*)R_EBX, R_ECX);}; *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX); break; case 3: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX); break; case 4: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI); break; case 5: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI); break; case 6: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP); break; default: printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[i].nbpars); emu->quit = 1; return; } printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX); return; } } switch (s) { case 1: // sys_exit emu->quit = 1; emu->exit = 1; R_EAX = R_EBX; // faking the syscall here, we don't want to really terminate the program now break; case 3: // sys_read R_EAX = (uint32_t)read((int)R_EBX, (void*)R_ECX, (size_t)R_EDX); break; case 4: // sys_write R_EAX = (uint32_t)write((int)R_EBX, (void*)R_ECX, (size_t)R_EDX); break; case 5: // sys_open if(s==5) {printf_log(LOG_DEBUG, " => sys_open(\"%s\", %d, %d)", (char*)R_EBX, of_convert(R_ECX), R_EDX);}; //R_EAX = (uint32_t)open((void*)R_EBX, of_convert(R_ECX), R_EDX); R_EAX = (uint32_t)my_open(emu, (void*)R_EBX, of_convert(R_ECX), R_EDX); break; case 6: // sys_close R_EAX = (uint32_t)close((int)R_EBX); break; #ifndef __NR_waitpid case 7: //sys_waitpid R_EAX = waitpid((pid_t)R_EBX, (int*)R_ECX, (int)R_EDX); break; #endif case 11: // sys_execve { char* prog = (char*)R_EBX; char** argv = (char**)R_ECX; char** envv = (char**)R_EDX; printf_log(LOG_DUMP, " => sys_execve(\"%s\", %p(\"%s\", \"%s\", \"%s\"...), %p)\n", prog, argv, (argv && argv[0])?argv[0]:"nil", (argv && argv[0] && argv[1])?argv[1]:"nil", (argv && argv[0] && argv[1] && argv[2])?argv[2]:"nil", envv); R_EAX = my_execve(emu, (const char*)R_EBX, (void*)R_ECX, (void*)R_EDX); } break; #ifndef __NR_time case 13: // sys_time (it's deprecated and remove on ARM EABI it seems) R_EAX = time(NULL); break; #endif case 54: // sys_ioctl R_EAX = (uint32_t)ioctl((int)R_EBX, R_ECX, R_EDX, R_ESI, R_EDI); break; case 55: // sys_fcntl if(R_ECX==4) { // filter out O_NONBLOCK so old stacally linked games that access X11 don't get EAGAIN error sometimes int tmp = of_convert((int)R_EDX)&(~O_NONBLOCK); if(R_EDX==0xFFFFF7FF) { // special case for ~O_NONBLOCK... int flags = fcntl(R_EBX, 3); tmp = flags&~O_NONBLOCK; } R_EAX = (uint32_t)fcntl((int)R_EBX, (int)R_ECX, tmp); } else R_EAX = (uint32_t)fcntl((int)R_EBX, (int)R_ECX, R_EDX); break; #ifndef __NR_getrlimit case 76: // sys_getrlimit... this is the old version, using the new one. Maybe some tranform is needed? R_EAX = getrlimit(R_EBX, (void*)R_ECX); break; #endif #ifndef __NR_select case 82: // select R_EAX = select(R_EBX, (fd_set*)R_ECX, (fd_set*)R_EDX, (fd_set*)R_ESI, (struct timeval*)R_EDI); break; #endif case 90: // old_mmap { struct mmap_arg_struct *st = (struct mmap_arg_struct*)R_EBX; R_EAX = (uintptr_t)mmap((void*)st->addr, st->len, st->prot, st->flags, st->fd, st->offset); } break; #ifndef __NR_socketcall case 102: { unsigned long *args = (unsigned long *)R_ECX; // need to do all call "by hand" switch(R_EBX) { case SYS_SOCKET: R_EAX = socket(args[0], args[1], args[2]); break; case SYS_BIND: R_EAX = bind(args[0], (void*)args[1], args[2]); break; case SYS_CONNECT: R_EAX = connect(args[0], (void*)args[1], args[2]); break; case SYS_LISTEN: R_EAX = listen(args[0], args[1]); break; case SYS_ACCEPT: R_EAX = accept(args[0], (void*)args[1], (void*)args[2]); break; case SYS_GETSOCKNAME: R_EAX = getsockname(args[0], (void*)args[1], (void*)args[2]); break; case SYS_GETPEERNAME: R_EAX = getpeername(args[0], (void*)args[1], (void*)args[2]); break; case SYS_SOCKETPAIR: R_EAX = socketpair(args[0], args[1], args[2], (int*)args[3]); break; case SYS_SEND: R_EAX = send(args[0], (void*)args[1], args[2], args[3]); break; case SYS_RECV: R_EAX = recv(args[0], (void*)args[1], args[2], args[3]); break; case SYS_SENDTO: R_EAX = sendto(args[0], (void*)args[1], args[2], args[3], (void*)args[4], args[5]); break; case SYS_RECVFROM: R_EAX = recvfrom(args[0], (void*)args[1], args[2], args[3], (void*)args[4], (void*)args[5]); break; case SYS_SHUTDOWN: R_EAX = shutdown(args[0], args[1]); break; case SYS_SETSOCKOPT: R_EAX = setsockopt(args[0], args[1], args[2], (void*)args[3], args[4]); break; case SYS_GETSOCKOPT: R_EAX = getsockopt(args[0], args[1], args[2], (void*)args[3], (void*)args[4]); break; case SYS_SENDMSG: R_EAX = sendmsg(args[0], (void*)args[1], args[2]); break; case SYS_RECVMSG: R_EAX = recvmsg(args[0], (void*)args[1], args[2]); break; case SYS_ACCEPT4: R_EAX = my_accept4(emu, args[0], (void*)args[1], (void*)args[2], args[3]); break; #ifdef SYS_RECVMMSG case SYS_RECVMMSG: R_EAX = my_recvmmsg(emu, args[0], (void*)args[1], args[2], args[3], (void*)args[4]); break; case SYS_SENDMMSG: R_EAX = my___sendmmsg(emu, args[0], (void*)args[1], args[2], args[3]); break; #endif default: printf_log(LOG_DEBUG, "BOX86 Error on Syscall 102: Unknown Soket command %d\n", R_EBX); R_EAX = -1; } } break; #endif #ifndef __NR_olduname case 109: // olduname { struct utsname un; R_EAX = uname(&un); if(!R_EAX) { struct oldold_utsname *old = (struct oldold_utsname*)R_EBX; memcpy(old->sysname, un.sysname, 9); memcpy(old->nodename, un.nodename, 9); memcpy(old->release, un.release, 9); memcpy(old->version, un.version, 9); strcpy(old->machine, "i686"); } } break; #endif #ifndef __NR_iopl case 110: // iopl R_EAX = 0; // only on x86, so return 0... break; #endif case 119: // sys_sigreturn emu->quit = 1; // we should be inside a DynaCall in a sigaction callback.... break; case 120: // clone { //struct x86_pt_regs *regs = (struct x86_pt_regs *)R_EDI; // lets duplicate the emu void* stack_base = (void*)R_ECX; int stack_size = 0; if(!R_ECX) { // allocate a new stack... stack_size = 1024*1024; stack_base = malloc(stack_size); // why not 1M... (normal operation do copy on write, simpler to just copy) // copy value from old stack to new stack int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_ESP); memcpy(stack_base-size_to_copy, (void*)R_ESP, size_to_copy); } x86emu_t * newemu = NewX86Emu(emu->context, R_EIP, (uintptr_t)stack_base, stack_size, (R_ECX)?0:1); SetupX86Emu(newemu); CloneEmu(newemu, emu); SetESP(newemu, (uintptr_t)stack_base); // setup registers /*if(regs) { SetEAX(newemu, regs->eax); SetEBX(newemu, regs->ebx); SetECX(newemu, regs->ecx); SetEDX(newemu, regs->edx); SetEDI(newemu, regs->edi); SetESI(newemu, regs->esi); SetEBP(newemu, regs->ebp); SetESP(newemu, (uintptr_t)stack_base - size_to_copy); } SetESP(newemu, (uintptr_t)stack_base - size_to_copy);*/ void* mystack = (R_EBX&CLONE_VM)?malloc(1024*1024):NULL; // stack for own process... memory leak, but no practical way to remove it int ret = clone(clone_fn, (void*)((R_EBX&CLONE_VM)?((uintptr_t)mystack+1024*1024):0), R_EBX, newemu, R_ESI, R_EDI, R_EBP); //int r = syscall(__NR_clone, R_EBX, (R_EBX&CLONE_VM)?((uintptr_t)mystack):0, R_EDX, R_ESI, NULL); // cannot use that syscall in C: how to setup the stack?! R_EAX = ret; } break; case 122: // uname { struct utsname un; R_EAX = uname(&un); if(!R_EAX) { struct old_utsname *old = (struct old_utsname*)R_EBX; memcpy(old->sysname, un.sysname, 65); memcpy(old->nodename, un.nodename, 65); memcpy(old->release, un.release, 65); memcpy(old->version, un.version, 65); strcpy(old->machine, "i686"); } } break; case 123: // SYS_modify_ldt R_EAX = my_modify_ldt(emu, R_EBX, (thread_area_t*)R_ECX, R_EDX); break; case 168: // sys_poll R_EAX = (uint32_t)poll((void*)R_EBX, R_ECX, (int)R_EDX); break; case 173: // sys_rt_sigreturn emu->quit = 1; // we should be inside a DynaCall in a sigaction callback.... break; case 174: // sys_rt_sigaction //printf_log(LOG_NONE, "Warning, Ignoring sys_rt_sigaction(0x%02X, %p, %p)\n", R_EBX, (void*)R_ECX, (void*)R_EDX); R_EAX = my_syscall_sigaction(emu, R_EBX, (void*)R_ECX, (void*)R_EDX, R_ESI); break; case 190: // vfork { int r = vfork(); R_EAX = r; } break; case 195: // stat64 { struct stat64 st; unsigned int r = syscall(__NR_stat64, R_EBX, &st); UnalignStat64(&st, (void*)R_ECX); R_EAX = r; } break; case 196: // lstat64 { struct stat64 st; unsigned int r = syscall(__NR_lstat64, R_EBX, &st); UnalignStat64(&st, (void*)R_ECX); R_EAX = r; } break; case 197: // fstat64 { struct stat64 st; unsigned int r = syscall(__NR_fstat64, R_EBX, &st); UnalignStat64(&st, (void*)R_ECX); R_EAX = r; } break; case 221: // sys_fcntl64 if(R_ECX==4) { int tmp = of_convert((int)R_EDX); R_EAX = (uint32_t)fcntl((int)R_EBX, R_ECX, tmp); } else R_EAX = (uint32_t)fcntl((int)R_EBX, (int)R_ECX, R_EDX); break; case 243: // set_thread_area R_EAX = my_set_thread_area((thread_area_t*)R_EBX); break; #ifndef NOALIGN case 254: // epoll_create R_EAX = my_epoll_create(emu, (int)R_EBX); break; case 255: // epoll_ctl R_EAX = my_epoll_ctl(emu, (int)R_EBX, (int)R_ECX, (int)R_EDX, (void*)R_ESI); break; case 256: // epoll_wait R_EAX = my_epoll_wait(emu, (int)R_EBX, (void*)R_ECX, (int)R_EDX, (int)R_ESI); break; #endif case 270: // tgkill R_EAX = syscall(__NR_tgkill, R_EBX, R_ECX, R_EDX); break; #ifndef NOALIGN case 329: // epoll_create1 R_EAX = my_epoll_create1(emu, of_convert(R_EBX)); break; #endif #ifndef __NR_getrandom case 355: // getrandom R_EAX = my_getrandom(emu, (void*)R_EBX, R_ECX, R_EDX); break; #endif default: printf_log(LOG_INFO, "Error: Unsupported Syscall 0x%02Xh (%d)\n", s, s); emu->quit = 1; emu->error |= ERR_UNIMPL; return; } printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX); }
封装对应的函数实现的例子如下:
EXPORT int my_epoll_create(x86emu_t* emu, int size) { return epoll_create(size); } EXPORT int my_epoll_create1(x86emu_t* emu, int flags) { return epoll_create1(flags); } EXPORT int32_t my_epoll_ctl(x86emu_t* emu, int32_t epfd, int32_t op, int32_t fd, void* event) { struct epoll_event _event[1] = {0}; if(event && (op!=EPOLL_CTL_DEL)) AlignEpollEvent(_event, event, 1); return epoll_ctl(epfd, op, fd, event?_event:event); } EXPORT int32_t my_epoll_wait(x86emu_t* emu, int32_t epfd, void* events, int32_t maxevents, int32_t timeout) { struct epoll_event _events[maxevents]; AlignEpollEvent(_events, events, maxevents); int32_t ret = epoll_wait(epfd, _events, maxevents, timeout); if(ret>0) UnalignEpollEvent(events, _events, ret); return ret; }
总结
接下来分析 Box86 的几部分重点内容:
动态指令翻译的过程
具体 X86 指令(opcode)参考 opcode
举例说明:
这里的 opcode X86 指令解析可参考 opcode解析 这篇博客,这里详细说明的 opcode 机器码的几个部分和解析流程。参考刚刚给出的 x86 opcode 查找表能够根据机器码前缀 66 、0F等数据最终找到当前要翻译执行的指令码。可以查找 GitHub 上有关汇编代码的项目来查找对应的指令和描述及需要解析的操作。
asm-dude ,在该项目中的 wiki 界面能够查到出错或者翻译执行的指令,如下界面:
从这里能够看到,指令 PALIGNR 就是 66 0F 4A 0F 或者 NP 0F 3A 0F 操作码对应的指令操作。这条指令通过阅读后面的描述可以知道是拼接后面两个寄存器的数据,并右移立即数[imm8]个字节数,将最终的数据存放到目标寄存器中。
了解到当前执行出错或者缺少的指令翻译后,我们可以将对应的操作添加到 box86 的对应位置中去。其中模拟器版本的操作存放在 emu/x86run.c emu/run0f.c emu/run660f.c 等文件中,根据指令首字节的数据分别找到对应的 0F 或者 66中的对应位置。而寄存器版本(对应使用arm操作指令的版本)操作就需要添加到 dynerec/dynerec_arm_00.c dynerec/dynerec_arm_0f.c dynerec/deynrec_arm_660f.c 这些文件中的对应位置去。
底层调用库接口使用流程
Box86 使用动态库有两种方式,
- 使用 BOX86_LD_LIBRARY_PATH 环境变量指定的 i386 架构的动态库,这样的库在运行过程中其实是处于再次动态翻译执行的方式去读取调用的。
- 另一种就是会去读取 ARM 机器上本地的一些库,但是在使用过程中其实是 box86 本身基于这些库的接口使用 dlopen 、dlsym等动态调用接口去读取本地动态库并使用的,虽然接口需要编写实现,但是使用过程中却不需要再次进行指令翻译,因为本身这些库就是 ARM 版本的本地库。
第一种方式其实就是指定环境变量到提供的 i386 动态库路径即可,这没什么可说的。最主要是第二种方式。
这里关于第二种方式能够本地调用的库的明细其实都写在 Box86 源码中的 src/library_list.h 文件中,根据宏 GO 会去自动生成对应的库接口 init等等调用接口,并自动调用 dlopen 打开对应的本地动态库,并且通过事先编辑好的接口函数去调用 dlsym 去获取需要调用的接口函数并使用。这样的话,当我们需要对 Box86 添加 ARM 本地动态库接口时,只需要在 src/wrapped/ 目录下添加对应的接口文件,具体编写可以参考下面的两个文件:
wrappedicon_private.c 文件添加的需要调用的本地动态库名称 iconvName =
"libiconv.so.2"; 。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define _GNU_SOURCE /* See feature_test_macros(7) */ #include <dlfcn.h> #include "wrappedlibs.h" #include "wrapper.h" #include "bridge.h" #include "librarian/library_private.h" #include "x86emu.h" const char* iconvName = "libiconv.so.2"; #define LIBNAME iconv #include "wrappedlib_init.h"
wrappedicon_private.h 文件,这里的 GO 宏就是为了指出需要用该动态库的哪些 API ,通过这个宏声明就会自动调用 dlsym 去从动态库中获取对应的函数接口。
#if !(defined(GO) && defined(GOM) && defined(GO2) && defined(DATA)) #error Meh.... #endif GO(iconv_canonicalize, pFp) GO(libiconv, uFppppp) GO(libiconv_close, iFp) GO(libiconv_open, pFpp) GO(libiconv_open_into, iFppp) GO(libiconv_set_relocation_prefix, vFpp) GO(libiconvctl, iFpip) //GO(libiconvlist, vFpp) // this one have callbacks
以上这些添加完成后,需要在 src/library_list.h 文件中添加对应动态库调用的声明,如下:
GO("libSM.so.6", libsm) GO("libICE.so.6", libice) GO("libusb-1.0.so.0", libusb1) GO("libncursesw.so.5", libncursesw) GO("libformw.so.5", libformw) GO("libncurses.so.5", libncurses) GO("libtinfo.so.5", libtinfo) GO("libncurses.so.6", libncurses6) GO("libtinfo.so.6", libtinfo6) GO("libtcmalloc_minimal.so.4", tcmallocminimal) GO("libmpg123.so.0", mpg123) GO("libgnutls.so.30", gnutls) GO("libcups.so.2", libcups) GO("d3dadapter9.so.1", d3dadapter9)
关于 Box86 的一些操作,就先描述到这里,如果还有需要了解的部分,可以在评论里告诉我啊,我会尽快添加的。😃