MacroAssemblerPrinter.cpp
1 /* 2 * Copyright (C) 2015-2017 Apple Inc. 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 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "MacroAssemblerPrinter.h" 28 29 #if ENABLE(ASSEMBLER) 30 #if ENABLE(MASM_PROBE) 31 32 #include "MacroAssembler.h" 33 #include <inttypes.h> 34 35 namespace JSC { 36 37 namespace Printer { 38 39 using CPUState = Probe::CPUState; 40 using RegisterID = MacroAssembler::RegisterID; 41 using FPRegisterID = MacroAssembler::FPRegisterID; 42 43 template<typename T> T nextID(T id) { return static_cast<T>(id + 1); } 44 45 void printAllRegisters(PrintStream& out, Context& context) 46 { 47 auto& cpu = context.probeContext.cpu; 48 unsigned charsToIndent = context.data.as<unsigned>(); 49 50 auto indent = [&] () { 51 for (unsigned i = 0; i < charsToIndent; ++i) 52 out.print(" "); 53 }; 54 #define INDENT indent() 55 56 INDENT; out.print("cpu: {\n"); 57 58 #if USE(JSVALUE32_64) 59 #define INTPTR_HEX_VALUE_FORMAT "0x%08" PRIxPTR 60 #else 61 #define INTPTR_HEX_VALUE_FORMAT "0x%016" PRIxPTR 62 #endif 63 64 for (auto id = MacroAssembler::firstRegister(); id <= MacroAssembler::lastRegister(); id = nextID(id)) { 65 intptr_t value = static_cast<intptr_t>(cpu.gpr(id)); 66 INDENT; out.printf(" %6s: " INTPTR_HEX_VALUE_FORMAT " %" PRIdPTR "\n", cpu.gprName(id), value, value); 67 } 68 for (auto id = MacroAssembler::firstSPRegister(); id <= MacroAssembler::lastSPRegister(); id = nextID(id)) { 69 intptr_t value = static_cast<intptr_t>(cpu.spr(id)); 70 INDENT; out.printf(" %6s: " INTPTR_HEX_VALUE_FORMAT " %" PRIdPTR "\n", cpu.sprName(id), value, value); 71 } 72 #undef INTPTR_HEX_VALUE_FORMAT 73 74 for (auto id = MacroAssembler::firstFPRegister(); id <= MacroAssembler::lastFPRegister(); id = nextID(id)) { 75 uint64_t u = bitwise_cast<uint64_t>(cpu.fpr(id)); 76 double d = cpu.fpr(id); 77 INDENT; out.printf(" %6s: 0x%016" PRIx64 " %.13g\n", cpu.fprName(id), u, d); 78 } 79 80 INDENT; out.print("}\n"); 81 #undef INDENT 82 83 } 84 85 void printPCRegister(PrintStream& out, Context& context) 86 { 87 auto cpu = context.probeContext.cpu; 88 void* value = cpu.pc(); 89 out.printf("pc:<%p %" PRIdPTR ">", value, bitwise_cast<intptr_t>(value)); 90 } 91 92 void printRegisterID(PrintStream& out, Context& context) 93 { 94 RegisterID regID = context.data.as<RegisterID>(); 95 const char* name = CPUState::gprName(regID); 96 intptr_t value = context.probeContext.gpr(regID); 97 out.printf("%s:<%p %" PRIdPTR ">", name, bitwise_cast<void*>(value), value); 98 } 99 100 void printFPRegisterID(PrintStream& out, Context& context) 101 { 102 FPRegisterID regID = context.data.as<FPRegisterID>(); 103 const char* name = CPUState::fprName(regID); 104 double value = context.probeContext.fpr(regID); 105 out.printf("%s:<0x%016" PRIx64 " %.13g>", name, bitwise_cast<uint64_t>(value), value); 106 } 107 108 void printAddress(PrintStream& out, Context& context) 109 { 110 MacroAssembler::Address address = context.data.as<MacroAssembler::Address>(); 111 RegisterID regID = address.base; 112 const char* name = CPUState::gprName(regID); 113 intptr_t value = context.probeContext.gpr(regID); 114 out.printf("Address{base:%s:<%p %" PRIdPTR ">, offset:<0x%x %d>", name, bitwise_cast<void*>(value), value, address.offset, address.offset); 115 } 116 117 void printMemory(PrintStream& out, Context& context) 118 { 119 const Memory& memory = context.data.as<Memory>(); 120 121 uint8_t* ptr = nullptr; 122 switch (memory.addressType) { 123 case Memory::AddressType::Address: { 124 ptr = reinterpret_cast<uint8_t*>(context.probeContext.gpr(memory.u.address.base)); 125 ptr += memory.u.address.offset; 126 break; 127 } 128 case Memory::AddressType::AbsoluteAddress: { 129 ptr = reinterpret_cast<uint8_t*>(const_cast<void*>(memory.u.absoluteAddress.m_ptr)); 130 break; 131 } 132 } 133 134 if (memory.dumpStyle == Memory::SingleWordDump) { 135 if (memory.numBytes == sizeof(int8_t)) { 136 auto p = reinterpret_cast<int8_t*>(ptr); 137 out.printf("%p:<0x%02x %d>", p, *p, *p); 138 return; 139 } 140 if (memory.numBytes == sizeof(int16_t)) { 141 auto p = bitwise_cast<int16_t*>(ptr); 142 out.printf("%p:<0x%04x %d>", p, *p, *p); 143 return; 144 } 145 if (memory.numBytes == sizeof(int32_t)) { 146 auto p = bitwise_cast<int32_t*>(ptr); 147 out.printf("%p:<0x%08x %d>", p, *p, *p); 148 return; 149 } 150 if (memory.numBytes == sizeof(int64_t)) { 151 auto p = bitwise_cast<int64_t*>(ptr); 152 out.printf("%p:<0x%016" PRIx64 " %" PRId64 ">", p, *p, *p); 153 return; 154 } 155 // Else, unknown word size. Fall thru and dump in the generic way. 156 } 157 158 // Generic dump: dump rows of 16 bytes in 4 byte groupings. 159 size_t numBytes = memory.numBytes; 160 for (size_t i = 0; i < numBytes; i++) { 161 if (!(i % 16)) 162 out.printf("%p: ", &ptr[i]); 163 else if (!(i % 4)) 164 out.printf(" "); 165 166 out.printf("%02x", ptr[i]); 167 168 if (i % 16 == 15) 169 out.print("\n"); 170 } 171 if (numBytes % 16 < 15) 172 out.print("\n"); 173 } 174 175 void printCallback(Probe::Context& probeContext) 176 { 177 auto& out = WTF::dataFile(); 178 PrintRecordList& list = *probeContext.arg<PrintRecordList*>(); 179 for (size_t i = 0; i < list.size(); i++) { 180 auto& record = list[i]; 181 Context context(probeContext, record.data); 182 record.printer(out, context); 183 } 184 } 185 186 } // namespace Printer 187 } // namespace JSC 188 189 #endif // ENABLE(MASM_PROBE) 190 #endif // ENABLE(ASSEMBLER)