mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-28 07:30:33 +00:00
Fix indent issues, pass out buffer size and fix disasm return value
This commit is contained in:
parent
2f950f5ebe
commit
49f40816d3
@ -151,6 +151,7 @@ CPU_MODEL cpu_models[] = {
|
||||
NULL
|
||||
}
|
||||
},
|
||||
//{ .model = NULL },
|
||||
};
|
||||
|
||||
/// XXX this code is awful
|
||||
@ -178,8 +179,11 @@ static CPU_MODEL *__get_cpu_model_recursive(const char *model) {
|
||||
|
||||
static CPU_MODEL *get_cpu_model(const char *model) {
|
||||
static CPU_MODEL *cpu = NULL;
|
||||
if (!model) {
|
||||
return NULL;
|
||||
}
|
||||
// cache
|
||||
if (cpu && !r_str_casecmp (model, cpu->model)) {
|
||||
if (cpu && cpu->model && !r_str_casecmp (model, cpu->model)) {
|
||||
return cpu;
|
||||
}
|
||||
return cpu = __get_cpu_model_recursive (model);
|
||||
@ -1687,31 +1691,26 @@ INVALID_OP:
|
||||
|
||||
//TODO: remove register analysis comment when each avr cpu will be implemented in asm plugin
|
||||
static int avr_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
|
||||
CPU_MODEL *cpu;
|
||||
ut64 offset;
|
||||
int size = -1;
|
||||
char mnemonic[32] = {0};
|
||||
|
||||
set_invalid_op (op, addr);
|
||||
|
||||
size = avr_anal (anal, mnemonic, addr, buf, len);
|
||||
int size = avr_anal (anal, mnemonic, sizeof (mnemonic), addr, buf, len);
|
||||
|
||||
if (!strcmp (mnemonic, "invalid") ||
|
||||
!strcmp (mnemonic, "truncated")) {
|
||||
op->eob = true;
|
||||
op->mnemonic = strdup(mnemonic);
|
||||
return -1;
|
||||
}
|
||||
if (!op) {
|
||||
return -1;
|
||||
op->mnemonic = strdup (mnemonic);
|
||||
op->size = 2;
|
||||
return -1;//R_MIN (len, 2);
|
||||
}
|
||||
|
||||
// select cpu info
|
||||
cpu = get_cpu_model (anal->cpu);
|
||||
CPU_MODEL *cpu = get_cpu_model (anal->cpu);
|
||||
|
||||
// set memory layout registers
|
||||
if (anal->esil) {
|
||||
offset = 0;
|
||||
ut64 offset = 0;
|
||||
r_anal_esil_reg_write (anal->esil, "_prog", offset);
|
||||
|
||||
offset += (1 << cpu->pc);
|
||||
@ -1729,7 +1728,7 @@ static int avr_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len,
|
||||
// process opcode
|
||||
avr_op_analyze (anal, op, addr, buf, len, cpu);
|
||||
|
||||
op->mnemonic = strdup (mnemonic);
|
||||
op->mnemonic = op->size > 1? strdup (mnemonic): "invalid";
|
||||
op->size = size;
|
||||
|
||||
return size;
|
||||
@ -1818,8 +1817,7 @@ static bool avr_custom_spm_page_erase(RAnalEsil *esil) {
|
||||
|
||||
// ESIL operation SPM_PAGE_FILL
|
||||
static bool avr_custom_spm_page_fill(RAnalEsil *esil) {
|
||||
CPU_MODEL *cpu;
|
||||
ut64 addr, page_size_bits, i;
|
||||
ut64 addr, i;
|
||||
ut8 r0, r1;
|
||||
|
||||
// sanity check
|
||||
@ -1843,8 +1841,8 @@ static bool avr_custom_spm_page_fill(RAnalEsil *esil) {
|
||||
r1 = i;
|
||||
|
||||
// get details about current MCU and fix input address
|
||||
cpu = get_cpu_model (esil->anal->cpu);
|
||||
page_size_bits = const_get_value (const_by_name (cpu, CPU_CONST_PARAM, "page_size"));
|
||||
CPU_MODEL *cpu = get_cpu_model (esil->anal->cpu);
|
||||
ut64 page_size_bits = const_get_value (const_by_name (cpu, CPU_CONST_PARAM, "page_size"));
|
||||
|
||||
// align and crop base address
|
||||
addr &= (MASK (page_size_bits) ^ 1);
|
||||
@ -1895,14 +1893,13 @@ static bool avr_custom_spm_page_write(RAnalEsil *esil) {
|
||||
}
|
||||
|
||||
static bool esil_avr_hook_reg_write(RAnalEsil *esil, const char *name, ut64 *val) {
|
||||
CPU_MODEL *cpu;
|
||||
|
||||
// r_return_val_if_fail (esil && esil->anal, false);
|
||||
if (!esil || !esil->anal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// select cpu info
|
||||
cpu = get_cpu_model (esil->anal->cpu);
|
||||
CPU_MODEL *cpu = get_cpu_model (esil->anal->cpu);
|
||||
|
||||
// crop registers and force certain values
|
||||
if (!strcmp (name, "pc")) {
|
||||
@ -1929,7 +1926,6 @@ static int esil_avr_init(RAnalEsil *esil) {
|
||||
r_anal_esil_set_op (esil, "SPM_PAGE_FILL", avr_custom_spm_page_fill, 0, 0, R_ANAL_ESIL_OP_TYPE_CUSTOM);
|
||||
r_anal_esil_set_op (esil, "SPM_PAGE_WRITE", avr_custom_spm_page_write, 0, 0, R_ANAL_ESIL_OP_TYPE_CUSTOM);
|
||||
esil->cb.hook_reg_write = esil_avr_hook_reg_write;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1938,7 +1934,7 @@ static int esil_avr_fini(RAnalEsil *esil) {
|
||||
}
|
||||
|
||||
static bool set_reg_profile(RAnal *anal) {
|
||||
char *registers_profile = strdup(
|
||||
char *registers_profile = strdup (
|
||||
"=PC pcl\n"
|
||||
"=SN r24\n"
|
||||
"=SP sp\n"
|
||||
|
@ -16,6 +16,18 @@ typedef struct _specialregs specialregs;
|
||||
|
||||
#define REGS_TABLE 9
|
||||
|
||||
/* gets the number from string
|
||||
duplicate from asm_x86_nz.c -- may be create a generic function? */
|
||||
static int getnum(const char *s) {
|
||||
if (!s || !*s) {
|
||||
return 0;
|
||||
}
|
||||
if (*s == '$') {
|
||||
s++;
|
||||
}
|
||||
return sdb_atoi (s);
|
||||
}
|
||||
|
||||
// radare tolower instruction in rasm, so we use 'x' instead of 'X' etc.
|
||||
specialregs RegsTable[REGS_TABLE] = {
|
||||
{"-x", OPERAND_XP}, {"x", OPERAND_X}, {"x+", OPERAND_XP},
|
||||
@ -116,6 +128,43 @@ int avr_encode(RAsm *a, RAsmOp *ao, const char *str) {
|
||||
return len;
|
||||
}
|
||||
|
||||
static int assemble_general_io_operand(const char *operand, uint32_t *res) {
|
||||
/*@
|
||||
requires strcmp (operand, "spl") == 0 || strcmp (operand, "0x3d") == 0 ||
|
||||
strcmp (operand, "sph") == 0 || strcmp (operand, "0x3e") == 0 ||
|
||||
strcmp (operand, "sreg") == 0 || strcmp (operand, "0x3f") == 0
|
||||
|
||||
behavior case_spl
|
||||
assumes strcmp (operand, "spl") == 0 || strcmp (operand, "0x3d") == 0
|
||||
ensure *res == 0x3d
|
||||
behavior case_sph
|
||||
assumes strcmp (operand, "sph") == 0 || strcmp (operand, "0x3e") == 0
|
||||
ensure *res == 0x3d
|
||||
behavior case_sreg
|
||||
assumes strcmp (operand, "sreg") == 0 || strcmp (operand, "0x3f") == 0
|
||||
ensure *res == 0x3d
|
||||
|
||||
complete behaviors;
|
||||
disjoint behaviors;
|
||||
*/
|
||||
int ret = -1;
|
||||
if (!strcmp (operand, "spl") || !strcmp (operand, "0x3d")) {
|
||||
*res = 0x3d;
|
||||
ret = 0;
|
||||
} else if (!strcmp (operand, "sph") || !strcmp (operand, "0x3e")) {
|
||||
*res = 0x3e;
|
||||
ret = 0;
|
||||
} else if (!strcmp (operand, "sreg") || !strcmp (operand, "0x3f")) {
|
||||
*res = 0x3f;
|
||||
ret = 0;
|
||||
}/* else {
|
||||
*res = getnum (operand); // return pure number
|
||||
ret = 0;
|
||||
}*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// assembles instruction argument (operand) based on its type
|
||||
int assemble_operand(RAsm *a, const char *operand, int type, uint32_t *res) {
|
||||
int ret = -1;
|
||||
@ -138,12 +187,12 @@ int assemble_operand(RAsm *a, const char *operand, int type, uint32_t *res) {
|
||||
break;
|
||||
case OPERAND_BRANCH_ADDRESS:
|
||||
case OPERAND_RELATIVE_ADDRESS: // TODO: <-- check for negative (should be correct, but...)
|
||||
temp = getnum (a, operand); // return pure number
|
||||
temp = getnum (operand); // return pure number
|
||||
/* the argument could be:
|
||||
- target address (will be calculated in according to current pc of assemble), ex: 0x4, 200, 0x1000
|
||||
or
|
||||
- relative address, ex: +2, -1, +60, -49 */
|
||||
if(a->pc || (operand[0] != '+' && operand[0] != '-')) { // for series of commands
|
||||
if (a->pc || (operand[0] != '+' && operand[0] != '-')) { // for series of commands
|
||||
/* +2 from documentation:
|
||||
If Rd != Rr (Z = 0) then PC <- PC + k + 1, else PC <- PC + 1 */
|
||||
temp -= a->pc + 2;
|
||||
@ -162,11 +211,11 @@ int assemble_operand(RAsm *a, const char *operand, int type, uint32_t *res) {
|
||||
case OPERAND_DES_ROUND:
|
||||
case OPERAND_LONG_ABSOLUTE_ADDRESS:
|
||||
case OPERAND_DATA:
|
||||
*res = getnum(a, operand); // return pure number
|
||||
*res = getnum (operand); // return pure number
|
||||
ret = 0;
|
||||
break;
|
||||
case OPERAND_COMPLEMENTED_DATA:
|
||||
*res = getnum(a, operand); // return pure number
|
||||
*res = getnum (operand); // return pure number
|
||||
*res = ~(*res) & 0xFF; // complement it
|
||||
ret = 0;
|
||||
break;
|
||||
@ -182,21 +231,19 @@ int assemble_operand(RAsm *a, const char *operand, int type, uint32_t *res) {
|
||||
*res = 0; //do nothing, operand is already encoded in opcode
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case OPERAND_YPQ:
|
||||
case OPERAND_ZPQ:
|
||||
if (strlen(operand) > 2) {
|
||||
/* return argument after '+' sign
|
||||
we've already checked presence of '+' in parse_specialreg */
|
||||
*res = getnum(a, operand + 2);
|
||||
*res = getnum (operand + 2);
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPERAND_REGISTER:
|
||||
if (strlen(operand) > 1) {
|
||||
// returns register number (r__)
|
||||
*res = getnum(a, operand + 1);
|
||||
*res = getnum (operand + 1);
|
||||
if (*res <= 32) {
|
||||
ret = 0;
|
||||
}
|
||||
@ -205,7 +252,7 @@ int assemble_operand(RAsm *a, const char *operand, int type, uint32_t *res) {
|
||||
case OPERAND_REGISTER_STARTR16:
|
||||
if (strlen(operand) > 1) {
|
||||
// returns register number (r__)
|
||||
*res = getnum(a, operand + 1);
|
||||
*res = getnum (operand + 1);
|
||||
if (*res >= 16 && *res <= 32) {
|
||||
*res -= 16;
|
||||
ret = 0;
|
||||
@ -228,11 +275,11 @@ uint16_t packDataByMask(uint16_t data, uint16_t mask) {
|
||||
* j counts through every bit of the original */
|
||||
for (i = 0, j = 0; i < 16; i++) {
|
||||
// If the mask has a bit in this position
|
||||
if (mask & (1<<i)) {
|
||||
if (mask & (1 << i)) {
|
||||
/* If there is a data bit with this mask bit counter(j),
|
||||
* then toggle that bit in the extracted data (result) by mask offset(i).*/
|
||||
if ((data & (1<<j)) != 0) {
|
||||
result |= (1<<i);
|
||||
if ((data & (1 << j)) != 0) {
|
||||
result |= (1 << i);
|
||||
}
|
||||
// Increment the original data bit count.
|
||||
j++;
|
||||
@ -277,7 +324,7 @@ int search_instruction(RAsm *a, char instr[3][MAX_TOKEN_SIZE], int args) {
|
||||
&& instructionSet[i].operandTypes[1] == OPERAND_LONG_ABSOLUTE_ADDRESS) {
|
||||
// ineffective, but needed for lds/sts and other cases
|
||||
if (strlen(instr[2]) > 0) {
|
||||
op2 = getnum (a, instr[2]);
|
||||
op2 = getnum (instr[2]);
|
||||
if (op2 > 127) {
|
||||
return i;
|
||||
}
|
||||
@ -297,7 +344,7 @@ int search_instruction(RAsm *a, char instr[3][MAX_TOKEN_SIZE], int args) {
|
||||
&& instructionSet[i].operandTypes[0] == OPERAND_LONG_ABSOLUTE_ADDRESS) {
|
||||
// same for 1st operand of sts
|
||||
if (strlen(instr[1]) > 0) {
|
||||
op1 = getnum (a, instr[1]);
|
||||
op1 = getnum (instr[1]);
|
||||
if (op1 > 127) {
|
||||
return i;
|
||||
}
|
||||
@ -341,53 +388,3 @@ int parse_specialreg(const char *reg) {
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/* gets the number from string
|
||||
duplicate from asm_x86_nz.c -- may be create a generic function? */
|
||||
int getnum(RAsm *a, const char *s) {
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
if (*s == '$') {
|
||||
s++;
|
||||
}
|
||||
return sdb_atoi (s);
|
||||
}
|
||||
|
||||
int assemble_general_io_operand(const char *operand, uint32_t *res) {
|
||||
/*@
|
||||
requires strcmp (operand, "spl") == 0 || strcmp (operand, "0x3d") == 0 ||
|
||||
strcmp (operand, "sph") == 0 || strcmp (operand, "0x3e") == 0 ||
|
||||
strcmp (operand, "sreg") == 0 || strcmp (operand, "0x3f") == 0
|
||||
|
||||
behavior case_spl
|
||||
assumes strcmp (operand, "spl") == 0 || strcmp (operand, "0x3d") == 0
|
||||
ensure *res == 0x3d
|
||||
behavior case_sph
|
||||
assumes strcmp (operand, "sph") == 0 || strcmp (operand, "0x3e") == 0
|
||||
ensure *res == 0x3d
|
||||
behavior case_sreg
|
||||
assumes strcmp (operand, "sreg") == 0 || strcmp (operand, "0x3f") == 0
|
||||
ensure *res == 0x3d
|
||||
|
||||
complete behaviors;
|
||||
disjoint behaviors;
|
||||
*/
|
||||
int ret = -1;
|
||||
if (strcmp (operand, "spl") == 0 || strcmp (operand, "0x3d") == 0) {
|
||||
*res = 0x3d;
|
||||
ret = 0;
|
||||
} else if (strcmp (operand, "sph") == 0 || strcmp (operand, "0x3e") == 0) {
|
||||
*res = 0x3e;
|
||||
ret = 0;
|
||||
} else if(strcmp (operand, "sreg") == 0 || strcmp (operand, "0x3f") == 0) {
|
||||
*res = 0x3f;
|
||||
ret = 0;
|
||||
}/* else {
|
||||
*res = getnum(a, operand); // return pure number
|
||||
ret = 0;
|
||||
}*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -16,9 +16,5 @@ int assemble_operand(RAsm *a, const char *operand, int type, uint32_t *res);
|
||||
uint16_t packDataByMask(uint16_t data, uint16_t mask);
|
||||
int search_instruction(RAsm *a, char instr[3][MAX_TOKEN_SIZE], int args);
|
||||
int parse_specialreg(const char *reg);
|
||||
int getnum(RAsm *a, const char *s);
|
||||
|
||||
int assemble_general_io_operand(const char *operand, uint32_t *res);
|
||||
|
||||
|
||||
#endif /* LIBR_ASM_ARCH_AVR_ASSEMBLE_H_ */
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "r_asm.h"
|
||||
#include <string.h>
|
||||
|
||||
int avr_decode (RAsm *a, char *out, ut64 addr, cut8 *buf, int len) {
|
||||
int avr_decode(RAsm *a, char *out, int out_len, ut64 addr, cut8 *buf, int len) {
|
||||
formattingOptions opt = { 0 };
|
||||
disassembledInstruction dins;
|
||||
assembledInstruction ins;
|
||||
@ -38,11 +38,11 @@ int avr_decode (RAsm *a, char *out, ut64 addr, cut8 *buf, int len) {
|
||||
if (disassembleInstruction (&context, &dins, ins)) {
|
||||
return -1;
|
||||
}
|
||||
if (printDisassembledInstruction (a, &context, out, dins, opt) < 0) {
|
||||
if (printDisassembledInstruction (a, &context, out, out_len, dins, opt) < 0) {
|
||||
return -1;
|
||||
}
|
||||
opsize = 4;
|
||||
} else if (printDisassembledInstruction (a, &context, out, dins, opt) < 0) {
|
||||
} else if (printDisassembledInstruction (a, &context, out, out_len, dins, opt) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (out[0] == '.' || !out[0]) {
|
||||
@ -51,16 +51,15 @@ int avr_decode (RAsm *a, char *out, ut64 addr, cut8 *buf, int len) {
|
||||
return opsize;
|
||||
}
|
||||
|
||||
|
||||
int avr_anal (RAnal *a, char *out, ut64 addr, cut8 *buf, int len) {
|
||||
int avr_anal(RAnal *a, char *out, int out_size, ut64 addr, cut8 *buf, int len) {
|
||||
formattingOptions opt = { 0 };
|
||||
disassembledInstruction dins;
|
||||
assembledInstruction ins;
|
||||
avrDisassembleContext context = { 0 };
|
||||
int opsize = 2;
|
||||
|
||||
r_str_ncpy (out, "invalid", out_size);
|
||||
if (len < 2) {
|
||||
strcpy (out, "truncated");
|
||||
return -1;
|
||||
}
|
||||
// be sure that the buffer is always set.
|
||||
@ -70,13 +69,11 @@ int avr_anal (RAnal *a, char *out, ut64 addr, cut8 *buf, int len) {
|
||||
out[0] = 0;
|
||||
|
||||
if (disassembleInstruction (&context, &dins, ins)) {
|
||||
strcpy (out, "invalid");
|
||||
return -1;
|
||||
}
|
||||
if (context.status > 0) {
|
||||
if (len < 4) {
|
||||
strcpy (out, "truncated");
|
||||
return -1;
|
||||
return -2;
|
||||
}
|
||||
ins.address = addr;
|
||||
//ins.opcode = (buf[0] | buf[1]<<8) | (buf[2]<<16) | (buf[3]<<24);
|
||||
@ -86,16 +83,13 @@ int avr_anal (RAnal *a, char *out, ut64 addr, cut8 *buf, int len) {
|
||||
(buf[1]<<8) | (buf[0]);
|
||||
*/
|
||||
if (disassembleInstruction (&context, &dins, ins)) {
|
||||
strcpy (out, "invalid");
|
||||
return -1;
|
||||
}
|
||||
if (analPrintDisassembledInstruction (a, &context, out, dins, opt) < 0) {
|
||||
strcpy (out, "invalid");
|
||||
if (analPrintDisassembledInstruction (a, &context, out, out_size, dins, opt) < 0) {
|
||||
return -1;
|
||||
}
|
||||
opsize = 4;
|
||||
} else if (analPrintDisassembledInstruction (a, &context, out, dins, opt) < 0) {
|
||||
strcpy (out, "invalid");
|
||||
} else if (analPrintDisassembledInstruction (a, &context, out, out_size, dins, opt) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (out[0] == '.' || !out[0]) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef AVR_DISASSEMBLER_H
|
||||
#define AVR_DISASSEMBLER_H
|
||||
|
||||
int avr_decode (RAsm *a, char *out, ut64 addr, cut8 *buf, int len);
|
||||
int avr_anal (RAnal *a, char *out, ut64 addr, cut8 *buf, int len);
|
||||
int avr_decode(RAsm *a, char *out, int out_size, ut64 addr, cut8 *buf, int len);
|
||||
int avr_anal(RAnal *a, char *out, int out_size, ut64 addr, cut8 *buf, int len);
|
||||
|
||||
#endif /* AVR_DISASSEMBLER_H */
|
||||
|
@ -36,12 +36,12 @@
|
||||
* and so that the printing of the formatted operand is not hard coded into the format operand code.
|
||||
* If an addressLabelPrefix is specified in formattingOptions (option is set and string is not NULL),
|
||||
* it will print the relative branch/jump/call with this prefix and the destination address as the label. */
|
||||
static int formatDisassembledOperand(RAsm *a, avrDisassembleContext *context, char *strOperand, int operandNum, const disassembledInstruction dInstruction, formattingOptions fOptions);
|
||||
static int analFormatDisassembledOperand(RAnal *a, avrDisassembleContext *context, char *strOperand, int operandNum, const disassembledInstruction dInstruction, formattingOptions fOptions);
|
||||
static int formatDisassembledOperand(RAsm *a, avrDisassembleContext *context, char *strOperand, int strOperandSize, int operandNum, const disassembledInstruction dInstruction, formattingOptions fOptions);
|
||||
static int analFormatDisassembledOperand(RAnal *a, avrDisassembleContext *context, char *strOperand, int strOperandSize, int operandNum, const disassembledInstruction dInstruction, formattingOptions fOptions);
|
||||
|
||||
|
||||
/* Prints a disassembled instruction, formatted with options set in the formattingOptions structure. */
|
||||
int printDisassembledInstruction(RAsm *a, avrDisassembleContext *context, char *out, const disassembledInstruction dInstruction, formattingOptions fOptions) {
|
||||
int printDisassembledInstruction(RAsm *a, avrDisassembleContext *context, char *out, int out_len, const disassembledInstruction dInstruction, formattingOptions fOptions) {
|
||||
//char fmt[64];
|
||||
int retVal, i;
|
||||
char strOperand[256];
|
||||
@ -49,64 +49,75 @@ int printDisassembledInstruction(RAsm *a, avrDisassembleContext *context, char *
|
||||
|
||||
/* If we just found a long instruction, there is nothing to be printed yet, since we don't
|
||||
* have the entire long address ready yet. */
|
||||
if (context->status == AVR_LONG_INSTRUCTION_FOUND)
|
||||
if (context->status == AVR_LONG_INSTRUCTION_FOUND) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcat (out, dInstruction.instruction->mnemonic);
|
||||
if (dInstruction.instruction->numOperands > 0)
|
||||
strcat (out, " ");
|
||||
RStrBuf *sb = r_strbuf_new (dInstruction.instruction->mnemonic);
|
||||
if (dInstruction.instruction->numOperands > 0) {
|
||||
r_strbuf_append (sb, " ");
|
||||
}
|
||||
|
||||
for (i = 0; i < dInstruction.instruction->numOperands; i++) {
|
||||
/* If we're not on the first operand, but not on the last one either, print a comma separating
|
||||
* the operands. */
|
||||
if (i > 0 && i != dInstruction.instruction->numOperands)
|
||||
strcat (out, ", ");
|
||||
if (i > 0 && i != dInstruction.instruction->numOperands) {
|
||||
r_strbuf_append (sb, ", ");
|
||||
}
|
||||
/* Format the disassembled operand into the string strOperand, and print it */
|
||||
retVal = formatDisassembledOperand(a, context, strOperand, i, dInstruction, fOptions);
|
||||
if (retVal < 0)
|
||||
retVal = formatDisassembledOperand (a, context, strOperand, sizeof (strOperand), i, dInstruction, fOptions);
|
||||
if (retVal < 0) {
|
||||
r_strbuf_free (sb);
|
||||
return retVal;
|
||||
}
|
||||
/* Print the operand and free if it's not NULL */
|
||||
strcat (out, strOperand);
|
||||
r_strbuf_append (sb, strOperand);
|
||||
}
|
||||
|
||||
const char *src = r_strbuf_get (sb);
|
||||
r_str_ncpy (out, src, out_len);
|
||||
r_strbuf_free (sb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Prints a disassembled instruction, formatted with options set in the formattingOptions structure. */
|
||||
int analPrintDisassembledInstruction(RAnal *a, avrDisassembleContext *context, char *out, const disassembledInstruction dInstruction, formattingOptions fOptions) {
|
||||
int analPrintDisassembledInstruction(RAnal *a, avrDisassembleContext *context, char *out, int out_len, const disassembledInstruction dInstruction, formattingOptions fOptions) {
|
||||
//char fmt[64];
|
||||
int retVal, i;
|
||||
char strOperand[256];
|
||||
*out = '\0';
|
||||
|
||||
/* If we just found a long instruction, there is nothing to be printed yet, since we don't
|
||||
* have the entire long address ready yet. */
|
||||
if (context->status == AVR_LONG_INSTRUCTION_FOUND)
|
||||
if (context->status == AVR_LONG_INSTRUCTION_FOUND) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcat (out, dInstruction.instruction->mnemonic);
|
||||
if (dInstruction.instruction->numOperands > 0)
|
||||
strcat (out, " ");
|
||||
|
||||
RStrBuf *sb = r_strbuf_new (dInstruction.instruction->mnemonic);
|
||||
if (dInstruction.instruction->numOperands > 0) {
|
||||
r_strbuf_append (sb, " ");
|
||||
}
|
||||
for (i = 0; i < dInstruction.instruction->numOperands; i++) {
|
||||
/* If we're not on the first operand, but not on the last one either, print a comma separating
|
||||
* the operands. */
|
||||
if (i > 0 && i != dInstruction.instruction->numOperands)
|
||||
strcat (out, ", ");
|
||||
if (i > 0 && i != dInstruction.instruction->numOperands) {
|
||||
r_strbuf_append (sb, ", ");
|
||||
}
|
||||
/* Format the disassembled operand into the string strOperand, and print it */
|
||||
retVal = analFormatDisassembledOperand(a, context, strOperand, i, dInstruction, fOptions);
|
||||
if (retVal < 0)
|
||||
retVal = analFormatDisassembledOperand (a, context, strOperand, sizeof (strOperand), i, dInstruction, fOptions);
|
||||
if (retVal < 0) {
|
||||
r_strbuf_free (sb);
|
||||
return retVal;
|
||||
}
|
||||
/* Print the operand and free if it's not NULL */
|
||||
strcat (out, strOperand);
|
||||
r_strbuf_append (sb, strOperand);
|
||||
}
|
||||
|
||||
char *src = r_strbuf_get (sb);
|
||||
r_str_ncpy (out, src, out_len);
|
||||
r_strbuf_free (sb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int formatDisassembledOperand(RAsm *a, avrDisassembleContext *context, char *strOperand, int operandNum, const disassembledInstruction dInstruction, formattingOptions fOptions) {
|
||||
static int formatDisassembledOperand(RAsm *a, avrDisassembleContext *context, char *strOperand, int strOperandSize, int operandNum, const disassembledInstruction dInstruction, formattingOptions fOptions) {
|
||||
char binary[9];
|
||||
int retVal;
|
||||
|
||||
@ -192,8 +203,7 @@ static int formatDisassembledOperand(RAsm *a, avrDisassembleContext *context, ch
|
||||
const char *current_register = NULL;
|
||||
bool is_register_found = false;
|
||||
|
||||
switch (dInstruction.operands[operandNum])
|
||||
{
|
||||
switch (dInstruction.operands[operandNum]) {
|
||||
case 0x3d:
|
||||
current_register = "spl";//check the architecture for spl
|
||||
is_register_found = true;
|
||||
@ -208,10 +218,8 @@ static int formatDisassembledOperand(RAsm *a, avrDisassembleContext *context, ch
|
||||
break;
|
||||
}
|
||||
|
||||
if (!strcmp (r_str_get (a->cpu), "ATmega328p"))
|
||||
{
|
||||
switch (dInstruction.operands[operandNum])
|
||||
{
|
||||
if (!strcmp (r_str_get (a->cpu), "ATmega328p")) {
|
||||
switch (dInstruction.operands[operandNum]) {
|
||||
case 0x03:
|
||||
current_register = "pinb";
|
||||
is_register_found = true;
|
||||
@ -384,33 +392,30 @@ static int formatDisassembledOperand(RAsm *a, avrDisassembleContext *context, ch
|
||||
}
|
||||
}
|
||||
if (!strcmp (r_str_get (a->cpu), "AT90S1200")) {
|
||||
switch (dInstruction.operands[operandNum])
|
||||
{
|
||||
switch (dInstruction.operands[operandNum]) {
|
||||
case 0x08:
|
||||
current_register = "acsr";
|
||||
is_register_found = true;
|
||||
break;
|
||||
is_register_found = true;
|
||||
break;
|
||||
case 0x10:
|
||||
current_register = "pind";
|
||||
is_register_found = true;
|
||||
break;
|
||||
current_register = "pind";
|
||||
is_register_found = true;
|
||||
break;
|
||||
case 0x11:
|
||||
current_register = "ddrd";
|
||||
is_register_found = true;
|
||||
break;
|
||||
current_register = "ddrd";
|
||||
is_register_found = true;
|
||||
break;
|
||||
case 0x12:
|
||||
current_register = "portd";
|
||||
is_register_found = true;
|
||||
break;
|
||||
current_register = "portd";
|
||||
is_register_found = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_register_found == true) {
|
||||
retVal = r_str_ncpy (strOperand, current_register, sizeof (current_register));
|
||||
}
|
||||
else {
|
||||
if (is_register_found) {
|
||||
retVal = r_str_ncpy (strOperand, current_register, sizeof (strOperand));
|
||||
} else {
|
||||
retVal = snprintf (strOperand, 5, "0x%x", dInstruction.operands[operandNum]);
|
||||
}
|
||||
break;
|
||||
@ -446,32 +451,16 @@ static int formatDisassembledOperand(RAsm *a, avrDisassembleContext *context, ch
|
||||
/* This is impossible by normal operation. */
|
||||
default: return ERROR_UNKNOWN_OPERAND;
|
||||
}
|
||||
if (retVal < 0)
|
||||
return ERROR_MEMORY_ALLOCATION_ERROR;
|
||||
return 0;
|
||||
return retVal <0? ERROR_MEMORY_ALLOCATION_ERROR: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Formats a disassembled operand with its prefix (such as 'R' to indicate a register) into the
|
||||
* pointer to a C-string strOperand, which must be free'd after it has been used.
|
||||
* I decided to format the disassembled operands individually into strings for maximum flexibility,
|
||||
* and so that the printing of the formatted operand is not hard coded into the format operand code.
|
||||
* If an addressLabelPrefix is specified in formattingOptions (option is set and string is not NULL),
|
||||
* it will print the relative branch/jump/call with this prefix and the destination address as the label. */
|
||||
static int analFormatDisassembledOperand(RAnal *a, avrDisassembleContext *context, char *strOperand, int operandNum, const disassembledInstruction dInstruction, formattingOptions fOptions) {
|
||||
static int analFormatDisassembledOperand(RAnal *a, avrDisassembleContext *context, char *strOperand, int strOperandSize, int operandNum, const disassembledInstruction dInstruction, formattingOptions fOptions) {
|
||||
char binary[9];
|
||||
int retVal;
|
||||
|
||||
@ -488,7 +477,7 @@ static int analFormatDisassembledOperand(RAnal *a, avrDisassembleContext *contex
|
||||
case OPERAND_REGISTER_STARTR16:
|
||||
case OPERAND_REGISTER_EVEN_PAIR_STARTR24:
|
||||
case OPERAND_REGISTER_EVEN_PAIR:
|
||||
retVal = sprintf (strOperand, "%s%d", OPERAND_PREFIX_REGISTER,
|
||||
retVal = snprintf (strOperand, strOperandSize, "%s%d", OPERAND_PREFIX_REGISTER,
|
||||
dInstruction.operands[operandNum]);
|
||||
break;
|
||||
case OPERAND_DATA:
|
||||
@ -502,20 +491,20 @@ static int analFormatDisassembledOperand(RAnal *a, avrDisassembleContext *contex
|
||||
binary[7-i] = '0';
|
||||
}
|
||||
binary[8] = '\0';
|
||||
retVal = sprintf(strOperand, "%s%s",
|
||||
retVal = snprintf (strOperand, strOperandSize, "%s%s",
|
||||
OPERAND_PREFIX_DATA_BIN, binary);
|
||||
} else if (fOptions.options & FORMAT_OPTION_DATA_DEC) {
|
||||
retVal = sprintf(strOperand, "%s%d",
|
||||
retVal = snprintf (strOperand, strOperandSize, "%s%d",
|
||||
OPERAND_PREFIX_DATA_DEC,
|
||||
dInstruction.operands[operandNum]);
|
||||
} else {
|
||||
retVal = sprintf(strOperand, "%s%02x",
|
||||
retVal = snprintf (strOperand, strOperandSize, "%s%02x",
|
||||
OPERAND_PREFIX_DATA_HEX,
|
||||
dInstruction.operands[operandNum]);
|
||||
}
|
||||
break;
|
||||
case OPERAND_BIT:
|
||||
retVal = sprintf(strOperand, "%s%d", OPERAND_PREFIX_BIT,
|
||||
retVal = snprintf (strOperand, strOperandSize, "%s%d", OPERAND_PREFIX_BIT,
|
||||
dInstruction.operands[operandNum]);
|
||||
break;
|
||||
case OPERAND_BRANCH_ADDRESS:
|
||||
@ -543,12 +532,12 @@ static int analFormatDisassembledOperand(RAnal *a, avrDisassembleContext *contex
|
||||
// retVal = sprintf(strOperand, "%s%d", OPERAND_PREFIX_BRANCH_ADDRESS, dInstruction.operands[operandNum]);
|
||||
}
|
||||
#endif
|
||||
retVal = sprintf(strOperand, "0x%x",
|
||||
retVal = snprintf (strOperand, strOperandSize, "0x%x",
|
||||
dInstruction.address + dInstruction.operands[operandNum]);
|
||||
//}
|
||||
break;
|
||||
case OPERAND_LONG_ABSOLUTE_ADDRESS:
|
||||
retVal = sprintf(strOperand, "%s%0*x",
|
||||
retVal = snprintf (strOperand, strOperandSize, "%s%0*x",
|
||||
OPERAND_PREFIX_ABSOLUTE_ADDRESS,
|
||||
fOptions.addressFieldWidth, context->longAddress);
|
||||
break;
|
||||
@ -557,8 +546,7 @@ static int analFormatDisassembledOperand(RAnal *a, avrDisassembleContext *contex
|
||||
const char *current_register = NULL;
|
||||
bool is_register_found = false;
|
||||
|
||||
switch (dInstruction.operands[operandNum])
|
||||
{
|
||||
switch (dInstruction.operands[operandNum]) {
|
||||
case 0x3d:
|
||||
current_register = "spl";//check the architecture for spl
|
||||
is_register_found = true;
|
||||
@ -573,10 +561,8 @@ static int analFormatDisassembledOperand(RAnal *a, avrDisassembleContext *contex
|
||||
break;
|
||||
}
|
||||
|
||||
if (!strcmp (r_str_get (a->cpu), "ATmega328p"))
|
||||
{
|
||||
switch (dInstruction.operands[operandNum])
|
||||
{
|
||||
if (!strcmp (r_str_get (a->cpu), "ATmega328p")) {
|
||||
switch (dInstruction.operands[operandNum]) {
|
||||
case 0x03:
|
||||
current_register = "pinb";
|
||||
is_register_found = true;
|
||||
@ -746,7 +732,7 @@ static int analFormatDisassembledOperand(RAnal *a, avrDisassembleContext *contex
|
||||
|
||||
default:
|
||||
if (is_register_found == false) {
|
||||
retVal = snprintf (strOperand, 5, "0x%x", dInstruction.operands[operandNum]);
|
||||
retVal = snprintf (strOperand, strOperandSize, "0x%x", dInstruction.operands[operandNum]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -754,12 +740,10 @@ static int analFormatDisassembledOperand(RAnal *a, avrDisassembleContext *contex
|
||||
|
||||
|
||||
if (is_register_found) {
|
||||
r_str_ncpy (strOperand, current_register, sizeof (current_register));
|
||||
r_str_ncpy (strOperand, current_register, strOperandSize);
|
||||
} else {
|
||||
retVal = snprintf (strOperand, strOperandSize, "0x%x", dInstruction.operands[operandNum]);
|
||||
}
|
||||
else {
|
||||
retVal = snprintf (strOperand, 5, "0x%x", dInstruction.operands[operandNum]);
|
||||
}
|
||||
|
||||
retVal = strlen (strOperand);
|
||||
break;
|
||||
}
|
||||
@ -775,45 +759,39 @@ static int analFormatDisassembledOperand(RAnal *a, avrDisassembleContext *contex
|
||||
dInstruction.operands[operandNum]);
|
||||
break;
|
||||
case OPERAND_YPQ:
|
||||
retVal = sprintf(strOperand, "y+%d",
|
||||
retVal = snprintf (strOperand, strOperandSize, "y+%d",
|
||||
dInstruction.operands[operandNum]);
|
||||
break;
|
||||
case OPERAND_ZPQ:
|
||||
retVal = sprintf(strOperand, "z+%d",
|
||||
retVal = snprintf (strOperand, strOperandSize, "z+%d",
|
||||
dInstruction.operands[operandNum]);
|
||||
break;
|
||||
case OPERAND_X: retVal = sprintf(strOperand, "x"); break;
|
||||
case OPERAND_XP: retVal = sprintf(strOperand, "x+"); break;
|
||||
case OPERAND_MX: retVal = sprintf(strOperand, "-x"); break;
|
||||
case OPERAND_Y: retVal = sprintf(strOperand, "y"); break;
|
||||
case OPERAND_YP: retVal = sprintf(strOperand, "y+"); break;
|
||||
case OPERAND_MY: retVal = sprintf(strOperand, "-y"); break;
|
||||
case OPERAND_Z: retVal = sprintf(strOperand, "z"); break;
|
||||
case OPERAND_ZP: retVal = sprintf(strOperand, "z+"); break;
|
||||
case OPERAND_MZ: retVal = sprintf(strOperand, "-z"); break;
|
||||
case OPERAND_X: retVal = snprintf (strOperand, strOperandSize, "x"); break;
|
||||
case OPERAND_XP: retVal = snprintf (strOperand, strOperandSize, "x+"); break;
|
||||
case OPERAND_MX: retVal = snprintf (strOperand, strOperandSize, "-x"); break;
|
||||
case OPERAND_Y: retVal = snprintf (strOperand, strOperandSize, "y"); break;
|
||||
case OPERAND_YP: retVal = snprintf (strOperand, strOperandSize, "y+"); break;
|
||||
case OPERAND_MY: retVal = snprintf (strOperand, strOperandSize, "-y"); break;
|
||||
case OPERAND_Z: retVal = snprintf (strOperand, strOperandSize, "z"); break;
|
||||
case OPERAND_ZP: retVal = snprintf (strOperand, strOperandSize, "z+"); break;
|
||||
case OPERAND_MZ: retVal = snprintf (strOperand, strOperandSize, "-z"); break;
|
||||
/* This is impossible by normal operation. */
|
||||
default: return ERROR_UNKNOWN_OPERAND;
|
||||
}
|
||||
if (retVal < 0)
|
||||
return ERROR_MEMORY_ALLOCATION_ERROR;
|
||||
return 0;
|
||||
return retVal < 0? ERROR_MEMORY_ALLOCATION_ERROR: 0;
|
||||
}
|
||||
|
||||
|
||||
int parse_registerpair(const char *operand) {
|
||||
int res = -1;
|
||||
char *first, *second, *op;
|
||||
int fnum, snum;
|
||||
|
||||
op = strdup (operand);
|
||||
first = strtok (op, ":");
|
||||
char *op = strdup (operand);
|
||||
char *first = strtok (op, ":");
|
||||
|
||||
if (!first || strlen (first) < 2) {
|
||||
free (op);
|
||||
return -1;
|
||||
}
|
||||
|
||||
second = strtok (NULL, ":");
|
||||
char *second = strtok (NULL, ":");
|
||||
|
||||
/* the next code handles two possible different representation of pair
|
||||
by pair rx+1:rx
|
||||
@ -825,21 +803,21 @@ int parse_registerpair(const char *operand) {
|
||||
this is currently useless, cause rasm2 filters ':' from assembler
|
||||
however, this bug soon will be fixed */
|
||||
if (first[0] == 'r' && second[0] == 'r') {
|
||||
fnum = atoi(first+1);
|
||||
snum = atoi(second+1);
|
||||
int fnum = atoi (first + 1);
|
||||
int snum = atoi (second + 1);
|
||||
if (fnum > snum && snum >= 0 && snum <= 30) {
|
||||
res = snum / 2;
|
||||
}
|
||||
} else if (first[0] >= 'x' && first[0] <= 'z'
|
||||
&& second[0] >= 'x' && second[0] <= 'z'
|
||||
&& first[1] == 'h' && second[1] == 'l') {
|
||||
&& second[0] >= 'x' && second[0] <= 'z'
|
||||
&& first[1] == 'h' && second[1] == 'l') {
|
||||
// convert to register pair number by inversing and invert (and adding 12)
|
||||
res = (2 - ('z' - first[0])) + 12;
|
||||
}
|
||||
} else {
|
||||
// the pair by even register (first)
|
||||
if (first[0] == 'r') {
|
||||
snum = atoi(first+1);
|
||||
int snum = atoi(first+1);
|
||||
if (snum >= 0 && snum <= 30) {
|
||||
res = snum / 2;
|
||||
}
|
||||
|
@ -80,8 +80,8 @@ typedef struct _formattingOptions formattingOptions;
|
||||
|
||||
|
||||
/* Prints a disassembled instruction, formatted with options set in the formattingOptions structure. */
|
||||
int printDisassembledInstruction(RAsm *, avrDisassembleContext *context, char *out, const disassembledInstruction dInstruction, formattingOptions fOptions);
|
||||
int analPrintDisassembledInstruction(RAnal *a, avrDisassembleContext *context, char *out, const disassembledInstruction dInstruction, formattingOptions fOptions);
|
||||
int printDisassembledInstruction(RAsm *, avrDisassembleContext *context, char *out, int out_len, const disassembledInstruction dInstruction, formattingOptions fOptions);
|
||||
int analPrintDisassembledInstruction(RAnal *a, avrDisassembleContext *context, char *out, int out_len, const disassembledInstruction dInstruction, formattingOptions fOptions);
|
||||
int parse_registerpair(const char *operand);
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* radare - LGPL - Copyright 2010-2018 - pancake, dark_k3y */
|
||||
/* radare - LGPL - Copyright 2010-2021 - pancake, dark_k3y */
|
||||
/* AVR assembler realization by Alexander Bolshev aka @dark_k3y, LGPL -- 2015,
|
||||
heavily based (and using!) on disassemble module */
|
||||
|
||||
@ -22,21 +22,22 @@
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
char buf_asm[32] = {0};
|
||||
op->size = avr_decode (a, buf_asm, a->pc, buf, len);
|
||||
int ret = avr_decode (a, buf_asm, sizeof (buf_asm), a->pc, buf, len);
|
||||
if (*buf_asm == '.') {
|
||||
*buf_asm = 0;
|
||||
}
|
||||
if (op->size >= 0) {
|
||||
r_strbuf_set (&op->buf_asm, buf_asm);
|
||||
} else{
|
||||
r_strbuf_set (&op->buf_asm, "invalid");
|
||||
if (ret > 1) {
|
||||
op->size = ret;
|
||||
} else {
|
||||
op->size = 2;
|
||||
}
|
||||
return op->size;
|
||||
const char *arg = (ret > 1)? buf_asm: "invalid";
|
||||
r_strbuf_set (&op->buf_asm, arg);
|
||||
return R_MAX (2, op->size);
|
||||
}
|
||||
|
||||
static int assemble(RAsm *a, RAsmOp *ao, const char *str) {
|
||||
size_t size = avr_encode(a, ao, str);
|
||||
return size;
|
||||
return avr_encode (a, ao, str);
|
||||
}
|
||||
|
||||
// AVR assembler realization ends
|
||||
|
@ -66,4 +66,4 @@ ad "brlt 0xc" 0cf0 8
|
||||
ad "brhs 0xe" 0df0 0xa
|
||||
ad "brts 0x10" 0ef0 0xc
|
||||
ad "brie 0x12" 0ff0 0xe
|
||||
d "invalid" ffff 2
|
||||
d "invalid" ffff 2
|
||||
|
Loading…
Reference in New Issue
Block a user