DWORD Detour_c::SetupDetour(void) { BYTE* CurrOpcode = (BYTE*)dwOldAddress; OpcodeLen = oplen(CurrOpcode); CurrOpcode += OpcodeLen; while(OpcodeLen < 5) { int Len = oplen(CurrOpcode); if(!Len) return 0; OpcodeLen += Len; CurrOpcode += Len; } if(VirtualProtect((PVOID)dwOldAddress, OpcodeLen, PAGE_EXECUTE_READWRITE, &dwTempProtect[0]) == FALSE) return 0; RtlCopyMemory((PVOID)PatchBackup, (PVOID)dwOldAddress, OpcodeLen); *(BYTE*) (dwOldAddress + 0) = 0xE9; *(DWORD*)(dwOldAddress + 1) = dwMyAddress - dwOldAddress - 5; for(int i=5; i < OpcodeLen; i++) *(BYTE*) (dwOldAddress + i) = 0x90; // NOP; if(VirtualProtect((PVOID)dwOldAddress, OpcodeLen, dwTempProtect[0], &dwTempProtect[1]) == FALSE) return 0; dwNewAddress = (DWORD)VirtualAlloc(NULL, OpcodeLen + 6, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if(dwNewAddress == NULL) return 0; RtlCopyMemory((PVOID)dwNewAddress, (PVOID)PatchBackup, OpcodeLen); *(BYTE*) (dwNewAddress + OpcodeLen + 0) = 0xE9; *(DWORD*)(dwNewAddress + OpcodeLen + 1) = (dwOldAddress + OpcodeLen) - (dwNewAddress + OpcodeLen + 5); return dwNewAddress; }
static void stab_entry(char *name,int type,int othr,int desc,char *s) { section *stabs; if (!(stabs = find_section(stabname,stabattr))) { section *str; dblock *db; stabs = new_section(stabname,stabattr,4); if (!(str = find_section(stabstrname,stabstrattr))) { str = new_section(stabstrname,stabstrattr,1); } else { if (str->pc != 0) ierror(0); } /* first byte of .stabstr is 0 */ add_atom(str,new_space_atom(number_expr(1),1,0)); /* compilation unit header has to be patched by output module */ new_stabstr(getfilename()); db = new_dblock(); db->size = 12; db->data = mymalloc(12); add_atom(stabs,new_data_atom(db,1)); } add_const_datadef(stabs,name?new_stabstr(name):0,32,1); add_const_datadef(stabs,type,8,1); add_const_datadef(stabs,othr,8,1); add_const_datadef(stabs,desc,16,1); if (s) { operand *op = new_operand(); int len = oplen(skip_operand(s),s); if (parse_operand(s,len,op,DATA_OPERAND(32))) { atom *a = new_datadef_atom(32,op); a->align = 1; add_atom(stabs,a); } else syntax_error(8); } else add_atom(stabs,new_space_atom(number_expr(4),1,0)); /* no value */ }
int CDetour::GetDetourLenAuto ( BYTE * &orig, int iMinLen ) { int tmpLen = 0; BYTE *pCurOp = orig; while ( tmpLen < iMinLen ) { int i = oplen( pCurOp ); if ( i == 0 || i == -1 ) return false; tmpLen += i; pCurOp += i; } return tmpLen; }
void parse(void) { char *s,*line,*ext[MAX_QUALIFIERS?MAX_QUALIFIERS:1],*op[MAX_OPERANDS]; char *labname,*start; int inst_len,ext_len[MAX_QUALIFIERS?MAX_QUALIFIERS:1],op_len[MAX_OPERANDS]; int ext_cnt,op_cnt; instruction *ip; while (line=read_next_line()){ if (clev >= MAXCONDLEV) syntax_error(16,clev); /* nesting depth exceeded */ if (!cond[clev]) { /* skip source until ELSE or ENDIF */ int idx; s = line; idx = check_directive(&s); if (idx >= 0) { if (!strncmp(directives[idx].name,"if",2)) { ifnesting++; } else if (ifnesting==0 && !strncmp(directives[idx].name,"else",4)) { cond[clev] = 1; } else if (directives[idx].func == handle_endif) { if (ifnesting == 0) { if (clev > 0) clev--; else syntax_error(14); /* endif without if */ } else ifnesting--; } } continue; } s=skip(line); if(handle_directive(s)) continue; /* skip spaces */ s=skip(s); if(!*s||*s==commentchar) continue; /* check for label */ start=s; if(labname=get_local_label(&s)){ /* local label? */ if(*s!=':'){ s=start; myfree(labname); labname=NULL; } } else if(ISIDSTART(*s)){ /* or global label? */ s++; while(ISIDCHAR(*s)) s++; if(*s!=':') s=start; else labname=cnvstr(start,s-start); } if(labname){ /* we have found a valid global or local label */ add_atom(0,new_label_atom(new_labsym(0,labname))); s=skip(s+1); myfree(labname); } if(!*s||*s==commentchar) continue; s=skip(parse_cpu_special(s)); if(*s==0||*s==commentchar) continue; if(handle_directive(s)) continue; /* read mnemonic name */ start=s; ext_cnt=0; if(!ISIDSTART(*s)){ syntax_error(10); continue; } #if MAX_QUALIFIERS==0 while(*s&&!isspace((unsigned char)*s)) s++; inst_len=s-start; #else s=parse_instruction(s,&inst_len,ext,ext_len,&ext_cnt); #endif s=skip(s); if(execute_macro(start,inst_len,ext,ext_len,ext_cnt,s,clev)) continue; /* read operands, terminated by comma (unless in parentheses) */ op_cnt=0; while(*s&&*s!=commentchar&&op_cnt<MAX_OPERANDS){ op[op_cnt]=s; s=skip_operand(s); op_len[op_cnt]=oplen(s,op[op_cnt]); #if !ALLOW_EMPTY_OPS if(op_len[op_cnt]<=0) syntax_error(5); else #endif op_cnt++; s=skip(s); if(*s!=','){ break; }else{ s=skip(s+1); } } s=skip(s); if(*s!=0&&*s!=commentchar) syntax_error(6); ip=new_inst(start,inst_len,op_cnt,op,op_len); #if MAX_QUALIFIERS>0 if(ip){ int i; for(i=0;i<ext_cnt;i++) ip->qualifiers[i]=cnvstr(ext[i],ext_len[i]); for(;i<MAX_QUALIFIERS;i++) ip->qualifiers[i]=0; } #endif if(ip){ add_atom(0,new_inst_atom(ip)); }else ; } if (clev > 0) syntax_error(15); /* if without endif */ }
void parse(void) { char *s,*line,*inst; char *ext[MAX_QUALIFIERS?MAX_QUALIFIERS:1]; char *op[MAX_OPERANDS]; int ext_len[MAX_QUALIFIERS?MAX_QUALIFIERS:1]; int op_len[MAX_OPERANDS]; int ext_cnt,op_cnt,inst_len; instruction *ip; while (line = read_next_line()) { if (!cond_state()) { /* skip source until ELSE or ENDIF */ int idx = -1; s = skip(line); if (labname = parse_labeldef(&s,1)) { if (*s == ':') s++; /* skip double-colon */ myfree(labname); s = skip(s); } else { if (inst = skip_identifier(s)) { inst = skip(inst); idx = check_directive(&inst); } } if (idx < 0) idx = check_directive(&s); if (idx >= 0) { if (directives[idx].func == handle_if) cond_skipif(); else if (directives[idx].func == handle_else) cond_else(); else if (directives[idx].func == handle_endif) cond_endif(); } continue; } s = skip(line); again: if (*s=='\0' || *line=='*' || *s==commentchar) continue; if (labname = parse_labeldef(&s,1)) { /* we have found a valid global or local label */ symbol *sym = new_labsym(0,labname); if (*s == ':') { /* double colon automatically declares label as exported */ sym->flags |= EXPORT; s++; } add_atom(0,new_label_atom(sym)); myfree(labname); s = skip(s); } else { /* there can still be a sym. in the 1st fld and an assignm. directive */ inst = s; labname = parse_symbol(&s); if (labname == NULL) { syntax_error(10); /* identifier expected */ continue; } s = skip(s); /* Now we have labname pointing to the first field in the line and s pointing to the second. Find out where the directive is. */ if (!ISEOL(s)) { #ifdef PARSE_CPU_LABEL if (PARSE_CPU_LABEL(labname,&s)) { myfree(labname); continue; } #endif if (handle_directive(s)) { myfree(labname); continue; } } /* directive or mnemonic must be in the first field */ myfree(labname); s = inst; } if (!strnicmp(s,".iif",4) || !(strnicmp(s,"iif",3))) { /* immediate conditional assembly: parse line after ',' when true */ s = skip(*s=='.'?s+4:s+3); if (do_cond(&s)) { s = skip(s); if (*s == ',') { s = skip(s+1); goto again; } else syntax_error(0); /* malformed immediate-if */ } continue; } /* check for directives */ s = parse_cpu_special(s); if (ISEOL(s)) continue; if (handle_directive(s)) continue; /* read mnemonic name */ inst = s; ext_cnt = 0; if (!ISIDSTART(*s)) { syntax_error(10); /* identifier expected */ continue; } #if MAX_QUALIFIERS==0 while (*s && !isspace((unsigned char)*s)) s++; inst_len = s - inst; #else s = parse_instruction(s,&inst_len,ext,ext_len,&ext_cnt); #endif if (!isspace((unsigned char)*s) && *s!='\0') syntax_error(2); /* no space before operands */ s = skip(s); if (execute_macro(inst,inst_len,ext,ext_len,ext_cnt,s)) continue; /* read operands, terminated by comma or blank (unless in parentheses) */ op_cnt = 0; while (!ISEOL(s) && op_cnt<MAX_OPERANDS) { op[op_cnt] = s; s = skip_operand(s); op_len[op_cnt] = oplen(s,op[op_cnt]); #if !ALLOW_EMPTY_OPS if (op_len[op_cnt] <= 0) syntax_error(5); /* missing operand */ else #endif op_cnt++; s = skip(s); if (*s != ',') break; else s = skip(s+1); } eol(s); ip = new_inst(inst,inst_len,op_cnt,op,op_len); #if MAX_QUALIFIERS>0 if (ip) { int i; for (i=0; i<ext_cnt; i++) ip->qualifiers[i] = cnvstr(ext[i],ext_len[i]); for(; i<MAX_QUALIFIERS; i++) ip->qualifiers[i] = NULL; } #endif if (ip) add_atom(0,new_inst_atom(ip)); } cond_check(); /* check for open conditional blocks */ }
/* Convert an instruction into a DATA atom including relocations, if necessary. */ dblock *eval_instruction(instruction *p,section *sec,taddr pc) { dblock *db=new_dblock(); int c,sz,enc,cc,ww,m=0; unsigned long code,code2,code3; rlist *relocs=0; if(p->qualifiers[0]){ int i; for(i=0;i<15;i++){ if(!strcmp(p->qualifiers[0],ccs[i])){ cc=i; break; } } if(i>15) ierror(0); }else cc=14; c=translate(p,sec,pc); enc=mnemonics[c].ext.encoding; db->size=sz=oplen(enc); db->data=mymalloc(db->size); code=mnemonics[c].ext.code; switch(enc){ case EN_ARITHR16: if(cc!=14) cpu_error(3); code=0x40000000|(code<<24); code|=(p->op[0]->reg<<16)|(p->op[1]->reg<<20); break; case EN_ARITHI16: if(cc!=14) cpu_error(3); code=0x60000000|((code>>1)<<25); code|=(p->op[0]->reg<<16)|(absval(p->op[1]->offset,sec,pc,5,0)<<20); break; case EN_FIX16: if(cc!=14) cpu_error(3); break; case EN_IBRANCH16: if(cc!=14) cpu_error(3); code|=(p->op[0]->reg<<16); break; case EN_RBRANCH16: code=0x18000000; code|=cc<<23; code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,0,7,0xfe)>>1)&127)<<16; break; case EN_MREG16: if(cc!=14) cpu_error(3); code|=(p->op[0]->dreg<<21)|(p->op[0]->reg<<16); break; case EN_RBRANCH32: if(code==0x90000000) code|=cc<<24; else code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,8,4,0xF000000)>>24)&0xf)<<24; code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,16,16,0x1fffe)>>1)&0x7fffff); code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,0,7,0xfe0000)>>17)&0x7f)<<16; break; case EN_FUNARY32: code=0xC0000040|(code<<21); code|=p->op[0]->reg<<16; code|=p->op[1]->reg<<11; code|=cc<<7; break; case EN_ARITHR32: code=0xC0000000|(code<<21); code|=p->op[0]->reg<<16; if(p->op[2]){ code|=p->op[1]->reg<<11; code|=p->op[2]->reg; }else{ code|=p->op[0]->reg<<11; code|=p->op[1]->reg; } code|=cc<<7; break; case EN_ARITHI32: code=0xC0000040|(code<<21); code|=p->op[0]->reg<<16; if(p->op[2]){ code|=p->op[1]->reg<<11; code|=absval(p->op[2]->offset,sec,pc,6,1); }else{ code|=p->op[0]->reg<<11; code|=absval(p->op[1]->offset,sec,pc,6,1); } code|=cc<<7; break; case EN_ADDCMPB64: // Large offset: invert CC, place a long branch after // so we really generate the following: // addcmpb<~cc> d, a, b, skip // b <destination> // skip: // <rest of code> m=1; if(cc&1) cc--; else cc++; case EN_ADDCMPB32: code=0x80000000|(code<<14); code|=cc<<24; code|=p->op[0]->reg<<16; if(code&0x4000){ code|=absval(p->op[1]->offset,sec,pc,4,1)<<20; }else{ code|=p->op[1]->reg<<20; } if(code&0x8000){ code|=absval(p->op[2]->offset,sec,pc,6,0)<<8; if(m) code|=4; else code|=((reloffset(p->op[3]->offset,sec,pc,&relocs,16,9,0x1ff)>>1)&0xff); }else{