Commit message: Fix #9943 - Invalid free on RAnal.avr
CVE: CVE-2018-11383
CWE: CWE-416
Vulnerability description: The r_strbuf_fini() function in radare2 2.5.0 allows remote attackers to cause a denial of service (invalid free and application crash) via a crafted ELF file because of an uninitialized variable in the CPSE handler in libr/anal/p/anal_avr.c.

Project: radare2

INST_HANDLER (adc) {	// ADC Rd, Rr
	int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
	int r = (buf[0] & 0xf) | ((buf[1] & 2) << 3);
	ESIL_A ("r%d,cf,+,r%d,+,", r, d);		// Rd + Rr + C
	__generic_add_update_flags_rr(op, d, r);	// FLAGS
	ESIL_A ("r%d,=,", d);				// Rd = result
}

Project: radare2

INST_HANDLER (add) {	// ADD Rd, Rr
	int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
	int r = (buf[0] & 0xf) | ((buf[1] & 2) << 3);
	ESIL_A ("r%d,r%d,+,", r, d);			// Rd + Rr
	__generic_add_update_flags_rr(op, d, r);	// FLAGS
	ESIL_A ("r%d,=,", d);				// Rd = result
}

Project: radare2

INST_HANDLER (adiw) {	// ADIW Rd+1:Rd, K
	int d = ((buf[0] & 0x30) >> 3) + 24;
	int k = (buf[0] & 0xf) | ((buf[0] >> 2) & 0x30);
	op->val = k;
	ESIL_A ("r%d:r%d,%d,+,", d + 1, d, k);			// Rd+1:Rd + Rr
	ESIL_A ("r%d,0x80,&,!,"					// V
		"0,RPICK,0x8000,&,!,!,"
		"&,vf,=,", d + 1);
	ESIL_A ("0,RPICK,0x8000,&,!,!,nf,=,");			// N
	ESIL_A ("0,RPICK,!,zf,=,");				// Z
	ESIL_A ("r%d,0x80,&,!,!,"				// C
		"0,RPICK,0x8000,&,!,"
		"&,cf,=,", d + 1);
	ESIL_A ("vf,nf,^,sf,=,");				// S
	ESIL_A ("r%d:r%d,=,", d + 1, d);			// Rd = result
}

Project: radare2

INST_HANDLER (and) {	// AND Rd, Rr
	if (len < 2) {
		return;
	}
	int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
	int r = (buf[0] & 0xf) | ((buf[1] & 2) << 3);
	ESIL_A ("r%d,r%d,&,", r, d);				// 0: Rd & Rr
	__generic_bitop_flags (op);				// up flags
	ESIL_A ("r%d,=,", d);					// Rd = Result
}

Project: radare2

INST_HANDLER (andi) {	// ANDI Rd, K
	if (len < 2) {
		return;
	}
	int d = ((buf[0] >> 4) & 0xf) + 16;
	int k = ((buf[1] & 0x0f) << 4) | (buf[0] & 0x0f);
	op->val = k;
	ESIL_A ("%d,r%d,&,", k, d);				// 0: Rd & Rr
	__generic_bitop_flags (op);				// up flags
	ESIL_A ("r%d,=,", d);					// Rd = Result
}

Project: radare2
File: anal_avr.c

INST_HANDLER (asr) {	// ASR Rd
	if (len < 2) {
		return;
	}
	int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
	ESIL_A ("1,r%d,>>,r%d,0x80,&,|,", d, d);		// 0: R=(Rd >> 1) | Rd7
	ESIL_A ("r%d,0x1,&,!,!,cf,=,", d);			// C = Rd0
	ESIL_A ("0,RPICK,!,zf,=,");				// Z
	ESIL_A ("0,RPICK,0x80,&,!,!,nf,=,");			// N
	ESIL_A ("nf,cf,^,vf,=,");				// V
	ESIL_A ("nf,vf,^,sf,=,");				// S
	ESIL_A ("r%d,=,", d);					// Rd = R
}

Project: radare2

INST_HANDLER (bclr) {	// BCLR s
	int s = (buf[0] >> 4) & 0x7;
	ESIL_A ("0xff,%d,1,<<,^,sreg,&=,", s);
}

Project: radare2
File: anal_avr.c

INST_HANDLER (break) {	// BREAK
	ESIL_A ("BREAK");
}

Project: radare2
File: anal_avr.c

INST_HANDLER (bst) {	// BST Rd, b
	if (len < 2) {
		return;
	}
	ESIL_A ("r%d,%d,1,<<,&,!,!,tf,=,",			// tf = Rd/b
		((buf[1] & 1) << 4) | ((buf[0] >> 4) & 0xf),	// r
		buf[0] & 0x7);					// b
}

Project: radare2

INST_HANDLER (call) {	// CALL k
	if (len < 4) {
		return;
	}
	op->jump = (buf[2] << 1)
		 | (buf[3] << 9)
		 | (buf[1] & 0x01) << 23
		 | (buf[0] & 0x01) << 17
		 | (buf[0] & 0xf0) << 14;
	op->fail = op->addr + op->size;
	op->cycles = cpu->pc <= 16 ? 3 : 4;
	if (!STR_BEGINS (cpu->model, "ATxmega")) {
		op->cycles--;	// AT*mega optimizes one cycle
	}
	ESIL_A ("pc,");				// esil is already pointing to
	__generic_push (op, CPU_PC_SIZE (cpu));	// push @ret in stack
	ESIL_A ("%"PFMT64d",pc,=,", op->jump);	// jump!
}

Project: radare2

INST_HANDLER (cbi) {	// CBI A, b
	int a = (buf[0] >> 3) & 0x1f;
	int b = buf[0] & 0x07;
	RStrBuf *io_port;

	op->family = R_ANAL_OP_FAMILY_IO;
	op->type2 = 1;
	op->val = a;

	io_port = __generic_io_dest (a, 0, cpu);
	ESIL_A ("0xff,%d,1,<<,^,%s,&,", b, io_port);
	r_strbuf_free (io_port);

	io_port = __generic_io_dest (a, 1, cpu);
	ESIL_A ("%s,", r_strbuf_get (io_port));
	r_strbuf_free (io_port);
}

Project: radare2

INST_HANDLER (com) {	// COM Rd
	int r = ((buf[0] >> 4) & 0x0f) | ((buf[1] & 1) << 4);

	ESIL_A ("r%d,0xff,-,0xff,&,r%d,=,", r, r);		// Rd = 0xFF-Rd
	ESIL_A ("0,cf,=,");					// C
	__generic_bitop_flags (op);				// ...rest...
}

Project: radare2
File: anal_avr.c

INST_HANDLER (cp) {	// CP Rd, Rr
	int r = (buf[0]        & 0x0f) | ((buf[1] << 3) & 0x10);
	int d = ((buf[0] >> 4) & 0x0f) | ((buf[1] << 4) & 0x10);
	ESIL_A ("r%d,r%d,-,", r, d);			// do Rd - Rr
	__generic_sub_update_flags_rr (op, d, r, 0);	// FLAGS (no carry)
}

Project: radare2
File: anal_avr.c

INST_HANDLER (cpc) {	// CPC Rd, Rr
	int r = (buf[0]        & 0x0f) | ((buf[1] << 3) & 0x10);
	int d = ((buf[0] >> 4) & 0x0f) | ((buf[1] << 4) & 0x10);

	ESIL_A ("cf,r%d,+,r%d,-,", r, d);		// Rd - Rr - C
	__generic_sub_update_flags_rr (op, d, r, 1);	// FLAGS (carry)
}

Project: radare2
File: anal_avr.c

INST_HANDLER (cpi) { // CPI Rd, K
	int d = ((buf[0] >> 4) & 0xf) + 16;
	int k = (buf[0] & 0xf) | ((buf[1] & 0xf) << 4);
	ESIL_A ("%d,r%d,-,", k, d);			// Rd - k
	__generic_sub_update_flags_rk (op, d, k, 0);	// FLAGS (carry)
}

Project: radare2

