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