Premetto che questo thread è riservato a chi conosce il C/C++ e ha un
po' di esperienza in debugging.
Sto indagando su un problema che ho con due applicativi quando accedono
ad alcune istruzioni della GPU.
Ho installato il pacchetto piglit, che permette di eseguire test sulla
propria GPU e ho provato ad eseguirne un set di 50-60 mila test e ho
identificato che almeno uno causa il comportamento anomalo che voglio
cercare di individuare e se possibile di risolvere.
Sto anche leggendo la documentazione di valgrind, presente sul suo sito
web per cercare di capire bene il suo funzionamento e intanto faccio
qualche test.
Come ambiente di debugger visuale (purtroppo in alcuni casi si deve
andare a guardare in n librerie a cascata e avere uno strumento che ti
semplifica alcuni task ti fa risparmiare un sacco di tempo) ho provato:
* ddd: è abbandonato da tanti anni, ha una visualizzazione pessima, ha
parecchi bug, alcuni lo rendono poco usabile
* nemiver: mi sembra molto più usabile di ddd, purtroppo anche questo è
stato abbandonato da un po' di anni
Altri debugger visuali in Debian non ne ho trovati (ce ne sono 2-3 con
ncurses, ma non li ho ancora provati), in rete ho visto che, rilasciati
come software libero e che sembrano validi, ce ne sono almeno due: uno
di kde (https://www.kdbg.org/) e uno della NSA
(https://www.ghidra-sre.org/).
Ho visto che ci sono parecchi programmi che hanno una gestione errata
della memoria e valgrind è eccellente per identificare i problemi
(notare che alcuni potrebbero essere dei falsi positivi e quindi bisogna
indagare a fondo).
Notare che su alcuni programmi di base, es: cat, non liberano la memoria
di proposito perché, mi hanno detto, è una perdita di tempo, dato che il
programma termina e alla sua terminazione tutta la memoria viene
liberata in automatico e più velocemente.
Per ora ho segnalato due bug:
1) cliinfo: non inizializzava, almeno nel mio caso specifico, una
variabile e causava la stampa di caratteri random che impedivano il
funzionamento di piglit
Bug: #975339[¹] che è già stato risolto
come si può vedere dal bug report:
==17199== Conditional jump or move depends on uninitialised value(s)
==17199== at 0x483BCE5: __strlen_sse2 (in
/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==17199== by 0x48F0ECD: __vfprintf_internal (vfprintf-internal.c:1688)
==17199== by 0x4990CC6: __printf_chk (printf_chk.c:33)
==17199== by 0x115D0C: printf (stdio2.h:107)
==17199== by 0x115D0C: checkNullGetDevices (clinfo.c:2739)
==17199== by 0x116E6C: checkNullBehavior (clinfo.c:2917)
==17199== by 0x10E70A: main (clinfo.c:3216)
==17199== Uninitialised value was created by a heap allocation
==17199== at 0x483877F: malloc (in
/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==17199== by 0x115B5C: realloc_strbuf (strbuf.h:38)
==17199== by 0x115B5C: checkNullGetDevices (clinfo.c:2655)
==17199== by 0x116E6C: checkNullBehavior (clinfo.c:2917)
==17199== by 0x10E70A: main (clinfo.c:3216)
Nella parte sottostante indica la variabile allocata con malloc e non
inizializzata, mentre nella parte soprastante indica il punto dove il
valore non inizializzato viene utilizzato.
2) il secondo l'ho appena segnalato, in questo caso è la lettura di una
variabile oltre il limite allocato:
Bug #975658[²]
==17446== Invalid read of size 8
==17446== at 0x5C706CA: UnknownInlinedFun (string_fortified.h:34)
==17446== by 0x5C706CA: drmDeviceAlloc (xf86drm.c:3594)
==17446== by 0x5C717C1: drmProcessPciDevice (xf86drm.c:3610)
==17446== by 0x5C717C1: process_device (xf86drm.c:4012)
==17446== by 0x5C756FE: drmGetDevice2 (xf86drm.c:4190)
==17446== by 0x5C0E1B8: drm_get_id_path_tag_for_fd (loader.c:292)
==17446== by 0x5C0E1B8: loader_get_user_preferred_fd (loader.c:319)
==17446== by 0x5C0426E: dri3_create_screen (dri3_glx.c:866)
==17446== by 0x5BF2E08: AllocAndFetchScreenConfigs (glxext.c:818)
==17446== by 0x5BF2E08: __glXInitialize (glxext.c:949)
==17446== by 0x5BEF4ED: GetGLXPrivScreenConfig (glxcmds.c:174)
==17446== by 0x5BEF4ED: glXQueryExtensionsString (glxcmds.c:1307)
==17446== by 0x4CEB640: wrapped_glXQueryExtensionsString
(glx_wrappers.h:129)
==17446== by 0x4CEB640: glx_display_set_extensions (glx_display.c:55)
==17446== by 0x4CEB640: glx_display_connect (glx_display.c:105)
[...]
==17446== Address 0x58c2da0 is 1 bytes after a block of size 15 alloc'd
==17446== at 0x483877F: malloc (in
/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==17446== by 0x5C71638: process_device (xf86drm.c:3987)
==17446== by 0x5C756FE: drmGetDevice2 (xf86drm.c:4190)
==17446== by 0x5C0E1B8: drm_get_id_path_tag_for_fd (loader.c:292)
==17446== by 0x5C0E1B8: loader_get_user_preferred_fd (loader.c:319)
==17446== by 0x5C0426E: dri3_create_screen (dri3_glx.c:866)
==17446== by 0x5BF2E08: AllocAndFetchScreenConfigs (glxext.c:818)
==17446== by 0x5BF2E08: __glXInitialize (glxext.c:949)
==17446== by 0x5BEF4ED: GetGLXPrivScreenConfig (glxcmds.c:174)
==17446== by 0x5BEF4ED: glXQueryExtensionsString (glxcmds.c:1307)
==17446== by 0x4CEB640: wrapped_glXQueryExtensionsString
(glx_wrappers.h:129)
==17446== by 0x4CEB640: glx_display_set_extensions (glx_display.c:55)
==17446== by 0x4CEB640: glx_display_connect (glx_display.c:105)
[...]
anche in questo caso, nella parte sotto viene indicata qual'è la
variabile e dove viene allocata e nella parte sopra dove viene letta
oltre l'area allocata.
Qui ho perso più tempo perché pensavo che l'errore derivasse dalle
chiamate iniziali dentro il test di piglit e percorrere tutta questa
catena risultava molto complesso anche perché la variabile iniziale era
una struttura, ma in realtà il problema è tutto dentro libdrm2.
Quindi è conveniente guardare subito i punti in cui c'è stata
l'allocazione/inizializzazione e il punto che ha generato l'errore per
cercare di capire il problema e poi se è dovuto a valori passati come
parametro andare a ritroso.
Ho provato ad usare valgrind su diversi programmi e il risultato è che
per molti ci sono diversi possibili errori, per esempio nel test di
piglit che ho eseguito ho ancora 1 errore di "Invalid read" su un'altra
libreria, come quello già segnalato (all'inizio erano 5, ma risolvendone
uno ne sono stati risolti 4 perché avevano la stessa fonte).
Poi ho provato ora valgrind con qalculate, che uso tantissimo, e qui
riporta diverse variabili usate senza essere state prima inizializzate
(anche qui il problema potrebbe non essere di qalculate, ma di qualche
libreria che utilizza).
Ripeto che in alcuni casi gli errori potrebbero essere falsi positivi e
quindi bisogna indagare e scoprirne la causa.
Ho letto che ci sono interi software che usano valgrind per rintracciare
questi problemi (mi sembra che ci siano anche LibreOffice e Firefox),
mentre altri non lo usano.
Naturalmente per ogni bug trovato bisogna trovare una patch e verificarla.
Se ci sono altre persone interessate potremmo aprire dei thread per
discutere di questi argomenti e scambiarci informazioni e consigli.
Ciao
Davide
[¹]
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=975339
[²]
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=975658