<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Aditya Basu</title>
    <description>notes of a graduate student</description>
    <link>https://www.adityabasu.me</link>
    <atom:link href="https://www.adityabasu.me/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>Setup kgdboc for kernel debugging</title>
        <description>&lt;p&gt;The goal is to setup a Linux based VirtualBox VM which can be debugged from the host, or another VM.
To debug using another physical machine, see &lt;a href=&quot;#debug-from-another-physical-machine&quot;&gt;Debug from another (physical) machine&lt;/a&gt; section.&lt;/p&gt;

&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;kgdboc is the debugger that helps debug the kernel over a remote gdb session.&lt;/p&gt;

&lt;p&gt;kdb gives a debug console to run commands directly against the kernel. It can dump physical memory, list running processes etc.&lt;/p&gt;

&lt;p&gt;At runtime one can dynamically switch between both the debugger. The latest official kernel doc is &lt;a href=&quot;https://www.kernel.org/doc/html/latest/dev-tools/kgdb.html#kernel-config-options-for-kgdb&quot; title=&quot;Kernel Debugging Guide&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;setup-the-virtualbox-vm&quot;&gt;Setup the VirtualBox VM&lt;/h1&gt;
&lt;p&gt;We will be debugging the VM’s kernel. Before we can debug the VM’s kernel, we need to prep the VM.&lt;/p&gt;

&lt;p&gt;To begin, go to the VM’s settings and open “Serial Ports”. Enable COM1, select port mode to be “Host Pipe”. Give the path as “/tmp/vm-serial-socket”.
Make sure to have “Connect to existing pipe/socket” &lt;strong&gt;unchecked&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/20200325-vm1-serial-socket.png&quot; alt=&quot;VirtualBox Serial Port Setting&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Alternatively if you are using vagrant, then add the following to your Vagrantfile and then run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vagrant reload&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;provider&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;virtualbox&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;customize&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;modifyvm&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;--uart1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;0x3f8&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;--uartmode1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;  /tmp/vm-serial-socket&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we need to make sure that the kernel is compiled with debugging support.
In kernel config, look under “Kernel hacking” ‣ “Kernel debugging” and select
KGDB: kernel debugger.&lt;/p&gt;

&lt;p&gt;To be able to add software breakpoints to the running kernel, we need to
disable kernel’s read-only data protection. In kernel config, look under
“Kernel hacking” ‣ “Write protect kernel read-only data structures” and
&lt;strong&gt;unselect&lt;/strong&gt; this option.&lt;/p&gt;

&lt;p&gt;The above will modify the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; file as below -&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# These options need to enabled in .config&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;CONFIG_FRAME_POINTER&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;y
&lt;span class=&quot;nv&quot;&gt;CONFIG_KGDB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;y
&lt;span class=&quot;nv&quot;&gt;CONFIG_KGDB_SERIAL_CONSOLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;y

&lt;span class=&quot;c&quot;&gt;# To disable RO protection on older kernels (ex. v3.2)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;CONFIG_DEBUG_RODATA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;n

&lt;span class=&quot;c&quot;&gt;# To disable RO protection on newer kernels (ex. v5.6.0)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;CONFIG_STRICT_KERNEL_RWX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;n
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Recompile and install the newly compiled kernel.&lt;/p&gt;

&lt;p&gt;Now to enable debugging support during boot, we need to add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kgdboc=ttyS0,115200&lt;/code&gt; to the kernel’s command line options. Also to do meaningful debugging, we disable KASLR using &lt;a href=&quot;https://stackoverflow.com/questions/44612822/why-gdb-cannot-find-the-source-lines-of-the-linux-kernel-when-debugging-through&quot; title=&quot;Cannot add breakpoint to kernel function&quot;&gt;nokaslr&lt;/a&gt;. For Ubuntu based distro, this can be done via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/default/grub&lt;/code&gt; file.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;vm1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'GRUB_CMDLINE_LINUX_DEFAULT=&quot;console=tty0 nokaslr kgdboc=kbd,ttyS0,115200&quot;'&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; /etc/default/grub

vm1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;update-grub
Generating grub.cfg ...
Found linux image: /boot/vmlinuz-3.2.0-pfwall-fedora-patches+
Found initrd image: /boot/initrd.img-3.2.0-pfwall-fedora-patches+
Found linux image: /boot/vmlinuz-3.2.0-126-virtual
Found initrd image: /boot/initrd.img-3.2.0-126-virtual
Found memtest86+ image: /boot/memtest86+.bin
&lt;span class=&quot;k&quot;&gt;done

&lt;/span&gt;vm1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;reboot
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After rebooting the virtual machine, verify that the serial port configured -&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# Verify serial port&lt;/span&gt;
vm1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dmesg | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;serial
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;    2.149591] serial8250: ttyS0 at I/O 0x3f8 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;irq &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 4&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; is a 16550A

&lt;span class=&quot;c&quot;&gt;# Verify kernel debugging support&lt;/span&gt;
vm1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dmesg | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;kgdboc
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;    0.000000] Command line: &lt;span class=&quot;nv&quot;&gt;BOOT_IMAGE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/boot/vmlinuz-3.2.0-pfwall-fedora-patches+ &lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;7d69eb56-ea8c-4243-8e7d-e2714fced818 ro &lt;span class=&quot;nv&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;tty0 &lt;span class=&quot;nv&quot;&gt;kgdboc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;kbd,ttyS0,115200
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;    0.000000] Kernel &lt;span class=&quot;nb&quot;&gt;command &lt;/span&gt;line: &lt;span class=&quot;nv&quot;&gt;BOOT_IMAGE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/boot/vmlinuz-3.2.0-pfwall-fedora-patches+ &lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;7d69eb56-ea8c-4243-8e7d-e2714fced818 ro &lt;span class=&quot;nv&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;tty0 &lt;span class=&quot;nv&quot;&gt;kgdboc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;kbd,ttyS0,115200
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;    3.458898] kgdb: Registered I/O driver kgdboc.

