mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
[rpcsx-os] export backtrace api
This commit is contained in:
parent
820a97ddec
commit
cf9add7209
|
|
@ -20,6 +20,7 @@ add_executable(rpcsx-os
|
|||
iodev/zero.cpp
|
||||
|
||||
main.cpp
|
||||
backtrace.cpp
|
||||
bridge.cpp
|
||||
vm.cpp
|
||||
ops.cpp
|
||||
|
|
|
|||
121
rpcsx-os/backtrace.cpp
Normal file
121
rpcsx-os/backtrace.cpp
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
#include "backtrace.hpp"
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
#include <libunwind.h>
|
||||
#include <link.h>
|
||||
#include <orbis/thread/Process.hpp>
|
||||
#include <ucontext.h>
|
||||
|
||||
std::size_t rx::printAddressLocation(char *dest, std::size_t destLen,
|
||||
orbis::Thread *thread,
|
||||
std::uint64_t address) {
|
||||
if (thread == nullptr || address == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (auto [id, module] : thread->tproc->modulesMap) {
|
||||
auto moduleBase = reinterpret_cast<std::uint64_t>(module->base);
|
||||
if (moduleBase > address || moduleBase + module->size <= address) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return std::snprintf(dest, destLen, "%s+%#" PRIx64, module->soName,
|
||||
address - moduleBase);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rx::printStackTrace(ucontext_t *context, int fileno) {
|
||||
unw_cursor_t cursor;
|
||||
|
||||
char buffer[1024];
|
||||
|
||||
if (int r = unw_init_local2(&cursor, context, UNW_INIT_SIGNAL_FRAME)) {
|
||||
int len = snprintf(buffer, sizeof(buffer), "unw_init_local: %s\n",
|
||||
unw_strerror(r));
|
||||
write(fileno, buffer, len);
|
||||
return;
|
||||
}
|
||||
|
||||
char functionName[256];
|
||||
|
||||
int count = 0;
|
||||
do {
|
||||
unw_word_t ip;
|
||||
unw_get_reg(&cursor, UNW_REG_IP, &ip);
|
||||
|
||||
unw_word_t off;
|
||||
int proc_res =
|
||||
unw_get_proc_name(&cursor, functionName, sizeof(functionName), &off);
|
||||
|
||||
Dl_info dlinfo;
|
||||
int dladdr_res = ::dladdr((void *)ip, &dlinfo);
|
||||
|
||||
unsigned long baseAddress =
|
||||
dladdr_res != 0 ? reinterpret_cast<std::uint64_t>(dlinfo.dli_fbase) : 0;
|
||||
|
||||
int len = snprintf(buffer, sizeof(buffer), "%3d: %s+%p: %s(%lx)+%#lx\n",
|
||||
count, (dladdr_res != 0 ? dlinfo.dli_fname : "??"),
|
||||
reinterpret_cast<void *>(ip - baseAddress),
|
||||
(proc_res == 0 ? functionName : "??"),
|
||||
reinterpret_cast<unsigned long>(
|
||||
proc_res == 0 ? ip - baseAddress - off : 0),
|
||||
static_cast<unsigned long>(proc_res == 0 ? off : 0));
|
||||
write(fileno, buffer, len);
|
||||
count++;
|
||||
} while (unw_step(&cursor) > 0 && count < 32);
|
||||
}
|
||||
|
||||
void rx::printStackTrace(ucontext_t *context, orbis::Thread *thread,
|
||||
int fileno) {
|
||||
unw_cursor_t cursor;
|
||||
|
||||
char buffer[1024];
|
||||
|
||||
if (int r = unw_init_local2(&cursor, context, UNW_INIT_SIGNAL_FRAME)) {
|
||||
int len = snprintf(buffer, sizeof(buffer), "unw_init_local: %s\n",
|
||||
unw_strerror(r));
|
||||
write(fileno, buffer, len);
|
||||
return;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
char functionName[256];
|
||||
do {
|
||||
unw_word_t ip;
|
||||
unw_get_reg(&cursor, UNW_REG_IP, &ip);
|
||||
std::size_t offset = 0;
|
||||
|
||||
offset +=
|
||||
std::snprintf(buffer + offset, sizeof(buffer) - offset, "%3d: ", count);
|
||||
|
||||
if (auto loc = printAddressLocation(buffer + offset,
|
||||
sizeof(buffer) - offset, thread, ip)) {
|
||||
offset += loc;
|
||||
offset += std::snprintf(buffer + offset, sizeof(buffer) - offset, "\n");
|
||||
} else {
|
||||
unw_word_t off;
|
||||
int proc_res =
|
||||
unw_get_proc_name(&cursor, functionName, sizeof(functionName), &off);
|
||||
|
||||
Dl_info dlinfo;
|
||||
int dladdr_res = ::dladdr((void *)ip, &dlinfo);
|
||||
|
||||
unsigned long baseAddress =
|
||||
dladdr_res != 0 ? reinterpret_cast<std::uint64_t>(dlinfo.dli_fbase)
|
||||
: 0;
|
||||
|
||||
offset = snprintf(buffer, sizeof(buffer), "%3d: %s+%p: %s(%lx)+%#lx\n",
|
||||
count, (dladdr_res != 0 ? dlinfo.dli_fname : "??"),
|
||||
reinterpret_cast<void *>(ip - baseAddress),
|
||||
(proc_res == 0 ? functionName : "??"),
|
||||
reinterpret_cast<unsigned long>(
|
||||
proc_res == 0 ? ip - baseAddress - off : 0),
|
||||
static_cast<unsigned long>(proc_res == 0 ? off : 0));
|
||||
}
|
||||
|
||||
write(fileno, buffer, offset);
|
||||
count++;
|
||||
} while (unw_step(&cursor) > 0 && count < 32);
|
||||
}
|
||||
12
rpcsx-os/backtrace.hpp
Normal file
12
rpcsx-os/backtrace.hpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "orbis/thread/Thread.hpp"
|
||||
#include <cstddef>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
namespace rx {
|
||||
std::size_t printAddressLocation(char *dest, std::size_t destLen,
|
||||
orbis::Thread *thread, std::uint64_t address);
|
||||
void printStackTrace(ucontext_t *context, int fileno);
|
||||
void printStackTrace(ucontext_t *context, orbis::Thread *thread, int fileno);
|
||||
} // namespace rx
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#include "align.hpp"
|
||||
#include "amdgpu/bridge/bridge.hpp"
|
||||
#include "backtrace.hpp"
|
||||
#include "bridge.hpp"
|
||||
#include "io-device.hpp"
|
||||
#include "io-devices.hpp"
|
||||
|
|
@ -9,8 +9,8 @@
|
|||
#include "vfs.hpp"
|
||||
#include "vm.hpp"
|
||||
|
||||
#include <elf.h>
|
||||
#include <filesystem>
|
||||
#include <linux/limits.h>
|
||||
#include <orbis/KernelContext.hpp>
|
||||
#include <orbis/module.hpp>
|
||||
#include <orbis/module/Module.hpp>
|
||||
|
|
@ -20,15 +20,9 @@
|
|||
#include <orbis/thread/ProcessOps.hpp>
|
||||
#include <orbis/thread/Thread.hpp>
|
||||
|
||||
#include <asm/prctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <libunwind.h>
|
||||
#include <link.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/ucontext.h>
|
||||
#include <ucontext.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <csignal>
|
||||
#include <cstddef>
|
||||
|
|
@ -36,120 +30,6 @@
|
|||
|
||||
static int g_gpuPid;
|
||||
|
||||
static void printStackTrace(ucontext_t *context, int fileno) {
|
||||
unw_cursor_t cursor;
|
||||
|
||||
char buffer[1024];
|
||||
|
||||
if (int r = unw_init_local2(&cursor, context, UNW_INIT_SIGNAL_FRAME)) {
|
||||
int len = snprintf(buffer, sizeof(buffer), "unw_init_local: %s\n",
|
||||
unw_strerror(r));
|
||||
write(fileno, buffer, len);
|
||||
return;
|
||||
}
|
||||
|
||||
char functionName[256];
|
||||
|
||||
int count = 0;
|
||||
do {
|
||||
unw_word_t ip;
|
||||
unw_get_reg(&cursor, UNW_REG_IP, &ip);
|
||||
|
||||
unw_word_t off;
|
||||
int proc_res =
|
||||
unw_get_proc_name(&cursor, functionName, sizeof(functionName), &off);
|
||||
|
||||
Dl_info dlinfo;
|
||||
int dladdr_res = ::dladdr((void *)ip, &dlinfo);
|
||||
|
||||
unsigned long baseAddress =
|
||||
dladdr_res != 0 ? reinterpret_cast<std::uint64_t>(dlinfo.dli_fbase) : 0;
|
||||
|
||||
int len = snprintf(buffer, sizeof(buffer), "%3d: %s+%p: %s(%lx)+%#lx\n",
|
||||
count, (dladdr_res != 0 ? dlinfo.dli_fname : "??"),
|
||||
reinterpret_cast<void *>(ip - baseAddress),
|
||||
(proc_res == 0 ? functionName : "??"),
|
||||
reinterpret_cast<unsigned long>(
|
||||
proc_res == 0 ? ip - baseAddress - off : 0),
|
||||
static_cast<unsigned long>(proc_res == 0 ? off : 0));
|
||||
write(fileno, buffer, len);
|
||||
count++;
|
||||
} while (unw_step(&cursor) > 0 && count < 32);
|
||||
}
|
||||
|
||||
static std::size_t printAddressLocation(char *dest, std::size_t destLen,
|
||||
orbis::Thread *thread,
|
||||
std::uint64_t address) {
|
||||
if (thread == nullptr || address == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (auto [id, module] : thread->tproc->modulesMap) {
|
||||
auto moduleBase = reinterpret_cast<std::uint64_t>(module->base);
|
||||
if (moduleBase > address || moduleBase + module->size <= address) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return std::snprintf(dest, destLen, "%s+%#" PRIx64, module->soName,
|
||||
address - moduleBase);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void printStackTrace(ucontext_t *context, orbis::Thread *thread,
|
||||
int fileno) {
|
||||
unw_cursor_t cursor;
|
||||
|
||||
char buffer[1024];
|
||||
|
||||
if (int r = unw_init_local2(&cursor, context, UNW_INIT_SIGNAL_FRAME)) {
|
||||
int len = snprintf(buffer, sizeof(buffer), "unw_init_local: %s\n",
|
||||
unw_strerror(r));
|
||||
write(fileno, buffer, len);
|
||||
return;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
char functionName[256];
|
||||
do {
|
||||
unw_word_t ip;
|
||||
unw_get_reg(&cursor, UNW_REG_IP, &ip);
|
||||
std::size_t offset = 0;
|
||||
|
||||
offset +=
|
||||
std::snprintf(buffer + offset, sizeof(buffer) - offset, "%3d: ", count);
|
||||
|
||||
if (auto loc = printAddressLocation(buffer + offset,
|
||||
sizeof(buffer) - offset, thread, ip)) {
|
||||
offset += loc;
|
||||
offset += std::snprintf(buffer + offset, sizeof(buffer) - offset, "\n");
|
||||
} else {
|
||||
unw_word_t off;
|
||||
int proc_res =
|
||||
unw_get_proc_name(&cursor, functionName, sizeof(functionName), &off);
|
||||
|
||||
Dl_info dlinfo;
|
||||
int dladdr_res = ::dladdr((void *)ip, &dlinfo);
|
||||
|
||||
unsigned long baseAddress =
|
||||
dladdr_res != 0 ? reinterpret_cast<std::uint64_t>(dlinfo.dli_fbase)
|
||||
: 0;
|
||||
|
||||
offset = snprintf(buffer, sizeof(buffer), "%3d: %s+%p: %s(%lx)+%#lx\n",
|
||||
count, (dladdr_res != 0 ? dlinfo.dli_fname : "??"),
|
||||
reinterpret_cast<void *>(ip - baseAddress),
|
||||
(proc_res == 0 ? functionName : "??"),
|
||||
reinterpret_cast<unsigned long>(
|
||||
proc_res == 0 ? ip - baseAddress - off : 0),
|
||||
static_cast<unsigned long>(proc_res == 0 ? off : 0));
|
||||
}
|
||||
|
||||
write(fileno, buffer, offset);
|
||||
count++;
|
||||
} while (unw_step(&cursor) > 0 && count < 32);
|
||||
}
|
||||
|
||||
__attribute__((no_stack_protector)) static void
|
||||
handle_signal(int sig, siginfo_t *info, void *ucontext) {
|
||||
if (auto hostFs = _readgsbase_u64()) {
|
||||
|
|
@ -171,17 +51,17 @@ handle_signal(int sig, siginfo_t *info, void *ucontext) {
|
|||
write(2, buf, len);
|
||||
|
||||
if (std::size_t printed =
|
||||
printAddressLocation(buf, sizeof(buf), rx::thread::g_current,
|
||||
rx::printAddressLocation(buf, sizeof(buf), rx::thread::g_current,
|
||||
(std::uint64_t)info->si_addr)) {
|
||||
printed += std::snprintf(buf + printed, sizeof(buf) - printed, "\n");
|
||||
write(2, buf, printed);
|
||||
}
|
||||
|
||||
if (rx::thread::g_current) {
|
||||
printStackTrace(reinterpret_cast<ucontext_t *>(ucontext),
|
||||
rx::printStackTrace(reinterpret_cast<ucontext_t *>(ucontext),
|
||||
rx::thread::g_current, 2);
|
||||
} else {
|
||||
printStackTrace(reinterpret_cast<ucontext_t *>(ucontext), 2);
|
||||
rx::printStackTrace(reinterpret_cast<ucontext_t *>(ucontext), 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue