• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 //   * Redistributions of source code must retain the above copyright notice,
8 //     this list of conditions and the following disclaimer.
9 //   * Redistributions in binary form must reproduce the above copyright notice,
10 //     this list of conditions and the following disclaimer in the documentation
11 //     and/or other materials provided with the distribution.
12 //   * Neither the name of ARM Limited nor the names of its contributors may be
13 //     used to endorse or promote products derived from this software without
14 //     specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #ifndef VIXL_AARCH64_DISASM_AARCH64_H
28 #define VIXL_AARCH64_DISASM_AARCH64_H
29 
30 #include <functional>
31 #include <unordered_map>
32 #include <utility>
33 
34 #include "../globals-vixl.h"
35 #include "../utils-vixl.h"
36 
37 #include "cpu-features-auditor-aarch64.h"
38 #include "decoder-aarch64.h"
39 #include "decoder-visitor-map-aarch64.h"
40 #include "instructions-aarch64.h"
41 #include "operands-aarch64.h"
42 
43 namespace vixl {
44 namespace aarch64 {
45 
46 class Disassembler : public DecoderVisitor {
47  public:
48   Disassembler();
49   Disassembler(char* text_buffer, int buffer_size);
50   virtual ~Disassembler();
51   char* GetOutput();
52 
53   // Declare all Visitor functions.
54   virtual void Visit(Metadata* metadata,
55                      const Instruction* instr) VIXL_OVERRIDE;
56 
57  protected:
58   virtual void ProcessOutput(const Instruction* instr);
59 
60   // Default output functions. The functions below implement a default way of
61   // printing elements in the disassembly. A sub-class can override these to
62   // customize the disassembly output.
63 
64   // Prints the name of a register.
65   // TODO: This currently doesn't allow renaming of V registers.
66   virtual void AppendRegisterNameToOutput(const Instruction* instr,
67                                           const CPURegister& reg);
68 
69   // Prints a PC-relative offset. This is used for example when disassembling
70   // branches to immediate offsets.
71   virtual void AppendPCRelativeOffsetToOutput(const Instruction* instr,
72                                               int64_t offset);
73 
74   // Prints an address, in the general case. It can be code or data. This is
75   // used for example to print the target address of an ADR instruction.
76   virtual void AppendCodeRelativeAddressToOutput(const Instruction* instr,
77                                                  const void* addr);
78 
79   // Prints the address of some code.
80   // This is used for example to print the target address of a branch to an
81   // immediate offset.
82   // A sub-class can for example override this method to lookup the address and
83   // print an appropriate name.
84   virtual void AppendCodeRelativeCodeAddressToOutput(const Instruction* instr,
85                                                      const void* addr);
86 
87   // Prints the address of some data.
88   // This is used for example to print the source address of a load literal
89   // instruction.
90   virtual void AppendCodeRelativeDataAddressToOutput(const Instruction* instr,
91                                                      const void* addr);
92 
93   // Same as the above, but for addresses that are not relative to the code
94   // buffer. They are currently not used by VIXL.
95   virtual void AppendAddressToOutput(const Instruction* instr,
96                                      const void* addr);
97   virtual void AppendCodeAddressToOutput(const Instruction* instr,
98                                          const void* addr);
99   virtual void AppendDataAddressToOutput(const Instruction* instr,
100                                          const void* addr);
101 
102  public:
103   // Get/Set the offset that should be added to code addresses when printing
104   // code-relative addresses in the AppendCodeRelative<Type>AddressToOutput()
105   // helpers.
106   // Below is an example of how a branch immediate instruction in memory at
107   // address 0xb010200 would disassemble with different offsets.
108   // Base address | Disassembly
109   //          0x0 | 0xb010200:  b #+0xcc  (addr 0xb0102cc)
110   //      0x10000 | 0xb000200:  b #+0xcc  (addr 0xb0002cc)
111   //    0xb010200 |       0x0:  b #+0xcc  (addr 0xcc)
112   void MapCodeAddress(int64_t base_address, const Instruction* instr_address);
113   int64_t CodeRelativeAddress(const void* instr);
114 
115  private:
116 #define DECLARE(A) virtual void Visit##A(const Instruction* instr);
117   VISITOR_LIST(DECLARE)
118 #undef DECLARE
119 
120   using FormToVisitorFnMap = std::unordered_map<
121       uint32_t,
122       std::function<void(Disassembler*, const Instruction*)>>;
123   static const FormToVisitorFnMap* GetFormToVisitorFnMap();
124 
125   std::string mnemonic_;
126   uint32_t form_hash_;
127 
SetMnemonicFromForm(const std::string & form)128   void SetMnemonicFromForm(const std::string& form) {
129     if (form != "unallocated") {
130       VIXL_ASSERT(form.find_first_of('_') != std::string::npos);
131       mnemonic_ = form.substr(0, form.find_first_of('_'));
132     }
133   }
134 
135   void Disassemble_PdT_PgZ_ZnT_ZmT(const Instruction* instr);
136   void Disassemble_ZdB_Zn1B_Zn2B_imm(const Instruction* instr);
137   void Disassemble_ZdB_ZnB_ZmB(const Instruction* instr);
138   void Disassemble_ZdD_PgM_ZnS(const Instruction* instr);
139   void Disassemble_ZdD_ZnD_ZmD(const Instruction* instr);
140   void Disassemble_ZdD_ZnD_ZmD_imm(const Instruction* instr);
141   void Disassemble_ZdD_ZnS_ZmS_imm(const Instruction* instr);
142   void Disassemble_ZdH_PgM_ZnS(const Instruction* instr);
143   void Disassemble_ZdH_ZnH_ZmH_imm(const Instruction* instr);
144   void Disassemble_ZdS_PgM_ZnD(const Instruction* instr);
145   void Disassemble_ZdS_PgM_ZnH(const Instruction* instr);
146   void Disassemble_ZdS_PgM_ZnS(const Instruction* instr);
147   void Disassemble_ZdS_ZnH_ZmH_imm(const Instruction* instr);
148   void Disassemble_ZdS_ZnS_ZmS(const Instruction* instr);
149   void Disassemble_ZdS_ZnS_ZmS_imm(const Instruction* instr);
150   void Disassemble_ZdT_PgM_ZnT(const Instruction* instr);
151   void Disassemble_ZdT_PgZ_ZnT_ZmT(const Instruction* instr);
152   void Disassemble_ZdT_Pg_Zn1T_Zn2T(const Instruction* instr);
153   void Disassemble_ZdT_Zn1T_Zn2T_ZmT(const Instruction* instr);
154   void Disassemble_ZdT_ZnT_ZmT(const Instruction* instr);
155   void Disassemble_ZdT_ZnT_ZmTb(const Instruction* instr);
156   void Disassemble_ZdT_ZnTb(const Instruction* instr);
157   void Disassemble_ZdT_ZnTb_ZmTb(const Instruction* instr);
158   void Disassemble_ZdaD_ZnD_ZmD_imm(const Instruction* instr);
159   void Disassemble_ZdaD_ZnH_ZmH_imm_const(const Instruction* instr);
160   void Disassemble_ZdaD_ZnS_ZmS_imm(const Instruction* instr);
161   void Disassemble_ZdaH_ZnH_ZmH_imm(const Instruction* instr);
162   void Disassemble_ZdaH_ZnH_ZmH_imm_const(const Instruction* instr);
163   void Disassemble_ZdaS_ZnB_ZmB_imm_const(const Instruction* instr);
164   void Disassemble_ZdaS_ZnH_ZmH(const Instruction* instr);
165   void Disassemble_ZdaS_ZnH_ZmH_imm(const Instruction* instr);
166   void Disassemble_ZdaS_ZnS_ZmS_imm(const Instruction* instr);
167   void Disassemble_ZdaS_ZnS_ZmS_imm_const(const Instruction* instr);
168   void Disassemble_ZdaT_PgM_ZnTb(const Instruction* instr);
169   void Disassemble_ZdaT_ZnT_ZmT(const Instruction* instr);
170   void Disassemble_ZdaT_ZnT_ZmT_const(const Instruction* instr);
171   void Disassemble_ZdaT_ZnT_const(const Instruction* instr);
172   void Disassemble_ZdaT_ZnTb_ZmTb(const Instruction* instr);
173   void Disassemble_ZdaT_ZnTb_ZmTb_const(const Instruction* instr);
174   void Disassemble_ZdnB_ZdnB(const Instruction* instr);
175   void Disassemble_ZdnB_ZdnB_ZmB(const Instruction* instr);
176   void Disassemble_ZdnS_ZdnS_ZmS(const Instruction* instr);
177   void Disassemble_ZdnT_PgM_ZdnT_ZmT(const Instruction* instr);
178   void Disassemble_ZdnT_PgM_ZdnT_const(const Instruction* instr);
179   void Disassemble_ZdnT_ZdnT_ZmT_const(const Instruction* instr);
180   void Disassemble_ZtD_PgZ_ZnD_Xm(const Instruction* instr);
181   void Disassemble_ZtD_Pg_ZnD_Xm(const Instruction* instr);
182   void Disassemble_ZtS_PgZ_ZnS_Xm(const Instruction* instr);
183   void Disassemble_ZtS_Pg_ZnS_Xm(const Instruction* instr);
184   void Disassemble_ZdaS_ZnB_ZmB(const Instruction* instr);
185   void Disassemble_Vd4S_Vn16B_Vm16B(const Instruction* instr);
186 
187   void DisassembleSVEShiftLeftImm(const Instruction* instr);
188   void DisassembleSVEShiftRightImm(const Instruction* instr);
189   void DisassembleSVEAddSubCarry(const Instruction* instr);
190   void DisassembleSVEAddSubHigh(const Instruction* instr);
191   void DisassembleSVEComplexIntAddition(const Instruction* instr);
192   void DisassembleSVEBitwiseTernary(const Instruction* instr);
193   void DisassembleSVEFlogb(const Instruction* instr);
194   void DisassembleSVEFPPair(const Instruction* instr);
195 
196   void DisassembleNoArgs(const Instruction* instr);
197 
198   void DisassembleNEONMulByElementLong(const Instruction* instr);
199   void DisassembleNEONDotProdByElement(const Instruction* instr);
200   void DisassembleNEONFPMulByElement(const Instruction* instr);
201   void DisassembleNEONHalfFPMulByElement(const Instruction* instr);
202   void DisassembleNEONFPMulByElementLong(const Instruction* instr);
203   void DisassembleNEONComplexMulByElement(const Instruction* instr);
204   void DisassembleNEON2RegLogical(const Instruction* instr);
205   void DisassembleNEON2RegExtract(const Instruction* instr);
206   void DisassembleNEON2RegAddlp(const Instruction* instr);
207   void DisassembleNEON2RegCompare(const Instruction* instr);
208   void DisassembleNEON2RegFPCompare(const Instruction* instr);
209   void DisassembleNEON2RegFPConvert(const Instruction* instr);
210   void DisassembleNEON2RegFP(const Instruction* instr);
211   void DisassembleNEON3SameLogical(const Instruction* instr);
212   void DisassembleNEON3SameFHM(const Instruction* instr);
213   void DisassembleNEON3SameNoD(const Instruction* instr);
214   void DisassembleNEONShiftLeftLongImm(const Instruction* instr);
215   void DisassembleNEONShiftRightImm(const Instruction* instr);
216   void DisassembleNEONShiftRightNarrowImm(const Instruction* instr);
217   void DisassembleNEONScalarSatMulLongIndex(const Instruction* instr);
218   void DisassembleNEONFPScalarMulIndex(const Instruction* instr);
219   void DisassembleNEONFPScalar3Same(const Instruction* instr);
220   void DisassembleNEONScalar3SameOnlyD(const Instruction* instr);
221   void DisassembleNEONFPAcrossLanes(const Instruction* instr);
222   void DisassembleNEONFP16AcrossLanes(const Instruction* instr);
223   void DisassembleNEONScalarShiftImmOnlyD(const Instruction* instr);
224   void DisassembleNEONScalarShiftRightNarrowImm(const Instruction* instr);
225   void DisassembleNEONScalar2RegMiscOnlyD(const Instruction* instr);
226   void DisassembleNEONFPScalar2RegMisc(const Instruction* instr);
227 
228   void Format(const Instruction* instr,
229               const char* mnemonic,
230               const char* format0,
231               const char* format1 = NULL);
232   void FormatWithDecodedMnemonic(const Instruction* instr,
233                                  const char* format0,
234                                  const char* format1 = NULL);
235 
236   void Substitute(const Instruction* instr, const char* string);
237   int SubstituteField(const Instruction* instr, const char* format);
238   int SubstituteRegisterField(const Instruction* instr, const char* format);
239   int SubstitutePredicateRegisterField(const Instruction* instr,
240                                        const char* format);
241   int SubstituteImmediateField(const Instruction* instr, const char* format);
242   int SubstituteLiteralField(const Instruction* instr, const char* format);
243   int SubstituteBitfieldImmediateField(const Instruction* instr,
244                                        const char* format);
245   int SubstituteShiftField(const Instruction* instr, const char* format);
246   int SubstituteExtendField(const Instruction* instr, const char* format);
247   int SubstituteConditionField(const Instruction* instr, const char* format);
248   int SubstitutePCRelAddressField(const Instruction* instr, const char* format);
249   int SubstituteBranchTargetField(const Instruction* instr, const char* format);
250   int SubstituteLSRegOffsetField(const Instruction* instr, const char* format);
251   int SubstitutePrefetchField(const Instruction* instr, const char* format);
252   int SubstituteBarrierField(const Instruction* instr, const char* format);
253   int SubstituteSysOpField(const Instruction* instr, const char* format);
254   int SubstituteCrField(const Instruction* instr, const char* format);
255   int SubstituteIntField(const Instruction* instr, const char* format);
256   int SubstituteSVESize(const Instruction* instr, const char* format);
257   int SubstituteTernary(const Instruction* instr, const char* format);
258 
259   std::pair<unsigned, unsigned> GetRegNumForField(const Instruction* instr,
260                                                   char reg_prefix,
261                                                   const char* field);
262 
RdIsZROrSP(const Instruction * instr)263   bool RdIsZROrSP(const Instruction* instr) const {
264     return (instr->GetRd() == kZeroRegCode);
265   }
266 
RnIsZROrSP(const Instruction * instr)267   bool RnIsZROrSP(const Instruction* instr) const {
268     return (instr->GetRn() == kZeroRegCode);
269   }
270 
RmIsZROrSP(const Instruction * instr)271   bool RmIsZROrSP(const Instruction* instr) const {
272     return (instr->GetRm() == kZeroRegCode);
273   }
274 
RaIsZROrSP(const Instruction * instr)275   bool RaIsZROrSP(const Instruction* instr) const {
276     return (instr->GetRa() == kZeroRegCode);
277   }
278 
279   bool IsMovzMovnImm(unsigned reg_size, uint64_t value);
280 
code_address_offset()281   int64_t code_address_offset() const { return code_address_offset_; }
282 
283  protected:
284   void ResetOutput();
285   void AppendToOutput(const char* string, ...) PRINTF_CHECK(2, 3);
286 
set_code_address_offset(int64_t code_address_offset)287   void set_code_address_offset(int64_t code_address_offset) {
288     code_address_offset_ = code_address_offset;
289   }
290 
291   char* buffer_;
292   uint32_t buffer_pos_;
293   uint32_t buffer_size_;
294   bool own_buffer_;
295 
296   int64_t code_address_offset_;
297 };
298 
299 
300 class PrintDisassembler : public Disassembler {
301  public:
PrintDisassembler(FILE * stream)302   explicit PrintDisassembler(FILE* stream)
303       : cpu_features_auditor_(NULL),
304         cpu_features_prefix_("// Needs: "),
305         cpu_features_suffix_(""),
306         signed_addresses_(false),
307         stream_(stream) {}
308 
309   // Convenience helpers for quick disassembly, without having to manually
310   // create a decoder.
311   void DisassembleBuffer(const Instruction* start, uint64_t size);
312   void DisassembleBuffer(const Instruction* start, const Instruction* end);
313   void Disassemble(const Instruction* instr);
314 
315   // If a CPUFeaturesAuditor is specified, it will be used to annotate
316   // disassembly. The CPUFeaturesAuditor is expected to visit the instructions
317   // _before_ the disassembler, such that the CPUFeatures information is
318   // available when the disassembler is called.
RegisterCPUFeaturesAuditor(CPUFeaturesAuditor * auditor)319   void RegisterCPUFeaturesAuditor(CPUFeaturesAuditor* auditor) {
320     cpu_features_auditor_ = auditor;
321   }
322 
323   // Set the prefix to appear before the CPU features annotations.
SetCPUFeaturesPrefix(const char * prefix)324   void SetCPUFeaturesPrefix(const char* prefix) {
325     VIXL_ASSERT(prefix != NULL);
326     cpu_features_prefix_ = prefix;
327   }
328 
329   // Set the suffix to appear after the CPU features annotations.
SetCPUFeaturesSuffix(const char * suffix)330   void SetCPUFeaturesSuffix(const char* suffix) {
331     VIXL_ASSERT(suffix != NULL);
332     cpu_features_suffix_ = suffix;
333   }
334 
335   // By default, addresses are printed as simple, unsigned 64-bit hex values.
336   //
337   // With `PrintSignedAddresses(true)`:
338   //  - negative addresses are printed as "-0x1234...",
339   //  - positive addresses have a leading space, like " 0x1234...", to maintain
340   //    alignment.
341   //
342   // This is most useful in combination with Disassembler::MapCodeAddress(...).
PrintSignedAddresses(bool s)343   void PrintSignedAddresses(bool s) { signed_addresses_ = s; }
344 
345  protected:
346   virtual void ProcessOutput(const Instruction* instr) VIXL_OVERRIDE;
347 
348   CPUFeaturesAuditor* cpu_features_auditor_;
349   const char* cpu_features_prefix_;
350   const char* cpu_features_suffix_;
351   bool signed_addresses_;
352 
353  private:
354   FILE* stream_;
355 };
356 }  // namespace aarch64
357 }  // namespace vixl
358 
359 #endif  // VIXL_AARCH64_DISASM_AARCH64_H
360