mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
Merge pull request #31 from daniel-k/pr/gdb_hermit_awareness
gdb-scripts: add convenience scripts to investigate kernel internals
This commit is contained in:
commit
ebc0930501
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