Upload
nishank-modi
View
214
Download
1
Embed Size (px)
Citation preview
Tutorial: ValgrindCS447/CS647/ECE453/ECE653/SE465
2014-2-14
What is Valgrind
Valgrind is a GPL'd system for debugging and profiling Linux programs. With Valgrind's tool suite you can automatically detect many memory management and threading bugs, avoiding hours of frustrating bug-hunting, making your programs more stable. You can also perform detailed profiling to help speed up your programs.
-- http://valgrind.org/info/
Valgrind Tool Suite
An instrumentation framework for building dynamic analysis tools● Memcheck: memory error detector● Cachegrind: cache profiler● Helgrind, DRD: thread error detectors● Massif: heap profiler● ...
Memcheck
● Intercept calls to malloc/new/free/delete● Check all reads and writes of memory● Detect memory-management problems
○ buffer overflow○ memory leak ○ allocation/deallocation mismatch○ R/W via dangling pointer○ use uninitialized memory○ ...
A Bit of Internals
Valgrind is essentially a virtual machine● Translate machine code into an architecture-
independent intermediate representation● Insert instrumentation code around the IR
(depending on the tool)● Translating back into machine code and run
on a simulated CPUMemcheck: every register/memory value has a “shadow value” containing information about it
Get Valgrind
● Install Valgrind○ ecelinux has Valgrind pre-installed○ Ubuntu: apt-get install valgrind○ Archlinux: pacman -S valgrind○ General: ./configure & make & make install
Use Memcheck to Debug
● Compile your program○ $ gcc -g example.c -o example○ -g: include debug info. so Valgrind knows line # ○ -O: optimization, -O2 and above can screw up
Valgrind report, not recommended● Run Valgrind
○ $ valgrind ./exmaple○ Memcheck is the default tool invoked○ --leak-check=full: list details of each leak○ --track-origins=yes: track the origin of
uninitialized values○ others via valgrind --help
Buffer Overflow (Eg.1)
1 #include <stdio.h>
2 #include <stdlib.h>
3 int main()
4 {
5 int *b = calloc(
6 4, sizeof(int));
7 printf("%d\n", b[4]);
8 free(b);
9 return 0;
10 }
==31015== Invalid read of size 4
==31015== at 0x4005B0: main
(e1.c:7)
==31015== Address 0x51dc050 is 0
bytes after a block of
size 16 alloc'd
==31015== at 0x4C29860: calloc(in
/usr/lib/valgrind/
vgpreload_memcheck-
amd64-linux.so)
==31015== by 0x4005A3: main
(e1.c:5)
Memory Leak (Eg.2)
1 #include <stdio.h>
2 #include <stdlib.h>
3 int main()
4 {
5 int *b = calloc(
6 4, sizeof(int));
7 printf("%d\n", b[3]);
8 return 0;
9 }
==32266== 16 bytes in 1 blocks are
definitely lost in loss
record 1 of 1
==32266== at 0x4C29860: calloc
(in /usr/lib/valgrind/
vgpreload_memcheck-
amd64-linux.so)
==32266== by 0x400553: main
(e2.c:5)
==32266== LEAK SUMMARY:
==32266== definitely lost: 16
bytes in 1 blocks
...
Dangling Pointer (Eg.3) 1 #include <stdio.h>
2 #include <stdlib.h>
3 int main()
4 {
5 int *b = calloc(
6 4, sizeof(int));
7 b[2] = 1;
8 free(b);
9 printf("%d\n", b[2]);
10 return 0;
11 }
==5021== Invalid read of size 4
==5021== at 0x4005CA: main
(e3.c:9)
==5021== Address 0x51dc048 is 8
bytes inside a block of
size 16 free'd
==5021== at 0x4C289DC: free (in
/usr/lib/valgrind/
vgpreload_memcheck-
amd64-linux.so)
==5021== by 0x4005C1: main
(e3.c:8)
Double Free (Eg.4) 1 #include <stdio.h>
2 #include <stdlib.h>
3 int main()
4 {
5 int *b = malloc(
6 4 * sizeof(int));
7 b[2] = 1;
8 free(b);
9 free(b);
10 return 0;
11 }
==2819== Invalid free() / delete /
delete[] / realloc()
==2819== at 0x4C289DC: free (in
/usr/lib/valgrind/
vgpreload_memcheck-
amd64-linux.so)
==2819== by 0x400578: main (e4.c:9)
==2819== Address 0x51dc040 is 0 bytes
inside a block of size 16
free'd
==2819== at 0x4C289DC: free (in
/usr/lib/valgrind/
vgpreload_memcheck-
amd64-linux.so)
Uninitialized Memory (Eg.5) 1 #include <stdio.h>
2 #include <stdlib.h>
3 int main()
4 {
5 int ret;
6 int *b = malloc(
7 4 * sizeof(int));
8 ret = b[2];
9 free(b);
10 return ret;
11 }
==3911== Syscall param
exit_group(status) contains
uninitialised byte(s)
...
==3911== Uninitialised value was
created by a heap allocation
==3911== at 0x4C27730: malloc
(in /usr/lib/valgrind/
vgpreload_memcheck-
amd64-linux.so)
==3911== by 0x40054E: main
(e5.c:6)
Caveats
● No bound checking on stack-allocated arrays int main() {
int a[10];
a[11] = 42;
}
● More time (20x-30x), more memory (2x)● Reveal problem only when input triggering it
is provided
Useful Links
● Valgrind Quick Start Guide○ http://valgrind.org/docs/manual/quick-start.
html#quick-start.intro● Valgrind Memcheck Manual
○ http://valgrind.org/docs/manual/mc-manual.html● Design and Architecture of Valgrind
○ Nicholas Nethercote & Julian Seward, Valgrind: A Framework for Heavyweight Dynamic Binary Instrumentation, PLDI’07