From d9c70e46f0461d434b218eeb0f0ca9363bd11750 Mon Sep 17 00:00:00 2001 From: "kipp%netscape.com" Date: Sat, 12 Sep 1998 19:25:06 +0000 Subject: [PATCH] new git-svn-id: svn://10.0.0.236/trunk@9945 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/xpcom/base/nsTraceRefcnt.cpp | 282 +++++++++++++++++++++++ mozilla/xpcom/base/nsTraceRefcntImpl.cpp | 282 +++++++++++++++++++++++ mozilla/xpcom/src/nsTraceRefcnt.cpp | 282 +++++++++++++++++++++++ mozilla/xpcom/src/nsTraceRefcnt.h | 59 +++++ 4 files changed, 905 insertions(+) create mode 100644 mozilla/xpcom/base/nsTraceRefcnt.cpp create mode 100644 mozilla/xpcom/base/nsTraceRefcntImpl.cpp create mode 100644 mozilla/xpcom/src/nsTraceRefcnt.cpp create mode 100644 mozilla/xpcom/src/nsTraceRefcnt.h diff --git a/mozilla/xpcom/base/nsTraceRefcnt.cpp b/mozilla/xpcom/base/nsTraceRefcnt.cpp new file mode 100644 index 00000000000..881d4f4284f --- /dev/null +++ b/mozilla/xpcom/base/nsTraceRefcnt.cpp @@ -0,0 +1,282 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ +#include "nsISupports.h" +#include "prprf.h" +#include "prlog.h" + +#if defined(_WIN32) +#include +#endif + +static PRLogModuleInfo* gTraceRefcntLog; + +static void InitTraceLog(void) +{ + if (0 == gTraceRefcntLog) { + gTraceRefcntLog = PR_NewLogModule("xpcomrefcnt"); + } +} + +#if defined(_WIN32) +#include "imagehlp.h" +#include + +#if 0 +static BOOL __stdcall +EnumSymbolsCB(LPSTR aSymbolName, + ULONG aSymbolAddress, + ULONG aSymbolSize, + PVOID aUserContext) +{ + int* countp = (int*) aUserContext; + int count = *countp; + if (count < 3) { + printf(" %p[%4d]: %s\n", aSymbolAddress, aSymbolSize, aSymbolName); + count++; + *countp = count++; + } + return TRUE; +} + +static BOOL __stdcall +EnumModulesCB(LPSTR aModuleName, + ULONG aBaseOfDll, + PVOID aUserContext) +{ + HANDLE myProcess = ::GetCurrentProcess(); + + printf("module=%s dll=%x\n", aModuleName, aBaseOfDll); +// int count = 0; +// SymEnumerateSymbols(myProcess, aBaseOfDll, EnumSymbolsCB, (void*) &count); + return TRUE; +} +#endif + +/** + * Walk the stack, translating PC's found into strings and recording the + * chain in aBuffer. For this to work properly, the dll's must be rebased + * so that the address in the file agrees with the address in memory. + * Otherwise StackWalk will return FALSE when it hits a frame in a dll's + * whose in memory address doesn't match it's in-file address. + * + * Fortunately, there is a handy dandy routine in IMAGEHLP.DLL that does + * the rebasing and accordingly I've made a tool to use it to rebase the + * DLL's in one fell swoop (see xpcom/tools/windows/rebasedlls.cpp). + */ +static void +WalkTheStack(char* aBuffer, int aBufLen) +{ + CONTEXT context; + STACKFRAME frame; + char* cp = aBuffer; + + aBuffer[0] = '\0'; + aBufLen--; // leave room for nul + + HANDLE myProcess = ::GetCurrentProcess(); + HANDLE myThread = ::GetCurrentThread(); + + // Get the context information for this thread. That way we will + // know where our sp, fp, pc, etc. are and can fill in the + // STACKFRAME with the initial values. + context.ContextFlags = CONTEXT_FULL; + GetThreadContext(myThread, &context); + + if (!SymInitialize(myProcess, ".;..\\lib", TRUE)) { + return; + } + +#if 0 + SymEnumerateModules(myProcess, EnumModulesCB, NULL); +#endif + + // Setup initial stack frame to walk from + memset(&frame, 0, sizeof(frame)); + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrPC.Offset = context.Eip; + frame.AddrReturn.Mode = AddrModeFlat; + frame.AddrReturn.Offset = context.Ebp; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context.Ebp; + frame.AddrStack.Mode = AddrModeFlat; + frame.AddrStack.Offset = context.Esp; + frame.Params[0] = context.Eax; + frame.Params[1] = context.Ecx; + frame.Params[2] = context.Edx; + frame.Params[3] = context.Ebx; + + // Now walk the stack and map the pc's to symbol names that we stuff + // append to *cp. + + int skip = 2; + int syms = 0; + while (aBufLen > 0) { + char symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 512]; + PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL) symbolBuffer; + pSymbol->SizeOfStruct = sizeof(symbolBuffer); + pSymbol->MaxNameLength = 512; + + DWORD oldAddress = frame.AddrPC.Offset; + BOOL b = ::StackWalk(IMAGE_FILE_MACHINE_I386, myProcess, myThread, + &frame, &context, NULL, + SymFunctionTableAccess, + SymGetModuleBase, + NULL); + if (!b || (0 == frame.AddrPC.Offset)) { + if (syms <= 1) { + skip = 7; + } + break; + } + if (--skip >= 0) { + continue; + } + DWORD disp; + if (SymGetSymFromAddr(myProcess, frame.AddrPC.Offset, &disp, pSymbol)) { + int nameLen = strlen(pSymbol->Name); + if (nameLen + 2 > aBufLen) { + break; + } + memcpy(cp, pSymbol->Name, nameLen); + cp += nameLen; + *cp++ = ' '; + aBufLen -= nameLen + 1; + syms++; + } + else { + if (11 > aBufLen) { + break; + } + char tmp[30]; + PR_snprintf(tmp, sizeof(tmp), "0x%08x ", frame.AddrPC.Offset); + memcpy(cp, tmp, 11); + cp += 11; + aBufLen -= 11; + syms++; + } + } + *cp = 0; +} + +#else /* _WIN32 */ +static void +WalkTheStack(char* aBuffer, int aBufLen) +{ + aBuffer[0] = '\0'; +} +#endif /* _WIN32 */ + +NS_COM void +nsTraceRefcnt::LoadLibrarySymbols(const char* aLibraryName, + void* aLibrayHandle) +{ +#ifdef MOZ_TRACE_XPCOM_REFCNT +#if defined(_WIN32) + HANDLE myProcess = ::GetCurrentProcess(); + + if (!SymInitialize(myProcess, ".;..\\lib", TRUE)) { + return; + } + + BOOL b = ::SymLoadModule(myProcess, + NULL, + (char*)aLibraryName, + (char*)aLibraryName, + 0, + 0); +// DWORD lastError = 0; +// if (!b) lastError = ::GetLastError(); +// printf("loading symbols for library %s => %s [%d]\n", aLibraryName, +// b ? "true" : "false", lastError); +#endif +#endif +} + +NS_COM unsigned long +nsTraceRefcnt::AddRef(void* aPtr, + unsigned long aNewRefcnt, + const char* aFile, + PRIntn aLine) +{ +#ifdef MOZ_TRACE_XPCOM_REFCNT + InitTraceLog(); + if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) { + char sb[1000]; + WalkTheStack(sb, sizeof(sb)); + PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG, + ("AddRef: %p: %d=>%d [%s] in %s (line %d)", + aPtr, aNewRefcnt-1, aNewRefcnt, sb, aFile, aLine)); + } +#endif + return aNewRefcnt; +} + +NS_COM unsigned long +nsTraceRefcnt::Release(void* aPtr, + unsigned long aNewRefcnt, + const char* aFile, + PRIntn aLine) +{ +#ifdef MOZ_TRACE_XPCOM_REFCNT + InitTraceLog(); + if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) { + char sb[1000]; + WalkTheStack(sb, sizeof(sb)); + PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG, + ("Release: %p: %d=>%d [%s] in %s (line %d)", + aPtr, aNewRefcnt+1, aNewRefcnt, sb, aFile, aLine)); + } +#endif + return aNewRefcnt; +} + +NS_COM void +nsTraceRefcnt::Create(void* aPtr, + const char* aType, + const char* aFile, + PRIntn aLine) +{ +#ifdef MOZ_TRACE_XPCOM_REFCNT + InitTraceLog(); + if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) { + char sb[1000]; + WalkTheStack(sb, sizeof(sb)); + PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG, + ("Create: %p[%s]: [%s] in %s (line %d)", + aPtr, aType, sb, aFile, aLine)); + } +#endif +} + +NS_COM void +nsTraceRefcnt::Destroy(void* aPtr, + const char* aFile, + PRIntn aLine) +{ +#ifdef MOZ_TRACE_XPCOM_REFCNT + InitTraceLog(); + if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) { + char sb[1000]; + WalkTheStack(sb, sizeof(sb)); + PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG, + ("Destroy: %p: [%s] in %s (line %d)", + aPtr, sb, aFile, aLine)); + } +#endif +} diff --git a/mozilla/xpcom/base/nsTraceRefcntImpl.cpp b/mozilla/xpcom/base/nsTraceRefcntImpl.cpp new file mode 100644 index 00000000000..881d4f4284f --- /dev/null +++ b/mozilla/xpcom/base/nsTraceRefcntImpl.cpp @@ -0,0 +1,282 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ +#include "nsISupports.h" +#include "prprf.h" +#include "prlog.h" + +#if defined(_WIN32) +#include +#endif + +static PRLogModuleInfo* gTraceRefcntLog; + +static void InitTraceLog(void) +{ + if (0 == gTraceRefcntLog) { + gTraceRefcntLog = PR_NewLogModule("xpcomrefcnt"); + } +} + +#if defined(_WIN32) +#include "imagehlp.h" +#include + +#if 0 +static BOOL __stdcall +EnumSymbolsCB(LPSTR aSymbolName, + ULONG aSymbolAddress, + ULONG aSymbolSize, + PVOID aUserContext) +{ + int* countp = (int*) aUserContext; + int count = *countp; + if (count < 3) { + printf(" %p[%4d]: %s\n", aSymbolAddress, aSymbolSize, aSymbolName); + count++; + *countp = count++; + } + return TRUE; +} + +static BOOL __stdcall +EnumModulesCB(LPSTR aModuleName, + ULONG aBaseOfDll, + PVOID aUserContext) +{ + HANDLE myProcess = ::GetCurrentProcess(); + + printf("module=%s dll=%x\n", aModuleName, aBaseOfDll); +// int count = 0; +// SymEnumerateSymbols(myProcess, aBaseOfDll, EnumSymbolsCB, (void*) &count); + return TRUE; +} +#endif + +/** + * Walk the stack, translating PC's found into strings and recording the + * chain in aBuffer. For this to work properly, the dll's must be rebased + * so that the address in the file agrees with the address in memory. + * Otherwise StackWalk will return FALSE when it hits a frame in a dll's + * whose in memory address doesn't match it's in-file address. + * + * Fortunately, there is a handy dandy routine in IMAGEHLP.DLL that does + * the rebasing and accordingly I've made a tool to use it to rebase the + * DLL's in one fell swoop (see xpcom/tools/windows/rebasedlls.cpp). + */ +static void +WalkTheStack(char* aBuffer, int aBufLen) +{ + CONTEXT context; + STACKFRAME frame; + char* cp = aBuffer; + + aBuffer[0] = '\0'; + aBufLen--; // leave room for nul + + HANDLE myProcess = ::GetCurrentProcess(); + HANDLE myThread = ::GetCurrentThread(); + + // Get the context information for this thread. That way we will + // know where our sp, fp, pc, etc. are and can fill in the + // STACKFRAME with the initial values. + context.ContextFlags = CONTEXT_FULL; + GetThreadContext(myThread, &context); + + if (!SymInitialize(myProcess, ".;..\\lib", TRUE)) { + return; + } + +#if 0 + SymEnumerateModules(myProcess, EnumModulesCB, NULL); +#endif + + // Setup initial stack frame to walk from + memset(&frame, 0, sizeof(frame)); + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrPC.Offset = context.Eip; + frame.AddrReturn.Mode = AddrModeFlat; + frame.AddrReturn.Offset = context.Ebp; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context.Ebp; + frame.AddrStack.Mode = AddrModeFlat; + frame.AddrStack.Offset = context.Esp; + frame.Params[0] = context.Eax; + frame.Params[1] = context.Ecx; + frame.Params[2] = context.Edx; + frame.Params[3] = context.Ebx; + + // Now walk the stack and map the pc's to symbol names that we stuff + // append to *cp. + + int skip = 2; + int syms = 0; + while (aBufLen > 0) { + char symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 512]; + PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL) symbolBuffer; + pSymbol->SizeOfStruct = sizeof(symbolBuffer); + pSymbol->MaxNameLength = 512; + + DWORD oldAddress = frame.AddrPC.Offset; + BOOL b = ::StackWalk(IMAGE_FILE_MACHINE_I386, myProcess, myThread, + &frame, &context, NULL, + SymFunctionTableAccess, + SymGetModuleBase, + NULL); + if (!b || (0 == frame.AddrPC.Offset)) { + if (syms <= 1) { + skip = 7; + } + break; + } + if (--skip >= 0) { + continue; + } + DWORD disp; + if (SymGetSymFromAddr(myProcess, frame.AddrPC.Offset, &disp, pSymbol)) { + int nameLen = strlen(pSymbol->Name); + if (nameLen + 2 > aBufLen) { + break; + } + memcpy(cp, pSymbol->Name, nameLen); + cp += nameLen; + *cp++ = ' '; + aBufLen -= nameLen + 1; + syms++; + } + else { + if (11 > aBufLen) { + break; + } + char tmp[30]; + PR_snprintf(tmp, sizeof(tmp), "0x%08x ", frame.AddrPC.Offset); + memcpy(cp, tmp, 11); + cp += 11; + aBufLen -= 11; + syms++; + } + } + *cp = 0; +} + +#else /* _WIN32 */ +static void +WalkTheStack(char* aBuffer, int aBufLen) +{ + aBuffer[0] = '\0'; +} +#endif /* _WIN32 */ + +NS_COM void +nsTraceRefcnt::LoadLibrarySymbols(const char* aLibraryName, + void* aLibrayHandle) +{ +#ifdef MOZ_TRACE_XPCOM_REFCNT +#if defined(_WIN32) + HANDLE myProcess = ::GetCurrentProcess(); + + if (!SymInitialize(myProcess, ".;..\\lib", TRUE)) { + return; + } + + BOOL b = ::SymLoadModule(myProcess, + NULL, + (char*)aLibraryName, + (char*)aLibraryName, + 0, + 0); +// DWORD lastError = 0; +// if (!b) lastError = ::GetLastError(); +// printf("loading symbols for library %s => %s [%d]\n", aLibraryName, +// b ? "true" : "false", lastError); +#endif +#endif +} + +NS_COM unsigned long +nsTraceRefcnt::AddRef(void* aPtr, + unsigned long aNewRefcnt, + const char* aFile, + PRIntn aLine) +{ +#ifdef MOZ_TRACE_XPCOM_REFCNT + InitTraceLog(); + if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) { + char sb[1000]; + WalkTheStack(sb, sizeof(sb)); + PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG, + ("AddRef: %p: %d=>%d [%s] in %s (line %d)", + aPtr, aNewRefcnt-1, aNewRefcnt, sb, aFile, aLine)); + } +#endif + return aNewRefcnt; +} + +NS_COM unsigned long +nsTraceRefcnt::Release(void* aPtr, + unsigned long aNewRefcnt, + const char* aFile, + PRIntn aLine) +{ +#ifdef MOZ_TRACE_XPCOM_REFCNT + InitTraceLog(); + if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) { + char sb[1000]; + WalkTheStack(sb, sizeof(sb)); + PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG, + ("Release: %p: %d=>%d [%s] in %s (line %d)", + aPtr, aNewRefcnt+1, aNewRefcnt, sb, aFile, aLine)); + } +#endif + return aNewRefcnt; +} + +NS_COM void +nsTraceRefcnt::Create(void* aPtr, + const char* aType, + const char* aFile, + PRIntn aLine) +{ +#ifdef MOZ_TRACE_XPCOM_REFCNT + InitTraceLog(); + if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) { + char sb[1000]; + WalkTheStack(sb, sizeof(sb)); + PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG, + ("Create: %p[%s]: [%s] in %s (line %d)", + aPtr, aType, sb, aFile, aLine)); + } +#endif +} + +NS_COM void +nsTraceRefcnt::Destroy(void* aPtr, + const char* aFile, + PRIntn aLine) +{ +#ifdef MOZ_TRACE_XPCOM_REFCNT + InitTraceLog(); + if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) { + char sb[1000]; + WalkTheStack(sb, sizeof(sb)); + PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG, + ("Destroy: %p: [%s] in %s (line %d)", + aPtr, sb, aFile, aLine)); + } +#endif +} diff --git a/mozilla/xpcom/src/nsTraceRefcnt.cpp b/mozilla/xpcom/src/nsTraceRefcnt.cpp new file mode 100644 index 00000000000..881d4f4284f --- /dev/null +++ b/mozilla/xpcom/src/nsTraceRefcnt.cpp @@ -0,0 +1,282 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ +#include "nsISupports.h" +#include "prprf.h" +#include "prlog.h" + +#if defined(_WIN32) +#include +#endif + +static PRLogModuleInfo* gTraceRefcntLog; + +static void InitTraceLog(void) +{ + if (0 == gTraceRefcntLog) { + gTraceRefcntLog = PR_NewLogModule("xpcomrefcnt"); + } +} + +#if defined(_WIN32) +#include "imagehlp.h" +#include + +#if 0 +static BOOL __stdcall +EnumSymbolsCB(LPSTR aSymbolName, + ULONG aSymbolAddress, + ULONG aSymbolSize, + PVOID aUserContext) +{ + int* countp = (int*) aUserContext; + int count = *countp; + if (count < 3) { + printf(" %p[%4d]: %s\n", aSymbolAddress, aSymbolSize, aSymbolName); + count++; + *countp = count++; + } + return TRUE; +} + +static BOOL __stdcall +EnumModulesCB(LPSTR aModuleName, + ULONG aBaseOfDll, + PVOID aUserContext) +{ + HANDLE myProcess = ::GetCurrentProcess(); + + printf("module=%s dll=%x\n", aModuleName, aBaseOfDll); +// int count = 0; +// SymEnumerateSymbols(myProcess, aBaseOfDll, EnumSymbolsCB, (void*) &count); + return TRUE; +} +#endif + +/** + * Walk the stack, translating PC's found into strings and recording the + * chain in aBuffer. For this to work properly, the dll's must be rebased + * so that the address in the file agrees with the address in memory. + * Otherwise StackWalk will return FALSE when it hits a frame in a dll's + * whose in memory address doesn't match it's in-file address. + * + * Fortunately, there is a handy dandy routine in IMAGEHLP.DLL that does + * the rebasing and accordingly I've made a tool to use it to rebase the + * DLL's in one fell swoop (see xpcom/tools/windows/rebasedlls.cpp). + */ +static void +WalkTheStack(char* aBuffer, int aBufLen) +{ + CONTEXT context; + STACKFRAME frame; + char* cp = aBuffer; + + aBuffer[0] = '\0'; + aBufLen--; // leave room for nul + + HANDLE myProcess = ::GetCurrentProcess(); + HANDLE myThread = ::GetCurrentThread(); + + // Get the context information for this thread. That way we will + // know where our sp, fp, pc, etc. are and can fill in the + // STACKFRAME with the initial values. + context.ContextFlags = CONTEXT_FULL; + GetThreadContext(myThread, &context); + + if (!SymInitialize(myProcess, ".;..\\lib", TRUE)) { + return; + } + +#if 0 + SymEnumerateModules(myProcess, EnumModulesCB, NULL); +#endif + + // Setup initial stack frame to walk from + memset(&frame, 0, sizeof(frame)); + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrPC.Offset = context.Eip; + frame.AddrReturn.Mode = AddrModeFlat; + frame.AddrReturn.Offset = context.Ebp; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context.Ebp; + frame.AddrStack.Mode = AddrModeFlat; + frame.AddrStack.Offset = context.Esp; + frame.Params[0] = context.Eax; + frame.Params[1] = context.Ecx; + frame.Params[2] = context.Edx; + frame.Params[3] = context.Ebx; + + // Now walk the stack and map the pc's to symbol names that we stuff + // append to *cp. + + int skip = 2; + int syms = 0; + while (aBufLen > 0) { + char symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 512]; + PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL) symbolBuffer; + pSymbol->SizeOfStruct = sizeof(symbolBuffer); + pSymbol->MaxNameLength = 512; + + DWORD oldAddress = frame.AddrPC.Offset; + BOOL b = ::StackWalk(IMAGE_FILE_MACHINE_I386, myProcess, myThread, + &frame, &context, NULL, + SymFunctionTableAccess, + SymGetModuleBase, + NULL); + if (!b || (0 == frame.AddrPC.Offset)) { + if (syms <= 1) { + skip = 7; + } + break; + } + if (--skip >= 0) { + continue; + } + DWORD disp; + if (SymGetSymFromAddr(myProcess, frame.AddrPC.Offset, &disp, pSymbol)) { + int nameLen = strlen(pSymbol->Name); + if (nameLen + 2 > aBufLen) { + break; + } + memcpy(cp, pSymbol->Name, nameLen); + cp += nameLen; + *cp++ = ' '; + aBufLen -= nameLen + 1; + syms++; + } + else { + if (11 > aBufLen) { + break; + } + char tmp[30]; + PR_snprintf(tmp, sizeof(tmp), "0x%08x ", frame.AddrPC.Offset); + memcpy(cp, tmp, 11); + cp += 11; + aBufLen -= 11; + syms++; + } + } + *cp = 0; +} + +#else /* _WIN32 */ +static void +WalkTheStack(char* aBuffer, int aBufLen) +{ + aBuffer[0] = '\0'; +} +#endif /* _WIN32 */ + +NS_COM void +nsTraceRefcnt::LoadLibrarySymbols(const char* aLibraryName, + void* aLibrayHandle) +{ +#ifdef MOZ_TRACE_XPCOM_REFCNT +#if defined(_WIN32) + HANDLE myProcess = ::GetCurrentProcess(); + + if (!SymInitialize(myProcess, ".;..\\lib", TRUE)) { + return; + } + + BOOL b = ::SymLoadModule(myProcess, + NULL, + (char*)aLibraryName, + (char*)aLibraryName, + 0, + 0); +// DWORD lastError = 0; +// if (!b) lastError = ::GetLastError(); +// printf("loading symbols for library %s => %s [%d]\n", aLibraryName, +// b ? "true" : "false", lastError); +#endif +#endif +} + +NS_COM unsigned long +nsTraceRefcnt::AddRef(void* aPtr, + unsigned long aNewRefcnt, + const char* aFile, + PRIntn aLine) +{ +#ifdef MOZ_TRACE_XPCOM_REFCNT + InitTraceLog(); + if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) { + char sb[1000]; + WalkTheStack(sb, sizeof(sb)); + PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG, + ("AddRef: %p: %d=>%d [%s] in %s (line %d)", + aPtr, aNewRefcnt-1, aNewRefcnt, sb, aFile, aLine)); + } +#endif + return aNewRefcnt; +} + +NS_COM unsigned long +nsTraceRefcnt::Release(void* aPtr, + unsigned long aNewRefcnt, + const char* aFile, + PRIntn aLine) +{ +#ifdef MOZ_TRACE_XPCOM_REFCNT + InitTraceLog(); + if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) { + char sb[1000]; + WalkTheStack(sb, sizeof(sb)); + PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG, + ("Release: %p: %d=>%d [%s] in %s (line %d)", + aPtr, aNewRefcnt+1, aNewRefcnt, sb, aFile, aLine)); + } +#endif + return aNewRefcnt; +} + +NS_COM void +nsTraceRefcnt::Create(void* aPtr, + const char* aType, + const char* aFile, + PRIntn aLine) +{ +#ifdef MOZ_TRACE_XPCOM_REFCNT + InitTraceLog(); + if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) { + char sb[1000]; + WalkTheStack(sb, sizeof(sb)); + PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG, + ("Create: %p[%s]: [%s] in %s (line %d)", + aPtr, aType, sb, aFile, aLine)); + } +#endif +} + +NS_COM void +nsTraceRefcnt::Destroy(void* aPtr, + const char* aFile, + PRIntn aLine) +{ +#ifdef MOZ_TRACE_XPCOM_REFCNT + InitTraceLog(); + if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) { + char sb[1000]; + WalkTheStack(sb, sizeof(sb)); + PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG, + ("Destroy: %p: [%s] in %s (line %d)", + aPtr, sb, aFile, aLine)); + } +#endif +} diff --git a/mozilla/xpcom/src/nsTraceRefcnt.h b/mozilla/xpcom/src/nsTraceRefcnt.h new file mode 100644 index 00000000000..36b04d031c2 --- /dev/null +++ b/mozilla/xpcom/src/nsTraceRefcnt.h @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ +#ifndef nsTraceRefcnt_h___ +#define nsTraceRefcnt_h___ + +#include "nsCom.h" + +/** + * This class is used to support tracing (and logging using nspr) of + * addref and release calls. Note that only calls that use the + * NS_ADDREF and related macros in nsISupports can be traced. + * + * The name of the nspr log module is "xpcomrefcnt" (case matters). + * + * This code only performs tracing built with debugging AND when + * built with -DMOZ_TRACE_XPCOM_REFCNT (because it's expensive!). + */ +class nsTraceRefcnt { +public: + static NS_COM unsigned long AddRef(void* aPtr, + unsigned long aNewRefcnt, + const char* aFile, + int aLine); + + static NS_COM unsigned long Release(void* aPtr, + unsigned long aNewRefcnt, + const char* aFile, + int aLine); + + static NS_COM void Create(void* aPtr, + const char* aType, + const char* aFile, + int aLine); + + static NS_COM void Destroy(void* aPtr, + const char* aFile, + int aLine); + + static NS_COM void LoadLibrarySymbols(const char* aLibraryName, + void* aLibrayHandle); +}; + +#endif /* nsTraceRefcnt_h___ */