/* Print out the sib byte of the parsed instruction in the given decoder state * to the given file. */ static void SibPrint(const NCDecoderInst* dinst, struct Gio* fp) { uint8_t sib = NCInstBytesByte(&dinst->inst_bytes, NCSibOffset(dinst)); if (!dinst->inst.hassibbyte) { /* This should not happen. */ gprintf(fp, "?"); } else if (sib_ss(sib) == 0) { if (sib_base(sib) == 5) { /* This code is JUST WRONG!. However, I am not fixing since * the decoder printer is broken in so many other ways!. See tables * 2-1 and 2-2 of "Intel 64 and IA-32 Architectures Software Developer's * Manual" for details of what should be done (there are * 3 cases, depending on the value of the mod field of the modrm * byte). * Note: While the changes here are not correct, they at least make * sure that we process bytes that are actually in the instruction. * That is, the code doesn't accidentally walk off the end of the * parsed instruction. */ gprintf(fp, "[0x%x]", DispValue32(dinst)); } else { /* Has a base register */ if (sib_index(sib) == 4) { /* No index */ gprintf(fp, "[%s]", gp_regs[sib_base(sib)]); } else { gprintf(fp, "[%s + %s]", gp_regs[sib_base(sib)], gp_regs[sib_index(sib)]); } } } else { if (sib_index(sib) == 4) { /* No index */ gprintf(fp, "[%s]", gp_regs[sib_base(sib)]); } else { gprintf(fp, "[%s + %d * %s]", gp_regs[sib_base(sib)], 1 << sib_ss(sib), gp_regs[sib_index(sib)]); } } }
/* * Read address at location and return updated location. */ db_addr_t db_read_address(db_addr_t loc, int short_addr, int regmodrm, int rex, struct i_addr *addrp) { int mod, rm, sib, index, disp, size; size = (short_addr ? LONG : QUAD); mod = f_mod(regmodrm); rm = f_rm(regmodrm, rex); if (mod == 3) { addrp->is_reg = TRUE; addrp->disp = rm; return (loc); } addrp->is_reg = FALSE; addrp->index = 0; if (rm == 4 || rm == 12) { get_value_inc(sib, loc, 1, FALSE); rm = sib_base(sib, rex); index = sib_index(sib, rex); if (index != 4) addrp->index = db_reg[size][index]; addrp->ss = sib_ss(sib); } switch (mod) { case 0: if (rm == 5) { get_value_inc(addrp->disp, loc, 4, FALSE); addrp->base = 0; } else { addrp->disp = 0; addrp->base = db_reg[size][rm]; } break; case 1: get_value_inc(disp, loc, 1, TRUE); addrp->disp = disp; addrp->base = db_reg[size][rm]; break; case 2: get_value_inc(disp, loc, 4, FALSE); addrp->disp = disp; addrp->base = db_reg[size][rm]; break; } return (loc); }
/* * Read address at location and return updated location. */ db_addr_t db_read_address(db_addr_t loc, int short_addr, int regmodrm, struct i_addr *addrp) { int mod, rm, sib, index, disp; mod = f_mod(regmodrm); rm = f_rm(regmodrm); if (mod == 3) { addrp->is_reg = TRUE; addrp->disp = rm; return (loc); } addrp->is_reg = FALSE; addrp->index = 0; if (short_addr) { addrp->index = 0; addrp->ss = 0; switch (mod) { case 0: if (rm == 6) { get_value_inc(disp, loc, 2, FALSE); addrp->disp = disp; addrp->base = 0; } else { addrp->disp = 0; addrp->base = db_index_reg_16[rm]; } break; case 1: get_value_inc(disp, loc, 1, TRUE); disp &= 0xffff; addrp->disp = disp; addrp->base = db_index_reg_16[rm]; break; case 2: get_value_inc(disp, loc, 2, FALSE); addrp->disp = disp; addrp->base = db_index_reg_16[rm]; break; } } else { if (rm == 4) { get_value_inc(sib, loc, 1, FALSE); rm = sib_base(sib); index = sib_index(sib); if (index != 4) addrp->index = db_reg[LONG][index]; addrp->ss = sib_ss(sib); } switch (mod) { case 0: if (rm == 5) { get_value_inc(addrp->disp, loc, 4, FALSE); addrp->base = 0; } else { addrp->disp = 0; addrp->base = db_reg[LONG][rm]; } break; case 1: get_value_inc(disp, loc, 1, TRUE); addrp->disp = disp; addrp->base = db_reg[LONG][rm]; break; case 2: get_value_inc(disp, loc, 4, FALSE); addrp->disp = disp; addrp->base = db_reg[LONG][rm]; break; } } return (loc); }
/* * Read address at location and return updated location. */ static db_addr_t db_read_address(db_addr_t loc, int short_addr, int rex, int regmodrm, struct i_addr *addrp) { int mod, rm, sib, index, disp, size, have_sib; mod = f_mod(rex, regmodrm); rm = f_rm(rex, regmodrm); if (mod == 3) { addrp->is_reg = TRUE; addrp->disp = rm; return (loc); } addrp->is_reg = FALSE; addrp->index = NULL; if (short_addr) size = LONG; else size = QUAD; if ((rm & 0x7) == 4) { get_value_inc(sib, loc, 1, FALSE); rm = sib_base(rex, sib); index = sib_index(rex, sib); if (index != 4) addrp->index = db_reg[1][size][index]; addrp->ss = sib_ss(rex, sib); have_sib = 1; } else have_sib = 0; switch (mod) { case 0: if (rm == 5) { get_value_inc(addrp->disp, loc, 4, FALSE); if (have_sib) addrp->base = NULL; else if (short_addr) addrp->base = "%eip"; else addrp->base = "%rip"; } else { addrp->disp = 0; addrp->base = db_reg[1][size][rm]; } break; case 1: get_value_inc(disp, loc, 1, TRUE); addrp->disp = disp; addrp->base = db_reg[1][size][rm]; break; case 2: get_value_inc(disp, loc, 4, FALSE); addrp->disp = disp; addrp->base = db_reg[1][size][rm]; break; } return (loc); }