core/DebugReporter.cpp
author Scott Ehlert <ds@alliedmods.net>
Sun Mar 30 07:00:22 2008 +0000 (2008-03-30)
changeset 1952 b7aa2b626807
child 2061 77bd041bbe72
permissions -rw-r--r--
Spring Cleaning, Part Ichi (1)
Various minor things done to project files
Updated sample extension project file and updated makefile to the new unified version (more changes likely on the way)
Updated regex project file and makefile
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "DebugReporter.h"
    33 #include "Logger.h"
    34 #include "PluginSys.h"
    35 #include "sm_stringutil.h"
    36 
    37 DebugReport g_DbgReporter;
    38 
    39 /* I'm really lazy.  This should probably be exported to ISourcePawnEngine someday,
    40  * but we need to make sure the JIT will deal with the version bump.
    41  */
    42 extern const char *GetSourcePawnErrorMessage(int error);
    43 
    44 void DebugReport::OnSourceModAllInitialized()
    45 {
    46 	g_pSourcePawn->SetDebugListener(this);
    47 }
    48 
    49 void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...)
    50 {
    51 	va_list ap;
    52 	char buffer[512];
    53 
    54 	va_start(ap, message);
    55 	UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
    56 	va_end(ap);
    57 
    58 	const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
    59 	const char *error = GetSourcePawnErrorMessage(err);
    60 
    61 	if (error)
    62 	{
    63 		g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
    64 	} else {
    65 		g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
    66 	}
    67 
    68 	g_Logger.LogError("[SM] %s", buffer);
    69 
    70 	if (func_idx != -1)
    71 	{
    72 		if (func_idx & 1)
    73 		{
    74 			func_idx >>= 1;
    75 			sp_public_t *function;
    76 			if (ctx->GetPublicByIndex(func_idx, &function) == SP_ERROR_NONE)
    77 			{
    78 				g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name);
    79 			}
    80 		}
    81 	}
    82 }
    83 
    84 void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr, int err, const char *message, ...)
    85 {
    86 	va_list ap;
    87 	char buffer[512];
    88 
    89 	va_start(ap, message);
    90 	UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
    91 	va_end(ap);
    92 
    93 	const char *plname = g_PluginSys.FindPluginByContext(pContext->GetContext())->GetFilename();
    94 	const char *error = GetSourcePawnErrorMessage(err);
    95 
    96 	if (error)
    97 	{
    98 		g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
    99 	} else {
   100 		g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
   101 	}
   102 
   103 	g_Logger.LogError("[SM] %s", buffer);
   104 
   105 	IPluginDebugInfo *pDebug;
   106 	if ((pDebug = pContext->GetDebugInfo()) == NULL)
   107 	{
   108 		g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
   109 		g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
   110 			_GetPluginIndex(pContext));
   111 		return;
   112 	}
   113 
   114 	const char *name;
   115 	if (pDebug->LookupFunction(code_addr, &name) == SP_ERROR_NONE)
   116 	{
   117 		g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name);
   118 	} else {
   119 		g_Logger.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr);
   120 	}
   121 }
   122 
   123 void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *error)
   124 {
   125 	const char *lastname;
   126 	const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
   127 	int n_err = error->GetErrorCode();
   128 
   129 	if (n_err != SP_ERROR_NATIVE)
   130 	{
   131 		g_Logger.LogError("[SM] Plugin encountered error %d: %s",
   132 			n_err,
   133 			error->GetErrorString());
   134 	}
   135 
   136 	if ((lastname=error->GetLastNative(NULL)) != NULL)
   137 	{
   138 		const char *custerr;
   139 		if ((custerr=error->GetCustomErrorString()) != NULL)
   140 		{
   141 			g_Logger.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr);
   142 		} else {
   143 			g_Logger.LogError("[SM] Native \"%s\" encountered a generic error.", lastname);
   144 		}
   145 	}
   146 
   147 	if (!error->DebugInfoAvailable())
   148 	{
   149 		g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
   150 		g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
   151 			_GetPluginIndex(ctx));
   152 		return;
   153 	}
   154 
   155 	CallStackInfo stk_info;
   156 	int i = 0;
   157 	g_Logger.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname);
   158 	while (error->GetTraceInfo(&stk_info))
   159 	{
   160 		g_Logger.LogError("[SM]   [%d]  Line %d, %s::%s()",
   161 			i++,
   162 			stk_info.line,
   163 			stk_info.filename,
   164 			stk_info.function);
   165 	}
   166 }
   167 
   168 int DebugReport::_GetPluginIndex(IPluginContext *ctx)
   169 {
   170 	int id = 1;
   171 	IPluginIterator *iter = g_PluginSys.GetPluginIterator();
   172 
   173 	for (; iter->MorePlugins(); iter->NextPlugin(), id++)
   174 	{
   175 		IPlugin *pl = iter->GetPlugin();
   176 		if (pl->GetBaseContext() == ctx)
   177 		{
   178 			iter->Release();
   179 			return id;
   180 		}
   181 	}
   182 
   183 	iter->Release();
   184 	return -1;
   185 }
   186