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