summaryrefslogtreecommitdiffhomepage
path: root/Private/Source/CodeManager.cxx
blob: 911aefd3beeaa4dc2d202abe40fee778a3d2a842 (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
/*
 *	========================================================
 *
 *	HCore
 * 	Copyright 2024 Mahrouss Logic, all rights reserved.
 *
 * 	========================================================
 */

#include <KernelKit/CodeManager.hpp>
#include <KernelKit/DebugOutput.hpp>
#include <KernelKit/FileManager.hpp>
#include <KernelKit/ProcessManager.hpp>
#include <NewKit/Defines.hpp>
#include <NewKit/ErrorID.hpp>
#include <NewKit/KernelHeap.hpp>
#include <NewKit/OwnPtr.hpp>
#include <NewKit/RuntimeCheck.hpp>
#include <NewKit/String.hpp>

namespace HCore {
namespace Detail {
UInt32 rt_get_pef_platform(void) noexcept {
#ifdef __32x0__
  return kPefArch32x0;
#elif defined(__64x0__)
  return kPefArch64x0;
#elif defined(__x86_64__)
  return kPefArchAMD64;
#else
  return kPefArchInvalid;
#endif  // __POWER || __x86_64__
}
}  // namespace Detail

PEFLoader::PEFLoader(const VoidPtr blob) : fCachedBlob(nullptr) {
  fCachedBlob = blob;
  fBad = false;

  MUST_PASS(fCachedBlob);
}

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;

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

bool PEFLoader::IsLoaded() noexcept { return !fBad && fCachedBlob; }

namespace Utils {
bool execute_from_image(PEFLoader &exec) noexcept {
  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);
}
}  // namespace Utils

const char *PEFLoader::Path() { return fPath.Leak().CData(); }

const char *PEFLoader::Format() { return "PEF"; }

const char *PEFLoader::MIME() { return "application/x-exec"; }
}  // namespace HCore