diff options
| author | Yogesh Tyagi <yogesh.tyagi@intel.com> | 2022-08-08 12:21:40 +0800 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2022-08-10 08:25:28 +0100 |
| commit | b9a57cad4db4ca62af3a49716bf7c56e22f56b71 (patch) | |
| tree | affb5a2134319502aa637ab1390ee4669e79bd91 /meta/lib | |
| parent | fdcb16c6b73158175bb4e0c42f65c99d344e6d46 (diff) | |
| download | poky-b9a57cad4db4ca62af3a49716bf7c56e22f56b71.tar.gz | |
gdbserver : add selftest
The test runs gdbserver on qemu and connects the gdb client from host over TCP.
It builds a cross gdb on the host and compiles the program to be debugged on the target,
launches the gdbserver and tries to connect cross gdb to it.
[YOCTO #13996]
(From OE-Core rev: 37164f7e39eea3a1e594d8306d2569868438ba93)
Signed-off-by: Yogesh Tyagi <yogesh.tyagi@intel.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib')
| -rw-r--r-- | meta/lib/oeqa/selftest/cases/gdbserver.py | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/meta/lib/oeqa/selftest/cases/gdbserver.py b/meta/lib/oeqa/selftest/cases/gdbserver.py new file mode 100644 index 0000000000..2c733a1342 --- /dev/null +++ b/meta/lib/oeqa/selftest/cases/gdbserver.py | |||
| @@ -0,0 +1,122 @@ | |||
| 1 | # SPDX-License-Identifier: MIT | ||
| 2 | # | ||
| 3 | import os | ||
| 4 | from subprocess import Popen, PIPE | ||
| 5 | import threading | ||
| 6 | import time | ||
| 7 | |||
| 8 | from oeqa.selftest.case import OESelftestTestCase | ||
| 9 | from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runqemu , runCmd | ||
| 10 | from oeqa.core.exception import OEQATimeoutError | ||
| 11 | |||
| 12 | |||
| 13 | #The test runs gdbserver on qemu and connects the gdb client from host over TCP. | ||
| 14 | # | ||
| 15 | #It builds a cross gdb on the host and compiles the program to be debugged on the target, | ||
| 16 | #launches the gdbserver and tries to connect cross gdb to it. | ||
| 17 | |||
| 18 | |||
| 19 | class GdbTest(OESelftestTestCase): | ||
| 20 | |||
| 21 | def run_gdb(self, native_sysroot=None, **options): | ||
| 22 | # Add path to cross gdb to environment. | ||
| 23 | extra_paths = "%s/usr/bin/%s" % (self.recipe_sysroot_native, self.target_sys) | ||
| 24 | nenv = dict(options.get('env', os.environ)) | ||
| 25 | nenv['PATH'] = extra_paths + ':' + nenv.get('PATH', '') | ||
| 26 | options['env'] = nenv | ||
| 27 | |||
| 28 | for count in range(5): | ||
| 29 | # Let the gdb server start before by putting client thread to sleep. | ||
| 30 | # Still, if gdb client happens to start before gdbserver, if will | ||
| 31 | # return "gdb connection timed out". In that case try | ||
| 32 | # connecting again | ||
| 33 | time.sleep(1) | ||
| 34 | cmd = "%s-gdb -ex 'set sysroot %s' -ex \"target remote %s:%s\" -ex continue -ex quit %s" \ | ||
| 35 | %(self.target_sys, self.recipe_sysroot_native, self.qemu_ip, self.gdbserver_port, self.binary) | ||
| 36 | r = runCmd(cmd, native_sysroot=self.recipe_sysroot_native, **options) | ||
| 37 | if "Connection timed out" not in r.output: | ||
| 38 | break | ||
| 39 | if count == 4: | ||
| 40 | self.assertTrue(False, "gdb unable to connect to gdbserver") | ||
| 41 | |||
| 42 | def run_gdb_client(self): | ||
| 43 | self.run_gdb(native_sysroot=self.recipe_sysroot_native, ignore_status=False) | ||
| 44 | |||
| 45 | def test_gdb_server(self): | ||
| 46 | self.target_dst = "/tmp/" | ||
| 47 | self.source = "test.c" | ||
| 48 | self.binary = "test" | ||
| 49 | self.target_source = self.target_dst + self.source | ||
| 50 | self.target_binary = self.target_dst + self.binary | ||
| 51 | self.gdbserver_port = 2001 | ||
| 52 | |||
| 53 | try: | ||
| 54 | # These aren't the actual IP addresses but testexport class needs something defined | ||
| 55 | features = 'TEST_SERVER_IP = "192.168.7.1"\n' | ||
| 56 | features += 'TEST_TARGET_IP = "192.168.7.2"\n' | ||
| 57 | features += 'EXTRA_IMAGE_FEATURES += "ssh-server-openssh"\n' | ||
| 58 | features += 'CORE_IMAGE_EXTRA_INSTALL += "gdbserver packagegroup-core-buildessential"\n' | ||
| 59 | self.write_config(features) | ||
| 60 | |||
| 61 | self.target_arch = get_bb_var('TARGET_ARCH') | ||
| 62 | self.target_sys = get_bb_var('TARGET_SYS') | ||
| 63 | |||
| 64 | recipe = "gdb-cross-%s" %self.target_arch | ||
| 65 | gdb_cross_bitbake_command = "%s -c addto_recipe_sysroot" %recipe | ||
| 66 | |||
| 67 | bitbake(gdb_cross_bitbake_command) | ||
| 68 | |||
| 69 | self.recipe_sysroot_native = get_bb_var('RECIPE_SYSROOT_NATIVE', recipe) | ||
| 70 | |||
| 71 | bitbake('core-image-minimal') | ||
| 72 | |||
| 73 | self.cross_gdb_name = "%s-gdb" %self.target_sys | ||
| 74 | |||
| 75 | # wrap the execution with a qemu instance | ||
| 76 | with runqemu("core-image-minimal", runqemuparams = "nographic") as qemu: | ||
| 77 | status, target_gcc = qemu.run_serial("which gcc") | ||
| 78 | |||
| 79 | self.assertNotEqual(target_gcc, None, 'gcc not found on the target') | ||
| 80 | |||
| 81 | self.qemu_ip = qemu.ip | ||
| 82 | |||
| 83 | # self.tc.files_dir = meta/lib/oeqa/files | ||
| 84 | src = os.path.join(self.tc.files_dir, 'test.c') | ||
| 85 | |||
| 86 | self.logger.debug("src : %s qemu.ip : %s self.target_dst : %s" % (src , self.qemu_ip , self.target_dst)) | ||
| 87 | cmd = "scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR %s root@%s:%s" % (src, qemu.ip, self.target_dst) | ||
| 88 | result = runCmd(cmd) | ||
| 89 | |||
| 90 | cmd = "cat %s" %(self.target_source) | ||
| 91 | status, output = qemu.run_serial(cmd) | ||
| 92 | self.assertIn("1234", output, "Source file copied to target is different that what is expected") | ||
| 93 | |||
| 94 | cmd = "%s %s -o %s -lm -g" % (target_gcc, self.target_source, self.target_binary) | ||
| 95 | status, output = qemu.run_serial(cmd) | ||
| 96 | |||
| 97 | cmd = "ls %s" %self.target_binary | ||
| 98 | status, output = qemu.run_serial(cmd) | ||
| 99 | self.assertNotIn("No such file or directory", output, "Test file compilation failed on target") | ||
| 100 | |||
| 101 | status, output = qemu.run_serial(self.target_binary) | ||
| 102 | self.assertIn("1234", output, "Test binary is different than what is expected") | ||
| 103 | |||
| 104 | cmd = "scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR root@%s:%s %s" % (qemu.ip, self.target_binary, os.getcwd()) | ||
| 105 | result = runCmd(cmd) | ||
| 106 | |||
| 107 | cmd = "strip -s --strip-debug %s" %self.target_binary | ||
| 108 | status, output = qemu.run_serial(cmd) | ||
| 109 | |||
| 110 | gdb_client_thread = threading.Thread(target=self.run_gdb_client) | ||
| 111 | gdb_client_thread.start() | ||
| 112 | |||
| 113 | cmd = "gdbserver localhost:%s %s" %(self.gdbserver_port, self.target_binary) | ||
| 114 | status, output = qemu.run_serial(cmd) | ||
| 115 | self.logger.debug("gdbserver status : %s output : %s" % (status, output)) | ||
| 116 | |||
| 117 | gdb_client_thread.join() | ||
| 118 | self.assertIn("1234", output, "Expected string (1234) not present in test output") | ||
| 119 | |||
| 120 | except OEQATimeoutError: | ||
| 121 | self.fail("gdbserver test timeout error") | ||
| 122 | |||
