Merge pull request #3514 from gookie-dev/perf/kernel-module-info-frame-tables
perf(libkernel): read a loaded image's unwind tables once in sceKernelGetModuleInfoFromAddr
This commit is contained in:
commit
989146c3b9
|
|
@ -22,7 +22,9 @@
|
|||
#else
|
||||
#include <dlfcn.h>
|
||||
#include <link.h>
|
||||
#include <mutex>
|
||||
#include <unistd.h>
|
||||
#include <unordered_map>
|
||||
#endif
|
||||
|
||||
extern "C" std::int32_t ModuleIdForImage_nid_no_patch(const void* native);
|
||||
|
|
@ -81,6 +83,24 @@ bool Contains(const dl_phdr_info& image, std::uintptr_t begin, std::uint64_t siz
|
|||
return false;
|
||||
}
|
||||
|
||||
struct FrameTableCache {
|
||||
std::mutex mutex;
|
||||
unsigned long long unloads = 0;
|
||||
std::unordered_map<std::uintptr_t, EhFrame::Tables> tables;
|
||||
};
|
||||
|
||||
EhFrame::Tables FrameTables(const dl_phdr_info& image, std::uintptr_t header) {
|
||||
static auto& cache = *new FrameTableCache();
|
||||
std::lock_guard lock(cache.mutex);
|
||||
if (cache.unloads != image.dlpi_subs) {
|
||||
cache.tables.clear();
|
||||
cache.unloads = image.dlpi_subs;
|
||||
}
|
||||
if (const auto found = cache.tables.find(header); found != cache.tables.end()) return found->second;
|
||||
const auto contains = [&](std::uintptr_t begin, std::uint64_t size) { return Contains(image, begin, size); };
|
||||
return cache.tables.emplace(header, EhFrame::ReadTables(contains, header, Caller)).first->second;
|
||||
}
|
||||
|
||||
std::string ImageName(const dl_phdr_info& image) {
|
||||
std::string path = image.dlpi_name ? image.dlpi_name : "";
|
||||
if (path.empty()) {
|
||||
|
|
@ -111,8 +131,7 @@ void Fill(const dl_phdr_info& image, TInfo& info) {
|
|||
info.tls_size = ToU32(header.p_memsz, "TLS size");
|
||||
info.tls_align = ToU32(header.p_align, "TLS alignment");
|
||||
} else if (header.p_type == PT_GNU_EH_FRAME) {
|
||||
const auto contains = [&](std::uintptr_t begin, std::uint64_t size) { return Contains(image, begin, size); };
|
||||
const auto tables = EhFrame::ReadTables(contains, address, Caller);
|
||||
const auto tables = FrameTables(image, address);
|
||||
info.eh_frame_hdr_addr = address;
|
||||
info.eh_frame_hdr_size = ToU32(header.p_memsz, "eh_frame_hdr size");
|
||||
info.eh_frame_addr = tables.frames;
|
||||
|
|
|
|||
|
|
@ -114,5 +114,16 @@ int main(int argc, char** argv) {
|
|||
ModuleInfoEx unset{};
|
||||
unset.st_size = 0xf0000;
|
||||
Require(sceKernelGetModuleInfoFromAddr(reinterpret_cast<std::uintptr_t>(add), 2, &unset) == 0 && unset.st_size == sizeof(ModuleInfoEx));
|
||||
const auto again = Query(add, 0);
|
||||
Require(again.eh_frame_hdr_addr == info.eh_frame_hdr_addr && again.eh_frame_hdr_size == info.eh_frame_hdr_size);
|
||||
Require(again.eh_frame_addr == info.eh_frame_addr && again.eh_frame_size == info.eh_frame_size);
|
||||
Require(dlclose_nid_postfix(module) == 0);
|
||||
void* reloaded = dlopen_nid_postfix(argv[1], 2);
|
||||
Require(reloaded != nullptr);
|
||||
const void* reloadedAdd = dlsym_nid_postfix(reloaded, "GuestModuleAdd");
|
||||
Require(reloadedAdd != nullptr);
|
||||
const auto fresh = Query(reloadedAdd, 0);
|
||||
Require(fresh.eh_frame_size == info.eh_frame_size && fresh.eh_frame_hdr_size == info.eh_frame_hdr_size);
|
||||
Require(fresh.eh_frame_addr - fresh.segments[0].address == info.eh_frame_addr - info.segments[0].address);
|
||||
Require(dlclose_nid_postfix(reloaded) == 0);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue