📄 swfdec_debugger.c
字号:
/* Swfdec * Copyright (C) 2006 Benjamin Otte <otte@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <string.h>#include "swfdec_debugger.h"#include "swfdec_debug.h"#include "swfdec_decoder.h"#include "swfdec_js.h"#include "swfdec_movie.h"#include "swfdec_player_internal.h"#include "js/jsdbgapi.h"#include "js/jsinterp.h" /* for frame->swf *//*** SwfdecDebuggerScript ***/typedef struct { SwfdecConstantPool * constant_pool; /* current constant pool */ GArray * commands; /* SwfdecDebuggerCommands parsed so far */} ScriptParser;static char *swfdec_debugger_print_push (ScriptParser *parser, const guint8 *data, guint len){ gboolean first = TRUE; SwfdecBits bits; GString *string = g_string_new ("Push"); swfdec_bits_init_data (&bits, data, len); while (swfdec_bits_left (&bits)) { guint type = swfdec_bits_get_u8 (&bits); if (first) g_string_append (string, " "); else g_string_append (string, ", "); first = FALSE; switch (type) { case 0: /* string */ { const char *s = swfdec_bits_skip_string (&bits); if (!s) { g_string_free (string, TRUE); return NULL; } g_string_append_c (string, '"'); g_string_append (string, s); g_string_append_c (string, '"'); break; } case 1: /* float */ g_string_append_printf (string, "%g", swfdec_bits_get_float (&bits)); break; case 2: /* null */ g_string_append (string, "null"); break; case 3: /* undefined */ g_string_append (string, "undefined"); break; case 4: /* register */ g_string_append_printf (string, "Register %u", swfdec_bits_get_u8 (&bits)); break; case 5: /* boolean */ g_string_append (string, swfdec_bits_get_u8 (&bits) ? "True" : "False"); break; case 6: /* double */ g_string_append_printf (string, "%g", swfdec_bits_get_double (&bits)); break; case 7: /* 32bit int */ g_string_append_printf (string, "%d", swfdec_bits_get_u32 (&bits)); break; case 8: /* 8bit ConstantPool address */ case 9: /* 16bit ConstantPool address */ { guint id; const char *s; if (!parser->constant_pool) { SWFDEC_ERROR ("no constant pool"); g_string_free (string, TRUE); return NULL; } id = type == 8 ? swfdec_bits_get_u8 (&bits) : swfdec_bits_get_u16 (&bits); s = swfdec_constant_pool_get (parser->constant_pool, id); if (!s) { SWFDEC_ERROR ("constant pool size too small"); g_string_free (string, TRUE); return NULL; } g_string_append_c (string, '"'); g_string_append (string, s); g_string_append_c (string, '"'); } break; default: SWFDEC_ERROR ("Push: type %u not implemented", type); return JS_FALSE; } } return g_string_free (string, FALSE);}/* NB: constant pool actions are special in that they are called at init time */static gbooleanswfdec_debugger_add_command (gconstpointer bytecode, guint action, const guint8 *data, guint len, gpointer parserp){ ScriptParser *parser = parserp; SwfdecDebuggerCommand command; command.code = bytecode; command.breakpoint = 0; if (action == 0x96) { /* PUSH */ command.description = swfdec_debugger_print_push (parser, data, len); } else { command.description = swfdec_script_print_action (action, data, len); } g_array_append_val (parser->commands, command); if (action == 0x88) { /* constant pool */ if (parser->constant_pool) swfdec_constant_pool_free (parser->constant_pool); parser->constant_pool = swfdec_constant_pool_new_from_action (data, len); } return TRUE;}static SwfdecDebuggerScript *swfdec_debugger_script_new (SwfdecScript *script){ ScriptParser parser; SwfdecDebuggerScript *ret; ret = g_new0 (SwfdecDebuggerScript, 1); ret->script = script; swfdec_script_ref (script); parser.commands = g_array_new (TRUE, FALSE, sizeof (SwfdecDebuggerCommand)); if (script->constant_pool) { parser.constant_pool = swfdec_constant_pool_new_from_action ( script->constant_pool->data + 3, script->constant_pool->length - 3); } else { parser.constant_pool = NULL; } swfdec_script_foreach (script, swfdec_debugger_add_command, &parser); ret->n_commands = parser.commands->len; ret->commands = (SwfdecDebuggerCommand *) g_array_free (parser.commands, FALSE); if (parser.constant_pool) swfdec_constant_pool_free (parser.constant_pool); return ret;}static voidswfdec_debugger_script_free (SwfdecDebuggerScript *script){ guint i; g_assert (script); swfdec_script_unref (script->script); for (i = 0; i < script->n_commands; i++) { g_free (script->commands[i].description); } g_free (script->commands); g_free (script);}/*** SwfdecDebugger ***/enum { SCRIPT_ADDED, SCRIPT_REMOVED, BREAKPOINT, BREAKPOINT_ADDED, BREAKPOINT_REMOVED, MOVIE_ADDED, MOVIE_REMOVED, LAST_SIGNAL};G_DEFINE_TYPE (SwfdecDebugger, swfdec_debugger, SWFDEC_TYPE_PLAYER)guint signals [LAST_SIGNAL] = { 0, };static voidswfdec_debugger_dispose (GObject *object){ SwfdecDebugger *debugger = SWFDEC_DEBUGGER (object); swfdec_debugger_set_stepping (debugger, FALSE); g_assert (g_hash_table_size (debugger->scripts) == 0); g_hash_table_destroy (debugger->scripts); if (debugger->breakpoints) g_array_free (debugger->breakpoints, TRUE); G_OBJECT_CLASS (swfdec_debugger_parent_class)->dispose (object);}static voidswfdec_debugger_class_init (SwfdecDebuggerClass *klass){ GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = swfdec_debugger_dispose; signals[SCRIPT_ADDED] = g_signal_new ("script-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[SCRIPT_REMOVED] = g_signal_new ("script-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[BREAKPOINT] = g_signal_new ("breakpoint", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals[BREAKPOINT_ADDED] = g_signal_new ("breakpoint-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals[BREAKPOINT_REMOVED] = g_signal_new ("breakpoint-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals[MOVIE_ADDED] = g_signal_new ("movie-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); signals[MOVIE_REMOVED] = g_signal_new ("movie-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT);}static voidswfdec_debugger_init (SwfdecDebugger *debugger){ debugger->scripts = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) swfdec_debugger_script_free);}/** * swfdec_debugger_new: * * Creates a #SwfdecPlayer that can be debugged. * * Returns: a new #SwfdecDebugger **/SwfdecPlayer *swfdec_debugger_new (void){ SwfdecPlayer *player; swfdec_init (); player = g_object_new (SWFDEC_TYPE_DEBUGGER, NULL); return player;}voidswfdec_debugger_add_script (SwfdecDebugger *debugger, SwfdecScript *script){ SwfdecDebuggerScript *dscript = swfdec_debugger_script_new (script); g_hash_table_insert (debugger->scripts, script, dscript); g_signal_emit (debugger, signals[SCRIPT_ADDED], 0, dscript);}SwfdecDebuggerScript *swfdec_debugger_get_script (SwfdecDebugger *debugger, SwfdecScript *script){ SwfdecDebuggerScript *dscript = g_hash_table_lookup (debugger->scripts, script); return dscript;}voidswfdec_debugger_remove_script (SwfdecDebugger *debugger, SwfdecScript *script){ SwfdecDebuggerScript *dscript = g_hash_table_lookup (debugger->scripts, script);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -