Skip to content

Commit d1b49ec

Browse files
committed
bpf-tools: Add new feature(leaksanitizer) on BPF CO-RE
Add leaksanitizer(lsan) feature on BPF CO-RE lsan feature originally comes from llvm-project https://github.com/llvm/llvm-project cvector.h comes from c-vector project https://github.com/eteran/c-vector uthash.h comes from uthash project https://github.com/troydhanson/uthash This tool detect and report dangling pointers periodically Usage: lsan [OPTION...] Detect memory leak resulting from dangling pointers. Either -c or -p is a mandatory option EXAMPLES: lsan -p 1234 # Detect leaks on process id 1234 lsan -c a.out # Detect leaks on a.out lsan -c 'a.out arg' # Detect leaks on a.out with argument lsan -c "a.out arg" # Detect leaks on a.out with argument -c, --command=COMMAND Execute and trace the specified command -i, --interval=INTERVAL Set interval in second to detect leak -p, --pid=PID Set pid -s, --suppressions=SUPPRESSIONS Suppressions file name -T, --top=TOP Report only specified amount of backtraces -v, --verbose Verbose debug output -w, --stop-the-world Stop the world during tracing -?, --help Give this help list --usage Give a short usage message -V, --version Print program version Mandatory or optional arguments to long options are also mandatory or optional for any corresponding short options. Report example: $ sudo ./lsan -c a.out -s suppr.txt Info: Execute child process: a.out Info: execute command: a.out(pid 8335) [2022-07-19 16:07:26] Print leaks: Could not open [uprobes] 4 bytes direct leak found in 1 allocations from stack id(19863) #1 0x00564465ed71bf foo #2 0x00564465ed721b main #3 0x007fc0a33f7d90 __libc_init_first [2022-07-19 16:07:36] Print leaks: 8 bytes direct leak found in 2 allocations from stack id(19863) #1 0x00564465ed71bf foo #2 0x00564465ed721b main #3 0x007fc0a33f7d90 __libc_init_first [2022-07-19 16:07:46] Print leaks: 12 bytes direct leak found in 3 allocations from stack id(19863) #1 0x00564465ed71bf foo #2 0x00564465ed721b main #3 0x007fc0a33f7d90 __libc_init_first Source code of test program: \#include <stdio.h> \#include <stdlib.h> \#include <unistd.h> int* foo() { int *tmp = malloc(sizeof(int)); *tmp = 99; return tmp; } int* bar() { int *tmp = malloc(sizeof(int)); *tmp = 22; return tmp; } int main() { int *a = NULL; while (1) { a = foo(); printf("%d\n", *a); a = bar(); free(a); sleep(10); } }
1 parent 9a5a22b commit d1b49ec

6 files changed

Lines changed: 2953 additions & 0 deletions

File tree

libbpf-tools/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ APPS = \
4141
hardirqs \
4242
klockstat \
4343
ksnoop \
44+
lsan \
4445
llcstat \
4546
mdflush \
4647
mountsnoop \