&lt;span class=&quot;c&quot;&gt;# To dynamically change the kgdboc parameters, use -&lt;/span&gt;
vm1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;ttyS0,115200 | &lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; /sys/module/kgdboc/parameters/kgdboc
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To manually trigger a kernel trap and enter into the debug prompt, use the following command. &lt;strong&gt;Note&lt;/strong&gt; that the ssh session or VM’s console will hang after running the below command.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# Trigger a trap&lt;/span&gt;
vm1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;g | &lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; /proc/sysrq-trigger
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;option-1-debug-via-host&quot;&gt;Option 1: Debug via Host&lt;/h1&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/vm-serial-socket&lt;/code&gt; gets created by VirtualBox when the VM is started.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;host&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;file &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; /tmp/vm-serial-socket
/tmp/vm-serial-socket: inode/socket&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;binary
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To enable gdb to access the socket, we need to expose a pseudoterminal device. For this we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;socat&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;host&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;socat /tmp/vm-serial-socket PTY,link&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/tmp/vm-serial-pty &amp;amp;

&lt;span class=&quot;c&quot;&gt;# For debugging&lt;/span&gt;
host&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;socat &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /tmp/vm-serial-socket PTY,link&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/tmp/vm-serial-pty
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Looking at the pty file that socat creates -&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;host&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;file /tmp/vm-serial-pty
/tmp/vm-serial-pty: symbolic &lt;span class=&quot;nb&quot;&gt;link &lt;/span&gt;to /dev/pts/8

host&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;file /dev/pts/8
/dev/pts/8: character special &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;136/8&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;using-gdbserver&quot;&gt;Using gdbserver&lt;/h2&gt;
&lt;p&gt;Run the below commands after trigerring a kernel trap in the VM (via sysrq), otherwise gdb will &lt;strong&gt;timeout&lt;/strong&gt; with the error.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;host&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb kernel/vmlinux &lt;span class=&quot;nt&quot;&gt;-ex&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;target remote /tmp/vm-serial-pty&quot;&lt;/span&gt;
GNU gdb &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Ubuntu 8.1-0ubuntu3.2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 8.1.0.20180409-git
Copyright &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 2018 Free Software Foundation, Inc.
...
Reading symbols from kernel/vmlinux...
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
Remote debugging using /tmp/vm-serial-pty
kgdb_breakpoint &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; at kernel/debug/debug_core.c:960
960     kernel/debug/debug_core.c: No such file or directory.
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; bt
&lt;span class=&quot;c&quot;&gt;#0  kgdb_breakpoint () at kernel/debug/debug_core.c:960&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#1  0xffffffff810bbef0 in sysrq_handle_dbg (key=&amp;lt;optimized out&amp;gt;) at kernel/debug/debug_core.c:750&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#2  0xffffffff81386181 in __handle_sysrq (key=103, check_mask=false) at drivers/tty/sysrq.c:522&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#3  0xffffffff8138627b in write_sysrq_trigger (file=&amp;lt;optimized out&amp;gt;, buf=&amp;lt;optimized out&amp;gt;, count=2, ppos=&amp;lt;optimized out&amp;gt;) at drivers/tty/sysrq.c:870&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#4  0xffffffff811b20c1 in proc_reg_write (file=0xffff88026ca7db00, buf=0x7fffffffc650 &quot;g\n&quot;, count=2, ppos=0xffff88026c503f48) at fs/proc/inode.c:218&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#5  0xffffffff811596a5 in vfs_write (file=0xffff88026ca7db00, buf=0x7fffffffc650 &quot;g\n&quot;, count=2, pos=0xffff88026c503f48) at fs/read_write.c:438&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#6  0xffffffff811599bb in sys_write (fd=&amp;lt;optimized out&amp;gt;, buf=0x7fffffffc650 &quot;g\n&quot;, count=2) at fs/read_write.c:495&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#7  &amp;lt;signal handler called&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#8  0x00007ffff7b01f10 in ?? ()&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#9  0x0000000000000000 in ?? ()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# To reboot (refer kernel/debug/gdbstub.c:gdb_cmd_reboot())&lt;/span&gt;
maintenance packet R0

&lt;span class=&quot;c&quot;&gt;# To switch to the kdb shell&lt;/span&gt;
maintenance packet 3
&lt;span class=&quot;c&quot;&gt;# and exit gdb with CTRL-C&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The following is the timeout error if the kernel being debugged does not trap before gdb tries to connect. If this happens, then quit gdb, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo g | sudo tee /proc/sysrq-trigger&lt;/code&gt; in the vm (kernel being debugged) and then run the above gdb command.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# Error on timeout&lt;/span&gt;
host&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb kernel/vmlinux &lt;span class=&quot;nt&quot;&gt;-ex&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;target remote /tmp/vm-serial-pty&quot;&lt;/span&gt;
GNU gdb &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Ubuntu 8.1-0ubuntu3.2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 8.1.0.20180409-git
Copyright &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 2018 Free Software Foundation, Inc.
...
Remote debugging using /tmp/vm-serial-pty
Ignoring packet error, continuing...
warning: unrecognized item &lt;span class=&quot;s2&quot;&gt;&quot;timeout&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;qSupported&quot;&lt;/span&gt; response
Ignoring packet error, continuing...
Remote replied unexpectedly to &lt;span class=&quot;s1&quot;&gt;'vMustReplyEmpty'&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;timeout&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Optionally, to view gdb's protocol packets&lt;/span&gt;
host&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb kernel/vmlinux &lt;span class=&quot;nt&quot;&gt;-ex&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;set debug remote 1&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ex&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;target remote /tmp/vm-serial-pty&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;using-kbd&quot;&gt;Using kbd&lt;/h2&gt;
&lt;p&gt;After issuing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;maintenance packet 3&lt;/code&gt; in gdb shell, you would have switched to the kbd shell. Now you can connect to the serial port (pty) directly using screen.&lt;/p&gt;

