static int assemble(RAsm *a, RAsmOp *op, const char *buf) { const bool is_thumb = (a->bits == 16); int opsize; ut32 opcode; if (a->bits == 64) { if (!arm64ass (buf, a->pc, &opcode)) { return -1; } } else { opcode = armass_assemble (buf, a->pc, is_thumb); if (a->bits != 32 && a->bits != 16) { eprintf ("Error: ARM assembler only supports 16 or 32 bits\n"); return -1; } } if (opcode == UT32_MAX) { return -1; } if (is_thumb) { const int o = opcode >> 16; opsize = o > 0? 4: 2; //(o&0x80 && ((o&0xe0)==0xe0))? 4: 2; if (opsize == 4) { if (a->big_endian) { r_write_le32 (op->buf, opcode); } else { r_write_be32 (op->buf, opcode); } } else if (opsize == 2) { r_write_be16 (op->buf, opcode & UT16_MAX); } } else {
static void __patch_reloc(RBuffer *buf, ut32 addr_to_patch, ut32 data_offset) { ut8 val[4] = { 0 }; r_write_le32 (val, data_offset); r_buf_write_at (buf, addr_to_patch, (void *) val, sizeof (val)); }
// TODO: SEE: R_API ut64 r_reg_get_value(RReg *reg, RRegItem *item) { .. dupped code? R_API int r_mem_set_num(ut8 *dest, int dest_size, ut64 num) { // LITTLE ENDIAN is the default for streams switch (dest_size) { case 1: r_write_le8 (dest, (ut8) (num & UT8_MAX)); break; case 2: r_write_le16 (dest, (ut16) (num & UT16_MAX)); break; case 4: r_write_le32 (dest, (ut32) (num & UT32_MAX)); break; case 8: r_write_le64 (dest, num); break; default: return false; } return true; }
R_API int r_core_write_op(RCore *core, const char *arg, char op) { int i, j, len, ret = false; char *str = NULL; ut8 *buf; // XXX we can work with config.block instead of dupping it buf = (ut8 *)malloc (core->blocksize); if (!buf) { goto beach; } memcpy (buf, core->block, core->blocksize); if (op!='e') { // fill key buffer either from arg or from clipboard if (arg) { // parse arg for key // r_hex_str2bin() is guaranteed to output maximum half the // input size, or 1 byte if there is just a single nibble. str = (char *)malloc (strlen (arg) / 2 + 1); if (!str) { goto beach; } len = r_hex_str2bin (arg, (ut8 *)str); // Output is invalid if there was just a single nibble, // but in that case, len is negative (-1). if (len <= 0) { eprintf ("Invalid hexpair string\n"); goto beach; } } else { // use clipboard as key len = core->yank_buf->length; if (len <= 0) { eprintf ("Clipboard is empty and no value argument(s) given\n"); goto beach; } str = r_mem_dup (core->yank_buf->buf, len); if (!str) { goto beach; } } } else { len = 0; } // execute the operand if (op=='e') { int wordsize = 1; char *os, *p, *s = strdup (arg); int n = 0, from = 0, to = UT8_MAX, dif = 0, step = 1; os = s; p = strchr (s, ' '); if (p) { *p = 0; from = r_num_math (core->num, s); s = p + 1; } p = strchr (s, ' '); if (p) { *p = 0; to = r_num_math (core->num, s); s = p + 1; } p = strchr (s, ' '); if (p) { *p = 0; step = r_num_math (core->num, s); s = p + 1; wordsize = r_num_math (core->num, s); } else { step = r_num_math (core->num, s); } free (os); eprintf ("from %d to %d step %d size %d\n", from, to, step, wordsize); dif = (to <= from)? UT8_MAX: to - from + 1; if (wordsize == 1) { from %= (UT8_MAX + 1); } if (dif < 1) { dif = UT8_MAX + 1; } if (step < 1) { step = 1; } if (wordsize < 1) { wordsize = 1; } if (wordsize == 1) { for (i = n = 0; i < core->blocksize; i++, n += step) { buf[i] = (ut8)(n % dif) + from; } } else if (wordsize == 2) { ut16 num16 = from; for (i = 0; i < core->blocksize; i += wordsize, num16 += step) { r_write_le16 (buf + i, num16); } } else if (wordsize == 4) { ut32 num32 = from; for (i = 0; i < core->blocksize; i += wordsize, num32 += step) { r_write_le32 (buf + i, num32); } } else if (wordsize == 8) { ut64 num64 = from; for (i = 0; i < core->blocksize; i += wordsize, num64 += step) { r_write_le64 (buf + i, num64); } } else { eprintf ("Invalid word size. Use 1, 2, 4 or 8\n"); } } else if (op=='2' || op=='4') { op -= '0'; // if i < core->blocksize would pass the test but buf[i+3] goes beyond the buffer if (core->blocksize > 3) { for (i=0; i<core->blocksize-3; i+=op) { /* endian swap */ ut8 tmp = buf[i]; buf[i] = buf[i+3]; buf[i+3] = tmp; if (op == 4) { tmp = buf[i + 1]; buf[i + 1] = buf[i + 2]; buf[i + 2] = tmp; } } } } else { for (i=j=0; i<core->blocksize; i++) { switch (op) { case 'x': buf[i] ^= str[j]; break; case 'a': buf[i] += str[j]; break; case 's': buf[i] -= str[j]; break; case 'm': buf[i] *= str[j]; break; case 'w': buf[i] = str[j]; break; case 'd': buf[i] = (str[j])? buf[i] / str[j]: 0; break; case 'r': buf[i] >>= str[j]; break; case 'l': buf[i] <<= str[j]; break; case 'o': buf[i] |= str[j]; break; case 'A': buf[i] &= str[j]; break; } j++; if (j >= len) { j = 0; /* cyclic key */ } } } ret = r_core_write_at (core, core->offset, buf, core->blocksize); beach: free (buf); free (str); return ret; }
R_API bool r_reg_set_value(RReg *reg, RRegItem *item, ut64 value) { int fits_in_arena; ut8 bytes[12]; ut8 *src = bytes; if (!item) { eprintf ("r_reg_set_value: item is NULL\n"); return false; } switch (item->size) { case 80: case 96: // long floating value r_reg_set_longdouble (reg, item, (long double)value); break; case 64: if (reg->big_endian) { r_write_be64 (src, value); } else { r_write_le64 (src, value); } break; case 32: if (reg->big_endian) { r_write_be32 (src, value); } else { r_write_le32 (src, value); } break; case 16: if (reg->big_endian) { r_write_be16 (src, value); } else { r_write_le16 (src, value); } break; case 8: r_write_ble8 (src, (ut8)(value & UT8_MAX)); break; case 1: if (value) { ut8 *buf = reg->regset[item->arena].arena->bytes + (item->offset / 8); int bit = (item->offset % 8); ut8 mask = (1 << bit); buf[0] = (buf[0] & (0xff ^ mask)) | mask; } else { int idx = item->offset / 8; RRegArena *arena = reg->regset[item->arena].arena; if (idx + item->size > arena->size) { eprintf ("RRegSetOverflow %d vs %d\n", idx + item->size, arena->size); return false; } ut8 *buf = arena->bytes + idx; int bit = item->offset % 8; ut8 mask = 0xff ^ (1 << bit); buf[0] = (buf[0] & mask) | 0; } return true; default: eprintf ("r_reg_set_value: Bit size %d not supported\n", item->size); return false; } fits_in_arena = (reg->regset[item->arena].arena->size - BITS2BYTES (item->offset) - BITS2BYTES (item->size)) >= 0; if (src && fits_in_arena) { r_mem_copybits (reg->regset[item->arena].arena->bytes + BITS2BYTES (item->offset), src, item->size); return true; } eprintf ("r_reg_set_value: Cannot set %s to 0x%" PFMT64x "\n", item->name, value); return false; }