diff --git a/common/goal_constants.h b/common/goal_constants.h index ea8d47375..91f5f2506 100644 --- a/common/goal_constants.h +++ b/common/goal_constants.h @@ -28,7 +28,7 @@ constexpr u32 GOAL_MEMUSAGE_METHOD = 8; // method ID of GOAL mem-usage constexpr int EE_MAIN_MEM_LOW_PROTECT = 1024 * 1024; constexpr int EE_MAIN_MEM_SIZE = 128 * (1 << 20); // 128 MB, same as PS2 TOOL -constexpr u64 EE_MAIN_MEM_MAP = 0x2000000000; // intentionally > 32-bit to catch pointer bugs +constexpr u64 EE_MAIN_MEM_MAP = 0x2123000000; // intentionally > 32-bit to catch pointer bugs // when true, attempt to map the EE memory in the low 2 GB of RAM // this allows us to use EE pointers as real pointers. However, this might not always work, diff --git a/decompiler/config/all-types.gc b/decompiler/config/all-types.gc index f1015fbc2..50d2da892 100644 --- a/decompiler/config/all-types.gc +++ b/decompiler/config/all-types.gc @@ -415,6 +415,10 @@ (enter function :offset-assert 28) (event basic :offset-assert 32) ) + (:methods + (new ((allocation symbol) (type-to-make type) (name basic) (code function) + (trans function) (enter function) (exit (function object)) (event function)) _type_ 0) + ) :method-count-assert 9 :size-assert #x24 :flag-assert #x900000024 diff --git a/game/kernel/kscheme.cpp b/game/kernel/kscheme.cpp index 9b1a3b93d..50bac9ef9 100644 --- a/game/kernel/kscheme.cpp +++ b/game/kernel/kscheme.cpp @@ -1060,7 +1060,6 @@ u64 call_method_of_type(u32 arg, Ptr type, u32 method_id) { } // throw std::runtime_error("call_method_of_type failed!\n"); printf("[ERROR] call_method_of_type failed!\n"); - printf("type is %s\n", info(type->symbol)->str->data()); return arg; } diff --git a/goal_src/kernel/gkernel-h.gc b/goal_src/kernel/gkernel-h.gc index b6df25f9e..8699b31d5 100644 --- a/goal_src/kernel/gkernel-h.gc +++ b/goal_src/kernel/gkernel-h.gc @@ -422,6 +422,11 @@ (event basic :offset-assert 32) ;; event handler function? ) + (:methods + (new ((allocation symbol) (type-to-make type) (name basic) (code function) + (trans function) (enter function) (exit (function object)) (event function)) _type_ 0) + ) + :size-assert #x24 :method-count-assert 9 :flag-assert #x900000024 diff --git a/goal_src/kernel/gkernel.gc b/goal_src/kernel/gkernel.gc index 1ef791a22..172c97d7d 100644 --- a/goal_src/kernel/gkernel.gc +++ b/goal_src/kernel/gkernel.gc @@ -1800,7 +1800,7 @@ ;; remember the stack pointer (set! temp sp) (.sub temp off) - (set! (-> obj sp) (the int sp)) + (set! (-> obj sp) (the int temp)) ;; back up registers we care about (.mov :color #f temp s0) @@ -1822,6 +1822,7 @@ ;; help coloring, it isn't smart enough to realize it's "safe" to use these registers. (.push :color #f s3) (.push :color #f s2) + (.push :color #f s2) (set! s3 (the uint func)) (set! s2 param-block) @@ -1835,7 +1836,7 @@ (-> s2 5) )) ) - + (.pop :color #f s2) (.pop :color #f s2) (.pop :color #f s3) (set! (-> pp stack-frame-top) (-> pp stack-frame-top next)) @@ -1846,6 +1847,7 @@ ) ) + (defun throw-dispatch ((obj catch-frame) value) "Throw the given value to the catch frame. Only can throw a 64-bit value. The original could throw 128 bits." @@ -1903,6 +1905,7 @@ (while cur (when (and (eq? (-> cur name) name) (eq? (-> cur type) catch-frame)) ;; match! + (throw-dispatch (the catch-frame cur) value) ) @@ -1910,6 +1913,7 @@ ;; call the cleanup function ((-> (the protect-frame cur) exit)) ) + (set! cur (-> cur next)) ) ) ) @@ -2015,11 +2019,12 @@ The function will run until it attempts to change state. At the first attempt to change state, this function will return. The idea is that you use this when you want to initialize a process NOW. This will then return the value of the function you called!" - (rlet ((pp :reg r13 :type process)) - (let ((param-array (new 'stack 'array 'uint64 6))) + (let ((param-array (new 'stack 'array 'uint64 6)) + ) ;; copy params to the stack. + (set! (-> param-array 0) (the uint64 a0)) (set! (-> param-array 1) (the uint64 a1)) (set! (-> param-array 2) (the uint64 a2)) @@ -2045,7 +2050,7 @@ ;; this means we died, and we should be deactivated. (deactivate pp) ) - ((= (-> pp status) 'initalize-go) + ((= (-> pp status) 'initialize-go) ;; we returned with a (suspend) or (go) ? not sure ;; either way, we're ready for next time! (set! (-> pp status) 'waiting-to-run) @@ -2251,7 +2256,7 @@ ; (break) ; ) (set! (-> obj status) 'dead) - (throw 'initalize #f) + (throw 'initialize #f) ) ) (set! (-> obj status) 'dead) diff --git a/goal_src/kernel/gstate.gc b/goal_src/kernel/gstate.gc index 664d61479..b3bb38d27 100644 --- a/goal_src/kernel/gstate.gc +++ b/goal_src/kernel/gstate.gc @@ -4,4 +4,3 @@ ;; name: gstate.gc ;; name in dgo: gstate ;; dgos: KERNEL - diff --git a/goalc/debugger/Debugger.cpp b/goalc/debugger/Debugger.cpp index 2856f602a..8cb56be02 100644 --- a/goalc/debugger/Debugger.cpp +++ b/goalc/debugger/Debugger.cpp @@ -193,8 +193,8 @@ void Debugger::update_break_info() { int rip_offset = 0; if (m_continue_info.valid && m_continue_info.is_addr_breakpiont) { - int offset_in_fmem = int(m_continue_info.addr_breakpoint.goal_addr) - - (map_loc.start_addr + info->offset_in_seg); + int offset_in_fmem = uint64_t(m_continue_info.addr_breakpoint.goal_addr) - + uint64_t(map_loc.start_addr + info->offset_in_seg); if (offset_in_fmem < 0 || offset_in_fmem >= int(function_mem.size())) { m_break_info.disassembly_failed = true; } else { @@ -580,7 +580,7 @@ void Debugger::update_continue_info() { update_break_info(); } - auto kv = m_addr_breakpoints.find(get_regs().rip - 1); + auto kv = m_addr_breakpoints.find(get_regs().rip - m_debug_context.base - 1); if (kv == m_addr_breakpoints.end()) { m_continue_info.subtract_1 = false; m_continue_info.is_addr_breakpiont = false; diff --git a/goalc/listener/Listener.cpp b/goalc/listener/Listener.cpp index 483616d4f..50338f6fd 100644 --- a/goalc/listener/Listener.cpp +++ b/goalc/listener/Listener.cpp @@ -90,6 +90,8 @@ bool Listener::connect_to_target(int n_tries, const std::string& ip, int port) { return true; } + disconnect(); + if (listen_socket >= 0) { close_socket(listen_socket); } diff --git a/test/goalc/source_templates/kernel/kernel-test.gc b/test/goalc/source_templates/kernel/kernel-test.gc index 2ee6697c9..68d523c71 100644 --- a/test/goalc/source_templates/kernel/kernel-test.gc +++ b/test/goalc/source_templates/kernel/kernel-test.gc @@ -1,3 +1,35 @@ +; (defun get-saved-regs ((dest (pointer uint64))) +; (rlet ((s0 :reg rbx :type uint) +; (s1 :reg rbp :type uint) +; (s2 :reg r10 :type uint) +; (s3 :reg r11 :type uint) +; (s4 :reg r12 :type uint)) +; (set! (-> dest 0) s0) +; (set! (-> dest 1) s1) +; (set! (-> dest 2) s2) +; (set! (-> dest 3) s3) +; (set! (-> dest 4) s4) + +; ) +; ) + +(defmacro with-named-reg-vars-check (&rest body) + `(let ((one 1) + (two 2) + (three 3) + (four 4) + (five 5) + (six 6) + (seven 7) + (eight 8) + (nine 9)) + ,@body + (format 0 "~d ~d ~d ~d ~d ~d " one two three four five six) + (format 0 "~d ~d ~d~%" seven eight nine) + ) + + ) + (defun deactivate-myself () "Deactivate the current process. A workaround because rlet isn't working well." (rlet ((pp :reg r13 :type process)) @@ -62,3 +94,44 @@ 0 0 0 0 0 0) 0 ) + +(defun init-child-proc (a0 a1 a2 a3 a4 a5) + (format #t "Args: ~D ~D ~D~%" a0 a1 a2) + (format #t "~D ~D ~D~%" a3 a4 a5) + (let ((stack-arr (new 'stack 'array 'uint8 12))) + (format #t "Stack Alignemnt ~D/16~%" (logand 15 (the uint stack-arr))) + ) + (if (eq? a0 (the int 0)) + (deactivate-myself) + ) + 'init-child-proc-result + ) + + +(defun initializer-process-function (a0) + (let ((child-proc (get-process *nk-dead-pool* process 1024))) + ;; let's go + (activate child-proc *active-pool* 'child-proc *kernel-dram-stack*) + (let ((result (run-function-in-process child-proc init-child-proc a0 2 3 4 5 6))) + (format #t "run-function-in-process result: ~A~%" result) + ) + ) + + (deactivate-myself) + ) + +(defun kernel-test-2 () + (define initalizer-process (get-process *nk-dead-pool* process 1024)) + (activate initalizer-process *active-pool* 'initializer-proc *kernel-dram-stack*) + (set-to-run (-> initalizer-process main-thread) + initializer-process-function + 0 0 0 0 0 0 + ) + (define initalizer-process-2 (get-process *nk-dead-pool* process 1024)) + (activate initalizer-process-2 *active-pool* 'initializer-proc-2 *kernel-dram-stack*) + (set-to-run (-> initalizer-process-2 main-thread) + initializer-process-function + 1 0 0 0 0 0 + ) + 0 + ) \ No newline at end of file diff --git a/test/goalc/test_goal_kernel.cpp b/test/goalc/test_goal_kernel.cpp index d270e38d9..85fe4fbf3 100644 --- a/test/goalc/test_goal_kernel.cpp +++ b/test/goalc/test_goal_kernel.cpp @@ -40,27 +40,32 @@ std::thread KernelTest::runtime_thread; Compiler KernelTest::compiler; GoalTest::CompilerTestRunner KernelTest::runner; -TEST_F(KernelTest, Basic) { - // first, let's load the kernel test code - runner.c->run_test_from_string("(ml \"test/goalc/source_templates/kernel/kernel-test.gc\")"); - auto& listener = runner.c->listener(); - +namespace { +std::string send_code_and_get_multiple_responses(const std::string& code, + int n_responses, + GoalTest::CompilerTestRunner* runner) { + auto& listener = runner->c->listener(); // record all print messages listener.record_messages(ListenerMessageKind::MSG_PRINT); // run the test. - runner.c->compile_and_send_from_string("(kernel-test)"); - - // kinda hacky, but wait until the kernel runs and sends all the messages - while (listener.get_received_message_count() < 10) { + runner->c->compile_and_send_from_string(code); + std::string result; + while (listener.get_received_message_count() < n_responses) { std::this_thread::sleep_for(std::chrono::microseconds(1000)); } auto messages = listener.stop_recording_messages(); - std::string result; for (auto& m : messages) { result += m; } + return result; +} +} // namespace + +TEST_F(KernelTest, Basic) { + runner.c->run_test_from_string("(ml \"test/goalc/source_templates/kernel/kernel-test.gc\")"); + std::string result = send_code_and_get_multiple_responses("(kernel-test)", 10, &runner); std::string expected = "0\n" @@ -86,4 +91,21 @@ TEST_F(KernelTest, Basic) { "proc2: 54\n"; EXPECT_EQ(expected, result); +} + +TEST_F(KernelTest, RunFunctionInProcess) { + runner.c->run_test_from_string("(ml \"test/goalc/source_templates/kernel/kernel-test.gc\")"); + std::string result = send_code_and_get_multiple_responses("(kernel-test-2)", 1, &runner); + + std::string expected = + "0\n" + "Args: 1 2 3\n" + "4 5 6\n" + "Stack Alignemnt 0/16\n" + "run-function-in-process result: init-child-proc-result\n" + "Args: 0 2 3\n" + "4 5 6\n" + "Stack Alignemnt 0/16\n" + "run-function-in-process result: #f\n"; + EXPECT_EQ(expected, result); } \ No newline at end of file