Merge pull request #16 from georgemoralis/dynamic_resolver
Dynamic resolver
This commit is contained in:
commit
e4047ba99c
|
@ -47,6 +47,7 @@ Module* Linker::LoadModule(const std::string& elf_name)
|
||||||
if (m->elf->isElfFile())
|
if (m->elf->isElfFile())
|
||||||
{
|
{
|
||||||
LoadModuleToMemory(m);
|
LoadModuleToMemory(m);
|
||||||
|
LoadDynamicInfo(m);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -158,3 +159,160 @@ void Linker::LoadModuleToMemory(Module* m)
|
||||||
runtime_address += instruction.info.length;
|
runtime_address += instruction.info.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Linker::LoadDynamicInfo(Module* m)
|
||||||
|
{
|
||||||
|
m->dynamic_info = new DynamicModuleInfo;
|
||||||
|
|
||||||
|
for (const auto* dyn = static_cast<elf_dynamic*>(m->m_dynamic); dyn->d_tag != DT_NULL; dyn++)
|
||||||
|
{
|
||||||
|
switch (dyn->d_tag)
|
||||||
|
{
|
||||||
|
case DT_SCE_HASH: //Offset of the hash table.
|
||||||
|
m->dynamic_info->hash_table = reinterpret_cast<void*>(static_cast<uint8_t*>(m->m_dynamic_data) + dyn->d_un.d_ptr);
|
||||||
|
break;
|
||||||
|
case DT_SCE_HASHSZ: //Size of the hash table
|
||||||
|
m->dynamic_info->hash_table_size = dyn->d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_SCE_STRTAB://Offset of the string table.
|
||||||
|
m->dynamic_info->str_table = reinterpret_cast<char*>(static_cast<uint8_t*>(m->m_dynamic_data) + dyn->d_un.d_ptr);
|
||||||
|
break;
|
||||||
|
case DT_SCE_STRSZ: //Size of the string table.
|
||||||
|
m->dynamic_info->str_table_size = dyn->d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_SCE_SYMTAB://Offset of the symbol table.
|
||||||
|
m->dynamic_info->symbol_table = reinterpret_cast<elf_symbol*>(static_cast<uint8_t*>(m->m_dynamic_data) + dyn->d_un.d_ptr);
|
||||||
|
break;
|
||||||
|
case DT_SCE_SYMTABSZ://Size of the symbol table.
|
||||||
|
m->dynamic_info->symbol_table_total_size = dyn->d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_INIT:
|
||||||
|
m->dynamic_info->init_virtual_addr = dyn->d_un.d_ptr;
|
||||||
|
break;
|
||||||
|
case DT_FINI:
|
||||||
|
m->dynamic_info->fini_virtual_addr = dyn->d_un.d_ptr;
|
||||||
|
break;
|
||||||
|
case DT_SCE_PLTGOT: //Offset of the global offset table.
|
||||||
|
m->dynamic_info->pltgot_virtual_addr = dyn->d_un.d_ptr;
|
||||||
|
break;
|
||||||
|
case DT_SCE_JMPREL: //Offset of the table containing jump slots.
|
||||||
|
m->dynamic_info->jmp_relocation_table = reinterpret_cast<elf_relocation*>(static_cast<uint8_t*>(m->m_dynamic_data) + dyn->d_un.d_ptr);
|
||||||
|
break;
|
||||||
|
case DT_SCE_PLTRELSZ: //Size of the global offset table.
|
||||||
|
m->dynamic_info->jmp_relocation_table_size = dyn->d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_SCE_PLTREL: //The type of relocations in the relocation table. Should be DT_RELA
|
||||||
|
m->dynamic_info->jmp_relocation_type = dyn->d_un.d_val;
|
||||||
|
if (m->dynamic_info->jmp_relocation_type != DT_RELA)
|
||||||
|
{
|
||||||
|
LOG_WARN_IF(debug_loader, "DT_SCE_PLTREL is NOT DT_RELA should check!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DT_SCE_RELA: //Offset of the relocation table.
|
||||||
|
m->dynamic_info->relocation_table = reinterpret_cast<elf_relocation*>(static_cast<uint8_t*>(m->m_dynamic_data) + dyn->d_un.d_ptr);
|
||||||
|
break;
|
||||||
|
case DT_SCE_RELASZ: //Size of the relocation table.
|
||||||
|
m->dynamic_info->relocation_table_size = dyn->d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_SCE_RELAENT : //The size of relocation table entries.
|
||||||
|
m->dynamic_info->relocation_table_entries_size = dyn->d_un.d_val;
|
||||||
|
if (m->dynamic_info->relocation_table_entries_size != 0x18) //this value should always be 0x18
|
||||||
|
{
|
||||||
|
LOG_WARN_IF(debug_loader, "DT_SCE_RELAENT is NOT 0x18 should check!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DT_INIT_ARRAY:// Address of the array of pointers to initialization functions
|
||||||
|
m->dynamic_info->init_array_virtual_addr = dyn->d_un.d_ptr;
|
||||||
|
break;
|
||||||
|
case DT_FINI_ARRAY: // Address of the array of pointers to termination functions
|
||||||
|
m->dynamic_info->fini_array_virtual_addr = dyn->d_un.d_ptr;
|
||||||
|
break;
|
||||||
|
case DT_INIT_ARRAYSZ://Size in bytes of the array of initialization functions
|
||||||
|
m->dynamic_info->init_array_size = dyn->d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_FINI_ARRAYSZ://Size in bytes of the array of terminationfunctions
|
||||||
|
m->dynamic_info->fini_array_size = dyn->d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_PREINIT_ARRAY://Address of the array of pointers to pre - initialization functions
|
||||||
|
m->dynamic_info->preinit_array_virtual_addr = dyn->d_un.d_ptr;
|
||||||
|
break;
|
||||||
|
case DT_PREINIT_ARRAYSZ://Size in bytes of the array of pre - initialization functions
|
||||||
|
m->dynamic_info->preinit_array_size = dyn->d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_SCE_SYMENT: //The size of symbol table entries
|
||||||
|
m->dynamic_info->symbol_table_entries_size = dyn->d_un.d_val;
|
||||||
|
if (m->dynamic_info->symbol_table_entries_size != 0x18) //this value should always be 0x18
|
||||||
|
{
|
||||||
|
LOG_WARN_IF(debug_loader, "DT_SCE_SYMENT is NOT 0x18 should check!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DT_DEBUG:
|
||||||
|
m->dynamic_info->debug = dyn->d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_TEXTREL:
|
||||||
|
m->dynamic_info->textrel = dyn->d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_FLAGS:
|
||||||
|
m->dynamic_info->flags = dyn->d_un.d_val;
|
||||||
|
if (m->dynamic_info->flags != 0x04) //this value should always be DF_TEXTREL (0x04)
|
||||||
|
{
|
||||||
|
LOG_WARN_IF(debug_loader, "DT_FLAGS is NOT 0x04 should check!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DT_NEEDED://Offset of the library string in the string table to be linked in.
|
||||||
|
if (m->dynamic_info->str_table != nullptr)//in theory this should already be filled from about just make a test case
|
||||||
|
{
|
||||||
|
m->dynamic_info->needed.push_back(m->dynamic_info->str_table + dyn->d_un.d_val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR_IF(debug_loader, "DT_NEEDED str table is not loaded should check!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DT_SCE_NEEDED_MODULE:
|
||||||
|
{
|
||||||
|
ModuleInfo info{};
|
||||||
|
info.value = dyn->d_un.d_val;
|
||||||
|
info.name = m->dynamic_info->str_table + info.name_offset;
|
||||||
|
m->dynamic_info->import_modules.push_back(info);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DT_SCE_IMPORT_LIB:
|
||||||
|
{
|
||||||
|
LibraryInfo info{};
|
||||||
|
info.value = dyn->d_un.d_val;
|
||||||
|
info.name = m->dynamic_info->str_table + info.name_offset;
|
||||||
|
m->dynamic_info->import_libs.push_back(info);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DT_SCE_FINGERPRINT:
|
||||||
|
//The fingerprint is a 24 byte (0x18) size buffer that contains a unique identifier for the given app.
|
||||||
|
//How exactly this is generated isn't known, however it is not necessary to have a valid fingerprint.
|
||||||
|
//While an invalid fingerprint will cause a warning to be printed to the kernel log, the ELF will still load and run.
|
||||||
|
LOG_INFO_IF(debug_loader, "unsupported DT_SCE_FINGERPRINT value = ..........: {:#018x}\n", dyn->d_un.d_val);
|
||||||
|
break;
|
||||||
|
case DT_SCE_IMPORT_LIB_ATTR:
|
||||||
|
//The upper 32-bits should contain the module index multiplied by 0x10000. The lower 32-bits should be a constant 0x9.
|
||||||
|
LOG_INFO_IF(debug_loader, "unsupported DT_SCE_IMPORT_LIB_ATTR value = ..........: {:#018x}\n", dyn->d_un.d_val);
|
||||||
|
break;
|
||||||
|
case DT_SCE_ORIGINAL_FILENAME:
|
||||||
|
m->dynamic_info->filename = m->dynamic_info->str_table + dyn->d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_SCE_MODULE_INFO://probably only useable in shared modules
|
||||||
|
{
|
||||||
|
ModuleInfo info{};
|
||||||
|
info.value = dyn->d_un.d_val;
|
||||||
|
info.name = m->dynamic_info->str_table + info.name_offset;
|
||||||
|
m->dynamic_info->export_modules.push_back(info);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DT_SCE_MODULE_ATTR:
|
||||||
|
//TODO?
|
||||||
|
LOG_INFO_IF(debug_loader, "unsupported DT_SCE_MODULE_ATTR value = ..........: {:#018x}\n", dyn->d_un.d_val);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_INFO_IF(debug_loader, "unsupported dynamic tag ..........: {:#018x}\n", dyn->d_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,8 @@
|
||||||
#include "../../Loader/Elf.h"
|
#include "../../Loader/Elf.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
struct DynamicModuleInfo;
|
||||||
|
|
||||||
/*this struct keeps neccesary info about loaded modules.Main executeable is included too as well*/
|
/*this struct keeps neccesary info about loaded modules.Main executeable is included too as well*/
|
||||||
struct Module
|
struct Module
|
||||||
{
|
{
|
||||||
|
@ -11,6 +13,81 @@ struct Module
|
||||||
|
|
||||||
void* m_dynamic = nullptr;
|
void* m_dynamic = nullptr;
|
||||||
void* m_dynamic_data = nullptr;
|
void* m_dynamic_data = nullptr;
|
||||||
|
DynamicModuleInfo* dynamic_info = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ModuleInfo
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
u64 value;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u32 name_offset;
|
||||||
|
u08 version_minor;
|
||||||
|
u08 version_major;
|
||||||
|
u16 id;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LibraryInfo
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
u64 value;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u32 name_offset;
|
||||||
|
u16 version;
|
||||||
|
u16 id;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicModuleInfo
|
||||||
|
{
|
||||||
|
void* hash_table = nullptr;
|
||||||
|
u64 hash_table_size = 0;
|
||||||
|
|
||||||
|
char* str_table = nullptr;
|
||||||
|
u64 str_table_size = 0;
|
||||||
|
|
||||||
|
elf_symbol* symbol_table = nullptr;
|
||||||
|
u64 symbol_table_total_size = 0;
|
||||||
|
u64 symbol_table_entries_size = 0;
|
||||||
|
|
||||||
|
u64 init_virtual_addr = 0;
|
||||||
|
u64 fini_virtual_addr = 0;
|
||||||
|
u64 pltgot_virtual_addr = 0;
|
||||||
|
u64 init_array_virtual_addr = 0;
|
||||||
|
u64 fini_array_virtual_addr = 0;
|
||||||
|
u64 preinit_array_virtual_addr = 0;
|
||||||
|
u64 init_array_size = 0;
|
||||||
|
u64 fini_array_size = 0;
|
||||||
|
u64 preinit_array_size = 0;
|
||||||
|
|
||||||
|
elf_relocation* jmp_relocation_table = nullptr;
|
||||||
|
u64 jmp_relocation_table_size = 0;
|
||||||
|
s64 jmp_relocation_type = 0;
|
||||||
|
|
||||||
|
elf_relocation* relocation_table = nullptr;
|
||||||
|
u64 relocation_table_size = 0;
|
||||||
|
u64 relocation_table_entries_size = 0;
|
||||||
|
|
||||||
|
u64 debug = 0;
|
||||||
|
u64 textrel = 0;
|
||||||
|
u64 flags = 0;
|
||||||
|
|
||||||
|
std::vector<const char*> needed;
|
||||||
|
std::vector<ModuleInfo> import_modules;
|
||||||
|
std::vector<ModuleInfo> export_modules;
|
||||||
|
std::vector<LibraryInfo> import_libs;
|
||||||
|
|
||||||
|
std::string filename;//filename with absolute path
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Linker
|
class Linker
|
||||||
|
@ -22,6 +99,7 @@ public:
|
||||||
Module* LoadModule(const std::string& elf_name);
|
Module* LoadModule(const std::string& elf_name);
|
||||||
Module* FindModule(/*u32 id*/);
|
Module* FindModule(/*u32 id*/);
|
||||||
void LoadModuleToMemory(Module* m);
|
void LoadModuleToMemory(Module* m);
|
||||||
|
void LoadDynamicInfo(Module* program);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Module*> m_modules;
|
std::vector<Module*> m_modules;
|
||||||
|
|
|
@ -323,6 +323,71 @@ struct elf_program_id_header
|
||||||
u64 firmver;
|
u64 firmver;
|
||||||
u08 digest[32];
|
u08 digest[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr s64 DT_NULL = 0;
|
||||||
|
constexpr s64 DT_NEEDED = 0x00000001;
|
||||||
|
constexpr s64 DT_RELA = 0x00000007;
|
||||||
|
constexpr s64 DT_INIT = 0x0000000c;
|
||||||
|
constexpr s64 DT_FINI = 0x0000000d;
|
||||||
|
constexpr s64 DT_DEBUG = 0x00000015;
|
||||||
|
constexpr s64 DT_TEXTREL = 0x00000016;
|
||||||
|
constexpr s64 DT_INIT_ARRAY = 0x00000019;
|
||||||
|
constexpr s64 DT_FINI_ARRAY = 0x0000001a;
|
||||||
|
constexpr s64 DT_INIT_ARRAYSZ = 0x0000001b;
|
||||||
|
constexpr s64 DT_FINI_ARRAYSZ = 0x0000001c;
|
||||||
|
constexpr s64 DT_FLAGS = 0x0000001e;
|
||||||
|
constexpr s64 DT_PREINIT_ARRAY = 0x00000020;
|
||||||
|
constexpr s64 DT_PREINIT_ARRAYSZ = 0x00000021;
|
||||||
|
constexpr s64 DT_SCE_FINGERPRINT = 0x61000007;
|
||||||
|
constexpr s64 DT_SCE_ORIGINAL_FILENAME = 0x61000009;
|
||||||
|
constexpr s64 DT_SCE_MODULE_INFO = 0x6100000d;
|
||||||
|
constexpr s64 DT_SCE_NEEDED_MODULE = 0x6100000f;
|
||||||
|
constexpr s64 DT_SCE_MODULE_ATTR = 0x61000011;
|
||||||
|
constexpr s64 DT_SCE_IMPORT_LIB = 0x61000015;
|
||||||
|
constexpr s64 DT_SCE_IMPORT_LIB_ATTR = 0x61000019;
|
||||||
|
constexpr s64 DT_SCE_HASH = 0x61000025;
|
||||||
|
constexpr s64 DT_SCE_PLTGOT = 0x61000027;
|
||||||
|
constexpr s64 DT_SCE_JMPREL = 0x61000029;
|
||||||
|
constexpr s64 DT_SCE_PLTREL = 0x6100002b;
|
||||||
|
constexpr s64 DT_SCE_PLTRELSZ = 0x6100002d;
|
||||||
|
constexpr s64 DT_SCE_RELA = 0x6100002f;
|
||||||
|
constexpr s64 DT_SCE_RELASZ = 0x61000031;
|
||||||
|
constexpr s64 DT_SCE_RELAENT = 0x61000033;
|
||||||
|
constexpr s64 DT_SCE_SYMENT = 0x6100003b;
|
||||||
|
constexpr s64 DT_SCE_HASHSZ = 0x6100003d;
|
||||||
|
constexpr s64 DT_SCE_STRTAB = 0x61000035;
|
||||||
|
constexpr s64 DT_SCE_STRSZ = 0x61000037;
|
||||||
|
constexpr s64 DT_SCE_SYMTAB = 0x61000039;
|
||||||
|
constexpr s64 DT_SCE_SYMTABSZ = 0x6100003f;
|
||||||
|
|
||||||
|
|
||||||
|
struct elf_dynamic
|
||||||
|
{
|
||||||
|
s64 d_tag;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
u64 d_val;
|
||||||
|
u64 d_ptr;
|
||||||
|
} d_un;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct elf_symbol
|
||||||
|
{
|
||||||
|
u32 st_name;
|
||||||
|
u08 st_info;
|
||||||
|
u08 st_other;
|
||||||
|
u16 st_shndx;
|
||||||
|
u64 st_value;
|
||||||
|
u64 st_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct elf_relocation
|
||||||
|
{
|
||||||
|
u64 rel_offset;
|
||||||
|
u64 rel_info;
|
||||||
|
s64 rel_addend;
|
||||||
|
};
|
||||||
|
|
||||||
class Elf
|
class Elf
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
11
src/main.cpp
11
src/main.cpp
|
@ -26,17 +26,21 @@
|
||||||
#endif
|
#endif
|
||||||
#include "Core/PS4/Linker.h"
|
#include "Core/PS4/Linker.h"
|
||||||
#include "Util/Singleton.h"
|
#include "Util/Singleton.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <Zydis/Zydis.h>
|
||||||
|
|
||||||
// Main code
|
// Main code
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
logging::init(true);//init logging
|
logging::init(true);//init logging
|
||||||
const char* const path = argv[1]; //argument 1 is the path of self file to boot
|
const char* const path = "videoout_basic.elf";// argv[1]; //argument 1 is the path of self file to boot
|
||||||
auto* linker = Singleton<Linker>::Instance();
|
auto* linker = Singleton<Linker>::Instance();
|
||||||
auto *module =linker->LoadModule(path);//load main executable
|
auto *module =linker->LoadModule(path);//load main executable
|
||||||
|
|
||||||
|
#if 0
|
||||||
// Setup SDL
|
// Setup SDL
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD) != 0)
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD) != 0)
|
||||||
{
|
{
|
||||||
|
@ -215,6 +219,7 @@ int main(int argc, char* argv[])
|
||||||
SDL_GL_DeleteContext(gl_context);
|
SDL_GL_DeleteContext(gl_context);
|
||||||
SDL_DestroyWindow(window);
|
SDL_DestroyWindow(window);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue