00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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;
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
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
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
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
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