93 Commits

Author SHA1 Message Date
nemerle
3905c4e281 Re-activate unit testing and starting work on proper memory segmentation support
Use Qt testing framework.

Reorganize source file references in CMakeLists.txt

Add simplistic Address header and type ( typedef for now )
2016-05-20 15:44:37 +02:00
nemerle
171abc0415 Remove unused variables. 2016-05-20 10:24:28 +02:00
nemerle
126e206b08 Constify parsehdr error/warning reporting function arguments. 2016-05-20 10:24:01 +02:00
nemerle
7f1a4e26bd Fix struct/class confusion for Function class. 2016-05-20 10:23:00 +02:00
nemerle
8875371cee Merge remote-tracking branch 'origin' into experimental_command_streams 2016-05-20 10:20:51 +02:00
nemerle
3af6f8f5c3 Merge branch 'qt5' into experimental_command_streams 2016-05-20 10:16:59 +02: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 d5985b4b97)
2016-05-19 19:52:48 +02:00
nemerle
d5985b4b97 Add parsehdr to the build
As requested in #22
2016-05-19 19:50:47 +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
5f68987001 Merge branch 'qt5' into experimental_command_streams 2016-05-19 15:57:52 +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
14ceb301c1 WIP - do not use. 2016-05-19 10:18:17 +02:00
nemerle
bc654cbf76 Fix: bad loader instancfe created for COM files 2016-05-10 14:48:46 +02:00
nemerle
9c6dfd676e Move JMP processing from Function class
Add MarkAsSwitchCase command
2016-05-10 14:02:26 +02:00
nemerle
ae27258e3c Move XCHG and DIV rewriters from Function class
Preliminary work for #19
2016-05-10 13:07:05 +02:00
nemerle
41e9faec0e Start moving parser functionality from Function class.
Add state switching operation to Function interface
2016-05-10 12:36:31 +02:00
nemerle
6f7bfbddf8 Fix: initialize initial state for start proc if no main was found 2016-05-10 10:46:23 +02:00
nemerle
db39014e1b A few more skeleton things for planner 2016-05-09 16:05:15 +02:00
nemerle
3376818a17 fix previous commit
Support simple character deletion operations in StructuredTextTarget.h
to support opcode suffix modification.
2016-05-09 11:53:03 +02:00
nemerle
72ca6bbb70 disassembler: more instructions output into structuredtext 2016-05-09 11:35:30 +02:00
nemerle
888de8d35e More tabs replaced with spaces 2016-05-06 15:57:15 +02:00
nemerle
59c199837c Replace some tabs with spaces 2016-05-06 15:04:45 +02:00
nemerle
152625d67d Extend responsibilities of FunctionViewWidget
Reduced IDcc interface functionality.

Fix a few bugs/warnings discovered by coverity.

Emit functionUpdate signal from project when function object internal
fields change.
2016-05-06 14:40:33 +02:00
nemerle
292e4041e1 Initialize some class attributes. 2016-05-06 00:26:52 +02:00
nemerle
36d95946b3 Show JMP targets 2016-05-05 23:55:39 +02:00
nemerle
4cc3b41e64 Use QTextDocument instead of html to build text display
Continued work on rendering disassembly level text.
2016-05-05 16:06:06 +02:00
nemerle
6ade935e37 Function's command queue implemented, flow control scanning starts to
work.
2016-05-05 14:28:25 +02:00
nemerle
c8fd3a01df Add AutomatedPlanner skeleton class 2016-05-04 14:22:28 +02:00
nemerle
29353111ac A few missing returns 2016-05-04 09:54:38 +02:00
nemerle
4dc321650f Add skeletal functions for ICODE -> StructuredText 2016-05-04 00:57:59 +02:00
nemerle
0521206de5 WIP: More GUI work, use shared_ptr to store Function references. 2016-05-03 13:59:14 +02:00
nemerle
60a4fefe95 Fix command queue stepping.
Also add instanceDescription to Command class to allow for more verbose command information reporting
2016-05-01 18:45:22 +02:00
nemerle
0391f67109 Per-Function flag to prevent decompilation/disassembly
For now it just sets PROC_ISLIB flag
2016-05-01 18:42:28 +02:00
nemerle
d22624a99b Missing include 2016-05-01 14:55:06 +02:00
nemerle
95acbaa7fa GUI work. 2016-04-29 15:51:02 +02:00
nemerle
2452984864 Convert more of Frontend processing to command lists. 2016-04-29 12:23:12 +02:00
nemerle
4682bda8d8 if CFG is missing Project::createFunction should create one 2016-04-29 12:22:42 +02:00
nemerle
4a6d97c1b1 Prepare CMakeLists for UI work 2016-04-29 12:21:33 +02:00
nemerle
3d5a907b30 Move Function closer to LLVM interface ( FunctionType etc. )
A few more places are using Commands.
2016-04-28 16:25:58 +02:00
nemerle
0684062130 Fix full_regression.sh mkdir 2016-04-28 13:13:35 +02:00
nemerle
62d8633113 Implementation 2016-04-26 16:18:23 +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
bb007ddefc

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
159 changed files with 16534 additions and 4322 deletions

6
.gitattributes vendored Normal file
View File

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

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 */
};

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

File diff suppressed because it is too large Load Diff

View File

@@ -317,6 +317,9 @@ struct x86_op_t{
case op_offset: case op_offset:
return data.offset; return data.offset;
case op_relative_far: case op_relative_far:
if (data.relative_far & 0x8000)
return (data.relative_far & 0xFFFF) | 0xFFFF0000;
else
return (int32_t)data.relative_far; return (int32_t)data.relative_far;
default: default:
assert(false); assert(false);
@@ -623,7 +626,7 @@ public:
/* the instruction proper */ /* the instruction proper */
enum x86_insn_prefix prefix; /* prefixes ORed together */ enum x86_insn_prefix prefix; /* prefixes ORed together */
char prefix_string[MAX_PREFIX_STR]; /* prefixes [might be truncated] */ char prefix_string[MAX_PREFIX_STR]; /* prefixes [might be truncated] */
char mnemonic[MAX_MNEM_STR]; char mnemonic[MAX_MNEM_STR+1];
x86_oplist_t *operands; /* list of explicit/implicit operands */ x86_oplist_t *operands; /* list of explicit/implicit operands */
size_t operand_count; /* total number of operands */ size_t operand_count; /* total number of operands */
size_t explicit_count; /* number of explicit operands */ size_t explicit_count; /* number of explicit operands */

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

@@ -1,128 +1,46 @@
PROJECT(dcc_original) PROJECT(dcc_original)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8) cmake_minimum_required(VERSION 3.1)
OPTION(dcc_build_tests "Enable unit tests." OFF)
#SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}) #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) ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS)
IF(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)") IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D_CRT_NONSTDC_NO_DEPRECATE) ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D_CRT_NONSTDC_NO_DEPRECATE -DNOMINMAX)
ADD_DEFINITIONS(/W4) ADD_DEFINITIONS(/W4)
ELSE() ELSE()
#-D_GLIBCXX_DEBUG #-D_GLIBCXX_DEBUG
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall --std=c++0x") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} " ) #--coverage SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} " ) #--coverage
ENDIF() ENDIF()
SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts;${CMAKE_MODULE_PATH}) SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts;${CMAKE_MODULE_PATH})
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
include(cotire)
FIND_PACKAGE(LLVM) set(CMAKE_INCLUDE_CURRENT_DIR ON)
FIND_PACKAGE(Boost) set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
find_package(Qt5Core)
find_package(Qt5Widgets)
find_package(Boost)
OPTION(dcc_build_tests "Enable unit tests." OFF)
IF(dcc_build_tests) IF(dcc_build_tests)
enable_testing() enable_testing()
FIND_PACKAGE(GMock) find_package(Qt5Test)
#FIND_PACKAGE(GMock)
ENDIF() ENDIF()
ADD_SUBDIRECTORY(3rd_party)
llvm_map_components_to_libraries(REQ_LLVM_LIBRARIES jit native mc support tablegen)
INCLUDE_DIRECTORIES( INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}
3rd_party/libdisasm 3rd_party/libdisasm
include include
include/idioms include/idioms
common
${Boost_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
${LLVM_INCLUDE_DIRS}
) )
set(dcc_LIB_SOURCES
src/ast.cpp
src/backend.cpp
src/bundle.cpp
src/chklib.cpp
src/comwrite.cpp
src/control.cpp
src/dataflow.cpp
src/disassem.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
src/idioms/call_idioms.cpp
src/idioms/epilogue_idioms.cpp
src/idioms/mov_idioms.cpp
src/idioms/neg_idioms.cpp
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
src/proplong.cpp
src/reducible.cpp
src/scanner.cpp
src/symtab.cpp
src/udm.cpp
src/BasicBlock.cpp
src/CallConvention.cpp
)
set(dcc_SOURCES
src/dcc.cpp
)
set(dcc_HEADERS
include/ast.h
include/bundle.h
include/BinaryImage.h
include/dcc.h
include/disassem.h
include/dosdcc.h
include/error.h
include/graph.h
include/hlicode.h
include/machine_x86.h
include/icode.h
include/idioms/idiom.h
include/idioms/idiom1.h
include/idioms/arith_idioms.h
include/idioms/call_idioms.h
include/idioms/epilogue_idioms.h
include/idioms/mov_idioms.h
include/idioms/neg_idioms.h
include/idioms/shift_idioms.h
include/idioms/xor_idioms.h
include/locident.h
include/perfhlib.h
include/project.h
include/scanner.h
include/state.h
include/symtab.h
include/types.h
include/Procedure.h
include/StackFrame.h
include/BasicBlock.h
include/CallConvention.h
) ADD_SUBDIRECTORY(3rd_party)
SOURCE_GROUP(Source FILES ${dcc_SOURCES}) ADD_SUBDIRECTORY(common)
SOURCE_GROUP(Headers FILES ${dcc_HEADERS}) ADD_SUBDIRECTORY(tools)
ADD_LIBRARY(dcc_lib STATIC ${dcc_LIB_SOURCES} ${dcc_HEADERS})
#cotire(dcc_lib)
ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS})
ADD_DEPENDENCIES(dcc_original dcc_lib)
TARGET_LINK_LIBRARIES(dcc_original LLVMSupport dcc_lib disasm_s ${REQ_LLVM_LIBRARIES} LLVMSupport)
if(dcc_build_tests)
ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(src)
endif()

View File

@@ -0,0 +1,21 @@
MACRO(ADD_UNIT_TEST name)
IF(NOT ${name}_TEST_VISITED)
# add the loader as a dll
ADD_EXECUTABLE(${name} ${ARGN})
qt5_use_modules(${name} Core)
MESSAGE(WARNING "Adding test " ${name} " " ${ARGN})
TARGET_LINK_LIBRARIES(${name} ${UNIT_TEST_LIBS})
ADD_TEST(NAME ${name} COMMAND ${name})
set_property(TEST ${name} APPEND PROPERTY ENVIRONMENT DCC_TEST_BASE=${PROJECT_SOURCE_DIR})
SET(${name}_TEST_VISITED true)
ENDIF()
ENDMACRO()
function(ADD_QTEST NAME)
add_executable(${NAME} ${NAME}.cpp ${NAME}.h) #${PROTO_SRCS} ${PROTO_HDRS}
target_link_libraries(${NAME} ${test_LIBRARIES})
qt5_use_modules(${NAME} Core Test)
add_test( NAME ${NAME} COMMAND $<TARGET_FILE:${NAME}>)
set_property(TEST ${NAME} APPEND PROPERTY ENVIRONMENT DCC_TEST_BASE=${PROJECT_SOURCE_DIR})
endfunction()

File diff suppressed because it is too large Load Diff

127
Readme.md Normal file
View File

@@ -0,0 +1,127 @@
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
================
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

@@ -2,5 +2,6 @@
#cd bld #cd bld
#make -j5 #make -j5
#cd .. #cd ..
mkdir -p tests/outputs
./test_use_base.sh ./test_use_base.sh
./regression_tester.rb ./dcc_original -s -c 2>stderr >stdout; diff -wB 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

39
common/perfhlib.h Normal file
View File

@@ -0,0 +1,39 @@
#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 #!/bin/bash
mkdir -p tests/outputs
./test_use_all.sh ./test_use_all.sh
./regression_tester.rb ./dcc_original -s -c 2>stderr >stdout; diff -wB tests/prev/ tests/outputs/ ./regression_tester.rb ./dcc_original -s -c 2>stderr >stdout; diff -wB tests/prev/ tests/outputs/

View File

@@ -3,15 +3,13 @@
#include <vector> #include <vector>
#include <bitset> #include <bitset>
#include <string> #include <string>
#include <llvm/ADT/ilist.h>
#include <llvm/ADT/ilist_node.h>
#include <boost/range/iterator_range.hpp> #include <boost/range/iterator_range.hpp>
#include "icode.h" #include "icode.h"
#include "types.h" #include "types.h"
#include "graph.h" #include "graph.h"
//#include "icode.h" //#include "icode.h"
/* Basic block (BB) node definition */ /* Basic block (BB) node definition */
struct Function; class Function;
class CIcodeRec; class CIcodeRec;
struct BB; struct BB;
struct LOCAL_ID; struct LOCAL_ID;
@@ -27,9 +25,9 @@ struct TYPEADR_TYPE
TYPEADR_TYPE(interval *v) : ip(0),BBptr(nullptr),intPtr(v) TYPEADR_TYPE(interval *v) : ip(0),BBptr(nullptr),intPtr(v)
{} {}
}; };
struct BB : public llvm::ilist_node<BB> struct BB
{ {
friend struct Function; friend class Function;
private: private:
BB(const BB&); BB(const BB&);
BB() : nodeType(0),traversed(DFS_NONE), BB() : nodeType(0),traversed(DFS_NONE),
@@ -111,7 +109,7 @@ public:
/// ///
const Function *getParent() const { return Parent; } const Function *getParent() const { return Parent; }
Function *getParent() { 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); BB * rmJMP(int marker, BB *pBB);
void genDU1(); void genDU1();
void findBBExps(LOCAL_ID &locals, Function *f); void findBBExps(LOCAL_ID &locals, Function *f);

View File

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

View File

@@ -1,31 +1,41 @@
#pragma once #pragma once
#include "ast.h" #include "ast.h"
#ifdef PASCAL
#undef PASCAL
#endif
class QTextStream;
struct CConv { struct CConv {
enum Type { enum CC_Type {
UNKNOWN=0, UNKNOWN=0,
C, C,
PASCAL PASCAL
}; };
virtual void processHLI(Function *func, Expr *_exp, iICODE picode)=0; virtual void processHLI(Function *func, Expr *_exp, iICODE picode)=0;
virtual void writeComments(std::ostream &)=0; //! given return and argument types fill Function's STKFRAME and return locations
static CConv * create(Type v); virtual void calculateStackLayout(Function *func)=0;
virtual void writeComments(QTextStream &)=0;
static CConv * create(CC_Type v);
protected: protected:
}; };
struct C_CallingConvention : public CConv { struct C_CallingConvention : public CConv {
virtual void processHLI(Function *func, Expr *_exp, iICODE picode); virtual void processHLI(Function *func, Expr *_exp, iICODE picode) override;
virtual void writeComments(std::ostream &); virtual void writeComments(QTextStream &) override;
void calculateStackLayout(Function *func) override;
private: private:
int processCArg(Function *callee, Function *pProc, ICODE *picode, size_t numArgs); int processCArg(Function *callee, Function *pProc, ICODE *picode, size_t numArgs);
}; };
struct Pascal_CallingConvention : public CConv { struct Pascal_CallingConvention : public CConv {
virtual void processHLI(Function *func, Expr *_exp, iICODE picode); virtual void processHLI(Function *func, Expr *_exp, iICODE picode) override;
virtual void writeComments(std::ostream &); virtual void writeComments(QTextStream &) override;
void calculateStackLayout(Function *func) override;
}; };
struct Unknown_CallingConvention : public CConv { struct Unknown_CallingConvention : public CConv {
void processHLI(Function *func, Expr *_exp, iICODE picode) {} void processHLI(Function *func, Expr *_exp, iICODE picode) override {}
virtual void writeComments(std::ostream &); void calculateStackLayout(Function *func) override;
virtual void writeComments(QTextStream &) override;
}; };

19
include/CallGraph.h Normal file
View File

@@ -0,0 +1,19 @@
#pragma once
#include "Procedure.h"
/* CALL GRAPH NODE */
struct CALL_GRAPH
{
PtrFunction 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(PtrFunction caller, PtrFunction callee);
//bool insertCallGraph(PtrFunction caller, PtrFunction callee);
void insertArc(PtrFunction newProc);
};
//extern CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */

44
include/DccFrontend.h Normal file
View File

@@ -0,0 +1,44 @@
#pragma once
#include <QtCore/QObject>
#include "src/Command.h"
#include "project.h"
class Project;
class DccFrontend : public QObject
{
Q_OBJECT
void LoadImage();
void parse(Project &proj);
public:
explicit DccFrontend(QObject *parent = 0);
bool FrontEnd(); /* frontend.c */
signals:
public slots:
};
struct MachineStateInitialization : public Command {
MachineStateInitialization() : Command("Initialize simulated machine state",eProject) {}
bool execute(CommandContext *ctx) override;
};
struct FindMain : public Command {
FindMain() : Command("Locate the main entry point",eProject) {}
bool execute(CommandContext *ctx);
};
struct CreateFunction : public Command {
QString m_name;
SegOffAddr m_addr;
FunctionType *m_type;
CreateFunction(QString name,SegOffAddr address,FunctionType *f) : Command("Create function",eProject),
m_name(name),
m_addr(address),
m_type(f)
{}
QString instanceDescription() const override;
bool execute(CommandContext *ctx) override;
};

View File

@@ -90,9 +90,9 @@ enum eLLFlags
/* Types of icodes */ /* Types of icodes */
enum icodeType enum icodeType
{ {
NOT_SCANNED = 0, // not even scanned yet NOT_SCANNED_ICODE = 0, // not even scanned yet
LOW_LEVEL, // low-level icode LOW_LEVEL_ICODE, // low-level icode
HIGH_LEVEL // high-level icode HIGH_LEVEL_ICODE // high-level icode
}; };
@@ -263,7 +263,8 @@ enum hlType
TYPE_STR, /* string */ TYPE_STR, /* string */
TYPE_CONST, /* constant (any type) */ TYPE_CONST, /* constant (any type) */
TYPE_FLOAT, /* floating point */ TYPE_FLOAT, /* floating point */
TYPE_DOUBLE /* double precision float */ TYPE_DOUBLE, /* double precision float */
TYPE_FUNC
}; };
/* Operand is defined, used or both flag */ /* Operand is defined, used or both flag */

View File

@@ -1,47 +1,30 @@
#pragma once #pragma once
#include <llvm/ADT/ilist.h>
//#include <llvm/ADT/ilist_node.h>
#include <bitset>
#include <map>
#include "BasicBlock.h" #include "BasicBlock.h"
#include "locident.h" #include "locident.h"
#include "state.h" #include "state.h"
#include "icode.h" #include "icode.h"
#include "StackFrame.h" #include "StackFrame.h"
#include "CallConvention.h" #include "CallConvention.h"
#include <memory>
#include <stdint.h>
#include <QtCore/QString>
#include <bitset>
#include <map>
class QIODevice;
class QTextStream;
/* PROCEDURE NODE */ /* PROCEDURE NODE */
struct CALL_GRAPH; struct CALL_GRAPH;
struct Expr; struct Expr;
struct Disassembler; struct Disassembler;
struct Function; class Function;
struct CALL_GRAPH; struct CALL_GRAPH;
struct PROG; struct PROG;
struct IStructuredTextTarget;
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 */ /* Procedure FLAGS */
enum PROC_FLAGS enum PROC_FLAGS
{ {
@@ -49,15 +32,11 @@ enum PROC_FLAGS
PROC_IJMP =0x00000200, /* Proc incomplete due to indirect jmp */ PROC_IJMP =0x00000200, /* Proc incomplete due to indirect jmp */
PROC_ICALL =0x00000400, /* Proc incomplete due to indirect call */ PROC_ICALL =0x00000400, /* Proc incomplete due to indirect call */
PROC_HLL =0x00001000, /* Proc is likely to be from a HLL */ 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 */
PROC_NEAR =0x00010000, /* Proc exits with near return */ PROC_NEAR =0x00010000, /* Proc exits with near return */
PROC_FAR =0x00020000, /* Proc exits with far return */ PROC_FAR =0x00020000, /* Proc exits with far return */
GRAPH_IRRED =0x00100000, /* Proc generates an irreducible graph */ GRAPH_IRRED =0x00100000, /* Proc generates an irreducible graph */
SI_REGVAR =0x00200000, /* SI is used as a stack variable */ SI_REGVAR =0x00200000, /* SI is used as a stack variable */
DI_REGVAR =0x00400000, /* DI is used as a stack variable */ 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 */ 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_OUTPUT =0x04000000, /* C for this proc has been output */
@@ -68,10 +47,43 @@ enum PROC_FLAGS
//#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */ //#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
}; };
struct FunctionType struct Type {
hlType dcc_type;
};
struct FunctionType : public Type
{ {
CConv * m_call_conv;
std::vector<Type> ContainedTys;
ID retVal; /* Return value - identifier */
bool m_vararg=false; bool m_vararg=false;
unsigned getNumParams() const { return ContainedTys.size(); }
bool isVarArg() const {return m_vararg;} bool isVarArg() const {return m_vararg;}
void setReturnType(hlType t) {
retVal.type = t;
}
void setReturnLocation(const LONGID_TYPE &v) {
retVal.loc = REG_FRAME;
retVal.longId() = v;
}
void setReturnLocation(eReg reg) {
retVal.loc = REG_FRAME;
retVal.id.regi = reg;
}
hlType getReturnType() const { return retVal.type; }
void addArgument(hlType hl) {
ContainedTys.push_back(Type {hl});
}
void clearArguments() { ContainedTys.clear(); }
void setCallingConvention(CConv::CC_Type cc);
static FunctionType *get(Type result,std::vector<Type> params, bool vararg_func) {
FunctionType * res = new FunctionType;
res->setReturnType(result.dcc_type);
std::swap(res->ContainedTys,params);
res->m_vararg = vararg_func;
return res;
}
}; };
struct Assignment struct Assignment
{ {
@@ -107,33 +119,44 @@ public:
} }
void push_back(BB *v) { m_listBB.push_back(v);} void push_back(BB *v) { m_listBB.push_back(v);}
}; };
struct Function : public llvm::ilist_node<Function> typedef std::shared_ptr<Function> PtrFunction;
enum DecompilationStep : uint32_t {
eNotDecoded, // no processing done yet
eDisassemblyInProgress,
eDissassembled, // low level disassembly done
//eLocatedImpureRefs,
//eStackTracing, // tracing stack depth across function calls
};
class Function : public std::enable_shared_from_this<Function>
{ {
typedef llvm::iplist<BB> BasicBlockListType; typedef std::list<BB *> BasicBlockListType;
// BasicBlock iterators... // BasicBlock iterators...
typedef BasicBlockListType::iterator iterator; typedef BasicBlockListType::iterator iterator;
typedef BasicBlockListType::const_iterator const_iterator; typedef BasicBlockListType::const_iterator const_iterator;
protected: protected:
BasicBlockListType BasicBlocks; ///< The basic blocks BasicBlockListType BasicBlocks; ///< The basic blocks
Function(FunctionType */*ty*/) : procEntry(0),depth(0),flg(0),cbParam(0),m_dfsLast(0),numBBs(0), Function(FunctionType *ty) : nStep(eNotDecoded),procEntry(0),depth(0),flg(0),cbParam(0),m_dfsLast(0),numBBs(0),
hasCase(false),liveAnal(0) hasCase(false),liveAnal(0)
{ {
type = ty;
if(!ty) // No type was provided, create it
type = new FunctionType; type = new FunctionType;
callingConv(CConv::UNKNOWN); callingConv(CConv::UNKNOWN);
} }
public: public:
DecompilationStep nStep; // decompilation step number for this function
FunctionType * type; FunctionType * type;
CConv * m_call_conv;
uint32_t procEntry; /* label number */ uint32_t procEntry; /* label number */
std::string name; /* Meaningful name for this proc */ QString name; /* Meaningful name for this proc */
STATE state; /* Entry state */ STATE state; /* Entry state */
int depth; /* Depth at which we found it - for printing */ int depth; /* Depth at which we found it - for printing */
uint32_t flg; /* Combination of Icode & Proc flags */ uint32_t flg; /* Combination of Icode & Proc flags */
int16_t cbParam; /* Probable no. of bytes of parameters */ int16_t cbParam; /* Probable no. of bytes of parameters */
STKFRAME args; /* Array of arguments */ STKFRAME args; /* Array of arguments */
LOCAL_ID localId; /* Local identifiers */ LOCAL_ID localId; /* Local identifiers */
ID retVal; /* Return value - identifier */
/* Icodes and control flow graph */ /* Icodes and control flow graph */
CIcodeRec Icode; /* Object with ICODE records */ CIcodeRec Icode; /* Object with ICODE records */
@@ -153,20 +176,25 @@ public:
delete type; delete type;
} }
public: public:
static Function *Create(FunctionType *ty=0,int /*Linkage*/=0,const std::string &nm="",void */*module*/=0) static PtrFunction Create(FunctionType *ty=0,int /*Linkage*/=0,const QString &nm="",void */*module*/=0)
{ {
Function *r=new Function(ty); PtrFunction r(new Function(ty));
r->name = nm; r->name = nm;
return r; return r;
} }
hlType getReturnType() const {
return getFunctionType()->getReturnType();
}
FunctionType *getFunctionType() const { FunctionType *getFunctionType() const {
return type; return type;
} }
CConv *callingConv() const { return m_call_conv;} CConv *callingConv() const { return type->m_call_conv;}
void callingConv(CConv::Type v); void callingConv(CConv::CC_Type v);
// bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;} // bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;}
bool hasRegArgs() const { return (flg & REG_ARGS)!=0;} bool hasRegArgs() const { return (flg & REG_ARGS)!=0;}
void markDoNotDecompile() { flg |= PROC_ISLIB; }
bool doNotDecompile() const { return isLibrary(); }
bool isLibrary() const { return (flg & PROC_ISLIB)!=0;} bool isLibrary() const { return (flg & PROC_ISLIB)!=0;}
void compoundCond(); void compoundCond();
void writeProcComments(); void writeProcComments();
@@ -180,19 +208,17 @@ public:
void createCFG(); void createCFG();
void markImpure(); void markImpure();
void findImmedDom(); void findImmedDom();
void FollowCtrl(CALL_GRAPH *pcallGraph, STATE *pstate);
void process_operands(ICODE &pIcode, STATE *pstate); void process_operands(ICODE &pIcode, STATE *pstate);
bool process_JMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
bool process_CALL(ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
void freeCFG(); void freeCFG();
void codeGen(std::ostream &fs); void codeGen(QIODevice & fs);
void mergeFallThrough(BB *pBB); void mergeFallThrough(BB *pBB);
void structIfs(); void structIfs();
void structLoops(derSeq *derivedG); void structLoops(derSeq *derivedG);
void buildCFG(Disassembler &ds); void buildCFG(Disassembler &ds);
void controlFlowAnalysis(); void controlFlowAnalysis();
void newRegArg(iICODE picode, iICODE ticode); void newRegArg(iICODE picode, iICODE ticode);
void writeProcComments(std::ostream &ostr); void writeProcComments(QTextStream & ostr);
void toStructuredText(IStructuredTextTarget *out,int level);
void displayCFG(); void displayCFG();
void displayStats(); void displayStats();
@@ -200,13 +226,12 @@ public:
void preprocessReturnDU(LivenessSet &_liveOut); void preprocessReturnDU(LivenessSet &_liveOut);
Expr * adjustActArgType(Expr *_exp, hlType forType); Expr * adjustActArgType(Expr *_exp, hlType forType);
std::string writeCall(Function *tproc, STKFRAME &args, int *numLoc); QString writeCall(Function *tproc, STKFRAME &args, int *numLoc);
void processDosInt(STATE *pstate, PROG &prog, bool done); void processDosInt(STATE *pstate, PROG &prog, bool done);
ICODE *translate_DIV(LLInst *ll, ICODE &_Icode);
ICODE *translate_XCHG(LLInst *ll, ICODE &_Icode); void switchState(DecompilationStep s);
protected: protected:
void extractJumpTableRange(ICODE& pIcode, STATE *pstate, JumpTable &table); void extractJumpTableRange(ICODE& pIcode, STATE *pstate, JumpTable &table);
bool followAllTableEntries(JumpTable &table, uint32_t cs, ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
bool removeInEdge_Flag_and_ProcessLatch(BB *pbb, BB *a, BB *b); bool removeInEdge_Flag_and_ProcessLatch(BB *pbb, BB *a, BB *b);
bool Case_X_and_Y(BB* pbb, BB* thenBB, BB* elseBB); bool Case_X_and_Y(BB* pbb, BB* thenBB, BB* elseBB);
bool Case_X_or_Y(BB* pbb, BB* thenBB, BB* elseBB); bool Case_X_or_Y(BB* pbb, BB* thenBB, BB* elseBB);
@@ -233,26 +258,8 @@ protected:
void genLiveKtes(); void genLiveKtes();
bool findDerivedSeq(derSeq &derivedGi); bool findDerivedSeq(derSeq &derivedGi);
bool nextOrderGraph(derSeq &derivedGi); bool nextOrderGraph(derSeq &derivedGi);
void addOutEdgesForConditionalJump(BB *pBB, int next_ip, LLInst *ll);
}; };
namespace llvm { typedef std::list<PtrFunction> FunctionListType;
template<> struct ilist_traits<typename ::Function>
: public ilist_default_traits<typename ::Function> {
// 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>)
typename ::Function *createSentinel() const {
return static_cast<typename ::Function*>(&Sentinel);
}
static void destroySentinel(typename ::Function*) {}
typename ::Function *provideInitialHead() const { return createSentinel(); }
typename ::Function *ensureHead(::Function*) const { return createSentinel(); }
static void noteHead(typename ::Function*, typename ::Function*) {}
private:
mutable ilist_node<typename ::Function> Sentinel;
};
}
typedef llvm::iplist<Function> FunctionListType;
typedef FunctionListType lFunction; typedef FunctionListType lFunction;
typedef lFunction::iterator ilFunction; typedef lFunction::iterator ilFunction;

View File

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

View File

@@ -5,11 +5,15 @@
* (C) Cristina Cifuentes * (C) Cristina Cifuentes
*/ */
#pragma once #pragma once
#include "Enums.h"
#include "msvc_fixes.h"
#include <boost/range/iterator_range.hpp>
#include <stdint.h> #include <stdint.h>
#include <cstring> #include <cstring>
#include <list> #include <list>
#include <boost/range/iterator_range.hpp>
#include "Enums.h"
static const int operandSize=20; static const int operandSize=20;
/* The following definitions and types define the Conditional Expression /* The following definitions and types define the Conditional Expression
* attributed syntax tree, as defined by the following EBNF: * attributed syntax tree, as defined by the following EBNF:
@@ -24,7 +28,7 @@ static const condOp condOpJCond[12] = {LESS, LESS_EQUAL, GREATER_EQUAL, GREATER,
EQUAL, NOT_EQUAL, LESS, GREATER_EQUAL, EQUAL, NOT_EQUAL, LESS, GREATER_EQUAL,
LESS_EQUAL, GREATER, GREATER_EQUAL, LESS}; LESS_EQUAL, GREATER, GREATER_EQUAL, LESS};
struct AstIdent; struct AstIdent;
struct Function; class Function;
struct STKFRAME; struct STKFRAME;
struct LOCAL_ID; struct LOCAL_ID;
struct ICODE; struct ICODE;
@@ -54,7 +58,7 @@ public:
/** Recursively deallocates the abstract syntax tree rooted at *exp */ /** Recursively deallocates the abstract syntax tree rooted at *exp */
virtual ~Expr() {} virtual ~Expr() {}
public: public:
virtual std::string walkCondExpr (Function * pProc, int* numLoc) const=0; virtual QString walkCondExpr (Function * pProc, int* numLoc) const=0;
virtual Expr *inverse() const=0; // return new COND_EXPR that is invarse of this 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 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 *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym)=0;
@@ -96,10 +100,12 @@ struct UnaryOperator : public Expr
} }
public: public:
int hlTypeSize(Function *pproc) const; int hlTypeSize(Function *pproc) const;
virtual std::string walkCondExpr(Function *pProc, int *numLoc) const; virtual QString walkCondExpr(Function *pProc, int *numLoc) const;
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym); virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym);
virtual hlType expType(Function *pproc) const; virtual hlType expType(Function *pproc) const;
virtual Expr *insertSubTreeLongReg(Expr *_expr, int longIdx); virtual Expr *insertSubTreeLongReg(Expr *_expr, int longIdx);
private:
QString wrapUnary(Function *pProc, int *numLoc, QChar op) const;
}; };
struct BinaryOperator : public Expr struct BinaryOperator : public Expr
@@ -120,7 +126,7 @@ struct BinaryOperator : public Expr
} }
~BinaryOperator() ~BinaryOperator()
{ {
assert(m_lhs!=m_rhs || m_lhs==nullptr); assert(m_lhs!=m_rhs or m_lhs==nullptr);
delete m_lhs; delete m_lhs;
delete m_rhs; delete m_rhs;
m_lhs=m_rhs=nullptr; m_lhs=m_rhs=nullptr;
@@ -184,7 +190,7 @@ struct BinaryOperator : public Expr
condOp op() const { return m_op;} condOp op() const { return m_op;}
/* Changes the boolean conditional operator at the root of this expression */ /* Changes the boolean conditional operator at the root of this expression */
void op(condOp o) { m_op=o;} void op(condOp o) { m_op=o;}
std::string walkCondExpr (Function * pProc, int* numLoc) const; QString walkCondExpr(Function * pProc, int* numLoc) const;
public: public:
hlType expType(Function *pproc) const; hlType expType(Function *pproc) const;
int hlTypeSize(Function *pproc) const; int hlTypeSize(Function *pproc) const;
@@ -211,7 +217,7 @@ struct AstIdent : public UnaryOperator
virtual int hlTypeSize(Function *pproc) const; virtual int hlTypeSize(Function *pproc) const;
virtual hlType expType(Function *pproc) const; virtual hlType expType(Function *pproc) const;
virtual Expr * performLongRemoval(eReg regi, LOCAL_ID *locId); virtual Expr * performLongRemoval(eReg regi, LOCAL_ID *locId);
virtual std::string walkCondExpr(Function *pProc, int *numLoc) const; virtual QString walkCondExpr(Function *pProc, int *numLoc) const;
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym); virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym);
virtual Expr *insertSubTreeLongReg(Expr *_expr, int longIdx); virtual Expr *insertSubTreeLongReg(Expr *_expr, int longIdx);
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId); virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId);
@@ -228,7 +234,7 @@ struct GlobalVariable : public AstIdent
return new GlobalVariable(*this); return new GlobalVariable(*this);
} }
GlobalVariable(int16_t segValue, int16_t off); GlobalVariable(int16_t segValue, int16_t off);
std::string walkCondExpr(Function *pProc, int *numLoc) const; QString walkCondExpr(Function *pProc, int *numLoc) const;
int hlTypeSize(Function *pproc) const; int hlTypeSize(Function *pproc) const;
hlType expType(Function *pproc) const; hlType expType(Function *pproc) const;
}; };
@@ -242,7 +248,7 @@ struct GlobalVariableIdx : public AstIdent
return new GlobalVariableIdx(*this); return new GlobalVariableIdx(*this);
} }
GlobalVariableIdx(int16_t segValue, int16_t off, uint8_t regi, const LOCAL_ID *locSym); GlobalVariableIdx(int16_t segValue, int16_t off, uint8_t regi, const LOCAL_ID *locSym);
std::string walkCondExpr(Function *pProc, int *numLoc) const; QString walkCondExpr(Function *pProc, int *numLoc) const;
int hlTypeSize(Function *pproc) const; int hlTypeSize(Function *pproc) const;
hlType expType(Function *pproc) const; hlType expType(Function *pproc) const;
}; };
@@ -264,7 +270,7 @@ struct Constant : public AstIdent
{ {
return new Constant(*this); return new Constant(*this);
} }
std::string walkCondExpr(Function *pProc, int *numLoc) const; QString walkCondExpr(Function *pProc, int *numLoc) const;
int hlTypeSize(Function *pproc) const; int hlTypeSize(Function *pproc) const;
hlType expType(Function *pproc) const; hlType expType(Function *pproc) const;
}; };
@@ -284,7 +290,7 @@ struct FuncNode : public AstIdent
{ {
return new FuncNode(*this); return new FuncNode(*this);
} }
std::string walkCondExpr(Function *pProc, int *numLoc) const; QString walkCondExpr(Function *pProc, int *numLoc) const;
int hlTypeSize(Function *pproc) const; int hlTypeSize(Function *pproc) const;
hlType expType(Function *pproc) const; hlType expType(Function *pproc) const;
}; };
@@ -310,7 +316,7 @@ struct RegisterNode : public AstIdent
{ {
return new RegisterNode(*this); return new RegisterNode(*this);
} }
std::string walkCondExpr(Function *pProc, int *numLoc) const; QString walkCondExpr(Function *pProc, int *numLoc) const;
int hlTypeSize(Function *) const; int hlTypeSize(Function *) const;
hlType expType(Function *pproc) const; hlType expType(Function *pproc) const;
bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId); bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId);

View File

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

View File

