#pragma once #include "ModuleHandle.hpp" #include "ModuleSegment.hpp" #include "../KernelAllocator.hpp" #include "../utils/Rc.hpp" #include "orbis-config.hpp" #include #include #include namespace orbis { struct Thread; struct Process; struct ModuleNeeded { utils::kstring name; std::uint16_t version; std::uint16_t attr; bool isExport; }; enum class SymbolBind : std::uint8_t { Local, Global, Weak, Unique = 10 }; enum class SymbolVisibility : std::uint8_t { Default, Internal, Hidden, Protected }; enum class SymbolType : std::uint8_t { NoType, Object, Function, Section, File, Common, Tls, IFunc = 10, }; struct Symbol { std::int32_t moduleIndex; std::uint32_t libraryIndex; std::uint64_t id; std::uint64_t address; std::uint64_t size; SymbolVisibility visibility; SymbolBind bind; SymbolType type; }; struct Relocation { std::uint64_t offset; std::uint32_t relType; std::uint32_t symbolIndex; std::int64_t addend; }; struct Module final { Process *proc{}; utils::kstring vfsPath; char moduleName[256]{}; char soName[256]{}; ModuleHandle id{}; uint32_t tlsIndex{}; ptr tlsInit{}; uint32_t tlsInitSize{}; uint32_t tlsSize{}; uint32_t tlsOffset{}; uint32_t tlsAlign{}; ptr initProc{}; ptr finiProc{}; ptr ehFrameHdr{}; ptr ehFrame{}; uint32_t ehFrameHdrSize{}; uint32_t ehFrameSize{}; ModuleSegment segments[4]{}; uint32_t segmentCount{}; std::uint8_t fingerprint[20]{}; ptr base{}; uint64_t size{}; ptr stackStart{}; ptr stackEnd{}; ptr processParam{}; uint64_t processParamSize{}; ptr moduleParam{}; uint64_t moduleParamSize{}; ptr pltGot{}; uint16_t version{}; uint16_t attributes{}; uint16_t type{}; uint16_t flags{}; uint64_t entryPoint{}; uint32_t phNum{}; uint64_t phdrAddress{}; bool isTlsDone = false; utils::kvector symbols; utils::kvector pltRelocations; utils::kvector nonPltRelocations; utils::kvector neededModules; utils::kvector neededLibraries; utils::kvector> importedModules; utils::kvector> namespaceModules; utils::kvector needed; std::atomic references{0}; unsigned _total_size = 0; void incRef() { if (_total_size != sizeof(Module)) std::abort(); if (references.fetch_add(1, std::memory_order::relaxed) > 512) { assert(!"too many references"); } } void decRef() { if (references.fetch_sub(1, std::memory_order::relaxed) == 1 && proc != nullptr) { destroy(); } } orbis::SysResult relocate(Process *process); private: void destroy(); }; utils::Ref createModule(Thread *p, std::string vfsPath, const char *name); } // namespace orbis