gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] gnash/server debugger.h debugger.cpp


From: Rob Savoye
Subject: [Gnash-commit] gnash/server debugger.h debugger.cpp
Date: Tue, 06 Feb 2007 21:10:08 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Rob Savoye <rsavoye>    07/02/06 21:10:08

Added files:
        server         : debugger.h debugger.cpp 

Log message:
        Oops, forgot to add the new files.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/server/debugger.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/debugger.cpp?cvsroot=gnash&rev=1.1

Patches:
Index: debugger.h
===================================================================
RCS file: debugger.h
diff -N debugger.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ debugger.h  6 Feb 2007 21:10:08 -0000       1.1
@@ -0,0 +1,133 @@
+// 
+//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifndef __DEBUGGER_H__
+#define __DEBUGGER_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef USE_DEBUGGER
+
+#include <string>
+#include <map>
+
+#include "as_environment.h"
+
+namespace gnash 
+{
+
+class Debugger {
+public:
+    Debugger();
+    ~Debugger();
+    // Return the default instance of Debugger
+    static Debugger& getDefaultInstance();
+
+    typedef enum {NONE, BREAK, CONTINUE, STOP} debug_state_e;
+    typedef enum {BOTH, WRITES, READS} watch_state_e;
+
+    void usage();
+//    bool command(const char cmd, as_environment &env);
+
+    void dissasemble(unsigned char *data);
+    void dissasemble();
+    void setBreakPoint(std::string &var);
+    void removeBreakPoint(std::string &var);
+    void dumpBreakPoints();
+
+    /// Set a watchpoint of a variable. Gnash stops and generates a
+    /// command prompt when there is a match.
+    void setWatchPoint(std::string &var, watch_state_e state);
+    void removeWatchPoint(std::string &var);
+    void dumpWatchPoints();
+
+    /// What to do when we've hit a breakpoint
+    void hitBreak() { _skipb--; };
+    
+    /// Execute the movie, skipping x breaks
+    void go(int x) { _skipb = x; };
+    bool isContinuing() { return (_skipb > 0) ? true : false; };
+
+    // These functions manipulate the environment stack
+    void dumpStackFrame(as_environment &env);
+    void dumpStackFrame();
+    void dumpLocalRegisters(as_environment &env);
+    void dumpLocalRegisters();
+    void dumpGlobalRegisters(as_environment &env);
+    void dumpGlobalRegisters();
+    void dumpLocalVariables(as_environment &env);
+    void dumpLocalVariables();
+    void setEnvStack(as_environment *x) { _env = x; };
+    as_environment *getEnvStack() { return _env; };
+
+    // 
+    void setFramePointer(unsigned char *x) { _pc = x; };
+    unsigned char *getFramePointer() { return _pc; };
+
+    void console(as_environment &env);
+    void console();
+    
+    /// Are the debugger features enabled ?
+    void enabled(bool x) { _enabled = x; };
+    bool isEnabled() { return _enabled; };
+
+    /// Print out a dissasembly as each opcode gets executed. This is
+    /// equivalant to -va, excpet it uses debugger syntax instead of
+    /// the more compact Debug log syntax.
+    void traceMode(bool x) { _tracing = x; };
+    /// is Trace Mode enabled ?
+    bool isTracing() { return _tracing; };
+
+    /// Are there any watchpoints set ?
+    int anyWatchPoints() { return _watchpoints.size(); };
+    /// Does the variable name match any watchpoints ?
+    bool matchWatchPoint(std::string &var, watch_state_e state);
+    
+    /// Are there any breakpoints set ?
+    int anyBreakPoints() { return _breakpoints.size(); };
+
+    // Manipulate a symbol table
+    void addSymbol(void *ptr, std::string name);
+    void *lookupSymbol(std::string &name);
+    std::string lookupSymbol(void *ptr);
+    void dumpSymbols();
+    
+    debug_state_e state() { return _state; };
+private:
+    bool                        _enabled;
+    bool                       _tracing;
+    debug_state_e               _state;
+    int                                _skipb;
+    as_environment            *_env;
+    unsigned char             *_pc;
+    std::map<std::string, watch_state_e> _watchpoints;
+    std::map<std::string, bool> _breakpoints;
+    std::map<void *, std::string> _symbols;
+};
+
+} // end of gnash namespace
+
+#endif // end of USE_DEBUGGER
+
+// __DEBUGGER_H__
+#endif
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:

