{"id":8650,"date":"2024-01-31T09:18:16","date_gmt":"2024-01-31T17:18:16","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=8650"},"modified":"2024-01-31T09:18:16","modified_gmt":"2024-01-31T17:18:16","slug":"tracing-externally-built-projects-with-quick-debug","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/tracing\/embedded\/external\/","title":{"rendered":"Tracing Externally Built Projects with Quick Debug"},"content":{"rendered":"<p>This tutorial shows how to use <a href=\"https:\/\/visualgdb.com\/documentation\/tracing\/\">Software Tracing<\/a> with the Quick Debug feature to record the execution of a project that was built outside VisualGDB on a different machine.<\/p>\n<p>We will first use a Linux machine to build a basic USB-controlled embedded application using the <a href=\"https:\/\/os.mbed.com\/\">mbed framework<\/a>, and then will copy the ELF file along with the sources to the Windows machine and will use VisualGDB to create trace of all commands received by it via USB.<\/p>\n<p>Note that if are already using VisualGDB to build your project, you can trace it much easier via the regular debugging GUI (see <a href=\"https:\/\/visualgdb.com\/tutorials\/tracing\/embedded\/\">this tutorial<\/a>). The steps shown in this tutorial are only needed if you want to trace an existing project without having to change its build process.<\/p>\n<p>Before you begin, install VisualGDB 6.0 or later.<\/p>\n<ol>\n<li>Install the mbed tools on the Linux machine. For Debian-based distributions, the command below should suffice:\n<pre class=\"\">sudo apt install gcc-arm-none-eabi python3-pip git mercurial<\/pre>\n<\/li>\n<li>Create a separate virtual Python environment and install the mbed scripts into it:\n<pre class=\"\">python3 -m venv ~\/mbed-python-env\r\nsource ~\/mbed-python-env\/bin\/activate\r\npip3 install mbed-cli<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/02-getmbed.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8652\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/02-getmbed.png\" alt=\"\" width=\"904\" height=\"464\" \/><\/a><\/li>\n<li>Once the mbed tools are ready, create a new mbed project by running <strong>mbed new &lt;Project Name&gt;<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/03-tracetest.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8653\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/03-tracetest.png\" alt=\"\" width=\"904\" height=\"299\" \/><\/a><\/li>\n<li>Once the project is created, add a file called <strong>main.cpp<\/strong> with the following contents to the project directory:\n<pre class=\"\">#include \"mbed.h\"\r\n#include \"USBSerial.h\"\r\n\r\n#if !defined(DEVICE_USBDEVICE) || !DEVICE_USBDEVICE\r\n#error The current target does not support the USB interface\r\n#endif\r\n\r\nUSBSerial serial;\r\n\r\nint main()\r\n{\r\n    DigitalOut led(LED1);\r\n\r\n    while (true) {\r\n        char ch = serial._getc();\r\n        if (ch == '1')\r\n        \tled = true;\r\n        else if (ch == '0')\r\n        \tled = false;\r\n    }\r\n}<\/pre>\n<\/li>\n<li>Select the target board (<strong>mbed target &lt;Target name&gt;<\/strong>) and build the project using the ARM toolchain (<strong>mbed compile -t GCC_ARM<\/strong>):<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/04-build.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8654\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/04-build.png\" alt=\"\" width=\"904\" height=\"299\" \/><\/a><\/li>\n<li>Once the project finished building, take a note of the <strong>.bin<\/strong> file:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/05-built.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8655\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/05-built.png\" alt=\"\" width=\"904\" height=\"612\" \/><\/a>In order to debug and trace the application, you would need to point VisualGDB to the ELF file (containing both the code and debug symbols) that has the same name as the <strong>.bin<\/strong> file, and the <strong>.elf<\/strong> extension.<\/li>\n<li>Copy the project sources and the ELF file to the Windows machine. Start Visual Studio and select <strong>Debug-&gt;Quick Debug with GDB<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/06-qdebug.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8656\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/06-qdebug.png\" alt=\"\" width=\"1281\" height=\"750\" \/><\/a><\/li>\n<li>Create a new embedded Quick Debug preset, point VisualGDB to the ELF file, and enable software tracing. If VisualGDB supports <a href=\"https:\/\/visualgdb.com\/documentation\/flashpatchers\/\">FLASH hotpatching<\/a> for your device, enable it so you won&#8217;t need to restart debugging after changing the tracepoints:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/07-settings.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8657\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/07-settings.png\" alt=\"\" width=\"986\" height=\"769\" \/><\/a><\/li>\n<li>If you try debugging now, VisualGDB will report missing relocation records inside the ELF file:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/08-reloc.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8658\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/08-reloc.png\" alt=\"\" width=\"1298\" height=\"861\" \/><\/a>This happens because in order to do software tracing, VisualGDB needs to reserve a part of the target memory for the tracing programs and data. VisualGDB can do it automatically by relocating the heap or stack (thus, requiring the relocation records in the ELF file) or you can do it manually by declaring an otherwise unused buffer variable and pointing VisualGDB to it. In this tutorial we will use the first approach and will enable relocation records on mbed side.<\/li>\n<li>In order to produce relocation records, you need to add &#8220;-Wl,-q&#8221; to the linker command line (LDFLAGS). For mbed this can be done by copying the <strong>debug.json<\/strong> profile to the project directory and patching it. You can find the profile path by running &#8220;<strong>find . | grep debug.json<\/strong>&#8220;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/09-profile.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8659\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/09-profile.png\" alt=\"\" width=\"904\" height=\"351\" \/><\/a><\/li>\n<li>Patch the local copy of the profile so that <strong>ld<\/strong> flags for\u00a0<strong>GCC_ARM<\/strong> will contain &#8220;<strong>-Wl,-q<\/strong>&#8220;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/10-patch.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8660\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/10-patch.png\" alt=\"\" width=\"904\" height=\"351\" \/><\/a>We also recommend replacing &#8220;-Og&#8221; with &#8220;-O0&#8221; for better debugging experience.<\/li>\n<li>Build the project using the new profile:\n<pre class=\"\">mbed compile -t GCC_ARM --profile=debug+reloc.json<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/11-build.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8661\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/11-build.png\" alt=\"\" width=\"1035\" height=\"351\" \/><\/a><\/li>\n<li>Copy the new ELF file to the Windows machine and update the path in the Quick Debug window:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/12-reloc.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8662\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/12-reloc.png\" alt=\"\" width=\"986\" height=\"769\" \/><\/a>Now you can click <strong>Debug<\/strong> to start debugging and tracing the program.<\/li>\n<li>The application shown in this tutorial uses the <a href=\"https:\/\/os.mbed.com\/handbook\/USBSerial\">USBSerial<\/a> class to emulate a serial port via a second USB port (separate from the ST-Link USB port). Make sure that port is connected and open it in a terminal program:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/port.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8663\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/port.png\" alt=\"\" width=\"887\" height=\"461\" \/><\/a><\/li>\n<li>The initial breakpoint in <strong>main()<\/strong> will trigger. However, because the program was built on a different machine, VisualGDB won&#8217;t know the location of the <strong>main.cpp<\/strong> file on the Windows machine and will ask for it. Locate it manually and create a rule to automatically map other source paths:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/13-map.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8664\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/13-map.png\" alt=\"\" width=\"1298\" height=\"861\" \/><\/a><\/li>\n<li>Try pressing F10 step over the <strong>DigitalOut<\/strong> initialization. If GDB ends up stepping into an interrupt handler, you can enable stepping over interrupts in the <strong>GDB Session<\/strong> window, step out of it (Shift-F12) and step over again (F10):<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/14-stepover.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8665\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/14-stepover.png\" alt=\"\" width=\"1298\" height=\"861\" \/><\/a><\/li>\n<li>Try setting a tracepoint at the first line that checks the value of <strong>ch. <\/strong>Configure it to trace ch and the <strong>Cortex-M<\/strong> cycle counter:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/15-trace.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8666\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/15-trace.png\" alt=\"\" width=\"1298\" height=\"861\" \/><\/a>Then, press F5 to continue debugging.<\/li>\n<li>If you are debugging a device supported by the FLASH hotpatching framework, the tracepoint will get applied immediately. Otherwise, it will be stored in the Quick Debug profile and will take effect during the next debug session. Try sending some characters to the virtual COM port and observe how the LED immediately turns on or off, and the trace event count is incremented:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/16-events.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8667\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/16-events.png\" alt=\"\" width=\"1298\" height=\"861\" \/><\/a>Tracing works directly on the target without stopping it in a debugger, so it can be used to capture events in real time, and review them later.<\/li>\n<li>Click on the &#8220;<span style=\"text-decoration: underline;\"><strong>N events<\/strong><\/span>&#8221; link or go to <strong>Debug-&gt;Windows-&gt;Tracepoints<\/strong> to review the captured events:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/17-data.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8668\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/17-data.png\" alt=\"\" width=\"1298\" height=\"861\" \/><\/a><\/li>\n<li>You can create table views and drag the variables from the <strong>Trace Data<\/strong> window to them to quickly see the value of a variable captured at different times. Try adding &#8216;ch&#8217; and the cycle counter to separate columns to see the exact characters received via the USB port, along with precise timestamps:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/18-table.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8670\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/18-table.png\" alt=\"\" width=\"1298\" height=\"861\" \/><\/a>Double-clicking on a row in the table will select that event, allowing you to review other captured data, or step forwards or backwards in time.<\/li>\n<li>Try setting a breakpoint on the &#8220;<strong>led = true<\/strong>&#8221; line and stepping in it. Once inside the <strong>operator=()<\/strong> implementation, set another tracepoint capturing the <strong>value<\/strong>. The tracepoints window will now show how receiving &#8216;1&#8217; or &#8216;0&#8217; via USB immediately triggers the tracepoint in the operator:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/20-write.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8671\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/20-write.png\" alt=\"\" width=\"1298\" height=\"861\" \/><\/a><\/li>\n<li>Once the debug session is over, VisualGDB will save all recorded data into a trace file. You can open it later via <strong>File-&gt;Open<\/strong> to step through the recorded events or view the tables created via the Trace Data window:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/21-tracefile.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8672\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/01\/21-tracefile.png\" alt=\"\" width=\"1298\" height=\"861\" \/><\/a><\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to use Software Tracing with the Quick Debug feature to record the execution of a project<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[247],"tags":[248,204],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8650"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=8650"}],"version-history":[{"count":2,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8650\/revisions"}],"predecessor-version":[{"id":8673,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8650\/revisions\/8673"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=8650"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=8650"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=8650"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}