DEGREE PROJECT IN INFORMATION AND COMMUNICATION TECHNOLOGY, SECOND CYCLE, 30 CREDITS STOCKHOLM, SWEDEN 2020

Verification of Formal Requirements through Tracing

JORRIT J. OLTHUIS

KTH ROYAL INSTITUTE OF TECHNOLOGY SCHOOL OF ELECTRICAL ENGINEERING AND COMPUTER SCIENCE

ABSTRACT I

Abstract

Software development in the railway application is governed by strict stan- dards which aim to ensure safety. It is for example highly recommended to use formal methods when specifying requirements. Moreover, it is mandatory to have certain roles be fulfilled by different people. A common technique is developing software tests for the requirements. Mak- ing sure that software requirements are properly described, interpreted and implemented by different people is a major challenge. Tests fully depend on the tester to cover all scenarios. Having more methods that simplify require- ment tracing and that depends less on thoroughness of the tester would provide many benefits. This thesis investigates whether and how software tracing can be used to vali- date formal requirements of software. The goal is to perform trace validation such that it can be used to complement more traditional verification techniques. By verifying formal requirements on traces, the detection of errors depends on the events in the traces. As a consequence, more traces provide a higher chance of detecting errors. Thereby eliminating risk of the tester missing important cases. The presented verification approach firstly specifies requirements in lin- ear temporal logic and converts this specification to a non-deterministic Büchi automaton, or a finite state machine which is also evaluated. Secondly, the approach describes several alternatives for collecting traces and how to link those to the formal specification. Lastly, the verification approach proposes an algorithm which takes the Büchi automaton and a trace to detect violations of the requirement. The validation approach is implemented in form of multiple tools and its op- eration shown by means of a toy example. This example models a railway application such that its requirements can be verified using the tools. The re- sults are then used to show how these tools can be used in an actual railway application. Using these research outcomes, and the stand-alone tool, an implementation in Trace Compass is created. This can, just like the stand-alone tool, decide for each pair of trace and requirement whether the trace violates the requirement. II ABSTRACT

Swedish abstract

Programvaruutveckling i järnvägsapplikationen styrs av strikta standarder som syftar till att säkerställa säkerheten. Det rekommenderas till exempel starkt att använda formella metoder när krav anges. Dessutom är det obligatoriskt att vissa roller uppfylls av olika ingenjörer. En vanlig teknik är att utveckla programvarutest för kraven. Det är en stor utmaning att se till att programvarukrav beskrivs, tolkas och implementeras på rätt sätt av olika ingenjörer. Tester beror helt på testaren för att täcka alla scenarier. Att ha fler metoder som förenklar spårning av krav och som beror mindre på testarens noggrannhet skulle ge många fördelar. Denna avhandling undersöker om och hur spårning av programvara (software tracing) kan användas för att värdera formella krav på programvara. Målet är att utföra spårningsvalidering så att den kan användas för att komplettera mer traditionella verifieringstekniker. Genom att verifiera formella krav på spår (trace) beror upptäckten av fel på händelserna i spåren. Som en konsekvens ger fler spår större möjlighet för att detektera fel. Därmed elimineras risken för att testaren missar viktiga fall. Den presenterade verifieringsmetoden specifi- cerar först kraven i linear temporal logic och omvandlar denna specifikation till en icke-deterministisk Büchi-automat, eller en ändlig tillståndsautomat som också utvärderas. För det andra beskriver tillvägagångssättet flera alternativ för att samla in spår och hur man länkar dem till den formella specifikationen. Slutligen föreslår verifieringsmetoden en algoritm som tar Büchi-automaten och ett spår för att upptäcka överträdelser av kravet. Valideringsmetoden implementeras i form av flera verktyg och dess funktion visas med hjälp av ett leksaksexempel. Detta exempel modellerar en järn- vägsapplikation så att dess krav kan verifieras med verktygen. Resultaten an- vänds sedan för att visa hur dessa verktyg kan användas i en verklig järn- vägsapplikation. Med hjälp av dessa forskningsresultat och det fristående verktyget skapas en implementering i Trace Compass. Detta kan, precis som det fristående verktyget, avgöra för varje par av spår och krav om spårningen bryter mot kravet. CONTENTS III

Contents

1 Introduction 1 1.1 Project goal ...... 2 1.2 Literature survey ...... 2 1.3 Structure ...... 4

2 Requirement specification survey 5 2.1 Formal definition ...... 5 2.2 Verification ...... 7

3 Tracing survey 10 3.1 Tracing tools ...... 10 3.2 Tracepoints ...... 12 3.3 Information reduction ...... 17

4 Method 18 4.1 BT’s constraints ...... 18 4.2 Tool architecture ...... 19

5 Requirement conversion evaluation 21 5.1 Specification ...... 21 5.2 FSM algorithm ...... 23 5.3 NBA algorithm ...... 24

6 Verification evaluation 27 6.1 State reconstruction ...... 27 6.2 Automaton execution ...... 27

7 Application 30 7.1 Bombardier Transportation ...... 30 7.2 Trace Compass ...... 32

8 Conclusion 33

9 Future work 34 9.1 Timing ...... 34 9.2 Undecidability ...... 35 9.3 Requirement specification ...... 35 IV CONTENTS

A Requirement specification 43 A.1 Example requirement ...... 43 A.2 JSON Schema ...... 46

B Requirement negation 51

C NBA specification 53 C.1 Example NBA ...... 53 C.2 JSON Schema ...... 55

D NBA conversion 58

E Trace Compass 61 1 INTRODUCTION 1

1 Introduction

In situations where traditional verification techniques do not produce satisfac- tory results, tracing may be part of the solution. Tracing can be used to obtain information on a process while it is executing. Generally, this information is used for debugging, profiling and verification. By inserting tracepoints in the source code of the program, or using existing tracepoints in the kernel, one is able to identify the state of the execution. Every time execution passes by this tracepoint, an event is generated. These events are shown in figure 1. Each event may be of a different type. Depending on the type they can have different parameters. Together these events form a trace. A trace is a representation of the execution of a process. In turn, this execution is a finite prefix of a possibly infinite run of that process. This project seeks to apply analysis techniques to traces to verify formal re- quirements of the program. This approach can then be used to complement other forms of software verification [28]. This project was proposed by Bombardier Transportation (BT). BT is a mo- bility solution provider with a broad rail industry portfolio. Its products range from trains to sub-systems and from signalling to complete transport systems. 500 million people in 60 different countries rely on a daily basis on BT’s tech- nologies for their commute. In the European Union, railway applications have to conform to several stan- dards, including EN 50128 [13]. Five safety integrity levels (SILs) are defined to indicate different sets of requirements that ensure different levels of safety. For a product to be used as a system critical component, the development pro- cess must conform to a higher SIL. Verification through traces is an uncommon method of verification. In case it would be used as the primary verification method in BT, it may be subject to

Trace

Event Event Event int string double

Figure 1: Abstract representation of a trace and its run. 2 1 INTRODUCTION

additional checking during the assessment phase since it has not been explic- itly pre-approved by the standard. Especially for higher SILs, this may cause development delays. Using tracing as a complementing verification method- ology should not cause any such problems.

1.1 Project goal The goal of this thesis is to investigate how traces can be used in order to verify requirements of a system. The primary goal of the requirements that will be checked is to specify the temporal behaviour (i.e. ordering of events) of the system. Some requirements may have an absolute time limit associated to it. Even though temporal and timing requirements sound similar, both describe very different types of requirements. This report will mainly investigate the trace validity problem [35]. Traces will be collected in software (i.e. not through hardware techniques [14]) on the operating system running C, C++ or similar programs. Java programs are explicitly excluded, as they can use features available in the Java VM. The goal is to gather and verify event based traces. In other words, for each event that occurs, an event entry is added to the trace. The requirements that were specified should be verifiable based on these events. They may include timestamps which would, in the future, allow the verification of timing con- straints in requirements. The final goal of this project is to identify tracing techniques and use this knowledge to create a proof of concept system to verify requirements on BT’s software. Some reasoning and choices have been made according to their needs. These are specified in section 4.1.

1.2 Literature survey Related to this project, Butt [12] completed their master thesis on a similar topic also at BT. However, rather than to use tracing for verification, they use it for profiling. The report gives a useful overview of tracing tools on Linux and FreeBSD. Also, it provides some details on the architecture of one of BT’s systems. 1 INTRODUCTION 3

In 1998, Lee et al. [31] proposed the monitoring and checking (MaC) frame- work to verify a system at run-time. This led to the first Runtime Verification1 (RV) workshop in 2001. The objective of RV is “to monitor, analyze and guide the execution of programs” which is similar to the goal of this project. Since then, many more suitable techniques – which are based on MaC – have been proposed. Most existing literature looks at how to define correct behaviour and how to compare this specification to system traces. For example, Ancona et al. [5] propose, unlike most literature, to use a different formalism than linear tem- poral logic (LTL), called Trace Expressions. Trace Expressions offer three main differences with LTL which make it, according to the authors, better suited for RV. However, when considering citations, it has rarely been used by other people than the authors. Moreover, no applications of trace expressions in practice were found. Several papers discuss an application of RV. Generally, their implementa- tion was developed just for Java programs. Bodden [10], and D’Amorim and Havelund [16] present tools that can be used for the verification of programs written in Java. As the software at BT is mostly written in C and C++, these tools are not directly useful for our applications. Finally, Frama-C2 provides a set of tools to verify C-programs. Kosmatov and Signoles [28] discuss a few of these plugins because they state the following: “dynamic techniques are not bothered by C code complexity but are not ex- haustive, abstract interpretation is exhaustive and almost automatic but may be imprecise and cannot verify complex functional properties.” BT’s idea is in line with this quote, as they want to augment existing verification techniques with tracing. With a specification in (E-)ACSL one can perform both a deductive verifica- tion with the Wp plugin and RV with the E-ACSL plugin. Similarly, value analysis and test case generation plugins are also available. The RV plugin only allows checking at runtime. This means that the execu- tion time may significantly be affected when checking and make appear or hide certain bugs. More literature is evaluated in sections 2 and 3, where different techniques in the area of tracing and verification are compared.

1https://runtime-verification.github.io/ 2https://frama-c.com/ 4 1 INTRODUCTION

1.3 Structure This section describes the structure of the remainder of this report. Figure 2 shows a schematic representation of the connection between the following sec- tions. The next section evaluates different ways to formally specify requirements and how to transform these requirements such that they can be checked. This cor- responds to the two upper boxes in figure 2. Next, section 3 focuses on the lower boxes in figure 2. It mostly discusses how to collect traces, and how to make sure those are the traces required for evaluating the requirements. Then, section 4 describes how these different components will be combined into a single system, taking the details of BT into account. Sections 5 and 6 evaluate the development of the tools. These tools are applied in section 7 in three different ways. A conclusion is drawn in section 8 after which section 9 makes some suggestions for future extensions of the tools.

