home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-07-21 | 17.1 KB | 588 lines | [TEXT/ttxt] |
- \ Yerk Disassembler
- \ 1/16/86 cdn Initial version
- \ 1/20/86 cdn Handle named input parameters and local variables
- \ 2/24/86 cdn Added detection of Immediate words
- \ Added RANGEOF
- \ 6/01/86 cdn Added (++>), (EX>), (TRAP), (DEFER), (JMP), COMPILE
- \ 6/02/86 cdn Added deClass, deObj, deModule, etc…
- \ 8/11/86 cdn Added multiple cfa recognition
- \ 8/25/86 cdn Added method decompilation
- \ 6/29/87 rfl Added the first three cases to handle floats
- \ 12/17/87 rfl Fixed .num to show signs
- \ 1/11/90 rfl Fixed ?isobj,?isclass,?ismod,?isvect,.32-bit etc. for protection
- \ against invalid RAM
- \ 3/14/90 rfl nhash now wordcol; took out ?isobj since now in Class
- \ 10/03/90 rfl added protection for lit numbers out of app range
- \ 10/26/90 rfl changed /module to |module so can decompile words with '/' in them
- \ 12/16/90 rfl added offCol instead of old ordered-col
- \ 3/29/91 rfl fixed slight bug setting 0 -> #p in decol
- \ 10/26/91 rfl undid a reserve back to allot in name/hash
- \ 2/25/92 rfl fixed super/self problem with decompiling a class method
- \ 5/14/93 rfl now decompiles vect, value, and sysvec contents too.
- \ 6/17/93 rfl fixed another super/self problem when de' a method
- \ 6/22/93 rfl added support for float named input and local vars
- \ 7/16/93 rfl after 3.64 release, redefined 'inapprange?' to use heapbot and top
- \ 7/21/93 rfl added inapprange? to 32-bit
-
- \ de' will decompile colon definitions and methods of classes; follow with a
- \ slash-module name to decompile module code. Named stack parms and local vars
- \ are indicated by a curly bracket syntax like the one used to compile them,
- \ however their actual names are no longer known after compilation so symbolic
- \ names parmN & varN are shown. Method selectors are also unavailable after
- \ compilation since they are hashed, so the common sequence: meth: obj
- \ decompiles as: ???: obj. Methods bound to ivars within class definitions
- \ are shown by the offset of the ivar data within the object. eg: ???: 12
- \ Anything completely unrecognized will display as ¿¿¿
- \
- \ "deflgs" bits:
- \ 0 - print absolute address of each item
- \ 1 - print relative address of each item
- \ 2 - print offset of each item
- \ 3 - display super class data
- \ 4 - display nested ivar stuctures
- \ 5 - display indexed data
-
- :module deMod
-
- 0 value tab
- : indent tab 4* out - 0 max spaces ;
-
- : .bld 1 tFace ; \ print in bold
- : .exp 64 tFace ; \ print in expanded
- : .nor 0 tFace ; \ revert to normal mode
- : .hash .bld ." hash:" . .nor ;
-
- \ : sign rot 0< IF 45 hold THEN ;
- \ ( val -- )
- : .num dup abs 0 <# #s sign #> type ;
-
- 0 value start
- \ Print address and/or offset of datum
- : .addr { addr -- }
- .bld
- deflgs 01 and IF addr +base .num ascii : emit THEN
- deflgs 02 and IF addr .num ascii : emit THEN
- deflgs 04 and IF addr start - .num ascii : emit THEN
- .nor ;
-
- : NewL ?pause
- CR dup .addr
- 0 -> out indent ;
-
- : ?NewL
- out tab 4* - 0> IF NewL THEN ;
-
- \ ( addr -- addr' ) print "parmN" or "varN"
- : .p/v
- dup @ >name 3+ c@ dup 48 - mp0 < \ mp0 is a peek at deComp's "#p" var
- IF ." parm" ELSE ." var" THEN
- emit space 4+ ;
-
- \ ( addr -- addr' ) print "parmN" or "varN"
- : .%p/v
- dup @ >name 4+ c@ dup 48 - mp0 < \ mp0 is a peek at deComp's "#p" var
- IF ." %parm" ELSE ." %var" THEN
- emit space 4+ ;
-
- 0 value nflgs
- \ ( pfa -- ) print name of definition and save name field flags
- : .nfa nfa dup id. c@ -> nflgs ;
-
- :CLASS wArray <Super Object 2 <Indexed
-
- :M AT: ?idx ^Elem w@ ;M
- :M TO: ?idx ^Elem w! ;M
-
- ;CLASS
-
- :CLASS wordCol <Super wArray
-
- Int Size \ # elements in list
-
- \ ( -- curSize ) Return #elements currently in list
- :M SIZE: Get: Size ;M
-
- \ ( val -- ) Add value to end of list
- :M ADD: Get: Size limit >=
- classErr" 137 Get: size To: Self
- 1 +: Size ;M
-
- \ ( val -- ind t OR f) Find a value in an OC
- :M INDEXOF: 0 swap Get: Size 0
- DO i (^elem) w@
- over = IF 2drop i 1 1 leave THEN
- LOOP drop ;M
-
- ;CLASS
-
- :CLASS OffArray <super wordCol
-
- var pointer
-
- :M init: ( addr --) put: pointer ;M
- :M at: ( ind -- addr) at: super get: pointer + ;M
- :M add: ( addr --) get: pointer - add: super ;M
-
- ;CLASS
-
- 370 WordCol nHash
- 370 OffArray hName
- : name/hash here init: hName
- new: loadFile
- " name/hash" name: topFile
- openReadOnly: topFile IF ." No name/hash table available" exit THEN
- BEGIN
- tib 128 expect: topFile 0=
- WHILE
- bytesRead: topFile 1-
- tib over here >str255 here c@ >uc
- here hash add: nHash
- here add: hName
- 1+ allot
- REPEAT
- remove: loadFile
- ;
- name/hash
-
- \ ( val -- )
- : .mName
- indexOf: nhash
- IF at: hName count type space
- ELSE ." ???: " THEN ;
-
- : inAppRange? ( addr -- addr b) dup heapBot heapTop within ;
-
- \ ( pfa #parms -- ) Decompile cfas starting from pfa
- : deComp { #p \ ;? cf? -- } \ #p number of parms, ;? end of defintion flag
- 0 -> ;?
- 1 ++> tab indent
- BEGIN ( addr )
- dup @
- CASE ( addr cfa )
- 'c flit OF 4+ dup print: float 10 + ENDOF
- 'c killfargs OF ." KillFargs" 6 + ENDOF
- 'c !fp(ip) OF ." -> " 4+ dup w@ 8 - 4 / $ 30 + ." %parm" emit 2+ space ENDOF
- 'c +fp(ip) OF ." ++> " 4+ dup w@ 8 - 4 / $ 30 + ." %parm" emit 2+ space ENDOF
- 'c lit OF 4+ dup @
- over 4+ @ dup 'c trap = swap 'c (fdos) = or
- IF ." $" .h
- ELSE inAppRange?
- IF ?cfa
- IF ." 'c " >name id.
- ELSE dup cfa ?cfa
- IF drop ." ' " nfa id.
- ELSE drop .num space
- THEN
- THEN
- ELSE .
- THEN
- THEN 4+ ENDOF
- 'c wlit OF 4+ dup w@
- over 2+ @ dup 'c trap = swap 'c (fdos) = or
- IF ." $" .h
- ELSE dup cfa inAppRange?
- IF ?cfa
- IF drop ." ' " nfa id.
- ELSE drop .num space
- THEN
- ELSE .
- THEN
- THEN 2+ ENDOF
- 'c wlitw OF 4+ ." w" dup w@ . 2+ ENDOF
- 'c (lits) OF 4+ ?NewL dup w@ ." <[" dup . ." ]> 'cfas "
- swap 2+ swap 0
- DO dup @ >name id. 4+ LOOP ENDOF
- 'c (trap) OF 4+ ascii $ emit
- base >R hex
- dup w@ . ." Trap " 2+
- R> -> base ENDOF
- 'c [trap] OF 4+ ascii $ emit
- base >R hex
- dup w@ . ." Trap " 12 +
- R> -> base ENDOF
- 'c (defer) OF 4+ dup w@ .mName ." [ ] " 2+ ENDOF
- 'c (classerr") OF 4+ ." ClassErr" ascii " emit
- dup w@ . 2+ ENDOF
- 'c (.rAbort) OF 4+ ." ?error"
- dup w@ . 2+ ENDOF
- 'c (.rStr) OF 4+ ." msg#"
- dup w@ . 2+ ENDOF
- 'c (.tStr) OF 4+ ." type#"
- dup w@ . 2+ ENDOF
- 'c compile OF 4+ ." Compile " dup @ >name id. 4+ ENDOF
- 'c branch OF 4+ ." Branch:" dup @ dup .
- over + .addr 4+ NewL ENDOF
- 'c 0branch OF 4+ ." 0Branch:" dup @ dup .
- over + .addr 4+ NewL ENDOF
- 'c (do) OF 8+ ?NewL ." DO " 1 ++> tab NewL ENDOF
- 'c (loop) OF 8+ -1 ++> tab ?NewL ." LOOP " ENDOF
- 'c (loop+) OF 8+ -1 ++> tab ?NewL ." +LOOP " ENDOF
- 'c (of) OF 8+ ." OF " ENDOF
- 'c (rof) OF 8+ ." RANGEOF " ENDOF
- 'c (select) OF 4+ ?NewL ." Select{" NewL
- @ dup dup dup @ - 4 / 1- 0
- DO i . ." is{ " 4- dup @ #p deComp
- ." }end" NewL
- LOOP ." default{ "
- 4- @ #p deComp
- ?NewL ." }Select" 4+ NewL ENDOF
- 'c (.") OF 4+ ascii . emit ascii " emit space
- count 2dup type ascii " emit space
- + align ENDOF
- 'c (lit") OF 4+ ascii " emit space
- count 2dup type ascii " emit space
- + align ENDOF
- 'c (ab") OF 4+ ." Abort" ascii " emit space
- count 2dup type ascii " emit space
- + align ENDOF
- 'c (al") OF 4+ ." Alert" ascii " emit space
- count 2dup type ascii " emit space
- + align ENDOF
- 'c (disp) OF 4+ ." Dispose> " dup @ 8- nfa id. 4+ ENDOF
- 'c (mdisp) OF 4+ ." Dispose> " dup w@ dup #p <
- IF ." parm" ELSE ." var" THEN
- 48 + emit space 2+ ENDOF
- 'c (be) OF ." Become " 4+ ENDOF
- 'c (semip) OF drop 1 -> ;? ENDOF
- 'c (jmp) OF 4+ @ .exp ." ( Forward referenced )"
- .nor NewL ENDOF
- 'c ;s OF drop 1 -> ;? ENDOF
- 'c (;m) OF drop 1 -> ;? ENDOF
- 'c (;code) OF drop CR ." (;CODE) " 1 -> ;? ENDOF
- 'c (,code) OF drop CR ." BUILD " 1 -> ;? ENDOF
- 'c header OF 10 + dup 2- w@ 4 / 0
- DO NewL .exp i .num ." cfa: " .nor
- NewL dup @ 10 + 0 deComp CR 4+
- LOOP drop 1 -> ;? ENDOF
- 'c @fp0 OF .%p/v ENDOF
- 'c @fp1 OF .%p/v ENDOF
- 'c @fp2 OF .%p/v ENDOF
- 'c @fp3 OF .%p/v ENDOF
- 'c @fp4 OF .%p/v ENDOF
- 'c @fp5 OF .%p/v ENDOF
- 'c mp0 OF .p/v ENDOF
- 'c mp1 OF .p/v ENDOF
- 'c mp2 OF .p/v ENDOF
- 'c mp3 OF .p/v ENDOF
- 'c mp4 OF .p/v ENDOF
- 'c mp5 OF .p/v ENDOF
- 'c ms0 OF ." -> " .p/v ENDOF
- 'c ms1 OF ." -> " .p/v ENDOF
- 'c ms2 OF ." -> " .p/v ENDOF
- 'c ms3 OF ." -> " .p/v ENDOF
- 'c ms4 OF ." -> " .p/v ENDOF
- 'c ms5 OF ." -> " .p/v ENDOF
- 'c (++>) OF 4+ dup w@ 8- 4 / dup #p < ." ++> "
- IF ." parm" ELSE ." var" THEN
- 48 + emit space 2+ ENDOF
- 'c (ex>) OF 4+ dup w@ 8- 4 / dup #p < ." exec> "
- IF ." parm" ELSE ." var" THEN
- 48 + emit space 2+ ENDOF
- \ OTHERWISE
-
- dup >body ?isObj \ normal early bound method?
- IF drop ( addr cfa )
- over 4+ @ @ ' m0cfa =
- IF over 4+ @ 6 - w@ .mName >name id. 8+
- deflgs 07 and IF dup 4- @ 6 - w@ .hash THEN
- ELSE >name id. 4+ THEN
-
- ELSE drop ( addr cfa )
-
- dup @ ' m1cfa = \ method bound to a private ivar?
- IF 10 - w@ .mName 4+
- dup w@ 65535 over = \ check for self/super ref
- IF drop dup 4- @ start <
- IF ." super" ELSE ." self" THEN
- ELSE .num THEN space 2+
- deflgs 07 and IF dup 6 - @ 10 - w@ .hash THEN
-
- ELSE ( addr cfa )
-
- dup @ ' m0cfa = \ method bound to a class
- IF dup 6 - w@ .mName
- latest BEGIN 2dup < WHILE pfa lfa @ REPEAT id. drop
- 4+
-
- ELSE ( addr cfa )
- ?cfa \ ultimately, this is the usual case
- IF >name dup id. n>count " INLINE" s=
- IF 4+ BEGIN dup w@ dup $ 49fa <>
- WHILE ascii $ emit .h 2+
- out 60 > IF NewL THEN
- REPEAT
- drop 4+
- THEN
- ELSE 1 -> cf? 9 1
- DO cfa ?cfa \ check for nth cfa
- IF dup @ >R valCode R = vectCode R = or
- fvalCode R = or svCode R> = or
- IF i 1 = IF ." ++> " ELSE ." -> " THEN
- ELSE 48 i+ emit 45 emit THEN
- >name id. 0 -> cf? leave
- THEN
- LOOP
- cf? IF drop ." ¿¿¿ " THEN \ all decomp failed
- THEN
- 4+
- THEN
-
- THEN
- THEN
-
- dup \ for consumption by endcase
-
- ENDCASE
-
- deflgs 07 and \ print address and/or offset?
- IF
- NewL \ new line for every word
- ELSE
- out 60 > IF NewL THEN
- THEN
-
- ;? UNTIL
- nflgs $ 40 and IF ." Immediate" THEN
- -1 ++> tab
- ;
-
- 0 value floatpos
- : isFloatP/V ( pos --) floatPos and IF ascii % emit THEN ;
-
- \ ( pfa -- ) decompile a definition; may have named stack
- : deCol { myPfa \ amt #p -- } \ #p number of parms
- 0 -> #p
- myPfa c@ \ Does definition has named stack or local vars
- IF ." { "
- myPfa c@ -> amt \ get the total number of parms and vars
- myPfa 1+ c@ -> floatPos \ get position of any floats
- amt $ F and -> #p \ look at parms first
- #p 0 DO i 1+ isFloatP/V ." parm" 48 i+ emit space LOOP
- amt 4 >> -dup
- IF ascii \ emit space 0 DO 1 #p i+ << isFloatP/V ." var" 48 #p + i+ emit space LOOP THEN
- ." -- }" myPfa 2+ -> myPfa
- THEN
- NewL myPfa #p deComp ;
-
- : NxtL ?pause
- CR 0 -> out indent ;
-
- \ ( pfa -- ) decompile a class definition
- : deClass { ^class \ k -- } CR
- 0 -> k 1 -> tab
- ^class mfa @ \ get starting addresses of method
- BEGIN dup ^class >
- WHILE 1 ++> k dup 2+ @
- REPEAT drop
- ." :CLASS " ^class nfa id.
- ." <Super " ^class 22 + @ nfa id.
- ^class 20 + w@ -dup IF . ." <Indexed" THEN CR
- ^class 18 + w@ NxtL .exp ." (" . ." Bytes )" .nor CR
- k 0 DO
- NewL ." :M " dup w@ .mName 14 + deCol
- NewL ." ;M" CR
- LOOP
- CR ." ;CLASS"
- ;
-
- 0 value odata
- : .) ascii ) emit ;
- : .( .addr ascii ( emit ;
-
- : .32-bit
- dup . inAppRange?
- IF ?cfa
- IF >name id. ELSE drop THEN
- ELSE drop
- THEN ;
-
- \ ( length -- ) display a fundamental datum from the object
- : .odata { w -- }
- odata .(
- w CASE
- 1 OF odata c@ . ENDOF
- 2 OF odata w@ . ENDOF
- 4 OF odata @ .32-bit ENDOF
- \ OTHERWISE
- w . ." Bytes " \ if not 1, 2 or 3; just tell how many bytes there are
- ENDCASE
- .)
- w ++> odata
- ;
-
- \ display indexed data cells with their indices
- : .idata { \ width -- }
- odata w@ -> width 4 ++> odata \ get width and skip indexed header
- odata 2- w@ 0
- DO NxtL
- i . width .odata \ print the contents of each element
- LOOP
- ;
-
- Forward .struct
-
- \ display contents of ivar
- : .ivars { lastNFA 1stNFA dlen \ inc -- }
- lastNFA 12 + 1stNFA
- DO 12 -> inc \ usual length of an ivar
- NxtL
- i 6 + @ \ get ivars class pointer
- dup ' Object =
- IF ." DATA " drop \ This ivar is DATA
- i lastNFA = \ If last ivar, can't subtract from next ivar
- IF dlen \ computes # bytes
- ELSE i 22 + w@ THEN
- i 10 + w@ - .odata
- ELSE
- dup nfa id. \ This ivar may be nested
- dup @width \ indexed?
- dup IF 14 -> inc
- 4 ++> odata THEN \ (get past indexed overhead)
- over ifa @ 3 pick 26 + > or \ nest?
- deflgs 16 and lAnd \ supposed to be displaying nested?
- IF 1 ++> tab .struct -1 ++> tab
- ELSE dfa w@ .odata THEN
- THEN
- inc +LOOP
- ;
-
- 0 value snest
-
- \ ( ^class -- ) print ivar data & indexed data (recursive from .ivars & self)
- :f .struct
- 1 ++> snest
- dup dfa w@ \ total length of object data
- over sfa @ dfa w@ \ length of super class data
- tab 0= over lAnd deflgs 08 and lAnd
- IF 3 pick dup sfa @ dup nfa CR ." --" id. CR \ display super data
- .struct nfa CR ." ==" id. CR
- ELSE dup ++> odata THEN \ skip super data
- - -dup \ total data minus super data
- IF over ifa @ \ pointer to last ivar
- 3 pick 26 + \ pointer to first ivar
- rot .ivars \ print ivar data
- ELSE tab 0= IF .exp ." ( No ivars )" .nor CR THEN THEN
- @width \ print indexed data if any
- IF deflgs 32 and snest 0= lAnd
- IF NxtL .exp ." --Indexed Data--" .nor
- .idata
- THEN
- THEN
- -1 ++> snest
- ;f
-
- \ ( pfa -- ) display the data of an object
- : deObj CR
- dup here >
- IF ." HEAP-OBJECT "
- ELSE dup nfa id. THEN \ otherwise print object name
- dup -> odata \ set start of data
- .exp ." is an Object of Class: " .nor
- cfa @ dup nfa id. \ print superclass name
- -1 -> snest 0 -> tab
- .struct \ print ivar data & indexed data
- ;
-
- \ ( pfa -- ) decompile a module definition
- : deModule { \ #imps -- }
- ." From " dup nfa id. ." Import{ "
- dup 16 + w@ -> #imps 12 + @
- #imps 1- 0 DO \ gather export words
- dup pfa lfa @
- LOOP
- #imps 0 DO \ print export word names
- id.
- LOOP
- ." }"
- ;
-
- 0 constant con
- 0 variable vare
-
- \ ( pfa -- pfa bool )
- : ?isMod modCode over cfa (@) drop = ;
- ' does> 20 + constant doesCode
-
- \ ( pfa -- ) setup for one of the decompilers: Colon, Class, Object, etc…
- : (de) ?pause
- dup -> start 0 -> nflgs 0 -> tab
- dup cfa @ over = IF nfa id. .exp ." is a Code word" .nor CR exit THEN
- ?isObj IF deObj CR exit THEN
- ?isClass IF deClass CR exit THEN
- ?isMod IF deModule CR exit THEN
- dup cfa @ ( pfa code )
- dup colCode = over ' colP = or
- IF drop CR ." : " dup .nfa deCol CR ." ; " CR exit THEN
-
- CASE
- over .nfa .exp ( pfa code )
-
- valCode OF .bld ." is a Value " .nor 8+ dup .( @ dup .32-bit .) cr
- ?isobj IF (de) ELSE drop THEN ENDOF
- fvalCode OF ." is an fValue" .nor drop ENDOF
- impCFA OF ." is an Import word " .nor dup .( space @ >name id. .)
- nflgs $ 40 and IF CR ." Immediate" THEN ENDOF
- 'code con OF ." is a Constant " .nor dup .( @ .32-bit .) ENDOF
- 'code vare OF ." is a Variable " .nor dup .( @ .32-bit .) ENDOF
- vectCode OF .bld ." is a Vect " .nor 8+ dup .( @ -dup IF 4+ dup nfa space id. .) cr (de)
- ELSE 0 . .) THEN ENDOF
- svCode OF ." is a sysVect " .nor 8+ dup 4+
- begin-dp @ rot @ + dup @ 0= IF drop dup THEN
- dup .( @ 4+ dup nfa space id. ." ) … default "
- swap dup .( @ >name space id. .) cr (de) ENDOF
- doesCode OF @ latest BEGIN 2dup < WHILE pfa lfa @ REPEAT
- ." is a " id. ." definition" .nor drop ENDOF
-
- \ OTHERWISE ( pfa code )
-
- ' (dodo) over 2+ @ =
- IF 0 >R latest BEGIN 2dup < WHILE R> drop dup >R pfa lfa @ REPEAT
- ." is a " R> id. ." definition" .nor 2drop
- ELSE
- dup 4- @ over =
- IF ." is an alias of " .nor nfa id.
- ELSE ." is a MYSTERY" .nor drop THEN
- THEN
-
- ENDCASE
- CR
- ;
-
- \ ( str255 chr -- offs t OR f )
- : charOf { adr chr -- }
- 0 \ bool
- adr c@ 1+ 1
- DO
- adr i+ c@ chr = IF drop i 1- 1 leave THEN
- LOOP
- ;
-
- \ ( str -- nfa ) lookup module vocabulary if specified; else main dictionary
- : dvoc { str -- }
- str ascii | charOf
- IF str over 1+ over c@ over - str rot + c! c! \ double string
- str count + latest (find) 0= Abort" not found" drop
- ?isMod 0= Abort" not a module"
- dup cfa execute \ get module into memory
- 8+ @ $ ffffff and
- @ $ ffffff and \ get nfa of last word in module
- ELSE latest THEN ;
-
- \ decompile any yerk word or method
- \ de' word[|module]
- \ de' meth: class[|module]
- : de'
- @word dup c@ over + c@ ascii : =
- IF dup count str255 drop hash \ method of a class
- @word dup
- dvoc (find) 0= Abort" not found" drop
- ?isClass 0= Abort" not a class"
- dup -> start (findm) ." :M " buf255 count type 4+ deCol
- CR ." ;M" CR
- ELSE \ normal word
- dup dvoc (find) 0= Abort" not found" drop
- (de)
- THEN ;
-
- ;Module
-