Free the mouse Replay DisassemblyNotes
Home | Changes | Index | Search | Go

Disassembly Notes


This page will be less well-organized than some of the others here; it's a dumping ground for any useful techniques or info I pick up that ought to be shared, but that either don't deserve extensive writeups, or just haven't received them yet.


Unlike the earlier models, the 4000 is based on VxWorks and uses multiple modules in standard MIPS_BE ELF file formats. The GNU binutils include useful tools for making sense of these files. Download, configure with something like ./configure --prefix=/home/jtl/apps/binutils-2.11.2-mips --program-prefix=mips --target=mips-wrs-vxworks, make, and make install, and you're well on your way.

ptv.bin, the primary program in previous versions, now appears to be the lowest-level of software, providing services traditionally associated with operating systems. This may be primarily VxWorks code, rather than ReplayTV-specific.; There are multiple .out modules and a CougLib.o library; all of these are in the Platform/Plymouth/Modules directory under the sys directory (which will be either sys1 or sys2; 411 ZONE will show which is being used). The ReplayTV GUI system, the UI built on top of it, and much of the rest, is in the IAppShell.out module.

I started off with something like:


base=`basename $file .out`
base=`basename $base .o`
base=`basename $base .bin`

strings - $file > $base.strings
mipsobjdump -s -j .data $file > $
mipsobjdump -s -j .rodata $file > $base.rodata
mipsobjdump -C -r $file > $base.reloc
mipsobjdump -C -d -mmips4650 $file > $base.dis
merge-disasm-reloc $base.dis $base.reloc > $file.combined
(the current version of the real one is a bit fancier than that) adds relocation records for the .text segment to the disassmebly of the segment (that doesn't work for ptv.bin, which is linked statically and has no

relocation records). For each module, you end up with a .strings file, containing just the strings in the file; useful for grepping to find particular text; .rodata, a hexdump of the read-only data segment; .data; a hexdump of the initialized modifiable data segment; .reloc, the relocations -- relocations for the text segment have been merged into the combined file, but there are possibly relocations for the data and rodata segments as well; .dis, the raw disassembly; and .combined, disassembly + relocation. Most of your disassembly time will be spent with combined files.


The MIPS32 architecture and instruction set references can be downloaded (after registration) from


Most of the intra-module interfaces seem to be handled via C++ vtables. Some classes are fairly traditional types, with multiple objects of the class; many others seem to have just one instance used globally (or possibly just lots of static functions). A call to a member function through a vtable looks something like:

; s0 is a pointer to an object; in this case, an IRPlatform *

; first, get a pointer to the vtable; there doesn't seem to be a rule-of-thumb
; for knowing where in the object it is.
    26d4:   8e020000    lw   v0,0(s0)
; get an offset into the object to use for 'self'.  Every case I've looked at,
; this is 0; I expect this is for multiple inheritance support.
    26d8:   844400b0    lh   a0,176(v0)
; get a pointer to the function itself.
    26dc:   8c4200b4    lw   v0,180(v0)
; add the object offset to the pointer we already have; this has to go into
; a0; all the other pointers involved are optional, but usual
    26e0:   02042021    addu   a0,s0,a0
; make the actual call
    26e4:   0040f809    jalr   v0      ; IRPLatform_mmb_176(sp + 32)
; remember that the instruction after the call itself is executed before
; the call; in this case, the first non-self argument is set here
    26e8:   27a50020    addiu   a1,sp,32
The notation I've been using is "Object_mmb_number", where number is the offset in the vtable to the object offset (the offset to the function pointer (180 in this case) or the C-style index (176/8 = 22 in this case) would make more sense -- I started using this notation before I fully understood what was happening).

Most (all) classes are split between interface and implementation classes; calling functions get a pointer to an IRPlatform object, for example, which is actually implemented by an IRPlatformImpl object.

Checking the ptv.sym file, we see that the IRPlatformImpl? virtual table is at 0xffffffff80163120. Adding 180 to that, we get 0xffffffff801631d4; looking at ptv.rodata, we find at 0x801631d4 (what happened to the leading 0xffffffff00000000? The MIPS IV architecture is 64-bits extended from an older 32-bit architecture very cleanly; it basically has a full 32-bit subset hidden cleanly inside with no mode bits. For reasons too involved to go into here (see Run, Mips, Run or write me if you're really interested) 32-bit constants when loaded into 64-bit registers always sign extend, and the entire top half of the 32-bit address space (which for other reasons is the only half normally used on an embedded system) is replicated in a teeny tiny bit of the 64-bit address space -- so, address 0xffffffff801631d4 is the same as address 0x801631d4. As a side note: I haven't seen any use of the full register width; 64 bit quantities are always split between two registers) the address 0x8002c3c0. Going back to ptv.combined, we find IRPlatformImpl::GetBootState(RBootState? &) at that address; in this case, we got somewhat lucky - functions called through vtables may not have visible names.


Update: Solved! daddiu, despite being 'unsigned', sign-extends its arguments, so anything in the upper-half of a 64k chunk will have a high-bit section 1 higher than I'd thought; so, how much have I gotten wrong, not knowing that? (and not knowing that offset(base) addressing is signed)

Update: Solved! They're MIPS32/MIPS4650 instructions, which aren't covered by the MIPS IV instruction set document I've been using, and weren't disassmebled because the ELF header claimed these are MIPS4000 files, not MIPS32/MIPS4650.

Updated: Solved! The symbol table marked them as objects, not functions, so the disassembler didn't even try - they must be assembly objects rather than C/C++, which makes sense. Using "-D" instead of "-d" fixes that. more later

-- ToddLarason - 09 Mar 2002

The __ctype values the Replay uses:

-- ToddLarason - 28 Mar 2002

to disassemble a straight memory dump: mipsobjdump -D -EB -m mips -b binary

-- ToddLarason - 29 Jun 2002

Your post will appear before this form in chronological order (newest at bottom)

Attachment: Action: Size: Date: Who: Comment: action 600 09 Mar 2002 - 16:26 ToddLarason action 630 09 Mar 2002 - 16:27 ToddLarason

Topic DisassemblyNotes . { Edit | Attach | Ref-By | Printable | Diffs | r1.8 | > | r1.7 | > | r1.6 | More }
Revision r1.8 - 14 Jul 2003 - 18:54 GMT - TWikiGuest
Parents: WebHome
Copyright © 2001 by the contributing authors. All material on this collaboration tool is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback.