use KDeviceSendConnectedMessage for graphics targets; upload helpful commands for gdb

This commit is contained in:
nakst 2022-01-01 21:15:37 +00:00
parent ea8b6cbd13
commit 0edeb4b6cc
5 changed files with 171 additions and 16 deletions

View File

@ -3116,6 +3116,12 @@ void DesktopSendMessage(EsMessage *message) {
+ EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("clock_offset_ms"), 0); + EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("clock_offset_ms"), 0);
EsEventSet(desktop.clockReadyEvent); EsEventSet(desktop.clockReadyEvent);
} }
} else if (message->device.type == ES_DEVICE_GRAPHICS_TARGET) {
if (desktop.setupDesktopUIComplete) {
DesktopSetup(); // Refresh desktop UI.
} else {
// The screen resolution will be correctly queried in DesktopSetup.
}
} }
} else if (message->type == ES_MSG_UNREGISTER_FILE_SYSTEM || message->type == ES_MSG_DEVICE_DISCONNECTED) { } else if (message->type == ES_MSG_UNREGISTER_FILE_SYSTEM || message->type == ES_MSG_DEVICE_DISCONNECTED) {
for (uintptr_t i = 0; i < desktop.allApplicationProcesses.Length(); i++) { for (uintptr_t i = 0; i < desktop.allApplicationProcesses.Length(); i++) {
@ -3137,12 +3143,6 @@ void DesktopSendMessage(EsMessage *message) {
EsMessagePostRemote(process->handle, message); EsMessagePostRemote(process->handle, message);
} }
} else if (message->type == ES_MSG_SET_SCREEN_RESOLUTION) {
if (desktop.setupDesktopUIComplete) {
DesktopSetup(); // Refresh desktop UI.
} else {
// The screen resolution will be correctly queried in DesktopSetup.
}
} else if (message->type == ES_MSG_KEY_DOWN) { } else if (message->type == ES_MSG_KEY_DOWN) {
ProcessGlobalKeyboardShortcuts(nullptr, message); ProcessGlobalKeyboardShortcuts(nullptr, message);
} else if (message->type == MSG_SETUP_DESKTOP_UI || message->type == ES_MSG_UI_SCALE_CHANGED) { } else if (message->type == MSG_SETUP_DESKTOP_UI || message->type == ES_MSG_UI_SCALE_CHANGED) {

View File

@ -399,7 +399,6 @@ extern "C" void *EsBufferWrite(EsBuffer *buffer, const void *source, size_t writ
/* Desktop messages: */ /* Desktop messages: */
#define ES_MSG_EMBEDDED_WINDOW_DESTROYED ((EsMessageType) (ES_MSG_SYSTEM_START + 0x001)) #define ES_MSG_EMBEDDED_WINDOW_DESTROYED ((EsMessageType) (ES_MSG_SYSTEM_START + 0x001))
#define ES_MSG_SET_SCREEN_RESOLUTION ((EsMessageType) (ES_MSG_SYSTEM_START + 0x002))
#define ES_MSG_DESKTOP ((EsMessageType) (ES_MSG_SYSTEM_START + 0x005)) #define ES_MSG_DESKTOP ((EsMessageType) (ES_MSG_SYSTEM_START + 0x005))
/* Messages sent from Desktop to application instances: */ /* Messages sent from Desktop to application instances: */

View File

@ -3,3 +3,149 @@
This file has not been written yet. `Notes from Discord.txt` may contain a few unorganized pointers, though. This file has not been written yet. `Notes from Discord.txt` may contain a few unorganized pointers, though.
TODO 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

View File

@ -355,3 +355,13 @@ nakst
Today at 8:57 AM Today at 8:57 AM
[gs:0] points to the CPULocalStorage, [gs:8] contains the address of the kernel stack (so it can be switched to in a syscall), [gs:16] points to the current thread [gs:0] points to the CPULocalStorage, [gs:8] contains the address of the kernel stack (so it can be switched to in a syscall), [gs:16] points to the current thread
You can't get the thread from the CPULocalStorage in most situations (i.e. with interrupts enabled), because it will change if the thread is rescheduled on a different CPU, and then you'd read the wrong thread You can't get the thread from the CPULocalStorage in most situations (i.e. with interrupts enabled), because it will change if the thread is rescheduled on a different CPU, and then you'd read the wrong thread
= Format specifiers for EsStringFormat/EsPrint/EsPanic/KernelPanic/KernelLog =
%d formats a long
%i formats a int
%x formats a uintptr_t
%c formats a char
%z formats a zero-terminated const char *
%s formats a non-zero-terminated string; pass the length ptrdiff_t first, then the pointer to base of the string const char *
%F formats a double

View File

@ -30,6 +30,7 @@ struct Graphics {
Surface frameBuffer; Surface frameBuffer;
bool debuggerActive; bool debuggerActive;
size_t totalSurfaceBytes; size_t totalSurfaceBytes;
KMutex registerFirstGraphicsTargetMutex;
}; };
void GraphicsUpdateScreen(K_USER_BUFFER void *bits = nullptr, EsRectangle *bounds = nullptr, uintptr_t stride = 0); void GraphicsUpdateScreen(K_USER_BUFFER void *bits = nullptr, EsRectangle *bounds = nullptr, uintptr_t stride = 0);
@ -102,14 +103,17 @@ bool KGraphicsIsTargetRegistered() {
} }
void KRegisterGraphicsTarget(KGraphicsTarget *target) { void KRegisterGraphicsTarget(KGraphicsTarget *target) {
// TODO Locking. // TODO Multi-monitor support.
if (graphics.target) return;
graphics.target = target; KMutexAcquire(&graphics.registerFirstGraphicsTargetMutex);
bool isFirst = graphics.target == nullptr;
if (isFirst) graphics.target = target;
KMutexRelease(&graphics.registerFirstGraphicsTargetMutex);
if (!isFirst) return;
KDeviceOpenHandle(target);
graphics.width = target->screenWidth; graphics.width = target->screenWidth;
graphics.height = target->screenHeight; graphics.height = target->screenHeight;
graphics.frameBuffer.Resize(graphics.width, graphics.height); graphics.frameBuffer.Resize(graphics.width, graphics.height);
#ifdef START_DEBUG_OUTPUT #ifdef START_DEBUG_OUTPUT
@ -117,11 +121,7 @@ void KRegisterGraphicsTarget(KGraphicsTarget *target) {
EsPrint("Hello\n"); EsPrint("Hello\n");
#else #else
windowManager.Initialise(); windowManager.Initialise();
KDeviceSendConnectedMessage(target, ES_DEVICE_GRAPHICS_TARGET);
_EsMessageWithObject m;
EsMemoryZero(&m, sizeof(m));
m.message.type = ES_MSG_SET_SCREEN_RESOLUTION;
DesktopSendMessage(&m);
#endif #endif
} }