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