Very Advanced Debugging Tips - Calvin Hsia's WebLog - Site Home - MSDN Blogs

Embed Size (px)

Citation preview

  • 8/9/2019 Very Advanced Debugging Tips - Calvin Hsia's WebLog - Site Home - MSDN Blogs

    1/3

    Very Advanced Debugging tips

    9CalvinH 22 Oct 2004 9:56 AM

    While debugging code, it might take very many complicated steps to reproduce an issue. The following applies to

    debugging both Visual FoxPro and Visual Studio Native code debugging, except where noted. The VFP

    debugger is modeled after the VS debugger, with the same plethora of windows: call stack, output, watch, locals,

    etc.)

     

    Stepping through from breakpoint to breakpoint, you might accidentally step over a function/method call rather

    than into it. Just right click on the desired line and choose Set Next Statement (or Shift-Ctrl-F10 in VS) This is

    changing the Instruction Pointer (IP). Keep in mind this executes the function again, and it may have had side

    effects. Also, you can’t just change the Instruction Pointer arbitrarily. Both VS and VFP give a warning when you

    try to do something bad, like Set Next Statement into a different function, bypassing function initialization, local

    variable declarations, etc.

     

    The Call stack is your friend. It’s very important to see how the code you’re looking at got called. You can click on

    the call stack at various levels to examine variables and code at those levels.

     

    Many times, debugging causes the application to behave differently. For example, put a breakpoint on the VFP

    Activate Method or the Window Procedure WM_ACTIVATE and it will be fired every time you resume from the

    debugger. In this and many other cases, it’s important to use the Debug Output window to show values

    dynamically.

     

    In VFP, “DEBUGOUT "this is a test", _vfp.Caption” will output to the Debug Output window. For native

    code, the OutputDebugString API will do the trick.

     Another useful technique is to modify the code and continue debugging. In certain versions of VB and VC# you

    could do that with native VS support called “Edit and Continue”. In FoxPro, you can do that by stepping out of the

    compiled code (PRG or VCX) , recompiling just that part, then stepping back in (via Set Next Statement). FoxPro

    does not require you to build an APP or EXE to run your code, so your code compile granularity is quite small. In

    VS Native code debugging, you can do that by stepping out until the module you want to modify is unloaded, then

    it can be recompiled and reloaded. Same idea as VFP, but the compiled unit granularity is quite coarse.

    However, in VS there is another simple way if the code you want to c change is fairly minor.

     

    The rest of this blog concerns only VS debugging: not VFP.

     

    (Tip: Make sure you have debug symbols loaded: here’s how)

     

    Just right click and choose Go To Disassembly(Ctrl-F11) and make sure addresses and code bytes are displayed

    (context menu).

     

    Here’s an example 

    if (sysusr >= MNPUSHFROMDEFAULT_MENU_BAR) {

    0094E284 83 7D 10 64 cmp dword ptr [sysusr],64h

    0094E288 7C 14 jl MNPushMenu2+1AEh (94E29Eh)

      miPtr->iStatus &= ~(IONSELSET | IONENTRYSET | IONEXITSET);

    0094E28A 8B 45 EC mov eax,dword ptr [miPtr]

    0094E28D 8B 48 04 mov ecx,dword ptr [eax+4]

    0094E290 81 E1 7F CF FF FF and ecx,0FFFFCF7Fh

    0094E296 8B 55 EC mov edx,dword ptr [miPtr]

    0094E299 89 4A 04 mov dword ptr [edx+4],ecx

      } else {

    0094E29C EB 12 jmp MNPushMenu2+1C0h (94E2B0h)

      niPtr->iStatus &= ~(IONSELSET | IONENTRYSET | IONEXITSET);

    0094E29E 8B 45 E8 mov eax,dword ptr [niPtr]

    0094E2A1 8B 48 04 mov ecx,dword ptr [eax+4]

    0094E2A4 81 E1 7F CF FF FF and ecx,0FFFFCF7Fh

    0094E2AA 8B 55 E8 mov edx,dword ptr [niPtr]

    0094E2AD 89 4A 04 mov dword ptr [edx+4],ecx

      }

     

    In this code, I want to change the code to do the code in the else clause always (remove the “else” line). It’s a

    simple modification without recompiling.

     

    Open a memory window via Debug->Window->Memory or Ctrl-Alt-M1 for Whidbey (I think it’s Ctrl-Alt-M for

    VS.Net 2003, which only had 1 memory window, instead of the 4 for Whidbey).

     

    Drag the desired address and drop it on the memory window.0x0094E29C eb 12 8b 45 e8 8b 48 04

    0x0094E2A4 81 e1 7f cf ff ff 8b 55

    0x0094E2AC e8 89 4a 04 e9 28 ff ff

    0x0094E2B4 ff 8b 45 f4 83 38 02 74

    You see the “else” being a 2 byte “jmp” instruction.

    We just want to replace these 2 bytes with a NOP (No Operation: Op Code= 0x90) which does nothing. Just

    change the “eb 12” in the memory window (it even has UnDo) to “90 90”

     

    The disassembly reflects this nicely:

     0094E299 89 4A 04 mov dword ptr [edx+4],ecx  } else {

    0094E29C 90 nop

    0094E29D 90 nop

    Now the currently loaded code has been changed and the modified version of this code will be executed. The

    disk version of the module has not been changed.

    y Advanced Debugging tips - Calvin Hsia's WebLog - Site Home ... http://blogs.msdn.com/b/calvin_hsia/archive/2004/10/22/246382.aspx

    3 30/03/2015 7:22

  • 8/9/2019 Very Advanced Debugging Tips - Calvin Hsia's WebLog - Site Home - MSDN Blogs

    2/3

     

    Not only can you change OP codes, but you can change data too. For example, the 0FFFFCF7F from above can

    be changed: you can see the value in the memory window.

     

    Armed with this technique, you can reduce the number of times you need to execute the repro scenario.

     

    Another technique is to keep your register window open. (Debug->Windows->Registers). The return value of a

    native code function call is in register EAX. If you’re stepping through assembly code, you can see it easily. If

    you’re stepping through C++ code, it might not be seen as easily (destructors or overloaded operators might fire

    after the function call)

     

    If the IP is on the first line above (0094E284) the register window shows this: (you might have to use the contextmenu to show Effective Address)

     EAX = 022D0B0C EBX = 7FFDF000 ECX = 00080B00

    EDX = 022D0B0C ESI = 0012DA14 EDI = 0012D618

    EIP = 0094E284 ESP = 0012CC84 EBP = 0012CCA4

    EFL = 00000206

     

    CS = 0000 DS = 0023 ES = 0023 SS = 0023 FS = 003B

    GS = 0000

     

    0012CCB4 = 00000065

     

    The red values show the changes each time you step. The last value shows the effective address. Since this is a

    CMP instruction, it shows the value of “dword ptr [sysusr]” which is 0x65

     

    Another example is “dword ptr [eax+4]”, which is handy to see in the register window.

     

    You can do other fancy things in the register window, like change the IP register directly (EIP means Extended

    Instruction Pointer, the 32 bit version of the 16 bi t IP register found on the 8080. Same all the registers starting

    with “E”, like EAX, EBX, etc.)

     

    41561

    Comments

    Garry Trinder #3 Dec 2004 4:49 !

    Garry Trinder #3 Dec 2004 ":" !

    Garry Trinder #" $eb 200" 4:04 !

    As a so%t&are developer' ( spend muc) o% my time loo*ing at code' learning )o& it &or*s' and %iguring+++

    Garry Trinder #3 !ay 200" 2:32 !

    ( received a comment on t)is post: ,ill -et.ast/rror ever &or* properly in V$+01+ ampnbsp( &as

    consistently+++

    Arya #" Aug 200" 3:00 !

    (n case o% debugging &atson cras) dumps +++ &)at do &e need to loo* %or in t)e disassembly5 ( am ne&

    at t)is' so please e6plain in detail+++

    7)an*s5

    Mr. Raybell #0 8ct 200" :09 !

    Does modi%ying t)e registers only &or* in native debugging' or can you modi%y t)em in managed

    debugging as &ell1 (% so' ( cant manage to %igure out )o& to &or* it' so per)aps (m missing

    somet)ing1 (td be )orribly )andy %or &)at (m doing rig)t no&+

    Garry Trinder #2" $eb 200 :44 !

    .et;s log all t)e calls t)at /6cel ma*es to open or create a %i le+

  • 8/9/2019 Very Advanced Debugging Tips - Calvin Hsia's WebLog - Site Home - MSDN Blogs

    3/3

    Garry Trinder #9 an 2009 9:4 !

    7)ere are various lea* detection met)ods %or memory allocators+ A popular one is to tag eac) allocation

    y Advanced Debugging tips - Calvin Hsia's WebLog - Site Home ... http://blogs.msdn.com/b/calvin_hsia/archive/2004/10/22/246382.aspx

    3 30/03/2015 7:22