Formal Conversion to specification checkable format

Matching events Verification between specification and traces

Where to insert Cleaning up Tracing tools traces tracing results

Figure 2: Simplified trace validation process. 2 REQUIREMENT SPECIFICATION SURVEY 5

2 Requirement specification survey

The specification of requirements composed of two sections. Firstly, we look at specification languages that allow one to set requirements. After that, dif- ferent methods to verify these requirements are presented. The alternatives below focus on requirement verification, rather than model checking. The main reason for this is that model checking requires a full model of the program. The development of such a specification is very time consum- ing, and too expressive to use in combination with tracing.

2.1 Formal definition In order to judge if the traces describe a correctly behaving system, there has to be a notion of what this correct behaviour is. There are two main ways to do this: Create a model of the entire system, and verify if they are the same; or specify a set of requirements which is then evaluated on a per requirement basis. This section will investigate the latter. This gives the user a finer control of what is verified and significantly reduces effort if only a small part of the sys- tem is to be verified. The main challenge in choosing a suitable formalism, is to find a balance be- tween its expressiveness and how straightforward it can be verified [31]. Based on the reviewed literature, most research finds this balance in some form of temporal logic. The formalisms presented below form an overview of what is available. Many more have been proposed, both for RV and other applications.

ACSL As discussed in the book by Almeida et al. [1], the ANSI/ISO C Spec- ification Language (ACSL) can be used to specify behaviour for C programs. The language allows one to specify properties on different levels. For exam- ple, apart from loop function contracts, one can also specify loop invariants. This is specified as precisely formatted comments in the source code. The full language is very broad and offers many ways to specify requirements. There is a similar language available for Java. The Java Modeling Lang- uage [30] is intended to specify method contracts. In order to achieve this goal, it does not require strict specification rules. This makes it extremely expressive, and very difficult to verify. 6 2 REQUIREMENT SPECIFICATION SURVEY

CASL The common algebraic specification language by Bidoit and Mos- ses [9] is an expressive language. It offers a combination of basic, structured, and architectural specifications and also allowing for libraries of those. The language provides versatile toolset for specifying functional requirements. To make sure it can still be verified, Nunes et al. [37] use a subset of the CASL language for RV.

FSM One of the least expressive alternatives is MOPBox for Java by Bod- den [10]. It requires users to create an FSM manually, in order to specify their requirement. While being not so expressive, it is much easier to verify requirements structured in this way, as will be shown in section 2.2.

MITL metric interval temporal logic allows one to set timing constraints on temporal operators. This language, developed by Alur et al. [3], enables one to specify a time interval of an operator. The operations until, future and globally are able to have these timing constraints. The difference with traditional MTL it that it does not allow singular intervals (e.g. [a, a]) on an operator. In practice this is not a problem, as the interval can be made small (an arbitrarily precise interval is allowed by the theory).

Modal µ-calculus This formal language has been used to do formal specifi- cation for model checking, for example by Groote and Mousavi [24]. Moreover, as shown by Cranen et al. [15], LTL can be converted in linear time to modal µ-calculus. Moreover, LTL is a small subset of µ-calculus. The expressiveness that µ-calculus offers may therefore pose challenges when checking against this formalism.

PEDL and MEDL In the original RV paper by Lee et al. [31], two definition languages were proposed for specifying requirements and monitoring scripts. The primitive event definition language is used for monitor construction. The meta event definition language is proposed to specify the requirements. In hindsight the authors realise that developers prefer to use specification lan- guages with which they are already familiar [26]. 2 REQUIREMENT SPECIFICATION SURVEY 7

QuickCheck QuickCheck3 is a plugin for Haskell that allows one to specify requirements within the source code. It provides a framework to automatically generate test cases based on function contracts for Haskell. It has been ported to many different programming languages, however most use a different spec- ification format. For RV it might be possible to use QuickCheck to generate significantly dif- ferent test inputs. During these executions one can collect traces. It would be especially benifitial if the QuickCheck specification can also be used as RV requirements.

RV-LTL Bauer et al. [7] look at three different versions of LTL and combine LTL3 and fluent linear temporal logic (FLTL) [25] to form an LTL version specifically designed for RV. RV-LTL, as this new version is called, can eas- ily be transformed into an FSM for verification. Also, it handles undecidable requirements (which might occur since a trace is a prefix of a possibly infi- nite run) by providing, apart from true and false, two inconclusive properties, namely probably true and probably false. A variant of this newly introduced RV-LTL was used by Maggi et al. [32] to describe process models.

Uppaal Uppaal is a model checking tool that allows the user to specify net- works of timed automata and formulate requirements for these. It can also verify whether these requirements are satisfied [8]. For specification of re- quirements they use a modified version of computation tree logic (CTL) that can handle time.

2.2 Verification Most literature proposes to convert the formalism of a single requirement into an FSM or a non-deterministic Büchi automaton (NBA). With the main dif- ference being that the latter has been created for infinite inputs. Using either for verification is straightforward. Both NBAs and finite state machines formally take the input as a word consist- ing of letters. Each letter may change the state. For this specific application, the word is the full trace and each trace event is a letter. 3https://hackage.haskell.org/package/QuickCheck 8 2 REQUIREMENT SPECIFICATION SURVEY

FSM A finite state machine (or finite state automaton) is a graph that changes state based on the inputs it gets. Some states are final states. In our case, these final states indicate when the requirement was violated. An FSM is defined by the following

Σ The finite, non-empty set of accepted inputs Q The finite, non-empty set of states δ The set of transition functions, of type Q × Σ → Q

q0 The initial state, q0 ∈ Q F The set of final states, F ⊆ Q

An input word is accepted iff, after executing the FSM on the word, the current state is in F . The main advantage of an FSM is its simplicity. It is straightforward to check it using a program. Moreover, its intuitiveness helps engineers understand what behaviour the FSM is describing. As a bonus, most engineers will already have worked with FSMs before. A disadvantage of constructing an FSM may be the number of states. For a linear temporal logic (LTL) requirement, the number of states grows with O(22n ) (where n is the size of the LTL formula), as shown by Kupferman and Vardi [29]. If more output is necessary than one boolean per state, a Moore machine can be used instead. A Moore machine is similar to an FSM. The difference is that it does not have accepting states, but allows an arbitrary output to be connected to states [7].

Büchi automaton The Büchi automaton is a variation of finite automata, which can accept infinite inputs. The definition is very similar to that of a non- deterministic finite automaton (NFA) with the most notable difference being the acceptance condition. An NFA accepts any input that is described by the automaton. An NBA has an additional acceptance condition. Let W ∈ Σ∗ be the infinite input word of the Büchi automaton, that can generate run R. The input is accepted iff

∀r ⊂ R : ∃r0 : r ⊂ r0 ∧ (r0 \ r) ∩ F 6= ∅ 2 REQUIREMENT SPECIFICATION SURVEY 9

That is, for every prefix r in R, there exists another prefix r0 that contains r and has at least one element in the accepting set. Or formulated in natural language, the input is accepted iff there exists a run for the given W that will visit infinitely many final states. As proven by Vardi and Wolper [41], each linear time propositional tempo- ral logic requirement can be converted to and from Büchi automata. Gerth et al. [21] showed an algorithm for the conversion of an LTL requirement to a la- belled generalised Büchi automaton. Later, various improvements were made to this algorithm, and it has for example been used by Deutschmann et al. [18]. The existence of a conversion algorithm is an important reason to choose to use a non-deterministic Büchi automaton. The disadvantage of non-deterministic Büchi automaton, as noted by Gian- nakopoulou et al. [22], is that NBAs are too expressive for verifying finite traces. Finite state machines should be enough to validate finite traces. More- over, NBAs are less common and intuitive because they are non-deterministic. This means that engineers are less likely to be familiar with them.

Timing Although neither FSMs nor NBAs support timing information na- tively, their definition can easily be extended to incorporate this. Moreover, as proven by Alur et al. [3], it is still feasible to verify the timed variant. Alur et al. use MITL for specification and transform this into timed automata (Event Clock logic). Raskin and Schobbens [38] translate State Clock logic to a State Clock automaton, which are less expressive then MITL and Event Clock logic, respectively. Similarly, a timed version of Büchi automaton was introduced by Alur and Dill [2]. This modified form is called a timed Büchi automaton or TBA for short. 10 3 TRACING SURVEY

3 Tracing survey

In order to verify the requirements of the previous section, traces need to be collected. First, this section looks at tools for collecting traces. Then, it de- termines what the tracing needs are based on a system and its requirements. Finally, this section checks if processing the traces can be simplified by ex- tracting only necessary information first.

3.1 Tracing tools There is a wide range of tracing tools to choose from, all with slightly different characteristics. Most of the tools are dependent on a specific kernel. When choosing a tool, one should take the kernel and OS into account. The tools below are all selected to run at least on Linux. A summary can be found in table 1. Note that in some cases a simple debugging tool may provide enough informa- tion to identify events (e.g. by logging a different number per event), to verify requirements.

4https://www.chromium.org/developers/how-tos/ trace-event-profiling-tool

OS Type Output format Parameters License barectf Independent Userspace CTF User defined MIT Kernel function Linux Kernel Plaintext GPLv2 dependent Kernel and GPLv2, LTTng Linux CTF User defined userspace MIT ltrace Linux Library calls Plaintext (custom) Library call dependent GPLv2 Linux Syscalls Plaintext (custom) Syscall dependent LGPLv2.1 Plaintext (custom), Userspace Relative function entry uftrace Linux Chrome4, GPLv2 functions and exit time Flamegraph [23]

Table 1: Comparison of tracing tools. 3 TRACING SURVEY 11

barectf barectf5 has specifically been designed for systems with no or a very limited OS. It only requires stdint.h to function. It generates tra- cepoints that a developer can insert and build into their application. When the program is run, it will generate a trace in Common Trace Format6 (CTF). Tracepoints can fairly trivially be disabled through the use of define guards. However, this does require that the application is rebuilt. barectf is avail- able under the MIT license. ftrace ftrace7 can be used to trace Linux kernel functions. These points were inserted by kernel developers. This means one can follow what the kernel is doing and what interactions there are between processes. In most Linux distributions ftrace is disabled by default, enabling requires rebuilding the kernel. When tracepoints are built into the kernel but not used, there is no overhead penalty. ftrace is part of the Linux kernel and can therefore be used under the GNU GPLv2 license.

