ROM -> RAM -> ROM, waiting for debug int.
[riscv-isa-sim.git] / riscv / gdbserver.cc
1 #include <arpa/inet.h>
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <sys/socket.h>
7 #include <sys/types.h>
8 #include <unistd.h>
9
10 #include <algorithm>
11 #include <cassert>
12 #include <cstdio>
13 #include <vector>
14
15 #include "disasm.h"
16 #include "sim.h"
17 #include "gdbserver.h"
18 #include "mmu.h"
19
20 #define C_EBREAK 0x9002
21 #define EBREAK 0x00100073
22
23 // Functions to generate RISC-V opcodes.
24 // TODO: Does this already exist somewhere?
25
26 static uint32_t bits(uint32_t value, unsigned int hi, unsigned int lo) {
27 return (value >> lo) & ((1 << (hi+1-lo)) - 1);
28 }
29 static uint32_t bit(uint32_t value, unsigned int b) {
30 return (value >> b) & 1;
31 }
32
33 static uint32_t jal(unsigned int rd, uint32_t imm) {
34 return (bit(imm, 20) << 31) |
35 (bits(imm, 10, 1) << 21) |
36 (bit(imm, 11) << 20) |
37 (bits(imm, 19, 12) << 12) |
38 (rd << 7) |
39 0x6f;
40 }
41
42 template <typename T>
43 unsigned int circular_buffer_t<T>::size() const
44 {
45 if (end >= start)
46 return end - start;
47 else
48 return end + capacity - start;
49 }
50
51 template <typename T>
52 void circular_buffer_t<T>::consume(unsigned int bytes)
53 {
54 start = (start + bytes) % capacity;
55 }
56
57 template <typename T>
58 unsigned int circular_buffer_t<T>::contiguous_empty_size() const
59 {
60 if (end >= start)
61 if (start == 0)
62 return capacity - end - 1;
63 else
64 return capacity - end;
65 else
66 return start - end - 1;
67 }
68
69 template <typename T>
70 unsigned int circular_buffer_t<T>::contiguous_data_size() const
71 {
72 if (end >= start)
73 return end - start;
74 else
75 return capacity - start;
76 }
77
78 template <typename T>
79 void circular_buffer_t<T>::data_added(unsigned int bytes)
80 {
81 end += bytes;
82 assert(end <= capacity);
83 if (end == capacity)
84 end = 0;
85 }
86
87 template <typename T>
88 void circular_buffer_t<T>::reset()
89 {
90 start = 0;
91 end = 0;
92 }
93
94 template <typename T>
95 void circular_buffer_t<T>::append(const T *src, unsigned int count)
96 {
97 unsigned int copy = std::min(count, contiguous_empty_size());
98 memcpy(contiguous_empty(), src, copy * sizeof(T));
99 data_added(copy);
100 count -= copy;
101 if (count > 0) {
102 assert(count < contiguous_empty_size());
103 memcpy(contiguous_empty(), src, count * sizeof(T));
104 data_added(count);
105 }
106 }
107
108 gdbserver_t::gdbserver_t(uint16_t port, sim_t *sim) :
109 sim(sim),
110 client_fd(0),
111 recv_buf(64 * 1024), send_buf(64 * 1024)
112 {
113 socket_fd = socket(AF_INET, SOCK_STREAM, 0);
114 if (socket_fd == -1) {
115 fprintf(stderr, "failed to make socket: %s (%d)\n", strerror(errno), errno);
116 abort();
117 }
118
119 fcntl(socket_fd, F_SETFL, O_NONBLOCK);
120 int reuseaddr = 1;
121 if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
122 sizeof(int)) == -1) {
123 fprintf(stderr, "failed setsockopt: %s (%d)\n", strerror(errno), errno);
124 abort();
125 }
126
127 struct sockaddr_in addr;
128 memset(&addr, 0, sizeof(addr));
129 addr.sin_family = AF_INET;
130 addr.sin_addr.s_addr = INADDR_ANY;
131 addr.sin_port = htons(port);
132
133 if (bind(socket_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
134 fprintf(stderr, "failed to bind socket: %s (%d)\n", strerror(errno), errno);
135 abort();
136 }
137
138 if (listen(socket_fd, 1) == -1) {
139 fprintf(stderr, "failed to listen on socket: %s (%d)\n", strerror(errno), errno);
140 abort();
141 }
142 }
143
144 void gdbserver_t::write_debug_ram(unsigned int index, uint32_t value)
145 {
146 char *ram = sim->debug_ram() + 4 * index;
147 ram[0] = value & 0xff;
148 ram[1] = (value >> 8) & 0xff;
149 ram[2] = (value >> 16) & 0xff;
150 ram[3] = (value >> 24) & 0xff;
151 }
152
153 void gdbserver_t::accept()
154 {
155 client_fd = ::accept(socket_fd, NULL, NULL);
156 if (client_fd == -1) {
157 if (errno == EAGAIN) {
158 // No client waiting to connect right now.
159 } else {
160 fprintf(stderr, "failed to accept on socket: %s (%d)\n", strerror(errno),
161 errno);
162 abort();
163 }
164 } else {
165 fcntl(client_fd, F_SETFL, O_NONBLOCK);
166
167 expect_ack = false;
168 extended_mode = false;
169
170 // gdb wants the core to be halted when it attaches.
171 processor_t *p = sim->get_core(0);
172 write_debug_ram(0, jal(0, (uint32_t) (DEBUG_ROM_START + 4 - DEBUG_RAM_START)));
173 p->set_debug_int();
174 }
175 }
176
177 void gdbserver_t::read()
178 {
179 // Reading from a non-blocking socket still blocks if there is no data
180 // available.
181
182 size_t count = recv_buf.contiguous_empty_size();
183 assert(count > 0);
184 ssize_t bytes = ::read(client_fd, recv_buf.contiguous_empty(), count);
185 if (bytes == -1) {
186 if (errno == EAGAIN) {
187 // We'll try again the next call.
188 } else {
189 fprintf(stderr, "failed to read on socket: %s (%d)\n", strerror(errno), errno);
190 abort();
191 }
192 } else if (bytes == 0) {
193 // The remote disconnected.
194 client_fd = 0;
195 processor_t *p = sim->get_core(0);
196 // TODO p->set_halted(false, HR_NONE);
197 recv_buf.reset();
198 send_buf.reset();
199 } else {
200 recv_buf.data_added(bytes);
201 }
202 }
203
204 void gdbserver_t::write()
205 {
206 if (send_buf.empty())
207 return;
208
209 while (!send_buf.empty()) {
210 unsigned int count = send_buf.contiguous_data_size();
211 assert(count > 0);
212 ssize_t bytes = ::write(client_fd, send_buf.contiguous_data(), count);
213 if (bytes == -1) {
214 fprintf(stderr, "failed to write to socket: %s (%d)\n", strerror(errno), errno);
215 abort();
216 } else if (bytes == 0) {
217 // Client can't take any more data right now.
218 break;
219 } else {
220 fprintf(stderr, "wrote %ld bytes: ", bytes);
221 for (unsigned int i = 0; i < bytes; i++) {
222 fprintf(stderr, "%c", send_buf[i]);
223 }
224 fprintf(stderr, "\n");
225 send_buf.consume(bytes);
226 }
227 }
228 }
229
230 void print_packet(const std::vector<uint8_t> &packet)
231 {
232 for (uint8_t c : packet) {
233 if (c >= ' ' and c <= '~')
234 fprintf(stderr, "%c", c);
235 else
236 fprintf(stderr, "\\x%x", c);
237 }
238 fprintf(stderr, "\n");
239 }
240
241 uint8_t compute_checksum(const std::vector<uint8_t> &packet)
242 {
243 uint8_t checksum = 0;
244 for (auto i = packet.begin() + 1; i != packet.end() - 3; i++ ) {
245 checksum += *i;
246 }
247 return checksum;
248 }
249
250 uint8_t character_hex_value(uint8_t character)
251 {
252 if (character >= '0' && character <= '9')
253 return character - '0';
254 if (character >= 'a' && character <= 'f')
255 return 10 + character - 'a';
256 if (character >= 'A' && character <= 'F')
257 return 10 + character - 'A';
258 return 0xff;
259 }
260
261 uint8_t extract_checksum(const std::vector<uint8_t> &packet)
262 {
263 return character_hex_value(*(packet.end() - 1)) +
264 16 * character_hex_value(*(packet.end() - 2));
265 }
266
267 void gdbserver_t::process_requests()
268 {
269 // See https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html
270
271 while (!recv_buf.empty()) {
272 std::vector<uint8_t> packet;
273 for (unsigned int i = 0; i < recv_buf.size(); i++) {
274 uint8_t b = recv_buf[i];
275
276 if (packet.empty() && expect_ack && b == '+') {
277 recv_buf.consume(1);
278 break;
279 }
280
281 if (packet.empty() && b == 3) {
282 fprintf(stderr, "Received interrupt\n");
283 recv_buf.consume(1);
284 handle_interrupt();
285 break;
286 }
287
288 if (b == '$') {
289 // Start of new packet.
290 if (!packet.empty()) {
291 fprintf(stderr, "Received malformed %ld-byte packet from debug client: ",
292 packet.size());
293 print_packet(packet);
294 recv_buf.consume(i);
295 break;
296 }
297 }
298
299 packet.push_back(b);
300
301 // Packets consist of $<packet-data>#<checksum>
302 // where <checksum> is
303 if (packet.size() >= 4 &&
304 packet[packet.size()-3] == '#') {
305 handle_packet(packet);
306 recv_buf.consume(i+1);
307 break;
308 }
309 }
310 // There's a partial packet in the buffer. Wait until we get more data to
311 // process it.
312 if (packet.size()) {
313 break;
314 }
315 }
316 }
317
318 void gdbserver_t::handle_halt_reason(const std::vector<uint8_t> &packet)
319 {
320 send_packet("S00");
321 }
322
323 void gdbserver_t::handle_general_registers_read(const std::vector<uint8_t> &packet)
324 {
325 // Register order that gdb expects is:
326 // "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
327 // "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
328 // "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
329 // "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
330
331 // Each byte of register data is described by two hex digits. The bytes with
332 // the register are transmitted in target byte order. The size of each
333 // register and their position within the ‘g’ packet are determined by the
334 // gdb internal gdbarch functions DEPRECATED_REGISTER_RAW_SIZE and
335 // gdbarch_register_name.
336
337 send("$");
338 running_checksum = 0;
339 processor_t *p = sim->get_core(0);
340 for (int r = 0; r < 32; r++) {
341 send(p->state.XPR[r]);
342 }
343 send_running_checksum();
344 expect_ack = true;
345 }
346
347 // First byte is the most-significant one.
348 // Eg. "08675309" becomes 0x08675309.
349 uint64_t consume_hex_number(std::vector<uint8_t>::const_iterator &iter,
350 std::vector<uint8_t>::const_iterator end)
351 {
352 uint64_t value = 0;
353
354 while (iter != end) {
355 uint8_t c = *iter;
356 uint64_t c_value = character_hex_value(c);
357 if (c_value > 15)
358 break;
359 iter++;
360 value <<= 4;
361 value += c_value;
362 }
363 return value;
364 }
365
366 // First byte is the least-significant one.
367 // Eg. "08675309" becomes 0x09536708
368 uint64_t consume_hex_number_le(std::vector<uint8_t>::const_iterator &iter,
369 std::vector<uint8_t>::const_iterator end)
370 {
371 uint64_t value = 0;
372 unsigned int shift = 4;
373
374 while (iter != end) {
375 uint8_t c = *iter;
376 uint64_t c_value = character_hex_value(c);
377 if (c_value > 15)
378 break;
379 iter++;
380 value |= c_value << shift;
381 if ((shift % 8) == 0)
382 shift += 12;
383 else
384 shift -= 4;
385 }
386 return value;
387 }
388
389 void consume_string(std::string &str, std::vector<uint8_t>::const_iterator &iter,
390 std::vector<uint8_t>::const_iterator end, uint8_t separator)
391 {
392 while (iter != end && *iter != separator) {
393 str.append(1, (char) *iter);
394 iter++;
395 }
396 }
397
398 // gdb's register list is defined in riscv_gdb_reg_names gdb/riscv-tdep.c in
399 // its source tree. We must interpret the numbers the same here.
400 enum {
401 REG_XPR0 = 0,
402 REG_XPR31 = 31,
403 REG_PC = 32,
404 REG_FPR0 = 33,
405 REG_FPR31 = 64,
406 REG_CSR0 = 65,
407 REG_CSR4095 = 4160,
408 REG_END = 4161
409 };
410
411 void gdbserver_t::handle_register_read(const std::vector<uint8_t> &packet)
412 {
413 // p n
414
415 std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
416 unsigned int n = consume_hex_number(iter, packet.end());
417 if (*iter != '#')
418 return send_packet("E01");
419
420 processor_t *p = sim->get_core(0);
421 send("$");
422 running_checksum = 0;
423
424 if (n >= REG_XPR0 && n <= REG_XPR31) {
425 send(p->state.XPR[n - REG_XPR0]);
426 } else if (n == REG_PC) {
427 send(p->state.pc);
428 } else if (n >= REG_FPR0 && n <= REG_FPR31) {
429 send(p->state.FPR[n - REG_FPR0]);
430 } else if (n >= REG_CSR0 && n <= REG_CSR4095) {
431 try {
432 send(p->get_csr(n - REG_CSR0));
433 } catch(trap_t& t) {
434 // It would be nicer to return an error here, but if you do that then gdb
435 // exits out of 'info registers all' as soon as it encounters a register
436 // that can't be read.
437 send((reg_t) 0);
438 }
439 } else {
440 return send_packet("E02");
441 }
442
443 send_running_checksum();
444 expect_ack = true;
445 }
446
447 void gdbserver_t::handle_register_write(const std::vector<uint8_t> &packet)
448 {
449 // P n...=r...
450
451 std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
452 unsigned int n = consume_hex_number(iter, packet.end());
453 if (*iter != '=')
454 return send_packet("E05");
455 iter++;
456
457 reg_t value = consume_hex_number_le(iter, packet.end());
458 if (*iter != '#')
459 return send_packet("E06");
460
461 processor_t *p = sim->get_core(0);
462
463 if (n >= REG_XPR0 && n <= REG_XPR31) {
464 p->state.XPR.write(n - REG_XPR0, value);
465 } else if (n == REG_PC) {
466 p->state.pc = value;
467 } else if (n >= REG_FPR0 && n <= REG_FPR31) {
468 p->state.FPR.write(n - REG_FPR0, value);
469 } else if (n >= REG_CSR0 && n <= REG_CSR4095) {
470 try {
471 p->set_csr(n - REG_CSR0, value);
472 } catch(trap_t& t) {
473 return send_packet("EFF");
474 }
475 } else {
476 return send_packet("E07");
477 }
478
479 return send_packet("OK");
480 }
481
482 void gdbserver_t::handle_memory_read(const std::vector<uint8_t> &packet)
483 {
484 // m addr,length
485 std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
486 reg_t address = consume_hex_number(iter, packet.end());
487 if (*iter != ',')
488 return send_packet("E10");
489 iter++;
490 reg_t length = consume_hex_number(iter, packet.end());
491 if (*iter != '#')
492 return send_packet("E11");
493
494 send("$");
495 running_checksum = 0;
496 char buffer[3];
497 processor_t *p = sim->get_core(0);
498 mmu_t* mmu = sim->debug_mmu;
499
500 for (reg_t i = 0; i < length; i++) {
501 sprintf(buffer, "%02x", mmu->load_uint8(address + i));
502 send(buffer);
503 }
504 send_running_checksum();
505 }
506
507 void gdbserver_t::handle_memory_binary_write(const std::vector<uint8_t> &packet)
508 {
509 // X addr,length:XX...
510 std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
511 reg_t address = consume_hex_number(iter, packet.end());
512 if (*iter != ',')
513 return send_packet("E20");
514 iter++;
515 reg_t length = consume_hex_number(iter, packet.end());
516 if (*iter != ':')
517 return send_packet("E21");
518 iter++;
519
520 processor_t *p = sim->get_core(0);
521 mmu_t* mmu = sim->debug_mmu;
522 for (unsigned int i = 0; i < length; i++) {
523 if (iter == packet.end()) {
524 return send_packet("E22");
525 }
526 mmu->store_uint8(address + i, *iter);
527 iter++;
528 }
529 if (*iter != '#')
530 return send_packet("E4b"); // EOVERFLOW
531
532 send_packet("OK");
533 }
534
535 void gdbserver_t::handle_continue(const std::vector<uint8_t> &packet)
536 {
537 // c [addr]
538 processor_t *p = sim->get_core(0);
539 if (packet[2] != '#') {
540 std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
541 p->state.pc = consume_hex_number(iter, packet.end());
542 if (*iter != '#')
543 return send_packet("E30");
544 }
545
546 // TODO p->set_halted(false, HR_NONE);
547 running = true;
548 }
549
550 void gdbserver_t::handle_step(const std::vector<uint8_t> &packet)
551 {
552 // s [addr]
553 processor_t *p = sim->get_core(0);
554 if (packet[2] != '#') {
555 std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
556 p->state.pc = consume_hex_number(iter, packet.end());
557 if (*iter != '#')
558 return send_packet("E40");
559 }
560
561 // TODO: p->set_single_step(true);
562 running = true;
563 }
564
565 void gdbserver_t::handle_kill(const std::vector<uint8_t> &packet)
566 {
567 // k
568 // The exact effect of this packet is not specified.
569 // Looks like OpenOCD disconnects?
570 // TODO
571 }
572
573 void gdbserver_t::handle_extended(const std::vector<uint8_t> &packet)
574 {
575 // Enable extended mode. In extended mode, the remote server is made
576 // persistent. The ‘R’ packet is used to restart the program being debugged.
577 send_packet("OK");
578 extended_mode = true;
579 }
580
581 void software_breakpoint_t::insert(mmu_t* mmu)
582 {
583 if (size == 2) {
584 instruction = mmu->load_uint16(address);
585 mmu->store_uint16(address, C_EBREAK);
586 } else {
587 instruction = mmu->load_uint32(address);
588 mmu->store_uint32(address, EBREAK);
589 }
590 fprintf(stderr, ">>> Read %x from %lx\n", instruction, address);
591 }
592
593 void software_breakpoint_t::remove(mmu_t* mmu)
594 {
595 fprintf(stderr, ">>> write %x to %lx\n", instruction, address);
596 if (size == 2) {
597 mmu->store_uint16(address, instruction);
598 } else {
599 mmu->store_uint32(address, instruction);
600 }
601 }
602
603 void gdbserver_t::handle_breakpoint(const std::vector<uint8_t> &packet)
604 {
605 // insert: Z type,addr,kind
606 // remove: z type,addr,kind
607
608 software_breakpoint_t bp;
609 bool insert = (packet[1] == 'Z');
610 std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
611 int type = consume_hex_number(iter, packet.end());
612 if (*iter != ',')
613 return send_packet("E50");
614 iter++;
615 bp.address = consume_hex_number(iter, packet.end());
616 if (*iter != ',')
617 return send_packet("E51");
618 iter++;
619 bp.size = consume_hex_number(iter, packet.end());
620 // There may be more options after a ; here, but we don't support that.
621 if (*iter != '#')
622 return send_packet("E52");
623
624 if (bp.size != 2 && bp.size != 4) {
625 return send_packet("E53");
626 }
627
628 processor_t *p = sim->get_core(0);
629 mmu_t* mmu = p->mmu;
630 if (insert) {
631 bp.insert(mmu);
632 breakpoints[bp.address] = bp;
633
634 } else {
635 bp = breakpoints[bp.address];
636 bp.remove(mmu);
637 breakpoints.erase(bp.address);
638 }
639 mmu->flush_icache();
640 sim->debug_mmu->flush_icache();
641 return send_packet("OK");
642 }
643
644 void gdbserver_t::handle_query(const std::vector<uint8_t> &packet)
645 {
646 std::string name;
647 std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
648
649 consume_string(name, iter, packet.end(), ':');
650 if (iter != packet.end())
651 iter++;
652 if (name == "Supported") {
653 send("$");
654 running_checksum = 0;
655 while (iter != packet.end()) {
656 std::string feature;
657 consume_string(feature, iter, packet.end(), ';');
658 if (iter != packet.end())
659 iter++;
660 if (feature == "swbreak+") {
661 send("swbreak+;");
662 }
663 }
664 return send_running_checksum();
665 }
666
667 fprintf(stderr, "Unsupported query %s\n", name.c_str());
668 return send_packet("");
669 }
670
671 void gdbserver_t::handle_packet(const std::vector<uint8_t> &packet)
672 {
673 if (compute_checksum(packet) != extract_checksum(packet)) {
674 fprintf(stderr, "Received %ld-byte packet with invalid checksum\n", packet.size());
675 fprintf(stderr, "Computed checksum: %x\n", compute_checksum(packet));
676 print_packet(packet);
677 send("-");
678 return;
679 }
680
681 fprintf(stderr, "Received %ld-byte packet from debug client: ", packet.size());
682 print_packet(packet);
683 send("+");
684
685 switch (packet[1]) {
686 case '!':
687 return handle_extended(packet);
688 case '?':
689 return handle_halt_reason(packet);
690 case 'g':
691 return handle_general_registers_read(packet);
692 case 'k':
693 return handle_kill(packet);
694 case 'm':
695 return handle_memory_read(packet);
696 // case 'M':
697 // return handle_memory_write(packet);
698 case 'X':
699 return handle_memory_binary_write(packet);
700 case 'p':
701 return handle_register_read(packet);
702 case 'P':
703 return handle_register_write(packet);
704 case 'c':
705 return handle_continue(packet);
706 case 's':
707 return handle_step(packet);
708 case 'z':
709 case 'Z':
710 return handle_breakpoint(packet);
711 case 'q':
712 case 'Q':
713 return handle_query(packet);
714 }
715
716 // Not supported.
717 fprintf(stderr, "** Unsupported packet: ");
718 print_packet(packet);
719 send_packet("");
720 }
721
722 void gdbserver_t::handle_interrupt()
723 {
724 processor_t *p = sim->get_core(0);
725 // TODO p->set_halted(true, HR_INTERRUPT);
726 send_packet("S02"); // Pretend program received SIGINT.
727 running = false;
728 }
729
730 void gdbserver_t::handle()
731 {
732 if (client_fd > 0) {
733 processor_t *p = sim->get_core(0);
734 /* TODO
735 if (running && p->halted) {
736 // The core was running, but now it's halted. Better tell gdb.
737 switch (p->halt_reason) {
738 case HR_NONE:
739 fprintf(stderr, "Internal error. Processor halted without reason.\n");
740 abort();
741 case HR_STEPPED:
742 case HR_INTERRUPT:
743 case HR_CMDLINE:
744 case HR_ATTACHED:
745 // There's no gdb code for this.
746 send_packet("T05");
747 break;
748 case HR_SWBP:
749 send_packet("T05swbreak:;");
750 break;
751 }
752 send_packet("T00");
753 // TODO: Actually include register values here
754 running = false;
755 }
756 */
757
758 this->read();
759 this->write();
760
761 } else {
762 this->accept();
763 }
764
765 this->process_requests();
766 }
767
768 void gdbserver_t::send(const char* msg)
769 {
770 unsigned int length = strlen(msg);
771 for (const char *c = msg; *c; c++)
772 running_checksum += *c;
773 send_buf.append((const uint8_t *) msg, length);
774 }
775
776 void gdbserver_t::send(uint64_t value)
777 {
778 char buffer[3];
779 for (unsigned int i = 0; i < 8; i++) {
780 sprintf(buffer, "%02x", (int) (value & 0xff));
781 send(buffer);
782 value >>= 8;
783 }
784 }
785
786 void gdbserver_t::send(uint32_t value)
787 {
788 char buffer[3];
789 for (unsigned int i = 0; i < 4; i++) {
790 sprintf(buffer, "%02x", (int) (value & 0xff));
791 send(buffer);
792 value >>= 8;
793 }
794 }
795
796 void gdbserver_t::send_packet(const char* data)
797 {
798 send("$");
799 running_checksum = 0;
800 send(data);
801 send_running_checksum();
802 expect_ack = true;
803 }
804
805 void gdbserver_t::send_running_checksum()
806 {
807 char checksum_string[4];
808 sprintf(checksum_string, "#%02x", running_checksum);
809 send(checksum_string);
810 }