Search in sources :

Example 1 with OpMem

use of suite.assembler.Amd64.OpMem in project suite by stupidsing.

the class Amd64Dump method dump.

private String dump(Operand op0) {
    int pointerSize = 4;
    OpReg[] regs;
    String name;
    if (pointerSize == 4)
        regs = amd64.reg32;
    else if (pointerSize == 8)
        regs = amd64.reg64;
    else
        return Fail.t();
    if (op0 instanceof OpImm) {
        OpImm opImm = (OpImm) op0;
        return dump(opImm.imm, opImm.size);
    } else if (op0 instanceof OpMem) {
        OpMem opMem = (OpMem) op0;
        int baseReg = opMem.baseReg;
        int indexReg = opMem.indexReg;
        String s = // 
        "" + // 
        (0 <= baseReg ? " + " + dump(regs[baseReg]) : "") + // 
        (0 <= indexReg ? " + " + dump(regs[indexReg]) + " * " + (1 << opMem.scale) : "") + (0 < opMem.dispSize ? dumpDisp(opMem.disp, pointerSize) : "");
        return "[" + s.substring(3) + "]";
    } else if ((name = (amd64.registerByName.inverse().get(op0).name)) != null)
        return name;
    else
        return op0.toString();
}
Also used : OpImm(suite.assembler.Amd64.OpImm) OpMem(suite.assembler.Amd64.OpMem) OpReg(suite.assembler.Amd64.OpReg)

Example 2 with OpMem

use of suite.assembler.Amd64.OpMem in project suite by stupidsing.

the class Amd64Interpret method interpret.

public int interpret(List<Instruction> instructions, Bytes code, Bytes input) {
    mem.position(positionCode0);
    mem.put(code.bs);
    eip = positionCode0;
    regs[esp] = baseStackx - 16;
    IntIntMap labels = new IntIntMap();
    for (int i = 0; i < instructions.size(); i++) {
        int i_ = i;
        Instruction instruction = instructions.get(i_);
        if (instruction.insn == Insn.LABEL)
            labels.update((int) ((OpImm) instruction.op0).imm, i0 -> i_ + 1);
    }
    while (true) {
        Instruction instruction = instructions.get(eip++);
        if (Boolean.FALSE)
            LogUtil.info(state(instruction));
        try {
            Operand op0 = instruction.op0;
            Operand op1 = instruction.op1;
            int source0, source1;
            IntSink assign;
            if (op0 instanceof OpImm) {
                source0 = (int) ((OpImm) op0).imm;
                assign = null;
            } else if (op0 instanceof OpMem) {
                int index = index(address((OpMem) op0));
                source0 = mem.getInt(index);
                assign = i -> mem.putInt(index, i);
            } else if (op0 instanceof OpReg) {
                int reg = ((OpReg) op0).reg;
                source0 = regs[reg];
                assign = i -> {
                    regs[reg] = i;
                };
            } else {
                source0 = 0;
                assign = null;
            }
            if (op1 instanceof OpImm)
                source1 = (int) ((OpImm) op1).imm;
            else if (op1 instanceof OpMem)
                source1 = mem.getInt(index(address((OpMem) op1)));
            else if (op1 instanceof OpReg)
                source1 = regs[((OpReg) op1).reg];
            else
                source1 = 0;
            switch(instruction.insn) {
                case ADD:
                    assign.sink(source0 + source1);
                    break;
                case CALL:
                    push(eip);
                    eip = labels.get(source0);
                    break;
                case CMP:
                    c = Integer.compare(source0, source1);
                    break;
                case DEC:
                    assign.sink(source0 - 1);
                    break;
                case INC:
                    assign.sink(source0 + 1);
                    break;
                case INT:
                    if (source0 == -128)
                        if (regs[eax] == 1)
                            return regs[ebx];
                        else if (regs[eax] == 3) {
                            int length = min(regs[edx], input.size());
                            int di = index(regs[ecx]);
                            for (int i = 0; i < length; i++) mem.put(di++, input.get(i));
                            input = input.range(length);
                            regs[eax] = length;
                        } else if (regs[eax] == 4) {
                            int length = regs[edx];
                            int si = index(regs[ecx]);
                            byte[] bs = new byte[length];
                            for (int i = 0; i < length; i++) bs[i] = mem.get(si++);
                            output.sink(Bytes.of(bs));
                        } else
                            Fail.t();
                    else
                        Fail.t();
                    break;
                case JE:
                    if (c == 0)
                        eip = labels.get(source0);
                    break;
                case JMP:
                    eip = labels.get(source0);
                    break;
                case JG:
                    if (0 < c)
                        eip = labels.get(source0);
                    break;
                case JGE:
                    if (0 <= c)
                        eip = labels.get(source0);
                    break;
                case JL:
                    if (c < 0)
                        eip = labels.get(source0);
                    break;
                case JLE:
                    if (c <= 0)
                        eip = labels.get(source0);
                    break;
                case JNE:
                    if (c != 0)
                        eip = labels.get(source0);
                    break;
                case LABEL:
                    break;
                case LEA:
                    assign.sink(address((OpMem) op1));
                    break;
                case MOV:
                    assign.sink(source1);
                    break;
                case POP:
                    assign.sink(pop());
                    break;
                case PUSH:
                    push(source0);
                    break;
                case RET:
                    eip = pop();
                    break;
                case SUB:
                    assign.sink(source0 - source1);
                    break;
                case XOR:
                    assign.sink(source0 ^ source1);
                    break;
                default:
                    Fail.t();
            }
        } catch (Exception ex) {
            LogUtil.info(state(instruction));
            throw ex;
        }
    }
}
Also used : Insn(suite.assembler.Amd64.Insn) Friends.min(suite.util.Friends.min) LogUtil(suite.os.LogUtil) OpMem(suite.assembler.Amd64.OpMem) IntIntMap(suite.primitive.adt.map.IntIntMap) Bytes(suite.primitive.Bytes) BytesBuilder(suite.primitive.Bytes.BytesBuilder) Instruction(suite.assembler.Amd64.Instruction) OpReg(suite.assembler.Amd64.OpReg) To(suite.util.To) ByteBuffer(java.nio.ByteBuffer) Funp_(suite.funp.Funp_) OpImm(suite.assembler.Amd64.OpImm) List(java.util.List) IntSink(suite.primitive.IntPrimitives.IntSink) Operand(suite.assembler.Amd64.Operand) Sink(suite.util.FunUtil.Sink) Fail(suite.util.Fail) IntIntMap(suite.primitive.adt.map.IntIntMap) OpImm(suite.assembler.Amd64.OpImm) Operand(suite.assembler.Amd64.Operand) IntSink(suite.primitive.IntPrimitives.IntSink) OpMem(suite.assembler.Amd64.OpMem) Instruction(suite.assembler.Amd64.Instruction) OpReg(suite.assembler.Amd64.OpReg)

Example 3 with OpMem

use of suite.assembler.Amd64.OpMem in project suite by stupidsing.

the class Amd64Assemble method modrm.