LTTng LTTng8 is a versatile tracing framework for Linux based operating systems. Just like barectf it outputs traces in the CTF format. These traces can originate from the kernel or from tracepoints inserted in the program by the developer. According to its developers, LTTng has a low overhead when tracing. The core components of LTTng are available under GNU GPLv2 and the MIT license. ltrace ltrace9 can track library calls that a specific program makes. De- pending on the architecture of an application, this can yield useful information on its structure and order when executing. Where possible, it will show read- able versions of parameters and return values of function calls. It does so in a custom format. It should be noted that at the time of writing, the most recent version was seven years old, released in 2013. ltrace is available for Linux distributions under the GNU GPLv2 license. 5https://github.com/efficios/barectf 6https://diamon.org/ctf/ 7https://www.kernel.org/doc/html/latest/trace/ftrace.html 8https://lttng.org/ 9https://www.ltrace.org/, https://linux.die.net/man/1/ltrace 12 3 TRACING SURVEY

strace strace10 is similar to ltrace. Instead, it traces all interactions between a process and the kernel (syscalls). Like ltrace it will show pa- rameters and return values in a readable form when possible. Moreover, it can connect to a process that is already running. Important to note that there is a speed penalty as described by Gregg11. It is released under the GNU LGPLv2.1 license. uftrace Finally, uftrace12 is a tool that can trace the functions in a pro- gram. It requires that a program is built using the -pg flag. It will measure which functions call each other, how much time is spent in each function and how often functions are called. Moreover, if the application was built with DWARF13 debugging information14, it can access parameters and return val- ues of functions. The output is in a custom format. It can however be converted to, among other formats, Brendan Gregg’s flamegraphs [23]. It is available un- der the GNU GPLv2 license.

3.2 Tracepoints Given the tools in section 3.1, the main question is how to use these tool to obtain traces. In general, lower level requirements involve more developer effort to generate the required traces. This section compares various situations when collecting traces. A summary of this section can be found in table 2. Little research has been done on which tracepoints are necessary to verify requirements on certain types of systems. Most likely, because this type of research is hard to generalise. Moreover, most formal analysis papers make an assumption about having proper traces. In practise this is not as easy. This section will identify a set of types of requirements. Then, an attempt is made to reason which events must be present in the trace to verify these types. The goal is to provide a suggestion as to which (additional) tracepoints one might need to implement in order to verify a certain type of requirement.

10https://strace.io/ 11http://www.brendangregg.com/perf.html#StaticKernelTracing 12https://github.com/namhyung/uftrace 13http://dwarfstd.org/ 14GCC will generate this when called with the -gdwarf flag. 3 TRACING SURVEY 13

Message Queue ftrace TCP/IP ftrace/strace Inter-process Shared memory ftrace/strace/ltrace Registers barectf/LTTng Libraries ltrace Intra-process Getters/setters uftrace Unstructured barectf/LTTng

Table 2: Summary of how to insert tracepoints based on requirements and program structure.

For the analyses below, the following tools and versions were used. For simpli- fying tracing of version 4.19.0 of the Linux kernel, trace-cmd 2.6.1 was used. Results for strace come from version 4.26, and ltrace ver- sion 0.7.3 was used. Further, LTTng version 2.10.6, uftrace version 0.9 and barectf version 2.3.1 were used.

Inter-process requirements The first category of requirements are those specified at the level of communi- cation between processes, or the level of input and output of a process. Several process communication techniques are identified below that might necessitate different tracing techniques.

Message queue Communication between two processes may happen through a message queue, set up on both sides. Here, the POSIX message queue15 sys- tem is used as an example. If the requirements do not need access to the payload of the messages in the queue, ftrace can be used to collect trace events. More specifically, sys_- mq_open shows that both sender and receiver open the same message queue. Both get a message queue descriptor for their respective end of the queue through the corresponding exit_syscall. After that, this descriptor is used to identify the queue when sending and receiving with sys_mq_timed- send and sys_mq_timedreceive respectively. Since the last two events have length as a property, one might be able to identify those based on length if only a few message queues are used. In theory, strace should be able to also trace these events, as they are syscalls. However, testing showed that we were not able to record these events.

15http://man7.org/linux/man-pages/man7/mq_overview.7.html 14 3 TRACING SURVEY

If more information is required from the perspective of the requirements, like the content of the messages, a tool like LTTng or barectf should be used. Both allow users to manually trace custom events with customer parameters. These parameters can be used to extract the important information.

TCP/IP A message queue is not possible if the processes are executing on different systems. A regularly used protocol is TCP/IP, however the below ap- plies to all processes that interface with Linux sockets. Similar to the message queue, ftrace tracepoints only contain very superfi- cial information on the communication. In order to obtain access to the con- tents of the packets, a similar approach to that of the message queue has to be used. Inserting manual tracepoints on the sender and/or on the receiver side gives access to more details. strace is able to provide more information than ftrace. Where ftrace provides only an identifier of the buffer, strace also records the actual pa- rameters. In this case, the read and write system calls are used to interact with the socket. strace reports this as a string, but the contents of the pack- age can be obtained in this way regardless of type. ltrace will also show the content of the packages, however it is much harder to identify different connections than it is with the strace output.

Shared memory Another way to communicate between two processes is via shared memory. Both processes get access to the same piece of memory, this way they can exchange information. As an example, the shared memory API of POSIX16 is used here. This situation is more difficult, as people are very much free to decide how to use this shared memory. As a consequence, ftrace provides no information that can be used in order to identify shared memory. strace shows that the process is retrieving information about the /de- v/shm filesystem. However, unlike socket communication it does not show any interactions with the shared memory. In some cases, like when sprintf() has been used to write to shared memory, ltrace will show the contents of what has been written. However, clearly, this is not a robust and generalisable setup. Generally, the most robust way to obtain events when using shared memory is to insert tracepoints manually where interactions with shared memory seg- ment happen. As said before, LTTng and barectf have these capabilities.

16http://man7.org/linux/man-pages/man7/shm_overview.7.html 3 TRACING SURVEY 15

Read/Write registers Most often, reading and writing registers is used on bare embedded systems17. Conceptually it is similar to shared memory, how- ever this does not require two processes for communication. It may rather be used as communication between a process and I/O on a hardware level. As this technique is used often in low-level systems, one should not expect the ability to install packages. As the tools under review did not provide great re- sults for shared memory, manual tracepoints with barectf will most likely be the best choice. If the system supports it, LTTng would be a fine choice also.

Intra-process requirements Requirements within a process are much more difficult to verify with off the shelf tracing solutions than requirements between processes. Most solutions use the kernel to get information on the behaviour of the process. Since now the parts of the process that are necessary for verification are not interacting with the kernel, those techniques cannot be used. Below, three scenarios for the structure of the program are identified. Each different architecture allows for a different type of tracing.

Libraries As mentioned in section 3.1, ltrace can be used to for tracing library calls. As in larger project components are often logically separated into different libraries. ltrace is then able to log the library calls, the parameters and return values. In most cases, this will be enough information to validate requirements of libraries.

Getters and setters Many requirements define a system state. Quite often this will correspond to the value of a certain variable or the values of a set of variables. Many variable are changed with getters and setters, as is common practise in object-oriented programming. If getters and setters are used, one can see their usage in the output of uf- trace. If the DWARF debugging was enabled when recording traces, the parameters and return values are saved. This allows one to validate the re- quirements based on a system state.

17As used in certain places in BT’s software. 16 3 TRACING SURVEY

Unstructured Finally, if there is no structure that helps to identify the state of the system, one has to insert traces manually. LTTng and barectf both support userspace tracepoints. It is advisable to insert tracepoints at every point where an important variable mentioned in a requirement may be modified. Depending on the situation, a balance should be found between creating more types of tracepoints, and storing more information in parameters of a single tracepoint type.

Timing requirements Requirements that enforce execution time of an algorithm or feature can easily be traced using uftrace. If uftrace cannot be used, one has to resort to a different tool. Note however, that these tools all require tracing to be inserted at or before compile time. If the requirements specify more advanced requirements than just the execu- tion time of a function, an alternative to uftrace has to be found. All tools presented in section 3.1 allow some form of timing information to be annotated to each event.

Algebraic requirements Some requirements may describe a system in mathematical formulas. Imag- ine a component of a system which should calculate the ith number in the Fibonacci sequence. Its requirement may contain the following specification √ √ 1+ 5 i 1− 5 i (( 2 ) − ( 2 ) ) Fi = √ 5 or even Fi = Fi−1 + Fi−2

In theory, it is possible to verify this requirement using traces. To formulate these requirements, one needs a formal language that is expressive enough. However, with such a language comes the drawback that verification becomes significantly more difficult. Moreover, there are different tools more suitable to check this type of require- ment. In trace validation, only the inputs that happen to occur in the traces will be verified. A value analysis [28] can do this for example for many more possible inputs. In some cases, static verification [28] might even be able to ensure all possible inputs satisfy the requirement. 3 TRACING SURVEY 17

3.3 Information reduction When many tracepoints are defined, a considerable amount of data is gener- ated. In RV, this data is processed during execution, which requires compu- tational power. Similarly, if the data the traces are stored, enough memory is required. Possibly, not all tracepoints are relevant in each state of the program. This might provide an opportunity to reduce the amount of data to be processed or stored. Research has been done in order to identify techniques to reduce traces. For example, Das and Johnson [17] and Khalid [27] looked at the accuracy of reduced traces. However, the goal in both cases was to simulate memory ac- cesses on computer architectures. The important difference is that losing any one specific tracepoint is not a problem for their application. For trace vali- dation this might be the difference between detecting a crucial error, and not doing so, or detecting an error that is not really there. More relevant research, like from Meyer and Wendehals [34], suggests to man- ually insert tracepoints only where instrumentation is required. It is indeed a good way to limit the number of tracepoints. However, this is mostly a manual process at design time, not an automated process when the traces are gen- erated. An automatic process would be preferred as enabling and disabling tracepoints manually is generally more time consuming than just processing more trace events. Finally, Fadel [20] shows a large number of state machines of trace events that describe certain types of typical Linux kernel behaviour. For example, reading a file is a fixed pattern of three system calls. In many cases, it is not necessary to get details of all these three events separately. Depending on the specific application, this might be summarised into a single access event. 18 4 METHOD

4 Method

