mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
gdb-scripts: add convenience scripts to investigate kernel internals
These scripts are based on those from the Linux kernel and currently can only show the state of HermitCore tasks.
This commit is contained in:
parent
5e9f932869
commit
d46b8b49f8
4 changed files with 234 additions and 0 deletions
59
hermit/usr/gdb/README.md
Normal file
59
hermit/usr/gdb/README.md
Normal file
|
@ -0,0 +1,59 @@
|
|||
GDB-scripts for HermitCore awareness
|
||||
====================================
|
||||
|
||||
The scripts located in this folder can be used when debugging HermitCore
|
||||
applications to gain more insight into kernel internals.
|
||||
|
||||
To use the scripts you have to load them from inside GDB:
|
||||
|
||||
```
|
||||
(gdb) source ../gdb/hermit-gdb.py
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
Show state of all tasks:
|
||||
|
||||
```
|
||||
(gdb) hermit-ps
|
||||
ID | STATE | CPU | PRIO | STACK | INSTRUCTION POINTER
|
||||
--------------------------------------------------------------------
|
||||
0 | IDL | 0 | 0 | 0x87f000 | 0x81108c <rollback>
|
||||
1 | IDL | 1 | 0 | 0x881000 | 0x81108c <rollback>
|
||||
2 | BLK | 0 | 8 | 0xd6000 | 0x81108c <rollback>
|
||||
3 | BLK | 0 | 16 | 0xf8000 | 0x81108c <rollback>
|
||||
4 | RUN | 1 | 8 | 0x10e000 | 0x981ee8 <thread_func1+40>
|
||||
5 | RUN | 0 | 8 | 0x124000 | 0x981e98 <thread_func2+40>
|
||||
```
|
||||
|
||||
Investigate state of specific task:
|
||||
|
||||
```
|
||||
(gdb) print $hermit_task_by_id(2)
|
||||
$1 = {id = 2, status = 3, last_core = 0, last_stack_pointer = 0x107e60, stack = 0xf8000, ist_addr = 0xe7000, flags = 0 '\000',
|
||||
prio = 16 '\020', timeout = 883, start_tick = 207, heap = 0x0, parent = 0, next = 0x0, prev = 0x0, tls_addr = 12204928,
|
||||
tls_size = 24, lwip_err = 0, signal_handler = 0x0, fpu = {fsave = {cwd = 0, swd = 0, twd = 0, fip = 0, fcs = 0, foo = 0, fos = 0,
|
||||
st_space = {0 <repeats 20 times>}, status = 0}, fxsave = {cwd = 0, swd = 0, twd = 0, fop = 0, {{rip = 0, rdp = 0}, {fip = 0,
|
||||
fcs = 0, foo = 0, fos = 0}}, mxcsr = 0, mxcsr_mask = 0, st_space = {0 <repeats 32 times>}, xmm_space = {
|
||||
0 <repeats 64 times>}, padding = {0 <repeats 12 times>}, {padding1 = {0 <repeats 12 times>}, sw_reserved = {
|
||||
0 <repeats 12 times>}}}, xsave = {fxsave = {cwd = 0, swd = 0, twd = 0, fop = 0, {{rip = 0, rdp = 0}, {fip = 0, fcs = 0,
|
||||
foo = 0, fos = 0}}, mxcsr = 0, mxcsr_mask = 0, st_space = {0 <repeats 32 times>}, xmm_space = {0 <repeats 64 times>},
|
||||
padding = {0 <repeats 12 times>}, {padding1 = {0 <repeats 12 times>}, sw_reserved = {0 <repeats 12 times>}}}, hdr = {
|
||||
xstate_bv = 0, xcomp_bv = 0, reserved = {0, 0, 0, 0, 0, 0}}, ymmh = {ymmh_space = {0 <repeats 64 times>}}}}}
|
||||
```
|
||||
|
||||
Show registered signal handlers (by `hermit_signal(signal_handler_t handler)`).
|
||||
Note that these are not signal handlers registered by newlib
|
||||
(`signal(int sig, _sig_func_ptr func)`).
|
||||
|
||||
```
|
||||
(gdb) hermit-ls-sighandler
|
||||
ID | Signal Handler
|
||||
------------------------------
|
||||
0 | 0x0
|
||||
1 | 0x0
|
||||
2 | 0x989660 <signal_dispatcher>
|
||||
3 | 0x0
|
||||
4 | 0x989660 <signal_dispatcher>
|
||||
5 | 0x989660 <signal_dispatcher>
|
||||
```
|
25
hermit/usr/gdb/hermit-gdb.py
Normal file
25
hermit/usr/gdb/hermit-gdb.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
#
|
||||
# gdb helper commands and functions for Linux kernel debugging
|
||||
#
|
||||
# loader module
|
||||
#
|
||||
# Copyright (c) Siemens AG, 2012, 2013
|
||||
#
|
||||
# Authors:
|
||||
# Jan Kiszka <jan.kiszka@siemens.com>
|
||||
#
|
||||
# This work is licensed under the terms of the GNU GPL version 2.
|
||||
#
|
||||
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
|
||||
try:
|
||||
gdb.parse_and_eval("0")
|
||||
gdb.execute("", to_string=True)
|
||||
except:
|
||||
gdb.write("NOTE: gdb 7.2 or later required for Linux helper scripts to "
|
||||
"work.\n")
|
||||
else:
|
||||
import hermit.tasks
|
1
hermit/usr/gdb/hermit/__init__.py
Normal file
1
hermit/usr/gdb/hermit/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
# nothing to do for the initialization of this package
|
149
hermit/usr/gdb/hermit/tasks.py
Normal file
149
hermit/usr/gdb/hermit/tasks.py
Normal file
|
@ -0,0 +1,149 @@
|
|||
#
|
||||
# gdb helper commands and functions for HermitCore debugging
|
||||
#
|
||||
# task & thread tools
|
||||
#
|
||||
# Copyright (c) Siemens AG, 2011-2013
|
||||
# Copyright (c) RWTH-Aaachen, 2016
|
||||
#
|
||||
# Authors:
|
||||
# Jan Kiszka <jan.kiszka@siemens.com>
|
||||
# Daniel Krebs <github@daniel-krebs.net>
|
||||
#
|
||||
# Inspired by prior work of Jan Kiszka and adapted by Daniel Krebs
|
||||
# for HermitCore.
|
||||
#
|
||||
# This work is licensed under the terms of the GNU GPL version 2.
|
||||
#
|
||||
|
||||
import gdb
|
||||
|
||||
|
||||
def task_lists():
|
||||
task_table = gdb.parse_and_eval("task_table")
|
||||
|
||||
for i in range(task_table.type.range()[1]):
|
||||
task = task_table[i]
|
||||
if task['status'] != 0:
|
||||
yield task
|
||||
|
||||
def get_task_by_pid(pid):
|
||||
for task in task_lists():
|
||||
if int(task['id']) == pid:
|
||||
return task
|
||||
return None
|
||||
|
||||
|
||||
class HermitTaskByIdFunc(gdb.Function):
|
||||
"""Find HermitCore task by ID and return the task_t variable.
|
||||
|
||||
$hermit_task_by_pid(ID): Given ID, iterate over all tasks of the target and
|
||||
return that task_t variable which PI matches."""
|
||||
|
||||
def __init__(self):
|
||||
super(HermitTaskByIdFunc, self).__init__("hermit_task_by_id")
|
||||
|
||||
def invoke(self, pid):
|
||||
task = get_task_by_pid(pid)
|
||||
if task:
|
||||
return task
|
||||
else:
|
||||
raise gdb.GdbError("No task with ID " + str(pid))
|
||||
|
||||
|
||||
HermitTaskByIdFunc()
|
||||
|
||||
def addressToSymbol(addr):
|
||||
s = gdb.execute("info symbol 0x%x" % addr, to_string=True)
|
||||
if 'No symbol matches' in s:
|
||||
return ''
|
||||
else:
|
||||
return s.split(' in')[0].replace(' ', '')
|
||||
|
||||
class HermitPs(gdb.Command):
|
||||
"""Dump Hermit tasks."""
|
||||
|
||||
def __init__(self):
|
||||
super(HermitPs, self).__init__("hermit-ps", gdb.COMMAND_DATA)
|
||||
|
||||
def invoke(self, arg, from_tty):
|
||||
# see include/hermit/task_types.h
|
||||
status_desc = {1: 'RDY', 2: 'RUN', 3: 'BLK', 4: 'FIN', 5: 'IDL'}
|
||||
|
||||
rowfmt = "{id:>3} | {status:^5} | {last_core:>3} | {prio:>4} | {stack:>10} | {rip:<28}\n"
|
||||
|
||||
header = rowfmt.format(id='ID', status='STATE', last_core='CPU',
|
||||
prio='PRIO', stack='STACK',
|
||||
rip='INSTRUCTION POINTER')
|
||||
|
||||
gdb.write(header)
|
||||
gdb.write((len(header) - 1) * '-' + '\n')
|
||||
|
||||
inferior = gdb.selected_inferior()
|
||||
currentInferiorThread = gdb.selected_thread()
|
||||
|
||||
for task in task_lists():
|
||||
|
||||
task_status = status_desc[int(task["status"])]
|
||||
|
||||
if task_status == 'RUN':
|
||||
# switch to inferior thread (cpu) that this task is running on
|
||||
for inferiorThread in inferior.threads():
|
||||
# GDB starts indexing at 1
|
||||
coreId = inferiorThread.num - 1
|
||||
if coreId == task['last_core']:
|
||||
inferiorThread.switch()
|
||||
break
|
||||
|
||||
# get instruction pointer and switch back
|
||||
rip = str(gdb.parse_and_eval('$pc'))
|
||||
currentInferiorThread.switch()
|
||||
|
||||
else:
|
||||
# find instruction pointer in saved stack
|
||||
rip_addr = task['last_stack_pointer'] + 20
|
||||
rip_val = int(rip_addr.dereference())
|
||||
# try to resolve a symbol
|
||||
rip_sym = addressToSymbol(rip_val)
|
||||
rip = "0x%x" % rip_val
|
||||
if rip_sym:
|
||||
rip += " <%s>" % rip_sym
|
||||
|
||||
gdb.write(rowfmt.format(
|
||||
id=int(task["id"]),
|
||||
status=task_status,
|
||||
rip=str(rip),
|
||||
prio=int(task['prio']),
|
||||
last_core=int(task['last_core']),
|
||||
stack="{:#x}".format(int(task['stack']))
|
||||
))
|
||||
|
||||
HermitPs()
|
||||
|
||||
|
||||
class HermitLsSighandler(gdb.Command):
|
||||
"""List signal handlers per tasks."""
|
||||
|
||||
def __init__(self):
|
||||
super(HermitLsSighandler, self).__init__("hermit-ls-sighandler", gdb.COMMAND_DATA)
|
||||
|
||||
def invoke(self, arg, from_tty):
|
||||
|
||||
rowfmt = "{id:>3} | {signal_handler:<24}\n"
|
||||
|
||||
header = rowfmt.format(id='ID', signal_handler='Signal Handler')
|
||||
|
||||
gdb.write(header)
|
||||
gdb.write((len(header) - 1) * '-' + '\n')
|
||||
|
||||
inferior = gdb.selected_inferior()
|
||||
currentInferiorThread = gdb.selected_thread()
|
||||
|
||||
for task in task_lists():
|
||||
|
||||
gdb.write(rowfmt.format(
|
||||
id=int(task["id"]),
|
||||
signal_handler=str(task['signal_handler']),
|
||||
))
|
||||
|
||||
HermitLsSighandler()
|
Loading…
Add table
Reference in a new issue