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