The goal of this project is to develop a tool that can verify requirements of the BT software using runtime generated traces. To be able to test the tool, a toy example is created to generate traces, specify formal requirements and test the verification of requirements. This provides a simplified way to test the tools in a similar environment to that of BT. The tools that will be developed are later on tested on this simplified toy ex- ample. Given those results, it should be possible to reason about how the tools can be used at BT but also for other applications. Due to time constraints, the tools will not be tested on an actual BT product. Instead, an argument will be made how the results from the toy example can be used to reason about usage in a BT scenario. The next sections will define the constraints that Bombardier Transportation’s existing software puts on the tools. This will enable them to implement these more easily later on. It will also explain which techniques from sections 2 and 3 will be used, respectively.

4.1 BT’s constraints The situation at BT adds several constraints to those already identified in sec- tion 1.1. Firstly, the applications to be considered are written in C or C++ and are running on a Linux or simple (e.g. FreeRTOS18, or µc/OS-II19) operating system. In the latter case, this means that also the availability of tools is often limited. The programs are mostly running on very limited hardware. That is, low com- putational power and often small memory. Therefore, the goal should not be to analyse traces online (as is done in RV). No choices should make it impos- sible, however, to use the tool – albeit in a slightly modified form – in an RV setup. Finally, the implementation and verification have to be done by different peo- ple at all SIL levels [13]. This means it is preferable that one can set up the verification with as little knowledge as possible about the implementation.

18https://www.freertos.org/ 19https://www.micrium.com/rtos/kernels/ 4 METHOD 19

BT’s architecture consists of several software components that interact with each other. Most requirements however, specify the behaviour within a single component. Depending on the team and situation, requirements and commu- nication between components may take different forms. The requirements that will be checked in this system are mostly of the form Whenever a happens, b should happen where a and b are events. For exam- ple, Whenever a train has passed, a signal should be sent to the control room. Often, this is accompanied with a time limit. Note that these requirements are very informal. In the example above it may for example be unclear when a train is considered to have passed.

4.2 Tool architecture Given the constraints of the previous section, this section presents the choices made for the techniques used in the tool. Figure 3 shows a graph of how these choices are combined in the final solution. The tracing tool must at least allow for the insertion of tracepoints. Some code may have a clear structure, but not all parts do. To make the tool work for any implementation architecture, we choose to manually insert user space tracepoints. This leaves LTTng and barectf as best choices for tools. The choice between those will mainly be directed by the availability on the system. Inserting user space tracepoints manually takes more time and knowledge than using, for example, ftrace. However, manually evaluating the system and each requirement to choose the correct tracepoints according to section 3.2 will take even more time. If a kernel trace provide sufficient data, the tool should be able to handle it.

LTL3/LTL FSM/NBA

Matching events Verification between specification and traces

barectf / Manually inserted No cleaning LTTng tracepoints

Figure 3: Refined trace validation process according to choices of section 4.2, based on figure 2. 20 4 METHOD

As the search of section 3.3 did not yield any useful and reliable way to reduce the amount of traces before analysis, such a technique will not be used in the proof of concept. However, events will be filtered on a per requirement basis. For the specification LTL will be used. Bauer et al. [6] used LTL specifically for finite traces (or prefixes of infinite traces). Therefore, it suits our applica- tion rather well. Moreover, the CENELEC standard specifies temporal logic as a preferred technique for all SILs [13]. They also present an algorithm for validating traces. RV-LTL [7] would also have been an appropriate choice for a specification language. However, as the description of FLTL with its weak next operator and the conversion to an FSM are not described by Manna and Pnueli [33], LTL3 by itself should suffice. If the requirement can be validated on a finite trace, the outcome will be either accepted20 or violated. Otherwise, the result will be undecidable or violated depending on whether, in the finite trace, a violating condition has been ob- served. In order to check the requirement on the trace, it has to be converted to an automaton. An algorithm for this – without timing requirements – has been specified by Bauer et al. [6]. Note that the arrow in figure 3 represents the complete algorithm, which is made up of multiple conversion steps. Alternatively, an NBA can be constructed. The number of states of an NBA is significantly less than that of a similar FSM. Therefore there may be a situation where it is much more convenient to use an NBA than an FSM. In either case, timing can be checked by adding the corresponding information to the automaton. Most likely, this should take the form of a State Clock [38], or Event Clock [4] automaton where timing constraints are added respectively to states or transitions.

20Accepted in this context means that the requirement was not invalidated on this trace. The concept of RV implies acceptance based only on the observed events. 5 REQUIREMENT CONVERSION EVALUATION 21

5 Requirement conversion evaluation

This section evaluates the requirement conversion that was proposed in the previous section. The program that was developed for this, is available under the MIT license on GitLab21. First, the specification of formal requirements is discussed. After that, two alternatives are evaluated. First a conversion to FSM is discussed, after which the NBA algorithm is explained.

5.1 Specification There are several goals for the language to specify the requirements. Most importantly, it should be straightforward to use for specification, and straight- forward to parse by the tool. This mostly means that the format should not make this thing harder than they need to be. Moreover, it should be based on an existing and well known language, even though it is a domain specific lan- guage (DSL). Finally, there should be opportunity to extend the language (e.g. for timing). Existing LTL specifications do not seem to meet these criteria. SPIN22, for example, is a common way to specify LTL requirements. Unfortunately, it is hard to read for large and deeply nested requirements. Moreover, it would require a custom parser to read the requirements. The specification for requirements of this project will be done in JSON. Ap- pendix A shows a complete example of the specification of a requirement. Code 1 shows a short requirement. The specification starts with a name to identify the requirement. Next, LTL describes the requirement. There are two optional informal specifications to better understand the goal of the requirement (see appendix A). The formal requirement specification in the example in code 1 starts at line 5. This is a re- cursive specification of LTL operators and abstract propositions (APs). Each AP is true or false at every point in time, and can be switched on or off by each trace event. The operands are specified in JSON arrays to preserve their order.

21https://gitlab.com/trace-validation/requirement-converter 22https://spinroot.com/ 22 5 REQUIREMENT CONVERSION EVALUATION

The where section of the requirement starting at line 12 provides the relation between the events (APs) of the LTL and the events in the trace. This allows for more flexibility in specifying tracepoints, and more clear specification of LTL. Each event has one trace event which will set it to true, and a trace event which will disable the event. A single tracepoint can be used for different events. See for example line 51 and 57 in appendix A where two events refer to the same tracepoint. These events may be true at different times due to their different parameters. Parameters that may have any value should be set to null. If no parameters are used, like in code 1, the parameters section can be left out. This version of the LTL language supports all boolean operators and the most common LTL operators. Only weak until and strong release are not supported. In the remainder of the report, the LTL operators are denoted as follows. Glob- ally (G), future (F), until (U), release (R), and next (X ).

1 {"requirement":{ 2 "name": "Simple example", 3 "simplifiedLTL": "sensor -> barrier", 4 "LTL":{ 5 "formalLTL":[ 6 {"if":[ 7 {"event": "sensor"}, 8 {"event": "barrier"} 9 ]} 10 ] 11 }, 12 "where":[ 13 {"event": "sensor", 14 "on": "ust_sensor_a_active", 15 "off": "ust_sensor_a_inactive"}, 16 {"event": "barrier", 17 "on": "ust_barrier_down", 18 "off": "ust_barrier_up"} 19 ] 20 }}

Code 1: Simple example of requirement specification in JSON. 5 REQUIREMENT CONVERSION EVALUATION 23

say T Esparza (emptiness) Gerth et al. Gerth et al. Push to incoming Sipser Bauer et al. LTL 2x Tableau 2x LGBA 2x GBA + No accepting sets of states2x NBA Bauer et al. (construction)2x NFA 2x DFA FSM

(n) n ) 2 ) Θ(n) Θ (2 Θ(n+u) Θ(nu) Θ O(n

Figure 4: Steps when converting and LTL to and FSM, with their worst case execution time. n is the number of nodes in input, u the number of labels/tran- sitions.

LTL specification Debugging is made easier by having simple requirements. Generally this means that some order of events has to be satisfied. Simply checking the order of two events (a preceding b) can generally be done as fol- lows G(a → (a Ub)) [36]. If event b has to be preceded by another event, c, this becomes G(a → (a U(c ∧ (c Ub)). Any of a, b and c may be more complex than just a single AP.

Safety requirements Safety requirements describe, unlike liveliness require- ments, that something bad may never happen [11]. Note that a safety require- ment is not simply the negation of the liveliness requirement. For example, when checking for presence of an event ψ, the liveliness require- ment would be Fψ. The negation ¬Fψ does not perform the intended safety verification. Rather, F¬ψ models the correct safety requirement.

5.2 FSM algorithm As mentioned section 2.2, Bauer et al. [6] describe an algorithm to verify LTL with an FSM. The steps for this are shown in figure 4. This algorithm constructs two finite automata. One for the requirement, and another automaton for the negation of the requirement. Both automata will ac- cept or reject the input. If both accept the input, the requirement is undecidable on a finite trace. If the positive automaton accepts the input, the requirement is accepted. Similarly, if the negative automaton accepts the input, the require- ment is violated. 24 5 REQUIREMENT CONVERSION EVALUATION

The conversion is done separately to obtain each automaton. Firstly, using the algorithm by Gerth et al. [21], an NBA is constructed. Next, a check for emptiness [19, Chapter 13.1] is done on each state. Using these, the finite states of the non-deterministic finite automaton (NFA) can be constructed. From the NFA, a deterministic finite automaton (DFA) can be constructed. This is done through powerset construction [39, Page 55]. This means that each state in the DFA represents, for all states of the NFA, if they are active or inactive. Clearly, this causes the number of states to grow with O(2n). Even worse, since transitions have to be updated pairwise, the execution time is O((2n)2). In the final step of the algorithm, the automata are combined pairwise. This means that resulting FSM is a single Moore machine that can output satisfied, violated or undecidable. However this also means the size of the final automa- ton is the multiplication of number of states of each of the two automata. When testing with a reasonable LTL formula23, two NBAs were generated. One of these NBAs consisted of 20 states. This means that there will be 1 million states in the DFA. Extrapolating the test case performance indicated that generating the full FSM generation process could take up to 25 hours. As- suming the size FSM is related to the execution time, validation of a trace on the FSM will take a unreasonable amount of time. This is unusable in any real world application. Moreover, the reason why FSMs were chosen, for their simplicity, is completely negated by the size of the au- tomaton. Therefore, the next section described how the NBA algorithm was used instead. This will not only lead to faster algorithms, but also to smaller automata that are easier to understand.

5.3 NBA algorithm The construction of an NBA from an LTL formula is described by Gerth et al. [21]. The algorithm first constructs a tableau from the simplified negated normal form of the input. This means it takes the formula and recursively deconstructs it into tableau nodes. Later on, tableau nodes are converted to nodes of a labelled generalised Büchi automaton (LGBA). The conversion also requires the generation of labels for each node. Each node has a set of subsets of APs that are true. Each subset indicates a valid configuration for the state to be active. The LGBA is then converted into a generalised Büchi automaton (GBA) by moving the labels to

233 abstract propositions and 5 operators 5 REQUIREMENT CONVERSION EVALUATION 25

1.0 1.1 1.2 1.3 1.4

Figure 5: Execution times in seconds of the conversion of 8 different LTL requirements. the incoming edges of each node. Both LGBA and GBA have a set of sets of accepting states. The automaton is accepted if it is possible to visit at least one state from each subset infinitely often. As the final step, the NBA, which can be used for validation, can be generated. In general, the conversion is done by duplicating the set of GBA states for every accepting set in the GBA. This is also described by Gerth et al. [21] and in the form of an algorithm by Tsay [40]. The paper by Gerth et al. [21] states: “A protocol is verified w.r.t. a property by constructing and automaton for the negation of the property.”. In other words, the algorithm is applied to the negated LTL. For the goal of this application, we should use the positive LTL instead. When verifying requirements, it is most important to know when (and where) a re- quirement was violated. Using the positive LTL formula, the output can dis- tinguish between violated and undecidable requirements. The full reasoning, with an example can be found in appendix B. The resulting NBA is stored in a file to be used and reused later on. It contains all information required by the verification tool. Like the LTL input, the output is contained in a JSON file. Most importantly, it contains the states, transitions and a copy of the where specification. The JSON Schema and an example are available in appendix C. Pseudo code for the full conversion from LTL to NBA is available in ap- pendix D. 26 5 REQUIREMENT CONVERSION EVALUATION

Toy example To present the features of the conversion tool, we developed an example to verify. This toy example is available under the MIT license on GitLab24. It models the controller for a simple level crossing. There is a single rail track on which trains move in one direction only. On each side of the track there is a barrier which can be lowered by the controller, this takes some time. There are three sensors to measure the location of the train. Finally, there is a signal to stop the train if the barriers are not lowered fast enough. This C example is similar to software that might be found at BT. Also, eight different LTL requirements were constructed. The following results were ob- tained when converting these requirements to NBA. The execution time of this algorithm is much better than that of the algorithm described in section 5.2. Even converting requirements with many APs and operators happens almost instantly. Testing was done on a dual core Debian virtual machine with a base frequency of 2.7 GHz and 2 GB of memory. Testing on a set of various requirements has shown that all requirements are converted in under two seconds. Figure 5 contains a box plot to show the spread the execution times. These low execution times allow for low effort iterations when creating requirements. Moreover, it is possible to convert a requirement each time it will be checked, circumventing the time consuming action of writing the NBA file to disk. The latter will be used in section 7.2.

24https://gitlab.com/trace-validation/toy-example 6 VERIFICATION EVALUATION 27

6 Verification evaluation

This section describes the process of verifying the requirement. The tool that is described here is available under the MIT license on GitLab25. There are two steps the in the validation algorithm. Section 6.1 first details how traces are used in the NBA. Then, section 6.2 details how the execution of the NBA is done.

6.1 State reconstruction As described in section 5.3, labels of the transitions are a set of subsets of the abstract propositions. Those APs that are present in the subset must all be activated, and all other APs must be deactivated in order to be able to execute the transition. By the nature of traces, they will arrive in sequence, not in parallel. This means only one AP can active at one time. Hence, the trace cannot directly be used to transition the NBA. Instead, the trace is used to reconstruct the state of the program during execution. Each trace event may enable or disable an AP. This technique allows multiple APs to be active at the same time, and traverse the NBA the way it was intended. The where section in the LTL specification defines on what trace event an AP is switched on or off. As shown in appendix A, each event has an on and off. If the trace event listed in on occurs (with the correct parameters), the AP is set to true. Similarly, when the off event is detected (with the correct parameters), the AP is set to false.

6.2 Automaton execution With the activation data of APs from the previous section, the automaton is executed to determine if the requirement was violated or not. Figure 6 shows how the parts of the verification tool work together to verify requirements. The verification tool starts by reading and parsing the JSON requirement. It uses code generated by quicktype26 from the JSON Schema in appendix C to read the input automaton. Using the where field, it generates a reconstructed state containing all APs.

25https://gitlab.com/trace-validation/trace-validator 26https://app.quicktype.io 28 6 VERIFICATION EVALUATION

All APs are initialised to false. A possible future extension might be to allow the user to set an initial value for each AP27. If by simplification the AP true was added, a special element of the reconstructed state is initialised to always be true. The main verification process reads the events of trace one by one. The reading is performed by CTF libraries from Trace Compass. For each trace event, the reconstructed state is updated, after which one step is taken in the NBA. In each step a check is done to see if there are any current states left. If not, there is no path accepting the input, and the requirement has been violated. This saves time as the remainder of the trace does not have to be read. Finally, after all traces have been read, a check needs to be performed to de- termine if it is possible to visit infinitely many accepting states. It uses the two-stack algorithm [19, Chapter 13.1] to find a loop which can be reached from the current state and contains at least one accepting state. It is also possible to perform this check after every step, to provide more useful insight in the verification process as has been done in section 7.2. This might affect the execution time.

Toy example To test and obtain timing data, the same toy example is used as in section 5.3. Using LTTng, traces were generated. The verification is done using the previously generated NBAs. Some of the requirements should be accepted, some rejected and some were intended to be undecidable. The verification of this toy example has been automated and is also available on GitLab28. 27This does not increase the expressiveness of the specification language. An AP starting out true is simply the negation of what is specified starting out false. 28https://gitlab.com/trace-validation/verification-example

Trace events State reconstruction

Violated / Not violated LTL to NBA NBA Execution LTL NBA

Figure 6: Graphical representation of logical connections between parts of the verification tool. 6 VERIFICATION EVALUATION 29 250 200 150 Execution time [s] Execution 100 50 0

2e+05 4e+05 6e+05 8e+05 1e+06

Number of events

Figure 7: Number of events in a trace versus execution time. Violated inputs are depicted by a square, non-violated inputs are circular data points.

The real world execution time mostly depends on the number of events in the trace that have to be handled or can be ignored. Using the same eight require- ments as in section 5.3, the execution time has been measured on five different traces on the same hardware as before. Figure 7 shows the execution times in seconds depending on the size of the trace. There seems to be a weak relation between the number of events in the trace and execution time. Testing seems to indicate that the execution time depends on the combination of the number of useful events, the size of the NBA, and whether requirement is violated early on. The number of useful events are considered to be only those events that are related to an AP. 30 7 APPLICATION

7 Application

This section reviews two very different applications of the verification system. The first, section 7.1, determines how BT could use these tools to improve on their verification efforts. It will also review the BT-specific constraints set in section 4.1. The second application shows how the approach has been integrated in the Trace Compass analysis tool. It will also discuss the advantages of this imple- mentation over the stand-alone tools.

7.1 Bombardier Transportation Section 4.1 described the constraints for BT. This section reviews these con- straints and investigates how BT may use these tools in their workflow. As stated in section 1, trace validation should be considered as an additional method of verification. For example, to test scenarios that were not covered by the manually written unit tests. The environment described by section 4.1 is a Linux or very limited operating system running C or C++ code. LTTng and barectf can collect traces from C and C++ code on both types of operating systems, respectively. The section also mentions online verification. As requested, the tool does not support on- line (runtime) verification. However, there is no reason why the tool could not be modified to verify at runtime. Finally, it should be possible to verify with the least amount of knowledge of internal behaviour of the system. The main question here is who should be in charge of creating the link between traces and APs. Unfortunately, this cannot automated reliably, as internal knowledge of the system is required at least at some point. The proposal is to let the developer insert traces and create APs. For any SIL, another person can then convert the requirements to LTL with APs and without any internal knowledge of the system. Sometimes the devel- oper will have to add more traces and APs upon request of the tester. Luckily, both people have the same project manager [13] which makes such a request easy. 7 APPLICATION 31

The tools require two inputs. A requirement written in LTL and a trace in the CTF format. During testing, both inputs received various requirements and traces. Testing has demonstrated that traces can be obtained on one of BT’s Linux based platforms using barectf. Even more limited platforms should also be able to collect traces, possibly using the debugging or logging functionalities of those platforms. Since the specification of requirements is controlled by the railway standard [13], requirements originally formulated in natural language have to be converted to LTL. As previously discussed, not all requirements can be converted to LTL. An example of a possible conversion is given below. One software application of BT has the following requirement: “While miss- ing IO status from [an auxiliary] board, signals controlled by [this] board shall be considered faulty and [...] the affected signal shall be activated with alarms.” Note that this requirement is ambiguous, even for BT engineers, and that is possible to split the requirement. This means that there may be many ways to formulate this requirement. We assume that traces have been properly inserted such that the AP behave as expected.

G( missing IO =⇒ ((faulty ∧ signal on ∧ alarm) R missing IO))

Note that this requirement does not specify when the consequences need to become true. Without timing, this cannot be done reliably. More on this in section 9.1. Nonetheless, if the consequences never become true, missing IO may never become false. This also determines how the requirement can be vi- olated. If missing IO becomes true, after which it becomes false again, without the consequences being valid in the meanwhile, the requirement is violated. Note that this requirement does not enforce when the consequences may be- come false again. For this we might specify the following.

G((missing IO ∧ faulty ∧ signal on ∧ alarm) =⇒ (missing IO ∧ faulty ∧ signal on ∧ alarm) U ¬missing IO)

Both requirements are undecidable. Hence, they may only be violated in finite time. 32 7 APPLICATION

7.2 Trace Compass Trace Compass is a well known tool for analysing traces. It supports several trace types and can do many analyses independent of the trace type. Since it is based on the Eclipse platform, it provides an intuitive graphical interface. This interface allows the user to quickly combine several analysis techniques. These reasons make Trace Compass well suited to host the verification tool. To improve maintainability, the Trace Compass implementation is directly based on the standalone tool. Other than some small interface changes, both versions are identical. The main difference is that the conversion of the requirement is done for each new trace. As shown in section 5.3, this conversion takes little time. Moreover, skipping the step to write the NBA to a file, saves even more execution time. Another difference is when to check if it is possible to visit infinitely many accepting states as mentioned in section 6.2. The standalone tool only reports violation of the complete requirement. This is much faster as the check has to be executed only once, but also much more difficult to find the violating bug. Since the graphical interface in Trace Compass is well suited to show when the requirement was violated the choice was made to perform this check after every step in the automaton. The resulting ideal workflow would be to initially run the standalone tool. If a requirement is violated, Trace Compass can be used for more thorough debugging. Screenshots of the tool can be found in appendix E. The main interface is shown in figure 9. The verification tool adds several rows in the Gantt chart. Most importantly, Acceptance will show VIOLATED or NON_VIOLATED updated at every event. Moreover, the state of all APs and the activation of states of the NBA can be found in this chart. The latter can be used to more precisely location violations when debugging. Figure 10 shows how different analyses are connected. After selecting a range in the Gantt chart, the corresponding trace events are highlighted in the top view. This allows the user to pinpoint violating events and quickly find the corresponding portion of code. Finally, figure 11 shows a violation of a requirement. Since no state is active, there is no more path to accept the input. The combination of analyses shows that the violation occurred at toy_tracepoint:barrier(north, 1, 0). 8 CONCLUSION 33

8 Conclusion

The main goal of this project was to determine if tracing can be used to verify formal requirements. By implementing several tools, it has become clear that it possible automatically verify formal requirements that were specified in LTL. Theoretically it is possible to generate an FSM (Moore machine) which will execute on the trace as an input word. However, testing has shown that this requires an amount of resources that is considered unreasonable in most cases. Instead, verification can be done using non-deterministic Büchi automata. To obtain traces, several alternatives were considered. Some applications may be able to validate requirements using kernel traces. However, not be limited to those applications, LTTng and barectf were used for collecting traces during this project. Finally, several applications were evaluated. A toy example was used to show how the tools could be used, and that they work as expected. From the con- clusion drawn from this toy example, it was validated that the tools can accept traces generated by Bombardier Transportation’s platforms. This showed that they could apply these techniques as an additional verification method to the development of their software. In order to gain more insight into the trace analysis process, the tools were modified to operate as an analysis in Trace Compass. 34 9 FUTURE WORK

9 Future work

There are some ways in which the tools can be significantly improved later on. Three ideas are presented. The first idea involves adding timing constraints to LTL operators. This ad- dition allows for significantly more requirements to be verified. The second requirement takes the idea of Bauer et al. [6] to distinguish undecidable re- quirements, and proposes to apply it to NBAs. The final proposal are several steps that can reduce the verification efforts.

9.1 Timing As mentioned before in section 2.2, timing would enable the verification of a completely new class of requirements. For example, the BT requirement from section 7.1 could become as follows.

G( missing IO =⇒ ((faulty ∧ signal on ∧ alarm) R1ms missing IO))

The addition being the 1 millisecond bound on release. This check will ensure that faulty ∧ signal on ∧ alarm happen soon enough after the missing IO signal. Another application of the addition of timing may be automatically generated code. A code generation tool will generally claim correctness of the code. This means the functional operation corresponds to the specification. Generally, there is no guarantee regarding response time. This verification tool with timing could help to resolve this. The code generation tool may automat- ically include traces in the generated code, and also automatically convert the requirements to LTL such that verification can mostly be automated. The ver- ification tool may then, just like correctness, be used to find violations of the timing of the requirements. Various authors propose methods to implement timing in LTL. MITL by Alur et al. [3] adds time ranges to the until operator. Other than normal LTL, only the negation, conjunction and until operators are defined. However, most op- erators can still be rewritten to a combination of those three. In practise only the next operator is no longer available. The resulting structure to verify the requirement is a timed DFA. The paper does not provide an algorithm for this conversion, however the steps are spec- ified. Clearly due to the different structure of DFAs and possible violation due to timing, a new checker has to be built. 9 FUTURE WORK 35

three-valued timed linear temporal logic (TLTL3) is an extended version of LTL3 [6]. It allows one to specify timing intervals since or until the next event. Moreover, the paper describes how to generate a monitor for verification of this requirement. As with the normal conversion to an FSM in section 5.2, there may be significant worst case exponential growth in size of the FSM. Finally, real time linear temporal logic (RTLTL) by Deutschmann et al. [18] extends the LTL to LGBA conversion by adding timing semantics. This does not take the approach of absolute time, which might make its usage more com- plex. Instead, the execution steps of the NBA are the time unit. The advantage is that there is no need to update the verification tool.

9.2 Undecidability One of the advantages of verification with FSMs is the ability to determine ac- cepted conditions. From a positive and a negative NBA, positive and negative DFAs are constructed, respectively [6]. As shown in appendix B, the different NBAs are able to distinguish between violated and undecidable, and satisfied and undecidable requirements. The advantage of both detecting satisfaction and violation of the requirement not only more fine-grained feedback for the developer, it also saves verification time. After a requirement is satisfied or violated, there is no need to analyse the remainder of the trace. Bauer et al. [6] have shown and proven that the combination of two DFAs can be used to determine conclusively whether a requirement is undecidable. By reasoning and testing results, it seems likely that two separate NBAs can accomplish the same. Unfortunately, there is seems to be no literature available proving that this actually works.

9.3 Requirement specification Currently, basic requirement specification is supported. Certain changes may make using the tools much easier and thereby reduce the cost of this additional verification method. First, it should be possible match an AP to several trace events. Consider the scenario where there are three types of trace events: ust_on, ust_off1 and ust_off2. Clearly, ust_on will set the AP to true, however there is no clear way to set the AP to false when either of the off events occurs. The 36 9 FUTURE WORK

only way to do so would be to combine multiple APs in conjunction in place of the single AP. Obviously, this is very inconvenient and makes the requirement significantly more difficult to understand. Building this feature into the JSON specification and the validation tool should be straightforward. Instead of checking for each incoming trace event whether it equals an AP’s on or off, it should check if it is part of the on or off set. Finally, the other way to simplify requirement specification is the introduction of a graphical interface. This may in some cases help to understand large requirements. For example, it may replace sets of APs like faulty ∧ signal on ∧ alarm by consequences in the requirement in section 7.1. Another feature of this graphical interface may be to provide templates for commonly checked patterns (e.g. after event a, event b should happen) to speed up the construction of new requirements. REFERENCES 37

References

[1] José Bacelar Almeida, Maria João Frade, Jorge Sousa Pinto, and Simão Melo de Sousa. Rigorous Software Development. Springer Lon- don, 2011. [2] Rajeev Alur and David L. Dill. A theory of timed automata. Theoretical Computer Science, 126:183–235, 1994. [3] Rajeev Alur, Tomás Feder, and Thomas A. Henzinger. The Benefits of Relaxing Punctuality. Journal of the ACM, 43(1):116–146, January 1996. [4] Rajeev Alur, Lmor Fix, and Thomas A. Henzinger. Event-clock au- tomata: a determinizable class of timed automata. Theoretical Computer Science, 211:253–273, 1999. [5] Davide Ancona, Angelo Ferrando, and Viviana Mascardi. Comparing Trace Expressions and Linear Temporal Logic for Runtime Verification, pages 47–64. Springer International Publishing, March 2016. [6] Andreas Bauer, Martin Leucker, and Christian Schallhart. Monitoring of Real-Time Properties. In FSTTCS, pages 260–272, 2006. [7] Andreas Bauer, Martin Leucker, and Christian Schallhart. Comparing LTL Semantics for Runtime Verification. Journal of Logic and Compu- tation, 20(3):651–674, February 2009. [8] Gerd Behrmann, Alexandre David, and Kim G. Larsen. A Tutorial on Uppaal. In Lecture Notes in Computer Science, Lecture Notes in Com- puter Science, pages 200–236. Springer Berlin Heidelberg, 2004. [9] Michel Bidoit and Peter D. Mosses. CASL User Manual, volume 2900 of Lecture Notes in Computer Science. Springer-Verlag, 2004. [10] Eric Bodden. MOPBox: A Library Approach to Runtime Verification. In Runtime Verification, pages 365–369. Springer Berlin Heidelberg, 2012. [11] Manfred Broy and Ketil Stølen. Specification and Development of Inter- active Systems. Springer New York, 2001. [12] Haseeb Aslam Butt. Investigation into tools to increase Observability of 2oo2 OS based Generic Product. Master’s thesis, Kungliga Tekniska Högskolan, 2018. 38 REFERENCES

[13] CENELEC. Railway application – Communication, signalling and pro- cessing systems – Software for railway control and protection systems. Technical Report BS EN 50128:2011, British Standards Institution, June 2011. [14] Lukas Convent, Sebastian Hungerecker, Torben Scheffel, Malte Schmitz, Daniel Thoma, and Alexander Weiss. Hardware-Based Runtime Verifi- cation with Embedded Tracing Units and Stream Processing. In Runtime Verification, pages 43–63. Springer International Publishing, 2018. [15] Sjoerd Cranen, Jan Friso Groote, and Michel Reniers. A linear trans- lation from LTL to the first-order modal µ-calculus. Computer Science Reports, 1009, 2010. [16] Marcelo D’Amorim and Klaus Havelund. Jeagle: a JAVA Runtime Ver- ification tool, 2005. [17] Sudanshu K. Das and Eric E. Johnson. Accuracy of Filtered Traces, 1995. [18] Rocco Deutschmann, Matthias Fruth, Horst Reichel, and Hans-Christian Reuss. Trace Checking with Real-Time Specifications, 2004. [19] Javier Esparza. Automata theory - An algorithmic approach, 2012. [20] Waseem Fadel. Techniques for the Abstraction of Traces to Facilitate the Understanding of the Behavioural Aspects of the Linux Kernel. Master’s thesis, Concordia University, November 2010. [21] R. Gerth, D. Peled, M. Y. Vardi, and P. Wolper. Simple On-the-fly Au- tomatic Verification of Linear Temporal Logic. Proceedings of the 6th Symposium on Logic in Computer Science, pages 3–18, 1996. [22] Dimitra Giannakopoulou and Klaus Havelund. Automata-Based Veri- fication of Temporal Properties on Running Programs. In Automated Software Engineering, 2001. [23] Brendan Gregg. The Flame Graph. acmqueue, 14(2):1–28, 2016. [24] Jan Friso Groote and Mohammad Reza Mousavi. Modeling and Analysis of Communicating Systems. The MIT Press, 2014. [25] Jeff Kramer Jeff Magee. Concurrency: State Models and Java Programs. Wiley John + Sons, 2006. REFERENCES 39

[26] Sampath Kannan, Moonzoo Kim, Insup Lee, Oleg Sokolsky, and Ma- hesh Viswanathan. A Retrospective Look at the Monitoring and Check- ing (MaC) Framework. In Runtime Verification, pages 1–14. Springer International Publishing, 2019. [27] H. Khalid. Validating trace-driven microarchitectural simulations. Mi- cro, IEEE, 20(6):76–82, December 2000. [28] Nikolai Kosmatov and Julien Signoles. Frama-C, A Collaborative Framework for C Code Verification: Tutorial Synopsis. In Runtime Ver- ification, pages 92–115. Springer International Publishing, 2016. [29] Orna Kupferman and Moshe Y. Vardi. Model Checking of Safety Prop- erties. Formal Methods in System Design, 19:291–314, 2001. [30] Gary T. Leavens and Yoonsik Cheon. Design by Contract with JML, September 2006. [31] Insup Lee, Hanene Ben-Abdallah, Sampath Kannan, Moonjoo Kim, Oleg Sokolsky, and Mahesh Viswanathan. A Monitoring and Checking Framework for Run-time Correctness Assurance, October 1998. [32] Fabrizio Maria Maggi, Michael Westergaard, Marco Montali, and Wil M. P. van der Aalst. Runtime Verification of LTL-Based Declarative Pro- cess Models. In Runtime Verification, pages 131–146. Springer Berlin Heidelberg, 2012. [33] Zohar Manna and Amir Pnueli. Temporal Verification of Reactive Sys- tems: Safety. Springer New York, 1995. [34] Matthias Meyer and Lothar Wendehals. Selective Tracing for Dynamic Analyses. In In Proc. of the 1 st Workshop on Program Comprehension through Dynamic Analysis (PCODA) at 12 th WCRE, pages 33–37. Uni- versiteit, 2005. [35] Aouatef Mrad, Samatar Ahmed, Sylvain Hallé, and Éric Beaudet. Ba- belTrace: A Collection of Transducers for Trace Validation. In Runtime Verification, pages 126–130. Springer Berlin Heidelberg, 2013. [36] Richard M. Murray, Nok Wongpiromsarn, and Ufuk Topcu. Lecture 3 - Linear Temporal Logic (LTL), 2012. Slide 6 + 21. 40 REFERENCES

[37] Isabel Nunes, Antónia Lopes, and Vasco T. Vasconcelos. Bridging the Gap between Algebraic Specification and Object-Oriented Generic Pro- gramming. In Runtime Verification, pages 115–131. Springer Berlin Hei- delberg, 2009. [38] Jean-François Raskin and Pierre-Yves Schobbens. State clock logic: A decidable real-time logic, 1997. [39] Micheal Sipser. Introduction to the theory of computation. PWS Pub. Co., 1997. [40] Yin-Kuen Tsay. Büchi Automata and Model Checking, 2009. [41] Moshe Vardi and Pierre Wolper. An Automata-Theoretic Approach to Automatic Program Verification, 1986. ACRONYMS 41

Acronyms

ACSL ANSI/ISO C Specification Language. 5 AP abstract proposition. 21–24, 26–32, 35, 36, 51

BT Bombardier Transportation. III, 1–4, 15, 18, 19, 26, 30, 31, 33, 34, 52

CASL common algebraic specification language. 6 CTF Common Trace Format. 11, 28, 31 CTL computation tree logic. 7

DFA deterministic finite automaton. 24, 34, 35 DSL domain specific language. 21

FLTL fluent linear temporal logic. 7, 20 FSM finite state machine. I, III, 6–9, 20, 21, 23, 24, 33, 35

GBA generalised Büchi automaton. 24, 25

LGBA labelled generalised Büchi automaton. 9, 24, 25, 35 LTL linear temporal logic. I, 3, 6–9, 20–27, 30, 31, 33–35, 51, 58

LTL3 three-valued linear temporal logic. 7, 20, 35

MaC monitoring and checking. 3 MEDL meta event definition language. 6 MITL metric interval temporal logic. 6, 9, 34 MTL metric temporal logic. 6

NBA non-deterministic Büchi automaton. I, III, IV, 7–9, 20, 21, 24–29, 32– 35, 51–53, 58 NFA non-deterministic finite automaton. 8, 24 42 ACRONYMS

PEDL primitive event definition language. 6 PTL propositional temporal logic. 9

RTLTL real time linear temporal logic. 35 RV Runtime Verification. 3, 5–7, 17, 18, 20 RV-LTL runtime verification linear temporal logic. 7, 20

SIL safety integrity level. 1, 2, 18, 20, 30

TBA timed Büchi automaton. 9

TLTL3 three-valued timed linear temporal logic. 35 A REQUIREMENT SPECIFICATION 43

A Requirement specification

A.1 Example requirement

1 { 2 "name": "Stop signal", 3 4 "LTL":{ 5 "natural language": "If sensor b is activated and not both barriers are down, set the signal to stop. All within a single iteration.", 6 "simplifiedLTL": "G( (b && !(N down && S down)) -> ((b && !(N down && S down) && !endloop) U !signal))", 7 "formalLTL":[ 8 {"globally":[ 9 {"if":[ 10 {"and":[ 11 {"not":[ 12 {"and":[ 13 {"event": "N down"}, 14 {"event": "S down"} 15 ]} 16 ]}, 17 {"event": "b"} 18 ]}, 19 {"until":[ 20 {"and":[ 21 {"not":[ 22 {"and":[ 23 {"event": "N down"}, 24 {"event": "S down"} 25 ]} 26 ]}, 27 {"and":[ 28 {"event": "b"}, 29 {"not":[ 30 {"event": "endloop"} 44 A REQUIREMENT SPECIFICATION

31 ]} 32 ]} 33 ]}, 34 {"not":[ 35 {"event": "signal"} 36 ]} 37 ]} 38 ]} 39 ]} 40 ] 41 }, 42 43 "where":[ 44 {"event": "b", 45 "on": "toy_tracepoint:sensor", 46 "on parameters":["b", "1"], 47 "off": "toy_tracepoint:sensor", 48 "off parameters":["b", "0"] 49 }, 50 {"event": "N down", 51 "on": "toy_tracepoint:barrier", 52 "on parameters":["north", "0","0"] , 53 "off": "toy_tracepoint:barrier", 54 "off parameters":["north", null, null] 55 }, 56 {"event": "S down", 57 "on": "toy_tracepoint:barrier", 58 "on parameters":["south", "0","0"] , 59 "off": "toy_tracepoint:barrier", 60 "off parameters":["south", null, null] 61 }, 62 {"event": "endloop", 63 "on": "toy_tracepoint:event", 64 "on parameters":["loop", "0"], 65 "off": "toy_tracepoint:event", A REQUIREMENT SPECIFICATION 45

66 "off parameters":["loop", "1"] 67 }, 68 {"event": "signal", 69 "on": "toy_tracepoint:signal", 70 "on parameters":["1"], 71 "off": "toy_tracepoint:signal", 72 "off parameters":["0"] 73 } 74 ] 75 } 46 A REQUIREMENT SPECIFICATION

A.2 JSON Schema

1 { 2 "$schema": "http://json-schema.org/draft -07/schema#", 3 "title": "LTL Requirement Schema", 4 5 "definitions":{ 6 " event ":{"type": "string"}, 7 "operator":{ 8 "type": "object", 9 "minProperties":1, 10 "maxProperties":1, 11 "properties":{ 12 " and ":{"$ref": "#/definitions/ and "}, 13 " or ":{"$ref": "#/definitions/or "}, 14 " if ":{"$ref": "#/definitions/if "}, 15 " iff ":{"$ref": "#/definitions/ iff "}, 16 " not ":{"$ref": "#/definitions/ not "}, 17 "globally":{"$ref":"#/ definitions/globally"}, 18 " future ":{"$ref": "#/definitions/ future "}, 19 " next ":{"$ref": "#/definitions/ next "}, 20 " until ":{"$ref": "#/definitions/ until "}, 21 " release ":{"$ref":"#/ definitions/release"}, 22 " event ":{"$ref": "#/definitions/ event "} 23 } 24 }, 25 " and ":{ 26 "type": "array", A REQUIREMENT SPECIFICATION 47

27 "minItems":2, 28 "maxItems":2, 29 "items":{"$ref": "#/definitions/ operator "} 30 }, 31 " or ":{ 32 "type": "array", 33 "minItems":2, 34 "maxItems":2, 35 "items":{"$ref": "#/definitions/ operator "} 36 }, 37 " if ":{ 38 "type": "array", 39 "minItems":2, 40 "maxItems":2, 41 "items":{"$ref": "#/definitions/ operator "} 42 }, 43 " iff ":{ 44 "type": "array", 45 "minItems":2, 46 "maxItems":2, 47 "items":{"$ref": "#/definitions/ operator "} 48 }, 49 " not ":{ 50 "type": "array", 51 "minItems":1, 52 "maxItems":1, 53 "items":{"$ref": "#/definitions/ operator "} 54 }, 55 "globally":{ 56 "type": "array", 57 "minItems":1, 58 "maxItems":1, 59 "items":{"$ref": "#/definitions/ operator "} 48 A REQUIREMENT SPECIFICATION

60 }, 61 " future ":{ 62 "type": "array", 63 "minItems":1, 64 "maxItems":1, 65 "items":{"$ref": "#/definitions/ operator "} 66 }, 67 " next ":{ 68 "type": "array", 69 "minItems":1, 70 "maxItems":1, 71 "items":{"$ref": "#/definitions/ operator "} 72 }, 73 " until ":{ 74 "type": "array", 75 "minItems":2, 76 "maxItems":2, 77 "items":{"$ref": "#/definitions/ operator "} 78 }, 79 " release ":{ 80 "type": "array", 81 "minItems":2, 82 "maxItems":2, 83 "items":{"$ref": "#/definitions/ operator "} 84 } 85 }, 86 87 "type": "object", 88 "properties":{ 89 " name ":{ 90 "description": "General name to describe requirement", 91 "type": "string" 92 }, 93 "LTL":{ A REQUIREMENT SPECIFICATION 49

94 "description": "Specification of the requirement", 95 "type": "object", 96 "properties":{ 97 "natural language":{"type":" string "}, 98 "simplified LTL":{"type": "string "}, 99 "formal LTL":{ 100 "type": "array", 101 "minItems":1, 102 "maxItems":1, 103 "items":[{"$ref":"#/ definitions/operator"}] 104 } 105 }, 106 "required":["formal LTL"], 107 "minProperties":1, 108 "maxProperties":3, 109 "additionalProperties": false 110 }, 111 " split ":{ 112 "description": "Optional indication on where to split iterations", 113 "type": "array", 114 "items":{"type": "string"} 115 }, 116 " where ":{ 117 "description": "Relation between events in the requirement and events in the trace", 118 "type": "array", 119 "items":{ 120 "type": "object", 121 "properties":{ 122 " event ":{"type": "string"}, 123 " on ":{"type": "string"}, 124 "on parameters":{ 125 "type": "array", 50 A REQUIREMENT SPECIFICATION

126 "minItems":1, 127 "items":{"type":["string", " null "]} 128 }, 129 " off ":{"type": "string"}, 130 "off parameters":{ 131 "type": "array", 132 "minItems":1, 133 "items":{"type":["string", " null "]} 134 } 135 }, 136 "required":["event", "on", "off"] , 137 "uniqueItems": true, 138 "minProperties":3, 139 "maxProperties":5 140 } 141 } 142 }, 143 "required":["name", "LTL", "where"], 144 "additionalProperties": false, 145 "minProperties":3, 146 "maxProperties":4 147 } B REQUIREMENT NEGATION 51

B Requirement negation

Gerth et al. [21] state that one should use negation of the original requirement. Their goal is, implicitly, to determine when the requirement has been satis- fied. Bauer et al. [6] use a similar negation in definition 2. They construct two automata, a positive and a negated automaton, to distinguish between satis- faction, violation and undecidability. Table 3 shows the relation between au- tomata and the possible outputs. If the positive or negated automaton reject the input, the requirements are violated and satisfied, respectively. If both accept the input, the requirement is undecidable on a finite input. If both automata are correctly generated, it should not be possible for both automata to reject the input. If we look at a simple example, where φ = Ga and ψ = ¬φ = ¬Ga = F¬a. φ is checking if in all instances, the AP called a is true. The corresponding positive NBA can be found in figure 8a. It will accept any input that has a at every instance. As soon as there is no a, there will be no path to accept the input. Figure 8b contains the negation of φ, which is equal to ψ. The edges labelled with a star are activated on any input. Until ¬a has been seen at least once, it might be possible to accept the input in the future. After ¬a has been seen, the accepting state will be active forever. Both requirements are undecidable, but might already be violated or satisfied on a finite input. If we use both automata to validate the original requirement, φ, we see the following. Requirement φ will accept the input (and determine that the input has been satisfied) if in none of the input steps, a was false. If a was false in at least one

Negated (ψ)

Accept Reject

Reject Violated ) φ Positive ( Accept Undecidable Satisfied

Table 3: Satisfaction of a requirement depending on whether the positive or negated LTL is used. 52 B REQUIREMENT NEGATION

* {a} *

{¬a}

(a) NBA for φ (b) NBA for ψ

Figure 8: Simple NBAs to verify φ and ψ. step, the input is rejected and the requirement is violated. This corresponds to top left and bottom two the entries in table 3, respectively. Requirement ψ is different, as it accepts any input. There will always be a possibility to reach the accepting state (and stay there) in the future. As this the negation of the original requirement, this means that it will always be possible to violate the requirement29, even if the requirement is undecidable. As can be seen in the acceptance column in table 3, there is no way to distinguish between violated and undecidability without another automaton. Since BT is most interested in finding requirement violations, it is important to distinguish violating requirements. The only way to do so, is by using the positive requirement (see table 3). Hence, the suggestion to use the negation of the requirement is not followed.

29The negation of the original requirement maps rejecting the input to satisfaction of the requirement. C NBA SPECIFICATION 53

C NBA specification

C.1 Example NBA

1 { 2 "name": "Example NBA", 3 "automaton":{ 4 "states":[ 5 {"ID":"0", 6 "initial": true, 7 "accepting": false 8 }, 9 {"ID":"1", 10 "initial": true, 11 "accepting": true 12 }, 13 {"ID":"2", 14 "initial": false, 15 "accepting": false 16 } 17 ], 18 "transitions":[ 19 ["0",["a", "b"],"1"], 20 ["0",["b"],"1"], 21 ["1",["a", "b", "c"],"0"], 22 ["1",["a", "c"],"2"], 23 ["2",["c"],"0"] 24 ], 25 "where":[ 26 {"event": "a", 27 "on": "a1", 28 "off": "a2", 29 }, 30 {"event": "b", 31 "on": "b", 32 "on parameters":["start"], 33 "off": "b", 34 "off parameters":["stop"] 35 }, 54 C NBA SPECIFICATION

36 {"event": "c", 37 "on": "trace_event_c", 38 "on parameters":[null, "enable"], 39 "off": "trace_event_c", 40 "off parameters":[null, "disable" ] 41 } 42 ] 43 } 44 } C NBA SPECIFICATION 55

C.2 JSON Schema

1 { 2 "$schema": "http://json-schema.org/draft -07/schema#", 3 "title": "NBA Schema", 4 5 "definitions":{ 6 " state ":{ 7 "type": "object", 8 "properties":{ 9 "ID":{"type": "string"}, 10 " initial ":{"type": "boolean"}, 11 "accepting":{"type": "boolean"} 12 }, 13 "required":["ID", "initial", " accepting "], 14 "minProperties":3, 15 "maxProperties":3 16 }, 17 "transition":{ 18 "type": "array", 19 "description": "Array of[source ID, {trace event}, destination ID]", 20 "items":[ 21 {"type": "string"}, 22 {"type": "array", 23 "items":{"type": "string"} 24 } 25 ], 26 "minItems":3, 27 "maxItems":3, 28 "additionalProperties": false 29 } 30 }, 31 32 "type": "object", 33 "properties":{ 34 " name ":{ 56 C NBA SPECIFICATION

35 "description": "Name to describe the requirement", 36 "type": "string" 37 }, 38 " split ":{ 39 "description": "Optional indication on where to split iterations", 40 "type": "array", 41 "items":{"type": "string"}, 42 "minItems":1 43 }, 44 "automaton":{ 45 "type": "object", 46 "properties":{ 47 " states ":{ 48 "type": "array", 49 "items":[{"$ref":"#/ definitions/state"}], 50 "minItems":1 51 }, 52 "transitions":{ 53 "type": "array", 54 "items":[{"$ref":"#/ definitions/transition"}], 55 "minItems":1 56 } 57 }, 58 "required":["states", "transitions" ], 59 "additionalProperties": false, 60 "minProperties":2, 61 "maxProperties":2 62 }, 63 " where ":{ 64 "description": "Relation between events in the requirement and events in the trace", 65 "type": "array", 66 "items":{ C NBA SPECIFICATION 57

67 "type": "object", 68 "properties":{ 69 " event ":{"type": "string"}, 70 " on ":{"type": "string"}, 71 "on parameters":{ 72 "type": "array", 73 "minItems":1, 74 "items":{"type":["string", " null "]} 75 }, 76 " off ":{"type": "string"}, 77 "off parameters":{ 78 "type": "array", 79 "minItems":1, 80 "items":{"type":["string", " null "]} 81 } 82 }, 83 "required":["event", "on", "off"] , 84 "uniqueItems": true, 85 "minProperties":3, 86 "maxProperties":5 87 } 88 } 89 }, 90 "required":["name", "automaton"], 91 "additionalProperties": false, 92 "minProperties":2, 93 "maxProperties":3 94 } 58 D NBA CONVERSION

D NBA conversion

This appendix provides pseudo code for the algorithm to convert LTL to NBA. An algorithm for the function create_graph() is available in the paper by Gerth et al. [21]. The input is LTL formula φ.

1 ψ = simplify (φ) 2 tableau = create_graph(ψ) 3 4 // CreateLGBA 5 f o r node ∈ tableau 6 a d d all sets of APs to lgbaState. labels such that each sets contains all η ∈ node.old, and no ¬η ∈ node . old 7 i f " init " ∈ node.incoming 8 s e t lgbaState.initial 9 f o r source ∈ node.incoming 10 a d d (source, node) to lgba 11 lgba.states = lgba.states∪{lgbaState} 12 f o r a U b ∈ ψ 13 // If there are no aUb, all states accept 14 f o r node ∈ tableau 15 i f a U b 6∈ node . old ∧ b ∈ node . old 16 acceptingSet = acceptingSet ∪ {lgbaState} 17 lgba.accepting = lgba.accepting ∪ { acceptingSet} 18 19 // CreateGBA 20 gba.states = lgba.states 21 gba.accepting = lgba.accepting 22 f o r trans ∈ lgba 23 f o r label ∈ trans.destination 24 gba.transitions = gba.transitions ∪ {(trans.source, label, trans. destination)} D NBA CONVERSION 59

25 // CreateNBA 26 f o r state ∈ gba . states 27 f o r i ∈ #gba.accepting 28 i f i = 0 ∧ state.initial

29 s e t state i . initial 30 // Any of the accepting sets works 31 i f i = 0 ∧ state ∈ gba.accepting[0]

32 s e t state i . accepting 33 nba.states = nba.states ∪ { state i } 34 f o r trans ∈ gba.transitions 35 f o r i ∈ #gba.accepting 36 i f trans.source ∈ gba.accepting[i] 37 nba.transitions = nba.

transitions ∪ {(trans.source i , trans.label, trans.

destination i )} 38 e l s e 39 nba.transitions = nba.

transitions ∪ {(trans.source i , trans.label, trans.

destination i+1 )} 40 r e t u r n nba

The simplify() function performs the following transformation.

1 r e t u r n push_negation(remove_operator(φ)) 2 3 f u n c t i o n remove_operator(φ) 4 i f φ has more operators 5 remove_operator(φ. operandA ) 6 remove_operator(φ. operandB ) 7 8 i f φ = F η 9 r e p l a c e by true U η 10 i f φ = G η 11 r e p l a c e by ¬( true U ¬η) 12 i f φ = η =⇒ ν 13 r e p l a c e by ¬η ∨ ν 60 D NBA CONVERSION

14 i f φ = η ⇐⇒ ν 15 r e p l a c e by (¬η ∨ ν)∧(η ∨ ¬ν) 16 r e t u r n φ 17 18 f u n c t i o n push_negation(φ) 19 i f φ is an AP 20 r e t u r n φ 21 i f φ = ¬ψ 22 s w i t c h ψ 23 c a s e ¬η 24 r e p l a c e φ by η 25 b r e a k 26 c a s e X η 27 r e p l a c e φ by X ¬η 28 b r e a k 29 c a s e η ∨ ν 30 r e p l a c e φ by ¬η ∧ ¬ν 31 b r e a k 32 c a s e η ∧ ν 33 r e p l a c e φ by ¬η ∨ ¬ν 34 b r e a k 35 c a s e η U ν 36 r e p l a c e φ by ¬η R ¬ν 37 b r e a k 38 c a s e η R ν 39 r e p l a c e φ by ¬η U ¬ν 40 b r e a k 41 42 push_negation(φ. operandA ) 43 push_negation(φ. operandB ) 44 r e t u r n φ E TRACE COMPASS 61

E Trace Compass 62 E TRACE COMPASS iue9 Figure E TRACE COMPASS 63 Figure 10 64 E TRACE COMPASS iue11 Figure E TRACE COMPASS 65

TRITA-EECS-EX-2020:900

www.kth.se