figure 1: Little languages in unix, early 1980s.
figure 2: oDt- 8 debugger syntax,
circa 1967.
Debuggers
adb
dbx
stabs
Programming tools
lex
make
m4
ratfor
yacc
Shells/utilities
sh
csh
awk
bc, dc
ed, ex, vi
sed
Games
rogue, trek
text formatting
eqn
pic
nroff, troff
Libraries
regex
configuration
sendmail.cf
400 /
display the content
of memory location 400
400 / 6046
observe the value
is 6046 at that location
400 / 6046 2345
rewrite the value
to 2345
3000B
set a breakpoint at 3000
ODT- 8 Octal Debugging Technique Manual,
DEC-D8-CoCo-D, Dec. 1967
figure 3: unix V3 “db” syntax, circa 1971
ous forms in active use, as shown in
Figure 1.
These languages vary from complete programming languages (sh)
to preprocessors (yacc) to command-line syntax (adb) to representations
of state machines or data structures (regular expressions, debugger
“stabs”). Twenty years later, when
Sun Microsystems released the modern Unix system Solaris 10, almost all
of the new significant operating-system features involved the introduction of new purpose-built languages:
the DTrace debugging software introduced the D language for tracing
queries; the Fault Management system included a language for describing fault propagations; the Zones and
Service Management features included XML configuration grammars and
new command-line interpreters.
The history of one of these little
Unix languages, that of the adb debugger, is particularly illustrative of
the accidental evolution and stickiness of something small but useful in
a larger system.
evolution trumps
intelligent Design
The early development of Unix occurred on DEC PDP systems, which
had a very simple debugger available
known as ODT, or Octal Debugging
Technique. (This terrific name conjures thoughts of a secret kung fu
maneuver used to render the PDP’s
12-bit registers paralyzed.) The ODT
program supported an incredibly
primitive syntax: an octal physical
memory address was specified at the
start of each command and suffixed
with a single character (say, B for
breakpoint) or a slash (/) to read and
optionally to write the content of that
memory location, as shown in Figure
2.
Thus, a little language was born.
The ODT syntax clearly inspired the
form of the first debugger for the new
Unix system being developed on the
PDP, which was simply called db. At
the time of Unix v3 in 1971, the db
command syntax borrowed the basic
ODT model and began extending it
with additional character suffixes to
define addressing modes and formatting options, as shown in Figure 3.
By 1980, db had been replaced by
adb, which was included with the
AT&T SVR3 Unix distribution. The syntax had evolved to add new debugging
commands over the intervening years
and now supported not just simple
addresses but arithmetic expressions
(123+456 / was now legal). Also, a
character after “/” now indicated a
data format, and a character after “$”
or “:” now indicated an action. The
adb syntax is shown in Figure 4.
The addition of “$<” to read an external file of commands was particularly interesting, because it spawned
the development of primitive adb
programs or macros that executed
a series of commands to display the
contents of a C data structure at a
particular memory address. That is,
to display a kernel proc structure, you
address / Print a word in octal
address \ Print a byte in octal
address ` Print a byte in ASCii
address Disassemble an instruction
Print the machine registers
Unix Version 3 Manual Pages, DB( 1), nov. 3, 1971.
figure 4: At&t SVR3 “adb” syntax,
circa 1980.
expression /o
Print a two-byte integer in
octal at the specified address
expression /x
Print a two-byte integer in
hexadecimal at the specified
address
expression /d
Print a two-byte integer in
decimal at the specified
address
$a Print an Algol stack backtrace
$c Print a C stack backtrace
$r Print the machine registers
expression :b
Set a breakpoint
$< filename read and execute the
command found in
the specified file
Kernighan, B. ratfor: A preprocessor for a rational
Fortran. Soft ware—Practice and Experience. oct. 1975.
would take its address and then type
“$<proc” to execute a predefined
series of commands to display each
memory of the C data structure for
a process. The content of the proc
macro in SunOS 4 from 1984 is shown
in Figure 5. To make this output understandable, the “/” command could
now be suffixed with quoted string
labels, newlines (n) and tabs (16t) to
be included among the decoded data.
38 communicAtionS of the Acm | APriL 2009 | voL. 52 | no. 4