INST_HANDLER (dec) {	// DEC Rd
	int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);
	ESIL_A ("-1,r%d,+,", d);				// --Rd
	ESIL_A ("0,RPICK,0x7f,==,vf,=,");			// V
	ESIL_A ("0,RPICK,0x80,&,!,!,nf,=,");			// N
	ESIL_A ("0,RPICK,!,zf,=,");				// Z
	ESIL_A ("vf,nf,^,sf,=,");				// S
	ESIL_A ("r%d,=,", d);					// Rd = Result
}

Project: radare2
File: anal_avr.c

INST_HANDLER (des) {	// DES k
	if (desctx.round < 16) {	//DES
		op->type = R_ANAL_OP_TYPE_CRYPTO;
		op->cycles = 1;		//redo this
		r_strbuf_setf (&op->esil, "%d,des", desctx.round);
	}
}

Project: radare2

INST_HANDLER (eijmp) {	// EIJMP
	ut64 z, eind;
	r_anal_esil_reg_read (anal->esil, "z",    &z,    NULL);
	r_anal_esil_reg_read (anal->esil, "eind", &eind, NULL);
	op->jump = ((eind << 16) + z) << 1;
	ESIL_A ("1,z,16,eind,<<,+,<<,pc,=,");
	op->cycles = 2;
}

Project: radare2

INST_HANDLER (elpm) {	// ELPM
	int d = ((buf[1] & 0xfe) == 0x90)
			? ((buf[1] & 1) << 4) | ((buf[0] >> 4) & 0xf)	// Rd
			: 0;						// R0
	ESIL_A ("16,rampz,<<,z,+,_prog,+,[1],");	// read RAMPZ:Z
	ESIL_A ("r%d,=,", d);				// Rd = [1]
	if ((buf[1] & 0xfe) == 0x90 && (buf[0] & 0xf) == 0x7) {
		ESIL_A ("16,1,z,+,DUP,z,=,>>,1,&,rampz,+=,");	// ++(rampz:z)
	}
}

Project: radare2
File: anal_avr.c

INST_HANDLER (fmul) {	// FMUL Rd, Rr
	int d = ((buf[0] >> 4) & 0x7) + 16;
	int r = (buf[0] & 0x7) + 16;

	ESIL_A ("1,r%d,r%d,*,<<,", r, d);		// 0: (Rd*Rr)<<1
	ESIL_A ("0xffff,&,");				// prevent overflow
	ESIL_A ("DUP,0xff,&,r0,=,");			// r0 = LO(0)
	ESIL_A ("8,0,RPICK,>>,0xff,&,r1,=,");		// r1 = HI(0)
	ESIL_A ("DUP,0x8000,&,!,!,cf,=,");		// C = R/16
	ESIL_A ("DUP,!,zf,=,");				// Z = !R
}

Project: radare2
File: anal_avr.c

INST_HANDLER (fmuls) {	// FMULS Rd, Rr
	int d = ((buf[0] >> 4) & 0x7) + 16;
	int r = (buf[0] & 0x7) + 16;

	ESIL_A ("1,");
	ESIL_A ("r%d,DUP,0x80,&,?{,0xffff00,|,},", d);	// sign extension Rd
	ESIL_A ("r%d,DUP,0x80,&,?{,0xffff00,|,},", r);	// sign extension Rr
	ESIL_A ("*,<<,", r, d);				// 0: (Rd*Rr)<<1

	ESIL_A ("0xffff,&,");				// prevent overflow
	ESIL_A ("DUP,0xff,&,r0,=,");			// r0 = LO(0)
	ESIL_A ("8,0,RPICK,>>,0xff,&,r1,=,");		// r1 = HI(0)
	ESIL_A ("DUP,0x8000,&,!,!,cf,=,");		// C = R/16
	ESIL_A ("DUP,!,zf,=,");				// Z = !R
}

Project: radare2
File: anal_avr.c

INST_HANDLER (fmulsu) {	// FMULSU Rd, Rr
	int d = ((buf[0] >> 4) & 0x7) + 16;
	int r = (buf[0] & 0x7) + 16;

	ESIL_A ("1,");
	ESIL_A ("r%d,DUP,0x80,&,?{,0xffff00,|,},", d);	// sign extension Rd
	ESIL_A ("r%d", r);				// unsigned Rr
	ESIL_A ("*,<<,");				// 0: (Rd*Rr)<<1

	ESIL_A ("0xffff,&,");				// prevent overflow
	ESIL_A ("DUP,0xff,&,r0,=,");			// r0 = LO(0)
	ESIL_A ("8,0,RPICK,>>,0xff,&,r1,=,");		// r1 = HI(0)
	ESIL_A ("DUP,0x8000,&,!,!,cf,=,");		// C = R/16
	ESIL_A ("DUP,!,zf,=,");				// Z = !R
}

Project: radare2

INST_HANDLER (ijmp) {	// IJMP k
	ut64 z;
	r_anal_esil_reg_read (anal->esil, "z", &z, NULL);
	op->jump = z << 1;
	op->cycles = 2;
	ESIL_A ("1,z,<<,pc,=,");		// jump!
}

Project: radare2

INST_HANDLER (icall) {	// ICALL k
	ESIL_A ("pc,");				// esil is already pointing to
	__generic_push (op, CPU_PC_SIZE (cpu));	// push @ret in stack
	INST_CALL (ijmp);
	if (!STR_BEGINS (cpu->model, "ATxmega")) {
		op->cycles--;
	}
}

Project: radare2
File: anal_avr.c

INST_HANDLER (in) {	// IN Rd, A
	int r = ((buf[0] >> 4) & 0x0f) | ((buf[1] & 0x01) << 4);
	int a = (buf[0] & 0x0f) | ((buf[1] & 0x6) << 3);
	RStrBuf *io_src = __generic_io_dest (a, 0, cpu);
	op->type2 = 0;
	op->val = a;
	op->family = R_ANAL_OP_FAMILY_IO;
	ESIL_A ("%s,r%d,=,", r_strbuf_get (io_src), r);
	r_strbuf_free (io_src);
}

Project: radare2

INST_HANDLER (inc) {	// INC Rd
	int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);
	ESIL_A ("1,r%d,+,", d);					// ++Rd
	ESIL_A ("0,RPICK,0x80,==,vf,=,");			// V
	ESIL_A ("0,RPICK,0x80,&,!,!,nf,=,");			// N
	ESIL_A ("0,RPICK,!,zf,=,");				// Z
	ESIL_A ("vf,nf,^,sf,=,");				// S
	ESIL_A ("r%d,=,", d);					// Rd = Result
}

Project: radare2
File: anal_avr.c

INST_HANDLER (jmp) {	// JMP k
	op->jump = (buf[2] << 1)
		 | (buf[3] << 9)
		 | (buf[1] & 0x01) << 23
		 | (buf[0] & 0x01) << 17
		 | (buf[0] & 0xf0) << 14;
	op->cycles = 3;
	ESIL_A ("%"PFMT64d",pc,=,", op->jump);	// jump!
}

Project: radare2

INST_HANDLER (lac) {	// LAC Z, Rd
	int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);

	__generic_ld_st (op, "ram", 'z', 1, 0, 0, 0);	// 0: Read (RAMPZ:Z)
	ESIL_A ("r%d,0xff,^,&,", d);			// 0: (Z) & ~Rd
	ESIL_A ("DUP,r%d,=,", d);			// Rd = [0]
	__generic_ld_st (op, "ram", 'z', 1, 0, 0, 1);	// Store in RAM
}

Project: radare2

INST_HANDLER (las) {	// LAS Z, Rd
	int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);

	__generic_ld_st (op, "ram", 'z', 1, 0, 0, 0);	// 0: Read (RAMPZ:Z)
	ESIL_A ("r%d,|,", d);				// 0: (Z) | Rd
	ESIL_A ("DUP,r%d,=,", d);			// Rd = [0]
	__generic_ld_st (op, "ram", 'z', 1, 0, 0, 1);	// Store in RAM
}

