mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-09 17:00:19 +02:00
These are completely unused since this ELFContainer is significantly less utilized than original expectations. More of this code is dead and can be removed in the future.
187 lines
4.3 KiB
C++
187 lines
4.3 KiB
C++
// SPDX-License-Identifier: MIT
|
|
#pragma once
|
|
|
|
#include <FEXCore/fextl/map.h>
|
|
#include <FEXCore/fextl/unordered_map.h>
|
|
#include <FEXCore/fextl/string.h>
|
|
#include <FEXCore/fextl/vector.h>
|
|
|
|
#include <cstdint>
|
|
#include <elf.h>
|
|
#include <functional>
|
|
#include <stddef.h>
|
|
#include <tuple>
|
|
#include <utility>
|
|
|
|
// Add macros which are missing in some versions of <elf.h>
|
|
#ifndef ELF32_ST_VISIBILITY
|
|
#define ELF32_ST_VISIBILITY(o) ((o)&0x3)
|
|
#endif
|
|
|
|
#ifndef ELF64_ST_VISIBILITY
|
|
#define ELF64_ST_VISIBILITY(o) ((o)&0x3)
|
|
#endif
|
|
|
|
namespace ELFLoader {
|
|
struct ELFSymbol {
|
|
uint64_t FileOffset;
|
|
uint64_t Address;
|
|
uint64_t Size;
|
|
uint8_t Type;
|
|
uint8_t Bind;
|
|
uint16_t SectionIndex;
|
|
const char* Name;
|
|
};
|
|
|
|
class ELFContainer {
|
|
public:
|
|
ELFContainer(const fextl::string& Filename, const fextl::string& RootFS, bool CustomInterpreter);
|
|
~ELFContainer();
|
|
|
|
uint64_t GetEntryPoint() const {
|
|
if (Mode == MODE_32BIT) {
|
|
return Header._32.e_entry;
|
|
} else {
|
|
return Header._64.e_entry;
|
|
}
|
|
}
|
|
|
|
using MemoryLayout = std::tuple<uint64_t, uint64_t, uint64_t>;
|
|
|
|
MemoryLayout GetLayout() const {
|
|
return std::make_tuple(MinPhysicalMemoryLocation, MaxPhysicalMemoryLocation, PhysicalMemorySize);
|
|
}
|
|
|
|
struct BRKInfo {
|
|
uint64_t Base;
|
|
uint64_t Size;
|
|
};
|
|
|
|
BRKInfo GetBRKInfo() const {
|
|
return {BRKBase, BRKSize};
|
|
}
|
|
|
|
// Data, Physical, Size
|
|
using MemoryWriter = std::function<void(void*, uint64_t, uint64_t)>;
|
|
void WriteLoadableSections(MemoryWriter Writer, uint64_t Offset = 0);
|
|
|
|
const ELFSymbol* GetSymbol(const char* Name);
|
|
const ELFSymbol* GetSymbol(uint64_t Address);
|
|
|
|
using RangeType = std::pair<uint64_t, uint64_t>;
|
|
const ELFSymbol* GetSymbolInRange(RangeType Address);
|
|
|
|
bool WasDynamic() const {
|
|
return DynamicProgram;
|
|
}
|
|
bool HasDynamicLinker() const {
|
|
return !DynamicLinker.empty();
|
|
}
|
|
bool WasLoaded() const {
|
|
return Loaded;
|
|
}
|
|
fextl::string& InterpreterLocation() {
|
|
return DynamicLinker;
|
|
}
|
|
|
|
const fextl::vector<const char*>* GetNecessaryLibs() const {
|
|
return &NecessaryLibs;
|
|
}
|
|
|
|
using SymbolGetter = std::function<ELFSymbol*(const char*, uint8_t)>;
|
|
void FixupRelocations(void* ELFBase, uint64_t GuestELFBase, SymbolGetter Getter);
|
|
|
|
using SymbolAdder = std::function<void(ELFSymbol*)>;
|
|
void AddSymbols(SymbolAdder Adder);
|
|
|
|
using UnwindAdder = std::function<void(uintptr_t)>;
|
|
void AddUnwindEntries(UnwindAdder Adder);
|
|
|
|
void GetInitLocations(uint64_t GuestELFBase, fextl::vector<uint64_t>* Locations);
|
|
|
|
|
|
bool HasTLS() const {
|
|
return TLSHeader._64 != nullptr;
|
|
}
|
|
uint64_t GetTLSBase() const {
|
|
if (GetMode() == ELFMode::MODE_64BIT) {
|
|
return TLSHeader._64->p_vaddr;
|
|
} else {
|
|
return TLSHeader._32->p_vaddr;
|
|
}
|
|
}
|
|
|
|
enum ELFMode {
|
|
MODE_32BIT,
|
|
MODE_64BIT,
|
|
};
|
|
|
|
ELFMode GetMode() const {
|
|
return Mode;
|
|
}
|
|
size_t GetProgramHeaderCount() const {
|
|
return ProgramHeaders.size();
|
|
}
|
|
|
|
enum ELFType {
|
|
TYPE_NONE,
|
|
TYPE_X86_64,
|
|
TYPE_X86_32,
|
|
TYPE_OTHER_ELF,
|
|
};
|
|
static ELFType GetELFType(const fextl::string& Filename);
|
|
static ELFType GetELFType(int FD);
|
|
static bool IsSupportedELF(const fextl::string& Filename) {
|
|
ELFType Type = GetELFType(Filename);
|
|
return Type == TYPE_X86_64 || Type == TYPE_X86_32;
|
|
}
|
|
|
|
private:
|
|
bool LoadELF(const fextl::string& Filename);
|
|
bool LoadELF_32();
|
|
bool LoadELF_64();
|
|
void CalculateMemoryLayouts();
|
|
void CalculateSymbols();
|
|
void GetDynamicLibs();
|
|
|
|
fextl::vector<char> RawFile;
|
|
union {
|
|
Elf32_Ehdr _32;
|
|
Elf64_Ehdr _64;
|
|
} Header;
|
|
|
|
union SectionHeader {
|
|
Elf32_Shdr* _32;
|
|
Elf64_Shdr* _64;
|
|
};
|
|
|
|
union ProgramHeader {
|
|
Elf32_Phdr* _32;
|
|
Elf64_Phdr* _64;
|
|
};
|
|
|
|
ELFMode Mode;
|
|
fextl::vector<SectionHeader> SectionHeaders;
|
|
fextl::vector<ProgramHeader> ProgramHeaders;
|
|
fextl::vector<ELFSymbol> Symbols;
|
|
fextl::vector<uintptr_t> UnwindEntries;
|
|
fextl::unordered_map<fextl::string, ELFSymbol*> SymbolMap;
|
|
fextl::map<uint64_t, ELFSymbol*> SymbolMapByAddress;
|
|
|
|
fextl::vector<const char*> NecessaryLibs;
|
|
|
|
uint64_t MinPhysicalMemoryLocation {0};
|
|
uint64_t MaxPhysicalMemoryLocation {0};
|
|
uint64_t PhysicalMemorySize {0};
|
|
|
|
uint64_t BRKBase {};
|
|
uint64_t BRKSize {};
|
|
ProgramHeader InterpreterHeader {};
|
|
bool DynamicProgram {false};
|
|
fextl::string DynamicLinker;
|
|
ProgramHeader TLSHeader {};
|
|
bool Loaded {false};
|
|
};
|
|
|
|
} // namespace ELFLoader
|