Add another kernel test, fix small bugs (#156)

* temp

* run function in process test

* windows debug

* debug

* update

* update

* again

* update

* fix same bug in debugger
This commit is contained in:
water111 2020-12-10 20:26:40 -05:00 committed by GitHub
parent e05f3ceefc
commit ba919a069c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 131 additions and 22 deletions

View file

@ -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,

View file

@ -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

View file

@ -1060,7 +1060,6 @@ u64 call_method_of_type(u32 arg, Ptr<Type> 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;
}

View file

@ -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

View file

@ -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)

View file

@ -4,4 +4,3 @@
;; name: gstate.gc
;; name in dgo: gstate
;; dgos: KERNEL

View file

@ -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;

View file

@ -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);
}

View file

@ -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
)

View file

@ -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);
}