&lt;p&gt;Again note that you can see a blank screen (after invoking screen) unless you issue a kernel trap in the kernel being debugged. If this happens then run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo g | sudo tee /proc/sysrq-trigger&lt;/code&gt; in the vm (kernel being debugged).&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;host&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;screen /tmp/vm-serial-pty
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1]kdb&amp;gt; ps
3 idle processes &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;state I&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; and 
51 sleeping system daemon &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;state M&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; processes suppressed,
use &lt;span class=&quot;s1&quot;&gt;'ps A'&lt;/span&gt; to see all.
Task Addr               Pid   Parent &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; cpu State Thread             Command
0xffff88026c51dc70     2033     2032  1    1   R  0xffff88026c51e0e0 &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tee

&lt;/span&gt;0xffff88028e4c0000        1        0  0    1   S  0xffff88028e4c0470  init
0xffff88026d7bdc70      280        1  0    2   S  0xffff88026d7be0e0  python
0xffff88026d7fdc70      367        1  0    1   S  0xffff88026d7fe0e0  upstart-udev-br
0xffff88026efb5c70      369        1  0    1   S  0xffff88026efb60e0  udevd
...

&lt;span class=&quot;c&quot;&gt;# For help&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1]kdb&amp;gt; ?
Command         Usage                Description
&lt;span class=&quot;nt&quot;&gt;----------------------------------------------------------&lt;/span&gt;
md              &amp;lt;vaddr&amp;gt;              Display Memory Contents, also mdWcN, e.g. md8c1
mdr             &amp;lt;vaddr&amp;gt; &amp;lt;bytes&amp;gt;      Display Raw Memory
mdp             &amp;lt;paddr&amp;gt; &amp;lt;bytes&amp;gt;      Display Physical Memory
mds             &amp;lt;vaddr&amp;gt;              Display Memory Symbolically
mm              &amp;lt;vaddr&amp;gt; &amp;lt;contents&amp;gt;   Modify Memory Contents
go              &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&amp;lt;vaddr&amp;gt;]            Continue Execution
...

&lt;span class=&quot;c&quot;&gt;# To continue kernel execution&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1]kdb&amp;gt; go

&lt;span class=&quot;c&quot;&gt;# To revert to kgdboc&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1]kdb&amp;gt; kgdboc
Entering please attach debugger or use &lt;span class=&quot;nv&quot;&gt;$D&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#44+ or $3#33&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Use Ctrl-A + k to kill the screen session.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Connect over kgdboc using gdb.&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;option-2-debug-via-another-vm&quot;&gt;Option 2: Debug via another VM&lt;/h1&gt;
&lt;p&gt;We can also spawn another virtual machine (say VM2) and debug the the first virtual machine (VM1).&lt;/p&gt;

