mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-28 15:34:33 +00:00
Update kernel
This commit is contained in:
parent
dcdba03426
commit
41db477173
12
.vscode/c_cpp_properties.json
vendored
12
.vscode/c_cpp_properties.json
vendored
@ -18,7 +18,7 @@
|
|||||||
"a86",
|
"a86",
|
||||||
"DEBUG=\"1\""
|
"DEBUG=\"1\""
|
||||||
],
|
],
|
||||||
"compilerPath": "${workspaceFolder}/../tools/cross/bin/amd64-elf-gcc",
|
"compilerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gcc",
|
||||||
"cStandard": "c17",
|
"cStandard": "c17",
|
||||||
"cppStandard": "c++20",
|
"cppStandard": "c++20",
|
||||||
"intelliSenseMode": "gcc-x64",
|
"intelliSenseMode": "gcc-x64",
|
||||||
@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
// C++ flags
|
// C++ flags
|
||||||
"-fno-rtti",
|
"-fno-rtti",
|
||||||
"-fexceptions",
|
"-fno-exceptions",
|
||||||
|
|
||||||
// Linker flags
|
// Linker flags
|
||||||
"-T${workspaceFolder}/Architecture/amd64/linker.ld",
|
"-T${workspaceFolder}/Architecture/amd64/linker.ld",
|
||||||
@ -91,7 +91,7 @@
|
|||||||
"a86",
|
"a86",
|
||||||
"DEBUG=\"1\""
|
"DEBUG=\"1\""
|
||||||
],
|
],
|
||||||
"compilerPath": "${workspaceFolder}/../tools/cross/bin/i386-elf-gcc",
|
"compilerPath": "${workspaceFolder}/../tools/cross/bin/i386-fennix-gcc",
|
||||||
"cStandard": "c17",
|
"cStandard": "c17",
|
||||||
"cppStandard": "c++20",
|
"cppStandard": "c++20",
|
||||||
"intelliSenseMode": "gcc-x86",
|
"intelliSenseMode": "gcc-x86",
|
||||||
@ -123,7 +123,7 @@
|
|||||||
|
|
||||||
// C++ flags
|
// C++ flags
|
||||||
"-fno-rtti",
|
"-fno-rtti",
|
||||||
"-fexceptions",
|
"-fno-exceptions",
|
||||||
|
|
||||||
// Linker flags
|
// Linker flags
|
||||||
"-T${workspaceFolder}/Architecture/i386/linker.ld",
|
"-T${workspaceFolder}/Architecture/i386/linker.ld",
|
||||||
@ -166,7 +166,7 @@
|
|||||||
"aa64",
|
"aa64",
|
||||||
"DEBUG=\"1\""
|
"DEBUG=\"1\""
|
||||||
],
|
],
|
||||||
"compilerPath": "${workspaceFolder}/../tools/cross/bin/aarch64-elf-gcc",
|
"compilerPath": "${workspaceFolder}/../tools/cross/bin/aarch64-fennix-gcc",
|
||||||
"cStandard": "c17",
|
"cStandard": "c17",
|
||||||
"cppStandard": "c++20",
|
"cppStandard": "c++20",
|
||||||
"intelliSenseMode": "linux-gcc-arm64",
|
"intelliSenseMode": "linux-gcc-arm64",
|
||||||
@ -193,7 +193,7 @@
|
|||||||
|
|
||||||
// C++ flags
|
// C++ flags
|
||||||
"-fno-rtti",
|
"-fno-rtti",
|
||||||
"-fexceptions",
|
"-fno-exceptions",
|
||||||
|
|
||||||
// Linker flags
|
// Linker flags
|
||||||
"-T${workspaceFolder}/Architecture/aarch64/linker.ld",
|
"-T${workspaceFolder}/Architecture/aarch64/linker.ld",
|
||||||
|
14
.vscode/extensions.json
vendored
Normal file
14
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"jeff-hykin.better-cpp-syntax",
|
||||||
|
"aaron-bond.better-comments",
|
||||||
|
"ms-vscode.cpptools",
|
||||||
|
"maziac.hex-hover-converter",
|
||||||
|
"zixuanwang.linkerscript",
|
||||||
|
"webfreak.debug",
|
||||||
|
"ibm.output-colorizer",
|
||||||
|
"wayou.vscode-todo-highlight",
|
||||||
|
"gruntfuggly.todo-tree",
|
||||||
|
"13xforever.language-x86-64-assembly"
|
||||||
|
]
|
||||||
|
}
|
51
.vscode/launch.json
vendored
51
.vscode/launch.json
vendored
@ -10,7 +10,42 @@
|
|||||||
"args": [],
|
"args": [],
|
||||||
"targetArchitecture": "x64",
|
"targetArchitecture": "x64",
|
||||||
"MIMode": "gdb",
|
"MIMode": "gdb",
|
||||||
"miDebuggerPath": "/usr/bin/gdb",
|
"miDebuggerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gdb",
|
||||||
|
"miDebuggerArgs": "",
|
||||||
|
"externalConsole": false,
|
||||||
|
"additionalSOLibSearchPath": "${workspaceFolder}",
|
||||||
|
"customLaunchSetupCommands": [
|
||||||
|
{
|
||||||
|
"text": "target remote localhost:1234",
|
||||||
|
"description": "Connect to QEMU remote debugger"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"description": "Enable pretty-printing for gdb",
|
||||||
|
"text": "-enable-pretty-printing",
|
||||||
|
"ignoreFailures": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "set breakpoint pending on",
|
||||||
|
"description": "Make breakpoint pending on future shared library load."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "file ${workspaceFolder}/kernel.fsys",
|
||||||
|
"description": "Load binary."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Attach to VM w/userspace binaries",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/kernel.fsys",
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"args": [],
|
||||||
|
"targetArchitecture": "x64",
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"miDebuggerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gdb",
|
||||||
"miDebuggerArgs": "",
|
"miDebuggerArgs": "",
|
||||||
"externalConsole": false,
|
"externalConsole": false,
|
||||||
"additionalSOLibSearchPath": "${workspaceFolder}",
|
"additionalSOLibSearchPath": "${workspaceFolder}",
|
||||||
@ -34,7 +69,19 @@
|
|||||||
"text": "file ${workspaceFolder}/kernel.fsys",
|
"text": "file ${workspaceFolder}/kernel.fsys",
|
||||||
"description": "Load binary."
|
"description": "Load binary."
|
||||||
},
|
},
|
||||||
]
|
{
|
||||||
|
"text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/bin/init",
|
||||||
|
"description": "Load /bin/init."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/lib/ld.so",
|
||||||
|
"description": "Load /lib/ld.so."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/usr/bin/doom",
|
||||||
|
"description": "Load /usr/bin/doom."
|
||||||
|
},
|
||||||
|
],
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -78,7 +78,7 @@ namespace ACPI
|
|||||||
}
|
}
|
||||||
else if (Event & ACPI_POWER_BUTTON)
|
else if (Event & ACPI_POWER_BUTTON)
|
||||||
{
|
{
|
||||||
if (TaskManager)
|
if (TaskManager && !TaskManager->IsPanic())
|
||||||
{
|
{
|
||||||
TaskManager->CreateThread(TaskManager->CreateProcess(nullptr,
|
TaskManager->CreateThread(TaskManager->CreateProcess(nullptr,
|
||||||
"Shutdown",
|
"Shutdown",
|
||||||
|
@ -29,15 +29,15 @@ namespace Memory
|
|||||||
Address &= 0xFFFFFFFFFFFFF000;
|
Address &= 0xFFFFFFFFFFFFF000;
|
||||||
|
|
||||||
PageMapIndexer Index = PageMapIndexer(Address);
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
|
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||||
|
|
||||||
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
|
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
|
||||||
PageDirectoryEntryPtr *PDE = nullptr;
|
PageDirectoryEntryPtr *PDE = nullptr;
|
||||||
PageTableEntryPtr *PTE = nullptr;
|
PageTableEntryPtr *PTE = nullptr;
|
||||||
|
|
||||||
if ((PML4.raw & Flag) > 0)
|
if ((PML4->raw & Flag) > 0)
|
||||||
{
|
{
|
||||||
PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
|
PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->GetAddress() << 12);
|
||||||
if (PDPTE)
|
if (PDPTE)
|
||||||
{
|
{
|
||||||
if ((PDPTE->Entries[Index.PDPTEIndex].Present))
|
if ((PDPTE->Entries[Index.PDPTEIndex].Present))
|
||||||
@ -74,15 +74,15 @@ namespace Memory
|
|||||||
Address &= 0xFFFFFFFFFFFFF000;
|
Address &= 0xFFFFFFFFFFFFF000;
|
||||||
|
|
||||||
PageMapIndexer Index = PageMapIndexer(Address);
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
|
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||||
|
|
||||||
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
|
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
|
||||||
PageDirectoryEntryPtr *PDE = nullptr;
|
PageDirectoryEntryPtr *PDE = nullptr;
|
||||||
PageTableEntryPtr *PTE = nullptr;
|
PageTableEntryPtr *PTE = nullptr;
|
||||||
|
|
||||||
if (PML4.Present)
|
if (PML4->Present)
|
||||||
{
|
{
|
||||||
PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
|
PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->GetAddress() << 12);
|
||||||
if (PDPTE)
|
if (PDPTE)
|
||||||
{
|
{
|
||||||
if (PDPTE->Entries[Index.PDPTEIndex].Present)
|
if (PDPTE->Entries[Index.PDPTEIndex].Present)
|
||||||
@ -112,6 +112,135 @@ namespace Memory
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Virtual::MapType Virtual::GetMapType(void *VirtualAddress)
|
||||||
|
{
|
||||||
|
// 0x1000 aligned
|
||||||
|
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||||
|
Address &= 0xFFFFFFFFFFFFF000;
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
|
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||||
|
|
||||||
|
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
|
||||||
|
PageDirectoryEntryPtr *PDE = nullptr;
|
||||||
|
PageTableEntryPtr *PTE = nullptr;
|
||||||
|
|
||||||
|
if (PML4->Present)
|
||||||
|
{
|
||||||
|
PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->GetAddress() << 12);
|
||||||
|
if (PDPTE)
|
||||||
|
{
|
||||||
|
if (PDPTE->Entries[Index.PDPTEIndex].Present)
|
||||||
|
{
|
||||||
|
if (PDPTE->Entries[Index.PDPTEIndex].PageSize)
|
||||||
|
return MapType::OneGB;
|
||||||
|
|
||||||
|
PDE = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
|
||||||
|
if (PDE)
|
||||||
|
{
|
||||||
|
if (PDE->Entries[Index.PDEIndex].Present)
|
||||||
|
{
|
||||||
|
if (PDE->Entries[Index.PDEIndex].PageSize)
|
||||||
|
return MapType::TwoMB;
|
||||||
|
|
||||||
|
PTE = (PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12);
|
||||||
|
if (PTE)
|
||||||
|
{
|
||||||
|
if (PTE->Entries[Index.PTEIndex].Present)
|
||||||
|
return MapType::FourKB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MapType::NoMapType;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageMapLevel5 *Virtual::GetPML5(void *VirtualAddress, MapType Type)
|
||||||
|
{
|
||||||
|
stub; /* TODO */
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageMapLevel4 *Virtual::GetPML4(void *VirtualAddress, MapType Type)
|
||||||
|
{
|
||||||
|
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||||
|
Address &= 0xFFFFFFFFFFFFF000;
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
|
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||||
|
if (PML4->Present)
|
||||||
|
return PML4;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageDirectoryPointerTableEntry *Virtual::GetPDPTE(void *VirtualAddress, MapType Type)
|
||||||
|
{
|
||||||
|
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||||
|
Address &= 0xFFFFFFFFFFFFF000;
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
|
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||||
|
if (!PML4->Present)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12);
|
||||||
|
PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex];
|
||||||
|
if (PDPTE->Present)
|
||||||
|
return PDPTE;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageDirectoryEntry *Virtual::GetPDE(void *VirtualAddress, MapType Type)
|
||||||
|
{
|
||||||
|
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||||
|
Address &= 0xFFFFFFFFFFFFF000;
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
|
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||||
|
if (!PML4->Present)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12);
|
||||||
|
PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex];
|
||||||
|
if (!PDPTE->Present)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)(PDPTE->GetAddress() << 12);
|
||||||
|
PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex];
|
||||||
|
if (PDE->Present)
|
||||||
|
return PDE;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageTableEntry *Virtual::GetPTE(void *VirtualAddress, MapType Type)
|
||||||
|
{
|
||||||
|
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||||
|
Address &= 0xFFFFFFFFFFFFF000;
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
|
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||||
|
if (!PML4->Present)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12);
|
||||||
|
PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex];
|
||||||
|
if (!PDPTE->Present)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)(PDPTE->GetAddress() << 12);
|
||||||
|
PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex];
|
||||||
|
if (!PDE->Present)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12);
|
||||||
|
PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex];
|
||||||
|
if (PTE->Present)
|
||||||
|
return PTE;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type)
|
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type)
|
||||||
{
|
{
|
||||||
SmartLock(this->MemoryLock);
|
SmartLock(this->MemoryLock);
|
||||||
@ -234,7 +363,7 @@ namespace Memory
|
|||||||
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||||
if (!PML4->Present)
|
if (!PML4->Present)
|
||||||
{
|
{
|
||||||
error("Page %#lx not present", PML4->GetAddress());
|
warn("Page %#lx not present", PML4->GetAddress());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +371,7 @@ namespace Memory
|
|||||||
PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex];
|
PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex];
|
||||||
if (!PDPTE->Present)
|
if (!PDPTE->Present)
|
||||||
{
|
{
|
||||||
error("Page %#lx not present", PDPTE->GetAddress());
|
warn("Page %#lx not present", PDPTE->GetAddress());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +385,7 @@ namespace Memory
|
|||||||
PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex];
|
PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex];
|
||||||
if (!PDE->Present)
|
if (!PDE->Present)
|
||||||
{
|
{
|
||||||
error("Page %#lx not present", PDE->GetAddress());
|
warn("Page %#lx not present", PDE->GetAddress());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +399,7 @@ namespace Memory
|
|||||||
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
|
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
|
||||||
if (!PTE.Present)
|
if (!PTE.Present)
|
||||||
{
|
{
|
||||||
error("Page %#lx not present", PTE.GetAddress());
|
warn("Page %#lx not present", PTE.GetAddress());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,50 +475,46 @@ namespace InterruptDescriptorTable
|
|||||||
outb(0xA1, 0xff);
|
outb(0xA1, 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ISR */
|
bool EnableISRs = true;
|
||||||
|
#ifdef DEBUG
|
||||||
|
EnableISRs = !DebuggerIsAttached;
|
||||||
|
if (!EnableISRs)
|
||||||
|
KPrint("\eFFA500The debugger is attached, disabling all ISRs.");
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
/* ISR */
|
||||||
// if (!DebuggerIsAttached)
|
SetEntry(0x0, InterruptHandler_0x0, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
if (true)
|
SetEntry(0x1, InterruptHandler_0x1, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
{
|
SetEntry(0x2, InterruptHandler_0x2, IST2, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
#endif
|
|
||||||
SetEntry(0x0, InterruptHandler_0x0, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
|
||||||
SetEntry(0x1, InterruptHandler_0x1, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
|
||||||
SetEntry(0x2, InterruptHandler_0x2, IST2, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
|
||||||
SetEntry(0x3, InterruptHandler_0x3, IST1, TRAP_32BIT, RING3, (!DebuggerIsAttached), GDT_KERNEL_CODE); /* Do not handle breakpoints if we are debugging the kernel. */
|
SetEntry(0x3, InterruptHandler_0x3, IST1, TRAP_32BIT, RING3, (!DebuggerIsAttached), GDT_KERNEL_CODE); /* Do not handle breakpoints if we are debugging the kernel. */
|
||||||
SetEntry(0x4, InterruptHandler_0x4, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x4, InterruptHandler_0x4, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x5, InterruptHandler_0x5, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x5, InterruptHandler_0x5, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x6, InterruptHandler_0x6, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x6, InterruptHandler_0x6, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x7, InterruptHandler_0x7, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x7, InterruptHandler_0x7, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x8, InterruptHandler_0x8, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x8, InterruptHandler_0x8, IST3, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x9, InterruptHandler_0x9, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x9, InterruptHandler_0x9, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0xa, InterruptHandler_0xa, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0xa, InterruptHandler_0xa, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0xb, InterruptHandler_0xb, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0xb, InterruptHandler_0xb, IST1, TRAP_32BIT, RING0, (!DebuggerIsAttached), GDT_KERNEL_CODE);
|
||||||
SetEntry(0xc, InterruptHandler_0xc, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0xc, InterruptHandler_0xc, IST3, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0xd, InterruptHandler_0xd, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0xd, InterruptHandler_0xd, IST3, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0xe, InterruptHandler_0xe, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0xe, InterruptHandler_0xe, IST3, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0xf, InterruptHandler_0xf, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0xf, InterruptHandler_0xf, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x10, InterruptHandler_0x10, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x10, InterruptHandler_0x10, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x11, InterruptHandler_0x11, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x11, InterruptHandler_0x11, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x12, InterruptHandler_0x12, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x12, InterruptHandler_0x12, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x13, InterruptHandler_0x13, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x13, InterruptHandler_0x13, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x14, InterruptHandler_0x14, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x14, InterruptHandler_0x14, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x15, InterruptHandler_0x15, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x15, InterruptHandler_0x15, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x16, InterruptHandler_0x16, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x16, InterruptHandler_0x16, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x17, InterruptHandler_0x17, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x17, InterruptHandler_0x17, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x18, InterruptHandler_0x18, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x18, InterruptHandler_0x18, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x19, InterruptHandler_0x19, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x19, InterruptHandler_0x19, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x1a, InterruptHandler_0x1a, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x1a, InterruptHandler_0x1a, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x1b, InterruptHandler_0x1b, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x1b, InterruptHandler_0x1b, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x1c, InterruptHandler_0x1c, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x1c, InterruptHandler_0x1c, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x1d, InterruptHandler_0x1d, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x1d, InterruptHandler_0x1d, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x1e, InterruptHandler_0x1e, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x1e, InterruptHandler_0x1e, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
SetEntry(0x1f, InterruptHandler_0x1f, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
|
SetEntry(0x1f, InterruptHandler_0x1f, IST1, TRAP_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||||
#ifdef DEBUG
|
|
||||||
}
|
|
||||||
else
|
|
||||||
KPrint("\eFFA500The debugger is attached, not setting up the ISR.");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* IRQ */
|
/* IRQ */
|
||||||
|
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"llvm-target": "x86_64-unknown-none",
|
|
||||||
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
|
|
||||||
"cpu": "x86-64",
|
|
||||||
"arch": "x86_64",
|
|
||||||
"features": "-mmx,-sse,+soft-float",
|
|
||||||
"target-endian": "little",
|
|
||||||
"target-pointer-width": "64",
|
|
||||||
"target-c-int-width": "32",
|
|
||||||
"os": "none",
|
|
||||||
"linker-flavor": "ld",
|
|
||||||
"pre-link-args": {
|
|
||||||
"ld": [
|
|
||||||
"-m64"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"no-compiler-rt": true,
|
|
||||||
"disable-redzone": true,
|
|
||||||
"eliminate-frame-pointer": false,
|
|
||||||
"morestack": false
|
|
||||||
}
|
|
@ -29,15 +29,15 @@ namespace Memory
|
|||||||
Address &= 0xFFFFF000;
|
Address &= 0xFFFFF000;
|
||||||
|
|
||||||
PageMapIndexer Index = PageMapIndexer(Address);
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
PageDirectoryEntry PDE = this->Table->Entries[Index.PDEIndex];
|
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||||
PageTableEntryPtr *PTE = nullptr;
|
PageTableEntryPtr *PTE = nullptr;
|
||||||
|
|
||||||
if ((PDE.raw & Flag) > 0)
|
if ((PDE->raw & Flag) > 0)
|
||||||
{
|
{
|
||||||
if (Type == MapType::FourMB && PDE.PageSize)
|
if (Type == MapType::FourMB && PDE->PageSize)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
PTE = (PageTableEntryPtr *)((uintptr_t)PDE.GetAddress() << 12);
|
PTE = (PageTableEntryPtr *)((uintptr_t)PDE->GetAddress() << 12);
|
||||||
if (PTE)
|
if (PTE)
|
||||||
{
|
{
|
||||||
if ((PTE->Entries[Index.PTEIndex].Present))
|
if ((PTE->Entries[Index.PTEIndex].Present))
|
||||||
@ -54,15 +54,15 @@ namespace Memory
|
|||||||
Address &= 0xFFFFF000;
|
Address &= 0xFFFFF000;
|
||||||
|
|
||||||
PageMapIndexer Index = PageMapIndexer(Address);
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
PageDirectoryEntry PDE = this->Table->Entries[Index.PDEIndex];
|
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||||
PageTableEntryPtr *PTE = nullptr;
|
PageTableEntryPtr *PTE = nullptr;
|
||||||
|
|
||||||
if (PDE.Present)
|
if (PDE->Present)
|
||||||
{
|
{
|
||||||
if (PDE.PageSize)
|
if (PDE->PageSize)
|
||||||
return (void *)((uintptr_t)PDE.GetAddress() << 12);
|
return (void *)((uintptr_t)PDE->GetAddress() << 12);
|
||||||
|
|
||||||
PTE = (PageTableEntryPtr *)((uintptr_t)PDE.GetAddress() << 12);
|
PTE = (PageTableEntryPtr *)((uintptr_t)PDE->GetAddress() << 12);
|
||||||
if (PTE)
|
if (PTE)
|
||||||
{
|
{
|
||||||
if (PTE->Entries[Index.PTEIndex].Present)
|
if (PTE->Entries[Index.PTEIndex].Present)
|
||||||
@ -72,6 +72,61 @@ namespace Memory
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Virtual::MapType Virtual::GetMapType(void *VirtualAddress)
|
||||||
|
{
|
||||||
|
// 0x1000 aligned
|
||||||
|
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||||
|
Address &= 0xFFFFFFFFFFFFF000;
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
|
|
||||||
|
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||||
|
PageTableEntryPtr *PTE = nullptr;
|
||||||
|
|
||||||
|
if (PDE->Present)
|
||||||
|
{
|
||||||
|
if (PDE->PageSize)
|
||||||
|
return MapType::FourMB;
|
||||||
|
|
||||||
|
PTE = (PageTableEntryPtr *)((uintptr_t)PDE->GetAddress() << 12);
|
||||||
|
if (PTE)
|
||||||
|
{
|
||||||
|
if (PTE->Entries[Index.PTEIndex].Present)
|
||||||
|
return MapType::FourKB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MapType::NoMapType;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageDirectoryEntry *Virtual::GetPDE(void *VirtualAddress, MapType Type)
|
||||||
|
{
|
||||||
|
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||||
|
Address &= 0xFFFFFFFFFFFFF000;
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
|
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||||
|
if (PDE->Present)
|
||||||
|
return PDE;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageTableEntry *Virtual::GetPTE(void *VirtualAddress, MapType Type)
|
||||||
|
{
|
||||||
|
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||||
|
Address &= 0xFFFFFFFFFFFFF000;
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
|
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||||
|
if (!PDE->Present)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12);
|
||||||
|
PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex];
|
||||||
|
if (PTE->Present)
|
||||||
|
return PTE;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type)
|
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type)
|
||||||
{
|
{
|
||||||
SmartLock(this->MemoryLock);
|
SmartLock(this->MemoryLock);
|
||||||
@ -159,7 +214,7 @@ namespace Memory
|
|||||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||||
if (!PDE->Present)
|
if (!PDE->Present)
|
||||||
{
|
{
|
||||||
error("Page %#lx not present", PDE->GetAddress());
|
warn("Page %#lx not present", PDE->GetAddress());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,7 +228,7 @@ namespace Memory
|
|||||||
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
|
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
|
||||||
if (!PTE.Present)
|
if (!PTE.Present)
|
||||||
{
|
{
|
||||||
error("Page %#lx not present", PTE.GetAddress());
|
warn("Page %#lx not present", PTE.GetAddress());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,29 +191,29 @@ SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
Memory::Virtual vma = Memory::Virtual(((Memory::PageTable *)CPU::x64::readcr3().raw));
|
Memory::Virtual vmm = Memory::Virtual(((Memory::PageTable *)CPU::x64::readcr3().raw));
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
Memory::Virtual vma = Memory::Virtual(((Memory::PageTable *)CPU::x32::readcr3().raw));
|
Memory::Virtual vmm = Memory::Virtual(((Memory::PageTable *)CPU::x32::readcr3().raw));
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
Memory::Virtual vma = Memory::Virtual();
|
Memory::Virtual vmm = Memory::Virtual();
|
||||||
#warning "TODO: aa64"
|
#warning "TODO: aa64"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool PageAvailable = vma.Check((void *)CheckPageFaultAddress);
|
bool PageAvailable = vmm.Check((void *)CheckPageFaultAddress);
|
||||||
debug("Page available (Check(...)): %s. %s",
|
debug("Page available (Check(...)): %s. %s",
|
||||||
PageAvailable ? "Yes" : "No",
|
PageAvailable ? "Yes" : "No",
|
||||||
(params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result.");
|
(params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result.");
|
||||||
|
|
||||||
if (PageAvailable)
|
if (PageAvailable)
|
||||||
{
|
{
|
||||||
bool Present = vma.Check((void *)CheckPageFaultAddress);
|
bool Present = vmm.Check((void *)CheckPageFaultAddress);
|
||||||
bool ReadWrite = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW);
|
bool ReadWrite = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW);
|
||||||
bool User = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US);
|
bool User = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US);
|
||||||
bool WriteThrough = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT);
|
bool WriteThrough = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT);
|
||||||
bool CacheDisabled = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD);
|
bool CacheDisabled = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD);
|
||||||
bool Accessed = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A);
|
bool Accessed = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A);
|
||||||
bool Dirty = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D);
|
bool Dirty = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D);
|
||||||
bool Global = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G);
|
bool Global = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G);
|
||||||
/* ... */
|
/* ... */
|
||||||
|
|
||||||
debug("Page available: %s", Present ? "Yes" : "No");
|
debug("Page available: %s", Present ? "Yes" : "No");
|
||||||
|
@ -708,12 +708,12 @@ namespace CrashHandler
|
|||||||
uint64_t TotalMemLength = KernelAllocator.GetTotalMemory();
|
uint64_t TotalMemLength = KernelAllocator.GetTotalMemory();
|
||||||
uint64_t ProgressLength = TotalMemLength;
|
uint64_t ProgressLength = TotalMemLength;
|
||||||
UniversalAsynchronousReceiverTransmitter::UART uart(port);
|
UniversalAsynchronousReceiverTransmitter::UART uart(port);
|
||||||
Memory::Virtual vma;
|
Memory::Virtual vmm;
|
||||||
uint8_t *Address = reinterpret_cast<uint8_t *>(0x0);
|
uint8_t *Address = reinterpret_cast<uint8_t *>(0x0);
|
||||||
int Progress = 0;
|
int Progress = 0;
|
||||||
for (size_t i = 0; i < TotalMemLength; i++)
|
for (size_t i = 0; i < TotalMemLength; i++)
|
||||||
{
|
{
|
||||||
if (vma.Check(Address))
|
if (vmm.Check(Address))
|
||||||
uart.Write(*Address);
|
uart.Write(*Address);
|
||||||
else if (cBoolSkip[0] == '0')
|
else if (cBoolSkip[0] == '0')
|
||||||
uart.Write((uint8_t)0);
|
uart.Write((uint8_t)0);
|
||||||
@ -988,9 +988,9 @@ namespace CrashHandler
|
|||||||
asmv("movq %%dr3, %0"
|
asmv("movq %%dr3, %0"
|
||||||
: "=r"(crashdata.dr3));
|
: "=r"(crashdata.dr3));
|
||||||
asmv("movq %%dr6, %0"
|
asmv("movq %%dr6, %0"
|
||||||
: "=r"(crashdata.dr6));
|
: "=r"(crashdata.dr6.raw));
|
||||||
asmv("movq %%dr7, %0"
|
asmv("movq %%dr7, %0"
|
||||||
: "=r"(crashdata.dr7));
|
: "=r"(crashdata.dr7.raw));
|
||||||
|
|
||||||
CPUData *cpudata = GetCurrentCPU();
|
CPUData *cpudata = GetCurrentCPU();
|
||||||
|
|
||||||
@ -1041,7 +1041,7 @@ namespace CrashHandler
|
|||||||
error("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp);
|
error("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp);
|
||||||
error("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, crashdata.efer.raw);
|
error("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, crashdata.efer.raw);
|
||||||
error("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx", crashdata.cr0.raw, crashdata.cr2.raw, crashdata.cr3.raw, crashdata.cr4.raw, crashdata.cr8.raw);
|
error("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx", crashdata.cr0.raw, crashdata.cr2.raw, crashdata.cr3.raw, crashdata.cr4.raw, crashdata.cr8.raw);
|
||||||
error("DR0=%#llx DR1=%#llx DR2=%#llx DR3=%#llx DR6=%#llx DR7=%#llx", crashdata.dr0, crashdata.dr1, crashdata.dr2, crashdata.dr3, crashdata.dr6, crashdata.dr7.raw);
|
error("DR0=%#llx DR1=%#llx DR2=%#llx DR3=%#llx DR6=%#llx DR7=%#llx", crashdata.dr0, crashdata.dr1, crashdata.dr2, crashdata.dr3, crashdata.dr6.raw, crashdata.dr7.raw);
|
||||||
|
|
||||||
error("CR0: PE:%s MP:%s EM:%s TS:%s ET:%s NE:%s WP:%s AM:%s NW:%s CD:%s PG:%s R0:%#x R1:%#x R2:%#x",
|
error("CR0: PE:%s MP:%s EM:%s TS:%s ET:%s NE:%s WP:%s AM:%s NW:%s CD:%s PG:%s R0:%#x R1:%#x R2:%#x",
|
||||||
crashdata.cr0.PE ? "True " : "False", crashdata.cr0.MP ? "True " : "False", crashdata.cr0.EM ? "True " : "False", crashdata.cr0.TS ? "True " : "False",
|
crashdata.cr0.PE ? "True " : "False", crashdata.cr0.MP ? "True " : "False", crashdata.cr0.EM ? "True " : "False", crashdata.cr0.TS ? "True " : "False",
|
||||||
@ -1073,12 +1073,16 @@ namespace CrashHandler
|
|||||||
Frame->rflags.ID ? "True " : "False", Frame->rflags.AlwaysOne,
|
Frame->rflags.ID ? "True " : "False", Frame->rflags.AlwaysOne,
|
||||||
Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3);
|
Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3);
|
||||||
|
|
||||||
error("DR7: LDR0:%s GDR0:%s LDR1:%s GDR1:%s LDR2:%s GDR2:%s LDR3:%s GDR3:%s CDR0:%s SDR0:%s CDR1:%s SDR1:%s CDR2:%s SDR2:%s CDR3:%s SDR3:%s R:%#x",
|
error("DR6: B0:%s B1:%s B2:%s B3:%s BD:%s BS:%s BT:%s",
|
||||||
crashdata.dr7.LocalDR0 ? "True " : "False", crashdata.dr7.GlobalDR0 ? "True " : "False", crashdata.dr7.LocalDR1 ? "True " : "False", crashdata.dr7.GlobalDR1 ? "True " : "False",
|
crashdata.dr6.B0 ? "True " : "False", crashdata.dr6.B1 ? "True " : "False", crashdata.dr6.B2 ? "True " : "False", crashdata.dr6.B3 ? "True " : "False",
|
||||||
crashdata.dr7.LocalDR2 ? "True " : "False", crashdata.dr7.GlobalDR2 ? "True " : "False", crashdata.dr7.LocalDR3 ? "True " : "False", crashdata.dr7.GlobalDR3 ? "True " : "False",
|
crashdata.dr6.BD ? "True " : "False", crashdata.dr6.BS ? "True " : "False", crashdata.dr6.BT ? "True " : "False");
|
||||||
crashdata.dr7.ConditionsDR0 ? "True " : "False", crashdata.dr7.SizeDR0 ? "True " : "False", crashdata.dr7.ConditionsDR1 ? "True " : "False", crashdata.dr7.SizeDR1 ? "True " : "False",
|
|
||||||
crashdata.dr7.ConditionsDR2 ? "True " : "False", crashdata.dr7.SizeDR2 ? "True " : "False", crashdata.dr7.ConditionsDR3 ? "True " : "False", crashdata.dr7.SizeDR3 ? "True " : "False",
|
error("DR7: L0:%s G0:%s L1:%s G1:%s L2:%s G2:%s L3:%s G3:%s LE:%s GE:%s GD:%s R/W0:%s LEN0:%s R/W1:%s LEN1:%s R/W2:%s LEN2:%s R/W3:%s LEN3:%s",
|
||||||
crashdata.dr7.Reserved);
|
crashdata.dr7.L0 ? "True " : "False", crashdata.dr7.G0 ? "True " : "False", crashdata.dr7.L1 ? "True " : "False", crashdata.dr7.G1 ? "True " : "False",
|
||||||
|
crashdata.dr7.L2 ? "True " : "False", crashdata.dr7.G2 ? "True " : "False", crashdata.dr7.L3 ? "True " : "False", crashdata.dr7.G3 ? "True " : "False",
|
||||||
|
crashdata.dr7.LE ? "True " : "False", crashdata.dr7.GE ? "True " : "False", crashdata.dr7.GD ? "True " : "False", crashdata.dr7.RW0 ? "True " : "False",
|
||||||
|
crashdata.dr7.LEN0 ? "True " : "False", crashdata.dr7.RW1 ? "True " : "False", crashdata.dr7.LEN1 ? "True " : "False", crashdata.dr7.RW2 ? "True " : "False",
|
||||||
|
crashdata.dr7.LEN2 ? "True " : "False", crashdata.dr7.RW3 ? "True " : "False", crashdata.dr7.LEN3 ? "True " : "False");
|
||||||
|
|
||||||
error("EFER: SCE:%s LME:%s LMA:%s NXE:%s SVME:%s LMSLE:%s FFXSR:%s TCE:%s R0:%#x R1:%#x R2:%#x",
|
error("EFER: SCE:%s LME:%s LMA:%s NXE:%s SVME:%s LMSLE:%s FFXSR:%s TCE:%s R0:%#x R1:%#x R2:%#x",
|
||||||
crashdata.efer.SCE ? "True " : "False", crashdata.efer.LME ? "True " : "False", crashdata.efer.LMA ? "True " : "False", crashdata.efer.NXE ? "True " : "False",
|
crashdata.efer.SCE ? "True " : "False", crashdata.efer.LME ? "True " : "False", crashdata.efer.LMA ? "True " : "False", crashdata.efer.NXE ? "True " : "False",
|
||||||
|
@ -91,11 +91,10 @@ namespace CrashHandler
|
|||||||
EHPrint("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx\n", data.cr0.raw, data.cr2.raw, data.cr3.raw, data.cr4.raw, data.cr8.raw);
|
EHPrint("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx\n", data.cr0.raw, data.cr2.raw, data.cr3.raw, data.cr4.raw, data.cr8.raw);
|
||||||
EHPrint("DR0=%#llx DR1=%#llx DR2=%#llx DR3=%#llx DR6=%#llx DR7=%#llx\n", data.dr0, data.dr1, data.dr2, data.dr3, data.dr6, data.dr7.raw);
|
EHPrint("DR0=%#llx DR1=%#llx DR2=%#llx DR3=%#llx DR6=%#llx DR7=%#llx\n", data.dr0, data.dr1, data.dr2, data.dr3, data.dr6, data.dr7.raw);
|
||||||
|
|
||||||
EHPrint("\eFC797BCR0: PE:%s MP:%s EM:%s TS:%s\n ET:%s NE:%s WP:%s AM:%s\n NW:%s CD:%s PG:%s\n R0:%#x R1:%#x R2:%#x\n",
|
EHPrint("\eFC797BCR0: PE:%s MP:%s EM:%s TS:%s\n ET:%s NE:%s WP:%s AM:%s\n NW:%s CD:%s PG:%s\n",
|
||||||
data.cr0.PE ? "True " : "False", data.cr0.MP ? "True " : "False", data.cr0.EM ? "True " : "False", data.cr0.TS ? "True " : "False",
|
data.cr0.PE ? "True " : "False", data.cr0.MP ? "True " : "False", data.cr0.EM ? "True " : "False", data.cr0.TS ? "True " : "False",
|
||||||
data.cr0.ET ? "True " : "False", data.cr0.NE ? "True " : "False", data.cr0.WP ? "True " : "False", data.cr0.AM ? "True " : "False",
|
data.cr0.ET ? "True " : "False", data.cr0.NE ? "True " : "False", data.cr0.WP ? "True " : "False", data.cr0.AM ? "True " : "False",
|
||||||
data.cr0.NW ? "True " : "False", data.cr0.CD ? "True " : "False", data.cr0.PG ? "True " : "False",
|
data.cr0.NW ? "True " : "False", data.cr0.CD ? "True " : "False", data.cr0.PG ? "True " : "False");
|
||||||
data.cr0.Reserved0, data.cr0.Reserved1, data.cr0.Reserved2);
|
|
||||||
|
|
||||||
EHPrint("\eFCBD79CR2: PFLA: %#llx\n",
|
EHPrint("\eFCBD79CR2: PFLA: %#llx\n",
|
||||||
data.cr2.PFLA);
|
data.cr2.PFLA);
|
||||||
@ -103,52 +102,48 @@ namespace CrashHandler
|
|||||||
EHPrint("\e79FC84CR3: PWT:%s PCD:%s PDBR:%#llx\n",
|
EHPrint("\e79FC84CR3: PWT:%s PCD:%s PDBR:%#llx\n",
|
||||||
data.cr3.PWT ? "True " : "False", data.cr3.PCD ? "True " : "False", data.cr3.PDBR);
|
data.cr3.PWT ? "True " : "False", data.cr3.PCD ? "True " : "False", data.cr3.PDBR);
|
||||||
|
|
||||||
EHPrint("\eBD79FCCR4: VME:%s PVI:%s TSD:%s DE:%s\n PSE:%s PAE:%s MCE:%s PGE:%s\n PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s\n LA57:%s VMXE:%s SMXE:%s PCIDE:%s\n OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s\n R0:%#x R1:%#x R2:%#x\n",
|
EHPrint("\eBD79FCCR4: VME:%s PVI:%s TSD:%s DE:%s\n PSE:%s PAE:%s MCE:%s PGE:%s\n PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s\n LA57:%s VMXE:%s SMXE:%s PCIDE:%s\n OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s\n",
|
||||||
data.cr4.VME ? "True " : "False", data.cr4.PVI ? "True " : "False", data.cr4.TSD ? "True " : "False", data.cr4.DE ? "True " : "False",
|
data.cr4.VME ? "True " : "False", data.cr4.PVI ? "True " : "False", data.cr4.TSD ? "True " : "False", data.cr4.DE ? "True " : "False",
|
||||||
data.cr4.PSE ? "True " : "False", data.cr4.PAE ? "True " : "False", data.cr4.MCE ? "True " : "False", data.cr4.PGE ? "True " : "False",
|
data.cr4.PSE ? "True " : "False", data.cr4.PAE ? "True " : "False", data.cr4.MCE ? "True " : "False", data.cr4.PGE ? "True " : "False",
|
||||||
data.cr4.PCE ? "True " : "False", data.cr4.UMIP ? "True " : "False", data.cr4.OSFXSR ? "True " : "False", data.cr4.OSXMMEXCPT ? "True " : "False",
|
data.cr4.PCE ? "True " : "False", data.cr4.UMIP ? "True " : "False", data.cr4.OSFXSR ? "True " : "False", data.cr4.OSXMMEXCPT ? "True " : "False",
|
||||||
data.cr4.LA57 ? "True " : "False", data.cr4.VMXE ? "True " : "False", data.cr4.SMXE ? "True " : "False", data.cr4.PCIDE ? "True " : "False",
|
data.cr4.LA57 ? "True " : "False", data.cr4.VMXE ? "True " : "False", data.cr4.SMXE ? "True " : "False", data.cr4.PCIDE ? "True " : "False",
|
||||||
data.cr4.OSXSAVE ? "True " : "False", data.cr4.SMEP ? "True " : "False", data.cr4.SMAP ? "True " : "False", data.cr4.PKE ? "True " : "False",
|
data.cr4.OSXSAVE ? "True " : "False", data.cr4.SMEP ? "True " : "False", data.cr4.SMAP ? "True " : "False", data.cr4.PKE ? "True " : "False");
|
||||||
#if defined(a64)
|
|
||||||
data.cr4.Reserved0, data.cr4.Reserved1, data.cr4.Reserved2);
|
|
||||||
#elif defined(a32)
|
|
||||||
data.cr4.Reserved0, data.cr4.Reserved1, 0);
|
|
||||||
#endif
|
|
||||||
EHPrint("\e79FCF5CR8: TPL:%d\n", data.cr8.TPL);
|
EHPrint("\e79FCF5CR8: TPL:%d\n", data.cr8.TPL);
|
||||||
#endif // a64 || a32
|
#endif // a64 || a32
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
EHPrint("\eFCFC02RFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x R3:%#x\n",
|
EHPrint("\eFCFC02RFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n",
|
||||||
data.Frame->rflags.CF ? "True " : "False", data.Frame->rflags.PF ? "True " : "False", data.Frame->rflags.AF ? "True " : "False", data.Frame->rflags.ZF ? "True " : "False",
|
data.Frame->rflags.CF ? "True " : "False", data.Frame->rflags.PF ? "True " : "False", data.Frame->rflags.AF ? "True " : "False", data.Frame->rflags.ZF ? "True " : "False",
|
||||||
data.Frame->rflags.SF ? "True " : "False", data.Frame->rflags.TF ? "True " : "False", data.Frame->rflags.IF ? "True " : "False", data.Frame->rflags.DF ? "True " : "False",
|
data.Frame->rflags.SF ? "True " : "False", data.Frame->rflags.TF ? "True " : "False", data.Frame->rflags.IF ? "True " : "False", data.Frame->rflags.DF ? "True " : "False",
|
||||||
data.Frame->rflags.OF ? "True " : "False", data.Frame->rflags.IOPL ? "True " : "False", data.Frame->rflags.NT ? "True " : "False", data.Frame->rflags.RF ? "True " : "False",
|
data.Frame->rflags.OF ? "True " : "False", data.Frame->rflags.IOPL ? "True " : "False", data.Frame->rflags.NT ? "True " : "False", data.Frame->rflags.RF ? "True " : "False",
|
||||||
data.Frame->rflags.VM ? "True " : "False", data.Frame->rflags.AC ? "True " : "False", data.Frame->rflags.VIF ? "True " : "False", data.Frame->rflags.VIP ? "True " : "False",
|
data.Frame->rflags.VM ? "True " : "False", data.Frame->rflags.AC ? "True " : "False", data.Frame->rflags.VIF ? "True " : "False", data.Frame->rflags.VIP ? "True " : "False",
|
||||||
data.Frame->rflags.ID ? "True " : "False", data.Frame->rflags.AlwaysOne,
|
data.Frame->rflags.ID ? "True " : "False", data.Frame->rflags.AlwaysOne);
|
||||||
data.Frame->rflags.Reserved0, data.Frame->rflags.Reserved1, data.Frame->rflags.Reserved2, data.Frame->rflags.Reserved3);
|
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
EHPrint("\eFCFC02EFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x\n",
|
EHPrint("\eFCFC02EFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n",
|
||||||
data.Frame->eflags.CF ? "True " : "False", data.Frame->eflags.PF ? "True " : "False", data.Frame->eflags.AF ? "True " : "False", data.Frame->eflags.ZF ? "True " : "False",
|
data.Frame->eflags.CF ? "True " : "False", data.Frame->eflags.PF ? "True " : "False", data.Frame->eflags.AF ? "True " : "False", data.Frame->eflags.ZF ? "True " : "False",
|
||||||
data.Frame->eflags.SF ? "True " : "False", data.Frame->eflags.TF ? "True " : "False", data.Frame->eflags.IF ? "True " : "False", data.Frame->eflags.DF ? "True " : "False",
|
data.Frame->eflags.SF ? "True " : "False", data.Frame->eflags.TF ? "True " : "False", data.Frame->eflags.IF ? "True " : "False", data.Frame->eflags.DF ? "True " : "False",
|
||||||
data.Frame->eflags.OF ? "True " : "False", data.Frame->eflags.IOPL ? "True " : "False", data.Frame->eflags.NT ? "True " : "False", data.Frame->eflags.RF ? "True " : "False",
|
data.Frame->eflags.OF ? "True " : "False", data.Frame->eflags.IOPL ? "True " : "False", data.Frame->eflags.NT ? "True " : "False", data.Frame->eflags.RF ? "True " : "False",
|
||||||
data.Frame->eflags.VM ? "True " : "False", data.Frame->eflags.AC ? "True " : "False", data.Frame->eflags.VIF ? "True " : "False", data.Frame->eflags.VIP ? "True " : "False",
|
data.Frame->eflags.VM ? "True " : "False", data.Frame->eflags.AC ? "True " : "False", data.Frame->eflags.VIF ? "True " : "False", data.Frame->eflags.VIP ? "True " : "False",
|
||||||
data.Frame->eflags.ID ? "True " : "False", data.Frame->eflags.AlwaysOne,
|
data.Frame->eflags.ID ? "True " : "False", data.Frame->eflags.AlwaysOne);
|
||||||
data.Frame->eflags.Reserved0, data.Frame->eflags.Reserved1, data.Frame->eflags.Reserved2);
|
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(a86)
|
#if defined(a86)
|
||||||
EHPrint("\eA0F0F0DR7: LDR0:%s GDR0:%s LDR1:%s GDR1:%s\n LDR2:%s GDR2:%s LDR3:%s GDR3:%s\n CDR0:%s SDR0:%s CDR1:%s SDR1:%s\n CDR2:%s SDR2:%s CDR3:%s SDR3:%s\n R:%#x\n",
|
EHPrint("\eA0A0A0DR6: B0:%s B1:%s B2:%s B3:%s BD:%s BS:%s BT:%s\n",
|
||||||
data.dr7.LocalDR0 ? "True " : "False", data.dr7.GlobalDR0 ? "True " : "False", data.dr7.LocalDR1 ? "True " : "False", data.dr7.GlobalDR1 ? "True " : "False",
|
data.dr6.B0 ? "True " : "False", data.dr6.B1 ? "True " : "False", data.dr6.B2 ? "True " : "False", data.dr6.B3 ? "True " : "False",
|
||||||
data.dr7.LocalDR2 ? "True " : "False", data.dr7.GlobalDR2 ? "True " : "False", data.dr7.LocalDR3 ? "True " : "False", data.dr7.GlobalDR3 ? "True " : "False",
|
data.dr6.BD ? "True " : "False", data.dr6.BS ? "True " : "False", data.dr6.BT ? "True " : "False");
|
||||||
data.dr7.ConditionsDR0 ? "True " : "False", data.dr7.SizeDR0 ? "True " : "False", data.dr7.ConditionsDR1 ? "True " : "False", data.dr7.SizeDR1 ? "True " : "False",
|
|
||||||
data.dr7.ConditionsDR2 ? "True " : "False", data.dr7.SizeDR2 ? "True " : "False", data.dr7.ConditionsDR3 ? "True " : "False", data.dr7.SizeDR3 ? "True " : "False",
|
EHPrint("\eA0F0F0DR7: L0:%s G0:%s L1:%s G1:%s\n L2:%s G2:%s L3:%s G3:%s\n LE:%s GE:%s GD:%s\n R/W0:%s LEN0:%s R/W1:%s LEN1:%s\n R/W2:%s LEN2:%s R/W3:%s LEN3:%s\n",
|
||||||
data.dr7.Reserved);
|
data.dr7.L0 ? "True " : "False", data.dr7.G0 ? "True " : "False", data.dr7.L1 ? "True " : "False", data.dr7.G1 ? "True " : "False",
|
||||||
|
data.dr7.L2 ? "True " : "False", data.dr7.G2 ? "True " : "False", data.dr7.L3 ? "True " : "False", data.dr7.G3 ? "True " : "False",
|
||||||
|
data.dr7.LE ? "True " : "False", data.dr7.GE ? "True " : "False", data.dr7.GD ? "True " : "False", data.dr7.RW0 ? "True " : "False",
|
||||||
|
data.dr7.LEN0 ? "True " : "False", data.dr7.RW1 ? "True " : "False", data.dr7.LEN1 ? "True " : "False", data.dr7.RW2 ? "True " : "False",
|
||||||
|
data.dr7.LEN2 ? "True " : "False", data.dr7.RW3 ? "True " : "False", data.dr7.LEN3 ? "True " : "False");
|
||||||
|
|
||||||
#ifdef a64
|
#ifdef a64
|
||||||
EHPrint("\e009FF0EFER: SCE:%s LME:%s LMA:%s NXE:%s\n SVME:%s LMSLE:%s FFXSR:%s TCE:%s\n R0:%#x R1:%#x R2:%#x\n",
|
EHPrint("\e009FF0EFER: SCE:%s LME:%s LMA:%s NXE:%s\n SVME:%s LMSLE:%s FFXSR:%s TCE:%s\n\n",
|
||||||
data.efer.SCE ? "True " : "False", data.efer.LME ? "True " : "False", data.efer.LMA ? "True " : "False", data.efer.NXE ? "True " : "False",
|
data.efer.SCE ? "True " : "False", data.efer.LME ? "True " : "False", data.efer.LMA ? "True " : "False", data.efer.NXE ? "True " : "False",
|
||||||
data.efer.SVME ? "True " : "False", data.efer.LMSLE ? "True " : "False", data.efer.FFXSR ? "True " : "False", data.efer.TCE ? "True " : "False",
|
data.efer.SVME ? "True " : "False", data.efer.LMSLE ? "True " : "False", data.efer.FFXSR ? "True " : "False", data.efer.TCE ? "True " : "False");
|
||||||
data.efer.Reserved0, data.efer.Reserved1, data.efer.Reserved2);
|
|
||||||
#endif // a64
|
#endif // a64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -56,10 +56,10 @@ namespace CrashHandler
|
|||||||
"Terminated", // Terminated
|
"Terminated", // Terminated
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Tasking::PCB *> Plist = TaskManager->GetProcessList();
|
|
||||||
|
|
||||||
if (TaskManager)
|
if (TaskManager)
|
||||||
{
|
{
|
||||||
|
std::vector<Tasking::PCB *> Plist = TaskManager->GetProcessList();
|
||||||
|
|
||||||
if (data.Thread)
|
if (data.Thread)
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->rip);
|
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->rip);
|
||||||
|
@ -250,22 +250,22 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (CurCPU)
|
if (CurCPU)
|
||||||
{
|
{
|
||||||
Memory::Virtual vma = Memory::Virtual(CurCPU->CurrentProcess->PageTable);
|
Memory::Virtual vmm = Memory::Virtual(CurCPU->CurrentProcess->PageTable);
|
||||||
bool PageAvailable = vma.Check((void *)CheckPageFaultAddress);
|
bool PageAvailable = vmm.Check((void *)CheckPageFaultAddress);
|
||||||
debug("Page available (Check(...)): %s. %s",
|
debug("Page available (Check(...)): %s. %s",
|
||||||
PageAvailable ? "Yes" : "No",
|
PageAvailable ? "Yes" : "No",
|
||||||
(params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result.");
|
(params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result.");
|
||||||
|
|
||||||
if (PageAvailable)
|
if (PageAvailable)
|
||||||
{
|
{
|
||||||
bool Present = vma.Check((void *)CheckPageFaultAddress);
|
bool Present = vmm.Check((void *)CheckPageFaultAddress);
|
||||||
bool ReadWrite = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW);
|
bool ReadWrite = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW);
|
||||||
bool User = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US);
|
bool User = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US);
|
||||||
bool WriteThrough = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT);
|
bool WriteThrough = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT);
|
||||||
bool CacheDisabled = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD);
|
bool CacheDisabled = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD);
|
||||||
bool Accessed = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A);
|
bool Accessed = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A);
|
||||||
bool Dirty = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D);
|
bool Dirty = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D);
|
||||||
bool Global = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G);
|
bool Global = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G);
|
||||||
/* ... */
|
/* ... */
|
||||||
|
|
||||||
debug("Page available: %s", Present ? "Yes" : "No");
|
debug("Page available: %s", Present ? "Yes" : "No");
|
||||||
|
@ -37,7 +37,8 @@ struct CRData
|
|||||||
CPU::x64::CR4 cr4;
|
CPU::x64::CR4 cr4;
|
||||||
CPU::x64::CR8 cr8;
|
CPU::x64::CR8 cr8;
|
||||||
CPU::x64::EFER efer;
|
CPU::x64::EFER efer;
|
||||||
uintptr_t dr0, dr1, dr2, dr3, dr6;
|
uintptr_t dr0, dr1, dr2, dr3;
|
||||||
|
CPU::x64::DR6 dr6;
|
||||||
CPU::x64::DR7 dr7;
|
CPU::x64::DR7 dr7;
|
||||||
|
|
||||||
long ID;
|
long ID;
|
||||||
@ -58,7 +59,8 @@ struct CRData
|
|||||||
CPU::x32::CR3 cr3;
|
CPU::x32::CR3 cr3;
|
||||||
CPU::x32::CR4 cr4;
|
CPU::x32::CR4 cr4;
|
||||||
CPU::x32::CR8 cr8;
|
CPU::x32::CR8 cr8;
|
||||||
uintptr_t dr0, dr1, dr2, dr3, dr6;
|
uintptr_t dr0, dr1, dr2, dr3;
|
||||||
|
CPU::x32::DR6 dr6;
|
||||||
CPU::x32::DR7 dr7;
|
CPU::x32::DR7 dr7;
|
||||||
|
|
||||||
long ID;
|
long ID;
|
||||||
|
@ -31,7 +31,7 @@ static inline NIF void uart_wrapper(char c, void *unused)
|
|||||||
UNUSED(unused);
|
UNUSED(unused);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline NIF void WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function)
|
static inline NIF bool WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, va_list args)
|
||||||
{
|
{
|
||||||
const char *DbgLvlString;
|
const char *DbgLvlString;
|
||||||
switch (Level)
|
switch (Level)
|
||||||
@ -54,35 +54,52 @@ static inline NIF void WritePrefix(DebugLevel Level, const char *File, int Line,
|
|||||||
case DebugLevelFixme:
|
case DebugLevelFixme:
|
||||||
DbgLvlString = "FIXME";
|
DbgLvlString = "FIXME";
|
||||||
break;
|
break;
|
||||||
|
case DebugLevelStub:
|
||||||
|
fctprintf(uart_wrapper, nullptr, "STUB | %s>%s() is stub\n", File, Function);
|
||||||
|
return false;
|
||||||
|
case DebugLevelFunction:
|
||||||
|
fctprintf(uart_wrapper, nullptr, "FUNC | %s>%s( ", File, Function);
|
||||||
|
vfctprintf(uart_wrapper, nullptr, Format, args);
|
||||||
|
fctprintf(uart_wrapper, nullptr, " )\n");
|
||||||
|
return false;
|
||||||
case DebugLevelUbsan:
|
case DebugLevelUbsan:
|
||||||
{
|
{
|
||||||
DbgLvlString = "UBSAN";
|
DbgLvlString = "UBSAN";
|
||||||
fctprintf(uart_wrapper, nullptr, "%s| ", DbgLvlString);
|
fctprintf(uart_wrapper, nullptr, "%s| ", DbgLvlString);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
DbgLvlString = "UNKNW";
|
DbgLvlString = "UNKNW";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fctprintf(uart_wrapper, nullptr, "%s|%s->%s:%d: ", DbgLvlString, File, Function, Line);
|
fctprintf(uart_wrapper, nullptr, "%s| %s>%s:%d: ", DbgLvlString, File, Function, Line);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace SysDbg
|
namespace SysDbg
|
||||||
{
|
{
|
||||||
NIF void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
NIF void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||||
{
|
{
|
||||||
WritePrefix(Level, File, Line, Function);
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, Format);
|
va_start(args, Format);
|
||||||
|
if (!WritePrefix(Level, File, Line, Function, Format, args))
|
||||||
|
{
|
||||||
|
va_end(args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
vfctprintf(uart_wrapper, nullptr, Format, args);
|
vfctprintf(uart_wrapper, nullptr, Format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
NIF void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
NIF void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||||
{
|
{
|
||||||
WritePrefix(Level, File, Line, Function);
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, Format);
|
va_start(args, Format);
|
||||||
|
if (!WritePrefix(Level, File, Line, Function, Format, args))
|
||||||
|
{
|
||||||
|
va_end(args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
vfctprintf(uart_wrapper, nullptr, Format, args);
|
vfctprintf(uart_wrapper, nullptr, Format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
uart_wrapper('\n', nullptr);
|
uart_wrapper('\n', nullptr);
|
||||||
@ -91,9 +108,13 @@ namespace SysDbg
|
|||||||
NIF void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
NIF void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||||
{
|
{
|
||||||
SmartTimeoutLock(DebuggerLock, 1000);
|
SmartTimeoutLock(DebuggerLock, 1000);
|
||||||
WritePrefix(Level, File, Line, Function);
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, Format);
|
va_start(args, Format);
|
||||||
|
if (!WritePrefix(Level, File, Line, Function, Format, args))
|
||||||
|
{
|
||||||
|
va_end(args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
vfctprintf(uart_wrapper, nullptr, Format, args);
|
vfctprintf(uart_wrapper, nullptr, Format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
@ -101,9 +122,13 @@ namespace SysDbg
|
|||||||
NIF void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
NIF void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||||
{
|
{
|
||||||
SmartTimeoutLock(DebuggerLock, 1000);
|
SmartTimeoutLock(DebuggerLock, 1000);
|
||||||
WritePrefix(Level, File, Line, Function);
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, Format);
|
va_start(args, Format);
|
||||||
|
if (!WritePrefix(Level, File, Line, Function, Format, args))
|
||||||
|
{
|
||||||
|
va_end(args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
vfctprintf(uart_wrapper, nullptr, Format, args);
|
vfctprintf(uart_wrapper, nullptr, Format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
uart_wrapper('\n', nullptr);
|
uart_wrapper('\n', nullptr);
|
||||||
@ -113,9 +138,13 @@ namespace SysDbg
|
|||||||
// C compatibility
|
// C compatibility
|
||||||
extern "C" NIF void SysDbgWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
extern "C" NIF void SysDbgWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||||
{
|
{
|
||||||
WritePrefix(Level, File, Line, Function);
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, Format);
|
va_start(args, Format);
|
||||||
|
if (!WritePrefix(Level, File, Line, Function, Format, args))
|
||||||
|
{
|
||||||
|
va_end(args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
vfctprintf(uart_wrapper, nullptr, Format, args);
|
vfctprintf(uart_wrapper, nullptr, Format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
@ -123,9 +152,13 @@ extern "C" NIF void SysDbgWrite(enum DebugLevel Level, const char *File, int Lin
|
|||||||
// C compatibility
|
// C compatibility
|
||||||
extern "C" NIF void SysDbgWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
extern "C" NIF void SysDbgWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||||
{
|
{
|
||||||
WritePrefix(Level, File, Line, Function);
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, Format);
|
va_start(args, Format);
|
||||||
|
if (!WritePrefix(Level, File, Line, Function, Format, args))
|
||||||
|
{
|
||||||
|
va_end(args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
vfctprintf(uart_wrapper, nullptr, Format, args);
|
vfctprintf(uart_wrapper, nullptr, Format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
uart_wrapper('\n', nullptr);
|
uart_wrapper('\n', nullptr);
|
||||||
@ -135,9 +168,13 @@ extern "C" NIF void SysDbgWriteLine(enum DebugLevel Level, const char *File, int
|
|||||||
extern "C" NIF void SysDbgLockedWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
extern "C" NIF void SysDbgLockedWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||||
{
|
{
|
||||||
SmartTimeoutLock(DebuggerLock, 1000);
|
SmartTimeoutLock(DebuggerLock, 1000);
|
||||||
WritePrefix(Level, File, Line, Function);
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, Format);
|
va_start(args, Format);
|
||||||
|
if (!WritePrefix(Level, File, Line, Function, Format, args))
|
||||||
|
{
|
||||||
|
va_end(args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
vfctprintf(uart_wrapper, nullptr, Format, args);
|
vfctprintf(uart_wrapper, nullptr, Format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
@ -146,9 +183,13 @@ extern "C" NIF void SysDbgLockedWrite(enum DebugLevel Level, const char *File, i
|
|||||||
extern "C" NIF void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
extern "C" NIF void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||||
{
|
{
|
||||||
SmartTimeoutLock(DebuggerLock, 1000);
|
SmartTimeoutLock(DebuggerLock, 1000);
|
||||||
WritePrefix(Level, File, Line, Function);
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, Format);
|
va_start(args, Format);
|
||||||
|
if (!WritePrefix(Level, File, Line, Function, Format, args))
|
||||||
|
{
|
||||||
|
va_end(args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
vfctprintf(uart_wrapper, nullptr, Format, args);
|
vfctprintf(uart_wrapper, nullptr, Format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
uart_wrapper('\n', nullptr);
|
uart_wrapper('\n', nullptr);
|
||||||
|
@ -216,7 +216,7 @@ namespace Driver
|
|||||||
}
|
}
|
||||||
|
|
||||||
debug("Loading drivers from %s", Config.DriverDirectory);
|
debug("Loading drivers from %s", Config.DriverDirectory);
|
||||||
foreach (auto DrvFile in DriverDirectory.node->Children)
|
foreach (auto DrvFile in DriverDirectory.GetChildren())
|
||||||
{
|
{
|
||||||
if (DrvFile->Flags != VirtualFileSystem::NodeFlags::FILE)
|
if (DrvFile->Flags != VirtualFileSystem::NodeFlags::FILE)
|
||||||
continue;
|
continue;
|
||||||
|
@ -116,7 +116,7 @@ void LockClass::DeadLock(SpinLockData Lock)
|
|||||||
this->Unlock();
|
this->Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TaskManager)
|
if (TaskManager && !TaskManager->IsPanic())
|
||||||
TaskManager->Schedule();
|
TaskManager->Schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +128,13 @@ int LockClass::Lock(const char *FunctionName)
|
|||||||
Retry:
|
Retry:
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (IsLocked.exchange(true, std::memory_order_acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000))
|
while (IsLocked.exchange(true, std::memory_order_acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000))
|
||||||
|
{
|
||||||
|
/* FIXME */
|
||||||
|
// if (TaskManager && !TaskManager->IsPanic())
|
||||||
|
// TaskManager->Schedule();
|
||||||
|
// else
|
||||||
CPU::Pause();
|
CPU::Pause();
|
||||||
|
}
|
||||||
|
|
||||||
if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000))
|
if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000))
|
||||||
{
|
{
|
||||||
@ -187,7 +193,7 @@ void LockClass::TimeoutDeadLock(SpinLockData Lock, uint64_t Timeout)
|
|||||||
this->Unlock();
|
this->Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TaskManager)
|
if (TaskManager && !TaskManager->IsPanic())
|
||||||
TaskManager->Schedule();
|
TaskManager->Schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +209,13 @@ int LockClass::TimeoutLock(const char *FunctionName, uint64_t Timeout)
|
|||||||
Retry:
|
Retry:
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (IsLocked.exchange(true, std::memory_order_acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000))
|
while (IsLocked.exchange(true, std::memory_order_acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000))
|
||||||
|
{
|
||||||
|
/* FIXME */
|
||||||
|
// if (TaskManager && !TaskManager->IsPanic())
|
||||||
|
// TaskManager->Schedule();
|
||||||
|
// else
|
||||||
CPU::Pause();
|
CPU::Pause();
|
||||||
|
}
|
||||||
|
|
||||||
if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000))
|
if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000))
|
||||||
{
|
{
|
||||||
|
@ -441,7 +441,10 @@ void *malloc(size_t Size)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw;
|
{
|
||||||
|
error("Unknown allocator type %d", AllocatorType);
|
||||||
|
CPU::Stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (EnableExternalMemoryTracer)
|
if (EnableExternalMemoryTracer)
|
||||||
@ -494,7 +497,10 @@ void *calloc(size_t n, size_t Size)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw;
|
{
|
||||||
|
error("Unknown allocator type %d", AllocatorType);
|
||||||
|
CPU::Stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (EnableExternalMemoryTracer)
|
if (EnableExternalMemoryTracer)
|
||||||
@ -547,7 +553,10 @@ void *realloc(void *Address, size_t Size)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw;
|
{
|
||||||
|
error("Unknown allocator type %d", AllocatorType);
|
||||||
|
CPU::Stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (EnableExternalMemoryTracer)
|
if (EnableExternalMemoryTracer)
|
||||||
@ -598,7 +607,10 @@ void free(void *Address)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw;
|
{
|
||||||
|
error("Unknown allocator type %d", AllocatorType);
|
||||||
|
CPU::Stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (EnableExternalMemoryTracer)
|
if (EnableExternalMemoryTracer)
|
||||||
|
@ -26,11 +26,14 @@ namespace Memory
|
|||||||
{
|
{
|
||||||
if (!Size)
|
if (!Size)
|
||||||
Size = node->Length;
|
Size = node->Length;
|
||||||
if (Offset > node->Length)
|
|
||||||
|
if ((size_t)node->Offset > node->Length)
|
||||||
return 0;
|
return 0;
|
||||||
if (Offset + Size > node->Length)
|
|
||||||
Size = node->Length - Offset;
|
if (node->Offset + Size > node->Length)
|
||||||
memcpy(Buffer, (uint8_t *)(node->Address + Offset), Size);
|
Size = node->Length - node->Offset;
|
||||||
|
|
||||||
|
memcpy(Buffer, (uint8_t *)(node->Address + node->Offset), Size);
|
||||||
return Size;
|
return Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,53 +41,21 @@ namespace Memory
|
|||||||
{
|
{
|
||||||
if (!Size)
|
if (!Size)
|
||||||
Size = node->Length;
|
Size = node->Length;
|
||||||
if (Offset > node->Length)
|
|
||||||
|
if ((size_t)node->Offset > node->Length)
|
||||||
return 0;
|
return 0;
|
||||||
if (Offset + Size > node->Length)
|
|
||||||
Size = node->Length - Offset;
|
if (node->Offset + Size > node->Length)
|
||||||
memcpy((uint8_t *)(node->Address + Offset), Buffer, Size);
|
Size = node->Length - node->Offset;
|
||||||
|
|
||||||
|
memcpy((uint8_t *)(node->Address + node->Offset), Buffer, Size);
|
||||||
return Size;
|
return Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
SeekFSFunction(MEM_Seek)
|
|
||||||
{
|
|
||||||
long NewOffset;
|
|
||||||
|
|
||||||
if (Whence == SEEK_SET)
|
|
||||||
{
|
|
||||||
if (Offset > node->Length)
|
|
||||||
return -1;
|
|
||||||
node->Offset = Offset;
|
|
||||||
NewOffset = (long)node->Offset;
|
|
||||||
}
|
|
||||||
else if (Whence == SEEK_CUR)
|
|
||||||
{
|
|
||||||
NewOffset = (long)(node->Offset + Offset);
|
|
||||||
if ((size_t)NewOffset > node->Length || NewOffset < 0)
|
|
||||||
return -1;
|
|
||||||
node->Offset = NewOffset;
|
|
||||||
}
|
|
||||||
else if (Whence == SEEK_END)
|
|
||||||
{
|
|
||||||
NewOffset = node->Length + Offset;
|
|
||||||
if (NewOffset < 0)
|
|
||||||
return -1;
|
|
||||||
node->Offset = NewOffset;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error("Invalid whence!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NewOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
VirtualFileSystem::FileSystemOperations mem_op = {
|
VirtualFileSystem::FileSystemOperations mem_op = {
|
||||||
.Name = "mem",
|
.Name = "mem",
|
||||||
.Read = MEM_Read,
|
.Read = MEM_Read,
|
||||||
.Write = MEM_Write,
|
.Write = MEM_Write,
|
||||||
.Seek = MEM_Seek,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
uint64_t MemMgr::GetAllocatedMemorySize()
|
uint64_t MemMgr::GetAllocatedMemorySize()
|
||||||
@ -160,7 +131,10 @@ namespace Memory
|
|||||||
if (User)
|
if (User)
|
||||||
Flags |= Memory::PTFlag::US;
|
Flags |= Memory::PTFlag::US;
|
||||||
|
|
||||||
Memory::Virtual(this->Table).Remap((void *)((uintptr_t)Address + (i * PAGE_SIZE)), (void *)((uint64_t)Address + (i * PAGE_SIZE)), Flags);
|
void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE));
|
||||||
|
|
||||||
|
Memory::Virtual vmm = Memory::Virtual(this->Table);
|
||||||
|
vmm.Remap(AddressToMap, AddressToMap, Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->Directory)
|
if (this->Directory)
|
||||||
@ -206,10 +180,12 @@ namespace Memory
|
|||||||
|
|
||||||
KernelAllocator.FreePages(Address, Count);
|
KernelAllocator.FreePages(Address, Count);
|
||||||
|
|
||||||
|
Memory::Virtual vmm = Memory::Virtual(this->Table);
|
||||||
for (size_t i = 0; i < Count; i++)
|
for (size_t i = 0; i < Count; i++)
|
||||||
{
|
{
|
||||||
Memory::Virtual(this->Table).Remap((void *)((uintptr_t)Address + (i * PAGE_SIZE)), (void *)((uint64_t)Address + (i * PAGE_SIZE)), Memory::PTFlag::RW);
|
void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE));
|
||||||
// Memory::Virtual(this->Table).Unmap((void *)((uintptr_t)Address + (i * PAGE_SIZE)));
|
vmm.Remap(AddressToMap, AddressToMap, Memory::PTFlag::RW);
|
||||||
|
// vmm.Unmap((void *)((uintptr_t)Address + (i * PAGE_SIZE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->Directory)
|
if (this->Directory)
|
||||||
@ -270,8 +246,11 @@ namespace Memory
|
|||||||
foreach (auto ap in AllocatedPagesList)
|
foreach (auto ap in AllocatedPagesList)
|
||||||
{
|
{
|
||||||
KernelAllocator.FreePages(ap.Address, ap.PageCount);
|
KernelAllocator.FreePages(ap.Address, ap.PageCount);
|
||||||
|
Memory::Virtual vmm = Memory::Virtual(this->Table);
|
||||||
for (size_t i = 0; i < ap.PageCount; i++)
|
for (size_t i = 0; i < ap.PageCount; i++)
|
||||||
Memory::Virtual(this->Table).Remap((void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), (void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), Memory::PTFlag::RW);
|
vmm.Remap((void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)),
|
||||||
|
(void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)),
|
||||||
|
Memory::PTFlag::RW);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->Directory)
|
if (this->Directory)
|
||||||
|
@ -120,6 +120,13 @@ namespace Memory
|
|||||||
return (void *)(PageBitmapIndex * PAGE_SIZE);
|
return (void *)(PageBitmapIndex * PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TaskManager && !TaskManager->IsPanic())
|
||||||
|
{
|
||||||
|
error("Out of memory! Killing current process...");
|
||||||
|
TaskManager->KillProcess(TaskManager->GetCurrentProcess(), Tasking::KILL_OOM);
|
||||||
|
TaskManager->Schedule();
|
||||||
|
}
|
||||||
|
|
||||||
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
|
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
|
||||||
CPU::Stop();
|
CPU::Stop();
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
@ -180,6 +187,13 @@ namespace Memory
|
|||||||
return (void *)(PageBitmapIndex * PAGE_SIZE);
|
return (void *)(PageBitmapIndex * PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TaskManager && !TaskManager->IsPanic())
|
||||||
|
{
|
||||||
|
error("Out of memory! Killing current process...");
|
||||||
|
TaskManager->KillProcess(TaskManager->GetCurrentProcess(), Tasking::KILL_OOM);
|
||||||
|
TaskManager->Schedule();
|
||||||
|
}
|
||||||
|
|
||||||
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
|
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
|
||||||
CPU::Halt(true);
|
CPU::Halt(true);
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
|
@ -957,11 +957,11 @@ namespace PCI
|
|||||||
{
|
{
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
int Entries = s_cst(int, ((((ACPI::ACPI *)PowerManager->GetACPI())->MCFG->Header.Length) - sizeof(ACPI::ACPI::MCFGHeader)) / sizeof(DeviceConfig));
|
int Entries = s_cst(int, ((((ACPI::ACPI *)PowerManager->GetACPI())->MCFG->Header.Length) - sizeof(ACPI::ACPI::MCFGHeader)) / sizeof(DeviceConfig));
|
||||||
Memory::Virtual vma = Memory::Virtual(KernelPageTable);
|
Memory::Virtual vmm = Memory::Virtual(KernelPageTable);
|
||||||
for (int t = 0; t < Entries; t++)
|
for (int t = 0; t < Entries; t++)
|
||||||
{
|
{
|
||||||
DeviceConfig *NewDeviceConfig = (DeviceConfig *)((uintptr_t)((ACPI::ACPI *)PowerManager->GetACPI())->MCFG + sizeof(ACPI::ACPI::MCFGHeader) + (sizeof(DeviceConfig) * t));
|
DeviceConfig *NewDeviceConfig = (DeviceConfig *)((uintptr_t)((ACPI::ACPI *)PowerManager->GetACPI())->MCFG + sizeof(ACPI::ACPI::MCFGHeader) + (sizeof(DeviceConfig) * t));
|
||||||
vma.Map((void *)NewDeviceConfig->BaseAddress, (void *)NewDeviceConfig->BaseAddress, Memory::PTFlag::RW);
|
vmm.Map((void *)NewDeviceConfig->BaseAddress, (void *)NewDeviceConfig->BaseAddress, Memory::PTFlag::RW);
|
||||||
debug("PCI Entry %d Address:%#llx BUS:%#llx-%#llx", t, NewDeviceConfig->BaseAddress,
|
debug("PCI Entry %d Address:%#llx BUS:%#llx-%#llx", t, NewDeviceConfig->BaseAddress,
|
||||||
NewDeviceConfig->StartBus, NewDeviceConfig->EndBus);
|
NewDeviceConfig->StartBus, NewDeviceConfig->EndBus);
|
||||||
for (uintptr_t Bus = NewDeviceConfig->StartBus; Bus < NewDeviceConfig->EndBus; Bus++)
|
for (uintptr_t Bus = NewDeviceConfig->StartBus; Bus < NewDeviceConfig->EndBus; Bus++)
|
||||||
|
171
Execute/BinaryParse.cpp
Normal file
171
Execute/BinaryParse.cpp
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <exec.hpp>
|
||||||
|
|
||||||
|
#include <msexec.h>
|
||||||
|
|
||||||
|
#include "../kernel.h"
|
||||||
|
#include "../Fex.hpp"
|
||||||
|
|
||||||
|
namespace Execute
|
||||||
|
{
|
||||||
|
BinaryType GetBinaryType(void *Image)
|
||||||
|
{
|
||||||
|
Fex *FexHdr = (Fex *)Image;
|
||||||
|
Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)Image;
|
||||||
|
IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)Image;
|
||||||
|
|
||||||
|
/* Check Fex magic */
|
||||||
|
if (FexHdr->Magic[0] == 'F' &&
|
||||||
|
FexHdr->Magic[1] == 'E' &&
|
||||||
|
FexHdr->Magic[2] == 'X' &&
|
||||||
|
FexHdr->Magic[3] == '\0')
|
||||||
|
{
|
||||||
|
/* If the fex type is driver, we shouldn't return as Fex. */
|
||||||
|
if (FexHdr->Type == FexFormatType::FexFormatType_Executable)
|
||||||
|
{
|
||||||
|
debug("Image - Fex");
|
||||||
|
return BinaryType::BinTypeFex;
|
||||||
|
}
|
||||||
|
else if (FexHdr->Type == FexFormatType::FexFormatType_Driver)
|
||||||
|
{
|
||||||
|
debug("Fex Driver is not supposed to be executed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Check ELF magic. */
|
||||||
|
else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 &&
|
||||||
|
ELFHeader->e_ident[EI_MAG1] == ELFMAG1 &&
|
||||||
|
ELFHeader->e_ident[EI_MAG2] == ELFMAG2 &&
|
||||||
|
ELFHeader->e_ident[EI_MAG3] == ELFMAG3)
|
||||||
|
{
|
||||||
|
debug("Image - ELF");
|
||||||
|
return BinaryType::BinTypeELF;
|
||||||
|
}
|
||||||
|
/* Every Windows executable starts with MZ header. */
|
||||||
|
else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE)
|
||||||
|
{
|
||||||
|
IMAGE_NT_HEADERS *PEHeader = (IMAGE_NT_HEADERS *)(((char *)Image) + MZHeader->e_lfanew);
|
||||||
|
IMAGE_OS2_HEADER *NEHeader = (IMAGE_OS2_HEADER *)(((char *)Image) + MZHeader->e_lfanew);
|
||||||
|
|
||||||
|
/* TODO: LE, EDOS */
|
||||||
|
if (PEHeader->Signature == IMAGE_NT_SIGNATURE)
|
||||||
|
{
|
||||||
|
debug("Image - PE");
|
||||||
|
return BinaryType::BinTypePE;
|
||||||
|
}
|
||||||
|
else if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE)
|
||||||
|
{
|
||||||
|
debug("Image - NE");
|
||||||
|
return BinaryType::BinTypeNE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debug("Image - MZ");
|
||||||
|
return BinaryType::BinTypeMZ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ... */
|
||||||
|
return BinaryType::BinTypeUnknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryType GetBinaryType(char *Path)
|
||||||
|
{
|
||||||
|
BinaryType Type = BinaryType::BinTypeInvalid;
|
||||||
|
VirtualFileSystem::File ExFile = vfs->Open(Path);
|
||||||
|
|
||||||
|
if (!ExFile.IsOK())
|
||||||
|
{
|
||||||
|
vfs->Close(ExFile);
|
||||||
|
return Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("File opened: %s", Path);
|
||||||
|
uint8_t *Buffer = new uint8_t[1024];
|
||||||
|
vfs->Read(ExFile, Buffer, 128);
|
||||||
|
|
||||||
|
Fex *FexHdr = (Fex *)Buffer;
|
||||||
|
Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)Buffer;
|
||||||
|
IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)Buffer;
|
||||||
|
|
||||||
|
/* Check Fex header. */
|
||||||
|
if (FexHdr->Magic[0] == 'F' &&
|
||||||
|
FexHdr->Magic[1] == 'E' &&
|
||||||
|
FexHdr->Magic[2] == 'X' &&
|
||||||
|
FexHdr->Magic[3] == '\0')
|
||||||
|
{
|
||||||
|
/* If the fex type is driver, we shouldn't return as Fex. */
|
||||||
|
if (FexHdr->Type == FexFormatType::FexFormatType_Executable)
|
||||||
|
{
|
||||||
|
debug("Image - Fex");
|
||||||
|
Type = BinaryType::BinTypeFex;
|
||||||
|
goto Success;
|
||||||
|
}
|
||||||
|
else if (FexHdr->Type == FexFormatType::FexFormatType_Driver)
|
||||||
|
{
|
||||||
|
fixme("Fex Driver is not supposed to be executed.");
|
||||||
|
/* TODO: Driver installation pop-up. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Check ELF header. */
|
||||||
|
else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 &&
|
||||||
|
ELFHeader->e_ident[EI_MAG1] == ELFMAG1 &&
|
||||||
|
ELFHeader->e_ident[EI_MAG2] == ELFMAG2 &&
|
||||||
|
ELFHeader->e_ident[EI_MAG3] == ELFMAG3)
|
||||||
|
{
|
||||||
|
debug("Image - ELF");
|
||||||
|
Type = BinaryType::BinTypeELF;
|
||||||
|
goto Success;
|
||||||
|
}
|
||||||
|
/* Check MZ header. */
|
||||||
|
else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE)
|
||||||
|
{
|
||||||
|
vfs->Seek(ExFile, MZHeader->e_lfanew, SEEK_SET);
|
||||||
|
vfs->Read(ExFile, Buffer, 512);
|
||||||
|
IMAGE_NT_HEADERS *PEHeader = (IMAGE_NT_HEADERS *)(((char *)Buffer) + MZHeader->e_lfanew);
|
||||||
|
IMAGE_OS2_HEADER *NEHeader = (IMAGE_OS2_HEADER *)(((char *)Buffer) + MZHeader->e_lfanew);
|
||||||
|
|
||||||
|
/* TODO: LE, EDOS */
|
||||||
|
if (PEHeader->Signature == IMAGE_NT_SIGNATURE)
|
||||||
|
{
|
||||||
|
debug("Image - PE");
|
||||||
|
Type = BinaryType::BinTypePE;
|
||||||
|
goto Success;
|
||||||
|
}
|
||||||
|
else if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE)
|
||||||
|
{
|
||||||
|
debug("Image - NE");
|
||||||
|
Type = BinaryType::BinTypeNE;
|
||||||
|
goto Success;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debug("Image - MZ");
|
||||||
|
Type = BinaryType::BinTypeMZ;
|
||||||
|
goto Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ... */
|
||||||
|
Type = BinaryType::BinTypeUnknown;
|
||||||
|
Success:
|
||||||
|
delete[] Buffer;
|
||||||
|
vfs->Close(ExFile);
|
||||||
|
return Type;
|
||||||
|
}
|
||||||
|
}
|
@ -1,288 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <exec.hpp>
|
|
||||||
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <msexec.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#include <abi.h>
|
|
||||||
|
|
||||||
#include "../../kernel.h"
|
|
||||||
#include "../../Fex.hpp"
|
|
||||||
|
|
||||||
using namespace Tasking;
|
|
||||||
using VirtualFileSystem::File;
|
|
||||||
using VirtualFileSystem::FileStatus;
|
|
||||||
using VirtualFileSystem::NodeFlags;
|
|
||||||
|
|
||||||
namespace Execute
|
|
||||||
{
|
|
||||||
struct InterpreterIPCDataLibrary
|
|
||||||
{
|
|
||||||
char Name[128];
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char Path[256];
|
|
||||||
void *ElfFile;
|
|
||||||
void *MemoryImage;
|
|
||||||
struct InterpreterIPCDataLibrary Libraries[64];
|
|
||||||
} InterpreterIPCData;
|
|
||||||
|
|
||||||
/* Passing arguments as a sanity check and debugging. */
|
|
||||||
void ELFInterpreterIPCThread(PCB *Process, char *Path, void *MemoryImage, void *ElfFile, std::vector<const char *> NeededLibraries)
|
|
||||||
{
|
|
||||||
debug("Interpreter thread started for %s", Path);
|
|
||||||
// Interpreter will create an IPC with token "LOAD".
|
|
||||||
char UniqueToken[16] = {'L', 'O', 'A', 'D', '\0'};
|
|
||||||
InterProcessCommunication::IPCHandle *Handle = nullptr;
|
|
||||||
while (Handle == nullptr)
|
|
||||||
{
|
|
||||||
debug("Searching for IPC with token %s", UniqueToken);
|
|
||||||
Handle = Process->IPC->SearchByToken(UniqueToken);
|
|
||||||
if (Handle == nullptr)
|
|
||||||
{
|
|
||||||
debug("Failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskManager->Sleep(200);
|
|
||||||
if (Handle == nullptr)
|
|
||||||
{
|
|
||||||
debug("Retrying...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug("IPC found, sending data...");
|
|
||||||
InterpreterIPCData *TmpBuffer = new InterpreterIPCData;
|
|
||||||
strcpy(TmpBuffer->Path, Path);
|
|
||||||
TmpBuffer->ElfFile = ElfFile;
|
|
||||||
TmpBuffer->MemoryImage = MemoryImage;
|
|
||||||
if (NeededLibraries.size() > 256)
|
|
||||||
warn("Too many libraries! (max 256)");
|
|
||||||
for (size_t i = 0; i < NeededLibraries.size(); i++)
|
|
||||||
{
|
|
||||||
strcpy(TmpBuffer->Libraries[i].Name, NeededLibraries[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
debug("OUTSIDE DATA");
|
|
||||||
debug("Path: %s", Path);
|
|
||||||
debug("ElfFile: %p", ElfFile);
|
|
||||||
debug("MemoryImage: %p", MemoryImage);
|
|
||||||
for (size_t i = 0; i < NeededLibraries.size(); i++)
|
|
||||||
{
|
|
||||||
debug("Library: %s", NeededLibraries[i]);
|
|
||||||
}
|
|
||||||
debug("INSIDE DATA");
|
|
||||||
debug("Path: %s", TmpBuffer->Path);
|
|
||||||
debug("ElfFile: %p", TmpBuffer->ElfFile);
|
|
||||||
debug("MemoryImage: %p", TmpBuffer->MemoryImage);
|
|
||||||
for (size_t i = 0; i < NeededLibraries.size(); i++)
|
|
||||||
{
|
|
||||||
debug("Library: %s", TmpBuffer->Libraries[i].Name);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RetryIPCWrite:
|
|
||||||
InterProcessCommunication::IPCErrorCode ret = Process->IPC->Write(Handle->ID, TmpBuffer, sizeof(InterpreterIPCData));
|
|
||||||
debug("Write returned %d", ret);
|
|
||||||
if (ret == InterProcessCommunication::IPCErrorCode::IPCNotListening)
|
|
||||||
{
|
|
||||||
debug("IPC not listening, retrying...");
|
|
||||||
TaskManager->Sleep(100);
|
|
||||||
goto RetryIPCWrite;
|
|
||||||
}
|
|
||||||
delete TmpBuffer;
|
|
||||||
/* Prevent race condition, maybe a
|
|
||||||
better idea is to watch when the
|
|
||||||
IPC is destroyed. */
|
|
||||||
TaskManager->Sleep(5000);
|
|
||||||
TEXIT(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
PCB *InterpreterTargetProcess;
|
|
||||||
std::string *InterpreterTargetPath; /* We can't have String as a constructor :( */
|
|
||||||
void *InterpreterMemoryImage;
|
|
||||||
void *InterpreterElfFile;
|
|
||||||
std::vector<const char *> InterpreterNeededLibraries;
|
|
||||||
void ELFInterpreterThreadWrapper()
|
|
||||||
{
|
|
||||||
ELFInterpreterIPCThread(InterpreterTargetProcess, (char *)InterpreterTargetPath->c_str(), InterpreterMemoryImage, InterpreterElfFile, InterpreterNeededLibraries);
|
|
||||||
delete InterpreterTargetPath, InterpreterTargetPath = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ELFBaseLoad ELFLoad(char *Path, const char **argv, const char **envp, Tasking::TaskCompatibility Compatibility)
|
|
||||||
{
|
|
||||||
/* We get the base name ("app.elf") */
|
|
||||||
const char *BaseName;
|
|
||||||
cwk_path_get_basename(Path, &BaseName, nullptr);
|
|
||||||
TaskArchitecture Arch = TaskArchitecture::UnknownArchitecture;
|
|
||||||
|
|
||||||
File ExFile = vfs->Open(Path);
|
|
||||||
|
|
||||||
if (ExFile.Status != FileStatus::OK)
|
|
||||||
{
|
|
||||||
vfs->Close(ExFile);
|
|
||||||
error("Failed to open file: %s", Path);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ExFile.node->Flags != NodeFlags::FILE)
|
|
||||||
{
|
|
||||||
vfs->Close(ExFile);
|
|
||||||
error("Invalid file path: %s", Path);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
else if (GetBinaryType(Path) != BinaryType::BinTypeELF)
|
|
||||||
{
|
|
||||||
vfs->Close(ExFile);
|
|
||||||
error("Invalid file type: %s", Path);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ExFileSize = ExFile.node->Length;
|
|
||||||
|
|
||||||
/* Allocate elf in memory */
|
|
||||||
void *ElfFile = KernelAllocator.RequestPages(TO_PAGES(ExFileSize + 1));
|
|
||||||
/* Copy the file to the allocated memory */
|
|
||||||
memcpy(ElfFile, (void *)ExFile.node->Address, ExFileSize);
|
|
||||||
debug("Elf file: %#lx - %#lx (length: %ld)", ElfFile, (uintptr_t)ElfFile + ExFileSize, ExFileSize);
|
|
||||||
|
|
||||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
|
|
||||||
|
|
||||||
switch (ELFHeader->e_machine)
|
|
||||||
{
|
|
||||||
case EM_386:
|
|
||||||
Arch = TaskArchitecture::x32;
|
|
||||||
break;
|
|
||||||
case EM_X86_64:
|
|
||||||
Arch = TaskArchitecture::x64;
|
|
||||||
break;
|
|
||||||
case EM_ARM:
|
|
||||||
Arch = TaskArchitecture::ARM32;
|
|
||||||
break;
|
|
||||||
case EM_AARCH64:
|
|
||||||
Arch = TaskArchitecture::ARM64;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This shouldn't be ignored
|
|
||||||
if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS32)
|
|
||||||
{
|
|
||||||
if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB)
|
|
||||||
fixme("ELF32 LSB");
|
|
||||||
else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB)
|
|
||||||
fixme("ELF32 MSB");
|
|
||||||
else
|
|
||||||
fixme("ELF32 Unknown");
|
|
||||||
}
|
|
||||||
else if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64)
|
|
||||||
{
|
|
||||||
if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB)
|
|
||||||
fixme("ELF64 LSB");
|
|
||||||
else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB)
|
|
||||||
fixme("ELF64 MSB");
|
|
||||||
else
|
|
||||||
fixme("ELF64 Unknown");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fixme("Unknown ELF");
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User, ElfFile);
|
|
||||||
Process->SetWorkingDirectory(vfs->GetNodeFromPath(Path)->Parent);
|
|
||||||
Memory::Virtual pV = Memory::Virtual(Process->PageTable);
|
|
||||||
for (size_t i = 0; i < TO_PAGES(ExFileSize); i++)
|
|
||||||
pV.Remap((void *)((uintptr_t)ElfFile + (i * PAGE_SIZE)), (void *)((uintptr_t)ElfFile + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
|
||||||
|
|
||||||
// for (size_t i = 0; i < TO_PAGES(ElfLazyResolverSize); i++)
|
|
||||||
// pV.Remap((void *)((uintptr_t)ElfLazyResolver + (i * PAGE_SIZE)), (void *)((uintptr_t)ElfLazyResolver + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
|
||||||
|
|
||||||
ELFBaseLoad bl;
|
|
||||||
|
|
||||||
switch (ELFHeader->e_type)
|
|
||||||
{
|
|
||||||
case ET_REL:
|
|
||||||
bl = ELFLoadRel(ElfFile, ExFile, Process);
|
|
||||||
break;
|
|
||||||
case ET_EXEC:
|
|
||||||
bl = ELFLoadExec(ElfFile, ExFile, Process);
|
|
||||||
break;
|
|
||||||
case ET_DYN:
|
|
||||||
bl = ELFLoadDyn(ElfFile, ExFile, Process);
|
|
||||||
break;
|
|
||||||
case ET_CORE:
|
|
||||||
{
|
|
||||||
fixme("ET_CORE not implemented");
|
|
||||||
TaskManager->RevertProcessCreation(Process);
|
|
||||||
vfs->Close(ExFile);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
case ET_NONE:
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
error("Unknown ELF Type: %d", ELFHeader->e_type);
|
|
||||||
vfs->Close(ExFile);
|
|
||||||
TaskManager->RevertProcessCreation(Process);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bl.Interpreter)
|
|
||||||
{
|
|
||||||
debug("ElfFile: %p ELFHeader: %p", ElfFile, ELFHeader);
|
|
||||||
|
|
||||||
InterpreterTargetProcess = Process;
|
|
||||||
InterpreterTargetPath = new std::string(Path); /* We store in a String because Path may get changed while outside ELFLoad(). */
|
|
||||||
InterpreterMemoryImage = bl.VirtualMemoryImage;
|
|
||||||
InterpreterElfFile = ElfFile;
|
|
||||||
InterpreterNeededLibraries = bl.NeededLibraries;
|
|
||||||
__sync;
|
|
||||||
TCB *InterpreterIPCThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)ELFInterpreterThreadWrapper);
|
|
||||||
InterpreterIPCThread->Rename("ELF Interpreter IPC Thread");
|
|
||||||
InterpreterIPCThread->SetPriority(TaskPriority::Low);
|
|
||||||
}
|
|
||||||
|
|
||||||
TCB *Thread = TaskManager->CreateThread(Process,
|
|
||||||
bl.InstructionPointer,
|
|
||||||
argv, envp, bl.auxv,
|
|
||||||
(IPOffset)0 /* ProgramHeader->p_offset */, // I guess I don't need this
|
|
||||||
Arch,
|
|
||||||
Compatibility);
|
|
||||||
|
|
||||||
foreach (Memory::MemMgr::AllocatedPages p in bl.TmpMem->GetAllocatedPagesList())
|
|
||||||
{
|
|
||||||
Thread->Memory->Add(p.Address, p.PageCount);
|
|
||||||
bl.TmpMem->DetachAddress(p.Address);
|
|
||||||
}
|
|
||||||
delete bl.TmpMem, bl.TmpMem = nullptr;
|
|
||||||
|
|
||||||
bl.sd.Process = Process;
|
|
||||||
bl.sd.Thread = Thread;
|
|
||||||
bl.sd.Status = ExStatus::OK;
|
|
||||||
vfs->Close(ExFile);
|
|
||||||
return bl;
|
|
||||||
}
|
|
||||||
}
|
|
187
Execute/Elf/ElfBaseLoad.cpp
Normal file
187
Execute/Elf/ElfBaseLoad.cpp
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <exec.hpp>
|
||||||
|
|
||||||
|
#include <memory.hpp>
|
||||||
|
#include <lock.hpp>
|
||||||
|
#include <msexec.h>
|
||||||
|
#include <cwalk.h>
|
||||||
|
#include <elf.h>
|
||||||
|
#include <abi.h>
|
||||||
|
|
||||||
|
#include "../../kernel.h"
|
||||||
|
#include "../../Fex.hpp"
|
||||||
|
|
||||||
|
using namespace Tasking;
|
||||||
|
using VirtualFileSystem::File;
|
||||||
|
using VirtualFileSystem::FileStatus;
|
||||||
|
using VirtualFileSystem::NodeFlags;
|
||||||
|
|
||||||
|
namespace Execute
|
||||||
|
{
|
||||||
|
ELFBaseLoad ELFLoad(char *Path,
|
||||||
|
const char **argv, const char **envp,
|
||||||
|
TaskCompatibility Compatibility)
|
||||||
|
{
|
||||||
|
const char *BaseName;
|
||||||
|
cwk_path_get_basename(Path, &BaseName, nullptr);
|
||||||
|
TaskArchitecture Arch = TaskArchitecture::UnknownArchitecture;
|
||||||
|
|
||||||
|
File ExFile = vfs->Open(Path);
|
||||||
|
|
||||||
|
if (ExFile.Status != FileStatus::OK)
|
||||||
|
{
|
||||||
|
vfs->Close(ExFile);
|
||||||
|
error("Failed to open file: %s", Path);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
else if (ExFile.GetFlags() != NodeFlags::FILE)
|
||||||
|
{
|
||||||
|
vfs->Close(ExFile);
|
||||||
|
error("Invalid file path: %s", Path);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
else if (GetBinaryType(Path) != BinaryType::BinTypeELF)
|
||||||
|
{
|
||||||
|
vfs->Close(ExFile);
|
||||||
|
error("Invalid file type: %s", Path);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ExFileSize = ExFile.GetLength();
|
||||||
|
|
||||||
|
void *ElfFile = KernelAllocator.RequestPages(TO_PAGES(ExFileSize + 1));
|
||||||
|
vfs->Read(ExFile, (uint8_t *)ElfFile, ExFileSize);
|
||||||
|
debug("Loaded elf %s at %#lx with the length of %ld",
|
||||||
|
Path, ElfFile, ExFileSize);
|
||||||
|
|
||||||
|
Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)ElfFile;
|
||||||
|
|
||||||
|
switch (ELFHeader->e_machine)
|
||||||
|
{
|
||||||
|
case EM_386:
|
||||||
|
Arch = TaskArchitecture::x32;
|
||||||
|
break;
|
||||||
|
case EM_X86_64:
|
||||||
|
Arch = TaskArchitecture::x64;
|
||||||
|
break;
|
||||||
|
case EM_ARM:
|
||||||
|
Arch = TaskArchitecture::ARM32;
|
||||||
|
break;
|
||||||
|
case EM_AARCH64:
|
||||||
|
Arch = TaskArchitecture::ARM64;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This shouldn't be ignored
|
||||||
|
if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS32)
|
||||||
|
fixme("32-bit ELF");
|
||||||
|
else if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64)
|
||||||
|
fixme("64-bit ELF");
|
||||||
|
else
|
||||||
|
fixme("Unknown class %d", ELFHeader->e_ident[EI_CLASS]);
|
||||||
|
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
|
if (ELFHeader->e_ident[EI_DATA] != ELFDATA2LSB)
|
||||||
|
{
|
||||||
|
fixme("ELF32 LSB expected, got %d", ELFHeader->e_ident[EI_DATA]);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (ELFHeader->e_ident[EI_DATA] != ELFDATA2MSB)
|
||||||
|
{
|
||||||
|
fixme("ELF32 MSB expected, got %d", ELFHeader->e_ident[EI_DATA]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(),
|
||||||
|
BaseName, TaskTrustLevel::User, ElfFile);
|
||||||
|
Process->SetWorkingDirectory(vfs->GetNodeFromPath(Path)->Parent);
|
||||||
|
Process->Info.Compatibility = TaskCompatibility::Native;
|
||||||
|
Process->Info.Architecture = TaskArchitecture::x64;
|
||||||
|
|
||||||
|
ELFBaseLoad bl;
|
||||||
|
|
||||||
|
ELFObject *obj = new ELFObject(Path, Process);
|
||||||
|
if (!obj->IsValid())
|
||||||
|
{
|
||||||
|
error("Failed to load ELF object");
|
||||||
|
vfs->Close(ExFile);
|
||||||
|
TaskManager->RevertProcessCreation(Process);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bl = obj->GetBaseLoadInfo();
|
||||||
|
|
||||||
|
/* TODO: Keep only the necessary headers */
|
||||||
|
Memory::Virtual vmm = Memory::Virtual(Process->PageTable);
|
||||||
|
for (size_t i = 0; i < TO_PAGES(ExFileSize); i++)
|
||||||
|
{
|
||||||
|
void *AddressToMap = (void *)((uintptr_t)ElfFile + (i * PAGE_SIZE));
|
||||||
|
vmm.Remap(AddressToMap, AddressToMap, Memory::RW | Memory::US);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bl.Interpreter)
|
||||||
|
{
|
||||||
|
debug("Keeping ElfFile at %p", ElfFile);
|
||||||
|
|
||||||
|
TCB *InterIPCThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(),
|
||||||
|
(IP)ELFInterpreterIPCThread,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
std::vector<AuxiliaryVector>(),
|
||||||
|
TaskArchitecture::x64,
|
||||||
|
TaskCompatibility::Native,
|
||||||
|
true);
|
||||||
|
|
||||||
|
std::vector<const char *> *tmp_needed_libs =
|
||||||
|
new std::vector<const char *>(bl.NeededLibraries);
|
||||||
|
|
||||||
|
InterIPCThread->SYSV_ABI_Call((uintptr_t)Process,
|
||||||
|
(uintptr_t) new std::string(Path),
|
||||||
|
(uintptr_t)bl.VirtualMemoryImage,
|
||||||
|
(uintptr_t)tmp_needed_libs);
|
||||||
|
|
||||||
|
InterIPCThread->Rename("ELF Interpreter IPC Thread");
|
||||||
|
InterIPCThread->SetPriority(TaskPriority::Low);
|
||||||
|
InterIPCThread->Status = TaskStatus::Ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
TCB *Thread = TaskManager->CreateThread(Process,
|
||||||
|
bl.InstructionPointer,
|
||||||
|
argv, envp, bl.auxv,
|
||||||
|
Arch,
|
||||||
|
Compatibility);
|
||||||
|
|
||||||
|
foreach (Memory::MemMgr::AllocatedPages p in bl.TmpMem->GetAllocatedPagesList())
|
||||||
|
{
|
||||||
|
Thread->Memory->Add(p.Address, p.PageCount);
|
||||||
|
bl.TmpMem->DetachAddress(p.Address);
|
||||||
|
}
|
||||||
|
delete bl.TmpMem, bl.TmpMem = nullptr;
|
||||||
|
|
||||||
|
bl.sd.Process = Process;
|
||||||
|
bl.sd.Thread = Thread;
|
||||||
|
bl.sd.Status = ExStatus::OK;
|
||||||
|
vfs->Close(ExFile);
|
||||||
|
return bl;
|
||||||
|
}
|
||||||
|
}
|
155
Execute/Elf/ElfInterpreter.cpp
Normal file
155
Execute/Elf/ElfInterpreter.cpp
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <exec.hpp>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "../../kernel.h"
|
||||||
|
|
||||||
|
using namespace Tasking;
|
||||||
|
|
||||||
|
namespace Execute
|
||||||
|
{
|
||||||
|
struct InterpreterIPCDataLibrary
|
||||||
|
{
|
||||||
|
char Name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char Path[256];
|
||||||
|
void *MemoryImage;
|
||||||
|
struct InterpreterIPCDataLibrary Libraries[64];
|
||||||
|
} InterpreterIPCData;
|
||||||
|
|
||||||
|
void ELFInterpreterIPCThread(PCB *TargetProcess,
|
||||||
|
std::string *TargetPath,
|
||||||
|
void *MemoryImage,
|
||||||
|
std::vector<const char *> *_NeededLibraries)
|
||||||
|
{
|
||||||
|
std::vector<const char *> NeededLibraries = *_NeededLibraries;
|
||||||
|
delete _NeededLibraries;
|
||||||
|
|
||||||
|
debug("Interpreter thread started for %s", TargetPath->c_str());
|
||||||
|
// Interpreter will create an IPC with token "LOAD".
|
||||||
|
char UniqueToken[16] = {'L', 'O', 'A', 'D', '\0'};
|
||||||
|
InterProcessCommunication::IPCHandle *Handle = nullptr;
|
||||||
|
while (Handle == nullptr)
|
||||||
|
{
|
||||||
|
debug("Searching for IPC with token %s", UniqueToken);
|
||||||
|
Handle = TargetProcess->IPC->SearchByToken(UniqueToken);
|
||||||
|
if (Handle == nullptr)
|
||||||
|
debug("Failed");
|
||||||
|
|
||||||
|
TaskManager->Sleep(200);
|
||||||
|
if (Handle == nullptr)
|
||||||
|
debug("Retrying...");
|
||||||
|
}
|
||||||
|
debug("IPC found, sending data...");
|
||||||
|
InterpreterIPCData *TmpBuffer = new InterpreterIPCData;
|
||||||
|
strncpy(TmpBuffer->Path, TargetPath->c_str(), sizeof(TmpBuffer->Path) - 1);
|
||||||
|
TmpBuffer->MemoryImage = MemoryImage;
|
||||||
|
size_t NeededLibsSize = NeededLibraries.size();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < NeededLibsSize; i++)
|
||||||
|
strncpy(TmpBuffer->Libraries[i].Name, NeededLibraries[i],
|
||||||
|
sizeof(TmpBuffer->Libraries[i].Name) - 1);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
debug("Input:");
|
||||||
|
debug("Path: %s", TargetPath->c_str());
|
||||||
|
debug("MemoryImage: %p", MemoryImage);
|
||||||
|
for (size_t i = 0; i < NeededLibsSize; i++)
|
||||||
|
debug("Library: %s", NeededLibraries[i]);
|
||||||
|
|
||||||
|
debug("Buffer:");
|
||||||
|
debug("Path: %s", TmpBuffer->Path);
|
||||||
|
debug("MemoryImage: %p", TmpBuffer->MemoryImage);
|
||||||
|
for (size_t i = 0; i < 64; i++)
|
||||||
|
{
|
||||||
|
if (TmpBuffer->Libraries[i].Name[0] != '\0')
|
||||||
|
break;
|
||||||
|
debug("Library: %s", TmpBuffer->Libraries[i].Name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RetryIPCWrite:
|
||||||
|
InterProcessCommunication::IPCErrorCode ret =
|
||||||
|
TargetProcess->IPC->Write(Handle->ID, TmpBuffer, sizeof(InterpreterIPCData));
|
||||||
|
debug("Write returned %d", ret);
|
||||||
|
if (ret == InterProcessCommunication::IPCErrorCode::IPCNotListening)
|
||||||
|
{
|
||||||
|
debug("IPC not listening, retrying...");
|
||||||
|
TaskManager->Sleep(100);
|
||||||
|
goto RetryIPCWrite;
|
||||||
|
}
|
||||||
|
delete TmpBuffer;
|
||||||
|
|
||||||
|
while (!TargetProcess->IPC->SearchByToken(UniqueToken))
|
||||||
|
TaskManager->Schedule();
|
||||||
|
|
||||||
|
debug("Interpreter thread finished for %s", TargetPath->c_str());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < NeededLibsSize; i++)
|
||||||
|
delete[] NeededLibraries[i];
|
||||||
|
|
||||||
|
delete TargetPath;
|
||||||
|
TEXIT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t LoadELFInterpreter(Memory::MemMgr *mem, Memory::Virtual &vmm, const char *Interpreter)
|
||||||
|
{
|
||||||
|
if (GetBinaryType((char *)Interpreter) != BinaryType::BinTypeELF)
|
||||||
|
{
|
||||||
|
error("Interpreter \"%s\" is not an ELF file.", Interpreter);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No need to check if it's valid because
|
||||||
|
the function that calls this already checks it. */
|
||||||
|
VirtualFileSystem::File ElfFile = vfs->Open(Interpreter);
|
||||||
|
|
||||||
|
Elf64_Ehdr ELFHeader;
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||||
|
debug("Interpreter type: %#x", ELFHeader.e_type);
|
||||||
|
|
||||||
|
uintptr_t BaseAddress;
|
||||||
|
size_t ElfPHDRsSize;
|
||||||
|
|
||||||
|
GetBaseAndSize(ElfFile, BaseAddress, ElfPHDRsSize);
|
||||||
|
MmImage MemoryImage = ELFCreateMemoryImage(mem, vmm, ElfFile, ElfPHDRsSize);
|
||||||
|
CopyLOADSegments(ElfFile, BaseAddress, (uintptr_t)MemoryImage.Physical);
|
||||||
|
vfs->Close(ElfFile);
|
||||||
|
|
||||||
|
bool IsPIC = ELFHeader.e_type == ET_DYN;
|
||||||
|
debug("Elf %s PIC", IsPIC ? "is" : "is not");
|
||||||
|
|
||||||
|
if (IsPIC)
|
||||||
|
{
|
||||||
|
debug("Interpreter entry point: %#lx (%#lx + %#lx)",
|
||||||
|
(uintptr_t)MemoryImage.Physical + ELFHeader.e_entry,
|
||||||
|
(uintptr_t)MemoryImage.Physical, ELFHeader.e_entry);
|
||||||
|
|
||||||
|
return (uintptr_t)MemoryImage.Physical + ELFHeader.e_entry;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debug("Interpreter entry point: %#lx", ELFHeader.e_entry);
|
||||||
|
return ELFHeader.e_entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
480
Execute/Elf/ElfLoader.cpp
Normal file
480
Execute/Elf/ElfLoader.cpp
Normal file
@ -0,0 +1,480 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <exec.hpp>
|
||||||
|
|
||||||
|
#include <memory.hpp>
|
||||||
|
#include <lock.hpp>
|
||||||
|
#include <msexec.h>
|
||||||
|
#include <cwalk.h>
|
||||||
|
#include <elf.h>
|
||||||
|
#include <abi.h>
|
||||||
|
|
||||||
|
#include "../../kernel.h"
|
||||||
|
#include "../../Fex.hpp"
|
||||||
|
|
||||||
|
using namespace Tasking;
|
||||||
|
using namespace VirtualFileSystem;
|
||||||
|
|
||||||
|
namespace Execute
|
||||||
|
{
|
||||||
|
ELFBaseLoad ELFObject::LoadExec_x86_32(File &ElfFile, PCB *TargetProcess)
|
||||||
|
{
|
||||||
|
stub;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
ELFBaseLoad ELFObject::LoadExec_x86_64(File &ElfFile, PCB *TargetProcess)
|
||||||
|
{
|
||||||
|
ELFBaseLoad ELFBase{};
|
||||||
|
|
||||||
|
uintptr_t BaseAddress;
|
||||||
|
size_t ElfPHDRsSize;
|
||||||
|
GetBaseAndSize(ElfFile, BaseAddress, ElfPHDRsSize);
|
||||||
|
|
||||||
|
Elf64_Ehdr ELFHeader;
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||||
|
uintptr_t EntryPoint = ELFHeader.e_entry;
|
||||||
|
debug("%s's entry point is %#lx", ElfFile.Name, EntryPoint);
|
||||||
|
|
||||||
|
ELFBase.TmpMem = new Memory::MemMgr(TargetProcess->PageTable); /* This should be deleted inside BaseLoad.cpp */
|
||||||
|
Memory::Virtual vmm(TargetProcess->PageTable);
|
||||||
|
|
||||||
|
/* If required, MemoryImage will be at virtual address. (unless is PIC)
|
||||||
|
tl;dr this is where the code is stored. */
|
||||||
|
MmImage MemoryImage = ELFCreateMemoryImage(ELFBase.TmpMem, vmm, ElfFile, ElfPHDRsSize);
|
||||||
|
|
||||||
|
debug("Solving symbols for %s", ElfFile.Name);
|
||||||
|
std::vector<Elf64_Shdr> DynamicString = ELFGetSections_x86_64(ElfFile, ".dynstr");
|
||||||
|
std::vector<Elf64_Shdr> StringTable = ELFGetSections_x86_64(ElfFile, ".strtab");
|
||||||
|
|
||||||
|
if (DynamicString.size() < 1) /* TODO: check if this is required */
|
||||||
|
DynamicString = StringTable;
|
||||||
|
|
||||||
|
/* Calculate entry point */
|
||||||
|
Elf64_Phdr FirstPhdr;
|
||||||
|
vfs->Seek(ElfFile, ELFHeader.e_phoff, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&FirstPhdr, sizeof(Elf64_Phdr));
|
||||||
|
/* FIXME: this is not the correct way to calculate entry point */
|
||||||
|
if (FirstPhdr.p_vaddr == 0)
|
||||||
|
{
|
||||||
|
debug("Entry point is null. Adding virtual address to entry point");
|
||||||
|
EntryPoint += (uintptr_t)MemoryImage.Virtual;
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyLOADSegments(ElfFile, BaseAddress, (uintptr_t)MemoryImage.Physical);
|
||||||
|
|
||||||
|
foreach (auto Tag in ELFGetDynamicTag_x86_64(ElfFile, DT_NEEDED))
|
||||||
|
{
|
||||||
|
const char *ReqLib = new char[256];
|
||||||
|
vfs->Seek(ElfFile, DynamicString[0].sh_offset + Tag.d_un.d_val, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)ReqLib, 256);
|
||||||
|
|
||||||
|
debug("DT_NEEDED - %s", ReqLib);
|
||||||
|
ELFBase.NeededLibraries.push_back(ReqLib);
|
||||||
|
}
|
||||||
|
|
||||||
|
char InterpreterPath[256] = {'\0'};
|
||||||
|
std::vector<Elf64_Phdr> PhdrINTERP = ELFGetSymbolType_x86_64(ElfFile, PT_INTERP);
|
||||||
|
foreach (auto Interp in PhdrINTERP)
|
||||||
|
{
|
||||||
|
const char *InterpPath = new char[256];
|
||||||
|
vfs->Seek(ElfFile, Interp.p_offset, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)InterpPath, 256);
|
||||||
|
|
||||||
|
memcpy((void *)InterpreterPath, InterpPath,
|
||||||
|
(strlen(InterpPath) > 256) ? 256 : strlen(InterpPath));
|
||||||
|
debug("Interpreter: %s", InterpreterPath);
|
||||||
|
delete[] InterpPath;
|
||||||
|
|
||||||
|
VirtualFileSystem::File InterpreterFile = vfs->Open(InterpreterPath);
|
||||||
|
if (!InterpreterFile.IsOK())
|
||||||
|
{
|
||||||
|
warn("Failed to open interpreter file: %s", InterpreterPath);
|
||||||
|
vfs->Close(InterpreterFile);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (GetBinaryType(InterpreterPath) != BinTypeELF)
|
||||||
|
{
|
||||||
|
warn("Interpreter %s is not an ELF file", InterpreterPath);
|
||||||
|
vfs->Close(InterpreterFile);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vfs->Close(InterpreterFile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(InterpreterPath) > 1)
|
||||||
|
{
|
||||||
|
EntryPoint = LoadELFInterpreter(ELFBase.TmpMem, vmm, InterpreterPath);
|
||||||
|
ELFBase.Interpreter = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("Entry Point: %#lx", EntryPoint);
|
||||||
|
|
||||||
|
char *aux_platform = (char *)ELFBase.TmpMem->RequestPages(1, true); /* TODO: 4096 bytes is too much for this */
|
||||||
|
strcpy(aux_platform, "x86_64");
|
||||||
|
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)0 /* FIXME */}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)MemoryImage.Virtual}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader.e_phnum}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader.e_phentsize}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader.e_phoff}}});
|
||||||
|
|
||||||
|
ELFBase.InstructionPointer = EntryPoint;
|
||||||
|
ELFBase.MemoryImage = MemoryImage.Physical;
|
||||||
|
ELFBase.VirtualMemoryImage = MemoryImage.Virtual;
|
||||||
|
|
||||||
|
ELFBase.Success = true;
|
||||||
|
return ELFBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
ELFBaseLoad ELFObject::LoadDyn_x86_32(File &ElfFile, PCB *TargetProcess, bool IsLibrary)
|
||||||
|
{
|
||||||
|
stub;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
ELFBaseLoad ELFObject::LoadDyn_x86_64(File &ElfFile, PCB *TargetProcess, bool IsLibrary)
|
||||||
|
{
|
||||||
|
ELFBaseLoad ELFBase{};
|
||||||
|
|
||||||
|
uintptr_t BaseAddress;
|
||||||
|
size_t ElfPHDRsSize;
|
||||||
|
GetBaseAndSize(ElfFile, BaseAddress, ElfPHDRsSize);
|
||||||
|
|
||||||
|
Elf64_Ehdr ELFHeader;
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||||
|
uintptr_t EntryPoint = ELFHeader.e_entry;
|
||||||
|
debug("%s's entry point is %#lx", ElfFile.Name, EntryPoint);
|
||||||
|
|
||||||
|
ELFBase.TmpMem = new Memory::MemMgr(TargetProcess->PageTable); /* This should be deleted inside BaseLoad.cpp */
|
||||||
|
Memory::Virtual vmm(TargetProcess->PageTable);
|
||||||
|
|
||||||
|
/* If required, MemoryImage will be at virtual address. (unless is PIC)
|
||||||
|
tl;dr this is where the code is stored. */
|
||||||
|
MmImage MemoryImage = ELFCreateMemoryImage(ELFBase.TmpMem, vmm, ElfFile, ElfPHDRsSize);
|
||||||
|
|
||||||
|
debug("Solving symbols for %s", ElfFile.Name);
|
||||||
|
std::vector<Elf64_Shdr> DynamicString = ELFGetSections_x86_64(ElfFile, ".dynstr");
|
||||||
|
std::vector<Elf64_Shdr> StringTable = ELFGetSections_x86_64(ElfFile, ".strtab");
|
||||||
|
|
||||||
|
if (DynamicString.size() < 1) /* TODO: check if this is required */
|
||||||
|
DynamicString = StringTable;
|
||||||
|
|
||||||
|
/* Calculate entry point */
|
||||||
|
Elf64_Phdr FirstPhdr;
|
||||||
|
vfs->Seek(ElfFile, ELFHeader.e_phoff, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&FirstPhdr, sizeof(Elf64_Phdr));
|
||||||
|
/* FIXME: this is not the correct way to calculate entry point */
|
||||||
|
if (FirstPhdr.p_vaddr == 0)
|
||||||
|
{
|
||||||
|
debug("Entry point is null. Adding virtual address to entry point");
|
||||||
|
EntryPoint += (uintptr_t)MemoryImage.Virtual;
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyLOADSegments(ElfFile, BaseAddress, (uintptr_t)MemoryImage.Physical);
|
||||||
|
|
||||||
|
foreach (auto Tag in ELFGetDynamicTag_x86_64(ElfFile, DT_NEEDED))
|
||||||
|
{
|
||||||
|
const char *ReqLib = new char[256];
|
||||||
|
vfs->Seek(ElfFile, DynamicString[0].sh_offset + Tag.d_un.d_val, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)ReqLib, 256);
|
||||||
|
|
||||||
|
debug("DT_NEEDED - %s", ReqLib);
|
||||||
|
ELFBase.NeededLibraries.push_back(ReqLib);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Elf64_Dyn> JmpRel = ELFGetDynamicTag_x86_64(ElfFile, DT_JMPREL);
|
||||||
|
std::vector<Elf64_Dyn> SymTab = ELFGetDynamicTag_x86_64(ElfFile, DT_SYMTAB);
|
||||||
|
std::vector<Elf64_Dyn> StrTab = ELFGetDynamicTag_x86_64(ElfFile, DT_STRTAB);
|
||||||
|
|
||||||
|
if (JmpRel.size() < 1)
|
||||||
|
{
|
||||||
|
debug("No DT_JMPREL");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SymTab.size() < 1)
|
||||||
|
{
|
||||||
|
debug("No DT_SYMTAB");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrTab.size() < 1)
|
||||||
|
{
|
||||||
|
debug("No DT_STRTAB");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JmpRel.size() > 1 &&
|
||||||
|
SymTab.size() > 1 &&
|
||||||
|
StrTab.size() > 1)
|
||||||
|
{
|
||||||
|
debug("JmpRel: %#lx, SymTab: %#lx, StrTab: %#lx", JmpRel[0].d_un.d_ptr, SymTab[0].d_un.d_ptr, StrTab[0].d_un.d_ptr);
|
||||||
|
Elf64_Rela *_JmpRel = (Elf64_Rela *)((uintptr_t)MemoryImage.Physical + (JmpRel[0].d_un.d_ptr - BaseAddress));
|
||||||
|
Elf64_Sym *_SymTab = (Elf64_Sym *)((uintptr_t)MemoryImage.Physical + (SymTab[0].d_un.d_ptr - BaseAddress));
|
||||||
|
|
||||||
|
char *_DynStr = (char *)((uintptr_t)MemoryImage.Physical + (StrTab[0].d_un.d_ptr - BaseAddress));
|
||||||
|
|
||||||
|
Elf64_Shdr *gotSection = nullptr;
|
||||||
|
Elf64_Shdr shdr;
|
||||||
|
for (Elf64_Half i = 0; i < ELFHeader.e_shnum; i++)
|
||||||
|
{
|
||||||
|
vfs->Seek(ElfFile, ELFHeader.e_shoff + i * sizeof(Elf64_Shdr), SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&shdr, sizeof(Elf64_Shdr));
|
||||||
|
if (shdr.sh_type == SHT_PROGBITS &&
|
||||||
|
(shdr.sh_flags & SHF_WRITE) &&
|
||||||
|
(shdr.sh_flags & SHF_ALLOC))
|
||||||
|
{
|
||||||
|
gotSection = new Elf64_Shdr;
|
||||||
|
*gotSection = shdr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gotSection)
|
||||||
|
{
|
||||||
|
Elf64_Xword numEntries = gotSection->sh_size / sizeof(Elf64_Addr);
|
||||||
|
for (Elf64_Xword i = 0; i < numEntries - 3; i++)
|
||||||
|
{
|
||||||
|
Elf64_Rela *Rel = _JmpRel + i;
|
||||||
|
Elf64_Addr *GOTEntry = (Elf64_Addr *)(Rel->r_offset + (uintptr_t)MemoryImage.Physical);
|
||||||
|
|
||||||
|
Elf64_Xword RelType = ELF64_R_TYPE(Rel->r_info);
|
||||||
|
debug("r_offset: %#lx RelType: %d", Rel->r_offset, RelType);
|
||||||
|
|
||||||
|
switch (RelType)
|
||||||
|
{
|
||||||
|
case R_X86_64_NONE:
|
||||||
|
break;
|
||||||
|
case R_X86_64_JUMP_SLOT:
|
||||||
|
{
|
||||||
|
Elf64_Xword SymIndex = ELF64_R_SYM(Rel->r_info);
|
||||||
|
Elf64_Sym *Sym = _SymTab + SymIndex;
|
||||||
|
|
||||||
|
if (Sym->st_name)
|
||||||
|
{
|
||||||
|
char *SymName = _DynStr + Sym->st_name;
|
||||||
|
debug("SymName: %s", SymName);
|
||||||
|
|
||||||
|
Elf64_Sym LibSym = ELFLookupSymbol(ElfFile, SymName);
|
||||||
|
|
||||||
|
if (LibSym.st_value)
|
||||||
|
{
|
||||||
|
*GOTEntry = (Elf64_Addr)((uintptr_t)MemoryImage.Physical + LibSym.st_value);
|
||||||
|
debug("GOT[%ld]: %#lx + %#lx = %#lx",
|
||||||
|
i, (uintptr_t)MemoryImage.Physical, LibSym.st_value, *GOTEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
fixme("RelType %d not supported", RelType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("GOT[%ld](%#lx): %#lx", i, GOTEntry, *GOTEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete gotSection;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debug("GOT section not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
foreach (auto Tag in ELFGetDynamicTag_x86_64(ElfFile, DT_NEEDED))
|
||||||
|
{
|
||||||
|
const char *ReqLib = new char[256];
|
||||||
|
vfs->Seek(ElfFile, DynamicString[0].sh_offset + Tag.d_un.d_val, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)ReqLib, 256);
|
||||||
|
|
||||||
|
debug("DT_NEEDED - %s", ReqLib);
|
||||||
|
ELFBase.NeededLibraries.push_back(ReqLib);
|
||||||
|
}
|
||||||
|
|
||||||
|
char InterpreterPath[256] = {'\0'};
|
||||||
|
std::vector<Elf64_Phdr> PhdrINTERP = ELFGetSymbolType_x86_64(ElfFile, PT_INTERP);
|
||||||
|
foreach (auto Interp in PhdrINTERP)
|
||||||
|
{
|
||||||
|
const char *InterpPath = new char[256];
|
||||||
|
vfs->Seek(ElfFile, Interp.p_offset, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)InterpPath, 256);
|
||||||
|
|
||||||
|
memcpy((void *)InterpreterPath, InterpPath,
|
||||||
|
(strlen(InterpPath) > 256) ? 256 : strlen(InterpPath));
|
||||||
|
debug("Interpreter: %s", InterpreterPath);
|
||||||
|
delete[] InterpPath;
|
||||||
|
|
||||||
|
VirtualFileSystem::File InterpreterFile = vfs->Open(InterpreterPath);
|
||||||
|
if (!InterpreterFile.IsOK())
|
||||||
|
{
|
||||||
|
warn("Failed to open interpreter file: %s", InterpreterPath);
|
||||||
|
vfs->Close(InterpreterFile);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (GetBinaryType(InterpreterPath) != BinTypeELF)
|
||||||
|
{
|
||||||
|
warn("Interpreter %s is not an ELF file", InterpreterPath);
|
||||||
|
vfs->Close(InterpreterFile);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vfs->Close(InterpreterFile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(InterpreterPath) > 1)
|
||||||
|
{
|
||||||
|
EntryPoint = LoadELFInterpreter(ELFBase.TmpMem, vmm, InterpreterPath);
|
||||||
|
ELFBase.Interpreter = true;
|
||||||
|
}
|
||||||
|
else if (IsLibrary)
|
||||||
|
{
|
||||||
|
/* FIXME: Detect interpreter from current running process. */
|
||||||
|
EntryPoint = LoadELFInterpreter(ELFBase.TmpMem, vmm, "/lib/ld.so");
|
||||||
|
ELFBase.Interpreter = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("Entry Point: %#lx", EntryPoint);
|
||||||
|
|
||||||
|
char *aux_platform = (char *)ELFBase.TmpMem->RequestPages(1, true); /* TODO: 4096 bytes is too much for this */
|
||||||
|
strcpy(aux_platform, "x86_64");
|
||||||
|
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)0 /* FIXME */}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)MemoryImage.Virtual}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader.e_phnum}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader.e_phentsize}}});
|
||||||
|
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader.e_phoff}}});
|
||||||
|
|
||||||
|
ELFBase.InstructionPointer = EntryPoint;
|
||||||
|
ELFBase.MemoryImage = MemoryImage.Physical;
|
||||||
|
ELFBase.VirtualMemoryImage = MemoryImage.Virtual;
|
||||||
|
|
||||||
|
ELFBase.Success = true;
|
||||||
|
return ELFBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
ELFObject::ELFObject(char *AbsolutePath,
|
||||||
|
PCB *TargetProcess,
|
||||||
|
bool IsLibrary)
|
||||||
|
{
|
||||||
|
if (GetBinaryType(AbsolutePath) != BinaryType::BinTypeELF)
|
||||||
|
{
|
||||||
|
error("%s is not an ELF file or is invalid.", AbsolutePath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VirtualFileSystem::File ExFile = vfs->Open(AbsolutePath);
|
||||||
|
|
||||||
|
Elf32_Ehdr ELFHeader;
|
||||||
|
vfs->Read(ExFile, (uint8_t *)&ELFHeader, sizeof(Elf32_Ehdr));
|
||||||
|
|
||||||
|
ELFBaseLoad bl;
|
||||||
|
switch (ELFHeader.e_type)
|
||||||
|
{
|
||||||
|
case ET_REL:
|
||||||
|
{
|
||||||
|
fixme("ET_REL not implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_EXEC:
|
||||||
|
{
|
||||||
|
switch (ELFHeader.e_machine)
|
||||||
|
{
|
||||||
|
case EM_386:
|
||||||
|
this->BaseLoadInfo = this->LoadExec_x86_32(ExFile,
|
||||||
|
TargetProcess);
|
||||||
|
break;
|
||||||
|
case EM_X86_64:
|
||||||
|
this->BaseLoadInfo = this->LoadExec_x86_64(ExFile,
|
||||||
|
TargetProcess);
|
||||||
|
break;
|
||||||
|
case EM_ARM:
|
||||||
|
error("ARM is not supported yet!");
|
||||||
|
break;
|
||||||
|
case EM_AARCH64:
|
||||||
|
error("ARM64 is not supported yet!");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("Unknown architecture: %d", ELFHeader.e_machine);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_DYN:
|
||||||
|
{
|
||||||
|
switch (ELFHeader.e_machine)
|
||||||
|
{
|
||||||
|
case EM_386:
|
||||||
|
this->BaseLoadInfo = this->LoadDyn_x86_32(ExFile,
|
||||||
|
TargetProcess,
|
||||||
|
IsLibrary);
|
||||||
|
break;
|
||||||
|
case EM_X86_64:
|
||||||
|
this->BaseLoadInfo = this->LoadDyn_x86_64(ExFile,
|
||||||
|
TargetProcess,
|
||||||
|
IsLibrary);
|
||||||
|
break;
|
||||||
|
case EM_ARM:
|
||||||
|
error("ARM is not supported yet!");
|
||||||
|
break;
|
||||||
|
case EM_AARCH64:
|
||||||
|
error("ARM64 is not supported yet!");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("Unknown architecture: %d", ELFHeader.e_machine);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_CORE:
|
||||||
|
{
|
||||||
|
fixme("ET_CORE not implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_NONE:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
error("Unknown ELF Type: %d", ELFHeader.e_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vfs->Close(ExFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
ELFObject::~ELFObject()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
340
Execute/Elf/ElfParse.cpp
Normal file
340
Execute/Elf/ElfParse.cpp
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <exec.hpp>
|
||||||
|
|
||||||
|
#include <msexec.h>
|
||||||
|
|
||||||
|
#include "../../kernel.h"
|
||||||
|
#include "../../Fex.hpp"
|
||||||
|
|
||||||
|
namespace Execute
|
||||||
|
{
|
||||||
|
bool ELFIs64(void *Header)
|
||||||
|
{
|
||||||
|
Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)Header;
|
||||||
|
if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Originally from https://wiki.osdev.org/ELF_Tutorial */
|
||||||
|
|
||||||
|
Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header)
|
||||||
|
{
|
||||||
|
return (Elf64_Shdr *)((uintptr_t)Header + Header->e_shoff);
|
||||||
|
}
|
||||||
|
|
||||||
|
Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index)
|
||||||
|
{
|
||||||
|
return &GetELFSheader(Header)[Index];
|
||||||
|
}
|
||||||
|
|
||||||
|
char *GetELFStringTable(Elf64_Ehdr *Header)
|
||||||
|
{
|
||||||
|
if (Header->e_shstrndx == SHN_UNDEF)
|
||||||
|
return nullptr;
|
||||||
|
return (char *)Header + GetELFSection(Header, Header->e_shstrndx)->sh_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset)
|
||||||
|
{
|
||||||
|
char *StringTable = GetELFStringTable(Header);
|
||||||
|
if (StringTable == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
return StringTable + Offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name)
|
||||||
|
{
|
||||||
|
Elf64_Shdr *SymbolTable = nullptr;
|
||||||
|
Elf64_Shdr *StringTable = nullptr;
|
||||||
|
|
||||||
|
for (Elf64_Half i = 0; i < Header->e_shnum; i++)
|
||||||
|
{
|
||||||
|
Elf64_Shdr *shdr = GetELFSection(Header, i);
|
||||||
|
switch (shdr->sh_type)
|
||||||
|
{
|
||||||
|
case SHT_SYMTAB:
|
||||||
|
SymbolTable = shdr;
|
||||||
|
StringTable = GetELFSection(Header, shdr->sh_link);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SymbolTable == nullptr || StringTable == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < (SymbolTable->sh_size / sizeof(Elf64_Sym)); i++)
|
||||||
|
{
|
||||||
|
Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym)));
|
||||||
|
char *String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name);
|
||||||
|
if (strcmp(String, Name) == 0)
|
||||||
|
return Symbol;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Elf64_Sym ELFLookupSymbol(VirtualFileSystem::File &ElfFile, const char *Name)
|
||||||
|
{
|
||||||
|
off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR);
|
||||||
|
|
||||||
|
Elf64_Ehdr Header;
|
||||||
|
vfs->Seek(ElfFile, 0, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&Header, sizeof(Elf64_Ehdr));
|
||||||
|
|
||||||
|
Elf64_Shdr SymbolTable;
|
||||||
|
Elf64_Shdr StringTable;
|
||||||
|
|
||||||
|
for (Elf64_Half i = 0; i < Header.e_shnum; i++)
|
||||||
|
{
|
||||||
|
Elf64_Shdr shdr;
|
||||||
|
vfs->Seek(ElfFile, Header.e_shoff + (i * sizeof(Elf64_Shdr)), SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&shdr, sizeof(Elf64_Shdr));
|
||||||
|
|
||||||
|
switch (shdr.sh_type)
|
||||||
|
{
|
||||||
|
case SHT_SYMTAB:
|
||||||
|
SymbolTable = shdr;
|
||||||
|
vfs->Seek(ElfFile, Header.e_shoff + (shdr.sh_link * sizeof(Elf64_Shdr)), SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&StringTable, sizeof(Elf64_Shdr));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SymbolTable.sh_name == 0 ||
|
||||||
|
StringTable.sh_name == 0)
|
||||||
|
{
|
||||||
|
error("Symbol table not found.");
|
||||||
|
vfs->Seek(ElfFile, OldOffset, SEEK_SET);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < (SymbolTable.sh_size / sizeof(Elf64_Sym)); i++)
|
||||||
|
{
|
||||||
|
// Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym)));
|
||||||
|
Elf64_Sym Symbol;
|
||||||
|
vfs->Seek(ElfFile, SymbolTable.sh_offset + (i * sizeof(Elf64_Sym)), SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&Symbol, sizeof(Elf64_Sym));
|
||||||
|
|
||||||
|
// char *String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name);
|
||||||
|
char String[256];
|
||||||
|
vfs->Seek(ElfFile, StringTable.sh_offset + Symbol.st_name, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&String, 256);
|
||||||
|
|
||||||
|
if (strcmp(String, Name) == 0)
|
||||||
|
{
|
||||||
|
vfs->Seek(ElfFile, OldOffset, SEEK_SET);
|
||||||
|
return Symbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error("Symbol not found.");
|
||||||
|
vfs->Seek(ElfFile, OldOffset, SEEK_SET);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index)
|
||||||
|
{
|
||||||
|
#if defined(a64)
|
||||||
|
if (Table == SHN_UNDEF || Index == SHN_UNDEF)
|
||||||
|
return 0;
|
||||||
|
Elf64_Shdr *SymbolTable = GetELFSection(Header, Table);
|
||||||
|
|
||||||
|
uint64_t STEntries = SymbolTable->sh_size / SymbolTable->sh_entsize;
|
||||||
|
if (Index >= STEntries)
|
||||||
|
{
|
||||||
|
error("Symbol index out of range %d-%u.", Table, Index);
|
||||||
|
return 0xdead;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t SymbolAddress = (uint64_t)Header + SymbolTable->sh_offset;
|
||||||
|
Elf64_Sym *Symbol = &((Elf64_Sym *)SymbolAddress)[Index];
|
||||||
|
|
||||||
|
if (Symbol->st_shndx == SHN_UNDEF)
|
||||||
|
{
|
||||||
|
Elf64_Shdr *StringTable = GetELFSection(Header, SymbolTable->sh_link);
|
||||||
|
const char *Name = (const char *)Header + StringTable->sh_offset + Symbol->st_name;
|
||||||
|
|
||||||
|
void *Target = (void *)ELFLookupSymbol(Header, Name)->st_value;
|
||||||
|
if (Target == nullptr)
|
||||||
|
{
|
||||||
|
if (ELF64_ST_BIND(Symbol->st_info) & STB_WEAK)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error("Undefined external symbol \"%s\".", Name);
|
||||||
|
return 0xdead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return (uintptr_t)Target;
|
||||||
|
}
|
||||||
|
else if (Symbol->st_shndx == SHN_ABS)
|
||||||
|
return Symbol->st_value;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Elf64_Shdr *Target = GetELFSection(Header, Symbol->st_shndx);
|
||||||
|
return (uintptr_t)Header + Symbol->st_value + Target->sh_offset;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CopyLOADSegments(VirtualFileSystem::File &ElfFile, uintptr_t HdrsBase, uintptr_t PhysicalBase)
|
||||||
|
{
|
||||||
|
off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR);
|
||||||
|
|
||||||
|
Elf64_Ehdr ELFHeader;
|
||||||
|
vfs->Seek(ElfFile, 0, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||||
|
|
||||||
|
Elf64_Phdr ProgramHeaders;
|
||||||
|
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||||
|
{
|
||||||
|
vfs->Seek(ElfFile, ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr));
|
||||||
|
if (ProgramHeaders.p_type != PT_LOAD)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uintptr_t SegmentDestination = (ProgramHeaders.p_vaddr - HdrsBase) + PhysicalBase;
|
||||||
|
|
||||||
|
debug("Copying segment to %#lx (%ld file bytes, %ld mem bytes)",
|
||||||
|
SegmentDestination,
|
||||||
|
ProgramHeaders.p_filesz, ProgramHeaders.p_memsz);
|
||||||
|
|
||||||
|
if (ProgramHeaders.p_filesz > 0)
|
||||||
|
{
|
||||||
|
vfs->Seek(ElfFile, ProgramHeaders.p_offset, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)SegmentDestination, ProgramHeaders.p_filesz);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ProgramHeaders.p_memsz - ProgramHeaders.p_filesz > 0)
|
||||||
|
memset((void *)(SegmentDestination + ProgramHeaders.p_filesz),
|
||||||
|
0,
|
||||||
|
ProgramHeaders.p_memsz - ProgramHeaders.p_filesz);
|
||||||
|
}
|
||||||
|
|
||||||
|
vfs->Seek(ElfFile, OldOffset, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetBaseAndSize(VirtualFileSystem::File &ElfFile, uintptr_t &Base, size_t &Size)
|
||||||
|
{
|
||||||
|
Base = UINTPTR_MAX;
|
||||||
|
Size = 0;
|
||||||
|
|
||||||
|
off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR);
|
||||||
|
|
||||||
|
Elf64_Ehdr ELFHeader;
|
||||||
|
vfs->Seek(ElfFile, 0, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||||
|
|
||||||
|
Elf64_Phdr ProgramHeaders;
|
||||||
|
vfs->Seek(ElfFile, ELFHeader.e_phoff, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr));
|
||||||
|
|
||||||
|
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||||
|
{
|
||||||
|
Base = MIN(Base, ProgramHeaders.p_vaddr);
|
||||||
|
uintptr_t SegmentEnd = ProgramHeaders.p_vaddr - Base + ProgramHeaders.p_memsz;
|
||||||
|
Size = MAX(Size, SegmentEnd);
|
||||||
|
|
||||||
|
vfs->Seek(ElfFile, sizeof(Elf64_Phdr), SEEK_CUR);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr));
|
||||||
|
}
|
||||||
|
debug("Base: %#lx, Size: %#lx (%ld, %ld KB)", Base, Size, Size, TO_KB(Size));
|
||||||
|
vfs->Seek(ElfFile, OldOffset, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
MmImage ELFCreateMemoryImage(Memory::MemMgr *mem,
|
||||||
|
Memory::Virtual &vmm,
|
||||||
|
VirtualFileSystem::File &ElfFile,
|
||||||
|
size_t Length)
|
||||||
|
{
|
||||||
|
off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR);
|
||||||
|
|
||||||
|
void *MemoryImage = nullptr;
|
||||||
|
Elf64_Ehdr ELFHeader;
|
||||||
|
vfs->Seek(ElfFile, 0, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||||
|
|
||||||
|
bool IsPIC = ELFHeader.e_type == ET_DYN;
|
||||||
|
UNUSED(IsPIC);
|
||||||
|
debug("Elf %s PIC", IsPIC ? "is" : "is not");
|
||||||
|
|
||||||
|
bool FirstProgramHeader = false;
|
||||||
|
uintptr_t FirstProgramHeaderVirtualAddress = 0x0;
|
||||||
|
|
||||||
|
Elf64_Phdr ProgramHeaders;
|
||||||
|
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||||
|
{
|
||||||
|
vfs->Seek(ElfFile, ELFHeader.e_phoff + i * sizeof(Elf64_Phdr), SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr));
|
||||||
|
if (ProgramHeaders.p_type != PT_LOAD)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!FirstProgramHeader)
|
||||||
|
{
|
||||||
|
FirstProgramHeader = true;
|
||||||
|
FirstProgramHeaderVirtualAddress = ProgramHeaders.p_vaddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ProgramHeaders.p_vaddr == 0)
|
||||||
|
{
|
||||||
|
debug("p_vaddr is 0, allocating %ld pages for image (size: %#lx)", TO_PAGES(Length), Length);
|
||||||
|
MemoryImage = mem->RequestPages(TO_PAGES(Length), true);
|
||||||
|
debug("MemoryImage: %#lx-%#lx", MemoryImage, (uintptr_t)MemoryImage + Length);
|
||||||
|
memset(MemoryImage, 0, Length);
|
||||||
|
|
||||||
|
vfs->Seek(ElfFile, OldOffset, SEEK_SET);
|
||||||
|
return {MemoryImage, (void *)FirstProgramHeaderVirtualAddress};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("Allocating %ld pages for image (size: %#lx)", TO_PAGES(Length), Length);
|
||||||
|
MemoryImage = mem->RequestPages(TO_PAGES(Length));
|
||||||
|
debug("MemoryImage: %#lx-%#lx", MemoryImage, (uintptr_t)MemoryImage + Length);
|
||||||
|
memset(MemoryImage, 0, Length);
|
||||||
|
|
||||||
|
uintptr_t FirstProgramHeaderVirtualAddressAligned = 0;
|
||||||
|
|
||||||
|
if (FirstProgramHeaderVirtualAddress != 0)
|
||||||
|
{
|
||||||
|
FirstProgramHeaderVirtualAddressAligned = ALIGN_DOWN(FirstProgramHeaderVirtualAddress, PAGE_SIZE);
|
||||||
|
debug("Aligning address %#lx to %#lx",
|
||||||
|
FirstProgramHeaderVirtualAddress,
|
||||||
|
FirstProgramHeaderVirtualAddressAligned);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
FirstProgramHeaderVirtualAddress = (uintptr_t)MemoryImage;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < TO_PAGES(Length); i++)
|
||||||
|
{
|
||||||
|
vmm.Remap((void *)((uintptr_t)FirstProgramHeaderVirtualAddressAligned + (i * PAGE_SIZE)), (void *)((uintptr_t)MemoryImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||||
|
debug("Remapped: %#lx -> %#lx", (uintptr_t)FirstProgramHeaderVirtualAddressAligned + (i * PAGE_SIZE), (uintptr_t)MemoryImage + (i * PAGE_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
vfs->Seek(ElfFile, OldOffset, SEEK_SET);
|
||||||
|
return {MemoryImage, (void *)FirstProgramHeaderVirtualAddress};
|
||||||
|
}
|
||||||
|
}
|
@ -27,11 +27,11 @@ namespace Execute
|
|||||||
/* Originally from https://wiki.osdev.org/ELF_Tutorial */
|
/* Originally from https://wiki.osdev.org/ELF_Tutorial */
|
||||||
|
|
||||||
ELFBaseLoad ELFLoadRel(void *BaseImage,
|
ELFBaseLoad ELFLoadRel(void *BaseImage,
|
||||||
VirtualFileSystem::File &ExFile,
|
const char *Name,
|
||||||
Tasking::PCB *Process)
|
Tasking::PCB *Process)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
UNUSED(ExFile);
|
UNUSED(Name);
|
||||||
debug("Relocatable");
|
debug("Relocatable");
|
||||||
/* TODO: I have to fully implement this, but for now I will leave it as it is now. */
|
/* TODO: I have to fully implement this, but for now I will leave it as it is now. */
|
||||||
warn("Relocatable ELF is not fully supported yet");
|
warn("Relocatable ELF is not fully supported yet");
|
159
Execute/Elf/ElfSharedObjects.cpp
Normal file
159
Execute/Elf/ElfSharedObjects.cpp
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <exec.hpp>
|
||||||
|
|
||||||
|
#include <memory.hpp>
|
||||||
|
#include <lock.hpp>
|
||||||
|
#include <msexec.h>
|
||||||
|
#include <cwalk.h>
|
||||||
|
#include <elf.h>
|
||||||
|
#include <abi.h>
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#include <dumper.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../../kernel.h"
|
||||||
|
#include "../../Fex.hpp"
|
||||||
|
|
||||||
|
using namespace Tasking;
|
||||||
|
|
||||||
|
NewLock(ExecuteServiceLock);
|
||||||
|
|
||||||
|
namespace Execute
|
||||||
|
{
|
||||||
|
Memory::MemMgr *mem = nullptr;
|
||||||
|
std::vector<SharedLibrary> Libs;
|
||||||
|
|
||||||
|
void LibraryManagerService()
|
||||||
|
{
|
||||||
|
mem = new Memory::MemMgr;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
SmartLock(ExecuteServiceLock);
|
||||||
|
foreach (auto &Lib in Libs)
|
||||||
|
{
|
||||||
|
if (Lib.RefCount > 0)
|
||||||
|
{
|
||||||
|
Lib.Timeout = TimeManager->CalculateTarget(10, Time::Units::Minutes);
|
||||||
|
debug("Reset timeout for %s", Lib.Identifier);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (Lib.Timeout < TimeManager->GetCounter())
|
||||||
|
{
|
||||||
|
// TODO: Remove library from memory
|
||||||
|
fixme("Removed library %s because of timeout", Lib.Identifier);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debug("Timeout for %s is %ld", Lib.Identifier, Lib.Timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug("Waiting 10 seconds...");
|
||||||
|
}
|
||||||
|
TaskManager->Sleep(10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AddLibrary(char *Identifier,
|
||||||
|
VirtualFileSystem::File &ExFile,
|
||||||
|
const Memory::Virtual &vmm)
|
||||||
|
{
|
||||||
|
SmartLock(ExecuteServiceLock);
|
||||||
|
SharedLibrary sl;
|
||||||
|
|
||||||
|
foreach (auto lib in Libs)
|
||||||
|
{
|
||||||
|
if (strcmp(lib.Identifier, Identifier) == 0)
|
||||||
|
{
|
||||||
|
debug("Library %s already loaded", Identifier);
|
||||||
|
lib.RefCount++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PCB *Process = TaskManager->GetCurrentProcess();
|
||||||
|
ELFObject *obj = new ELFObject(vfs->GetPathFromNode(ExFile.GetNode()).get(), Process, true);
|
||||||
|
if (!obj->IsValid())
|
||||||
|
{
|
||||||
|
error("Failed to load dynamic ELF");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ELFBaseLoad bl = obj->GetBaseLoadInfo();
|
||||||
|
|
||||||
|
strncpy(sl.Identifier, Identifier, sizeof(sl.Identifier) - 1);
|
||||||
|
char *AbsolutePath = vfs->GetPathFromNode(ExFile.GetNode()).get();
|
||||||
|
strncpy(sl.Path, AbsolutePath, sizeof(sl.Path) - 1);
|
||||||
|
sl.Timeout = TimeManager->CalculateTarget(10, Time::Units::Minutes);
|
||||||
|
sl.RefCount = 0;
|
||||||
|
sl.MemoryImage = (uintptr_t)bl.MemoryImage;
|
||||||
|
sl.Length = ExFile.GetLength();
|
||||||
|
Libs.push_back(sl);
|
||||||
|
debug("Library %s loaded at %#lx", Identifier, sl.MemoryImage);
|
||||||
|
|
||||||
|
if (bl.InstructionPointer)
|
||||||
|
{
|
||||||
|
TCB *Thread = TaskManager->CreateThread(Process,
|
||||||
|
bl.InstructionPointer,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
bl.auxv,
|
||||||
|
Process->Info.Architecture,
|
||||||
|
Process->Info.Compatibility,
|
||||||
|
true);
|
||||||
|
Thread->Rename(Identifier);
|
||||||
|
Thread->Status = TaskStatus::Ready;
|
||||||
|
|
||||||
|
foreach (Memory::MemMgr::AllocatedPages p in bl.TmpMem->GetAllocatedPagesList())
|
||||||
|
{
|
||||||
|
Thread->Memory->Add(p.Address, p.PageCount);
|
||||||
|
bl.TmpMem->DetachAddress(p.Address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (Memory::MemMgr::AllocatedPages p in bl.TmpMem->GetAllocatedPagesList())
|
||||||
|
{
|
||||||
|
/* FIXME: MEMORY LEAK */
|
||||||
|
// Process->Memory->Add(p.Address, p.PageCount);
|
||||||
|
bl.TmpMem->DetachAddress(p.Address);
|
||||||
|
fixme("Potential memory leak. (%#lx - %ld)",
|
||||||
|
p.Address, p.PageCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedLibrary GetLibrary(char *Identifier)
|
||||||
|
{
|
||||||
|
SmartLock(ExecuteServiceLock);
|
||||||
|
foreach (auto Lib in Libs)
|
||||||
|
{
|
||||||
|
if (strcmp(Lib.Identifier, Identifier) == 0)
|
||||||
|
{
|
||||||
|
Lib.RefCount++;
|
||||||
|
debug("Library %s found at %#lx", Identifier, Lib.MemoryImage);
|
||||||
|
return Lib;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error("Library %s not found", Identifier);
|
||||||
|
return SharedLibrary();
|
||||||
|
}
|
||||||
|
}
|
@ -1,229 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <exec.hpp>
|
|
||||||
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <msexec.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#include <abi.h>
|
|
||||||
|
|
||||||
#include "../../kernel.h"
|
|
||||||
#include "../../Fex.hpp"
|
|
||||||
|
|
||||||
using namespace Tasking;
|
|
||||||
|
|
||||||
namespace Execute
|
|
||||||
{
|
|
||||||
ELFBaseLoad ELFLoadExec(void *ElfFile,
|
|
||||||
VirtualFileSystem::File &ExFile,
|
|
||||||
Tasking::PCB *Process)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
debug("Executable");
|
|
||||||
ELFBaseLoad ELFBase = {};
|
|
||||||
/* This should be deleted inside BaseLoad.cpp */
|
|
||||||
ELFBase.TmpMem = new Memory::MemMgr(Process->PageTable);
|
|
||||||
|
|
||||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
|
|
||||||
Memory::Virtual pV(Process->PageTable);
|
|
||||||
|
|
||||||
uintptr_t BaseAddress = UINTPTR_MAX;
|
|
||||||
uint64_t ElfAppSize = 0;
|
|
||||||
uintptr_t EntryPoint = ELFHeader->e_entry;
|
|
||||||
debug("%s's entry point is %#lx", ExFile.Name, EntryPoint);
|
|
||||||
|
|
||||||
Elf64_Phdr ItrPhdr;
|
|
||||||
|
|
||||||
/* Get base address */
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr,
|
|
||||||
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
|
||||||
sizeof(Elf64_Phdr));
|
|
||||||
|
|
||||||
BaseAddress = MIN(BaseAddress, ItrPhdr.p_vaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get size */
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr,
|
|
||||||
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
|
||||||
sizeof(Elf64_Phdr));
|
|
||||||
|
|
||||||
uintptr_t SegmentEnd;
|
|
||||||
SegmentEnd = ItrPhdr.p_vaddr - BaseAddress + ItrPhdr.p_memsz;
|
|
||||||
ElfAppSize = MAX(ElfAppSize, SegmentEnd);
|
|
||||||
}
|
|
||||||
debug("BaseAddress: %#lx | ElfAppSize: %#lx (%ld, %ld KB)", BaseAddress, ElfAppSize, ElfAppSize, TO_KB(ElfAppSize));
|
|
||||||
|
|
||||||
/* If required, MemoryImage will be at virtual address. (unless has PIE)
|
|
||||||
*
|
|
||||||
* tl;dr this is where the code is stored. */
|
|
||||||
MmImage MemoryImage = ELFCreateMemoryImage(ELFBase.TmpMem, pV, ElfFile, ElfAppSize);
|
|
||||||
|
|
||||||
debug("Solving symbols for address: %#llx", (uintptr_t)ElfFile);
|
|
||||||
Elf64_Shdr *ElfSections = (Elf64_Shdr *)((uintptr_t)ElfFile + ELFHeader->e_shoff);
|
|
||||||
Elf64_Shdr *DynamicString = nullptr;
|
|
||||||
Elf64_Shdr *StringTable = nullptr;
|
|
||||||
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_shnum; i++)
|
|
||||||
{
|
|
||||||
char *DynamicStringTable = (char *)((uintptr_t)ElfFile + ElfSections[ELFHeader->e_shstrndx].sh_offset + ElfSections[i].sh_name);
|
|
||||||
|
|
||||||
if (strcmp(DynamicStringTable, ".dynstr") == 0)
|
|
||||||
{
|
|
||||||
DynamicString = &ElfSections[i];
|
|
||||||
debug("Found .dynstr");
|
|
||||||
}
|
|
||||||
else if (strcmp(DynamicStringTable, ".strtab") == 0)
|
|
||||||
{
|
|
||||||
StringTable = &ElfSections[i];
|
|
||||||
debug("Found .strtab");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DynamicString)
|
|
||||||
DynamicString = StringTable;
|
|
||||||
|
|
||||||
/* Calculate entry point */
|
|
||||||
memcpy(&ItrPhdr, (uint8_t *)ElfFile + ELFHeader->e_phoff, sizeof(Elf64_Phdr));
|
|
||||||
if (ItrPhdr.p_vaddr == 0)
|
|
||||||
EntryPoint += (uintptr_t)MemoryImage.Virtual;
|
|
||||||
|
|
||||||
char InterpreterPath[256] = {'\0'};
|
|
||||||
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr,
|
|
||||||
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
|
||||||
sizeof(Elf64_Phdr));
|
|
||||||
|
|
||||||
switch (ItrPhdr.p_type)
|
|
||||||
{
|
|
||||||
case PT_NULL:
|
|
||||||
fixme("PT_NULL");
|
|
||||||
break;
|
|
||||||
case PT_LOAD:
|
|
||||||
{
|
|
||||||
debug("PT_LOAD - Offset: %#lx, VirtAddr: %#lx, FileSiz: %ld, MemSiz: %ld, Align: %#lx",
|
|
||||||
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
|
|
||||||
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
|
|
||||||
uintptr_t MAddr = (ItrPhdr.p_vaddr - BaseAddress) + (uintptr_t)MemoryImage.Physical;
|
|
||||||
fixme("Address: %#lx %s%s%s", MAddr,
|
|
||||||
(ItrPhdr.p_flags & PF_R) ? "R" : "",
|
|
||||||
(ItrPhdr.p_flags & PF_W) ? "W" : "",
|
|
||||||
(ItrPhdr.p_flags & PF_X) ? "X" : "");
|
|
||||||
|
|
||||||
memcpy((void *)MAddr, (uint8_t *)ElfFile + ItrPhdr.p_offset, ItrPhdr.p_filesz);
|
|
||||||
debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)ElfFile + ItrPhdr.p_offset, MAddr, ItrPhdr.p_filesz);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PT_DYNAMIC:
|
|
||||||
{
|
|
||||||
debug("PT_DYNAMIC - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx",
|
|
||||||
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
|
|
||||||
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
|
|
||||||
|
|
||||||
Elf64_Dyn *Dynamic = (Elf64_Dyn *)((uint8_t *)ElfFile + ItrPhdr.p_offset);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < ItrPhdr.p_filesz / sizeof(Elf64_Dyn); i++)
|
|
||||||
{
|
|
||||||
if (Dynamic[i].d_tag == DT_NEEDED)
|
|
||||||
{
|
|
||||||
if (!DynamicString)
|
|
||||||
{
|
|
||||||
error("DynamicString is null");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *ReqLib = (const char *)((uintptr_t)ElfFile + DynamicString->sh_offset + Dynamic[i].d_un.d_val);
|
|
||||||
debug("DT_NEEDED - Name[%ld]: %s", i, ReqLib);
|
|
||||||
ELFBase.NeededLibraries.push_back(ReqLib);
|
|
||||||
}
|
|
||||||
else if (Dynamic[i].d_tag == DT_NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PT_INTERP:
|
|
||||||
{
|
|
||||||
debug("PT_INTERP - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx",
|
|
||||||
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
|
|
||||||
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
|
|
||||||
|
|
||||||
memcpy((void *)InterpreterPath, (uint8_t *)ElfFile + ItrPhdr.p_offset, 256);
|
|
||||||
debug("Interpreter: %s", InterpreterPath);
|
|
||||||
|
|
||||||
VirtualFileSystem::File InterpreterFile = vfs->Open(InterpreterPath);
|
|
||||||
if (!InterpreterFile.IsOK())
|
|
||||||
warn("Failed to open interpreter file: %s", InterpreterPath);
|
|
||||||
|
|
||||||
vfs->Close(InterpreterFile);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* ... */
|
|
||||||
case PT_PHDR:
|
|
||||||
{
|
|
||||||
fixme("PT_PHDR - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx",
|
|
||||||
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
|
|
||||||
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
warn("Unknown or unsupported program header type: %d", ItrPhdr.p_type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen(InterpreterPath) > 1)
|
|
||||||
{
|
|
||||||
EntryPoint = LoadELFInterpreter(ELFBase.TmpMem, pV, InterpreterPath);
|
|
||||||
ELFBase.Interpreter = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug("Entry Point: %#lx", EntryPoint);
|
|
||||||
|
|
||||||
char *aux_platform = (char *)ELFBase.TmpMem->RequestPages(1, true);
|
|
||||||
strcpy(aux_platform, "x86_64");
|
|
||||||
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)vfs->GetPathFromNode(ExFile.node).get()}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)MemoryImage.Virtual}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader->e_phnum}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader->e_phentsize}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader->e_phoff}}});
|
|
||||||
|
|
||||||
ELFBase.InstructionPointer = EntryPoint;
|
|
||||||
ELFBase.MemoryImage = MemoryImage.Physical;
|
|
||||||
ELFBase.VirtualMemoryImage = MemoryImage.Virtual;
|
|
||||||
|
|
||||||
ELFBase.Success = true;
|
|
||||||
return ELFBase;
|
|
||||||
#elif defined(a32)
|
|
||||||
return {};
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,330 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <exec.hpp>
|
|
||||||
|
|
||||||
#include <msexec.h>
|
|
||||||
|
|
||||||
#include "../../kernel.h"
|
|
||||||
#include "../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Execute
|
|
||||||
{
|
|
||||||
/* Originally from https://wiki.osdev.org/ELF_Tutorial */
|
|
||||||
|
|
||||||
Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header)
|
|
||||||
{
|
|
||||||
return (Elf64_Shdr *)((uintptr_t)Header + Header->e_shoff);
|
|
||||||
}
|
|
||||||
|
|
||||||
Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index)
|
|
||||||
{
|
|
||||||
return &GetELFSheader(Header)[Index];
|
|
||||||
}
|
|
||||||
|
|
||||||
char *GetELFStringTable(Elf64_Ehdr *Header)
|
|
||||||
{
|
|
||||||
if (Header->e_shstrndx == SHN_UNDEF)
|
|
||||||
return nullptr;
|
|
||||||
return (char *)Header + GetELFSection(Header, Header->e_shstrndx)->sh_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset)
|
|
||||||
{
|
|
||||||
char *StringTable = GetELFStringTable(Header);
|
|
||||||
if (StringTable == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
return StringTable + Offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
Elf64_Shdr *SymbolTable = nullptr;
|
|
||||||
Elf64_Shdr *StringTable = nullptr;
|
|
||||||
Elf64_Sym *Symbol = nullptr;
|
|
||||||
char *String = nullptr;
|
|
||||||
|
|
||||||
for (Elf64_Half i = 0; i < Header->e_shnum; i++)
|
|
||||||
{
|
|
||||||
Elf64_Shdr *shdr = GetELFSection(Header, i);
|
|
||||||
switch (shdr->sh_type)
|
|
||||||
{
|
|
||||||
case SHT_SYMTAB:
|
|
||||||
SymbolTable = shdr;
|
|
||||||
StringTable = GetELFSection(Header, shdr->sh_link);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SymbolTable == nullptr || StringTable == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < (SymbolTable->sh_size / sizeof(Elf64_Sym)); i++)
|
|
||||||
{
|
|
||||||
Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym)));
|
|
||||||
String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name);
|
|
||||||
if (strcmp(String, Name) == 0)
|
|
||||||
return Symbol;
|
|
||||||
}
|
|
||||||
#elif defined(a32)
|
|
||||||
#endif
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
if (Table == SHN_UNDEF || Index == SHN_UNDEF)
|
|
||||||
return 0;
|
|
||||||
Elf64_Shdr *SymbolTable = GetELFSection(Header, Table);
|
|
||||||
|
|
||||||
uint64_t STEntries = SymbolTable->sh_size / SymbolTable->sh_entsize;
|
|
||||||
if (Index >= STEntries)
|
|
||||||
{
|
|
||||||
error("Symbol index out of range %d-%u.", Table, Index);
|
|
||||||
return 0xdead;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t SymbolAddress = (uint64_t)Header + SymbolTable->sh_offset;
|
|
||||||
Elf64_Sym *Symbol = &((Elf64_Sym *)SymbolAddress)[Index];
|
|
||||||
|
|
||||||
if (Symbol->st_shndx == SHN_UNDEF)
|
|
||||||
{
|
|
||||||
Elf64_Shdr *StringTable = GetELFSection(Header, SymbolTable->sh_link);
|
|
||||||
const char *Name = (const char *)Header + StringTable->sh_offset + Symbol->st_name;
|
|
||||||
|
|
||||||
void *Target = (void *)ELFLookupSymbol(Header, Name)->st_value;
|
|
||||||
if (Target == nullptr)
|
|
||||||
{
|
|
||||||
if (ELF64_ST_BIND(Symbol->st_info) & STB_WEAK)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error("Undefined external symbol \"%s\".", Name);
|
|
||||||
return 0xdead;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return (uintptr_t)Target;
|
|
||||||
}
|
|
||||||
else if (Symbol->st_shndx == SHN_ABS)
|
|
||||||
return Symbol->st_value;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Elf64_Shdr *Target = GetELFSection(Header, Symbol->st_shndx);
|
|
||||||
return (uintptr_t)Header + Symbol->st_value + Target->sh_offset;
|
|
||||||
}
|
|
||||||
#elif defined(a32)
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
Elf64_Dyn *ELFGetDynamicTag(void *ElfFile, enum DynamicArrayTags Tag)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
|
|
||||||
|
|
||||||
Elf64_Phdr ItrPhdr;
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr, (uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, sizeof(Elf64_Phdr));
|
|
||||||
if (ItrPhdr.p_type == PT_DYNAMIC)
|
|
||||||
{
|
|
||||||
Elf64_Dyn *Dynamic = (Elf64_Dyn *)((uint8_t *)ElfFile + ItrPhdr.p_offset);
|
|
||||||
for (size_t i = 0; i < ItrPhdr.p_filesz / sizeof(Elf64_Dyn); i++)
|
|
||||||
{
|
|
||||||
if (Dynamic[i].d_tag == Tag)
|
|
||||||
{
|
|
||||||
debug("Found dynamic tag %d at %#lx [d_val: %#lx].", Tag, &Dynamic[i], Dynamic[i].d_un.d_val);
|
|
||||||
return &Dynamic[i];
|
|
||||||
}
|
|
||||||
if (Dynamic[i].d_tag == DT_NULL)
|
|
||||||
{
|
|
||||||
debug("Reached end of dynamic tag list for tag %d.", Tag);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug("Dynamic tag %d not found.", Tag);
|
|
||||||
return nullptr;
|
|
||||||
#elif defined(a32)
|
|
||||||
return nullptr;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
MmImage ELFCreateMemoryImage(Memory::MemMgr *mem, Memory::Virtual &pV, void *ElfFile, size_t Length)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
void *MemoryImage = nullptr;
|
|
||||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
|
|
||||||
bool IsPIC = ELFHeader->e_type == ET_DYN;
|
|
||||||
UNUSED(IsPIC);
|
|
||||||
debug("Elf %s PIC", IsPIC ? "is" : "is not");
|
|
||||||
|
|
||||||
/* TODO: Not sure what I am supposed to do with this.
|
|
||||||
* It is supposed to detect if it's PIC or not but I
|
|
||||||
* don't know if it's right. */
|
|
||||||
if (ELFGetDynamicTag(ElfFile, DT_TEXTREL))
|
|
||||||
{
|
|
||||||
fixme("Text relocation is not(?) tested yet!");
|
|
||||||
MemoryImage = (uint8_t *)mem->RequestPages(TO_PAGES(Length + 1), true);
|
|
||||||
memset(MemoryImage, 0, Length);
|
|
||||||
return {MemoryImage, 0x0};
|
|
||||||
}
|
|
||||||
|
|
||||||
Elf64_Phdr ItrPhdr;
|
|
||||||
uintptr_t FirstProgramHeaderVirtualAddress = 0x0;
|
|
||||||
|
|
||||||
bool FirstProgramHeader = false;
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr,
|
|
||||||
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
|
||||||
sizeof(Elf64_Phdr));
|
|
||||||
|
|
||||||
if (ItrPhdr.p_type == PT_LOAD && !FirstProgramHeader)
|
|
||||||
{
|
|
||||||
FirstProgramHeaderVirtualAddress = ItrPhdr.p_vaddr;
|
|
||||||
FirstProgramHeader = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ItrPhdr.p_type == PT_LOAD && ItrPhdr.p_vaddr == 0)
|
|
||||||
{
|
|
||||||
debug("p_vaddr is 0, allocating %ld pages for image (size: %#lx)", TO_PAGES(Length), Length);
|
|
||||||
MemoryImage = mem->RequestPages(TO_PAGES(Length), true);
|
|
||||||
debug("MemoryImage: %#lx-%#lx", MemoryImage, (uintptr_t)MemoryImage + Length);
|
|
||||||
memset(MemoryImage, 0, Length);
|
|
||||||
return {MemoryImage, (void *)FirstProgramHeaderVirtualAddress};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug("Allocating %ld pages for image (size: %#lx)", TO_PAGES(Length), Length);
|
|
||||||
MemoryImage = mem->RequestPages(TO_PAGES(Length));
|
|
||||||
debug("MemoryImage: %#lx-%#lx", MemoryImage, (uintptr_t)MemoryImage + Length);
|
|
||||||
memset(MemoryImage, 0, Length);
|
|
||||||
|
|
||||||
if (FirstProgramHeaderVirtualAddress != 0)
|
|
||||||
FirstProgramHeaderVirtualAddress &= 0xFFFFFFFFFFFFF000;
|
|
||||||
else
|
|
||||||
FirstProgramHeaderVirtualAddress = (uintptr_t)MemoryImage;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < TO_PAGES(Length); i++)
|
|
||||||
{
|
|
||||||
pV.Remap((void *)((uintptr_t)FirstProgramHeaderVirtualAddress + (i * PAGE_SIZE)), (void *)((uintptr_t)MemoryImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
|
||||||
debug("Remapped: %#lx -> %#lx", (uintptr_t)FirstProgramHeaderVirtualAddress + (i * PAGE_SIZE), (uintptr_t)MemoryImage + (i * PAGE_SIZE));
|
|
||||||
}
|
|
||||||
return {MemoryImage, (void *)FirstProgramHeaderVirtualAddress};
|
|
||||||
#elif defined(a32)
|
|
||||||
return {};
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t LoadELFInterpreter(Memory::MemMgr *mem, Memory::Virtual &pV, const char *Interpreter)
|
|
||||||
{
|
|
||||||
if (GetBinaryType((char *)Interpreter) != BinaryType::BinTypeELF)
|
|
||||||
{
|
|
||||||
error("Interpreter \"%s\" is not an ELF file.", Interpreter);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No need to check if it's valid, the GetBinaryType() call above does that. */
|
|
||||||
VirtualFileSystem::File File = vfs->Open(Interpreter);
|
|
||||||
|
|
||||||
#if defined(a64)
|
|
||||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)File.node->Address;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
const char *InterpreterType[6] = {
|
|
||||||
"ET_NONE",
|
|
||||||
"ET_REL",
|
|
||||||
"ET_EXEC",
|
|
||||||
"ET_DYN",
|
|
||||||
"ET_CORE",
|
|
||||||
"ET_LOPROC - ET_HIPROC"};
|
|
||||||
Elf64_Half IntType = ELFHeader->e_type;
|
|
||||||
if (IntType > 5)
|
|
||||||
IntType = 5;
|
|
||||||
debug("Interpreter type: %s - %#x", InterpreterType[IntType], ELFHeader->e_type);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uintptr_t BaseAddress = UINTPTR_MAX;
|
|
||||||
uint64_t ElfAppSize = 0;
|
|
||||||
|
|
||||||
Elf64_Phdr ItrPhdr;
|
|
||||||
|
|
||||||
/* Get base address */
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr,
|
|
||||||
(uint8_t *)File.node->Address + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
|
||||||
sizeof(Elf64_Phdr));
|
|
||||||
|
|
||||||
BaseAddress = MIN(BaseAddress, ItrPhdr.p_vaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get size */
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr,
|
|
||||||
(uint8_t *)File.node->Address + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
|
||||||
sizeof(Elf64_Phdr));
|
|
||||||
|
|
||||||
uintptr_t SegmentEnd;
|
|
||||||
SegmentEnd = ItrPhdr.p_vaddr - BaseAddress + ItrPhdr.p_memsz;
|
|
||||||
ElfAppSize = MAX(ElfAppSize, SegmentEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
MmImage MemoryImage = ELFCreateMemoryImage(mem, pV, (void *)File.node->Address, ElfAppSize);
|
|
||||||
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr,
|
|
||||||
(uint8_t *)File.node->Address + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
|
||||||
sizeof(Elf64_Phdr));
|
|
||||||
|
|
||||||
if (ItrPhdr.p_type == PT_LOAD)
|
|
||||||
{
|
|
||||||
debug("PT_LOAD - Offset: %#lx, VirtAddr: %#lx, FileSiz: %ld, MemSiz: %ld, Align: %#lx",
|
|
||||||
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
|
|
||||||
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
|
|
||||||
uintptr_t MAddr = (ItrPhdr.p_vaddr - BaseAddress) + (uintptr_t)MemoryImage.Physical;
|
|
||||||
fixme("Address: %#lx %s%s%s", MAddr,
|
|
||||||
(ItrPhdr.p_flags & PF_R) ? "R" : "",
|
|
||||||
(ItrPhdr.p_flags & PF_W) ? "W" : "",
|
|
||||||
(ItrPhdr.p_flags & PF_X) ? "X" : "");
|
|
||||||
|
|
||||||
memcpy((void *)MAddr, (uint8_t *)File.node->Address + ItrPhdr.p_offset, ItrPhdr.p_filesz);
|
|
||||||
debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)File.node->Address + ItrPhdr.p_offset, MAddr, ItrPhdr.p_filesz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vfs->Close(File);
|
|
||||||
debug("Interpreter entry point: %#lx (%#lx + %#lx)", (uintptr_t)MemoryImage.Physical + ELFHeader->e_entry,
|
|
||||||
(uintptr_t)MemoryImage.Physical, ELFHeader->e_entry);
|
|
||||||
return (uintptr_t)MemoryImage.Physical + ELFHeader->e_entry;
|
|
||||||
#elif defined(a32)
|
|
||||||
vfs->Close(File);
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
62
Execute/Elf/ParseFunctions/ELFGetDynamicTag.cpp
Normal file
62
Execute/Elf/ParseFunctions/ELFGetDynamicTag.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <exec.hpp>
|
||||||
|
|
||||||
|
#include "../../../kernel.h"
|
||||||
|
|
||||||
|
namespace Execute
|
||||||
|
{
|
||||||
|
std::vector<Elf64_Dyn> ELFGetDynamicTag_x86_64(VirtualFileSystem::File &ElfFile,
|
||||||
|
DynamicArrayTags Tag)
|
||||||
|
{
|
||||||
|
off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR);
|
||||||
|
std::vector<Elf64_Dyn> Ret;
|
||||||
|
|
||||||
|
Elf64_Ehdr ELFHeader;
|
||||||
|
vfs->Seek(ElfFile, 0, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||||
|
|
||||||
|
std::vector<Elf64_Phdr> DYNAMICPhdrs = ELFGetSymbolType_x86_64(ElfFile, PT_DYNAMIC);
|
||||||
|
|
||||||
|
if (DYNAMICPhdrs.size() < 1)
|
||||||
|
{
|
||||||
|
error("No dynamic phdrs found.");
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (auto Phdr in DYNAMICPhdrs)
|
||||||
|
{
|
||||||
|
Elf64_Dyn Dynamic;
|
||||||
|
for (size_t i = 0; i < Phdr.p_filesz / sizeof(Elf64_Dyn); i++)
|
||||||
|
{
|
||||||
|
vfs->Seek(ElfFile, Phdr.p_offset + (i * sizeof(Elf64_Dyn)), SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&Dynamic, sizeof(Elf64_Dyn));
|
||||||
|
|
||||||
|
if (Dynamic.d_tag != Tag)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
debug("Found dynamic tag %d at %#lx [d_val: %#lx].",
|
||||||
|
Tag, &Dynamic, Dynamic.d_un.d_val);
|
||||||
|
Ret.push_back(Dynamic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vfs->Seek(ElfFile, OldOffset, SEEK_SET);
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
}
|
54
Execute/Elf/ParseFunctions/ELFGetSections.cpp
Normal file
54
Execute/Elf/ParseFunctions/ELFGetSections.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <exec.hpp>
|
||||||
|
|
||||||
|
#include "../../../kernel.h"
|
||||||
|
|
||||||
|
namespace Execute
|
||||||
|
{
|
||||||
|
std::vector<Elf64_Shdr> ELFGetSections_x86_64(VirtualFileSystem::File &ElfFile,
|
||||||
|
const char *SectionName)
|
||||||
|
{
|
||||||
|
off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR);
|
||||||
|
std::vector<Elf64_Shdr> Ret;
|
||||||
|
|
||||||
|
Elf64_Ehdr ELFHeader;
|
||||||
|
vfs->Seek(ElfFile, 0, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||||
|
|
||||||
|
Elf64_Shdr *SectionHeaders = new Elf64_Shdr[ELFHeader.e_shnum];
|
||||||
|
vfs->Seek(ElfFile, ELFHeader.e_shoff, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)SectionHeaders, sizeof(Elf64_Shdr) * ELFHeader.e_shnum);
|
||||||
|
|
||||||
|
char *SectionNames = new char[SectionHeaders[ELFHeader.e_shstrndx].sh_size];
|
||||||
|
vfs->Seek(ElfFile, SectionHeaders[ELFHeader.e_shstrndx].sh_offset, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)SectionNames, SectionHeaders[ELFHeader.e_shstrndx].sh_size);
|
||||||
|
|
||||||
|
for (Elf64_Half i = 0; i < ELFHeader.e_shnum; ++i)
|
||||||
|
{
|
||||||
|
const char *Name = SectionNames + SectionHeaders[i].sh_name;
|
||||||
|
if (strcmp(Name, SectionName) == 0)
|
||||||
|
Ret.push_back(SectionHeaders[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
vfs->Seek(ElfFile, OldOffset, SEEK_SET);
|
||||||
|
delete[] SectionHeaders;
|
||||||
|
delete[] SectionNames;
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
}
|
50
Execute/Elf/ParseFunctions/ELFGetSymbolType.cpp
Normal file
50
Execute/Elf/ParseFunctions/ELFGetSymbolType.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <exec.hpp>
|
||||||
|
|
||||||
|
#include "../../../kernel.h"
|
||||||
|
|
||||||
|
namespace Execute
|
||||||
|
{
|
||||||
|
std::vector<Elf64_Phdr> ELFGetSymbolType_x86_64(VirtualFileSystem::File &ElfFile,
|
||||||
|
SegmentTypes Tag)
|
||||||
|
{
|
||||||
|
off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR);
|
||||||
|
std::vector<Elf64_Phdr> Ret;
|
||||||
|
|
||||||
|
Elf64_Ehdr ELFHeader;
|
||||||
|
vfs->Seek(ElfFile, 0, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||||
|
|
||||||
|
Elf64_Phdr ProgramHeaders;
|
||||||
|
vfs->Seek(ElfFile, ELFHeader.e_phoff, SEEK_SET);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr));
|
||||||
|
|
||||||
|
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||||
|
{
|
||||||
|
if (ProgramHeaders.p_type == Tag)
|
||||||
|
Ret.push_back(ProgramHeaders);
|
||||||
|
|
||||||
|
vfs->Seek(ElfFile, sizeof(Elf64_Phdr), SEEK_CUR);
|
||||||
|
vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr));
|
||||||
|
}
|
||||||
|
|
||||||
|
vfs->Seek(ElfFile, OldOffset, SEEK_SET);
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
}
|
@ -1,263 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <exec.hpp>
|
|
||||||
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <msexec.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#include <abi.h>
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#include <dumper.hpp>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../../kernel.h"
|
|
||||||
#include "../../Fex.hpp"
|
|
||||||
|
|
||||||
using namespace Tasking;
|
|
||||||
|
|
||||||
NewLock(ExecuteServiceLock);
|
|
||||||
|
|
||||||
namespace Execute
|
|
||||||
{
|
|
||||||
Memory::MemMgr *mem = nullptr;
|
|
||||||
std::vector<SharedLibraries> Libs;
|
|
||||||
|
|
||||||
void StartExecuteService()
|
|
||||||
{
|
|
||||||
mem = new Memory::MemMgr;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
SmartLock(ExecuteServiceLock);
|
|
||||||
foreach (auto &Lib in Libs)
|
|
||||||
{
|
|
||||||
if (Lib.RefCount > 0)
|
|
||||||
{
|
|
||||||
Lib.Timeout = TimeManager->CalculateTarget(10, Time::Units::Minutes);
|
|
||||||
debug("Reset timeout for %s", Lib.Identifier);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (Lib.Timeout < TimeManager->GetCounter())
|
|
||||||
{
|
|
||||||
// TODO: Remove
|
|
||||||
fixme("Removed library %s because of timeout", Lib.Identifier);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
debug("Timeout for %s is %ld", Lib.Identifier, Lib.Timeout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug("Waiting 10 seconds...");
|
|
||||||
}
|
|
||||||
TaskManager->Sleep(10000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AddLibrary(char *Identifier, void *ElfImage, size_t Length, const Memory::Virtual &pV)
|
|
||||||
{
|
|
||||||
SmartLock(ExecuteServiceLock);
|
|
||||||
SharedLibraries sl;
|
|
||||||
|
|
||||||
foreach (auto lib in Libs)
|
|
||||||
{
|
|
||||||
if (strcmp(lib.Identifier, Identifier) == 0)
|
|
||||||
{
|
|
||||||
debug("Library %s already loaded", Identifier);
|
|
||||||
lib.RefCount++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(sl.Identifier, Identifier);
|
|
||||||
sl.Timeout = TimeManager->CalculateTarget(10, Time::Units::Minutes);
|
|
||||||
sl.RefCount = 0;
|
|
||||||
|
|
||||||
void *LibFile = mem->RequestPages(TO_PAGES(Length + 1), true);
|
|
||||||
debug("LibFile: %#lx", LibFile);
|
|
||||||
memcpy(LibFile, (void *)ElfImage, Length);
|
|
||||||
Memory::Virtual().Map(LibFile, LibFile, Length, Memory::RW | Memory::US | Memory::G);
|
|
||||||
|
|
||||||
Memory::Virtual ncpV = pV;
|
|
||||||
sl.MemoryImage = r_cst(uint64_t, ELFCreateMemoryImage(mem, ncpV, LibFile, Length).Physical);
|
|
||||||
debug("MemoryImage: %#lx", sl.MemoryImage);
|
|
||||||
|
|
||||||
uintptr_t BaseAddress = UINTPTR_MAX;
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
Elf64_Phdr ItrProgramHeader;
|
|
||||||
|
|
||||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)LibFile)->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrProgramHeader, (uint8_t *)LibFile + ((Elf64_Ehdr *)LibFile)->e_phoff + ((Elf64_Ehdr *)LibFile)->e_phentsize * i, sizeof(Elf64_Phdr));
|
|
||||||
BaseAddress = MIN(BaseAddress, ItrProgramHeader.p_vaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)LibFile)->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrProgramHeader, (uint8_t *)LibFile + ((Elf64_Ehdr *)LibFile)->e_phoff + ((Elf64_Ehdr *)LibFile)->e_phentsize * i, sizeof(Elf64_Phdr));
|
|
||||||
if (ItrProgramHeader.p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
debug("PT_LOAD - Offset: %#lx, VirtAddr: %#lx, FileSiz: %ld, MemSiz: %ld, Align: %#lx",
|
|
||||||
ItrProgramHeader.p_offset, ItrProgramHeader.p_vaddr,
|
|
||||||
ItrProgramHeader.p_filesz, ItrProgramHeader.p_memsz, ItrProgramHeader.p_align);
|
|
||||||
uintptr_t MAddr = (ItrProgramHeader.p_vaddr - BaseAddress) + (uintptr_t)sl.MemoryImage;
|
|
||||||
fixme("Address: %#lx %s%s%s", MAddr,
|
|
||||||
(ItrProgramHeader.p_flags & PF_R) ? "R" : "",
|
|
||||||
(ItrProgramHeader.p_flags & PF_W) ? "W" : "",
|
|
||||||
(ItrProgramHeader.p_flags & PF_X) ? "X" : "");
|
|
||||||
|
|
||||||
memcpy((void *)MAddr, (uint8_t *)LibFile + ItrProgramHeader.p_offset, ItrProgramHeader.p_filesz);
|
|
||||||
debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)LibFile + ItrProgramHeader.p_offset, (uintptr_t)MAddr, ItrProgramHeader.p_filesz);
|
|
||||||
break;
|
|
||||||
#elif defined(a32)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(a64)
|
|
||||||
struct Elf64_Dyn *JmpRel = ELFGetDynamicTag((void *)LibFile, DT_JMPREL);
|
|
||||||
struct Elf64_Dyn *SymTab = ELFGetDynamicTag((void *)LibFile, DT_SYMTAB);
|
|
||||||
struct Elf64_Dyn *StrTab = ELFGetDynamicTag((void *)LibFile, DT_STRTAB);
|
|
||||||
|
|
||||||
if (!JmpRel)
|
|
||||||
{
|
|
||||||
debug("No DT_JMPREL");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SymTab)
|
|
||||||
{
|
|
||||||
debug("No DT_SYMTAB");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!StrTab)
|
|
||||||
{
|
|
||||||
debug("No DT_STRTAB");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (JmpRel && SymTab && StrTab)
|
|
||||||
{
|
|
||||||
debug("JmpRel: %#lx, SymTab: %#lx, StrTab: %#lx", JmpRel->d_un.d_ptr, SymTab->d_un.d_ptr, StrTab->d_un.d_ptr);
|
|
||||||
Elf64_Rela *_JmpRel = (Elf64_Rela *)(sl.MemoryImage + (JmpRel->d_un.d_ptr - BaseAddress));
|
|
||||||
Elf64_Sym *_SymTab = (Elf64_Sym *)(sl.MemoryImage + (SymTab->d_un.d_ptr - BaseAddress));
|
|
||||||
|
|
||||||
char *_DynStr = (char *)(sl.MemoryImage + (StrTab->d_un.d_ptr - BaseAddress));
|
|
||||||
|
|
||||||
Elf64_Shdr *gotSection = nullptr;
|
|
||||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)LibFile)->e_shnum; i++)
|
|
||||||
{
|
|
||||||
Elf64_Shdr *shdr = (Elf64_Shdr *)((uint8_t *)LibFile + ((Elf64_Ehdr *)LibFile)->e_shoff + i * sizeof(Elf64_Shdr));
|
|
||||||
if (shdr->sh_type == SHT_PROGBITS && (shdr->sh_flags & SHF_WRITE) && (shdr->sh_flags & SHF_ALLOC))
|
|
||||||
{
|
|
||||||
gotSection = shdr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug("LIB_DBG");
|
|
||||||
|
|
||||||
if (gotSection)
|
|
||||||
{
|
|
||||||
Elf64_Xword numEntries = gotSection->sh_size / sizeof(Elf64_Addr);
|
|
||||||
for (Elf64_Xword i = 0; i < numEntries - 3; i++)
|
|
||||||
{
|
|
||||||
Elf64_Rela *Rel = _JmpRel + i;
|
|
||||||
Elf64_Addr *GOTEntry = (Elf64_Addr *)(Rel->r_offset + sl.MemoryImage);
|
|
||||||
|
|
||||||
Elf64_Xword RelType = ELF64_R_TYPE(Rel->r_info);
|
|
||||||
debug("r_offset: %#lx RelType: %d", Rel->r_offset, RelType);
|
|
||||||
|
|
||||||
switch (RelType)
|
|
||||||
{
|
|
||||||
case R_X86_64_NONE:
|
|
||||||
break;
|
|
||||||
case R_X86_64_JUMP_SLOT:
|
|
||||||
{
|
|
||||||
Elf64_Xword SymIndex = ELF64_R_SYM(Rel->r_info);
|
|
||||||
Elf64_Sym *Sym = _SymTab + SymIndex;
|
|
||||||
|
|
||||||
if (Sym->st_name)
|
|
||||||
{
|
|
||||||
char *SymName = _DynStr + Sym->st_name;
|
|
||||||
debug("SymName: %s", SymName);
|
|
||||||
|
|
||||||
Elf64_Sym *LibSym = ELFLookupSymbol((Elf64_Ehdr *)LibFile, SymName);
|
|
||||||
|
|
||||||
if (LibSym)
|
|
||||||
{
|
|
||||||
*GOTEntry = (Elf64_Addr)(sl.MemoryImage + LibSym->st_value);
|
|
||||||
debug("GOT[%ld]: %#lx + %#lx = %#lx", i, sl.MemoryImage, LibSym->st_value, *GOTEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
fixme("RelType %d not supported", RelType);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug("GOT[%ld](%#lx): %#lx", i, GOTEntry, *GOTEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
debug("GOT section not found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sl.Address = r_cst(uint64_t, LibFile);
|
|
||||||
debug("Casted LibFile %#lx -> %#lx", LibFile, sl.Address);
|
|
||||||
sl.Length = Length;
|
|
||||||
|
|
||||||
debug("Library %s loaded at %#lx (full file: %#lx)", Identifier, sl.MemoryImage, LibFile);
|
|
||||||
|
|
||||||
Libs.push_back(sl);
|
|
||||||
return true;
|
|
||||||
#elif defined(a32)
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchLibrary(char *Identifier)
|
|
||||||
{
|
|
||||||
UNUSED(Identifier);
|
|
||||||
SmartLock(ExecuteServiceLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedLibraries GetLibrary(char *Identifier)
|
|
||||||
{
|
|
||||||
SmartLock(ExecuteServiceLock);
|
|
||||||
foreach (auto Lib in Libs)
|
|
||||||
{
|
|
||||||
if (strcmp(Lib.Identifier, Identifier) == 0)
|
|
||||||
{
|
|
||||||
Lib.RefCount++;
|
|
||||||
debug("Library %s found (%#lx %#lx)", Identifier, Lib.Address, Lib.MemoryImage);
|
|
||||||
return Lib;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// throw std::runtime_error("Library not found");
|
|
||||||
return SharedLibraries();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <exec.hpp>
|
|
||||||
|
|
||||||
#include <msexec.h>
|
|
||||||
|
|
||||||
#include "../kernel.h"
|
|
||||||
#include "../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Execute
|
|
||||||
{
|
|
||||||
BinaryType GetBinaryType(void *Image)
|
|
||||||
{
|
|
||||||
Fex *FexHdr = (Fex *)Image;
|
|
||||||
|
|
||||||
/* Elf64_Ehdr and Elf32_Ehdr are very similar (Elf64_Half and
|
|
||||||
Elf32_Half are the same size type) so we can use directly Elf64_Ehdr. */
|
|
||||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)Image;
|
|
||||||
|
|
||||||
IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)Image;
|
|
||||||
|
|
||||||
/* Check Fex magic */
|
|
||||||
if (FexHdr->Magic[0] == 'F' && FexHdr->Magic[1] == 'E' && FexHdr->Magic[2] == 'X' && FexHdr->Magic[3] == '\0')
|
|
||||||
{
|
|
||||||
/* If the fex type is driver, we shouldn't return as Fex. */
|
|
||||||
if (FexHdr->Type == FexFormatType::FexFormatType_Executable)
|
|
||||||
{
|
|
||||||
debug("Image - Fex");
|
|
||||||
return BinaryType::BinTypeFex;
|
|
||||||
}
|
|
||||||
else if (FexHdr->Type == FexFormatType::FexFormatType_Driver)
|
|
||||||
{
|
|
||||||
debug("Fex Driver is not supposed to be executed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Check ELF magic. */
|
|
||||||
else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 &&
|
|
||||||
ELFHeader->e_ident[EI_MAG1] == ELFMAG1 &&
|
|
||||||
ELFHeader->e_ident[EI_MAG2] == ELFMAG2 &&
|
|
||||||
ELFHeader->e_ident[EI_MAG3] == ELFMAG3)
|
|
||||||
{
|
|
||||||
debug("Image - ELF");
|
|
||||||
return BinaryType::BinTypeELF;
|
|
||||||
}
|
|
||||||
/* Every Windows executable starts with MZ header. */
|
|
||||||
else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE)
|
|
||||||
{
|
|
||||||
IMAGE_NT_HEADERS *PEHeader = (IMAGE_NT_HEADERS *)(((char *)Image) + MZHeader->e_lfanew);
|
|
||||||
IMAGE_OS2_HEADER *NEHeader = (IMAGE_OS2_HEADER *)(((char *)Image) + MZHeader->e_lfanew);
|
|
||||||
|
|
||||||
/* TODO: LE, EDOS */
|
|
||||||
if (PEHeader->Signature == IMAGE_NT_SIGNATURE)
|
|
||||||
{
|
|
||||||
debug("Image - PE");
|
|
||||||
return BinaryType::BinTypePE;
|
|
||||||
}
|
|
||||||
else if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE)
|
|
||||||
{
|
|
||||||
debug("Image - NE");
|
|
||||||
return BinaryType::BinTypeNE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
debug("Image - MZ");
|
|
||||||
return BinaryType::BinTypeMZ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ... */
|
|
||||||
return BinaryType::BinTypeUnknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
BinaryType GetBinaryType(char *Path)
|
|
||||||
{
|
|
||||||
BinaryType Type = BinaryType::BinTypeInvalid;
|
|
||||||
VirtualFileSystem::File ExFile = vfs->Open(Path);
|
|
||||||
|
|
||||||
if (ExFile.IsOK())
|
|
||||||
{
|
|
||||||
debug("File opened: %s", Path);
|
|
||||||
Type = GetBinaryType((void *)ExFile.node->Address);
|
|
||||||
}
|
|
||||||
|
|
||||||
vfs->Close(ExFile);
|
|
||||||
return Type;
|
|
||||||
}
|
|
||||||
}
|
|
@ -39,68 +39,58 @@ namespace Execute
|
|||||||
|
|
||||||
VirtualFileSystem::File ExFile = vfs->Open(Path);
|
VirtualFileSystem::File ExFile = vfs->Open(Path);
|
||||||
|
|
||||||
if (ExFile.IsOK())
|
if (!ExFile.IsOK())
|
||||||
{
|
{
|
||||||
if (ExFile.node->Flags != VirtualFileSystem::NodeFlags::FILE)
|
if (ExFile.Status == VirtualFileSystem::FileStatus::NotFound)
|
||||||
{
|
{
|
||||||
ret.Status = ExStatus::InvalidFilePath;
|
ret.Status = ExStatus::InvalidFilePath;
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret.Status = ExStatus::InvalidFile;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ExFile.GetFlags() != VirtualFileSystem::NodeFlags::FILE)
|
||||||
|
{
|
||||||
|
ret.Status = ExStatus::InvalidFilePath;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (GetBinaryType(Path))
|
switch (GetBinaryType(Path))
|
||||||
{
|
{
|
||||||
case BinaryType::BinTypeFex:
|
case BinaryType::BinTypeFex:
|
||||||
{
|
{
|
||||||
Fex *FexHdr = (Fex *)ExFile.node->Address;
|
Fex FexHdr;
|
||||||
if (FexHdr->Type == FexFormatType::FexFormatType_Executable)
|
vfs->Read(ExFile, (uint8_t *)&FexHdr, sizeof(Fex));
|
||||||
|
if (FexHdr.Type == FexFormatType::FexFormatType_Executable)
|
||||||
{
|
{
|
||||||
const char *BaseName;
|
stub;
|
||||||
cwk_path_get_basename(Path, &BaseName, nullptr);
|
assert(false);
|
||||||
PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User);
|
|
||||||
|
|
||||||
void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile.node->Length + 1));
|
|
||||||
memcpy(BaseImage, (void *)ExFile.node->Address, ExFile.node->Length);
|
|
||||||
|
|
||||||
Memory::Virtual(Process->PageTable).Map((void *)BaseImage, (void *)BaseImage, ExFile.node->Length, Memory::PTFlag::RW | Memory::PTFlag::US);
|
|
||||||
|
|
||||||
std::vector<AuxiliaryVector> auxv; // TODO!
|
|
||||||
|
|
||||||
TCB *Thread = TaskManager->CreateThread(Process,
|
|
||||||
(IP)FexHdr->EntryPoint,
|
|
||||||
argv, envp, auxv,
|
|
||||||
(IPOffset)BaseImage,
|
|
||||||
TaskArchitecture::x64,
|
|
||||||
TaskCompatibility::Native);
|
|
||||||
ret.Process = Process;
|
|
||||||
ret.Thread = Thread;
|
|
||||||
ret.Status = ExStatus::OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.Status = ExStatus::InvalidFileHeader;
|
ret.Status = ExStatus::InvalidFileHeader;
|
||||||
goto Exit;
|
break;
|
||||||
}
|
}
|
||||||
case BinaryType::BinTypeELF:
|
case BinaryType::BinTypeELF:
|
||||||
{
|
{
|
||||||
ELFBaseLoad bl = ELFLoad(Path, argv, envp);
|
ELFBaseLoad bl = ELFLoad(Path, argv, envp);
|
||||||
if (!bl.Success)
|
if (!bl.Success)
|
||||||
{
|
{
|
||||||
ret.Status = ExStatus::GenericError;
|
ret.Status = ExStatus::LoadingProcedureFailed;
|
||||||
goto Exit;
|
break;
|
||||||
}
|
}
|
||||||
ret = bl.sd;
|
ret = bl.sd;
|
||||||
goto Exit;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
ret.Status = ExStatus::Unsupported;
|
ret.Status = ExStatus::Unsupported;
|
||||||
goto Exit;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (ExFile.Status == VirtualFileSystem::FileStatus::NotFound)
|
|
||||||
ret.Status = ExStatus::InvalidFilePath;
|
|
||||||
else
|
|
||||||
ret.Status = ExStatus::InvalidFile;
|
|
||||||
|
|
||||||
Exit:
|
Exit:
|
||||||
vfs->Close(ExFile);
|
vfs->Close(ExFile);
|
||||||
|
@ -28,52 +28,20 @@ namespace VirtualFileSystem
|
|||||||
{
|
{
|
||||||
if (!Size)
|
if (!Size)
|
||||||
Size = node->Length;
|
Size = node->Length;
|
||||||
if (Offset > node->Length)
|
|
||||||
|
if ((size_t)node->Offset > node->Length)
|
||||||
return 0;
|
return 0;
|
||||||
if (Offset + Size > node->Length)
|
|
||||||
Size = node->Length - Offset;
|
if (node->Offset + Size > node->Length)
|
||||||
memcpy(Buffer, (uint8_t *)(node->Address + Offset), Size);
|
Size = node->Length - node->Offset;
|
||||||
|
|
||||||
|
memcpy(Buffer, (uint8_t *)(node->Address + node->Offset), Size);
|
||||||
return Size;
|
return Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
SeekFSFunction(USTAR_Seek)
|
|
||||||
{
|
|
||||||
long NewOffset;
|
|
||||||
|
|
||||||
if (Whence == SEEK_SET)
|
|
||||||
{
|
|
||||||
if (Offset > node->Length)
|
|
||||||
return -1;
|
|
||||||
node->Offset = Offset;
|
|
||||||
NewOffset = node->Offset;
|
|
||||||
}
|
|
||||||
else if (Whence == SEEK_CUR)
|
|
||||||
{
|
|
||||||
NewOffset = node->Offset + Offset;
|
|
||||||
if ((size_t)NewOffset > node->Length || NewOffset < 0)
|
|
||||||
return -1;
|
|
||||||
node->Offset = NewOffset;
|
|
||||||
}
|
|
||||||
else if (Whence == SEEK_END)
|
|
||||||
{
|
|
||||||
NewOffset = node->Length + Offset;
|
|
||||||
if (NewOffset < 0)
|
|
||||||
return -1;
|
|
||||||
node->Offset = NewOffset;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error("Invalid whence!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NewOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileSystemOperations ustar_op = {
|
FileSystemOperations ustar_op = {
|
||||||
.Name = "ustar",
|
.Name = "ustar",
|
||||||
.Read = USTAR_Read,
|
.Read = USTAR_Read,
|
||||||
.Seek = USTAR_Seek,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool USTAR::TestArchive(uintptr_t Address)
|
bool USTAR::TestArchive(uintptr_t Address)
|
||||||
|
@ -46,7 +46,6 @@ namespace VirtualFileSystem
|
|||||||
size_t Size = 1;
|
size_t Size = 1;
|
||||||
size_t PathSize = 0;
|
size_t PathSize = 0;
|
||||||
|
|
||||||
// Traverse the filesystem tree and build the path by adding each parent's Name field to the Path array
|
|
||||||
while (Parent != FileSystemRoot && Parent != nullptr)
|
while (Parent != FileSystemRoot && Parent != nullptr)
|
||||||
{
|
{
|
||||||
bool Found = false;
|
bool Found = false;
|
||||||
@ -82,36 +81,26 @@ namespace VirtualFileSystem
|
|||||||
Parent = Parent->Parent;
|
Parent = Parent->Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the total size of the final path string
|
|
||||||
for (size_t i = 0; i < PathSize; i++)
|
for (size_t i = 0; i < PathSize; i++)
|
||||||
{
|
|
||||||
Size += strlen(Path[i]);
|
Size += strlen(Path[i]);
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate a new string for the final path
|
|
||||||
std::shared_ptr<char> FinalPath;
|
std::shared_ptr<char> FinalPath;
|
||||||
FinalPath.reset(new char[Size]);
|
FinalPath.reset(new char[Size]);
|
||||||
|
|
||||||
size_t Offset = 0;
|
size_t Offset = 0;
|
||||||
|
|
||||||
// Concatenate the elements of the Path array into the FinalPath string
|
|
||||||
for (size_t i = PathSize - 1; i < PathSize; i--)
|
for (size_t i = PathSize - 1; i < PathSize; i--)
|
||||||
{
|
{
|
||||||
if (Path[i] == nullptr)
|
if (Path[i] == nullptr)
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
size_t ElementSize = strlen(Path[i]);
|
size_t ElementSize = strlen(Path[i]);
|
||||||
memcpy(FinalPath.get() + Offset, Path[i], ElementSize);
|
memcpy(FinalPath.get() + Offset, Path[i], ElementSize);
|
||||||
Offset += ElementSize;
|
Offset += ElementSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a null terminator to the final path string
|
|
||||||
FinalPath.get()[Size - 1] = '\0';
|
FinalPath.get()[Size - 1] = '\0';
|
||||||
|
|
||||||
// Deallocate the Path array
|
|
||||||
delete[] Path, Path = nullptr;
|
delete[] Path, Path = nullptr;
|
||||||
|
|
||||||
vfsdbg("GetPathFromNode()->\"%s\"", FinalPath.get());
|
vfsdbg("GetPathFromNode()->\"%s\"", FinalPath.get());
|
||||||
return FinalPath;
|
return FinalPath;
|
||||||
}
|
}
|
||||||
@ -498,7 +487,7 @@ namespace VirtualFileSystem
|
|||||||
return FileStatus::OK;
|
return FileStatus::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Virtual::Read(File &File, size_t Offset, uint8_t *Buffer, size_t Size)
|
size_t Virtual::Read(File &File, uint8_t *Buffer, size_t Size)
|
||||||
{
|
{
|
||||||
SmartLock(VFSLock);
|
SmartLock(VFSLock);
|
||||||
if (unlikely(!File.node))
|
if (unlikely(!File.node))
|
||||||
@ -516,10 +505,10 @@ namespace VirtualFileSystem
|
|||||||
File.Status = FileStatus::OK;
|
File.Status = FileStatus::OK;
|
||||||
|
|
||||||
vfsdbg("Reading %s out->%016x", File.Name, Buffer);
|
vfsdbg("Reading %s out->%016x", File.Name, Buffer);
|
||||||
return File.node->Operator->Read(File.node, Offset, Size, Buffer);
|
return File.node->Operator->Read(File.node, Size, Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Virtual::Write(File &File, size_t Offset, uint8_t *Buffer, size_t Size)
|
size_t Virtual::Write(File &File, uint8_t *Buffer, size_t Size)
|
||||||
{
|
{
|
||||||
SmartLock(VFSLock);
|
SmartLock(VFSLock);
|
||||||
if (unlikely(!File.node))
|
if (unlikely(!File.node))
|
||||||
@ -537,7 +526,72 @@ namespace VirtualFileSystem
|
|||||||
File.Status = FileStatus::OK;
|
File.Status = FileStatus::OK;
|
||||||
|
|
||||||
vfsdbg("Writing %s out->%016x", File.Name, Buffer);
|
vfsdbg("Writing %s out->%016x", File.Name, Buffer);
|
||||||
return File.node->Operator->Write(File.node, Offset, Size, Buffer);
|
return File.node->Operator->Write(File.node, Size, Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t Virtual::Seek(File &File, off_t Offset, uint8_t Whence)
|
||||||
|
{
|
||||||
|
SmartLock(VFSLock);
|
||||||
|
Node *node = File.node;
|
||||||
|
File.Status = FileStatus::OK;
|
||||||
|
|
||||||
|
if (unlikely(!node))
|
||||||
|
{
|
||||||
|
File.Status = FileStatus::InvalidNode;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(!node->Operator))
|
||||||
|
{
|
||||||
|
File.Status = FileStatus::InvalidOperator;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(node->Operator->Seek))
|
||||||
|
{
|
||||||
|
node->Offset = File.ContextOffset;
|
||||||
|
File.ContextOffset = node->Operator->Seek(node, Offset, Whence);
|
||||||
|
return File.ContextOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Whence)
|
||||||
|
{
|
||||||
|
case SEEK_SET:
|
||||||
|
{
|
||||||
|
if ((size_t)Offset > node->Length)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
File.ContextOffset = node->Offset = Offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SEEK_CUR:
|
||||||
|
{
|
||||||
|
off_t NewOffset = File.ContextOffset + Offset;
|
||||||
|
if ((size_t)NewOffset > node->Length ||
|
||||||
|
NewOffset < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
File.ContextOffset = node->Offset = NewOffset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SEEK_END:
|
||||||
|
{
|
||||||
|
off_t NewOffset = node->Length + Offset;
|
||||||
|
if ((size_t)NewOffset > node->Length ||
|
||||||
|
NewOffset < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
File.ContextOffset = node->Offset = NewOffset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
error("Invalid whence!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return File.ContextOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: CHECK Open */
|
/* TODO: CHECK Open */
|
||||||
@ -551,6 +605,7 @@ namespace VirtualFileSystem
|
|||||||
{
|
{
|
||||||
File file{};
|
File file{};
|
||||||
file.node = FileSystemRoot;
|
file.node = FileSystemRoot;
|
||||||
|
|
||||||
strcpy(file.Name, "/");
|
strcpy(file.Name, "/");
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
@ -559,8 +614,10 @@ namespace VirtualFileSystem
|
|||||||
{
|
{
|
||||||
File file{};
|
File file{};
|
||||||
file.node = Parent;
|
file.node = Parent;
|
||||||
|
|
||||||
if (unlikely(!file.node))
|
if (unlikely(!file.node))
|
||||||
file.Status = FileStatus::NotFound;
|
file.Status = FileStatus::NotFound;
|
||||||
|
|
||||||
cwk_path_get_basename(GetPathFromNode(Parent).get(), &basename, nullptr);
|
cwk_path_get_basename(GetPathFromNode(Parent).get(), &basename, nullptr);
|
||||||
strcpy(file.Name, basename);
|
strcpy(file.Name, basename);
|
||||||
return file;
|
return file;
|
||||||
@ -575,6 +632,7 @@ namespace VirtualFileSystem
|
|||||||
|
|
||||||
if (!file.node)
|
if (!file.node)
|
||||||
file.Status = FileStatus::NotFound;
|
file.Status = FileStatus::NotFound;
|
||||||
|
|
||||||
cwk_path_get_basename(GetPathFromNode(Parent).get(), &basename, nullptr);
|
cwk_path_get_basename(GetPathFromNode(Parent).get(), &basename, nullptr);
|
||||||
strcpy(file.Name, basename);
|
strcpy(file.Name, basename);
|
||||||
return file;
|
return file;
|
||||||
@ -631,6 +689,8 @@ namespace VirtualFileSystem
|
|||||||
if (unlikely(!File.node))
|
if (unlikely(!File.node))
|
||||||
return FileStatus::InvalidHandle;
|
return FileStatus::InvalidHandle;
|
||||||
vfsdbg("Closing %s", File.Name);
|
vfsdbg("Closing %s", File.Name);
|
||||||
|
|
||||||
|
File.node->Offset = 0;
|
||||||
return FileStatus::OK;
|
return FileStatus::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
68
Kernel.cpp
68
Kernel.cpp
@ -77,6 +77,8 @@ LockClass mExtTrkLock;
|
|||||||
* - [ ] COW (Copy On Write) for the virtual memory. (https://en.wikipedia.org/wiki/Copy-on-write)
|
* - [ ] COW (Copy On Write) for the virtual memory. (https://en.wikipedia.org/wiki/Copy-on-write)
|
||||||
* - [ ] Bootstrap should have a separate bss section + PHDR.
|
* - [ ] Bootstrap should have a separate bss section + PHDR.
|
||||||
* - [ ] Reimplement the driver conflict detection.
|
* - [ ] Reimplement the driver conflict detection.
|
||||||
|
* - [ ] Elf loader shouldn't create a full copy of the elf binary. Copy only the needed sections.
|
||||||
|
* - [ ] Use NX-bit.
|
||||||
*
|
*
|
||||||
* ISSUES:
|
* ISSUES:
|
||||||
* - [x] Kernel stack is smashed when an interrupt occurs. (this bug it occurs when an interrupt like IRQ1 or IRQ12 occurs)
|
* - [x] Kernel stack is smashed when an interrupt occurs. (this bug it occurs when an interrupt like IRQ1 or IRQ12 occurs)
|
||||||
@ -168,6 +170,19 @@ LockClass mExtTrkLock;
|
|||||||
* - Atomic operations:
|
* - Atomic operations:
|
||||||
* https://en.cppreference.com/w/cpp/atomic/atomic
|
* https://en.cppreference.com/w/cpp/atomic/atomic
|
||||||
*
|
*
|
||||||
|
* - ELF:
|
||||||
|
* https://www.sco.com/developers/gabi/latest/ch4.eheader.html
|
||||||
|
* https://refspecs.linuxfoundation.org/elf/elf.pdf
|
||||||
|
* https://docs.oracle.com/cd/E19683-01/817-3677/chapter6-42444/index.html
|
||||||
|
* https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-83432/index.html
|
||||||
|
* https://www.youtube.com/watch?v=nC1U1LJQL8o
|
||||||
|
* https://stevens.netmeister.org/631/elf.html
|
||||||
|
* https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h
|
||||||
|
*
|
||||||
|
* - C++ ABI:
|
||||||
|
* https://github.com/gcc-mirror/gcc/tree/master/libstdc%2B%2B-v3
|
||||||
|
* https://itanium-cxx-abi.github.io/cxx-abi/abi.html
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef a64
|
#ifdef a64
|
||||||
@ -259,8 +274,12 @@ EXTERNC void KPrint(const char *Format, ...)
|
|||||||
EXTERNC NIF void Main()
|
EXTERNC NIF void Main()
|
||||||
{
|
{
|
||||||
Display = new Video::Display(bInfo.Framebuffer[0]);
|
Display = new Video::Display(bInfo.Framebuffer[0]);
|
||||||
KPrint("%s - %s [\e058C19%s\eFFFFFF]", KERNEL_NAME, KERNEL_VERSION, GIT_COMMIT_SHORT);
|
|
||||||
KPrint("CPU: \e058C19%s \e8822AA%s \e8888FF%s", CPU::Hypervisor(), CPU::Vendor(), CPU::Name());
|
KPrint("%s - %s [\e058C19%s\eFFFFFF]",
|
||||||
|
KERNEL_NAME, KERNEL_VERSION, GIT_COMMIT_SHORT);
|
||||||
|
KPrint("CPU: \e058C19%s \e8822AA%s \e8888FF%s",
|
||||||
|
CPU::Hypervisor(), CPU::Vendor(), CPU::Name());
|
||||||
|
|
||||||
if (DebuggerIsAttached)
|
if (DebuggerIsAttached)
|
||||||
KPrint("\eFFA500Kernel debugger detected.");
|
KPrint("\eFFA500Kernel debugger detected.");
|
||||||
|
|
||||||
@ -293,7 +312,8 @@ EXTERNC NIF void Main()
|
|||||||
Video::FontInfo fi = Display->GetCurrentFont()->GetInfo();
|
Video::FontInfo fi = Display->GetCurrentFont()->GetInfo();
|
||||||
Display->SetBufferCursor(1, 0, buf->Height - fi.Height);
|
Display->SetBufferCursor(1, 0, buf->Height - fi.Height);
|
||||||
PutCharBufferIndex = 1;
|
PutCharBufferIndex = 1;
|
||||||
printf("Fennix Operating System - %s [\e058C19%s\eFFFFFF]\n", KERNEL_VERSION, GIT_COMMIT_SHORT);
|
printf("Fennix Operating System - %s [\e058C19%s\eFFFFFF]\n",
|
||||||
|
KERNEL_VERSION, GIT_COMMIT_SHORT);
|
||||||
Display->SetBuffer(1);
|
Display->SetBuffer(1);
|
||||||
PutCharBufferIndex = 0;
|
PutCharBufferIndex = 0;
|
||||||
}
|
}
|
||||||
@ -434,13 +454,13 @@ EXTERNC NIF void Main()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
File dev = vfs->Open("/dev");
|
File dev = vfs->Open("/dev");
|
||||||
if (dev.node->Flags != NodeFlags::DIRECTORY)
|
if (dev.GetFlags() != NodeFlags::DIRECTORY)
|
||||||
{
|
{
|
||||||
KPrint("\eE85230/dev is not a directory! Halting...");
|
KPrint("\eE85230/dev is not a directory! Halting...");
|
||||||
CPU::Stop();
|
CPU::Stop();
|
||||||
}
|
}
|
||||||
vfs->Close(dev);
|
vfs->Close(dev);
|
||||||
DevFS = dev.node;
|
DevFS = dev.GetNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vfs->PathExists("/mnt"))
|
if (!vfs->PathExists("/mnt"))
|
||||||
@ -448,13 +468,13 @@ EXTERNC NIF void Main()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
File mnt = vfs->Open("/mnt");
|
File mnt = vfs->Open("/mnt");
|
||||||
if (mnt.node->Flags != NodeFlags::DIRECTORY)
|
if (mnt.GetFlags() != NodeFlags::DIRECTORY)
|
||||||
{
|
{
|
||||||
KPrint("\eE85230/mnt is not a directory! Halting...");
|
KPrint("\eE85230/mnt is not a directory! Halting...");
|
||||||
CPU::Stop();
|
CPU::Stop();
|
||||||
}
|
}
|
||||||
vfs->Close(mnt);
|
vfs->Close(mnt);
|
||||||
MntFS = mnt.node;
|
MntFS = mnt.GetNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vfs->PathExists("/proc"))
|
if (!vfs->PathExists("/proc"))
|
||||||
@ -462,13 +482,41 @@ EXTERNC NIF void Main()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
File proc = vfs->Open("/proc", nullptr);
|
File proc = vfs->Open("/proc", nullptr);
|
||||||
if (proc.node->Flags != NodeFlags::DIRECTORY)
|
if (proc.GetFlags() != NodeFlags::DIRECTORY)
|
||||||
{
|
{
|
||||||
KPrint("\eE85230/proc is not a directory! Halting...");
|
KPrint("\eE85230/proc is not a directory! Halting...");
|
||||||
CPU::Stop();
|
CPU::Stop();
|
||||||
}
|
}
|
||||||
vfs->Close(proc);
|
vfs->Close(proc);
|
||||||
ProcFS = proc.node;
|
ProcFS = proc.GetNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vfs->PathExists("/var"))
|
||||||
|
VarLogFS = vfs->Create("/var", NodeFlags::DIRECTORY);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
File var = vfs->Open("/var", nullptr);
|
||||||
|
if (var.GetFlags() != NodeFlags::DIRECTORY)
|
||||||
|
{
|
||||||
|
KPrint("\eE85230/var is not a directory! Halting...");
|
||||||
|
CPU::Stop();
|
||||||
|
}
|
||||||
|
vfs->Close(var);
|
||||||
|
VarLogFS = var.GetNode();
|
||||||
|
|
||||||
|
if (!vfs->PathExists("/var/log"))
|
||||||
|
VarLogFS = vfs->Create("/var/log", NodeFlags::DIRECTORY);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
File var_log = vfs->Open("/var/log", nullptr);
|
||||||
|
if (var_log.GetFlags() != NodeFlags::DIRECTORY)
|
||||||
|
{
|
||||||
|
KPrint("\eE85230/var/log is not a directory! Halting...");
|
||||||
|
CPU::Stop();
|
||||||
|
}
|
||||||
|
vfs->Close(var_log);
|
||||||
|
VarLogFS = var_log.GetNode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KPrint("\e058C19################################");
|
KPrint("\e058C19################################");
|
||||||
@ -552,7 +600,7 @@ EXTERNC __no_stack_protector void BeforeShutdown(bool Reboot)
|
|||||||
if (DriverManager)
|
if (DriverManager)
|
||||||
delete DriverManager, DriverManager = nullptr;
|
delete DriverManager, DriverManager = nullptr;
|
||||||
|
|
||||||
if (TaskManager)
|
if (TaskManager && !TaskManager->IsPanic())
|
||||||
{
|
{
|
||||||
TaskManager->SignalShutdown();
|
TaskManager->SignalShutdown();
|
||||||
delete TaskManager, TaskManager = nullptr;
|
delete TaskManager, TaskManager = nullptr;
|
||||||
|
@ -51,6 +51,7 @@ Recovery::KernelRecovery *RecoveryScreen = nullptr;
|
|||||||
VirtualFileSystem::Node *DevFS = nullptr;
|
VirtualFileSystem::Node *DevFS = nullptr;
|
||||||
VirtualFileSystem::Node *MntFS = nullptr;
|
VirtualFileSystem::Node *MntFS = nullptr;
|
||||||
VirtualFileSystem::Node *ProcFS = nullptr;
|
VirtualFileSystem::Node *ProcFS = nullptr;
|
||||||
|
VirtualFileSystem::Node *VarLogFS = nullptr;
|
||||||
|
|
||||||
NewLock(ShutdownLock);
|
NewLock(ShutdownLock);
|
||||||
|
|
||||||
@ -226,27 +227,26 @@ void TestSyscallsKernel()
|
|||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
std::vector<AuxiliaryVector>(),
|
std::vector<AuxiliaryVector>(),
|
||||||
0,
|
|
||||||
Tasking::TaskArchitecture::x64,
|
Tasking::TaskArchitecture::x64,
|
||||||
Tasking::TaskCompatibility::Native,
|
Tasking::TaskCompatibility::Native,
|
||||||
true);
|
true);
|
||||||
SyscallsTestThread->SetCritical(true);
|
SyscallsTestThread->SetCritical(true);
|
||||||
TaskManager->GetSecurityManager()->TrustToken(SyscallsTestThread->Security.UniqueToken, Tasking::TTL::FullTrust);
|
TaskManager->GetSecurityManager()->TrustToken(SyscallsTestThread->Security.UniqueToken, Tasking::TTL::FullTrust);
|
||||||
|
|
||||||
Memory::Virtual va = Memory::Virtual(SyscallsTestProcess->PageTable);
|
Memory::Virtual vmm = Memory::Virtual(SyscallsTestProcess->PageTable);
|
||||||
|
|
||||||
// va.Remap((void *)TestSyscalls, va.GetPhysical((void *)TestSyscalls), Memory::P | Memory::RW | Memory::US);
|
// vmm.Remap((void *)TestSyscalls, vmm.GetPhysical((void *)TestSyscalls), Memory::P | Memory::RW | Memory::US);
|
||||||
|
|
||||||
// for (uintptr_t k = (uintptr_t)&_kernel_start; k < (uintptr_t)&_kernel_end; k += PAGE_SIZE)
|
// for (uintptr_t k = (uintptr_t)&_kernel_start; k < (uintptr_t)&_kernel_end; k += PAGE_SIZE)
|
||||||
// {
|
// {
|
||||||
// va.Remap((void *)k, (void *)va.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US);
|
// vmm.Remap((void *)k, (void *)vmm.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US);
|
||||||
// debug("Remapped %#lx %#lx", k, va.GetPhysical((void *)k));
|
// debug("Remapped %#lx %#lx", k, vmm.GetPhysical((void *)k));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
for (uintptr_t k = (uintptr_t)TestSyscalls - PAGE_SIZE; k < (uintptr_t)TestSyscalls + FROM_PAGES(5); k += PAGE_SIZE)
|
for (uintptr_t k = (uintptr_t)TestSyscalls - PAGE_SIZE; k < (uintptr_t)TestSyscalls + FROM_PAGES(5); k += PAGE_SIZE)
|
||||||
{
|
{
|
||||||
va.Remap((void *)k, (void *)va.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US);
|
vmm.Remap((void *)k, (void *)vmm.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US);
|
||||||
debug("Remapped %#lx %#lx", k, va.GetPhysical((void *)k));
|
debug("Remapped %#lx %#lx", k, vmm.GetPhysical((void *)k));
|
||||||
}
|
}
|
||||||
|
|
||||||
SyscallsTestThread->Status = Tasking::TaskStatus::Ready;
|
SyscallsTestThread->Status = Tasking::TaskStatus::Ready;
|
||||||
@ -274,7 +274,7 @@ Execute::SpawnData SpawnInit()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Files: 0.tga 1.tga ... 26.tga */
|
/* Files: 0.tga 1.tga ... 26.tga */
|
||||||
void *Frames[27];
|
uint8_t *Frames[27];
|
||||||
uint32_t FrameSizes[27];
|
uint32_t FrameSizes[27];
|
||||||
size_t FrameCount = 1;
|
size_t FrameCount = 1;
|
||||||
|
|
||||||
@ -292,9 +292,9 @@ void BootLogoAnimationThread()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameSizes[FrameCount] = s_cst(uint32_t, ba.node->Length);
|
FrameSizes[FrameCount] = s_cst(uint32_t, ba.GetLength());
|
||||||
Frames[FrameCount] = new uint8_t[ba.node->Length];
|
Frames[FrameCount] = new uint8_t[ba.GetLength()];
|
||||||
memcpy((void *)Frames[FrameCount], (void *)ba.node->Address, ba.node->Length);
|
vfs->Read(ba, Frames[FrameCount], ba.GetLength());
|
||||||
vfs->Close(ba);
|
vfs->Close(ba);
|
||||||
FrameCount++;
|
FrameCount++;
|
||||||
}
|
}
|
||||||
@ -425,7 +425,7 @@ void KernelMainThread()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
Tasking::TCB *tskMgr = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr);
|
TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr);
|
||||||
TreeFS(vfs->GetRootNode(), 0);
|
TreeFS(vfs->GetRootNode(), 0);
|
||||||
TestSyscallsKernel();
|
TestSyscallsKernel();
|
||||||
#endif
|
#endif
|
||||||
@ -462,7 +462,7 @@ void KernelMainThread()
|
|||||||
Execute::SpawnData ret = {Execute::ExStatus::Unknown, nullptr, nullptr};
|
Execute::SpawnData ret = {Execute::ExStatus::Unknown, nullptr, nullptr};
|
||||||
Tasking::TCB *ExecuteThread = nullptr;
|
Tasking::TCB *ExecuteThread = nullptr;
|
||||||
int ExitCode = -1;
|
int ExitCode = -1;
|
||||||
ExecuteThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)Execute::StartExecuteService);
|
ExecuteThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)Execute::LibraryManagerService);
|
||||||
ExecuteThread->Rename("Library Manager");
|
ExecuteThread->Rename("Library Manager");
|
||||||
ExecuteThread->SetCritical(true);
|
ExecuteThread->SetCritical(true);
|
||||||
ExecuteThread->SetPriority(Tasking::Idle);
|
ExecuteThread->SetPriority(Tasking::Idle);
|
||||||
@ -499,7 +499,8 @@ void KernelMainThread()
|
|||||||
Exit:
|
Exit:
|
||||||
if (ExitCode != 0)
|
if (ExitCode != 0)
|
||||||
{
|
{
|
||||||
KPrint("\eE85230Userspace process exited with code %d", ExitCode);
|
KPrint("\eE85230Userspace process exited with code %d (%#x)", ExitCode,
|
||||||
|
ExitCode < 0 ? ExitCode * -1 : ExitCode);
|
||||||
KPrint("Dropping to recovery screen...");
|
KPrint("Dropping to recovery screen...");
|
||||||
TaskManager->Sleep(2500);
|
TaskManager->Sleep(2500);
|
||||||
TaskManager->WaitForThread(blaThread);
|
TaskManager->WaitForThread(blaThread);
|
||||||
|
@ -1,294 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Fennix Kernel.
|
|
||||||
|
|
||||||
Fennix Kernel is free software: you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fennix Kernel is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
// TODO: complete implementation for everything
|
|
||||||
// TODO: https://wiki.osdev.org/C%2B%2B
|
|
||||||
|
|
||||||
#define ATEXIT_MAX_FUNCS 128
|
|
||||||
|
|
||||||
typedef unsigned uarch_t;
|
|
||||||
|
|
||||||
struct atexit_func_entry_t
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Each member is at least 4 bytes large. Such that each entry is 12bytes.
|
|
||||||
* 128 * 12 = 1.5KB exact.
|
|
||||||
**/
|
|
||||||
void (*destructor_func)(void *);
|
|
||||||
void *obj_ptr;
|
|
||||||
void *dso_handle;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
_URC_NO_REASON = 0,
|
|
||||||
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
|
|
||||||
_URC_FATAL_PHASE2_ERROR = 2,
|
|
||||||
_URC_FATAL_PHASE1_ERROR = 3,
|
|
||||||
_URC_NORMAL_STOP = 4,
|
|
||||||
_URC_END_OF_STACK = 5,
|
|
||||||
_URC_HANDLER_FOUND = 6,
|
|
||||||
_URC_INSTALL_CONTEXT = 7,
|
|
||||||
_URC_CONTINUE_UNWIND = 8
|
|
||||||
} _Unwind_Reason_Code;
|
|
||||||
|
|
||||||
struct _Unwind_Context;
|
|
||||||
typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
|
|
||||||
typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__)));
|
|
||||||
typedef unsigned _Unwind_Word __attribute__((__mode__(__unwind_word__)));
|
|
||||||
typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code, struct _Unwind_Exception *);
|
|
||||||
typedef int _Unwind_Action;
|
|
||||||
|
|
||||||
struct type_info
|
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct unexpected_handler
|
|
||||||
{
|
|
||||||
void (*unexpected)();
|
|
||||||
};
|
|
||||||
|
|
||||||
struct terminate_handler
|
|
||||||
{
|
|
||||||
void (*handler)();
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Unwind_Exception
|
|
||||||
{
|
|
||||||
_Unwind_Exception_Class exception_class;
|
|
||||||
_Unwind_Exception_Cleanup_Fn exception_cleanup;
|
|
||||||
#if !defined(__USING_SJLJ_EXCEPTIONS__) && defined(__SEH__)
|
|
||||||
_Unwind_Word private_[6];
|
|
||||||
#else
|
|
||||||
_Unwind_Word private_1;
|
|
||||||
_Unwind_Word private_2;
|
|
||||||
#endif
|
|
||||||
} __attribute__((__aligned__));
|
|
||||||
|
|
||||||
struct __cxa_exception
|
|
||||||
{
|
|
||||||
#if __LP64__
|
|
||||||
size_t referenceCount;
|
|
||||||
#endif
|
|
||||||
type_info *exceptionType;
|
|
||||||
void (*exceptionDestructor)(void *);
|
|
||||||
unexpected_handler unexpectedHandler;
|
|
||||||
terminate_handler terminateHandler;
|
|
||||||
__cxa_exception *nextException;
|
|
||||||
int handlerCount;
|
|
||||||
|
|
||||||
#ifdef __ARM_EABI_UNWINDER__
|
|
||||||
__cxa_exception *nextPropagatingException;
|
|
||||||
int propagationCount;
|
|
||||||
#else
|
|
||||||
int handlerSwitchValue;
|
|
||||||
const unsigned char *actionRecord;
|
|
||||||
const unsigned char *languageSpecificData;
|
|
||||||
_Unwind_Ptr catchTemp;
|
|
||||||
void *adjustedPtr;
|
|
||||||
#endif
|
|
||||||
#if !__LP64__
|
|
||||||
size_t referenceCount;
|
|
||||||
#endif
|
|
||||||
_Unwind_Exception unwindHeader;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* extern */ void *__dso_handle = 0;
|
|
||||||
atexit_func_entry_t __atexit_funcs[ATEXIT_MAX_FUNCS];
|
|
||||||
uarch_t __atexit_func_count = 0;
|
|
||||||
|
|
||||||
extern "C" int __cxa_atexit(void (*f)(void *), void *objptr, void *dso)
|
|
||||||
{
|
|
||||||
fixme("__cxa_atexit( %p %p %p ) triggered.", f, objptr, dso);
|
|
||||||
if (__atexit_func_count >= ATEXIT_MAX_FUNCS)
|
|
||||||
return -1;
|
|
||||||
__atexit_funcs[__atexit_func_count].destructor_func = f;
|
|
||||||
__atexit_funcs[__atexit_func_count].obj_ptr = objptr;
|
|
||||||
__atexit_funcs[__atexit_func_count].dso_handle = dso;
|
|
||||||
__atexit_func_count++;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void __cxa_finalize(void *f)
|
|
||||||
{
|
|
||||||
fixme("__cxa_finalize( %p ) triggered.", f);
|
|
||||||
uarch_t i = __atexit_func_count;
|
|
||||||
if (!f)
|
|
||||||
{
|
|
||||||
while (i--)
|
|
||||||
if (__atexit_funcs[i].destructor_func)
|
|
||||||
(*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (i--)
|
|
||||||
if (__atexit_funcs[i].destructor_func == f)
|
|
||||||
{
|
|
||||||
(*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr);
|
|
||||||
__atexit_funcs[i].destructor_func = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" _Unwind_Reason_Code __gxx_personality_v0(int version, _Unwind_Action actions, _Unwind_Exception_Class exception_class, _Unwind_Exception *ue_header, _Unwind_Context *context)
|
|
||||||
{
|
|
||||||
fixme("__gxx_personality_v0( %d %p %p %p %p ) triggered.", version, actions, exception_class, ue_header, context);
|
|
||||||
return _URC_NO_REASON;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void _Unwind_Resume(struct _Unwind_Exception *exc) { fixme("_Unwind_Resume( %p ) triggered.", exc); }
|
|
||||||
|
|
||||||
static inline size_t align_exception_allocation_size(size_t s, size_t a) { return (s + a - 1) & ~(a - 1); }
|
|
||||||
|
|
||||||
void unexpected_header_stub() { fixme("unexpected() called."); }
|
|
||||||
void terminate_header_stub() { fixme("terminate() called."); }
|
|
||||||
|
|
||||||
extern "C" void *__cxa_allocate_exception(size_t thrown_size) throw()
|
|
||||||
{
|
|
||||||
fixme("__cxa_allocate_exception( %d ) triggered.", thrown_size);
|
|
||||||
|
|
||||||
size_t real_size = align_exception_allocation_size(thrown_size + sizeof(__cxa_exception), alignof(__cxa_exception));
|
|
||||||
|
|
||||||
__cxa_exception *header = (__cxa_exception *)kmalloc(real_size);
|
|
||||||
if (!header)
|
|
||||||
{
|
|
||||||
error("Failed to allocate exception.");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
header->referenceCount = 1;
|
|
||||||
header->exceptionType = nullptr;
|
|
||||||
header->exceptionDestructor = nullptr;
|
|
||||||
header->unexpectedHandler = {.unexpected = unexpected_header_stub};
|
|
||||||
header->terminateHandler = {.handler = terminate_header_stub};
|
|
||||||
header->nextException = nullptr;
|
|
||||||
header->handlerCount = -1;
|
|
||||||
header->handlerSwitchValue = 0;
|
|
||||||
header->actionRecord = nullptr;
|
|
||||||
header->languageSpecificData = nullptr;
|
|
||||||
header->catchTemp = 0;
|
|
||||||
header->adjustedPtr = nullptr;
|
|
||||||
|
|
||||||
return header + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void _Unwind_RaiseException(_Unwind_Exception *exc)
|
|
||||||
{
|
|
||||||
fixme("_Unwind_RaiseException( %p ) triggered.", exc);
|
|
||||||
|
|
||||||
__cxa_exception *header = ((__cxa_exception *)exc) - 1;
|
|
||||||
if (header->terminateHandler.handler)
|
|
||||||
{
|
|
||||||
debug("Calling terminate handler.");
|
|
||||||
header->terminateHandler.handler();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error("Unhandled exception.");
|
|
||||||
CPU::Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
CPU::Halt(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void __cxa_throw(void *thrown_object, void *tinfo, void (*dest)(void *))
|
|
||||||
{
|
|
||||||
fixme("__cxa_throw( %p %p %p ) triggered.", thrown_object, tinfo, dest);
|
|
||||||
|
|
||||||
__cxa_exception *header = ((__cxa_exception *)thrown_object) - 1;
|
|
||||||
header->exceptionType = (type_info *)tinfo;
|
|
||||||
header->exceptionDestructor = dest;
|
|
||||||
|
|
||||||
_Unwind_RaiseException(&header->unwindHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void __cxa_rethrow() { fixme("__cxa_rethrow() triggered."); }
|
|
||||||
|
|
||||||
extern "C" void __cxa_pure_virtual() { fixme("__cxa_pure_virtual() triggered."); }
|
|
||||||
|
|
||||||
extern "C" void __cxa_throw_bad_array_new_length() { fixme("__cxa_throw_bad_array_new_length() triggered."); }
|
|
||||||
|
|
||||||
extern "C" void __cxa_free_exception(void *thrown_exception) { fixme("__cxa_free_exception( %p ) triggered.", thrown_exception); }
|
|
||||||
|
|
||||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
|
|
||||||
extern "C" void *__cxa_begin_catch(void *e) throw()
|
|
||||||
#else
|
|
||||||
extern "C" void *__cxa_begin_catch(void *e)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
fixme("__cxa_begin_catch( %p ) triggered.", e);
|
|
||||||
return (void *)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void __cxa_end_catch() { fixme("__cxa_end_catch() triggered."); }
|
|
||||||
|
|
||||||
__extension__ typedef int __guard __attribute__((mode(__DI__)));
|
|
||||||
|
|
||||||
extern "C" int __cxa_guard_acquire(__guard *g)
|
|
||||||
{
|
|
||||||
fixme("__cxa_guard_acquire( %p ) triggered.", g);
|
|
||||||
return !*(char *)(g);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void __cxa_guard_release(__guard *g)
|
|
||||||
{
|
|
||||||
fixme("__cxa_guard_release( %p ) triggered.", g);
|
|
||||||
*(char *)g = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void __cxa_guard_abort(__guard *g) { fixme("__cxa_guard_abort( %p ) triggered.", g); }
|
|
||||||
|
|
||||||
// vtable for __cxxabiv1::__class_type_info
|
|
||||||
extern "C" void *_ZTVN10__cxxabiv117__class_type_infoE(void)
|
|
||||||
{
|
|
||||||
fixme("_ZTVN10__cxxabiv117__class_type_infoE() triggered.");
|
|
||||||
return (void *)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// vtable for __cxxabiv1::__si_class_type_info
|
|
||||||
extern "C" void *_ZTVN10__cxxabiv120__si_class_type_infoE(void)
|
|
||||||
{
|
|
||||||
fixme("_ZTVN10__cxxabiv120__si_class_type_infoE() triggered.");
|
|
||||||
return (void *)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// typeinfo for int
|
|
||||||
extern "C" void *_ZTIi(void)
|
|
||||||
{
|
|
||||||
fixme("_ZTIi() triggered.");
|
|
||||||
return (void *)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// typeinfo for unsigned char*
|
|
||||||
extern "C" void *_ZTIPh(void)
|
|
||||||
{
|
|
||||||
fixme("_ZTIPh() triggered.");
|
|
||||||
return (void *)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// typeinfo for char const*
|
|
||||||
extern "C" void *_ZTIPKc(void)
|
|
||||||
{
|
|
||||||
fixme("_ZTIPKc() triggered.");
|
|
||||||
return (void *)0;
|
|
||||||
}
|
|
103
Library/libstdc++/class_type_info.cpp
Normal file
103
Library/libstdc++/class_type_info.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
namespace __cxxabiv1
|
||||||
|
{
|
||||||
|
__class_type_info::~__class_type_info() {}
|
||||||
|
|
||||||
|
bool __class_type_info::__do_upcast(const __class_type_info *Destination,
|
||||||
|
const void *Object,
|
||||||
|
__upcast_result &__restrict Result) const
|
||||||
|
{
|
||||||
|
if (*this != *Destination)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Result.dst_ptr = Object;
|
||||||
|
Result.base_type = nonvirtual_base_type;
|
||||||
|
Result.part2dst = __contained_public;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __class_type_info::__do_upcast(const __class_type_info *DestinationType,
|
||||||
|
void **ObjectPointer) const
|
||||||
|
{
|
||||||
|
__upcast_result Result(__vmi_class_type_info::__flags_unknown_mask);
|
||||||
|
|
||||||
|
__do_upcast(DestinationType, *ObjectPointer, Result);
|
||||||
|
|
||||||
|
if (!((Result.part2dst &
|
||||||
|
__class_type_info::__contained_public) ==
|
||||||
|
__class_type_info::__contained_public))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*ObjectPointer = const_cast<void *>(Result.dst_ptr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __class_type_info::__do_catch(const type_info *ThrowType,
|
||||||
|
void **ThrowObject,
|
||||||
|
unsigned Outer) const
|
||||||
|
{
|
||||||
|
if (*this == *ThrowType)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (Outer >= 4)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return ThrowType->__do_upcast(this, ThrowObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __class_type_info::__do_dyncast(ptrdiff_t,
|
||||||
|
__sub_kind AccessPath,
|
||||||
|
const __class_type_info *DestinationType,
|
||||||
|
const void *ObjectPointer,
|
||||||
|
const __class_type_info *SourceType,
|
||||||
|
const void *SourcePointer,
|
||||||
|
__dyncast_result &__restrict Result) const
|
||||||
|
{
|
||||||
|
if (ObjectPointer == SourcePointer &&
|
||||||
|
*this == *SourceType)
|
||||||
|
{
|
||||||
|
Result.whole2src = AccessPath;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*this == *DestinationType)
|
||||||
|
{
|
||||||
|
Result.dst_ptr = ObjectPointer;
|
||||||
|
Result.whole2dst = AccessPath;
|
||||||
|
Result.dst2src = __not_contained;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
__class_type_info::__sub_kind __class_type_info::__do_find_public_src(ptrdiff_t,
|
||||||
|
const void *ObjectPointer,
|
||||||
|
const __class_type_info *,
|
||||||
|
const void *SourcePointer) const
|
||||||
|
{
|
||||||
|
if (SourcePointer == ObjectPointer)
|
||||||
|
return __contained_public;
|
||||||
|
|
||||||
|
return __not_contained;
|
||||||
|
}
|
||||||
|
}
|
221
Library/libstdc++/cxxabi.cpp
Normal file
221
Library/libstdc++/cxxabi.cpp
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cxxabi.h>
|
||||||
|
|
||||||
|
#include <memory.hpp>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <smp.hpp>
|
||||||
|
|
||||||
|
#include "../../kernel.h"
|
||||||
|
|
||||||
|
void __dso_handle_stub() { stub; }
|
||||||
|
|
||||||
|
/* extern */ void *__dso_handle = (void *)&__dso_handle_stub;
|
||||||
|
|
||||||
|
namespace __cxxabiv1
|
||||||
|
{
|
||||||
|
atexit_func_entry_t __atexit_funcs[ATEXIT_MAX_FUNCS];
|
||||||
|
uarch_t __atexit_func_count = 0;
|
||||||
|
|
||||||
|
__cxa_eh_globals *__cxa_get_globals() noexcept
|
||||||
|
{
|
||||||
|
return &GetCurrentCPU()->EHGlobals;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int __cxa_atexit(void (*f)(void *), void *objptr, void *dso)
|
||||||
|
{
|
||||||
|
debug("Registering atexit function %p( %p, %p )",
|
||||||
|
f, objptr, dso);
|
||||||
|
|
||||||
|
if (__atexit_func_count >= ATEXIT_MAX_FUNCS)
|
||||||
|
return -1;
|
||||||
|
__atexit_funcs[__atexit_func_count].destructor_func = f;
|
||||||
|
__atexit_funcs[__atexit_func_count].obj_ptr = objptr;
|
||||||
|
__atexit_funcs[__atexit_func_count].dso_handle = dso;
|
||||||
|
__atexit_func_count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void __cxa_finalize(void *f)
|
||||||
|
{
|
||||||
|
fixme("__cxa_finalize( %p ) called.", f);
|
||||||
|
uarch_t i = __atexit_func_count;
|
||||||
|
if (!f)
|
||||||
|
{
|
||||||
|
while (i--)
|
||||||
|
if (__atexit_funcs[i].destructor_func)
|
||||||
|
(*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i--)
|
||||||
|
if (__atexit_funcs[i].destructor_func == f)
|
||||||
|
{
|
||||||
|
(*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr);
|
||||||
|
__atexit_funcs[i].destructor_func = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" _Unwind_Reason_Code __gxx_personality_v0(int version, _Unwind_Action actions, _Unwind_Exception_Class exception_class, _Unwind_Exception *ue_header, _Unwind_Context *context)
|
||||||
|
{
|
||||||
|
fixme("__gxx_personality_v0( %d %p %p %p %p ) called.", version, actions, exception_class, ue_header, context);
|
||||||
|
return _URC_NO_REASON;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void *__cxa_begin_catch(void *thrown_object) noexcept
|
||||||
|
{
|
||||||
|
function("%p", thrown_object);
|
||||||
|
|
||||||
|
__cxa_exception *Exception = (__cxa_exception *)thrown_object - 1;
|
||||||
|
__cxa_eh_globals *Globals = __cxa_get_globals();
|
||||||
|
|
||||||
|
Exception->handlerCount++;
|
||||||
|
Globals->uncaughtExceptions--;
|
||||||
|
|
||||||
|
Exception->nextException = Globals->caughtExceptions;
|
||||||
|
Globals->caughtExceptions = Exception;
|
||||||
|
return Exception + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void __cxa_end_catch()
|
||||||
|
{
|
||||||
|
fixme("__cxa_end_catch() called.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static __always_inline inline size_t align_exception_allocation_size(size_t a, size_t b)
|
||||||
|
{
|
||||||
|
return (a + b - 1) & ~(b - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __always_inline inline void INIT_EXCEPTION_CLASS(_Unwind_Exception_Class *c)
|
||||||
|
{
|
||||||
|
char *ptr = (char *)c;
|
||||||
|
ptr[0] = 'G';
|
||||||
|
ptr[1] = 'N';
|
||||||
|
ptr[2] = 'U';
|
||||||
|
ptr[3] = 'C';
|
||||||
|
ptr[4] = 'C';
|
||||||
|
ptr[5] = '+';
|
||||||
|
ptr[6] = '+';
|
||||||
|
ptr[7] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void unexpected_header_stub() { fixme("unexpected() called."); }
|
||||||
|
|
||||||
|
void terminate_header_stub()
|
||||||
|
{
|
||||||
|
if (TaskManager && !TaskManager->IsPanic())
|
||||||
|
{
|
||||||
|
TaskManager->KillThread(TaskManager->GetCurrentThread(), Tasking::KILL_CXXABI_EXCEPTION);
|
||||||
|
TaskManager->Schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
error("No task manager to kill thread!");
|
||||||
|
CPU::Stop(); /* FIXME: Panic */
|
||||||
|
}
|
||||||
|
|
||||||
|
void exception_cleanup_stub(_Unwind_Reason_Code Code,
|
||||||
|
_Unwind_Exception *Exception)
|
||||||
|
{
|
||||||
|
fixme("exception_cleanup( %d %p ) called.",
|
||||||
|
Code, Exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void *__cxa_allocate_exception(size_t thrown_size) throw()
|
||||||
|
{
|
||||||
|
debug("Allocating exception of size %d.", thrown_size);
|
||||||
|
|
||||||
|
size_t alloc_size = align_exception_allocation_size(thrown_size + sizeof(__cxa_exception), alignof(__cxa_exception));
|
||||||
|
__cxa_exception *Exception = (__cxa_exception *)kmalloc(alloc_size);
|
||||||
|
memset(Exception, 0, alloc_size);
|
||||||
|
return Exception + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" __noreturn void __cxa_throw(void *thrown_object,
|
||||||
|
std::type_info *tinfo,
|
||||||
|
void (*dest)(void *))
|
||||||
|
{
|
||||||
|
trace("Throwing exception of type \"%s\". ( object: %p, destructor: %p )",
|
||||||
|
tinfo->name(), thrown_object, dest);
|
||||||
|
|
||||||
|
__cxa_eh_globals *Globals = __cxa_get_globals();
|
||||||
|
Globals->uncaughtExceptions++;
|
||||||
|
|
||||||
|
__cxa_exception *Exception = (__cxa_exception *)thrown_object - 1;
|
||||||
|
Exception->exceptionType = (std::type_info *)tinfo;
|
||||||
|
Exception->exceptionDestructor = dest;
|
||||||
|
Exception->unexpectedHandler = &unexpected_header_stub;
|
||||||
|
Exception->terminateHandler = &terminate_header_stub;
|
||||||
|
Exception->unwindHeader.exception_cleanup = &exception_cleanup_stub;
|
||||||
|
INIT_EXCEPTION_CLASS(&Exception->unwindHeader.exception_class);
|
||||||
|
Exception->adjustedPtr = thrown_object;
|
||||||
|
|
||||||
|
_Unwind_RaiseException(&Exception->unwindHeader);
|
||||||
|
__cxa_begin_catch(&Exception->unwindHeader);
|
||||||
|
|
||||||
|
error("Uncaught exception!");
|
||||||
|
CPU::Stop(); /* FIXME: Panic */
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void __cxa_rethrow()
|
||||||
|
{
|
||||||
|
fixme("__cxa_rethrow() called.");
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void __cxa_pure_virtual()
|
||||||
|
{
|
||||||
|
fixme("__cxa_pure_virtual() called.");
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void __cxa_throw_bad_array_new_length()
|
||||||
|
{
|
||||||
|
fixme("__cxa_throw_bad_array_new_length() called.");
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void __cxa_free_exception(void *thrown_exception)
|
||||||
|
{
|
||||||
|
fixme("__cxa_free_exception( %p ) called.",
|
||||||
|
thrown_exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
__extension__ typedef int __guard __attribute__((mode(__DI__)));
|
||||||
|
|
||||||
|
extern "C" int __cxa_guard_acquire(__guard *g)
|
||||||
|
{
|
||||||
|
fixme("__cxa_guard_acquire( %p ) called.", g);
|
||||||
|
return !*(char *)(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void __cxa_guard_release(__guard *g)
|
||||||
|
{
|
||||||
|
fixme("__cxa_guard_release( %p ) called.", g);
|
||||||
|
*(char *)g = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void __cxa_guard_abort(__guard *g)
|
||||||
|
{
|
||||||
|
fixme("__cxa_guard_abort( %p ) called.", g);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" __noreturn void __cxa_bad_typeid()
|
||||||
|
{
|
||||||
|
fixme("__cxa_bad_typeid() called.");
|
||||||
|
CPU::Stop(); /* FIXME: Crash the system */
|
||||||
|
}
|
||||||
|
}
|
@ -15,24 +15,9 @@
|
|||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <exec.hpp>
|
#include <typeinfo>
|
||||||
|
|
||||||
#include <memory.hpp>
|
namespace __cxxabiv1
|
||||||
#include <lock.hpp>
|
|
||||||
#include <msexec.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#include <abi.h>
|
|
||||||
|
|
||||||
#include "../../kernel.h"
|
|
||||||
#include "../../Fex.hpp"
|
|
||||||
|
|
||||||
using namespace Tasking;
|
|
||||||
|
|
||||||
namespace Execute
|
|
||||||
{
|
{
|
||||||
void FEXLoad()
|
__fundamental_type_info::~__fundamental_type_info() {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
88
Library/libstdc++/pbase_type_info.cpp
Normal file
88
Library/libstdc++/pbase_type_info.cpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
namespace __cxxabiv1
|
||||||
|
{
|
||||||
|
__pbase_type_info::~__pbase_type_info() {}
|
||||||
|
|
||||||
|
bool __pbase_type_info::__do_catch(const type_info *ThrowType,
|
||||||
|
void **ThrowObject,
|
||||||
|
unsigned outer) const
|
||||||
|
{
|
||||||
|
#ifndef __GXX_RTTI
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
if (*this == *ThrowType)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (*ThrowType == typeid(nullptr))
|
||||||
|
{
|
||||||
|
if (typeid(*this) == typeid(__pointer_type_info))
|
||||||
|
{
|
||||||
|
*ThrowObject = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (typeid(*this) == typeid(__pointer_to_member_type_info))
|
||||||
|
{
|
||||||
|
if (this->Pointee->__is_function_p())
|
||||||
|
{
|
||||||
|
using pmf_type = void (__pbase_type_info::*)();
|
||||||
|
static const pmf_type pmf = nullptr;
|
||||||
|
*ThrowObject = const_cast<pmf_type *>(&pmf);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using pm_type = int __pbase_type_info::*;
|
||||||
|
static const pm_type pm = nullptr;
|
||||||
|
*ThrowObject = const_cast<pm_type *>(&pm);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeid(*this) != typeid(*ThrowType))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!(outer & 1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const __pbase_type_info *ThrownType =
|
||||||
|
static_cast<const __pbase_type_info *>(ThrowType);
|
||||||
|
|
||||||
|
unsigned TypeFlags = ThrownType->Flags;
|
||||||
|
|
||||||
|
const unsigned FlagQualificationMask = __transaction_safe_mask | __noexcept_mask;
|
||||||
|
unsigned ThrowFlagQualification = (TypeFlags & FlagQualificationMask);
|
||||||
|
unsigned CatchFlagQualification = (Flags & FlagQualificationMask);
|
||||||
|
if (ThrowFlagQualification & ~CatchFlagQualification)
|
||||||
|
TypeFlags &= CatchFlagQualification;
|
||||||
|
if (CatchFlagQualification & ~ThrowFlagQualification)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (TypeFlags & ~Flags)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!(Flags & __const_mask))
|
||||||
|
outer &= ~1;
|
||||||
|
|
||||||
|
return __pointer_catch(ThrownType, ThrowObject, outer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
42
Library/libstdc++/pointer_type_info.cpp
Normal file
42
Library/libstdc++/pointer_type_info.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
namespace __cxxabiv1
|
||||||
|
{
|
||||||
|
__pointer_type_info::~__pointer_type_info() {}
|
||||||
|
|
||||||
|
bool __pointer_type_info::__is_pointer_p() const { return true; }
|
||||||
|
|
||||||
|
bool __pointer_type_info::__pointer_catch(const __pbase_type_info *ThrownType,
|
||||||
|
void **ThrowObject,
|
||||||
|
unsigned Outer) const
|
||||||
|
{
|
||||||
|
#ifndef __GXX_RTTI
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
if (Outer < 2 && *this->Pointee == typeid(void))
|
||||||
|
return !ThrownType->Pointee->__is_function_p();
|
||||||
|
|
||||||
|
return __pbase_type_info::__pointer_catch(ThrownType,
|
||||||
|
ThrowObject,
|
||||||
|
Outer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
102
Library/libstdc++/si_class_type_info.cpp
Normal file
102
Library/libstdc++/si_class_type_info.cpp
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
namespace __cxxabiv1
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
inline const T *adjust_pointer(const void *Base,
|
||||||
|
ptrdiff_t Offset)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const T *>(reinterpret_cast<const char *>(Base) + Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
__si_class_type_info::~__si_class_type_info() {}
|
||||||
|
|
||||||
|
__class_type_info::__sub_kind __si_class_type_info::
|
||||||
|
__do_find_public_src(ptrdiff_t SourceToDestination,
|
||||||
|
const void *ObjectPointer,
|
||||||
|
const __class_type_info *SourceType,
|
||||||
|
const void *SourcePointer) const
|
||||||
|
{
|
||||||
|
if (SourcePointer == ObjectPointer && *this == *SourceType)
|
||||||
|
return __contained_public;
|
||||||
|
|
||||||
|
return this->BaseType->__do_find_public_src(SourceToDestination,
|
||||||
|
ObjectPointer,
|
||||||
|
SourceType,
|
||||||
|
SourcePointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __si_class_type_info::__do_dyncast(ptrdiff_t SourceToDestination,
|
||||||
|
__sub_kind AccessPath,
|
||||||
|
const __class_type_info *DestinationType,
|
||||||
|
const void *ObjectPointer,
|
||||||
|
const __class_type_info *SourceType,
|
||||||
|
const void *SourcePointer,
|
||||||
|
__dyncast_result &__restrict Result) const
|
||||||
|
{
|
||||||
|
if (*this == *DestinationType)
|
||||||
|
{
|
||||||
|
Result.dst_ptr = ObjectPointer;
|
||||||
|
Result.whole2dst = AccessPath;
|
||||||
|
|
||||||
|
if (SourceToDestination == -2)
|
||||||
|
{
|
||||||
|
Result.dst2src = __not_contained;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SourceToDestination >= 0)
|
||||||
|
{
|
||||||
|
Result.dst2src = adjust_pointer<void>(ObjectPointer,
|
||||||
|
SourceToDestination) == SourcePointer
|
||||||
|
? __contained_public
|
||||||
|
: __not_contained;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ObjectPointer == SourcePointer &&
|
||||||
|
*this == *SourceType)
|
||||||
|
{
|
||||||
|
Result.whole2src = AccessPath;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->BaseType->__do_dyncast(SourceToDestination,
|
||||||
|
AccessPath,
|
||||||
|
DestinationType,
|
||||||
|
ObjectPointer,
|
||||||
|
SourceType,
|
||||||
|
SourcePointer,
|
||||||
|
Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __si_class_type_info::__do_upcast(const __class_type_info *Destination,
|
||||||
|
const void *ObjectPointer,
|
||||||
|
__upcast_result &__restrict Result) const
|
||||||
|
{
|
||||||
|
if (__class_type_info::__do_upcast(Destination, ObjectPointer, Result))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return this->BaseType->__do_upcast(Destination, ObjectPointer, Result);
|
||||||
|
}
|
||||||
|
}
|
@ -15,30 +15,27 @@
|
|||||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <exec.hpp>
|
#include <unwind.h>
|
||||||
|
#include <cxxabi.h>
|
||||||
#include <memory.hpp>
|
#include <debug.h>
|
||||||
#include <lock.hpp>
|
#include <cpu.hpp>
|
||||||
#include <msexec.h>
|
#include <smp.hpp>
|
||||||
#include <cwalk.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#include <abi.h>
|
|
||||||
|
|
||||||
#include "../../kernel.h"
|
#include "../../kernel.h"
|
||||||
#include "../../Fex.hpp"
|
|
||||||
|
|
||||||
using namespace Tasking;
|
using namespace __cxxabiv1;
|
||||||
|
|
||||||
namespace Execute
|
#if (1) /* Stubs if libgcc is not present */
|
||||||
|
extern "C" _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *Exception)
|
||||||
{
|
{
|
||||||
ELFBaseLoad ELFLoadDyn(void *BaseImage,
|
fixme("_Unwind_RaiseException( %p ) called.", Exception);
|
||||||
VirtualFileSystem::File &ExFile,
|
error("Unhandled exception.");
|
||||||
Tasking::PCB *Process)
|
return _URC_FATAL_PHASE1_ERROR;
|
||||||
|
// return _URC_NO_REASON;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void _Unwind_Resume(struct _Unwind_Exception *Exception)
|
||||||
{
|
{
|
||||||
UNUSED(BaseImage);
|
fixme("_Unwind_Resume( %p ) called.", Exception);
|
||||||
UNUSED(ExFile);
|
|
||||||
UNUSED(Process);
|
|
||||||
fixme("Not implemented");
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif
|
39
Library/std/typeinfo.cpp
Normal file
39
Library/std/typeinfo.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
type_info::~type_info() {}
|
||||||
|
|
||||||
|
bool type_info::__do_catch(const type_info *ThrowType,
|
||||||
|
void **ThrowObject,
|
||||||
|
unsigned Outer) const
|
||||||
|
{
|
||||||
|
stub;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool type_info::__do_upcast(const __cxxabiv1::__class_type_info *Target,
|
||||||
|
void **ObjectPointer) const
|
||||||
|
{
|
||||||
|
stub;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
22
Makefile
22
Makefile
@ -27,29 +27,26 @@ S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./Architecture/i386/
|
|||||||
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
|
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
|
||||||
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
|
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
|
||||||
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
|
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
|
||||||
RS_SOURCES = $(shell find ./ -type f -name '*.rs' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
|
|
||||||
else ifeq ($(OSARCH), i386)
|
else ifeq ($(OSARCH), i386)
|
||||||
ASM_SOURCES = $(shell find ./ -type f -name '*.asm' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
|
ASM_SOURCES = $(shell find ./ -type f -name '*.asm' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
|
||||||
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
|
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
|
||||||
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
|
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
|
||||||
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
|
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
|
||||||
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
|
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
|
||||||
RS_SOURCES = $(shell find ./ -type f -name '*.rs' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
|
|
||||||
else ifeq ($(OSARCH), aarch64)
|
else ifeq ($(OSARCH), aarch64)
|
||||||
ASM_SOURCES = $(shell find ./ -type f -name '*.asm' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
|
ASM_SOURCES = $(shell find ./ -type f -name '*.asm' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
|
||||||
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
|
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
|
||||||
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
|
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
|
||||||
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
|
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
|
||||||
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
|
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
|
||||||
RS_SOURCES = $(shell find ./ -type f -name '*.rs' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
|
|
||||||
endif
|
endif
|
||||||
HEADERS = $(sort $(dir $(wildcard ./include/*))) $(sort $(dir $(wildcard ./include_std/*)))
|
HEADERS = $(sort $(dir $(wildcard ./include/*))) $(sort $(dir $(wildcard ./include_std/*)))
|
||||||
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(RS_SOURCES:.rs=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(s_SOURCES:.s=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
|
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(s_SOURCES:.s=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
|
||||||
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
|
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
|
||||||
GCNO_OBJ = $(C_SOURCES:.c=.gcno) $(CPP_SOURCES:.cpp=.gcno)
|
GCNO_OBJ = $(C_SOURCES:.c=.gcno) $(CPP_SOURCES:.cpp=.gcno)
|
||||||
INCLUDE_DIR = -I./include -I./include_std
|
INCLUDE_DIR = -I./include -I./include_std
|
||||||
|
|
||||||
LDFLAGS := -Wl,-Map kernel.map -shared -nostdlib -nodefaultlibs -nolibc
|
LDFLAGS := -Wl,-Map kernel.map -static -nostdlib -nodefaultlibs -nolibc
|
||||||
|
|
||||||
# Disable all warnings by adding "-w" in WARNCFLAG and if you want to treat the warnings as errors, add "-Werror"
|
# Disable all warnings by adding "-w" in WARNCFLAG and if you want to treat the warnings as errors, add "-Werror"
|
||||||
WARNCFLAG = -Wall -Wextra \
|
WARNCFLAG = -Wall -Wextra \
|
||||||
@ -76,9 +73,8 @@ CFLAG_STACK_PROTECTOR := -fstack-protector-all
|
|||||||
LDFLAGS += -TArchitecture/amd64/linker.ld \
|
LDFLAGS += -TArchitecture/amd64/linker.ld \
|
||||||
-fno-pic -fno-pie \
|
-fno-pic -fno-pie \
|
||||||
-Wl,-static,--no-dynamic-linker,-ztext \
|
-Wl,-static,--no-dynamic-linker,-ztext \
|
||||||
-nostdlib -nodefaultlibs -nolibc \
|
|
||||||
-zmax-page-size=0x1000 \
|
-zmax-page-size=0x1000 \
|
||||||
-Wl,-Map kernel.map -shared
|
-Wl,-Map kernel.map
|
||||||
|
|
||||||
else ifeq ($(OSARCH), i386)
|
else ifeq ($(OSARCH), i386)
|
||||||
|
|
||||||
@ -89,9 +85,8 @@ CFLAG_STACK_PROTECTOR := -fstack-protector-all
|
|||||||
LDFLAGS += -TArchitecture/i386/linker.ld \
|
LDFLAGS += -TArchitecture/i386/linker.ld \
|
||||||
-fno-pic -fno-pie \
|
-fno-pic -fno-pie \
|
||||||
-Wl,-static,--no-dynamic-linker,-ztext \
|
-Wl,-static,--no-dynamic-linker,-ztext \
|
||||||
-nostdlib -nodefaultlibs -nolibc \
|
|
||||||
-zmax-page-size=0x1000 \
|
-zmax-page-size=0x1000 \
|
||||||
-Wl,-Map kernel.map -shared
|
-Wl,-Map kernel.map
|
||||||
|
|
||||||
else ifeq ($(OSARCH), aarch64)
|
else ifeq ($(OSARCH), aarch64)
|
||||||
|
|
||||||
@ -99,9 +94,8 @@ CFLAGS += -pipe -fno-builtin -Wstack-protector -Daa64 -fPIC -mno-outline-atomics
|
|||||||
CFLAG_STACK_PROTECTOR := -fstack-protector-all
|
CFLAG_STACK_PROTECTOR := -fstack-protector-all
|
||||||
LDFLAGS += -TArchitecture/aarch64/linker.ld -fPIC -pie \
|
LDFLAGS += -TArchitecture/aarch64/linker.ld -fPIC -pie \
|
||||||
-Wl,-static,--no-dynamic-linker,-ztext \
|
-Wl,-static,--no-dynamic-linker,-ztext \
|
||||||
-nostdlib -nodefaultlibs -nolibc \
|
|
||||||
-zmax-page-size=0x1000 \
|
-zmax-page-size=0x1000 \
|
||||||
-Wl,-Map kernel.map -static
|
-Wl,-Map kernel.map
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -158,11 +152,7 @@ $(KERNEL_FILENAME): $(OBJ)
|
|||||||
# https://gcc.gnu.org/projects/cxx-status.html
|
# https://gcc.gnu.org/projects/cxx-status.html
|
||||||
%.o: %.cpp $(HEADERS)
|
%.o: %.cpp $(HEADERS)
|
||||||
$(info Compiling $<)
|
$(info Compiling $<)
|
||||||
$(CPP) $(CFLAGS) $(CFLAG_STACK_PROTECTOR) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@ -fno-rtti
|
$(CPP) $(CFLAGS) $(CFLAG_STACK_PROTECTOR) $(WARNCFLAG) -std=c++20 -c $< -o $@ -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
%.o: %.rs $(HEADERS) $(RUST_TARGET_PATH)
|
|
||||||
$(info Compiling $<)
|
|
||||||
$(RUSTC) $< -C panic=abort -C soft-float --emit=obj -o $@
|
|
||||||
|
|
||||||
%.o: %.asm
|
%.o: %.asm
|
||||||
ifeq ($(OSARCH), aarch64)
|
ifeq ($(OSARCH), aarch64)
|
||||||
|
@ -168,26 +168,6 @@ namespace NetworkInterfaceManager
|
|||||||
fixme("Stop network stack");
|
fixme("Stop network stack");
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadFSFunction(NetRead)
|
|
||||||
{
|
|
||||||
UNUSED(node);
|
|
||||||
UNUSED(Offset);
|
|
||||||
UNUSED(Size);
|
|
||||||
UNUSED(Buffer);
|
|
||||||
fixme("Not implemented.");
|
|
||||||
return Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteFSFunction(NetWrite)
|
|
||||||
{
|
|
||||||
UNUSED(node);
|
|
||||||
UNUSED(Offset);
|
|
||||||
UNUSED(Size);
|
|
||||||
UNUSED(Buffer);
|
|
||||||
fixme("Not implemented.");
|
|
||||||
return Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CallStartNetworkStackWrapper() { NIManager->StartNetworkStack(); }
|
void CallStartNetworkStackWrapper() { NIManager->StartNetworkStack(); }
|
||||||
|
|
||||||
void NetworkInterface::StartService()
|
void NetworkInterface::StartService()
|
||||||
|
@ -79,18 +79,18 @@ namespace Recovery
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *PCMRaw = KernelAllocator.RequestPages(TO_PAGES(pcm.node->Length + 1));
|
void *PCMRaw = KernelAllocator.RequestPages(TO_PAGES(pcm.GetLength() + 1));
|
||||||
memcpy(PCMRaw, (void *)pcm.node->Address, pcm.node->Length);
|
vfs->Read(pcm, (uint8_t *)PCMRaw, pcm.GetLength());
|
||||||
|
|
||||||
KernelCallback callback{};
|
KernelCallback callback{};
|
||||||
callback.Reason = SendReason;
|
callback.Reason = SendReason;
|
||||||
callback.AudioCallback.Send.Data = (uint8_t *)PCMRaw;
|
callback.AudioCallback.Send.Data = (uint8_t *)PCMRaw;
|
||||||
callback.AudioCallback.Send.Length = pcm.node->Length;
|
callback.AudioCallback.Send.Length = pcm.GetLength();
|
||||||
debug("Playing audio...");
|
debug("Playing audio...");
|
||||||
int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback);
|
int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback);
|
||||||
UNUSED(status);
|
UNUSED(status);
|
||||||
debug("Audio played! %d", status);
|
debug("Audio played! %d", status);
|
||||||
KernelAllocator.FreePages((void *)PCMRaw, TO_PAGES(pcm.node->Length + 1));
|
KernelAllocator.FreePages((void *)PCMRaw, TO_PAGES(pcm.GetLength() + 1));
|
||||||
vfs->Close(pcm);
|
vfs->Close(pcm);
|
||||||
TEXIT(0);
|
TEXIT(0);
|
||||||
}
|
}
|
||||||
@ -364,8 +364,8 @@ namespace Recovery
|
|||||||
KernelRecovery::~KernelRecovery()
|
KernelRecovery::~KernelRecovery()
|
||||||
{
|
{
|
||||||
debug("Destructor called");
|
debug("Destructor called");
|
||||||
TaskManager->KillThread(guiThread, 0);
|
TaskManager->KillThread(guiThread, Tasking::KILL_SUCCESS);
|
||||||
TaskManager->KillThread(recoveryThread, 0);
|
TaskManager->KillThread(recoveryThread, Tasking::KILL_SUCCESS);
|
||||||
delete gui, gui = nullptr;
|
delete gui, gui = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
#include "../syscalls.h"
|
#include "../syscalls.h"
|
||||||
#include "../kernel.h"
|
#include "../kernel.h"
|
||||||
|
|
||||||
#include "../../Userspace/libs/include/libsys/base.h" /* KCtl */
|
|
||||||
#include "../ipc.h"
|
#include "../ipc.h"
|
||||||
|
|
||||||
using InterProcessCommunication::IPC;
|
using InterProcessCommunication::IPC;
|
||||||
@ -41,32 +40,32 @@ using Tasking::TTL::Untrusted;
|
|||||||
static inline bool CheckTrust(int TrustLevel)
|
static inline bool CheckTrust(int TrustLevel)
|
||||||
{
|
{
|
||||||
Token token = TaskManager->GetCurrentThread()->Security.UniqueToken;
|
Token token = TaskManager->GetCurrentThread()->Security.UniqueToken;
|
||||||
if (TaskManager->GetSecurityManager()->IsTokenTrusted(token, TrustLevel))
|
if (likely(TaskManager->GetSecurityManager()->IsTokenTrusted(token, TrustLevel)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
warn("Thread %s(%lld) tried to access a system call \"%s\" with insufficient trust level",
|
warn("Thread %s(%lld) tried to access a system call \"%s\" with insufficient trust level",
|
||||||
TaskManager->GetCurrentThread()->Name, TaskManager->GetCurrentThread()->ID,
|
TaskManager->GetCurrentThread()->Name, TaskManager->GetCurrentThread()->ID,
|
||||||
KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_extract_return_addr(__builtin_return_address(0))));
|
KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_extract_return_addr(__builtin_return_address(0))));
|
||||||
debug("Token: token=%#lx, trust=%d", token, TaskManager->GetSecurityManager()->GetTokenTrustLevel(token));
|
debug("token=%#lx, trust=%d", token, TaskManager->GetSecurityManager()->GetTokenTrustLevel(token));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sys_exit(SyscallsFrame *Frame, int code)
|
static int sys_exit(SyscallsFrame *Frame, int code)
|
||||||
{
|
{
|
||||||
/* Allow everyone to exit */
|
|
||||||
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted | UnknownTrustLevel))
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted | UnknownTrustLevel))
|
||||||
return SYSCALL_ACCESS_DENIED;
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
trace("Userspace thread %s(%lld) exited with code %#llx", TaskManager->GetCurrentThread()->Name, TaskManager->GetCurrentThread()->ID, code);
|
trace("Userspace thread %s(%lld) exited with code %#llx", TaskManager->GetCurrentThread()->Name, TaskManager->GetCurrentThread()->ID, code);
|
||||||
TaskManager->GetCurrentThread()->ExitCode = code;
|
TaskManager->GetCurrentThread()->ExitCode = code;
|
||||||
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Terminated;
|
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Terminated;
|
||||||
|
TaskManager->Schedule();
|
||||||
|
|
||||||
UNUSED(Frame);
|
UNUSED(Frame);
|
||||||
return SYSCALL_OK;
|
return SYSCALL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sys_print(SyscallsFrame *Frame, char Char, int Index)
|
static int sys_print(SyscallsFrame *Frame, char Char, int Index)
|
||||||
{
|
{
|
||||||
/* Only trusted threads can write to the kernel console */
|
|
||||||
if (!CheckTrust(TrustedByKernel | Trusted))
|
if (!CheckTrust(TrustedByKernel | Trusted))
|
||||||
return SYSCALL_ACCESS_DENIED;
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
@ -84,18 +83,18 @@ static int sys_print(SyscallsFrame *Frame, char Char, int Index)
|
|||||||
|
|
||||||
static uintptr_t sys_request_pages(SyscallsFrame *Frame, size_t Count)
|
static uintptr_t sys_request_pages(SyscallsFrame *Frame, size_t Count)
|
||||||
{
|
{
|
||||||
/* Allow everyone to request pages */
|
|
||||||
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
||||||
return SYSCALL_ACCESS_DENIED;
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
UNUSED(Frame);
|
UNUSED(Frame);
|
||||||
return (uintptr_t)TaskManager->GetCurrentThread()->Memory->RequestPages(Count + 1, true);
|
return (uintptr_t)TaskManager->GetCurrentThread()->Memory->RequestPages(Count + 1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sys_free_pages(SyscallsFrame *Frame, uintptr_t Address, size_t Count)
|
static int sys_free_pages(SyscallsFrame *Frame, uintptr_t Address, size_t Count)
|
||||||
{
|
{
|
||||||
/* Allow everyone to free pages */
|
|
||||||
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
||||||
return SYSCALL_ACCESS_DENIED;
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
TaskManager->GetCurrentThread()->Memory->FreePages((void *)Address, Count + 1);
|
TaskManager->GetCurrentThread()->Memory->FreePages((void *)Address, Count + 1);
|
||||||
UNUSED(Frame);
|
UNUSED(Frame);
|
||||||
return SYSCALL_OK;
|
return SYSCALL_OK;
|
||||||
@ -103,14 +102,50 @@ static int sys_free_pages(SyscallsFrame *Frame, uintptr_t Address, size_t Count)
|
|||||||
|
|
||||||
static int sys_detach_address(SyscallsFrame *Frame, uintptr_t Address)
|
static int sys_detach_address(SyscallsFrame *Frame, uintptr_t Address)
|
||||||
{
|
{
|
||||||
/* Only trusted threads can detach allocated addresses */
|
|
||||||
if (!CheckTrust(TrustedByKernel | Trusted))
|
if (!CheckTrust(TrustedByKernel | Trusted))
|
||||||
return SYSCALL_ACCESS_DENIED;
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
TaskManager->GetCurrentThread()->Memory->DetachAddress((void *)Address);
|
TaskManager->GetCurrentThread()->Memory->DetachAddress((void *)Address);
|
||||||
UNUSED(Frame);
|
UNUSED(Frame);
|
||||||
return SYSCALL_OK;
|
return SYSCALL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sys_memory_map(SyscallsFrame *Frame, uintptr_t VirtualAddress, uintptr_t PhysicalAddress, size_t Size, enum MemoryMapFlags Flags)
|
||||||
|
{
|
||||||
|
if (!CheckTrust(TrustedByKernel))
|
||||||
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
|
if (Flags > 7) /* (MAP_PRESENT | MAP_WRITABLE | MAP_USER) */
|
||||||
|
return SYSCALL_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
Memory::PageTable *PageTable = TaskManager->GetCurrentProcess()->PageTable;
|
||||||
|
{
|
||||||
|
Memory::Virtual vmm = Memory::Virtual(PageTable);
|
||||||
|
vmm.Map((void *)VirtualAddress,
|
||||||
|
(void *)PhysicalAddress,
|
||||||
|
Size, Flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
UNUSED(Frame);
|
||||||
|
return SYSCALL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sys_memory_unmap(SyscallsFrame *Frame, uintptr_t VirtualAddress, size_t Size)
|
||||||
|
{
|
||||||
|
if (!CheckTrust(TrustedByKernel))
|
||||||
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
|
Memory::PageTable *PageTable = TaskManager->GetCurrentProcess()->PageTable;
|
||||||
|
{
|
||||||
|
Memory::Virtual vmm = Memory::Virtual(PageTable);
|
||||||
|
vmm.Unmap((void *)VirtualAddress,
|
||||||
|
Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
UNUSED(Frame);
|
||||||
|
return SYSCALL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4)
|
static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4)
|
||||||
{
|
{
|
||||||
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
||||||
@ -130,6 +165,7 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
|
|||||||
{
|
{
|
||||||
if (!CheckTrust(TrustedByKernel | Trusted))
|
if (!CheckTrust(TrustedByKernel | Trusted))
|
||||||
return SYSCALL_ACCESS_DENIED;
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
char *Identifier = (char *)Arg1;
|
char *Identifier = (char *)Arg1;
|
||||||
const char *Path = (const char *)Arg2;
|
const char *Path = (const char *)Arg2;
|
||||||
|
|
||||||
@ -158,7 +194,8 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
|
|||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
// TODO: Check process binary path
|
VirtualFileSystem::Node *cwd = TaskManager->GetCurrentProcess()->CurrentWorkingDirectory;
|
||||||
|
FullPath = vfs->GetPathFromNode(cwd).get();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -173,38 +210,27 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
|
|||||||
goto RetryReadPath;
|
goto RetryReadPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Execute::AddLibrary(Identifier, f))
|
||||||
|
{
|
||||||
vfs->Close(f);
|
vfs->Close(f);
|
||||||
if (Execute::AddLibrary(Identifier, (void *)f.node->Address, f.node->Length))
|
|
||||||
return SYSCALL_OK;
|
return SYSCALL_OK;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
vfs->Close(f);
|
||||||
return SYSCALL_INTERNAL_ERROR;
|
return SYSCALL_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
case KCTL_GET_ELF_LIB_FILE:
|
|
||||||
{
|
|
||||||
if (!CheckTrust(TrustedByKernel | Trusted))
|
|
||||||
return SYSCALL_ACCESS_DENIED;
|
|
||||||
char *Identifier = (char *)Arg1;
|
|
||||||
if (!Identifier)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
Execute::SharedLibraries lib = Execute::GetLibrary(Identifier);
|
|
||||||
if (!lib.Address)
|
|
||||||
{
|
|
||||||
debug("Failed to get library address %#lx", (uintptr_t)lib.Address);
|
|
||||||
}
|
|
||||||
|
|
||||||
debug("Returning library address %#lx (%s)", (uintptr_t)lib.Address, Identifier);
|
|
||||||
return (uintptr_t)lib.Address;
|
|
||||||
}
|
}
|
||||||
case KCTL_GET_ELF_LIB_MEMORY_IMAGE:
|
case KCTL_GET_ELF_LIB_MEMORY_IMAGE:
|
||||||
{
|
{
|
||||||
if (!CheckTrust(TrustedByKernel | Trusted))
|
if (!CheckTrust(TrustedByKernel | Trusted))
|
||||||
return SYSCALL_ACCESS_DENIED;
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
char *Identifier = (char *)Arg1;
|
char *Identifier = (char *)Arg1;
|
||||||
if (!Identifier)
|
if (!Identifier)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Execute::SharedLibraries lib = Execute::GetLibrary(Identifier);
|
Execute::SharedLibrary lib = Execute::GetLibrary(Identifier);
|
||||||
|
|
||||||
if (!lib.MemoryImage)
|
if (!lib.MemoryImage)
|
||||||
{
|
{
|
||||||
@ -214,15 +240,29 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
|
|||||||
debug("Returning memory image %#lx (%s)", (uintptr_t)lib.MemoryImage, Identifier);
|
debug("Returning memory image %#lx (%s)", (uintptr_t)lib.MemoryImage, Identifier);
|
||||||
return (uintptr_t)lib.MemoryImage;
|
return (uintptr_t)lib.MemoryImage;
|
||||||
}
|
}
|
||||||
case KCTL_GET_FRAMEBUFFER_BUFFER:
|
case KCTL_GET_ABSOLUTE_PATH:
|
||||||
return r_cst(uint64_t, Display->GetBuffer(0)->Buffer);
|
{
|
||||||
case KCTL_GET_FRAMEBUFFER_WIDTH:
|
if (!CheckTrust(TrustedByKernel | Trusted))
|
||||||
return Display->GetBuffer(0)->Width;
|
return SYSCALL_ACCESS_DENIED;
|
||||||
case KCTL_GET_FRAMEBUFFER_HEIGHT:
|
|
||||||
return Display->GetBuffer(0)->Height;
|
|
||||||
case KCTL_GET_FRAMEBUFFER_SIZE:
|
|
||||||
return Display->GetBuffer(0)->Size;
|
|
||||||
|
|
||||||
|
char *Identifier = (char *)Arg1;
|
||||||
|
void *Buffer = (void *)Arg2;
|
||||||
|
size_t BufferSize = Arg3;
|
||||||
|
|
||||||
|
if (!Identifier || !Buffer || !BufferSize)
|
||||||
|
return SYSCALL_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
Execute::SharedLibrary lib = Execute::GetLibrary(Identifier);
|
||||||
|
|
||||||
|
if (!lib.MemoryImage)
|
||||||
|
return SYSCALL_INTERNAL_ERROR;
|
||||||
|
|
||||||
|
if (BufferSize < sizeof(lib.Path))
|
||||||
|
return SYSCALL_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
memcpy(Buffer, lib.Path, sizeof(lib.Path));
|
||||||
|
return SYSCALL_OK;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
warn("KernelCTL: Unknown command: %lld", Command);
|
warn("KernelCTL: Unknown command: %lld", Command);
|
||||||
@ -237,17 +277,11 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
|
|||||||
UNUSED(Frame);
|
UNUSED(Frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sys_ipc(SyscallsFrame *Frame, enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size)
|
|
||||||
{
|
|
||||||
/* Allow everyone to use IPC */
|
|
||||||
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
|
||||||
return SYSCALL_ACCESS_DENIED;
|
|
||||||
UNUSED(Frame);
|
|
||||||
return TaskManager->GetCurrentProcess()->IPC->HandleSyscall(Command, Type, ID, Flags, Buffer, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t sys_file_open(SyscallsFrame *Frame, const char *Path, uint64_t Flags)
|
static uint64_t sys_file_open(SyscallsFrame *Frame, const char *Path, uint64_t Flags)
|
||||||
{
|
{
|
||||||
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
||||||
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
debug("(Path: %s, Flags: %#lx)", Path, Flags);
|
debug("(Path: %s, Flags: %#lx)", Path, Flags);
|
||||||
VirtualFileSystem::Node *cwd = nullptr;
|
VirtualFileSystem::Node *cwd = nullptr;
|
||||||
if (vfs->PathIsRelative(Path))
|
if (vfs->PathIsRelative(Path))
|
||||||
@ -273,6 +307,9 @@ static uint64_t sys_file_open(SyscallsFrame *Frame, const char *Path, uint64_t F
|
|||||||
|
|
||||||
static int sys_file_close(SyscallsFrame *Frame, void *KernelPrivate)
|
static int sys_file_close(SyscallsFrame *Frame, void *KernelPrivate)
|
||||||
{
|
{
|
||||||
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
||||||
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
debug("(KernelPrivate: %#lx)", KernelPrivate);
|
debug("(KernelPrivate: %#lx)", KernelPrivate);
|
||||||
|
|
||||||
if (KernelPrivate)
|
if (KernelPrivate)
|
||||||
@ -287,38 +324,44 @@ static int sys_file_close(SyscallsFrame *Frame, void *KernelPrivate)
|
|||||||
UNUSED(Frame);
|
UNUSED(Frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t sys_file_read(SyscallsFrame *Frame, void *KernelPrivate, uint64_t Offset, uint8_t *Buffer, uint64_t Size)
|
static uint64_t sys_file_read(SyscallsFrame *Frame, void *KernelPrivate, uint8_t *Buffer, uint64_t Size)
|
||||||
{
|
{
|
||||||
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
||||||
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
if (KernelPrivate == nullptr)
|
if (KernelPrivate == nullptr)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)", KernelPrivate, Offset, Buffer, Size);
|
debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)", KernelPrivate, Buffer, Size);
|
||||||
return vfs->Read(*(VirtualFileSystem::File *)KernelPrivate, (size_t)Offset, Buffer, (size_t)Size);
|
return vfs->Read(*(VirtualFileSystem::File *)KernelPrivate, Buffer, (size_t)Size);
|
||||||
UNUSED(Frame);
|
UNUSED(Frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t sys_file_write(SyscallsFrame *Frame, void *KernelPrivate, uint64_t Offset, uint8_t *Buffer, uint64_t Size)
|
static uint64_t sys_file_write(SyscallsFrame *Frame, void *KernelPrivate, uint8_t *Buffer, uint64_t Size)
|
||||||
{
|
{
|
||||||
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
||||||
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
if (KernelPrivate == nullptr)
|
if (KernelPrivate == nullptr)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)", KernelPrivate, Offset, Buffer, Size);
|
debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)", KernelPrivate, Buffer, Size);
|
||||||
return vfs->Write(*(VirtualFileSystem::File *)KernelPrivate, (size_t)Offset, Buffer, (size_t)Size);
|
return vfs->Write(*(VirtualFileSystem::File *)KernelPrivate, Buffer, (size_t)Size);
|
||||||
UNUSED(Frame);
|
UNUSED(Frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t sys_file_seek(SyscallsFrame *Frame, void *KernelPrivate, uint64_t Offset, int Whence)
|
static off_t sys_file_seek(SyscallsFrame *Frame, void *KernelPrivate, off_t Offset, int Whence)
|
||||||
{
|
{
|
||||||
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
||||||
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
if (KernelPrivate == nullptr)
|
if (KernelPrivate == nullptr)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
debug("(KernelPrivate: %#lx, Offset: %#lx, Whence: %d)", KernelPrivate, Offset, Whence);
|
debug("(KernelPrivate: %#lx, Offset: %#lx, Whence: %d)", KernelPrivate, Offset, Whence);
|
||||||
VirtualFileSystem::File *KPObj = (VirtualFileSystem::File *)KernelPrivate;
|
VirtualFileSystem::File *KPObj = (VirtualFileSystem::File *)KernelPrivate;
|
||||||
|
|
||||||
if (KPObj->node->Operator->Seek == nullptr)
|
off_t ret = vfs->Seek(*KPObj, (off_t)Offset, (uint8_t)Whence);
|
||||||
return SYSCALL_INTERNAL_ERROR;
|
|
||||||
|
|
||||||
uint64_t ret = KPObj->node->Operator->Seek(KPObj->node, (size_t)Offset, (uint8_t)Whence);
|
|
||||||
debug("Seek %s %ld", KPObj->Name, ret);
|
debug("Seek %s %ld", KPObj->Name, ret);
|
||||||
return ret;
|
return ret;
|
||||||
UNUSED(Frame);
|
UNUSED(Frame);
|
||||||
@ -326,12 +369,27 @@ static uint64_t sys_file_seek(SyscallsFrame *Frame, void *KernelPrivate, uint64_
|
|||||||
|
|
||||||
static int sys_file_status(SyscallsFrame *Frame)
|
static int sys_file_status(SyscallsFrame *Frame)
|
||||||
{
|
{
|
||||||
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
||||||
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
fixme("sys_file_status: %#lx", Frame);
|
fixme("sys_file_status: %#lx", Frame);
|
||||||
return SYSCALL_NOT_IMPLEMENTED;
|
return SYSCALL_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sys_ipc(SyscallsFrame *Frame, enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size)
|
||||||
|
{
|
||||||
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
||||||
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
|
UNUSED(Frame);
|
||||||
|
return TaskManager->GetCurrentProcess()->IPC->HandleSyscall(Command, Type, ID, Flags, Buffer, Size);
|
||||||
|
}
|
||||||
|
|
||||||
static int sys_sleep(SyscallsFrame *Frame, uint64_t Milliseconds)
|
static int sys_sleep(SyscallsFrame *Frame, uint64_t Milliseconds)
|
||||||
{
|
{
|
||||||
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
||||||
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
UNUSED(Frame);
|
UNUSED(Frame);
|
||||||
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
||||||
return SYSCALL_ACCESS_DENIED;
|
return SYSCALL_ACCESS_DENIED;
|
||||||
@ -341,7 +399,6 @@ static int sys_sleep(SyscallsFrame *Frame, uint64_t Milliseconds)
|
|||||||
|
|
||||||
static int sys_fork(SyscallsFrame *Frame)
|
static int sys_fork(SyscallsFrame *Frame)
|
||||||
{
|
{
|
||||||
UNUSED(Frame);
|
|
||||||
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
||||||
return SYSCALL_ACCESS_DENIED;
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
@ -360,14 +417,13 @@ static int sys_fork(SyscallsFrame *Frame)
|
|||||||
}
|
}
|
||||||
|
|
||||||
strncpy(NewProcess->Name, Parent->Name, sizeof(NewProcess->Name));
|
strncpy(NewProcess->Name, Parent->Name, sizeof(NewProcess->Name));
|
||||||
NewProcess->IPC->Fork(Parent->IPC); // FIXME: Do we need to do this?
|
NewProcess->IPC->Fork(Parent->IPC);
|
||||||
|
|
||||||
Tasking::TCB *NewThread = TaskManager->CreateThread(NewProcess,
|
Tasking::TCB *NewThread = TaskManager->CreateThread(NewProcess,
|
||||||
0,
|
0,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
std::vector<AuxiliaryVector>(),
|
std::vector<AuxiliaryVector>(),
|
||||||
0,
|
|
||||||
Thread->Info.Architecture,
|
Thread->Info.Architecture,
|
||||||
Thread->Info.Compatibility,
|
Thread->Info.Compatibility,
|
||||||
true);
|
true);
|
||||||
@ -428,6 +484,7 @@ static int sys_fork(SyscallsFrame *Frame)
|
|||||||
debug("Forked thread \"%s\"(%d) to \"%s\"(%d)", Thread->Name, Thread->ID, NewThread->Name, NewThread->ID);
|
debug("Forked thread \"%s\"(%d) to \"%s\"(%d)", Thread->Name, Thread->ID, NewThread->Name, NewThread->ID);
|
||||||
NewThread->Status = Tasking::TaskStatus::Ready;
|
NewThread->Status = Tasking::TaskStatus::Ready;
|
||||||
return (int)NewThread->ID;
|
return (int)NewThread->ID;
|
||||||
|
UNUSED(Frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sys_wait(SyscallsFrame *Frame)
|
static int sys_wait(SyscallsFrame *Frame)
|
||||||
@ -476,11 +533,17 @@ static int sys_get_current_thread(SyscallsFrame *Frame)
|
|||||||
|
|
||||||
static int sys_get_current_process_id(SyscallsFrame *Frame)
|
static int sys_get_current_process_id(SyscallsFrame *Frame)
|
||||||
{
|
{
|
||||||
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
||||||
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
return (int)TaskManager->GetCurrentProcess()->ID;
|
return (int)TaskManager->GetCurrentProcess()->ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sys_get_current_thread_id(SyscallsFrame *Frame)
|
static int sys_get_current_thread_id(SyscallsFrame *Frame)
|
||||||
{
|
{
|
||||||
|
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
|
||||||
|
return SYSCALL_ACCESS_DENIED;
|
||||||
|
|
||||||
return (int)TaskManager->GetCurrentThread()->ID;
|
return (int)TaskManager->GetCurrentThread()->ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,16 +583,17 @@ static int sys_sys_reserved_create_thread(SyscallsFrame *Frame)
|
|||||||
return SYSCALL_NOT_IMPLEMENTED;
|
return SYSCALL_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *NativeSyscallsTable[] = {
|
static void *NativeSyscallsTable[_MaxSyscall] = {
|
||||||
[_Exit] = (void *)sys_exit,
|
[_Exit] = (void *)sys_exit,
|
||||||
[_Print] = (void *)sys_print,
|
[_Print] = (void *)sys_print,
|
||||||
|
|
||||||
[_RequestPages] = (void *)sys_request_pages,
|
[_RequestPages] = (void *)sys_request_pages,
|
||||||
[_FreePages] = (void *)sys_free_pages,
|
[_FreePages] = (void *)sys_free_pages,
|
||||||
[_DetachAddress] = (void *)sys_detach_address,
|
[_DetachAddress] = (void *)sys_detach_address,
|
||||||
|
[_MemoryMap] = (void *)sys_memory_map,
|
||||||
|
[_MemoryUnmap] = (void *)sys_memory_unmap,
|
||||||
|
|
||||||
[_KernelCTL] = (void *)sys_kernelctl,
|
[_KernelCTL] = (void *)sys_kernelctl,
|
||||||
[_IPC] = (void *)sys_ipc,
|
|
||||||
|
|
||||||
[_FileOpen] = (void *)sys_file_open,
|
[_FileOpen] = (void *)sys_file_open,
|
||||||
[_FileClose] = (void *)sys_file_close,
|
[_FileClose] = (void *)sys_file_close,
|
||||||
@ -538,6 +602,7 @@ static void *NativeSyscallsTable[] = {
|
|||||||
[_FileSeek] = (void *)sys_file_seek,
|
[_FileSeek] = (void *)sys_file_seek,
|
||||||
[_FileStatus] = (void *)sys_file_status,
|
[_FileStatus] = (void *)sys_file_status,
|
||||||
|
|
||||||
|
[_IPC] = (void *)sys_ipc,
|
||||||
[_Sleep] = (void *)sys_sleep,
|
[_Sleep] = (void *)sys_sleep,
|
||||||
[_Fork] = (void *)sys_fork,
|
[_Fork] = (void *)sys_fork,
|
||||||
[_Wait] = (void *)sys_wait,
|
[_Wait] = (void *)sys_wait,
|
||||||
@ -573,9 +638,9 @@ uintptr_t HandleNativeSyscalls(SyscallsFrame *Frame)
|
|||||||
return SYSCALL_INTERNAL_ERROR;
|
return SYSCALL_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// debug("[%#lx]->( %#lx %#lx %#lx %#lx %#lx %#lx )",
|
debug("[%#lx]->( %#lx %#lx %#lx %#lx %#lx %#lx )",
|
||||||
// Frame->rax,
|
Frame->rax,
|
||||||
// Frame->rdi, Frame->rsi, Frame->rdx, Frame->rcx, Frame->r8, Frame->r9);
|
Frame->rdi, Frame->rsi, Frame->rdx, Frame->rcx, Frame->r8, Frame->r9);
|
||||||
|
|
||||||
uintptr_t ret = call((uintptr_t)Frame, Frame->rdi, Frame->rsi, Frame->rdx, Frame->r10, Frame->r8, Frame->r9);
|
uintptr_t ret = call((uintptr_t)Frame, Frame->rdi, Frame->rsi, Frame->rdx, Frame->r10, Frame->r8, Frame->r9);
|
||||||
Frame->rax = ret;
|
Frame->rax = ret;
|
||||||
|
@ -55,7 +55,7 @@ extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame)
|
|||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
error("Unknown compatibility mode! Killing thread...");
|
error("Unknown compatibility mode! Killing thread...");
|
||||||
TaskManager->KillThread(TaskManager->GetCurrentThread(), -0xCA11);
|
TaskManager->KillThread(TaskManager->GetCurrentThread(), Tasking::KILL_SYSCALL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ namespace Tasking
|
|||||||
gnat_schedbg("\"%s\"(%d) and next thread is \"%s\"(%d)",
|
gnat_schedbg("\"%s\"(%d) and next thread is \"%s\"(%d)",
|
||||||
CurrentCPU->CurrentProcess->Threads[i]->Name,
|
CurrentCPU->CurrentProcess->Threads[i]->Name,
|
||||||
CurrentCPU->CurrentProcess->Threads[i]->ID,
|
CurrentCPU->CurrentProcess->Threads[i]->ID,
|
||||||
thread->Name, thread->ID);
|
nextThread->Name, nextThread->ID);
|
||||||
|
|
||||||
if (nextThread->Status != TaskStatus::Ready)
|
if (nextThread->Status != TaskStatus::Ready)
|
||||||
{
|
{
|
||||||
@ -212,7 +212,7 @@ namespace Tasking
|
|||||||
|
|
||||||
CurrentCPU->CurrentThread = nextThread;
|
CurrentCPU->CurrentThread = nextThread;
|
||||||
gnat_schedbg("[thd 0 -> end] Scheduling thread %d parent of %s->%d Procs %d",
|
gnat_schedbg("[thd 0 -> end] Scheduling thread %d parent of %s->%d Procs %d",
|
||||||
thread->ID, thread->Parent->Name,
|
nextThread->ID, nextThread->Parent->Name,
|
||||||
CurrentCPU->CurrentProcess->Threads.size(), ProcessList.size());
|
CurrentCPU->CurrentProcess->Threads.size(), ProcessList.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -431,13 +431,13 @@ namespace Tasking
|
|||||||
|
|
||||||
SafeFunction NIF void OnScreenTaskManagerUpdate()
|
SafeFunction NIF void OnScreenTaskManagerUpdate()
|
||||||
{
|
{
|
||||||
TimeManager->Sleep(100);
|
TimeManager->Sleep(10, Time::Units::Milliseconds);
|
||||||
Video::ScreenBuffer *sb = Display->GetBuffer(0);
|
Video::ScreenBuffer *sb = Display->GetBuffer(0);
|
||||||
for (short i = 0; i < 340; i++)
|
for (short i = 0; i < 340; i++)
|
||||||
{
|
{
|
||||||
for (short j = 0; j < 200; j++)
|
for (short j = 0; j < 600; j++)
|
||||||
{
|
{
|
||||||
uint32_t *Pixel = (uint32_t *)((uintptr_t)sb->Buffer + (j * sb->Width + i) * (bInfo->Framebuffer[0].BitsPerPixel / 8));
|
uint32_t *Pixel = (uint32_t *)((uintptr_t)sb->Buffer + (j * sb->Width + i) * (bInfo.Framebuffer[0].BitsPerPixel / 8));
|
||||||
*Pixel = 0x222222;
|
*Pixel = 0x222222;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -465,7 +465,7 @@ namespace Tasking
|
|||||||
sanity = 0;
|
sanity = 0;
|
||||||
Display->SetBufferCursor(0, tmpX, tmpY);
|
Display->SetBufferCursor(0, tmpX, tmpY);
|
||||||
Display->SetBuffer(0);
|
Display->SetBuffer(0);
|
||||||
TimeManager->Sleep(100);
|
TimeManager->Sleep(10, Time::Units::Milliseconds);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -483,7 +483,6 @@ namespace Tasking
|
|||||||
CPUData *CurrentCPU = GetCurrentCPU();
|
CPUData *CurrentCPU = GetCurrentCPU();
|
||||||
this->LastCore.store(CurrentCPU->ID);
|
this->LastCore.store(CurrentCPU->ID);
|
||||||
schedbg("Scheduler called on CPU %d.", CurrentCPU->ID);
|
schedbg("Scheduler called on CPU %d.", CurrentCPU->ID);
|
||||||
schedbg("%d: %ld%%", CurrentCPU->ID, GetUsage(CurrentCPU->ID));
|
|
||||||
|
|
||||||
#ifdef DEBUG_SCHEDULER
|
#ifdef DEBUG_SCHEDULER
|
||||||
{
|
{
|
||||||
@ -595,7 +594,7 @@ namespace Tasking
|
|||||||
|
|
||||||
*Frame = CurrentCPU->CurrentThread->Registers;
|
*Frame = CurrentCPU->CurrentThread->Registers;
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(CurrentCPU->CurrentThread->IPHistory) / sizeof(CurrentCPU->CurrentThread->IPHistory[0]); i++)
|
for (size_t i = 0; i < (sizeof(CurrentCPU->CurrentThread->IPHistory) / sizeof(CurrentCPU->CurrentThread->IPHistory[0])) - 1; i++)
|
||||||
CurrentCPU->CurrentThread->IPHistory[i + 1] = CurrentCPU->CurrentThread->IPHistory[i];
|
CurrentCPU->CurrentThread->IPHistory[i + 1] = CurrentCPU->CurrentThread->IPHistory[i];
|
||||||
|
|
||||||
CurrentCPU->CurrentThread->IPHistory[0] = Frame->rip;
|
CurrentCPU->CurrentThread->IPHistory[0] = Frame->rip;
|
||||||
|
@ -187,7 +187,7 @@ namespace Tasking
|
|||||||
PCB *Task::GetCurrentProcess() { return GetCurrentCPU()->CurrentProcess.load(); }
|
PCB *Task::GetCurrentProcess() { return GetCurrentCPU()->CurrentProcess.load(); }
|
||||||
TCB *Task::GetCurrentThread() { return GetCurrentCPU()->CurrentThread.load(); }
|
TCB *Task::GetCurrentThread() { return GetCurrentCPU()->CurrentThread.load(); }
|
||||||
|
|
||||||
PCB *Task::GetProcessByID(UPID ID)
|
PCB *Task::GetProcessByID(TID ID)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < ProcessList.size(); i++)
|
for (size_t i = 0; i < ProcessList.size(); i++)
|
||||||
if (ProcessList[i]->ID == ID)
|
if (ProcessList[i]->ID == ID)
|
||||||
@ -195,7 +195,7 @@ namespace Tasking
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
TCB *Task::GetThreadByID(UTID ID)
|
TCB *Task::GetThreadByID(TID ID)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < ProcessList.size(); i++)
|
for (size_t i = 0; i < ProcessList.size(); i++)
|
||||||
for (size_t j = 0; j < ProcessList[i]->Threads.size(); j++)
|
for (size_t j = 0; j < ProcessList[i]->Threads.size(); j++)
|
||||||
@ -257,14 +257,8 @@ namespace Tasking
|
|||||||
thread->Parent->Status = TaskStatus::Sleeping;
|
thread->Parent->Status = TaskStatus::Sleeping;
|
||||||
thread->Info.SleepUntil = TimeManager->CalculateTarget(Milliseconds, Time::Units::Milliseconds);
|
thread->Info.SleepUntil = TimeManager->CalculateTarget(Milliseconds, Time::Units::Milliseconds);
|
||||||
tskdbg("Thread \"%s\"(%d) is going to sleep until %llu", thread->Name, thread->ID, thread->Info.SleepUntil);
|
tskdbg("Thread \"%s\"(%d) is going to sleep until %llu", thread->Name, thread->ID, thread->Info.SleepUntil);
|
||||||
// TaskingScheduler_OneShot(1);
|
|
||||||
// IRQ16
|
|
||||||
TaskingLock.Unlock();
|
TaskingLock.Unlock();
|
||||||
#if defined(a86)
|
this->Schedule();
|
||||||
asmv("int $0x30"); /* This will trigger the IRQ16 instantly so we won't execute the next instruction */
|
|
||||||
#elif defined(aa64)
|
|
||||||
asmv("svc #0x30"); /* This will trigger the IRQ16 instantly so we won't execute the next instruction */
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::SignalShutdown()
|
void Task::SignalShutdown()
|
||||||
@ -313,7 +307,7 @@ namespace Tasking
|
|||||||
delete Process->ELFSymbolTable, Process->ELFSymbolTable = nullptr;
|
delete Process->ELFSymbolTable, Process->ELFSymbolTable = nullptr;
|
||||||
delete Process, Process = nullptr;
|
delete Process, Process = nullptr;
|
||||||
ProcessList.remove(i);
|
ProcessList.remove(i);
|
||||||
NextPID--;
|
this->NextPID--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -334,7 +328,7 @@ namespace Tasking
|
|||||||
delete Thread->Memory, Thread->Memory = nullptr;
|
delete Thread->Memory, Thread->Memory = nullptr;
|
||||||
SecurityManager.DestroyToken(Thread->Security.UniqueToken);
|
SecurityManager.DestroyToken(Thread->Security.UniqueToken);
|
||||||
delete Thread, Thread = nullptr;
|
delete Thread, Thread = nullptr;
|
||||||
NextTID--;
|
this->NextTID--;
|
||||||
}
|
}
|
||||||
|
|
||||||
__no_sanitize("undefined") TCB *Task::CreateThread(PCB *Parent,
|
__no_sanitize("undefined") TCB *Task::CreateThread(PCB *Parent,
|
||||||
@ -342,7 +336,6 @@ namespace Tasking
|
|||||||
const char **argv,
|
const char **argv,
|
||||||
const char **envp,
|
const char **envp,
|
||||||
const std::vector<AuxiliaryVector> &auxv,
|
const std::vector<AuxiliaryVector> &auxv,
|
||||||
IPOffset Offset,
|
|
||||||
TaskArchitecture Architecture,
|
TaskArchitecture Architecture,
|
||||||
TaskCompatibility Compatibility,
|
TaskCompatibility Compatibility,
|
||||||
bool ThreadNotReady)
|
bool ThreadNotReady)
|
||||||
@ -372,7 +365,6 @@ namespace Tasking
|
|||||||
Thread->ID = this->NextTID++;
|
Thread->ID = this->NextTID++;
|
||||||
strcpy(Thread->Name, Parent->Name);
|
strcpy(Thread->Name, Parent->Name);
|
||||||
Thread->EntryPoint = EntryPoint;
|
Thread->EntryPoint = EntryPoint;
|
||||||
Thread->Offset = Offset;
|
|
||||||
Thread->ExitCode = 0xdead;
|
Thread->ExitCode = 0xdead;
|
||||||
if (ThreadNotReady)
|
if (ThreadNotReady)
|
||||||
Thread->Status = TaskStatus::Waiting;
|
Thread->Status = TaskStatus::Waiting;
|
||||||
@ -405,7 +397,7 @@ namespace Tasking
|
|||||||
|
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
memset(&Thread->Registers, 0, sizeof(CPU::x64::TrapFrame)); // Just in case
|
memset(&Thread->Registers, 0, sizeof(CPU::x64::TrapFrame)); // Just in case
|
||||||
Thread->Registers.rip = (EntryPoint + Offset);
|
Thread->Registers.rip = EntryPoint;
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
#endif
|
#endif
|
||||||
@ -440,7 +432,7 @@ namespace Tasking
|
|||||||
Thread->Stack = new Memory::StackGuard(true, Parent->PageTable);
|
Thread->Stack = new Memory::StackGuard(true, Parent->PageTable);
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
SecurityManager.TrustToken(Thread->Security.UniqueToken, TTL::Untrusted);
|
SecurityManager.TrustToken(Thread->Security.UniqueToken, TTL::Untrusted);
|
||||||
Thread->ShadowGSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_SHADOW_GS_BASE);
|
Thread->ShadowGSBase = (uint64_t)GetCurrentCPU();
|
||||||
Thread->GSBase = 0;
|
Thread->GSBase = 0;
|
||||||
Thread->FSBase = 0;
|
Thread->FSBase = 0;
|
||||||
Thread->Registers.cs = GDT_USER_CODE;
|
Thread->Registers.cs = GDT_USER_CODE;
|
||||||
@ -625,13 +617,13 @@ namespace Tasking
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#ifdef a64
|
#ifdef a64
|
||||||
debug("Thread offset is %#lx (EntryPoint: %#lx) => RIP: %#lx", Thread->Offset, Thread->EntryPoint, Thread->Registers.rip);
|
debug("Thread EntryPoint: %#lx => RIP: %#lx", Thread->EntryPoint, Thread->Registers.rip);
|
||||||
if (Parent->Security.TrustLevel == TaskTrustLevel::User)
|
if (Parent->Security.TrustLevel == TaskTrustLevel::User)
|
||||||
debug("Thread stack region is %#lx-%#lx (U) and rsp is %#lx", Thread->Stack->GetStackBottom(), Thread->Stack->GetStackTop(), Thread->Registers.rsp);
|
debug("Thread stack region is %#lx-%#lx (U) and rsp is %#lx", Thread->Stack->GetStackBottom(), Thread->Stack->GetStackTop(), Thread->Registers.rsp);
|
||||||
else
|
else
|
||||||
debug("Thread stack region is %#lx-%#lx (K) and rsp is %#lx", Thread->Stack->GetStackBottom(), Thread->Stack->GetStackTop(), Thread->Registers.rsp);
|
debug("Thread stack region is %#lx-%#lx (K) and rsp is %#lx", Thread->Stack->GetStackBottom(), Thread->Stack->GetStackTop(), Thread->Registers.rsp);
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
debug("Thread offset is %#lx (EntryPoint: %#lx) => RIP: %#lx", Thread->Offset, Thread->EntryPoint, Thread->Registers.eip);
|
debug("Thread EntryPoint: %#lx => RIP: %#lx", Thread->EntryPoint, Thread->Registers.eip);
|
||||||
if (Parent->Security.TrustLevel == TaskTrustLevel::User)
|
if (Parent->Security.TrustLevel == TaskTrustLevel::User)
|
||||||
debug("Thread stack region is %#lx-%#lx (U) and rsp is %#lx", Thread->Stack->GetStackBottom(), Thread->Stack->GetStackTop(), Thread->Registers.esp);
|
debug("Thread stack region is %#lx-%#lx (U) and rsp is %#lx", Thread->Stack->GetStackBottom(), Thread->Stack->GetStackTop(), Thread->Registers.esp);
|
||||||
else
|
else
|
||||||
@ -654,7 +646,7 @@ namespace Tasking
|
|||||||
{
|
{
|
||||||
SmartLock(TaskingLock);
|
SmartLock(TaskingLock);
|
||||||
PCB *Process = new PCB;
|
PCB *Process = new PCB;
|
||||||
Process->ID = this->NextPID++;
|
Process->ID = NextPID++;
|
||||||
strcpy(Process->Name, Name);
|
strcpy(Process->Name, Name);
|
||||||
if (Parent == nullptr)
|
if (Parent == nullptr)
|
||||||
Process->Parent = this->GetCurrentProcess();
|
Process->Parent = this->GetCurrentProcess();
|
||||||
@ -667,7 +659,7 @@ namespace Tasking
|
|||||||
Process->Security.UniqueToken = SecurityManager.CreateToken();
|
Process->Security.UniqueToken = SecurityManager.CreateToken();
|
||||||
|
|
||||||
char ProcFSName[16];
|
char ProcFSName[16];
|
||||||
sprintf(ProcFSName, "%ld", Process->ID);
|
sprintf(ProcFSName, "%d", Process->ID);
|
||||||
Process->ProcessDirectory = vfs->Create(ProcFSName, VirtualFileSystem::NodeFlags::DIRECTORY, ProcFS);
|
Process->ProcessDirectory = vfs->Create(ProcFSName, VirtualFileSystem::NodeFlags::DIRECTORY, ProcFS);
|
||||||
Process->memDirectory = vfs->Create("mem", VirtualFileSystem::NodeFlags::DIRECTORY, Process->ProcessDirectory);
|
Process->memDirectory = vfs->Create("mem", VirtualFileSystem::NodeFlags::DIRECTORY, Process->ProcessDirectory);
|
||||||
Process->IPC = new InterProcessCommunication::IPC((void *)Process);
|
Process->IPC = new InterProcessCommunication::IPC((void *)Process);
|
||||||
@ -706,7 +698,7 @@ namespace Tasking
|
|||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
error("Unknown elevation.");
|
error("Unknown elevation.");
|
||||||
this->NextPID--;
|
NextPID--;
|
||||||
delete Process;
|
delete Process;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -767,9 +759,10 @@ namespace Tasking
|
|||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
TaskArchitecture Arch = TaskArchitecture::ARM64;
|
TaskArchitecture Arch = TaskArchitecture::ARM64;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PCB *kproc = CreateProcess(nullptr, "Kernel", TaskTrustLevel::Kernel);
|
PCB *kproc = CreateProcess(nullptr, "Kernel", TaskTrustLevel::Kernel);
|
||||||
kproc->ELFSymbolTable = KernelSymbolTable;
|
kproc->ELFSymbolTable = KernelSymbolTable;
|
||||||
TCB *kthrd = CreateThread(kproc, EntryPoint, nullptr, nullptr, std::vector<AuxiliaryVector>(), 0, Arch);
|
TCB *kthrd = CreateThread(kproc, EntryPoint, nullptr, nullptr, std::vector<AuxiliaryVector>(), Arch);
|
||||||
kthrd->Rename("Main Thread");
|
kthrd->Rename("Main Thread");
|
||||||
debug("Created Kernel Process: %s and Thread: %s", kproc->Name, kthrd->Name);
|
debug("Created Kernel Process: %s and Thread: %s", kproc->Name, kthrd->Name);
|
||||||
TaskingLock.Lock(__FUNCTION__);
|
TaskingLock.Lock(__FUNCTION__);
|
||||||
@ -843,12 +836,12 @@ namespace Tasking
|
|||||||
if (Thread == GetCurrentCPU()->CurrentThread.load() ||
|
if (Thread == GetCurrentCPU()->CurrentThread.load() ||
|
||||||
Thread == CleanupThread)
|
Thread == CleanupThread)
|
||||||
continue;
|
continue;
|
||||||
this->KillThread(Thread, 0xFFFF);
|
this->KillThread(Thread, KILL_SCHEDULER_DESTRUCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Process == GetCurrentCPU()->CurrentProcess.load())
|
if (Process == GetCurrentCPU()->CurrentProcess.load())
|
||||||
continue;
|
continue;
|
||||||
this->KillProcess(Process, 0xFFFF);
|
this->KillProcess(Process, KILL_SCHEDULER_DESTRUCTION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,14 +112,14 @@ __constructor void TestMacros()
|
|||||||
result = ROUND_UP(x, y);
|
result = ROUND_UP(x, y);
|
||||||
if (result != 0x200)
|
if (result != 0x200)
|
||||||
{
|
{
|
||||||
error("ERROR: ROUND_UP failed: %d != 0x200\n", result);
|
error("ERROR: ROUND_UP failed: %d != 0x200", result);
|
||||||
inf_loop;
|
inf_loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ROUND_DOWN(x, y);
|
result = ROUND_DOWN(x, y);
|
||||||
if (result != 0x100)
|
if (result != 0x100)
|
||||||
{
|
{
|
||||||
error("ERROR: ROUND_DOWN failed: %d != 0x100\n", result);
|
error("ERROR: ROUND_DOWN failed: %d != 0x100", result);
|
||||||
inf_loop;
|
inf_loop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ void TestMemoryAllocation()
|
|||||||
uintptr_t prq2 = (uintptr_t)kmalloc(0x1000);
|
uintptr_t prq2 = (uintptr_t)kmalloc(0x1000);
|
||||||
kfree((void *)prq2);
|
kfree((void *)prq2);
|
||||||
|
|
||||||
debug(" Result:\t1-[%#lx]; 2-[%#lx]\n", (void *)prq1, (void *)prq2);
|
debug(" Result:\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2);
|
||||||
assert(prq1 == prq2);
|
assert(prq1 == prq2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
218
include/cpu.hpp
218
include/cpu.hpp
@ -289,45 +289,82 @@ namespace CPU
|
|||||||
uint32_t ss; // Stack Segment
|
uint32_t ss; // Stack Segment
|
||||||
} TrapFrame;
|
} TrapFrame;
|
||||||
|
|
||||||
// ! TODO: UNTESTED!
|
typedef union DR6
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/** @brief Breakpoint #0 Condition Detected */
|
||||||
|
uint64_t B0 : 1;
|
||||||
|
/** @brief Breakpoint #1 Condition Detected */
|
||||||
|
uint64_t B1 : 1;
|
||||||
|
/** @brief Breakpoint #2 Condition Detected */
|
||||||
|
uint64_t B2 : 1;
|
||||||
|
/** @brief Breakpoint #3 Condition Detected */
|
||||||
|
uint64_t B3 : 1;
|
||||||
|
/** @brief Reserved */
|
||||||
|
uint64_t Reserved0 : 8;
|
||||||
|
/** @brief Reserved */
|
||||||
|
uint64_t Reserved1 : 1;
|
||||||
|
/** @brief Breakpoint Debug Access Detected */
|
||||||
|
uint64_t BD : 1;
|
||||||
|
/** @brief Breakpoint Single Step */
|
||||||
|
uint64_t BS : 1;
|
||||||
|
/** @brief Breakpoint Task Switch */
|
||||||
|
uint64_t BT : 1;
|
||||||
|
/** @brief Reserved */
|
||||||
|
uint64_t Reserved2 : 15;
|
||||||
|
};
|
||||||
|
uint64_t raw;
|
||||||
|
} DR6;
|
||||||
|
|
||||||
typedef union DR7
|
typedef union DR7
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
/** @brief Local DR0 Breakpoint (0) */
|
/** @brief Local Exact Breakpoint #0 Enabled */
|
||||||
uint32_t LocalDR0 : 1;
|
uint32_t L0 : 1;
|
||||||
/** @brief Global DR0 Breakpoint (1) */
|
/** @brief Global Exact Breakpoint #0 Enabled */
|
||||||
uint32_t GlobalDR0 : 1;
|
uint32_t G0 : 1;
|
||||||
/** @brief Local DR1 Breakpoint (2) */
|
/** @brief Local Exact Breakpoint #1 Enabled */
|
||||||
uint32_t LocalDR1 : 1;
|
uint32_t L1 : 1;
|
||||||
/** @brief Global DR1 Breakpoint (3) */
|
/** @brief Global Exact Breakpoint #1 Enabled */
|
||||||
uint32_t GlobalDR1 : 1;
|
uint32_t G1 : 1;
|
||||||
/** @brief Local DR2 Breakpoint (4) */
|
/** @brief Local Exact Breakpoint #2 Enabled */
|
||||||
uint32_t LocalDR2 : 1;
|
uint32_t L2 : 1;
|
||||||
/** @brief Global DR2 Breakpoint (5) */
|
/** @brief Global Exact Breakpoint #2 Enabled */
|
||||||
uint32_t GlobalDR2 : 1;
|
uint32_t G2 : 1;
|
||||||
/** @brief Local DR3 Breakpoint (6) */
|
/** @brief Local Exact Breakpoint #3 Enabled */
|
||||||
uint32_t LocalDR3 : 1;
|
uint32_t L3 : 1;
|
||||||
/** @brief Global DR3 Breakpoint (7) */
|
/** @brief Global Exact Breakpoint #3 Enabled */
|
||||||
uint32_t GlobalDR3 : 1;
|
uint32_t G3 : 1;
|
||||||
/** @brief Reserved [7 - (16-17)] */
|
/** @brief Local Exact Breakpoint Enabled */
|
||||||
uint32_t Reserved : 9;
|
uint32_t LE : 1;
|
||||||
/** @brief Conditions for DR0 (16-17) */
|
/** @brief Global Exact Breakpoint Enabled */
|
||||||
uint32_t ConditionsDR0 : 1;
|
uint32_t GE : 1;
|
||||||
/** @brief Size of DR0 Breakpoint (18-19) */
|
/** @brief Reserved */
|
||||||
uint32_t SizeDR0 : 1;
|
uint32_t Reserved0 : 1;
|
||||||
/** @brief Conditions for DR1 (20-21) */
|
/** @brief Reserved */
|
||||||
uint32_t ConditionsDR1 : 1;
|
uint32_t Reserved1 : 2;
|
||||||
/** @brief Size of DR1 Breakpoint (22-23) */
|
/** @brief General Detect Enabled */
|
||||||
uint32_t SizeDR1 : 1;
|
uint32_t GD : 1;
|
||||||
/** @brief Conditions for DR2 (24-25) */
|
/** @brief Reserved */
|
||||||
uint32_t ConditionsDR2 : 1;
|
uint32_t Reserved2 : 2;
|
||||||
/** @brief Size of DR2 Breakpoint (26-27) */
|
/** @brief Type of Transaction(s) to Trap */
|
||||||
uint32_t SizeDR2 : 1;
|
uint32_t RW0 : 2;
|
||||||
/** @brief Conditions for DR3 (28-29) */
|
/** @brief Length of Breakpoint #0 */
|
||||||
uint32_t ConditionsDR3 : 1;
|
uint32_t LEN0 : 2;
|
||||||
/** @brief Size of DR3 Breakpoint (30-31) */
|
/** @brief Type of Transaction(s) to Trap */
|
||||||
uint32_t SizeDR3 : 1;
|
uint32_t RW1 : 2;
|
||||||
|
/** @brief Length of Breakpoint #1 */
|
||||||
|
uint32_t LEN1 : 2;
|
||||||
|
/** @brief Type of Transaction(s) to Trap */
|
||||||
|
uint32_t RW2 : 2;
|
||||||
|
/** @brief Length of Breakpoint #2 */
|
||||||
|
uint32_t LEN2 : 2;
|
||||||
|
/** @brief Type of Transaction(s) to Trap */
|
||||||
|
uint32_t RW3 : 2;
|
||||||
|
/** @brief Length of Breakpoint #3 */
|
||||||
|
uint32_t LEN3 : 2;
|
||||||
};
|
};
|
||||||
uint32_t raw;
|
uint32_t raw;
|
||||||
} DR7;
|
} DR7;
|
||||||
@ -590,45 +627,86 @@ namespace CPU
|
|||||||
uint64_t raw;
|
uint64_t raw;
|
||||||
} __packed EFER;
|
} __packed EFER;
|
||||||
|
|
||||||
// ! TODO: UNTESTED!
|
typedef union DR6
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/** @brief Breakpoint #0 Condition Detected */
|
||||||
|
uint64_t B0 : 1;
|
||||||
|
/** @brief Breakpoint #1 Condition Detected */
|
||||||
|
uint64_t B1 : 1;
|
||||||
|
/** @brief Breakpoint #2 Condition Detected */
|
||||||
|
uint64_t B2 : 1;
|
||||||
|
/** @brief Breakpoint #3 Condition Detected */
|
||||||
|
uint64_t B3 : 1;
|
||||||
|
/** @brief Reserved */
|
||||||
|
uint64_t Reserved0 : 8;
|
||||||
|
/** @brief Reserved */
|
||||||
|
uint64_t Reserved1 : 1;
|
||||||
|
/** @brief Breakpoint Debug Access Detected */
|
||||||
|
uint64_t BD : 1;
|
||||||
|
/** @brief Breakpoint Single Step */
|
||||||
|
uint64_t BS : 1;
|
||||||
|
/** @brief Breakpoint Task Switch */
|
||||||
|
uint64_t BT : 1;
|
||||||
|
/** @brief Reserved */
|
||||||
|
uint64_t Reserved2 : 15;
|
||||||
|
/** @brief Reserved */
|
||||||
|
uint64_t Reserved3 : 32;
|
||||||
|
};
|
||||||
|
uint64_t raw;
|
||||||
|
} DR6;
|
||||||
|
|
||||||
typedef union DR7
|
typedef union DR7
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
/** @brief Local DR0 Breakpoint (0) */
|
/** @brief Local Exact Breakpoint #0 Enabled */
|
||||||
uint64_t LocalDR0 : 1;
|
uint64_t L0 : 1;
|
||||||
/** @brief Global DR0 Breakpoint (1) */
|
/** @brief Global Exact Breakpoint #0 Enabled */
|
||||||
uint64_t GlobalDR0 : 1;
|
uint64_t G0 : 1;
|
||||||
/** @brief Local DR1 Breakpoint (2) */
|
/** @brief Local Exact Breakpoint #1 Enabled */
|
||||||
uint64_t LocalDR1 : 1;
|
uint64_t L1 : 1;
|
||||||
/** @brief Global DR1 Breakpoint (3) */
|
/** @brief Global Exact Breakpoint #1 Enabled */
|
||||||
uint64_t GlobalDR1 : 1;
|
uint64_t G1 : 1;
|
||||||
/** @brief Local DR2 Breakpoint (4) */
|
/** @brief Local Exact Breakpoint #2 Enabled */
|
||||||
uint64_t LocalDR2 : 1;
|
uint64_t L2 : 1;
|
||||||
/** @brief Global DR2 Breakpoint (5) */
|
/** @brief Global Exact Breakpoint #2 Enabled */
|
||||||
uint64_t GlobalDR2 : 1;
|
uint64_t G2 : 1;
|
||||||
/** @brief Local DR3 Breakpoint (6) */
|
/** @brief Local Exact Breakpoint #3 Enabled */
|
||||||
uint64_t LocalDR3 : 1;
|
uint64_t L3 : 1;
|
||||||
/** @brief Global DR3 Breakpoint (7) */
|
/** @brief Global Exact Breakpoint #3 Enabled */
|
||||||
uint64_t GlobalDR3 : 1;
|
uint64_t G3 : 1;
|
||||||
/** @brief Reserved [7 - (16-17)] */
|
/** @brief Local Exact Breakpoint Enabled */
|
||||||
uint64_t Reserved : 9;
|
uint64_t LE : 1;
|
||||||
/** @brief Conditions for DR0 (16-17) */
|
/** @brief Global Exact Breakpoint Enabled */
|
||||||
uint64_t ConditionsDR0 : 1;
|
uint64_t GE : 1;
|
||||||
/** @brief Size of DR0 Breakpoint (18-19) */
|
/** @brief Reserved */
|
||||||
uint64_t SizeDR0 : 1;
|
uint64_t Reserved0 : 1;
|
||||||
/** @brief Conditions for DR1 (20-21) */
|
/** @brief Reserved */
|
||||||
uint64_t ConditionsDR1 : 1;
|
uint64_t Reserved1 : 2;
|
||||||
/** @brief Size of DR1 Breakpoint (22-23) */
|
/** @brief General Detect Enabled */
|
||||||
uint64_t SizeDR1 : 1;
|
uint64_t GD : 1;
|
||||||
/** @brief Conditions for DR2 (24-25) */
|
/** @brief Reserved */
|
||||||
uint64_t ConditionsDR2 : 1;
|
uint64_t Reserved2 : 2;
|
||||||
/** @brief Size of DR2 Breakpoint (26-27) */
|
/** @brief Type of Transaction(s) to Trap */
|
||||||
uint64_t SizeDR2 : 1;
|
uint64_t RW0 : 2;
|
||||||
/** @brief Conditions for DR3 (28-29) */
|
/** @brief Length of Breakpoint #0 */
|
||||||
uint64_t ConditionsDR3 : 1;
|
uint64_t LEN0 : 2;
|
||||||
/** @brief Size of DR3 Breakpoint (30-31) */
|
/** @brief Type of Transaction(s) to Trap */
|
||||||
uint64_t SizeDR3 : 1;
|
uint64_t RW1 : 2;
|
||||||
|
/** @brief Length of Breakpoint #1 */
|
||||||
|
uint64_t LEN1 : 2;
|
||||||
|
/** @brief Type of Transaction(s) to Trap */
|
||||||
|
uint64_t RW2 : 2;
|
||||||
|
/** @brief Length of Breakpoint #2 */
|
||||||
|
uint64_t LEN2 : 2;
|
||||||
|
/** @brief Type of Transaction(s) to Trap */
|
||||||
|
uint64_t RW3 : 2;
|
||||||
|
/** @brief Length of Breakpoint #3 */
|
||||||
|
uint64_t LEN3 : 2;
|
||||||
|
/** @brief Reserved */
|
||||||
|
uint64_t Reserved3 : 32;
|
||||||
};
|
};
|
||||||
uint64_t raw;
|
uint64_t raw;
|
||||||
} DR7;
|
} DR7;
|
||||||
|
@ -23,13 +23,15 @@
|
|||||||
enum DebugLevel
|
enum DebugLevel
|
||||||
{
|
{
|
||||||
DebugLevelNone = 0,
|
DebugLevelNone = 0,
|
||||||
DebugLevelError = 1,
|
DebugLevelError,
|
||||||
DebugLevelWarning = 2,
|
DebugLevelWarning,
|
||||||
DebugLevelInfo = 3,
|
DebugLevelInfo,
|
||||||
DebugLevelDebug = 4,
|
DebugLevelDebug,
|
||||||
DebugLevelTrace = 5,
|
DebugLevelTrace,
|
||||||
DebugLevelFixme = 6,
|
DebugLevelFixme,
|
||||||
DebugLevelUbsan = 7
|
DebugLevelUbsan,
|
||||||
|
DebugLevelStub,
|
||||||
|
DebugLevelFunction,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -48,12 +50,15 @@ namespace SysDbg
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define debug(Format, ...) SysDbg::WriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define debug(Format, ...) SysDbg::WriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
#define ubsan(Format, ...) SysDbg::WriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define ubsan(Format, ...) SysDbg::WriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
|
#define function(Format, ...) SysDbg::WriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define debug(Format, ...)
|
#define debug(Format, ...)
|
||||||
#define ubsan(Format, ...)
|
#define ubsan(Format, ...)
|
||||||
|
#define function(Format, ...)
|
||||||
#endif
|
#endif
|
||||||
#define trace(Format, ...) SysDbg::WriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define trace(Format, ...) SysDbg::WriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
#define fixme(Format, ...) SysDbg::WriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define fixme(Format, ...) SysDbg::WriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
|
#define stub SysDbg::WriteLine(DebugLevelStub, __FILE__, __LINE__, __FUNCTION__, "stub")
|
||||||
|
|
||||||
#define locked_error(Format, ...) SysDbg::LockedWriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define locked_error(Format, ...) SysDbg::LockedWriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
#define locked_warn(Format, ...) SysDbg::LockedWriteLine(DebugLevelWarning, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define locked_warn(Format, ...) SysDbg::LockedWriteLine(DebugLevelWarning, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
@ -61,12 +66,15 @@ namespace SysDbg
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define locked_debug(Format, ...) SysDbg::LockedWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define locked_debug(Format, ...) SysDbg::LockedWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
#define locked_ubsan(Format, ...) SysDbg::LockedWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define locked_ubsan(Format, ...) SysDbg::LockedWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
|
#define locked_function(Format, ...) SysDbg::LockedWriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define locked_debug(Format, ...)
|
#define locked_debug(Format, ...)
|
||||||
#define locked_ubsan(Format, ...)
|
#define locked_ubsan(Format, ...)
|
||||||
|
#define locked_function(Format, ...)
|
||||||
#endif
|
#endif
|
||||||
#define locked_trace(Format, ...) SysDbg::LockedWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define locked_trace(Format, ...) SysDbg::LockedWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
#define locked_fixme(Format, ...) SysDbg::LockedWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define locked_fixme(Format, ...) SysDbg::LockedWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
|
#define locked_stub SysDbg::LockedWriteLine(DebugLevelStub, __FILE__, __LINE__, __FUNCTION__, "stub")
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -81,12 +89,15 @@ void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, co
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define debug(Format, ...) SysDbgWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define debug(Format, ...) SysDbgWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
#define ubsan(Format, ...) SysDbgWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define ubsan(Format, ...) SysDbgWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
|
#define function(Format, ...) SysDbgWriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define debug(Format, ...)
|
#define debug(Format, ...)
|
||||||
#define ubsan(Format, ...)
|
#define ubsan(Format, ...)
|
||||||
|
#define function(Format, ...)
|
||||||
#endif
|
#endif
|
||||||
#define trace(Format, ...) SysDbgWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define trace(Format, ...) SysDbgWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
#define fixme(Format, ...) SysDbgWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define fixme(Format, ...) SysDbgWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
|
#define stub SysDbgWriteLine(DebugLevelStub, __FILE__, __LINE__, __FUNCTION__, "stub")
|
||||||
|
|
||||||
#define locked_error(Format, ...) SysDbgLockedWriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define locked_error(Format, ...) SysDbgLockedWriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
#define locked_warn(Format, ...) SysDbgLockedWriteLine(DebugLevelWarning, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define locked_warn(Format, ...) SysDbgLockedWriteLine(DebugLevelWarning, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
@ -94,15 +105,16 @@ void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, co
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define locked_debug(Format, ...) SysDbgLockedWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define locked_debug(Format, ...) SysDbgLockedWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
#define locked_ubsan(Format, ...) SysDbgLockedWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define locked_ubsan(Format, ...) SysDbgLockedWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
|
#define locked_function(Format, ...) SysDbgLockedWriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define locked_debug(Format, ...)
|
#define locked_debug(Format, ...)
|
||||||
#define locked_ubsan(Format, ...)
|
#define locked_ubsan(Format, ...)
|
||||||
|
#define locked_function(Format, ...)
|
||||||
#endif
|
#endif
|
||||||
#define locked_trace(Format, ...) SysDbgLockedWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define locked_trace(Format, ...) SysDbgLockedWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
#define locked_fixme(Format, ...) SysDbgLockedWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
#define locked_fixme(Format, ...) SysDbgLockedWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||||
|
#define locked_stub SysDbgLockedWriteLine(DebugLevelStub, __FILE__, __LINE__, __FUNCTION__, "stub")
|
||||||
|
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
#define stub fixme("stub")
|
|
||||||
|
|
||||||
#endif // !__FENNIX_KERNEL_DEBUGGER_H__
|
#endif // !__FENNIX_KERNEL_DEBUGGER_H__
|
||||||
|
746
include/elf.h
746
include/elf.h
@ -20,9 +20,6 @@
|
|||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
// https://wiki.osdev.org/ELF_Tutorial
|
|
||||||
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h
|
|
||||||
|
|
||||||
/* 32-bit ELF base types. */
|
/* 32-bit ELF base types. */
|
||||||
typedef uint32_t Elf32_Addr;
|
typedef uint32_t Elf32_Addr;
|
||||||
typedef uint16_t Elf32_Half;
|
typedef uint16_t Elf32_Half;
|
||||||
@ -40,174 +37,28 @@ typedef uint32_t Elf64_Word;
|
|||||||
typedef uint64_t Elf64_Xword;
|
typedef uint64_t Elf64_Xword;
|
||||||
typedef int64_t Elf64_Sxword;
|
typedef int64_t Elf64_Sxword;
|
||||||
|
|
||||||
#define EI_NIDENT 16
|
enum IdentificationIndex
|
||||||
|
|
||||||
typedef struct elf32_hdr
|
|
||||||
{
|
{
|
||||||
unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
|
EI_MAG0 = 0,
|
||||||
Elf32_Half e_type;
|
EI_MAG1 = 1,
|
||||||
Elf32_Half e_machine;
|
EI_MAG2 = 2,
|
||||||
Elf32_Word e_version;
|
EI_MAG3 = 3,
|
||||||
Elf32_Addr e_entry; /* Entry point virtual address */
|
EI_CLASS = 4,
|
||||||
Elf32_Off e_phoff; /* Program header table file offset */
|
EI_DATA = 5,
|
||||||
Elf32_Off e_shoff; /* Section header table file offset */
|
EI_VERSION = 6,
|
||||||
Elf32_Word e_flags;
|
EI_OSABI = 7,
|
||||||
Elf32_Half e_ehsize;
|
EI_ABIVERSION = 8,
|
||||||
Elf32_Half e_phentsize;
|
EI_PAD = 9,
|
||||||
Elf32_Half e_phnum;
|
EI_NIDENT = 16
|
||||||
Elf32_Half e_shentsize;
|
|
||||||
Elf32_Half e_shnum;
|
|
||||||
Elf32_Half e_shstrndx;
|
|
||||||
} Elf32_Ehdr;
|
|
||||||
|
|
||||||
typedef struct elf64_hdr
|
|
||||||
{
|
|
||||||
unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
|
|
||||||
Elf64_Half e_type;
|
|
||||||
Elf64_Half e_machine;
|
|
||||||
Elf64_Word e_version;
|
|
||||||
Elf64_Addr e_entry; /* Entry point virtual address */
|
|
||||||
Elf64_Off e_phoff; /* Program header table file offset */
|
|
||||||
Elf64_Off e_shoff; /* Section header table file offset */
|
|
||||||
Elf64_Word e_flags;
|
|
||||||
Elf64_Half e_ehsize;
|
|
||||||
Elf64_Half e_phentsize;
|
|
||||||
Elf64_Half e_phnum;
|
|
||||||
Elf64_Half e_shentsize;
|
|
||||||
Elf64_Half e_shnum;
|
|
||||||
Elf64_Half e_shstrndx;
|
|
||||||
} Elf64_Ehdr;
|
|
||||||
|
|
||||||
typedef struct elf32_shdr
|
|
||||||
{
|
|
||||||
Elf32_Word sh_name;
|
|
||||||
Elf32_Word sh_type;
|
|
||||||
Elf32_Word sh_flags;
|
|
||||||
Elf32_Addr sh_addr;
|
|
||||||
Elf32_Off sh_offset;
|
|
||||||
Elf32_Word sh_size;
|
|
||||||
Elf32_Word sh_link;
|
|
||||||
Elf32_Word sh_info;
|
|
||||||
Elf32_Word sh_addralign;
|
|
||||||
Elf32_Word sh_entsize;
|
|
||||||
} Elf32_Shdr;
|
|
||||||
|
|
||||||
typedef struct elf64_shdr
|
|
||||||
{
|
|
||||||
Elf64_Word sh_name; /* Section name, index in string tbl */
|
|
||||||
Elf64_Word sh_type; /* Type of section */
|
|
||||||
Elf64_Xword sh_flags; /* Miscellaneous section attributes */
|
|
||||||
Elf64_Addr sh_addr; /* Section virtual addr at execution */
|
|
||||||
Elf64_Off sh_offset; /* Section file offset */
|
|
||||||
Elf64_Xword sh_size; /* Size of section in bytes */
|
|
||||||
Elf64_Word sh_link; /* Index of another section */
|
|
||||||
Elf64_Word sh_info; /* Additional section information */
|
|
||||||
Elf64_Xword sh_addralign; /* Section alignment */
|
|
||||||
Elf64_Xword sh_entsize; /* Entry size if section holds table */
|
|
||||||
} Elf64_Shdr;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
Elf32_Word p_type;
|
|
||||||
Elf32_Off p_offset;
|
|
||||||
Elf32_Addr p_vaddr;
|
|
||||||
Elf32_Addr p_paddr;
|
|
||||||
Elf32_Word p_filesz;
|
|
||||||
Elf32_Word p_memsz;
|
|
||||||
Elf32_Word p_flags;
|
|
||||||
Elf32_Word p_align;
|
|
||||||
} Elf32_Phdr;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
Elf64_Word p_type;
|
|
||||||
Elf64_Word p_flags;
|
|
||||||
Elf64_Off p_offset;
|
|
||||||
Elf64_Addr p_vaddr;
|
|
||||||
Elf64_Addr p_paddr;
|
|
||||||
Elf64_Xword p_filesz;
|
|
||||||
Elf64_Xword p_memsz;
|
|
||||||
Elf64_Xword p_align;
|
|
||||||
} Elf64_Phdr;
|
|
||||||
|
|
||||||
typedef struct elf32_rel
|
|
||||||
{
|
|
||||||
Elf32_Addr r_offset;
|
|
||||||
Elf32_Word r_info;
|
|
||||||
} Elf32_Rel;
|
|
||||||
|
|
||||||
typedef struct elf64_rel
|
|
||||||
{
|
|
||||||
Elf64_Addr r_offset; /* Location at which to apply the action */
|
|
||||||
Elf64_Xword r_info; /* index and type of relocation */
|
|
||||||
} Elf64_Rel;
|
|
||||||
|
|
||||||
typedef struct elf32_sym
|
|
||||||
{
|
|
||||||
Elf32_Word st_name;
|
|
||||||
Elf32_Addr st_value;
|
|
||||||
Elf32_Word st_size;
|
|
||||||
unsigned char st_info;
|
|
||||||
unsigned char st_other;
|
|
||||||
Elf32_Half st_shndx;
|
|
||||||
} Elf32_Sym;
|
|
||||||
|
|
||||||
typedef struct elf64_sym
|
|
||||||
{
|
|
||||||
Elf64_Word st_name; /* Symbol name, index in string tbl */
|
|
||||||
unsigned char st_info; /* Type and binding attributes */
|
|
||||||
unsigned char st_other; /* No defined meaning, 0 */
|
|
||||||
Elf64_Half st_shndx; /* Associated section index */
|
|
||||||
Elf64_Addr st_value; /* Value of the symbol */
|
|
||||||
Elf64_Xword st_size; /* Associated symbol size */
|
|
||||||
} Elf64_Sym;
|
|
||||||
|
|
||||||
struct Elf32_Dyn
|
|
||||||
{
|
|
||||||
Elf32_Sword d_tag; /* Type of dynamic table entry. */
|
|
||||||
union
|
|
||||||
{
|
|
||||||
Elf32_Word d_val; /* Integer value of entry. */
|
|
||||||
Elf32_Addr d_ptr; /* Pointer value of entry. */
|
|
||||||
} d_un;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Elf64_Dyn
|
|
||||||
{
|
|
||||||
Elf64_Sxword d_tag; /* Type of dynamic table entry. */
|
|
||||||
union
|
|
||||||
{
|
|
||||||
Elf64_Xword d_val; /* Integer value of entry. */
|
|
||||||
Elf64_Addr d_ptr; /* Pointer value of entry. */
|
|
||||||
} d_un;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
Elf64_Addr r_offset;
|
|
||||||
Elf64_Xword r_info;
|
|
||||||
Elf64_Sxword r_addend;
|
|
||||||
} Elf64_Rela;
|
|
||||||
|
|
||||||
enum Elf_Ident
|
|
||||||
{
|
|
||||||
EI_MAG0 = 0, // 0x7F
|
|
||||||
EI_MAG1 = 1, // 'E'
|
|
||||||
EI_MAG2 = 2, // 'L'
|
|
||||||
EI_MAG3 = 3, // 'F'
|
|
||||||
EI_CLASS = 4, // Architecture (32/64)
|
|
||||||
EI_DATA = 5, // Byte Order
|
|
||||||
EI_VERSION = 6, // ELF Version
|
|
||||||
EI_OSABI = 7, // OS Specific
|
|
||||||
EI_ABIVERSION = 8, // OS Specific
|
|
||||||
EI_PAD = 9 // Padding
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Elf_OSABI
|
enum Elf_OSABI
|
||||||
{
|
{
|
||||||
ELFOSABI_NONE = 0,
|
ELFOSABI_NONE = 0,
|
||||||
|
ELFOSABI_SYSV = 0,
|
||||||
ELFOSABI_HPUX = 1,
|
ELFOSABI_HPUX = 1,
|
||||||
ELFOSABI_NETBSD = 2,
|
ELFOSABI_NETBSD = 2,
|
||||||
|
ELFOSABI_GNU = 3,
|
||||||
ELFOSABI_LINUX = 3,
|
ELFOSABI_LINUX = 3,
|
||||||
ELFOSABI_HURD = 4,
|
ELFOSABI_HURD = 4,
|
||||||
ELFOSABI_SOLARIS = 6,
|
ELFOSABI_SOLARIS = 6,
|
||||||
@ -229,22 +80,62 @@ enum Elf_OSABI
|
|||||||
ELFOSABI_STANDALONE = 255
|
ELFOSABI_STANDALONE = 255
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Elf_Type
|
enum FileIdentifiers
|
||||||
{
|
{
|
||||||
ET_NONE = 0, // Unknown Type
|
ET_NONE = 0,
|
||||||
ET_REL = 1, // Relocatable File
|
ET_REL = 1,
|
||||||
ET_EXEC = 2, // Executable File
|
ET_EXEC = 2,
|
||||||
ET_DYN = 3, // Shared Object File
|
ET_DYN = 3,
|
||||||
ET_CORE = 4, // Core File
|
ET_CORE = 4,
|
||||||
ET_LOPROC = 0xff00, // Processor Specific
|
ET_LOPROC = 0xff00,
|
||||||
ET_HIPROC = 0xffff // Processor Specific
|
ET_HIPROC = 0xffff
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RtT_Types
|
enum RelocationTypes
|
||||||
{
|
{
|
||||||
R_386_NONE = 0, // No relocation
|
R_386_NONE = 0,
|
||||||
R_386_32 = 1, // Symbol + Offset
|
R_386_32 = 1,
|
||||||
R_386_PC32 = 2, // Symbol + Offset - Section Offset
|
R_386_PC32 = 2,
|
||||||
|
R_386_GOT32 = 3,
|
||||||
|
R_386_PLT32 = 4,
|
||||||
|
R_386_COPY = 5,
|
||||||
|
R_386_GLOB_DAT = 6,
|
||||||
|
R_386_JMP_SLOT = 7,
|
||||||
|
R_386_RELATIVE = 8,
|
||||||
|
R_386_GOTOFF = 9,
|
||||||
|
R_386_GOTPC = 10,
|
||||||
|
R_386_32PLT = 11,
|
||||||
|
R_386_TLS_TPOFF = 14,
|
||||||
|
R_386_TLS_IE = 15,
|
||||||
|
R_386_TLS_GOTIE = 16,
|
||||||
|
R_386_TLS_LE = 17,
|
||||||
|
R_386_TLS_GD = 18,
|
||||||
|
R_386_TLS_LDM = 19,
|
||||||
|
R_386_16 = 20,
|
||||||
|
R_386_PC16 = 21,
|
||||||
|
R_386_8 = 22,
|
||||||
|
R_386_PC8 = 23,
|
||||||
|
R_386_TLS_GD_32 = 24,
|
||||||
|
R_386_TLS_GD_PUSH = 25,
|
||||||
|
R_386_TLS_GD_CALL = 26,
|
||||||
|
R_386_TLS_GD_POP = 27,
|
||||||
|
R_386_TLS_LDM_32 = 28,
|
||||||
|
R_386_TLS_LDM_PUSH = 29,
|
||||||
|
R_386_TLS_LDM_CALL = 30,
|
||||||
|
R_386_TLS_LDM_POP = 31,
|
||||||
|
R_386_TLS_LDO_32 = 32,
|
||||||
|
R_386_TLS_IE_32 = 33,
|
||||||
|
R_386_TLS_LE_32 = 34,
|
||||||
|
R_386_TLS_DTPMOD32 = 35,
|
||||||
|
R_386_TLS_DTPOFF32 = 36,
|
||||||
|
R_386_TLS_TPOFF32 = 37,
|
||||||
|
R_386_SIZE32 = 38,
|
||||||
|
R_386_TLS_GOTDESC = 39,
|
||||||
|
R_386_TLS_DESC_CALL = 40,
|
||||||
|
R_386_TLS_DESC = 41,
|
||||||
|
R_386_IRELATIVE = 42,
|
||||||
|
R_386_GOT32X = 43,
|
||||||
|
R_386_NUM = 44,
|
||||||
|
|
||||||
R_X86_64_NONE = 0,
|
R_X86_64_NONE = 0,
|
||||||
R_X86_64_64 = 1,
|
R_X86_64_64 = 1,
|
||||||
@ -259,52 +150,69 @@ enum RtT_Types
|
|||||||
R_X86_64_32 = 10,
|
R_X86_64_32 = 10,
|
||||||
R_X86_64_32S = 11,
|
R_X86_64_32S = 11,
|
||||||
R_X86_64_16 = 12,
|
R_X86_64_16 = 12,
|
||||||
|
R_X86_64_PC16 = 13,
|
||||||
|
R_X86_64_8 = 14,
|
||||||
|
R_X86_64_PC8 = 15,
|
||||||
|
R_X86_64_DTPMOD64 = 16,
|
||||||
|
R_X86_64_DTPOFF64 = 17,
|
||||||
|
R_X86_64_TPOFF64 = 18,
|
||||||
|
R_X86_64_TLSGD = 19,
|
||||||
|
R_X86_64_TLSLD = 20,
|
||||||
|
R_X86_64_DTPOFF32 = 21,
|
||||||
|
R_X86_64_GOTTPOFF = 22,
|
||||||
|
R_X86_64_TPOFF32 = 23,
|
||||||
|
R_X86_64_PC64 = 24,
|
||||||
|
R_X86_64_GOTOFF64 = 25,
|
||||||
|
R_X86_64_GOTPC32 = 26,
|
||||||
|
R_X86_64_GOT64 = 27,
|
||||||
|
R_X86_64_GOTPCREL64 = 28,
|
||||||
|
R_X86_64_GOTPC64 = 29,
|
||||||
|
R_X86_64_GOTPLT64 = 30,
|
||||||
|
R_X86_64_PLTOFF64 = 31,
|
||||||
|
R_X86_64_SIZE32 = 32,
|
||||||
|
R_X86_64_SIZE64 = 33,
|
||||||
|
R_X86_64_GOTPC32_TLSDESC = 34,
|
||||||
|
R_X86_64_TLSDESC_CALL = 35,
|
||||||
|
R_X86_64_TLSDESC = 36,
|
||||||
|
R_X86_64_IRELATIVE = 37,
|
||||||
|
R_X86_64_RELATIVE64 = 38,
|
||||||
|
R_X86_64_GOTPCRELX = 41,
|
||||||
|
R_X86_64_REX_GOTPCRELX = 42,
|
||||||
|
R_X86_64_NUM = 43
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ProgFlags_Types
|
enum SegmentFlags
|
||||||
{
|
{
|
||||||
PF_X = 1,
|
PF_X = 1,
|
||||||
PF_W = 2,
|
PF_W = 2,
|
||||||
PF_R = 4
|
PF_R = 4,
|
||||||
|
PF_MASKPROC = 0xf0000000
|
||||||
};
|
};
|
||||||
|
|
||||||
enum StT_Bindings
|
enum SymbolBindings
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @brief Local symbol. Symbol is not visible outside the object file.
|
|
||||||
*/
|
|
||||||
STB_LOCAL = 0,
|
STB_LOCAL = 0,
|
||||||
/**
|
|
||||||
* @brief Global symbol. These symbols are visible to all object files being combined.
|
|
||||||
*/
|
|
||||||
STB_GLOBAL = 1,
|
STB_GLOBAL = 1,
|
||||||
/**
|
|
||||||
* @brief Weak symbols. These symbols are like global symbols, but their definitions are not required. Weak symbols are not visible outside the object file containing their definition.
|
|
||||||
*/
|
|
||||||
STB_WEAK = 2,
|
STB_WEAK = 2,
|
||||||
/**
|
|
||||||
* @brief Values in this inclusive range are reserved for operating system-specific semantics.
|
|
||||||
*/
|
|
||||||
STB_LOOS = 10,
|
STB_LOOS = 10,
|
||||||
/**
|
|
||||||
* @brief Values in this inclusive range are reserved for operating system-specific semantics.
|
|
||||||
*/
|
|
||||||
STB_HIOS = 12,
|
STB_HIOS = 12,
|
||||||
/**
|
|
||||||
* @brief Values in this inclusive range are reserved for processor-specific semantics.
|
|
||||||
*/
|
|
||||||
STB_LOPROC = 13,
|
STB_LOPROC = 13,
|
||||||
/**
|
|
||||||
* @brief Values in this inclusive range are reserved for processor-specific semantics.
|
|
||||||
*/
|
|
||||||
STB_HIPROC = 15
|
STB_HIPROC = 15
|
||||||
};
|
};
|
||||||
|
|
||||||
enum StT_Types
|
enum SymbolTypes
|
||||||
{
|
{
|
||||||
STT_NOTYPE = 0, // No type
|
STT_NOTYPE = 0,
|
||||||
STT_OBJECT = 1, // Variables, arrays, etc.
|
STT_OBJECT = 1,
|
||||||
STT_FUNC = 2 // Methods or functions
|
STT_FUNC = 2,
|
||||||
|
STT_SECTION = 3,
|
||||||
|
STT_FILE = 4,
|
||||||
|
STT_COMMON = 5,
|
||||||
|
STT_LOOS = 10,
|
||||||
|
STT_HIOS = 12,
|
||||||
|
STT_LOPROC = 13,
|
||||||
|
STT_SPARC_REGISTER = 13,
|
||||||
|
STT_HIPROC = 15
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SegmentTypes
|
enum SegmentTypes
|
||||||
@ -325,7 +233,6 @@ enum SegmentTypes
|
|||||||
PT_HIPROC = 0x7fffffff
|
PT_HIPROC = 0x7fffffff
|
||||||
};
|
};
|
||||||
|
|
||||||
/* https://docs.oracle.com/cd/E19683-01/817-3677/chapter6-42444/index.html */
|
|
||||||
enum DynamicArrayTags
|
enum DynamicArrayTags
|
||||||
{
|
{
|
||||||
DT_NULL = 0,
|
DT_NULL = 0,
|
||||||
@ -398,7 +305,7 @@ enum DynamicArrayTags
|
|||||||
DT_HIPROC = 0x7fffffff
|
DT_HIPROC = 0x7fffffff
|
||||||
};
|
};
|
||||||
|
|
||||||
// used for Elf64_Sym st_info
|
/* Used for Elf64_Sym st_info */
|
||||||
#define ELF32_ST_BIND(info) ((info) >> 4)
|
#define ELF32_ST_BIND(info) ((info) >> 4)
|
||||||
#define ELF32_ST_TYPE(info) ((info)&0xf)
|
#define ELF32_ST_TYPE(info) ((info)&0xf)
|
||||||
#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type)&0xf))
|
#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type)&0xf))
|
||||||
@ -406,7 +313,7 @@ enum DynamicArrayTags
|
|||||||
#define ELF64_ST_TYPE(info) ((info)&0xf)
|
#define ELF64_ST_TYPE(info) ((info)&0xf)
|
||||||
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type)&0xf))
|
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type)&0xf))
|
||||||
|
|
||||||
// used for Elf64_Sym st_other
|
/* Used for Elf64_Sym st_other */
|
||||||
#define ELF32_ST_VISIBILITY(o) ((o)&0x3)
|
#define ELF32_ST_VISIBILITY(o) ((o)&0x3)
|
||||||
#define ELF64_ST_VISIBILITY(o) ((o)&0x3)
|
#define ELF64_ST_VISIBILITY(o) ((o)&0x3)
|
||||||
|
|
||||||
@ -427,68 +334,395 @@ enum DynamicArrayTags
|
|||||||
#define SHN_UNDEF 0
|
#define SHN_UNDEF 0
|
||||||
#define SHN_ABS 0xfff1
|
#define SHN_ABS 0xfff1
|
||||||
|
|
||||||
#define SHT_NOBITS 8
|
|
||||||
#define SHT_REL 9
|
|
||||||
|
|
||||||
#define SHF_WRITE 0x1
|
#define SHF_WRITE 0x1
|
||||||
#define SHF_ALLOC 0x2
|
#define SHF_ALLOC 0x2
|
||||||
|
|
||||||
#define EM_386 0x3 // x86 Machine Type
|
#define EM_NONE 0 /* No machine */
|
||||||
#define EM_X86_64 0x3E // 64bit
|
#define EM_M32 1 /* AT&T WE 32100 */
|
||||||
#define EM_ARM 0x28 // ARM
|
#define EM_SPARC 2 /* SPARC */
|
||||||
#define EM_AARCH64 0xb7 // ARM64
|
#define EM_386 3 /* Intel 80386 */
|
||||||
|
#define EM_68K 4 /* Motorola 68000 */
|
||||||
|
#define EM_88K 5 /* Motorola 88000 */
|
||||||
|
#define EM_IAMCU 6 /* Intel MCU */
|
||||||
|
#define EM_860 7 /* Intel 80860 */
|
||||||
|
#define EM_MIPS 8 /* MIPS I Architecture */
|
||||||
|
#define EM_S370 9 /* IBM System/370 Processor */
|
||||||
|
#define EM_MIPS_RS3_LE 10 /* MIPS RS3000 Little-endian */
|
||||||
|
#define EM_PARISC 15 /* Hewlett-Packard PA-RISC */
|
||||||
|
#define EM_VPP500 17 /* Fujitsu VPP500 */
|
||||||
|
#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */
|
||||||
|
#define EM_960 19 /* Intel 80960 */
|
||||||
|
#define EM_PPC 20 /* PowerPC */
|
||||||
|
#define EM_PPC64 21 /* 64-bit PowerPC */
|
||||||
|
#define EM_S390 22 /* IBM System/390 Processor */
|
||||||
|
#define EM_SPU 23 /* IBM SPU/SPC */
|
||||||
|
#define EM_V800 36 /* NEC V800 */
|
||||||
|
#define EM_FR20 37 /* Fujitsu FR20 */
|
||||||
|
#define EM_RH32 38 /* TRW RH-32 */
|
||||||
|
#define EM_RCE 39 /* Motorola RCE */
|
||||||
|
#define EM_ARM 40 /* ARM 32-bit architecture (AARCH32) */
|
||||||
|
#define EM_ALPHA 41 /* Digital Alpha */
|
||||||
|
#define EM_SH 42 /* Hitachi SH */
|
||||||
|
#define EM_SPARCV9 43 /* SPARC Version 9 */
|
||||||
|
#define EM_TRICORE 44 /* Siemens TriCore embedded processor */
|
||||||
|
#define EM_ARC 45 /* Argonaut RISC Core, Argonaut Technologies Inc. */
|
||||||
|
#define EM_H8_300 46 /* Hitachi H8/300 */
|
||||||
|
#define EM_H8_300H 47 /* Hitachi H8/300H */
|
||||||
|
#define EM_H8S 48 /* Hitachi H8S */
|
||||||
|
#define EM_H8_500 49 /* Hitachi H8/500 */
|
||||||
|
#define EM_IA_64 50 /* Intel IA-64 processor architecture */
|
||||||
|
#define EM_MIPS_X 51 /* Stanford MIPS-X */
|
||||||
|
#define EM_COLDFIRE 52 /* Motorola ColdFire */
|
||||||
|
#define EM_68HC12 53 /* Motorola M68HC12 */
|
||||||
|
#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator */
|
||||||
|
#define EM_PCP 55 /* Siemens PCP */
|
||||||
|
#define EM_NCPU 56 /* Sony nCPU embedded RISC processor */
|
||||||
|
#define EM_NDR1 57 /* Denso NDR1 microprocessor */
|
||||||
|
#define EM_STARCORE 58 /* Motorola Star*Core processor */
|
||||||
|
#define EM_ME16 59 /* Toyota ME16 processor */
|
||||||
|
#define EM_ST100 60 /* STMicroelectronics ST100 processor */
|
||||||
|
#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ embedded processor family */
|
||||||
|
#define EM_X86_64 62 /* AMD x86-64 architecture */
|
||||||
|
#define EM_PDSP 63 /* Sony DSP Processor */
|
||||||
|
#define EM_PDP10 64 /* Digital Equipment Corp. PDP-10 */
|
||||||
|
#define EM_PDP11 65 /* Digital Equipment Corp. PDP-11 */
|
||||||
|
#define EM_FX66 66 /* Siemens FX66 microcontroller */
|
||||||
|
#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 bit microcontroller */
|
||||||
|
#define EM_ST7 68 /* STMicroelectronics ST7 8-bit microcontroller */
|
||||||
|
#define EM_68HC16 69 /* Motorola MC68HC16 Microcontroller */
|
||||||
|
#define EM_68HC11 70 /* Motorola MC68HC11 Microcontroller */
|
||||||
|
#define EM_68HC08 71 /* Motorola MC68HC08 Microcontroller */
|
||||||
|
#define EM_68HC05 72 /* Motorola MC68HC05 Microcontroller */
|
||||||
|
#define EM_SVX 73 /* Silicon Graphics SVx */
|
||||||
|
#define EM_ST19 74 /* STMicroelectronics ST19 8-bit microcontroller */
|
||||||
|
#define EM_VAX 75 /* Digital VAX */
|
||||||
|
#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */
|
||||||
|
#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */
|
||||||
|
#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */
|
||||||
|
#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */
|
||||||
|
#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */
|
||||||
|
#define EM_HUANY 81 /* Harvard University machine-independent object files */
|
||||||
|
#define EM_PRISM 82 /* SiTera Prism */
|
||||||
|
#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */
|
||||||
|
#define EM_FR30 84 /* Fujitsu FR30 */
|
||||||
|
#define EM_D10V 85 /* Mitsubishi D10V */
|
||||||
|
#define EM_D30V 86 /* Mitsubishi D30V */
|
||||||
|
#define EM_V850 87 /* NEC v850 */
|
||||||
|
#define EM_M32R 88 /* Mitsubishi M32R */
|
||||||
|
#define EM_MN10300 89 /* Matsushita MN10300 */
|
||||||
|
#define EM_MN10200 90 /* Matsushita MN10200 */
|
||||||
|
#define EM_PJ 91 /* picoJava */
|
||||||
|
#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
|
||||||
|
#define EM_ARC_COMPACT 93 /* ARC International ARCompact processor (old spelling/synonym: EM_ARC_A5) */
|
||||||
|
#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
|
||||||
|
#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor */
|
||||||
|
#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose Processor */
|
||||||
|
#define EM_NS32K 97 /* National Semiconductor 32000 series */
|
||||||
|
#define EM_TPC 98 /* Tenor Network TPC processor */
|
||||||
|
#define EM_SNP1K 99 /* Trebia SNP 1000 processor */
|
||||||
|
#define EM_ST200 100 /* STMicroelectronics (www.st.com) ST200 microcontroller */
|
||||||
|
#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family */
|
||||||
|
#define EM_MAX 102 /* MAX Processor */
|
||||||
|
#define EM_CR 103 /* National Semiconductor CompactRISC microprocessor */
|
||||||
|
#define EM_F2MC16 104 /* Fujitsu F2MC16 */
|
||||||
|
#define EM_MSP430 105 /* Texas Instruments embedded microcontroller msp430 */
|
||||||
|
#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor */
|
||||||
|
#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors */
|
||||||
|
#define EM_SEP 108 /* Sharp embedded microprocessor */
|
||||||
|
#define EM_ARCA 109 /* Arca RISC Microprocessor */
|
||||||
|
#define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University */
|
||||||
|
#define EM_EXCESS 111 /* eXcess: 16/32/64-bit configurable embedded CPU */
|
||||||
|
#define EM_DXP 112 /* Icera Semiconductor Inc. Deep Execution Processor */
|
||||||
|
#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */
|
||||||
|
#define EM_CRX 114 /* National Semiconductor CompactRISC CRX microprocessor */
|
||||||
|
#define EM_XGATE 115 /* Motorola XGATE embedded processor */
|
||||||
|
#define EM_C166 116 /* Infineon C16x/XC16x processor */
|
||||||
|
#define EM_M16C 117 /* Renesas M16C series microprocessors */
|
||||||
|
#define EM_DSPIC30F 118 /* Microchip Technology dsPIC30F Digital Signal Controller */
|
||||||
|
#define EM_CE 119 /* Freescale Communication Engine RISC core */
|
||||||
|
#define EM_M32C 120 /* Renesas M32C series microprocessors */
|
||||||
|
#define EM_TSK3000 131 /* Altium TSK3000 core */
|
||||||
|
#define EM_RS08 132 /* Freescale RS08 embedded processor */
|
||||||
|
#define EM_SHARC 133 /* Analog Devices SHARC family of 32-bit DSP processors */
|
||||||
|
#define EM_ECOG2 134 /* Cyan Technology eCOG2 microprocessor */
|
||||||
|
#define EM_SCORE7 135 /* Sunplus S+core7 RISC processor */
|
||||||
|
#define EM_DSP24 136 /* New Japan Radio (NJR) 24-bit DSP Processor */
|
||||||
|
#define EM_VIDEOCORE3 137 /* Broadcom VideoCore III processor */
|
||||||
|
#define EM_LATTICEMICO32 138 /* RISC processor for Lattice FPGA architecture */
|
||||||
|
#define EM_SE_C17 139 /* Seiko Epson C17 family */
|
||||||
|
#define EM_TI_C6000 140 /* The Texas Instruments TMS320C6000 DSP family */
|
||||||
|
#define EM_TI_C2000 141 /* The Texas Instruments TMS320C2000 DSP family */
|
||||||
|
#define EM_TI_C5500 142 /* The Texas Instruments TMS320C55x DSP family */
|
||||||
|
#define EM_TI_ARP32 143 /* Texas Instruments Application Specific RISC Processor, 32bit fetch */
|
||||||
|
#define EM_TI_PRU 144 /* Texas Instruments Programmable Realtime Unit */
|
||||||
|
#define EM_MMDSP_PLUS 160 /* STMicroelectronics 64bit VLIW Data Signal Processor */
|
||||||
|
#define EM_CYPRESS_M8C 161 /* Cypress M8C microprocessor */
|
||||||
|
#define EM_R32C 162 /* Renesas R32C series microprocessors */
|
||||||
|
#define EM_TRIMEDIA 163 /* NXP Semiconductors TriMedia architecture family */
|
||||||
|
#define EM_QDSP6 164 /* QUALCOMM DSP6 Processor */
|
||||||
|
#define EM_8051 165 /* Intel 8051 and variants */
|
||||||
|
#define EM_STXP7X 166 /* STMicroelectronics STxP7x family of configurable and extensible RISC processors */
|
||||||
|
#define EM_NDS32 167 /* Andes Technology compact code size embedded RISC processor family */
|
||||||
|
#define EM_ECOG1 168 /* Cyan Technology eCOG1X family */
|
||||||
|
#define EM_ECOG1X 168 /* Cyan Technology eCOG1X family */
|
||||||
|
#define EM_MAXQ30 169 /* Dallas Semiconductor MAXQ30 Core Micro-controllers */
|
||||||
|
#define EM_XIMO16 170 /* New Japan Radio (NJR) 16-bit DSP Processor */
|
||||||
|
#define EM_MANIK 171 /* M2000 Reconfigurable RISC Microprocessor */
|
||||||
|
#define EM_CRAYNV2 172 /* Cray Inc. NV2 vector architecture */
|
||||||
|
#define EM_RX 173 /* Renesas RX family */
|
||||||
|
#define EM_METAG 174 /* Imagination Technologies META processor architecture */
|
||||||
|
#define EM_MCST_ELBRUS 175 /* MCST Elbrus general purpose hardware architecture */
|
||||||
|
#define EM_ECOG16 176 /* Cyan Technology eCOG16 family */
|
||||||
|
#define EM_CR16 177 /* National Semiconductor CompactRISC CR16 16-bit microprocessor */
|
||||||
|
#define EM_ETPU 178 /* Freescale Extended Time Processing Unit */
|
||||||
|
#define EM_SLE9X 179 /* Infineon Technologies SLE9X core */
|
||||||
|
#define EM_L10M 180 /* Intel L10M */
|
||||||
|
#define EM_K10M 181 /* Intel K10M */
|
||||||
|
#define EM_AARCH64 183 /* ARM 64-bit architecture (AARCH64) */
|
||||||
|
#define EM_AVR32 185 /* Atmel Corporation 32-bit microprocessor family */
|
||||||
|
#define EM_STM8 186 /* STMicroeletronics STM8 8-bit microcontroller */
|
||||||
|
#define EM_TILE64 187 /* Tilera TILE64 multicore architecture family */
|
||||||
|
#define EM_TILEPRO 188 /* Tilera TILEPro multicore architecture family */
|
||||||
|
#define EM_MICROBLAZE 189 /* Xilinx MicroBlaze 32-bit RISC soft processor core */
|
||||||
|
#define EM_CUDA 190 /* NVIDIA CUDA architecture */
|
||||||
|
#define EM_TILEGX 191 /* Tilera TILE-Gx multicore architecture family */
|
||||||
|
#define EM_CLOUDSHIELD 192 /* CloudShield architecture family */
|
||||||
|
#define EM_COREA_1ST 193 /* KIPO-KAIST Core-A 1st generation processor family */
|
||||||
|
#define EM_COREA_2ND 194 /* KIPO-KAIST Core-A 2nd generation processor family */
|
||||||
|
#define EM_ARC_COMPACT2 195 /* Synopsys ARCompact V2 */
|
||||||
|
#define EM_OPEN8 196 /* Open8 8-bit RISC soft processor core */
|
||||||
|
#define EM_RL78 197 /* Renesas RL78 family */
|
||||||
|
#define EM_VIDEOCORE5 198 /* Broadcom VideoCore V processor */
|
||||||
|
#define EM_78KOR 199 /* Renesas 78KOR family */
|
||||||
|
#define EM_56800EX 200 /* Freescale 56800EX Digital Signal Controller (DSC) */
|
||||||
|
#define EM_BA1 201 /* Beyond BA1 CPU architecture */
|
||||||
|
#define EM_BA2 202 /* Beyond BA2 CPU architecture */
|
||||||
|
#define EM_XCORE 203 /* XMOS xCORE processor family */
|
||||||
|
#define EM_MCHP_PIC 204 /* Microchip 8-bit PIC(r) family */
|
||||||
|
#define EM_INTEL205 205 /* Reserved by Intel */
|
||||||
|
#define EM_INTEL206 206 /* Reserved by Intel */
|
||||||
|
#define EM_INTEL207 207 /* Reserved by Intel */
|
||||||
|
#define EM_INTEL208 208 /* Reserved by Intel */
|
||||||
|
#define EM_INTEL209 209 /* Reserved by Intel */
|
||||||
|
#define EM_KM32 210 /* KM211 KM32 32-bit processor */
|
||||||
|
#define EM_KMX32 211 /* KM211 KMX32 32-bit processor */
|
||||||
|
#define EM_KMX16 212 /* KM211 KMX16 16-bit processor */
|
||||||
|
#define EM_KMX8 213 /* KM211 KMX8 8-bit processor */
|
||||||
|
#define EM_KVARC 214 /* KM211 KVARC processor */
|
||||||
|
#define EM_CDP 215 /* Paneve CDP architecture family */
|
||||||
|
#define EM_COGE 216 /* Cognitive Smart Memory Processor */
|
||||||
|
#define EM_COOL 217 /* Bluechip Systems CoolEngine */
|
||||||
|
#define EM_NORC 218 /* Nanoradio Optimized RISC */
|
||||||
|
#define EM_CSR_KALIMBA 219 /* CSR Kalimba architecture family */
|
||||||
|
#define EM_Z80 220 /* Zilog Z80 */
|
||||||
|
#define EM_VISIUM 221 /* Controls and Data Services VISIUMcore processor */
|
||||||
|
#define EM_FT32 222 /* FTDI Chip FT32 high performance 32-bit RISC architecture */
|
||||||
|
#define EM_MOXIE 223 /* Moxie processor family */
|
||||||
|
#define EM_AMDGPU 224 /* AMD GPU architecture */
|
||||||
|
#define EM_RISCV 243 /* RISC-V */
|
||||||
|
|
||||||
#define EV_CURRENT 0x1 // ELF Current Version
|
#define EV_NONE 0x0 /* Invalid ELF Version */
|
||||||
|
#define EV_CURRENT 0x1 /* ELF Current Version */
|
||||||
|
|
||||||
#define ELFMAG0 0x7F // e_ident[EI_MAG0]
|
#define ELFMAG0 0x7F
|
||||||
#define ELFMAG1 'E' // e_ident[EI_MAG1]
|
#define ELFMAG1 'E'
|
||||||
#define ELFMAG2 'L' // e_ident[EI_MAG2]
|
#define ELFMAG2 'L'
|
||||||
#define ELFMAG3 'F' // e_ident[EI_MAG3]
|
#define ELFMAG3 'F'
|
||||||
|
|
||||||
#define ELFDATANONE 0 /* e_ident[EI_DATA] */
|
#define ELFDATANONE 0
|
||||||
#define ELFDATA2LSB 1
|
#define ELFDATA2LSB 1
|
||||||
#define ELFDATA2MSB 2
|
#define ELFDATA2MSB 2
|
||||||
|
|
||||||
#define ELFCLASSNONE 0 /* EI_CLASS */
|
#define ELFCLASSNONE 0
|
||||||
#define ELFCLASS32 1
|
#define ELFCLASS32 1
|
||||||
#define ELFCLASS64 2
|
#define ELFCLASS64 2
|
||||||
#define ELFCLASSNUM 3
|
#define ELFCLASSNUM 3
|
||||||
|
|
||||||
#define SHT_NULL 0 /* Section header table entry unused */
|
enum SpecialSections
|
||||||
#define SHT_PROGBITS 1 /* Program data */
|
{
|
||||||
#define SHT_SYMTAB 2 /* Symbol table */
|
SHT_NULL = 0,
|
||||||
#define SHT_STRTAB 3 /* String table */
|
SHT_PROGBITS = 1,
|
||||||
#define SHT_RELA 4 /* Relocation entries with addends */
|
SHT_SYMTAB = 2,
|
||||||
#define SHT_HASH 5 /* Symbol hash table */
|
SHT_STRTAB = 3,
|
||||||
#define SHT_DYNAMIC 6 /* Dynamic linking information */
|
SHT_RELA = 4,
|
||||||
#define SHT_NOTE 7 /* Notes */
|
SHT_HASH = 5,
|
||||||
#define SHT_NOBITS 8 /* Program space with no data (bss) */
|
SHT_DYNAMIC = 6,
|
||||||
#define SHT_REL 9 /* Relocation entries, no addends */
|
SHT_NOTE = 7,
|
||||||
#define SHT_SHLIB 10 /* Reserved */
|
SHT_NOBITS = 8,
|
||||||
#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
|
SHT_REL = 9,
|
||||||
#define SHT_INIT_ARRAY 14 /* Array of constructors */
|
SHT_SHLIB = 10,
|
||||||
#define SHT_FINI_ARRAY 15 /* Array of destructors */
|
SHT_DYNSYM = 11,
|
||||||
#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
|
SHT_INIT_ARRAY = 14,
|
||||||
#define SHT_GROUP 17 /* Section group */
|
SHT_FINI_ARRAY = 15,
|
||||||
#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
|
SHT_PREINIT_ARRAY = 16,
|
||||||
#define SHT_NUM 19 /* Number of defined types. */
|
SHT_GROUP = 17,
|
||||||
#define SHT_LOOS 0x60000000 /* Start OS-specific. */
|
SHT_SYMTAB_SHNDX = 18,
|
||||||
#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */
|
SHT_NUM = 19,
|
||||||
#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */
|
SHT_LOOS = 0x60000000,
|
||||||
#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */
|
SHT_GNU_ATTRIBUTES = 0x6ffffff5,
|
||||||
#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */
|
SHT_GNU_HASH = 0x6ffffff6,
|
||||||
#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */
|
SHT_GNU_LIBLIST = 0x6ffffff7,
|
||||||
#define SHT_SUNW_move 0x6ffffffa
|
SHT_CHECKSUM = 0x6ffffff8,
|
||||||
#define SHT_SUNW_COMDAT 0x6ffffffb
|
SHT_LOSUNW = 0x6ffffffa,
|
||||||
#define SHT_SUNW_syminfo 0x6ffffffc
|
SHT_SUNW_move = 0x6ffffffa,
|
||||||
#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */
|
SHT_SUNW_COMDAT = 0x6ffffffb,
|
||||||
#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */
|
SHT_SUNW_syminfo = 0x6ffffffc,
|
||||||
#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */
|
SHT_GNU_verdef = 0x6ffffffd,
|
||||||
#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */
|
SHT_GNU_verneed = 0x6ffffffe,
|
||||||
#define SHT_HIOS 0x6fffffff /* End OS-specific type */
|
SHT_GNU_versym = 0x6fffffff,
|
||||||
#define SHT_LOPROC 0x70000000 /* Start of processor-specific */
|
SHT_HISUNW = 0x6fffffff,
|
||||||
#define SHT_HIPROC 0x7fffffff /* End of processor-specific */
|
SHT_HIOS = 0x6fffffff,
|
||||||
#define SHT_LOUSER 0x80000000 /* Start of application-specific */
|
SHT_LOPROC = 0x70000000,
|
||||||
#define SHT_HIUSER 0x8fffffff /* End of application-specific */
|
SHT_HIPROC = 0x7fffffff,
|
||||||
|
SHT_LOUSER = 0x80000000,
|
||||||
|
SHT_HIUSER = 0x8fffffff
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct elf32_hdr
|
||||||
|
{
|
||||||
|
unsigned char e_ident[EI_NIDENT];
|
||||||
|
Elf32_Half e_type;
|
||||||
|
Elf32_Half e_machine;
|
||||||
|
Elf32_Word e_version;
|
||||||
|
Elf32_Addr e_entry;
|
||||||
|
Elf32_Off e_phoff;
|
||||||
|
Elf32_Off e_shoff;
|
||||||
|
Elf32_Word e_flags;
|
||||||
|
Elf32_Half e_ehsize;
|
||||||
|
Elf32_Half e_phentsize;
|
||||||
|
Elf32_Half e_phnum;
|
||||||
|
Elf32_Half e_shentsize;
|
||||||
|
Elf32_Half e_shnum;
|
||||||
|
Elf32_Half e_shstrndx;
|
||||||
|
} Elf32_Ehdr;
|
||||||
|
|
||||||
|
typedef struct elf64_hdr
|
||||||
|
{
|
||||||
|
unsigned char e_ident[EI_NIDENT];
|
||||||
|
Elf64_Half e_type;
|
||||||
|
Elf64_Half e_machine;
|
||||||
|
Elf64_Word e_version;
|
||||||
|
Elf64_Addr e_entry;
|
||||||
|
Elf64_Off e_phoff;
|
||||||
|
Elf64_Off e_shoff;
|
||||||
|
Elf64_Word e_flags;
|
||||||
|
Elf64_Half e_ehsize;
|
||||||
|
Elf64_Half e_phentsize;
|
||||||
|
Elf64_Half e_phnum;
|
||||||
|
Elf64_Half e_shentsize;
|
||||||
|
Elf64_Half e_shnum;
|
||||||
|
Elf64_Half e_shstrndx;
|
||||||
|
} Elf64_Ehdr;
|
||||||
|
|
||||||
|
typedef struct elf32_shdr
|
||||||
|
{
|
||||||
|
Elf32_Word sh_name;
|
||||||
|
Elf32_Word sh_type;
|
||||||
|
Elf32_Word sh_flags;
|
||||||
|
Elf32_Addr sh_addr;
|
||||||
|
Elf32_Off sh_offset;
|
||||||
|
Elf32_Word sh_size;
|
||||||
|
Elf32_Word sh_link;
|
||||||
|
Elf32_Word sh_info;
|
||||||
|
Elf32_Word sh_addralign;
|
||||||
|
Elf32_Word sh_entsize;
|
||||||
|
} Elf32_Shdr;
|
||||||
|
|
||||||
|
typedef struct elf64_shdr
|
||||||
|
{
|
||||||
|
Elf64_Word sh_name;
|
||||||
|
Elf64_Word sh_type;
|
||||||
|
Elf64_Xword sh_flags;
|
||||||
|
Elf64_Addr sh_addr;
|
||||||
|
Elf64_Off sh_offset;
|
||||||
|
Elf64_Xword sh_size;
|
||||||
|
Elf64_Word sh_link;
|
||||||
|
Elf64_Word sh_info;
|
||||||
|
Elf64_Xword sh_addralign;
|
||||||
|
Elf64_Xword sh_entsize;
|
||||||
|
} Elf64_Shdr;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Elf32_Word p_type;
|
||||||
|
Elf32_Off p_offset;
|
||||||
|
Elf32_Addr p_vaddr;
|
||||||
|
Elf32_Addr p_paddr;
|
||||||
|
Elf32_Word p_filesz;
|
||||||
|
Elf32_Word p_memsz;
|
||||||
|
Elf32_Word p_flags;
|
||||||
|
Elf32_Word p_align;
|
||||||
|
} Elf32_Phdr;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Elf64_Word p_type;
|
||||||
|
Elf64_Word p_flags;
|
||||||
|
Elf64_Off p_offset;
|
||||||
|
Elf64_Addr p_vaddr;
|
||||||
|
Elf64_Addr p_paddr;
|
||||||
|
Elf64_Xword p_filesz;
|
||||||
|
Elf64_Xword p_memsz;
|
||||||
|
Elf64_Xword p_align;
|
||||||
|
} Elf64_Phdr;
|
||||||
|
|
||||||
|
typedef struct elf32_rel
|
||||||
|
{
|
||||||
|
Elf32_Addr r_offset;
|
||||||
|
Elf32_Word r_info;
|
||||||
|
} Elf32_Rel;
|
||||||
|
|
||||||
|
typedef struct elf64_rel
|
||||||
|
{
|
||||||
|
Elf64_Addr r_offset;
|
||||||
|
Elf64_Xword r_info;
|
||||||
|
} Elf64_Rel;
|
||||||
|
|
||||||
|
typedef struct elf32_sym
|
||||||
|
{
|
||||||
|
Elf32_Word st_name;
|
||||||
|
Elf32_Addr st_value;
|
||||||
|
Elf32_Word st_size;
|
||||||
|
unsigned char st_info;
|
||||||
|
unsigned char st_other;
|
||||||
|
Elf32_Half st_shndx;
|
||||||
|
} Elf32_Sym;
|
||||||
|
|
||||||
|
typedef struct elf64_sym
|
||||||
|
{
|
||||||
|
Elf64_Word st_name;
|
||||||
|
unsigned char st_info;
|
||||||
|
unsigned char st_other;
|
||||||
|
Elf64_Half st_shndx;
|
||||||
|
Elf64_Addr st_value;
|
||||||
|
Elf64_Xword st_size;
|
||||||
|
} Elf64_Sym;
|
||||||
|
|
||||||
|
struct Elf32_Dyn
|
||||||
|
{
|
||||||
|
Elf32_Sword d_tag;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
Elf32_Word d_val;
|
||||||
|
Elf32_Addr d_ptr;
|
||||||
|
} d_un;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elf64_Dyn
|
||||||
|
{
|
||||||
|
Elf64_Sxword d_tag;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
Elf64_Xword d_val;
|
||||||
|
Elf64_Addr d_ptr;
|
||||||
|
} d_un;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Elf64_Addr r_offset;
|
||||||
|
Elf64_Xword r_info;
|
||||||
|
Elf64_Sxword r_addend;
|
||||||
|
} Elf64_Rela;
|
||||||
|
|
||||||
#endif // !__FENNIX_KERNEL_ELF_H__
|
#endif // !__FENNIX_KERNEL_ELF_H__
|
||||||
|
23
include/emmintrin.h
Normal file
23
include/emmintrin.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_KERNEL_EMMINTRIN_H__
|
||||||
|
#define __FENNIX_KERNEL_EMMINTRIN_H__
|
||||||
|
|
||||||
|
/* stub header */
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_EMMINTRIN_H__
|
@ -23,6 +23,7 @@
|
|||||||
#include <filesystem.hpp>
|
#include <filesystem.hpp>
|
||||||
#include <task.hpp>
|
#include <task.hpp>
|
||||||
#include <std.hpp>
|
#include <std.hpp>
|
||||||
|
#include <vector>
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
|
|
||||||
namespace Execute
|
namespace Execute
|
||||||
@ -44,6 +45,7 @@ namespace Execute
|
|||||||
OK,
|
OK,
|
||||||
Unsupported,
|
Unsupported,
|
||||||
GenericError,
|
GenericError,
|
||||||
|
LoadingProcedureFailed,
|
||||||
InvalidFile,
|
InvalidFile,
|
||||||
InvalidFileFormat,
|
InvalidFileFormat,
|
||||||
InvalidFileHeader,
|
InvalidFileHeader,
|
||||||
@ -59,13 +61,13 @@ namespace Execute
|
|||||||
Tasking::TCB *Thread;
|
Tasking::TCB *Thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SharedLibraries
|
struct SharedLibrary
|
||||||
{
|
{
|
||||||
char Identifier[64];
|
char Identifier[64];
|
||||||
|
char Path[256];
|
||||||
uint64_t Timeout;
|
uint64_t Timeout;
|
||||||
int RefCount;
|
int RefCount;
|
||||||
|
|
||||||
uintptr_t Address;
|
|
||||||
uintptr_t MemoryImage;
|
uintptr_t MemoryImage;
|
||||||
size_t Length;
|
size_t Length;
|
||||||
};
|
};
|
||||||
@ -95,7 +97,38 @@ namespace Execute
|
|||||||
void *Virtual;
|
void *Virtual;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ELFObject
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ELFBaseLoad BaseLoadInfo{};
|
||||||
|
|
||||||
|
ELFBaseLoad LoadExec_x86_32(VirtualFileSystem::File &ElfFile,
|
||||||
|
Tasking::PCB *TargetProcess);
|
||||||
|
|
||||||
|
ELFBaseLoad LoadExec_x86_64(VirtualFileSystem::File &ElfFile,
|
||||||
|
Tasking::PCB *TargetProcess);
|
||||||
|
|
||||||
|
ELFBaseLoad LoadDyn_x86_32(VirtualFileSystem::File &ElfFile,
|
||||||
|
Tasking::PCB *TargetProcess,
|
||||||
|
bool IsLibrary);
|
||||||
|
|
||||||
|
ELFBaseLoad LoadDyn_x86_64(VirtualFileSystem::File &ElfFile,
|
||||||
|
Tasking::PCB *TargetProcess,
|
||||||
|
bool IsLibrary);
|
||||||
|
|
||||||
|
public:
|
||||||
|
ELFBaseLoad GetBaseLoadInfo() { return BaseLoadInfo; }
|
||||||
|
bool IsValid() { return BaseLoadInfo.Success; }
|
||||||
|
|
||||||
|
ELFObject(char *AbsolutePath,
|
||||||
|
Tasking::PCB *TargetProcess,
|
||||||
|
bool IsLibrary = false);
|
||||||
|
~ELFObject();
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Full binary size. */
|
||||||
BinaryType GetBinaryType(void *Image);
|
BinaryType GetBinaryType(void *Image);
|
||||||
|
|
||||||
BinaryType GetBinaryType(char *Path);
|
BinaryType GetBinaryType(char *Path);
|
||||||
|
|
||||||
SpawnData Spawn(char *Path, const char **argv, const char **envp);
|
SpawnData Spawn(char *Path, const char **argv, const char **envp);
|
||||||
@ -103,46 +136,55 @@ namespace Execute
|
|||||||
ELFBaseLoad ELFLoad(char *Path, const char **argv, const char **envp,
|
ELFBaseLoad ELFLoad(char *Path, const char **argv, const char **envp,
|
||||||
Tasking::TaskCompatibility Compatibility = Tasking::TaskCompatibility::Native);
|
Tasking::TaskCompatibility Compatibility = Tasking::TaskCompatibility::Native);
|
||||||
|
|
||||||
|
void ELFInterpreterIPCThread(Tasking::PCB *TargetProcess,
|
||||||
|
std::string *TargetPath,
|
||||||
|
void *MemoryImage,
|
||||||
|
std::vector<const char *> *NeededLibraries);
|
||||||
|
|
||||||
|
bool ELFIs64(void *Header);
|
||||||
Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header);
|
Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header);
|
||||||
Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index);
|
Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index);
|
||||||
char *GetELFStringTable(Elf64_Ehdr *Header);
|
char *GetELFStringTable(Elf64_Ehdr *Header);
|
||||||
char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset);
|
char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset);
|
||||||
Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name);
|
Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name);
|
||||||
|
Elf64_Sym ELFLookupSymbol(VirtualFileSystem::File &ElfFile, const char *Name);
|
||||||
uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index);
|
uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index);
|
||||||
Elf64_Dyn *ELFGetDynamicTag(void *ElfFile, enum DynamicArrayTags Tag);
|
|
||||||
|
std::vector<Elf64_Phdr> ELFGetSymbolType_x86_64(VirtualFileSystem::File &ElfFile, SegmentTypes Tag);
|
||||||
|
std::vector<Elf32_Phdr> ELFGetSymbolType_x86_32(VirtualFileSystem::File &ElfFile, SegmentTypes Tag);
|
||||||
|
|
||||||
|
std::vector<Elf64_Shdr> ELFGetSections_x86_64(VirtualFileSystem::File &ElfFile, const char *SectionName);
|
||||||
|
std::vector<Elf32_Shdr> ELFGetSections_x86_32(VirtualFileSystem::File &ElfFile, const char *SectionName);
|
||||||
|
|
||||||
|
std::vector<Elf64_Dyn> ELFGetDynamicTag_x86_64(VirtualFileSystem::File &ElfFile, DynamicArrayTags Tag);
|
||||||
|
std::vector<Elf32_Dyn> ELFGetDynamicTag_x86_32(VirtualFileSystem::File &ElfFile, DynamicArrayTags Tag);
|
||||||
|
|
||||||
|
void CopyLOADSegments(VirtualFileSystem::File &ElfFile, uintptr_t HdrsBase, uintptr_t PhysicalBase);
|
||||||
|
void GetBaseAndSize(VirtualFileSystem::File &ElfFile, uintptr_t &Base, size_t &Size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a ELF Memory Image
|
* @brief Create a ELF Memory Image
|
||||||
*
|
*
|
||||||
* @param mem The memory manager to use
|
* @param mem The memory manager to use
|
||||||
* @param pV Memory::Virtual object to use
|
* @param vmm Memory::Virtual object to use
|
||||||
* @param ElfFile ELF file loaded in memory (FULL FILE)
|
* @param ElfFile The ELF File
|
||||||
* @param Length Length of @p ElfFile
|
* @param Length Length of @p ElfFile
|
||||||
* @return The Memory Image (Physical and Virtual)
|
* @return The Memory Image (Physical and Virtual)
|
||||||
*/
|
*/
|
||||||
MmImage ELFCreateMemoryImage(Memory::MemMgr *mem, Memory::Virtual &pV, void *ElfFile, size_t Length);
|
MmImage ELFCreateMemoryImage(Memory::MemMgr *mem,
|
||||||
|
Memory::Virtual &vmm,
|
||||||
|
VirtualFileSystem::File &ElfFile,
|
||||||
|
size_t Length);
|
||||||
|
|
||||||
uintptr_t LoadELFInterpreter(Memory::MemMgr *mem, Memory::Virtual &pV, const char *Interpreter);
|
uintptr_t LoadELFInterpreter(Memory::MemMgr *mem,
|
||||||
|
Memory::Virtual &vmm,
|
||||||
|
const char *Interpreter);
|
||||||
|
|
||||||
ELFBaseLoad ELFLoadRel(void *ElfFile,
|
void LibraryManagerService();
|
||||||
VirtualFileSystem::File &ExFile,
|
|
||||||
Tasking::PCB *Process);
|
|
||||||
|
|
||||||
ELFBaseLoad ELFLoadExec(void *ElfFile,
|
|
||||||
VirtualFileSystem::File &ExFile,
|
|
||||||
Tasking::PCB *Process);
|
|
||||||
|
|
||||||
ELFBaseLoad ELFLoadDyn(void *ElfFile,
|
|
||||||
VirtualFileSystem::File &ExFile,
|
|
||||||
Tasking::PCB *Process);
|
|
||||||
|
|
||||||
void StartExecuteService();
|
|
||||||
bool AddLibrary(char *Identifier,
|
bool AddLibrary(char *Identifier,
|
||||||
void *ElfImage,
|
VirtualFileSystem::File &ExFile,
|
||||||
size_t Length,
|
const Memory::Virtual &vmm = Memory::Virtual());
|
||||||
const Memory::Virtual &pV = Memory::Virtual());
|
SharedLibrary GetLibrary(char *Identifier);
|
||||||
void SearchLibrary(char *Identifier);
|
|
||||||
SharedLibraries GetLibrary(char *Identifier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !__FENNIX_KERNEL_FILE_EXECUTE_H__
|
#endif // !__FENNIX_KERNEL_FILE_EXECUTE_H__
|
||||||
|
@ -34,8 +34,8 @@ namespace VirtualFileSystem
|
|||||||
|
|
||||||
typedef size_t (*OperationMount)(const char *, unsigned long, const void *);
|
typedef size_t (*OperationMount)(const char *, unsigned long, const void *);
|
||||||
typedef size_t (*OperationUmount)(int);
|
typedef size_t (*OperationUmount)(int);
|
||||||
typedef size_t (*OperationRead)(Node *node, size_t Offset, size_t Size, uint8_t *Buffer);
|
typedef size_t (*OperationRead)(Node *node, size_t Size, uint8_t *Buffer);
|
||||||
typedef size_t (*OperationWrite)(Node *node, size_t Offset, size_t Size, uint8_t *Buffer);
|
typedef size_t (*OperationWrite)(Node *node, size_t Size, uint8_t *Buffer);
|
||||||
typedef void (*OperationOpen)(Node *node, uint8_t Mode, uint8_t Flags);
|
typedef void (*OperationOpen)(Node *node, uint8_t Mode, uint8_t Flags);
|
||||||
typedef void (*OperationClose)(Node *node);
|
typedef void (*OperationClose)(Node *node);
|
||||||
typedef size_t (*OperationSync)(void);
|
typedef size_t (*OperationSync)(void);
|
||||||
@ -46,14 +46,14 @@ namespace VirtualFileSystem
|
|||||||
#define MountFSFunction(name) size_t name(const char *unknown0, unsigned long unknown1, const uint8_t *unknown2)
|
#define MountFSFunction(name) size_t name(const char *unknown0, unsigned long unknown1, const uint8_t *unknown2)
|
||||||
#define UMountFSFunction(name) size_t name(int unknown0)
|
#define UMountFSFunction(name) size_t name(int unknown0)
|
||||||
|
|
||||||
#define ReadFSFunction(name) size_t name(VirtualFileSystem::Node *node, size_t Offset, size_t Size, uint8_t *Buffer)
|
#define ReadFSFunction(name) size_t name(VirtualFileSystem::Node *node, size_t Size, uint8_t *Buffer)
|
||||||
#define WriteFSFunction(name) size_t name(VirtualFileSystem::Node *node, size_t Offset, size_t Size, uint8_t *Buffer)
|
#define WriteFSFunction(name) size_t name(VirtualFileSystem::Node *node, size_t Size, uint8_t *Buffer)
|
||||||
#define OpenFSFunction(name) void name(VirtualFileSystem::Node *node, uint8_t Mode, uint8_t Flags)
|
#define OpenFSFunction(name) void name(VirtualFileSystem::Node *node, uint8_t Mode, uint8_t Flags)
|
||||||
#define CloseFSFunction(name) void name(VirtualFileSystem::Node *node)
|
#define CloseFSFunction(name) void name(VirtualFileSystem::Node *node)
|
||||||
#define SyncFSFunction(name) size_t name(void)
|
#define SyncFSFunction(name) size_t name(void)
|
||||||
#define CreateFSFunction(name) void name(VirtualFileSystem::Node *node, char *Name, uint16_t NameLength)
|
#define CreateFSFunction(name) void name(VirtualFileSystem::Node *node, char *Name, uint16_t NameLength)
|
||||||
#define MkdirFSFunction(name) void name(VirtualFileSystem::Node *node, char *Name, uint16_t NameLength)
|
#define MkdirFSFunction(name) void name(VirtualFileSystem::Node *node, char *Name, uint16_t NameLength)
|
||||||
#define SeekFSFunction(name) size_t name(VirtualFileSystem::Node *node, size_t Offset, uint8_t Whence)
|
#define SeekFSFunction(name) off_t name(VirtualFileSystem::Node *node, off_t Offset, uint8_t Whence)
|
||||||
|
|
||||||
enum FileStatus
|
enum FileStatus
|
||||||
{
|
{
|
||||||
@ -120,7 +120,7 @@ namespace VirtualFileSystem
|
|||||||
uint64_t UserIdentifier = 0, GroupIdentifier = 0;
|
uint64_t UserIdentifier = 0, GroupIdentifier = 0;
|
||||||
uintptr_t Address = 0;
|
uintptr_t Address = 0;
|
||||||
size_t Length = 0;
|
size_t Length = 0;
|
||||||
size_t Offset = 0;
|
off_t Offset = 0;
|
||||||
Node *Parent = nullptr;
|
Node *Parent = nullptr;
|
||||||
FileSystemOperations *Operator = nullptr;
|
FileSystemOperations *Operator = nullptr;
|
||||||
/* For root node:
|
/* For root node:
|
||||||
@ -135,9 +135,37 @@ namespace VirtualFileSystem
|
|||||||
{
|
{
|
||||||
char Name[FILENAME_LENGTH];
|
char Name[FILENAME_LENGTH];
|
||||||
FileStatus Status;
|
FileStatus Status;
|
||||||
Node *node;
|
bool IsOK()
|
||||||
|
{
|
||||||
|
return Status == FileStatus::OK;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsOK() { return Status == FileStatus::OK; }
|
size_t GetLength()
|
||||||
|
{
|
||||||
|
return node->Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Node *> GetChildren()
|
||||||
|
{
|
||||||
|
return node->Children;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeFlags GetFlags()
|
||||||
|
{
|
||||||
|
return node->Flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Special cases only. */
|
||||||
|
Node *GetNode()
|
||||||
|
{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Node *node;
|
||||||
|
off_t ContextOffset;
|
||||||
|
|
||||||
|
friend class Virtual;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Manage / etc.. */
|
/* Manage / etc.. */
|
||||||
@ -178,8 +206,9 @@ namespace VirtualFileSystem
|
|||||||
File Mount(const char *Path, FileSystemOperations *Operator);
|
File Mount(const char *Path, FileSystemOperations *Operator);
|
||||||
FileStatus Unmount(File &File);
|
FileStatus Unmount(File &File);
|
||||||
|
|
||||||
size_t Read(File &File, size_t Offset, uint8_t *Buffer, size_t Size);
|
size_t Read(File &File, uint8_t *Buffer, size_t Size);
|
||||||
size_t Write(File &File, size_t Offset, uint8_t *Buffer, size_t Size);
|
size_t Write(File &File, uint8_t *Buffer, size_t Size);
|
||||||
|
off_t Seek(File &File, off_t Offset, uint8_t Whence);
|
||||||
|
|
||||||
File Open(const char *Path, Node *Parent = nullptr);
|
File Open(const char *Path, Node *Parent = nullptr);
|
||||||
FileStatus Close(File &File);
|
FileStatus Close(File &File);
|
||||||
|
@ -192,9 +192,17 @@ namespace Memory
|
|||||||
uintptr_t Dirty : 1; // 6
|
uintptr_t Dirty : 1; // 6
|
||||||
uintptr_t PageAttributeTable : 1; // 7
|
uintptr_t PageAttributeTable : 1; // 7
|
||||||
uintptr_t Global : 1; // 8
|
uintptr_t Global : 1; // 8
|
||||||
uintptr_t Available0 : 3; // 9-11
|
uintptr_t Available0 : 1; // 9
|
||||||
|
uintptr_t Available1 : 1; // 10
|
||||||
|
uintptr_t Available2 : 1; // 11
|
||||||
uintptr_t Address : 40; // 12-51
|
uintptr_t Address : 40; // 12-51
|
||||||
uintptr_t Available1 : 7; // 52-58
|
uintptr_t Available3 : 1; // 52
|
||||||
|
uintptr_t Available4 : 1; // 53
|
||||||
|
uintptr_t Available5 : 1; // 54
|
||||||
|
uintptr_t Available6 : 1; // 55
|
||||||
|
uintptr_t Available7 : 1; // 56
|
||||||
|
uintptr_t Available8 : 1; // 57
|
||||||
|
uintptr_t Available9 : 1; // 58
|
||||||
uintptr_t ProtectionKey : 4; // 59-62
|
uintptr_t ProtectionKey : 4; // 59-62
|
||||||
uintptr_t ExecuteDisable : 1; // 63
|
uintptr_t ExecuteDisable : 1; // 63
|
||||||
#elif defined(a32)
|
#elif defined(a32)
|
||||||
@ -207,7 +215,9 @@ namespace Memory
|
|||||||
uintptr_t Dirty : 1; // 6
|
uintptr_t Dirty : 1; // 6
|
||||||
uintptr_t PageAttributeTable : 1; // 7
|
uintptr_t PageAttributeTable : 1; // 7
|
||||||
uintptr_t Global : 1; // 8
|
uintptr_t Global : 1; // 8
|
||||||
uintptr_t Available0 : 3; // 9-11
|
uintptr_t Available0 : 1; // 9
|
||||||
|
uintptr_t Available1 : 1; // 10
|
||||||
|
uintptr_t Available2 : 1; // 11
|
||||||
uintptr_t Address : 20; // 12-31
|
uintptr_t Address : 20; // 12-31
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
#endif
|
#endif
|
||||||
@ -285,11 +295,19 @@ namespace Memory
|
|||||||
uintptr_t Dirty : 1; // 6
|
uintptr_t Dirty : 1; // 6
|
||||||
uintptr_t PageSize : 1; // 7
|
uintptr_t PageSize : 1; // 7
|
||||||
uintptr_t Global : 1; // 8
|
uintptr_t Global : 1; // 8
|
||||||
uintptr_t Available0 : 3; // 9-11
|
uintptr_t Available0 : 1; // 9
|
||||||
|
uintptr_t Available1 : 1; // 10
|
||||||
|
uintptr_t Available2 : 1; // 11
|
||||||
uintptr_t PageAttributeTable : 1; // 12
|
uintptr_t PageAttributeTable : 1; // 12
|
||||||
uintptr_t Reserved0 : 8; // 13-20
|
uintptr_t Reserved0 : 8; // 13-20
|
||||||
uintptr_t Address : 31; // 21-51
|
uintptr_t Address : 31; // 21-51
|
||||||
uintptr_t Available1 : 7; // 52-58
|
uintptr_t Available3 : 1; // 52
|
||||||
|
uintptr_t Available4 : 1; // 53
|
||||||
|
uintptr_t Available5 : 1; // 54
|
||||||
|
uintptr_t Available6 : 1; // 55
|
||||||
|
uintptr_t Available7 : 1; // 56
|
||||||
|
uintptr_t Available8 : 1; // 57
|
||||||
|
uintptr_t Available9 : 1; // 58
|
||||||
uintptr_t ProtectionKey : 4; // 59-62
|
uintptr_t ProtectionKey : 4; // 59-62
|
||||||
uintptr_t ExecuteDisable : 1; // 63
|
uintptr_t ExecuteDisable : 1; // 63
|
||||||
} TwoMB;
|
} TwoMB;
|
||||||
@ -319,7 +337,9 @@ namespace Memory
|
|||||||
uintptr_t Dirty : 1; // 6
|
uintptr_t Dirty : 1; // 6
|
||||||
uintptr_t PageSize : 1; // 7
|
uintptr_t PageSize : 1; // 7
|
||||||
uintptr_t Global : 1; // 8
|
uintptr_t Global : 1; // 8
|
||||||
uintptr_t Available0 : 3; // 9-11
|
uintptr_t Available0 : 1; // 9
|
||||||
|
uintptr_t Available1 : 1; // 10
|
||||||
|
uintptr_t Available2 : 1; // 11
|
||||||
uintptr_t PageAttributeTable : 1; // 12
|
uintptr_t PageAttributeTable : 1; // 12
|
||||||
uintptr_t Address0 : 8; // 13-20
|
uintptr_t Address0 : 8; // 13-20
|
||||||
uintptr_t Reserved0 : 1; // 21
|
uintptr_t Reserved0 : 1; // 21
|
||||||
@ -395,11 +415,19 @@ namespace Memory
|
|||||||
uintptr_t Dirty : 1; // 6
|
uintptr_t Dirty : 1; // 6
|
||||||
uintptr_t PageSize : 1; // 7
|
uintptr_t PageSize : 1; // 7
|
||||||
uintptr_t Global : 1; // 8
|
uintptr_t Global : 1; // 8
|
||||||
uintptr_t Available0 : 3; // 9-11
|
uintptr_t Available0 : 1; // 9
|
||||||
|
uintptr_t Available1 : 1; // 10
|
||||||
|
uintptr_t Available2 : 1; // 11
|
||||||
uintptr_t PageAttributeTable : 1; // 12
|
uintptr_t PageAttributeTable : 1; // 12
|
||||||
uintptr_t Reserved0 : 17; // 13-29
|
uintptr_t Reserved0 : 17; // 13-29
|
||||||
uintptr_t Address : 22; // 30-51
|
uintptr_t Address : 22; // 30-51
|
||||||
uintptr_t Available1 : 7; // 52-58
|
uintptr_t Available3 : 1; // 52
|
||||||
|
uintptr_t Available4 : 1; // 53
|
||||||
|
uintptr_t Available5 : 1; // 54
|
||||||
|
uintptr_t Available6 : 1; // 55
|
||||||
|
uintptr_t Available7 : 1; // 56
|
||||||
|
uintptr_t Available8 : 1; // 57
|
||||||
|
uintptr_t Available9 : 1; // 58
|
||||||
uintptr_t ProtectionKey : 4; // 59-62
|
uintptr_t ProtectionKey : 4; // 59-62
|
||||||
uintptr_t ExecuteDisable : 1; // 63
|
uintptr_t ExecuteDisable : 1; // 63
|
||||||
} OneGB;
|
} OneGB;
|
||||||
@ -754,6 +782,21 @@ namespace Memory
|
|||||||
*/
|
*/
|
||||||
void *GetPhysical(void *VirtualAddress);
|
void *GetPhysical(void *VirtualAddress);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get map type of the page.
|
||||||
|
* @param VirtualAddress Virtual address of the page.
|
||||||
|
* @return Map type of the page.
|
||||||
|
*/
|
||||||
|
MapType GetMapType(void *VirtualAddress);
|
||||||
|
|
||||||
|
#ifdef a64
|
||||||
|
PageMapLevel5 *GetPML5(void *VirtualAddress, MapType Type = MapType::FourKB);
|
||||||
|
PageMapLevel4 *GetPML4(void *VirtualAddress, MapType Type = MapType::FourKB);
|
||||||
|
PageDirectoryPointerTableEntry *GetPDPTE(void *VirtualAddress, MapType Type = MapType::FourKB);
|
||||||
|
#endif /* a64 */
|
||||||
|
PageDirectoryEntry *GetPDE(void *VirtualAddress, MapType Type = MapType::FourKB);
|
||||||
|
PageTableEntry *GetPTE(void *VirtualAddress, MapType Type = MapType::FourKB);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Map page.
|
* @brief Map page.
|
||||||
*
|
*
|
||||||
|
104
include/msexec.h
104
include/msexec.h
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
// some of the code is from: https://github.com/dotnet/llilc/blob/main/include/clr/ntimage.h
|
/* Some of the code is from: https://github.com/dotnet/llilc/blob/main/include/clr/ntimage.h */
|
||||||
|
|
||||||
#define near /* __near */
|
#define near /* __near */
|
||||||
#define far /* __far */
|
#define far /* __far */
|
||||||
@ -110,61 +110,61 @@ typedef double DOUBLE;
|
|||||||
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13
|
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13
|
||||||
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14
|
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14
|
||||||
|
|
||||||
typedef struct _IMAGE_DOS_HEADER // DOS .EXE header
|
typedef struct _IMAGE_DOS_HEADER /* DOS .EXE header */
|
||||||
{
|
{
|
||||||
USHORT e_magic; // Magic number
|
USHORT e_magic; /* Magic number */
|
||||||
USHORT e_cblp; // Bytes on last page of file
|
USHORT e_cblp; /* Bytes on last page of file */
|
||||||
USHORT e_cp; // Pages in file
|
USHORT e_cp; /* Pages in file */
|
||||||
USHORT e_crlc; // Relocations
|
USHORT e_crlc; /* Relocations */
|
||||||
USHORT e_cparhdr; // Size of header in paragraphs
|
USHORT e_cparhdr; /* Size of header in paragraphs */
|
||||||
USHORT e_minalloc; // Minimum extra paragraphs needed
|
USHORT e_minalloc; /* Minimum extra paragraphs needed */
|
||||||
USHORT e_maxalloc; // Maximum extra paragraphs needed
|
USHORT e_maxalloc; /* Maximum extra paragraphs needed */
|
||||||
USHORT e_ss; // Initial (relative) SS value
|
USHORT e_ss; /* Initial (relative) SS value */
|
||||||
USHORT e_sp; // Initial SP value
|
USHORT e_sp; /* Initial SP value */
|
||||||
USHORT e_csum; // Checksum
|
USHORT e_csum; /* Checksum */
|
||||||
USHORT e_ip; // Initial IP value
|
USHORT e_ip; /* Initial IP value */
|
||||||
USHORT e_cs; // Initial (relative) CS value
|
USHORT e_cs; /* Initial (relative) CS value */
|
||||||
USHORT e_lfarlc; // File address of relocation table
|
USHORT e_lfarlc; /* File address of relocation table */
|
||||||
USHORT e_ovno; // Overlay number
|
USHORT e_ovno; /* Overlay number */
|
||||||
USHORT e_res[4]; // Reserved words
|
USHORT e_res[4]; /* Reserved words */
|
||||||
USHORT e_oemid; // OEM identifier (for e_oeminfo)
|
USHORT e_oemid; /* OEM identifier (for e_oeminfo) */
|
||||||
USHORT e_oeminfo; // OEM information; e_oemid specific
|
USHORT e_oeminfo; /* OEM information; e_oemid specific */
|
||||||
USHORT e_res2[10]; // Reserved words
|
USHORT e_res2[10]; /* Reserved words */
|
||||||
USHORT e_lfanew; // File address of new exe header
|
USHORT e_lfanew; /* File address of new exe header */
|
||||||
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
|
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
|
||||||
|
|
||||||
typedef struct _IMAGE_OS2_HEADER // OS/2 .EXE header
|
typedef struct _IMAGE_OS2_HEADER /* OS/2 .EXE header */
|
||||||
{
|
{
|
||||||
USHORT ne_magic; // Magic number
|
USHORT ne_magic; /* Magic number */
|
||||||
UCHAR ne_ver; // Version number
|
UCHAR ne_ver; /* Version number */
|
||||||
UCHAR ne_rev; // Revision number
|
UCHAR ne_rev; /* Revision number */
|
||||||
USHORT ne_enttab; // Offset of Entry Table
|
USHORT ne_enttab; /* Offset of Entry Table */
|
||||||
USHORT ne_cbenttab; // Number of bytes in Entry Table
|
USHORT ne_cbenttab; /* Number of bytes in Entry Table */
|
||||||
UINT ne_crc; // Checksum of whole file
|
UINT ne_crc; /* Checksum of whole file */
|
||||||
USHORT ne_flags; // Flag word
|
USHORT ne_flags; /* Flag word */
|
||||||
USHORT ne_autodata; // Automatic data segment number
|
USHORT ne_autodata; /* Automatic data segment number */
|
||||||
USHORT ne_heap; // Initial heap allocation
|
USHORT ne_heap; /* Initial heap allocation */
|
||||||
USHORT ne_stack; // Initial stack allocation
|
USHORT ne_stack; /* Initial stack allocation */
|
||||||
UINT ne_csip; // Initial CS:IP setting
|
UINT ne_csip; /* Initial CS:IP setting */
|
||||||
UINT ne_sssp; // Initial SS:SP setting
|
UINT ne_sssp; /* Initial SS:SP setting */
|
||||||
USHORT ne_cseg; // Count of file segments
|
USHORT ne_cseg; /* Count of file segments */
|
||||||
USHORT ne_cmod; // Entries in Module Reference Table
|
USHORT ne_cmod; /* Entries in Module Reference Table */
|
||||||
USHORT ne_cbnrestab; // Size of non-resident name table
|
USHORT ne_cbnrestab; /* Size of non-resident name table */
|
||||||
USHORT ne_segtab; // Offset of Segment Table
|
USHORT ne_segtab; /* Offset of Segment Table */
|
||||||
USHORT ne_rsrctab; // Offset of Resource Table
|
USHORT ne_rsrctab; /* Offset of Resource Table */
|
||||||
USHORT ne_restab; // Offset of resident name table
|
USHORT ne_restab; /* Offset of resident name table */
|
||||||
USHORT ne_modtab; // Offset of Module Reference Table
|
USHORT ne_modtab; /* Offset of Module Reference Table */
|
||||||
USHORT ne_imptab; // Offset of Imported Names Table
|
USHORT ne_imptab; /* Offset of Imported Names Table */
|
||||||
UINT ne_nrestab; // Offset of Non-resident Names Table
|
UINT ne_nrestab; /* Offset of Non-resident Names Table */
|
||||||
USHORT ne_cmovent; // Count of movable entries
|
USHORT ne_cmovent; /* Count of movable entries */
|
||||||
USHORT ne_align; // Segment alignment shift count
|
USHORT ne_align; /* Segment alignment shift count */
|
||||||
USHORT ne_cres; // Count of resource segments
|
USHORT ne_cres; /* Count of resource segments */
|
||||||
UCHAR ne_exetyp; // Target Operating system
|
UCHAR ne_exetyp; /* Target Operating system */
|
||||||
UCHAR ne_flagsothers; // Other .EXE flags
|
UCHAR ne_flagsothers; /* Other .EXE flags */
|
||||||
USHORT ne_pretthunks; // offset to return thunks
|
USHORT ne_pretthunks; /* offset to return thunks */
|
||||||
USHORT ne_psegrefbytes; // offset to segment ref. bytes
|
USHORT ne_psegrefbytes; /* offset to segment ref. bytes */
|
||||||
USHORT ne_swaparea; // Minimum code swap area size
|
USHORT ne_swaparea; /* Minimum code swap area size */
|
||||||
USHORT ne_expver; // Expected Windows version number
|
USHORT ne_expver; /* Expected Windows version number */
|
||||||
} IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER;
|
} IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER;
|
||||||
|
|
||||||
typedef struct _IMAGE_SECTION_HEADER
|
typedef struct _IMAGE_SECTION_HEADER
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#define __FENNIX_KERNEL_SMP_H__
|
#define __FENNIX_KERNEL_SMP_H__
|
||||||
|
|
||||||
#include <task.hpp>
|
#include <task.hpp>
|
||||||
|
#include <cxxabi.h>
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
@ -61,6 +62,9 @@ struct CPUData
|
|||||||
/** @brief Current running thread */
|
/** @brief Current running thread */
|
||||||
std::atomic<Tasking::TCB *> CurrentThread;
|
std::atomic<Tasking::TCB *> CurrentThread;
|
||||||
|
|
||||||
|
/** @brief Unwind data */
|
||||||
|
__cxa_eh_globals EHGlobals;
|
||||||
|
|
||||||
/** @brief Architecture-specific data. */
|
/** @brief Architecture-specific data. */
|
||||||
CPUArchData Data;
|
CPUArchData Data;
|
||||||
|
|
||||||
|
@ -32,10 +32,13 @@
|
|||||||
|
|
||||||
namespace Tasking
|
namespace Tasking
|
||||||
{
|
{
|
||||||
typedef unsigned long IP;
|
/** @brief Instruction Pointer */
|
||||||
typedef __UINTPTR_TYPE__ IPOffset;
|
typedef __UINTPTR_TYPE__ IP;
|
||||||
typedef unsigned long UPID;
|
/** @brief Process ID */
|
||||||
typedef unsigned long UTID;
|
typedef int PID;
|
||||||
|
/** @brief Thread ID */
|
||||||
|
typedef int TID;
|
||||||
|
/* @brief Token */
|
||||||
typedef __UINTPTR_TYPE__ Token;
|
typedef __UINTPTR_TYPE__ Token;
|
||||||
|
|
||||||
enum TaskArchitecture
|
enum TaskArchitecture
|
||||||
@ -84,6 +87,16 @@ namespace Tasking
|
|||||||
Critical = 10
|
Critical = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum KillErrorCodes : int
|
||||||
|
{
|
||||||
|
KILL_SCHEDULER_DESTRUCTION = -0xFFFF,
|
||||||
|
KILL_CXXABI_EXCEPTION = -0xECE97,
|
||||||
|
KILL_SYSCALL = -0xCA11,
|
||||||
|
KILL_OOM = -0x1008,
|
||||||
|
KILL_ERROR = -0x1,
|
||||||
|
KILL_SUCCESS = 0,
|
||||||
|
};
|
||||||
|
|
||||||
struct TaskSecurity
|
struct TaskSecurity
|
||||||
{
|
{
|
||||||
TaskTrustLevel TrustLevel;
|
TaskTrustLevel TrustLevel;
|
||||||
@ -109,11 +122,10 @@ namespace Tasking
|
|||||||
|
|
||||||
struct TCB
|
struct TCB
|
||||||
{
|
{
|
||||||
UTID ID;
|
TID ID;
|
||||||
char Name[256];
|
char Name[256];
|
||||||
struct PCB *Parent;
|
struct PCB *Parent;
|
||||||
IP EntryPoint;
|
IP EntryPoint;
|
||||||
IPOffset Offset;
|
|
||||||
int ExitCode;
|
int ExitCode;
|
||||||
Memory::StackGuard *Stack;
|
Memory::StackGuard *Stack;
|
||||||
Memory::MemMgr *Memory;
|
Memory::MemMgr *Memory;
|
||||||
@ -174,11 +186,34 @@ namespace Tasking
|
|||||||
trace("Setting kernel debug mode of thread %s to %s", Name, Enable ? "true" : "false");
|
trace("Setting kernel debug mode of thread %s to %s", Name, Enable ? "true" : "false");
|
||||||
Security.IsKernelDebugEnabled = Enable;
|
Security.IsKernelDebugEnabled = Enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SYSV_ABI_Call(uintptr_t Arg1 = 0,
|
||||||
|
uintptr_t Arg2 = 0,
|
||||||
|
uintptr_t Arg3 = 0,
|
||||||
|
uintptr_t Arg4 = 0,
|
||||||
|
uintptr_t Arg5 = 0,
|
||||||
|
uintptr_t Arg6 = 0,
|
||||||
|
void *Function = nullptr)
|
||||||
|
{
|
||||||
|
CriticalSection cs;
|
||||||
|
#if defined(a64)
|
||||||
|
this->Registers.rdi = Arg1;
|
||||||
|
this->Registers.rsi = Arg2;
|
||||||
|
this->Registers.rdx = Arg3;
|
||||||
|
this->Registers.rcx = Arg4;
|
||||||
|
this->Registers.r8 = Arg5;
|
||||||
|
this->Registers.r9 = Arg6;
|
||||||
|
if (Function != nullptr)
|
||||||
|
this->Registers.rip = (uint64_t)Function;
|
||||||
|
#else
|
||||||
|
#warning "SYSV ABI not implemented for this architecture"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PCB
|
struct PCB
|
||||||
{
|
{
|
||||||
UPID ID;
|
PID ID;
|
||||||
char Name[256];
|
char Name[256];
|
||||||
PCB *Parent;
|
PCB *Parent;
|
||||||
int ExitCode;
|
int ExitCode;
|
||||||
@ -243,8 +278,8 @@ namespace Tasking
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Security SecurityManager;
|
Security SecurityManager;
|
||||||
UPID NextPID = 0;
|
PID NextPID = 0;
|
||||||
UTID NextTID = 0;
|
TID NextTID = 0;
|
||||||
|
|
||||||
std::vector<PCB *> ProcessList;
|
std::vector<PCB *> ProcessList;
|
||||||
PCB *IdleProcess = nullptr;
|
PCB *IdleProcess = nullptr;
|
||||||
@ -289,6 +324,7 @@ namespace Tasking
|
|||||||
Security *GetSecurityManager() { return &SecurityManager; }
|
Security *GetSecurityManager() { return &SecurityManager; }
|
||||||
void CleanupProcessesThread();
|
void CleanupProcessesThread();
|
||||||
void Panic() { StopScheduler = true; }
|
void Panic() { StopScheduler = true; }
|
||||||
|
bool IsPanic() { return StopScheduler; }
|
||||||
__always_inline inline void Schedule()
|
__always_inline inline void Schedule()
|
||||||
{
|
{
|
||||||
#if defined(a86)
|
#if defined(a86)
|
||||||
@ -301,16 +337,16 @@ namespace Tasking
|
|||||||
void RevertProcessCreation(PCB *Process);
|
void RevertProcessCreation(PCB *Process);
|
||||||
void RevertThreadCreation(TCB *Thread);
|
void RevertThreadCreation(TCB *Thread);
|
||||||
|
|
||||||
void KillThread(TCB *tcb, int Code)
|
void KillThread(TCB *tcb, enum KillErrorCodes Code)
|
||||||
{
|
{
|
||||||
tcb->Status = TaskStatus::Terminated;
|
tcb->Status = TaskStatus::Terminated;
|
||||||
tcb->ExitCode = Code;
|
tcb->ExitCode = (int)Code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KillProcess(PCB *pcb, int Code)
|
void KillProcess(PCB *pcb, enum KillErrorCodes Code)
|
||||||
{
|
{
|
||||||
pcb->Status = TaskStatus::Terminated;
|
pcb->Status = TaskStatus::Terminated;
|
||||||
pcb->ExitCode = Code;
|
pcb->ExitCode = (int)Code;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -325,9 +361,9 @@ namespace Tasking
|
|||||||
*/
|
*/
|
||||||
TCB *GetCurrentThread();
|
TCB *GetCurrentThread();
|
||||||
|
|
||||||
PCB *GetProcessByID(UPID ID);
|
PCB *GetProcessByID(PID ID);
|
||||||
|
|
||||||
TCB *GetThreadByID(UTID ID);
|
TCB *GetThreadByID(TID ID);
|
||||||
|
|
||||||
/** @brief Wait for process to terminate */
|
/** @brief Wait for process to terminate */
|
||||||
void WaitForProcess(PCB *pcb);
|
void WaitForProcess(PCB *pcb);
|
||||||
@ -356,7 +392,6 @@ namespace Tasking
|
|||||||
const char **argv = nullptr,
|
const char **argv = nullptr,
|
||||||
const char **envp = nullptr,
|
const char **envp = nullptr,
|
||||||
const std::vector<AuxiliaryVector> &auxv = std::vector<AuxiliaryVector>(),
|
const std::vector<AuxiliaryVector> &auxv = std::vector<AuxiliaryVector>(),
|
||||||
IPOffset Offset = 0,
|
|
||||||
TaskArchitecture Architecture = TaskArchitecture::x64,
|
TaskArchitecture Architecture = TaskArchitecture::x64,
|
||||||
TaskCompatibility Compatibility = TaskCompatibility::Native,
|
TaskCompatibility Compatibility = TaskCompatibility::Native,
|
||||||
bool ThreadNotReady = false);
|
bool ThreadNotReady = false);
|
||||||
|
@ -78,8 +78,19 @@ typedef __builtin_va_list va_list;
|
|||||||
|
|
||||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||||
|
|
||||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
#define MAX(a, b) \
|
||||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
({ \
|
||||||
|
__typeof__(a) _a = (a); \
|
||||||
|
__typeof__(b) _b = (b); \
|
||||||
|
_a > _b ? _a : _b; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define MIN(a, b) \
|
||||||
|
({ \
|
||||||
|
__typeof__(a) _a = (a); \
|
||||||
|
__typeof__(b) _b = (b); \
|
||||||
|
_a < _b ? _a : _b; \
|
||||||
|
})
|
||||||
|
|
||||||
#define ROUND_UP(x, y) (((x) + (y)-1) & ~((y)-1))
|
#define ROUND_UP(x, y) (((x) + (y)-1) & ~((y)-1))
|
||||||
#define ROUND_DOWN(x, y) ((x) & ~((y)-1))
|
#define ROUND_DOWN(x, y) ((x) & ~((y)-1))
|
||||||
@ -183,6 +194,9 @@ typedef __SIG_ATOMIC_TYPE__ sig_atomic_t;
|
|||||||
// TODO: ssize_t
|
// TODO: ssize_t
|
||||||
typedef intptr_t ssize_t;
|
typedef intptr_t ssize_t;
|
||||||
|
|
||||||
|
typedef long off_t;
|
||||||
|
typedef long long off64_t;
|
||||||
|
|
||||||
#define INT8_MAX __INT8_MAX__
|
#define INT8_MAX __INT8_MAX__
|
||||||
#define INT8_MIN (-INT8_MAX - 1)
|
#define INT8_MIN (-INT8_MAX - 1)
|
||||||
#define UINT8_MAX __UINT8_MAX__
|
#define UINT8_MAX __UINT8_MAX__
|
||||||
@ -359,6 +373,9 @@ typedef uint48_t uint_fast48_t;
|
|||||||
#define likely(x) __builtin_expect(!!(x), 1)
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
|
|
||||||
|
#define PUBLIC __visibility("default")
|
||||||
|
#define PRIVATE __visibility("hidden")
|
||||||
|
|
||||||
#define SafeFunction __no_stack_protector __no_sanitize_address __no_sanitize_undefined __no_address_safety_analysis __no_sanitize_thread
|
#define SafeFunction __no_stack_protector __no_sanitize_address __no_sanitize_undefined __no_address_safety_analysis __no_sanitize_thread
|
||||||
|
|
||||||
#define NIF __no_instrument_function
|
#define NIF __no_instrument_function
|
||||||
|
69
include_std/cxxabi.h
Normal file
69
include_std/cxxabi.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_KERNEL_CXXABI_H__
|
||||||
|
#define __FENNIX_KERNEL_CXXABI_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <unwind.h>
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
namespace __cxxabiv1
|
||||||
|
{
|
||||||
|
#define ATEXIT_MAX_FUNCS 128
|
||||||
|
|
||||||
|
typedef unsigned uarch_t;
|
||||||
|
|
||||||
|
struct atexit_func_entry_t
|
||||||
|
{
|
||||||
|
void (*destructor_func)(void *);
|
||||||
|
void *obj_ptr;
|
||||||
|
void *dso_handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __cxa_exception
|
||||||
|
{
|
||||||
|
std::type_info *exceptionType;
|
||||||
|
void (*exceptionDestructor)(void *);
|
||||||
|
std::terminate_handler unexpectedHandler;
|
||||||
|
std::terminate_handler terminateHandler;
|
||||||
|
__cxa_exception *nextException;
|
||||||
|
int handlerCount;
|
||||||
|
#ifdef __ARM_EABI_UNWINDER__
|
||||||
|
__cxa_exception *nextPropagatingException;
|
||||||
|
int propagationCount;
|
||||||
|
#else
|
||||||
|
int handlerSwitchValue;
|
||||||
|
const unsigned char *actionRecord;
|
||||||
|
const unsigned char *languageSpecificData;
|
||||||
|
_Unwind_Ptr catchTemp;
|
||||||
|
void *adjustedPtr;
|
||||||
|
#endif
|
||||||
|
_Unwind_Exception unwindHeader;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct __cxa_eh_globals
|
||||||
|
{
|
||||||
|
__cxxabiv1::__cxa_exception *caughtExceptions;
|
||||||
|
unsigned int uncaughtExceptions;
|
||||||
|
#ifdef __ARM_EABI_UNWINDER__
|
||||||
|
__cxxabiv1::__cxa_exception *propagatingExceptions;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_CXXABI_H__
|
41
include_std/exception
Normal file
41
include_std/exception
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_KERNEL_EXCEPTION_H__
|
||||||
|
#define __FENNIX_KERNEL_EXCEPTION_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
class exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
exception() noexcept {}
|
||||||
|
virtual ~exception() noexcept;
|
||||||
|
exception(const exception &) = default;
|
||||||
|
exception &operator=(const exception &) = default;
|
||||||
|
exception(exception &&) = default;
|
||||||
|
exception &operator=(exception &&) = default;
|
||||||
|
|
||||||
|
virtual const char *what() const noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*terminate_handler)();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_EXCEPTION_H__
|
@ -123,7 +123,7 @@ namespace std
|
|||||||
|
|
||||||
NIF T &null_elem()
|
NIF T &null_elem()
|
||||||
{
|
{
|
||||||
static T null_elem;
|
static T null_elem{};
|
||||||
return null_elem;
|
return null_elem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
25
include_std/stdarg.h
Normal file
25
include_std/stdarg.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_KERNEL_STDARG_H__
|
||||||
|
#define __FENNIX_KERNEL_STDARG_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_STDARG_H__
|
@ -18,18 +18,4 @@
|
|||||||
#ifndef _STDLIB_H
|
#ifndef _STDLIB_H
|
||||||
#define _STDLIB_H
|
#define _STDLIB_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void *malloc(__SIZE_TYPE__ Size);
|
|
||||||
void *calloc(__SIZE_TYPE__ n, __SIZE_TYPE__ Size);
|
|
||||||
void *realloc(void *Address, __SIZE_TYPE__ Size);
|
|
||||||
void free(void *Address);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // !_STDLIB_H
|
#endif // !_STDLIB_H
|
||||||
|
337
include_std/typeinfo
Normal file
337
include_std/typeinfo
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_KERNEL_TYPEINFO_H__
|
||||||
|
#define __FENNIX_KERNEL_TYPEINFO_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
namespace __cxxabiv1
|
||||||
|
{
|
||||||
|
class __class_type_info;
|
||||||
|
class __si_class_type_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
class type_info
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~type_info();
|
||||||
|
|
||||||
|
bool operator==(const type_info &Argument) const noexcept
|
||||||
|
{
|
||||||
|
return ((Name == Argument.Name) ||
|
||||||
|
(Name[0] != '*' &&
|
||||||
|
__builtin_strcmp(Name, Argument.Name) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const type_info &Argument) const noexcept
|
||||||
|
{
|
||||||
|
return !operator==(Argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool before(const type_info &Argument) const noexcept
|
||||||
|
{
|
||||||
|
return (Name[0] == '*' && Argument.Name[0] == '*')
|
||||||
|
? Name < Argument.Name
|
||||||
|
: __builtin_strcmp(Name, Argument.Name) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *name() const noexcept
|
||||||
|
{
|
||||||
|
return Name[0] == '*' ? Name + 1 : Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool __is_pointer_p() const
|
||||||
|
{
|
||||||
|
return Name[0] == '*';
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool __is_function_p() const
|
||||||
|
{
|
||||||
|
return Name[0] == '(';
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool __do_catch(const type_info *ThrowType,
|
||||||
|
void **ThrowObject,
|
||||||
|
unsigned Outer) const;
|
||||||
|
|
||||||
|
virtual bool __do_upcast(const __cxxabiv1::__class_type_info *Target,
|
||||||
|
void **ObjectPointer) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const char *Name;
|
||||||
|
explicit type_info(const char *n) : Name(n) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
type_info &operator=(const type_info &);
|
||||||
|
type_info(const type_info &);
|
||||||
|
};
|
||||||
|
|
||||||
|
class bad_cast : public exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bad_cast() noexcept {}
|
||||||
|
virtual ~bad_cast() noexcept;
|
||||||
|
virtual const char *what() const noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
class bad_typeid : public exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bad_typeid() noexcept {}
|
||||||
|
virtual ~bad_typeid() noexcept;
|
||||||
|
virtual const char *what() const noexcept;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace __cxxabiv1
|
||||||
|
{
|
||||||
|
class __pbase_type_info : public std::type_info
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
unsigned int Flags;
|
||||||
|
const std::type_info *Pointee;
|
||||||
|
|
||||||
|
explicit __pbase_type_info(const char *n, int Qualifiers,
|
||||||
|
const std::type_info *Type)
|
||||||
|
: std::type_info(n),
|
||||||
|
Flags(Qualifiers),
|
||||||
|
Pointee(Type) {}
|
||||||
|
virtual ~__pbase_type_info();
|
||||||
|
|
||||||
|
enum __masks
|
||||||
|
{
|
||||||
|
__const_mask = 0x1,
|
||||||
|
__volatile_mask = 0x2,
|
||||||
|
__restrict_mask = 0x4,
|
||||||
|
__incomplete_mask = 0x8,
|
||||||
|
__incomplete_class_mask = 0x10,
|
||||||
|
__transaction_safe_mask = 0x20,
|
||||||
|
__noexcept_mask = 0x40
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
__pbase_type_info(const __pbase_type_info &);
|
||||||
|
|
||||||
|
__pbase_type_info &operator=(const __pbase_type_info &);
|
||||||
|
|
||||||
|
virtual bool __do_catch(const std::type_info *ThrowType,
|
||||||
|
void **ThrowObject,
|
||||||
|
unsigned int Outer) const;
|
||||||
|
|
||||||
|
inline bool __pointer_catch(const __pbase_type_info *ThrownType,
|
||||||
|
void **ThrowObject,
|
||||||
|
unsigned Outer) const
|
||||||
|
{
|
||||||
|
return Pointee->__do_catch(ThrownType->Pointee, ThrowObject, Outer + 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class __pointer_type_info : public __pbase_type_info
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit __pointer_type_info(const char *n,
|
||||||
|
int Qualifiers,
|
||||||
|
const std::type_info *Type)
|
||||||
|
: __pbase_type_info(n, Qualifiers, Type) {}
|
||||||
|
virtual ~__pointer_type_info();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool __is_pointer_p() const;
|
||||||
|
|
||||||
|
virtual bool __pointer_catch(const __pbase_type_info *ThrowType,
|
||||||
|
void **ThrowObject,
|
||||||
|
unsigned Outer) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FIXME: stub */
|
||||||
|
class __pointer_to_member_type_info : public __pbase_type_info
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
class __fundamental_type_info : public std::type_info
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit __fundamental_type_info(const char *n) : std::type_info(n) {}
|
||||||
|
virtual ~__fundamental_type_info();
|
||||||
|
};
|
||||||
|
|
||||||
|
class __base_class_type_info
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const __class_type_info *BaseType;
|
||||||
|
#ifdef __LP64__
|
||||||
|
long long OffsetFlags;
|
||||||
|
#else
|
||||||
|
long OffsetFlags;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum __offset_flags_masks
|
||||||
|
{
|
||||||
|
__virtual_mask = 0x1,
|
||||||
|
__public_mask = 0x2,
|
||||||
|
__hwm_bit = 0x2,
|
||||||
|
__offset_shift = 0x8
|
||||||
|
};
|
||||||
|
|
||||||
|
bool __is_virtual_p() const
|
||||||
|
{
|
||||||
|
return OffsetFlags & __virtual_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __is_public_p() const
|
||||||
|
{
|
||||||
|
return OffsetFlags & __public_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptrdiff_t __offset() const
|
||||||
|
{
|
||||||
|
return static_cast<ptrdiff_t>(OffsetFlags) >> __offset_shift;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FIXME: stub */
|
||||||
|
class __vmi_class_type_info /* : public __class_type_info */
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum __flags_masks
|
||||||
|
{
|
||||||
|
__non_diamond_repeat_mask = 0x1,
|
||||||
|
__diamond_shaped_mask = 0x2,
|
||||||
|
__flags_unknown_mask = 0x10
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class __class_type_info : public std::type_info
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit __class_type_info(const char *n)
|
||||||
|
: std::type_info(n) {}
|
||||||
|
virtual ~__class_type_info();
|
||||||
|
|
||||||
|
enum __sub_kind
|
||||||
|
{
|
||||||
|
__unknown = 0,
|
||||||
|
__not_contained,
|
||||||
|
__contained_ambig,
|
||||||
|
__contained_virtual_mask = __base_class_type_info::__virtual_mask,
|
||||||
|
__contained_public_mask = __base_class_type_info::__public_mask,
|
||||||
|
__contained_mask = 1 << __base_class_type_info::__hwm_bit,
|
||||||
|
__contained_private = __contained_mask,
|
||||||
|
__contained_public = __contained_mask | __contained_public_mask
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __upcast_result
|
||||||
|
{
|
||||||
|
const void *dst_ptr;
|
||||||
|
__sub_kind part2dst;
|
||||||
|
int src_details;
|
||||||
|
const __class_type_info *base_type;
|
||||||
|
|
||||||
|
__upcast_result(int d)
|
||||||
|
: dst_ptr(NULL),
|
||||||
|
part2dst(__unknown),
|
||||||
|
src_details(d),
|
||||||
|
base_type(NULL) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __dyncast_result
|
||||||
|
{
|
||||||
|
const void *dst_ptr;
|
||||||
|
__sub_kind whole2dst;
|
||||||
|
__sub_kind whole2src;
|
||||||
|
__sub_kind dst2src;
|
||||||
|
int whole_details;
|
||||||
|
|
||||||
|
__dyncast_result(int details_ = __vmi_class_type_info::__flags_unknown_mask)
|
||||||
|
: dst_ptr(NULL),
|
||||||
|
whole2dst(__unknown),
|
||||||
|
whole2src(__unknown),
|
||||||
|
dst2src(__unknown),
|
||||||
|
whole_details(details_) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
__dyncast_result(const __dyncast_result &);
|
||||||
|
|
||||||
|
__dyncast_result &
|
||||||
|
operator=(const __dyncast_result &);
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual __sub_kind __do_find_public_src(ptrdiff_t SourceToDestination,
|
||||||
|
const void *ObjectPointer,
|
||||||
|
const __class_type_info *SourceType,
|
||||||
|
const void *SubroutinePointer) const;
|
||||||
|
|
||||||
|
virtual bool __do_upcast(const __class_type_info *Destination,
|
||||||
|
const void *Object,
|
||||||
|
__upcast_result &__restrict Result) const;
|
||||||
|
|
||||||
|
virtual bool __do_dyncast(ptrdiff_t SourceToDestination,
|
||||||
|
__sub_kind AccessPath,
|
||||||
|
const __class_type_info *DestinationType,
|
||||||
|
const void *ObjectPointer,
|
||||||
|
const __class_type_info *SourceType,
|
||||||
|
const void *SourcePointer,
|
||||||
|
__dyncast_result &Result) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool __do_upcast(const __class_type_info *DestinationType,
|
||||||
|
void **ObjectPointer) const;
|
||||||
|
|
||||||
|
virtual bool __do_catch(const type_info *ThrowType,
|
||||||
|
void **ThrowObject,
|
||||||
|
unsigned Outer) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class __si_class_type_info : public __class_type_info
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const __class_type_info *BaseType;
|
||||||
|
|
||||||
|
explicit __si_class_type_info(const char *n,
|
||||||
|
const __class_type_info *Base)
|
||||||
|
: __class_type_info(n),
|
||||||
|
BaseType(Base) {}
|
||||||
|
virtual ~__si_class_type_info();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
__si_class_type_info(const __si_class_type_info &);
|
||||||
|
|
||||||
|
__si_class_type_info &operator=(const __si_class_type_info &);
|
||||||
|
|
||||||
|
virtual bool __do_dyncast(ptrdiff_t SourceToDestination, __sub_kind AccessPath,
|
||||||
|
const __class_type_info *DestinationType, const void *ObjectPointer,
|
||||||
|
const __class_type_info *SourceType, const void *SourcePointer,
|
||||||
|
__dyncast_result &Result) const;
|
||||||
|
|
||||||
|
virtual __sub_kind __do_find_public_src(ptrdiff_t SourceToDestination,
|
||||||
|
const void *ObjectPointer,
|
||||||
|
const __class_type_info *SourceType,
|
||||||
|
const void *SubroutinePointer) const;
|
||||||
|
|
||||||
|
virtual bool __do_upcast(const __class_type_info *Destination,
|
||||||
|
const void *Object,
|
||||||
|
__upcast_result &__restrict Result) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const __class_type_info *const nonvirtual_base_type = static_cast<const __class_type_info *>(0) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_TYPEINFO_H__
|
78
include_std/unwind.h
Normal file
78
include_std/unwind.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FENNIX_KERNEL_UNWIND_H__
|
||||||
|
#define __FENNIX_KERNEL_UNWIND_H__
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
enum _Unwind_Reason_Code
|
||||||
|
{
|
||||||
|
_URC_NO_REASON = 0,
|
||||||
|
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
|
||||||
|
_URC_FATAL_PHASE2_ERROR = 2,
|
||||||
|
_URC_FATAL_PHASE1_ERROR = 3,
|
||||||
|
_URC_NORMAL_STOP = 4,
|
||||||
|
_URC_END_OF_STACK = 5,
|
||||||
|
_URC_HANDLER_FOUND = 6,
|
||||||
|
_URC_INSTALL_CONTEXT = 7,
|
||||||
|
_URC_CONTINUE_UNWIND = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void *_Unwind_Context_Reg_Val;
|
||||||
|
typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__)));
|
||||||
|
typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
|
||||||
|
typedef unsigned _Unwind_Word __attribute__((__mode__(__unwind_word__)));
|
||||||
|
typedef signed _Unwind_Sword __attribute__((__mode__(__unwind_word__)));
|
||||||
|
typedef int _Unwind_Action;
|
||||||
|
|
||||||
|
enum _UA : _Unwind_Action
|
||||||
|
{
|
||||||
|
_UA_SEARCH_PHASE = 1,
|
||||||
|
_UA_CLEANUP_PHASE = 2,
|
||||||
|
_UA_HANDLER_FRAME = 4,
|
||||||
|
_UA_FORCE_UNWIND = 8,
|
||||||
|
_UA_END_OF_STACK = 16
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code,
|
||||||
|
struct _Unwind_Exception *);
|
||||||
|
|
||||||
|
typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(int,
|
||||||
|
_Unwind_Action,
|
||||||
|
_Unwind_Exception_Class,
|
||||||
|
struct _Unwind_Exception *,
|
||||||
|
struct _Unwind_Context *);
|
||||||
|
|
||||||
|
struct _Unwind_Exception
|
||||||
|
{
|
||||||
|
_Unwind_Exception_Class exception_class;
|
||||||
|
_Unwind_Exception_Cleanup_Fn exception_cleanup;
|
||||||
|
_Unwind_Word private_1;
|
||||||
|
_Unwind_Word private_2;
|
||||||
|
} __attribute__((__aligned__));
|
||||||
|
|
||||||
|
struct _Unwind_Context;
|
||||||
|
|
||||||
|
struct _Unwind_FrameState
|
||||||
|
{
|
||||||
|
_Unwind_Personality_Fn personality;
|
||||||
|
};
|
||||||
|
|
||||||
|
EXTERNC _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *Exception);
|
||||||
|
|
||||||
|
#endif // !__FENNIX_KERNEL_UNWIND_H__
|
1
kernel.h
1
kernel.h
@ -62,6 +62,7 @@ extern Recovery::KernelRecovery *RecoveryScreen;
|
|||||||
extern VirtualFileSystem::Node *DevFS;
|
extern VirtualFileSystem::Node *DevFS;
|
||||||
extern VirtualFileSystem::Node *MntFS;
|
extern VirtualFileSystem::Node *MntFS;
|
||||||
extern VirtualFileSystem::Node *ProcFS;
|
extern VirtualFileSystem::Node *ProcFS;
|
||||||
|
extern VirtualFileSystem::Node *VarLogFS;
|
||||||
|
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
121
syscalls.h
121
syscalls.h
@ -35,12 +35,75 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifndef SEEK_SET
|
||||||
|
#define SEEK_SET 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SEEK_CUR
|
||||||
|
#define SEEK_CUR 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SEEK_END
|
||||||
|
#define SEEK_END 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum MemoryMapFlags
|
||||||
|
{
|
||||||
|
MAP_PRESENT = 1 << 0,
|
||||||
|
MAP_WRITABLE = 1 << 1,
|
||||||
|
MAP_USER = 1 << 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum KCtl
|
||||||
|
{
|
||||||
|
KCTL_NULL,
|
||||||
|
|
||||||
|
KCTL_GET_PID,
|
||||||
|
KCTL_GET_TID,
|
||||||
|
KCTL_GET_UID,
|
||||||
|
KCTL_GET_GID,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the page size
|
||||||
|
*/
|
||||||
|
KCTL_GET_PAGE_SIZE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check whether the current thread is critical
|
||||||
|
*/
|
||||||
|
KCTL_IS_CRITICAL,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register an ELF library
|
||||||
|
* @fn int RegisterELFLib(char *Identifier, char *Path)
|
||||||
|
*/
|
||||||
|
KCTL_REGISTER_ELF_LIB,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get an ELF library
|
||||||
|
* @fn uintptr_t GetELFLib(char *Identifier);
|
||||||
|
*/
|
||||||
|
KCTL_GET_ELF_LIB_MEMORY_IMAGE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the absolute path of a library file
|
||||||
|
* @fn int GetAbsolutePath(char *Identifier, char *Buffer, size_t BufferSize)
|
||||||
|
*/
|
||||||
|
KCTL_GET_ABSOLUTE_PATH,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enum NativeSyscalls
|
* @enum NativeSyscalls
|
||||||
* Enumeration of all the native syscalls available in the kernel
|
* Enumeration of all the native syscalls available in the kernel
|
||||||
*/
|
*/
|
||||||
enum NativeSyscalls
|
enum NativeSyscalls
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Basic syscalls
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
/** @brief Exit the process.
|
/** @brief Exit the process.
|
||||||
* @fn int Exit(int Code)
|
* @fn int Exit(int Code)
|
||||||
* This syscall is used to exit the current process with the provided exit code.
|
* This syscall is used to exit the current process with the provided exit code.
|
||||||
@ -53,6 +116,12 @@ enum NativeSyscalls
|
|||||||
*/
|
*/
|
||||||
_Print,
|
_Print,
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Memory syscalls
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
/** @brief Request pages of memory
|
/** @brief Request pages of memory
|
||||||
* @fn uintptr_t RequestPages(size_t Count)
|
* @fn uintptr_t RequestPages(size_t Count)
|
||||||
* This syscall is used to request a specific number of pages of memory from the kernel.
|
* This syscall is used to request a specific number of pages of memory from the kernel.
|
||||||
@ -71,6 +140,29 @@ enum NativeSyscalls
|
|||||||
*/
|
*/
|
||||||
_DetachAddress,
|
_DetachAddress,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Map memory address
|
||||||
|
* @fn int MapAddress(uintptr_t VirtualAddress, uintptr_t PhysicalAddress, size_t Size, enum MemoryMapFlags Flags)
|
||||||
|
* This syscall is used to map a specific memory address to the current process.
|
||||||
|
*
|
||||||
|
* @param Size The size of the memory region to map. Not pages.
|
||||||
|
*/
|
||||||
|
_MemoryMap,
|
||||||
|
|
||||||
|
/** @brief Unmap memory address
|
||||||
|
* @fn int UnmapAddress(uintptr_t VirtualAddress, size_t Size)
|
||||||
|
* This syscall is used to unmap a specific memory address from the current process.
|
||||||
|
*
|
||||||
|
* @param Size The size of the memory region to unmap. Not pages.
|
||||||
|
*/
|
||||||
|
_MemoryUnmap,
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Kernel Control syscalls
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
/** @brief Kernel Control
|
/** @brief Kernel Control
|
||||||
* @fn uintptr_t KernelCTL(enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4)
|
* @fn uintptr_t KernelCTL(enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4)
|
||||||
* This syscall is used to control certain aspects of the kernel or get information about it.
|
* This syscall is used to control certain aspects of the kernel or get information about it.
|
||||||
@ -78,11 +170,10 @@ enum NativeSyscalls
|
|||||||
_KernelCTL,
|
_KernelCTL,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates/Reads/Writes/Deletes an IPC Pipe/Shared Memory/Message Queue/etc.
|
*
|
||||||
* @fn int IPC(enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size)
|
* File syscalls
|
||||||
* This syscall is used to create, read, write or delete an IPC Pipe/Shared Memory/Message Queue/etc.
|
*
|
||||||
*/
|
*/
|
||||||
_IPC,
|
|
||||||
|
|
||||||
/** @brief Open a file
|
/** @brief Open a file
|
||||||
* @fn void *FileOpen(const char *Path, uint64_t Flags)
|
* @fn void *FileOpen(const char *Path, uint64_t Flags)
|
||||||
@ -97,19 +188,19 @@ enum NativeSyscalls
|
|||||||
_FileClose,
|
_FileClose,
|
||||||
|
|
||||||
/** @brief Read from a file
|
/** @brief Read from a file
|
||||||
* @fn uint64_t FileRead(void *KernelPrivate, uint64_t Offset, uint8_t *Buffer, uint64_t Size)
|
* @fn uint64_t FileRead(void *KernelPrivate, uint8_t *Buffer, uint64_t Size)
|
||||||
* This syscall is used to read a specific number of bytes from a file at a specific offset.
|
* This syscall is used to read a specific number of bytes from a file at a specific offset.
|
||||||
*/
|
*/
|
||||||
_FileRead,
|
_FileRead,
|
||||||
|
|
||||||
/** @brief Write to a file
|
/** @brief Write to a file
|
||||||
* @fn uint64_t FileWrite(void *KernelPrivate, uint64_t Offset, uint8_t *Buffer, uint64_t Size)
|
* @fn uint64_t FileWrite(void *KernelPrivate, uint8_t *Buffer, uint64_t Size)
|
||||||
* This syscall is used to write a specific number of bytes to a file at a specific offset.
|
* This syscall is used to write a specific number of bytes to a file at a specific offset.
|
||||||
*/
|
*/
|
||||||
_FileWrite,
|
_FileWrite,
|
||||||
|
|
||||||
/** @brief Seek in a file
|
/** @brief Seek in a file
|
||||||
* @fn uint64_t FileSeek(void *KernelPrivate, uint64_t Offset, int Whence)
|
* @fn off_t FileSeek(void *KernelPrivate, off_t Offset, int Whence)
|
||||||
* This syscall is used to change the current offset in a file.
|
* This syscall is used to change the current offset in a file.
|
||||||
*/
|
*/
|
||||||
_FileSeek,
|
_FileSeek,
|
||||||
@ -120,6 +211,19 @@ enum NativeSyscalls
|
|||||||
*/
|
*/
|
||||||
_FileStatus,
|
_FileStatus,
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Process syscalls
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates/Reads/Writes/Deletes an IPC Pipe/Shared Memory/Message Queue/etc.
|
||||||
|
* @fn int IPC(enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size)
|
||||||
|
* This syscall is used to create, read, write or delete an IPC Pipe/Shared Memory/Message Queue/etc.
|
||||||
|
*/
|
||||||
|
_IPC,
|
||||||
|
|
||||||
/** @brief Sleep for a specific amount of time
|
/** @brief Sleep for a specific amount of time
|
||||||
* @fn int Sleep(uint64_t Milliseconds)
|
* @fn int Sleep(uint64_t Milliseconds)
|
||||||
* This syscall is used to sleep the current thread for a specific amount of time.
|
* This syscall is used to sleep the current thread for a specific amount of time.
|
||||||
@ -215,6 +319,9 @@ enum NativeSyscalls
|
|||||||
|
|
||||||
/** @brief Reserved syscall */
|
/** @brief Reserved syscall */
|
||||||
_SysReservedCreateThread,
|
_SysReservedCreateThread,
|
||||||
|
|
||||||
|
/** @brief Not a real syscall */
|
||||||
|
_MaxSyscall
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user