Index: debugger.cpp
===================================================================
RCS file: debugger.cpp
diff -N debugger.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ debugger.cpp        6 Feb 2007 21:10:08 -0000       1.1
@@ -0,0 +1,581 @@
+// 
+//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string>
+#include <sstream>
+#include <map>
+
+#include "rc.h"
+#include "debugger.h"
+#include "log.h"
+#include "as_value.h"
+#include "as_environment.h"
+#include "swf.h"
+#include "ASHandlers.h"
+
+namespace {
+gnash::LogFile& dbglogfile = gnash::LogFile::getDefaultInstance();
+gnash::RcInitFile& rcfile = gnash::RcInitFile::getDefaultInstance();
+const gnash::SWF::SWFHandlers& ash = gnash::SWF::SWFHandlers::instance();
+}
+
+using namespace std;
+using namespace gnash::SWF;
+
+namespace gnash 
+{
+
+const char *as_arg_strs[] = {
+    "ARG_NONE",
+    "ARG_STR",
+    "ARG_HEX",
+    "ARG_U8",
+    "ARG_U16",
+    "ARG_S16",
+    "ARG_PUSH_DATA",
+    "ARG_DECL_DICT",
+    "ARG_FUNCTION2"
+};
+const char *state_strs[] = { "rw", "w", "r" };
+
+Debugger::Debugger() 
+    : _enabled(false), _tracing(false), _state(NONE), _skipb(0), _env(0), 
_pc(0)
+{
+//    GNASH_REPORT_FUNCTION;
+}
+
+Debugger::~Debugger()
+{
+//    GNASH_REPORT_FUNCTION;
+}
+
+Debugger&
+Debugger::getDefaultInstance()
+{
+       static Debugger dbg;
+       return dbg;
+}
+
+void
+Debugger::usage()
+{
+//    GNASH_REPORT_FUNCTION;
+    cerr << "Gnash Debugger" << endl;
+    cerr << "\t? - help" << endl;
+    cerr << "\tq - Quit" << endl;
+    cerr << "\tt - Toggle Trace Mode" << endl;
+    cerr << "\tc - Continue" << endl;
+    cerr << "\td - Dissasemble current line" << endl;
+    // info commands
+    cerr << "\ti f - Dump Stack Frame" << endl;
+    cerr << "\ti s - Dump symbols" << endl;
+    cerr << "\ti g - Global Regs" << endl;
+    cerr << "\ti l - Local Variables" << endl;
+    cerr << "\ti w - Dump watch points" << endl;
+    cerr << "\ti b - Dump break points" << endl;
+    // break and watch points
+    cerr << "\tw name [r:w:b] - set variable watchpoint" << endl;
+    cerr << "\tw name d - delete variable watchpoint" << endl;
+    cerr << "\tb name - set function break point" << endl;
+}
+
+void
+Debugger::console()
+{
+//    GNASH_REPORT_FUNCTION;
+    console(*_env);
+}
+
+// Open a user console for debugging commands. The abbreviations and
+// commands are roughly based on GDBs.
+void
+Debugger::console(as_environment &env)
+{
+//    GNASH_REPORT_FUNCTION;
+
+    // If the debugger isn't enabled, there is nothing to do.
+    if (!this->isEnabled()) {
+       return;
+    }
+    
+    if (_env == static_cast<as_environment *>(0)) {
+       cerr << "WARNING: environment not set yet";
+       cerr << "\nOnly watch point commands will work untill after you 
continue." << endl;
+    }
+//     if (this->isContinuing()) {
+//     this->hitBreak();
+//     } else {
+    string action;
+    string var, sstate;
+    Debugger::watch_state_e wstate;
+    bool keep_going = true;
+
+    dbglogfile << "Debugger enabled >> " << endl;
+    while (keep_going) {
+       cerr << "gnashdbg> ";
+       cin >> action;
+       switch (action[0]) {
+           // Quit Gnash.
+         case 'Q':
+         case 'q':
+             exit(0);
+             break;
+             // Continue executing.
+         case 'c':
+             this->go(10);
+             keep_going = false;
+             break;
+             // Informational commands.
+         case 'i':
+             cin >> var;
+             switch (var[0]) {
+               case 'd':
+                   this->dissasemble();
+                 break;
+               case 'b':
+                   this->dumpBreakPoints();
+                   break;
+               case 'w':
+                   this->dumpWatchPoints();
+                   break;
+               case 'r':
+                   this->dumpLocalRegisters(env);
+                   break;
+               case 'g':
+                   this->dumpGlobalRegisters(env);
+                   break;
+               case 'l':
+                   this->dumpLocalVariables(env);
+                   break;
+               case 'f':
+                   this->dumpStackFrame(env);
+                   break;
+               case 's':
+                   this->dumpSymbols();
+                   break;
+             };
+             break;
+             // Tracing mode. This prints a disasembly every time
+             // Gnash stops at a watch or break point.
+         case 't':
+             if (this->isTracing()) {
+                 this->traceMode(false);
+             } else {
+                 this->traceMode(true);
+             }
+             break;
+             // Print a help screen
+         case '?':
+             this->usage();
+             break;
+             // Set a watchpoint
+         case 'w':
+             cin >> var >> sstate;
+             switch (sstate[0]) {
+                 // Break on reads
+               case 'r':
+                   wstate = Debugger::READS;
+                   break;
+                   // Break on writes
+               case 'w':
+                   wstate = Debugger::WRITES;
+                   break;
+                   // Break on any accesses
+               case 'b':
+               default:
+                   wstate = Debugger::BOTH;
+                   break;
+             };
+             // Delete a watch point
+             if (sstate[0] == 'd') {
+                 this->removeWatchPoint(var);
+             } else {
+                 this->setWatchPoint(var, wstate);
+             }
+             break;
+         default:
+             break;
+       };
+    }
+}
+
+void
+Debugger::dissasemble()
+{
+//    GNASH_REPORT_FUNCTION;
+    this->dissasemble(_pc);
+}
+
+void
+Debugger::dissasemble(unsigned char *data)
+{
+//    GNASH_REPORT_FUNCTION;
+    as_arg_t fmt = ARG_HEX;
+    action_type        action_id = static_cast<action_type>(data[0]);
+    int val = 0;
+    string str;
+    unsigned char num[10];
+    memset(num, 0, 10);
+
+    if (_pc == 0) {
+    }
+    
+    // Show instruction.
+    if (action_id > ash.lastType()) {
+       cerr << "WARNING: <unknown>[0x" << action_id  << "]" << endl;
+    } else {
+       if (ash[action_id].getName().size() > 0) {
+           cerr << "Action: " << (void *)action_id << ": " << 
ash[action_id].getName().c_str() << endl;
+       } else {
+           cerr << "Action: " << (void *)action_id << ": " << "WARNING: 
unknown ID" << endl;
+       }
+       fmt = ash[action_id].getArgFormat();
+    }
+
+    // If we get a ActionPushData opcode, get the parameters
+    if (action_id & 0x80) {
+       int length = data[1] | (data[2] << 8);
+       cerr << "\tArg format is: " << as_arg_strs[fmt] << " Length is: " << 
length << endl;
+       switch (fmt) {
+         case ARG_NONE:
+             dbglogfile << "ERROR: No format flag!" << endl;
+             break;
+         case ARG_STR:
+             if ((length == 1) && (data[3] == 0)) {
+                 str = "null";
+             } else {
+                 for (int i = 0; i < length; i++) {
+                     if (data[3 + i] != 0) {
+                         str += data[3 + i];
+                     } else {
+                         break;
+                     }
+                 }
+             }
+             cerr << "Got string (" << length << " bytes): " << "\"" << str << 
"\"" << endl;
+             break;
+         case ARG_HEX:
+             for (int i = 0; i < length; i++) {
+                 hexify(num, (const unsigned char *)&data[3 + i], 1, false);
+                 cerr << "0x" << num << " ";
+             }
+             cerr << endl;
+//           cerr << "FIXME: Got hex: " << num << endl;
+             break;
+         case ARG_U8:
+             val = data[3];
+//           cerr << "FIXME: Got u8: " << val << endl;
+             break;
+         case ARG_U16:
+             val = data[3] | (data[4] << 8);
+//           cerr << "FIXME: Got u16: " << val << endl;
+             break;
+         case ARG_S16:
+             val = data[3] | (data[4] << 8);
+             if (val & 0x8000) {
+                 val |= ~0x7FFF;       // sign-extend
+             }
+//           cerr << "FIXME: Got s16: " << val << endl;
+             break;
+         case ARG_PUSH_DATA:
+             break;
+         case ARG_DECL_DICT:
+             break;
+         case ARG_FUNCTION2:
+             break;
+         default:
+             dbglogfile << "ERROR: No format flag!" << endl;
+             break;
+       } // end of switch(fmt)
+    }
+}
+
+void
+Debugger::setBreakPoint(std::string & /* asname */)
+{
+//    GNASH_REPORT_FUNCTION;
+    dbglogfile << "WARNING: " << __PRETTY_FUNCTION__ << " is unimplemented!" 
<< endl;
+}
+
+void
+Debugger::removeBreakPoint(std::string &var)
+{
+//    GNASH_REPORT_FUNCTION;
+    
+    string name;
+    std::map<std::string, bool>::const_iterator it;
+    it = _breakpoints.find(var);
+    if (it != _breakpoints.end()) {
+       _breakpoints.erase(var);
+    }
+}
+
+void
+Debugger::dumpBreakPoints()
+{
+//    GNASH_REPORT_FUNCTION;
+    string name;
+    bool val;
+    std::map<std::string, bool>::const_iterator it;
+    
+    for (it=_breakpoints.begin(); it != _breakpoints.end(); it++) {
+       name = it->first;
+       val = it->second;
+       if (name.size()) {
+           dbglogfile << name << endl;
+       }
+    }
+}
+
+void
+Debugger::setWatchPoint(std::string &var, watch_state_e state)
+{
+//    GNASH_REPORT_FUNCTION;
+    _watchpoints[var] = state;
+    dbglogfile << "Setting watchpoint for variable: \"" << var << "" << endl;
+}
+
+void
+Debugger::removeWatchPoint(std::string &var)
+{
+//    GNASH_REPORT_FUNCTION;
+    
+    string name;
+    std::map<std::string, watch_state_e>::const_iterator it;
+    it = _watchpoints.find(var);
+    if (it != _watchpoints.end()) {
+       _watchpoints.erase(var);
+    }
+}
+
+void
+Debugger::dumpWatchPoints()
+{
+//    GNASH_REPORT_FUNCTION;
+    string name;
+    watch_state_e state;
+    int index = 0;
+    std::map<std::string, watch_state_e>::const_iterator it;
+    
+    for (it=_watchpoints.begin(); it != _watchpoints.end(); it++) {
+       name = it->first;
+       state = it->second;
+       index++;
+       if (name.size()) {
+           cerr << "\twatch #" << index << ": " << name
+                << " \"" << state_strs[state] << "\"" << endl;
+       }
+    }
+}
+
+bool
+Debugger::matchWatchPoint(std::string &var, watch_state_e state)
+{
+//    GNASH_REPORT_FUNCTION;
+    std::map<std::string, watch_state_e>::const_iterator it;
+    it =_watchpoints.find(var);
+    if (it == _watchpoints.end()) {
+       dbglogfile << "No Match for variable \"" << var << "\"" << endl;
+       return false;
+    } else {
+       if (state == _watchpoints[var]) {
+           dbglogfile << "Matched for variable \"" << var << "\": \""
+                      << state_strs[state] << "\"" << endl;
+           this->console();
+           return true;
+       }
+       return false;
+    }
+}
+
+// These functions manipulate the environment stack
+void
+Debugger::dumpStackFrame()
+{
+//    GNASH_REPORT_FUNCTION;
+    if (_env == 0) {
+       dbglogfile << "WARNING: environment not set in " << __PRETTY_FUNCTION__ 
<< endl;
+       return;
+    }
+    this->dumpStackFrame(*_env);
+}
+
+void
+Debugger::dumpStackFrame(as_environment &env)
+{
+//    GNASH_REPORT_FUNCTION;    
+    if (_env == static_cast<as_environment *>(0)) {
+       dbglogfile << "WARNING: environment not set in " << __PRETTY_FUNCTION__ 
<< endl;
+       return;
+    }
+    if (env.stack_size()) {
+        dbglogfile << "Stack Dump of: " << (void *)&env << endl;
+        for (unsigned int i=0, n=env.stack_size(); i<n; i++) {
+            cerr << "\t" << i << ": \"" << env.m_stack[i].to_string() << "\"";
+           as_value val = env.m_stack[i];
+// FIXME: we want to print the name of the function
+//         if (val.is_as_function()) {
+//         }
+//         string name = this->lookupSymbol(val.to_object());
+//         if (name.size()) {
+//             cerr << "NAME IS: " << name << endl;
+//         }
+           
+           if (val.is_object()) {
+               cerr << " has #" << val.to_object()->get_ref_count() << " 
references";
+           }
+           cerr << endl;
+        }
+    }
+    else {
+        dbglogfile << "Stack Dump of 0x" << (void *)&env << ": empty" << endl;
+    }
+}
+
+void
+Debugger::dumpLocalRegisters()
+{
+//    GNASH_REPORT_FUNCTION;
+    this->dumpLocalRegisters(*_env);
+}
+
+void
+Debugger::dumpLocalRegisters(as_environment &env)
+{
+//    GNASH_REPORT_FUNCTION;
+    if (_env == static_cast<as_environment *>(0)) {
+       dbglogfile << "WARNING: environment not set in " << __PRETTY_FUNCTION__ 
<< endl;
+       return;
+    }
+    size_t n=env.num_local_registers();
+    if ( ! n ) {
+        return;
+    }
+    dbglogfile << "Local Register Dump: " << endl;
+    for (unsigned int i=0; i<n; i++) {
+        cerr << "\treg #" << i << ": \"" << env.local_register(i).to_string() 
<< "\"" << endl;
+    }
+}
+
+void
+Debugger::dumpGlobalRegisters()
+{
+//    GNASH_REPORT_FUNCTION;
+    this->dumpGlobalRegisters(*_env);
+}
+
+void
+Debugger::dumpGlobalRegisters(as_environment &env)
+{
+//    GNASH_REPORT_FUNCTION;  
+    if (_env == static_cast<as_environment *>(0)) {
+       dbglogfile << "WARNING: environment not set in " << __PRETTY_FUNCTION__ 
<< endl;
+       return;
+    }
+    std::string registers;
+    stringstream ss;
+    dbglogfile << "Global Registers Dump:" << endl;
+    for (unsigned int i=0; i<4; ++i) {
+       ss << "\treg #" << i << ": \"";
+       ss << env.global_register(i).to_std_string() << "\"" << endl;
+    }
+    cerr << ss.str().c_str() << endl;
+}
+
+void
+Debugger::dumpLocalVariables()
+{
+//    GNASH_REPORT_FUNCTION;
+    this->dumpLocalVariables(*_env);
+}
+
+void
+Debugger::dumpLocalVariables(as_environment &env)
+{
+//    GNASH_REPORT_FUNCTION;
+    if (_env == static_cast<as_environment *>(0)) {
+       dbglogfile << "WARNING: environment not set in " << __PRETTY_FUNCTION__ 
<< endl;
+       return;
+    }
+    dbglogfile << "Local variable Dump:" << endl;
+    as_environment::frame_slot slot;
+    for (size_t i = 0, n=env.get_local_frame_top(); i < n; ++i) {
+        slot  = env.m_local_frames[i];
+       cerr << "\t" << slot.m_name << " = " << slot.m_value.to_std_string() << 
endl;
+    }
+}
+
+/// Get the address associated with a name
+void *
+Debugger::lookupSymbol(std::string &name)
+{
+    GNASH_REPORT_FUNCTION;
+    std::map<void *, std::string>::const_iterator it;
+    for (it=_symbols.begin(); it != _symbols.end(); it++) {
+       if (it->second == name) {
+           dbglogfile << "Found symbol " << name.c_str() << " at address: " << 
it->first << endl;
+           return it->first;
+       }
+    }
+    return static_cast<void *>(0);
+}
+
+void
+Debugger::addSymbol(void *ptr, std::string name)
+{
+    GNASH_REPORT_FUNCTION;
+    dbglogfile << "Adding symbol " << name << " at address: " << ptr << endl;
+    _symbols[ptr] = name;
+}
+
+
+/// Get the name associated with an address
+std::string
+Debugger::lookupSymbol(void *ptr)
+{
+    GNASH_REPORT_FUNCTION;
+    std::map<void *, std::string>::const_iterator it;
+    it = _symbols.find(ptr);
+    if (it != _symbols.end()) {
+       dbglogfile << "Found symbol " << it->second.c_str() << " at address: " 
<< ptr << endl;
+       return it->second;
+    }    
+}
+
+void
+Debugger::dumpSymbols()
+{
+//    GNASH_REPORT_FUNCTION;
+    std::map<void *, std::string>::const_iterator it;    
+    for (it=_symbols.begin(); it != _symbols.end(); it++) {
+       string name = it->second;
+       void *addr = it->first;
+       if (name.size()) {
+           cerr << addr << ": " << name << endl;
+       }
+    }
+}
+
+} // end of gnash namespace
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:




reply via email to

[Prev in Thread] Current Thread [Next in Thread]