How to debug/da

From The Document Foundation Wiki
Jump to: navigation, search

Contents

Debugningsindstillinger

Du skal aktivere debugningsunderstøttelse for at kunne lave noget praktisk interaktiv debugging. Du kan aktivere den for hele prototypen med ./autogen.sh --enable-debug eller blot for specifikke moduler with --enable-debug --enable-selective-debuginfo="sw/ xmloff/".

En anden meget hjælpsom indstilling til debugning er --enable-dbgutil, som ligner --enable-debug og desuden aktiverer mere- eller-mindre nyttige sætninger og supplerende debugning-kode samt også STL-debugningstilstand i libstdc++ på nogle GCC-baserede platforme (men ikke Mac OS X, fordi Apples libstdc++ mangler understøttelse af den og clang libc++ ikke lader til at have en debugningstilstand), og bruger debug-biblioteker (herunder debug STL) med MSVC. Bemærk, at det ikke er muligt at blande indbygget kode bygget med og uden --enable-dbgutil.

Bemærk, at en fuldstændig prototype med --enable-debug or --enable-dbgutil til alle moduler optager ~30 GB diskplads. Hvis du synes, dette er for meget, kan du enten bruge --enable-selective-debuginfo eller lave en hel non-debug prototype og så genopbygge bare de moduler, du er interesset i:

make <module>.clean && make <module> debug=t

Debugning med gdb

Der er to metoder: Du kan starte LibreOffice med det dedikerede script (soffice, swriter osv.) og så knytte debuggeren til LibreOffice-processen eller starte LibreOffice binært (soffice.bin) direkte fra debuggeren.
I de følgende noter er variablen $LOROOT sat til stien til den mappe, som du klonede kerne git-lageret til, dvs. stien til mappen, hvor skriptet autogen.sh er placeret.

Tilknytning til processen soffice.bin

Det er ganske enkelt, fordi soffice-skriptet vil sørge for at opsætte de nødvendige miljø-variabler:

 
$ instdir/program/soffice # or /sdraw /swriter ... 
$ gdb --pid=$(pidof soffice.bin) 
(gdb)

Når du kører start-skriptet soffice, swriter, …), kan du overflytte -norestore option: Det vil undertrykke genstart/gendan efter fatale fejl.
Til at tilknytte og frigøre en proces inde fra gdb-skallen kan du bruge kommandoerne attach <pid> and detach, den sidste behøver ingen argumenter.
Efter tilknytning til processen soffice.bin stopper gdb programmet.

Start LibreOffice fra debuggeren (gdb)

Under 3.5 og senere er det letteste at give denne enkle kommando på topniveau (den startede soffice.bin vil lytte til et navngivet rør, så du kan endda forbinde til det fra en anden processer via UNO):

 
 make debugrun

Under 5.0 og senere vil dette også fungere med MSCV, men det vil kun starte soffice.bin og du skal tilknytte debuggeren manuelt fra Visual Studio.

En gdb begynderbog

Når først programmet er stoppet, kan du søge efter symboler, se data og opsætte afbrydelsespunkter:

 
(gdb) info fun DrawEllipse 
Alle funktioner, der matcher det regulære udtryk "DrawEllipse": 

File $LOROOT/svtools/source/filter.vcl/wmf/winmtf.cxx: 
void WinMtfOutput::DrawEllipse(Rectangle const&); 

File $LOROOT/clone/libs-gui/vcl/source/gdi/outdev5.cxx:<span style="color:#000000" /> 
void OutputDevice::DrawEllipse(Rectangle const&); 

File $LOROOT/clone/libs-gui/vcl/source/gdi/pdfwriter.cxx: 
void vcl::PDFWriter::DrawEllipse(Rectangle const&); 

Symboler, der ikke debugger: 
0x00007f826dd4a318 OutputDevice::DrawEllipse(Rectangle const&) 
0x00007f826dd4a318 [mailto:_ZN12OutputDevice11DrawEllipseERK9Rectangle@plt _ZN12OutputDevice11DrawEllipseERK9Rectangle@plt] 

(gdb) break vcl::PDFWriter::DrawEllipse 
Breakpoint 1 at 0x7f826c7c5e20: file /opt/shared/work/source_code/libreoffice/libo/clone/libs-gui/vcl/source/gdi/pdfwriter.cxx, line 159.

Nu er der sat et afbrydelsespunkt på placeringen med relation til den givne metode. Bemærk, at metodenavnet skal være fuldt kvalificeret med klasse navn og ombrydende mellemrum til navne.
Den almene syntaks er: break <location>, hvor <location> kan være en fuldt kvalificeret funktion, en hukommelsesadresse eller et filnavn fulgt af et ”.“ og et linjenummer. Læs flere detaljer om begrebet location på gdb manualsiden: Specifying a Location

Til oplistning af de opsatte afbrydelsespunkter kan du bruge kommandoen:

 
(gdb) info break 
Num   Type      Disp Enb Address      What 
1    breakpoint   keep y  0x00007f826c7c5e20 in vcl::PDFWriter::DrawEllipse(Rectangle const&) 
                        at /opt/shared/work/source_code/libreoffice/libo/clone/libsgui/vcl/source/gdi/pdfwriter.cxx:159

Til at fjerne afbrydelsespunkter kan du bruge en af følgende kommandoer:

 
clear <location> 
delete <breakpoint number>

Verserende afbrydelsespunkter