Project: radare2

INST_HANDLER (lat) {	// LAT Z, Rd
	int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);

	__generic_ld_st (op, "ram", 'z', 1, 0, 0, 0);	// 0: Read (RAMPZ:Z)
	ESIL_A ("r%d,^,", d);				// 0: (Z) ^ Rd
	ESIL_A ("DUP,r%d,=,", d);			// Rd = [0]
	__generic_ld_st (op, "ram", 'z', 1, 0, 0, 1);	// Store in RAM
}

Project: radare2

INST_HANDLER (ld) {	// LD Rd, X
	__generic_ld_st (
		op, "ram",
		'x',				// use index register X
		0,				// no use RAMP* registers
		(buf[0] & 0xf) == 0xe
			? -1			// pre decremented
			: (buf[0] & 0xf) == 0xd
				? 1		// post incremented
				: 0,		// no increment
		0,				// offset always 0
		0);				// load operation (!st)
	ESIL_A ("r%d,=,", ((buf[1] & 1) << 4) | ((buf[0] >> 4) & 0xf));
	op->cycles = (buf[0] & 0x3) == 0
			? 2			// LD Rd, X
			: (buf[0] & 0x3) == 1
				? 2		// LD Rd, X+
				: 3;		// LD Rd, -X
	if (!STR_BEGINS (cpu->model, "ATxmega") && op->cycles > 1) {
		op->cycles--;
	}
}

Project: radare2
File: anal_avr.c

INST_HANDLER (ldi) {	// LDI Rd, K
	int k = (buf[0] & 0xf) + ((buf[1] & 0xf) << 4);
	int d = ((buf[0] >> 4) & 0xf) + 16;
	op->val = k;
	ESIL_A ("0x%x,r%d,=,", k, d);
}

Project: radare2

INST_HANDLER (lds) {	// LDS Rd, k
	if (len < 4) {
		return;
	}
	int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);
	int k = (buf[3] << 8) | buf[2];
	op->ptr = k;

	__generic_ld_st (op, "ram", 0, 1, 0, k, 0);
	ESIL_A ("r%d,=,", d);
}

Project: radare2
File: anal_avr.c

INST_HANDLER (lsr) {	// LSR Rd
	int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
	ESIL_A ("1,r%d,>>,", d);				// 0: R=(Rd >> 1)
	ESIL_A ("r%d,0x1,&,!,!,cf,=,", d);			// C = Rd0
	ESIL_A ("0,RPICK,!,zf,=,");				// Z
	ESIL_A ("0,nf,=,");					// N
	ESIL_A ("nf,cf,^,vf,=,");				// V
	ESIL_A ("nf,vf,^,sf,=,");				// S
	ESIL_A ("r%d,=,", d);					// Rd = R
}

Project: radare2
File: anal_avr.c

INST_HANDLER (mov) {	// MOV Rd, Rr
	int d = ((buf[1] << 4) & 0x10) | ((buf[0] >> 4) & 0x0f);
	int r = ((buf[1] << 3) & 0x10) | (buf[0] & 0x0f);
	ESIL_A ("r%d,r%d,=,", r, d);
}

Project: radare2
File: anal_avr.c

INST_HANDLER (mul) {	// MUL Rd, Rr
	int d = ((buf[1] << 4) & 0x10) | ((buf[0] >> 4) & 0x0f);
	int r = ((buf[1] << 3) & 0x10) | (buf[0] & 0x0f);

	ESIL_A ("r%d,r%d,*,", r, d);			// 0: (Rd*Rr)<<1
	ESIL_A ("DUP,0xff,&,r0,=,");			// r0 = LO(0)
	ESIL_A ("8,0,RPICK,>>,0xff,&,r1,=,");		// r1 = HI(0)
	ESIL_A ("DUP,0x8000,&,!,!,cf,=,");		// C = R/15
	ESIL_A ("DUP,!,zf,=,");				// Z = !R
}

Project: radare2
File: anal_avr.c

INST_HANDLER (muls) {	// MULS Rd, Rr
	int d = (buf[0] >> 4 & 0x0f) + 16;
	int r = (buf[0] & 0x0f) + 16;

	ESIL_A ("r%d,DUP,0x80,&,?{,0xffff00,|,},", r);	// sign extension Rr
	ESIL_A ("r%d,DUP,0x80,&,?{,0xffff00,|,},", d);	// sign extension Rd
	ESIL_A ("*,");					// 0: (Rd*Rr)
	ESIL_A ("DUP,0xff,&,r0,=,");			// r0 = LO(0)
	ESIL_A ("8,0,RPICK,>>,0xff,&,r1,=,");		// r1 = HI(0)
	ESIL_A ("DUP,0x8000,&,!,!,cf,=,");		// C = R/15
	ESIL_A ("DUP,!,zf,=,");				// Z = !R
}

Project: radare2
File: anal_avr.c

INST_HANDLER (mulsu) {	// MULSU Rd, Rr
	int d = (buf[0] >> 4 & 0x07) + 16;
	int r = (buf[0] & 0x07) + 16;

	ESIL_A ("r%d,", r);				// unsigned Rr
	ESIL_A ("r%d,DUP,0x80,&,?{,0xffff00,|,},", d);	// sign extension Rd
	ESIL_A ("*,");					// 0: (Rd*Rr)
	ESIL_A ("DUP,0xff,&,r0,=,");			// r0 = LO(0)
	ESIL_A ("8,0,RPICK,>>,0xff,&,r1,=,");		// r1 = HI(0)
	ESIL_A ("DUP,0x8000,&,!,!,cf,=,");		// C = R/15
	ESIL_A ("DUP,!,zf,=,");				// Z = !R
}

Project: radare2
File: anal_avr.c

INST_HANDLER (nop) {	// NOP
	ESIL_A (",,");
}

Project: radare2
File: anal_avr.c

INST_HANDLER (or) {	// OR Rd, Rr
	int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
	int r = (buf[0] & 0xf) | ((buf[1] & 2) << 3);
	ESIL_A ("r%d,r%d,|,", r, d);				// 0: (Rd | Rr)
	ESIL_A ("0,RPICK,!,zf,=,");				// Z
	ESIL_A ("0,RPICK,0x80,&,!,!,nf,=,");			// N
	ESIL_A ("0,vf,=,");					// V
	ESIL_A ("nf,sf,=,");					// S
	ESIL_A ("r%d,=,", d);					// Rd = result
}

Project: radare2

INST_HANDLER (ori) {	// ORI Rd, K
	int d = ((buf[0] >> 4) & 0xf) + 16;
	int k = (buf[0] & 0xf) | ((buf[1] & 0xf) << 4);
	op->val = k;
	ESIL_A ("r%d,%d,|,", d, k);				// 0: (Rd | k)
	ESIL_A ("0,RPICK,!,zf,=,");				// Z
	ESIL_A ("0,RPICK,0x80,&,!,!,nf,=,");			// N
	ESIL_A ("0,vf,=,");					// V
	ESIL_A ("nf,sf,=,");					// S
	ESIL_A ("r%d,=,", d);					// Rd = result
}

Project: radare2
File: anal_avr.c

INST_HANDLER (pop) {	// POP Rd
	int d = ((buf[1] & 0x1) << 4) | ((buf[0] >> 4) & 0xf);
	__generic_pop (op, 1);
	ESIL_A ("r%d,=,", d);	// store in Rd

}

Project: radare2

INST_HANDLER (push) {	// PUSH Rr
	int r = ((buf[1] & 0x1) << 4) | ((buf[0] >> 4) & 0xf);
	ESIL_A ("r%d,", r);	// load Rr
	__generic_push (op, 1);	// push it into stack
	op->cycles = !STR_BEGINS (cpu->model, "ATxmega")
			? 1	// AT*mega optimizes one cycle
			: 2;
}

Project: radare2

