/* * Unable to convert to OREG (notoff() returned failure). Output * suitable instructions to replace OREG. */ void myormake(NODE *q) { NODE *p; if (x2debug) printf("myormake(%p)\n", q); p = q->n_left; /* * This handles failed OREGs conversions, due to the offset * being too large for an OREG. */ if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_right->n_op == ICON) { if (isreg(p->n_left) == 0) (void)geninsn(p->n_left, INAREG); if (isreg(p->n_right) == 0) (void)geninsn(p->n_right, INAREG); (void)geninsn(p, INAREG); } else if (p->n_op == REG) { q->n_op = OREG; q->n_lval = p->n_lval; q->n_rval = p->n_rval; tfree(p); } }
void cmp_rm32_rm32(int dest, int source) { //eg, "cmp dest, source" if(isreg(dest)) { //destination is a register putbyte(0x39); if(isreg(source)) { //we have a "cmp %eax,%ebx" putbyte((0xc0+(dest*0x8))+source); } else { //we have a "cmp %eax,(%ebx)" putbyte((dest*0x8)+source-0x8); } } else { //destination is a memory offset located in register putbyte(0x3b); if(isreg(source)) { //we have a "cmp (%eax),%ebx" putbyte((source*0x8)+dest-0x8); } else { //we have a "cmp (%eax),(%ebx)" //this is an illegal instruction aerror("Error: in cmp_rm32_rm32"); } } }
/* * Turn a UMUL-referenced node into OREG. * Be careful about register classes, this is a place where classes change. */ void offstar(NODE *p, int shape) { if (x2debug) printf("offstar(%p)\n", p); if (isreg(p)) return; /* Is already OREG */ if (p->n_op == UMUL) p = p->n_left; /* double indexed umul */ if (inctree(p)) /* Do post-inc conversion */ return; if( p->n_op == PLUS || p->n_op == MINUS ){ if (p->n_right->n_op == ICON) { if (isreg(p->n_left) == 0) (void)geninsn(p->n_left, INAREG); /* Converted in ormake() */ return; } } (void)geninsn(p, INAREG); }
/* * Turn a UMUL-referenced node into OREG. * Be careful about register classes, this is a place where classes change. */ void offstar(NODE *p, int shape) { NODE *r; if (x2debug) printf("offstar(%p)\n", p); if (isreg(p)) return; /* Is already OREG */ r = p->n_right; if( p->n_op == PLUS || p->n_op == MINUS ){ if( r->n_op == ICON ){ if (isreg(p->n_left) == 0) (void)geninsn(p->n_left, INAREG); /* Converted in ormake() */ return; } if (r->n_op == LS && r->n_right->n_op == ICON && getlval(r->n_right) == 2 && p->n_op == PLUS) { if (isreg(p->n_left) == 0) (void)geninsn(p->n_left, INAREG); if (isreg(r->n_left) == 0) (void)geninsn(r->n_left, INAREG); return; } } (void)geninsn(p, INAREG); }
//set the MOV void MOV::set(int type1, intptr_t val1, int type2, intptr_t val2) { //MOV-exclusive specials if (val1 == EAX && isreg(type1) && type2 == ptrfromreg(type1)) { MEMPTR* memptr = (MEMPTR*)(val2); if (memptr->reg1 == -1) { if (type1 == TREG32) bytes.assign("\xA1").append(to4bytes(memptr->constant)); else if (type1 == TREG16) bytes.assign("\x66\xA1").append(to4bytes(memptr->constant)); else if (type1 == TREG8) bytes.assign("\xA0").append(to4bytes(memptr->constant)); if (memptr->deletable) delete memptr; return; } } else if (val2 == EAX && isreg(type2) && type1 == ptrfromreg(type2)) { MEMPTR* memptr = (MEMPTR*)(val1); if (memptr->reg1 == -1) { if (type2 == TREG32) bytes.assign("\xA3").append(to4bytes(memptr->constant)); else if (type2 == TREG16) bytes.assign("\x66\xA3").append(to4bytes(memptr->constant)); else if (type2 == TREG8) bytes.assign("\xA2").append(to4bytes(memptr->constant)); if (memptr->deletable) delete memptr; return; } } //move data addresses if (type2 == TDATAADDRESS) { set(type1, val1, TCONSTANT, IMAGEBASE); tag = TAGOPXDATAADDRESS; tag2 = val2; tag3 = type1; tag4 = val1; //move code addresses } else if (type2 == TCODEADDRESS) { set(type1, val1, TCONSTANT, IMAGEBASE); tag = TAGOPXCODEADDRESS; tagp = val2; tag3 = type1; tag4 = val1; //regular setting } else if (type1 == TREG32) setreg(type1, val1, type2, val2, "", "", 0xB8, "", "\x8B"); else if (type1 == TREG16) setreg(type1, val1, type2, val2, "", "\x66", 0xB8, "", "\x66\x8B"); else if (type1 == TREG8) setreg(type1, val1, type2, val2, "", "", 0xB0, "", "\x8A"); else if (type1 == TDWORDPTR) setptr(type1, val1, type2, val2, "\x89", "", "\xC7", 0); else if (type1 == TWORDPTR) setptr(type1, val1, type2, val2, "\x66\x89", "", "\x66\xC7", 0); else if (type1 == TBYTEPTR) setptr(type1, val1, type2, val2, "\x88", "\xC6", "", 0); else if (isdataptr(type1)) setdataptr(type1, val1, type2, val2); }
void and_imm_rm32(int size, int reg) { /* * imm is ok because it is sign extended * unlike add and sub when reg==eax */ //check if size is an imm8 if(0x0<=size && size <=0xff) { //check if register if(isreg(reg)) { //special case for accumulator register eax /* if(reg==EAX) { //add imm8 to r8 putbyte(0x24); putbyte(size); } else {*/ //add sign extended imm8 to r32 putbyte(0x83); putbyte(0xe0+reg); putbyte(size); // } } //memory location else { putbyte(0x83); putbyte(0x20+reg-0x8); putbyte(size); } } //size is bigger than imm8 else { if(isreg(reg)) { //special case for accumulator register eax if(reg==EAX) { putbyte(0x25); put4bytes(size); } else { putbyte(0x81); putbyte(0xe0+reg); put4bytes(size); } } else { putbyte(0x81); putbyte(0x20+reg-0x8); put4bytes(size); } } }
void dec_reg(int reg) { if(isreg(reg)) { putbyte(0x48+reg); } else aerror("Error: dec reg is not a register"); }
int expr() { int mode; int id1; int ixarr; int ids; if (istoken(T_CONST)) {doconst(); return 1; } mode=typeName(); /*0=V,1=*,2=&*/ if (token=='(') {docall1(); goto e1; } if (isreg()) goto e1; id1=searchname(); gettypes(id1); ids=signi; ixarr=0; if (istoken('[')) { ixarr=searchname(); expect(T_NAME); expect(']'); gettypes(ixarr); if (widthi==0) error1("Arrayindex muss int sein"); } if (istoken(T_PLUSPLUS )) {if(mode)error1("Nur var erlaubt");doinc();goto e1;} if (istoken(T_MINUSMINUS)) {if(mode)error1("Nur var erlaubt");dodec();goto e1;} if (istoken(T_PLUSASS )) {compoundass("add", mode); goto e1;} if (istoken(T_MINUSASS )) {compoundass("sub", mode); goto e1;} if (istoken(T_ANDASS )) {compoundass("and", mode); goto e1;} if (istoken(T_ORASS )) {compoundass("or" , mode); goto e1;} if (istoken(T_MULASS )) {error1("nicht implementiert");} if (istoken(T_DIVASS )) {error1("nicht implementiert");} if (istoken('=')) { isconst=expr(); if (isconst) { if(mode==0) {prs("\n;++++ mov "); printName(id1); prs(", "); prnum(lexval); } } doassign(mode, id1, ixarr); goto e1;} dovar1(mode, "mov", ixarr, id1); e1: if (istoken('+')) rterm("add"); else if (istoken('-')) rterm("sub" ); else if (istoken('&')) rterm("and" ); else if (istoken('|')) rterm("or" ); else if (istoken(T_LESSLESS)) rterm("shl"); else if (istoken(T_GREATGREAT)) rterm("shr"); else if (istoken('*')) domul (ids); else if (istoken('/')) doidiv(ids); else if (istoken('%')) domod (ids); if (isrelational()) { rterm("cmp"); cmpneg(ids);} return 0; }
void inc_reg(int reg) { if(isreg(reg)) { putbyte(0x40+reg); } else aerror("Error: inc reg is not a register"); }
/* setup for assignment operator */ int setasg(NODE *p, int cookie) { if (x2debug) printf("setasg(%p,%s)\n", p, prcook(cookie)); if (p->n_left->n_op == FLD && !isreg(p->n_left->n_left)) { NODE *l, *r; int reg; geninsn(p->n_left->n_left, INAREG); reg = DECRA(p->n_left->n_left->n_reg, 0); l = tcopy(p->n_left->n_left); p->n_left->n_left->n_op = REG; p->n_left->n_left->n_rval = reg; p->n_left->n_left->n_lval = 0; r = tcopy(p->n_left->n_left); geninsn(p->n_left, INAREG); l = mkbinode(ASSIGN, l, r, l->n_type); geninsn(l, INAREG); return (1); } return (0); }
//set a 2 operand reg/??? instruction using the given bytes void AssemblyInstruction::setreg(int rtype, intptr_t regn, int type2, intptr_t val2, string ocbyteconstant, string ocbigconstant, int yy, string ocspecialconstant, string ocvalat) { //reg/constant if (type2 == TCONSTANT) { //EAX = AX = AL, all share the special if (regn == EAX && ocspecialconstant.length() > 0) { if (rtype == TREG8) bytes.assign(ocspecialconstant).append(1, (char)(val2)); else bytes.assign(ocspecialconstant).append(rtype == TREG16 ? to2bytes((int)(val2)) : to4bytes((int)(val2))); //byte constant with any reg } else if (rtype == TREG8 || (val2 >= -128 && val2 <= 127 && ocbyteconstant.compare("") != 0)) bytes.assign(ocbyteconstant).append(1, (char)(yy + regn)).append(1, (char)(val2)); //word or dword constant else bytes.assign(ocbigconstant).append(1, (char)(yy + regn)).append(rtype == TREG16 ? to2bytes((int)(val2)) : to4bytes((int)(val2))); //reg/reg } else if (isreg(type2)) bytes.assign(ocvalat).append(1, (char)(0xC0 + regn * 8 + val2)); //reg/ptr else if (isptr(type2)) bytes.assign(ocvalat).append(((MEMPTR*)(val2))->toptr(0, (char)(regn))); //reg/data ptr else if (isdataptr(type2)) { set(rtype, regn, ptrfromreg(rtype), blankdataptr); tag = TAGREGDATAPTR; tag2 = val2; tag3 = rtype; tag4 = regn; } }
/* * Turn a UMUL-referenced node into OREG. * Be careful about register classes, this is a place where classes change. * * AMD64 (and i386) have a quite powerful addressing scheme: * : 4(%rax) 4 + %rax * : 4(%rbx,%rax,8) 4 + %rbx + %rax * 8 * : 4(,%rax) 4 + %rax * 8 * The 8 above can be 1,2,4 or 8. */ void offstar(NODE *p, int shape) { NODE *l; if (x2debug) { printf("offstar(%p)\n", p); fwalk(p, e2print, 0); } if (isreg(p)) return; /* Matched (%rax) */ if (findls(p, 0)) return; /* Matched (,%rax,8) */ if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_left->n_op == ICON) { l = p->n_right; if (isreg(l)) return; /* Matched 4(%rax) */ if (findls(l, 0)) return; /* Matched 4(,%rax,8) */ if (l->n_op == PLUS && isreg(l->n_right)) { if (findls(l->n_left, 0)) return; /* Matched 4(%rbx,%rax,8) */ (void)geninsn(l->n_left, INAREG); return; /* Generate 4(%rbx,%rax) */ } (void)geninsn(l, INAREG); return; /* Generate 4(%rbx) */ } if (p->n_op == PLUS) { if (!isreg(p->n_left)) /* ensure right is REG */ (void)geninsn(p->n_left, INAREG); if (isreg(p->n_right)) return; /* Matched (%rax,%rbx) */ if (findls(p->n_right, 0)) return; /* Matched (%rax,%rbx,4) */ (void)geninsn(p->n_right, INAREG); return; /* Generate (%rbx,%rax) */ } (void)geninsn(p, INAREG); }
void lea_m32_r32_disp(int source, int dest, int disp) { if(!isreg(source)) { if(isreg(dest)) { putbyte(0x8d); if(-127<=(PSIZE*disp) && (disp*PSIZE)<=128) { putbyte(0x40+(dest*0x8)+source-0x8); putbyte((PSIZE*disp)&0xff); } else { putbyte(0x80+(dest*0x8)+source-0x8); put_little_endian(PSIZE*disp); } } else aerror("Error in lea. dest is not a register"); } else aerror("Error in lea. source is not a memory loc"); }
void cmp_imm_r32(int size, int reg) { //sign extended imm if(0<=size && size<=255) { if(isreg(reg)) { putbyte(0x83); putbyte(0xf8+reg); putbyte(size); } else aerror("Error: not reg in cmp_imm_r32"); } else { //imm32 if(isreg(reg)) { putbyte(0x81); putbyte(0xf8+reg); put4bytes(size); } else aerror("Error: not reg in cmp_imm_r32"); } }
void sub_imm32_rm32(int size, int reg) { if(isreg(reg)) { putbyte(0x81); putbyte(0xe8+reg); put_little_endian(size); } else { putbyte(0x81); putbyte(0x28+reg-0x8); put_little_endian(size); } }
void sub_imm8_rm32(int size, int reg) { //check if register if(isreg(reg)) { putbyte(0x83); //sub sign-extended imm8 from r/m32 putbyte(0xe8+reg); putbyte(size); } else { putbyte(0x83); putbyte(0x28+reg-0x8);//FIXME is this right? putbyte(size); } }
static int inctree(NODE *p) { if (p->n_op == MINUS && p->n_left->n_op == ASSIGN && p->n_left->n_right->n_op == PLUS && treecmp(p->n_left->n_left, p->n_left->n_right->n_left) && p->n_right->n_op == ICON && p->n_right->n_lval == 1 && p->n_left->n_right->n_right->n_op == ICON && p->n_left->n_right->n_right->n_lval == 1) { /* post-increment by 1; (r0)+ */ if (isreg(p->n_left->n_left)) /* Ignore if index not in reg */ return 1; } return 0; }
//set a 2 operand data pointer instruction void AssemblyInstruction::setdataptr(int type1, int val1, int type2, int val2) { if (isreg(type2)) { set(ptrfromreg(type2), blankdataptr, type2, val2); tag = TAGDATAPTRREG; tag2 = val1; tag3 = type2; tag4 = val2; } else if (type2 == TCONSTANT) { set(ptrfromdataptr(type1), blankdataptr, type2, val2); tag = tagconstantfromdataptr(type1); tag2 = val1; tag3 = type2; tag4 = val2; } }
/* * Turn a UMUL-referenced node into OREG. * Be careful about register classes, this is a place where classes change. */ void offstar(NODE *p, int shape) { NODE *r; if (x2debug) printf("offstar(%p)\n", p); if (isreg(p)) return; /* Is already OREG */ r = p->n_right; if( p->n_op == PLUS || p->n_op == MINUS ){ if( r->n_op == ICON ){ if (isreg(p->n_left) == 0 || (p->n_left->n_op == REG && p->n_left->n_rval != 2 && p->n_left->n_rval != 3)) (void)geninsn(p->n_left, INBREG); /* Converted in ormake() */ return; } } (void)geninsn(p, INBREG); }
void mov_rm32_rm32(int dest, int source) { //eg, "mov dest, source" if(isreg(dest)) { //destination is a register putbyte(0x89); if(isreg(source)) { //we have a "mov %eax,%ebx" putbyte((0xc0+(dest*0x8))+source); } else { if(dest==ESP) aerror("Error: ESP in mov_rm32_rm32"); if(source==ESPM) { putbyte(0x4+(dest*0x8)); putbyte(0x24); //SIB ESP } else { //we have a "mov %eax,(%ebx)" putbyte((dest*0x8)+source-0x8); } } } else { //destination is a memory offset located in register putbyte(0x8b); if(isreg(source)) { //we have a "mov (%eax),%ebx" putbyte((source*0x8)+dest-0x8); } else { //we have a "mov (%eax),(%ebx)" //this is an illegal instruction aerror("Error: in mov_rm32_rm32"); } } }
/* * Turn a UMUL-referenced node into OREG. */ void offstar(NODE *p, int shape) { if (x2debug) printf("offstar(%p)\n", p); if (p->n_op == PLUS || p->n_op == MINUS) { if (p->n_right->n_op == ICON) { if (isreg(p->n_left) == 0) (void)geninsn(p->n_left, INAREG); /* Converted in ormake() */ return; } } (void)geninsn(p, INAREG); }
void mov_r32_addr(int dest, void *source) { //eg, "mov %eax, 0x0" where 0x0 = C_stack if(isreg(dest)) { //special case for eax if(dest==EAX) { putbyte(0xa3); put_addr(source); } else { putbyte(0x89); putbyte((dest*0x8)+0x5); put_addr(source); } } else aerror("Error in moving an address to a reg"); }
void mov_addr_r32(void *dest, int source) { //eg, "mov 0x0, %eax" where 0x0 = C_stack if(isreg(source)) { //special case for eax if(source==EAX) { putbyte(0xa1); put_addr(dest); } else { putbyte(0x8b); putbyte((source*0x8)+0x5); put_addr(dest); } } else aerror("Error in moving a reg to an address"); }
/* * Check if LS and try to make it indexable. * Ignore SCONV to long. * Return 0 if failed. */ static int findls(NODE *p, int check) { CONSZ c; if (p->n_op == SCONV && p->n_type == LONG && p->n_left->n_type == INT) p = p->n_left; /* Ignore pointless SCONVs here */ if (p->n_op != LS || p->n_right->n_op != ICON) return 0; if ((c = p->n_right->n_lval) != 1 && c != 2 && c != 3) return 0; if (check == 1 && p->n_left->n_op != REG) return 0; if (!isreg(p->n_left)) (void)geninsn(p->n_left, INAREG); return 1; }
//set a 2 operand memory pointer/??? instruction using the given bytes void AssemblyInstruction::setptr(int ptype, intptr_t val1, int type2, intptr_t val2, string ocreg, string ocbyteconstant, string ocbigconstant, int yy) { //ptr/reg if (isreg(type2)) bytes.assign(ocreg).append(((MEMPTR*)(val1))->toptr(0, (char)(val2))); //ptr/constant else if (type2 == TCONSTANT) { //byte constant if (ptype == TBYTEPTR || (val2 >= -128 && val2 <= 127 && ocbyteconstant.compare("") != 0)) bytes.assign(ocbyteconstant).append(((MEMPTR*)(val1))->toptr((char)(yy))).append(1, (char)(val2)); //word or dword constant else if (ptype == TWORDPTR) bytes.assign(ocbigconstant).append(((MEMPTR*)(val1))->toptr((char)(yy))).append(to2bytes((int)(val2))); else bytes.assign(ocbigconstant).append(((MEMPTR*)(val1))->toptr((char)(yy))).append(to4bytes((int)(val2))); } }
int r2c_main(int ac, char **av) { int c; char *file = 0; char *p; int rc = 1; int product = 1; MDBM *idDB, *goneDB; MDBM *md5DB = 0; RANGE rargs = {0}; char *sfile; char **revs = 0; longopt lopts[] = { { "standalone", 'S' }, /* treat comps as standalone */ { 0, 0 } }; while ((c = getopt(ac, av, "PRr;S", lopts)) != -1) { switch (c) { case 'P': break; // do not doc case 'R': // do not doc case 'S': product = 0; break; case 'r': if (range_addArg(&rargs, optarg, 0)) usage(); break; default: usage(); break; } } unless ((file = av[optind]) && !av[optind+1]) usage(); sfile = name2sccs(file); if (!isreg(sfile) && isKey(file)) { proj_cd2root(); idDB = loadDB(IDCACHE, 0, DB_IDCACHE); goneDB = loadDB(GONE, 0, DB_GONE); file = key2path(file, idDB, goneDB, &md5DB); mdbm_close(idDB); mdbm_close(goneDB); mdbm_close(md5DB); unless (file) goto out; }
addsob() { register struct node *p, *p1; for (p = &first; (p1 = p->forw)!=0; p = p1) { if (p->op==DEC && isreg(p->code)>=0 && p1->combop==(CBR|JNE<<8)) { if (p->refc < p1->ref->refc) continue; if (p->refc - p1->ref->refc > 50) continue; p->labno = p1->labno; p->combop = SOB; p1->forw->back = p; p->forw = p1->forw; nsob++; } } }
addsob() { register struct node *p, *p1; for (p = &first; (p1 = p->forw)!=0; p = p1) { if (p->op==DEC && isreg(p->code)>=0 && p1->op==CBR && p1->subop==JNE) { if (p->refc < p1->ref->refc) continue; if (toofar(p1)) continue; p->labno = p1->labno; p->op = SOB; p->subop = 0; p1->forw->back = p; p->forw = p1->forw; nsob++; } } }
/** * handle the DEOP command */ void cs_deop(char *src, int ac, char **av) { char *nick,*chan; int level_src,level_target; user *u,*u1; ChanInfo *c; if(ac<3) { notice(cs_name,src,CS_OP_ERR_USAGE,"DEOP"); notice(cs_name,src,CS_RPL_HLP,cs_name, "DEOP"); return; } nick = sstrdup(av[2]); chan = sstrdup(av[1]); if(!isregcs(chan)) { notice(cs_name,src,CS_ERR_NOTREG,chan); return; } if(!isreg(nick)) { notice(cs_name,src,NS_ERR_NOTREG,nick); return; } u = finduser(src); u1 = finduser(nick); c = findchan(chan); level_src = cs_xop_get_level(u,c); level_target = cs_xop_get_level(u1,c); if(level_src<AOP_LIST) { notice(cs_name,src,CS_XOP_ERR_HIGHERACCESS,"Aop"); return; } if(level_target<AOP_LIST) { if(stricmp(src,nick)==0) { notice(cs_name,src,CS_XOP_ERR_HIGHERACCESS,"Aop"); return; } else { notice(cs_name,src,CS_XOP_ERR_HIGHERACCESS2,nick); return; } } deop(cs_name,nick,chan); return; }
/* ------------------------------------------------------------ * change_dir: * accept a pathname and change to that directory * * (1) Check pathname for NULL, set to root if so * (2) get INODE of pathname into a MINODE * (3) get INODE into minode[] table * (4) check DIR type, return if not a DIR * (5) dispose of running->cwd, change to found MINODE* dir * -----------------------------------------------------------------*/ void change_dir(char** args) { MINODE* dir; int ino; int dev = running->cwd->dev; // (1) Check for pathname if(args[0] == NULL) // no path provided { iput(running->cwd); // Dispose of cwd running->cwd = root; // change to root return; } // (2) get INODE of pathname into a MINODE ino = getino(&dev, args[0]); // (2.1) get inumber dir = iget(dev, ino); // (3) get INODE into minode[] table if(dir == NULL) // unable to find directory { printf("No such file or directory %s\n", args[0]); return; } else // Release running->cwd and update to dir { // (4) Check DIR type, return if not directory if(isreg(dir)) // if dir is a regular file { printf("Error: Not a directory %s\n", args[0]); iput(dir); // release minode[] entry return; } // (5) We've found the (valid) directory iput(running->cwd); // dispose the current cwd running->cwd = iget(dir->dev, dir->ino); // load new cwd by calling iget iput(dir); // write back to disk } }