<div class="xblock xblock-public_view xblock-public_view-vertical" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-init="VerticalStudentView" data-runtime-class="LmsRuntime" data-runtime-version="1" data-block-type="vertical" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@vertical+block@df435f15924b4cf1a52c31fd12314125" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="vert-mod">
<div class="vert vert-0" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@markdown+block@5b11aaaa531649f3abd0f4471fa06ffd">
<div class="xblock xblock-public_view xblock-public_view-markdown" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="markdown" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@markdown+block@5b11aaaa531649f3abd0f4471fa06ffd" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="markdown_xblock"><p>In Practice #1 we learned how to compile and run UEFI firmware for QEMU (OVMF). In this section we will learn couple debugging methods:</p>
<ul>
<li>Debugging using EDK II logging features</li>
<li>Debugging using EDK II debug code statement</li>
<li>Debugging using GDB remote target connecting to EDK II Debug Agent</li>
<li>Debugging using GDB remote target connecting to QEMU</li>
</ul>
<h1>Enabling debugging at build time</h1>
<p>To created debug build target use <code>-b DEBUG</code> parameter:</p>
<div class="codehilite">
<pre><span></span><code>build -p OvmfPkg/OvmfPkgX64.dsc -b DEBUG -t GCC5 -n <span class="k">$(</span>nproc<span class="k">)</span> -a X64 all
</code></pre>
</div>
<h1>Add DebugLib to DSC file</h1>
<p>Since we use existing <code>OvmfPkg/OvmfPkgX64.dsc</code> let's check how DebugLib was added:</p>
<div class="codehilite">
<pre><span></span><code>user@user-OST-VM:~/edk2$ grep DebugLib OvmfPkg/OvmfPkgX64.dsc <span class="p">|</span>sort<span class="p">|</span>uniq
DebugLib<span class="p">|</span>MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
DebugLib<span class="p">|</span>OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
DebugLib<span class="p">|</span>OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPort.inf
</code></pre>
</div>
<p>As we can see there are multiple libraries available in our platform description file. If we look inside the DSC file we will find that <code>BaseDebugLibSerialPort</code> is used when <code>DEBUG_ON_SERIAL_PORT</code> is defined. We can define it at build time using <code>-D DEBUG_ON_SERIAL_PORT</code>, but before we do that let's see what happens if <code>DEBUG_ON_SERIAL_PORT</code> is not defined. In the DSC we see that <code>PlatformRomDebugLibIoPort</code> or <code>PlatformDebugLibIoPort</code> are used. First just in SEC libraries and second with other UEFI phases libraries.</p>
<h2>Exercise #1: How to see output PlatformRomDebugLibIoPort functions?</h2>
<ol>
<li>We can look for PlatformRomDebugLibIoPort.inf</li>
<li>In section Sources we can find DebugLib.c</li>
<li>Inside we can find the following functions calls <code>DebugPrint->DebugVPrint->DebugPrintMarker</code></li>
<li>The last thing <code>DebugPrintMarker</code> performs is <code>IoWriteFifo8</code> to some PCD (Platform Configuration Databse) - PCD in this case is decoded using <code>PcdGet16()</code> function. Please note the parameter of that function as we will refer to it in next exercise as "I/O Debug Port".</li>
<li>Please find "I/O Debug Port" in OvmfPkg.dec declaration file - the default file for PCD definitions.</li>
<li>Knowing that hex value, let's run QEMU. Do not forget to replace <code><I/O Debug Port></code> with the correct value, and see if we can get any debug prints from SEC phase:</li>
</ol>
<div class="codehilite">
<pre><span></span><code>qemu-system-x86_64 -nographic -bios Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd -chardev file,path<span class="o">=</span>debug.log,id<span class="o">=</span>edk2-debug -device isa-debugcon,iobase<span class="o">=</span><I/O Debug Port>,chardev<span class="o">=</span>edk2-debug
</code></pre>
</div>
<p>To understand what PCD is you can read <a href="https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/edkii-platform-config-database-entries-paper.pdf">Intel white paper</a>.</p>
</div>
</div>
</div>
<div class="vert vert-1" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@done+block@ddfbe01acff749c49a61132d7860e9a7">
<div class="xblock xblock-public_view xblock-public_view-done" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="done" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@done+block@ddfbe01acff749c49a61132d7860e9a7" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="True">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Completion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
<div class="vert vert-2" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@discussion+block@809f05f5dfe14b99ab47ff8dedeb5851">
<div class="xblock xblock-public_view xblock-public_view-discussion" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="discussion" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@discussion+block@809f05f5dfe14b99ab47ff8dedeb5851" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Discussion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
</div>
<script type="text/javascript">
(function (require) {
require(['/static/js/dateutil_factory.be68acdff619.js?raw'], function () {
require(['js/dateutil_factory'], function (DateUtilFactory) {
DateUtilFactory.transform('.localized-datetime');
});
});
}).call(this, require || RequireJS.require);
</script>
<script>
function emit_event(message) {
parent.postMessage(message, '*');
}
</script>
</div>
<div class="xblock xblock-public_view xblock-public_view-vertical" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-init="VerticalStudentView" data-runtime-class="LmsRuntime" data-runtime-version="1" data-block-type="vertical" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@vertical+block@3f7de0b5c78c4e0ebbe336219bbd7daa" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="vert-mod">
<div class="vert vert-0" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@markdown+block@60158b87c73d4debb3db71fda729c03c">
<div class="xblock xblock-public_view xblock-public_view-markdown" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="markdown" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@markdown+block@60158b87c73d4debb3db71fda729c03c" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="markdown_xblock"><h1>Debugging by printing</h1>
<p>This is one of the most easiest, popular and efficient way of debugging firmware.</p>
<h2>Exercise #2: Let's add debug log to SEC module</h2>
<ol>
<li>One of the first lines that we saw in debug log from Exercise #1 should be <code>SecCoreStartupWithStack</code> - please find the C file where this string occurs</li>
<li>Add another debug message right after the above message</li>
<li>Recompile</li>
<li>Dump the logs as in Exercise #1 and make sure your modification is present in the log</li>
</ol>
</div>
</div>
</div>
<div class="vert vert-1" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@done+block@0e7f76cc3be84e7facf63ede9fb85436">
<div class="xblock xblock-public_view xblock-public_view-done" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="done" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@done+block@0e7f76cc3be84e7facf63ede9fb85436" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="True">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Completion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
<div class="vert vert-2" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@discussion+block@a1d66407d65747ae94e2aa533836d166">
<div class="xblock xblock-public_view xblock-public_view-discussion" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="discussion" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@discussion+block@a1d66407d65747ae94e2aa533836d166" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Discussion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
</div>
<script type="text/javascript">
(function (require) {
require(['/static/js/dateutil_factory.be68acdff619.js?raw'], function () {
require(['js/dateutil_factory'], function (DateUtilFactory) {
DateUtilFactory.transform('.localized-datetime');
});
});
}).call(this, require || RequireJS.require);
</script>
<script>
function emit_event(message) {
parent.postMessage(message, '*');
}
</script>
</div>
<div class="xblock xblock-public_view xblock-public_view-vertical" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-init="VerticalStudentView" data-runtime-class="LmsRuntime" data-runtime-version="1" data-block-type="vertical" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@vertical+block@5cde3f53f21c4b838c823391f70ecd77" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="vert-mod">
<div class="vert vert-0" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@markdown+block@c885e4bf503e4cc7a2cd375f6232084e">
<div class="xblock xblock-public_view xblock-public_view-markdown" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="markdown" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@markdown+block@c885e4bf503e4cc7a2cd375f6232084e" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="markdown_xblock"><p>Let's use QEMU feature to connect GDB and debug EDKII code.</p>
<p>First let's run QEMU with GDB server listnening and waiting for connection:</p>
<pre><code>qemu-system-x86_64 -nographic -bios Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd -chardev file,path=debug.log,id=edk2-debug -device isa-debugcon,iobase=<I/O Debug Port>,chardev=edk2-debug -s -S
</code></pre>
<p>Do not forget to replace <code><I/O Debug Port></code> with the value obtained in the previous exercise in this section.</p>
<h2>Exercise #3: Debugging EFI files</h2>
<ul>
<li>Run gdb</li>
</ul>
<div class="codehilite">
<pre><span></span><code>user@user-OST-VM:~/edk2$ gdb
GNU gdb <span class="o">(</span>Ubuntu <span class="m">9</span>.2-0ubuntu1~20.04.1<span class="o">)</span> <span class="m">9</span>.2
Copyright <span class="o">(</span>C<span class="o">)</span> <span class="m">2020</span> Free Software Foundation, Inc.
License GPLv3+: GNU GPL version <span class="m">3</span> 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 <span class="s2">"show copying"</span> and <span class="s2">"show warranty"</span> <span class="k">for</span> details.
This GDB was configured as <span class="s2">"x86_64-linux-gnu"</span>.
Type <span class="s2">"show configuration"</span> <span class="k">for</span> configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, <span class="nb">type</span> <span class="s2">"help"</span>.
Type <span class="s2">"apropos word"</span> to search <span class="k">for</span> commands related to <span class="s2">"word"</span>.
<span class="o">(</span>gdb<span class="o">)</span>
</code></pre>
</div>
<ul>
<li>Load <code>SecMain.debug</code> file to obtain addresses of <code>.text</code> and <code>.data</code> sections</li>
</ul>
<div class="codehilite">
<pre><span></span><code><span class="o">(</span>gdb<span class="o">)</span> file Build/OvmfX64/DEBUG_GCC5/X64/SecMain.debug
Reading symbols from Build/OvmfX64/DEBUG_GCC5/X64/SecMain.debug...
<span class="o">(</span>gdb<span class="o">)</span> info file
Symbols from <span class="s2">"/home/user/edk2/Build/OvmfX64/DEBUG_GCC5/X64/SecMain.debug"</span>.
Local <span class="nb">exec</span> file:
<span class="sb">`</span>/home/user/edk2/Build/OvmfX64/DEBUG_GCC5/X64/SecMain.debug<span class="err">'</span>, file <span class="nb">type</span> elf64-x86-64.
Entry point: 0x64f0
0x0000000000000240 - 0x00000000000088fe is .text
0x0000000000008900 - 0x0000000000009a60 is .data
0x0000000000009a80 - 0x0000000000009a80 is .eh_frame
</code></pre>
</div>
<ul>
<li>In other terminal look in <code>Build/OvmfX64/DEBUG_GCC5/Ovmf.map</code> for base address of <code>SecMain</code></li>
</ul>
<div class="codehilite">
<pre><span></span><code>user@user-OST-VM:~/edk2$ grep SecMain Build/OvmfX64/DEBUG_GCC5/Ovmf.map
SecMain <span class="o">(</span>Fixed Flash Address, <span class="nv">BaseAddress</span><span class="o">=</span><SecMain_BaseAddress>, <span class="nv">EntryPoint</span><span class="o">=</span>0x00fffd2584, <span class="nv">Type</span><span class="o">=</span>PE<span class="o">)</span>
<span class="o">(</span><span class="nv">IMAGE</span><span class="o">=</span>/home/user/edk2/Build/OvmfX64/DEBUG_GCC5/X64/OvmfPkg/Sec/SecMain/DEBUG/SecMain.efi<span class="o">)</span>
</code></pre>
</div>
<ul>
<li>Reload symbols using correct addresses of sections:</li>
</ul>
<div class="codehilite">
<pre><span></span><code><span class="o">(</span>gdb<span class="o">)</span> symbol-file
Discard symbol table from <span class="sb">`</span>/home/user/edk2/Build/OvmfX64/DEBUG_GCC5/X64/SecMain.debug<span class="err">'</span>? <span class="o">(</span>y or n<span class="o">)</span> y
No symbol file now.
<span class="o">(</span>gdb<span class="o">)</span> add-symbol-file Build/OvmfX64/DEBUG_GCC5/X64/SecMain.debug <span class="o">(</span><SecMain_BaseAddress>+0x0000000000000240<span class="o">)</span> -s .data <span class="o">(</span><SecMain_BaseAddress>+0x0000000000008900<span class="o">)</span>
add symbol table from file <span class="s2">"Build/OvmfX64/DEBUG_GCC5/X64/SecMain.debug"</span> at
.text_addr <span class="o">=</span> 0xfffcc2d4
.data_addr <span class="o">=</span> 0xfffd4994
<span class="o">(</span>y or n<span class="o">)</span> y
Reading symbols from Build/OvmfX64/DEBUG_GCC5/X64/SecMain.debug...
</code></pre>
</div>
<ul>
<li>Add breakpoint <code>SecCoreStartupWithStack</code></li>
</ul>
<div class="codehilite">
<pre><span></span><code><span class="o">(</span>gdb<span class="o">)</span> <span class="nb">break</span> SecCoreStartupWithStack
</code></pre>
</div>
<ul>
<li>Connect to target:</li>
</ul>
<pre><code>(gdb) target remote :1234
</code></pre>
<ul>
<li>Continue execution by <code>(gdb) c</code></li>
<li>Step to debug print you added in Exercise #2</li>
</ul>
</div>
</div>
</div>
<div class="vert vert-1" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@done+block@8ef5c8efef154efe8cdacf4e22cf1f6c">
<div class="xblock xblock-public_view xblock-public_view-done" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="done" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@done+block@8ef5c8efef154efe8cdacf4e22cf1f6c" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="True">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Completion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
<div class="vert vert-2" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@discussion+block@e198097258c3491fb645e0e148fab3de">
<div class="xblock xblock-public_view xblock-public_view-discussion" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="discussion" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@discussion+block@e198097258c3491fb645e0e148fab3de" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Discussion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
</div>
<script type="text/javascript">
(function (require) {
require(['/static/js/dateutil_factory.be68acdff619.js?raw'], function () {
require(['js/dateutil_factory'], function (DateUtilFactory) {
DateUtilFactory.transform('.localized-datetime');
});
});
}).call(this, require || RequireJS.require);
</script>
<script>
function emit_event(message) {
parent.postMessage(message, '*');
}
</script>
</div>
<div class="xblock xblock-public_view xblock-public_view-vertical" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-init="VerticalStudentView" data-runtime-class="LmsRuntime" data-runtime-version="1" data-block-type="vertical" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@vertical+block@d49560dc1ca34527ae4987ea12354ddb" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="vert-mod">
<div class="vert vert-0" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@markdown+block@91b04905a27f49edbdb25cf9d75956e9">
<div class="xblock xblock-public_view xblock-public_view-markdown" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="markdown" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@markdown+block@91b04905a27f49edbdb25cf9d75956e9" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="markdown_xblock"><p>ASSERT is another macro delivered by DebugLib to simplify debugging process by providing additional information about location of problem.</p>
<p>EDKII uses many debug macros which you can read about <a href="https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/31_testing_and_debugging_uefi_drivers/readme.4">here</a>.</p>
<h2>Exercise #4: Let's try ASSERT</h2>
<ul>
<li>Please add following modification:</li>
</ul>
<div class="codehilite">
<pre><span></span><code><span class="gh">diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c</span>
<span class="gh">index 2c5561661e..fec863836a 100644</span>
<span class="gd">--- a/OvmfPkg/Sec/SecMain.c</span>
<span class="gi">+++ b/OvmfPkg/Sec/SecMain.c</span>
<span class="gu">@@ -815,6 +815,7 @@ SecCoreStartupWithStack (</span>
(UINT32)(UINTN)TopOfCurrentStack
));
<span class="gi">+ ASSERT (FALSE);</span>
//
// Initialize floating point operating environment
// to be compliant with UEFI spec.
</code></pre>
</div>
<ul>
<li>Recompile the code</li>
<li>Run in QEMU</li>
</ul>
<pre><code>qemu-system-x86_64 -nographic -bios Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd -chardev file,path=debug.log,id=edk2-debug -device isa-debugcon,iobase=<I/O Debug Port>,chardev=edk2-debug
</code></pre>
<ul>
<li>In debug.log file you should find following:</li>
</ul>
<pre><code>ASSERT /home/user/edk2/OvmfPkg/Sec/SecMain.c(823): ((BOOLEAN)(0==1))
</code></pre>
<p>As you can see <code>ASSERT</code> macro provide source code file and line, as well as information about the value of the condition which triggered ASSERT. Macro is triggered when its parameter value is FALSE.</p>
<p>Please make sure to remove above modification (assert addition) to avoid problems with further exercises.</p>
</div>
</div>
</div>
<div class="vert vert-1" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@done+block@c015d93c01694110af867448abb3ff8c">
<div class="xblock xblock-public_view xblock-public_view-done" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="done" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@done+block@c015d93c01694110af867448abb3ff8c" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="True">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Completion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
<div class="vert vert-2" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@discussion+block@c1b1c5e54ac543fda3a58b286f6f6107">
<div class="xblock xblock-public_view xblock-public_view-discussion" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="discussion" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@discussion+block@c1b1c5e54ac543fda3a58b286f6f6107" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Discussion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
</div>
<script type="text/javascript">
(function (require) {
require(['/static/js/dateutil_factory.be68acdff619.js?raw'], function () {
require(['js/dateutil_factory'], function (DateUtilFactory) {
DateUtilFactory.transform('.localized-datetime');
});
});
}).call(this, require || RequireJS.require);
</script>
<script>
function emit_event(message) {
parent.postMessage(message, '*');
}
</script>
</div>
<div class="xblock xblock-public_view xblock-public_view-vertical" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-init="VerticalStudentView" data-runtime-class="LmsRuntime" data-runtime-version="1" data-block-type="vertical" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@vertical+block@99a4d78e73c342b3852d1beca0c997a5" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="vert-mod">
<div class="vert vert-0" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@markdown+block@ed2cb3fd452b4545b617f0ab3abc6609">
<div class="xblock xblock-public_view xblock-public_view-markdown" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="markdown" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@markdown+block@ed2cb3fd452b4545b617f0ab3abc6609" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="markdown_xblock"><p>Debugging of some code parts may be challenging because of compiler optimizations, which are enabled by default. Compiler optimization can be disabled in two ways:</p>
<ul>
<li>In DSC for whole package </li>
<li>In INF file just for one module </li>
</ul>
<h2>Exercise #5: disable compiler optimization in INF</h2>
<ul>
<li>Let's build RELEASE and check the size of SecMain module</li>
</ul>
<div class="codehilite">
<pre><span></span><code>build -p OvmfPkg/OvmfPkgX64.dsc -b RELEASE -t GCC5 -n <span class="k">$(</span>nproc<span class="k">)</span> -a X64 all
</code></pre>
</div>
<div class="codehilite">
<pre><span></span><code>user@user-OST-VM:~/edk2$ ls -al Build/OvmfX64/RELEASE_GCC5/X64/SecMain.efi
-rw-rw-r-- <span class="m">1</span> user user <span class="m">32128</span> maj <span class="m">14</span> <span class="m">00</span>:11 Build/OvmfX64/RELEASE_GCC5/X64/SecMain.efi
</code></pre>
</div>
<ul>
<li>Let's build DEBUG and check the size of SecMain module</li>
</ul>
<div class="codehilite">
<pre><span></span><code>build -p OvmfPkg/OvmfPkgX64.dsc -b DEBUG -t GCC5 -n <span class="k">$(</span>nproc<span class="k">)</span> -a X64 all
</code></pre>
</div>
<div class="codehilite">
<pre><span></span><code>user@user-OST-VM:~/edk2$ ls -al Build/OvmfX64/DEBUG_GCC5/X64/SecMain.efi
-rw-rw-r-- <span class="m">1</span> user user <span class="m">39808</span> maj <span class="m">14</span> <span class="m">00</span>:08 Build/OvmfX64/DEBUG_GCC5/X64/SecMain.efi
</code></pre>
</div>
<ul>
<li>Let's disable optimization in DEBUG build</li>
</ul>
<div class="codehilite">
<pre><span></span><code><span class="gh">diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf</span>
<span class="gh">index 95cf0025e1..3c0af1d1ed 100644</span>
<span class="gd">--- a/OvmfPkg/Sec/SecMain.inf</span>
<span class="gi">+++ b/OvmfPkg/Sec/SecMain.inf</span>
<span class="gu">@@ -80,3 +80,6 @@</span>
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
<span class="gi">+</span>
<span class="gi">+[BuildOptions]</span>
<span class="gi">+ GCC:*_*_*_CC_FLAGS = -O0</span>
</code></pre>
</div>
<div class="codehilite">
<pre><span></span><code>build -p OvmfPkg/OvmfPkgX64.dsc -b DEBUG -t GCC5 -n <span class="k">$(</span>nproc<span class="k">)</span> -a X64 all
</code></pre>
</div>
<pre><code>user@user-OST-VM:~/edk2$ ls -al Build/OvmfX64/DEBUG_GCC5/X64/SecMain.efi
-rw-rw-r-- 1 user user 45376 maj 14 00:17 Build/OvmfX64/DEBUG_GCC5/X64/SecMain.efi
</code></pre>
<p>What we can see is that DEBUG is bigger from RELEASE ~25%, but unoptimized debug binary is 40% bigger. The compiler definitely uses shortcuts, that may cause problems when debugging EDKII code. So if you face unexpected behavior during debugging it is worth to consider disabling compiler optimization.</p>
<h2>Exercise #6: disable compiler optimization in DSC</h2>
<p>In case of DSC we disable optimization in the same way, under the same section <code>[BuildOptions]</code>, but in <code>OvmfPkgX64.dsc</code> we already have some flags for GCC RELEASE build.</p>
<div class="codehilite">
<pre><span></span><code><span class="gh">diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc</span>
<span class="gh">index 718399299f..fddbc1cf00 100644</span>
<span class="gd">--- a/OvmfPkg/OvmfPkgX64.dsc</span>
<span class="gi">+++ b/OvmfPkg/OvmfPkgX64.dsc</span>
<span class="gu">@@ -74,6 +74,7 @@</span>
[BuildOptions]
GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG
<span class="gi">+ GCC:DEBUG_*_*_CC_FLAGS = -O0</span>
INTEL:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
MSFT:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
!if $(TOOL_CHAIN_TAG) != "XCODE5" && $(TOOL_CHAIN_TAG) != "CLANGPDB"
!if $(TOOL_CHAIN_TAG) != "XCODE5" && $(TOOL_CHAIN_TAG) != "CLANGPDB"
</code></pre>
</div>
<p>Please note change in wildcard (<code>*</code>) and fact that instead of having <code>*_*_*_CC_FLAGS</code> as in module build options, we distinguish RELEASE and DEBUG build flags.</p>
<div class="codehilite">
<pre><span></span><code>build -p OvmfPkg/OvmfPkgX64.dsc -b DEBUG -t GCC5 -n <span class="k">$(</span>nproc<span class="k">)</span> -a X64 all
</code></pre>
</div>
<pre><code>user@user-OST-VM:~/edk2$ ls -al Build/OvmfX64/DEBUG_GCC5/X64/SecMain.efi
-rw-rw-r-- 1 user user 74432 maj 14 00:28 Build/OvmfX64/DEBUG_GCC5/X64/SecMain.efi
</code></pre>
<p>The effect is that all code used in this package is built without optimization, which means that binaries are even bigger since not only the module itself but everything this module uses is built without optimization. The increase in size in comparison to RELEASE is more then 2x.</p>
<p>Of course the above method can be used to add arbitrary defines or compiler parameters either package-wide or module-wide.</p>
</div>
</div>
</div>
<div class="vert vert-1" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@done+block@495943ad5c89465296e961fbf542f052">
<div class="xblock xblock-public_view xblock-public_view-done" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="done" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@done+block@495943ad5c89465296e961fbf542f052" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="True">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Completion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
<div class="vert vert-2" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@discussion+block@3b7d9cd2e7f04cba9156384c079282bc">
<div class="xblock xblock-public_view xblock-public_view-discussion" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="discussion" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@discussion+block@3b7d9cd2e7f04cba9156384c079282bc" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Discussion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
</div>
<script type="text/javascript">
(function (require) {
require(['/static/js/dateutil_factory.be68acdff619.js?raw'], function () {
require(['js/dateutil_factory'], function (DateUtilFactory) {
DateUtilFactory.transform('.localized-datetime');
});
});
}).call(this, require || RequireJS.require);
</script>
<script>
function emit_event(message) {
parent.postMessage(message, '*');
}
</script>
</div>
<div class="xblock xblock-public_view xblock-public_view-vertical" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-init="VerticalStudentView" data-runtime-class="LmsRuntime" data-runtime-version="1" data-block-type="vertical" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@vertical+block@dad6b46e71534fdc963f3beaae07b3cb" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="vert-mod">
<div class="vert vert-0" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@markdown+block@b6ae274709ea488c84e6fa010f8c2a92">
<div class="xblock xblock-public_view xblock-public_view-markdown" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="markdown" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@markdown+block@b6ae274709ea488c84e6fa010f8c2a92" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="markdown_xblock"><p>EDKII provides the SourceLevelDebug family of packages, which support an alternative way of debugging EDKII source code.
The <a href="https://www.intel.com/content/dam/develop/external/us/en/documents/udk-debugger-tool-user-manual-v1-11-820238.pdf">documentation</a> is outdated,
but worth reading if you plan to use this features with real hardware. There is also a presentation from UEFI forum <a href="https://uefi.org/sites/default/files/resources/EDK_II_SW_debugger_v0.1_lj-Plugfest.pdf">here</a>. Source level debugging features supported on Linux are:</p>
<ul>
<li>GDB support</li>
<li>SEC debugging after temporary RAM initialization</li>
<li>SMM debugging</li>
<li>Debugging for a multiprocessor environment - i.e. an ability to debug code running on application processors (APs), not only the bootstrap processor (BSP)</li>
</ul>
<h2>Exercise #7: Install Intel UDK Debugger Tool</h2>
<ul>
<li>Download, unpack and install:</li>
</ul>
<pre><code>wget https://downloadmirror.intel.com/674526/udk-debugger-tool-v1-5-1-linux.zip
unzip udk-debugger-tool-v1-5-1-linux.zip
chmod +x ./UDK_Debugger_Tool_v1_5_1.bin
sudo ./UDK_Debugger_Tool_v1_5_1.bin -i console
</code></pre>
<p>(<a href="https://gitlab.com/opensecuritytraining/arch4021-intro-uefi-additional-files/-/blob/master/udk-debugger-tool-v1-5-1-linux.zip">Mirror copy of udk-debugger-tool-v1-5-1-linux.zip</a> incase the above link breaks)</p>
<ul>
<li>Follow instructions with default options until <code>Debug Port Channel</code> selection, for which you should choose <code>4</code> (TCP), and then provide server:<code>localhost</code> and port <code>1234</code>.</li>
<li><code>/etc/udkdebugger.conf</code> debug port section should look as follows:</li>
</ul>
<pre><code>[Debug Port]
Channel = TCP
Port = 1234
Server = localhost
</code></pre>
<h2>Exercise #8: Enable Source Level Debugging</h2>
<ul>
<li>Modify DSC file:</li>
</ul>
<div class="codehilite">
<pre><span></span><code><span class="gh">diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc</span>
<span class="gh">index 718399299f..2b1fb75c05 100644</span>
<span class="gd">--- a/OvmfPkg/OvmfPkgX64.dsc</span>
<span class="gi">+++ b/OvmfPkg/OvmfPkgX64.dsc</span>
<span class="gu">@@ -31,7 +31,7 @@</span>
#
DEFINE SECURE_BOOT_ENABLE = FALSE
DEFINE SMM_REQUIRE = FALSE
<span class="gd">- DEFINE SOURCE_DEBUG_ENABLE = FALSE</span>
<span class="gi">+ DEFINE SOURCE_DEBUG_ENABLE = TRUE</span>
!include OvmfPkg/OvmfTpmDefines.dsc.inc
</code></pre>
</div>
<ul>
<li>Build</li>
</ul>
<pre><code>build -p OvmfPkg/OvmfPkgX64.dsc -b DEBUG -t GCC5 -n $(nproc) -a X64 all
</code></pre>
<ul>
<li>Run QEMU, please note serial parameter, which sets up a server to which Intel UDK Debugger can connect</li>
</ul>
<pre><code>qemu-system-x86_64 -nographic -bios Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd -serial tcp:127.0.0.1:1234,server
</code></pre>
<ul>
<li>Run UDK Debugger</li>
</ul>
<pre><code>user@user-OST-VM:~$ /opt/intel/udkdebugger/bin/udk-gdb-server
Intel(R) UEFI Development Kit Debugger Tool Version 1.5.1
Debugging through TCP (localhost:1234)
Redirect Target output to TCP port (20715)
Debug agent revision: 0.4
GdbServer on user-OST-VM is waiting for connection on port 1235
Connect with 'target remote user-OST-VM:1235'
</code></pre>
<ul>
<li>Connect with GDB to port 1235</li>
</ul>
<pre><code>user@user-OST-VM:~$ gdb
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
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-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) target remote :1235
Remote debugging using :1235
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
(gdb) source /opt/intel/udkdebugger/script/udk_gdb_script
##############################################################
# This GDB configuration file contains settings and scripts
# for debugging UDK firmware.
# WARNING: Setting pending breakpoints is NOT supported by the GDB!
##############################################################
Loading symbol for address: 0xfffd04fa
add symbol table from file "/home/user/edk2/Build/OvmfX64/DEBUG_GCC5/X64/OvmfPkg/Sec/SecMain/DEBUG/SecMain.dll" at
.text_addr = 0xfffcc2d4
.data_addr = 0xfffd8c14
(udb) bt
#0 CpuBreakpoint () at /home/user/edk2/MdePkg/Library/BaseLib/X64/GccInline.c:60
#1 PeCoffLoaderExtraActionCommon (ImageContext=0x81fb80, ImageContext@entry=0x0, Signature=1145130828)
at /home/user/edk2/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c:144
#2 0x00000000fffd2aab in PeCoffLoaderRelocateImageExtraAction (ImageContext=0x81fb80) at /home/user/edk2/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c:213
#3 FindAndReportEntryPoints (PeiCoreEntryPoint=0x81fb78, BootFirmwareVolumePtr=<synthetic pointer>) at /home/user/edk2/OvmfPkg/Sec/SecMain.c:708
#4 SecStartupPhase2 (Context=0x81fd20) at /home/user/edk2/OvmfPkg/Sec/SecMain.c:915
#5 0x00000000fffd5861 in DebugPortInitialize (Function=0xfffd0ae7 <InitializeDebugAgentPhase2>, Context=0x81fce0)
at /home/user/edk2/SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.c:66
#6 InitializeDebugAgent (Function=0xfffd2404 <SecStartupPhase2>, Context=0x81fd20, InitFlag=1)
at /home/user/edk2/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c:413
#7 SecCoreStartupWithStack (BootFv=<optimized out>, TopOfCurrentStack=<optimized out>) at /home/user/edk2/OvmfPkg/Sec/SecMain.c:885
#8 0x00000000fffd58d1 in _ModuleEntryPoint ()
#9 0x5aa55aa55aa55aa5 in jQuery22406169556978992354_1653477231226 ()
#10 0x5aa55aa55aa55aa5 in jQuery22406169556978992354_1653477231226 ()
#11 0x5aa55aa55aa55aa5 in jQuery22404820768266656186_1655765907187 ()
#12 0x5aa55aa55aa55aa5 in jQuery22409580249608885256_1655765982338 ()
#13 0x0000000000000000 in jQuery22406487671619152364_1655766019494 ()
</code></pre>
<p>As you can see UDK script recognize paths, location and correctly loaded text and data section. It also can recognize backtrace to some extent.</p>
</div>
</div>
</div>
<div class="vert vert-1" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@done+block@2b527a91398b462882adeaad172914dd">
<div class="xblock xblock-public_view xblock-public_view-done" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="done" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@done+block@2b527a91398b462882adeaad172914dd" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="True">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Completion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
<div class="vert vert-2" data-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@discussion+block@74963ed3310c4888b94bffcd162cc3d6">
<div class="xblock xblock-public_view xblock-public_view-discussion" data-course-id="course-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1" data-block-type="discussion" data-usage-id="block-v1:OpenSecurityTraining2+4021_Intro_UEFI+2022_v1+type@discussion+block@74963ed3310c4888b94bffcd162cc3d6" data-request-token="26db7930091911efabb30242ac12000b" data-graded="True" data-has-score="False">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Discussion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
</div>
<script type="text/javascript">
(function (require) {
require(['/static/js/dateutil_factory.be68acdff619.js?raw'], function () {
require(['js/dateutil_factory'], function (DateUtilFactory) {
DateUtilFactory.transform('.localized-datetime');
});
});
}).call(this, require || RequireJS.require);
</script>
<script>
function emit_event(message) {
parent.postMessage(message, '*');
}
</script>
</div>