private Modrm modrm(Operand operand, int num) {
    int mod, rm, s, i, b, dispSize;
    long disp;
    if (operand instanceof OpReg) {
        // EAX
        OpReg op = (OpReg) operand;
        mod = 3;
        rm = op.reg;
        s = i = b = -1;
        dispSize = 0;
        disp = 0;
    } else if (operand instanceof OpMem) {
        OpMem op = (OpMem) operand;
        int baseReg = op.baseReg;
        int indexReg;
        int ds0 = op.dispSize;
        if ((op.indexReg & 7) != 4)
            indexReg = op.indexReg;
        else
            indexReg = Fail.t("bad operand");
        if (baseReg < 0 && indexReg < 0) {
            // [0x1234]
            mod = 0;
            rm = 5;
            s = i = b = -1;
            dispSize = 4;
        } else if (0 <= baseReg && indexReg < 0)
            if ((baseReg & 7) != 4) {
                // [EAX], [EAX + 0x1234]
                int ds1 = (baseReg & 7) == 5 && ds0 == 0 ? 1 : ds0;
                mod = dispMod(ds1);
                rm = baseReg;
                s = i = b = -1;
                dispSize = ds1;
            } else {
                // [ESP + 0], [ESP + 0x1234]
                int ds1 = baseReg == 4 && ds0 == 0 ? 1 : ds0;
                mod = dispMod(ds1);
                rm = 4;
                s = 0;
                i = 4;
                b = baseReg & 7;
                dispSize = ds1;
            }
        else if (baseReg < 0 && 0 <= indexReg) {
            // [4 * EBX + 0x1234]
            mod = 0;
            rm = 4;
            s = scale(op);
            i = indexReg;
            b = 5;
            dispSize = 4;
        } else if (0 <= baseReg && 0 <= indexReg)
            if ((baseReg & 7) != 5) {
                // [4 * EBX + EAX + 0x1234]
                mod = dispMod(ds0);
                rm = 4;
                s = scale(op);
                i = indexReg;
                b = baseReg;
                dispSize = ds0;
            } else
                throw new RuntimeException("bad operand");
        else
            throw new RuntimeException("bad operand");
        disp = op.disp;
    } else
        throw new RuntimeException("bad operand");
    Modrm modrm = new Modrm();
    modrm.size = operand.size;
    modrm.mod = mod;
    modrm.num = num;
    modrm.rm = rm;
    modrm.s = s;
    modrm.i = i;
    modrm.b = b;
    modrm.dispSize = dispSize;
    modrm.disp = disp;
    return modrm;
}
Also used : OpMem(suite.assembler.Amd64.OpMem) OpReg(suite.assembler.Amd64.OpReg)

Example 4 with OpMem

use of suite.assembler.Amd64.OpMem in project suite by stupidsing.

the class Amd64Parse method parseOpMem.

private Operand parseOpMem(Node[] m, int size) {
    OpMem opMem = amd64.new OpMem();
    opMem.size = size;
    opMem.indexReg = -1;
    opMem.baseReg = -1;
    opMem.dispSize = 0;
    for (Node component : scan(m[0], ".0 + .1")) if ((m = Suite.pattern(".0 * .1").match(component)) != null)
        if (opMem.indexReg < 0) {
            opMem.indexReg = amd64.regByName.get(m[0]).reg;
            opMem.scale = ((Int) m[1]).number;
        } else
            Fail.t("bad operand");
    else if (component instanceof Int)
        if (opMem.dispSize == 0) {
            opMem.disp = ((Int) component).number;
            opMem.dispSize = 4;
        } else
            Fail.t("bad operand");
    else if (opMem.baseReg < 0)
        opMem.baseReg = amd64.regByName.get(component).reg;
    else
        Fail.t("bad operand");
    return opMem;
}
Also used : Node(suite.node.Node) OpMem(suite.assembler.Amd64.OpMem) Int(suite.node.Int)

Example 5 with OpMem

use of suite.assembler.Amd64.OpMem in project suite by stupidsing.

the class P4DecomposeOperand method decomposeOpMem.

