showedge

Synopsis

void showedge(string top, eset edges)
void showedge(string top, eset edges, int level)
 
void showedge(string src, string trg, eset edges)
void showedge(string src, string trg, eset edges, int level)

Description

Showedge is another interactive factbase exploration command, similar to show, showpath and showtree. Showedge is used for exploring dependence or usage edges going either between two subsystems in or within a single subsystem in a software architecture graph. In short, showedge command solves the "Where did that edge come from?" problem. To understand the usefulness of the showedge command, it is essential to understand the problem it solves.

"Where did that edge come from?" problem. Grok is used primarily for studying and exploring the architecture of software, and the "Where did that edge come from?" problem (referred to hereinafter as "WDTECF problem" or "the problem" for short) is encountered frequently in that area. The conceptual structure of software can be pictured as a containment tree - a large program contains (is made up of) several subsystems, which in turn contain subsystems of their own, which contain files, which contain functions, variables and classes.

The containment tree captures only a small part of information about the structure of software. Various leaves of the tree communicate with each other in various ways: through funciton calls and variable access, for example. It can be said that some parts of this tree use, or depend on, resources located in other parts of the tree. In large software systems, the amount of these dependencies is very large, and the structure of the dependencies is very complex. The final picture of the software architecture graph we are studying, then, is the containment tree augmented with the "uses" edges which point from clients to suppliers of resources.

Because software architecture graphs for even small-scale systems are usually very large, it is often beneficial to take a bird's eye view of the system: ignore, at least temporarily, the lower levels of the containment structure, and focus on subsystem-sized elements of the software. The "uses" edges would still be useful in this case, but preserving them takes some work, because they always connect very low-level software components, such as functions and variables.

To add these edges to higher levels of the containment tree, they are lifted; this means that if there are two subsystems, A and B, and something in A uses something in B, at any level, then A is also said to use B. In large software systems, where subsystems themselves are complex and composed of multiple components, an edge may be lifted many times, propagaiting information aobut the resource use within a system up the containment tree.

Through lifting, many use edges tend to be aggregated into few - if there are many things in A that use many things in B, after lifting they will all still be represented by the single use edge going from A to B. So the edge between A and B is in fact a compound edge, consisting of many use relationships, possibly of different types, between different subsystem members. In taking a bird's eye view of the system, we gained perspective at the expense of detail.

The WDTECF problem is the general task of reconstructing the details of linkage between two subsystems engaged in a use relationship. The two most interesting things to find out about subsystem-level use relationship are cardinality and sources. Cardinality is a simple number--how many "real" use relationships make up the compound use edge between the two subsystems. The source question is the heart of the WDTECF problem: it is the task of finding out what parts of one subsystem use what parts of another subsystem. It is this problem that showedge is designed to solve.

Showedge. Depending on the form used to invoke it, showedge shows the edges of a given kind and their cardinalities, going between two subsystems or within a single subsystem, lowering and decomposing the edges either to the bottom of the containment structure or to a predetermined depth.

Example

The factbase used in this example is an extracted software architecture of a simple compiler. The fact base representing the "as-linked view" of this compiler is available for download from the QLDX Examples page. The containment information is held in a relation called "contain"; the use information is represented by relation "cLinks".

Usage relationships within an entity. The top of the containment structure is called "c488", the executable itself. If we want to find out about the usage patterns within c488, we can use the second form of the command, which allows us to look at all links within a structure up to a predetermined depth. We will look only one level down, to see information about c488 and its immidiate descendants, with the following command:

>> showedge ("c488", cLinks, 1)
This produces the following output:
315 : c488
|  51 : codegen.o
|  22 : machine.o
|  4 : main.o
|  19 : parser.o
|  31 : scanner.o
|  24 : semantics.o
|  14 : symbol.o
|  6 : tset.o
|  10 : => (cLinks semantics.o symbol.o)
|  1 : => (cLinks semantics.o codegen.o)
|  3 : => (cLinks semantics.o main.o)
|  4 : => (cLinks codegen.o semantics.o)
|  4 : => (cLinks codegen.o symbol.o)
|  4 : => (cLinks codegen.o main.o)
|  4 : => (cLinks codegen.o machine.o)
|  8 : => (cLinks scanner.o main.o)
|  1 : => (cLinks main.o scanner.o)
|  2 : => (cLinks main.o codegen.o)
|  1 : => (cLinks main.o machine.o)
|  2 : => (cLinks main.o parser.o)
|  2 : => (cLinks main.o semantics.o)
|  5 : => (cLinks machine.o main.o)
|  11 : => (cLinks parser.o main.o)
|  4 : => (cLinks parser.o tset.o)
|  5 : => (cLinks parser.o scanner.o)
|  1 : => (cLinks parser.o semantics.o)
|  1 : => (cLinks parser.o codegen.o)
|  2 : => (cLinks tset.o main.o)
|  10 : => (cLinks semantics.o /lib/libc.so.6)
|  7 : => (cLinks symbol.o /lib/libc.so.6)
|  12 : => (cLinks codegen.o /lib/libc.so.6)
|  9 : => (cLinks scanner.o /lib/libc.so.6)
|  13 : => (cLinks machine.o /lib/libc.so.6)
|  7 : => (cLinks main.o /lib/libc.so.6)
|  9 : => (cLinks parser.o /lib/libc.so.6)
|  2 : => (cLinks tset.o /lib/libc.so.6)

The output tells us that there are a total of 315 cLinks relationships within c488 (first line of the output). They are between and within the object files that make up the c488 executable. The codegen.o object file, for example, has 51 cLinks relationships within it (line 2), machine.o has 22 (line 3) and so on.