I det tilfælde et symbol tilhører et endnu ikke indlæst delt bibliotek, kan du stadig tilføje et afbrydelsespunkt i relation til dette symbol, gdb vil opsætte et såkaldt ”verserende afbrydelsespunkt“, som bliver aktiveret, så snart symbolet bliver tilgængeligt.

(gdb) break SVGActionWriter::ImplWriteRect 
Can't find member of namespace, class, struct, or union named "SVGActionWriter::ImplWriteRect" 
Vink: Prøv 'SVGActionWriter::ImplWriteRect<TAB> eller 'SVGActionWriter::ImplWriteRect<ESC-?> 
(Bemærk det indledende enkelte citationstegn) 
Opret afbrydelsespunkt afhængigt af kommende indlæsning af delt biblioteK? (y eller [n]) y 
Breakpoint 1 (SVGActionWriter::ImplWriteRect) pending. 
(gdb) info break 
Num   Type      Disp Enb Address  What 
1    breakpoint   keep y  <PENDING> SVGActionWriter::ImplWriteRect

Hvis du ønsker, at gdb opsætter ethvert ukendt symbol som verserende afbrydelsespunkt uden at spørge dig hver gang, hvad det skla gøre, skal du køre den følgende kommando:

set breakpoint pending on

for at vende tilbage til standardtilstand sætter du den til ”auto“.

En udfordring med verserende afslutningspunkter er, at du skal huske hele navnet på den den kvalificerede funktion eller metode: Kommandoen info fun vil ikke hjælpe dig, da symbolet stadig er ukendt. ”Delte objektbegivenheder“ giver en mulig løsning.

Dumpe strenge

Med magien i gdb pretty printers vil ”print string“ fra gdb 7 og fremefter dumpe indholdet af strengen uanset om det er en UTF-16 rtl::OUString eller en 8-bit rtl::OString. Der er pretty-printer support af sane dumping for en vifte af andre objekter såvel som strenge, fx Any, Sequence, Date, Time osv. Brug ”print/r“ (eller ”p/r“), hvis du virkelig er nødt til at se strukturen uden pretty-print. Pretty printere aktiveres automatisk til indbygget debugging og til kørsel fra instdir.

Bemærk: hvis pretty-printere ikke virker ud af boksen, er det sandsynligvis en gdb sikkerhedsindstilling, der forhindrer at de indlæses; se efter en fejlmeddelelse vedrørende ”safe-path“. For at undgå dette problem tilføj dette til konfigurationsfilen $HOME/.gdbinit:

add-auto-load-safe-path /path/to/your/lo/git 

Bemærk: Apple gdb er antik og understøtter ikke Python pretty-printere-

Dumpe STL containere

GDB kan også pretty-printe indholdet af STL-containere, hvilket er meget nyttigt.

Det følgende gælder kun ældre LibreOffice-versioner: siden version 4.0 bundles libstdc++ ikke længere

Men dette virker måske ikke ud af boksen, eftersom LibreOffice-installationssættet indeholder sin egen libstdc++, så gdb ikke kan auto-indlæse de relaterede Python-filer.

På et Feodora 16-system går denne tilføjelse uden om problemet (du skal nok tilpasse versionsnumrene til dit system):

 
# omgå at OOo/LO indeholder sin egen libstdc++ 
python 
import sys 
sys.path.insert(0, '/usr/share/gcc-4.6.1/python') 
end 
source /usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.16-gdb.py

Delte objekthændelser

En delt objekthændelse indtræder hver gang et delt bibliotek indlæses eller udlæses. Som standard er det ikke aktiveret, men du kan slå det til med følgende kommando:

set stop-on-solib-events 1

Nu stoppes programmet hver gang, der indlæses et delt bibliotek og du vil kunne søge efter nye symboler og opsætte nye afbrydelsespunkter.
Du bør kun aktivere delte objekthændelser, når du ved, at det delte bibliotek, du er interesseret i, bliver indlæst om kort tid, ellers skal du give kommandoen continue en masse gange og alt vil blive meget irriterende.
Hvordan kan du vide, om et delt bibliotek, du er interesseret i, er blevet indlæst ? Du kan se det med kommandoen info shared <reg expr>. Denne kommando vil opliste alle indlæste delte biblioteker, som matcher det givne regulære udtryk.

Debug UNO

Når søger efter den rigtige C++-type af en UNO-henvisning kan du bruge:

 
(gdb) print *rShape._pInterface 
$1 = {_vptr.XInterface = 0x2aaac99f9728 <vtable for SvxShapeText+648>} 
(gdb) print rShape._pInterface 
$2 = (com::sun::star::uno::XInterface *) 0x2313e9

Diverse hjælpere

Nogle gdb-udtryk, som kunne være nyttige under visse omstændigheder:

  • info mutex: viser, hvilke tråde, der har låst hvilke mutex
  • fcatch: stopper, når et udtryk kastes, men kun hvis en given funktion er på stakken

Debugning med DDD (en gdb brugerflade)

Hvis du vil tilknytte debuggeren til processen soffice.bin, er du nødt til at starte LibreOffice:

$ cd $LOROOT/install/program 
$ ./soffice  # or ./swriter, ./simpress, ...

I det tilfælde, at du ønsker at starte LibreOffice fra debuggeren, er du i alle tilfælde nødt til at source miljø-variablerne før du kører det:

$ cd $LOROOT/install/program 
$ source ./ooenv