public OpMem decomposeOpMem(int fd, Funp n0, int disp0, int size) {
    class Decompose {

        private Operator operator;

        private List<Funp> nodes = new ArrayList<>();

        private Decompose(Operator operator) {
            this.operator = operator;
        }

        private void decompose(Funp n_) {
            FunpTree tree;
            if (n_ instanceof FunpTree && (tree = (FunpTree) n_).operator == operator) {
                decompose(tree.left);
                decompose(tree.right);
            } else
                nodes.add(n_);
        }
    }
    Fun2<Operator, Funp, List<Funp>> decompose = (operator, n_) -> {
        Decompose dec = new Decompose(operator);
        dec.decompose(n_);
        return dec.nodes;
    };
    class DecomposeMult {

        private long scale = 1;

        private OpReg reg;

        private List<Funp> mults = new ArrayList<>();

        private void decompose(Funp n0) {
            FunpTree2 tree;
            Funp r;
            for (Funp n1 : decompose.apply(TermOp.MULT__, n0)) if (n1 instanceof FunpFramePointer && isUseEbp && reg == null)
                reg = amd64.ebp;
            else if (n1 instanceof FunpNumber)
                scale *= ((FunpNumber) n1).i.get();
            else if (// 
            n1 instanceof FunpTree2 && // 
            (tree = (FunpTree2) n1).operator == TreeUtil.SHL && (r = tree.right) instanceof FunpNumber) {
                decompose(tree.left);
                scale <<= ((FunpNumber) r).i.get();
            } else
                mults.add(n1);
        }
    }
    class DecomposePlus {

        private OpReg baseReg = null, indexReg = null;

        private int scale = 1, disp = disp0;

        private boolean ok = is124(size);

        private DecomposePlus(Funp n0) {
            for (Funp n1 : decompose.apply(TermOp.PLUS__, n0)) if (n1 instanceof FunpFramePointer && !isUseEbp) {
                addReg(amd64.esp, 1);
                disp -= fd;
            } else {
                DecomposeMult dec = new DecomposeMult();
                dec.decompose(n1);
                if (dec.mults.isEmpty()) {
                    OpReg reg_ = dec.reg;
                    long scale_ = dec.scale;
                    if (reg_ != null)
                        addReg(reg_, scale_);
                    else
                        disp += scale_;
                } else
                    ok = false;
            }
        }

        private void addReg(OpReg reg_, long scale_) {
            if (scale_ == 1 && baseReg == null)
                baseReg = reg_;
            else if (is1248(scale_) && indexReg == null) {
                indexReg = reg_;
                scale = (int) scale_;
            } else
                ok = false;
        }

        private OpMem op() {
            return ok ? amd64.mem(baseReg, indexReg, scale, disp, size) : null;
        }
    }
    return new DecomposePlus(n0).op();
}
Also used : Operator(suite.node.io.Operator) OpMem(suite.assembler.Amd64.OpMem) FunpTree(suite.funp.P0.FunpTree) Amd64(suite.assembler.Amd64) TermOp(suite.node.io.TermOp) OpReg(suite.assembler.Amd64.OpReg) ArrayList(java.util.ArrayList) FunpTree2(suite.funp.P0.FunpTree2) Funp(suite.funp.Funp_.Funp) List(java.util.List) FunpFramePointer(suite.funp.P2.FunpFramePointer) Fun2(suite.util.FunUtil2.Fun2) FunpNumber(suite.funp.P0.FunpNumber) Operand(suite.assembler.Amd64.Operand) FunpMemory(suite.funp.P2.FunpMemory) Operator(suite.node.io.Operator) TreeUtil(suite.node.util.TreeUtil) FunpDontCare(suite.funp.P0.FunpDontCare) FunpTree2(suite.funp.P0.FunpTree2) FunpNumber(suite.funp.P0.FunpNumber) Funp(suite.funp.Funp_.Funp) ArrayList(java.util.ArrayList) List(java.util.List) FunpFramePointer(suite.funp.P2.FunpFramePointer) FunpTree(suite.funp.P0.FunpTree) OpReg(suite.assembler.Amd64.OpReg)

Aggregations

OpMem (suite.assembler.Amd64.OpMem)5 OpReg (suite.assembler.Amd64.OpReg)4 List (java.util.List)2 OpImm (suite.assembler.Amd64.OpImm)2 Operand (suite.assembler.Amd64.Operand)2 ByteBuffer (java.nio.ByteBuffer)1 ArrayList (java.util.ArrayList)1 Amd64 (suite.assembler.Amd64)1 Insn (suite.assembler.Amd64.Insn)1 Instruction (suite.assembler.Amd64.Instruction)1 Funp_ (suite.funp.Funp_)1 Funp (suite.funp.Funp_.Funp)1 FunpDontCare (suite.funp.P0.FunpDontCare)1 FunpNumber (suite.funp.P0.FunpNumber)1 FunpTree (suite.funp.P0.FunpTree)1 FunpTree2 (suite.funp.P0.FunpTree2)1 FunpFramePointer (suite.funp.P2.FunpFramePointer)1 FunpMemory (suite.funp.P2.FunpMemory)1 Int (suite.node.Int)1 Node (suite.node.Node)1