Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
777c64a
NOT TESTED FIX: IDA GUI FIX
Maroc-OS Jan 15, 2016
d5682b6
dis: arch_name was wrong in raise
Maroc-OS Jan 15, 2016
cc4e415
Merge pull request #1 from Maroc-OS/patch-1
Maroc-OS Jan 15, 2016
b9af816
Update README.md
Maroc-OS Jan 24, 2016
8c967ea
Update README.md
Maroc-OS Jan 24, 2016
f8781e2
Update README.md
Maroc-OS Jan 24, 2016
ce24a64
add Codacy Badge badge
Maroc-OS Jan 24, 2016
5f1a311
change tarvis link
Maroc-OS Jan 24, 2016
dee7233
Update CodeClimate
Maroc-OS Jan 25, 2016
4fe9770
Fix duplicates, update .gitugnore, and minor changes
Maroc-OS Jan 26, 2016
bf30524
Fix duplicates, update .gitugnore, and minor changes
Maroc-OS Jan 26, 2016
dc68a61
add codeclimate coverage api
Maroc-OS Jan 26, 2016
a81d16a
SMALL FIX: in c.py there was a self definition in init with same name…
Maroc-OS Jan 27, 2016
5fb9e7b
FIX: ir/generic we are raising a non callable NotImplemented instead …
Maroc-OS Jan 28, 2016
caad21f
Fix previews commit, & minor changes
Maroc-OS Jan 28, 2016
200e8d2
FIX: Unreachable return after raise.
Maroc-OS Jan 28, 2016
e83c2d3
remove unnecessary parens
Maroc-OS Jan 28, 2016
c95475a
clean-up's
Maroc-OS Jan 28, 2016
80f52ad
another NotImplementedError
Maroc-OS Jan 28, 2016
38a2db4
clean test graph
Maroc-OS Jan 28, 2016
fef9b2c
code climate changes
Maroc-OS Jan 28, 2016
02d45c2
code climate changes
Maroc-OS Jan 28, 2016
d3ee3a6
code climate changes
Maroc-OS Jan 28, 2016
f77e2cd
coverage changes
Maroc-OS Jan 28, 2016
c65be46
clean up travis
Maroc-OS Jan 28, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
engines:
duplication:
enabled: true
config:
languages:
- python
fixme:
enabled: true
radon:
enabled: true
config:
python_version: 2
pep8:
enabled: true
ratings:
paths:
- "**.py"
exclude_paths:
- tests/**/*
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
*~
*.pyc
parser.out
parsetab.py
*.i64
*.idb
.DS_Store
.coverage
coverage.xml
24 changes: 21 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
sudo: false

language: python

python:
- "2.7"
install: "pip install -r requirements.txt"
script: python tests/run.py
- 2.7

install:
- pip install -r requirements.txt

addons:
code_climate:
repo_token:
secure: ehr0JgLCt81b9ST4sj2eeStCHpUu119ZUi6jVELxgRwwMok8KHxSDjAE3JMX50AFYOU7zzfZECH8ZKICeDZE1vKjLI0CN7f6wv/4MNVoO50cpAlC4sjVNpxkWjf5DJwqQgkQ+R/Pe3pSoDRt4CY2DKFj0Mow4HwzjPIQGqiYNirr0UQh+aK4RSidYwHynssClMOjIgYIHwLikmMSEf/f8odJmlBQrebR2qDG0mTAGRVOgUziSizaoNSYrnLSFL1v5QJSihfa6AOPv6Zh+oRcq0r8MpEw6XVgSRB21zqRhVlXnGVSOn5Nzynbi4MalBjhT/TzJ0cDiTGLMuNvEtaGEjTbGWksXciI/Fd4LWKni5W/GNyOFaq5/d+3JYGSM7ncQKLZf9BOeAKiUuyl5A+/69AmDylSYMa+DPaNyllV2GOoiUoin8weyG4eHUthAgF4/bSzXjv8VCViRWaAqROXqhf6raJkEjt3G2eHPlv8KjPFrcQk8Oa9yu/GZJHh01w1ZBT9RgDutD2PunR7W4TlD7LZ8msEY6smtQfgagrV9rC35Mn9jwmyIFVA68dxJIPdkPIIDKmYlAJgj6hlLg2Kb5pOrd/S2f8jiqeUSahwBpetxy0OhqNgqO7pS8GXhxcxtmYOzZ6rWF0W+9M7QwV7RnZPEmVX1WbnOn2Wcx2R3kk=

before_install:
- pip install codecov

script:
- coverage run tests/run.py

