/* XXX: exporting this so drwrap can use it but I might prefer to have * this in drutil or the upcoming drsys */ DR_EXPORT int drmgr_decode_sysnum_from_wrapper(app_pc entry) { void *drcontext = dr_get_current_drcontext(); int num = -1; byte *pc = entry; uint opc; instr_t instr; instr_init(drcontext, &instr); do { instr_reset(drcontext, &instr); pc = decode(drcontext, pc, &instr); if (!instr_valid(&instr)) break; /* unknown system call sequence */ opc = instr_get_opcode(&instr); /* sanity check: wrapper should be short */ if (pc - entry > 20) break; /* unknown system call sequence */ if (opc == OP_mov_imm && opnd_is_reg(instr_get_dst(&instr, 0)) && opnd_get_reg(instr_get_dst(&instr, 0)) == DR_REG_EAX && opnd_is_immed_int(instr_get_src(&instr, 0))) { num = (int) opnd_get_immed_int(instr_get_src(&instr, 0)); break; /* success */ } /* stop at call to vsyscall (wow64) or at int itself */ } while (opc != OP_call_ind && opc != OP_int && opc != OP_sysenter && opc != OP_syscall); instr_free(drcontext, &instr); return num; }
void memory_write(void *pc, void *prev_pc) { void *drcontext = dr_get_current_drcontext(); instr_t *instr = instr_create(drcontext); dr_mcontext_t mctx; opnd_t dst; ctx_t ctx; pc = dr_app_pc_for_decoding(pc); mctx.flags = DR_MC_CONTROL|DR_MC_INTEGER; mctx.size = sizeof(mctx); dr_get_mcontext(drcontext, &mctx); instr_init(drcontext, instr); if (!decode(drcontext, pc, instr)) { dr_printf("Decode of instruction at %p failed\n", pc); return; } ctx.addr = prev_pc; ctx.dr_addr = prev_pc; for (int i = 0; i < instr_num_dsts(instr); i++) { dst = instr_get_dst(instr, i); check_opnd(dst, pc, 0, drcontext, &mctx, &ctx); } instr_destroy(drcontext, instr); }
static app_pc get_function_entry(app_pc C_var) { void *drcontext = dr_get_current_drcontext(); byte *pc; instr_t inst; instr_init(drcontext, &inst); pc = decode(drcontext, C_var, &inst); ASSERT(pc != NULL, "invalid instr at function entry"); if (instr_get_opcode(&inst) == OP_jmp) { /* skip jmp in ILT */ ASSERT(opnd_is_pc(instr_get_target(&inst)), "decoded jmp should have pc tgt"); pc = opnd_get_pc(instr_get_target(&inst)); } else pc = C_var; instr_free(drcontext, &inst); return pc; }
static void test_strict_invalid(void *dc) { instr_t instr; byte *pc; const byte buf[] = { 0xf2, 0x0f, 0xd8, 0xe9 }; /* psubusb w/ invalid prefix */ instr_init(dc, &instr); /* The instr should be valid by default and invalid if decode_strict */ pc = decode(dc, (byte *)buf, &instr); ASSERT(pc != NULL); disassemble_set_syntax(DR_DISASM_STRICT_INVALID); instr_reset(dc, &instr); pc = decode(dc, (byte *)buf, &instr); ASSERT(pc == NULL); instr_free(dc, &instr); }
void Shade::disassemble_code(void *code, void *target, size_t size) { instr_t instr; byte *pos = (byte *)code; byte *stop = (byte *)code + size; while(pos < stop) { instr_init(0, &instr); byte *next = decode_from_copy(0, pos, (byte *)target + (pos - (byte *)code), &instr); print_instr(pos - (byte *)code + (byte *)target, &instr); pos = next; instr_free(0, &instr); } }
int main(int argc, char *argv[]) { FILE *fp,*opfp,*testf; int test,n,c,ln,i,m,m1,m2,b,flag=0,flag1=1,len,last,first,dig,id,errorflag=0,flen=0; long int madd=0000000,mm=1048575; label lbl[10]; char ch,*nem[4],*str,*token,*token1,*token2,*token3,*s=" ",state,c1; str = (char *)malloc(sizeof(char)*50); token1 = (char *)malloc(sizeof(char)*10); token2 = (char *)malloc(sizeof(char)*20); token3 = (char *)malloc(sizeof(char)*20); //printf("file name %s\n", argv[1]); fp = fopen(argv[1],"r"); // opens input file which contains assembly code testf = fopen(argv[1],"r"); opfp = fopen("stable.txt","w"); if( fp == NULL ) { perror("Error while opening the file.\n"); exit(EXIT_FAILURE); } for(m1=0;m1<10;m1++) { lbl[m1].labels = (char *)malloc(sizeof(char)*10); } register_init(); instr_init(); for (c1 = getc(testf); c1 != EOF; c1 = getc(testf)){ if (c1 == '\n') // Increment count if this character is newline flen++; } fclose(testf); //printf("--%d--",flen); while( fgets(str,50,fp)!=NULL) //line reading { state='X'; if(flen==l){ strcat(str,"\0"); } if((str!="")&&((flen!=l))) str[strlen(str)-1]='\0'; if(strcmp(str,"")==0) strcpy(str,"BLANK LINE"); if(l==0) { if(strlen(str)!=5) { printf("error in line : %d",l+1); errorflag=1; } strncpy(token1,str,5);//printf( "==%s",token1 ); if(strcmp(token1,(ins[0].nemo))!=0) { printf("error in line : %d",l+1); errorflag=1; } } if(l>0) { //printf( "%00000007ld\t\t%s\n",madd,str ); madd+=32; state='X'; token = strtok(str,s); // instruction name len=strlen(token); last=token[len-1]; if(last==58) { token[strlen(token)-1]='\0';//printf("--%s\n",token); strcpy(lbl[lb].labels,token); lbl[lb].mad=(madd-32); lb++; token = strtok(NULL,s); } while( token != NULL ) { for(b=1;b<=4;b++) // data transfer (MOV) { if(strcmp(token,(ins[b].nemo))==0) { state='T'; break; } } for(b=5;b<=8;b++) // direct address { if(strcmp(token,(ins[b].nemo))==0) { state='I'; break; } } for(b=9;b<=15;b++) // arithmatic instruction and AND { if(strcmp(token,(ins[b].nemo))==0) { state='A'; id=b; break; } } for(b=16;b<=18;b++) // OR types { if(strcmp(token,(ins[b].nemo))==0) { id=b; state='O'; break; } } for(b=19;b<=20;b++) // NOT { if(strcmp(token,(ins[b].nemo))==0) { state='N'; break; } } for(b=21;b<=26;b++) // type INS r1 { if(strcmp(token,(ins[b].nemo))==0) { state='R'; break; } } if(strcmp(token,(ins[27].nemo))==0) // compare CMP { state='P'; } for(b=28;b<=36;b++) // branching instruction { if(strcmp(token,(ins[b].nemo))==0) { state='B'; break; } } for(b=37;b<=40;b++) // machine control instruction { if(strcmp(token,(ins[b].nemo))==0) { state='C'; } } switch(state) { case 'A': flag1=0; token = strtok(NULL,s); // 1st token if(token!=NULL){ for(m=0;m<64;m++) { if((strcmp(token,regs[m].regi)==0)) { regs[m].used=0; token = strtok(NULL,s); // 2nd token if(token!=NULL){ if((token[0]==91)&&(id!=13)&&(token[strlen(token)-1]==93)) { flag1=1; token++; token[strlen(token)-1]='\0'; token2 = strtok(NULL,s); if(token2 != NULL){ state='X'; break; } } for(m1=0;m1<64;m1++) { if((strcmp(token,regs[m1].regi)==0)) { regs[m1].used=0; if(flag1==1) state='F'; token = strtok(NULL,s);// 3rd token if((token==NULL)&&(id==13)) state='X'; if((token!=NULL)){ for(m2=0;m2<64;m2++){ if((strcmp(token,regs[m2].regi)==0)){ regs[m2].used=0; state='F'; break; } else{ flag=0; state='X'; } } token = strtok(NULL,s); if(token!=NULL){state='X';break;} } break; } } }break; } } } break; case 'T': token = strtok(NULL,s); // 1st token if(token!=NULL){ if(token[0]==91) { if(token[strlen(token)-1]!=93) { state='X'; } token++; token[strlen(token)-1]='\0'; } for(m=0;m<64;m++) { if((strcmp(token,regs[m].regi)==0)) { regs[m].used=0; token = strtok(NULL,s); // 2nd token if(token!=NULL){ if(token[0]==91) { if(token[strlen(token)-1]!=93) { state='X'; } token++; token[strlen(token)-1]='\0'; } if(token[0]==35) { if(strlen(token)!=1) strcpy(lbl[lb++].labels,token); else{ state='X'; break; } } for(m1=0;m1<64;m1++) { if((strcmp(token,regs[m1].regi)==0)||(token[0]==35)) { if((m1<64)&&(token[0]!=35)) { regs[m1].used=0; } state='F'; break; } } token = strtok(NULL,s); if(token!=NULL){state='X';break;} }break; } } } break; case 'O': flag=0; token = strtok(NULL,s); // 1st token if(token!=NULL){ for(m=0;m<64;m++) { if((strcmp(token,regs[m].regi)==0)) { regs[m].used=0; token = strtok(NULL,s); // 2nd token if(token!=NULL){ if(token[0]==91&&(token[strlen(token)-1]==93)) { token++; token[strlen(token)-1]='\0'; flag=2; token1 = strtok(NULL,s); if(token1 != NULL){state='X';break;} } for(m1=0;m1<64;m1++) { if((strcmp(token,regs[m1].regi)==0)) { regs[m1].used=0; token = strtok(NULL,s);// 3rd token if(token!=NULL){ for(m2=0;m2<64;m2++){ if((strcmp(token,regs[m2].regi)==0)){ regs[m2].used=0; state='F'; break; } else{ flag=0; state='X'; } } token = strtok(NULL,s); if(token!=NULL){state='X';break;} } else state='X'; if(flag!=0){ state='F'; }break; } else { if((checkHex(token)==1)){ state='F'; token1 = strtok(NULL,s); if(token1 != NULL){state='X';break;} } } } }break; } } } break; case 'B': token = strtok(NULL,s); // 1st token------- if(token!=NULL){ state='F'; } token = strtok(NULL,s); if(token!=NULL){state='X';} break; case 'P': token = strtok(NULL,s); // 1st token if(token!=NULL){ for(m=0;m<64;m++) { if((strcmp(token,regs[m].regi)==0)) { regs[m].used=0; token = strtok(NULL,s); //2nd token if(token!=NULL){ for(m1=0;m1<64;m1++) { if((strcmp(token,regs[m1].regi)==0)) { regs[m1].used=0; state='F'; } } } break; } } } token = strtok(NULL,s); if(token!=NULL){state='X';} break; case 'I': token = strtok(NULL,s); // 1st token if(token!=NULL){ for(m=0;m<64;m++) { if((strcmp(token,regs[m].regi)==0)) { regs[m].used=0; break; } } } token = strtok(NULL,s); // 2nd token if(token!=NULL){ if(checkHex(token)==1){ state='F'; } } token = strtok(NULL,s); if(token!=NULL){state='X';} break; case 'R': token = strtok(NULL,s); // 1st token if(token!=NULL){ for(m=0;m<64;m++) { if((strcmp(token,regs[m].regi)==0)) { regs[m].used=0; state='F'; break; } } } token = strtok(NULL,s); if(token!=NULL){state='X';} break; case 'N': token = strtok(NULL,s); // 1st token if(token!=NULL){ if(token[0]==91) { token++; token[strlen(token)-1]='\0'; } for(m=0;m<64;m++) { if((strcmp(token,regs[m].regi)==0)) { regs[m].used=0; state='F'; break; } } } token = strtok(NULL,s); if(token!=NULL){state='X';} break; case 'C': state='F'; token = strtok(NULL,s); if(token!=NULL) state='X'; break; default: state='X'; } token = strtok(NULL,s); if(state!='F') { printf("\nerror in line : %d",l+1); errorflag=1; } break; } } l++; } for(m1=0;m1<lb;m1++) { if(lbl[m1].labels[0]==35) { lbl[m1].mad=madd; madd+=32; } } for(m1=0;m1<lb;m1++) { //printf("Labels :: %s \t address :: %ld\n",lbl[m1].labels,lbl[m1].mad); fprintf(opfp,"%s\t%ld\n",lbl[m1].labels,lbl[m1].mad); } fclose(fp); fclose(opfp); strcpy(token3,"pass2.exe "); strcat(token3,argv[1]); if(errorflag==0) system(token3); exit(0); }
std::string raw2trace_t::append_bb_entries(uint tidx, offline_entry_t *in_entry, OUT bool *handled) { uint instr_count = in_entry->pc.instr_count; instr_t instr; trace_entry_t buf_start[MAX_COMBINED_ENTRIES]; app_pc start_pc = modvec[in_entry->pc.modidx].map_base + in_entry->pc.modoffs; app_pc pc, decode_pc = start_pc; if ((in_entry->pc.modidx == 0 && in_entry->pc.modoffs == 0) || modvec[in_entry->pc.modidx].map_base == NULL) { // FIXME i#2062: add support for code not in a module (vsyscall, JIT, etc.). // Once that support is in we can remove the bool return value and handle // the memrefs up here. VPRINT(3, "Skipping ifetch for %u instrs not in a module\n", instr_count); *handled = false; return ""; } else { VPRINT(3, "Appending %u instrs in bb " PFX " in mod %u +" PIFX " = %s\n", instr_count, (ptr_uint_t)start_pc, (uint)in_entry->pc.modidx, (ptr_uint_t)in_entry->pc.modoffs, modvec[in_entry->pc.modidx].path); } bool skip_icache = false; if (instr_count == 0) { // L0 filtering adds a PC entry with a count of 0 prior to each memref. skip_icache = true; instr_count = 1; // We set a flag to avoid peeking forward on instr entries. if (!instrs_are_separate) instrs_are_separate = true; } CHECK(!instrs_are_separate || instr_count == 1, "cannot mix 0-count and >1-count"); instr_init(dcontext, &instr); for (uint i = 0; i < instr_count; ++i) { trace_entry_t *buf = buf_start; app_pc orig_pc = decode_pc - modvec[in_entry->pc.modidx].map_base + modvec[in_entry->pc.modidx].orig_base; bool skip_instr = false; instr_reset(dcontext, &instr); // We assume the default ISA mode and currently require the 32-bit // postprocessor for 32-bit applications. pc = decode(dcontext, decode_pc, &instr); if (pc == NULL || !instr_valid(&instr)) { WARN("Encountered invalid/undecodable instr @ %s+" PFX, modvec[in_entry->pc.modidx].path, (ptr_uint_t)in_entry->pc.modoffs); break; } CHECK(!instr_is_cti(&instr) || i == instr_count - 1, "invalid cti"); if (instr_is_rep_string(&instr)) { // We want it to look like the original rep string instead of the // drutil-expanded loop. if (!prev_instr_was_rep_string) prev_instr_was_rep_string = true; else skip_instr = true; } else prev_instr_was_rep_string = false; // FIXME i#1729: make bundles via lazy accum until hit memref/end. if (!skip_instr) { DO_VERBOSE(3, { instr_set_translation(&instr, orig_pc); dr_print_instr(dcontext, STDOUT, &instr, ""); });
/* returns whether found a syscall * - found_eax: whether the caller has seen "mov imm => %eax" * - found_edx: whether the caller has seen "mov $0x7ffe0300 => %edx", * xref the comment in process_syscall_instr. */ static bool process_syscall_call(void *dcontext, byte *next_pc, instr_t *call, bool found_eax, bool found_edx) { int num_instr; byte *pc; instr_t instr; bool found_syscall = false; assert(instr_get_opcode(call) == OP_call && opnd_is_pc(instr_get_target(call))); pc = opnd_get_pc(instr_get_target(call)); if (pc > next_pc + MAX_SYSENTER_CALLEE_OFFSET || pc <= next_pc /* assuming the call won't go backward */) return false; /* handle win8 x86 which has sysenter callee adjacent-"inlined" * ntdll!NtYieldExecution: * 77d7422c b801000000 mov eax,1 * 77d74231 e801000000 call ntdll!NtYieldExecution+0xb (77d74237) * 77d74236 c3 ret * 77d74237 8bd4 mov edx,esp * 77d74239 0f34 sysenter * 77d7423b c3 ret * * or DrMem-i#1366-c#2 * USER32!NtUserCreateWindowStation: * 75caea7a b841110000 mov eax,0x1141 * 75caea7f e838000000 call user32!...+0xd (75caeabc) * 75caea84 c22000 ret 0x20 * ... * USER32!GetWindowStationName: * 75caea8c 8bff mov edi,edi * 75caea8e 55 push ebp * ... * 75caeabc 8bd4 mov edx,esp * 75caeabe 0f34 sysenter * 75caeac0 c3 ret */ /* We expect the win8 x86 sysenter adjacent "inlined" callee to be as simple as * 75caeabc 8bd4 mov edx,esp * 75caeabe 0f34 sysenter * 75caeac0 c3 ret */ instr_init(dcontext, &instr); num_instr = 0; do { instr_reset(dcontext, &instr); pc = decode(dcontext, pc, &instr); if (verbose) dr_print_instr(dcontext, STDOUT, &instr, ""); if (pc == NULL || !instr_valid(&instr)) break; if (instr_is_syscall(&instr) || instr_is_call_indirect(&instr)) { found_syscall = process_syscall_instr(dcontext, &instr, found_eax, found_edx); break; } else if (instr_is_cti(&instr)) { break; } num_instr++; } while (num_instr <= MAX_INSTRS_SYSENTER_CALLEE); instr_free(dcontext, &instr); return found_syscall; }
static void module_load_event(void *drcontext, const module_data_t *mod, bool loaded) { if (strstr(dr_module_preferred_name(mod), "client.drwrap-test.appdll.") != NULL) { bool ok; instr_t inst; app_pc init_pc, pc, next_pc; load_count++; if (load_count == 2) { /* test no-frills */ drwrap_set_global_flags(DRWRAP_NO_FRILLS); } addr_replace = (app_pc) dr_get_proc_address(mod->handle, "replaceme"); CHECK(addr_replace != NULL, "cannot find lib export"); ok = drwrap_replace(addr_replace, (app_pc) replacewith, false); CHECK(ok, "replace failed"); addr_replace2 = (app_pc) dr_get_proc_address(mod->handle, "replaceme2"); CHECK(addr_replace2 != NULL, "cannot find lib export"); ok = drwrap_replace_native(addr_replace2, (app_pc) replacewith2, true/*at entry*/, 0, (void *)(ptr_int_t)DRWRAP_NATIVE_PARAM, false); CHECK(ok, "replace_native failed"); init_pc = (app_pc) dr_get_proc_address(mod->handle, "replace_callsite"); CHECK(init_pc != NULL, "cannot find lib export"); /* Find callsite: we assume we'll linearly hit a ret. We take final call * to skip any PIC call. */ instr_init(drcontext, &inst); pc = init_pc; do { instr_reset(drcontext, &inst); next_pc = decode(drcontext, pc, &inst); if (!instr_valid(&inst)) break; /* if initial jmp, follow it to handle ILT-indirection */ if (pc == init_pc && instr_is_ubr(&inst)) next_pc = opnd_get_pc(instr_get_target(&inst)); else if (instr_is_call(&inst)) addr_replace_callsite = pc; pc = next_pc; } while (instr_valid(&inst) && !instr_is_return(&inst)); CHECK(addr_replace_callsite != NULL, "cannot find lib export"); ok = drwrap_replace_native(addr_replace_callsite, (app_pc) replace_callsite, false/*!at entry*/, 0, (void *)(ptr_int_t)DRWRAP_NATIVE_PARAM, false); CHECK(ok, "replace_native failed"); instr_free(drcontext, &inst); wrap_addr(&addr_level0, "level0", mod, true, true); wrap_addr(&addr_level1, "level1", mod, true, true); wrap_addr(&addr_level2, "level2", mod, true, true); wrap_addr(&addr_tailcall, "makes_tailcall", mod, true, true); wrap_addr(&addr_skipme, "skipme", mod, true, true); wrap_addr(&addr_repeat, "repeatme", mod, true, true); wrap_addr(&addr_preonly, "preonly", mod, true, false); wrap_addr(&addr_postonly, "postonly", mod, false, true); wrap_addr(&addr_runlots, "runlots", mod, false, true); /* test longjmp */ wrap_unwindtest_addr(&addr_long0, "long0", mod); wrap_unwindtest_addr(&addr_long1, "long1", mod); wrap_unwindtest_addr(&addr_long2, "long2", mod); wrap_unwindtest_addr(&addr_long3, "long3", mod); wrap_unwindtest_addr(&addr_longdone, "longdone", mod); drmgr_set_tls_field(drcontext, tls_idx, (void *)(ptr_uint_t)0); #ifdef WINDOWS /* test SEH */ /* we can't do this test for no-frills b/c only one wrap per addr */ if (load_count == 1) { ok = drwrap_wrap_ex(addr_long0, wrap_unwindtest_seh_pre, wrap_unwindtest_seh_post, NULL, DRWRAP_UNWIND_ON_EXCEPTION); CHECK(ok, "wrap failed"); ok = drwrap_wrap_ex(addr_long1, wrap_unwindtest_seh_pre, wrap_unwindtest_seh_post, NULL, DRWRAP_UNWIND_ON_EXCEPTION); CHECK(ok, "wrap failed"); ok = drwrap_wrap_ex(addr_long2, wrap_unwindtest_seh_pre, wrap_unwindtest_seh_post, NULL, DRWRAP_UNWIND_ON_EXCEPTION); CHECK(ok, "wrap failed"); ok = drwrap_wrap_ex(addr_long3, wrap_unwindtest_seh_pre, wrap_unwindtest_seh_post, NULL, DRWRAP_UNWIND_ON_EXCEPTION); CHECK(ok, "wrap failed"); ok = drwrap_wrap_ex(addr_longdone, wrap_unwindtest_seh_pre, wrap_unwindtest_seh_post, NULL, DRWRAP_UNWIND_ON_EXCEPTION); CHECK(ok, "wrap failed"); } #endif /* test leaner wrapping */ if (load_count == 2) drwrap_set_global_flags(DRWRAP_NO_FRILLS | DRWRAP_FAST_CLEANCALLS); wrap_addr(&addr_skip_flags, "skip_flags", mod, true, false); } }
int main(int argc, char *argv[]) { FILE *fp,*opfp,*omc,*mc,*testf; int test,n,c,ln,i,m,m1,m2,b,flag=0,len,last,digit=0,var,id=0,f,flen=0; long int madd=0; char ch,*nem[4],*str,*token,*s=" ",state,*str1,*s1="\t",*token1,*temp,*token2,c1;//*labels[10] str = (char *)malloc(sizeof(char)*50); str1 = (char *)malloc(sizeof(char)*50); token1 = (char *)malloc(sizeof(char)*50); token2 = (char *)malloc(sizeof(char)*50); register_init(); instr_init(); opfp = fopen("stable.txt","r"); if(opfp == NULL) { perror("Error while opening the file.\n"); exit(EXIT_FAILURE); } //printf("file name %s\n", argv[1]); fp = fopen(argv[1],"r"); // opens file testf = fopen(argv[1],"r"); omc = fopen("mcode.txt","w"); mc= fopen("onlymcode.txt","w"); if(fp == NULL) { perror("Error while opening the file.\n"); exit(EXIT_FAILURE); } label lbl[10]; for(m1=0;m1<10;m1++) { lbl[m1].labels = (char *)malloc(sizeof(char)*10); } for(m1=0;m1<10;m1++) { lbl[m1].mad = (char *)malloc(sizeof(char)*10); } while( fgets(str1,50,opfp)!=NULL) { token=strtok(str1,s1); while(token!=NULL) { strcpy(lbl[lb].labels,token); token=strtok(NULL,s1); strcpy(lbl[lb].mad,token); token=strtok(NULL,s1); }++lb; } /*for(m1=0;m1<lb;m1++) { printf("Labels :: %s \t address :: %s\n",lbl[m1].labels,lbl[m1].mad); } */ for (c1 = getc(testf); c1 != EOF; c1 = getc(testf)){ if (c1 == '\n') // Increment count if this character is newline flen++; } fclose(testf); while( fgets(str,50,fp)!=NULL) //line reading { state='X'; if(flen==l){ strcat(str,"\0"); } if((str!="")&&((flen!=l))) str[strlen(str)-1]='\0'; if(l>0) { //printf( "\n%00000007ld\t%s",madd,str ); fprintf(omc,"\n%00000007ld\t%s",madd,str ); madd+=32; state='X'; token = strtok(str,s); // instruction name len=strlen(token); last=token[len-1]; if(last==58) { token = strtok(NULL,s); } while( token != NULL ) { for(b=1;b<=4;b++) // MOV { if(strcmp(token,(ins[b].nemo))==0) { state='M'; id=b; break; } } for(b=5;b<=8;b++) // direct address { if(strcmp(token,(ins[b].nemo))==0) { state='I'; //printf("\nMCODE : %s ",ins[b].mcode); fprintf(omc,"\nMCODE : %s ",ins[b].mcode); fprintf(mc,"\n%s",ins[b].mcode); break; } } for(b=9;b<=10;b++) // ADD { if(strcmp(token,(ins[b].nemo))==0) { state='A'; id=b; break; } } for(b=11;b<=13;b++) // MUL { if(strcmp(token,(ins[b].nemo))==0) { state='A'; id=b; break; } } for(b=14;b<=15;b++) // AND { if(strcmp(token,(ins[b].nemo))==0) { state='A'; id=b; break; } } for(b=16;b<=18;b++) // OR { if(strcmp(token,(ins[b].nemo))==0) { state='O'; break; } } for(b=19;b<=20;b++) // NOT { if(strcmp(token,(ins[b].nemo))==0) { state='N'; id=b; break; } } for(b=21;b<=26;b++) // type INS r1 { if(strcmp(token,(ins[b].nemo))==0) { //printf("\nMCODE : %s ",ins[b].mcode); fprintf(omc,"\nMCODE : %s ",ins[b].mcode); fprintf(mc,"\n%s",ins[b].mcode); state='R'; break; } } if(strcmp(token,(ins[27].nemo))==0) // compare CMP { id=28; state='M'; } for(b=28;b<=36;b++) // branching instruction JMP { if(strcmp(token,(ins[b].nemo))==0) { state='B'; //printf("\nMCODE : %s ",ins[b].mcode); fprintf(omc,"\nMCODE : %s ",ins[b].mcode); fprintf(mc,"\n%s",ins[b].mcode); break; } } for(b=37;b<=40;b++) // machine control instruction { if(strcmp(token,(ins[b].nemo))==0) { state='C'; //printf("\nMCODE : %s ",ins[b].mcode); fprintf(omc,"\nMCODE : %s\n",ins[b].mcode); fprintf(mc,"\n%s",ins[b].mcode); } } switch(state) { case 'M': token = strtok(NULL,s); // 1st token------- if(token!=NULL){ if(token[0]==91) { token++; token[strlen(token)-1]='\0'; f=4; } for(m=0;m<64;m++) { if((strcmp(token,regs[m].regi)==0)) { strcpy(token1,regs[m].address); strcpy(token2,regs[m].address); strcat(token1," "); token = strtok(NULL,s); // 2nd token------- if(token!=NULL){ if(token[0]==91) { token++; token[strlen(token)-1]='\0'; for(m1=0;m1<64;m1++) { if((strcmp(token,regs[m1].regi)==0)) { strcat(token1,regs[m1].address); strcat(token2,regs[m1].address); //printf("\nMCODE : %s %s",ins[3].mcode,token1); fprintf(omc,"\nMCODE : %s %s\n",ins[3].mcode,token1); fprintf(mc,"\n%s%s",ins[3].mcode,token2); break; } } token="xx"; } for(m1=0;m1<64;m1++) { if((strcmp(token,regs[m1].regi)==0)) { if(f!=4) { strcat(token1,regs[m1].address); strcat(token2,regs[m1].address); //printf("\nMCODE : %s %s",ins[id].mcode,token1); fprintf(omc,"\nMCODE : %s %s\n",ins[id].mcode,token1); fprintf(mc,"\n%s%s",ins[id].mcode,token2); state='F'; } if(f==4) { strcat(token1,regs[m1].address); strcat(token2,regs[m1].address); //printf("\nMCODE : %s %s",ins[4].mcode,token1); fprintf(omc,"\nMCODE : %s %s\n",ins[4].mcode,token1); fprintf(mc,"\n%s%s",ins[4].mcode,token2); f=0; state='F'; } break; } else { if(token[0]==35) { for(var=0;var<lb;var++) { if(strcmp(lbl[var].labels,token)==0) { lbl[var].mad[strlen(lbl[var].mad)-1]='\0'; strcat(token1,appendLeft(toBin(atoi(lbl[var].mad)))); strcat(token2,appendLeft(toBin(atoi(lbl[var].mad)))); //printf("\nMCODE : %s %s",ins[++id].mcode,token1); fprintf(omc,"\nMCODE : %s %s\n",ins[id].mcode,token1); fprintf(mc,"\n%s%s",ins[id].mcode,token2); token++; break; } } } } } token = strtok(NULL,s); if(token!=NULL){state='X';break;} }break; } } } break; case 'I': token = strtok(NULL,s); // 1st token------- if(token!=NULL){ for(m=0;m<64;m++) { if((strcmp(token,regs[m].regi)==0)) { //printf("%s ",regs[m].address); fprintf(omc,"%s ",regs[m].address); fprintf(mc,"%s",regs[m].address); break; } } } token = strtok(NULL,s); // 2nd token------- //printf("%s",hextoBin(token)); fprintf(omc,"%s\n",hextoBin(token)); fprintf(mc,"%s",hextoBin(token)); break; case 'A': token = strtok(NULL,s);//1st token for(m=0;m<64;m++) { if((strcmp(token,regs[m].regi)==0)) { strcpy(token1,regs[m].address); strcpy(token2,regs[m].address); strcat(token1," "); token = strtok(NULL,s);//2nd token if(token[0]==91) { token++; token[strlen(token)-1]='\0'; id++; f=6; } for(m1=0;m1<64;m1++) { if((strcmp(token,regs[m1].regi)==0)) { strcat(token1,regs[m1].address); strcat(token2,regs[m1].address); if(f==6){ //printf("\nMCODE : %s %s",ins[id].mcode,token1); fprintf(omc,"\nMCODE : %s %s\n",ins[id].mcode,token1); fprintf(mc,"\n%s%s",ins[id].mcode,token2); f=0; break; } token = strtok(NULL,s);//3rd token for(m2=0;m2<64;m2++) { if((strcmp(token,regs[m2].regi)==0)) { strcat(token1," "); strcat(token1,regs[m2].address); strcat(token2,regs[m2].address); //printf("\nMCODE : %s %s",ins[id].mcode,token1); fprintf(omc,"\nMCODE : %s %s\n",ins[id].mcode,token1); fprintf(mc,"\n%s%s",ins[id].mcode,token2); break; } } break; } } break; } } break; case 'O': token = strtok(NULL,s);//1st token for(m=0;m<64;m++) { if((strcmp(token,regs[m].regi)==0)) { strcpy(token1,regs[m].address); strcpy(token2,regs[m].address); strcat(token1," "); token = strtok(NULL,s);//2nd token if(token[0]==91) { token++; token[strlen(token)-1]='\0'; id++; id++; f=6; } if(checkHex(token)==1) { id++; //printf("\nMCODE : %s %s %s",ins[id].mcode,token1,hextoBin(token)); fprintf(omc,"\nMCODE : %s %s %s\n",ins[id].mcode,token1,hextoBin(token)); fprintf(mc,"\n%s%s%s",ins[id].mcode,token2,hextoBin(token)); break; } for(m1=0;m1<64;m1++) { if((strcmp(token,regs[m1].regi)==0)) { strcat(token1,regs[m1].address); strcat(token2,regs[m1].address); strcat(token1," "); if(f==6){ //printf("\nMCODE : %s %s",ins[id].mcode,token1); fprintf(omc,"\nMCODE : %s %s\n",ins[id].mcode,token1); fprintf(mc,"\n%s%s",ins[id].mcode,token2); f=0; break; } token = strtok(NULL,s);//3rd token for(m2=0;m2<64;m2++) { if((strcmp(token,regs[m2].regi)==0)) { //puts(token); strcat(token1,regs[m2].address);//puts(token1); strcat(token2,regs[m2].address); //printf("\nMCODE : %s %s",ins[id].mcode,token1); fprintf(omc,"\nMCODE : %s %s\n",ins[id].mcode,token1); fprintf(mc,"\n%s%s",ins[id].mcode,token2); break; } } break; } } break; } } break; case 'N': token = strtok(NULL,s); // 1st token------- if(token!=NULL){ if(token[0]==91) { token++; token[strlen(token)-1]='\0'; id++; } for(m=0;m<64;m++) { if((strcmp(token,regs[m].regi)==0)) { //printf("\nMCODE : %s %s",ins[id].mcode,regs[m].address); fprintf(omc,"\nMCODE : %s %s\n",ins[id].mcode,regs[m].address); fprintf(mc,"\n%s%s",ins[id].mcode,regs[m].address); break; } } } break; case 'R': token = strtok(NULL,s); // 1st token------- if(token!=NULL){ for(m=0;m<64;m++) { if((strcmp(token,regs[m].regi)==0)) { //printf("%s",regs[m].address); fprintf(omc,"%s\n",regs[m].address); fprintf(mc,"%s",regs[m].address); break; } } } break; case 'B': token = strtok(NULL,s); // 1st token------- if(token!=NULL){ for(m1=0;m1<lb;m1++) { if(strcmp(lbl[m1].labels,token)==0) { lbl[m1].mad[strlen(lbl[m1].mad)-1]='\0'; //printf("%s",appendLeft(toBin(atoi(lbl[m1].mad)))); fprintf(omc,"%s\n",appendLeft(toBin(atoi(lbl[m1].mad)))); fprintf(mc,"%s",appendLeft(toBin(atoi(lbl[m1].mad)))); break; } if(m1==lb-1) { printf("\nError in code!!No lebel found in jump instruction at line %d !! Exit from program !!",l+1); exit(0); } } if(lb==0) { printf("\nError in code!!No lebel found in jump instruction at line %d !! Exit from program !!",l+1); exit(0); } } break; default: state='X'; } token = strtok(NULL,s); break; } } l++; } printf("compilation successful :D "); fclose(fp); fclose(opfp); fclose(mc); append(); return 0; }
/* Here we attempt to combine a loop involving ldex (load exclusive) and * stex (store exclusive) into an OP_ldstex macro-instruction. The algorithm * is roughly this: * * Decode up to (2 * N) instructions while: * - none of them are indirect branches or system calls * - none of them is a direct branch out of these (2 * N) instructions * - none of them is OP_xx (to be safe) * - there is, or might yet be, both ldex and stex in the first N * - none of them is a non-branch PC-relative instruction: ADR, ADRP, * PC-relative PRFM, literal load (this last condition could be removed * if we mangled such instructions as we encountered them) * * To save time, give up if the first instruction is neither ldex nor stex * and there is no branch to it. * Take a sub-block containing both ldex and stex from the first N instructions. * Expand this sub-block to a minimal single-entry single-exit block. * Give up if the sub-block grows beyond N instructions. * Finally, give up if the sub-block does not contain the first instruction. * Also give up if the sub-block uses all of X0-X5 and the stolen register * because we would be unable to mangle such a block. * * XXX: This function uses a lot of CPU time. It could be made faster in * several ways, for example by caching decoded instructions or using a * custom decoder to recognise the particular instructions that we care * about here. */ byte * decode_ldstex(dcontext_t *dcontext, byte *pc_, byte *orig_pc_, instr_t *instr_ldstex) { # define N (MAX_INSTR_LENGTH / AARCH64_INSTR_SIZE) instr_t ibuf[2 * N]; uint *pc = (uint *)pc_; uint *orig_pc = (uint *)orig_pc_; bool seen_ldex = false; bool seen_stex = false; bool seen_branch_to_start = false; bool failed = false; int ldstex_beg = -1; int ldstex_end = -1; int i, len; /* Decode up to 2 * N instructions. */ for (i = 0; i < N; i++) { instr_t *instr = &ibuf[i]; instr_init(dcontext, instr); decode_from_copy(dcontext, (byte *)(pc + i), (byte *)(orig_pc + i), instr); if (instr_is_mbr_arch(instr) || instr_is_syscall(instr) || instr_get_opcode(instr) == OP_xx || instr_is_nonbranch_pcrel(instr)) break; if (instr_is_ubr_arch(instr) || instr_is_cbr_arch(instr)) { ptr_uint_t target = (ptr_uint_t)instr_get_branch_target_pc(instr); if (target < (ptr_uint_t)pc || target > (ptr_uint_t)(pc + 2 * N)) break; if (target == (ptr_uint_t)pc) seen_branch_to_start = true; } if (instr_is_exclusive_load(instr)) seen_ldex = true; if (instr_is_exclusive_store(instr)) seen_stex = true; if (i + 1 >= N && !(seen_ldex && seen_stex)) break; if (ldstex_beg == -1 && (seen_ldex || seen_stex)) ldstex_beg = i; if (ldstex_end == -1 && (seen_ldex && seen_stex)) ldstex_end = i + 1; } if (i < N) { instr_reset(dcontext, &ibuf[i]); len = i; } else len = N; /* Quick check for hopeless situations. */ if (len == 0 || !(seen_ldex && seen_stex) || !(seen_branch_to_start || (instr_is_exclusive_load(&ibuf[0]) || instr_is_exclusive_store(&ibuf[0])))) { for (i = 0; i < len; i++) instr_reset(dcontext, &ibuf[i]); return NULL; } /* There are several ways we could choose a sub-block containing both ldex * and stex from the first N instructions. Investigate further, perhaps. * We have already set ldstex_beg and ldstex_end. */ ASSERT(ldstex_beg != -1 && ldstex_end != -1 && ldstex_beg < ldstex_end); /* Expand ldstex sub-block until it is a single-entry single-exit block. */ for (;;) { int new_beg = ldstex_beg; int new_end = ldstex_end; for (i = ldstex_beg; i < ldstex_end; i++) { instr_t *instr = &ibuf[i]; if (instr_is_ubr_arch(instr) || instr_is_cbr_arch(instr)) { int target = (uint *)instr_get_branch_target_pc(instr) - pc; if (target > len) { failed = true; break; } if (target < new_beg) new_beg = target; if (target > new_end) new_end = target; } } if (new_beg == ldstex_beg && new_end == ldstex_end) break; ldstex_beg = new_beg; ldstex_end = new_end; } if (ldstex_beg != 0) failed = true; if (!failed) { /* Check whether the sub-block uses the stolen register and all of X0-X5. * If it does, it would be impossible to mangle it so it is better not to * create an OP_ldstex. */ reg_id_t regs[] = { dr_reg_stolen, DR_REG_X0, DR_REG_X1, DR_REG_X2, DR_REG_X3, DR_REG_X4, DR_REG_X5 }; int r; for (r = 0; r < sizeof(regs) / sizeof(*regs); r++) { for (i = ldstex_beg; i < ldstex_end; i++) { if (instr_uses_reg(&ibuf[i], regs[r])) break; } if (i >= ldstex_end) break; } if (r >= sizeof(regs) / sizeof(*regs)) failed = true; } if (!failed) { instr_create_ldstex(dcontext, ldstex_end - ldstex_beg, pc + ldstex_beg, &ibuf[ldstex_beg], instr_ldstex); } for (i = 0; i < len; i++) instr_reset(dcontext, &ibuf[i]); return failed ? NULL : (byte *)(pc + ldstex_end); }