Add assert to save me from myself.
[riscv-tests.git] / debug / gdbserver.py
1 #!/usr/bin/env python
2
3 import argparse
4 import binascii
5 import random
6 import sys
7 import tempfile
8 import time
9 import os
10
11 import targets
12 import testlib
13 from testlib import assertEqual, assertNotEqual, assertIn
14 from testlib import assertGreater, assertTrue, assertRegexpMatches, assertLess
15 from testlib import GdbTest
16
17 MSTATUS_UIE = 0x00000001
18 MSTATUS_SIE = 0x00000002
19 MSTATUS_HIE = 0x00000004
20 MSTATUS_MIE = 0x00000008
21 MSTATUS_UPIE = 0x00000010
22 MSTATUS_SPIE = 0x00000020
23 MSTATUS_HPIE = 0x00000040
24 MSTATUS_MPIE = 0x00000080
25 MSTATUS_SPP = 0x00000100
26 MSTATUS_HPP = 0x00000600
27 MSTATUS_MPP = 0x00001800
28 MSTATUS_FS = 0x00006000
29 MSTATUS_XS = 0x00018000
30 MSTATUS_MPRV = 0x00020000
31 MSTATUS_PUM = 0x00040000
32 MSTATUS_MXR = 0x00080000
33 MSTATUS_VM = 0x1F000000
34 MSTATUS32_SD = 0x80000000
35 MSTATUS64_SD = 0x8000000000000000
36
37 # pylint: disable=abstract-method
38
39 def ihex_line(address, record_type, data):
40 assert len(data) < 128
41 line = ":%02X%04X%02X" % (len(data), address, record_type)
42 check = len(data)
43 check += address % 256
44 check += address >> 8
45 check += record_type
46 for char in data:
47 value = ord(char)
48 check += value
49 line += "%02X" % value
50 line += "%02X\n" % ((256-check)%256)
51 return line
52
53 def ihex_parse(line):
54 assert line.startswith(":")
55 line = line[1:]
56 data_len = int(line[:2], 16)
57 address = int(line[2:6], 16)
58 record_type = int(line[6:8], 16)
59 data = ""
60 for i in range(data_len):
61 data += "%c" % int(line[8+2*i:10+2*i], 16)
62 return record_type, address, data
63
64 def readable_binary_string(s):
65 return "".join("%02x" % ord(c) for c in s)
66
67 class SimpleRegisterTest(GdbTest):
68 def check_reg(self, name):
69 a = random.randrange(1<<self.target.xlen)
70 b = random.randrange(1<<self.target.xlen)
71 self.gdb.p("$%s=0x%x" % (name, a))
72 self.gdb.stepi()
73 assertEqual(self.gdb.p("$%s" % name), a)
74 self.gdb.p("$%s=0x%x" % (name, b))
75 self.gdb.stepi()
76 assertEqual(self.gdb.p("$%s" % name), b)
77
78 def setup(self):
79 # 0x13 is nop
80 self.gdb.command("p *((int*) 0x%x)=0x13" % self.target.ram)
81 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 4))
82 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 8))
83 self.gdb.p("$pc=0x%x" % self.target.ram)
84
85 class SimpleS0Test(SimpleRegisterTest):
86 def test(self):
87 self.check_reg("s0")
88
89 class SimpleS1Test(SimpleRegisterTest):
90 def test(self):
91 self.check_reg("s1")
92
93 class SimpleT0Test(SimpleRegisterTest):
94 def test(self):
95 self.check_reg("t0")
96
97 class SimpleT1Test(SimpleRegisterTest):
98 def test(self):
99 self.check_reg("t1")
100
101 class SimpleF18Test(SimpleRegisterTest):
102 def check_reg(self, name):
103 a = random.random()
104 b = random.random()
105 self.gdb.p_raw("$%s=%f" % (name, a))
106 self.gdb.stepi()
107 assertLess(abs(float(self.gdb.p_raw("$%s" % name)) - a), .001)
108 self.gdb.p_raw("$%s=%f" % (name, b))
109 self.gdb.stepi()
110 assertLess(abs(float(self.gdb.p_raw("$%s" % name)) - b), .001)
111
112 def early_applicable(self):
113 return self.target.extensionSupported('F')
114
115 def test(self):
116 self.check_reg("f18")
117
118 class SimpleMemoryTest(GdbTest):
119 def access_test(self, size, data_type):
120 assertEqual(self.gdb.p("sizeof(%s)" % data_type), size)
121 a = 0x86753095555aaaa & ((1<<(size*8))-1)
122 b = 0xdeadbeef12345678 & ((1<<(size*8))-1)
123 self.gdb.p("*((%s*)0x%x) = 0x%x" % (data_type, self.target.ram, a))
124 self.gdb.p("*((%s*)0x%x) = 0x%x" % (data_type, self.target.ram + size,
125 b))
126 assertEqual(self.gdb.p("*((%s*)0x%x)" % (data_type, self.target.ram)),
127 a)
128 assertEqual(self.gdb.p("*((%s*)0x%x)" % (
129 data_type, self.target.ram + size)), b)
130
131 class MemTest8(SimpleMemoryTest):
132 def test(self):
133 self.access_test(1, 'char')
134
135 class MemTest16(SimpleMemoryTest):
136 def test(self):
137 self.access_test(2, 'short')
138
139 class MemTest32(SimpleMemoryTest):
140 def test(self):
141 self.access_test(4, 'int')
142
143 class MemTest64(SimpleMemoryTest):
144 def test(self):
145 self.access_test(8, 'long long')
146
147 class MemTestReadInvalid(SimpleMemoryTest):
148 def test(self):
149 # This test relies on 'gdb_report_data_abort enable' being executed in
150 # the openocd.cfg file.
151 try:
152 self.gdb.p("*((int*)0xdeadbeef)")
153 assert False, "Read should have failed."
154 except testlib.CannotAccess as e:
155 assertEqual(e.address, 0xdeadbeef)
156 self.gdb.p("*((int*)0x%x)" % self.target.ram)
157
158 class MemTestWriteInvalid(SimpleMemoryTest):
159 def test(self):
160 # This test relies on 'gdb_report_data_abort enable' being executed in
161 # the openocd.cfg file.
162 try:
163 self.gdb.p("*((int*)0xdeadbeef)=8675309")
164 assert False, "Write should have failed."
165 except testlib.CannotAccess as e:
166 assertEqual(e.address, 0xdeadbeef)
167 self.gdb.p("*((int*)0x%x)=6874742" % self.target.ram)
168
169 class MemTestBlock(GdbTest):
170 def test(self):
171 length = 1024
172 line_length = 16
173 a = tempfile.NamedTemporaryFile(suffix=".ihex")
174 data = ""
175 for i in range(length / line_length):
176 line_data = "".join(["%c" % random.randrange(256)
177 for _ in range(line_length)])
178 data += line_data
179 a.write(ihex_line(i * line_length, 0, line_data))
180 a.flush()
181
182 self.gdb.command("restore %s 0x%x" % (a.name, self.target.ram))
183 for offset in range(0, length, 19*4) + [length-4]:
184 value = self.gdb.p("*((int*)0x%x)" % (self.target.ram + offset))
185 written = ord(data[offset]) | \
186 (ord(data[offset+1]) << 8) | \
187 (ord(data[offset+2]) << 16) | \
188 (ord(data[offset+3]) << 24)
189 assertEqual(value, written)
190
191 b = tempfile.NamedTemporaryFile(suffix=".ihex")
192 self.gdb.command("dump ihex memory %s 0x%x 0x%x" % (b.name,
193 self.target.ram, self.target.ram + length))
194 for line in b:
195 record_type, address, line_data = ihex_parse(line)
196 if record_type == 0:
197 assertEqual(readable_binary_string(line_data),
198 readable_binary_string(
199 data[address:address+len(line_data)]))
200
201 class InstantHaltTest(GdbTest):
202 def test(self):
203 assertEqual(self.target.reset_vector, self.gdb.p("$pc"))
204 # mcycle and minstret have no defined reset value.
205 mstatus = self.gdb.p("$mstatus")
206 assertEqual(mstatus & (MSTATUS_MIE | MSTATUS_MPRV |
207 MSTATUS_VM), 0)
208
209 class InstantChangePc(GdbTest):
210 def test(self):
211 """Change the PC right as we come out of reset."""
212 # 0x13 is nop
213 self.gdb.command("p *((int*) 0x%x)=0x13" % self.target.ram)
214 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 4))
215 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 8))
216 self.gdb.p("$pc=0x%x" % self.target.ram)
217 self.gdb.stepi()
218 assertEqual((self.target.ram + 4), self.gdb.p("$pc"))
219 self.gdb.stepi()
220 assertEqual((self.target.ram + 8), self.gdb.p("$pc"))
221
222 class DebugTest(GdbTest):
223 # Include malloc so that gdb can make function calls. I suspect this malloc
224 # will silently blow through the memory set aside for it, so be careful.
225 compile_args = ("programs/debug.c", "programs/checksum.c",
226 "programs/tiny-malloc.c", "-DDEFINE_MALLOC", "-DDEFINE_FREE")
227
228 def setup(self):
229 self.gdb.load()
230 self.gdb.b("_exit")
231
232 def exit(self, expected_result=0xc86455d4):
233 output = self.gdb.c()
234 assertIn("Breakpoint", output)
235 assertIn("_exit", output)
236 assertEqual(self.gdb.p("status"), expected_result)
237
238 class DebugCompareSections(DebugTest):
239 def test(self):
240 output = self.gdb.command("compare-sections")
241 matched = 0
242 for line in output.splitlines():
243 if line.startswith("Section"):
244 assert line.endswith("matched.")
245 matched += 1
246 assertGreater(matched, 1)
247
248 class DebugFunctionCall(DebugTest):
249 def test(self):
250 self.gdb.b("main:start")
251 self.gdb.c()
252 assertEqual(self.gdb.p('fib(6)'), 8)
253 assertEqual(self.gdb.p('fib(7)'), 13)
254 self.exit()
255
256 class DebugChangeString(DebugTest):
257 def test(self):
258 text = "This little piggy went to the market."
259 self.gdb.b("main:start")
260 self.gdb.c()
261 self.gdb.p('fox = "%s"' % text)
262 self.exit(0x43b497b8)
263
264 class DebugTurbostep(DebugTest):
265 def test(self):
266 """Single step a bunch of times."""
267 self.gdb.b("main:start")
268 self.gdb.c()
269 self.gdb.command("p i=0")
270 last_pc = None
271 advances = 0
272 jumps = 0
273 for _ in range(100):
274 self.gdb.stepi()
275 pc = self.gdb.p("$pc")
276 assertNotEqual(last_pc, pc)
277 if last_pc and pc > last_pc and pc - last_pc <= 4:
278 advances += 1
279 else:
280 jumps += 1
281 last_pc = pc
282 # Some basic sanity that we're not running between breakpoints or
283 # something.
284 assertGreater(jumps, 10)
285 assertGreater(advances, 50)
286
287 class DebugExit(DebugTest):
288 def test(self):
289 self.exit()
290
291 class DebugSymbols(DebugTest):
292 def test(self):
293 self.gdb.b("main")
294 self.gdb.b("rot13")
295 output = self.gdb.c()
296 assertIn(", main ", output)
297 output = self.gdb.c()
298 assertIn(", rot13 ", output)
299
300 class DebugBreakpoint(DebugTest):
301 def test(self):
302 self.gdb.b("rot13")
303 # The breakpoint should be hit exactly 2 times.
304 for _ in range(2):
305 output = self.gdb.c()
306 self.gdb.p("$pc")
307 assertIn("Breakpoint ", output)
308 assertIn("rot13 ", output)
309 self.exit()
310
311 class Hwbp1(DebugTest):
312 def test(self):
313 if self.target.instruction_hardware_breakpoint_count < 1:
314 return 'not_applicable'
315
316 self.gdb.hbreak("rot13")
317 # The breakpoint should be hit exactly 2 times.
318 for _ in range(2):
319 output = self.gdb.c()
320 self.gdb.p("$pc")
321 assertRegexpMatches(output, r"[bB]reakpoint")
322 assertIn("rot13 ", output)
323 self.exit()
324
325 class Hwbp2(DebugTest):
326 def test(self):
327 if self.target.instruction_hardware_breakpoint_count < 2:
328 return 'not_applicable'
329
330 self.gdb.hbreak("main")
331 self.gdb.hbreak("rot13")
332 # We should hit 3 breakpoints.
333 for expected in ("main", "rot13", "rot13"):
334 output = self.gdb.c()
335 self.gdb.p("$pc")
336 assertRegexpMatches(output, r"[bB]reakpoint")
337 assertIn("%s " % expected, output)
338 self.exit()
339
340 class TooManyHwbp(DebugTest):
341 def run(self):
342 for i in range(30):
343 self.gdb.hbreak("*rot13 + %d" % (i * 4))
344
345 output = self.gdb.c()
346 assertIn("Cannot insert hardware breakpoint", output)
347 # Clean up, otherwise the hardware breakpoints stay set and future
348 # tests may fail.
349 self.gdb.command("D")
350
351 class Registers(DebugTest):
352 def test(self):
353 # Get to a point in the code where some registers have actually been
354 # used.
355 self.gdb.b("rot13")
356 self.gdb.c()
357 self.gdb.c()
358 # Try both forms to test gdb.
359 for cmd in ("info all-registers", "info registers all"):
360 output = self.gdb.command(cmd)
361 for reg in ('zero', 'ra', 'sp', 'gp', 'tp'):
362 assertIn(reg, output)
363
364 #TODO
365 # mcpuid is one of the few registers that should have the high bit set
366 # (for rv64).
367 # Leave this commented out until gdb and spike agree on the encoding of
368 # mcpuid (which is going to be renamed to misa in any case).
369 #assertRegexpMatches(output, ".*mcpuid *0x80")
370
371 #TODO:
372 # The instret register should always be changing.
373 #last_instret = None
374 #for _ in range(5):
375 # instret = self.gdb.p("$instret")
376 # assertNotEqual(instret, last_instret)
377 # last_instret = instret
378 # self.gdb.stepi()
379
380 self.exit()
381
382 class UserInterrupt(DebugTest):
383 def test(self):
384 """Sending gdb ^C while the program is running should cause it to
385 halt."""
386 self.gdb.b("main:start")
387 self.gdb.c()
388 self.gdb.p("i=123")
389 self.gdb.c(wait=False)
390 time.sleep(0.5)
391 output = self.gdb.interrupt()
392 assert "main" in output
393 assertGreater(self.gdb.p("j"), 10)
394 self.gdb.p("i=0")
395 self.exit()
396
397 class StepTest(GdbTest):
398 compile_args = ("programs/step.S", )
399
400 def setup(self):
401 self.gdb.load()
402 self.gdb.b("main")
403 self.gdb.c()
404
405 def test(self):
406 main_address = self.gdb.p("$pc")
407 if self.target.extensionSupported("c"):
408 sequence = (4, 8, 0xc, 0xe, 0x14, 0x18, 0x22, 0x1c, 0x24, 0x24)
409 else:
410 sequence = (4, 8, 0xc, 0x10, 0x18, 0x1c, 0x28, 0x20, 0x2c, 0x2c)
411 for expected in sequence:
412 self.gdb.stepi()
413 pc = self.gdb.p("$pc")
414 assertEqual("%x" % (pc - main_address), "%x" % expected)
415
416 class TriggerTest(GdbTest):
417 compile_args = ("programs/trigger.S", )
418 def setup(self):
419 self.gdb.load()
420 self.gdb.b("_exit")
421 self.gdb.b("main")
422 self.gdb.c()
423
424 def exit(self):
425 output = self.gdb.c()
426 assertIn("Breakpoint", output)
427 assertIn("_exit", output)
428
429 class TriggerExecuteInstant(TriggerTest):
430 """Test an execute breakpoint on the first instruction executed out of
431 debug mode."""
432 def test(self):
433 main_address = self.gdb.p("$pc")
434 self.gdb.command("hbreak *0x%x" % (main_address + 4))
435 self.gdb.c()
436 assertEqual(self.gdb.p("$pc"), main_address+4)
437
438 class TriggerLoadAddress(TriggerTest):
439 def test(self):
440 self.gdb.command("rwatch *((&data)+1)")
441 output = self.gdb.c()
442 assertIn("read_loop", output)
443 assertEqual(self.gdb.p("$a0"),
444 self.gdb.p("(&data)+1"))
445 self.exit()
446
447 class TriggerLoadAddressInstant(TriggerTest):
448 """Test a load address breakpoint on the first instruction executed out of
449 debug mode."""
450 def test(self):
451 self.gdb.command("b just_before_read_loop")
452 self.gdb.c()
453 read_loop = self.gdb.p("&read_loop")
454 self.gdb.command("rwatch data")
455 self.gdb.c()
456 # Accept hitting the breakpoint before or after the load instruction.
457 assertIn(self.gdb.p("$pc"), [read_loop, read_loop + 4])
458 assertEqual(self.gdb.p("$a0"), self.gdb.p("&data"))
459
460 class TriggerStoreAddress(TriggerTest):
461 def test(self):
462 self.gdb.command("watch *((&data)+3)")
463 output = self.gdb.c()
464 assertIn("write_loop", output)
465 assertEqual(self.gdb.p("$a0"),
466 self.gdb.p("(&data)+3"))
467 self.exit()
468
469 class TriggerStoreAddressInstant(TriggerTest):
470 def test(self):
471 """Test a store address breakpoint on the first instruction executed out
472 of debug mode."""
473 self.gdb.command("b just_before_write_loop")
474 self.gdb.c()
475 write_loop = self.gdb.p("&write_loop")
476 self.gdb.command("watch data")
477 self.gdb.c()
478 # Accept hitting the breakpoint before or after the store instruction.
479 assertIn(self.gdb.p("$pc"), [write_loop, write_loop + 4])
480 assertEqual(self.gdb.p("$a0"), self.gdb.p("&data"))
481
482 class TriggerDmode(TriggerTest):
483 def check_triggers(self, tdata1_lsbs, tdata2):
484 dmode = 1 << (self.target.xlen-5)
485
486 triggers = []
487
488 if self.target.xlen == 32:
489 xlen_type = 'int'
490 elif self.target.xlen == 64:
491 xlen_type = 'long long'
492 else:
493 raise NotImplementedError
494
495 dmode_count = 0
496 i = 0
497 for i in range(16):
498 tdata1 = self.gdb.p("((%s *)&data)[%d]" % (xlen_type, 2*i))
499 if tdata1 == 0:
500 break
501 tdata2 = self.gdb.p("((%s *)&data)[%d]" % (xlen_type, 2*i+1))
502
503 if tdata1 & dmode:
504 dmode_count += 1
505 else:
506 assertEqual(tdata1 & 0xffff, tdata1_lsbs)
507 assertEqual(tdata2, tdata2)
508
509 assertGreater(i, 1)
510 assertEqual(dmode_count, 1)
511
512 return triggers
513
514 def test(self):
515 self.gdb.command("hbreak write_load_trigger")
516 self.gdb.b("clear_triggers")
517 self.gdb.p("$pc=write_store_trigger")
518 output = self.gdb.c()
519 assertIn("write_load_trigger", output)
520 self.check_triggers((1<<6) | (1<<1), 0xdeadbee0)
521 output = self.gdb.c()
522 assertIn("clear_triggers", output)
523 self.check_triggers((1<<6) | (1<<0), 0xfeedac00)
524
525 class RegsTest(GdbTest):
526 compile_args = ("programs/regs.S", )
527 def setup(self):
528 self.gdb.load()
529 self.gdb.b("main")
530 self.gdb.b("handle_trap")
531 self.gdb.c()
532
533 class WriteGprs(RegsTest):
534 def test(self):
535 regs = [("x%d" % n) for n in range(2, 32)]
536
537 self.gdb.p("$pc=write_regs")
538 for i, r in enumerate(regs):
539 self.gdb.p("$%s=%d" % (r, (0xdeadbeef<<i)+17))
540 self.gdb.p("$x1=data")
541 self.gdb.command("b all_done")
542 output = self.gdb.c()
543 assertIn("Breakpoint ", output)
544
545 # Just to get this data in the log.
546 self.gdb.command("x/30gx data")
547 self.gdb.command("info registers")
548 for n in range(len(regs)):
549 assertEqual(self.gdb.x("data+%d" % (8*n), 'g'),
550 ((0xdeadbeef<<n)+17) & ((1<<self.target.xlen)-1))
551
552 class WriteCsrs(RegsTest):
553 def test(self):
554 # As much a test of gdb as of the simulator.
555 self.gdb.p("$mscratch=0")
556 self.gdb.stepi()
557 assertEqual(self.gdb.p("$mscratch"), 0)
558 self.gdb.p("$mscratch=123")
559 self.gdb.stepi()
560 assertEqual(self.gdb.p("$mscratch"), 123)
561
562 self.gdb.p("$pc=write_regs")
563 self.gdb.p("$x1=data")
564 self.gdb.command("b all_done")
565 self.gdb.command("c")
566
567 assertEqual(123, self.gdb.p("$mscratch"))
568 assertEqual(123, self.gdb.p("$x1"))
569 assertEqual(123, self.gdb.p("$csr832"))
570
571 class DownloadTest(GdbTest):
572 def setup(self):
573 # pylint: disable=attribute-defined-outside-init
574 length = min(2**20, self.target.ram_size - 2048)
575 self.download_c = tempfile.NamedTemporaryFile(prefix="download_",
576 suffix=".c", delete=False)
577 self.download_c.write("#include <stdint.h>\n")
578 self.download_c.write(
579 "unsigned int crc32a(uint8_t *message, unsigned int size);\n")
580 self.download_c.write("uint32_t length = %d;\n" % length)
581 self.download_c.write("uint8_t d[%d] = {\n" % length)
582 self.crc = 0
583 assert length % 16 == 0
584 for i in range(length / 16):
585 self.download_c.write(" /* 0x%04x */ " % (i * 16))
586 for _ in range(16):
587 value = random.randrange(1<<8)
588 self.download_c.write("0x%02x, " % value)
589 self.crc = binascii.crc32("%c" % value, self.crc)
590 self.download_c.write("\n")
591 self.download_c.write("};\n")
592 self.download_c.write("uint8_t *data = &d[0];\n")
593 self.download_c.write(
594 "uint32_t main() { return crc32a(data, length); }\n")
595 self.download_c.flush()
596
597 if self.crc < 0:
598 self.crc += 2**32
599
600 self.binary = self.target.compile(self.download_c.name,
601 "programs/checksum.c")
602 self.gdb.command("file %s" % self.binary)
603
604 def test(self):
605 self.gdb.load()
606 self.gdb.command("b _exit")
607 self.gdb.c(timeout=60)
608 assertEqual(self.gdb.p("status"), self.crc)
609 os.unlink(self.download_c.name)
610
611 class MprvTest(GdbTest):
612 compile_args = ("programs/mprv.S", )
613 def setup(self):
614 self.gdb.load()
615
616 def test(self):
617 """Test that the debugger can access memory when MPRV is set."""
618 self.gdb.c(wait=False)
619 time.sleep(0.5)
620 self.gdb.interrupt()
621 output = self.gdb.command("p/x *(int*)(((char*)&data)-0x80000000)")
622 assertIn("0xbead", output)
623
624 class PrivTest(GdbTest):
625 compile_args = ("programs/priv.S", )
626 def setup(self):
627 # pylint: disable=attribute-defined-outside-init
628 self.gdb.load()
629
630 misa = self.target.misa
631 self.supported = set()
632 if misa & (1<<20):
633 self.supported.add(0)
634 if misa & (1<<18):
635 self.supported.add(1)
636 if misa & (1<<7):
637 self.supported.add(2)
638 self.supported.add(3)
639
640 class PrivRw(PrivTest):
641 def test(self):
642 """Test reading/writing priv."""
643 for privilege in range(4):
644 self.gdb.p("$priv=%d" % privilege)
645 self.gdb.stepi()
646 actual = self.gdb.p("$priv")
647 assertIn(actual, self.supported)
648 if privilege in self.supported:
649 assertEqual(actual, privilege)
650
651 class PrivChange(PrivTest):
652 def test(self):
653 """Test that the core's privilege level actually changes."""
654
655 if 0 not in self.supported:
656 return 'not_applicable'
657
658 self.gdb.b("main")
659 self.gdb.c()
660
661 # Machine mode
662 self.gdb.p("$priv=3")
663 main_address = self.gdb.p("$pc")
664 self.gdb.stepi()
665 assertEqual("%x" % self.gdb.p("$pc"), "%x" % (main_address+4))
666
667 # User mode
668 self.gdb.p("$priv=0")
669 self.gdb.stepi()
670 # Should have taken an exception, so be nowhere near main.
671 pc = self.gdb.p("$pc")
672 assertTrue(pc < main_address or pc > main_address + 0x100)
673
674 parsed = None
675 def main():
676 parser = argparse.ArgumentParser(
677 description="Test that gdb can talk to a RISC-V target.",
678 epilog="""
679 Example command line from the real world:
680 Run all RegsTest cases against a physical FPGA, with custom openocd command:
681 ./gdbserver.py --freedom-e300 --cmd "$HOME/SiFive/openocd/src/openocd -s $HOME/SiFive/openocd/tcl -d" Simple
682 """)
683 targets.add_target_options(parser)
684
685 testlib.add_test_run_options(parser)
686
687 # TODO: remove global
688 global parsed # pylint: disable=global-statement
689 parsed = parser.parse_args()
690
691 target = parsed.target(parsed.cmd, parsed.run, parsed.isolate)
692 if parsed.xlen:
693 target.xlen = parsed.xlen
694
695 module = sys.modules[__name__]
696
697 return testlib.run_all_tests(module, target, parsed)
698
699 # TROUBLESHOOTING TIPS
700 # If a particular test fails, run just that one test, eg.:
701 # ./gdbserver.py MprvTest.test_mprv
702 # Then inspect gdb.log and spike.log to see what happened in more detail.
703
704 if __name__ == '__main__':
705 sys.exit(main())