debugserver.cc

Go to the documentation of this file.
00001 /*
00002  *  debugserver.cc: handle usecode debugging messages from client
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 #if (defined(USE_EXULTSTUDIO) && defined(USECODE_DEBUGGER))
00026 
00027 #include <iostream>
00028 #include <iomanip>
00029 
00030 #include "servemsg.h"
00031 #include "server.h"
00032 #include "gamewin.h"
00033 #include "ucinternal.h"
00034 #include "debugserver.h"
00035 #include "debugmsg.h"
00036 #include "ucdebugging.h"
00037 #include "utils.h"
00038 #include "stackframe.h"
00039 #include "ucserial.h"
00040 #include "useval.h"
00041 #include "ucfunction.h"
00042 
00043 // message handler that only handles debugging messages. 
00044 void Handle_client_debug_message(int& fd)
00045 {
00046   unsigned char data[Exult_server::maxlength];
00047   Exult_server::Msg_type id;
00048   int datalen = Exult_server::Receive_data(fd, id, data, sizeof(data));
00049   if (datalen < 0)
00050     return;
00051   switch (id) {
00052   case Exult_server::usecode_debugging:
00053     Handle_debug_message(&data[0], datalen);
00054     break;
00055   default:
00056     // maybe reply something like "unable to handle message" ?
00057     break;
00058   }
00059 
00060 }
00061 
00062 void Handle_debug_message(unsigned char* data, int datalen)
00063 {
00064   Usecode_machine *ucm = Game_window::get_instance()->get_usecode();
00065   Usecode_internal *uci = dynamic_cast<Usecode_internal*>(ucm);
00066   
00067   if (uci == 0)
00068     return; // huh?
00069 
00070   Exult_server::Debug_msg_type id = (Exult_server::Debug_msg_type)data[0];
00071 
00072   unsigned char *ptr = data;
00073 
00074   if (uci->is_on_breakpoint()) {
00075     // accept extra messages now
00076 
00077     switch(id) {
00078     case Exult_server::dbg_continue:
00079       uci->set_breakpoint_action(0);
00080       break;
00081     case Exult_server::dbg_stepinto:
00082       uci->set_breakpoint_action(0);
00083       uci->set_breakpoint();
00084       break;
00085     case Exult_server::dbg_stepover:
00086       uci->set_breakpoint_action(0);
00087       uci->dbg_stepover();
00088       break;
00089     case Exult_server::dbg_finish:
00090       uci->set_breakpoint_action(0);
00091       uci->dbg_finish();
00092       break;
00093     case Exult_server::dbg_get_callstack:
00094     {
00095       unsigned char d[3];
00096       d[0] = (unsigned char)Exult_server::dbg_callstack;
00097       unsigned char* ptr = &d[1];
00098       int callstacksize = uci->get_callstack_size();
00099       Write2(ptr, callstacksize);
00100       Exult_server::Send_data(client_socket,
00101                   Exult_server::usecode_debugging,
00102                   d, 3);
00103       for (int i=0; i < callstacksize; i++) {
00104         Stack_frame *frame = uci->get_stackframe(i);
00105         Stack_frame_out(client_socket,
00106                 frame->function->id,
00107                 (int)(frame->ip - frame->code),
00108                 frame->call_chain,
00109                 frame->call_depth,
00110                 frame->eventid,
00111                 (long)frame->caller_item,
00112                 frame->num_args,
00113                 frame->num_vars,
00114                 frame->locals);
00115       }
00116       break;
00117     }
00118     case Exult_server::dbg_get_stack:
00119     {
00120       Usecode_value zeroval((int)0);
00121       unsigned char data[Exult_server::maxlength];
00122       unsigned char* ptr = &data[0];
00123       *ptr++ = (unsigned char)Exult_server::dbg_stack;
00124       int stacksize = uci->get_stack_size();
00125       Write2(ptr, stacksize);
00126       int remaining = Exult_server::maxlength - 3;
00127       for (int i=0; i < stacksize; i++) {
00128         Usecode_value* val = uci->peek_stack(i);
00129         int vallen = -1;
00130         if (val) {
00131           vallen = val->save(ptr, remaining);
00132         }
00133         if (vallen == -1) {
00134           if (remaining >= 5)
00135             vallen = zeroval.save(ptr, remaining);
00136           std::cerr << "Error: stack larger than max. message!"
00137                 << std::endl;
00138         }
00139         if (vallen != -1) {
00140           remaining -= vallen;
00141           ptr += vallen;
00142         }
00143       }
00144       Exult_server::Send_data(client_socket,
00145                   Exult_server::usecode_debugging,
00146                   data, Exult_server::maxlength - remaining);
00147       break;
00148     }
00149     default:
00150       break;
00151     }
00152   }
00153 
00154   // these messages can always be handled
00155   switch(id) {
00156   case Exult_server::dbg_break:
00157     uci->set_breakpoint();
00158     break;
00159   case Exult_server::dbg_get_status:
00160   {
00161     unsigned char c;
00162     if (uci->is_on_breakpoint()) {
00163       c = (unsigned char)Exult_server::dbg_on_breakpoint;
00164     } else {
00165       c = (unsigned char)Exult_server::dbg_continuing;
00166     }
00167     Exult_server::Send_data(client_socket,
00168                 Exult_server::usecode_debugging,
00169                 &c, 1);
00170     break;
00171   }
00172   case Exult_server::dbg_set_location_bp:
00173   {
00174     ptr++;
00175     int funcid = Read4(ptr);
00176     int ip = Read4(ptr);
00177 
00178     std::cout << "Setting breakpoint at " << std::hex << std::setfill('0')
00179           << std::setw(4) << funcid << ", " << std::setw(4) << ip 
00180           << std::setfill(' ') << std::dec << std::endl;
00181 
00182     // +++++ check for duplicates?
00183 
00184     int breakpoint_id = uci->set_location_breakpoint(funcid, ip);
00185     unsigned char d[13];
00186     d[0] = (unsigned char)(Exult_server::dbg_set_location_bp);
00187     unsigned char *dptr = &d[1];
00188     Write4(dptr, funcid);
00189     Write4(dptr, ip);
00190     Write4(dptr, breakpoint_id);
00191     Exult_server::Send_data(client_socket,
00192                 Exult_server::usecode_debugging,
00193                 d, 13);
00194     break;
00195   }
00196   case Exult_server::dbg_clear_breakpoint:
00197   {
00198     ptr++;
00199     int breakpoint_id = Read4(ptr);
00200     bool ok = uci->clear_breakpoint(breakpoint_id);
00201     if (ok) {
00202       // reply
00203       Exult_server::Send_data(client_socket,
00204                   Exult_server::usecode_debugging,
00205                   data, 5);
00206     }
00207     break;
00208   }
00209   case Exult_server::dbg_get_breakpoints:
00210   {
00211     uci->transmit_breakpoints(client_socket);
00212     break;
00213   }
00214   default:
00215     break;
00216   }
00217 
00218 }
00219 
00220 
00221 #endif

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