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 DisassembleCpy(const Instruction* instr); 188 void DisassembleSet(const Instruction* instr); 189 void DisassembleMinMaxImm(const Instruction* instr); 190 191 void DisassembleSVEShiftLeftImm(const Instruction* instr); 192 void DisassembleSVEShiftRightImm(const Instruction* instr); 193 void DisassembleSVEAddSubCarry(const Instruction* instr); 194 void DisassembleSVEAddSubHigh(const Instruction* instr); 195 void DisassembleSVEComplexIntAddition(const Instruction* instr); 196 void DisassembleSVEBitwiseTernary(const Instruction* instr); 197 void DisassembleSVEFlogb(const Instruction* instr); 198 void DisassembleSVEFPPair(const Instruction* instr); 199 void DisassembleSVEPmull(const Instruction* instr); 200 void DisassembleSVEPmull128(const Instruction* instr); 201 202 void DisassembleNoArgs(const Instruction* instr); 203 204 void DisassembleNEONMulByElementLong(const Instruction* instr); 205 void DisassembleNEONDotProdByElement(const Instruction* instr); 206 void DisassembleNEONFPMulByElement(const Instruction* instr); 207 void DisassembleNEONHalfFPMulByElement(const Instruction* instr); 208 void DisassembleNEONFPMulByElementLong(const Instruction* instr); 209 void DisassembleNEONComplexMulByElement(const Instruction* instr); 210 void DisassembleNEON2RegLogical(const Instruction* instr); 211 void DisassembleNEON2RegExtract(const Instruction* instr); 212 void DisassembleNEON2RegAddlp(const Instruction* instr); 213 void DisassembleNEON2RegCompare(const Instruction* instr); 214 void DisassembleNEON2RegFPCompare(const Instruction* instr); 215 void DisassembleNEON2RegFPConvert(const Instruction* instr); 216 void DisassembleNEON2RegFP(const Instruction* instr); 217 void DisassembleNEON3SameLogical(const Instruction* instr); 218 void DisassembleNEON3SameFHM(const Instruction* instr); 219 void DisassembleNEON3SameNoD(const Instruction* instr); 220 void DisassembleNEONShiftLeftLongImm(const Instruction* instr); 221 void DisassembleNEONShiftRightImm(const Instruction* instr); 222 void DisassembleNEONShiftRightNarrowImm(const Instruction* instr); 223 void DisassembleNEONScalarSatMulLongIndex(const Instruction* instr); 224 void DisassembleNEONFPScalarMulIndex(const Instruction* instr); 225 void DisassembleNEONFPScalar3Same(const Instruction* instr); 226 void DisassembleNEONScalar3SameOnlyD(const Instruction* instr); 227 void DisassembleNEONFPAcrossLanes(const Instruction* instr); 228 void DisassembleNEONFP16AcrossLanes(const Instruction* instr); 229 void DisassembleNEONScalarShiftImmOnlyD(const Instruction* instr); 230 void DisassembleNEONScalarShiftRightNarrowImm(const Instruction* instr); 231 void DisassembleNEONScalar2RegMiscOnlyD(const Instruction* instr); 232 void DisassembleNEONFPScalar2RegMisc(const Instruction* instr); 233 void DisassembleNEONPolynomialMul(const Instruction* instr); 234 void DisassembleNEON4Same(const Instruction* instr); 235 void DisassembleNEONXar(const Instruction* instr); 236 void DisassembleNEONRax1(const Instruction* instr); 237 void DisassembleSHA512(const Instruction* instr); 238 239 void DisassembleMTELoadTag(const Instruction* instr); 240 void DisassembleMTEStoreTag(const Instruction* instr); 241 void DisassembleMTEStoreTagPair(const Instruction* instr); 242 243 void Disassemble_XdSP_XnSP_Xm(const Instruction* instr); 244 void Disassemble_XdSP_XnSP_uimm6_uimm4(const Instruction* instr); 245 void Disassemble_Xd_XnSP_Xm(const Instruction* instr); 246 void Disassemble_Xd_XnSP_XmSP(const Instruction* instr); 247 248 void VisitCryptoSM3(const Instruction* instr); 249 void VisitCryptoSM4(const Instruction* instr); 250 251 void Format(const Instruction* instr, 252 const char* mnemonic, 253 const char* format0, 254 const char* format1 = NULL); 255 void FormatWithDecodedMnemonic(const Instruction* instr, 256 const char* format0, 257 const char* format1 = NULL); 258 259 void Substitute(const Instruction* instr, const char* string); 260 int SubstituteField(const Instruction* instr, const char* format); 261 int SubstituteRegisterField(const Instruction* instr, const char* format); 262 int SubstitutePredicateRegisterField(const Instruction* instr, 263 const char* format); 264 int SubstituteImmediateField(const Instruction* instr, const char* format); 265 int SubstituteLiteralField(const Instruction* instr, const char* format); 266 int SubstituteBitfieldImmediateField(const Instruction* instr, 267 const char* format); 268 int SubstituteShiftField(const Instruction* instr, const char* format); 269 int SubstituteExtendField(const Instruction* instr, const char* format); 270 int SubstituteConditionField(const Instruction* instr, const char* format); 271 int SubstitutePCRelAddressField(const Instruction* instr, const char* format); 272 int SubstituteBranchTargetField(const Instruction* instr, const char* format); 273 int SubstituteLSRegOffsetField(const Instruction* instr, const char* format); 274 int SubstitutePrefetchField(const Instruction* instr, const char* format); 275 int SubstituteBarrierField(const Instruction* instr, const char* format); 276 int SubstituteSysOpField(const Instruction* instr, const char* format); 277 int SubstituteCrField(const Instruction* instr, const char* format); 278 int SubstituteIntField(const Instruction* instr, const char* format); 279 int SubstituteSVESize(const Instruction* instr, const char* format); 280 int SubstituteTernary(const Instruction* instr, const char* format); 281 282 std::pair<unsigned, unsigned> GetRegNumForField(const Instruction* instr, 283 char reg_prefix, 284 const char* field); 285 RdIsZROrSP(const Instruction * instr)286 bool RdIsZROrSP(const Instruction* instr) const { 287 return (instr->GetRd() == kZeroRegCode); 288 } 289 RnIsZROrSP(const Instruction * instr)290 bool RnIsZROrSP(const Instruction* instr) const { 291 return (instr->GetRn() == kZeroRegCode); 292 } 293 RmIsZROrSP(const Instruction * instr)294 bool RmIsZROrSP(const Instruction* instr) const { 295 return (instr->GetRm() == kZeroRegCode); 296 } 297 RaIsZROrSP(const Instruction * instr)298 bool RaIsZROrSP(const Instruction* instr) const { 299 return (instr->GetRa() == kZeroRegCode); 300 } 301 302 bool IsMovzMovnImm(unsigned reg_size, uint64_t value); 303 code_address_offset()304 int64_t code_address_offset() const { return code_address_offset_; } 305 306 protected: 307 void ResetOutput(); 308 void AppendToOutput(const char* string, ...) PRINTF_CHECK(2, 3); 309 set_code_address_offset(int64_t code_address_offset)310 void set_code_address_offset(int64_t code_address_offset) { 311 code_address_offset_ = code_address_offset; 312 } 313 314 char* buffer_; 315 uint32_t buffer_pos_; 316 uint32_t buffer_size_; 317 bool own_buffer_; 318 319 int64_t code_address_offset_; 320 }; 321 322 323 class PrintDisassembler : public Disassembler { 324 public: PrintDisassembler(FILE * stream)325 explicit PrintDisassembler(FILE* stream) 326 : cpu_features_auditor_(NULL), 327 cpu_features_prefix_("// Needs: "), 328 cpu_features_suffix_(""), 329 signed_addresses_(false), 330 stream_(stream) {} 331 332 // Convenience helpers for quick disassembly, without having to manually 333 // create a decoder. 334 void DisassembleBuffer(const Instruction* start, uint64_t size); 335 void DisassembleBuffer(const Instruction* start, const Instruction* end); 336 void Disassemble(const Instruction* instr); 337 338 // If a CPUFeaturesAuditor is specified, it will be used to annotate 339 // disassembly. The CPUFeaturesAuditor is expected to visit the instructions 340 // _before_ the disassembler, such that the CPUFeatures information is 341 // available when the disassembler is called. RegisterCPUFeaturesAuditor(CPUFeaturesAuditor * auditor)342 void RegisterCPUFeaturesAuditor(CPUFeaturesAuditor* auditor) { 343 cpu_features_auditor_ = auditor; 344 } 345 346 // Set the prefix to appear before the CPU features annotations. SetCPUFeaturesPrefix(const char * prefix)347 void SetCPUFeaturesPrefix(const char* prefix) { 348 VIXL_ASSERT(prefix != NULL); 349 cpu_features_prefix_ = prefix; 350 } 351 352 // Set the suffix to appear after the CPU features annotations. SetCPUFeaturesSuffix(const char * suffix)353 void SetCPUFeaturesSuffix(const char* suffix) { 354 VIXL_ASSERT(suffix != NULL); 355 cpu_features_suffix_ = suffix; 356 } 357 358 // By default, addresses are printed as simple, unsigned 64-bit hex values. 359 // 360 // With `PrintSignedAddresses(true)`: 361 // - negative addresses are printed as "-0x1234...", 362 // - positive addresses have a leading space, like " 0x1234...", to maintain 363 // alignment. 364 // 365 // This is most useful in combination with Disassembler::MapCodeAddress(...). PrintSignedAddresses(bool s)366 void PrintSignedAddresses(bool s) { signed_addresses_ = s; } 367 368 protected: 369 virtual void ProcessOutput(const Instruction* instr) VIXL_OVERRIDE; 370 371 CPUFeaturesAuditor* cpu_features_auditor_; 372 const char* cpu_features_prefix_; 373 const char* cpu_features_suffix_; 374 bool signed_addresses_; 375 376 private: 377 FILE* stream_; 378 }; 379 } // namespace aarch64 380 } // namespace vixl 381 382 #endif // VIXL_AARCH64_DISASM_AARCH64_H 383