From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/debug_8cpp-source.html | 1083 +++++++++++++++++++++++++++++++ 1 file changed, 1083 insertions(+) create mode 100644 docs/doxygen/nel/debug_8cpp-source.html (limited to 'docs/doxygen/nel/debug_8cpp-source.html') diff --git a/docs/doxygen/nel/debug_8cpp-source.html b/docs/doxygen/nel/debug_8cpp-source.html new file mode 100644 index 00000000..55add418 --- /dev/null +++ b/docs/doxygen/nel/debug_8cpp-source.html @@ -0,0 +1,1083 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# Home   # nevrax.com   
+ + + + +
Nevrax
+ + + + + + + + + + +
+ + +
+ Nevrax.org
+ + + + + + + +
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
+
+ + +
+ + +
+Docs + +
+  + + + + + +
Documentation 
+ +
+Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  
+

debug.cpp

Go to the documentation of this file.
00001 
+00007 /* Copyright, 2000 Nevrax Ltd.
+00008  *
+00009  * This file is part of NEVRAX NEL.
+00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
+00011  * it under the terms of the GNU General Public License as published by
+00012  * the Free Software Foundation; either version 2, or (at your option)
+00013  * any later version.
+00014 
+00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
+00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
+00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+00018  * General Public License for more details.
+00019 
+00020  * You should have received a copy of the GNU General Public License
+00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
+00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+00023  * MA 02111-1307, USA.
+00024  */
+00025 
+00026 #ifdef HAVE_NELCONFIG_H
+00027 #  include "nelconfig.h"
+00028 #endif // HAVE_NELCONFIG_H
+00029 
+00030 #include "stdmisc.h"
+00031 #include "nel/misc/log.h"
+00032 #include "nel/misc/displayer.h"
+00033 #include "nel/misc/mem_displayer.h"
+00034 #include "nel/misc/command.h"
+00035 #include "nel/misc/report.h"
+00036 #include "nel/misc/path.h"
+00037 
+00038 #ifdef NL_OS_WINDOWS
+00039 #       define _WIN32_WINDOWS   0x0410
+00040 #       define WINVER                   0x0400
+00041 #       include <windows.h>
+00042 #       include <direct.h>
+00043 #       include <imagehlp.h>
+00044 #       pragma comment(lib, "imagehlp.lib")
+00045 #       define getcwd(_a, _b) (_getcwd(_a,_b))
+00046 #elif defined NL_OS_UNIX
+00047 #       include <unistd.h>
+00048 #       include <stdio.h>
+00049 #       include <stdlib.h>
+00050 #       define IsDebuggerPresent() false
+00051 #endif
+00052 
+00053 #include <stdarg.h>
+00054 #include <iostream>
+00055 
+00056 using namespace std;
+00057  
+00058 // If you don't want to add default displayer, put 0 instead of 1. In this case, you
+00059 // have to manage yourself displayer (in final release for example, we have to put 0)
+00060 // Alternatively, you can use --without-logging when using configure to set
+00061 // it to 0.
+00062 #ifndef NEL_DEFAULT_DISPLAYER
+00063 #define NEL_DEFAULT_DISPLAYER 1
+00064 #endif // NEL_DEFAULT_DISPLAYER
+00065 
+00066 // Put 0 if you don't want to display in file "log.log"
+00067 // Alternatively, you can use --without-logging when using configure to set
+00068 // it to 0.
+00069 #ifndef NEL_LOG_IN_FILE
+00070 #define NEL_LOG_IN_FILE 1
+00071 #endif // NEL_LOG_IN_FILE
+00072 
+00073 #define DEFAULT_DISPLAYER NEL_DEFAULT_DISPLAYER
+00074 
+00075 #define LOG_IN_FILE NEL_LOG_IN_FILE
+00076 
+00077 // If true, debug system will trap crashs even if the appli is in debugger
+00078 static const bool TrapCrashInDebugger = false;
+00079 
+00080 namespace NLMISC 
+00081 {
+00082 
+00083 // Need an assert in the macro
+00084 bool DebugNeedAssert = false;
+00085 
+00086 CLog *ErrorLog = NULL;
+00087 CLog *WarningLog = NULL;
+00088 CLog *InfoLog = NULL;
+00089 CLog *DebugLog = NULL;
+00090 CLog *AssertLog = NULL;
+00091 
+00092 CMemDisplayer *DefaultMemDisplayer = NULL;
+00093 CMsgBoxDisplayer *DefaultMsgBoxDisplayer = NULL;
+00094 
+00095 static CStdDisplayer *sd = NULL;
+00096 static CFileDisplayer *fd = NULL;
+00097 
+00098 void nlFatalError (const char *format, ...)
+00099 {
+00100         char *str;
+00101         NLMISC_CONVERT_VARGS (str, format, 256/*NLMISC::MaxCStringSize*/);
+00102 
+00103         NLMISC::DebugNeedAssert = NLMISC::DefaultMsgBoxDisplayer==0;
+00104 
+00105         NLMISC::ErrorLog->displayNL (str);
+00106 
+00107         if (NLMISC::DebugNeedAssert)
+00108                 NLMISC_BREAKPOINT;
+00109 
+00110 #ifndef NL_OS_WINDOWS
+00111         exit(EXIT_FAILURE);
+00112 #endif
+00113 
+00114 }
+00115 
+00116 void nlError (const char *format, ...)
+00117 {
+00118         char *str;
+00119         NLMISC_CONVERT_VARGS (str, format, 256/*NLMISC::MaxCStringSize*/);
+00120 
+00121         NLMISC::DebugNeedAssert = NLMISC::DefaultMsgBoxDisplayer==0;
+00122 
+00123         NLMISC::ErrorLog->displayNL (str);
+00124 
+00125         if (NLMISC::DebugNeedAssert)
+00126                 NLMISC_BREAKPOINT;
+00127 
+00128 #ifndef NL_OS_WINDOWS
+00129         exit(EXIT_FAILURE);
+00130 #endif
+00131 }
+00132 
+00133 // the default behavior is to display all in standard output and to a file named "log.log";
+00134 
+00135 void initDebug2 (bool logInFile)
+00136 {
+00137         static bool alreadyInit = false;
+00138 
+00139         if (!alreadyInit)
+00140         {
+00141 #if DEFAULT_DISPLAYER
+00142 
+00143                 // put the standard displayer everywhere
+00144 
+00145 #ifdef NL_DEBUG
+00146                 DebugLog->addDisplayer (sd);
+00147 #endif // NL_DEBUG
+00148                 InfoLog->addDisplayer (sd);
+00149                 WarningLog->addDisplayer (sd);
+00150                 AssertLog->addDisplayer (sd);
+00151                 ErrorLog->addDisplayer (sd);
+00152 
+00153                 // put the memory displayer everywhere
+00154 
+00155                 // use the memory displayer and bypass all filter (even for the debug mode)
+00156                 DebugLog->addDisplayer (DefaultMemDisplayer, true);
+00157                 InfoLog->addDisplayer (DefaultMemDisplayer, true);
+00158                 WarningLog->addDisplayer (DefaultMemDisplayer, true);
+00159                 AssertLog->addDisplayer (DefaultMemDisplayer, true);
+00160                 ErrorLog->addDisplayer (DefaultMemDisplayer, true);
+00161 
+00162                 // put the file displayer only if wanted
+00163 
+00164 #if LOG_IN_FILE
+00165                 if (logInFile)
+00166                 {
+00167 #ifdef NL_DEBUG
+00168                         DebugLog->addDisplayer (fd);
+00169 #endif // NL_DEBUG
+00170                         InfoLog->addDisplayer (fd);
+00171                         WarningLog->addDisplayer (fd);
+00172                         AssertLog->addDisplayer (fd);
+00173                         ErrorLog->addDisplayer (fd);
+00174                 }
+00175 #endif // LOG_IN_FILE
+00176 
+00177                 // put the message box only in release for error
+00178 
+00179                 if (TrapCrashInDebugger || !IsDebuggerPresent ())
+00180                 {
+00181                         AssertLog->addDisplayer (DefaultMsgBoxDisplayer);
+00182                         ErrorLog->addDisplayer (DefaultMsgBoxDisplayer);
+00183                 }
+00184 
+00185 #endif // DEFAULT_DISPLAYER
+00186                 alreadyInit = true;
+00187         }
+00188         else
+00189         {
+00190                 nlwarning ("NLMISC::initDebug2() already called");
+00191         }
+00192 }
+00193 
+00194 
+00195 #ifdef NL_OS_WINDOWS
+00196 
+00197 //
+00198 //
+00199 //
+00200 
+00201 static DWORD __stdcall GetModuleBase(HANDLE hProcess, DWORD dwReturnAddress)
+00202 {
+00203         IMAGEHLP_MODULE moduleInfo;
+00204 
+00205         if (SymGetModuleInfo(hProcess, dwReturnAddress, &moduleInfo))
+00206                 return moduleInfo.BaseOfImage;
+00207         else
+00208         {
+00209                 MEMORY_BASIC_INFORMATION memoryBasicInfo;
+00210 
+00211                 if (::VirtualQueryEx(hProcess, (LPVOID) dwReturnAddress,
+00212                         &memoryBasicInfo, sizeof(memoryBasicInfo)))
+00213                 {
+00214                         DWORD cch = 0;
+00215                         char szFile[MAX_PATH] = { 0 };
+00216 
+00217                  cch = GetModuleFileNameA((HINSTANCE)memoryBasicInfo.AllocationBase,
+00218                                                                  szFile, MAX_PATH);
+00219 
+00220                 if (cch && (lstrcmp(szFile, "DBFN")== 0))
+00221                 {
+00222                          if (!SymLoadModule(hProcess,
+00223                                    NULL, "MN",
+00224                                    NULL, (DWORD) memoryBasicInfo.AllocationBase, 0))
+00225                                 {
+00226                                         DWORD dwError = GetLastError();
+00227 //                                      nlinfo("Error: %d", dwError);
+00228                                 }
+00229                 }
+00230                 else
+00231                 {
+00232                  if (!SymLoadModule(hProcess,
+00233                            NULL, ((cch) ? szFile : NULL),
+00234                            NULL, (DWORD) memoryBasicInfo.AllocationBase, 0))
+00235                         {
+00236                                 DWORD dwError = GetLastError();
+00237 //                              nlinfo("Error: %d", dwError);
+00238                          }
+00239 
+00240                 }
+00241 
+00242                  return (DWORD) memoryBasicInfo.AllocationBase;
+00243           }
+00244 //              else
+00245 //                      nlinfo("Error is %d", GetLastError());
+00246         }
+00247 
+00248         return 0;
+00249 }
+00250 
+00251 LPVOID __stdcall FunctionTableAccess (HANDLE hProcess, DWORD AddrBase)
+00252 {
+00253         AddrBase = 0x40291f;
+00254         DWORD addr = SymGetModuleBase (hProcess, AddrBase);
+00255         HRESULT hr = GetLastError ();
+00256         
+00257         IMAGEHLP_MODULE moduleInfo;
+00258         moduleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
+00259         SymGetModuleInfo(hProcess, addr, &moduleInfo);
+00260         hr = GetLastError ();
+00261         SymLoadModule(hProcess, NULL, NULL, NULL, 0, 0);
+00262         hr = GetLastError ();
+00263 
+00264         LPVOID temp = SymFunctionTableAccess (hProcess, AddrBase);
+00265         hr = GetLastError ();
+00266         return temp;
+00267 }
+00268 
+00269 class EDebug : public ETrapDebug
+00270 {
+00271 public: 
+00272         
+00273         EDebug() { _Reason = "Nothing about EDebug"; }
+00274 
+00275         ~EDebug () { }
+00276 
+00277         EDebug(EXCEPTION_POINTERS * pexp) : m_pexp(pexp) { nlassert(pexp != 0); createWhat(); }
+00278         EDebug(const EDebug& se) : m_pexp(se.m_pexp) { createWhat(); }
+00279 
+00280         void createWhat ()
+00281         {
+00282                 string shortExc, longExc, subject;
+00283                 string addr, ext;
+00284                 sint skipNFirst = 0;
+00285                 _Reason = "";
+00286 
+00287                 if (m_pexp == NULL)
+00288                 {
+00289                         _Reason = "Unknown exception, don't have context.";
+00290                 }
+00291                 else
+00292                 {
+00293                         switch (m_pexp->ExceptionRecord->ExceptionCode)
+00294                         {
+00295                         case EXCEPTION_ACCESS_VIOLATION          : shortExc="Access Violation"; longExc="The thread attempted to read from or write to a virtual address for which it does not have the appropriate access";
+00296                                 ext = ", thread attempts to ";
+00297                                 ext += m_pexp->ExceptionRecord->ExceptionInformation[0]?"write":"read";
+00298                                 if (m_pexp->ExceptionRecord->ExceptionInformation[1])
+00299                                         ext += toString(" at 0x%X",m_pexp->ExceptionRecord->ExceptionInformation[1]);
+00300                                 else
+00301                                         ext += " at <NULL>";
+00302                                 break;
+00303                         case EXCEPTION_DATATYPE_MISALIGNMENT     : shortExc="Datatype Misalignment"; longExc="The thread attempted to read or write data that is misaligned on hardware that does not provide alignment. For example, 16-bit values must be aligned on 2-byte boundaries, 32-bit values on 4-byte boundaries, and so on"; break;
+00304                         case EXCEPTION_BREAKPOINT                : shortExc="Breakpoint"; longExc="A breakpoint was encountered"; break;
+00305                         case EXCEPTION_SINGLE_STEP               : shortExc="Single Step"; longExc="A trace trap or other single-instruction mechanism signaled that one instruction has been executed"; break;
+00306                         case EXCEPTION_ARRAY_BOUNDS_EXCEEDED     : shortExc="Array Bounds Exceeded"; longExc="The thread attempted to access an array element that is out of bounds, and the underlying hardware supports bounds checking"; break;
+00307                         case EXCEPTION_FLT_DENORMAL_OPERAND      : shortExc="Float Denormal Operand"; longExc="One of the operands in a floating-point operation is denormal. A denormal value is one that is too small to represent as a standard floating-point value"; break;
+00308                         case EXCEPTION_FLT_DIVIDE_BY_ZERO        : shortExc="Float Divide By Zero"; longExc="The thread attempted to divide a floating-point value by a floating-point divisor of zero"; break;
+00309                         case EXCEPTION_FLT_INEXACT_RESULT        : shortExc="Float Inexact Result"; longExc="The result of a floating-point operation cannot be represented exactly as a decimal fraction"; break;
+00310                         case EXCEPTION_FLT_INVALID_OPERATION     : shortExc="Float Invalid Operation"; longExc="This exception represents any floating-point exception not included in this list"; break;
+00311                         case EXCEPTION_FLT_OVERFLOW              : shortExc="Float Overflow"; longExc="The exponent of a floating-point operation is greater than the magnitude allowed by the corresponding type"; break;
+00312                         case EXCEPTION_FLT_STACK_CHECK           : shortExc="Float Stack Check"; longExc="The stack overflowed or underflowed as the result of a floating-point operation"; break;
+00313                         case EXCEPTION_FLT_UNDERFLOW             : shortExc="Float Underflow"; longExc="The exponent of a floating-point operation is less than the magnitude allowed by the corresponding type"; break;
+00314                         case EXCEPTION_INT_DIVIDE_BY_ZERO        : shortExc="Integer Divide By Zero"; longExc="The thread attempted to divide an integer value by an integer divisor of zero"; break;
+00315                         case EXCEPTION_INT_OVERFLOW              : shortExc="Integer Overflow"; longExc="The result of an integer operation caused a carry out of the most significant bit of the result"; break;
+00316                         case EXCEPTION_PRIV_INSTRUCTION          : shortExc="Privileged Instruction"; longExc="The thread attempted to execute an instruction whose operation is not allowed in the current machine mode"; break;
+00317                         case EXCEPTION_IN_PAGE_ERROR             : shortExc="In Page Error"; longExc="The thread tried to access a page that was not present, and the system was unable to load the page. -ie. the program or memory mapped file couldn't be paged in because it isn't accessable any more. Device drivers can return this exception if something went wrong with the read (i.e hardware problems)"; break;
+00318                         case EXCEPTION_ILLEGAL_INSTRUCTION       : shortExc="Illegal Instruction"; longExc="The thread tried to execute an invalid instruction -such as MMX opcodes on a non MMX system. Branching to an invalid location can cause this -something stack corruption often causes"; break;
+00319                         case EXCEPTION_NONCONTINUABLE_EXCEPTION  : shortExc="Noncontinuable Exception"; longExc="The thread attempted to continue execution after a noncontinuable exception occurred"; break;
+00320                         case EXCEPTION_STACK_OVERFLOW            : shortExc="Stack Overflow"; longExc="Stack overflow. Can occur during errant recursion, or when a function creates a particularly large array on the stack"; break;
+00321                         case EXCEPTION_INVALID_DISPOSITION       : shortExc="Invalid Disposition"; longExc="Whatever number the exception filter returned, it wasn't a value the OS knows about"; break;
+00322                         case EXCEPTION_GUARD_PAGE                : shortExc="Guard Page"; longExc="Memory Allocated as PAGE_GUARD by VirtualAlloc() has been accessed"; break;
+00323                         case EXCEPTION_INVALID_HANDLE            : shortExc="Invalid Handle"; longExc=""; break;
+00324                         case CONTROL_C_EXIT                      : shortExc="Control-C"; longExc="Lets the debugger know the user hit Ctrl-C. Seemingly for console apps only"; break;
+00325                         case STATUS_NO_MEMORY                    : shortExc="No Memory"; longExc="Called by HeapAlloc() if you specify HEAP_GENERATE_EXCEPTIONS and there is no memory or heap corruption";
+00326                                 ext = ", unable to allocate ";
+00327                                 ext += toString ("%d bytes", m_pexp->ExceptionRecord->ExceptionInformation [0]);
+00328                                 break;
+00329                         case STATUS_WAIT_0                       : shortExc="Wait 0"; longExc=""; break;
+00330                         case STATUS_ABANDONED_WAIT_0             : shortExc="Abandoned Wait 0"; longExc=""; break;
+00331                         case STATUS_USER_APC                     : shortExc="User APC"; longExc="A user APC was delivered to the current thread before the specified Timeout interval expired"; break;
+00332                         case STATUS_TIMEOUT                      : shortExc="Timeout"; longExc=""; break;
+00333                         case STATUS_PENDING                      : shortExc="Pending"; longExc=""; break;
+00334                         case STATUS_SEGMENT_NOTIFICATION         : shortExc="Segment Notification"; longExc=""; break;
+00335                         case STATUS_FLOAT_MULTIPLE_FAULTS        : shortExc="Float Multiple Faults"; longExc=""; break;
+00336                         case STATUS_FLOAT_MULTIPLE_TRAPS         : shortExc="Float Multiple Traps"; longExc=""; break;
+00337                         case STATUS_ILLEGAL_VLM_REFERENCE        : shortExc="Illegal VLM Reference"; longExc=""; break;
+00338                         case 0xE06D7363                          : shortExc="Microsoft C++ Exception"; longExc="Microsoft C++ Exception"; break;        // cpp exception
+00339                         case 0xACE0ACE                           : shortExc=""; longExc="";
+00340                                 if (m_pexp->ExceptionRecord->NumberParameters == 1)
+00341                                         skipNFirst = m_pexp->ExceptionRecord->ExceptionInformation [0];
+00342                                 break;  // just want the stack
+00343                         default                                  : shortExc="Unknown Exception"; longExc="Unknown Exception "+toString("0x%X", m_pexp->ExceptionRecord->ExceptionCode); break;
+00344                         };
+00345 
+00346                         if(m_pexp->ExceptionRecord != NULL)
+00347                         {
+00348                                 if (m_pexp->ExceptionRecord->ExceptionAddress)
+00349                                         addr = toString(" at 0x%X", m_pexp->ExceptionRecord->ExceptionAddress);
+00350                                 else
+00351                                         addr = " at <NULL>";
+00352                         }
+00353 
+00354                         string progname;
+00355                         if(!shortExc.empty() || !longExc.empty())
+00356                         {
+00357                                 char name[1024];
+00358                                 GetModuleFileName (NULL, name, 1023);
+00359                                 progname = CFile::getFilename(name);
+00360                                 progname += " ";
+00361                         }
+00362 
+00363                         subject = progname + shortExc + addr;
+00364 
+00365                         if (_Reason.empty())
+00366                         {
+00367                                 if (!shortExc.empty()) _Reason += shortExc + " exception generated" + addr + ext + ".\n";
+00368                                 if (!longExc.empty()) _Reason += longExc + ".\n";
+00369                         }
+00370 
+00371                         // display the stack
+00372                         addStackAndLogToReason (skipNFirst);
+00373 
+00374                         if(!shortExc.empty() || !longExc.empty())
+00375                         {
+00376                                 bool i = false;
+00377                                 report (progname+shortExc, "", subject, _Reason, true, 1, true, 1, true, i);
+00378                         }
+00379                 }
+00380         }
+00381 
+00382         // display the callstack
+00383         void addStackAndLogToReason (sint skipNFirst = 0)
+00384         {
+00385                 // ace hack
+00386                 skipNFirst = 0;
+00387                 
+00388                 DWORD symOptions = SymGetOptions();
+00389                 symOptions |= SYMOPT_LOAD_LINES;
+00390                 symOptions &= ~SYMOPT_UNDNAME;
+00391                 SymSetOptions (symOptions);
+00392                 
+00393                 nlverify (SymInitialize(getProcessHandle(), NULL, FALSE) == TRUE);
+00394 
+00395                 STACKFRAME callStack;
+00396                 ::ZeroMemory (&callStack, sizeof(callStack));
+00397                 callStack.AddrPC.Mode      = AddrModeFlat;
+00398                 callStack.AddrPC.Offset    = m_pexp->ContextRecord->Eip;
+00399                 callStack.AddrStack.Mode   = AddrModeFlat;
+00400                 callStack.AddrStack.Offset = m_pexp->ContextRecord->Esp;
+00401                 callStack.AddrFrame.Mode   = AddrModeFlat;
+00402                 callStack.AddrFrame.Offset = m_pexp->ContextRecord->Ebp;
+00403 
+00404                 _Reason += "\nCallstack:\n";
+00405                 _Reason += "-------------------------------\n";
+00406                 for (sint32 i = 0; ; i++)
+00407                 {
+00408                         SetLastError(0);
+00409                         BOOL res = StackWalk (IMAGE_FILE_MACHINE_I386, getProcessHandle(), GetCurrentThread(), &callStack,
+00410                                 m_pexp->ContextRecord, NULL, FunctionTableAccess, GetModuleBase, NULL);
+00411 
+00412                         if (res == FALSE || callStack.AddrFrame.Offset == 0)
+00413                                 break;
+00414                 
+00415                         string symInfo, srcInfo;
+00416 
+00417                         if (i >= skipNFirst)
+00418                         {
+00419                                 srcInfo = getSourceInfo (callStack.AddrPC.Offset);
+00420                                 symInfo = getFuncInfo (callStack.AddrPC.Offset, callStack.AddrFrame.Offset);
+00421                                 _Reason += srcInfo + ": " + symInfo + "\n";
+00422                         }
+00423                 }
+00424                 _Reason += "-------------------------------\n";
+00425                 _Reason += "\n";
+00426                 if(DefaultMemDisplayer)
+00427                 {
+00428                         _Reason += "Log with no filter:\n";
+00429                         _Reason += "-------------------------------\n";
+00430                         DefaultMemDisplayer->write (_Reason);
+00431                 }
+00432                 else
+00433                 {
+00434                         _Reason += "No log\n";
+00435                 }
+00436                 _Reason += "-------------------------------\n";
+00437 
+00438                 nlverify (SymCleanup(getProcessHandle()) == TRUE);
+00439         }
+00440 
+00441         string getSourceInfo (DWORD addr)
+00442         {
+00443                 string str;
+00444 
+00445                 IMAGEHLP_LINE  line;
+00446                 ::ZeroMemory (&line, sizeof (line));
+00447                 line.SizeOfStruct = sizeof(line);
+00448 
+00449                 // "Debugging Applications" John Robbins
+00450                 // The problem is that the symbol engine finds only those source
+00451                 // line addresses (after the first lookup) that fall exactly on
+00452                 // a zero displacement. I'll walk backward 100 bytes to
+00453                 // find the line and return the proper displacement.
+00454                 bool ok = true;
+00455                 DWORD displacement = 0 ;
+00456                 DWORD resdisp;
+00457                 while (!SymGetLineFromAddr (getProcessHandle(), addr - displacement, (DWORD*)&resdisp, &line))
+00458                 {        
+00459                         if (100 == ++displacement)
+00460                         {
+00461                                 ok = false;
+00462                                 break;
+00463                         }
+00464                 }
+00465 
+00466                 // "Debugging Applications" John Robbins
+00467                 // I found the line, and the source line information is correct, so
+00468                 // change the displacement if I had to search backward to find the source line.
+00469                 if (displacement)    
+00470                         resdisp = displacement;    
+00471 
+00472                 if (ok)
+00473                 {
+00474                         str = line.FileName;
+00475                         str += "(" + toString (line.LineNumber) + ")";
+00476                         str += toString(": 0x%X", addr);
+00477                 }
+00478                 else
+00479                 {
+00480                         HRESULT hr = GetLastError();
+00481                         IMAGEHLP_MODULE module;
+00482                         ::ZeroMemory (&module, sizeof(module));
+00483                         module.SizeOfStruct = sizeof(module);
+00484 
+00485                         if (SymGetModuleInfo (getProcessHandle(), addr, &module))
+00486                         {
+00487                                 str = module.ModuleName;
+00488                         }
+00489                         else
+00490                         {
+00491                                 HRESULT hr = GetLastError ();
+00492                                 str = "<NoModule>";
+00493                         }
+00494                         str += toString("!0x%X", addr);
+00495                 }
+00496 
+00497                 /*
+00498                 DWORD disp;
+00499                 if (SymGetLineFromAddr (getProcessHandle(), addr, &disp, &line))
+00500                 {
+00501                         str = line.FileName;
+00502                         str += "(" + toString (line.LineNumber) + ")";
+00503                 }
+00504                 else
+00505                 {
+00506                         HRESULT hr = GetLastError();
+00507                         IMAGEHLP_MODULE module;
+00508                         ::ZeroMemory (&module, sizeof(module));
+00509                         module.SizeOfStruct = sizeof(module);
+00510 
+00511                         if (SymGetModuleInfo (getProcessHandle(), addr, &module))
+00512                         {
+00513                                 str = module.ModuleName;
+00514                         }
+00515                         else
+00516                         {
+00517                                 HRESULT hr = GetLastError ();
+00518                                 str = "<NoModule>";
+00519                         }
+00520                         char tmp[32];
+00521                         sprintf (tmp, "!0x%X", addr);
+00522                         str += tmp;
+00523                 }
+00524                 str +=" DEBUG:"+toString("0x%08X", addr);*/
+00525                 
+00526                 return str;
+00527         }
+00528 
+00529         HANDLE getProcessHandle()
+00530         {
+00531                 return CSystemInfo::isNT()?GetCurrentProcess():(HANDLE)GetCurrentProcessId();
+00532         }
+00533 
+00534         // return true if found
+00535         bool findAndErase(string &str, const char *token, const char *replace = NULL)
+00536         {
+00537                 int pos;
+00538                 if ((pos = str.find(token)) != string::npos)
+00539                 {
+00540                         str.erase (pos,strlen(token));
+00541                         if (replace != NULL)
+00542                                 str.insert (pos, replace);
+00543                         return true;
+00544                 }
+00545                 else
+00546                         return false;
+00547         }
+00548 
+00549         // remove space and const stuffs
+00550         // rawType contains the type without anything (to compare with known type)
+00551         // displayType contains the type without std:: and stl ugly things
+00552         void cleanType(string &rawType, string &displayType)
+00553         {
+00554                 while (findAndErase(rawType, "std::")) ;
+00555                 while (findAndErase(displayType, "std::")) ;
+00556 
+00557                 while (findAndErase(rawType, "const")) ;
+00558 
+00559                 while (findAndErase(rawType, " ")) ;
+00560 
+00561                 while (findAndErase(rawType, "&")) ;
+00562 
+00563                 // rename ugly stl type
+00564 
+00565                 while (findAndErase(rawType, "classbasic_string<char,classchar_traits<char>,classallocator<char>>", "string")) ;
+00566                 while (findAndErase(displayType, "class basic_string<char,class char_traits<char>,class allocator<char> >", "string")) ;
+00567                 while (findAndErase(rawType, "classvector<char,class char_traits<char>,class allocator<char> >", "string")) ;
+00568         }
+00569 
+00570         string getFuncInfo (DWORD funcAddr, DWORD stackAddr)
+00571         {
+00572                 string str ("NoSymbol");
+00573 
+00574                 DWORD symSize = 10000;
+00575                 PIMAGEHLP_SYMBOL  sym = (PIMAGEHLP_SYMBOL) GlobalAlloc (GMEM_FIXED, symSize);
+00576                 ::ZeroMemory (sym, symSize);
+00577                 sym->SizeOfStruct = symSize;
+00578                 sym->MaxNameLength = symSize - sizeof(IMAGEHLP_SYMBOL);
+00579 
+00580                 DWORD disp = 0;
+00581                 if (SymGetSymFromAddr (getProcessHandle(), funcAddr, &disp, sym) == FALSE)
+00582                 {
+00583                         return str;
+00584                 }
+00585 
+00586                 CHAR undecSymbol[1024];
+00587                 if (UnDecorateSymbolName (sym->Name, undecSymbol, 1024, UNDNAME_COMPLETE | UNDNAME_NO_THISTYPE | UNDNAME_NO_SPECIAL_SYMS | UNDNAME_NO_MEMBER_TYPE | UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS ) > 0)
+00588                 {
+00589                         str = undecSymbol;
+00590                 }
+00591                 else if (SymUnDName (sym, undecSymbol, 1024) == TRUE)
+00592                 {
+00593                         str = undecSymbol;
+00594                 }
+00595 
+00596                 // replace param with the value of the stack for this param
+00597 
+00598                 string parse = str;
+00599                 str = "";
+00600                 uint pos = 0;
+00601                 sint stop = 0;
+00602 
+00603                 string type;
+00604 
+00605                 uint i = parse.find ("(");
+00606 
+00607                 // copy the function name
+00608                 str = parse.substr(0, i);
+00609 
+00610 //              nlinfo ("not parsed '%s'", parse.c_str());
+00611 
+00613 
+00614 /*              // if there s parameter, parse them
+00615                 if(i!=string::npos)
+00616                 {
+00617                         // copy the '('
+00618                         str += parse[i];
+00619                         for (i++; i < parse.size (); i++)
+00620                         {
+00621                                 if (parse[i] == '<')
+00622                                          stop++;
+00623                                 if (parse[i] == '>')
+00624                                          stop--;
+00625 
+00626                                 if (stop==0 && (parse[i] == ',' || parse[i] == ')'))
+00627                                 {
+00628                                         ULONG *addr = (ULONG*)(stackAddr) + 2 + pos++;
+00629 
+00630                                         string displayType = type;
+00631                                         cleanType (type, displayType);
+00632 
+00633                                         char tmp[1024];
+00634                                         if(type == "void")
+00635                                         {
+00636                                                 tmp[0]='\0';
+00637                                         }
+00638                                         else if(type == "int")
+00639                                         {
+00640                                                 sprintf (tmp, "%d", *addr);
+00641                                         }
+00642                                         else if (type == "char")
+00643                                         {
+00644                                                 if (isprint(*addr))
+00645                                                 {
+00646                                                         sprintf (tmp, "'%c'", *addr);
+00647                                                 }
+00648                                                 else
+00649                                                 {
+00650                                                         sprintf (tmp, "%d", *addr);
+00651                                                 }
+00652                                         }
+00653                                         else if (type == "char*" && *addr != NULL)
+00654                                         {
+00655                                                 uint pos = 0;
+00656                                                 tmp[pos++] = '\"';
+00657                                                 for (uint i = 0; i < strlen((char*)*addr); i++)
+00658                                                 {
+00659                                                         if (pos == 1020)
+00660                                                                 break;
+00661                                                         char c = ((char *)*addr)[i];
+00662                                                         if (c == '\n')
+00663                                                         {
+00664                                                                 tmp[pos++] = '\\';
+00665                                                                 tmp[pos++] = 'n';
+00666                                                         }
+00667                                                         else if (c == '\r')
+00668                                                         {
+00669                                                                 tmp[pos++] = '\\';
+00670                                                                 tmp[pos++] = 'r';
+00671                                                         }
+00672                                                         else if (c == '\t')
+00673                                                         {
+00674                                                                 tmp[pos++] = '\\';
+00675                                                                 tmp[pos++] = 't';
+00676                                                         }
+00677                                                         else
+00678                                                                 tmp[pos++] = c;
+00679                                                 }
+00680                                                 tmp[pos++] = '\"';
+00681                                                 tmp[pos++] = '\0';
+00682                                         }
+00683                                         else if (type == "string" && *addr != NULL)
+00684                                         {
+00685                                                 sprintf (tmp, "\"%s\"", ((string*)addr)->c_str());
+00686                                         }
+00687                                         else
+00688                                         {
+00689                                                 if(*addr == NULL)
+00690                                                         sprintf (tmp, "<NULL>");
+00691                                                 else
+00692                                                         sprintf (tmp, "0x%X", *addr);
+00693                                         }
+00694 
+00695                                         str += displayType;
+00696                                         if(tmp[0]!='\0')
+00697                                         {
+00698                                                 str += "=";
+00699                                                 str += tmp;
+00700                                         }
+00701                                         str += parse[i];
+00702                                         type = "";
+00703                                 }
+00704                                 else
+00705                                 {
+00706                                         type += parse[i];
+00707                                 }
+00708                         }
+00709                         GlobalFree (sym);
+00710                         if (disp != 0)
+00711                         {
+00712                                 str += " + ";
+00713                                 str += toString (disp);
+00714                                 str += " bytes";
+00715                         }
+00716                 }
+00717 */
+00718 //              nlinfo ("after parsing '%s'", str.c_str());
+00719 
+00720                 return str;
+00721         }
+00722 
+00723 private:
+00724         EXCEPTION_POINTERS * m_pexp;
+00725 };
+00726 
+00727 // workaround of VCPP synchronous exception and se translator
+00728 bool global_force_exception_flag = false;
+00729 #define WORKAROUND_VCPP_SYNCHRONOUS_EXCEPTION  if (global_force_exception_flag) force_exception_frame();
+00730 void force_exception_frame(...) {std::cout.flush();}
+00731 
+00732 static void exceptionTranslator(unsigned, EXCEPTION_POINTERS *pexp)
+00733 {
+00734         // ace desactive because we can't debug if activated
+00735         //if (!TrapCrashInDebugger && IsDebuggerPresent ())
+00736         {
+00737                 if (pexp->ExceptionRecord->ExceptionCode == 0xACE0ACE)
+00738                         throw EDebug (pexp);
+00739                 else
+00740                         return;
+00741         }
+00742         /*else
+00743         {
+00744                 if (pexp->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
+00745                         return;
+00746                 else
+00747                         throw EDebug (pexp);
+00748         }*/
+00749 }
+00750 
+00751 #endif // NL_OS_WINDOWS
+00752 
+00753 void getCallStackAndLog (string &result, sint skipNFirst)
+00754 {
+00755 #ifdef NL_OS_WINDOWS
+00756         try
+00757         {
+00758                 WORKAROUND_VCPP_SYNCHRONOUS_EXCEPTION // force to install a exception frame             
+00759                         
+00760                 DWORD array[1];
+00761                 array[0] = skipNFirst;
+00762                 RaiseException (0xACE0ACE, 0, 1, array);
+00763         }
+00764         catch (EDebug &e)
+00765         {
+00766                 result += e.what();
+00767         }
+00768 #else
+00769         result += "No callstack available";
+00770 #endif
+00771 }
+00772 
+00773 
+00774 void createDebug (const char *logPath, bool logInFile)
+00775 {
+00776         NL_ALLOC_CONTEXT (_Debug)
+00777         
+00778         static bool alreadyCreate = false;
+00779         if (!alreadyCreate)
+00780         {
+00781                 // Debug Info for mutexes
+00782 #ifdef MUTEX_DEBUG
+00783                 initAcquireTimeMap();
+00784 #endif
+00785 
+00786 #ifdef NL_OS_WINDOWS
+00787                 //if (!IsDebuggerPresent ())
+00788                 {
+00789                         _set_se_translator(exceptionTranslator);
+00790                 }
+00791 #endif // NL_OS_WINDOWS
+00792 
+00793 
+00794                 ErrorLog = new CLog (CLog::LOG_ERROR);
+00795                 WarningLog = new CLog (CLog::LOG_WARNING);
+00796                 InfoLog = new CLog (CLog::LOG_INFO);
+00797                 DebugLog = new CLog (CLog::LOG_DEBUG);
+00798                 AssertLog = new CLog (CLog::LOG_ASSERT);
+00799 
+00800                 sd = new CStdDisplayer ("DEFAULT_SD");
+00801                 if (TrapCrashInDebugger || !IsDebuggerPresent ())
+00802                 {
+00803                         DefaultMsgBoxDisplayer = new CMsgBoxDisplayer ("DEFAULT_MBD");
+00804                 }
+00805 #if LOG_IN_FILE
+00806                 if (logInFile)
+00807                 {
+00808                         string fn;
+00809                         if (logPath != NULL)
+00810                         {
+00811                                 fn += logPath;
+00812                         }
+00813                         else
+00814                         {
+00815                                 // log.log must always be accessed in creation current path directory
+00816                                 char    tmpPath[1024];
+00817                                 fn += getcwd(tmpPath, 1024);
+00818                                 fn += "/";
+00819                         }
+00820                         fn += "log.log";
+00821                         fd = new CFileDisplayer (fn, false, "DEFAULT_FD");
+00822                 }
+00823 #endif // LOG_IN_FILE
+00824                 DefaultMemDisplayer = new CMemDisplayer ("DEFAULT_MD");
+00825                 
+00826                 initDebug2(logInFile);
+00827 
+00828                 alreadyCreate = true;
+00829         }
+00830 }
+00831 
+00832 
+00833 
+00834 
+00835 //
+00836 // Commands
+00837 //
+00838 
+00839 NLMISC_COMMAND (displayMemlog, "displays the last N line of the log in memory", "[<NbLines>]")
+00840 {
+00841         uint nbLines;
+00842 
+00843         if (args.size() == 0) nbLines = 100;
+00844         else if (args.size() == 1) nbLines = atoi(args[0].c_str());
+00845         else return false;
+00846 
+00847         if (DefaultMemDisplayer == NULL) return false;
+00848 
+00849         deque<string>::const_iterator it;
+00850         
+00851         const deque<string> &str = DefaultMemDisplayer->lockStrings ();
+00852 
+00853         if (nbLines >= str.size())
+00854                 it = str.begin();
+00855         else
+00856                 it = str.end() - nbLines;
+00857 
+00858         DefaultMemDisplayer->write (&log);
+00859 
+00860         DefaultMemDisplayer->unlockStrings ();
+00861 
+00862         return true;
+00863 }
+00864 
+00865 
+00866 NLMISC_COMMAND(resetFilters, "disable all filters on Nel loggers", "[debug|info|warning|error|assert]")
+00867 {
+00868         if(args.size() == 0)
+00869         {
+00870                 DebugLog->resetFilters();
+00871                 InfoLog->resetFilters();
+00872                 WarningLog->resetFilters();
+00873                 ErrorLog->resetFilters();
+00874                 AssertLog->resetFilters();
+00875         }
+00876         else if (args.size() == 1)
+00877         {
+00878                 if (args[0] == "debug") DebugLog->resetFilters();
+00879                 else if (args[0] == "info") InfoLog->resetFilters();
+00880                 else if (args[0] == "warning") WarningLog->resetFilters();
+00881                 else if (args[0] == "error") ErrorLog->resetFilters();
+00882                 else if (args[0] == "assert") AssertLog->resetFilters();
+00883         }
+00884         else
+00885         {
+00886                 return false;
+00887         }
+00888 
+00889         return true;
+00890 }
+00891 
+00892 NLMISC_COMMAND(addPositiveFilterDebug, "add a positive filter on DebugLog", "<filterstr>")
+00893 {
+00894         if(args.size() != 1) return false;
+00895         DebugLog->addPositiveFilter( args[0].c_str() );
+00896         return true;
+00897 }
+00898 
+00899 NLMISC_COMMAND(addNegativeFilterDebug, "add a negative filter on DebugLog", "<filterstr>")
+00900 {
+00901         if(args.size() != 1) return false;
+00902         DebugLog->addNegativeFilter( args[0].c_str() );
+00903         return true;
+00904 }
+00905 
+00906 NLMISC_COMMAND(removeFilterDebug, "remove a filter on DebugLog", "[<filterstr>]")
+00907 {
+00908         if(args.size() == 0)
+00909                 DebugLog->removeFilter();
+00910         else if(args.size() == 1)
+00911                 DebugLog->removeFilter( args[0].c_str() );
+00912         else return false;
+00913         return true;
+00914 }
+00915 
+00916 NLMISC_COMMAND(displayFilterDebug, "display filter on DebugLog", "")
+00917 {
+00918         if(args.size() != 0) return false;
+00919         DebugLog->displayFilter(log);
+00920         return true;
+00921 }
+00922 
+00923 NLMISC_COMMAND(addPositiveFilterInfo, "add a positive filter on InfoLog", "<filterstr>")
+00924 {
+00925         if(args.size() != 1) return false;
+00926         InfoLog->addPositiveFilter( args[0].c_str() );
+00927         return true;
+00928 }
+00929 
+00930 NLMISC_COMMAND(addNegativeFilterInfo, "add a negative filter on InfoLog", "<filterstr>")
+00931 {
+00932         if(args.size() != 1) return false;
+00933         InfoLog->addNegativeFilter( args[0].c_str() );
+00934         return true;
+00935 }
+00936 
+00937 NLMISC_COMMAND(removeFilterInfo, "remove a filter on InfoLog", "[<filterstr>]")
+00938 {
+00939         if(args.size() == 0)
+00940                 InfoLog->removeFilter();
+00941         else if(args.size() == 1)
+00942                 InfoLog->removeFilter( args[0].c_str() );
+00943         else return false;
+00944         return true;
+00945 }
+00946 
+00947 NLMISC_COMMAND(displayFilterInfo, "display filter on InfoLog", "[d|i|w|e]")
+00948 {
+00949         if(args.size() > 1) return false;
+00950         if ( args.size() == 1 )
+00951         {
+00952                 if ( strcmp( args[0].c_str(), "d" ) == 0 )
+00953                         InfoLog->displayFilter(*DebugLog);
+00954                 else if ( strcmp( args[0].c_str(), "i" ) == 0 )
+00955                         InfoLog->displayFilter(*InfoLog);
+00956                 else if ( strcmp( args[0].c_str(), "w" ) == 0 )
+00957                         InfoLog->displayFilter(*WarningLog);
+00958                 else if ( strcmp( args[0].c_str(), "e" ) == 0 )
+00959                         InfoLog->displayFilter(*ErrorLog);
+00960                 else
+00961                         return false;
+00962         }
+00963         else
+00964         {
+00965                 InfoLog->displayFilter(log);
+00966         }
+00967         return true;
+00968 }
+00969 
+00970 NLMISC_COMMAND(addPositiveFilterWarning, "add a positive filter on WarningLog", "<filterstr>")
+00971 {
+00972         if(args.size() != 1) return false;
+00973         WarningLog->addPositiveFilter( args[0].c_str() );
+00974         return true;
+00975 }
+00976 
+00977 NLMISC_COMMAND(addNegativeFilterWarning, "add a negative filter on WarningLog", "<filterstr>")
+00978 {
+00979         if(args.size() != 1) return false;
+00980         WarningLog->addNegativeFilter( args[0].c_str() );
+00981         return true;
+00982 }
+00983 
+00984 NLMISC_COMMAND(removeFilterWarning, "remove a filter on WarningLog", "[<filterstr>]")
+00985 {
+00986         if(args.size() == 0)
+00987                 WarningLog->removeFilter();
+00988         else if(args.size() == 1)
+00989                 WarningLog->removeFilter( args[0].c_str() );
+00990         else return false;
+00991         return true;
+00992 }
+00993 
+00994 NLMISC_COMMAND(displayFilterWarning, "display filter on WarningLog", "")
+00995 {
+00996         if(args.size() != 0) return false;
+00997         WarningLog->displayFilter(log);
+00998         return true;
+00999 }
+01000 
+01001 NLMISC_COMMAND(assert, "generate a failed assert", "")
+01002 {
+01003         if(args.size() != 0) return false;
+01004         nlassertex (false, ("Assert generated by the assert command"));
+01005         return true;
+01006 }
+01007 
+01008 NLMISC_COMMAND(stop, "generate a stop", "")
+01009 {
+01010         if(args.size() != 0) return false;
+01011         nlstopex (("Stop generated by the stop command"));
+01012         return true;
+01013 }
+01014 
+01015 } // NLMISC
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1