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 43namespace vixl { 44namespace aarch64 { 45 46class 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 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 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 286 bool RdIsZROrSP(const Instruction* instr) const { 287 return (instr->GetRd() == kZeroRegCode); 288 } 289 290 bool RnIsZROrSP(const Instruction* instr) const { 291 return (instr->GetRn() == kZeroRegCode); 292 } 293 294 bool RmIsZROrSP(const Instruction* instr) const { 295 return (instr->GetRm() == kZeroRegCode); 296 } 297 298 bool RaIsZROrSP(const Instruction* instr) const { 299 return (instr->GetRa() == kZeroRegCode); 300 } 301 302 bool IsMovzMovnImm(unsigned reg_size, uint64_t value); 303 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 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 324class PrintDisassembler : public Disassembler { 325 public: 326#ifndef PANDA_BUILD 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. 350 void RegisterCPUFeaturesAuditor(CPUFeaturesAuditor* auditor) { 351 cpu_features_auditor_ = auditor; 352 } 353 354 // Set the prefix to appear before the CPU features annotations. 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. 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(...). 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