]>
git.saurik.com Git - apple/javascriptcore.git/blob - interpreter/VMInspector.cpp
2 * Copyright (C) 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "VMInspector.h"
29 #if ENABLE(VMINSPECTOR)
31 #include "JSCInlines.h"
32 #include <wtf/ASCIICType.h>
33 #include <wtf/text/WTFString.h>
37 const char* VMInspector::getTypeName(JSValue value
)
41 if (value
.isBoolean())
45 if (value
.isUndefined())
54 void VMInspector::dumpFrame0(CallFrame
* frame
)
56 dumpFrame(frame
, 0, 0, 0, 0);
59 void VMInspector::dumpFrame(CallFrame
* frame
, const char* prefix
,
60 const char* funcName
, const char* file
, int line
)
62 int frameCount
= VMInspector::countFrames(frame
);
67 if (frame
->codeBlock())
68 vPC
= frame
->currentVPC();
70 #define CAST reinterpret_cast
73 printf("%s ", prefix
);
75 printf("frame [%d] %p { cb %p:%s, retPC %p:%s, scope %p:%s, callee %p:%s, callerFrame %p:%s, argc %d, vPC %p }",
77 CAST
<void*>(frame
[JSStack::CodeBlock
].payload()),
78 getTypeName(frame
[JSStack::CodeBlock
].jsValue()),
79 CAST
<void*>(frame
[JSStack::ReturnPC
].payload()),
80 getTypeName(frame
[JSStack::ReturnPC
].jsValue()),
81 CAST
<void*>(frame
[JSStack::ScopeChain
].payload()),
82 getTypeName(frame
[JSStack::ScopeChain
].jsValue()),
83 CAST
<void*>(frame
[JSStack::Callee
].payload()),
84 getTypeName(frame
[JSStack::Callee
].jsValue()),
85 CAST
<void*>(frame
[JSStack::CallerFrame
].callFrame()),
86 getTypeName(frame
[JSStack::CallerFrame
].jsValue()),
87 frame
[JSStack::ArgumentCount
].payload(),
90 if (funcName
|| file
|| (line
>= 0)) {
93 printf(" %s", funcName
);
102 int VMInspector::countFrames(CallFrame
* frame
)
105 while (frame
&& !frame
->isVMEntrySentinel()) {
107 frame
= frame
->callerFrame();
113 //============================================================================
114 // class FormatPrinter
115 // - implements functionality to support fprintf.
117 // The FormatPrinter classes do the real formatting and printing.
118 // By default, the superclass FormatPrinter will print to stdout (printf).
119 // Each of the subclass will implement the other ...printf() options.
120 // The subclasses are:
122 // FileFormatPrinter - fprintf
123 // StringFormatPrinter - sprintf
124 // StringNFormatPrinter - snprintf
126 class FormatPrinter
{
128 virtual ~FormatPrinter() { }
130 void print(const char* format
, va_list args
);
133 // Low level printers:
134 bool printArg(const char* format
, ...);
135 virtual bool printArg(const char* format
, va_list args
);
137 // JS type specific printers:
138 void printWTFString(va_list args
, bool verbose
);
142 // The public print() function is the real workhorse behind the printf
143 // family of functions. print() deciphers the % formatting, translate them
144 // to primitive formats, and dispatches to underlying printArg() functions
145 // to do the printing.
147 // The non-public internal printArg() function is virtual and is responsible
148 // for handling the variations between printf, fprintf, sprintf, and snprintf.
150 void FormatPrinter::print(const char* format
, va_list args
)
152 const char* p
= format
;
153 const char* errorStr
;
155 // buffer is only used for 2 purposes:
156 // 1. To temporarily hold a copy of normal chars (not needing formatting)
157 // to be passed to printArg() and printed.
159 // The incoming format string may contain a string of normal chars much
160 // longer than 128, but we handle this by breaking them out to 128 chars
161 // fragments and printing each fragment before re-using the buffer to
162 // load up the next fragment.
164 // 2. To hold a single "%..." format to be passed to printArg() to process
167 char buffer
[129]; // 128 chars + null terminator.
168 char* end
= &buffer
[sizeof(buffer
) - 1];
169 const char* startOfFormatSpecifier
= 0;
175 // Print leading normal chars:
176 while (c
!= '\0' && c
!= '%') {
179 // Out of buffer space. Flush the fragment, and start over.
181 bool success
= printArg("%s", buffer
);
190 // If we have stuff in the buffer, flush the fragment:
191 if (curr
!= buffer
) {
192 ASSERT(curr
< end
+ 1);
194 bool success
= printArg("%s", buffer
);
201 // End if there are not more chars to print:
205 // If we get here, we've must have seen a '%':
206 startOfFormatSpecifier
= p
- 1;
207 ASSERT(*startOfFormatSpecifier
== '%');
210 // Check for "%%" case:
212 bool success
= printArg("%c", '%');
220 // Check for JS (%J<x>) formatting extensions:
222 bool verbose
= false;
225 if (UNLIKELY(c
== '\0')) {
226 errorStr
= p
- 2; // Rewind to % in "%J\0"
233 if (UNLIKELY(c
== '\0')) {
234 errorStr
= p
- 3; // Rewind to % in "%J+\0"
240 // %Js - WTF::String*
242 printWTFString(args
, verbose
);
247 // Check for non-JS extensions:
248 } else if (c
== 'b') {
249 int value
= va_arg(args
, int);
250 printArg("%s", value
? "TRUE" : "FALSE");
254 // If we didn't handle the format in one of the above cases,
255 // rewind p and let the standard formatting check handle it
257 p
= startOfFormatSpecifier
;
260 // Check for standard formatting:
261 // A format specifier always starts with a % and ends with some
262 // alphabet. We'll do the simple thing and scan until the next
263 // alphabet, or the end of string.
265 // In the following, we're going to use buffer as storage for a copy
266 // of a single format specifier. Hence, conceptually, we can think of
267 // 'buffer' as synonymous with 'argFormat' here:
269 #define ABORT_IF_FORMAT_TOO_LONG(curr) \
271 if (UNLIKELY(curr >= end)) \
272 goto formatTooLong; \
276 *curr
++ = *p
++; // Output the first % in the format specifier.
277 c
= *p
++; // Grab the next char in the format specifier.
279 // Checks for leading modifiers e.g. "%-d":
280 // 0, -, ' ', +, '\''
281 if (c
== '0' || c
== '-' || c
== ' ' || c
== '+' || c
== '\'' || c
== '#') {
282 ABORT_IF_FORMAT_TOO_LONG(curr
);
287 // Checks for decimal digit field width modifiers e.g. "%2f":
288 while (c
>= '0' && c
<= '9') {
289 ABORT_IF_FORMAT_TOO_LONG(curr
);
294 // Checks for '.' e.g. "%2.f":
296 ABORT_IF_FORMAT_TOO_LONG(curr
);
300 // Checks for decimal digit precision modifiers e.g. "%.2f":
301 while (c
>= '0' && c
<= '9') {
302 ABORT_IF_FORMAT_TOO_LONG(curr
);
308 // Checks for the modifier <m> where <m> can be:
311 if (c
== 'l' || c
== 'h' || c
== 'j' || c
== 't' || c
== 'z' || c
== 'L') {
312 ABORT_IF_FORMAT_TOO_LONG(curr
);
317 // Checks for the modifier ll or hh in %<x><m>:
318 if ((prevChar
== 'l' || prevChar
== 'h') && c
== prevChar
) {
319 ABORT_IF_FORMAT_TOO_LONG(curr
);
325 // Checks for %<x> where <x> can be:
326 // d, i, n, o, u, x, X
327 // But hey, we're just going to do the simple thing and allow any
328 // alphabet. The user is expected to pass correct format specifiers.
329 // We won't do any format checking here. We'll just pass it on, and the
330 // underlying ...printf() implementation may do the needed checking
331 // at its discretion.
332 while (c
!= '\0' && !isASCIIAlpha(c
)) {
333 ABORT_IF_FORMAT_TOO_LONG(curr
);
338 ABORT_IF_FORMAT_TOO_LONG(curr
);
341 // Uh oh. Bad format. We should have gotten an alphabet instead.
342 // Print the supposed format as a string instead:
347 // Otherwise, we have the alpha that terminates the format.
348 // Terminate the buffer (i.e. argFormat) string:
349 ASSERT(isASCIIAlpha(c
));
350 ABORT_IF_FORMAT_TOO_LONG(curr
);
353 bool success
= printArg(buffer
, args
);
359 #undef ABORT_IF_FORMAT_TOO_LONG
364 // Print the error string:
365 ASSERT(!!startOfFormatSpecifier
);
366 p
= startOfFormatSpecifier
;
368 printArg("ERROR @ Format too long at \"%s\"\n", p
);
372 // We've got an error. Can't do any more work. Print an error message if
373 // possible and then just return.
375 // The errorStr may be pointing into the middle of buffer, or the original
376 // format string. Move the string to buffer for consistency, and also so
377 // that we can strip it of newlines below.
378 if (errorStr
!= buffer
) {
379 size_t length
= strlen(errorStr
);
380 if (length
> sizeof(buffer
) - 1)
381 length
= sizeof(buffer
) - 1;
382 memmove(buffer
, errorStr
, length
);
383 buffer
[length
] = '\0'; // Terminate the moved error string.
385 // Strip the newlines:
388 if (*cp
== '\n' || *cp
== '\r')
392 // Print the error string:
393 printArg("ERROR @ \"%s\"\n", buffer
);
397 bool FormatPrinter::printArg(const char* format
, ...)
400 va_start(args
, format
);
401 bool success
= printArg(format
, args
);
406 bool FormatPrinter::printArg(const char* format
, va_list args
)
408 int count
= ::vprintf(format
, args
);
409 return (count
>= 0); // Fail if less than 0 chars printed.
413 // %Js - WTF::String*
414 // verbose mode prints: WTF::String "<your string>"
415 void FormatPrinter::printWTFString(va_list args
, bool verbose
)
417 const String
* str
= va_arg(args
, const String
*);
419 // Print verbose header if appropriate:
421 printArg("WTF::String \"");
423 // Print the string itself:
424 if (!str
->isEmpty()) {
426 const LChar
* chars
= str
->characters8();
427 printArg("%s", reinterpret_cast<const char*>(chars
));
429 const UChar
* chars
= str
->characters16();
430 printArg("%S", reinterpret_cast<const wchar_t*>(chars
));
434 // Print verbose footer if appropriate:
440 //============================================================================
441 // class FileFormatPrinter
442 // - implements functionality to support fprintf.
444 class FileFormatPrinter
: public FormatPrinter
{
446 FileFormatPrinter(FILE*);
448 virtual bool printArg(const char* format
, va_list args
);
453 FileFormatPrinter::FileFormatPrinter(FILE* file
)
458 bool FileFormatPrinter::printArg(const char* format
, va_list args
)
460 int count
= ::vfprintf(m_file
, format
, args
);
461 return (count
>= 0); // Fail if less than 0 chars printed.
465 //============================================================================
466 // class StringFormatPrinter
467 // - implements functionality to support sprintf.
469 class StringFormatPrinter
: public FormatPrinter
{
471 StringFormatPrinter(char* buffer
);
473 virtual bool printArg(const char* format
, va_list args
);
478 StringFormatPrinter::StringFormatPrinter(char* buffer
)
483 bool StringFormatPrinter::printArg(const char* format
, va_list args
)
485 int count
= ::vsprintf(m_buffer
, format
, args
);
487 return (count
>= 0); // Fail if less than 0 chars printed.
491 //============================================================================
492 // class StringNFormatPrinter
493 // - implements functionality to support snprintf.
495 class StringNFormatPrinter
: public FormatPrinter
{
497 StringNFormatPrinter(char* buffer
, size_t);
499 virtual bool printArg(const char* format
, va_list args
);
506 StringNFormatPrinter::StringNFormatPrinter(char* buffer
, size_t size
)
512 bool StringNFormatPrinter::printArg(const char* format
, va_list args
)
515 int count
= ::vsnprintf(m_buffer
, m_size
, format
, args
);
517 // According to vsnprintf specs, ...
518 bool success
= (count
>= 0);
519 if (static_cast<size_t>(count
) >= m_size
) {
520 // If count > size, then we didn't have enough buffer space.
524 // Adjust the buffer to what's left if appropriate:
531 // No more room to print. Declare it a fail:
536 //============================================================================
537 // VMInspector printf family of methods:
539 void VMInspector::fprintf(FILE* file
, const char* format
, ...)
542 va_start(args
, format
);
543 FileFormatPrinter(file
).print(format
, args
);
547 void VMInspector::printf(const char* format
, ...)
550 va_start(args
, format
);
551 FormatPrinter().print(format
, args
);
555 void VMInspector::sprintf(char* buffer
, const char* format
, ...)
558 va_start(args
, format
);
559 StringFormatPrinter(buffer
).print(format
, args
);
563 void VMInspector::snprintf(char* buffer
, size_t size
, const char* format
, ...)
566 va_start(args
, format
);
567 StringNFormatPrinter(buffer
, size
).print(format
, args
);
573 #endif // ENABLE(VMINSPECTOR)