@@ -5,10 +5,10 @@
#pragma once #pragma once
//TODO: Remove boolT //TODO: Remove boolT
#include <llvm/ADT/ilist.h>
#include <utility> #include <utility>
#include <algorithm> #include <algorithm>
#include <bitset> #include <bitset>
#include <QtCore/QString>
#include "Enums.h" #include "Enums.h"
#include "types.h" #include "types.h"
@@ -26,7 +26,7 @@ extern bundle cCode; /* Output C procedure's declaration and code */
/**** Global variables ****/ /**** 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 */ typedef struct { /* Command line option flags */
unsigned verbose : 1; unsigned verbose : 1;
@@ -37,7 +37,8 @@ typedef struct { /* Command line option flags */
unsigned Stats : 1; unsigned Stats : 1;
unsigned Interact : 1; /* Interactive mode */ unsigned Interact : 1; /* Interactive mode */
unsigned Calls : 1; /* Follow register indirect calls */ unsigned Calls : 1; /* Follow register indirect calls */
char filename[80]; /* The input filename */ QString filename; /* The input filename */
uint32_t CustomEntryPoint;
} OPTION; } OPTION;
extern OPTION option; /* Command line options */ extern OPTION option; /* Command line options */
@@ -71,40 +72,28 @@ extern STATS stats; /* Icode statistics */
/**** Global function prototypes ****/ /**** 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 udm(void); /* udm.c */
void freeCFG(BB * cfg); /* graph.c */ void freeCFG(BB * cfg); /* graph.c */
BB * newBB(BB *, int, int, uint8_t, int, Function *); /* graph.c */ BB * newBB(BB *, int, int, uint8_t, int, Function *); /* graph.c */
void BackEnd(char *filename, CALL_GRAPH *); /* backend.c */ void BackEnd(CALL_GRAPH *); /* backend.c */
extern char *cChar(uint8_t c); /* backend.c */ extern char *cChar(uint8_t c); /* backend.c */
eErrorId scan(uint32_t ip, ICODE &p); /* scanner.c */ eErrorId scan(uint32_t ip, ICODE &p); /* scanner.c */
void parse (CALL_GRAPH * *); /* parser.c */ void parse (CALL_GRAPH * *); /* parser.c */
extern int strSize (const uint8_t *, char); /* parser.c */ extern int strSize (const uint8_t *, char); /* parser.c */
//void disassem(int pass, Function * pProc); /* disassem.c */ void interactDis(const PtrFunction &, int initIC); /* disassem.c */
void interactDis(Function *, int initIC); /* disassem.c */
bool JmpInst(llIcode opcode); /* idioms.c */ bool JmpInst(llIcode opcode); /* idioms.c */
queue::iterator appendQueue(queue &Q, BB *node); /* reducible.c */ queue::iterator appendQueue(queue &Q, BB *node); /* reducible.c */
void SetupLibCheck(void); /* chklib.c */ bool SetupLibCheck(QString pattern_file_id); /* chklib.c */
void CleanupLibCheck(void); /* chklib.c */ void CleanupLibCheck(void); /* chklib.c */
bool LibCheck(Function &p); /* chklib.c */ bool LibCheck(Function &p); /* chklib.c */
/* Exported functions from hlicode.c */ /* Exported functions from hlicode.c */
const char *writeJcond(const HLTYPE &, Function *, int *); QString writeJcond(const HLTYPE &, Function *, int *);
const char *writeJcondInv (HLTYPE, Function *, int *); QString writeJcondInv(HLTYPE, Function *, int *);
/* Exported funcions from locident.c */ /* Exported funcions from locident.c */

14
include/dcc_interface.h Normal file
View File

@@ -0,0 +1,14 @@
#pragma once
#include "Procedure.h"
#include <QtCore/QObject>
#include <QtCore/QDir>
class IStructuredTextTarget;
struct IDcc {
static IDcc *get();
virtual bool load(QString name)=0; // load and preprocess -> find entry point
virtual QDir installDir()=0;
virtual QDir dataDir(QString kind)=0;
};

View File

@@ -5,28 +5,35 @@
*************************************************************************** ***************************************************************************
*/ */
#pragma once #pragma once
#include "bundle.h"
#include <memory>
#include <fstream> #include <fstream>
#include <vector> #include <vector>
#include "bundle.h" #include <QString>
#include <QTextStream>
struct LLInst; struct LLInst;
class Function;
typedef std::shared_ptr<Function> PtrFunction;
struct Disassembler struct Disassembler
{ {
protected: protected:
int pass; int pass=0;
int g_lab; int g_lab=0;
//bundle &cCode; QIODevice *m_disassembly_target=nullptr;
std::ofstream m_fp; QTextStream m_fp;
std::vector<std::string> m_decls; std::vector<std::string> m_decls;
std::vector<std::string> m_code; std::vector<std::string> m_code;
public: public:
Disassembler(int _p) : pass(_p) Disassembler(int _p) : pass(_p)
{ {
g_lab=0;
} }
public:
void disassem(Function *ppProc); void disassem(PtrFunction ppProc);
void disassem(Function *ppProc, int i); void disassem(PtrFunction ppProc, int i);
void dis1Line(LLInst &inst, int loc_ip, int pass); void dis1Line(LLInst &inst, int loc_ip, int pass);
}; };
/* Definitions for extended keys (first key is zero) */ /* Definitions for extended keys (first key is zero) */

View File

@@ -8,7 +8,7 @@
#include <stdint.h> #include <stdint.h>
#include <list> #include <list>
struct Function; class Function;
/* Types of basic block nodes */ /* Types of basic block nodes */
/* Real basic blocks: type defined according to their out-edges */ /* Real basic blocks: type defined according to their out-edges */
enum eBBKind enum eBBKind

View File

@@ -3,6 +3,16 @@
* (C) Cristina Cifuentes * (C) Cristina Cifuentes
****************************************************************************/ ****************************************************************************/
#pragma once #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 <memory>
#include <vector> #include <vector>
#include <list> #include <list>
@@ -10,21 +20,12 @@
#include <set> #include <set>
#include <algorithm> #include <algorithm>
#include <initializer_list> #include <initializer_list>
#include <llvm/ADT/ilist.h>
#include <llvm/ADT/ilist_node.h>
#include <llvm/MC/MCInst.h>
#include <llvm/IR/Instruction.h>
#include <boost/range/iterator_range.hpp>
#include "libdis.h"
#include "Enums.h"
#include "state.h" // State depends on INDEXBASE, but later need STATE
#include "CallConvention.h"
//enum condId; //enum condId;
struct LOCAL_ID; struct LOCAL_ID;
struct BB; struct BB;
struct Function; class Function;
struct STKFRAME; struct STKFRAME;
class CIcodeRec; class CIcodeRec;
struct ICODE; struct ICODE;
@@ -58,12 +59,7 @@ public:
} }
friend void swap(LivenessSet& first, LivenessSet& second) // nothrow friend void swap(LivenessSet& first, LivenessSet& second) // nothrow
{ {
// enable ADL (not necessary in our case, but good practice) std::swap(first.registers, second.registers);
using std::swap;
// by swapping the members of two classes,
// the two classes are effectively swapped
swap(first.registers, second.registers);
} }
LivenessSet &operator|=(const LivenessSet &other) LivenessSet &operator|=(const LivenessSet &other)
{ {
@@ -142,7 +138,7 @@ struct HlTypeSupport
{ {
//hlIcode opcode; /* hlIcode opcode */ //hlIcode opcode; /* hlIcode opcode */
virtual bool removeRegFromLong(eReg regi, LOCAL_ID *locId)=0; virtual bool removeRegFromLong(eReg regi, LOCAL_ID *locId)=0;
virtual std::string writeOut(Function *pProc, int *numLoc) const=0; virtual QString writeOut(Function *pProc, int *numLoc) const=0;
protected: protected:
Expr * performLongRemoval (eReg regi, LOCAL_ID *locId, Expr *tree); Expr * performLongRemoval (eReg regi, LOCAL_ID *locId, Expr *tree);
}; };
@@ -159,10 +155,10 @@ struct CallType : public HlTypeSupport
public: 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; return false;
} }
std::string writeOut(Function *pProc, int *numLoc) const; QString writeOut(Function *pProc, int *numLoc) const;
}; };
struct AssignType : public HlTypeSupport struct AssignType : public HlTypeSupport
{ {
@@ -170,12 +166,12 @@ struct AssignType : public HlTypeSupport
protected: protected:
public: public:
Expr *m_lhs; Expr *m_lhs;
Expr *rhs; Expr *m_rhs;
AssignType() {} AssignType() {}
Expr *lhs() const {return m_lhs;} Expr *lhs() const {return m_lhs;}
void lhs(Expr *l); void lhs(Expr *l);
bool removeRegFromLong(eReg regi, LOCAL_ID *locId); bool removeRegFromLong(eReg regi, LOCAL_ID *locId);
std::string writeOut(Function *pProc, int *numLoc) const; QString writeOut(Function *pProc, int *numLoc) const;
}; };
struct ExpType : public HlTypeSupport struct ExpType : public HlTypeSupport
{ {
@@ -187,7 +183,7 @@ struct ExpType : public HlTypeSupport
v=performLongRemoval(regi,locId,v); v=performLongRemoval(regi,locId,v);
return true; return true;
} }
std::string writeOut(Function *pProc, int *numLoc) const; QString writeOut(Function *pProc, int *numLoc) const;
}; };
struct HLTYPE struct HLTYPE
@@ -241,7 +237,7 @@ public:
return *this; return *this;
} }
public: public:
std::string write1HlIcode(Function *pProc, int *numLoc) const; QString write1HlIcode(Function *pProc, int *numLoc) const;
void setAsgn(Expr *lhs, Expr *rhs); void setAsgn(Expr *lhs, Expr *rhs);
} ; } ;
/* LOW_LEVEL icode operand record */ /* LOW_LEVEL icode operand record */
@@ -257,7 +253,7 @@ struct LLOperand
bool is_offset; // set by jumps bool is_offset; // set by jumps
bool is_compound; bool is_compound;
size_t width; size_t width;
//union {/* Source operand if (flg & I) */ /* Source operand if (flg & I) */
struct { /* Call & # actual arg bytes */ struct { /* Call & # actual arg bytes */
Function *proc; /* pointer to target proc (for CALL(F))*/ Function *proc; /* pointer to target proc (for CALL(F))*/
int cb; /* # actual arg bytes */ int cb; /* # actual arg bytes */
@@ -275,12 +271,12 @@ struct LLOperand
} }
bool operator==(const LLOperand &with) const bool operator==(const LLOperand &with) const
{ {
return (seg==with.seg) && return (seg==with.seg) and
(segOver==with.segOver) && (segOver==with.segOver) and
(segValue==with.segValue) && (segValue==with.segValue) and
(regi == with.regi) && (regi == with.regi) and
(off == with.off) && (off == with.off) and
(opz==with.opz) && (opz==with.opz) and
(proc.proc==with.proc.proc); (proc.proc==with.proc.proc);
} }
int64_t getImm2() const {return opz;} int64_t getImm2() const {return opz;}
@@ -304,19 +300,20 @@ struct LLOperand
Op.regi = (eReg)Val; Op.regi = (eReg)Val;
return Op; return Op;
} }
bool isSet() bool isSet() const
{ {
return not (*this == LLOperand()); return not (*this == LLOperand());
} }
void addProcInformation(int param_count, CConv::Type call_conv); void addProcInformation(int param_count, CConv::CC_Type call_conv);
bool isImmediate() const { return immed;} bool isImmediate() const { return immed;}
void setImmediate(bool x) { immed=x;} void setImmediate(bool x) { immed=x;}
bool compound() const {return is_compound;} // dx:ax pair bool compound() const {return is_compound;} // dx:ax pair
size_t byteWidth() const { assert(width<=4); return width;} size_t byteWidth() const { assert(width<=4); return width;}
}; };
struct LLInst : public llvm::MCInst //: public llvm::ilist_node<LLInst> struct LLInst
{ {
protected: protected:
uint32_t m_opcode; // Low level opcode identifier
uint32_t flg; /* icode flags */ uint32_t flg; /* icode flags */
LLOperand m_src; /* source operand */ LLOperand m_src; /* source operand */
public: public:
@@ -328,49 +325,51 @@ public:
int caseEntry; int caseEntry;
std::vector<uint32_t> caseTbl2; std::vector<uint32_t> caseTbl2;
int hllLabNum; /* label # for hll codegen */ int hllLabNum; /* label # for hll codegen */
uint32_t getOpcode() const { return m_opcode;}
void setOpcode(uint32_t op) { m_opcode=op; }
bool conditionalJump() bool conditionalJump()
{ {
return (getOpcode() >= iJB) && (getOpcode() < iJCXZ); return (getOpcode() >= iJB) and (getOpcode() < iJCXZ);
} }
bool testFlags(uint32_t x) const { return (flg & x)!=0;} bool testFlags(uint32_t x) const { return (flg & x)!=0;}
void setFlags(uint32_t flag) {flg |= flag;} void setFlags(uint32_t flag) {flg |= flag;}
void clrFlags(uint32_t flag) void clrFlags(uint32_t flag);
{
if(getOpcode()==iMOD)
{
assert(false);
}
flg &= ~flag;
}
uint32_t getFlag() const {return flg;} uint32_t getFlag() const {return flg;}
uint32_t GetLlLabel() const { return label;} uint32_t GetLlLabel() const { return label;}
void SetImmediateOp(uint32_t dw) {m_src.SetImmediateOp(dw);} void SetImmediateOp(uint32_t dw) {m_src.SetImmediateOp(dw);}
bool match(llIcode op) bool match(llIcode op)
{ {
return (getOpcode()==op); return (getOpcode()==op);
} }
bool matchWithRegDst(llIcode op) bool matchWithRegDst(llIcode op)
{ {
return (getOpcode()==op) and m_dst.isReg(); return match(op) and m_dst.isReg();
} }
bool match(llIcode op,eReg dest) bool match(llIcode op,eReg dest)
{ {
return (getOpcode()==op)&&m_dst.regi==dest; return match(op) and match(dest);
} }
bool match(llIcode op,eReg dest,uint32_t flgs) bool match(llIcode op,eReg dest,uint32_t flgs)
{ {
return (getOpcode()==op) and (m_dst.regi==dest) and testFlags(flgs); return match(op) and match(dest) and testFlags(flgs);
} }
bool match(llIcode op,eReg dest,eReg src_reg) bool match(llIcode op,eReg dest,eReg src_reg)
{ {
return (getOpcode()==op)&&(m_dst.regi==dest)&&(m_src.regi==src_reg); return match(op) and match(dest) and (m_src.regi==src_reg);
} }
bool match(eReg dest,eReg src_reg) bool match(eReg dest,eReg src_reg)
{ {
return (m_dst.regi==dest)&&(m_src.regi==src_reg); return match(dest) and (m_src.regi==src_reg);
}
bool matchAny(std::initializer_list<llIcode> ops) {
for(llIcode op : ops) {
if(match(op))
return true;
}
return false;
} }
bool match(eReg dest) bool match(eReg dest)
{ {
@@ -378,7 +377,7 @@ public:
} }
bool match(llIcode op,uint32_t flgs) bool match(llIcode op,uint32_t flgs)
{ {
return (getOpcode()==op) and testFlags(flgs); return match(op) and testFlags(flgs);
} }
void set(llIcode op,uint32_t flags) void set(llIcode op,uint32_t flags)
{ {
@@ -400,44 +399,40 @@ public:
} }
void emitGotoLabel(int indLevel); void emitGotoLabel(int indLevel);
void findJumpTargets(CIcodeRec &_pc); void findJumpTargets(CIcodeRec &_pc);
void writeIntComment(std::ostringstream &s); void writeIntComment(QTextStream & s);
void dis1Line(int loc_ip, int pass); void dis1Line(int loc_ip, int pass);
std::ostringstream &strSrc(std::ostringstream &os,bool skip_comma=false);
void flops(std::ostringstream &out); void flops(QTextStream & out);
bool isJmpInst(); bool isJmpInst();
HLTYPE createCall(); HLTYPE createCall();
LLInst(ICODE *container) : flg(0),codeIdx(0),numBytes(0),m_link(container) LLInst(ICODE *container) : flg(0),codeIdx(0),numBytes(0),m_link(container)
{ {
setOpcode(0); setOpcode(0);
} }
const LLOperand & dst() const { return m_dst; }
LLOperand & dst() { return m_dst; }
const LLOperand & src() const { return m_src; } const LLOperand & src() const { return m_src; }
LLOperand & src() { return m_src; } LLOperand & src() { return m_src; }
void replaceSrc(const LLOperand &with) void replaceSrc(const LLOperand &with) { m_src = with; }
{ void replaceSrc(eReg r) { m_src = LLOperand::CreateReg2(r); }
m_src = with; void replaceSrc(int64_t r) { m_src = LLOperand::CreateImm2(r); }
} void replaceDst(const LLOperand &with) { m_dst = with; }
void replaceSrc(eReg r) bool srcIsImmed() const { return (flg & I)!=0; }
{
m_src = LLOperand::CreateReg2(r);
}
void replaceSrc(int64_t r)
{
m_src = LLOperand::CreateImm2(r);
}
void replaceDst(const LLOperand &with)
{
m_dst = with;
}
// void replaceDst(eReg r)
// {
// dst = LLOperand::CreateReg2(r);
// }
ICODE *m_link;
condId idType(opLoc sd) const; condId idType(opLoc sd) const;
const LLOperand * get(opLoc sd) const { return (sd == SRC) ? &src() : &m_dst; } const LLOperand * get(opLoc sd) const { return (sd == SRC) ? &src() : &m_dst; }
LLOperand * get(opLoc sd) { return (sd == SRC) ? &src() : &m_dst; } LLOperand * get(opLoc sd) { return (sd == SRC) ? &src() : &m_dst; }
ICODE * m_link;
}; };
struct ADDRESS {
};
struct BinaryArea {
ADDRESS start;
ADDRESS fin;
};
#include <boost/icl/interval_set.hpp>
#include <boost/icl/interval_map.hpp>
/* Icode definition: LOW_LEVEL and HIGH_LEVEL */ /* Icode definition: LOW_LEVEL and HIGH_LEVEL */
struct ICODE struct ICODE
@@ -445,7 +440,7 @@ struct ICODE
// use llvm names at least // use llvm names at least
typedef BB MachineBasicBlock; typedef BB MachineBasicBlock;
protected: protected:
LLInst m_ll; LLInst *m_ll;
HLTYPE m_hl; HLTYPE m_hl;
MachineBasicBlock * Parent; /* BB to which this icode belongs */ MachineBasicBlock * Parent; /* BB to which this icode belongs */
bool invalid; /* Has no HIGH_LEVEL equivalent */ bool invalid; /* Has no HIGH_LEVEL equivalent */
@@ -460,17 +455,17 @@ public:
template<int TYPE> template<int TYPE>
struct TypeFilter struct TypeFilter
{ {
bool operator()(ICODE *ic) {return ic->type==HIGH_LEVEL;} bool operator()(ICODE *ic) {return ic->type==TYPE;}
bool operator()(ICODE &ic) {return ic.type==HIGH_LEVEL;} bool operator()(ICODE &ic) {return ic.type==TYPE;}
}; };
template<int TYPE> template<int TYPE>
struct TypeAndValidFilter struct TypeAndValidFilter
{ {
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==HIGH_LEVEL)&&ic.valid();} bool operator()(ICODE &ic) {return (ic.type==TYPE) and ic.valid();}
}; };
static TypeFilter<HIGH_LEVEL> select_high_level; static TypeFilter<HIGH_LEVEL_ICODE> select_high_level;
static TypeAndValidFilter<HIGH_LEVEL> select_valid_high_level; static TypeAndValidFilter<HIGH_LEVEL_ICODE> select_valid_high_level;
/* Def/Use of registers and stack variables */ /* Def/Use of registers and stack variables */
struct DU_ICODE struct DU_ICODE
{ {
@@ -506,7 +501,7 @@ public:
if(iter==uses.end()) if(iter==uses.end())
return; return;
uses.erase(iter); 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));
} }
}; };
@@ -548,8 +543,8 @@ public:
DU1 du1; /* du chain 1 */ DU1 du1; /* du chain 1 */
int loc_ip; // used by CICodeRec to number ICODEs int loc_ip; // used by CICodeRec to number ICODEs
LLInst * ll() { return &m_ll;} LLInst * ll() { return m_ll;}
const LLInst * ll() const { return &m_ll;} const LLInst * ll() const { return m_ll;}
HLTYPE * hlU() { HLTYPE * hlU() {
// assert(type==HIGH_LEVEL); // assert(type==HIGH_LEVEL);
@@ -572,7 +567,7 @@ public:
// set this icode to be an assign // set this icode to be an assign
void setAsgn(Expr *lhs, Expr *rhs) void setAsgn(Expr *lhs, Expr *rhs)
{ {
type=HIGH_LEVEL; type=HIGH_LEVEL_ICODE;
hlU()->setAsgn(lhs,rhs); hlU()->setAsgn(lhs,rhs);
} }
void setUnary(hlIcode op, Expr *_exp); void setUnary(hlIcode op, Expr *_exp);
@@ -589,8 +584,46 @@ public:
{ {
return hlU()->call.newStkArg(exp,opcode,pproc); return hlU()->call.newStkArg(exp,opcode,pproc);
} }
ICODE() : m_ll(this),Parent(0),invalid(false),type(NOT_SCANNED),loc_ip(0) ICODE() :Parent(0),invalid(false),type(NOT_SCANNED_ICODE),loc_ip(0)
{ {
m_ll = new LLInst(this);
}
~ICODE() {
delete m_ll;
}
ICODE(const ICODE &v) {
m_ll = new LLInst(*v.m_ll);
m_hl = v.m_hl;
Parent = v.Parent;
insn = v.insn;
type = v.type;
du = v.du;
du1 = v.du1;
loc_ip = v.loc_ip;
}
ICODE & operator=(const ICODE &v) {
delete m_ll;
m_ll = v.m_ll;
m_hl = v.m_hl;
Parent = v.Parent;
insn = v.insn;
type = v.type;
du = v.du;
du1 = v.du1;
loc_ip = v.loc_ip;
return *this;
}
ICODE & operator=(ICODE &&v) {
std::swap(m_ll,v.m_ll);
std::swap(m_hl,v.m_hl);
std::swap(Parent , v.Parent);
std::swap(insn , v.insn);
std::swap(type , v.type);
std::swap(du , v.du);
std::swap(du1 , v.du1);
std::swap(loc_ip , v.loc_ip);
return *this;
} }
public: public:
const MachineBasicBlock* getParent() const { return Parent; } const MachineBasicBlock* getParent() const { return Parent; }
@@ -600,21 +633,20 @@ public:
}; };
/** Map n low level instructions to m high level instructions /** Map n low level instructions to m high level instructions
*/ */
struct MappingLLtoML //struct MappingLLtoML
{ //{
typedef llvm::iplist<llvm::Instruction> InstListType; // typedef boost::iterator_range<iICODE> rSourceRange;
typedef boost::iterator_range<iICODE> rSourceRange; // typedef boost::iterator_range<InstListType::iterator> rTargetRange;
typedef boost::iterator_range<InstListType::iterator> rTargetRange; // rSourceRange m_low_level;
rSourceRange m_low_level; // rTargetRange m_middle_level;
rTargetRange m_middle_level; //};
};
// This is the icode array object. // This is the icode array object.
class CIcodeRec : public std::list<ICODE> class CIcodeRec : public std::list<ICODE>
{ {
public: public:
CIcodeRec(); // Constructor CIcodeRec(); // Constructor
ICODE * addIcode(ICODE *pIcode); ICODE * addIcode(const ICODE * pIcode);
void SetInBB(rCODE &rang, BB* pnewBB); void SetInBB(rCODE &rang, BB* pnewBB);
bool labelSrch(uint32_t target, uint32_t &pIndex); bool labelSrch(uint32_t target, uint32_t &pIndex);
iterator labelSrch(uint32_t target); iterator labelSrch(uint32_t target);

View File

@@ -6,14 +6,17 @@
*/ */
#pragma once #pragma once
#include "msvc_fixes.h"
#include "types.h"
#include "Enums.h"
#include "machine_x86.h"
#include <QtCore/QString>
#include <stdint.h> #include <stdint.h>
#include <vector> #include <vector>
#include <list> #include <list>
#include <set> #include <set>
#include <algorithm> #include <algorithm>
#include "types.h"
#include "Enums.h"
#include "machine_x86.h"
/* Type definition */ /* Type definition */
// this array has to stay in-order of addition i.e. not std::set<iICODE,std::less<iICODE> > // this array has to stay in-order of addition i.e. not std::set<iICODE,std::less<iICODE> >
@@ -99,14 +102,11 @@ public:
frameType loc; /* Frame location */ frameType loc; /* Frame location */
bool hasMacro; /* Identifier requires a macro */ bool hasMacro; /* Identifier requires a macro */
char macro[10]; /* Macro for this identifier */ char macro[10]; /* Macro for this identifier */
std::string name; /* Identifier's name */ QString name; /* Identifier's name */
union ID_UNION { /* Different types of identifiers */ union ID_UNION { /* Different types of identifiers */
friend struct ID;
protected:
LONG_STKID_TYPE longStkId; /* For TYPE_LONG_(UN)SIGN on the stack */ LONG_STKID_TYPE longStkId; /* For TYPE_LONG_(UN)SIGN on the stack */
public: eReg regi; /* For TYPE_BYTE(WORD)_(UN)SIGN registers */
eReg regi; /* For TYPE_BYTE(uint16_t)_(UN)SIGN registers */ struct { /* For TYPE_BYTE(WORD)_(UN)SIGN on the stack */
struct { /* For TYPE_BYTE(uint16_t)_(UN)SIGN on the stack */
uint8_t regOff; /* register offset (if any) */ uint8_t regOff; /* register offset (if any) */
int off; /* offset from BP */ int off; /* offset from BP */
} bwId; } bwId;
@@ -118,21 +118,22 @@ public:
} longKte; } longKte;
ID_UNION() { /*new (&longStkId) LONG_STKID_TYPE();*/} ID_UNION() { /*new (&longStkId) LONG_STKID_TYPE();*/}
} id; } id;
LONGID_TYPE & longId() {assert(isLong() && loc==REG_FRAME); return m_longId;}
const LONGID_TYPE & longId() const {assert(isLong() && loc==REG_FRAME); return m_longId;} LONGID_TYPE & longId() {assert(isLong() and loc==REG_FRAME); return m_longId;}
LONG_STKID_TYPE & longStkId() {assert(isLong() && loc==STK_FRAME); return id.longStkId;} const LONGID_TYPE & longId() const {assert(isLong() and loc==REG_FRAME); return m_longId;}
const LONG_STKID_TYPE & longStkId() const {assert(isLong() && loc==STK_FRAME); return id.longStkId;} 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();
ID(hlType t, frameType f); ID(hlType t, frameType f);
ID(hlType t, const LONGID_TYPE &s); ID(hlType t, const LONGID_TYPE &s);
ID(hlType t, const LONG_STKID_TYPE &s); ID(hlType t, const LONG_STKID_TYPE &s);
ID(hlType t, const LONGGLB_TYPE &s); ID(hlType t, const LONGGLB_TYPE &s);
bool isSigned() const { return (type==TYPE_BYTE_SIGN)||(type==TYPE_WORD_SIGN)||(type==TYPE_LONG_SIGN);} bool isSigned() const { return (type==TYPE_BYTE_SIGN) or (type==TYPE_WORD_SIGN) or (type==TYPE_LONG_SIGN);}
uint16_t typeBitsize() const uint16_t typeBitsize() const
{ {
return TypeContainer::typeSize(type)*8; return TypeContainer::typeSize(type)*8;
} }
bool isLong() const { return (type==TYPE_LONG_UNSIGN)||(type==TYPE_LONG_SIGN); } bool isLong() const { return (type==TYPE_LONG_UNSIGN) or (type==TYPE_LONG_SIGN); }
void setLocalName(int i) void setLocalName(int i)
{ {
char buf[32]; char buf[32];
@@ -164,7 +165,7 @@ public:
int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset); int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
void newIdent(hlType t, frameType f); void newIdent(hlType t, frameType f);
void flagByteWordId(int off); 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();} size_t csym() const {return id_arr.size();}
void newRegArg(iICODE picode, iICODE ticode) const; void newRegArg(iICODE picode, iICODE ticode) const;
void processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode, bool isLong) const; void processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode, bool isLong) const;

View File

@@ -1,9 +1,11 @@
#pragma once #pragma once
#include <QtCore/QString>
#include <stdint.h> #include <stdint.h>
#include <string>
#include <sstream>
#include <bitset> #include <bitset>
class QTextStream;
struct LivenessSet; struct LivenessSet;
/* Machine registers */ /* Machine registers */
enum eReg enum eReg
@@ -60,13 +62,13 @@ class Machine_X86 : public SourceMachine
public: public:
Machine_X86(); Machine_X86();
virtual ~Machine_X86() {} virtual ~Machine_X86() {}
static const std::string &regName(eReg r); static const QString & regName(eReg r);
static const std::string &opcodeName(unsigned r); static const QString & opcodeName(unsigned r);
static const std::string &floatOpName(unsigned r); static const QString & floatOpName(unsigned r);
bool physicalReg(eReg r); bool physicalReg(eReg r);
/* Writes the registers that are set in the bitvector */ /* Writes the registers that are set in the bitvector */
//TODO: move this into Machine_X86 ? //TODO: move this into Machine_X86 ?
static void writeRegVector (std::ostream &ostr,const LivenessSet &regi); static void writeRegVector (QTextStream & ostr, const LivenessSet &regi);
static eReg subRegH(eReg reg); static eReg subRegH(eReg reg);
static eReg subRegL(eReg reg); static eReg subRegL(eReg reg);
static bool isMemOff(eReg r); static bool isMemOff(eReg r);

3
include/msvc_fixes.h Normal file
View File

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

View File

@@ -1,38 +0,0 @@
#pragma once
/* Perfect hashing function library. Contains functions to generate perfect
hashing functions
* (C) Mike van Emmerik
*/
#include <stdint.h>
/* 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

@@ -1,67 +1,174 @@
#pragma once #pragma once
#include <string>
#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 "symtab.h" #include "symtab.h"
#include "BinaryImage.h" #include "BinaryImage.h"
#include "Procedure.h" #include "Procedure.h"
#include "state.h"
#include "src/Command.h"
#include <boost/icl/interval.hpp>
#include <boost/icl/interval_map.hpp>
#include <boost/icl/split_interval_map.hpp>
#include <QtCore/QString>
#include <list>
#include <unordered_set>
#include <unordered_map>
#include <string>
#include <stdint.h>
#include <assert.h>
class QString;
class SourceMachine; class SourceMachine;
struct CALL_GRAPH; struct CALL_GRAPH;
class IProject struct DosLoader;
{ struct SegOffAddr {
virtual PROG *binary()=0; uint16_t seg;
virtual const std::string & project_name() const =0; uint32_t addr;
virtual const std::string & binary_path() const =0;
}; };
class Project : public IProject enum CompilerVendor {
eUnknownVendor=0,
eBorland,
eMicrosoft,
eLogitech,
};
enum CompilerLanguage {
eUnknownLanguage=0,
eAnsiCorCPP,
ePascal,
eModula2
};
enum CompilerMemoryModel {
eUnknownMemoryModel=0,
eTiny,
eSmall,
eCompact,
eMedium,
eLarge
};
struct LoaderMetadata {
CompilerVendor compiler_vendor;
CompilerLanguage compiler_language;
CompilerMemoryModel compiler_memory_model;
int compiler_version;
QString compilerId() const {
switch(compiler_vendor) {
case eBorland:
switch(compiler_language) {
case eUnknownLanguage:
return QString("bx") + codeModelChar();
case eAnsiCorCPP:
return QString("b%1%2").arg(compiler_version).arg(codeModelChar());
case ePascal:
return QString("tp%1").arg(compiler_version);
default:
return "xxx";
}
case eMicrosoft:
assert(compiler_language==eAnsiCorCPP);
return QString("m%1%2").arg(compiler_version).arg(codeModelChar());
case eLogitech:
assert(compiler_language==eModula2);
return QString("l%1%2").arg(compiler_version).arg(codeModelChar());
case eUnknownVendor:
return "xxx";
}
return "xxx";
}
QChar codeModelChar() const {
switch(compiler_memory_model) {
case eUnknownMemoryModel: return 'x';
case eTiny: return 't';
case eSmall: return 's';
case eCompact: return 'c';
case eMedium: return 'm';
case eLarge: return 'l';
}
return 'x';
}
};
class Project : public QObject
{ {
static Project *s_instance; Q_OBJECT
std::string m_fname;
std::string m_project_name;
public: public:
DosLoader * m_selected_loader;
bool m_metadata_available=false;
LoaderMetadata m_loader_data;
uint32_t SynthLab; //!< Last snthetic lab idx
SYMTAB symtab; //!< Global symbol table
FunctionListType pProcList; //!< List of located functions
CALL_GRAPH * callGraph; //!< Pointer to the head of the call graph
STATE m_entry_state; //!< Machine state at program load
typedef llvm::iplist<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 */ PROG prog; /* Loaded program image parameters */
// no copies CommandStream m_project_command_stream;
std::unordered_map<PtrFunction,CommandStream> m_function_streams;
bool m_error_state;
struct PatternLocator *m_pattern_locator;
public:
// prevent Project instance copying
Project(const Project&) = delete; Project(const Project&) = delete;
const Project & operator=(const Project & l) =delete; const Project & operator=(const Project & l) =delete;
// only moves // only moves
Project(); // default constructor, Project(); // default constructor,
public: void create(const QString &a);
void create(const std::string & a);
const std::string &project_name() const {return m_project_name;} bool addLoadCommands(QString fname);
const std::string &binary_path() const {return m_fname;} void processAllCommands();
void resetCommandsAndErrorState();
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 funcIter(Function *to_find);
ilFunction findByEntry(uint32_t entry); PtrFunction findByEntry(uint32_t entry);
ilFunction createFunction(FunctionType *f,const std::string &name); PtrFunction findByName(const QString &name);
PtrFunction createFunction(FunctionType *f, const QString & name, SegOffAddr addr);
bool valid(ilFunction iter); bool valid(ilFunction iter);
int getSymIdxByAdd(uint32_t adr); int getSymIdxByAdd(uint32_t adr);
bool validSymIdx(size_t idx); bool validSymIdx(size_t idx);
size_t symbolSize(size_t idx); size_t symbolSize(size_t idx);
hlType symbolType(size_t idx); hlType symbolType(size_t idx);
const std::string &symbolName(size_t idx); const QString & symbolName(size_t idx);
const SYM & getSymByIdx(size_t idx) const; const SYM & getSymByIdx(size_t idx) const;
LoaderMetadata &getLoaderMetadata() { assert(m_metadata_available); return m_loader_data; }
void setLoaderMetadata(LoaderMetadata d) { m_loader_data = d; m_metadata_available=true;}
static Project * get(); static Project * get();
PROG * binary() {return &prog;} PROG * binary() {return &prog;}
SourceMachine *machine(); SourceMachine *machine();
const FunctionListType &functions() const { return pProcList; }
FunctionListType &functions() { return pProcList; }
bool addCommand(Command *cmd);
bool addCommand(PtrFunction f, Command *cmd); // Add function level command
bool hasCommands(const PtrFunction &f);
CommandStream *functionCommands(const PtrFunction &f);
void dumpAllErrors();
void setLoader(DosLoader *ins);
void processCommands(int count=1);
void processFunctionCommands(const PtrFunction & func, int count);
public slots:
void onCommandStreamFinished(bool state);
signals:
void newFunctionCreated(PtrFunction);
void functionUpdate(const PtrFunction &);
void loaderSelected();
void commandListChanged();
protected: protected:
void initialize(); void initialize();
void writeGlobSymTable(); void writeGlobSymTable();
protected:
static Project * s_instance;
QString m_fname;
QString m_project_name;
QString m_output_path;
CommandContext m_command_ctx;
}; };
//extern Project g_proj;

View File