libbpf-tools/cvector.h

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
2+
#ifndef CVECTOR_H_
3+
#define CVECTOR_H_
4+
5+
#include <assert.h> /* for assert */
6+
#include <stdlib.h> /* for malloc/realloc/free */
7+
8+
/**
9+
* @brief cvector_vector_type - The vector type used in this library
10+
*/
11+
#define cvector_vector_type(type) type *
12+
13+
/**
14+
* @brief cvector_set_capacity - For internal use, sets the capacity variable of the vector
15+
* @param vec - the vector
16+
* @param size - the new capacity to set
17+
* @return void
18+
*/
19+
#define cvector_set_capacity(vec, size) \
20+
do { \
21+
if (vec) { \
22+
((size_t *)(vec))[-1] = (size); \
23+
} \
24+
} while (0)
25+
26+
/**
27+
* @brief cvector_set_size - For internal use, sets the size variable of the vector
28+
* @param vec - the vector
29+
* @param size - the new capacity to set
30+
* @return void
31+
*/
32+
#define cvector_set_size(vec, size) \
33+
do { \
34+
if (vec) { \
35+
((size_t *)(vec))[-2] = (size); \
36+
} \
37+
} while (0)
38+
39+
/**
40+
* @brief cvector_capacity - gets the current capacity of the vector
41+
* @param vec - the vector
42+
* @return the capacity as a size_t
43+
*/
44+
#define cvector_capacity(vec) \
45+
((vec) ? ((size_t *)(vec))[-1] : (size_t)0)
46+
47+
/**
48+
* @brief cvector_size - gets the current size of the vector
49+
* @param vec - the vector
50+
* @return the size as a size_t
51+
*/
52+
#define cvector_size(vec) \
53+
((vec) ? ((size_t *)(vec))[-2] : (size_t)0)
54+
55+
/**
56+
* @brief cvector_empty - returns non-zero if the vector is empty
57+
* @param vec - the vector
58+
* @return non-zero if empty, zero if non-empty
59+
*/
60+
#define cvector_empty(vec) \
61+
(cvector_size(vec) == 0)
62+
63+
/**
64+
* @brief cvector_grow - For internal use, ensures that the vector is at least <count> elements big
65+
* @param vec - the vector
66+
* @param count - the new capacity to set
67+
* @return void
68+
*/
69+
#define cvector_grow(vec, count) \
70+
do { \
71+
const size_t cv_sz = (count) * sizeof(*(vec)) + (sizeof(size_t) * 2); \
72+
if (!(vec)) { \
73+
size_t *cv_p = malloc(cv_sz); \
74+
assert(cv_p); \
75+
(vec) = (void *)(&cv_p[2]); \
76+
cvector_set_capacity((vec), (count)); \
77+
cvector_set_size((vec), 0); \
78+
} else { \
79+
size_t *cv_p1 = &((size_t *)(vec))[-2]; \
80+
size_t *cv_p2 = realloc(cv_p1, (cv_sz)); \
81+
assert(cv_p2); \
82+
(vec) = (void *)(&cv_p2[2]); \
83+
cvector_set_capacity((vec), (count)); \
84+
} \
85+
} while (0)
86+
87+
/**
88+
* @brief cvector_pop_back - removes the last element from the vector
89+
* @param vec - the vector
90+
* @return void
91+
*/
92+
#define cvector_pop_back(vec) \
93+
do { \
94+
cvector_set_size((vec), cvector_size(vec) - 1); \
95+
} while (0)
96+
97+
/**
98+
* @brief cvector_erase - removes the element at index i from the vector
99+
* @param vec - the vector
100+
* @param i - index of element to remove
101+
* @return void
102+
*/
103+
#define cvector_erase(vec, i) \
104+
do { \
105+
if (vec) { \
106+
const size_t cv_sz = cvector_size(vec); \
107+
if ((i) < cv_sz) { \
108+
cvector_set_size((vec), cv_sz - 1); \
109+
size_t cv_x; \
110+
for (cv_x = (i); cv_x < (cv_sz - 1); ++cv_x) { \
111+
(vec)[cv_x] = (vec)[cv_x + 1]; \
112+
} \
113+
} \
114+
} \
115+
} while (0)
116+
117+
/**
118+
* @brief cvector_free - frees all memory associated with the vector
119+
* @param vec - the vector
120+
* @return void
121+
*/
122+
#define cvector_free(vec) \
123+
do { \
124+
if (vec) { \
125+
size_t *p1 = &((size_t *)(vec))[-2]; \
126+
free(p1); \
127+
} \
128+
} while (0)
129+
130+
/**
131+
* @brief cvector_begin - returns an iterator to first element of the vector
132+
* @param vec - the vector
133+
* @return a pointer to the first element (or NULL)
134+
*/
135+
#define cvector_begin(vec) \
136+
(vec)
137+
138+
/**
139+
* @brief cvector_end - returns an iterator to one past the last element of the vector
140+
* @param vec - the vector
141+
* @return a pointer to one past the last element (or NULL)
142+
*/
143+
#define cvector_end(vec) \
144+
((vec) ? &((vec)[cvector_size(vec)]) : NULL)
145+
146+
/* user request to use logarithmic growth algorithm */
147+
#ifdef CVECTOR_LOGARITHMIC_GROWTH
148+
149+
/**
150+
* @brief cvector_push_back - adds an element to the end of the vector
151+
* @param vec - the vector
152+
* @param value - the value to add
153+
* @return void
154+
*/
155+
#define cvector_push_back(vec, value) \
156+
do { \
157+
size_t cv_cap = cvector_capacity(vec); \
158+
if (cv_cap <= cvector_size(vec)) { \
159+
cvector_grow((vec), !cv_cap ? cv_cap + 1 : cv_cap * 2); \
160+
} \
161+
vec[cvector_size(vec)] = (value); \
162+
cvector_set_size((vec), cvector_size(vec) + 1); \
163+
} while (0)
164+
165+
#else
166+
167+
/**
168+
* @brief cvector_push_back - adds an element to the end of the vector
169+
* @param vec - the vector
170+
* @param value - the value to add
171+
* @return void
172+
*/
173+
#define cvector_push_back(vec, value) \
174+
do { \
175+
size_t cv_cap = cvector_capacity(vec); \
176+
if (cv_cap <= cvector_size(vec)) { \
177+
cvector_grow((vec), cv_cap + 1); \
178+
} \
179+
vec[cvector_size(vec)] = (value); \
180+
cvector_set_size((vec), cvector_size(vec) + 1); \
181+
} while (0)
182+
183+
#endif /* CVECTOR_LOGARITHMIC_GROWTH */
184+
185+
/**
186+
* @brief cvector_copy - copy a vector
187+
* @param from - the original vector
188+
* @param to - destination to which the function copy to
189+
* @return void
190+
*/
191+
#define cvector_copy(from, to) \
192+
do { \
193+
for(size_t i = 0; i < cvector_size(from); i++) { \
194+
cvector_push_back(to, from[i]); \
195+
} \
196+
} while (0) \
197+
198+
#endif /* CVECTOR_H_ */

0 commit comments

Comments
 (0)