&lt;p&gt;For this we need to set up VM2 to be the client for the socket created by VM1. Go to the VM2’s settings and open “Serial Ports”. Enable COM1, select port mode to be “Host Pipe”. Give the path as “/tmp/vm-serial-socket”.
&lt;strong&gt;Check&lt;/strong&gt; the option “Connect to existing pipe/socket”.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/20200325-vm2-serial-socket.png&quot; alt=&quot;VirtualBox Serial Port Setting for VM2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Alternatively if you are using vagrant, then add the following to your Vagrantfile and then run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vagrant reload&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;provider&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;virtualbox&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;customize&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;modifyvm&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;--uart1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;0x3f8&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;--uartmode1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;client&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;  /tmp/vm-serial-socket&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now start VM2 and verify the serial connection using -&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# Verify serial port&lt;/span&gt;
vm2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dmesg | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;serial
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;    2.149591] serial8250: ttyS0 at I/O 0x3f8 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;irq &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 4&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; is a 16550A
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now VM2 sees a physical serial port instead of a socket. Hence we no longer need to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;socat&lt;/code&gt; to create a pseudoterminal device. The following is a summary of updated commands -&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# Debug via kgdboc&lt;/span&gt;
vm2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;gdb /vagrant/kernel/vmlinux &lt;span class=&quot;nt&quot;&gt;-ex&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;target remote /dev/ttyS0&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Debug via kdb&lt;/span&gt;
vm2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;screen /dev/ttyS0
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;gotchas&quot;&gt;Gotchas&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;p&gt;Remote debugging (i.e. press CTRL-C to drop into gdb prompt) cannot be triggered over serial or via gdb. You need to break in from the guest kernel (using sysrq).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;extras&quot;&gt;Extras&lt;/h1&gt;
&lt;h2 id=&quot;kernels-command-line-parameters&quot;&gt;Kernel’s command line parameters&lt;/h2&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;vm1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /proc/cmdline 
&lt;span class=&quot;nv&quot;&gt;BOOT_IMAGE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/boot/vmlinuz-3.2.0-pfwall-fedora-patches+ &lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;7d69eb56-ea8c-4243-8e7d-e2714fced818 ro &lt;span class=&quot;nv&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;tty0 nokaslr &lt;span class=&quot;nv&quot;&gt;kgdboc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;kbd,ttyS0,115200
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;get-kernel-symbols-at-runtime&quot;&gt;Get kernel symbols at runtime&lt;/h2&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# Get runtime symbol table&lt;/span&gt;
vm1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo head&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-5&lt;/span&gt; /proc/kallsyms 
0000000000000000 D irq_stack_union
0000000000000000 D __per_cpu_start
0000000000004000 D gdt_page
0000000000005000 d exception_stacks
000000000000b000 d tlb_vector_offset
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that &lt;a href=&quot;https://stackoverflow.com/questions/10447491/reading-kallsyms-in-user-mode&quot; title=&quot;Reading kernel symbols&quot;&gt;only superuser (i.e. root)&lt;/a&gt; can read the kernel addresses of the symbols.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;vm1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-5&lt;/span&gt; /proc/kallsyms 
0000000000000000 D irq_stack_union
0000000000000000 D __per_cpu_start
0000000000000000 D gdt_page
0000000000000000 d exception_stacks
0000000000000000 d tlb_vector_offset
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;print-variables-from-the-live-kernel&quot;&gt;Print variables from the live kernel&lt;/h2&gt;
&lt;p&gt;The file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/proc/kcore&lt;/code&gt; is the kernel’s core dump file at a specific time. gdb can be used to &lt;a href=&quot;https://www.linux.com/training-tutorials/kernel-newbie-corner-kernel-and-module-debugging-gdb/&quot; title=&quot;Debugging live kernel and its modules&quot;&gt;interpret it&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;vm1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb /vagrant/kernel/vmlinux /proc/kcore
GNU gdb &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 7.4-2012.04
Copyright &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later &amp;lt;http://gnu.org/licenses/gpl.html&amp;gt;
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type &lt;span class=&quot;s2&quot;&gt;&quot;show copying&quot;&lt;/span&gt;
and &lt;span class=&quot;s2&quot;&gt;&quot;show warranty&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;details.
This GDB was configured as &lt;span class=&quot;s2&quot;&gt;&quot;x86_64-linux-gnu&quot;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
For bug reporting instructions, please see:
&amp;lt;http://bugs.launchpad.net/gdb-linaro/&amp;gt;...
Reading symbols from /home/vagrant/linux-pfwall/vmlinux...done.
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;New process 1]
Core was generated by &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BOOT_IMAGE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/boot/vmlinuz-3.2.0-pfwall-fedora-patches+ &lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;7d69eb56-ea8c-42&lt;span class=&quot;s1&quot;&gt;'.
#0  0x0000000000000000 in ?? ()

(gdb) p vfs_read
$4 = {ssize_t (struct file *, char *, size_t, loff_t *)} 0xffffffff811597a1 &amp;lt;vfs_read&amp;gt;

(gdb) print irq_err_count
$11 = {counter = 0}

&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Reloading the core dump -&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; core-file /proc/kcore
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;New process 1]
Core was generated by &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BOOT_IMAGE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/boot/vmlinuz-3.2.0-pfwall-fedora-patches+ &lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;7d69eb56-ea8c-42&lt;span class=&quot;s1&quot;&gt;'.
#0  0x0000000000000000 in ?? ()
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;view-printk-messages-in-gdb&quot;&gt;View printk messages in gdb&lt;/h2&gt;

&lt;p&gt;This feature is available on newer kernels such as v5.6.0. Use any of the following methods to enable printks’ in the gdb console -&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Method #1:&lt;/strong&gt; Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kgdbcon&lt;/code&gt; to kernel’s command line option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Method #2:&lt;/strong&gt; At runtime, use sysfs before configuring an I/O driver (i.e. kgdb)&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;1 | &lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; /sys/module/kgdb/parameters/kgdb_use_con
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;debug-from-another-physical-machine&quot;&gt;Debug from another (physical) machine&lt;/h2&gt;

&lt;p&gt;When using a &lt;strong&gt;physical serial connection&lt;/strong&gt;, i.e. debugging one physical machine (instead of a VM) using another physical machine, it may be necessary to specify the baud rate. Also root permissions are needed to access the serial port (hence the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo&lt;/code&gt;).&lt;/p&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;gdbserver&quot;&gt;gdbserver&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;host&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;file /dev/ttyUSB0
/dev/ttyUSB0: character special &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;188/0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Debug via physical serial&lt;/span&gt;
host&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;gdb vmlinux &lt;span class=&quot;nt&quot;&gt;-ex&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;target remote /dev/ttyUSB0&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; 115200
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class=&quot;no_toc&quot; id=&quot;kbd&quot;&gt;kbd&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# -L records the entire session in screenlog.0&lt;/span&gt;
host&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;screen &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; /dev/ttyUSB0 115200

&lt;span class=&quot;c&quot;&gt;# To exit use: Ctrl+a k y&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4 class=&quot;no_toc&quot; id=&quot;updates&quot;&gt;Updates&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;October 1, 2020:
    &lt;ul&gt;
      &lt;li&gt;Guidelines to debug a physical machine&lt;/li&gt;
      &lt;li&gt;Instructions to reboot kernel via gdb&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;April 7, 2020:
    &lt;ul&gt;
      &lt;li&gt;Add kernel config option to disable read-only kernel protection&lt;/li&gt;
      &lt;li&gt;Method to view printk messages in gdb&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;March 31, 2020:
    &lt;ul&gt;
      &lt;li&gt;Add – Print variables from the live kernel&lt;/li&gt;
      &lt;li&gt;Add – Kernel’s command line parameters&lt;/li&gt;
      &lt;li&gt;Add – Get kernel symbols at runtime&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;!-- References --&gt;

