stackdepot.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. # SPDX-License-Identifier: GPL-2.0
  2. #
  3. # Copyright (c) 2023 MediaTek Inc.
  4. #
  5. # Authors:
  6. # Kuan-Ying Lee <Kuan-Ying.Lee@mediatek.com>
  7. #
  8. import gdb
  9. from linux import utils, constants
  10. if constants.LX_CONFIG_STACKDEPOT:
  11. stack_record_type = utils.CachedType('struct stack_record')
  12. DEPOT_STACK_ALIGN = 4
  13. def help():
  14. t = """Usage: lx-stack_depot_lookup [Hex handle value]
  15. Example:
  16. lx-stack_depot_lookup 0x00c80300\n"""
  17. gdb.write("Unrecognized command\n")
  18. raise gdb.GdbError(t)
  19. def stack_depot_fetch(handle):
  20. global DEPOT_STACK_ALIGN
  21. global stack_record_type
  22. stack_depot_disabled = gdb.parse_and_eval('stack_depot_disabled')
  23. if stack_depot_disabled:
  24. raise gdb.GdbError("stack_depot_disabled\n")
  25. handle_parts_t = gdb.lookup_type("union handle_parts")
  26. parts = handle.cast(handle_parts_t)
  27. offset = parts['offset'] << DEPOT_STACK_ALIGN
  28. pools_num = gdb.parse_and_eval('pools_num')
  29. if handle == 0:
  30. raise gdb.GdbError("handle is 0\n")
  31. pool_index = parts['pool_index_plus_1'] - 1
  32. if pool_index >= pools_num:
  33. gdb.write("pool index %d out of bounds (%d) for stack id 0x%08x\n" % (parts['pool_index'], pools_num, handle))
  34. return gdb.Value(0), 0
  35. stack_pools = gdb.parse_and_eval('stack_pools')
  36. try:
  37. pool = stack_pools[pool_index]
  38. stack = (pool + gdb.Value(offset).cast(utils.get_size_t_type())).cast(stack_record_type.get_type().pointer())
  39. size = int(stack['size'].cast(utils.get_ulong_type()))
  40. return stack['entries'], size
  41. except Exception as e:
  42. gdb.write("%s\n" % e)
  43. return gdb.Value(0), 0
  44. def stack_depot_print(handle):
  45. if not constants.LX_CONFIG_STACKDEPOT:
  46. raise gdb.GdbError("CONFIG_STACKDEPOT is not enabled")
  47. entries, nr_entries = stack_depot_fetch(handle)
  48. if nr_entries > 0:
  49. for i in range(0, nr_entries):
  50. try:
  51. gdb.execute("x /i 0x%x" % (int(entries[i])))
  52. except Exception as e:
  53. gdb.write("%s\n" % e)
  54. class StackDepotLookup(gdb.Command):
  55. """Search backtrace by handle"""
  56. def __init__(self):
  57. if constants.LX_CONFIG_STACKDEPOT:
  58. super(StackDepotLookup, self).__init__("lx-stack_depot_lookup", gdb.COMMAND_SUPPORT)
  59. def invoke(self, args, from_tty):
  60. if not constants.LX_CONFIG_STACKDEPOT:
  61. raise gdb.GdbError('CONFIG_STACKDEPOT is not set')
  62. argv = gdb.string_to_argv(args)
  63. if len(argv) == 1:
  64. handle = int(argv[0], 16)
  65. stack_depot_print(gdb.Value(handle).cast(utils.get_uint_type()))
  66. else:
  67. help()
  68. StackDepotLookup()