Endelig kan du starte DDD med kommandoen ddd.

I begge tilfælde skal du sætte programmet op til at blive debugget. Klik på elementet Open Program i menuen File. Et fildialog-vindue popper op: vælg den eksekverbare fil soffice.bin, som du kan finde under $LOROOT/install/program. I det tilfælde at du allerede har startet LibreOffice, er du nødt til at tilknytte processen soffice.bin: du kan gøre det med menuelementet File>Attach to process. Du får præsenteret en liste over kørende processer. Dobbeltklik på processen soffice.bin (den skulle allerede være markeret). På samme måde frigør du processen ved at køre kommandoen File>Detach.

Når det er tilknyttet processen, er programmet suspenderet og du kan begynde at debugge det. Boksen ”Command Tool“ åbnes automatisk med et helt sæt handlingsknapper til at genoptage eksekvering og gå gennem programmet. Nederst i DDD-vinduet kan du se ”GDB Console“: en skal, hvor du kan kan køre gdb-kommandoer direkte. Oven over GDB-konsollen findes ”Source Window“ (kildevinduet), hvor du kan se programmets kildekode.

For at ændre skrift-typen og -størrelsen i GDB-konsollen og kildevinduet skal du gå til Edit>Preferences...>Fonts og ændre egenskaben Fixed Font. For at gøre dine tilpasninger permanente skal du tjekke elementet Save Options i menuen Edit.

