ucdebugging.cc

Go to the documentation of this file.
00001 /*
00002  *  ucdebugging.cc - Debugging-related functions for usecode
00003  *
00004  *  Copyright (C) 2002  The Exult Team
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019  */
00020 
00021 #ifdef HAVE_CONFIG_H
00022 #  include <config.h>
00023 #endif
00024 
00025 #include "ucdebugging.h"
00026 #include "ucinternal.h"
00027 #include "stackframe.h"
00028 #include "ucfunction.h"
00029 #include "utils.h"
00030 
00031 #include "servemsg.h"
00032 #include "debugmsg.h"
00033 
00034 Breakpoint::Breakpoint(bool once)
00035 {
00036   this->once = once;
00037   id = Breakpoints::getNewID();
00038 }
00039 
00040 AnywhereBreakpoint::AnywhereBreakpoint()
00041   : Breakpoint(true)
00042 { }
00043 
00044 LocationBreakpoint::LocationBreakpoint(int functionid, int ip, bool once)
00045   : Breakpoint(once)
00046 {
00047   this->functionid = functionid;
00048   this->ip = ip;
00049 }
00050 
00051 bool LocationBreakpoint::check(Stack_frame *frame) const
00052 {
00053   return (frame->function->id == functionid) &&
00054     ((int)(frame->ip - frame->code) == ip);
00055 }
00056 
00057 void LocationBreakpoint::serialize(int fd) const
00058 {
00059   unsigned char d[13];
00060   d[0] = (unsigned char)(Exult_server::dbg_set_location_bp);
00061   unsigned char *dptr = &d[1];
00062   Write4(dptr, functionid);
00063   Write4(dptr, ip);
00064   Write4(dptr, id);
00065   Exult_server::Send_data(fd, Exult_server::usecode_debugging, d, 13);  
00066 }
00067 
00068 StepoverBreakpoint::StepoverBreakpoint(Stack_frame* frame)
00069   : Breakpoint(true)
00070 {
00071   call_chain = frame->call_chain;
00072   call_depth = frame->call_depth;
00073 }
00074 
00075 bool StepoverBreakpoint::check(Stack_frame *frame) const
00076 {
00077   return ((frame->call_chain == call_chain &&
00078        frame->call_depth <= call_depth) ||
00079 
00080       (frame->call_chain < call_chain));
00081 }
00082 
00083 FinishBreakpoint::FinishBreakpoint(Stack_frame* frame)
00084   : Breakpoint(true)
00085 {
00086   call_chain = frame->call_chain;
00087   call_depth = frame->call_depth;
00088 }
00089 
00090 bool FinishBreakpoint::check(Stack_frame *frame) const
00091 {
00092   return ((frame->call_chain == call_chain &&
00093        frame->call_depth < call_depth) ||
00094 
00095       (frame->call_chain < call_chain));
00096 }
00097 
00098 
00099 
00100 int Breakpoints::lastID = 0;
00101 
00102 Breakpoints::Breakpoints()
00103 {
00104 }
00105 
00106 Breakpoints::~Breakpoints()
00107 {
00108   std::list<Breakpoint*>::iterator iter;
00109 
00110   // clear queue
00111   for (iter = breaks.begin(); iter != breaks.end(); ++iter)
00112   {
00113     delete (*iter);
00114   }
00115 }
00116 
00117 
00118 // returns ID of a (any) breakpoint encountered, or -1 if no breakpoints
00119 int Breakpoints::check(Stack_frame* frame)
00120 {
00121   // check all breakpoints (always check all of them, even if match found)
00122   // and delete the matching ones with 'once' set
00123 
00124   // question: do we really want to delete a breakpoint (with once set)
00125   // as soon as it is triggered? (or wait a while until it has been
00126   // processed properly?)
00127   // also, it might be necessary to return a list of all matching and/or
00128   // deleted breakpoints
00129   // OTOH, which 'once' breakpoint is hit is generally not interesting,
00130   // and also, only one of these will be set, usually.
00131 
00132   int breakID = -1;
00133 
00134   std::list<Breakpoint*>::iterator iter;
00135 
00136   for (iter = breaks.begin(); iter != breaks.end(); ++iter)
00137   {
00138     if ((*iter)->check(frame)) {
00139       breakID = (*iter)->id;
00140       if ((*iter)->once) {
00141         delete (*iter);
00142         (*iter) = 0;
00143       }
00144     }
00145   }
00146 
00147   breaks.remove((Breakpoint*)0); // delete all NULLs from the list
00148 
00149   return breakID;
00150 }
00151 
00152 void Breakpoints::add(Breakpoint* breakpoint)
00153 {
00154   breaks.remove(breakpoint); // avoid double occurences
00155 
00156   breaks.push_back(breakpoint);
00157 }
00158 
00159 void Breakpoints::remove(Breakpoint* breakpoint)
00160 {
00161   breaks.remove(breakpoint);
00162 }
00163 
00164 bool Breakpoints::remove(int id)
00165 {
00166   bool found = false;
00167 
00168   std::list<Breakpoint*>::iterator iter;
00169 
00170   for (iter = breaks.begin(); iter != breaks.end(); ++iter)
00171   {
00172     if ((*iter)->id == id) {
00173       found = true;
00174       delete (*iter);
00175       (*iter) = 0;
00176     }
00177   }
00178 
00179   breaks.remove((Breakpoint*)0); // delete all NULLs from the list
00180 
00181   return found;
00182 }
00183 
00184 void Breakpoints::transmit(int fd)
00185 {
00186   std::list<Breakpoint*>::iterator iter;
00187 
00188   for (iter = breaks.begin(); iter != breaks.end(); ++iter)
00189     (*iter)->serialize(fd);
00190 }

Generated on Mon Jul 9 14:42:52 2007 for ExultEngine by  doxygen 1.5.1