Does anyone know how to decompile open firmware words and retrieve values from them?
Information about OF would be appreciated. I am mostly interested in the binary format of dictionary entries and what the 'code' functions look like internally.
r16 | rHere | Heap pointer |
r19 | rTOR | Top value of return stack |
r20 | rTOS | Top value of data stack |
r21 | rNOS | 2nd value of data stack |
r22 | rTOL | Top value of loop stack |
r23 | rNOL | 2nd value of loop stack |
r24 | rLP | Loop stack pointer |
r25 | rSV | Pointer to OF kernel globals (the so-called "start vector") |
r26 | rFP | Frame pointer, no clue what it means |
r27 | rEP | Exception frame pointer, used by CATCH |
r28 | rTTP | Token table pointer for translating FCODE token number to code address |
r29 | rMyself | Execution context |
r30 | rRP | OF Return stack pointer (rstack) |
r31 | rRP | OF data stack pointer (dstack) |
Header
Padding to the 4byte boundary
PowerPC machine code for low-level words
int32_t link; // offset to the previous word if any, otherwise NULL
uint8_t flags; // flags describing properties of this word (see below)
uint8_t type; // word type (see below)
uint16_t token; // FCODE token number
PStr name; // Pascal (length-prefixed) name of this word if bit 5 of the flags is unset
Bit 7 - isFindable
Bit 6 - isImmediate
Bit 5 - isHeaderless
Bit 4 - isAlias
Bit 3 - isInstance
0xB7 = subroutine
0xB8 = value
0xB9 = variable
0xBA = constant
0xBC = defer (?)
0xBD = buffer (?)
0xBE = field (?)
0xBF = low-level word, contains raw PowerPC machine code following the header
dl 0xFFFFFFD8; // offset to previous word
db 0x80; // isFindable
db 0xBF; // type = low-level word
dw 0x0422; // FCODE token number
pstr "pvr@"; // name = read processor version register
db 0,0,0; // padding bytes for code alignment
stwu rTOS, -4(rDP); // push cached top of stack value to data stack
mfpvr rTOS; // load processor version register into rTOS
blr ; // jump to next word
: get-bl-adr dup @ dup 7fffffc and dup 3000000 and if fc000000 or then swap 2 and if swap drop else + then ;
This useful function takes the address to a b or bl instruction and decodes it to get the address it points to. It is meant to be used like this:' .registers c + get-bl-adr
This retrieves the execution token of the word called ci-regs. ci-regs returns the address of the buffer used to hold the registers of the client interface program in OF. This lets you read and/or modify those registers easily.: get-bl-adr dup @ dup 7fffffc and dup 3000000 and if fc000000 or then swap 2 and if swap drop else + then ;
' .registers c + get-bl-adr 8 + @ value reg-buf
: print-frame-info dup dup ." @" 8 u.r @ ." SP: " 8 u.r ." CR: " dup 4 + @ 8 u.r ." LR: " dup 8 + @ 8 u.r cr @ ;
: dumpcistack reg-buf 4 + @ begin print-frame-info dup 0= until drop ;
dev /openprom/client-services
: open .registers cr reg-buf 4 + @ ." cur-stack is " 8 u.r cr dumpcistack open ;
mac-boot
Here is an example of its output:Client's Fix Pt Regs:
00 00000080 0010fcf8 deadbeef 001198c8 001198c4 00000001 0010ff34 001198c8
08 001198d4 0010fd5c 0010fda4 0010ff65 001198b8 00000000 00104800 001047e0
10 00000000 00104798 00000000 001170a0 9e9044d8 9e9044d8 00106b34 00218288
18 0026f1e0 00000000 00000000 001170a4 ffffffff 00119890 001198d8 0010fd60
Special Regs:
%IV: 00000300 %SRR0: 0020dc68 %SRR1: 00003030
%CR: 4884204c %LR: 0020dc68 %CTR: ff80a290 %XER: 00000000
%DAR: 00b94000 %DSISR: 42000000 %SDR1: 1ffe0000
cur-stack is 0010fcf8
@0010fcf8 SP: 0010fd38 CR: 00104798 LR: 00000000
@0010fd38 SP: 00110268 CR: 28242087 LR: 0020a910
@00110268 SP: 00110798 CR: 2884204c LR: 0020b558
@00110798 SP: 00110cc8 CR: 2824204c LR: 0020b480
@00110cc8 SP: 001111f8 CR: 28242086 LR: 0020b558
@001111f8 SP: 00111728 CR: 28242086 LR: 0020b480
@00111728 SP: 00111c58 CR: 28242044 LR: 0020b558
@00111c58 SP: 00112188 CR: 28442087 LR: 0020b558
@00112188 SP: 001126b8 CR: 28242087 LR: 0020b558
@001126b8 SP: 00112be8 CR: 28242087 LR: 0020b558
@00112be8 SP: 00113118 CR: 28242087 LR: 0020b558
@00113118 SP: 00113648 CR: 28242087 LR: 0020b558
@00113648 SP: 00113b78 CR: 28242087 LR: 0020b558
@00113b78 SP: 001140a8 CR: 28242087 LR: 0020b558
@001140a8 SP: 001145d8 CR: 28242087 LR: 0020b558
@001145d8 SP: 00114b08 CR: 28242087 LR: 0020b558
@00114b08 SP: 00115038 CR: 28242087 LR: 0020b558
@00115038 SP: 00115568 CR: 28242082 LR: 0020b558
@00115568 SP: 00115a98 CR: 28242082 LR: 0020b558
@00115a98 SP: 00115fc8 CR: 28242082 LR: 0020b558
@00115fc8 SP: 001164f8 CR: 28242082 LR: 0020b558
@001164f8 SP: 00116a28 CR: 28244082 LR: 0020b480
@00116a28 SP: 00116f78 CR: 8440004c LR: 00205644
@00116f78 SP: 00000000 CR: 00000000 LR: 00000000
I haven't gotten around to it yet, but the stack also stores function parameters and saved registers...