/* * ======================================================== * * HCore * Copyright Mahrouss Logic, all rights reserved. * * ======================================================== */ #include #include #include #include #include #include #include #include #include #include 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> file; file.New(const_cast(path), kRestrictRB); if (StringBuilder::Equals(file->MIME(), this->MIME())) { fPath = StringBuilder::Construct(path).Leak(); fCachedBlob = file->Read(); PEFContainer *container = reinterpret_cast(fCachedBlob); auto fFree = [&]() -> void { kcout << "CodeManager: Warning: Executable format error!\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(fCachedBlob); PEFCommandHeader *container_header = reinterpret_cast( (UIntPtr)fCachedBlob + sizeof(PEFContainer)); ErrorOr errOrSym; switch (kind) { case kPefCode: { errOrSym = StringBuilder::Construct(".text$"); break; } case kPefData: { errOrSym = StringBuilder::Construct(".data$"); break; } case kPefZero: { errOrSym = StringBuilder::Construct(".page_zero$"); break; } default: return nullptr; } char *unconstSymbol = const_cast(name); for (SizeT i = 0UL; i < rt_string_len(name, 0); ++i) { if (unconstSymbol[i] == ' ') { unconstSymbol[i] = '$'; } } errOrSym.Leak().Leak() += name; for (SizeT index = 0; index < container->Count; ++index) { if (StringBuilder::Equals(container_header->Name, errOrSym.Leak().Leak().CData())) { if (container_header->Kind == kind) return (VoidPtr)(static_cast(fCachedBlob) + container_header->Offset); } } return nullptr; } ErrorOr PEFLoader::LoadStart() { if (auto sym = this->FindSymbol(kPefStart, kPefCode); sym) return ErrorOr(sym); return ErrorOr(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 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-hcore-exec"; } } // namespace HCore