<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="et">
	<id>http://courses.cs.taltech.ee/w/index.php?action=history&amp;feed=atom&amp;title=Exploring_Debugger_%28ITS8020%29</id>
	<title>Exploring Debugger (ITS8020) - Redigeerimiste ajalugu</title>
	<link rel="self" type="application/atom+xml" href="http://courses.cs.taltech.ee/w/index.php?action=history&amp;feed=atom&amp;title=Exploring_Debugger_%28ITS8020%29"/>
	<link rel="alternate" type="text/html" href="http://courses.cs.taltech.ee/w/index.php?title=Exploring_Debugger_(ITS8020)&amp;action=history"/>
	<updated>2026-05-21T23:38:12Z</updated>
	<subtitle>Selle lehekülje redigeerimiste ajalugu</subtitle>
	<generator>MediaWiki 1.35.9</generator>
	<entry>
		<id>http://courses.cs.taltech.ee/w/index.php?title=Exploring_Debugger_(ITS8020)&amp;diff=7087&amp;oldid=prev</id>
		<title>Irve: Uus lehekülg: &#039;This lab will show how a debugger could be used to explore a running program. We also try to use objdump program for disassembling.  == Compilation ==  Since the compiler by defa...&#039;</title>
		<link rel="alternate" type="text/html" href="http://courses.cs.taltech.ee/w/index.php?title=Exploring_Debugger_(ITS8020)&amp;diff=7087&amp;oldid=prev"/>
		<updated>2018-09-21T08:37:19Z</updated>

		<summary type="html">&lt;p&gt;Uus lehekülg: &amp;#039;This lab will show how a debugger could be used to explore a running program. We also try to use objdump program for disassembling.  == Compilation ==  Since the compiler by defa...&amp;#039;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Uus lehekülg&lt;/b&gt;&lt;/p&gt;&lt;div&gt;This lab will show how a debugger could be used to explore a running program. We also try to use objdump program for disassembling.&lt;br /&gt;
