1# Copyright 2000-2020 Free Software Foundation, Inc.
2
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 3 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16# This file is based on config/gdbserver.exp, which was written by
17# Michael Snyder (msnyder@redhat.com).
18
19#
20# To be addressed or set in your baseboard config file:
21#
22#   set_board_info gdb_protocol "remote"
23#	Unles you have a gdbserver that uses a different protocol...
24#	After GDB starts you should check global $gdbserver_protocol instead as
25#	the testfile may force a specific different target protocol itself.
26#
27#   set_board_info gdb_server_prog
28#	This will be the path to the gdbserver program you want to test.
29#	Defaults to "gdbserver".
30#
31#   set_board_info sockethost
32#	The name of the host computer whose socket is being used.
33#	Defaults to "localhost".  Note: old gdbserver requires
34#	that you define this, but libremote/gdbserver does not.
35#
36#   set_board_info gdb,socketport
37#	Port id to use for socket connection.  If not set explicitly,
38#	it will start at "2345" and increment for each use.
39#	After GDB starts you should check global $gdbserver_gdbport for the
40#	real port used.  It is not useful if $gdbserver_reconnect_p was not set.
41#
42
43#
44# gdb_target_cmd_ext
45# Send gdb the "target" command.  Returns 0 on success, 1 on failure, 2 on
46# unsupported.
47# If specified, then ADDITIONAL_TEXT must match the text that comes after
48# the connection message in order for the procedure to succeed.
49#
50proc gdb_target_cmd_ext { targetname serialport {additional_text ""} } {
51    global gdb_prompt
52
53    set serialport_re [string_to_regexp $serialport]
54    for {set i 1} {$i <= 3} {incr i} {
55	send_gdb "target $targetname $serialport\n"
56	gdb_expect 60 {
57	    -re "A program is being debugged already.*ill it.*y or n. $" {
58		send_gdb "y\n"
59		exp_continue
60	    }
61	    -re "unknown host.*$gdb_prompt" {
62	        verbose "Couldn't look up $serialport"
63	    }
64	    -re "Couldn't establish connection to remote.*$gdb_prompt $" {
65		verbose "Connection failed"
66	    }
67	    -re "Non-stop mode requested, but remote does not support non-stop.*$gdb_prompt $" {
68		verbose "remote does not support non-stop"
69		return 1
70	    }
71	    -re "Remote MIPS debugging.*$additional_text.*$gdb_prompt" {
72		verbose "Set target to $targetname"
73		return 0
74	    }
75	    -re "Remote debugging using .*$serialport_re.*$additional_text.*$gdb_prompt $" {
76		verbose "Set target to $targetname"
77		return 0
78	    }
79	    -re "Remote debugging using stdio.*$additional_text.*$gdb_prompt $" {
80		verbose "Set target to $targetname"
81		return 0
82	    }
83	    -re "Remote target $targetname connected to.*$additional_text.*$gdb_prompt $" {
84		verbose "Set target to $targetname"
85		return 0
86	    }
87	    -re "Connected to.*$additional_text.*$gdb_prompt $" {
88		verbose "Set target to $targetname"
89		return 0
90	    }
91	    -re "Ending remote.*$gdb_prompt $" { }
92	    -re "Connection refused.*$gdb_prompt $" {
93		verbose "Connection refused by remote target.  Pausing, and trying again."
94		sleep 30
95		continue
96	    }
97	    -re "Timeout reading from remote system.*$gdb_prompt $" {
98		verbose "Got timeout error from gdb."
99	    }
100	    -notransfer -re "Remote debugging using .*\r\n> $" {
101		# We got an unexpected prompt while creating the target.
102		# Leave it there for the test to diagnose.
103		return 1
104	    }
105	    -re ": Network is unreachable.\r\n.*$gdb_prompt $" {
106		return 2
107	    }
108	    timeout {
109		send_gdb ""
110		break
111	    }
112	}
113    }
114    return 1
115}
116
117# Like gdb_target_cmd_ext, but returns 0 on success, 1 on failure.
118
119proc gdb_target_cmd { args } {
120    set res [eval gdb_target_cmd_ext $args]
121    return [expr $res == 0 ? 0 : 1]
122}
123
124global portnum
125set portnum "2345"
126
127# Locate the gdbserver binary.  Returns "" if gdbserver could not be found.
128
129proc find_gdbserver { } {
130  global GDB
131  global GDBSERVER
132
133  if [info exists GDBSERVER] {
134    return ${GDBSERVER}
135  }
136
137  if [target_info exists gdb_server_prog] {
138    return [target_info gdb_server_prog]
139  }
140
141  set toplevel [file join [file dirname $GDB] .. gdbserver]
142  foreach gdbserver [list "${GDB}server" $toplevel] {
143      if { [file isdirectory $gdbserver] } {
144	  append gdbserver "/gdbserver"
145      }
146
147      if { [file executable $gdbserver] } {
148	  return $gdbserver
149      }
150  }
151
152  return ""
153}
154
155# Return non-zero if we should skip gdbserver-specific tests.
156
157proc skip_gdbserver_tests { } {
158  if { [find_gdbserver] == "" } {
159    return 1
160  }
161
162    # If GDB is lack of XML support, and targets, like arm, have
163    # multiple target descriptions, GDB doesn't know which target
164    # description GDBserver uses, and may fail to parse 'g' packet
165    # after connection.
166    if { [gdb_skip_xml_test]
167	 && ([istarget "arm*-*-linux*"]
168	     || [istarget "mips*-*-linux*"]
169	     || [istarget "powerpc*-*-linux*"]
170	     || [istarget "s390*-*-linux*"]
171	     || [istarget "x86_64-*-linux*"]
172	     || [istarget "i\[34567\]86-*-linux*"]) } {
173	return 1
174    }
175
176  return 0
177}
178
179# Download the currently loaded program to the target if necessary.
180# Return the target system filename.
181# NOTE: This was named "gdbserver_download", but that collides with the
182# dejagnu "download" API function when using load_generic_config "gdbserver".
183
184proc gdbserver_download_current_prog { } {
185    global gdbserver_host_exec
186    global gdbserver_host_mtime
187    global gdbserver_server_exec
188    global last_loaded_file
189
190    if { ![info exists last_loaded_file] } {
191	return ""
192    }
193
194    set host_exec $last_loaded_file
195
196    # If we already downloaded a file to the target, see if we can reuse it.
197    set reuse 0
198    if { [info exists gdbserver_server_exec] } {
199	set reuse 1
200
201	# If the file has changed, we can not.
202	if { $host_exec != $gdbserver_host_exec } {
203	    set reuse 0
204	}
205
206	# If the mtime has changed, we can not.
207	if { [file mtime $host_exec] != $gdbserver_host_mtime } {
208	    set reuse 0
209	}
210    }
211
212    if { $reuse == 0 } {
213	set gdbserver_host_exec $host_exec
214	set gdbserver_host_mtime [file mtime $host_exec]
215	set gdbserver_server_exec [gdb_remote_download target $host_exec]
216    }
217
218    return $gdbserver_server_exec
219}
220
221# Default routine to compute the argument to "target remote".
222
223proc gdbserver_default_get_remote_address { host port } {
224    # Historically HOST included the trailing ":".
225    # To avoid breaking any board files out there we leave things alone.
226    return "$host$port"
227}
228
229# Default routine to compute the "comm" argument for gdbserver.
230
231proc gdbserver_default_get_comm_port { port } {
232    return "$port"
233}
234
235# Start a gdbserver process with initial OPTIONS and trailing ARGUMENTS.
236# The port will be filled in between them automatically.
237#
238# Returns the target protocol and socket to connect to.
239
240proc gdbserver_start { options arguments } {
241    global portnum
242    global GDB_TEST_SOCKETHOST
243
244    # Port id -- either specified in baseboard file, or managed here.
245    if [target_info exists gdb,socketport] {
246	set portnum [target_info gdb,socketport]
247    } else {
248	# Bump the port number to avoid conflicts with hung ports.
249	incr portnum
250    }
251
252    # Extract the local and remote host ids from the target board struct.
253    if { [info exists GDB_TEST_SOCKETHOST] } {
254	# The user is not supposed to provide a port number, just a
255	# hostname/address, therefore we add the trailing ":" here.
256	set debughost "${GDB_TEST_SOCKETHOST}:"
257	# Escape open and close square brackets.
258	set debughost_tmp [string map { [ \\[ ] \\] } $debughost]
259	# We need a "gdbserver" version of the debughost, which will
260	# have the possible connection prefix stripped.  This is
261	# because gdbserver currently doesn't recognize the prefixes.
262	regsub -all "^\(tcp:|udp:|tcp4:|udp4:|tcp6:|udp6:\)" $debughost_tmp "" debughost_gdbserver
263    } elseif [target_info exists sockethost] {
264	set debughost [target_info sockethost]
265	set debughost_gdbserver $debughost
266    } else {
267	set debughost "localhost:"
268	set debughost_gdbserver $debughost
269    }
270
271    # Some boards use a different value for the port that is passed to
272    # gdbserver and the port that is passed to the "target remote" command.
273    # One example is the stdio gdbserver support.
274    if [target_info exists gdb,get_remote_address] {
275	set get_remote_address [target_info gdb,get_remote_address]
276    } else {
277	set get_remote_address gdbserver_default_get_remote_address
278    }
279    if [target_info exists gdbserver,get_comm_port] {
280	set get_comm_port [target_info gdbserver,get_comm_port]
281    } else {
282	set get_comm_port gdbserver_default_get_comm_port
283    }
284
285    # Extract the protocol
286    if [target_info exists gdb_protocol] {
287	set protocol [target_info gdb_protocol]
288    } else {
289	set protocol "remote"
290    }
291
292    set gdbserver [find_gdbserver]
293
294    # Loop till we find a free port.
295    while 1 {
296	# Fire off the debug agent.
297	set gdbserver_command "$gdbserver"
298
299	# If gdbserver_reconnect will be called $gdbserver_reconnect_p must be
300	# set to true already during gdbserver_start.
301	global gdbserver_reconnect_p
302	global srcdir
303	global subdir
304	if {![info exists gdbserver_reconnect_p] || !$gdbserver_reconnect_p} {
305	    # GDB client could accidentally connect to a stale server.
306	    append gdbserver_command " --once"
307	}
308
309	# Enable debug if set.
310	if [gdbserver_debug_enabled] {
311	    global gdbserverdebug
312	    set enabled 0
313	    foreach entry [split $gdbserverdebug ,] {
314	      switch -- $entry {
315		"debug" {
316		  append gdbserver_command " --debug"
317		  set enabled 1
318		}
319		"remote" {
320		  append gdbserver_command " --remote-debug"
321		  set enabled 1
322		}
323	      }
324	    }
325	    # Ensure debugfile is only added if something has been enabled
326	    if { $enabled } {
327	      set debugfile [standard_output_file gdbserver.debug]
328	      append gdbserver_command " --debug-file=$debugfile"
329	    }
330	}
331
332	if { $options != "" } {
333	    append gdbserver_command " $options"
334	}
335	if { $debughost_gdbserver != "" } {
336	    append gdbserver_command " $debughost_gdbserver"
337	}
338	if { $portnum != "" } {
339	    if { $debughost_gdbserver == "" } {
340		append gdbserver_command " "
341	    }
342	    append gdbserver_command "[$get_comm_port $portnum]"
343	}
344	if { $arguments != "" } {
345	    append gdbserver_command " $arguments"
346	}
347
348	gdbserver_write_cmd_file $gdbserver_command
349
350	global server_spawn_id
351	set server_spawn_id [remote_spawn target $gdbserver_command]
352
353	# GDBserver doesn't do inferior I/O through GDB.  But we can
354	# talk to the program using GDBserver's tty instead.
355	global inferior_spawn_id
356	set inferior_spawn_id $server_spawn_id
357
358	# Wait for the server to open its TCP socket, so that GDB can connect.
359	expect {
360	    -i $server_spawn_id
361	    -timeout 120
362	    -notransfer
363	    -re "Listening on" { }
364	    -re "Can't (bind address|listen on socket): Address already in use\\.\r\n" {
365		verbose -log "Port $portnum is already in use."
366		if ![target_info exists gdb,socketport] {
367		    # Bump the port number to avoid the conflict.
368		    wait -i $expect_out(spawn_id)
369		    incr portnum
370		    continue
371		}
372	    }
373	    -re ".*: cannot resolve name: .*\r\n" {
374		error "gdbserver cannot resolve name."
375	    }
376	    timeout {
377		error "Timeout waiting for gdbserver response."
378	    }
379	}
380	break
381    }
382
383    return [list $protocol [$get_remote_address $debughost $portnum]]
384}
385
386# Start a gdbserver process running SERVER_EXEC, and connect GDB
387# to it.  CHILD_ARGS are passed to the inferior.
388#
389# Returns the target protocol and socket to connect to.
390
391proc gdbserver_spawn { child_args } {
392    set target_exec [gdbserver_download_current_prog]
393
394    # Fire off the debug agent.  This flavour of gdbserver takes as
395    # arguments the port information, the name of the executable file to
396    # be debugged, and any arguments.
397    set arguments "$target_exec"
398    if { $child_args != "" } {
399	append arguments " $child_args"
400    }
401    return [gdbserver_start "" $arguments]
402}
403
404# Close the GDBserver connection.
405
406proc close_gdbserver {} {
407    global server_spawn_id
408
409    # We can't just call close, because if gdbserver is local then that means
410    # that it will get a SIGHUP.  Doing it this way could also allow us to
411    # get at the inferior's input or output if necessary, and means that we
412    # don't need to redirect output.
413
414    if {![info exists server_spawn_id]} {
415	return
416    }
417
418    verbose "Quitting GDBserver"
419
420    catch "close -i $server_spawn_id"
421    catch "wait -i $server_spawn_id"
422    unset server_spawn_id
423}
424
425# Hook into GDB exit, and close GDBserver.  We must load this
426# explicitly here, and rename the procedures we want to override.
427load_lib mi-support.exp
428
429if { [info procs gdbserver_orig_gdb_exit] == "" } {
430    rename gdb_exit gdbserver_orig_gdb_exit
431    rename mi_gdb_exit gdbserver_orig_mi_gdb_exit
432}
433
434# Cleanup gdbserver $server_spawn_id
435
436proc gdbserver_exit { is_mi } {
437    global gdb_spawn_id server_spawn_id
438    global gdb_prompt
439
440    if {[info exists gdb_spawn_id] && [info exists server_spawn_id]} {
441	# GDB may be terminated in an expected way or an unexpected way,
442	# but DejaGNU doesn't know that, so gdb_spawn_id isn't unset.
443	# Catch the exceptions.
444	catch {
445	    if { $is_mi } {
446		set monitor_exit "-interpreter-exec console \"monitor exit\""
447	    } else {
448		set monitor_exit "monitor exit"
449	    }
450	    send_gdb "$monitor_exit\n";
451	    # We use expect rather than gdb_expect because
452	    # we want to suppress printing exception messages, otherwise,
453	    # remote_expect, invoked by gdb_expect, prints the exceptions.
454	    expect {
455		-i "$gdb_spawn_id" -re "$gdb_prompt $" {
456		    exp_continue
457		}
458		-i "$server_spawn_id" eof {
459		    wait -i $expect_out(spawn_id)
460		    unset server_spawn_id
461		}
462               timeout {
463                   warning "Timed out waiting for EOF in server after $monitor_exit"
464               }
465	    }
466	}
467    }
468    close_gdbserver
469}
470
471# Local version of gdb_exit that also cleans up gdbserver $server_spawn_id.
472
473proc gdbserver_gdb_exit { is_mi } {
474    global gdb_spawn_id server_spawn_id
475    global gdb_prompt
476    global gdbserver_reconnect_p
477
478    # Leave GDBserver running if we're exiting GDB in order to
479    # reconnect to the same instance of GDBserver again.
480    if {[info exists gdbserver_reconnect_p] && $gdbserver_reconnect_p} {
481	if { $is_mi } {
482	    gdbserver_orig_mi_gdb_exit
483	} else {
484	    gdbserver_orig_gdb_exit
485	}
486	return
487    }
488
489    gdbserver_exit $is_mi
490
491    if { $is_mi } {
492	gdbserver_orig_mi_gdb_exit
493    } else {
494	gdbserver_orig_gdb_exit
495    }
496}
497
498proc gdb_exit {} {
499    gdbserver_gdb_exit 0
500}
501
502proc mi_gdb_exit {} {
503    gdbserver_gdb_exit 1
504}
505
506# Start a gdbserver process running HOST_EXEC and pass CHILD_ARGS
507# to it.  Return 0 on success, or non-zero on failure: 2 if gdbserver
508# failed to start or 1 if we couldn't connect to it.
509
510proc gdbserver_run { child_args } {
511    global gdbserver_protocol
512    global gdbserver_gdbport
513
514    # Kill anything running before we try to start gdbserver, in case
515    # we are sharing a serial connection.
516    global gdb_prompt
517    send_gdb "kill\n" optional
518    gdb_expect 120 {
519	-re "Kill the program being debugged. .y or n. $" {
520	    send_gdb "y\n"
521	    verbose "\t\tKilling previous program being debugged"
522	    exp_continue
523	}
524	-re "$gdb_prompt $" {
525	    # OK.
526	}
527    }
528
529    if { [catch { gdbserver_spawn $child_args } res] == 1 } {
530	perror $res
531	return 2
532    }
533    set gdbserver_protocol [lindex $res 0]
534    set gdbserver_gdbport [lindex $res 1]
535
536    return [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
537}
538
539# Reconnect to the previous gdbserver session.
540
541proc gdbserver_reconnect { } {
542    global gdbserver_protocol
543    global gdbserver_gdbport
544
545    global gdbserver_reconnect_p
546    if {![info exists gdbserver_reconnect_p] || !$gdbserver_reconnect_p} {
547	error "gdbserver_reconnect_p is not set before gdbserver_reconnect"
548	return 0
549    }
550
551    return [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
552}
553
554# Start gdbserver in extended mode with OPTIONS and connect to it.  Note
555# this frobs $gdbserver_protocol, so should be used only from a board
556# that usually connects in target remote mode.
557proc gdbserver_start_extended { {options ""} } {
558    global gdbserver_protocol
559    global gdbserver_gdbport
560    global use_gdb_stub
561
562    set gdbserver_options "--multi"
563
564    if { $options != "" } {
565	append gdbserver_options " $options"
566    }
567
568    if { [catch { gdbserver_start $gdbserver_options "" } res] == 1 } {
569	perror $res
570	return 2
571    }
572    set gdbserver_protocol [lindex $res 0]
573    if { [string first "extended-" $gdbserver_protocol] != 0} {
574	set gdbserver_protocol "extended-$gdbserver_protocol"
575    }
576    set gdbserver_gdbport [lindex $res 1]
577
578    # Even if the board file is testing with target remote, our caller
579    # wants to test against gdbserver in extended-remote mode.  Make sure to
580    # disable stub-like techniques.
581    set use_gdb_stub 0
582
583    return [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
584}
585
586# Start and connect to a gdbserver in extended/multi mode.  Unlike
587# gdbserver_start_extended, this does not frob $gdbserver_protocol.
588
589proc gdbserver_start_multi { } {
590    global gdbserver_protocol
591    global gdbserver_gdbport
592
593    if { [catch { gdbserver_start "--multi" "" } res] == 1 } {
594	perror $res
595	return 2
596    }
597    set gdbserver_protocol [lindex $res 0]
598    set gdbserver_gdbport [lindex $res 1]
599
600    return [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
601}
602
603# Start a gdbserver process in multi/extended mode, and have GDB
604# connect to it (MI version).  Return 0 on success, or non-zero on
605# failure.
606
607proc mi_gdbserver_start_multi { } {
608    global gdbserver_protocol
609    global gdbserver_gdbport
610
611    if { [catch { gdbserver_start "--multi" "" } res] == 1 } {
612	perror $res
613	return 2
614    }
615    set gdbserver_protocol [lindex $res 0]
616    set gdbserver_gdbport [lindex $res 1]
617
618    return [mi_gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
619}
620
621# Check if debugging is enabled for gdbserver.
622
623proc gdbserver_debug_enabled { } {
624    global gdbserverdebug
625
626    # If not already read, get the debug setting from environment or board setting.
627    if ![info exists gdbserverdebug] {
628	global env
629	if [info exists env(GDBSERVER_DEBUG)] {
630	    set gdbserverdebug $env(GDBSERVER_DEBUG)
631	} elseif [target_info exists gdbserver,debug] {
632	    set gdbserverdebug [target_info gdbserver,debug]
633	} else {
634	    return 0
635	}
636    }
637
638    # Expand the all option
639    if { $gdbserverdebug == "all" } {
640      set gdbserverdebug "debug,remote,replay"
641    }
642
643    # Ensure it is not empty.
644    return [expr { $gdbserverdebug != "" }]
645}
646
647# Write the command line used to invocate gdbserver to the cmd file.
648
649proc gdbserver_write_cmd_file { cmdline } {
650    set logfile [standard_output_file_with_gdb_instance gdbserver.cmd]
651    set cmd_file [open $logfile w]
652    puts $cmd_file $cmdline
653    catch "close $cmd_file"
654}
655
656# Override gdb_debug_init so that we can set replay logging in GDB if required.
657# Backup the original function so we can call it afterwards
658
659rename gdb_debug_init _gdb_debug_init
660
661proc gdb_debug_init { } {
662    global gdbserverdebug
663    global gdb_prompt
664
665    if [gdbserver_debug_enabled] {
666      foreach entry [split $gdbserverdebug ,] {
667	if { $entry == "replay" } {
668	  set replayfile [standard_output_file_with_gdb_instance gdbserver.replay]
669          send_gdb "set remotelogfile $replayfile\n" optional
670	  gdb_expect 10 {
671	    -re "$gdb_prompt $" {}
672	  }
673	}
674      }
675    }
676
677    # Now call the standard debug init function
678    _gdb_debug_init
679}
680