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