Update kernel

This commit is contained in:
Alex 2023-06-10 13:11:25 +03:00
parent dcdba03426
commit 41db477173
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
82 changed files with 6342 additions and 4079 deletions

View File

@ -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
View 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
View File

@ -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."
},
],
} }
] ]
} }

View File

@ -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",

View File

@ -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;
} }

View File

@ -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 */

View File

@ -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
}

View File

@ -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;
} }

View File

@ -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");

View File

@ -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",

View File

@ -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

View File

@ -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);

View File

@ -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");

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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))
{ {

View File

@ -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)

View File

@ -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)

View File

@ -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();

View File

@ -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
View 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;
}
}

View File

@ -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
View 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;
}
}

View 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
View 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
View 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};
}
}

View File

@ -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");

View 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();
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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)

View File

@ -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;
} }

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View 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;
}
}

View 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 */
}
}

View File

@ -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() {}
{
}
} }

View 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
}
}

View 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
}
}

View 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);
}
}

View File

@ -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
View 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;
}
}

View File

@ -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)

View File

@ -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()

View File

@ -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;
} }
} }

View File

@ -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;

View File

@ -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;
} }
} }

View File

@ -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;

View File

@ -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);
} }
} }

View File

@ -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;
} }
} }

View File

@ -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);
} }

View File

@ -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;

View File

@ -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__

View File

@ -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
View 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__

View File

@ -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__

View File

@ -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);

View 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.
* *

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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
View 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
View 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__

View File

@ -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
View 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__

View File

@ -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
View 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
View 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__

View File

@ -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

View File

@ -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
}; };
/** /**