34019d170261ac9503c28182f72209558cda7dac
[WebKit-https.git] / Source / JavaScriptCore / assembler / 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 = reinterpret_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 = reinterpret_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 = reinterpret_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)