Skip to content

Commit 4abcf38

Browse files
committed
Add leak examples. Update report.
1 parent d04e495 commit 4abcf38

File tree

4 files changed

+251
-0
lines changed

4 files changed

+251
-0
lines changed

ProjectAnalysisReport.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ Valgrind setup and dir structure
2828

2929
##### valgrind memcheck
3030

31+
Alat memcheck pruza mogucnost analize koda u kontekstu bezbednog upravljanja memorijom. Postoji nekoliko kategorija potencijalnih problema sa memorijom. Najbitniji tipovi memorijskih gresaka opisani su ispod:
32+
33+
1) definitely lost - Memorija je alocirana i nikada nije oslobodjena, a pokazivac na tu memoriju je definitivno izgubljen i ne postoji nacin da mu program pristupi.
34+
2) indirectly lost - Memorijski blok nije direktno izgubljen, ali zavisi od bloka memorije koji jeste izgubljen.
35+
3) possibly lost - Memorijski blok je alociran, ali Valgrind ne moze da zakljuci da li je izgubljen.
36+
4) still reachable - Memorjski blok je alociran i neoslobodjen, ali i dalje postoji pokazivac na njega.
37+
3138
Nakon pokretanja memcheck alata nad jednostavnim primerom (`samples/bluetooth/beacon` pokrenut uz pomoc skripte `run_beacon_valgrind.sh`), vidimo da se greske vecinski ticu POSIX podsistema i funkcija koje nisu nuzno deo Zephyr OS-a. Naime, sve funkcije se zavrsavaju pozivom deljene biblioteke kojoj nemamo pristup u izvornom obliku.
3239

3340
```bash
@@ -180,6 +187,7 @@ Nakon pokretanja memcheck alata nad jednostavnim primerom (`samples/bluetooth/be
180187
181188
```
182189
190+
Najveci broj bajtova koji su problematicni je `still reachable`. Ovo nije nuzno problem kao sto cemo videti ispod.
183191
184192
U svakom slucaju, probacemo da ispratimo call trace za neke od pronadjenih gresaka u okviru samog Zephyr OS sistema.
185193
Jos jedno zapazanje je da se `main` funkcija ne smatra kao ulazna tacka za aplikaciju iskompajliranu za izvrsavanje na POSIX platformi. Naime, u fajlu `posix_cheats.h` vidimo da se main funkcija preimenuje u `_posix_zephyr_main` koja odgovara main funkciji u nasem primeru.
@@ -253,6 +261,8 @@ Takodje vidimo da je izbor napravljen zarad osiguravanja pravilnog izvrsavanja n
253261
254262
Poslusacemo savet u vezi koriscenja fajla za ignorisanje valgrind gresaka i pokrenuti analizu ispocetka. Dodajemo opciju `-s` za ukljucivanje supression fajla u `run_beacon_valgrind.sh` skriptu. _Za postizanje prvobitnog izlaza, pokrenuti skriptu bez ove opcije._
255263
264+
Sam suppression fajl navodi pravila za ignorisanje `reachable` i `possible` tipova gresaka koje smo videli u prvobitnom izlazu. Konkretno ignorisu se alokacije koje su nastale pozivima `posix_nex_thread` funkcija izmedju ostalih.
265+
256266
Izlaz iz ovako konfigurisane analize nam govori da su sve prijavljene greske u vezi alokacije bile izazvane konfiguracijom sistema za emulaciju. Pokusacemo i pokretanje aplikacije za babblesim platformu kasnije. Za sad, dobijamo prijavljene greske o koriscenju neinicijalizovane memorije. Nadalje cemo uvek uvlaciti fajl za suppression kako bismo se fokusirali samo na greske koje sama aplikacija moze izazvati.
257267
258268
```bash
@@ -393,6 +403,38 @@ Izmene u izvornom kodu `userchan.c` date su u patchu `userchan_fix_uninit_access
393403
==104210== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
394404
```
395405
406+
Kao dodatak, napravicemo i primere za ostale tipove gresaka sa memorijom uvodjenjem sledecih funkcija:
407+
408+
```c
409+
typedef struct {
410+
char *data;
411+
} Node;
412+
413+
void leak_indirectly() {
414+
Node *node = malloc(sizeof(Node)); // Allocated struct
415+
node->data = malloc(50); // Allocated internal pointer
416+
417+
// If `node` is lost, `node->data` is also lost (indirectly)
418+
}
419+
```
420+
421+
422+
```c
423+
void possibly_lost() {
424+
void *ptr = malloc(100);
425+
ptr = ptr - 5; // Pointer is now shifted
426+
}
427+
```
428+
429+
```c
430+
void still_reachable() {
431+
static char *global_ptr;
432+
global_ptr = malloc(100);
433+
}
434+
```
435+
436+
Izmena se nalazi u fajlu `memleak_demo_all_leaks.patch`, a rezultati analize su u `valgrind_20250209_195054_all.log`. U rezultujucem fajlu vidimo da se prijavljuju ostali tipovi gresaka TODO(avra): opisati dalje...
437+
396438
##### valgrind tool2
397439
398440
--- ;

