Finalized new debugging system

This commit is contained in:
David Anderson 2005-09-11 03:58:38 +00:00
parent 401ee3c97f
commit 760e29e531
8 changed files with 515 additions and 241 deletions

View File

@ -35,6 +35,7 @@
#include "CFile.h"
#include "amx.h"
#include "natives.h"
#include "debugger.h"
extern const char *no_function;
@ -220,6 +221,56 @@ CPluginMngr::CPlugin::~CPlugin( )
unload_amxscript( &amx, &code );
}
int AMXAPI native_handler(AMX *amx, int index)
{
Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER];
char name[sNAMEMAX+1];
amx_GetNative(amx, index, name);
return pHandler->HandleNative(name, index, 0);
}
static cell AMX_NATIVE_CALL invalid_native(AMX *amx, cell *params)
{
//A script has accidentally called an invalid native! give them a
// first chance to block the resulting error.
Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER];
//this should never happen
if (!pHandler)
{
LogError(amx, AMX_ERR_INVNATIVE, "Invalid native attempt");
return 0;
}
//this should never happen because this native won't be called
// if the plugin isn't filtering.
if (!pHandler->IsNativeFiltering())
{
LogError(amx, AMX_ERR_INVNATIVE, "Invalid native attempt");
return 0;
}
char name[sNAMEMAX+1];
int native = amx->usertags[UT_NATIVE];
int err = amx_GetNative(amx, native, name);
if (err != AMX_ERR_NONE)
name[0] = '\0';
//1 - because we're trapping usage
if (!pHandler->HandleNative(name, native, 1))
{
LogError(amx, AMX_ERR_INVNATIVE, NULL);
return 0;
}
//Someday maybe allow native filters to write their own return value?
return 0;
}
void CPluginMngr::CPlugin::Finalize()
{
char buffer[128];
@ -229,10 +280,19 @@ void CPluginMngr::CPlugin::Finalize()
{
if ( amx_Register(&amx, core_Natives, -1) != AMX_ERR_NONE )
{
status = ps_bad_load;
sprintf(buffer, "Plugin uses an unknown function (name \"%s\") - check your modules.ini.", no_function);
errorMsg.assign(buffer);
amx.error = AMX_ERR_NOTFOUND;
Handler *pHandler = (Handler *)amx.userdata[UD_HANDLER];
int res = 0;
if (pHandler->IsNativeFiltering())
res = amx_CheckNatives(&amx, native_handler);
if (!res)
{
status = ps_bad_load;
sprintf(buffer, "Plugin uses an unknown function (name \"%s\") - check your modules.ini.", no_function);
errorMsg.assign(buffer);
amx.error = AMX_ERR_NOTFOUND;
} else {
amx_RegisterToAny(&amx, invalid_native);
}
}
} else {
status = ps_bad_load;

View File

@ -425,10 +425,7 @@ int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params)
AMX_FUNCSTUB *func;
AMX_NATIVE f;
assert(amx!=NULL);
hdr=(AMX_HEADER *)amx->base;
assert(hdr!=NULL);
assert(hdr->magic==AMX_MAGIC);
assert(hdr->natives<=hdr->libraries);
#if defined AMX_NATIVETABLE
if (index<NULL) {
@ -444,40 +441,10 @@ int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params)
#endif
assert(f!=NULL);
/* Now that we have found the function, patch the program so that any
* subsequent call will call the function directly (bypassing this
* callback).
* This trick cannot work in the JIT, because the program would need to
* be re-JIT-compiled after patching a P-code instruction.
/* As of AMX Mod X 1.56, we don't patch sysreq.c to sysreq.d anymore.
* Otherwise, we'd have no way of knowing the last native to be used.
*/
#if !defined JIT
if (amx->sysreq_d != 0)
{
//if we're about to patch this, and we're debugging, don't patch!
//otherwise we won't be able to get back native names
if (amx->flags & AMX_FLAG_DEBUG)
{
amx->sysreq_d = 0;
} else {
/* at the point of the call, the CIP pseudo-register points directly
* behind the SYSREQ instruction and its parameter.
*/
unsigned char *code=amx->base+(int)hdr->cod+(int)amx->cip-4;
assert(amx->cip >= 4 && amx->cip < (hdr->dat - hdr->cod));
assert(sizeof(f)<=sizeof(cell)); /* function pointer must fit in a cell */
#if defined __GNUC__ || defined ASM32
if (*(cell*)code==index) {
#else
if (*(cell*)code!=OP_SYSREQ_PRI) {
assert(*(cell*)(code-sizeof(cell))==OP_SYSREQ_C);
assert(*(cell*)code==index);
#endif //defined __GNU__ || defined ASM32
*(cell*)(code-sizeof(cell))=amx->sysreq_d;
*(cell*)code=(cell)f;
} /* if */
} /* if */
} /* if */
#endif //!defined JIT
amx->usertags[UT_NATIVE] = (long)index;
/* Note:
* params[0] == number of bytes for the additional parameters passed to the native function
@ -486,7 +453,9 @@ int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params)
*/
amx->error=AMX_ERR_NONE;
*result = f(amx,params);
return amx->error;
}
#endif /* defined AMX_INIT */
@ -1571,6 +1540,61 @@ static AMX_NATIVE findfunction(const char *name, const AMX_NATIVE_INFO *list, in
}
const char *no_function;
int AMXAPI amx_CheckNatives(AMX *amx, AMX_NATIVE_FILTER nf)
{
AMX_FUNCSTUB *func;
AMX_HEADER *hdr;
int i,numnatives,res=0;
hdr=(AMX_HEADER *)amx->base;
assert(hdr!=NULL);
assert(hdr->magic==AMX_MAGIC);
assert(hdr->natives<=hdr->libraries);
numnatives=NUMENTRIES(hdr,natives,libraries);
func=GETENTRY(hdr,natives,0);
for (i=0; i<numnatives; i++) {
if (func->address==0) {
/* this function is not yet located */
res=nf(amx,i);
if (!res)
{
no_function = GETENTRYNAME(hdr,func);
return 0;
}
} /* if */
func=(AMX_FUNCSTUB*)((unsigned char*)func+hdr->defsize);
} /* for */
return 1;
}
int AMXAPI amx_RegisterToAny(AMX *amx, AMX_NATIVE f)
{
AMX_FUNCSTUB *func;
AMX_HEADER *hdr;
int i,numnatives,err;
hdr=(AMX_HEADER *)amx->base;
assert(hdr!=NULL);
assert(hdr->magic==AMX_MAGIC);
assert(hdr->natives<=hdr->libraries);
numnatives=NUMENTRIES(hdr,natives,libraries);
err=AMX_ERR_NONE;
func=GETENTRY(hdr,natives,0);
for (i=0; i<numnatives; i++) {
if (func->address==0) {
/* this function is not yet located */
func->address=(ucell)f;
} /* if */
func=(AMX_FUNCSTUB*)((unsigned char*)func+hdr->defsize);
} /* for */
if (err==AMX_ERR_NONE)
amx->flags|=AMX_FLAG_NTVREG;
return err;
}
int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *list, int number)
{
AMX_FUNCSTUB *func;

View File

@ -166,6 +166,7 @@ typedef cell (AMX_NATIVE_CALL *AMX_NATIVE)(struct tagAMX *amx, cell *params);
typedef int (AMXAPI *AMX_CALLBACK)(struct tagAMX *amx, cell index,
cell *result, cell *params);
typedef int (AMXAPI *AMX_DEBUG)(struct tagAMX *amx);
typedef int (AMXAPI *AMX_NATIVE_FILTER)(struct tagAMX *amx, int index);
#if !defined _FAR
#define _FAR
#endif
@ -301,6 +302,7 @@ enum {
AMX_ERR_DIVIDE, /* divide by zero */
AMX_ERR_SLEEP, /* go into sleepmode - code can be restarted */
AMX_ERR_INVSTATE, /* invalid state for this access */
AMX_ERR_INVNATIVE, /* invalid native was used */
AMX_ERR_MEMORY = 16, /* out of memory */
AMX_ERR_FORMAT, /* invalid file format */
@ -340,6 +342,7 @@ enum {
#define UD_DEBUGGER 2
#define UD_OPCODELIST 1
#define UD_HANDLER 0
#define UT_NATIVE 3
/* for native functions that use floating point parameters, the following
* two macros are convenient for casting a "cell" into a "float" type _without_
@ -373,6 +376,7 @@ uint32_t * AMXAPI amx_Align32(uint32_t *v);
#endif
int AMXAPI amx_Allot(AMX *amx, int cells, cell *amx_addr, cell **phys_addr);
int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params);
int AMXAPI amx_CheckNatives(AMX *amx, AMX_NATIVE_FILTER nf);
int AMXAPI amx_Cleanup(AMX *amx);
int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data);
int AMXAPI amx_Exec(AMX *amx, cell *retval, int index);
@ -402,6 +406,7 @@ int AMXAPI amx_PushArray(AMX *amx, cell *amx_addr, cell **phys_addr, const cell
int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char *string, int pack, int use_wchar);
int AMXAPI amx_RaiseError(AMX *amx, int error);
int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *nativelist, int number);
int AMXAPI amx_RegisterToAny(AMX *amx, AMX_NATIVE f);
int AMXAPI amx_Release(AMX *amx, cell amx_addr);
int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback);
int AMXAPI amx_SetDebugHook(AMX *amx, AMX_DEBUG debug);

View File

@ -3012,174 +3012,198 @@ static cell AMX_NATIVE_CALL query_client_cvar(AMX *amx, cell *params)
return 1;
}
AMX_NATIVE_INFO amxmod_Natives[] = {
{ "client_cmd", client_cmd },
{ "client_print", client_print },
{ "console_cmd", console_cmd },
{ "console_print", console_print },
{ "cvar_exists", cvar_exists },
{ "emit_sound", emit_sound },
{ "engclient_cmd", engclient_cmd },
{ "engclient_print", engclient_print },
{ "find_player", find_player },
{ "find_plugin_byfile", find_plugin_byfile },
{ "force_unmodified", force_unmodified },
{ "format_time", format_time},
{ "get_clcmd", get_clcmd},
{ "get_clcmdsnum", get_clcmdsnum},
{ "get_concmd", get_concmd},
{ "get_concmdsnum", get_concmdsnum},
{ "get_cvar_flags", get_cvar_flags },
{ "get_cvar_float", get_cvar_float },
{ "get_cvar_num", get_cvar_num },
{ "get_cvar_string", get_cvar_string },
{ "get_distance", get_distance },
{ "get_distance_f", get_distance_f },
{ "get_flags", get_flags },
{ "get_gametime", get_gametime},
{ "get_localinfo", get_localinfo},
{ "get_mapname", get_mapname},
{ "get_maxplayers", get_maxplayers },
{ "get_modname", get_modname},
{ "get_players", get_players },
{ "get_playersnum", get_playersnum },
{ "get_plugin", get_plugin },
{ "get_pluginsnum", get_pluginsnum },
{ "get_srvcmd", get_srvcmd },
{ "get_srvcmdsnum", get_srvcmdsnum },
{ "get_systime", get_systime},
{ "get_time", get_time},
{ "get_timeleft", get_timeleft},
{ "get_user_aiming", get_user_aiming },
{ "get_user_ammo", get_user_ammo},
{ "get_user_armor", get_user_armor },
{ "get_user_attacker",get_user_attacker },
{ "get_user_authid", get_user_authid },
{ "get_user_flags", get_user_flags },
{ "get_user_frags", get_user_frags },
{ "get_user_deaths", get_user_deaths },
{ "get_user_health", get_user_health },
{ "get_user_index", get_user_index },
{ "get_user_info", get_user_info },
{ "get_user_ip", get_user_ip },
{ "get_user_menu", get_user_menu},
{ "get_user_msgid", get_user_msgid},
{ "get_user_msgname", get_user_msgname},
{ "get_user_name", get_user_name },
{ "get_user_origin", get_user_origin},
{ "get_user_ping", get_user_ping },
{ "get_user_team", get_user_team },
{ "get_user_time", get_user_time },
{ "get_user_userid", get_user_userid },
{ "hcsardhnExsnu", register_byval },
{ "user_has_weapon", user_has_weapon },
{ "get_user_weapon", get_user_weapon},
{ "get_user_weapons", get_user_weapons},
{ "get_weaponname", get_weaponname},
{ "get_xvar_float", get_xvar_num },
{ "get_xvar_id", get_xvar_id },
{ "get_xvar_num", get_xvar_num },
{ "is_dedicated_server",is_dedicated_server },
{ "is_linux_server", is_linux_server },
{ "is_amd64_server", is_amd64_server },
{ "is_jit_enabled", is_jit_enabled },
{ "is_user_authorized", is_user_authorized },
{ "is_map_valid", is_map_valid },
{ "is_user_alive", is_user_alive },
{ "is_user_bot", is_user_bot },
{ "is_user_connected", is_user_connected },
{ "is_user_connecting", is_user_connecting },
{ "is_user_hltv", is_user_hltv },
{ "log_message", log_message },
{ "log_to_file", log_to_file },
{ "num_to_word", num_to_word },
{ "parse_loguser", parse_loguser },
{ "parse_time", parse_time },
{ "pause", pause },
{ "precache_model", precache_model },
{ "precache_sound", precache_sound },
{ "random_float", random_float },
{ "random_num", random_num },
{ "read_argc", read_argc },
{ "read_args", read_args },
{ "read_argv", read_argv },
{ "read_data", read_data },
{ "read_datanum", read_datanum },
{ "read_flags", read_flags },
{ "read_logargc", read_logargc },
{ "read_logargv", read_logargv },
{ "read_logdata", read_logdata },
{ "register_clcmd", register_clcmd },
{ "register_concmd", register_concmd },
{ "register_cvar", register_cvar },
{ "register_event", register_event },
{ "register_logevent",register_logevent},
{ "register_menucmd", register_menucmd },
{ "register_menuid", register_menuid },
{ "require_module", require_module },
{ "register_plugin", register_plugin },
{ "register_srvcmd", register_srvcmd },
{ "remove_cvar_flags", remove_cvar_flags },
{ "remove_quotes", remove_quotes },
{ "remove_task", remove_task },
{ "change_task", change_task },
{ "remove_user_flags", remove_user_flags },
{ "server_cmd", server_cmd },
{ "server_exec", server_exec },
{ "server_print", server_print },
{ "set_cvar_flags", set_cvar_flags },
{ "set_cvar_float", set_cvar_float },
{ "set_cvar_num", set_cvar_num },
{ "set_cvar_string", set_cvar_string },
{ "set_hudmessage", set_hudmessage },
{ "set_localinfo", set_localinfo},
{ "set_task", set_task },
{ "set_user_flags", set_user_flags},
{ "set_user_info", set_user_info },
{ "set_xvar_float", set_xvar_num },
{ "set_xvar_num", set_xvar_num },
{ "show_hudmessage", show_hudmessage },
{ "show_menu", show_menu },
{ "show_motd", show_motd },
{ "task_exists", task_exists },
{ "unpause", unpause },
{ "user_kill", user_kill },
{ "user_slap", user_slap },
{ "xvar_exists", xvar_exists },
{ "is_module_loaded", is_module_loaded },
{ "is_plugin_loaded", is_plugin_loaded },
{ "get_modulesnum", get_modulesnum },
{ "get_module", get_module },
{ "log_amx", log_amx },
{ "get_func_id", get_func_id },
{ "callfunc_begin", callfunc_begin },
{ "callfunc_begin_i", callfunc_begin_i },
{ "callfunc_end", callfunc_end },
{ "callfunc_push_int", callfunc_push_byval },
{ "callfunc_push_str", callfunc_push_str },
{ "callfunc_push_float", callfunc_push_byval },
{ "callfunc_push_intrf", callfunc_push_byref },
{ "callfunc_push_floatrf", callfunc_push_byref },
{ "message_begin", message_begin },
{ "message_end", message_end },
{ "write_angle", write_angle },
{ "write_byte", write_byte },
{ "write_char", write_char },
{ "write_coord", write_coord },
{ "write_entity", write_entity },
{ "write_long", write_long },
{ "write_short", write_short },
{ "write_string", write_string },
{ "get_langsnum", get_langsnum },
{ "get_lang", get_lang },
{ "register_dictionary", register_dictionary },
{ "lang_exists", lang_exists },
{ "md5", amx_md5 },
{ "md5_file", amx_md5_file },
{ "plugin_flags", plugin_flags},
{ "lang_phrase", lang_phrase},
{ "mkdir", amx_mkdir},
{ "int3", int3},
{ "query_client_cvar", query_client_cvar },
{ NULL, NULL }
static cell AMX_NATIVE_CALL amx_abort(AMX *amx, cell *params)
{
int err = params[1];
int len;
char *fmt = format_amxstring(amx, params, 2, len);
if (fmt[0] == '\0')
fmt = NULL;
const char *filename = "";
CPluginMngr::CPlugin *pPlugin = g_plugins.findPluginFast(amx);
if (pPlugin)
filename = pPlugin->getName();
if (fmt)
LogError(amx, err, "[%s] %s", filename, fmt);
else
LogError(amx, err, NULL);
return 1;
}
AMX_NATIVE_INFO amxmodx_Natives[] = {
{"abort", amx_abort},
{"callfunc_begin", callfunc_begin},
{"callfunc_begin_i", callfunc_begin_i},
{"callfunc_end", callfunc_end},
{"callfunc_push_int", callfunc_push_byval},
{"callfunc_push_float", callfunc_push_byval},
{"callfunc_push_intrf", callfunc_push_byref},
{"callfunc_push_floatrf", callfunc_push_byref},
{"callfunc_push_str", callfunc_push_str},
{"client_cmd", client_cmd},
{"client_print", client_print},
{"console_cmd", console_cmd},
{"console_print", console_print},
{"cvar_exists", cvar_exists},
{"emit_sound", emit_sound},
{"engclient_cmd", engclient_cmd},
{"engclient_print", engclient_print},
{"find_player", find_player},
{"find_plugin_byfile", find_plugin_byfile},
{"force_unmodified", force_unmodified},
{"format_time", format_time},
{"get_clcmd", get_clcmd},
{"get_clcmdsnum", get_clcmdsnum},
{"get_concmd", get_concmd},
{"get_concmdsnum", get_concmdsnum},
{"get_cvar_flags", get_cvar_flags},
{"get_cvar_float", get_cvar_float},
{"get_cvar_num", get_cvar_num},
{"get_cvar_string", get_cvar_string},
{"get_distance", get_distance},
{"get_distance_f", get_distance_f},
{"get_flags", get_flags},
{"get_func_id", get_func_id},
{"get_gametime", get_gametime},
{"get_lang", get_lang},
{"get_langsnum", get_langsnum},
{"get_localinfo", get_localinfo},
{"get_mapname", get_mapname},
{"get_maxplayers", get_maxplayers},
{"get_modname", get_modname},
{"get_module", get_module},
{"get_modulesnum", get_modulesnum},
{"get_players", get_players},
{"get_playersnum", get_playersnum},
{"get_plugin", get_plugin},
{"get_pluginsnum", get_pluginsnum},
{"get_srvcmd", get_srvcmd},
{"get_srvcmdsnum", get_srvcmdsnum},
{"get_systime", get_systime},
{"get_time", get_time},
{"get_timeleft", get_timeleft},
{"get_user_aiming", get_user_aiming},
{"get_user_ammo", get_user_ammo},
{"get_user_armor", get_user_armor},
{"get_user_attacker", get_user_attacker},
{"get_user_authid", get_user_authid},
{"get_user_flags", get_user_flags},
{"get_user_frags", get_user_frags},
{"get_user_deaths", get_user_deaths},
{"get_user_health", get_user_health},
{"get_user_index", get_user_index},
{"get_user_info", get_user_info},
{"get_user_ip", get_user_ip},
{"get_user_menu", get_user_menu},
{"get_user_msgid", get_user_msgid},
{"get_user_msgname", get_user_msgname},
{"get_user_name", get_user_name},
{"get_user_origin", get_user_origin},
{"get_user_ping", get_user_ping},
{"get_user_team", get_user_team},
{"get_user_time", get_user_time},
{"get_user_userid", get_user_userid},
{"hcsardhnexsnu", register_byval},
{"user_has_weapon", user_has_weapon},
{"get_user_weapon", get_user_weapon},
{"get_user_weapons", get_user_weapons},
{"get_weaponname", get_weaponname},
{"get_xvar_float", get_xvar_num},
{"get_xvar_id", get_xvar_id},
{"get_xvar_num", get_xvar_num},
{"int3", int3},
{"is_amd64_server", is_amd64_server},
{"is_dedicated_server", is_dedicated_server},
{"is_jit_enabled", is_jit_enabled},
{"is_linux_server", is_linux_server},
{"is_map_valid", is_map_valid},
{"is_module_loaded", is_module_loaded},
{"is_plugin_loaded", is_plugin_loaded},
{"is_user_alive", is_user_alive},
{"is_user_authorized", is_user_authorized},
{"is_user_bot", is_user_bot},
{"is_user_connected", is_user_connected},
{"is_user_connecting", is_user_connecting},
{"is_user_hltv", is_user_hltv},
{"lang_exists", lang_exists},
{"lang_phrase", lang_phrase},
{"log_amx", log_amx},
{"log_message", log_message},
{"log_to_file", log_to_file},
{"md5", amx_md5},
{"md5_file", amx_md5_file},
{"message_begin", message_begin},
{"message_end", message_end},
{"mkdir", amx_mkdir},
{"num_to_word", num_to_word},
{"parse_loguser", parse_loguser},
{"parse_time", parse_time},
{"pause", pause},
{"plugin_flags", plugin_flags},
{"precache_model", precache_model},
{"precache_sound", precache_sound},
{"query_client_cvar", query_client_cvar},
{"random_float", random_float},
{"random_num", random_num},
{"read_argc", read_argc},
{"read_args", read_args},
{"read_argv", read_argv},
{"read_data", read_data},
{"read_datanum", read_datanum},
{"read_flags", read_flags},
{"read_logargc", read_logargc},
{"read_logargv", read_logargv},
{"read_logdata", read_logdata},
{"register_clcmd", register_clcmd},
{"register_concmd", register_concmd},
{"register_cvar", register_cvar},
{"register_dictionary", register_dictionary},
{"register_event", register_event},
{"register_logevent", register_logevent},
{"register_menucmd", register_menucmd},
{"register_menuid", register_menuid},
{"register_plugin", register_plugin},
{"register_srvcmd", register_srvcmd},
{"require_module", require_module},
{"remove_cvar_flags", remove_cvar_flags},
{"remove_quotes", remove_quotes},
{"remove_task", remove_task},
{"change_task", change_task},
{"remove_user_flags", remove_user_flags},
{"server_cmd", server_cmd},
{"server_exec", server_exec},
{"server_print", server_print},
{"set_cvar_flags", set_cvar_flags},
{"set_cvar_float", set_cvar_float},
{"set_cvar_num", set_cvar_num},
{"set_cvar_string", set_cvar_string},
{"set_hudmessage", set_hudmessage},
{"set_localinfo", set_localinfo},
{"set_task", set_task},
{"set_user_flags", set_user_flags},
{"set_user_info", set_user_info},
{"set_xvar_float", set_xvar_num},
{"set_xvar_num", set_xvar_num},
{"show_hudmessage", show_hudmessage},
{"show_menu", show_menu},
{"show_motd", show_motd},
{"task_exists", task_exists},
{"unpause", unpause},
{"user_kill", user_kill},
{"user_slap", user_slap},
{"write_angle", write_angle},
{"write_byte", write_byte},
{"write_char", write_char},
{"write_coord", write_coord},
{"write_entity", write_entity},
{"write_long", write_long},
{"write_short", write_short},
{"write_string", write_string},
{"xvar_exists", xvar_exists},
{NULL, NULL}
};

View File

@ -74,11 +74,11 @@
extern AMX_NATIVE_INFO core_Natives[];
extern AMX_NATIVE_INFO time_Natives[];
extern AMX_NATIVE_INFO power_Natives[];
extern AMX_NATIVE_INFO amxmod_Natives[];
extern AMX_NATIVE_INFO file_Natives[];
extern AMX_NATIVE_INFO float_Natives[];
extern AMX_NATIVE_INFO string_Natives[];
extern AMX_NATIVE_INFO vault_Natives[];
extern AMX_NATIVE_INFO amxmodx_Natives[];
extern AMX_NATIVE_INFO file_Natives[];
extern AMX_NATIVE_INFO float_Natives[];
extern AMX_NATIVE_INFO string_Natives[];
extern AMX_NATIVE_INFO vault_Natives[];
#ifndef __linux__
#define DLLOAD(path) (DLHANDLE)LoadLibrary(path)

View File

@ -430,24 +430,25 @@ int Debugger::FormatError(char *buffer, size_t maxLength)
buffer += size;
maxLength -= size;
if (error == AMX_ERR_NATIVE)
if (error == AMX_ERR_NATIVE || error == AMX_ERR_INVNATIVE)
{
char native_name[32];
char native_name[sNAMEMAX+1];
int num = 0;
//go two instructions back
/*//go two instructions back
cip -= (sizeof(cell) * 2);
int instr = _GetOpcodeFromCip(cip, p_cip);
if (instr == OP_SYSREQ_C)
{
num = (int)*p_cip;
} else if (instr == OP_SYSREQ_PRI) {
num = (int)m_pAmx->pri;
}
if (num)
}*/
//New code only requires this...
num = m_pAmx->usertags[UT_NATIVE];
amx_err = amx_GetNative(m_pAmx, num, native_name);
/*if (num)
amx_err = amx_GetNative(m_pAmx, (int)*p_cip, native_name);
else
amx_err = AMX_ERR_NOTFOUND;
if (!amx_err)
amx_err = AMX_ERR_NOTFOUND;*/
//if (!amx_err)
size += _snprintf(buffer, maxLength, "(native \"%s\")", native_name);
} else if (error == AMX_ERR_BOUNDS) {
tagAMX_DBG *pDbg = m_pAmxDbg;
@ -731,7 +732,7 @@ const char *GenericError(int err)
"divide",
"sleep",
"invalid access state",
NULL,
"native not found",
NULL,
"out of memory", //16
"bad file format",
@ -760,6 +761,9 @@ int AMXAPI Debugger::DebugHook(AMX *amx)
if (!amx || !(amx->flags & AMX_FLAG_DEBUG))
return AMX_ERR_NONE;
if (amx->flags & AMX_FLAG_PRENIT)
return AMX_ERR_NONE;
pDebugger = (Debugger *)amx->userdata[UD_DEBUGGER];
if (!pDebugger)
@ -872,7 +876,7 @@ int Handler::SetErrorHandler(const char *function)
error = amx_FindPublic(m_pAmx, function, &m_iErrFunc);
if (error != AMX_ERR_NONE)
if (error != AMX_ERR_NONE && m_iErrFunc < 1)
m_iErrFunc = -1;
return error;
@ -884,7 +888,7 @@ int Handler::SetModuleFilter(const char *function)
error = amx_FindPublic(m_pAmx, function, &m_iModFunc);
if (error != AMX_ERR_NONE)
if (error != AMX_ERR_NONE && m_iModFunc < 1)
m_iModFunc = -1;
return error;
@ -896,7 +900,7 @@ int Handler::SetNativeFilter(const char *function)
error = amx_FindPublic(m_pAmx, function, &m_iNatFunc);
if (error != AMX_ERR_NONE)
if (error != AMX_ERR_NONE && !IsNativeFiltering())
m_iNatFunc = -1;
return error;
@ -918,6 +922,94 @@ const char *Handler::GetLastMsg()
return m_MsgCache.c_str();
}
int Handler::HandleModule(const char *module)
{
if (m_iModFunc < 1)
return 0;
/**
* This is the most minimalistic handler of them all
*/
cell hea_addr, *phys_addr, retval;
//temporarily set prenit
m_pAmx->flags |= AMX_FLAG_PRENIT;
amx_PushString(m_pAmx, &hea_addr, &phys_addr, module, 0, 0);
int err = amx_Exec(m_pAmx, &retval, m_iModFunc);
amx_Release(m_pAmx, hea_addr);
m_pAmx->flags &= ~AMX_FLAG_PRENIT;
if (err != AMX_ERR_NONE)
return 0;
return (int)retval;
}
int Handler::HandleNative(const char *native, int index, int trap)
{
if (!IsNativeFiltering())
return 0;
/**
* Our handler here is a bit different from HandleError().
* For one, there is no current error in pDebugger, so we
* don't have to save some states.
*/
m_InNativeFilter = true;
Debugger *pDebugger = (Debugger *)m_pAmx->userdata[UD_DEBUGGER];
if (pDebugger && trap)
pDebugger->BeginExec();
cell hea_addr, *phys_addr, retval;
if (!trap)
m_pAmx->flags |= AMX_FLAG_PRENIT;
amx_Push(m_pAmx, trap);
amx_Push(m_pAmx, index);
amx_PushString(m_pAmx, &hea_addr, &phys_addr, native, 0, 0);
int err = amx_Exec(m_pAmx, &retval, m_iNatFunc);
if (err != AMX_ERR_NONE)
{
//LogError() took care of something for us.
if (err == -1)
{
m_InNativeFilter = false;
amx_Release(m_pAmx, hea_addr);
return 1;
}
if (!trap)
{
AMXXLOG_Log("[AMXX] Runtime failure %d occurred in native filter. Aborting plugin load.", err);
return 0;
}
//handle this manually.
//we need to push this through an error filter, same as executeForwards!
if (pDebugger && pDebugger->ErrorExists())
{
//don't display, it was already handled.
} else if (err != -1) {
LogError(m_pAmx, err, NULL);
}
AMXXLOG_Log("[AMXX] NOTE: Runtime failures in native filters are not good!");
retval = 0;
}
if (!trap)
m_pAmx->flags &= ~AMX_FLAG_PRENIT;
if (pDebugger && trap)
pDebugger->EndExec();
amx_Release(m_pAmx, hea_addr);
m_InNativeFilter = false;
return (int)retval;
}
int Handler::HandleError(const char *msg)
{
if (m_iErrFunc <= 0)
@ -1073,11 +1165,63 @@ static cell AMX_NATIVE_CALL dbg_fmt_error(AMX *amx, cell *params)
return 1;
}
static cell AMX_NATIVE_CALL set_native_filter(AMX *amx, cell *params)
{
Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER];
if (!pHandler)
{
Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND);
AMXXLOG_Log("[AMXX] Plugin not initialized correctly.");
return 0;
}
if (!pHandler->IsNativeFiltering())
{
//we can only initialize this during PRENIT
if (! (amx->flags & AMX_FLAG_PRENIT) )
return 0;
}
int len;
char *func = get_amxstring(amx, params[1], 0, len);
int err = pHandler->SetNativeFilter(func);
if (err != AMX_ERR_NONE)
{
Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND);
AMXXLOG_Log("[AMXX] Function not found: %s", function);
return 0;
}
return 1;
}
static cell AMX_NATIVE_CALL set_module_filter(AMX *amx, cell *params)
{
if ( !(amx->flags & AMX_FLAG_PRENIT) )
return -1;
Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER];
if (!pHandler)
return -2;
int len;
char *function = get_amxstring(amx, params[1], 0, len);
return pHandler->SetModuleFilter(function);
}
AMX_NATIVE_INFO g_DebugNatives[] = {
{"set_error_filter", set_error_filter},
{"dbg_trace_begin", dbg_trace_begin},
{"dbg_trace_next", dbg_trace_next},
{"dbg_trace_info", dbg_trace_info},
{"dbg_fmt_error", dbg_fmt_error},
{"set_native_filter", set_native_filter},
{"set_module_filter", set_module_filter},
{NULL, NULL},
};

View File

@ -159,7 +159,7 @@ public:
int SetModuleFilter(const char *function);
public:
int HandleError(const char *msg);
int HandleNative(const char *native);
int HandleNative(const char *native, int index, int trap);
int HandleModule(const char *module);
public:
bool IsHandling() const { return m_Handling; }
@ -167,12 +167,16 @@ public:
const char *GetLastMsg();
trace_info_t *GetTrace() const { return m_pTrace; }
const char *GetFmtCache() { return m_FmtCache.c_str(); }
bool IsNativeFiltering() { return (m_iNatFunc > 0); }
bool InNativeFilter() { return m_InNativeFilter; }
private:
AMX *m_pAmx;
int m_iErrFunc;
int m_iModFunc;
int m_iNatFunc;
bool m_Handling;
//in the future, make this a stack!
bool m_InNativeFilter;
String m_MsgCache;
String m_FmtCache;
trace_info_t *m_pTrace;

View File

@ -344,6 +344,7 @@ int CheckModules(AMX *amx, char error[128])
bool isdbi = false;
CList<CModule,const char *>::iterator a;
const amxx_module_info_s *info;
Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER];
for (int i=0; i<numLibraries; i++)
{
@ -385,6 +386,11 @@ int CheckModules(AMX *amx, char error[128])
if (!found)
found = LibraryExists(buffer);
if (!found)
{
if (pHandler->HandleModule(buffer))
found = true;
}
if (!found)
{
sprintf(error, "Module \"%s\" required for plugin. Check modules.ini.", buffer);
return 0;
@ -406,7 +412,7 @@ int set_amxnatives(AMX* amx,char error[128])
amx_Register(amx, string_Natives, -1);
amx_Register(amx, float_Natives, -1);
amx_Register(amx, file_Natives, -1);
amx_Register(amx, amxmod_Natives, -1);
amx_Register(amx, amxmodx_Natives, -1);
amx_Register(amx, power_Natives, -1);
amx_Register(amx, time_Natives, -1);
amx_Register(amx, vault_Natives, -1);
@ -1306,19 +1312,26 @@ void LogError(AMX *amx, int err, const char *fmt, ...)
//give the plugin first chance to handle any sort of error
Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER];
if (pHandler)
if (pHandler->InNativeFilter())
{
if (pHandler->IsHandling())
if (pDebugger)
pDebugger->EndExec();
} else {
if (pHandler)
{
if (fmt != NULL)
pHandler->SetErrorMsg(msg_buffer);
return;
}
//give the user a first-chance at blocking the error from displaying
if (pHandler->HandleError(fmt ? msg_buffer : NULL) != 0)
{
amx->error = -1;
return;
if (pHandler->IsHandling())
{
if (fmt != NULL)
pHandler->SetErrorMsg(msg_buffer);
return;
}
//give the user a first-chance at blocking the error from displaying
if (pHandler->HandleError(fmt ? msg_buffer : NULL) != 0)
{
amx->error = -1;
return;
}
}
}