• 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 "../globals-vixl.h"
31 #include "../utils-vixl.h"
32 
33 #include "cpu-features-auditor-aarch64.h"
34 #include "decoder-aarch64.h"
35 #include "instructions-aarch64.h"
36 #include "operands-aarch64.h"
37 
38 namespace vixl {
39 namespace aarch64 {
40 
41 class Disassembler : public DecoderVisitor {
42  public:
43   Disassembler();
44   Disassembler(char* text_buffer, int buffer_size);
45   virtual ~Disassembler();
46   char* GetOutput();
47 
48 // Declare all Visitor functions.
49 #define DECLARE(A) \
50   virtual void Visit##A(const Instruction* instr) VIXL_OVERRIDE;
51   VISITOR_LIST(DECLARE)
52 #undef DECLARE
53 
54  protected:
55   virtual void ProcessOutput(const Instruction* instr);
56 
57   // Default output functions. The functions below implement a default way of
58   // printing elements in the disassembly. A sub-class can override these to
59   // customize the disassembly output.
60 
61   // Prints the name of a register.
62   // TODO: This currently doesn't allow renaming of V registers.
63   virtual void AppendRegisterNameToOutput(const Instruction* instr,
64                                           const CPURegister& reg);
65 
66   // Prints a PC-relative offset. This is used for example when disassembling
67   // branches to immediate offsets.
68   virtual void AppendPCRelativeOffsetToOutput(const Instruction* instr,
69                                               int64_t offset);
70 
71   // Prints an address, in the general case. It can be code or data. This is
72   // used for example to print the target address of an ADR instruction.
73   virtual void AppendCodeRelativeAddressToOutput(const Instruction* instr,
74                                                  const void* addr);
75 
76   // Prints the address of some code.
77   // This is used for example to print the target address of a branch to an
78   // immediate offset.
79   // A sub-class can for example override this method to lookup the address and
80   // print an appropriate name.
81   virtual void AppendCodeRelativeCodeAddressToOutput(const Instruction* instr,
82                                                      const void* addr);
83 
84   // Prints the address of some data.
85   // This is used for example to print the source address of a load literal
86   // instruction.
87   virtual void AppendCodeRelativeDataAddressToOutput(const Instruction* instr,
88                                                      const void* addr);
89 
90   // Same as the above, but for addresses that are not relative to the code
91   // buffer. They are currently not used by VIXL.
92   virtual void AppendAddressToOutput(const Instruction* instr,
93                                      const void* addr);
94   virtual void AppendCodeAddressToOutput(const Instruction* instr,
95                                          const void* addr);
96   virtual void AppendDataAddressToOutput(const Instruction* instr,
97                                          const void* addr);
98 
99  public:
100   // Get/Set the offset that should be added to code addresses when printing
101   // code-relative addresses in the AppendCodeRelative<Type>AddressToOutput()
102   // helpers.
103   // Below is an example of how a branch immediate instruction in memory at
104   // address 0xb010200 would disassemble with different offsets.
105   // Base address | Disassembly
106   //          0x0 | 0xb010200:  b #+0xcc  (addr 0xb0102cc)
107   //      0x10000 | 0xb000200:  b #+0xcc  (addr 0xb0002cc)
108   //    0xb010200 |       0x0:  b #+0xcc  (addr 0xcc)
109   void MapCodeAddress(int64_t base_address, const Instruction* instr_address);
110   int64_t CodeRelativeAddress(const void* instr);
111 
112  private:
113   void Format(const Instruction* instr,
114               const char* mnemonic,
115               const char* format);
116   void Substitute(const Instruction* instr, const char* string);
117   int SubstituteField(const Instruction* instr, const char* format);
118   int SubstituteRegisterField(const Instruction* instr, const char* format);
119   int SubstituteImmediateField(const Instruction* instr, const char* format);
120   int SubstituteLiteralField(const Instruction* instr, const char* format);
121   int SubstituteBitfieldImmediateField(const Instruction* instr,
122                                        const char* format);
123   int SubstituteShiftField(const Instruction* instr, const char* format);
124   int SubstituteExtendField(const Instruction* instr, const char* format);
125   int SubstituteConditionField(const Instruction* instr, const char* format);
126   int SubstitutePCRelAddressField(const Instruction* instr, const char* format);
127   int SubstituteBranchTargetField(const Instruction* instr, const char* format);
128   int SubstituteLSRegOffsetField(const Instruction* instr, const char* format);
129   int SubstitutePrefetchField(const Instruction* instr, const char* format);
130   int SubstituteBarrierField(const Instruction* instr, const char* format);
131   int SubstituteSysOpField(const Instruction* instr, const char* format);
132   int SubstituteCrField(const Instruction* instr, const char* format);
RdIsZROrSP(const Instruction * instr)133   bool RdIsZROrSP(const Instruction* instr) const {
134     return (instr->GetRd() == kZeroRegCode);
135   }
136 
RnIsZROrSP(const Instruction * instr)137   bool RnIsZROrSP(const Instruction* instr) const {
138     return (instr->GetRn() == kZeroRegCode);
139   }
140 
RmIsZROrSP(const Instruction * instr)141   bool RmIsZROrSP(const Instruction* instr) const {
142     return (instr->GetRm() == kZeroRegCode);
143   }
144 
RaIsZROrSP(const Instruction * instr)145   bool RaIsZROrSP(const Instruction* instr) const {
146     return (instr->GetRa() == kZeroRegCode);
147   }
148 
149   bool IsMovzMovnImm(unsigned reg_size, uint64_t value);
150 
code_address_offset()151   int64_t code_address_offset() const { return code_address_offset_; }
152 
153  protected:
154   void ResetOutput();
155   void AppendToOutput(const char* string, ...) PRINTF_CHECK(2, 3);
156 
set_code_address_offset(int64_t code_address_offset)157   void set_code_address_offset(int64_t code_address_offset) {
158     code_address_offset_ = code_address_offset;
159   }
160 
161   char* buffer_;
162   uint32_t buffer_pos_;
163   uint32_t buffer_size_;
164   bool own_buffer_;
165 
166   int64_t code_address_offset_;
167 };
168 
169 
170 class PrintDisassembler : public Disassembler {
171  public:
PrintDisassembler(FILE * stream)172   explicit PrintDisassembler(FILE* stream)
173       : cpu_features_auditor_(NULL),
174         cpu_features_prefix_("// Needs: "),
175         cpu_features_suffix_(""),
176         stream_(stream) {}
177 
178   // Convenience helpers for quick disassembly, without having to manually
179   // create a decoder.
180   void DisassembleBuffer(const Instruction* start, uint64_t size);
181   void DisassembleBuffer(const Instruction* start, const Instruction* end);
182   void Disassemble(const Instruction* instr);
183 
184   // If a CPUFeaturesAuditor is specified, it will be used to annotate
185   // disassembly. The CPUFeaturesAuditor is expected to visit the instructions
186   // _before_ the disassembler, such that the CPUFeatures information is
187   // available when the disassembler is called.
RegisterCPUFeaturesAuditor(CPUFeaturesAuditor * auditor)188   void RegisterCPUFeaturesAuditor(CPUFeaturesAuditor* auditor) {
189     cpu_features_auditor_ = auditor;
190   }
191 
192   // Set the prefix to appear before the CPU features annotations.
SetCPUFeaturesPrefix(const char * prefix)193   void SetCPUFeaturesPrefix(const char* prefix) {
194     VIXL_ASSERT(prefix != NULL);
195     cpu_features_prefix_ = prefix;
196   }
197 
198   // Set the suffix to appear after the CPU features annotations.
SetCPUFeaturesSuffix(const char * suffix)199   void SetCPUFeaturesSuffix(const char* suffix) {
200     VIXL_ASSERT(suffix != NULL);
201     cpu_features_suffix_ = suffix;
202   }
203 
204  protected:
205   virtual void ProcessOutput(const Instruction* instr) VIXL_OVERRIDE;
206 
207   CPUFeaturesAuditor* cpu_features_auditor_;
208   const char* cpu_features_prefix_;
209   const char* cpu_features_suffix_;
210 
211  private:
212   FILE* stream_;
213 };
214 }  // namespace aarch64
215 }  // namespace vixl
216 
217 #endif  // VIXL_AARCH64_DISASM_AARCH64_H
218