1 /**************************************************************************
3 * Copyright 2007-2009 VMware, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
41 #define PATH_MAX _MAX_PATH
44 #define snprintf _snprintf
47 #define vsnprintf _vsnprintf
55 static gzFile g_gzFile = NULL;
56 static char g_szFileName[PATH_MAX];
57 static CRITICAL_SECTION CriticalSection;
59 static void _Close(void) {
60 if(g_gzFile != NULL) {
63 DeleteCriticalSection(&CriticalSection);
67 static void _Open(const char *szName, const char *szExtension) {
70 static unsigned dwCounter = 0;
72 char szProcessPath[PATH_MAX];
76 GetModuleFileNameA(NULL, szProcessPath, sizeof(szProcessPath)/sizeof(szProcessPath[0]));
78 lpProcessName = strrchr(szProcessPath, '\\');
79 lpProcessName = lpProcessName ? lpProcessName + 1 : szProcessPath;
80 lpProcessExt = strrchr(lpProcessName, '.');
88 snprintf(g_szFileName, PATH_MAX, "%s.%s.%u.%s.gz", lpProcessName, szName, dwCounter, szExtension);
90 snprintf(g_szFileName, PATH_MAX, "%s.%s.%s.gz", lpProcessName, szName, szExtension);
92 file = fopen(g_szFileName, "rb");
101 g_gzFile = gzopen(g_szFileName, "wb");
102 InitializeCriticalSection(&CriticalSection);
105 static inline void _ReOpen(void) {
109 static inline void Write(const char *sBuffer, size_t dwBytesToWrite) {
113 gzwrite(g_gzFile, sBuffer, dwBytesToWrite);
116 static inline void Write(const char *szText) {
117 Write(szText, strlen(szText));
121 Escape(const char *s) {
127 Indent(unsigned level) {
128 for(unsigned i = 0; i < level; ++i)
138 Tag(const char *name) {
145 BeginTag(const char *name) {
152 BeginTag(const char *name,
153 const char *attr1, const char *value1) {
164 BeginTag(const char *name,
165 const char *attr1, const char *value1,
166 const char *attr2, const char *value2) {
181 BeginTag(const char *name,
182 const char *attr1, const char *value1,
183 const char *attr2, const char *value2,
184 const char *attr3, const char *value3) {
203 EndTag(const char *name) {
209 void Open(const char *name) {
211 Write("<?xml version='1.0' encoding='UTF-8'?>");
213 Write("<?xml-stylesheet type='text/xsl' href='apitrace.xsl'?>");
229 void Text(const char *text) {
233 static void TextChar(char c) {
240 void TextF(const char *format, ...) {
243 va_start(ap, format);
244 vsnprintf(szBuffer, sizeof(szBuffer), format, ap);
249 static LARGE_INTEGER frequency = {0};
250 static LARGE_INTEGER startcounter;
252 void BeginCall(const char *function) {
253 EnterCriticalSection(&CriticalSection);
255 BeginTag("call", "name", function);
258 if(!frequency.QuadPart)
259 QueryPerformanceFrequency(&frequency);
261 QueryPerformanceCounter(&startcounter);
265 LARGE_INTEGER endcounter;
268 QueryPerformanceCounter(&endcounter);
269 usecs = (endcounter.QuadPart - startcounter.QuadPart)*1000000/frequency.QuadPart;
272 BeginTag("duration");
273 TextF("%llu", usecs);
280 gzflush(g_gzFile, Z_SYNC_FLUSH);
281 LeaveCriticalSection(&CriticalSection);
284 void BeginArg(const char *type, const char *name) {
286 BeginTag("arg", "type", type, "name", name);
294 void BeginReturn(const char *type) {
296 BeginTag("ret", "type", type);
299 void EndReturn(void) {
304 void BeginElement(const char *type, const char *name) {
305 BeginTag("elem", "type", type, "name", name);
308 void BeginElement(const char *type) {
309 BeginTag("elem", "type", type);
312 void EndElement(void) {
316 void BeginReference(const char *type, const void *addr) {
318 snprintf(saddr, sizeof(saddr), "%p", addr);
319 BeginTag("ref", "type", type, "addr", saddr);
322 void EndReference(void) {
326 void DumpString(const char *str) {
327 const unsigned char *p = (const unsigned char *)str;
334 while((c = *p++) != 0) {
339 else if(c >= 0x20 && c <= 0x7e)
348 unsigned char octal0 = c & 0x7;
349 unsigned char octal1 = (c >> 3) & 0x7;
350 unsigned char octal2 = (c >> 3) & 0x7;
352 TextF("\\%u%u%u", octal2, octal1, octal0);
354 TextF("\\%u%u", octal1, octal0);
356 TextF("\\%u", octal0);
362 void DumpWString(const wchar_t *str) {
363 const wchar_t *p = str;
370 while((c = *p++) != 0) {
375 else if(c >= 0x20 && c <= 0x7e)
384 unsigned octal0 = c & 0x7;
385 unsigned octal1 = (c >> 3) & 0x7;
386 unsigned octal2 = (c >> 3) & 0x7;
388 TextF("\\%u%u%u", octal2, octal1, octal0);
390 TextF("\\%u%u", octal1, octal0);
392 TextF("\\%u", octal0);
398 } /* namespace Log */