run-gdb 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #!/usr/bin/env python3
  2. import os
  3. import shlex
  4. import sys
  5. import signal
  6. import subprocess
  7. import common
  8. defaults = {
  9. 'after': '',
  10. 'before': '',
  11. 'break_at': None,
  12. 'kgdb': False,
  13. 'no_continue': False,
  14. 'no_lxsymbols': False,
  15. 'sim': False,
  16. 'userland': None,
  17. }
  18. def main(args, extra_args=None):
  19. '''
  20. :param args: argparse parse_argument() output. Must contain all the common options,
  21. but does not need GDB specific ones.
  22. :type args: argparse.Namespace
  23. :param extra_args: extra arguments to be added to args
  24. :type extra_args: Dict[str,Any]
  25. :return: GDB exit status
  26. :rtype: int
  27. '''
  28. global defaults
  29. args = common.resolve_args(defaults, args, extra_args)
  30. after = shlex.split(args.after)
  31. before = shlex.split(args.before)
  32. if args.break_at is not None:
  33. break_at = ['-ex', 'break {}'.format(args.break_at)]
  34. else:
  35. break_at = []
  36. linux_full_system = (args.baremetal is None and args.userland is None)
  37. if args.userland:
  38. image = common.resolve_userland(args.userland)
  39. elif args.baremetal:
  40. image = args.baremetal
  41. else:
  42. image = common.vmlinux
  43. if args.baremetal:
  44. allowed_toolchains = ['crosstool-ng', 'buildroot', 'host']
  45. else:
  46. allowed_toolchains = ['buildroot', 'crosstool-ng', 'host']
  47. cmd = (
  48. [common.get_toolchain_tool('gdb', allowed_toolchains=allowed_toolchains)] +
  49. before +
  50. ['-q']
  51. )
  52. if linux_full_system:
  53. cmd.extend(['-ex', 'add-auto-load-safe-path {}'.format(common.linux_build_dir)])
  54. if args.sim:
  55. target = 'sim'
  56. else:
  57. if args.kgdb:
  58. port = common.extra_serial_port
  59. else:
  60. port = common.gdb_port
  61. target = 'remote localhost:{}'.format(port)
  62. cmd.extend([
  63. '-ex', 'file {}'.format(image),
  64. '-ex', 'target {}'.format(target),
  65. ])
  66. if not args.kgdb:
  67. cmd.extend(break_at)
  68. if not args.no_continue:
  69. # ## lx-symbols
  70. #
  71. # ### lx-symbols after continue
  72. #
  73. # lx symbols must be run after continue.
  74. #
  75. # running it immediately after the connect on the bootloader leads to failure,
  76. # likely because kernel structure on which it depends are not yet available.
  77. #
  78. # With this setup, continue runs, and lx-symbols only runs when a break happens,
  79. # either by hitting the breakpoint, or by entering Ctrl + C.
  80. #
  81. # Sure, if the user sets a break on a raw address of the bootloader,
  82. # problems will still arise, but let's think about that some other time.
  83. #
  84. # ### lx-symbols autoload
  85. #
  86. # The lx-symbols commands gets loaded through the file vmlinux-gdb.py
  87. # which gets put on the kernel build root when python debugging scripts are enabled.
  88. cmd.extend(['-ex', 'continue'])
  89. if not args.no_lxsymbols and linux_full_system:
  90. cmd.extend(['-ex', 'lx-symbols {}'.format(common.kernel_modules_build_subdir)])
  91. cmd.extend(after)
  92. # I would rather have cwd be out_rootfs_overlay_dir,
  93. # but then lx-symbols cannot fine the vmlinux and fails with:
  94. # vmlinux: No such file or directory.
  95. return common.run_cmd(
  96. cmd,
  97. cmd_file=os.path.join(common.run_dir, 'run-gdb.sh'),
  98. cwd=common.linux_build_dir
  99. )
  100. if __name__ == '__main__':
  101. parser = common.get_argparse(argparse_args={'description': 'Connect with GDB to an emulator to debug Linux itself'})
  102. parser.add_argument(
  103. '-A', '--after', default=defaults['after'],
  104. help='Pass extra arguments to GDB, to be appended after all other arguments'
  105. )
  106. parser.add_argument(
  107. '--before', default=defaults['before'],
  108. help='Pass extra arguments to GDB to be prepended before any of the arguments passed by this script'
  109. )
  110. parser.add_argument(
  111. '-C', '--no-continue', default=defaults['no_continue'], action='store_true',
  112. help="Don't run continue after connecting"
  113. )
  114. parser.add_argument(
  115. '-k', '--kgdb', default=defaults['kgdb'], action='store_true'
  116. )
  117. parser.add_argument(
  118. '--sim', default=defaults['sim'], action='store_true',
  119. help='''Use the built-in GDB CPU simulator
  120. See: https://github.com/cirosantilli/linux-kernel-module-cheat#gdb-builtin-cpu-simulator
  121. '''
  122. )
  123. parser.add_argument(
  124. '-X', '--no-lxsymbols', default=defaults['no_lxsymbols'], action='store_true'
  125. )
  126. parser.add_argument(
  127. '--userland', default=defaults['userland'],
  128. )
  129. parser.add_argument(
  130. 'break_at', nargs='?',
  131. help='Extra options to append at the end of the emulator command line'
  132. )
  133. args = common.setup(parser)
  134. sys.exit(main(args))