mirror of https://gitlab.com/nakst/essence
use KDeviceSendConnectedMessage for graphics targets; upload helpful commands for gdb
This commit is contained in:
parent
ea8b6cbd13
commit
0edeb4b6cc
|
@ -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) {
|
||||||
|
|
|
@ -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: */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue