Disassembler
Volume Number: | | 1
|
Issue Number: | | 6
|
Column Tag: | | MacNosy
|
A New Disassembler
By Steve Jasik
A New Disassembler
As a compiler writer specializing in code generation, I decided to build a Disassembler to better understand the Motorola 68000 and the Macintosh operating system. Given the poor quality of the documentation and the general lack of source listings, a powerful disassembler is a useful tool for debugging and getting information about the system.
MacNosy and its helper programs consist of over 7000 lines of Pascal and about 300 lines of assembly lanaguage code. Internally, MacNosy contains many features usually associated with a compiler such as a table manager, symbol table enter/lookup routines, a reference map, global flow analysis, etc.
Features
MacNosy has many features that place it an order of magnitude above other disassemblers. They include:
Symbol dictionaries of the Rom names and global symbols (0 - $B00) along with value to symbol substitution in appropriate places.
Selective list of procedures in a file by procedure name or substring.
Ability to place the disassembled output on a file in assembler listing output or assembler input format (MDS .list or .asm format).
References to the symbols are collected and may be selectively viewed.
Ability to search the program file for references to selected addresss, trap (rom) calls, resource type references, constant or string references.
Ability to translate the segment relative address of an instruction to the disk file relative address for code patching purposes.
MacNosy records its input on a .jrnl file (in text format) for later playback. This feature is used as an educational tool and as a medium of communication between developers, hackers, etc.
Ability to reformat data in its natural format via directives. This is in addition to the automatic recognition of various character string formats.
A full or selective listing of the resources in a file. Format is similar to that of the Resource Mover, but you get more information with less work.
A built-in mini editor to view files without leaving Nosy.
Facts and Specifications
MacNosy runs on a 512K Mac or a 1 Meg Lisa under the Workshop O.S. or the Macworks environment.
It is capable of disassembling the resource fork of any application file, ROM, Macsbug, and various resource types in the System file (DRVR, PACK, INIT, CDEF, WDEF, etc). Note that source listing of the WDEF, CDEF procedures come with the MacSupplement.
The released disk contains both the Mac and Lisa versions of MacNosy, some sample .jrnl files to acquaint you with it, source code for the table manager (this may be useful to other developers) and the SfGetFile routines so you can see how it selects files to disassemble.
How does MacNosy work?
When disassembling a file, one must know the structure (code or data) of a given piece of the file. To do this, Nosy uses the fact that every program has a call graph. The nodes of the graph are the procedures and the edges are the calls (A calls B, etc). As Nosy is primarily interested in the size of the nodes, it ignores some aspects of the graph (such as recursion) which leads to cycles in the graph. Because of this, the graph reduces to a Directed Acyclic (without cycles) Graph. We can get sloppy in our terminology and refer to the DAG as a tree of procedures.
Discovering the size and extent of a procedure is a messy problem that entails disassembling instructions, and looking for the procedure exits. The potential presence of spaghetti code makes the algorithm more complicated.
At this point a reasonable strategy is to treat the file as a collection of code and data blocks (contigious set of bytes). We start at the entry points and walk the tree until all possible procedures have been discovered. The remaining areas are caterogized as data blocks. During the tree walk Nosy builds symbol tables for the various categories of labels which are:
Procedure (JSR X) X = procnnn or the 8 character name following the proc if compiled by Lisa Pascal with the D+ option on.
Global labels ( X(A5) )
X = globnnn
Data labels (LEA X or PEA X)
X = datannn
Common labels (JMP X, Bcc X from another proc) - com_nnn
Local labels within a procedure - loc_nnn
You can change the names of all but the local labels in Nosy.
Example 1 - A fragment of the resource list of a System file.
Note that for the DITLs the accompanying text/controls are listed.
26 resource types, data index = 100
Type FRSV att indx length name
ID 1 00 CF12 A 0 0
Type ALRT att indx length name
ID -3997 20 CDBC C 0 0
ID -3996 20 CDCC C 0 0
ID -3995 20 CDDC C 0 0
ID -3994 20 CDEC C 0 0
Type DITL att indx length name
ID -15936 20 BA6C 1E
ID -6047 20 CA18 1A6 <Initialize> <Eject> <OK>
Do you want to initialize it?
This disk is unreadable:
This disk is damaged:
This is not a Macintosh disk:
Please name this disk:
Initializing disk . . .
Initialization failed!
Initialize this disk?
ID -4000 20 CC7C A8 <Open> <O> <Cancel> <Eject> <Drive>
h
ID -3999 20 CD28 90 <Save> <Cancel> Save as: <Eject> <Drive>
Example 2 - code fragment from a little test program I wrote.
The output listing format is:
aaa: hhhh hhhh cccc label opcode address $ssaaaaaa
aaa = segment relative address , hhhh and ccccc are the value of the instruction in hex and ascii. The field ssaaaaaa is the address of any label or symbol reference in the
address field. ss is the segment number of the reference.
I have suppressed leading zeros in most cases and many of the numeric formats use decimal conversion. The macros POP and PUSH have the obvious meaning. The QUAL pseudo implies that all the labels of the form loc_nnn are local to the procedure. The line right after it tells us who calls it. The line with _Button is a trap macro. The DNAME macro expands to the 8 character name which is used by Lisabug and Nosy.
440: QUAL CHK_USER
; refs - TEST
440:
440: 4E56 0000 NV.. CHK_USER LINK A6,#0
444: 4267 Bg CLR -(A7)
446: A974 .t _Button
448: 101F .. POP.B D0
44A: 6714 g. BEQ loc_2
$1000460
44C: 2F0E /. PUSH.L A6
44E: 4EBA FFC0 N... JSR WAITBUTT
$1000410
452: 4267 Bg loc_1 CLR -(A7)
454: A974 .t _Button
456: 101F .. POP.B D0
458: 67F8 g. BEQ loc_1
$1000452
45A: 2F0E /. PUSH.L A6
45C: 4EBA FFB2 N... JSR WAITBUTT
$1000410
460: 4E5E N^ loc_2 UNLK A6
462: 4E75 Nu RTS
464:
464: C348 data21 DNAME CHK_USER,0,2
Example 3 - This next routine was dumped to the hardcopy file in .asm format.
It is suitable for input to the MDS assembler ASM.
QUAL WCR
; refs - TEST
WCR LINK A6,#0
PUSH.L glob13(A5)
PEA data19
CLR -(A7)
JSR %W_STR
PUSH.L glob13(A5)
JSR %W_LN
PUSH.L glob12(A5)
PEA glob8(A5)
PUSH #255
JSR %R_STR
PUSH.L glob12(A5)
JSR %R_LN
UNLK A6
RTS
data18 DNAME WCR ,0,2
; refs - WCR+8
data19 STR wait for cr
Example 4 - Note the Value to Symbol substitution in this ROM fragment listing
404C12: 50F8 0902 P... Launch S_T LaunchFlag
$902
404C16: 31E8 0004 0936 1....6 loc_2 MOVE 4(A0),CurPageOption
$936
404C1C: 2058 X MOVE.L (A0)+,A0
404C1E: 43F8 0910 C... LEA CurApName,A1
$910
404C22: 7020 p MOVEQ #32,D0
404C24: A02E .. _BlockMove
Example 5 - Sample Reference Map listing fragment of the System Globals from ROM
114 HeapEnd proc203 MaxMem proc253
118 TheZone proc201 proc203 GetZone MaxMem proc212 proc232
InitResources proc852 MoreMasters InitZone
proc204
SetGrowZone
11C uTableBase proc36 proc89 proc96 RDrvrInstall SystemTask
proc942
SystemMenu OpenDeskacc BlockMove com_28
Example 6 - Sample Segment Reference Map listing fragment of Nosy.
Inter seg refs are prefixed with n/. This map may be used for procedure balancing.
seg# procedure fba blen refs (seg#/proc) called by
1] HEAP_OVF 1D6 50 ADD_USED 4/NEW_TBL
1] SET_MAX 208 120 CLR_TBL 4/REL_TBLS 3/RTN_PTR
1] CLR_TBL 280 46 DI_PROC 3/SEARCH_C 4/DI_FILE
3/SEARCH_C
1] MOVEUP 2AE 80 ADD_USED
1] ADD_ENTR 2FE 42 DI_PROC ENTER_LA PUT_REF
NEW_CASE
ADD_ISPR 3/CHK_PROC 4/NI_FILE
4/DI_FILE
PROCESS_
1] SET_USED 328 44 4/NI_FILE
Disassemblling the ROM
I Would like to show a sample listing of a piece or two of ROM but I dont want to start any fights with Apples Lawyers. So like sex, I leave it for you to do it in the privacy of your own home.
I found a few interesting things looking around the ROM. One is an interesting piece of unreachable code at 40AD30 which blasts 32 long words into RAM and then hangs. Another is the come from code in the rom patch area in the system heap. In many cases bugs were patched by placing a CMPI.L $40xxxx,28(A7) followed by a suitable jump in unrelated routines. A rather obnoxious example is BlockMove which contains 3 such checks. I will be forming a MacNosy Users Group (Special Interest Group) on the Delphi Information Service (800-544-4005) starting in April to study the ROM and swap jrnl files. Admission will be limited to registered owners of MacNosy.
Ordering Information
If ordered from the author before May 1, 1985 cost is $55, including sales tax for CA. residents. After that it will be sold in selected stores or direct for $70. Orders should be addressed to:
Steve Jasik
343 Trenton Way
Menlo Park, Ca. 94025
(415-322-1386)