]>
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: | |
6aea44fc | 42 | virtual void ProcessOutput(const Instruction *instr) { |
999b53ec CF |
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]; | |
8d298bee PM |
70 | uint32_t instrval; |
71 | const Instruction *instr; | |
999b53ec CF |
72 | int status; |
73 | ||
74 | status = info->read_memory_func(addr, bytes, INSN_SIZE, info); | |
75 | if (status != 0) { | |
76 | info->memory_error_func(status, addr, info); | |
77 | return -1; | |
78 | } | |
79 | ||
80 | if (!vixl_is_initialized()) { | |
81 | vixl_init(info->stream); | |
82 | } | |
83 | ||
8d298bee PM |
84 | instrval = bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24; |
85 | instr = reinterpret_cast<const Instruction *>(&instrval); | |
86 | vixl_disasm->MapCodeAddress(addr, instr); | |
87 | vixl_decoder->Decode(instr); | |
999b53ec CF |
88 | |
89 | return INSN_SIZE; | |
90 | } |