Subversion Repositories Kolibri OS

Rev

Rev 425 | Rev 465 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. $Revision: 431 $
  2. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3. ;;                                                              ;;
  4. ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
  5. ;; Distributed under terms of the GNU General Public License    ;;
  6. ;;                                                              ;;
  7. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  8.  
  9. ; diamond, 2006
  10. sys_debug_services:
  11.         cmp     eax, 9
  12.         ja      @f
  13.         jmp     dword [sys_debug_services_table+eax*4]
  14. @@:     ret
  15. sys_debug_services_table:
  16.         dd      debug_set_event_data
  17.         dd      debug_getcontext
  18.         dd      debug_setcontext
  19.         dd      debug_detach
  20.         dd      debug_suspend
  21.         dd      debug_resume
  22.         dd      debug_read_process_memory
  23.         dd      debug_write_process_memory
  24.         dd      debug_terminate
  25.         dd      debug_set_drx
  26.  
  27. debug_set_event_data:
  28. ; in: ebx = pointer
  29. ; destroys eax
  30.         mov     eax, [CURRENT_TASK]
  31.         shl     eax, 8
  32.         mov     [eax+SLOT_BASE+APPDATA.dbg_event_mem], ebx
  33.         ret
  34.  
  35. get_debuggee_slot:
  36. ; in: ebx=PID
  37. ; out: CF=1 if error
  38. ;      CF=0 and eax=slot*0x20 if ok
  39. ; out: interrupts disabled
  40.         cli
  41.         mov     eax, ebx
  42.         call    pid_to_slot
  43.         test    eax, eax
  44.         jz      .ret_bad
  45.         shl     eax, 5
  46.         push    ebx
  47.         mov     ebx, [CURRENT_TASK]
  48.         cmp     [SLOT_BASE+eax*8+APPDATA.debugger_slot], ebx
  49.         pop     ebx
  50.         jnz     .ret_bad
  51. ;       clc     ; automatically
  52.         ret
  53. .ret_bad:
  54.         stc
  55.         ret
  56.  
  57. debug_detach:
  58. ; in: ebx=pid
  59. ; destroys eax,ebx
  60.         call    get_debuggee_slot
  61.         jc      .ret
  62.         and     dword [eax*8+SLOT_BASE+APPDATA.debugger_slot], 0
  63.         call    do_resume
  64. .ret:
  65.         sti
  66.         ret
  67.  
  68. debug_terminate:
  69. ; in: ebx=pid
  70.         call    get_debuggee_slot
  71.         jc      debug_detach.ret
  72.         mov     ebx, eax
  73.         shr     ebx, 5
  74.         push    2
  75.         pop     eax
  76.         jmp     sys_system
  77.  
  78. debug_suspend:
  79. ; in: ebx=pid
  80. ; destroys eax,ebx
  81.         call    get_debuggee_slot
  82.         jc      .ret
  83.         mov     bl, [CURRENT_TASK+eax+TASKDATA.state] ; process state
  84.         test    bl, bl
  85.         jz      .1
  86.         cmp     bl, 5
  87.         jnz     .ret
  88.         mov     bl, 2
  89. .2:     mov     [CURRENT_TASK+eax+TASKDATA.state], bl
  90. .ret:
  91.         sti
  92.         ret
  93. .1:
  94.         inc     ebx
  95.         jmp     .2
  96.  
  97. do_resume:
  98.         mov     bl, [CURRENT_TASK+eax+TASKDATA.state]
  99.         cmp     bl, 1
  100.         jz      .1
  101.         cmp     bl, 2
  102.         jnz     .ret
  103.         mov     bl, 5
  104. .2:     mov     [CURRENT_TASK+eax+TASKDATA.state], bl
  105. .ret:   ret
  106. .1:     dec     ebx
  107.         jmp     .2
  108.  
  109. debug_resume:
  110. ; in: ebx=pid
  111. ; destroys eax,ebx
  112.         call    get_debuggee_slot
  113.         jc      .ret
  114.         call    do_resume
  115. .ret:   sti
  116.         ret
  117.  
  118. debug_getcontext:
  119. ; in:
  120. ; ebx=pid
  121. ; ecx=sizeof(CONTEXT)
  122. ; edx->CONTEXT
  123. ; destroys eax,ecx,edx,esi,edi
  124.         cmp     ecx, 28h
  125.         jnz     .ret
  126.         add     edx, std_application_base_address
  127.         push    ebx
  128.         mov     ebx, edx
  129.         call    check_region
  130.         pop     ebx
  131.         dec     eax
  132.         jnz     .ret
  133.         call    get_debuggee_slot
  134.         jc      .ret
  135.         imul    eax, tss_step/32
  136.         add     eax, tss_data
  137.         mov     edi, edx
  138.         cmp     [eax+TSS._cs], app_code
  139.         jnz     .ring0
  140.         lea     esi, [eax+TSS._eip]
  141.         shr     ecx, 2
  142.         rep     movsd
  143.         jmp     .ret
  144. .ring0:
  145. ; note that following code assumes that all interrupt/exception handlers
  146. ; saves ring-3 context by push ds es, pushad in this order
  147.         mov     esi, [eax+TSS._esp0]
  148. ; top of ring0 stack: ring3 stack ptr (ss+esp), iret data (cs+eip+eflags), ds, es, pushad
  149.         sub     esi, 8+12+8+20h
  150.         lodsd
  151.         mov     [edi+24h], eax
  152.         lodsd
  153.         mov     [edi+20h], eax
  154.         lodsd
  155.         mov     [edi+1Ch], eax
  156.         lodsd
  157.         lodsd
  158.         mov     [edi+14h], eax
  159.         lodsd
  160.         mov     [edi+10h], eax
  161.         lodsd
  162.         mov     [edi+0Ch], eax
  163.         lodsd
  164.         mov     [edi+8], eax
  165.         add     esi, 8
  166.         lodsd
  167.         mov     [edi], eax
  168.         lodsd
  169.         lodsd
  170.         mov     [edi+4], eax
  171.         lodsd
  172.         mov     [edi+18h], eax
  173. .ret:
  174.         sti
  175.         ret
  176.  
  177. debug_setcontext:
  178. ; in:
  179. ; ebx=pid
  180. ; ecx=sizeof(CONTEXT)
  181. ; edx->CONTEXT
  182. ; destroys eax,ecx,edx,esi,edi
  183.         cmp     ecx, 28h
  184.         jnz     .ret
  185.         add     edx, std_application_base_address
  186.         push    ebx
  187.         mov     ebx, edx
  188.         call    check_region
  189.         pop     ebx
  190.         dec     eax
  191.         jnz     .ret
  192.         call    get_debuggee_slot
  193.         jc      .stiret
  194.         imul    eax, tss_step/32
  195.         add     eax, tss_data
  196.         mov     esi, edx
  197.         cmp     [eax+TSS._cs], app_code
  198.         jnz     .ring0
  199.         lea     edi, [eax+TSS._eip]
  200.         shr     ecx, 2
  201.         rep     movsd
  202.         jmp     .stiret
  203. .ring0:
  204.         mov     edi, [eax+TSS._esp0]
  205.         sub     edi, 8+12+8+20h
  206.         mov     eax, [esi+24h]
  207.         stosd
  208.         mov     eax, [esi+20h]
  209.         stosd
  210.         mov     eax, [esi+1Ch]
  211.         stosd
  212.         scasd
  213.         mov     eax, [esi+14h]
  214.         stosd
  215.         mov     eax, [esi+10h]
  216.         stosd
  217.         mov     eax, [esi+0Ch]
  218.         stosd
  219.         mov     eax, [esi+8]
  220.         stosd
  221.         add     edi, 8
  222.         mov     eax, [esi]
  223.         stosd
  224.         scasd
  225.         mov     eax, [esi+4]
  226.         stosd
  227.         mov     eax, [esi+18h]
  228.         stosd
  229. .stiret:
  230.         sti
  231. .ret:
  232.         ret
  233.  
  234. debug_set_drx:
  235.         call    get_debuggee_slot
  236.         jc      .errret
  237.         mov     ebp, eax
  238.         lea     eax, [eax*8+SLOT_BASE+APPDATA.dbg_regs]
  239. ; [eax]=dr0, [eax+4]=dr1, [eax+8]=dr2, [eax+C]=dr3
  240. ; [eax+10]=dr7
  241.         add     edx, std_application_base_address
  242.         jc      .errret
  243.         cmp     cl, 3
  244.         ja      .errret
  245.         mov     ebx, dr7
  246.         shr     ebx, cl
  247.         shr     ebx, cl
  248.         test    ebx, 2          ; bit 1+2*index = G0..G3, global break enable
  249.         jnz     .errret2
  250.         test    ch, ch
  251.         jns     .new
  252. ; clear breakpoint
  253.         movzx   ecx, cl
  254.         add     ecx, ecx
  255.         and     dword [eax+ecx*2], 0    ; clear DR<i>
  256.         btr     dword [eax+10h], ecx    ; clear L<i> bit
  257.         test    byte [eax+10h], 55h
  258.         jnz     .okret
  259.         imul    eax, ebp, tss_step/32
  260.         and     byte [eax + tss_data + TSS._trap], not 1
  261. .okret:
  262.         and     dword [esp+36], 0
  263.         sti
  264.         ret
  265. .errret:
  266.         sti
  267.         mov     dword [esp+36], 1
  268.         ret
  269. .errret2:
  270.         sti
  271.         mov     dword [esp+36], 2
  272.         ret
  273. .new:
  274. ; add new breakpoint
  275. ; cl=index; ch=flags; edx=address
  276.         test    ch, 0xF0
  277.         jnz     .errret
  278.         mov     bl, ch
  279.         and     bl, 3
  280.         cmp     bl, 2
  281.         jz      .errret
  282.         mov     bl, ch
  283.         shr     bl, 2
  284.         cmp     bl, 2
  285.         jz      .errret
  286.         test    dl, bl
  287.         jnz     .errret
  288.         or      byte [eax+10h+1], 3     ; set GE and LE flags
  289.         movzx   ebx, ch
  290.         movzx   ecx, cl
  291.         add     ecx, ecx
  292.         bts     dword [eax+10h], ecx    ; set L<i> flag
  293.         add     ecx, ecx
  294.         mov     [eax+ecx], edx          ; set DR<i>
  295.         shl     ebx, cl
  296.         mov     edx, 0xF
  297.         shl     edx, cl
  298.         not     edx
  299.         and     [eax+10h+2], dx
  300.         or      [eax+10h+2], bx         ; set R/W and LEN fields
  301.         imul    eax, ebp, tss_step/32
  302.         or      byte [eax + tss_data + TSS._trap], 1
  303.         jmp     .okret
  304.  
  305. debug_read_process_memory:
  306. ; in:
  307. ; ebx=pid
  308. ; ecx=length
  309. ; esi->buffer in debugger
  310. ; edx=address in debuggee
  311. ; out: [esp+36]=sizeof(read)
  312. ; destroys all
  313.         add     esi, std_application_base_address
  314.         push    ebx
  315.         mov     ebx, esi
  316.         call    check_region
  317.         pop     ebx
  318.         dec     eax
  319.         jnz     .err
  320.         call    get_debuggee_slot
  321.         jc      .err
  322.         shr     eax, 5
  323.         mov     ebx, esi
  324.         call    read_process_memory
  325.         sti
  326.         mov     dword [esp+36], eax
  327.         ret
  328. .err:
  329.         or      dword [esp+36], -1
  330.         ret
  331.  
  332. debug_write_process_memory:
  333. ; in:
  334. ; ebx=pid
  335. ; ecx=length
  336. ; esi->buffer in debugger
  337. ; edx=address in debuggee
  338. ; out: [esp+36]=sizeof(write)
  339. ; destroys all
  340.         add     esi, std_application_base_address
  341.         push    ebx
  342.         mov     ebx, esi
  343.         call    check_region
  344.         pop     ebx
  345.         dec     eax
  346.         jnz     debug_read_process_memory.err
  347.         call    get_debuggee_slot
  348.         jc      debug_read_process_memory.err
  349.         shr     eax, 5
  350.         mov     ebx, esi
  351.         call    write_process_memory
  352.         sti
  353.         mov     [esp+36], eax
  354.         ret
  355.  
  356. debugger_notify:
  357. ; in: eax=debugger slot
  358. ;     ecx=size of debug message
  359. ;     [esp+4]..[esp+4+ecx]=message
  360. ; interrupts must be disabled!
  361. ; destroys all general registers
  362. ; interrupts remain disabled
  363.         xchg    ebp, eax
  364.         mov     edi, [timer_ticks]
  365.         add     edi, 500        ; 5 sec timeout
  366. .1:
  367.         mov     eax, ebp
  368.         shl     eax, 8
  369.         mov     edx, [SLOT_BASE+eax+APPDATA.dbg_event_mem]
  370.         test    edx, edx
  371.         jz      .ret
  372. ; read buffer header
  373.         push    ecx
  374.         push    eax
  375.         push    eax
  376.         mov     eax, ebp
  377.         mov     ebx, esp
  378.         mov     ecx, 8
  379.         call    read_process_memory
  380.         cmp     eax, ecx
  381.         jz      @f
  382.         add     esp, 12
  383.         jmp     .ret
  384. @@:
  385.         cmp     dword [ebx], 0
  386.         jg      @f
  387. .2:
  388.         pop     ecx
  389.         pop     ecx
  390.         pop     ecx
  391.         cmp     dword [CURRENT_TASK], 1
  392.         jnz     .notos
  393.         cmp     [timer_ticks], edi
  394.         jae     .ret
  395. .notos:
  396.         sti
  397.         call    change_task
  398.         cli
  399.         jmp     .1
  400. @@:
  401.         mov     ecx, [ebx+8]
  402.         add     ecx, [ebx+4]
  403.         cmp     ecx, [ebx]
  404.         ja      .2
  405. ; advance buffer position
  406.         push    ecx
  407.         mov     ecx, 4
  408.         sub     ebx, ecx
  409.         mov     eax, ebp
  410.         add     edx, ecx
  411.         call    write_process_memory
  412.         pop     eax
  413. ; write message
  414.         mov     eax, ebp
  415.         add     edx, ecx
  416.         add     edx, [ebx+8]
  417.         add     ebx, 20
  418.         pop     ecx
  419.         pop     ecx
  420.         pop     ecx
  421.         call    write_process_memory
  422. ; new debug event
  423.         mov     eax, ebp
  424.         shl     eax, 8
  425.         or      byte [SLOT_BASE+eax+APPDATA.event_mask+1], 1      ; set flag 100h
  426. .ret:
  427.         ret
  428.  
  429. debug_exc:
  430. ; int 1 = #DB
  431.         save_ring3_context
  432.         cld
  433.         mov     ax, os_data
  434.         mov     ds, ax
  435.         mov     es, ax
  436.         mov     eax, dr6
  437.         test    ax, ax
  438.         jns     @f
  439. ; this is exception from task switch
  440. ; set DRx registers for task and continue
  441.         mov     eax, [CURRENT_TASK]
  442.         shl     eax, 8
  443.         add     eax, SLOT_BASE+APPDATA.dbg_regs
  444.         mov     ecx, [eax+0]
  445.         mov     dr0, ecx
  446.         mov     ecx, [eax+4]
  447.         mov     dr1, ecx
  448.         mov     ecx, [eax+8]
  449.         mov     dr2, ecx
  450.         mov     ecx, [eax+0Ch]
  451.         mov     dr3, ecx
  452.         xor     ecx, ecx
  453.         mov     dr6, ecx
  454.         mov     ecx, [eax+10h]
  455.         mov     dr7, ecx
  456.         restore_ring3_context
  457.         iretd
  458. @@:
  459.         push    eax
  460.         xor     eax, eax
  461.         mov     dr6, eax
  462. ; test if debugging
  463.         cli
  464.         mov     eax, [CURRENT_TASK]
  465.         shl     eax, 8
  466.         mov     eax, [SLOT_BASE+eax+APPDATA.debugger_slot]
  467.         test    eax, eax
  468.         jnz     .debug
  469.         sti
  470. ; not debuggee => say error and terminate
  471.         add     esp, 28h+4
  472.         mov     [error_interrupt], 1
  473.         call    show_error_parameters
  474.         mov     edx, [TASK_BASE]
  475.         mov     byte [edx+TASKDATA.state], 4
  476.         jmp     change_task
  477. .debug:
  478. ; we are debugged process, notify debugger and suspend ourself
  479. ; eax=debugger PID
  480.         pop     edx
  481.         mov     ebx, dr7
  482.         mov     cl, not 1
  483. .l1:
  484.         test    bl, 1
  485.         jnz     @f
  486.         and     dl, cl
  487. @@:
  488.         shr     ebx, 2
  489.         add     cl, cl
  490.         inc     ecx
  491.         cmp     cl, not 10h
  492.         jnz     .l1
  493.         push    edx     ; DR6 image
  494.         mov     ecx, [TASK_BASE]
  495.         push    dword [ecx+TASKDATA.pid]        ; PID
  496.         push    12
  497.         pop     ecx
  498.         push    3       ; 3 = debug exception
  499.         call    debugger_notify
  500.         pop     ecx
  501.         pop     ecx
  502.         pop     ecx
  503.         mov     edx, [TASK_BASE]
  504.         mov     byte [edx+TASKDATA.state], 1    ; suspended
  505.         call    change_task
  506.         restore_ring3_context
  507.         iretd
  508.