[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Migliorare Debian e il software libero: trovare bug con valgrind e scrivere le patch



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


Reply to: