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 #ifndef PANDA_BUILD 49 Disassembler(); 50 #else 51 Disassembler() = delete; 52 Disassembler(AllocatorWrapper allocator); 53 #endif 54 Disassembler(char* text_buffer, int buffer_size); 55 virtual ~Disassembler(); 56 char* GetOutput(); 57 GetDefaultBufferSize()58 static constexpr size_t GetDefaultBufferSize() { return kDefaultBufferSize; } 59 60 // Declare all Visitor functions. 61 virtual void Visit(Metadata* metadata, 62 const Instruction* instr) VIXL_OVERRIDE; 63 64 protected: 65 virtual void ProcessOutput(const Instruction* instr); 66 67 // Default output functions. The functions below implement a default way of 68 // printing elements in the disassembly. A sub-class can override these to 69 // customize the disassembly output. 70 71 // Prints the name of a register. 72 // TODO: This currently doesn't allow renaming of V registers. 73 virtual void AppendRegisterNameToOutput(const Instruction* instr, 74 const CPURegister& reg); 75 76 // Prints a PC-relative offset. This is used for example when disassembling 77 // branches to immediate offsets. 78 virtual void AppendPCRelativeOffsetToOutput(const Instruction* instr, 79 int64_t offset); 80 81 // Prints an address, in the general case. It can be code or data. This is 82 // used for example to print the target address of an ADR instruction. 83 virtual void AppendCodeRelativeAddressToOutput(const Instruction* instr, 84 const void* addr); 85 86 // Prints the address of some code. 87 // This is used for example to print the target address of a branch to an 88 // immediate offset. 89 // A sub-class can for example override this method to lookup the address and 90 // print an appropriate name. 91 virtual void AppendCodeRelativeCodeAddressToOutput(const Instruction* instr, 92 const void* addr); 93 94 // Prints the address of some data. 95 // This is used for example to print the source address of a load literal 96 // instruction. 97 virtual void AppendCodeRelativeDataAddressToOutput(const Instruction* instr, 98 const void* addr); 99 100 // Same as the above, but for addresses that are not relative to the code 101 // buffer. They are currently not used by VIXL. 102 virtual void AppendAddressToOutput(const Instruction* instr, 103 const void* addr); 104 virtual void AppendCodeAddressToOutput(const Instruction* instr, 105 const void* addr); 106 virtual void AppendDataAddressToOutput(const Instruction* instr, 107 const void* addr); 108 109 public: 110 // Get/Set the offset that should be added to code addresses when printing 111 // code-relative addresses in the AppendCodeRelative<Type>AddressToOutput() 112 // helpers. 113 // Below is an example of how a branch immediate instruction in memory at 114 // address 0xb010200 would disassemble with different offsets. 115 // Base address | Disassembly 116 // 0x0 | 0xb010200: b #+0xcc (addr 0xb0102cc) 117 // 0x10000 | 0xb000200: b #+0xcc (addr 0xb0002cc) 118 // 0xb010200 | 0x0: b #+0xcc (addr 0xcc) 119 void MapCodeAddress(int64_t base_address, const Instruction* instr_address); 120 int64_t CodeRelativeAddress(const void* instr); 121 122 private: 123 static constexpr size_t kDefaultBufferSize {256U}; 124 125 #define DECLARE(A) virtual void Visit##A(const Instruction* instr); 126 VISITOR_LIST(DECLARE) 127 #undef DECLARE 128 129 using FormToVisitorFnMap = FormToVisitorFnMapT<Disassembler>; 130 131 static const FormToVisitorFnMap FORM_TO_VISITOR; 132 133 static const FormToVisitorFnMap* GetFormToVisitorFnMap(); 134 135 std::string mnemonic_; 136 uint32_t form_hash_; 137 SetMnemonicFromForm(const std::string& form)138 void SetMnemonicFromForm(const std::string& form) { 139 if (form != "unallocated") { 140 VIXL_ASSERT(form.find_first_of('_') != std::string::npos); 141 mnemonic_ = form.substr(0, form.find_first_of('_')); 142 } 143 } 144 145 void Disassemble_PdT_PgZ_ZnT_ZmT(const Instruction* instr); 146 void Disassemble_ZdB_Zn1B_Zn2B_imm(const Instruction* instr); 147 void Disassemble_ZdB_ZnB_ZmB(const Instruction* instr); 148 void Disassemble_ZdD_PgM_ZnS(const Instruction* instr); 149 void Disassemble_ZdD_ZnD_ZmD(const Instruction* instr); 150 void Disassemble_ZdD_ZnD_ZmD_imm(const Instruction* instr); 151 void Disassemble_ZdD_ZnS_ZmS_imm(const Instruction* instr); 152 void Disassemble_ZdH_PgM_ZnS(const Instruction* instr); 153 void Disassemble_ZdH_ZnH_ZmH_imm(const Instruction* instr); 154 void Disassemble_ZdS_PgM_ZnD(const Instruction* instr); 155 void Disassemble_ZdS_PgM_ZnH(const Instruction* instr); 156 void Disassemble_ZdS_PgM_ZnS(const Instruction* instr); 157 void Disassemble_ZdS_ZnH_ZmH_imm(const Instruction* instr); 158 void Disassemble_ZdS_ZnS_ZmS(const Instruction* instr); 159 void Disassemble_ZdS_ZnS_ZmS_imm(const Instruction* instr); 160 void Disassemble_ZdT_PgM_ZnT(const Instruction* instr); 161 void Disassemble_ZdT_PgZ_ZnT_ZmT(const Instruction* instr); 162 void Disassemble_ZdT_Pg_Zn1T_Zn2T(const Instruction* instr); 163 void Disassemble_ZdT_Zn1T_Zn2T_ZmT(const Instruction* instr); 164 void Disassemble_ZdT_ZnT_ZmT(const Instruction* instr); 165 void Disassemble_ZdT_ZnT_ZmTb(const Instruction* instr); 166 void Disassemble_ZdT_ZnTb(const Instruction* instr); 167 void Disassemble_ZdT_ZnTb_ZmTb(const Instruction* instr); 168 void Disassemble_ZdaD_ZnD_ZmD_imm(const Instruction* instr); 169 void Disassemble_ZdaD_ZnH_ZmH_imm_const(const Instruction* instr); 170 void Disassemble_ZdaD_ZnS_ZmS_imm(const Instruction* instr); 171 void Disassemble_ZdaH_ZnH_ZmH_imm(const Instruction* instr); 172 void Disassemble_ZdaH_ZnH_ZmH_imm_const(const Instruction* instr); 173 void Disassemble_ZdaS_ZnB_ZmB_imm_const(const Instruction* instr); 174 void Disassemble_ZdaS_ZnH_ZmH(const Instruction* instr); 175 void Disassemble_ZdaS_ZnH_ZmH_imm(const Instruction* instr); 176 void Disassemble_ZdaS_ZnS_ZmS_imm(const Instruction* instr); 177 void Disassemble_ZdaS_ZnS_ZmS_imm_const(const Instruction* instr); 178 void Disassemble_ZdaT_PgM_ZnTb(const Instruction* instr); 179 void Disassemble_ZdaT_ZnT_ZmT(const Instruction* instr); 180 void Disassemble_ZdaT_ZnT_ZmT_const(const Instruction* instr); 181 void Disassemble_ZdaT_ZnT_const(const Instruction* instr); 182 void Disassemble_ZdaT_ZnTb_ZmTb(const Instruction* instr); 183 void Disassemble_ZdaT_ZnTb_ZmTb_const(const Instruction* instr); 184 void Disassemble_ZdnB_ZdnB(const Instruction* instr); 185 void Disassemble_ZdnB_ZdnB_ZmB(const Instruction* instr); 186 void Disassemble_ZdnS_ZdnS_ZmS(const Instruction* instr); 187 void Disassemble_ZdnT_PgM_ZdnT_ZmT(const Instruction* instr); 188 void Disassemble_ZdnT_PgM_ZdnT_const(const Instruction* instr); 189 void Disassemble_ZdnT_ZdnT_ZmT_const(const Instruction* instr); 190 void Disassemble_ZtD_PgZ_ZnD_Xm(const Instruction* instr); 191 void Disassemble_ZtD_Pg_ZnD_Xm(const Instruction* instr); 192 void Disassemble_ZtS_PgZ_ZnS_Xm(const Instruction* instr); 193 void Disassemble_ZtS_Pg_ZnS_Xm(const Instruction* instr); 194 void Disassemble_ZdaS_ZnB_ZmB(const Instruction* instr); 195 void Disassemble_Vd4S_Vn16B_Vm16B(const Instruction* instr); 196 197 void DisassembleCpy(const Instruction* instr); 198 void DisassembleSet(const Instruction* instr); 199 void DisassembleMinMaxImm(const Instruction* instr); 200 201 void DisassembleSVEShiftLeftImm(const Instruction* instr); 202 void DisassembleSVEShiftRightImm(const Instruction* instr); 203 void DisassembleSVEAddSubCarry(const Instruction* instr); 204 void DisassembleSVEAddSubHigh(const Instruction* instr); 205 void DisassembleSVEComplexIntAddition(const Instruction* instr); 206 void DisassembleSVEBitwiseTernary(const Instruction* instr); 207 void DisassembleSVEFlogb(const Instruction* instr); 208 void DisassembleSVEFPPair(const Instruction* instr); 209 210 void DisassembleNoArgs(const Instruction* instr); 211 212 void DisassembleNEONMulByElementLong(const Instruction* instr); 213 void DisassembleNEONDotProdByElement(const Instruction* instr); 214 void DisassembleNEONFPMulByElement(const Instruction* instr); 215 void DisassembleNEONHalfFPMulByElement(const Instruction* instr); 216 void DisassembleNEONFPMulByElementLong(const Instruction* instr); 217 void DisassembleNEONComplexMulByElement(const Instruction* instr); 218 void DisassembleNEON2RegLogical(const Instruction* instr); 219 void DisassembleNEON2RegExtract(const Instruction* instr); 220 void DisassembleNEON2RegAddlp(const Instruction* instr); 221 void DisassembleNEON2RegCompare(const Instruction* instr); 222 void DisassembleNEON2RegFPCompare(const Instruction* instr); 223 void DisassembleNEON2RegFPConvert(const Instruction* instr); 224 void DisassembleNEON2RegFP(const Instruction* instr); 225 void DisassembleNEON3SameLogical(const Instruction* instr); 226 void DisassembleNEON3SameFHM(const Instruction* instr); 227 void DisassembleNEON3SameNoD(const Instruction* instr); 228 void DisassembleNEONShiftLeftLongImm(const Instruction* instr); 229 void DisassembleNEONShiftRightImm(const Instruction* instr); 230 void DisassembleNEONShiftRightNarrowImm(const Instruction* instr); 231 void DisassembleNEONScalarSatMulLongIndex(const Instruction* instr); 232 void DisassembleNEONFPScalarMulIndex(const Instruction* instr); 233 void DisassembleNEONFPScalar3Same(const Instruction* instr); 234 void DisassembleNEONScalar3SameOnlyD(const Instruction* instr); 235 void DisassembleNEONFPAcrossLanes(const Instruction* instr); 236 void DisassembleNEONFP16AcrossLanes(const Instruction* instr); 237 void DisassembleNEONScalarShiftImmOnlyD(const Instruction* instr); 238 void DisassembleNEONScalarShiftRightNarrowImm(const Instruction* instr); 239 void DisassembleNEONScalar2RegMiscOnlyD(const Instruction* instr); 240 void DisassembleNEONFPScalar2RegMisc(const Instruction* instr); 241 242 void DisassembleMTELoadTag(const Instruction* instr); 243 void DisassembleMTEStoreTag(const Instruction* instr); 244 void DisassembleMTEStoreTagPair(const Instruction* instr); 245 246 void Disassemble_XdSP_XnSP_Xm(const Instruction* instr); 247 void Disassemble_XdSP_XnSP_uimm6_uimm4(const Instruction* instr); 248 void Disassemble_Xd_XnSP_Xm(const Instruction* instr); 249 void Disassemble_Xd_XnSP_XmSP(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) const286 bool RdIsZROrSP(const Instruction* instr) const { 287 return (instr->GetRd() == kZeroRegCode); 288 } 289 RnIsZROrSP(const Instruction* instr) const290 bool RnIsZROrSP(const Instruction* instr) const { 291 return (instr->GetRn() == kZeroRegCode); 292 } 293 RmIsZROrSP(const Instruction* instr) const294 bool RmIsZROrSP(const Instruction* instr) const { 295 return (instr->GetRm() == kZeroRegCode); 296 } 297 RaIsZROrSP(const Instruction* instr) const298 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() const304 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 std::optional<AllocatorWrapper> allocator_; 318 bool own_buffer_ {false}; 319 320 int64_t code_address_offset_; 321 }; 322 323 324 class PrintDisassembler : public Disassembler { 325 public: 326 #ifndef PANDA_BUILD PrintDisassembler(FILE* stream)327 explicit PrintDisassembler(FILE* stream) 328 : cpu_features_auditor_(NULL), 329 #else 330 explicit PrintDisassembler(FILE* stream) = delete; 331 explicit PrintDisassembler(AllocatorWrapper allocator, FILE* stream) 332 : Disassembler(allocator), cpu_features_auditor_(NULL), allocator_(allocator), 333 #endif 334 cpu_features_prefix_("// Needs: "), 335 cpu_features_suffix_(""), 336 signed_addresses_(false), 337 stream_(stream) {} 338 339 340 // Convenience helpers for quick disassembly, without having to manually 341 // create a decoder. 342 void DisassembleBuffer(const Instruction* start, uint64_t size); 343 void DisassembleBuffer(const Instruction* start, const Instruction* end); 344 void Disassemble(const Instruction* instr); 345 346 // If a CPUFeaturesAuditor is specified, it will be used to annotate 347 // disassembly. The CPUFeaturesAuditor is expected to visit the instructions 348 // _before_ the disassembler, such that the CPUFeatures information is 349 // available when the disassembler is called. RegisterCPUFeaturesAuditor(CPUFeaturesAuditor* auditor)350 void RegisterCPUFeaturesAuditor(CPUFeaturesAuditor* auditor) { 351 cpu_features_auditor_ = auditor; 352 } 353 354 // Set the prefix to appear before the CPU features annotations. SetCPUFeaturesPrefix(const char* prefix)355 void SetCPUFeaturesPrefix(const char* prefix) { 356 VIXL_ASSERT(prefix != NULL); 357 cpu_features_prefix_ = prefix; 358 } 359 360 // Set the suffix to appear after the CPU features annotations. SetCPUFeaturesSuffix(const char* suffix)361 void SetCPUFeaturesSuffix(const char* suffix) { 362 VIXL_ASSERT(suffix != NULL); 363 cpu_features_suffix_ = suffix; 364 } 365 366 // By default, addresses are printed as simple, unsigned 64-bit hex values. 367 // 368 // With `PrintSignedAddresses(true)`: 369 // - negative addresses are printed as "-0x1234...", 370 // - positive addresses have a leading space, like " 0x1234...", to maintain 371 // alignment. 372 // 373 // This is most useful in combination with Disassembler::MapCodeAddress(...). PrintSignedAddresses(bool s)374 void PrintSignedAddresses(bool s) { signed_addresses_ = s; } 375 376 protected: 377 virtual void ProcessOutput(const Instruction* instr) VIXL_OVERRIDE; 378 379 CPUFeaturesAuditor* cpu_features_auditor_; 380 #ifdef PANDA_BUILD 381 AllocatorWrapper allocator_; 382 #endif 383 const char* cpu_features_prefix_; 384 const char* cpu_features_suffix_; 385 bool signed_addresses_; 386 387 private: 388 FILE* stream_; 389 }; 390 } // namespace aarch64 391 } // namespace vixl 392 393 #endif // VIXL_AARCH64_DISASM_AARCH64_H 394