@@ -3,15 +3,16 @@
* (C) Cristina Cifuentes, Mike van Emmerik * (C) Cristina Cifuentes, Mike van Emmerik
****************************************************************************/ ****************************************************************************/
#pragma once #pragma once
#include <stdint.h>
#include <cstring>
#include "machine_x86.h" #include "machine_x86.h"
#include <stdint.h>
#include <string.h>
/* STATE TABLE */ /* STATE TABLE */
struct STATE struct STATE
{ {
uint32_t IP; /* Offset into Image */ uint32_t IP; /* Offset into Image */
int16_t r[INDEX_BX_SI]; /* Value of segs and AX */ int16_t r[INDEX_BX_SI]; /* Register values */
bool f[INDEX_BX_SI]; /* True if r[.] has a value */ bool f[INDEX_BX_SI]; /* True if r[.] has a value */
struct struct
{ /* For case stmt indexed reg */ { /* For case stmt indexed reg */

View File

@@ -3,10 +3,17 @@
* (C) Mike van Emmerik * (C) Mike van Emmerik
*/ */
#pragma once #pragma once
#include <string>
#include <stdint.h>
#include "Enums.h" #include "Enums.h"
#include "types.h" #include "types.h"
#include "msvc_fixes.h"
#include <QtCore/QString>
#include <string>
#include <vector>
#include <stdint.h>
class QTextStream;
struct Expr; struct Expr;
struct AstIdent; struct AstIdent;
struct TypeContainer; struct TypeContainer;
@@ -15,7 +22,7 @@ struct TypeContainer;
/* * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * */
struct SymbolCommon 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 */ int size; /* Size/maximum size */
hlType type; /* probable type */ hlType type; /* probable type */
eDuVal duVal; /* DEF, USE, VAL */ eDuVal duVal; /* DEF, USE, VAL */
@@ -36,21 +43,14 @@ struct SYM : public SymbolCommon
struct STKSYM : public SymbolCommon struct STKSYM : public SymbolCommon
{ {
typedef int16_t tLabel; typedef int16_t tLabel;
Expr *actual; /* Expression tree of actual parameter */ Expr * actual=0; /* Expression tree of actual parameter */
AstIdent *regs; /* For register arguments only */ AstIdent * regs=0; /* For register arguments only */
tLabel label; /* Immediate off from BP (+:args, -:params) */ tLabel label=0; /* Immediate off from BP (+:args, -:params) */
uint8_t regOff; /* Offset is a register (e.g. SI, DI) */ uint8_t regOff=0; /* Offset is a register (e.g. SI, DI) */
bool hasMacro; /* This type needs a macro */ bool hasMacro=false; /* This type needs a macro */
std::string macro; /* Macro name */ QString macro; /* Macro name */
bool invalid; /* Boolean: invalid entry in formal arg list*/ bool invalid=false; /* Boolean: invalid entry in formal arg list*/
STKSYM() int arrayMembers=1; // for local variables if >1 marks this stack symbol as an array
{
actual=0;
regs=0;
label=0;
regOff=0;
invalid=hasMacro = false;
}
void setArgName(int i) void setArgName(int i)
{ {
char buf[32]; char buf[32];
@@ -86,7 +86,7 @@ public:
void updateSymType(uint32_t symbol, const TypeContainer &tc); void updateSymType(uint32_t symbol, const TypeContainer &tc);
SYM *updateGlobSym(uint32_t operand, int size, uint16_t duFlag, bool &inserted_new); SYM *updateGlobSym(uint32_t operand, int size, uint16_t duFlag, bool &inserted_new);
}; };
struct Function; class Function;
struct SYMTABLE struct SYMTABLE
{ {
std::string pSymName; /* Ptr to symbolic name or comment */ std::string pSymName; /* Ptr to symbolic name or comment */
@@ -99,19 +99,19 @@ struct SYMTABLE
{ {
// does not yse pSymName, to ease finding by symOff/symProc combo // does not yse pSymName, to ease finding by symOff/symProc combo
// in map<SYMTABLE,X> // in map<SYMTABLE,X>
return (symOff==other.symOff) && symProc==(other.symProc); return (symOff==other.symOff) and symProc==(other.symProc);
} }
}; };
enum tableType /* The table types */ enum tableType /* The table types */
{ {
Label=0, /* The label table */ Label=0, /* The label table */
Comment /* The comment table */ Comment, /* The comment table */
NUM_TABLE_TYPES /* Number of entries: must be last */
}; };
constexpr int NUM_TABLE_TYPES = int(Comment)+1; /* Number of entries: must be last */
void createSymTables(void); void createSymTables(void);
void destroySymTables(void); void destroySymTables(void);
bool 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 */ void selectTable(tableType); /* Select a particular table */

View File

@@ -5,9 +5,13 @@
*************************************************************************** ***************************************************************************
*/ */
#pragma once #pragma once
#include "Enums.h"
#include "msvc_fixes.h"
#include <cassert> #include <cassert>
#include <stdint.h> #include <stdint.h>
#include "Enums.h" #include <stdlib.h>
/**** Common definitions and macros ****/ /**** Common definitions and macros ****/
#define MAX 0x7FFFFFFF #define MAX 0x7FFFFFFF
@@ -64,12 +68,22 @@ struct eDuVal
use = x&USE; use = x&USE;
val = x&VAL; 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] = { static constexpr const char * hlTypes[13] = {
"", "char", "unsigned char", "int", "unsigned int", "",
"long", "unsigned long", "record", "int *", "char *", "char",
"", "float", "double" "unsigned char",
"int",
"unsigned int",
"long",
"unsigned long",
"record",
"int *",
"char *",
"",
"float",
"double"
}; };
struct TypeContainer struct TypeContainer
@@ -91,6 +105,8 @@ struct TypeContainer
return 4; return 4;
case TYPE_FLOAT: case TYPE_FLOAT:
return 4; return 4;
case TYPE_PTR:
return 2;
default: default:
return ~0; return ~0;
} }

BIN
prototypes/dcclibs.dat Normal file

Binary file not shown.

View File

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

BIN
sigs/dccb2s.sig Normal file

Binary file not shown.

BIN
sigs/dccb3l.sig Normal file

Binary file not shown.

BIN
sigs/dccb3s.SIG Normal file

Binary file not shown.

6
src/Address.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#include <stdint.h>
typedef uint32_t LinearAddress;
#define INVALID_ADDR Address(~0U)

60
src/AutomatedPlanner.cpp Normal file
View File

@@ -0,0 +1,60 @@
#include "AutomatedPlanner.h"
#include "project.h"
#include "FollowControlFlow.h"
#include <QtCore/QDebug>
/**
* @class AutomatedPlanner
* @brief Class responsible for building command lists
*
* The goal for top level [Project] plan is to build a fully decompiled representation of source binaries
*/
AutomatedPlanner::AutomatedPlanner()
{
}
/**
* @brief Given a state of a project, add actions that will advance the decompilation
* @param project
*/
void AutomatedPlanner::planFor(Project &project) {
// TODO: For now this logic is sprinkled all over the place, should move it here
// IF NO BINARY IMAGE LOADED - > add SelectImage/SelectProject command
// IF NO LOADER SELECTED -> add SelectLoader command
// ...
}
void AutomatedPlanner::planFor(Function & func) {
if(func.doNotDecompile())
return; // for functions marked as non-decompileable we don't add any commands
//TODO: Consider cases where commands are queued, but we can still plan some additional steps
bool function_has_commands = Project::get()->hasCommands(func.shared_from_this());
if(function_has_commands) {
qDebug() << "Function "<<func.name<<"still has some commands queued, planning skipped";
}
switch(func.nStep) {
case eNotDecoded:
addAction(func,new FollowControlFlow(func.state));
break;
case eDisassemblyInProgress:
// The command queue is empty and function is in eDisassemblyInProgress state ? Switch to eDisassembled
assert(false and "Not implemented yet");
break;
case eDissassembled:
// addAction(func,new LowLevelMarkImpure(func)
assert(false and "Not implemented yet");
break;
}
}
void AutomatedPlanner::addAction(Function & func, Command * cmd)
{
Project::get()->addCommand(func.shared_from_this(),cmd);
}
void AutomatedPlanner::addAction(Project & func, Command * cmd)
{
func.addCommand(cmd);
}

20
src/AutomatedPlanner.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef AUTOMATEDPLANNER_H
#define AUTOMATEDPLANNER_H
class Project;
class Function;
class Command;
class AutomatedPlanner
{
public:
AutomatedPlanner();
void planFor(Project & project);
void planFor(Function & func);
protected:
void addAction(Function &func,Command *cmd);
void addAction(Project &func,Command *cmd);
};
#endif // AUTOMATEDPLANNER_H

View File

@@ -1,11 +1,16 @@
#include "BasicBlock.h"
#include "msvc_fixes.h"
#include "Procedure.h"
#include "dcc.h"
#include "msvc_fixes.h"
#include <QtCore/QTextStream>
#include <cassert> #include <cassert>
#include <string> #include <string>
#include <boost/range/rbegin.hpp> #include <boost/range/rbegin.hpp>
#include <boost/range/rend.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 std;
using namespace boost; using namespace boost;
@@ -28,11 +33,11 @@ BB *BB::Create(const rCODE &r,eBBKind _nodeType, Function *parent)
pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail = pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail =
pnewBB->latchNode= pnewBB->loopFollow = NO_NODE; pnewBB->latchNode= pnewBB->loopFollow = NO_NODE;
pnewBB->instructions = r; pnewBB->instructions = r;
int addr = pnewBB->begin()->loc_ip;
/* Mark the basic block to which the icodes belong to, but only for /* 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(parent)
{ {
int addr = pnewBB->begin()->loc_ip;
//setInBB should automatically handle if our range is empty //setInBB should automatically handle if our range is empty
parent->Icode.SetInBB(pnewBB->instructions, pnewBB); parent->Icode.SetInBB(pnewBB->instructions, pnewBB);
@@ -40,10 +45,10 @@ BB *BB::Create(const rCODE &r,eBBKind _nodeType, Function *parent)
parent->m_ip_to_bb[addr] = pnewBB; parent->m_ip_to_bb[addr] = pnewBB;
parent->m_actual_cfg.push_back(pnewBB); parent->m_actual_cfg.push_back(pnewBB);
pnewBB->Parent = parent; pnewBB->Parent = parent;
}
if ( r.begin() != parent->Icode.end() ) /* Only for code BB's */ if ( r.begin() != parent->Icode.end() ) /* Only for code BB's */
stats.numBBbef++; stats.numBBbef++;
}
return pnewBB; return pnewBB;
} }
@@ -90,7 +95,7 @@ void BB::displayDfs()
dfsFirstNum, dfsLastNum, dfsFirstNum, dfsLastNum,
immedDom == MAX ? -1 : immedDom); immedDom == MAX ? -1 : immedDom);
printf("loopType = %s, loopHead = %d, latchNode = %d, follow = %d\n", printf("loopType = %s, loopHead = %d, latchNode = %d, follow = %d\n",
s_loopType[loopType], s_loopType[(int)loopType],
loopHead == MAX ? -1 : loopHead, loopHead == MAX ? -1 : loopHead,
latchNode == MAX ? -1 : latchNode, latchNode == MAX ? -1 : latchNode,
loopFollow == MAX ? -1 : loopFollow); loopFollow == MAX ? -1 : loopFollow);
@@ -136,12 +141,15 @@ void BB::displayDfs()
*/ */
ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, bool &repCond) 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]; latch = pProc->m_dfsLast[this->latchNode];
std::ostringstream ostr; QString ostr_contents;
QTextStream ostr(&ostr_contents);
ICODE* picode; ICODE* picode;
switch (loopType) switch (loopType)
{ {
case WHILE_TYPE: case eNodeHeaderType::WHILE_TYPE:
picode = &this->back(); picode = &this->back();
/* Check for error in while condition */ /* Check for error in while condition */
@@ -163,43 +171,45 @@ ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&lat
picode->hlU()->replaceExpr(picode->hl()->expr()->inverse()); picode->hlU()->replaceExpr(picode->hl()->expr()->inverse());
} }
{ {
string e=picode->hl()->expr()->walkCondExpr (pProc, numLoc); QString e=picode->hl()->expr()->walkCondExpr (pProc, numLoc);
ostr << "\n"<<indentStr(indLevel)<<"while ("<<e<<") {\n"; ostr << "\n"<<indentStr(indLevel)<<"while ("<<e<<") {\n";
} }
picode->invalidate(); picode->invalidate();
break; break;
case REPEAT_TYPE: case eNodeHeaderType::REPEAT_TYPE:
ostr << "\n"<<indentStr(indLevel)<<"do {\n"; ostr << "\n"<<indentStr(indLevel)<<"do {\n";
picode = &latch->back(); picode = &latch->back();
picode->invalidate(); picode->invalidate();
break; break;
case ENDLESS_TYPE: case eNodeHeaderType::ENDLESS_TYPE:
ostr << "\n"<<indentStr(indLevel)<<"for (;;) {\n"; ostr << "\n"<<indentStr(indLevel)<<"for (;;) {\n";
picode = &latch->back(); picode = &latch->back();
break;
} }
cCode.appendCode(ostr.str()); ostr.flush();
cCode.appendCode(ostr_contents);
stats.numHLIcode += 1; stats.numHLIcode += 1;
indLevel++; indLevel++;
return picode; return picode;
} }
bool BB::isEndOfPath(int latch_node_idx) const bool BB::isEndOfPath(int latch_node_idx) const
{ {
return nodeType == RETURN_NODE || nodeType == TERMINATE_NODE || return nodeType == RETURN_NODE or nodeType == TERMINATE_NODE or
nodeType == NOWHERE_NODE || (dfsLastNum == latch_node_idx); nodeType == NOWHERE_NODE or dfsLastNum == latch_node_idx;
} }
void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode, int _ifFollow) void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode, int _ifFollow)
{ {
int follow; /* 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 */ ICODE * picode; /* Pointer to HLI_JCOND instruction */
std::string l; /* Pointer to HLI_JCOND expression */ QString l; /* Pointer to HLI_JCOND expression */
bool emptyThen, /* THEN clause is empty */ bool emptyThen, /* THEN clause is empty */
repCond; /* Repeat condition for while() */ repCond; /* Repeat condition for while() */
/* Check if this basic block should be analysed */ /* 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; return;
if (wasTraversedAtLevel(DFS_ALPHA)) if (wasTraversedAtLevel(DFS_ALPHA))
@@ -209,17 +219,16 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
/* Check for start of loop */ /* Check for start of loop */
repCond = false; repCond = false;
latch = nullptr; latch = nullptr;
if (loopType)
{
picode=writeLoopHeader(indLevel, pProc, numLoc, latch, repCond); picode=writeLoopHeader(indLevel, pProc, numLoc, latch, repCond);
}
/* Write the code for this basic block */ /* Write the code for this basic block */
if (repCond == false) if (repCond == false)
{ {
std::ostringstream ostr; QString ostr_contents;
QTextStream ostr(&ostr_contents);
writeBB(ostr,indLevel, pProc, numLoc); writeBB(ostr,indLevel, pProc, numLoc);
cCode.appendCode(ostr.str()); ostr.flush();
cCode.appendCode(ostr_contents);
} }
/* Check for end of path */ /* Check for end of path */
@@ -227,12 +236,12 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
return; return;
/* Check type of loop/node and process code */ /* 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); assert(latch);
if (this != latch) /* loop is over several bbs */ if (this != latch) /* loop is over several bbs */
{ {
if (loopType == WHILE_TYPE) if (loopType == eNodeHeaderType::WHILE_TYPE)
{ {
succ = edges[THEN].BBptr; succ = edges[THEN].BBptr;
if (succ->dfsLastNum == loopFollow) if (succ->dfsLastNum == loopFollow)
@@ -248,9 +257,10 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
/* Loop epilogue: generate the loop trailer */ /* Loop epilogue: generate the loop trailer */
indLevel--; 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 /* Check if there is need to repeat other statements involved
* in while condition, then, emit the loop trailer */ * in while condition, then, emit the loop trailer */
if (repCond) if (repCond)
@@ -258,13 +268,14 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
writeBB(ostr,indLevel+1, pProc, numLoc); writeBB(ostr,indLevel+1, pProc, numLoc);
} }
ostr <<indentStr(indLevel)<< "} /* end of while */\n"; 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)); cCode.appendCode( "%s} /* end of loop */\n",indentStr(indLevel));
else if (loopType == REPEAT_TYPE) else if (loopType == eNodeHeaderType::REPEAT_TYPE)
{ {
string e = "//*failed*//"; QString e = "//*failed*//";
if (picode->hl()->opcode != HLI_JCOND) if (picode->hl()->opcode != HLI_JCOND)
{ {
reportError (REPEAT_FAIL); reportError (REPEAT_FAIL);
@@ -273,7 +284,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
{ {
e=picode->hl()->expr()->walkCondExpr (pProc, numLoc); e=picode->hl()->expr()->walkCondExpr (pProc, numLoc);
} }
cCode.appendCode( "%s} while (%s);\n", indentStr(indLevel),e.c_str()); cCode.appendCode( "%s} while (%s);\n", indentStr(indLevel),qPrintable(e));
} }
/* Recurse on the loop follow */ /* Recurse on the loop follow */
@@ -305,13 +316,13 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
if (succ->dfsLastNum != follow) /* THEN part */ if (succ->dfsLastNum != follow) /* THEN part */
{ {
l = writeJcond ( *back().hl(), pProc, numLoc); l = writeJcond ( *back().hl(), pProc, numLoc);
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l.c_str()); cCode.appendCode( "\n%s%s", indentStr(indLevel-1), qPrintable(l));
succ->writeCode (indLevel, pProc, numLoc, _latchNode,follow); succ->writeCode (indLevel, pProc, numLoc, _latchNode,follow);
} }
else /* empty THEN part => negate ELSE part */ else /* empty THEN part => negate ELSE part */
{ {
l = writeJcondInv ( *back().hl(), pProc, numLoc); l = writeJcondInv ( *back().hl(), pProc, numLoc);
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l.c_str()); cCode.appendCode( "\n%s%s", indentStr(indLevel-1), qPrintable(l));
edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, follow); edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, follow);
emptyThen = true; emptyThen = true;
} }
@@ -331,7 +342,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
} }
/* else (empty ELSE part) */ /* 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", cCode.appendCode( "%s}\n%selse {\n",
indentStr(indLevel-1), indentStr(indLevel - 1)); indentStr(indLevel-1), indentStr(indLevel - 1));
@@ -347,7 +358,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
else /* no follow => if..then..else */ else /* no follow => if..then..else */
{ {
l = writeJcond ( *back().hl(), pProc, numLoc); l = writeJcond ( *back().hl(), pProc, numLoc);
cCode.appendCode( "%s%s", indentStr(indLevel-1), l.c_str()); cCode.appendCode( "%s%s", indentStr(indLevel-1), qPrintable(l));
edges[THEN].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow); edges[THEN].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow);
cCode.appendCode( "%s}\n%selse {\n", indentStr(indLevel-1), indentStr(indLevel - 1)); cCode.appendCode( "%s}\n%selse {\n", indentStr(indLevel-1), indentStr(indLevel - 1));
edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow); edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow);
@@ -370,7 +381,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
* Args: pBB: pointer to the current basic block. * Args: pBB: pointer to the current basic block.
* Icode: pointer to the array of icodes for current procedure. * Icode: pointer to the array of icodes for current procedure.
* lev: indentation level - used for formatting. */ * 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 /* Save the index into the code table in case there is a later goto
* into this instruction (first instruction of the BB) */ * into this instruction (first instruction of the BB) */
@@ -380,10 +391,10 @@ void BB::writeBB(std::ostream &ostr,int lev, Function * pProc, int *numLoc)
for(ICODE &pHli : instructions) 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); QString line = pHli.hl()->write1HlIcode(pProc, numLoc);
if (!line.empty()) if (not line.isEmpty())
{ {
ostr<<indentStr(lev)<<line; ostr<<indentStr(lev)<<line;
stats.numHLIcode++; stats.numHLIcode++;

View File

@@ -1,13 +1,131 @@
SET(dcc_test_SOURCES set(dcc_LIB_SOURCES
tests/comwrite.cpp CallConvention.cpp
tests/project.cpp ast.cpp
tests/loader.cpp backend.cpp
bundle.cpp
chklib.cpp
comwrite.cpp
control.cpp
dataflow.cpp
disassem.cpp
DccFrontend.cpp
error.cpp
fixwild.cpp
graph.cpp
hlicode.cpp
hltype.cpp
machine_x86.cpp
icode.cpp
RegisterNode
idioms.cpp
idioms/idiom1.cpp
idioms/arith_idioms.cpp
idioms/call_idioms.cpp
idioms/epilogue_idioms.cpp
idioms/mov_idioms.cpp
idioms/neg_idioms.cpp
idioms/shift_idioms.cpp
idioms/xor_idioms.cpp
locident.cpp
liveness_set.cpp
parser.h
parser.cpp
procs.cpp
project.cpp
Procedure.cpp
proplong.cpp
reducible.cpp
scanner.cpp
symtab.cpp
udm.cpp
BasicBlock.cpp
dcc_interface.cpp
MemoryChunk
MemorySegment
MemorySegmentCoordinator
Command.cpp
Command.h
Loaders.cpp
Loaders.h
FollowControlFlow.cpp
FollowControlFlow.h
AutomatedPlanner
)
set(dcc_UI_SOURCES
ui/DccMainWindow.ui
ui/DccMainWindow.h
ui/DccMainWindow.cpp
ui/FunctionViewWidget.ui
ui/FunctionViewWidget.h
ui/FunctionViewWidget.cpp
ui/FunctionListDockWidget.ui
ui/FunctionListDockWidget.cpp
ui/FunctionListDockWidget.h
ui/RenderTags.cpp
ui/RenderTags.h
ui/CommandQueueView.cpp
ui/CommandQueueView.h
ui/CommandQueueView.ui
)
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
../include/error.h
../include/graph.h
../include/hlicode.h
../include/machine_x86.h
../include/icode.h
../include/idioms/idiom.h
../include/idioms/idiom1.h
../include/idioms/arith_idioms.h
../include/idioms/call_idioms.h
../include/idioms/epilogue_idioms.h
../include/idioms/mov_idioms.h
../include/idioms/neg_idioms.h
../include/idioms/shift_idioms.h
../include/idioms/xor_idioms.h
../include/locident.h
../include/CallConvention.h
../include/project.h
../include/scanner.h
../include/state.h
../include/symtab.h
../include/types.h
../include/Procedure.h
../include/StackFrame.h
../include/BasicBlock.h
../include/dcc_interface.h
) )
include_directories(${GMOCK_INCLUDE_DIRS} ${GMOCK_ROOT}/gtest/include)
add_executable(tester ${dcc_test_SOURCES})
ADD_DEPENDENCIES(tester dcc_lib)
target_link_libraries(tester dcc_lib disasm_s SOURCE_GROUP(Headers FILES ${dcc_HEADERS})
${GMOCK_BOTH_LIBRARIES} ${REQ_LLVM_LIBRARIES})
add_test(dcc-tests tester) set(dcc_SOURCES
dcc.cpp
)
SOURCE_GROUP(Source FILES ${dcc_SOURCES} ${dcc_LIB_SOURCES})
ADD_LIBRARY(dcc_lib STATIC ${dcc_LIB_SOURCES} ${dcc_HEADERS})
qt5_use_modules(dcc_lib Core)
ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_UI_SOURCES})
ADD_DEPENDENCIES(dcc_original dcc_lib)
TARGET_LINK_LIBRARIES(dcc_original dcc_lib dcc_hash disasm_s)
qt5_use_modules(dcc_original Core Widgets)
SET_PROPERTY(TARGET dcc_original PROPERTY CXX_STANDARD 11)
SET_PROPERTY(TARGET dcc_original PROPERTY CXX_STANDARD_REQUIRED ON)
if(dcc_build_tests)
ADD_SUBDIRECTORY(tests)
endif()

View File

@@ -1,17 +1,98 @@
#include <ostream>
#include <cassert>
#include "CallConvention.h" #include "CallConvention.h"
CConv *CConv::create(Type v) #include "Procedure.h"
#include <QtCore/QTextStream>
#include <ostream>
#include <cassert>
static void calculateReturnLocations(Function *func) {
switch(func->getReturnType()) {
case TYPE_LONG_SIGN:
case TYPE_LONG_UNSIGN:
func->getFunctionType()->setReturnLocation(LONGID_TYPE(rDX,rAX));
break;
case TYPE_WORD_SIGN:
case TYPE_WORD_UNSIGN:
func->getFunctionType()->setReturnLocation(rAX);
break;
case TYPE_BYTE_SIGN:
case TYPE_BYTE_UNSIGN:
func->getFunctionType()->setReturnLocation(rAL);
break;
}
}
static void calculateArgLocations_allOnStack(Function *func) {
FunctionType *type = func->type;
int stack_offset=2;
if(func->args.size() == type->ContainedTys.size())
return;
func->args.resize(type->ContainedTys.size());
func->args.numArgs=0;
for(Type & argtype : type->ContainedTys) {
STKSYM &arg(func->args[func->args.numArgs]);
arg.label= stack_offset;
arg.size = TypeContainer::typeSize(argtype.dcc_type);
arg.type = argtype.dcc_type;
arg.setArgName(func->args.numArgs);
stack_offset+=arg.size;
func->args.m_maxOff=stack_offset;
func->args.numArgs++;
}
func->cbParam = stack_offset;
}
static void rebuildArguments_FromStackLayout(Function *func) {
STKFRAME &stk(func->args);
std::map<int,const STKSYM *> arg_locations;
FunctionType *f;
for(const STKSYM & s: stk) {
if(s.label>0) {
arg_locations[s.label] = &s;
}
}
if(arg_locations.empty())
return;
std::vector<Type> argtypes;
auto stack_loc_iter = arg_locations.begin();
for(int i=stack_loc_iter->first; i<=arg_locations.rbegin()->first; ) {
int till_next_loc=stack_loc_iter->first-i;
if(till_next_loc==0) {
int entry_size=stack_loc_iter->second->size;
argtypes.push_back({stack_loc_iter->second->type});
i+=entry_size;
++stack_loc_iter;
} else {
if(till_next_loc>=4) {
argtypes.push_back({TYPE_LONG_SIGN});
i+=4;
} else if(till_next_loc>=2) {
argtypes.push_back({TYPE_WORD_SIGN});
i+=2;
} else {
argtypes.push_back({TYPE_BYTE_SIGN});
i+=1;
}
}
}
f = FunctionType::get({func->type->getReturnType()},argtypes,func->type->isVarArg());
f->retVal = func->type->retVal;
delete func->type;
func->type = f;
}
CConv *CConv::create(CC_Type v)
{ {
static C_CallingConvention *c_call = nullptr; static C_CallingConvention *c_call = nullptr;
static Pascal_CallingConvention *p_call = nullptr; static Pascal_CallingConvention *p_call = nullptr;
static Unknown_CallingConvention *u_call= nullptr; static Unknown_CallingConvention *u_call= nullptr;
if(!c_call) if(nullptr==c_call)
c_call = new C_CallingConvention; c_call = new C_CallingConvention;
if(!p_call) if(nullptr==p_call)
p_call = new Pascal_CallingConvention; p_call = new Pascal_CallingConvention;
if(!u_call) if(nullptr==u_call)
u_call = new Unknown_CallingConvention; u_call = new Unknown_CallingConvention;
switch(v) { switch(v) {
case UNKNOWN: return u_call; case UNKNOWN: return u_call;
@@ -22,15 +103,35 @@ CConv *CConv::create(Type v)
return nullptr; return nullptr;
} }
void C_CallingConvention::writeComments(std::ostream &ostr) void C_CallingConvention::writeComments(QTextStream & ostr)
{ {
ostr << " * C calling convention.\n"; ostr << " * C calling convention.\n";
} }
void Pascal_CallingConvention::writeComments(std::ostream &ostr)
void C_CallingConvention::calculateStackLayout(Function *func)
{
calculateReturnLocations(func);
rebuildArguments_FromStackLayout(func);
calculateArgLocations_allOnStack(func);
}
void Pascal_CallingConvention::writeComments(QTextStream & ostr)
{ {
ostr << " * Pascal calling convention.\n"; ostr << " * Pascal calling convention.\n";
} }
void Unknown_CallingConvention::writeComments(std::ostream &ostr) void Pascal_CallingConvention::calculateStackLayout(Function *func)
{
calculateReturnLocations(func);
//TODO: pascal args are passed in reverse order ?
rebuildArguments_FromStackLayout(func);
calculateArgLocations_allOnStack(func);
}
void Unknown_CallingConvention::writeComments(QTextStream & ostr)
{ {
ostr << " * Unknown calling convention.\n"; ostr << " * Unknown calling convention.\n";
} }
void Unknown_CallingConvention::calculateStackLayout(Function *func)
{
calculateReturnLocations(func);
rebuildArguments_FromStackLayout(func);
calculateArgLocations_allOnStack(func);
}

138
src/Command.cpp Normal file
View File

@@ -0,0 +1,138 @@
#include "Command.h"
#include "DccFrontend.h"
#include "dcc.h"
#include "project.h"
#include "Loaders.h"
#include <QFile>
bool LoaderSelection::execute(CommandContext * ctx)
{
Project *proj=ctx->m_project;
if(nullptr==proj) {
ctx->recordFailure(this,"No active project ");
return false;
}
if(m_filename.isEmpty()) {
ctx->recordFailure(this,"No executable path given to loader selector");
return false;
}
QFile finfo(m_filename);
/* Open the input file */
if(not finfo.open(QFile::ReadOnly)) {
ctx->recordFailure(this,QString("Cannot open file %1").arg(m_filename));
return false;
}
/* Read in first 2 bytes to check EXE signature */
if (finfo.size()<=2)
{
ctx->recordFailure(this,QString("File %1 is too small").arg(m_filename));
}
ComLoader com_loader;
ExeLoader exe_loader;
if(exe_loader.canLoad(finfo)) {
proj->setLoader(new ExeLoader);
return true;
}
if(com_loader.canLoad(finfo)) {
proj->setLoader(new ComLoader);
return true;
}
ctx->recordFailure(this,QString("None of the available loaders can load file %1").arg(m_filename));
return true;
}
bool LoaderApplication::execute(CommandContext * ctx)
{
Project *proj=ctx->m_project;
if(nullptr==proj) {
ctx->recordFailure(this,"No active project ");
return false;
}
if(!proj->m_selected_loader) {
ctx->recordFailure(this,QString("No loader selected for project %1").arg(proj->project_name()));
return false;
}
QFile finfo(m_filename);
if(not finfo.open(QFile::ReadOnly)) {
ctx->recordFailure(this,QString("Cannot open file %1").arg(m_filename));
return false;
}
bool load_res = proj->m_selected_loader->load(proj->prog,finfo);
if(!load_res) {
ctx->recordFailure(this,QString("Failure during load: %1").arg(m_filename));
return false;
}
if (option.verbose)
proj->prog.displayLoadInfo();
FunctionType *main_type = FunctionType::get(Type{TYPE_UNKNOWN},{ },false);
main_type->setCallingConvention(CConv::UNKNOWN);
/* Create initial procedure at program start address */
PROG &prog(proj->prog);
CreateFunction *cmd = new CreateFunction("start",
SegOffAddr {prog.segMain,((uint32_t)prog.initCS << 4) + prog.initIP},
main_type);
proj->addCommand(cmd);
return true;
}
bool CommandStream::add(Command * c) {
if(m_commands.size()>=m_maximum_command_count)
return false;
m_commands.push_back(c);
return true;
}
void CommandStream::setMaximumCommandCount(int maximum_command_count) {
m_maximum_command_count = maximum_command_count;
}
void CommandStream::processAll(CommandContext *ctx)
{
while(not m_commands.isEmpty()) {
Command *cmd = m_commands.takeFirst();
if(false==cmd->execute(ctx)) {
emit streamCompleted(false);
break;
}
m_recently_executed.push_back(cmd);
}
emit streamCompleted(true);
}
bool CommandStream::processOne(CommandContext *ctx)
{
if(not m_commands.isEmpty()) {
Command *cmd = m_commands.takeFirst();
if(false==cmd->execute(ctx)) {
emit streamChanged();
return false;
}
m_recently_executed.push_back(cmd);
}
emit streamChanged();
return true;
}
void CommandStream::clear()
{
qDeleteAll(m_commands);
qDeleteAll(m_recently_executed);
m_commands.clear();
m_recently_executed.clear();
}
void CommandContext::reset()
{
for(int i=0; i<m_failures.size(); ++i) {
delete m_failures[i].first;
}
m_failures.clear();
}

95
src/Command.h Normal file
View File

@@ -0,0 +1,95 @@
#ifndef COMMAND_H
#define COMMAND_H
#include <memory>
#include <QtCore/QObject>
#include <QtCore/QVector>
#include <QtCore/QPair>
class Project;
class Function;
typedef std::shared_ptr<Function> PtrFunction;
enum CommandLevel {
eProject,
eBinary,
eFunction,
eBasicBlock,
eInstruction
};
class Command;
class CommandContext {
public:
void recordFailure(Command *cmd,QString error_message) {
m_failures.push_back({cmd,error_message});
}
Project *m_project;
PtrFunction m_func;
QVector<QPair<Command *,QString>> m_failures;
void reset();
};
class Command
{
QString m_command_name;
CommandLevel m_level;
public:
Command(QString n,CommandLevel level) : m_command_name(n),m_level(level) {}
virtual ~Command() {}
QString name() const { return m_command_name;}
virtual QString instanceDescription() const { return m_command_name; }
virtual bool execute(CommandContext *) { return false; }
};
class CompoundCommand : public Command {
QVector<Command *> m_contained;
public:
CompoundCommand(QString n,CommandLevel l) : Command(n,l) {
}
void addCommand(Command *c) {
m_contained.push_back(c);
}
bool execute(CommandContext * ctx) {
for(Command * c : m_contained) {
if(!c->execute(ctx))
return false;
}
return true;
}
};
class CommandStream : public QObject
{
Q_OBJECT
int m_maximum_command_count=5;
public:
QVector<Command *> m_recently_executed;
QVector<Command *> m_commands;
bool add(Command *c);
void setMaximumCommandCount(int maximum_command_count);
bool processOne(CommandContext *ctx);
void processAll(CommandContext *ctx);
void clear();
bool isEmpty() const { return m_commands.isEmpty(); }
signals:
void streamCompleted(bool success);
void streamChanged();
};
// Effect: loader has been selected and set in current project
class LoaderSelection : public Command {
QString m_filename;
public:
virtual ~LoaderSelection() {}
LoaderSelection(QString f) : Command("Select loader",eProject),m_filename(f) {}
bool execute(CommandContext * ctx) override;
};
// trigger Project->m_selected_loader has changed
// Effect: the PROG object is loaded using the current loader
class LoaderApplication : public Command {
QString m_filename;
public:
virtual ~LoaderApplication() {}
LoaderApplication(QString f) : Command("Apply loader",eProject),m_filename(f) {}
bool execute(CommandContext * ctx) override;
};
#endif // COMMAND_H

230
src/DccFrontend.cpp Normal file
View File

@@ -0,0 +1,230 @@
#include "DccFrontend.h"
#include "Loaders.h"
#include "dcc.h"
#include "msvc_fixes.h"
#include "project.h"
#include "disassem.h"
#include "CallGraph.h"
#include "Command.h"
#include "chklib.h"
#include <QtCore/QFileInfo>
#include <QtCore/QDebug>
#include <cstdio>
//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(PtrFunction &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(PtrFunction &f : Project::get()->pProcList)
{
f->bindIcodeOff();
}
/* Print memory bitmap */
if (option.Map)
displayMemMap();
return(true); // we no longer own proj !
}
/*****************************************************************************
* LoadImage
****************************************************************************/
/* Parses the program, builds the call graph, and returns the list of
* procedures found */
void DccFrontend::parse(Project &proj)
{
/* Set initial state */
proj.addCommand(new MachineStateInitialization);
proj.addCommand(new FindMain);
}
bool MachineStateInitialization::execute(CommandContext *ctx)
{
assert(ctx && ctx->m_project);
Project &proj(*ctx->m_project);
const PROG &prog(proj.prog);
proj.m_entry_state.setState(rES, 0); /* PSP segment */
proj.m_entry_state.setState(rDS, 0);
proj.m_entry_state.setState(rCS, prog.initCS);
proj.m_entry_state.setState(rSS, prog.initSS);
proj.m_entry_state.setState(rSP, prog.initSP);
proj.m_entry_state.IP = ((uint32_t)prog.initCS << 4) + prog.initIP;
proj.SynthLab = SYNTHESIZED_MIN;
return true;
}
bool FindMain::execute(CommandContext *ctx) {
Project &proj(*ctx->m_project);
const PROG &prog(proj.prog);
PtrFunction start_func = proj.findByName("start");
if(ctx->m_project->m_entry_state.IP==0) {
ctx->recordFailure(this,"Cannot search for main func when no entry point was found");
return false;
}
/* Check for special settings of initial state, based on idioms of the startup code */
if(checkStartup(ctx->m_project->m_entry_state)) {
start_func->markDoNotDecompile(); // we have main, do not decompile the start proc
//TODO: main arguments and return values should depend on detected compiler/library
FunctionType *main_type = FunctionType::get(Type{TYPE_WORD_SIGN},{ Type{TYPE_WORD_SIGN},Type{TYPE_PTR} },false);
main_type->setCallingConvention(CConv::C);
proj.addCommand(new CreateFunction("main",SegOffAddr {prog.segMain,prog.offMain},main_type));
proj.addCommand(new LoadPatternLibrary());
} else {
start_func->state = proj.m_entry_state; // just in case we fail to find main, initialize 'state' for start func
}
return true;
}
QString CreateFunction::instanceDescription() const {
return QString("%1 \"%2\" @ 0x%3").arg(name()).arg(m_name).arg(m_addr.addr,0,16,QChar('0'));
}
bool CreateFunction::execute(CommandContext *ctx) {
Project &proj(*ctx->m_project);
const PROG &prog(proj.prog);
PtrFunction func = proj.createFunction(m_type,m_name,m_addr);
if(m_name=="main") {
/* In medium and large models, the segment of main may (will?) not be
the same as the initial CS segment (of the startup code) */
proj.m_entry_state.setState(rCS, prog.segMain);
proj.m_entry_state.IP = prog.offMain;
func->state = proj.m_entry_state;
}
if(m_name=="start") {
proj.addCommand(new MachineStateInitialization);
proj.addCommand(new FindMain);
}
// proj.addCommand(new ProcessFunction);
//proj.addCommand(new FollowControl());
/* Recursively build entire procedure list */
//proj.callGraph->proc->FollowCtrl(proj.callGraph, &proj.m_entry_state);
return true;
}

49
src/FollowControlFlow.cpp Normal file
View File

@@ -0,0 +1,49 @@
#include "FollowControlFlow.h"
#include "project.h"
#include "parser.h"
QString FollowControlFlow::instanceDescription() const
{
return name() + " @ 0x"+QString::number(m_start_state.IP,16);
}
bool FollowControlFlow::execute(CommandContext *ctx)
{
Project &proj(*ctx->m_project);
PtrFunction scanned_func(ctx->m_func);
scanned_func->switchState(eDisassemblyInProgress);
FollowCtrl(*scanned_func,proj.callGraph, &m_start_state);
return false;
}
QString MarkAsSwitchCase::instanceDescription() const
{
return name() + QString(" 0x%1 -> 0x%2 ; case %3")
.arg(m_src_addr,8,16,QChar('0'))
.arg(m_dst_addr,8,16,QChar('0'))
.arg(m_case_label);
}
bool MarkAsSwitchCase::execute(CommandContext * ctx)
{
//TODO: record code/data referneces in project for navigation UI purposes ?
auto switch_insn = ctx->m_func->Icode.labelSrch(m_src_addr);
if(switch_insn==ctx->m_func->Icode.end()) {
ctx->recordFailure(this,QString("switch instruction @ 0x%1 not found in procedure's instructions ?")
.arg(m_src_addr,8,16,QChar('0')));
return false;
}
auto insn = ctx->m_func->Icode.labelSrch(m_dst_addr);
if(insn==ctx->m_func->Icode.end()) {
ctx->recordFailure(this,QString("switch target instruction 0x%1 not found in procedure's instructions ?")
.arg(m_dst_addr,8,16,QChar('0')));
return false;
}
insn->ll()->caseEntry = m_case_label;
insn->ll()->setFlags(CASE);
switch_insn->ll()->caseTbl2.push_back( m_dst_addr );
return true;
}

39
src/FollowControlFlow.h Normal file
View File

@@ -0,0 +1,39 @@
#ifndef FOLLOWCONTROLFLOW_H
#define FOLLOWCONTROLFLOW_H
#include "Command.h"
#include "state.h"
class FollowControlFlow : public Command
{
STATE m_start_state;
public:
FollowControlFlow(STATE addr) : Command("Follow control flow",eFunction),m_start_state(addr) {}
// Command interface
public:
QString instanceDescription() const override;
bool execute(CommandContext *ctx) override;
};
// mark instruction at address m_dst_addr as a case m_case_label of switch located at m_src_addr
class MarkAsSwitchCase : public Command
{
uint32_t m_src_addr;
uint32_t m_dst_addr;
int m_case_label;
public:
MarkAsSwitchCase(uint32_t src_addr,uint32_t dst_addr,int lab) :
Command("Mark as switch case",eFunction),
m_src_addr(src_addr),
m_dst_addr(dst_addr),
m_case_label(lab)
{}
// Command interface
public:
QString instanceDescription() const override;
bool execute(CommandContext *ctx) override;
};
#endif // FOLLOWCONTROLFLOW_H

177
src/Loaders.cpp Normal file
View File

@@ -0,0 +1,177 @@
#include "Loaders.h"
#include "dcc.h"
#include <QtCore/QDebug>
#define EXE_RELOCATION 0x10 /* EXE images rellocated to above PSP */
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;
void DosLoader::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());
}
bool ComLoader::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 ComLoader::load(PROG & prog, QFile & fp) {
prog.fCOM = true;
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;
}
bool ExeLoader::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 ExeLoader::load(PROG & prog, QFile & fp) {
prog.fCOM = false;
/* 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;
}

31
src/Loaders.h Normal file
View File

@@ -0,0 +1,31 @@
#ifndef LOADERS_H
#define LOADERS_H
#include "BinaryImage.h"
#include <QtCore/QFile>
#include <stdlib.h>
struct DosLoader {
protected:
void prepareImage(PROG &prog,size_t sz,QFile &fp);
public:
virtual bool canLoad(QFile &fp)=0;
virtual QString loaderName() const =0;
virtual bool load(PROG &prog,QFile &fp)=0;
};
struct ComLoader : public DosLoader {
virtual ~ComLoader() {}
bool canLoad(QFile &fp) override;
bool load(PROG &prog,QFile &fp) override;
QString loaderName() const override { return "16-bit DOS - COM loader"; }
};
struct ExeLoader : public DosLoader {
virtual ~ExeLoader() {}
bool canLoad(QFile &fp) override;
bool load(PROG &prog,QFile &fp) override;
QString loaderName() const override { return "16-bit DOS - EXE loader"; }
};
#endif // LOADERS_H

22
src/MemoryChunk.cpp Normal file
View File

@@ -0,0 +1,22 @@
#include "MemoryChunk.h"
#include <boost/icl/interval.hpp>
#include <boost/icl/right_open_interval.hpp>
#include <boost/icl/left_open_interval.hpp>
#include <boost/icl/closed_interval.hpp>
#include <boost/icl/open_interval.hpp>
using namespace boost::icl;
MemoryChunk::MemoryChunk(LinearAddress start, LinearAddress fin) : m_start(start),m_fin(fin)
{
}
bool MemoryChunk::contains(LinearAddress addr) const
{
return addr>=m_start && addr<m_fin;
}
uint64_t MemoryChunk::size() const
{
return m_fin-m_start;
}

24
src/MemoryChunk.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef BYTECHUNK_H
#define BYTECHUNK_H
#include "Address.h"
#include <utility>
#include <inttypes.h>
/**
* @brief The MemoryChunk class represents a continuous range of Addresses
*/
class MemoryChunk
{
private:
LinearAddress m_start;
LinearAddress m_fin;
public:
MemoryChunk(LinearAddress start,LinearAddress fin);
bool contains(LinearAddress addr) const;
uint64_t size() const;
std::pair<LinearAddress,LinearAddress> bounds() const { return std::make_pair(m_start,m_fin); }
};
#endif // BYTECHUNK_H

5
src/MemorySegment.cpp Normal file
View File

@@ -0,0 +1,5 @@
#include "MemorySegment.h"
MemorySegment::MemorySegment(LinearAddress base, LinearAddress start, LinearAddress fin) : MemoryChunk(start,fin) {
m_base = base;
}

19
src/MemorySegment.h Normal file
View File

@@ -0,0 +1,19 @@
#pragma once
#include "MemoryChunk.h"
#include <QtCore/QString>
/**
* @brief The MemorySegment represents a single chunk of memory with additional properties.
*/
class MemorySegment : public MemoryChunk
{
uint16_t m_base;
int m_flags;
QString m_name;
public:
MemorySegment(LinearAddress base,LinearAddress start,LinearAddress fin);
const QString &getName() const { return m_name; }
void setName(const QString &v) { m_name = v; }
};

View File

@@ -0,0 +1,54 @@
#include "MemorySegmentCoordinator.h"
#include <boost/icl/interval_map.hpp>
#include <boost/icl/split_interval_map.hpp>
#include <utility>
using namespace boost::icl;
class MemorySegmentCoordinatorImpl {
boost::icl::interval_map<LinearAddress,SegmentHolder> m_segmentation_map;
public:
bool addSegment(LinearAddress base, LinearAddress start, LinearAddress fin, const char * name, int flags) {
if(start>fin)
return false;
if(start<base)
return false;
MemorySegment *seg = new MemorySegment(base,start,fin);
seg->setName(name);
//
auto segment_bounds(seg->bounds());
m_segmentation_map.add(std::make_pair(
interval<LinearAddress>::right_open(segment_bounds.first,segment_bounds.second),
seg)
);
return true;
}
uint32_t numberOfSegments() const { return interval_count(m_segmentation_map); }
const MemorySegment *get(LinearAddress addr) {
auto iter = m_segmentation_map.find(addr);
if(iter==m_segmentation_map.end()) {
return nullptr;
}
return iter->second;
}
};
MemorySegmentCoordinator::MemorySegmentCoordinator()
{
m_impl = new MemorySegmentCoordinatorImpl;
}
bool MemorySegmentCoordinator::addSegment(LinearAddress base, LinearAddress start, LinearAddress fin, const char * name, int flags)
{
return m_impl->addSegment(base,start,fin,name,flags);
}
uint32_t MemorySegmentCoordinator::size()
{
return m_impl->numberOfSegments();
}
MemorySegment *MemorySegmentCoordinator::getSegment(LinearAddress addr)
{
return const_cast<MemorySegment *>(m_impl->get(addr));
}

View File

@@ -0,0 +1,34 @@
#pragma once
#include "MemorySegment.h"
struct SegmentHolder {
SegmentHolder() : val(nullptr) {}
SegmentHolder(MemorySegment *inf) : val(inf) {}
MemorySegment *operator->() { return val;}
MemorySegment &operator*() const { return *val;}
operator MemorySegment *() { return val;}
operator const MemorySegment *() const { return val;}
SegmentHolder operator+=(const SegmentHolder &/*s*/) {
throw std::runtime_error("Cannot aggregate MemorySegments !");
}
MemorySegment *val;
};
/**
* @brief The MemorySegmentCoordinator class is responsible for:
* - Managing the lifetime of MemorySegments
* - Providing convenience functions for querying the segment-related data
*/
class MemorySegmentCoordinator
{
class MemorySegmentCoordinatorImpl *m_impl;
public:
MemorySegmentCoordinator();
bool addSegment(LinearAddress base,LinearAddress start,LinearAddress fin,const char *name,int flags);
uint32_t size();
MemorySegment *getSegment(LinearAddress addr);
};

View File

@@ -1,6 +1,12 @@
#include "Procedure.h" #include "Procedure.h"
#include "msvc_fixes.h"
#include "project.h" #include "project.h"
#include "scanner.h" #include "scanner.h"
#include "ui/StructuredTextTarget.h"
#include <QtCore/QDebug>
//FunctionType *Function::getFunctionType() const //FunctionType *Function::getFunctionType() const
//{ //{
// return &m_type; // return &m_type;
@@ -15,7 +21,7 @@ void JumpTable::pruneEntries(uint16_t cs)
for (uint32_t i = start; i < finish; i += 2) 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]);
if (target < finish && target >= start) if (target < finish and target >= start)
finish = target; finish = target;
else if (target >= (uint32_t)prg->cbImage) else if (target >= (uint32_t)prg->cbImage)
finish = i; finish = i;
@@ -25,13 +31,107 @@ void JumpTable::pruneEntries(uint16_t cs)
{ {
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 */ /* 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; finish = i;
} }
} }
void Function::callingConv(CConv::Type v) { void Function::callingConv(CConv::CC_Type v) {
m_call_conv=CConv::create(v); type->setCallingConvention(v);
getFunctionType()->m_call_conv->calculateStackLayout(this);
}
static QString sizeToPtrName(int size)
{
switch(size)
{
case 1:
return "BYTE ptr" ;
case 2:
return "WORD ptr";
case 4:
return "DWORD ptr";
}
return "UNKOWN ptr";
}
static void toStructuredText(STKFRAME &stk,IStructuredTextTarget *out, int level) {
int curlevel = 0;
int maxlevel = stk.m_maxOff - stk.m_minOff;
for(STKSYM & p : stk)
{
if (curlevel > p.label)
{
qWarning() << "error, var collapse!!!";
curlevel = p.label;
}
else if (curlevel < p.label)
{
out->addSpace(4);
out->prtt(QString("gap len = %1").arg(p.label - curlevel,0,16));
curlevel = p.label;
out->addEOL();
}
out->addSpace(4);
out->addTaggedString(XT_Symbol,p.name,&p);
out->prtt("equ");
out->addSpace();
out->prtt(sizeToPtrName(p.size));
out->addSpace();
if (p.arrayMembers>1)
{
out->addTaggedString(XT_Number,QString::number(p.arrayMembers,16));
out->prtt("dup (?)");
out->addSpace();
}
out->TAGbegin(XT_Number, NULL);
out->prtt(QString("%1h").arg(p.label,0,16));
out->TAGend(XT_Number);
out->addEOL();
curlevel += p.size * p.arrayMembers;
}
if (curlevel < maxlevel)
{
out->prtt(QString(" gap len = %1h").arg(maxlevel - curlevel,0,16));
}
}
extern void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level);
static void toStructuredText(ICODE &stk,IStructuredTextTarget *out, int level) {
if(level==0) {
toStructuredText(stk.ll(),out,level);
}
}
void Function::toStructuredText(IStructuredTextTarget *out, int level)
{
out->TAGbegin(XT_Function, this);
out->addTaggedString(XT_FuncName,name);
out->prtt(" proc");
out->addEOL();
::toStructuredText(args,out,level);
out->addEOL();
for(ICODE &ic : Icode) {
::toStructuredText(ic,out,level);
}
out->addTaggedString(XT_FuncName,name);
out->addSpace();
out->prtt("endp");
out->addEOL();
out->TAGend(XT_Function);
}
void FunctionType::setCallingConvention(CConv::CC_Type cc)
{
m_call_conv=CConv::create(cc);
assert(m_call_conv);
}
void Function::switchState(DecompilationStep s)
{
nStep = s;
} }

View File

@@ -1,19 +1,20 @@
#include "types.h"
#include "msvc_fixes.h"
#include "ast.h"
#include "bundle.h"
#include "machine_x86.h"
#include "project.h"
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <cassert> #include <cassert>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range.hpp> #include <boost/range.hpp>
#include <boost/range/adaptors.hpp>
//#include <boost/range/algorithm.hpp> //#include <boost/range/algorithm.hpp>
//#include <boost/assign.hpp> //#include <boost/assign.hpp>
#include "types.h"
#include "ast.h"
#include "bundle.h"
#include "machine_x86.h"
#include "project.h"
using namespace std; using namespace std;
using namespace boost::adaptors; using namespace boost::adaptors;
RegisterNode::RegisterNode(const LLOperand &op, LOCAL_ID *locsym) RegisterNode::RegisterNode(const LLOperand &op, LOCAL_ID *locsym)
@@ -41,7 +42,7 @@ RegisterNode::RegisterNode(const LLOperand &op, LOCAL_ID *locsym)
// ident.type(REGISTER); // ident.type(REGISTER);
// hlType type_sel; // hlType type_sel;
// regType reg_type; // regType reg_type;
// if ((icodeFlg & B) || (icodeFlg & SRC_B)) // if ((icodeFlg & B) or (icodeFlg & SRC_B))
// { // {
// type_sel = TYPE_BYTE_SIGN; // type_sel = TYPE_BYTE_SIGN;
// reg_type = BYTE_REG; // reg_type = BYTE_REG;
@@ -55,42 +56,42 @@ RegisterNode::RegisterNode(const LLOperand &op, LOCAL_ID *locsym)
// regiType = reg_type; // regiType = reg_type;
//} //}
string RegisterNode::walkCondExpr(Function *pProc, int *numLoc) const QString RegisterNode::walkCondExpr(Function *pProc, int *numLoc) const
{ {
std::ostringstream codeOut; QString codeOut;
std::ostringstream o; QString o;
assert(&pProc->localId==m_syms); assert(&pProc->localId==m_syms);
ID *id = &pProc->localId.id_arr[regiIdx]; ID *id = &pProc->localId.id_arr[regiIdx];
if (id->name[0] == '\0') /* no name */ if (id->name[0] == '\0') /* no name */
{ {
id->setLocalName(++(*numLoc)); id->setLocalName(++(*numLoc));
codeOut <<TypeContainer::typeName(id->type)<< " "<<id->name<<"; "; codeOut += QString("%1 %2; ").arg(TypeContainer::typeName(id->type)).arg(id->name);
codeOut <<"/* "<<Machine_X86::regName(id->id.regi)<<" */\n"; codeOut += QString("/* %1 */\n").arg(Machine_X86::regName(id->id.regi));
} }
if (id->hasMacro) if (id->hasMacro)
o << id->macro << "("<<id->name<<")"; o += QString("%1(%2)").arg(id->macro).arg(id->name);
else else
o << id->name; o += id->name;
cCode.appendDecl(codeOut.str()); cCode.appendDecl(codeOut);
return o.str(); return o;
} }
int RegisterNode::hlTypeSize(Function *) const int RegisterNode::hlTypeSize(Function *) const
{ {
if (regiType == BYTE_REG) if (regiType == BYTE_REG)
return (1); return 1;
else else
return (2); return 2;
} }
hlType RegisterNode::expType(Function *pproc) const hlType RegisterNode::expType(Function *pproc) const
{ {
if (regiType == BYTE_REG) if (regiType == BYTE_REG)
return (TYPE_BYTE_SIGN); return TYPE_BYTE_SIGN;
else else
return (TYPE_WORD_SIGN); return TYPE_WORD_SIGN;
} }
Expr *RegisterNode::insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym) Expr *RegisterNode::insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym)

