mirror of
https://github.com/Hizenberg469/GDB-tutorial.git
synced 2026-04-20 06:12:23 +03:00
238 lines
6.3 KiB
Plaintext
238 lines
6.3 KiB
Plaintext
DEBUGGING TECHNIQUES:
|
|
---------------------
|
|
|
|
|
|
-> Delta Debugging:
|
|
++++++++++++++++
|
|
|
|
|
|
It is a technique like binary search, where we can decrease the section
|
|
under analysis to find bugs.
|
|
|
|
Like, we can use multiple breakpoints to the program and see
|
|
where the program faces issue and when it faces. It could
|
|
face the issue before some breakpoint could be reached or
|
|
after some breakpoints are encountered.
|
|
This way we can reduce our search space and section of analysis.
|
|
|
|
|
|
-> Assertion:
|
|
++++++++++
|
|
|
|
|
|
assert(): It check if the assumption which is passed
|
|
as an argument is true. If it isn't, the
|
|
program will Abort and core dumped.
|
|
|
|
This is for runtime check and the program
|
|
is part of C library.
|
|
|
|
To use it we need #include <cassert> statement
|
|
in C++ program.
|
|
|
|
static_assert(): It check the assumption at compile time
|
|
and throw compilation error if the
|
|
assertion fails.
|
|
|
|
|
|
This is helpful where we can evaluate
|
|
variable as constant expression using
|
|
constexpr keywords, which could help
|
|
in static assertion failure.
|
|
|
|
|
|
-> Investigating Code by Calling functions within GDB:
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
* We can call a function from GDB when haven't reached
|
|
the point where we execute the function.
|
|
|
|
We can do function call from GDB itself.
|
|
|
|
We can use...
|
|
|
|
Command:
|
|
(gdb)call <function-name>( <arguments>.... )
|
|
|
|
|
|
-> Attaching the Debugger to a Running Process:
|
|
++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
To attach a running to process to a gdb.
|
|
|
|
Command:
|
|
$gdb -p <process-id>
|
|
|
|
We can get the process id using below command:
|
|
|
|
$ps aux | grep <process-name>
|
|
|
|
To Detach a process and let it run, we can use
|
|
command:
|
|
(gdb)detach
|
|
|
|
|
|
-> Core Dumped -- and how to look at those files.
|
|
++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
When the program crashes and it throws a
|
|
message:
|
|
|
|
$Segmentation fault(core dumped)
|
|
|
|
|
|
This means that the accessing illegal
|
|
memory location and the particular message
|
|
in parenthesis means that the kernel
|
|
took the snapshot of the VAS of the program
|
|
and saved it in a "core" file.
|
|
|
|
|
|
However, this "core" file is only allowed
|
|
to be generated when the system is configured
|
|
to allow this operation.
|
|
|
|
To check if the core file is allowed to be generated
|
|
or not we can use...
|
|
|
|
Command:
|
|
$ulimit -a
|
|
|
|
This -a flag display all the limits of the system
|
|
like size of core file allowed to be generated,
|
|
maximum size of the file allowed, etc.
|
|
|
|
|
|
To particularly see the core file size that is allowed,
|
|
we can use...
|
|
|
|
Command:
|
|
$ulimit -c
|
|
|
|
If it display 0, then core file is now allowed to be
|
|
generated.
|
|
|
|
In order to allow the core files to be generated,
|
|
we need to set the allowed core file size, by
|
|
using following command:
|
|
|
|
Command:
|
|
$ulimit -c <size>
|
|
|
|
Here, if <size> : unlimited, then there is no
|
|
restriction in the allowed core file size which
|
|
will be generated.
|
|
|
|
|
|
It will generate the core file, but now in order to
|
|
get the core file we a utility tool called
|
|
|
|
"systemd-coredump"
|
|
|
|
Install it using package manager.
|
|
|
|
To know about the core dump that occured, we can use
|
|
command of this utility.
|
|
|
|
$coredumpctl
|
|
|
|
It will display all the core dump that has occured till now
|
|
|
|
To display some further detail and location of the coredump
|
|
that is being store we can use command:
|
|
|
|
Command:
|
|
$coredumpctl dump
|
|
|
|
|
|
Note:
|
|
|
|
The core dump file generated is a snapshot of the memory
|
|
when the program crashed. We can open the coredump file
|
|
with gdb using
|
|
$coredumpctl gdb
|
|
|
|
However, with core dump, we cannot move the execution of
|
|
the program as it is not running, we can only inspect
|
|
the state of the program when it faced the issue.
|
|
|
|
|
|
In order to generate core file in the same directory as where
|
|
the executable is present we need to do some configuration.
|
|
After that when the core file is generated in the same
|
|
directory as where the executable is present.
|
|
We can run the core file with executable with debug symbol
|
|
by running the below command:
|
|
|
|
Command:
|
|
$gdb ./<program> <corefile>
|
|
|
|
|
|
-> Core Dumped - gcore for running process:
|
|
++++++++++++++++++++++++++++++++++++++++
|
|
|
|
To generatea core file for running process.
|
|
|
|
We can use gcore, to use it:
|
|
|
|
Command:
|
|
$gcore <PID>
|
|
|
|
|
|
Run the generated core file with executable with debug symbols
|
|
|
|
|
|
To load the generated core file to gdb use command:
|
|
|
|
$gdb -c <corefile>
|
|
|
|
|
|
Note that since core file alone won't show the functions and symbols,etc.
|
|
Load the file with executable compiled with debug symbols.
|
|
|
|
|
|
-> Examining Memory in GDB (also hex):
|
|
+++++++++++++++++++++++++++++++++++
|
|
|
|
|
|
To examine the data structure using examine command.
|
|
|
|
we can use command:
|
|
|
|
Command;
|
|
(gdb)x &<object-name>
|
|
|
|
We get the output in format as shown below:
|
|
|
|
<address of the object in program>: <value of the first byte>
|
|
|
|
|
|
x/nfu
|
|
|
|
* n -> The repeat count is a decimal integer, the default is 1.
|
|
It specifies how much memory (counting by units u) to
|
|
display. If a negative number is specified, memory is examined
|
|
backward from addr.
|
|
|
|
* f -> The display format is one of the formats used by print('x', 'd',
|
|
'u', 'o', 't', 'a', 'c', 'f', 's'), 'i'(for machine instructions)
|
|
and 'm'(for displaying messages). The default is 'x'(hexadecimal)
|
|
initially. The default changes each time you use either x or print.
|
|
|
|
* u -> The unit size is any of
|
|
|
|
b
|
|
Bytes.
|
|
|
|
h
|
|
Halfwords (two bytes).
|
|
|
|
w
|
|
Words (four bytes). This is the initial default.
|
|
|
|
g
|
|
Giant words (eight bytes)
|
|
|
|
|