mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-05-18 17:34:52 +00:00
common: Rewrite logging based on cut down citra logger (#86)
* common: Rewrite logging based on cut down Citra logger * code: Misc fixes * core: Bring back tls handler * linker: Cleanup * config: Remove log level * logging: Enable console output by default * core: Fix windows build
This commit is contained in:
parent
b3084646a8
commit
79d6c8a377
70 changed files with 3212 additions and 1541 deletions
|
@ -2,31 +2,29 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <Zydis/Zydis.h>
|
||||
#include <fmt/core.h>
|
||||
#include "common/log.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/aerolib/aerolib.h"
|
||||
#include "core/aerolib/stubs.h"
|
||||
#include "core/hle/libraries/libkernel/thread_management.h"
|
||||
#include "core/linker.h"
|
||||
#include "core/tls.h"
|
||||
#include "core/virtual_memory.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
constexpr bool debug_loader = true;
|
||||
static constexpr u64 LoadAddress = SYSTEM_RESERVED + CODE_BASE_OFFSET;
|
||||
|
||||
static u64 g_load_addr = SYSTEM_RESERVED + CODE_BASE_OFFSET;
|
||||
|
||||
static u64 get_aligned_size(const elf_program_header& phdr) {
|
||||
static u64 GetAlignedSize(const elf_program_header& phdr) {
|
||||
return (phdr.p_align != 0 ? (phdr.p_memsz + (phdr.p_align - 1)) & ~(phdr.p_align - 1)
|
||||
: phdr.p_memsz);
|
||||
}
|
||||
|
||||
static u64 calculate_base_size(const elf_header& ehdr, std::span<const elf_program_header> phdr) {
|
||||
static u64 CalculateBaseSize(const elf_header& ehdr, std::span<const elf_program_header> phdr) {
|
||||
u64 base_size = 0;
|
||||
for (u16 i = 0; i < ehdr.e_phnum; i++) {
|
||||
if (phdr[i].p_memsz != 0 && (phdr[i].p_type == PT_LOAD || phdr[i].p_type == PT_SCE_RELRO)) {
|
||||
u64 last_addr = phdr[i].p_vaddr + get_aligned_size(phdr[i]);
|
||||
u64 last_addr = phdr[i].p_vaddr + GetAlignedSize(phdr[i]);
|
||||
if (last_addr > base_size) {
|
||||
base_size = last_addr;
|
||||
}
|
||||
|
@ -35,7 +33,7 @@ static u64 calculate_base_size(const elf_header& ehdr, std::span<const elf_progr
|
|||
return base_size;
|
||||
}
|
||||
|
||||
static std::string encodeId(u64 nVal) {
|
||||
static std::string EncodeId(u64 nVal) {
|
||||
std::string enc;
|
||||
const char pCodes[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
|
||||
if (nVal < 0x40u) {
|
||||
|
@ -57,97 +55,37 @@ Linker::Linker() = default;
|
|||
|
||||
Linker::~Linker() = default;
|
||||
|
||||
Module* Linker::LoadModule(const std::string& elf_name) {
|
||||
Module* Linker::LoadModule(const std::filesystem::path& elf_name) {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
|
||||
auto& m = m_modules.emplace_back();
|
||||
m.linker = this;
|
||||
m.elf.Open(elf_name);
|
||||
if (!std::filesystem::exists(elf_name)) {
|
||||
LOG_ERROR(Core_Linker, "Provided module {} does not exist", elf_name.string());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (m.elf.isElfFile()) {
|
||||
LoadModuleToMemory(&m);
|
||||
LoadDynamicInfo(&m);
|
||||
LoadSymbols(&m);
|
||||
Relocate(&m);
|
||||
auto& m = m_modules.emplace_back();
|
||||
m = std::make_unique<Module>();
|
||||
m->elf.Open(elf_name);
|
||||
|
||||
if (m->elf.IsElfFile()) {
|
||||
LoadModuleToMemory(m.get());
|
||||
LoadDynamicInfo(m.get());
|
||||
LoadSymbols(m.get());
|
||||
Relocate(m.get());
|
||||
} else {
|
||||
m_modules.pop_back();
|
||||
return nullptr; // It is not a valid elf file //TODO check it why!
|
||||
}
|
||||
|
||||
return &m;
|
||||
return m.get();
|
||||
}
|
||||
|
||||
Module* Linker::FindModule(/*u32 id*/) {
|
||||
Module* Linker::FindModule(u32 id) {
|
||||
// TODO atm we only have 1 module so we don't need to iterate on vector
|
||||
if (m_modules.empty()) [[unlikely]] {
|
||||
return nullptr;
|
||||
}
|
||||
return &m_modules[0];
|
||||
}
|
||||
|
||||
struct TLSPattern {
|
||||
uint8_t pattern[5];
|
||||
uint8_t pattern_size;
|
||||
uint8_t imm_size;
|
||||
uint8_t target_reg;
|
||||
};
|
||||
|
||||
constexpr TLSPattern tls_patterns[] = {
|
||||
{{0x64, 0x48, 0xA1},
|
||||
3,
|
||||
8,
|
||||
0}, // 64 48 A1 | 00 00 00 00 00 00 00 00 # mov rax, qword ptr fs:[64b imm]
|
||||
|
||||
{{0x64, 0x48, 0x8B, 0x4, 0x25},
|
||||
5,
|
||||
4,
|
||||
0}, // 64 48 8B 04 25 | 00 00 00 00 # mov rax,qword ptr fs:[0]
|
||||
{{0x64, 0x48, 0x8B, 0xC, 0x25}, 5, 4, 1}, // rcx
|
||||
{{0x64, 0x48, 0x8B, 0x14, 0x25}, 5, 4, 2}, // rdx
|
||||
{{0x64, 0x48, 0x8B, 0x1C, 0x25}, 5, 4, 3}, // rbx
|
||||
{{0x64, 0x48, 0x8B, 0x24, 0x25}, 5, 4, 4}, // rsp
|
||||
{{0x64, 0x48, 0x8B, 0x2C, 0x25}, 5, 4, 5}, // rbp
|
||||
{{0x64, 0x48, 0x8B, 0x34, 0x25}, 5, 4, 6}, // rsi
|
||||
{{0x64, 0x48, 0x8B, 0x3C, 0x25}, 5, 4, 7}, // rdi
|
||||
{{0x64, 0x4C, 0x8B, 0x4, 0x25}, 5, 4, 8}, // r8
|
||||
{{0x64, 0x4C, 0x8B, 0xC, 0x25}, 5, 4, 9}, // r9
|
||||
{{0x64, 0x4C, 0x8B, 0x14, 0x25}, 5, 4, 10}, // r10
|
||||
{{0x64, 0x4C, 0x8B, 0x1C, 0x25}, 5, 4, 11}, // r11
|
||||
{{0x64, 0x4C, 0x8B, 0x24, 0x25}, 5, 4, 12}, // r12
|
||||
{{0x64, 0x4C, 0x8B, 0x2C, 0x25}, 5, 4, 13}, // r13
|
||||
{{0x64, 0x4C, 0x8B, 0x34, 0x25}, 5, 4, 14}, // r14
|
||||
{{0x64, 0x4C, 0x8B, 0x3C, 0x25}, 5, 4, 15}, // r15
|
||||
};
|
||||
|
||||
void PatchTLS(u64 segment_addr, u64 segment_size) {
|
||||
uint8_t* code = (uint8_t*)segment_addr;
|
||||
auto remaining_size = segment_size;
|
||||
|
||||
while (remaining_size) {
|
||||
for (auto& tls_pattern : tls_patterns) {
|
||||
auto total_size = tls_pattern.pattern_size + tls_pattern.imm_size;
|
||||
if (remaining_size >= total_size) {
|
||||
if (memcmp(code, tls_pattern.pattern, tls_pattern.pattern_size) == 0) {
|
||||
if (tls_pattern.imm_size == 4)
|
||||
printf("PATTERN32 FOUND @ %p, reg: %d offset: %X\n", code,
|
||||
tls_pattern.target_reg,
|
||||
*(uint32_t*)(code + tls_pattern.pattern_size));
|
||||
else
|
||||
printf("PATTERN64 FOUND @ %p, reg: %d offset: %lX\n", code,
|
||||
tls_pattern.target_reg,
|
||||
*(uint64_t*)(code + tls_pattern.pattern_size));
|
||||
code[0] = 0xcd;
|
||||
code[1] = 0x80 + tls_pattern.target_reg;
|
||||
code[2] = tls_pattern.pattern_size | (tls_pattern.imm_size << 4);
|
||||
code += total_size - 1;
|
||||
remaining_size -= total_size - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
code++;
|
||||
remaining_size--;
|
||||
}
|
||||
return m_modules[0].get();
|
||||
}
|
||||
|
||||
void Linker::LoadModuleToMemory(Module* m) {
|
||||
|
@ -155,18 +93,18 @@ void Linker::LoadModuleToMemory(Module* m) {
|
|||
const auto elf_header = m->elf.GetElfHeader();
|
||||
const auto elf_pheader = m->elf.GetProgramHeader();
|
||||
|
||||
u64 base_size = calculate_base_size(elf_header, elf_pheader);
|
||||
u64 base_size = CalculateBaseSize(elf_header, elf_pheader);
|
||||
m->aligned_base_size = (base_size & ~(static_cast<u64>(0x1000) - 1)) +
|
||||
0x1000; // align base size to 0x1000 block size (TODO is that the default
|
||||
// block size or it can be changed?
|
||||
|
||||
m->base_virtual_addr = VirtualMemory::memory_alloc(g_load_addr, m->aligned_base_size,
|
||||
m->base_virtual_addr = VirtualMemory::memory_alloc(LoadAddress, m->aligned_base_size,
|
||||
VirtualMemory::MemoryMode::ExecuteReadWrite);
|
||||
|
||||
LOG_INFO_IF(debug_loader, "====Load Module to Memory ========\n");
|
||||
LOG_INFO_IF(debug_loader, "base_virtual_addr ......: {:#018x}\n", m->base_virtual_addr);
|
||||
LOG_INFO_IF(debug_loader, "base_size ..............: {:#018x}\n", base_size);
|
||||
LOG_INFO_IF(debug_loader, "aligned_base_size ......: {:#018x}\n", m->aligned_base_size);
|
||||
LOG_INFO(Core_Linker, "====Load Module to Memory ========");
|
||||
LOG_INFO(Core_Linker, "base_virtual_addr ......: {:#018x}", m->base_virtual_addr);
|
||||
LOG_INFO(Core_Linker, "base_size ..............: {:#018x}", base_size);
|
||||
LOG_INFO(Core_Linker, "aligned_base_size ......: {:#018x}", m->aligned_base_size);
|
||||
|
||||
for (u16 i = 0; i < elf_header.e_phnum; i++) {
|
||||
switch (elf_pheader[i].p_type) {
|
||||
|
@ -175,14 +113,14 @@ void Linker::LoadModuleToMemory(Module* m) {
|
|||
if (elf_pheader[i].p_memsz != 0) {
|
||||
u64 segment_addr = elf_pheader[i].p_vaddr + m->base_virtual_addr;
|
||||
u64 segment_file_size = elf_pheader[i].p_filesz;
|
||||
u64 segment_memory_size = get_aligned_size(elf_pheader[i]);
|
||||
u64 segment_memory_size = GetAlignedSize(elf_pheader[i]);
|
||||
auto segment_mode = m->elf.ElfPheaderFlagsStr(elf_pheader[i].p_flags);
|
||||
LOG_INFO_IF(debug_loader, "program header = [{}] type = {}\n", i,
|
||||
m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
|
||||
LOG_INFO_IF(debug_loader, "segment_addr ..........: {:#018x}\n", segment_addr);
|
||||
LOG_INFO_IF(debug_loader, "segment_file_size .....: {}\n", segment_file_size);
|
||||
LOG_INFO_IF(debug_loader, "segment_memory_size ...: {}\n", segment_memory_size);
|
||||
LOG_INFO_IF(debug_loader, "segment_mode ..........: {}\n", segment_mode);
|
||||
LOG_INFO(Core_Linker, "program header = [{}] type = {}", i,
|
||||
m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
|
||||
LOG_INFO(Core_Linker, "segment_addr ..........: {:#018x}", segment_addr);
|
||||
LOG_INFO(Core_Linker, "segment_file_size .....: {}", segment_file_size);
|
||||
LOG_INFO(Core_Linker, "segment_memory_size ...: {}", segment_memory_size);
|
||||
LOG_INFO(Core_Linker, "segment_mode ..........: {}", segment_mode);
|
||||
|
||||
m->elf.LoadSegment(segment_addr, elf_pheader[i].p_offset, segment_file_size);
|
||||
|
||||
|
@ -190,8 +128,8 @@ void Linker::LoadModuleToMemory(Module* m) {
|
|||
PatchTLS(segment_addr, segment_file_size);
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR_IF(debug_loader, "p_memsz==0 in type {}\n",
|
||||
m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
|
||||
LOG_ERROR(Core_Linker, "p_memsz==0 in type {}",
|
||||
m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
|
||||
}
|
||||
break;
|
||||
case PT_DYNAMIC:
|
||||
|
@ -200,8 +138,8 @@ void Linker::LoadModuleToMemory(Module* m) {
|
|||
m->elf.LoadSegment(reinterpret_cast<u64>(m->m_dynamic.data()),
|
||||
elf_pheader[i].p_offset, elf_pheader[i].p_filesz);
|
||||
} else {
|
||||
LOG_ERROR_IF(debug_loader, "p_filesz==0 in type {}\n",
|
||||
m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
|
||||
LOG_ERROR(Core_Linker, "p_filesz==0 in type {}",
|
||||
m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
|
||||
}
|
||||
break;
|
||||
case PT_SCE_DYNLIBDATA:
|
||||
|
@ -210,23 +148,23 @@ void Linker::LoadModuleToMemory(Module* m) {
|
|||
m->elf.LoadSegment(reinterpret_cast<u64>(m->m_dynamic_data.data()),
|
||||
elf_pheader[i].p_offset, elf_pheader[i].p_filesz);
|
||||
} else {
|
||||
LOG_ERROR_IF(debug_loader, "p_filesz==0 in type {}\n",
|
||||
m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
|
||||
LOG_ERROR(Core_Linker, "p_filesz==0 in type {}",
|
||||
m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
|
||||
}
|
||||
break;
|
||||
case PT_TLS:
|
||||
m->tls.image_virtual_addr = elf_pheader[i].p_vaddr + m->base_virtual_addr;
|
||||
m->tls.image_size = get_aligned_size(elf_pheader[i]);
|
||||
LOG_INFO_IF(debug_loader, "tls virtual address ={:#x}\n", m->tls.image_virtual_addr);
|
||||
LOG_INFO_IF(debug_loader, "tls image size ={}\n", m->tls.image_size);
|
||||
m->tls.image_size = GetAlignedSize(elf_pheader[i]);
|
||||
LOG_INFO(Core_Linker, "tls virtual address ={:#x}", m->tls.image_virtual_addr);
|
||||
LOG_INFO(Core_Linker, "tls image size ={}", m->tls.image_size);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR_IF(debug_loader, "Unimplemented type {}\n",
|
||||
m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
|
||||
LOG_ERROR(Core_Linker, "Unimplemented type {}",
|
||||
m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type));
|
||||
}
|
||||
}
|
||||
LOG_INFO_IF(debug_loader, "program entry addr ..........: {:#018x}\n",
|
||||
m->elf.GetElfEntry() + m->base_virtual_addr);
|
||||
LOG_INFO(Core_Linker, "program entry addr ..........: {:#018x}",
|
||||
m->elf.GetElfEntry() + m->base_virtual_addr);
|
||||
}
|
||||
|
||||
void Linker::LoadDynamicInfo(Module* m) {
|
||||
|
@ -273,7 +211,7 @@ void Linker::LoadDynamicInfo(Module* m) {
|
|||
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!");
|
||||
LOG_WARNING(Core_Linker, "DT_SCE_PLTREL is NOT DT_RELA should check!");
|
||||
}
|
||||
break;
|
||||
case DT_SCE_RELA: // Offset of the relocation table.
|
||||
|
@ -288,7 +226,7 @@ void Linker::LoadDynamicInfo(Module* m) {
|
|||
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!");
|
||||
LOG_WARNING(Core_Linker, "DT_SCE_RELAENT is NOT 0x18 should check!");
|
||||
}
|
||||
break;
|
||||
case DT_INIT_ARRAY: // Address of the array of pointers to initialization functions
|
||||
|
@ -314,7 +252,7 @@ void Linker::LoadDynamicInfo(Module* m) {
|
|||
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!");
|
||||
LOG_WARNING(Core_Linker, "DT_SCE_SYMENT is NOT 0x18 should check!");
|
||||
}
|
||||
break;
|
||||
case DT_DEBUG:
|
||||
|
@ -327,7 +265,7 @@ void Linker::LoadDynamicInfo(Module* m) {
|
|||
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!");
|
||||
LOG_WARNING(Core_Linker, "DT_FLAGS is NOT 0x04 should check!");
|
||||
}
|
||||
break;
|
||||
case DT_NEEDED: // Offset of the library string in the string table to be linked in.
|
||||
|
@ -336,21 +274,21 @@ void Linker::LoadDynamicInfo(Module* m) {
|
|||
{
|
||||
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!");
|
||||
LOG_ERROR(Core_Linker, "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;
|
||||
info.enc_id = encodeId(info.id);
|
||||
info.enc_id = EncodeId(info.id);
|
||||
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;
|
||||
info.enc_id = encodeId(info.id);
|
||||
info.enc_id = EncodeId(info.id);
|
||||
m->dynamic_info.import_libs.push_back(info);
|
||||
} break;
|
||||
case DT_SCE_FINGERPRINT:
|
||||
|
@ -358,16 +296,14 @@ void Linker::LoadDynamicInfo(Module* m) {
|
|||
// 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);
|
||||
LOG_INFO(Core_Linker, "unsupported DT_SCE_FINGERPRINT value = ..........: {:#018x}",
|
||||
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);
|
||||
LOG_INFO(Core_Linker, "unsupported DT_SCE_IMPORT_LIB_ATTR value = ......: {:#018x}",
|
||||
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;
|
||||
|
@ -377,24 +313,23 @@ void Linker::LoadDynamicInfo(Module* m) {
|
|||
ModuleInfo info{};
|
||||
info.value = dyn->d_un.d_val;
|
||||
info.name = m->dynamic_info.str_table + info.name_offset;
|
||||
info.enc_id = encodeId(info.id);
|
||||
info.enc_id = EncodeId(info.id);
|
||||
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);
|
||||
LOG_INFO(Core_Linker, "unsupported DT_SCE_MODULE_ATTR value = ..........: {:#018x}",
|
||||
dyn->d_un.d_val);
|
||||
break;
|
||||
case DT_SCE_EXPORT_LIB: {
|
||||
LibraryInfo info{};
|
||||
info.value = dyn->d_un.d_val;
|
||||
info.name = m->dynamic_info.str_table + info.name_offset;
|
||||
info.enc_id = encodeId(info.id);
|
||||
info.enc_id = EncodeId(info.id);
|
||||
m->dynamic_info.export_libs.push_back(info);
|
||||
} break;
|
||||
default:
|
||||
LOG_INFO_IF(debug_loader, "unsupported dynamic tag ..........: {:#018x}\n", dyn->d_tag);
|
||||
LOG_INFO(Core_Linker, "unsupported dynamic tag ..........: {:#018x}", dyn->d_tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -442,7 +377,7 @@ const LibraryInfo* Linker::FindLibrary(const Module& m, const std::string& id) {
|
|||
void Linker::LoadSymbols(Module* m) {
|
||||
if (m->dynamic_info.symbol_table == nullptr || m->dynamic_info.str_table == nullptr ||
|
||||
m->dynamic_info.symbol_table_total_size == 0) {
|
||||
LOG_INFO_IF(debug_loader, "Symbol table not found!\n");
|
||||
LOG_INFO(Core_Linker, "Symbol table not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -466,8 +401,8 @@ void Linker::LoadSymbols(Module* m) {
|
|||
case STB_WEAK:
|
||||
break;
|
||||
default:
|
||||
LOG_INFO_IF(debug_loader, "Unsupported bind {} for name symbol {} \n", bind,
|
||||
ids.at(0));
|
||||
LOG_INFO(Core_Linker, "Unsupported bind {} for name symbol {}", bind,
|
||||
ids.at(0));
|
||||
continue;
|
||||
}
|
||||
switch (type) {
|
||||
|
@ -475,16 +410,16 @@ void Linker::LoadSymbols(Module* m) {
|
|||
case STT_FUN:
|
||||
break;
|
||||
default:
|
||||
LOG_INFO_IF(debug_loader, "Unsupported type {} for name symbol {} \n", type,
|
||||
ids.at(0));
|
||||
LOG_INFO(Core_Linker, "Unsupported type {} for name symbol {}", type,
|
||||
ids.at(0));
|
||||
continue;
|
||||
}
|
||||
switch (visibility) {
|
||||
case STV_DEFAULT:
|
||||
break;
|
||||
default:
|
||||
LOG_INFO_IF(debug_loader, "Unsupported visibility {} for name symbol {} \n",
|
||||
visibility, ids.at(0));
|
||||
LOG_INFO(Core_Linker, "Unsupported visibility {} for name symbol {}",
|
||||
visibility, ids.at(0));
|
||||
continue;
|
||||
}
|
||||
// if st_value!=0 then it's export symbol
|
||||
|
@ -515,97 +450,98 @@ void Linker::LoadSymbols(Module* m) {
|
|||
m->import_sym.AddSymbol(sym_r, 0);
|
||||
}
|
||||
|
||||
LOG_INFO_IF(
|
||||
debug_loader,
|
||||
"name {} function {} library {} module {} bind {} type {} visibility {}\n",
|
||||
ids.at(0), nidName, library->name, module->name, bind, type, visibility);
|
||||
LOG_INFO(Core_Linker,
|
||||
"name = {}, function = {}, library = {}, module = {}, bind = {}, type = "
|
||||
"{}, visibility = {}",
|
||||
ids.at(0), nidName, library->name, module->name, bind, type, visibility);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static void relocate(u32 idx, elf_relocation* rel, Module* m, bool isJmpRel) {
|
||||
auto type = rel->GetType();
|
||||
auto symbol = rel->GetSymbol();
|
||||
auto addend = rel->rel_addend;
|
||||
auto* symbolsTlb = m->dynamic_info.symbol_table;
|
||||
auto* namesTlb = m->dynamic_info.str_table;
|
||||
|
||||
u64 rel_value = 0;
|
||||
u64 rel_base_virtual_addr = m->base_virtual_addr;
|
||||
u64 rel_virtual_addr = m->base_virtual_addr + rel->rel_offset;
|
||||
bool rel_isResolved = false;
|
||||
u8 rel_sym_type = 0;
|
||||
std::string rel_name;
|
||||
|
||||
switch (type) {
|
||||
case R_X86_64_RELATIVE:
|
||||
if (symbol != 0) // should be always zero
|
||||
{
|
||||
// LOG_INFO_IF(debug_loader, "R_X86_64_RELATIVE symbol not zero = {:#010x}\n", type,
|
||||
// symbol);//found it openorbis but i am not sure it worth logging
|
||||
}
|
||||
rel_value = rel_base_virtual_addr + addend;
|
||||
rel_isResolved = true;
|
||||
break;
|
||||
case R_X86_64_64:
|
||||
case R_X86_64_JUMP_SLOT: // similar but addend is not take into account
|
||||
{
|
||||
auto sym = symbolsTlb[symbol];
|
||||
auto sym_bind = sym.GetBind();
|
||||
auto sym_type = sym.GetType();
|
||||
auto sym_visibility = sym.GetVisibility();
|
||||
u64 symbol_vitrual_addr = 0;
|
||||
Loader::SymbolRecord symrec{};
|
||||
switch (sym_type) {
|
||||
case STT_FUN:
|
||||
rel_sym_type = 2;
|
||||
break;
|
||||
case STT_OBJECT:
|
||||
rel_sym_type = 1;
|
||||
break;
|
||||
default:
|
||||
LOG_INFO_IF(debug_loader, "unknown symbol type {}\n", sym_type);
|
||||
}
|
||||
if (sym_visibility != 0) // should be zero log if else
|
||||
{
|
||||
LOG_INFO_IF(debug_loader, "symbol visilibity !=0\n");
|
||||
}
|
||||
switch (sym_bind) {
|
||||
case STB_GLOBAL:
|
||||
rel_name = namesTlb + sym.st_name;
|
||||
m->linker->Resolve(rel_name, rel_sym_type, m, &symrec);
|
||||
symbol_vitrual_addr = symrec.virtual_address;
|
||||
rel_isResolved = (symbol_vitrual_addr != 0);
|
||||
|
||||
rel_name = symrec.name;
|
||||
if (type == R_X86_64_JUMP_SLOT) {
|
||||
addend = 0;
|
||||
}
|
||||
rel_value = (rel_isResolved ? symbol_vitrual_addr + addend : 0);
|
||||
if (!rel_isResolved) {
|
||||
LOG_INFO_IF(debug_loader,
|
||||
"R_X86_64_64-R_X86_64_JUMP_SLOT sym_type {} bind STB_GLOBAL symbol : "
|
||||
"{:#010x}\n",
|
||||
sym_type, symbol);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_INFO_IF(debug_loader, "UNK bind {}\n", sym_bind);
|
||||
}
|
||||
|
||||
} break;
|
||||
default:
|
||||
LOG_INFO_IF(debug_loader, "UNK type {:#010x} rel symbol : {:#010x}\n", type, symbol);
|
||||
}
|
||||
|
||||
if (rel_isResolved) {
|
||||
VirtualMemory::memory_patch(rel_virtual_addr, rel_value);
|
||||
} else {
|
||||
LOG_INFO_IF(debug_loader, "function not patched! {}\n", rel_name);
|
||||
}
|
||||
}
|
||||
|
||||
void Linker::Relocate(Module* m) {
|
||||
const auto relocate = [this](u32 idx, elf_relocation* rel, Module* m, bool isJmpRel) {
|
||||
auto type = rel->GetType();
|
||||
auto symbol = rel->GetSymbol();
|
||||
auto addend = rel->rel_addend;
|
||||
auto* symbolsTlb = m->dynamic_info.symbol_table;
|
||||
auto* namesTlb = m->dynamic_info.str_table;
|
||||
|
||||
u64 rel_value = 0;
|
||||
u64 rel_base_virtual_addr = m->base_virtual_addr;
|
||||
u64 rel_virtual_addr = m->base_virtual_addr + rel->rel_offset;
|
||||
bool rel_isResolved = false;
|
||||
u8 rel_sym_type = 0;
|
||||
std::string rel_name;
|
||||
|
||||
switch (type) {
|
||||
case R_X86_64_RELATIVE:
|
||||
if (symbol != 0) // should be always zero
|
||||
{
|
||||
// LOG_INFO(Core_Linker, "R_X86_64_RELATIVE symbol not zero = {:#010x}\n", type,
|
||||
// symbol);//found it openorbis but i am not sure it worth logging
|
||||
}
|
||||
rel_value = rel_base_virtual_addr + addend;
|
||||
rel_isResolved = true;
|
||||
break;
|
||||
case R_X86_64_64:
|
||||
case R_X86_64_JUMP_SLOT: // similar but addend is not take into account
|
||||
{
|
||||
auto sym = symbolsTlb[symbol];
|
||||
auto sym_bind = sym.GetBind();
|
||||
auto sym_type = sym.GetType();
|
||||
auto sym_visibility = sym.GetVisibility();
|
||||
u64 symbol_vitrual_addr = 0;
|
||||
Loader::SymbolRecord symrec{};
|
||||
switch (sym_type) {
|
||||
case STT_FUN:
|
||||
rel_sym_type = 2;
|
||||
break;
|
||||
case STT_OBJECT:
|
||||
rel_sym_type = 1;
|
||||
break;
|
||||
default:
|
||||
LOG_INFO(Core_Linker, "unknown symbol type {}", sym_type);
|
||||
}
|
||||
if (sym_visibility != 0) // should be zero log if else
|
||||
{
|
||||
LOG_INFO(Core_Linker, "symbol visilibity !=0");
|
||||
}
|
||||
switch (sym_bind) {
|
||||
case STB_GLOBAL:
|
||||
rel_name = namesTlb + sym.st_name;
|
||||
Resolve(rel_name, rel_sym_type, m, &symrec);
|
||||
symbol_vitrual_addr = symrec.virtual_address;
|
||||
rel_isResolved = (symbol_vitrual_addr != 0);
|
||||
|
||||
rel_name = symrec.name;
|
||||
if (type == R_X86_64_JUMP_SLOT) {
|
||||
addend = 0;
|
||||
}
|
||||
rel_value = (rel_isResolved ? symbol_vitrual_addr + addend : 0);
|
||||
if (!rel_isResolved) {
|
||||
LOG_INFO(Core_Linker,
|
||||
"R_X86_64_64-R_X86_64_JUMP_SLOT sym_type {} bind STB_GLOBAL symbol : "
|
||||
"{:#010x}",
|
||||
sym_type, symbol);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_INFO(Core_Linker, "UNK bind {}", sym_bind);
|
||||
}
|
||||
|
||||
} break;
|
||||
default:
|
||||
LOG_INFO(Core_Linker, "UNK type {:#010x} rel symbol : {:#010x}", type, symbol);
|
||||
}
|
||||
|
||||
if (rel_isResolved) {
|
||||
VirtualMemory::memory_patch(rel_virtual_addr, rel_value);
|
||||
} else {
|
||||
LOG_INFO(Core_Linker, "function not patched! {}", rel_name);
|
||||
}
|
||||
};
|
||||
|
||||
u32 idx = 0;
|
||||
for (auto* rel = m->dynamic_info.relocation_table;
|
||||
reinterpret_cast<u8*>(rel) < reinterpret_cast<u8*>(m->dynamic_info.relocation_table) +
|
||||
|
@ -654,8 +590,8 @@ void Linker::Resolve(const std::string& name, int Symtype, Module* m,
|
|||
return_info->virtual_address = AeroLib::GetStub(sr.name.c_str());
|
||||
return_info->name = "Unknown !!!";
|
||||
}
|
||||
LOG_ERROR_IF(debug_loader, "Linker: Stub resolved {} as {} (lib: {}, mod: {}) \n",
|
||||
sr.name, return_info->name, library->name, module->name);
|
||||
LOG_ERROR(Core_Linker, "Linker: Stub resolved {} as {} (lib: {}, mod: {})", sr.name,
|
||||
return_info->name, library->name, module->name);
|
||||
}
|
||||
} else {
|
||||
//__debugbreak();//den tha prepei na ftasoume edo
|
||||
|
@ -672,7 +608,7 @@ static PS4_SYSV_ABI void ProgramExitFunc() {
|
|||
fmt::print("exit function called\n");
|
||||
}
|
||||
|
||||
static void run_main_entry(u64 addr, EntryParams* params, exit_func_t exit_func) {
|
||||
static void RunMainEntry(u64 addr, EntryParams* params, exit_func_t exit_func) {
|
||||
// reinterpret_cast<entry_func_t>(addr)(params, exit_func); // can't be used, stack has to have
|
||||
// a specific layout
|
||||
|
||||
|
@ -702,7 +638,7 @@ void Linker::Execute() {
|
|||
p.argv[0] = "eboot.bin"; // hmm should be ok?
|
||||
|
||||
const auto& module = m_modules.at(0);
|
||||
run_main_entry(module.elf.GetElfEntry() + module.base_virtual_addr, &p, ProgramExitFunc);
|
||||
RunMainEntry(module->elf.GetElfEntry() + module->base_virtual_addr, &p, ProgramExitFunc);
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue