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 }
1.5.1