INST_HANDLER (rcall) {	// RCALL k
	op->jump = (op->addr
		+ (((((buf[1] & 0xf) << 8) | buf[0]) << 1)
			| (((buf[1] & 0x8) ? ~((int) 0x1fff) : 0)))
		+ 2) & CPU_PC_MASK (cpu);
	op->fail = op->addr + op->size;
	ESIL_A ("pc,");				// esil already points to next
	__generic_push (op, CPU_PC_SIZE (cpu));	// push @ret addr
	ESIL_A ("%"PFMT64d",pc,=,", op->jump);	// jump!
	if (!strncasecmp (cpu->model, "ATtiny", 6)) {
		op->cycles = 4;	// ATtiny is always slow
	} else {
		op->cycles = cpu->pc <= 16 ? 3 : 4;
		if (!STR_BEGINS (cpu->model, "ATxmega")) {
			op->cycles--;	// ATxmega optimizes one cycle
		}
	}
}

Project: radare2

INST_HANDLER (ret) {	// RET
	op->eob = true;
	__generic_pop (op, CPU_PC_SIZE (cpu));
	ESIL_A ("pc,=,");	// jump!
	if (CPU_PC_SIZE (cpu) > 2) {	// if we have a bus bigger than 16 bit
		op->cycles++;	// (i.e. a 22-bit bus), add one extra cycle
	}
}

Project: radare2

INST_HANDLER (reti) {	// RETI
	op->family = R_ANAL_OP_FAMILY_PRIV;

	INST_CALL (ret);

	ESIL_A ("1,if,=,");
}

Project: radare2
File: anal_avr.c

INST_HANDLER (rjmp) {	// RJMP k
	op->jump = (op->addr
#ifdef _MSC_VER
#pragma message ("anal_avr.c: WARNING: Probably broken on windows")
		+ ((((( buf[1] & 0xf) << 9) | (buf[0] << 1)))
			| (buf[1] & 0x8 ? ~(0x1fff) : 0))
#else
		+ ((((( (typeof (op->jump)) buf[1] & 0xf) << 9) | ((typeof (op->jump)) buf[0] << 1)))
			| (buf[1] & 0x8 ? ~((typeof (op->jump)) 0x1fff) : 0))
#endif
		+ 2) & CPU_PC_MASK (cpu);
	ESIL_A ("%"PFMT64d",pc,=,", op->jump);
}

Project: radare2
File: anal_avr.c

INST_HANDLER (ror) {	// ROR Rd
	int d = ((buf[0] >> 4) & 0x0f) | ((buf[1] << 4) & 0x10);
	ESIL_A ("1,r%d,>>,7,cf,<<,|,", d);		// 0: (Rd>>1) | (cf<<7)
	ESIL_A ("r%d,1,&,cf,=,", d);			// C
	ESIL_A ("0,RPICK,!,zf,=,");			// Z
	ESIL_A ("0,RPICK,0x80,&,!,!,nf,=,");		// N
	ESIL_A ("nf,cf,^,vf,=,");			// V
	ESIL_A ("vf,nf,^,sf,=,");			// S
	ESIL_A ("r%d,=,", d);				// Rd = result
}

Project: radare2
File: anal_avr.c

INST_HANDLER (sbc) {	// SBC Rd, Rr
	int r = (buf[0] & 0x0f) | ((buf[1] & 0x2) << 3);
	int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);

	ESIL_A ("cf,r%d,+,r%d,-,", r, d);		// 0: (Rd-Rr-C)
	__generic_sub_update_flags_rr (op, d, r, 1);	// FLAGS (carry)
	ESIL_A ("r%d,=,", d);				// Rd = Result
}

Project: radare2
File: anal_avr.c

INST_HANDLER (sbci) {	// SBCI Rd, k
	int d = ((buf[0] >> 4) & 0xf) + 16;
	int k = ((buf[1] & 0xf) << 4) | (buf[0] & 0xf);
	op->val = k;

	ESIL_A ("cf,%d,+,r%d,-,", k, d);		// 0: (Rd-k-C)
	__generic_sub_update_flags_rk (op, d, k, 1);	// FLAGS (carry)
	ESIL_A ("r%d,=,", d);				// Rd = Result
}

Project: radare2
File: anal_avr.c

INST_HANDLER (sub) {	// SUB Rd, Rr
	int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
	int r = (buf[0] & 0xf) | ((buf[1] & 2) << 3);

	ESIL_A ("r%d,r%d,-,", r, d);			// 0: (Rd-k)
	__generic_sub_update_flags_rr (op, d, r, 0);	// FLAGS (no carry)
	ESIL_A ("r%d,=,", d);				// Rd = Result
}

Project: radare2
File: anal_avr.c

INST_HANDLER (subi) {	// SUBI Rd, k
	int d = ((buf[0] >> 4) & 0xf) + 16;
	int k = ((buf[1] & 0xf) << 4) | (buf[0] & 0xf);
	op->val = k;

	ESIL_A ("%d,r%d,-,", k, d);			// 0: (Rd-k)
	__generic_sub_update_flags_rk (op, d, k, 1);	// FLAGS (no carry)
	ESIL_A ("r%d,=,", d);				// Rd = Result
}

Project: radare2

INST_HANDLER (sbi) {	// SBI A, b
	int a = (buf[0] >> 3) & 0x1f;
	int b = buf[0] & 0x07;
	RStrBuf *io_port;

	op->type2 = 1;
	op->val = a;
	op->family = R_ANAL_OP_FAMILY_IO;

	io_port = __generic_io_dest (a, 0, cpu);
	ESIL_A ("0xff,%d,1,<<,|,%s,&,", b, io_port);
	r_strbuf_free (io_port);

	io_port = __generic_io_dest (a, 1, cpu);
	ESIL_A ("%s,", r_strbuf_get (io_port));
	r_strbuf_free (io_port);
}

Project: radare2

INST_HANDLER (sbix) {	// SBIC A, b
	int a = (buf[0] >> 3) & 0x1f;
	int b = buf[0] & 0x07;
	RAnalOp next_op;
	RStrBuf *io_port;

	op->type2 = 0;
	op->val = a;
	op->family = R_ANAL_OP_FAMILY_IO;

	avr_op_analyze (anal,
			&next_op,
			op->addr + op->size, buf + op->size,
			len - op->size,
			cpu);
	r_strbuf_fini (&next_op.esil);
	op->jump = op->addr + next_op.size + 2;

	op->cycles = 1;	// XXX: This is a bug, because depends on eval state,

	io_port = __generic_io_dest (a, 0, cpu);
	ESIL_A ("%d,1,<<,%s,&,", b, io_port);		// IO(A,b)
	ESIL_A ((buf[1] & 0xe) == 0xc
			? "!,"				// SBIC => branch if 0
			: "!,!,");			// SBIS => branch if 1
	ESIL_A ("?{,%"PFMT64d",pc,=,},", op->jump);	// ?true => jmp
	r_strbuf_free (io_port);
}

Project: radare2
File: anal_avr.c

INST_HANDLER (sbiw) {	// SBIW Rd+1:Rd, K
	int d = ((buf[0] & 0x30) >> 3) + 24;
	int k = (buf[0] & 0xf) | ((buf[0] >> 2) & 0x30);
	op->val = k;
	ESIL_A ("%d,r%d:r%d,-,", k, d + 1, d);		// 0(Rd+1:Rd - Rr)
	ESIL_A ("r%d,0x80,&,!,!,"			// V
		"0,RPICK,0x8000,&,!,"
		"&,vf,=,", d + 1);
	ESIL_A ("0,RPICK,0x8000,&,!,!,nf,=,");		// N
	ESIL_A ("0,RPICK,!,zf,=,");			// Z
	ESIL_A ("r%d,0x80,&,!,"				// C
		"0,RPICK,0x8000,&,!,!,"
		"&,cf,=,", d + 1);
	ESIL_A ("vf,nf,^,sf,=,");			// S
	ESIL_A ("r%d:r%d,=,", d + 1, d);		// Rd = result
}

Project: radare2

INST_HANDLER (sbrx) {	// SBRC Rr, b
	int b = buf[0] & 0x7;
	int r = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x01) << 4);
	RAnalOp next_op = {0};

	avr_op_analyze (anal,
			&next_op,
			op->addr + op->size, buf + op->size, len - op->size,
			cpu);
	r_strbuf_fini (&next_op.esil);
	op->jump = op->addr + next_op.size + 2;

	op->cycles = 1;	// XXX: This is a bug, because depends on eval state,
	ESIL_A ("%d,1,<<,r%d,&,", b, r);			// Rr(b)
	ESIL_A ((buf[1] & 0xe) == 0xc
			? "!,"		// SBRC => branch if cleared
			: "!,!,");	// SBRS => branch if set
	ESIL_A ("?{,%"PFMT64d",pc,=,},", op->jump);	// ?true => jmp
}

Project: radare2
File: anal_avr.c

INST_HANDLER (sleep) {	// SLEEP
	ESIL_A ("BREAK");
}

Project: radare2

INST_HANDLER (spm) {	// SPM Z+
	ut64 spmcsr;

	r_anal_esil_reg_read (anal->esil, "spmcsr", &spmcsr, NULL);

	ESIL_A ("0x7c,spmcsr,&=,");

	switch (spmcsr & 0x7f) {
		case 0x03: // PAGE ERASE
			ESIL_A ("16,rampz,<<,z,+,"); // push target address
			ESIL_A ("SPM_PAGE_ERASE,");  // do magic
			break;

		case 0x01: // FILL TEMPORARY BUFFER
			ESIL_A ("r1,r0,");           // push data
			ESIL_A ("z,");               // push target address
			ESIL_A ("SPM_PAGE_FILL,");   // do magic
			break;

		case 0x05: // WRITE PAGE
			ESIL_A ("16,rampz,<<,z,+,"); // push target address
			ESIL_A ("SPM_PAGE_WRITE,");  // do magic
			break;

		default:
			eprintf ("SPM: I dont know what to do with SPMCSR %02x.\n",
					(unsigned int) spmcsr);
	}

	op->cycles = 1;	// This is truly false. Datasheets do not publish how
}

Project: radare2

INST_HANDLER (st) {	// ST X, Rr
	ESIL_A ("r%d,", ((buf[1] & 1) << 4) | ((buf[0] >> 4) & 0xf));
	__generic_ld_st (
		op, "ram",
		'x',				// use index register X
		0,				// no use RAMP* registers
		(buf[0] & 0xf) == 0xe
			? -1			// pre decremented
			: (buf[0] & 0xf) == 0xd
				? 1		// post increment
				: 0,		// no increment
		0,				// offset always 0
		1);				// store operation (st)
}

Project: radare2
File: anal_avr.c

INST_HANDLER (swap) {	// SWAP Rd
	int d = ((buf[1] & 0x1) << 4) | ((buf[0] >> 4) & 0xf);
	ESIL_A ("4,r%d,>>,0x0f,&,", d);		// (Rd >> 4) & 0xf
	ESIL_A ("4,r%d,<<,0xf0,&,", d);		// (Rd >> 4) & 0xf
	ESIL_A ("|,", d);			// S[0] | S[1]
	ESIL_A ("r%d,=,", d);			// Rd = result
}

Project: radare2
File: anal_avr.c

static int __esil_pop_argument(RAnalEsil *esil, ut64 *v) {
	char *t = r_anal_esil_pop (esil);
	if (!t || !r_anal_esil_get_parm (esil, t, v)) {
		free (t);
		return false;
	}
	free (t);
	return true;
}

Project: radare2
File: anal_avr.c

static void __generic_add_update_flags(RAnalOp *op, char t_d, ut64 v_d, char t_rk, ut64 v_rk) {
	RStrBuf *d_strbuf, *rk_strbuf;
	char *d, *rk;

	d_strbuf = r_strbuf_new (NULL);
	rk_strbuf = r_strbuf_new (NULL);
	r_strbuf_setf (d_strbuf,  t_d  == 'r' ? "r%d" : "%" PFMT64d, v_d);
	r_strbuf_setf (rk_strbuf, t_rk == 'r' ? "r%d" : "%" PFMT64d, v_rk);

	d = r_strbuf_get(d_strbuf);
	rk = r_strbuf_get(rk_strbuf);

	ESIL_A ("%s,0x08,&,!,!," "%s,0x08,&,!,!,"    "&,"	// H
		"%s,0x08,&,!,!," "0,RPICK,0x08,&,!," "&,"
		"%s,0x08,&,!,!," "0,RPICK,0x08,&,!," "&,"
		"|,|,hf,=,",
		d, rk, rk, d);
	ESIL_A ("%s,0x80,&,!,!," "%s,0x80,&,!,!,"      "&,"	// V
		""               "0,RPICK,0x80,&,!,"   "&,"
		"%s,0x80,&,!,"   "%s,0x80,&,!,"        "&,"
		""               "0,RPICK,0x80,&,!,!," "&,"
		"|,vf,=,",
		d, rk, d, rk);
	ESIL_A ("0,RPICK,0x80,&,!,!,nf,=,");			// N
	ESIL_A ("0,RPICK,!,zf,=,");				// Z
	ESIL_A ("%s,0x80,&,!,!," "%s,0x80,&,!,!,"    "&,"	// C
		"%s,0x80,&,!,!," "0,RPICK,0x80,&,!," "&,"
		"%s,0x80,&,!,!," "0,RPICK,0x80,&,!," "&,"
		"|,|,cf,=,",
		d, rk, rk, d);
	ESIL_A ("vf,nf,^,sf,=,");				// S

	r_strbuf_free (d_strbuf);
	r_strbuf_free (rk_strbuf);
}

Project: radare2
File: anal_avr.c

static void __generic_bitop_flags(RAnalOp *op) {
	ESIL_A ("0,vf,=,");					// V
	ESIL_A ("0,RPICK,0x80,&,!,!,nf,=,");			// N
	ESIL_A ("0,RPICK,!,zf,=,");				// Z
	ESIL_A ("vf,nf,^,sf,=,");				// S
}

Project: radare2
File: anal_avr.c

static RStrBuf *__generic_io_dest(ut8 port, int write, CPU_MODEL *cpu) {
	RStrBuf *r = r_strbuf_new ("");
	CPU_CONST *c = const_by_value (cpu, CPU_CONST_REG, port);
	if (c != NULL) {
		r_strbuf_set (r, c->key);
		if (write) {
			r_strbuf_append (r, ",=");
		}
	} else {
		r_strbuf_setf (r, "_io,%d,+,%s[1]", port, write ? "=" : "");
	}

	return r;
}

Project: radare2

static void __generic_ld_st(RAnalOp *op, char *mem, char ireg, int use_ramp, int prepostdec, int offset, int st) {
	if (ireg) {
		if (prepostdec < 0) {
			ESIL_A ("1,%c,-,%c,=,", ireg, ireg);
		}
		ESIL_A ("%c,", ireg);
		if (offset != 0) {
			ESIL_A ("%d,+,", offset);
		}
	} else {
		ESIL_A ("%d,", offset);
	}
	if (use_ramp) {
		ESIL_A ("16,ramp%c,<<,+,", ireg ? ireg : 'd');
	}
	ESIL_A ("_%s,+,", mem);
	ESIL_A ("%s[1],", st ? "=" : "");
	if (ireg && prepostdec > 0) {
		ESIL_A ("1,%c,+,%c,=,", ireg, ireg);
	}
}

Project: radare2
File: anal_avr.c

static void __generic_push(RAnalOp *op, int sz) {
	ESIL_A ("sp,_ram,+,");			// calc pointer SRAM(sp)
	if (sz > 1) {
		ESIL_A ("-%d,+,", sz - 1);	// dec SP by 'sz'
	}
	ESIL_A ("=[%d],", sz);			// store value in stack
	ESIL_A ("-%d,sp,+=,", sz);		// decrement stack pointer
}

Project: radare2
File: anal_avr.c

