summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/arm/symbols.cpp85
-rw-r--r--src/core/debugger/debugger.cpp21
-rw-r--r--src/core/debugger/gdbstub.cpp199
-rw-r--r--src/core/debugger/gdbstub.h1
-rw-r--r--src/core/hle/kernel/k_thread.cpp4
-rw-r--r--src/core/hle/kernel/k_thread.h10
-rw-r--r--src/core/hle/service/hid/controllers/gesture.cpp4
-rw-r--r--src/core/hle/service/hid/controllers/gesture.h3
-rw-r--r--src/core/hle/service/hid/irs.cpp249
-rw-r--r--src/core/hle/service/hid/irs.h232
-rw-r--r--src/core/hle/service/jit/jit_context.cpp32
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_consumer.cpp29
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_core.cpp4
-rw-r--r--src/core/hle/service/nvflinger/buffer_slot.h1
-rw-r--r--src/core/loader/elf.cpp183
15 files changed, 703 insertions, 354 deletions
diff --git a/src/core/arm/symbols.cpp b/src/core/arm/symbols.cpp
index 4aa1a1ee1..0259c7ea2 100644
--- a/src/core/arm/symbols.cpp
+++ b/src/core/arm/symbols.cpp
@@ -3,73 +3,14 @@
#include "common/bit_field.h"
#include "common/common_funcs.h"
+#include "common/elf.h"
#include "core/arm/symbols.h"
#include "core/core.h"
#include "core/memory.h"
-namespace Core {
-namespace {
-
-constexpr u64 ELF_DYNAMIC_TAG_NULL = 0;
-constexpr u64 ELF_DYNAMIC_TAG_STRTAB = 5;
-constexpr u64 ELF_DYNAMIC_TAG_SYMTAB = 6;
-constexpr u64 ELF_DYNAMIC_TAG_SYMENT = 11;
-
-enum class ELFSymbolType : u8 {
- None = 0,
- Object = 1,
- Function = 2,
- Section = 3,
- File = 4,
- Common = 5,
- TLS = 6,
-};
-
-enum class ELFSymbolBinding : u8 {
- Local = 0,
- Global = 1,
- Weak = 2,
-};
-
-enum class ELFSymbolVisibility : u8 {
- Default = 0,
- Internal = 1,
- Hidden = 2,
- Protected = 3,
-};
-
-struct ELF64Symbol {
- u32 name_index;
- union {
- u8 info;
-
- BitField<0, 4, ELFSymbolType> type;
- BitField<4, 4, ELFSymbolBinding> binding;
- };
- ELFSymbolVisibility visibility;
- u16 sh_index;
- u64 value;
- u64 size;
-};
-static_assert(sizeof(ELF64Symbol) == 0x18, "ELF64Symbol has incorrect size.");
-
-struct ELF32Symbol {
- u32 name_index;
- u32 value;
- u32 size;
- union {
- u8 info;
-
- BitField<0, 4, ELFSymbolType> type;
- BitField<4, 4, ELFSymbolBinding> binding;
- };
- ELFSymbolVisibility visibility;
- u16 sh_index;
-};
-static_assert(sizeof(ELF32Symbol) == 0x10, "ELF32Symbol has incorrect size.");
-
-} // Anonymous namespace
+using namespace Common::ELF;
+namespace Core {
namespace Symbols {
template <typename Word, typename ELFSymbol, typename ByteReader>
@@ -110,15 +51,15 @@ static Symbols GetSymbols(ByteReader ReadBytes) {
const Word value = ReadWord(dynamic_index + sizeof(Word));
dynamic_index += 2 * sizeof(Word);
- if (tag == ELF_DYNAMIC_TAG_NULL) {
+ if (tag == ElfDtNull) {
break;
}
- if (tag == ELF_DYNAMIC_TAG_STRTAB) {
+ if (tag == ElfDtStrtab) {
string_table_offset = value;
- } else if (tag == ELF_DYNAMIC_TAG_SYMTAB) {
+ } else if (tag == ElfDtSymtab) {
symbol_table_offset = value;
- } else if (tag == ELF_DYNAMIC_TAG_SYMENT) {
+ } else if (tag == ElfDtSyment) {
symbol_entry_size = value;
}
}
@@ -134,14 +75,14 @@ static Symbols GetSymbols(ByteReader ReadBytes) {
ELFSymbol symbol{};
ReadBytes(&symbol, symbol_index, sizeof(ELFSymbol));
- VAddr string_offset = string_table_offset + symbol.name_index;
+ VAddr string_offset = string_table_offset + symbol.st_name;
std::string name;
for (u8 c = Read8(string_offset); c != 0; c = Read8(++string_offset)) {
name += static_cast<char>(c);
}
symbol_index += symbol_entry_size;
- out[name] = std::make_pair(symbol.value, symbol.size);
+ out[name] = std::make_pair(symbol.st_value, symbol.st_size);
}
return out;
@@ -152,9 +93,9 @@ Symbols GetSymbols(VAddr base, Core::Memory::Memory& memory, bool is_64) {
[&](void* ptr, size_t offset, size_t size) { memory.ReadBlock(base + offset, ptr, size); }};
if (is_64) {
- return GetSymbols<u64, ELF64Symbol>(ReadBytes);
+ return GetSymbols<u64, Elf64_Sym>(ReadBytes);
} else {
- return GetSymbols<u32, ELF32Symbol>(ReadBytes);
+ return GetSymbols<u32, Elf32_Sym>(ReadBytes);
}
}
@@ -164,9 +105,9 @@ Symbols GetSymbols(std::span<const u8> data, bool is_64) {
}};
if (is_64) {
- return GetSymbols<u64, ELF64Symbol>(ReadBytes);
+ return GetSymbols<u64, Elf64_Sym>(ReadBytes);
} else {
- return GetSymbols<u32, ELF32Symbol>(ReadBytes);
+ return GetSymbols<u32, Elf32_Sym>(ReadBytes);
}
}
diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp
index 68ab33e46..8d64990ed 100644
--- a/src/core/debugger/debugger.cpp
+++ b/src/core/debugger/debugger.cpp
@@ -20,15 +20,16 @@ template <typename Readable, typename Buffer, typename Callback>
static void AsyncReceiveInto(Readable& r, Buffer& buffer, Callback&& c) {
static_assert(std::is_trivial_v<Buffer>);
auto boost_buffer{boost::asio::buffer(&buffer, sizeof(Buffer))};
- r.async_read_some(boost_buffer, [&](const boost::system::error_code& error, size_t bytes_read) {
- if (!error.failed()) {
- const u8* buffer_start = reinterpret_cast<const u8*>(&buffer);
- std::span<const u8> received_data{buffer_start, buffer_start + bytes_read};
- c(received_data);
- }
+ r.async_read_some(
+ boost_buffer, [&, c](const boost::system::error_code& error, size_t bytes_read) {
+ if (!error.failed()) {
+ const u8* buffer_start = reinterpret_cast<const u8*>(&buffer);
+ std::span<const u8> received_data{buffer_start, buffer_start + bytes_read};
+ c(received_data);
+ }
- AsyncReceiveInto(r, buffer, c);
- });
+ AsyncReceiveInto(r, buffer, c);
+ });
}
template <typename Readable, typename Buffer>
@@ -65,7 +66,7 @@ public:
}
stopped = true;
- signal_pipe.write_some(boost::asio::buffer(&thread, sizeof(thread)));
+ boost::asio::write(signal_pipe, boost::asio::buffer(&thread, sizeof(thread)));
return true;
}
@@ -74,7 +75,7 @@ public:
}
void WriteToClient(std::span<const u8> data) override {
- client_socket.write_some(boost::asio::buffer(data.data(), data.size_bytes()));
+ boost::asio::write(client_socket, boost::asio::buffer(data.data(), data.size_bytes()));
}
void SetActiveThread(Kernel::KThread* thread) override {
diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp
index 0c36069a6..f52d78829 100644
--- a/src/core/debugger/gdbstub.cpp
+++ b/src/core/debugger/gdbstub.cpp
@@ -34,6 +34,65 @@ constexpr char GDB_STUB_REPLY_ERR[] = "E01";
constexpr char GDB_STUB_REPLY_OK[] = "OK";
constexpr char GDB_STUB_REPLY_EMPTY[] = "";
+static u8 CalculateChecksum(std::string_view data) {
+ return std::accumulate(data.begin(), data.end(), u8{0},
+ [](u8 lhs, u8 rhs) { return static_cast<u8>(lhs + rhs); });
+}
+
+static std::string EscapeGDB(std::string_view data) {
+ std::string escaped;
+ escaped.reserve(data.size());
+
+ for (char c : data) {
+ switch (c) {
+ case '#':
+ escaped += "}\x03";
+ break;
+ case '$':
+ escaped += "}\x04";
+ break;
+ case '*':
+ escaped += "}\x0a";
+ break;
+ case '}':
+ escaped += "}\x5d";
+ break;
+ default:
+ escaped += c;
+ break;
+ }
+ }
+
+ return escaped;
+}
+
+static std::string EscapeXML(std::string_view data) {
+ std::string escaped;
+ escaped.reserve(data.size());
+
+ for (char c : data) {
+ switch (c) {
+ case '&':
+ escaped += "&amp;";
+ break;
+ case '"':
+ escaped += "&quot;";
+ break;
+ case '<':
+ escaped += "&lt;";
+ break;
+ case '>':
+ escaped += "&gt;";
+ break;
+ default:
+ escaped += c;
+ break;
+ }
+ }
+
+ return escaped;
+}
+
GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_)
: DebuggerFrontend(backend_), system{system_} {
if (system.CurrentProcess()->Is64BitProcess()) {
@@ -255,6 +314,80 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
}
}
+// Structure offsets are from Atmosphere
+// See osdbg_thread_local_region.os.horizon.hpp and osdbg_thread_type.os.horizon.hpp
+
+static std::optional<std::string> GetNameFromThreadType32(Core::Memory::Memory& memory,
+ const Kernel::KThread* thread) {
+ // Read thread type from TLS
+ const VAddr tls_thread_type{memory.Read32(thread->GetTLSAddress() + 0x1fc)};
+ const VAddr argument_thread_type{thread->GetArgument()};
+
+ if (argument_thread_type && tls_thread_type != argument_thread_type) {
+ // Probably not created by nnsdk, no name available.
+ return std::nullopt;
+ }
+
+ if (!tls_thread_type) {
+ return std::nullopt;
+ }
+
+ const u16 version{memory.Read16(tls_thread_type + 0x26)};
+ VAddr name_pointer{};
+ if (version == 1) {
+ name_pointer = memory.Read32(tls_thread_type + 0xe4);
+ } else {
+ name_pointer = memory.Read32(tls_thread_type + 0xe8);
+ }
+
+ if (!name_pointer) {
+ // No name provided.
+ return std::nullopt;
+ }
+
+ return memory.ReadCString(name_pointer, 256);
+}
+
+static std::optional<std::string> GetNameFromThreadType64(Core::Memory::Memory& memory,
+ const Kernel::KThread* thread) {
+ // Read thread type from TLS
+ const VAddr tls_thread_type{memory.Read64(thread->GetTLSAddress() + 0x1f8)};
+ const VAddr argument_thread_type{thread->GetArgument()};
+
+ if (argument_thread_type && tls_thread_type != argument_thread_type) {
+ // Probably not created by nnsdk, no name available.
+ return std::nullopt;
+ }
+
+ if (!tls_thread_type) {
+ return std::nullopt;
+ }
+
+ const u16 version{memory.Read16(tls_thread_type + 0x46)};
+ VAddr name_pointer{};
+ if (version == 1) {
+ name_pointer = memory.Read64(tls_thread_type + 0x1a0);
+ } else {
+ name_pointer = memory.Read64(tls_thread_type + 0x1a8);
+ }
+
+ if (!name_pointer) {
+ // No name provided.
+ return std::nullopt;
+ }
+
+ return memory.ReadCString(name_pointer, 256);
+}
+
+static std::optional<std::string> GetThreadName(Core::System& system,
+ const Kernel::KThread* thread) {
+ if (system.CurrentProcess()->Is64BitProcess()) {
+ return GetNameFromThreadType64(system.Memory(), thread);
+ } else {
+ return GetNameFromThreadType32(system.Memory(), thread);
+ }
+}
+
static std::string_view GetThreadWaitReason(const Kernel::KThread* thread) {
switch (thread->GetWaitReasonForDebugging()) {
case Kernel::ThreadWaitReasonForDebugging::Sleep:
@@ -289,6 +422,18 @@ static std::string GetThreadState(const Kernel::KThread* thread) {
}
}
+static std::string PaginateBuffer(std::string_view buffer, std::string_view request) {
+ const auto amount{request.substr(request.find(',') + 1)};
+ const auto offset_val{static_cast<u64>(strtoll(request.data(), nullptr, 16))};
+ const auto amount_val{static_cast<u64>(strtoll(amount.data(), nullptr, 16))};
+
+ if (offset_val + amount_val > buffer.size()) {
+ return fmt::format("l{}", buffer.substr(offset_val));
+ } else {
+ return fmt::format("m{}", buffer.substr(offset_val, amount_val));
+ }
+}
+
void GDBStub::HandleQuery(std::string_view command) {
if (command.starts_with("TStatus")) {
// no tracepoint support
@@ -297,18 +442,8 @@ void GDBStub::HandleQuery(std::string_view command) {
SendReply("PacketSize=4000;qXfer:features:read+;qXfer:threads:read+;qXfer:libraries:read+;"
"vContSupported+;QStartNoAckMode+");
} else if (command.starts_with("Xfer:features:read:target.xml:")) {
- const auto offset{command.substr(30)};
- const auto amount{command.substr(command.find(',') + 1)};
-
- const auto offset_val{static_cast<u64>(strtoll(offset.data(), nullptr, 16))};
- const auto amount_val{static_cast<u64>(strtoll(amount.data(), nullptr, 16))};
const auto target_xml{arch->GetTargetXML()};
-
- if (offset_val + amount_val > target_xml.size()) {
- SendReply("l" + target_xml.substr(offset_val));
- } else {
- SendReply("m" + target_xml.substr(offset_val, amount_val));
- }
+ SendReply(PaginateBuffer(target_xml, command.substr(30)));
} else if (command.starts_with("Offsets")) {
Loader::AppLoader::Modules modules;
system.GetAppLoader().ReadNSOModules(modules);
@@ -321,6 +456,20 @@ void GDBStub::HandleQuery(std::string_view command) {
SendReply(fmt::format("TextSeg={:x}",
system.CurrentProcess()->PageTable().GetCodeRegionStart()));
}
+ } else if (command.starts_with("Xfer:libraries:read::")) {
+ Loader::AppLoader::Modules modules;
+ system.GetAppLoader().ReadNSOModules(modules);
+
+ std::string buffer;
+ buffer += R"(<?xml version="1.0"?>)";
+ buffer += "<library-list>";
+ for (const auto& [base, name] : modules) {
+ buffer += fmt::format(R"(<library name="{}"><segment address="{:#x}"/></library>)",
+ EscapeXML(name), base);
+ }
+ buffer += "</library-list>";
+
+ SendReply(PaginateBuffer(buffer, command.substr(21)));
} else if (command.starts_with("fThreadInfo")) {
// beginning of list
const auto& threads = system.GlobalSchedulerContext().GetThreadList();
@@ -332,20 +481,26 @@ void GDBStub::HandleQuery(std::string_view command) {
} else if (command.starts_with("sThreadInfo")) {
// end of list
SendReply("l");
- } else if (command.starts_with("Xfer:threads:read")) {
+ } else if (command.starts_with("Xfer:threads:read::")) {
std::string buffer;
- buffer += R"(l<?xml version="1.0"?>)";
+ buffer += R"(<?xml version="1.0"?>)";
buffer += "<threads>";
const auto& threads = system.GlobalSchedulerContext().GetThreadList();
- for (const auto& thread : threads) {
- buffer += fmt::format(R"(<thread id="{:x}" core="{:d}" name="Thread {:d}">{}</thread>)",
+ for (const auto* thread : threads) {
+ auto thread_name{GetThreadName(system, thread)};
+ if (!thread_name) {
+ thread_name = fmt::format("Thread {:d}", thread->GetThreadID());
+ }
+
+ buffer += fmt::format(R"(<thread id="{:x}" core="{:d}" name="{}">{}</thread>)",
thread->GetThreadID(), thread->GetActiveCore(),
- thread->GetThreadID(), GetThreadState(thread));
+ EscapeXML(*thread_name), GetThreadState(thread));
}
buffer += "</threads>";
- SendReply(buffer);
+
+ SendReply(PaginateBuffer(buffer, command.substr(19)));
} else if (command.starts_with("Attached")) {
SendReply("0");
} else if (command.starts_with("StartNoAckMode")) {
@@ -438,14 +593,10 @@ std::optional<std::string> GDBStub::DetachCommand() {
return data.substr(1, data.size() - 4);
}
-u8 GDBStub::CalculateChecksum(std::string_view data) {
- return std::accumulate(data.begin(), data.end(), u8{0},
- [](u8 lhs, u8 rhs) { return static_cast<u8>(lhs + rhs); });
-}
-
void GDBStub::SendReply(std::string_view data) {
- const auto output{
- fmt::format("{}{}{}{:02x}", GDB_STUB_START, data, GDB_STUB_END, CalculateChecksum(data))};
+ const auto escaped{EscapeGDB(data)};
+ const auto output{fmt::format("{}{}{}{:02x}", GDB_STUB_START, escaped, GDB_STUB_END,
+ CalculateChecksum(escaped))};
LOG_TRACE(Debug_GDBStub, "Writing reply: {}", output);
// C++ string support is complete rubbish
diff --git a/src/core/debugger/gdbstub.h b/src/core/debugger/gdbstub.h
index aa1f7de6c..1bb638187 100644
--- a/src/core/debugger/gdbstub.h
+++ b/src/core/debugger/gdbstub.h
@@ -34,7 +34,6 @@ private:
std::optional<std::string> DetachCommand();
Kernel::KThread* GetThreadByID(u64 thread_id);
- static u8 CalculateChecksum(std::string_view data);
void SendReply(std::string_view data);
void SendStatus(char status);
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index ab9ce6a86..940334f59 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -198,6 +198,10 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s
resource_limit_release_hint = false;
cpu_time = 0;
+ // Set debug context.
+ stack_top = user_stack_top;
+ argument = arg;
+
// Clear our stack parameters.
std::memset(static_cast<void*>(std::addressof(GetStackParameters())), 0,
sizeof(StackParameters));
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index 60ae0da78..f4d83f99a 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -660,6 +660,14 @@ public:
void IfDummyThreadTryWait();
void IfDummyThreadEndWait();
+ [[nodiscard]] uintptr_t GetArgument() const {
+ return argument;
+ }
+
+ [[nodiscard]] VAddr GetUserStackTop() const {
+ return stack_top;
+ }
+
private:
static constexpr size_t PriorityInheritanceCountMax = 10;
union SyncObjectBuffer {
@@ -791,6 +799,8 @@ private:
std::vector<KSynchronizationObject*> wait_objects_for_debugging;
VAddr mutex_wait_address_for_debugging{};
ThreadWaitReasonForDebugging wait_reason_for_debugging{};
+ uintptr_t argument;
+ VAddr stack_top;
public:
using ConditionVariableThreadTreeType = ConditionVariableThreadTree;
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index 3eae1ae35..32e0708ba 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -61,6 +61,7 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
}
last_update_timestamp = shared_memory->gesture_lifo.timestamp;
+ UpdateGestureSharedMemory(gesture, time_difference);
}
void Controller_Gesture::ReadTouchInput() {
@@ -94,8 +95,7 @@ bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
return false;
}
-void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,
- GestureProperties& gesture,
+void Controller_Gesture::UpdateGestureSharedMemory(GestureProperties& gesture,
f32 time_difference) {
GestureType type = GestureType::Idle;
GestureAttribute attributes{};
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index c62a341bf..0d6099ea0 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -107,8 +107,7 @@ private:
bool ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference);
// Updates the shared memory to the next state
- void UpdateGestureSharedMemory(u8* data, std::size_t size, GestureProperties& gesture,
- f32 time_difference);
+ void UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_difference);
// Initializes new gesture
void NewGesture(GestureProperties& gesture, GestureType& type, GestureAttribute& attributes);
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp
index 9e32f3e60..d2a91d913 100644
--- a/src/core/hle/service/hid/irs.cpp
+++ b/src/core/hle/service/hid/irs.cpp
@@ -5,7 +5,9 @@
#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_shared_memory.h"
+#include "core/hle/kernel/k_transfer_memory.h"
#include "core/hle/kernel/kernel.h"
+#include "core/hle/service/hid/errors.h"
#include "core/hle/service/hid/irs.h"
namespace Service::HID {
@@ -38,21 +40,32 @@ IRS::IRS(Core::System& system_) : ServiceFramework{system_, "irs"} {
}
void IRS::ActivateIrsensor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
+ applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IRS::DeactivateIrsensor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
+ applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IRS::GetIrsensorSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_IRS, "called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_IRS, "called, applet_resource_user_id={}", applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
@@ -60,35 +73,109 @@ void IRS::GetIrsensorSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
}
void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ IrCameraHandle camera_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_IRS,
+ "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
+ parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
+ parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ IrCameraHandle camera_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ PackedMomentProcessorConfig processor_config;
+ };
+ static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_IRS,
+ "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
+ parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
+ parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ IrCameraHandle camera_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ PackedClusteringProcessorConfig processor_config;
+ };
+ static_assert(sizeof(Parameters) == 0x40, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_IRS,
+ "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
+ parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
+ parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ IrCameraHandle camera_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ PackedImageTransferProcessorConfig processor_config;
+ u32 transfer_memory_size;
+ };
+ static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+ const auto t_mem_handle{ctx.GetCopyHandle(0)};
+
+ auto t_mem =
+ system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle);
+
+ LOG_WARNING(Service_IRS,
+ "(STUBBED) called, npad_type={}, npad_id={}, transfer_memory_size={}, "
+ "applet_resource_user_id={}",
+ parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
+ parameters.transfer_memory_size, parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ IrCameraHandle camera_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_IRS,
+ "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
+ parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
+ parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 5};
rb.Push(ResultSuccess);
@@ -97,71 +184,195 @@ void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) {
}
void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto camera_handle{rp.PopRaw<IrCameraHandle>()};
+ const auto processor_config{rp.PopRaw<PackedTeraPluginProcessorConfig>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_IRS,
+ "(STUBBED) called, npad_type={}, npad_id={}, mode={}, mcu_version={}.{}, "
+ "applet_resource_user_id={}",
+ camera_handle.npad_type, camera_handle.npad_id, processor_config.mode,
+ processor_config.required_mcu_version.major,
+ processor_config.required_mcu_version.minor, applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
+
+ if (npad_id > Core::HID::NpadIdType::Player8 && npad_id != Core::HID::NpadIdType::Invalid &&
+ npad_id != Core::HID::NpadIdType::Handheld) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(InvalidNpadId);
+ return;
+ }
+
+ IrCameraHandle camera_handle{
+ .npad_id = static_cast<u8>(NpadIdTypeToIndex(npad_id)),
+ .npad_type = Core::HID::NpadStyleIndex::None,
+ };
+
+ LOG_WARNING(Service_IRS, "(STUBBED) called, npad_id={}, camera_npad_id={}, camera_npad_type={}",
+ npad_id, camera_handle.npad_id, camera_handle.npad_type);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
- rb.PushRaw<u32>(device_handle);
+ rb.PushRaw(camera_handle);
}
void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto camera_handle{rp.PopRaw<IrCameraHandle>()};
+ const auto processor_config{rp.PopRaw<PackedPointingProcessorConfig>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(
+ Service_IRS,
+ "(STUBBED) called, npad_type={}, npad_id={}, mcu_version={}.{}, applet_resource_user_id={}",
+ camera_handle.npad_type, camera_handle.npad_id, processor_config.required_mcu_version.major,
+ processor_config.required_mcu_version.minor, applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ IrCameraHandle camera_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_IRS,
+ "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
+ parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
+ parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto camera_handle{rp.PopRaw<IrCameraHandle>()};
+ const auto mcu_version{rp.PopRaw<PackedMcuVersion>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(
+ Service_IRS,
+ "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}, mcu_version={}.{}",
+ camera_handle.npad_type, camera_handle.npad_id, applet_resource_user_id, mcu_version.major,
+ mcu_version.minor);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IRS::SetFunctionLevel(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ IrCameraHandle camera_handle;
+ PackedFunctionLevel function_level;
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_IRS,
+ "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
+ parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
+ parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ IrCameraHandle camera_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ PackedImageTransferProcessorExConfig processor_config;
+ u64 transfer_memory_size;
+ };
+ static_assert(sizeof(Parameters) == 0x38, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+ const auto t_mem_handle{ctx.GetCopyHandle(0)};
+
+ auto t_mem =
+ system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle);
+
+ LOG_WARNING(Service_IRS,
+ "(STUBBED) called, npad_type={}, npad_id={}, transfer_memory_size={}, "
+ "applet_resource_user_id={}",
+ parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
+ parameters.transfer_memory_size, parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto camera_handle{rp.PopRaw<IrCameraHandle>()};
+ const auto processor_config{rp.PopRaw<PackedIrLedProcessorConfig>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_IRS,
+ "(STUBBED) called, npad_type={}, npad_id={}, light_target={}, mcu_version={}.{} "
+ "applet_resource_user_id={}",
+ camera_handle.npad_type, camera_handle.npad_id, processor_config.light_target,
+ processor_config.required_mcu_version.major,
+ processor_config.required_mcu_version.minor, applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ IrCameraHandle camera_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_IRS,
+ "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
+ parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
+ parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_IRS, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ PackedFunctionLevel function_level;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_IRS, "(STUBBED) called, function_level={}, applet_resource_user_id={}",
+ parameters.function_level.function_level, parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h
index efb29d3fd..361dc2213 100644
--- a/src/core/hle/service/hid/irs.h
+++ b/src/core/hle/service/hid/irs.h
@@ -3,6 +3,7 @@
#pragma once
+#include "core/hid/hid_types.h"
#include "core/hle/service/service.h"
namespace Core {
@@ -17,6 +18,235 @@ public:
~IRS() override;
private:
+ // This is nn::irsensor::IrCameraStatus
+ enum IrCameraStatus : u32 {
+ Available,
+ Unsupported,
+ Unconnected,
+ };
+
+ // This is nn::irsensor::IrCameraInternalStatus
+ enum IrCameraInternalStatus : u32 {
+ Stopped,
+ FirmwareUpdateNeeded,
+ Unkown2,
+ Unkown3,
+ Unkown4,
+ FirmwareVersionRequested,
+ FirmwareVersionIsInvalid,
+ Ready,
+ Setting,
+ };
+
+ // This is nn::irsensor::detail::StatusManager::IrSensorMode
+ enum IrSensorMode : u64 {
+ None,
+ MomentProcessor,
+ ClusteringProcessor,
+ ImageTransferProcessor,
+ PointingProcessorMarker,
+ TeraPluginProcessor,
+ IrLedProcessor,
+ };
+
+ // This is nn::irsensor::ImageProcessorStatus
+ enum ImageProcessorStatus : u8 {
+ stopped,
+ running,
+ };
+
+ // This is nn::irsensor::ImageTransferProcessorFormat
+ enum ImageTransferProcessorFormat : u8 {
+ Size320x240,
+ Size160x120,
+ Size80x60,
+ Size40x30,
+ Size20x15,
+ };
+
+ // This is nn::irsensor::AdaptiveClusteringMode
+ enum AdaptiveClusteringMode : u8 {
+ StaticFov,
+ DynamicFov,
+ };
+
+ // This is nn::irsensor::AdaptiveClusteringTargetDistance
+ enum AdaptiveClusteringTargetDistance : u8 {
+ Near,
+ Middle,
+ Far,
+ };
+
+ // This is nn::irsensor::IrsHandAnalysisMode
+ enum IrsHandAnalysisMode : u8 {
+ Silhouette,
+ Image,
+ SilhoueteAndImage,
+ SilhuetteOnly,
+ };
+
+ // This is nn::irsensor::IrSensorFunctionLevel
+ enum IrSensorFunctionLevel : u8 {
+ unknown0,
+ unknown1,
+ unknown2,
+ unknown3,
+ unknown4,
+ };
+
+ // This is nn::irsensor::IrCameraHandle
+ struct IrCameraHandle {
+ u8 npad_id{};
+ Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None};
+ INSERT_PADDING_BYTES(2);
+ };
+ static_assert(sizeof(IrCameraHandle) == 4, "IrCameraHandle is an invalid size");
+
+ struct IrsRect {
+ s16 x;
+ s16 y;
+ s16 width;
+ s16 height;
+ };
+
+ // This is nn::irsensor::PackedMcuVersion
+ struct PackedMcuVersion {
+ u16 major;
+ u16 minor;
+ };
+ static_assert(sizeof(PackedMcuVersion) == 4, "PackedMcuVersion is an invalid size");
+
+ // This is nn::irsensor::MomentProcessorConfig
+ struct MomentProcessorConfig {
+ u64 exposire_time;
+ u8 light_target;
+ u8 gain;
+ u8 is_negative_used;
+ INSERT_PADDING_BYTES(7);
+ IrsRect window_of_interest;
+ u8 preprocess;
+ u8 preprocess_intensity_threshold;
+ INSERT_PADDING_BYTES(5);
+ };
+ static_assert(sizeof(MomentProcessorConfig) == 0x28,
+ "MomentProcessorConfig is an invalid size");
+
+ // This is nn::irsensor::PackedMomentProcessorConfig
+ struct PackedMomentProcessorConfig {
+ u64 exposire_time;
+ u8 light_target;
+ u8 gain;
+ u8 is_negative_used;
+ INSERT_PADDING_BYTES(5);
+ IrsRect window_of_interest;
+ PackedMcuVersion required_mcu_version;
+ u8 preprocess;
+ u8 preprocess_intensity_threshold;
+ INSERT_PADDING_BYTES(2);
+ };
+ static_assert(sizeof(PackedMomentProcessorConfig) == 0x20,
+ "PackedMomentProcessorConfig is an invalid size");
+
+ // This is nn::irsensor::ClusteringProcessorConfig
+ struct ClusteringProcessorConfig {
+ u64 exposire_time;
+ u32 light_target;
+ u32 gain;
+ u8 is_negative_used;
+ INSERT_PADDING_BYTES(7);
+ IrsRect window_of_interest;
+ u32 pixel_count_min;
+ u32 pixel_count_max;
+ u32 object_intensity_min;
+ u8 is_external_light_filter_enabled;
+ INSERT_PADDING_BYTES(3);
+ };
+ static_assert(sizeof(ClusteringProcessorConfig) == 0x30,
+ "ClusteringProcessorConfig is an invalid size");
+
+ // This is nn::irsensor::PackedClusteringProcessorConfig
+ struct PackedClusteringProcessorConfig {
+ u64 exposire_time;
+ u8 light_target;
+ u8 gain;
+ u8 is_negative_used;
+ INSERT_PADDING_BYTES(5);
+ IrsRect window_of_interest;
+ PackedMcuVersion required_mcu_version;
+ u32 pixel_count_min;
+ u32 pixel_count_max;
+ u32 object_intensity_min;
+ u8 is_external_light_filter_enabled;
+ INSERT_PADDING_BYTES(2);
+ };
+ static_assert(sizeof(PackedClusteringProcessorConfig) == 0x30,
+ "PackedClusteringProcessorConfig is an invalid size");
+
+ // This is nn::irsensor::PackedImageTransferProcessorConfig
+ struct PackedImageTransferProcessorConfig {
+ u64 exposire_time;
+ u8 light_target;
+ u8 gain;
+ u8 is_negative_used;
+ INSERT_PADDING_BYTES(5);
+ PackedMcuVersion required_mcu_version;
+ u8 format;
+ INSERT_PADDING_BYTES(3);
+ };
+ static_assert(sizeof(PackedImageTransferProcessorConfig) == 0x18,
+ "PackedImageTransferProcessorConfig is an invalid size");
+
+ // This is nn::irsensor::PackedTeraPluginProcessorConfig
+ struct PackedTeraPluginProcessorConfig {
+ PackedMcuVersion required_mcu_version;
+ u8 mode;
+ INSERT_PADDING_BYTES(3);
+ };
+ static_assert(sizeof(PackedTeraPluginProcessorConfig) == 0x8,
+ "PackedTeraPluginProcessorConfig is an invalid size");
+
+ // This is nn::irsensor::PackedPointingProcessorConfig
+ struct PackedPointingProcessorConfig {
+ IrsRect window_of_interest;
+ PackedMcuVersion required_mcu_version;
+ };
+ static_assert(sizeof(PackedPointingProcessorConfig) == 0xC,
+ "PackedPointingProcessorConfig is an invalid size");
+
+ // This is nn::irsensor::PackedFunctionLevel
+ struct PackedFunctionLevel {
+ IrSensorFunctionLevel function_level;
+ INSERT_PADDING_BYTES(3);
+ };
+ static_assert(sizeof(PackedFunctionLevel) == 0x4, "PackedFunctionLevel is an invalid size");
+
+ // This is nn::irsensor::PackedImageTransferProcessorExConfig
+ struct PackedImageTransferProcessorExConfig {
+ u64 exposire_time;
+ u8 light_target;
+ u8 gain;
+ u8 is_negative_used;
+ INSERT_PADDING_BYTES(5);
+ PackedMcuVersion required_mcu_version;
+ ImageTransferProcessorFormat origin_format;
+ ImageTransferProcessorFormat trimming_format;
+ u16 trimming_start_x;
+ u16 trimming_start_y;
+ u8 is_external_light_filter_enabled;
+ INSERT_PADDING_BYTES(3);
+ };
+ static_assert(sizeof(PackedImageTransferProcessorExConfig) == 0x20,
+ "PackedImageTransferProcessorExConfig is an invalid size");
+
+ // This is nn::irsensor::PackedIrLedProcessorConfig
+ struct PackedIrLedProcessorConfig {
+ PackedMcuVersion required_mcu_version;
+ u8 light_target;
+ INSERT_PADDING_BYTES(3);
+ };
+ static_assert(sizeof(PackedIrLedProcessorConfig) == 0x8,
+ "PackedIrLedProcessorConfig is an invalid size");
+
void ActivateIrsensor(Kernel::HLERequestContext& ctx);
void DeactivateIrsensor(Kernel::HLERequestContext& ctx);
void GetIrsensorSharedMemoryHandle(Kernel::HLERequestContext& ctx);
@@ -35,8 +265,6 @@ private:
void RunIrLedProcessor(Kernel::HLERequestContext& ctx);
void StopImageProcessorAsync(Kernel::HLERequestContext& ctx);
void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx);
-
- const u32 device_handle{0xABCD};
};
class IRS_SYS final : public ServiceFramework<IRS_SYS> {
diff --git a/src/core/hle/service/jit/jit_context.cpp b/src/core/hle/service/jit/jit_context.cpp
index 19bd85b6c..4ed3f02e2 100644
--- a/src/core/hle/service/jit/jit_context.cpp
+++ b/src/core/hle/service/jit/jit_context.cpp
@@ -11,10 +11,13 @@
#include "common/alignment.h"
#include "common/common_funcs.h"
#include "common/div_ceil.h"
+#include "common/elf.h"
#include "common/logging/log.h"
#include "core/hle/service/jit/jit_context.h"
#include "core/memory.h"
+using namespace Common::ELF;
+
namespace Service::JIT {
constexpr std::array<u8, 8> SVC0_ARM64 = {
@@ -26,25 +29,6 @@ constexpr std::array HELPER_FUNCTIONS{
"_stop", "_resolve", "_panic", "memcpy", "memmove", "memset",
};
-struct Elf64_Dyn {
- u64 d_tag;
- u64 d_un;
-};
-
-struct Elf64_Rela {
- u64 r_offset;
- u64 r_info;
- s64 r_addend;
-};
-
-static constexpr u32 Elf64_RelaType(const Elf64_Rela* rela) {
- return static_cast<u32>(rela->r_info);
-}
-
-constexpr int DT_RELA = 7; /* Address of Rela relocs */
-constexpr int DT_RELASZ = 8; /* Total size of Rela relocs */
-constexpr int R_AARCH64_RELATIVE = 1027; /* Adjust by program base. */
-
constexpr size_t STACK_ALIGN = 16;
class JITContextImpl;
@@ -206,17 +190,17 @@ public:
if (!dyn.d_tag) {
break;
}
- if (dyn.d_tag == DT_RELA) {
- rela_dyn = dyn.d_un;
+ if (dyn.d_tag == ElfDtRela) {
+ rela_dyn = dyn.d_un.d_ptr;
}
- if (dyn.d_tag == DT_RELASZ) {
- num_rela = dyn.d_un / sizeof(Elf64_Rela);
+ if (dyn.d_tag == ElfDtRelasz) {
+ num_rela = dyn.d_un.d_val / sizeof(Elf64_Rela);
}
}
for (size_t i = 0; i < num_rela; i++) {
const auto rela{callbacks->ReadMemory<Elf64_Rela>(rela_dyn + i * sizeof(Elf64_Rela))};
- if (Elf64_RelaType(&rela) != R_AARCH64_RELATIVE) {
+ if (Elf64RelType(rela.r_info) != ElfAArch64Relative) {
continue;
}
const VAddr contents{callbacks->MemoryRead64(rela.r_offset)};
diff --git a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp
index d7db77aff..4b3d5efd6 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp
@@ -89,14 +89,6 @@ Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer,
LOG_DEBUG(Service_NVFlinger, "acquiring slot={}", slot);
- // If the front buffer is still being tracked, update its slot state
- if (core->StillTracking(*front)) {
- slots[slot].acquire_called = true;
- slots[slot].needs_cleanup_on_release = false;
- slots[slot].buffer_state = BufferState::Acquired;
- slots[slot].fence = Fence::NoFence();
- }
-
// If the buffer has previously been acquired by the consumer, set graphic_buffer to nullptr to
// avoid unnecessarily remapping this buffer on the consumer side.
if (out_buffer->acquire_called) {
@@ -139,26 +131,11 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc
++current;
}
- if (slots[slot].buffer_state == BufferState::Acquired) {
- slots[slot].fence = release_fence;
- slots[slot].buffer_state = BufferState::Free;
-
- listener = core->connected_producer_listener;
-
- LOG_DEBUG(Service_NVFlinger, "releasing slot {}", slot);
- } else if (slots[slot].needs_cleanup_on_release) {
- LOG_DEBUG(Service_NVFlinger, "releasing a stale buffer slot {} (state = {})", slot,
- slots[slot].buffer_state);
+ slots[slot].buffer_state = BufferState::Free;
- slots[slot].needs_cleanup_on_release = false;
+ listener = core->connected_producer_listener;
- return Status::StaleBufferSlot;
- } else {
- LOG_ERROR(Service_NVFlinger, "attempted to release buffer slot {} but its state was {}",
- slot, slots[slot].buffer_state);
-
- return Status::BadValue;
- }
+ LOG_DEBUG(Service_NVFlinger, "releasing slot {}", slot);
core->SignalDequeueCondition();
}
diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.cpp b/src/core/hle/service/nvflinger/buffer_queue_core.cpp
index d4e8b44d0..ea4a14ea4 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_core.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue_core.cpp
@@ -84,10 +84,6 @@ void BufferQueueCore::FreeBufferLocked(s32 slot) {
slots[slot].graphic_buffer.reset();
- if (slots[slot].buffer_state == BufferState::Acquired) {
- slots[slot].needs_cleanup_on_release = true;
- }
-
slots[slot].buffer_state = BufferState::Free;
slots[slot].frame_number = UINT32_MAX;
slots[slot].acquire_called = false;
diff --git a/src/core/hle/service/nvflinger/buffer_slot.h b/src/core/hle/service/nvflinger/buffer_slot.h
index 6b3e87446..0cd0e9964 100644
--- a/src/core/hle/service/nvflinger/buffer_slot.h
+++ b/src/core/hle/service/nvflinger/buffer_slot.h
@@ -31,7 +31,6 @@ struct BufferSlot final {
u64 frame_number{};
Fence fence;
bool acquire_called{};
- bool needs_cleanup_on_release{};
bool attached_by_consumer{};
bool is_preallocated{};
};
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index cf5933699..dfb10c34f 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -6,6 +6,7 @@
#include <memory>
#include "common/common_funcs.h"
#include "common/common_types.h"
+#include "common/elf.h"
#include "common/logging/log.h"
#include "core/hle/kernel/code_set.h"
#include "core/hle/kernel/k_page_table.h"
@@ -13,159 +14,7 @@
#include "core/loader/elf.h"
#include "core/memory.h"
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// ELF Header Constants
-
-// File type
-enum ElfType {
- ET_NONE = 0,
- ET_REL = 1,
- ET_EXEC = 2,
- ET_DYN = 3,
- ET_CORE = 4,
- ET_LOPROC = 0xFF00,
- ET_HIPROC = 0xFFFF,
-};
-
-// Machine/Architecture
-enum ElfMachine {
- EM_NONE = 0,
- EM_M32 = 1,
- EM_SPARC = 2,
- EM_386 = 3,
- EM_68K = 4,
- EM_88K = 5,
- EM_860 = 7,
- EM_MIPS = 8
-};
-
-// File version
-#define EV_NONE 0
-#define EV_CURRENT 1
-
-// Identification index
-#define EI_MAG0 0
-#define EI_MAG1 1
-#define EI_MAG2 2
-#define EI_MAG3 3
-#define EI_CLASS 4
-#define EI_DATA 5
-#define EI_VERSION 6
-#define EI_PAD 7
-#define EI_NIDENT 16
-
-// Sections constants
-
-// Section types
-#define SHT_NULL 0
-#define SHT_PROGBITS 1
-#define SHT_SYMTAB 2
-#define SHT_STRTAB 3
-#define SHT_RELA 4
-#define SHT_HASH 5
-#define SHT_DYNAMIC 6
-#define SHT_NOTE 7
-#define SHT_NOBITS 8
-#define SHT_REL 9
-#define SHT_SHLIB 10
-#define SHT_DYNSYM 11
-#define SHT_LOPROC 0x70000000
-#define SHT_HIPROC 0x7FFFFFFF
-#define SHT_LOUSER 0x80000000
-#define SHT_HIUSER 0xFFFFFFFF
-
-// Section flags
-enum ElfSectionFlags {
- SHF_WRITE = 0x1,
- SHF_ALLOC = 0x2,
- SHF_EXECINSTR = 0x4,
- SHF_MASKPROC = 0xF0000000,
-};
-
-// Segment types
-#define PT_NULL 0
-#define PT_LOAD 1
-#define PT_DYNAMIC 2
-#define PT_INTERP 3
-#define PT_NOTE 4
-#define PT_SHLIB 5
-#define PT_PHDR 6
-#define PT_LOPROC 0x70000000
-#define PT_HIPROC 0x7FFFFFFF
-
-// Segment flags
-#define PF_X 0x1
-#define PF_W 0x2
-#define PF_R 0x4
-#define PF_MASKPROC 0xF0000000
-
-typedef unsigned int Elf32_Addr;
-typedef unsigned short Elf32_Half;
-typedef unsigned int Elf32_Off;
-typedef signed int Elf32_Sword;
-typedef unsigned int Elf32_Word;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// ELF file header
-
-struct Elf32_Ehdr {
- unsigned char e_ident[EI_NIDENT];
- Elf32_Half e_type;
- Elf32_Half e_machine;
- Elf32_Word e_version;
- Elf32_Addr e_entry;
- Elf32_Off e_phoff;
- Elf32_Off e_shoff;
- Elf32_Word e_flags;
- Elf32_Half e_ehsize;
- Elf32_Half e_phentsize;
- Elf32_Half e_phnum;
- Elf32_Half e_shentsize;
- Elf32_Half e_shnum;
- Elf32_Half e_shstrndx;
-};
-
-// Section header
-struct Elf32_Shdr {
- Elf32_Word sh_name;
- Elf32_Word sh_type;
- Elf32_Word sh_flags;
- Elf32_Addr sh_addr;
- Elf32_Off sh_offset;
- Elf32_Word sh_size;
- Elf32_Word sh_link;
- Elf32_Word sh_info;
- Elf32_Word sh_addralign;
- Elf32_Word sh_entsize;
-};
-
-// Segment header
-struct Elf32_Phdr {
- Elf32_Word p_type;
- Elf32_Off p_offset;
- Elf32_Addr p_vaddr;
- Elf32_Addr p_paddr;
- Elf32_Word p_filesz;
- Elf32_Word p_memsz;
- Elf32_Word p_flags;
- Elf32_Word p_align;
-};
-
-// Symbol table entry
-struct Elf32_Sym {
- Elf32_Word st_name;
- Elf32_Addr st_value;
- Elf32_Word st_size;
- unsigned char st_info;
- unsigned char st_other;
- Elf32_Half st_shndx;
-};
-
-// Relocation entries
-struct Elf32_Rel {
- Elf32_Addr r_offset;
- Elf32_Word r_info;
-};
+using namespace Common::ELF;
////////////////////////////////////////////////////////////////////////////////////////////////////
// ElfReader class
@@ -193,11 +42,11 @@ public:
}
// Quick accessors
- ElfType GetType() const {
- return (ElfType)(header->e_type);
+ u16 GetType() const {
+ return header->e_type;
}
- ElfMachine GetMachine() const {
- return (ElfMachine)(header->e_machine);
+ u16 GetMachine() const {
+ return header->e_machine;
}
VAddr GetEntryPoint() const {
return entryPoint;
@@ -220,13 +69,13 @@ public:
const u8* GetSectionDataPtr(int section) const {
if (section < 0 || section >= header->e_shnum)
return nullptr;
- if (sections[section].sh_type != SHT_NOBITS)
+ if (sections[section].sh_type != ElfShtNobits)
return GetPtr(sections[section].sh_offset);
else
return nullptr;
}
bool IsCodeSection(int section) const {
- return sections[section].sh_type == SHT_PROGBITS;
+ return sections[section].sh_type == ElfShtProgBits;
}
const u8* GetSegmentPtr(int segment) {
return GetPtr(segments[segment].p_offset);
@@ -256,7 +105,7 @@ ElfReader::ElfReader(void* ptr) {
}
const char* ElfReader::GetSectionName(int section) const {
- if (sections[section].sh_type == SHT_NULL)
+ if (sections[section].sh_type == ElfShtNull)
return nullptr;
int name_offset = sections[section].sh_name;
@@ -272,7 +121,7 @@ Kernel::CodeSet ElfReader::LoadInto(VAddr vaddr) {
LOG_DEBUG(Loader, "String section: {}", header->e_shstrndx);
// Should we relocate?
- relocate = (header->e_type != ET_EXEC);
+ relocate = (header->e_type != ElfTypeExec);
if (relocate) {
LOG_DEBUG(Loader, "Relocatable module");
@@ -288,7 +137,7 @@ Kernel::CodeSet ElfReader::LoadInto(VAddr vaddr) {
u64 total_image_size = 0;
for (unsigned int i = 0; i < header->e_phnum; ++i) {
const Elf32_Phdr* p = &segments[i];
- if (p->p_type == PT_LOAD) {
+ if (p->p_type == ElfPtLoad) {
total_image_size += (p->p_memsz + 0xFFF) & ~0xFFF;
}
}
@@ -303,14 +152,14 @@ Kernel::CodeSet ElfReader::LoadInto(VAddr vaddr) {
LOG_DEBUG(Loader, "Type: {} Vaddr: {:08X} Filesz: {:08X} Memsz: {:08X} ", p->p_type,
p->p_vaddr, p->p_filesz, p->p_memsz);
- if (p->p_type == PT_LOAD) {
+ if (p->p_type == ElfPtLoad) {
Kernel::CodeSet::Segment* codeset_segment;
- u32 permission_flags = p->p_flags & (PF_R | PF_W | PF_X);
- if (permission_flags == (PF_R | PF_X)) {
+ u32 permission_flags = p->p_flags & (ElfPfRead | ElfPfWrite | ElfPfExec);
+ if (permission_flags == (ElfPfRead | ElfPfExec)) {
codeset_segment = &codeset.CodeSegment();
- } else if (permission_flags == (PF_R)) {
+ } else if (permission_flags == (ElfPfRead)) {
codeset_segment = &codeset.RODataSegment();
- } else if (permission_flags == (PF_R | PF_W)) {
+ } else if (permission_flags == (ElfPfRead | ElfPfWrite)) {
codeset_segment = &codeset.DataSegment();
} else {
LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id {} with flags {:X}", i,