patches/memleak_demo_all_leaks.patch

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
diff --git a/drivers/bluetooth/hci/userchan.c b/drivers/bluetooth/hci/userchan.c
2+
index 50c3165809d..0c9553b655b 100644
3+
--- a/drivers/bluetooth/hci/userchan.c
4+
+++ b/drivers/bluetooth/hci/userchan.c
5+
@@ -58,7 +58,7 @@ static K_KERNEL_STACK_DEFINE(rx_thread_stack,
6+
CONFIG_ARCH_POSIX_RECOMMENDED_STACK_SIZE);
7+
static struct k_thread rx_thread_data;
8+
9+
-static unsigned short bt_dev_index;
10+
+static unsigned short bt_dev_index = 0;
11+
12+
#define TCP_ADDR_BUFF_SIZE 16
13+
static bool hci_socket;
14+
@@ -328,7 +328,8 @@ static int user_chan_open(void)
15+
int fd;
16+
17+
if (hci_socket) {
18+
- struct sockaddr_hci addr;
19+
+ struct sockaddr addr;
20+
+ struct sockaddr_hci *hci_addr = (struct sockaddr_hci *)&addr;
21+
22+
fd = socket(PF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
23+
BTPROTO_HCI);
24+
@@ -337,9 +338,12 @@ static int user_chan_open(void)
25+
}
26+
27+
(void)memset(&addr, 0, sizeof(addr));
28+
- addr.hci_family = AF_BLUETOOTH;
29+
- addr.hci_dev = bt_dev_index;
30+
- addr.hci_channel = HCI_CHANNEL_USER;
31+
+ hci_addr->hci_family = AF_BLUETOOTH;
32+
+ hci_addr->hci_dev = bt_dev_index;
33+
+ hci_addr->hci_channel = HCI_CHANNEL_USER;
34+
+
35+
+ // LOG_ERR("sizeof(sockaddr_hci) = %zu\n", sizeof(struct sockaddr_hci));
36+
+ // LOG_ERR("sizeof(sockaddr_rc) = %zu\n", sizeof(struct sockaddr));
37+
38+
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
39+
int err = -errno;
40+
diff --git a/samples/bluetooth/beacon/prj.conf b/samples/bluetooth/beacon/prj.conf
41+
index 045c5c5f61d..dad48c73103 100644
42+
--- a/samples/bluetooth/beacon/prj.conf
43+
+++ b/samples/bluetooth/beacon/prj.conf
44+
@@ -1,3 +1,5 @@
45+
CONFIG_BT=y
46+
CONFIG_LOG=y
47+
CONFIG_BT_DEVICE_NAME="Test beacon"
48+
+CONFIG_DEBUG=y
49+
+CONFIG_NO_OPTIMIZATIONS=y
50+
\ No newline at end of file
51+
diff --git a/samples/bluetooth/beacon/src/main.c b/samples/bluetooth/beacon/src/main.c
52+
index 484b6e94c8f..cc9a6033f23 100644
53+
--- a/samples/bluetooth/beacon/src/main.c
54+
+++ b/samples/bluetooth/beacon/src/main.c
55+
@@ -10,6 +10,8 @@
56+
#include <stddef.h>
57+
#include <zephyr/sys/printk.h>
58+
#include <zephyr/sys/util.h>
59+
+#include <stdlib.h>
60+
+#include <string.h>
61+
62+
#include <zephyr/bluetooth/bluetooth.h>
63+
#include <zephyr/bluetooth/hci.h>
64+
@@ -40,6 +42,43 @@ static const struct bt_data sd[] = {
65+
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
66+
};
67+
68+
+void mem_leak(){
69+
+ printk("mem_leak()\n");
70+
+ void *ptr = malloc(100);
71+
+}
72+
+
73+
+void use_uninitialized_mem(){
74+
+ printk("use_uninitialized_mem()\n");
75+
+ int *ptr = malloc(sizeof(int));
76+
+ int value = *ptr;
77+
+ free(ptr);
78+
+}
79+
+
80+
+typedef struct {
81+
+ char *data;
82+
+} Node;
83+
+
84+
+void leak_indirectly() {
85+
+ Node *node = malloc(sizeof(Node)); // Allocated struct
86+
+ node->data = malloc(50); // Allocated internal pointer
87+
+
88+
+ // If `node` is lost, `node->data` is also lost (indirectly)
89+
+}
90+
+
91+
+void possibly_lost() {
92+
+ int *ptr1 = malloc(100); // Allocate memory
93+
+
94+
+ ptr1 += 10; // Overwrite ptr1 with ptr2, losing the original ptr1
95+
+
96+
+ // At this point, the memory allocated for ptr1 is "possibly lost"
97+
+ // because ptr1 no longer points to it
98+
+}
99+
+
100+
+void still_reachable() {
101+
+ static char *global_ptr;
102+
+ global_ptr = malloc(100);
103+
+}
104+
+
105+
static void bt_ready(int err)
106+
{
107+
char addr_s[BT_ADDR_LE_STR_LEN];
108+
@@ -80,6 +119,13 @@ int main(void)
109+
110+
printk("Starting Beacon Demo\n");
111+
112+
+ printk("Calling memleak functions\n");
113+
+ mem_leak();
114+
+ use_uninitialized_mem();
115+
+ leak_indirectly();
116+
+ possibly_lost();
117+
+ still_reachable();
118+
+
119+
/* Initialize the Bluetooth Subsystem */
120+
err = bt_enable(bt_ready);
121+
if (err) {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
==108541== Memcheck, a memory error detector
2+
==108541== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
3+
==108541== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
4+
==108541== Command: ./build/zephyr/zephyr.exe --bt-dev=hci1
5+
==108541== Parent PID: 108540
6+
==108541==
7+
==108541==
8+
==108541== HEAP SUMMARY:
9+
==108541== in use at exit: 3,122 bytes in 12 blocks
10+
==108541== total heap usage: 24 allocs, 12 frees, 14,636 bytes allocated
11+
==108541==
12+
==108541== 50 bytes in 1 blocks are indirectly lost in loss record 1 of 12
13+
==108541== at 0x40436A0: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-x86-linux.so)
14+
==108541== by 0x8049988: leak_indirectly (main.c:63)
15+
==108541== by 0x8049B0B: _posix_zephyr_main (main.c:125)
16+
==108541== by 0x8059292: bg_thread_main (init.c:564)
17+
==108541== by 0x804B32F: z_thread_entry (thread_entry.c:48)
18+
==108541== by 0x804E560: posix_arch_thread_entry (thread.c:96)
19+
==108541== by 0x804EA85: nct_thread_starter (nct.c:366)
20+
==108541== by 0x41F4C00: start_thread (pthread_create.c:442)
21+
==108541== by 0x428F309: clone (clone.S:107)
22+
==108541==
23+
==108541== 54 (4 direct, 50 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 12
24+
==108541== at 0x40436A0: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-x86-linux.so)
25+
==108541== by 0x8049978: leak_indirectly (main.c:62)
26+
==108541== by 0x8049B0B: _posix_zephyr_main (main.c:125)
27+
==108541== by 0x8059292: bg_thread_main (init.c:564)
28+
==108541== by 0x804B32F: z_thread_entry (thread_entry.c:48)
29+
==108541== by 0x804E560: posix_arch_thread_entry (thread.c:96)
30+
==108541== by 0x804EA85: nct_thread_starter (nct.c:366)
31+
==108541== by 0x41F4C00: start_thread (pthread_create.c:442)
32+
==108541== by 0x428F309: clone (clone.S:107)
33+
==108541==
34+
==108541== 100 bytes in 1 blocks are still reachable in loss record 5 of 12
35+
==108541== at 0x40436A0: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-x86-linux.so)
36+
==108541== by 0x80499C2: still_reachable (main.c:79)
37+
==108541== by 0x8049B15: _posix_zephyr_main (main.c:127)
38+
==108541== by 0x8059292: bg_thread_main (init.c:564)
39+
==108541== by 0x804B32F: z_thread_entry (thread_entry.c:48)
40+
==108541== by 0x804E560: posix_arch_thread_entry (thread.c:96)
41+
==108541== by 0x804EA85: nct_thread_starter (nct.c:366)
42+
==108541== by 0x41F4C00: start_thread (pthread_create.c:442)
43+
==108541== by 0x428F309: clone (clone.S:107)
44+
==108541==
45+
==108541== 100 bytes in 1 blocks are definitely lost in loss record 6 of 12
46+
==108541== at 0x40436A0: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-x86-linux.so)
47+
==108541== by 0x8049920: mem_leak (main.c:47)
48+
==108541== by 0x8049B01: _posix_zephyr_main (main.c:123)
49+
==108541== by 0x8059292: bg_thread_main (init.c:564)
50+
==108541== by 0x804B32F: z_thread_entry (thread_entry.c:48)
51+
==108541== by 0x804E560: posix_arch_thread_entry (thread.c:96)
52+
==108541== by 0x804EA85: nct_thread_starter (nct.c:366)
53+
==108541== by 0x41F4C00: start_thread (pthread_create.c:442)
54+
==108541== by 0x428F309: clone (clone.S:107)
55+
==108541==
56+
==108541== 100 bytes in 1 blocks are definitely lost in loss record 7 of 12
57+
==108541== at 0x40436A0: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-x86-linux.so)
58+
==108541== by 0x80499A5: possibly_lost (main.c:69)
59+
==108541== by 0x8049B10: _posix_zephyr_main (main.c:126)
60+
==108541== by 0x8059292: bg_thread_main (init.c:564)
61+
==108541== by 0x804B32F: z_thread_entry (thread_entry.c:48)
62+
==108541== by 0x804E560: posix_arch_thread_entry (thread.c:96)
63+
==108541== by 0x804EA85: nct_thread_starter (nct.c:366)
64+
==108541== by 0x41F4C00: start_thread (pthread_create.c:442)
65+
==108541== by 0x428F309: clone (clone.S:107)
66+
==108541==
67+
==108541== LEAK SUMMARY:
68+
==108541== definitely lost: 204 bytes in 3 blocks
69+
==108541== indirectly lost: 50 bytes in 1 blocks
70+
==108541== possibly lost: 0 bytes in 0 blocks
71+
==108541== still reachable: 100 bytes in 1 blocks
72+
==108541== suppressed: 2,768 bytes in 7 blocks
73+
==108541==
74+
==108541== For lists of detected and suppressed errors, rerun with: -s
75+
==108541== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 4 from 4)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
WARNING: Using a test - not safe - entropy source
2+
*** Booting Zephyr OS build v4.0.0-2878-g6f240ef18c11 ***
3+
Starting Beacon Demo
4+
Calling memleak functions
5+
mem_leak()
6+
use_uninitialized_mem()
7+
[00:00:00.400,000] <inf> bt_hci_core: Identity: 8C:88:0B:0A:55:94 (public)
8+
[00:00:00.400,000] <inf> bt_hci_core: HCI: version 5.1 (0x0a) revision 0xdfc6, manufacturer 0x005d
9+
[00:00:00.400,000] <inf> bt_hci_core: LMP: version 5.1 (0x0a) subver 0xd922
10+
Bluetooth initialized
11+
Beacon started, advertising as 8C:88:0B:0A:55:94 (public)
12+
13+
Stopped at 8.920s

0 commit comments

Comments
 (0)