<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Benjamin Fu</title>
    <description>The latest articles on Forem by Benjamin Fu (@benjamin_fu_172185a01088f).</description>
    <link>https://forem.com/benjamin_fu_172185a01088f</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3900022%2F81eec7bf-d058-4be3-b145-a4926973fa88.png</url>
      <title>Forem: Benjamin Fu</title>
      <link>https://forem.com/benjamin_fu_172185a01088f</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/benjamin_fu_172185a01088f"/>
    <language>en</language>
    <item>
      <title>Can high school students develop a debugger? Lavender dbg is my answer</title>
      <dc:creator>Benjamin Fu</dc:creator>
      <pubDate>Tue, 05 May 2026 04:54:16 +0000</pubDate>
      <link>https://forem.com/benjamin_fu_172185a01088f/lavender-dbg-56fp</link>
      <guid>https://forem.com/benjamin_fu_172185a01088f/lavender-dbg-56fp</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3apb562xyk2izqume701.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3apb562xyk2izqume701.png" alt="Lavender Cover" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Environment Requirements&lt;/li&gt;
&lt;li&gt;Core Features&lt;/li&gt;
&lt;li&gt;Core Design and Code Analysis&lt;/li&gt;
&lt;li&gt;Actual Execution Demo&lt;/li&gt;
&lt;li&gt;Architecture Overview&lt;/li&gt;
&lt;li&gt;How You Can Expand&lt;/li&gt;
&lt;li&gt;Future Plans &amp;amp; Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;What is this&lt;/strong&gt;&lt;br&gt;
Can high school students develop a debugger?&lt;br&gt;
Lavender dbg is my answer.&lt;/p&gt;

&lt;p&gt;It is a basic debugger, running on Linux and implemented in C++, aiming to create a debugger that is easy to read and expand.&lt;/p&gt;