The lines containing the symbol => describe cLinks realtionships going between the entities that make up the c488 executable. The line

|  10 : => (cLinks semantics.o symbol.o)
for example, tells us that there are 10 links going from the semantics.o to symbol.o The symbol => shows that this is a compound link, and it is possible to explore it further by descending to lower levels of the containment tree.

We can now use the first form of the command to explore the links within one of the object files that make up the c488 executable. In this case the parameter specifying the number of levels to go down in the containment structure is omitted, and all the levels are opened. Because the number of links in the object files is small, the output remains small enough to comprehend:

>> showedge ("machine.o", cLinks )
22 : machine.o
|   -> (cLinks machine.o[.text+0x252] machine.o[*COM*+0x2000])
|   -> (cLinks machine.o[.text+0x252] machine.o[.data+0x100])
|   -> (cLinks machine.o[.text+0x252] machine.o[.rodata+0x88])
|   -> (cLinks machine.o[.text+0x445] machine.o[*COM*+0x2000])
|   -> (cLinks machine.o[.text+0x445] machine.o[.text+0x252])
|   -> (cLinks machine.o[.text+0x445] machine.o[.rodata+0x88])
|   -> (cLinks machine.o[.text+0x445] machine.o[.text+0x0])
|   -> (cLinks machine.o[.text+0x445] machine.o[.text+0x388])
|   -> (cLinks machine.o[.text+0x445] machine.o[.text+0x16e])
|   -> (cLinks machine.o[.text+0x445] machine.o[.rodata+0x86])
|   -> (cLinks machine.o[.text+0x445] machine.o[.data+0x170])
|   -> (cLinks machine.o[.text+0x445] machine.o[.data+0x174])
|   -> (cLinks machine.o[.text+0x445] machine.o[*COM*+0x28])
|   -> (cLinks machine.o[.text+0x1f9] machine.o[*COM*+0x2000])
|   -> (cLinks machine.o[.text+0x1f9] machine.o[.rodata+0x86])
|   -> (cLinks machine.o[.text+0x1f9] machine.o[*COM*+0x28])
|   -> (cLinks machine.o[.text+0x0] machine.o[*COM*+0x2000])
|   -> (cLinks machine.o[.text+0x0] machine.o[.data+0x170])
|   -> (cLinks machine.o[.text+0x0] machine.o[*COM*+0x28])
|   -> (cLinks machine.o[.text+0x388] machine.o[.text+0x252])
|   -> (cLinks machine.o[.text+0x16e] machine.o[.text+0x0])
|   -> (cLinks machine.o[.text+0x16e] machine.o[.data+0x174])
This output shows the usage information between the entities contained within the machine.o object file. There are 22 usage relations, and none of them are compound edges - they are all marked with the single edge symbol -> rather than =>. The entity names that are displayed are not very informative at present time. for example, the second line of the output tells us that entity named machine.o[.text+0x252] links to entity named machine.o[*COM*+0x2000].

It is possible to find out more about the entities by looking up their parameters directly or using the show command. Indeed, by using the commands

>> show ("machine.o[.text+0x252]")
>> show ("machine.o[*COM*+0x2000]")
we will find that machine.o[.text+0x252] is a function named "formatInstruction", whereas machine.o[*COM*+0x2000] is an object (i.e. a variable) named "memory". Future implementations of showedge will include this information with the output; at present, it still has to be looked up separately.

Usage relationships between entities. Thus far we have seen how showedge can be used to study edges within an entity, such as an executable or an object file. We will now see a more direct application of showedge to the WDTECF problem: examining an edge between two entities. Looking at the output of the showedge ("c488", cLinks, 1) command, we can see that there is a usage relationship between the object files semantics.o and codegen.o, and that it is bi-directional - semantics.o uses things defined in codegen.o, and vice versa. Let us examine that relationship more closely, by looking at the usage edge between these two object files:

>> showedge ("codegen.o", "semantics.o" , cLinks, 1 )
5 : =>
|  1 : => (cLinks semantics.o codegen.o)
|  4 : => (cLinks codegen.o semantics.o)
We are looking the fourth form of the showedge command to look at only the first level of the edge. Even this short output provides a wealth of information. We can tell that there are a total of five usage edges going between codegen.o and semantics.o. They are split into two compound edges; the compound edge going from codegen.o to semantics.o has four "real" usage edges in it. The compound edge going in the opposite direction has only one real edge in it, but it is still considered "compound" and marked with the => symbol because it is a "lifted" edge that has been derived, rather than extracted from the software.

Since there are only five total edges going between the two files, we can omit the parameter indicating the number of levels to go down the containment structure withouth fear of being overwhelmed with input. This command gives us all the details about the edges going between the codegen and semantics object files:

>> showedge ("codegen.o", "semantics.o" , cLinks )
5 : =>
|  1 : => (cLinks semantics.o codegen.o)
|  |   -> (cLinks semantics.o[.text+0x20a] codegen.o[.text+0x20f])
|  4 : => (cLinks codegen.o semantics.o)
|  |   -> (cLinks codegen.o[.text+0x42c] semantics.o[.text+0x1a8])
|  |   -> (cLinks codegen.o[.text+0x42c] semantics.o[.data+0x180])
|  |   -> (cLinks codegen.o[.text+0x2bf] semantics.o[.data+0x180])
|  |   -> (cLinks codegen.o[.text+0x39f] semantics.o[.data+0x180])

All the edges going between the two files are displayed. As before, some of the names displayed are not very informative, but more information about any of the displayed entities can be easily obtained by using the show command.

See Also

show showtree showpath