Fix indent issues, pass out buffer size and fix disasm return value

This commit is contained in:
pancake 2021-12-09 01:14:17 +01:00 committed by pancake
parent 2f950f5ebe
commit 49f40816d3
9 changed files with 196 additions and 234 deletions

View File

@ -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"

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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]) {

View File

@ -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 */

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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