&lt;p&gt;In addition, Lavender's main function is to help users analyze the logic behind the program, including maps output, ELF file parsing, and assembly output. For details, please refer to: &lt;strong&gt;Core Features&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Link :&lt;/strong&gt; &lt;a href="https://github.com/Benjamin-fuu-u/lavender-dbg" rel="noopener noreferrer"&gt;https://github.com/Benjamin-fuu-u/lavender-dbg&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can also see it on notion :&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.notion.so/Lavender-dbg-34c01dbb4304802e9013d2ad249e60e2?pvs=21" rel="noopener noreferrer"&gt;https://delirious-rise-a64.notion.site/Lavender-dbg-34c01dbb4304802e9013d2ad249e60e2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Chinese (繁體中文) notion page&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.notion.so/Lavender-dbg-34901dbb430480f1a237c7ad881f9cbe?pvs=21" rel="noopener noreferrer"&gt;https://delirious-rise-a64.notion.site/Lavender-dbg-34901dbb430480f1a237c7ad881f9cbe&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This project was assisted by AI during production, and the author is not a native English speaker, I ask AI to assist in translation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Suitable for&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Beginners in system programming&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users who want to understand debugger principles&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;People curious about underlying principles&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Not suitable for&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Users who need professional features&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Penetration testing or CTF competition environments&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Highlights&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code is readable and easy to understand, clearly demonstrating the underlying principles of the debugger&lt;/li&gt;
&lt;li&gt;Clear architecture, easy to expand, can add or remove features according to your needs&lt;/li&gt;
&lt;li&gt;Lays the foundation for system programming&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Environment Requirements
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Environment Requirements&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Operating System &lt;code&gt;Linux&lt;/code&gt; (recommended &lt;code&gt;Linux MINT&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Compilation tools &lt;code&gt;g++(C++17)&lt;/code&gt;, &lt;code&gt;gcc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Build tools &lt;code&gt;CMake 3.16+&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;External packages &lt;code&gt;capstone&lt;/code&gt;, &lt;code&gt;objdump&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;File Setup&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lavender dbg/
├── CMakeLists.txt
└── src/
    ├── main.cpp
    ├── target.c
    └── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please set up the files as shown above and install the following tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installation Commands&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;g++ gcc
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;cmake            &lt;span class="c"&gt;#cmake&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;binutils         &lt;span class="c"&gt;#objdump&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;libcapstone-dev  &lt;span class="c"&gt;#capstone&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create a &lt;code&gt;build&lt;/code&gt; folder under lavender dbg&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;build
&lt;span class="nb"&gt;cd &lt;/span&gt;build
cmake ..  &lt;span class="c"&gt;# First time must configure CMake, cmake is in the parent directory&lt;/span&gt;
make      &lt;span class="c"&gt;#compile program&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In the future, if modifying CMake, enter &lt;code&gt;cmake&lt;/code&gt;. If changing program content, enter &lt;code&gt;make&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./lavender ./target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Core Features
&lt;/h1&gt;

&lt;p&gt;Lavender dbg is a debugger used to help users understand the underlying principles behind programs, and can perform the following functions:&lt;br&gt;
&lt;strong&gt;1. Maps output&lt;/strong&gt;&lt;br&gt;
At the beginning of the program, it prints the &lt;code&gt;maps&lt;/code&gt; of the child process just started; you can also modify the settings to view during program runtime.&lt;br&gt;
&lt;strong&gt;2. Function address output&lt;/strong&gt;&lt;br&gt;
The program automatically prints all internal, external, and system functions when the child process starts, but does not include dynamic link libraries like &lt;code&gt;libc.so&lt;/code&gt;.&lt;br&gt;
&lt;strong&gt;3. CLI output; this program provides two functions: setting breakpoints and single-step&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;breakpoint&lt;/strong&gt; &lt;br&gt;
Can use hexadecimal or function names; after setting a breakpoint, it automatically goes to the breakpoint and displays &lt;code&gt;stack&lt;/code&gt;, &lt;code&gt;register&lt;/code&gt;, and the next five lines of assembly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Single-step execution&lt;/strong&gt;&lt;br&gt;
Can customize the number of steps, and automatically skips when encountering &lt;code&gt;call&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can refer to the actual execution demo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can also write your own custom functions&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Actual Execution Demo
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Maps Output&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcsa3fzgmuqrwu53ry4dt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcsa3fzgmuqrwu53ry4dt.png" alt="Maps Output" width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the image above, you can see the maps, stack, vdso, code, and other sections at the beginning of program startup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section Types&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;code&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Mostly code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;stack&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;vdso&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shared block, providing commonly used modules directly to the program&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;heap&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Heap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DATA&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Mostly storing data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;libc.so&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Standard C library&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Breakpoint Output&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsmu9silc268jww85ipqe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsmu9silc268jww85ipqe.png" alt="Breakpoint Main" width="800" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the information displayed by Lavender when setting a breakpoint at main, including the next five lines of code (Current and next five instruction), registers, stack, and other information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Register Types&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Register&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Register&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RIP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Current instruction position&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;RDI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Register 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RSP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Stack top&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;RSI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Register 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RBP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Stack bottom&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;RDX&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Register 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RAX&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Return value&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ZF&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Judgment flag&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Single Step Output&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjl15p37xit3vk3tojqoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjl15p37xit3vk3tojqoa.png" alt="Call Puts Print Hello" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the image above, you can see the machine code line by line; each line of machine code displays registers, with changes highlighted. If it is a call, it displays the called function name (but if it is libc etc., it will not find it, will not display function name).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Also Supports Child Process Input&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66tarb50cyj7lad61too.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66tarb50cyj7lad61too.png" alt="Lavender Input Name" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the situation when the child process handled by Lavender has input; you can see inputting the name "lavender".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9i8y8o4wt7lgbch8ppas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9i8y8o4wt7lgbch8ppas.png" alt="Lavender Output Hello, Name" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see outputting the name "lavender".&lt;/p&gt;
&lt;h1&gt;
  
  
  Core Design and Code Analysis
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Starting Child Process&lt;/strong&gt;&lt;br&gt;
The debugger and target program are two independent processes. Therefore, I use &lt;code&gt;fork()&lt;/code&gt; to copy the child process, then use &lt;code&gt;execv()&lt;/code&gt; to replace the child process with the target program, and finally let the child process call &lt;code&gt;PTRACE_TRACEME&lt;/code&gt; to request the kernel to be traced by the parent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;pid_t&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// if pid = -1 , error occured&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;cerr&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Fork error"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;strerror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// pid is 0 , this is child program&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ask system to be traced by parents&lt;/span&gt;
    &lt;span class="n"&gt;ptrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PTRACE_TRACEME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;const_cast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_path&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// fork into target_path state , if success , code below will not run&lt;/span&gt;
    &lt;span class="c1"&gt;// target path is for kernel , args for child program&lt;/span&gt;
    &lt;span class="n"&gt;execv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;cerr&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Errno : "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;strerror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Breakpoint Recovery Design&lt;/strong&gt;&lt;br&gt;
When setting a breakpoint, I replace the first &lt;code&gt;byte&lt;/code&gt; of the target address with &lt;code&gt;0xcc&lt;/code&gt;, then use &lt;code&gt;PTRACE_CONT&lt;/code&gt; to let the program run at full speed; when the CPU hits &lt;code&gt;0xcc&lt;/code&gt;, it automatically pauses and triggers &lt;code&gt;SIGTRAP&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After the breakpoint is triggered, three things need to be done:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write back the backed-up machine code from when the breakpoint was set&lt;/li&gt;
&lt;li&gt;Pull back the &lt;code&gt;RIP&lt;/code&gt; (when the CPU executes to &lt;code&gt;0xcc&lt;/code&gt;, &lt;code&gt;RIP&lt;/code&gt; has already pointed to the next instruction)&lt;/li&gt;
&lt;li&gt;Write back the current &lt;code&gt;registers&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Run until hit 0xcc&lt;/span&gt;
&lt;span class="n"&gt;ptrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PTRACE_CONT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Wait for hit 0xcc&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;waitpid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WIFSIGNALED&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"[Debugger] : Program exited with code "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;WTERMSIG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Write back the backup&lt;/span&gt;
&lt;span class="n"&gt;ptrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PTRACE_POKETEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_bp_addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_bp_backup&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Get current RIP&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;user_regs_struct&lt;/span&gt; &lt;span class="n"&gt;regs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;ptrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PTRACE_GETREGS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;regs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// RIP pointer already jumped to next instruction, need to pull back and write back regs&lt;/span&gt;
&lt;span class="n"&gt;regs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m_bp_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;ptrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PTRACE_SETREGS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;regs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BOLD_CORAL_RED&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"[Debugger] Hit breakpoint at 0x"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;hex&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;m_bp_addr&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;dec&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RESET&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;endl&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Smart Stepover, Automatically Skip on Call&lt;/strong&gt;&lt;br&gt;
In the stepover function design, it automatically skips encountered &lt;code&gt;call&lt;/code&gt; functions and displays where to jump next. Therefore, I passed in the symbols storing each function address (obtained by &lt;code&gt;symbols.cpp&lt;/code&gt;), then, due to ASLR randomization, the symbols store only offsets, and must add &lt;code&gt;base_address&lt;/code&gt; to get the real address of the function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We need to do the following four things:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Determine if the instruction is &lt;code&gt;call(X86_INS_CALL)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If it is a call, set a breakpoint at the next instruction of this instruction (after jumping, &lt;code&gt;return&lt;/code&gt; will come back here)&lt;/li&gt;
&lt;li&gt;Check if there is a function name corresponding to the address in symbols &lt;strong&gt;(if it is &lt;code&gt;libc&lt;/code&gt; etc., it will show not found)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Run to the breakpoint
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isCall&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;insn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;X86_INS_CALL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Place to return after call&lt;/span&gt;
&lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;nextaddr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rip&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;insn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;call_target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mh"&gt;0xE8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;call_target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rip&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;cs_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;insn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;cs_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isCall&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// First find from symbol, is there jump target function name, if in libc will not find&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;base_address&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;call_target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BOLD_LIGHT_RED&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Call -&amp;gt; [ "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;" ]"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// If call, set breakpoint at end of call&lt;/span&gt;
    &lt;span class="n"&gt;set_breakpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nextaddr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;run_to_breakpoint&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;
  ptrace — common requests
  &lt;br&gt;
Signature: &lt;code&gt;ptrace(request, pid, addr, data)&lt;/code&gt; — if it is oneself, pid can be ignored (fill in 0)

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Request&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PTRACE_TRACEME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Request to be traced by the kernel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PTRACE_CONT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Execute until encountering a signal (SIGNAL)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PTRACE_PEEKTEXT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PTRACE_GETREGS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Obtain registers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PTRACE_SETREGS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Modify registers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PTRACE_SINGLESTEP&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Single-step execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PTRACE_KILL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Force end child process&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;/p&gt;

&lt;p&gt;
  capstone — commands
  &lt;br&gt;
| Function | Description |&lt;br&gt;
|---|---|&lt;br&gt;
| &lt;code&gt;cs_open(CS_ARCH_X86, CS_MODE_64, &amp;amp;handle)&lt;/code&gt; | Initialize capstone, specify X86-64 instructions |&lt;br&gt;
| &lt;code&gt;cs_disasm(handle, buf, sizeof(buf), rip, 1, &amp;amp;insn)&lt;/code&gt; | Convert machine code (existing in &lt;code&gt;buf&lt;/code&gt;) to assembly language |&lt;br&gt;
| &lt;code&gt;cs_free(insn, count)&lt;/code&gt; | Release memory allocated for &lt;code&gt;insn&lt;/code&gt; |&lt;br&gt;
| &lt;code&gt;cs_close(&amp;amp;handle)&lt;/code&gt; | Close and release capstone handle |&lt;br&gt;
| &lt;code&gt;X86_INS_CALL&lt;/code&gt; | Used to determine if the current is a &lt;code&gt;call&lt;/code&gt; instruction |&lt;br&gt;


&lt;/p&gt;

&lt;p&gt;
  Signal control (waitpid)
  &lt;br&gt;
| Macro | Description |&lt;br&gt;
|---|---|&lt;br&gt;
| &lt;code&gt;WIFSTOPPED(status)&lt;/code&gt; | Used to confirm if the child process entered pause without receiving a signal |&lt;br&gt;
| &lt;code&gt;WIFSIGNALED(status)&lt;/code&gt; | Used to confirm if the child process ended by signal |&lt;br&gt;
| &lt;code&gt;WTERMSIG(status)&lt;/code&gt; | Which signal ended, often paired with &lt;code&gt;WIFSIGNALED(status)&lt;/code&gt; |&lt;br&gt;
| &lt;code&gt;WIFEXITED(status)&lt;/code&gt; | Normal exit |&lt;br&gt;


&lt;/p&gt;

&lt;p&gt;
  Printed maps fields
  &lt;br&gt;
| Field | Description |&lt;br&gt;
|---|---|&lt;br&gt;
| &lt;code&gt;start_address&lt;/code&gt; | Start address |&lt;br&gt;
| &lt;code&gt;end_address&lt;/code&gt; | End address |&lt;br&gt;
| &lt;code&gt;permissions&lt;/code&gt; | Permissions |&lt;br&gt;
| &lt;code&gt;offset&lt;/code&gt; | Offset |&lt;br&gt;
| &lt;code&gt;pathname&lt;/code&gt; | Path |&lt;br&gt;


&lt;/p&gt;

&lt;p&gt;
  objdump commands
  &lt;br&gt;
| Command | Description |&lt;br&gt;
|---|---|&lt;br&gt;
| &lt;code&gt;objdump -t -- &amp;lt;path&amp;gt; 2&amp;gt;/dev/null&lt;/code&gt; | Grab &lt;code&gt;symbol&lt;/code&gt; in &lt;code&gt;.text&lt;/code&gt; |&lt;br&gt;
| &lt;code&gt;objdump -d -- &amp;lt;path&amp;gt; 2&amp;gt;/dev/null&lt;/code&gt; | Grab &lt;code&gt;@plt&lt;/code&gt; external functions |&lt;br&gt;


&lt;/p&gt;

&lt;p&gt;
  Important included header files
  &lt;br&gt;
&lt;strong&gt;Standard Library&lt;/strong&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Header&lt;/th&gt;
&lt;th&gt;Provides&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;iostream&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;cout&lt;/code&gt;, &lt;code&gt;cerr&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;iomanip&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;setw&lt;/code&gt; field control, &lt;code&gt;setfill&lt;/code&gt;, &lt;code&gt;hex&lt;/code&gt; hexadecimal, &lt;code&gt;dec&lt;/code&gt; decimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;cstdlib&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;exit()&lt;/code&gt; end program&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;cerrno&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;errno&lt;/code&gt; error code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;cstring&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;strerror&lt;/code&gt; translate &lt;code&gt;error&lt;/code&gt;, &lt;code&gt;memcpy&lt;/code&gt; content copy, &lt;code&gt;strstr&lt;/code&gt; find string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;vector&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vector&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;string&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;sstream&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;istringstream&lt;/code&gt;, &lt;code&gt;stringstream&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;fstream&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;file stream&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;cstdint&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uint64_t&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;cstdio&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;FILE*&lt;/code&gt;, &lt;code&gt;popen&lt;/code&gt; create pipe, &lt;code&gt;pclose&lt;/code&gt; close pipe, &lt;code&gt;fgets&lt;/code&gt; read string, reads limited length, can avoid buffer overflow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;algorithm&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;min&lt;/code&gt;, &lt;code&gt;sort()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;stdio.h&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;printf&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;System Call Related Libraries&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Header&lt;/th&gt;
&lt;th&gt;Provides&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;unistd.h&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;fork()&lt;/code&gt; copy program &lt;code&gt;execv()&lt;/code&gt; replace with child program&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;sys/types.h&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pid_t&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;sys/wait.h&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;waitpid&lt;/code&gt;, &lt;code&gt;WIF&lt;/code&gt; related macros&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;sys/ptrace.h&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ptrace&lt;/code&gt; related&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;sys/user.h&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;user_regs_struct&lt;/code&gt; read registers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Third-party Packages&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Header&lt;/th&gt;
&lt;th&gt;Provides&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;capstone/capstone.h&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;capstone&lt;/code&gt; disassemble&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;/p&gt;

&lt;h1&gt;
  
  
  Architecture Overview
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Project Architecture Diagram&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lavender-dbg/
├── CMakeLists.txt
└── src/
    ├── main.cpp             # Module integration and CLI
    ├── target.c             # Target program in C
    ├── common/
    │   └── color.h          # Output color definitions
    ├── debugger/            # Debugger module
    │   ├── debugger.cpp
    │   └── debugger.h
    ├── memory/              # /proc/maps reading
    │   ├── memory.cpp
    │   └── memory.h
    ├── process/             # Subprocess launching and control
    │   ├── process.cpp
    │   └── process.h
    └── symbols/             # ELF symbol parsing
        ├── symbols.cpp
        └── symbols.h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Main Program Execution Flow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Program Startup&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User provides the debugged program name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;target.c&lt;/code&gt; is compiled along with the build as the default debug target&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Child Process Creation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parent Process (lavender)
└─ fork()
     ├─ Child Process → execv (CMake automatically compiles target.c as the default debug target)
     │       + PTRACE_TRACEME  ← Requests the kernel to be traced by the parent
     └─ Parent Process → Waits for and controls the child process
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Reading Memory Mapping&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read &lt;code&gt;/proc/[PID]/maps&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Obtain &lt;code&gt;maps&lt;/code&gt; and &lt;code&gt;base_address&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;ELF File Parsing&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use &lt;code&gt;objdump&lt;/code&gt; to parse &lt;code&gt;ELF&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;Obtain function offsets&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;CLI Interactive Output&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;breakpoint&lt;/code&gt; After setting breakpoint, immediately executes to the breakpoint&lt;/li&gt;
&lt;li&gt;Executes line by line; if encountering &lt;code&gt;call&lt;/code&gt;, automatically queries the symbol table, looks up the jump function name, and sets breakpoint at the return location&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Program End&lt;/strong&gt;&lt;br&gt;
After child process or user exits CLI, read the report left by child process, ensure to end child process, then end parent process&lt;/p&gt;

&lt;h1&gt;
  
  
  How You Can Expand
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Current Limitations of This Project&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cannot directly modify the memory content of the target process&lt;/li&gt;
&lt;li&gt;Parent program currently shares the same terminal with child process; if using &lt;code&gt;step&lt;/code&gt; to enter input function, may cause abnormality&lt;/li&gt;
&lt;li&gt;Uses parent program to start target child process; cannot &lt;code&gt;attach&lt;/code&gt; to any process&lt;/li&gt;
&lt;li&gt;May have some functions missing or unstable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How to Expand&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Modify child process memory content&lt;/strong&gt;
Lavender currently can only read; can add &lt;code&gt;PTRACE_POKETEXT&lt;/code&gt; to change memory&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attach to any program&lt;/strong&gt;
Lavender currently uses fork(); you can change to &lt;code&gt;PTRACE_ATTACH&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom CLI interface&lt;/strong&gt;
Commands in main.cpp are easy to replace and change&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terminal separation&lt;/strong&gt;
Lavender currently has child and parent sharing the same terminal; you can use &lt;code&gt;dup2&lt;/code&gt; to separate&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Future Plans &amp;amp; Conclusion
&lt;/h1&gt;

&lt;p&gt;Lavender dbg is a debugger built in a simple and understandable way; piecing together the entire debugger by hand, the understanding of the underlying logic can be said to be very profound. In the future when using &lt;code&gt;dbg&lt;/code&gt;, I think there will be more insights.&lt;/p&gt;

&lt;p&gt;During the development process, I used AI to help query syntax, debug, and think about the overall program architecture. But I understand the meaning of every line of code, and believe that collaborating with AI will be the trend in the future.&lt;/p&gt;

&lt;p&gt;I hope everyone can learn some underlying logic from this project, or become interested in underlying logic because of it, or even assemble a dbg by hand—of course, using AI to develop is also a good choice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Link:&lt;/strong&gt;&lt;a href="https://github.com/Benjamin-fuu-u/lavender-dbg" rel="noopener noreferrer"&gt;https://github.com/Benjamin-fuu-u/lavender-dbg&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you like my project or my ideas, you can give me a star; that would be a great encouragement to me!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>linux</category>
      <category>cpp</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
