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