after_success:
- codecov
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
decompiler ![Build Status](https://api.travis-ci.org/EiNSTeiN-/decompiler.svg)
[![Build Status](https://travis-ci.org/Maroc-OS/decompiler.svg)](https://travis-ci.org/Maroc-OS/decompiler)
[![Codacy Badge](https://api.codacy.com/project/badge/grade/6066dcab6432437f9a360b0663deeae8)](https://www.codacy.com/app/merruk-company/decompiler)
[![Code Climate](https://codeclimate.com/github/Maroc-OS/decompiler/badges/gpa.svg)](https://codeclimate.com/github/Maroc-OS/decompiler)
[![codecov.io](https://codecov.io/github/Maroc-OS/decompiler/coverage.svg?branch=master)](https://codecov.io/github/Maroc-OS/decompiler?branch=master)
[![Issue Count](https://codeclimate.com/github/Maroc-OS/decompiler/badges/issue_count.svg)](https://codeclimate.com/github/Maroc-OS/decompiler)
==============

A multi-backends decompiler written in python. It currently supports IDA and Capstone.
Expand Down
2 changes: 1 addition & 1 deletion src/decompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ class decompiler_t(object):
step_locals_renamed,
step_ssa_removed,
step_combined,
step_decompiled,
step_decompiled
]

def __init__(self, disasm, ea):
Expand Down
1 change: 0 additions & 1 deletion src/host/capstone/dis/intel.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ def get_operand_expression(self, ea, n):
expr = value_t(op.imm, op.size*8)
else:
raise RuntimeError('%x: unhandled operand type: %s' % (ea, repr(op.type)))
return

return expr

Expand Down
1 change: 0 additions & 1 deletion src/host/dis.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
except ImportError as e:
print repr(e)
traceback.print_exc()
pass
except BaseException as e:
print repr(e)
traceback.print_exc()
Expand Down
2 changes: 1 addition & 1 deletion src/host/ida/dis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def disassembler_for_arch(arch_name=None):
print 'Architecture: 64-bit intel.'
return (ir.IR_INTEL_x64, ir.intel.ir_intel_x64, intel.disassembler)

raise RuntimeError("Don't know which arch to choose for %s" % (repr(filetype), ))
raise RuntimeError("Don't know which arch to choose for %s" % (repr(arch_name), ))

def create(arch_name=None):
""" Find the correct disassembler module for this host.
Expand Down
1 change: 0 additions & 1 deletion src/host/ida/dis/intel.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ def get_operand_expression(self, ea, n):
expr = value_t(addr, self.get_operand_size(op))
else:
raise RuntimeError('%x: unhandled operand type: %s %s' % (ea, repr(op.type), repr(idc.GetOpnd(ea, 1))))
return

return expr

Expand Down
13 changes: 9 additions & 4 deletions src/host/ida/ui/decompiler_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
'Locations renamed',
'Expressions propagated',
'Dead code pruned',
'Decompiled',
'Decompiled'
]

class DecompilerForm(idaapi.PluginForm):
Expand Down Expand Up @@ -69,7 +69,9 @@ def populate_form(self):
for phase in decompilation_phase:
self.phase_selection.addItem(phase)

self.phase_selection.setCurrentIndex(decompiler.STEP_DECOMPILED)
# case sensitive for step_decompiled and setCurrentIndex argument should be integer,
# so why not just (0)???
self.phase_selection.setCurrentIndex(0)
self.phase_selection.currentIndexChanged.connect(self.phase_selected)

self.parent.setLayout(layout)
Expand All @@ -80,13 +82,16 @@ def phase_selected(self, index):
self.decompile(index)
return

def decompile(self, wanted_step=decompiler.STEP_DECOMPILED):
def decompile(self, wanted_step=None):

if not wanted_step:
wanted_step = decompiler.step_decompiled

dis = host.dis.available_disassemblers['ida'].create()
d = decompiler.decompiler_t(dis, self.ea)

for step in d.steps():
print 'Decompiler step: %u - %s' % (step, decompilation_phase[step])
#~ print 'Decompiler step: %u - %s' % (step, decompilation_phase[step]) # this print is not treated correctelly.
if step >= wanted_step:
break

Expand Down
8 changes: 4 additions & 4 deletions src/host/ida/ui/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ def main():
try:
hotkey_ctx
if idaapi.del_hotkey(hotkey_ctx):
print("Hotkey unregistered!")
print "Hotkey unregistered!"
del hotkey_ctx
else:
print("Failed to delete hotkey!")
print "Failed to delete hotkey!"
except:
pass
hotkey_ctx = idaapi.add_hotkey("F5", show_decompiler)
if hotkey_ctx is None:
print("Failed to register hotkey!")
print "Failed to register hotkey!"
del hotkey_ctx
else:
print("Press F5 to decompile a function.")
print "Press F5 to decompile a function."
10 changes: 5 additions & 5 deletions src/ir/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ class ir_base(object):

def is_return(self, ea):
""" return True if this is a return instruction. """
raise NotImplemented('base class must override this method')
raise NotImplementedError('base class must override this method')

def has_jump(self, ea):
""" return true if this instruction is a jump """
raise NotImplemented('base class must override this method')
raise NotImplementedError('base class must override this method')

def next_instruction_ea(self, ea):
""" return the address of the next instruction. """
raise NotImplemented('base class must override this method')
raise NotImplementedError('base class must override this method')

def jump_branches(self, ea):
""" if this instruction is a jump, yield the destination(s)
Expand All @@ -30,12 +30,12 @@ def jump_branches(self, ea):
note that the destination expression is usually a value_t
representing an address within the function, however it may
be any other operand type such as a register. """
raise NotImplemented('base class must override this method')
raise NotImplementedError('base class must override this method')

def generate_statements(self, ea):
""" this is where the magic happens, this method yeilds one or more new
statement corresponding to the given location. """
raise NotImplemented('base class must override this method')
raise NotImplementedError('base class must override this method')


## following functions are typically implemented at the host level. they are used mostly to
Expand Down
72 changes: 24 additions & 48 deletions src/output/c.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def __init__(self, function, indent=' '):
self.function = function
self.arch = function.arch
self.indent = indent
self.display_labels = self.display_labels()
self.show_labels = self.display_labels()
self.done_labels = None
return

Expand Down Expand Up @@ -315,53 +315,25 @@ def expression_tokens(self, obj):
yield tok
return

if type(obj) == sign_t:
yield token_keyword('SIGN')
l, r = self.matching('(', ')')
yield l
for tok in self.expression_tokens(obj.op):
yield tok
yield r
return

if type(obj) == overflow_t:
yield token_keyword('OVERFLOW')
l, r = self.matching('(', ')')
yield l
for tok in self.expression_tokens(obj.op):
yield tok
yield r
return

if type(obj) == parity_t:
yield token_keyword('PARITY')
l, r = self.matching('(', ')')
yield l
for tok in self.expression_tokens(obj.op):
yield tok
yield r
return

if type(obj) == adjust_t:
yield token_keyword('ADJUST')
l, r = self.matching('(', ')')
yield l
for tok in self.expression_tokens(obj.op):
yield tok
yield r
if obj is None:
yield token_keyword('None')
return

if type(obj) == carry_t:
yield token_keyword('CARRY')
l, r = self.matching('(', ')')
yield l
for tok in self.expression_tokens(obj.op):
yield tok
yield r
if type(obj) == sign_t:
obj_type = 'SIGN'
elif type(obj) == overflow_t:
obj_type = 'OVERFLOW'
elif type(obj) == parity_t:
obj_type = 'PARITY'
elif type(obj) == adjust_t:
obj_type = 'ADJUST'
elif type(obj) == carry_t:
obj_type = 'CARRY'
elif type(obj) == phi_t:
obj_type = 'Φ'
return

if type(obj) == phi_t:
yield token_keyword('Φ')
if type(obj) == phi_t or obj_type == 'Φ':
l, r = self.matching('(', ')')
yield l
for op in obj.operands:
Expand All @@ -371,17 +343,21 @@ def expression_tokens(self, obj):
yield token_character(' ')
yield r
return

if obj is None:
yield token_keyword('None')
else:
yield token_keyword(obj_type)
l, r = self.matching('(', ')')
yield l
for tok in self.expression_tokens(obj.op):
yield tok
yield r
return

raise ValueError('cannot display object of type %s' % (obj.__class__.__name__, ))

def statement_tokens(self, obj, indent=0):

if isinstance(obj, statement_t) and obj.ea is not None:
if obj.ea in self.display_labels and obj.ea not in self.done_labels:
if obj.ea in self.show_labels and obj.ea not in self.done_labels:
yield token_global('loc_%x' % (obj.ea, ))
yield token_character(':')
yield token_character('\n')
Expand Down
1 change: 0 additions & 1 deletion src/propagator.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ def __init__(self, function):
def is_assignment(self, stmt):
return isinstance(stmt.expr, assign_t) and \
isinstance(stmt.expr.op1, assignable_t)
return False

def replace(self, defn, value, use):
new = value.copy(with_definition=True)
Expand Down
2 changes: 1 addition & 1 deletion src/ssa.py
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ def rename_groups(self, phi, groups):
else:
print 'more than one group'
print ' ', repr(groups)
raise 'not implemented'
raise NotImplementedError('not implemented.')

return

Expand Down
3 changes: 1 addition & 2 deletions tests/unit/test_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
try:
import capstone
except ImportError as e:
print 'warning: Capstone tests are unavailable'
pass
print 'Capstone tests are unavailable\n\warning: %s' % e

class callconv(object):
def __init__(self, callconv):
Expand Down