/ assembler / MacroAssemblerPrinter.cpp
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)