Merge pull request #167 from SysRay/work

bugfixes for libc malloc
This commit is contained in:
SysRay 2024-05-26 15:53:16 +02:00 committed by GitHub
commit 6d58b63d47
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 86 additions and 57 deletions

View File

@ -91,21 +91,19 @@ int32_t MemoryManager::virtualQuery(uint64_t addr, SceKernelVirtualQueryInfo* in
boost::unique_lock lock(m_mutexInt);
auto itItem = m_mappings.lower_bound(addr);
if (itItem == m_mappings.end() || (itItem != m_mappings.begin() && itItem->first != addr)) --itItem; // Get the correct item
if (!(itItem->first <= addr && (itItem->first + itItem->second.size >= addr))) {
LOG_TRACE(L"Query Error: addr:0x%08llx", addr);
return getErr(ErrCode::_EACCES);
}
if (itItem == m_mappings.end() && addr > (itItem->first + itItem->second.size)) return getErr(ErrCode::_EACCES); // End reached
if (itItem == m_mappings.end() || (itItem != m_mappings.begin() && itItem->first != addr)) --itItem; // Get the correct item
int res = getErr(ErrCode::_EACCES);
switch (itItem->second.type) {
case MappingType::Direct: {
res = m_directMemory->virtualQuery(addr, info);
res = m_directMemory->virtualQuery(itItem->first, info);
} break;
case MappingType::Flexible: {
res = m_flexibleMemory->virtualQuery(addr, info);
res = m_flexibleMemory->virtualQuery(itItem->first, info);
} break;
case MappingType::Fixed: {
} break;
@ -116,7 +114,8 @@ int32_t MemoryManager::virtualQuery(uint64_t addr, SceKernelVirtualQueryInfo* in
}
if (res == Ok) {
LOG_TRACE(L"Query OK: addr:0x%08llx - start:0x%08llx end:0x%08llx prot:%d type:%d", addr, info->start, info->end, info->protection, info->memoryType);
LOG_TRACE(L"Query OK: addr:0x%08llx - start:0x%08llx end:0x%08llx prot:%d type:%d", itItem->first, info->start, info->end, info->protection,
info->memoryType);
} else {
LOG_TRACE(L"Query Error: addr:0x%08llx", addr);
}

View File

@ -27,7 +27,7 @@ enum class MemoryState {
Commited,
};
struct MemoryMapping {
struct MemoryMappingDirect {
uint64_t addr = 0;
uint64_t heapAddr = 0; // addr for MemoryInfo
@ -83,8 +83,8 @@ class DirectMemory: public IMemoryType {
IMemoryManager* m_parent;
std::map<uint64_t, MemoryInfo> m_objects;
std::map<uint64_t, MemoryMapping> m_mappings;
std::map<uint64_t, MemoryInfo> m_objects;
std::map<uint64_t, MemoryMappingDirect> m_mappings;
uint64_t m_allocSize = 0;
uint64_t m_usedSize = 0;
@ -222,7 +222,7 @@ int DirectMemory::alloc(size_t len, size_t alignment, int memoryType, uint64_t*
m_allocSize += len;
m_objects.emplace(std::make_pair(
*outAddr, MemoryInfo {.addr = *outAddr, .size = len, .alignment = alignment, .memoryType = memoryType, .vmaAlloc = alloc, .vmaBlock = block}));
m_parent->registerMapping(*outAddr, len, MappingType::Direct);
LOG_DEBUG(L"-> Allocated: len:0x%08llx alignment:0x%08llx memorytype:%d -> 0x%08llx", len, alignment, memoryType, *outAddr);
return Ok;
@ -349,15 +349,15 @@ int DirectMemory::map(uint64_t vaddr, off_t offset, size_t len, int prot, int fl
info->allocAddr = ptr;
info->state = MemoryState::Commited;
info->prot = prot;
LOG_DEBUG(L"Commit| addr:0x%08llx len:0x%08llx prot:%d ->", info->addr, info->size, prot, ptr);
}
// - commit
*outAddr = (uint64_t)info->allocAddr + fakeAddrOffset;
m_mappings.emplace(
std::make_pair(*outAddr, MemoryMapping {.addr = *outAddr, .heapAddr = info->addr, .size = len, .alignment = alignment, .vmaAlloc = alloc}));
std::make_pair(*outAddr, MemoryMappingDirect {.addr = *outAddr, .heapAddr = info->addr, .size = len, .alignment = alignment, .vmaAlloc = alloc}));
m_parent->registerMapping(*outAddr, len, MappingType::Direct);
m_usedSize += len;
LOG_DEBUG(L"-> Map: start:0x%08llx(0x%x) len:0x%08llx alignment:0x%08llx prot:%d -> 0x%08llx", vaddr, offset, len, alignment, prot, *outAddr);
@ -397,6 +397,7 @@ int DirectMemory::reserve(uint64_t start, size_t len, size_t alignment, int flag
m_objects.emplace(
std::make_pair(*outAddr, MemoryInfo {.addr = *outAddr, .size = len, .alignment = alignment, .memoryType = 0, .state = MemoryState::Reserved}));
m_parent->registerMapping(*outAddr, len, MappingType::Direct);
return Ok;
}
@ -481,13 +482,12 @@ int32_t DirectMemory::virtualQuery(uint64_t addr, SceKernelVirtualQueryInfo* inf
LOG_USE_MODULE(DirectMemory);
boost::unique_lock lock(m_mutexInt);
if (m_objects.empty()) return getErr(ErrCode::_EACCES);
auto itItem = m_objects.lower_bound(addr);
if (itItem == m_objects.end() || (itItem != m_objects.begin() && itItem->first != addr)) --itItem; // Get the correct item
if (itItem == m_objects.end() && addr > (itItem->first + itItem->second.size)) return getErr(ErrCode::_EACCES); // End reached
if (!(itItem->first <= addr && (itItem->first + itItem->second.size >= addr))) {
return getErr(ErrCode::_EACCES);
}
if (itItem == m_objects.end() || (itItem != m_objects.begin() && itItem->first != addr)) --itItem; // Get the correct item
info->protection = itItem->second.prot;
info->memoryType = itItem->second.memoryType;
@ -496,10 +496,10 @@ int32_t DirectMemory::virtualQuery(uint64_t addr, SceKernelVirtualQueryInfo* inf
info->isPooledMemory = false;
// info->isStack = false; // done by parent
auto itMapping = m_mappings.lower_bound(addr);
if (itMapping == m_mappings.end() || (itMapping != m_mappings.begin() && itMapping->first != addr)) --itMapping; // Get the correct item
auto itMapping = m_mappings.lower_bound(itItem->first);
if (itMapping == m_mappings.end() || (itMapping != m_mappings.begin() && itMapping->first != itItem->first)) --itMapping; // Get the correct item
if (!(itMapping->first <= addr && (itMapping->first + itMapping->second.size >= addr))) {
if (!(itMapping->first <= itItem->first && (itMapping->first + itMapping->second.size > itItem->first))) {
if (itItem->second.state == MemoryState::Reserved) {
info->start = (void*)itItem->first;
info->end = (void*)(itItem->first + itItem->second.size);
@ -512,7 +512,7 @@ int32_t DirectMemory::virtualQuery(uint64_t addr, SceKernelVirtualQueryInfo* inf
info->start = (void*)itMapping->first;
info->end = (void*)(itMapping->first + itMapping->second.size);
info->offset = itMapping->second.heapAddr - itMapping->first;
info->offset = 0;
info->isCommitted = true;
return Ok;
@ -526,8 +526,8 @@ int32_t DirectMemory::directQuery(uint64_t offset, SceKernelDirectMemoryQueryInf
for (auto& item: m_objects) {
auto off = item.second.addr - DIRECTMEM_START;
if (offset >= off && offset < off + item.second.size) {
info->start = off;
info->end = off + item.second.size;
info->start = item.second.addr;
info->end = item.second.addr + item.second.size;
info->memoryType = item.second.memoryType;

View File

@ -49,7 +49,7 @@ class IFormat: public Symbols::IResolve {
virtual Symbols::SymbolInfo getSymbolInfo(uint64_t const relIndex) const = 0;
virtual void relocate(Program const* prog, uint64_t invalidMemoryAddr) = 0;
virtual void relocate(Program const* prog, uint64_t invalidMemoryAddr, std::string_view libName) = 0;
virtual std::unordered_map<uint64_t, std::string_view> getDebugStrings() const = 0;
virtual std::string collectDebugInfos(std::unordered_map<uint64_t, std::string_view>& debugStrings) const = 0;

View File

@ -500,7 +500,7 @@ class Parser_ELF64: public IFormat {
Symbols::RelocationInfo getRelocationInfo(IRuntimeLinker const* linker, elf64::Elf64_Rela const* r, Program const* prog,
elf64::SymbolMap const& symbolsMap) const;
void relocate(Program const* prog, uint64_t invalidMemoryAddr) final;
void relocate(Program const* prog, uint64_t invalidMemoryAddr, std::string_view libName) final;
bool isShared() const { return (m_elfHeader->type == elf64::ET_DYNAMIC); }
@ -1420,7 +1420,7 @@ void Parser_ELF64::setupMissingRelocationHandler(Program* prog, void* relocateHa
}
}
void Parser_ELF64::relocate(Program const* prog, uint64_t invalidMemoryAddr) {
void Parser_ELF64::relocate(Program const* prog, uint64_t invalidMemoryAddr, std::string_view libName) {
LOG_USE_MODULE(ELF64);
LOG_INFO(L"relocate %s", prog->filename.c_str());
@ -1431,12 +1431,22 @@ void Parser_ELF64::relocate(Program const* prog, uint64_t invalidMemoryAddr) {
return ret;
};
auto relocateAll = [this, prog, invalidMemoryAddr, load](IRuntimeLinker& linker, elf64::Elf64_Rela const* records, uint64_t numBytes,
bool const isJmpRelaTable) {
auto relocateAll = [&](IRuntimeLinker& linker, elf64::Elf64_Rela const* records, uint64_t numBytes, bool const isJmpRelaTable) {
uint32_t index = 0;
for (auto const* r = records; reinterpret_cast<uint8_t const*>(r) < reinterpret_cast<uint8_t const*>(records) + numBytes; r++, index++) {
auto const ri = getRelocationInfo(&linker, r, prog, m_dynamicInfo->symbolsMap);
bool patched = false;
auto const ri = getRelocationInfo(&linker, r, prog, m_dynamicInfo->symbolsMap);
if (!libName.empty()) {
auto idData = util::splitString(ri.name, '#');
if (idData.size() == 3) {
auto lib = getLibrary(m_dynamicInfo.get(), idData[1]);
if (lib->name != libName) continue;
} else
continue;
}
bool patched = false;
if (ri.resolved) {
patched = patchReplace(ri.vaddr, ri.value);
} else {

View File

@ -21,8 +21,8 @@ struct alignas(32) EntryParams {
};
struct ModulInfo {
uint64_t address;
uint64_t size;
uint64_t seg0Addr;
uint64_t seg0Size;
uint64_t procParamAddr;
};

View File

@ -302,7 +302,7 @@ class RuntimeLinker: public IRuntimeLinker {
ModulInfo mainModuleInfo() const final {
auto prog = accessMainProg();
return {prog->baseVaddr, prog->baseSize, prog->procParamVaddr};
return {prog->moduleInfoEx.segments[0].address, prog->moduleInfoEx.segments[0].size, prog->procParamVaddr};
}
SceKernelModuleInfoEx const* getModuleInfoEx(uint64_t vaddr) const final {
@ -569,9 +569,13 @@ int RuntimeLinker::loadStartModule(std::filesystem::path const& path, size_t arg
// - imports
// relocate
auto libName = pProgram->filename.stem().string();
for (auto& prog: m_programList) {
prog.second->relocate(prog.first.get(), m_invalidMemoryAddr);
if (prog.second->getImportedLibs().find(libName) == prog.second->getImportedLibs().end()) continue;
prog.second->relocate(prog.first.get(), m_invalidMemoryAddr, libName);
}
format->relocate(pProgram, m_invalidMemoryAddr, "");
uintptr_t const entryAddr = pProgram->entryOffAddr + pProgram->baseVaddr;
LOG_INFO(L"-> Starting %s entry:0x%08llx tlsIndex:%u", pProgram->filename.c_str(), entryAddr, tlsIndex);
@ -840,7 +844,7 @@ uintptr_t RuntimeLinker::execute() {
// Relocate all (Set Imported Symbols)
m_invalidMemoryAddr = memory::alloc(INVALID_MEMORY, 4096, 0);
for (auto& prog: m_programList) {
if (prog.first) prog.second->relocate(prog.first.get(), m_invalidMemoryAddr);
if (prog.first) prog.second->relocate(prog.first.get(), m_invalidMemoryAddr, "");
}
setupTlsStaticBlock(); // relocate may init tls -> copy after relocate

View File

@ -187,12 +187,13 @@ int main(int argc, char** argv) {
}
// --- modules
auto mainProg = accessRuntimeLinker().accessMainProg();
auto* procParam = (ProcParam*)accessRuntimeLinker().accessMainProg()->procParamVaddr;
// Set flexiblememory size if available
if (procParam->header.size < (8 + offsetof(ProcParam, PSceLibcParam))) {
auto memparam = procParam->_sceKernelMemParam;
if (memparam != 0 && memparam->sceKernelFlexibleMemorySize != nullptr) {
if (procParam->header.size > (8 + offsetof(ProcParam, PSceLibcParam))) {
auto memparam = (SceKernelMemParam*)((uint64_t)procParam->_sceKernelMemParam + mainProg->baseVaddr);
if (procParam->_sceKernelMemParam != 0 && memparam->sceKernelFlexibleMemorySize != nullptr) {
accessMemoryManager()->flexibleMemory()->setTotalSize(*memparam->sceKernelFlexibleMemorySize);
}
}
@ -207,7 +208,7 @@ int main(int argc, char** argv) {
pthread::attrInit(&attr);
// set thread stack size if available
if (procParam->header.size < (8 + offsetof(ProcParam, sceUserMainThreadStackSize))) {
if (procParam->header.size > (8 + offsetof(ProcParam, sceUserMainThreadStackSize))) {
if (procParam->sceUserMainThreadStackSize != 0 && *procParam->sceUserMainThreadStackSize != 0)
pthread::attrSetstacksize(&attr, *procParam->sceUserMainThreadStackSize);
}

View File

@ -173,26 +173,34 @@ EXPORT SYSV_ABI int32_t sceKernelIsStack(void* addr, void** start, void** end) {
EXPORT SYSV_ABI int32_t sceKernelVirtualQuery(uintptr_t addr, int flags, SceKernelVirtualQueryInfo* info, size_t infoSize) {
if (info == nullptr || infoSize != sizeof(SceKernelVirtualQueryInfo)) return getErr(ErrCode::_EFAULT);
if (accessMemoryManager()->virtualQuery((uint64_t)addr, info) == Ok) return Ok;
LOG_USE_MODULE(dmem);
constexpr uint64_t DIRECTMEM_START = 0x100000000u;
uint64_t base = (uint64_t)addr;
if (addr >= DIRECTMEM_START) {
if (accessMemoryManager()->virtualQuery((uint64_t)addr, info) != Ok) {
LOG_TRACE(L"Query Error: addr:0x%08llx -> start:0x%08llx, end:0x%08llx, type:%d", addr, info->start, info->end, info->memoryType);
return getErr(ErrCode::_EACCES);
}
} else {
uint64_t base = (uint64_t)addr;
if ((uint64_t)addr < IMAGE_BASE) {
addr = IMAGE_BASE;
if ((uint64_t)addr < IMAGE_BASE) {
addr = IMAGE_BASE;
}
base = memory::queryAlloc(addr, (uintptr_t*)&info->start, (uintptr_t*)&info->end, &info->protection);
if (base <= 0) {
if (accessMemoryManager()->virtualQuery((uint64_t)addr, info) != Ok) {
LOG_TRACE(L"Query Error: addr:0x%08llx -> start:0x%08llx, end:0x%08llx, type:%d", addr, info->start, info->end, info->memoryType);
return getErr(ErrCode::_EACCES);
}
} else {
info->isCommitted = true;
info->isFlexibleMemory = true;
info->offset = 0;
}
}
base = memory::queryAlloc(addr, (uintptr_t*)&info->start, (uintptr_t*)&info->end, &info->protection);
if (base <= 0) {
LOG_TRACE(L"Query Error: addr:0x%08llx -> start:0x%08llx, end:0x%08llx, type:%d", addr, info->start, info->end, info->memoryType);
return getErr(ErrCode::_EACCES);
}
info->isCommitted = true;
info->isFlexibleMemory = true;
info->offset = (int64_t)addr - (int64_t)info->start;
LOG_TRACE(L"Query OK: addr:0x%08llx -> start:0x%08llx end:0x%08llx prot:%d type:%d", addr, info->start, info->end, info->protection, info->memoryType);
return Ok;
}

View File

@ -100,10 +100,17 @@ EXPORT SYSV_ABI void* _sceModuleParam() {
return reinterpret_cast<void*>(procParamVaddr);
}
EXPORT SYSV_ABI int sceKernelInternalMemoryGetModuleSegmentInfo(ModulInfo* info) {
struct ModuleSegmentInfo {
uint64_t addr;
uint64_t size;
};
EXPORT SYSV_ABI int sceKernelInternalMemoryGetModuleSegmentInfo(ModuleSegmentInfo* info) {
if (info == nullptr) return getErr(ErrCode::_EFAULT);
*info = accessRuntimeLinker().mainModuleInfo();
auto mainInfo = accessRuntimeLinker().mainModuleInfo();
info->addr = mainInfo.seg0Addr;
info->size = mainInfo.seg0Size;
return Ok;
}