&lt;!-- Unused References --&gt;
</description>
        <pubDate>Wed, 25 Mar 2020 00:00:00 -0400</pubDate>
        <link>https://www.adityabasu.me/blog/2020/03/kgdboc-setup/</link>
        <guid isPermaLink="true">https://www.adityabasu.me/blog/2020/03/kgdboc-setup/</guid>
      </item>
    
      <item>
        <title>Disable Hyper-V</title>
        <description>&lt;p&gt;Running 64-bit VirtualBox 6.0 VMs with Hyper-V does not work yet. So one possible solution is to turn off Hyper-V. However turning off Hyper-V from “Turn Windows Features On or Off” does not completely turn off Hyper-V.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;virtualbox-logs&quot;&gt;VirtualBox Logs&lt;/h2&gt;
&lt;p&gt;The following logs represent the problem -&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;...
00:00:02.401079 NEM: Adjusting APIC configuration from X2APIC to APIC max mode.  X2APIC is not supported by the WinHvPlatform API!
00:00:02.401084 NEM: Disable Hyper-V if you need X2APIC for your guests!
00:00:02.401180 NEM: NEMR3Init: Active.
00:00:02.401218 MM: cbHyperHeap=0x140000 (1310720)
00:00:02.401801 CPUM: No hardware-virtualization capability detected
...
00:00:02.405504 VMSetError: F:\tinderbox\win-6.0\src\VBox\VMM\VMMR3\NEMR3Native-win.cpp(1463) int __cdecl nemR3NativeInitAfterCPUM(struct VM *); rc=VERR_NEM_VM_CREATE_FAILED
00:00:02.405534 VMSetError: Call to WHvSetupPartition failed: ERROR_SUCCESS (Last=0xc000000d/87)
00:00:02.405558 NEM: Destroying partition 0000000001763a60 with its 0 VCpus...
00:00:02.533155 ERROR [COM]: aRC=E_FAIL (0x80004005) aIID={872da645-4a9b-1727-bee2-5585105b9eed} aComponent={ConsoleWrap} aText={Call to WHvSetupPartition failed: ERROR_SUCCESS (Last=0xc000000d/87) (VERR_NEM_VM_CREATE_FAILED)}, preserve=false aResultDetail=-6805
00:00:02.533347 Console: Machine state changed to 'PoweredOff'
00:00:02.540651 Power up failed (vrc=VERR_NEM_VM_CREATE_FAILED, rc=E_FAIL (0X80004005))
...
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;fix&quot;&gt;Fix&lt;/h2&gt;
&lt;p&gt;To disable Hyper-V during boot, run the following in cmd.exe (Administrator) -&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;bcdedit /set hypervisorlaunchtype off
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that &lt;strong&gt;WSL 2.0&lt;/strong&gt; relies on Hyper-V. So it will likely not work.&lt;/p&gt;

&lt;!--
	Backlinks:
	* https://news.ycombinator.com/item?id=19843596
 --&gt;
</description>
        <pubDate>Wed, 18 Sep 2019 00:00:00 -0400</pubDate>
        <link>https://www.adityabasu.me/blog/2019/09/disable-hyper-v/</link>
        <guid isPermaLink="true">https://www.adityabasu.me/blog/2019/09/disable-hyper-v/</guid>
      </item>
    
      <item>
        <title>Setting up SSH Agent</title>
        <description>&lt;p&gt;Stuff about ssh agents.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;manaully-add-ssh-keys-to-the-agent&quot;&gt;Manaully add ssh keys to the agent&lt;/h2&gt;

&lt;p&gt;Add identities -&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# On Linux&lt;/span&gt;
ssh-add &lt;span class=&quot;nt&quot;&gt;-k&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# On macOS&lt;/span&gt;
ssh-add &lt;span class=&quot;nt&quot;&gt;-K&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;List loaded identities&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;ssh-add &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;automatically-load-keys&quot;&gt;Automatically load keys&lt;/h2&gt;

&lt;p&gt;To auto-load to the agent while logging in -&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;AddKeysToAgent yes&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;~/.ssh/config
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Thu, 11 Jul 2019 00:00:00 -0400</pubDate>
        <link>https://www.adityabasu.me/blog/2019/07/ssh-agent/</link>
        <guid isPermaLink="true">https://www.adityabasu.me/blog/2019/07/ssh-agent/</guid>
      </item>
    
      <item>
        <title>Versioning Resume (&amp; LaTeX docs) using Git SHA</title>
        <description>&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;tl;dr&lt;/strong&gt; Tagging resume using version numbers derived from git commit SHA. This helps in quickly retrieving any specific version of the resume. Also storing old PDF copies of the resume is not necessary.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;workflow&quot;&gt;Workflow&lt;/h2&gt;

&lt;p&gt;My resume is typeset using LaTeX and revision controlled under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt;. There is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Makefile&lt;/code&gt; in the root directory to take care of compiling the resume and producing the final PDF. My old resume editing workflow is roughly -&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Update my resume (comprises of a couple of commits).&lt;/li&gt;
  &lt;li&gt;Tag the latest commit with an incrementing &lt;a href=&quot;https://semver.org/&quot;&gt;semantic version number&lt;/a&gt;. I used to maintain a major and minor release number, ex. v1.4.&lt;/li&gt;
  &lt;li&gt;Push the updates to GitHub.&lt;/li&gt;
  &lt;li&gt;Make a release on GitHub for the relevant tag and upload the a PDF version for that release.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;So why maintain a version number?&lt;/strong&gt; Simply put it helps me retrieve the exact copy of my resume that someone else has. And there is no need to store every PDF version of my resume.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;However semantic versioning has issues!&lt;/strong&gt; They are pretty useful in general, but they introduce quite a bit of overhead. My main dislike for them stems from the manual version increments that are necessary, esp. when doing just some minor updates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The alternative.&lt;/strong&gt; A rolling release with version numbers that correspond to the abbrev (or shortened) git commit SHA. The extra thing I add on top is the &lt;strong&gt;commit date&lt;/strong&gt;. This helps my human brain quickly identify the latest version. The &lt;strong&gt;build date&lt;/strong&gt; can also be used but it changes every time the resume gets recompiled. So my preference is the &lt;strong&gt;commit date&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefit.&lt;/strong&gt; Now every time someone has a question regarding my resume, I simply get the abbrev SHA version. Now both of us are looking at the exact same copy of the resume!&lt;/p&gt;

