ˇ ´ UCEN ´I TECHNICKE´ V BRNEˇ VYSOKE BRNO UNIVERSITY OF TECHNOLOGY
ˇ ´ICH TECHNOLOGI´I FAKULTA INFORMACN ´ ´ U ˚ USTAV INTELIGENTN´ICH SYSTEM FACULTY OF INFORMATION TECHNOLOGY DEPARTMENT OF INTELLIGENT SYSTEMS
´ ´I AUTOMATIZOVANE´ METODY HLEDAN ˇ ´ICH ˇ CHYB V PREKLADA C
´ RSK ˇ ´ PRACE ´ BAKALA A BACHELOR’S THESIS
´ AUTOR PRACE AUTHOR
BRNO 2008
¨ PETR MULLER
ˇ ´ UCEN ´I TECHNICKE ´ V BRNE ˇ VYSOKE BRNO UNIVERSITY OF TECHNOLOGY
ˇ ´ICH TECHNOLOGI´I FAKULTA INFORMACN ´ ´ U ˚ USTAV INTELIGENTN´ICH SYSTEM FACULTY OF INFORMATION TECHNOLOGY DEPARTMENT OF INTELLIGENT SYSTEMS
´ ´I AUTOMATIZOVANE´ METODY HLEDAN ˇ ´ICH ˇ CHYB V PREKLADA C AUTOMATED METHODS OF FINDING BUGS IN COMPILERS
ˇ ´ PRACE ´ BAKALA´ RSK A BACHELOR’S THESIS
´ AUTOR PRACE
¨ PETR MULLER
AUTHOR
´ VEDOUC´I PRACE SUPERVISOR
BRNO 2008
ˇ VOJNAR, Ph.D. ´S doc. Ing. TOMA
Abstrakt Tato pr´ace se zab´ yv´a aplikac´ı metody fuzz testing k testov´an´ı pˇrekladaˇc˚ u a interpret˚ u. V prvn´ı ˇc´asti pojedn´av´a o pˇrekladaˇc´ıch, optimalizac´ıch a chyb´ach typick´ ych pro optimalizuj´ıc´ı pˇrekladaˇc. Analyzuje vhodnost metod statick´e a dynamick´e anal´ yzy pro hled´an´ı tˇechto chyb a jako vhodnou navrhuje dynamickou metodu fuzz testov´an´ı. V r´amci pr´ace byl implementov´an n´astroj pro testov´an´ı pˇrekladaˇc˚ u pouˇz´ıvaj´ıc´ı tuto metodu, kter´ y byl aplikov´ an na nˇekolik pˇr´ıpad˚ u, pˇriˇcemˇz se podaˇrilo nal´ezt s´erii chyb v rozˇs´ıˇren´ ych pˇrekladaˇc´ıch, a to vˇcetnˇe napˇr. GCC.
Kl´ıˇ cov´ a slova pˇrekladaˇce, testov´an´ı, gener´ator n´ahodn´ ych vˇet, gramatiky, Python, jazyk C
Abstract This thesis discusses an application of the fuzz testing method for testing compilers and interpreters. In the first part, it deals with compilers, optimizations, and bugs typical for an optimizing compiler. It analyzes applicability of static and dynamic analysis methods for searching such bugs and proposes dynamic fuzz testing as suitable for this task. A compiler testing tool suite using this method was implemented within this thesis and applied on several real compilers, including GCC, in which the tool revealed a series of bugs.
Keywords compilers, testing, random sentence generator, grammars, Python, C language
Citace Petr M¨ uller: Automatizovan´e metody hled´an´ı chyb v pˇrekladaˇc´ıch, bakal´aˇrsk´a pr´ace, Brno, FIT VUT v Brnˇe, 2008
Automatizovan´ e metody hled´ an´ı chyb v pˇ rekladaˇ c´ıch Prohl´ aˇ sen´ı Prohlaˇsuji, ˇze jsem tuto bakal´aˇrskou pr´aci vypracoval samostatnˇe pod veden´ım doc. Ing. Tom´aˇse Vojnara, Ph.D. Uvedl jsem vˇsechny liter´arn´ı prameny a publikace, ze kter´ ych jsem ˇcerpal. ....................... Petr M¨ uller 14. kvˇetna 2008
Podˇ ekov´ an´ı Dˇekuji doc. Tom´aˇsi Vojnarovi za veden´ı t´eto pr´ace a mnoho podnˇetn´ ych rad a pˇripom´ınek. R´ad bych tak´e podˇekoval panu Benovi Levensonovi za podporu a veden´ı m´e pr´ace v oboru testov´ an´ı pˇrekladaˇc˚ u.
c Petr M¨
uller, 2008. Tato pr´ ace vznikla jako ˇskoln´ı d´ılo na Vysok´em uˇcen´ı technick´em v Brnˇe, Fakultˇe informaˇcn´ıch technologi´ı. Pr´ ace je chr´ anˇena autorsk´ym z´ akonem a jej´ı uˇzit´ı bez udˇelen´ı opr´ avnˇen´ı autorem je nez´ akonn´e, s v´yjimkou z´ akonem definovan´ych pˇr´ıpad˚ u.
Obsah ´ 1 Uvod
3
2 Pˇ rekladaˇ ce a optimalizace 2.1 Pˇrekladaˇce a interprety . . . . 2.1.1 Pˇrekladaˇce . . . . . . . 2.1.2 Interprety . . . . . . . . 2.2 Principy konstrukce pˇrekladaˇc˚ u 2.2.1 Front-end . . . . . . . . 2.2.2 Middle-end . . . . . . . 2.2.3 Back-end . . . . . . . . 2.3 Optimalizace . . . . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
4 4 4 4 4 5 6 6 6
3 Chyby v pˇ rekladaˇ c´ıch a metody jejich hled´ an´ı 3.1 Chyby v pˇrekladaˇc´ıch . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 Obecn´e chyby v programech . . . . . . . . . . . . . . . . . . . . 3.1.2 Chyby typick´e pro pˇrekladaˇce . . . . . . . . . . . . . . . . . . . 3.2 Hled´an´ı a testovac´ı pokryt´ı r˚ uzn´ ych typ˚ u chyb . . . . . . . . . . . . . 3.2.1 Statick´a anal´ yza . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.2 Dynamick´a anal´ yza . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.3 Metody testov´an´ı pˇrekladaˇc˚ u c´ılen´e na jejich typick´e probl´emy
. . . . . . .
. . . . . . .
. . . . . . .
7 7 7 7 9 10 10 11
. . . . . . . . .
12 12 13 15 15 15 20 21 22 22
. . . . . . . . . . . . . . . . . . .
23
5 Aplikace na re´ aln´ e pˇ r´ıpady 5.1 Metodika . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2 Testovan´e pˇrekladaˇce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3 Klasifikace v´ ysledk˚ u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25 25 26 26
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
4 N´ avrh syst´ emu pro testov´ an´ı pˇ rekladaˇ c˚ u 4.1 Principy metody fuzz testing . . . . . . . 4.2 Celkov´ y n´avrh a implementace . . . . . . 4.3 Spitter . . . . . . . . . . . . . . . . . . . . 4.3.1 Gener´ator . . . . . . . . . . . . . . 4.3.2 Director . . . . . . . . . . . . . . . 4.3.3 Pˇr´ıklad cel´eho procesu . . . . . . . 4.3.4 Pomocn´e moduly . . . . . . . . . . 4.4 Builder . . . . . . . . . . . . . . . . . . . 4.5 Comparator . . . . . . . . . . . . . . . . . 4.6 Pokryt´ı pro pˇrekladaˇce specifick´ ych chyb navrˇzen´ ym syst´emem . . . . . . . . . . . .
1
. . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
5.4
5.5
5.6 5.7
5.8
Pˇr´ıpad 1: gcc s r˚ uzn´ ymi optimalizacemi 5.4.1 Prostˇred´ı a podm´ınky . . . . . . 5.4.2 Spitter . . . . . . . . . . . . . . . 5.4.3 Randprog . . . . . . . . . . . . . 5.4.4 fuzz . . . . . . . . . . . . . . . . 5.4.5 Zhodnocen´ı experimentu . . . . . Pˇr´ıpad 2: GCC, TCC . . . . . . . . . . . 5.5.1 Prostˇred´ı a podm´ınky . . . . . . 5.5.2 Spitter . . . . . . . . . . . . . . . 5.5.3 Randprog . . . . . . . . . . . . . 5.5.4 fuzz . . . . . . . . . . . . . . . . Zhodnocen´ı experimentu . . . . . . . . . Pˇr´ıpad 3: icc, gcc . . . . . . . . . . . . . 5.7.1 Prostˇred´ı a podm´ınky . . . . . . 5.7.2 Spitter . . . . . . . . . . . . . . . 5.7.3 Randprog . . . . . . . . . . . . . 5.7.4 fuzz . . . . . . . . . . . . . . . . 5.7.5 Zhodnocen´ı experimentu . . . . . Pˇr´ıpad 4: gcc-stable, gcc-bleeding edge . 5.8.1 Prostˇred´ı a podm´ınky . . . . . . 5.8.2 Spitter . . . . . . . . . . . . . . . 5.8.3 Randprog . . . . . . . . . . . . . 5.8.4 fuzz . . . . . . . . . . . . . . . . 5.8.5 Zhodnocen´ı experimentu . . . . .
6 Z´ avˇ er 6.1 Zhodnocen´ı v´ ysledk˚ u . . . . . . . . . 6.1.1 Gener´atory n´ahodn´eho k´odu 6.1.2 Syst´em pro testov´an´ı . . . . . 6.2 Zhodnocen´ı pouˇzitelnosti metody . . 6.3 Dalˇs´ı v´ yvoj . . . . . . . . . . . . . . A Nalezen´ e chyby A.1 Chyba 1 . . . A.2 Chyba 2 . . . A.3 Chyba 3 . . . A.4 Chyba 4 . . . A.5 Chyba 5 . . . A.6 Chyba 6 . . . A.7 Chyba 7 . . . A.8 Chyba 8 . . . A.9 Chyba 9 . . . A.10 Chyba 10 . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
2
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
27 27 27 27 27 29 29 29 29 29 30 30 30 30 31 31 31 33 33 33 34 34 34 34
. . . . .
36 36 36 37 37 37
. . . . . . . . . .
38 38 39 40 41 42 43 44 45 46 47
Kapitola 1
´ Uvod Neodmyslitelnou souˇc´ast´ı ˇretˇezce n´astroj˚ u pro v´ yvoj modern´ıch poˇc´ıtaˇcov´ ych program˚ u jsou pˇrekladaˇce a interprety programovac´ıch nebo jin´ ych jazyk˚ u. V´ yvoj aplikac´ı v assemblerech je v souˇcasnosti z´aleˇzitost´ı vestavˇen´ ych platforem a vysoce optimalizovan´ ych operac´ı. Naprost´a vˇetˇsina program˚ u je ps´ana v kompilovan´ ych nebo interpretovan´ ych programovac´ıch jazyc´ıch. Ty umoˇzn ˇuj´ı program´atorovi formulovat program na vysok´em stupni abstrakce a obstar´avaj´ı mnoho automatizovan´ ych u ´kol˚ u, kter´ ymi se potom program´ator nemus´ı zab´ yvat. Pˇrekladaˇce jsou velmi komplexn´ı n´astroje a poskytuj´ı sv´ ym uˇzivatel˚ u st´ale dokonalejˇs´ı a sloˇzitˇejˇs´ı sluˇzby, napˇr. automatickou paralelizaci pro v´ıceprocesorov´e ˇci v´ıcej´ adrov´e syst´emy, masivn´ı optimalizace apod. Vˇetˇsina program´ator˚ u je na tˇechto sluˇzb´ach z´ avisl´ a, protoˇze je mimo jejich moˇznosti tvoˇrit ruˇcnˇe stejnˇe v´ ykonn´e programy, jako je tomu s pouˇzit´ım pˇrekladaˇc˚ u a dalˇs´ıch modern´ıch n´astroj˚ u. Z´aroveˇ n je tvorba program˚ u bez tˇechto n´astroj˚ u neefektivn´ı a n´akladn´a. Jako kaˇzd´ y program, i pˇrekladaˇce obsahuj´ı chyby. Modern´ı pˇrekladaˇce jsou typicky velmi sloˇzit´e syst´emy, kter´e bˇehem aˇz stovek pr˚ ubˇeh˚ u k´odem mohou naprosto zmˇenit jeho podobu. Vzhledem k v´ ysadn´ımu postaven´ı pˇrekladaˇc˚ u v ˇretezci v´ yvoje program˚ u je tedy velmi podstatn´a jejich spr´avn´a funkˇcnost. Tato pr´ace si klade za c´ıl zhodnotit moˇznosti automatizace testov´an´ı pˇrekladaˇc˚ u, na z´akladˇe tˇechto znalost´ı implementovat syst´em pro hled´an´ı chyb v nich a otestovat jeho aplikaci v praxi. Tato pr´ace se zamˇeˇruje na testov´an´ı pˇrekladaˇc˚ u jazyka C, ale obecn´e principy zde popsan´e je moˇzn´e aplikovat i na testov´an´ı nejen pˇrekladaˇce kompilovan´ ych jazyk˚ u, ale i pro hled´an´ı chyb v interpretech. Prvn´ı ˇc´ast pr´ace obsahuje teoretick´ y z´aklad pro testovan´ı pˇrekladaˇc˚ u a zahrnuje z´ akladn´ı definice z oblasti. D´ale pojedn´av´a o chyb´ach, kter´e se v pˇrekladaˇc´ıch vyskytuj´ı a metod´ ach, kter´e je moˇzn´e pˇri jejich hled´an´ı pouˇz´ıt. Druh´a ˇc´ast obsahuje n´avrh a popis implementace syst´emu, kter´ y tyto metody popsan´e v prvn´ı ˇc´asti uv´ad´ı v r´amci t´eto pr´ace do praxe pˇriˇcemˇz vyuˇz´ıv´a fakt, kter´e byly zjiˇstˇeny v prvn´ı ˇc´asti, k u ´pln´emu a efektivnˇejˇs´ımu testovac´ıho pokryt´ı pˇrekladaˇce. Ve tˇret´ı ˇc´asti byl implementovan´ y prototyp syst´emu aplikov´an na nˇekter´e rozˇs´ıˇren´e pˇrekladaˇce jazyka C. Je zde pops´ana metodika testov´an´ı, jeho pr˚ ubˇeh a analyzov´any v´ ysledky testov´an´ı.
3
Kapitola 2
Pˇ rekladaˇ ce a optimalizace Tato kapitola zpracov´av´a teoretick´ y z´aklad pro oblast pˇrekladaˇc˚ u. Uv´ad´ı z´akladn´ı principy konstrukce pˇrekladaˇce, jeho obvykl´e souˇc´asti a jejich funkci. Zab´ yv´a se tak´e optimalizacemi, kter´e modern´ı pˇrekladaˇce nad k´odem prov´adˇej´ı pro vyˇsˇs´ı efektivitu pˇreloˇzen´eho programu.
2.1 2.1.1
Pˇ rekladaˇ ce a interprety Pˇ rekladaˇ ce
Pˇrekladaˇc [6] (t´eˇz kompil´ator, z angl. compiler ) je program, schopn´ y ˇc´ıst program v jednom jazyce – zvan´em zdrojov´em – a pˇreloˇzit ho do ekvivalentn´ıho programu zapsan´em v jin´em jazyce – c´ılov´em. Pojem pˇrekladaˇc je typicky pouˇz´ıv´an pro programy prov´ adˇej´ıc´ı pˇreklad programu zapsan´eho ve vyˇsˇs´ım programovac´ım jazyce do jazyka niˇzˇs´ıho, nejˇcastˇeji strojov´eho k´odu poˇc´ıtaˇce. Pˇr´ıkladem jazyk˚ u, kter´e jsou obvykle pˇr´ımo pˇrekl´ad´any jsou C, C++ nebo rodina jazyk˚ u Fortran. C´ılem je z abstraktn´ıho z´apisu algoritmu z´ıskat spustiteln´ y program. Programy prov´adˇej´ıc´ı opaˇcn´ y pˇreklad se naz´ yvaj´ı dekompil´ atory. Existuj´ı i programy, kter´e prov´adˇej´ı pˇreklad mezi jazyky zhruba stejn´e u ´rovnˇe abstrakce.
2.1.2
Interprety
Interpret je naproti tomu program, kter´ y m´ısto pˇrekladu programy napsan´e ve vyˇsˇs´ım programovac´ım jazyce pˇr´ımo spouˇst´ı, tj. interpretuje. Interpret b´ yv´a obvykle postaven jako virtu´aln´ı stroj pˇr´ımo prov´adˇej´ıc´ı pˇr´ıkazy programovac´ıho jazyka nebo instrukce vnitˇrn´ıho mezik´ odu. V´ yhodou tohoto pˇr´ıstupu je vyˇsˇs´ı abstrakce od hardwaru a operaˇcn´ıho syst´emu, coˇz s sebou nese vˇetˇs´ı pohodl´ı, robustnost, menˇs´ı n´achylnost k chyb´am a lepˇs´ı moˇznosti diagnostiky. Naproti tomu b´ yv´a program pˇreloˇzen´ y do strojov´eho k´ odu pˇrekladaˇcem mnohem rychlejˇs´ı neˇz ekvivalentn´ı program prov´adˇen´ y interpretem, a to z d˚ uvodu vyˇsˇs´ıho mnoˇzstv´ı reˇzijn´ıho k´odu. Typick´ ymi z´astupci interpretovan´ ych jazyk˚ u jsou modern´ı dynamick´e programovac´ı jazyky, tedy napˇr. Python, Ruby nebo Lua.
2.2
Principy konstrukce pˇ rekladaˇ c˚ u
Zp˚ usob˚ u konstrukce pˇrekladaˇc˚ u je v´ıce, ale nejˇcastˇeji se uplatˇ nuje dˇelen´ı programu na dvˇe ˇc´asti. Prvn´ım je front-end, kter´ y je orientovan´ y na zdrojov´ y jazyk, a back-end, orientovan´ y na c´ılov´ y jazyk. Nˇekter´e pˇrekladaˇcov´e syst´emy, jako napˇr´ıklad GCC, kter´e maj´ı rozs´ ahlou 4
ˇc´ast optimalizac´ı nad mezik´odem, s touto ˇc´ast´ı pracuj´ı jako se samostatnou [16] a naz´ yvaj´ı ji middle-end.
2.2.1
Front-end
V ˇc´asti pˇrekladaˇce nazvan´e front-end se obvykle prov´adˇej´ı tyto kroky: lexik´aln´ı anal´ yza, syntaktick´a anal´ yza, s´emantick´a anal´ yza a pˇreklad do mezik´odu. Konstrukce front-endu je silnˇe v´az´ana na zdrojov´ y jazyk a mˇela by b´ yt nez´avisl´a na c´ılov´em jazyce. Lexik´ aln´ı anal´ yza ˇ ast pˇrekladaˇce prov´adˇej´ıc´ı lexik´ C´ aln´ı anal´ yzu se naz´ yv´a lexik´aln´ı analyz´ator (angl. scanner ). Lexik´aln´ı anal´ yza je u ´vodn´ı krok pˇrekladu, kter´ y v ˇcist´em textu rozezn´av´a tzv. lex´emy (angl. tokeny) – prvky zdrojov´eho jazyka. Ty n´aslednˇe pˇred´av´a syntaktick´emu analyz´ atoru. Lexik´ aln´ı analyz´atory b´ yvaj´ı implementov´any obvykle pomoc´ı regul´arn´ıch v´ yraz˚ u. Pro tvorbu scanner˚ u jsou bˇeˇznˇe pouˇz´ıvan´e automatizovan´e n´astroje, napˇr. Lex [13]. Syntaktick´ a anal´ yza Syntaktick´a anal´ yza rozezn´av´a v sekvenci lexik´aln´ıch symbol˚ u syntaktickou strukturu podle pravidel gramatiky pˇr´ısluˇsn´eho jazyka. V´ ystup t´eto ˇc´asti pˇrekladaˇce zachycuje strukturu programu ve tvaru vhodn´em k dalˇs´ımu zpracov´an´ı, typicky ve tvaru derivaˇcn´ıho stromu. ˇ asti pˇrekladaˇce prov´adˇej´ıc´ı syntaktickou anal´ C´ yzu se ˇr´ık´a syntaktick´ y analyz´ator (angl. parser ). Metod sestrojen´ı syntaktick´eho analyz´atoru je v´ıce. Z´akladn´ımi dvˇema pˇr´ıstupy (kter´e se pak d´ale dˇel´ı) jsou pˇr´ıstup shora-dol˚ u a zdola-nahoru. R˚ uzn´e pˇr´ıstupy [10] k sestrojen´ı syntaktick´eho analyz´atoru produkuj´ı parsery schopn´e zpracovat r˚ uznˇe sloˇzit´e gramatiky. Parsery se ˇcasto generuj´ı automatizovan´ ymi n´astroji, napˇr. Yacc [12]. S´ emantick´ a anal´ yza S´emantick´ y analyz´ator v derivaˇcn´ım stromu rozezn´av´a a zpracov´av´a informace o v´ yznamu pˇr´ıkaz˚ u. Uplatˇ nuje s´emantick´a omezen´ı a oznamuje chyby v s´emantice programu. Pˇ reklad do mezik´ odu Vˇetˇsina pˇrekladaˇc˚ u nepˇrekl´ad´a pˇr´ımo z jednoho jazyka do druh´eho (i kdyˇz i takov´e pˇrekladaˇce existuj´ı), ale pouˇz´ıvaj´ı jeˇstˇe tˇret´ı intern´ı reprezentaci. Existuj´ı dva z´akladn´ı typy intern´ı reprezentace: [6] • Syntaktick´e a jin´e stromy. V tomto pˇr´ıpadˇe je intern´ı reprezentace generov´ ana jako v´ ystup f´az´ı syntaktick´e a s´emantick´e anal´ yzy. • Serializovan´a reprezentace. V´ ystup s´emantick´e anal´ yzy se pˇrevede na posloupnost instrukc´ı jazyka intern´ı reprezentace. Typick´ ym pˇr´ıkladem je tˇr´ıadresov´ y k´od. Sloˇzit´e pˇrekladaˇce mohou m´ıt i nˇekolik intern´ıch reprezentac´ı k´odu [16]. V tom pˇr´ıpadˇe se ˇc´ast obsluhuj´ıc´ı mezik´od obvykle neˇrad´ı do pˇredn´ı (front-end ), ale do stˇredn´ı vrstvy (middle-end ). Pˇrevody mezi intern´ımi reprezentacemi pˇredstavuj´ı sloˇzit´e ˇc´asti pˇrekladaˇc˚ u, psan´e obvykle ruˇcnˇe.
5
2.2.2
Middle-end
Middle-end se naz´ yv´a ta ˇc´ast pˇrekladaˇce, kde se na u ´rovni intern´ı reprezentace prov´ adˇej´ı optimalizace a jin´e zmˇeny pˇr´ımo v logice programu. Jen nˇekter´e projekty naz´ yvaj´ı tuto ˇca´st pˇrekladaˇce middle-end, jin´e tento term´ın nepouˇz´ıvaj´ı a operuj´ı jen s dvˇema ˇc´astmi. V t´eto pr´aci je term´ın middle-end pouˇz´ıv´an. Kromˇe operac´ı nad intern´ı reprezentac´ı programu prob´ıhaj´ı v t´eto ˇc´asti optimalizace, kter´e maj´ı za u ´kol upravit program pro nˇejak´ y u ´ˇcel – obvykle k vyˇsˇs´ımu v´ ykonu nebo k minimalizaci velikosti v´ ysledn´eho programu. Optimalizacemi se bl´ıˇze zab´ yv´a ˇc´ast 2.3.
2.2.3
Back-end
Back-end je ˇc´ast v´azan´a na c´ılov´ y jazyk, obvykle strojov´ y k´od nebo k´od v aassembleru V´ ysledn´a podoba intern´ı reprezentace programu se zde pˇrev´ad´ı do c´ılov´eho jazyka. Probl´emy ˇreˇsen´e v t´eto f´azi jsou velmi r˚ uzn´e, ale pˇr´ıkladem mohou b´ yt n´asleduj´ıc´ı, kter´e jsou nejobvyklejˇs´ı: • Efektivn´ı vyuˇzit´ı instrukˇcn´ı sady c´ılov´eho procesoru, vˇcetnˇe sloˇzit´ ych a specializovan´ ych instrukc´ı. • Alokace registr˚ u. Vzhledem k v´ ykonu je vhodn´e maximum dat umist’ovat do registr˚ u m´ısto do pamˇeti. • Paralelizace. Vyuˇzit´ı moˇznost´ı c´ılov´e architektury k paraleln´ımu bˇehu vhodn´ ych ˇca´st´ı programu na multi/hyperskal´arn´ıch procesorech, popˇr. syst´emech s v´ıce j´adry nebo procesory.
2.3
Optimalizace
Rozˇs´ıˇren´e programovac´ı jazyky a jejich s´emantick´e konstrukce nejsou ze sv´e podstaty vytvoˇren´e pro optim´aln´ı vyuˇzit´ı zdroj˚ u programy, kter´e jsou v nich naps´any. Jsou uzp˚ usoben´e prim´arnˇe k snadn´emu vyj´adˇren´ı algoritmu ˇclovˇekem a jeho n´asledn´emu pˇrekladu do strojov´eho k´odu. Pokud bychom pˇrekl´adali program jen jako sekvenci na sobˇe nez´avisl´ ych pˇr´ıkaz˚ u a kaˇzd´ y pˇr´ıkaz doslovnˇe pˇreloˇzili do strojov´ ych instrukc´ı, vznikne mnoˇzstv´ı neefektivn´ıho k´odu. Pro optim´aln´ı vyuˇzit´ı zdroj˚ u (ˇcas, pamˇet’, m´ısto na disku) je tedy nutn´e program zefektivnit. Toto m˚ uˇze b´ yt provedeno bud’ program´atorem, pokud pˇrizp˚ usob´ı svuj program poˇzadavk˚ um na optim´aln´ı vyuˇzit´ı zdroj˚ u, nebo automaticky pˇrekladaˇcem. Pr´ avˇe v pˇrekladaˇc´ıch se skryv´a velk´ y potenci´al pro zefektivnˇen´ı programu. Bˇehem pˇrekladu m´ a pˇrekladaˇc k dispozici velmi detailn´ı informace o podobˇe pˇrekl´adan´eho programu. Tyto informace lze analyzovat a na z´akladˇe t´eto anal´ yzy automaticky rozezn´avat instrukce, kter´e lze vypustit nebo nahradit jin´ ymi bez zmˇeny funkce programu. Modern´ı pˇrekladaˇce obsahuj´ı rozs´ahlou sadu ˇcasto velmi sloˇzit´ ych optimalizac´ı. Obecnˇe se optimalizac´ı naz´ yv´ a jak´ ykoliv proces na kter´ekoliv u ´rovni tvorby programu, kter´ y zefektivˇ nuje jeho vyuˇzit´ı kritick´ ych zdroj˚ u. V t´eto pr´aci se z d˚ uvodu jej´ıho zamˇeˇren´ı na pˇrekladaˇce pouˇz´ıv´a term´ın “optimalizace” pro zmˇeny k´odu, kter´e automaticky vykon´ av´ a kompil´ator pˇri pˇrekladu programu. Konkr´etn´ım pˇr´ıkladem optimalizac´ı [6], kter´e m˚ uˇze pˇrekladaˇc nad k´odem prov´adˇet m˚ uˇze b´ yt eliminace mrtv´eho k´odu, ˇs´ıˇren´ı konstant, nebo pˇr´ım´ y v´ ypoˇcet v´ yraz˚ u, jejichˇz v´ ysledek je zn´am uˇz v dobˇe pˇrekladu.
6
Kapitola 3
Chyby v pˇ rekladaˇ c´ıch a metody jejich hled´ an´ı Jako vˇsechny programy, i pˇrekladaˇce obsahuj´ı chyby. Tato kapitola se zab´ yv´a chybami, kter´e se vyskytuj´ı v pˇrekladaˇc´ıch, d˚ usledky jejich v´ yskytu, a metodami jejich hled´an´ı.
3.1
Chyby v pˇ rekladaˇ c´ıch
Pˇrekladaˇc je d˚ uleˇzitou souˇc´ast´ı v´ yvojov´eho ˇretˇezce. Chyby v nˇem tedy mohou m´ıt masivn´ı d˚ usledky. Takov´ ym m˚ uˇze b´ yt napˇr´ıklad zbrˇzdˇen´ı v´ yvoje programu, kdy mus´ı b´ yt k´ od, kter´ y pˇrekladaˇc nedok´aˇze pˇreloˇzit, nahrazen jin´ ym. Jin´ ym pˇr´ıkladem m˚ uˇze b´ yt zan´aˇsen´ı chyb vznikl´ ych ˇspatn´ ym pˇrekladem do programu, popˇr´ıpadˇe tich´ y pˇreklad neplatn´eho k´ odu s nedefinovan´ ym chov´an´ım. Takov´e chyby se zvl´aˇstˇe ˇspatnˇe diagnostikuj´ı, protoˇze vyplynou na povrch v pˇreloˇzen´em programu, nikoliv pˇrekladaˇci sam´em. Samotn´emu urˇcen´ı zdroje chyby v pˇrekladaˇci tedy pˇredch´ az´ı f´aze, kdy se chyba hled´a na nespr´avn´em m´ıstˇe, coˇz zbyteˇcnˇe spotˇrebov´av´a zdroje a pˇri pokusu o opravu m˚ uˇze zp˚ usobit zanesen´ı dalˇs´ı chyby.
3.1.1
Obecn´ e chyby v programech
Pˇrekladaˇce, zvl´aˇstˇe modern´ı pˇrekladaˇcov´e syst´emy pro vˇetˇs´ı mnoˇzstv´ı jazyk˚ u a architektur, jsou typicky velmi komplexn´ı programy. Jako takov´e jsou pochopitelnˇe n´achyln´e pro v´ yskyt bˇeˇzn´ ych program´atorsk´ ych chyb, stejn´ ych jako v jak´emkoli jin´em programu. Pro jazyk C jsou takov´ ymi typick´ ymi chybami napˇr´ıklad ˇspatn´a pr´ace s ukazateli, ignorov´an´ı moˇzn´ ych chybov´ ych stav˚ u nebo nedostateˇcn´a opatˇren´ı pˇri pr´aci s polemi koneˇcn´e d´elky. Rozˇs´ıˇren´e pˇrekladaˇce (GCC, Visual C++ Compiler) tyto bˇeˇzn´e chyby, kter´e by u obyˇcejn´eho programu obvykle vedly ke zhroucen´ı nebo nedefinovan´emu chov´an´ı, zachyt´avaj´ı vnitˇrn´ımi mechanismy (zachyt´av´an´ı sign´al˚ u, makra assert a jin´e) a interpretuj´ı je jako tzv. ICE – Internal Compiler Error.
3.1.2
Chyby typick´ e pro pˇ rekladaˇ ce
Kromˇe bˇeˇzn´ ych chyb se v pˇrekladaˇc´ıch vyskytuj´ı chyby, kter´e jsou pro nˇe specifick´e. Jedn´ a se obvykle o s´emantick´e chyby – pˇrekladaˇc funguje tak, jak byl naprogramov´an, ale byl naprogramov´an ˇspatnˇe. Tyto chyby se daj´ı roztˇr´ıdit do nˇekolika kategori´ı a n´aslednˇe klasifikovat. Open-source komunita zab´ yvaj´ıc´ı se pˇrekladaˇci obvykle pouˇz´ıv´a kategorie, kter´e definuje projekt GCC [1], nebo alespoˇ n kategorie velmi podobn´e. 7
Klasifikace chyb dle projektu GCC Accepts-invalid Pˇrekladaˇc tiˇse akceptuje a pˇreloˇz´ı neplatn´ y k´od, i kdyˇz by ho mˇel odm´ıtnout. Chov´an´ı neplatn´eho k´ odu nen´ı definov´ano a v´ ysledkem je nepˇredv´ıdateln´e chov´ an´ı preloˇzen´eho programu. Jedn´a se o velmi v´aˇznou chybu – chyba se projev´ı vadn´ ym chov´an´ım pˇreloˇzen´eho programu a proces urˇcov´an´ı zdroje chyby je dlouh´ y a n´ aroˇcn´ y. Assemble-failure Pˇrekladaˇc selˇze pˇri generov´an´ı v´ ysledn´eho k´odu. D˚ uvody mohou b´ yt r˚ uzn´e, napˇr. dvojit´a definice jednoho symbolu. Protoˇze se tento typ chyby projev´ı uˇz pˇri pˇrekladu, a to aˇz po f´azi pˇrijet´ı k´odu, jedn´a se o nepˇr´ıliˇs z´avaˇzn´ y typ chyby. Compile-time-hog Pˇreklad trv´a neadekv´atnˇe dlouho, nebo se nezastav´ı. Pˇr´ıˇcinou b´ yv´ a neoptimalizovav´ y pr˚ ubˇeh k´ odem, kdy se vlivem podoby vnitˇrn´ı reprezentace pˇrekladaˇc zacykl´ı nebo zvol´ı velmi neoptim´aln´ı cestu. Jedn´a se o m´alo z´avaˇzn´ y typ chyby, vyvstane uˇz pˇri pouˇzit´ı pˇrekladaˇce a pomoc´ı profilovac´ıch n´ astroj˚ u nebo vnitˇrn´ı introspekce pˇrekladaˇce je moˇzn´e relativnˇe snadno neoptim´aln´ı m´ısto programu odhalit. Diagnostic Selh´an´ı diagnostick´eho hl´aˇsen´ı. Pˇrekladaˇc nezobraz´ı chybov´e hl´aˇsen´ı nebo varov´an´ı, kdyˇz by mˇel, popˇr. je takov´e hl´aˇsen´ı chybn´e nebo zav´adˇej´ıc´ı. ICE-on-invalid Pˇrekladaˇc se zhrout´ı pˇri zpracov´an´ı neplatn´eho k´odu. Jedn´a se o nepˇr´ıliˇs z´avaˇznou chybu. Neplatn´ y k´od by mˇel b´ yt stejnˇe odm´ıtnut, takˇze zhroucen´ı pˇrekladaˇce je pouze chyba robustnosti pˇri oˇsetˇrov´an´ı neplatn´eho k´odu. ICE m˚ uˇze b´ yt zp˚ usobeno i bˇeˇznou program´atorskou chybou. ICE-on-valid Pˇrekladaˇc se zhrout´ı pˇri zpracov´av´an´ı platn´eho k´odu. Jedn´a se o z´ avaˇznou chybu. Platn´ y k´od by mˇel b´ yt pˇreloˇzen, a selh´an´ı v tomto u ´kolu je tedy selh´ an´ı z´akladn´ıho u ´ˇcelu pˇrekladaˇce. Diagnostika b´ yv´a obvykle nepˇr´ıliˇs obt´ıˇzn´a, s pouˇzit´ım modern´ıch program´atorsk´ ych n´astroj˚ u m˚ uˇze b´ yt pomˇernˇe snadn´e identifikovat m´ısto kde ke zhroucen´ı doˇslo a data nebo instrukce, kter´e ho zp˚ usobily. ICE m˚ uˇze b´ yt zp˚ usobeno i bˇeˇznou program´atorskou chybou. Link-failure Pˇrekladaˇc vygeneruje objekt, kter´ y nejde sestavit (slinkovat) s jin´ ym k´ odem. Jedn´a se o m´enˇe z´avaˇznou variantu chyby wrong-code, protoˇze vyjde najevo uˇz pˇri linkov´an´ı programu, coˇz n´asleduje obvykle hned po pˇrekladu. D˚ uvody selh´an´ı sestaven´ı jsou podobn´e jako u chyby assemble-failure. Memory-hog Pˇrekladaˇc spotˇrebov´av´a pˇri bˇehu neadekv´atn´ı mnoˇzstv´ı pamˇeti. Pˇr´ıˇciny a ostatn´ı znaky jsou podobn´e jako u chyby compile-time-hog. Missed-optimization Pˇrekladaˇc nezaregistruje ˇc´ast k´odu, kterou by mohl optimalizovat. Velmi ˇspatnˇe odhaliteln´a chyba, zejm´ena z toho d˚ uvodu, ˇze se projevuje aˇz v niˇzˇs´ım v´ ykonu pˇreloˇzen´eho programu, coˇz je zpozorovateln´e jen pˇri d˚ ukladn´em testov´ an´ı nebo opravdu v´ yrazn´em sn´ıˇzen´ı v´ ykonu. Z´avaˇznost z´avis´ı na velikosti sn´ıˇzen´ı v´ ykonu aplikac´ı. Register-allocator Chyba typu missed-opimization zp˚ usoben´a vadnou funkc´ı alok´ atoru registr˚ u. Pˇrekladaˇc v tomto pˇr´ıpadˇe nevyuˇzije moˇznosti uloˇzit hodnotu do registru m´ısto do pamˇeti, i kdyˇz by to v danou chv´ıli bylo moˇzn´e. Rejects-valid Pˇrekladaˇc odm´ıtne platn´ y k´od. Jedn´a se o stˇrednˇe z´avaˇznou chybu, kter´ a br´an´ı pouˇzit´ı kompil´atoru. Diagnostika nen´ı n´aroˇcn´a, chyba se projevuje uˇz pˇri pˇrekladu. 8
Wrong-code Pˇrekladaˇc generuje vadn´ y k´od – k´od s jin´ ym v´ yznamem neˇz mˇel p˚ uvodn´ı platn´ y zdrojov´ y k´od. Jedn´ a se o nejz´avaˇznˇejˇs´ı chybu pˇrekladaˇce. Chyba se projevuje aˇz vadn´ ym chov´an´ım pˇreloˇzen´eho programu, pˇriˇcemˇz nen´ı moˇzn´e ve zdrojov´em k´ odu vystopovat chybu – protoˇze tam ˇz´adn´a nen´ı. Chybu je nutn´e izolovat a objevit na u ´rovni c´ılov´eho jazyka pˇreloˇzen´eho programu, coˇz je zdlouhav´e a n´aroˇcn´e. Klasifikace z´ avaˇ znosti chyb Tabulka 3.1 uv´ad´ı klasifikaci z´avaˇznosti chyb v pˇrekladaˇc´ıch, vypracovanou v r´amci t´eto pr´ace. V u ´vahu byla br´ana tˇri hlediska – dopad na uˇzivatele, zp˚ usob, jak´ ym se chyba projev´ı, a diagnostika. Dopad na uˇzivatele byl rozdˇelen do tˇr´ı u ´rovn´ı: • N´ızk´y : Dopad na uˇzivatele je n´ızk´ y, nebr´an´ı mu ve spr´avn´em pouˇzit´ı pˇrekladaˇce. • Stˇredn´ı: Omezuje moˇznosti uˇzivatele a nut´ı jej pouˇz´ıvat nestandardn´ı ˇreˇsen´ı. Pˇreklad´ a programy kter´e funguj´ı spr´ avnˇe, ale s urˇcit´ ymi omezen´ımi. • Vysok´y : Zabraˇ nuje uˇzivateli v pouˇzit´ı pˇrekladaˇce, nebo generuje neplatn´e programy. Zp˚ usob, kter´ ym se chyba projev´ı, je tak´e troj´ı: • Pˇri pˇrekladu: Chyba se objev´ı jiˇz pˇri pˇrekladu. • Po pˇrekladu: Chyba se projev´ı bezprostˇrednˇe po pouˇzit´ı v´ ystupu pˇrekladaˇce. • Neprojev´ı: Chyba se neprojev´ı v souvislosti s pˇrekladaˇcem. Diagnostiku dˇel´ıme tak´e do tˇr´ı u ´rovn´ı: • Zjevn´e : Zjevnˇe se jedn´a o chybu pˇrekladaˇce. • Maskovan´e : Chyba se objevuje pˇri pouˇzit´ı pˇrekladaˇce, ale zd´a se, ˇze pˇrekladaˇc je v poˇr´adku. • Skryt´e : Chyba je skryt´a a projevuje se pˇri pouˇzit´ı v´ ysledn´eho programu. Souvislost se ˇspatnou funkc´ı pˇrekladaˇce vyjde najevo aˇz pˇri d˚ ukladn´e anal´ yze defektu.
3.2
Hled´ an´ı a testovac´ı pokryt´ı r˚ uzn´ ych typ˚ u chyb
Obecn´e metody hled´an´ı chyb v pˇrekladaˇc´ıch se v z´asadˇe neliˇs´ı od metod pouˇz´ıvan´ ych pro jin´e programy. Obt´ıˇz spoˇc´ıv´a ve faktu, ˇze pˇrekladaˇce jsou programy s nekoneˇcn´ ym prostorem moˇzn´ ych vstup˚ u, a nav´ıc nen´ı moˇzn´e dopˇredu jednoznaˇcnˇe urˇcit, jak m´a pˇreklad vypadat – pro jeden vstupn´ı program P obvykle existuje v´ıce moˇzn´ ych ekvivalentn´ıch reprezentac´ı v c´ılov´em k´odu. To v´ yraznˇe sniˇzuje moˇznosti testov´an´ı spr´avnosti v´ ystupu.
9
Tabulka 3.1: Klasifikace typ˚ u chyb v pˇrekladaˇc´ıch Typ chyby accepts-invalid assemble-failure compile-time-hog diagnostic ice-on-invalid ice-on-valid link-failure memory-hog missed-optimization register-allocator rejects-valid wrong-code
3.2.1
Dopad na uˇ zivatele Vysok´ y Vysok´ y Stˇredn´ı N´ızk´ y N´ızk´ y Vysok´ y Vysok´ y Stˇredn´ı/N´ızk´a Stˇredn´ı Stˇredn´ı Vysok´ y Vysok´ y
Zp˚ usob projevu Neprojev´ı se Po pˇrekladu Pˇri pˇrekladu Pˇri pˇrekladu Pˇri pˇrekladu Pˇri pˇrekladu Po pˇrekladu Pˇri pˇrekladu Neprojev´ı se Neprojev´ı se Pˇri pˇrekladu Neprojev´ı se
Diagnostika Skryt´e Maskovan´e/Zjevn´e Zjevn´e Maskovan´e Zjevn´e Zjevn´e Maskovan´e/Zjevn´e Maskovan´e Skryt´e Skryt´e Maskovan´e/zjevn´e Skryt´e
Statick´ a anal´ yza
Statick´a anal´ yza je proces, kdy se zjiˇst’uj´ı informace o programu bez jeho spuˇstˇen´ı. M˚ uˇze se jednat o sbˇer dat anal´ yzou zdrojov´eho k´odu, reprezentace v mezik´odu bˇehem pˇrekladu nebo anal´ yzu objektov´eho a bin´arn´ıho tvaru pˇreloˇzen´eho programu. Konkr´etn´ı metody jsou r˚ uzn´e – nejbˇeˇznˇejˇs´ı jsou n´astroje, kter´e analyzuj´ı zdrojov´ y k´od a hledaj´ı vzorce indikuj´ıc´ı typick´e program´atorsk´e chyby, nebo n´astroje typu lint, kter´e hledaj´ı podezˇrel´e s´emantick´e konstrukce. Takov´e n´astroje tak´e dok´ aˇz´ı napˇr´ıklad nal´ezt vˇetve programu, kter´e se nikdy neprovedou, nebo naopak takov´e, kter´e se provedou vˇzdy, pˇrestoˇze jsou zanoˇreny v podm´ınˇen´em pˇr´ıkazu. Moˇznost´ı hledan´ ych vzor˚ u je mnoho a je moˇzn´e staticky hledat i chyby, kter´e nejsou jen obecn´e s´emantick´e chyby, ale chyby v logice programu. Moˇznosti metod statick´e anal´ yzy pro testov´an´ı pˇrekladaˇc˚ u jsou omezen´e na hled´ an´ı chyb typu ICE, kter´e jsou ˇcasto zp˚ usobeny bˇeˇzn´ ymi program´atorsk´ ymi chybami.
3.2.2
Dynamick´ a anal´ yza
Dynamickou anal´ yzou se naz´ yv´a proces, kdy o programu z´ısk´av´ame informace jeho spouˇstˇen´ım. Spuˇstˇen´ım programu v prostˇred´ı virtu´aln´ıho procesoru m˚ uˇzeme napˇr´ıklad detekovat chyby, kter´e z k´odu nemus´ı b´ yt zcela zjevn´e a tud´ıˇz je obt´ıˇzn´e je odhalit statick´ ymi metodami. Typick´ ym probl´emem, kter´ y je moˇzn´e odhalit pomoc´ı spuˇstˇen´ı jsou probl´emy soubˇehu (angl. race condition), popˇr´ıpadˇe probl´emy vznikl´e nespr´avn´ ym pouˇzit´ım pamˇeti v jazyce C. Pˇr´ıkladem n´astroje pro dynamickou anal´ yzu program˚ u je soubor utilit valgrind. Obsahuje n´astroje urˇcen´e pro detekci pamˇet’ov´ ych chyb, chyb spojen´ ych s vl´akny, detektor soubˇeh˚ u, a profilovac´ı n´astroje vol´an´ı funkc´ı a vyuˇzit´ı hromady (heapu). Valgrind [9] pouˇz´ıv´ a pr´avˇe pˇr´ıstup virtu´aln´ıho procesoru, kter´ y prov´ad´ı testovan´e instukce, ke kter´ ym jednotliv´e n´astroje pˇrid´avaj´ı svoje vlastn´ı informace pro anal´ yzu.
10
3.2.3
Metody testov´ an´ı pˇ rekladaˇ c˚ u c´ılen´ e na jejich typick´ e probl´ emy
Vˇsechny obecn´e n´astroje pro zajiˇstˇen´ı kvality softwaru lze samozˇrejmˇe pouˇz´ıt i k hled´ an´ı chyb v pˇrekladaˇc´ıch – je to tak´e software. Sofistikovan´e n´astroje dok´aˇz´ı naj´ıt mnoho chyb, ale nejsou c´ılen´e. Vzhledem k nejednoznaˇcnosti spr´avn´eho v´ ystupu pˇrekladaˇce obecn´e metody selh´avaj´ı v detekci s´emantick´ ych chyb, zejm´ena spr´avnˇe implementovan´ ych ˇspatn´ ych princip˚ u. Tyto chyby lze naj´ıt jen velmi ˇspatnˇe. Neexistuje mnoho metod, kter´ ymi je moˇzn´e urˇcit, zda pˇrekladaˇc pro nˇejak´ y vstup vytvoˇril spr´avn´ y v´ ystup. Jednou z cest je pokr´ yt kaˇzdou metodu nebo funkci uvnitˇr pˇrekladaˇce, kter´a nˇejak manipuluje s k´odem, kvalitn´ımi jednotkov´ ymi testy. Pokud jsou jednotliv´e ˇc´asti pˇrekladaˇce navrˇzeny dostateˇcnˇe ortogon´alnˇe, a kaˇzd´a metoda nebo funkce m´a jasnˇe definovan´e vstupy, v´ ystupy a ˇcinnost, pak je moˇzn´e jednotkov´ ymi testy zjiˇst’ovat, zda kaˇzd´ y takov´ y u ´sek k´odu dˇel´a to, co je definov´ano. Zde plat´ı, ˇze spr´avn´a ˇcinnost syst´emu tvoˇren´eho mnoha menˇs´ımi jednotkami (kter´e musej´ı b´ yt co nejv´ıce ortogon´aln´ı) se ovˇeˇruje snadnˇeji [11], pokud ovˇeˇrujeme ˇcinnost jednotliv´ ych souˇc´ast´ı, neˇz pokud bychom ovˇeˇrovali chov´an´ı cel´eho syst´emu. Jinou metodou, jej´ımˇz pouˇzit´ım je moˇzn´e se zamˇeˇrit pr´avˇe na spr´avn´ y v´ ystup pˇrekladaˇce, je tzv. fuzz testing, na kter´em byl zaloˇzen syst´em d´ale navrˇzen´ y v t´eto pr´aci. Princip t´eto medody a jej´ı praktick´a implementace pro toto pouˇzit´ı je pops´an v n´asleduj´ıc´ı kapitole.
11
Kapitola 4
N´ avrh syst´ emu pro testov´ an´ı pˇ rekladaˇ c˚ u V t´eto kapitole pˇredstav´ıme n´avrh metody pro testov´an´ı spr´avnosti v´ ystupu pˇrekladaˇce a implementaci syst´emu, kter´ y tuto metodu vyuˇz´ıv´a.
4.1
Principy metody fuzz testing
Z´akladem cel´eho syst´emu je metoda zvan´a fuzz testing. Jedn´a se o metodu testov´an´ı typu u, kter´e jsou black-box 1 , kdy se pro program generuje velk´e mnoˇzstv´ı testovac´ıch vstup˚ programem zpracov´any. Chov´an´ı programu se pot´e analyzuje. Je jasn´e, ˇze zcela n´ ahodnˇe generovan´ y vstup bude pravdˇepodobnˇe neplatn´ y, a proto se za selh´an´ı povaˇzuje zhroucen´ı programu. Pokud program dok´aˇze n´ahodn´a data jakkoliv zpracovat, v´ ysledkem testu je u ´spˇech. V´ yhodou t´eto metody je jej´ı aˇz trivi´aln´ı implementace a automatizace. Je snadn´e generovat testovac´ı pˇr´ıpady, pˇredkl´adat je program˚ um a zjiˇst’ovat, zda se zhrout´ı. Velk´ a rychlost generov´an´ı testovac´ıch pˇr´ıpad˚ u znamen´a, ˇze je moˇzn´e otestovat mnoho pˇr´ıpad˚ uv relativnˇe kr´atk´em ˇcase. To zvyˇsuje pravdˇepodobnost, ˇze nˇekter´a n´ahodn´a data aktivuj´ı dosud skrytou chybu v programu, kterou spust´ı jen data s urˇcit´ ymi charakteristikami. Z´ aroveˇ n tato metoda dok´aˇze program vystavovat podm´ınk´am, jak´e by ˇclovˇek-tester pravdˇepodobnˇe nevytvoˇril. ´ celem testu samozˇrejmˇe nen´ı zjiˇst’ovat prost´ Uˇ y fakt, zda program dok´aˇze zvl´adnout libovoln´ y neplatn´ y vstup. Prav´ ym d˚ uvodem je, ˇze zhroucen´ı programu na jak´ ychkoliv datech m˚ uˇze ukazovat na neoˇsetˇrenou speci´aln´ı situaci, zpravidla typu pˇreteˇcen´ı z´asobn´ıku (buffer overflow ).2 Vzhledem k tomu, ˇze chyby tohoto typu jsou hlavn´ım zdrojem bezpeˇcnostn´ıch probl´em˚ u, je vhodn´e takto testovat zejm´ena pro s´ıt’ov´e sluˇzby a jin´e programy, kter´e dost´ avaj´ı data ke zpracov´an´ı po s´ıti nebo z jin´eho ned˚ uvˇeryhodn´eho zdroje. Schopnost zhroutit server s´ıt’ov´e sluˇzby pouh´ ym pˇredloˇzen´ım speci´aln´ıch dat je bezpeˇcnostn´ı chyba sama o sobˇe [15]. Fuzz testing je moˇzn´e pouˇz´ıt velmi c´ılenˇe, a to i na pˇrekladaˇce. Pˇr´ıkladem m˚ uˇze b´ yt pr´ace Christiana Lindiga [14], kter´ y vytvoˇril program, testuj´ıc´ı dodrˇzov´an´ı volac´ıch konvenc´ı pˇrekladaˇci jazyka C pro r˚ uzn´e architektury. Pˇri testov´an´ı samotn´em dok´azal velmi rychle naj´ıt chyby ve zpracov´an´ı sloˇzitˇejˇs´ıch struktur v pˇr´ıpadˇe, ˇze byly pouˇzity jako variadick´ y 1 black-box je testovac´ı metoda zamˇeˇren´ a na zkoum´ an´ı chov´ an´ı syst´emu na z´ akladˇe jeho vnˇejˇs´ıch projev˚ u, bez znalosti vnitˇrn´ı implementace. 2 buffer overflow je chyba, kdy se program pokouˇs´ı zapsat data za hranice m´ısta v pamˇeti, kter´e je jim vyhrazeno [8]
12
argument [18]. Zde navrˇzen´ y syst´em pro testov´an´ı pˇrekladaˇc˚ u se zamˇeˇruje na schopnost pˇrekladaˇce dodat spr´avnou reprezentaci programu v c´ılov´em jazyce. Vzhledem k tomuto z´amˇeru je nutn´e jednoduchou koncepci fuzz testov´an´ı rozˇs´ıˇrit. V pˇr´ıpadˇe, ˇze bychom generovali zcela n´ahodn´a data, byla by naprost´a vˇetˇsina vstupn´ıch dat neplatn´ ym k´odem, kter´ y by pˇrekladaˇc mˇel odm´ıtnout. Byla by tedy testov´ana pouze ta ˇc´ast k´odu pˇrekladaˇce, kter´a odm´ıt´ a neplatn´e vstupy. Je nutn´e sestrojit gener´ator n´ ahodn´eho platn´eho k´odu zdrojov´eho jazyka, kter´ y pˇrekladaˇc nebude m´ıt probl´em pˇreloˇzit. T´ım se pokr´ yv´a cel´ y proces pˇrekladu programu a je tak moˇzn´e aktivovat chyby v kaˇzd´em k´odu, kter´ y je zapojen do procesu pˇrekladu. Dalˇs´ım probl´emem, kter´ y je pak zapotˇreb´ı rozˇreˇsit, je zjiˇst’ov´an´ı, zda je v´ ystup pˇrekladaˇce platn´ y. Jak bylo ˇreˇceno v ˇc´asti 3.2, pro jeden program obvykle existuje v´ıce platn´ ych pˇreklad˚ u, v z´avislosti napˇr. na pouˇzit´em pˇrekladaˇci, optimalizaˇcn´ıch procesech, nebo na u ´rovni, s jakou pˇrekladaˇc dok´aˇze vyuˇz´ıt specializovan´ ych instrukc´ı c´ılov´eho jazyka (instrukc´ı procesoru). Nen´ı tedy moˇzn´e porovn´avat samotn´ y v´ ystup, protoˇze nem˚ uˇzeme jednoznaˇcnˇe urˇcit, zda je pˇreklad spr´avn´ y nebo ne. Pˇr´ıstup naˇseho syst´emu je pˇreloˇzit program dvakr´ at nebo v´ıcekr´at v odliˇsn´ ych podm´ınk´ach, coˇz m˚ uˇze b´ yt pˇreloˇzen´ı jin´ ym pˇrekladaˇcem, nebo pˇreloˇzen´ı stejn´ ym pˇrekladaˇcem s odliˇsn´ ym nastaven´ım. Pˇreloˇzen´e programy se spust´ı a zaznamen´a se jejich v´ ystup. Program by mˇel produkovat stejn´ y v´ ystup bez ohledu na to, jak´ ym pˇrekladaˇcem byl preloˇzen. Testem je tedy srovn´an´ı obou v´ ystup˚ u, popˇr´ıpadˇe jin´ a pomocn´a krit´eria (porovn´an´ı u ´spˇeˇsnosti pˇrekladu nebo zp˚ usobu ukonˇcen´ı programu). Pokud je u ´spˇeˇsnost pˇrekladu a v´ ystup pˇreloˇzen´eho programu stejn´ y, pak je v´ ysledkem testu u ´spˇech. Pokud se liˇs´ı, pak to m˚ uˇze indikovat chybu v jednom z pˇrekladaˇc˚ u, protoˇze je nepravdˇepodobn´e, ˇze by stejn´a chyba byla pˇr´ıtomn´a v obou na sobˇe nez´avisl´ ych pˇrekladaˇc´ıch. Tomuto pˇr´ıstupu mus´ı b´ yt pˇrizp˚ usoben i gener´ator testovac´ıcho k´odu, kter´ y by mˇel produkovat programy s deterministick´ ym chov´an´ım. Programy by mˇely tak´e poskytovat na v´ ystup dostatek informac´ı o sv´em vnitˇrn´ım stavu, aby bylo moˇzn´e zjistit anom´alie.
4.2
Celkov´ y n´ avrh a implementace
Navrˇzen´ y syst´em pro testov´an´ı je rozdˇelen na tˇri ˇc´asti, spojen´e dohromady jednoduch´ ym r´amcem. Prvn´ı a nejd˚ uleˇzitˇejˇs´ı ˇc´ ast´ı je gener´ator testovac´ıho zdrojov´eho k´odu. Syst´em je navrˇzen tak, aby se dal pouˇz´ıt jak´ ykoliv program, kter´ y vyprodukuje pouˇziteln´ y vstup. Obsahuje ale sv˚ uj vlastn´ı gener´ator k´odu, jm´enem Spitter. V´ ystup gener´atoru je pot´e vstupem pro modul Builder, kter´ y vyprodukuje vˇsechny v´ ystupy k anal´ yze. Tyto v´ ystupy jsou pot´e analyzov´any modulem Comparator, kter´ y rozhoduje, zda byla nalezena anom´alie nebo ne. V pˇr´ıpadˇe ˇze ano, pak se zdrojov´ y k´od a vˇsechny v´ ystupy uschovaj´ı k pozdˇejˇs´ı anal´ yze. Jeden test probˇehne velmi rychle, a proto je moˇzn´e v kr´atk´em ˇcase otestovat velk´e mnoˇzstv´ı testovac´ıch pˇr´ıpad˚ u. T´ım je dosaˇzeno vˇetˇs´ıho pokryt´ı k´odu testovan´ ych pˇrekladaˇc˚ u. Vˇetˇsina k´odu v cel´em syst´emu je naps´ana ve skriptovac´ım jazyce Python, ˇc´ast utilit je naps´ana v jazyce pˇr´ıkazov´eho interpretu BASH. Oba interpretovan´e jazyky byly zvoleny z d˚ uvodu snazˇs´ı implementace, zejm´ena v pˇr´ıpadˇe gener´atoru testovac´ıho k´odu jazyka C. Cel´ y syst´em je pˇrehlednˇe graficky zn´azornˇen na obr´azku 4.1.
13
Obr´azek 4.1: Sch´ema syst´emu
14
4.3
Spitter
V´ ystupem Spitteru je program v jazyce C, kter´ y je v pozdˇejˇs´ıch f´az´ıch pˇrekl´ad´an a analyzov´an. Jedn´a se o ˇr´ızen´ y gener´ator n´ahodn´ ych vˇet jazyka C. Skl´ad´a se ze dvou hlavn´ıch ˇc´ast´ı, pojmenovan´ ych Director a Generator, a dalˇs´ıch tˇr´ı menˇs´ıch. Podrobnˇejˇs´ı popis vˇsech ˇc´ast´ı je uveden v t´eto sekci.
4.3.1
Gener´ ator
Gener´ ator je modul, obsahuj´ıc´ı jednu tˇr´ıdu. Jedin´e, co generator prov´ad´ı je tvorba n´ahodn´ ych vˇet podle gramatiky. Princip gener´atoru je totoˇzn´ y [17] s konstrukc´ı syntaktick´eho analyz´atoru pomoc´ı techniky rekurzivn´ıho sestupu, jen postup je obr´acen´ y. Parser uˇz´ıvaj´ıc´ı rekurzivn´ı sestup je program, kter´ y se skl´ad´a ze vz´ajemnˇe rekurzivn´ıch funkc´ı, kter´e rozezn´avaj´ı jednotliv´e jazykov´e konstrukce. Sch´ema syntaktick´eho analyz´atoru pak kop´ıruje podobu gramatiky jazyka. Gener´ator je implementov´an podobnˇe. Implementuje metodu generate(symbol), kter´ a z´ısk´ a od Directoru seznam moˇzn´ ych rozvoj˚ u. Z nich se n´ahodnˇe vybere jeden rozvoj. N´ ahodn´ y v´ ybˇer je ovlivnˇen v´ahami, kter´e mohou b´ yt jednotliv´ ym rozvoj˚ um v seznamu pˇriˇrazeny. Rozvoj je reprezentov´an dalˇs´ım seznamem, kter´ y obsahuje vˇsechny symboly v rozvoji. Pro kaˇzd´ y symbol v rozvoji se provede n´asleduj´ıc´ı operace: pokud se jedn´a o termin´al, pak se pˇr´ımo zap´ıˇse do v´ ystupn´ıho bufferu, kter´ y udrˇzuje jiˇz vygenerovan´e symboly. V pˇr´ıpadˇe, ˇze se jedn´a o netermin´al, pak se pro nˇej rekurzivnˇe zavol´a metoda generate a n´avratov´ a hodnota se zap´ıˇse do bufferu. V pˇr´ıpadˇe ˇze se jedn´a o voliteln´ y termin´al, pak se n´ ahodnˇe zjist´ı, zda se bude symbol generovat a v pˇr´ıpadˇe ˇze ano, pak je postup stejn´ y jako u netery princip, kter´ y min´alu. Pˇrehlednˇe to ukazuje pseudok´od 4.3.1. Jedn´a se o velmi zjednoduˇsen´ zn´azorˇ nuje jen samotn´e generov´an´ı. Skuteˇcn´a implementace je sloˇzitˇejˇs´ı, obsahuje dalˇs´ı obsluˇzn´ y k´od (logov´an´ı a oˇsetˇrov´an´ı speci´aln´ıch situac´ı), a nav´ıc funkci n´avratu k pˇredchoz´ım verz´ım, pokud nˇejak´ y symbol z nˇejak´eho d˚ uvodu nemohl b´ yt vygenerov´an (tzv. backtracking). Tato funkce, pˇrestoˇze je v gener´atoru implementov´ana, nen´ı syst´emem vyuˇz´ıv´ ana, protoˇze s n´ı nedok´aˇze korektnˇe pracovat vrstva Director. Pokud by toto omezen´ı bylo odstranˇeno, umoˇznilo by to pouˇz´ıt agresivnˇejˇs´ı potlaˇcov´an´ı rekurzivn´ıch probl´em˚ u popsan´ ych n´ıˇze, protoˇze by jiˇz nebylo nutn´e ponech´avat kaˇzd´emu symbolu alespoˇ n jeden rozvoj i v pˇr´ıpadˇe, ˇze i ten by byl za norm´aln´ıch okolnost´ı podle konfigurace vypuˇstˇen. Jednoduch´ y gener´ator sestrojen´ y v´ yˇse popsan´ ym zp˚ usobem trp´ı v´ yrazn´ ymi probl´emy v pˇr´ıpadˇe, ˇze generovan´a gramatika obsahuje pravidla, kter´a jsou rekurzivn´ı. V programovac´ıch jazyc´ıch jde zejm´ena o pravidla popisuj´ıc´ı v´ yrazy, kdy operandem vˇetˇsiny oper´ ator˚ u mohou b´ yt znovu dalˇs´ı v´ yrazy. V gramatice jazyka C [18] jsou v´ yrazy pops´any vˇetˇs´ım mnoˇzstv´ım pravidel, jejichˇz hierarchie vyjadˇruje prioritu oper´ator˚ u. Vˇsechna tato pravidla jsou rekurzivn´ı, a pravidlo na nejniˇzˇs´ı u ´rovni obsahuje rozvoj se symbolem v´ yrazu opˇet na u ´rovni nejvyˇsˇs´ı. V tomto konkr´etn´ım pˇr´ıpadˇe bˇehem generov´an´ı doch´azelo k masivn´ımu zanoˇrov´an´ı generovan´ ych v´ yraz˚ u a k dosaˇzen´ı maxim´aln´ı hloubky rekurzivn´ıch vol´an´ı funkc´ı v interpretu jazyka Python. Tyto probl´emy byly vyˇreˇseny ve vrstvˇe Director pomoc´ı nˇekolika technik b´l´ıˇze popsan´ ych v sekci 4.3.2.
4.3.2
Director
´ Director je nejrozs´ahlejˇs´ı modul z cel´eho syst´emu. Ukolem Directoru je ˇr´ıdit funkci gener´atoru takov´ ym zp˚ usobem, aby v´ ystupem byl validn´ı a sem´anticky spr´avn´ y k´od. Funkce directoru jsou zaloˇzeny na tzv. s´emantick´ ych jednotk´ach. 15
Obr´azek 4.2: Pseudok´od principu metody generate def generate ( symbol ): director . reportStart ( symbol ) productions = director . getSymbol ( symbol ) selected = w e ig ht e dR a nd om S el e ct io n ( productions ) buffer = "" for symbol in selected : if symbol . type == TERMINAL : buffer += symbol . value elif symbol . type == OPTIONAL_NONTERMINAL and rand (0 ,1) < symbol . probability : buffer += generate ( symbol ) elif symbol . type == NONTERMINAL : buffer += generate ( symbol ) buffer = director . reportFinish ( symbol , buffer ) return buffer
S´ emantick´ e jednotky S´emantick´a jednotka je struktura, kter´a udrˇzuje informace o podobˇe jedn´e s´emantick´e konstrukce jazyka C. S´emantickou konstrukc´ı rozum´ıme ˇc´ast programu, kter´a nese nˇejakou informaci, kter´a mus´ı b´ yt dostupn´a i jin´ ym s´emantick´ ym jednotk´am (napˇr. pˇr´ıkaz deklarace promˇenn´e nese informaci, ˇze v nadˇrazen´em bloku je moˇzn´e pouˇz´ıt identifik´ator promˇenn´e ve v´ yrazech, jejichˇz typ je s typem promˇenn´e kompatibiln´ı). Director buduje z´asobn´ık takov´ ychto s´emantick´ ych jednotek a na z´akladˇe informac´ı, kter´e jsou v nˇem obsaˇzeny, ˇr´ıd´ı generov´an´ı. Jednotliv´e vlastnosti s´emantick´ ych jednotek jsou urˇcov´any ihned, jak jsou gener´atorem vytvoˇreny a metodou reportFinish pˇred´any pˇr´ısluˇsn´e symboly. Pˇresn´ y princip a informace o jednotliv´ ych s´emantick´ ych jednotk´ach budou pops´ any n´ıˇze. S´emantick´a jednotka udrˇzuje n´asleduj´ıc´ı informace: Promˇ enn´ e Udrˇzuje informaci, zda dan´a s´emantick´a jednotka vytv´aˇr´ı r´amec (scope) pro definici promˇenn´ ych. Implementov´an je jako slovn´ık, jehoˇz kl´ıˇcem je datov´ y typ a hodnotou je seznam identifik´ator˚ u oznaˇcuj´ıc´ıch promˇenn´e tohoto typu v tomto r´ amci. Hodnota None znamen´a, ˇze tato s´emantick´a jednotka vlastn´ı r´amec nevytv´aˇr´ı. Identifik´ ator Udrˇzuje informaci, zda dan´a s´emantick´a jednotka m´a vlastn´ı identifik´ ator. Implementov´an je jako ˇretˇezec, obsahuj´ıc´ı pˇr´ısluˇsn´ y identifik´ator. Pokud mu zat´ım identifik´ator nebyl pˇriˇrazen (coˇz je pˇr´ıpad napˇr. s´emantick´e jednotky deklarace pˇredt´ım, neˇz je vygenerov´an symbol urˇcuj´ıc´ı identifik´ator), je ˇretˇezec pr´azdn´ y. Hodnota None znamen´a, ˇze dan´a s´emantick´a jednotka nem˚ uˇze m´ıt pˇriˇrazen identifik´ator. Typ Datov´ y typ s´emantick´e jednotky, kter´ y z´aroveˇ n omezuje datov´ y typ jej´ıch podsymbol˚ u. M˚ uˇze nab´ yvat tˇechto hodnot: • True. Znamen´a “jak´ ykoliv typ”. Tato s´emantick´a jednotka nijak neomezuje typ sv´ ych podsymbol˚ u.
16
• False. Tato s´emantick´a jednotka omezuje typ sv´ ych podsymbol˚ u, ale jeˇstˇe j´ı nebyl pˇriˇrazen pˇr´ısluˇsn´ y typ. • None. Znamen´a “nezaj´ım´a se o typ”. Tyto jednotky jsou z hlediska typu zcela ignorov´any. Pˇrej´ımaj´ı tak vlastnˇe typ sv´ ych nadˇrazen´ ych s´emantick´ ych jednotek. •
. S´emantick´a jednotka omezuje typy sv´ ych podsymbol˚ u na datov´e typy kompatibiln´ı se sv´ ym datov´ ym typem. N´ avratov´ y typ Podobnˇe jako typ, jen udrˇzuje informaci o n´avratov´em typu funkce a niˇc´ım neomezuje generov´an´ı podsymbolu, kromˇe urˇcen´ı typu v´ yrazu v pˇr´ıkazu return. Funkce Informace a jejich reprezentace jsou podobn´e, jako je tomu u r´amce pro promˇenn´e. R´amec pro funkce vytv´aˇr´ı pouze nejvyˇsˇs´ı semantick´a jednotka (Program). Kromˇe identifik´atoru a n´avratov´eho typu se uchov´av´a jeˇstˇe informace o poˇctu a datov´ ych typech parametr˚ u. Parametry Opˇet s´emantick´a informace specifick´a pro funkce. Uchov´av´a se v podobˇe seznamu dvojic (datov´ y typ, identifik´ ator). Funkce Directoru Director slouˇz´ı jako vrstva mezi abstraktn´ı reprezentac´ı gramatiky v programu a samotn´ ym gener´ atorem, kter´a modifikuje podobu gramatick´ ych pravidel pˇredt´ım, neˇz je gener´ atoru pˇred´a. Obsahuje dvˇe z´akladn´ı vnitˇrn´ı struktury, ve kter´ ych udrˇzuje aktu´aln´ı podobu s´emantiky programu: Z´ asobn´ık symbol˚ u Udrˇzuje podobu aktu´aln´ı vˇetve derivaˇcn´ıho stromu generovan´eho programu. Tato data jsou pouˇzita k omezen´ı probl´em˚ u spojen´ ych s rekurz´ı nˇekter´ ych gramatick´ ych symbol˚ u. Z´ asobn´ık s´ emantick´ ych jednotek Udrˇzuje podobu aktu´aln´ı vˇetve stromu s´emantick´ ych jednotek. Princip s´emantick´ ych jednotek je pops´an n´ıˇze. Tato data slouˇz´ı k zaznamen´av´an´ı s´emantick´e podoby programu a ˇr´ızen´ı generov´an´ı na jej´ım z´akladˇe. Funkce directoru spoˇc´ıv´a v poskytov´an´ı sluˇzby pro samotn´ y gener´ator. Cel´ y proces pro jeden symbol funguje n´asledovnˇe: 1. Director pˇrijme od gener´atoru vol´an´ı metody reportStart(symbol). Director zaˇrad´ı symbol na z´asobn´ık symbol˚ u. V pˇr´ıpadˇe ˇze se jedn´a o symbol, kter´ y vytv´aˇr´ı s´emantickou jednotku, pak ji vytvoˇr´ı, pˇriˇrad´ı j´ı pˇr´ısluˇsn´e parametry a zaˇrad´ı na z´ asobn´ık s´emantick´ ych jednotek. 2. Director pˇrijme od gener´atoru vol´an´ı metody getSymbol(symbol), kterou gener´ ator ˇz´ad´a o v´aˇzen´ y seznam moˇzn´ ych rozvoj˚ u pro symbol. Director zjist´ı tento seznam z gramatick´eho pravidla, kter´e z´ısk´a od modulu 4.3.4. Pot´e analyzuje aktu´aln´ı vrcholy obou vnitˇrn´ıch z´asobn´ık˚ u, a na jejich z´akladˇe m˚ uˇze do seznamu pˇridat nov´e rozvoje nebo nˇekter´e odebrat. Je tak´e moˇzn´e zmˇenit podobu nebo v´ ahu nˇekter´ ych pravidel. Takto zmˇenˇen´ y seznam pot´e vr´at´ı gener´atoru. Zmˇeny, kter´e Director prov´ad´ı, jsou pro kaˇzdou s´emantickou jednotku jin´e, coˇz je d˚ uvod, proˇc je Director jako modul z´ avisl´ y na jazyce, kter´ y se m´a generovat – algoritmus prov´adˇen´ ych zmˇen je pops´an pˇr´ımo programem, nikoliv vstupem programu nebo metadaty.
17
3. Director d´ale prov´ad´ı tento proces pro vˇsechny podsymboly aktu´alnˇe generovan´eho symbolu. Pro nˇekter´e s´emantick´e jednotky oˇcek´av´a konkr´etn´ı vygenerovan´e podsymboly. Jejich hodnotami pak nastavuje vlastnosti takov´e s´emantick´e jednotky. 4. Director pˇrijme od gener´atoru vol´an´ı metody reportFinish(symbol, expanded), kterou gener´ator oznamuje ukonˇcen´ı generov´an´ı jednoho symbolu, a tak´e pˇred´ av´ ak posledn´ım u ´prav´am podobu vygenerovan´eho symbolu v parametru expanded. Director vyjme pˇr´ısluˇsn´ y symbol ze z´asobn´ıku a v pˇr´ıpadˇe, ˇze se jedn´a o symbol vytv´ aˇrej´ıc´ı s´emantickou jednotku, i ze z´asobn´ıku s´emantick´ ych jednotek. Pˇr´ıpadnou s´emantickou jednotku zpracuje (m˚ uˇze napˇr. definovat nebo zmˇenit vlastnost nˇekter´e jin´e, existuj´ıc´ı hloubˇeji v z´asobn´ıku). V´ yslednou podobu symbolu m˚ uˇze pot´e jeˇstˇe zmˇenit a nakonec ji jako uˇz zcela koneˇcnou vr´at´ı gener´atoru. I zde jsou zpracov´an´ı a proveden´e zmˇeny specifick´e pro kaˇzdou s´emantickou jednotku. Jednotliv´e prov´adˇen´e akce jsou pops´ any v´ yˇse u popisu samotn´ ych s´emantick´ ych jednotek. Implementovan´ e s´ emantick´ e jednotky pro jazyk C Implementace gener´atoru v t´eto pr´aci pokr´ yv´a pomˇernˇe omezenou mnoˇzinu prostoru jazyka C. Pokryty byly z´akladn´ı konstrukce jazyka C, jako jsou pˇriˇrazovac´ı pˇr´ıkaz, r˚ uzn´a vˇetven´ı a cykly, a v´ yrazy zahrnuj´ıc´ı operace s promˇenn´ ymi a funkcemi. Podporov´any jsou aritmetick´e a relaˇcn´ı v´ yrazy. Nejsou podporov´any vˇsechny oper´atory a tak´e operace se sloˇzen´ ymi (struct, union) nebo uˇzivatelsk´ ymi datov´ ymi typy. Tak´e nejsou implementov´any operace zahrnuj´ıc´ı pole a ukazatele. N´ahodn´e generov´an´ı takov´eho k´odu vn´aˇs´ı do chov´an´ı programu velk´e mnoˇzstv´ı entropie a sloˇzitost gener´atoru by v pˇr´ıpadˇe implementace vˇsech tˇechto vlastnost´ı jazyka C vzrostla do m´ıry, kter´a je pro p˚ uvodn´ı u ´ˇcel (prototypov´a implementace urˇcen´ ak experiment´aln´ı aplikaci fuzz testingu na pˇrekladaˇce) zbyteˇcn´a. Implementov´any byly tedy s´emantick´e jednotky uveden´e v n´ asleduj´ıc´ım seznamu. V z´avorce za n´azvem jsou uvedeny symboly, kter´e iniciuj´ı vznik t´eto s´emantick´e jednotky. Program (<program>) S´emantick´a jednotka reprezentuj´ıc´ı cel´ y program. Tvoˇr´ı r´amec pro definici promˇenn´ ych i funkc´ı. Pˇri ukonˇcen´ı generov´an´ı se na zaˇc´atek v´ ysledku pˇripoj´ı seznam deklarac´ı, kter´e inicializuj´ı promˇenn´e, kter´e nebyly inicializov´any v samotn´em programu. Function () S´emantick´a jednotka reprezentuj´ıc´ı definici funkce. Netvoˇr´ı r´amec pro definici promˇenn´ ych, pouze parametr˚ u. Pokud je na vrcholu z´ asobn´ıku s´emantick´ ych jednotek a nem´a jeˇstˇe definovanou pˇr´ısluˇsnou hodnotu, pak se prvn´ı n´asleduj´ıc´ı vygenerovan´ y datov´ y typ pˇriˇrad´ı jako n´avratov´ y typ, identifik´ator jako n´azev funkce, a uloˇz´ı se vygenerovan´e identifik´atory parametr˚ u s datov´ ymi typy. V okamˇziku, kdyz se zaˇcne generovat blok funkce, jsou promˇenn´e reprezentuj´ıc´ı parametry pˇrid´any do r´amce promˇenn´ ych v tomto bloku, takˇze je moˇzn´e s nimi v tˇele funkce pracovat. Po skonˇcen´ı generov´an´ı se funkce pˇrid´a do nejbliˇzˇs´ıho r´amce funkc´ı v z´asobn´ıku s´emantick´ ych jednotek, aby mohla b´ yt v tomto r´amci tak´e vol´ana. SimpleDeclaration (<declaration>) Reprezentuje jednoduchou deklaraci promˇenn´e bez jej´ı inicializace. Director pˇri jej´ım generov´an´ı oˇcek´av´ a vygenerovan´e symboly typu a identifik´atoru a pˇriˇrad´ı je do odpov´ıdaj´ıc´ıch pol´ı. Po ukonˇcen´ı se promˇenn´ a pˇrid´ a do nejbliˇzˇs´ıho r´amce pro promˇenn´e a tak´e do vnitˇrn´ıho seznamu neinicializovan´ ych promˇenn´ ych.
18
AssigningDeclaration ( : Reprezentuje deklaraci promˇenn´e s jej´ı inicializac´ı. Postup je stejn´ y jako v pˇr´ıpadˇe s´emantick´e jednotky SimpleDeclaration, jen se po vygenerov´an´ı identifik´atoru vygeneruje jeˇstˇe oper´ ator pˇriˇrazen´ı a v´ yraz, kter´ y m´a typ omezen na datov´e typy kompatibiln´ı s datov´ ym typem deklarovan´e promˇenn´e. Block (, ) Reprezentuje blok, pouˇzit´ y jako tˇelo funkce, cyklu, nebo podmiˇ novac´ıho pˇr´ıkazu. Tvoˇr´ı r´amec pro definice promˇenn´ ych. Tˇri symboly definuj´ıc´ı bloky se od sebe liˇs´ı pouˇzit´ım ukonˇcovac´ıch pojistek, coˇz je zajiˇstˇen´ı v´ ystupu a opuˇstˇen´ı bloku. Zachyt´avaj´ı se n´asleduj´ıc´ı symboly: • , kter´ y zajist´ı vygenerov´an´ı pˇr´ıkaz˚ u pro vyps´an´ı obsahu vˇsech promˇenn´ ych definovan´ ych v r´amci bloku na jeho konci. Tento symbol se vyskytuje pro vˇsechny tˇri symboly tvoˇr´ıc´ı blok. • zajist´ı pˇr´ıkaz break pro opuˇstˇen´ı bloku v pˇr´ıpadˇe, ˇze tento uˇz probˇehl v´ıcekr´at, neˇz je konfigurovateln´a hodnota. To slouˇz´ı k zabr´ anˇen´ı v´ yskytu nekoneˇcn´ ych smyˇcek. Tento pˇr´ıkaz je vygenerov´ an na konci bloku v cyklech. • zajist´ı vygenerov´an´ı pˇr´ıkazu return pro opuˇstˇen´ı bloku v pˇr´ıpadˇe, ˇze tento uˇz probˇehl v´ıcekr´at, neˇz je konfigurovateln´ a hodnota. To slouˇz´ı k zabr´ anˇen´ı v´ yskytu nekoneˇcn´ ych smyˇcek pˇri rekurzivn´ım vol´ an´ı funkce. N´avratov´a hodnota v pˇr´ıpadˇe tohoto ukonˇcen´ı jen poˇcet pr˚ ubˇeh˚ u funkc´ı. Tento pˇr´ıkaz je vygenerov´an na zaˇc´atku bloku funkce. Main (<main function>) Reprezentuje blok funkce main(). Vytv´aˇr´ı r´amec pro definici promˇenn´ ych. V z´asadˇe se jedn´a o stejnou s´emantickou jednotku jako Block, ale na konci se kromˇe v´ ypisu promˇenn´ ych v r´amci bloku vyp´ıˇs´ı tak´e glob´aln´ı promˇenn´e. Assignment () Reprezentuje pˇriˇrazovac´ı pˇr´ıkaz. Pˇri generov´an´ı identifik´ atoru Director zjist´ı seznam vˇsech promˇenn´ ych, viditeln´ ych v aktu´aln´ım r´amci, a pro gener´ator vytvoˇr´ı seznam rozvoj˚ u, kter´e je obsahuj´ı jako jedin´ y termin´aln´ı symbol. V pˇr´ıpadˇe ˇze neexistuje ˇz´adn´a promˇenn´a, kterou by bylo moˇzn´e na lev´e stranˇe pˇriˇrazovac´ıho pˇr´ıkazu pouˇz´ıt, se pˇriˇrazovavac´ı pˇr´ıkaz zmˇen´ı na deklaraci nov´e promˇenn´e s inicializac´ı. V´ yraz na prav´e stranˇe pˇriˇrazovac´ıho pˇr´ıkazu m´a datov´ y typ omezen na typ promˇenn´e na lev´e stranˇe. Expression (<expression>) Nejsloˇzitˇejˇs´ı s´emantick´a jednotka, reprezentuj´ıc´ı v´ yraz. Obsahuje omezen´ı typu sv´ ych podsymbol˚ u, nˇekdy dan´e s´emantikou pˇredem (parametr funkce), nˇekdy se urˇcuje aˇz po zjiˇstˇen´ı typu prvn´ı vygenerovan´e konstanty, funkce, nebo promˇenn´e v nˇem (pˇr´ıkladem je operand v relaˇcn´ıch v´ yrazech). Pˇri jeho zpracov´an´ı Director prov´ad´ı nˇekolik zmˇen pro zajiˇstˇen´ı pouˇzit´ı konstant, jiˇz vygenerovan´ ych promˇenn´ ych a funkc´ı, a tak´e pro omezen´ı rekurzivity, kdy se nˇekter´e symboly maj´ı sklony generovat donekoneˇcna. Prov´adˇej´ı se n´asleduj´ıc´ı akce: • Generov´an´ı konstant ve v´ yrazu. V pˇr´ıpadˇe, ˇze je typ nadˇrazen´e s´emantick´e jednotky omezen, je vylouˇcen´e generov´an´ı konstant, se kter´ ymi nen´ı typ v´ yrazu kompatibiln´ı. Rozsah ˇc´ıseln´ ych konstant nen´ı nijak oˇsetˇrov´an, protoˇze n´avratovou hodnotu v´ yrazu stejnˇe nelze urˇcit pˇredem vzhledem k funkc´ım, u kter´ ych nen´ı moˇzn´e zajistit, ˇze budou vracet hodnoty z platn´eho rozsahu. Norma jazyka C pro celoˇc´ıseln´e datov´e typy definuje pravidlo, ˇze pouˇzit´ım hodnoty vyˇsˇs´ı neˇz rozsah datov´eho typu se hodnota potichu urˇc´ı jako hodnota modulo rozsah, takˇze 19
chov´an´ı r˚ uzn´ ych pˇrekladaˇc˚ u by mˇelo v tˇechto pˇr´ıpadech b´ yt na stejn´em stroji stejn´e [18]. Pro datov´e typy float a double jsou neleg´aln´ı hodnoty interpretov´any jako INF nebo NaN, a tak´e by mˇely b´ yt stejn´e. • Generov´an´ı promˇenn´ ych ve v´ yrazu. Pˇri tvorbˇe seznamu moˇzn´ ych rozvoj˚ u jsou zjiˇstˇeny vˇsechny viditeln´e promˇenn´e, kter´e maj´ı typ kompatibiln´ı s typem v´ yrazu. Pro kaˇzdou promˇennou je pot´e vytvoˇren rozvoj s pravdˇepodobnost´ı generov´ an´ı rovnou jedn´e, kter´ y obsahuje indetifik´ator promˇenn´e jako termin´aln´ı symbol. • Generov´an´ı vol´an´ı funkc´ı ve v´ yrazu. Pˇri tvorbˇe seznamu moˇzn´ ych rozvoj˚ u pro operandy jsou zjiˇstˇeny vˇsechny funkce s n´avratov´ ym typem kompatibiln´ım s typem v´ yrazu. Pro kaˇzdou funkci je pot´e vygenerov´an rozvoj obsahuj´ıc´ı identifik´ator funkce jako termin´al, a pot´e v z´avork´ach uzavˇren´ y seznam umˇel´ ych netermin´al˚ u. Kaˇzd´ y takov´ y netermin´al m´a tvar <param/function/index>, napˇr pro vol´an´ı funkce double D(int,double,char) bude m´ıt pˇr´ısluˇsn´ y rozvoj podobu D(<param/D/0>, <param/D/1>, <param/D/2>). Gener´ator nev´ı, ˇze tyto netermin´aly jsou pouˇzity pouze ve vnitˇrn´ım mechanismu Directoru a norm´ alnˇe poˇz´ad´a o jejich rozvoje. Kdyˇz o nˇe poˇz´ad´a, Director gener´ atoru vr´at´ı jedin´ y rozvoj obsahuj´ıc´ı symbol <expression>. Typ s´emantick´e jednotky, vytvoˇren´e pro tento v´ yraz, bude nastaven na datov´ y typ index-t´eho parametru funkce function. Tyto informace Director zjist´ı v s´emantick´e jednotce, v jej´ımˇz r´ amci je function definov´ana. Vzhledem k tomu, ˇze je zbyteˇcn´e volat jednu funkci v´ıcekr´at, je pouˇzit´ı vol´ an´ı funkce omezeno. Jakmile je jej´ı vol´an´ı pouˇzito v´ıcekr´ at neˇz je hodnota v konfiguraci, pak se uˇz jej´ı dalˇs´ı vol´an´ı generovat nebudou. • Omezen´ı rekurzivity. V´ yraz je ze sv´e podstaty rekurzivn´ı – kaˇzd´ ym operandem m˚ uˇze b´ yt zase dalˇs´ı v´ yraz. To m˚ uˇze pˇri ˇspatn´e konfiguraci v´est k neukonˇcen´ı procesu generov´an´ı, nebo jeho selh´an´ı. Pro oˇsetˇren´ı t´eto situace si Director udrˇzuje hloubku hierarchie aktu´alnˇe generovan´ ych v´ yraz˚ u a od urˇcit´e konfigurovateln´e hloubky zaˇcne pˇri generov´an´ı operand˚ u pravdˇepodobnostnˇe preferovat hodnoty pˇred dalˇs´ımi v´ yrazy. Se vzr˚ ustaj´ıc´ı hloubkou v´ yrazu tak´e zvyˇsuje pravdˇepodobnost vygenerov´an´ı liter´aln´ı konstanty pˇred generov´an´ım promˇenn´ ych nebo funkc´ı.
4.3.3
Pˇ r´ıklad cel´ eho procesu
Director m´a na vrcholu z´asobn´ıku s´emantickou jednotku Block, kter´a obsahuje jiˇz definovan´e promˇenn´e int A, float B. V s´emantick´e jednotce Program na dnˇe z´asobn´ıku je tak´e definov´ana funkce int C(int). Director pˇrijme vol´an´ı reportStart(’assgn declaration’). Tento symbol vytv´aˇr´ı s´emantickou jednotku AssigningDeclaration, Director ji vytvoˇr´ı a vloˇz´ı na z´asobn´ık. Na n´asleduj´ıc´ı vol´an´ı getSymbol(’assgn declaration’) vr´at´ı rozvoj = <expression>. N´asleduje generov´an´ı typu, kter´ y nevytv´aˇr´ı s´emantickou jednotku a jako rozvoje jsou pro nˇej vr´aceny jednotliv´e datov´e typy. Director registruje vol´an´ı reportFinish(’type’, ’int’), zjist´ı ˇze SJ na vrcholu z´asobn´ıku je AssigningDeclaration, a pˇriˇrad´ı j´ı vygenerovan´ y datov´ y typ, tedy ’int’. D´ale je vygenerov´an identifik´ ator, a Director opˇet registruje aˇz vol´an´ı reportFinish(’identifier’, ’IDEN’). Stejn´ ym zp˚ usobem jako v pˇr´ıpadˇe typu pˇriˇrad´ı SJ na vrcholu z´asobn´ıku identifik´ator IDEN. Pˇri vol´ an´ı metody reportStart(’expression’) zjist´ı, ˇze aktu´aln´ı s´emantick´a jednotka je AssigningDeclaration s jiˇz urˇcen´ ym typem, kter´ ym je ’int’. Vytvoˇr´ı tedy SJ Expression, rovnou j´ı pˇriˇrad´ı typ ’int’ a zaˇrad´ı ji na z´asobn´ık. Pˇri generov´an´ı podsymbol˚ u v´ yrazu je vˇzdy zjiˇstˇeno, ˇze nadˇrazen´a SJ m´a typ int a v nadˇrazen´ ych SJ, kter´e vytv´aˇrej´ı r´amce pro promˇenn´e jsou 20
definov´any promˇenn´e A,B a funkce C. Director zjist´ı z´akladn´ı pravidlo pro rozvoj operandu, kter´e vypad´a takto: ::= | | . Z tohoto rozvoje vyˇrad´ı rozvoj se symbolem floating constant, protoˇze nen´ı kompatibiln´ı s datov´ ym typem int. K rozvoji d´ale pˇriˇrad´ı rozvoj s identifik´atorem A, ale ne identifik´atorem B, opˇet z d˚ uvodu nekompatibiln´ıho typu. Nakonec pˇriˇrad´ı jeˇstˇe rozvoj obsahuj´ıc´ı vol´an´ı funkce C. V´ ysledn´ y seznam rozvoj˚ u vypad´a takto: ::= | | | A | C(<param/A/0>. Na pˇr´ıpadn´e vol´an´ı metody reportStart(’param/A/0’) vytvoˇr´ı director SJ Expression s datov´ ym typem nult´eho parametru funkce A. Tyto informace jsou pˇr´ıtomn´e v s´emantick´e jednotce Program na dnˇe z´asobn´ıku. D´ale se v tomto pˇr´ıpadˇe postupuje zase jako pˇri generov´an´ı v´ yrazu. Nakonec cel´eho procesu je vol´ ana metoda reportFinish(’assgn declaration’, ’int IDEN = 168 + C(0/A)’). Pˇri vol´ an´ı t´eto metody Director vyhled´a v z´asobn´ıku nejbliˇzˇs´ı SJ, kter´a vytv´aˇr´ı r´amec pro promˇenn´e, a vloˇz´ı do n´ı informaci o pˇr´ıtomnosti promˇenn´e IDEN s datov´ ym typem ’int’. Znamen´a to, ˇze n´asleduj´ıc´ı SJ, kter´e budou v r´amci stejn´eho bloku generov´any, mohou s promˇennou IDEN pracovat.
4.3.4
Pomocn´ e moduly
Souˇc´ast´ı programu Spitter jsou tak´e tˇri pomocn´e moduly. Tyto moduly obsluhuj´ı specifick´e ˇc´asti programu, kter´e pˇr´ımo nesouvisej´ı s generov´an´ım vˇet. Modul Grammar tvoˇr´ı abstraktn´ı vrstvu, ve kter´e jsou uchov´av´any informace o gramatice. Modul Logger se star´ a o v´ ystup. Modul BNF Parser rozezn´av´a v textov´em souboru pravidla gramatiky definovan´ a v Backus-Naurovˇe Formˇe. Grammar Modul Grammar pˇredstavuje abstraktn´ı vrstvu uchov´avaj´ıc´ı podobu gramatiky generovan´eho jazyka. Obsahuje tyto tˇr´ıdy reprezentuj´ıc´ı r˚ uzn´e elementy, pouˇzit´e pro popis gramatiky: • Element je b´azov´a tˇr´ıda pro vˇsechny prvky gramatiky. Obsahuje pouze metody pro logov´an´ı, kter´e mohou vyuˇz´ıvat modul Logger. • Symbol reprezentuje jeden symbol gramatiky. Jeho prvky jsou jm´eno a typ. Typ m˚ uˇze b´ yt termin´al nebo netermin´al. Pokud je typ symbolu termin´al, pak se nevyuˇz´ıv´ a vlastnost jm´eno. • OptSymbol je potomkem tˇr´ıdy Symbol. Reprezentuje symbol, kter´ y m´a nav´ıc volitelnou moˇznost generov´an´ı, coˇz je ˇc´ıslo s plovouc´ı desetinnou ˇc´arkou v intervalu < 0, 1 >. • Production reprezentuje jeden moˇzn´ y rozvoj netermin´alu. Obsahuje pouze seznam symbol˚ u v poˇrad´ı, v jak´em se maj´ı vygenerovat. 21
• Rule reprezentuje pravidlo. Obsahuje jm´eno netermin´alu, pro kter´ y je urˇceno, a tak´e seznam moˇzn´ ych rozvoj˚ u. Rozvoje mohou m´ıt v´ahu, kter´a urˇcuje pomˇer pravdˇepodobnost´ı s jakou se vygeneruj´ı. • Grammar reprezentuje celou gramatiku. Obsahuje seznam netermin´al˚ u, pro kter´e existuj´ı pravidla. Obsahuje tak´e seznam pravidel. Implementuje nav´ıc metodu pro ovˇeˇren´ı korektnosti gramatiky – zda pro kaˇzd´ y netermin´al pouˇzit´ y na prav´e stranˇe pravidla existuje pravidlo pro jeho generov´an´ı. Logger Modul Logger obsluhuje v´ ystup a logov´an´ı programu. Podstatnou vlastnost´ı je konfigurovatelnost smˇerov´an´ı obou v´ ystup˚ u. Vzhledem k povaze logov´an´ı ˇcinnosti gener´atoru umoˇzn ˇuje odsazov´an´ı v´ ystupu podle aktu´aln´ı hloubky v derivaˇcn´ım stromu a tak´e volbu u ´rovnˇe logov´an´ı. BNF Parser Modul BNF Parser obsluhuje ˇcten´ı a rozezn´av´an´ı pravidel gramatiky z textov´eho vstupu a pˇred´av´a je modulu Grammar. Jedn´a se o velmi jednoduch´ y modul, vyuˇz´ıvaj´ıc´ı lexik´ aln´ı a syntaktick´ y Ply [7].
4.4
Builder
Builder je ˇc´ast syst´emu, kter´a se star´a o vytvoˇren´ı vˇsech v´ ystup˚ u, kter´e se budou pozdˇeji Comparatorem analyzovat. Jedn´ a se o velmi jednoduch´ y skript, kter´ y jako parametr bere cestu k souboru a seznam znaˇcek konfigurac´ı pˇrekladaˇc˚ u, pro kter´e se testovac´ı k´od zkompiluje. Ze souboru s nastaven´ım potom naˇc´ıt´a konfigurace pro spouˇstˇen´ı jednotliv´ ych pˇrekladaˇc˚ u. Kaˇzd´a konfigurace mus´ı m´ıt unik´atn´ı znaˇcku, podle kter´e je moˇzn´e ji identifikovat. Konfigurace d´ale obsahuje znaˇcky, podle kter´ ych se urˇcuj´ı pozice zdrojov´eho souboru a v´ ystupu v pˇr´ıkazu, kter´ y vol´a pˇrekladaˇc. Pˇreloˇzen´ y program je Builderem spuˇstˇen a jeho v´ ystup zaznamen´an. Pokud se program s´am neukonˇc´ı do nastaven´eho poˇctu vteˇrin, je mu odesl´ an sign´al SIGTERM. V´ ystupem builderu jsou soubory: • TAG.build obsahuje zpr´avy, kter´e pˇrekladaˇc bˇehem zpracov´av´an´ı zdrojov´eho k´ odu vypsal na standardn´ı nebo chybov´ y v´ ystup. • TAG.buildresult obsahuje v´ ysledek pˇrekladu, tj. informaci, zda byl pˇreklad u ´spˇeˇsn´ y. • TAG je vlastn´ı spustiteln´ y soubor. • TAG.termination obsahuje informaci, zda se pˇreloˇzen´ y program ukonˇcil standardnˇe, nebo zda musel b´ yt ukonˇcen sign´alem. • TAG.output obsahuje v´ ystup pˇreloˇzen´eho programu po spuˇstˇen´ı.
4.5
Comparator
Comparator je jednoduch´ y modul, jehoˇz u ´kolem je porovnat v´ ystupy, kter´e vytvoˇril modul Builder, a na jejich z´akladˇe rozhodnout o tom, zda bude v´ ysledek testu to ˇze testovan´e 22
pˇrekladaˇce uspˇely, nebo nˇekter´ y selhal. Selh´an´ı dˇel´ı na nˇekolik druh˚ u, kter´e se pozdˇeji uchov´avaj´ı a reportuj´ı oddˇelenˇe. Tato selh´an´ı jsou oznaˇcena jako anom´alie. Existuj´ı tˇri druhy anom´ali´ı: anom´alie pˇrekladu (rozd´ıln´a u ´spˇeˇsnost pˇrekladu), anom´alie ukonˇcen´ı (rozd´ıln´ y zp˚ usob ukonˇcen´ı) a koneˇcnˇe anom´alie v´ ystupu (spuˇstˇen´e programy maj´ı odliˇsn´ y v´ ystup). Comparator nejprve porovn´a v´ ysledky pˇreklad˚ u. Pokud jsou odliˇsn´e, pak se v´ ysledek testu n´ahl´as´ı jako anom´alie pˇrekladu. Pˇr´ıpad kdy oba pˇreklady selˇzou je moˇzn´e nastavit jako anom´alii i jako platn´ y v´ ysledek. Pokud pouˇz´ıv´ame gener´ator, o kter´em v´ıme, ˇze produkuje vˇzdy jen naprosto validn´ı k´od, pak je jak´ekoliv selh´an´ı anom´ali´ı a vˇsechny v´ ysledky se zachovaj´ı k anal´ yze ˇclovˇekem. Pro gener´ator produkuj´ıc´ı neplatn´ y k´od je odm´ıtnut´ı pˇrekladu spr´avnˇe funguj´ıc´ım pˇrekladaˇcem oˇcek´avan´e a proto se za anom´alii nepovaˇzuje. V pˇr´ıpadˇe ˇze nebyla objevena anom´alie ve v´ ysledku pˇrekladu, porovn´a se zp˚ usob ukonˇcen´ı programu. Pokud se liˇs´ı, pak jsou prohl´aˇseny za anom´alii ukonˇcen´ı. Stejnˇe jako u v´ ysledk˚ u pˇrekladu, i zde je moˇzn´e nastavit, jak´ ym zp˚ usobem se bude nakl´adat se stejn´ ymi, ale negativn´ımi v´ ysledky (pro tento pˇr´ıpad je to n´asiln´e ukonˇcen´ı). I v tomto pˇr´ıpadˇe, pokud m´ ame jistotu, ˇze gener´ator tvoˇr´ı programy, kter´e by se mˇely ukonˇcit samy, je n´asiln´e ukonˇcen´ı pˇreloˇzen´eho programu anom´ali´ı. Pokud nen´ı objevena anom´alie ve dvou pˇredchoz´ıch kroc´ıch, pak se porovn´avaj´ı v´ ystupy spuˇstˇen´ ych program˚ u. Zde se za anom´alii povaˇzuj´ı uˇz jen rozd´ıln´e v´ ystupy. Oba v´ ystupy jsou volitelnˇe provˇeˇreny na pˇr´ıtomnost znak˚ u faleˇsn´eho selh´an´ı, kdy syst´em nahl´as´ı anom´ alii, ’ kter´a ale m˚ uˇze b´ yt zp˚ usobena bud jiˇz zn´amou chybou, nebo jin´ ym zn´am´ ym nedeterministick´ ym chov´an´ım generovan´ ych program˚ u. Takov´ ym typick´ ym znakem je ukonˇcen´ı programu sign´alem SIGFPE3 , kter´ y nast´av´a v pˇr´ıpadˇe dˇelen´ı nulou [15]. Toto dˇelen´ı nulou se ale m˚ uˇze nach´azet ve v´ yrazu, kter´ y pˇrekladaˇc odoptimalizuje a potom se m˚ uˇze st´ at, ˇze jeden pˇreklad selˇze se sign´alem SIGFPE, ale druh´ y dobˇehne v poˇr´adku. Ovˇeˇrov´an´ı na faleˇsn´e selh´an´ı je moˇzno konfigurovat. V´ ystupem Comparatoru je n´avratov´ y k´od, kter´ y urˇcuje, zda byla nalezena nˇejak´a anom´ alie, a jej´ı typ v pˇr´ıpadˇe ˇze ano.
4.6
Pokryt´ı pro pˇ rekladaˇ ce specifick´ ych chyb navrˇ zen´ ym syst´ emem
V pˇr´ıpadˇe optim´aln´ı implementace cel´eho syst´emu je moˇzn´e pˇredpokl´adat, ˇze dos´ ahneme takov´eho pokryt´ı typ˚ u chyb v pˇrekladaˇc´ıch, jak´e uv´ad´ı tabulka 4.1. Z tabulky je vidˇet, ˇze kvalitn´ı pokryt´ı pˇrin´aˇs´ı uˇz prvn´ı f´aze porovn´av´an´ı, ihned pˇri pˇrekladu. Pro dobr´e pokryt´ı nen´ı tedy potˇreba gener´ator deterministick´eho k´odu, staˇc´ı platn´ y k´od. Deterministick´ y v´ ystup je ale tˇreba pro detekci chyb typu wrong-code, na nˇeˇz je tato pr´ace zamˇeˇrena. Pro pokryt´ı nˇekter´ ych chyb, kter´e jsou oznaˇceny jako “Moˇzn´e” by byly tˇreba modifikace jednotliv´ ych ˇc´ast´ı.
3
sign´ al Floating Point Exception, indikuj´ıc´ı obecnou chybu pˇri operaci s ˇc´ıslem s plovouc´ı desetinnou ˇc´ arkou
23
Tabulka 4.1: Pokryt´ı typ˚ u chyb v pˇrekladaˇc´ıch navrˇzen´ ym syst´emem Typ chyby accepts-invalid assemble-failure compile-time-hog diagnostic ice-on-invalid ice-on-valid link-failure memory-hog missed-optimization register-allocator rejects-valid wrong-code
Pokryt´ı Moˇzn´e (s gener´atorem neplatn´eho k´odu) Ano Moˇzn´e Ne Moˇzn´e (s gener´atorem neplatn´eho k´odu) Ano Ano Ne Ne Ne Ano Ano
24
Typ anom´ alie Anom´alie pˇrekladu Anom´alie pˇrekladu Anom´alie pˇrekladu ˇ adn´a Z´ Anom´alie pˇrekladu Anom´alie pˇrekladu Anom´alie pˇrekladu ˇ adn´a Z´ ˇ adn´a Z´ ˇ adn´a Z´ Anom´alie pˇrekladu Anom´alie v´ ystupu/ukonˇcen´ı
Kapitola 5
Aplikace na re´ aln´ e pˇ r´ıpady Cel´ y syst´em byl podroben ˇctyˇrem experiment˚ um, porovn´avaj´ıc´ım r˚ uzn´e konfigurace r˚ uzn´ ych pˇrekladaˇc˚ u. Tato kapitola popisuje jejich nastaven´ı, pr˚ ubˇeh a v´ ysledky.
5.1
Metodika
Syst´em byl testov´an na ˇctyˇrech r˚ uzn´ ych pˇr´ıpadech, kter´e pokr´ yvaj´ı spektrum moˇzn´ ych pouˇzit´ı syst´emu. Tˇemito pˇr´ıpady jsou: • produkˇcn´ı pˇrekladaˇc v r˚ uzn´ ych konfigurac´ıch, • produkˇcn´ı pˇrekladaˇc proti pˇrekladaˇci, kter´ y jeˇstˇe nedos´ahl verze 1, • open-source produkˇcn´ı pˇrekladaˇce proti produkˇcn´ımu propriet´arn´ımu, • produkˇcn´ı pˇrekladaˇc ve stabiln´ı verzi proti stejn´emu pˇrekladaˇci ve v´ yvojov´e verzi. P˚ uvodnˇe bylo u ´myslu testovat v´ıce open-source neprodukˇcn´ıch pˇrekladaˇc˚ u proti produkˇcn´ımu, ale nepodaˇrilo se zprovoznit jin´e open-source pˇrekladaˇce neˇz GCC a TCC. Pro kaˇzdou variantu byl syst´em testov´an se tˇremi r˚ uzn´ ymi gener´atory, pouˇzit´ ymi pro tvorbu testovac´ıho vstupu. Tento pˇr´ıstup byl zvolen kv˚ uli objektivitˇe. Pokud by mnou implementovan´ y gener´ator (Spitter popsan´ y v sekci 4.3) nemˇel vlastnosti potˇrebn´e pro u ´spˇeˇsn´e vyhled´av´an´ı chyb, pak je tˇreba zjistit chov´an´ı syst´emu s jin´ ym gener´atorem. Pokud by ani tento gener´ator nemˇel poˇzadovan´e v´ ysledky, pak by bylo moˇzn´e tuto metodu prohl´ asit za neefektivn´ı a vyvodit z toho z´ avˇery. Pouˇzit´e gener´atory jsou tyto: • Spitter je mnou implementovan´ y gener´ator. Dok´aˇze generovat omezenou podmnoˇzinu jazyka C. Programy jsou validn´ı a ukonˇcuj´ı se. Implementaˇcn´ım jazykem je Python. • Randprog je gener´ator n´ ahodn´ ych program˚ u jazyka C, implementovan´ y Bryanem Turnerem [19]. Dok´aˇze generovat omezenou podmnoˇzinu jazyka C. Programy jsou validn´ı, a aˇckoliv program obsahuje k´od kter´ y m´a zabr´anit nekoneˇcn´ ym cykl˚ um, programy musej´ı b´ yt obˇcas ukonˇceny sign´alem. Implementaˇcn´ım jazykem je C++. • fuzz pˇredstavuje ˇcistˇe n´ahodn´ y vstup o d´elce 1000 byte, realizovan´ y pˇr´ıkazem dd if=/dev/urandom. Tento gener´ator byl zvolen z d˚ uvodu z´amˇeru porovn´an´ı ˇcist´eho fuzz testingu s variantou navrˇzenou v t´eto pr´aci. 25
Vzhledem k relativn´ı rychlosti jednoho testu byl pro jednu variantu zvolen poˇcet 5000 test˚ u. V pˇr´ıpadˇe, ˇze bˇehem testov´an´ı jedn´e varianty byly testov´any r˚ uzn´e konfigurace pˇrekladaˇc˚ u (napˇr. optimalizac´ı), pak byl pro kaˇzdou konfiguraci proveden pomˇern´ y poˇcet test˚ u (napˇr. pro dvˇe konfigurace bylo s kaˇzdou provedeno 2500 test˚ u). Pro odliˇsn´e konfigurace byly generov´any odliˇsn´e testovac´ı pˇr´ıpady. Po ubˇehnut´ı vˇsech test˚ u byly analyzov´ any v´ ysledky, a objeven´e anom´alie byly klasifikov´any jako faleˇsn´e nebo prav´e.
5.2
Testovan´ e pˇ rekladaˇ ce
Testov´any byly pˇrekladaˇce uveden´e v n´asleduj´ıc´ım seznamu. Dalˇs´ı podm´ınky v testovac´ım prostˇred´ı se v jednotliv´ ych variant´ach testov´an´ı liˇsily, a jsou uvedeny u kaˇzd´eho pˇr´ıpadu ’ zvl´aˇst . y syst´em vyv´ıjen´ y jako souˇca´st • GCC (GNU Compiler Collection)[2] je pˇrekladaˇcov´ projektu GNU. Jedn´a se o nejrozˇs´ıˇrenˇejˇs´ı pˇrekladaˇc aplikac´ı v open-source komunitˇe pouˇz´ıvaj´ıc´ı syst´em GNU/Linux[4]. Obsahuje front-endy pro jazyky C, C++, ObjC, Fortran, Java a Ada. Je dostupn´ y pod licenc´ı GPLv3. • TCC (Tiny C Compiler)[5] je pˇrekladaˇc jazyka C, zamˇeˇren´ y na kompaktnost a rychlost. Obsahuje vlastn´ı assembler a linker, a implementuje dvˇe zaj´ımav´e vlastnosti: schopnost interpretovat zdrojov´ y k´od jazyka C jako skript, a zabudovan´e testy na nˇekter´e program´atosk´e s´emantick´e chyby (bound checker ). TCC zat´ım nedos´ ahl stabiln´ı verze. Je dostupn´ y pod licenc´ı BSD. u C, C++ a Fortran pro platformy firmy • ICC (Intel C Compiler)[3] je pˇrekladaˇc jazyk˚ Intel, kterou je tak´e vyv´ıjen. V´ yhodou jsou vynikaj´ıc´ı optimalizace na nativn´ıch platform´ach. Jedn´a se o komerˇcn´ı, propriet´arn´ı pˇrekladaˇc dostupn´ y zdarma pro nekomerˇcn´ı vyuˇzit´ı. Akademick´e vyuˇzit´ı nen´ı povaˇzov´ano za nekomerˇcn´ı, bylo tedy vyuˇzito instalace tohoto pˇrekladaˇce na ˇskoln´ıch serverech s patˇriˇcnou licenc´ı.
5.3
Klasifikace v´ ysledk˚ u
• Anom´alie pˇrekladu znamen´ a, ˇze v´ ysledek pˇrekladu byl u obou pˇrekladaˇc˚ u odliˇsn´ y. • Anom´alie ukonˇcen´ı znamen´a, ˇze jeden program byl ukonˇcen sign´alem, zat´ımco druh´ y korektnˇe dobˇehl. • Anom´alie v´ ystupu oznaˇcuje pˇr´ıpad, kdy se v´ ystupy spuˇstˇen´ ych program˚ u liˇs´ı. • Selh´an´ı pˇrekladu oznaˇcuje pˇr´ıpad, kdy pˇri pˇrekladu selˇzou oba pˇrekladaˇce. • Ignorovan´e v´ ysledky byly takov´e, kdy alespoˇ n jeden program byl ukonˇcen sign´ alem SIGFPE. Anom´alie byly n´aslednˇe ruˇcnˇe analyzov´any a klasifikov´any jako prav´e chyby, nebo ˇ y byl pˇr´ıpad, kdy byla jedna chyba nahl´aˇsena nˇekolikr´at. V takov´em faleˇsn´ a hl´aˇsen´ı. Cast´ pˇr´ıpadˇe je zapoˇc´ıt´ana pouze jednou, stejnˇe jako nˇekolik faleˇsn´ ych hl´aˇsen´ı, kter´e byly zp˚ usobeny stejnou chybou v testovac´ım syst´emu.
26
5.4
Pˇ r´ıpad 1: gcc s r˚ uzn´ ymi optimalizacemi
V t´eto ˇc´asti byl syst´em aplikov´an na open-source produkˇcn´ı pˇrekladaˇc s vypnut´ ymi optimalizacemi jako referenˇcn´ı a stejn´ y pˇrekladaˇc s r˚ uzn´ ymi u ´rovnˇemi optimalizac´ı.
5.4.1
Prostˇ red´ı a podm´ınky
Testovan´ y pˇ rekladaˇ c Testovan´ y pˇrekladaˇc byl GNU Compiler Collection ve verzi 4.1.2-33, dod´avan´ y v RPM bal´ıˇcku distribuce Fedora gcc-4.1.2-33.fc8.rpm. Bylo provedeno 1500 experiment˚ u pro tˇri r˚ uzn´e u ´rovnˇe optimalizac´ı – optimalizace v´ ykonu -O2, silnˇejˇs´ı optimalizace v´ ykonu -O3 a optimalizace velikosti v´ ysledn´eho k´odu -Os. Referenˇ cn´ı pˇ rekladaˇ c Referenˇcn´ım pˇrekladaˇcem byl v tomto experimentu rovnˇeˇz GNU Compiler Collection ve verzi 4.1.2-33, dod´avan´ y v RPM bal´ıˇcku distribuce Fedora gcc-4.1.2-33.fc8.rpm, s explicitnˇe deaktivovan´ ymi optimalizacemi (volba -O0). Prostˇ red´ı Testov´an´ı prob´ıhalo v n´asleduj´ıc´ım prostˇred´ı. • Procesor: AMD Athlon(tm) 64 Processor 3800+ • Operaˇ cn´ı syst´ em: Fedora 8 • J´ adro: Linux 2.6.24.4-64.fc8 #1 SMP i686 athlon i386 GNU/Linux • Linker: GNU ld verze 2.17.50.0.18-1 20070731 • Knihovna C: glibc-2.7-2
5.4.2
Spitter
V´ ysledky jsou uvedeny v tabulce 5.1. Bˇehem tohoto testov´an´ı nebyly nalezeny ˇz´adn´e chyby v testovan´em pˇrekladaˇci. Selh´an´ı pˇrekladu byla zp˚ usobena nedokonal´ ym generov´an´ım Spitteru, kdy je jeden identifik´ator, nejˇcastˇeji jednoznakov´ y, pouˇzit v programu v´ıcekr´ at.
5.4.3
Randprog
V´ ysledky jsou uvedeny v tabulce 5.2. Vysok´ y poˇcet anom´ali´ı ukonˇcen´ı je d´an podobou program˚ u generovan´ ych programem Randprog. Programy j´ım generovan´e maj´ı obˇcas pomˇernˇe dlouhou dobu trv´an´ı, a proto byla ˇcasto anom´alie vyvolan´a t´ım, ˇze po uplynut´ı limitu 5 sekund byl takov´ y program umˇele zabit. Byla nalezena jedna chyba (demonstrovan´ a v doy v´ ysledek bitov´e datc´ıch A.1 a A.2) , kdy byl v optimalizovan´em k´odu ˇspatnˇe vypoˇc´ıtan´ operace.
5.4.4
fuzz
V´ ysledky uv´ad´ı tabulka 5.3. Test dopadl zcela dle oˇcek´av´an´ı, vˇsechny n´ahodn´e vstupy byly pˇrekladaˇcem korektnˇe odm´ıtnuty. Nebylo zjiˇstˇeno ani jedno zhroucen´ı pˇrekladaˇce. 27
Tabulka 5.1: GCC -O0 vs. GCC -O2, -O3, -Os, Spitter Testy -O2 -O3 -Os Celkem 1500 1500 1500 OK 1456 1457 1460 Anom´alie pˇrekladu 0 0 0 Anom´alie ukonˇcen´ı 0 0 0 Anom´alie v´ ystupu 0 0 0 Selh´an´ı pˇrekladu 15 3 11 Ignorovan´e v´ ysledky 29 40 29 Poˇcet skuteˇcn´ ych chyb 0 0 0 Poˇcet faleˇsn´ ych chyb 0 0 0
Tabulka 5.2: GCC -O0 vs. GCC -O2, -O3, -Os, Randprog Testy -O2 -O3 -Os Celkem 1500 1500 1500 OK 1345 1335 1349 Anom´alie pˇrekladu 0 0 0 Anom´alie ukonˇcen´ı 155 162 151 Anom´alie v´ ystupu 0 3 0 Selh´an´ı pˇrekladu 0 0 0 Ignorovan´e v´ ysledky 0 0 0 Poˇcet skuteˇcn´ ych chyb 0 2 0 Poˇcet faleˇsn´ ych chyb 0 0 0
Tabulka 5.3: GCC -O0 vs. GCC -O2, -O3, Testy -O2 -O3 Celkem 1500 1500 OK 0 0 Selh´an´ı pˇrekladu 1500 1500 Poˇcet skuteˇcn´ ych chyb 0 0 Poˇcet faleˇsn´ ych chyb 0 0
28
-Os, fuzz -Os 1500 0 1500 0 0
5.4.5
Zhodnocen´ı experimentu
Naproti oˇcek´av´an´ı nebyly nalezeny t´emˇeˇr ˇz´adn´e chyby. D˚ uvodem m˚ uˇze b´ yt fakt, ˇze pˇrekladaˇc GCC verze 4.1.2 je uˇz´ıv´an jiˇz pomˇernˇe dlouhou dobu a zjevn´e chyby byly jiˇz objeveny. Je tak´e moˇzn´e, ˇze pˇri vˇetˇs´ım poˇctu testovac´ıch pˇr´ıpad˚ u by k nalezen´ı chyby mohlo doj´ıt. Zaj´ımav´ y bude tento experiment aplikovan´ y na v´ yvojovou verzi pˇrekladaˇce GCC.
5.5
Pˇ r´ıpad 2: GCC, TCC
V t´eto ˇc´asti byl syst´em aplikov´ an na open-source produkˇcn´ı pˇrekladaˇc jako referenˇcn´ı a open-source nedospˇel´ y pˇrekladaˇc jako testovan´ y.
5.5.1
Prostˇ red´ı a podm´ınky
Testovan´ y pˇ rekladaˇ c Testovan´ y pˇrekladaˇc byl Tiny C Compiler ve verzi 0.9.24, pˇreloˇzen´ y a sestaven´ y ze zdrojov´ ych k´od˚ u dostupn´ ych na webov´ ych str´ank´ach projektu, pˇreloˇzen´ y standardn´ım GNU v´ yvojov´ ym ˇretˇezcem (pˇrekladaˇc GCC 4.1.2-33, linker ld 2.17.50.0.18-1, knihovna C glibc glibc-2.7-2). Referenˇ cn´ı pˇ rekladaˇ c Referenˇcn´ım pˇrekladaˇcem byl v tomto experimentu GNU Compiler Collection ve verzi 4.1.233, dod´avan´ y v RPM bal´ıˇcku distribuce Fedora gcc-4.1.2-33.fc8.rpm. Prostˇ red´ı • Procesor: AMD Athlon(tm) 64 Processor 3800+ • Operaˇ cn´ı syst´ em: Fedora 8 • J´ adro: Linux 2.6.24.4-64.fc8 #1 SMP i686 athlon i386 GNU/Linux • Linker: GNU ld verze 2.17.50.0.18-1 20070731 • Knihovna C: glibc-2.7-2
5.5.2
Spitter
V tomto pˇr´ıpadˇe bylo nalezeno velk´e mnoˇzstv´ı anom´ali´ı. V´ ysledky jsou uvedeny v tabulce 5.4. Vˇsechny anom´alie pˇrekladu jsou zp˚ usobeny r˚ uzn´ ymi variantami chyby uveden´e v pˇr´ıloze A.5, kdy pˇrekladaˇc TCC neodm´ıtne k´od, kde jsou pˇredefinov´any symboly na jin´ y typ, popˇr´ıpadˇe jdou definov´any jako jin´ y typ symbolu. Velk´e mnoˇzstv´ı anom´ali´ı v´ ystupu je zp˚ usobeno variantami chyby A.9 a dalˇs´ımi. Objevily se tak´e nˇekter´e faleˇsn´e chyby, zejm´ena ve spojitosti s pˇresnost´ı operac´ı velmi vysok´ ych ˇc´ısel s plovouc´ı ˇr´adovou ˇc´arkou, kdy se ztr´ac´ı pˇresnost tohoto datov´eho typu a pˇrekladaˇce se s t´ım vyrovn´avaj´ı r˚ uzn´ ym zp˚ usobem.
5.5.3
Randprog
V´ ysledky jsou uvedeny v tabulce 5.4. Pˇr´ıˇciny anom´ali´ı nebyly do detailu vyˇsetˇrov´any, vzhledem k velikosti pˇr´ıpad˚ u generovan´ ych programem Randprog. 29
Tabulka 5.4: Testy Celkem OK Anom´alie pˇrekladu Anom´alie ukonˇcen´ı Anom´alie v´ ystupu Selh´an´ı pˇrekladu Ignorovan´e v´ ysledky Poˇcet skuteˇcn´ ych chyb Poˇcet faleˇsn´ ych chyb
5.5.4
GCC vs. TCC Spitter Randprog 5000 5000 4083 4427 14 0 0 514 680 59 7 0 216 0 7 0 2 0
fuzz 5000 0 0 0 0 5000 0 0 0
fuzz
ˇ e fuzz testov´an´ı nenalezlo v obou pˇrekladaˇc´ıch V´ ysledky jsou uvedeny v tabulce 5.4. Cist´ ˇz´adnou chybu.
5.6
Zhodnocen´ı experimentu
V t´eto kombinaci bylo testov´an´ı nej´ uspˇeˇsnˇejˇs´ı. V pomˇeru k relativnˇe lehk´emu testov´ an´ı bylo nalezeno sedm r˚ uzn´ ych chyb, coˇz potvrzuje vhodnost metody pro testov´an´ı nedospˇel´eho pˇrekladaˇce. Z´aroveˇ n se uk´azala v´ yrazn´a nevhodnost program˚ u generovan´ ych programem Randprog pro testov´an´ı. I v pˇr´ıpadˇe, ˇze byla nalezena anom´alie, vyˇsetˇrov´an´ı pˇr´ıˇciny v generovan´em k´odu by bylo velmi obt´ıˇzn´e a nam´ahav´e, protoˇze Randprog generuje velmi obs´ahl´e programy s extr´emnˇe sloˇzit´ ym pr˚ ubˇehem k´odem.
5.7
Pˇ r´ıpad 3: icc, gcc
Tato ˇc´ast se zab´ yv´a experimentem, kdy byl syst´em testov´an na kombinaci produkˇcn´ıho open-source pˇrekladaˇce a produkˇcn´ıho propriet´arn´ıho pˇrekladaˇce. Jako referenˇcn´ı pˇrekladaˇc byl zvolen open-source pˇrekladaˇc GCC, jako testovan´ y pˇrekladaˇc propriet´arn´ı. Testy probˇehly ve dvou variant´ach nastaven´ı optimalizac´ı testovan´eho pˇrekladaˇce.
5.7.1
Prostˇ red´ı a podm´ınky
Testovan´ y pˇ rekladaˇ c Testovan´ y pˇrekladaˇc byl Intel C++ Compiler ve verzi 10.0, nainstalovan´ y na poˇc´ıtaˇci merlin.fit.vutbr.cz. Bylo provedeno 2500 experiment˚ u pro dvˇe r˚ uzn´e u ´rovnˇe optimalizac´ı – optimalizace v´ ykonu -O2 a explicitnˇe deaktivovan´e optimalizace -O0. Referenˇ cn´ı pˇ rekladaˇ c Referenˇcn´ım pˇrekladaˇcem byl v tomto experimentu GNU Compiler Collection ve verzi 4.2.3, nainstalovan´ y na poˇc´ıtaˇci merlin.fit.vutbr.cz. Optimalizace byly explicitnˇe deaktivov´any (volba -O0).
30
Prostˇ red´ı • Procesor: Dual-Core AMD Opteron(tm) Processor 2216 • Operaˇ cn´ı syst´ em: CentOS verze 5 • J´ adro: Linux 2.6.16.60 #2 SMP x86 64 x86 64 x86 64 GNU/Linux • Linker: GNU ld verze 2.18 • Knihovna C: glibc-2.5-18
5.7.2
Spitter
V´ ysledky uv´ad´ı tabulka 5.5. Tento experiment uk´azal mnoho chyb a nedostateˇcn´ ych zajiˇstˇen´ı implementovan´eho gener´atoru, coˇz vy´ ustilo ve velk´ y poˇcet r˚ uzn´ ych faleˇsn´ ych hl´aˇsen´ı. D˚ uvodem byl fakt, ˇze ICC je pˇrekladaˇc, jehoˇz funkcionalita je v´ yraznˇeji odliˇsn´a od GCC, i kdyˇz jeˇstˇe st´ale v r´amci normy. ICC dok´azal na rozd´ıl od GCC odhalit pˇr´ıliˇs velkou konstantu uˇz v dobˇe pˇrekladu (jedin´a anom´alie p´rekladu). Byly odhaleny dva druhy faleˇsn´ ych chyb. Jedn´ım d˚ uvodem byla schopnost pˇrekladaˇce ICC odhalit nedostateˇcnou pˇresnost promˇenn´e s hodnotou s plovouc´ı ˇr´adovou ˇc´arkou, pokud byly zapnut´e optimalizace. V tomto pˇr´ıpadˇe pˇrekladaˇc zmˇenil datov´ y typ float na datov´ y typ double, coˇz se odrazilo na v´ ystupu odliˇsn´em od GCC, kter´ y tuto optimalizaci nezvl´ad´a. Za chybu to ale nelze povaˇzovat v ani jednom pˇr´ıpadˇe. Druh´ ym faleˇsn´ ym hl´aˇsen´ım byl odliˇsn´ y obsah promˇenn´e typu long long (nebo jin´eho celoˇc´ıseln´eho typu niˇzˇs´ı velikosti) v pˇr´ıpadˇe, ˇze do n´ı byla pˇriˇrazena hodnota typu s plovouc´ı ˇr´adovou ˇc´arkou, kter´a byla vˇetˇs´ı neˇz maxim´aln´ı hodnota typu long long. Pˇr´ıklad viz. pseudok´od 5.7.2. Program pˇreloˇzen´ y GCC do takov´e promˇenn´e pˇriˇradil hodnotu LLONG MAX. Program pˇreloˇzen´ y ICC do n´ı pˇriˇradil hodnotu o jedna vyˇsˇs´ı, coˇz zp˚ usob´ı pˇreteˇcen´ı na nejniˇzˇs´ı hodnotu v rozsahu pˇr´ısluˇsn´eho datov´eho typu. Autorovi se nepodaˇrilo v normˇe jazyka C nal´ezt definici, kter´e by toto chov´an´ı odporovalo, takˇze nemohla b´ yt prohl´ aˇsena za chybu.
5.7.3
Randprog
V´ ysledky uv´ad´ı tabulka 5.6. V tomto experimentu se prok´azala relativn´ı nevhodnost gener´atoru Randprog pro u ´ˇcely fuzz testov´an´ı r˚ uzn´ ych pˇrekladaˇc˚ u. Vysok´e ˇc´ıslo anom´ ali´ı ukonˇcen´ı znamen´a fakt, ˇze mnoho test˚ u nebylo ukonˇceno do stanoven´eho ˇcasu. Testovac´ı pˇr´ıpady, kter´e prob´ıhaj´ı dlouhou dobu, nejsou pro fuzz testov´an´ı vhodn´e, protoˇze se t´ım ztr´ac´ı v´ yrazn´a v´ yhoda – moˇznost zpracovat velk´e mnoˇzstv´ı test˚ u bˇehem kr´atk´e doby. Z´aroveˇ n v tomto pˇr´ıpadˇe nebyly analyzov´any chyby ve v´ ystupu. Randprog obˇcas generuje i skuteˇcnˇe velmi rozs´ahl´e programy, v ˇr´adu desetitis´ıc˚ u ˇr´adk˚ u. Z´aroveˇ n jedin´ y jeho v´ ystup (a jeho v´ ypoˇcet) je proveden aˇz zcela na konci programu, a je tak velmi obt´ıˇzn´e nal´ezt m´ısto, ve kter´em se funkcionalita liˇs´ı od referenˇcn´ıho pˇrekladu. Vzhledem k n´achylnosti kombinace GCC/ICC na rozd´ılnost v´ ystupu popsan´eho v sekci 5.7.2 je tak´e velmi pravdˇepodobn´e, ˇze tyto anom´alie jsou zp˚ usobeny pr´ avˇe takov´ ym rozd´ıln´ ym v´ ysledkem pˇriˇrazen´ı.
5.7.4
fuzz
V´ ysledky uv´ad´ı tabulka 5.7. Ani v t´eto kombinaci nebyla ˇcist´ ym fuzz testov´an´ım nalezena ˇz´adn´a chyba. Vˇsechny neplatn´e vstupy byly korektnˇe odm´ıtnuty obˇema pˇrekladaˇci. 31
Tabulka 5.5: GCC vs. ICC, Spitter Testy -O0 -O2 Celkem 2500 2500 OK 2455 2411 Anom´alie pˇrekladu 1 0 Anom´alie ukonˇcen´ı 0 0 Anom´alie v´ ystupu 13 28 Selh´an´ı pˇrekladu 18 13 Ignorovan´e v´ ysledky 13 48 Poˇcet skuteˇcn´ ych chyb 0 0 Poˇcet faleˇsn´ ych chyb 1 1
Tabulka 5.6: GCC vs. ICC, Randprog Testy -O0 -O2 Celkem 2500 2500 OK 2203 2249 Anom´alie pˇrekladu 0 0 Anom´alie ukonˇcen´ı 277 232 Anom´alie v´ ystupu 20 19 Selh´an´ı pˇrekladu 0 0 Ignorovan´e v´ ysledky 0 0 Poˇcet skuteˇcn´ ych chyb 0 0 Poˇcet faleˇsn´ ych chyb 0 0
Tabulka 5.7: GCC vs. Testy Celkem OK Selh´an´ı pˇrekladu Ignorovan´e v´ ysledky Poˇcet skuteˇcn´ ych chyb Poˇcet faleˇsn´ ych chyb
32
ICC, fuzz -O0 -O2 2500 2500 0 0 2500 2500 0 0 0 0 0 0
$ cat testcase . c # include < stdio .h > int main (){ unsigned long long a = 0 x1 . P +150000; signed long long b = 0 x1 . P +150000; printf (" Unsigned : % llu \ n " , a ); printf (" Signed : % lli \ n " , b ); }
// > ULLONG_MAX // > LLONG_MAX
$ gcc testcase . c ; ./ a . out Unsigned : 18446744073709551615 Signed : 9223372036854775807
// ULLONG_MAX // LLONG_MAX
$ icc testcase . c ; ./ a . out Unsigned : 0 Signed : -9223372036854775808
// ULLONG_MIN // LLONG_MIN
Obr´azek 5.1: Pˇr´ıklad chov´an´ı konverze typu pro vysok´e hodnoty
5.7.5
Zhodnocen´ı experimentu
V´ ystupy tohoto experimentu byly velmi sloˇzit´e na vyhodnocen´ı. Objevilo se mnoho anom´ ali´ı, kter´e byly zp˚ usobeny rozd´ıln´ ym chov´an´ım popsan´ ym v´ yˇse, a mezi jejich velk´ ym mnoˇzstv´ım bylo obt´ıˇzn´e a pracn´e hledat jak´ekoliv jin´e vadn´e chov´an´ı, coˇz vy´ ustilo ve fakt, ˇze nebyla nalezena jedin´a opravdov´a chyba. Z´aroveˇ n tak´e teto experiment uk´azal na nepohodlnost pr´ace s anom´aliemi v pˇr´ıpadˇe, ˇze jich je vˇetˇs´ı mnoˇzstv´ı, zp˚ usoben´e jednou pˇr´ıˇcinou.
5.8
Pˇ r´ıpad 4: gcc-stable, gcc-bleeding edge
Posledn´ı experiment se zab´ yval testov´an´ım posledn´ı v´ yvojov´e verze pˇrekladaˇce GCC, jehoˇz zdrojov´ y k´od byl staˇzen pˇr´ımo ze syst´emu spr´avy verz´ı. Tato kombinace byla zvolena pro otestov´an´ı moˇznosti pouˇz´ıt syst´em pˇri regresn´ım testov´an´ı pˇrekladaˇce.
5.8.1
Prostˇ red´ı a podm´ınky
Testovan´ y pˇ rekladaˇ c Testovan´ y pˇrekladaˇc byl GCC ve verzi 4.4.0, jehoˇz zdrojov´ y k´od byl z´ısk´an z vˇetve HEAD syst´emu spr´avy verz´ı dne 28.4.2008. Pˇreloˇzen byl proveden´ım pln´eho 3-f´azov´eho bootstrapu [2], coˇz dokazuje, ˇze pˇrekladaˇc je alespoˇ n tak kvalitn´ı, aby pˇreloˇzil s´am sebe. Referenˇ cn´ı pˇ rekladaˇ c Referenˇcn´ım pˇrekladaˇcem byl v tomto experimentu GNU Compiler Collection ve verzi 4.1.233, dod´avan´ y v RPM bal´ıˇcku distribuce Fedora gcc-4.1.2-33.fc8.rpm.
33
Prostˇ red´ı • Procesor: AMD Athlon(tm) 64 Processor 3800+ • Operaˇ cn´ı syst´ em: Fedora 8 • J´ adro: Linux 2.6.24.4-64.fc8 #1 SMP i686 athlon i386 GNU/Linux • Linker: GNU ld verze 2.17.50.0.18-1 20070731 • Knihovna C: glibc-2.7-2
5.8.2
Spitter
V´ ysledky uv´ad´ı tabulka 5.8. Toto testov´an´ı objevilo jednu chybu typu ICE-on-valid, kter´ a byla pˇr´ıtomn´a v obou pˇrekladaˇc´ıch a projevovala se jen s vypnut´ ymi optimalizacemi. Podrobnosti jsou uvedeny v dodatku A.3. Tato chyba byla nalezena pˇri zbˇeˇzn´em proch´ azen´ı logu selhan´ ych pˇreklad˚ u a pˇrinesla n´apad na moˇzn´e rozˇs´ıˇren´ı syst´emu pro zachyt´ av´ an´ı a hl´aˇsen´ı tˇechto pˇr´ıpad˚ u jako anom´alie. Faleˇsn´e hl´aˇsen´ı m´a svuj p˚ uvod ve vlastnosti jazyka C, kdy nen´ı urˇceno v jak´em poˇrad´ı jsou vyhodnocov´any jednotliv´e ˇc´asti v´ yrazu. Obˇe anom´alie obsahovaly v´ yraz, ve kter´em je jedna funkce vol´ana dvakr´ at s r˚ uzn´ ymi argumenty a v´ ysledkem je rozd´ıln´ y v´ ystup v pˇr´ıpadˇe rozd´ıln´eho poˇrad´ı vol´an´ı funkce.
5.8.3
Randprog
V´ ysledky uv´ad´ı tabulka 5.9. Objevena byla jedna chyba typu ICE-on-invalid (pops´ ana ystupu nebyly analyv dodatku A.4) v pˇr´ıpadˇe, ˇze byly vypnut´e optimalizace. Anom´alie v´ zov´any vzhledem k velikosti pˇr´ıpad˚ u, kter´e selhaly. Ve vˇsech pˇr´ıpadech se jednalo o n´ ahodn´e programy s v´ıce neˇz 4000 ˇr´adky a v´ıce neˇz dvaceti funkcemi.
5.8.4
fuzz
Nebyla nalezena ˇz´adn´a chyba. V´ ysledky uv´ad´ı tabulka 5.10.
5.8.5
Zhodnocen´ı experimentu
Tento experiment uk´azal na nedokonalost syst´emu v pˇr´ıpadˇe, ˇze pˇreklad nestandardnˇe (ICE) selˇze u obou pˇrekladaˇc˚ u. Takov´ y pˇr´ıpad je zaˇrazen jako Selh´an´ı pˇrekladu a m˚ uˇze tak b´ yt pˇrehl´ednut´ y, pokud jsou analyzov´any jen anom´alie. Toto by mˇelo b´ yt v budoucnosti oˇsetˇreno l´epe. Nalezeny byly dvˇe chyby, coˇz je niˇzˇs´ı v´ ysledek, neˇz se oˇcek´avalo u HEAD vˇetve projektu.
34
Tabulka 5.8: GCC 4.1.2 vs. GCC 4.4.0, Spitter Testy -O0 -O2 Celkem 2500 2500 OK 2476 2370 Anom´alie pˇrekladu 0 0 Anom´alie ukonˇcen´ı 0 0 Anom´alie v´ ystupu 2 0 Selh´an´ı pˇrekladu 13 13 Ignorovan´e v´ ysledky 9 117 Poˇcet skuteˇcn´ ych chyb 1 0 Poˇcet faleˇsn´ ych chyb 1 0
Tabulka 5.9: GCC 4.1.2 vs. GCC 4.4.0, Randprog Testy -O0 -O2 Celkem 2500 2500 OK 2249 2234 Anom´alie pˇrekladu 1 0 Anom´alie ukonˇcen´ı 250 261 Anom´alie v´ ystupu 0 5 Selh´an´ı pˇrekladu 0 0 Ignorovan´e v´ ysledky 0 0 Poˇcet skuteˇcn´ ych chyb 1 0 Poˇcet faleˇsn´ ych chyb 0 0
Tabulka 5.10: GCC 4.1.2 vs. Testy Celkem OK Selh´an´ı pˇrekladu Ignorovan´e v´ ysledky Poˇcet skuteˇcn´ ych chyb Poˇcet faleˇsn´ ych chyb
35
GCC 4.4.0, fuzz -O0 -O2 2500 2500 0 0 2500 2500 0 0 0 0 0 0
Kapitola 6
Z´ avˇ er V z´avˇeru jsou zhodnoceny dosaˇzen´e v´ ysledky a tak´e nast´ınˇen dalˇs´ı moˇzn´ y v´ yvoj projektu.
6.1
Zhodnocen´ı v´ ysledk˚ u
V t´eto pr´aci byla pops´ana problematika chyb v pˇrekladaˇcich, se zamˇeˇren´ım na typick´e problemy s nimi spojen´e. Byl navrˇzen pˇr´ıstup k testov´an´ı pˇrekladaˇc˚ u pomoc´ı automatizace metody fuzz testing. Podle tohoto pˇr´ıstupu byl implementov´an prototyp syst´emu pro testov´an´ı pˇrekladaˇc˚ u, se kter´ ym byly provedeny experimenty na tˇrech rozˇs´ıˇren´ ych pˇrekladaˇc´ıch v r˚ uzn´ ych verz´ıch. Ve dvou ze tˇr´ı takto testovan´ ych pˇrekladaˇc˚ u byly bˇehem experiment˚ u nalezeny chyby. N´asleduje zhodnocen´ı jednotliv´ ych ˇc´ast´ı projektu.
6.1.1
Gener´ atory n´ ahodn´ eho k´ odu
Byly prostudov´any moˇznosti sestrojen´ı gener´atoru n´ahodn´ ych vˇet platn´eho k´odu v jazyce C. Jeden gener´ator byl implementov´an autorem t´eto pr´ace, a pro lepˇs´ı zhodnocen´ı byly provedeny experimenty s gener´atorem k´odu jin´eho autora. Spitter Gener´ator implementovan´ y jako souˇc´ast t´eto pr´ace. Podaˇrilo se dos´ahnout relativnˇe sluˇsn´e u ´rovnˇe pouˇzitelnosti generovan´ ych vˇet pro testov´an´ı. Generovan´e vˇety byly rychle pˇreloˇziteln´e a tak´e s n´ızk´ ym trv´an´ım bˇehu. Avˇsak byly tak´e zjiˇstˇeny chyby a probl´emy, kter´e s sebou nese zvolen´e ˇreˇsen´ı. V pr˚ ubˇehu experiment˚ u se vyskytovaly dva vˇetˇs´ı probl´emy, kter´e byly zdrojem faleˇsn´ ych chybov´ ych hl´aˇsen´ı: • Nedefinovan´e poˇrad´ı vyhodnocov´an´ı podv´ yraz˚ u v jednom v´ yrazu. V pˇr´ıpadˇe, ˇze byla napˇr. jedna funkce vol´ana v jednom v´ yrazu v´ıcekr´at s r˚ uzn´ ymi parametry, pak se v´ ystup programu liˇsil v pˇr´ıpadˇe, ˇze pˇrekladaˇce zvolily odliˇsn´e poˇrad´ı vyhodnocen´ı v´ yraz˚ u. • Pˇr´ıliˇs vysok´e hodnoty konstant a v´ ysledk˚ u v´ yraz˚ u. Zejm´ena pˇri operac´ıch s velmi vysok´ ymi ˇc´ısly typu float ˇci double, kter´e ztr´acej´ı pˇresnost, se vyskytovaly probl´emy s odliˇsn´ ym v´ ystupem. Gener´ ator tak´e dok´azal produkovat jen velmi omezenou podmnoˇzinu jazyka C.
36
Randprog Tento gener´ator vol´ı jin´ y pˇr´ıstup k v´ ypisu v´ ystupu generovan´ ych program˚ u. V´ ystup je pouze jeden, a jsou do nˇej prom´ıtnuty vˇsechny operace proveden´e pˇri bˇehu programu. Tento pˇr´ıstup s sebou nese znaˇcn´e obt´ıˇze pˇri zjiˇst’ov´an´ı m´ısta, kde doˇslo k chybˇe. V´ yrazn´e jsou zvl´ aˇstˇe v kombinaci s druhou vlastnost´ı gener´atoru, kterou je ˇcasto velmi dlouh´ y vygenerovan´ y program – ˇcasto v ˇr´adu tis´ıc˚ u aˇz desetitis´ıc˚ u ˇr´adk˚ u, obsahuj´ıc´ıch mnoho dlouh´ ych cykl˚ ua rekurzivn´ıch vol´an´ı. Programy maj´ı velmi dlouhou dobu bˇehu, coˇz neguje z´asadn´ı v´ yhodu testovac´ı metody – moˇznost testovat velk´e mnoˇzstv´ı pˇr´ıpad˚ u za kr´atk´ y ˇcas. V´ yhodou Randprogu bylo, ˇze neprodukoval neplatn´ y k´od. Fakt, ˇze j´ım vytvoˇren´e programy se velmi ˇspatnˇe analyzuj´ı, ale zabr´anil nalezen´ı moˇzn´ ych chyb v programech, coˇz velmi sniˇzuje moˇznost jeho pouˇzit´ı pro tuto metodu testov´an´ı.
6.1.2
Syst´ em pro testov´ an´ı
Cel´ y syst´em fungoval pomˇernˇe spolehlivˇe. S jeho pomoc´ı bylo nalezeno nˇekolik chyb v pˇrekladaˇc´ıch. V´ yhodou bylo snadn´e pouˇzit´ı r˚ uzn´ ych gener´ator˚ u testovac´ıch pˇr´ıpad˚ u. Ponˇekud nepohodln´a je pr´ace s nalezen´ ymi anom´aliemi, kdy je tˇreba ruˇcnˇe analyzovat vytvoˇren´ y zdrojov´ y k´od a hledat m´ısto, kde se chyba vytv´aˇr´ı. Je to tak´e pracn´e a zdlouhav´e v pˇr´ıpadˇe vˇetˇs´ıho mnoˇzstv´ı anom´ali´ı, kter´e jsou n´asledkem jedin´e chyby. Syst´em by tak´e mohl l´epe zvl´adat situace, kdy dojde k ukonˇcen´ı programu n´asilnˇe z d˚ uvodu ˇcasov´eho limitu, nebo doruˇcen´ım nˇekter´eho ze sign´al˚ u zp˚ usobuj´ıc´ıch ukonˇcen´ı programu.
6.2
Zhodnocen´ı pouˇ zitelnosti metody
V t´eto pr´aci byla zkoum´ana pouˇzitelnost metody fuzz testing k testov´an´ı pˇrekladaˇc˚ u. Bylo dosaˇzeno pozitivn´ıch v´ ysledk˚ u, ale negativem z˚ ust´av´ a obt´ıˇzn´a anal´ yza samotn´eho selh´avaj´ıc´ıho testovac´ıho pˇr´ıpadu. Ve srovn´an´ı se statick´ ymi metodami tak´e tato dynamick´a metoda produkuje velk´e mnoˇzstv´ı faleˇsn´ ych upozornˇen´ı. Nepˇr´ıjemn´ y je tak´e fakt, ˇze jedna chyba m˚ uˇze zp˚ usobit velk´e mnoˇzstv´ı selh´an´ı, a v takov´em mnoˇzstv´ı se obt´ıˇznˇe hledaj´ı jin´e chyby. V pˇr´ıpadˇe, ˇze by tyto probl´emy byly odstranˇeny, pak je dle n´azoru autora tuto metodu moˇzn´e pouˇz´ıt k u ´spˇeˇsn´emu a snazˇs´ımu testov´an´ı pˇrekladaˇc˚ u.
6.3
Dalˇ s´ı v´ yvoj
Pro syst´em byl zaloˇzen projekt, um´ıstˇen´ y na http://code.googlecode.com/p/fucc/, kde bude pokraˇcovat jeho v´ yvoj. Z t´eto pr´ ace vypl´ yv´a pomˇernˇe jednoznaˇcn´ y postup pro dalˇs´ı v´ yvoj projektu. Je potˇreba se zamˇeˇrit zejm´ena na gener´ator, kde je nutn´e opravit chyby, kter´e zp˚ usobuj´ı generov´an´ı neplatn´eho nebo nedeterministick´eho k´odu. Bylo by tak´e dobr´e zvˇetˇsit podmnoˇzinu jazyka C, kterou Spitter dok´aˇze generovat. D´ale je nutn´e refaktorovat nebo rozdˇelit tˇr´ıdu Director gener´atoru, je pˇr´ıliˇs rozs´ahl´a a nepˇrehledn´a. V neposledn´ı ˇradˇe je tak´e tˇreba poskytnout programu moˇznost konfigurac´ı a vˇetˇs´ı robustnost. Velk´ ym pˇr´ınosem by tak´e bylo zhotoven´ı jednoduch´eho uˇzivatelsk´eho rozhran´ı, kter´e by zjednoduˇsilo pouˇzit´ı syst´emu. Pro anal´ yzu by byl velmi pˇr´ınosn´ y n´astroj, kter´ y by dok´azal z pˇredloˇzen´eho zdrojov´eho k´odu odstranit vˇsechno, co neovlivn´ı v´ ystup programu. V dlouhodob´em horizontu by mohlo b´ yt zaj´ımav´e zamˇeˇren´ı na Director, kter´ y byl m´enˇe v´az´an na konkr´etn´ı jazyk.
37
Dodatek A
Nalezen´ e chyby V t´eto ˇc´asti jsou uvedeny chyby v pˇrekladaˇc´ıch, nalezen´e ve f´azi testov´an´ı vytvoˇren´eho syst´emu. Jedn´a se o ruˇcnˇe vyextrahovan´e testovac´ı pˇr´ıpady, kter´e jsou upraveny tak, aby obsahovaly co nejmenˇs´ı mnoˇzstv´ı k´odu potˇrebn´eho pro demonstraci defektu.
A.1
Chyba 1
Um´ıstˇ en´ı chyby
GCC 4.1.2-33 se zapnut´ ymi optimalizacemi
Typ chyby wrong-code Zdrojov´ y k´ od a reprodukce $ cat tc1052.c #include int main(){ long var = 0x19DF1618; printf("var: %i\n", printf("var*var: %i\n", printf("(var*var) << var: %i\n", printf("LONG_MAX: %i\n", return 0; } $ gcc -O3 tc1052.c ; ./a.out var: 434050584 var*var: 800596544 (var*var) << var: 0 LONG_MAX: 2147483647
var); var*var); (var*var) << var); LONG_MAX);
Pˇ redpokl´ adan´ e chov´ an´ı $ gcc -O3 tc1052.c ; ./a.out var: 434050584 var*var: 800596544 (var*var) << var: 1073741824 LONG_MAX: 2147483647 38
A.2
Chyba 2
Um´ıstˇ en´ı chyby
GCC 4.1.2-33 se zapnut´ ymi optimalizacemi
Typ chyby wrong-code Zdrojov´ y k´ od a reprodukce $ cat tc661.c int main (int argc, void *argv[]) { unsigned long l_40452115 = 0x027F1A57; printf ("l_40452115: %i\n", l_40452115); printf ("l_40452115 >> l_40452115: %i\n", l_40452115 >> l_40452115); return 0; } $ gcc -O3 tc661.c ; ./a.out l_40452115: 41884247 l_40452115 >> l_40452115: 0 Pˇ redpokl´ adan´ e chov´ an´ı $ gcc -O3 tc661.c ; ./a.out l_40452115: 41884247 l_40452115 >> l_40452115: 4
39
A.3
Chyba 3
Um´ıstˇ en´ı chyby
GCC 4.1.2-33, a GCC 4.4.0, s vypnut´ ymi optimalizacemi
Typ chyby ICE-on-valid Zdrojov´ y k´ od a reprodukce $ cat tc250.c int main(){ float c2 = 1.0; if ( ! ! c2 * 07ll == 0 ){ printf("BOGUS!\n"); } else{ printf("PASS\n"); } } $ gcc tc250.c && ./a.out tc250.c: In function ‘main’: tc250.c:11: internal compiler error: in simplify_subreg, at simplify-rtx.c:3818 Pˇ redpokl´ adan´ e chov´ an´ı $ gcc tc250.c && ./a.out PASS
40
A.4
Chyba 4
Um´ıstˇ en´ı chyby
GCC 4.4.0, s vypnut´ ymi optimalizacemi
Typ chyby ICE-on-invalid Zdrojov´ y k´ od a reprodukce $ cat tc1047.c func_86234633 (unsigned long p_27126309) { unsigned char l_20121738 = 0xF9; if ((l_20121738 >> 0x97B05850)) { } } $ gcc tc1047.c -O0 -c tc1047.c: In function ‘func_86234633’: tc1047.c:4: warning: right shift count >= width of type tc1047.c:7: error: unrecognizable insn: (insn 6 5 7 3 tc1047.c:4 (set (reg:QI 60) (const_int -1750050736 [0x97b05850])) -1 (nil)) tc1047.c:7: internal compiler error: in extract_insn, at recog.c:1983 Pˇ redpokl´ adan´ e chov´ an´ı $ gcc tc1047.c -O0 -c tc1047.c: In function ‘func_86234633’: tc1047.c:4: warning: right shift count >= width of type
41
A.5
Chyba 5
Um´ıstˇ en´ı chyby
TCC 0.9.24
Typ chyby accepts-invalid Zdrojov´ y k´ od a reprodukce $ cat aaa.c int aaa(int P, long P, short P, double P){ int a = P; } $ tcc aaa.c -c && echo PASS || echo FAIL PASS Pˇ redpokl´ adan´ e chov´ an´ı $ tcc aaa.c -c && echo PASS || echo FAIL FAIL
42
A.6
Chyba 6
Um´ıstˇ en´ı chyby
TCC 0.9.24
Typ chyby wrong-code Zdrojov´ y k´ od a reprodukce $ cat 1536.c int main (int argc, char *argv[]) { int m1D = ’K’; double FT = 61.11; long ct = 0xB466; if ( (3795ll) % (long long)(FT) - FT > (long long)(L’\xaD’ + ct ) % (int)m1D){ printf ("NONE"); return 1; } return 0; } $ tcc 1536.c $ ./a.out && echo PASS Neopr´ avnˇ en´ y pˇ rı ´stup do pamˇ eti (SIGSEGV) Pˇ redpokl´ adan´ e chov´ an´ı $ tcc 1536.c $ ./a.out && echo PASS PASS
43
A.7
Chyba 7
Um´ıstˇ en´ı chyby
TCC 0.9.24
Typ chyby wrong-code Zdrojov´ y k´ od a reprodukce $ cat 16.c long long P4 = 1; int main (int argc, char *argv[]) { unsigned long long aaa = ((((long long)(0007Lu)) % ((long long)(0x81)))+P4); unsigned long long bbb = (17l); printf("aaa: %i\n", aaa); printf("bbb: %i\n", bbb); if (aaa >= bbb) printf ("--- This is under aaa >= bbb block from variables \n"); } $ tcc 16.c; ./a.out aaa: 8 bbb: 17 --- This is under (aaa >= bbb) block from variables Pˇ redpokl´ adan´ e chov´ an´ı $ tcc 16.c; ./a.out aaa: 8 bbb: 17
44
A.8
Chyba 8
Um´ıstˇ en´ı chyby
TCC 0.9.24
Typ chyby wrong-code Zdrojov´ y k´ od a reprodukce $ cat 16.c unsigned int B (short K) { K = (2 + ’U’); printf("K397L5: %i\n", K); if ((K - K) <= K) printf ("THIS IS IN ((%i-%i) <= %i BLOCK\n", K, K, K); else printf ("THIS IS IN ((%i-%i) <= %i ELSE BLOCK\n", K, K, K); return L’g’ + ((((long long) (L’~’)) % ((long long) (L’\?’ + (’g’))))); }; int main (int argc, char *argv[]) { B (L’\v’-2979u); } $ tcc 232.c; ./a.out K397L5: 87 THIS IS IN ((87-87) <= 87 ELSE BLOCK Pˇ redpokl´ adan´ e chov´ an´ı $ tcc 232.c; ./a.out K397L5: 87 THIS IS IN ((87-87) <= 87 BLOCK
45
A.9
Chyba 9
Um´ıstˇ en´ı chyby
TCC 0.9.24
Typ chyby wrong-code Zdrojov´ y k´ od a reprodukce $ cat try.c double a =1; int main(){ printf("%f\n",a); return 0; } $ cat try2.c long long Q = 1; int main (int argc, char *argv[]) { printf("Global long long Q: %llu\n", Q); } $ tcc try.c; ./a.out 0.000000 $ tcc try2.c; ./aout Global long long Q: 629445874048565249 Pˇ redpokl´ adan´ e chov´ an´ı $ tcc try.c; ./a.out 1.000000 $ tcc try2.c; ./aout Global long long Q: 1
46
A.10
Chyba 10
Um´ıstˇ en´ı chyby
TCC 0.9.24
Typ chyby wrong-code Zdrojov´ y k´ od a reprodukce $ cat tc551.c long long D = 1; int main(int argc, char *argv[]){ printf("LEFT : %u\n", (D)); printf("RIGHT: %u\n", (’+’ - 0l) + ’;’ - D + 0234620 ); if ( (D) <= (’+’ - 0l) + ’;’ - D + 0234620 ){ printf("PASS - WE ARE IN (LEFT <= RIGHT) IF BLOCK\n"); } } $ tcc tc551.c; ./a.out LEFT : 1 RIGHT: 80373 Pˇ redpokl´ adan´ e chov´ an´ı LEFT : 1 RIGHT: 80373 PASS - WE ARE IN (LEFT <= RIGHT) IF BLOCK
47
Literatura [1] GCC bugzilla keyword descriptions [online]. 2008 [cit. 2008-04-15]. Dostupn´ yz WWW: . [2] GCC online documentation [online]. 2008 [cit. 2008-05-13]. Dostupn´ y z WWW: . R C++ compiler documentation [online]. c2008 [cit. 2008-05-13]. [3] Intel, Inc. Intel Dostupn´ y z WWW: .
[4] Ohloh. Ohloh.net : Open Source, revealed [online]. 2008 [cit. 2008-05-13]. Dostupn´ yz WWW: . [5] Tiny C Compiler Reference Documentation [online]. 2008 [cit. 2008-05-13]. Dostupn´ y z WWW: . [6] AHO, Alfred V., et al. Compilers : Principles, Techniques, and Tools. 2nd edition. [s.l.] : Addison-Wesley, 2007. 964 s. [7] BEAZLEY, David M. PLY : Python Lex-Yacc [online]. [2007] [cit. 2008-04-12]. Dostupn´ y z WWW: . [9] Valgrind User Manual [online]. 2008 [cit. 2008-04-18]. Dostupn´ y z WWW: . [10] GRUNE, Dick, JACOBS, Ceriel J.H. Parsing techniques: A practical guide. Chichester, Anglie : Ellis Horwood Limited, 1990. [11] THOMAS, David, HUNT, Andrew. Program´ ator Pragmatik. Brno : Computer Press, 2007. 219 s. [12] JOHNSON, Stephen C. Yacc : Yet Another Compiler-Compiler [online]. [2007] [cit. 2008-04-12]. Dostupn´ y z WWW:
[14] LINDIG, Cristian. Random testing if C calling conventions. Sixth International Symposium on Automated and Analysis-Driven Debugging (AADEBUG) [s.l.] : [s.n.], 2003. Dostupn´ y z WWW: <www.st.cs.uni-sb.de/ lindig/papers/lindig-aadebug-2005.pdf>. [15] MITCHELL, Mark, OLDHAM, Jeffrey, SAMUEL, Alex. Pokroˇcil´e programov´ an´ı v operaˇcn´ım syst´emu Linux. Praha : Softpress, c2002. 265 s. ISBN 80-86497-29-1. [16] NOVILLO, Diego. From source to binary. Red Hat Magazine [online]. 2004, no. 2 [cit. 2008-03-23]. Dostupn´ y z WWW: . [17] SCHWARTZ, R. Writing nonsense with perl. Linux Magazine [online]. 1999, no. 9 [cit. 2008-03-23]. Dostupn´ y z WWW: . ˇ ycarsko, 1999. [18] ISO 9899 TC3. Programming Languages - C. ISO, Geneva, Sv´ [19] TURNER, Bryan. Random C Program Generator [online]. [2007] [cit. 2008-04-24]. Dostupn´ y z WWW: .
49