Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / remote / remote.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: remote.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21/////////////////////////////////////////////////////////////////////
22//
23// FIle: remote.cc
24//
25// Copyright (C) 2005 Sun Microsystems, Inc.
26// All rights reserved.
27//
28
29
30//
31// Frontend socket interface for the debugger
32//
33
34
35
36
37
38
39#include <sys/types.h>
40#include <sys/socket.h>
41#include <sys/conf.h>
42#include <stropts.h>
43#include <signal.h>
44#include <netinet/in.h>
45#include <sys/un.h>
46#include <arpa/inet.h>
47#include <netdb.h>
48#include <stdio.h>
49#include <unistd.h>
50#include <fcntl.h>
51#include <string.h> /* for memset in FD_ZERO */
52#include <errno.h>
53#include <thread.h>
54#include <stdlib.h>
55
56#include <assert.h>
57
58#include "types.h"
59#include "cpu_interface.h"
60#include "remote.h"
61
62// output debug log messages
63int g_debug_on = 1;
64#define DEBUG(s) if(g_debug_on){s}
65
66#define SWAP_BIT_5_0(I) ((( (I) & 0x01e ) | ( ((I) & 0x020) >> 5 )) & 0x1f)
67
68
69const int FOREVER = 1;
70
71// command delimiters
72const char START_CHR = '$';
73const char END_CHR = '#';
74
75
76
77typedef enum INSTATE
78{
79 UNATTACHED,
80 STOPPED,
81 RUNNING
82
83} state_t;
84
85
86
87const int MAX_BUF_SIZE = 8192;
88
89
90
91
92// external routines called from this module
93extern int cpu_set_breakpoint ( int cpu_id, VCPU_BpType type, uint64_t addr );
94extern int cpu_remove_breakpoint ( int cpu_id, VCPU_BpType type, uint64_t addr );
95
96extern void UI_exec_cmd ( char *cmd );
97
98
99// Convert number NIB to a hex digit.
100static int tohex (int nib)
101{
102 if (nib < 10)
103 return '0' + nib;
104 else
105 return 'a' + nib - 10;
106}
107
108
109// Convert hex digit A to a number.
110static int fromhex (uint8_t a)
111{
112 int value = 0;
113 if (a >= '0' && a <= '9')
114 value = a - '0';
115 else if (a >= 'a' && a <= 'f')
116 value = a - 'a' + 10;
117 else if (a >= 'A' && a <= 'F')
118 value = a - 'A' + 10;
119 else
120 printf ("Reply contains invalid hex digit %d", a);
121
122 return value & 0xf;
123}
124
125// read next parameter from the command string;
126// return param value;
127// set string pointer to the next param
128static uint64_t read_next_param ( uint8_t **p )
129{
130 uint64_t value = 0;
131
132 if (p != NULL)
133 {
134 // remove all spaces
135 while((*p)[0] == ' ')
136 (*p)++;
137
138
139 for (int i=0; i<100; i++)
140 {
141 uint8_t c = (*p)[i];
142 if (c == '#' || c == '\0')
143 {
144 // last character
145 *p = NULL;
146 break;
147 }
148 else if (c == ',' || c == ':' || c == ' ')
149 {
150 // end of parameter
151 (*p)+=i+1;
152 break;
153 }
154 else
155 {
156 // convert from hex
157 value = (value<<4) | fromhex(c);
158 }
159 }
160 }
161
162 return value;
163}
164
165static uint64_t get_value
166(
167 uint8_t **buf, // buffer to get value from
168 int size // size of the value
169)
170{
171 assert( size <= 8 );
172
173 int i = 0;
174 uint64_t value = 0;
175
176 for (int offset = size * 8 - 4; offset>=0; offset -= 4)
177 value = value | fromhex ( (*buf)[i++] ) << offset;
178
179 *buf += i; // update buffer pointer
180
181 return value;
182}
183
184
185
186static void put_value
187(
188 uint8_t **buf, // buffer to put a hex string value
189 uint64_t val, // value
190 int size // number of bytes ( should less or equal 8 )
191)
192{
193 assert( size <= 8 );
194 int i = 0;
195 for (int offset = size * 8 - 4; offset>=0; offset -= 4)
196 {
197 (*buf)[i++] = uint8_t( tohex (int(val >> offset)&0xf ));
198 }
199 *buf += i; // update the buffer pointer
200}
201
202
203
204
205
206
207class SocketInterface
208{
209
210public:
211
212 int id; // connection id
213
214 SocketInterface *next;
215
216 int socket;
217 state_t state;
218
219 thread_t thread_id;
220
221 int cpu_id; // current cpu id
222
223
224 uint64_t symtab_base;
225 char * symtab_fname;
226
227
228 // communication buffers
229 uint8_t send_buffer[MAX_BUF_SIZE];
230 uint8_t recv_buffer[MAX_BUF_SIZE];
231
232
233public:
234
235 SocketInterface ()
236 {
237 id = 0;
238 next = NULL;
239 state = UNATTACHED;
240 thread_id = 0;
241 cpu_id = 0;
242
243 }
244
245 ~SocketInterface () { close(socket); }
246
247
248 // send an ack - command was recieved
249 void reply_ack ()
250 {
251 uint8_t ack[4] = {'+',0};
252 DEBUG( printf("send an ack : + ; "); );
253 write( socket, ack, 1);
254 }
255
256 void reply_nack ()
257 {
258 uint8_t nack[4] = {'-',0};
259 DEBUG( printf("send a nack : -\n"); );
260 write( socket, nack, 1);
261 }
262
263 void reply_ok ()
264 {
265 send_buffer[1] = 'O';
266 send_buffer[2] = 'K';
267 this->send(3);
268 }
269
270 void reply_not_implemented ()
271 {
272 this->send(0);
273 }
274
275
276 // send error number in hex
277 void reply_error ( uint32_t error_number )
278 {
279 send_buffer[1] = 'E';
280 send_buffer[2] = tohex ((error_number >> 4) & 0xf);
281 send_buffer[3] = tohex (error_number & 0xf);
282 this->send (4);
283
284 }
285
286
287 // send target stop reason in hex
288 void reply_target_stopped (uint32_t reason)
289 {
290 send_buffer[1] = 'S';
291 send_buffer[2] = tohex ((reason >> 4) & 0xf);
292 send_buffer[3] = tohex (reason & 0xf);
293 this->send (4);
294
295 }
296
297
298 // send a data from the send_buffer;
299 // add first, last control symbols and a checksum
300 int send ( int size )
301 {
302 int n = 0;
303
304 // first control char
305 send_buffer[n++] = START_CHR;
306 uint8_t check_sum = 0;
307
308 while (n<size)
309 {
310 if ( n > MAX_BUF_SIZE-3 )
311 return -1;
312
313 uint8_t c = send_buffer[n];
314
315 // check null terminated
316 if ( c == '\0')
317 break;
318
319 check_sum += c;
320 n++;
321 }
322 // insert end control char
323 send_buffer[n++] = END_CHR;
324
325 // insert a check sum
326 send_buffer[n++] = tohex ((check_sum >> 4) & 0xf);
327 send_buffer[n++] = tohex (check_sum & 0xf);
328 send_buffer[n] = 0; // null terminate
329
330 DEBUG( printf("\n intf %d send a reply :%s \n", id, send_buffer); );
331
332 uint64_t res = write( socket, send_buffer, n);
333
334 return (res != n) ? -1 : 0;
335 }
336
337
338
339
340 // read a command into recieve buffer;
341 // overwrite a previous command if it was there;
342 // return the number of bytes read,-1 if error
343 int recv ()
344 {
345 uint8_t c;
346 int n = 0;
347 int packet_started = 0;
348
349 while ( n < MAX_BUF_SIZE )
350 {
351 // read one character
352 if ( read (socket, &c, 1) == 1 )
353 {
354 // one character recieved
355 if ( c == START_CHR)
356 {
357 // begin a new command
358 n = 0;
359 packet_started = 1;
360 continue;
361 }
362 if ( c == END_CHR)
363 {
364 // last character in the command
365 recv_buffer[n] = 0; // null terminated
366 return n;
367 }
368
369 // accumulate the characters
370 if (packet_started)
371 {
372 recv_buffer[n] = c;
373 }
374 n++;
375 }
376 }
377
378 return (-1); // data is incomplete
379 }
380
381 // read one register value from the recieve buffer
382 int read_reg ()
383 {
384
385 uint8_t *args = recv_buffer+1;
386 int reg_idx = (int)read_next_param ( &args );
387
388
389 uint8_t *sbuf = send_buffer+1; // skip first control char
390 uint64_t value = 0;
391 int size = 8;
392
393 // read 8 byte gpr value
394 if (reg_idx < 32)
395 {
396 g_vcpu[cpu_id]->get_reg(VCPU_IRF_0 + reg_idx, &value);
397 put_value( &sbuf, value, 8);
398 }
399 else if (reg_idx < 64) // read 4 byte fpr value
400 {
401 g_vcpu[cpu_id]->get_reg(VCPU_FRF_0 + reg_idx - 32, &value);
402 put_value( &sbuf, value, 4);
403 }
404 else if (reg_idx < 80) // read 8 byte fpr value
405 {
406 g_vcpu[cpu_id]->get_reg(VCPU_DRF_0 + reg_idx - 64 + 16, &value);
407 put_value( &sbuf, value, 8);
408 }
409 else if (reg_idx < 90) // read control reg value
410 {
411 switch(reg_idx)
412 {
413 case 80: g_vcpu[cpu_id]->get_reg(VCPU_ASR_PC, &value); break;
414 case 81: g_vcpu[cpu_id]->get_reg(VCPU_ASR_NPC, &value); break;
415 case 82: g_vcpu[cpu_id]->get_reg(VCPU_PR_PSTATE, &value); break;
416 case 83: g_vcpu[cpu_id]->get_reg(VCPU_ASR_FSR, &value); break;
417 case 84: g_vcpu[cpu_id]->get_reg(VCPU_ASR_FPRS, &value); break;
418 case 85: g_vcpu[cpu_id]->get_reg(VCPU_ASR_Y, &value); break;
419 case 86: g_vcpu[cpu_id]->get_reg(VCPU_PR_CWP, &value); break;
420 case 87: g_vcpu[cpu_id]->get_reg(VCPU_PR_PSTATE, &value); break;
421 case 88: g_vcpu[cpu_id]->get_reg(VCPU_ASR_ASI, &value); break;
422 case 89: g_vcpu[cpu_id]->get_reg(VCPU_ASR_CCR, &value); break;
423 }
424 put_value( &sbuf, value, 8);
425 }
426 else if (reg_idx < 122) // read 8 byte fpr value
427 {
428 g_vcpu[cpu_id]->get_reg(VCPU_DRF_0 + reg_idx - 90, &value);
429 put_value( &sbuf, value, 8);
430 }
431 else if (reg_idx < 138) // read 16 byte fpr value
432 {
433 int regnum = (reg_idx - 122) * 2;
434 g_vcpu[cpu_id]->get_reg(VCPU_DRF_0 + regnum, &value);
435 put_value( &sbuf, value, 8);
436 g_vcpu[cpu_id]->get_reg(VCPU_DRF_0 + regnum + 1, &value);
437 put_value( &sbuf, value, 8);
438 }
439 else
440 {
441 reply_error (0);
442 return 1;
443 }
444
445 int msg_size = int(sbuf - send_buffer);
446 send(msg_size);
447 return 0;
448
449 }
450
451 int read_all_regs ()
452 {
453 uint8_t *sbuf = send_buffer+1; // skip first control char
454
455 // read all GPRs
456 for (int i=0; i<32; i++)
457 {
458 uint64_t gpr;
459 g_vcpu[cpu_id]->get_reg(VCPU_IRF_0 + i, &gpr);
460 put_value( &sbuf, gpr, 8);
461 }
462
463 // read all 32 bit fp regs
464 for (int i=0; i<32; i++)
465 {
466 uint64_t fpr = 0;
467 g_vcpu[cpu_id]->get_reg(VCPU_FRF_0 + i, &fpr);
468 put_value( &sbuf, fpr, 4);
469 }
470
471 // read all 64 bit fp regs
472 for (int i=32; i<64; i+=2)
473 {
474 // swap bit 5 and 0
475 uint64_t dfpr = 0;
476 g_vcpu[cpu_id]->get_reg(VCPU_DRF_0 + (i / 2), &dfpr);
477 put_value( &sbuf, dfpr, 8);
478 }
479
480 // read control registers
481 uint64_t reg;
482 g_vcpu[cpu_id]->get_reg(VCPU_ASR_PC, &reg);
483 put_value( &sbuf, reg, 8);
484
485 g_vcpu[cpu_id]->get_reg(VCPU_ASR_NPC, &reg);
486 put_value( &sbuf, reg, 8);
487
488 g_vcpu[cpu_id]->get_reg(VCPU_PR_PSTATE, &reg);
489 put_value( &sbuf, reg, 8);
490
491 g_vcpu[cpu_id]->get_reg(VCPU_ASR_FSR, &reg);
492 put_value( &sbuf, reg, 8);
493
494 g_vcpu[cpu_id]->get_reg(VCPU_ASR_FPRS, &reg);
495 put_value( &sbuf, reg, 8);
496
497 g_vcpu[cpu_id]->get_reg(VCPU_ASR_Y, &reg);
498 put_value( &sbuf, reg, 8);
499
500 int msg_size = int(sbuf - send_buffer);
501 send(msg_size);
502 return 0;
503 }
504
505
506 int write_all_regs ()
507 {
508 uint64_t reg;
509 uint8_t *buf = recv_buffer;
510
511 // write all GPRs
512 for (int i=0; i<32; i++)
513 {
514 reg = get_value( &buf, 8);
515 g_vcpu[cpu_id]->set_reg(VCPU_IRF_0 + i, reg);
516 }
517
518 // write all 32 bit fp regs
519 for (int i=0; i<32; i++)
520 {
521 reg = get_value( &buf, 4);
522 g_vcpu[cpu_id]->set_reg(VCPU_FRF_0 + i, reg);
523 }
524
525 // write all 64 bit fp regs
526 for (int i=32; i<64; i+=2)
527 {
528 reg = get_value( &buf, 8);
529 g_vcpu[cpu_id]->set_reg(VCPU_DRF_0 + (i / 2), reg);
530 }
531
532 // write control registers
533 reg = get_value( &buf, 8);
534 g_vcpu[cpu_id]->set_reg(VCPU_ASR_PC, reg);
535
536 reg = get_value( &buf, 8);
537 g_vcpu[cpu_id]->set_reg(VCPU_ASR_NPC, reg);
538
539 reg = get_value( &buf, 8);
540 g_vcpu[cpu_id]->set_reg(VCPU_PR_PSTATE, reg);
541
542 reg = get_value( &buf, 8);
543 g_vcpu[cpu_id]->set_reg(VCPU_ASR_FSR, reg);
544
545 reg = get_value( &buf, 8);
546 g_vcpu[cpu_id]->set_reg(VCPU_ASR_FPRS, reg);
547
548 reg = get_value( &buf, 8);
549 g_vcpu[cpu_id]->set_reg(VCPU_ASR_Y, reg);
550
551 return 0;
552 }
553
554 int read_mem ()
555 {
556 uint8_t *args = recv_buffer+1;
557 uint64_t addr = read_next_param ( &args );
558 int size = (int)read_next_param ( &args );
559
560 if (size <= 0)
561 {
562 reply_error (0);
563 return 1;
564 }
565
566 if (size > MAX_BUF_SIZE-3)
567 {
568 size = MAX_BUF_SIZE-3;
569 }
570
571 uint8_t *sbuf = send_buffer+1;
572
573
574 // read from the double word aligned address
575 uint64_t addr8 = addr & ~uint64_t(7);
576 uint64_t value = 0;
577 if ( g_vcpu[cpu_id]->read_mem(addr8, &value, 8) != 0 )
578 {
579 reply_error (1);
580 return 1;
581 }
582 DEBUG( printf(" read dword %llx from address %llx \n", value, addr8); );
583
584 // alignement for the very first byte
585 int start_byte_idx = int(addr & 0x7);
586 int end_byte_idx = start_byte_idx + size-1;
587 if (end_byte_idx>7)
588 end_byte_idx = 7;
589 int chunck_size = end_byte_idx - start_byte_idx + 1;
590
591
592 if (end_byte_idx<7)
593 value >>= ((7-end_byte_idx)*8);
594 if (chunck_size<8)
595 value &= ((uint64_t(1)<<(chunck_size*8))-1);
596
597 put_value( &sbuf, value, chunck_size);
598
599 int msg_size = int(sbuf - send_buffer);
600 send( msg_size );
601
602 return 0;
603 }
604
605 int write_mem()
606 {
607 uint8_t *args = recv_buffer+1;
608
609 uint64_t addr = read_next_param ( &args );
610 int size = (int)read_next_param ( &args );
611
612 // allow only double word aligned addresses
613 if ((size <= 0) || ( addr & 0x7 ) )
614 {
615 reply_error (0);
616 return 1;
617 }
618
619 for (int i=0; i<size/8; i++)
620 {
621 // double word aligned address
622 addr = ( addr + i*8 ) & ~uint64_t(7);
623
624 uint64_t value = get_value ( &args ,size );
625 if (g_vcpu[cpu_id]->write_mem(addr, value, 8) != 0)
626 {
627 reply_error (1);
628 return 1;
629 }
630
631 }
632
633
634 reply_ok ();
635 return 0;
636 }
637
638 int set_break ()
639 {
640
641 uint8_t *args = recv_buffer+1;
642
643 int type = (int)read_next_param ( &args );
644 uint64_t addr = read_next_param ( &args );
645 int size = (int)read_next_param ( &args );
646
647 switch (type)
648 {
649 case 0: // sw breakpoint
650 case 1: // hw breakpoint
651
652 if (cpu_set_breakpoint(cpu_id, VCPU_BP_INSTR_ADDR, addr) != 0)
653 {
654 reply_error(1);
655 return 1;
656 }
657 break;
658
659 case 2: // write watchpoint
660
661 if (cpu_set_breakpoint(cpu_id, VCPU_BP_DATA_WRITE_ADDR, addr) != 0)
662 {
663 reply_error(1);
664 return 1;
665 }
666
667 break;
668
669 case 3: // read watchpoint
670
671 if (cpu_set_breakpoint(cpu_id, VCPU_BP_DATA_READ_ADDR, addr) != 0)
672 {
673 reply_error(1);
674 return 1;
675 }
676 break;
677
678 default:
679 reply_error (0);
680 return 1;
681 }
682
683
684 reply_ok ();
685 return 0;
686
687 }
688
689 int remove_break ()
690 {
691 uint8_t *args = recv_buffer+1;
692
693 int type = (int)read_next_param ( &args );
694 uint64_t addr = read_next_param ( &args );
695 int size = (int)read_next_param ( &args );
696
697 switch (type)
698 {
699 case 0: // sw breakpoint
700 case 1: // hw breakpoint
701
702 if (cpu_remove_breakpoint(cpu_id, VCPU_BP_INSTR_ADDR, addr) != 0)
703 {
704 //reply_error(1);
705 return 1;
706 }
707 break;
708
709 case 2: // write watchpoint
710
711 if (cpu_remove_breakpoint(cpu_id, VCPU_BP_DATA_WRITE_ADDR, addr) != 0)
712 {
713 //reply_error(1);
714 return 1;
715 }
716
717 break;
718
719 case 3: // read watchpoint
720
721 if (cpu_remove_breakpoint(cpu_id, VCPU_BP_DATA_READ_ADDR, addr) != 0)
722 {
723 //reply_error(1);
724 return 1;
725 }
726 break;
727
728 default:
729 reply_error (0);
730 return 1;
731
732 }
733
734 reply_ok ();
735 return 0;
736 }
737
738
739};
740
741
742// head of linked list of interface objects
743SocketInterface * gpIntf;
744
745
746// This routine is called when target is stoped.
747// Inform the debugger about the reason of stopping.
748int target_stopped ( int reason )
749{
750 SocketInterface *in = gpIntf;
751
752 // for all attached remote interfaces
753 while ( in )
754 {
755 if(in->state == RUNNING)
756 {
757 in->reply_target_stopped (reason);
758 in->state = STOPPED;
759 }
760
761 in = in->next;
762 }
763 return 0;
764}
765
766
767
768
769
770
771// This new thread is invoked once contact with a debugger is
772// been established. This thread exits once that debugger
773// connection vanishes.
774// Any one debugger can stop the simulation, all are required
775// to be active to continue simulation.
776
777extern "C"
778void * in_worker_thread (void * argp)
779{
780
781 SocketInterface *in = (SocketInterface *)argp;
782
783 // run the command interface until we get the
784 // command to termnate this session
785
786 while (FOREVER)
787 {
788
789 // get the command packet
790 int csize = in->recv();
791
792 if ( csize <= 0)
793 {
794 printf ("failed in communication");
795 in->reply_nack(); // send a nack
796 continue;
797 }
798
799 // send an ack
800 in->reply_ack();
801
802 DEBUG( printf(" remote interface %d got a command %s: ", in->id, in->recv_buffer); );
803
804 char command = in->recv_buffer[0];
805
806 switch ( command )
807 {
808
809 case '?': // why stopped
810 DEBUG( printf("get the the reason why stoped \n"); );
811
812 in->reply_target_stopped (0);
813 break;
814
815
816 case 'p': // read register
817 DEBUG( printf("read register :%s \n", in->recv_buffer+1); );
818 in->read_reg ();
819 //in->reply_not_implemented(); // not implemented
820 break;
821
822 case 'g': // read all registers
823 {
824 DEBUG( printf("read all register \n" ); );
825
826 in->read_all_regs ();
827
828 break;
829 }
830
831 case 'G': // write registers
832 {
833 DEBUG( printf("write registers: %s\n", in->recv_buffer+1); );
834
835 in->write_all_regs();
836
837 in->reply_ok();
838 break;
839 }
840
841 case 'm': // read memory
842 {
843
844 DEBUG( printf("read memory : %s \n", in->recv_buffer+1); );
845
846 in->read_mem();
847 break;
848 }
849 case 'M': // write memory
850 {
851 DEBUG( printf("write memory :%s \n", in->recv_buffer+1); );
852
853 in->write_mem();
854 break;
855 }
856
857 case 'c': // continue from address
858 DEBUG( printf("continue %s \n", in->recv_buffer+1); );
859 in->state = RUNNING;
860 UI_exec_cmd("run\n");
861 break;
862
863 case 's': // step from address
864 DEBUG( printf("step :%s \n", in->recv_buffer+1); );
865 in->state = RUNNING;
866 UI_exec_cmd("stepi 1\n");
867 break;
868
869 case 'z': // remove a breakpoint
870 DEBUG( printf("remove a breakpoint :%s \n", in->recv_buffer+1); );
871
872 in->remove_break();
873 break;
874
875 case 'Z': // set a breakpoint
876 DEBUG( printf("set a breakpoint :%s \n", in->recv_buffer+1); );
877
878 in->set_break();
879 break;
880
881 case 'k': // killed
882 goto quit;
883
884 case 'D': // detach the session
885 goto quit;
886
887 default:
888 DEBUG( printf("\n unimplemented command %s \n", in->recv_buffer); );
889 in->reply_not_implemented(); // not implemented
890 }
891 }
892
893
894
895quit:
896
897 // remove interface structure from the list
898 SocketInterface *prev=NULL;
899 for ( SocketInterface *p = gpIntf;
900 p != NULL;
901 prev = p, p = p->next )
902 {
903 if (p == in)
904 {
905 if (prev)
906 prev->next = in->next;
907 else
908 gpIntf = in->next;
909
910 close (in->socket);
911 delete in;
912 break;
913 }
914 }
915
916
917 thr_exit(NULL);
918
919 return NULL;
920}
921
922
923
924
925
926
927
928
929
930
931
932
933// main program thread
934// to wait for user interface connections.
935extern "C"
936void *wait_connection (void *param)
937{
938 static fd_set comm_channels;
939 int tcp_attach_socket, res;
940 struct sockaddr_in tcp_server;
941 struct sockaddr_in from;
942 int fromlen;
943 int skt;
944 int fh, length, on=1;
945 int max_channel;
946 sigset_t sigs;
947 struct hostent * hp;
948 char * froms;
949 int retry_cnt=0;
950
951 sigfillset(&sigs);
952 thr_sigsetmask(SIG_BLOCK, &sigs, NULL);
953
954 skt = socket(AF_INET, SOCK_STREAM, 0);
955 if (skt < 0)
956 {
957 printf ("ERROR: cannot opening stream socket\n");
958 return NULL;
959 }
960
961 // enable the reuse of this socket if this process dies
962 if (setsockopt(skt,SOL_SOCKET,SO_REUSEADDR,(char*)&on,int(sizeof(on)))<0)
963 {
964 printf ("ERROR: turning on REUSEADDR \n");
965 return NULL;
966 }
967
968 RemoteConfig *config = (RemoteConfig *)param;
969
970 g_debug_on = config->debug_on;
971
972retry: // bind the connection
973
974 tcp_server.sin_family = AF_INET;
975 tcp_server.sin_addr.s_addr = INADDR_ANY;
976 tcp_server.sin_port = config->port;
977
978 retry_cnt++;
979 printf("- trying port:%d", config->port);
980
981 if (bind(skt, (struct sockaddr *)&tcp_server, int(sizeof(tcp_server))) < 0)
982 {
983 switch (errno)
984 {
985 case EAGAIN:
986 goto retry;
987
988 case EADDRINUSE:
989 printf("\nPort %d already in use ", config->port);
990
991 default:
992 printf("ERROR: binding tcp stream socket");
993 return NULL;
994 }
995 }
996
997
998 length = int(sizeof(tcp_server));
999 if (getsockname(skt, (struct sockaddr *) &tcp_server, &length)==-1)
1000 {
1001 printf("ERROR:getting socket name");
1002 return NULL;
1003 }
1004
1005 // start waiting for the connection
1006 printf("\nWaiting for connection on port # %d\n",ntohs(tcp_server.sin_port));
1007 listen(skt, config->max_connections);
1008
1009 tcp_attach_socket = skt;
1010 max_channel = tcp_attach_socket;
1011 FD_ZERO(&comm_channels);
1012 FD_SET(tcp_attach_socket, &comm_channels);
1013
1014 // Wait for a control connection
1015 int next_connection = 0;
1016 while(FOREVER)
1017 {
1018
1019 if (next_connection > config->max_connections - 1)
1020 {
1021 sleep (2);
1022 continue;
1023 }
1024
1025 res = select(max_channel+1, &comm_channels, (fd_set*)0, (fd_set*)0, (struct timeval*)0 /* stall */);
1026 if (res<0)
1027 {
1028 printf("ERROR: select");
1029 break;
1030 }
1031
1032 // accept the connection
1033 fromlen = int(sizeof(from));
1034 fh = accept(tcp_attach_socket,(struct sockaddr *)&from, (int*)&fromlen);
1035
1036
1037 hp = gethostbyaddr((char *)&from.sin_addr, 4, AF_INET);
1038 if (hp == (struct hostent *)0)
1039 {
1040 froms = inet_ntoa(from.sin_addr);
1041 fprintf(stderr,"cant resolve hostname for %s\n", froms);;
1042 }
1043 else
1044 {
1045 froms = hp->h_name;
1046 }
1047 printf("got remote connection from %s : port %d\n", froms, from.sin_port);
1048
1049 // Create the thread to handle this debugger
1050 // connection. It cleans up after itself
1051 // if anything goes wrong
1052
1053 SocketInterface *in = new SocketInterface ();
1054 if (gpIntf == NULL)
1055 {
1056 gpIntf = in;
1057 }
1058 else
1059 {
1060 in->next = gpIntf;
1061 gpIntf = in;
1062 }
1063
1064 in->id = next_connection;
1065 next_connection++;
1066
1067 in->socket = fh;
1068 DEBUG( printf("connection %d on socket_id=%d\n", in->id, in->socket); );
1069
1070
1071 thr_create(NULL, NULL, in_worker_thread, (void*)in, THR_BOUND, &in->thread_id);
1072
1073 }; // while forever
1074
1075
1076 return NULL;
1077}
1078
1079
1080
1081int start_connection ( RemoteConfig *config )
1082{
1083 thread_t thread_id;
1084
1085
1086 // start thread waiting for a remote connection
1087 thr_create(NULL, NULL, wait_connection, (void *)config, THR_BOUND, &thread_id);
1088
1089 printf ( "remote debug server started...\n");
1090
1091 return 0;
1092
1093}
1094
1095int destroy_connection ()
1096{
1097 SocketInterface *in = gpIntf;
1098
1099 // for all attached remote interfaces
1100 while ( in )
1101 {
1102 in->reply_target_stopped (SIGNAL_HUP);
1103 SocketInterface *p = in;
1104 in = in->next;
1105 delete in;
1106 }
1107 return 0;
1108}
1109
1110
1111////////////////////////////////////////////////////////
1112//
1113// Get exported interface from the Remote shared library.
1114//
1115// Assign function pointers in the interface structure.
1116//
1117//
1118// return: 0 - success; 1 - fail;
1119
1120int get_ex_remote_interface
1121(
1122 RemoteExInterface *intf // pointer to the interface structure
1123)
1124{
1125 intf->create = start_connection;
1126 intf->destroy = destroy_connection;
1127 intf->update_status = target_stopped;
1128
1129 return 0;
1130}
1131
1132
1133
1134
1135
1136
1137
1138