&lt;h2 id=&quot;my-setup&quot;&gt;My Setup&lt;/h2&gt;

&lt;h3 id=&quot;step-1---update-makefile&quot;&gt;Step 1 - Update Makefile&lt;/h3&gt;
&lt;p&gt;I have the following recipe in my Makefile.&lt;/p&gt;

&lt;div class=&quot;language-make highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# $ man git-log
#	%h:  abbreviated commit hash
#	%ad: author date (format respects --date= option)
&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.PHONY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;version&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;git log &lt;span class=&quot;nt&quot;&gt;--date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;short &lt;span class=&quot;nt&quot;&gt;--format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dt. %ad || ver. %h&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; 1
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Example output:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make version
dt. 2019-07-02 &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; ver. 53267a4
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;step-2---update-latex-source&quot;&gt;Step 2 - Update LaTeX source&lt;/h3&gt;

&lt;p&gt;Inside my LaTeX document, the following snippet embeds the output of the above command.&lt;/p&gt;

&lt;div class=&quot;language-latex highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;\input&lt;/span&gt;|&quot;make  --silent version&quot;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;step-3---tweak-latex-command-line-flags&quot;&gt;Step 3 - Tweak LaTeX command-line flags&lt;/h3&gt;

&lt;p&gt;Now for the above command to work, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--shell-escape&lt;/code&gt; flag needs to be passed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pdflatex&lt;/code&gt;. The compilation command looks like -&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# pdflatex&lt;/span&gt;
pdflatex &lt;span class=&quot;nt&quot;&gt;--shell-escape&lt;/span&gt; resume.tex

&lt;span class=&quot;c&quot;&gt;# xelatex&lt;/span&gt;
xelatex &lt;span class=&quot;nt&quot;&gt;--shell-escape&lt;/span&gt; resume.tex
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h3&gt;

&lt;p&gt;My entire Makefile:&lt;/p&gt;
&lt;div class=&quot;language-make highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;SRC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;resume.tex
&lt;span class=&quot;nv&quot;&gt;TARGET&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;resume.pdf

&lt;span class=&quot;nl&quot;&gt;$TARGET&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;*.tex *.cls&lt;/span&gt;
	xelatex &lt;span class=&quot;nt&quot;&gt;--shell-escape&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;${SRC}&lt;/span&gt;
	open &lt;span class=&quot;nv&quot;&gt;${TARGET}&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;.PHONY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;version&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;git log &lt;span class=&quot;nt&quot;&gt;--date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;short &lt;span class=&quot;nt&quot;&gt;--format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dt. %ad || ver. %h&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; 1

&lt;span class=&quot;nl&quot;&gt;.PHONY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;clean&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;clean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.aux &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.log &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.out &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.synctex.gz &lt;span class=&quot;nv&quot;&gt;${TARGET}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These are all the steps needed to get a rolling release. The final document looks like -&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/20190705-resume.png&quot; alt=&quot;Resume stamped with a release version&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One important point&lt;/strong&gt; is that any changes made to the resume need to be &lt;strong&gt;committed first&lt;/strong&gt;. Otherwise the resume will get marked with an older (and incorrect) version number.&lt;/p&gt;

&lt;h2 id=&quot;bonus&quot;&gt;Bonus&lt;/h2&gt;
&lt;p&gt;Alternatively, a TeX only approach looks like -&lt;/p&gt;

&lt;div class=&quot;language-latex highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;% Store the command output in a temporary file&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\immediate\write&lt;/span&gt;18&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;git log --date=short --format=&quot;dt. &lt;span class=&quot;c&quot;&gt;%ad || ver. %h&quot; -n 1 &amp;gt;gitcommit.tex}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;% Use the output&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;gitcommit.tex&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;% Remove the temporary file&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\immediate\write&lt;/span&gt;18&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;rm gitcommit.tex&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Fri, 05 Jul 2019 00:00:00 -0400</pubDate>
        <link>https://www.adityabasu.me/blog/2019/07/resume-with-git-sha-version/</link>
        <guid isPermaLink="true">https://www.adityabasu.me/blog/2019/07/resume-with-git-sha-version/</guid>
      </item>
    
      <item>
        <title>Quirks about PCI</title>
        <description>&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;tl;dr&lt;/strong&gt; Notes while working with PCI.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The 64-bit PCI registers are broken up as in to two 32-bit registers.
