]>
Commit | Line | Data |
---|---|---|
999b53ec CF |
1 | /* |
2 | * ARM A64 disassembly output wrapper to libvixl | |
3 | * Copyright (c) 2013 Linaro Limited | |
4 | * Written by Claudio Fontana | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation, either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | #include "a64/disasm-a64.h" | |
21 | ||
22 | extern "C" { | |
23 | #include "disas/bfd.h" | |
24 | } | |
25 | ||
26 | using namespace vixl; | |
27 | ||
28 | static Decoder *vixl_decoder = NULL; | |
29 | static Disassembler *vixl_disasm = NULL; | |
30 | ||
31 | /* We don't use libvixl's PrintDisassembler because its output | |
32 | * is a little unhelpful (trailing newlines, for example). | |
33 | * Instead we use our own very similar variant so we have | |
34 | * control over the format. | |
35 | */ | |
36 | class QEMUDisassembler : public Disassembler { | |
37 | public: | |
38 | explicit QEMUDisassembler(FILE *stream) : stream_(stream) { } | |
39 | ~QEMUDisassembler() { } | |
40 | ||
41 | protected: | |
42 | void ProcessOutput(Instruction *instr) { | |
43 | fprintf(stream_, "%08" PRIx32 " %s", | |
44 | instr->InstructionBits(), GetOutput()); | |
45 | } | |
46 | ||
47 | private: | |
48 | FILE *stream_; | |
49 | }; | |
50 | ||
51 | static int vixl_is_initialized(void) | |
52 | { | |
53 | return vixl_decoder != NULL; | |
54 | } | |
55 | ||
56 | static void vixl_init(FILE *f) { | |
57 | vixl_decoder = new Decoder(); | |
58 | vixl_disasm = new QEMUDisassembler(f); | |
59 | vixl_decoder->AppendVisitor(vixl_disasm); | |
60 | } | |
61 | ||
62 | #define INSN_SIZE 4 | |
63 | ||
64 | /* Disassemble ARM A64 instruction. This is our only entry | |
65 | * point from QEMU's C code. | |
66 | */ | |
67 | int print_insn_arm_a64(uint64_t addr, disassemble_info *info) | |
68 | { | |
69 | uint8_t bytes[INSN_SIZE]; | |
70 | uint32_t instr; | |
71 | int status; | |
72 | ||
73 | status = info->read_memory_func(addr, bytes, INSN_SIZE, info); | |
74 | if (status != 0) { | |
75 | info->memory_error_func(status, addr, info); | |
76 | return -1; | |
77 | } | |
78 | ||
79 | if (!vixl_is_initialized()) { | |
80 | vixl_init(info->stream); | |
81 | } | |
82 | ||
83 | instr = bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24; | |
84 | vixl_decoder->Decode(reinterpret_cast<Instruction*>(&instr)); | |
85 | ||
86 | return INSN_SIZE; | |
87 | } |