For at starte LibreOffice fra debuggeren kan du klikke på knappen Run (i det flydende vindue Command Tool. Eller du kan give kommandoen run eller start direkte i GDB-konsollen, som vil lade dig videregive argumenterne i kommandolinjen til programmet.

Med menupunktet Status>Backtrace åbner du en dialogboks med en række funktionskald: de begynder med opkaldet til hovedfunktionen og går til det sidste funktionskald: det, hvor programmet er stoppet. Vælg et funktionskald på denne liste og kildekoden, hvor funktionskaldet udføres, bliver vist i Source Window (hvis kildefilen er fundet). En stor pil i venstre side vil vise eksekveringens aktuelle position. Hvis du vil undersøge eftersporingen af en anden tråd, er du nødt til at åbne dialogboksen Thread med det samme navn i menuen Status.

I DDD-menuen er der til højre et redigeringsfelt med flere knapper. Du kan se hver knap som en handling, der vil blive udført på den aktuelle tekst i redigeringsfeltet, hver gang der klikkes på knappen. Hvis du skriver et fuldt kvalificeret symbolnavn og så klikker på knappen Lookup, bliver kildefilen åbnet i Source Window der, hvor symbolet er defineret. Hvis du skriver en streng i redigeringsfeltet og klikker på knappen Find>> (fremad) søges den givne streng fremad i den aktuelt viste kildefil.

Når det symbol, du skriver i redigeringsfeltet, er en gyldig lokation vil et klik på knappen Break indsætte et afbrydelsespunkt på det sted. Hvis du åbner kildefilen med det givne symbol, vil du se, at et lille ”stop“-ikon er kommet frem til venstre på den linje, hvor symbolet er defineret og viser, at der er oprettet et afbrydelsespunkt. Et højreklik på det vil åbne en kontekstmenu med flere indstillinger. På samme måde vil et klik på knappen Watch definere et iagttagelsespunkt for det givne symbol. En anden måde at oprette et afbrydelsespunkt på er at højreklikke på elementet Set Breakpoint.

Knappen Print vil udskrive værdien af det symbol, du indtastede i redigeringsfeltet i gdb-skallen. Til mere komplekse værdier vil knappen Display vise symbolværdien i Data Window, som automatisk vil åbnes over Source Window. Hvis du peger med musen på et variabel- symbol i Source Window vil dets værdi endda blive automatisk vist i en lille værktøjstipsboks. I Datavinduet kan kan du også vise alle tilgængelige lokale variabler og argumenter, der er videregivet til den aktuelle funktion: for at gøre dem synlige skal du vælge de berørte elementer i menuen Data. Hver databoks, der vises i Datavinduet kaldes et Display Du kan flytte det i Datavinduet som du vil, og når du højreklikker på det, ses derudover en kontekstmenu med flere indstillinger.

Verserende Afbrydelsespunkter

Verserende afbrydelsespunkter understøttes ikke af DDD. Selv om du kører kommandoen break <endnu ukendt symbol> direkte i GDB-konsollen, får du intet spørgsmål om at tilføje det som et afbrydelsespunkt. En omgåelse er at sætte egenskaben breakpoint pending som til (som standard er den sat til auto og du kan gøre det ved at eksekvere kommandoen set breakpoint pending on i GDB-konsollen eller ved at markere den beslægtede kommando i dialogen GDB Settings (Edit>GDB Settings ...).
Nu kan du ved knappen opsætte enhver gyldig streng som et afbrydelsespunkt (verserende eller ej). Men pas på! Der er en drilsk ulempe. Det første ikke-verserende afbrydelsespunkt, du opretter, efter at du har opsat et verserende bliver overskygget af det. Når du åbner dialogen Breackpoints (Source>Breakpoints...), vil du se, at det ikke-verserende afbrydelsespunkt ikke kan slettes og at dets egenskaber ikke kan sættes. Enhver handling, du udfører på det ikke-verserende afbrydelsespunkt, selv gennem kontekstmenuen i Source Window, vil blive udført på det verserende.
Tag alligevel ikke fejl, dette er udelukkende et DDD brugerflade-problem: Selv om det er nedtonet, er det ikke-verserende afbrydelsespunkt indstillet og programmet vil stoppe ved det, og i alle tilfælde kan det håndteres direkte gennem GDB-konsollen. Når det verserende afbrydelsespunkt er slettet, kan det ikke verserende også håndteres gennem DDD-front-enden.

Delte Objekthændelser

For at aktivere delte objekthændelser kan du give kommandoen set stop-on-solib-events 1 i GDB-konsollen eller markere elementet Stopping for Shared Library Events i dialogen GDB Settings (Edit>GDB Setting...)

Åbning af kildefiler

Du kan lede efter kildefiler gennem dialogen Open Source (File>Open Source...): her, i redigeringsfeltet Filter kan du indtaste en streng fx  : "*main*" (der bruges globbing regler) og enhver kildefil, der indeholder et kendt symbol vil blive matchet mod denne streng, når du klikker på knappen Filter nederst. Du kan se flere detaljer om funktionaliteterne i dialogen Open Source, når du klikker på knappen Help.

Debugning med Eclipse CDT under Linux

1- Tilføj ny debugningskonfiguration (libreoffice).

2- I Main tab-> C/C++ Application, blad frem filen soffice.bin, som skulle være i : {your build path}/libreoffice/instdir/program/soffice.bin. (Sørg for at have aktiveret dubug i din prototype).

3- I projektfeltet tilføjer du projektet libreoffice.

4- Klik på ”Select other“ i vinduet Debug-indstillinger.

5- Marker ”Use configuration specific settings“ og vælg ”Standard Attach to Process Launcher“.

Sørg for at have disse parametre på fanebladet Debugger: - Debugger: gdb/mi - GDB debugger: gdb - GDB kommandofil: .gdbinit. - GDB kommandosæt: Standard (Linux). - Protokol: mi. - Marker ”Use full file path to set breakpoints“.

7- Klik på anvend og luk.

8- Modificer debugger timeout for at forebygge denne meddelelse under debugning. ”Target is not responding (timed out)“ Gå til Window -> Preferences -> C/C++ -> Debug -> GDB MI og indstil debugger timeout til 200000 ms og launch timeout til 300000 ms.

9- Hvis du bruger Ubuntu er det sidste trin før debugning af libreoffice at modificere ptrace_scope for at gøre den mindre restriktiv. Det skulle forebygge denne meddelelse: "Could not attach to process. If your uid matches the uid of the target process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try again as the root user. For more details, see /etc/sysctl.d/10-ptrace.conf". Du behøver kun at sætte ptrace_scope til 0 i /etc/sysctl.d/10-ptrace.conf.

10- God fornøjelse med at debugge og indsætte afbrydelsespunkter i eclipse efter forgodtbefindende.

Debugning med WinDbg eller Visual Studio (under Windows)

I Visual Studio kan kald-stakkene i begyndelsen virke unyttige, aktiver Microsoft Symbol Server i konfigurationen: Tools ▸ Options ▸ Debugging ▸ Symbols og klik på "Symbol Servers".

Se information om, hvor du sætter WinDbg eller Visual Studio op til at debugge TDFs release builds med downloadede symboler se How to get a backtrace with WinDbg.

Deaktiver tilpasningsallokatoren til memcheck manuelt

Det anbefalede måde at bruge valgrind/memcheck på er at køre soffice --valgrind eller at eksportere miljøvariablen VALGRIND=memcheck, som automatisk vil gøre det følgende for dig.

Som standard bruger LibreOffice en tilpasset hukommelsesallokator, så vlagrind vil ikke være i stand til give de fulde resultater, medmindre denne er deaktiveret, deaktiver den ved kørselstid med ...

$ export G_SLICE=always-malloc

Dette er med overlæg det samme variabelnavn og -værdi, som deaktiverer glib's anderledes tilpasningsallokator for at gøre det lettere at debugge. Den kan også deaktiveres ved byggetid med

$ ./autogen.sh --with-alloc=system

Debugning af prototypeværktøjer

I det tilfælde at buildet brækker, når der kaldes et værktøj, som faktisk er specialbygget under byggeprocessen, er der sandsynligvis en fejl i værktøjets kode. Du kan bruge miljøvariablen BUILDTOOLTRACE til at køre byggeværktøjet i strace, valgrind eller en debugger:

make BUILDTOOLTRACE='strace' PARALLELISM=1       # kør i strace 
make BUILDTOOLTRACE='gdb --args' PARALLELISM=1     # debug med gdb 
make BUILDTOOLTRACE='$(DEVENV) /debugexe' PARALLELISM=1 # debug med Visual Studio 

Kørsel af cppunit tests

For at køre cppunit-testen foo i modullinjen gør du dette: cd bar && make CppunitTest_foo

Foo-delen i det, der vises i en non-ordret prototypelog og dens første komponent vil sædvanligvis være modulet (bar-delen); hvis ikke, kører du grep foo */*.mk, for at finde ud af det. Fx kan testkørslen, når prototypesystemet udskriver [build CUT] sw_subsequent_ooxmlexport, køres manuelt med cd sw && make CppunitTest_sw_subsequent_ooxmlexport

Debugning af cppunit-tests

Hvis en cppunit-test bryder ned på bygningstidspunktet, kan du få en debugger ind her med ...

$ export CPPUNITTRACE="gdb --args"

når du nu bygger (og gennemtvinger et ikke-parallelt build med -j1), vil gdb starte med cppunit-testen indlæst og du taster ”run“ for at eksekvere testen under gdb. This option used to be GDBCPPUNITTRACE before October 2013

Under Windows kan du starte unit-testen i Visual Studio med:

$ export CPPUNITTRACE="\"path_to_your_devenv.exe\" /debugexe"

med path_to_your_devenv.exe som den absolutte sti + devenv.exe. Dette vil starte Visual Studio og du starter testen direkte fra brugerinterfacet.

Under Mac OS X har du ikke længere adgang til gdb, som er blevet erstattet af lldb. Du kan imidlertid stadig bruge CPPUNITTRACE gennem

$ export CPPUNITTRACE="\"path_to_your_devenv.exe\" /debugexe"

Den opfører sig meget som linux, men vær opmærksom på, at kommandoerne er forskellige mellem gdb og lldb.

Hvis testen bryder ned og beklager sig over en ikke-fanget undtagelse, kan du alternativt trace en cppuunit-test for at finde det sted, den seneste undtagelse blev kastet fra, med

$ export DEBUGCPPUNIT=TRUE

som vil logge kast og gribninger i gdbtrace.log

Debugning af perfcheck og kørsel af cppunit-tests med valgrind

Præstationstests (make perfcheck) eller tests, der kører under valgrind (se afsnittene herunder) kan ikke debugges direkte. Valgrind indeholder imidlertid en gdbserver og testen kan køres, når du har eksporteret

$ export VALGRIND_GDB=TRUE

start så testen normalt og start gdb med

$ gdb workdir/LinkTarget/Executable/cppunittester

og i gdb-prompten

$ target remote | vgdb

Valgrinde (memcheck'e) cppunit-tests

På bygningstidspunktet kan du memcheck'e cppunit-testen med flere med

$ export VALGRIND=memcheck

Dette vil automatisk indstille G_SLICE=always-malloc og skulle bevirke, at cppunit-tests og hunspell-regressionstests bliver kørt under valgrind --tool=memcheck

Valgrinde (memcheck'e) selve LibreOffice

$ export VALGRIND=memcheck

Dette vil automatisk indstille G_SLICE=always-malloc og bevirke at LibreOffice til at køre sig selv under valgrind med --tool=memcheck

Valgrinde (helgrinde) cppunit-tests

På byggetidspunktet kan du helgrinde cppunit-testen med flere med

$ export VALGRIND=helgrind

Valgrinde (helgrinde) selve LibreOffice

$ export VALGRIND=helgrind

Dette vil bevirke, at LibreOffice kører sig selv uner valgrind med --tool=helgrind

Kørsel af de efterfølgende tests

Et top-niveau make check vil først lave et helt build, og så køre alle de efterfølgende tests, mens et top-niveau make subsequentcheck udelukkende vil køre alle de efterfølgende test.

Du kan også lave dem inde fra et modul eller i et modul alene.

Du kan køre en enkelt efterfølgende test via dets mål (se i foo/Module_foo.mk), fx cd sw && make -rs JunitTest_sw_complex. Delen cd foo er ikke nødvendig, med speeder processen op.

Hvis testen fejler, kan det skyldes en anden localisering end ”en-US“. I så fald kører du ”export LANG=C“ og gør et forsøg til.

Debugning af de efterfølgende tests

Der vil være en logfil fra den fejlede test, du kan se på den med en tekstbehandler:

workdir/JunitTest/<module>_<complex|unoapi>/done.log 

Logfilen vil indeholde en Java stack trace af den fejlede test og hvis soffice.bin brød ned og efterlod en kernefil, vil du også se en C++ stack trace fra nedbrudet.

Hvis der ikke er noget nedbrud, så skulle et kig på Java stack tracen henvise dig til den Java testkode, der fejlede, de mest interessante rammer er normalt i klasserne complex.<module>..." og koden til disse er i <module>/qa/complex/. Dette skulle henvise dig noget interessant UNO API-metode, som er kaldt på C++-siden i soffice.bin.

Til debugging vil dette nu starte office-installationen inde fra instdir inside of gdb:

make debugrun 

Få først den skrækkelige gdb TUI til at forsvinde med ”C-x a“ og sæt så et afbrydelsespunkt ved den fejlende metode og kør og et startcenter skulle poppe op.

Derefter kan du (i en anden teminal) køre:

make gb_JunitTest_DEBUGRUN=T <module>.subsequentcheck 

Dette vil eksekvere testen mod den kørende <soffice>soffice.bin og forhåbentligt skulle afbrydelsespunktet blive ramt, så du kan fortsætte debugningen derfra.

Debugning af qadedevOOo/unopai'ens efterfølgende tests

QadevOOo/unoapi-tests er noget besværlige at debugge.

Hvis en test fejler, er du først nødt til at finde ud af, hvilken metode, den beklagede sig over, åbn denne fil i en tekstbehandler:

workdir/JunitTest/<module>_unoapi/done.log 

I slutningen findes følgende resume, der udpeger den komponenttest, der fejlede:

Failures that appeared during scenario execution: 
         toolkit.AccessibleStatusBarItem 
1 of 53 tests failed 

Search for FAIL. Dette viser en fejl som denne:

LOG> getCharacterBounds(6) 
LOG> Text at this place:  
LOG> Character bounds outside component 
LOG> Character rect: 43, -566, 0, 0 
LOG> Component rect: 91, 2, 71, 18 
Method getCharacterBounds() finished with state FAILED 
LOG> getCharacterBounds(): PASSED.FAILED 

Hvis du scroller en smule op, ser du en linje som denne:

checking: [toolkit.AccessibleStatusBarItem::com::sun::star::accessibility::XAccessibleText] is iface: [com.sun.star.accessibility.XAccessibleText] testcode: [ifc.accessibility._XAccessibleText] 

Hvilke punkter i Java testkoden, som er eksekveret her, ifc.accessibility._XAccessibleText, svarende til qadevOOo/tests/java/ifc/accessibility/_XAccessibleText.java. Der er også en Java opsætningskode, der er specifik for den testede komponenttoolkit.AccessibleStatusBarItem i qadevOOo/tests/java/mod/_toolkit/AccessibleStatusBarItem.java.

Nu reducerer du testen en smule for hurtigere testning: Rediger den tilsvarende scenariefil, sædvanligvis kaldet <module>/qa/unoapi/<module>.sce, og fjerner alt undtagen den ene linje som svarer til den fejlede test, her AccessibleStatusBarItem, og tjek, at den stadig fejler:

Nu er den vanskelige del i dette tilfælde at finde ud af, hvor den fejlende metode er implementeret; ofte (fx i Writer) vil klassen hedde næsten det samme som den testede komponent, men i dette eksempel checkCharacterBounds Overraskende nok er det ikke aktuelt i modulet værktøjskasse, men git grep peger på accessibility/source/standard/vclxaccessiblestatusbaritem.cxx, som indeholder en VCLXAccessibleStatusBarItem::getCharacterBounds metode.

Når du først har fundet denne information, går du videre med make debugrun osv. Som beskrevet i den forrige sektion ”Debugning af de efterfølgende tests“.

Søgning efter en hukommelseskorruption under Windows ved hjælp af DrMemory

Hvis du har en nedbrudsfejl under Windows og stacktracen er inden for 'malloc' eller 'free' eller 'new' eller 'delete', har mest sandsynligt, at du har en hukommelseskorruption – ofte hører periodiske fejl også hjemme i disse grupper. Til disse tilfælde findes der et vidunderligt-nyt-værktøj (til Windows) ved navn DrMemory; du får det her: http://www.drmemory.org/

Og du er nødt til at installerde det og aktivere indsættelsen af det i din systemsti.

Du bør også få fat i en windows-prototype med debug.symboler fra: http://dev-builds.libreoffice.org/win32-debug/

Så har du brug for en konsol af en slags; for lige nu at få nogetsomhelst fornuftigt fra det værktøj, du vil køre:

drmemory -no_count_leaks -ignore_asserts -no_check_gdi -no_check_uninitialized -- soffice.exe 

Det betyder, at du kommer ret meget længere, forhåbentlig til det punkt, hvor det bryder ned med din fejl. Eftersom filvælgeren giver nedbrug i selve drmemory, Får du brug for at bruge 'seneste filer' eller kommandolinjen for være i stand til at indlæse dit dokument.

Forvent at det er – virkelig – langsomt; det er normalt :-), men det gør nogle smarte ting. Forhåbentlig vil din fejl i den sidste ende give en:

Error #7: UNADDRESSABLE ACCESS: writing 0x2b9ca0f4-0x2b9ca0f8 4 byte(s) 

fejllog, som er en alvorlig fejl og en meget nyttig sporing omkring den.

Kørsel af CppUnit-test med DrMemory

Du kan køre enhver CppUnit-test med DrMemory for at opspore ikke-initialiserede hukommelsesadgange og hukommelseshåndteringsfejl som denne:

CPPUNITTRACE="drmemory -no_check_gdi -free_max_frames 30 -suppress C:/Users/xxx/drmemory-suppressions.txt" make CppunitTest_sw_uiwriter 

Bemærk, at

  • DrMemory selv har tendens til løbe tør for hukommelse og dø, mens den rapporterer de rigelige hukommelseslækager i nogle af de større CppUnit-tests i 32-bits prototyper; for at undgå dette, kan du bruge argumenterne -no_count_leaks -no_check_handle_leaks .
  • DrMemory har tendens til at knuse sig til stop (eller i det mindste blev 2 timer uafbrudt CPU-tid observeret med 1.9.0-4, før tålmodigheden slap op) under kørsel af java.exe, som er spækket med adskillige unit-tests, især CppunitTest_dbaccess_hsqldb_test, CppunitTest_dbaccess_RowSetClones og CppunitTest_services. For at omgå dette problem kan du bruge -no_follow_children eller konfigurere DrMemory til at ignorere java.exe ved at køre drconfig.exe -quiet -reg java.exe -norun. (Mærkeligt nok er jvm.dllunder kørslen mindre poblematisk: der produceres millioner af fejl, men de kan let undertrykkes, som beskrevet nedenfor.)
  • DrMemory har ikke en parallel til valgrind memcheck's --track-origins=yes, så at opspore den grundlæggende årsag til ikke-initialiserede hukommelsesadgange giver en del yderligere arbejde; i disse tilfælde bør du prøve, om du kan reproducere problemet på en anden platform for at få en bedre stack trace.
  • DrMemory rapporterer falske positive i JPEG-billeder, der er importeret af SSE“-koden i jpeg-turbohttps://github.com/DynamoRIO/drmemory/issues/540. Uheldigvis kan den gøre dette på steder langt fra JPEG-importfilteret, fx i CppunitTest_sw_globalfilter bliver UNINITIALIZED READ-fejl rapporteret under eksport af VCL Bitmap til en PNG. Omgåelsen er at tvinge jpeg-rurbo til at stoppe brugen af SSE2 ved at sætte en miljøvariabel: export JSIMD_FORCEMMX=1.
  • DrMemory rapporterer diverse andre falske positive, end dem der kan undertrykkes via argumentet -suppress.

Her er et eksempel på drmemory-suppressions.txt til falske positive, der er dukket op under kørsel af Cppunit-tests med DrMemory-1.9.0-4:

UNADDRESSABLE ACCESS 
name=suppress all UA in java.exe 
java.exe!* 

UNINITIALIZED READ 
name=suppress all UR in java.exe 
java.exe!* 

UNADDRESSABLE ACCESS 
name=suppress all UA in jvm.dll 
jvm.dll!* 

UNINITIALIZED READ 
name=suppress all UR in jvm.dll 
jvm.dll!* 

WARNING 
name=suppress all warning in jvm.dll 
jvm.dll!* 

UNADDRESSABLE ACCESS 
name=UA in JIT code from jvm.dll 
<not in a module> 
... 
jvm.dll!* 


UNINITIALIZED READ 
name=UR in JIT code from jvm.dll 
<not in a module> 
... 
jvm.dll!* 

INVALID HEAP ARGUMENT 
name=https://connect.microsoft.com/VisualStudio/feedback/details/750951/std-locale-implementation-in-crt-assumes-all-facets-to-be-allocated-on-crt-heap-and-crashes-in-destructor-in-debug-mode-if-a-facet-was-allocated-by-a-custom-allocator 
drmemorylib.dll!replace_free 
*!std::_DebugHeapDelete<> 
*!std::_Fac_node::~_Fac_node 
*!std::_Fac_node::`scalar deleting destructor' 
*!std::_DebugHeapDelete<> 
*!std::_Fac_tidy_reg_t::~_Fac_tidy_reg_t 
*!std::`dynamic atexit destructor for '_Fac_tidy_reg 
*!_CRT_INIT 
*!__DllMainCRTStartup 
*!_DllMainCRTStartup 
ntdll.dll!RtlQueryEnvironmentVariable 
ntdll.dll!LdrShutdownProcess 
ntdll.dll!RtlExitUserProcess 
KERNEL32.dll!ExitProcess 

UNINITIALIZED READ 
name=https://github.com/DynamoRIO/drmemory/issues/1824 (input UR) 
system call NtUserGetClipboardFormatName UNICODE_STRING.MaximumLength 
sysdtrans.dll!CDataFormatTranslator::getClipboardFormatName 

UNADDRESSABLE ACCESS 
name=https://github.com/DynamoRIO/drmemory/issues/1824 (input UA) 
system call NtUserGetClipboardFormatName UNICODE_STRING content 
sysdtrans.dll!CDataFormatTranslator::getClipboardFormatName 

UNINITIALIZED READ 
name=https://github.com/DynamoRIO/drmemory/issues/1824 (output1) 
sal3.dll!* 
sal3.dll!rtl_ustr_compareIgnoreAsciiCase_WithLength 
ftransl.dll!rtl::OUString::equalsIgnoreAsciiCase 
ftransl.dll!CDataFormatTranslator::findDataFlavorForNativeFormatName 
ftransl.dll!CDataFormatTranslator::getDataFlavorFromSystemDataType 
sysdtrans.dll!CDataFormatTranslator::getDataFlavorFromFormatEtc 
sysdtrans.dll!CDOTransferable::formatEtcToDataFlavor 
sysdtrans.dll!CDOTransferable::initFlavorList 
sysdtrans.dll!CDTransObjFactory::createTransferableFromDataObj 

UNINITIALIZED READ 
name=https://github.com/DynamoRIO/drmemory/issues/1824 (output2) 
sal3.dll!rtl::compareIgnoreAsciiCase 
sal3.dll!rtl_ustr_compareIgnoreAsciiCase_WithLength 
sysdtrans.dll!rtl::OUString::equalsIgnoreAsciiCase 
sysdtrans.dll!CDataFormatTranslator::isTextHtmlFormat 

UNINITIALIZED READ 
name=https://github.com/DynamoRIO/drmemory/issues/1825 
system call NtGdiAddFontResourceW parameter value #4 
GDI32.dll!GdiAddFontResourceW 
GDI32.dll!AddFontResourceExW 
vcllo.dll!ImplAddTempFont 
vcllo.dll!WinSalGraphics::AddTempDevFont 
vcllo.dll!OutputDevice::AddTempDevFont 

UNINITIALIZED READ 
name=https://github.com/DynamoRIO/drmemory/issues/1827 
* 
KERNELBASE.dll!WaitNamedPipeW 
sal3.dll!osl_createPipe 

UNINITIALIZED READ 
name=CPython custom allocator PyObject_Realloc 
python??_d.dll!PyObject_Realloc 

UNINITIALIZED READ 
name=CPython custom allocator PyObject_Free 
python??_d.dll!PyObject_Free 

UNINITIALIZED READ 
name=CPython custom allocator PyObject_Realloc 
python??.dll!PyObject_Realloc 


UNINITIALIZED READ 
name=CPython custom allocator PyObject_Free 
python??.dll!PyObject_Free 

WARNING 
name=prefetching unaddressable memory in jpeg-turbo 
vcllo.dll!jsimd_idct_islow_sse2 
vcllo.dll!jsimd_idct_islow 
vcllo.dll!decompress_data 

Debugning af C++ UNO livscykler

Henvisningstællingen gemmes som m_refCount, så fx pause i UNO objektkonstruktør and tilføj en overvågning til den for at se, hvem der tager delt ejerskab over objektet.

(gdb) watch * (&m_refCount)

bin/refcount_leak.py

Hvis acquire() and release() kald til en UNO service ikke matches, vil objektet bløde. Der findes et skript, der kan parse gdb backtraces og prøve at balancere acquire() og release() og sortere dem efter, hvor sandsynlige de er.

Se vink om syntaks i kommentarerne øverst i bin/refcount_leak.py i kernelageret.

Bemærk, at gdb er længe om udskrive backtraces; 4000 backtraces tager > 3 timer på en laptop med en aktuel 15W TDP CPU.

En anden ulempe er, at resultatet af skriptet har brug for nogen manuel fortolkning, men den kan opdage nøgne opkald til acquire(), som lækker.

Instrumentet uno::Henvisning

Der findes en patch on gerrit, som tilføjer dummy tildeling af hukommelse til hvert patch on gerrit så at standardværktøjer som valgrind og adressesanitør kan opdage det, når selve uno::Reference er lækket.

Dette er måske den letteste måde at opspore en læk på, men ulemperne er, at den ikke opdage nøgne acquire() kald og at instrumenteringen kræver en fuld ombygning; også den supplerende globale lås kan få configmgr til at gå i baglås.

Bemærk, at rettelsen aktuelt er ukomplet og måske ikke opdager lækning fra uno::Any og rtl::Reference (men det kan være ordnet).

Påstande og logning

Se [[Udvikling/GenerelProgrammeringsRetningslinjer#Påstande og logning ==

Miljøvariabler

  • SAL_NO_MOUSEGRABS=1 forhindrer LibreOffice fra at overtage musen under debugning på under X11.

Makroer, der kontroller Debug-kode

  • Makroen NDEBUG er standardmåden at kontrollere standardfunktionaliteten assert på. Den er defineret i almindelige produktionsprototyper, står udefineret for --enable-debug/--enable-dbgutil (bemærk, at det ”de“aktiverer påstande at definere den).
  • Makroerne SAL_LOG_INFO og SAL_LOG_WARN kontrollerer om hhv. SAL_INFO og funktionaliteteten SAL_WARN fra include/sal/log.hxx er aktiveret. De står udefinerede i almindelige produktionsprototyper, defineret --enable-debug/--enable-dbgutil. Hvis defineret, kontrolleres deres adfærd af miljøvariablen SAL_LOG (se detaljer i dokumentationen af include/sal/log.hxx).
  • Makroen DBG_UTIL aktiverer supplerende kode, som potentielt påvirker ABI-kompatibiliteten ved at ændre offentlige datastrukturer. (Så at aktivere den er en alt-eller-intet beslutning; generelt kan du ikke bygge bare en del af LibreOffice med den aktiveret. Af historiske grunde kontrollerer den også de forældede makroer DBG_ASSERT osv. fra include/tools/debug.hxx.) Den står udefineret i produktionsprototyper og defineret i --enable-dbgutil.
  • Makroen _GLIBCXX_DEBUG aktiverer nyttige påstande i implementeringen af ibstdc++ STL, som påvirker ABI-kompatibiliteten; den aktiveres også at --enable-dbgutil på ELF-baserede GCC-platforme (TODO: dette kunne fungere på alle GCC-platforme, hvis bare nogen testede det).
  • Makroen OSL_DEBUG_LEVEL kontrollerer supplerende, potentielt ekscessivt kostbar debug-kode (men som ikke påvirker kompatibiliteten). Den er defineret som 0 i almindelige produktionsprototyper, som 1 i --enable-debug/--enable-dbgutil (der aktiverer de forældede OSL_ASSERT osv. makroer fra include/osl/diagnose.h) og som 2 eller højere med et udtrykkeligt dbglevel=N argument til make.

Debugge Python-komponenter i LibreOffice

For at debugge indlæsningen af Python Script Provider, sætter du variablen DEBUG=0 i pythonloader.py.

For at debugge skripts med Python Script Provider sætter du variablen PYSCRIPT_LOG_LEVEL=DEBUG og (valgfrit) PYSCRIPT_LOG_STDOUT=0 til at omdirigere til filen $UserInstallation/Scripts/python/log.txt.

For at se metodekaldene, der eksekveres af pyuno Python/UNO-broen, sætter du mijøvariablerne PYUNO_LOGLEVEL=ARGS og (valgfrit) PYUNO_LOGTARGET=mylogfile.

Debugge Java-komponenter i LibreOffice

Hvis du vil debugge de dele af LibreOffice, som er implementeret i Java, vil GDB måske være mindre nyttig.

Det kan lejlighedvist være nyttige bare at få Java-niveau stack trace, som når der er baglås, hvor Java-koden potentielt er involveret; værktøjet jstack kan udskrive den, bare giv den soffice.bins proces-id som argument.

Til en faktisk debugning er en IDE mest bekvemt (selv om der også er en kommandolinje debugger jdb); Der en beskrivelse af, hvordan tingene skal sættes op til Eclipse og NetBean på denne OOo forum posting.