So,&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;REGISTER is represented as
	REGISTER_1
	REGISTER_1
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Fri, 28 Jun 2019 00:00:00 -0400</pubDate>
        <link>https://www.adityabasu.me/blog/2019/06/pci-quirks/</link>
        <guid isPermaLink="true">https://www.adityabasu.me/blog/2019/06/pci-quirks/</guid>
      </item>
    
      <item>
        <title>Generating favicon for personal blog</title>
        <description>&lt;p&gt;We will go through creating a favicon (an avatar), converting it to necessary image format(s), and finally configuring webpages to use it.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;First we need to create a favicon to add it to our website. For a personal blog I prefer using a personalized avatar. I used &lt;a href=&quot;https://avatarmaker.com/&quot;&gt;avatarmaker.com&lt;/a&gt; to create my avatar and downloaded the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;svg&lt;/code&gt; version to have a high quality image. Now the only bowsers that support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;svg&lt;/code&gt; favicons are Firefox and Safari. Hence it is a good idea to create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;png&lt;/code&gt; version as well for say Chrome users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You might also want to create an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ico&lt;/code&gt; version.&lt;/p&gt;

&lt;h2 id=&quot;generating-the-png-version&quot;&gt;Generating the png version&lt;/h2&gt;
&lt;p&gt;For this I used &lt;a href=&quot;https://github.com/shakiba/svgexport&quot;&gt;svgexport&lt;/a&gt;. This utility can convert &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.svg&lt;/code&gt; images to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.png&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.jpg&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.jpeg&lt;/code&gt; versions.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;First you will need to install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm&lt;/code&gt;. Go to &lt;a href=&quot;https://nodejs.org/en/download/&quot;&gt;this link&lt;/a&gt; to download and install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;To install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;svgexport&lt;/code&gt; on mac type the following in the terminal:
    &lt;div class=&quot;language-bash nolineno highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;npm &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--unsafe-perm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--allow-root&lt;/span&gt; svgexport
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Now to generate the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;png&lt;/code&gt; version of the favicon, use
    &lt;div class=&quot;language-bash nolineno highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;svgexport images/favicon.svg images/favicon.png 64x
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For me, the file sizes were:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;favicon.svg = 51 KB&lt;/li&gt;
  &lt;li&gt;favicon.png = 1.1 MB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I tried using &lt;em&gt;ImageMagick&lt;/em&gt; to convert the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.svg&lt;/code&gt; file to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.png&lt;/code&gt; file. However it gave me errors and failed converting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;svg&lt;/code&gt; file downloaded from &lt;a href=&quot;https://avatarmaker.com/&quot;&gt;avatarmaker.com&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;embedding-the-favicons-in-html--page&quot;&gt;Embedding the favicons in html  page&lt;/h2&gt;
&lt;p&gt;Next we need to add the following html tags to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;head&amp;gt;...&amp;lt;/head&amp;gt;&lt;/code&gt; section of all webpages:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;shortcut icon&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;image/svg&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/images/favicon.svg&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;shortcut icon&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;image/png&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/images/favicon.png&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now the favicon should be picked up by web browsers whenever your website gets loaded.&lt;/p&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;https://avatarmaker.com/&lt;/li&gt;
  &lt;li&gt;https://github.com/shakiba/svgexport&lt;/li&gt;
  &lt;li&gt;https://stackoverflow.com/questions/9853325/how-to-convert-a-svg-to-a-png-with-image-magick&lt;/li&gt;
  &lt;li&gt;https://www.w3.org/2005/10/howto-favicon&lt;/li&gt;
  &lt;li&gt;https://codex.wordpress.org/Creating_a_Favicon&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 21 Nov 2018 00:00:00 -0500</pubDate>
        <link>https://www.adityabasu.me/blog/2018/11/generating-favicon/</link>
        <guid isPermaLink="true">https://www.adityabasu.me/blog/2018/11/generating-favicon/</guid>
      </item>
    
      <item>
        <title>Managing multiple repositories using mr</title>
        <description>&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;tl;dr&lt;/strong&gt; Using the &lt;strong&gt;mr&lt;/strong&gt; tool, you can issue commands to multiple repositories in parallel. You can pull new changes, do simultaneous commits or just get the last commit log.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My typical day starts with updating a few code repositories. When dealing with a small number of repos, it’s not a problem to do a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull&lt;/code&gt; for each repo. But once you handle more than 4-5 repos, it’s worth automating the process.&lt;/p&gt;

&lt;p&gt;Also, at times when you forget to commit some work, it can be handy to run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git
status&lt;/code&gt; on all your repos and see which repos need attention.&lt;/p&gt;

&lt;p&gt;I recently came across a tool made by Joey: &lt;strong&gt;myrepos&lt;/strong&gt; (or &lt;strong&gt;mr&lt;/strong&gt;). The tool supports many types of repositories - git, mercurial, cvs, svn, etc.&lt;/p&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# Debian / Ubuntu (recent versions)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;mr

&lt;span class=&quot;c&quot;&gt;# Mac&lt;/span&gt;
brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;mr

&lt;span class=&quot;c&quot;&gt;# Others:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# - Just put the `mr` perl script in your `PATH` and it should work!&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;core-usage&quot;&gt;Core Usage&lt;/h2&gt;
&lt;p&gt;The tool looks for a file called &lt;strong&gt;.mrconfig&lt;/strong&gt; in the current directory. This is an &lt;strong&gt;ini&lt;/strong&gt; file which tracks all the repositories using relative paths, for example -&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# file: ~/.mrconfig
&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;[.homesick/repos/dotfiles]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;checkout&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;git clone 'git@github.com:mitthu/dotfiles.git' 'dotfiles'&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To start managing an existing repository (ex. &lt;strong&gt;handbook&lt;/strong&gt;), run -&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# handbook repo is located in ~/handbook&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mr register handbook
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The above updates the &lt;strong&gt;.mrconfig&lt;/strong&gt; to -&lt;/p&gt;
&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# file: ~/.mrconfig
&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;[.homesick/repos/dotfiles]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;checkout&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;git clone 'git@github.com:mitthu/dotfiles.git' 'dotfiles'&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[handbook]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;checkout&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;git clone 'git@github.com:mitthu/handbook.git' 'handbook'&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;action-git-checkout&quot;&gt;Action: git checkout&lt;/h3&gt;
&lt;p&gt;To checkout/clone the repositories in &lt;strong&gt;.mrconfig&lt;/strong&gt; (skips already cloned repositories), run -&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mr checkout
mr checkout: /Users/mitthu/.homesick/repos/dotfiles
Cloning into &lt;span class=&quot;s1&quot;&gt;'dotfiles'&lt;/span&gt;...
remote: Enumerating objects: 1406, &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
remote: Total 1406 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;delta 0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, reused 0 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;delta 0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, pack-reused 1406
Receiving objects: 100% &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1406/1406&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, 455.60 KiB | 3.21 MiB/s, &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
Resolving deltas: 100% &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;823/823&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;

