A postscript version of Volume 2 is available.
This is the second volume of a two volume report on unravel, a Computer Aided Software Engineering (CASE) tool for software written in ANSI C, that can assist evaluation of high integrity software by using program slices to extract computations for examination. In this volume, we provide a user manual for unravel. This manual is intended to provide the user with enough information to use unravel without any other reference. To this end, a brief simplified description of program slicing is provided in addition to a tutorial example and a detailed description of unravel operation. This user manual also discusses limitations of unravel and how to deal with code containing extensions to ANSI C that would inhibit the correct operation of unravel.
| Certain trade names and company products are mentioned in the text or identified. In no case does such identification imply recommendation or endorsement by the National Institute of Standards and Technology, nor does it imply that the products are necessarily the best available for the purpose. |
|---|
UNIX is a trademark of UNIX System Laboratories, Inc.
The X Window System is a trademark of M. I. T.
5 Unravel Limitations and Assumptions
Appendix A:Unravel Quick Reference
2-1: Slicing Example 1 flavors.c
2-2: Unravel Slicing Example 1 Flow Graph
2-3: Slicing Example 1 Data-Flow Sets
2-4: Slicing Example 1 Active Sets For S<18,sweet>
2-5: Unravel Structure Overview
2-6: Unravel Operation Checklist
2-7: Slicing Example 2 refinery.h
2-8: Slicing Example 2 input.c
2-9: Slicing Example 2 cool.c
2-10: Slicing Example 2 pressure.c
2-11: Slicing Example 2 refinery.c
2-13: Initial Main Control Panel
2-14: Initial Analyzer Control Panel
2-15: Analyzer Control Panel During Analysis
2-16: Main Control Panel After Analysis
2-17: Selection Control Panel
2-18: Slice on pump_ok
2-19: Slice on level_ok
2-20: Intersection of Slices on pump_ok and level_ok
2-21: Slice on a_dump
A-1: Unravel Operation Checklist
This volume describes the operation of version 2.1 of the program slicing tool, unravel, developed by the National Institute of Standards and Technology (NIST). Development of unravel was funded by both the United States Nuclear Regulatory Commission (NRC) and the National Communications System (NCS) under contracts RES-92-005, FIN #L24803, and DNRO46115, respectively. The tool can be used to compute program slices of programs written in ANSI C.
Program slicing can be used to transform a large program into a smaller one containing only those statements relevant to the computation of a given variable. Program slices aid program debugging, program maintenance, program understanding, and automatic integration of program variants.
The users of unravel are assumed to have a working knowledge of computers and ANSI C, but they may not be familiar with UNIX, POSIX or program slicing.
Unravel is intended to support the understanding and evaluation of software by allowing the user to investigate a program through program slices.
To achieve the goal of making unravel a portable and easy to use slicing tool, the following general requirements were met:
Section 2 explains program slicing and gives an example of using unravel to examine a small program. Details of unravel operation are given in section 3. Section 4 discusses using unravel on non-ANSI C programs. The limitations of unravel and assumptions about source code to be analyzed are discussed in section 5.
Unravel is a tool for program understanding that uses program slicing to identify statements relevant to some computation. This section describes program slicing, the software architecture of unravel, a scenario for using unravel, and presents a detailed example of using unravel. The description of program slicing is a simplified discussion of the theory followed by an example illustrating the steps in computing a program slice.
Some terminology about programs and program components needs to be clearly defined so that the reader understands how unravel views an ANSI C program. It is important to understand that unravel sees a program as a collection of procedures executed as a unit. A program has one main procedure (called main) and some number of other procedures that are arbitrarily grouped in one or more source files.
Program slicing is a family of program decomposition techniques based on extracting statements relevant to a computation in a program. A slice is a smaller program that reproduces a subset of the original program's behavior. This is advantageous since the slice can, by excluding irrelevant statements, collect an algorithm for a given calculation that may be scattered throughout a program. It is easier for a programmer interested in a subset of the program's behavior to understand the corresponding slice than to deal with the entire program. The utility and power of program slicing comes from the potential automation of tedious and error prone tasks. Research on program slicing is being conducted on program debugging, program testing, program integration, parallel program execution and software maintenance. Several variations on this theme have been developed, including program dicing, dynamic slicing and decomposition slicing.
An informal definition of a program slice (taken at statement n on variable v) is all statements that might affect the value that v has just before control reaches statement n. A slicing criterion defines the starting place for a program slice. It is composed of the statement n and the variable v. Statements are included in a program slice with either a direct influence or an indirect influence on the criterion variable. A statement assigning a value to a variable that could influence the value of the criterion variable at the criterion statement is a direct influence. A compound statement (e.g., for or while) that controls execution of another statement included in the slice is an indirect influence.
This is not intended to be a complete discussion of program slicing but, an overview to give the
user insight into the behavior of unravel. Some language features such as pointers and procedure
calls introduce complications that would require lengthy discussion.
To compute program slices, a program is first represented as a flow-graph of nodes annotated
with lists of variables assigned a value or used at each node and directed edges indicating
control-flow. A flow-graph node roughly corresponds to an executable statement, however some
statements such as a for statement are divided into several nodes to represent the various parts
of the for statement that do control variable initialization, loop termination testing and control
variable modification. The edges of the flow-graph connect each node, n, to the nodes
(statements) that could be executed after n. An example program is presented in
Figure 2-1 with
the corresponding flow-graph in
Figure 2-2
and the node number to line number mapping in
Figure 2-3.
To understand the basics of transforming a program into a flow-graph here are the
rules to follow for programs composed only of assignment statements,
if statements and while
statements. The flow-graph is composed of nodes that represent the statements and edges that
represent execution flow between pairs of statements.
Figure 2-2: Unravel Slicing Example 1 Flow Graph
A program slice is computed for a given slicing criterion from an annotated flow-graph. These
annotations include variables referenced and defined at each flow-graph node and the active
variable set. The active set is the set of variables that the criterion variable depends on just
before program execution reaches the associated node.
A program can be represented by a flow-graph annotated by variables referenced and defined at
each flow-graph node. A program slice can be computed on a program for a given slicing
criterion with the help of one more annotation to the flow-graph, called the active variable set
or active set. The active set is the set of variables that the criterion variable depends on just
before program execution reaches the associated node.
The computation begins with all the active sets except for the active set for the slicing criterion
statement initialized to the empty set. The active set for the criterion statement is initialized to
the criterion variable. The slice is computed by propagating active sets across flow-graph nodes
until the active sets stabilize (i.e., stop changing). Computation of the active set for an arbitrary
node, n, is controlled by comparing variables defined at node n with the active sets of immediate
successor nodes by the following rules:
When a statement is included in a slice that is part of a compound
statement such as if or while,
the framework of the compound statement is included in the slice and any variables used in a
controlling condition are added to the active set of the compound statement.
To summarize the algorithm for computing a slice:
Figure 2-3
presents the data-flow sets annotating the flow-graph from
Figure 2-2
used in computing program slices on the program of
Figure 2-1
. The columns labeled Node and Succ
(successor) represent the flow-graph of the program. The columns
labeled Refs and Defs contain
the variables referenced and assigned-to (defined) at each node.
The column labeled Req is the
required set for the node, used to list other nodes that
are required by any slice containing the
given node. The required set is used to capture both syntactic
relations such as the inclusion of
the opening and closing program braces (nodes 2 and 20),
and control relations of if, while and
other compound statements (e.g., node 12 at line 17 requires node 11,
the while on line 16).
For example, suppose we want to know how the value of the variable
sweet printed at line 25
of
Figure 2-3
is computed. The specification of a slicing criterion requires a variable and a node
in the flow-graph. Node 18 corresponds to the printf statement
at line 25, therefore, the criterion
would be S<18,sweet>. The active set for node 18 is
initially {sweet}. Since nodes 9 through 18
do not assign a value to sweet no changes take place to the
active set as it is propagated
backward, and these nodes are not included in the slice.
Node 8 assigns a value to sweet based
on red and green and so node 8 (line 13) is included in
the slice and sweet is replaced in the
active set by red and green at node 8. Node 7 is
included in the slice because the active
variable red is assigned a value, however the active set does
not really change with red being
replaced by red. At node 3, red is assigned
a constant value and the node is added to the slice
and red is dropped from the active set. Node 5 is included in
the slice and green is dropped
from the active set since green is assigned a constant value
at node 5. The active sets are summarized in
Figure 2-4
. The slice is now complete except for some syntactic dependencies
(nodes 1, 2 and 20) that are captured by the requires set.
Figure 2-3: Slicing Example 1 Data-Flow Sets
Figure 2-4: Slicing Example 1 Active Sets For S<18,sweet>
This section describes the software architecture of unravel.
Unravel operates on the source files
from a single directory.
Figure 2-5
presents an overview of unravel. The circles represent files
and the boxes represent processing steps. Source files are transformed
to corresponding language
independent format (LIF) files by the analyzer. The LIF files
for a given program are bound
together by the linker into a single link file.
The link file is the primary input to the slicer. To
use unravel, the source program files must first be analyzed
and linked. A window based user
interface gives the user of unravel access to these components
and helps manage the results.
Figure 2-5: Unravel Structure Overview
This section is a tutorial talking a user through an example of using
unravel. The two most
important steps for using unravel successfully take place before
unravel is executed. The user
should have a general understanding of the architecture of the source
code in order to select
slicing criteria that can provide relevant information.
Figure 2-6
presents an operational checklist
that serves as an overview and guide to unravel operation.
The figure is repeated in
Appendix A
for quick reference. The steps to using unravel follow.
This section describes using unravel on a short tutorial
example. We will go through the steps to run the analyzer
and the slicer.
The example source code in Figures 2-7 through 2-11 and in
Figure 2-1 is provided with the unravel distribution. The
source code is located in the example subdirectory of the unravel
distribution. There are two example programs, flavors and refinery.
The program flavors is completely contained in the file flavors.c.
The other program, refinery, is spread over five files:
refinery.c, refinery.h, input.c, cool.c and pressure.c.
Figure 2-7: Slicing Example 2 refinery.h
Figure 2-8: Slicing Example 2 input.c
Figure 2-9: Slicing Example 2 cool.c
For the program flavors we would like to examine the
computation of sweet and sour and
evaluate any code common to these two computations. For the
program refinery we would like
to examine the computation of pump_ok, level_ok, and
a_dump.
After due consideration, the slices in
Table 2-1 were selected.
Table 2-1: Planned Slices
The user should locate the source directory for this example,
then use the UNIX cd command to set the current directory.
Figure 2-13 displays the initial Main Control Panel
on the example directory. Note the following:
The analyzer examines the current directory for source program
files and automatically places the file on either a list of files to
be analyzed or a list to be ignored. A source file that has been
analyzed since the last change to the source file is placed on
the Files Not Selected list; a source
file that has not been analyzed or has been changed since its
last analysis is placed on the
Selected Files list.
Figure 2-13: Initial Main Control Panel
Figure 2-14
displays the initial Analyzer Control Panel. Note the following:
Figure 2-14: Initial Analyzer Control Panel
Figure 2-15: Analyzer Control Panel During Analysis
Figure 2-16: Main Control Panel After Analysis
After the analysis is done the user should return to the
Main Control Panel and review the
analysis results. To display the analysis results select the
Last Analysis entry on the Review History menu.
A summary of each source file analyzed is presented. If any syntax
errors were found (i.e., the source is not ANSI C), the location of
the error in the source file is indicated. The error should
be repaired and the analyzer run again until there are no errors.
Section 5.1 discusses what to do with some common extensions to ANSI C.
This section describes invoking and using the slicer. This is a two
step process; first, the program to be sliced is selected, then the
slicing criteria is specified and the slices examined.
After the analysis is complete and any syntax errors have been
repaired, the user runs the slicer
by clicking on the Run Slicer button of the Main Control
Panel. If there is more than one program to choose from, the
Selection Control Panel is displayed as in
Figure 2-17. The user
should either click on a program file name or click on the Exit
button. If the user clicks on the Exit button, the
Selection Control Panel pops-down and control returns to the
Main Control Panel. To select the program refinery.c the user
clicks on that program name.
Figure 2-17: Selection Control Panel
After a program is selected from the Selection Control Panel,
the Slice Control Panel pops-up.
The user can do the following with the Slice Control Panel:
To compute the first slice from our list of planned slices in
Table 2.1, the user needs to select
the global variable pump_ok. To select pump_ok the
user does the following:
To specify the location for the slicing criterion and initiate
computing the slice do the following:
Figure 2-19 presents the results of slicing on level_ok
at the same location. Note from the figure that this slice is labeled
secondary slice while the other slice is labeled
primary slice. The terms primary and secondary
are used to label two slices for computing set operations on the
slices. To compute a secondary slice, the user clicks the criterion
location with the middle mouse button rather than the left mouse button.
Now that we have two slices we can intersect slices to determine if
there is shared code. To compute the intersection displayed in
Figure 2-20, the user moves the mouse cursor to the Operation
button, pushes and holds the left mouse button, drags the mouse to the
Intersection entry and releases.
The slice on a_dump can be computed in similar fashion:
When the user is finished computing slices, the user clicks on
Exit in the Slice Control Panel.
Figure 2-18: Slice on pump_ok
Figure 2-19: Slice on level_ok
Figure 2-20: Intersection of Slices on pump_ok and level_ok
Figure 2-21: Slice on a_dump
Unravel is implemented in ANSI C under UNIX with a user interface built with the Athena
Widgets of the MIT X Window System, running the X window system under the UNIX operating
system.
The interface control panels are each composed of several interface objects from the MIT Athena
Widget Set that the user can manipulate using the mouse to communicate with unravel. This
section discusses how the user can interact with each Athena Widget used by unravel.
Unravel uses the following interface objects, each of which is described in subsequent sections.
Unravel uses a mouse with three buttons, referred to as
left, middle and right. To interact with an
object the user first positions the mouse cursor, an image on the
screen that tracks mouse motion, over the object. Then the user
does one of the following: types on the keyboard, clicks a mouse
button or drags the mouse. To click a mouse button means to
push the button on the mouse and then release the button. A
double click is two mouse button clicks in a short (about one
second) time. To drag the mouse means to push a mouse button,
move the mouse while holding the button down and then release the
button.
Display labels are used to display information to the user.
As the user requests unravel to do tasks the displayed
information changes to inform the user of actions taken. The user
has no direct input to a display label.
A button on an unravel control panel has an oval border. To push a button, position the mouse
cursor over the button and click the left mouse button. When the mouse button is pushed, the
button is highlighted in reverse video. If the mouse cursor is dragged outside the button,
highlighting is turned off and nothing happens if the button is released, otherwise, the button
invokes its function when the button is released.
A pull down menu button has an oval border. Unravel uses
menus to group related actions for invocation by the user dragging
the mouse. The user positions the mouse cursor over the menu
button, then presses and holds the left mouse button. The menu
appears in a window under the menu button. The user may drag
the mouse cursor over the menu entries and release the button on the
entry that should be invoked. The current entry is indicated by
reverse video. If the button is released outside the menu nothing
happens.
Unravel uses pop-up lists for the user to select files,
procedures or variables, usually for specifying a variable in a
slicing criterion. To select an item from a pop-up list, position
the mouse cursor over the item and click the left mouse button.
A text input window is used to get text from the user. The
mouse cursor must be positioned somewhere within the text input
window. The text input window has a text cursor shaped like
the caret character (^). Any characters typed are inserted at the
text cursor. The text cursor can be moved by positioning the mouse
cursor over the desired location and clicking the left mouse button.
The character to the left of the text cursor can be removed by the
delete key.
A scroll bar is usually used to control the display of
information that needs more space than allocated on the screen.
Unravel uses scroll bars on text windows, text input windows
and pop-up lists. Scroll bars may be either horizontal or vertical.
All three mouse buttons can be used to manipulate the scroll bar
when the mouse cursor is positioned within the scroll bar.
A text window is used by unravel to display history logs
and help screens. A text window has scroll bars if the window is too
small to display the text. The user can navigate through the file by
either the scroll bar or by searching for a string. To search for a
string type CTRL-S to pop-up a search control window. Enter
the target string in the text input box just after the Search
for: label. Either the return key or the Search
button starts the search. The next instance of the search target can
be found by either the return key or the Search button.
There is a Cancel button to pop-down the search control window
when done.
The user interface displays four control panels and two pop-up
information windows. The four control panels are the following:
All control panels have the following features:
Two application resources, runningFG and runningBG, are
defined for analyzer and slicer. These resources are a
foreground and a background color that are used to indicate a lengthy
operation is in progress.
The two information pop-ups display a history of user activities and
help text for each panel. Both pop-ups are displayed by the same
program. An information pop-up window consists of a done
button to dismiss (pop-down) the window and a scrollable text window.
The function of the Main Control Panel is to respond to user
interaction with the panel. All files are assumed to be in the
current directory.
Unravel performs the following initializations:
The Main Control Panel displays the following information:
The Main Control Panel buttons invoke the following actions:
The Analyzer Control Panel presents the user with:
The Analyzer Control Panel buttons invoke the following actions:
Exit Analyzer This button Appends the file HISTORY-A to
HISTORY and then exits.
File Selection The File Selection button pops-up a menu
with the following four choices and actions:
Analyze Selected Files/Stop Analysis This button runs the
analyzer on each selected file, adding the contents of the C
preprocessor options window to the C preprocessor command line and
adding the contents of the parser options window to the parser
command line. When the Analyzer Control Panel button is pushed
the button label is changed from Analyze Selected Files to
Stop Analysis. If the Stop Analysis button is pressed,
unravel will not analyze any more of the selected files after
the file currently being analyzed is finished. As each file is
analyzed, the file name currently being analyzed is displayed on the
status line along with a progress indication. The progress indication
is defined by the following: number each file in sequence starting
from 1 in the order that the files will be analyzed. Display the
file's sequence number and the total number of files. The status line
is set to the foreground and background colors specified in the
application resources runningFG and runningBG.
After all selected files have been analyzed, the map program
is run automatically.
Clear Deletes the analysis files (.LIF, .H and
.T) for each selected file and deletes the SYSTEM file.
Help: The Help button displays a pop-up window of
information about the Analyzer Control Panel.
The C preprocessor options text window allows the user to specify
any C preprocessor options that are normally used to compile the
source code to be analyzed. The two most common options are
preprocessor symbol definition (-D) and include directory
path (-I). When and how to use the i-D option depends
on how the source code is usually compiled. The -I option
is used to specify the location (directory path) of include files
not located in the current directory.
The parser options text window allows the user to specify
options to the parser. The parser has two options related to dynamic
memory allocation that might be needed. There is a list of function
names that are assumed to allocate dynamic storage. When
unravel encounters a call to one of these functions a dynamic
variable is created in the form @file_name#line number[sequence
number] to represent any memory allocated by the statement. If
the function call result is cast to a pointer to a base type,
the generated variable is declared to be of the base type.
There are several other options to the parser, intentionally
undocumented, that are not useful to the user of unravel but
are important for debugging and performance analysis.
The Selection Control Panel presents the user with:
The Exit button pops-down the panel with no further action.
If a file from the list is selected, the file is linked, the
Selection Control Panel is popped-down and the slicer is called.
The status line initially indicates that select is
waiting for the user to make a selection. After a file is selected,
the status line indicates that a file is being linked.
If there is exactly one main program file, the file is linked and
the slicer is called without bringing up the
Selection Control Panel.
The Help button pops-up a file of information about the
Selection Control Panel. The slice history file is updated
with a message indicating the file to be linked before the linker
is called. Any linker output is appended to the slice history file.
The slicer accepts slicing criteria from the user, computes a program
slice for each criterion given, saves each slice for later recall and
displays the program in a scrollable window. The slicer presents the
user with:
Primary slice and secondary slice has no significance
other than being convenient names for two slices when an operation such
as intersection is performed on two slices.
The buttons do the following:
There are six information display windows on the control panel.
The Select menu is used to specify a criterion variable, to
aid navigation by marking the location of a procedure in the tick
bar and to select a previously computed slice for display.
The Select menu has the following selections:
The Operation menu has the following selections:
The text window has four actions triggered by the mouse.
The source program line under the mouse pointer when the mouse button is clicked specifies the
statement for the slicing criterion. If the specified slicing criterion has already been used to
compute a slice (without interruption), then the slice is not computed, but is retrieved and
displayed.
History and help information pop-ups are handled by a single program. The text may have either
horizontal or vertical scroll bars as needed. It is possible to search for a string by typing
CTRL-S and typing the target string in the search pop-up. There is a Cancel button to
pop-down the search control window when done.
This section discusses how to resolve two problems that can arise when using unravel. The first
problem occurs when the software to be analyzed is not strict ANSI C. The second problem can
occur when more than one program is being analyzed.
Unravel is designed for ANSI C and is strict about the language accepted. There exist C
compilers that for a variety of reasons have implemented extensions to the C language. When
these extensions involve additional data types, additional data attributes, additional keywords, or
changes to the language syntax, unravel cannot be used without first modifying the source code.
This section discusses how to accomplish these modifications.
Any unknown keywords or data types bring the unravel analyzer to a stop at that point with a
message indicating the line number and file. If there are a few deviations from ANSI C, it is
sometimes possible to make the program acceptable to unravel with a few small changes to the
source program under analysis. If there are a large number of extensions or there are any
significant syntactic additions then modifications to the source program may be too
time-consuming to be practical.
A common extension is to include additional data types in the C language. Provided that the
added data types do not also add significantly new semantics they can be handled by inserting
a #define preprocessor command to equate the new type to an existing builtin type. For
example, if a compiler adds a boolean type, the following preprocessor statement could be used
to equate boolean with int:
#define boolean int
Another common extension is additional data attributes. For example, a compiler might add the
keyword extended to indicate that floating point numbers should use 128 bits rather than the 64
bits used in double precision. This keyword can be eliminated by defining the keyword to be
null:
#define extended
Sometimes the C preprocessor is extended. The extensions must be replaced in such a way that
the result of the ANSI C preprocessor used by unravel produces the same result as the vendor
C preprocessor. An alternative to replacing the extensions is to use the extended preprocessor
to preprocess the source program.
If the unravel user is interested in more than one source program the source files for all the
source program files can be in the same directory, however, if there are two or more functions
with the same name, unravel cannot determine which is the procedure that belongs with a given
main program.
The example in
Figure 4-1 presents five source files
(alpha.c, beta.c, theta.c, phi.c and web.c)
that correspond to two source programs. Source program alpha
requires the files alpha.c, theta.c
and web.c. The second source program, beta, requires the
files beta.c, phi.c and web.c.
If we run the unravel analyzer on all the these files, the analyzer reports that the procedure angle
is defined in more than one file (theta.c and phi.c).
There are two possible ways to deal with
the problem, either move each set of source files for a given source program to a separate
directory or only analyze the source files for one source program at a time.
Figure 4-1: Ambiguous Example
To put each source program in separate directories, use the UNIX mkdir command to create a
directory for each program (i.e., one subdirectory for each main procedure), then move source
files (with the mv command) to the subdirectories where they belong. If a source file is used
by more than one source program, use the link command, ln, to place a link to the source file
in each subdirectory.
Alternatively, the user can analyze only files alpha.c, theta.c and web.c. Then the user runs the
slicer and selects alpha. After slicing on alpha is finished, the user can go back to the Analyzer
Control Panel and clear alpha.c and theta.c, then analyze beta.c and phi.c and run the slicer
on beta.
Unravel has limitations for several reasons. For example, an approximate solution to some
aspect of slicing may be implemented to avoid a severe performance penalty. Other limitations
arise from the static nature of program slicing. This section presents the most serious limitations.
Unravel ignores cast operations except where the cast is on the return value of the malloc
function. This can cause a problem when a variable is declared as one data type and then cast
to another data type. For example, consider the following code:
Unravel loses the connection between the variable x and the object pointed to by y. Unravel
expects that y points to an object of type ab_type, however when unravel finds that y points to
x, unravel is unable to see that y->b is really x[1] because unravel expects to find x.b.
As a result, statements that influence the value of x are not in the slice. If there is one such cast
then a second slice could be computed on x at the cast statement and the two slices unioned
together.
Unravel expects the address operator (&) to be applied only to variables and not applied to
expressions. This turns out to be a design error that causes expression such as &a->b to be
ignored. This can cause statements to be omitted from a slice.
When computing active sets for a statement that dereferences a pointer variable each object that
the variable might point to should be added to the active set. At different locations in a program
the set of objects that a pointer could point to may be different. For each pointer, unravel
identifies all objects that the pointer might point to. This can cause statements to be included
in a slice that could be excluded with a more precise pointer tracking algorithm.
Pointers to functions are ignored.
Unions are treated like structures by unravel. The union members appear to unravel as separate
data objects rather than overlapping objects.
Unravel ignores unconditional branch statements (i.e., goto, break, and continue). In most
programs this does not change the content of computed slices in a significant way however, some
statements that should be in some slices are omitted. For example, in the following code a slice
on x should include all lines shown, however, if the break statement is ignored, lines 4 and 1
are omitted. Note that the statements missing are concerned with the calculation of another
variable (z) and do not have a direct role in the calculation of x. This problem will be addressed
in a later release of unravel.
Unravel has no knowledge of any libraries that might be used by vendor code. This includes
the ANSI C library. Any library procedure call is assumed to not use or change any global
variable. Any variable whose address is passed to a library procedure is assumed to be changed,
and if a structure all members are assumed to be changed.
Figure A-1: Unravel Operation Checklist
2.1.1 Creating a Flow-Graph
1 main()
2 {
3 int red, green, blue, yellow;
4 int sweet,sour,salty,bitter;
5 int i;
6
7 red = 1;
8 blue = 5;
9 green = 8;
10 yellow = 2;
11
12 red = 2*red;
13 sweet = red*green;
14 sour = 0;
15 i = 0;
16 while ( i < red) {
17 sour = sour + green;
18 i = i + 1;
19 }
20 salty = blue + yellow;
21 yellow = sour + 1;
22 bitter = yellow + green;
23
24 printf ("%d %d %d %d\n",
25 sweet,sour,salty,bitter);
26 exit(0);
27 }
2.1.2 Computing Program Slices
2.1.3 Slicing Example
2.2 Unravel Architecture
2.3 Operational Scenario
2.4 Tutorial Example
2.4.1 Orientation
1 typedef struct {
2 int value;
3 } sensor_rec,*sensor_ptr;
4
5 int pressure,flow,volt,level;
6 int pump_ok,flow_ok;
7 int presure_ok,level_ok;
1 # include "refinery.h"
2 get_sensor_v (sensor_ptr s) { s->value = read_sensor(); }
3 get_sensor_f (sensor_ptr s) { s->value = read_sensor(); }
4 get_sensor_l (sensor_ptr s) { s->value = read_sensor(); }
5 get_sensor_p (sensor_ptr s) { s->value = read_sensor(); }
1 # include "refinery.h"
2 int coolant_sys(p,f)
3 sensor_ptr p,f;
4 {
5
6 volt = p->value;
7 flow = f->value;
8 pump_ok = pump_undervolt(volt);
9 flow_ok = coolant_flow(flow);
10 }
1 # include "refinery.h"
2 int pressure_sys(p,w)
3 sensor_ptr p,w;
4 {
5
6 pressure = p->value;
7 level = w->value;
8 pressure_ok = check_pressure(pressure);
9 level_ok = water_level(level);
10 }
1 # include "refinery.h"
2 main()
3 {
4 int p_alarm,c_alarm,alarm;
5 sensor_rec pump_sensor,flow_sensor;
6 sensor_rec pressure_sensor,level_sensor;
7
8 while (1){
9
10 get_sensor_v(&pump_sensor);
11 get_sensor_f(&flow_sensor);
12 get_sensor_p(&pressure_sensor);
13 get_sensor_l(&level_sensor);
14
15 pressure_sys(&pressure_sensor,&level_sensor);
16 coolant_sys(&pump_sensor,&flow_sensor);
17 p_alarm = !(pressure_ok && level_ok);
18 c_alarm = !(pump_ok && flow_ok);
19 alarm = c_alarm || p_alarm;
20 if (alarm) system_shutdown();
21 }
22 }
2.4.2 Slice Criteria Selection
Slicing Criteria
Variable
Location
File
Procedure
Name
File
Procedure
Line No.
refinery.h
global
pump_ok
cool.c
main
10
refinery.h
global
level_ok
cool.c
main
10
refinery.c
main
a_dump
refinery.c
main
22
flavors.c
main
sweet
flavors.c
main
25
flavors.c
main
sour
flavors.c
main
25
2.4.3 Setting Source Directory
2.4.4 Executing Unravel
2.4.5 Executing the Analyzer
2.4.6 Analysis Review
2.4.7 Using the Slicer
2.4.7.1 Selecting a Program to Slice
2.4.7.2 Executing the Slicer
2.4.8 Exiting Unravel
When the user is finished with unravel, the user clicks on
Exit in the Main Control Panel.
3 Operating Unravel
3.1 Using The Interface Control Panels
3.1.1 Using a Mouse
3.1.2 Display Label
3.1.3 Button
3.1.4 Pull Down Menu
3.1.5 Pop-up List
3.1.6 Text Input Window
3.1.7 Scroll Bar
3.1.8 Text Window
3.2 User Interface Control Panels
3.2.1 Main Control Panel
3.2.2 Analyzer Control Panel
3.2.3 Selection Control Panel
3.2.4 Slice Control Panel
3.2.5 Help/History Pop-up
4 Solving Problems
4.1 Source Code Not ANSI C
4.1.1 Additional Data Types
4.1.2 Additional Data Attributes
4.1.3 Preprocessor Extensions
4.2 Ambiguous procedures
4.2.1 Separate Directories
mkdir alpha beta
mv alpha.c theta.c alpha
mv beta.c phi.c beta
ln web.c alpha
ln web.c beta
4.2.2 One at a Time
5 Unravel Limitations and Assumptions
5.1 Casts
1 typedef struct {
2 int a;
3 int b; } ab_type;
4 int x[2];
5 ab_type *y;
6 . . .
7 y = (ab_type *) x;
8 y->b = 10;
5.2 Address Operator
5.3 Pointers
5.4 Unions
5.5 Goto and Branch Statements
1 z = a;
2 while (y) {
3 y--;
4 if (z) break;
5 x = w;
6 }
5.6 Libraries
Appendix A: Unravel Quick Reference