|
15 | 15 |
|
16 | 16 | static TraceState state = {0}; |
17 | 17 |
|
| 18 | +static void mval_to_buf(qemu_plugin_mem_value *val, uint8_t *buf) { |
| 19 | + size_t mem_val_size = 0; |
| 20 | + switch (val->type) { |
| 21 | + case QEMU_PLUGIN_MEM_VALUE_U8: |
| 22 | + buf[0] = val->data.u8; |
| 23 | + mem_val_size = 1; |
| 24 | + break; |
| 25 | + case QEMU_PLUGIN_MEM_VALUE_U16: |
| 26 | + buf[0] = (uint8_t)val->data.u16; |
| 27 | + buf[1] = (uint8_t)(val->data.u16 >> 8); |
| 28 | + mem_val_size = 2; |
| 29 | + break; |
| 30 | + case QEMU_PLUGIN_MEM_VALUE_U32: |
| 31 | + buf[0] = (uint8_t)val->data.u32; |
| 32 | + buf[1] = (uint8_t)(val->data.u32 >> 8); |
| 33 | + buf[2] = (uint8_t)(val->data.u32 >> 16); |
| 34 | + buf[3] = (uint8_t)(val->data.u32 >> 24); |
| 35 | + mem_val_size = 4; |
| 36 | + break; |
| 37 | + case QEMU_PLUGIN_MEM_VALUE_U64: |
| 38 | + for (size_t i = 0; i < 8; ++i) { |
| 39 | + buf[i] = (uint8_t)(val->data.u64 >> (i * 8)); |
| 40 | + } |
| 41 | + mem_val_size = 8; |
| 42 | + break; |
| 43 | + case QEMU_PLUGIN_MEM_VALUE_U128: |
| 44 | + for (size_t i = 0; i < 8; ++i) { |
| 45 | + buf[i] = (uint8_t)(val->data.u128.low >> (i * 8)); |
| 46 | + } |
| 47 | + for (size_t i = 0; i < 8; ++i) { |
| 48 | + buf[i + 8] = (uint8_t)(val->data.u128.high >> (i * 8)); |
| 49 | + } |
| 50 | + mem_val_size = 16; |
| 51 | + break; |
| 52 | + default: |
| 53 | + g_assert(false); |
| 54 | + } |
| 55 | + swap_to_le(buf, mem_val_size, state.is_big_endian); |
| 56 | +} |
| 57 | + |
| 58 | +static size_t mval_type_to_int(enum qemu_plugin_mem_value_type type) { |
| 59 | + switch (type) { |
| 60 | + case QEMU_PLUGIN_MEM_VALUE_U8: |
| 61 | + return 8; |
| 62 | + case QEMU_PLUGIN_MEM_VALUE_U16: |
| 63 | + return 16; |
| 64 | + case QEMU_PLUGIN_MEM_VALUE_U32: |
| 65 | + return 32; |
| 66 | + case QEMU_PLUGIN_MEM_VALUE_U64: |
| 67 | + return 64; |
| 68 | + case QEMU_PLUGIN_MEM_VALUE_U128: |
| 69 | + return 128; |
| 70 | + default: |
| 71 | + g_assert(false); |
| 72 | + } |
| 73 | + return 0; |
| 74 | +} |
| 75 | + |
18 | 76 | static void add_mem_op(VCPU *vcpu, unsigned int vcpu_index, FrameBuffer *fbuf, |
19 | 77 | uint64_t vaddr, qemu_plugin_mem_value *mval, |
20 | 78 | bool is_store) { |
21 | | - if (!frame_buffer_append_mem_info(fbuf, vaddr, mval, is_store)) { |
| 79 | + size_t mval_bits = mval_type_to_int(mval->type); |
| 80 | + uint8_t *buf = g_malloc(mval_bits / 8); |
| 81 | + mval_to_buf(mval, buf); |
| 82 | + if (!frame_buffer_append_mem_info(fbuf, vaddr, buf, mval_bits, is_store)) { |
22 | 83 | qemu_plugin_outs("Failed to append memory info\n"); |
23 | 84 | } |
24 | 85 | return; |
@@ -54,7 +115,7 @@ static void add_post_reg_state(VCPU *vcpu, unsigned int vcpu_index, |
54 | 115 | &g_array_index(current_regs, qemu_plugin_reg_descriptor, i); |
55 | 116 | int s = qemu_plugin_read_register(reg->handle, rdata); |
56 | 117 | assert(s == prev_reg->content->len); |
57 | | - swap_to_le(rdata->data, s, HOST_BIG_ENDIAN); |
| 118 | + swap_to_le(rdata->data, s, state.is_big_endian); |
58 | 119 | if (!memcmp(rdata->data, prev_reg->content->data, s)) { |
59 | 120 | // No change |
60 | 121 | // Flush byte array |
@@ -83,8 +144,9 @@ static void add_pre_reg_state(VCPU *vcpu, unsigned int vcpu_index, |
83 | 144 | g_assert(!strcmp(prev_reg->name, reg->name) && |
84 | 145 | prev_reg->handle == reg->handle); |
85 | 146 | memcpy_le(prev_reg->content->data, rdata->data, prev_reg->content->len, |
86 | | - HOST_BIG_ENDIAN); |
87 | | - frame_buffer_append_reg_info(fbuf, reg->name, rdata, s, OperandRead); |
| 147 | + state.is_big_endian); |
| 148 | + frame_buffer_append_reg_info(fbuf, reg->name, prev_reg->content, s, |
| 149 | + OperandRead); |
88 | 150 | // Flush byte array |
89 | 151 | g_byte_array_set_size(rdata, 0); |
90 | 152 | } |
@@ -342,6 +404,14 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, |
342 | 404 | qemu_plugin_outs("Pass it with 'out=<output_file>'.\n\n"); |
343 | 405 | exit(1); |
344 | 406 | } |
| 407 | + char *endianess = get_argv_val(argv, argc, "endianess"); |
| 408 | + if (!endianess || (strcmp(endianess, "b") && strcmp(endianess, "l"))) { |
| 409 | + qemu_plugin_outs("'endianess' argument is missing or is not 'b' or 'l'.\n"); |
| 410 | + qemu_plugin_outs("This is required until QEMU plugins get a richer API.\n"); |
| 411 | + qemu_plugin_outs("Pass it with 'endianess=[b/l]'.\n\n"); |
| 412 | + exit(1); |
| 413 | + } |
| 414 | + state.is_big_endian = endianess[0] == 'b'; |
345 | 415 |
|
346 | 416 | state.target_name = g_strdup(info->target_name); |
347 | 417 | state.frame_buffer = g_ptr_array_new(); |
|
0 commit comments