Documentation
dumpopo
Usage
Syntax: dumpopo.lua <filename>|--stdin [options] [<procName> [<startAddr>]]
Prints information about the specified OPO (compiled OPL) file.
If just a filename is specified, prints information about the file and all the
procedures it contains. With --all or a <procName>, prints an assembly listing
of all procedures or the specified procedure, respectively. The <startAddr>
argument can be used to skip over some amount of the procedure code, which can
be useful when debugging code using obfuscation techniques.
Options:
--all, -a
Prints assembly listing of all procedures, if neither <procName> or
--decompile is specified.
--decompile, -d
Convert the compiled code back to OPL source code and print to stdout.
Decompiles all procedures unless <procName> is specified.
--annotate, -t
In addition to setting the annotate and show-elided options (see below),
also prefixes each line with the address of the start of the first
statement on that line.
--name <proc>:<name>=<newname>
Manually specify a name for a local in the given proc. Can be used
multiple times for multiple variables. For example to rename local_00AC%
to event% in the MAIN proc, specify --name MAIN:local_00AC=event. Has
no effect unless --decompile is specified.
--aif <path>, -i <path>
Adds an APP...ENDA block to the decompile output based on the given AIF
file.
--stdin
Read from stdin rather than a file. <filename> must not be specified.
--option <opt>, -o <opt>
Pass an option to the decompiler to customise its output.
Options include:
annotate
Adds comments about inferred block structure.
show-elided
Add comments for control statements that are normally not
shown, such as implicit returns, and GOTOs that are part of
block structures.
no-elide
Like show-elided, but leave the statements in place rather than
commenting them.
no-merge-prints
Do not recombine print commands into compound print statements.
no-breaks
Do not convert GOTOs into BREAKs and CONTINUEs where applicable.
no-elses
Do not convert non-dropping-through IF...ENDIF into
IF...ELSE...ENDIF. Implies no-elseifs.
no-elseifs
Do not combine ELSE + IF... into ELSEIF.
no-whiles
Do not convert applicable IF...ENDIF into WHILE...ENDWH. Due to
the way ELSE blocks are calculated requiring the WHILE transform
to have taken place, this option implies no-elses and
no-elseifs.
Overview
Parses compiled-OPL programs, optionally decoding or decompiling the QCode.
For example, when run with no additional arguments, the structure of the file and the procedures it contains are listed. For example, when run on the very basic example program simple.opo:
$ ./bin/dumpopo.lua examples/Tests/simple.opo
UID2: 0x10000073
UID3: 0x10000168
translatorVersion: 0x200A minRunVersion: 0x200A
Source name: D:\Program
procTableIdx: 0x0000006B
1: TEST @ 0x0000001F code=0x00000036 size=0x00000018 line=0
Subproc "WAT" offset=0x0012 nargs=0
maxStack: 8
iDataSize: 23 (0x00000017)
iTotalTableSize: 5 (0x00000005)
2: WAT @ 0x0000004E code=0x00000060 size=0x0000000B line=6
maxStack: 0
iDataSize: 18 (0x00000012)
iTotalTableSize: 0 (0x00000000)
Decode support
If a procedure name or --all is given, the procedure QCode is decoded:
$ ./bin/dumpopo.lua examples/Tests/simple.opo --all
UID2: 0x10000073
UID3: 0x10000168
translatorVersion: 0x200A minRunVersion: 0x200A
Source name: D:\Program
procTableIdx: 0x0000006B
1: TEST @ 0x0000001F code=0x00000036 size=0x00000018 line=0
Subproc "WAT" offset=0x0012 nargs=0
maxStack: 8
iDataSize: 23 (0x00000017)
iTotalTableSize: 5 (0x00000005)
00000036: 2B [ConstantString] "Hello world!"
00000044: 8B [PrintString]
00000045: 92 [PrintCarriageReturn]
00000046: 53 [RunProcedure] 0x0012 (name="WAT" nargs=0)
00000049: 82 [DropFloat]
0000004A: 57 [CallFunction] 0x0A (Get)
0000004C: 80 [DropInt]
0000004D: 76 [ZeroReturnFloat]
2: WAT @ 0x0000004E code=0x00000060 size=0x0000000B line=6
maxStack: 0
iDataSize: 18 (0x00000012)
iTotalTableSize: 0 (0x00000000)
00000060: 2B [ConstantString] "Waaaat"
00000068: 8B [PrintString]
00000069: 92 [PrintCarriageReturn]
0000006A: 76 [ZeroReturnFloat]
Decompilation
If --decompile is given, an attempt is made to convert the QCode back to OPL source code. While the OPL compiler is not hugely complex, not all information is preserved so the source code is unlikely to be identical to the original - in particular, names of local variables are thrown away by the compiler so the decompiler will generate new names for them based on their location in the procedure. In the case of simple.opo which has no variables or complex flow control, the output is very close to the original:
$ ./bin/dumpopo.lua examples/Tests/simple.opo --decompile
PROC TEST:
PRINT "Hello world!"
WAT:
GET
ENDP
PROC WAT:
PRINT "Waaaat"
ENDP