&lt;br /&gt;
== Compilation ==&lt;br /&gt;
&lt;br /&gt;
Since the compiler by default wants to generate the smallest possible executable (as far as effortless compilation is concerned), it removes data about function names from the file (it&amp;#039;s called the [http://en.wikipedia.org/wiki/Symbol_table symbol table]). To prevent stripping the symbol table from the file, use -g for compilation.&lt;br /&gt;
&lt;br /&gt;
  gcc -g filename.c -o filename&lt;br /&gt;
&lt;br /&gt;
Thus the need to create makefile for easier compilation.&lt;br /&gt;
&lt;br /&gt;
Why the symbol table is needed? Debugger uses it to provide valuable additional data while debugging. Note that in the world of embedded real-time systems, any modifications to the executable, even the -g or optimizations might affect the performance characteristics.&lt;br /&gt;
&lt;br /&gt;
In short: while developing a program, use the -g option for compilation.&lt;br /&gt;
&lt;br /&gt;
== Debugger ==&lt;br /&gt;
&lt;br /&gt;
We use command-line debugger gdb - GNU DeBugger. Note that it does have graphical front-end, named ddd, but will take effort to get it running properly over X under windows. GDB is powerful and suprisingly easy to use.&lt;br /&gt;
&lt;br /&gt;
* [http://sources.redhat.com/gdb/current/onlinedocs/gdb.html GDB manual]&lt;br /&gt;
* You can type &amp;quot;help&amp;quot; or &amp;quot;help &amp;#039;&amp;#039;command&amp;#039;&amp;#039;&amp;quot; in gdb for reminder of commands and their syntax. There are many, but you will probably only use a small subset of them anyway.&lt;br /&gt;
&lt;br /&gt;
To run it with your compiled program, type:&lt;br /&gt;
 gdb programname&lt;br /&gt;
&lt;br /&gt;
It will show the prompt (gdb) and nothing will happen. The program is waiting for you to set up breakpoints/watches and the run command.&lt;br /&gt;
&lt;br /&gt;
To exit gdb, type:&lt;br /&gt;
 quit&lt;br /&gt;
&lt;br /&gt;
== Running the program ==&lt;br /&gt;
&lt;br /&gt;
To run a program in gdb, use the command:&lt;br /&gt;
 run&lt;br /&gt;
&lt;br /&gt;
The program will run until you interrupt it with CTRL+C (in which case the program will be stopped wherever it was and you can examine wherever you are), the program finishes or crashes. Crashes are most interesting, since you get to see where the crash happens and examine the stack.&lt;br /&gt;
&lt;br /&gt;
You can also specify the arguments after the &amp;quot;run&amp;quot; command.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Task&amp;#039;&amp;#039;&amp;#039;: Run a program withing gdb, then run a crashing program within gdb. Observe the results.&lt;br /&gt;
&lt;br /&gt;
== Breakpoints ==&lt;br /&gt;
&lt;br /&gt;
To stop your program a certain point, you can add breakpoints to the program before running it. You can set them to functions, line numbers or even to specific lines on spefific files. If you need, you can even stop when your program tries to run a specific instruction on some memory address.&lt;br /&gt;
&lt;br /&gt;
* break &amp;#039;&amp;#039;function&amp;#039;&amp;#039;&lt;br /&gt;
* break &amp;#039;&amp;#039;linenumber&amp;#039;&amp;#039;&lt;br /&gt;
* break &amp;#039;&amp;#039;file:function&amp;#039;&amp;#039;&lt;br /&gt;
* break &amp;#039;&amp;#039;file:linenumber&amp;#039;&amp;#039;&lt;br /&gt;
* break *&amp;#039;&amp;#039;address&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To see the breakpoints, type &lt;br /&gt;
 info break&lt;br /&gt;
&lt;br /&gt;
If you make mistakes, delete them (you get numbers with &amp;quot;info break&amp;quot;):&lt;br /&gt;
 delete &amp;#039;&amp;#039;breakpoint number&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Task&amp;#039;&amp;#039;&amp;#039;: Add a breakpoint, then run until it arrives.&lt;br /&gt;
&lt;br /&gt;
== Examining the program ==&lt;br /&gt;
&lt;br /&gt;
You should now have a stopped program somewhere. Debugger is excellent for inspecting memory: variables and stack can be read.&lt;br /&gt;
&lt;br /&gt;
Most basic program for content is print:&lt;br /&gt;
 print &amp;#039;&amp;#039;variablename&amp;#039;&amp;#039;&lt;br /&gt;
 print array[2]&lt;br /&gt;
 print $eax&lt;br /&gt;
&lt;br /&gt;
You can also dereference pointers with *. Print is so common, that it can be shortened to just &amp;#039;p&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
 p $eax&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Tips:&amp;#039;&amp;#039;&amp;#039; You can eXamine memory with the x command. To see all the registers, write &amp;#039;info registers&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Task&amp;#039;&amp;#039;&amp;#039;: Examine the variables in your program. Add some struct to your program and try whether and how it can be seen.&lt;br /&gt;
&lt;br /&gt;
== Changing the variables ==&lt;br /&gt;
&lt;br /&gt;
Changing variables is extremely easy. You can just use &amp;#039;print&amp;#039; command with = .&lt;br /&gt;
&lt;br /&gt;
 print x = 888&lt;br /&gt;
 p c = &amp;#039;\0&amp;#039;&lt;br /&gt;
&lt;br /&gt;
If you don&amp;#039;t want to see the variable, you can also use the &amp;#039;set&amp;#039; command:&lt;br /&gt;
 set var x = 99&lt;br /&gt;
 set var c = EOF&lt;br /&gt;
&lt;br /&gt;
== Call stack ==&lt;br /&gt;
&lt;br /&gt;
You can examine the call stack with backtrace command: it&amp;#039;s human readable and you get the line numbers and function names for each stack frame:&lt;br /&gt;
 backtrace&lt;br /&gt;
&lt;br /&gt;
For just getting the current frame information, type:&lt;br /&gt;
 frame&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Task&amp;#039;&amp;#039;&amp;#039; Find a program with segmentation fault (or create one). Run it until it crashes, then examine where it did so.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Tip:&amp;#039;&amp;#039;&amp;#039; To examine local variables of some other frame, you can use &amp;#039;up&amp;#039; command to move upwards in stack frames, then use &amp;#039;frame&amp;#039;. Try it.&lt;br /&gt;
&lt;br /&gt;
== Stepping ==&lt;br /&gt;
&lt;br /&gt;
You can also make the stopped program to run in small increments. The commands for that are &amp;#039;next&amp;#039; and &amp;#039;step&amp;#039;. &lt;br /&gt;
* next - execute the next line of code.&lt;br /&gt;
* step - execute the next line of code while &amp;#039;&amp;#039;stepping&amp;#039;&amp;#039; into any called functions&lt;br /&gt;
* continue - continue running normally&lt;br /&gt;
&lt;br /&gt;
If you want to see the line where you are:&lt;br /&gt;
 list&lt;br /&gt;
&lt;br /&gt;
You can add a line number to list, to see code in particurlar location.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Tip&amp;#039;&amp;#039;: you can also run by only one instruction: &amp;#039;stepi&amp;#039; and &amp;#039;nexti&amp;#039; commands do this.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Task&amp;#039;&amp;#039;&amp;#039;: Run a program with breakpoints, try to understand the difference between &amp;#039;step&amp;#039; and &amp;#039;next&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
== Watchpoint ==&lt;br /&gt;
&lt;br /&gt;
You can stop the program whenever some variable changes. Such places are called watchpoints:&lt;br /&gt;
 watch &amp;#039;&amp;#039;variablename&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Task&amp;#039;&amp;#039;&amp;#039;: Add a watchpoint for some variable, see how it behaves. Use &amp;#039;continue&amp;#039; to keep running.&lt;br /&gt;
&lt;br /&gt;
== Disassembling ==&lt;br /&gt;
&lt;br /&gt;
You can turn the numbers that are fed into the processor into readable assembly:&lt;br /&gt;
 disas&lt;br /&gt;
 disas &amp;#039;&amp;#039;functionname&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Task&amp;#039;&amp;#039;&amp;#039;: Try to disassemble some simple arithmetic function. Observe how it manages the stack before starting the computation and how it prepares it before returning.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can also disassemble with the &amp;#039;objdump&amp;#039; program.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Task&amp;#039;&amp;#039;&amp;#039;: Disassemble a program: how does the result differ from gdb&amp;#039;s disas? Also, test other options for objdump.&lt;br /&gt;
&lt;br /&gt;
== Morale ==&lt;br /&gt;
&lt;br /&gt;
Once you understand how the stack is managed, assembler language starts to make sense. You can disassemble any compiled program, but they are messy without the source code and symbol table. &lt;br /&gt;
&lt;br /&gt;
You could try to write a program which runs two functions, the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; one quits, the &amp;#039;&amp;#039;second&amp;#039;&amp;#039; one does something interesting. You could then change the &amp;quot;main&amp;quot; function so that its &amp;#039;call&amp;#039; instruction would call the &amp;#039;&amp;#039;second&amp;#039;&amp;#039; function instead of the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; without looking at the source code.  Alternatively (bonus task) one could find a &amp;#039;jmp&amp;#039; instruction and change its address to jump just before the second function. Simple replacement of 4 bytes can make a lot of difference.&lt;br /&gt;
&lt;br /&gt;
I hope that the process was enlightening. [https://www.youtube.com/watch?v=Skl71urqKu0 Use it for good, not evil].&lt;/div&gt;</summary>
		<author><name>Irve</name></author>
	</entry>
</feed>