Debugging Applications with Intel ® SDE
Using the system debugger to directly debug applications that runs under Intel SDE will result in debugging SDE and not the application. Intel SDE provides the means to use the standard system debugger to debug applications with emulated instructions that run with Intel SDE.
Quick Links:
- Debugging Emulated Code on WindowsDebugging emulated code on Windows
- Debugging Emulated Code on LinuxDebugging emulated code on Linux
- Debugging applications with AVX-512 code
- Debugging emulated code on Mac OSX
Debugging Emulated Code on Windows*
Starting with Intel SDE version 5.38, we support debugging with emulated instructions and registers when using Microsoft Visual Studio 2012*. You can compile your application with earlier versions of Visual Studio if required. But to use the debugging features with SDE, you must use Microsoft Visual Studio 2012. Installing the MSI on the Intel SDE download page adds the required support for debugging.
The Intel SDE extensions to MSVS give you the following new features:
- The ability to launch a debug session under SDE.
- An extension to the standard MSVS disassembly window that knows about the new instructions. You can set breakpoints and single-step over new instructions.
- A new emulated register window that displays the new register values that are emulated by SDE. The values can be displayed in various formats.
- A new “SDE console” window which can be used to pass additional commands to SDE for debugging.
Prerequisites:
- Windows 7 (or windows server 2008)
- Visual Studio 2012 – You can use any of the editions (Ultimate, Professional, etc.), except the Express edition. Also, make sure you have an RTM release.
- Installing the latest SDE kit (5.38 or later)
Instructions: First, install the prerequisites listed above. Then, do the following to enable debugging with SDE:
- If you do not already have an MSVS project file, you must create one. I typically create an empty project and specify the executable that I want to debug in the “Application Command” property. Also set the “Application Command Arguments”, if you have any.
- Under Debug->Options and Settings...->Intel® SDE Debugger, set the “SDE Kit Directory” property to point to the root of your (unpacked) SDE kit. There is a <Browse> option that allows you to choose the directory with the file browser. Click OK to save your changes.
- Open the project properties. At the top of the project properties there is a drop-down labeled “Debugger to launch”. Change this drop-down to “SDE Debugger”.
- If you have a pre-built executable, you can replace the Application Command field with the path to your executable.
- Click OK to save your changes.
- Before starting the debugger, you probably want to set some breakpoints in your application. Do this by opening a source file in MSVS, navigate to a line, and press F9. When you are ready, start debugging either by pressing F5 or by clicking on
- Once a debugger session is started, you can view the emulated registers and see the emulated instructions. Open the Emulated Registers window by choosing “DEBUG->Windows->Emulated Registers” in the IDE. You can change the output format for individual register by right clicking. Open the disassembly window by choosing “DEBUG->Windows->Disassembly”.
- By right clicking on a register, you can change its display format to various signed/unsigned integer widths, single, double, hex and binary.
- In the SDE console window, you have various lower level options for talking to SDE using the same command syntax we use with GDB on Linux. Open this window by choosing “DEBUG->Windows->Intel(R) SDE Console”.
Known issues and limitations of the Intel SDE debugging feature on Windows*:
- You cannot attach to running processes.
- You cannot use the "Express" edition of MSVS; It does not support the required extensions. You cannot use windbg; It does not support the required APIs
Debugging Emulated Code on Linux*
For Intel SDE version 6.7 and later, you must use the new version of gdb available in the attachments section at the lower section of Intel SDE main article. This version of gdb provides an XML protocol for communication between Intel SDE and the debugger.
In general you need two windows to do this.
In window #1:
% sde -debug -- yourapp
In window #2
% gdb yourapp
Then from within gdb, you issue a "target remote :portnumber" where "portnumber" is the number shown in window #1. Don't forget the colon before the port number. This gdb is internally using python, therefore you must set the PYTHONHOME environment variable to the home of a python 2.7 (one is provided with the same gdb package).
Debugging Example
In one window:
% sde-external-6.7.0-2013-09-21-lin/sde -mpx-mode -debug -- mpx-test
Application stopped until continued from debugger.
Start GDB, then issue this command at the (gdb) prompt:target remote :48617
In another window:
% gdb mpx-test
GNU gdb (GDB) 7.5-4.0.61
Copyright (C) 2010 Free Software Foundation, Inc; (C) 2013 Intel Corp.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
For information about how to find Technical Support, Product Updates,
User Forums, FAQs, tips and tricks, and other support information, please visit:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /nfs/iil/ptl/bistro/atal/tmp/SDE/mpx-test...done.
(gdb) target remote :48617
Remote debugging using :48617
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00002aaaaaaabb00 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) break main
Breakpoint 1 at 0x4007b0
Here we set a breakpoint in the main of our application.
(gdb) c
Continuing.
Breakpoint 1, 0x00000000004007b0 in main ()
(gdb) x/20i $pc
=> 0x4007b0 <main+4>: sub $0x30,%rsp 0x4007b4 <main+8>: mov %edi,-0x18(%rbp) 0x4007b7 <main+11>: bndstx %bnd0,-0x10(%rbp,%rsi,1) 0x4007bc <main+16>: mov %rsi,-0x10(%rbp) 0x4007c0 <main+20>: movl $0x11,-0x24(%rbp) 0x4007c7 <main+27>: movl $0x0,-0x20(%rbp) 0x4007ce <main+34>: mov $0x1,%eax 0x4007d3 <main+39>: add -0x20(%rbp),%eax 0x4007d6 <main+42>: mov %eax,-0x1c(%rbp) 0x4007d9 <main+45>: mov -0x1c(%rbp),%eax 0x4007dc <main+48>: mov %eax,-0x20(%rbp) 0x4007df <main+51>: mov -0x1c(%rbp),%eax 0x4007e2 <main+54>: test %eax,%eax 0x4007e4 <main+56>: bnd je 0x400811 <main+101> 0x4007e7 <main+59>: lea -0x30(%rbp),%rax 0x4007eb <main+63>: bndmk 0x9(%rax),%bnd0 0x4007f0 <main+68>: mov -0x20(%rbp),%edx 0x4007f3 <main+71>: movslq %edx,%rdx 0x4007f6 <main+74>: add %rdx,%rax 0x4007f9 <main+77>: bndcl %rax,%bnd0
Show the disassembly of the main function. This function has some MPX instructions.
Set a breakpoint before the "bndmk" instruction at address 0x4007eb.
(gdb) b *0x4007eb
Breakpoint 2 at 0x4007eb
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x00000000004007b7 in main ()
The SIGSEGV signal that we see here is due to the execution of the "bndstx" instruction at address 0x4007b7. This signal is handled by the MPX runtime library.
(gdb) c
Continuing.
Breakpoint 2, 0x00000000004007eb in main ()
(gdb) x/i $pc
=> 0x4007eb <main+63>: bndmk 0x9(%rax),%bnd0
Stop before the execution of the "bndmk" instruction and see the initial value of the bnd0 register.
(gdb) p/x $bnd0
$1 = {lbound = 0x0, ubound = 0xffffffffffffffff} : size -1
(gdb) si
0x00000000004007f0 in main ()
After a single step, we see that the value has changed.
(gdb) p/x $bnd0
$2 = {lbound = 0x7fffffffdcf0, ubound = 0x7fffffffdcf9} : size 10
To print all the bnd registers in hex:
(gdb) monitor bnd-get-regs
bnd0: 0xffff800000002306_00007fffffffdcf0
bnd1: 0x0000000000000000_0000000000000000
bnd2: 0x0000000000000000_0000000000000000
bnd3: 0x0000000000000000_0000000000000000
One can also query Intel SDE to disassemble things using XED. This is a request for disassembly of 30 bytes at the indicated address:
(gdb) monitor xdis 0x4007f0 30
XDIS 0000004007f0: BASE 8B55E0 mov edx, dword ptr [rbp-0x20] XDIS 0000004007f3: LONGMODE 4863D2 movsxd rdx, edx XDIS 0000004007f6: BASE 4803C2 add rax, rdx XDIS 0000004007f9: MPX F3480F1AC0 bndcl bnd0, rax XDIS 0000004007fe: MPX F2480F1AC0 bndcu bnd0, rax XDIS 000000400803: BASE C60041 mov byte ptr [rax], 0x41 XDIS 000000400806: BASE 8B45E0 mov eax, dword ptr [rbp-0x20] XDIS 000000400809: BASE 8B55DC mov edx, dword ptr [rbp-0x24] XDIS 00000040080c: BASE 3BC2 cmp eax, edx
Debugging applications with AVX-512 code
As in the previous example, to debug applications with AVX-512 code you need two windows.
In the first window run Intel SDE:
% sde-external-6.7.0-2013-09-21-lin/sde -knl -debug -- vgatherdps.exe
Application stopped until continued from debugger.Start GDB, then issue this command at the (gdb) prompt:
target remote :60738
In the second window run GDB supporting AVX-512.
% gdb vgatherdps.exe
GNU gdb (GDB) 7.5-4.0.61
Copyright (C) 2010 Free Software Foundation, Inc; (C) 2013 Intel Corp.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
For information about how to find Technical Support, Product Updates,
User Forums, FAQs, tips and tricks, and other support information, please visit:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /nfs/iil/disks/sde/atal/SDE/SKY/sde/tests/uisatest/skylake/homebrew/vgatherdps.exe...done.
Type the target remote command from the other windows.
(gdb) target remote :60738
Remote debugging using :60738
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.20x00002aaaaaaaba80 in _start () from /lib64/ld-linux-x86-64.so.2
Now you can type GDB commands and debug your application.
(gdb) break main
Breakpoint 1 at 0x400618: file vgatherdps.c, line 40.(gdb) cont
Continuing.
Breakpoint 1, main ()
at vgatherdps.c:40
40 int main() {(gdb) list
35 if ((uint32_t) *v1 == (uint32_t) *v2)
36 return 1;
37 return 0;
38 }
39
40 int main() {
41 int i = 0;
42 uint64_t z = 0;
43 uint16_t mask_result = 0xffff;
44 data_t indices,output;(gdb) list 585354 __asm {55 // make k1 = all 1s56 kxnorw k1, k1, k157 lea REG, base58 vmovdqu32 zmm2, indices59 vgatherdps zmm1{k1}, [REG+zmm2*4]60 vmovdqu32 output, zmm161 kmovw [mask_result],k162 }
Now set a breakpoint at line 59, and examine the ZMM register content before the execution of the instruction.
(gdb) b 59
Breakpoint 2 at 0x400703: file vgatherdps.c, line 59.(gdb) c
Continuing.
Breakpoint 2, main ()
at vgatherdps.c:59
59 vgatherdps zmm1{k1}, [REG+zmm2*4](gdb) p/x $zmm1$1 = {v16_float = {0x0 <repeats 16 times>}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},v64_int8 = {0x0 <repeats 64 times>}, v32_int16 = {0x0 <repeats 32 times>}, v16_int32 = {0x0 <repeats 16 times>}, v8_int64 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int128 = {0x00000000000000000000000000000000, 0x00000000000000000000000000000000,0x00000000000000000000000000000000, 0x00000000000000000000000000000000}}
Now execute the single instruction and see how the register content has changed.
(gdb) ni
60 vmovdqu32 output, zmm1(gdb) disass 0x4006ee,0x400730Dump of assembler code from 0x4006ee to 0x400730:0x000004006ee <main+214>: kxnorw %k1,%k1,%k1 0x000004006f2 <main+218>: lea -0x10e8(%rbp),%rdx 0x000004006f9 <main+225>: vmovdqu32 -0xb0(%rbp),%zmm2 0x00000400703 <main+235>: vgatherdps (%rdx,%zmm2,4),%zmm1{%k1} => 0x0000040070a <main+242>: vmovdqu32 %zmm1,-0x70(%rbp) 0x00000400714 <main+252>: kmovw %k1,-0x10f0(%rbp) 0x0000040071c <main+260>: movl $0x0,-0xe8(%rbp) 0x00000400726 <main+270>: movl $0x0,-0x10ec(%rbp)End of assembler dump.
(gdb) p/x $zmm1$3 = {v16_float = {0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14},v8_double = {0x2000, 0x20000, 0x80000, 0x200000, 0x800002, 0x2000008, 0x4000010, 0x8000020},v64_int8 = {0x0, 0x0, 0xa0, 0x40, 0x0, 0x0, 0xc0, 0x40, 0x0, 0x0, 0xe0, 0x40, 0x0, 0x0, 0x0, 0x41, 0x0,0x0, 0x10, 0x41, 0x0, 0x0, 0x20, 0x41, 0x0, 0x0, 0x30, 0x41, 0x0, 0x0, 0x40, 0x41, 0x0, 0x0, 0x50,0x41, 0x0, 0x0, 0x60, 0x41, 0x0, 0x0, 0x70, 0x41, 0x0, 0x0, 0x80, 0x41, 0x0, 0x0, 0x88, 0x41, 0x0,0x0, 0x90, 0x41, 0x0, 0x0, 0x98, 0x41, 0x0, 0x0, 0xa0, 0x41}, v32_int16 = {0x0, 0x40a0, 0x0, 0x40c0,0x0, 0x40e0, 0x0, 0x4100, 0x0, 0x4110, 0x0, 0x4120, 0x0, 0x4130, 0x0, 0x4140, 0x0, 0x4150, 0x0,0x4160, 0x0, 0x4170, 0x0, 0x4180, 0x0, 0x4188, 0x0, 0x4190, 0x0, 0x4198, 0x0, 0x41a0}, v16_int32 = {0x40a00000, 0x40c00000, 0x40e00000, 0x41000000, 0x41100000, 0x41200000, 0x41300000, 0x41400000,0x41500000, 0x41600000, 0x41700000, 0x41800000, 0x41880000, 0x41900000, 0x41980000, 0x41a00000},v8_int64 = {0x40c0000040a00000, 0x4100000040e00000, 0x4120000041100000, 0x4140000041300000,0x4160000041500000, 0x4180000041700000, 0x4190000041880000, 0x41a0000041980000}, v4_int128 = {0x4100000040e0000040c0000040a00000, 0x41400000413000004120000041100000,0x41800000417000004160000041500000, 0x41a00000419800004190000041880000}}
You can also use the Intel SDE monitor command for disassembly and for viewing register content.
(gdb) monitor xdis 0x4006ee 46
XDIS 00004006ee: AVX512VEX C5F446C9 kxnorw k1, k1, k1 XDIS 00004006f2: BASE 488D9518EFFFFF lea rdx, ptr [rbp-0x10e8] XDIS 00004006f9: AVX512EVEX 62F17E486F9550FFFFFF vmovdqu32 zmm2, k0, zmmword ptr [rbp-0xb0] XDIS 0000400703: AVX512EVEX 62F27D49920C92 vgatherdps zmm1, k1, zmmword ptr [rdx+zmm2*4] XDIS 000040070a: AVX512EVEX 62F17E487F8D90FFFFFF vmovdqu32 zmmword ptr [rbp-0x70], k0, zmm1 XDIS 0000400714: AVX512VEX C5F8918D10EFFFFF kmovw word ptr [rbp-0x10f0], k1(gdb) monitor zmm-get-reg 1
zmm01: 0x41a00000_41980000_41900000_41880000_41800000_41700000_41600000_41500000_ 41400000_41300000_41200000_41100000_41000000_40e00000_40c00000_40a00000 int8: 65 -96 0 0 65 -104 0 0 65 -112 0 0 65 -120 0 0 65 -128 0 0 65 112 0 0 65 96 0 0 65 80 0 0 65 64 0 0 65 48 0 0 65 32 0 0 65 16 0 0 65 0 0 0 64 -32 0 0 64 -64 0 0 64 -96 0 0 int16: 16800 0 16792 0 16784 0 16776 0 16768 0 16752 0 16736 0 16720 0 16704 0 16688 0 16672 0 16656 0 16640 0 16608 0 16576 0 16544 0 int32: 1101004800 1100480512 1099956224 1099431936 1098907648 1097859072 1096810496 1095761920 1094713344 1093664768 1092616192 1091567616 1090519040 1088421888 1086324736 1084227584 int64: 4728779609839501312 4724276010211082240 4719772410582138880 4710765211325300736 4701758012068462592 4692750812811624448 4683743613553737728 4665729215040061440 uint8: 65 160 0 0 65 152 0 0 65 144 0 0 65 136 0 0 65 128 0 0 65 112 0 0 65 96 0 0 65 80 0 0 65 64 0 0 65 48 0 0 65 32 0 0 65 16 0 0 65 0 0 0 64 224 0 0 64 192 0 0 64 160 0 0 uint16: 16800 0 16792 0 16784 0 16776 0 16768 0 16752 0 16736 0 16720 0 16704 0 16688 0 16672 0 16656 0 16640 0 16608 0 16576 0 16544 0 uint32: 1101004800 1100480512 1099956224 1099431936 1098907648 1097859072 1096810496 1095761920 1094713344 1093664768 1092616192 1091567616 1090519040 1088421888 1086324736 1084227584 uint64: 4728779609839501312 4724276010211082240 4719772410582138880 4710765211325300736 4701758012068462592 4692750812811624448 4683743613553737728 4665729215040061440 float: 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 double: 1.34218e+08 6.71089e+07 3.35544e+07 8.38861e+06 2.09715e+06 524288 131072 8192
To see all monitor commands:
(gdb) monitor help sde
xdis ADDRESS NBYTES - Disassemble NBYTES at ADDRESS xdis-xml ADDRESS NBYTES - Disassemble NBYTES at ADDRESS with XML formatting register-information - Description of supported registers bnd-get-regs - Dump all the BND regs bnd-get-reg N - Dump the BND reg N bndstatus-get-regs - Dump the BNDSTATUS bndstatus-get-reg - Dump the BNDSTATUS bndcfgu-get-regs - Dump the BNDCFGU bndcfgu-get-reg - Dump the BNDCFGU bnd-set-reg N UB_LB - Set the bounds of BND reg N. UB,LB can be empty bndstatus-set-reg VALUE - Set the BNDSTATUS bndcfgu-set-reg VALUE - Set the BNDCFGU k-set-reg N VALUE - Set the mask register N to hex VALUE zmm-set-reg N VALUE - Set the ZMM register N to hex VALUE k-get-regs - Dump the mask registers k-get-reg N - Dump the mask register N zmm-get-reg N - Dump the ZMM register N in various formats zmm-get-regs - Dump the ZMM registers in hex(gdb) cont
Continuing.[Inferior 1 (Remote target) exited normally]
(gdb)
Debugging Emulated Code on Mac OSX*
Staring with Intel SDE version 6.20 and later, you now can use lldb to debug emulated code on Mac OSX.
Note: the 'monitor' command available when debugging with GDB on Linux is not yet available with lldb.
In general you need two windows to do this.
In window #1:
% sde -debug -- yourapp
In window #2
% lldb yourapp
Then from within lldb, you issue a "gdb-remote portnumber" where "portnumber" is the number shown in window #1. Now you can use you normal lldb commands to debug the application.
Debugging Example
In one window:
% sde-external-6.20.0-2014-02-13-mac/sde -knl -debug -- knl-test
Application stopped until continued from debugger.
Start LLDB, then issue this command at the (lldb) prompt:
gdb-remote 53196
In another window:
% lldb knl-test
Current executable set to 'knl-test' (x86_64).
(lldb) gdb-remote 53196
Process 7683 stopped
* thread #1: tid = 0x1e03, 0x00007fff69acd028 dyld`_dyld_start, stop reason = signal SIGINT
frame #0: 0x00007fff69acd028 dyld`_dyld_start
dyld`_dyld_start:
-> 0x7fff69acd028: pushq $0
0x7fff69acd02a: movq %rsp, %rbp
0x7fff69acd02d: andq $-16, %rsp
0x7fff69acd031: movq 8(%rbp), %rdi
(lldb) b main
Breakpoint 1: where = knl-test`main + 43 at test.c:43, address = 0x00000001000008ab
(lldb) c
Process 7683 resuming
Process 7683 stopped
* thread #1: tid = 0x1e03, 0x0000000109ecc8ab knl-test`main + 43 at test.c:43, stop reason = breakpoint 1.1
frame #0: 0x0000000109ecc8ab knl-test`main + 43 at test.c:43
40 int main() {
41 int i = 0;
42 uint64_t z = 0;
-> 43 uint16_t mask_result = 0xffff;
44 data_t indices,output;
45 for(i=0;i<16;i++) {
46 indices.i[i] = i;
(lldb) list
47 }
48 float base[1024];
49 for(i=0;i<1024;i++) {
50 base[i]=i + 5;
51 }
52
53
(lldb) list
54 __asm {
55 // make k1 = all 1s
56 kxnorw k1, k1, k1
57 lea REG, base
58 vmovdqu32 zmm2, indices
59 vgatherdps zmm1{k1}, [REG+zmm2*4]
60 vmovdqu32 output, zmm1
(lldb) b 60
Breakpoint 2: where = knl-test`main + 202 at test.c:60, address = 0x0000000109ecc94a
(lldb) c
Process 7683 resuming
Process 7683 stopped
* thread #1: tid = 0x1e03, 0x0000000109ecc94a knl-test`main + 202 at test.c:60, stop reason = breakpoint 2.1
frame #0: 0x0000000109ecc94a knl-test`main + 202 at test.c:60
57 lea REG, base
58 vmovdqu32 zmm2, indices
59 vgatherdps zmm1{k1}, [REG+zmm2*4]
-> 60 vmovdqu32 output, zmm1
61 kmovw [mask_result],k1
62 }
63
(lldb) register read zmm1
zmm1 = {0x00 0x00 0x50 0x41 0x00 0x00 0x60 0x41 0x00 0x00 0x70 0x41 0x00 0x00 0x80 0x41 0x00 0x00 0x88 0x41 0x00 0x00 0x90 0x41 0x00 0x00 0x98 0x41 0x00 0x00 0xa0 0x41}
(lldb) register read k1
k1 = 0x0000000000000000
(lldb)