mr checkout: /Users/mitthu/handbook
Cloning into &lt;span class=&quot;s1&quot;&gt;'handbook'&lt;/span&gt;...
remote: Enumerating objects: 32, &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
remote: Total 32 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;delta 0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, reused 0 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;delta 0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, pack-reused 32
Receiving objects: 100% &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;32/32&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, 4.75 KiB | 4.75 MiB/s, &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
Resolving deltas: 100% &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;14/14&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;

mr checkout: finished &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;2 ok&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;action-git-pull&quot;&gt;Action: git pull&lt;/h3&gt;
&lt;p&gt;Now to &lt;strong&gt;update&lt;/strong&gt; (i.e. do a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull&lt;/code&gt; on) all managed repos, run -&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# Update all managed repositories (sequential)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mr update
mr update: /Users/mitthu/.homesick/repos/dotfiles
Already up to date.

mr update: /Users/mitthu/handbook
Already up to date.

mr update: finished &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;2 ok&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Run `git pull` simultaneously, say on 8 repos at a time&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mr update &lt;span class=&quot;nt&quot;&gt;-j8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;action-git-status&quot;&gt;Action: git status&lt;/h3&gt;
&lt;p&gt;To find out any uncommited/unpushed changes, run -&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mr status
mr status: /home/mitthu/.homesick/repos/dotfiles
8c6f508 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD, master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; Add X automation script.

mr status: /home/mitthu/handbook

mr status: finished &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;2 ok&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;my-workflow&quot;&gt;My Workflow&lt;/h2&gt;
&lt;p&gt;I have mutiple &lt;strong&gt;.mrconfig&lt;/strong&gt;’s, but I do make sure not to have too many configs. Using too many configs, would defeat the very purpose of automation, as you will be doing &lt;strong&gt;mr update&lt;/strong&gt; in multiple directories.&lt;/p&gt;

&lt;p&gt;I have a directory called repos in my home directory -&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# Directory structure of ~/repos&lt;/span&gt;
~/repos
|-- following
|   |-- ansible-django
|   .... &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;all repos I follow&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; ....
|   &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; .mrconfig
|-- ops
|   |-- dotfiles_deploy
|   .... &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;my personal automation stuff&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; ....
|   &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; .mrconfig
&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; work
    |-- gitosis-admin
    .... &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;work related stuff&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; ...
    &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; .mrconfig
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Apart from the above, I also have an &lt;strong&gt;.mrconfig&lt;/strong&gt; in my home directory. In this config, I add all the repos which I use daily and all my current projects. So everyday, I just have to do an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mr update&lt;/code&gt; in my home folder.&lt;/p&gt;

&lt;p&gt;There are a few repos to which I do not have push permissions (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/repos/following/*&lt;/code&gt;). &lt;strong&gt;mr&lt;/strong&gt; will fail to push to such repos. It does not look very encouraging to see commands failing. To fix this, I override the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mr push&lt;/code&gt; command for those specific repos. So for example, if I don’t want to push to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;handbook&lt;/code&gt; repo, I will update my &lt;strong&gt;.mrconfig&lt;/strong&gt; as follows -&lt;/p&gt;
&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# file: ~/.mrconfig
&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;[handbook]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;checkout&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;git clone 'git@github.com:mitthu/handbook.git' 'handbook'&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;echo &quot;DO NOT PUSH&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The above would just run echo out “DO NOT PUSH” on an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mr push&lt;/code&gt; run. For example -&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mr push
mr push: /home/mitthu/handbook
DO NOT PUSH

mr push: finished &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1 ok&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;tips&quot;&gt;Tips&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Teach new commands to mr (or overrride existing commands) via the ‘DEFAULT’ section in &lt;strong&gt;.mrconfig&lt;/strong&gt;, for example -
    &lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nn&quot;&gt;[DEFAULT]&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Teach mr how to &quot;mr gc&quot; in git repos.
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;git_gc&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;git gc &quot;$@&quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Always fetch and rebase changes
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;git_update&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;git pull --rebase&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Use cron and mr to keep forked repositories up to date with upstream.&lt;/li&gt;
  &lt;li&gt;Use cron, mr and pushover to send notifications about uncommitted/unpushed changes at 5:00 pm.&lt;/li&gt;
  &lt;li&gt;Doc: man page of mr (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man mr&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Doc: &lt;a href=&quot;http://myrepos.branchable.com/&quot;&gt;Homepage - mr&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Last updated on&lt;/strong&gt;: June 18, 2019&lt;/p&gt;
</description>
        <pubDate>Thu, 02 Apr 2015 00:00:00 -0400</pubDate>
        <link>https://www.adityabasu.me/blog/2015/04/mr-tool/</link>
        <guid isPermaLink="true">https://www.adityabasu.me/blog/2015/04/mr-tool/</guid>
      </item>
    
  </channel>
</rss>