{"componentChunkName":"component---src-templates-post-template-js","path":"/unix-xv6-003-setup-kernel-debug-en","result":{"data":{"markdownRemark":{"id":"5f0f9371-7541-57ce-8e78-bdd04fc75a1c","html":"<blockquote>\n<p>This page has been machine-translated from the <a href=\"/unix-xv6-003-setup-kernel-debug\">original page</a>.</p>\n</blockquote>\n<p>I have been reading <a href=\"https://github.com/mit-pdos/xv6-public\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">xv6 OS</a>, inspired by <a href=\"https://amzn.to/3q8TU3K\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">First OS Code Reading – Learning Kernel Mechanisms with UNIX V6</a>.</p>\n<p>I want to get better at reverse engineering and to deepen my knowledge of kernels and operating systems.</p>\n<p><a href=\"https://amzn.to/3I6fkVt\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Understanding the Linux Kernel</a> was quite heavy going, so I was looking for somewhere lighter to start. That is when I learned that UNIX V6 has a total code size of around 10,000 lines — just barely comprehensible for a human being — and I became interested.</p>\n<p>However, UNIX V6 itself does not run on x86 CPUs, so I decided to read the source code of <a href=\"https://github.com/kash1064/xv6-public\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">kash1064/xv6-public: xv6 OS</a>, which is a fork of <a href=\"https://github.com/mit-pdos/xv6-public\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">xv6 OS</a>, an x86-architecture port of UNIX V6.</p>\n<p><a href=\"/unix-xv6-002-load-kernel-en\">In the previous article</a>, we read through the xv6 OS build and boot process.</p>\n<p>I was eager to start reading the kernel proper, but there were parts I could not understand just by reading the code. So I decided to set up a debugging environment first to help deepen my understanding.</p>\n<!-- omit in toc -->\n<h2 id=\"table-of-contents\" style=\"position:relative;\"><a href=\"#table-of-contents\" aria-label=\"table of contents permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Table of Contents</h2>\n<ul>\n<li>\n<p><a href=\"#debugging-xv6-os-with-qemu-gdb\">Debugging xv6 OS with QEMU-GDB</a></p>\n<ul>\n<li><a href=\"#qemu-option-arguments-during-debugging\">QEMU Option Arguments During Debugging</a></li>\n<li><a href=\"#trying-the-debugger\">Trying the Debugger</a></li>\n</ul>\n</li>\n<li><a href=\"#summary\">Summary</a></li>\n</ul>\n<h2 id=\"debugging-xv6-os-with-qemu-gdb\" style=\"position:relative;\"><a href=\"#debugging-xv6-os-with-qemu-gdb\" aria-label=\"debugging xv6 os with qemu gdb permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Debugging xv6 OS with QEMU-GDB</h2>\n<p>The following article was helpful as a reference for the basic procedure.</p>\n<p>Reference: <a href=\"https://qiita.com/ksky/items/974ad1249cfb2dcf5437\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Creating a debug environment for xv6 - Qiita</a></p>\n<p>In my environment I wanted the QEMU console to appear in a separate GUI window, so unlike the article above I am using <code class=\"language-text\">qemu-gdb</code> rather than <code class=\"language-text\">qemu-nox-gdb</code>.</p>\n<p>Connecting the debugger is very straightforward — simply run the following command:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token comment\"># Run in the same directory as the Makefile</span>\n<span class=\"token function\">make</span> qemu-gdb</code></pre></div>\n<p>Next, open another terminal and enter the following commands to enable debugging:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token comment\"># Specify the kernel binary as the debug target in gdb</span>\ngdb kernel\n\n<span class=\"token comment\"># Remote debug via gdb</span>\ntarget remote localhost:26000</code></pre></div>\n<p>First, <code class=\"language-text\">make qemu-gdb</code> builds xv6 OS and then invokes <code class=\"language-text\">qemu-system-i386 -serial mon:stdio -drive file=fs.img,index=1,media=disk,format=raw -drive file=xv6.img,index=0,media=disk,format=raw -smp 2 -m 512  -S -gdb tcp::26000</code>.</p>\n<p>The QEMU option arguments are examined one by one below.</p>\n<h3 id=\"qemu-option-arguments-during-debugging\" style=\"position:relative;\"><a href=\"#qemu-option-arguments-during-debugging\" aria-label=\"qemu option arguments during debugging permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>QEMU Option Arguments During Debugging</h3>\n<p>The option arguments used when running <code class=\"language-text\">make qemu-gdb</code> are as follows:</p>\n<table>\n<thead>\n<tr>\n<th align=\"center\">Option Argument</th>\n<th align=\"center\">Purpose</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td align=\"center\">-serial &#x3C;dev></td>\n<td align=\"center\">Redirect the virtual serial device to the host.<br />With <code class=\"language-text\">mon:stdio</code>, both the console and the QEMU monitor are displayed in the terminal.</td>\n</tr>\n<tr>\n<td align=\"center\">-drive &#x3C;options></td>\n<td align=\"center\">Add a new block device or interface.<br />Here, <code class=\"language-text\">xv6.img</code> and <code class=\"language-text\">fs.img</code> are each loaded as a disk.</td>\n</tr>\n<tr>\n<td align=\"center\">-smp &#x3C;cpus></td>\n<td align=\"center\">Emulate SMP (multi-processor system) using the specified number of CPUs.</td>\n</tr>\n<tr>\n<td align=\"center\">-m &#x3C;MB or GB></td>\n<td align=\"center\">Specify the memory size at virtual machine startup (default unit: MB).<br />A prefix such as <code class=\"language-text\">1G</code> can be used to specify gigabytes.</td>\n</tr>\n<tr>\n<td align=\"center\">-S</td>\n<td align=\"center\">Do not use the CPU at startup (i.e., halt immediately after power-on and wait for a GDB connection).</td>\n</tr>\n<tr>\n<td align=\"center\">-gdb &#x3C;tcp::port></td>\n<td align=\"center\">Accept GDB connections on the specified protocol and port.</td>\n</tr>\n</tbody>\n</table>\n<p>Reference: <a href=\"https://www.qemu.org/docs/master/system/invocation.html#hxtool-0\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Invocation — QEMU documentation</a></p>\n<p>Reference: <a href=\"https://qiita.com/wataash/items/174b454d4478898a556b\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">QEMU Options Cheat Sheet for Kernel Debugging - Qiita</a></p>\n<h3 id=\"trying-the-debugger\" style=\"position:relative;\"><a href=\"#trying-the-debugger\" aria-label=\"trying the debugger permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Trying the Debugger</h3>\n<p>Symbol information for the xv6 kernel is stored in <code class=\"language-text\">kernel.sym</code> at build time.</p>\n<p>Looking up the address of a symbol on the GDB side gives the same result:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ info address main\nSymbol <span class=\"token string\">\"main\"</span> is a <span class=\"token keyword\">function</span> at address 0x80103040.</code></pre></div>\n<p>Set a breakpoint at the <code class=\"language-text\">main</code> function:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ main\n$ c\nContinuing.\n<span class=\"token punctuation\">[</span>----------------------------------registers-----------------------------------<span class=\"token punctuation\">]</span>\nEAX: 0x80103040 --<span class=\"token operator\">></span> 0xfb1e0ff3 \nEBX: 0x10094 --<span class=\"token operator\">></span> 0x0 --<span class=\"token operator\">></span> 0xf000ff53 \nECX: 0x0 --<span class=\"token operator\">></span> 0xf000ff53 \nEDX: 0x1f0 --<span class=\"token operator\">></span> 0xf000ff53 \nESI: 0x10094 --<span class=\"token operator\">></span> 0x0 --<span class=\"token operator\">></span> 0xf000ff53 \nEDI: 0x0 --<span class=\"token operator\">></span> 0xf000ff53 \nEBP: 0x7bf8 --<span class=\"token operator\">></span> 0x0 --<span class=\"token operator\">></span> 0xf000ff53 \nESP: 0x8010b5c0 --<span class=\"token operator\">></span> 0x0 --<span class=\"token operator\">></span> 0xf000ff53 \nEIP: 0x80103040 --<span class=\"token operator\">></span> 0xfb1e0ff3\nEFLAGS: 0x86 <span class=\"token punctuation\">(</span>carry PARITY adjust zero SIGN <span class=\"token builtin class-name\">trap</span> interrupt direction overflow<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">[</span>-------------------------------------code-------------------------------------<span class=\"token punctuation\">]</span>\n   0x80103034 <span class=\"token operator\">&lt;</span>mpenter+2<span class=\"token operator\"><span class=\"token file-descriptor important\">0</span>></span>:\tcall   0x801027a0 <span class=\"token operator\">&lt;</span>lapicinit<span class=\"token operator\">></span>\n   0x80103039 <span class=\"token operator\">&lt;</span>mpenter+2<span class=\"token operator\"><span class=\"token file-descriptor important\">5</span>></span>:\tcall   0x80102fe0 <span class=\"token operator\">&lt;</span>mpmain<span class=\"token operator\">></span>\n   0x8010303e:\txchg   ax,ax\n<span class=\"token operator\">=</span><span class=\"token operator\">></span> 0x80103040 <span class=\"token operator\">&lt;</span>main<span class=\"token operator\">></span>:\tendbr32 \n   0x80103044 <span class=\"token operator\">&lt;</span>main+<span class=\"token operator\"><span class=\"token file-descriptor important\">4</span>></span>:\tlea    ecx,<span class=\"token punctuation\">[</span>esp+0x4<span class=\"token punctuation\">]</span>\n   0x80103048 <span class=\"token operator\">&lt;</span>main+<span class=\"token operator\"><span class=\"token file-descriptor important\">8</span>></span>:\tand    esp,0xfffffff0\n   0x8010304b <span class=\"token operator\">&lt;</span>main+1<span class=\"token operator\"><span class=\"token file-descriptor important\">1</span>></span>:\tpush   DWORD PTR <span class=\"token punctuation\">[</span>ecx-0x4<span class=\"token punctuation\">]</span>\n   0x8010304e <span class=\"token operator\">&lt;</span>main+1<span class=\"token operator\"><span class=\"token file-descriptor important\">4</span>></span>:\tpush   ebp\n<span class=\"token punctuation\">[</span>------------------------------------stack-------------------------------------<span class=\"token punctuation\">]</span>\n0000<span class=\"token operator\">|</span> 0x8010b5c0 --<span class=\"token operator\">></span> 0x0 --<span class=\"token operator\">></span> 0xf000ff53 \n0004<span class=\"token operator\">|</span> 0x8010b5c4 --<span class=\"token operator\">></span> 0x0 --<span class=\"token operator\">></span> 0xf000ff53 \n0008<span class=\"token operator\">|</span> 0x8010b5c8 --<span class=\"token operator\">></span> 0x0 --<span class=\"token operator\">></span> 0xf000ff53 \n0012<span class=\"token operator\">|</span> 0x8010b5cc --<span class=\"token operator\">></span> 0x0 --<span class=\"token operator\">></span> 0xf000ff53 \n0016<span class=\"token operator\">|</span> 0x8010b5d0 --<span class=\"token operator\">></span> 0x0 --<span class=\"token operator\">></span> 0xf000ff53 \n0020<span class=\"token operator\">|</span> 0x8010b5d4 --<span class=\"token operator\">></span> 0x0 --<span class=\"token operator\">></span> 0xf000ff53 \n0024<span class=\"token operator\">|</span> 0x8010b5d8 --<span class=\"token operator\">></span> 0x0 --<span class=\"token operator\">></span> 0xf000ff53 \n0028<span class=\"token operator\">|</span> 0x8010b5dc --<span class=\"token operator\">></span> 0x0 --<span class=\"token operator\">></span> 0xf000ff53 \n<span class=\"token punctuation\">[</span>------------------------------------------------------------------------------<span class=\"token punctuation\">]</span>\nLegend: code, data, rodata, value\n\nThread <span class=\"token number\">1</span> hit Breakpoint <span class=\"token number\">1</span>, main <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> at main.c:19</code></pre></div>\n<p>In my environment I have gdb-peda enabled, so quite a bit of information is displayed.</p>\n<p>This completes the setup for debugging the kernel.</p>\n<h2 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Summary</h2>\n<p>I originally planned to use bochs, but the troubleshooting did not go well, so I decided to use GDB for debugging instead.</p>\n<p>This approach turned out to be better in the end since it is easier to configure and I am more comfortable with it.</p>\n<p>This time I will really, truly start reading the kernel proper.</p>","fields":{"slug":"/unix-xv6-003-setup-kernel-debug-en","tagSlugs":["/tag/unix-en/","/tag/xv-6-en/","/tag/kernel-en/","/tag/os-en/","/tag/english/"]},"frontmatter":{"date":"2022-01-24","description":"Reading the source code of xv6 OS, an educational operating system, to learn about the kernel. In this article, we set up a GDB debugging environment for the xv6 OS kernel.","tags":["Unix (en)","xv6 (en)","Kernel (en)","OS (en)","English"],"title":"Reading xv6 OS Seriously to Fully Understand the Kernel – GDB Debug Environment Setup","socialImage":{"publicURL":"/static/8ad19b30a768f586cec17434bc789068/unix-xv6-003-setup-kernel-debug.png"}}}},"pageContext":{"slug":"/unix-xv6-003-setup-kernel-debug-en"}},"staticQueryHashes":["251939775","401334301","825871152"]}