mirror of
https://github.com/idapython/src
synced 2026-06-08 14:47:00 +00:00
132 lines
3.2 KiB
Python
132 lines
3.2 KiB
Python
"""
|
|
summary: superficially modify the decompilation output
|
|
|
|
description:
|
|
modifies the decompilation output in a superficial manner,
|
|
by removing some white spaces
|
|
|
|
Note: this is rather crude, not quite "pythonic" code.
|
|
|
|
level: intermediate
|
|
"""
|
|
|
|
import idautils
|
|
import idc
|
|
import ida_idaapi
|
|
import ida_hexrays
|
|
import ida_lines
|
|
|
|
do_dbg = False
|
|
|
|
def dbg(msg):
|
|
if do_dbg:
|
|
print(msg)
|
|
pass
|
|
|
|
def is_cident_char(c):
|
|
return c.isalnum() or c == '_'
|
|
|
|
def my_tag_skipcodes(l, storage):
|
|
n = ida_lines.tag_skipcodes(l)
|
|
if n > 0:
|
|
dbg("Skipping %d chars ('%s')" % (n, l[0:n]))
|
|
storage.append(l[0:n])
|
|
return l[n:]
|
|
|
|
def remove_spaces(sl):
|
|
|
|
dbg("*" * 80)
|
|
l = sl.line
|
|
|
|
global do_dbg
|
|
# do_dbg = l.find("const char *") > -1
|
|
|
|
out = []
|
|
|
|
def push(c):
|
|
dbg("Appending '%s'" % c)
|
|
out.append(c)
|
|
|
|
# skip initial spaces, do not compress them
|
|
def eat_spaces(l):
|
|
while True:
|
|
l = my_tag_skipcodes(l, out)
|
|
if not l:
|
|
break
|
|
c = l[0]
|
|
if not c.isspace():
|
|
break
|
|
push(c)
|
|
l = l[1:]
|
|
return l
|
|
l = eat_spaces(l)
|
|
|
|
# remove all spaces except in string and char constants
|
|
delim = None # if not None, then we are skipping until 'delim'
|
|
last = None # last seen character
|
|
|
|
while True:
|
|
dbg("-" * 60)
|
|
dbg("l: '%s'" % l)
|
|
dbg("d: '%s'" % delim)
|
|
dbg("out: '%s'" % out)
|
|
|
|
# go until comments
|
|
l = my_tag_skipcodes(l, out)
|
|
if l.startswith("//"):
|
|
push(l)
|
|
break
|
|
nchars = ida_lines.tag_advance(l, 1)
|
|
push(l[0:nchars])
|
|
l = l[nchars:]
|
|
l = my_tag_skipcodes(l, out)
|
|
if not l:
|
|
break
|
|
c = l[0]
|
|
dbg("c: '%s', last: '%s', l: '%s'" % (c, last, l))
|
|
if delim:
|
|
# we're inside a literal.
|
|
if c == delim:
|
|
delim = None # literal ended
|
|
elif c == '"' or c == "'":
|
|
delim = c # string/char literal started
|
|
elif c.isspace():
|
|
end = l.lstrip()
|
|
nptr = my_tag_skipcodes(end, out)
|
|
dbg("end: '%s', nptr: '%s'" % (end, nptr))
|
|
# do not concatenate idents
|
|
if not is_cident_char(last) or not is_cident_char(nptr[0]):
|
|
l = end
|
|
c = l[0] if l else ''
|
|
dbg("new l: '%s'" % l)
|
|
last = l[0] if l else ''
|
|
|
|
sl.line = "".join(out)
|
|
|
|
|
|
class vds6_hooks_t(ida_hexrays.Hexrays_Hooks):
|
|
def func_printed(self, cfunc):
|
|
for sl in cfunc.get_pseudocode():
|
|
remove_spaces(sl);
|
|
return 0
|
|
|
|
# a plugin interface, boilerplate code
|
|
class my_plugin_t(ida_idaapi.plugin_t):
|
|
flags = ida_idaapi.PLUGIN_HIDE
|
|
wanted_name = "Hex-Rays space remover (IDAPython)"
|
|
wanted_hotkey = ""
|
|
comment = "Sample plugin6 for Hex-Rays decompiler"
|
|
help = ""
|
|
def init(self):
|
|
if ida_hexrays.init_hexrays_plugin():
|
|
self.vds6_hooks = vds6_hooks_t()
|
|
self.vds6_hooks.hook()
|
|
return ida_idaapi.PLUGIN_KEEP # keep us in the memory
|
|
def term(self):
|
|
self.vds6_hooks.unhook()
|
|
def run(self, arg):
|
|
pass
|
|
|
|
def PLUGIN_ENTRY():
|
|
return my_plugin_t()
|