mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 13:00:15 +02:00
Adjust the project to be able to be installed
Cleans up file locations
This commit is contained in:
1 parent
43ec043478
commit
33daca99e2
11 files changed
+43
-81
No files matched your search
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static inline uint64_t AlignUp(uint64_t value, uint64_t size) {
|
||||
return value + (size - value % size) % size;
|
||||
};
|
||||
|
||||
static inline uint64_t AlignDown(uint64_t value, uint64_t size) {
|
||||
return value - value % size;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
|
||||
#include <elf.h>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace ELFLoader {
|
||||
struct ELFSymbol {
|
||||
uint64_t FileOffset;
|
||||
uint64_t Address;
|
||||
uint64_t Size;
|
||||
uint8_t Type;
|
||||
uint8_t Bind;
|
||||
uint16_t SectionIndex;
|
||||
char const *Name;
|
||||
};
|
||||
|
||||
class ELFContainer {
|
||||
public:
|
||||
ELFContainer(std::string const &Filename, bool CustomInterpreter);
|
||||
~ELFContainer();
|
||||
|
||||
uint64_t GetEntryPoint() const { return Header.e_entry; }
|
||||
|
||||
using MemoryLayout = std::tuple<uint64_t, uint64_t, uint64_t>;
|
||||
|
||||
MemoryLayout GetLayout() const {
|
||||
return std::make_tuple(MinPhysicalMemoryLocation, MaxPhysicalMemoryLocation,
|
||||
PhysicalMemorySize);
|
||||
}
|
||||
|
||||
// Data, Physical, Size
|
||||
using MemoryWriter = std::function<void(void *, uint64_t, uint64_t)>;
|
||||
void WriteLoadableSections(MemoryWriter Writer, uint64_t Offset = 0);
|
||||
|
||||
ELFSymbol const *GetSymbol(char const *Name);
|
||||
ELFSymbol const *GetSymbol(uint64_t Address);
|
||||
|
||||
using RangeType = std::pair<uint64_t, uint64_t>;
|
||||
ELFSymbol const *GetSymbolInRange(RangeType Address);
|
||||
|
||||
bool WasDynamic() const { return DynamicProgram; }
|
||||
std::string &InterpreterLocation() { return DynamicLinker; }
|
||||
|
||||
std::vector<char const*> const *GetNecessaryLibs() const { return &NecessaryLibs; }
|
||||
|
||||
void PrintRelocationTable() const;
|
||||
|
||||
using SymbolGetter = std::function<ELFSymbol*(char const*, uint8_t)>;
|
||||
void FixupRelocations(void *ELFBase, uint64_t GuestELFBase, SymbolGetter Getter);
|
||||
|
||||
using SymbolAdder = std::function<void(ELFSymbol*)>;
|
||||
void AddSymbols(SymbolAdder Adder);
|
||||
|
||||
void GetInitLocations(uint64_t GuestELFBase, std::vector<uint64_t> *Locations);
|
||||
|
||||
bool HasTLS() const { return TLSHeader != nullptr; }
|
||||
uint64_t InitializeThreadSlot(void *ELFBase, std::function<void(void const*, uint64_t)> Writer) const;
|
||||
|
||||
private:
|
||||
bool LoadELF(std::string const &Filename);
|
||||
void CalculateMemoryLayouts();
|
||||
void CalculateSymbols();
|
||||
void GetDynamicLibs();
|
||||
|
||||
// Information functions
|
||||
void PrintHeader() const;
|
||||
void PrintSectionHeaders() const;
|
||||
void PrintProgramHeaders() const;
|
||||
void PrintSymbolTable() const;
|
||||
void PrintInitArray() const;
|
||||
void PrintDynamicTable() const;
|
||||
|
||||
std::vector<char> RawFile;
|
||||
Elf64_Ehdr Header;
|
||||
std::vector<Elf64_Shdr*> SectionHeaders;
|
||||
std::vector<Elf64_Phdr*> ProgramHeaders;
|
||||
std::vector<ELFSymbol> Symbols;
|
||||
std::unordered_map<std::string, ELFSymbol *> SymbolMap;
|
||||
std::map<uint64_t, ELFSymbol *> SymbolMapByAddress;
|
||||
|
||||
std::vector<char const*> NecessaryLibs;
|
||||
|
||||
uint64_t MinPhysicalMemoryLocation{0};
|
||||
uint64_t MaxPhysicalMemoryLocation{0};
|
||||
uint64_t PhysicalMemorySize{0};
|
||||
Elf64_Phdr* InterpreterHeader{};
|
||||
bool DynamicProgram{false};
|
||||
std::string DynamicLinker;
|
||||
Elf64_Phdr const *TLSHeader{};
|
||||
};
|
||||
|
||||
} // namespace ELFLoader
|
||||
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include "ELFLoader.h"
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace ELFLoader {
|
||||
class ELFSymbolDatabase final {
|
||||
public:
|
||||
ELFSymbolDatabase(::ELFLoader::ELFContainer *file);
|
||||
~ELFSymbolDatabase();
|
||||
|
||||
::ELFLoader::ELFContainer::MemoryLayout GetFileLayout() const;
|
||||
|
||||
void MapMemoryRegions(std::function<void*(uint64_t, uint64_t)> Mapper);
|
||||
void WriteLoadableSections(::ELFLoader::ELFContainer::MemoryWriter Writer);
|
||||
|
||||
uint64_t DefaultRIP() const;
|
||||
|
||||
using RangeType = std::pair<uint64_t, uint64_t>;
|
||||
::ELFLoader::ELFSymbol const *GetSymbolInRange(RangeType Address);
|
||||
::ELFLoader::ELFSymbol const *GetGlobalSymbolInRange(RangeType Address);
|
||||
::ELFLoader::ELFSymbol const *GetNoWeakSymbolInRange(RangeType Address);
|
||||
|
||||
void GetInitLocations(std::vector<uint64_t> *Locations);
|
||||
uint64_t InitializeThreadSlot(std::function<void(void const*, uint64_t)> Writer) const;
|
||||
|
||||
private:
|
||||
::ELFLoader::ELFContainer *File;
|
||||
|
||||
struct ELFInfo {
|
||||
std::string Name;
|
||||
::ELFLoader::ELFContainer* Container;
|
||||
::ELFLoader::ELFContainer::MemoryLayout CustomLayout;
|
||||
void *ELFBase;
|
||||
uint64_t GuestBase;
|
||||
};
|
||||
|
||||
ELFInfo LocalInfo;
|
||||
std::vector<ELFInfo*> DynamicELFInfo;
|
||||
std::vector<ELFInfo*> InitializationOrder;
|
||||
|
||||
std::unordered_map<std::string, ELFInfo*> NameToELF;
|
||||
std::vector<std::string> LibrarySearchPaths;
|
||||
|
||||
// Symbols
|
||||
std::vector<ELFLoader::ELFSymbol*> Symbols;
|
||||
using SymbolTableType = std::unordered_map<std::string, ELFLoader::ELFSymbol *>;
|
||||
SymbolTableType SymbolMap;
|
||||
SymbolTableType SymbolMapGlobalOnly;
|
||||
SymbolTableType SymbolMapNoWeak;
|
||||
SymbolTableType SymbolMapNoMain;
|
||||
SymbolTableType SymbolMapNoMainNoWeak;
|
||||
std::map<uint64_t, ELFLoader::ELFSymbol *> SymbolMapByAddress;
|
||||
|
||||
bool FindLibraryFile(std::string *Result, const char *Library);
|
||||
void FillLibrarySearchPaths();
|
||||
void FillMemoryLayouts();
|
||||
void FillInitializationOrder();
|
||||
void FillSymbols();
|
||||
|
||||
void HandleRelocations();
|
||||
|
||||
::ELFLoader::ELFSymbol const *GetSymbolFromTable(RangeType Address, std::unordered_map<std::string, ELFLoader::ELFSymbol *> &Table);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <stdarg.h>
|
||||
|
||||
namespace LogMan {
|
||||
enum DebugLevels {
|
||||
NONE = 0, ///< Expect zero messages
|
||||
ASSERT = 1, ///< Assert throwing
|
||||
ERROR = 2, ///< Only Errors printed
|
||||
DEBUG = 3, ///< Debug messages added
|
||||
INFO = 4, ///< Info messages added
|
||||
STDOUT = 5, ///< Meant to go to STDOUT
|
||||
STDERR = 6, ///< Meant to go to STDERR
|
||||
};
|
||||
|
||||
constexpr DebugLevels MSG_LEVEL = INFO;
|
||||
|
||||
namespace Throw {
|
||||
using ThrowHandler = void(*)(char const *Message);
|
||||
void InstallHandler(ThrowHandler Handler);
|
||||
|
||||
[[noreturn]] void M(const char *fmt, va_list args);
|
||||
|
||||
#ifdef NDEBUG
|
||||
static inline void A(bool, const char*, ...) {}
|
||||
#else
|
||||
static inline void A(bool Value, const char *fmt, ...) {
|
||||
if (MSG_LEVEL >= ASSERT && !Value) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
M(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Throw
|
||||
|
||||
namespace Msg {
|
||||
using MsgHandler = void(*)(DebugLevels Level, char const *Message);
|
||||
void InstallHandler(MsgHandler Handler);
|
||||
|
||||
void M(DebugLevels Level, const char *fmt, va_list args);
|
||||
|
||||
#ifdef NDEBUG
|
||||
static inline void A(const char*, ...) {}
|
||||
#else
|
||||
static inline void A(const char *fmt, ...) {
|
||||
if (MSG_LEVEL >= ASSERT) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
M(ASSERT, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
__builtin_trap();
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void E(const char *fmt, ...) {
|
||||
if (MSG_LEVEL >= ERROR) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
M(ERROR, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
static inline void D(const char *fmt, ...) {
|
||||
if (MSG_LEVEL >= DEBUG) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
M(DEBUG, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
static inline void I(const char *fmt, ...) {
|
||||
if (MSG_LEVEL >= INFO) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
M(INFO, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void OUT(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
M(STDOUT, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static inline void ERR(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
M(STDERR, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
} // namespace Msg
|
||||
} // namespace LogMan
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
namespace SU::VM {
|
||||
class VMInstance {
|
||||
public:
|
||||
struct RegisterState {
|
||||
uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp;
|
||||
uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
|
||||
uint64_t rip, rflags;
|
||||
};
|
||||
|
||||
struct SpecialRegisterState {
|
||||
struct {
|
||||
uint64_t base;
|
||||
} fs, gs;
|
||||
};
|
||||
|
||||
static VMInstance* Create();
|
||||
virtual ~VMInstance() {}
|
||||
|
||||
virtual void SetPhysicalMemorySize(uint64_t Size) = 0;
|
||||
virtual void AddMemoryMapping(uint64_t VirtualAddress, uint64_t PhysicalAddress, uint64_t Size) = 0;
|
||||
virtual void *GetPhysicalMemoryPointer() = 0;
|
||||
virtual void SetVMRIP(uint64_t VirtualAddress) = 0;
|
||||
virtual bool SetStepping(bool Step) = 0;
|
||||
virtual bool Run() = 0;
|
||||
virtual bool Initialize() = 0;
|
||||
virtual int ExitReason() = 0;
|
||||
virtual uint64_t GetFailEntryReason() = 0;
|
||||
virtual RegisterState GetRegisterState() = 0;
|
||||
virtual SpecialRegisterState GetSpecialRegisterState() = 0;
|
||||
|
||||
virtual void SetRegisterState(RegisterState &State) = 0;
|
||||
virtual void SetSpecialRegisterState(SpecialRegisterState &State) = 0;
|
||||
|
||||
virtual void Debug() = 0;
|
||||
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user