Merge remote-tracking branch 'upstream/master' into spurs_taskset
This commit is contained in:
+9
-1
@@ -109,7 +109,15 @@ struct FileListener : LogListener
|
||||
if (mPrependChannelName)
|
||||
{
|
||||
text.insert(0, gTypeNameTable[static_cast<u32>(msg.mType)].mName);
|
||||
|
||||
|
||||
if (msg.mType == Log::TTY)
|
||||
{
|
||||
text = fmt::escape(text);
|
||||
if (text[text.length() - 1] != '\n')
|
||||
{
|
||||
text += '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
mFile.Write(text);
|
||||
}
|
||||
|
||||
+32
-1
@@ -179,7 +179,7 @@ std::string fmt::replace_all(const std::string &src, const std::string& from, co
|
||||
pos += to.length();
|
||||
}
|
||||
|
||||
return src;
|
||||
return target;
|
||||
}
|
||||
|
||||
//TODO: move this wx Stuff somewhere else
|
||||
@@ -339,3 +339,34 @@ std::string fmt::tolower(std::string source)
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
std::string fmt::toupper(std::string source)
|
||||
{
|
||||
std::transform(source.begin(), source.end(), source.begin(), ::toupper);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
std::string fmt::escape(std::string source)
|
||||
{
|
||||
const std::pair<std::string, std::string> escape_list[] =
|
||||
{
|
||||
{ "\\", "\\\\" },
|
||||
{ "\a", "\\a" },
|
||||
{ "\b", "\\b" },
|
||||
{ "\f", "\\f" },
|
||||
{ "\n", "\\n\n" },
|
||||
{ "\r", "\\r" },
|
||||
{ "\t", "\\t" },
|
||||
{ "\v", "\\v" },
|
||||
};
|
||||
|
||||
source = fmt::replace_all(source, escape_list);
|
||||
|
||||
for (char c = 0; c < 32; c++)
|
||||
{
|
||||
if (c != '\n') source = fmt::replace_all(source, std::string(1, c), fmt::Format("\\x%02X", c));
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
+45
-1
@@ -177,6 +177,8 @@ namespace fmt
|
||||
std::string to_udec(u64 value);
|
||||
std::string to_sdec(s64 value);
|
||||
|
||||
std::string toupper(std::string source);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
size_t get_fmt_start(const char* fmt, size_t len);
|
||||
@@ -198,6 +200,10 @@ namespace fmt
|
||||
{
|
||||
return to_hex(arg, get_fmt_precision(fmt, len));
|
||||
}
|
||||
else if (fmt[len - 1] == 'X')
|
||||
{
|
||||
return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len)));
|
||||
}
|
||||
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
|
||||
{
|
||||
return to_udec(arg);
|
||||
@@ -218,6 +224,10 @@ namespace fmt
|
||||
{
|
||||
return to_hex(arg, get_fmt_precision(fmt, len));
|
||||
}
|
||||
else if (fmt[len - 1] == 'X')
|
||||
{
|
||||
return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len)));
|
||||
}
|
||||
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
|
||||
{
|
||||
return to_udec(arg);
|
||||
@@ -238,6 +248,10 @@ namespace fmt
|
||||
{
|
||||
return to_hex(arg, get_fmt_precision(fmt, len));
|
||||
}
|
||||
else if (fmt[len - 1] == 'X')
|
||||
{
|
||||
return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len)));
|
||||
}
|
||||
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
|
||||
{
|
||||
return to_udec(arg);
|
||||
@@ -258,6 +272,10 @@ namespace fmt
|
||||
{
|
||||
return to_hex(arg, get_fmt_precision(fmt, len));
|
||||
}
|
||||
else if (fmt[len - 1] == 'X')
|
||||
{
|
||||
return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len)));
|
||||
}
|
||||
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
|
||||
{
|
||||
return to_udec(arg);
|
||||
@@ -278,6 +296,10 @@ namespace fmt
|
||||
{
|
||||
return to_hex((u8)arg, get_fmt_precision(fmt, len));
|
||||
}
|
||||
else if (fmt[len - 1] == 'X')
|
||||
{
|
||||
return fmt::toupper(to_hex((u8)arg, get_fmt_precision(fmt, len)));
|
||||
}
|
||||
else if (fmt[len - 1] == 'd')
|
||||
{
|
||||
return to_sdec(arg);
|
||||
@@ -298,6 +320,10 @@ namespace fmt
|
||||
{
|
||||
return to_hex((u16)arg, get_fmt_precision(fmt, len));
|
||||
}
|
||||
else if (fmt[len - 1] == 'X')
|
||||
{
|
||||
return fmt::toupper(to_hex((u16)arg, get_fmt_precision(fmt, len)));
|
||||
}
|
||||
else if (fmt[len - 1] == 'd')
|
||||
{
|
||||
return to_sdec(arg);
|
||||
@@ -318,6 +344,10 @@ namespace fmt
|
||||
{
|
||||
return to_hex((u32)arg, get_fmt_precision(fmt, len));
|
||||
}
|
||||
else if (fmt[len - 1] == 'X')
|
||||
{
|
||||
return fmt::toupper(to_hex((u32)arg, get_fmt_precision(fmt, len)));
|
||||
}
|
||||
else if (fmt[len - 1] == 'd')
|
||||
{
|
||||
return to_sdec(arg);
|
||||
@@ -338,6 +368,10 @@ namespace fmt
|
||||
{
|
||||
return to_hex((u64)arg, get_fmt_precision(fmt, len));
|
||||
}
|
||||
else if (fmt[len - 1] == 'X')
|
||||
{
|
||||
return fmt::toupper(to_hex((u64)arg, get_fmt_precision(fmt, len)));
|
||||
}
|
||||
else if (fmt[len - 1] == 'd')
|
||||
{
|
||||
return to_sdec(arg);
|
||||
@@ -358,6 +392,10 @@ namespace fmt
|
||||
{
|
||||
return to_hex((u32&)arg, get_fmt_precision(fmt, len));
|
||||
}
|
||||
else if (fmt[len - 1] == 'X')
|
||||
{
|
||||
return fmt::toupper(to_hex((u32&)arg, get_fmt_precision(fmt, len)));
|
||||
}
|
||||
else if (fmt[len - 1] == 'f')
|
||||
{
|
||||
return std::to_string(arg);
|
||||
@@ -378,6 +416,10 @@ namespace fmt
|
||||
{
|
||||
return to_hex((u64&)arg, get_fmt_precision(fmt, len));
|
||||
}
|
||||
else if (fmt[len - 1] == 'X')
|
||||
{
|
||||
return fmt::toupper(to_hex((u64&)arg, get_fmt_precision(fmt, len)));
|
||||
}
|
||||
else if (fmt[len - 1] == 'f')
|
||||
{
|
||||
return std::to_string(arg);
|
||||
@@ -394,7 +436,7 @@ namespace fmt
|
||||
{
|
||||
static std::string text(const char* fmt, size_t len, bool arg)
|
||||
{
|
||||
if (fmt[len - 1] == 'x')
|
||||
if (fmt[len - 1] == 'x' || fmt[len - 1] == 'X')
|
||||
{
|
||||
return to_hex(arg, get_fmt_precision(fmt, len));
|
||||
}
|
||||
@@ -579,4 +621,6 @@ namespace fmt
|
||||
std::string merge(std::vector<std::string> source, const std::string& separator);
|
||||
std::string merge(std::initializer_list<std::vector<std::string>> sources, const std::string& separator);
|
||||
std::string tolower(std::string source);
|
||||
std::string toupper(std::string source);
|
||||
std::string escape(std::string source);
|
||||
}
|
||||
|
||||
+49
-19
@@ -213,9 +213,10 @@ static const reg_table_t reg_table[17] =
|
||||
|
||||
#endif
|
||||
|
||||
bool handle_access_violation(const u32 addr, x64_context* context)
|
||||
bool handle_access_violation(const u32 addr, bool is_writing, x64_context* context)
|
||||
{
|
||||
if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET) // RawSPU MMIO registers
|
||||
// check if address is RawSPU MMIO register
|
||||
if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET)
|
||||
{
|
||||
// one x64 instruction is manually decoded and interpreted
|
||||
x64_op_t op;
|
||||
@@ -277,6 +278,12 @@ bool handle_access_violation(const u32 addr, x64_context* context)
|
||||
return true;
|
||||
}
|
||||
|
||||
// check if fault is caused by reservation
|
||||
if (vm::reservation_query(addr, is_writing))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: allow recovering from a page fault as a feature of PS3 virtual memory
|
||||
return false;
|
||||
}
|
||||
@@ -285,38 +292,49 @@ bool handle_access_violation(const u32 addr, x64_context* context)
|
||||
|
||||
void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
|
||||
{
|
||||
const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)Memory.GetBaseAddr();
|
||||
const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::g_base_addr;
|
||||
const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0;
|
||||
|
||||
if (u == EXCEPTION_ACCESS_VIOLATION && (u32)addr64 == addr64)
|
||||
{
|
||||
if (handle_access_violation((u32)addr64, pExp->ContextRecord))
|
||||
{
|
||||
// restore context (further code shouldn't be reached)
|
||||
RtlRestoreContext(pExp->ContextRecord, nullptr);
|
||||
|
||||
// it's dangerous because destructors won't be executed
|
||||
}
|
||||
|
||||
throw fmt::format("Access violation %s location 0x%llx", is_writing ? "writing" : "reading", addr64);
|
||||
}
|
||||
|
||||
// else some fatal error (should crash)
|
||||
}
|
||||
|
||||
const PVOID exception_handler = (atexit([]{ RemoveVectoredExceptionHandler(exception_handler); }), AddVectoredExceptionHandler(1, [](PEXCEPTION_POINTERS pExp) -> LONG
|
||||
{
|
||||
const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::g_base_addr;
|
||||
const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0;
|
||||
|
||||
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
|
||||
(u32)addr64 == addr64 &&
|
||||
GetCurrentNamedThread() &&
|
||||
handle_access_violation((u32)addr64, is_writing, pExp->ContextRecord))
|
||||
{
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
}));
|
||||
|
||||
#else
|
||||
|
||||
void signal_handler(int sig, siginfo_t* info, void* uct)
|
||||
{
|
||||
const u64 addr64 = (u64)info->si_addr - (u64)Memory.GetBaseAddr();
|
||||
const u64 addr64 = (u64)info->si_addr - (u64)vm::g_base_addr;
|
||||
const bool is_writing = ((ucontext_t*)uct)->uc_mcontext.gregs[REG_ERR] & 0x2;
|
||||
|
||||
if ((u32)addr64 == addr64 && GetCurrentNamedThread())
|
||||
{
|
||||
if (handle_access_violation((u32)addr64, (ucontext_t*)uct))
|
||||
if (handle_access_violation((u32)addr64, is_writing, (ucontext_t*)uct))
|
||||
{
|
||||
return; // proceed execution
|
||||
}
|
||||
|
||||
// TODO: this may be wrong
|
||||
throw fmt::format("Access violation at location 0x%llx", addr64);
|
||||
throw fmt::format("Access violation %s location 0x%llx", is_writing ? "writing" : "reading", addr64);
|
||||
}
|
||||
|
||||
// else some fatal error
|
||||
@@ -352,6 +370,11 @@ void SetCurrentNamedThread(NamedThreadBase* value)
|
||||
return;
|
||||
}
|
||||
|
||||
if (old_value)
|
||||
{
|
||||
vm::reservation_free();
|
||||
}
|
||||
|
||||
if (value && value->m_tls_assigned.exchange(true))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Thread '%s' was already assigned to g_tls_this_thread of another thread", value->GetThreadName());
|
||||
@@ -421,8 +444,17 @@ void ThreadBase::Start()
|
||||
|
||||
#ifdef _WIN32
|
||||
auto old_se_translator = _set_se_translator(_se_translator);
|
||||
if (!exception_handler)
|
||||
{
|
||||
LOG_ERROR(GENERAL, "exception_handler not set");
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (sigaction_result == -1) assert(!"sigaction() failed");
|
||||
if (sigaction_result == -1)
|
||||
{
|
||||
printf("sigaction() failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
SetCurrentNamedThread(this);
|
||||
@@ -560,8 +592,6 @@ void thread_t::start(std::function<void()> func)
|
||||
|
||||
#ifdef _WIN32
|
||||
auto old_se_translator = _set_se_translator(_se_translator);
|
||||
#else
|
||||
if (sigaction_result == -1) assert(!"sigaction() failed");
|
||||
#endif
|
||||
|
||||
NamedThreadBase info(name);
|
||||
|
||||
Reference in New Issue
Block a user