View File

@@ -4,29 +4,32 @@
* Date: September 1993 * Date: September 1993
* (C) Cristina Cifuentes * (C) Cristina Cifuentes
*/ */
#include "ast.h"
#include "msvc_fixes.h"
#include "types.h"
#include "bundle.h"
#include "machine_x86.h"
#include "project.h"
#include <QtCore/QTextStream>
#include <boost/range.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/assign.hpp>
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <cassert> #include <cassert>
#include <boost/range.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/assign.hpp>
#include "types.h"
#include "ast.h"
#include "bundle.h"
#include "machine_x86.h"
#include "project.h"
using namespace std; using namespace std;
using namespace boost; using namespace boost;
using namespace boost::adaptors; using namespace boost::adaptors;
extern int strSize (const uint8_t *, char); extern int strSize (const uint8_t *, char);
extern char *cChar(uint8_t c); extern char *cChar(uint8_t c);
// Conditional operator symbols in C. Index by condOp enumeration type // Conditional operator symbols in C. Index by condOp enumeration type
static const char * const condOpSym[] = { " <= ", " < ", " == ", " != ", " > ", " >= ", static const char * const condOpSym[] = { " <= ", " < ", " == ", " != ", " > ", " >= ",
" & ", " | ", " ^ ", " ~ ", " & ", " | ", " ^ ", " ~ ",
@@ -130,7 +133,7 @@ GlobalVariable::GlobalVariable(int16_t segValue, int16_t off)
globIdx = i; globIdx = i;
} }
string GlobalVariable::walkCondExpr(Function *, int *) const QString GlobalVariable::walkCondExpr(Function *, int *) const
{ {
if(valid) if(valid)
return Project::get()->symtab[globIdx].name; return Project::get()->symtab[globIdx].name;
@@ -146,7 +149,7 @@ AstIdent *AstIdent::Loc(int off, LOCAL_ID *localId)
for (i = 0; i < localId->csym(); i++) for (i = 0; i < localId->csym(); i++)
{ {
const ID &lID(localId->id_arr[i]); const ID &lID(localId->id_arr[i]);
if ((lID.id.bwId.off == off) && (lID.id.bwId.regOff == 0)) if ((lID.id.bwId.off == off) and (lID.id.bwId.regOff == 0))
break; break;
} }
if (i == localId->csym()) if (i == localId->csym())
@@ -181,19 +184,17 @@ GlobalVariableIdx::GlobalVariableIdx (int16_t segValue, int16_t off, uint8_t reg
for (i = 0; i < locSym->csym(); i++) for (i = 0; i < locSym->csym(); i++)
{ {
const BWGLB_TYPE &lID(locSym->id_arr[i].id.bwGlb); const BWGLB_TYPE &lID(locSym->id_arr[i].id.bwGlb);
if ((lID.seg == segValue) && (lID.off == off) && (lID.regi == regi)) if ((lID.seg == segValue) and (lID.off == off) and (lID.regi == regi))
break; break;
} }
if (i == locSym->csym()) if (i == locSym->csym())
printf ("Error, indexed-glob var not found in local id table\n"); printf ("Error, indexed-glob var not found in local id table\n");
idxGlbIdx = i; idxGlbIdx = i;
} }
string GlobalVariableIdx::walkCondExpr(Function *pProc, int *) const QString GlobalVariableIdx::walkCondExpr(Function *pProc, int *) const
{ {
ostringstream o;
auto bwGlb = &pProc->localId.id_arr[idxGlbIdx].id.bwGlb; auto bwGlb = &pProc->localId.id_arr[idxGlbIdx].id.bwGlb;
o << (bwGlb->seg << 4) + bwGlb->off << "["<<Machine_X86::regName(bwGlb->regi)<<"]"; return QString("%1[%2]").arg((bwGlb->seg << 4) + bwGlb->off).arg(Machine_X86::regName(bwGlb->regi));
return o.str();
} }
@@ -221,7 +222,7 @@ AstIdent *AstIdent::Long(LOCAL_ID *localId, opLoc sd, iICODE pIcode, hlFirst f,
{ {
AstIdent *newExp; AstIdent *newExp;
/* Check for long constant and save it as a constant expression */ /* Check for long constant and save it as a constant expression */
if ((sd == SRC) && pIcode->ll()->testFlags(I)) /* constant */ if ((sd == SRC) and pIcode->ll()->srcIsImmed()) /* constant */
{ {
int value; int value;
if (f == HIGH_FIRST) if (f == HIGH_FIRST)
@@ -296,8 +297,8 @@ Expr *AstIdent::id(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_
const LLOperand &pm(*ll_insn.get(sd)); const LLOperand &pm(*ll_insn.get(sd));
if ( ((sd == DST) && ll_insn.testFlags(IM_DST)) or if ( ((sd == DST) and ll_insn.testFlags(IM_DST)) or
((sd == SRC) && ll_insn.testFlags(IM_SRC)) or ((sd == SRC) and ll_insn.testFlags(IM_SRC)) or
(sd == LHS_OP)) /* for MUL lhs */ (sd == LHS_OP)) /* for MUL lhs */
{ /* implicit dx:ax */ { /* implicit dx:ax */
idx = pProc->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(rDX, rAX), ix_); idx = pProc->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(rDX, rAX), ix_);
@@ -306,13 +307,13 @@ Expr *AstIdent::id(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_
duIcode.setRegDU (rAX, du); duIcode.setRegDU (rAX, du);
} }
else if ((sd == DST) && ll_insn.testFlags(IM_TMP_DST)) else if ((sd == DST) and ll_insn.testFlags(IM_TMP_DST))
{ /* implicit tmp */ { /* implicit tmp */
newExp = new RegisterNode(LLOperand(rTMP,2), &pProc->localId); newExp = new RegisterNode(LLOperand(rTMP,2), &pProc->localId);
duIcode.setRegDU(rTMP, (operDu)eUSE); duIcode.setRegDU(rTMP, (operDu)eUSE);
} }
else if ((sd == SRC) && ll_insn.testFlags(I)) /* constant */ else if ((sd == SRC) and ll_insn.srcIsImmed()) /* constant */
newExp = new Constant(ll_insn.src().getImm2(), 2); newExp = new Constant(ll_insn.src().getImm2(), 2);
else if (pm.regi == rUNDEF) /* global variable */ else if (pm.regi == rUNDEF) /* global variable */
newExp = new GlobalVariable(pm.segValue, pm.off); newExp = new GlobalVariable(pm.segValue, pm.off);
@@ -325,14 +326,14 @@ Expr *AstIdent::id(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_
else if (pm.off) /* offset */ else if (pm.off) /* offset */
{ // TODO: this is ABI specific, should be actually based on Function calling conv { // TODO: this is ABI specific, should be actually based on Function calling conv
if ((pm.seg == rSS) && (pm.regi == INDEX_BP)) /* idx on bp */ if ((pm.seg == rSS) and (pm.regi == INDEX_BP)) /* idx on bp */
{ {
if (pm.off >= 0) /* argument */ if (pm.off >= 0) /* argument */
newExp = AstIdent::Param (pm.off, &pProc->args); newExp = AstIdent::Param (pm.off, &pProc->args);
else /* local variable */ else /* local variable */
newExp = AstIdent::Loc (pm.off, &pProc->localId); newExp = AstIdent::Loc (pm.off, &pProc->localId);
} }
else if ((pm.seg == rDS) && (pm.regi == INDEX_BX)) /* bx */ else if ((pm.seg == rDS) and (pm.regi == INDEX_BX)) /* bx */
{ {
if (pm.off > 0) /* global variable */ if (pm.off > 0) /* global variable */
newExp = new GlobalVariableIdx(pm.segValue, pm.off, rBX,&pProc->localId); newExp = new GlobalVariableIdx(pm.segValue, pm.off, rBX,&pProc->localId);
@@ -345,9 +346,9 @@ Expr *AstIdent::id(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_
/**** check long ops, indexed global var *****/ /**** check long ops, indexed global var *****/
} }
else /* (pm->regi >= INDEXBASE && pm->off = 0) => indexed && no off */ else /* (pm->regi >= INDEXBASE and pm->off = 0) => indexed and no off */
{ {
if ((pm.seg == rDS) && (pm.regi > INDEX_BP_DI)) /* dereference */ if ((pm.seg == rDS) and (pm.regi > INDEX_BP_DI)) /* dereference */
{ {
eReg selected; eReg selected;
switch (pm.regi) { switch (pm.regi) {
@@ -376,13 +377,13 @@ condId LLInst::idType(opLoc sd) const
{ {
const LLOperand &pm((sd == SRC) ? src() : m_dst); const LLOperand &pm((sd == SRC) ? src() : m_dst);
if ((sd == SRC) && testFlags(I)) if ((sd == SRC) and srcIsImmed())
return (CONSTANT); return (CONSTANT);
else if (pm.regi == 0) else if (pm.regi == 0)
return (GLOB_VAR); return (GLOB_VAR);
else if ( pm.isReg() ) else if ( pm.isReg() )
return (REGISTER); return (REGISTER);
else if ((pm.seg == rSS) && (pm.regi == INDEX_BP)) else if ((pm.seg == rSS) and (pm.regi == INDEX_BP))
{ {
//TODO: which pm.seg/pm.regi pairs should produce PARAM/LOCAL_VAR ? //TODO: which pm.seg/pm.regi pairs should produce PARAM/LOCAL_VAR ?
if (pm.off >= 0) if (pm.off >= 0)
@@ -523,42 +524,40 @@ Expr * HlTypeSupport::performLongRemoval (eReg regi, LOCAL_ID *locId, Expr *tree
} }
/* Returns the string located in image, formatted in C format. */ /* Returns the string located in image, formatted in C format. */
static std::string getString (int offset) static QString getString (int offset)
{ {
PROG &prog(Project::get()->prog); PROG &prog(Project::get()->prog);
ostringstream o; QString o;
int strLen, i; int strLen, i;
strLen = strSize (&prog.image()[offset], '\0'); strLen = strSize (&prog.image()[offset], '\0');
o << '"'; o += '"';
for (i = 0; i < strLen; i++) for (i = 0; i < strLen; i++)
o<<cChar(prog.image()[offset+i]); o += cChar(prog.image()[offset+i]);
o << "\"\0"; o += "\"\0";
return (o.str()); return o;
} }
string BinaryOperator::walkCondExpr(Function * pProc, int* numLoc) const QString BinaryOperator::walkCondExpr(Function * pProc, int* numLoc) const
{ {
std::ostringstream outStr;
outStr << "(";
if(m_op!=NOT)
{
outStr << lhs()->walkCondExpr(pProc, numLoc);
}
assert(rhs()); assert(rhs());
outStr << condOpSym[m_op];
outStr << rhs()->walkCondExpr(pProc, numLoc); return QString("(%1%2%3)")
outStr << ")"; .arg((m_op!=NOT) ? lhs()->walkCondExpr(pProc, numLoc) : "")
return outStr.str(); .arg(condOpSym[m_op])
.arg(rhs()->walkCondExpr(pProc, numLoc));
} }
string AstIdent::walkCondExpr(Function *pProc, int *numLoc) const QString AstIdent::walkCondExpr(Function *pProc, int *numLoc) const
{ {
int16_t off; /* temporal - for OTHER */ int16_t off; /* temporal - for OTHER */
ID* id; /* Pointer to local identifier table */ ID* id; /* Pointer to local identifier table */
BWGLB_TYPE* bwGlb; /* Ptr to BWGLB_TYPE (global indexed var) */ BWGLB_TYPE* bwGlb; /* Ptr to BWGLB_TYPE (global indexed var) */
STKSYM * psym; /* Pointer to argument in the stack */ STKSYM * psym; /* Pointer to argument in the stack */
std::ostringstream outStr,codeOut; QString codeContents;
QString collectedContents;
QTextStream codeOut(&codeContents);
QTextStream o(&collectedContents);
std::ostringstream o;
switch (ident.idType) switch (ident.idType)
{ {
case LOCAL_VAR: case LOCAL_VAR:
@@ -587,7 +586,7 @@ string AstIdent::walkCondExpr(Function *pProc, int *numLoc) const
codeOut <<"/* "<<Machine_X86::regName(id->longId().h()) << ":" << codeOut <<"/* "<<Machine_X86::regName(id->longId().h()) << ":" <<
Machine_X86::regName(id->longId().l()) << " */\n"; Machine_X86::regName(id->longId().l()) << " */\n";
o << id->name; o << id->name;
pProc->localId.propLongId (id->longId().l(),id->longId().h(), id->name.c_str()); pProc->localId.propLongId (id->longId().l(),id->longId().h(), id->name);
} }
else /* GLB_FRAME */ else /* GLB_FRAME */
{ {
@@ -613,71 +612,55 @@ string AstIdent::walkCondExpr(Function *pProc, int *numLoc) const
} /* eos */ } /* eos */
outStr << o.str(); cCode.appendDecl(codeContents);
cCode.appendDecl(codeOut.str()); return collectedContents;
return outStr.str();
} }
string UnaryOperator::walkCondExpr(Function *pProc, int *numLoc) const QString UnaryOperator::wrapUnary(Function *pProc, int *numLoc,QChar op) const
{ {
std::ostringstream outStr; QString outStr = op;
bool needBracket=true; QString inner = unaryExp->walkCondExpr (pProc, numLoc);
if (unaryExp->m_type == IDENTIFIER)
outStr += inner;
else
outStr += "("+inner+')';
return outStr;
}
QString UnaryOperator::walkCondExpr(Function *pProc, int *numLoc) const
{
QString outStr;
switch(m_type) switch(m_type)
{ {
case NEGATION: case NEGATION:
if (unaryExp->m_type == IDENTIFIER) outStr+=wrapUnary(pProc,numLoc,'!');
{
needBracket = false;
outStr << "!";
}
else
outStr << "! (";
outStr << unaryExp->walkCondExpr (pProc, numLoc);
if (needBracket == true)
outStr << ")";
break; break;
case ADDRESSOF: case ADDRESSOF:
if (unaryExp->m_type == IDENTIFIER) outStr+=wrapUnary(pProc,numLoc,'&');
{
needBracket = false;
outStr << "&";
}
else
outStr << "&(";
outStr << unaryExp->walkCondExpr (pProc, numLoc);
if (needBracket == true)
outStr << ")";
break; break;
case DEREFERENCE: case DEREFERENCE:
outStr << "*"; outStr+=wrapUnary(pProc,numLoc,'*');
if (unaryExp->m_type == IDENTIFIER)
needBracket = false;
else
outStr << "(";
outStr << unaryExp->walkCondExpr (pProc, numLoc);
if (needBracket == true)
outStr << ")";
break; break;
case POST_INC: case POST_INC:
outStr << unaryExp->walkCondExpr (pProc, numLoc) << "++"; outStr += unaryExp->walkCondExpr (pProc, numLoc) + "++";
break; break;
case POST_DEC: case POST_DEC:
outStr << unaryExp->walkCondExpr (pProc, numLoc) << "--"; outStr += unaryExp->walkCondExpr (pProc, numLoc) + "--";
break; break;
case PRE_INC: case PRE_INC:
outStr << "++"<< unaryExp->walkCondExpr (pProc, numLoc); outStr += "++" + unaryExp->walkCondExpr (pProc, numLoc);
break; break;
case PRE_DEC: case PRE_DEC:
outStr << "--"<< unaryExp->walkCondExpr (pProc, numLoc); outStr += "--" + unaryExp->walkCondExpr (pProc, numLoc);
break; break;
} }
return outStr.str(); return outStr;
} }
/* Walks the conditional expression tree and returns the result on a string */ /* Walks the conditional expression tree and returns the result on a string */
@@ -877,7 +860,7 @@ Expr *AstIdent::performLongRemoval(eReg regi, LOCAL_ID *locId)
eReg AstIdent::otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl) eReg AstIdent::otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
{ {
ID *id = &locTbl->id_arr[idx]; ID *id = &locTbl->id_arr[idx];
if ((id->loc == REG_FRAME) && ((id->type == TYPE_LONG_SIGN) || if ((id->loc == REG_FRAME) and ((id->type == TYPE_LONG_SIGN) or
(id->type == TYPE_LONG_UNSIGN))) (id->type == TYPE_LONG_UNSIGN)))
{ {
if (id->longId().h() == regi) if (id->longId().h() == regi)
@@ -889,14 +872,12 @@ eReg AstIdent::otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
} }
string Constant::walkCondExpr(Function *, int *) const QString Constant::walkCondExpr(Function *, int *) const
{ {
ostringstream o;
if (kte.kte < 1000) if (kte.kte < 1000)
o << kte.kte; return QString::number(kte.kte);
else else
o << "0x"<<std::hex << kte.kte; return "0x" + QString::number(kte.kte,16);
return o.str();
} }
int Constant::hlTypeSize(Function *) const int Constant::hlTypeSize(Function *) const
@@ -909,17 +890,17 @@ hlType Constant::expType(Function *pproc) const
return TYPE_CONST; return TYPE_CONST;
} }
string FuncNode::walkCondExpr(Function *pProc, int *numLoc) const QString FuncNode::walkCondExpr(Function *pProc, int *numLoc) const
{ {
return pProc->writeCall(call.proc,*call.args, numLoc); return pProc->writeCall(call.proc,*call.args, numLoc);
} }
int FuncNode::hlTypeSize(Function *) const int FuncNode::hlTypeSize(Function *) const
{ {
return hlSize[call.proc->retVal.type]; return hlSize[call.proc->getReturnType()];
} }
hlType FuncNode::expType(Function *) const hlType FuncNode::expType(Function *) const
{ {
return call.proc->retVal.type; return call.proc->getReturnType();
} }

View File

@@ -4,10 +4,20 @@
* Purpose: Back-end module. Generates C code for each procedure. * Purpose: Back-end module. Generates C code for each procedure.
* (C) Cristina Cifuentes * (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 <cassert>
#include <string> #include <string>
#include <boost/range.hpp> #include <boost/range.hpp>
#include <boost/range/adaptors.hpp> #include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm.hpp> #include <boost/range/algorithm.hpp>
#include <fstream> #include <fstream>
@@ -15,15 +25,13 @@
#include <sstream> #include <sstream>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include "dcc.h"
#include "disassem.h"
#include "project.h"
#include "CallGraph.h"
using namespace boost; using namespace boost;
using namespace boost::adaptors; using namespace boost::adaptors;
bundle cCode; /* Procedure declaration and code */
using namespace std; using namespace std;
bundle cCode; /* Procedure declaration and code */
/* Returns a unique index to the next label */ /* Returns a unique index to the next label */
int getNextLabel() int getNextLabel()
{ {
@@ -35,14 +43,14 @@ int getNextLabel()
/* displays statistics on the subroutine */ /* displays statistics on the subroutine */
void Function::displayStats () void Function::displayStats ()
{ {
printf("\nStatistics - Subroutine %s\n", name.c_str()); qDebug() << "\nStatistics - Subroutine" << name;
printf ("Number of Icode instructions:\n"); qDebug() << "Number of Icode instructions:";
printf (" Low-level : %4d\n", stats.numLLIcode); qDebug() << " Low-level :" << stats.numLLIcode;
if (! (flg & PROC_ASM)) if (not (flg & PROC_ASM))
{ {
printf (" High-level: %4d\n", stats.numHLIcode); qDebug() << " High-level:"<<stats.numHLIcode;
printf (" Percentage reduction: %2.2f%%\n", 100.0 - (stats.numHLIcode * qDebug() << QString(" Percentage reduction: %1%%").arg(100.0 - (stats.numHLIcode *
100.0) / stats.numLLIcode); 100.0) / stats.numLLIcode,4,'f',2,QChar('0'));
} }
} }
@@ -100,7 +108,7 @@ char *cChar (uint8_t c)
* Note: to get to the value of the variable: * Note: to get to the value of the variable:
* com file: prog.Image[operand] * com file: prog.Image[operand]
* exe file: prog.Image[operand+0x100] */ * exe file: prog.Image[operand+0x100] */
static void printGlobVar (std::ostream &ostr,SYM * psym) static void printGlobVar (QTextStream &ostr,SYM * psym)
{ {
int j; int j;
PROG &prog(Project::get()->prog); PROG &prog(Project::get()->prog);
@@ -123,10 +131,10 @@ static void printGlobVar (std::ostream &ostr,SYM * psym)
break; break;
default: default:
{ {
ostringstream strContents; QString strContents;
for (j=0; j < psym->size; j++) for (j=0; j < psym->size; j++)
strContents << cChar(prog.image()[relocOp + j]); strContents += cChar(prog.image()[relocOp + j]);
ostr << "char\t*"<<psym->name<<" = \""<<strContents.str()<<"\";\n"; ostr << "char\t*"<<psym->name<<" = \""<<strContents<<"\";\n";
} }
} }
} }
@@ -137,7 +145,8 @@ static void printGlobVar (std::ostream &ostr,SYM * psym)
* initialization. */ * initialization. */
void Project::writeGlobSymTable() void Project::writeGlobSymTable()
{ {
std::ostringstream ostr; QString contents;
QTextStream ostr(&contents);
if (symtab.empty()) if (symtab.empty())
return; return;
@@ -161,19 +170,20 @@ void Project::writeGlobSymTable()
} }
} }
ostr<< "\n"; ostr<< "\n";
cCode.appendDecl( ostr.str() ); ostr.flush();
cCode.appendDecl( contents );
} }
/* Writes the header information and global variables to the output C file /* Writes the header information and global variables to the output C file
* fp. */ * fp. */
static void writeHeader (std::ostream &_ios, char *fileName) static void writeHeader (QIODevice &_ios, const std::string &fileName)
{ {
PROG &prog(Project::get()->prog); PROG &prog(Project::get()->prog);
/* Write header information */ /* Write header information */
cCode.init(); cCode.init();
cCode.appendDecl( "/*\n"); 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( " * File type\t: %s\n", (prog.fCOM)?"COM":"EXE");
cCode.appendDecl( " */\n\n#include \"dcc.h\"\n\n"); cCode.appendDecl( " */\n\n#include \"dcc.h\"\n\n");
@@ -204,10 +214,11 @@ static void emitFwdGotoLabel (ICODE * pt, int indLevel)
/* Writes the procedure's declaration (including arguments), local variables, /* Writes the procedure's declaration (including arguments), local variables,
* and invokes the procedure that writes the code of the given record *hli */ * 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; int numLoc;
ostringstream ostr; QString ostr_contents;
QTextStream ostr(&ostr_contents);
//STKFRAME * args; /* Procedure arguments */ //STKFRAME * args; /* Procedure arguments */
//char buf[200], /* Procedure's definition */ //char buf[200], /* Procedure's definition */
// arg[30]; /* One argument */ // arg[30]; /* One argument */
@@ -215,31 +226,28 @@ void Function::codeGen (std::ostream &fs)
/* Write procedure/function header */ /* Write procedure/function header */
cCode.init(); cCode.init();
if (flg & PROC_IS_FUNC) /* Function */ if (getReturnType() != TYPE_UNKNOWN) /* Function */
ostr<< "\n"<<TypeContainer::typeName(retVal.type)<<" "<<name<<" ("; ostr << QString("\n%1 %2 (").arg(TypeContainer::typeName(getReturnType())).arg(name);
else /* Procedure */ else /* Procedure */
ostr<< "\nvoid "<<name<<" ("; ostr << "\nvoid "+name+" (";
/* Write arguments */ /* Write arguments */
struct validArg struct validArg
{ {
bool operator()(STKSYM &s) { return s.invalid==false;} bool operator()(STKSYM &s) { return s.invalid==false;}
}; };
auto valid_args = args | filtered(validArg()); QStringList parts;
int count_valid = std::distance(valid_args.begin(),valid_args.end()); for (STKSYM &arg : (args | filtered(validArg())))
for (STKSYM &arg : valid_args)
{ {
ostr<<hlTypes[arg.type]<<" "<<arg.name; parts << QString("%1 %2").arg(hlTypes[arg.type]).arg(arg.name);
if(--count_valid!=0)
ostr<<", ";
} }
ostr<<")\n"; ostr << parts.join(", ")+")\n";
/* Write comments */ /* Write comments */
writeProcComments( ostr ); writeProcComments( ostr );
/* Write local variables */ /* Write local variables */
if (! (flg & PROC_ASM)) if (not (flg & PROC_ASM))
{ {
numLoc = 0; numLoc = 0;
for (ID &refId : localId ) for (ID &refId : localId )
@@ -250,8 +258,8 @@ void Function::codeGen (std::ostream &fs)
if (refId.loc == REG_FRAME) if (refId.loc == REG_FRAME)
{ {
/* Register variables are assigned to a local variable */ /* Register variables are assigned to a local variable */
if (((flg & SI_REGVAR) && (refId.id.regi == rSI)) || if (((flg & SI_REGVAR) and (refId.id.regi == rSI)) or
((flg & DI_REGVAR) && (refId.id.regi == rDI))) ((flg & DI_REGVAR) and (refId.id.regi == rDI)))
{ {
refId.setLocalName(++numLoc); refId.setLocalName(++numLoc);
ostr << "int "<<refId.name<<";\n"; ostr << "int "<<refId.name<<";\n";
@@ -267,12 +275,14 @@ void Function::codeGen (std::ostream &fs)
} }
} }
} }
fs<<ostr.str(); ostr.flush();
fs.write(ostr_contents.toLatin1());
/* Write procedure's code */ /* Write procedure's code */
if (flg & PROC_ASM) /* generate assembler */ if (flg & PROC_ASM) /* generate assembler */
{ {
Disassembler ds(3); Disassembler ds(3);
ds.disassem(this); ds.disassem(this->shared_from_this());
} }
else /* generate C */ else /* generate C */
{ {
@@ -284,36 +294,41 @@ void Function::codeGen (std::ostream &fs)
freeBundle (&cCode); freeBundle (&cCode);
/* Write Live register analysis information */ /* 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++) for (size_t i = 0; i < numBBs; i++)
{ {
pBB = m_dfsLast[i]; pBB = m_dfsLast[i];
if (pBB->flg & INVALID_BB) continue; /* skip invalid BBs */ if (pBB->flg & INVALID_BB) continue; /* skip invalid BBs */
cout << "BB "<<i<<"\n"; debug_stream << "BB "<<i<<"\n";
cout << " Start = "<<pBB->begin()->loc_ip; debug_stream << " Start = "<<pBB->begin()->loc_ip;
cout << ", end = "<<pBB->begin()->loc_ip+pBB->size()<<"\n"; debug_stream << ", end = "<<pBB->begin()->loc_ip+pBB->size()<<"\n";
cout << " LiveUse = "; debug_stream << " LiveUse = ";
Machine_X86::writeRegVector(cout,pBB->liveUse); Machine_X86::writeRegVector(debug_stream,pBB->liveUse);
cout << "\n Def = "; debug_stream << "\n Def = ";
Machine_X86::writeRegVector(cout,pBB->def); Machine_X86::writeRegVector(debug_stream,pBB->def);
cout << "\n LiveOut = "; debug_stream << "\n LiveOut = ";
Machine_X86::writeRegVector(cout,pBB->liveOut); Machine_X86::writeRegVector(debug_stream,pBB->liveOut);
cout << "\n LiveIn = "; debug_stream << "\n LiveIn = ";
Machine_X86::writeRegVector(cout,pBB->liveIn); Machine_X86::writeRegVector(debug_stream,pBB->liveIn);
cout <<"\n\n"; debug_stream <<"\n\n";
}
debug_stream.flush();
qDebug() << debug_contents.toLatin1();
} }
} }
/* Recursive procedure. Displays the procedure's code in depth-first order /* Recursive procedure. Displays the procedure's code in depth-first order
* of the call graph. */ * of the call graph. */
static void backBackEnd (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 */ // IFace.Yield(); /* This is a good place to yield to other apps */
/* Check if this procedure has been processed already */ /* 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)) (pcallGraph->proc->flg & PROC_ISLIB))
return; return;
pcallGraph->proc->flg |= PROC_OUTPUT; pcallGraph->proc->flg |= PROC_OUTPUT;
@@ -332,7 +347,7 @@ static void backBackEnd (CALL_GRAPH * pcallGraph, std::ostream &_ios)
/* Generate statistics */ /* Generate statistics */
if (option.Stats) if (option.Stats)
pcallGraph->proc->displayStats (); pcallGraph->proc->displayStats ();
if (! (pcallGraph->proc->flg & PROC_ASM)) if (not (pcallGraph->proc->flg & PROC_ASM))
{ {
stats.totalLL += stats.numLLIcode; stats.totalLL += stats.numLLIcode;
stats.totalHL += stats.numHLIcode; stats.totalHL += stats.numHLIcode;
@@ -341,22 +356,20 @@ static void backBackEnd (CALL_GRAPH * pcallGraph, std::ostream &_ios)
/* Invokes the necessary routines to produce code one procedure at a time. */ /* 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 */ /* Get output file name */
std::string outNam(fileName); QString outNam(Project::get()->output_name("b")); /* b for beta */
outNam = outNam.substr(0,outNam.rfind("."))+".b"; /* b for beta */ QFile fs(outNam); /* Output C file */
/* Open output file */ /* Open output file */
fs.open(outNam); if(not fs.open(QFile::WriteOnly|QFile::Text))
if(!fs.is_open()) fatalError (CANNOT_OPEN, outNam.toStdString().c_str());
fatalError (CANNOT_OPEN, outNam.c_str());
printf ("dcc: Writing C beta file %s\n", outNam.c_str()); qDebug()<<"dcc: Writing C beta file"<<outNam;
/* Header information */ /* Header information */
writeHeader (fs, option.filename); writeHeader (fs, option.filename.toStdString());
/* Initialize total Icode instructions statistics */ /* Initialize total Icode instructions statistics */
stats.totalLL = 0; stats.totalLL = 0;
@@ -367,7 +380,7 @@ void BackEnd (char *fileName, CALL_GRAPH * pcallGraph)
/* Close output file */ /* Close output file */
fs.close(); 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 <memory.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <QtCore/QIODevice>
#define deltaProcLines 20 #define deltaProcLines 20
using namespace std; using namespace std;
@@ -21,26 +21,26 @@ using namespace std;
* tab is removed and replaced by this label */ * tab is removed and replaced by this label */
void strTable::addLabelBundle (int idx, int label) void strTable::addLabelBundle (int idx, int label)
{ {
char s[16]; QString &processedLine(at(idx));
sprintf (s, "l%d: ", label); QString s = QString("l%1: ").arg(label);
if(at(idx).size()<4) if(processedLine.size()<4)
at(idx)=s; processedLine = s;
else 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. */ /* 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++) 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 /* Writes the contents of the bundle (procedure code and declaration) to
* a file. */ * a file. */
void writeBundle (std::ostream &ios, bundle procCode) void writeBundle (QIODevice &ios, bundle procCode)
{ {
writeStrTab (ios, procCode.decl); writeStrTab (ios, procCode.decl);
writeStrTab (ios, procCode.code); writeStrTab (ios, procCode.code);
@@ -70,7 +70,7 @@ void bundle::appendCode(const char *format,...)
code.push_back(buf); code.push_back(buf);
va_end (args); va_end (args);
} }
void bundle::appendCode(const std::string &s) void bundle::appendCode(const QString & s)
{ {
code.push_back(s); code.push_back(s);
} }
@@ -85,7 +85,7 @@ void bundle::appendDecl(const char *format,...)
va_end (args); va_end (args);
} }
void bundle::appendDecl(const std::string &v) void bundle::appendDecl(const QString &v)
{ {
decl.push_back(v); decl.push_back(v);
} }

File diff suppressed because it is too large Load Diff

51
src/chklib.h Normal file
View File

@@ -0,0 +1,51 @@
#ifndef CHKLIB_H
#define CHKLIB_H
#include "Command.h"
#include "Enums.h"
#include "perfhlib.h"
#include <QtCore/QFile>
#include <QtCore/QString>
#include <vector>
class Function;
// This will create a PatternLocator instance load it and pass it to project instance.
struct LoadPatternLibrary : public Command {
LoadPatternLibrary() : Command("Load patterns for the file",eProject) {}
bool execute(CommandContext *ctx) override;
};
class PatternLocator {
std::vector<hlType> pArg; /* Points to the array of param types */
QString pattern_id;
int numFunc=0; /* Number of func names actually stored */
int numArg=0; /* Number of param names actually stored */
public:
struct HT * ht =nullptr; //!< The hash table
struct PH_FUNC_STRUCT * pFunc=nullptr; //!< Points to the array of func names
PatternLocator(QString name) : pattern_id(name) {}
~PatternLocator();
bool load();
int searchPList(const char * name);
bool LibCheck(Function & pProc);
private:
bool readProtoFile();
PerfectHash g_pattern_hasher;
int numKeys=0; /* Number of hash table entries (keys) */
int numVert=0; /* Number of vertices in the graph (also size of g[]) */
unsigned PatLen=0; /* Size of the keys (pattern length) */
unsigned SymLen=0; /* Max size of the symbols, including null */
/* Pointers to start of T1, T2 */
uint16_t * T1base = nullptr;
uint16_t * T2base = nullptr;
uint16_t * g = nullptr; /* g[] */
};
extern bool checkStartup(struct STATE &state);
#endif // CHKLIB_H

View File

@@ -7,9 +7,12 @@
****************************************************************************/ ****************************************************************************/
#include "dcc.h" #include "dcc.h"
#include "msvc_fixes.h"
#include "machine_x86.h" #include "machine_x86.h"
#include <string.h> #include <string.h>
#include <sstream> #include <sstream>
#include <QTextStream>
using namespace std; using namespace std;
#define intSize 40 #define intSize 40
@@ -148,7 +151,7 @@ static const char *intOthers[] = {
/* Writes the description of the current interrupt. Appends it to the /* Writes the description of the current interrupt. Appends it to the
* string s. */ * string s. */
void LLInst::writeIntComment (std::ostringstream &s) void LLInst::writeIntComment (QTextStream &s)
{ {
uint32_t src_immed=src().getImm2(); uint32_t src_immed=src().getImm2();
s<<"\t/* "; s<<"\t/* ";
@@ -156,7 +159,7 @@ void LLInst::writeIntComment (std::ostringstream &s)
{ {
s <<int21h[m_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]; s <<intOthers[src_immed - 0x20];
} }
@@ -186,12 +189,15 @@ void LLInst::writeIntComment (std::ostringstream &s)
//, &cCode.decl //, &cCode.decl
void Function::writeProcComments() void Function::writeProcComments()
{ {
std::ostringstream ostr; QString dest_str;
{
QTextStream ostr(&dest_str);
writeProcComments(ostr); writeProcComments(ostr);
cCode.appendDecl(ostr.str()); }
cCode.appendDecl(dest_str);
} }
void Function::writeProcComments(std::ostream &ostr) void Function::writeProcComments(QTextStream &ostr)
{ {
int i; int i;
ID *id; /* Pointer to register argument identifier */ ID *id; /* Pointer to register argument identifier */
@@ -233,9 +239,9 @@ void Function::writeProcComments(std::ostream &ostr)
if (this->flg & PROC_ASM) if (this->flg & PROC_ASM)
{ {
ostr << " * Untranslatable routine. Assembler provided.\n"; ostr << " * Untranslatable routine. Assembler provided.\n";
if (this->flg & PROC_IS_FUNC) switch (getReturnType()) { // TODO: Functions return value in various regs
switch (this->retVal.type) { // TODO: Functions return value in various regs case TYPE_BYTE_SIGN:
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN: case TYPE_BYTE_UNSIGN:
ostr << " * Return value in register al.\n"; ostr << " * Return value in register al.\n";
break; break;
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN: case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
@@ -244,8 +250,11 @@ void Function::writeProcComments(std::ostream &ostr)
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN: case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
ostr << " * Return value in registers dx:ax.\n"; ostr << " * Return value in registers dx:ax.\n";
break; break;
case TYPE_UNKNOWN:
// void return type
break;
default: default:
fprintf(stderr,"Unknown retval type %d",this->retVal.type); fprintf(stderr,"Unknown retval type %d",getReturnType());
break; break;
} /* eos */ } /* eos */
} }

View File

@@ -2,6 +2,10 @@
* Description : Performs control flow analysis on the CFG * Description : Performs control flow analysis on the CFG
* (C) Cristina Cifuentes * (C) Cristina Cifuentes
********************************************************************/ ********************************************************************/
#include "dcc.h"
#include "msvc_fixes.h"
#include <boost/range/algorithm.hpp> #include <boost/range/algorithm.hpp>
#include <algorithm> #include <algorithm>
#include <list> #include <list>
@@ -10,15 +14,10 @@
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
#include "dcc.h"
//typedef struct list {
// int nodeIdx;
// struct list *next;
//} nodeList;
typedef std::list<int> nodeList; /* dfsLast index to the node */ typedef std::list<int> nodeList; /* dfsLast index to the node */
#define ancestor(a,b) ((a->dfsLastNum < b->dfsLastNum) && (a->dfsFirstNum < b->dfsFirstNum)) #define ancestor(a,b) ((a->dfsLastNum < b->dfsLastNum) and (a->dfsFirstNum < b->dfsFirstNum))
/* there is a path on the DFST from a to b if the a was first visited in a /* 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 * dfs, and a was later visited than b when doing the last visit of each
* node. */ * node. */
@@ -48,7 +47,7 @@ static int commonDom (int currImmDom, int predImmDom, Function * pProc)
if (predImmDom == NO_DOM) /* predecessor is the root */ if (predImmDom == NO_DOM) /* predecessor is the root */
return (currImmDom); return (currImmDom);
while ((currImmDom != NO_DOM) && (predImmDom != NO_DOM) && while ((currImmDom != NO_DOM) and (predImmDom != NO_DOM) and
(currImmDom != predImmDom)) (currImmDom != predImmDom))
{ {
if (currImmDom < predImmDom) if (currImmDom < predImmDom)
@@ -121,7 +120,7 @@ static void findEndlessFollow (Function * pProc, nodeList &loopNodes, BB * head)
for (TYPEADR_TYPE &typeaddr: pProc->m_dfsLast[loop_node]->edges) for (TYPEADR_TYPE &typeaddr: pProc->m_dfsLast[loop_node]->edges)
{ {
int succ = typeaddr.BBptr->dfsLastNum; int succ = typeaddr.BBptr->dfsLastNum;
if ((! inList(loopNodes, succ)) && (succ < head->loopFollow)) if ((not inList(loopNodes, succ)) and (succ < head->loopFollow))
head->loopFollow = succ; head->loopFollow = succ;
} }
} }
@@ -149,7 +148,7 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
continue; continue;
immedDom = pProc->m_dfsLast[i]->immedDom; immedDom = pProc->m_dfsLast[i]->immedDom;
if (inList (loopNodes, immedDom) && inInt(pProc->m_dfsLast[i], intNodes)) if (inList (loopNodes, immedDom) and inInt(pProc->m_dfsLast[i], intNodes))
{ {
insertList (loopNodes, i); insertList (loopNodes, i);
if (pProc->m_dfsLast[i]->loopHead == NO_NODE)/*not in other loop*/ if (pProc->m_dfsLast[i]->loopHead == NO_NODE)/*not in other loop*/
@@ -163,12 +162,12 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
/* Determine type of loop and follow node */ /* Determine type of loop and follow node */
intNodeType = head->nodeType; intNodeType = head->nodeType;
if (latchNode->nodeType == TWO_BRANCH) if (latchNode->nodeType == TWO_BRANCH)
if ((intNodeType == TWO_BRANCH) || (latchNode == head)) if ((intNodeType == TWO_BRANCH) or (latchNode == head))
if ((latchNode == head) || if ((latchNode == head) or
(inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum) && (inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum) and
inList (loopNodes, head->edges[ELSE].BBptr->dfsLastNum))) inList (loopNodes, head->edges[ELSE].BBptr->dfsLastNum)))
{ {
head->loopType = REPEAT_TYPE; head->loopType = eNodeHeaderType::REPEAT_TYPE;
if (latchNode->edges[0].BBptr == head) if (latchNode->edges[0].BBptr == head)
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum; head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
else else
@@ -177,7 +176,7 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
} }
else else
{ {
head->loopType = WHILE_TYPE; head->loopType = eNodeHeaderType::WHILE_TYPE;
if (inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum)) if (inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum))
head->loopFollow = head->edges[ELSE].BBptr->dfsLastNum; head->loopFollow = head->edges[ELSE].BBptr->dfsLastNum;
else else
@@ -186,7 +185,7 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
} }
else /* head = anything besides 2-way, latch = 2-way */ else /* head = anything besides 2-way, latch = 2-way */
{ {
head->loopType = REPEAT_TYPE; head->loopType = eNodeHeaderType::REPEAT_TYPE;
if (latchNode->edges[THEN].BBptr == head) if (latchNode->edges[THEN].BBptr == head)
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum; head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
else else
@@ -196,12 +195,12 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
else /* latch = 1-way */ else /* latch = 1-way */
if (latchNode->nodeType == LOOP_NODE) if (latchNode->nodeType == LOOP_NODE)
{ {
head->loopType = REPEAT_TYPE; head->loopType = eNodeHeaderType::REPEAT_TYPE;
head->loopFollow = latchNode->edges[0].BBptr->dfsLastNum; head->loopFollow = latchNode->edges[0].BBptr->dfsLastNum;
} }
else if (intNodeType == TWO_BRANCH) else if (intNodeType == TWO_BRANCH)
{ {
head->loopType = WHILE_TYPE; head->loopType = eNodeHeaderType::WHILE_TYPE;
pbb = latchNode; pbb = latchNode;
thenDfs = head->edges[THEN].BBptr->dfsLastNum; thenDfs = head->edges[THEN].BBptr->dfsLastNum;
elseDfs = head->edges[ELSE].BBptr->dfsLastNum; elseDfs = head->edges[ELSE].BBptr->dfsLastNum;
@@ -222,7 +221,7 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
* loop, so it is safer to consider it an endless loop */ * loop, so it is safer to consider it an endless loop */
if (pbb->dfsLastNum <= head->dfsLastNum) if (pbb->dfsLastNum <= head->dfsLastNum)
{ {
head->loopType = ENDLESS_TYPE; head->loopType = eNodeHeaderType::ENDLESS_TYPE;
findEndlessFollow (pProc, loopNodes, head); findEndlessFollow (pProc, loopNodes, head);
break; break;
} }
@@ -234,7 +233,7 @@ static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &int
} }
else else
{ {
head->loopType = ENDLESS_TYPE; head->loopType = eNodeHeaderType::ENDLESS_TYPE;
findEndlessFollow (pProc, loopNodes, head); findEndlessFollow (pProc, loopNodes, head);
} }
@@ -299,9 +298,9 @@ void Function::structLoops(derSeq *derivedG)
for (size_t i = 0; i < intHead->inEdges.size(); i++) for (size_t i = 0; i < intHead->inEdges.size(); i++)
{ {
pred = intHead->inEdges[i]; pred = intHead->inEdges[i];
if (inInt(pred, intNodes) && isBackEdge(pred, intHead)) if (inInt(pred, intNodes) and isBackEdge(pred, intHead))
{ {
if (! latchNode) if (nullptr == latchNode)
latchNode = pred; latchNode = pred;
else if (pred->dfsLastNum > latchNode->dfsLastNum) else if (pred->dfsLastNum > latchNode->dfsLastNum)
latchNode = pred; latchNode = pred;
@@ -314,7 +313,7 @@ void Function::structLoops(derSeq *derivedG)
/* Check latching node is at the same nesting level of case /* Check latching node is at the same nesting level of case
* statements (if any) and that the node doesn't belong to * statements (if any) and that the node doesn't belong to
* another loop. */ * another loop. */
if ((latchNode->caseHead == intHead->caseHead) && if ((latchNode->caseHead == intHead->caseHead) and
(latchNode->loopHead == NO_NODE)) (latchNode->loopHead == NO_NODE))
{ {
intHead->latchNode = latchNode->dfsLastNum; intHead->latchNode = latchNode->dfsLastNum;
@@ -353,7 +352,7 @@ static void tagNodesInCase (BB * pBB, nodeList &l, int head, int tail)
pBB->traversed = DFS_CASE; pBB->traversed = DFS_CASE;
current = pBB->dfsLastNum; current = pBB->dfsLastNum;
if ((current != tail) && (pBB->nodeType != MULTI_BRANCH) && (inList (l, pBB->immedDom))) if ((current != tail) and (pBB->nodeType != MULTI_BRANCH) and (inList (l, pBB->immedDom)))
{ {
insertList (l, current); insertList (l, current);
pBB->caseHead = head; pBB->caseHead = head;
@@ -385,7 +384,7 @@ void Function::structCases()
* the current header node, and is not a successor. */ * the current header node, and is not a successor. */
for (size_t j = i + 2; j < numBBs; j++) for (size_t j = i + 2; j < numBBs; j++)
{ {
if ((!successor(j, i, this)) && (m_dfsLast[j]->immedDom == i)) if ((not successor(j, i, this)) and (m_dfsLast[j]->immedDom == i))
{ {
if (exitNode == NO_NODE) if (exitNode == NO_NODE)
{ {
@@ -446,7 +445,7 @@ void Function::structIfs ()
if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */ if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */
continue; 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; followInEdges = 0;
follow = 0; follow = 0;
@@ -468,10 +467,10 @@ void Function::structIfs ()
/* Determine follow according to number of descendants /* Determine follow according to number of descendants
* immediately dominated by this node */ * immediately dominated by this node */
if ((follow != 0) && (followInEdges > 1)) if ((follow != 0) and (followInEdges > 1))
{ {
currNode->ifFollow = follow; currNode->ifFollow = follow;
if (!unresolved.empty()) if (not unresolved.empty())
flagNodes (unresolved, follow, this); flagNodes (unresolved, follow, this);
} }
else else
@@ -617,33 +616,33 @@ void Function::compoundCond()
change = true; //assume change change = true; //assume change
/* Check (X || Y) case */ /* Check (X or Y) case */
if ((thenBB->nodeType == TWO_BRANCH) && (thenBB->numHlIcodes == 1) && if ((thenBB->nodeType == TWO_BRANCH) and (thenBB->numHlIcodes == 1) and
(thenBB->inEdges.size() == 1) && (thenBB->edges[ELSE].BBptr == elseBB)) (thenBB->inEdges.size() == 1) and (thenBB->edges[ELSE].BBptr == elseBB))
{ {
if(Case_X_or_Y(pbb, thenBB, elseBB)) if(Case_X_or_Y(pbb, thenBB, elseBB))
--i; --i;
} }
/* Check (!X && Y) case */ /* Check (not X and Y) case */
else if ((thenBB->nodeType == TWO_BRANCH) && (thenBB->numHlIcodes == 1) && else if ((thenBB->nodeType == TWO_BRANCH) and (thenBB->numHlIcodes == 1) and
(thenBB->inEdges.size() == 1) && (thenBB->edges[THEN].BBptr == elseBB)) (thenBB->inEdges.size() == 1) and (thenBB->edges[THEN].BBptr == elseBB))
{ {
if(Case_notX_and_Y(pbb, thenBB, elseBB)) if(Case_notX_and_Y(pbb, thenBB, elseBB))
--i; --i;
} }
/* Check (X && Y) case */ /* Check (X and Y) case */
else if ((elseBB->nodeType == TWO_BRANCH) && (elseBB->numHlIcodes == 1) && else if ((elseBB->nodeType == TWO_BRANCH) and (elseBB->numHlIcodes == 1) and
(elseBB->inEdges.size()==1) && (elseBB->edges[THEN].BBptr == thenBB)) (elseBB->inEdges.size()==1) and (elseBB->edges[THEN].BBptr == thenBB))
{ {
if(Case_X_and_Y(pbb, thenBB, elseBB )) if(Case_X_and_Y(pbb, thenBB, elseBB ))
--i; --i;
} }
/* Check (!X || Y) case */ /* Check (not X or Y) case */
else if ((elseBB->nodeType == TWO_BRANCH) && (elseBB->numHlIcodes == 1) && else if ((elseBB->nodeType == TWO_BRANCH) and (elseBB->numHlIcodes == 1) and
(elseBB->inEdges.size() == 1) && (elseBB->edges[ELSE].BBptr == thenBB)) (elseBB->inEdges.size() == 1) and (elseBB->edges[ELSE].BBptr == thenBB))
{ {
if(Case_notX_or_Y(pbb, thenBB, elseBB )) if(Case_notX_or_Y(pbb, thenBB, elseBB ))
--i; --i;

View File

@@ -4,18 +4,22 @@
* Purpose: Data flow analysis module. * Purpose: Data flow analysis module.
* (C) Cristina Cifuentes * (C) Cristina Cifuentes
****************************************************************************/ ****************************************************************************/
#include "dcc.h"
#include "project.h"
#include "msvc_fixes.h"
#include <boost/range.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/assign.hpp>
#include <stdint.h> #include <stdint.h>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <cstdio> #include <cstdio>
#include <boost/range.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/assign.hpp>
#include "dcc.h"
#include "project.h"
using namespace boost; using namespace boost;
using namespace boost::adaptors; using namespace boost::adaptors;
struct ExpStack struct ExpStack
@@ -28,7 +32,7 @@ struct ExpStack
void push(Expr *); void push(Expr *);
Expr * pop(); Expr * pop();
Expr * top() const { Expr * top() const {
if(!expStk.empty()) if(not expStk.empty())
return expStk.back(); return expStk.back();
return nullptr; return nullptr;
} }
@@ -143,10 +147,9 @@ void Function::elimCondCodes ()
//auto reversed_instructions = pBB->range() | reversed; //auto reversed_instructions = pBB->range() | reversed;
for (useAt = pBB->rbegin(); useAt != pBB->rend(); useAt++) for (useAt = pBB->rbegin(); useAt != pBB->rend(); useAt++)
{ {
ICODE &useIcode(*useAt);
llIcode useAtOp = llIcode(useAt->ll()->getOpcode()); llIcode useAtOp = llIcode(useAt->ll()->getOpcode());
use = useAt->ll()->flagDU.u; use = useAt->ll()->flagDU.u;
if ((useAt->type != LOW_LEVEL) || ( ! useAt->valid() ) || ( 0 == use )) if ((useAt->type != LOW_LEVEL_ICODE) or ( not useAt->valid() ) or ( 0 == use ))
continue; continue;
/* Find definition within the same basic block */ /* Find definition within the same basic block */
defAt=useAt; defAt=useAt;
@@ -159,8 +162,7 @@ void Function::elimCondCodes ()
continue; continue;
notSup = false; notSup = false;
LLOperand *dest_ll = defIcode.ll()->get(DST); LLOperand *dest_ll = defIcode.ll()->get(DST);
LLOperand *src_ll = defIcode.ll()->get(SRC); if ((useAtOp >= iJB) and (useAtOp <= iJNS))
if ((useAtOp >= iJB) && (useAtOp <= iJNS))
{ {
iICODE befDefAt = (++riICODE(defAt)).base(); iICODE befDefAt = (++riICODE(defAt)).base();
switch (defIcode.ll()->getOpcode()) switch (defIcode.ll()->getOpcode())
@@ -196,7 +198,7 @@ void Function::elimCondCodes ()
reportError (JX_NOT_DEF, defIcode.ll()->getOpcode()); reportError (JX_NOT_DEF, defIcode.ll()->getOpcode());
flg |= PROC_ASM; /* generate asm */ flg |= PROC_ASM; /* generate asm */
} }
if (! notSup) if (not notSup)
{ {
assert(lhs); assert(lhs);
assert(rhs); assert(rhs);
@@ -221,14 +223,14 @@ void Function::elimCondCodes ()
{ {
ICODE &a(*defAt); ICODE &a(*defAt);
ICODE &b(*useAt); ICODE &b(*useAt);
reportError (NOT_DEF_USE,a.ll()->getOpcode(),b.ll()->getOpcode()); reportError (NOT_DEF_USE,a.ll()->label,a.ll()->getOpcode(),b.ll()->getOpcode());
flg |= PROC_ASM; /* generate asm */ flg |= PROC_ASM; /* generate asm */
} }
break; break;
} }
/* Check for extended basic block */ /* Check for extended basic block */
if ((pBB->size() == 1) &&(useAtOp >= iJB) && (useAtOp <= iJNS)) if ((pBB->size() == 1) and(useAtOp >= iJB) and (useAtOp <= iJNS))
{ {
ICODE & _prev(pBB->back()); /* For extended basic blocks - previous icode inst */ ICODE & _prev(pBB->back()); /* For extended basic blocks - previous icode inst */
if (_prev.hl()->opcode == HLI_JCOND) if (_prev.hl()->opcode == HLI_JCOND)
@@ -270,7 +272,7 @@ void Function::genLiveKtes ()
continue; // skip invalid BBs continue; // skip invalid BBs
for(ICODE &insn : *pbb) for(ICODE &insn : *pbb)
{ {
if ((insn.type == HIGH_LEVEL) && ( insn.valid() )) if ((insn.type == HIGH_LEVEL_ICODE) and ( insn.valid() ))
{ {
liveUse |= (insn.du.use - def); liveUse |= (insn.du.use - def);
def |= insn.du.def; def |= insn.du.def;
@@ -320,12 +322,12 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
pbb->liveOut = in_liveOut; pbb->liveOut = in_liveOut;
/* Get return expression of function */ /* Get return expression of function */
if (flg & PROC_IS_FUNC) if (getReturnType()!=TYPE_UNKNOWN)
{ {
auto picode = pbb->rbegin(); /* icode of function return */ auto picode = pbb->rbegin(); /* icode of function return */
if (picode->hl()->opcode == HLI_RET) if (picode->hl()->opcode == HLI_RET)
{ {
picode->hlU()->expr(AstIdent::idID(&retVal, &localId, (++pbb->rbegin()).base())); picode->hlU()->expr(AstIdent::idID(&type->retVal, &localId, (++pbb->rbegin()).base()));
picode->du.use = in_liveOut; picode->du.use = in_liveOut;
} }
} }
@@ -344,7 +346,7 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
pcallee = ticode.hl()->call.proc; pcallee = ticode.hl()->call.proc;
/* user/runtime routine */ /* user/runtime routine */
if (! (pcallee->flg & PROC_ISLIB)) if (not (pcallee->flg & PROC_ISLIB))
{ {
if (pcallee->liveAnal == false) /* hasn't been processed */ if (pcallee->liveAnal == false) /* hasn't been processed */
pcallee->dataFlow (pbb->liveOut); pcallee->dataFlow (pbb->liveOut);
@@ -352,7 +354,7 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
} }
else /* library routine */ else /* library routine */
{ {
if ( (pcallee->flg & PROC_IS_FUNC) && /* returns a value */ if ( (pcallee->getReturnType()!=TYPE_UNKNOWN) and /* returns a value */
(pcallee->liveOut & pbb->edges[0].BBptr->liveIn).any() (pcallee->liveOut & pbb->edges[0].BBptr->liveIn).any()
) )
pbb->liveOut = pcallee->liveOut; pbb->liveOut = pcallee->liveOut;
@@ -360,10 +362,11 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
pbb->liveOut.reset(); pbb->liveOut.reset();
} }
if ((! (pcallee->flg & PROC_ISLIB)) || ( pbb->liveOut.any() )) if ((not (pcallee->flg & PROC_ISLIB)) or ( pbb->liveOut.any() ))
{ {
switch (pcallee->retVal.type) { switch (pcallee->getReturnType()) {
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN: case TYPE_LONG_SIGN:
case TYPE_LONG_UNSIGN:
ticode.du1.setDef(rAX).addDef(rDX); ticode.du1.setDef(rAX).addDef(rDX);
//TODO: use Calling convention to properly set regs here //TODO: use Calling convention to properly set regs here
break; break;
@@ -387,7 +390,7 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
pbb->liveIn = LivenessSet(pbb->liveUse + (pbb->liveOut - pbb->def)); pbb->liveIn = LivenessSet(pbb->liveUse + (pbb->liveOut - pbb->def));
/* Check if live sets have been modified */ /* Check if live sets have been modified */
if ((prevLiveIn != pbb->liveIn) || (prevLiveOut != pbb->liveOut)) if ((prevLiveIn != pbb->liveIn) or (prevLiveOut != pbb->liveOut))
change = true; change = true;
} }
} }
@@ -414,9 +417,9 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
* register */ * register */
bool BB::FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at) bool BB::FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at)
{ {
if ((regi == rDI) && (flg & DI_REGVAR)) if ((regi == rDI) and (flg & DI_REGVAR))
return true; return true;
if ((regi == rSI) && (flg & SI_REGVAR)) if ((regi == rSI) and (flg & SI_REGVAR))
return true; return true;
if (distance(start_at,end())>1) /* several instructions */ if (distance(start_at,end())>1) /* several instructions */
{ {
@@ -459,7 +462,7 @@ bool BB::FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at)
* on optimized code. */ * on optimized code. */
void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, ICODE &picode) void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, ICODE &picode)
{ {
if (!((picode.hl()->opcode == HLI_CALL) && (picode.hl()->call.proc->flg & PROC_IS_FUNC))) if (not ((picode.hl()->opcode == HLI_CALL) and (picode.hl()->call.proc->getReturnType()!=TYPE_UNKNOWN)))
return; return;
BB *tbb = this->edges[0].BBptr; BB *tbb = this->edges[0].BBptr;
@@ -477,7 +480,7 @@ void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, ICODE &picode)
/* if not used in this basic block, check if the /* if not used in this basic block, check if the
* register is live out, if so, make it the last * register is live out, if so, make it the last
* definition of this register */ * definition of this register */
if ( picode.du1.used(defRegIdx) && tbb->liveOut.testRegAndSubregs(regi)) if ( picode.du1.used(defRegIdx) and tbb->liveOut.testRegAndSubregs(regi))
picode.du.lastDefRegi.addReg(regi); picode.du.lastDefRegi.addReg(regi);
} }
@@ -490,11 +493,11 @@ void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, ICODE &picode)
void BB::RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode) void BB::RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode)
{ {
if (picode->valid() and not picode->du1.used(defRegIdx) and if (picode->valid() and not picode->du1.used(defRegIdx) and
(not picode->du.lastDefRegi.testRegAndSubregs(regi)) && (not picode->du.lastDefRegi.testRegAndSubregs(regi)) and
(not ((picode->hl()->opcode == HLI_CALL) && (not ((picode->hl()->opcode == HLI_CALL) and
(picode->hl()->call.proc->flg & PROC_ISLIB)))) (picode->hl()->call.proc->flg & PROC_ISLIB))))
{ {
if (! (this->liveOut.testRegAndSubregs(regi))) /* not liveOut */ if (not (this->liveOut.testRegAndSubregs(regi))) /* not liveOut */
{ {
bool res = picode->removeDefRegi (regi, defRegIdx+1,&Parent->localId); bool res = picode->removeDefRegi (regi, defRegIdx+1,&Parent->localId);
if (res == true) if (res == true)
@@ -542,7 +545,7 @@ void BB::genDU1()
defRegIdx++; defRegIdx++;
/* Check if all defined registers have been processed */ /* Check if all defined registers have been processed */
if ((defRegIdx >= picode->du1.getNumRegsDef()) || (defRegIdx == MAX_REGS_DEF)) if ((defRegIdx >= picode->du1.getNumRegsDef()) or (defRegIdx == MAX_REGS_DEF))
break; break;
} }
} }
@@ -576,7 +579,7 @@ void LOCAL_ID::forwardSubs (Expr *lhs, Expr *rhs, iICODE picode, iICODE ticode,
return; return;
/* Insert on rhs of ticode, if possible */ /* Insert on rhs of ticode, if possible */
res = Expr::insertSubTreeReg (ticode->hlU()->asgn.rhs,rhs, id_arr[lhs_reg->regiIdx].id.regi, this); res = Expr::insertSubTreeReg (ticode->hlU()->asgn.m_rhs,rhs, id_arr[lhs_reg->regiIdx].id.regi, this);
if (res) if (res)
{ {
picode->invalidate(); picode->invalidate();
@@ -590,7 +593,7 @@ void LOCAL_ID::forwardSubs (Expr *lhs, Expr *rhs, iICODE picode, iICODE ticode,
{ {
eReg inserted = id_arr[lhs_reg->regiIdx].id.regi; eReg inserted = id_arr[lhs_reg->regiIdx].id.regi;
eReg lhsReg = id_arr[op->regiIdx].id.regi; eReg lhsReg = id_arr[op->regiIdx].id.regi;
if((lhsReg==inserted)||Machine_X86::isSubRegisterOf(lhsReg,inserted)) if((lhsReg==inserted) or Machine_X86::isSubRegisterOf(lhsReg,inserted))
{ {
// Do not replace ax = XYZ; given ax = H << P; with H << P = // Do not replace ax = XYZ; given ax = H << P; with H << P =
return; return;
@@ -615,7 +618,7 @@ static void forwardSubsLong (int longIdx, Expr *_exp, iICODE picode, iICODE tico
return; return;
/* Insert on rhs of ticode, if possible */ /* Insert on rhs of ticode, if possible */
res = Expr::insertSubTreeLongReg (_exp, ticode->hlU()->asgn.rhs, longIdx); res = Expr::insertSubTreeLongReg (_exp, ticode->hlU()->asgn.m_rhs, longIdx);
if (res) if (res)
{ {
picode->invalidate(); picode->invalidate();
@@ -646,7 +649,7 @@ bool BinaryOperator::xClear(rICODE range_to_check, iICODE lastBBinst, const LOCA
{ {
if(nullptr==m_rhs) if(nullptr==m_rhs)
return false; return false;
if ( ! m_rhs->xClear (range_to_check, lastBBinst, locs) ) if ( not m_rhs->xClear (range_to_check, lastBBinst, locs) )
return false; return false;
if(nullptr==m_lhs) if(nullptr==m_lhs)
return false; return false;
@@ -669,9 +672,7 @@ int C_CallingConvention::processCArg (Function * callee, Function * pProc, ICODE
Expr *_exp; Expr *_exp;
bool res; bool res;
int size_of_arg=0; int size_of_arg=0;
PROG &prog(Project::get()->prog); Project &proj(*Project::get());
/* if (numArgs == 0) /* if (numArgs == 0)
return; */ return; */
assert(pProc==g_exp_stk.func); assert(pProc==g_exp_stk.func);
@@ -691,8 +692,8 @@ int C_CallingConvention::processCArg (Function * callee, Function * pProc, ICODE
} }
else { else {
if(numArgs<callee->args.size()) { if(numArgs<callee->args.size()) {
if(prog.addressingMode=='l') { if(proj.getLoaderMetadata().compiler_memory_model==eLarge) {
if((callee->args[numArgs].type==TYPE_STR)||(callee->args[numArgs].type==TYPE_PTR)) { if((callee->args[numArgs].type==TYPE_STR) or (callee->args[numArgs].type==TYPE_PTR)) {
RegisterNode *rn = dynamic_cast<RegisterNode *>(g_exp_stk.top()); RegisterNode *rn = dynamic_cast<RegisterNode *>(g_exp_stk.top());
AstIdent *idn = dynamic_cast<AstIdent *>(g_exp_stk.top()); AstIdent *idn = dynamic_cast<AstIdent *>(g_exp_stk.top());
if(rn) { if(rn) {
@@ -758,11 +759,11 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
if(isLong) if(isLong)
{ {
forwardSubsLong (lhs_ident->ident.idNode.longIdx, forwardSubsLong (lhs_ident->ident.idNode.longIdx,
p_hl.asgn.rhs, picode,ticode, p_hl.asgn.m_rhs, picode,ticode,
&numHlIcodes); &numHlIcodes);
} }
else else
this->forwardSubs (lhs_ident, p_hl.asgn.rhs, picode, ticode, numHlIcodes); this->forwardSubs (lhs_ident, p_hl.asgn.m_rhs, picode, ticode, numHlIcodes);
break; break;
case HLI_JCOND: case HLI_PUSH: case HLI_RET: case HLI_JCOND: case HLI_PUSH: case HLI_RET:
@@ -770,7 +771,7 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
{ {
assert(lhs_ident); assert(lhs_ident);
res = Expr::insertSubTreeLongReg ( res = Expr::insertSubTreeLongReg (
p_hl.asgn.rhs, p_hl.asgn.m_rhs,
t_hl.exp.v, t_hl.exp.v,
lhs_ident->ident.idNode.longIdx); lhs_ident->ident.idNode.longIdx);
} }
@@ -780,7 +781,7 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
assert(lhs_reg); assert(lhs_reg);
res = Expr::insertSubTreeReg ( res = Expr::insertSubTreeReg (
t_hl.exp.v, t_hl.exp.v,
p_hl.asgn.rhs, p_hl.asgn.m_rhs,
id_arr[lhs_reg->regiIdx].id.regi, id_arr[lhs_reg->regiIdx].id.regi,
this); this);
} }
@@ -817,9 +818,9 @@ void C_CallingConvention::processHLI(Function *func,Expr *_exp, iICODE picode) {
numArgs++; numArgs++;
} }
} }
else if ((cb == 0) && picode->ll()->testFlags(REST_STK)) else if ((cb == 0) and picode->ll()->testFlags(REST_STK))
{ {
while (! g_exp_stk.empty()) while (not g_exp_stk.empty())
{ {
k+=processCArg (pp, func, &(*picode), numArgs); k+=processCArg (pp, func, &(*picode), numArgs);
numArgs++; numArgs++;
@@ -876,17 +877,18 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
bool res; bool res;
ID *_retVal; // function return value ID *_retVal; // function return value
Expr *_exp; // expression pointer - for HLI_POP and HLI_CALL */ Expr *_exp; // expression pointer - for HLI_POP and HLI_CALL
//Expr *lhs; // exp ptr for return value of a HLI_CALL */ //Expr *lhs; // exp ptr for return value of a HLI_CALL
iICODE ticode; // Target icode */ iICODE ticode; // Target icode
HLTYPE *ti_hl=nullptr; HLTYPE *ti_hl=nullptr;
uint8_t regi; uint8_t regi;
numHlIcodes = 0; numHlIcodes = 0;
assert(&fnc->localId==&locals); assert(&fnc->localId==&locals);
// register(s) to be forward substituted */ // register(s) to be forward substituted
auto valid_and_highlevel = instructions | filtered(ICODE::TypeAndValidFilter<HIGH_LEVEL>()); auto valid_and_highlevel = instructions | filtered(ICODE::TypeAndValidFilter<HIGH_LEVEL_ICODE>());
for (auto picode = valid_and_highlevel.begin(); picode != valid_and_highlevel.end(); picode++) for (auto picode = valid_and_highlevel.begin(); picode != valid_and_highlevel.end(); picode++)
{ {
ICODE &_ic(*picode);
HLTYPE &_icHl(*picode->hlU()); HLTYPE &_icHl(*picode->hlU());
numHlIcodes++; numHlIcodes++;
if (picode->du1.getNumRegsDef() == 1) /* uint8_t/uint16_t regs */ if (picode->du1.getNumRegsDef() == 1) /* uint8_t/uint16_t regs */
@@ -908,12 +910,12 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
* icode expression */ * icode expression */
ticode = picode->du1.idx[0].uses.front(); ticode = picode->du1.idx[0].uses.front();
if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) && if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) and
((ticode->hl()->opcode != HLI_CALL) && ((ticode->hl()->opcode != HLI_CALL) and
(ticode->hl()->opcode != HLI_RET))) (ticode->hl()->opcode != HLI_RET)))
continue; continue;
if (_icHl.asgn.rhs->xClear (make_iterator_range(picode.base(),picode->du1.idx[0].uses[0]), if (_icHl.asgn.m_rhs->xClear (make_iterator_range(picode.base(),picode->du1.idx[0].uses[0]),
end(), locals)) end(), locals))
{ {
locals.processTargetIcode(picode.base(), numHlIcodes, ticode,false); locals.processTargetIcode(picode.base(), numHlIcodes, ticode,false);
@@ -927,8 +929,8 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
// call F() <- somehow this is marked as user of POP ? // call F() <- somehow this is marked as user of POP ?
ticode = picode->du1.idx[0].uses.front(); ticode = picode->du1.idx[0].uses.front();
ti_hl = ticode->hlU(); ti_hl = ticode->hlU();
if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) && if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) and
((ti_hl->opcode != HLI_CALL) && ((ti_hl->opcode != HLI_CALL) and
(ti_hl->opcode != HLI_RET))) (ti_hl->opcode != HLI_RET)))
continue; continue;
@@ -968,14 +970,14 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
case HLI_CALL: case HLI_CALL:
ticode = picode->du1.idx[0].uses.front(); ticode = picode->du1.idx[0].uses.front();
ti_hl = ticode->hlU(); ti_hl = ticode->hlU();
_retVal = &_icHl.call.proc->retVal; _retVal = &_icHl.call.proc->type->retVal;
switch (ti_hl->opcode) switch (ti_hl->opcode)
{ {
case HLI_ASSIGN: case HLI_ASSIGN:
assert(ti_hl->asgn.rhs); assert(ti_hl->asgn.m_rhs);
_exp = _icHl.call.toAst(); _exp = _icHl.call.toAst();
res = Expr::insertSubTreeReg (ti_hl->asgn.rhs,_exp, _retVal->id.regi, &locals); res = Expr::insertSubTreeReg (ti_hl->asgn.m_rhs,_exp, _retVal->id.regi, &locals);
if (! res) if (not res)
Expr::insertSubTreeReg (ti_hl->asgn.m_lhs, _exp,_retVal->id.regi, &locals); Expr::insertSubTreeReg (ti_hl->asgn.m_lhs, _exp,_retVal->id.regi, &locals);
//TODO: HERE missing: 2 regs //TODO: HERE missing: 2 regs
picode->invalidate(); picode->invalidate();
@@ -1022,13 +1024,12 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
switch (_icHl.opcode) switch (_icHl.opcode)
{ {
case HLI_ASSIGN: case HLI_ASSIGN:
/* Replace rhs of current icode into target /* Replace rhs of current icode into target icode expression */
* icode expression */
if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0]) if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0])
{ {
ticode = picode->du1.idx[0].uses.front(); ticode = picode->du1.idx[0].uses.front();
if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) && if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) and
((ticode->hl()->opcode != HLI_CALL) && ((ticode->hl()->opcode != HLI_CALL) and
(ticode->hl()->opcode != HLI_RET))) (ticode->hl()->opcode != HLI_RET)))
continue; continue;
locals.processTargetIcode(picode.base(), numHlIcodes, ticode,true); locals.processTargetIcode(picode.base(), numHlIcodes, ticode,true);
@@ -1039,18 +1040,19 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0]) if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0])
{ {
ticode = picode->du1.idx[0].uses.front(); ticode = picode->du1.idx[0].uses.front();
if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) && if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) and
((ticode->hl()->opcode != HLI_CALL) && ((ticode->hl()->opcode != HLI_CALL) and
(ticode->hl()->opcode != HLI_RET))) (ticode->hl()->opcode != HLI_RET)))
continue; continue;
_exp = g_exp_stk.pop(); /* pop last exp pushed */ _exp = g_exp_stk.pop(); /* pop last exp pushed */
switch (ticode->hl()->opcode) { switch (ticode->hl()->opcode) {
case HLI_ASSIGN: case HLI_ASSIGN:
forwardSubsLong (dynamic_cast<AstIdent *>(_icHl.expr())->ident.idNode.longIdx, forwardSubsLong (static_cast<AstIdent *>(_icHl.expr())->ident.idNode.longIdx,
_exp, picode.base(), ticode, &numHlIcodes); _exp, picode.base(), ticode, &numHlIcodes);
break; break;
case HLI_JCOND: case HLI_PUSH: case HLI_JCOND:
case HLI_PUSH:
res = Expr::insertSubTreeLongReg (_exp, res = Expr::insertSubTreeLongReg (_exp,
ticode->hlU()->exp.v, ticode->hlU()->exp.v,
dynamic_cast<AstIdent *>(_icHl.asgn.lhs())->ident.idNode.longIdx); dynamic_cast<AstIdent *>(_icHl.asgn.lhs())->ident.idNode.longIdx);
@@ -1078,7 +1080,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
AstIdent::Long(&locals, DST, AstIdent::Long(&locals, DST,
ticode,HIGH_FIRST, picode.base(), ticode,HIGH_FIRST, picode.base(),
eDEF, *(++iICODE(ticode))->ll())); eDEF, *(++iICODE(ticode))->ll()));
ticode->hlU()->asgn.rhs = _exp; ticode->hlU()->asgn.m_rhs = _exp;
picode->invalidate(); picode->invalidate();
numHlIcodes--; numHlIcodes--;
break; break;
@@ -1092,7 +1094,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
case HLI_JCOND: case HLI_JCOND:
_exp = _icHl.call.toAst(); _exp = _icHl.call.toAst();
_retVal = &picode->hl()->call.proc->retVal; _retVal = &picode->hl()->call.proc->type->retVal;
res = Expr::insertSubTreeLongReg (_exp, res = Expr::insertSubTreeLongReg (_exp,
ticode->hlU()->exp.v, ticode->hlU()->exp.v,
locals.newLongReg ( _retVal->type, _retVal->longId(), picode.base())); locals.newLongReg ( _retVal->type, _retVal->longId(), picode.base()));
@@ -1117,6 +1119,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
} /* eos */ } /* eos */
} }
} }
/* HLI_PUSH doesn't define any registers, only uses registers. /* HLI_PUSH doesn't define any registers, only uses registers.
* Push the associated expression to the register on the local * Push the associated expression to the register on the local
* expression stack */ * expression stack */
@@ -1142,7 +1145,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
if ( not _icHl.call.proc->isLibrary() and (not picode->du1.used(0)) and (picode->du1.getNumRegsDef() > 0)) if ( not _icHl.call.proc->isLibrary() and (not picode->du1.used(0)) and (picode->du1.getNumRegsDef() > 0))
{ {
_exp = new FuncNode(_icHl.call.proc, _icHl.call.args); _exp = new FuncNode(_icHl.call.proc, _icHl.call.args);
auto lhs = AstIdent::idID (&_icHl.call.proc->retVal, &locals, picode.base()); auto lhs = AstIdent::idID (&_icHl.call.proc->type->retVal, &locals, picode.base());
picode->setAsgn(lhs, _exp); picode->setAsgn(lhs, _exp);
} }
} }
@@ -1179,89 +1182,90 @@ void Function::preprocessReturnDU(LivenessSet &_liveOut)
if(not _liveOut.any()) if(not _liveOut.any())
return; return;
} }
flg |= PROC_IS_FUNC;
isAx = _liveOut.testReg(rAX); isAx = _liveOut.testReg(rAX);
isBx = _liveOut.testReg(rBX); isBx = _liveOut.testReg(rBX);
isCx = _liveOut.testReg(rCX); isCx = _liveOut.testReg(rCX);
isDx = _liveOut.testReg(rDX); isDx = _liveOut.testReg(rDX);
bool isAL = !isAx && _liveOut.testReg(rAL); bool isAL = not isAx and _liveOut.testReg(rAL);
bool isAH = !isAx && _liveOut.testReg(rAH); bool isAH = not isAx and _liveOut.testReg(rAH);
bool isBL = !isBx && _liveOut.testReg(rBL); bool isBL = not isBx and _liveOut.testReg(rBL);
bool isBH = !isBx && _liveOut.testReg(rBH); bool isBH = not isBx and _liveOut.testReg(rBH);
bool isCL = !isCx && _liveOut.testReg(rCL); bool isCL = not isCx and _liveOut.testReg(rCL);
bool isCH = !isCx && _liveOut.testReg(rCH); bool isCH = not isCx and _liveOut.testReg(rCH);
bool isDL = !isDx && _liveOut.testReg(rDL); bool isDL = not isDx and _liveOut.testReg(rDL);
bool isDH = !isDx && _liveOut.testReg(rDH); bool isDH = not isDx and _liveOut.testReg(rDH);
if(isAL && isAH) if(isAL and isAH)
{ {
isAx = true; isAx = true;
isAH=isAL=false; isAH=isAL=false;
} }
if(isDL && isDH) if(isDL and isDH)
{ {
isDx = true; isDx = true;
isDH=isDL=false; isDH=isDL=false;
} }
if(isBL && isBH) if(isBL and isBH)
{ {
isBx = true; isBx = true;
isBH=isBL=false; isBH=isBL=false;
} }
if(isCL && isCH) if(isCL and isCH)
{ {
isCx = true; isCx = true;
isCH=isCL=false; isCH=isCL=false;
} }
if (isAx && isDx) /* long or pointer */ if (isAx and isDx) /* long or pointer */
{ {
retVal.type = TYPE_LONG_SIGN; type->setReturnType(TYPE_LONG_SIGN);
retVal.loc = REG_FRAME; type->m_call_conv->calculateStackLayout(this);
retVal.longId() = LONGID_TYPE(rDX,rAX);
/*idx = */localId.newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(rDX,rAX), Icode.begin()); /*idx = */localId.newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(rDX,rAX), Icode.begin());
localId.propLongId (rAX, rDX, "\0"); localId.propLongId (rAX, rDX, "");
} }
else if (isAx || isBx || isCx || isDx) /* uint16_t */ else if (isAx or isBx or isCx or isDx) /* uint16_t */
{ {
retVal.type = TYPE_WORD_SIGN; eReg selected_reg;
retVal.loc = REG_FRAME;
if (isAx) if (isAx)
retVal.id.regi = rAX; selected_reg = rAX;
else if (isBx) else if (isBx)
retVal.id.regi = rBX; selected_reg = rBX;
else if (isCx) else if (isCx)
retVal.id.regi = rCX; selected_reg = rCX;
else else
retVal.id.regi = rDX; selected_reg = rDX;
/*idx = */localId.newByteWordReg(TYPE_WORD_SIGN,retVal.id.regi); type->setReturnType(TYPE_WORD_SIGN);
type->m_call_conv->calculateStackLayout(this);
/*idx = */localId.newByteWordReg(TYPE_WORD_SIGN,selected_reg);
} }
else if(isAL||isBL||isCL||isDL) else if(isAL or isBL or isCL or isDL)
{ {
retVal.type = TYPE_BYTE_SIGN; eReg selected_reg;
retVal.loc = REG_FRAME;
if (isAL) if (isAL)
retVal.id.regi = rAL; selected_reg = rAL;
else if (isBL) else if (isBL)
retVal.id.regi = rBL; selected_reg = rBL;
else if (isCL) else if (isCL)
retVal.id.regi = rCL; selected_reg = rCL;
else else
retVal.id.regi = rDL; selected_reg = rDL;
/*idx = */localId.newByteWordReg(TYPE_BYTE_SIGN,retVal.id.regi); type->setReturnType(TYPE_BYTE_SIGN);
type->m_call_conv->calculateStackLayout(this);
/*idx = */localId.newByteWordReg(TYPE_BYTE_SIGN,selected_reg);
} }
else if(isAH||isBH||isCH||isDH) else if(isAH or isBH or isCH or isDH)
{ {
retVal.type = TYPE_BYTE_SIGN; eReg selected_reg;
retVal.loc = REG_FRAME;
if (isAH) if (isAH)
retVal.id.regi = rAH; selected_reg = rAH;
else if (isBH) else if (isBH)
retVal.id.regi = rBH; selected_reg = rBH;
else if (isCH) else if (isCH)
retVal.id.regi = rCH; selected_reg = rCH;
else else
retVal.id.regi = rDH; selected_reg = rDH;
/*idx = */localId.newByteWordReg(TYPE_BYTE_SIGN,retVal.id.regi); type->setReturnType(TYPE_BYTE_SIGN);
type->m_call_conv->calculateStackLayout(this);
/*idx = */localId.newByteWordReg(TYPE_BYTE_SIGN,selected_reg);
} }
} }
} }
@@ -1285,7 +1289,7 @@ void Function::dataFlow(LivenessSet &_liveOut)
elimCondCodes(); elimCondCodes();
genLiveKtes(); genLiveKtes();
liveRegAnalysis (_liveOut); /* calls dataFlow() recursively */ liveRegAnalysis (_liveOut); /* calls dataFlow() recursively */
if (! (flg & PROC_ASM)) /* can generate C for pProc */ if (not (flg & PROC_ASM)) /* can generate C for pProc */
{ {
genDU1 (); /* generate def/use level 1 chain */ genDU1 (); /* generate def/use level 1 chain */
findExps (); /* forward substitution algorithm */ findExps (); /* forward substitution algorithm */

View File

@@ -4,124 +4,123 @@
* (C) Cristina Cifuentes * (C) Cristina Cifuentes
****************************************************************************/ ****************************************************************************/
#include <cstring>
#include "dcc.h" #include "dcc.h"
#include "project.h"
#include "msvc_fixes.h"
#include "project.h"
#include "CallGraph.h" #include "CallGraph.h"
#include "DccFrontend.h"
#include <cstring>
#include <iostream>
#include <QtCore/QCoreApplication>
#include <QtWidgets/QApplication>
#include <QCommandLineParser>
#include <QtCore/QFile>
#include "ui/DccMainWindow.h"
/* Global variables - extern to other modules */ /* Global variables - extern to other modules */
extern char *asm1_name, *asm2_name; /* Assembler output filenames */ extern QString asm1_name, asm2_name; /* Assembler output filenames */
extern SYMTAB symtab; /* Global symbol table */ extern SYMTAB symtab; /* Global symbol table */
extern STATS stats; /* cfg statistics */ extern STATS stats; /* cfg statistics */
//PROG prog; /* programs fields */
extern OPTION option; /* Command line options */ extern 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 char *initargs(int argc, char *argv[]);
static void displayTotalStats(void); static void displayTotalStats(void);
#include <llvm/Support/raw_os_ostream.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/PrettyStackTrace.h>
#include <llvm/Support/Signals.h>
#include <llvm/Support/Host.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Target/TargetInstrInfo.h>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/CodeGen/MachineInstrBuilder.h>
#include <llvm/TableGen/Main.h>
#include <llvm/TableGen/TableGenBackend.h>
#include <llvm/TableGen/Record.h>
/**************************************************************************** /****************************************************************************
* main * main
***************************************************************************/ ***************************************************************************/
#include <iostream> void setupOptions(QCoreApplication &app) {
using namespace llvm; //[-a1a2cmsi]
bool TVisitor(raw_ostream &OS, RecordKeeper &Records) QCommandLineParser parser;
{ parser.setApplicationDescription("dcc");
Record *rec = Records.getDef("ADD8i8"); parser.addHelpOption();
if(rec) //parser.addVersionOption();
{ //QCommandLineOption showProgressOption("p", QCoreApplication::translate("main", "Show progress during copy"));
if(not rec->getTemplateArgs().empty()) QCommandLineOption boolOpts[] {
std::cout << "Has template args\n"; QCommandLineOption {"v", QCoreApplication::translate("main", "verbose")},
auto classes(rec->getSuperClasses()); QCommandLineOption {"V", QCoreApplication::translate("main", "very verbose")},
for(auto val : rec->getSuperClasses()) QCommandLineOption {"c", QCoreApplication::translate("main", "Follow register indirect calls")},
std::cout << "Super "<<val->getName()<<"\n"; 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);
// DagInit * in = rec->getValueAsDag(val.getName()); const QStringList args = parser.positionalArguments();
// in->dump(); if(args.empty()) {
for(const RecordVal &val : rec->getValues()) parser.showHelp();
{
// val.dump();
} }
rec->dump(); // 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;
} }
// rec = Records.getDef("CCR"); option.Map = parser.isSet(boolOpts[3]);
// if(rec) option.Stats = parser.isSet(boolOpts[4]);
// rec->dump(); option.Interact = false;
for(auto val : Records.getDefs()) option.Calls = parser.isSet(boolOpts[2]);
{ option.filename = args.first();
//std::cout<< "Def "<<val.first<<"\n"; option.CustomEntryPoint = parser.value(entryPointOption).toUInt(0,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";
} }
return false;
}
int testTblGen(int argc, char **argv)
{
using namespace llvm;
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram(argc,argv);
cl::ParseCommandLineOptions(argc,argv);
return llvm::TableGenMain(argv[0],TVisitor);
InitializeNativeTarget();
Triple TheTriple;
std::string def = sys::getDefaultTargetTriple();
std::string MCPU="i386";
std::string MARCH="x86";
InitializeAllTargetInfos();
InitializeAllTargetMCs();
InitializeAllAsmPrinters();
InitializeAllAsmParsers();
InitializeAllDisassemblers();
std::string TargetTriple("i386-pc-linux-gnu");
TheTriple = Triple(Triple::normalize(TargetTriple));
MCOperand op=llvm::MCOperand::CreateImm(11);
MCAsmInfo info;
raw_os_ostream wrap(std::cerr);
op.print(wrap,&info);
wrap.flush();
std::cerr<<"\n";
std::string lookuperr;
TargetRegistry::printRegisteredTargetsForVersion();
const Target *t = TargetRegistry::lookupTarget(MARCH,TheTriple,lookuperr);
TargetOptions opts;
std::string Features;
opts.PrintMachineCode=1;
TargetMachine *tm = t->createTargetMachine(TheTriple.getTriple(),MCPU,Features,opts);
std::cerr<<tm->getInstrInfo()->getName(97)<<"\n";
const MCInstrDesc &ds(tm->getInstrInfo()->get(97));
const MCOperandInfo *op1=ds.OpInfo;
uint16_t impl_def = ds.getImplicitDefs()[0];
std::cerr<<lookuperr<<"\n";
exit(0);
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
/* Extract switches and filename */ QCoreApplication::setApplicationName("dcc");
strcpy(option.filename, initargs(argc, argv)); QCoreApplication::setApplicationVersion("0.2");
if(argc==1) {
QApplication app(argc,argv);
DccMainWindow win;
win.show();
return app.exec();
}
QCoreApplication app(argc,argv);
setupOptions(app);
Project *proj = Project::get();
/* Front end reads in EXE or COM file, parses it into I-code while /* 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 * building the call graph and attaching appropriate bits of code for
* each procedure. * each procedure.
*/ */
DccFrontend fe(option.filename); proj->create(option.filename);
DccFrontend fe(&app);
proj->addLoadCommands(option.filename);
proj->processAllCommands();
if(proj->m_error_state) {
proj->dumpAllErrors();
return -1;
}
if (option.verbose)
proj->prog.displayLoadInfo();
if(false==fe.FrontEnd ()) if(false==fe.FrontEnd ())
return -1; return -1;
if(option.asm1) if(option.asm1)
@@ -138,98 +137,16 @@ int main(int argc, char **argv)
* analysis, data flow etc. and outputs it to output file ready for * analysis, data flow etc. and outputs it to output file ready for
* re-compilation. * re-compilation.
*/ */
BackEnd(asm1_name ? asm1_name:option.filename, Project::get()->callGraph); BackEnd(proj->callGraph);
Project::get()->callGraph->write(); proj->callGraph->write();
if (option.Stats) if (option.Stats)
displayTotalStats(); displayTotalStats();
/*
freeDataStructures(pProcList);
*/
return 0; 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 static void
displayTotalStats () displayTotalStats ()
/* Displays final statistics for the complete program */ /* Displays final statistics for the complete program */

35
src/dcc_interface.cpp Normal file
View File

@@ -0,0 +1,35 @@
#include "dcc_interface.h"
#include "dcc.h"
#include "project.h"
struct DccImpl : public IDcc {
PtrFunction m_current_func;
// IDcc interface
public:
bool load(QString name)
{
option.filename = name;
Project::get()->create(name);
return Project::get()->addLoadCommands(name);
}
void SetCurFunc_by_Name(QString v)
{
PtrFunction p(Project::get()->findByName(v));
if(p!=nullptr)
m_current_func = p;
}
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 * dcc project disassembler
* (C) Cristina Cifuentes, Mike van Emmerik, Jeff Ledermann * (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 <stdint.h>
#include <vector> #include <vector>
#include <map> #include <map>
@@ -9,11 +18,8 @@
#include <iomanip> #include <iomanip>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "src/ui/StructuredTextTarget.h"
#include "dcc.h"
#include "symtab.h"
#include "disassem.h"
#include "project.h"
// Note: for the time being, there is no interactive disassembler // Note: for the time being, there is no interactive disassembler
// for unix // for unix
@@ -70,8 +76,8 @@ static const char *szFlops3C[] =
static const char *szPtr[2] = { "word ptr ", "byte ptr " }; static const char *szPtr[2] = { "word ptr ", "byte ptr " };
static void formatRM(ostringstream &p, const LLOperand &pm); static void formatRM(QTextStream & p, const LLOperand &pm);
static ostringstream &strDst(ostringstream &os, uint32_t flg, const LLOperand &pm); static QTextStream & strDst(QTextStream & os, uint32_t flg, const LLOperand &pm);
static char *strHex(uint32_t d); static char *strHex(uint32_t d);
//static int checkScanned(uint32_t pcCur); //static int checkScanned(uint32_t pcCur);
@@ -81,12 +87,12 @@ bool callArg(uint16_t off, char *temp); /* Check for procedure name */
//static FILE *dis_g_fp; //static FILE *dis_g_fp;
static CIcodeRec pc; static CIcodeRec pc;
static int cb, j, numIcode, allocIcode; static int cb, numIcode, allocIcode;
static map<int,int> pl; static map<int,int> pl;
static uint32_t nextInst; static uint32_t nextInst;
static bool fImpure; //static bool fImpure;
//static int g_lab; //static int g_lab;
static Function * pProc; /* Points to current proc struct */ static PtrFunction pProc; /* Points to current proc struct */
struct POSSTACK_ENTRY struct POSSTACK_ENTRY
{ {
@@ -107,7 +113,7 @@ static vector<POSSTACK_ENTRY> posStack; /* position stack */
void LLInst::findJumpTargets(CIcodeRec &_pc) void LLInst::findJumpTargets(CIcodeRec &_pc)
{ {
if (testFlags(I) && ! testFlags(JMP_ICODE) && isJmpInst()) if (srcIsImmed() and not testFlags(JMP_ICODE) and isJmpInst())
{ {
/* Replace the immediate operand with an icode index */ /* Replace the immediate operand with an icode index */
iICODE labTgt=_pc.labelSrch(src().getImm2()); iICODE labTgt=_pc.labelSrch(src().getImm2());
@@ -133,7 +139,7 @@ void LLInst::findJumpTargets(CIcodeRec &_pc)
* pass == 3 generates output on file .b * pass == 3 generates output on file .b
****************************************************************************/ ****************************************************************************/
void Disassembler::disassem(Function * ppProc) void Disassembler::disassem(PtrFunction ppProc)
{ {
@@ -150,11 +156,11 @@ void Disassembler::disassem(Function * ppProc)
if (pass != 3) if (pass != 3)
{ {
auto p = (pass == 1)? asm1_name: asm2_name; auto p = (pass == 1)? asm1_name: asm2_name;
m_fp.open(p,ios_base::app); m_disassembly_target = new QFile(p);
if (!m_fp.is_open()) if(!m_disassembly_target->open(QFile::WriteOnly|QFile::Text|QFile::Append)) {
{ fatalError(CANNOT_OPEN, p.toStdString().c_str());
fatalError(CANNOT_OPEN, p);
} }
m_fp.setDevice(m_disassembly_target);
} }
/* Create temporary code array */ /* Create temporary code array */
// Mike: needs objectising! // Mike: needs objectising!
@@ -177,7 +183,7 @@ void Disassembler::disassem(Function * ppProc)
/* Write procedure header */ /* Write procedure header */
if (pass != 3) 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"; m_fp << "\t\t"<<pProc->name<<" PROC "<< near_far<<"\n";
} }
@@ -192,7 +198,10 @@ void Disassembler::disassem(Function * ppProc)
if (pass != 3) if (pass != 3)
{ {
m_fp << "\n\t\t"<<pProc->name<<" ENDP\n\n"; 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(); pc.clear();
@@ -205,345 +214,7 @@ void Disassembler::disassem(Function * ppProc)
****************************************************************************/ ****************************************************************************/
void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass) void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
{ {
PROG &prog(Project::get()->prog); assert(false);
ostringstream oper_stream;
ostringstream hex_bytes;
ostringstream result_stream;
ostringstream opcode_with_mods;
ostringstream operands_s;
oper_stream << uppercase;
hex_bytes << uppercase;
/* 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))))
{
return;
}
else if (inst.testFlags(NO_CODE))
{
return;
}
if (inst.testFlags(TARGET | CASE))
{
if (pass == 3)
cCode.appendCode("\n"); /* Print to c code buffer */
else
m_fp<< "\n"; /* No, print to the stream */
}
/* Find next instruction label and print hex bytes */
if (inst.testFlags(SYNTHETIC))
nextInst = inst.label;
else
{
cb = (uint32_t) inst.numBytes;
nextInst = inst.label + cb;
/* Output hexa 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 << ' ';
}
}
oper_stream << setw(POS_LAB) << left<< hex_bytes.str();
/* Check if there is a symbol here */
selectTable(Label);
oper_stream << setw(5)<<left; // align for the labels
{
ostringstream lab_contents;
if (readVal(lab_contents, inst.label, nullptr))
{
lab_contents << ':'; /* Also removes the null */
}
else if (inst.testFlags(TARGET)) /* Symbols override Lnn labels */
{
/* Print label */
if (pl.count(loc_ip)==0)
{
pl[loc_ip] = ++g_lab;
}
lab_contents<< "L"<<pl[loc_ip]<<':';
}
oper_stream<< lab_contents.str();
}
if ((inst.getOpcode()==iSIGNEX )&& inst.testFlags(B))
{
inst.setOpcode(iCBW);
}
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.m_dst);
inst.strSrc(operands_s);
break;
case iESC:
inst.flops(operands_s);
break;
case iSAR: case iSHL: case iSHR: case iRCL: case iRCR: case iROL:
case iROR:
strDst(operands_s,inst.getFlag() | I, inst.m_dst);
if(inst.testFlags(I))
inst.strSrc(operands_s);
else
operands_s<<", cl";
break;
case iINC: case iDEC: case iNEG: case iNOT: case iPOP:
strDst(operands_s,inst.getFlag() | I, inst.m_dst);
break;
case iPUSH:
if (inst.testFlags(I))
{
operands_s<<strHex(inst.src().getImm2());
}
else
{
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.m_dst) <<", ";
formatRM(operands_s, inst.src());
inst.strSrc(operands_s);
}
else
strDst(operands_s,inst.getFlag() | I, inst.src());
break;
case iLDS: case iLES: case iBOUND:
strDst(operands_s,inst.getFlag(), inst.m_dst)<<", dword ptr";
inst.strSrc(operands_s,true);
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:case iLOOP: case iLOOPE:case iLOOPNE:
case iJMP: case iJMPF:
/* Check if there is a symbol here */
{
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, nullptr))
{
break; /* Symbolic label. Done */
}
}
if (inst.testFlags(NO_LABEL))
{
//strcpy(p + WID_PTR, strHex(pIcode->ll()->immed.op));
operands_s<<strHex(inst.src().getImm2());
}
else if (inst.testFlags(I) )
{
j = inst.src().getImm2();
if (pl.count(j)==0) /* Forward jump */
{
pl[j] = ++g_lab;
}
if (inst.getOpcode() == iJMPF)
{
operands_s<<" far ptr ";
}
operands_s<<"L"<<pl[j];
}
else if (inst.getOpcode() == iJMPF)
{
operands_s<<"dword ptr";
inst.strSrc(operands_s,true);
}
else
{
strDst(operands_s,I, inst.src());
}
break;
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;
}
else if (inst.getOpcode() == iCALLF)
{
operands_s<<"dword ptr ";
inst.strSrc(operands_s,true);
}
else
strDst(operands_s,I, inst.src());
break;
case iENTER:
operands_s<<strHex(inst.m_dst.off) << ", " << strHex(inst.src().getImm2());
break;
case iRET: case iRETF: case iINT:
if (inst.testFlags(I))
{
operands_s<<strHex(inst.src().getImm2());
}
break;
case iCMPS: case iREPNE_CMPS: case iREPE_CMPS:
case iSCAS: case iREPNE_SCAS: case iREPE_SCAS:
case iSTOS: case iREP_STOS:
case iLODS: case iREP_LODS:
case iMOVS: case iREP_MOVS:
case iINS: case iREP_INS:
case iOUTS: case iREP_OUTS:
if (inst.src().segOver)
{
bool is_dx_src=(inst.getOpcode() == iOUTS || 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)
{
operands_s<<Machine_X86::regName(inst.src().segOver); // szWreg[src.segOver-rAX]
}
else
{
operands_s<<"es:[di], "<<Machine_X86::regName(inst.src().segOver);
}
operands_s<<":[si]";
}
else
{
(inst.getFlag() & B)? opcode_with_mods<< "B": opcode_with_mods<< "W";
}
break;
case iXLAT:
if (inst.src().segOver)
{
operands_s<<" "<<szPtr[1];
operands_s<<Machine_X86::regName(inst.src().segOver)<<":[bx]";
}
break;
case iIN:
(inst.getFlag() & B)? operands_s<<"al, " : operands_s<< "ax, ";
(inst.testFlags(I))? operands_s << strHex(inst.src().getImm2()) : operands_s<< "dx";
break;
case iOUT:
{
std::string d1=((inst.testFlags(I))? strHex(inst.src().getImm2()): "dx");
std::string d2=((inst.getFlag() & B) ? ", al": ", ax");
operands_s<<d1 << d2;
}
break;
default:
break;
}
oper_stream << setw(15) << left <<opcode_with_mods.str();
oper_stream << operands_s.str();
/* Comments */
if (inst.testFlags(SYNTHETIC))
{
fImpure = false;
}
else
{
for (j = inst.label, fImpure = 0; j > 0 && j < (int)nextInst; j++)
{
fImpure |= BITMAP(j, BM_DATA);
}
}
result_stream << setw(54) << left << oper_stream.str();
/* Check for user supplied comment */
selectTable(Comment);
ostringstream cbuf;
if (readVal(cbuf, inst.label, nullptr))
{
result_stream <<"; "<<cbuf.str();
}
else if (fImpure || (inst.testFlags(SWITCH | CASE | SEG_IMMED | IMPURE | SYNTHETIC | TERMINATES)))
{
if (inst.testFlags(CASE))
{
result_stream << ";Case l"<< inst.caseEntry;
}
if (inst.testFlags(SWITCH))
{
result_stream << ";Switch ";
}
if (fImpure)
{
result_stream << ";Accessed as data ";
}
if (inst.testFlags(IMPURE))
{
result_stream << ";Impure operand ";
}
if (inst.testFlags(SEG_IMMED))
{
result_stream << ";Segment constant";
}
if (inst.testFlags(TERMINATES))
{
result_stream << ";Exit to DOS";
}
}
/* Comment on iINT icodes */
if (inst.getOpcode() == iINT)
inst.writeIntComment(result_stream);
/* Display output line */
if(pass==3)
{
/* 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());
}
else
{
char buf[12];
/* output to .a1 or .a2 file */
if (not inst.testFlags(SYNTHETIC) )
{
sprintf(buf,"%03d %06X",loc_ip, inst.label);
}
else /* SYNTHETIC instruction */
{
sprintf(buf,"%03d ",loc_ip);
result_stream<<";Synthetic inst";
}
m_fp<<buf<< " " << result_stream.str() << "\n";
}
} }
@@ -551,7 +222,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
/**************************************************************************** /****************************************************************************
* formatRM * formatRM
***************************************************************************/ ***************************************************************************/
static void formatRM(std::ostringstream &p, const LLOperand &pm) static void formatRM(QTextStream &p, const LLOperand &pm)
{ {
//char seg[4]; //char seg[4];
@@ -588,7 +259,7 @@ static void formatRM(std::ostringstream &p, const LLOperand &pm)
/***************************************************************************** /*****************************************************************************
* strDst * 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 */ /* Immediates to memory require size descriptor */
//os << setw(WID_PTR); //os << setw(WID_PTR);
@@ -602,19 +273,19 @@ static ostringstream & strDst(ostringstream &os,uint32_t flg, const LLOperand &p
/**************************************************************************** /****************************************************************************
* strSrc * * strSrc *
****************************************************************************/ ****************************************************************************/
ostringstream &LLInst::strSrc(ostringstream &os,bool skip_comma) //QTextStream &LLInst::strSrc(QTextStream &os,bool skip_comma)
{ //{
if(false==skip_comma) // if(false==skip_comma)
os<<", "; // os<<", ";
if (testFlags(I)) // if (srcIsImmed())
os<<strHex(src().getImm2()); // os<<strHex(src().getImm2());
else if (testFlags(IM_SRC)) /* level 2 */ // else if (testFlags(IM_SRC)) /* level 2 */
os<<"dx:ax"; // os<<"dx:ax";
else // else
formatRM(os, src()); // formatRM(os, src());
return os; // return os;
} //}
@@ -633,14 +304,18 @@ static char *strHex(uint32_t d)
/**************************************************************************** /****************************************************************************
* interactDis - interactive disassembler * * interactDis - interactive disassembler *
****************************************************************************/ ****************************************************************************/
void interactDis(Function * /*initProc*/, int /*initIC*/) void interactDis(const PtrFunction & 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; return;
} }
/* Handle the floating point opcodes (icode iESC) */ /* 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(); uint8_t op = (uint8_t)src().getImm2();
@@ -652,8 +327,8 @@ void LLInst::flops(std::ostringstream &out)
{ {
/* The mod/rm mod bits are not set to 11 (i.e. register). This is the normal floating point opcode */ /* 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<<Machine_X86::floatOpName(op)<<' ';
out <<setw(10); out.setFieldWidth(10);
if ((op == 0x29) || (op == 0x1F)) if ((op == 0x29) or (op == 0x1F))
{ {
out << "tbyte ptr "; out << "tbyte ptr ";
} }
@@ -683,7 +358,7 @@ void LLInst::flops(std::ostringstream &out)
break; break;
} }
} }
out.setFieldWidth(0);
formatRM(out, m_dst); formatRM(out, m_dst);
} }
else else
@@ -722,7 +397,7 @@ void LLInst::flops(std::ostringstream &out)
break; break;
default: default:
out << Machine_X86::floatOpName(0x40+op); out << Machine_X86::floatOpName(0x40+op);
if ((op >= 0x20) && (op <= 0x27)) if ((op >= 0x20) and (op <= 0x27))
{ {
/* This is the ST(i), ST form. */ /* This is the ST(i), ST form. */
out << "ST("<<destRegIdx - rAX<<"),ST"; out << "ST("<<destRegIdx - rAX<<"),ST";
@@ -737,5 +412,230 @@ void LLInst::flops(std::ostringstream &out)
} }
} }
} }
struct AsmFormatter {
IStructuredTextTarget * target;
int operand_count;
void visitOperand(const LLOperand &pm) {
if(not pm.isSet())
return;
if(operand_count>0) {
target->prtt(", ");
}
operand_count++;
if (pm.immed and not pm.isReg()) {
//target->addTaggedString(XT_Keyword,szPtr[flg&B]);
target->addTaggedString(XT_Number,strHex(pm.getImm2()));
return;
}
if (pm.segOver)
{
target->prtt(Machine_X86::regName(pm.segOver)+':');
}
if (pm.regi == rUNDEF)
{
target->prtt(QString("[")+strHex((uint32_t)pm.off)+"]");
}
else if (pm.isReg())
{
target->prtt(Machine_X86::regName(pm.regi));
}
else if (pm.off)
{
if (pm.off < 0)
{
target->prtt("["+Machine_X86::regName(pm.regi)+"-"+strHex((uint32_t)(- pm.off))+"]");
}
else
{
target->prtt("["+Machine_X86::regName(pm.regi)+"+"+strHex((uint32_t)(pm.off))+"]");
}
}
else
target->prtt("["+Machine_X86::regName(pm.regi)+"]");
}
};
void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level) {
AsmFormatter formatter {out};
const LLInst &inst(*insn);
QString opcode = Machine_X86::opcodeName(insn->getOpcode());
out->addSpace(4);
out->addTaggedString(XT_Number,QString("%1").arg(insn->label,8,16,QChar('0').toUpper()));
out->addSpace(4);
out->addTaggedString(XT_Keyword,Machine_X86::opcodeName(insn->getOpcode()),insn);
out->addSpace(2);
switch(insn->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:
case iSAR: case iSHL: case iSHR: case iRCL: case iRCR: case iROL:
case iROR:
formatter.visitOperand(insn->dst());
formatter.visitOperand(insn->src());
break;
case iINC: case iDEC: case iNEG: case iNOT: case iPOP:
formatter.visitOperand(insn->dst());
break;
case iPUSH:
formatter.visitOperand(insn->dst());
break;
case iDIV: case iIDIV: case iMUL: case iIMUL: case iMOD:
if (inst.srcIsImmed())
{
formatter.visitOperand(insn->dst());
formatter.visitOperand(insn->src());
}
else
formatter.visitOperand(insn->dst());
break;
case iLDS: case iLES: case iBOUND:
formatter.visitOperand(insn->dst());
formatter.visitOperand(insn->src());
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:case iLOOP: case iLOOPE:case iLOOPNE:
case iJMP: case iJMPF:
/* Check if there is a symbol here */
{
// ICODE *lab=pc.GetIcode(inst.src().getImm2());
// selectTable(Label);
// 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))
{
//strcpy(p + WID_PTR, strHex(pIcode->ll()->immed.op));
out->addTaggedString(XT_AsmLabel,strHex(inst.src().getImm2()));
}
else if (inst.srcIsImmed() )
{
int64_t tgt_addr = inst.src().getImm2();
if (inst.getOpcode() == iJMPF)
{
out->addTaggedString(XT_Keyword," far ptr ");
}
out->addTaggedString(XT_AsmLabel,QString("L_%1").arg(strHex(tgt_addr)));
}
else if (inst.getOpcode() == iJMPF)
{
out->addTaggedString(XT_Keyword,"dword ptr");
formatter.visitOperand(inst.src());
}
else
{
formatter.visitOperand(inst.src());
}
break;
case iCALL: case iCALLF:
if (inst.srcIsImmed())
{
out->addTaggedString(XT_Keyword,QString("%1 ptr ").arg((inst.getOpcode() == iCALL) ? "near" : "far"));
out->addTaggedString(XT_AsmLabel,(inst.src().proc.proc)->name);
}
else if (inst.getOpcode() == iCALLF)
{
out->addTaggedString(XT_Keyword,"dword ptr ");
formatter.visitOperand(inst.src());
}
else
formatter.visitOperand(inst.src());
break;
case iENTER:
formatter.visitOperand(inst.dst());
formatter.visitOperand(inst.src());
break;
case iRET:
case iRETF:
case iINT:
formatter.visitOperand(inst.src());
break;
case iCMPS: case iREPNE_CMPS: case iREPE_CMPS:
case iSCAS: case iREPNE_SCAS: case iREPE_SCAS:
case iSTOS: case iREP_STOS:
case iLODS: case iREP_LODS:
case iMOVS: case iREP_MOVS:
case iINS: case iREP_INS:
case iOUTS: case iREP_OUTS:
if (inst.src().segOver)
{
bool is_dx_src=(inst.getOpcode() == iOUTS or inst.getOpcode() == iREP_OUTS);
if(is_dx_src)
{
out->addTaggedString(XT_Symbol,"dx");
out->prtt(", ");
out->addTaggedString(XT_Keyword,szPtr[inst.getFlag() & B]);
out->addSpace(2);
}
else
out->addTaggedString(XT_Keyword,szPtr[inst.getFlag() & B]);
if (inst.getOpcode() == iLODS or
inst.getOpcode() == iREP_LODS or
inst.getOpcode() == iOUTS or
inst.getOpcode() == iREP_OUTS)
{
out->addTaggedString(XT_Symbol,Machine_X86::regName(inst.src().segOver)); // szWreg[src.segOver-rAX]
}
else
{
out->addTaggedString(XT_Symbol,"es:[di]");
out->prtt(", ");
out->addTaggedString(XT_Symbol,Machine_X86::regName(inst.src().segOver));
}
out->addTaggedString(XT_Symbol,":[si]");
}
else
{
out->delChars(2); // TODO: this is wonky way of adding instruction suffix
if(inst.getFlag() & B)
out->addTaggedString(XT_Keyword,"B");
else
out->addTaggedString(XT_Keyword,"W");
out->addSpace(2);
}
break;
case iXLAT:
if (inst.src().segOver)
{
out->addTaggedString(XT_Keyword,QString(" ") + szPtr[1]);
out->addTaggedString(XT_Symbol,Machine_X86::regName(inst.src().segOver)+":[bx]");
}
break;
case iIN:
out->addTaggedString(XT_Symbol, (inst.getFlag() & B)? "al" : "ax");
out->prtt(", ");
formatter.visitOperand(inst.src());
break;
case iOUT:
{
formatter.visitOperand(inst.src());
if(inst.srcIsImmed())
out->addTaggedString(XT_Number, strHex(inst.src().getImm2()));
else
out->addTaggedString(XT_Symbol, "dx");
out->prtt(", ");
out->addTaggedString(XT_Symbol, (inst.getFlag() & B)? "al" : "ax");
}
}
out->addEOL();
}

View File

@@ -28,7 +28,7 @@
{IP_OUT_OF_RANGE ,"Instruction at location %06lX goes beyond loaded image\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"}, {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"}, {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"}, {NOT_DEF_USE ,"%x: Def - use not supported. Def op = %d, use op = %d.\n"},
{REPEAT_FAIL ,"Failed to construct repeat..until() condition.\n"}, {REPEAT_FAIL ,"Failed to construct repeat..until() condition.\n"},
{WHILE_FAIL ,"Failed to construct while() condition.\n"}, {WHILE_FAIL ,"Failed to construct while() condition.\n"},
}; };

View File

@@ -9,18 +9,15 @@
* * * *
\* * * * * * * * * * * * */ \* * * * * * * * * * * * */
#include "msvc_fixes.h"
#include <memory.h> #include <memory.h>
#include <stdint.h>
#ifndef PATLEN #ifndef PATLEN
#define PATLEN 23 #define PATLEN 23
#define WILD 0xF4 #define WILD 0xF4
#endif #endif
#ifndef bool
#define bool unsigned char
#define uint8_t unsigned char
#endif
static int pc; /* Indexes into pat[] */ static int pc; /* Indexes into pat[] */
/* prototypes */ /* prototypes */
@@ -410,7 +407,7 @@ void fixWildCards(uint8_t pat[])
case 0xCD: /* int nn */ case 0xCD: /* int nn */
intArg = pat[pc++]; intArg = pat[pc++];
if ((intArg >= 0x34) && (intArg <= 0x3B)) if ((intArg >= 0x34) and (intArg <= 0x3B))
{ {
/* Borland/Microsoft FP emulations */ /* Borland/Microsoft FP emulations */
if (ModRM(pat)) return; if (ModRM(pat)) return;

View File

@@ -82,7 +82,7 @@ bool DccFrontend::FrontEnd ()
if (option.asm1) 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 */ /* Search through code looking for impure references and flag them */

View File

@@ -3,22 +3,30 @@
* (C) Cristina Cifuentes * (C) Cristina Cifuentes
****************************************************************************/ ****************************************************************************/
#include <string.h> #include "graph.h"
#include "msvc_fixes.h"
#include "dcc.h"
#include "project.h"
#include <boost/range/rbegin.hpp> #include <boost/range/rbegin.hpp>
#include <boost/range/rend.hpp> #include <boost/range/rend.hpp>
#include <boost/range/adaptors.hpp> #include <string.h>
#include "dcc.h"
#include "graph.h"
#include "project.h"
using namespace std; using namespace std;
using namespace boost; using namespace boost;
extern Project g_proj;
//static BB * rmJMP(Function * pProc, int marker, BB * pBB); //static BB * rmJMP(Function * pProc, int marker, BB * pBB);
//static void mergeFallThrough(Function * pProc, BB * pBB); //static void mergeFallThrough(Function * pProc, BB * pBB);
//static void dfsNumbering(BB * pBB, std::vector<BB*> &dfsLast, int *first, int *last); //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 * createCFG - Create the basic control flow graph
****************************************************************************/ ****************************************************************************/
@@ -68,16 +76,13 @@ void Function::createCFG()
case iJO: case iJNO: case iJP: case iJNP: case iJO: case iJNO: case iJP: case iJNP:
case iJCXZ: case iJCXZ:
pBB = BB::Create(current_range, TWO_BRANCH, this); pBB = BB::Create(current_range, TWO_BRANCH, this);
CondJumps: addOutEdgesForConditionalJump(pBB,nextIcode->loc_ip, ll);
pBB->addOutEdge(nextIcode->loc_ip);
/* This is checking for jumps off into nowhere */
if ( not ll->testFlags(NO_LABEL) )
pBB->addOutEdge(ll->src().getImm2());
break; break;
case iLOOP: case iLOOPE: case iLOOPNE: case iLOOP: case iLOOPE: case iLOOPNE:
pBB = BB::Create(current_range, LOOP_NODE, this); pBB = BB::Create(current_range, LOOP_NODE, this);
goto CondJumps; addOutEdgesForConditionalJump(pBB,nextIcode->loc_ip, ll);
break;
case iJMPF: case iJMP: case iJMPF: case iJMP:
if (ll->testFlags(SWITCH)) if (ll->testFlags(SWITCH))
@@ -87,7 +92,7 @@ CondJumps:
pBB->addOutEdge(elem); pBB->addOutEdge(elem);
hasCase = true; hasCase = true;
} }
else if ((ll->getFlag() & (I | NO_LABEL)) == I) //TODO: WHY NO_LABEL TESTIT else if (ll->srcIsImmed() and not ll->testFlags(NO_LABEL)) //TODO: WHY NO_LABEL TESTIT
{ {
pBB = BB::Create(current_range, ONE_BRANCH, this); pBB = BB::Create(current_range, ONE_BRANCH, this);
pBB->addOutEdge(ll->src().getImm2()); pBB->addOutEdge(ll->src().getImm2());
@@ -100,7 +105,7 @@ CondJumps:
{ {
Function * p = ll->src().proc.proc; Function * p = ll->src().proc.proc;
pBB = BB::Create(current_range, CALL_NODE, this); pBB = BB::Create(current_range, CALL_NODE, this);
if (p && not ((p->flg) & TERMINATES) ) if (p and not ((p->flg) & TERMINATES) )
pBB->addOutEdge(nextIcode->loc_ip); pBB->addOutEdge(nextIcode->loc_ip);
break; break;
} }
@@ -132,6 +137,8 @@ CondJumps:
// end iterator will be updated by expression in for statement // end iterator will be updated by expression in for statement
current_range=make_iterator_range(nextIcode,nextIcode); current_range=make_iterator_range(nextIcode,nextIcode);
} }
if (nextIcode == Icode.end())
break;
} }
for (auto pr : m_ip_to_bb) for (auto pr : m_ip_to_bb)
{ {
@@ -146,7 +153,7 @@ CondJumps:
} }
auto iter2=m_ip_to_bb.find(ip); auto iter2=m_ip_to_bb.find(ip);
if(iter2==m_ip_to_bb.end()) if(iter2==m_ip_to_bb.end())
fatalError(NO_BB, ip, name.c_str()); fatalError(NO_BB, ip, qPrintable(name));
psBB = iter2->second; psBB = iter2->second;
elem.BBptr = psBB; elem.BBptr = psBB;
psBB->inEdges.push_back((BB *)nullptr); psBB->inEdges.push_back((BB *)nullptr);
@@ -203,7 +210,7 @@ void Function::compressCFG()
* (Un)Conditional -> Unconditional jump */ * (Un)Conditional -> Unconditional jump */
for (BB *pBB : m_actual_cfg) //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; continue;
for (TYPEADR_TYPE &edgeRef : pBB->edges) for (TYPEADR_TYPE &edgeRef : pBB->edges)
{ {
@@ -265,7 +272,7 @@ BB *BB::rmJMP(int marker, BB * pBB)
{ {
marker += (int)DFS_JMP; 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) if (pBB->traversed != marker)
{ {
@@ -292,7 +299,7 @@ BB *BB::rmJMP(int marker, BB * pBB)
do { do {
pBB = pBB->edges[0].BBptr; pBB = pBB->edges[0].BBptr;
pBB->inEdges.pop_back(); // was --numInedges pBB->inEdges.pop_back(); // was --numInedges
if (! pBB->inEdges.empty()) if (not pBB->inEdges.empty())
{ {
pBB->front().ll()->setFlags(NO_CODE); pBB->front().ll()->setFlags(NO_CODE);
pBB->front().invalidate(); pBB->front().invalidate();
@@ -314,11 +321,11 @@ BB *BB::rmJMP(int marker, BB * pBB)
void BB::mergeFallThrough( CIcodeRec &Icode) void BB::mergeFallThrough( CIcodeRec &Icode)
{ {
BB * pChild; BB * pChild;
if (!this) if (nullptr==this)
{ {
printf("mergeFallThrough on empty BB!\n"); 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; pChild = edges[0].BBptr;
/* Jump to next instruction can always be removed */ /* Jump to next instruction can always be removed */

View File

@@ -4,17 +4,17 @@
* Date: September-October 1993 * Date: September-October 1993
* (C) Cristina Cifuentes * (C) Cristina Cifuentes
*/ */
#include "dcc.h"
#include <QtCore/QDebug>
#include <QtCore/QString>
#include <cassert> #include <cassert>
#include <string.h> #include <string.h>
#include <string> #include <string>
#include <sstream> #include <sstream>
#include "dcc.h"
using namespace std; using namespace std;
static char buf[lineSize]; /* Line buffer for hl icode output */
/* Places the new HLI_ASSIGN high-level operand in the high-level icode array */ /* Places the new HLI_ASSIGN high-level operand in the high-level icode array */
void HLTYPE::setAsgn(Expr *lhs, Expr *rhs) void HLTYPE::setAsgn(Expr *lhs, Expr *rhs)
{ {
@@ -24,12 +24,12 @@ void HLTYPE::setAsgn(Expr *lhs, Expr *rhs)
} }
void ICODE::checkHlCall() 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 */ /* Places the new HLI_CALL high-level operand in the high-level icode array */
void ICODE::newCallHl() void ICODE::newCallHl()
{ {
type = HIGH_LEVEL; type = HIGH_LEVEL_ICODE;
hlU()->setCall(ll()->src().proc.proc); hlU()->setCall(ll()->src().proc.proc);
if (ll()->src().proc.cb != 0) if (ll()->src().proc.cb != 0)
@@ -48,7 +48,7 @@ void ICODE::newCallHl()
* array */ * array */
void ICODE::setUnary(hlIcode op, Expr *_exp) void ICODE::setUnary(hlIcode op, Expr *_exp)
{ {
type = HIGH_LEVEL; type = HIGH_LEVEL_ICODE;
hlU()->set(op,_exp); hlU()->set(op,_exp);
} }
@@ -56,7 +56,7 @@ void ICODE::setUnary(hlIcode op, Expr *_exp)
/* Places the new HLI_JCOND high-level operand in the high-level icode array */ /* Places the new HLI_JCOND high-level operand in the high-level icode array */
void ICODE::setJCond(Expr *cexp) void ICODE::setJCond(Expr *cexp)
{ {
type = HIGH_LEVEL; type = HIGH_LEVEL_ICODE;
hlU()->set(HLI_JCOND,cexp); hlU()->set(HLI_JCOND,cexp);
} }
@@ -83,7 +83,7 @@ bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId)
for ( ; numDefs > 0; numDefs--) for ( ; numDefs > 0; numDefs--)
{ {
if (du1.used(numDefs-1)||(du.lastDefRegi.testReg(regi))) if (du1.used(numDefs-1) or (du.lastDefRegi.testReg(regi)))
break; break;
} }
} }
@@ -320,7 +320,7 @@ void Function::highLevelGen()
LLOperand *src_ll = ll->get(SRC); LLOperand *src_ll = ll->get(SRC);
if ( ll->testFlags(NOT_HLL) ) if ( ll->testFlags(NOT_HLL) )
pIcode->invalidate(); pIcode->invalidate();
if ((pIcode->type != LOW_LEVEL) or not pIcode->valid() ) if ((pIcode->type != LOW_LEVEL_ICODE) or not pIcode->valid() )
continue; continue;
_flg = ll->getFlag(); _flg = ll->getFlag();
if (not ll->testFlags(IM_OPS)) /* not processing IM_OPS yet */ if (not ll->testFlags(IM_OPS)) /* not processing IM_OPS yet */
@@ -328,11 +328,11 @@ void Function::highLevelGen()
{ {
if ( not ll->testFlags(NO_SRC) ) /* if there is src op */ if ( not ll->testFlags(NO_SRC) ) /* if there is src op */
rhs = AstIdent::id (*pIcode->ll(), SRC, this, i, *pIcode, NONE); rhs = AstIdent::id (*pIcode->ll(), SRC, this, i, *pIcode, NONE);
if(ll->m_dst.isSet() || (ll->getOpcode()==iMOD)) if(ll->m_dst.isSet() or (ll->getOpcode()==iMOD))
lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE); lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
} }
if(ll->getOpcode()==iPUSH) { if(ll->getOpcode()==iPUSH) {
if(ll->testFlags(I)) { if(ll->srcIsImmed()) {
lhs = new Constant(src_ll->opz,src_ll->byteWidth()); lhs = new Constant(src_ll->opz,src_ll->byteWidth());
} }
// lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE); // lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
@@ -353,7 +353,7 @@ void Function::highLevelGen()
case iCALL: case iCALL:
case iCALLF: case iCALLF:
pIcode->type = HIGH_LEVEL; pIcode->type = HIGH_LEVEL_ICODE;
pIcode->hl( ll->createCall() ); pIcode->hl( ll->createCall() );
break; break;
@@ -399,7 +399,8 @@ void Function::highLevelGen()
} }
break; break;
case iMOV: pIcode->setAsgn(lhs, rhs); case iMOV:
pIcode->setAsgn(lhs, rhs);
break; break;
case iMUL: case iMUL:
@@ -432,7 +433,8 @@ void Function::highLevelGen()
break; break;
case iRET: case iRET:
case iRETF: pIcode->setUnary(HLI_RET, nullptr); case iRETF:
pIcode->setUnary(HLI_RET, nullptr);
break; break;
case iSHL: case iSHL:
@@ -461,6 +463,8 @@ void Function::highLevelGen()
rhs = new BinaryOperator(XOR,lhs, rhs); rhs = new BinaryOperator(XOR,lhs, rhs);
pIcode->setAsgn(lhs, rhs); pIcode->setAsgn(lhs, rhs);
break; break;
//TODO: default: // mostly to silence static analyzer warnings ?
// delete rhs;
} }
} }
@@ -477,82 +481,68 @@ void Function::highLevelGen()
/* Returns the string that represents the procedure call of tproc (ie. with /* Returns the string that represents the procedure call of tproc (ie. with
* actual parameters) */ * actual parameters) */
std::string Function::writeCall (Function * tproc, STKFRAME & args, int *numLoc) QString Function::writeCall (Function * tproc, STKFRAME & args, int *numLoc)
{ {
//string condExp; //string condExp;
ostringstream ostr; QString ostr;
ostr<<tproc->name<<" ("; ostr+=tproc->name+" (";
for(const STKSYM &sym : args) for(const STKSYM &sym : args)
{ {
if(sym.actual) if(sym.actual)
ostr << sym.actual->walkCondExpr (this, numLoc); ostr += sym.actual->walkCondExpr(this, numLoc);
else else
ostr << ""; ostr += "";
if((&sym)!=&(args.back())) if((&sym)!=&(args.back()))
ostr << ", "; ostr += ", ";
} }
ostr << ")"; ostr += ")";
return ostr.str(); return ostr;
} }
/* Displays the output of a HLI_JCOND icode. */ /* Displays the output of a HLI_JCOND icode. */
const char *writeJcond (const HLTYPE &h, Function * pProc, int *numLoc) QString writeJcond (const HLTYPE &h, Function * pProc, int *numLoc)
{ {
memset (buf, ' ', sizeof(buf));
buf[0] = '\0';
strcat (buf, "if ");
if(h.opcode==HLI_INVALID) if(h.opcode==HLI_INVALID)
{ {
return "if (*HLI_INVALID*) {\n"; return "if (*HLI_INVALID*) {\n";
} }
assert(h.expr()); assert(h.expr());
Expr *inverted=h.expr()->inverse(); Expr *inverted=h.expr()->inverse();
//inverseCondOp (&h.exp); //inverseCondOp (&h.exp);
std::string e = inverted->walkCondExpr (pProc, numLoc); QString inverted_form = inverted->walkCondExpr (pProc, numLoc);
delete inverted; delete inverted;
strcat (buf, e.c_str());
strcat (buf, " {\n"); return QString("if %1 {\n").arg(inverted_form);
return (buf);
} }
/* Displays the inverse output of a HLI_JCOND icode. This is used in the case /* 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 * when the THEN clause of an if..then..else is empty. The clause is
* negated and the ELSE clause is used instead. */ * negated and the ELSE clause is used instead. */
const char *writeJcondInv(HLTYPE h, Function * pProc, int *numLoc) QString writeJcondInv(HLTYPE h, Function * pProc, int *numLoc)
{ {
memset (buf, ' ', sizeof(buf)); QString _form;
buf[0] = '\0';
strcat (buf, "if ");
std::string e;
if(h.expr()==nullptr) if(h.expr()==nullptr)
e = "( *failed condition recovery* )"; _form = "( *failed condition recovery* )";
else else
e = h.expr()->walkCondExpr (pProc, numLoc); _form = h.expr()->walkCondExpr (pProc, numLoc);
return QString("if %1 {\n").arg(_form);
strcat (buf, e.c_str());
strcat (buf, " {\n");
return (buf);
} }
string AssignType::writeOut(Function *pProc, int *numLoc) const QString AssignType::writeOut(Function *pProc, int *numLoc) const
{ {
ostringstream ostr; return QString("%1 = %2;\n")
ostr << m_lhs->walkCondExpr (pProc, numLoc); .arg(m_lhs->walkCondExpr (pProc, numLoc))
ostr << " = "; .arg(m_rhs->walkCondExpr (pProc, numLoc));
ostr << rhs->walkCondExpr (pProc, numLoc);
ostr << ";\n";
return ostr.str();
} }
string CallType::writeOut(Function *pProc, int *numLoc) const QString CallType::writeOut(Function *pProc, int *numLoc) const
{ {
ostringstream ostr; return pProc->writeCall (proc, *args, numLoc) + ";\n";
ostr << pProc->writeCall (proc, *args, numLoc);
ostr << ";\n";
return ostr.str();
} }
string ExpType::writeOut(Function *pProc, int *numLoc) const QString ExpType::writeOut(Function *pProc, int *numLoc) const
{ {
if(v==nullptr) if(v==nullptr)
return ""; return "";
@@ -567,16 +557,15 @@ void HLTYPE::set(Expr *l, Expr *r)
//assert((asgn.lhs==0) and (asgn.rhs==0)); //prevent memory leaks //assert((asgn.lhs==0) and (asgn.rhs==0)); //prevent memory leaks
assert(dynamic_cast<UnaryOperator *>(l)); assert(dynamic_cast<UnaryOperator *>(l));
asgn.m_lhs=l; asgn.m_lhs=l;
asgn.rhs=r; asgn.m_rhs=r;
} }
/* Returns a string with the contents of the current high-level icode. /** 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 * \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 * done in a separate routine to be able to support the removal of
* empty THEN clauses on an if..then..else. */ * empty THEN clauses on an if..then..else.
string HLTYPE::write1HlIcode (Function * pProc, int *numLoc) const */
QString HLTYPE::write1HlIcode (Function * pProc, int *numLoc) const
{ {
string e;
ostringstream ostr;
const HlTypeSupport *p = get(); const HlTypeSupport *p = get();
switch (opcode) switch (opcode)
{ {
@@ -585,26 +574,23 @@ string HLTYPE::write1HlIcode (Function * pProc, int *numLoc) const
case HLI_CALL: case HLI_CALL:
return p->writeOut(pProc,numLoc); return p->writeOut(pProc,numLoc);
case HLI_RET: case HLI_RET:
{
QString e;
e = p->writeOut(pProc,numLoc); e = p->writeOut(pProc,numLoc);
if (! e.empty()) if (not e.isEmpty())
ostr << "return (" << e << ");\n"; return QString("return (%1);\n").arg(e);
break; break;
}
case HLI_POP: case HLI_POP:
ostr << "HLI_POP "; return QString("HLI_POP %1\n").arg(p->writeOut(pProc,numLoc));
ostr << p->writeOut(pProc,numLoc);
ostr << "\n";
break;
case HLI_PUSH: case HLI_PUSH:
ostr << "HLI_PUSH "; return QString("HLI_PUSH %1\n").arg(p->writeOut(pProc,numLoc));
ostr << p->writeOut(pProc,numLoc);
ostr << "\n";
break;
case HLI_JCOND: //Handled elsewhere case HLI_JCOND: //Handled elsewhere
break; break;
default: default:
fprintf(stderr," HLTYPE::write1HlIcode - Unhandled opcode %d\n",opcode); qCritical() << " HLTYPE::write1HlIcode - Unhandled opcode" << opcode;
} }
return ostr.str(); return "";
} }
@@ -619,16 +605,22 @@ void ICODE::writeDU()
{ {
int my_idx = loc_ip; int my_idx = loc_ip;
{ {
ostringstream ostr; QString ostr_contents;
{
QTextStream ostr(&ostr_contents);
Machine_X86::writeRegVector(ostr,du.def); Machine_X86::writeRegVector(ostr,du.def);
if (!ostr.str().empty()) }
printf ("Def (reg) = %s\n", ostr.str().c_str()); if (not ostr_contents.isEmpty())
qDebug() << QString("Def (reg) = %1\n").arg(ostr_contents);
} }
{ {
ostringstream ostr; QString ostr_contents;
{
QTextStream ostr(&ostr_contents);
Machine_X86::writeRegVector(ostr,du.use); Machine_X86::writeRegVector(ostr,du.use);
if (!ostr.str().empty()) }
printf ("Use (reg) = %s\n", ostr.str().c_str()); if (not ostr_contents.isEmpty())
qDebug() << QString("Use (reg) = %1\n").arg(ostr_contents);
} }
/* Print du1 chain */ /* Print du1 chain */

View File

@@ -1,24 +1,22 @@
// Object oriented icode code for dcc // Object oriented icode code for dcc
// (C) 1997 Mike Van Emmerik // (C) 1997 Mike Van Emmerik
#include "icode.h"
#include <stdlib.h> #include "msvc_fixes.h"
#include "dcc.h" #include "dcc.h"
#include "types.h" // Common types like uint8_t, etc #include "types.h" // Common types like uint8_t, etc
#include "ast.h" // Some icode types depend on these #include "ast.h" // Some icode types depend on these
#include "icode.h"
#include <stdlib.h>
ICODE::TypeFilter<HIGH_LEVEL> ICODE::select_high_level; ICODE::TypeFilter<HIGH_LEVEL_ICODE> ICODE::select_high_level;
ICODE::TypeAndValidFilter<HIGH_LEVEL> ICODE::select_valid_high_level; ICODE::TypeAndValidFilter<HIGH_LEVEL_ICODE> ICODE::select_valid_high_level;
CIcodeRec::CIcodeRec() CIcodeRec::CIcodeRec()
{ {
} }
/* Copies the icode that is pointed to by pIcode to the icode array. /* Copies the icode that is pointed to by pIcode to the icode array. */
* If there is need to allocate extra memory, it is done so, and ICODE * CIcodeRec::addIcode(const ICODE *pIcode)
* the alloc variable is adjusted. */
ICODE * CIcodeRec::addIcode(ICODE *pIcode)
{ {
push_back(*pIcode); push_back(*pIcode);
back().loc_ip = size()-1; back().loc_ip = size()-1;
@@ -67,6 +65,15 @@ extern bundle cCode;
* is created and a goto is also emitted. * is created and a goto is also emitted.
* Note: this procedure is to be used when the label is to be backpatched * Note: this procedure is to be used when the label is to be backpatched
* onto code in cCode.code */ * onto code in cCode.code */
void LLInst::clrFlags(uint32_t flag)
{
if(getOpcode()==iMOD)
{
assert(false);
}
flg &= ~flag;
}
void LLInst::emitGotoLabel (int indLevel) void LLInst::emitGotoLabel (int indLevel)
{ {
if ( not testFlags(HLL_LABEL) ) /* node hasn't got a lab */ if ( not testFlags(HLL_LABEL) ) /* node hasn't got a lab */
@@ -75,8 +82,7 @@ void LLInst::emitGotoLabel (int indLevel)
hllLabNum = getNextLabel(); hllLabNum = getNextLabel();
setFlags(HLL_LABEL); setFlags(HLL_LABEL);
/* Node has been traversed already, so backpatch this label into /* Node has been traversed already, so backpatch this label into the code */
* the code */
cCode.code.addLabelBundle (codeIdx, hllLabNum); cCode.code.addLabelBundle (codeIdx, hllLabNum);
} }
cCode.appendCode( "%sgoto L%ld;\n", indentStr(indLevel), hllLabNum); cCode.appendCode( "%sgoto L%ld;\n", indentStr(indLevel), hllLabNum);
@@ -87,9 +93,9 @@ void LLInst::emitGotoLabel (int indLevel)
bool LLOperand::isReg() const bool LLOperand::isReg() const
{ {
return (regi>=rAX) && (regi<=rTMP); return (regi>=rAX) and (regi<=rTMP);
} }
void LLOperand::addProcInformation(int param_count, CConv::Type call_conv) void LLOperand::addProcInformation(int param_count, CConv::CC_Type call_conv)
{ {
proc.proc->cbParam = (int16_t)param_count; proc.proc->cbParam = (int16_t)param_count;
proc.cb = param_count; proc.cb = param_count;

View File

@@ -3,10 +3,12 @@
* (C) Cristina Cifuentes * (C) Cristina Cifuentes
****************************************************************************/ ****************************************************************************/
#include <llvm/Support/PatternMatch.h> //#include <llvm/Config/llvm-config.h>
#include <boost/iterator/filter_iterator.hpp> //#if( (LLVM_VERSION_MAJOR==3 ) and (LLVM_VERSION_MINOR>3) )
#include <cstring> //#include <llvm/IR/PatternMatch.h>
#include <deque> //#else
//#include <llvm/Support/PatternMatch.h>
//#endif
#include "idiom.h" #include "idiom.h"
#include "idiom1.h" #include "idiom1.h"
#include "epilogue_idioms.h" #include "epilogue_idioms.h"
@@ -17,6 +19,11 @@
#include "shift_idioms.h" #include "shift_idioms.h"
#include "arith_idioms.h" #include "arith_idioms.h"
#include "dcc.h" #include "dcc.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 * JmpInst - Returns true if opcode is a conditional or unconditional jump
****************************************************************************/ ****************************************************************************/
@@ -117,11 +124,10 @@ void Function::findIdioms()
/* Check for library functions that return a long register. /* Check for library functions that return a long register.
* Propagate this result */ * Propagate this result */
if (pIcode->ll()->src().proc.proc != nullptr) if (pIcode->ll()->src().proc.proc != nullptr)
if ((pIcode->ll()->src().proc.proc->flg & PROC_ISLIB) && if ( pIcode->ll()->src().proc.proc->flg & PROC_ISLIB )
(pIcode->ll()->src().proc.proc->flg & PROC_IS_FUNC))
{ {
if ((pIcode->ll()->src().proc.proc->retVal.type==TYPE_LONG_SIGN) if ((pIcode->ll()->src().proc.proc->getReturnType()==TYPE_LONG_SIGN)
|| (pIcode->ll()->src().proc.proc->retVal.type == TYPE_LONG_UNSIGN)) or (pIcode->ll()->src().proc.proc->getReturnType() == TYPE_LONG_UNSIGN))
localId.newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(rDX,rAX), pIcode/*ip*/); localId.newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(rDX,rAX), pIcode/*ip*/);
} }
@@ -204,10 +210,10 @@ void Function::findIdioms()
} }
/* Check if number of parameter bytes match their calling convention */ /* 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 ? 4 : 2);
delta = args.maxOff - args.m_minOff; delta = args.m_maxOff - args.m_minOff;
if (cbParam != delta) if (cbParam != delta)
{ {
cbParam = delta; cbParam = delta;
@@ -231,7 +237,7 @@ void Function::bindIcodeOff()
for(ICODE &c : Icode) // TODO: use filtered here for(ICODE &c : Icode) // TODO: use filtered here
{ {
LLInst *ll=c.ll(); LLInst *ll=c.ll();
if (ll->testFlags(I) && ll->isJmpInst()) if (ll->srcIsImmed() and ll->isJmpInst())
{ {
iICODE loc=Icode.labelSrch(ll->src().getImm2()); iICODE loc=Icode.labelSrch(ll->src().getImm2());
if (loc!=Icode.end()) if (loc!=Icode.end())
@@ -248,10 +254,10 @@ void Function::bindIcodeOff()
LLInst *ll=icode.ll(); LLInst *ll=icode.ll();
if (not ll->isJmpInst()) if (not ll->isJmpInst())
continue; continue;
if (ll->testFlags(I) ) if (ll->srcIsImmed())
{ {
uint32_t found; uint32_t found;
if (! Icode.labelSrch(ll->src().getImm2(), found)) if (not Icode.labelSrch(ll->src().getImm2(), found))
ll->setFlags( NO_LABEL ); ll->setFlags( NO_LABEL );
else else
ll->replaceSrc(LLOperand::CreateImm2(found)); ll->replaceSrc(LLOperand::CreateImm2(found));

View File

@@ -1,5 +1,10 @@
#include "dcc.h"
#include "arith_idioms.h" #include "arith_idioms.h"
#include "dcc.h"
#include "msvc_fixes.h"
#include <QtCore/QDebug>
using namespace std; using namespace std;
/***************************************************************************** /*****************************************************************************
@@ -105,7 +110,7 @@ bool Idiom18::match(iICODE picode)
if(not m_icodes[0]->ll()->matchWithRegDst(iMOV) ) if(not m_icodes[0]->ll()->matchWithRegDst(iMOV) )
return false; return false;
regi = m_icodes[0]->ll()->m_dst.regi; regi = m_icodes[0]->ll()->m_dst.regi;
if( not ( m_icodes[2]->ll()->match(iCMP,regi) && if( not ( m_icodes[2]->ll()->match(iCMP,regi) and
m_icodes[3]->ll()->conditionalJump() ) ) m_icodes[3]->ll()->conditionalJump() ) )
return false; return false;
// Simple matching finished, select apropriate matcher based on dst type // Simple matching finished, select apropriate matcher based on dst type
@@ -118,9 +123,9 @@ bool Idiom18::match(iICODE picode)
else if ( m_icodes[1]->ll()->m_dst.isReg() ) /* register */ else if ( m_icodes[1]->ll()->m_dst.isReg() ) /* register */
{ {
m_idiom_type = 1; m_idiom_type = 1;
// if ((m_icodes[1]->ll()->dst.regi == rSI) && (m_func->flg & SI_REGVAR)) // if ((m_icodes[1]->ll()->dst.regi == rSI) and (m_func->flg & SI_REGVAR))
// m_idiom_type = 1; // m_idiom_type = 1;
// else if ((m_icodes[1]->ll()->dst.regi == rDI) && (m_func->flg & DI_REGVAR)) // else if ((m_icodes[1]->ll()->dst.regi == rDI) and (m_func->flg & DI_REGVAR))
// m_idiom_type = 1; // m_idiom_type = 1;
} }
else if (m_icodes[1]->ll()->m_dst.off) /* local variable */ else if (m_icodes[1]->ll()->m_dst.off) /* local variable */
@@ -131,7 +136,8 @@ bool Idiom18::match(iICODE picode)
/* not supported yet */ /* not supported yet */
ICODE &ic(*picode); ICODE &ic(*picode);
const Function *my_proc(ic.getParent()->getParent()); const Function *my_proc(ic.getParent()->getParent());
printf("Unsupported idiom18 type at %x in %s:%x : indexed\n",ic.loc_ip,my_proc->name.c_str(),my_proc->procEntry); qWarning() << "Unsupported idiom18 type at"<< QString::number(ic.loc_ip,16)
<< "in"<< my_proc->name <<':'<< QString::number(my_proc->procEntry,16) << "- indexed";
} }
switch(m_idiom_type) switch(m_idiom_type)
@@ -204,8 +210,8 @@ bool Idiom19::match(iICODE picode)
/* not supported yet */ ; /* not supported yet */ ;
else if ( m_icodes[0]->ll()->m_dst.isReg() ) /* register */ else if ( m_icodes[0]->ll()->m_dst.isReg() ) /* register */
{ {
// if (((picode->ll()->dst.regi == rSI) && (pproc->flg & SI_REGVAR)) || // if (((picode->ll()->dst.regi == rSI) and (pproc->flg & SI_REGVAR)) or
// ((picode->ll()->dst.regi == rDI) && (pproc->flg & DI_REGVAR))) // ((picode->ll()->dst.regi == rDI) and (pproc->flg & DI_REGVAR)))
return true; return true;
} }
else if (m_icodes[0]->ll()->m_dst.off) /* stack variable */ else if (m_icodes[0]->ll()->m_dst.off) /* stack variable */
@@ -271,9 +277,9 @@ bool Idiom20::match(iICODE picode)
else if ( ll_dest.isReg() ) /* register */ else if ( ll_dest.isReg() ) /* register */
{ {
type = 1; type = 1;
// if ((ll_dest.regi == rSI) && (m_func->flg & SI_REGVAR)) // if ((ll_dest.regi == rSI) and (m_func->flg & SI_REGVAR))
// type = 1; // type = 1;
// else if ((ll_dest.regi == rDI) && (m_func->flg & DI_REGVAR)) // else if ((ll_dest.regi == rDI) and (m_func->flg & DI_REGVAR))
// type = 1; // type = 1;
} }
else if (ll_dest.off) /* local variable */ else if (ll_dest.off) /* local variable */
@@ -286,7 +292,7 @@ bool Idiom20::match(iICODE picode)
} }
regi = m_icodes[1]->ll()->m_dst.regi; regi = m_icodes[1]->ll()->m_dst.regi;
const LLOperand &mov_src(m_icodes[1]->ll()->src()); const LLOperand &mov_src(m_icodes[1]->ll()->src());
if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) && m_icodes[3]->ll()->conditionalJump()) if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) and m_icodes[3]->ll()->conditionalJump())
{ {
switch(type) switch(type)
{ {

View File

@@ -1,5 +1,8 @@
#include "dcc.h"
#include "call_idioms.h" #include "call_idioms.h"
#include "dcc.h"
#include "msvc_fixes.h"
using namespace std; using namespace std;
/***************************************************************************** /*****************************************************************************
* idiom3 - C calling convention. * idiom3 - C calling convention.
@@ -22,7 +25,7 @@ bool Idiom3::match(iICODE picode)
/* Match ADD SP, immed */ /* Match ADD SP, immed */
for(int i=0; i<2; ++i) for(int i=0; i<2; ++i)
m_icodes[i] = picode++; m_icodes[i] = picode++;
if ( m_icodes[1]->ll()->testFlags(I) && m_icodes[1]->ll()->match(iADD,rSP)) if ( m_icodes[1]->ll()->srcIsImmed() and m_icodes[1]->ll()->match(iADD,rSP))
{ {
m_param_count = m_icodes[1]->ll()->src().getImm2(); m_param_count = m_icodes[1]->ll()->src().getImm2();
return true; return true;
@@ -36,7 +39,7 @@ bool Idiom3::match(iICODE picode)
} }
int Idiom3::action() int Idiom3::action()
{ {
if (m_icodes[0]->ll()->testFlags(I) ) if (m_icodes[0]->ll()->srcIsImmed())
{ {
m_icodes[0]->ll()->src().addProcInformation(m_param_count,CConv::C); m_icodes[0]->ll()->src().addProcInformation(m_param_count,CConv::C);
} }
@@ -78,10 +81,10 @@ bool Idiom17::match(iICODE picode)
{ {
int i=0; int i=0;
regi = m_icodes[1]->ll()->m_dst.regi; regi = m_icodes[1]->ll()->m_dst.regi;
if ((regi >= rAX) && (regi <= rBX)) if ((regi >= rAX) and (regi <= rBX))
i++; i++;
while (picode != m_end && picode->ll()->match(iPOP)) while (picode != m_end and picode->ll()->match(iPOP))
{ {
if (picode->ll()->m_dst.regi != regi) if (picode->ll()->m_dst.regi != regi)
break; break;
@@ -94,7 +97,7 @@ bool Idiom17::match(iICODE picode)
} }
int Idiom17::action() int Idiom17::action()
{ {
if (m_icodes[0]->ll()->testFlags(I)) if (m_icodes[0]->ll()->srcIsImmed())
{ {
m_icodes[0]->ll()->src().addProcInformation(m_param_count,CConv::C); m_icodes[0]->ll()->src().addProcInformation(m_param_count,CConv::C);
for(size_t idx=1; idx<m_icodes.size(); ++idx) for(size_t idx=1; idx<m_icodes.size(); ++idx)

View File

@@ -1,6 +1,8 @@
#include "dcc.h"
#include "epilogue_idioms.h" #include "epilogue_idioms.h"
#include "dcc.h"
#include "msvc_fixes.h"
/***************************************************************************** /*****************************************************************************
* popStkVars - checks for * popStkVars - checks for
* [POP DI] * [POP DI]
@@ -14,9 +16,9 @@ void EpilogIdiom::popStkVars(iICODE pIcode)
/* Match [POP DI] */ /* Match [POP DI] */
if (pIcode->ll()->match(iPOP)) 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); 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); m_icodes.push_front(pIcode);
} }
++pIcode; ++pIcode;
@@ -25,9 +27,9 @@ void EpilogIdiom::popStkVars(iICODE pIcode)
/* Match [POP SI] */ /* Match [POP SI] */
if (pIcode->ll()->match(iPOP)) 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); 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); m_icodes.push_front(pIcode);
} }
} }
@@ -46,7 +48,7 @@ bool Idiom2::match(iICODE pIcode)
iICODE nicode; iICODE nicode;
if(pIcode==m_func->Icode.begin()) // pIcode->loc_ip == 0 if(pIcode==m_func->Icode.begin()) // pIcode->loc_ip == 0
return false; return false;
if ( pIcode->ll()->testFlags(I) || (not pIcode->ll()->match(rSP,rBP)) ) if ( pIcode->ll()->srcIsImmed() or (not pIcode->ll()->match(rSP,rBP)) )
return false; return false;
if(distance(pIcode,m_end)<3) if(distance(pIcode,m_end)<3)
return false; return false;
@@ -55,21 +57,21 @@ bool Idiom2::match(iICODE pIcode)
m_icodes.push_back(pIcode); m_icodes.push_back(pIcode);
/* Get next icode, skip over holes in the icode array */ /* Get next icode, skip over holes in the icode array */
nicode = ++iICODE(pIcode); nicode = ++iICODE(pIcode);
while (nicode->ll()->testFlags(NO_CODE) && (nicode != m_end)) while (nicode->ll()->testFlags(NO_CODE) and (nicode != m_end))
{ {
nicode++; nicode++;
} }
if(nicode == m_end) if(nicode == m_end)
return false; return false;
//TODO: strange test here - 'I' means instruction has immediate source operand
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 m_icodes.push_back(nicode++); // Matched POP BP
/* Match RET(F) */ /* Match RET(F) */
if ( nicode != m_end && if ( nicode != m_end and
!(nicode->ll()->testFlags(I | TARGET | CASE)) && not (nicode->ll()->testFlags(I | TARGET | CASE)) and
(nicode->ll()->match(iRET) || nicode->ll()->match(iRETF)) nicode->ll()->matchAny({iRET,iRETF})
) )
{ {
m_icodes.push_back(nicode); // Matched RET m_icodes.push_back(nicode); // Matched RET
@@ -118,7 +120,7 @@ bool Idiom4::match(iICODE pIcode)
{ {
iICODE prev1 = --iICODE(pIcode); iICODE prev1 = --iICODE(pIcode);
/* Check for POP BP */ /* 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()->srcIsImmed() )
m_icodes.push_back(prev1); m_icodes.push_back(prev1);
else if(prev1!=m_func->Icode.begin()) else if(prev1!=m_func->Icode.begin())
{ {
@@ -129,7 +131,7 @@ bool Idiom4::match(iICODE pIcode)
} }
/* Check for RET(F) immed */ /* Check for RET(F) immed */
if (pIcode->ll()->testFlags(I) ) if (pIcode->ll()->srcIsImmed() )
{ {
m_param_count = (int16_t)pIcode->ll()->src().getImm2(); m_param_count = (int16_t)pIcode->ll()->src().getImm2();
return true; return true;
@@ -138,7 +140,7 @@ bool Idiom4::match(iICODE pIcode)
} }
int Idiom4::action() 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 for(size_t idx=0; idx<m_icodes.size()-1; ++idx) // don't invalidate last entry
m_icodes[idx]->invalidate(); m_icodes[idx]->invalidate();

View File

@@ -1,5 +1,8 @@
#include "idiom1.h" #include "idiom1.h"
#include "dcc.h" #include "dcc.h"
#include "msvc_fixes.h"
/***************************************************************************** /*****************************************************************************
* checkStkVars - Checks for PUSH SI * checkStkVars - Checks for PUSH SI
@@ -19,14 +22,14 @@ int Idiom1::checkStkVars (iICODE pIcode)
{ {
si_matched = 1; si_matched = 1;
++pIcode; ++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; di_matched = 1;
} }
else if (pIcode->ll()->match(iPUSH,rDI)) else if (pIcode->ll()->match(iPUSH,rDI))
{ {
di_matched = 1; di_matched = 1;
++pIcode; ++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; si_matched = 1;
} }
m_func->flg |= (si_matched ? SI_REGVAR : 0) | (di_matched ? DI_REGVAR : 0); 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_icodes.clear();
m_min_off = 0; m_min_off = 0;
/* PUSH BP as first instruction of procedure */ /* PUSH BP as first instruction of procedure */
if ( (not picode->ll()->testFlags(I)) && picode->ll()->src().regi == rBP) if ( (not picode->ll()->srcIsImmed()) and picode->ll()->src().regi == rBP)
{ {
m_icodes.push_back( picode++ ); // insert iPUSH m_icodes.push_back( picode++ ); // insert iPUSH
if(picode==m_end) if(picode==m_end)
return false; return false;
/* MOV BP, SP as next instruction */ /* 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 m_icodes.push_back( picode++ ); // insert iMOV
if(picode==m_end) if(picode==m_end)
@@ -75,7 +78,7 @@ bool Idiom1::match(iICODE picode)
/* Look for SUB SP, immed */ /* Look for SUB SP, immed */
if ( 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 m_icodes.push_back( picode++ ); // insert iSUB
@@ -98,8 +101,8 @@ bool Idiom1::match(iICODE picode)
if(picode == m_end) if(picode == m_end)
return false; return false;
/* Look for MOV BP, SP */ /* Look for MOV BP, SP */
if ( picode != m_end && if ( picode != m_end and
!picode->ll()->testFlags(I | TARGET | CASE) && not picode->ll()->testFlags(I | TARGET | CASE) and
picode->ll()->match(iMOV,rBP,rSP)) picode->ll()->match(iMOV,rBP,rSP))
{ {
m_icodes.push_back(picode); m_icodes.push_back(picode);
@@ -119,7 +122,7 @@ bool Idiom1::match(iICODE picode)
m_icodes.push_back(picode++); m_icodes.push_back(picode++);
} }
return !m_icodes.empty(); return not m_icodes.empty();
} }
int Idiom1::action() int Idiom1::action()
{ {

View File

@@ -1,5 +1,8 @@
#include "dcc.h"
#include "mov_idioms.h" #include "mov_idioms.h"
#include "dcc.h"
#include "msvc_fixes.h"
using namespace std; using namespace std;
/***************************************************************************** /*****************************************************************************
@@ -27,20 +30,20 @@ bool Idiom14::match(iICODE pIcode)
return false; return false;
m_icodes[0]=pIcode++; m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++; m_icodes[1]=pIcode++;
LLInst * matched [] = {m_icodes[0]->ll(),m_icodes[1]->ll()}; LLInst * matched [] {m_icodes[0]->ll(),m_icodes[1]->ll()};
/* Check for regL */ /* Check for regL */
m_regL = m_icodes[0]->ll()->m_dst.regi; m_regL = matched[0]->m_dst.regi;
if (not m_icodes[0]->ll()->testFlags(I) && ((m_regL == rAX) || (m_regL ==rBX))) if (not matched[0]->srcIsImmed() and ((m_regL == rAX) or (m_regL ==rBX)))
{ {
/* Check for XOR regH, regH */ /* 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]->srcIsImmed())
{ {
m_regH = m_icodes[1]->ll()->m_dst.regi; m_regH = matched[1]->m_dst.regi;
if (m_regH == m_icodes[1]->ll()->src().getReg2()) if (m_regH == matched[1]->src().getReg2())
{ {
if ((m_regL == rAX) && (m_regH == rDX)) if ((m_regL == rAX) and (m_regH == rDX))
return true; return true;
if ((m_regL == rBX) && (m_regH == rCX)) if ((m_regL == rBX) and (m_regH == rCX))
return true; return true;
} }
} }
@@ -49,14 +52,11 @@ bool Idiom14::match(iICODE pIcode)
} }
int Idiom14::action() int Idiom14::action()
{ {
int idx;
AstIdent *lhs;
Expr *rhs;
idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(m_regH,m_regL), m_icodes[0]); int idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(m_regH,m_regL), m_icodes[0]);
lhs = AstIdent::LongIdx (idx); AstIdent *lhs = AstIdent::LongIdx (idx);
m_icodes[0]->setRegDU( m_regH, eDEF); m_icodes[0]->setRegDU( m_regH, eDEF);
rhs = AstIdent::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[0]->setAsgn(lhs, rhs);
m_icodes[1]->invalidate(); m_icodes[1]->invalidate();
return 2; return 2;
@@ -84,10 +84,10 @@ bool Idiom13::match(iICODE pIcode)
/* Check for regL */ /* Check for regL */
regi = m_icodes[0]->ll()->m_dst.regi; regi = m_icodes[0]->ll()->m_dst.regi;
if (not m_icodes[0]->ll()->testFlags(I) && (regi >= rAL) && (regi <= rBH)) if (not m_icodes[0]->ll()->srcIsImmed() and (regi >= rAL) and (regi <= rBH))
{ {
/* Check for MOV regH, 0 */ /* 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()->m_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.
{ {

View File

@@ -1,5 +1,8 @@
#include "dcc.h"
#include "neg_idioms.h" #include "neg_idioms.h"
#include "dcc.h"
#include "msvc_fixes.h"
using namespace std; using namespace std;
@@ -23,7 +26,7 @@ bool Idiom11::match (iICODE picode)
for(int i=0; i<3; ++i) for(int i=0; i<3; ++i)
m_icodes[i]=picode++; m_icodes[i]=picode++;
type = m_icodes[0]->ll()->idType(DST); type = m_icodes[0]->ll()->idType(DST);
if(type==CONSTANT || type == OTHER) if(type==CONSTANT or type == OTHER)
return false; return false;
/* Check NEG reg/mem /* Check NEG reg/mem
* SBB reg/mem, 0*/ * SBB reg/mem, 0*/
@@ -32,7 +35,7 @@ bool Idiom11::match (iICODE picode)
switch (type) switch (type)
{ {
case GLOB_VAR: case GLOB_VAR:
if ((m_icodes[2]->ll()->m_dst.segValue == m_icodes[0]->ll()->m_dst.segValue) && 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)) (m_icodes[2]->ll()->m_dst.off == m_icodes[0]->ll()->m_dst.off))
return true; return true;
break; break;
@@ -83,11 +86,11 @@ bool Idiom16::match (iICODE picode)
m_icodes[i]=picode++; m_icodes[i]=picode++;
uint8_t regi = m_icodes[0]->ll()->m_dst.regi; uint8_t regi = m_icodes[0]->ll()->m_dst.regi;
if ((regi >= rAX) && (regi < INDEX_BX_SI)) 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()->match(iSBB) and m_icodes[2]->ll()->match(iINC))
if ((m_icodes[1]->ll()->m_dst.regi == (m_icodes[1]->ll()->src().getReg2())) && if ((m_icodes[1]->ll()->m_dst.regi == (m_icodes[1]->ll()->src().getReg2())) and
m_icodes[1]->ll()->match((eReg)regi) && m_icodes[1]->ll()->match((eReg)regi) and
m_icodes[2]->ll()->match((eReg)regi)) m_icodes[2]->ll()->match((eReg)regi))
return true; return true;
} }

View File

@@ -1,5 +1,8 @@
#include "dcc.h"
#include "shift_idioms.h" #include "shift_idioms.h"
#include "dcc.h"
#include "msvc_fixes.h"
using namespace std; using namespace std;
@@ -18,8 +21,8 @@ bool Idiom8::match(iICODE pIcode)
return false; return false;
m_icodes[0]=pIcode++; m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++; m_icodes[1]=pIcode++;
if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1)) if (m_icodes[0]->ll()->srcIsImmed() and (m_icodes[0]->ll()->src().getImm2() == 1))
if ( m_icodes[1]->ll()->match(iRCR,I) && if ( m_icodes[1]->ll()->match(iRCR,I) and
(m_icodes[1]->ll()->src().getImm2() == 1)) (m_icodes[1]->ll()->src().getImm2() == 1))
return true; return true;
return false; return false;
@@ -62,7 +65,7 @@ bool Idiom15::match(iICODE pIcode)
if(distance(pIcode,m_end)<2) if(distance(pIcode,m_end)<2)
return false; return false;
/* Match SHL reg, 1 */ /* Match SHL reg, 1 */
if (not pIcode->ll()->testFlags(I) or (pIcode->ll()->src().getImm2() != 1)) if (not pIcode->ll()->srcIsImmed() or (pIcode->ll()->src().getImm2() != 1))
return false; return false;
m_icodes.clear(); m_icodes.clear();
regi = pIcode->ll()->m_dst.regi; regi = pIcode->ll()->m_dst.regi;
@@ -107,8 +110,8 @@ bool Idiom12::match(iICODE pIcode)
return false; return false;
m_icodes[0]=pIcode++; m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++; m_icodes[1]=pIcode++;
if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1)) if (m_icodes[0]->ll()->srcIsImmed() and (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[1]->ll()->match(iRCL,I) and (m_icodes[1]->ll()->src().getImm2() == 1))
return true; return true;
return false; return false;
} }
@@ -147,8 +150,8 @@ bool Idiom9::match(iICODE pIcode)
return false; return false;
m_icodes[0]=pIcode++; m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++; m_icodes[1]=pIcode++;
if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1)) if (m_icodes[0]->ll()->srcIsImmed() and (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[1]->ll()->match(iRCR,I) and (m_icodes[1]->ll()->src().getImm2() == 1))
return true; return true;
return false; return false;
} }

View File

@@ -1,5 +1,8 @@
#include "dcc.h"
#include "xor_idioms.h" #include "xor_idioms.h"
#include "dcc.h"
#include "msvc_fixes.h"
using namespace std; using namespace std;
/***************************************************************************** /*****************************************************************************
@@ -23,16 +26,16 @@ bool Idiom21::match (iICODE picode)
m_icodes[0]=picode++; m_icodes[0]=picode++;
m_icodes[1]=picode++; m_icodes[1]=picode++;
if (not m_icodes[1]->ll()->testFlags(I)) if (not m_icodes[1]->ll()->srcIsImmed())
return false; return false;
dst = &m_icodes[0]->ll()->m_dst; dst = &m_icodes[0]->ll()->m_dst;
src = &m_icodes[0]->ll()->src(); 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; 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 true;
} }
return false; return false;
@@ -67,7 +70,7 @@ bool Idiom7::match(iICODE picode)
src = &picode->ll()->src(); src = &picode->ll()->src();
if (dst->regi == 0) /* global variable */ 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; return true;
} }
else if (dst->regi < INDEX_BX_SI) /* register */ else if (dst->regi < INDEX_BX_SI) /* register */
@@ -75,17 +78,17 @@ bool Idiom7::match(iICODE picode)
if (dst->regi == src->regi) if (dst->regi == src->regi)
return true; 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 true;
} }
return false; return false;
} }
int Idiom7::action() int Idiom7::action()
{ {
Expr *lhs; Expr *lhs = AstIdent::id (*m_icode->ll(), DST, m_func, m_icode, *m_icode, NONE);
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->setAsgn(dynamic_cast<AstIdent *>(lhs), new Constant(0, 2));
m_icode->du.use.reset(); /* clear register used in iXOR */ m_icode->du.use.reset(); /* clear register used in iXOR */
m_icode->ll()->setFlags(I); m_icode->ll()->setFlags(I);
@@ -114,8 +117,8 @@ bool Idiom10::match(iICODE pIcode)
m_icodes[0]=pIcode++; m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++; m_icodes[1]=pIcode++;
/* Check OR reg, reg */ /* Check OR reg, reg */
if (not m_icodes[0]->ll()->testFlags(I) && if (not m_icodes[0]->ll()->srcIsImmed() and
m_icodes[0]->ll()->src().isReg() && m_icodes[0]->ll()->src().isReg() and
(m_icodes[0]->ll()->src().getReg2() == m_icodes[0]->ll()->m_dst.getReg2())) (m_icodes[0]->ll()->src().getReg2() == m_icodes[0]->ll()->m_dst.getReg2()))
if (m_icodes[1]->ll()->match(iJNE)) //.conditionalJump() if (m_icodes[1]->ll()->match(iJNE)) //.conditionalJump()
{ {

View File

@@ -4,10 +4,13 @@
* Date: October 1993 * Date: October 1993
* (C) Cristina Cifuentes * (C) Cristina Cifuentes
*/ */
#include "locident.h"
#include "dcc.h"
#include "msvc_fixes.h"
#include <cstring> #include <cstring>
#include "locident.h"
#include "dcc.h"
bool LONGID_TYPE::srcDstRegMatch(iICODE a, iICODE b) const bool LONGID_TYPE::srcDstRegMatch(iICODE a, iICODE b) const
{ {
return (a->ll()->src().getReg2()==m_l) and (b->ll()->m_dst.getReg2()==m_h); return (a->ll()->src().getReg2()==m_l) and (b->ll()->m_dst.getReg2()==m_h);
@@ -23,7 +26,7 @@ ID::ID(hlType t, frameType f) : type(t),illegal(false),hasMacro(false)
macro[0]=0; macro[0]=0;
memset(&id,0,sizeof(id)); memset(&id,0,sizeof(id));
loc=f; loc=f;
assert(not ((t==TYPE_LONG_SIGN)||(t==TYPE_LONG_UNSIGN))); 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) ID::ID(hlType t,const LONGID_TYPE &s) : type(t),illegal(false),hasMacro(false)
{ {
@@ -31,7 +34,7 @@ ID::ID(hlType t,const LONGID_TYPE &s) : type(t),illegal(false),hasMacro(false)
memset(&id,0,sizeof(id)); memset(&id,0,sizeof(id));
loc=REG_FRAME; loc=REG_FRAME;
m_longId = s; m_longId = s;
assert((t==TYPE_LONG_SIGN)||(t==TYPE_LONG_UNSIGN)); 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) ID::ID(hlType t,const LONG_STKID_TYPE &s) : type(t),illegal(false),hasMacro(false)
{ {
@@ -39,7 +42,7 @@ ID::ID(hlType t,const LONG_STKID_TYPE &s) : type(t),illegal(false),hasMacro(fals
memset(&id,0,sizeof(id)); memset(&id,0,sizeof(id));
loc=STK_FRAME; loc=STK_FRAME;
id.longStkId = s; id.longStkId = s;
assert((t==TYPE_LONG_SIGN)||(t==TYPE_LONG_UNSIGN)); assert((t==TYPE_LONG_SIGN) or (t==TYPE_LONG_UNSIGN));
} }
ID::ID(hlType t, const LONGGLB_TYPE &s) : type(t),illegal(false) ID::ID(hlType t, const LONGGLB_TYPE &s) : type(t),illegal(false)
@@ -48,7 +51,7 @@ ID::ID(hlType t, const LONGGLB_TYPE &s) : type(t),illegal(false)
memset(&id,0,sizeof(id)); memset(&id,0,sizeof(id));
loc=GLB_FRAME; loc=GLB_FRAME;
id.longGlb = s; id.longGlb = s;
assert((t==TYPE_LONG_SIGN)||(t==TYPE_LONG_UNSIGN)); assert((t==TYPE_LONG_SIGN) or (t==TYPE_LONG_UNSIGN));
} }
@@ -75,7 +78,7 @@ int LOCAL_ID::newByteWordReg(hlType t, eReg regi)
/* Check for entry in the table */ /* Check for entry in the table */
auto found=std::find_if(id_arr.begin(),id_arr.end(),[t,regi](ID &el)->bool { 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()) if(found!=id_arr.end())
return found-id_arr.begin(); return found-id_arr.begin();
@@ -96,9 +99,9 @@ int LOCAL_ID::newByteWordReg(hlType t, eReg regi)
void LOCAL_ID::flagByteWordId (int off) void LOCAL_ID::flagByteWordId (int off)
{ {
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off](ID &en)->bool { 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.type == TYPE_WORD_SIGN) or (en.type == TYPE_BYTE_SIGN)) and
if ((en.typeBitsize()<=16) && if ((en.typeBitsize()<=16) and
(en.id.bwId.off == off) && (en.id.bwId.regOff == 0)) (en.id.bwId.off == off) and (en.id.bwId.regOff == 0))
return true; return true;
return false; return false;
}); });
@@ -118,7 +121,7 @@ int LOCAL_ID::newByteWordStk(hlType t, int off, uint8_t regOff)
/* Check for entry in the table */ /* Check for entry in the table */
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off,regOff](ID &el)->bool { 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)) if ((el.id.bwId.off == off) and (el.id.bwId.regOff == regOff))
return true; return true;
return false; return false;
}); });
@@ -148,9 +151,9 @@ int LOCAL_ID::newIntIdx(int16_t seg, int16_t off, eReg regi, hlType t)
/* Check for entry in the table */ /* Check for entry in the table */
for (size_t 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 */ if (/*(locSym->id[idx].type == t) and Not checking type */
(id_arr[idx].id.bwGlb.seg == seg) && (id_arr[idx].id.bwGlb.seg == seg) and
(id_arr[idx].id.bwGlb.off == off) && (id_arr[idx].id.bwGlb.off == off) and
(id_arr[idx].id.bwGlb.regi == regi)) (id_arr[idx].id.bwGlb.regi == regi))
return (idx); return (idx);
} }
@@ -178,10 +181,10 @@ int LOCAL_ID::newLongReg(hlType t, const LONGID_TYPE &longT, iICODE ix_)
for (idx = 0; idx < id_arr.size(); idx++) for (idx = 0; idx < id_arr.size(); idx++)
{ {
ID &entry(id_arr[idx]); ID &entry(id_arr[idx]);
if(!entry.isLong() || (entry.loc != REG_FRAME)) if(not entry.isLong() or (entry.loc != REG_FRAME))
continue; continue;
if (/*(locSym->id[idx].type == t) && Not checking type */ if (/*(locSym->id[idx].type == t) and Not checking type */
(entry.longId().h() == regH) && (entry.longId().h() == regH) and
(entry.longId().l() == regL)) (entry.longId().l() == regL))
{ {
/* Check for occurrence in the list */ /* Check for occurrence in the list */
@@ -201,7 +204,7 @@ int LOCAL_ID::newLongReg(hlType t, const LONGID_TYPE &longT, iICODE ix_)
id_arr.back().idx.push_back(ix_); id_arr.back().idx.push_back(ix_);
return (id_arr.size() - 1); return (id_arr.size() - 1);
} }
/* Returns an identifier conditional expression node of type TYPE_LONG or /** Returns an identifier conditional expression node of type TYPE_LONG or
* TYPE_WORD_SIGN */ * TYPE_WORD_SIGN */
AstIdent * LOCAL_ID::createId(const ID *retVal, iICODE ix_) AstIdent * LOCAL_ID::createId(const ID *retVal, iICODE ix_)
{ {
@@ -218,9 +221,9 @@ int LOCAL_ID::newLongGlb(int16_t seg, int16_t offH, int16_t offL,hlType t)
/* Check for entry in the table */ /* Check for entry in the table */
for (idx = 0; idx < id_arr.size(); idx++) for (idx = 0; idx < id_arr.size(); idx++)
{ {
if (/*(locSym->id[idx].type == t) && Not checking type */ if (/*(locSym->id[idx].type == t) and Not checking type */
(id_arr[idx].id.longGlb.seg == seg) && (id_arr[idx].id.longGlb.seg == seg) and
(id_arr[idx].id.longGlb.offH == offH) && (id_arr[idx].id.longGlb.offH == offH) and
(id_arr[idx].id.longGlb.offL == offL)) (id_arr[idx].id.longGlb.offL == offL))
return (idx); return (idx);
} }
@@ -242,21 +245,17 @@ int LOCAL_ID::newLongIdx( int16_t seg, int16_t offH, int16_t offL,uint8_t regi,
/* Check for entry in the table */ /* Check for entry in the table */
for (idx = 0; idx < id_arr.size(); idx++) for (idx = 0; idx < id_arr.size(); idx++)
{ {
if (/*(locSym->id[idx].type == t) && Not checking type */ if (/*(locSym->id[idx].type == t) and Not checking type */
(id_arr[idx].id.longGlb.seg == seg) && (id_arr[idx].id.longGlb.seg == seg) and
(id_arr[idx].id.longGlb.offH == offH) && (id_arr[idx].id.longGlb.offH == offH) and
(id_arr[idx].id.longGlb.offL == offL) && (id_arr[idx].id.longGlb.offL == offL) and
(id_arr[idx].id.longGlb.regi == regi)) (id_arr[idx].id.longGlb.regi == regi))
return (idx); return (idx);
} }
/* Not in the table, create new identifier */ /* Not in the table, create new identifier */
newIdent (t, GLB_FRAME); id_arr.push_back(ID(t,LONGGLB_TYPE(seg,offH,offL,regi)));
idx = id_arr.size() - 1; 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); return (idx);
} }
@@ -272,8 +271,8 @@ int LOCAL_ID::newLongStk(hlType t, int offH, int offL)
{ {
if(id_arr[idx].loc!=STK_FRAME) if(id_arr[idx].loc!=STK_FRAME)
continue; continue;
if ((id_arr[idx].type == t) && if ((id_arr[idx].type == t) and
(id_arr[idx].longStkId().offH == offH) && (id_arr[idx].longStkId().offH == offH) and
(id_arr[idx].longStkId().offL == offL)) (id_arr[idx].longStkId().offL == offL))
return (idx); return (idx);
} }
@@ -320,9 +319,9 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
} }
else if (pmL->off) { /* offset */ 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); 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 */ { /* glb var indexed on bx */
printf("Bx indexed global, BX is an unused parameter to newLongIdx\n"); printf("Bx indexed global, BX is an unused parameter to newLongIdx\n");
idx = newLongIdx(pmH->segValue, pmH->off, pmL->off,rBX,TYPE_LONG_SIGN); idx = newLongIdx(pmH->segValue, pmH->off, pmL->off,rBX,TYPE_LONG_SIGN);
@@ -332,8 +331,8 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
printf ("long not supported, idx <> bp\n"); printf ("long not supported, idx <> bp\n");
} }
else /* (pm->regi >= INDEXBASE && pm->off = 0) => indexed && no off */ else /* (pm->regi >= INDEXBASE and pm->off = 0) => indexed and no off */
printf ("long not supported, idx && no off\n"); printf ("long not supported, idx and no off\n");
return (idx); return (idx);
} }
@@ -357,7 +356,7 @@ bool checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc
pmLdst = &atOffset.m_dst; pmLdst = &atOffset.m_dst;
pmHsrc = &pIcode->ll()->src(); pmHsrc = &pIcode->ll()->src();
pmLsrc = &atOffset.src(); pmLsrc = &atOffset.src();
// if ((longId.offH == pmHsrc->off) && (longId.offL == pmLsrc->off)) // if ((longId.offH == pmHsrc->off) and (longId.offL == pmLsrc->off))
// { // {
// asgn.lhs = AstIdent::LongIdx (i); // asgn.lhs = AstIdent::LongIdx (i);
@@ -367,14 +366,14 @@ bool checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc
// } // }
// return true; // return true;
// } // }
// else if ((longId.offH == pmHdst->off) && (longId.offL == pmLdst->off)) // 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.lhs = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset);
// asgn.rhs = AstIdent::LongIdx (i); // asgn.rhs = AstIdent::LongIdx (i);
// return true; // return true;
// } // }
if ((longId.offH == pmHdst->off) && (longId.offL == pmLdst->off)) if ((longId.offH == pmHdst->off) and (longId.offL == pmLdst->off))
{ {
asgn.lhs = AstIdent::LongIdx (i); asgn.lhs = AstIdent::LongIdx (i);
@@ -384,7 +383,7 @@ bool checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc
} }
return true; 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 = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset); asgn.lhs = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset);
asgn.rhs = AstIdent::LongIdx (i); asgn.rhs = AstIdent::LongIdx (i);
@@ -414,7 +413,7 @@ bool checkLongRegEq (LONGID_TYPE longId, iICODE pIcode, int i,
pmHsrc = &pIcode->ll()->src(); pmHsrc = &pIcode->ll()->src();
pmLsrc = &atOffset.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 = AstIdent::LongIdx (i); asgn.lhs = AstIdent::LongIdx (i);
if ( not pIcode->ll()->testFlags(NO_SRC) ) if ( not pIcode->ll()->testFlags(NO_SRC) )
@@ -423,7 +422,7 @@ bool checkLongRegEq (LONGID_TYPE longId, iICODE pIcode, int i,
} }
return true; 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 = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode, eDEF, atOffset); asgn.lhs = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode, eDEF, atOffset);
asgn.rhs = AstIdent::LongIdx (i); asgn.rhs = AstIdent::LongIdx (i);
@@ -442,7 +441,7 @@ eReg otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
ID *id; ID *id;
id = &locTbl->id_arr[idx]; id = &locTbl->id_arr[idx];
if ((id->loc == REG_FRAME) && ((id->type == TYPE_LONG_SIGN) || if ((id->loc == REG_FRAME) and ((id->type == TYPE_LONG_SIGN) or
(id->type == TYPE_LONG_UNSIGN))) (id->type == TYPE_LONG_UNSIGN)))
{ {
if (id->longId().h() == regi) if (id->longId().h() == regi)
@@ -454,11 +453,12 @@ eReg otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
} }
/* Checks if the registers regL and regH have been used independently in /**
* Checks if the registers regL and regH have been used independently in
* the local identifier table. If so, macros for these registers are * the local identifier table. If so, macros for these registers are
* placed in the local identifier table, as these registers belong to a * placed in the local identifier table, as these registers belong to a
* long register identifier. */ * 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) for (ID &rid : id_arr)
{ {

View File

@@ -1,8 +1,13 @@
#include <cassert>
#include "machine_x86.h" #include "machine_x86.h"
#include "msvc_fixes.h"
#include "icode.h" #include "icode.h"
#include <QtCore/QTextStream>
#include <cassert>
// Index registers **** temp solution // Index registers **** temp solution
static const std::string regNames[] = { static const QString regNames[] = {
"undef", "undef",
"ax", "cx", "dx", "bx", "ax", "cx", "dx", "bx",
"sp", "bp", "si", "di", "sp", "bp", "si", "di",
@@ -17,17 +22,17 @@ static const std::string regNames[] = {
/* uint8_t and uint16_t registers */ /* uint8_t and uint16_t registers */
Machine_X86::Machine_X86() Machine_X86::Machine_X86()
{ {
static_assert((sizeof(regNames)/sizeof(std::string))==LAST_REG, static_assert((sizeof(regNames)/sizeof(QString))==LAST_REG,
"Reg count not equal number of strings"); "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]; return regNames[r];
} }
static const std::string szOps[] = static const QString szOps[] =
{ {
"CBW", "AAA", "AAD", "AAM", "AAS", "ADC", "ADD", "AND", "CBW", "AAA", "AAD", "AAM", "AAS", "ADC", "ADD", "AND",
"BOUND","CALL", "CALL", "CLC", "CLD", "CLI", "CMC", "CMP", "BOUND","CALL", "CALL", "CLC", "CLD", "CLI", "CMC", "CMP",
@@ -45,7 +50,7 @@ static const std::string szOps[] =
"XLAT", "XOR", "INTO", "NOP", "REPNE", "REPE", "MOD" "XLAT", "XOR", "INTO", "NOP", "REPNE", "REPE", "MOD"
}; };
/* The following opcodes are for mod != 3 */ /* The following opcodes are for mod != 3 */
static std::string szFlops1[] = static const QString szFlops1[] =
{ {
/* 0 1 2 3 4 5 6 7 */ /* 0 1 2 3 4 5 6 7 */
"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */ "FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */
@@ -58,7 +63,7 @@ static std::string szFlops1[] =
"FILD", "???", "FIST", "FISTP", "FBLD", "???", "FBSTP", "FISTP" /* 38 */ "FILD", "???", "FIST", "FISTP", "FBLD", "???", "FBSTP", "FISTP" /* 38 */
}; };
/* The following opcodes are for mod == 3 */ /* The following opcodes are for mod == 3 */
static std::string szFlops2[] = static const QString szFlops2[] =
{ {
/* 0 1 2 3 4 5 6 7 */ /* 0 1 2 3 4 5 6 7 */
"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */ "FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */
@@ -71,17 +76,17 @@ static std::string szFlops2[] =
"FILD", "???", "FIST", "FISTP", "", "???", "FBSTP", "FISTP" /* 38 */ "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]; 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)); r-= (sizeof(szFlops1)/sizeof(QString));
assert(r<(sizeof(szFlops2)/sizeof(std::string))); assert(r<(sizeof(szFlops2)/sizeof(QString)));
return szFlops2[r]; return szFlops2[r];
} }
return szFlops1[r]; return szFlops1[r];
@@ -89,11 +94,11 @@ const std::string &Machine_X86::floatOpName(unsigned r)
bool Machine_X86::physicalReg(eReg r) bool Machine_X86::physicalReg(eReg r)
{ {
return (r>=rAX) && (r<rTMP); return (r>=rAX) and (r<rTMP);
} }
bool Machine_X86::isMemOff(eReg r) 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 //TODO: Move these to Machine_X86
eReg Machine_X86::subRegH(eReg reg) eReg Machine_X86::subRegH(eReg reg)
@@ -106,18 +111,18 @@ eReg Machine_X86::subRegL(eReg reg)
} }
bool Machine_X86::isSubRegisterOf(eReg reg,eReg parent) 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 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) bool Machine_X86::hasSubregisters(eReg reg)
{ {
return ((reg >= rAX) && (reg <= rBX)); return ((reg >= rAX) and (reg <= rBX));
} }
bool Machine_X86::isPartOfComposite(eReg reg) bool Machine_X86::isPartOfComposite(eReg reg)
{ {
return ((reg >= rAL) && (reg <= rBH)); return ((reg >= rAL) and (reg <= rBH));
} }
eReg Machine_X86::compositeParent(eReg reg) eReg Machine_X86::compositeParent(eReg reg)
@@ -133,7 +138,7 @@ eReg Machine_X86::compositeParent(eReg reg)
} }
return rUNDEF; return rUNDEF;
} }
void Machine_X86::writeRegVector (std::ostream &ostr,const LivenessSet &regi) void Machine_X86::writeRegVector (QTextStream &ostr,const LivenessSet &regi)
{ {
int j; int j;
for (j = rAX; j < INDEX_BX_SI; j++) for (j = rAX; j < INDEX_BX_SI; j++)

File diff suppressed because it is too large Load Diff

7
src/parser.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef PARSER_H
#define PARSER_H
class Function;
struct CALL_GRAPH;
struct STATE;
void FollowCtrl(Function & func, CALL_GRAPH * pcallGraph, STATE *pstate);
#endif // PARSER_H

View File

@@ -1,101 +0,0 @@
/*
* Perfect hashing function library. Contains functions to generate perfect
* hashing functions
* (C) Mike van Emmerik
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "perfhlib.h"
/* Private data structures */
static uint16_t *T1, *T2; /* Pointers to T1[i], T2[i] */
static short *g; /* g[] */
//static int numEdges; /* An edge counter */
//static bool *visited; /* Array of bools: whether visited */
/* Private prototypes */
//static void initGraph(void);
//static void addToGraph(int e, int v1, int v2);
//static bool isCycle(void);
//static void duplicateKeys(int v1, int v2);
PatternHasher g_pattern_hasher;
void PatternHasher::init(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 */
T1base = new uint16_t [EntryLen * SetSize];
T2base = new uint16_t [EntryLen * SetSize];
graphNode = new int [NumEntry*2 + 1];
graphNext = new int [NumEntry*2 + 1];
graphFirst = new int [NumVert + 1];
g = new short [NumVert + 1];
// visited = new bool [NumVert + 1];
return;
}
void PatternHasher::cleanup(void)
{
/* Free the storage for variable sized tables etc */
delete [] T1base;
delete [] T2base;
delete [] graphNode;
delete [] graphNext;
delete [] graphFirst;
delete [] g;
// delete [] visited;
}
int PatternHasher::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;
}
uint16_t * PatternHasher::readT1(void)
{
return T1base;
}
uint16_t *PatternHasher::readT2(void)
{
return T2base;
}
uint16_t * PatternHasher::readG(void)
{
return (uint16_t *)g;
}

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