static void __generic_sub_update_flags(RAnalOp *op, char t_d, ut64 v_d, char t_rk, ut64 v_rk, int carry) {
	RStrBuf *d_strbuf, *rk_strbuf;
	char *d, *rk;

	d_strbuf = r_strbuf_new (NULL);
	rk_strbuf = r_strbuf_new (NULL);
	r_strbuf_setf (d_strbuf,  t_d  == 'r' ? "r%d" : "%" PFMT64d, v_d);
	r_strbuf_setf (rk_strbuf, t_rk == 'r' ? "r%d" : "%" PFMT64d, v_rk);

	d = r_strbuf_get(d_strbuf);
	rk = r_strbuf_get(rk_strbuf);

	ESIL_A ("%s,0x08,&,!,"   "%s,0x08,&,!,!,"      "&,"	// H
		"%s,0x08,&,!,!," "0,RPICK,0x08,&,!,!," "&,"
		"%s,0x08,&,!,"   "0,RPICK,0x08,&,!,!," "&,"
		"|,|,hf,=,",
		d, rk, rk, d);
	ESIL_A ("%s,0x80,&,!,!," "%s,0x80,&,!,"        "&,"	// V
		""               "0,RPICK,0x80,&,!,"   "&,"
		"%s,0x80,&,!,"   "%s,0x80,&,!,!,"      "&,"
		""               "0,RPICK,0x80,&,!,!," "&,"
		"|,vf,=,",
		d, rk, d, rk);
	ESIL_A ("0,RPICK,0x80,&,!,!,nf,=,");			// N
	if (carry)
		ESIL_A ("0,RPICK,!,zf,&,zf,=,");		// Z
	else
		ESIL_A ("0,RPICK,!,zf,=,");			// Z
	ESIL_A ("%s,0x80,&,!,"   "%s,0x80,&,!,!,"      "&,"	// C
		"%s,0x80,&,!,!," "0,RPICK,0x80,&,!,!," "&,"
		"%s,0x80,&,!,"   "0,RPICK,0x80,&,!,!," "&,"
		"|,|,cf,=,",
		d, rk, rk, d);
	ESIL_A ("vf,nf,^,sf,=,");				// S

	r_strbuf_free (d_strbuf);
	r_strbuf_free (rk_strbuf);
}

Project: radare2
File: anal_avr.c

static void __generic_sub_update_flags_rk(RAnalOp *op, int d, int k, int carry) {
	__generic_sub_update_flags(op, 'r', d, 'k', k, carry);
}

Project: radare2
File: anal_avr.c

static void __generic_sub_update_flags_rr(RAnalOp *op, int d, int r, int carry) {
	__generic_sub_update_flags(op, 'r', d, 'r', r, carry);
}

Project: radare2

static int avr_custom_des (RAnalEsil *esil) {
	ut64 key, encrypt, text,des_round;
	ut32 key_lo, key_hi, buf_lo, buf_hi;
	if (!esil || !esil->anal || !esil->anal->reg) {
		return false;
	}
	if (!__esil_pop_argument (esil, &des_round)) {
		return false;
	}
	r_anal_esil_reg_read (esil, "hf", &encrypt, NULL);
	r_anal_esil_reg_read (esil, "deskey", &key, NULL);
	r_anal_esil_reg_read (esil, "text", &text, NULL);

	key_lo = key & UT32_MAX;
	key_hi = key >> 32;
	buf_lo = text & UT32_MAX;
	buf_hi = text >> 32;

	if (des_round != desctx.round) {
		desctx.round = des_round;
	}

	if (!desctx.round) {
		int i;
		r_des_permute_key (&key_lo, &key_hi);
		for (i = 0; i < 16; i++) {
			r_des_round_key (i, &desctx.round_key_lo[i], &desctx.round_key_hi[i], &key_lo, &key_hi);
		}
		r_des_permute_block0 (&buf_lo, &buf_hi);
	}

	if (encrypt) {
		r_des_round (&buf_lo, &buf_hi, &desctx.round_key_lo[desctx.round], &desctx.round_key_hi[desctx.round]);
	} else {
		r_des_round (&buf_lo, &buf_hi, &desctx.round_key_lo[15 - desctx.round], &desctx.round_key_hi[15 - desctx.round]);
	}

	if (desctx.round == 15) {
		r_des_permute_block1 (&buf_hi, &buf_lo);
		desctx.round = 0;
	} else {
		desctx.round++;
	}

	r_anal_esil_reg_write (esil, "text", text);
	return true;
}

Project: radare2

static int avr_custom_spm_page_erase(RAnalEsil *esil) {
	CPU_MODEL *cpu;
	ut8 c;
	ut64 addr, page_size_bits, i;

	if (!esil || !esil->anal || !esil->anal->reg) {
		return false;
	}

	if (!__esil_pop_argument(esil, &addr)) {
		return false;
	}

	cpu = get_cpu_model (esil->anal->cpu);
	page_size_bits = const_get_value (const_by_name (cpu, CPU_CONST_PARAM, "page_size"));

	addr &= ~(MASK (page_size_bits));

	c = 0xff;
	for (i = 0; i < (1ULL << page_size_bits); i++) {
		r_anal_esil_mem_write (
			esil, (addr + i) & CPU_PC_MASK (cpu), &c, 1);
	}

	return true;
}

Project: radare2

static int avr_custom_spm_page_fill(RAnalEsil *esil) {
	CPU_MODEL *cpu;
	ut64 addr, page_size_bits, i;
	ut8 r0, r1;

	if (!esil || !esil->anal || !esil->anal->reg) {
		return false;
	}

	if (!__esil_pop_argument(esil, &addr)) {
		return false;
	}

	if (!__esil_pop_argument (esil, &i)) {
		return false;
	}
	r0 = i;

	if (!__esil_pop_argument (esil, &i)) {
		return false;
	}
	r1 = i;

	cpu = get_cpu_model (esil->anal->cpu);
	page_size_bits = const_get_value (const_by_name (cpu, CPU_CONST_PARAM, "page_size"));

	addr &= (MASK (page_size_bits) ^ 1);

	r_anal_esil_mem_write (esil, addr++, &r0, 1);
	r_anal_esil_mem_write (esil, addr++, &r1, 1);

	return true;
}

Project: radare2

static int avr_custom_spm_page_write(RAnalEsil *esil) {
	CPU_MODEL *cpu;
	char *t = NULL;
	ut64 addr, page_size_bits, tmp_page;

	if (!esil || !esil->anal || !esil->anal->reg) {
		return false;
	}

	if (!__esil_pop_argument (esil, &addr)) {
		return false;
	}

	cpu = get_cpu_model (esil->anal->cpu);
	page_size_bits = const_get_value (const_by_name (cpu, CPU_CONST_PARAM, "page_size"));
	r_anal_esil_reg_read (esil, "_page", &tmp_page, NULL);

	addr &= (~(MASK (page_size_bits)) & CPU_PC_MASK (cpu));

	if (!(t = malloc (1 << page_size_bits))) {
		eprintf ("Cannot alloc a buffer for copying the temporary page.\n");
		return false;
	}
	r_anal_esil_mem_read (esil, tmp_page, (ut8 *) t, 1 << page_size_bits);
	r_anal_esil_mem_write (esil, addr, (ut8 *) t, 1 << page_size_bits);

	return true;
}

Project: radare2

static int avr_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
	CPU_MODEL *cpu;
	ut64 offset;

	if (!op) {
		return 2;
	}

	cpu = get_cpu_model (anal->cpu);

	if (anal->esil) {
		offset = 0;
		r_anal_esil_reg_write (anal->esil, "_prog", offset);

		offset += (1 << cpu->pc);
		r_anal_esil_reg_write (anal->esil, "_io", offset);

		offset += const_get_value (const_by_name (cpu, CPU_CONST_PARAM, "sram_start"));
		r_anal_esil_reg_write (anal->esil, "_sram", offset);

		offset += const_get_value (const_by_name (cpu, CPU_CONST_PARAM, "sram_size"));
		r_anal_esil_reg_write (anal->esil, "_eeprom", offset);

		offset += const_get_value (const_by_name (cpu, CPU_CONST_PARAM, "eeprom_size"));
		r_anal_esil_reg_write (anal->esil, "_page", offset);
	}
	avr_op_analyze (anal, op, addr, buf, len, cpu);

	return op->size;
}

