Implement adrp instruction for arm64

This commit is contained in:
pancake 2017-08-01 04:35:14 +02:00
parent 94df0f1b44
commit 6d953c3b33
3 changed files with 125 additions and 99 deletions

View File

@ -360,6 +360,37 @@ static ut32 orr(ArmOp *op, int addr) {
return data;
}
static ut32 adrp(ArmOp *op, ut64 addr, ut32 k) { //, int reg, ut64 dst) {
ut64 at = 0LL;
ut32 data = k;
if (op->operands[0].type == ARM_GPR) {
data += ((op->operands[0].reg & 0xff) << 24);
} else {
eprintf ("Usage: adrp x0, addr\n");
return UT32_MAX;
}
if (op->operands[1].type == ARM_CONSTANT) {
// XXX what about negative values?
at = op->operands[1].immediate - addr;
at /= 4;
} else {
eprintf ("Usage: adrp, x0, addr\n");
return UT32_MAX;
}
ut8 b0 = at;
ut8 b1 = (at >> 3) & 0xff;
ut8 b2 = (at >> (8 + 7)) & 0xff;
#if 0
data += b0 << 29;
data += b1 << 16;
data += b2 << 24;
#endif
data += b0 << 16;
data += b1 << 8;
return data;
}
static ut32 adr(ArmOp *op, int addr) {
ut32 data = UT32_MAX;
ut64 at = 0LL;
@ -430,113 +461,90 @@ static bool parseOperands(char* str, ArmOp *op) {
return false;
}
while (token[0] != '\0') {
while (token) {
char *next = strchr (token, ',');
if (next) {
*next++ = 0;
}
op->operands[operand].type = ARM_NOTYPE;
op->operands[operand].reg_type = ARM_UNDEFINED;
switch (token[0]) {
case ' ':
token ++;
continue;
break;
case 'x':
x = strchr (token, ',');
if (x) {
x[0] = '\0';
}
op->operands_count ++;
op->operands[operand].type = ARM_GPR;
op->operands[operand].reg_type = ARM_REG64;
op->operands[operand].reg = r_num_math (NULL, token + 1);
case ' ':
token ++;
continue;
break;
case 'w':
x = strchr (token, ',');
if (x) {
x[0] = '\0';
}
op->operands_count ++;
op->operands[operand].type = ARM_GPR;
op->operands[operand].reg_type = ARM_REG32;
op->operands[operand].reg = r_num_math (NULL, token + 1);
case 'x':
x = strchr (token, ',');
if (x) {
x[0] = '\0';
}
op->operands_count ++;
op->operands[operand].type = ARM_GPR;
op->operands[operand].reg_type = ARM_REG64;
op->operands[operand].reg = r_num_math (NULL, token + 1);
break;
case 'v':
x = strchr (token, ',');
if (x) {
x[0] = '\0';
}
op->operands_count ++;
op->operands[operand].type = ARM_FP;
op->operands[operand].reg = r_num_math (NULL, token + 1);
case 'w':
op->operands_count ++;
op->operands[operand].type = ARM_GPR;
op->operands[operand].reg_type = ARM_REG32;
op->operands[operand].reg = r_num_math (NULL, token + 1);
break;
case 's':
case 'S':
x = strchr (token, ',');
if (x) {
x[0] = '\0';
}
if (token[1] == 'P' || token [1] == 'p') {
int i;
for (i = 0; msr_const[i].name; i++) {
if (!strncasecmp (token, msr_const[i].name, strlen (msr_const[i].name))) {
op->operands[operand].sp_val = msr_const[i].val;
break;
}
case 'v':
op->operands_count ++;
op->operands[operand].type = ARM_FP;
op->operands[operand].reg = r_num_math (NULL, token + 1);
break;
case 's':
case 'S':
if (token[1] == 'P' || token [1] == 'p') {
int i;
for (i = 0; msr_const[i].name; i++) {
if (!strncasecmp (token, msr_const[i].name, strlen (msr_const[i].name))) {
op->operands[operand].sp_val = msr_const[i].val;
break;
}
op->operands_count ++;
op->operands[operand].type = ARM_GPR;
op->operands[operand].reg_type = ARM_SP | ARM_REG64;
op->operands[operand].reg = r_num_math (NULL, token + 1);
break;
}
mem_opt = get_mem_option (token);
if (mem_opt != -1) {
op->operands_count ++;
op->operands[operand].type = ARM_MEM_OPT;
op->operands[operand].mem_option = mem_opt;
}
break;
case 'L':
case 'l':
case 'I':
case 'i':
case 'N':
case 'n':
case 'O':
case 'o':
case 'p':
case 'P':
x = strchr (token, ',');
if (x) {
x[0] = '\0';
}
mem_opt = get_mem_option (token);
if (mem_opt != -1) {
op->operands_count ++;
op->operands[operand].type = ARM_MEM_OPT;
op->operands[operand].mem_option = mem_opt;
}
break;
case '-':
op->operands[operand].sign = -1;
default:
x = strchr (token, ',');
if (x) {
x[0] = '\0';
}
op->operands_count ++;
op->operands[operand].type = ARM_CONSTANT;
op->operands[operand].immediate = r_num_math (NULL, token);
imm_count++;
op->operands[operand].type = ARM_GPR;
op->operands[operand].reg_type = ARM_SP | ARM_REG64;
op->operands[operand].reg = r_num_math (NULL, token + 1);
break;
}
mem_opt = get_mem_option (token);
if (mem_opt != -1) {
op->operands_count ++;
op->operands[operand].type = ARM_MEM_OPT;
op->operands[operand].mem_option = mem_opt;
}
break;
case 'L':
case 'l':
case 'I':
case 'i':
case 'N':
case 'n':
case 'O':
case 'o':
case 'p':
case 'P':
mem_opt = get_mem_option (token);
if (mem_opt != -1) {
op->operands_count ++;
op->operands[operand].type = ARM_MEM_OPT;
op->operands[operand].mem_option = mem_opt;
}
break;
case '-':
op->operands[operand].sign = -1;
// falthru
default:
op->operands_count ++;
op->operands[operand].type = ARM_CONSTANT;
op->operands[operand].immediate = r_num_math (NULL, token);
imm_count++;
break;
}
if (x && x[0] == '\0') {
free (t);
return true;
}
if (!x) {
break;
}
token = ++x;
token = next;
operand ++;
if (operand > MAX_OPERANDS) {
free (t);
@ -583,6 +591,10 @@ bool arm64ass(const char *str, ut64 addr, ut32 *op) {
*op = adr (&ops, addr);
return *op != -1;
}
if (!strncmp (str, "adrp x", 6)) {
*op = adrp (&ops, addr, 0x000000d0);
return *op != -1;
}
if (!strcmp (str, "nop")) {
*op = 0x1f2003d5;
return *op != -1;

View File

@ -32,11 +32,12 @@ R_API RBuffer *r_buf_new_with_pointers(const ut8 *bytes, ut64 len);
R_API RBuffer *r_buf_new_with_buf(RBuffer *b);
R_API RBuffer *r_buf_new_file(const char *file, bool newFile);
R_API RBuffer *r_buf_new_slurp(const char *file);
R_API RBuffer *r_buf_new_empty (ut64 len);
R_API RBuffer *r_buf_mmap(const char *file, int flags);
R_API RBuffer *r_buf_new_sparse(void);
R_API bool r_buf_dump (RBuffer *buf, const char *file);
/* methods */
R_API int r_buf_set_bits(RBuffer *b, int bitoff, int bitsize, ut64 value);
R_API bool r_buf_set_bits(RBuffer *b, ut64 at, const ut8* buf, int bitoff, int count);
R_API int r_buf_set_bytes(RBuffer *b, const ut8 *buf, ut64 length);
R_API int r_buf_set_bytes_steal(RBuffer *b, const ut8 *buf, ut64 length);
R_API int r_buf_append_string(RBuffer *b, const char *str);

View File

@ -131,6 +131,16 @@ R_API RBuffer *r_buf_new_with_pointers (const ut8 *bytes, ut64 len) {
return b;
}
R_API RBuffer *r_buf_new_empty (ut64 len) {
RBuffer *b = r_buf_new ();
b->buf = calloc (len, 1);
if (!b->buf) {
return NULL;
}
b->length = len;
return b;
}
R_API RBuffer *r_buf_new_with_bytes (const ut8 *bytes, ut64 len) {
RBuffer *b = r_buf_new ();
if (b && bytes && (len > 0 && len != UT64_MAX)) {
@ -275,7 +285,8 @@ R_API int r_buf_seek (RBuffer *b, st64 addr, int whence) {
return (int)b->cur;
}
R_API int r_buf_set_bits(RBuffer *b, int bitoff, int bitsize, ut64 value) {
R_API bool r_buf_set_bits(RBuffer *b, ut64 at, const ut8* buf, int bitoff, int count) {
r_mem_copybits_delta (b->buf, at * 8, buf, bitoff, count);
// TODO: implement r_buf_set_bits
// TODO: get the implementation from reg/value.c ?
return false;
@ -585,7 +596,9 @@ static int r_buf_fcpy_at (RBuffer *b, ut64 addr, ut8 *buf, const char *fmt, int
}
R_API ut8 *r_buf_get_at (RBuffer *b, ut64 addr, int *left) {
if (b->empty) return 0;
if (b->empty) {
return 0;
}
if (b->fd != -1) {
eprintf ("r_buf_get_at not supported for r_buf_new_file\n");
return 0;