summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/gdbstub/gdbstub.cpp20
-rw-r--r--src/core/hle/function_wrappers.h38
-rw-r--r--src/core/hle/svc.cpp66
3 files changed, 61 insertions, 63 deletions
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index be2b2e25f..d6be16ef6 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -644,7 +644,7 @@ static void ReadMemory() {
644 644
645 auto start_offset = command_buffer + 1; 645 auto start_offset = command_buffer + 1;
646 auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); 646 auto addr_pos = std::find(start_offset, command_buffer + command_length, ',');
647 PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); 647 VAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset));
648 648
649 start_offset = addr_pos + 1; 649 start_offset = addr_pos + 1;
650 u32 len = 650 u32 len =
@@ -656,12 +656,14 @@ static void ReadMemory() {
656 SendReply("E01"); 656 SendReply("E01");
657 } 657 }
658 658
659 const u8* data = Memory::GetPointer(addr); 659 if (!Memory::IsValidVirtualAddress(addr)) {
660 if (!data) {
661 return SendReply("E00"); 660 return SendReply("E00");
662 } 661 }
663 662
664 MemToGdbHex(reply, data, len); 663 std::vector<u8> data(len);
664 Memory::ReadBlock(addr, data.data(), len);
665
666 MemToGdbHex(reply, data.data(), len);
665 reply[len * 2] = '\0'; 667 reply[len * 2] = '\0';
666 SendReply(reinterpret_cast<char*>(reply)); 668 SendReply(reinterpret_cast<char*>(reply));
667} 669}
@@ -670,18 +672,20 @@ static void ReadMemory() {
670static void WriteMemory() { 672static void WriteMemory() {
671 auto start_offset = command_buffer + 1; 673 auto start_offset = command_buffer + 1;
672 auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); 674 auto addr_pos = std::find(start_offset, command_buffer + command_length, ',');
673 PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); 675 VAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset));
674 676
675 start_offset = addr_pos + 1; 677 start_offset = addr_pos + 1;
676 auto len_pos = std::find(start_offset, command_buffer + command_length, ':'); 678 auto len_pos = std::find(start_offset, command_buffer + command_length, ':');
677 u32 len = HexToInt(start_offset, static_cast<u32>(len_pos - start_offset)); 679 u32 len = HexToInt(start_offset, static_cast<u32>(len_pos - start_offset));
678 680
679 u8* dst = Memory::GetPointer(addr); 681 if (!Memory::IsValidVirtualAddress(addr)) {
680 if (!dst) {
681 return SendReply("E00"); 682 return SendReply("E00");
682 } 683 }
683 684
684 GdbHexToMem(dst, len_pos + 1, len); 685 std::vector<u8> data(len);
686
687 GdbHexToMem(data.data(), len_pos + 1, len);
688 Memory::WriteBlock(addr, data.data(), len);
685 SendReply("OK"); 689 SendReply("OK");
686} 690}
687 691
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index 5e6002f4e..f93439f21 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -58,22 +58,21 @@ void Wrap() {
58 FuncReturn(retval); 58 FuncReturn(retval);
59} 59}
60 60
61template <ResultCode func(s32*, u32*, s32, bool, s64)> 61template <ResultCode func(s32*, VAddr, s32, bool, s64)>
62void Wrap() { 62void Wrap() {
63 s32 param_1 = 0; 63 s32 param_1 = 0;
64 s32 retval = func(&param_1, (Kernel::Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), 64 s32 retval =
65 (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))) 65 func(&param_1, PARAM(1), (s32)PARAM(2), (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0)))
66 .raw; 66 .raw;
67 67
68 Core::CPU().SetReg(1, (u32)param_1); 68 Core::CPU().SetReg(1, (u32)param_1);
69 FuncReturn(retval); 69 FuncReturn(retval);
70} 70}
71 71
72template <ResultCode func(s32*, u32*, s32, u32)> 72template <ResultCode func(s32*, VAddr, s32, u32)>
73void Wrap() { 73void Wrap() {
74 s32 param_1 = 0; 74 s32 param_1 = 0;
75 u32 retval = 75 u32 retval = func(&param_1, PARAM(1), (s32)PARAM(2), PARAM(3)).raw;
76 func(&param_1, (Kernel::Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), PARAM(3)).raw;
77 76
78 Core::CPU().SetReg(1, (u32)param_1); 77 Core::CPU().SetReg(1, (u32)param_1);
79 FuncReturn(retval); 78 FuncReturn(retval);
@@ -152,21 +151,6 @@ void Wrap() {
152 FuncReturn(func(PARAM(0)).raw); 151 FuncReturn(func(PARAM(0)).raw);
153} 152}
154 153
155template <ResultCode func(s64*, u32, u32*, u32)>
156void Wrap() {
157 FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1),
158 (u32*)Memory::GetPointer(PARAM(2)), (s32)PARAM(3))
159 .raw);
160}
161
162template <ResultCode func(u32*, const char*)>
163void Wrap() {
164 u32 param_1 = 0;
165 u32 retval = func(&param_1, (char*)Memory::GetPointer(PARAM(1))).raw;
166 Core::CPU().SetReg(1, param_1);
167 FuncReturn(retval);
168}
169
170template <ResultCode func(u32*, s32, s32)> 154template <ResultCode func(u32*, s32, s32)>
171void Wrap() { 155void Wrap() {
172 u32 param_1 = 0; 156 u32 param_1 = 0;
@@ -222,13 +206,11 @@ void Wrap() {
222 FuncReturn(func(PARAM(0), PARAM(1)).raw); 206 FuncReturn(func(PARAM(0), PARAM(1)).raw);
223} 207}
224 208
225template <ResultCode func(Kernel::Handle*, Kernel::Handle*, const char*, u32)> 209template <ResultCode func(Kernel::Handle*, Kernel::Handle*, VAddr, u32)>
226void Wrap() { 210void Wrap() {
227 Kernel::Handle param_1 = 0; 211 Kernel::Handle param_1 = 0;
228 Kernel::Handle param_2 = 0; 212 Kernel::Handle param_2 = 0;
229 u32 retval = func(&param_1, &param_2, 213 u32 retval = func(&param_1, &param_2, PARAM(2), PARAM(3)).raw;
230 reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3))
231 .raw;
232 Core::CPU().SetReg(1, param_1); 214 Core::CPU().SetReg(1, param_1);
233 Core::CPU().SetReg(2, param_2); 215 Core::CPU().SetReg(2, param_2);
234 FuncReturn(retval); 216 FuncReturn(retval);
@@ -268,9 +250,9 @@ void Wrap() {
268 func(((s64)PARAM(1) << 32) | PARAM(0)); 250 func(((s64)PARAM(1) << 32) | PARAM(0));
269} 251}
270 252
271template <void func(const char*, int len)> 253template <void func(VAddr, int len)>
272void Wrap() { 254void Wrap() {
273 func((char*)Memory::GetPointer(PARAM(0)), PARAM(1)); 255 func(PARAM(0), PARAM(1));
274} 256}
275 257
276template <void func(u8)> 258template <void func(u8)>
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 6be5db13f..e8ca419d5 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -201,17 +201,21 @@ static ResultCode UnmapMemoryBlock(Kernel::Handle handle, u32 addr) {
201} 201}
202 202
203/// Connect to an OS service given the port name, returns the handle to the port to out 203/// Connect to an OS service given the port name, returns the handle to the port to out
204static ResultCode ConnectToPort(Kernel::Handle* out_handle, const char* port_name) { 204static ResultCode ConnectToPort(Kernel::Handle* out_handle, VAddr port_name_address) {
205 if (port_name == nullptr) 205 if (!Memory::IsValidVirtualAddress(port_name_address))
206 return Kernel::ERR_NOT_FOUND; 206 return Kernel::ERR_NOT_FOUND;
207 if (std::strlen(port_name) > 11) 207
208 static constexpr std::size_t PortNameMaxLength = 11;
209 // Read 1 char beyond the max allowed port name to detect names that are too long.
210 std::string port_name = Memory::ReadCString(port_name_address, PortNameMaxLength + 1);
211 if (port_name.size() > PortNameMaxLength)
208 return Kernel::ERR_PORT_NAME_TOO_LONG; 212 return Kernel::ERR_PORT_NAME_TOO_LONG;
209 213
210 LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name); 214 LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name.c_str());
211 215
212 auto it = Service::g_kernel_named_ports.find(port_name); 216 auto it = Service::g_kernel_named_ports.find(port_name);
213 if (it == Service::g_kernel_named_ports.end()) { 217 if (it == Service::g_kernel_named_ports.end()) {
214 LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name); 218 LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name.c_str());
215 return Kernel::ERR_NOT_FOUND; 219 return Kernel::ERR_NOT_FOUND;
216 } 220 }
217 221
@@ -303,12 +307,11 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds)
303} 307}
304 308
305/// Wait for the given handles to synchronize, timeout after the specified nanoseconds 309/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
306static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 handle_count, 310static ResultCode WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle_count,
307 bool wait_all, s64 nano_seconds) { 311 bool wait_all, s64 nano_seconds) {
308 Kernel::Thread* thread = Kernel::GetCurrentThread(); 312 Kernel::Thread* thread = Kernel::GetCurrentThread();
309 313
310 // Check if 'handles' is invalid 314 if (!Memory::IsValidVirtualAddress(handles_address))
311 if (handles == nullptr)
312 return Kernel::ERR_INVALID_POINTER; 315 return Kernel::ERR_INVALID_POINTER;
313 316
314 // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If 317 // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If
@@ -323,7 +326,8 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
323 std::vector<ObjectPtr> objects(handle_count); 326 std::vector<ObjectPtr> objects(handle_count);
324 327
325 for (int i = 0; i < handle_count; ++i) { 328 for (int i = 0; i < handle_count; ++i) {
326 auto object = Kernel::g_handle_table.Get<Kernel::WaitObject>(handles[i]); 329 Kernel::Handle handle = Memory::Read32(handles_address + i * sizeof(Kernel::Handle));
330 auto object = Kernel::g_handle_table.Get<Kernel::WaitObject>(handle);
327 if (object == nullptr) 331 if (object == nullptr)
328 return ERR_INVALID_HANDLE; 332 return ERR_INVALID_HANDLE;
329 objects[i] = object; 333 objects[i] = object;
@@ -452,10 +456,9 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
452} 456}
453 457
454/// In a single operation, sends a IPC reply and waits for a new request. 458/// In a single operation, sends a IPC reply and waits for a new request.
455static ResultCode ReplyAndReceive(s32* index, Kernel::Handle* handles, s32 handle_count, 459static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_count,
456 Kernel::Handle reply_target) { 460 Kernel::Handle reply_target) {
457 // 'handles' has to be a valid pointer even if 'handle_count' is 0. 461 if (!Memory::IsValidVirtualAddress(handles_address))
458 if (handles == nullptr)
459 return Kernel::ERR_INVALID_POINTER; 462 return Kernel::ERR_INVALID_POINTER;
460 463
461 // Check if 'handle_count' is invalid 464 // Check if 'handle_count' is invalid
@@ -466,7 +469,8 @@ static ResultCode ReplyAndReceive(s32* index, Kernel::Handle* handles, s32 handl
466 std::vector<ObjectPtr> objects(handle_count); 469 std::vector<ObjectPtr> objects(handle_count);
467 470
468 for (int i = 0; i < handle_count; ++i) { 471 for (int i = 0; i < handle_count; ++i) {
469 auto object = Kernel::g_handle_table.Get<Kernel::WaitObject>(handles[i]); 472 Kernel::Handle handle = Memory::Read32(handles_address + i * sizeof(Kernel::Handle));
473 auto object = Kernel::g_handle_table.Get<Kernel::WaitObject>(handle);
470 if (object == nullptr) 474 if (object == nullptr)
471 return ERR_INVALID_HANDLE; 475 return ERR_INVALID_HANDLE;
472 objects[i] = object; 476 objects[i] = object;
@@ -619,8 +623,10 @@ static void Break(u8 break_reason) {
619} 623}
620 624
621/// Used to output a message on a debug hardware unit - does nothing on a retail unit 625/// Used to output a message on a debug hardware unit - does nothing on a retail unit
622static void OutputDebugString(const char* string, int len) { 626static void OutputDebugString(VAddr address, int len) {
623 LOG_DEBUG(Debug_Emulated, "%.*s", len, string); 627 std::vector<char> string(len);
628 Memory::ReadBlock(address, string.data(), len);
629 LOG_DEBUG(Debug_Emulated, "%.*s", len, string.data());
624} 630}
625 631
626/// Get resource limit 632/// Get resource limit
@@ -638,9 +644,9 @@ static ResultCode GetResourceLimit(Kernel::Handle* resource_limit, Kernel::Handl
638} 644}
639 645
640/// Get resource limit current values 646/// Get resource limit current values
641static ResultCode GetResourceLimitCurrentValues(s64* values, Kernel::Handle resource_limit_handle, 647static ResultCode GetResourceLimitCurrentValues(VAddr values, Kernel::Handle resource_limit_handle,
642 u32* names, u32 name_count) { 648 VAddr names, u32 name_count) {
643 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", 649 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%08X, name_count=%d",
644 resource_limit_handle, names, name_count); 650 resource_limit_handle, names, name_count);
645 651
646 SharedPtr<Kernel::ResourceLimit> resource_limit = 652 SharedPtr<Kernel::ResourceLimit> resource_limit =
@@ -648,16 +654,19 @@ static ResultCode GetResourceLimitCurrentValues(s64* values, Kernel::Handle reso
648 if (resource_limit == nullptr) 654 if (resource_limit == nullptr)
649 return ERR_INVALID_HANDLE; 655 return ERR_INVALID_HANDLE;
650 656
651 for (unsigned int i = 0; i < name_count; ++i) 657 for (unsigned int i = 0; i < name_count; ++i) {
652 values[i] = resource_limit->GetCurrentResourceValue(names[i]); 658 u32 name = Memory::Read32(names + i * sizeof(u32));
659 s64 value = resource_limit->GetCurrentResourceValue(name);
660 Memory::Write64(values + i * sizeof(u64), value);
661 }
653 662
654 return RESULT_SUCCESS; 663 return RESULT_SUCCESS;
655} 664}
656 665
657/// Get resource limit max values 666/// Get resource limit max values
658static ResultCode GetResourceLimitLimitValues(s64* values, Kernel::Handle resource_limit_handle, 667static ResultCode GetResourceLimitLimitValues(VAddr values, Kernel::Handle resource_limit_handle,
659 u32* names, u32 name_count) { 668 VAddr names, u32 name_count) {
660 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", 669 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%08X, name_count=%d",
661 resource_limit_handle, names, name_count); 670 resource_limit_handle, names, name_count);
662 671
663 SharedPtr<Kernel::ResourceLimit> resource_limit = 672 SharedPtr<Kernel::ResourceLimit> resource_limit =
@@ -665,8 +674,11 @@ static ResultCode GetResourceLimitLimitValues(s64* values, Kernel::Handle resour
665 if (resource_limit == nullptr) 674 if (resource_limit == nullptr)
666 return ERR_INVALID_HANDLE; 675 return ERR_INVALID_HANDLE;
667 676
668 for (unsigned int i = 0; i < name_count; ++i) 677 for (unsigned int i = 0; i < name_count; ++i) {
669 values[i] = resource_limit->GetMaxResourceValue(names[i]); 678 u32 name = Memory::Read32(names + i * sizeof(u32));
679 s64 value = resource_limit->GetMaxResourceValue(names);
680 Memory::Write64(values + i * sizeof(u64), value);
681 }
670 682
671 return RESULT_SUCCESS; 683 return RESULT_SUCCESS;
672} 684}
@@ -1098,9 +1110,9 @@ static ResultCode CreateMemoryBlock(Kernel::Handle* out_handle, u32 addr, u32 si
1098} 1110}
1099 1111
1100static ResultCode CreatePort(Kernel::Handle* server_port, Kernel::Handle* client_port, 1112static ResultCode CreatePort(Kernel::Handle* server_port, Kernel::Handle* client_port,
1101 const char* name, u32 max_sessions) { 1113 VAddr name_address, u32 max_sessions) {
1102 // TODO(Subv): Implement named ports. 1114 // TODO(Subv): Implement named ports.
1103 ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented"); 1115 ASSERT_MSG(name_address == 0, "Named ports are currently unimplemented");
1104 1116
1105 using Kernel::ServerPort; 1117 using Kernel::ServerPort;
1106 using Kernel::ClientPort; 1118 using Kernel::ClientPort;