Project: radare2

static OPCODE_DESC* avr_op_analyze(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len, CPU_MODEL *cpu) {
	OPCODE_DESC *opcode_desc;
	if (len < 2) {
		return NULL;
	}
	ut16 ins = (buf[1] << 8) | buf[0];
	int fail;
	char *t;

	memset (op, 0, sizeof (RAnalOp));
	op->ptr = UT64_MAX;
	op->val = UT64_MAX;
	op->jump = UT64_MAX;
	r_strbuf_init (&op->esil);

	for (opcode_desc = opcodes; opcode_desc->handler; opcode_desc++) {
		if ((ins & opcode_desc->mask) == opcode_desc->selector) {
			fail = 0;

			op->cycles = opcode_desc->cycles;
			op->size = opcode_desc->size;
			op->type = opcode_desc->type;
			op->jump = UT64_MAX;
			op->fail = UT64_MAX;
			op->addr = addr;

			r_strbuf_setf (&op->esil, "");

			opcode_desc->handler (anal, op, buf, len, &fail, cpu);
			if (fail) {
				goto INVALID_OP;
			}
			if (op->cycles <= 0) {
				opcode_desc->cycles = 2;
			}
			op->nopcode = (op->type == R_ANAL_OP_TYPE_UNK);

			t = r_strbuf_get (&op->esil);
			if (t && strlen (t) > 1) {
				t += strlen (t) - 1;
				if (*t == ',') {
					*t = '\0';
				}
			}

			return opcode_desc;
		}
	}

	if ((ins & 0xff00) == 0xff00 && (ins & 0xf) > 7) {
		goto INVALID_OP;
	}

INVALID_OP:
	op->family = R_ANAL_OP_FAMILY_UNKNOWN;
	op->type = R_ANAL_OP_TYPE_UNK;
	op->addr = addr;
	op->fail = UT64_MAX;
	op->jump = UT64_MAX;
	op->ptr = UT64_MAX;
	op->val = UT64_MAX;
	op->nopcode = 1;
	op->cycles = 1;
	op->size = 2;
	r_strbuf_set (&op->esil, "1,$");

	return NULL;
}

Project: radare2
File: anal_avr.c

static CPU_CONST *const_by_name(CPU_MODEL *cpu, int type, char *c) {
	CPU_CONST **clist, *citem;

	for (clist = cpu->consts; *clist; clist++) {
		for (citem = *clist; citem->key; citem++) {
			if (!strcmp (c, citem->key)
			&& (type == CPU_CONST_NONE || type == citem->type)) {
				return citem;
			}
		}
	}
	if (cpu->inherit_cpu_p)
		return const_by_name (cpu->inherit_cpu_p, type, c);
	eprintf ("ERROR: CONSTANT key[%s] NOT FOUND.\n", c);
	return NULL;
}

Project: radare2
File: anal_avr.c

static CPU_CONST *const_by_value(CPU_MODEL *cpu, int type, ut32 v) {
	CPU_CONST **clist, *citem;

	for (clist = cpu->consts; *clist; clist++) {
		for (citem = *clist; citem && citem->key; citem++) {
			if (citem->value == (MASK (citem->size * 8) & v)
			&& (type == CPU_CONST_NONE || type == citem->type)) {
				return citem;
			}
		}
	}
	if (cpu->inherit_cpu_p)
		return const_by_value (cpu->inherit_cpu_p, type, v);
	return NULL;
}

Project: radare2
File: anal_avr.c

static ut32 const_get_value(CPU_CONST *c) {
	return c ? MASK (c->size * 8) & c->value : 0;
}

Project: radare2
File: anal_avr.c

static int esil_avr_fini(RAnalEsil *esil) {
	return true;
}

Project: radare2

static int esil_avr_hook_reg_write(RAnalEsil *esil, const char *name, ut64 *val) {
	CPU_MODEL *cpu;

	if (!esil || !esil->anal) {
		return 0;
	}

	cpu = get_cpu_model (esil->anal->cpu);

	if (!strcmp (name, "pc")) {
		*val &= CPU_PC_MASK (cpu);
	} else if (!strcmp (name, "pcl")) {
		if (cpu->pc < 8) {
			*val &= MASK (8);
		}
	} else if (!strcmp (name, "pch")) {
		*val = cpu->pc > 8
			? *val & MASK (cpu->pc - 8)
			: 0;
	}

	return 0;
}

Project: radare2

static CPU_MODEL *get_cpu_model(char *model) {
	static CPU_MODEL *cpu = NULL;

	if (cpu && !strcasecmp (model, cpu->model))
		return cpu;

	cpu = __get_cpu_model_recursive (model);

	return cpu;
}

Project: radare2

static int set_reg_profile(RAnal *anal) {
	const char *p =
		"=PC	pcl\n"
		"=SP	sp\n"
		"=A0	r25\n"
		"=A1	r24\n"
		"=A2	r23\n"
		"=A3	r22\n"
		"=R0	r24\n"
#if 0
PC: 16- or 22-bit program counter
SP: 8- or 16-bit stack pointer
SREG: 8-bit status register
RAMPX, RAMPY, RAMPZ, RAMPD and EIND:
#endif
		"gpr	r0	.8	0	0\n"
		"gpr	r1	.8	1	0\n"
		"gpr	r2	.8	2	0\n"
		"gpr	r3	.8	3	0\n"
		"gpr	r4	.8	4	0\n"
		"gpr	r5	.8	5	0\n"
		"gpr	r6	.8	6	0\n"
		"gpr	r7	.8	7	0\n"
		"gpr	text	.64	0	0\n"
		"gpr	r8	.8	8	0\n"
		"gpr	r9	.8	9	0\n"
		"gpr	r10	.8	10	0\n"
		"gpr	r11	.8	11	0\n"
		"gpr	r12	.8	12	0\n"
		"gpr	r13	.8	13	0\n"
		"gpr	r14	.8	14	0\n"
		"gpr	r15	.8	15	0\n"
		"gpr	deskey	.64	8	0\n"
		"gpr	r16	.8	16	0\n"
		"gpr	r17	.8	17	0\n"
		"gpr	r18	.8	18	0\n"
		"gpr	r19	.8	19	0\n"
		"gpr	r20	.8	20	0\n"
		"gpr	r21	.8	21	0\n"
		"gpr	r22	.8	22	0\n"
		"gpr	r23	.8	23	0\n"
		"gpr	r24	.8	24	0\n"
		"gpr	r25	.8	25	0\n"
		"gpr	r26	.8	26	0\n"
		"gpr	r27	.8	27	0\n"
		"gpr	r28	.8	28	0\n"
		"gpr	r29	.8	29	0\n"
		"gpr	r30	.8	30	0\n"
		"gpr	r31	.8	31	0\n"

		"gpr	r17:r16	.16	16	0\n"
		"gpr	r19:r18	.16	18	0\n"
		"gpr	r21:r20	.16	20	0\n"
		"gpr	r23:r22	.16	22	0\n"
		"gpr	r25:r24	.16	24	0\n"
		"gpr	r27:r26	.16	26	0\n"
		"gpr	r29:r28	.16	28	0\n"
		"gpr	r31:r30	.16	30	0\n"

		"gpr	x	.16	26	0\n"
		"gpr	y	.16	28	0\n"
		"gpr	z	.16	30	0\n"
		"gpr	pc	.32	32	0\n"
		"gpr	pcl	.16	32	0\n"
		"gpr	pch	.16	34	0\n"
		"gpr	sp	.16	36	0\n"
		"gpr	spl	.8	36	0\n"
		"gpr	sph	.8	37	0\n"
		"gpr	sreg	.8	38	0\n"
		"gpr	cf	.1	38.0	0\n" // Carry. This is a borrow flag on subtracts.
		"gpr	zf	.1	38.1	0\n" // Zero. Set to 1 when an arithmetic result is zero.
		"gpr	nf	.1	38.2	0\n" // Negative. Set to a copy of the most significant bit of an arithmetic result.
		"gpr	vf	.1	38.3	0\n" // Overflow flag. Set in case of two's complement overflow.
		"gpr	sf	.1	38.4	0\n" // Sign flag. Unique to AVR, this is always (N ^ V) (xor), and shows the true sign of a comparison.
		"gpr	hf	.1	38.5	0\n" // Half carry. This is an internal carry from additions and is used to support BCD arithmetic.
		"gpr	tf	.1	38.6	0\n" // Bit copy. Special bit load and bit store instructions use this bit.
		"gpr	if	.1	38.7	0\n" // Interrupt flag. Set when interrupts are enabled.
		"gpr	rampx	.8	39	0\n"
		"gpr	rampy	.8	40	0\n"
		"gpr	rampz	.8	41	0\n"
		"gpr	rampd	.8	42	0\n"
		"gpr	eind	.8	43	0\n"
		"gpr	_prog	.32	44	0\n"
		"gpr    _page   .32     48	0\n"
		"gpr	_eeprom	.32	52	0\n"
		"gpr	_ram	.32	56	0\n"
		"gpr	_io	.32	56	0\n"
		"gpr	_sram	.32	60	0\n"
		"gpr    spmcsr  .8      64      0\n"
		;

	return r_reg_set_profile_string (anal->reg, p);
}

