blob: 47c7bd1b2484d17d1f480a93d11c5e020df848e1 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
/*
* ========================================================
*
* hCore
* Copyright Mahrouss Logic, all rights reserved.
*
* ========================================================
*/
#include <KernelKit/FileManager.hpp>
#include <KernelKit/CodeManager.hpp>
#include <KernelKit/DebugOutput.hpp>
#include <KernelKit/ProcessManager.hpp>
#include <NewKit/KHeap.hpp>
#include <NewKit/String.hpp>
#include <NewKit/OwnPtr.hpp>
#include <NewKit/ErrorID.hpp>
namespace hCore
{
namespace Detail
{
UInt32 rt_get_pef_platform(void)
{
#ifdef __powerpc
return kPefArchPower;
#elif defined(__arc__)
return kPefArchARC;
#elif defined(__x86_64__)
return kPefArchAMD64;
#else
return kPefArchInvalid;
#endif // __POWER || __x86_64__
}
}
PEFLoader::PEFLoader(const char* path)
: fCachedBlob(nullptr), fBad(false)
{
OwnPtr<FileStream<char>> file;
file.New(const_cast<Char*>(path));
if (StringBuilder::Equals(file->MIME(), this->MIME()))
{
fPath = StringBuilder::Construct(path).Leak();
fCachedBlob = file->ReadAll();
PEFContainer* container = reinterpret_cast<PEFContainer*>(fCachedBlob);
auto fFree = [&]() -> void {
kcout << "CodeManager: Warning: Bad executable, program will not be started!\n";
fBad = true;
kernel_delete_ptr(fCachedBlob);
fCachedBlob = nullptr;
};
if (container->Cpu == Detail::rt_get_pef_platform() &&
container->Magic[0] == kPefMagic[0] &&
container->Magic[1] == kPefMagic[1] &&
container->Magic[2] == kPefMagic[2] &&
container->Abi == kPefAbi)
{
if (container->Kind != kPefKindObject &&
container->Kind != kPefKindDebug)
{
kcout << "CodeManager: Info: Good executable. can proceed.\n";
return;
}
}
fFree();
}
}
PEFLoader::~PEFLoader()
{
if (fCachedBlob)
kernel_delete_ptr(fCachedBlob);
}
VoidPtr PEFLoader::FindSymbol(const char* name, Int32 kind)
{
if (!fCachedBlob ||
fBad)
return nullptr;
PEFContainer* container = reinterpret_cast<PEFContainer*>(fCachedBlob);
PEFCommandHeader* container_header = reinterpret_cast<PEFCommandHeader*>((UIntPtr)fCachedBlob + sizeof(PEFContainer));
for (SizeT index = 0; index < container->Count; ++index)
{
kcout << "Iterating over container at index: " << StringBuilder::FromInt("%", index) << ", name: " << container_header->Name << "\n";
if (StringBuilder::Equals(container_header->Name, name))
{
kcout << "Found potential container, checking for validity.\n";
if (container_header->Kind == kind)
return static_cast<UIntPtr*>(fCachedBlob) + container_header->Offset;
continue;
}
}
return nullptr;
}
ErrorOr<VoidPtr> PEFLoader::LoadStart()
{
if (auto sym = this->FindSymbol("__start", kPefCode); sym)
return ErrorOr<VoidPtr>(sym);
return ErrorOr<VoidPtr>(ME_EXEC_ERROR);
}
bool PEFLoader::IsLoaded() noexcept { return !fBad && fCachedBlob; }
namespace Utils
{
bool execute_from_image(PEFLoader& exec)
{
auto errOrStart = exec.LoadStart();
if (errOrStart.Error() != 0)
return false;
Process proc(errOrStart.Leak().Leak());
Ref<Process> refProc = proc;
return ProcessManager::Shared().Leak().Add(refProc);
}
}
const char* PEFLoader::Path() { return fPath.Leak().CData(); }
const char* PEFLoader::Format() { return "PEF"; }
const char* PEFLoader::MIME() { return "application/x-exec"; }
} // namespace hCore
|