Most of the time spent in the debugging of programs and the analysis of system
dumps is in the interpretation of data found in memory images.
The symbolic formatter provides a powerful and efficient way of referencing
this data symbolically and displaying it using its declared type(s).
Regardless of the source language, all data are formatted using a Pascal-style
syntax.
Most examples used in this section are based upon the following types:
CONST MINGRADES = 1; MAXGRADES = 10;
MINSTUDENTS = 1; MAXSTUDENTS = 5;
TYPE
GradeRange = MINGRADES .. MAXGRADES;
GradesArray = ARRAY [ GradeRange ] OF integer;
Class = ( SENIOR, JUNIOR, SOPHOMORE, FRESHMAN );
NameStr = string[8];
StudentRecord = RECORD
Name : NameStr;
Id : integer;
Year : Class;
NumGrades : GradeRange;
Grades : GradesArray;
END;
TYPE Subjects = (ENGLISH, MATH, HISTORY, HEALTH, PHYSED, SCIENCE);
SubjectSet = SET of subjects;
TYPE MStype = (MARRIED, DIVORCED, SINGLE, WIDOWED);
PersonPtr = ^Person;
Person = RECORD
Next : PersonPtr;
Name : string[16];
Sex : (MALE, FEMALE);
CASE ms : MStype OF
MARRIED : (NumKids : integer);
DIVORCED : (HowLong : integer);
SINGLE : (Looking : boolean);
WIDOWED : ();
END;
|
The following examples assume the System Debug variable addr1 contains the virtual address of a data structure corresponding to the type StudentArray.
A hexadecimal display of that area of memory would be produced by the
following:
$nmdebug > dv addr1,10
$ VIRT 7b8.40200010 $ 00000004 42696c6c 00000000 00000000
$ VIRT 7b8.40200020 $ 00000001 00040000 0000002d 00000041
$ VIRT 7b8.40200030 $ 0000004e 00000042 00000000 00000000
$ VIRT 7b8.40200040 $ 00000000 00000000 00000000 00000000
$nmdebug > dv addr1,6,a
$ VIRT 7b8.40200010 A .... Bill .... .... .... ....
|
This leaves to the user the task of matching the displayed data to the
declared types. When more complicated data structures are involved, it is easy to see that the process of matching the raw data to the corresponding high-level declarations could become exceedingly cumbersome.
The symbolic formatting facility allows users to display data in
terms of the declared structures. In the case of the record
StudentRecord in the above example, the symbolic formatter produces the following output:
$nmdebug > fv addr1 "StudentRecord"
RECORD
NAME : 'Bill'
ID : 1
YEAR : SENIOR
NUMGRADES : 4
GRADES :
[ 1 ]: 2d
[ 2 ]: 41
[ 3 ]: 4e
[ 4 ]: 42
[ 5 ]: 0
[ 6 ]: 0
[ 7 ]: 0
[ 8 ]: 0
[ 9 ]: 0
[ a ]: 0
END
|
Just as you can display data symbolically, you can also use symbolic addressing to locate and restrict the data to be displayed. The symbolic access facility allows users to extract simple values from a data structure by name for use in expressions and macros. For example, to test if year (year in school) is SENIOR, one could write:
$nmdebug > VAR year = SYMVAL(addr1, "StudentRecord.Year")
$nmdebug > IF year = "SENIOR" THEN WL "He is a SENIOR!!"
|
This is obviously more lucid than the corresponding bit-extraction sequence:
$nmdebug > VAR year = BITX( [addr1+$14], 0, #8 )
$nmdebug > IF ( year = 0 ) THEN WL "He is a SENIOR!!"
|
In summary, the symbolic formatting and access facility allows the user to display and reference data in a more natural way, namely through the use of the symbolic data type names declared at the source level. Furthermore, it frees authors of macros and simple formatted displays
from worrying about the allocation of data within a data structure and from tracking changes to these structures as
they evolve.
The remaining subsections describe the symbolic formatting and access facility in more detail.