Project: radare2

static void __anal_reg_list(RCore *core, int type, int bits, char mode) {
	RReg *hack = core->dbg->reg;
	const char *use_color;
	int use_colors = r_config_get_i (core->config, "scr.color");
	if (use_colors) {
#undef ConsP
#define ConsP(x) (core->cons && core->cons->pal.x)? core->cons->pal.x
		use_color = ConsP (creg) : Color_BWHITE;
	} else {
		use_color = NULL;
	}
	if (bits < 0) {
		bits = 0;
	} else if (!bits) {
		bits = core->anal->bits;
	}
	if (core->anal) {
		core->dbg->reg = core->anal->reg;
		if (core->anal->cur && core->anal->cur->arch) {
			/* workaround for thumb */
			if (!strcmp (core->anal->cur->arch, "arm") && bits == 16) {
				bits = 32;
			}
			/* workaround for 6502 */
			if (!strcmp (core->anal->cur->arch, "6502") && bits == 8) {
				r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 16, mode, use_color); // XXX detect which one is current usage
			}
			if (!strcmp (core->anal->cur->arch, "avr") && bits == 8) {
				r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 16, mode, use_color); // XXX detect which one is current usage
			}
		}
	}

	if (mode == '=') {
		int pcbits = 0;
		const char *pcname = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
		RRegItem *reg = r_reg_get (core->anal->reg, pcname, 0);
		if (bits != reg->size) {
			pcbits = reg->size;
		}
		if (pcbits) {
			r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, pcbits, 2, use_color); // XXX detect which one is current usage
		}
	}
	r_debug_reg_list (core->dbg, type, bits, mode, use_color);
	core->dbg->reg = hack;
}

Project: radare2

static void _anal_calls(RCore *core, ut64 addr, ut64 addr_end) {
	RAnalOp op;
	int bufi;
	int depth = r_config_get_i (core->config, "anal.depth");
	const int addrbytes = core->io->addrbytes;
	const int bsz = 4096;
	ut8 *buf;
	ut8 *block;
	bufi = 0;
	if (addr_end - addr > UT32_MAX) {
		return;
	}
	buf = malloc (bsz);
	block = malloc (bsz);
	if (!buf || !block) {
		eprintf ("Error: cannot allocate buf or block\n");
		free (buf);
		free (block);
		return;
	}

	int minop = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_MIN_OP_SIZE);
	if (minop < 1) {
		minop = 1;
	}
	while (addr < addr_end) {
		if (r_cons_is_breaked ()) {
			break;
		}
		if (bufi > 4000) {
			bufi = 0;
		}
		if (!bufi) {
			r_io_read_at (core->io, addr, buf, bsz);
		}
		memset (block, -1, bsz);
		if (!memcmp (buf, block, bsz)) {
			addr += bsz;
			continue;
		}
		memset (block, 0, bsz);
		if (!memcmp (buf, block, bsz)) {
			addr += bsz;
			continue;
		}
		if (r_anal_op (core->anal, &op, addr, buf + bufi, bsz - bufi, 0) > 0) {
			if (op.size < 1) {
				op.size = minop;
			}
			if (op.type == R_ANAL_OP_TYPE_CALL) {
#if JAYRO_03
#error FUCK
				if (!anal_is_bad_call (core, from, to, addr, buf, bufi)) {
					fcn = r_anal_get_fcn_in (core->anal, op.jump, R_ANAL_FCN_TYPE_ROOT);
					if (!fcn) {
						r_core_anal_fcn (core, op.jump, addr,
						  R_ANAL_REF_TYPE_NULL, depth);
					}
				}
#else
				r_anal_xrefs_set (core->anal, R_ANAL_REF_TYPE_CALL, addr, op.jump);
				if (r_io_is_valid_offset (core->io, op.jump, 1)) {
					r_core_anal_fcn (core, op.jump, addr, R_ANAL_REF_TYPE_NULL, depth);
				}
#endif
			}

		} else {
			op.size = minop;
		}
		if ((int)op.size < 1) {
			op.size = minop;
		}
		addr += op.size;
		bufi += addrbytes * op.size;
		r_anal_op_fini (&op);
	}
	free (buf);
	free (block);
}

Project: radare2
File: cmd_anal.c

static void aea_stats_fini (AeaStats *stats) {
	R_FREE (stats->regs);
	R_FREE (stats->regread);
	R_FREE (stats->regwrite);
	R_FREE (stats->inputregs);
}

Project: radare2

static void aea_stats_init (AeaStats *stats) {
	stats->regs = r_list_newf (free);
	stats->regread = r_list_newf (free);
	stats->regwrite = r_list_newf (free);
	stats->inputregs = r_list_newf (free);
}

Project: radare2

static void afCc(RCore *core, const char *input) {
	ut64 addr;
	RAnalFunction *fcn;
	if (*input == ' ') {
		addr = r_num_math (core->num, input);
	} else {
		addr = core->offset;
	}
	if (addr == 0LL) {
		fcn = r_anal_fcn_find_name (core->anal, input + 3);
	} else {
		fcn = r_anal_get_fcn_in (core->anal, addr, R_ANAL_FCN_TYPE_NULL);
	}
	if (fcn) {
		ut32 totalCycles = r_anal_fcn_cost (core->anal, fcn);
		r_cons_printf ("%d\n", totalCycles);
	} else {
		eprintf ("Cannot find function\n");
	}
}

Project: radare2
File: cmd_anal.c

static void agraph_print_edge_dot(RANode *from, RANode *to, void *user) {
	r_cons_printf ("\"%s\" -> \"%s\"\n", from->title, to->title);
}

Project: radare2

static void agraph_print_node(RANode *n, void *user) {
	char *encbody, *cmd;
	int len = strlen (n->body);

	if (n->body[len - 1] == '\n') {
		len--;
	}
	encbody = r_base64_encode_dyn (n->body, len);
	cmd = r_str_newf ("agn \"%s\" base64:%s\n", n->title, encbody);
	r_cons_printf (cmd);
	free (cmd);
	free (encbody);
}

Project: radare2

static void agraph_print_node_dot(RANode *n, void *user) {
	char *label = strdup (n->body);
	if (!label || !*label) {
		r_cons_printf ("\"%s\" [URL=\"%s\", color=\"lightgray\", label=\"%s\"]\n",
				n->title, n->title, n->title);
	} else {
		r_cons_printf ("\"%s\" [URL=\"%s\", color=\"lightgray\", label=\"%s\\n%s\"]\n",
				n->title, n->title, n->title, label);
	}
	free (label);
}