5.1 KiB
Debugging
This file has not been written yet. Notes from Discord.txt
may contain a few unorganized pointers, though.
TODO
GDB commands
Here are various commands for GDB for inspecting kernel state. Put these in your .gdbinit
file if you want to use them. Please note that some of these may be out of date.
The ldcx
command is used to load the RIP, RSP and RBP registers from an InterruptContext
.
define ldcx
set $new_rip = context->rip
set $new_rsp = context->rsp
set $new_rbp = context->rbp
set $rip = $new_rip
set $rsp = $new_rsp
set $rbp = $new_rbp
set $rip = $new_rip
end
define ldcx32
set $new_eip = context->eip
set $new_esp = context->esp
set $new_ebp = context->ebp
set $eip = $new_eip
set $esp = $new_esp
set $ebp = $new_ebp
set $eip = $new_eip
end
The print_page_list
command follows and prints a linked list from the physical memory manager's page frame database.
define print_page_list
set $index = $arg0
while $index
set $page_frame = pmm.pageFrames[$index]
p $index
p $page_frame
set $index = $page_frame.list.next
end
end
Here are some Python commands. PrintKernelMMSpaceRegions
prints the memory regions in the kernel's memory space. PrintDeviceTree
prints all devices in the kernel's device tree, including the number of open reference to each device. PrintBootFileSystemNodes
prints all the loaded nodes in the boot filesystem ("0:/"). PrintCachedNodes
prints all the nodes that are in cached but have no open references. This also installs hooks for the gf GDB frontend watch window for EsRectangle
and Array<T>
.
py
def EsRectangleHook(item, field):
if field:
if field == '[width]': return gdb.Value(int(item['r']) - item['l'])
if field == '[height]': return gdb.Value(int(item['b']) - item['t'])
else:
print('[width]')
print('[height]')
_gf_fields_recurse(item)
def EsArrayHook(item, field):
if field:
return item['array'][int(field[1:-1])]
else:
print('(d_arr)',ArrayLength(item['array']))
def ArrayLength(arrayBase):
if int(arrayBase):
return int(gdb.parse_and_eval('(_ArrayHeader*)' + str(int(arrayBase)) + '-1')['length'])
return 0
def PrintAVLKey(key, end='\n'):
charPointer = gdb.lookup_type('char').pointer()
nameBytes = int(key['longKeyBytes'])
name = key['longKey'].cast(charPointer)
print(name.string('utf-8', 'strict', nameBytes), end=end)
def PrintNodePath(node, end='\n'):
if isinstance(node, str):
node = gdb.parse_and_eval(node)
parent = node['directoryEntry']['parent']
if int(parent):
PrintNodePath(parent, end='/')
key = node['directoryEntry']['item']['key']
PrintAVLKey(key, end)
def PrintCachedNodes():
item = gdb.parse_and_eval('fs.cachedNodes.firstItem')
offset = int(gdb.parse_and_eval('(uintptr_t)(&((KNode*)0)->cacheItem)-(uintptr_t)((KNode*)0)'))
while int(item):
node = gdb.parse_and_eval('(KNode*)' + str(int(item) - offset))
PrintNodePath(node)
item = item['nextItem']
def PrintDirectoryEntryAndChildren(directoryEntry, indent=''):
if isinstance(directoryEntry, str):
directoryEntry = gdb.parse_and_eval(directoryEntry)
print('"', end='')
PrintAVLKey(directoryEntry['item']['key'], end='"')
node = directoryEntry['node']
recurse = None
if int(node):
print(', node H' + str(int(node['handles'])), end='')
if int(directoryEntry['type']) == 0x10:
print(', dir', end='')
fsDirectory = node.cast(gdb.lookup_type('FSDirectory').pointer())
recurse = fsDirectory['entries']['root']
print('')
if recurse:
RecurseIntoNodeAVLTree(recurse, indent + '\t')
def RecurseIntoNodeAVLTree(item, indent):
if not int(item):
return
RecurseIntoNodeAVLTree(item['children'][0], indent)
RecurseIntoNodeAVLTree(item['children'][1], indent)
print(indent, end='')
PrintDirectoryEntryAndChildren(item['thisItem'], indent)
def PrintBootFileSystemNodes():
PrintDirectoryEntryAndChildren('fs.bootFileSystem.rootDirectory.directoryEntry')
def RecurseIntoDeviceTree(device, indent):
print(indent, device['cDebugName'].string('utf-8'), device['handles'])
childCount = ArrayLength(device['children']['array'])
for i in range(childCount):
RecurseIntoDeviceTree(device['children']['array'][i], indent + ' | ')
def PrintDeviceTree():
RecurseIntoDeviceTree(gdb.parse_and_eval('deviceTreeRoot'), '')
def PrintMemoryRegion(region):
print('region: ' + hex(int(region)))
print('\tbaseAddress: ' + hex(int(region['baseAddress'])))
print('\tsize: ' + str(4 * int(region['pageCount'])) + ' KB')
flags = int(region['flags'])
print('\tflags: ' + hex(flags))
if flags & 0x200:
print('\tnormal region')
print('\t\tcommit: ' + str(4 * int(region['data']['normal']['commitPageCount'])) + ' KB')
def RecurseIntoMMSpaceAVLTree(item):
if not int(item):
return
RecurseIntoMMSpaceAVLTree(item['children'][0])
RecurseIntoMMSpaceAVLTree(item['children'][1])
PrintMemoryRegion(item['thisItem'])
def PrintKernelMMSpaceRegions():
RecurseIntoMMSpaceAVLTree(gdb.parse_and_eval('_kernelMMSpace.usedRegions.root'))
gf_hooks = { 'EsRectangle': EsRectangleHook, 'Array': EsArrayHook }
end