1 / 17

Facilities for x86 debugging

Facilities for x86 debugging. Introduction to Pentium features that can assist programmers in their debugging of software. TF-bit in EFLAGS. Our ‘trydebug.s’ demo showed how to use the TF-bit to perform ‘single-stepping’ of a Linux application program (e.g., ‘hello’)

sveta
Télécharger la présentation

Facilities for x86 debugging

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Facilities for x86 debugging Introduction to Pentium features that can assist programmers in their debugging of software

  2. TF-bit in EFLAGS • Our ‘trydebug.s’ demo showed how to use the TF-bit to perform ‘single-stepping’ of a Linux application program (e.g., ‘hello’) • The ‘popfd’ instruction was used to set TF • But single-stepping starts only AFTER the immediately following instruction executes • An exception-handler for INT-1 can display information about the state of the task

  3. Using ‘objdump’ output • You can generate an assembler ‘listing’ of the instructions in our ‘hello’ application • You can then use the listing to follow along with the ‘single-stepping’ through that code • Here’s how to do it: $ objdump –d hello > hello.u • (The ‘-d’ option stands for ‘disassembly’)

  4. A slight ‘flaw’ • We cannot single-step the execution of an ‘int-0x80’ instruction (Linux’s system-calls) • Our exception-handler’s ‘iretd’ instruction will restore the TF-bit to EFLAGS, but the single-step ‘trap’ doesn’t take effect until after the immediately following instruction • This means we ‘skip’ seeing a display of the registers immediately after ‘int-0x80’

  5. Fixing the ‘flaw’ • The Pentium offers a way to overcome the problem of a delayed effect when TF is set • We can use the Debug Registers to set an instruction ‘breakpoint’ which will interrupt the CPU at a specific instruction-address • There are six Debug Registers: DR0, DR1, DR2, DR3 (breakpoints) DR6 (the Debug Status register) DR7 *the Debug Control register)

  6. Breakpoint Address Registers DR0 DR1 DR2 DR3

  7. Special ‘MOV’ instructions • Use ‘mov DRn, genreg’ to write into DRn • Use ‘mov genreg, DRn’ to read from DRn • These instructions are ‘privileged’ (i.e., can only be executed by code running in ring0)

  8. Debug Control Register (DR7) 15 0 0 0 G D 0 0 1 G E L E G 3 L 3 G 2 L 2 G 1 L 1 G 0 L 0 Least significant word 31 16 LEN 3 R/W 3 LEN 2 R/W 2 LEN 1 R/W 1 LEN 0 R/W 0 Most significant word

  9. What kinds of breakpoints? LEN R/W LEN 00 = one byte 01 = two bytes 10 = undefined 11 = four bytes R/W 00 = break on instruction fetch only 01 = break on data writes only 10 = undefined (unless DE set in CR4) 11 = break on data reads or writes (but not on instruction fetches)

  10. Control Register 4 • The Pentium uses Control Register 4 to activate certain extended features of the processor, while still allowing for backward compatibility of software written for earlier Intel x86 processors • An example: Debug Extensions (DE-bit) 31 3 0 other feature bits D E CR4

  11. Debug Status Register (DR6) 15 0 B T B S B D 0 1 1 1 1 1 1 1 1 B 3 B 2 B 1 B 0 Least significant word 31 16 unused ( all bits here are set to 1 ) Most significant word

  12. Where to set a breakpoint • Suppose you want to trigger a ‘debug’ fault at the instruction immediately following the software Linux ‘int-0x80’ system-call • Your debug exception-handler can use the saved CS:EIP values on its stack to check that ‘int-0x80’ has caused an exception • Machine-code is: 0xCD, 0x80 (2 bytes) • So set a ‘breakpoint’ at address EIP+2

  13. How to set this breakpoint isrDBG: push ebp mov ebp, esp pushad ; put breakpoint-address in DR0 mov eax, 4[ebp] add eax, #2 mov dr0, eax

  14. Setting a breakpoint (continued) ; enable local breakpoint for DR0 mov eax, DR7 bts eax, #0 ; set LE0 mov DR7, eax … popad pop ebp iretd

  15. Detecting a ‘breakpoint’ • Your debug exception-handler reads DR6 to check for occurrences of breakpoints mov eax, DR6 ; get debug status bt eax, #0 ; breakpoint #0? jnc notBP0 ; no, another cause bts 12[ebp], #16 ; set the RF-bit ; or disable breakpoint0 in register DR7 notBP0:

  16. In-Class Exercise #1 • Modify the debug exception-handler in our ‘trydebug.s’ demo-program (on website) so that it will ‘single-step’ past ‘int-0x80’ • But don’t forget to disable any breakpoints that might still be in effect when you enter the ‘do_exit’ procedure (to terminate your ‘hello’ application), by writing a zero value into the Debug Control Register DR7

  17. In-class exercise #2 • After you have completed exercise #1, you can try this further exercise: use a different Debug Register (i.e.,, DR1, DR2, or DR3) to set an instruction-breakpoint at the entry to your ‘int-0x80’ service-routine • This will allow you to do single-stepping of your system-call handlers (e.g., ‘do_write’) • (A problem arises with ‘do_read’ though)

More Related