Browse Source

Add support for single stepping and fix fasm bug.

Giovanni Mascellani 5 years ago
parent
commit
a9504d1fe9
4 changed files with 139 additions and 13 deletions
  1. 4 1
      Makefile
  2. 83 10
      asmg/fasm.g
  3. 51 1
      boot/idt.asm
  4. 1 1
      contrib/fasm

+ 4 - 1
Makefile

@@ -52,7 +52,10 @@ diskfs/mescc/x86_defs.m1:
 	mkdir -p diskfs/mescc
 	cp contrib/M2-Planet/test/common_x86/x86_defs.M1 $@
 
-diskfs/fasm/fasm.asm: contrib/fasm/source/*.inc contrib/fasm/source/asmc/*
+# Unfortunately the order of the files is relevant here, otherwise
+# some internal offsets wrap around because they are store in single
+# words
+diskfs/fasm/fasm.asm: contrib/fasm/source/version.inc contrib/fasm/source/errors.inc contrib/fasm/source/symbdump.inc contrib/fasm/source/preproce.inc contrib/fasm/source/parser.inc contrib/fasm/source/exprpars.inc contrib/fasm/source/assemble.inc contrib/fasm/source/exprcalc.inc contrib/fasm/source/formats.inc contrib/fasm/source/x86_64.inc contrib/fasm/source/avx.inc contrib/fasm/source/tables.inc contrib/fasm/source/messages.inc contrib/fasm/source/variable.inc contrib/fasm/source/asmc/system.inc contrib/fasm/source/asmc/fasm.asm
 	mkdir -p diskfs/fasm
 	cat $^ > $@
 

+ 83 - 10
asmg/fasm.g

@@ -55,20 +55,20 @@ fun fasm_read 3 {
 
   $i
   @i 0 = ;
-  "Reading " 1 platform_log ;
-  count itoa 1 platform_log ;
-  " bytes: " 1 platform_log ;
+  #"Reading " 1 platform_log ;
+  #count itoa 1 platform_log ;
+  #" bytes: " 1 platform_log ;
   while i count < {
     $tmp
     @tmp fd vfs_read = ;
-    tmp 1 platform_write_char ;
+    #tmp 1 platform_write_char ;
     if tmp 0xffffffff == {
       0 ret ;
     }
     buf i + tmp =c ;
     @i i 1 + = ;
   }
-  " done!\n" 1 platform_log ;
+  #" done!\n" 1 platform_log ;
   1 ret ;
 }
 
@@ -104,9 +104,9 @@ fun fasm_lseek 3 {
 
   $res
   @res fd off whence vfs_seek = ;
-  "Seek to " 1 platform_log ;
-  res itoa 1 platform_log ;
-  "\n" 1 platform_log ;
+  #"Seek to " 1 platform_log ;
+  #res itoa 1 platform_log ;
+  #"\n" 1 platform_log ;
   res ret ;
 }
 
@@ -150,12 +150,70 @@ fun fasm_display_block 2 {
   }
 }
 
+$instr_num
 $ret_instr_enter
 
 fun error_additional_handler 0 {
-  "Fault happened after executing " 1 platform_log ;
+  "Fault happened after retiring " 1 platform_log ;
   read_ret_instr ret_instr_enter - itoa 1 platform_log ;
-  " instructions.\n" 1 platform_log ;
+  " instructions (according to PMC).\n" 1 platform_log ;
+  "Fault happened after executing " 1 platform_log ;
+  instr_num itoa 1 platform_log ;
+  " instructions (according to single step counter).\n" 1 platform_log ;
+}
+
+$dumping
+$breakpoint
+$breakpoint_instr_num
+
+fun single_step_handler 1 {
+  $regs
+  @regs 0 param = ;
+
+  $ip
+  @ip regs 0x20 + ** = ;
+
+  # "Instruction number " 1 platform_log ;
+  # instr_num itoa 1 platform_log ;
+  # "\n" 1 platform_log ;
+
+  @instr_num instr_num 1 + = ;
+
+  if breakpoint_instr_num 0 != instr_num breakpoint_instr_num == && {
+    @dumping 1 = ;
+  }
+
+  if ip breakpoint == {
+    @dumping 1 = ;
+  }
+
+  if dumping {
+    "EAX=" 1 platform_log ;
+    regs 0x1c + ** itoa 1 platform_log ;
+    ", EBX=" 1 platform_log ;
+    regs 0x10 + ** itoa 1 platform_log ;
+    ", ECX=" 1 platform_log ;
+    regs 0x18 + ** itoa 1 platform_log ;
+    ", EDX=" 1 platform_log ;
+    regs 0x14 + ** itoa 1 platform_log ;
+    ", ESI=" 1 platform_log ;
+    regs 0x4 + ** itoa 1 platform_log ;
+    ", EDI=" 1 platform_log ;
+    regs 0x0 + ** itoa 1 platform_log ;
+    ", ESP=" 1 platform_log ;
+    regs 0xc + ** itoa 1 platform_log ;
+    ", EBP=" 1 platform_log ;
+    regs 0x8 + ** itoa 1 platform_log ;
+    "\n" 1 platform_log ;
+
+    "Instruction number " 1 platform_log ;
+    instr_num itoa 1 platform_log ;
+    ": EIP=" 1 platform_log ;
+    ip itoa 1 platform_log ;
+    ", code: " 1 platform_log ;
+    ip 32 dump_mem ;
+    "\n\n" 1 platform_log ;
+  }
 }
 
 fun compile_fasm 0 {
@@ -211,14 +269,29 @@ fun compile_fasm 0 {
   read_ret_instr itoa 1 platform_log ;
   "\n" 1 platform_log ;
 
+  # Enable single stepping
+  @instr_num 0 = ;
+  @dumping 0 = ;
+  #@breakpoint ctx "fix_tables" asmctx_get_symbol_addr = ;
+  @breakpoint_instr_num 0 = ;
+  0x10010 @single_step_handler = ;
+  0x1001c ** \0 ;
+
   # Run fasm
   $res
   @res handles vector_data main_addr \1 = ;
 
+  # Disable single stepping
+  0x10014 0 = ;
+
   "Retired instruction counter after exiting fasm: " 1 platform_log ;
   read_ret_instr itoa 1 platform_log ;
   "\n" 1 platform_log ;
 
+  "Executed instruction number after exiting fasm: " 1 platform_log ;
+  instr_num itoa 1 platform_log ;
+  "\n" 1 platform_log ;
+
   "fasm returned " 1 platform_log ;
   res itoa 1 platform_log ;
   "\n" 1 platform_log ;

+ 51 - 1
boot/idt.asm

@@ -16,7 +16,10 @@
 ;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
   ADDITIONAL_HANDLER equ 0x10000
-  IDT_BASE equ 0x10010
+  SINGLE_STEP_HANDLER equ 0x10010
+  SINGLE_STEP_ENABLED equ 0x10014
+  ENABLE_SINGLE_STEP_HOOK equ 0x1001c
+  IDT_BASE equ 0x11000
   IDT_SIZE equ 0x800
 
 empty_idt:
@@ -72,6 +75,8 @@ setup_idt:
   mov dword [idt_offset], IDT_BASE
   lidt [idt_desc]
 
+  mov DWORD [ENABLE_SINGLE_STEP_HOOK], enable_single_step
+
   ret
 
   align 4
@@ -195,3 +200,48 @@ str_first_fault:
   db 'FIRST FAULT!', 0xa, 0xd, 0
 str_double_fault:
   db 'Double fault detected!', 0xa, 0xd, 0
+
+
+single_step_handler:
+  pusha
+  mov ebp, esp
+
+  ;; Possibly call the user defined handler
+  mov eax, [SINGLE_STEP_HANDLER]
+  test eax, eax
+  jz single_step_handler_restart
+  push ebp
+  call eax
+  add esp, 4
+
+single_step_handler_restart:
+  ;; Test if we have to reenable the trap flag
+  and DWORD [ebp+0x28], 0xfffffeff
+  mov eax, [SINGLE_STEP_ENABLED]
+  test eax, eax
+  jz single_step_handler_disable
+
+  ;; Reenable the trap flag
+  or DWORD [ebp+0x28], 0x100
+
+single_step_handler_disable:
+
+  popa
+  iret
+
+
+enable_single_step:
+  ;; Remember single step is enabled
+  mov DWORD [SINGLE_STEP_ENABLED], 1
+
+  ;; Fill the IDT entry
+  mov eax, 1
+  mov edx, single_step_handler
+  call fill_idt_entry
+
+  ;; Actually set flag
+  pushf
+  or DWORD [esp], 0x100
+  popf
+
+  ret

+ 1 - 1
contrib/fasm

@@ -1 +1 @@
-Subproject commit 34b300de518b99608adae1da160369cf42330243
+Subproject commit d198e99141b42b272fd3cefcf007a12b5be24adf