Compare commits

...

77 Commits
master ... qt5

Author SHA1 Message Date
Godzil
b58f315c98 cleanup things, stop trying with CS 2018-09-19 17:59:25 +01:00
Godzil
7687c2b7d2 Trying to make parser to correctly handle CS 2018-09-18 18:50:13 +01:00
Artur K
0abbce6f4e
Merge pull request #32 from nemerle/add-license-1
Create LICENSE
2018-03-23 19:59:48 +01:00
Artur K
8ffdf657ec
Create LICENSE
Original code was using GPL.
2018-03-23 19:59:34 +01:00
nemerle
2232a76033 Disregard signed/unsigned difference in AstIdent::idID 2017-02-13 16:14:38 +01:00
nemerle
d6af9c1555 Add iInvalid enum value for invalid instructions
Various cleanups.
2017-02-13 13:24:54 +01:00
nemerle
d7acc8cd4d rename otherLongRegi to getPairedRegisterAt, make it a method of
LOCAL_ID struct.
2017-02-13 12:31:30 +01:00
nemerle
a5f1d17e83 Various code cleanups. 2017-02-13 12:11:29 +01:00
nemerle
29efcd5be1 Remove references to malloc.h closes #28 2017-02-07 12:09:58 +01:00
Artur K
4656db9484 Merge pull request #25 from gitter-badger/gitter-badge
Add a Gitter chat badge to Readme.md
2016-05-23 13:30:14 +02:00
The Gitter Badger
b33d7239e5 Add Gitter badge 2016-05-23 11:28:47 +00:00
Artur K
e1f0c084f8 Merge pull request #24 from lab313ru/patch-1
Fixed symbol name collision in parsehdr
2016-05-20 10:13:45 +02:00
Lab 313
e2a6b25345 Fixed collision with round math.h function 2016-05-20 11:01:00 +03:00
nemerle
f210ed78c2 Add the last of the original tools dispsig and srchsig
Closes #22
2016-05-19 20:15:37 +02:00
nemerle
ccc8cc526b Add readsig tool to build
As requested in #22
2016-05-19 20:03:49 +02:00
nemerle
cd6797499f Add parsehdr to the build
As requested in #22

(cherry picked from commit d5985b4b97cb06a89050c34674878c6430432fe1)
2016-05-19 19:52:48 +02:00
nemerle
b60903306f Fix memset-of-non-POD bug.
PROG contains vector, but was memset.
2016-05-19 16:17:08 +02:00
nemerle
1df7cb3be4 Fix msvc detection + prevent range library from pulling in boost::regex 2016-05-19 14:45:03 +02:00
nemerle
a7265f06b0 Fix msvc detection in cmake 2016-05-19 14:14:26 +02:00
nemerle
58532f4402 Removing LLVM dependency contd. 2016-05-19 12:40:59 +02:00
nemerle
7d986ef661 Removing LLVM dependencies WIP 2016-05-19 11:14:46 +02:00
nemerle
7f4197acc1 Use cmake features to mark c++11 as a required standard 2016-05-19 10:44:45 +02:00
nemerle
e71c8051c3 Rename icodeType entries
Following 2f80f16e6f76e3794ddc35ac9a6c1a86cb11cd28
2016-05-19 10:27:15 +02:00
nemerle
73cf949e25 Undefine PASCAL if it's defined as a macro
Following 0af07017b9c2f14435bd0fd103ae199cbf840bb0
2016-05-19 10:20:51 +02:00
nemerle
b2be1cf2da Simplify: SetupLibCheck does not depend on PROG or Project classes.
It also does not exit the program when ".sig" loader fails.

Use QString to build signature filename.
2016-04-26 13:42:41 +02:00
nemerle
94e3016a5b Fix SetCurFunc_by_Name implementation 2016-04-26 13:36:57 +02:00
nemerle
145a50369e Fix: Jump labels were printed incorrectly. 2016-04-26 13:35:20 +02:00
Vladimir Kryvian
d77927c608 Added new line for "removeRegFromLong not supproted" message in icode.h. 2016-04-26 10:06:00 +02:00
Vladimir Kryvian
3bb72987a6 Fixed double import with correct one in makedsig. 2016-04-26 10:05:10 +02:00
nemerle
c782892db4 Prevent the use of msvc's min/max macros 2016-04-26 09:26:28 +02:00
nemerle
a944ea5da8 Implement some of the methods in DccImpl 2016-04-26 09:23:34 +02:00
nemerle
d1738ea630 New feature: option to decompile only a specific function.
Similar to boomerang's -E option:

```
dcc -E 0x1222 ./TARGET.EXE
```

Will only decompile function at given address.
This might help in isolating dcc crashes.
2016-04-26 00:46:56 +02:00
nemerle
5f39236ba2 Fix LOCAL_ID::newLongIdx 2016-04-26 00:27:49 +02:00
nemerle
ede09ddae3 Record native function address as part of the name.
Might help while debugging dcc's handling of large programs.
2016-04-25 16:08:51 +02:00
nemerle
34b1f4f4fe Fix: long processing regression introduced in
bb007ddefc0465d36d394fbc4dbe811a633fc72e

Invalidated instructions should still be processed in findBBExps
2016-04-25 16:02:58 +02:00
nemerle
d6249916e1 More logic operator replacements.
Use Qt string classes.
2016-04-25 15:51:58 +02:00
nemerle
9cd3226536 Normalize logic operation keywords and add use msvc fix
Logical or should be only 'or','and','not', and not error prone
'||','&&','!'
2016-04-25 11:39:07 +02:00
nemerle
3f217e83da Add header that will contain msvc fixes 2016-04-25 10:08:25 +02:00
nemerle
652cfb67c3 Add simple gitattributes 2016-04-25 10:03:55 +02:00
nemerle
c0e9ba2fb3 Add addOutEdgesForConditionalJump to header 2016-04-25 10:03:30 +02:00
nemerle
5963f5fd4d Thanks to @lab313ru : fix bad iterator usage
Trying to increment past the end in graph.cpp

Also removed a goto by extracting a common function.
2016-04-24 12:22:15 +02:00
nemerle
12ee08f87e Implement two new switch idioms closes #14 2016-04-23 20:05:11 +02:00
nemerle
5c85c92d1a Replace tabs with spaces 2016-04-22 11:45:23 +02:00
nemerle
b509d0fcf0 Extend disassembly failure reporting a bit. 2016-04-22 10:47:14 +02:00
nemerle
bb007ddefc Stop processing invalidated instructions in dataflow 2016-04-22 10:36:29 +02:00
nemerle
9129d48429 Comment out a debugging printf 2016-04-22 10:35:41 +02:00
nemerle
d105182051 Add missing \n to error printf 2016-04-22 10:35:14 +02:00
nemerle
157a968372 Assume TYPE_STR is returned in exactly the same way as TYPE_PTR is 2016-04-22 10:34:36 +02:00
Artur K
bae2a582f1 Merge pull request #11 from lab313ru/lab313ru-patch-1
Lab313ru patch 1
2016-04-22 09:19:02 +02:00
Lab 313
19191876e2 Update libdis.h
Fixed negative address getting.
2016-04-22 02:37:22 +03:00
Lab 313
fcfe3c1f4b Update scanner.cpp
Fixed negative address calculating.
2016-04-22 02:35:40 +03:00
nemerle
97f093feaa This build requires LLVM, does not need ncurses - modify CMakeLists.txt to match 2016-02-13 15:14:14 +01:00
Artur K.
3561de6e12 Merge pull request #5 from Arthur2e5/patch-1
README: Recognizing code segments
2015-10-20 06:18:10 +00:00
Mingye Wang
e84d09b97c README: Recognizing code segments 2015-10-20 01:15:59 -04:00
Artur K.
d8a4fe1c04 Merge pull request #4 from Arthur2e5/patch-1
README: tweak formatting by a bit
2015-10-20 05:15:49 +00:00
Mingye Wang
e4e6ad6415 README: tweak formatting by a bit
Trying to get a nice balance between Markdown rendering and plain text readability. And I think I got it.
2015-10-20 01:11:34 -04:00
nemerle
2543617930 Remove llvm as a build requirement 2015-08-13 20:46:54 +02:00
nemerle
bc5784a8f2 Fix #1 - just use QFileInfo. 2015-05-28 15:13:43 +02:00
Artur K
842687726f Update the dcc tools code 2015-04-28 14:59:00 +02:00
nemerle
c5c9196561 Fix for functional tests when running on clean checkout 2015-02-10 17:31:57 +01:00
nemerle
a697ad05c0 Add original dcc tools to repository
* makedsig has been integrated with makedstp, it should handle both LIB and TPL files
* other tools have not been modified
2015-02-10 17:28:50 +01:00
Artur K.
d8c66e7791 Update Readme.md 2014-06-05 15:01:12 +02:00
nemerle
337a6c44aa Added original readme 2014-05-25 12:36:39 +02:00
nemerle
cde4484821 Remove unused local 2014-05-25 12:33:18 +02:00
nemerle
36b063c183 Working towards gui integration with exetoc_qt 2014-05-24 17:08:05 +02:00
nemerle
3603877f42 Qt5 command options processing 2014-03-07 20:01:36 +01:00
nemerle
50950028e0 Pre-qt5 2014-03-07 19:42:27 +01:00
nemerle
1c5e1c2fce replace boolT with plain old bool in a few places 2014-02-28 11:26:02 +01:00
nemerle
5c7799b778 Const fixes and name updates for libdis.h 2014-02-28 11:24:09 +01:00
Artur K
0209b7ceb2 Changes 2012-07-20 18:18:25 +02:00
Artur K
f6118dc0c4 Fixes to libdisasm, also use it a bit more 2012-07-19 19:50:34 +02:00
Artur K
d5e1fc733f Fixes to libdisasm, also use it a bit more 2012-07-19 19:37:30 +02:00
Artur K
c1eb8df114 Split COND_EXPR into Unary/Binary/AstIdent subclasses 2012-07-16 19:31:29 +02:00
Artur K
ca129c5177 Fix to idiom19 and fixFloatEmulation() 2012-07-15 20:17:16 +02:00
Artur K
c19231a1bd extracted FunctionCfg as it's own class 2012-07-15 16:52:59 +02:00
Artur K
5087a051b5 More simplifications on BB creation 2012-07-14 23:04:09 +02:00
Artur K
ba110a64cb removed most of clang warnings / errors 2012-03-29 22:02:25 +02:00
140 changed files with 22213 additions and 8322 deletions

6
.gitattributes vendored Normal file
View File

@ -0,0 +1,6 @@
* text=auto
*.c text
*.cpp text
*.ui text
*.qrc text
*.h text

4
.gitignore vendored
View File

@ -4,4 +4,6 @@ tests/prev
tests/outputs/*
tests/errors
*.autosave
bld*
bld*
*.user
*.idb

68
3rd_party/libdisasm/INTEL_BUGS vendored Normal file
View File

@ -0,0 +1,68 @@
PMOVMSKB
Gd, Pq1H
PMOVMSKB
(66)
Gd, Vdq1H
should be
PMOVMSKB
Gd, Qq1H
PMOVMSKB
(66)
Gd, Wdq1H
The instruction represented by this opcode expression does not support any
operand to be a memory location.
MASKMOVQ
Pq, Pq1H
MASKMOVDQU
(66)
Vdq, Vdq1H
should be
MASKMOVQ
Pq, Pq1H
MASKMOVDQU
(66)
Vdq, Wdq1H
MOVMSKPS
Gd, Vps1H
MOVMSKPD
(66)
Gd, Vpd1H
should be
MOVMSKPS
Gd, Wps1H
MOVMSKPD
(66)
Gd, Wpd1H
The opcode table entries for LFS, LGS, and LSS
L[FGS]S
Mp
should be
L[FGS]S
Gv,Mp
MOVHLPS
Vps, Vps
MOVLHPS
Vps, Vps
should be
MOVHLPS
Vps, Wps
MOVLHPS
Vps, Wps

137
3rd_party/libdisasm/LICENSE vendored Normal file
View File

@ -0,0 +1,137 @@
The "Clarified Artistic License"
Preamble
The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to make
reasonable modifications.
Definitions:
"Package" refers to the collection of files distributed by the
Copyright Holder, and derivatives of that collection of files
created through textual modification.
"Standard Version" refers to such a Package if it has not been
modified, or has been modified in accordance with the wishes
of the Copyright Holder as specified below.
"Copyright Holder" is whoever is named in the copyright or
copyrights for the package.
"You" is you, if you're thinking about copying or distributing
this Package.
"Distribution fee" is a fee you charge for providing a copy of this
Package to another party.
"Freely Available" means that no fee is charged for the right to use
the item, though there may be fees involved in handling the item.
1. You may make and give away verbatim copies of the source form of the
Standard Version of this Package without restriction, provided that you
duplicate all of the original copyright notices and associated disclaimers.
2. You may apply bug fixes, portability fixes and other modifications
derived from the Public Domain, or those made Freely Available, or from
the Copyright Holder. A Package modified in such a way shall still be
considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way, provided
that you insert a prominent notice in each changed file stating how and
when you changed that file, and provided that you do at least ONE of the
following:
a) place your modifications in the Public Domain or otherwise make them
Freely Available, such as by posting said modifications to Usenet or
an equivalent medium, or placing the modifications on a major archive
site allowing unrestricted access to them, or by allowing the Copyright
Holder to include your modifications in the Standard Version of the
Package.
b) use the modified Package only within your corporation or organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided, and provide
a separate manual page for each non-standard executable that clearly
documents how it differs from the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
e) permit and encourge anyone who receives a copy of the modified Package
permission to make your modifications Freely Available in some specific
way.
4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:
a) distribute a Standard Version of the executables and library files,
together with instructions (in the manual page or equivalent) on where
to get the Standard Version.
b) accompany the distribution with the machine-readable source of
the Package with your modifications.
c) give non-standard executables non-standard names, and clearly
document the differences in manual pages (or equivalent), together
with instructions on where to get the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
e) offer the machine-readable source of the Package, with your
modifications, by mail order.
5. You may charge a distribution fee for any distribution of this Package.
If you offer support for this Package, you may charge any fee you choose
for that support. You may not charge a license fee for the right to use
this Package itself. You may distribute this Package in aggregate with
other (possibly commercial and possibly nonfree) programs as part of a
larger (possibly commercial and possibly nonfree) software distribution,
and charge license fees for other parts of that software distribution,
provided that you do not advertise this Package as a product of your own.
If the Package includes an interpreter, You may embed this Package's
interpreter within an executable of yours (by linking); this shall be
construed as a mere form of aggregation, provided that the complete
Standard Version of the interpreter is so embedded.
6. The scripts and library files supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whoever generated
them, and may be sold commercially, and may be aggregated with this
Package. If such scripts or library files are aggregated with this
Package via the so-called "undump" or "unexec" methods of producing a
binary executable image, then distribution of such an image shall
neither be construed as a distribution of this Package nor shall it
fall under the restrictions of Paragraphs 3 and 4, provided that you do
not represent such an executable image as a Standard Version of this
Package.
7. C subroutines (or comparably compiled subroutines in other
languages) supplied by you and linked into this Package in order to
emulate subroutines and variables of the language defined by this
Package shall not be considered part of this Package, but are the
equivalent of input as in Paragraph 6, provided these subroutines do
not change the language in any way that would cause it to fail the
regression tests for the language.
8. Aggregation of the Standard Version of the Package with a commercial
distribution is always permitted provided that the use of this Package is
embedded; that is, when no overt attempt is made to make this Package's
interfaces visible to the end user of the commercial distribution.
Such use shall not be construed as a distribution of this Package.
9. The name of the Copyright Holder may not be used to endorse or promote
products derived from this software without specific prior written permission.
10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
The End

12
3rd_party/libdisasm/NAMESPACE.TXT vendored Normal file
View File

@ -0,0 +1,12 @@
The rewritten libdisasm code uses the following namespaces:
Prefix Namespace
----------------------------------------------------
x86_ Global 'libdisasm' namespace
ia32_ Internal IA32 ISA namespace
ia64_ Internal IA64 ISA namespace
ix64_ Internal X86-64 ISA namespace
Note that the 64-bit ISAs are not yet supported/written.

2
3rd_party/libdisasm/README vendored Normal file
View File

@ -0,0 +1,2 @@
This is a cut-up version of libdisasm originally from the bastard project http://bastard.sourceforge.net/

43
3rd_party/libdisasm/TODO vendored Normal file
View File

@ -0,0 +1,43 @@
x86_format.c
------------
intel: jmpf -> jmp, callf -> call
att: jmpf -> ljmp, callf -> lcall
opcode table
------------
finish typing instructions
fix flag clear/set/toggle types
ix64 stuff
----------
document output file formats in web page
features doc: register aliases, implicit operands, stack mods,
ring0 flags, eflags, cpu model/isa
ia32_handle_* implementation
fix operand 0F C2
CMPPS
* sysenter, sysexit as CALL types -- preceded by MSR writes
* SYSENTER/SYSEXIT stack : overwrites SS, ESP
* stos, cmps, scas, movs, ins, outs, lods -> OP_PTR
* OP_SIZE in implicit operands
* use OP_SIZE to choose reg sizes!
DONE?? :
implicit operands: provide action ?
e.g. add/inc for stach, write, etc
replace table numbers in opcodes.dat with
#defines for table names
replace 0 with INSN_INVALID [or maybe FF for imnvalid and 00 for Not Applicable */
no wait that is only for prefix tables -- n/p
if ( prefx) only use if insn != invalid
these should cover all the wacky disasm exceptions
for the rep one we can chet, match only a 0x90
todo: privilege | ring

36
3rd_party/libdisasm/ia32_fixup.cpp vendored Normal file
View File

@ -0,0 +1,36 @@
#include <stdio.h>
static const char * mem_fixup[256] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 00 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 08 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 10 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 18 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 20 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 28 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 30 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 38 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 40 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 48 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 50 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 58 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 60 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 68 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 70 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 78 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 80 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 88 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 90 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 98 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* A0 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* A8 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* B0 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* B8 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* C0 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* C8 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* D0 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* D8 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* E0 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* E8 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* F0 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* F8 */
};

View File

@ -20,81 +20,81 @@ typedef struct {
static op_implicit_list_t list_aaa[] =
/* 37 : AAA : rw AL */
/* 3F : AAS : rw AL */
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* aaa */
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* aaa */
static op_implicit_list_t list_aad[] =
/* D5 0A, D5 (ib) : AAD : rw AX */
/* D4 0A, D4 (ib) : AAM : rw AX */
{{ OP_R | OP_W, REG_WORD_OFFSET }, {0}}; /* aad */
{{ OP_R | OP_W, REG_WORD_OFFSET }, {0,0}}; /* aad */
static op_implicit_list_t list_call[] =
/* E8, FF, 9A, FF : CALL : rw ESP, rw EIP */
/* C2, C3, CA, CB : RET : rw ESP, rw EIP */
{{ OP_R | OP_W, REG_EIP_INDEX },
{ OP_R | OP_W, REG_ESP_INDEX }, {0}}; /* call, ret */
{ OP_R | OP_W, REG_ESP_INDEX }, {0,0}}; /* call, ret */
static op_implicit_list_t list_cbw[] =
/* 98 : CBW : r AL, rw AX */
{{ OP_R | OP_W, REG_WORD_OFFSET },
{ OP_R, REG_BYTE_OFFSET}, {0}}; /* cbw */
{ OP_R, REG_BYTE_OFFSET}, {0,0}}; /* cbw */
static op_implicit_list_t list_cwde[] =
/* 98 : CWDE : r AX, rw EAX */
{{ OP_R | OP_W, REG_DWORD_OFFSET },
{ OP_R, REG_WORD_OFFSET }, {0}}; /* cwde */
{ OP_R, REG_WORD_OFFSET }, {0,0}}; /* cwde */
static op_implicit_list_t list_clts[] =
/* 0F 06 : CLTS : rw CR0 */
{{ OP_R | OP_W, REG_CTRL_OFFSET}, {0}}; /* clts */
{{ OP_R | OP_W, REG_CTRL_OFFSET}, {0,0}}; /* clts */
static op_implicit_list_t list_cmpxchg[] =
/* 0F B0 : CMPXCHG : rw AL */
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* cmpxchg */
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* cmpxchg */
static op_implicit_list_t list_cmpxchgb[] =
/* 0F B1 : CMPXCHG : rw EAX */
{{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* cmpxchg */
{{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* cmpxchg */
static op_implicit_list_t list_cmpxchg8b[] =
/* 0F C7 : CMPXCHG8B : rw EDX, rw EAX, r ECX, r EBX */
{{ OP_R | OP_W, REG_DWORD_OFFSET },
{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
{ OP_R, REG_DWORD_OFFSET + 1 },
{ OP_R, REG_DWORD_OFFSET + 3 }, {0}}; /* cmpxchg8b */
{ OP_R, REG_DWORD_OFFSET + 3 }, {0,0}}; /* cmpxchg8b */
static op_implicit_list_t list_cpuid[] =
/* 0F A2 : CPUID : rw EAX, w EBX, w ECX, w EDX */
{{ OP_R | OP_W, REG_DWORD_OFFSET },
{ OP_W, REG_DWORD_OFFSET + 1 },
{ OP_W, REG_DWORD_OFFSET + 2 },
{ OP_W, REG_DWORD_OFFSET + 3 }, {0}}; /* cpuid */
{ OP_W, REG_DWORD_OFFSET + 3 }, {0,0}}; /* cpuid */
static op_implicit_list_t list_cwd[] =
/* 99 : CWD/CWQ : rw EAX, w EDX */
{{ OP_R | OP_W, REG_DWORD_OFFSET },
{ OP_W, REG_DWORD_OFFSET + 2 }, {0}}; /* cwd */
{ OP_W, REG_DWORD_OFFSET + 2 }, {0,0}}; /* cwd */
static op_implicit_list_t list_daa[] =
/* 27 : DAA : rw AL */
/* 2F : DAS : rw AL */
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* daa */
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* daa */
static op_implicit_list_t list_idiv[] =
/* F6 : DIV, IDIV : r AX, w AL, w AH */
/* FIXED: first op was EAX, not Aw. TODO: verify! */
{{ OP_R, REG_WORD_OFFSET },
{ OP_W, REG_BYTE_OFFSET },
{ OP_W, REG_BYTE_OFFSET + 4 }, {0}}; /* div */
{ OP_W, REG_BYTE_OFFSET + 4 }, {0,0}}; /* div */
static op_implicit_list_t list_div[] =
/* F7 : DIV, IDIV : rw EDX, rw EAX */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* div */
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* div */
static op_implicit_list_t list_enter[] =
/* C8 : ENTER : rw ESP w EBP */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 4 },
{ OP_R, REG_DWORD_OFFSET + 5 }, {0}}; /* enter */
{ OP_R, REG_DWORD_OFFSET + 5 }, {0,0}}; /* enter */
static op_implicit_list_t list_f2xm1[] =
/* D9 F0 : F2XM1 : rw ST(0) */
@ -109,7 +109,7 @@ static op_implicit_list_t list_f2xm1[] =
/* D9 FE : FSIN : rw ST(0) */
/* D9 FA : FSQRT : rw ST(0) */
/* D9 F4 : FXTRACT : rw ST(0) */
{{ OP_R | OP_W, REG_FPU_OFFSET }, {0}}; /* f2xm1 */
{{ OP_R | OP_W, REG_FPU_OFFSET }, {0,0}}; /* f2xm1 */
static op_implicit_list_t list_fcom[] =
/* D8, DC, DE D9 : FCOM : r ST(0) */
@ -117,17 +117,17 @@ static op_implicit_list_t list_fcom[] =
/* DF, D8 : FIST : r ST(0) */
/* D9 E4 : FTST : r ST(0) */
/* D9 E5 : FXAM : r ST(0) */
{{ OP_R, REG_FPU_OFFSET }, {0}}; /* fcom */
{{ OP_R, REG_FPU_OFFSET }, {0,0}}; /* fcom */
static op_implicit_list_t list_fpatan[] =
/* D9 F3 : FPATAN : r ST(0), rw ST(1) */
{{ OP_R, REG_FPU_OFFSET }, {0}}; /* fpatan */
{{ OP_R, REG_FPU_OFFSET }, {0,0}}; /* fpatan */
static op_implicit_list_t list_fprem[] =
/* D9 F8, D9 F5 : FPREM : rw ST(0) r ST(1) */
/* D9 FD : FSCALE : rw ST(0), r ST(1) */
{{ OP_R | OP_W, REG_FPU_OFFSET },
{ OP_R, REG_FPU_OFFSET + 1 }, {0}}; /* fprem */
{ OP_R, REG_FPU_OFFSET + 1 }, {0,0}}; /* fprem */
static op_implicit_list_t list_faddp[] =
/* DE C1 : FADDP : r ST(0), rw ST(1) */
@ -135,67 +135,67 @@ static op_implicit_list_t list_faddp[] =
/* D9 F1 : FYL2X : r ST(0), rw ST(1) */
/* D9 F9 : FYL2XP1 : r ST(0), rw ST(1) */
{{ OP_R, REG_FPU_OFFSET },
{ OP_R | OP_W, REG_FPU_OFFSET + 1 }, {0}}; /* faddp */
{ OP_R | OP_W, REG_FPU_OFFSET + 1 }, {0,0}}; /* faddp */
static op_implicit_list_t list_fucompp[] =
/* DA E9 : FUCOMPP : r ST(0), r ST(1) */
{{ OP_R, REG_FPU_OFFSET },
{ OP_R, REG_FPU_OFFSET + 1 }, {0}}; /* fucompp */
{ OP_R, REG_FPU_OFFSET + 1 }, {0,0}}; /* fucompp */
static op_implicit_list_t list_imul[] =
/* F6 : IMUL : r AL, w AX */
/* F6 : MUL : r AL, w AX */
{{ OP_R, REG_BYTE_OFFSET },
{ OP_W, REG_WORD_OFFSET }, {0}}; /* imul */
{ OP_W, REG_WORD_OFFSET }, {0,0}}; /* imul */
static op_implicit_list_t list_mul[] =
/* F7 : IMUL : rw EAX, w EDX */
/* F7 : MUL : rw EAX, w EDX */
{{ OP_R | OP_W, REG_DWORD_OFFSET },
{ OP_W, REG_DWORD_OFFSET + 2 }, {0}}; /* imul */
{ OP_W, REG_DWORD_OFFSET + 2 }, {0,0}}; /* imul */
static op_implicit_list_t list_lahf[] =
/* 9F : LAHF : r EFLAGS, w AH */
{{ OP_R, REG_FLAGS_INDEX },
{ OP_W, REG_BYTE_OFFSET + 4 }, {0}}; /* lahf */
{ OP_W, REG_BYTE_OFFSET + 4 }, {0,0}}; /* lahf */
static op_implicit_list_t list_ldmxcsr[] =
/* 0F AE : LDMXCSR : w MXCSR SSE Control Status Reg */
{{ OP_W, REG_MXCSG_INDEX }, {0}}; /* ldmxcsr */
{{ OP_W, REG_MXCSG_INDEX }, {0,0}}; /* ldmxcsr */
static op_implicit_list_t list_leave[] =
/* C9 : LEAVE : rw ESP, w EBP */
{{ OP_R | OP_W, REG_ESP_INDEX },
{ OP_W, REG_DWORD_OFFSET + 5 }, {0}}; /* leave */
{ OP_W, REG_DWORD_OFFSET + 5 }, {0,0}}; /* leave */
static op_implicit_list_t list_lgdt[] =
/* 0F 01 : LGDT : w GDTR */
{{ OP_W, REG_GDTR_INDEX }, {0}}; /* lgdt */
{{ OP_W, REG_GDTR_INDEX }, {0,0}}; /* lgdt */
static op_implicit_list_t list_lidt[] =
/* 0F 01 : LIDT : w IDTR */
{{ OP_W, REG_IDTR_INDEX }, {0}}; /* lidt */
{{ OP_W, REG_IDTR_INDEX }, {0,0}}; /* lidt */
static op_implicit_list_t list_lldt[] =
/* 0F 00 : LLDT : w LDTR */
{{ OP_W, REG_LDTR_INDEX }, {0}}; /* lldt */
{{ OP_W, REG_LDTR_INDEX }, {0,0}}; /* lldt */
static op_implicit_list_t list_lmsw[] =
/* 0F 01 : LMSW : w CR0 */
{{ OP_W, REG_CTRL_OFFSET }, {0}}; /* lmsw */
{{ OP_W, REG_CTRL_OFFSET }, {0,0}}; /* lmsw */
static op_implicit_list_t list_loop[] =
/* E0, E1, E2 : LOOP : rw ECX */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* loop */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0,0}};/* loop */
static op_implicit_list_t list_ltr[] =
/* 0F 00 : LTR : w Task Register */
{{ OP_W, REG_TR_INDEX }, {0}}; /* ltr */
{{ OP_W, REG_TR_INDEX }, {0,0}}; /* ltr */
static op_implicit_list_t list_pop[] =
/* 8F, 58, 1F, 07, 17, 0F A1, 0F A9 : POP : rw ESP */
/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
{{ OP_R | OP_W, REG_ESP_INDEX }, {0}}; /* pop, push */
{{ OP_R | OP_W, REG_ESP_INDEX }, {0,0}}; /* pop, push */
static op_implicit_list_t list_popad[] =
/* 61 : POPAD : rw esp, w edi esi ebp ebx edx ecx eax */
@ -206,12 +206,12 @@ static op_implicit_list_t list_popad[] =
{ OP_W, REG_DWORD_OFFSET + 3 },
{ OP_W, REG_DWORD_OFFSET + 2 },
{ OP_W, REG_DWORD_OFFSET + 1 },
{ OP_W, REG_DWORD_OFFSET }, {0}}; /* popad */
{ OP_W, REG_DWORD_OFFSET }, {0,0}}; /* popad */
static op_implicit_list_t list_popfd[] =
/* 9D : POPFD : rw esp, w eflags */
{{ OP_R | OP_W, REG_ESP_INDEX },
{ OP_W, REG_FLAGS_INDEX }, {0}}; /* popfd */
{ OP_W, REG_FLAGS_INDEX }, {0,0}}; /* popfd */
static op_implicit_list_t list_pushad[] =
/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
@ -223,102 +223,102 @@ static op_implicit_list_t list_pushad[] =
{ OP_R, REG_DWORD_OFFSET + 3 },
{ OP_R, REG_DWORD_OFFSET + 5 },
{ OP_R, REG_DWORD_OFFSET + 6 },
{ OP_R, REG_DWORD_OFFSET + 7 }, {0}}; /* pushad */
{ OP_R, REG_DWORD_OFFSET + 7 }, {0,0}}; /* pushad */
static op_implicit_list_t list_pushfd[] =
/* 9C : PUSHFD : rw esp, r eflags */
{{ OP_R | OP_W, REG_ESP_INDEX },
{ OP_R, REG_FLAGS_INDEX }, {0}}; /* pushfd */
{ OP_R, REG_FLAGS_INDEX }, {0,0}}; /* pushfd */
static op_implicit_list_t list_rdmsr[] =
/* 0F 32 : RDMSR : r ECX, w EDX, w EAX */
{{ OP_R, REG_DWORD_OFFSET + 1 },
{ OP_W, REG_DWORD_OFFSET + 2 },
{ OP_W, REG_DWORD_OFFSET }, {0}}; /* rdmsr */
{ OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdmsr */
static op_implicit_list_t list_rdpmc[] =
/* 0F 33 : RDPMC : r ECX, w EDX, w EAX */
{{ OP_R, REG_DWORD_OFFSET + 1 },
{ OP_W, REG_DWORD_OFFSET + 2 },
{ OP_W, REG_DWORD_OFFSET }, {0}}; /* rdpmc */
{ OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdpmc */
static op_implicit_list_t list_rdtsc[] =
/* 0F 31 : RDTSC : rw EDX, rw EAX */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* rdtsc */
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdtsc */
static op_implicit_list_t list_rep[] =
/* F3, F2 ... : REP : rw ECX */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* rep */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0,0}};/* rep */
static op_implicit_list_t list_rsm[] =
/* 0F AA : RSM : r CR4, r CR0 */
{{ OP_R, REG_CTRL_OFFSET + 4 },
{ OP_R, REG_CTRL_OFFSET }, {0}}; /* rsm */
{ OP_R, REG_CTRL_OFFSET }, {0,0}}; /* rsm */
static op_implicit_list_t list_sahf[] =
/* 9E : SAHF : r ah, rw eflags (set SF ZF AF PF CF) */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sahf */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sahf */
static op_implicit_list_t list_sgdt[] =
/* 0F : SGDT : r gdtr */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sgdt */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sgdt */
static op_implicit_list_t list_sidt[] =
/* 0F : SIDT : r idtr */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sidt */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sidt */
static op_implicit_list_t list_sldt[] =
/* 0F : SLDT : r ldtr */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sldt */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sldt */
static op_implicit_list_t list_smsw[] =
/* 0F : SMSW : r CR0 */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* smsw */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* smsw */
static op_implicit_list_t list_stmxcsr[] =
/* 0F AE : STMXCSR : r MXCSR */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* stmxcsr */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* stmxcsr */
static op_implicit_list_t list_str[] =
/* 0F 00 : STR : r TR (task register) */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* str */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* str */
static op_implicit_list_t list_sysenter[] =
/* 0F 34 : SYSENTER : w cs, w eip, w ss, w esp, r CR0, w eflags
* r sysenter_cs_msr, sysenter_esp_msr, sysenter_eip_msr */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sysenter */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sysenter */
static op_implicit_list_t list_sysexit[] =
/* 0F 35 : SYSEXIT : r edx, r ecx, w cs, w eip, w ss, w esp
* r sysenter_cs_msr */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sysexit */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sysexit */
static op_implicit_list_t list_wrmsr[] =
/* 0F 30 : WRMST : r edx, r eax, r ecx */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* wrmsr */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* wrmsr */
static op_implicit_list_t list_xlat[] =
/* D7 : XLAT : rw al r ebx (ptr) */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* xlat */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* xlat */
/* TODO:
* monitor 0f 01 c8 eax OP_R ecx OP_R edx OP_R
* mwait 0f 01 c9 eax OP_R ecx OP_R
*/
static op_implicit_list_t list_monitor[] =
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* monitor */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* monitor */
static op_implicit_list_t list_mwait[] =
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* mwait */
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* mwait */
op_implicit_list_t *op_implicit_list[] = {
/* This is a list of implicit operands which are read/written by
@ -407,7 +407,21 @@ unsigned int Ia32_Decoder::ia32_insn_implicit_ops( unsigned int impl_idx ) {
if (!op) {
op = m_decoded->x86_operand_new();
/* all implicit operands are registers */
handle_impl_reg( op, list->operand );
if(m_decoded->addr_size==2)
{
if(list->operand==REG_EIP_INDEX)
handle_impl_reg( op, REG_IP_INDEX );
else if(list->operand<REG_WORD_OFFSET)
{
handle_impl_reg( op, (list->operand-REG_DWORD_OFFSET)+REG_WORD_OFFSET);
assert((list->operand-REG_DWORD_OFFSET)<REG_WORD_OFFSET-REG_DWORD_OFFSET);
}
else
handle_impl_reg( op, list->operand);
}
else
handle_impl_reg( op, list->operand );
/* decrement the 'explicit count' incremented by default in
* x86_operand_new */
m_decoded->explicit_count = m_decoded->explicit_count -1;

View File

@ -240,7 +240,7 @@ void Ia32_Decoder::ia32_handle_prefix( unsigned int prefixes ) {
}
static void reg_32_to_16( x86_op_t *op, x86_insn_t *insn, void *arg ) {
static void reg_32_to_16( x86_op_t *op, x86_insn_t */*insn*/, void */*arg*/ ) {
/* if this is a 32-bit register and it is a general register ... */
if ( op->type == op_register && op->data.reg.size == 4 &&
@ -539,12 +539,11 @@ size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
size_t Ia32_Decoder::handle_insn_suffix( unsigned char *buf, size_t buf_len,
ia32_insn_t *raw_insn ) {
ia32_table_desc_t *table_desc;
// ia32_table_desc_t *table_desc;
ia32_insn_t *sfx_insn;
size_t size;
unsigned int prefixes = 0;
table_desc = &ia32_tables[raw_insn->table];
//table_desc = &ia32_tables[raw_insn->table];
size = ia32_table_lookup( buf, buf_len, raw_insn->table, &sfx_insn,
&prefixes );
if (size == INVALID_INSN || sfx_insn->mnem_flag == INS_INVALID ) {

View File

@ -137,7 +137,7 @@ static int ia32_invariant_modrm( unsigned char *in, unsigned char *out,
}
static int ia32_decode_invariant( unsigned char *buf, size_t buf_len,
static int ia32_decode_invariant( unsigned char *buf, size_t /*buf_len*/,
ia32_insn_t *t, unsigned char *out,
unsigned int prefixes, x86_invariant_t *inv) {
@ -251,13 +251,13 @@ static int ia32_decode_invariant( unsigned char *buf, size_t buf_len,
case ADDRMETH_X:
inv->operands[x].flags.op_signed=true;
inv->operands[x].flags.op_pointer=true;
inv->operands[x].flags.op_seg=x86_op_flags::op_ds_seg;
inv->operands[x].flags.op_seg=(x86_op_flags::op_ds_seg)>>8;
inv->operands[x].flags.op_string=true;
break;
case ADDRMETH_Y:
inv->operands[x].flags.op_signed=true;
inv->operands[x].flags.op_pointer=true;
inv->operands[x].flags.op_seg=x86_op_flags::op_es_seg;
inv->operands[x].flags.op_seg=x86_op_flags::op_es_seg>>8;
inv->operands[x].flags.op_string=true;
break;
case ADDRMETH_RR:
@ -307,6 +307,7 @@ size_t ia32_disasm_invariant( unsigned char * buf, size_t buf_len,
}
size_t ia32_disasm_size( unsigned char *buf, size_t buf_len ) {
x86_invariant_t inv = { {0} };
x86_invariant_t inv;
memset(&inv,0,sizeof(x86_invariant_t));
return( ia32_disasm_invariant( buf, buf_len, &inv ) );
}

View File

@ -155,12 +155,12 @@ static size_t modrm_decode16( unsigned char *buf, unsigned int buf_len,
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 3);
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 7);
case MOD16_RM_BPSI:
op->flags.op_seg = x86_op_flags::op_ss_seg;
op->flags.op_seg = x86_op_flags::op_ss_seg>>8;
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 5);
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 6);
break;
case MOD16_RM_BPDI:
op->flags.op_seg = x86_op_flags::op_ss_seg;
op->flags.op_seg = x86_op_flags::op_ss_seg>>8;
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 5);
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 7);
break;
@ -172,7 +172,7 @@ static size_t modrm_decode16( unsigned char *buf, unsigned int buf_len,
break;
case MOD16_RM_BP:
if ( modrm->mod != MOD16_MOD_NODISP ) {
op->flags.op_seg = x86_op_flags::op_ss_seg;
op->flags.op_seg = x86_op_flags::op_ss_seg>>8;
ia32_handle_register(&ea->base,
REG_WORD_OFFSET + 5);
}

3206
3rd_party/libdisasm/ia32_opcode.dat vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -20,17 +20,17 @@ static void apply_seg( x86_op_t *op, unsigned int prefixes ) {
switch ( prefixes & PREFIX_REG_MASK ) {
/* NOTE: that op->flags for segment override are not a bitfield */
case PREFIX_CS:
op->flags.op_seg = x86_op_flags::op_cs_seg; break;
op->flags.op_seg = x86_op_flags::op_cs_seg>>8; break;
case PREFIX_SS:
op->flags.op_seg = x86_op_flags::op_ss_seg; break;
op->flags.op_seg = x86_op_flags::op_ss_seg>>8; break;
case PREFIX_DS:
op->flags.op_seg = x86_op_flags::op_ds_seg; break;
op->flags.op_seg = x86_op_flags::op_ds_seg>>8; break;
case PREFIX_ES:
op->flags.op_seg = x86_op_flags::op_es_seg; break;
op->flags.op_seg = x86_op_flags::op_es_seg>>8; break;
case PREFIX_FS:
op->flags.op_seg = x86_op_flags::op_fs_seg; break;
op->flags.op_seg = x86_op_flags::op_fs_seg>>8; break;
case PREFIX_GS:
op->flags.op_seg = x86_op_flags::op_gs_seg; break;
op->flags.op_seg = x86_op_flags::op_gs_seg>>8; break;
}
return;
@ -107,19 +107,17 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
/* No MODRM : note these set operand type explicitly */
case ADDRMETH_A: /* No modR/M -- direct addr */
op->type = op_absolute;
//according to Intel Manuals, offset goes first
/* segment:offset address used in far calls */
x86_imm_sized( buf, buf_len,
&op->data.absolute.segment, 2 );
if ( m_decoded->addr_size == 4 ) {
x86_imm_sized( buf, buf_len,
&op->data.absolute.offset.off32, 4 );
size = 6;
} else {
x86_imm_sized( buf, buf_len,
&op->data.absolute.offset.off16, 2 );
x86_imm_sized( buf, buf_len, &op->data.absolute.offset.off32, 4 );
size = 4;
} else {
x86_imm_sized( buf, buf_len, &op->data.absolute.offset.off16, 2 );
size = 2;
}
x86_imm_sized( buf+size, buf_len-size, &op->data.absolute.segment, 2 );
size+=2;
break;
case ADDRMETH_I: /* Immediate val */
@ -136,21 +134,28 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
size = op_size;
break;
case ADDRMETH_J: /* Rel offset to add to IP [jmp] */
/* this fills op->data.near_offset or
/* this fills op->data.near_offset or
op->data.far_offset depending on the size of
the operand */
op->flags.op_signed = true;
if ( op_size == 1 ) {
/* one-byte near offset */
op->type = op_relative_near;
x86_imm_signsized(buf, buf_len, &op->data.relative_near, 1);
} else {
/* far offset...is this truly signed? */
op->type = op_relative_far;
x86_imm_signsized(buf, buf_len,
&op->data.relative_far, op_size );
switch(op_size)
{
case 1:
/* one-byte near offset */
op->type = op_relative_near;
size = x86_imm_signsized(buf, buf_len, &op->data.relative_near, 1);
break;
case 2:
/* far offset...is this truly signed? */
op->type = op_relative_far;
int16_t offset_val; // easier upcast to int32_t
size = x86_imm_signsized(buf, buf_len, &offset_val, 2 );
op->data.relative_far=offset_val;
break;
default:
assert(false);
size=0;
}
size = op_size;
break;
case ADDRMETH_O: /* No ModR/M; op is word/dword offset */
/* NOTE: these are actually RVAs not offsets to seg!! */
@ -172,20 +177,20 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
case ADDRMETH_X: /* Memory addressed by DS:SI [string] */
op->type = op_expression;
op->flags.op_hardcode = true;
op->flags.op_seg = x86_op_flags::op_ds_seg;
op->flags.op_seg = x86_op_flags::op_ds_seg>>8;
op->flags.op_pointer = true;
op->flags.op_string = true;
ia32_handle_register( &op->data.expression.base,
REG_DWORD_OFFSET + 6 );
gen_regs + 6 );
break;
case ADDRMETH_Y: /* Memory addressed by ES:DI [string] */
op->type = op_expression;
op->flags.op_hardcode = true;
op->flags.op_seg = x86_op_flags::op_es_seg;
op->flags.op_seg = x86_op_flags::op_es_seg>>8;
op->flags.op_pointer = true;
op->flags.op_string = true;
ia32_handle_register( &op->data.expression.base,
REG_DWORD_OFFSET + 7 );
gen_regs + 7 );
break;
case ADDRMETH_RR: /* Gen Register hard-coded in opcode */
op->type = op_register;
@ -255,10 +260,10 @@ size_t Ia32_Decoder::decode_operand_size( unsigned int op_type, x86_op_t *op ) {
break;
case OPTYPE_p: /* 32/48-bit ptr [op size attr] */
/* technically these flags are not accurate: the
* value s a 16:16 pointer or a 16:32 pointer, where
* the first '16' is a segment */
* value s a 16:16 pointer or a 16:32 pointer, where
* the first '16' is a segment */
size = (m_decoded->addr_size == 4) ? 6 : 4;
op->datatype = (size == 4) ? op_descr32 : op_descr16;
op->datatype = (size == 6) ? op_descr32 : op_descr16;
break;
case OPTYPE_b: /* byte, ignore op-size */
size = 1;

View File

@ -31,45 +31,45 @@
* of the MMX registers, so this aliasing is not 100% accurate.
* */
static struct {
unsigned char alias; /* id of register this is an alias for */
unsigned char shift; /* # of bits register must be shifted */
unsigned char alias; /* id of register this is an alias for */
unsigned char shift; /* # of bits register must be shifted */
} ia32_reg_aliases[] = {
{ 0,0 },
{ REG_DWORD_OFFSET, 0 }, /* al : 1 */
{ REG_DWORD_OFFSET, 8 }, /* ah : 2 */
{ REG_DWORD_OFFSET, 0 }, /* ax : 3 */
{ REG_DWORD_OFFSET + 1, 0 }, /* cl : 4 */
{ REG_DWORD_OFFSET + 1, 8 }, /* ch : 5 */
{ REG_DWORD_OFFSET + 1, 0 }, /* cx : 6 */
{ REG_DWORD_OFFSET + 2, 0 }, /* dl : 7 */
{ REG_DWORD_OFFSET + 2, 8 }, /* dh : 8 */
{ REG_DWORD_OFFSET + 2, 0 }, /* dx : 9 */
{ REG_DWORD_OFFSET + 3, 0 }, /* bl : 10 */
{ REG_DWORD_OFFSET + 3, 8 }, /* bh : 11 */
{ REG_DWORD_OFFSET + 3, 0 }, /* bx : 12 */
{ REG_DWORD_OFFSET + 4, 0 }, /* sp : 13 */
{ REG_DWORD_OFFSET + 5, 0 }, /* bp : 14 */
{ REG_DWORD_OFFSET + 6, 0 }, /* si : 15 */
{ REG_DWORD_OFFSET + 7, 0 }, /* di : 16 */
{ REG_EIP_INDEX, 0 }, /* ip : 17 */
{ REG_FPU_OFFSET, 0 }, /* mm0 : 18 */
{ REG_FPU_OFFSET + 1, 0 }, /* mm1 : 19 */
{ REG_FPU_OFFSET + 2, 0 }, /* mm2 : 20 */
{ REG_FPU_OFFSET + 3, 0 }, /* mm3 : 21 */
{ REG_FPU_OFFSET + 4, 0 }, /* mm4 : 22 */
{ REG_FPU_OFFSET + 5, 0 }, /* mm5 : 23 */
{ REG_FPU_OFFSET + 6, 0 }, /* mm6 : 24 */
{ REG_FPU_OFFSET + 7, 0 } /* mm7 : 25 */
};
{ 0,0 },
{ REG_DWORD_OFFSET, 0 }, /* al : 1 */
{ REG_DWORD_OFFSET, 8 }, /* ah : 2 */
{ REG_DWORD_OFFSET, 0 }, /* ax : 3 */
{ REG_DWORD_OFFSET + 1, 0 }, /* cl : 4 */
{ REG_DWORD_OFFSET + 1, 8 }, /* ch : 5 */
{ REG_DWORD_OFFSET + 1, 0 }, /* cx : 6 */
{ REG_DWORD_OFFSET + 2, 0 }, /* dl : 7 */
{ REG_DWORD_OFFSET + 2, 8 }, /* dh : 8 */
{ REG_DWORD_OFFSET + 2, 0 }, /* dx : 9 */
{ REG_DWORD_OFFSET + 3, 0 }, /* bl : 10 */
{ REG_DWORD_OFFSET + 3, 8 }, /* bh : 11 */
{ REG_DWORD_OFFSET + 3, 0 }, /* bx : 12 */
{ REG_DWORD_OFFSET + 4, 0 }, /* sp : 13 */
{ REG_DWORD_OFFSET + 5, 0 }, /* bp : 14 */
{ REG_DWORD_OFFSET + 6, 0 }, /* si : 15 */
{ REG_DWORD_OFFSET + 7, 0 }, /* di : 16 */
{ REG_EIP_INDEX, 0 }, /* ip : 17 */
{ REG_FPU_OFFSET, 0 }, /* mm0 : 18 */
{ REG_FPU_OFFSET + 1, 0 }, /* mm1 : 19 */
{ REG_FPU_OFFSET + 2, 0 }, /* mm2 : 20 */
{ REG_FPU_OFFSET + 3, 0 }, /* mm3 : 21 */
{ REG_FPU_OFFSET + 4, 0 }, /* mm4 : 22 */
{ REG_FPU_OFFSET + 5, 0 }, /* mm5 : 23 */
{ REG_FPU_OFFSET + 6, 0 }, /* mm6 : 24 */
{ REG_FPU_OFFSET + 7, 0 } /* mm7 : 25 */
};
/* REGISTER TABLE: size, type, and name of every register in the
* CPU. Does not include MSRs since the are, after all,
* model specific. */
static struct {
unsigned int size;
enum x86_reg_type type;
unsigned int alias;
char mnemonic[8];
unsigned int size;
enum x86_reg_type type;
unsigned int alias;
char mnemonic[8];
} ia32_reg_table[NUM_X86_REGS + 2] = {
{ 0, reg_undef, 0, "" },
/* REG_DWORD_OFFSET */
@ -189,7 +189,7 @@ static struct {
{ REG_DWORD_SIZE, reg_sys, 0, "esp_msr" },
/* REG_EIPMSR_INDEX : SYSENTER_EIP_MSR : 92 */
{ REG_DWORD_SIZE, reg_sys, 0, "eip_msr" },
{ 0 }
{ 0,reg_undef,0,"" }
};
@ -197,38 +197,38 @@ static size_t sz_regtable = NUM_X86_REGS + 1;
void ia32_handle_register( x86_reg_t *reg, size_t id ) {
unsigned int alias;
if (! id || id > sz_regtable ) {
return;
}
memset( reg, 0, sizeof(x86_reg_t) );
strncpy( reg->name, ia32_reg_table[id].mnemonic, MAX_REGNAME );
reg->type = ia32_reg_table[id].type;
reg->size = ia32_reg_table[id].size;
alias = ia32_reg_table[id].alias;
if ( alias ) {
reg->alias = ia32_reg_aliases[alias].alias;
reg->shift = ia32_reg_aliases[alias].shift;
}
reg->id = id;
unsigned int alias;
if (! id || id > sz_regtable ) {
return;
}
memset( reg, 0, sizeof(x86_reg_t) );
strncpy( reg->name, ia32_reg_table[id].mnemonic, MAX_REGNAME );
reg->type = ia32_reg_table[id].type;
reg->size = ia32_reg_table[id].size;
alias = ia32_reg_table[id].alias;
if ( alias ) {
reg->alias = ia32_reg_aliases[alias].alias;
reg->shift = ia32_reg_aliases[alias].shift;
}
reg->id = id;
return;
}
size_t ia32_true_register_id( size_t id ) {
size_t reg;
size_t reg;
if (! id || id > sz_regtable ) {
return 0;
}
if (! id || id > sz_regtable ) {
return 0;
}
reg = id;
if (ia32_reg_table[reg].alias) {
reg = ia32_reg_aliases[ia32_reg_table[reg].alias].alias;
}
return reg;
reg = id;
if (ia32_reg_table[reg].alias) {
reg = ia32_reg_aliases[ia32_reg_table[reg].alias].alias;
}
return reg;
}

View File

@ -6,6 +6,7 @@
#endif
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <stdint.h>
/* 'NEW" types
@ -89,7 +90,7 @@ enum x86_options { /* these can be ORed together */
opt_none= 0,
opt_ignore_nulls=1, /* ignore sequences of > 4 NULL bytes */
opt_16_bit=2, /* 16-bit/DOS disassembly */
opt_att_mnemonics=4, /* use AT&T syntax names for alternate opcode mnemonics */
opt_att_mnemonics=4 /* use AT&T syntax names for alternate opcode mnemonics */
};
/* ========================================= Instruction Representation */
@ -133,12 +134,12 @@ enum x86_reg_type { /* NOTE: these may be ORed together */
/* x86_reg_t : an X86 CPU register */
struct x86_reg_t {
char name[MAX_REGNAME];
enum x86_reg_type type; /* what register is used for */
unsigned int size; /* size of register in bytes */
unsigned int id; /* register ID #, for quick compares */
unsigned int alias; /* ID of reg this is an alias for */
unsigned int shift; /* amount to shift aliased reg by */
char name[MAX_REGNAME];
enum x86_reg_type type; /* what register is used for */
unsigned int size; /* size of register in bytes */
unsigned int id; /* register ID #, for quick compares */
unsigned int alias; /* ID of reg this is an alias for */
unsigned int shift; /* amount to shift aliased reg by */
x86_reg_t * aliased_reg( ) {
x86_reg_t * reg = (x86_reg_t * )calloc( sizeof(x86_reg_t), 1 );
reg->x86_reg_from_id( id );
@ -158,11 +159,11 @@ typedef struct {
/* x86_absolute_t : an X86 segment:offset address (descriptor) */
typedef struct {
unsigned short segment; /* loaded directly into CS */
union {
unsigned short off16; /* loaded directly into IP */
uint32_t off32; /* loaded directly into EIP */
} offset;
unsigned short segment; /* loaded directly into CS */
union {
unsigned short off16; /* loaded directly into IP */
uint32_t off32; /* loaded directly into EIP */
} offset;
} x86_absolute_t;
enum x86_op_type { /* mutually exclusive */
@ -250,57 +251,87 @@ struct x86_op_flags { /* ORed together, but segs are mutually exclusive */
/* x86_op_t : an X86 instruction operand */
struct x86_op_t{
friend struct x86_insn_t;
enum x86_op_type type; /* operand type */
enum x86_op_datatype datatype; /* operand size */
enum x86_op_access access; /* operand access [RWX] */
x86_op_flags flags; /* misc flags */
union {
/* sizeof will have to work on these union members! */
/* immediate values */
char sbyte;
short sword;
int32_t sdword;
qword_t sqword;
unsigned char byte;
unsigned short word;
uint32_t dword;
qword_t qword;
float sreal;
double dreal;
/* misc large/non-native types */
unsigned char extreal[10];
unsigned char bcd[10];
qword_t dqword[2];
unsigned char simd[16];
unsigned char fpuenv[28];
/* offset from segment */
uint32_t offset;
x86_reg_t reg; /* ID of CPU register */
char relative_near; /* offsets from current insn */
int32_t relative_far;
x86_absolute_t absolute; /* segment:offset */
x86_ea_t expression; /* effective address [expression] */
} data;
/* this is needed to make formatting operands more sane */
void * insn; /* pointer to x86_insn_t owning operand */
size_t size()
enum x86_op_type type; /* operand type */
enum x86_op_datatype datatype; /* operand size */
enum x86_op_access access; /* operand access [RWX] */
x86_op_flags flags; /* misc flags */
union {
/* sizeof will have to work on these union members! */
/* immediate values */
char sbyte;
short sword;
int32_t sdword;
qword_t sqword;
unsigned char byte;
unsigned short word;
uint32_t dword;
qword_t qword;
float sreal;
double dreal;
/* misc large/non-native types */
unsigned char extreal[10];
unsigned char bcd[10];
qword_t dqword[2];
unsigned char simd[16];
unsigned char fpuenv[28];
/* offset from segment */
uint32_t offset;
/* ID of CPU register */
x86_reg_t reg;
/* offsets from current insn */
char relative_near;
int32_t relative_far;
/* segment:offset */
x86_absolute_t absolute;
/* effective address [expression] */
x86_ea_t expression;
} data;
/* this is needed to make formatting operands more sane */
void * insn; /* pointer to x86_insn_t owning operand */
size_t size() const
{
return operand_size();
}
/* get size of operand data in bytes */
size_t operand_size();
size_t operand_size() const;
/* format (sprintf) an operand into 'buf' using specified syntax */
int x86_format_operand(char *buf, int len, enum x86_asm_format format );
bool is_address( ) {
bool is_address( ) const {
return ( type == op_absolute || type == op_offset );
}
bool is_relative( ) {
bool is_relative( ) const {
return ( type == op_relative_near || type == op_relative_far );
}
bool is_immediate( ) const { return ( type == op_immediate ); }
int32_t getAddress()
{
assert(is_address()||is_relative());
switch ( type ) {
case op_relative_near:
return (int32_t) data.relative_near;
case op_absolute:
if(datatype==op_descr16)
return int32_t((data.absolute.segment)<<4) + data.absolute.offset.off16;
else
return int32_t((data.absolute.segment)<<4) + data.absolute.offset.off32;
case op_offset:
return data.offset;
case op_relative_far:
if (data.relative_far & 0x8000)
return (data.relative_far & 0xFFFF) | 0xFFFF0000;
else
return (int32_t)data.relative_far;
default:
assert(false);
break;
}
return ~0;
}
char * format( enum x86_asm_format format );
x86_op_t * copy()
{
x86_op_t *op = (x86_op_t *) calloc( sizeof(x86_op_t), 1 );
if ( op ) {
memcpy( op, this, sizeof(x86_op_t) );
}
@ -439,7 +470,7 @@ enum x86_insn_note {
insn_note_smm = 2, /* "" in System Management Mode */
insn_note_serial = 4, /* Serializing instruction */
insn_note_nonswap = 8, /* Does not swap arguments in att-style formatting */
insn_note_nosuffix = 16, /* Does not have size suffix in att-style formatting */
insn_note_nosuffix = 16 /* Does not have size suffix in att-style formatting */
};
/* This specifies what effects the instruction has on the %eflags register */
@ -520,7 +551,6 @@ enum x86_insn_prefix {
/* TODO: maybe provide insn_new/free(), and have disasm return new insn_t */
/* FOREACH types: these are used to limit the foreach results to
* operands which match a certain "type" (implicit or explicit)
* or which are accessed in certain ways (e.g. read or write). Note
@ -572,8 +602,8 @@ private:
void x86_oplist_append(x86_oplist_t *op);
public:
/* information about the instruction */
uint32_t addr; /* load address */
uint32_t offset; /* offset into file/buffer */
uint32_t addr; /* load address */
uint32_t offset; /* offset into file/buffer */
x86_insn_group group; /* meta-type, e.g. INS_EXEC */
x86_insn_type type; /* type, e.g. INS_BRANCH */
x86_insn_note note; /* note, e.g. RING0 */
@ -604,29 +634,36 @@ public:
void *block; /* code block containing this insn */
void *function; /* function containing this insn */
int tag; /* tag the insn as seen/processed */
x86_op_t * x86_operand_new();
size_t x86_operand_count( enum x86_op_foreach_type type );
x86_op_t *x86_operand_new();
/* convenience routine: returns count of operands matching 'type' */
size_t x86_operand_count( enum x86_op_foreach_type type );
/* accessor functions for the operands */
x86_op_t * x86_operand_1st( );
x86_op_t * x86_operand_2nd( );
x86_op_t * x86_operand_3rd( );
x86_op_t * get_dest();
int32_t x86_get_rel_offset( );
x86_op_t * x86_get_branch_target( );
x86_op_t * x86_get_imm( );
uint8_t * x86_get_raw_imm( );
x86_op_t * operand_1st( );
x86_op_t * operand_2nd( );
x86_op_t * operand_3rd( );
const x86_op_t * get_dest() const;
int32_t x86_get_rel_offset( );
x86_op_t * x86_get_branch_target( );
x86_op_t * x86_get_imm( );
/* More accessor fuctions, this time for user-defined info... */
void x86_set_insn_addr( uint32_t addr );
int x86_format_mnemonic( char *buf, int len, enum x86_asm_format format);
int x86_format_insn( char *buf, int len, enum x86_asm_format);
void x86_oplist_free( );
uint8_t * x86_get_raw_imm( );
/* set the address (usually RVA) of the insn */
void x86_set_insn_addr( uint32_t addr );
/* format (sprintf) an instruction mnemonic into 'buf' using specified syntax */
int x86_format_mnemonic( char *buf, int len, enum x86_asm_format format);
int x86_format_insn( char *buf, int len, enum x86_asm_format);
void x86_oplist_free( );
/* returns 0 if an instruction is invalid, 1 if valid */
bool is_valid( );
uint32_t x86_get_address( );
void make_invalid(unsigned char *buf);
void make_invalid(unsigned char *buf);
/* instruction tagging: these routines allow the programmer to mark
* instructions as "seen" in a DFS, for example. libdisasm does not use
* the tag field.*/
/* set insn->tag to 1 */
void x86_tag_insn( );
/* return insn->tag */
int x86_insn_is_tagged();
/* set insn->tag to 0 */
void x86_untag_insn();
@ -722,7 +759,7 @@ public:
* offset : Offset in buffer to disassemble
* insn : Structure to fill with disassembled instruction
*/
unsigned int x86_disasm( unsigned char *buf, unsigned int buf_len,
unsigned int x86_disasm(const unsigned char *buf, unsigned int buf_len,
uint32_t buf_rva, unsigned int offset,
x86_insn_t * insn );
/* x86_disasm_range: Sequential disassembly of a range of bytes in a buffer,
@ -803,7 +840,7 @@ public:
* void x86_get_aliased_reg( x86_reg_t *alias_reg, x86_reg_t *output_reg )
* where 'alias_reg' is a reg operand and 'output_reg' is filled with the
* register that the operand is an alias for */
//#define x86_get_aliased_reg( alias_reg, output_reg ) \
//#define x86_get_aliased_reg( alias_reg, output_reg )
// x86_reg_from_id( alias_reg->alias, output_reg )

49
3rd_party/libdisasm/libdisasm.def vendored Normal file
View File

@ -0,0 +1,49 @@
;libdisasm.def : Declares the module parameters
LIBRARY "libdisasm.dll"
DESCRIPTION "libdisasm exported functions"
EXPORTS
x86_addr_size @1
x86_cleanup @2
x86_disasm @3
x86_disasm_forward @4
x86_disasm_range @5
x86_endian @6
x86_format_header @7
x86_format_insn @8
x86_format_mnemonic @9
x86_format_operand @10
x86_fp_reg @11
x86_get_branch_target @12
x86_get_imm @13
x86_get_options @14
x86_get_raw_imm @15
x86_get_rel_offset @16
x86_imm_signsized @17
x86_imm_sized @18
x86_init @19
x86_insn_is_tagged @20
x86_insn_is_valid @21
x86_invariant_disasm @22
x86_ip_reg @23
x86_max_insn_size @24
x86_op_size @25
x86_operand_1st @26
x86_operand_2nd @27
x86_operand_3rd @28
x86_operand_count @29
x86_operand_foreach @30
x86_operand_new @31
x86_operand_size @32
x86_oplist_free @33
x86_reg_from_id @34
x86_report_error @35
x86_set_insn_addr @36
x86_set_insn_block @37
x86_set_insn_function @38
x86_set_insn_offset @39
x86_set_options @40
x86_set_reporter @41
x86_size_disasm @42
x86_sp_reg @43
x86_tag_insn @44

View File

@ -9,8 +9,8 @@
#ifdef _MSC_VER
#define snprintf _snprintf
#define inline __inline
#define snprintf _snprintf
#define inline __inline
#endif
void x86_insn_t::make_invalid(unsigned char *buf)
{
@ -21,9 +21,9 @@ void x86_insn_t::make_invalid(unsigned char *buf)
type = insn_invalid;
memcpy( bytes, buf, 1 );
}
unsigned int X86_Disasm::x86_disasm( unsigned char *buf, unsigned int buf_len,
uint32_t buf_rva, unsigned int offset,
x86_insn_t *insn ){
unsigned int X86_Disasm::x86_disasm( const unsigned char *buf, unsigned int buf_len,
uint32_t buf_rva, unsigned int offset,
x86_insn_t *insn ){
int len, size;
unsigned char bytes[MAX_INSTRUCTION_SIZE];
@ -52,8 +52,8 @@ unsigned int X86_Disasm::x86_disasm( unsigned char *buf, unsigned int buf_len,
/* copy enough bytes for disassembly into buffer : this
* helps prevent buffer overruns at the end of a file */
memset( bytes, 0, MAX_INSTRUCTION_SIZE );
memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len :
MAX_INSTRUCTION_SIZE );
memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len :
MAX_INSTRUCTION_SIZE );
/* actually do the disassembly */
/* TODO: allow switching when more disassemblers are added */
@ -81,140 +81,139 @@ unsigned int X86_Disasm::x86_disasm( unsigned char *buf, unsigned int buf_len,
}
unsigned int X86_Disasm::x86_disasm_range( unsigned char *buf, uint32_t buf_rva,
unsigned int offset, unsigned int len,
DISASM_CALLBACK func, void *arg ) {
x86_insn_t insn;
unsigned int buf_len, size, count = 0, bytes = 0;
unsigned int offset, unsigned int len,
DISASM_CALLBACK func, void *arg ) {
x86_insn_t insn;
unsigned int buf_len, size, count = 0, bytes = 0;
/* buf_len is implied by the arguments */
buf_len = len + offset;
/* buf_len is implied by the arguments */
buf_len = len + offset;
while ( bytes < len ) {
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
&insn );
if ( size ) {
/* invoke callback if it exists */
if ( func ) {
(*func)( &insn, arg );
}
bytes += size;
count ++;
} else {
/* error */
bytes++; /* try next byte */
}
insn.x86_oplist_free();
while ( bytes < len ) {
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
&insn );
if ( size ) {
/* invoke callback if it exists */
if ( func ) {
(*func)( &insn, arg );
}
bytes += size;
count ++;
} else {
/* error */
bytes++; /* try next byte */
}
return( count );
insn.x86_oplist_free();
}
return( count );
}
static inline int follow_insn_dest( x86_insn_t *insn ) {
if ( insn->type == insn_jmp || insn->type == insn_jcc ||
insn->type == insn_call || insn->type == insn_callcc ) {
return(1);
}
return(0);
if ( insn->type == insn_jmp || insn->type == insn_jcc ||
insn->type == insn_call || insn->type == insn_callcc ) {
return(1);
}
return(0);
}
static inline int insn_doesnt_return( x86_insn_t *insn ) {
return( (insn->type == insn_jmp || insn->type == insn_return) ? 1: 0 );
return( (insn->type == insn_jmp || insn->type == insn_return) ? 1: 0 );
}
static int32_t internal_resolver( x86_op_t *op, x86_insn_t *insn ){
int32_t next_addr = -1;
if ( x86_optype_is_address(op->type) ) {
next_addr = op->data.sdword;
} else if ( op->type == op_relative_near ) {
next_addr = insn->addr + insn->size + op->data.relative_near;
} else if ( op->type == op_relative_far ) {
next_addr = insn->addr + insn->size + op->data.relative_far;
}
return( next_addr );
int32_t next_addr = -1;
if ( x86_optype_is_address(op->type) ) {
next_addr = op->data.sdword;
} else if ( op->type == op_relative_near ) {
next_addr = insn->addr + insn->size + op->data.relative_near;
} else if ( op->type == op_relative_far ) {
next_addr = insn->addr + insn->size + op->data.relative_far;
}
return( next_addr );
}
unsigned int X86_Disasm::x86_disasm_forward( unsigned char *buf, unsigned int buf_len,
uint32_t buf_rva, unsigned int offset,
DISASM_CALLBACK func, void *arg,
DISASM_RESOLVER resolver, void *r_arg ){
x86_insn_t insn;
x86_op_t *op;
int32_t next_addr;
uint32_t next_offset;
unsigned int size, count = 0, bytes = 0, cont = 1;
uint32_t buf_rva, unsigned int offset,
DISASM_CALLBACK func, void *arg,
DISASM_RESOLVER resolver, void *r_arg ){
x86_insn_t insn;
x86_op_t *op;
int32_t next_addr;
int32_t next_offset;
unsigned int size, count = 0, bytes = 0, cont = 1;
while ( cont && bytes < buf_len ) {
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
while ( cont && bytes < buf_len ) {
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
&insn );
if ( size ) {
/* invoke callback if it exists */
if ( func ) {
(*func)( &insn, arg );
}
bytes += size;
count ++;
} else {
/* error */
bytes++; /* try next byte */
}
if ( follow_insn_dest(&insn) ) {
op = insn.x86_operand_1st();//x86_get_dest_operand
next_addr = -1;
/* if caller supplied a resolver, use it to determine
* the address to disassemble */
if ( resolver ) {
next_addr = resolver(op, &insn, r_arg);
} else {
next_addr = internal_resolver(op, &insn);
}
if (next_addr != -1 ) {
next_offset = next_addr - buf_rva;
/* if offset is in this buffer... */
if ( next_offset >= 0 &&
next_offset < buf_len ) {
/* go ahead and disassemble */
count += x86_disasm_forward( buf,
buf_len,
buf_rva,
next_offset,
func, arg,
resolver, r_arg );
} else {
/* report unresolved address */
x86_report_error( report_disasm_bounds,
(void*)(long)next_addr );
}
}
} /* end follow_insn */
if ( insn_doesnt_return(&insn) ) {
/* stop disassembling */
cont = 0;
}
insn.x86_oplist_free( );
if ( size ) {
/* invoke callback if it exists */
if ( func ) {
(*func)( &insn, arg );
}
bytes += size;
count ++;
} else {
/* error */
bytes++; /* try next byte */
}
return( count );
if ( follow_insn_dest(&insn) ) {
op = insn.operand_1st();//x86_get_dest_operand
next_addr = -1;
/* if caller supplied a resolver, use it to determine
* the address to disassemble */
if ( resolver ) {
next_addr = resolver(op, &insn, r_arg);
} else {
next_addr = internal_resolver(op, &insn);
}
if (next_addr != -1 ) {
next_offset = next_addr - buf_rva;
/* if offset is in this buffer... */
if ( next_offset >= 0 && next_offset < buf_len ) {
/* go ahead and disassemble */
count += x86_disasm_forward( buf,
buf_len,
buf_rva,
next_offset,
func, arg,
resolver, r_arg );
} else {
/* report unresolved address */
x86_report_error( report_disasm_bounds,
(void*)(long)next_addr );
}
}
} /* end follow_insn */
if ( insn_doesnt_return(&insn) ) {
/* stop disassembling */
cont = 0;
}
insn.x86_oplist_free( );
}
return( count );
}
/* invariant instruction representation */
size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
x86_invariant_t *inv ){
if (! buf || ! buf_len || ! inv ) {
return(0);
}
size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
x86_invariant_t *inv ){
if (! buf || ! buf_len || ! inv ) {
return(0);
}
return ia32_disasm_invariant(buf, buf_len, inv);
return ia32_disasm_invariant(buf, buf_len, inv);
}
size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len ) {
if (! buf || ! buf_len ) {
return(0);
}
if (! buf || ! buf_len ) {
return(0);
}
return ia32_disasm_size(buf, buf_len);
return ia32_disasm_size(buf, buf_len);
}

View File

@ -46,7 +46,7 @@
} \
} while( 0 )
static char *prefix_strings[] = {
static const char *prefix_strings[] = {
"", /* no prefix */
"repz ", /* the trailing spaces make it easy to prepend to mnemonic */
"repnz ",
@ -115,7 +115,7 @@ static void get_operand_data_str( x86_op_t *op, char *str, int len ){
static void get_operand_regtype_str( int regtype, char *str, int len )
{
static struct {
char *name;
const char *name;
int value;
} operand_regtypes[] = {
{"reg_gen" , 0x00001},
@ -284,7 +284,7 @@ static int format_expr( x86_ea_t *ea, char *buf, int len,
static int format_seg( x86_op_t *op, char *buf, int len,
enum x86_asm_format format ) {
int len_orig = len;
char *reg = "";
const char *reg = "";
if (! op || ! buf || ! len || ! op->flags.whole) {
return(0);
@ -295,8 +295,9 @@ static int format_seg( x86_op_t *op, char *buf, int len,
if (! (int) op->flags.op_seg) {
return(0);
}
switch (op->flags.op_seg) {
uint16_t seg_ov=uint16_t(op->flags.op_seg)<<8;
switch (seg_ov)
{
case x86_op_flags::op_es_seg: reg = "es"; break;
case x86_op_flags::op_cs_seg: reg = "cs"; break;
case x86_op_flags::op_ss_seg: reg = "ss"; break;
@ -328,9 +329,9 @@ static int format_seg( x86_op_t *op, char *buf, int len,
return( len_orig - len ); /* return length of appended string */
}
static char *get_operand_datatype_str( x86_op_t *op ){
static const char *get_operand_datatype_str( x86_op_t *op ){
static char *types[] = {
static const char *types[] = {
"sbyte", /* 0 */
"sword",
"sqword",
@ -405,7 +406,7 @@ static int format_insn_eflags_str( enum x86_flag_status flags, char *buf,
int len) {
static struct {
char *name;
const char *name;
int value;
} insn_flags[] = {
{ "carry_set ", 0x0001 },
@ -440,9 +441,9 @@ static int format_insn_eflags_str( enum x86_flag_status flags, char *buf,
return( len_orig - len );
}
static char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
static const char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
static char *types[] = {
static const char *types[] = {
"", // 0
"controlflow",// 1
"arithmetic", // 2
@ -467,10 +468,10 @@ static char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
return types[gp];
}
static char *get_insn_type_str( enum x86_insn_type type ) {
static const char *get_insn_type_str( enum x86_insn_type type ) {
static struct {
char *name;
const char *name;
int value;
} types[] = {
/* insn_controlflow */
@ -592,8 +593,8 @@ static char *get_insn_type_str( enum x86_insn_type type ) {
return "";
}
static char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
static char *intel[] = {
static const char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
static const char *intel[] = {
"", // 0
"8086", // 1
"80286", // 2
@ -620,8 +621,8 @@ static char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
return "";
}
static char *get_insn_isa_str( enum x86_insn_isa isa ) {
static char *subset[] = {
static const char *get_insn_isa_str( enum x86_insn_isa isa ) {
static const char *subset[] = {
NULL, // 0
"General Purpose", // 1
"Floating Point", // 2
@ -880,11 +881,11 @@ static int format_operand_xml( x86_op_t *op, x86_insn_t *insn, char *buf,
return( strlen( buf ) );
}
static int format_operand_raw( x86_op_t *op, x86_insn_t *insn, char *buf,
static int format_operand_raw( x86_op_t *op, x86_insn_t */*insn*/, char *buf,
int len){
char str[MAX_OP_RAW_STRING];
char *datatype = get_operand_datatype_str(op);
const char *datatype = get_operand_datatype_str(op);
switch (op->type) {
case op_register:
@ -1042,7 +1043,7 @@ char * x86_op_t::format( enum x86_asm_format format ) {
static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
int size = 0;
char *suffix;
const char *suffix;
if (! insn || ! buf || ! len )
return(0);
@ -1051,8 +1052,8 @@ static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
/* do long jump/call prefix */
if ( insn->type == insn_jmp || insn->type == insn_call ) {
if (! is_imm_jmp( insn->x86_operand_1st() ) ||
(insn->x86_operand_1st())->datatype != op_byte ) {
if (! is_imm_jmp( insn->operand_1st() ) ||
(insn->operand_1st())->datatype != op_byte ) {
/* far jump/call, use "l" prefix */
STRNCAT( buf, "l", len );
}
@ -1076,11 +1077,11 @@ static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
insn->type == insn_out
)) {
if ( insn->x86_operand_count( op_explicit ) > 0 &&
is_memory_op( insn->x86_operand_1st() ) ){
size = insn->x86_operand_1st()->operand_size();
is_memory_op( insn->operand_1st() ) ){
size = insn->operand_1st()->operand_size();
} else if ( insn->x86_operand_count( op_explicit ) > 1 &&
is_memory_op( insn->x86_operand_2nd() ) ){
size = insn->x86_operand_2nd()->operand_size();
is_memory_op( insn->operand_2nd() ) ){
size = insn->operand_2nd()->operand_size();
}
}
@ -1094,7 +1095,6 @@ static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
return ( strlen( buf ) );
}
/** format (sprintf) an instruction mnemonic into 'buf' using specified syntax */
int x86_format_mnemonic(x86_insn_t *insn, char *buf, int len,
enum x86_asm_format format){
char str[MAX_OP_STRING];
@ -1137,7 +1137,7 @@ static int format_insn_note(x86_insn_t *insn, char *buf, int len){
return( len_orig - len );
}
static int format_raw_insn( x86_insn_t *insn, char *buf, int len ){
static int format_raw_insn( x86_insn_t *insn, char *buf, size_t len ){
struct op_string opstr = { buf, len };
int i;
@ -1223,24 +1223,24 @@ static int format_xml_insn( x86_insn_t *insn, char *buf, int len ) {
len -= format_insn_eflags_str( insn->flags_tested, buf, len );
STRNCAT( buf, "\"/>\n\t</flags>\n", len );
if ( insn->x86_operand_1st() ) {
insn->x86_operand_1st()->x86_format_operand(str,
if ( insn->operand_1st() ) {
insn->operand_1st()->x86_format_operand(str,
sizeof str, xml_syntax);
STRNCAT( buf, "\t<operand name=dest>\n", len );
STRNCAT( buf, str, len );
STRNCAT( buf, "\t</operand>\n", len );
}
if ( insn->x86_operand_2nd() ) {
insn->x86_operand_2nd()->x86_format_operand(str,sizeof str,
if ( insn->operand_2nd() ) {
insn->operand_2nd()->x86_format_operand(str,sizeof str,
xml_syntax);
STRNCAT( buf, "\t<operand name=src>\n", len );
STRNCAT( buf, str, len );
STRNCAT( buf, "\t</operand>\n", len );
}
if ( insn->x86_operand_3rd() ) {
insn->x86_operand_3rd()->x86_format_operand(str,sizeof str,
if ( insn->operand_3rd() ) {
insn->operand_3rd()->x86_format_operand(str,sizeof str,
xml_syntax);
STRNCAT( buf, "\t<operand name=imm>\n", len );
STRNCAT( buf, str, len );
@ -1342,13 +1342,13 @@ int x86_insn_t::x86_format_insn( char *buf, int len,
STRNCAT( buf, "\t", len );
/* dest */
if ( (dst = x86_operand_1st()) && !(dst->flags.op_implied) ) {
if ( (dst = operand_1st()) && !(dst->flags.op_implied) ) {
dst->x86_format_operand(str, MAX_OP_STRING, format);
STRNCAT( buf, str, len );
}
/* src */
if ( (src = x86_operand_2nd()) ) {
if ( (src = operand_2nd()) ) {
if ( !(dst->flags.op_implied) ) {
STRNCAT( buf, ", ", len );
}
@ -1357,9 +1357,9 @@ int x86_insn_t::x86_format_insn( char *buf, int len,
}
/* imm */
if ( x86_operand_3rd()) {
if ( operand_3rd()) {
STRNCAT( buf, ", ", len );
x86_operand_3rd()->x86_format_operand(str, MAX_OP_STRING,format);
operand_3rd()->x86_format_operand(str, MAX_OP_STRING,format);
STRNCAT( buf, str, len );
}
@ -1373,8 +1373,8 @@ int x86_insn_t::x86_format_insn( char *buf, int len,
/* not sure which is correct? sometimes GNU as requires
* an imm as the first operand, sometimes as the third... */
/* imm */
if ( x86_operand_3rd() ) {
x86_operand_3rd()->x86_format_operand(str, MAX_OP_STRING,format);
if ( operand_3rd() ) {
operand_3rd()->x86_format_operand(str, MAX_OP_STRING,format);
STRNCAT( buf, str, len );
/* there is always 'dest' operand if there is 'src' */
STRNCAT( buf, ", ", len );
@ -1382,13 +1382,13 @@ int x86_insn_t::x86_format_insn( char *buf, int len,
if ( (note & insn_note_nonswap ) == 0 ) {
/* regular AT&T style swap */
src = x86_operand_2nd();
dst = x86_operand_1st();
src = operand_2nd();
dst = operand_1st();
}
else {
/* special-case instructions */
src = x86_operand_1st();
dst = x86_operand_2nd();
src = operand_1st();
dst = operand_2nd();
}
/* src */
@ -1431,20 +1431,20 @@ int x86_insn_t::x86_format_insn( char *buf, int len,
/* print operands */
/* dest */
if ( x86_operand_1st() ) {
x86_operand_1st()->x86_format_operand(str, MAX_OP_STRING,format);
if ( operand_1st() ) {
operand_1st()->x86_format_operand(str, MAX_OP_STRING,format);
STRNCATF( buf, "%s\t", str, len );
}
/* src */
if ( x86_operand_2nd() ) {
x86_operand_2nd()->x86_format_operand(str, MAX_OP_STRING,format);
if ( operand_2nd() ) {
operand_2nd()->x86_format_operand(str, MAX_OP_STRING,format);
STRNCATF( buf, "%s\t", str, len );
}
/* imm */
if ( x86_operand_3rd()) {
x86_operand_3rd()->x86_format_operand(str, MAX_OP_STRING,format);
if ( operand_3rd()) {
operand_3rd()->x86_format_operand(str, MAX_OP_STRING,format);
STRNCAT( buf, str, len );
}
}

View File

@ -17,7 +17,6 @@ int x86_insn_is_valid( x86_insn_t *insn ) {
return 0;
}
/** \returns false if an instruction is invalid, true if valid */
bool x86_insn_t::is_valid( )
{
if ( this && this->type != insn_invalid && this->size > 0 )
@ -94,13 +93,12 @@ x86_op_t * x86_insn_t::x86_get_branch_target() {
return NULL;
}
x86_op_t * x86_insn_t::get_dest() {
const x86_op_t * x86_insn_t::get_dest() const {
x86_oplist_t *op_lst;
assert(this);
if ( ! operands ) {
return NULL;
}
assert(this->x86_operand_count(op_dest)==1);
for (op_lst = operands; op_lst; op_lst = op_lst->next ) {
if ( op_lst->op.access & op_write)
return &(op_lst->op);
@ -171,7 +169,7 @@ uint8_t *x86_insn_t::x86_get_raw_imm() {
}
size_t x86_op_t::operand_size() {
size_t x86_op_t::operand_size() const {
switch (datatype ) {
case op_byte: return 1;
case op_word: return 2;
@ -203,13 +201,12 @@ size_t x86_op_t::operand_size() {
return(4); /* default size */
}
/** set the address (usually RVA) of the insn */
void x86_insn_t::x86_set_insn_addr( uint32_t _addr ) {
addr = _addr;
}
void x86_insn_t::x86_set_insn_offset( unsigned int offset ){
offset = offset;
void x86_insn_t::x86_set_insn_offset( unsigned int _offset ){
offset = _offset;
}
void x86_insn_t::x86_set_insn_function( void * func ){
@ -220,7 +217,6 @@ void x86_insn_t::x86_set_insn_block( void * _block ){
block = _block;
}
/** set insn->tag to 1 */
void x86_insn_t::x86_tag_insn(){
tag = 1;
}
@ -229,7 +225,6 @@ void x86_insn_t::x86_untag_insn(){
tag = 0;
}
/** \return insn->tag */
int x86_insn_t::x86_insn_is_tagged(){
return tag;
}

View File

@ -4,31 +4,31 @@
void x86_insn_t::x86_oplist_append( x86_oplist_t *op ) {
x86_oplist_t *list;
x86_oplist_t *list;
assert(this);
list = operands;
if (! list ) {
operand_count = 1;
/* Note that we have no way of knowing if this is an
list = operands;
if (! list ) {
operand_count = 1;
/* Note that we have no way of knowing if this is an
* exlicit operand or not, since the caller fills
* the x86_op_t after we return. We increase the
* explicit count automatically, and ia32_insn_implicit_ops
* decrements it */
explicit_count = 1;
operands = op;
explicit_count = 1;
operands = op;
return;
}
/* get to end of list */
for ( ; list->next; list = list->next )
;
operand_count = operand_count + 1;
explicit_count = explicit_count + 1;
list->next = op;
return;
}
/* get to end of list */
for ( ; list->next; list = list->next )
;
operand_count = operand_count + 1;
explicit_count = explicit_count + 1;
list->next = op;
return;
}
bool x86_insn_t::containsFlag(x86_eflags tofind, x86_flag_status in)
@ -48,7 +48,7 @@ bool x86_insn_t::containsFlag(x86_eflags tofind, x86_flag_status in)
return (in & (insn_dir_set | insn_dir_clear))!=0;
case insn_eflag_sign:
return (in & (insn_sign_set | insn_sign_clear | insn_zero_set_or_sign_ne_oflow |
insn_sign_eq_oflow | insn_sign_ne_oflow))!=0;
insn_sign_eq_oflow | insn_sign_ne_oflow))!=0;
case insn_eflag_parity:
return (in & (insn_parity_set | insn_parity_clear))!=0;
}
@ -56,31 +56,31 @@ bool x86_insn_t::containsFlag(x86_eflags tofind, x86_flag_status in)
}
x86_op_t * x86_insn_t::x86_operand_new( ) {
x86_oplist_t *op;
x86_oplist_t *op;
assert(this);
op = (x86_oplist_t *)calloc( sizeof(x86_oplist_t), 1 );
op->op.insn = this;
x86_oplist_append( op );
return( &(op->op) );
op = (x86_oplist_t *)calloc( sizeof(x86_oplist_t), 1 );
op->op.insn = this;
x86_oplist_append( op );
return( &(op->op) );
}
/** free the operand list associated with an instruction -- useful for
* preventing memory leaks when free()ing an x86_insn_t */
void x86_insn_t::x86_oplist_free( )
{
x86_oplist_t *op, *list;
x86_oplist_t *op, *list;
assert(this);
for ( list = operands; list; ) {
op = list;
list = list->next;
free(op);
}
for ( list = operands; list; ) {
op = list;
list = list->next;
free(op);
}
operands = NULL;
operand_count = 0;
explicit_count = 0;
operands = NULL;
operand_count = 0;
explicit_count = 0;
return;
return;
}
/* ================================================== LIBDISASM API */
@ -88,122 +88,121 @@ void x86_insn_t::x86_oplist_free( )
enum... yet one more confusing thing in the API */
int x86_insn_t::x86_operand_foreach( x86_operand_fn func, void *arg, enum x86_op_foreach_type type )
{
x86_oplist_t *list;
char _explicit = 1, implicit = 1;
x86_oplist_t *list;
char _explicit = 1, implicit = 1;
assert(this);
if ( ! func ) {
return 0;
}
if ( ! func ) {
return 0;
}
/* note: explicit and implicit can be ORed together to
/* note: explicit and implicit can be ORed together to
* allow an "all" limited by access type, even though the
* user is stupid to do this since it is default behavior :) */
if ( (type & op_explicit) && ! (type & op_implicit) ) {
implicit = 0;
}
if ( (type & op_implicit) && ! (type & op_explicit) ) {
_explicit = 0;
}
type = (x86_op_foreach_type)((int)type & 0x0F); /* mask out explicit/implicit operands */
for ( list = operands; list; list = list->next ) {
if (! implicit && (list->op.flags.op_implied) ) {
/* operand is implicit */
continue;
if ( (type & op_explicit) && ! (type & op_implicit) ) {
implicit = 0;
}
if ( (type & op_implicit) && ! (type & op_explicit) ) {
_explicit = 0;
}
if (! _explicit && ! (list->op.flags.op_implied) ) {
/* operand is not implicit */
continue;
type = (x86_op_foreach_type)((int)type & 0x0F); /* mask out explicit/implicit operands */
for ( list = operands; list; list = list->next ) {
if (! implicit && (list->op.flags.op_implied) ) {
/* operand is implicit */
continue;
}
if (! _explicit && ! (list->op.flags.op_implied) ) {
/* operand is not implicit */
continue;
}
switch ( type ) {
case op_any:
break;
case op_dest:
if (! (list->op.access & op_write) ) {
continue;
}
break;
case op_src:
if (! (list->op.access & op_read) ) {
continue;
}
break;
case op_ro:
if (! (list->op.access & op_read) ||
(list->op.access & op_write ) ) {
continue;
}
break;
case op_wo:
if (! (list->op.access & op_write) ||
(list->op.access & op_read ) ) {
continue;
}
break;
case op_xo:
if (! (list->op.access & op_execute) ) {
continue;
}
break;
case op_rw:
if (! (list->op.access & op_write) ||
! (list->op.access & op_read ) ) {
continue;
}
break;
case op_implicit: case op_explicit: /* make gcc happy */
break;
}
/* any non-continue ends up here: invoke the callback */
(*func)( &list->op, this, arg );
}
switch ( type ) {
case op_any:
break;
case op_dest:
if (! (list->op.access & op_write) ) {
continue;
}
break;
case op_src:
if (! (list->op.access & op_read) ) {
continue;
}
break;
case op_ro:
if (! (list->op.access & op_read) ||
(list->op.access & op_write ) ) {
continue;
}
break;
case op_wo:
if (! (list->op.access & op_write) ||
(list->op.access & op_read ) ) {
continue;
}
break;
case op_xo:
if (! (list->op.access & op_execute) ) {
continue;
}
break;
case op_rw:
if (! (list->op.access & op_write) ||
! (list->op.access & op_read ) ) {
continue;
}
break;
case op_implicit: case op_explicit: /* make gcc happy */
break;
}
/* any non-continue ends up here: invoke the callback */
(*func)( &list->op, this, arg );
}
return 1;
return 1;
}
static void count_operand( x86_op_t *op, x86_insn_t *insn, void *arg ) {
size_t * count = (size_t *) arg;
*count = *count + 1;
static void count_operand( x86_op_t */*op*/, x86_insn_t */*insn*/, void *arg ) {
size_t * count = (size_t *) arg;
*count = *count + 1;
}
/** convenience routine: returns count of operands matching 'type' */
size_t x86_insn_t::x86_operand_count( enum x86_op_foreach_type type ) {
size_t count = 0;
size_t count = 0;
/* save us a list traversal for common counts... */
if ( type == op_any ) {
return operand_count;
} else if ( type == op_explicit ) {
return explicit_count;
}
/* save us a list traversal for common counts... */
if ( type == op_any ) {
return operand_count;
} else if ( type == op_explicit ) {
return explicit_count;
}
x86_operand_foreach( count_operand, &count, type );
return count;
x86_operand_foreach( count_operand, &count, type );
return count;
}
/* accessor functions */
x86_op_t * x86_insn_t::x86_operand_1st() {
if (! explicit_count ) {
return NULL;
}
x86_op_t * x86_insn_t::operand_1st() {
if (! explicit_count ) {
return NULL;
}
return &(operands->op);
return &(operands->op);
}
x86_op_t * x86_insn_t::x86_operand_2nd( ) {
if ( explicit_count < 2 ) {
return NULL;
}
x86_op_t * x86_insn_t::operand_2nd( ) {
if ( explicit_count < 2 ) {
return NULL;
}
return &(operands->next->op);
return &(operands->next->op);
}
x86_op_t * x86_insn_t::x86_operand_3rd( ) {
if ( explicit_count < 3 ) {
return NULL;
}
return &(operands->next->next->op);
x86_op_t * x86_insn_t::operand_3rd( ) {
if ( explicit_count < 3 ) {
return NULL;
}
return &(operands->next->next->op);
}

View File

@ -1,38 +1,47 @@
PROJECT(dcc_original)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
cmake_minimum_required(VERSION 3.1)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
find_package(Qt5Core)
OPTION(dcc_build_tests "Enable unit tests." OFF)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS)
IF(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D_CRT_NONSTDC_NO_DEPRECATE)
#SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS)
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D_CRT_NONSTDC_NO_DEPRECATE -DNOMINMAX)
ADD_DEFINITIONS(/W4)
ELSE()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall --std=c++0x")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_GLIBCXX_DEBUG " ) #--coverage
#-D_GLIBCXX_DEBUG
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} " ) #--coverage
ENDIF()
SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts;${CMAKE_MODULE_PATH})
FIND_PACKAGE(LLVM)
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
include(cotire)
FIND_PACKAGE(Boost)
IF(dcc_build_tests)
enable_testing()
FIND_PACKAGE(GMock)
ENDIF()
ADD_SUBDIRECTORY(3rd_party)
llvm_map_components_to_libraries(REQ_LLVM_LIBRARIES jit native mc support)
INCLUDE_DIRECTORIES(
3rd_party/libdisasm
include
include/idioms
common
${Boost_INCLUDE_DIRS}
${LLVM_INCLUDE_DIRS}
)
set(dcc_SOURCES
src/dcc.cpp
ADD_SUBDIRECTORY(3rd_party)
ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(tools)
set(dcc_LIB_SOURCES
src/CallConvention.cpp
src/ast.cpp
src/backend.cpp
src/bundle.cpp
@ -41,13 +50,15 @@ set(dcc_SOURCES
src/control.cpp
src/dataflow.cpp
src/disassem.cpp
src/DccFrontend.cpp
src/error.cpp
src/fixwild.cpp
src/frontend.cpp
src/graph.cpp
src/hlicode.cpp
src/hltype.cpp
src/machine_x86.cpp
src/icode.cpp
src/RegisterNode
src/idioms.cpp
src/idioms/idiom1.cpp
src/idioms/arith_idioms.cpp
@ -58,8 +69,8 @@ set(dcc_SOURCES
src/idioms/shift_idioms.cpp
src/idioms/xor_idioms.cpp
src/locident.cpp
src/liveness_set.cpp
src/parser.cpp
src/perfhlib.cpp
src/procs.cpp
src/project.cpp
src/Procedure.cpp
@ -69,11 +80,17 @@ set(dcc_SOURCES
src/symtab.cpp
src/udm.cpp
src/BasicBlock.cpp
src/dcc_interface.cpp
)
set(dcc_SOURCES
src/dcc.cpp
)
set(dcc_HEADERS
include/ast.h
include/bundle.h
include/BinaryImage.h
include/DccFrontend.h
include/Enums.h
include/dcc.h
include/disassem.h
include/dosdcc.h
@ -92,7 +109,7 @@ set(dcc_HEADERS
include/idioms/shift_idioms.h
include/idioms/xor_idioms.h
include/locident.h
include/perfhlib.h
include/CallConvention.h
include/project.h
include/scanner.h
include/state.h
@ -101,14 +118,25 @@ set(dcc_HEADERS
include/Procedure.h
include/StackFrame.h
include/BasicBlock.h
include/dcc_interface.h
)
SOURCE_GROUP(Source FILES ${dcc_SOURCES})
SOURCE_GROUP(Headers FILES ${dcc_HEADERS})
ADD_LIBRARY(dcc_lib STATIC ${dcc_LIB_SOURCES} ${dcc_HEADERS})
qt5_use_modules(dcc_lib Core)
#cotire(dcc_lib)
ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS})
TARGET_LINK_LIBRARIES(dcc_original disasm_s ${REQ_LLVM_LIBRARIES})
ADD_DEPENDENCIES(dcc_original dcc_lib)
TARGET_LINK_LIBRARIES(dcc_original dcc_lib dcc_hash disasm_s)
qt5_use_modules(dcc_original Core)
SET_PROPERTY(TARGET dcc_original PROPERTY CXX_STANDARD 11)
SET_PROPERTY(TARGET dcc_original PROPERTY CXX_STANDARD_REQUIRED ON)
#ADD_SUBDIRECTORY(gui)
if(dcc_build_tests)
ADD_SUBDIRECTORY(src)
endif()

3392
CMakeScripts/cotire.cmake Normal file

File diff suppressed because it is too large Load Diff

339
LICENSE Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

129
Readme.md Normal file
View File

@ -0,0 +1,129 @@
I've fixed many issues in this codebase, among other things - memory reallocation during decompilation.
To reflect those fixes, I've edited the original readme a bit.
* * *
dcc Distribution
================
[![Join the chat at https://gitter.im/nemerle/dcc](https://badges.gitter.im/nemerle/dcc.svg)](https://gitter.im/nemerle/dcc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
The code provided in this distribution is (C) by their authors:
- Cristina Cifuentes (most of dcc code)
- Mike van Emmerik (signatures and prototype code)
- Jeff Ledermann (some disassembly code)
and is provided "as is". Additional contributor list is available
[on GitHub](https://github.com/nemerle/dcc/graphs/contributors).
The following files are included in the dccoo.tar.gz distribution:
- dcc.zip (dcc.exe DOS program, 1995)
- dccsrc.zip (source code *.c, *.h for dcc, 1993-1994)
- dcc32.zip (dcc_oo.exe 32 bit console (Win95/Win-NT) program, 1997)
- dccsrcoo.zip (source code *.cpp, *.h for "oo" dcc, 1993-1997)
- dccbsig.zip (library signatures for Borland C compilers, 1994)
- dccmsig.zip (library signatures for Microsoft C compilers, 1994)
- dcctpsig.zip (library signatures for Turbo Pascal compilers, 1994)
- dcclibs.dat (prototype file for C headers, 1994)
- test.zip (sample test files: *.c *.exe *.b, 1993-1996)
- makedsig.zip (creates a .sig file from a .lib C file, 1994)
- makedstp.zip (creates a .sig file from a Pascal library file, 1994)
- readsig.zip (reads signatures in a .sig file, 1994)
- dispsrch.zip (displays the name of a function given a signature, 1994)
- parsehdr.zip (generates a prototype file (dcclibs.dat) from C *.h files, 1994)
Note that the dcc_oo.exe program (in dcc32.zip) is a 32 bit program,
so it won't work under Windows 3.1. Also, it is a console mode program,
meaning that it has to be run in the "Command Prompt" window (sometimes
known as the "Dos Box"). It is not a GUI program.
The following files are included in the test.zip file: fibo,
benchsho, benchlng, benchfn, benchmul, byteops, intops, longops,
max, testlong, matrixmu, strlen, dhamp.
The version of dcc included in this distribution (dccsrcoo.zip and
dcc32.exe) is a bit better than the first release, but it is still
broken in some cases, and we do not have the time to work in this
project at present so we cannot provide any changes.
Comments on individual files:
- fibo (fibonacci): the small model (fibos.exe) decompiles correctly,
the large model (fibol.exe) expects an extra argument for
`scanf()`. This argument is the segment and is not displayed.
- benchsho: the first `scanf()` takes loc0 as an argument. This is
part of a long variable, but dcc does not have any clue at that
stage that the stack offset pushed on the stack is to be used
as a long variable rather than an integer variable.
- benchlng: as part of the `main()` code, `LO(loc1) | HI(loc1)` should
be displayed instead of `loc3 | loc9`. These two integer variables
are equivalent to the one long loc1 variable.
- benchfn: see benchsho.
- benchmul: see benchsho.
- byteops: decompiles correctly.
- intops: the du analysis for `DIV` and `MOD` is broken. dcc currently
generates code for a long and an integer temporary register that
were used as part of the analysis.
- longops: decompiles correctly.
- max: decompiles correctly.
- testlong: this example decompiles correctly given the algorithms
implemented in dcc. However, it shows that when long variables
are defined and used as integers (or long) without giving dcc
any hint that this is happening, the variable will be treated as
two integer variables. This is due to the fact that the assembly
code is in terms of integer registers, and long registers are not
available in 80286, so a long variable is equivalent to two integer
registers. dcc only knows of this through idioms such as add two
long variables.
- matrixmu: decompiles correctly. Shows that arrays are not supported
in dcc.
- strlen: decompiles correctly. Shows that pointers are partially
supported by dcc.
- dhamp: this program has far more data types than what dcc recognizes
at present.
Our thanks to Gary Shaffstall for some debugging work. Current bugs
are:
- [ ] if the code generated in the one line is too long, the (static)
buffer used for that line is clobbered. Solution: make the buffer
larger (currently 200 chars).
- [ ] the large memory model problem & `scanf()`
- [ ] dcc's error message shows a p option available which doesn't
exist, and doesn't show an i option which exists.
- [x] there is a nasty problem whereby some arrays can get reallocated
to a new address, and some pointers can become invalid. This mainly
tends to happen to larger executable files. A major rewrite will
probably be required to fix this.
For more information refer to the thesis "Reverse Compilation
Techniques" by Cristina Cifuentes, Queensland University of
Technology, 1994, and the dcc home page:
http://www.it.uq.edu.au/groups/csm/dcc_readme.html
Please note that the executable version of dcc provided in this
distribution does not necessarily match the source code provided,
some changes were done without us keeping track of every change.
Using dcc
---------
Here is a very brief summary of switches for dcc:
* `a1`, `a2`: assembler output, before and after re-ordering of input code
* `c`: Attempt to follow control through indirect call instructions
* `i`: Enter interactive disassembler
* `m`: Memory map
* `s`: Statistics summary
* `v`, `V`: verbose (and Very verbose)
* `o` filename: Use filename as assembler output file
If dcc encounters illegal instructions, it will attempt to enter the so called
interactive disassembler. The idea of this was to allow commands to fix the
problem so that dcc could continue, but no such changes are implemented
as yet. (Note: the Unix versions do not have the interactive disassembler). If
you get into this, you can get out of it by pressing `^X` (control-X). Once dcc
has entered the interactive disassembler, however, there is little chance that
it will recover and produce useful output.
If dcc loads the signature file `dccxxx.sig`, this means that it has not
recognised the compiler library used. You can place the signatures in a
different direcory to where you are working if you set the DCC environment
variable to point to their path. Note that if dcc can't find its signature
files, it will be severely handicapped.

View File

@ -1,6 +1,7 @@
#!/bin/bash
cd bld
make -j5
cd ..
#cd bld
#make -j5
#cd ..
mkdir -p tests/outputs
./test_use_base.sh
./regression_tester.rb ./bld/dcc_original -s -c 2>stderr >stdout; diff tests/prev/ tests/outputs/
./regression_tester.rb ./dcc_original -s -c 2>stderr >stdout; diff -wB tests/prev/ tests/outputs/

7
common/CMakeLists.txt Normal file
View File

@ -0,0 +1,7 @@
set(SRC
perfhlib.cpp
perfhlib.h
PatternCollector.h
)
add_library(dcc_hash STATIC ${SRC})

82
common/PatternCollector.h Normal file
View File

@ -0,0 +1,82 @@
#ifndef PATTERNCOLLECTOR
#define PATTERNCOLLECTOR
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <vector>
#define SYMLEN 16 /* Number of chars in the symbol name, incl null */
#define PATLEN 23 /* Number of bytes in the pattern part */
struct HASHENTRY
{
char name[SYMLEN]; /* The symbol name */
uint8_t pat [PATLEN]; /* The pattern */
uint16_t offset; /* Offset (needed temporarily) */
};
struct PatternCollector {
uint8_t buf[100], bufSave[7]; /* Temp buffer for reading the file */
uint16_t readShort(FILE *f)
{
uint8_t b1, b2;
if (fread(&b1, 1, 1, f) != 1)
{
printf("Could not read\n");
exit(11);
}
if (fread(&b2, 1, 1, f) != 1)
{
printf("Could not read\n");
exit(11);
}
return (b2 << 8) + b1;
}
void grab(FILE *f,int n)
{
if (fread(buf, 1, n, f) != (size_t)n)
{
printf("Could not read\n");
exit(11);
}
}
uint8_t readByte(FILE *f)
{
uint8_t b;
if (fread(&b, 1, 1, f) != 1)
{
printf("Could not read\n");
exit(11);
}
return b;
}
uint16_t readWord(FILE *fl)
{
uint8_t b1, b2;
b1 = readByte(fl);
b2 = readByte(fl);
return b1 + (b2 << 8);
}
/* Called by map(). Return the i+1th key in *pKeys */
uint8_t *getKey(int i)
{
return keys[i].pat;
}
/* Display key i */
void dispKey(int i)
{
printf("%s", keys[i].name);
}
std::vector<HASHENTRY> keys; /* array of keys */
virtual int readSyms(FILE *f)=0;
};
#endif // PATTERNCOLLECTOR

438
common/perfhlib.cpp Normal file
View File

@ -0,0 +1,438 @@
/*
*$Log: perfhlib.c,v $
* Revision 1.5 93/09/29 14:45:02 emmerik
* Oops, didn't do the casts last check in
*
* Revision 1.4 93/09/29 14:41:45 emmerik
* Added casts to mod instructions to keep the SVR4 compiler happy
*
*
* Perfect hashing function library. Contains functions to generate perfect
* hashing functions
*/
#include "perfhlib.h"
#include "PatternCollector.h"
#include "msvc_fixes.h"
#include <stdio.h>
#include <cassert>
#include <stdlib.h>
#include <string.h>
/* Private data structures */
//static int NumEntry; /* Number of entries in the hash table (# keys) */
//static int EntryLen; /* Size (bytes) of each entry (size of keys) */
//static int SetSize; /* Size of the char set */
//static char SetMin; /* First char in the set */
//static int NumVert; /* c times NumEntry */
//static uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */
static uint16_t *T1, *T2; /* Pointers to T1[i], T2[i] */
static int *graphNode; /* The array of edges */
static int *graphNext; /* Linked list of edges */
static int *graphFirst;/* First edge at a vertex */
static int numEdges; /* An edge counter */
static bool *visited; /* Array of bools: whether visited */
static bool *deleted; /* Array of bools: whether deleted */
/* Private prototypes */
static void duplicateKeys(int v1, int v2);
void PerfectHash::setHashParams(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,
int _NumVert)
{
/* These parameters are stored in statics so as to obviate the need for
passing all these (or defererencing pointers) for every call to hash()
*/
NumEntry = _NumEntry;
EntryLen = _EntryLen;
SetSize = _SetSize;
SetMin = _SetMin;
NumVert = _NumVert;
/* Allocate the variable sized tables etc */
if ((T1base = (uint16_t *)malloc(EntryLen * SetSize * sizeof(uint16_t))) == 0)
{
goto BadAlloc;
}
if ((T2base = (uint16_t *)malloc(EntryLen * SetSize * sizeof(uint16_t))) == 0)
{
goto BadAlloc;
}
if ((graphNode = (int *)malloc((NumEntry*2 + 1) * sizeof(int))) == 0)
{
goto BadAlloc;
}
if ((graphNext = (int *)malloc((NumEntry*2 + 1) * sizeof(int))) == 0)
{
goto BadAlloc;
}
if ((graphFirst = (int *)malloc((NumVert + 1) * sizeof(int))) == 0)
{
goto BadAlloc;
}
if ((g = (short *)malloc((NumVert+1) * sizeof(short))) == 0)
{
goto BadAlloc;
}
if ((visited = (bool *)malloc((NumVert+1) * sizeof(bool))) == 0)
{
goto BadAlloc;
}
if ((deleted = (bool *)malloc((NumEntry+1) * sizeof(bool))) == 0)
{
goto BadAlloc;
}
return;
BadAlloc:
printf("Could not allocate memory\n");
hashCleanup();
exit(1);
}
void PerfectHash::hashCleanup(void)
{
/* Free the storage for variable sized tables etc */
if (T1base) free(T1base);
if (T2base) free(T2base);
if (graphNode) free(graphNode);
if (graphNext) free(graphNext);
if (graphFirst) free(graphFirst);
if (g) free(g);
if (visited) free(visited);
if (deleted) free(deleted);
}
void PerfectHash::map(PatternCollector *collector)
{
m_collector = collector;
assert(nullptr!=collector);
int i, j, c;
uint16_t f1, f2;
bool cycle;
uint8_t *keys;
c = 0;
do
{
initGraph();
cycle = false;
/* Randomly generate T1 and T2 */
for (i=0; i < SetSize*EntryLen; i++)
{
T1base[i] = rand() % NumVert;
T2base[i] = rand() % NumVert;
}
for (i=0; i < NumEntry; i++)
{
f1 = 0; f2 = 0;
keys = m_collector->getKey(i);
for (j=0; j < EntryLen; j++)
{
T1 = T1base + j * SetSize;
T2 = T2base + j * SetSize;
f1 += T1[keys[j] - SetMin];
f2 += T2[keys[j] - SetMin];
}
f1 %= (uint16_t)NumVert;
f2 %= (uint16_t)NumVert;
if (f1 == f2)
{
/* A self loop. Reject! */
printf("Self loop on vertex %d!\n", f1);
cycle = true;
break;
}
addToGraph(numEdges++, f1, f2);
}
if (cycle or (cycle = isCycle())) /* OK - is there a cycle? */
{
printf("Iteration %d\n", ++c);
}
else
{
break;
}
}
while (/* there is a cycle */ 1);
}
/* Initialise the graph */
void PerfectHash::initGraph()
{
int i;
for (i=1; i <= NumVert; i++)
{
graphFirst[i] = 0;
}
for (i= -NumEntry; i <= NumEntry; i++)
{
/* No need to init graphNode[] as they will all be filled by successive
calls to addToGraph() */
graphNext[NumEntry+i] = 0;
}
numEdges = 0;
}
/* Add an edge e between vertices v1 and v2 */
/* e, v1, v2 are 0 based */
void PerfectHash::addToGraph(int e, int v1, int v2)
{
e++; v1++; v2++; /* So much more convenient */
graphNode[NumEntry+e] = v2; /* Insert the edge information */
graphNode[NumEntry-e] = v1;
graphNext[NumEntry+e] = graphFirst[v1]; /* Insert v1 to list of alphas */
graphFirst[v1]= e;
graphNext[NumEntry-e] = graphFirst[v2]; /* Insert v2 to list of omegas */
graphFirst[v2]= -e;
}
bool PerfectHash::DFS(int parentE, int v)
{
int e, w;
/* Depth first search of the graph, starting at vertex v, looking for
cycles. parent and v are origin 1. Note parent is an EDGE,
not a vertex */
visited[v] = true;
/* For each e incident with v .. */
for (e = graphFirst[v]; e; e = graphNext[NumEntry+e])
{
uint8_t *key1;
if (deleted[abs(e)])
{
/* A deleted key. Just ignore it */
continue;
}
key1 = m_collector->getKey(abs(e)-1);
w = graphNode[NumEntry+e];
if (visited[w])
{
/* Did we just come through this edge? If so, ignore it. */
if (abs(e) != abs(parentE))
{
/* There is a cycle in the graph. There is some subtle code here
to work around the distinct possibility that there may be
duplicate keys. Duplicate keys will always cause unit
cycles, since f1 and f2 (used to select v and w) will be the
same for both. The edges (representing an index into the
array of keys) are distinct, but the key values are not.
The logic is as follows: for the candidate edge e, check to
see if it terminates in the parent vertex. If so, we test
the keys associated with e and the parent, and if they are
the same, we can safely ignore e for the purposes of cycle
detection, since edge e adds nothing to the cycle. Cycles
involving v, w, and e0 will still be found. The parent
edge was not similarly eliminated because at the time when
it was a candidate, v was not yet visited.
We still have to remove the key from further consideration,
since each edge is visited twice, but with a different
parent edge each time.
*/
/* We save some stack space by calculating the parent vertex
for these relatively few cases where it is needed */
int parentV = graphNode[NumEntry-parentE];
if (w == parentV)
{
uint8_t *key2;
key2=m_collector->getKey(abs(parentE)-1);
if (memcmp(key1, key2, EntryLen) == 0)
{
printf("Duplicate keys with edges %d and %d (",
e, parentE);
m_collector->dispKey(abs(e)-1);
printf(" & ");
m_collector->dispKey(abs(parentE)-1);
printf(")\n");
deleted[abs(e)] = true; /* Wipe the key */
}
else
{
/* A genuine (unit) cycle. */
printf("There is a unit cycle involving vertex %d and edge %d\n", v, e);
return true;
}
}
else
{
/* We have reached a previously visited vertex not the
parent. Therefore, we have uncovered a genuine cycle */
printf("There is a cycle involving vertex %d and edge %d\n", v, e);
return true;
}
}
}
else /* Not yet seen. Traverse it */
{
if (DFS(e, w))
{
/* Cycle found deeper down. Exit */
return true;
}
}
}
return false;
}
bool PerfectHash::isCycle(void)
{
int v, e;
for (v=1; v <= NumVert; v++)
{
visited[v] = false;
}
for (e=1; e <= NumEntry; e++)
{
deleted[e] = false;
}
for (v=1; v <= NumVert; v++)
{
if (not visited[v])
{
if (DFS(-32767, v))
{
return true;
}
}
}
return false;
}
void PerfectHash::traverse(int u)
{
int w, e;
visited[u] = true;
/* Find w, the neighbours of u, by searching the edges e associated with u */
e = graphFirst[1+u];
while (e)
{
w = graphNode[NumEntry+e]-1;
if (not visited[w])
{
g[w] = (abs(e)-1 - g[u]) % NumEntry;
if (g[w] < 0) g[w] += NumEntry; /* Keep these positive */
traverse(w);
}
e = graphNext[NumEntry+e];
}
}
void PerfectHash::assign(void)
{
int v;
for (v=0; v < NumVert; v++)
{
g[v] = 0; /* g is sparse; leave the gaps 0 */
visited[v] = false;
}
for (v=0; v < NumVert; v++)
{
if (not visited[v])
{
g[v] = 0;
traverse(v);
}
}
}
int PerfectHash::hash(uint8_t *string)
{
uint16_t u, v;
int j;
u = 0;
for (j=0; j < EntryLen; j++)
{
T1 = T1base + j * SetSize;
u += T1[string[j] - SetMin];
}
u %= NumVert;
v = 0;
for (j=0; j < EntryLen; j++)
{
T2 = T2base + j * SetSize;
v += T2[string[j] - SetMin];
}
v %= NumVert;
return (g[u] + g[v]) % NumEntry;
}
#if 0
void dispRecord(int i);
void
duplicateKeys(int v1, int v2)
{
int i, j;
uint8_t *keys;
int u, v;
v1--; v2--; /* These guys are origin 1 */
printf("Duplicate keys:\n");
for (i=0; i < NumEntry; i++)
{
getKey(i, &keys);
u = 0;
for (j=0; j < EntryLen; j++)
{
T1 = T1base + j * SetSize;
u += T1[keys[j] - SetMin];
}
u %= NumVert;
if ((u != v1) and (u != v2)) continue;
v = 0;
for (j=0; j < EntryLen; j++)
{
T2 = T2base + j * SetSize;
v += T2[keys[j] - SetMin];
}
v %= NumVert;
if ((v == v2) or (v == v1))
{
printf("Entry #%d key: ", i+1);
for (j=0; j < EntryLen; j++) printf("%02X ", keys[j]);
printf("\n");
dispRecord(i+1);
}
}
exit(1);
}
#endif

38
common/perfhlib.h Normal file
View File

@ -0,0 +1,38 @@
#pragma once
#include <stdint.h>
/** Perfect hashing function library. Contains functions to generate perfect
hashing functions */
struct PatternCollector;
struct PerfectHash {
uint16_t *T1base;
uint16_t *T2base; /* Pointers to start of T1, T2 */
short *g; /* g[] */
int NumEntry; /* Number of entries in the hash table (# keys) */
int EntryLen; /* Size (bytes) of each entry (size of keys) */
int SetSize; /* Size of the char set */
char SetMin; /* First char in the set */
int NumVert; /* c times NumEntry */
/** Set the parameters for the hash table */
void setHashParams(int _numEntry, int _entryLen, int _setSize, char _setMin, int _numVert);
public:
void map(PatternCollector * collector); /* Part 1 of creating the tables */
void hashCleanup(); /* Frees memory allocated by setHashParams() */
void assign(); /* Part 2 of creating the tables */
int hash(uint8_t *string); /* Hash the string to an int 0 .. NUMENTRY-1 */
const uint16_t *readT1(void) const { return T1base; }
const uint16_t *readT2(void) const { return T2base; }
const uint16_t *readG(void) const { return (uint16_t *)g; }
uint16_t *readT1(void){ return T1base; }
uint16_t *readT2(void){ return T2base; }
uint16_t *readG(void) { return (uint16_t *)g; }
private:
void initGraph();
void addToGraph(int e, int v1, int v2);
bool isCycle();
bool DFS(int parentE, int v);
void traverse(int u);
PatternCollector *m_collector; /* used to retrieve the keys */
};

View File

@ -1,3 +1,4 @@
#!/bin/bash
makedir -p tests/outputs
./test_use_all.sh
./regression_tester.rb ./bld/dcc_original -s -c 2>stderr >stdout; diff tests/prev/ tests/outputs/
./regression_tester.rb ./dcc_original -s -c 2>stderr >stdout; diff -wB tests/prev/ tests/outputs/

View File

@ -3,9 +3,7 @@
#include <vector>
#include <bitset>
#include <string>
#include <llvm/ADT/ilist.h>
#include <llvm/ADT/ilist_node.h>
#include <boost/range.hpp>
#include <boost/range/iterator_range.hpp>
#include "icode.h"
#include "types.h"
#include "graph.h"
@ -16,24 +14,28 @@ class CIcodeRec;
struct BB;
struct LOCAL_ID;
struct interval;
//TODO: consider default address value -> INVALID
struct TYPEADR_TYPE
{
uint32_t ip; /* Out edge icode address */
BB * BBptr; /* Out edge pointer to next BB */
interval *intPtr; /* Out edge ptr to next interval*/
TYPEADR_TYPE(uint32_t addr=0) : ip(addr),BBptr(nullptr),intPtr(nullptr)
{}
TYPEADR_TYPE(interval *v) : ip(0),BBptr(nullptr),intPtr(v)
{}
};
struct BB : public llvm::ilist_node<BB>
struct BB
{
friend struct Function;
private:
BB(const BB&);
BB() : nodeType(0),traversed(DFS_NONE),
numHlIcodes(0),flg(0),
inEdges(0),
edges(0),beenOnH(0),inEdgeCount(0),reachingInt(0),
inInterval(0),correspInt(0),liveUse(0),def(0),liveIn(0),liveOut(0),
dfsFirstNum(0),dfsLastNum(0),immedDom(0),ifFollow(0),loopType(0),latchNode(0),
inInterval(0),correspInt(0),
dfsFirstNum(0),dfsLastNum(0),immedDom(0),ifFollow(0),loopType(NO_TYPE),latchNode(0),
numBackEdges(0),loopHead(0),loopFollow(0),caseHead(0),caseTail(0),index(0)
{
@ -41,6 +43,7 @@ private:
//friend class SymbolTableListTraits<BB, Function>;
typedef boost::iterator_range<iICODE> rCODE;
rCODE instructions;
rCODE &my_range() {return instructions;}
public:
struct ValidFunctor
@ -54,10 +57,10 @@ public:
ICODE &front();
ICODE &back();
size_t size();
uint8_t nodeType; /* Type of node */
eDFS traversed; /* last traversal id is held here traversed yet? */
int numHlIcodes; /* No. of high-level icodes */
uint32_t flg; /* BB flags */
uint8_t nodeType; /* Type of node */
eDFS traversed; /* last traversal id is held here traversed yet? */
int numHlIcodes; /* No. of high-level icodes */
uint32_t flg; /* BB flags */
/* In edges and out edges */
std::vector<BB *> inEdges; // does not own held pointers
@ -72,36 +75,31 @@ public:
interval *inInterval; /* Node's interval */
/* For derived sequence construction */
interval *correspInt; /* Corresponding interval in
* derived graph Gi-1 */
/* For live register analysis
* LiveIn(b) = LiveUse(b) U (LiveOut(b) - Def(b)) */
std::bitset<32> liveUse; /* LiveUse(b) */
std::bitset<32> def; /* Def(b) */
std::bitset<32> liveIn; /* LiveIn(b) */
std::bitset<32> liveOut; /* LiveOut(b) */
interval *correspInt; //!< Corresponding interval in derived graph Gi-1
// For live register analysis
// LiveIn(b) = LiveUse(b) U (LiveOut(b) - Def(b))
LivenessSet liveUse; /* LiveUse(b) */
LivenessSet def; /* Def(b) */
LivenessSet liveIn; /* LiveIn(b) */
LivenessSet liveOut; /* LiveOut(b) */
/* For structuring analysis */
int dfsFirstNum; /* DFS #: first visit of node */
int dfsLastNum; /* DFS #: last visit of node */
int immedDom; /* Immediate dominator (dfsLast
* index) */
int immedDom; /* Immediate dominator (dfsLast index) */
int ifFollow; /* node that ends the if */
int loopType; /* Type of loop (if any) */
eNodeHeaderType loopType; /* Type of loop (if any) */
int latchNode; /* latching node of the loop */
int numBackEdges; /* # of back edges */
int loopHead; /* most nested loop head to which
* thcis node belongs (dfsLast) */
size_t numBackEdges; /* # of back edges */
int loopHead; /* most nested loop head to which this node belongs (dfsLast) */
int loopFollow; /* node that follows the loop */
int caseHead; /* most nested case to which this
node belongs (dfsLast) */
int caseHead; /* most nested case to which this node belongs (dfsLast) */
int caseTail; /* tail node for the case */
int index; /* Index, used in several ways */
static BB * Create(void *ctx=0,const std::string &s="",Function *parent=0,BB *insertBefore=0);
static BB * Create(int start, int ip, uint8_t nodeType, int numOutEdges, Function * parent);
static BB * Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, Function *parent);
static BB * CreateIntervalBB(Function *parent);
static BB * Create(const rCODE &r, eBBKind _nodeType, Function *parent);
void writeCode(int indLevel, Function *pProc, int *numLoc, int latchNode, int ifFollow);
void mergeFallThrough(CIcodeRec &Icode);
void dfsNumbering(std::vector<BB *> &dfsLast, int *first, int *last);
@ -111,21 +109,26 @@ public:
///
const Function *getParent() const { return Parent; }
Function *getParent() { return Parent; }
void writeBB(std::ostream &ostr, int lev, Function *pProc, int *numLoc);
void writeBB(QTextStream & ostr, int lev, Function *pProc, int *numLoc);
BB * rmJMP(int marker, BB *pBB);
void genDU1();
int findBBExps(LOCAL_ID &locals, Function *f);
void findBBExps(LOCAL_ID &locals, Function *f);
bool valid() {return 0==(flg & INVALID_BB); }
bool wasTraversedAtLevel(int l) const {return traversed==l;}
ICODE * writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, boolT &repCond);
void addOutEdge(uint32_t ip) // TODO: fix this
ICODE * writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, bool &repCond);
void addOutEdge(uint32_t ip) // TODO: fix this
{
edges[0].ip = ip;
edges.push_back(TYPEADR_TYPE(ip));
}
void addOutEdgeInterval(interval *i) // TODO: fix this
{
edges.push_back(TYPEADR_TYPE(i));
}
void RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode);
private:
bool FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at);
void ProcessUseDefForFunc(eReg regi, int defRegIdx, iICODE picode);
void ProcessUseDefForFunc(eReg regi, int defRegIdx, ICODE &picode);
bool isEndOfPath(int latch_node_idx) const;
Function *Parent;

View File

@ -1,20 +1,25 @@
#pragma once
#include <stdint.h>
#include <vector>
struct PROG /* Loaded program image parameters */
{
int16_t initCS;
int16_t initIP; /* These are initial load values */
int16_t initSS; /* Probably not of great interest */
uint16_t initSP;
bool fCOM; /* Flag set if COM program (else EXE)*/
int cReloc; /* No. of relocation table entries */
uint32_t * relocTable; /* Ptr. to relocation table */
uint8_t * map; /* Memory bitmap ptr */
int cProcs; /* Number of procedures so far */
int offMain; /* The offset of the main() proc */
uint16_t segMain; /* The segment of the main() proc */
bool bSigs; /* True if signatures loaded */
int cbImage; /* Length of image in bytes */
uint8_t * Image; /* Allocated by loader to hold entire program image */
uint16_t initCS=0;
uint16_t initIP=0; /* These are initial load values */
uint16_t initSS=0; /* Probably not of great interest */
uint16_t initSP=0;
bool fCOM=false; /* Flag set if COM program (else EXE)*/
int cReloc=0; /* No. of relocation table entries */
std::vector<uint32_t> relocTable; /* Ptr. to relocation table */
uint8_t * map=nullptr; /* Memory bitmap ptr */
int cProcs=0; /* Number of procedures so far */
int offMain=0; /* The offset of the main() proc */
uint16_t segMain=0; /* The segment of the main() proc */
bool bSigs=false; /* True if signatures loaded */
int cbImage=0; /* Length of image in bytes */
uint8_t * Imagez=nullptr; /* Allocated by loader to hold entire program image */
int addressingMode=0;
public:
const uint8_t *image() const {return Imagez;}
void displayLoadInfo();
};

33
include/CallConvention.h Normal file
View File

@ -0,0 +1,33 @@
#pragma once
#include "ast.h"
class QTextStream;
struct CConv {
enum Type {
eUnknown=0,
eCdecl,
ePascal
};
virtual void processHLI(Function *func, Expr *_exp, iICODE picode)=0;
virtual void writeComments(QTextStream &)=0;
static CConv * create(Type v);
protected:
};
struct C_CallingConvention : public CConv {
virtual void processHLI(Function *func, Expr *_exp, iICODE picode);
virtual void writeComments(QTextStream &);
private:
int processCArg(Function *callee, Function *pProc, ICODE *picode, size_t numArgs);
};
struct Pascal_CallingConvention : public CConv {
virtual void processHLI(Function *func, Expr *_exp, iICODE picode);
virtual void writeComments(QTextStream &);
};
struct Unknown_CallingConvention : public CConv {
void processHLI(Function *func, Expr *_exp, iICODE picode) {}
virtual void writeComments(QTextStream &);
};

19
include/CallGraph.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include "Procedure.h"
/* CALL GRAPH NODE */
struct CALL_GRAPH
{
ilFunction proc; /* Pointer to procedure in pProcList */
std::vector<CALL_GRAPH *> outEdges; /* array of out edges */
public:
void write();
CALL_GRAPH()
{
}
public:
void writeNodeCallGraph(int indIdx);
bool insertCallGraph(ilFunction caller, ilFunction callee);
bool insertCallGraph(Function *caller, ilFunction callee);
void insertArc(ilFunction newProc);
};
//extern CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */

17
include/DccFrontend.h Normal file
View File

@ -0,0 +1,17 @@
#pragma once
#include <QObject>
class Project;
class DccFrontend : public QObject
{
Q_OBJECT
void LoadImage();
void parse(Project &proj);
std::string m_fname;
public:
explicit DccFrontend(QObject *parent = 0);
bool FrontEnd(); /* frontend.c */
signals:
public slots:
};

View File

@ -8,6 +8,7 @@ enum regType
};
enum condId
{
UNDEF=0,
GLOB_VAR, /* global variable */
REGISTER, /* register */
LOCAL_VAR, /* negative disp */
@ -31,19 +32,19 @@ enum condOp
GREATER_EQUAL, /* >= */
/* For general expressions */
AND, /* & */
OR, /* | */
XOR, /* ^ */
NOT, /* ~ */ /* 1's complement */
ADD, /* + */
SUB, /* - */
MUL, /* * */
DIV, /* / */
SHR, /* >> */
SHL, /* << */
MOD, /* % */
DBL_AND, /* && */
DBL_OR, /* || */
DUMMY /* */
OR, /* | */
XOR, /* ^ */
NOT, /* ~ */ /* 1's complement */
ADD, /* + */
SUB, /* - */
MUL, /* * */
DIV, /* / */
SHR, /* >> */
SHL, /* << */
MOD, /* % */
DBL_AND, /* && */
DBL_OR, /* || */
DUMMY /* */
};
/* LOW_LEVEL operand location: source or destination */
enum opLoc
@ -57,48 +58,48 @@ enum opLoc
enum eLLFlags
{
B =0x0000001, /* uint8_t operands (value implicitly used) */
I =0x0000002, /* Immed. source */
NOT_HLL =0x0000004, /* Not HLL inst. */
FLOAT_OP =0x0000008, /* ESC or WAIT */
SEG_IMMED =0x0000010, /* Number is relocated segment value */
IMPURE =0x0000020, /* Instruction modifies code */
WORD_OFF =0x0000040, /* Inst has uint16_t offset ie.could be address */
TERMINATES =0x0000080, /* Instruction terminates program */
CASE =0x0000100, /* Label as case part of switch */
SWITCH =0x0000200, /* Treat indirect JMP as switch stmt */
TARGET =0x0000400, /* Jump target */
SYNTHETIC =0x0000800, /* Synthetic jump instruction */
NO_LABEL =0x0001000, /* Immed. jump cannot be linked to a label */
NO_CODE =0x0002000, /* Hole in Icode array */
SYM_USE =0x0004000, /* Instruction uses a symbol */
SYM_DEF =0x0008000, /* Instruction defines a symbol */
NO_SRC =0x0010000, /* Opcode takes no source */
NO_OPS =0x0020000, /* Opcode takes no operands */
IM_OPS =0x0040000, /* Opcode takes implicit operands */
SRC_B =0x0080000, /* Source operand is uint8_t (dest is uint16_t) */
HLL_LABEL =0x0100000, /* Icode has a high level language label */
IM_DST =0x0200000, /* Implicit DST for opcode (SIGNEX) */
IM_SRC =0x0400000, /* Implicit SRC for opcode (dx:ax) */
IM_TMP_DST =0x0800000, /* Implicit rTMP DST for opcode (DIV/IDIV) */
JMP_ICODE =0x1000000, /* Jmp dest immed.op converted to icode index */
JX_LOOP =0x2000000, /* Cond jump is part of loop conditional exp */
REST_STK =0x4000000 /* Stack needs to be restored after CALL */
B = 0x0000001, /* uint8_t operands (value implicitly used) */
I = 0x0000002, /* Immed. source */
NOT_HLL = 0x0000004, /* Not HLL inst. */
FLOAT_OP = 0x0000008, /* ESC or WAIT */
SEG_IMMED = 0x0000010, /* Number is relocated segment value */
IMPURE = 0x0000020, /* Instruction modifies code */
WORD_OFF = 0x0000040, /* Inst has uint16_t offset ie.could be address */
TERMINATES = 0x0000080, /* Instruction terminates program */
CASE = 0x0000100, /* Label as case part of switch */
SWITCH = 0x0000200, /* Treat indirect JMP as switch stmt */
TARGET = 0x0000400, /* Jump target */
SYNTHETIC = 0x0000800, /* Synthetic jump instruction */
NO_LABEL = 0x0001000, /* Immed. jump cannot be linked to a label */
NO_CODE = 0x0002000, /* Hole in Icode array */
SYM_USE = 0x0004000, /* Instruction uses a symbol */
SYM_DEF = 0x0008000, /* Instruction defines a symbol */
NO_SRC = 0x0010000, /* Opcode takes no source */
NO_OPS = 0x0020000, /* Opcode takes no operands */
IM_OPS = 0x0040000, /* Opcode takes implicit operands */
SRC_B = 0x0080000, /* Source operand is uint8_t (dest is uint16_t) */
HLL_LABEL = 0x0100000, /* Icode has a high level language label */
IM_DST = 0x0200000, /* Implicit DST for opcode (SIGNEX) */
IM_SRC = 0x0400000, /* Implicit SRC for opcode (dx:ax) */
IM_TMP_DST = 0x0800000, /* Implicit rTMP DST for opcode (DIV/IDIV) */
JMP_ICODE = 0x1000000, /* Jmp dest immed.op converted to icode index */
JX_LOOP = 0x2000000, /* Cond jump is part of loop conditional exp */
REST_STK = 0x4000000 /* Stack needs to be restored after CALL */
#define ICODEMASK 0x0FF00FF /* Masks off parser flags */
};
/* Types of icodes */
enum icodeType
{
NOT_SCANNED = 0, // not even scanned yet
LOW_LEVEL, // low-level icode
HIGH_LEVEL // high-level icode
NOT_SCANNED_ICODE = 0, // not even scanned yet
LOW_LEVEL_ICODE, // low-level icode
HIGH_LEVEL_ICODE // high-level icode
};
/* LOW_LEVEL icode opcodes */
enum llIcode
{
//iINVALID,
iINVALID=-1,
iCBW, /* 0 */
iAAA,
iAAD,
@ -176,7 +177,7 @@ enum llIcode
iPOP,
iPOPA,
iPOPF,
iPUSH,
iPUSH, // 77
iPUSHA,
iPUSHF,
iRCL, /* 80 */
@ -216,6 +217,7 @@ enum condNodeType
{
UNKNOWN_OP=0,
BOOLEAN_OP, /* condOps */
NEGATION, /* not (2's complement) */
ADDRESSOF, /* addressOf (&) */
DEREFERENCE, /* contents of (*) */
@ -237,7 +239,7 @@ enum hlFirst
/* HIGH_LEVEL icodes opcodes */
enum hlIcode
{
HLI_INVALID,
HLI_INVALID=0,
HLI_ASSIGN, /* := */
HLI_CALL, /* Call procedure */
HLI_JCOND, /* Conditional jump */

View File

@ -2,32 +2,29 @@
#include "ast.h"
#include "types.h"
#include "machine_x86.h"
struct GlobalVariable;
struct AstIdent;
struct IDENTTYPE
{
friend struct GlobalVariable;
friend struct Constant;
friend struct AstIdent;
protected:
condId idType;
regType regiType; /* for REGISTER only */
public:
condId type() {return idType;}
void type(condId t) {idType=t;}
union _idNode {
int regiIdx; /* index into localId, REGISTER */
int globIdx; /* index into symtab for GLOB_VAR */
int localIdx; /* idx into localId, LOCAL_VAR */
int paramIdx; /* idx into args symtab, PARAMS */
int idxGlbIdx; /* idx into localId, GLOB_VAR_IDX */
struct _kte
{ /* for CONSTANT only */
uint32_t kte; /* value of the constant */
uint8_t size; /* #bytes size constant */
} kte;
uint32_t strIdx; /* idx into image, for STRING */
int longIdx; /* idx into LOCAL_ID table, LONG_VAR*/
struct _call { /* for FUNCTION only */
Function *proc;
STKFRAME *args;
} call;
struct { /* for OTHER; tmp struct */
eReg seg; /* segment */
eReg regi; /* index mode */
int16_t off; /* offset */
} other;
} idNode;
IDENTTYPE() : idType(UNDEF)
{}
};

View File

@ -1,46 +1,28 @@
#pragma once
#include <llvm/ADT/ilist.h>
#include <llvm/ADT/ilist_node.h>
#include <bitset>
#include "BasicBlock.h"
#include "locident.h"
#include "state.h"
#include "icode.h"
#include "StackFrame.h"
#include "CallConvention.h"
#include <QtCore/QString>
#include <bitset>
#include <map>
class QIODevice;
class QTextStream;
/* PROCEDURE NODE */
struct CALL_GRAPH;
struct COND_EXPR;
struct Expr;
struct Disassembler;
struct Function;
struct CALL_GRAPH;
struct PROG;
typedef llvm::iplist<Function> FunctionListType;
typedef FunctionListType lFunction;
typedef lFunction::iterator ilFunction;
struct Function;
namespace llvm
{
// Traits for intrusive list of basic blocks...
template<>
struct ilist_traits<BB> : public ilist_default_traits<BB>
{
// createSentinel is used to get hold of the node that marks the end of the
// list... (same trick used here as in ilist_traits<Instruction>)
BB *createSentinel() const {
return static_cast<BB*>(&Sentinel);
}
static void destroySentinel(BB*) {}
BB *provideInitialHead() const { return createSentinel(); }
BB *ensureHead(BB*) const { return createSentinel(); }
static void noteHead(BB*, BB*) {}
//static ValueSymbolTable *getSymTab(Function *ItemParent);
private:
mutable ilist_half_node<BB> Sentinel;
};
}
/* Procedure FLAGS */
enum PROC_FLAGS
{
@ -48,9 +30,9 @@ enum PROC_FLAGS
PROC_IJMP =0x00000200,/* Proc incomplete due to indirect jmp */
PROC_ICALL =0x00000400, /* Proc incomplete due to indirect call */
PROC_HLL =0x00001000, /* Proc is likely to be from a HLL */
CALL_PASCAL =0x00002000, /* Proc uses Pascal calling convention */
CALL_C =0x00004000, /* Proc uses C calling convention */
CALL_UNKNOWN=0x00008000, /* Proc uses unknown calling convention */
// CALL_PASCAL =0x00002000, /* Proc uses Pascal calling convention */
// CALL_C =0x00004000, /* Proc uses C calling convention */
// CALL_UNKNOWN=0x00008000, /* Proc uses unknown calling convention */
PROC_NEAR =0x00010000, /* Proc exits with near return */
PROC_FAR =0x00020000, /* Proc exits with far return */
GRAPH_IRRED =0x00100000, /* Proc generates an irreducible graph */
@ -58,24 +40,24 @@ enum PROC_FLAGS
DI_REGVAR =0x00400000, /* DI is used as a stack variable */
PROC_IS_FUNC=0x00800000, /* Proc is a function */
REG_ARGS =0x01000000, /* Proc has registers as arguments */
PROC_VARARG =0x02000000, /* Proc has variable arguments */
// PROC_VARARG =0x02000000, /* Proc has variable arguments */
PROC_OUTPUT =0x04000000, /* C for this proc has been output */
PROC_RUNTIME=0x08000000, /* Proc is part of the runtime support */
PROC_ISLIB =0x10000000, /* Proc is a library function */
PROC_ASM =0x20000000, /* Proc is an intrinsic assembler routine */
PROC_IS_HLL =0x40000000 /* Proc has HLL prolog code */
#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
//#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
};
struct FunctionType
{
bool m_vararg;
bool m_vararg=false;
bool isVarArg() const {return m_vararg;}
};
struct Assignment
{
COND_EXPR *lhs;
COND_EXPR *rhs;
Expr *lhs;
Expr *rhs;
};
struct JumpTable
{
@ -86,61 +68,92 @@ struct JumpTable
size_t entrySize() { return 2;}
void pruneEntries(uint16_t cs);
};
struct Function : public llvm::ilist_node<Function>
class FunctionCfg
{
typedef llvm::iplist<BB> BasicBlockListType;
std::list<BB*> m_listBB; /* Ptr. to BB list/CFG */
public:
typedef std::list<BB*>::iterator iterator;
iterator begin() {
return m_listBB.begin();
}
iterator end() {
return m_listBB.end();
}
BB * &front() { return m_listBB.front();}
void nodeSplitting()
{
/* Converts the irreducible graph G into an equivalent reducible one, by
* means of node splitting. */
fprintf(stderr,"Attempt to perform node splitting: NOT IMPLEMENTED\n");
}
void push_back(BB *v) { m_listBB.push_back(v);}
};
struct Function
{
typedef std::list<BB *> BasicBlockListType;
// BasicBlock iterators...
typedef BasicBlockListType::iterator iterator;
typedef BasicBlockListType::const_iterator const_iterator;
private:
protected:
BasicBlockListType BasicBlocks; ///< The basic blocks
Function(FunctionType */*ty*/) : procEntry(0),depth(0),flg(0),cbParam(0),m_dfsLast(0),numBBs(0),
hasCase(false),liveAnal(0)
{
type = new FunctionType;
callingConv(CConv::eUnknown);
}
public:
FunctionType * type;
CConv * m_call_conv;
uint32_t procEntry; /* label number */
std::string name; /* Meaningful name for this proc */
STATE state; /* Entry state */
QString name; /* Meaningful name for this proc */
STATE state; /* Entry state */
int depth; /* Depth at which we found it - for printing */
uint32_t flg; /* Combination of Icode & Proc flags */
int16_t cbParam; /* Probable no. of bytes of parameters */
uint32_t flg; /* Combination of Icode & Proc flags */
int16_t cbParam; /* Probable no. of bytes of parameters */
STKFRAME args; /* Array of arguments */
LOCAL_ID localId; /* Local identifiers */
ID retVal; /* Return value - identifier */
/* Icodes and control flow graph */
CIcodeRec Icode; /* Object with ICODE records */
std::list<BB*> m_cfg; /* Ptr. to BB list/CFG */
FunctionCfg m_actual_cfg;
std::vector<BB*> m_dfsLast;
std::list<BB*> heldBBs;
//BB * *dfsLast; /* Array of pointers to BBs in dfsLast
std::map<int,BB*> m_ip_to_bb;
// * (reverse postorder) order */
size_t numBBs; /* Number of BBs in the graph cfg */
bool hasCase; /* Procedure has a case node */
/* For interprocedural live analysis */
std::bitset<32> liveIn; /* Registers used before defined */
std::bitset<32> liveOut; /* Registers that may be used in successors */
bool liveAnal; /* Procedure has been analysed already */
LivenessSet liveIn; /* Registers used before defined */
LivenessSet liveOut; /* Registers that may be used in successors */
bool liveAnal; /* Procedure has been analysed already */
Function(void *ty=0) : procEntry(0),depth(0),flg(0),cbParam(0),m_cfg(0),m_dfsLast(0),numBBs(0),
hasCase(false),liveIn(0),liveOut(0),liveAnal(0)//,next(0),prev(0)
{
virtual ~Function() {
delete type;
}
public:
static Function *Create(void *ty=0,int Linkage=0,const std::string &nm="",void *module=0)
static Function *Create(FunctionType *ty=0,int /*Linkage*/=0,const QString &nm="",void */*module*/=0)
{
Function *r=new Function(ty);
r->name = nm;
return r;
}
bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;}
FunctionType *getFunctionType() const {
return type;
}
CConv *callingConv() const { return m_call_conv;}
void callingConv(CConv::Type v);
// bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;}
bool hasRegArgs() const { return (flg & REG_ARGS)!=0;}
bool isLibrary() const { return (flg & PROC_ISLIB)!=0;}
void compoundCond();
void writeProcComments();
void lowLevelAnalysis();
void bindIcodeOff();
void dataFlow(std::bitset<32> &liveOut);
void dataFlow(LivenessSet &liveOut);
void compressCFG();
void highLevelGen();
void structure(derSeq *derivedG);
@ -151,22 +164,27 @@ public:
void FollowCtrl(CALL_GRAPH *pcallGraph, STATE *pstate);
void process_operands(ICODE &pIcode, STATE *pstate);
bool process_JMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
boolT process_CALL(ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
bool process_CALL(ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
void freeCFG();
void codeGen(std::ostream &fs);
void codeGen(QIODevice & fs);
void mergeFallThrough(BB *pBB);
void structIfs();
void structLoops(derSeq *derivedG);
void buildCFG(Disassembler &ds);
void controlFlowAnalysis();
void newRegArg(iICODE picode, iICODE ticode);
void writeProcComments(std::ostream &ostr);
void writeProcComments(QTextStream & ostr);
void displayCFG();
void displayStats();
void processHliCall(COND_EXPR *exp, iICODE picode);
void processHliCall(Expr *exp, iICODE picode);
void preprocessReturnDU(std::bitset<32> &_liveOut);
void preprocessReturnDU(LivenessSet &_liveOut);
Expr * adjustActArgType(Expr *_exp, hlType forType);
QString writeCall(Function *tproc, STKFRAME &args, int *numLoc);
void processDosInt(STATE *pstate, PROG &prog, bool done);
ICODE *translate_DIV(LLInst *ll, ICODE &_Icode);
ICODE *translate_XCHG(LLInst *ll, ICODE &_Icode);
protected:
void extractJumpTableRange(ICODE& pIcode, STATE *pstate, JumpTable &table);
bool followAllTableEntries(JumpTable &table, uint32_t cs, ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
@ -190,10 +208,18 @@ protected:
void findExps();
void genDU1();
void elimCondCodes();
void liveRegAnalysis(std::bitset<32> &in_liveOut);
void liveRegAnalysis(LivenessSet &in_liveOut);
void findIdioms();
void propLong();
void genLiveKtes();
uint8_t findDerivedSeq (derSeq &derivedGi);
bool findDerivedSeq(derSeq &derivedGi);
bool nextOrderGraph(derSeq &derivedGi);
void addOutEdgesForConditionalJump(BB* pBB, int next_ip, LLInst *ll);
private:
bool decodeIndirectJMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
bool decodeIndirectJMP2(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
};
typedef std::list<Function> FunctionListType;
typedef FunctionListType lFunction;
typedef lFunction::iterator ilFunction;

View File

@ -13,7 +13,7 @@ struct STKFRAME : public SymbolTableCommon<STKSYM>
int16_t maxOff; /* Maximum offset in stack frame*/
int cb; /* Number of bytes in arguments */
int numArgs; /* No. of arguments in the table*/
void adjustForArgType(int numArg_, hlType actType_);
void adjustForArgType(size_t numArg_, hlType actType_);
STKFRAME() : m_minOff(0),maxOff(0),cb(0),numArgs(0)
{

View File

@ -5,10 +5,15 @@
* (C) Cristina Cifuentes
*/
#pragma once
#include "Enums.h"
#include "msvc_fixes.h"
#include <boost/range/iterator_range.hpp>
#include <stdint.h>
#include <cstring>
#include <list>
#include "Enums.h"
#include <boost/range.hpp>
static const int operandSize=20;
/* The following definitions and types define the Conditional Expression
* attributed syntax tree, as defined by the following EBNF:
@ -20,131 +25,164 @@ static const int operandSize=20;
*/
/* High-level BOOLEAN conditions for iJB..iJNS icodes */
static const condOp condOpJCond[12] = {LESS, LESS_EQUAL, GREATER_EQUAL, GREATER,
EQUAL, NOT_EQUAL, LESS, GREATER_EQUAL,
LESS_EQUAL, GREATER, GREATER_EQUAL, LESS};
EQUAL, NOT_EQUAL, LESS, GREATER_EQUAL,
LESS_EQUAL, GREATER, GREATER_EQUAL, LESS};
struct AstIdent;
struct Function;
struct STKFRAME;
struct LOCAL_ID;
struct ICODE;
struct LLInst;
struct LLOperand;
struct ID;
typedef std::list<ICODE>::iterator iICODE;
typedef boost::iterator_range<iICODE> rICODE;
#include "IdentType.h"
/* Expression data type */
struct COND_EXPR
struct Expr
{
protected:
struct /* for BOOLEAN_OP */
{
condOp op;
COND_EXPR *lhs;
COND_EXPR *rhs;
} boolExpr;
public:
condNodeType m_type; /* Conditional Expression Node Type */
public:
static bool insertSubTreeLongReg(Expr *exp, Expr *&tree, int longIdx);
static bool insertSubTreeReg(Expr *&tree, Expr *_expr, eReg regi, const LOCAL_ID *locsym);
static bool insertSubTreeReg(AstIdent *&tree, Expr *_expr, eReg regi, const LOCAL_ID *locsym);
public:
public:
condNodeType m_type; /* Conditional Expression Node Type */
union _exprNode { /* Different cond expr nodes */
COND_EXPR *unaryExp; /* for NEGATION,ADDRESSOF,DEREFERENCE*/
IDENTTYPE ident; /* for IDENTIFIER */
} expr;
COND_EXPR *lhs()
virtual Expr *clone() const=0; //!< Makes a deep copy of the given expression
Expr(condNodeType t=UNKNOWN_OP) : m_type(t)
{
assert(m_type==BOOLEAN_OP);
return boolExpr.lhs;
}
const COND_EXPR *lhs() const
{
assert(m_type==BOOLEAN_OP);
return boolExpr.lhs;
}
COND_EXPR *rhs()
{
assert(m_type==BOOLEAN_OP);
return boolExpr.rhs;
}
const COND_EXPR *rhs() const
{
assert(m_type==BOOLEAN_OP);
return boolExpr.rhs;
}
condOp op() const { return boolExpr.op;}
public:
static COND_EXPR *idRegIdx(int idx, regType reg_type);
static COND_EXPR *idKte(uint32_t kte, uint8_t size);
static COND_EXPR *idLoc(int off, LOCAL_ID *localId);
static COND_EXPR *idReg(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym);
static COND_EXPR *idLongIdx(int idx);
static COND_EXPR *idOther(eReg seg, eReg regi, int16_t off);
static COND_EXPR *idParam(int off, const STKFRAME *argSymtab);
static COND_EXPR *unary(condNodeType t, COND_EXPR *sub_expr);
static COND_EXPR *idLong(LOCAL_ID *localId, opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
static COND_EXPR *idFunc(Function *pproc, STKFRAME *args);
static COND_EXPR *idID(const ID *retVal, LOCAL_ID *locsym, iICODE ix_);
static COND_EXPR * id(const LLInst &ll_insn, opLoc sd, Function *pProc, iICODE ix_, ICODE &duIcode, operDu du);
static COND_EXPR *boolOp(COND_EXPR *_lhs, COND_EXPR *_rhs, condOp _op);
static bool insertSubTreeLongReg(COND_EXPR *exp, COND_EXPR **tree, int longIdx);
static bool insertSubTreeReg(COND_EXPR *&tree, COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym);
public:
virtual COND_EXPR *clone() const;
void release();
void changeBoolOp(condOp newOp);
COND_EXPR(const COND_EXPR &other)
{
m_type=other.m_type;
expr=other.expr;
boolExpr=other.boolExpr;
}
COND_EXPR(condNodeType t=UNKNOWN_OP) : m_type(t)
{
memset(&expr,0,sizeof(_exprNode));
memset(&boolExpr,0,sizeof(boolExpr));
}
virtual ~COND_EXPR() {}
/** Recursively deallocates the abstract syntax tree rooted at *exp */
virtual ~Expr() {}
public:
virtual COND_EXPR *inverse() const; // return new COND_EXPR that is invarse of this
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId);
virtual COND_EXPR *insertSubTreeReg(COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym);
virtual COND_EXPR *insertSubTreeLongReg(COND_EXPR *_expr, int longIdx);
virtual hlType expType(Function *pproc) const;
virtual QString walkCondExpr (Function * pProc, int* numLoc) const=0;
virtual Expr *inverse() const=0; // return new COND_EXPR that is invarse of this
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId)=0;
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym)=0;
virtual Expr *insertSubTreeLongReg(Expr *_expr, int longIdx)=0;
virtual hlType expType(Function *pproc) const=0;
virtual int hlTypeSize(Function *pproc) const=0;
virtual Expr * performLongRemoval(eReg regi, LOCAL_ID *locId) { return this; }
};
struct BinaryOperator : public COND_EXPR
struct UnaryOperator : public Expr
{
UnaryOperator(condNodeType t=UNKNOWN_OP) : Expr(t),unaryExp(nullptr) {}
Expr *unaryExp;
virtual Expr *inverse() const
{
if (m_type == NEGATION) //TODO: memleak here
{
return unaryExp->clone();
}
return this->clone();
}
virtual Expr *clone() const
{
UnaryOperator *newExp = new UnaryOperator(*this);
newExp->unaryExp = unaryExp->clone();
return newExp;
}
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs);
static UnaryOperator *Create(condNodeType t, Expr *sub_expr)
{
UnaryOperator *newExp = new UnaryOperator();
newExp->m_type = t;
newExp->unaryExp = sub_expr;
return (newExp);
}
~UnaryOperator()
{
delete unaryExp;
unaryExp=nullptr;
}
public:
int hlTypeSize(Function *pproc) const;
virtual QString walkCondExpr(Function *pProc, int *numLoc) const;
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym);
virtual hlType expType(Function *pproc) const;
virtual Expr *insertSubTreeLongReg(Expr *_expr, int longIdx);
private:
QString wrapUnary(Function *pProc, int *numLoc, QChar op) const;
};
struct BinaryOperator : public Expr
{
condOp m_op;
COND_EXPR *m_lhs;
COND_EXPR *m_rhs;
BinaryOperator(condOp o)
Expr *m_lhs;
Expr *m_rhs;
BinaryOperator(condOp o) : Expr(BOOLEAN_OP)
{
m_op = o;
m_lhs=m_rhs=nullptr;
}
static BinaryOperator *Create(condOp o,COND_EXPR *l,COND_EXPR *r);
static BinaryOperator *CreateAdd(COND_EXPR *l,COND_EXPR *r);
virtual COND_EXPR *inverse();
virtual COND_EXPR *clone();
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs);
virtual COND_EXPR *insertSubTreeReg(COND_EXPR *_expr, eReg regi, LOCAL_ID *locsym);
virtual COND_EXPR *insertSubTreeLongReg(COND_EXPR *_expr, int longIdx);
BinaryOperator(condOp o,Expr *l,Expr *r) : Expr(BOOLEAN_OP)
{
m_op = o;
m_lhs=l;
m_rhs=r;
}
~BinaryOperator()
{
assert(m_lhs!=m_rhs or m_lhs==nullptr);
delete m_lhs;
delete m_rhs;
m_lhs=m_rhs=nullptr;
}
static BinaryOperator *Create(condOp o,Expr *l,Expr *r)
{
BinaryOperator *res = new BinaryOperator(o);
res->m_lhs = l;
res->m_rhs = r;
return res;
}
static BinaryOperator *LogicAnd(Expr *l,Expr *r)
{
return Create(DBL_AND,l,r);
}
static BinaryOperator *createSHL(Expr *l,Expr *r)
{
return Create(SHL,l,r);
}
static BinaryOperator *And(Expr *l,Expr *r)
{
return Create(AND,l,r);
}
static BinaryOperator *Or(Expr *l,Expr *r)
{
return Create(OR,l,r);
}
static BinaryOperator *LogicOr(Expr *l,Expr *r)
{
return Create(DBL_OR,l,r);
}
static BinaryOperator *CreateAdd(Expr *l,Expr *r) {
return Create(ADD,l,r);
COND_EXPR *lhs()
}
void changeBoolOp(condOp newOp);
virtual Expr *inverse() const;
virtual Expr *clone() const;
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs);
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym);
virtual Expr *insertSubTreeLongReg(Expr *_expr, int longIdx);
const Expr *lhs() const
{
return const_cast<const Expr *>(const_cast<BinaryOperator *>(this)->lhs());
}
const Expr *rhs() const
{
return const_cast<const Expr *>(const_cast<BinaryOperator *>(this)->rhs());
}
Expr *lhs()
{
assert(m_type==BOOLEAN_OP);
return m_lhs;
}
const COND_EXPR *lhs() const
{
assert(m_type==BOOLEAN_OP);
return m_lhs;
}
COND_EXPR *rhs()
{
assert(m_type==BOOLEAN_OP);
return m_rhs;
}
const COND_EXPR *rhs() const
Expr *rhs()
{
assert(m_type==BOOLEAN_OP);
return m_rhs;
@ -152,26 +190,131 @@ struct BinaryOperator : public COND_EXPR
condOp op() const { return m_op;}
/* Changes the boolean conditional operator at the root of this expression */
void op(condOp o) { m_op=o;}
QString walkCondExpr(Function * pProc, int* numLoc) const;
public:
hlType expType(Function *pproc) const;
int hlTypeSize(Function *pproc) const;
};
struct UnaryOperator : public COND_EXPR
struct AstIdent : public UnaryOperator
{
condOp op;
COND_EXPR *unaryExp;
virtual COND_EXPR *inverse();
virtual COND_EXPR *clone();
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs);
static UnaryOperator *Create(condNodeType t, COND_EXPR *sub_expr)
AstIdent() : UnaryOperator(IDENTIFIER)
{
UnaryOperator *newExp = new UnaryOperator();
newExp->m_type=t;
newExp->unaryExp = sub_expr;
return (newExp);
}
};
IDENTTYPE ident; /* for IDENTIFIER */
static AstIdent * Loc(int off, LOCAL_ID *localId);
static AstIdent * LongIdx(int idx);
static AstIdent * String(uint32_t idx);
static AstIdent * Other(eReg seg, eReg regi, int16_t off);
static AstIdent * Param(int off, const STKFRAME *argSymtab);
static AstIdent * Long(LOCAL_ID *localId, opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
static AstIdent * idID(const ID *retVal, LOCAL_ID *locsym, iICODE ix_);
static Expr * id(const LLInst &ll_insn, opLoc sd, Function *pProc, iICODE ix_, ICODE &duIcode, operDu du);
struct GlobalVariable : public COND_EXPR
{
static COND_EXPR *Create(int16_t segValue, int16_t off);
virtual Expr *clone() const
{
return new AstIdent(*this);
}
virtual int hlTypeSize(Function *pproc) const;
virtual hlType expType(Function *pproc) const;
virtual Expr * performLongRemoval(eReg regi, LOCAL_ID *locId);
virtual QString walkCondExpr(Function *pProc, int *numLoc) const;
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym);
virtual Expr *insertSubTreeLongReg(Expr *_expr, int longIdx);
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId);
};
struct GlobalVariable : public AstIdent
{
bool valid;
int globIdx;
virtual Expr *clone() const
{
return new GlobalVariable(*this);
}
GlobalVariable(int16_t segValue, int16_t off);
QString walkCondExpr(Function *pProc, int *numLoc) const;
int hlTypeSize(Function *pproc) const;
hlType expType(Function *pproc) const;
};
struct GlobalVariableIdx : public AstIdent
{
bool valid;
int idxGlbIdx; /* idx into localId, GLOB_VAR_IDX */
virtual Expr *clone() const
{
return new GlobalVariableIdx(*this);
}
GlobalVariableIdx(int16_t segValue, int16_t off, uint8_t regi, const LOCAL_ID *locSym);
QString walkCondExpr(Function *pProc, int *numLoc) const;
int hlTypeSize(Function *pproc) const;
hlType expType(Function *pproc) const;
};
struct Constant : public AstIdent
{
struct _kte
{ /* for CONSTANT only */
uint32_t kte; /* value of the constant */
uint8_t size; /* #bytes size constant */
} kte;
Constant(uint32_t _kte, uint8_t size)
{
ident.idType = CONSTANT;
kte.kte = _kte;
kte.size = size;
}
virtual Expr *clone() const
{
return new Constant(*this);
}
QString walkCondExpr(Function *pProc, int *numLoc) const;
int hlTypeSize(Function *pproc) const;
hlType expType(Function *pproc) const { return TYPE_CONST; }
};
struct FuncNode : public AstIdent
{
struct _call { /* for FUNCTION only */
Function *proc;
STKFRAME *args;
} call;
FuncNode(Function *pproc, STKFRAME *args)
{
call.proc = pproc;
call.args = args;
}
virtual Expr *clone() const
{
return new FuncNode(*this);
}
QString walkCondExpr(Function *pProc, int *numLoc) const;
int hlTypeSize(Function *pproc) const;
hlType expType(Function *pproc) const;
};
struct RegisterNode : public AstIdent
{
const LOCAL_ID *m_syms;
regType regiType; /* for REGISTER only */
int regiIdx; /* index into localId, REGISTER */
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym);
RegisterNode(int idx, regType reg_type,const LOCAL_ID *syms)
{
m_syms= syms;
ident.type(REGISTER);
regiType = reg_type;
regiIdx = idx;
}
RegisterNode(const LLOperand &, LOCAL_ID *locsym);
//RegisterNode(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym);
virtual Expr *clone() const
{
return new RegisterNode(*this);
}
QString walkCondExpr(Function *pProc, int *numLoc) const;
int hlTypeSize(Function *) const;
hlType expType(Function *pproc) const;
bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId);
};
struct Constant : public COND_EXPR
{};

View File

@ -7,8 +7,10 @@
#pragma once
#include <stdio.h>
#include <vector>
#include <string>
struct strTable : std::vector<std::string>
#include <QtCore/QString>
#include <QtCore/QIODevice>
struct strTable : std::vector<QString>
{
/* Returns the next available index into the table */
size_t nextIdx() {return size();}
@ -20,9 +22,9 @@ struct bundle
{
public:
void appendCode(const char *format, ...);
void appendCode(const std::string &s);
void appendCode(const QString &s);
void appendDecl(const char *format, ...);
void appendDecl(const std::string &);
void appendDecl(const QString &);
void init()
{
decl.clear();
@ -33,10 +35,10 @@ public:
int current_indent;
};
extern bundle cCode;
#define lineSize 360 /* 3 lines in the mean time */
//void newBundle (bundle *procCode);
void writeBundle (std::ostream &ios, bundle procCode);
void writeBundle (QIODevice & ios, bundle procCode);
void freeBundle (bundle *procCode);

View File

@ -5,10 +5,10 @@
#pragma once
//TODO: Remove boolT
#include <llvm/ADT/ilist.h>
#include <utility>
#include <algorithm>
#include <bitset>
#include <QtCore/QString>
#include "Enums.h"
#include "types.h"
@ -20,54 +20,32 @@
#include "bundle.h"
#include "Procedure.h"
#include "BasicBlock.h"
struct Project;
class Project;
/* CALL GRAPH NODE */
struct CALL_GRAPH
{
ilFunction proc; /* Pointer to procedure in pProcList */
std::vector<CALL_GRAPH *> outEdges; /* array of out edges */
public:
void write();
CALL_GRAPH() : outEdges(0)
{
}
public:
void writeNodeCallGraph(int indIdx);
bool insertCallGraph(ilFunction caller, ilFunction callee);
bool insertCallGraph(Function *caller, ilFunction callee);
void insertArc(ilFunction newProc);
};
//#define NUM_PROCS_DELTA 5 /* delta # procs a proc invokes */
//extern std::list<Function> pProcList;
//extern FunctionListType pProcList;
//extern CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
extern bundle cCode; /* Output C procedure's declaration and code */
/**** Global variables ****/
extern char *asm1_name, *asm2_name; /* Assembler output filenames */
extern QString asm1_name, asm2_name; /* Assembler output filenames */
typedef struct { /* Command line option flags */
unsigned verbose : 1;
unsigned VeryVerbose : 1;
unsigned asm1 : 1; /* Early disassembly listing */
unsigned asm2 : 1; /* Disassembly listing after restruct */
unsigned Map : 1;
unsigned Stats : 1;
unsigned Interact : 1; /* Interactive mode */
unsigned Calls : 1; /* Follow register indirect calls */
char filename[80]; /* The input filename */
} OPTION;
/** Command line option flags */
struct OPTION
{
bool verbose;
bool VeryVerbose;
bool asm1; /* Early disassembly listing */
bool asm2; /* Disassembly listing after restruct */
bool Map;
bool Stats;
bool Interact; /* Interactive mode */
bool Calls; /* Follow register indirect calls */
QString filename; /* The input filename */
uint32_t CustomEntryPoint;
};
extern OPTION option; /* Command line options */
#include "BinaryImage.h"
extern std::bitset<32> duReg[30]; /* def/use bits for registers */
//extern uint32_t duReg[30]; /* def/use bits for registers */
extern std::bitset<32> maskDuReg[30]; /* masks off du bits for regs */
/* Registers used by icode instructions */
/* Memory map states */
enum eAreaType
@ -94,56 +72,33 @@ extern STATS stats; /* Icode statistics */
/**** Global function prototypes ****/
class DccFrontend
{
void LoadImage(Project &proj);
void parse(Project &proj);
std::string m_fname;
public:
DccFrontend(const std::string &fname) : m_fname(fname)
{
}
bool FrontEnd(); /* frontend.c */
};
void udm(void); /* udm.c */
void freeCFG(BB * cfg); /* graph.c */
BB * newBB(BB *, int, int, uint8_t, int, Function *); /* graph.c */
void BackEnd(char *filename, CALL_GRAPH *); /* backend.c */
char *cChar(uint8_t c); /* backend.c */
void BackEnd(CALL_GRAPH *); /* backend.c */
extern char *cChar(uint8_t c); /* backend.c */
eErrorId scan(uint32_t ip, ICODE &p); /* scanner.c */
void parse (CALL_GRAPH * *); /* parser.c */
int strSize (uint8_t *, char); /* parser.c */
extern int strSize (const uint8_t *, char); /* parser.c */
//void disassem(int pass, Function * pProc); /* disassem.c */
void interactDis(Function * initProc, int initIC); /* disassem.c */
void interactDis(Function *, int initIC); /* disassem.c */
bool JmpInst(llIcode opcode); /* idioms.c */
queue::iterator appendQueue(queue &Q, BB *node); /* reducible.c */
void SetupLibCheck(void); /* chklib.c */
bool SetupLibCheck(void); /* chklib.c */
void CleanupLibCheck(void); /* chklib.c */
bool LibCheck(Function &p); /* chklib.c */
/* Exported functions from procs.c */
boolT insertCallGraph (CALL_GRAPH *, ilFunction, ilFunction);
void adjustActArgType (COND_EXPR *, hlType, Function *);
/* Exported functions from ast.c */
std::string walkCondExpr (const COND_EXPR *exp, Function * pProc, int *);
int hlTypeSize (const COND_EXPR *, Function *);
//hlType expType (const COND_EXPR *, Function *);
/* Exported functions from hlicode.c */
std::string writeCall (Function *, STKFRAME &, Function *, int *);
char *writeJcond (const HLTYPE &, Function *, int *);
char *writeJcondInv (HLTYPE, Function *, int *);
QString writeJcond(const HLTYPE &, Function *, int *);
QString writeJcondInv(HLTYPE, Function *, int *);
/* Exported funcions from locident.c */
boolT checkLongEq (LONG_STKID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &atOffset);
boolT checkLongRegEq (LONGID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &);
eReg otherLongRegi(eReg, int, LOCAL_ID *);
bool checkLongEq(LONG_STKID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &atOffset);
bool checkLongRegEq(LONGID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &);
extern const char *indentStr(int level);

24
include/dcc_interface.h Normal file
View File

@ -0,0 +1,24 @@
#pragma once
#include "Procedure.h"
#include <QtCore/QObject>
#include <QtCore/QDir>
class IXmlTarget;
struct IDcc {
static IDcc *get();
virtual void BaseInit()=0;
virtual void Init(QObject *tgt)=0;
virtual lFunction::iterator GetFirstFuncHandle()=0;
virtual lFunction::iterator GetCurFuncHandle()=0;
virtual void analysis_Once()=0;
virtual void load(QString name)=0; // load and preprocess -> find entry point
virtual void prtout_asm(IXmlTarget *,int level=0)=0;
virtual void prtout_cpp(IXmlTarget *,int level=0)=0;
virtual size_t getFuncCount()=0;
virtual const lFunction &validFunctions() const =0;
virtual void SetCurFunc_by_Name(QString )=0;
virtual QDir installDir()=0;
virtual QDir dataDir(QString kind)=0;
};

View File

@ -1,20 +1,26 @@
/****************************************************************************
* dcc project disassembler header
* (C) Mike van Emmerik
****************************************************************************/
/*
***************************************************************************
dcc project disassembler header
(C) Mike van Emmerik
***************************************************************************
*/
#pragma once
#include <sstream>
#include "bundle.h"
#include <fstream>
#include <vector>
#include "bundle.h"
#include <QString>
#include <QTextStream>
struct LLInst;
struct Function;
struct Disassembler
{
protected:
int pass;
int g_lab;
//bundle &cCode;
std::ofstream m_fp;
QIODevice *m_disassembly_target;
QTextStream m_fp;
std::vector<std::string> m_decls;
std::vector<std::string> m_code;
@ -32,24 +38,6 @@ public:
#define EXT 0x100 /* "Extended" flag */
#ifdef __MSDOS__
#define KEY_DOWN EXT+'P'
#define KEY_LEFT EXT+'K'
#define KEY_UP EXT+'H'
#define KEY_RIGHT EXT+'M'
#define KEY_NPAGE EXT+'Q'
#define KEY_PPAGE EXT+'I'
#endif
#ifdef _CONSOLE
#define KEY_DOWN 0x50 /* Same as keypad scancodes */
#define KEY_LEFT 0x4B
#define KEY_UP 0x48
#define KEY_RIGHT 0x4D
#define KEY_NPAGE 0x51
#define KEY_PPAGE 0x49
#endif
#ifdef __UNIX__
#define KEY_DOWN EXT+'B'
#define KEY_LEFT EXT+'D'

View File

@ -1,8 +1,11 @@
/***************************************************************************
/*
=**************************************************************************
* File : dosdcc.h
* Purpose : include file for files decompiled by dcc.
* Copyright (c) Cristina Cifuentes - QUT - 1992
**************************************************************************/
*************************************************************************
*/
/* Type definitions for intel 80x86 architecture */
typedef unsigned int uint16_t; /* 16 bits */
@ -18,7 +21,7 @@ typedef struct {
uint16_t lowBitWord : 1;
uint16_t filler1 : 6;
uint16_t highBitByte : 1;
/* high uint8_t */
/* high uint8_t */
uint16_t lowBitByte : 1;
uint16_t filler2 : 6;
uint16_t highBitWord : 1;

View File

@ -1,7 +1,10 @@
/*****************************************************************************
/*
****************************************************************************
* Error codes
* (C) Cristina Cifuentes
****************************************************************************/
***************************************************************************
*/
#pragma once
/* These definitions refer to errorMessage in error.c */

View File

@ -1,10 +1,13 @@
/*****************************************************************************
/*
****************************************************************************
* CFG, BB and interval related definitions
* (C) Cristina Cifuentes
****************************************************************************/
* ( C ) Cristina Cifuentes
****************************************************************************
*/
#pragma once
#include <stdint.h>
#include <list>
#include <vector>
struct Function;
/* Types of basic block nodes */
/* Real basic blocks: type defined according to their out-edges */
@ -55,6 +58,7 @@ enum eNodeHeaderType
#define ELSE 1 /* else edge */
/* Basic Block (BB) flags */
#define INVALID_BB 0x0001 /* BB is not valid any more */
#define IS_LATCH_NODE 0x0002 /* BB is the latching node of a loop */
@ -64,30 +68,24 @@ typedef std::list<BB *> queue;
struct interval
{
uint8_t numInt; /* # of the interval */
uint8_t numOutEdges; /* Number of out edges */
uint8_t numInt=0; /* # of the interval */
uint8_t numOutEdges=0; /* Number of out edges */
queue nodes; /* Nodes of the interval*/
queue::iterator currNode; /* Current node */
interval *next; /* Next interval */
BB *firstOfInt();
interval()
{
numInt=numOutEdges=0;
currNode=nodes.end();
next=0;
}
interval * next=0; /* Next interval */
BB * firstOfInt();
interval() : currNode(nodes.end()){
}
void appendNodeInt(queue &pqH, BB *node);
};
/* Derived Sequence structure */
struct derSeq_Entry
{
BB * Gi; /* Graph pointer */
interval * Ii; /* Interval list of Gi */
derSeq_Entry() : Gi(0),Ii(0)
{
}
BB * Gi=nullptr; /* Graph pointer */
std::list<interval *> m_intervals;
interval * Ii=nullptr; /* Interval list of Gi */
~derSeq_Entry();
public:
void findIntervals(Function *c);

View File

@ -3,21 +3,23 @@
* (C) Cristina Cifuentes
****************************************************************************/
#pragma once
#include "msvc_fixes.h"
#include "BinaryImage.h"
#include "libdis.h"
#include "Enums.h"
#include "state.h" // State depends on INDEXBASE, but later need STATE
#include "CallConvention.h"
#include <boost/range/iterator_range.hpp>
#include <QtCore/QString>
#include <memory>
#include <vector>
#include <list>
#include <bitset>
#include <llvm/ADT/ilist.h>
#include <llvm/ADT/ilist_node.h>
#include <llvm/CodeGen/MachineInstr.h>
#include <llvm/MC/MCInst.h>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/Value.h>
#include <llvm/Instruction.h>
#include <boost/range.hpp>
#include "libdis.h"
#include "Enums.h"
#include "state.h" // State depends on INDEXBASE, but later need STATE
#include <set>
#include <algorithm>
#include <initializer_list>
//enum condId;
@ -25,13 +27,97 @@ struct LOCAL_ID;
struct BB;
struct Function;
struct STKFRAME;
struct CIcodeRec;
class CIcodeRec;
struct ICODE;
struct bundle;
typedef std::list<ICODE>::iterator iICODE;
typedef std::list<ICODE>::reverse_iterator riICODE;
typedef boost::iterator_range<iICODE> rCODE;
extern std::bitset<32> duReg[30];
struct LivenessSet
{
std::set<eReg> registers;
public:
LivenessSet(const std::initializer_list<eReg> &init) : registers(init) {}
LivenessSet() {}
LivenessSet(const LivenessSet &other) : registers(other.registers)
{
}
void reset()
{
registers.clear();
}
// LivenessSet(LivenessSet &&other) : LivenessSet()
// {
// swap(*this,other);
// }
LivenessSet &operator=(LivenessSet other)
{
swap(*this,other);
return *this;
}
friend void swap(LivenessSet& first, LivenessSet& second) // nothrow
{
std::swap(first.registers, second.registers);
}
LivenessSet &operator|=(const LivenessSet &other)
{
registers.insert(other.registers.begin(),other.registers.end());
return *this;
}
LivenessSet &operator&=(const LivenessSet &other)
{
std::set<eReg> res;
std::set_intersection(registers.begin(),registers.end(),
other.registers.begin(),other.registers.end(),
std::inserter(res, res.end()));
registers = res;
return *this;
}
LivenessSet &operator-=(const LivenessSet &other)
{
std::set<eReg> res;
std::set_difference(registers.begin(),registers.end(),
other.registers.begin(),other.registers.end(),
std::inserter(res, res.end()));
registers = res;
return *this;
}
LivenessSet operator-(const LivenessSet &other) const
{
return LivenessSet(*this) -= other;
}
LivenessSet operator+(const LivenessSet &other) const
{
return LivenessSet(*this) |= other;
}
LivenessSet operator &(const LivenessSet &other) const
{
return LivenessSet(*this) &= other;
}
bool any() const
{
return not registers.empty();
}
bool operator==(const LivenessSet &other) const
{
return registers==other.registers;
}
bool operator!=(const LivenessSet &other) const { return not(*this==other);}
LivenessSet &setReg(int r);
LivenessSet &addReg(int r);
bool testReg(int r) const
{
return registers.find(eReg(r))!=registers.end();
}
bool testRegAndSubregs(int r) const;
LivenessSet &clrReg(int r);
private:
void postProcessCompositeRegs();
};
/* uint8_t and uint16_t registers */
/* Def/use of flags - low 4 bits represent flags */
@ -45,14 +131,16 @@ struct DU
#define MAX_REGS_DEF 4 /* 2 regs def'd for long-reg vars */
struct COND_EXPR;
struct Expr;
struct AstIdent;
struct UnaryOperator;
struct HlTypeSupport
{
//hlIcode opcode; /* hlIcode opcode */
virtual bool removeRegFromLong(eReg regi, LOCAL_ID *locId)=0;
virtual std::string writeOut(Function *pProc, int *numLoc)=0;
virtual bool removeRegFromLong(eReg regi, LOCAL_ID *locId)=0;
virtual QString writeOut(Function *pProc, int *numLoc) const=0;
protected:
void performLongRemoval (eReg regi, LOCAL_ID *locId, COND_EXPR *tree);
Expr * performLongRemoval (eReg regi, LOCAL_ID *locId, Expr *tree);
};
struct CallType : public HlTypeSupport
@ -61,41 +149,41 @@ struct CallType : public HlTypeSupport
Function * proc;
STKFRAME * args; // actual arguments
void allocStkArgs (int num);
bool newStkArg(COND_EXPR *exp, llIcode opcode, Function *pproc);
void placeStkArg(COND_EXPR *exp, int pos);
virtual COND_EXPR * toId();
bool newStkArg(Expr *exp, llIcode opcode, Function *pproc);
void placeStkArg(Expr *exp, int pos);
virtual Expr * toAst();
public:
bool removeRegFromLong(eReg regi, LOCAL_ID *locId)
bool removeRegFromLong(eReg /*regi*/, LOCAL_ID * /*locId*/)
{
printf("CallType : removeRegFromLong not supproted");
printf("CallType : removeRegFromLong not supproted\n");
return false;
}
std::string writeOut(Function *pProc, int *numLoc);
QString writeOut(Function *pProc, int *numLoc) const;
};
struct AssignType : public HlTypeSupport
{
/* for HLI_ASSIGN */
COND_EXPR *lhs;
COND_EXPR *rhs;
AssignType() : lhs(0),rhs(0) {}
bool removeRegFromLong(eReg regi, LOCAL_ID *locId)
{
performLongRemoval(regi,locId,lhs);
return true;
}
std::string writeOut(Function *pProc, int *numLoc);
protected:
public:
Expr * m_lhs;
Expr * m_rhs;
AssignType() {}
Expr *lhs() const {return m_lhs;}
void lhs(Expr *l);
bool removeRegFromLong(eReg regi, LOCAL_ID *locId);
QString writeOut(Function *pProc, int *numLoc) const;
};
struct ExpType : public HlTypeSupport
{
/* for HLI_JCOND, HLI_RET, HLI_PUSH, HLI_POP*/
COND_EXPR *v;
ExpType() : v(0) {}
Expr * v;
ExpType() : v(nullptr) {}
bool removeRegFromLong(eReg regi, LOCAL_ID *locId)
{
performLongRemoval(regi,locId,v);
v=performLongRemoval(regi,locId,v);
return true;
}
std::string writeOut(Function *pProc, int *numLoc);
QString writeOut(Function *pProc, int *numLoc) const;
};
struct HLTYPE
@ -106,35 +194,27 @@ public:
hlIcode opcode; /* hlIcode opcode */
AssignType asgn;
CallType call;
HlTypeSupport *get()
HlTypeSupport *get();
const HlTypeSupport *get() const
{
switch(opcode)
{
case HLI_ASSIGN: return &asgn;
case HLI_RET:
case HLI_POP:
case HLI_JCOND:
case HLI_PUSH: return &exp;
case HLI_CALL: return &call;
default:
return 0;
}
return const_cast<const HlTypeSupport *>(const_cast<HLTYPE*>(this)->get());
}
void expr(COND_EXPR *e)
void expr(Expr *e)
{
assert(e);
exp.v=e;
}
void replaceExpr(COND_EXPR *e)
Expr *getMyExpr()
{
assert(e);
delete exp.v;
exp.v=e;
if(opcode==HLI_CALL)
return call.toAst();
return expr();
}
COND_EXPR * expr() { return exp.v;}
const COND_EXPR * const expr() const { return exp.v;}
void set(hlIcode i,COND_EXPR *e)
void replaceExpr(Expr *e);
Expr * expr() { return exp.v;}
const Expr * expr() const { return exp.v;}
void set(hlIcode i,Expr *e)
{
if(i!=HLI_RET)
assert(e);
@ -142,106 +222,128 @@ public:
opcode=i;
exp.v=e;
}
void set(COND_EXPR *l,COND_EXPR *r)
{
assert(l);
assert(r);
opcode = HLI_ASSIGN;
assert((asgn.lhs==0) and (asgn.rhs==0)); //prevent memory leaks
asgn.lhs=l;
asgn.rhs=r;
}
void set(Expr *l,Expr *r);
void setCall(Function *proc);
HLTYPE(hlIcode op=HLI_INVALID) : opcode(op)
{}
// HLTYPE() // help valgrind find uninitialized HLTYPES
// {}
HLTYPE & operator=(const HLTYPE &l)
{
exp=l.exp;
opcode=l.opcode;
asgn=l.asgn;
call=l.call;
exp = l.exp;
opcode = l.opcode;
asgn = l.asgn;
call = l.call;
return *this;
}
public:
std::string write1HlIcode(Function *pProc, int *numLoc);
void setAsgn(COND_EXPR *lhs, COND_EXPR *rhs);
QString write1HlIcode(Function *pProc, int *numLoc) const;
void setAsgn(Expr *lhs, Expr *rhs);
} ;
/* LOW_LEVEL icode operand record */
struct LLOperand
{
llvm::MCOperand llvm_op;
eReg seg; /* CS, DS, ES, SS */
eReg segOver; /* CS, DS, ES, SS if segment override */
int16_t segValue; /* Value of segment seg during analysis */
eReg regi; /* 0 < regs < INDEXBASE <= index modes */
int16_t off; /* memory address offset */
uint32_t opz; /* idx of immed src op */
bool immed;
bool is_offset; // set by jumps
bool is_compound;
size_t width;
//union {/* Source operand if (flg & I) */
struct { /* Call & # actual arg bytes */
Function *proc; /* pointer to target proc (for CALL(F))*/
int cb; /* # actual arg bytes */
} proc;
LLOperand() : seg(rUNDEF),segValue(0),segOver(rUNDEF),regi(rUNDEF),off(0),opz(0)
LLOperand() : seg(rUNDEF),segOver(rUNDEF),segValue(0),regi(rUNDEF),off(0),
opz(0),immed(0),is_offset(false),is_compound(0),width(0)
{
proc.proc=0;
proc.cb=0;
}
LLOperand(eReg r,size_t w) : LLOperand()
{
regi=r;
width=w;
}
bool operator==(const LLOperand &with) const
{
return (seg==with.seg) and
(segOver==with.segOver) and
(segValue==with.segValue) and
(regi == with.regi) and
(off == with.off) and
(opz==with.opz) and
(proc.proc==with.proc.proc);
}
int64_t getImm2() const {return opz;}
void SetImmediateOp(uint32_t dw)
{
opz=dw;
}
eReg getReg2() {return regi;}
eReg getReg2() const {return regi;}
bool isReg() const;
static LLOperand CreateImm2(int64_t Val)
static LLOperand CreateImm2(int64_t Val,uint8_t wdth=2)
{
LLOperand Op;
//Op.Kind = kImmediate;
//Op.ImmVal = Val;
Op.immed=true;
Op.opz = Val;
Op.width = wdth;
return Op;
}
static LLOperand CreateReg2(unsigned Val)
{
LLOperand Op;
// Op.Kind = kRegister;
// Op.RegVal = Reg;
Op.regi = (eReg)Val;
return Op;
}
void addProcInformation(int param_count,uint32_t call_conv);
bool isSet()
{
return not (*this == LLOperand());
}
void addProcInformation(int param_count, CConv::Type call_conv);
bool isImmediate() const { return immed;}
void setImmediate(bool x) { immed=x;}
bool compound() const {return is_compound;} // dx:ax pair
size_t byteWidth() const { assert(width<=4); return width;}
};
struct LLInst : public llvm::MCInst //: public llvm::ilist_node<LLInst>
struct LLInst
{
protected:
uint32_t flg; /* icode flags */
LLOperand m_src; /* source operand */
llIcode m_opcode; // Low level opcode identifier
uint32_t flg; /* icode flags */
LLOperand m_src; /* source operand */
public:
int codeIdx; /* Index into cCode.code */
uint8_t numBytes; /* Number of bytes this instr */
uint32_t label; /* offset in image (20-bit adr) */
LLOperand dst; /* destination operand */
DU flagDU; /* def/use of flags */
int caseEntry;
int codeIdx; /* Index into cCode.code */
uint8_t numBytes; /* Number of bytes this instr */
uint32_t label; /* offset in image (20-bit adr) */
LLOperand m_dst; /* destination operand */
DU flagDU; /* def/use of flags */
int caseEntry;
std::vector<uint32_t> caseTbl2;
int hllLabNum; /* label # for hll codegen */
bool conditionalJump()
{
return (getOpcode() >= iJB) && (getOpcode() < iJCXZ);
}
bool testFlags(uint32_t x) const { return (flg & x)!=0;}
void setFlags(uint32_t flag) {flg |= flag;}
void clrFlags(uint32_t flag)
{
if(getOpcode()==iMOD)
{
assert(false);
}
flg &= ~flag;
}
uint32_t getFlag() const {return flg;}
//llIcode getOpcode() const { return opcode; }
uint32_t GetLlLabel() const { return label;}
llIcode getOpcode() const { return m_opcode;}
void setOpcode(uint32_t op) { m_opcode=(llIcode)op; }
bool conditionalJump()
{
return (getOpcode() >= iJB) and (getOpcode() < iJCXZ);
}
bool testFlags(uint32_t x) const { return (flg & x)!=0;}
void setFlags(uint32_t flag) {flg |= flag;}
void clrFlags(uint32_t flag)
{
if(getOpcode()==iMOD)
{
assert(false);
}
flg &= ~flag;
}
uint32_t getFlag() const {return flg;}
uint32_t GetLlLabel() const { return label;}
void SetImmediateOp(uint32_t dw) {m_src.SetImmediateOp(dw);}
@ -250,25 +352,29 @@ public:
{
return (getOpcode()==op);
}
bool matchWithRegDst(llIcode op)
{
return (getOpcode()==op) and m_dst.isReg();
}
bool match(llIcode op,eReg dest)
{
return (getOpcode()==op)&&dst.regi==dest;
return (getOpcode()==op)&&m_dst.regi==dest;
}
bool match(llIcode op,eReg dest,uint32_t flgs)
{
return (getOpcode()==op) and (dst.regi==dest) and testFlags(flgs);
return (getOpcode()==op) and (m_dst.regi==dest) and testFlags(flgs);
}
bool match(llIcode op,eReg dest,eReg src_reg)
{
return (getOpcode()==op)&&(dst.regi==dest)&&(m_src.regi==src_reg);
return (getOpcode()==op) and (m_dst.regi==dest) and (m_src.regi==src_reg);
}
bool match(eReg dest,eReg src_reg)
{
return (dst.regi==dest)&&(m_src.regi==src_reg);
return (m_dst.regi==dest) and (m_src.regi==src_reg);
}
bool match(eReg dest)
{
return (dst.regi==dest);
return (m_dst.regi==dest);
}
bool match(llIcode op,uint32_t flgs)
{
@ -279,15 +385,27 @@ public:
setOpcode(op);
flg =flags;
}
void set(llIcode op,uint32_t flags,eReg dst_reg)
{
setOpcode(op);
m_dst = LLOperand::CreateReg2(dst_reg);
flg =flags;
}
void set(llIcode op,uint32_t flags,eReg dst_reg,const LLOperand &src_op)
{
setOpcode(op);
m_dst = LLOperand::CreateReg2(dst_reg);
m_src = src_op;
flg =flags;
}
void emitGotoLabel(int indLevel);
void findJumpTargets(CIcodeRec &_pc);
void writeIntComment(std::ostringstream &s);
void writeIntComment(QTextStream & s);
void dis1Line(int loc_ip, int pass);
std::ostringstream &strSrc(std::ostringstream &os,bool skip_comma=false);
QTextStream & strSrc(QTextStream & os, bool skip_comma=false);
void flops(std::ostringstream &out);
void flops(QTextStream & out);
bool isJmpInst();
HLTYPE toHighLevel(COND_EXPR *lhs, COND_EXPR *rhs, Function *func);
HLTYPE createCall();
LLInst(ICODE *container) : flg(0),codeIdx(0),numBytes(0),m_link(container)
{
@ -309,16 +427,16 @@ public:
}
void replaceDst(const LLOperand &with)
{
dst = with;
}
void replaceDst(eReg r)
{
dst = LLOperand::CreateReg2(r);
m_dst = with;
}
// void replaceDst(eReg r)
// {
// dst = LLOperand::CreateReg2(r);
// }
ICODE *m_link;
condId idType(opLoc sd) const;
const LLOperand * get(opLoc sd) const { return (sd == SRC) ? &src() : &dst; }
LLOperand * get(opLoc sd) { return (sd == SRC) ? &src() : &dst; }
const LLOperand * get(opLoc sd) const { return (sd == SRC) ? &src() : &m_dst; }
LLOperand * get(opLoc sd) { return (sd == SRC) ? &src() : &m_dst; }
};
/* Icode definition: LOW_LEVEL and HIGH_LEVEL */
@ -342,17 +460,17 @@ public:
template<int TYPE>
struct TypeFilter
{
bool operator()(ICODE *ic) {return ic->type==HIGH_LEVEL;}
bool operator()(ICODE &ic) {return ic.type==HIGH_LEVEL;}
bool operator()(ICODE *ic) {return ic->type==TYPE;}
bool operator()(ICODE &ic) {return ic.type==TYPE;}
};
template<int TYPE>
struct TypeAndValidFilter
{
bool operator()(ICODE *ic) {return (ic->type==HIGH_LEVEL)&&(ic->valid());}
bool operator()(ICODE &ic) {return (ic.type==HIGH_LEVEL)&&ic.valid();}
bool operator()(ICODE *ic) {return (ic->type==TYPE) and (ic->valid());}
bool operator()(ICODE &ic) {return (ic.type==TYPE) and ic.valid();}
};
static TypeFilter<HIGH_LEVEL> select_high_level;
static TypeAndValidFilter<HIGH_LEVEL> select_valid_high_level;
static TypeFilter<HIGH_LEVEL_ICODE> select_high_level;
static TypeAndValidFilter<HIGH_LEVEL_ICODE> select_valid_high_level;
/* Def/Use of registers and stack variables */
struct DU_ICODE
{
@ -362,18 +480,21 @@ public:
use.reset();
lastDefRegi.reset();
}
std::bitset<32> def; // For Registers: position in bitset is reg index
std::bitset<32> use; // For Registers: position in uint32_t is reg index
std::bitset<32> lastDefRegi;// Bit set if last def of this register in BB
LivenessSet def; // For Registers: position in bitset is reg index
LivenessSet use; // For Registers: position in uint32_t is reg index
LivenessSet lastDefRegi;// Bit set if last def of this register in BB
void addDefinedAndUsed(eReg r)
{
def |= duReg[r];
use |= duReg[r];
def.addReg(r);
use.addReg(r);
}
};
struct DU1
{
protected:
int numRegsDef; /* # registers defined by this inst */
public:
struct Use
{
int Reg; // used register
@ -385,11 +506,10 @@ public:
if(iter==uses.end())
return;
uses.erase(iter);
assert("Same user more then once!" && uses.end()==std::find(uses.begin(),uses.end(),us));
assert("Same user more then once!" and uses.end()==std::find(uses.begin(),uses.end(),us));
}
};
int numRegsDef; /* # registers defined by this inst */
uint8_t regi[MAX_REGS_DEF+1]; /* registers defined by this inst */
Use idx[MAX_REGS_DEF+1];
//int idx[MAX_REGS_DEF][MAX_USES]; /* inst that uses this def */
@ -414,20 +534,33 @@ public:
Use &u(idx[regIdx]);
u.removeUser(ic);
}
int getNumRegsDef() const {return numRegsDef;}
void clearAllDefs() {numRegsDef=0;}
DU1 &addDef(eReg r) {numRegsDef++; return *this;}
DU1 &setDef(eReg r) {numRegsDef=1; return *this;}
void removeDef(eReg r) {numRegsDef--;}
DU1() : numRegsDef(0)
{
}
};
icodeType type; /* Icode type */
DU_ICODE du; /* Def/use regs/vars */
DU1 du1; /* du chain 1 */
DU_ICODE du; /* Def/use regs/vars */
DU1 du1; /* du chain 1 */
int loc_ip; // used by CICodeRec to number ICODEs
LLInst * ll() { return &m_ll;}
const LLInst * ll() const { return &m_ll;}
HLTYPE * hl() { return &m_hl;}
const HLTYPE * hl() const { return &m_hl;}
HLTYPE * hlU() {
// assert(type==HIGH_LEVEL);
// assert(m_hl.opcode!=HLI_INVALID);
return &m_hl;
}
const HLTYPE * hl() const {
// assert(type==HIGH_LEVEL);
// assert(m_hl.opcode!=HLI_INVALID);
return &m_hl;
}
void hl(const HLTYPE &v) { m_hl=v;}
void setRegDU(eReg regi, operDu du_in);
@ -437,13 +570,13 @@ public:
condId idType(opLoc sd);
// HLL setting functions
// set this icode to be an assign
void setAsgn(COND_EXPR *lhs, COND_EXPR *rhs)
void setAsgn(Expr *lhs, Expr *rhs)
{
type=HIGH_LEVEL;
hl()->setAsgn(lhs,rhs);
type=HIGH_LEVEL_ICODE;
hlU()->setAsgn(lhs,rhs);
}
void setUnary(hlIcode op, COND_EXPR *_exp);
void setJCond(COND_EXPR *cexp);
void setUnary(hlIcode op, Expr *_exp);
void setJCond(Expr *cexp);
void emitGotoLabel(int indLevel);
void copyDU(const ICODE &duIcode, operDu _du, operDu duDu);
@ -452,39 +585,38 @@ public:
public:
bool removeDefRegi(eReg regi, int thisDefIdx, LOCAL_ID *locId);
void checkHlCall();
bool newStkArg(COND_EXPR *exp, llIcode opcode, Function *pproc)
bool newStkArg(Expr *exp, llIcode opcode, Function *pproc)
{
return hl()->call.newStkArg(exp,opcode,pproc);
return hlU()->call.newStkArg(exp,opcode,pproc);
}
ICODE() : m_ll(this),type(NOT_SCANNED),Parent(0),loc_ip(0),invalid(false)
ICODE() : m_ll(this),Parent(0),invalid(false),type(NOT_SCANNED_ICODE),loc_ip(0)
{
}
public:
const MachineBasicBlock* getParent() const { return Parent; }
MachineBasicBlock* getParent() { return Parent; }
//unsigned getNumOperands() const { return (unsigned)Operands.size(); }
const MachineBasicBlock* getParent() const { return Parent; }
MachineBasicBlock* getParent() { return Parent; }
//unsigned getNumOperands() const { return (unsigned)Operands.size(); }
};
/** Map n low level instructions to m high level instructions
*/
struct MappingLLtoML
{
typedef llvm::iplist<llvm::Instruction> InstListType;
typedef boost::iterator_range<iICODE> rSourceRange;
typedef boost::iterator_range<InstListType::iterator> rTargetRange;
rSourceRange m_low_level;
rTargetRange m_middle_level;
};
//struct MappingLLtoML
//{
// typedef boost::iterator_range<iICODE> rSourceRange;
// typedef boost::iterator_range<InstListType::iterator> rTargetRange;
// rSourceRange m_low_level;
// rTargetRange m_middle_level;
//};
// This is the icode array object.
class CIcodeRec : public std::list<ICODE>
{
public:
CIcodeRec(); // Constructor
ICODE * addIcode(ICODE *pIcode);
void SetInBB(rCODE &rang, BB* pnewBB);
bool labelSrch(uint32_t target, uint32_t &pIndex);
ICODE * addIcode(ICODE *pIcode);
void SetInBB(rCODE &rang, BB* pnewBB);
bool labelSrch(uint32_t target, uint32_t &pIndex);
iterator labelSrch(uint32_t target);
ICODE * GetIcode(int ip);
ICODE * GetIcode(size_t ip);
bool alreadyDecoded(uint32_t target);
};

View File

@ -37,6 +37,8 @@ struct Idiom18 : public Idiom
protected:
iICODE m_icodes[4];
bool m_is_dec;
/* type of variable: 1 = reg-var, 2 = local */
int m_idiom_type;
public:
Idiom18(Function *f) : Idiom(f)
{
@ -64,7 +66,7 @@ struct Idiom20 : public Idiom
{
protected:
iICODE m_icodes[4];
bool m_is_dec;
condNodeType m_is_dec;
public:
Idiom20(Function *f) : Idiom(f)
{

11
include/loader.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
class ILoader
{
};
class LoaderManger
{
};

View File

@ -6,102 +6,144 @@
*/
#pragma once
#include "msvc_fixes.h"
#include "types.h"
#include "Enums.h"
#include "machine_x86.h"
#include <QtCore/QString>
#include <stdint.h>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include "types.h"
#include "Enums.h"
#include "machine_x86.h"
/* Type definition */
// this array has to stay in-order of addition i.e. not std::set<iICODE,std::less<iICODE> >
// TODO: why ?
struct COND_EXPR;
struct Expr;
struct AstIdent;
struct ICODE;
struct LLInst;
typedef std::list<ICODE>::iterator iICODE;
struct IDX_ARRAY : public std::vector<iICODE>
{
bool inList(iICODE idx)
bool inList(iICODE idx) const
{
return std::find(begin(),end(),idx)!=end();
}
};
typedef enum
enum frameType
{
STK_FRAME, /* For stack vars */
REG_FRAME, /* For register variables */
GLB_FRAME /* For globals */
} frameType;
};
typedef struct
struct BWGLB_TYPE
{
int16_t seg; /* segment value */
int16_t off; /* offset */
eReg regi; /* optional indexed register */
} BWGLB_TYPE;
} ;
typedef struct
{ /* For TYPE_LONG_(UN)SIGN on the stack */
/* For TYPE_LONG_(UN)SIGN on the stack */
struct LONG_STKID_TYPE
{
int offH; /* high offset from BP */
int offL; /* low offset from BP */
} LONG_STKID_TYPE;
LONG_STKID_TYPE(int h,int l) : offH(h),offL(l) {}
};
/* For TYPE_LONG_(UN)SIGN registers */
struct LONGID_TYPE
{ /* For TYPE_LONG_(UN)SIGN registers */
eReg h; /* high register */
eReg l; /* low register */
{
protected:
eReg m_h; /* high register */
eReg m_l; /* low register */
public:
void set(eReg highpart,eReg lowpart)
{
m_h = highpart;
m_l = lowpart;
}
eReg l() const { return m_l; }
eReg h() const { return m_h; }
bool srcDstRegMatch(iICODE a,iICODE b) const;
LONGID_TYPE() {} // uninitializing constructor to help valgrind catch uninit accesses
LONGID_TYPE(eReg h,eReg l) : m_h(h),m_l(l) {}
};
struct LONGGLB_TYPE /* For TYPE_LONG_(UN)SIGN globals */
{
int16_t seg; /* segment value */
int16_t offH; /* offset high */
int16_t offL; /* offset low */
uint8_t regi; /* optional indexed register */
LONGGLB_TYPE(int16_t _seg,int16_t _H,int16_t _L,int8_t _reg=0)
{
seg=_seg;
offH=_H;
offL=_L;
regi=_reg;
}
};
/* ID, LOCAL_ID */
struct ID
{
protected:
LONGID_TYPE m_longId; /* For TYPE_LONG_(UN)SIGN registers */
public:
hlType type; /* Probable type */
bool illegal; /* Boolean: not a valid field any more */
//std::vector<iICODE> idx;
IDX_ARRAY idx; /* Index into icode array (REG_FRAME only) */
frameType loc; /* Frame location */
bool illegal; /* Boolean: not a valid field any more */
bool hasMacro; /* Identifier requires a macro */
char macro[10]; /* Macro for this identifier */
std::string name; /* Identifier's name */
union { /* Different types of identifiers */
eReg regi; /* For TYPE_BYTE(uint16_t)_(UN)SIGN registers */
struct { /* For TYPE_BYTE(uint16_t)_(UN)SIGN on the stack */
QString name; /* Identifier's name */
union ID_UNION { /* Different types of identifiers */
friend struct ID;
protected:
LONG_STKID_TYPE longStkId; /* For TYPE_LONG_(UN)SIGN on the stack */
public:
eReg regi; /* For TYPE_BYTE(WORD)_(UN)SIGN registers */
struct { /* For TYPE_BYTE(WORD)_(UN)SIGN on the stack */
uint8_t regOff; /* register offset (if any) */
int off; /* offset from BP */
} bwId;
} bwId;
BWGLB_TYPE bwGlb; /* For TYPE_BYTE(uint16_t)_(UN)SIGN globals */
LONGID_TYPE longId; /* For TYPE_LONG_(UN)SIGN registers */
LONG_STKID_TYPE longStkId; /* For TYPE_LONG_(UN)SIGN on the stack */
struct { /* For TYPE_LONG_(UN)SIGN globals */
int16_t seg; /* segment value */
int16_t offH; /* offset high */
int16_t offL; /* offset low */
uint8_t regi; /* optional indexed register */
} longGlb;
LONGGLB_TYPE longGlb;
struct { /* For TYPE_LONG_(UN)SIGN constants */
uint32_t h; /* high uint16_t */
uint32_t l; /* low uint16_t */
} longKte;
ID_UNION() { /*new (&longStkId) LONG_STKID_TYPE();*/}
} id;
ID();
ID(hlType t, frameType f);
bool isSigned() const { return (type==TYPE_BYTE_SIGN)||(type==TYPE_WORD_SIGN)||(type==TYPE_LONG_SIGN);}
uint16_t typeBitsize() const
{
return TypeContainer::typeSize(type)*8;
}
void setLocalName(int i)
{
char buf[32];
sprintf (buf, "loc%ld", i);
name=buf;
}
LONGID_TYPE & longId() {assert(isLong() and loc==REG_FRAME); return m_longId;}
const LONGID_TYPE & longId() const {assert(isLong() and loc==REG_FRAME); return m_longId;}
LONG_STKID_TYPE & longStkId() {assert(isLong() and loc==STK_FRAME); return id.longStkId;}
const LONG_STKID_TYPE & longStkId() const {assert(isLong() and loc==STK_FRAME); return id.longStkId;}
ID();
ID(hlType t, frameType f);
ID(hlType t, const LONGID_TYPE &s);
ID(hlType t, const LONG_STKID_TYPE &s);
ID(hlType t, const LONGGLB_TYPE &s);
bool isSigned() const { return (type==TYPE_BYTE_SIGN) or (type==TYPE_WORD_SIGN) or (type==TYPE_LONG_SIGN);}
uint16_t typeBitsize() const
{
return TypeContainer::typeSize(type)*8;
}
bool isLong() const { return (type==TYPE_LONG_UNSIGN) or (type==TYPE_LONG_SIGN); }
void setLocalName(int i)
{
char buf[32];
sprintf (buf, "loc%d", i);
name=buf;
}
bool isLongRegisterPair() const { return (loc == REG_FRAME) and isLong();}
eReg getPairedRegister(eReg first) const;
};
struct LOCAL_ID
@ -121,18 +163,19 @@ public:
std::vector<ID>::iterator end() {return id_arr.end();}
int newByteWordReg(hlType t, eReg regi);
int newByteWordStk(hlType t, int off, uint8_t regOff);
int newIntIdx(int16_t seg, int16_t off, eReg regi, int ix, hlType t);
int newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_);
int newIntIdx(int16_t seg, int16_t off, eReg regi, hlType t);
int newLongReg(hlType t, const LONGID_TYPE &longT, iICODE ix_);
int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, int off);
int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
void newIdent(hlType t, frameType f);
void flagByteWordId(int off);
void propLongId(uint8_t regL, uint8_t regH, const char *name);
void propLongId(uint8_t regL, uint8_t regH, const QString & name);
size_t csym() const {return id_arr.size();}
void newRegArg(iICODE picode, iICODE ticode) const;
void processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode, bool isLong) const;
void forwardSubs(COND_EXPR *lhs, COND_EXPR *rhs, iICODE picode, iICODE ticode, int &numHlIcodes) const;
COND_EXPR *createId(const ID *retVal, iICODE ix_);
void newRegArg(ICODE & picode, ICODE & ticode) const;
void processTargetIcode(ICODE & picode, int &numHlIcodes, ICODE & ticode, bool isLong) const;
void forwardSubs(Expr *lhs, Expr *rhs, ICODE & picode, ICODE & ticode, int &numHlIcodes) const;
AstIdent *createId(const ID *retVal, iICODE ix_);
eReg getPairedRegisterAt(int idx,eReg first) const;
};

View File

@ -1,9 +1,12 @@
#pragma once
#include <QtCore/QString>
#include <stdint.h>
#include <string>
#include <sstream>
#include <bitset>
class QTextStream;
struct LivenessSet;
/* Machine registers */
enum eReg
{
@ -32,8 +35,9 @@ enum eReg
rBH = 20,
rTMP= 21, /* temp register for DIV/IDIV/MOD */
rTMP2= 22, /* temp register for DIV/IDIV/MOD */
/* Indexed modes go from INDEXBASE to INDEXBASE+7 */
INDEX_BX_SI = 22, // "bx+si"
INDEX_BX_SI = 23, // "bx+si"
INDEX_BX_DI, // "bx+di"
INDEX_BP_SI, // "bp+si"
INDEX_BP_DI, // "bp+di"
@ -58,25 +62,20 @@ class Machine_X86 : public SourceMachine
public:
Machine_X86();
virtual ~Machine_X86() {}
static const std::string &regName(eReg r);
static const std::string &opcodeName(unsigned r);
static const std::string &floatOpName(unsigned r);
static const QString & regName(eReg r);
static const QString & opcodeName(unsigned r);
static const QString & floatOpName(unsigned r);
bool physicalReg(eReg r);
/* Writes the registers that are set in the bitvector */
//TODO: move this into Machine_X86 ?
static void writeRegVector (std::ostream &ostr,const std::bitset<32> &regi)
{
int j;
for (j = rAX; j < INDEX_BX_SI; j++)
{
if (regi.test(j-1))
ostr << regName(eReg(j))<<" ";
}
}
static eReg subRegH(eReg reg); //TODO: move these into machine_x86
static void writeRegVector (QTextStream & ostr, const LivenessSet &regi);
static eReg subRegH(eReg reg);
static eReg subRegL(eReg reg);
static bool isMemOff(eReg r);
static bool isSubRegisterOf(eReg reg, eReg parent);
static bool hasSubregisters(eReg reg);
static bool isPartOfComposite(eReg reg);
static eReg compositeParent(eReg reg);
};

3
include/msvc_fixes.h Normal file
View File

@ -0,0 +1,3 @@
#ifdef _MSC_VER
#include <iso646.h>
#endif

View File

@ -1,41 +0,0 @@
#pragma once
/* Perfect hashing function library. Contains functions to generate perfect
hashing functions
* (C) Mike van Emmerik
*/
//#define bool unsigned char
#define uint8_t unsigned char
#define uint16_t unsigned short
/* Prototypes */
void hashCleanup(void); /* Frees memory allocated by hashParams() */
void map(void); /* Part 1 of creating the tables */
/* The application must provide these functions: */
void getKey(int i, uint8_t **pKeys);/* Set *keys to point to the i+1th key */
void dispKey(int i); /* Display the key */
class PatternHasher
{
uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */
int NumEntry; /* Number of entries in the hash table (# keys) */
int EntryLen; /* Size (bytes) of each entry (size of keys) */
int SetSize; /* Size of the char set */
char SetMin; /* First char in the set */
int NumVert; /* c times NumEntry */
int *graphNode; /* The array of edges */
int *graphNext; /* Linked list of edges */
int *graphFirst;/* First edge at a vertex */
public:
uint16_t *readT1(void); /* Returns a pointer to the T1 table */
uint16_t *readT2(void); /* Returns a pointer to the T2 table */
uint16_t *readG(void); /* Returns a pointer to the g table */
void init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,int _NumVert); /* Set the parameters for the hash table */
void cleanup();
int hash(unsigned char *string); //!< Hash the string to an int 0 .. NUMENTRY-1
};
extern PatternHasher g_pattern_hasher;
/* Macro reads a LH uint16_t from the image regardless of host convention */
#ifndef LH
#define LH(p) ((int)((uint8_t *)(p))[0] + ((int)((uint8_t *)(p))[1] << 8))
#endif

View File

@ -3,75 +3,72 @@
#include <stdint.h>
#include <cassert>
#include <list>
#include <llvm/ADT/ilist.h>
#include <boost/icl/interval.hpp>
#include <boost/icl/interval_map.hpp>
#include <boost/icl/split_interval_map.hpp>
#include <unordered_set>
#include <QtCore/QString>
#include "symtab.h"
#include "BinaryImage.h"
struct Function;
struct SourceMachine;
#include "Procedure.h"
class QString;
class SourceMachine;
struct CALL_GRAPH;
typedef llvm::iplist<Function> FunctionListType;
typedef FunctionListType lFunction;
typedef lFunction::iterator ilFunction;
struct Project
class IProject
{
SYMTAB symtab; /* Global symbol table */
virtual PROG *binary()=0;
virtual const QString & project_name() const =0;
virtual const QString & binary_path() const =0;
};
class Project : public IProject
{
static Project *s_instance;
QString m_fname;
QString m_project_name;
QString m_output_path;
public:
std::string m_fname;
FunctionListType pProcList;
CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
PROG prog; /* Loaded program image parameters */
Project() {}
// no copies
Project(const Project&) = delete;
const Project &operator=(const Project & l) =delete;
// only moves
Project(Project && l)
{
m_fname =l.m_fname;
size_t before=l.pProcList.size();
pProcList.splice(pProcList.end(),l.pProcList);
callGraph=l.callGraph;
l.m_fname.clear();
l.pProcList.clear();
l.callGraph=0;
assert(before==pProcList.size());
}
Project &operator=(Project && l)
{
if(this == &l)
return *this;
m_fname =l.m_fname;
size_t before=l.pProcList.size();
pProcList.splice(pProcList.end(),l.pProcList);
callGraph=l.callGraph;
l.m_fname.clear();
l.pProcList.clear();
l.callGraph=0;
assert(before==pProcList.size());
return *this;
}
typedef std::list<Function> FunctionListType;
typedef FunctionListType lFunction;
typedef FunctionListType::iterator ilFunction;
SYMTAB symtab; /* Global symbol table */
FunctionListType pProcList;
CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
PROG prog; /* Loaded program image parameters */
// no copies
Project(const Project&) = delete;
const Project & operator=(const Project & l) =delete;
// only moves
Project(); // default constructor,
public:
ilFunction funcIter(Function *to_find);
ilFunction findByEntry(uint32_t entry);
ilFunction createFunction();
bool valid(ilFunction iter);
void create(const QString &a);
bool load();
const QString & output_path() const {return m_output_path;}
const QString & project_name() const {return m_project_name;}
const QString & binary_path() const {return m_fname;}
QString output_name(const char *ext);
ilFunction funcIter(Function *to_find);
ilFunction findByEntry(uint32_t entry);
ilFunction createFunction(FunctionType *f, const QString & name);
bool valid(ilFunction iter);
int getSymIdxByAdd(uint32_t adr);
bool validSymIdx(size_t idx);
size_t symbolSize(size_t idx);
hlType symbolType(size_t idx);
const std::string &symbolName(size_t idx);
const SYM &getSymByIdx(size_t idx) const;
int getSymIdxByAddr(uint32_t adr);
bool validSymIdx(size_t idx);
size_t symbolSize(size_t idx);
hlType symbolType(size_t idx);
const QString & symbolName(size_t idx);
const SYM & getSymByIdx(size_t idx) const;
static Project *get();
PROG * binary() {return &prog;}
SourceMachine *machine();
static Project * get();
PROG * binary() {return &prog;}
SourceMachine *machine();
const FunctionListType &functions() const { return pProcList; }
FunctionListType &functions() { return pProcList; }
protected:
void writeGlobSymTable();
void initialize();
void writeGlobSymTable();
};
//extern Project g_proj;

View File

@ -4,9 +4,9 @@
*/
#include <stdint.h>
#include "error.h"
/* Extracts reg bits from middle of mod-reg-rm uint8_t */
#define REG(x) ((uint8_t)(x & 0x38) >> 3)
//#define LH(p) ((int)((uint8_t *)(p))[0] + ((int)((uint8_t *)(p))[1] << 8))
struct ICODE;
/* Extracts reg bits from middle of mod-reg-rm uint8_t */
extern eErrorId scan(uint32_t ip, ICODE &p);

View File

@ -11,7 +11,7 @@
struct STATE
{
uint32_t IP; /* Offset into Image */
int16_t r[INDEX_BX_SI]; /* Value of segs and AX */
uint16_t r[INDEX_BX_SI]; /* Value of segs and AX */
bool f[INDEX_BX_SI]; /* True if r[.] has a value */
struct
{ /* For case stmt indexed reg */
@ -30,6 +30,10 @@ struct STATE
memset(r,0,sizeof(int16_t)*INDEX_BX_SI); //TODO: move this to machine_x86
memset(f,0,sizeof(uint8_t)*INDEX_BX_SI);
}
void setMemoryByte(uint32_t addr,uint8_t val)
{
//TODO: make this into a full scale value tracking class !
}
};

View File

@ -3,18 +3,22 @@
* (C) Mike van Emmerik
*/
#pragma once
#include <string>
#include <stdint.h>
#include "Enums.h"
#include "types.h"
struct COND_EXPR;
#include "msvc_fixes.h"
#include <QtCore/QString>
#include <string>
#include <stdint.h>
struct Expr;
struct AstIdent;
struct TypeContainer;
/* * * * * * * * * * * * * * * * * */
/* Symbol table structs and protos */
/* * * * * * * * * * * * * * * * * */
struct SymbolCommon
{
std::string name; /* New name for this variable/symbol/argument */
QString name; /* New name for this variable/symbol/argument */
int size; /* Size/maximum size */
hlType type; /* probable type */
eDuVal duVal; /* DEF, USE, VAL */
@ -23,30 +27,25 @@ struct SymbolCommon
};
struct SYM : public SymbolCommon
{
typedef uint32_t tLabel;
SYM() : label(0),flg(0)
{
}
int32_t label; /* physical address (20 bit) */
uint32_t label; /* physical address (20 bit) */
uint32_t flg; /* SEG_IMMED, IMPURE, WORD_OFF */
};
/* STACK FRAME */
struct STKSYM : public SymbolCommon
{
COND_EXPR *actual; /* Expression tree of actual parameter */
COND_EXPR *regs; /* For register arguments only */
int16_t label; /* Immediate off from BP (+:args, -:params) */
uint8_t regOff; /* Offset is a register (e.g. SI, DI) */
bool hasMacro; /* This type needs a macro */
std::string macro; /* Macro name */
bool invalid; /* Boolean: invalid entry in formal arg list*/
STKSYM()
{
actual=regs=0;
label=0;
regOff=0;
invalid=hasMacro = false;
}
typedef int16_t tLabel;
Expr * actual=0; /* Expression tree of actual parameter */
AstIdent * regs=0; /* For register arguments only */
tLabel label=0; /* Immediate off from BP (+:args, -:params) */
uint8_t regOff=0; /* Offset is a register (e.g. SI, DI) */
bool hasMacro=false; /* This type needs a macro */
QString macro; /* Macro name */
bool invalid=false; /* Boolean: invalid entry in formal arg list*/
void setArgName(int i)
{
char buf[32];
@ -60,13 +59,13 @@ class SymbolTableCommon : public std::vector<T>
public:
typedef typename std::vector<T>::iterator iterator;
typedef typename std::vector<T>::const_iterator const_iterator;
iterator findByLabel(int lab)
iterator findByLabel(typename T::tLabel lab)
{
auto iter = std::find_if(this->begin(),this->end(),
[lab](T &s)->bool {return s.label==lab;});
return iter;
}
const_iterator findByLabel(int lab) const
const_iterator findByLabel(typename T::tLabel lab) const
{
auto iter = std::find_if(this->begin(),this->end(),
[lab](const T &s)->bool {return s.label==lab;});
@ -95,19 +94,19 @@ struct SYMTABLE
{
// does not yse pSymName, to ease finding by symOff/symProc combo
// in map<SYMTABLE,X>
return (symOff==other.symOff) && symProc==(other.symProc);
return (symOff==other.symOff) and symProc==(other.symProc);
}
};
enum tableType /* The table types */
{
Label=0, /* The label table */
Comment, /* The comment table */
NUM_TABLE_TYPES /* Number of entries: must be last */
Comment /* The comment table */
};
constexpr int NUM_TABLE_TYPES = int(Comment)+1; /* Number of entries: must be last */
void createSymTables(void);
void destroySymTables(void);
boolT readVal (std::ostringstream &symName, uint32_t symOff, Function *symProc);
bool readVal (QTextStream & symName, uint32_t symOff, Function *symProc);
void selectTable(tableType); /* Select a particular table */

View File

@ -1,19 +1,21 @@
/****************************************************************************
/*
***************************************************************************
* dcc project general header
* (C) Cristina Cifuentes, Mike van Emmerik
****************************************************************************/
***************************************************************************
*/
#pragma once
#include "Enums.h"
#include "msvc_fixes.h"
#include <cassert>
#include <stdint.h>
#include "Enums.h"
#include <stdlib.h>
/**** Common definitions and macros ****/
#define MAX 0x7FFFFFFF
/* Type definitions used in the program */
typedef unsigned char byte; /* 8 bits */
typedef unsigned short word;/* 16 bits */
typedef short int16; /* 16 bits */
typedef unsigned char boolT; /* 8 bits */
#define SYNTHESIZED_MIN 0x100000 /* Synthesized labs use bits 21..32 */
@ -22,17 +24,17 @@ typedef unsigned char boolT; /* 8 bits */
#define PATLEN 23 /* Length of proc patterns */
#define WILD 0xF4 /* The wild byte */
/****** MACROS *******/
/* MACROS */
/* Macro reads a LH word from the image regardless of host convention */
/* Returns a 16 bit quantity, e.g. C000 is read into an Int as C000 */
// Macro reads a LH word from the image regardless of host convention
// Returns a 16 bit quantity, e.g. C000 is read into an Int as C000
//#define LH(p) ((int16)((byte *)(p))[0] + ((int16)((byte *)(p))[1] << 8))
#define LH(p) ((word)((byte *)(p))[0] + ((word)((byte *)(p))[1] << 8))
#define LH(p) ((uint16_t)((uint8_t *)(p))[0] + ((uint16_t)((uint8_t *)(p))[1] << 8))
/* Macro reads a LH word from the image regardless of host convention */
/* Returns a signed quantity, e.g. C000 is read into an Int as FFFFC000 */
#define LH_SIGNED(p) (((byte *)(p))[0] + (((char *)(p))[1] << 8))
#define LH_SIGNED(p) (((uint8_t *)(p))[0] + (((char *)(p))[1] << 8))
/* Macro tests bit b for type t in prog.map */
#define BITMAP(b, t) (prog.map[(b) >> 2] & ((t) << (((b) & 3) << 1)))
@ -53,24 +55,35 @@ struct eDuVal
USE=2,
VAL=4
};
int def :1; /* Variable was first defined than used */
int use :1; /* Variable was first used than defined */
int val :1; /* Variable has an initial value. 2 cases:
* 1. When variable is used first (ie. global)
* 2. When a value is moved into the variable
* for the first time. */
uint8_t def :1; //!< Variable was first defined than used
uint8_t use :1; //!< Variable was first used than defined
uint8_t val :1; /* Variable has an initial value. 2 cases:
1. When variable is used first (ie. global)
2. When a value is moved into the variable
for the first time.
*/
void setFlags(uint16_t x)
{
def = x&DEF;
use = x&USE;
val = x&VAL;
}
bool isUSE_VAL() {return use&&val;} /* Use and Val */
bool isUSE_VAL() {return use and val;} //Use and Val
};
static constexpr const char * hlTypes[13] = {
"", "char", "unsigned char", "int", "unsigned int",
"long", "unsigned long", "record", "int *", "char *",
"", "float", "double"
"",
"char",
"unsigned char",
"int",
"unsigned int",
"long",
"unsigned long",
"record",
"int *",
"char *",
"",
"float",
"double"
};
struct TypeContainer
@ -88,6 +101,12 @@ struct TypeContainer
return 2;
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
return 1;
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
return 4;
case TYPE_FLOAT:
return 4;
default:
return ~0;
}
return 0;
}

BIN
prototypes/dcclibs.dat Normal file

Binary file not shown.

View File

@ -14,8 +14,10 @@ def perform_test(exepath,filepath,outname,args)
filepath=path_local(filepath)
joined_args = args.join(' ')
printf("calling:" + "#{exepath} -a1 #{joined_args} -o#{output_path}.a1 #{filepath}\n")
result = `#{exepath} -a1 -o#{output_path}.a1 #{filepath}`
result = `#{exepath} -a2 #{joined_args} -o#{output_path}.a2 #{filepath}`
STDERR << "Errors for : #{filepath}\n"
result = `#{exepath} -a 1 -o#{output_path}.a1 #{filepath}`
result = `#{exepath} -a 2 #{joined_args} -o#{output_path}.a2 #{filepath}`
result = `#{exepath} #{joined_args} -o#{output_path} #{filepath}`
puts result
p $?
end

BIN
sigs/dccb2s.sig Normal file

Binary file not shown.

View File

@ -1,15 +1,20 @@
#include "BasicBlock.h"
#include "msvc_fixes.h"
#include "Procedure.h"
#include "dcc.h"
#include "msvc_fixes.h"
#include <QtCore/QTextStream>
#include <cassert>
#include <string>
#include <boost/range/rbegin.hpp>
#include <boost/range/rend.hpp>
#include <boost/range/adaptors.hpp>
#include "BasicBlock.h"
#include "Procedure.h"
#include "dcc.h"
using namespace std;
using namespace boost;
BB *BB::Create(void *ctx, const string &s, Function *parent, BB *insertBefore)
BB *BB::Create(void */*ctx*/, const string &/*s*/, Function *parent, BB */*insertBefore*/)
{
BB *pnewBB = new BB;
pnewBB->Parent = parent;
@ -19,7 +24,7 @@ BB *BB::Create(void *ctx, const string &s, Function *parent, BB *insertBefore)
* @arg start - basic block starts here, might be parent->Icode.end()
* @arg fin - last of basic block's instructions
*/
BB *BB::Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, Function *parent)
BB *BB::Create(const rCODE &r,eBBKind _nodeType, Function *parent)
{
BB* pnewBB;
pnewBB = new BB;
@ -27,47 +32,30 @@ BB *BB::Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, Fun
pnewBB->immedDom = NO_DOM;
pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail =
pnewBB->latchNode= pnewBB->loopFollow = NO_NODE;
pnewBB->instructions = make_iterator_range(start,fin);
if(start==parent->Icode.end())
{
pnewBB->instructions = make_iterator_range(parent->Icode.end(),parent->Icode.end());
}
else
{
pnewBB->instructions.advance_end(1); // 1 after fin, to create range where fin is inclusive
}
if (numOutEdges)
pnewBB->edges.resize(numOutEdges);
pnewBB->instructions = r;
/* Mark the basic block to which the icodes belong to, but only for
* real code basic blocks (ie. not interval bbs) */
* real code basic blocks (ie. not interval bbs) */
if(parent)
{
if (start != parent->Icode.end())
parent->Icode.SetInBB(pnewBB->instructions, pnewBB);
parent->heldBBs.push_back(pnewBB);
parent->m_cfg.push_back(pnewBB);
int addr = pnewBB->begin()->loc_ip;
//setInBB should automatically handle if our range is empty
parent->Icode.SetInBB(pnewBB->instructions, pnewBB);
assert(parent->m_ip_to_bb.find(addr)==parent->m_ip_to_bb.end());
parent->m_ip_to_bb[addr] = pnewBB;
parent->m_actual_cfg.push_back(pnewBB);
pnewBB->Parent = parent;
}
if ( start != parent->Icode.end() ) /* Only for code BB's */
if ( r.begin() != parent->Icode.end() ) /* Only for code BB's */
stats.numBBbef++;
}
return pnewBB;
}
BB *BB::Create(int start, int ip, uint8_t _nodeType, int numOutEdges, Function *parent)
BB *BB::CreateIntervalBB(Function *parent)
{
iICODE st(parent->Icode.begin());
iICODE fin(parent->Icode.begin());
if(start==-1)
{
st = parent->Icode.end();
fin = parent->Icode.end();
}
else
{
advance(st,start);
advance(fin,ip);
}
return Create(st,fin,_nodeType,numOutEdges,parent);
iICODE endOfParent = parent->Icode.end();
return Create(make_iterator_range(endOfParent,endOfParent),INTERVAL_NODE,nullptr);
}
static const char *const s_nodeType[] = {"branch", "if", "case", "fall", "return", "call",
@ -81,14 +69,14 @@ static const char *const s_loopType[] = {"noLoop", "while", "repeat", "loop", "f
void BB::display()
{
printf("\nnode type = %s, ", s_nodeType[nodeType]);
printf("start = %ld, length = %ld, #out edges = %ld\n", begin()->loc_ip, size(), edges.size());
printf("start = %d, length = %zd, #out edges = %zd\n", begin()->loc_ip, size(), edges.size());
for (size_t i = 0; i < edges.size(); i++)
{
if(edges[i].BBptr==0)
printf(" outEdge[%2d] = Unlinked out edge to %d\n",i, edges[i].ip);
if(edges[i].BBptr==nullptr)
printf(" outEdge[%2zd] = Unlinked out edge to %d\n",i, edges[i].ip);
else
printf(" outEdge[%2d] = %d\n",i, edges[i].BBptr->begin()->loc_ip);
printf(" outEdge[%2zd] = %d\n",i, edges[i].BBptr->begin()->loc_ip);
}
}
/*****************************************************************************
@ -101,29 +89,29 @@ void BB::displayDfs()
traversed = DFS_DISP;
printf("node type = %s, ", s_nodeType[nodeType]);
printf("start = %ld, length = %ld, #in-edges = %ld, #out-edges = %ld\n",
printf("start = %d, length = %zd, #in-edges = %zd, #out-edges = %zd\n",
begin()->loc_ip, size(), inEdges.size(), edges.size());
printf("dfsFirst = %ld, dfsLast = %ld, immed dom = %ld\n",
printf("dfsFirst = %d, dfsLast = %d, immed dom = %d\n",
dfsFirstNum, dfsLastNum,
immedDom == MAX ? -1 : immedDom);
printf("loopType = %s, loopHead = %ld, latchNode = %ld, follow = %ld\n",
s_loopType[loopType],
printf("loopType = %s, loopHead = %d, latchNode = %d, follow = %d\n",
s_loopType[(int)loopType],
loopHead == MAX ? -1 : loopHead,
latchNode == MAX ? -1 : latchNode,
loopFollow == MAX ? -1 : loopFollow);
printf ("ifFollow = %ld, caseHead = %ld, caseTail = %ld\n",
printf ("ifFollow = %d, caseHead = %d, caseTail = %d\n",
ifFollow == MAX ? -1 : ifFollow,
caseHead == MAX ? -1 : caseHead,
caseTail == MAX ? -1 : caseTail);
if (nodeType == INTERVAL_NODE)
printf("corresponding interval = %ld\n", correspInt->numInt);
printf("corresponding interval = %d\n", correspInt->numInt);
else
{
int edge_idx=0;
for(BB *node : inEdges)
{
printf (" inEdge[%ld] = %ld\n", edge_idx, node->begin()->loc_ip);
printf (" inEdge[%d] = %d\n", edge_idx, node->begin()->loc_ip);
edge_idx++;
}
}
@ -132,9 +120,9 @@ void BB::displayDfs()
for(TYPEADR_TYPE &edg : edges)
{
if (nodeType == INTERVAL_NODE)
printf(" outEdge[%ld] = %ld\n", i, edg.BBptr->correspInt->numInt);
printf(" outEdge[%d] = %d\n", i, edg.BBptr->correspInt->numInt);
else
printf(" outEdge[%d] = %ld\n", i, edg.BBptr->begin()->loc_ip);
printf(" outEdge[%d] = %d\n", i, edg.BBptr->begin()->loc_ip);
++i;
}
printf("----\n");
@ -146,21 +134,22 @@ void BB::displayDfs()
pb.BBptr->displayDfs();
}
}
/* Recursive procedure that writes the code for the given procedure, pointed
* to by pBB.
* Parameters: pBB: pointer to the cfg.
* Icode: pointer to the Icode array for the cfg graph of the
* current procedure.
* indLevel: indentation level - used for formatting.
* numLoc: last # assigned to local variables */
ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, boolT &repCond)
/** Recursive procedure that writes the code for the given procedure, pointed
to by pBB.
\param indLevel indentation level - used for formatting.
\param numLoc: last # assigned to local variables
*/
ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, bool &repCond)
{
if(loopType == eNodeHeaderType::NO_TYPE)
return nullptr;
latch = pProc->m_dfsLast[this->latchNode];
std::ostringstream ostr;
QString ostr_contents;
QTextStream ostr(&ostr_contents);
ICODE* picode;
switch (loopType)
{
case WHILE_TYPE:
case eNodeHeaderType::WHILE_TYPE:
picode = &this->back();
/* Check for error in while condition */
@ -179,45 +168,48 @@ ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&lat
* the THEN path of the header node */
if (edges[ELSE].BBptr->dfsLastNum == loopFollow)
{
picode->hl()->replaceExpr(picode->hl()->expr()->inverse());
picode->hlU()->replaceExpr(picode->hl()->expr()->inverse());
}
{
string e=walkCondExpr (picode->hl()->expr(), pProc, numLoc);
QString e=picode->hl()->expr()->walkCondExpr (pProc, numLoc);
ostr << "\n"<<indentStr(indLevel)<<"while ("<<e<<") {\n";
}
picode->invalidate();
break;
case REPEAT_TYPE:
case eNodeHeaderType::REPEAT_TYPE:
ostr << "\n"<<indentStr(indLevel)<<"do {\n";
picode = &latch->back();
picode->invalidate();
break;
case ENDLESS_TYPE:
case eNodeHeaderType::ENDLESS_TYPE:
ostr << "\n"<<indentStr(indLevel)<<"for (;;) {\n";
picode = &latch->back();
break;
}
cCode.appendCode(ostr.str());
ostr.flush();
cCode.appendCode(ostr_contents);
stats.numHLIcode += 1;
indLevel++;
return picode;
}
bool BB::isEndOfPath(int latch_node_idx) const
{
return nodeType == RETURN_NODE || nodeType == TERMINATE_NODE ||
nodeType == NOWHERE_NODE || (dfsLastNum == latch_node_idx);
return nodeType == RETURN_NODE or nodeType == TERMINATE_NODE or
nodeType == NOWHERE_NODE or dfsLastNum == latch_node_idx;
}
void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode, int _ifFollow)
{
int follow; /* ifFollow */
BB * succ, *latch; /* Successor and latching node */
BB * succ, *latch; /* Successor and latching node */
ICODE * picode; /* Pointer to HLI_JCOND instruction */
char *l; /* Pointer to HLI_JCOND expression */
boolT emptyThen, /* THEN clause is empty */
repCond; /* Repeat condition for while() */
QString l; /* Pointer to HLI_JCOND expression */
bool emptyThen, /* THEN clause is empty */
repCond; /* Repeat condition for while() */
/* Check if this basic block should be analysed */
if ((_ifFollow != UN_INIT) && (this == pProc->m_dfsLast[_ifFollow]))
if ((_ifFollow != UN_INIT) and (this == pProc->m_dfsLast[_ifFollow]))
return;
if (wasTraversedAtLevel(DFS_ALPHA))
@ -226,18 +218,17 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
/* Check for start of loop */
repCond = false;
latch = NULL;
if (loopType)
{
latch = nullptr;
picode=writeLoopHeader(indLevel, pProc, numLoc, latch, repCond);
}
/* Write the code for this basic block */
if (repCond == false)
{
std::ostringstream ostr;
QString ostr_contents;
QTextStream ostr(&ostr_contents);
writeBB(ostr,indLevel, pProc, numLoc);
cCode.appendCode(ostr.str());
ostr.flush();
cCode.appendCode(ostr_contents);
}
/* Check for end of path */
@ -245,12 +236,12 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
return;
/* Check type of loop/node and process code */
if ( loopType) /* there is a loop */
if ( loopType!=eNodeHeaderType::NO_TYPE ) /* there is a loop */
{
assert(latch);
if (this != latch) /* loop is over several bbs */
{
if (loopType == WHILE_TYPE)
if (loopType == eNodeHeaderType::WHILE_TYPE)
{
succ = edges[THEN].BBptr;
if (succ->dfsLastNum == loopFollow)
@ -266,9 +257,10 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
/* Loop epilogue: generate the loop trailer */
indLevel--;
if (loopType == WHILE_TYPE)
if (loopType == eNodeHeaderType::WHILE_TYPE)
{
std::ostringstream ostr;
QString ostr_contents;
QTextStream ostr(&ostr_contents);
/* Check if there is need to repeat other statements involved
* in while condition, then, emit the loop trailer */
if (repCond)
@ -276,18 +268,23 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
writeBB(ostr,indLevel+1, pProc, numLoc);
}
ostr <<indentStr(indLevel)<< "} /* end of while */\n";
cCode.appendCode(ostr.str());
ostr.flush();
cCode.appendCode(ostr_contents);
}
else if (loopType == ENDLESS_TYPE)
else if (loopType == eNodeHeaderType::ENDLESS_TYPE)
cCode.appendCode( "%s} /* end of loop */\n",indentStr(indLevel));
else if (loopType == REPEAT_TYPE)
else if (loopType == eNodeHeaderType::REPEAT_TYPE)
{
QString e = "//*failed*//";
if (picode->hl()->opcode != HLI_JCOND)
reportError (REPEAT_FAIL);
{
string e=walkCondExpr (picode->hl()->expr(), pProc, numLoc);
cCode.appendCode( "%s} while (%s);\n", indentStr(indLevel),e.c_str());
reportError (REPEAT_FAIL);
}
else
{
e=picode->hl()->expr()->walkCondExpr (pProc, numLoc);
}
cCode.appendCode( "%s} while (%s);\n", indentStr(indLevel),qPrintable(e));
}
/* Recurse on the loop follow */
@ -319,13 +316,13 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
if (succ->dfsLastNum != follow) /* THEN part */
{
l = writeJcond ( *back().hl(), pProc, numLoc);
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l);
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), qPrintable(l));
succ->writeCode (indLevel, pProc, numLoc, _latchNode,follow);
}
else /* empty THEN part => negate ELSE part */
{
l = writeJcondInv ( *back().hl(), pProc, numLoc);
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l);
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), qPrintable(l));
edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, follow);
emptyThen = true;
}
@ -345,7 +342,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
}
/* else (empty ELSE part) */
}
else if (! emptyThen) /* already visited => emit label */
else if (not emptyThen) /* already visited => emit label */
{
cCode.appendCode( "%s}\n%selse {\n",
indentStr(indLevel-1), indentStr(indLevel - 1));
@ -361,7 +358,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
else /* no follow => if..then..else */
{
l = writeJcond ( *back().hl(), pProc, numLoc);
cCode.appendCode( "%s%s", indentStr(indLevel-1), l);
cCode.appendCode( "%s%s", indentStr(indLevel-1), qPrintable(l));
edges[THEN].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow);
cCode.appendCode( "%s}\n%selse {\n", indentStr(indLevel-1), indentStr(indLevel - 1));
edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow);
@ -384,7 +381,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
* Args: pBB: pointer to the current basic block.
* Icode: pointer to the array of icodes for current procedure.
* lev: indentation level - used for formatting. */
void BB::writeBB(std::ostream &ostr,int lev, Function * pProc, int *numLoc)
void BB::writeBB(QTextStream &ostr,int lev, Function * pProc, int *numLoc)
{
/* Save the index into the code table in case there is a later goto
* into this instruction (first instruction of the BB) */
@ -394,10 +391,10 @@ void BB::writeBB(std::ostream &ostr,int lev, Function * pProc, int *numLoc)
for(ICODE &pHli : instructions)
{
if ((pHli.type == HIGH_LEVEL) && ( pHli.valid() )) //TODO: use filtering range here.
if ((pHli.type == HIGH_LEVEL_ICODE) and ( pHli.valid() )) //TODO: use filtering range here.
{
std::string line = pHli.hl()->write1HlIcode(pProc, numLoc);
if (!line.empty())
QString line = pHli.hl()->write1HlIcode(pProc, numLoc);
if (not line.isEmpty())
{
ostr<<indentStr(lev)<<line;
stats.numHLIcode++;
@ -410,27 +407,26 @@ void BB::writeBB(std::ostream &ostr,int lev, Function * pProc, int *numLoc)
iICODE BB::begin()
{
return instructions.begin();//range_start;
return instructions.begin();
}
iICODE BB::end() const
{
return instructions.end();//range_end
return instructions.end();
}
ICODE &BB::back()
{
return instructions.back();//*rbegin();
return instructions.back();
}
size_t BB::size()
{
return distance(instructions.begin(),instructions.end());
}
ICODE &BB::front()
{
return instructions.front();//*begin();
return instructions.front();
}
riICODE BB::rbegin()

View File

@ -1,7 +1,13 @@
SET(dcc_test_SOURCES tests/comwrite.cpp)
SET(dcc_test_SOURCES
tests/comwrite.cpp
tests/project.cpp
tests/loader.cpp
)
include_directories(${GMOCK_INCLUDE_DIRS} ${GMOCK_ROOT}/gtest/include)
enable_testing()
add_executable(tester ${dcc_test_SOURCES})
target_link_libraries(tester
ADD_DEPENDENCIES(tester dcc_lib)
target_link_libraries(tester dcc_lib disasm_s
${GMOCK_BOTH_LIBRARIES} ${REQ_LLVM_LIBRARIES})
add_test(dcc-tests tester)

37
src/CallConvention.cpp Normal file
View File

@ -0,0 +1,37 @@
#include <ostream>
#include <cassert>
#include "CallConvention.h"
#include <QtCore/QTextStream>
CConv *CConv::create(Type v)
{
static C_CallingConvention *c_call = nullptr;
static Pascal_CallingConvention *p_call = nullptr;
static Unknown_CallingConvention *u_call= nullptr;
if(nullptr==c_call)
c_call = new C_CallingConvention;
if(nullptr==p_call)
p_call = new Pascal_CallingConvention;
if(nullptr==u_call)
u_call = new Unknown_CallingConvention;
switch(v) {
case eUnknown: return u_call;
case eCdecl: return c_call;
case ePascal: return p_call;
}
assert(false);
return nullptr;
}
void C_CallingConvention::writeComments(QTextStream & ostr)
{
ostr << " * C calling convention.\n";
}
void Pascal_CallingConvention::writeComments(QTextStream & ostr)
{
ostr << " * Pascal calling convention.\n";
}
void Unknown_CallingConvention::writeComments(QTextStream & ostr)
{
ostr << " * Unknown calling convention.\n";
}

535
src/DccFrontend.cpp Normal file
View File

@ -0,0 +1,535 @@
#include "DccFrontend.h"
#include "dcc.h"
#include "msvc_fixes.h"
#include "project.h"
#include "disassem.h"
#include "CallGraph.h"
#include <QtCore/QFileInfo>
#include <QtCore/QDebug>
#include <cstdio>
class Loader
{
bool loadIntoProject(IProject *);
};
struct PSP { /* PSP structure */
uint16_t int20h; /* interrupt 20h */
uint16_t eof; /* segment, end of allocation block */
uint8_t res1; /* reserved */
uint8_t dosDisp[5]; /* far call to DOS function dispatcher */
uint8_t int22h[4]; /* vector for terminate routine */
uint8_t int23h[4]; /* vector for ctrl+break routine */
uint8_t int24h[4]; /* vector for error routine */
uint8_t res2[22]; /* reserved */
uint16_t segEnv; /* segment address of environment block */
uint8_t res3[34]; /* reserved */
uint8_t int21h[6]; /* opcode for int21h and far return */
uint8_t res4[6]; /* reserved */
uint8_t fcb1[16]; /* default file control block 1 */
uint8_t fcb2[16]; /* default file control block 2 */
uint8_t res5[4]; /* reserved */
uint8_t cmdTail[0x80]; /* command tail and disk transfer area */
};
static struct MZHeader { /* EXE file header */
uint8_t sigLo; /* .EXE signature: 0x4D 0x5A */
uint8_t sigHi;
uint16_t lastPageSize; /* Size of the last page */
uint16_t numPages; /* Number of pages in the file */
uint16_t numReloc; /* Number of relocation items */
uint16_t numParaHeader; /* # of paragraphs in the header */
uint16_t minAlloc; /* Minimum number of paragraphs */
uint16_t maxAlloc; /* Maximum number of paragraphs */
uint16_t initSS; /* Segment displacement of stack */
uint16_t initSP; /* Contents of SP at entry */
uint16_t checkSum; /* Complemented checksum */
uint16_t initIP; /* Contents of IP at entry */
uint16_t initCS; /* Segment displacement of code */
uint16_t relocTabOffset; /* Relocation table offset */
uint16_t overlayNum; /* Overlay number */
} header;
#define EXE_RELOCATION 0x10 /* EXE images rellocated to above PSP */
//static void LoadImage(char *filename);
static void displayMemMap(void);
/****************************************************************************
* displayLoadInfo - Displays low level loader type info.
***************************************************************************/
void PROG::displayLoadInfo(void)
{
int i;
printf("File type is %s\n", (fCOM)?"COM":"EXE");
if (not fCOM) {
printf("Signature = %02X%02X\n", header.sigLo, header.sigHi);
printf("File size %% 512 = %04X\n", LH(&header.lastPageSize));
printf("File size / 512 = %04X pages\n", LH(&header.numPages));
printf("# relocation items = %04X\n", LH(&header.numReloc));
printf("Offset to load image = %04X paras\n", LH(&header.numParaHeader));
printf("Minimum allocation = %04X paras\n", LH(&header.minAlloc));
printf("Maximum allocation = %04X paras\n", LH(&header.maxAlloc));
}
printf("Load image size = %08lX\n", cbImage - sizeof(PSP));
printf("Initial SS:SP = %04X:%04X\n", initSS, initSP);
printf("Initial CS:IP = %04X:%04X\n", initCS, initIP);
if (option.VeryVerbose and cReloc)
{
printf("\nRelocation Table\n");
for (i = 0; i < cReloc; i++)
{
printf("%06X -> [%04X]\n", relocTable[i],LH(image() + relocTable[i]));
}
}
printf("\n");
}
/*****************************************************************************
* fill - Fills line for displayMemMap()
****************************************************************************/
static void fill(int ip, char *bf)
{
PROG &prog(Project::get()->prog);
static uint8_t type[4] = {'.', 'd', 'c', 'x'};
uint8_t i;
for (i = 0; i < 16; i++, ip++)
{
*bf++ = ' ';
*bf++ = (ip < prog.cbImage)? type[(prog.map[ip >> 2] >> ((ip & 3) * 2)) & 3]: ' ';
}
*bf = '\0';
}
/*****************************************************************************
* displayMemMap - Displays the memory bitmap
****************************************************************************/
static void displayMemMap(void)
{
PROG &prog(Project::get()->prog);
char c, b1[33], b2[33], b3[33];
uint8_t i;
int ip = 0;
printf("\nMemory Map\n");
while (ip < prog.cbImage)
{
fill(ip, b1);
printf("%06X %s\n", ip, b1);
ip += 16;
for (i = 3, c = b1[1]; i < 32 and c == b1[i]; i += 2)
; /* Check if all same */
if (i > 32)
{
fill(ip, b2); /* Skip until next two are not same */
fill(ip+16, b3);
if (not (strcmp(b1, b2) || strcmp(b1, b3)))
{
printf(" :\n");
do
{
ip += 16;
fill(ip+16, b1);
} while (0==strcmp(b1, b2));
}
}
}
printf("\n");
}
DccFrontend::DccFrontend(QObject *parent) :
QObject(parent)
{
}
/*****************************************************************************
* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode
* rewritter, and displays any useful information.
****************************************************************************/
bool DccFrontend::FrontEnd ()
{
/* Do depth first flow analysis building call graph and procedure list,
* and attaching the I-code to each procedure */
parse (*Project::get());
if (option.asm1)
{
qWarning() << "dcc: writing assembler file "<<asm1_name<<'\n';
}
/* Search through code looking for impure references and flag them */
Disassembler ds(1);
for(Function &f : Project::get()->pProcList)
{
f.markImpure();
if (option.asm1)
{
ds.disassem(&f);
}
}
if (option.Interact)
{
interactDis(&Project::get()->pProcList.front(), 0); /* Interactive disassembler */
}
/* Converts jump target addresses to icode offsets */
for(Function &f : Project::get()->pProcList)
{
f.bindIcodeOff();
}
/* Print memory bitmap */
if (option.Map)
displayMemMap();
return(true); // we no longer own proj !
}
struct DosLoader {
protected:
void prepareImage(PROG &prog,size_t sz,QFile &fp) {
/* Allocate a block of memory for the program. */
prog.cbImage = sz + sizeof(PSP);
prog.Imagez = new uint8_t [prog.cbImage];
prog.Imagez[0] = 0xCD; /* Fill in PSP int 20h location */
prog.Imagez[1] = 0x20; /* for termination checking */
/* Read in the image past where a PSP would go */
if (sz != fp.read((char *)prog.Imagez + sizeof(PSP),sz))
fatalError(CANNOT_READ, fp.fileName().toLocal8Bit().data());
}
};
struct ComLoader : public DosLoader {
bool canLoad(QFile &fp) {
fp.seek(0);
char sig[2];
if(2==fp.read(sig,2)) {
return not (sig[0] == 0x4D and sig[1] == 0x5A);
}
return false;
}
bool load(PROG &prog,QFile &fp) {
fp.seek(0);
/* COM file
* In this case the load module size is just the file length
*/
auto cb = fp.size();
/* COM programs start off with an ORG 100H (to leave room for a PSP)
* This is also the implied start address so if we load the image
* at offset 100H addresses should all line up properly again.
*/
prog.initCS = 0;
prog.initIP = 0x100;
prog.initSS = 0;
prog.initSP = 0xFFFE;
prog.cReloc = 0;
prepareImage(prog, cb, fp);
/* Set up memory map */
cb = (prog.cbImage + 3) / 4;
prog.map = (uint8_t *)malloc(cb);
memset(prog.map, BM_UNKNOWN, (size_t)cb);
return true;
}
};
#if 0
struct RomLoader {
bool canLoad(QFile &fp) {
fp.seek(0xFFF0);
uint8_t sig[1];
if(fp.read((char *)sig,1) == 1)
{
return (sig[0] == 0xEA);
}
return false;
}
bool load(PROG &prog,QFile &fp) {
printf("Loading ROM...\n");
fp.seek(0);
/* ROM file
* In this case the load module size is just the file length
*/
auto cb = fp.size();
fp.seek(cb - 0x10);
uint8_t buf[5];
printf("Going to get CS/IP...\n");
if(fp.read((char *)buf, 5) != 5)
{
return false;
}
fp.seek(0);
/* ROM File, Hard to say where it is suppose to start, so try to trust the
*/
prog.initIP = (buf[2] << 8) | buf[1];
//prog.initCS = 0;
prog.initCS = (buf[4] << 8) | buf[3];
prog.initSS = 0;
prog.initSP = 0xFFFE;
prog.cReloc = 0;
prepareImage(prog, cb, fp);
/* Set up memory map */
cb = (prog.cbImage + 3) / 4;
prog.map = (uint8_t *)malloc(cb);
memset(prog.map, BM_UNKNOWN, (size_t)cb);
return true;
}
protected:
void prepareImage(PROG &prog, size_t sz, QFile &fp)
{
int32_t start = 0x100000 - sz;
/* Allocate a block of memory for the program. */
prog.cbImage = 1 * 1024 * 1024; /* Allocate the whole 1MB memory */
//prog.cbImage = 64 * 1024; /* Allocate the whole 1MB memory */
prog.Imagez = new uint8_t [prog.cbImage];
if (fp.read((char *)prog.Imagez + start, sz) != sz)
//if (fp.read((char *)prog.Imagez, sz) != sz)
{
fatalError(CANNOT_READ, fp.fileName().toLocal8Bit().data());
}
}
};
#else
struct RomLoader {
bool canLoad(QFile &fp) {
fp.seek(0xFFF0);
uint8_t sig[1];
if(fp.read((char *)sig,1) == 1)
{
return (sig[0] == 0xEA);
}
return false;
}
bool load(PROG &prog,QFile &fp) {
fp.seek(0);
/* COM file
* In this case the load module size is just the file length
*/
auto cb = fp.size();
/* COM programs start off with an ORG 100H (to leave room for a PSP)
* This is also the implied start address so if we load the image
* at offset 100H addresses should all line up properly again.
*/
prog.initCS = 0;
prog.initIP = 0x000;
prog.initSS = 0;
prog.initSP = 0xFFFE;
prog.cReloc = 0;
prepareImage(prog, cb, fp);
/* Set up memory map */
cb = (prog.cbImage + 3) / 4;
prog.map = (uint8_t *)malloc(cb);
memset(prog.map, BM_UNKNOWN, (size_t)cb);
return true;
}
protected:
void prepareImage(PROG &prog, size_t sz, QFile &fp)
{
/* Allocate a block of memory for the program. */
prog.cbImage = sz;
prog.Imagez = new uint8_t[prog.cbImage];
if (sz != fp.read((char *)prog.Imagez, sz))
fatalError(CANNOT_READ, fp.fileName().toLocal8Bit().data());
}
};
#endif
struct ExeLoader : public DosLoader {
bool canLoad(QFile &fp) {
if(fp.size()<sizeof(header))
return false;
MZHeader tmp_header;
fp.seek(0);
fp.read((char *)&tmp_header, sizeof(header));
if(not (tmp_header.sigLo == 0x4D and tmp_header.sigHi == 0x5A))
return false;
/* This is a typical DOS kludge! */
if (LH(&header.relocTabOffset) == 0x40)
{
qDebug() << "Don't understand new EXE format";
return false;
}
return true;
}
bool load(PROG &prog,QFile &fp) {
/* Read rest of header */
fp.seek(0);
if (fp.read((char *)&header, sizeof(header)) != sizeof(header))
return false;
/* Calculate the load module size.
* This is the number of pages in the file
* less the length of the header and reloc table
* less the number of bytes unused on last page
*/
uint32_t cb = (uint32_t)LH(&header.numPages) * 512 - (uint32_t)LH(&header.numParaHeader) * 16;
if (header.lastPageSize)
{
cb -= 512 - LH(&header.lastPageSize);
}
/* We quietly ignore minAlloc and maxAlloc since for our
* purposes it doesn't really matter where in real memory
* the program would end up. EXE programs can't really rely on
* their load location so setting the PSP segment to 0 is fine.
* Certainly programs that prod around in DOS or BIOS are going
* to have to load DS from a constant so it'll be pretty
* obvious.
*/
prog.initCS = (int16_t)LH(&header.initCS) + EXE_RELOCATION;
prog.initIP = (int16_t)LH(&header.initIP);
prog.initSS = (int16_t)LH(&header.initSS) + EXE_RELOCATION;
prog.initSP = (int16_t)LH(&header.initSP);
prog.cReloc = (int16_t)LH(&header.numReloc);
/* Allocate the relocation table */
if (prog.cReloc)
{
prog.relocTable.resize(prog.cReloc);
fp.seek(LH(&header.relocTabOffset));
/* Read in seg:offset pairs and convert to Image ptrs */
uint8_t buf[4];
for (int i = 0; i < prog.cReloc; i++)
{
fp.read((char *)buf,4);
prog.relocTable[i] = LH(buf) + (((int)LH(buf+2) + EXE_RELOCATION)<<4);
}
}
/* Seek to start of image */
uint32_t start_of_image= LH(&header.numParaHeader) * 16;
fp.seek(start_of_image);
/* Allocate a block of memory for the program. */
prepareImage(prog,cb,fp);
/* Set up memory map */
cb = (prog.cbImage + 3) / 4;
prog.map = (uint8_t *)malloc(cb);
memset(prog.map, BM_UNKNOWN, (size_t)cb);
/* Relocate segment constants */
for(uint32_t v : prog.relocTable) {
uint8_t *p = &prog.Imagez[v];
uint16_t w = (uint16_t)LH(p) + EXE_RELOCATION;
*p++ = (uint8_t)(w & 0x00FF);
*p = (uint8_t)((w & 0xFF00) >> 8);
}
return true;
}
};
/*****************************************************************************
* LoadImage
****************************************************************************/
bool Project::load()
{
// addTask(loaderSelection,PreCond(BinaryImage))
// addTask(applyLoader,PreCond(Loader))
const char *fname = binary_path().toLocal8Bit().data();
QFile finfo(binary_path());
/* Open the input file */
if(not finfo.open(QFile::ReadOnly)) {
fatalError(CANNOT_OPEN, fname);
}
/* Read in first 2 bytes to check EXE signature */
if (finfo.size()<=2)
{
fatalError(CANNOT_READ, fname);
}
RomLoader rom_loader;
ComLoader com_loader;
ExeLoader exe_loader;
if(rom_loader.canLoad(finfo)) {
/* We have no relacation and code should be on 64K only,
* So let's consider it as a COM file
*/
prog.fCOM = true;
return rom_loader.load(prog,finfo);
}
if(exe_loader.canLoad(finfo)) {
prog.fCOM = false;
return exe_loader.load(prog,finfo);
}
if(com_loader.canLoad(finfo)) {
prog.fCOM = true;
return com_loader.load(prog,finfo);
}
return false;
}
uint32_t SynthLab;
/* Parses the program, builds the call graph, and returns the list of
* procedures found */
void DccFrontend::parse(Project &proj)
{
PROG &prog(proj.prog);
STATE state;
/* Set initial state */
state.setState(rES, 0); /* PSP segment */
state.setState(rDS, 0);
state.setState(rCS, prog.initCS);
state.setState(rSS, prog.initSS);
state.setState(rSP, prog.initSP);
state.IP = ((uint32_t)prog.initCS << 4) + prog.initIP;
SynthLab = SYNTHESIZED_MIN;
/* Check for special settings of initial state, based on idioms of the
startup code */
state.checkStartup();
ilFunction start_proc;
/* Make a struct for the initial procedure */
if (prog.offMain != -1)
{
start_proc = proj.createFunction(0,"main");
start_proc->retVal.loc = REG_FRAME;
start_proc->retVal.type = TYPE_WORD_SIGN;
start_proc->retVal.id.regi = rAX;
/* We know where main() is. Start the flow of control from there */
start_proc->procEntry = prog.offMain;
/* In medium and large models, the segment of main may (will?) not be
the same as the initial CS segment (of the startup code) */
state.setState(rCS, prog.segMain);
state.IP = prog.offMain;
}
else
{
start_proc = proj.createFunction(0,"start");
/* Create initial procedure at program start address */
start_proc->procEntry = (uint32_t)state.IP;
}
/* The state info is for the first procedure */
start_proc->state = state;
/* Set up call graph initial node */
proj.callGraph = new CALL_GRAPH;
proj.callGraph->proc = start_proc;
/* This proc needs to be called to set things up for LibCheck(), which
checks a proc to see if it is a know C (etc) library */
prog.bSigs = SetupLibCheck();
//BUG: proj and g_proj are 'live' at this point !
/* Recursively build entire procedure list */
start_proc->FollowCtrl(proj.callGraph, &state);
/* This proc needs to be called to clean things up from SetupLibCheck() */
CleanupLibCheck();
}

View File

@ -1,6 +1,9 @@
#include "Procedure.h"
#include "msvc_fixes.h"
#include "project.h"
#include "scanner.h"
//FunctionType *Function::getFunctionType() const
//{
// return &m_type;
@ -14,8 +17,8 @@ void JumpTable::pruneEntries(uint16_t cs)
PROG *prg(Project::get()->binary());
for (uint32_t i = start; i < finish; i += 2)
{
uint32_t target = cs + LH(&prg->Image[i]);
if (target < finish && target >= start)
uint32_t target = cs + LH(&prg->image()[i]);
if (target < finish and target >= start)
finish = target;
else if (target >= (uint32_t)prg->cbImage)
finish = i;
@ -23,10 +26,15 @@ void JumpTable::pruneEntries(uint16_t cs)
ICODE _Icode; // used as scan input
for (uint32_t i = start; i < finish; i += 2)
{
uint32_t target = cs + LH(&prg->Image[i]);
uint32_t target = cs + LH(&prg->image()[i]);
/* Be wary of 00 00 as code - it's probably data */
if (! (prg->Image[target] || prg->Image[target+1]) || scan(target, _Icode))
if (not (prg->image()[target] or prg->image()[target+1]) or scan(target, _Icode))
finish = i;
}
}
void Function::callingConv(CConv::Type v) {
m_call_conv=CConv::create(v);
}

122
src/RegisterNode.cpp Normal file
View File

@ -0,0 +1,122 @@
#include "types.h"
#include "msvc_fixes.h"
#include "ast.h"
#include "bundle.h"
#include "machine_x86.h"
#include "project.h"
#include <stdint.h>
#include <string>
#include <sstream>
#include <iostream>
#include <cassert>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range.hpp>
//#include <boost/range/algorithm.hpp>
//#include <boost/assign.hpp>
using namespace std;
using namespace boost::adaptors;
RegisterNode::RegisterNode(const LLOperand &op, LOCAL_ID *locsym)
{
m_syms = locsym;
ident.type(REGISTER);
hlType type_sel;
regType reg_type;
if (op.byteWidth()==1)
{
type_sel = TYPE_BYTE_SIGN;
reg_type = BYTE_REG;
}
else /* uint16_t */
{
type_sel = TYPE_WORD_SIGN;
reg_type = WORD_REG;
}
regiIdx = locsym->newByteWordReg(type_sel, op.regi);
regiType = reg_type;
}
//RegisterNode::RegisterNode(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym)
//{
// ident.type(REGISTER);
// hlType type_sel;
// regType reg_type;
// if ((icodeFlg & B) or (icodeFlg & SRC_B))
// {
// type_sel = TYPE_BYTE_SIGN;
// reg_type = BYTE_REG;
// }
// else /* uint16_t */
// {
// type_sel = TYPE_WORD_SIGN;
// reg_type = WORD_REG;
// }
// regiIdx = locsym->newByteWordReg(type_sel, regi);
// regiType = reg_type;
//}
QString RegisterNode::walkCondExpr(Function *pProc, int *numLoc) const
{
QString codeOut;
QString o;
assert(&pProc->localId==m_syms);
ID *id = &pProc->localId.id_arr[regiIdx];
if (id->name[0] == '\0') /* no name */
{
id->setLocalName(++(*numLoc));
codeOut += QString("%1 %2; ").arg(TypeContainer::typeName(id->type)).arg(id->name);
codeOut += QString("/* %1 */\n").arg(Machine_X86::regName(id->id.regi));
}
if (id->hasMacro)
o += QString("%1(%2)").arg(id->macro).arg(id->name);
else
o += id->name;
cCode.appendDecl(codeOut);
return o;
}
int RegisterNode::hlTypeSize(Function *) const
{
if (regiType == BYTE_REG)
return 1;
else
return 2;
}
hlType RegisterNode::expType(Function *pproc) const
{
if (regiType == BYTE_REG)
return TYPE_BYTE_SIGN;
else
return TYPE_WORD_SIGN;
}
Expr *RegisterNode::insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym)
{
assert(locsym==m_syms);
eReg treeReg = locsym->id_arr[regiIdx].id.regi;
if (treeReg == regi) /* uint16_t reg */
{
return _expr;
}
else if(Machine_X86::isSubRegisterOf(treeReg,regi)) /* uint16_t/uint8_t reg */
{
return _expr;
}
return nullptr;
}
bool RegisterNode::xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId)
{
uint8_t regi = locId.id_arr[regiIdx].id.regi;
range_to_check.advance_begin(1);
auto all_valid_and_high_level_after_start = range_to_check | filtered(ICODE::select_valid_high_level);
for (ICODE &i : all_valid_and_high_level_after_start)
if (i.du.def.testRegAndSubregs(regi))
return false;
if (all_valid_and_high_level_after_start.end().base() != lastBBinst)
return true;
return false;
}

File diff suppressed because it is too large Load Diff

View File

@ -4,20 +4,34 @@
* Purpose: Back-end module. Generates C code for each procedure.
* (C) Cristina Cifuentes
****************************************************************************/
#include "dcc.h"
#include "msvc_fixes.h"
#include "disassem.h"
#include "project.h"
#include "CallGraph.h"
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QStringList>
#include <QtCore/QDebug>
#include <cassert>
#include <string>
#include <boost/range.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm.hpp>
#include "dcc.h"
#include "disassem.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <string.h>
#include <stdio.h>
#include "project.h"
bundle cCode; /* Procedure declaration and code */
using namespace boost;
using namespace boost::adaptors;
using namespace std;
bundle cCode; /* Procedure declaration and code */
/* Returns a unique index to the next label */
int getNextLabel()
{
@ -29,14 +43,14 @@ int getNextLabel()
/* displays statistics on the subroutine */
void Function::displayStats ()
{
printf("\nStatistics - Subroutine %s\n", name.c_str());
printf ("Number of Icode instructions:\n");
printf (" Low-level : %4d\n", stats.numLLIcode);
if (! (flg & PROC_ASM))
qDebug() << "\nStatistics - Subroutine" << name;
qDebug() << "Number of Icode instructions:";
qDebug() << " Low-level :" << stats.numLLIcode;
if (not (flg & PROC_ASM))
{
printf (" High-level: %4d\n", stats.numHLIcode);
printf (" Percentage reduction: %2.2f%%\n", 100.0 - (stats.numHLIcode *
100.0) / stats.numLLIcode);
qDebug() << " High-level:"<<stats.numHLIcode;
qDebug() << QString(" Percentage reduction: %1%%").arg(100.0 - (stats.numHLIcode *
100.0) / stats.numLLIcode,4,'f',2,QChar('0'));
}
}
@ -94,7 +108,7 @@ char *cChar (uint8_t c)
* Note: to get to the value of the variable:
* com file: prog.Image[operand]
* exe file: prog.Image[operand+0x100] */
static void printGlobVar (std::ostream &ostr,SYM * psym)
static void printGlobVar (QTextStream &ostr,SYM * psym)
{
int j;
PROG &prog(Project::get()->prog);
@ -103,24 +117,24 @@ static void printGlobVar (std::ostream &ostr,SYM * psym)
switch (psym->size)
{
case 1:
ostr << "uint8_t\t"<<psym->name<<" = "<<prog.Image[relocOp]<<";\n";
ostr << "uint8_t\t"<<psym->name<<" = "<<prog.image()[relocOp]<<";\n";
break;
case 2:
ostr << "uint16_t\t"<<psym->name<<" = "<<LH(prog.Image+relocOp)<<";\n";
ostr << "uint16_t\t"<<psym->name<<" = "<<LH(prog.image()+relocOp)<<";\n";
break;
case 4: if (psym->type == TYPE_PTR) /* pointer */
ostr << "uint16_t *\t"<<psym->name<<" = "<<LH(prog.Image+relocOp)<<";\n";
ostr << "uint16_t *\t"<<psym->name<<" = "<<LH(prog.image()+relocOp)<<";\n";
else /* char */
ostr << "char\t"<<psym->name<<"[4] = \""<<
prog.Image[relocOp]<<prog.Image[relocOp+1]<<
prog.Image[relocOp+2]<<prog.Image[relocOp+3]<<";\n";
prog.image()[relocOp]<<prog.image()[relocOp+1]<<
prog.image()[relocOp+2]<<prog.image()[relocOp+3]<<";\n";
break;
default:
{
ostringstream strContents;
QString strContents;
for (j=0; j < psym->size; j++)
strContents << cChar(prog.Image[relocOp + j]);
ostr << "char\t*"<<psym->name<<" = \""<<strContents.str()<<"\";\n";
strContents += cChar(prog.image()[relocOp + j]);
ostr << "char\t*"<<psym->name<<" = \""<<strContents<<"\";\n";
}
}
}
@ -131,7 +145,8 @@ static void printGlobVar (std::ostream &ostr,SYM * psym)
* initialization. */
void Project::writeGlobSymTable()
{
std::ostringstream ostr;
QString contents;
QTextStream ostr(&contents);
if (symtab.empty())
return;
@ -139,13 +154,13 @@ void Project::writeGlobSymTable()
for (SYM &sym : symtab)
{
if (sym.duVal.isUSE_VAL()) /* first used */
printGlobVar (ostr,&sym);
printGlobVar (ostr,&sym);
else { /* first defined */
switch (sym.size) {
case 1: ostr<<"uint8_t\t"; break;
case 2: ostr<<"int\t"; break;
case 2: ostr<<"int16_t\t"; break;
case 4: if (sym.type == TYPE_PTR)
ostr<<"int\t*";
ostr<<"int32_t\t*";
else
ostr<<"char\t*";
break;
@ -155,19 +170,20 @@ void Project::writeGlobSymTable()
}
}
ostr<< "\n";
cCode.appendDecl( ostr.str() );
ostr.flush();
cCode.appendDecl( contents );
}
/* Writes the header information and global variables to the output C file
* fp. */
static void writeHeader (std::ostream &_ios, char *fileName)
static void writeHeader (QIODevice &_ios, const std::string &fileName)
{
PROG &prog(Project::get()->prog);
/* Write header information */
cCode.init();
cCode.appendDecl( "/*\n");
cCode.appendDecl( " * Input file\t: %s\n", fileName);
cCode.appendDecl( " * Input file\t: %s\n", fileName.c_str());
cCode.appendDecl( " * File type\t: %s\n", (prog.fCOM)?"COM":"EXE");
cCode.appendDecl( " */\n\n#include \"dcc.h\"\n\n");
@ -178,11 +194,12 @@ static void writeHeader (std::ostream &_ios, char *fileName)
}
// Note: Not currently called!
/* Checks the given icode to determine whether it has a label associated
/** Checks the given icode to determine whether it has a label associated
* to it. If so, a goto is emitted to this label; otherwise, a new label
* is created and a goto is also emitted.
* Note: this procedure is to be used when the label is to be forward on
* the code; that is, the target code has not been traversed yet. */
#if 0
static void emitFwdGotoLabel (ICODE * pt, int indLevel)
{
if ( not pt->ll()->testFlags(HLL_LABEL)) /* node hasn't got a lab */
@ -193,14 +210,15 @@ static void emitFwdGotoLabel (ICODE * pt, int indLevel)
}
cCode.appendCode( "%sgoto l%ld;\n", indentStr(indLevel), pt->ll()->hllLabNum);
}
#endif
/* Writes the procedure's declaration (including arguments), local variables,
* and invokes the procedure that writes the code of the given record *hli */
void Function::codeGen (std::ostream &fs)
void Function::codeGen (QIODevice &fs)
{
int numLoc;
ostringstream ostr;
QString ostr_contents;
QTextStream ostr(&ostr_contents);
//STKFRAME * args; /* Procedure arguments */
//char buf[200], /* Procedure's definition */
// arg[30]; /* One argument */
@ -209,26 +227,27 @@ void Function::codeGen (std::ostream &fs)
/* Write procedure/function header */
cCode.init();
if (flg & PROC_IS_FUNC) /* Function */
ostr<< "\n"<<TypeContainer::typeName(retVal.type)<<" "<<name<<" (";
ostr << QString("\n%1 %2 (").arg(TypeContainer::typeName(retVal.type)).arg(name);
else /* Procedure */
ostr<< "\nvoid "<<name<<" (";
ostr << "\nvoid "+name+" (";
/* Write arguments */
for (size_t i = 0; i < args.size(); i++)
struct validArg
{
if ( args[i].invalid )
continue;
ostr<<hlTypes[args[i].type]<<" "<<args[i].name;
if (i < (args.size() - 1))
ostr<<", ";
bool operator()(STKSYM &s) { return s.invalid==false;}
};
QStringList parts;
for (STKSYM &arg : (args | filtered(validArg())))
{
parts << QString("%1 %2").arg(hlTypes[arg.type]).arg(arg.name);
}
ostr<<")\n";
ostr << parts.join(", ")+")\n";
/* Write comments */
writeProcComments( ostr );
/* Write local variables */
if (! (flg & PROC_ASM))
if (not (flg & PROC_ASM))
{
numLoc = 0;
for (ID &refId : localId )
@ -239,8 +258,8 @@ void Function::codeGen (std::ostream &fs)
if (refId.loc == REG_FRAME)
{
/* Register variables are assigned to a local variable */
if (((flg & SI_REGVAR) && (refId.id.regi == rSI)) ||
((flg & DI_REGVAR) && (refId.id.regi == rDI)))
if (((flg & SI_REGVAR) and (refId.id.regi == rSI)) or
((flg & DI_REGVAR) and (refId.id.regi == rDI)))
{
refId.setLocalName(++numLoc);
ostr << "int "<<refId.name<<";\n";
@ -256,7 +275,9 @@ void Function::codeGen (std::ostream &fs)
}
}
}
fs<<ostr.str();
ostr.flush();
fs.write(ostr_contents.toLatin1());
/* Write procedure's code */
if (flg & PROC_ASM) /* generate assembler */
{
@ -265,7 +286,7 @@ void Function::codeGen (std::ostream &fs)
}
else /* generate C */
{
m_cfg.front()->writeCode (1, this, &numLoc, MAX, UN_INIT);
m_actual_cfg.front()->writeCode (1, this, &numLoc, MAX, UN_INIT);
}
cCode.appendCode( "}\n\n");
@ -273,44 +294,49 @@ void Function::codeGen (std::ostream &fs)
freeBundle (&cCode);
/* Write Live register analysis information */
if (option.verbose)
if (option.verbose) {
QString debug_contents;
QTextStream debug_stream(&debug_contents);
for (size_t i = 0; i < numBBs; i++)
{
pBB = m_dfsLast[i];
if (pBB->flg & INVALID_BB) continue; /* skip invalid BBs */
cout << "BB "<<i<<"\n";
cout << " Start = "<<pBB->begin()->loc_ip;
cout << ", end = "<<pBB->begin()->loc_ip+pBB->size()<<"\n";
cout << " LiveUse = ";
Machine_X86::writeRegVector(cout,pBB->liveUse);
cout << "\n Def = ";
Machine_X86::writeRegVector(cout,pBB->def);
cout << "\n LiveOut = ";
Machine_X86::writeRegVector(cout,pBB->liveOut);
cout << "\n LiveIn = ";
Machine_X86::writeRegVector(cout,pBB->liveIn);
cout <<"\n\n";
debug_stream << "BB "<<i<<"\n";
debug_stream << " Start = "<<pBB->begin()->loc_ip;
debug_stream << ", end = "<<pBB->begin()->loc_ip+pBB->size()<<"\n";
debug_stream << " LiveUse = ";
Machine_X86::writeRegVector(debug_stream,pBB->liveUse);
debug_stream << "\n Def = ";
Machine_X86::writeRegVector(debug_stream,pBB->def);
debug_stream << "\n LiveOut = ";
Machine_X86::writeRegVector(debug_stream,pBB->liveOut);
debug_stream << "\n LiveIn = ";
Machine_X86::writeRegVector(debug_stream,pBB->liveIn);
debug_stream <<"\n\n";
}
debug_stream.flush();
qDebug() << debug_contents.toLatin1();
}
}
/* Recursive procedure. Displays the procedure's code in depth-first order
* of the call graph. */
static void backBackEnd (char *filename, CALL_GRAPH * pcallGraph, std::ostream &_ios)
static void backBackEnd (CALL_GRAPH * pcallGraph, QIODevice &_ios)
{
// IFace.Yield(); /* This is a good place to yield to other apps */
/* Check if this procedure has been processed already */
if ((pcallGraph->proc->flg & PROC_OUTPUT) ||
if ((pcallGraph->proc->flg & PROC_OUTPUT) or
(pcallGraph->proc->flg & PROC_ISLIB))
return;
pcallGraph->proc->flg |= PROC_OUTPUT;
/* Dfs if this procedure has any successors */
for (size_t i = 0; i < pcallGraph->outEdges.size(); i++)
for (auto & elem : pcallGraph->outEdges)
{
backBackEnd (filename, pcallGraph->outEdges[i], _ios);
backBackEnd (elem, _ios);
}
/* Generate code for this procedure */
@ -321,7 +347,7 @@ static void backBackEnd (char *filename, CALL_GRAPH * pcallGraph, std::ostream &
/* Generate statistics */
if (option.Stats)
pcallGraph->proc->displayStats ();
if (! (pcallGraph->proc->flg & PROC_ASM))
if (not (pcallGraph->proc->flg & PROC_ASM))
{
stats.totalLL += stats.numLLIcode;
stats.totalHL += stats.numHLIcode;
@ -330,33 +356,31 @@ static void backBackEnd (char *filename, CALL_GRAPH * pcallGraph, std::ostream &
/* Invokes the necessary routines to produce code one procedure at a time. */
void BackEnd (char *fileName, CALL_GRAPH * pcallGraph)
void BackEnd(CALL_GRAPH * pcallGraph)
{
std::ofstream fs; /* Output C file */
/* Get output file name */
std::string outNam(fileName);
outNam = outNam.substr(0,outNam.rfind("."))+".b"; /* b for beta */
QString outNam(Project::get()->output_name("b")); /* b for beta */
QFile fs(outNam); /* Output C file */
/* Open output file */
fs.open(outNam);
if(!fs.is_open())
fatalError (CANNOT_OPEN, outNam.c_str());
printf ("dcc: Writing C beta file %s\n", outNam.c_str());
if(not fs.open(QFile::WriteOnly|QFile::Text))
fatalError (CANNOT_OPEN, outNam.toStdString().c_str());
qDebug()<<"dcc: Writing C beta file"<<outNam;
/* Header information */
writeHeader (fs, fileName);
writeHeader (fs, option.filename.toStdString());
/* Initialize total Icode instructions statistics */
stats.totalLL = 0;
stats.totalHL = 0;
/* Process each procedure at a time */
backBackEnd (fileName, pcallGraph, fs);
backBackEnd (pcallGraph, fs);
/* Close output file */
fs.close();
printf ("dcc: Finished writing C beta file\n");
qDebug() << "dcc: Finished writing C beta file";
}

View File

@ -10,7 +10,7 @@
#include <memory.h>
#include <stdlib.h>
#include <string.h>
#include <QtCore/QIODevice>
#define deltaProcLines 20
using namespace std;
@ -21,26 +21,26 @@ using namespace std;
* tab is removed and replaced by this label */
void strTable::addLabelBundle (int idx, int label)
{
char s[16];
sprintf (s, "l%d: ", label);
if(at(idx).size()<4)
at(idx)=s;
QString &processedLine(at(idx));
QString s = QString("l%1: ").arg(label);
if(processedLine.size()<4)
processedLine = s;
else
at(idx) = string(s)+at(idx).substr(4);
processedLine = s+processedLine.mid(4);
}
/* Writes the contents of the string table on the file fp. */
static void writeStrTab (std::ostream &ios, strTable &strTab)
static void writeStrTab (QIODevice &ios, strTable &strTab)
{
for (size_t i = 0; i < strTab.size(); i++)
ios << strTab[i];
ios.write(strTab[i].toLatin1());
}
/* Writes the contents of the bundle (procedure code and declaration) to
* a file. */
void writeBundle (std::ostream &ios, bundle procCode)
void writeBundle (QIODevice &ios, bundle procCode)
{
writeStrTab (ios, procCode.decl);
writeStrTab (ios, procCode.code);
@ -70,7 +70,7 @@ void bundle::appendCode(const char *format,...)
code.push_back(buf);
va_end (args);
}
void bundle::appendCode(const std::string &s)
void bundle::appendCode(const QString & s)
{
code.push_back(s);
}
@ -85,7 +85,7 @@ void bundle::appendDecl(const char *format,...)
va_end (args);
}
void bundle::appendDecl(const std::string &v)
void bundle::appendDecl(const QString &v)
{
decl.push_back(v);
}

View File

@ -5,18 +5,21 @@
* (C) Mike van Emmerik
*/
#include <stdio.h>
#include <stdlib.h>
#ifdef __BORLAND__
#include <mem.h>
#else
#include <memory.h>
#endif
#include <string.h>
#include "dcc.h"
#include "msvc_fixes.h"
#include "project.h"
#include "perfhlib.h"
#include "dcc_interface.h"
#include <QtCore/QDir>
#include <QtCore/QString>
#include <QtCore/QDebug>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
PerfectHash g_pattern_hasher;
#define NIL -1 /* Used like NULL, but 0 is valid */
/* Hash table structure */
@ -50,13 +53,13 @@ int numVert; /* Number of vertices in the graph (also size of g[]
unsigned PatLen; /* Size of the keys (pattern length) */
unsigned SymLen; /* Max size of the symbols, including null */
static FILE *g_file; /* File being read */
static char sSigName[100]; /* Full path name of .sig file */
static QString sSigName; /* Full path name of .sig file */
static uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */
static uint16_t *g; /* g[] */
static HT *ht; /* The hash table */
static PH_FUNC_STRUCT *pFunc; /* Points to the array of func names */
static hlType *pArg=0; /* Points to the array of param types */
static hlType *pArg=nullptr; /* Points to the array of param types */
static int numFunc; /* Number of func names actually stored */
static int numArg; /* Number of param names actually stored */
#define DCCLIBS "dcclibs.dat" /* Name of the prototypes data file */
@ -68,13 +71,12 @@ void readFileSection(uint16_t* p, int len, FILE *_file);
void cleanup(void);
void checkStartup(STATE *state);
void readProtoFile(void);
void fixNewline(char *s);
int searchPList(char *name);
void checkHeap(char *msg); /* For debugging */
void fixWildCards(uint8_t pat[]); /* In fixwild.c */
static boolT locatePattern(uint8_t *source, int iMin, int iMax, uint8_t *pattern,
static bool locatePattern(const uint8_t *source, int iMin, int iMax, uint8_t *pattern,
int iPatLen, int *index);
/* * * * * * * * * * * * * * * *\
@ -219,8 +221,8 @@ static uint8_t pattMainSmall[] =
0xFF, 0x36, WILD, WILD, /* Push argv */
0xFF, 0x36, WILD, WILD, /* Push argc */
0xE8, WILD, WILD /* call _main */
/* 0x50, /* push ax... not in Borland V3 */
/* 0xE8 /* call _exit */
// 0x50, /* push ax... not in Borland V3 */
// 0xE8 /* call _exit */
};
/* Num bytes from start pattern to the relative offset of main() */
#define OFFMAINSMALL 13
@ -232,9 +234,9 @@ static uint8_t pattMainMedium[] =
0xFF, 0x36, WILD, WILD, /* Push argv */
0xFF, 0x36, WILD, WILD, /* Push argc */
0x9A, WILD, WILD, WILD, WILD /* call far _main */
/* 0x50 /* push ax */
/* 0x0E, /* push cs NB not tested Borland */
/* 0xE8 /* call _exit */
// 0x50 /* push ax */
// 0x0E, /* push cs NB not tested Borland */
// 0xE8 /* call _exit */
};
/* Num bytes from start pattern to the relative offset of main() */
#define OFFMAINMEDIUM 13
@ -248,8 +250,8 @@ static uint8_t pattMainCompact[] =
0xFF, 0x36, WILD, WILD, /* Push argv hi */
0xFF, 0x36, WILD, WILD, /* Push argc */
0xE8, WILD, WILD, /* call _main */
/* 0x50, /* push ax */
/* 0xE8 /* call _exit */
// 0x50, /* push ax */
// 0xE8 /* call _exit */
};
/* Num bytes from start pattern to the relative offset of main() */
#define OFFMAINCOMPACT 21
@ -263,9 +265,9 @@ static uint8_t pattMainLarge[] =
0xFF, 0x36, WILD, WILD, /* Push argv hi */
0xFF, 0x36, WILD, WILD, /* Push argc */
0x9A, WILD, WILD, WILD, WILD /* call far _main */
/* 0x50 /* push ax */
/* 0x0E, /* push cs */
/* 0xE8 /* call _exit */
// 0x50 /* push ax */
// 0x0E, /* push cs */
// 0xE8 /* call _exit */
};
/* Num bytes from start pattern to the relative offset of main() */
#define OFFMAINLARGE 21
@ -296,22 +298,21 @@ static uint8_t pattMsChkstk[] =
/* This procedure is called to initialise the library check code */
void SetupLibCheck(void)
bool SetupLibCheck(void)
{
PROG &prog(Project::get()->prog);
uint16_t w, len;
int i;
if ((g_file = fopen(sSigName, "rb")) == NULL)
IDcc *dcc = IDcc::get();
QString fpath = dcc->dataDir("sigs").absoluteFilePath(sSigName);
if ((g_file = fopen(qPrintable(fpath), "rb")) == nullptr)
{
printf("Warning: cannot open signature file %s\n", sSigName);
return;
printf("Warning: cannot open signature file %s\n", qPrintable(fpath));
return false;
}
readProtoFile();
prog.bSigs = false; /* False unless everything goes right */
/* Read the parameters */
grab(4, g_file);
if (memcmp("dccs", buf, 4) != 0)
@ -323,22 +324,20 @@ void SetupLibCheck(void)
numVert = readFileShort(g_file);
PatLen = readFileShort(g_file);
SymLen = readFileShort(g_file);
if ((PatLen != PATLEN) || (SymLen != SYMLEN))
if ((PatLen != PATLEN) or (SymLen != SYMLEN))
{
printf("Sorry! Compiled for sym and pattern lengths of %d and %d\n",
SYMLEN, PATLEN);
exit(1);
printf("Sorry! Compiled for sym and pattern lengths of %d and %d\n", SYMLEN, PATLEN);
return false;
}
/* Initialise the perfhlib stuff. Also allocates T1, T2, g, etc */
/* Set the parameters for the hash table */
g_pattern_hasher.init(
g_pattern_hasher.setHashParams(
numKeys, /* The number of symbols */
PatLen, /* The length of the pattern to be hashed */
256, /* The character set of the pattern (0-FF) */
0, /* Minimum pattern character value */
numVert); /* Specifies c, the sparseness of the graph.
See Czech, Havas and Majewski for details */
numVert); /* Specifies c, the sparseness of the graph. See Czech, Havas and Majewski for details */
T1base = g_pattern_hasher.readT1();
T2base = g_pattern_hasher.readT2();
g = g_pattern_hasher.readG();
@ -355,7 +354,7 @@ void SetupLibCheck(void)
if (w != len)
{
printf("Problem with size of T1: file %d, calc %d\n", w, len);
exit(4);
return false;
}
readFileSection(T1base, len, g_file);
@ -363,13 +362,13 @@ void SetupLibCheck(void)
if (memcmp("T2", buf, 2) != 0)
{
printf("Expected 'T2'\n");
exit(3);
return false;
}
w = readFileShort(g_file);
if (w != len)
{
printf("Problem with size of T2: file %d, calc %d\n", w, len);
exit(4);
return false;
}
readFileSection(T2base, len, g_file);
@ -378,14 +377,14 @@ void SetupLibCheck(void)
if (memcmp("gg", buf, 2) != 0)
{
printf("Expected 'gg'\n");
exit(3);
return false;
}
len = (uint16_t)(numVert * sizeof(uint16_t));
w = readFileShort(g_file);
if (w != len)
{
printf("Problem with size of g[]: file %d, calc %d\n", w, len);
exit(4);
return false;
}
readFileSection(g, len, g_file);
@ -393,22 +392,22 @@ void SetupLibCheck(void)
/* This is now the hash table */
/* First allocate space for the table */
ht = new HT[numKeys];
if ( 0 == ht)
if ( nullptr == ht)
{
printf("Could not allocate hash table\n");
exit(1);
return false;
}
grab(2, g_file);
if (memcmp("ht", buf, 2) != 0)
{
printf("Expected 'ht'\n");
exit(3);
return false;
}
w = readFileShort(g_file);
if (w != numKeys * (SymLen + PatLen + sizeof(uint16_t)))
{
printf("Problem with size of hash table: file %d, calc %d\n", w, len);
exit(6);
return false;
}
@ -417,11 +416,11 @@ void SetupLibCheck(void)
if (fread(&ht[i], 1, SymLen + PatLen, g_file) != SymLen + PatLen)
{
printf("Could not read signature\n");
exit(11);
return false;
}
}
fclose(g_file);
prog.bSigs = true;
return true;
}
@ -447,7 +446,7 @@ bool LibCheck(Function & pProc)
if (prog.bSigs == false)
{
/* No signatures... can't rely on hash parameters to be initialised
so always return false */
so always return false */
return false;
}
@ -458,25 +457,27 @@ bool LibCheck(Function & pProc)
pProc.name = "main";
return false;
}
memcpy(pat, &prog.Image[fileOffset], PATLEN);
//memmove(pat, &prog.Image[fileOffset], PATLEN);
if(fileOffset + PATLEN > prog.cbImage)
return false;
memcpy(pat, &prog.image()[fileOffset], PATLEN);
//memmove(pat, &prog.image()[fileOffset], PATLEN);
fixWildCards(pat); /* Fix wild cards in the copy */
h = g_pattern_hasher.hash(pat); /* Hash the found proc */
/* We always have to compare keys, because the hash function will
always return a valid index */
/* We always have to compare keys, because the hash function will always return a valid index */
if (memcmp(ht[h].htPat, pat, PATLEN) == 0)
{
/* We have a match. Save the name, if not already set */
if (pProc.name.empty() ) /* Don't overwrite existing name */
if (pProc.name.isEmpty() ) /* Don't overwrite existing name */
{
/* Give proc the new name */
pProc.name = ht[h].htSym;
}
/* But is it a real library function? */
i = NIL;
if ((numFunc == 0) || (i=searchPList(ht[h].htSym)) != NIL)
if ((numFunc == 0) or (i=searchPList(ht[h].htSym)) != NIL)
{
pProc.flg |= PROC_ISLIB; /* It's a lib function */
pProc.callingConv(CConv::eCdecl);
if (i != NIL)
{
/* Allocate space for the arg struct, and copy the hlType to
@ -494,19 +495,26 @@ bool LibCheck(Function & pProc)
pProc.flg |= PROC_IS_FUNC;
switch (pProc.retVal.type) {
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
pProc.liveOut = duReg[rDX] | duReg[rAX];
pProc.liveOut.setReg(rDX).addReg(rAX);
break;
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
pProc.liveOut = duReg[rAX];
pProc.liveOut.setReg(rAX);
break;
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
pProc.liveOut = duReg[rAL];
pProc.liveOut.setReg(rAL);
break;
case TYPE_STR:
case TYPE_PTR:
fprintf(stderr,"Warning assuming Large memory model\n");
pProc.liveOut.setReg(rAX).addReg(rDS);
break;
default:
qCritical() << QString("Unknown retval type %1 for %2 in LibCheck")
.arg(pProc.retVal.type).arg(pProc.name);
/*** other types are not considered yet ***/
}
}
if (pFunc[i].bVararg)
pProc.flg |= PROC_VARARG;
pProc.getFunctionType()->m_vararg = pFunc[i].bVararg;
}
}
else if (i == NIL)
@ -516,7 +524,7 @@ bool LibCheck(Function & pProc)
pProc.flg |= PROC_RUNTIME; /* => is a runtime routine */
}
}
if (locatePattern(prog.Image, pProc.procEntry,
if (locatePattern(prog.image(), pProc.procEntry,
pProc.procEntry+sizeof(pattMsChkstk),
pattMsChkstk, sizeof(pattMsChkstk), &Idx))
{
@ -526,7 +534,7 @@ bool LibCheck(Function & pProc)
pProc.args.numArgs = 0; /* With no args */
}
return (boolT)((pProc.flg & PROC_ISLIB) != 0);
return pProc.isLibrary();
}
@ -540,8 +548,7 @@ void grab(int n, FILE *_file)
}
}
uint16_t
readFileShort(FILE *f)
uint16_t readFileShort(FILE *f)
{
uint8_t b1, b2;
@ -559,8 +566,7 @@ readFileShort(FILE *f)
}
// Read a section of the file, considering endian issues
void
readFileSection(uint16_t* p, int len, FILE* f)
void readFileSection(uint16_t* p, int len, FILE* f)
{
for (int i=0; i < len; i += 2)
{
@ -569,12 +575,12 @@ readFileSection(uint16_t* p, int len, FILE* f)
}
/* The following two functions are dummies, since we don't call map() */
void getKey(int i, uint8_t **keys)
void getKey(int /*i*/, uint8_t **/*keys*/)
{
}
void dispKey(int i)
void dispKey(int /*i*/)
{
}
@ -583,11 +589,11 @@ void dispKey(int i)
iPatLen). The pattern can contain wild bytes; if you really want to match
for the pattern that is used up by the WILD uint8_t, tough - it will match with
everything else as well. */
static boolT locatePattern(uint8_t *source, int iMin, int iMax, uint8_t *pattern, int iPatLen,
static bool locatePattern(const uint8_t *source, int iMin, int iMax, uint8_t *pattern, int iPatLen,
int *index)
{
int i, j;
uint8_t *pSrc; /* Pointer to start of considered source */
const uint8_t *pSrc; /* Pointer to start of considered source */
int iLast;
iLast = iMax - iPatLen; /* Last source uint8_t to consider */
@ -599,7 +605,7 @@ static boolT locatePattern(uint8_t *source, int iMin, int iMax, uint8_t *pattern
for (j=0; j < iPatLen; j++)
{
/* j is the index of the uint8_t being considered in the pattern. */
if ((*pSrc != pattern[j]) && (pattern[j] != WILD))
if ((*pSrc != pattern[j]) and (pattern[j] != WILD))
{
/* A definite mismatch */
break; /* Break to outer loop */
@ -634,25 +640,24 @@ void STATE::checkStartup()
char chModel = 'x';
char chVendor = 'x';
char chVersion = 'x';
char *pPath;
char temp[4];
startOff = ((uint32_t)prog.initCS << 4) + prog.initIP;
/* Check the Turbo Pascal signatures first, since they involve only the
first 3 bytes, and false positives may be founf with the others later */
if (locatePattern(prog.Image, startOff, startOff+5, pattBorl4on,sizeof(pattBorl4on), &i))
if (locatePattern(prog.image(), startOff, startOff+5, pattBorl4on,sizeof(pattBorl4on), &i))
{
/* The first 5 bytes are a far call. Follow that call and
determine the version from that */
rel = LH(&prog.Image[startOff+1]); /* This is abs off of init */
para= LH(&prog.Image[startOff+3]);/* This is abs seg of init */
rel = LH(&prog.image()[startOff+1]); /* This is abs off of init */
para= LH(&prog.image()[startOff+3]);/* This is abs seg of init */
init = ((uint32_t)para << 4) + rel;
if (locatePattern(prog.Image, init, init+26, pattBorl4Init,
if (locatePattern(prog.image(), init, init+26, pattBorl4Init,
sizeof(pattBorl4Init), &i))
{
setState(rDS, LH(&prog.Image[i+1]));
setState(rDS, LH(&prog.image()[i+1]));
printf("Borland Pascal v4 detected\n");
chVendor = 't'; /* Trubo */
chModel = 'p'; /* Pascal */
@ -661,11 +666,11 @@ void STATE::checkStartup()
prog.segMain = prog.initCS; /* At the 5 uint8_t jump */
goto gotVendor; /* Already have vendor */
}
else if (locatePattern(prog.Image, init, init+26, pattBorl5Init,
else if (locatePattern(prog.image(), init, init+26, pattBorl5Init,
sizeof(pattBorl5Init), &i))
{
setState( rDS, LH(&prog.Image[i+1]));
setState( rDS, LH(&prog.image()[i+1]));
printf("Borland Pascal v5.0 detected\n");
chVendor = 't'; /* Trubo */
chModel = 'p'; /* Pascal */
@ -674,11 +679,11 @@ void STATE::checkStartup()
prog.segMain = prog.initCS;
goto gotVendor; /* Already have vendor */
}
else if (locatePattern(prog.Image, init, init+26, pattBorl7Init,
else if (locatePattern(prog.image(), init, init+26, pattBorl7Init,
sizeof(pattBorl7Init), &i))
{
setState( rDS, LH(&prog.Image[i+1]));
setState( rDS, LH(&prog.image()[i+1]));
printf("Borland Pascal v7 detected\n");
chVendor = 't'; /* Trubo */
chModel = 'p'; /* Pascal */
@ -695,45 +700,45 @@ void STATE::checkStartup()
but decides the model required. Note: must do the far data models
(large and compact) before the others, since they are the same pattern
as near data, just more pushes at the start. */
if(prog.cbImage>startOff+0x180+sizeof(pattMainLarge))
if(prog.cbImage>int(startOff+0x180+sizeof(pattMainLarge)))
{
if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainLarge,sizeof(pattMainLarge), &i))
if (locatePattern(prog.image(), startOff, startOff+0x180, pattMainLarge,sizeof(pattMainLarge), &i))
{
rel = LH(&prog.Image[i+OFFMAINLARGE]); /* This is abs off of main */
para= LH(&prog.Image[i+OFFMAINLARGE+2]);/* This is abs seg of main */
rel = LH(&prog.image()[i+OFFMAINLARGE]); /* This is abs off of main */
para= LH(&prog.image()[i+OFFMAINLARGE+2]);/* This is abs seg of main */
/* Save absolute image offset */
prog.offMain = ((uint32_t)para << 4) + rel;
prog.segMain = (uint16_t)para;
chModel = 'l'; /* Large model */
}
else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainCompact,
else if (locatePattern(prog.image(), startOff, startOff+0x180, pattMainCompact,
sizeof(pattMainCompact), &i))
{
rel = LH_SIGNED(&prog.Image[i+OFFMAINCOMPACT]);/* This is the rel addr of main */
rel = LH_SIGNED(&prog.image()[i+OFFMAINCOMPACT]);/* This is the rel addr of main */
prog.offMain = i+OFFMAINCOMPACT+2+rel; /* Save absolute image offset */
prog.segMain = prog.initCS;
chModel = 'c'; /* Compact model */
}
else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainMedium,
else if (locatePattern(prog.image(), startOff, startOff+0x180, pattMainMedium,
sizeof(pattMainMedium), &i))
{
rel = LH(&prog.Image[i+OFFMAINMEDIUM]); /* This is abs off of main */
para= LH(&prog.Image[i+OFFMAINMEDIUM+2]);/* This is abs seg of main */
rel = LH(&prog.image()[i+OFFMAINMEDIUM]); /* This is abs off of main */
para= LH(&prog.image()[i+OFFMAINMEDIUM+2]);/* This is abs seg of main */
prog.offMain = ((uint32_t)para << 4) + rel;
prog.segMain = (uint16_t)para;
chModel = 'm'; /* Medium model */
}
else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainSmall,
else if (locatePattern(prog.image(), startOff, startOff+0x180, pattMainSmall,
sizeof(pattMainSmall), &i))
{
rel = LH_SIGNED(&prog.Image[i+OFFMAINSMALL]); /* This is rel addr of main */
rel = LH_SIGNED(&prog.image()[i+OFFMAINSMALL]); /* This is rel addr of main */
prog.offMain = i+OFFMAINSMALL+2+rel; /* Save absolute image offset */
prog.segMain = prog.initCS;
chModel = 's'; /* Small model */
}
else if (memcmp(&prog.Image[startOff], pattTPasStart, sizeof(pattTPasStart)) == 0)
else if (memcmp(&prog.image()[startOff], pattTPasStart, sizeof(pattTPasStart)) == 0)
{
rel = LH_SIGNED(&prog.Image[startOff+1]); /* Get the jump offset */
rel = LH_SIGNED(&prog.image()[startOff+1]); /* Get the jump offset */
prog.offMain = rel+startOff+3; /* Save absolute image offset */
prog.offMain += 0x20; /* These first 32 bytes are setting up */
prog.segMain = prog.initCS;
@ -757,30 +762,30 @@ void STATE::checkStartup()
}
printf("Model: %c\n", chModel);
prog.addressingMode = chModel;
/* Now decide the compiler vendor and version number */
if (memcmp(&prog.Image[startOff], pattMsC5Start, sizeof(pattMsC5Start)) == 0)
if (memcmp(&prog.image()[startOff], pattMsC5Start, sizeof(pattMsC5Start)) == 0)
{
/* Yes, this is Microsoft startup code. The DS is sitting right here
in the next 2 bytes */
setState( rDS, LH(&prog.Image[startOff+sizeof(pattMsC5Start)]));
setState( rDS, LH(&prog.image()[startOff+sizeof(pattMsC5Start)]));
chVendor = 'm'; /* Microsoft compiler */
chVersion = '5'; /* Version 5 */
printf("MSC 5 detected\n");
}
/* The C8 startup pattern is different from C5's */
else if (memcmp(&prog.Image[startOff], pattMsC8Start, sizeof(pattMsC8Start)) == 0)
else if (memcmp(&prog.image()[startOff], pattMsC8Start, sizeof(pattMsC8Start)) == 0)
{
setState( rDS, LH(&prog.Image[startOff+sizeof(pattMsC8Start)]));
setState( rDS, LH(&prog.image()[startOff+sizeof(pattMsC8Start)]));
printf("MSC 8 detected\n");
chVendor = 'm'; /* Microsoft compiler */
chVersion = '8'; /* Version 8 */
}
/* The C8 .com startup pattern is different again! */
else if (memcmp(&prog.Image[startOff], pattMsC8ComStart,
else if (memcmp(&prog.image()[startOff], pattMsC8ComStart,
sizeof(pattMsC8ComStart)) == 0)
{
printf("MSC 8 .com detected\n");
@ -788,27 +793,27 @@ void STATE::checkStartup()
chVersion = '8'; /* Version 8 */
}
else if (locatePattern(prog.Image, startOff, startOff+0x30, pattBorl2Start,
else if (locatePattern(prog.image(), startOff, startOff+0x30, pattBorl2Start,
sizeof(pattBorl2Start), &i))
{
/* Borland startup. DS is at the second uint8_t (offset 1) */
setState( rDS, LH(&prog.Image[i+1]));
setState( rDS, LH(&prog.image()[i+1]));
printf("Borland v2 detected\n");
chVendor = 'b'; /* Borland compiler */
chVersion = '2'; /* Version 2 */
}
else if (locatePattern(prog.Image, startOff, startOff+0x30, pattBorl3Start,
else if (locatePattern(prog.image(), startOff, startOff+0x30, pattBorl3Start,
sizeof(pattBorl3Start), &i))
{
/* Borland startup. DS is at the second uint8_t (offset 1) */
setState( rDS, LH(&prog.Image[i+1]));
setState( rDS, LH(&prog.image()[i+1]));
printf("Borland v3 detected\n");
chVendor = 'b'; /* Borland compiler */
chVersion = '3'; /* Version 3 */
}
else if (locatePattern(prog.Image, startOff, startOff+0x30, pattLogiStart,
else if (locatePattern(prog.image(), startOff, startOff+0x30, pattLogiStart,
sizeof(pattLogiStart), &i))
{
/* Logitech modula startup. DS is 0, despite appearances */
@ -825,31 +830,12 @@ void STATE::checkStartup()
gotVendor:
/* Use the DCC environment variable to set where the .sig files will
be found. Otherwise, assume current directory */
pPath = getenv("DCC");
if (pPath)
{
strcpy(sSigName, pPath); /* Use path given */
if (sSigName[strlen(sSigName)-1] != '/')
{
strcat(sSigName, "/"); /* Append a slash if necessary */
}
}
else
{
strcpy(sSigName, "./"); /* Current directory */
}
strcat(sSigName, "dcc");
temp[1] = '\0';
temp[0] = chVendor;
strcat(sSigName, temp); /* Add vendor */
temp[0] = chVersion;
strcat(sSigName, temp); /* Add version */
temp[0] = chModel;
strcat(sSigName, temp); /* Add model */
strcat(sSigName, ".sig"); /* Add extension */
printf("Signature file: %s\n", sSigName);
sSigName = QString("dcc%1%2%3.sig")
.arg(QChar(chVendor)) /* Add vendor */
.arg(QChar(chVersion)) /* Add version */
.arg(QChar(chModel)) /* Add model */
;
printf("Signature file: %s\n", qPrintable(sSigName));
}
@ -862,45 +848,29 @@ gotVendor:
*/
void readProtoFile(void)
{
IDcc *dcc = IDcc::get();
QString szProFName = dcc->dataDir("prototypes").absoluteFilePath(DCCLIBS); /* Full name of dclibs.lst */
FILE *fProto;
char *pPath; /* Point to the environment string */
char szProFName[81]; /* Full name of dclibs.lst */
int i;
/* Use the DCC environment variable to set where the dcclibs.lst file will
be found. Otherwise, assume current directory */
pPath = getenv("DCC");
if (pPath)
if ((fProto = fopen(qPrintable(szProFName), "rb")) == nullptr)
{
strcpy(szProFName, pPath); /* Use path given */
if (szProFName[strlen(szProFName)-1] != '/')
{
strcat(szProFName, "/"); /* Append a slash if necessary */
}
}
else
{
strcpy(szProFName, "./"); /* Current directory */
}
strcat(szProFName, DCCLIBS);
if ((fProto = fopen(szProFName, "rb")) == NULL)
{
printf("Warning: cannot open library prototype data file %s\n", szProFName);
printf("Warning: cannot open library prototype data file %s\n", qPrintable(szProFName));
return;
}
grab(4, fProto);
if (strncmp(buf, "dccp", 4) != 0)
{
printf("%s is not a dcc prototype file\n", szProFName);
printf("%s is not a dcc prototype file\n", qPrintable(szProFName));
exit(1);
}
grab(2, fProto);
if (strncmp(buf, "FN", 2) != 0)
{
printf("FN (Function Name) subsection expected in %s\n", szProFName);
printf("FN (Function Name) subsection expected in %s\n", qPrintable(szProFName));
exit(2);
}
@ -927,7 +897,7 @@ void readProtoFile(void)
grab(2, fProto);
if (strncmp(buf, "PM", 2) != 0)
{
printf("PM (Parameter) subsection expected in %s\n", szProFName);
printf("PM (Parameter) subsection expected in %s\n", qPrintable(szProFName));
exit(2);
}
@ -947,8 +917,7 @@ void readProtoFile(void)
}
int
searchPList(char *name)
int searchPList(char *name)
{
/* Search through the symbol names for the name */
/* Use binary search */
@ -985,10 +954,7 @@ searchPList(char *name)
{
return mn; /* Found! */
}
else
{
return NIL;
}
return NIL;
}

View File

@ -7,9 +7,12 @@
****************************************************************************/
#include "dcc.h"
#include "msvc_fixes.h"
#include "machine_x86.h"
#include <string.h>
#include <sstream>
#include <QTextStream>
using namespace std;
#define intSize 40
@ -148,33 +151,33 @@ static const char *intOthers[] = {
/* Writes the description of the current interrupt. Appends it to the
* string s. */
void LLInst::writeIntComment (std::ostringstream &s)
void LLInst::writeIntComment (QTextStream &s)
{
uint32_t src_immed=src().getImm2();
s<<"\t/* ";
if (src_immed == 0x21)
{
s <<int21h[dst.off];
s <<int21h[m_dst.off];
}
else if (src_immed > 0x1F && src_immed < 0x2F)
else if (src_immed > 0x1F and src_immed < 0x2F)
{
s <<intOthers[src_immed - 0x20];
}
else if (src_immed == 0x2F)
{
switch (dst.off)
switch (m_dst.off)
{
case 0x01 :
s << "Print spooler";
break;
case 0x02:
s << "Assign";
break;
case 0x10:
s << "Share";
break;
case 0xB7:
s << "Append";
case 0x01 :
s << "Print spooler";
break;
case 0x02:
s << "Assign";
break;
case 0x10:
s << "Share";
break;
case 0xB7:
s << "Append";
}
}
else
@ -186,12 +189,15 @@ void LLInst::writeIntComment (std::ostringstream &s)
//, &cCode.decl
void Function::writeProcComments()
{
std::ostringstream ostr;
writeProcComments(ostr);
cCode.appendDecl(ostr.str());
QString dest_str;
{
QTextStream ostr(&dest_str);
writeProcComments(ostr);
}
cCode.appendDecl(dest_str);
}
void Function::writeProcComments(std::ostream &ostr)
void Function::writeProcComments(QTextStream &ostr)
{
int i;
ID *id; /* Pointer to register argument identifier */
@ -207,16 +213,16 @@ void Function::writeProcComments(std::ostream &ostr)
{
psym = &this->args[i];
ostr << " * "<<psym->name<<" = ";
if (psym->regs->expr.ident.idType == REGISTER)
if (psym->regs->ident.type() == REGISTER)
{
id = &this->localId.id_arr[psym->regs->expr.ident.idNode.regiIdx];
id = &this->localId.id_arr[((RegisterNode *)psym->regs)->regiIdx];
ostr << Machine_X86::regName(id->id.regi);
}
else /* long register */
{
id = &this->localId.id_arr[psym->regs->expr.ident.idNode.longIdx];
ostr << Machine_X86::regName(id->id.longId.h) << ":";
ostr << Machine_X86::regName(id->id.longId.l);
id = &this->localId.id_arr[psym->regs->ident.idNode.longIdx];
ostr << Machine_X86::regName(id->longId().h()) << ":";
ostr << Machine_X86::regName(id->longId().l());
}
ostr << ".\n";
@ -235,26 +241,23 @@ void Function::writeProcComments(std::ostream &ostr)
ostr << " * Untranslatable routine. Assembler provided.\n";
if (this->flg & PROC_IS_FUNC)
switch (this->retVal.type) { // TODO: Functions return value in various regs
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
ostr << " * Return value in register al.\n";
break;
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
ostr << " * Return value in register ax.\n";
break;
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
ostr << " * Return value in registers dx:ax.\n";
break;
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
ostr << " * Return value in register al.\n";
break;
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
ostr << " * Return value in register ax.\n";
break;
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
ostr << " * Return value in registers dx:ax.\n";
break;
default:
fprintf(stderr,"Unknown retval type %d",this->retVal.type);
break;
} /* eos */
}
/* Calling convention */
if (this->flg & CALL_PASCAL)
ostr << " * Pascal calling convention.\n";
else if (this->flg & CALL_C)
ostr << " * C calling convention.\n";
else if (this->flg & CALL_UNKNOWN)
ostr << " * Unknown calling convention.\n";
callingConv()->writeComments(ostr);
/* Other flags */
if (this->flg & (PROC_BADINST | PROC_IJMP))
{

View File

@ -2,33 +2,34 @@
* Description : Performs control flow analysis on the CFG
* (C) Cristina Cifuentes
********************************************************************/
#include <boost/range/algorithm.hpp>
#include <algorithm>
#include <list>
#include <cassert>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "dcc.h"
#include "msvc_fixes.h"
//typedef struct list {
// int nodeIdx;
// struct list *next;
//} nodeList;
#include <boost/range/algorithm.hpp>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <list>
namespace {
typedef std::list<int> nodeList; /* dfsLast index to the node */
#define ancestor(a,b) ((a->dfsLastNum < b->dfsLastNum) && (a->dfsFirstNum < b->dfsFirstNum))
/* there is a path on the DFST from a to b if the a was first visited in a
* dfs, and a was later visited than b when doing the last visit of each
* node. */
bool inline ancestor(BB *a,BB *b)
{
return (a->dfsLastNum < b->dfsLastNum) and (a->dfsFirstNum < b->dfsFirstNum);
}
/* Checks if the edge (p,s) is a back edge. If node s was visited first
/** Checks if the edge (p,s) is a back edge. If node s was visited first
* during the dfs traversal (ie. s has a smaller dfsFirst number) or s == p,
* then it is a backedge.
* Also incrementes the number of backedges entries to the header node. */
static bool isBackEdge (BB * p,BB * s)
bool isBackEdge (BB * p,BB * s)
{
if (p->dfsFirstNum >= s->dfsFirstNum)
{
@ -39,16 +40,16 @@ static bool isBackEdge (BB * p,BB * s)
}
/* Finds the common dominator of the current immediate dominator
/** Finds the common dominator of the current immediate dominator
* currImmDom and its predecessor's immediate dominator predImmDom */
static int commonDom (int currImmDom, int predImmDom, Function * pProc)
int commonDom (int currImmDom, int predImmDom, Function * pProc)
{
if (currImmDom == NO_DOM)
return (predImmDom);
if (predImmDom == NO_DOM) /* predecessor is the root */
return (currImmDom);
while ((currImmDom != NO_DOM) && (predImmDom != NO_DOM) &&
while ((currImmDom != NO_DOM) and (predImmDom != NO_DOM) and
(currImmDom != predImmDom))
{
if (currImmDom < predImmDom)
@ -58,9 +59,214 @@ static int commonDom (int currImmDom, int predImmDom, Function * pProc)
}
return (currImmDom);
}
/* Returns whether or not the node n (dfsLast numbering of a basic block)
* is on the list l. */
bool inList (const nodeList &l, int n)
{
return std::find(l.begin(),l.end(),n)!=l.end();
}
/* Returns whether the node n belongs to the queue list q. */
bool inInt(BB * n, queue &q)
{
return std::find(q.begin(),q.end(),n)!=q.end();
}
/** Recursive procedure to find nodes that belong to the interval (ie. nodes
* from G1). */
void findNodesInInt (queue &intNodes, int level, interval *Ii)
{
if (level == 1)
{
for(BB *en : Ii->nodes)
{
appendQueue(intNodes,en);
}
}
else
{
for(BB *en : Ii->nodes)
{
findNodesInInt(intNodes,level-1,en->correspInt);
}
}
}
/* Finds the follow of the endless loop headed at node head (if any).
* The follow node is the closest node to the loop. */
void findEndlessFollow (Function * pProc, nodeList &loopNodes, BB * head)
{
head->loopFollow = MAX;
for( int loop_node : loopNodes)
{
for (const TYPEADR_TYPE &typeaddr: pProc->m_dfsLast[loop_node]->edges)
{
int succ = typeaddr.BBptr->dfsLastNum;
if ((not inList(loopNodes, succ)) and (succ < head->loopFollow))
head->loopFollow = succ;
}
}
}
/* Finds the immediate dominator of each node in the graph pProc->cfg.
//static void findNodesInLoop(BB * latchNode,BB * head,PPROC pProc,queue *intNodes)
/* Flags nodes that belong to the loop determined by (latchNode, head) and
* determines the type of loop. */
void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &intNodes)
{
int i, headDfsNum, intNodeType;
nodeList loopNodes;
int immedDom, /* dfsLast index to immediate dominator */
thenDfs, elseDfs; /* dsfLast index for THEN and ELSE nodes */
BB * pbb;
/* Flag nodes in loop headed by head (except header node) */
headDfsNum = head->dfsLastNum;
head->loopHead = headDfsNum;
loopNodes.push_back(headDfsNum);
for (i = headDfsNum + 1; i < latchNode->dfsLastNum; i++)
{
if (pProc->m_dfsLast[i]->flg & INVALID_BB) /* skip invalid BBs */
continue;
immedDom = pProc->m_dfsLast[i]->immedDom;
if (inList (loopNodes, immedDom) and inInt(pProc->m_dfsLast[i], intNodes))
{
loopNodes.push_back(i);
if (pProc->m_dfsLast[i]->loopHead == NO_NODE)/*not in other loop*/
pProc->m_dfsLast[i]->loopHead = headDfsNum;
}
}
latchNode->loopHead = headDfsNum;
if (latchNode != head)
loopNodes.push_back(latchNode->dfsLastNum);
/* Determine type of loop and follow node */
intNodeType = head->nodeType;
if (latchNode->nodeType == TWO_BRANCH)
if ((intNodeType == TWO_BRANCH) or (latchNode == head))
if ((latchNode == head) or
(inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum) and
inList (loopNodes, head->edges[ELSE].BBptr->dfsLastNum)))
{
head->loopType = eNodeHeaderType::REPEAT_TYPE;
if (latchNode->edges[0].BBptr == head)
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
else
head->loopFollow = latchNode->edges[THEN].BBptr->dfsLastNum;
latchNode->back().ll()->setFlags(JX_LOOP);
}
else
{
head->loopType = eNodeHeaderType::WHILE_TYPE;
if (inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum))
head->loopFollow = head->edges[ELSE].BBptr->dfsLastNum;
else
head->loopFollow = head->edges[THEN].BBptr->dfsLastNum;
head->back().ll()->setFlags(JX_LOOP);
}
else /* head = anything besides 2-way, latch = 2-way */
{
head->loopType = eNodeHeaderType::REPEAT_TYPE;
if (latchNode->edges[THEN].BBptr == head)
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
else
head->loopFollow = latchNode->edges[THEN].BBptr->dfsLastNum;
latchNode->back().ll()->setFlags(JX_LOOP);
}
else /* latch = 1-way */
if (latchNode->nodeType == LOOP_NODE)
{
head->loopType = eNodeHeaderType::REPEAT_TYPE;
head->loopFollow = latchNode->edges[0].BBptr->dfsLastNum;
}
else if (intNodeType == TWO_BRANCH)
{
head->loopType = eNodeHeaderType::WHILE_TYPE;
pbb = latchNode;
thenDfs = head->edges[THEN].BBptr->dfsLastNum;
elseDfs = head->edges[ELSE].BBptr->dfsLastNum;
while (1)
{
if (pbb->dfsLastNum == thenDfs)
{
head->loopFollow = elseDfs;
break;
}
else if (pbb->dfsLastNum == elseDfs)
{
head->loopFollow = thenDfs;
break;
}
/* Check if couldn't find it, then it is a strangely formed
* loop, so it is safer to consider it an endless loop */
if (pbb->dfsLastNum <= head->dfsLastNum)
{
head->loopType = eNodeHeaderType::ENDLESS_TYPE;
findEndlessFollow (pProc, loopNodes, head);
break;
}
pbb = pProc->m_dfsLast[pbb->immedDom];
}
if (pbb->dfsLastNum > head->dfsLastNum)
pProc->m_dfsLast[head->loopFollow]->loopHead = NO_NODE; /*****/
head->back().ll()->setFlags(JX_LOOP);
}
else
{
head->loopType = eNodeHeaderType::ENDLESS_TYPE;
findEndlessFollow (pProc, loopNodes, head);
}
loopNodes.clear();
}
/** \returns whether the BB indexed by s is a successor of the BB indexed by \arg h
* \note that h is a case node.
*/
bool successor (int s, int h, Function * pProc)
{
BB * header = pProc->m_dfsLast[h];
auto iter = std::find_if(header->edges.begin(),
header->edges.end(),
[s](const TYPEADR_TYPE &te)->bool{ return te.BBptr->dfsLastNum == s;});
return iter!=header->edges.end();
}
/** Recursive procedure to tag nodes that belong to the case described by
* the list l, head and tail (dfsLast index to first and exit node of the
* case). */
void tagNodesInCase (BB * pBB, nodeList &l, int head, int tail)
{
int current; /* index to current node */
pBB->traversed = DFS_CASE;
current = pBB->dfsLastNum;
if ((current != tail) and (pBB->nodeType != MULTI_BRANCH) and (inList (l, pBB->immedDom)))
{
l.push_back(current);
pBB->caseHead = head;
for(TYPEADR_TYPE &edge : pBB->edges)
{
if (edge.BBptr->traversed != DFS_CASE)
tagNodesInCase (edge.BBptr, l, head, tail);
}
}
}
/** Flags all nodes in the list l as having follow node f, and deletes all
* nodes from the list. */
void flagNodes (nodeList &l, int f, Function * pProc)
{
for(int idx : l)
{
pProc->m_dfsLast[idx]->ifFollow = f;
}
l.clear();
}
} // end of anonymouse namespace
/** Finds the immediate dominator of each node in the graph pProc->cfg.
* Adapted version of the dominators algorithm by Hecht and Ullman; finds
* immediate dominators only.
* Note: graph should be reducible */
@ -82,188 +288,7 @@ void Function::findImmedDom ()
}
/* Inserts the node n to the list l. */
static void insertList (nodeList &l, int n)
{
l.push_back(n);
}
/* Returns whether or not the node n (dfsLast numbering of a basic block)
* is on the list l. */
static bool inList (const nodeList &l, int n)
{
return std::find(l.begin(),l.end(),n)!=l.end();
}
/* Frees space allocated by the list l. */
static void freeList (nodeList &l)
{
l.clear();
}
/* Returns whether the node n belongs to the queue list q. */
static boolT inInt(BB * n, queue &q)
{
return std::find(q.begin(),q.end(),n)!=q.end();
}
/* Finds the follow of the endless loop headed at node head (if any).
* The follow node is the closest node to the loop. */
static void findEndlessFollow (Function * pProc, nodeList &loopNodes, BB * head)
{
head->loopFollow = MAX;
for( int loop_node : loopNodes)
{
for (TYPEADR_TYPE &typeaddr: pProc->m_dfsLast[loop_node]->edges)
{
int succ = typeaddr.BBptr->dfsLastNum;
if ((! inList(loopNodes, succ)) && (succ < head->loopFollow))
head->loopFollow = succ;
}
}
}
//static void findNodesInLoop(BB * latchNode,BB * head,PPROC pProc,queue *intNodes)
/* Flags nodes that belong to the loop determined by (latchNode, head) and
* determines the type of loop. */
static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &intNodes)
{
int i, headDfsNum, intNodeType;
nodeList loopNodes;
int immedDom, /* dfsLast index to immediate dominator */
thenDfs, elseDfs; /* dsfLast index for THEN and ELSE nodes */
BB * pbb;
/* Flag nodes in loop headed by head (except header node) */
headDfsNum = head->dfsLastNum;
head->loopHead = headDfsNum;
insertList (loopNodes, headDfsNum);
for (i = headDfsNum + 1; i < latchNode->dfsLastNum; i++)
{
if (pProc->m_dfsLast[i]->flg & INVALID_BB) /* skip invalid BBs */
continue;
immedDom = pProc->m_dfsLast[i]->immedDom;
if (inList (loopNodes, immedDom) && inInt(pProc->m_dfsLast[i], intNodes))
{
insertList (loopNodes, i);
if (pProc->m_dfsLast[i]->loopHead == NO_NODE)/*not in other loop*/
pProc->m_dfsLast[i]->loopHead = headDfsNum;
}
}
latchNode->loopHead = headDfsNum;
if (latchNode != head)
insertList (loopNodes, latchNode->dfsLastNum);
/* Determine type of loop and follow node */
intNodeType = head->nodeType;
if (latchNode->nodeType == TWO_BRANCH)
if ((intNodeType == TWO_BRANCH) || (latchNode == head))
if ((latchNode == head) ||
(inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum) &&
inList (loopNodes, head->edges[ELSE].BBptr->dfsLastNum)))
{
head->loopType = REPEAT_TYPE;
if (latchNode->edges[0].BBptr == head)
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
else
head->loopFollow = latchNode->edges[THEN].BBptr->dfsLastNum;
latchNode->back().ll()->setFlags(JX_LOOP);
}
else
{
head->loopType = WHILE_TYPE;
if (inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum))
head->loopFollow = head->edges[ELSE].BBptr->dfsLastNum;
else
head->loopFollow = head->edges[THEN].BBptr->dfsLastNum;
head->back().ll()->setFlags(JX_LOOP);
}
else /* head = anything besides 2-way, latch = 2-way */
{
head->loopType = REPEAT_TYPE;
if (latchNode->edges[THEN].BBptr == head)
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
else
head->loopFollow = latchNode->edges[THEN].BBptr->dfsLastNum;
latchNode->back().ll()->setFlags(JX_LOOP);
}
else /* latch = 1-way */
if (latchNode->nodeType == LOOP_NODE)
{
head->loopType = REPEAT_TYPE;
head->loopFollow = latchNode->edges[0].BBptr->dfsLastNum;
}
else if (intNodeType == TWO_BRANCH)
{
head->loopType = WHILE_TYPE;
pbb = latchNode;
thenDfs = head->edges[THEN].BBptr->dfsLastNum;
elseDfs = head->edges[ELSE].BBptr->dfsLastNum;
while (1)
{
if (pbb->dfsLastNum == thenDfs)
{
head->loopFollow = elseDfs;
break;
}
else if (pbb->dfsLastNum == elseDfs)
{
head->loopFollow = thenDfs;
break;
}
/* Check if couldn't find it, then it is a strangely formed
* loop, so it is safer to consider it an endless loop */
if (pbb->dfsLastNum <= head->dfsLastNum)
{
head->loopType = ENDLESS_TYPE;
findEndlessFollow (pProc, loopNodes, head);
break;
}
pbb = pProc->m_dfsLast[pbb->immedDom];
}
if (pbb->dfsLastNum > head->dfsLastNum)
pProc->m_dfsLast[head->loopFollow]->loopHead = NO_NODE; /*****/
head->back().ll()->setFlags(JX_LOOP);
}
else
{
head->loopType = ENDLESS_TYPE;
findEndlessFollow (pProc, loopNodes, head);
}
freeList(loopNodes);
}
//static void findNodesInInt (queue **intNodes, int level, interval *Ii)
/* Recursive procedure to find nodes that belong to the interval (ie. nodes
* from G1). */
static void findNodesInInt (queue &intNodes, int level, interval *Ii)
{
if (level == 1)
{
for(BB *en : Ii->nodes)
{
appendQueue(intNodes,en);
}
}
else
{
for(BB *en : Ii->nodes)
{
findNodesInInt(intNodes,level-1,en->correspInt);
}
}
}
/* Algorithm for structuring loops */
/** Algorithm for structuring loops */
void Function::structLoops(derSeq *derivedG)
{
interval *Ii;
@ -276,13 +301,12 @@ void Function::structLoops(derSeq *derivedG)
/* Structure loops */
/* for all derived sequences Gi */
for(derSeq::iterator iter=derivedG->begin(); iter!=derivedG->end(); ++iter)
for(auto & elem : *derivedG)
{
level++;
Ii = iter->Ii;
while (Ii) /* for all intervals Ii of Gi */
for (Ii = elem.Ii; Ii!=nullptr; Ii = Ii->next) /* for all intervals Ii of Gi */
{
latchNode = NULL;
latchNode = nullptr;
intNodes.clear();
/* Find interval head (original BB node in G1) and create
@ -299,14 +323,13 @@ void Function::structLoops(derSeq *derivedG)
for (size_t i = 0; i < intHead->inEdges.size(); i++)
{
pred = intHead->inEdges[i];
if (inInt(pred, intNodes) && isBackEdge(pred, intHead))
if (! latchNode)
if (inInt(pred, intNodes) and isBackEdge(pred, intHead))
{
if (nullptr == latchNode)
latchNode = pred;
else
{
if (pred->dfsLastNum > latchNode->dfsLastNum)
latchNode = pred;
}
else if (pred->dfsLastNum > latchNode->dfsLastNum)
latchNode = pred;
}
}
/* Find nodes in the loop and the type of loop */
@ -315,7 +338,7 @@ void Function::structLoops(derSeq *derivedG)
/* Check latching node is at the same nesting level of case
* statements (if any) and that the node doesn't belong to
* another loop. */
if ((latchNode->caseHead == intHead->caseHead) &&
if ((latchNode->caseHead == intHead->caseHead) and
(latchNode->loopHead == NO_NODE))
{
intHead->latchNode = latchNode->dfsLastNum;
@ -323,48 +346,6 @@ void Function::structLoops(derSeq *derivedG)
latchNode->flg |= IS_LATCH_NODE;
}
}
/* Next interval */
Ii = Ii->next;
}
/* Next derived sequence */
}
}
/* Returns whether the BB indexed by s is a successor of the BB indexed by
* h. Note that h is a case node. */
static bool successor (int s, int h, Function * pProc)
{
BB * header;
header = pProc->m_dfsLast[h];
auto iter = std::find_if(header->edges.begin(),
header->edges.end(),
[s](const TYPEADR_TYPE &te)->bool{ return te.BBptr->dfsLastNum == s;});
return iter!=header->edges.end();
}
/* Recursive procedure to tag nodes that belong to the case described by
* the list l, head and tail (dfsLast index to first and exit node of the
* case). */
static void tagNodesInCase (BB * pBB, nodeList &l, int head, int tail)
{
int current, /* index to current node */
i;
pBB->traversed = DFS_CASE;
current = pBB->dfsLastNum;
if ((current != tail) && (pBB->nodeType != MULTI_BRANCH) && (inList (l, pBB->immedDom)))
{
insertList (l, current);
pBB->caseHead = head;
for(TYPEADR_TYPE &edge : pBB->edges)
{
if (edge.BBptr->traversed != DFS_CASE)
tagNodesInCase (edge.BBptr, l, head, tail);
}
}
}
@ -374,72 +355,58 @@ static void tagNodesInCase (BB * pBB, nodeList &l, int head, int tail)
* has a case node. */
void Function::structCases()
{
int i, j;
BB * caseHeader; /* case header node */
int exitNode = NO_NODE; /* case exit node */
nodeList caseNodes; /* temporary: list of nodes in case */
/* Linear scan of the nodes in reverse dfsLast order, searching for
* case nodes */
for (i = numBBs - 1; i >= 0; i--)
if (m_dfsLast[i]->nodeType == MULTI_BRANCH)
{
caseHeader = m_dfsLast[i];
/* Find descendant node which has as immediate predecessor
* the current header node, and is not a successor. */
for (j = i + 2; j < numBBs; j++)
{
if ((!successor(j, i, this)) &&
(m_dfsLast[j]->immedDom == i))
if (exitNode == NO_NODE)
exitNode = j;
else if (m_dfsLast[exitNode]->inEdges.size() < m_dfsLast[j]->inEdges.size())
exitNode = j;
}
m_dfsLast[i]->caseTail = exitNode;
/* Tag nodes that belong to the case by recording the
* header field with caseHeader. */
insertList (caseNodes, i);
m_dfsLast[i]->caseHead = i;
for(TYPEADR_TYPE &pb : caseHeader->edges)
{
tagNodesInCase(pb.BBptr, caseNodes, i, exitNode);
}
//for (j = 0; j < caseHeader->edges[j]; j++)
// tagNodesInCase (caseHeader->edges[j].BBptr, caseNodes, i, exitNode);
if (exitNode != NO_NODE)
m_dfsLast[exitNode]->caseHead = i;
}
}
/* Flags all nodes in the list l as having follow node f, and deletes all
* nodes from the list. */
static void flagNodes (nodeList &l, int f, Function * pProc)
{
nodeList::iterator p;
for(int idx : l)
for (int i = numBBs - 1; i >= 0; i--)
{
pProc->m_dfsLast[idx]->ifFollow = f;
}
l.clear();
}
if ((m_dfsLast[i]->nodeType != MULTI_BRANCH))
continue;
BB * caseHeader = m_dfsLast[i];; /* case header node */
/* Find descendant node which has as immediate predecessor
* the current header node, and is not a successor. */
for (size_t j = i + 2; j < numBBs; j++)
{
if ((not successor(j, i, this)) and (m_dfsLast[j]->immedDom == i))
{
if (exitNode == NO_NODE)
exitNode = j;
else if (m_dfsLast[exitNode]->inEdges.size() < m_dfsLast[j]->inEdges.size())
exitNode = j;
}
}
m_dfsLast[i]->caseTail = exitNode;
/* Tag nodes that belong to the case by recording the
* header field with caseHeader. */
caseNodes.push_back(i);
m_dfsLast[i]->caseHead = i;
for(TYPEADR_TYPE &pb : caseHeader->edges)
{
tagNodesInCase(pb.BBptr, caseNodes, i, exitNode);
}
//for (j = 0; j < caseHeader->edges[j]; j++)
// tagNodesInCase (caseHeader->edges[j].BBptr, caseNodes, i, exitNode);
if (exitNode != NO_NODE)
m_dfsLast[exitNode]->caseHead = i;
}
}
/* Structures if statements */
void Function::structIfs ()
{
size_t followInEdges; /* Largest # in-edges so far */
int curr, /* Index for linear scan of nodes */
desc, /* Index for descendant */
followInEdges, /* Largest # in-edges so far */
/*desc,*/ /* Index for descendant */
follow; /* Possible follow node */
nodeList domDesc, /* List of nodes dominated by curr */
unresolved /* List of unresolved if nodes */
;
BB * currNode, /* Pointer to current node */
* pbb;
* pbb;
/* Linear scan of nodes in reverse dfsLast order */
for (curr = numBBs - 1; curr >= 0; curr--)
@ -448,17 +415,17 @@ void Function::structIfs ()
if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */
continue;
if ((currNode->nodeType == TWO_BRANCH) && (!currNode->back().ll()->testFlags(JX_LOOP)))
if ((currNode->nodeType == TWO_BRANCH) and (not currNode->back().ll()->testFlags(JX_LOOP)))
{
followInEdges = 0;
follow = 0;
/* Find all nodes that have this node as immediate dominator */
for (desc = curr+1; desc < numBBs; desc++)
for (size_t desc = curr+1; desc < numBBs; desc++)
{
if (m_dfsLast[desc]->immedDom == curr)
{
insertList (domDesc, desc);
domDesc.push_back(desc);
pbb = m_dfsLast[desc];
if ((pbb->inEdges.size() - pbb->numBackEdges) >= followInEdges)
{
@ -470,16 +437,16 @@ void Function::structIfs ()
/* Determine follow according to number of descendants
* immediately dominated by this node */
if ((follow != 0) && (followInEdges > 1))
if ((follow != 0) and (followInEdges > 1))
{
currNode->ifFollow = follow;
if (!unresolved.empty())
if (not unresolved.empty())
flagNodes (unresolved, follow, this);
}
else
insertList (unresolved, curr);
unresolved.push_back(curr);
}
freeList (domDesc);
domDesc.clear();
}
}
bool Function::removeInEdge_Flag_and_ProcessLatch(BB *pbb,BB *a,BB *b)
@ -507,14 +474,14 @@ void Function::replaceInEdge(BB* where, BB* which,BB* with)
}
bool Function::Case_notX_or_Y(BB* pbb, BB* thenBB, BB* elseBB)
{
HLTYPE &hl1(*pbb->back().hl());
HLTYPE &hl2(*thenBB->back().hl());
HLTYPE &hl1(*pbb->back().hlU());
HLTYPE &hl2(*thenBB->back().hlU());
BB* obb = elseBB->edges[THEN].BBptr;
/* Construct compound DBL_OR expression */
hl1.replaceExpr(hl1.expr()->inverse());
hl1.expr(COND_EXPR::boolOp (hl1.expr(), hl2.expr(), DBL_OR));
hl1.expr(BinaryOperator::Create(DBL_OR,hl1.expr(), hl2.expr()));
/* Replace in-edge to obb from e to pbb */
replaceInEdge(obb,elseBB,pbb);
@ -528,12 +495,14 @@ bool Function::Case_notX_or_Y(BB* pbb, BB* thenBB, BB* elseBB)
}
bool Function::Case_X_and_Y(BB* pbb, BB* thenBB, BB* elseBB)
{
HLTYPE &hl1(*pbb->back().hl());
HLTYPE &hl2(*thenBB->back().hl());
HLTYPE &hl1(*pbb->back().hlU());
HLTYPE &hl2(*thenBB->back().hlU());
BB* obb = elseBB->edges[ELSE].BBptr;
Expr * hl2_expr = hl2.getMyExpr();
/* Construct compound DBL_AND expression */
hl1.expr(COND_EXPR::boolOp (hl1.expr(),hl2.expr(), DBL_AND));
assert(hl1.expr());
assert(hl2_expr);
hl1.expr(BinaryOperator::Create(DBL_AND,hl1.expr(),hl2_expr));
/* Replace in-edge to obb from e to pbb */
replaceInEdge(obb,elseBB,pbb);
@ -547,15 +516,15 @@ bool Function::Case_X_and_Y(BB* pbb, BB* thenBB, BB* elseBB)
bool Function::Case_notX_and_Y(BB* pbb, BB* thenBB, BB* elseBB)
{
HLTYPE &hl1(*pbb->back().hl());
HLTYPE &hl2(*thenBB->back().hl());
HLTYPE &hl1(*pbb->back().hlU());
HLTYPE &hl2(*thenBB->back().hlU());
BB* obb = thenBB->edges[ELSE].BBptr;
/* Construct compound DBL_AND expression */
hl1.replaceExpr(hl1.expr()->inverse());
hl1.expr(COND_EXPR::boolOp (hl1.expr(), hl2.expr(), DBL_AND));
hl1.expr(BinaryOperator::LogicAnd(hl1.expr(), hl2.expr()));
/* Replace in-edge to obb from t to pbb */
replaceInEdge(obb,thenBB,pbb);
@ -570,13 +539,13 @@ bool Function::Case_notX_and_Y(BB* pbb, BB* thenBB, BB* elseBB)
bool Function::Case_X_or_Y(BB* pbb, BB* thenBB, BB* elseBB)
{
HLTYPE &hl1(*pbb->back().hl());
HLTYPE &hl2(*thenBB->back().hl());
HLTYPE &hl1(*pbb->back().hlU());
HLTYPE &hl2(*thenBB->back().hlU());
BB * obb = thenBB->edges[THEN].BBptr;
/* Construct compound DBL_OR expression */
hl1.expr(COND_EXPR::boolOp (hl1.expr(), hl2.expr(), DBL_OR));
hl1.expr(BinaryOperator::LogicOr(hl1.expr(), hl2.expr()));
/* Replace in-edge to obb from t to pbb */
@ -603,7 +572,7 @@ void Function::compoundCond()
/* Traverse nodes in postorder, this way, the header node of a
* compound condition is analysed first */
for (int i = 0; i < this->numBBs; i++)
for (size_t i = 0; i < this->numBBs; i++)
{
pbb = this->m_dfsLast[i];
if (pbb->flg & INVALID_BB)
@ -617,33 +586,33 @@ void Function::compoundCond()
change = true; //assume change
/* Check (X || Y) case */
if ((thenBB->nodeType == TWO_BRANCH) && (thenBB->numHlIcodes == 1) &&
(thenBB->inEdges.size() == 1) && (thenBB->edges[ELSE].BBptr == elseBB))
/* Check (X or Y) case */
if ((thenBB->nodeType == TWO_BRANCH) and (thenBB->numHlIcodes == 1) and
(thenBB->inEdges.size() == 1) and (thenBB->edges[ELSE].BBptr == elseBB))
{
if(Case_X_or_Y(pbb, thenBB, elseBB))
--i;
}
/* Check (!X && Y) case */
else if ((thenBB->nodeType == TWO_BRANCH) && (thenBB->numHlIcodes == 1) &&
(thenBB->inEdges.size() == 1) && (thenBB->edges[THEN].BBptr == elseBB))
/* Check (not X and Y) case */
else if ((thenBB->nodeType == TWO_BRANCH) and (thenBB->numHlIcodes == 1) and
(thenBB->inEdges.size() == 1) and (thenBB->edges[THEN].BBptr == elseBB))
{
if(Case_notX_and_Y(pbb, thenBB, elseBB))
--i;
}
/* Check (X && Y) case */
else if ((elseBB->nodeType == TWO_BRANCH) && (elseBB->numHlIcodes == 1) &&
(elseBB->inEdges.size()==1) && (elseBB->edges[THEN].BBptr == thenBB))
/* Check (X and Y) case */
else if ((elseBB->nodeType == TWO_BRANCH) and (elseBB->numHlIcodes == 1) and
(elseBB->inEdges.size()==1) and (elseBB->edges[THEN].BBptr == thenBB))
{
if(Case_X_and_Y(pbb, thenBB, elseBB ))
--i;
}
/* Check (!X || Y) case */
else if ((elseBB->nodeType == TWO_BRANCH) && (elseBB->numHlIcodes == 1) &&
(elseBB->inEdges.size() == 1) && (elseBB->edges[ELSE].BBptr == thenBB))
/* Check (not X or Y) case */
else if ((elseBB->nodeType == TWO_BRANCH) and (elseBB->numHlIcodes == 1) and
(elseBB->inEdges.size() == 1) and (elseBB->edges[ELSE].BBptr == thenBB))
{
if(Case_notX_or_Y(pbb, thenBB, elseBB ))
--i;
@ -654,8 +623,7 @@ void Function::compoundCond()
}
}
/* Structuring algorithm to find the structures of the graph pProc->cfg */
/** Structuring algorithm to find the structures of the graph pProc->cfg */
void Function::structure(derSeq *derivedG)
{
/* Find immediate dominators of the graph */

File diff suppressed because it is too large Load Diff

View File

@ -5,156 +5,141 @@
****************************************************************************/
#include "dcc.h"
#include "msvc_fixes.h"
#include "project.h"
#include <string.h>
#include "CallGraph.h"
#include "DccFrontend.h"
#include <cstring>
#include <iostream>
#include <QtCore/QCoreApplication>
#include <QCommandLineParser>
#include <QtCore/QFile>
/* Global variables - extern to other modules */
char *asm1_name, *asm2_name; /* Assembler output filenames */
SYMTAB symtab; /* Global symbol table */
STATS stats; /* cfg statistics */
//PROG prog; /* programs fields */
OPTION option; /* Command line options */
//Function * pProcList; /* List of procedures, topologically sort */
//Function * pLastProc; /* Pointer to last node in procedure list */
//FunctionListType pProcList;
//CALL_GRAPH *callGraph; /* Call graph of the program */
static char *initargs(int argc, char *argv[]);
static void displayTotalStats(void);
#include <llvm/Support/raw_os_ostream.h>
extern QString asm1_name, asm2_name; /* Assembler output filenames */
extern SYMTAB symtab; /* Global symbol table */
extern STATS stats; /* cfg statistics */
extern OPTION option; /* Command line options */
static void displayTotalStats();
/****************************************************************************
* main
***************************************************************************/
#include <iostream>
extern Project g_proj;
int main(int argc, char *argv[])
void setupOptions(const QCoreApplication &app) {
//[-a1a2cmsi]
QCommandLineParser parser;
parser.setApplicationDescription("dcc");
parser.addHelpOption();
//parser.addVersionOption();
//QCommandLineOption showProgressOption("p", QCoreApplication::translate("main", "Show progress during copy"));
QCommandLineOption boolOpts[] {
QCommandLineOption {"v", QCoreApplication::translate("main", "verbose")},
QCommandLineOption {"V", QCoreApplication::translate("main", "very verbose")},
QCommandLineOption {"c", QCoreApplication::translate("main", "Follow register indirect calls")},
QCommandLineOption {"m", QCoreApplication::translate("main", "Print memory maps of program")},
QCommandLineOption {"s", QCoreApplication::translate("main", "Print stats")}
};
for(QCommandLineOption &o : boolOpts) {
parser.addOption(o);
}
QCommandLineOption assembly("a", QCoreApplication::translate("main", "Produce assembly"),"assembly_level");
QCommandLineOption targetFileOption(QStringList() << "o" << "output",
QCoreApplication::translate("main", "Place output into <file>."),
QCoreApplication::translate("main", "file"));
QCommandLineOption entryPointOption(QStringList() << "E",
QCoreApplication::translate("main", "Custom entry point as hex"),
QCoreApplication::translate("main", "offset"),
"0"
);
parser.addOption(targetFileOption);
parser.addOption(assembly);
parser.addOption(entryPointOption);
//parser.addOption(forceOption);
// Process the actual command line arguments given by the user
parser.addPositionalArgument("source", QCoreApplication::translate("main", "Dos Executable file to decompile."));
parser.process(app);
const QStringList args = parser.positionalArguments();
if(args.empty()) {
parser.showHelp();
}
// source is args.at(0), destination is args.at(1)
option.verbose = parser.isSet(boolOpts[0]);
option.VeryVerbose = parser.isSet(boolOpts[1]);
if(parser.isSet(assembly)) {
option.asm1 = parser.value(assembly).toInt()==1;
option.asm2 = parser.value(assembly).toInt()==2;
}
option.Map = parser.isSet(boolOpts[3]);
option.Stats = parser.isSet(boolOpts[4]);
option.Interact = false;
option.Calls = parser.isSet(boolOpts[2]);
option.filename = args.first();
option.CustomEntryPoint = parser.value(entryPointOption).toUInt(nullptr,16);
if(parser.isSet(targetFileOption))
asm1_name = asm2_name = parser.value(targetFileOption);
else if(option.asm1 or option.asm2) {
asm1_name = option.filename+".a1";
asm2_name = option.filename+".a2";
}
}
int main(int argc, char **argv)
{
// llvm::MCOperand op=llvm::MCOperand::CreateImm(11);
// llvm::MCAsmInfo info;
// llvm::raw_os_ostream wrap(std::cerr);
// op.print(wrap,&info);
// wrap.flush();
/* Extract switches and filename */
strcpy(option.filename, initargs(argc, argv));
QCoreApplication app(argc,argv);
QCoreApplication::setApplicationVersion("0.1");
setupOptions(app);
/* Front end reads in EXE or COM file, parses it into I-code while
* building the call graph and attaching appropriate bits of code for
* each procedure.
*/
DccFrontend fe(option.filename);
Project::get()->create(option.filename);
DccFrontend fe(&app);
if(not Project::get()->load()) {
return -1;
}
if (option.verbose)
Project::get()->prog.displayLoadInfo();
if(false==fe.FrontEnd ())
return -1;
if(option.asm1)
return 0;
/* In the middle is a so called Universal Decompiling Machine.
* It processes the procedure list and I-code and attaches where it can
* to each procedure an optimised cfg and ud lists
*/
udm();
if(option.asm2)
return 0;
/* Back end converts each procedure into C using I-code, interval
* analysis, data flow etc. and outputs it to output file ready for
* re-compilation.
*/
BackEnd(option.filename, g_proj.callGraph);
BackEnd(Project::get()->callGraph);
g_proj.callGraph->write();
Project::get()->callGraph->write();
if (option.Stats)
displayTotalStats();
/*
freeDataStructures(pProcList);
*/
return 0;
}
/****************************************************************************
* initargs - Extract command line arguments
***************************************************************************/
static char *initargs(int argc, char *argv[])
{
char *pc;
while (--argc > 0 && (*++argv)[0] == '-')
{
for (pc = argv[0]+1; *pc; pc++)
switch (*pc)
{
case 'a': /* Print assembler listing */
if (*(pc+1) == '2')
option.asm2 = true;
else
option.asm1 = true;
if (*(pc+1) == '1' || *(pc+1) == '2')
pc++;
break;
case 'c':
option.Calls = true;
break;
case 'i':
option.Interact = true;
break;
case 'm': /* Print memory map */
option.Map = true;
break;
case 's': /* Print Stats */
option.Stats = true;
break;
case 'V': /* Very verbose => verbose */
option.VeryVerbose = true;
case 'v':
option.verbose = true; /* Make everything verbose */
break;
case 'o': /* assembler output file */
if (*(pc+1)) {
asm1_name = asm2_name = pc+1;
goto NextArg;
}
else if (--argc > 0) {
asm1_name = asm2_name = *++argv;
goto NextArg;
}
default:
fatalError(INVALID_ARG, *pc);
return *argv;
}
NextArg:;
}
if (argc == 1)
{
if (option.asm1 || option.asm2)
{
if (! asm1_name)
{
asm1_name = strcpy((char*)malloc(strlen(*argv)+4), *argv);
pc = strrchr(asm1_name, '.');
if (pc > strrchr(asm1_name, '/'))
{
*pc = '\0';
}
asm2_name = (char*)malloc(strlen(asm1_name)+4) ;
strcat(strcpy(asm2_name, asm1_name), ".a2");
unlink(asm2_name);
strcat(asm1_name, ".a1");
}
unlink(asm1_name); /* Remove asm output files */
}
return *argv; /* filename of the program to decompile */
}
fatalError(USAGE);
return *argv; // does not reach this.
}
static void
displayTotalStats ()
/* Displays final statistics for the complete program */
{
printf ("\nFinal Program Statistics\n");
printf (" Total number of low-level Icodes : %ld\n", stats.totalLL);
printf (" Total number of high-level Icodes: %ld\n", stats.totalHL);
printf (" Total number of low-level Icodes : %d\n", stats.totalLL);
printf (" Total number of high-level Icodes: %d\n", stats.totalHL);
printf (" Total reduction of instructions : %2.2f%%\n", 100.0 -
(stats.totalHL * 100.0) / stats.totalLL);
}

70
src/dcc_interface.cpp Normal file
View File

@ -0,0 +1,70 @@
#include "dcc_interface.h"
#include "dcc.h"
#include "project.h"
struct DccImpl : public IDcc {
ilFunction m_current_func;
// IDcc interface
public:
void BaseInit()
{
m_current_func = Project::get()->functions().end();
}
void Init(QObject *tgt)
{
}
ilFunction GetFirstFuncHandle()
{
return Project::get()->functions().begin();
}
ilFunction GetCurFuncHandle()
{
return m_current_func;
}
void analysis_Once()
{
}
void load(QString name)
{
option.filename = name;
Project::get()->create(name);
}
void prtout_asm(IXmlTarget *, int level)
{
}
void prtout_cpp(IXmlTarget *, int level)
{
}
size_t getFuncCount()
{
return Project::get()->functions().size();
}
const lFunction &validFunctions() const
{
return Project::get()->functions();
}
void SetCurFunc_by_Name(QString v)
{
lFunction & funcs(Project::get()->functions());
for(auto iter=funcs.begin(),fin=funcs.end(); iter!=fin; ++iter) {
if(iter->name==v) {
m_current_func = iter;
return;
}
}
}
QDir installDir() {
return QDir(".");
}
QDir dataDir(QString kind) { // return directory containing decompilation helper data -> signatures/includes/etc.
QDir res(installDir());
res.cd(kind);
return res;
}
};
IDcc* IDcc::get() {
static IDcc *v=0;
if(nullptr == v)
v = new DccImpl;
return v;
}

View File

@ -2,6 +2,15 @@
* dcc project disassembler
* (C) Cristina Cifuentes, Mike van Emmerik, Jeff Ledermann
****************************************************************************/
#include "disassem.h"
#include "dcc.h"
#include "msvc_fixes.h"
#include "symtab.h"
#include "project.h"
#include <QtCore/QFile>
#include <QtCore/QDebug>
#include <stdint.h>
#include <vector>
#include <map>
@ -10,10 +19,6 @@
#include <stdio.h>
#include <string.h>
#include "dcc.h"
#include "symtab.h"
#include "disassem.h"
#include "project.h"
// Note: for the time being, there is no interactive disassembler
// for unix
@ -70,21 +75,21 @@ static const char *szFlops3C[] =
static const char *szPtr[2] = { "word ptr ", "byte ptr " };
static void formatRM(ostringstream &p, uint32_t flg, const LLOperand &pm);
static ostringstream &strDst(ostringstream &os, uint32_t flg, const LLOperand &pm);
static void formatRM(QTextStream & p, const LLOperand &pm);
static QTextStream & strDst(QTextStream & os, uint32_t flg, const LLOperand &pm);
static char *strHex(uint32_t d);
//static int checkScanned(uint32_t pcCur);
//static void setProc(Function * proc);
//static void dispData(uint16_t dataSeg);
boolT callArg(uint16_t off, char *temp); /* Check for procedure name */
bool callArg(uint16_t off, char *temp); /* Check for procedure name */
//static FILE *dis_g_fp;
static CIcodeRec pc;
static int cb, j, numIcode, allocIcode;
static map<int,int> pl;
static uint32_t nextInst;
static boolT fImpure;
static bool fImpure;
//static int g_lab;
static Function * pProc; /* Points to current proc struct */
@ -94,7 +99,7 @@ struct POSSTACK_ENTRY
Function * pProc; /* A pointer to a PROCEDURE structure */
} ;
static vector<POSSTACK_ENTRY> posStack; /* position stack */
static uint8_t iPS; /* Index into the stack */
//static uint8_t iPS; /* Index into the stack */
// These are "curses equivalent" functions. (Used to use curses for all this,
@ -107,7 +112,7 @@ static uint8_t iPS; /* Index into the stack */
void LLInst::findJumpTargets(CIcodeRec &_pc)
{
if (testFlags(I) && ! testFlags(JMP_ICODE) && isJmpInst())
if (testFlags(I) and not testFlags(JMP_ICODE) and isJmpInst())
{
/* Replace the immediate operand with an icode index */
iICODE labTgt=_pc.labelSrch(src().getImm2());
@ -150,11 +155,11 @@ void Disassembler::disassem(Function * ppProc)
if (pass != 3)
{
auto p = (pass == 1)? asm1_name: asm2_name;
m_fp.open(p,ios_base::app);
if (!m_fp.is_open())
{
fatalError(CANNOT_OPEN, p);
m_disassembly_target = new QFile(p);
if(!m_disassembly_target->open(QFile::WriteOnly|QFile::Text|QFile::Append)) {
fatalError(CANNOT_OPEN, p.toStdString().c_str());
}
m_fp.setDevice(m_disassembly_target);
}
/* Create temporary code array */
// Mike: needs objectising!
@ -177,7 +182,7 @@ void Disassembler::disassem(Function * ppProc)
/* Write procedure header */
if (pass != 3)
{
std::string near_far=(pProc->flg & PROC_FAR)? "FAR": "NEAR";
const char * near_far=(pProc->flg & PROC_FAR)? "FAR": "NEAR";
m_fp << "\t\t"<<pProc->name<<" PROC "<< near_far<<"\n";
}
@ -192,7 +197,10 @@ void Disassembler::disassem(Function * ppProc)
if (pass != 3)
{
m_fp << "\n\t\t"<<pProc->name<<" ENDP\n\n";
m_fp.close();
m_fp.setDevice(nullptr);
m_disassembly_target->close();
delete m_disassembly_target;
}
pc.clear();
@ -206,19 +214,23 @@ void Disassembler::disassem(Function * ppProc)
void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
{
PROG &prog(Project::get()->prog);
ostringstream oper_stream;
ostringstream hex_bytes;
ostringstream result_stream;
ostringstream opcode_with_mods;
ostringstream operands_s;
oper_stream << uppercase;
hex_bytes << uppercase;
QString oper_contents;
QTextStream oper_stream(&oper_contents);
QString hex_bytes;
QString result_contents;
QTextStream result_stream(&result_contents);
QString opcode_with_mods;
QString operands_contents;
QTextStream operands_s(&operands_contents);
oper_stream.setNumberFlags(QTextStream::UppercaseBase|QTextStream::UppercaseDigits);
/* Disassembly stage 1 --
* Do not try to display NO_CODE entries or synthetic instructions,
* other than JMPs, that have been introduced for def/use analysis. */
if ((option.asm1) &&
( inst.testFlags(NO_CODE) ||
(inst.testFlags(SYNTHETIC) && (inst.getOpcode() != iJMP))))
* Do not try to display NO_CODE entries or synthetic instructions,
* other than JMPs, that have been introduced for def/use analysis. */
if ((option.asm1) and
( inst.testFlags(NO_CODE) or
(inst.testFlags(SYNTHETIC) and (inst.getOpcode() != iJMP))))
{
return;
}
@ -242,25 +254,28 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
cb = (uint32_t) inst.numBytes;
nextInst = inst.label + cb;
/* Output hexa code in program image */
/* Output hex code in program image */
if (pass != 3)
{
for (j = 0; j < cb; j++)
{
hex_bytes << hex << setw(2) << setfill('0') << uint16_t(prog.Image[inst.label + j]);
hex_bytes += QString("%1").arg(uint16_t(prog.image()[inst.label + j]),2,16,QChar('0')).toUpper();
}
hex_bytes << ' ';
hex_bytes += ' ';
}
}
oper_stream << setw(POS_LAB) << left<< hex_bytes.str();
oper_stream.setFieldWidth(POS_LAB);
oper_stream.setFieldAlignment(QTextStream::AlignLeft);
oper_stream << hex_bytes;
/* Check if there is a symbol here */
selectTable(Label);
oper_stream << setw(5)<<left; // align for the labels
oper_stream.setFieldWidth(5); // align for the labels
{
ostringstream lab_contents;
if (readVal(lab_contents, inst.label, 0))
QString lab_contents;
QTextStream lab_stream(&lab_contents);
if (readVal(lab_stream, inst.label, nullptr))
{
lab_contents << ':'; /* Also removes the null */
lab_stream << ':'; /* Also removes the null */
}
else if (inst.testFlags(TARGET)) /* Symbols override Lnn labels */
{
@ -269,21 +284,23 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
{
pl[loc_ip] = ++g_lab;
}
lab_contents<< "L"<<pl[loc_ip]<<':';
lab_stream<< "L"<<pl[loc_ip]<<':';
}
oper_stream<< lab_contents.str();
lab_stream.flush();
oper_stream << lab_contents;
oper_stream.setFieldWidth(0);
}
if ((inst.getOpcode()==iSIGNEX )&& inst.testFlags(B))
if ((inst.getOpcode()==iSIGNEX )and inst.testFlags(B))
{
inst.setOpcode(iCBW);
}
opcode_with_mods<<Machine_X86::opcodeName(inst.getOpcode());
opcode_with_mods += Machine_X86::opcodeName(inst.getOpcode());
switch ( inst.getOpcode() )
{
case iADD: case iADC: case iSUB: case iSBB: case iAND: case iOR:
case iXOR: case iTEST: case iCMP: case iMOV: case iLEA: case iXCHG:
strDst(operands_s,inst.getFlag(), inst.dst);
strDst(operands_s,inst.getFlag(), inst.m_dst);
inst.strSrc(operands_s);
break;
@ -293,7 +310,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
case iSAR: case iSHL: case iSHR: case iRCL: case iRCR: case iROL:
case iROR:
strDst(operands_s,inst.getFlag() | I, inst.dst);
strDst(operands_s,inst.getFlag() | I, inst.m_dst);
if(inst.testFlags(I))
inst.strSrc(operands_s);
else
@ -301,7 +318,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
break;
case iINC: case iDEC: case iNEG: case iNOT: case iPOP:
strDst(operands_s,inst.getFlag() | I, inst.dst);
strDst(operands_s,inst.getFlag() | I, inst.m_dst);
break;
case iPUSH:
@ -311,15 +328,15 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
}
else
{
strDst(operands_s,inst.getFlag() | I, inst.dst);
strDst(operands_s,inst.getFlag() | I, inst.m_dst);
}
break;
case iDIV: case iIDIV: case iMUL: case iIMUL: case iMOD:
if (inst.testFlags(I))
{
strDst(operands_s,inst.getFlag(), inst.dst) <<", ";
formatRM(operands_s, inst.getFlag(), inst.src());
strDst(operands_s,inst.getFlag(), inst.m_dst) <<", ";
formatRM(operands_s, inst.src());
inst.strSrc(operands_s);
}
else
@ -327,7 +344,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
break;
case iLDS: case iLES: case iBOUND:
strDst(operands_s,inst.getFlag(), inst.dst)<<", dword ptr";
strDst(operands_s,inst.getFlag(), inst.m_dst)<<", dword ptr";
inst.strSrc(operands_s,true);
break;
@ -339,15 +356,15 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
case iJMP: case iJMPF:
/* Check if there is a symbol here */
{
ICODE *lab=pc.GetIcode(inst.src().getImm2());
{
ICODE *lab=pc.GetIcode(inst.src().getImm2());
selectTable(Label);
if ((inst.src().getImm2() < (uint32_t)numIcode) && /* Ensure in range */
readVal(operands_s, lab->ll()->label, 0))
if ((inst.src().getImm2() < (uint32_t)numIcode) and /* Ensure in range */
readVal(operands_s, lab->ll()->label, nullptr))
{
break; /* Symbolic label. Done */
}
}
}
if (inst.testFlags(NO_LABEL))
{
@ -381,11 +398,10 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
case iCALL: case iCALLF:
if (inst.testFlags(I))
{
if((inst.getOpcode() == iCALL))
operands_s<< "near";
else
operands_s<< " far";
operands_s<<" ptr "<<(inst.src().proc.proc)->name;
QString oper = QString("%1 ptr %2")
.arg((inst.getOpcode() == iCALL) ? "near" : "far")
.arg((inst.src().proc.proc)->name);
operands_s<< qPrintable(oper);
}
else if (inst.getOpcode() == iCALLF)
{
@ -397,8 +413,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
break;
case iENTER:
operands_s<<strHex(inst.dst.off)<<", ";
operands_s<<strHex(inst.src().getImm2());
operands_s<<strHex(inst.m_dst.off) << ", " << strHex(inst.src().getImm2());
break;
case iRET: case iRETF: case iINT:
@ -417,15 +432,15 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
case iOUTS: case iREP_OUTS:
if (inst.src().segOver)
{
bool is_dx_src=(inst.getOpcode() == iOUTS || inst.getOpcode() == iREP_OUTS);
bool is_dx_src=(inst.getOpcode() == iOUTS or inst.getOpcode() == iREP_OUTS);
if(is_dx_src)
operands_s<<"dx, "<<szPtr[inst.getFlag() & B];
else
operands_s<<szPtr[inst.getFlag() & B];
if (inst.getOpcode() == iLODS ||
inst.getOpcode() == iREP_LODS ||
inst.getOpcode() == iOUTS ||
inst.getOpcode() == iREP_OUTS)
if (inst.getOpcode() == iLODS or
inst.getOpcode() == iREP_LODS or
inst.getOpcode() == iOUTS or
inst.getOpcode() == iREP_OUTS)
{
operands_s<<Machine_X86::regName(inst.src().segOver); // szWreg[src.segOver-rAX]
}
@ -437,9 +452,12 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
}
else
{
(inst.getFlag() & B)? opcode_with_mods<< "B": opcode_with_mods<< "W";
if(inst.getFlag() & B)
opcode_with_mods+='B';
else
opcode_with_mods+='W';
}
break;
break;
case iXLAT:
if (inst.src().segOver)
@ -456,17 +474,18 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
case iOUT:
{
std::string d1=((inst.testFlags(I))? strHex(inst.src().getImm2()): "dx");
std::string d2=((inst.getFlag() & B) ? ", al": ", ax");
QString d1=((inst.testFlags(I))? strHex(inst.src().getImm2()): "dx");
QString d2=((inst.getFlag() & B) ? ", al": ", ax");
operands_s<<d1 << d2;
}
break;
break;
default:
break;
}
oper_stream << setw(15) << left <<opcode_with_mods.str();
oper_stream << operands_s.str();
oper_stream.setFieldWidth(15);
operands_s.flush();
oper_stream << qSetFieldWidth(15) << opcode_with_mods << qSetFieldWidth(0) << operands_contents;
/* Comments */
if (inst.testFlags(SYNTHETIC))
{
@ -474,21 +493,26 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
}
else
{
for (j = inst.label, fImpure = 0; j > 0 && j < (int)nextInst; j++)
for (j = inst.label, fImpure = 0; j > 0 and j < (int)nextInst; j++)
{
fImpure |= BITMAP(j, BM_DATA);
}
}
result_stream << setw(54) << left << oper_stream.str();
result_stream.setFieldWidth(54);
result_stream.setFieldAlignment(QTextStream::AlignLeft);
oper_stream.flush();
result_stream << oper_contents;
result_stream.setFieldWidth(0);
/* Check for user supplied comment */
selectTable(Comment);
ostringstream cbuf;
if (readVal(cbuf, inst.label, 0))
QString cbuf_contents;
QTextStream cbuf(&cbuf_contents);
if (readVal(cbuf, inst.label, nullptr))
{
result_stream <<"; "<<cbuf.str();
cbuf.flush();
result_stream <<"; "<<*cbuf.string();
}
else if (fImpure || (inst.testFlags(SWITCH | CASE | SEG_IMMED | IMPURE | SYNTHETIC | TERMINATES)))
else if (fImpure or (inst.testFlags(SWITCH | CASE | SEG_IMMED | IMPURE | SYNTHETIC | TERMINATES)))
{
if (inst.testFlags(CASE))
{
@ -526,8 +550,9 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
/* output to .b code buffer */
if (inst.testFlags(SYNTHETIC))
result_stream<<";Synthetic inst";
if (pass == 3) /* output to .b code buffer */
cCode.appendCode("%s\n", result_stream.str().c_str());
if (pass == 3) { /* output to .b code buffer */
cCode.appendCode("%s\n", qPrintable(result_contents));
}
}
else
@ -543,7 +568,8 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
sprintf(buf,"%03d ",loc_ip);
result_stream<<";Synthetic inst";
}
m_fp<<buf<< " " << result_stream.str() << "\n";
result_stream.flush();
m_fp<<buf<< " " << result_contents << "\n";
}
}
@ -552,7 +578,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
/****************************************************************************
* formatRM
***************************************************************************/
static void formatRM(std::ostringstream &p, uint32_t flg, const LLOperand &pm)
static void formatRM(QTextStream &p, const LLOperand &pm)
{
//char seg[4];
@ -589,13 +615,13 @@ static void formatRM(std::ostringstream &p, uint32_t flg, const LLOperand &pm)
/*****************************************************************************
* strDst
****************************************************************************/
static ostringstream & strDst(ostringstream &os,uint32_t flg, const LLOperand &pm)
static QTextStream & strDst(QTextStream &os,uint32_t flg, const LLOperand &pm)
{
/* Immediates to memory require size descriptor */
//os << setw(WID_PTR);
if ((flg & I) and not pm.isReg())
os << szPtr[flg & B];
formatRM(os, flg, pm);
formatRM(os, pm);
return os;
}
@ -603,7 +629,7 @@ static ostringstream & strDst(ostringstream &os,uint32_t flg, const LLOperand &p
/****************************************************************************
* strSrc *
****************************************************************************/
ostringstream &LLInst::strSrc(ostringstream &os,bool skip_comma)
QTextStream &LLInst::strSrc(QTextStream &os,bool skip_comma)
{
if(false==skip_comma)
os<<", ";
@ -612,7 +638,7 @@ ostringstream &LLInst::strSrc(ostringstream &os,bool skip_comma)
else if (testFlags(IM_SRC)) /* level 2 */
os<<"dx:ax";
else
formatRM(os, getFlag(), src());
formatRM(os, src());
return os;
}
@ -627,7 +653,7 @@ static char *strHex(uint32_t d)
static char buf[10];
d &= 0xFFFF;
sprintf(buf, "0%lX%s", d, (d > 9)? "h": "");
sprintf(buf, "0%X%s", d, (d > 9)? "h": "");
return (buf + (buf[1] <= '9'));
}
@ -636,25 +662,29 @@ static char *strHex(uint32_t d)
****************************************************************************/
void interactDis(Function * initProc, int initIC)
{
printf("Sorry - interactive disasassembler option not available for Unix\n");
QString procname = "UNKNOWN";
if(initProc)
procname = initProc->name;
qDebug() << "Wanted to start interactive disasassembler for "<<procname<<":"<<initIC;
return;
}
/* Handle the floating point opcodes (icode iESC) */
void LLInst::flops(std::ostringstream &out)
void LLInst::flops(QTextStream &out)
{
char bf[30];
//char bf[30];
uint8_t op = (uint8_t)src().getImm2();
/* Note that op is set to the escape number, e.g.
esc 0x38 is FILD */
if ( not dst.isReg() )
if ( not m_dst.isReg() )
{
/* The mod/rm mod bits are not set to 11 (i.e. register). This is the normal floating point opcode */
out<<Machine_X86::floatOpName(op)<<' ';
out <<setw(10);
if ((op == 0x29) || (op == 0x1F))
out.setFieldWidth(10);
if ((op == 0x29) or (op == 0x1F))
{
out << "tbyte ptr ";
}
@ -684,8 +714,8 @@ void LLInst::flops(std::ostringstream &out)
break;
}
}
formatRM(out, getFlag(), dst);
out.setFieldWidth(0);
formatRM(out, m_dst);
}
else
{
@ -694,7 +724,7 @@ void LLInst::flops(std::ostringstream &out)
normal opcodes. Because the opcodes are slightly different for
this case (e.g. op=04 means FSUB if reg != 3, but FSUBR for
reg == 3), a separate table is used (szFlops2). */
int destRegIdx=dst.regi - rAX;
int destRegIdx=m_dst.regi - rAX;
switch (op)
{
case 0x0C:
@ -723,7 +753,7 @@ void LLInst::flops(std::ostringstream &out)
break;
default:
out << Machine_X86::floatOpName(0x40+op);
if ((op >= 0x20) && (op <= 0x27))
if ((op >= 0x20) and (op <= 0x27))
{
/* This is the ST(i), ST form. */
out << "ST("<<destRegIdx - rAX<<"),ST";

View File

@ -11,36 +11,37 @@
#include "dcc.h"
static std::map<eErrorId,std::string> errorMessage =
{
{INVALID_ARG ,"Invalid option -%c\n"},
{INVALID_OPCODE ,"Invalid instruction %02X at location %06lX\n"},
{INVALID_386OP ,"Don't understand 80386 instruction %02X at location %06lX\n"},
{FUNNY_SEGOVR ,"Segment override with no memory operand at location %06lX\n"},
{FUNNY_REP ,"REP prefix without a string instruction at location %06lX\n"},
{CANNOT_OPEN ,"Cannot open %s\n"},
{CANNOT_READ ,"Error while reading %s\n"},
{MALLOC_FAILED ,"malloc of %ld bytes failed\n"},
{NEWEXE_FORMAT ,"Don't understand new EXE format\n"},
{NO_BB ,"Failed to find a BB for jump to %ld in proc %s\n"},
{INVALID_SYNTHETIC_BB,"Basic Block is a synthetic jump\n"},
{INVALID_INT_BB ,"Failed to find a BB for interval\n"},
{IP_OUT_OF_RANGE ,"Instruction at location %06lX goes beyond loaded image\n"},
{DEF_NOT_FOUND ,"Definition not found for condition code usage at opcode %d\n"},
{JX_NOT_DEF ,"JX use, definition not supported at opcode #%d\n"},
{NOT_DEF_USE ,"Def - use not supported. Def op = %d, use op = %d.\n"},
{REPEAT_FAIL ,"Failed to construct repeat..until() condition.\n"},
{WHILE_FAIL ,"Failed to construct while() condition.\n"},
};
static const std::map<eErrorId,std::string> errorMessage =
{
{INVALID_ARG ,"Invalid option -%c\n"},
{INVALID_OPCODE ,"Invalid instruction %02X at location %06lX\n"},
{INVALID_386OP ,"Don't understand 80386 instruction %02X at location %06lX\n"},
{FUNNY_SEGOVR ,"Segment override with no memory operand at location %06lX\n"},
{FUNNY_REP ,"REP prefix without a string instruction at location %06lX\n"},
{CANNOT_OPEN ,"Cannot open %s\n"},
{CANNOT_READ ,"Error while reading %s\n"},
{MALLOC_FAILED ,"malloc of %ld bytes failed\n"},
{NEWEXE_FORMAT ,"Don't understand new EXE format\n"},
{NO_BB ,"Failed to find a BB for jump to %ld in proc %s\n"},
{INVALID_SYNTHETIC_BB,"Basic Block is a synthetic jump\n"},
{INVALID_INT_BB ,"Failed to find a BB for interval\n"},
{IP_OUT_OF_RANGE ,"Instruction at location %06lX goes beyond loaded image\n"},
{DEF_NOT_FOUND ,"Definition not found for condition code usage at opcode %d\n"},
{JX_NOT_DEF ,"JX use, definition not supported at opcode #%d\n"},
{NOT_DEF_USE ,"%x: Def - use not supported. Def op = %d, use op = %d.\n"},
{REPEAT_FAIL ,"Failed to construct repeat..until() condition.\n"},
{WHILE_FAIL ,"Failed to construct while() condition.\n"},
};
/****************************************************************************
fatalError: displays error message and exits the program.
****************************************************************************/
void fatalError(eErrorId errId, ...)
{ va_list args;
//#ifdef __UNIX__ /* ultrix */
{
va_list args;
//#ifdef __UNIX__ /* ultrix */
#if 0
int errId;
int errId;
va_start(args);
errId = va_arg(args, int);
@ -49,10 +50,12 @@ void fatalError(eErrorId errId, ...)
#endif
if (errId == USAGE)
fprintf(stderr,"Usage: dcc [-a1a2cmpsvVi][-o asmfile] DOS_executable\n");
fprintf(stderr,"Usage: dcc [-a1a2cmpsvVi][-o asmfile] DOS_executable\n");
else {
auto msg_iter = errorMessage.find(errId);
assert(msg_iter!=errorMessage.end());
fprintf(stderr, "dcc: ");
vfprintf(stderr, errorMessage[errId].c_str(), args);
vfprintf(stderr, msg_iter->second.c_str(), args);
}
va_end(args);
exit((int)errId);
@ -63,10 +66,11 @@ void fatalError(eErrorId errId, ...)
reportError: reports the warning/error and continues with the program.
****************************************************************************/
void reportError(eErrorId errId, ...)
{ va_list args;
//#ifdef __UNIX__ /* ultrix */
{
va_list args;
//#ifdef __UNIX__ /* ultrix */
#if 0
int errId;
int errId;
va_start(args);
errId = va_arg(args, int);
@ -74,6 +78,8 @@ void reportError(eErrorId errId, ...)
va_start(args, errId);
#endif
fprintf(stderr, "dcc: ");
vfprintf(stderr, errorMessage[errId].c_str(), args);
auto msg_iter = errorMessage.find(errId);
assert(msg_iter!=errorMessage.end());
vfprintf(stderr, msg_iter->second.c_str(), args);
va_end(args);
}

View File

@ -9,18 +9,15 @@
* *
\* * * * * * * * * * * * */
#include "msvc_fixes.h"
#include <memory.h>
#include <stdint.h>
#ifndef PATLEN
#define PATLEN 23
#define WILD 0xF4
#endif
#ifndef bool
#define bool unsigned char
#define uint8_t unsigned char
#endif
static int pc; /* Indexes into pat[] */
/* prototypes */
@ -82,8 +79,9 @@ TwoWild(uint8_t pat[])
static bool
FourWild(uint8_t pat[])
{
TwoWild(pat);
return TwoWild(pat);
if(TwoWild(pat))
return true;
return TwoWild(pat);
}
/* Chop from the current point by wiping with zeroes. Can't rely on anything
@ -180,8 +178,7 @@ static bool op0F(uint8_t pat[])
processor is in 16 bit address mode (real mode).
PATLEN bytes are scanned.
*/
void
fixWildCards(uint8_t pat[])
void fixWildCards(uint8_t pat[])
{
uint8_t op, quad, intArg;
@ -339,7 +336,7 @@ fixWildCards(uint8_t pat[])
if (op & 1) pc += 2;
else pc += 1;
continue;
}
case 0xB0: /* B0 - BF */
{
@ -410,7 +407,7 @@ fixWildCards(uint8_t pat[])
case 0xCD: /* int nn */
intArg = pat[pc++];
if ((intArg >= 0x34) && (intArg <= 0x3B))
if ((intArg >= 0x34) and (intArg <= 0x3B))
{
/* Borland/Microsoft FP emulations */
if (ModRM(pat)) return;

View File

@ -7,10 +7,17 @@
#include "dcc.h"
#include "disassem.h"
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h> /* For malloc, free, realloc */
#include "project.h"
class Loader
{
bool loadIntoProject(IProject *);
};
typedef struct { /* PSP structure */
uint16_t int20h; /* interrupt 20h */
uint16_t eof; /* segment, end of allocation block */
@ -50,7 +57,7 @@ static struct { /* EXE file header */
#define EXE_RELOCATION 0x10 /* EXE images rellocated to above PSP */
static void LoadImage(char *filename);
//static void LoadImage(char *filename);
static void displayLoadInfo(void);
static void displayMemMap(void);
@ -58,31 +65,29 @@ static void displayMemMap(void);
* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode
* rewritter, and displays any useful information.
****************************************************************************/
extern Project g_proj;
bool DccFrontend::FrontEnd ()
{
g_proj.callGraph = 0;
g_proj.m_fname = m_fname;
Project::get()->callGraph = nullptr;
Project::get()->create(m_fname);
/* Load program into memory */
LoadImage(g_proj);
LoadImage(*Project::get());
if (option.verbose)
displayLoadInfo();
/* Do depth first flow analysis building call graph and procedure list,
* and attaching the I-code to each procedure */
parse (g_proj);
parse (*Project::get());
if (option.asm1)
{
printf("dcc: writing assembler file %s\n", asm1_name);
printf("dcc: writing assembler file %s\n", asm1_name.c_str());
}
/* Search through code looking for impure references and flag them */
Disassembler ds(1);
for(Function &f : g_proj.pProcList)
for(Function &f : Project::get()->pProcList)
{
f.markImpure();
if (option.asm1)
@ -92,11 +97,11 @@ bool DccFrontend::FrontEnd ()
}
if (option.Interact)
{
interactDis(&g_proj.pProcList.front(), 0); /* Interactive disassembler */
interactDis(&Project::get()->pProcList.front(), 0); /* Interactive disassembler */
}
/* Converts jump target addresses to icode offsets */
for(Function &f : g_proj.pProcList)
for(Function &f : Project::get()->pProcList)
{
f.bindIcodeOff();
}
@ -125,7 +130,7 @@ static void displayLoadInfo(void)
printf("Minimum allocation = %04X paras\n", LH(&header.minAlloc));
printf("Maximum allocation = %04X paras\n", LH(&header.maxAlloc));
}
printf("Load image size = %04X\n", prog.cbImage - sizeof(PSP));
printf("Load image size = %04" PRIiPTR "\n", prog.cbImage - sizeof(PSP));
printf("Initial SS:SP = %04X:%04X\n", prog.initSS, prog.initSP);
printf("Initial CS:IP = %04X:%04X\n", prog.initCS, prog.initIP);
@ -134,7 +139,7 @@ static void displayLoadInfo(void)
printf("\nRelocation Table\n");
for (i = 0; i < prog.cReloc; i++)
{
printf("%06X -> [%04X]\n", prog.relocTable[i],LH(prog.Image + prog.relocTable[i]));
printf("%06X -> [%04X]\n", prog.relocTable[i],LH(prog.image() + prog.relocTable[i]));
}
}
printf("\n");
@ -208,23 +213,23 @@ void DccFrontend::LoadImage(Project &proj)
uint8_t buf[4];
/* Open the input file */
if ((fp = fopen(proj.m_fname.c_str(), "rb")) == NULL)
if ((fp = fopen(proj.binary_path().c_str(), "rb")) == nullptr)
{
fatalError(CANNOT_OPEN, proj.m_fname.c_str());
fatalError(CANNOT_OPEN, proj.binary_path().c_str());
}
/* Read in first 2 bytes to check EXE signature */
if (fread(&header, 1, 2, fp) != 2)
{
fatalError(CANNOT_READ, proj.m_fname.c_str());
fatalError(CANNOT_READ, proj.binary_path().c_str());
}
if (! (prog.fCOM = (boolT)(header.sigLo != 0x4D || header.sigHi != 0x5A))) {
prog.fCOM = (header.sigLo != 0x4D || header.sigHi != 0x5A);
if (! prog.fCOM ) {
/* Read rest of header */
fseek(fp, 0, SEEK_SET);
if (fread(&header, sizeof(header), 1, fp) != 1)
{
fatalError(CANNOT_READ, proj.m_fname.c_str());
fatalError(CANNOT_READ, proj.binary_path().c_str());
}
/* This is a typical DOS kludge! */
@ -245,13 +250,13 @@ void DccFrontend::LoadImage(Project &proj)
}
/* We quietly ignore minAlloc and maxAlloc since for our
* purposes it doesn't really matter where in real memory
* the program would end up. EXE programs can't really rely on
* their load location so setting the PSP segment to 0 is fine.
* Certainly programs that prod around in DOS or BIOS are going
* to have to load DS from a constant so it'll be pretty
* obvious.
*/
* purposes it doesn't really matter where in real memory
* the program would end up. EXE programs can't really rely on
* their load location so setting the PSP segment to 0 is fine.
* Certainly programs that prod around in DOS or BIOS are going
* to have to load DS from a constant so it'll be pretty
* obvious.
*/
prog.initCS = (int16_t)LH(&header.initCS) + EXE_RELOCATION;
prog.initIP = (int16_t)LH(&header.initIP);
prog.initSS = (int16_t)LH(&header.initSS) + EXE_RELOCATION;
@ -298,14 +303,14 @@ void DccFrontend::LoadImage(Project &proj)
/* Allocate a block of memory for the program. */
prog.cbImage = cb + sizeof(PSP);
prog.Image = new uint8_t [prog.cbImage];
prog.Image[0] = 0xCD; /* Fill in PSP int 20h location */
prog.Image[1] = 0x20; /* for termination checking */
prog.Imagez = new uint8_t [prog.cbImage];
prog.Imagez[0] = 0xCD; /* Fill in PSP int 20h location */
prog.Imagez[1] = 0x20; /* for termination checking */
/* Read in the image past where a PSP would go */
if (cb != (int)fread(prog.Image + sizeof(PSP), 1, (size_t)cb, fp))
if (cb != (int)fread(prog.Imagez + sizeof(PSP), 1, (size_t)cb, fp))
{
fatalError(CANNOT_READ, proj.m_fname.c_str());
fatalError(CANNOT_READ, proj.binary_path().c_str());
}
/* Set up memory map */
@ -318,7 +323,7 @@ void DccFrontend::LoadImage(Project &proj)
{
for (i = 0; i < prog.cReloc; i++)
{
uint8_t *p = &prog.Image[prog.relocTable[i]];
uint8_t *p = &prog.Imagez[prog.relocTable[i]];
uint16_t w = (uint16_t)LH(p) + EXE_RELOCATION;
*p++ = (uint8_t)(w & 0x00FF);
*p = (uint8_t)((w & 0xFF00) >> 8);

View File

@ -3,15 +3,30 @@
* (C) Cristina Cifuentes
****************************************************************************/
#include "dcc.h"
#include <string.h>
#include <malloc.h> /* For free() */
#include "graph.h"
#include "msvc_fixes.h"
#include "dcc.h"
#include "project.h"
#include <boost/range/rbegin.hpp>
#include <boost/range/rend.hpp>
#include <string.h>
using namespace std;
using namespace boost;
extern Project g_proj;
//static BB * rmJMP(Function * pProc, int marker, BB * pBB);
static void mergeFallThrough(Function * pProc, BB * pBB);
static void dfsNumbering(BB * pBB, std::vector<BB*> &dfsLast, int *first, int *last);
//static void mergeFallThrough(Function * pProc, BB * pBB);
//static void dfsNumbering(BB * pBB, std::vector<BB*> &dfsLast, int *first, int *last);
void Function::addOutEdgesForConditionalJump(BB * pBB,int next_ip, LLInst *ll)
{
pBB->addOutEdge(next_ip);
/* This is checking for jumps off into nowhere */
if ( not ll->testFlags(NO_LABEL) )
pBB->addOutEdge(ll->src().getImm2());
}
/*****************************************************************************
* createCFG - Create the basic control flow graph
@ -29,142 +44,119 @@ void Function::createCFG()
* 5) Repeated string instructions
* 6) End of procedure
*/
int i;
int ip;
BB * psBB;
BB * pBB;
iICODE pIcode = Icode.begin();
iICODE iStart = Icode.begin();
stats.numBBbef = stats.numBBaft = 0;
for (; pIcode!=Icode.end(); ++pIcode)
rICODE current_range=make_iterator_range(pIcode,++iICODE(pIcode));
for (; pIcode!=Icode.end(); ++pIcode,current_range.advance_end(1))
{
iICODE nextIcode = ++iICODE(pIcode);
pBB = nullptr;
LLInst *ll = pIcode->ll();
/* Only process icodes that have valid instructions */
if(ll->testFlags(NO_CODE))
continue;
/* Stick a NOWHERE_NODE on the end if we terminate
* with anything other than a ret, jump or terminate */
* with anything other than a ret, jump or terminate */
if (nextIcode == Icode.end() and
(not ll->testFlags(TERMINATES)) and
(not ll->match(iJMP)) and (not ll->match(iJMPF)) and
(not ll->match(iRET)) and (not ll->match(iRETF)))
{
//pBB=BB::Create(start, ip, NOWHERE_NODE, 0, this);
pBB=BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this);
pBB=BB::Create(current_range, NOWHERE_NODE, this);
}
/* Only process icodes that have valid instructions */
else if (not ll->testFlags(NO_CODE) )
{
else
switch (ll->getOpcode()) {
case iJB: case iJBE: case iJAE: case iJA:
case iJL: case iJLE: case iJGE: case iJG:
case iJE: case iJNE: case iJS: case iJNS:
case iJO: case iJNO: case iJP: case iJNP:
case iJCXZ:
pBB = BB::Create(iStart, pIcode, TWO_BRANCH, 2, this);
CondJumps:
//start = ip + 1;
iStart = ++iICODE(pIcode);
pBB->edges[0].ip = (uint32_t)iStart->loc_ip;
/* This is for jumps off into nowhere */
if ( ll->testFlags(NO_LABEL) )
{
pBB->edges.pop_back();
}
else
pBB->edges[1].ip = ll->src().getImm2();
break;
case iJB: case iJBE: case iJAE: case iJA:
case iJL: case iJLE: case iJGE: case iJG:
case iJE: case iJNE: case iJS: case iJNS:
case iJO: case iJNO: case iJP: case iJNP:
case iJCXZ:
pBB = BB::Create(current_range, TWO_BRANCH, this);
addOutEdgesForConditionalJump(pBB,nextIcode->loc_ip, ll);
break;
case iLOOP: case iLOOPE: case iLOOPNE:
//pBB = BB::Create(start, ip, LOOP_NODE, 2, this);
pBB = BB::Create(iStart, pIcode, LOOP_NODE, 2, this);
goto CondJumps;
case iLOOP: case iLOOPE: case iLOOPNE:
pBB = BB::Create(current_range, LOOP_NODE, this);
addOutEdgesForConditionalJump(pBB,nextIcode->loc_ip, ll);
break;
case iJMPF: case iJMP:
if (ll->testFlags(SWITCH))
{
//pBB = BB::Create(start, ip, MULTI_BRANCH, ll->caseTbl.numEntries, this);
pBB = BB::Create(iStart, pIcode, MULTI_BRANCH, ll->caseTbl2.size(), this);
for (i = 0; i < ll->caseTbl2.size(); i++)
pBB->edges[i].ip = ll->caseTbl2[i];
hasCase = true;
}
else if ((ll->getFlag() & (I | NO_LABEL)) == I) //TODO: WHY NO_LABEL TESTIT
{
//pBB = BB::Create(start, ip, ONE_BRANCH, 1, this);
pBB = BB::Create(iStart, pIcode, ONE_BRANCH, 1, this);
pBB->edges[0].ip = ll->src().getImm2();
}
else
BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this);
iStart = ++iICODE(pIcode);
break;
case iCALLF: case iCALL:
case iJMPF: case iJMP:
if (ll->testFlags(SWITCH))
{
Function * p = ll->src().proc.proc;
if (p)
i = ((p->flg) & TERMINATES) ? 0 : 1;
else
i = 1;
pBB = BB::Create(iStart, pIcode, CALL_NODE, i, this);
iStart = ++iICODE(pIcode);//start = ip + 1;
if (i)
pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start;
pBB = BB::Create(current_range, MULTI_BRANCH, this);
for (auto & elem : ll->caseTbl2)
pBB->addOutEdge(elem);
hasCase = true;
}
break;
else if ((ll->getFlag() & (I | NO_LABEL)) == I) //TODO: WHY NO_LABEL TESTIT
{
pBB = BB::Create(current_range, ONE_BRANCH, this);
pBB->addOutEdge(ll->src().getImm2());
}
else
pBB = BB::Create(current_range, NOWHERE_NODE, this);
break;
case iRET: case iRETF:
//BB::Create(start, ip, RETURN_NODE, 0, this);
BB::Create(iStart, pIcode, RETURN_NODE, 0, this);
iStart = ++iICODE(pIcode);
break;
default:
/* Check for exit to DOS */
iICODE next1=++iICODE(pIcode);
if ( ll->testFlags(TERMINATES) )
{
pBB = BB::Create(iStart, pIcode, TERMINATE_NODE, 0, this);
//pBB = BB::Create(start, ip, TERMINATE_NODE, 0, this);
iStart = ++iICODE(pIcode); // start = ip + 1;
}
/* Check for a fall through */
else if (next1 != Icode.end())
{
if (next1->ll()->testFlags(TARGET | CASE))
{
//pBB = BB::Create(start, ip, FALL_NODE, 1, this);
pBB = BB::Create(iStart, pIcode, FALL_NODE, 1, this);
iStart = ++iICODE(pIcode); // start = ip + 1;
pBB->addOutEdge(iStart->loc_ip);
pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start;
}
}
break;
case iCALLF: case iCALL:
{
Function * p = ll->src().proc.proc;
pBB = BB::Create(current_range, CALL_NODE, this);
if (p and not ((p->flg) & TERMINATES) )
pBB->addOutEdge(nextIcode->loc_ip);
break;
}
}
}
auto iter=heldBBs.begin();
/* Convert list of BBs into a graph */
for (; iter!=heldBBs.end(); ++iter)
{
pBB = *iter;
for (size_t edeg_idx = 0; edeg_idx < pBB->edges.size(); edeg_idx++)
case iRET: case iRETF:
pBB = BB::Create(current_range, RETURN_NODE, this);
break;
default:
/* Check for exit to DOS */
if ( ll->testFlags(TERMINATES) )
{
pBB = BB::Create(current_range, TERMINATE_NODE, this);
}
/* Check for a fall through */
else if (nextIcode != Icode.end())
{
if (nextIcode->ll()->testFlags(TARGET | CASE))
{
pBB = BB::Create(current_range, FALL_NODE, this);
pBB->addOutEdge(nextIcode->loc_ip);
}
}
break;
}
if(pBB!=nullptr) // created a new Basic block
{
uint32_t ip = pBB->edges[edeg_idx].ip;
// restart the range
// end iterator will be updated by expression in for statement
current_range=make_iterator_range(nextIcode,nextIcode);
}
if (nextIcode == Icode.end())
break;
}
for (auto pr : m_ip_to_bb)
{
BB* pBB=pr.second;
for (auto & elem : pBB->edges)
{
int32_t ip = elem.ip;
if (ip >= SYNTHESIZED_MIN)
{
fatalError (INVALID_SYNTHETIC_BB);
return;
}
auto iter2=std::find_if(heldBBs.begin(),heldBBs.end(),
[ip](BB *psBB)->bool {return psBB->begin()->loc_ip==ip;});
if(iter2==heldBBs.end())
fatalError(NO_BB, ip, name.c_str());
psBB = *iter2;
pBB->edges[edeg_idx].BBptr = psBB;
auto iter2=m_ip_to_bb.find(ip);
if(iter2==m_ip_to_bb.end())
fatalError(NO_BB, ip, qPrintable(name));
psBB = iter2->second;
elem.BBptr = psBB;
psBB->inEdges.push_back((BB *)nullptr);
}
}
@ -179,8 +171,8 @@ void Function::markImpure()
continue;
//assert that case tbl has less entries then symbol table ????
//WARNING: Case entries are held in symbol table !
assert(g_proj.validSymIdx(icod.ll()->caseEntry));
const SYM &psym(g_proj.getSymByIdx(icod.ll()->caseEntry));
assert(Project::get()->validSymIdx(icod.ll()->caseEntry));
const SYM &psym(Project::get()->getSymByIdx(icod.ll()->caseEntry));
for (int c = (int)psym.label; c < (int)psym.label+psym.size; c++)
{
if (BITMAP(c, BM_CODE))
@ -194,21 +186,16 @@ void Function::markImpure()
}
/*****************************************************************************
* newBB - Allocate new BB and link to end of list
*****************************************************************************/
/*****************************************************************************
* freeCFG - Deallocates a cfg
****************************************************************************/
void Function::freeCFG()
{
for(BB *p : heldBBs)
for(auto p : m_ip_to_bb)
{
delete p;
delete p.second;
}
m_ip_to_bb.clear();
}
@ -222,9 +209,9 @@ void Function::compressCFG()
/* First pass over BB list removes redundant jumps of the form
* (Un)Conditional -> Unconditional jump */
for (BB *pBB : m_cfg)
for (BB *pBB : m_actual_cfg) //m_cfg
{
if(pBB->inEdges.empty() || (pBB->nodeType != ONE_BRANCH && pBB->nodeType != TWO_BRANCH))
if(pBB->inEdges.empty() or (pBB->nodeType != ONE_BRANCH and pBB->nodeType != TWO_BRANCH))
continue;
for (TYPEADR_TYPE &edgeRef : pBB->edges)
{
@ -244,18 +231,17 @@ void Function::compressCFG()
/* Next is a depth-first traversal merging any FALL_NODE or
* ONE_BRANCH that fall through to a node with that as their only
* in-edge. */
m_cfg.front()->mergeFallThrough(Icode);
m_actual_cfg.front()->mergeFallThrough(Icode);
/* Remove redundant BBs created by the above compressions
* and allocate in-edge arrays as required. */
stats.numBBaft = stats.numBBbef;
for(auto iter=m_cfg.begin(); iter!=m_cfg.end(); ++iter)
bool entry_node=true;
for(BB *pBB : m_actual_cfg)
{
BB * pBB = *iter;
if (pBB->inEdges.empty())
{
if (iter == m_cfg.begin()) /* Init it misses out on */
if (entry_node) /* Init it misses out on */
pBB->index = UN_INIT;
else
{
@ -267,15 +253,16 @@ void Function::compressCFG()
{
pBB->inEdgeCount = pBB->inEdges.size();
}
entry_node=false;
}
/* Allocate storage for dfsLast[] array */
numBBs = stats.numBBaft;
m_dfsLast.resize(numBBs,0); // = (BB **)allocMem(numBBs * sizeof(BB *))
m_dfsLast.resize(numBBs,nullptr); // = (BB **)allocMem(numBBs * sizeof(BB *))
/* Now do a dfs numbering traversal and fill in the inEdges[] array */
last = numBBs - 1;
m_cfg.front()->dfsNumbering(m_dfsLast, &first, &last);
m_actual_cfg.front()->dfsNumbering(m_dfsLast, &first, &last);
}
@ -286,7 +273,7 @@ BB *BB::rmJMP(int marker, BB * pBB)
{
marker += (int)DFS_JMP;
while (pBB->nodeType == ONE_BRANCH && pBB->size() == 1)
while (pBB->nodeType == ONE_BRANCH and pBB->size() == 1)
{
if (pBB->traversed != marker)
{
@ -313,7 +300,7 @@ BB *BB::rmJMP(int marker, BB * pBB)
do {
pBB = pBB->edges[0].BBptr;
pBB->inEdges.pop_back(); // was --numInedges
if (! pBB->inEdges.empty())
if (not pBB->inEdges.empty())
{
pBB->front().ll()->setFlags(NO_CODE);
pBB->front().invalidate();
@ -335,13 +322,11 @@ BB *BB::rmJMP(int marker, BB * pBB)
void BB::mergeFallThrough( CIcodeRec &Icode)
{
BB * pChild;
int i;
if (!this)
if (nullptr==this)
{
printf("mergeFallThrough on empty BB!\n");
}
while (nodeType == FALL_NODE || nodeType == ONE_BRANCH)
while (nodeType == FALL_NODE or nodeType == ONE_BRANCH)
{
pChild = edges[0].BBptr;
/* Jump to next instruction can always be removed */
@ -375,9 +360,11 @@ void BB::mergeFallThrough( CIcodeRec &Icode)
traversed = DFS_MERGE;
/* Process all out edges recursively */
for (i = 0; i < edges.size(); i++)
if (edges[i].BBptr->traversed != DFS_MERGE)
edges[i].BBptr->mergeFallThrough(Icode);
for (auto & elem : edges)
{
if (elem.BBptr->traversed != DFS_MERGE)
elem.BBptr->mergeFallThrough(Icode);
}
}
@ -399,7 +386,7 @@ void BB::dfsNumbering(std::vector<BB *> &dfsLast, int *first, int *last)
pChild->inEdges[pChild->index++] = this;
/* Is this the last visit? */
if (pChild->index == pChild->inEdges.size())
if (pChild->index == int(pChild->inEdges.size()))
pChild->index = UN_INIT;
if (pChild->traversed != DFS_NUM)

View File

@ -4,51 +4,38 @@
* Date: September-October 1993
* (C) Cristina Cifuentes
*/
#include "dcc.h"
#include <QtCore/QDebug>
#include <QtCore/QString>
#include <cassert>
#include <string.h>
#include <string>
#include <sstream>
#include "dcc.h"
using namespace std;
#define ICODE_DELTA 25
/* Masks off bits set by duReg[] */
std::bitset<32> maskDuReg[] = { 0x00,
0xFEEFFE, 0xFDDFFD, 0xFBB00B, 0xF77007, /* uint16_t regs */
0xFFFFEF, 0xFFFFDF, 0xFFFFBF, 0xFFFF7F,
0xFFFEFF, 0xFFFDFF, 0xFFFBFF, 0xFFF7FF, /* seg regs */
0xFFEFFF, 0xFFDFFF, 0xFFBFFF, 0xFF7FFF, /* uint8_t regs */
0xFEFFFF, 0xFDFFFF, 0xFBFFFF, 0xF7FFFF,
0xEFFFFF, /* tmp reg */
0xFFFFB7, 0xFFFF77, 0xFFFF9F, 0xFFFF5F, /* index regs */
0xFFFFBF, 0xFFFF7F, 0xFFFFDF, 0xFFFFF7 };
static char buf[lineSize]; /* Line buffer for hl icode output */
/* Places the new HLI_ASSIGN high-level operand in the high-level icode array */
void HLTYPE::setAsgn(COND_EXPR *lhs, COND_EXPR *rhs)
void HLTYPE::setAsgn(Expr *lhs, Expr *rhs)
{
assert(lhs);
set(lhs,rhs);
}
void ICODE::checkHlCall()
{
//assert((ll()->immed.proc.cb != 0)||ll()->immed.proc.proc!=0);
//assert((ll()->immed.proc.cb != 0) or ll()->immed.proc.proc!=0);
}
/* Places the new HLI_CALL high-level operand in the high-level icode array */
void ICODE::newCallHl()
{
type = HIGH_LEVEL;
hl()->opcode = HLI_CALL;
hl()->call.proc = ll()->src().proc.proc;
hl()->call.args = new STKFRAME;
type = HIGH_LEVEL_ICODE;
hlU()->setCall(ll()->src().proc.proc);
if (ll()->src().proc.cb != 0)
hl()->call.args->cb = ll()->src().proc.cb;
hlU()->call.args->cb = ll()->src().proc.cb;
else if(hl()->call.proc)
hl()->call.args->cb =hl()->call.proc->cbParam;
hlU()->call.args->cb = hl()->call.proc->cbParam;
else
{
printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n");
@ -59,18 +46,18 @@ void ICODE::newCallHl()
/* Places the new HLI_POP/HLI_PUSH/HLI_RET high-level operand in the high-level icode
* array */
void ICODE::setUnary(hlIcode op, COND_EXPR *_exp)
void ICODE::setUnary(hlIcode op, Expr *_exp)
{
type = HIGH_LEVEL;
hl()->set(op,_exp);
type = HIGH_LEVEL_ICODE;
hlU()->set(op,_exp);
}
/* Places the new HLI_JCOND high-level operand in the high-level icode array */
void ICODE::setJCond(COND_EXPR *cexp)
void ICODE::setJCond(Expr *cexp)
{
type = HIGH_LEVEL;
hl()->set(HLI_JCOND,cexp);
type = HIGH_LEVEL_ICODE;
hlU()->set(HLI_JCOND,cexp);
}
@ -90,13 +77,13 @@ bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId)
{
int numDefs;
numDefs = du1.numRegsDef;
numDefs = du1.getNumRegsDef();
if (numDefs == thisDefIdx)
{
for ( ; numDefs > 0; numDefs--)
{
if (du1.used(numDefs-1)||(du.lastDefRegi[regi]))
if (du1.used(numDefs-1) or (du.lastDefRegi.testReg(regi)))
break;
}
}
@ -106,11 +93,12 @@ bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId)
invalidate();
return true;
}
HlTypeSupport *p=hl()->get();
HlTypeSupport *p=hlU()->get();
if(p and p->removeRegFromLong(regi,locId))
{
du1.numRegsDef--;
du.def &= maskDuReg[regi];
du1.removeDef(regi); //du1.numRegsDef--;
//du.def &= maskDuReg[regi];
du.def.clrReg(regi);
}
return false;
}
@ -158,7 +146,7 @@ HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
break;
case iDEC:
rhs = COND_EXPR::idKte (1, 2);
rhs = AstIdent::idKte (1, 2);
rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
res.setAsgn(lhs, rhs);
break;
@ -168,12 +156,12 @@ HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
rhs = COND_EXPR::boolOp (lhs, rhs, DIV);
if ( ll->testFlags(B) )
{
lhs = COND_EXPR::idReg (rAL, 0, &localId);
lhs = AstIdent::idReg (rAL, 0, &localId);
pIcode->setRegDU( rAL, eDEF);
}
else
{
lhs = COND_EXPR::idReg (rAX, 0, &localId);
lhs = AstIdent::idReg (rAX, 0, &localId);
pIcode->setRegDU( rAX, eDEF);
}
res.setAsgn(lhs, rhs);
@ -181,12 +169,12 @@ HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
case iIMUL:
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
lhs = COND_EXPR::id (*pIcode, LHS_OP, func, i, *pIcode, NONE);
lhs = AstIdent::id (*pIcode, LHS_OP, func, i, *pIcode, NONE);
res.setAsgn(lhs, rhs);
break;
case iINC:
rhs = COND_EXPR::idKte (1, 2);
rhs = AstIdent::idKte (1, 2);
rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
res.setAsgn(lhs, rhs);
break;
@ -200,12 +188,12 @@ HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
rhs = COND_EXPR::boolOp (lhs, rhs, MOD);
if ( ll->testFlags(B) )
{
lhs = COND_EXPR::idReg (rAH, 0, &localId);
lhs = AstIdent::idReg (rAH, 0, &localId);
pIcode->setRegDU( rAH, eDEF);
}
else
{
lhs = COND_EXPR::idReg (rDX, 0, &localId);
lhs = AstIdent::idReg (rDX, 0, &localId);
pIcode->setRegDU( rDX, eDEF);
}
res.setAsgn(lhs, rhs);
@ -216,7 +204,7 @@ HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
case iMUL:
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
lhs = COND_EXPR::id (*pIcode, LHS_OP, this, i, *pIcode, NONE);
lhs = AstIdent::id (*pIcode, LHS_OP, this, i, *pIcode, NONE);
res.setAsgn(lhs, rhs);
break;
@ -277,147 +265,184 @@ HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
return res;
}
#endif
static bool needsLhs(unsigned opc)
{
switch (opc)
{
case iCALL:
case iCALLF:
case iRET:
case iRETF:
default: return false;
case iADD:
case iAND:
case iDEC:
case iDIV:
case iIDIV:/* should be signed div */
case iIMUL:
case iINC:
case iLEA:
case iMOD:
case iMOV:
case iMUL:
case iNEG:
case iNOT:
case iOR:
case iPOP:
case iPUSH:
case iSHL:
case iSAR: /* signed */
case iSHR:
case iSIGNEX:
case iSUB:
case iXCHG:
case iXOR:
return true;
}
}
/* Translates LOW_LEVEL icodes to HIGH_LEVEL icodes - 1st stage.
* Note: this process should be done before data flow analysis, which
* refines the HIGH_LEVEL icodes. */
void Function::highLevelGen()
{
int numIcode; /* number of icode instructions */
iICODE pIcode; /* ptr to current icode node */
COND_EXPR *lhs, *rhs; /* left- and right-hand side of expression */
size_t numIcode; /* number of icode instructions */
iICODE pIcode; /* ptr to current icode node */
Expr *rhs; /* left- and right-hand side of expression */
uint32_t _flg; /* icode flags */
numIcode = Icode.size();
for (iICODE i = Icode.begin(); i!=Icode.end() ; ++i)
{
Expr *lhs=nullptr;
assert(numIcode==Icode.size());
pIcode = i; //Icode.GetIcode(i)
LLInst *ll = pIcode->ll();
LLOperand *dst_ll = ll->get(DST);
LLOperand *src_ll = ll->get(SRC);
if ( ll->testFlags(NOT_HLL) )
pIcode->invalidate();
if ((pIcode->type != LOW_LEVEL) or not pIcode->valid() )
if ((pIcode->type != LOW_LEVEL_ICODE) or not pIcode->valid() )
continue;
_flg = ll->getFlag();
if ((_flg & IM_OPS) != IM_OPS) /* not processing IM_OPS yet */
if ((_flg & NO_OPS) != NO_OPS) /* if there are opers */
if (not ll->testFlags(IM_OPS)) /* not processing IM_OPS yet */
if ( not ll->testFlags(NO_OPS) ) /* if there are opers */
{
if ( not ll->testFlags(NO_SRC) ) /* if there is src op */
rhs = COND_EXPR::id (*pIcode->ll(), SRC, this, i, *pIcode, NONE);
lhs = COND_EXPR::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
rhs = AstIdent::id (*pIcode->ll(), SRC, this, i, *pIcode, NONE);
if(ll->m_dst.isSet() or (ll->getOpcode()==iMOD))
lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
}
if(ll->getOpcode()==iPUSH) {
if(ll->testFlags(I)) {
lhs = new Constant(src_ll->opz,src_ll->byteWidth());
}
// lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
}
if(needsLhs(ll->getOpcode()))
assert(lhs!=nullptr);
switch (ll->getOpcode())
{
case iADD:
rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
rhs = new BinaryOperator(ADD,lhs, rhs);
pIcode->setAsgn(lhs, rhs);
break;
case iAND:
rhs = COND_EXPR::boolOp (lhs, rhs, AND);
rhs = BinaryOperator::And(lhs, rhs);
pIcode->setAsgn(lhs, rhs);
break;
case iCALL:
case iCALLF:
pIcode->type = HIGH_LEVEL;
pIcode->type = HIGH_LEVEL_ICODE;
pIcode->hl( ll->createCall() );
break;
case iDEC:
rhs = COND_EXPR::idKte (1, 2);
rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
rhs = new BinaryOperator(SUB,lhs, new Constant(1, 2));
pIcode->setAsgn(lhs, rhs);
break;
case iDIV:
case iIDIV:/* should be signed div */
rhs = COND_EXPR::boolOp (lhs, rhs, DIV);
if ( ll->testFlags(B) )
{
lhs = COND_EXPR::idReg (rAL, 0, &localId);
pIcode->setRegDU( rAL, eDEF);
}
else
{
lhs = COND_EXPR::idReg (rAX, 0, &localId);
pIcode->setRegDU( rAX, eDEF);
}
{
eReg v = ( dst_ll->byteWidth()==1) ? rAL:rAX;
rhs = new BinaryOperator(DIV,lhs, rhs);
lhs = new RegisterNode(LLOperand(v, dst_ll->byteWidth()), &localId);
pIcode->setRegDU( v, eDEF);
pIcode->setAsgn(lhs, rhs);
}
break;
case iIMUL:
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
lhs = COND_EXPR::id (*ll, LHS_OP, this, i, *pIcode, NONE);
rhs = new BinaryOperator(MUL,lhs, rhs);
lhs = AstIdent::id (*ll, LHS_OP, this, i, *pIcode, NONE);
pIcode->setAsgn(lhs, rhs);
break;
case iINC:
rhs = COND_EXPR::idKte (1, 2);
rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
rhs = new BinaryOperator(ADD,lhs, new Constant(1, 2));
pIcode->setAsgn(lhs, rhs);
break;
case iLEA:
rhs = COND_EXPR::unary (ADDRESSOF, rhs);
rhs =UnaryOperator::Create(ADDRESSOF, rhs);
pIcode->setAsgn(lhs, rhs);
break;
case iMOD:
rhs = COND_EXPR::boolOp (lhs, rhs, MOD);
if ( ll->testFlags(B) )
{
lhs = COND_EXPR::idReg (rAH, 0, &localId);
pIcode->setRegDU( rAH, eDEF);
}
else
{
lhs = COND_EXPR::idReg (rDX, 0, &localId);
pIcode->setRegDU( rDX, eDEF);
}
{
rhs = new BinaryOperator(MOD,lhs, rhs);
eReg lhs_reg = (dst_ll->byteWidth()==1) ? rAH : rDX;
lhs = new RegisterNode(LLOperand(lhs_reg, dst_ll->byteWidth()), &localId);
pIcode->setRegDU( lhs_reg, eDEF);
pIcode->setAsgn(lhs, rhs);
}
break;
case iMOV: pIcode->setAsgn(lhs, rhs);
break;
case iMUL:
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
lhs = COND_EXPR::id (*ll, LHS_OP, this, i, *pIcode, NONE);
rhs = new BinaryOperator(MUL,lhs, rhs);
lhs = AstIdent::id (*ll, LHS_OP, this, i, *pIcode, NONE);
pIcode->setAsgn(lhs, rhs);
break;
case iNEG:
rhs = COND_EXPR::unary (NEGATION, lhs);
rhs = UnaryOperator::Create(NEGATION, lhs);
pIcode->setAsgn(lhs, rhs);
break;
case iNOT:
rhs = COND_EXPR::boolOp (NULL, rhs, NOT);
rhs = new BinaryOperator(NOT,nullptr, rhs); // TODO: change this to unary NOT ?
pIcode->setAsgn(lhs, rhs);
break;
case iOR:
rhs = COND_EXPR::boolOp (lhs, rhs, OR);
rhs = new BinaryOperator(OR,lhs, rhs);
pIcode->setAsgn(lhs, rhs);
break;
case iPOP: pIcode->setUnary(HLI_POP, lhs);
case iPOP:
pIcode->setUnary(HLI_POP, lhs);
break;
case iPUSH: pIcode->setUnary(HLI_PUSH, lhs);
case iPUSH:
pIcode->setUnary(HLI_PUSH, lhs);
break;
case iRET:
case iRETF: pIcode->setUnary(HLI_RET, NULL);
case iRETF: pIcode->setUnary(HLI_RET, nullptr);
break;
case iSHL:
rhs = COND_EXPR::boolOp (lhs, rhs, SHL);
rhs = new BinaryOperator(SHL,lhs, rhs);
pIcode->setAsgn(lhs, rhs);
break;
case iSAR: /* signed */
case iSHR:
rhs = COND_EXPR::boolOp (lhs, rhs, SHR); /* unsigned*/
rhs = new BinaryOperator(SHR,lhs, rhs); /* unsigned*/
pIcode->setAsgn(lhs, rhs);
break;
@ -425,7 +450,7 @@ void Function::highLevelGen()
break;
case iSUB:
rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
rhs = new BinaryOperator(SUB,lhs, rhs);
pIcode->setAsgn(lhs, rhs);
break;
@ -433,7 +458,7 @@ void Function::highLevelGen()
break;
case iXOR:
rhs = COND_EXPR::boolOp (lhs, rhs, XOR);
rhs = new BinaryOperator(XOR,lhs, rhs);
pIcode->setAsgn(lhs, rhs);
break;
}
@ -442,151 +467,125 @@ void Function::highLevelGen()
}
/* Modifies the given conditional operator to its inverse. This is used
* in if..then[..else] statements, to reflect the condition that takes the
* then part. */
COND_EXPR *COND_EXPR::inverse () const
{
static condOp invCondOp[] = {GREATER, GREATER_EQUAL, NOT_EQUAL, EQUAL,
LESS_EQUAL, LESS, DUMMY,DUMMY,DUMMY,DUMMY,
DUMMY, DUMMY, DUMMY, DUMMY, DUMMY, DUMMY,
DUMMY, DBL_OR, DBL_AND};
COND_EXPR *res=0;
if (m_type == BOOLEAN_OP)
{
switch ( op() )
{
case LESS_EQUAL: case LESS: case EQUAL:
case NOT_EQUAL: case GREATER: case GREATER_EQUAL:
res = this->clone();
res->boolExpr.op = invCondOp[op()];
return res;
/**
\fn COND_EXPR::inverse
Modifies the given conditional operator to its inverse. This is used
in if..then[..else] statements, to reflect the condition that takes the
then part.
*/
case AND: case OR: case XOR: case NOT: case ADD:
case SUB: case MUL: case DIV: case SHR: case SHL: case MOD:
return COND_EXPR::unary (NEGATION, this->clone());
case DBL_AND: case DBL_OR:
// Binary::Create(invertop,lhs->inverse(),rhs->inverse());
res = this->clone();
res->boolExpr.op = invCondOp[op()];
res->boolExpr.lhs=lhs()->inverse ();
res->boolExpr.rhs=rhs()->inverse ();
return res;
} /* eos */
}
else if (m_type == NEGATION) //TODO: memleak here
{
return expr.unaryExp->clone();
}
return this->clone();
/* other types are left unmodified */
}
/* Returns the string that represents the procedure call of tproc (ie. with
* actual parameters) */
std::string writeCall (Function * tproc, STKFRAME & args, Function * pproc, int *numLoc)
QString Function::writeCall (Function * tproc, STKFRAME & args, int *numLoc)
{
int i; /* counter of # arguments */
string condExp;
ostringstream ostr;
ostr<<tproc->name<<" (";
//string condExp;
QString ostr;
ostr+=tproc->name+" (";
for(const STKSYM &sym : args)
{
ostr << walkCondExpr (sym.actual, pproc, numLoc);
if(sym.actual)
ostr += sym.actual->walkCondExpr(this, numLoc);
else
ostr += "";
if((&sym)!=&(args.back()))
ostr << ", ";
ostr += ", ";
}
ostr << ")";
return ostr.str();
ostr += ")";
return ostr;
}
/* Displays the output of a HLI_JCOND icode. */
char *writeJcond (const HLTYPE &h, Function * pProc, int *numLoc)
QString writeJcond (const HLTYPE &h, Function * pProc, int *numLoc)
{
if(h.opcode==HLI_INVALID)
{
return "if (*HLI_INVALID*) {\n";
}
assert(h.expr());
memset (buf, ' ', sizeof(buf));
buf[0] = '\0';
strcat (buf, "if ");
COND_EXPR *inverted=h.expr()->inverse();
Expr *inverted=h.expr()->inverse();
//inverseCondOp (&h.exp);
std::string e = walkCondExpr (inverted, pProc, numLoc);
QString inverted_form = inverted->walkCondExpr (pProc, numLoc);
delete inverted;
strcat (buf, e.c_str());
strcat (buf, " {\n");
return (buf);
return QString("if %1 {\n").arg(inverted_form);
}
/* Displays the inverse output of a HLI_JCOND icode. This is used in the case
* when the THEN clause of an if..then..else is empty. The clause is
* negated and the ELSE clause is used instead. */
char *writeJcondInv (HLTYPE h, Function * pProc, int *numLoc)
QString writeJcondInv(HLTYPE h, Function * pProc, int *numLoc)
{
memset (buf, ' ', sizeof(buf));
buf[0] = '\0';
strcat (buf, "if ");
std::string e = walkCondExpr (h.expr(), pProc, numLoc);
strcat (buf, e.c_str());
strcat (buf, " {\n");
return (buf);
QString _form;
if(h.expr()==nullptr)
_form = "( *failed condition recovery* )";
else
_form = h.expr()->walkCondExpr (pProc, numLoc);
return QString("if %1 {\n").arg(_form);
}
string AssignType::writeOut(Function *pProc, int *numLoc)
QString AssignType::writeOut(Function *pProc, int *numLoc) const
{
ostringstream ostr;
ostr << walkCondExpr (lhs, pProc, numLoc);
ostr << " = ";
ostr << walkCondExpr (rhs, pProc, numLoc);
ostr << ";\n";
return ostr.str();
return QString("%1 = %2;\n")
.arg(m_lhs->walkCondExpr (pProc, numLoc))
.arg(m_rhs->walkCondExpr (pProc, numLoc));
}
string CallType::writeOut(Function *pProc, int *numLoc)
QString CallType::writeOut(Function *pProc, int *numLoc) const
{
ostringstream ostr;
ostr << writeCall (proc, *args, pProc,numLoc);
ostr << ";\n";
return ostr.str();
return pProc->writeCall (proc, *args, numLoc) + ";\n";
}
string ExpType::writeOut(Function *pProc, int *numLoc)
QString ExpType::writeOut(Function *pProc, int *numLoc) const
{
return walkCondExpr (v, pProc, numLoc);
if(v==nullptr)
return "";
return v->walkCondExpr (pProc, numLoc);
}
void HLTYPE::set(Expr *l, Expr *r)
{
assert(l);
assert(r);
opcode = HLI_ASSIGN;
//assert((asgn.lhs==0) and (asgn.rhs==0)); //prevent memory leaks
assert(dynamic_cast<UnaryOperator *>(l));
asgn.m_lhs=l;
asgn.m_rhs=r;
}
/* Returns a string with the contents of the current high-level icode.
* Note: this routine does not output the contens of HLI_JCOND icodes. This is
* done in a separate routine to be able to support the removal of
* empty THEN clauses on an if..then..else. */
string HLTYPE::write1HlIcode (Function * pProc, int *numLoc)
QString HLTYPE::write1HlIcode (Function * pProc, int *numLoc) const
{
string e;
ostringstream ostr;
HlTypeSupport *p = get();
const HlTypeSupport *p = get();
switch (opcode)
{
case HLI_ASSIGN:
return p->writeOut(pProc,numLoc);
case HLI_CALL:
return p->writeOut(pProc,numLoc);
case HLI_RET:
e = p->writeOut(pProc,numLoc);
if (! e.empty())
ostr << "return (" << e << ");\n";
break;
case HLI_POP:
ostr << "HLI_POP ";
ostr << p->writeOut(pProc,numLoc);
ostr << "\n";
break;
case HLI_PUSH:
ostr << "HLI_PUSH ";
ostr << p->writeOut(pProc,numLoc);
ostr << "\n";
break;
case HLI_ASSIGN:
return p->writeOut(pProc,numLoc);
case HLI_CALL:
return p->writeOut(pProc,numLoc);
case HLI_RET:
{
QString e;
e = p->writeOut(pProc,numLoc);
if (not e.isEmpty())
return QString("return (%1);\n").arg(e);
break;
}
return ostr.str();
case HLI_POP:
return QString("HLI_POP %1\n").arg(p->writeOut(pProc,numLoc));
case HLI_PUSH:
return QString("HLI_PUSH %1\n").arg(p->writeOut(pProc,numLoc));
case HLI_JCOND: //Handled elsewhere
break;
default:
qCritical() << " HLTYPE::write1HlIcode - Unhandled opcode" << opcode;
}
return "";
}
@ -601,30 +600,36 @@ void ICODE::writeDU()
{
int my_idx = loc_ip;
{
ostringstream ostr;
Machine_X86::writeRegVector(ostr,du.def);
if (!ostr.str().empty())
printf ("Def (reg) = %s\n", ostr.str().c_str());
QString ostr_contents;
{
QTextStream ostr(&ostr_contents);
Machine_X86::writeRegVector(ostr,du.def);
}
if (not ostr_contents.isEmpty())
qDebug() << QString("Def (reg) = %1\n").arg(ostr_contents);
}
{
ostringstream ostr;
Machine_X86::writeRegVector(ostr,du.use);
if (!ostr.str().empty())
printf ("Use (reg) = %s\n", ostr.str().c_str());
QString ostr_contents;
{
QTextStream ostr(&ostr_contents);
Machine_X86::writeRegVector(ostr,du.use);
}
if (not ostr_contents.isEmpty())
qDebug() << QString("Use (reg) = %1\n").arg(ostr_contents);
}
/* Print du1 chain */
printf ("# regs defined = %d\n", du1.numRegsDef);
printf ("# regs defined = %d\n", du1.getNumRegsDef());
for (int i = 0; i < MAX_REGS_DEF; i++)
{
if (not du1.used(i))
continue;
printf ("%d: du1[%d][] = ", my_idx, i);
for(auto j : du1.idx[i].uses)
{
printf ("%d ", j->loc_ip);
}
printf ("\n");
printf ("%d: du1[%d][] = ", my_idx, i);
for(auto j : du1.idx[i].uses)
{
printf ("%d ", j->loc_ip);
}
printf ("\n");
}
/* For HLI_CALL, print # parameter bytes */

25
src/hltype.cpp Normal file
View File

@ -0,0 +1,25 @@
#include "icode.h"
#include "ast.h"
void HLTYPE::replaceExpr(Expr *e)
{
assert(e);
delete exp.v;
exp.v=e;
}
HlTypeSupport *HLTYPE::get()
{
switch(opcode)
{
case HLI_ASSIGN: return &asgn;
case HLI_RET:
case HLI_POP:
case HLI_JCOND:
case HLI_PUSH: return &exp;
case HLI_CALL: return &call;
default:
return nullptr;
}
}

View File

@ -1,19 +1,16 @@
// Object oriented icode code for dcc
// (C) 1997 Mike Van Emmerik
#include "icode.h"
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include "msvc_fixes.h"
#include "dcc.h"
#include "types.h" // Common types like uint8_t, etc
#include "ast.h" // Some icode types depend on these
#include "icode.h"
#define ICODE_DELTA 25 // Amount to allocate for new chunk
#include <stdlib.h>
ICODE::TypeFilter<HIGH_LEVEL> ICODE::select_high_level;
ICODE::TypeAndValidFilter<HIGH_LEVEL> ICODE::select_valid_high_level;
ICODE::TypeFilter<HIGH_LEVEL_ICODE> ICODE::select_high_level;
ICODE::TypeAndValidFilter<HIGH_LEVEL_ICODE> ICODE::select_valid_high_level;
CIcodeRec::CIcodeRec()
{
}
@ -31,9 +28,7 @@ ICODE * CIcodeRec::addIcode(ICODE *pIcode)
void CIcodeRec::SetInBB(rCODE &rang, BB *pnewBB)
{
for(ICODE &ic : rang)
{
ic.setParent(pnewBB);
}
}
/* labelSrchRepl - Searches the icodes for instruction with label = target, and
@ -57,9 +52,9 @@ CIcodeRec::iterator CIcodeRec::labelSrch(uint32_t target)
{
return find_if(begin(),end(),[target](ICODE &l) -> bool {return l.ll()->label==target;});
}
ICODE * CIcodeRec::GetIcode(int ip)
ICODE * CIcodeRec::GetIcode(size_t ip)
{
assert(ip>=0 && ip<size());
assert(ip<size());
iICODE res=begin();
advance(res,ip);
return &(*res);
@ -92,11 +87,28 @@ void LLInst::emitGotoLabel (int indLevel)
bool LLOperand::isReg() const
{
return (regi>=rAX) && (regi<=rTMP);
return (regi>=rAX) and (regi<=rTMP);
}
void LLOperand::addProcInformation(int param_count, uint32_t call_conv)
void LLOperand::addProcInformation(int param_count, CConv::Type call_conv)
{
proc.proc->cbParam = (int16_t)param_count;
proc.cb = param_count;
proc.proc->flg |= call_conv;
proc.proc->callingConv(call_conv);
}
void HLTYPE::setCall(Function *proc)
{
opcode = HLI_CALL;
call.proc = proc;
call.args = new STKFRAME;
}
bool AssignType::removeRegFromLong(eReg regi, LOCAL_ID *locId)
{
m_lhs=lhs()->performLongRemoval(regi,locId);
return true;
}
void AssignType::lhs(Expr *l)
{
assert(dynamic_cast<UnaryOperator *>(l));
m_lhs=l;
}

View File

@ -3,8 +3,12 @@
* (C) Cristina Cifuentes
****************************************************************************/
#include <cstring>
#include <deque>
//#include <llvm/Config/llvm-config.h>
//#if( (LLVM_VERSION_MAJOR==3 ) and (LLVM_VERSION_MINOR>3) )
//#include <llvm/IR/PatternMatch.h>
//#else
//#include <llvm/Support/PatternMatch.h>
//#endif
#include "idiom.h"
#include "idiom1.h"
#include "epilogue_idioms.h"
@ -15,8 +19,11 @@
#include "shift_idioms.h"
#include "arith_idioms.h"
#include "dcc.h"
#include <llvm/Support/PatternMatch.h>
#include "msvc_fixes.h"
#include <boost/iterator/filter_iterator.hpp>
#include <cstring>
#include <deque>
/*****************************************************************************
* JmpInst - Returns true if opcode is a conditional or unconditional jump
****************************************************************************/
@ -116,13 +123,13 @@ void Function::findIdioms()
case iCALL: case iCALLF:
/* Check for library functions that return a long register.
* Propagate this result */
if (pIcode->ll()->src().proc.proc != 0)
if ((pIcode->ll()->src().proc.proc->flg & PROC_ISLIB) &&
if (pIcode->ll()->src().proc.proc != nullptr)
if ((pIcode->ll()->src().proc.proc->flg & PROC_ISLIB) and
(pIcode->ll()->src().proc.proc->flg & PROC_IS_FUNC))
{
if ((pIcode->ll()->src().proc.proc->retVal.type==TYPE_LONG_SIGN)
|| (pIcode->ll()->src().proc.proc->retVal.type == TYPE_LONG_UNSIGN))
localId.newLongReg(TYPE_LONG_SIGN, rDX, rAX, pIcode/*ip*/);
or (pIcode->ll()->src().proc.proc->retVal.type == TYPE_LONG_UNSIGN))
localId.newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(rDX,rAX), pIcode/*ip*/);
}
/* Check for idioms */
@ -204,14 +211,14 @@ void Function::findIdioms()
}
/* Check if number of parameter bytes match their calling convention */
if ((flg & PROC_HLL) && (!args.empty()))
if ((flg & PROC_HLL) and (not args.empty()))
{
args.m_minOff += (flg & PROC_FAR ? 4 : 2);
args.m_minOff += ((flg & PROC_FAR)!=0 ? 4 : 2);
delta = args.maxOff - args.m_minOff;
if (cbParam != delta)
{
cbParam = delta;
flg |= (CALL_MASK & CALL_UNKNOWN);
callingConv(CConv::eUnknown);
}
}
}
@ -231,7 +238,7 @@ void Function::bindIcodeOff()
for(ICODE &c : Icode) // TODO: use filtered here
{
LLInst *ll=c.ll();
if (ll->testFlags(I) && ll->isJmpInst())
if (ll->testFlags(I) and ll->isJmpInst())
{
iICODE loc=Icode.labelSrch(ll->src().getImm2());
if (loc!=Icode.end())
@ -251,7 +258,7 @@ void Function::bindIcodeOff()
if (ll->testFlags(I) )
{
uint32_t found;
if (! Icode.labelSrch(ll->src().getImm2(), found))
if (not Icode.labelSrch(ll->src().getImm2(), found))
ll->setFlags( NO_LABEL );
else
ll->replaceSrc(LLOperand::CreateImm2(found));

View File

@ -1,5 +1,10 @@
#include "dcc.h"
#include "arith_idioms.h"
#include "dcc.h"
#include "msvc_fixes.h"
#include <QtCore/QDebug>
using namespace std;
/*****************************************************************************
@ -25,10 +30,11 @@ bool Idiom5::match(iICODE pIcode)
int Idiom5::action()
{
COND_EXPR *rhs,*lhs,*expr;
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll());
rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
expr = COND_EXPR::boolOp (lhs, rhs, ADD);
AstIdent *rhs,*lhs;
Expr *expr;
lhs = AstIdent::Long (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll());
rhs = AstIdent::Long (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
expr = new BinaryOperator(ADD,lhs, rhs);
m_icodes[0]->setAsgn(lhs, expr);
m_icodes[1]->invalidate();
return 2;
@ -58,10 +64,12 @@ bool Idiom6::match(iICODE pIcode)
int Idiom6::action()
{
COND_EXPR *rhs,*lhs,*expr;
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll());
rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
expr = COND_EXPR::boolOp (lhs, rhs, SUB);
AstIdent *rhs,*lhs;
Expr *expr;
lhs = AstIdent::Long (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll());
rhs = AstIdent::Long (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
expr = new BinaryOperator(SUB,lhs, rhs);
m_icodes[0]->setAsgn(lhs, expr);
m_icodes[1]->invalidate();
return 2;
@ -95,77 +103,80 @@ bool Idiom18::match(iICODE picode)
for(int i=0; i<4; ++i)
m_icodes[i] =picode++;
m_idiom_type=-1;
m_is_dec = m_icodes[1]->ll()->match(iDEC);
int type = -1; /* type of variable: 1 = reg-var, 2 = local */
uint8_t regi; /* register of the MOV */
uint8_t regi; /* register of the MOV */
if(not m_icodes[0]->ll()->matchWithRegDst(iMOV) )
return false;
regi = m_icodes[0]->ll()->m_dst.regi;
if( not ( m_icodes[2]->ll()->match(iCMP,regi) and
m_icodes[3]->ll()->conditionalJump() ) )
return false;
// Simple matching finished, select apropriate matcher based on dst type
/* Get variable */
if (m_icodes[1]->ll()->dst.regi == 0) /* global variable */
if (m_icodes[1]->ll()->m_dst.regi == 0) /* global variable */
{
/* not supported yet */
type = 0;
m_idiom_type = 0;
}
else if ( m_icodes[1]->ll()->dst.isReg() ) /* register */
else if ( m_icodes[1]->ll()->m_dst.isReg() ) /* register */
{
if ((m_icodes[1]->ll()->dst.regi == rSI) && (m_func->flg & SI_REGVAR))
type = 1;
else if ((m_icodes[1]->ll()->dst.regi == rDI) && (m_func->flg & DI_REGVAR))
type = 1;
m_idiom_type = 1;
// if ((m_icodes[1]->ll()->dst.regi == rSI) and (m_func->flg & SI_REGVAR))
// m_idiom_type = 1;
// else if ((m_icodes[1]->ll()->dst.regi == rDI) and (m_func->flg & DI_REGVAR))
// m_idiom_type = 1;
}
else if (m_icodes[1]->ll()->dst.off) /* local variable */
type = 2;
else if (m_icodes[1]->ll()->m_dst.off) /* local variable */
m_idiom_type = 2;
else /* indexed */
{
type=3;
m_idiom_type=3;
/* not supported yet */
printf("Unsupported idiom18 type: indexed");
ICODE &ic(*picode);
const Function *my_proc(ic.getParent()->getParent());
qWarning() << "Unsupported idiom18 type at"<< QString::number(ic.loc_ip,16)
<< "in"<< my_proc->name <<':'<< QString::number(my_proc->procEntry,16) << "- indexed";
}
switch(type)
switch(m_idiom_type)
{
case 0: // global
printf("Unsupported idiom18 type: global variable");
break;
case 1: /* register variable */
/* Check previous instruction for a MOV */
if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src().regi == m_icodes[1]->ll()->dst.regi))
{
regi = m_icodes[0]->ll()->dst.regi;
if ( m_icodes[0]->ll()->dst.isReg() )
case 0: // global
printf("Unsupported idiom18 type at %x : global variable\n",picode->loc_ip);
break;
case 1: /* register variable */
/* Check previous instruction for a MOV */
if ( m_icodes[0]->ll()->src().regi == m_icodes[1]->ll()->m_dst.regi)
{
if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) &&
m_icodes[3]->ll()->conditionalJump() )
return true;
return true;
}
}
break;
case 2: /* local */
if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src().off == m_icodes[1]->ll()->dst.off))
{
regi = m_icodes[0]->ll()->dst.regi;
if ( m_icodes[0]->ll()->dst.isReg() )
break;
case 2: /* local */
if (m_icodes[0]->ll()->src().off == m_icodes[1]->ll()->m_dst.off)
{
if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) &&
m_icodes[3]->ll()->conditionalJump() )
return true;
return true;
}
}
break;
case 3: // indexed
printf("Unsupported idiom18 type: indexed");
break;
break;
case 3: // indexed
printf("Untested idiom18 type: indexed\n");
if ((m_icodes[0]->ll()->src() == m_icodes[1]->ll()->m_dst))
{
return true;
}
break;
}
return false;
}
int Idiom18::action() // action length
{
COND_EXPR *rhs, *lhs; /* Pointers to left and right hand side exps */
COND_EXPR *expr;
lhs = COND_EXPR::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[1], *m_icodes[1], eUSE);
lhs = COND_EXPR::unary ( m_is_dec ? POST_DEC : POST_INC, lhs);
rhs = COND_EXPR::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[1], *m_icodes[3], eUSE);
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB]);
Expr *rhs,*lhs;/* Pointers to left and right hand side exps */
Expr *expr;
lhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[1], *m_icodes[1], eUSE);
lhs = UnaryOperator::Create(m_is_dec ? POST_DEC : POST_INC, lhs);
rhs = AstIdent::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[1], *m_icodes[3], eUSE);
expr = new BinaryOperator(condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB],lhs, rhs);
m_icodes[3]->setJCond(expr);
m_icodes[0]->invalidate();
@ -188,35 +199,41 @@ bool Idiom19::match(iICODE picode)
{
if(std::distance(picode,m_end)<2)
return false;
ICODE &ic(*picode);
int type;
for(int i=0; i<2; ++i)
m_icodes[i] =picode++;
m_is_dec = m_icodes[0]->ll()->match(iDEC);
if (m_icodes[0]->ll()->dst.regi == 0) /* global variable */
if ( not m_icodes[1]->ll()->conditionalJump() )
return false;
if (m_icodes[0]->ll()->m_dst.regi == 0) /* global variable */
/* not supported yet */ ;
else if ( m_icodes[0]->ll()->dst.isReg() ) /* register */
else if ( m_icodes[0]->ll()->m_dst.isReg() ) /* register */
{
// if (((picode->ll()->dst.regi == rSI) && (pproc->flg & SI_REGVAR)) ||
// ((picode->ll()->dst.regi == rDI) && (pproc->flg & DI_REGVAR)))
if (m_icodes[1]->ll()->conditionalJump())
return true;
// if (((picode->ll()->dst.regi == rSI) and (pproc->flg & SI_REGVAR)) or
// ((picode->ll()->dst.regi == rDI) and (pproc->flg & DI_REGVAR)))
return true;
}
else if (m_icodes[0]->ll()->dst.off) /* stack variable */
else if (m_icodes[0]->ll()->m_dst.off) /* stack variable */
{
if ( m_icodes[1]->ll()->conditionalJump() )
return true;
return true;
}
else /* indexed */
/* not supported yet */ ;
{
fprintf(stderr,"idiom19 : Untested type [indexed]\n");
return true;
/* not supported yet */
}
return false;
}
int Idiom19::action()
{
COND_EXPR *lhs,*rhs,*expr;
lhs = COND_EXPR::id (*m_icodes[1]->ll(), DST, m_func, m_icodes[0], *m_icodes[1], eUSE);
lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
rhs = COND_EXPR::idKte (0, 2);
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[1]->ll()->getOpcode() - iJB]);
Expr *lhs,*expr;
lhs = AstIdent::id (*m_icodes[0]->ll(), DST, m_func, m_icodes[0], *m_icodes[1], eUSE);
lhs = UnaryOperator::Create(m_is_dec ? PRE_DEC : PRE_INC, lhs);
expr = new BinaryOperator(condOpJCond[m_icodes[1]->ll()->getOpcode() - iJB],lhs, new Constant(0, 2));
m_icodes[1]->setJCond(expr);
m_icodes[0]->invalidate();
return 2;
@ -245,10 +262,13 @@ bool Idiom20::match(iICODE picode)
return false;
for(int i=0; i<4; ++i)
m_icodes[i] =picode++;
/* Check second instruction for a MOV */
if( not m_icodes[1]->ll()->matchWithRegDst(iMOV) )
return false;
m_is_dec = m_icodes[0]->ll()->match(iDEC);
m_is_dec = m_icodes[0]->ll()->match(iDEC) ? PRE_DEC : PRE_INC;
LLOperand &ll_dest(m_icodes[0]->ll()->dst);
const LLOperand &ll_dest(m_icodes[0]->ll()->m_dst);
/* Get variable */
if (ll_dest.regi == 0) /* global variable */
{
@ -256,57 +276,56 @@ bool Idiom20::match(iICODE picode)
}
else if ( ll_dest.isReg() ) /* register */
{
if ((ll_dest.regi == rSI) && (m_func->flg & SI_REGVAR))
type = 1;
else if ((ll_dest.regi == rDI) && (m_func->flg & DI_REGVAR))
type = 1;
type = 1;
// if ((ll_dest.regi == rSI) and (m_func->flg & SI_REGVAR))
// type = 1;
// else if ((ll_dest.regi == rDI) and (m_func->flg & DI_REGVAR))
// type = 1;
}
else if (ll_dest.off) /* local variable */
type = 2;
else /* indexed */
{
printf("idiom20 : Unsupported type [indexed]\n");
printf("idiom20 : Untested type [indexed]\n");
type = 3;
/* not supported yet */ ;
}
/* Check previous instruction for a MOV */
if (type == 1) /* register variable */
regi = m_icodes[1]->ll()->m_dst.regi;
const LLOperand &mov_src(m_icodes[1]->ll()->src());
if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) and m_icodes[3]->ll()->conditionalJump())
{
if (m_icodes[1]->ll()->match(iMOV) &&
(m_icodes[1]->ll()->src().regi == ll_dest.regi))
switch(type)
{
regi = m_icodes[1]->ll()->dst.regi;
if ( m_icodes[1]->ll()->dst.isReg() )
{
if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) &&
m_icodes[3]->ll()->conditionalJump())
case 1: /* register variable */
if ((mov_src.regi == ll_dest.regi))
{
return true;
}
}
}
else if (type == 2) /* local */
{
if ( m_icodes[0]->ll()->match(iMOV) &&
(m_icodes[1]->ll()->src().off == ll_dest.off))
{
regi = m_icodes[1]->ll()->dst.regi;
if ( m_icodes[1]->ll()->dst.isReg() )
{
if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) &&
m_icodes[3]->ll()->conditionalJump())
}
break;
case 2: // local
if ((mov_src.off == ll_dest.off))
{
return true;
}
}
break;
case 3:
fprintf(stderr,"Test 3 ");
if ((mov_src == ll_dest))
{
return true;
}
break;
}
}
return false;
}
int Idiom20::action()
{
COND_EXPR *lhs,*rhs,*expr;
lhs = COND_EXPR::id (*m_icodes[1]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], eUSE);
lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
rhs = COND_EXPR::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[0], *m_icodes[3], eUSE);
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB]);
Expr *lhs,*rhs,*expr;
lhs = AstIdent::id (*m_icodes[1]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], eUSE);
lhs = UnaryOperator::Create(m_is_dec, lhs);
rhs = AstIdent::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[0], *m_icodes[3], eUSE);
expr = new BinaryOperator(condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB],lhs, rhs);
m_icodes[3]->setJCond(expr);
for(int i=0; i<3; ++i)
m_icodes[i]->invalidate();

View File

@ -1,5 +1,8 @@
#include "dcc.h"
#include "call_idioms.h"
#include "dcc.h"
#include "msvc_fixes.h"
using namespace std;
/*****************************************************************************
* idiom3 - C calling convention.
@ -22,7 +25,7 @@ bool Idiom3::match(iICODE picode)
/* Match ADD SP, immed */
for(int i=0; i<2; ++i)
m_icodes[i] = picode++;
if ( m_icodes[1]->ll()->testFlags(I) && m_icodes[1]->ll()->match(iADD,rSP))
if ( m_icodes[1]->ll()->testFlags(I) and m_icodes[1]->ll()->match(iADD,rSP))
{
m_param_count = m_icodes[1]->ll()->src().getImm2();
return true;
@ -38,7 +41,7 @@ int Idiom3::action()
{
if (m_icodes[0]->ll()->testFlags(I) )
{
m_icodes[0]->ll()->src().addProcInformation(m_param_count,CALL_C);
m_icodes[0]->ll()->src().addProcInformation(m_param_count,CConv::eCdecl);
}
else
{
@ -77,13 +80,13 @@ bool Idiom17::match(iICODE picode)
if (m_icodes[1]->ll()->match(iPOP))
{
int i=0;
regi = m_icodes[1]->ll()->dst.regi;
if ((regi >= rAX) && (regi <= rBX))
regi = m_icodes[1]->ll()->m_dst.regi;
if ((regi >= rAX) and (regi <= rBX))
i++;
while (picode != m_end && picode->ll()->match(iPOP))
while (picode != m_end and picode->ll()->match(iPOP))
{
if (picode->ll()->dst.regi != regi)
if (picode->ll()->m_dst.regi != regi)
break;
i++;
m_icodes.push_back(picode++);
@ -96,7 +99,7 @@ int Idiom17::action()
{
if (m_icodes[0]->ll()->testFlags(I))
{
m_icodes[0]->ll()->src().addProcInformation(m_param_count,CALL_C);
m_icodes[0]->ll()->src().addProcInformation(m_param_count,CConv::eCdecl);
for(size_t idx=1; idx<m_icodes.size(); ++idx)
{
m_icodes[idx]->invalidate();

View File

@ -1,6 +1,8 @@
#include "dcc.h"
#include "epilogue_idioms.h"
#include "dcc.h"
#include "msvc_fixes.h"
/*****************************************************************************
* popStkVars - checks for
* [POP DI]
@ -14,9 +16,9 @@ void EpilogIdiom::popStkVars(iICODE pIcode)
/* Match [POP DI] */
if (pIcode->ll()->match(iPOP))
{
if ((m_func->flg & DI_REGVAR) && pIcode->ll()->match(rDI))
if ((m_func->flg & DI_REGVAR) and pIcode->ll()->match(rDI))
m_icodes.push_front(pIcode);
else if ((m_func->flg & SI_REGVAR) && pIcode->ll()->match(rSI))
else if ((m_func->flg & SI_REGVAR) and pIcode->ll()->match(rSI))
m_icodes.push_front(pIcode);
}
++pIcode;
@ -25,9 +27,9 @@ void EpilogIdiom::popStkVars(iICODE pIcode)
/* Match [POP SI] */
if (pIcode->ll()->match(iPOP))
{
if ((m_func->flg & SI_REGVAR) && pIcode->ll()->match(rSI))
if ((m_func->flg & SI_REGVAR) and pIcode->ll()->match(rSI))
m_icodes.push_front(pIcode);
else if ((m_func->flg & DI_REGVAR) && pIcode->ll()->match(rDI))
else if ((m_func->flg & DI_REGVAR) and pIcode->ll()->match(rDI))
m_icodes.push_front(pIcode);
}
}
@ -46,7 +48,7 @@ bool Idiom2::match(iICODE pIcode)
iICODE nicode;
if(pIcode==m_func->Icode.begin()) // pIcode->loc_ip == 0
return false;
if ( pIcode->ll()->testFlags(I) || (not pIcode->ll()->match(rSP,rBP)) )
if ( pIcode->ll()->testFlags(I) or (not pIcode->ll()->match(rSP,rBP)) )
return false;
if(distance(pIcode,m_end)<3)
return false;
@ -55,21 +57,21 @@ bool Idiom2::match(iICODE pIcode)
m_icodes.push_back(pIcode);
/* Get next icode, skip over holes in the icode array */
nicode = ++iICODE(pIcode);
while (nicode->ll()->testFlags(NO_CODE) && (nicode != m_end))
while (nicode->ll()->testFlags(NO_CODE) and (nicode != m_end))
{
nicode++;
}
if(nicode == m_end)
return false;
if (nicode->ll()->match(iPOP,rBP) && ! (nicode->ll()->testFlags(I | TARGET | CASE)) )
if (nicode->ll()->match(iPOP,rBP) and not (nicode->ll()->testFlags(I | TARGET | CASE)) )
{
m_icodes.push_back(nicode++); // Matched POP BP
/* Match RET(F) */
if ( nicode != m_end &&
!(nicode->ll()->testFlags(I | TARGET | CASE)) &&
(nicode->ll()->match(iRET) || nicode->ll()->match(iRETF))
if ( nicode != m_end and
not (nicode->ll()->testFlags(I | TARGET | CASE)) and
(nicode->ll()->match(iRET) or nicode->ll()->match(iRETF))
)
{
m_icodes.push_back(nicode); // Matched RET
@ -118,7 +120,7 @@ bool Idiom4::match(iICODE pIcode)
{
iICODE prev1 = --iICODE(pIcode);
/* Check for POP BP */
if (prev1->ll()->match(iPOP,rBP) && not prev1->ll()->testFlags(I) )
if (prev1->ll()->match(iPOP,rBP) and not prev1->ll()->testFlags(I) )
m_icodes.push_back(prev1);
else if(prev1!=m_func->Icode.begin())
{
@ -138,7 +140,7 @@ bool Idiom4::match(iICODE pIcode)
}
int Idiom4::action()
{
if( ! m_icodes.empty()) // if not an empty RET[F] N
if( not m_icodes.empty()) // if not an empty RET[F] N
{
for(size_t idx=0; idx<m_icodes.size()-1; ++idx) // don't invalidate last entry
m_icodes[idx]->invalidate();
@ -146,7 +148,7 @@ int Idiom4::action()
if(m_param_count)
{
m_func->cbParam = (int16_t)m_param_count;
m_func->flg |= CALL_PASCAL;
m_func->callingConv(CConv::ePascal);
}
return 1;
}

View File

@ -1,8 +1,11 @@
#include "idiom1.h"
#include "dcc.h"
#include "msvc_fixes.h"
/*****************************************************************************
/* checkStkVars - Checks for PUSH SI
* checkStkVars - Checks for PUSH SI
* [PUSH DI]
* or PUSH DI
* [PUSH SI]
@ -19,14 +22,14 @@ int Idiom1::checkStkVars (iICODE pIcode)
{
si_matched = 1;
++pIcode;
if ((pIcode != m_end) && pIcode->ll()->match(iPUSH,rDI)) // Look for PUSH DI
if ((pIcode != m_end) and pIcode->ll()->match(iPUSH,rDI)) // Look for PUSH DI
di_matched = 1;
}
else if (pIcode->ll()->match(iPUSH,rDI))
{
di_matched = 1;
++pIcode;
if ((pIcode != m_end) && pIcode->ll()->match(iPUSH,rSI)) // Look for PUSH SI
if ((pIcode != m_end) and pIcode->ll()->match(iPUSH,rSI)) // Look for PUSH SI
si_matched = 1;
}
m_func->flg |= (si_matched ? SI_REGVAR : 0) | (di_matched ? DI_REGVAR : 0);
@ -60,13 +63,13 @@ bool Idiom1::match(iICODE picode)
m_icodes.clear();
m_min_off = 0;
/* PUSH BP as first instruction of procedure */
if ( (not picode->ll()->testFlags(I)) && picode->ll()->src().regi == rBP)
if ( (not picode->ll()->testFlags(I)) and picode->ll()->src().regi == rBP)
{
m_icodes.push_back( picode++ ); // insert iPUSH
if(picode==m_end)
return false;
/* MOV BP, SP as next instruction */
if ( !picode->ll()->testFlags(I | TARGET | CASE) && picode->ll()->match(iMOV ,rBP,rSP) )
if ( not picode->ll()->testFlags(I | TARGET | CASE) and picode->ll()->match(iMOV ,rBP,rSP) )
{
m_icodes.push_back( picode++ ); // insert iMOV
if(picode==m_end)
@ -75,7 +78,7 @@ bool Idiom1::match(iICODE picode)
/* Look for SUB SP, immed */
if (
picode->ll()->testFlags(I | TARGET | CASE) && picode->ll()->match(iSUB,rSP)
picode->ll()->testFlags(I | TARGET | CASE) and picode->ll()->match(iSUB,rSP)
)
{
m_icodes.push_back( picode++ ); // insert iSUB
@ -98,8 +101,8 @@ bool Idiom1::match(iICODE picode)
if(picode == m_end)
return false;
/* Look for MOV BP, SP */
if ( picode != m_end &&
!picode->ll()->testFlags(I | TARGET | CASE) &&
if ( picode != m_end and
not picode->ll()->testFlags(I | TARGET | CASE) and
picode->ll()->match(iMOV,rBP,rSP))
{
m_icodes.push_back(picode);
@ -115,11 +118,11 @@ bool Idiom1::match(iICODE picode)
else // push di [push si] / push si [push di]
{
size_t n = checkStkVars (picode);
for(int i=0; i<n; ++i)
for(size_t i=0; i<n; ++i)
m_icodes.push_back(picode++);
}
return !m_icodes.empty();
return not m_icodes.empty();
}
int Idiom1::action()
{

View File

@ -1,5 +1,8 @@
#include "dcc.h"
#include "mov_idioms.h"
#include "dcc.h"
#include "msvc_fixes.h"
using namespace std;
/*****************************************************************************
@ -27,19 +30,20 @@ bool Idiom14::match(iICODE pIcode)
return false;
m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++;
LLInst * matched [] {m_icodes[0]->ll(),m_icodes[1]->ll()};
/* Check for regL */
m_regL = m_icodes[0]->ll()->dst.regi;
if (not m_icodes[0]->ll()->testFlags(I) && ((m_regL == rAX) || (m_regL ==rBX)))
m_regL = matched[0]->m_dst.regi;
if (not matched[0]->testFlags(I) and ((m_regL == rAX) or (m_regL ==rBX)))
{
/* Check for XOR regH, regH */
if (m_icodes[1]->ll()->match(iXOR) && not m_icodes[1]->ll()->testFlags(I))
if (matched[1]->match(iXOR) and not matched[1]->testFlags(I))
{
m_regH = m_icodes[1]->ll()->dst.regi;
if (m_regH == m_icodes[1]->ll()->src().getReg2())
m_regH = matched[1]->m_dst.regi;
if (m_regH == matched[1]->src().getReg2())
{
if ((m_regL == rAX) && (m_regH == rDX))
if ((m_regL == rAX) and (m_regH == rDX))
return true;
if ((m_regL == rBX) && (m_regH == rCX))
if ((m_regL == rBX) and (m_regH == rCX))
return true;
}
}
@ -48,12 +52,11 @@ bool Idiom14::match(iICODE pIcode)
}
int Idiom14::action()
{
int idx;
COND_EXPR *lhs,*rhs;
idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, m_regH, m_regL, m_icodes[0]);
lhs = COND_EXPR::idLongIdx (idx);
int idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(m_regH,m_regL), m_icodes[0]);
AstIdent *lhs = AstIdent::LongIdx (idx);
m_icodes[0]->setRegDU( m_regH, eDEF);
rhs = COND_EXPR::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
Expr *rhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
m_icodes[0]->setAsgn(lhs, rhs);
m_icodes[1]->invalidate();
return 2;
@ -80,13 +83,13 @@ bool Idiom13::match(iICODE pIcode)
eReg regi;
/* Check for regL */
regi = m_icodes[0]->ll()->dst.regi;
if (not m_icodes[0]->ll()->testFlags(I) && (regi >= rAL) && (regi <= rBH))
regi = m_icodes[0]->ll()->m_dst.regi;
if (not m_icodes[0]->ll()->testFlags(I) and (regi >= rAL) and (regi <= rBH))
{
/* Check for MOV regH, 0 */
if (m_icodes[1]->ll()->match(iMOV,I) && (m_icodes[1]->ll()->src().getImm2() == 0))
if (m_icodes[1]->ll()->match(iMOV,I) and (m_icodes[1]->ll()->src().getImm2() == 0))
{
if (m_icodes[1]->ll()->dst.regi == (regi + 4)) //WARNING: based on distance between AH-AL,BH-BL etc.
if (m_icodes[1]->ll()->m_dst.regi == (regi + 4)) //WARNING: based on distance between AH-AL,BH-BL etc.
{
m_loaded_reg=(eReg)(regi - rAL + rAX);
return true;
@ -98,11 +101,14 @@ bool Idiom13::match(iICODE pIcode)
int Idiom13::action()
{
COND_EXPR *lhs,*rhs;
lhs = COND_EXPR::idReg (m_loaded_reg, 0, &m_func->localId);
AstIdent *lhs;
Expr *rhs;
eReg regi = m_icodes[0]->ll()->m_dst.regi;
m_icodes[0]->du1.removeDef(regi);
//m_icodes[0]->du1.numRegsDef--; /* prev uint8_t reg def */
lhs = new RegisterNode(LLOperand(m_loaded_reg, 0), &m_func->localId);
m_icodes[0]->setRegDU( m_loaded_reg, eDEF);
m_icodes[0]->du1.numRegsDef--; /* prev uint8_t reg def */
rhs = COND_EXPR::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
rhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
m_icodes[0]->setAsgn(lhs, rhs);
m_icodes[1]->invalidate();
return 2;

View File

@ -1,5 +1,8 @@
#include "dcc.h"
#include "neg_idioms.h"
#include "dcc.h"
#include "msvc_fixes.h"
using namespace std;
@ -16,14 +19,14 @@ using namespace std;
****************************************************************************/
bool Idiom11::match (iICODE picode)
{
const char *matchstring="(oNEG rH) (oNEG rL) (SBB \rH i0)";
//const char *matchstring="(oNEG rH) (oNEG rL) (SBB \rH i0)";
condId type; /* type of argument */
if(distance(picode,m_end)<3)
return false;
for(int i=0; i<3; ++i)
m_icodes[i]=picode++;
type = m_icodes[0]->ll()->idType(DST);
if(type==CONSTANT || type == OTHER)
if(type==CONSTANT or type == OTHER)
return false;
/* Check NEG reg/mem
* SBB reg/mem, 0*/
@ -31,28 +34,31 @@ bool Idiom11::match (iICODE picode)
return false;
switch (type)
{
case GLOB_VAR:
if ((m_icodes[2]->ll()->dst.segValue == m_icodes[0]->ll()->dst.segValue) &&
(m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off))
return true;
break;
case REGISTER:
if (m_icodes[2]->ll()->dst.regi == m_icodes[0]->ll()->dst.regi)
return true;
break;
case PARAM:
case LOCAL_VAR:
if (m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off)
return true;
break;
case GLOB_VAR:
if ((m_icodes[2]->ll()->m_dst.segValue == m_icodes[0]->ll()->m_dst.segValue) and
(m_icodes[2]->ll()->m_dst.off == m_icodes[0]->ll()->m_dst.off))
return true;
break;
case REGISTER:
if (m_icodes[2]->ll()->m_dst.regi == m_icodes[0]->ll()->m_dst.regi)
return true;
break;
case PARAM:
case LOCAL_VAR:
if (m_icodes[2]->ll()->m_dst.off == m_icodes[0]->ll()->m_dst.off)
return true;
break;
default:
fprintf(stderr,"Idiom11::match unhandled type %d\n",type);
}
return false;
}
int Idiom11::action()
{
COND_EXPR *lhs,*rhs;
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], HIGH_FIRST,m_icodes[0], USE_DEF, *m_icodes[1]->ll());
rhs = COND_EXPR::unary (NEGATION, lhs);
AstIdent *lhs;
Expr *rhs;
lhs = AstIdent::Long (&m_func->localId, DST, m_icodes[0], HIGH_FIRST,m_icodes[0], USE_DEF, *m_icodes[1]->ll());
rhs = UnaryOperator::Create(NEGATION, lhs);
m_icodes[0]->setAsgn(lhs, rhs);
m_icodes[1]->invalidate();
m_icodes[2]->invalidate();
@ -73,18 +79,18 @@ int Idiom11::action()
****************************************************************************/
bool Idiom16::match (iICODE picode)
{
const char *matchstring="(oNEG rR) (oSBB rR rR) (oINC rR)";
//const char *matchstring="(oNEG rR) (oSBB rR rR) (oINC rR)";
if(distance(picode,m_end)<3)
return false;
for(int i=0; i<3; ++i)
m_icodes[i]=picode++;
uint8_t regi = m_icodes[0]->ll()->dst.regi;
if ((regi >= rAX) && (regi < INDEX_BX_SI))
uint8_t regi = m_icodes[0]->ll()->m_dst.regi;
if ((regi >= rAX) and (regi < INDEX_BX_SI))
{
if (m_icodes[1]->ll()->match(iSBB) && m_icodes[2]->ll()->match(iINC))
if ((m_icodes[1]->ll()->dst.regi == (m_icodes[1]->ll()->src().getReg2())) &&
m_icodes[1]->ll()->match((eReg)regi) &&
if (m_icodes[1]->ll()->match(iSBB) and m_icodes[2]->ll()->match(iINC))
if ((m_icodes[1]->ll()->m_dst.regi == (m_icodes[1]->ll()->src().getReg2())) and
m_icodes[1]->ll()->match((eReg)regi) and
m_icodes[2]->ll()->match((eReg)regi))
return true;
}
@ -92,9 +98,10 @@ bool Idiom16::match (iICODE picode)
}
int Idiom16::action()
{
COND_EXPR *lhs,*rhs;
lhs = COND_EXPR::idReg (m_icodes[0]->ll()->dst.regi, m_icodes[0]->ll()->getFlag(),&m_func->localId);
rhs = COND_EXPR::unary (NEGATION, lhs->clone());
AstIdent *lhs;
Expr *rhs;
lhs = new RegisterNode(*m_icodes[0]->ll()->get(DST),&m_func->localId);
rhs = UnaryOperator::Create(NEGATION, lhs->clone());
m_icodes[0]->setAsgn(lhs, rhs);
m_icodes[1]->invalidate();
m_icodes[2]->invalidate();

View File

@ -1,5 +1,8 @@
#include "dcc.h"
#include "shift_idioms.h"
#include "dcc.h"
#include "msvc_fixes.h"
using namespace std;
@ -18,8 +21,8 @@ bool Idiom8::match(iICODE pIcode)
return false;
m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++;
if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1))
if ( m_icodes[1]->ll()->match(iRCR,I) &&
if (m_icodes[0]->ll()->testFlags(I) and (m_icodes[0]->ll()->src().getImm2() == 1))
if ( m_icodes[1]->ll()->match(iRCR,I) and
(m_icodes[1]->ll()->src().getImm2() == 1))
return true;
return false;
@ -28,16 +31,16 @@ bool Idiom8::match(iICODE pIcode)
int Idiom8::action()
{
int idx;
COND_EXPR *rhs,*lhs,*expr;
AstIdent *lhs;
Expr *expr;
eReg regH,regL;
regH=m_icodes[0]->ll()->dst.regi;
regL=m_icodes[1]->ll()->dst.regi;
idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, regH, regL, m_icodes[0]);
lhs = COND_EXPR::idLongIdx (idx);
regH=m_icodes[0]->ll()->m_dst.regi;
regL=m_icodes[1]->ll()->m_dst.regi;
idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(regH,regL), m_icodes[0]);
lhs = AstIdent::LongIdx (idx);
m_icodes[0]->setRegDU( regL, USE_DEF);
rhs = COND_EXPR::idKte(1,2);
expr = COND_EXPR::boolOp(lhs, rhs, SHR);
expr = new BinaryOperator(SHR,lhs, new Constant(1, 2));
m_icodes[0]->setAsgn(lhs, expr);
m_icodes[1]->invalidate();
return 2;
@ -65,7 +68,7 @@ bool Idiom15::match(iICODE pIcode)
if (not pIcode->ll()->testFlags(I) or (pIcode->ll()->src().getImm2() != 1))
return false;
m_icodes.clear();
regi = pIcode->ll()->dst.regi;
regi = pIcode->ll()->m_dst.regi;
m_icodes.push_back(pIcode++);
while( (pIcode!=m_end) and
pIcode->ll()->match(iSHL,(eReg)regi,I) and
@ -78,12 +81,12 @@ bool Idiom15::match(iICODE pIcode)
int Idiom15::action()
{
COND_EXPR *lhs,*rhs,*_exp;
lhs = COND_EXPR::idReg (m_icodes[0]->ll()->dst.regi,
m_icodes[0]->ll()->getFlag() & NO_SRC_B,
&m_func->localId);
rhs = COND_EXPR::idKte (m_icodes.size(), 2);
_exp = COND_EXPR::boolOp (lhs, rhs, SHL);
AstIdent *lhs;
Expr *rhs,*_exp;
lhs = new RegisterNode(*m_icodes[0]->ll()->get(DST), &m_func->localId);
rhs = new Constant(m_icodes.size(), 2);
_exp = new BinaryOperator(SHL,lhs, rhs);
m_icodes[0]->setAsgn(lhs, _exp);
for (size_t i=1; i<m_icodes.size()-1; ++i)
{
@ -107,8 +110,8 @@ bool Idiom12::match(iICODE pIcode)
return false;
m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++;
if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1))
if (m_icodes[1]->ll()->match(iRCL,I) && (m_icodes[1]->ll()->src().getImm2() == 1))
if (m_icodes[0]->ll()->testFlags(I) and (m_icodes[0]->ll()->src().getImm2() == 1))
if (m_icodes[1]->ll()->match(iRCL,I) and (m_icodes[1]->ll()->src().getImm2() == 1))
return true;
return false;
}
@ -116,16 +119,17 @@ bool Idiom12::match(iICODE pIcode)
int Idiom12::action()
{
int idx;
COND_EXPR *rhs,*lhs,*expr;
eReg regH,regL;
regL=m_icodes[0]->ll()->dst.regi;
regH=m_icodes[1]->ll()->dst.regi;
Expr *expr;
AstIdent *lhs;
idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN, regH, regL,m_icodes[0]);
lhs = COND_EXPR::idLongIdx (idx);
eReg regH,regL;
regL=m_icodes[0]->ll()->m_dst.regi;
regH=m_icodes[1]->ll()->m_dst.regi;
idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN, LONGID_TYPE(regH,regL),m_icodes[0]);
lhs = AstIdent::LongIdx (idx);
m_icodes[0]->setRegDU( regH, USE_DEF);
rhs = COND_EXPR::idKte (1, 2);
expr = COND_EXPR::boolOp (lhs, rhs, SHL);
expr = new BinaryOperator(SHL,lhs, new Constant(1, 2));
m_icodes[0]->setAsgn(lhs, expr);
m_icodes[1]->invalidate();
return 2;
@ -146,8 +150,8 @@ bool Idiom9::match(iICODE pIcode)
return false;
m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++;
if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1))
if (m_icodes[1]->ll()->match(iRCR,I) && (m_icodes[1]->ll()->src().getImm2() == 1))
if (m_icodes[0]->ll()->testFlags(I) and (m_icodes[0]->ll()->src().getImm2() == 1))
if (m_icodes[1]->ll()->match(iRCR,I) and (m_icodes[1]->ll()->src().getImm2() == 1))
return true;
return false;
}
@ -155,15 +159,15 @@ bool Idiom9::match(iICODE pIcode)
int Idiom9::action()
{
int idx;
COND_EXPR *rhs,*lhs,*expr;
AstIdent *lhs;
Expr *expr;
eReg regH,regL;
regL=m_icodes[1]->ll()->dst.regi;
regH=m_icodes[0]->ll()->dst.regi;
idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN,regH,regL,m_icodes[0]);
lhs = COND_EXPR::idLongIdx (idx);
regL=m_icodes[1]->ll()->m_dst.regi;
regH=m_icodes[0]->ll()->m_dst.regi;
idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN,LONGID_TYPE(regH,regL),m_icodes[0]);
lhs = AstIdent::LongIdx (idx);
m_icodes[0]->setRegDU(regL, USE_DEF);
rhs = COND_EXPR::idKte (1, 2);
expr = COND_EXPR::boolOp (lhs, rhs, SHR);
expr = new BinaryOperator(SHR,lhs, new Constant(1, 2));
m_icodes[0]->setAsgn(lhs, expr);
m_icodes[1]->invalidate();
return 2;

View File

@ -1,5 +1,8 @@
#include "dcc.h"
#include "xor_idioms.h"
#include "dcc.h"
#include "msvc_fixes.h"
using namespace std;
/*****************************************************************************
@ -26,24 +29,26 @@ bool Idiom21::match (iICODE picode)
if (not m_icodes[1]->ll()->testFlags(I))
return false;
dst = &m_icodes[0]->ll()->dst;
dst = &m_icodes[0]->ll()->m_dst;
src = &m_icodes[0]->ll()->src();
if ((dst->regi == src->getReg2()) && (dst->getReg2() > 0) && (dst->getReg2() < INDEX_BX_SI))
if ((dst->regi == src->getReg2()) and (dst->getReg2() > 0) and (dst->getReg2() < INDEX_BX_SI))
{
if ((dst->getReg2() == rDX) && m_icodes[1]->ll()->match(rAX))
if ((dst->getReg2() == rDX) and m_icodes[1]->ll()->match(rAX))
return true;
if ((dst->getReg2() == rCX) && m_icodes[1]->ll()->match(rBX))
if ((dst->getReg2() == rCX) and m_icodes[1]->ll()->match(rBX))
return true;
}
return false;
}
int Idiom21::action()
{
COND_EXPR *lhs,*rhs;
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0],HIGH_FIRST, m_icodes[0], eDEF, *m_icodes[1]->ll());
rhs = COND_EXPR::idKte (m_icodes[1]->ll()->src().getImm2() , 4);
Expr *rhs;
AstIdent *lhs;
lhs = AstIdent::Long (&m_func->localId, DST, m_icodes[0],HIGH_FIRST, m_icodes[0], eDEF, *m_icodes[1]->ll());
rhs = new Constant(m_icodes[1]->ll()->src().getImm2(), 4);
m_icodes[0]->setAsgn(lhs, rhs);
m_icodes[0]->du.use = 0; /* clear register used in iXOR */
m_icodes[0]->du.use.reset(); /* clear register used in iXOR */
m_icodes[1]->invalidate();
return 2;
}
@ -61,11 +66,11 @@ bool Idiom7::match(iICODE picode)
return false;
const LLOperand *dst, *src;
m_icode=picode;
dst = &picode->ll()->dst;
dst = &picode->ll()->m_dst;
src = &picode->ll()->src();
if (dst->regi == 0) /* global variable */
{
if ((dst->segValue == src->segValue) && (dst->off == src->off))
if ((dst->segValue == src->segValue) and (dst->off == src->off))
return true;
}
else if (dst->regi < INDEX_BX_SI) /* register */
@ -73,20 +78,19 @@ bool Idiom7::match(iICODE picode)
if (dst->regi == src->regi)
return true;
}
else if ((dst->off) && (dst->seg == rSS) && (dst->regi == INDEX_BP)) /* offset from BP */
else if ((dst->off) and (dst->seg == rSS) and (dst->regi == INDEX_BP)) /* offset from BP */
{
if ((dst->off == src->off) && (dst->seg == src->seg) && (dst->regi == src->regi))
if ((dst->off == src->off) and (dst->seg == src->seg) and (dst->regi == src->regi))
return true;
}
return false;
}
int Idiom7::action()
{
COND_EXPR *lhs,*rhs;
lhs = COND_EXPR::id (*m_icode->ll(), DST, m_func, m_icode, *m_icode, NONE);
rhs = COND_EXPR::idKte (0, 2);
m_icode->setAsgn(lhs, rhs);
m_icode->du.use = 0; /* clear register used in iXOR */
Expr *lhs;
lhs = AstIdent::id (*m_icode->ll(), DST, m_func, m_icode, *m_icode, NONE);
m_icode->setAsgn(dynamic_cast<AstIdent *>(lhs), new Constant(0, 2));
m_icode->du.use.reset(); /* clear register used in iXOR */
m_icode->ll()->setFlags(I);
return 1;
}
@ -113,9 +117,9 @@ bool Idiom10::match(iICODE pIcode)
m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++;
/* Check OR reg, reg */
if (not m_icodes[0]->ll()->testFlags(I) &&
m_icodes[0]->ll()->src().isReg() &&
(m_icodes[0]->ll()->src().getReg2() == m_icodes[0]->ll()->dst.getReg2()))
if (not m_icodes[0]->ll()->testFlags(I) and
m_icodes[0]->ll()->src().isReg() and
(m_icodes[0]->ll()->src().getReg2() == m_icodes[0]->ll()->m_dst.getReg2()))
if (m_icodes[1]->ll()->match(iJNE)) //.conditionalJump()
{
return true;
@ -127,8 +131,9 @@ int Idiom10::action()
{
m_icodes[0]->ll()->set(iCMP,I);
m_icodes[0]->ll()->replaceSrc(LLOperand::CreateImm2(0));
m_icodes[0]->du.def = 0;
m_icodes[0]->du1.numRegsDef = 0;
m_icodes[0]->du.def.reset(); //TODO: this defines FLAGS
m_icodes[0]->du1.clearAllDefs();
//m_icodes[0]->du1.numRegsDef = 0;
return 2;
}

54
src/liveness_set.cpp Normal file
View File

@ -0,0 +1,54 @@
#include "BasicBlock.h"
#include "machine_x86.h"
/* DU bit definitions for each reg value - including index registers */
LivenessSet duReg[] = { {},
//AH AL . . AX, BH
{rAH,rAL,rAX},{rCH,rCL,rCX},{rDH,rDL,rDX},{rBH,rBL,rBX},
/* uint16_t regs */
{rSP},{rBP},{rSI},{rDI},
/* seg regs */
{rES},{rCS},{rSS},{rDS},
/* uint8_t regs */
{rAL},{rCL},{rDL},{rBL},
{rAH},{rCH},{rDH},{rBH},
/* tmp reg */
{rTMP},{rTMP2},
/* index regs */
{rBX,rSI},{rBX,rDI},{rBP,rSI},{rBP,rDI},
{rSI},{rDI},{rBP},{rBX}
};
LivenessSet &LivenessSet::setReg(int r)
{
this->reset();
*this |= duReg[r];
return *this;
}
LivenessSet &LivenessSet::clrReg(int r)
{
return *this -= duReg[r];
}
LivenessSet &LivenessSet::addReg(int r)
{
*this |= duReg[r];
// postProcessCompositeRegs();
return *this;
}
bool LivenessSet::testRegAndSubregs(int r) const
{
return (*this & duReg[r]).any();
}
void LivenessSet::postProcessCompositeRegs()
{
if(testReg(rAL) and testReg(rAH))
registers.insert(rAX);
if(testReg(rCL) and testReg(rCH))
registers.insert(rCX);
if(testReg(rDL) and testReg(rDH))
registers.insert(rDX);
if(testReg(rBL) and testReg(rBH))
registers.insert(rBX);
}

View File

@ -4,33 +4,69 @@
* Date: October 1993
* (C) Cristina Cifuentes
*/
#include "locident.h"
#include "dcc.h"
#include "msvc_fixes.h"
#include <cstring>
#include "locident.h"
#include "dcc.h"
#include <QtCore/QDebug>
static const int LOCAL_ID_DELTA = 25;
static const int IDX_ARRAY_DELTA = 5;
bool LONGID_TYPE::srcDstRegMatch(iICODE a, iICODE b) const
{
return (a->ll()->src().getReg2()==l) and (b->ll()->dst.getReg2()==h);
return (a->ll()->src().getReg2()==m_l) and (b->ll()->m_dst.getReg2()==m_h);
}
ID::ID() : type(TYPE_UNKNOWN),illegal(false),loc(STK_FRAME),hasMacro(false)
{
name[0]=0;
macro[0]=0;
memset(&id,0,sizeof(id));
}
ID::ID(hlType t, frameType f) : type(t),illegal(false),hasMacro(false)
{
name[0]=0;
macro[0]=0;
memset(&id,0,sizeof(id));
loc=f;
assert(not ((t==TYPE_LONG_SIGN) or (t==TYPE_LONG_UNSIGN)));
}
ID::ID(hlType t,const LONGID_TYPE &s) : type(t),illegal(false),hasMacro(false)
{
macro[0]=0;
memset(&id,0,sizeof(id));
loc=REG_FRAME;
m_longId = s;
assert((t==TYPE_LONG_SIGN) or (t==TYPE_LONG_UNSIGN));
}
ID::ID(hlType t,const LONG_STKID_TYPE &s) : type(t),illegal(false),hasMacro(false)
{
macro[0]=0;
memset(&id,0,sizeof(id));
loc=STK_FRAME;
id.longStkId = s;
assert((t==TYPE_LONG_SIGN) or (t==TYPE_LONG_UNSIGN));
}
ID::ID(hlType t, const LONGGLB_TYPE &s) : type(t),illegal(false)
{
macro[0]=0;
memset(&id,0,sizeof(id));
loc=GLB_FRAME;
id.longGlb = s;
assert((t==TYPE_LONG_SIGN) or (t==TYPE_LONG_UNSIGN));
}
eReg ID::getPairedRegister(eReg first) const {
if (longId().h() == first)
return (longId().l());
else if (longId().l() == first)
return (longId().h());
return rUNDEF;
}
#define LOCAL_ID_DELTA 25
#define IDX_ARRAY_DELTA 5
/* Creates a new identifier node of type t and returns it.
* Arguments: locSym : local long symbol table
@ -39,8 +75,7 @@ ID::ID(hlType t, frameType f) : type(t),illegal(false),hasMacro(false)
* ix : index into icode array where this var is used */
void LOCAL_ID::newIdent(hlType t, frameType f)
{
ID newid(t,f);
id_arr.push_back(newid);
id_arr.emplace_back(t,f);
}
@ -48,19 +83,16 @@ void LOCAL_ID::newIdent(hlType t, frameType f)
* TYPE_WORD_(UN)SIGN type. Returns the index to this new entry. */
int LOCAL_ID::newByteWordReg(hlType t, eReg regi)
{
int idx;
/* Check for entry in the table */
auto found=std::find_if(id_arr.begin(),id_arr.end(),[t,regi](ID &el)->bool {
return ((el.type == t) && (el.id.regi == regi));
});
return ((el.type == t) and (el.id.regi == regi));
});
if(found!=id_arr.end())
return found-id_arr.begin();
/* Not in table, create new identifier */
newIdent (t, REG_FRAME);
idx = id_arr.size() - 1;
id_arr[idx].id.regi = regi;
return (idx);
id_arr.back().id.regi = regi;
return id_arr.size() - 1;
}
@ -72,13 +104,9 @@ int LOCAL_ID::newByteWordReg(hlType t, eReg regi)
* flagging this entry as illegal is all that can be done. */
void LOCAL_ID::flagByteWordId (int off)
{
int idx;
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off](ID &en)->bool {
//if (((en.type == TYPE_WORD_SIGN) || (en.type == TYPE_BYTE_SIGN)) &&
if ((en.typeBitsize()<=16) &&
(en.id.bwId.off == off) && (en.id.bwId.regOff == 0))
return true;
return false;
//if (((en.type == TYPE_WORD_SIGN) or (en.type == TYPE_BYTE_SIGN)) and
return ((en.typeBitsize()<=16) and (en.id.bwId.off == off) and (en.id.bwId.regOff == 0));
});
if(found==id_arr.end())
{
@ -92,23 +120,21 @@ void LOCAL_ID::flagByteWordId (int off)
* TYPE_WORD_(UN)SIGN type. Returns the index to this new entry. */
int LOCAL_ID::newByteWordStk(hlType t, int off, uint8_t regOff)
{
int idx;
/* Check for entry in the table */
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off,regOff](ID &el)->bool {
if ((el.id.bwId.off == off) && (el.id.bwId.regOff == regOff))
return true;
return false;
});
if ((el.id.bwId.off == off) and (el.id.bwId.regOff == regOff))
return true;
return false;
});
if(found!=id_arr.end())
return found-id_arr.begin(); //return Index to found element
/* Not in table, create new identifier */
newIdent (t, STK_FRAME);
idx = id_arr.size() - 1;
id_arr[idx].id.bwId.regOff = regOff;
id_arr[idx].id.bwId.off = off;
return (idx);
ID &last_id(id_arr.back());
last_id.id.bwId.regOff = regOff;
last_id.id.bwId.off = off;
return id_arr.size()-1;
}
@ -121,71 +147,68 @@ int LOCAL_ID::newByteWordStk(hlType t, int off, uint8_t regOff)
* regi: indexed register into global variable
* ix: index into icode array
* t: HIGH_LEVEL type */
int LOCAL_ID::newIntIdx(int16_t seg, int16_t off, eReg regi, int ix, hlType t)
int LOCAL_ID::newIntIdx(int16_t seg, int16_t off, eReg regi, hlType t)
{
int idx;
/* Check for entry in the table */
for (idx = 0; idx < id_arr.size(); idx++)
for (size_t idx = 0; idx < id_arr.size(); idx++)
{
if (/*(locSym->id[idx].type == t) && Not checking type */
(id_arr[idx].id.bwGlb.seg == seg) &&
(id_arr[idx].id.bwGlb.off == off) &&
(id_arr[idx].id.bwGlb.regi == regi))
if (/*(locSym->id[idx].type == t) and Not checking type */
(id_arr[idx].id.bwGlb.seg == seg) and
(id_arr[idx].id.bwGlb.off == off) and
(id_arr[idx].id.bwGlb.regi == regi))
return (idx);
}
/* Not in the table, create new identifier */
newIdent (t, GLB_FRAME);
idx = id_arr.size() - 1;
id_arr[idx].id.bwGlb.seg = seg;
id_arr[idx].id.bwGlb.off = off;
id_arr[idx].id.bwGlb.regi = regi;
return (idx);
id_arr.back().id.bwGlb.seg = seg;
id_arr.back().id.bwGlb.off = off;
id_arr.back().id.bwGlb.regi = regi;
return id_arr.size() - 1;
}
/* Checks if the entry exists in the locSym, if so, returns the idx to this
* entry; otherwise creates a new register identifier node of type
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
int LOCAL_ID::newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_)
int LOCAL_ID::newLongReg(hlType t, const LONGID_TYPE &longT, iICODE ix_)
{
eReg regH,regL;
regL = longT.l();
regH = longT.h();
size_t idx;
//iICODE ix_;
/* Check for entry in the table */
for (idx = 0; idx < id_arr.size(); idx++)
{
ID &entry(id_arr[idx]);
if (/*(locSym->id[idx].type == t) && Not checking type */
(entry.id.longId.h == regH) &&
(entry.id.longId.l == regL))
if(not entry.isLongRegisterPair())
continue;
if (/*(locSym->id[idx].type == t) and Not checking type */
(entry.longId().h() == regH) and
(entry.longId().l() == regL))
{
/* Check for occurrence in the list */
if (entry.idx.inList(ix_))
return (idx);
return idx;
else
{
/* Insert icode index in list */
entry.idx.push_back(ix_);
//entry.idx.insert(ix_);
return (idx);
return idx;
}
}
}
/* Not in the table, create new identifier */
newIdent (t, REG_FRAME);
id_arr[id_arr.size()-1].idx.push_back(ix_);//insert(ix_);
idx = id_arr.size() - 1;
id_arr[idx].id.longId.h = regH;
id_arr[idx].id.longId.l = regL;
return (idx);
id_arr.emplace_back(t, LONGID_TYPE(regH,regL));
id_arr.back().idx.push_back(ix_);
return (id_arr.size() - 1);
}
/* Returns an identifier conditional expression node of type TYPE_LONG or
* TYPE_WORD_SIGN */
COND_EXPR * LOCAL_ID::createId(const ID *retVal, iICODE ix_)
/** \returns an identifier conditional expression node of type TYPE_LONG or TYPE_WORD_SIGN */
AstIdent * LOCAL_ID::createId(const ID *retVal, iICODE ix_)
{
return COND_EXPR::idID(retVal,this,ix_);
return AstIdent::idID(retVal,this,ix_);
}
/* Checks if the entry exists in the locSym, if so, returns the idx to this
@ -198,20 +221,17 @@ int LOCAL_ID::newLongGlb(int16_t seg, int16_t offH, int16_t offL,hlType t)
/* Check for entry in the table */
for (idx = 0; idx < id_arr.size(); idx++)
{
if (/*(locSym->id[idx].type == t) && Not checking type */
(id_arr[idx].id.longGlb.seg == seg) &&
(id_arr[idx].id.longGlb.offH == offH) &&
(id_arr[idx].id.longGlb.offL == offL))
if (/*(locSym->id[idx].type == t) and Not checking type */
(id_arr[idx].id.longGlb.seg == seg) and
(id_arr[idx].id.longGlb.offH == offH) and
(id_arr[idx].id.longGlb.offL == offL))
return (idx);
}
printf("%d",t);
/* Not in the table, create new identifier */
newIdent (t, GLB_FRAME);
idx = id_arr.size() - 1;
id_arr[idx].id.longGlb.seg = seg;
id_arr[idx].id.longGlb.offH = offH;
id_arr[idx].id.longGlb.offL = offL;
return (idx);
id_arr.emplace_back(t, LONGGLB_TYPE(seg,offH,offL));
return id_arr.size() - 1;
}
@ -220,27 +240,20 @@ int LOCAL_ID::newLongGlb(int16_t seg, int16_t offH, int16_t offL,hlType t)
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
int LOCAL_ID::newLongIdx( int16_t seg, int16_t offH, int16_t offL,uint8_t regi, hlType t)
{
size_t idx;
/* Check for entry in the table */
for (idx = 0; idx < id_arr.size(); idx++)
for (size_t idx = 0; idx < id_arr.size(); idx++)
{
if (/*(locSym->id[idx].type == t) && Not checking type */
(id_arr[idx].id.longGlb.seg == seg) &&
(id_arr[idx].id.longGlb.offH == offH) &&
(id_arr[idx].id.longGlb.offL == offL) &&
(id_arr[idx].id.longGlb.regi == regi))
if (/*(locSym->id[idx].type == t) and Not checking type */
(id_arr[idx].id.longGlb.seg == seg) and
(id_arr[idx].id.longGlb.offH == offH) and
(id_arr[idx].id.longGlb.offL == offL) and
(id_arr[idx].id.longGlb.regi == regi))
return (idx);
}
/* Not in the table, create new identifier */
newIdent (t, GLB_FRAME);
idx = id_arr.size() - 1;
id_arr[idx].id.longGlb.seg = seg;
id_arr[idx].id.longGlb.offH = offH;
id_arr[idx].id.longGlb.offL = offL;
id_arr[idx].id.longGlb.regi = regi;
return (idx);
id_arr.emplace_back(t,LONGGLB_TYPE(seg,offH,offL,regi));
return id_arr.size() - 1;
}
@ -253,9 +266,11 @@ int LOCAL_ID::newLongStk(hlType t, int offH, int offL)
/* Check for entry in the table */
for (idx = 0; idx < id_arr.size(); idx++)
{
if ((id_arr[idx].type == t) &&
(id_arr[idx].id.longStkId.offH == offH) &&
(id_arr[idx].id.longStkId.offL == offL))
if(id_arr[idx].loc!=STK_FRAME)
continue;
if ((id_arr[idx].type == t) and
(id_arr[idx].longStkId().offH == offH) and
(id_arr[idx].longStkId().offL == offL))
return (idx);
}
@ -264,11 +279,8 @@ int LOCAL_ID::newLongStk(hlType t, int offH, int offL)
flagByteWordId (offL);
/* Create new identifier */
newIdent (t, STK_FRAME);
idx = id_arr.size() - 1;
id_arr[idx].id.longStkId.offH = offH;
id_arr[idx].id.longStkId.offL = offL;
return (idx);
id_arr.emplace_back(t,LONG_STKID_TYPE(offH,offL));
return (id_arr.size() - 1);
}
@ -277,9 +289,9 @@ int LOCAL_ID::newLongStk(hlType t, int offH, int offL)
* number in an expression record. */
int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, LLInst &atOffset)
{
size_t idx;
size_t idx = ~0; //WARNING: clients of this method might propagate this bogus value!
const LLOperand *pmH, *pmL;
LLInst &p_ll(*pIcode->ll());
LLInst &p_ll(*pIcode->ll());
if (f == LOW_FIRST)
{
pmL = p_ll.get(sd);
@ -296,7 +308,7 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
else if (pmL->regi < INDEX_BX_SI) /* register */
{
idx = newLongReg(TYPE_LONG_SIGN, pmH->regi, pmL->regi, ix);
idx = newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(pmH->regi, pmL->regi), ix);
if (f == HIGH_FIRST)
pIcode->setRegDU( pmL->regi, du); /* low part */
else
@ -304,9 +316,9 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
}
else if (pmL->off) { /* offset */
if ((pmL->seg == rSS) && (pmL->regi == INDEX_BP)) /* idx on bp */
if ((pmL->seg == rSS) and (pmL->regi == INDEX_BP)) /* idx on bp */
idx = newLongStk(TYPE_LONG_SIGN, pmH->off, pmL->off);
else if ((pmL->seg == rDS) && (pmL->regi == INDEX_BX)) /* bx */
else if ((pmL->seg == rDS) and (pmL->regi == INDEX_BX)) /* bx */
{ /* glb var indexed on bx */
printf("Bx indexed global, BX is an unused parameter to newLongIdx\n");
idx = newLongIdx(pmH->segValue, pmH->off, pmL->off,rBX,TYPE_LONG_SIGN);
@ -316,10 +328,10 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
printf ("long not supported, idx <> bp\n");
}
else /* (pm->regi >= INDEXBASE && pm->off = 0) => indexed && no off */
printf ("long not supported, idx && no off\n");
else /* (pm->regi >= INDEXBASE and pm->off = 0) => indexed and no off */
printf ("long not supported, idx and no off\n");
return (idx);
return idx;
}
@ -332,30 +344,46 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
* idx : idx into icode array
* pProc : ptr to current procedure record
* rhs, lhs : return expressions if successful. */
boolT checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc, Assignment &asgn, LLInst &atOffset)
bool checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc, Assignment &asgn, LLInst &atOffset)
{
/* pointers to LOW_LEVEL icodes */
const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc;
pmHdst = &pIcode->ll()->dst;
pmLdst = &atOffset.dst;
pmHdst = &pIcode->ll()->m_dst;
pmLdst = &atOffset.m_dst;
pmHsrc = &pIcode->ll()->src();
pmLsrc = &atOffset.src();
// if ((longId.offH == pmHsrc->off) and (longId.offL == pmLsrc->off))
// {
// asgn.lhs = AstIdent::LongIdx (i);
if ((longId.offH == pmHdst->off) && (longId.offL == pmLdst->off))
// if ( not pIcode->ll()->testFlags(NO_SRC) )
// {
// asgn.rhs = AstIdent::Long (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
// }
// return true;
// }
// else if ((longId.offH == pmHdst->off) and (longId.offL == pmLdst->off))
// {
// asgn.lhs = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset);
// asgn.rhs = AstIdent::LongIdx (i);
// return true;
// }
if ((longId.offH == pmHdst->off) and (longId.offL == pmLdst->off))
{
asgn.lhs = COND_EXPR::idLongIdx (i);
asgn.lhs = AstIdent::LongIdx (i);
if ( not pIcode->ll()->testFlags(NO_SRC) )
{
asgn.rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
asgn.rhs = AstIdent::Long (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
}
return true;
}
else if ((longId.offH == pmHsrc->off) && (longId.offL == pmLsrc->off))
else if ((longId.offH == pmHsrc->off) and (longId.offL == pmLsrc->off))
{
asgn.lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset);
asgn.rhs = COND_EXPR::idLongIdx (i);
asgn.lhs = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset);
asgn.rhs = AstIdent::LongIdx (i);
return true;
}
return false;
@ -371,54 +399,48 @@ boolT checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pPro
* idx : idx into icode array
* pProc : ptr to current procedure record
* rhs, lhs : return expressions if successful. */
boolT checkLongRegEq (LONGID_TYPE longId, iICODE pIcode, int i,
Function * pProc, Assignment &asgn, LLInst &atOffset)
bool checkLongRegEq (LONGID_TYPE longId, iICODE pIcode, int i,
Function * pProc, Assignment &asgn, LLInst &atOffset)
{
/* pointers to LOW_LEVEL icodes */
const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc;
pmHdst = &pIcode->ll()->dst;
pmLdst = &atOffset.dst;
pmHdst = &pIcode->ll()->m_dst;
pmLdst = &atOffset.m_dst;
pmHsrc = &pIcode->ll()->src();
pmLsrc = &atOffset.src();
if ((longId.h == pmHdst->regi) && (longId.l == pmLdst->regi))
if ((longId.h() == pmHdst->regi) and (longId.l() == pmLdst->regi))
{
asgn.lhs = COND_EXPR::idLongIdx (i);
asgn.lhs = AstIdent::LongIdx (i);
if ( not pIcode->ll()->testFlags(NO_SRC) )
{
asgn.rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
asgn.rhs = AstIdent::Long (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
}
return true;
}
else if ((longId.h == pmHsrc->regi) && (longId.l == pmLsrc->regi))
else if ((longId.h() == pmHsrc->regi) and (longId.l() == pmLsrc->regi))
{
asgn.lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode, eDEF, atOffset);
asgn.rhs = COND_EXPR::idLongIdx (i);
asgn.lhs = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode, eDEF, atOffset);
asgn.rhs = AstIdent::LongIdx (i);
return true;
}
return false;
}
/* Given an index into the local identifier table for a long register
* variable, determines whether regi is the high or low part, and returns
* the other part */
eReg otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
eReg LOCAL_ID::getPairedRegisterAt(int idx,eReg regi) const
{
ID *id;
id = &locTbl->id_arr[idx];
if ((id->loc == REG_FRAME) && ((id->type == TYPE_LONG_SIGN) ||
(id->type == TYPE_LONG_UNSIGN)))
eReg res=rUNDEF; // Cristina: please check this!
const ID *id = &id_arr[idx];
if (id->isLongRegisterPair())
{
if (id->id.longId.h == regi)
return (id->id.longId.l);
else if (id->id.longId.l == regi)
return (id->id.longId.h);
res = id->getPairedRegister(regi);
}
return rUNDEF; // Cristina: please check this!
qWarning() << "Cannot find paired register";
return res;
}
@ -426,7 +448,7 @@ eReg otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
* the local identifier table. If so, macros for these registers are
* placed in the local identifier table, as these registers belong to a
* long register identifier. */
void LOCAL_ID::propLongId (uint8_t regL, uint8_t regH, const char *name)
void LOCAL_ID::propLongId (uint8_t regL, uint8_t regH, const QString &name)
{
for (ID &rid : id_arr)
{
@ -441,9 +463,9 @@ void LOCAL_ID::propLongId (uint8_t regL, uint8_t regH, const char *name)
if (rid.id.regi == regL)
{
strcpy (rid.macro, "LO");
}
}
else // if (rid.id.regi == regH)
{
{
strcpy (rid.macro, "HI");
}
}

View File

@ -1,14 +1,20 @@
#include <cassert>
#include "machine_x86.h"
#include "msvc_fixes.h"
#include "icode.h"
#include <QtCore/QTextStream>
#include <cassert>
// Index registers **** temp solution
static const std::string regNames[] = {
static const QString regNames[] = {
"undef",
"ax", "cx", "dx", "bx",
"sp", "bp", "si", "di",
"es", "cs", "ss", "ds",
"al", "cl", "dl", "bl",
"ah", "ch", "dh", "bh",
"tmp",
"tmp","tmp2",
"bx+si", "bx+di", "bp+si", "bp+di",
"si", "di", "bp", "bx"
};
@ -16,17 +22,17 @@ static const std::string regNames[] = {
/* uint8_t and uint16_t registers */
Machine_X86::Machine_X86()
{
static_assert((sizeof(regNames)/sizeof(std::string))==LAST_REG,
"Reg count not equal number of strings");
static_assert((sizeof(regNames)/sizeof(QString))==LAST_REG,
"Reg count not equal number of strings");
}
const std::string &Machine_X86::regName(eReg r)
const QString &Machine_X86::regName(eReg r)
{
assert(r<(sizeof(regNames)/sizeof(std::string)));
assert(r<(sizeof(regNames)/sizeof(QString)));
return regNames[r];
}
static const std::string szOps[] =
static const QString szOps[] =
{
"CBW", "AAA", "AAD", "AAM", "AAS", "ADC", "ADD", "AND",
"BOUND","CALL", "CALL", "CLC", "CLD", "CLI", "CMC", "CMP",
@ -44,7 +50,7 @@ static const std::string szOps[] =
"XLAT", "XOR", "INTO", "NOP", "REPNE", "REPE", "MOD"
};
/* The following opcodes are for mod != 3 */
static std::string szFlops1[] =
static const QString szFlops1[] =
{
/* 0 1 2 3 4 5 6 7 */
"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */
@ -57,7 +63,7 @@ static std::string szFlops1[] =
"FILD", "???", "FIST", "FISTP", "FBLD", "???", "FBSTP", "FISTP" /* 38 */
};
/* The following opcodes are for mod == 3 */
static std::string szFlops2[] =
static const QString szFlops2[] =
{
/* 0 1 2 3 4 5 6 7 */
"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */
@ -70,17 +76,17 @@ static std::string szFlops2[] =
"FILD", "???", "FIST", "FISTP", "", "???", "FBSTP", "FISTP" /* 38 */
};
const std::string &Machine_X86::opcodeName(unsigned r)
const QString &Machine_X86::opcodeName(unsigned r)
{
assert(r<(sizeof(szOps)/sizeof(std::string)));
assert(r<(sizeof(szOps)/sizeof(QString)));
return szOps[r];
}
const std::string &Machine_X86::floatOpName(unsigned r)
const QString &Machine_X86::floatOpName(unsigned r)
{
if(r>=(sizeof(szFlops1)/sizeof(std::string)))
if(r>=(sizeof(szFlops1)/sizeof(QString)))
{
r-= (sizeof(szFlops1)/sizeof(std::string));
assert(r<(sizeof(szFlops2)/sizeof(std::string)));
r-= (sizeof(szFlops1)/sizeof(QString));
assert(r<(sizeof(szFlops2)/sizeof(QString)));
return szFlops2[r];
}
return szFlops1[r];
@ -88,11 +94,11 @@ const std::string &Machine_X86::floatOpName(unsigned r)
bool Machine_X86::physicalReg(eReg r)
{
return (r>=rAX) && (r<rTMP);
return (r>=rAX) and (r<rTMP);
}
bool Machine_X86::isMemOff(eReg r)
{
return r == 0 || r >= INDEX_BX_SI;
return r == 0 or r >= INDEX_BX_SI;
}
//TODO: Move these to Machine_X86
eReg Machine_X86::subRegH(eReg reg)
@ -105,7 +111,39 @@ eReg Machine_X86::subRegL(eReg reg)
}
bool Machine_X86::isSubRegisterOf(eReg reg,eReg parent)
{
if ((parent < rAX) || (parent > rBX))
if ((parent < rAX) or (parent > rBX))
return false; // only AX -> BX are coverede by subregisters
return ((reg==subRegH(parent)) || (reg == subRegL(parent)));
return ((reg==subRegH(parent)) or (reg == subRegL(parent)));
}
bool Machine_X86::hasSubregisters(eReg reg)
{
return ((reg >= rAX) and (reg <= rBX));
}
bool Machine_X86::isPartOfComposite(eReg reg)
{
return ((reg >= rAL) and (reg <= rBH));
}
eReg Machine_X86::compositeParent(eReg reg)
{
switch(reg)
{
case rAL: case rAH: return rAX;
case rCL: case rCH: return rCX;
case rDL: case rDH: return rDX;
case rBL: case rBH: return rBX;
default:
return rUNDEF;
}
return rUNDEF;
}
void Machine_X86::writeRegVector (QTextStream &ostr,const LivenessSet &regi)
{
int j;
for (j = rAX; j < INDEX_BX_SI; j++)
{
if (regi.testReg(j))
ostr << regName(eReg(j))<<" ";
}
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More