IDAPython for IDA 8.4

This commit is contained in:
Arnaud Diederen
2024-02-21 14:22:30 +01:00
parent 6142005952
commit ae62cd4df5
75 changed files with 167600 additions and 505202 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ A script that tries to determine the call stack
Run the application with the debugger, suspend the debugger, select a thread and finally run the script.
Copyright (c) 1990-2023 Hex-Rays
Copyright (c) 1990-2024 Hex-Rays
ALL RIGHTS RESERVED.
"""
import ida_ua
+1 -1
View File
@@ -2,7 +2,7 @@
A script to demonstrate how to send commands to the debugger and then parse and use the output in IDA
Copyright (c) 1990-2023 Hex-Rays
Copyright (c) 1990-2024 Hex-Rays
ALL RIGHTS RESERVED.
"""
+1 -1
View File
@@ -2,7 +2,7 @@
This script shows how to send debugger commands and use the result in IDA
Copyright (c) 1990-2023 Hex-Rays
Copyright (c) 1990-2024 Hex-Rays
ALL RIGHTS RESERVED.
"""
+1 -1
View File
@@ -13,7 +13,7 @@ The general syntax is:
* To specify in which context the instructions should be assembled, pass asm_where=ea:
find("jmp dword ptr [esp]", asm_where=here())
Copyright (c) 1990-2023 Hex-Rays
Copyright (c) 1990-2024 Hex-Rays
ALL RIGHTS RESERVED.
"""
from __future__ import print_function
+1 -1
View File
@@ -4,7 +4,7 @@ A script that graphs all the exception handlers in a given process
It will be easy to see what thread uses what handler and what handlers are commonly used between threads
Copyright (c) 1990-2023 Hex-Rays
Copyright (c) 1990-2024 Hex-Rays
ALL RIGHTS RESERVED.
"""
from __future__ import print_function
+1 -1
View File
@@ -2,7 +2,7 @@
This script shows how to send debugger commands and use the result in IDA
Copyright (c) 1990-2023 Hex-Rays
Copyright (c) 1990-2024 Hex-Rays
ALL RIGHTS RESERVED.
"""
+1 -1
View File
@@ -2,7 +2,7 @@ from __future__ import print_function
# -----------------------------------------------------------------------
# VirusTotal IDA Plugin
# By Elias Bachaalany <elias at hex-rays.com>
# (c) Hex-Rays 2011-2023
# (c) Hex-Rays 2011-2024
#
# Special thanks:
# - VirusTotal team
+14561
View File
File diff suppressed because it is too large Load Diff
+68992
View File
File diff suppressed because it is too large Load Diff
-12514
View File
File diff suppressed because it is too large Load Diff
+14228
View File
File diff suppressed because it is too large Load Diff
+67968
View File
File diff suppressed because it is too large Load Diff
-12356
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -53,7 +53,7 @@ To achieve that, you want to use the `directorargout` typemap:
%typemap(directorargout) qstrvec_t * (qstrvec_t tmp)
{ // %typemap(directorargout) qstrvec_t *
if ( PyW_PyListToStrVec(&tmp, $result) >= 0 )
if ( PyW_PySeqToStrVec(&tmp, $result) >= 0 )
{
$1->swap(tmp);
}
+1 -1
View File
@@ -79,7 +79,7 @@ act_name = "example:add_action"
if ida_kernwin.register_action(ida_kernwin.action_desc_t(
act_name, # Name. Acts as an ID. Must be unique.
"Say hi!", # Label. That's what users see.
"Say ~h~i!", # Label. That's what users see. Can have an accelerator key specified between '~'
SayHi("developer"), # Handler. Called when activated, and for updating
"Ctrl+F12", # Shortcut (optional)
"Greets the user", # Tooltip (optional)
@@ -15,53 +15,113 @@ author: Gergely Erdelyi (gergely.erdelyi@d-dome.net)
# with members of different types.
#---------------------------------------------------------------------
import ida_struct
import ida_idaapi
import ida_bytes
import ida_nalt
import ida_typeinf
import idc
sid = ida_struct.get_struc_id("mystr1")
if sid != -1:
idc.del_struc(sid)
sid = ida_struct.add_struc(ida_idaapi.BADADDR, "mystr1", 0)
print("%x" % sid)
tif = ida_typeinf.tinfo_t()
if tif.get_named_type(None, "mystr1"):
ida_typeinf.del_named_type(None, "mystr1", ida_typeinf.NTF_TYPE)
ida_typeinf.idc_parse_types('struct mystr1 { };', 0)
if not tif.get_named_type(None, "mystr1"):
print("Error retrieving mystr1")
print("%x" % tif.get_ordinal())
# Test simple data types
simple_types_data = [
(ida_bytes.FF_BYTE, 1),
(ida_bytes.FF_WORD, 2),
(ida_bytes.FF_DWORD, 4),
(ida_bytes.FF_QWORD, 8),
(ida_bytes.FF_TBYTE, 10),
(ida_bytes.FF_OWORD, 16),
(ida_bytes.FF_FLOAT, 4),
(ida_bytes.FF_DOUBLE, 8),
(ida_bytes.FF_PACKREAL, 10),
(ida_typeinf.BTF_BYTE, 1),
(ida_typeinf.BTF_INT16, 2),
(ida_typeinf.BTF_UINT32, 4),
(ida_typeinf.BTF_INT64, 8),
(ida_typeinf.BTF_INT128, 16),
(ida_typeinf.BTF_FLOAT, 4),
(ida_typeinf.BTF_DOUBLE, 8),
(ida_typeinf.BTF_TBYTE, 10),
]
udm = ida_typeinf.udm_t()
for i, tpl in enumerate(simple_types_data):
t, nsize = tpl
print("t%x:"% ((t|ida_bytes.FF_DATA) & 0xFFFFFFFF),
idc.add_struc_member(sid, "t%02d"%i, ida_idaapi.BADADDR, (t|ida_bytes.FF_DATA )&0xFFFFFFFF, -1, nsize))
udm.name = "t%02d" % i
udm.size = nsize * 8
udm.type = ida_typeinf.tinfo_t(t)
udm.offset = tif.get_unpadded_size() * 8
print("t%x:"% t,
ida_typeinf.tinfo_errstr(tif.add_udm(udm)) )
repr = ida_typeinf.value_repr_t()
repr.set_vtype(ida_typeinf.FRB_NUMO)
print("Set member representation to octal:",
ida_typeinf.tinfo_errstr(tif.set_udm_repr(3, repr)) )
# Test ASCII type
print("ASCII:", idc.add_struc_member(sid, "tascii", -1, ida_bytes.FF_STRLIT|ida_bytes.FF_DATA, ida_nalt.STRTYPE_C, 8))
udm = ida_typeinf.udm_t()
udm.name = "tascii"
udm.size = 8 * 8
udm.type.parse('char tascii[8] __strlit(C,"windows-1252");') # no other way?
udm.offset = tif.get_size() * 8
print("%s:"% udm.name,
ida_typeinf.tinfo_errstr(tif.add_udm(udm)) )
# Test struc member type
msid = ida_struct.get_struc_id("mystr2")
if msid != -1:
idc.del_struc(msid)
msid = idc.add_struc(-1, "mystr2", 0)
print(idc.add_struc_member(msid, "member1", -1, (ida_bytes.FF_DWORD|ida_bytes.FF_DATA )&0xFFFFFFFF, -1, 4))
print(idc.add_struc_member(msid, "member2", -1, (ida_bytes.FF_DWORD|ida_bytes.FF_DATA )&0xFFFFFFFF, -1, 4))
# Test struct member type by preparing the whole structure at once
mtif = ida_typeinf.tinfo_t()
if mtif.get_named_type(None, "mystr2"):
ida_typeinf.del_named_type(None, "mystr2", ida_typeinf.NTF_TYPE)
msize = ida_struct.get_struc_size(msid)
print("Struct:", idc.add_struc_member(sid, "tstruct", -1, ida_bytes.FF_STRUCT|ida_bytes.FF_DATA, msid, msize))
print("Stroff:", idc.add_struc_member(sid, "tstroff", -1, ida_bytes.stroff_flag()|ida_bytes.FF_DWORD, msid, 4))
mudt = ida_typeinf.udt_type_data_t()
mudt.name="mystr2"
mudm = ida_typeinf.udm_t()
mudm.name="member1"
mudm.type = ida_typeinf.tinfo_t(ida_typeinf.BTF_INT)
mudt.push_back(mudm)
mudm.name="member2"
mudt.push_back(mudm)
mtif.create_udt(mudt)
print("Struct 2:", ida_typeinf.tinfo_errstr(mtif.set_named_type(None, "mystr2")) )
#Test structure member
udm.size = mtif.get_size() * 8
udm.offset = tif.get_unpadded_size() * 8
udm.name = "tstruct"
udm.type = mtif
print("Struct member:", ida_typeinf.tinfo_errstr(tif.add_udm(udm)) )
#Test pointer to structure
udm.name = "strptr"
udm.size = 32
udm.offset = tif.get_unpadded_size() * 8
if not mtif.create_ptr(mtif):
print("Error while creating structure pointer")
udm.type = mtif
print("Strptr:", ida_typeinf.tinfo_errstr(tif.add_udm(udm)) )
#Test structure offset
udm.name = "tstroff"
udm.size = 32
udm.offset = tif.get_unpadded_size() * 8
udm.type.parse("int tstroff __stroff(mystr2);")
print("Stroff:", ida_typeinf.tinfo_errstr(tif.add_udm(udm)) )
# Test offset types
print("Offset:", idc.add_struc_member(sid, "toffset", -1, ida_bytes.off_flag()|ida_bytes.FF_DATA|ida_bytes.FF_DWORD, 0, 4))
print("Offset:", idc.set_member_type(sid, 0, ida_bytes.off_flag()|ida_bytes.FF_DATA|ida_bytes.FF_DWORD, 0, 4))
udm.name = "toffset"
udm.size = 32
udm.offset = tif.get_unpadded_size() * 8
udm.type.parse("void *toffset;")
print("Offset:", ida_typeinf.tinfo_errstr(tif.add_udm(udm)) )
# Test C bitfield types
udm.name = "tbitfield"
udm.offset = tif.get_unpadded_size() * 8
btif = ida_typeinf.tinfo_t()
btif.create_bitfield(4, 2, True) # unsigned __int32 : 2
udm.size = 2
udm.type = btif
print("Bitfield:", ida_typeinf.tinfo_errstr(tif.add_udm(udm)) )
# Print the expanded structure
pflags = ida_typeinf.PRTYPE_TYPE|ida_typeinf.PRTYPE_DEF|ida_typeinf.PRTYPE_MULTI
print(tif._print(tif.get_type_name(), pflags))
if mtif.get_named_type(None, "mystr2"):
print(mtif._print(mtif.get_type_name(), pflags))
print("Done")
@@ -14,9 +14,9 @@ description:
import ida_bytes
import ida_idaapi
import ida_lines
import ida_struct
import ida_netnode
import ida_nalt
import ida_typeinf
import sys
import struct
@@ -37,7 +37,8 @@ class pascal_data_type(ida_bytes.data_type_t):
def calc_item_size(self, ea, maxsize):
# Custom data types may be used in structure definitions. If this case
# ea is a member id. Check for this situation and return 1
if ida_struct.is_member_id(ea):
tif = ida_typeinf.tinfo_t()
if tif.get_udm_by_tid(None, ea) != -1:
return 1
# get the length byte
@@ -87,7 +88,8 @@ class simplevm_data_type(ida_bytes.data_type_t):
asm_keyword)
def calc_item_size(self, ea, maxsize):
if ida_struct.is_member_id(ea):
tif = ida_typeinf.tinfo_t()
if tif.get_udm_by_tid(None, ea) != -1:
return 1
# get the opcode and see if it has an imm
n = 5 if (ida_bytes.get_byte(ea) & 3) == 0 else 1
+32 -18
View File
@@ -12,32 +12,37 @@ description:
* select some text in one of the listing widgets (i.e.,
"IDA View-*", "Enums", "Structures", "Pseudocode-*")
* press Ctrl+Shift+S to dump the selection
"""
import ida_kernwin
import ida_lines
def get_widget_lines(widget, tp0, tp1):
"""
get lines between places tp0 and tp1 in widget
"""
ud = ida_kernwin.get_viewer_user_data(widget)
lnar = ida_kernwin.linearray_t(ud)
lnar.set_place(tp0.at)
lines = []
while True:
cur_place = lnar.get_place()
first_line_ref = ida_kernwin.l_compare2(cur_place, tp0.at, ud)
last_line_ref = ida_kernwin.l_compare2(cur_place, tp1.at, ud)
if last_line_ref > 0: # beyond last line
break
line = ida_lines.tag_remove(lnar.down())
if last_line_ref == 0: # at last line
line = line[0:tp1.x]
elif first_line_ref == 0: # at first line
line = ' ' * tp0.x + line[tp0.x:]
lines.append(line)
return lines
class dump_selection_handler_t(ida_kernwin.action_handler_t):
def activate(self, ctx):
if ctx.has_flag(ida_kernwin.ACF_HAS_SELECTION):
tp0, tp1 = ctx.cur_sel._from, ctx.cur_sel.to
ud = ida_kernwin.get_viewer_user_data(ctx.widget)
lnar = ida_kernwin.linearray_t(ud)
lnar.set_place(tp0.at)
lines = []
while True:
cur_place = lnar.get_place()
first_line_ref = ida_kernwin.l_compare2(cur_place, tp0.at, ud)
last_line_ref = ida_kernwin.l_compare2(cur_place, tp1.at, ud)
if last_line_ref > 0: # beyond last line
break
line = ida_lines.tag_remove(lnar.down())
if last_line_ref == 0: # at last line
line = line[0:tp1.x]
elif first_line_ref == 0: # at first line
line = ' ' * tp0.x + line[tp0.x:]
lines.append(line)
lines = get_widget_lines(ctx.widget, ctx.cur_sel._from, ctx.cur_sel.to)
for line in lines:
print(line)
return 1
@@ -69,3 +74,12 @@ if ida_kernwin.register_action(
dump_selection_handler_t(),
ACTION_SHORTCUT)):
print("Registered action \"%s\"" % ACTION_NAME)
# dump current selection
p0 = ida_kernwin.twinpos_t()
p1 = ida_kernwin.twinpos_t()
view = ida_kernwin.get_current_viewer()
if ida_kernwin.read_selection(view, p0, p1):
lines = get_widget_lines(view, p0, p1)
print("\n".join(lines))
+31 -13
View File
@@ -14,8 +14,11 @@ import ida_idaapi
import ida_hexrays
import ida_lines
do_dbg = False
def dbg(msg):
#print(msg)
if do_dbg:
print(msg)
pass
def is_cident_char(c):
@@ -23,13 +26,19 @@ def is_cident_char(c):
def my_tag_skipcodes(l, storage):
n = ida_lines.tag_skipcodes(l)
dbg("Skipping %d chars ('%s')" % (n, l[0:n]))
storage.append(l[0:n])
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):
@@ -37,25 +46,34 @@ def remove_spaces(sl):
out.append(c)
# skip initial spaces, do not compress them
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:]
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
dbg("-" * 60)
nchars = ida_lines.tag_advance(l, 1)
push(l[0:nchars])
l = l[nchars:]
+7 -1
View File
@@ -163,7 +163,13 @@ class vds_hooks_t(ida_hexrays.Hexrays_Hooks):
def cmt_changed(self, cfunc, loc, cmt):
return self._log()
def build_callinfo(self, *args):
def build_callinfo(self, blk, type):
return self._log()
def callinfo_built(self, blk):
return self._log()
def calls_done(self, mba):
return self._log()
vds_hooks = vds_hooks_t()
+5 -3
View File
@@ -21,6 +21,10 @@ class my_modifier_t(ida_hexrays.user_lvar_modifier_t):
def modify_lvars(self, lvars):
def log(msg):
print("modify_lvars: %s" % msg)
"""Note: lvars.lvvec contains only variables modified from the defaults.
To change other variables, you can, for example, first use rename_lvar()
so they get added to this list, then use modify_user_lvar_info() or modify_lvars().
"""
log("len(lvars.lvvec) = %d" % len(lvars.lvvec))
log("lvars.lmaps.size() = %d" % lvars.lmaps.size())
log("lvars.stkoff_delta = %d" % lvars.stkoff_delta)
@@ -36,9 +40,7 @@ class my_modifier_t(ida_hexrays.user_lvar_modifier_t):
varlog("flags = %x" % one.flags)
new_type = self.new_types.get(one.name)
if new_type:
tif = ida_typeinf.tinfo_t()
ida_typeinf.parse_decl(tif, None, new_type, 0)
one.type = tif
ida_typeinf.parse_decl(one.type, None, new_type, 0)
one.name = self.name_prefix + one.name
one.cmt = self.cmt_prefix + one.cmt
+10 -6
View File
@@ -15,7 +15,6 @@ import ida_kernwin
import ida_hexrays
import ida_typeinf
import ida_idaapi
import ida_struct
import ida_funcs
import idautils
@@ -66,12 +65,17 @@ class XrefsForm(ida_kernwin.PluginForm):
xtype = x.type
xtype.remove_ptr_or_array()
typename = ida_typeinf.print_tinfo('', 0, 0, ida_typeinf.PRTYPE_1LINE, xtype, '', '')
tif = ida_typeinf.tinfo_t()
if not tif.get_named_type(None, typename):
print("Error while retrieving %s type.", typename)
return typename
udm = ida_typeinf.udm_t()
udm.offset = m
if tif.find_udm(udm, ida_typeinf.STRMEM_OFFSET) == -1:
print("Error while retrieving %s member.", typename)
return typename
sid = ida_struct.get_struc_id(typename)
sptr = ida_struct.get_struc(sid)
member = ida_struct.get_member(sptr, m)
return '%s::%s' % (typename, member)
return '%s::%s' % (typename, udm.name)
def OnCreate(self, widget):
+1 -1
View File
@@ -223,7 +223,7 @@ class idb_logger_hooks_t(ida_idp.IDB_Hooks):
def loader_finished(self, li, neflags, filetypename):
return self._log()
def local_types_changed(self):
def local_types_changed(self, ltc, ordinal, name):
return self._log()
def make_code(self, insn):
+19 -10
View File
@@ -11,8 +11,7 @@ import binascii
import ida_idp
import ida_bytes
import ida_nalt
import ida_struct
import ida_enum
import ida_typeinf
class operand_changed_t(ida_idp.IDB_Hooks):
def log(self, msg):
@@ -26,9 +25,14 @@ class operand_changed_t(ida_idp.IDB_Hooks):
opi = ida_bytes.get_opinfo(buf, ea, n, flags)
if opi:
if ida_bytes.is_struct(flags):
self.log("New struct: 0x%08X (name=%s)" % (
opi.tid,
ida_struct.get_struc_name(opi.tid)))
tif = ida_typeinf.tinfo_t()
if tif.get_type_by_tid(opi.tid):
self.log("New struct: 0x%08X ordinal: %d (name=%s)" % (
tif.get_tid(),
tif.get_ordinal(),
tif.get_type_name()))
else:
self.log("Failed tif")
elif ida_bytes.is_strlit(flags):
encidx = ida_nalt.get_str_encoding_idx(opi.strtype)
if encidx == ida_nalt.STRENC_DEFAULT:
@@ -50,16 +54,21 @@ class operand_changed_t(ida_idp.IDB_Hooks):
opi.ri.tdelta,
opi.ri.flags))
elif ida_bytes.is_enum(flags, n):
self.log("New enum: 0x%08X (enum=%s), serial=%d" % (
opi.ec.tid,
ida_enum.get_enum_name(opi.ec.tid),
opi.ec.serial))
tif = ida_typeinf.tinfo_t()
if tif.get_type_by_tid(opi.ec.tid):
self.log("New enum: 0x%08X ordinal: %d (enum=%s), serial=%d" % (
opi.ec.tid,
tif.get_ordinal(),
tif.get_type_name(),
opi.ec.serial))
else:
self.log("Failed tif")
pass
elif ida_bytes.is_stroff(flags, n):
parts = []
for i in range(opi.path.len):
tid = opi.path.ids[i]
parts.append("0x%08X (name=%s)" % (tid, ida_struct.get_struc_name(tid)))
parts.append("0x%08X (name=%s)" % (tid, ida_typeinf.get_tid_name(tid)))
self.log("New stroff: path=[%s] (len=%d, delta=0x%08X)" % (
", ".join(parts),
opi.path.len,
+31 -30
View File
@@ -446,29 +446,27 @@ members of different types.
<li>APIs used
<ul>
<li>ida_bytes.FF_BYTE</li>
<li>ida_bytes.FF_DATA</li>
<li>ida_bytes.FF_DOUBLE</li>
<li>ida_bytes.FF_DWORD</li>
<li>ida_bytes.FF_FLOAT</li>
<li>ida_bytes.FF_OWORD</li>
<li>ida_bytes.FF_PACKREAL</li>
<li>ida_bytes.FF_QWORD</li>
<li>ida_bytes.FF_STRLIT</li>
<li>ida_bytes.FF_STRUCT</li>
<li>ida_bytes.FF_TBYTE</li>
<li>ida_bytes.FF_WORD</li>
<li>ida_bytes.off_flag</li>
<li>ida_bytes.stroff_flag</li>
<li>ida_idaapi.BADADDR</li>
<li>ida_nalt.STRTYPE_C</li>
<li>ida_struct.add_struc</li>
<li>ida_struct.get_struc_id</li>
<li>ida_struct.get_struc_size</li>
<li>idc.add_struc</li>
<li>idc.add_struc_member</li>
<li>idc.del_struc</li>
<li>idc.set_member_type</li>
<li>ida_typeinf.BTF_BYTE</li>
<li>ida_typeinf.BTF_DOUBLE</li>
<li>ida_typeinf.BTF_FLOAT</li>
<li>ida_typeinf.BTF_INT</li>
<li>ida_typeinf.BTF_INT128</li>
<li>ida_typeinf.BTF_INT16</li>
<li>ida_typeinf.BTF_INT64</li>
<li>ida_typeinf.BTF_TBYTE</li>
<li>ida_typeinf.BTF_UINT32</li>
<li>ida_typeinf.FRB_NUMO</li>
<li>ida_typeinf.NTF_TYPE</li>
<li>ida_typeinf.PRTYPE_DEF</li>
<li>ida_typeinf.PRTYPE_MULTI</li>
<li>ida_typeinf.PRTYPE_TYPE</li>
<li>ida_typeinf.del_named_type</li>
<li>ida_typeinf.idc_parse_types</li>
<li>ida_typeinf.tinfo_errstr</li>
<li>ida_typeinf.tinfo_t</li>
<li>ida_typeinf.udm_t</li>
<li>ida_typeinf.udt_type_data_t</li>
<li>ida_typeinf.value_repr_t</li>
</ul>
</li>
@@ -561,7 +559,7 @@ one format for a specific 'custom data type'.)
<li>ida_lines.SCOLOR_REG</li>
<li>ida_nalt.get_input_file_path</li>
<li>ida_netnode.netnode</li>
<li>ida_struct.is_member_id</li>
<li>ida_typeinf.tinfo_t</li>
</ul>
</li>
@@ -700,10 +698,13 @@ After running this script:
<li>ida_kernwin.BWN_STRUCTS</li>
<li>ida_kernwin.action_desc_t</li>
<li>ida_kernwin.action_handler_t</li>
<li>ida_kernwin.get_current_viewer</li>
<li>ida_kernwin.get_viewer_user_data</li>
<li>ida_kernwin.l_compare2</li>
<li>ida_kernwin.linearray_t</li>
<li>ida_kernwin.read_selection</li>
<li>ida_kernwin.register_action</li>
<li>ida_kernwin.twinpos_t</li>
<li>ida_kernwin.unregister_action</li>
<li>ida_lines.tag_remove</li>
</ul>
@@ -2940,7 +2941,6 @@ comments and/or types of local variables.
<li>ida_hexrays.modify_user_lvars</li>
<li>ida_hexrays.user_lvar_modifier_t</li>
<li>ida_typeinf.parse_decl</li>
<li>ida_typeinf.tinfo_t</li>
<li>idc.here</li>
</ul>
</li>
@@ -3006,11 +3006,11 @@ pressed in the Decompiler window.
<li>ida_kernwin.action_handler_t</li>
<li>ida_kernwin.attach_action_to_popup</li>
<li>ida_kernwin.register_action</li>
<li>ida_struct.get_member</li>
<li>ida_struct.get_struc</li>
<li>ida_struct.get_struc_id</li>
<li>ida_typeinf.PRTYPE_1LINE</li>
<li>ida_typeinf.STRMEM_OFFSET</li>
<li>ida_typeinf.print_tinfo</li>
<li>ida_typeinf.tinfo_t</li>
<li>ida_typeinf.udm_t</li>
<li>idautils.Functions</li>
<li>idautils.XrefsTo</li>
</ul>
@@ -3096,7 +3096,6 @@ an instruction's operand, or a data item.
<li>ida_bytes.is_strlit</li>
<li>ida_bytes.is_stroff</li>
<li>ida_bytes.is_struct</li>
<li>ida_enum.get_enum_name</li>
<li>ida_idp.IDB_Hooks</li>
<li>ida_nalt.STRENC_DEFAULT</li>
<li>ida_nalt.get_default_encoding_idx</li>
@@ -3104,7 +3103,8 @@ an instruction's operand, or a data item.
<li>ida_nalt.get_str_encoding_idx</li>
<li>ida_nalt.get_strtype_bpu</li>
<li>ida_nalt.opinfo_t</li>
<li>ida_struct.get_struc_name</li>
<li>ida_typeinf.get_tid_name</li>
<li>ida_typeinf.tinfo_t</li>
</ul>
</li>
@@ -4145,6 +4145,7 @@ IDA, with a custom widget.
<li>ida_kernwin.Choose.CHCOL_FNAME</li>
<li>ida_kernwin.Choose.CHCOL_HEX</li>
<li>ida_kernwin.Choose.CHCOL_PLAIN</li>
<li>ida_kernwin.get_icon_id_by_name</li>
<li>idautils.Functions</li>
<li>idc.del_func</li>
</ul>
+31 -30
View File
@@ -336,29 +336,27 @@ Usage of the API to create & populate a structure with
members of different types.
#### Uses
* ida_bytes.FF_BYTE
* ida_bytes.FF_DATA
* ida_bytes.FF_DOUBLE
* ida_bytes.FF_DWORD
* ida_bytes.FF_FLOAT
* ida_bytes.FF_OWORD
* ida_bytes.FF_PACKREAL
* ida_bytes.FF_QWORD
* ida_bytes.FF_STRLIT
* ida_bytes.FF_STRUCT
* ida_bytes.FF_TBYTE
* ida_bytes.FF_WORD
* ida_bytes.off_flag
* ida_bytes.stroff_flag
* ida_idaapi.BADADDR
* ida_nalt.STRTYPE_C
* ida_struct.add_struc
* ida_struct.get_struc_id
* ida_struct.get_struc_size
* idc.add_struc
* idc.add_struc_member
* idc.del_struc
* idc.set_member_type
* ida_typeinf.BTF_BYTE
* ida_typeinf.BTF_DOUBLE
* ida_typeinf.BTF_FLOAT
* ida_typeinf.BTF_INT
* ida_typeinf.BTF_INT128
* ida_typeinf.BTF_INT16
* ida_typeinf.BTF_INT64
* ida_typeinf.BTF_TBYTE
* ida_typeinf.BTF_UINT32
* ida_typeinf.FRB_NUMO
* ida_typeinf.NTF_TYPE
* ida_typeinf.PRTYPE_DEF
* ida_typeinf.PRTYPE_MULTI
* ida_typeinf.PRTYPE_TYPE
* ida_typeinf.del_named_type
* ida_typeinf.idc_parse_types
* ida_typeinf.tinfo_errstr
* ida_typeinf.tinfo_t
* ida_typeinf.udm_t
* ida_typeinf.udt_type_data_t
* ida_typeinf.value_repr_t
#### Author
Gergely Erdelyi (gergely.erdelyi@d-dome.net)
@@ -439,7 +437,7 @@ one format for a specific 'custom data type'.)
* ida_lines.SCOLOR_REG
* ida_nalt.get_input_file_path
* ida_netnode.netnode
* ida_struct.is_member_id
* ida_typeinf.tinfo_t
</blockquote>
@@ -556,10 +554,13 @@ Ctrl+Shift+S
* ida_kernwin.BWN_STRUCTS
* ida_kernwin.action_desc_t
* ida_kernwin.action_handler_t
* ida_kernwin.get_current_viewer
* ida_kernwin.get_viewer_user_data
* ida_kernwin.l_compare2
* ida_kernwin.linearray_t
* ida_kernwin.read_selection
* ida_kernwin.register_action
* ida_kernwin.twinpos_t
* ida_kernwin.unregister_action
* ida_lines.tag_remove
@@ -2447,7 +2448,6 @@ comments and/or types of local variables.
* ida_hexrays.modify_user_lvars
* ida_hexrays.user_lvar_modifier_t
* ida_typeinf.parse_decl
* ida_typeinf.tinfo_t
* idc.here
</blockquote>
@@ -2505,11 +2505,11 @@ ctxmenu Hexrays_Hooks
* ida_kernwin.action_handler_t
* ida_kernwin.attach_action_to_popup
* ida_kernwin.register_action
* ida_struct.get_member
* ida_struct.get_struc
* ida_struct.get_struc_id
* ida_typeinf.PRTYPE_1LINE
* ida_typeinf.STRMEM_OFFSET
* ida_typeinf.print_tinfo
* ida_typeinf.tinfo_t
* ida_typeinf.udm_t
* idautils.Functions
* idautils.XrefsTo
@@ -2581,7 +2581,6 @@ IDB_Hooks
* ida_bytes.is_strlit
* ida_bytes.is_stroff
* ida_bytes.is_struct
* ida_enum.get_enum_name
* ida_idp.IDB_Hooks
* ida_nalt.STRENC_DEFAULT
* ida_nalt.get_default_encoding_idx
@@ -2589,7 +2588,8 @@ IDB_Hooks
* ida_nalt.get_str_encoding_idx
* ida_nalt.get_strtype_bpu
* ida_nalt.opinfo_t
* ida_struct.get_struc_name
* ida_typeinf.get_tid_name
* ida_typeinf.tinfo_t
</blockquote>
@@ -3454,6 +3454,7 @@ chooser functions
* ida_kernwin.Choose.CHCOL_FNAME
* ida_kernwin.Choose.CHCOL_HEX
* ida_kernwin.Choose.CHCOL_PLAIN
* ida_kernwin.get_icon_id_by_name
* idautils.Functions
* idc.del_func
@@ -24,7 +24,7 @@ class my_funcs_t(ida_kernwin.Choose):
[ ["Address", 10 | ida_kernwin.Choose.CHCOL_HEX],
["Name", 30 | ida_kernwin.Choose.CHCOL_PLAIN | ida_kernwin.Choose.CHCOL_FNAME] ])
self.items = []
self.icon = 41
self.icon = ida_kernwin.get_icon_id_by_name("resources/menu/OpenFunctions.svg")
def OnInit(self):
self.items = [ [hex(x), ida_funcs.get_func_name(x), x]
+3
View File
@@ -149,3 +149,6 @@ void ext_api_t::clear()
}
#endif
ext_api_t extapi;
+2
View File
@@ -59,4 +59,6 @@ struct ext_api_t
void clear();
};
extern ext_api_t extapi;
#endif // EXTAPI_HPP
-3
View File
@@ -34,8 +34,6 @@
#include "extapi.hpp"
#include "extapi.cpp"
ext_api_t extapi;
//-------------------------------------------------------------------------
idapython_plugin_t *idapython_plugin_t::instance = nullptr;
@@ -620,7 +618,6 @@ struct python_highlighter_t : public ida_syntax_highlighter_t
"raise|return|try|while|with|yield|"
"None|True|False",HF_KEYWORD1);
add_keywords("self", HF_KEYWORD2);
add_keywords("def", HF_KEYWORD3);
}
void add_new_keywords()
+6 -5
View File
@@ -8,10 +8,11 @@ global:
PyW_GetStringAttr;
PyW_IsSequenceType;
PyW_ObjectToString;
PyW_PyListToEaVec;
PyW_PyListToEa64Vec;
PyW_PyListToSizeVec;
PyW_PyListToStrVec;
PyW_PySeqToEaVec;
PyW_PySeqToTidVec;
PyW_PySeqToEa64Vec;
PyW_PySeqToSizeVec;
PyW_PySeqToStrVec;
PyW_from_jvalue_t;
PyW_to_jvalue_t;
PyW_from_jobj_t;
@@ -56,7 +57,7 @@ global:
python_timer_new;
pyvar_to_idcvar;
pyvar_to_idcvar_or_error;
pyvar_walk_list;
pyvar_walk_seq;
pyw_convert_idc_args;
register_module_lifecycle_callbacks;
set_script_timeout;
+6 -5
View File
@@ -9,10 +9,11 @@ EXPORTS
PyW_StrVecToPyList
PyW_IsSequenceType
PyW_ObjectToString
PyW_PyListToEaVec
PyW_PyListToEa64Vec
PyW_PyListToSizeVec
PyW_PyListToStrVec
PyW_PySeqToEaVec
PyW_PySeqToTidVec
PyW_PySeqToEa64Vec
PyW_PySeqToSizeVec
PyW_PySeqToStrVec
PyW_from_jvalue_t
PyW_to_jvalue_t
PyW_from_jobj_t
@@ -47,7 +48,7 @@ EXPORTS
python_timer_del
pyvar_to_idcvar
pyvar_to_idcvar_or_error
pyvar_walk_list
pyvar_walk_seq
pyw_convert_idc_args
set_script_timeout
set_interruptible_state
+99 -47
View File
@@ -18,13 +18,36 @@ include ../../allmake.mak
#----------------------------------------------------------------------
# default goals
.PHONY: configs modules pyfiles deployed_modules idapython_modules api_contents pydoc_injections pyqt sip bins public_tree test_idc docs tbd examples_index
all: configs modules pyfiles deployed_modules idapython_modules api_contents pydoc_injections pyqt sip bins examples_index # public_tree test_idc docs
.PHONY: configs modules pyfiles deployed_modules idapython_modules api_check api_contents pyqt sip bins public_tree test_idc docs tbd examples_index test_pywraps
all: configs modules pyfiles deployed_modules idapython_modules api_check api_contents pyqt sip bins examples_index test_pywraps # public_tree test_idc docs
ifeq ($(OUT_OF_TREE_BUILD),)
IDAPYSWITCH:=$(R)idapyswitch$(B)
IDAPYSWITCH_DEP:=$(IDAPYSWITCH)
IDAPYSWITCH_PATH:=$(IDAPYSWITCH)
TEST_PYWRAPS_RESULT_FNAME:=test_pywraps$(ADRSIZE).txt
ifdef __NT__
# On Windows, we cannot afford to use `test_pywraps` during a
# debug build: since `test_pywraps.exe` relies on `python3.dll`
# (and corresponding headers), Python will force optimized
# iterators resulting in errors such as:
# dumb.obj : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '2' doesn't match value '0' in test_pywraps.obj
# And as it turns out, doing it during an optimized build
# is problematic as well, because it'll typically not find
# `python3.dll`. I tried to support it by patching `PATH`,
# but now we're dealing with cygwin confusion...
ifdef NDEBUG
HAS_TEST_PYWRAPS:=1
PYTHON_ROOT_CYGPATH:=$(shell cygpath $(PYTHON_ROOT))
TEST_PYWRAPS_ENV:=PATH="$$PATH:$(PYTHON_ROOT_CYGPATH)"
endif
else
HAS_TEST_PYWRAPS:=1
endif
ifeq ($(HAS_TEST_PYWRAPS),1)
TEST_PYWRAPS:=$(F)$(TEST_PYWRAPS_RESULT_FNAME).marker
endif
BINS += $(IDAPYSWITCH)
else
ifdef __NT__
@@ -127,6 +150,7 @@ PYTHON_OBJS += $(F)idapython$(O)
$(MODULE): MODULE_OBJS += $(PYTHON_OBJS)
$(MODULE): $(PYTHON_OBJS) $(IDAPYSWITCH_MODULE_DEP) $(TBD_MODULE_DEP)
ifdef __NT__
$(MODULE): OUTDLL = /DLL /NOEXP
$(MODULE): LDFLAGS += /DEF:$(IDAPYTHON_IMPLIB_DEF) /IMPLIB:$(IDAPYTHON_IMPLIB_PATH)
endif
@@ -143,6 +167,7 @@ PATCH_CONST=$(Q)$(PYTHON) tools/patch_constants.py -i $(1) -o $(2)
# TODO move this below, but it might be necessary before the defines-*
ifdef DO_IDAMAKE_SIMPLIFY
QCHKAPI = @echo $(call qcolor,chkapi) && #
QDUMPAPI = @echo $(call qcolor,dumpapi) && #
QDEPLOY = @echo $(call qcolor,deploy) $$< && #
QGENDOXYCFG = @echo $(call qcolor,gendoxycfg) $@ && #
QGENHOOKS = @echo $(call qcolor,genhooks) $< && #
@@ -155,7 +180,6 @@ ifdef DO_IDAMAKE_SIMPLIFY
QSWIG = @echo $(call qcolor,swig) $$< && #
QUPDATE_SDK = @echo $(call qcolor,update_sdk) $< && #
QSPLIT_HEXRAYS_TEMPLATES = @echo $(call qcolor,split_hexrays_templates) $< && #
QPYDOC_INJECTIONS = @echo $(call qcolor,check_injections) $@ && #
QGEN_EXAMPLES_INDEX = @echo $(call qcolor,gen_examples_index) $@ && #
endif
@@ -187,9 +211,9 @@ else
endif
ifeq ($(OUT_OF_TREE_BUILD),)
IDAT_CMD=TVHEADLESS=1 $(IDAT_PATH)$(SUFF64)
IDAT_CMD=TVHEADLESS=1 "$(IDAT_PATH)$(SUFF64)"
else
IDAT_CMD=TVHEADLESS=1 IDAPYTHON_DYNLOAD_BASE=$(R) $(IDAT_PATH)$(SUFF64)
IDAT_CMD=TVHEADLESS=1 IDAPYTHON_DYNLOAD_BASE=$(R) "$(IDAT_PATH)$(SUFF64)"
endif
# envvar HAS_HEXRAYS must have been set by build.py if needed
@@ -274,6 +298,7 @@ MODULES_NAMES += pro
MODULES_NAMES += problems
MODULES_NAMES += range
MODULES_NAMES += registry
MODULES_NAMES += regfinder
MODULES_NAMES += search
MODULES_NAMES += segment
MODULES_NAMES += segregs
@@ -291,6 +316,7 @@ endif
ALL_ST_WRAP_CPP = $(foreach mod,$(MODULES_NAMES),$(ST_WRAP)/$(mod).cpp)
ALL_ST_WRAP_PY = $(foreach mod,$(MODULES_NAMES),$(ST_WRAP)/ida_$(mod).py)
ALL_ST_WRAP_PY_FINAL = $(foreach mod,$(MODULES_NAMES),$(ST_WRAP)/ida_$(mod).py.final)
DEPLOYED_MODULES = $(foreach mod,$(MODULES_NAMES),$(DEPLOY_LIBDIR)/_ida_$(mod)$(PYDLL_EXT))
IDAPYTHON_MODULES = $(foreach mod,$(MODULES_NAMES),$(DEPLOY_PYDIR)/ida_$(mod).py)
PYTHON_BINARY_MODULES = $(foreach mod,$(MODULES_NAMES),$(DEPLOY_LIBDIR)/_ida_$(mod)$(PYDLL_EXT))
@@ -617,8 +643,8 @@ CC_DEFS += MISSED_BC695
CC_DEFS += $(DEF_TYPE_TABLE)
CC_DEFS += $(WITH_HEXRAYS_DEF)
CC_DEFS += USE_STANDARD_FILE_FUNCTIONS
CC_DEFS += VER_MAJOR="7"
CC_DEFS += VER_MINOR="4"
CC_DEFS += VER_MAJOR=$(IDAVER_MAJOR)
CC_DEFS += VER_MINOR=$(IDAVER_MINOR)
CC_DEFS += VER_PATCH="0"
CC_DEFS += __EXPR_SRC
CC_INCP += $(F)
@@ -702,8 +728,12 @@ define make-module-rules
# the presence of the generated .cpp file, and not other generated
# files.
# ../../bin/x86_linux_gcc/python/ida_$(1).py (note: dep. on .cpp. See note above.)
$(DEPLOY_PYDIR)/ida_$(1).py: $(ST_WRAP)/$(1).cpp tools/inject_pydoc.py $(PARSED_HEADERS_MARKER) $(call find-pydoc-patches-deps,$(1)) $(call find-patch-codegen-deps,$(1))
# ../../bin/x86_linux_gcc/python/ida_$(1).py
$(DEPLOY_PYDIR)/ida_$(1).py: $(ST_WRAP)/ida_$(1).py.final
$(Q)$(CP) $$< $$@
# obj/x86_linux_gcc/wrappers/ida_X.py.final (note: dep. on .cpp. See note above.)
$(ST_WRAP)/ida_$(1).py.final: $(ST_WRAP)/$(1).cpp tools/inject_pydoc.py $(PARSED_HEADERS_MARKER) $(call find-pydoc-patches-deps,$(1)) $(call find-patch-codegen-deps,$(1))
$(QINJECT_PYDOC)$(PYTHON) tools/inject_pydoc.py \
--xml-doc-directory $(ST_PARSED_HEADERS) \
--module $(1) \
@@ -817,63 +847,47 @@ endif
#----------------------------------------------------------------------
ifdef TESTABLE_BUILD
API_CONTENTS = api_contents$(EXTRASUF1)$(PYTHON_VERSION_MAJOR).txt
API_CONTENTS = api_contents$(EXTRASUF1).brief
else
API_CONTENTS = release_api_contents$(EXTRASUF1)$(PYTHON_VERSION_MAJOR).txt
API_CONTENTS = api_contents$(EXTRASUF1).full
API_CONTENTS_OPTS := --dump-doc
endif
ST_API_CONTENTS = $(F)$(API_CONTENTS)
ST_API_CONTENTS_SUCCESS = $(ST_API_CONTENTS).success
.PRECIOUS: $(ST_API_CONTENTS)
api_contents: $(ST_API_CONTENTS_SUCCESS)
$(ST_API_CONTENTS_SUCCESS): $(ALL_ST_WRAP_CPP)
ifeq ($(or $(__CODE_CHECKER__),$(NO_CMP_API),$(__ASAN__),$(IDAHOME),$(DEMO_OR_FREE)),)
$(QCHKAPI)$(PYTHON) tools/chkapi.py $(WITH_HEXRAYS_CHKAPI) -i $(subst $(space),$(comma),$(ALL_ST_WRAP_CPP)) -p $(subst $(space),$(comma),$(ALL_ST_WRAP_PY)) -r $(ST_API_CONTENTS)
$(ST_API_CONTENTS_SUCCESS): $(ALL_ST_WRAP_PY_FINAL) $(API_CONTENTS) tools/py_scanner.py
$(QDUMPAPI)$(PYTHON) tools/py_scanner.py --dump-kind $(API_CONTENTS_OPTS) --paths $(subst $(space),$(comma),$(ALL_ST_WRAP_PY_FINAL)) > $(ST_API_CONTENTS)
ifeq ($(OUT_OF_TREE_BUILD),)
ifdef CMP_API # turn off comparison when bw-compat is off, or api_contents will differ
$(Q)(diff -w $(API_CONTENTS) $(ST_API_CONTENTS)) > /dev/null || \
$(Q)((diff -w $(API_CONTENTS) $(ST_API_CONTENTS)) > /dev/null && touch $@) || \
(echo "API CONTENTS CHANGED! update $(API_CONTENTS) or fix the API" && \
echo "(New API: $(ST_API_CONTENTS)) ***" && \
(diff -U 1 -w $(API_CONTENTS) $(ST_API_CONTENTS) && false))
endif
(diff -U 1 -w $(API_CONTENTS) $(ST_API_CONTENTS); true))
else
$(Q)touch $@
endif
else
$(ST_API_CONTENTS_SUCCESS): $(ALL_ST_WRAP_PY_FINAL) tools/py_scanner.py
$(Q)touch $@
endif
#-------------------------------------------------------------------------
ST_API_CHECK_SUCCESS := $(F)api_check.success
api_check: $(ST_API_CHECK_SUCCESS)
$(ST_API_CHECK_SUCCESS): $(ALL_ST_WRAP_CPP)
ifeq ($(or $(__CODE_CHECKER__),$(NO_CMP_API),$(__ASAN__),$(IDAHOME),$(DEMO_OR_FREE)),)
$(QCHKAPI)$(PYTHON) tools/chkapi.py $(WITH_HEXRAYS_CHKAPI) -i $(subst $(space),$(comma),$(ALL_ST_WRAP_CPP)) -p $(subst $(space),$(comma),$(ALL_ST_WRAP_PY))
endif
$(Q)touch $@
#----------------------------------------------------------------------
# Check that doc injection is stable
ifdef TESTABLE_BUILD
PYDOC_INJECTIONS = pydoc_injections$(EXTRASUF1)$(PYTHON_VERSION_MAJOR).txt
else
PYDOC_INJECTIONS = release_pydoc_injections$(EXTRASUF1)$(PYTHON_VERSION_MAJOR).txt
endif
ST_PYDOC_INJECTIONS = $(F)$(PYDOC_INJECTIONS)
ST_PYDOC_INJECTIONS_SUCCESS = $(ST_PYDOC_INJECTIONS).success
.PRECIOUS: $(ST_PYDOC_INJECTIONS)
ifdef __EA64__
DUMPDOC_IS_64:=True
else
DUMPDOC_IS_64:=False
endif
ifndef NOTEAMS
VAULT_SERVER_OPTS=-Ovault:host=$(TEAMS_BUILD_HOST):port=$(TEAMS_BUILD_PORT):user=$(TEAMS_BUILD_USER):pass=$(TEAMS_BUILD_PASS)
endif
PYDOC_INJECTIONS_IDAT_CMD=$(IDAT_CMD) $(BATCH_SWITCH) $(VAULT_SERVER_OPTS) -S"$< $(ST_PYDOC_INJECTIONS) $(ST_WRAP) $(DUMPDOC_IS_64)" -t -L$(F)dumpdoc.log >/dev/null
pydoc_injections: $(ST_PYDOC_INJECTIONS_SUCCESS)
$(ST_PYDOC_INJECTIONS_SUCCESS): tools/dumpdoc.py $(IDAPYTHON_MODULES) $(PYTHON_BINARY_MODULES)
ifeq ($(or $(__CODE_CHECKER__),$(NO_CMP_API),$(__ASAN__),$(IDAHOME),$(DEMO_OR_FREE)),)
$(QPYDOC_INJECTIONS)$(PYDOC_INJECTIONS_IDAT_CMD) || \
(echo "Command \"$(PYDOC_INJECTIONS_IDAT_CMD)\" failed. Check \"$(F)dumpdoc.log\" for details." && false)
$(Q)(diff -w $(PYDOC_INJECTIONS) $(ST_PYDOC_INJECTIONS)) > /dev/null || \
(echo "PYDOC INJECTION CHANGED! update $(PYDOC_INJECTIONS) or fix .. what needs fixing" && \
echo "(New API: $(ST_PYDOC_INJECTIONS)) ***" && \
(diff -U 1 -w $(PYDOC_INJECTIONS) $(ST_PYDOC_INJECTIONS) && false))
endif
$(Q)touch $@
#----------------------------------------------------------------------
DOCS_MODULES=$(foreach mod,$(MODULES_NAMES),ida_$(mod))
SORTED_DOCS_MODULES=$(sort $(DOCS_MODULES))
@@ -935,6 +949,34 @@ ifdef __NT__
endif
$(R)idapyswitch$(B): $(call dumb_target, pro, $(IDAPYSWITCH_OBJS))
#----------------------------------------------------------------------
TEST_PYWRAPS_OBJS += $(F)test_pywraps$(O)
TEST_PYWRAPS_DEPS := pywraps.cpp pywraps.hpp extapi.cpp extapi.hpp
$(F)test_pywraps$(O): $(PARSED_HEADERS_MARKER) $(TEST_PYWRAPS_DEPS)
ifdef __NT__
ifneq ($(OUT_OF_TREE_BUILD),)
# SDK provides only MT libraries
$(F)test_pywraps$(O): RUNTIME_LIBSW=/MT
endif
endif
$(R)test_pywraps$(B): $(call dumb_target, json idc unicode pro, $(TEST_PYWRAPS_OBJS)) $(PYTHON_LDFLAGS)
$(F)$(TEST_PYWRAPS_RESULT_FNAME).marker: $(R)test_pywraps$(B)
$(Q)$(TEST_PYWRAPS_ENV) $(R)test_pywraps$(B) > $(F)$(TEST_PYWRAPS_RESULT_FNAME)
ifeq ($(OUT_OF_TREE_BUILD),)
$(Q)((diff -w $(TEST_PYWRAPS_RESULT_FNAME) $(F)$(TEST_PYWRAPS_RESULT_FNAME)) > /dev/null && touch $@) || \
(echo "$(TEST_PYWRAPS_RESULT_FNAME) changed" && \
(diff -U 1 -w $(TEST_PYWRAPS_RESULT_FNAME) $(F)$(TEST_PYWRAPS_RESULT_FNAME); true))
else
$(Q)touch $@
endif
ifdef __CODE_CHECKER__
test_pywraps: ;
else
test_pywraps: $(TEST_PYWRAPS)
endif
#----------------------------------------------------------------------
ifdef __MAC__
tbd: $(TBD_MODULE_DEP)
@@ -1071,6 +1113,7 @@ $(F)idapyswitch$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
../../ldr/mach-o/h/sys/_symbol_aliasing.h \
../../ldr/mach-o/h/sys/cdefs.h \
../../ldr/mach-o/macho_node.h \
../../ldr/mach-o/strtab_reader_t.h \
../../ldr/mach-o/uncompress.cpp ../../ldr/pe/../idaldr.h \
../../ldr/pe/common.cpp ../../ldr/pe/common.h \
../../ldr/pe/pe.h idapyswitch.cpp idapyswitch_linux.cpp \
@@ -1083,5 +1126,14 @@ $(F)idapython$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \
$(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)parsejson.hpp $(I)pro.h \
$(I)range.hpp $(I)segment.hpp $(I)typeinf.hpp $(I)ua.hpp \
$(I)xref.hpp extapi.cpp \
extapi.hpp idapython.cpp pywraps.cpp pywraps.hpp
$(I)xref.hpp extapi.hpp idapython.cpp pywraps.cpp \
pywraps.hpp
$(F)test_pywraps$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \
$(I)err.h $(I)expr.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)gdl.hpp $(I)graph.hpp $(I)ida.hpp $(I)idd.hpp \
$(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lex.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \
$(I)name.hpp $(I)netnode.hpp $(I)parsejson.hpp $(I)pro.h \
$(I)range.hpp $(I)segment.hpp $(I)typeinf.hpp $(I)ua.hpp \
$(I)xref.hpp extapi.cpp extapi.hpp pywraps.cpp \
pywraps.hpp test_pywraps.cpp
Binary file not shown.
-116572
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+46 -10
View File
@@ -790,7 +790,7 @@ def define_local_var(start, end, location, name):
return 0
# Find out if location is in the [bp+xx] form
r = re.compile("\[([a-z]+)([-+][0-9a-fx]+)", re.IGNORECASE)
r = re.compile(r"\[([a-z]+)([-+][0-9a-fx]+)", re.IGNORECASE)
m = r.match(location)
if m:
@@ -4520,7 +4520,7 @@ def __m1tol(v):
Otherwise, return 'v'.
"""
if v == -1:
return ida_netnode.BADNODE
return ida_netnode.BADNODE
else:
return v
@@ -4978,13 +4978,38 @@ def get_type(ea):
"""
return ida_typeinf.idc_get_type(ea)
def SizeOf(typestr):
def sizeof(typestr):
"""
Returns the size of the type. It is equivalent to IDC's sizeof().
Use name, tp, fld = idc.parse_decl() ; SizeOf(tp) to retrieve the size
@return: -1 if typestring is not valid otherwise the size of the type
@param typestr: can be specified as a typeinfo tuple (e.g. the result of get_tinfo()),
serialized type byte string,
or a string with C declaration (e.g. "int")
@return: -1 if typestring is not valid or has no size. otherwise size of the type
"""
return ida_typeinf.calc_type_size(None, typestr)
if isinstance(typestr, tuple):
if len(typestr) == 3:
# result of idc.parse_decl() ?
tp = typestr[1]
elif len(typestr) == 2:
# reult of idc.get_tinfo() ?
tp = typestr[0]
else:
tp = None
elif isinstance(typestr, bytes):
# raw serialized byte string ?
tp = typestr
elif isinstance(typestr, str):
# C declaration ?
name, tp, _ = parse_decl(typestr, 0)
# here, 'tp' should be the serialized type string
if isinstance(tp, bytes):
r = ida_typeinf.calc_type_size(None, tp)
return -1 if r is None else r
else:
raise TypeError("idc.sizeof(): expected type tuple, serialized type string, or C declaration")
SizeOf = sizeof
def get_tinfo(ea):
"""
@@ -5182,10 +5207,21 @@ def GetLocalType(ordinal, flags):
return ida_typeinf.idc_print_type(type, fields, name, flags)
return ""
PRTYPE_1LINE = 0x0000 # print to one line
PRTYPE_MULTI = 0x0001 # print to many lines
PRTYPE_TYPE = 0x0002 # print type declaration (not variable declaration)
PRTYPE_PRAGMA = 0x0004 # print pragmas for alignment
PRTYPE_1LINE = 0x0000 # print to one line
PRTYPE_MULTI = 0x0001 # print to many lines
PRTYPE_TYPE = 0x0002 # print type declaration (not variable declaration)
PRTYPE_PRAGMA = 0x0004 # print pragmas for alignment
PRTYPE_SEMI = 0x0008 # append ; to the end
PRTYPE_CPP = 0x0010 # use c++ name (only for print_type())
PRTYPE_DEF = 0x0020 # tinfo_t: print definition, if available
PRTYPE_NOARGS = 0x0040 # tinfo_t: do not print function argument names
PRTYPE_NOARRS = 0x0080 # tinfo_t: print arguments with #FAI_ARRAY as pointers
PRTYPE_NORES = 0x0100 # tinfo_t: never resolve types (meaningful with PRTYPE_DEF)
PRTYPE_RESTORE = 0x0200 # tinfo_t: print restored types for #FAI_ARRAY and #FAI_STRUCT
PRTYPE_NOREGEX = 0x0400 # do not apply regular expressions to beautify name
PRTYPE_COLORED = 0x0800 # add color tag COLOR_SYMBOL for any parentheses, commas and colons
PRTYPE_METHODS = 0x1000 # tinfo_t: print udt methods
PRTYPE_1LINCMT = 0x2000 # print comments in one line mode
def get_numbered_type_name(ordinal):
+79 -88
View File
@@ -114,10 +114,11 @@ ref_t ida_export PyW_StrVecToPyList(const qstrvec_t &vec)
}
//-------------------------------------------------------------------------
static Py_ssize_t pyvar_walk_list(
static Py_ssize_t pyvar_walk_seq(
const ref_t &py_list,
int (idaapi *cb)(const ref_t &py_item, Py_ssize_t index, void *ud),
void *ud)
void *ud,
size_t maxsize)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
@@ -130,6 +131,8 @@ static Py_ssize_t pyvar_walk_list(
bool is_seq = !PyList_CheckExact(o);
Py_ssize_t seqsz = is_seq ? PySequence_Size(o) : PyList_Size(o);
if ( maxsize < seqsz )
seqsz = maxsize;
for ( Py_ssize_t i = 0; i < seqsz; ++i )
{
// Get the item
@@ -162,17 +165,18 @@ static Py_ssize_t pyvar_walk_list(
}
//-------------------------------------------------------------------------
Py_ssize_t ida_export pyvar_walk_list(
Py_ssize_t ida_export pyvar_walk_seq(
PyObject *py_list,
int (idaapi *cb)(const ref_t &py_item, Py_ssize_t index, void *ud),
void *ud)
void *ud,
size_t maxsize)
{
borref_t r(py_list);
return pyvar_walk_list(r, cb, ud);
return pyvar_walk_seq(r, cb, ud, maxsize);
}
//---------------------------------------------------------------------------
Py_ssize_t ida_export PyW_PyListToSizeVec(sizevec_t *out, PyObject *py_list)
Py_ssize_t ida_export PyW_PySeqToSizeVec(sizevec_t *out, PyObject *py_list, size_t maxsize)
{
out->clear();
struct ida_local lambda_t
@@ -187,11 +191,14 @@ Py_ssize_t ida_export PyW_PyListToSizeVec(sizevec_t *out, PyObject *py_list)
return CIP_OK;
}
};
return pyvar_walk_list(py_list, lambda_t::cvt, out);
return pyvar_walk_seq(py_list, lambda_t::cvt, out, maxsize);
}
//---------------------------------------------------------------------------
Py_ssize_t ida_export PyW_PyListToEaVec(eavec_t *out, PyObject *py_list)
Py_ssize_t ida_export PyW_PySeqToEaVec(
eavec_t *out,
PyObject *py_list,
size_t maxsize)
{
out->clear();
struct ida_local lambda_t
@@ -217,11 +224,20 @@ Py_ssize_t ida_export PyW_PyListToEaVec(eavec_t *out, PyObject *py_list)
return CIP_OK;
}
};
return pyvar_walk_list(py_list, lambda_t::cvt, out);
return pyvar_walk_seq(py_list, lambda_t::cvt, out, maxsize);
}
//-------------------------------------------------------------------------
Py_ssize_t ida_export PyW_PyListToEa64Vec(ea64vec_t *out, PyObject *py_list)
Py_ssize_t ida_export PyW_PySeqToTidVec(
qvector<tid_t> *out,
PyObject *py_list,
size_t maxsize)
{
return PyW_PySeqToEaVec((eavec_t *) out, py_list, maxsize);
}
//-------------------------------------------------------------------------
Py_ssize_t ida_export PyW_PySeqToEa64Vec(ea64vec_t *out, PyObject *py_list, size_t maxsize)
{
out->clear();
struct ida_local lambda_t
@@ -247,11 +263,11 @@ Py_ssize_t ida_export PyW_PyListToEa64Vec(ea64vec_t *out, PyObject *py_list)
return CIP_OK;
}
};
return pyvar_walk_list(py_list, lambda_t::cvt, out);
return pyvar_walk_seq(py_list, lambda_t::cvt, out, maxsize);
}
//---------------------------------------------------------------------------
Py_ssize_t ida_export PyW_PyListToStrVec(qstrvec_t *out, PyObject *py_list)
Py_ssize_t ida_export PyW_PySeqToStrVec(qstrvec_t *out, PyObject *py_list, size_t maxsize)
{
out->clear();
struct ida_local lambda_t
@@ -265,7 +281,7 @@ Py_ssize_t ida_export PyW_PyListToStrVec(qstrvec_t *out, PyObject *py_list)
return CIP_OK;
}
};
return pyvar_walk_list(py_list, lambda_t::cvt, out);
return pyvar_walk_seq(py_list, lambda_t::cvt, out, maxsize);
}
//-------------------------------------------------------------------------
@@ -1315,96 +1331,71 @@ bool ida_export PyW_GetNumberAsIDC(PyObject *py_var, idc_value_t *idc_var)
bool is_64;
if ( !PyW_GetNumber(py_var, &num, &is_64) )
return false;
if ( !is_64 || int64(num) >= SVAL_MIN && int64(num) <= SVAL_MAX ) //-V560 is always true
idc_var->set_long(sval_t(num));
else
if ( is_64 )
idc_var->set_int64(int64(num));
else
idc_var->set_long(sval_t(num));
return true;
}
//-------------------------------------------------------------------------
// Parses a Python object as a long or long long
CASSERT(sizeof(PY_LONG_LONG) == 8);
bool ida_export PyW_GetNumber(PyObject *py_var, uint64 *num, bool *is_64)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
bool rc = true;
#define SETNUM(numexpr, is64_expr) \
do \
{ \
if ( num != nullptr ) \
*num = numexpr; \
if ( is_64 != nullptr ) \
*is_64 = is64_expr; \
} while ( false )
uint64 _num = 0;
bool _is_64 = false;
if ( num == nullptr )
num = &_num;
if ( is_64 == nullptr )
is_64 = &_is_64;
do
*is_64 = false;
if ( !PyLong_CheckExact(py_var) )
return false;
// Try to convert to a signed long long
PY_LONG_LONG ll = PyLong_AsLongLong(py_var);
if ( PyErr_Occurred() == nullptr )
{
if ( !PyLong_CheckExact(py_var) )
{
rc = false;
break;
}
if ( ll < int64(INT_MIN) || ll > int64(INT_MAX) )
*is_64 = true;
*num = uint64(ll);
return true;
}
constexpr bool is_long_64 = sizeof(long) > 4;
// Not a signed long long. Try unsigned long long
PyErr_Clear();
unsigned PY_LONG_LONG ull = PyLong_AsUnsignedLongLong(py_var);
if ( PyErr_Occurred() == nullptr )
{
*is_64 = true;
*num = uint64(ull);
return true;
}
// Can we convert to C long?
long l = PyLong_AsLong(py_var);
if ( PyErr_Occurred() == nullptr )
{
SETNUM(uint64(l), is_long_64);
break;
}
// Clear last error
// Binary AND it with uint64(-1)
if ( PyErr_Occurred() == PyExc_TypeError )
{
PyErr_Clear();
// Can be fit into a C unsigned long?
unsigned long ul = PyLong_AsUnsignedLong(py_var);
if ( PyErr_Occurred() == nullptr ) //-V547 'PyErr_Occurred() == nullptr' is always false
newref_t py_mask(Py_BuildValue("K", 0xFFFFFFFFFFFFFFFFull));
newref_t py_num(PyNumber_And(py_var, py_mask.o));
if ( py_num && py_mask )
{
SETNUM(uint64(ul), is_long_64);
break;
}
PyErr_Clear();
// Try to parse as int64
PY_LONG_LONG ll = PyLong_AsLongLong(py_var);
if ( PyErr_Occurred() == nullptr ) //-V547 'PyErr_Occurred() == nullptr' is always false
{
SETNUM(uint64(ll), true);
break;
}
PyErr_Clear();
// Try to parse as uint64
unsigned PY_LONG_LONG ull = PyLong_AsUnsignedLongLong(py_var);
PyObject *err = PyErr_Occurred();
if ( err == nullptr ) //-V547 'err == 0' is always false
{
SETNUM(uint64(ull), true);
break;
}
// Negative number? _And_ it with uint64(-1)
rc = false;
if ( err == PyExc_TypeError )
{
newref_t py_mask(Py_BuildValue("K", 0xFFFFFFFFFFFFFFFFull));
newref_t py_num(PyNumber_And(py_var, py_mask.o));
if ( py_num && py_mask )
ull = PyLong_AsUnsignedLongLong(py_num.o);
if ( PyErr_Occurred() == nullptr ) //-V547 'PyErr_Occurred() == nullptr' is always false
{
PyErr_Clear();
ull = PyLong_AsUnsignedLongLong(py_num.o);
if ( PyErr_Occurred() == nullptr ) //-V547 'PyErr_Occurred() == nullptr' is always false
{
SETNUM(uint64(ull), true);
rc = true;
}
*is_64 = true;
*num = uint64(ull);
return true;
}
}
PyErr_Clear();
} while ( false );
return rc;
#undef SETNUM
}
PyErr_Clear();
return false;
}
//-------------------------------------------------------------------------
@@ -1747,7 +1738,7 @@ void ida_export py_customidamemo_t_unbind(py_customidamemo_t *_this)
PyObject_SetAttrString(_this->self.o, S_M_THIS, Py_None);
_this->self = newref_t(nullptr);
_this->view = nullptr;
_this->view = nullptr;
}
//-------------------------------------------------------------------------
@@ -2033,7 +2024,7 @@ bool ida_export idapython_convert_cli_completions(
ok = PyList_Check(i0.o) && PyLong_Check(i1.o) && PyLong_Check(i2.o);
if ( ok )
{
ok = PyW_PyListToStrVec(out_completions, i0.o) > 0;
ok = PyW_PySeqToStrVec(out_completions, i0.o) > 0;
if ( ok )
{
*out_match_start = PyLong_AsLong(i1.o);
@@ -2042,7 +2033,7 @@ bool ida_export idapython_convert_cli_completions(
}
else
{
// Clear the error that was set by PyW_PyListToStrVec()
// Clear the error that was set by PyW_PySeqToStrVec()
PyErr_Clear();
}
}
+9 -7
View File
@@ -492,11 +492,12 @@ idaman int ida_export pyvar_to_idcvar(
int *gvar_sn=nullptr);
//-------------------------------------------------------------------------
// Walks a Python list or Sequence and calls the callback
idaman Py_ssize_t ida_export pyvar_walk_list(
// Walks a Python sequence and calls the callback
idaman Py_ssize_t ida_export pyvar_walk_seq(
PyObject *py_list,
int (idaapi *cb)(const ref_t &py_item, Py_ssize_t index, void *ud)=nullptr,
void *ud = nullptr);
void *ud = nullptr,
size_t maxsize=size_t(-1));
// Converts a vector to a Python list object
idaman ref_t ida_export PyW_SizeVecToPyList(const sizevec_t &vec);
@@ -507,9 +508,10 @@ idaman ref_t ida_export PyW_StrVecToPyList(const qstrvec_t &vec);
// An exception will be raised in case:
// - py_list is not a sequence
// - a member of py_list cannot be converted to the numeric target type
idaman Py_ssize_t ida_export PyW_PyListToSizeVec(sizevec_t *out, PyObject *py_list);
idaman Py_ssize_t ida_export PyW_PyListToEaVec(eavec_t *out, PyObject *py_list);
idaman Py_ssize_t ida_export PyW_PyListToStrVec(qstrvec_t *out, PyObject *py_list);
idaman Py_ssize_t ida_export PyW_PySeqToSizeVec(sizevec_t *out, PyObject *py_list, size_t maxsize=size_t(-1));
idaman Py_ssize_t ida_export PyW_PySeqToEaVec(eavec_t *out, PyObject *py_list, size_t maxsize=size_t(-1));
idaman Py_ssize_t ida_export PyW_PySeqToStrVec(qstrvec_t *out, PyObject *py_list, size_t maxsize=size_t(-1));
idaman Py_ssize_t ida_export PyW_PySeqToTidVec(qvector<tid_t> *out, PyObject *py_list, size_t maxsize=size_t(-1));
idaman PyObject *ida_export PyW_from_jvalue_t(const jvalue_t &v);
idaman bool ida_export PyW_to_jvalue_t(jvalue_t *out, PyObject *py);
@@ -524,7 +526,7 @@ typedef uint64 ea64_t;
#endif
typedef qvector<ea64_t> ea64vec_t;
#endif // LUMINA_HPP
idaman Py_ssize_t ida_export PyW_PyListToEa64Vec(ea64vec_t *out, PyObject *py_list);
idaman Py_ssize_t ida_export PyW_PySeqToEa64Vec(ea64vec_t *out, PyObject *py_list, size_t maxsize=size_t(-1));
//-------------------------------------------------------------------------
#include <idd.hpp>
+40 -30
View File
@@ -93,37 +93,37 @@ static bool py_do_get_bytes(
//<inline(py_bytes)>
#define MS_0TYPE 0x00F00000LU ///< Mask for 1st arg typing
#define FF_0VOID 0x00000000LU ///< Void (unknown)?
#define FF_0NUMH 0x00100000LU ///< Hexadecimal number?
#define FF_0NUMD 0x00200000LU ///< Decimal number?
#define FF_0CHAR 0x00300000LU ///< Char ('x')?
#define FF_0SEG 0x00400000LU ///< Segment?
#define FF_0OFF 0x00500000LU ///< Offset?
#define FF_0NUMB 0x00600000LU ///< Binary number?
#define FF_0NUMO 0x00700000LU ///< Octal number?
#define FF_0ENUM 0x00800000LU ///< Enumeration?
#define FF_0FOP 0x00900000LU ///< Forced operand?
#define FF_0STRO 0x00A00000LU ///< Struct offset?
#define FF_0STK 0x00B00000LU ///< Stack variable?
#define FF_0FLT 0x00C00000LU ///< Floating point number?
#define FF_0CUST 0x00D00000LU ///< Custom representation?
#define MS_0TYPE 0x00F00000 ///< Mask for 1st arg typing
#define FF_0VOID 0x00000000 ///< Void (unknown)?
#define FF_0NUMH 0x00100000 ///< Hexadecimal number?
#define FF_0NUMD 0x00200000 ///< Decimal number?
#define FF_0CHAR 0x00300000 ///< Char ('x')?
#define FF_0SEG 0x00400000 ///< Segment?
#define FF_0OFF 0x00500000 ///< Offset?
#define FF_0NUMB 0x00600000 ///< Binary number?
#define FF_0NUMO 0x00700000 ///< Octal number?
#define FF_0ENUM 0x00800000 ///< Enumeration?
#define FF_0FOP 0x00900000 ///< Forced operand?
#define FF_0STRO 0x00A00000 ///< Struct offset?
#define FF_0STK 0x00B00000 ///< Stack variable?
#define FF_0FLT 0x00C00000 ///< Floating point number?
#define FF_0CUST 0x00D00000 ///< Custom representation?
#define MS_1TYPE 0x0F000000LU ///< Mask for the type of other operands
#define FF_1VOID 0x00000000LU ///< Void (unknown)?
#define FF_1NUMH 0x01000000LU ///< Hexadecimal number?
#define FF_1NUMD 0x02000000LU ///< Decimal number?
#define FF_1CHAR 0x03000000LU ///< Char ('x')?
#define FF_1SEG 0x04000000LU ///< Segment?
#define FF_1OFF 0x05000000LU ///< Offset?
#define FF_1NUMB 0x06000000LU ///< Binary number?
#define FF_1NUMO 0x07000000LU ///< Octal number?
#define FF_1ENUM 0x08000000LU ///< Enumeration?
#define FF_1FOP 0x09000000LU ///< Forced operand?
#define FF_1STRO 0x0A000000LU ///< Struct offset?
#define FF_1STK 0x0B000000LU ///< Stack variable?
#define FF_1FLT 0x0C000000LU ///< Floating point number?
#define FF_1CUST 0x0D000000LU ///< Custom representation?
#define MS_1TYPE 0x0F000000 ///< Mask for the type of other operands
#define FF_1VOID 0x00000000 ///< Void (unknown)?
#define FF_1NUMH 0x01000000 ///< Hexadecimal number?
#define FF_1NUMD 0x02000000 ///< Decimal number?
#define FF_1CHAR 0x03000000 ///< Char ('x')?
#define FF_1SEG 0x04000000 ///< Segment?
#define FF_1OFF 0x05000000 ///< Offset?
#define FF_1NUMB 0x06000000 ///< Binary number?
#define FF_1NUMO 0x07000000 ///< Octal number?
#define FF_1ENUM 0x08000000 ///< Enumeration?
#define FF_1FOP 0x09000000 ///< Forced operand?
#define FF_1STRO 0x0A000000 ///< Struct offset?
#define FF_1STK 0x0B000000 ///< Stack variable?
#define FF_1FLT 0x0C000000 ///< Floating point number?
#define FF_1CUST 0x0D000000 ///< Custom representation?
//------------------------------------------------------------------------
/*
@@ -313,6 +313,16 @@ static PyObject *py_get_8bit(ea_t ea, uint32 v, int nbit)
return Py_BuildValue("(i" PY_BV_EA "ki)", int(uint32(octet)), bvea_t(ea), v, nbit);
}
//-------------------------------------------------------------------------
static bool ida_export py_op_stroff(
const insn_t &insn,
int n,
const qvector<tid_t> &path,
adiff_t delta)
{
return op_stroff(insn, n, path.begin(), path.size(), delta);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
+2 -1
View File
@@ -426,7 +426,8 @@ class __cbhooks_t(Hexrays_Hooks):
def create_hint(self, *args): return self.callback(hxe_create_hint, *args)
def text_ready(self, *args): return self.callback(hxe_text_ready, *args)
def populating_popup(self, *args): return self.callback(hxe_populating_popup, *args)
# NOTE: Do not add support for new notifications here;
# non-Hexrays_Hooks callbacks are deprecated.
def install_hexrays_callback(callback):
"Deprecated. Please use Hexrays_Hooks instead"
+1 -1
View File
@@ -685,7 +685,7 @@ static bool py_execute_ui_requests(PyObject *py_list)
// Walk the list and extract all callables
bool init(PyObject *py_list)
{
Py_ssize_t count = pyvar_walk_list(
Py_ssize_t count = pyvar_walk_seq(
py_list,
s_py_list_walk_cb,
this);
+7 -1
View File
@@ -8,6 +8,9 @@
//<inline(py_kernwin_askform)>
#define DECLARE_FORM_ACTIONS form_actions_t *fa = (form_actions_t *)p_fa;
#ifdef TESTABLE_BUILD
#include <features.hpp>
#endif
//---------------------------------------------------------------------------
static bool textctrl_info_t_assign(PyObject *self, PyObject *other)
{
@@ -313,7 +316,7 @@ static bool formchgcbfa_set_field_value(
{
sizevec_t selection;
if ( !PySequence_Check(py_val)
|| PyW_PyListToSizeVec(&selection, py_val) < 0 )
|| PyW_PySeqToSizeVec(&selection, py_val) < 0 )
{
break;
}
@@ -350,6 +353,9 @@ static size_t py_get_open_form()
static void py_register_compiled_form(PyObject *py_form)
{
#ifdef TESTABLE_BUILD
add_test_feature("idapy:askform");
#endif
PyW_register_compiled_form(py_form);
}
+5 -6
View File
@@ -746,7 +746,7 @@ class py_chooser_multi_t : public chooser_multi_t, public py_chooser_mixin_t
cbres_t res;
// this is an easy but not an optimal way of converting
if ( !PySequence_Check(pyres.result.o)
|| PyW_PyListToSizeVec(sel, pyres.result.o) <= 0 )
|| PyW_PySeqToSizeVec(sel, pyres.result.o) <= 0 )
{
sel->clear();
res = NOTHING_CHANGED;
@@ -886,7 +886,7 @@ PyObject *choose_choose(PyObject *self)
ref_t deflt_attr(PyW_TryGetAttrString(self, "deflt"));
if ( deflt_attr != nullptr
&& PyList_Check(deflt_attr.o)
&& PyW_PyListToSizeVec(&deflt, deflt_attr.o) < 0 )
&& PyW_PySeqToSizeVec(&deflt, deflt_attr.o) < 0 )
{
deflt.clear();
}
@@ -989,10 +989,9 @@ PyObject *py_get_chooser_data(const char *chooser_caption, int n)
qstrvec_t data;
if ( !get_chooser_data(&data, chooser_caption, n) )
Py_RETURN_NONE;
PyObject *py_list = PyList_New(data.size());
for ( size_t i = 0; i < data.size(); ++i )
PyList_SetItem(py_list, i, PyUnicode_FromString(data[i].c_str()));
return py_list;
ref_t py_list_ref = PyW_StrVecToPyList(data);
py_list_ref.incref();
return py_list_ref.o;
}
#define CH_NOIDB 0x00000040 // bw-compat
+1 -1
View File
@@ -43,7 +43,7 @@ static bool qstrvec_t_from_list(
qstrvec_t *sv = qstrvec_t_get_clink(self);
return (sv == nullptr || !PySequence_Check(py_list))
? false
: (PyW_PyListToStrVec(sv, py_list) >= 0);
: (PyW_PySeqToStrVec(sv, py_list) >= 0);
}
static size_t qstrvec_t_size(PyObject *self)
+4 -4
View File
@@ -27,8 +27,8 @@ PyObject *idc_parse_decl(til_t *ti, const char *decl, int flags)
def calc_type_size(ti, tp):
"""
Returns the size of a type
@param ti: Type info. 'None' can be passed.
@param tp: type string
@param ti: Type info library. 'None' can be passed.
@param tp: serialized type byte string
@return:
- None on failure
- The size of the type
@@ -56,7 +56,7 @@ PyObject *py_calc_type_size(const til_t *ti, PyObject *tp)
}
else
{
PyErr_SetString(PyExc_ValueError, "String expected!");
PyErr_SetString(PyExc_ValueError, "serialized type byte sequence expected!");
return nullptr;
}
}
@@ -517,7 +517,7 @@ PyObject *py_get_named_type(const til_t *til, const char *name, int ntf_flags)
const type_t *type = nullptr;
const p_list *fields = nullptr, *field_cmts = nullptr;
const char *cmt = nullptr;
sclass_t sclass = sc_unk;
sclass_t sclass = SC_UNK;
uint64 value = 0;
int code = get_named_type(til, name, ntf_flags, &type, &fields, &cmt, &field_cmts, &sclass, (uint32 *) &value);
if ( code == 0 )
+24
View File
@@ -23,4 +23,28 @@ class _wrap_cvar(object):
cvar = _wrap_cvar()
# for compatilibity:
sc_auto = SC_AUTO
sc_ext = SC_EXT
sc_friend = SC_FRIEND
sc_reg = SC_REG
sc_stat = SC_STAT
sc_type = SC_TYPE
sc_unk = SC_UNK
sc_virt = SC_VIRT
TERR_SAVE = TERR_SAVE_ERROR
TERR_WRONGNAME = TERR_BAD_NAME
TERR_BADSYNC = TERR_BAD_SYNC
BADORD = 0xFFFFFFFF
enum_member_vec_t = edmvec_t
enum_member_t = edm_t
udt_member_t = udm_t
tinfo_t.find_udt_member = tinfo_t.find_udm
IMPTYPE_VERBOSE = 0x0001
IMPTYPE_OVERRIDE = 0x0002
#</pycode(py_typeinf)>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1
View File
@@ -38,6 +38,7 @@
%ignore bin_search; // we redefine our own, w/ 2 params swapped, so we can apply the typemaps below
%rename (bin_search) py_bin_search;
%rename (bin_search) bin_search2;
%rename (op_stroff) py_op_stroff;
%ignore bin_search2(ea_t, ea_t, const uchar *, const uchar *, size_t, int);
%ignore bytes_match_for_bin_search;
+5
View File
@@ -87,6 +87,11 @@
%get_process_options_out_qstring(sdir);
%get_process_options_out_qstring(host);
%get_process_options_out_qstring(pass);
%typemap(in, numinputs=0) launch_env_t *envs (launch_env_t temp)
{
// %typemap(in, numinputs=0) launch_env_t *envs (launch_envs_t temp)
$1 = &temp;
}
%apply int *OUTPUT { int *port };
// specialize for 'get_process_options()'s first output
+1 -1
View File
@@ -804,7 +804,7 @@ cexpr_t *citem_t_cexpr_get(citem_t *item) { return (cexpr_t *) item; }
%extend ctree_item_t {
CTREE_ITEM_MEMBER_REF(citem_t *, it);
CTREE_CONDITIONAL_ITEM_MEMBER_REF(citem_t *, it, VDI_EXPR);
CTREE_CONDITIONAL_ITEM_MEMBER_REF(cexpr_t*, e, VDI_EXPR);
CTREE_CONDITIONAL_ITEM_MEMBER_REF(cinsn_t*, i, VDI_EXPR);
CTREE_CONDITIONAL_ITEM_MEMBER_REF(lvar_t*, l, VDI_LVAR);
+1
View File
@@ -58,6 +58,7 @@ struct undo_records_t;
%ignore processor_t::ensure_processor;
%ignore processor_t::lvar_off;
%ignore processor_t::is_lumina_usable;
%ignore processor_t::get_regfinder();
// The following are queried by the "scripting" processor module support
%ignore processor_t::id;
%ignore processor_t::flag;
+13
View File
@@ -68,6 +68,13 @@ struct dirspec_t;
%ignore get_chooser_data;
%rename (get_chooser_data) py_get_chooser_data;
%template(chooser_row_info_vec_t) qvector<chooser_row_info_t>;
%typemap(out) qstrvec_t *
{
Py_XDECREF($result);
$result = qstrvec2pylist(*$1);
}
%rename (del_hotkey) py_del_hotkey;
%rename (add_hotkey) py_add_hotkey;
@@ -427,11 +434,13 @@ SWIG_DECLARE_PY_CLINKED_OBJECT(textctrl_info_t)
%newobject place_t::as_enumplace_t;
%newobject place_t::as_structplace_t;
%newobject place_t::as_simpleline_place_t;
%newobject place_t::as_tiplace_t;
%extend place_t {
static idaplace_t *as_idaplace_t(place_t *p) { return p != nullptr ? (idaplace_t *) p->clone() : nullptr; }
static enumplace_t *as_enumplace_t(place_t *p) { return p != nullptr ? (enumplace_t *) p->clone() : nullptr; }
static structplace_t *as_structplace_t(place_t *p) { return p != nullptr ? (structplace_t *) p->clone() : nullptr; }
static simpleline_place_t *as_simpleline_place_t(place_t *p) { return p != nullptr ? (simpleline_place_t *) p->clone() : nullptr; }
static tiplace_t *as_tiplace_t(place_t *p) { return p != nullptr ? (tiplace_t *) p->clone() : nullptr; }
PyObject *py_generate(void *ud, int maxsize)
{
@@ -460,6 +469,8 @@ SWIG_DECLARE_PY_CLINKED_OBJECT(textctrl_info_t)
return place_t.as_structplace_t(self.at)
def place_as_simpleline_place_t(self):
return place_t.as_simpleline_place_t(self.at)
def place_as_tiplace_t(self):
return place_t.as_tiplace_t(self.at)
def place(self, view):
ptype = get_viewer_place_type(view)
@@ -471,6 +482,8 @@ SWIG_DECLARE_PY_CLINKED_OBJECT(textctrl_info_t)
return self.place_as_structplace_t()
elif ptype == TCCPT_SIMPLELINE_PLACE:
return self.place_as_simpleline_place_t()
elif ptype == TCCPT_TIPLACE:
return self.place_as_simpleline_place_t()
else:
return self.at
}
+1 -1
View File
@@ -178,7 +178,7 @@
resultobj = qstrvec2pylist(*($1));
}
%numbers_list_to_values_vec(ea64vec_t, SWIGTYPE_p_qvectorT_unsigned_long_long_t, PyW_PyListToEa64Vec);
%numbers_list_to_values_vec(ea64vec_t, SWIGTYPE_p_qvectorT_unsigned_long_long_t, PyW_PySeqToEa64Vec);
%include "lumina.hpp"
+1 -1
View File
@@ -102,7 +102,7 @@ typedef int diff_source_idx_t;
{ // %typemap(directorargout) qstrvec_t *
if ( $result != Py_None )
{
if ( PyW_PyListToStrVec(&tmp, $result) >= 0 )
if ( PyW_PySeqToStrVec(&tmp, $result) >= 0 )
{
$1->insert($1->end(), tmp.begin(), tmp.end());
}
+1
View File
@@ -85,6 +85,7 @@
%ignore qhandle_t;
%ignore qstrlen;
%ignore qstrcmp;
%ignore qstrncmp;
%ignore qstrstr;
%ignore qstrchr;
%ignore qstrrchr;
+2
View File
@@ -3,6 +3,8 @@
%ignore rangeset_t::upper_bound;
%ignore rangeset_t::move_chunk;
%ignore rangeset_t::check_move_args;
%ignore range64_t;
%ignore range64vec_t;
%template(rangevec_base_t) qvector<range_t>;
%template(array_of_rangesets) qvector<rangeset_t>;
+109
View File
@@ -0,0 +1,109 @@
%{
#include <regfinder.hpp>
%}
//-------------------------------------------------------------------------
// ignore not published structs
%ignore reg_finder_op_t;
%ignore reg_finder_t;
//-------------------------------------------------------------------------
%immutable reg_value_def_t::SHORT_INSN;
%immutable reg_value_def_t::PC_BASED;
%immutable reg_value_def_t::LIKE_GOT;
%ignore reg_value_def_t::val_eq;
%ignore reg_value_def_t::val_less;
//-------------------------------------------------------------------------
// dstr() as str()
%ignore reg_value_info_t::dstr;
%extend reg_value_info_t
{
inline qstring __str__() const { return $self->dstr(); }
}
//-------------------------------------------------------------------------
// ignore helpers
%ignore reg_finder_invalidate_cache(reg_finder_t *_this, ea_t ea);
%ignore reg_finder_find(reg_finder_t *_this, reg_value_info_t *out, ea_t ea, ea_t ds, reg_finder_op_t op, int max_depth);
%ignore reg_finder_calc_op_addr(reg_finder_t *_this, reg_value_info_t *addr, const op_t *memop, const insn_t *insn, ea_t ea, ea_t ds);
%ignore reg_finder_emulate_mem_read(reg_finder_t *_this, reg_value_info_t *value, const reg_value_info_t *addr, int width, bool is_signed, const insn_t *insn);
%ignore reg_finder_emulate_binary_op(reg_finder_t *_this, reg_value_info_t *value, int aop, const op_t *op1, const op_t *op2, const insn_t *insn, ea_t ea, ea_t ds, reg_finder_binary_ops_adjust_fun adjust, void *ud);
%ignore reg_finder_emulate_unary_op(reg_finder_t *_this, reg_value_info_t *value, int aop, int reg, const insn_t *insn, ea_t ea, ea_t ds);
%ignore reg_finder_may_modify_stkvars(const reg_finder_t *_this, reg_finder_op_t op, const insn_t *insn);
%ignore reg_finder_ctr(reg_finder_t *_this);
%ignore reg_finder_dtr(reg_finder_t *_this);
%ignore reg_value_def_dstr(const reg_value_def_t *_this, qstring *vout, int how, const procmod_t *pm);
%ignore reg_value_info_dstr(const reg_value_info_t *_this, qstring *vout, const procmod_t *pm);
%ignore reg_value_info_vals_union(reg_value_info_t *_this, const reg_value_info_t *r);
%ignore reg_finder_op_make_rfop(func_t *pfn, const insn_t *insn, const op_t *op);
//-------------------------------------------------------------------------
// add access to reg_value_info_t::vals
%ignore reg_value_info_t::vals_begin;
%ignore reg_value_info_t::vals_end;
%ignore reg_value_info_t::vals_size;
%extend reg_value_info_t
{
inline size_t __len__() const { return $self->vals_size(); }
inline const reg_value_def_t &__getitem__(size_t i) const
{
if ( i >= $self->vals_size() )
throw std::out_of_range("out of bounds access");
return $self->vals_begin()[i];
}
}
//-------------------------------------------------------------------------
// For 'find_reg_value()'
%define %val_t_result_as_output(TYPE, CONVFUNC, NAME)
%typemap(in,numinputs=0) TYPE *NAME (TYPE temp = 0)
{
// %val_t_result_as_output(TYPE, CONVFUNC, NAME) %typemap(in,numinputs=0)
$1 = &temp;
}
%typemap(argout) TYPE *NAME
{
// %val_t_result_as_output(TYPE, CONVFUNC, NAME) %typemap(argout)
Py_XDECREF(resultobj);
if ( result == 1 )
{
resultobj = CONVFUNC(*(TYPE *) $1);
}
else if ( result == 0 )
{
Py_INCREF(Py_None);
resultobj = Py_None;
}
else
{
SWIG_exception_fail(SWIG_RuntimeError, "The processor module does not support a register tracker");
}
}
%enddef
%val_t_result_as_output(uint32, PyLong_FromUnsignedLong, uval);
%val_t_result_as_output(uint64, PyLong_FromUnsignedLongLong, uval);
%val_t_result_as_output(int32, PyLong_FromLong, sval);
%val_t_result_as_output(int64, PyLong_FromLongLong, sval);
//-------------------------------------------------------------------------
// For 'find_nearest_rvi()'
%typemap(in) int reg[2] (int temp[2])
{
// %typemap(in) int reg[2] (int temp[2])
if ( !PyTuple_Check($input)
|| PyTuple_Size($input) != 2
|| !PyLong_Check(PyTuple_GetItem($input, 0))
|| !PyLong_Check(PyTuple_GetItem($input, 1)) )
{
SWIG_exception_fail(
SWIG_TypeError,
"in method '" "$symname" "', argument " "$argnum"" of type (long, long)");
}
temp[0] = PyLong_AsLong(PyTuple_GetItem($input, 0));
temp[1] = PyLong_AsLong(PyTuple_GetItem($input, 1));
$1 = temp;
}
%include "regfinder.hpp"
+40 -8
View File
@@ -3,6 +3,8 @@
#include <struct.hpp>
%}
%constant bmask64_t DEFMASK64 = bmask64_t(-1);
// Most of these could be wrapped if needed
%ignore get_cc;
%ignore get_effective_cc;
@@ -48,6 +50,8 @@
%ignore get_numbered_type(const til_t *, uint32, const type_t **, const p_list **, const char **, const p_list **, sclass_t *);
%rename (get_numbered_type) py_get_numbered_type;
%ignore NTF_NOSYNC;
%ignore skipName;
%ignore extract_comment;
%ignore skipComment;
@@ -112,7 +116,6 @@
%ignore is_stkarg_load_t;
%ignore has_delay_slot_t;
%ignore gen_use_arg_types;
%ignore enable_numbered_types;
%ignore compact_numbered_types;
%ignore callregs_t::findreg;
@@ -129,15 +132,34 @@
%ignore bitfield_type_data_t::serialize;
%ignore func_type_data_t::serialize;
%ignore func_type_data_t::deserialize;
%ignore tinfo_t::serialize(qtype *, qtype *, qtype *, int) const;
%ignore name_requires_qualifier;
%ignore tinfo_visitor_t::level;
%ignore tinfo_t::deserialize(const til_t *, const qtype *, const qtype *, const qtype *);
%ignore tinfo_t::serialize(qtype *, qtype *, qtype *, int) const;
%ignore tinfo_t::deserialize(const til_t *, const qtype *, const qtype *, const qtype *, const char *);
%ignore tinfo_get_innermost_udm;
%ignore save_tinfo2;
// Let's declare our own version of `deserialize_tinfo2` before
// SWiG hits the one that's in `typeinf.hpp` (and cannot, alas,
// enjoy the addition of the default value.)
%rename (deserialize_tinfo) deserialize_tinfo2;
%inline %{
idaman bool ida_export deserialize_tinfo2(tinfo_t *tif, const til_t *til, const type_t **ptype, const p_list **pfields, const p_list **pfldcmts, const char *cmt=nullptr);
%}
%ignore deserialize_tinfo;
%ignore deserialize_tinfo2;
%ignore get_udm_by_tid(tinfo_t *tif, udm_t *udm, tid_t tid);
%ignore get_edm_by_tid(tinfo_t *tif, edm_t *edm, tid_t tid);
%ignore get_type_by_tid(tinfo_t *tif, tid_t tid);
%ignore get_tinfo_by_edm_name(tinfo_t *tif, til_t *til, const char *mname);
%ignore value_repr_t__parse_value_repr;
%ignore enum_type_data_t__set_value_repr;
%ignore custloc_desc_t;
%ignore install_custom_argloc;
%ignore remove_custom_argloc;
%ignore retrieve_custom_argloc;
%ignore enum_type_visitor_t;
%ignore visit_edms;
%make_argout_errbuf_raise_when_null_result();
@@ -192,6 +214,9 @@
}
}
%apply size_t *OUTPUT {size_t *out_index};
%apply uint64 *OUTPUT {uint64 *out_bitoffset};
//---------------------------------------------------------------------
%define %tinfo_t_or_simple_tinfo_t_container_lifecycle(Type)
// Instead of re-defining all constructors, add the registering
@@ -219,23 +244,30 @@
// as it would call til_register_python_tinfo_t_instance() a second time
// after '%typemap(out) tinfo_t *' already did it.
%extend tinfo_t {
~tinfo_t(void)
~tinfo_t()
{
til_deregister_python_tinfo_t_instance($self);
delete $self;
}
}
%ignore tinfo_t::~tinfo_t(void);
%ignore tinfo_t::~tinfo_t();
%template(funcargvec_t) qvector<funcarg_t>;
%template(reginfovec_t) qvector<reg_info_t>;
%template(enum_member_vec_t) qvector<enum_member_t>;
%template(edmvec_t) qvector<edm_t>;
%template(argpartvec_t) qvector<argpart_t>;
%uncomparable_elements_qvector(valstr_t, valstrvec_t);
%uncomparable_elements_qvector(regobj_t, regobjvec_t);
%uncomparable_elements_qvector(type_attr_t, type_attrs_t);
%template(udtmembervec_template_t) qvector<udt_member_t>;
%extend value_repr_t
{
inline qstring __str__() const { qstring tmp; $self->print(&tmp); return tmp; }
}
%template(udtmembervec_template_t) qvector<udm_t>;
%ignore udt_type_data_t::VERSION;
%ignore udt_type_data_old_t;
%extend tinfo_t {
PyObject *get_attr(const qstring &key, bool all_attrs=true)
@@ -264,7 +296,7 @@
%typemap(in) const sclass_t * {
// %typemap(in) const sclass_t *
if ( $input == Py_None )
$1 = new sclass_t(sc_unk);
$1 = new sclass_t(SC_UNK);
else if ( PyLong_Check($input) )
$1 = new sclass_t(sclass_t(PyLong_AsLong($input)));
else
+188
View File
@@ -0,0 +1,188 @@
#include <pro.h>
#include <expr.hpp>
#include "extapi.hpp"
#include "extapi.cpp"
#include "pywraps.hpp"
#include "pywraps.cpp"
//-------------------------------------------------------------------------
idapython_plugin_t *ida_export get_plugin_instance() { return nullptr; }
void ida_export set_interruptible_state(bool) {}
ssize_t ida_export invoke_callbacks(hook_type_t, int, va_list) { return 0; }
bool ida_export hook_to_notification_point(hook_type_t, hook_cb_t *, void *) { return false; }
int ida_export unhook_from_notification_point(hook_type_t, hook_cb_t *, void *) { return false; }
void ida_export cleanup_argloc(argloc_t *) { INTERR(30755); }
void ida_export clear_tinfo_t(tinfo_t *) { INTERR(30756); }
fpvalue_error_t ida_export ieee_realcvt(void *, fpvalue_t *, uint16) { return REAL_ERROR_FORMAT; }
//-------------------------------------------------------------------------
static qvector<void*> prevent_warnings()
{
qvector<void *> buf;
buf.push_back((void *) &clear_python_timer_instances);
buf.push_back((void *) &til_clear_python_tinfo_t_instances);
buf.push_back((void *) &deinit_pywraps);
buf.push_back((void *) &init_pywraps);
buf.push_back((void *) &pywraps_check_autoscripts);
buf.push_back((void *) &free_compiled_form_instances);
return buf;
}
//-------------------------------------------------------------------------
idcfuncs_t idc_func_table = { 0 };
//-------------------------------------------------------------------------
static const char *inifile = "test_pywraps.ini";
static size_t lnnum = 0;
//------------------------------------------------------------------------
AS_PRINTF(1, 2) NORETURN static void fatal(const char *format, ...)
{
if ( lnnum != 0 )
qeprintf("%s:%" FMT_Z ": ", inifile, lnnum);
va_list va;
va_start(va, format);
qstring buf;
buf.vsprnt(format, va);
qeprintf("%s\n", buf.c_str());
va_end(va);
qexit(EXIT_FAILURE);
}
//-------------------------------------------------------------------------
static bool read_test_case(qstring *out, FILE *fp)
{
out->qclear();
char buf[MAXSTR];
bool printed_header = false;
while ( qfgets(buf, sizeof(buf), fp) )
{
++lnnum;
// msg("%s", buf);
if ( buf[0] == '\0' )
continue;
buf[strlen(buf)-1] = '\0';
char *ptr = skip_spaces(buf);
if ( *ptr == '\0' || *ptr == ';' )
continue;
if ( !printed_header )
{
msg("--- TEST: %s\n", buf);
printed_header = true;
}
*out = buf;
return true;
}
return false;
}
//-------------------------------------------------------------------------
static void run_test_case(
qstrvec_t *out,
const qstring &expr,
PyObject *globals)
{
qstrvec_t argv;
expr.split(&argv, " ");
QASSERT(30757, argv.size() == 2);
newref_t py_arg1(extapi.PyRun_StringFlags_ptr(
argv[1].c_str(),
Py_eval_input,
globals,
globals,
nullptr));
QASSERT(30758, py_arg1 != nullptr);
if ( argv[0] == "READ_NUM" )
{
{
qstring &buf = out->push_back();
buf = "PyW_GetNumber : ";
uint64 num = 0;
bool is_64 = false;
if ( PyW_GetNumber(py_arg1.o, &num, &is_64) )
{
buf.cat_sprnt("is_64: %s, unsigned: %llu; signed: %lld; hex: 0x%llx",
is_64 ? "true" : "false", uint64(num), int64(num), uint64(num));
}
else
{
buf.append("Could not convert to a number");
}
}
{
qstring &buf = out->push_back();
buf = "PyW_GetNumberAsIDC: ";
idc_value_t idcv;
if ( PyW_GetNumberAsIDC(py_arg1.o, &idcv) )
{
switch ( idcv.vtype )
{
case VT_LONG:
#ifdef __EA64__
buf.cat_sprnt("(64-bit sval_t) unsigned: %llu; signed: %lld; hex: 0x%llx",
uval_t(idcv.num), idcv.num, uval_t(idcv.num));
#else
buf.cat_sprnt("(32-bit sval_t) unsigned: %u; signed: %d; hex: 0x%x",
uval_t(idcv.num), idcv.num, idcv.num);
#endif
break;
case VT_INT64:
buf.cat_sprnt("(int64) unsigned: %llu; signed: %lld; hex: 0x%llx",
uint64(idcv.i64), idcv.i64, uint64(idcv.i64));
break;
default:
INTERR(30759);
}
}
else
{
buf.append("Could not convert to an IDC value");
}
}
}
else
{
INTERR(30760);
}
}
//-------------------------------------------------------------------------
int main(int argc, char *argv[])
{
if ( argc > 1 )
inifile = argv[1];
prevent_warnings();
FILE *fp = qfopen(inifile, "rt");
if ( fp == nullptr )
fatal("%s: %s", inifile, qerrstr(-1));
Py_InitializeEx(0 /* Don't catch SIGPIPE, SIGXFZ, SIGXFSZ & SIGINT signals */);
qstring errbuf;
QASSERT(30761, extapi.load(&errbuf));
PyObject *module = PyImport_AddModule("__main__");
PyObject *globals = PyModule_GetDict(module);
qstring req;
while ( read_test_case(&req, fp) )
{
qstrvec_t resp;
run_test_case(&resp, req, globals);
for ( const auto &r : resp )
msg(" => %s\n", r.c_str());
}
Py_Finalize();
qfclose(fp);
return EXIT_SUCCESS;
}
+34
View File
@@ -0,0 +1,34 @@
READ_NUM 12
READ_NUM 0xFFFF
READ_NUM 0xFFFFFFFF
READ_NUM 0x00000FFFFFFF
READ_NUM 0x0000FFFFFFFF
READ_NUM 0x0000FFFFFFFFFFFF
READ_NUM 0x0000FFFFFFFFFFFF1234
READ_NUM 0x00000000FFFFFFFF
READ_NUM 0x00000000FFFFFFFF1234
READ_NUM 0xFFFFFFFFFFFF0000
READ_NUM 0x1234FFFFFFFFFFFF0000
READ_NUM 0xFFFFFFFF00000000
READ_NUM 0x1234FFFFFFFF00000000
READ_NUM 0xFFFFFFFF0000
READ_NUM 0x1234FFFFFFFF0000
READ_NUM 0xFFFFFFFF00001234
READ_NUM -0xFFFF
READ_NUM -0xFFFFFFFF
READ_NUM -0x00000FFFFFFF
READ_NUM -0x0000FFFFFFFF
READ_NUM -0x0000FFFFFFFFFFFF
READ_NUM -0x0000FFFFFFFFFFFF1234
READ_NUM -0x00000000FFFFFFFF
READ_NUM -0x00000000FFFFFFFF1234
READ_NUM -0xFFFFFFFFFFFF0000
READ_NUM -0x1234FFFFFFFFFFFF0000
READ_NUM -0xFFFFFFFF00000000
READ_NUM -0x1234FFFFFFFF00000000
READ_NUM -0x1234FFFFFFFF0000
READ_NUM -0xFFFFFFFF0000
READ_NUM -0xFFFFFFFF00001234
READ_NUM "Hello"
READ_NUM "None"
READ_NUM True
+102
View File
@@ -0,0 +1,102 @@
--- TEST: READ_NUM 12
=> PyW_GetNumber : is_64: false, unsigned: 12; signed: 12; hex: 0xc
=> PyW_GetNumberAsIDC: (32-bit sval_t) unsigned: 12; signed: 12; hex: 0xc
--- TEST: READ_NUM 0xFFFF
=> PyW_GetNumber : is_64: false, unsigned: 65535; signed: 65535; hex: 0xffff
=> PyW_GetNumberAsIDC: (32-bit sval_t) unsigned: 65535; signed: 65535; hex: 0xffff
--- TEST: READ_NUM 0xFFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 4294967295; signed: 4294967295; hex: 0xffffffff
=> PyW_GetNumberAsIDC: (int64) unsigned: 4294967295; signed: 4294967295; hex: 0xffffffff
--- TEST: READ_NUM 0x00000FFFFFFF
=> PyW_GetNumber : is_64: false, unsigned: 268435455; signed: 268435455; hex: 0xfffffff
=> PyW_GetNumberAsIDC: (32-bit sval_t) unsigned: 268435455; signed: 268435455; hex: 0xfffffff
--- TEST: READ_NUM 0x0000FFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 4294967295; signed: 4294967295; hex: 0xffffffff
=> PyW_GetNumberAsIDC: (int64) unsigned: 4294967295; signed: 4294967295; hex: 0xffffffff
--- TEST: READ_NUM 0x0000FFFFFFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 281474976710655; signed: 281474976710655; hex: 0xffffffffffff
=> PyW_GetNumberAsIDC: (int64) unsigned: 281474976710655; signed: 281474976710655; hex: 0xffffffffffff
--- TEST: READ_NUM 0x0000FFFFFFFFFFFF1234
=> PyW_GetNumber : is_64: true, unsigned: 18446744073709490740; signed: -60876; hex: 0xffffffffffff1234
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446744073709490740; signed: -60876; hex: 0xffffffffffff1234
--- TEST: READ_NUM 0x00000000FFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 4294967295; signed: 4294967295; hex: 0xffffffff
=> PyW_GetNumberAsIDC: (int64) unsigned: 4294967295; signed: 4294967295; hex: 0xffffffff
--- TEST: READ_NUM 0x00000000FFFFFFFF1234
=> PyW_GetNumber : is_64: true, unsigned: 281474976649780; signed: 281474976649780; hex: 0xffffffff1234
=> PyW_GetNumberAsIDC: (int64) unsigned: 281474976649780; signed: 281474976649780; hex: 0xffffffff1234
--- TEST: READ_NUM 0xFFFFFFFFFFFF0000
=> PyW_GetNumber : is_64: true, unsigned: 18446744073709486080; signed: -65536; hex: 0xffffffffffff0000
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446744073709486080; signed: -65536; hex: 0xffffffffffff0000
--- TEST: READ_NUM 0x1234FFFFFFFFFFFF0000
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM 0xFFFFFFFF00000000
=> PyW_GetNumber : is_64: true, unsigned: 18446744069414584320; signed: -4294967296; hex: 0xffffffff00000000
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446744069414584320; signed: -4294967296; hex: 0xffffffff00000000
--- TEST: READ_NUM 0x1234FFFFFFFF00000000
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM 0xFFFFFFFF0000
=> PyW_GetNumber : is_64: true, unsigned: 281474976645120; signed: 281474976645120; hex: 0xffffffff0000
=> PyW_GetNumberAsIDC: (int64) unsigned: 281474976645120; signed: 281474976645120; hex: 0xffffffff0000
--- TEST: READ_NUM 0x1234FFFFFFFF0000
=> PyW_GetNumber : is_64: true, unsigned: 1311954866448302080; signed: 1311954866448302080; hex: 0x1234ffffffff0000
=> PyW_GetNumberAsIDC: (int64) unsigned: 1311954866448302080; signed: 1311954866448302080; hex: 0x1234ffffffff0000
--- TEST: READ_NUM 0xFFFFFFFF00001234
=> PyW_GetNumber : is_64: true, unsigned: 18446744069414588980; signed: -4294962636; hex: 0xffffffff00001234
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446744069414588980; signed: -4294962636; hex: 0xffffffff00001234
--- TEST: READ_NUM -0xFFFF
=> PyW_GetNumber : is_64: false, unsigned: 18446744073709486081; signed: -65535; hex: 0xffffffffffff0001
=> PyW_GetNumberAsIDC: (32-bit sval_t) unsigned: 4294901761; signed: -65535; hex: 0xffff0001
--- TEST: READ_NUM -0xFFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 18446744069414584321; signed: -4294967295; hex: 0xffffffff00000001
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446744069414584321; signed: -4294967295; hex: 0xffffffff00000001
--- TEST: READ_NUM -0x00000FFFFFFF
=> PyW_GetNumber : is_64: false, unsigned: 18446744073441116161; signed: -268435455; hex: 0xfffffffff0000001
=> PyW_GetNumberAsIDC: (32-bit sval_t) unsigned: 4026531841; signed: -268435455; hex: 0xf0000001
--- TEST: READ_NUM -0x0000FFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 18446744069414584321; signed: -4294967295; hex: 0xffffffff00000001
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446744069414584321; signed: -4294967295; hex: 0xffffffff00000001
--- TEST: READ_NUM -0x0000FFFFFFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 18446462598732840961; signed: -281474976710655; hex: 0xffff000000000001
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446462598732840961; signed: -281474976710655; hex: 0xffff000000000001
--- TEST: READ_NUM -0x0000FFFFFFFFFFFF1234
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM -0x00000000FFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 18446744069414584321; signed: -4294967295; hex: 0xffffffff00000001
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446744069414584321; signed: -4294967295; hex: 0xffffffff00000001
--- TEST: READ_NUM -0x00000000FFFFFFFF1234
=> PyW_GetNumber : is_64: true, unsigned: 18446462598732901836; signed: -281474976649780; hex: 0xffff00000000edcc
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446462598732901836; signed: -281474976649780; hex: 0xffff00000000edcc
--- TEST: READ_NUM -0xFFFFFFFFFFFF0000
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM -0x1234FFFFFFFFFFFF0000
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM -0xFFFFFFFF00000000
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM -0x1234FFFFFFFF00000000
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM -0x1234FFFFFFFF0000
=> PyW_GetNumber : is_64: true, unsigned: 17134789207261249536; signed: -1311954866448302080; hex: 0xedcb000000010000
=> PyW_GetNumberAsIDC: (int64) unsigned: 17134789207261249536; signed: -1311954866448302080; hex: 0xedcb000000010000
--- TEST: READ_NUM -0xFFFFFFFF0000
=> PyW_GetNumber : is_64: true, unsigned: 18446462598732906496; signed: -281474976645120; hex: 0xffff000000010000
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446462598732906496; signed: -281474976645120; hex: 0xffff000000010000
--- TEST: READ_NUM -0xFFFFFFFF00001234
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM "Hello"
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM "None"
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM True
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
+102
View File
@@ -0,0 +1,102 @@
--- TEST: READ_NUM 12
=> PyW_GetNumber : is_64: false, unsigned: 12; signed: 12; hex: 0xc
=> PyW_GetNumberAsIDC: (64-bit sval_t) unsigned: 12; signed: 12; hex: 0xc
--- TEST: READ_NUM 0xFFFF
=> PyW_GetNumber : is_64: false, unsigned: 65535; signed: 65535; hex: 0xffff
=> PyW_GetNumberAsIDC: (64-bit sval_t) unsigned: 65535; signed: 65535; hex: 0xffff
--- TEST: READ_NUM 0xFFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 4294967295; signed: 4294967295; hex: 0xffffffff
=> PyW_GetNumberAsIDC: (int64) unsigned: 4294967295; signed: 4294967295; hex: 0xffffffff
--- TEST: READ_NUM 0x00000FFFFFFF
=> PyW_GetNumber : is_64: false, unsigned: 268435455; signed: 268435455; hex: 0xfffffff
=> PyW_GetNumberAsIDC: (64-bit sval_t) unsigned: 268435455; signed: 268435455; hex: 0xfffffff
--- TEST: READ_NUM 0x0000FFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 4294967295; signed: 4294967295; hex: 0xffffffff
=> PyW_GetNumberAsIDC: (int64) unsigned: 4294967295; signed: 4294967295; hex: 0xffffffff
--- TEST: READ_NUM 0x0000FFFFFFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 281474976710655; signed: 281474976710655; hex: 0xffffffffffff
=> PyW_GetNumberAsIDC: (int64) unsigned: 281474976710655; signed: 281474976710655; hex: 0xffffffffffff
--- TEST: READ_NUM 0x0000FFFFFFFFFFFF1234
=> PyW_GetNumber : is_64: true, unsigned: 18446744073709490740; signed: -60876; hex: 0xffffffffffff1234
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446744073709490740; signed: -60876; hex: 0xffffffffffff1234
--- TEST: READ_NUM 0x00000000FFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 4294967295; signed: 4294967295; hex: 0xffffffff
=> PyW_GetNumberAsIDC: (int64) unsigned: 4294967295; signed: 4294967295; hex: 0xffffffff
--- TEST: READ_NUM 0x00000000FFFFFFFF1234
=> PyW_GetNumber : is_64: true, unsigned: 281474976649780; signed: 281474976649780; hex: 0xffffffff1234
=> PyW_GetNumberAsIDC: (int64) unsigned: 281474976649780; signed: 281474976649780; hex: 0xffffffff1234
--- TEST: READ_NUM 0xFFFFFFFFFFFF0000
=> PyW_GetNumber : is_64: true, unsigned: 18446744073709486080; signed: -65536; hex: 0xffffffffffff0000
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446744073709486080; signed: -65536; hex: 0xffffffffffff0000
--- TEST: READ_NUM 0x1234FFFFFFFFFFFF0000
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM 0xFFFFFFFF00000000
=> PyW_GetNumber : is_64: true, unsigned: 18446744069414584320; signed: -4294967296; hex: 0xffffffff00000000
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446744069414584320; signed: -4294967296; hex: 0xffffffff00000000
--- TEST: READ_NUM 0x1234FFFFFFFF00000000
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM 0xFFFFFFFF0000
=> PyW_GetNumber : is_64: true, unsigned: 281474976645120; signed: 281474976645120; hex: 0xffffffff0000
=> PyW_GetNumberAsIDC: (int64) unsigned: 281474976645120; signed: 281474976645120; hex: 0xffffffff0000
--- TEST: READ_NUM 0x1234FFFFFFFF0000
=> PyW_GetNumber : is_64: true, unsigned: 1311954866448302080; signed: 1311954866448302080; hex: 0x1234ffffffff0000
=> PyW_GetNumberAsIDC: (int64) unsigned: 1311954866448302080; signed: 1311954866448302080; hex: 0x1234ffffffff0000
--- TEST: READ_NUM 0xFFFFFFFF00001234
=> PyW_GetNumber : is_64: true, unsigned: 18446744069414588980; signed: -4294962636; hex: 0xffffffff00001234
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446744069414588980; signed: -4294962636; hex: 0xffffffff00001234
--- TEST: READ_NUM -0xFFFF
=> PyW_GetNumber : is_64: false, unsigned: 18446744073709486081; signed: -65535; hex: 0xffffffffffff0001
=> PyW_GetNumberAsIDC: (64-bit sval_t) unsigned: 18446744073709486081; signed: -65535; hex: 0xffffffffffff0001
--- TEST: READ_NUM -0xFFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 18446744069414584321; signed: -4294967295; hex: 0xffffffff00000001
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446744069414584321; signed: -4294967295; hex: 0xffffffff00000001
--- TEST: READ_NUM -0x00000FFFFFFF
=> PyW_GetNumber : is_64: false, unsigned: 18446744073441116161; signed: -268435455; hex: 0xfffffffff0000001
=> PyW_GetNumberAsIDC: (64-bit sval_t) unsigned: 18446744073441116161; signed: -268435455; hex: 0xfffffffff0000001
--- TEST: READ_NUM -0x0000FFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 18446744069414584321; signed: -4294967295; hex: 0xffffffff00000001
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446744069414584321; signed: -4294967295; hex: 0xffffffff00000001
--- TEST: READ_NUM -0x0000FFFFFFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 18446462598732840961; signed: -281474976710655; hex: 0xffff000000000001
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446462598732840961; signed: -281474976710655; hex: 0xffff000000000001
--- TEST: READ_NUM -0x0000FFFFFFFFFFFF1234
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM -0x00000000FFFFFFFF
=> PyW_GetNumber : is_64: true, unsigned: 18446744069414584321; signed: -4294967295; hex: 0xffffffff00000001
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446744069414584321; signed: -4294967295; hex: 0xffffffff00000001
--- TEST: READ_NUM -0x00000000FFFFFFFF1234
=> PyW_GetNumber : is_64: true, unsigned: 18446462598732901836; signed: -281474976649780; hex: 0xffff00000000edcc
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446462598732901836; signed: -281474976649780; hex: 0xffff00000000edcc
--- TEST: READ_NUM -0xFFFFFFFFFFFF0000
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM -0x1234FFFFFFFFFFFF0000
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM -0xFFFFFFFF00000000
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM -0x1234FFFFFFFF00000000
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM -0x1234FFFFFFFF0000
=> PyW_GetNumber : is_64: true, unsigned: 17134789207261249536; signed: -1311954866448302080; hex: 0xedcb000000010000
=> PyW_GetNumberAsIDC: (int64) unsigned: 17134789207261249536; signed: -1311954866448302080; hex: 0xedcb000000010000
--- TEST: READ_NUM -0xFFFFFFFF0000
=> PyW_GetNumber : is_64: true, unsigned: 18446462598732906496; signed: -281474976645120; hex: 0xffff000000010000
=> PyW_GetNumberAsIDC: (int64) unsigned: 18446462598732906496; signed: -281474976645120; hex: 0xffff000000010000
--- TEST: READ_NUM -0xFFFFFFFF00001234
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM "Hello"
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM "None"
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
--- TEST: READ_NUM True
=> PyW_GetNumber : Could not convert to a number
=> PyW_GetNumberAsIDC: Could not convert to an IDC value
+1 -1
View File
@@ -67,7 +67,7 @@ else:
# creates a regular expression
def make_re(tag, module, prefix):
s = '%(p)s<%(tag)s\(%(m)s\)>(.+?)%(p)s</%(tag)s\(%(m)s\)>' % {'m': module, 'tag': tag, 'p': prefix}
s = r'%(p)s<%(tag)s\(%(m)s\)>(.+?)%(p)s</%(tag)s\(%(m)s\)>' % {'m': module, 'tag': tag, 'p': prefix}
return (s, re.compile(s, re.DOTALL))
+91 -61
View File
@@ -39,6 +39,7 @@ extern plugin_t PLUGIN;
%feature("nodirector") generic_linput_t;
%feature("nodirector") place_t;
%feature("nodirector") idaplace_t;
%feature("nodirector") tiplace_t;
%feature("nodirector") qrefcnt_obj_t;
%feature("nodirector") qstring_printer_t;
%feature("nodirector") simpleline_place_t;
@@ -438,61 +439,44 @@ static PyObject *type##_get_clink_ptr(PyObject *self)
%enddef
//---------------------------------------------------------------------
// Convert an incoming Python list to a tid_t[] array
%typemap(in) tid_t[ANY](tid_t temp[$1_dim0]) {
int i, len;
%typemap(in) tid_t[ANY] (qvector<tid_t> temp)
{
// %typemap(in) tid_t[ANY] (qvector<tid_t> temp)
Py_ssize_t len = PyW_PySeqToTidVec(&temp, $input, $1_dim0);
if ( len == CIP_FAILED )
return nullptr;
if (!PySequence_Check($input))
{
PyErr_SetString(PyExc_TypeError,"Expecting a sequence");
return nullptr;
}
/* Cap the number of elements to copy */
len = PySequence_Length($input) < $1_dim0 ? PySequence_Length($input) : $1_dim0;
for (i =0; i < len; i++)
{
newref_t item(PySequence_GetItem($input,i));
if (!PyLong_Check(item.o))
{
PyErr_SetString(PyExc_ValueError,"Expecting a sequence of long integers");
return nullptr;
}
temp[i] = PyLong_AsUnsignedLong(item.o);
}
$1 = &temp[0];
temp.resize($1_dim0, 0); // make sure we have enough memory allocated
$1 = temp.begin();
}
//-------------------------------------------------------------------------
// Same, but with non-fixed sized arrays.
%typemap(in) (const tid_t *path, int plen) (qvector<tid_t> temp) {
if (!PySequence_Check($input))
{
PyErr_SetString(PyExc_TypeError,"Expecting a sequence");
return nullptr;
}
int plen = PySequence_Length($input);
if ( plen <= 0 )
{
PyErr_SetString(PyExc_TypeError, "Sequence must have at least 1 item");
return nullptr;
}
temp.resize(plen);
for ( int i =0; i < plen; ++i )
{
newref_t item(PySequence_GetItem($input,i));
if (!PyLong_Check(item.o))
{
PyErr_SetString(PyExc_ValueError,"Expecting a sequence of long integers");
return nullptr;
}
%typemap(in) (const tid_t *path, int plen) (qvector<tid_t> temp)
{
// %typemap(in) (const tid_t *path, int plen/path_len) (qvector<tid_t> temp),
Py_ssize_t len = PyW_PySeqToTidVec(&temp, $input);
if ( len == CIP_FAILED )
return nullptr;
temp[i] = PyLong_AsUnsignedLong(item.o);
}
$1 = temp.begin();
$2 = int(temp.size());
$1 = temp.begin();
$2 = int(temp.size());
}
//-------------------------------------------------------------------------
%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) const qvector<tid_t> &path
{
// %typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) const qvector<tid_t> &path
$1 = PyW_IsSequenceType($input);
}
%typemap(in) (const qvector<tid_t> &path) (qvector<tid_t> temp)
{
// %typemap(in) (const qvector<tid_t> &path)
Py_ssize_t len = PyW_PySeqToTidVec(&temp, $input);
if ( len == CIP_FAILED )
return nullptr;
$1 = &temp;
}
%{
@@ -1031,7 +1015,7 @@ SWIGINTERN PyObject *_maybe_byte_array_or_none_result(
//-------------------------------------------------------------------------
%fragment("cvt_const_insn_t_ref", "header")
{
bool convert_const_insn_t_ref(insn_t *out, PyObject *in)
bool convert_const_insn_t_ref(insn_t *out, PyObject *in, swig_type_info *ty)
{
uint64 ea;
bool ok = PyW_GetNumber(in, &ea);
@@ -1039,14 +1023,14 @@ SWIGINTERN PyObject *_maybe_byte_array_or_none_result(
{
insn_t tmp;
ok = decode_insn(&tmp, ea_t(ea)) > 0;
if ( ok )
if ( ok && out != nullptr )
*out = tmp;
}
else
{
insn_t *p_insn = nullptr;
ok = SWIG_ConvertPtr(in, (void **) &p_insn, SWIGTYPE_p_insn_t, 0) >= 0 && p_insn != nullptr;
if ( ok )
ok = SWIG_ConvertPtr(in, (void **) &p_insn, ty, 0) >= 0 && p_insn != nullptr;
if ( ok && out != nullptr )
*out = *p_insn;
}
return ok;
@@ -1057,10 +1041,14 @@ SWIGINTERN PyObject *_maybe_byte_array_or_none_result(
%typemap(in, fragment="cvt_const_insn_t_ref") (const insn_t &) (insn_t lins)
{
// %typemap(in) (const insn_t &)
if ( !convert_const_insn_t_ref(&lins, $input) )
if ( !convert_const_insn_t_ref(&lins, $input, $1_descriptor) )
SWIG_exception_fail(SWIG_ValueError, "Expected either an address, or a non-null ida_ua.insn_t instance");
$1 = &lins;
}
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, fragment="cvt_const_insn_t_ref") const insn_t &
{ // %typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) const insn_t &
$1 = convert_const_insn_t_ref(nullptr, $input, $1_descriptor);
}
%typemap(doc) (const insn_t &) "$1_name: an ida_ua.insn_t, or an address (C++: const insn_t &)"
//---------------------------------------------------------------------
@@ -1132,6 +1120,7 @@ typedef int ui_notification_t;
%apply long long { qoff64_t };
%apply qstring *result { qstring *out };
%apply qstring *result { qstring *out_name };
%apply qstring *result { qstring *buf };
%apply qstring *result { qstring *errbuf };
%apply int *OUTPUT { int *icon };
@@ -1262,15 +1251,13 @@ struct dynamic_wrapped_array_t {
//-------------------------------------------------------------------------
#if SWIG_VERSION == 0x40000 || SWIG_VERSION == 0x40001
%typemap(out) tinfo_t {}
%typemap(ret) tinfo_t
%typemap(out) tinfo_t
{
// %typemap(ret) tinfo_t
// %typemap(out) tinfo_t
tinfo_t *ni = new tinfo_t($1);
til_register_python_tinfo_t_instance(ni);
$result = SWIG_NewPointerObj(ni, $&1_descriptor, SWIG_POINTER_OWN | 0);
}
%typemap(check) tinfo_t *
{
// %typemap(check) tinfo_t *
@@ -1290,6 +1277,25 @@ struct dynamic_wrapped_array_t {
// %typemap(newfree) tinfo_t *
delete $1;
}
// Specialization for member `tinfo_t`'s, which we want to return as-is
%typemap(out) tinfo_t *type,
tinfo_t *tif,
tinfo_t *obj_type,
tinfo_t *closure,
tinfo_t *parent,
tinfo_t *elem_type,
tinfo_t *rettype,
tinfo_t *return_type,
tinfo_t *idb_type,
tinfo_t *formal_type,
tinfo_t *functype,
tinfo_t *idb_type
{
// %typemap(out) tinfo_t *type (specialization for member tinfo_t)
$result = SWIG_NewPointerObj($1, $1_descriptor, 0);
}
#else
#error Ensure tinfo_t wrapping is compatible with this version of SWIG
#endif
@@ -1581,9 +1587,9 @@ SWIGINTERN PyObject *qstrvec2pylist(const qstrvec_t &vec, int flags=0)
%numbers_list_to_values_vec_helper(VECTYPE, SWIGTYPE, PYLIST_CONVERTOR, &);
%enddef
#ifdef __EA64__
%numbers_list_to_values_vec(eavec_t, SWIGTYPE_p_qvectorT_unsigned_long_long_t, PyW_PyListToEaVec);
%numbers_list_to_values_vec(eavec_t, SWIGTYPE_p_qvectorT_unsigned_long_long_t, PyW_PySeqToEaVec);
#else
%numbers_list_to_values_vec(eavec_t, SWIGTYPE_p_qvectorT_unsigned_int_t, PyW_PyListToEaVec);
%numbers_list_to_values_vec(eavec_t, SWIGTYPE_p_qvectorT_unsigned_int_t, PyW_PySeqToEaVec);
#endif
//-------------------------------------------------------------------------
@@ -1799,6 +1805,30 @@ ${NONNULL_TYPEMAPS}
$2 = $input;
}
%typemap(in) (printer_t *printer)
{
// %typemap(in) (printer_t *printer)
if ( $input == Py_None )
{
$1 = nullptr;
}
else if ( PyBool_Check($input) )
{
$1 = $input == Py_True ? msg : nullptr;
}
else
{
int res = SWIG_ConvertFunctionPtr($input, (void**)(&$1), SWIGTYPE_p_f_p_q_const__char_v_______int);
if ( !SWIG_IsOK(res) )
{
SWIG_exception_fail(SWIG_ArgError(res), "in method '" "parse_decls" "', argument " "3"" of type '" "printer_t *""'");
SWIG_exception_fail(
SWIG_TypeError,
"in method '" "$symname" "', argument " "$argnum"" of type 'printer_t *'");
}
}
}
%define %define_regval_python_accessors()
%{
//-------------------------------------------------------------------------
-544
View File
@@ -1,544 +0,0 @@
import __future__
import re
import sys
import inspect
import types
import ast
import os
import argparse
sys.stdout.write("### dumpdoc here!\n")
for key in os.environ:
sys.stdout.write("### %s = \"%s\"\n" % (key, os.environ[key]))
if sys.version_info[0] == 3:
# for Python3, we always use the same pydoc module from Python3.5. this keeps the output consistent across different Python3 versions.
import imp
inspect = imp.load_source('inspect', os.path.join("tools", "inspect.py"))
pydoc = imp.load_source('pydoc', os.path.join("tools", "pydoc.py"))
import inspect
import pydoc
import idc
output, wrappers_dir, is_64 = idc.ARGV[1], idc.ARGV[2], idc.ARGV[3] == "True"
sys.stdout.write("### Parameter \"output\" = \"%s\"\n" % output)
sys.stdout.write("### Parameter \"wrappers_dir\" = \"%s\"\n" % wrappers_dir)
sys.stdout.write("### Parameter \"is_64\" = \"%s\"\n" % is_64)
try:
from cStringIO import StringIO
except:
from io import StringIO
import ida_hexrays
def dummy_replacement():
pass
ida_hexrays.DecompilationFailure.add_note = dummy_replacement
idc.DeprecatedIDCError.add_note = dummy_replacement
ignore_types = (int, float, str, bool, dict, list, tuple, bytes, types.ModuleType, __future__._Feature)
TRANSLATED_MARKER = b"\xE2\x86\x97"
if sys.version_info.major < 3:
string_types = (str, unicode)
ignore_types = ignore_types + (long, types.NoneType)
else:
string_types = (str,)
ignore_types = ignore_types + (type(None),)
TRANSLATED_MARKER = TRANSLATED_MARKER.decode("UTF-8")
ignore_names = [
"_IDCFUNC_CB_T",
"call_idc_func__",
"_BUTTONCB_T",
"_FORMCHGCB_T",
"__ask_form_callable",
"__open_form_callable",
"_notify_when_dispatcher",
"_make_badattr_property",
"long_type",
"cvar",
"__spec__",
"SourceFileLoader",
"__loader__",
"_make_badattr_property",
re.compile("_Swig.*"),
re.compile("_swig.*"),
"SWIG_PyInstanceMethod_New",
"svalvec_t", # aliased with intvec_t or int64vec_t
"uvalvec_t", # aliased with uintvec_t or uint64vec_t
"eavec_t", # aliased with uvalvec_t
("ida_ida", "__getattr__"),
("idc", "__getattr__"),
("__future__", "_Feature"),
]
def should_ignore_name(namespace_name, name):
for ign in ignore_names:
if isinstance(ign, tuple):
if ign == (namespace_name, name):
return True
elif isinstance(ign, string_types):
if ign == name:
return True
else:
if ign.match(name):
return True
return False
def apply_translations(translations, input):
lines = input.split("\n")
out = []
for l in lines:
for all_frm, dst, marker in translations:
assert(isinstance(all_frm, tuple))
for frm in all_frm:
idx = l.find(frm)
if idx > -1:
# sys.stderr.write("SPOTTED '%s' in '%s', position %s\n" % (frm, l, idx))
l = l[0:idx] + dst + l[idx+len(frm):]
if marker:
l += TRANSLATED_MARKER
# sys.stderr.write("ADDING '%s'\n" % l)
out.append(l)
return '\n'.join(out)
all_specific_translations = {
"ida_hexrays.casm_t" : [
((
"uintvec_t",
"uint64vec_t"
), "eavec_t", True),
((
"unsigned int *",
"unsigned long long *"
), "unsigned-ea-like-numeric-type *", True),
((
"unsigned int &",
"unsigned long long &"
), "unsigned-ea-like-numeric-type &", True),
((
"unsigned int const &",
"unsigned long long const &"
), "unsigned-ea-like-numeric-type const &", True),
((
"qvector< unsigned int >::",
"qvector< unsigned long long >::"
), "qvector< unsigned-ea-like-numeric-type >::", True),
((
"qvector< unsigned int > &",
"qvector< unsigned long long > &"
), "qvector< unsigned-ea-like-numeric-type > &", True),
],
"ida_hexrays.ivl_t" : [
((
") -> 'unsigned int'",
") -> 'unsigned long long'", # py3
), ") -> 'unsigned-ea-like-numeric-type'", True),
((
") -> unsigned int",
") -> unsigned long long", # py3
), ") -> unsigned-ea-like-numeric-type", True),
],
"ida_hexrays.uval_ivl_t" : [
((
") -> 'unsigned int'",
") -> 'unsigned long long'", # py3
), ") -> 'unsigned-ea-like-numeric-type'", True),
((
") -> unsigned int",
") -> unsigned long long", # py3
), ") -> unsigned-ea-like-numeric-type", True),
((
"_off: unsigned int",
"_off: unsigned long long", # py3
), "_off: unsigned-ea-like-numeric-type", True),
((
"_size: unsigned int",
"_size: unsigned long long", # py3
), "_size: unsigned-ea-like-numeric-type", True),
],
"ida_hexrays.ivlset_t" : [
((
"ivlset_tpl< ivl_t,unsigned int >::",
"ivlset_tpl< ivl_t,unsigned long long >::", # py3
), "ivlset_tpl< ivl_t,unsigned-ea-like-numeric-type >::", True),
((
"v: unsigned int",
"v: unsigned long long"
), "v: unsigned-ea-like-numeric-type", True),
],
"ida_hexrays.uval_ivl_ivlset_t" : [
((
"ivlset_tpl< ivl_t,unsigned int >::",
"ivlset_tpl< ivl_t,unsigned long long >::",
), "ivlset_tpl< ivl_t,unsigned-ea-like-numeric-type >::", True),
((
"v: unsigned int",
"v: unsigned long long"
), "v: unsigned-ea-like-numeric-type", True),
],
"ida_segment.segment_defsr_array" : [
((
"unsigned int const &",
"unsigned long long const &",
), "unsigned-ea-like-numeric-type const &", True),
((
"data: unsigned int (&)",
"data: unsigned long long (&)",
), "data: unsigned-ea-like-numeric-type (&)", True),
],
"ida_nalt.strpath_ids_array" : [
# py3
((
"unsigned int const &",
"unsigned long long const &",
), "unsigned-ea-like-numeric-type const &", True),
# py3
((
"data: unsigned int (&)",
"data: unsigned long long (&)",
), "data: unsigned-ea-like-numeric-type (&)", True),
],
"idc.add_func" : [
(("add_func(start, end=4294967295)",
"add_func(start, end=4294967295L)",
"add_func(start, end=18446744073709551615)", # py3
"add_func(start, end=18446744073709551615L)",
), "add_func(start, end=BADADDR)", True),
],
"idc.next_head" : [
(("next_head(ea, maxea=4294967295)",
"next_head(ea, maxea=4294967295L)",
"next_head(ea, maxea=18446744073709551615)", # py3
"next_head(ea, maxea=18446744073709551615L)",
), "next_head(ea, maxea=BADADDR)", True),
],
"ida_xref.casevec_t" : [
((
"qvector< int >",
"qvector< long long >",
), "qvector< signed-ea-like-numeric-type >", True),
],
# all that follows is for py3
"ida_dbg.dbg_bin_search" : [
((
"'uint32 *, qstring *'",
"'uint64 *, qstring *'",
), "'unsigned-ea-like-numeric-type *, qstring *'", True),
],
"ida_dbg.get_ip_val" : [
((
"'uint32 *'",
"'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_dbg.get_sp_val" : [
((
"'uint32 *'",
"'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_funcs.dyn_ea_array" : [
((
"-> unsigned int const &",
"-> unsigned long long const &",
), "-> unsigned-ea-like-numeric-type const &", True),
((
"-> unsigned int *",
"-> unsigned long long *",
), "-> unsigned-ea-like-numeric-type *", True),
((
"_data: unsigned int *",
"_data: unsigned long long *",
), "_data: unsigned-ea-like-numeric-type *", True),
((
"v: unsigned int const &",
"v: unsigned long long const &",
), "v: unsigned-ea-like-numeric-type const &", True),
# Python3
((
"-> 'unsigned int const &'",
"-> 'unsigned long long const &'",
), "-> 'unsigned-ea-like-numeric-type const &'", True),
],
"ida_idp.ph_find_op_value" : [
((
"uint32",
"uint64",
), "unsigned-ea-like-numeric-type", True),
],
"ida_idp.ph_find_reg_value" : [
((
"uint32",
"uint64",
), "unsigned-ea-like-numeric-type", True),
],
"ida_hexrays.user_iflags_t" : [
((
"int([x]) -> integer",
), "int(x=0) -> integer", False),
],
"ida_hexrays.eamap_t" : [
((
"int([x]) -> integer",
), "int(x=0) -> integer", False),
((
"_Keyval: unsigned int const &",
"_Keyval: unsigned long long const &"
), "_Keyval: unsigned-ea-like-numeric-type const &", True),
],
"ida_hexrays.user_unions_t" : [
((
"_Keyval: unsigned int const &",
"_Keyval: unsigned long long const &"
), "_Keyval: unsigned-ea-like-numeric-type const &", True),
],
"ida_hexrays.DecompilationFailure" : [
((
"Helper for pickle.",
), "helper for pickle", False),
],
"idc.DeprecatedIDCError" : [
((
"Helper for pickle.",
), "helper for pickle", False),
],
"ida_idp._processor_t" : [
((
"'uint32 *'",
"'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_idp._processor_t_find_op_value" : [
((
"'uint32 *'",
"'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_idp._processor_t_find_reg_value" : [
((
"'uint32 *'",
"'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_kernwin.atoea" : [
((
"-> 'uint32 *'",
"-> 'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_kernwin.str2ea" : [
((
"-> 'uint32 *'",
"-> 'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_kernwin.str2ea_ex" : [
((
"-> 'uint32 *'",
"-> 'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_kernwin.PluginForm" : [
((
"module '__main__' from 'tools/dumpdoc.py'",
"module '__main__' (built-in)",
), "module 'main'", False),
],
}
if is_64:
all_specific_translations["ida_dirtree.direntry_t"] = [
((
"BADIDX = 18446744073709551615L",
"BADIDX = 18446744073709551615",
), "BADIDX = unsigned-ea-like-numeric-type(-1)", False),
]
else:
all_specific_translations["ida_dirtree.direntry_t"] = [
((
"BADIDX = 4294967295L",
"BADIDX = 4294967295",
), "BADIDX = unsigned-ea-like-numeric-type(-1)", False),
]
def dump_namespace(namespace, namespace_name, keys, vec_info=None):
spotted_things = []
for thing_name in keys:
# sys.stderr.write("THING NAME: %s\n" % thing_name)
if should_ignore_name(namespace_name, thing_name):
continue
thing = getattr(namespace, thing_name)
if isinstance(thing, ignore_types):
continue
if thing in spotted_things:
continue
specific_translations = all_specific_translations.get(
"%s.%s" % (namespace_name, thing_name),
None)
if specific_translations:
was_stdout = sys.stdout
sys.stdout = StringIO()
pydoc.help(thing)
# sys.stderr.write("VALUE FOR %s.%s: %s" % (namespace_name, thing_name, sys.stdout.getvalue()))
translated = apply_translations(specific_translations, sys.stdout.getvalue())
# sys.stderr.write("TRANSLATED %s.%s: %s" % (namespace_name, thing_name, translated))
sys.stdout = was_stdout
sys.stdout.write(translated)
else:
pydoc.help(thing)
spotted_things.append(thing)
class variable_collector_t(ast.NodeVisitor):
OUTSIDE = 0
IN_CLASS = 1
IN_FUNCTION = 2
def __init__(self, variables, module_name):
self.variables = variables
self.module_name = module_name
self.context = self.OUTSIDE
self.class_name = ""
self.assign_last_line = -1
super(variable_collector_t, self).__init__()
def visit_FunctionDef(self, node):
old_context = self.context
self.context = self.IN_FUNCTION
self.generic_visit(node)
self.context = old_context
def visit_ClassDef(self, node):
if self.context == self.IN_FUNCTION:
return
if self.context == self.IN_CLASS:
prefix = self.class_name + "."
else:
prefix = ""
self.class_name = prefix + node.name
old_context = self.context
self.context = self.IN_CLASS
self.generic_visit(node)
self.context = old_context
def visit_Assign(self, node):
if self.context == self.IN_FUNCTION:
return
if self.context == self.IN_CLASS:
prefix = self.class_name + "."
else:
prefix = ""
if len(node.targets) == 1:
target = node.targets[0]
if isinstance(target, ast.Name):
self.assign_variable = prefix + target.id
self.assign_last_line = self._highest_lineno(node)
def _highest_lineno(self, node):
if hasattr(node, "end_lineno"):
return node.end_lineno
highest = node.lineno
for child in ast.walk(node):
if hasattr(child, "lineno") and child.lineno > highest:
highest = child.lineno
return highest
def visit_Expr(self, node):
if not isinstance(node.value, ast.Str):
return
if hasattr(node, "end_lineno"):
line_before = node.lineno - 1 # in this case, lineno = start
else:
# hack until Python 3.8; if <3.8, lineno = end
line_before = node.lineno - len(node.value.s.split("\n"))
if line_before == self.assign_last_line:
self.variables.append(
"\nDocumentation on variable %s in module %s:\n\n%s\n" \
% (self.assign_variable,
self.module_name,
self._cleandoc(node.value.s)))
def _cleandoc(self, docstring):
if docstring:
docstring = inspect.cleandoc(docstring)
# 4-blanks indent
docstring = "\n".join(" " + line for line in docstring.split("\n"))
return docstring
def collect_variables(variables, module_name, filename):
with open(filename, "r") as f:
tree = ast.parse(f.read())
visitor = variable_collector_t(variables, module_name)
visitor.visit(tree)
# By default, pydoc.help() hides members that start with "_"
# unless they start and end with "__" (with an exception for
# __doc__ and __module__)
# We want those "_" members, since there are important
# things such as tinfo_t._print in there.
orig_visiblename = pydoc.visiblename
def my_visiblename(name, all=None, obj=None):
v = orig_visiblename(name, all=all, obj=obj)
if not v and name.startswith("_") and name not in ["__doc__", "__module__"]:
v = True
return v
pydoc.visiblename = my_visiblename
def iter_modules():
for mname in sorted(sys.modules):
if mname.startswith("ida_") or mname == "idc":
yield mname, sys.modules[mname]
sys.stdout.write("### Before collecting help\n")
old_stdout = sys.stdout ### debug
sys.stdout = StringIO()
for mname, module in iter_modules():
print("Module \"%s\"s docstring:\n\"\"\"%s\"\"\"\n" % (mname, module.__doc__))
dump_namespace(module, mname, sorted(dir(module)))
old_stdout.write("### After collecting help\n")
final = apply_translations([], sys.stdout.getvalue())
old_stdout.write("### After applying translations\n")
def module_file(module):
name, ext = os.path.splitext(module.__file__)
if ext == ".pyc":
ext = ".py"
return name + ext
old_stdout.write("### Before collecting variables\n")
variables = ["\n=== DOCUMENTATION FOR VARIABLES ===\n"]
for mname, module in iter_modules():
collect_variables(variables, mname, module_file(module))
old_stdout.write("### After collecting variables (%d of them)\n" % len(variables))
final += "".join(variables)
with open(output, "wb") as f:
if sys.version_info.major <= 2:
f.write(final)
else:
f.write(final.encode("utf-8"))
old_stdout.write("### Wrote output (%d chars), end of script\n" % len(final))
idaapi.qexit(0)
+4 -4
View File
@@ -43,7 +43,7 @@ def read_config():
global config
config_path = os.path.join(prog_dir, prog_name + ".cfg")
with open(config_path, "r") as f:
with open(config_path, "r", encoding="UTF-8", errors="surrogateescape") as f:
config = ast.literal_eval(f.read())
config["exclude"] = set(config["exclude"])
@@ -73,7 +73,7 @@ class Examples(object):
for relpath, path in self._files_with_extension(".py", args.examples_dir):
verb("Processing \"%s\"" % path)
with open(path, "r") as f:
with open(path, "r", encoding="UTF-8", errors="surrogateescape") as f:
self._load_ast(relpath, ast.parse(f.read(), path))
self._post_read_processing()
@@ -649,11 +649,11 @@ class ExamplesIndex(object):
def __init__(self):
self.replacer = TemplateReplacer()
with open(args.template, "r") as f:
with open(args.template, "r", encoding="UTF-8", errors="surrogateescape") as f:
self.replacer.template(f.read())
def produce(self, examples, all_keywords):
with open(args.output, "w") as f:
with open(args.output, "w", encoding="UTF-8") as f:
self.replacer.expand(examples, all_keywords, f)
#-------------------------------------------------------------------------------
+2 -1
View File
@@ -123,10 +123,11 @@ def gen_notifications(out):
pname = recipe_data.get("params", {}).get(pname, {}).get("rename", pname)
ptype = p["type"]
pick_type = ptype
# instead of va_argi() we jst promote the type to "int"
if ptype in ["bool", "char", "uchar", "uint16", "cref_t",
"dref_t", "cm_t", "ui_notification_t", "dbg_notification_t",
"tcc_renderer_type_t", "range_kind_t", "demreq_type_t",
"ctree_maturity_t", "comp_t"]:
"ctree_maturity_t", "comp_t", "local_type_change_t"]:
cast = ptype
pick_type = "int"
else:
+1
View File
@@ -5,6 +5,7 @@ recipe = {
"ev_last_cb_before_type_callbacks" : {"ignore" : True},
"ev_get_idd_opinfo" : {"ignore" : True},
"ev_loader_elf_machine" : {"ignore" : True},
"ev_get_regfinder" : {"ignore" : True},
"ev_broadcast" : {"ignore" : True},
"ev_obsolete1" : {"ignore" : True},
"ev_obsolete2" : {"ignore" : True},
+2 -2
View File
@@ -113,7 +113,7 @@ wrap_regex = re.compile(r"SWIGINTERN PyObject \*_wrap_([a-zA-Z0-9_]*)\(.*")
director_method_regex = re.compile(r".*((SwigDirector_([a-zA-Z0-9_]*))::~?([a-zA-Z0-9_]*))\(.*")
swig_clink_var_get_regex = re.compile(r"SWIGINTERN PyObject \*(Swig_var_[a-zA-Z0-9_]*_get).*")
swig_clink_var_set_regex = re.compile(r"SWIGINTERN int (Swig_var_[a-zA-Z0-9_]*_set).*")
SWIG_Python_TypeError_regex = re.compile(".*(SWIG_Python_TypeError)\(const char \*type, PyObject \*obj\).*")
SWIG_Python_TypeError_regex = re.compile(r".*(SWIG_Python_TypeError)\(const char \*type, PyObject \*obj\).*")
SwigPyObject_dealloc_regex = re.compile(r"^(SwigPyObject_dealloc)\(PyObject \*v\)$")
all_lines = [
@@ -322,7 +322,7 @@ with open(args.input) as f:
elif line.find("result = PyObject_CallMethodObjArgs") > -1:
call_args = args_cmoa
if call_args:
subst = re.sub("\(.*\);", call_args + ";", line)
subst = re.sub(r"\(.*\);", call_args + ";", line)
if add_error:
subst = ["#error CHECK_THAT_THIS_WORKS", subst]
elif patch_kind == "nullptr_result_on_py_error":
+9
View File
@@ -92,4 +92,13 @@ if ( __argcnt == 2 )
"(swig_get_self(), (PyObject *) swig_method_name ,(PyObject *)obj0,(__argcnt < 3 ? nullptr : (PyObject *)obj1), nullptr)")
),
],
"SwigDirector_IDB_Hooks::local_types_changed" : [
("director_method_call_arity_cap", (
False, # add GIL lock
"local_types_changed",
"(method ,(__argcnt < 2 ? nullptr : (PyObject *)obj0), (__argcnt < 2 ? nullptr : (PyObject *)obj1), (__argcnt < 2 ? nullptr : (PyObject *)obj2), nullptr)",
"(swig_get_self(), (PyObject *) swig_method_name ,(__argcnt < 2 ? nullptr : (PyObject *)obj0), (__argcnt < 2 ? nullptr : (PyObject *)obj1), (__argcnt < 2 ? nullptr : (PyObject *)obj2), nullptr)")
),
],
}
+531
View File
@@ -0,0 +1,531 @@
import sys
import ast
import inspect
import argparse
import os
p = argparse.ArgumentParser()
p.add_argument("-p", "--paths", type=str, required=True, help="Path(s) to the file(s) to parse")
p.add_argument("-c", "--dump-doc", default=False, action="store_true", help="Dump python docstrings")
p.add_argument("-k", "--dump-kind", default=False, action="store_true", help="Dump scopes kinds (class, method, ...)")
args = p.parse_args()
class scope_t(object):
def __init__(self, node, scope):
self.node = node
self.parent = None
self.children = []
self.doc = None
def _new_scope(self, _type, node):
scope = _type(node, self)
self.children.append(scope)
scope.parent = self
return scope
def kind(self):
return self.__class__.__name__.replace("_t", "")
def new_class(self, node):
return self._new_scope(class_t, node)
def new_method(self, node):
return self._new_scope(method_t, node)
def new_function(self, node):
return self._new_scope(function_t, node)
def new_variable(self, node, variable_name):
s = self._new_scope(variable_t, node)
s.variable_name = variable_name
return s
def get_name(self):
return self.node.name
def get_full_name_parts(self):
parts = []
s = self
while s is not None:
parts.append(s.get_name())
s = s.parent
return reversed(parts)
def get_full_name(self):
return ".".join(self.get_full_name_parts())
def set_doc(self, doc):
self.doc = doc
class module_t(scope_t):
pass
class class_t(scope_t):
pass
class method_t(scope_t):
pass
class function_t(scope_t):
pass
class variable_t(scope_t):
def get_name(self):
return self.variable_name
DF_DOC = 0x1
DF_KIND = 0x2
def dump(scope, flags=0, sort=True):
lines = []
def dump1(s):
name = s.get_full_name()
line = [name]
if (flags & DF_KIND) != 0:
line.append("(%s)" % s.kind())
lines.append(" ".join(line))
if (flags & DF_DOC) != 0:
if s.doc is not None:
lines.extend(s.doc.split("\n"))
lines.append("")
children = s.children[:]
if sort:
children = sorted(children, key=lambda n: n.get_name())
for c in children:
dump1(c)
dump1(scope)
return "\n".join(lines)
class collector_t(ast.NodeVisitor):
class temp_scope_t(object):
def __init__(self, collector, scope):
self.collector = collector
self.scope = scope
def __enter__(self):
old_scope = self.collector.scope
self.collector.scope = self.scope
self.scope = old_scope # swoop in the old context
def __exit__(self, tp, value, traceback):
self.collector.scope = self.scope
if value:
raise
def __init__(self, module_name):
class module_node_t(object):
def __init__(self, name):
self.name = name
self.scope = module_t(module_node_t(module_name), None)
self.assign_last_line = -1
super(collector_t, self).__init__()
def in_function(self):
return isinstance(self.scope, function_t)
def in_class(self):
return isinstance(self.scope, class_t)
def accept(self, node):
return True
def visit_FunctionDef(self, node):
if self.accept(node):
if self.in_class():
s = self.scope.new_method(node)
else:
s = self.scope.new_function(node)
with self.temp_scope_t(self, s):
self.generic_visit(node)
def visit_ClassDef(self, node):
if self.in_function():
return
if self.accept(node):
with self.temp_scope_t(self, self.scope.new_class(node)):
self.generic_visit(node)
def visit_Assign(self, node):
if self.in_function():
return
if len(node.targets) == 1:
target = node.targets[0]
if isinstance(target, ast.Name):
self.assign_variable = target.id
self.assign_last_line = self._highest_lineno(node)
def _highest_lineno(self, node):
if hasattr(node, "end_lineno"):
return node.end_lineno
highest = node.lineno
for child in ast.walk(node):
if hasattr(child, "lineno") and child.lineno > highest:
highest = child.lineno
return highest
def visit_Expr(self, node):
# print("%d: %s" % (node.lineno, ast.dump(node.value)))
if not isinstance(node.value, ast.Str):
return
if hasattr(node, "end_lineno"):
line_before = node.lineno - 1 # in this case, lineno = start
else:
# hack until Python 3.8; if <3.8, lineno = end
line_before = node.lineno - len(node.value.s.split("\n"))
clean_doc = self._cleandoc(node.value.s)
if line_before == self.assign_last_line:
self.scope.new_variable(node, self.assign_variable).set_doc(clean_doc)
else:
self.scope.set_doc(clean_doc)
# self.variables.append(
# "\nDocumentation on variable %s in module %s:\n\n%s\n" \
# % (self.assign_variable,
# self.module_name,
# self._cleandoc(node.value.s)))
def _cleandoc(self, docstring):
if docstring:
docstring = inspect.cleandoc(docstring)
# 4-blanks indent
docstring = "\n".join(" " + line for line in docstring.split("\n"))
return docstring
class docfixing_collector_t(collector_t):
IGNORE = [
"ida_kernwin.__ask_form_callable",
"ida_kernwin.__call_form_callable",
"ida_kernwin.__open_form_callable",
"*._SwigNonDynamicMeta",
"*._swig_add_metaclass",
"*._swig_add_metaclass.wrapper",
"*._swig_repr",
"*._swig_setattr_nondynamic_class_variable",
"*._swig_setattr_nondynamic_class_variable.set_class_attr",
"*._swig_setattr_nondynamic_instance_variable",
"*._swig_setattr_nondynamic_instance_variable.set_instance_attr",
"*.*.dump_state",
]
def accept(self, node):
full_name_parts = list(self.scope.get_full_name_parts()) + [node.name]
for ign in self.IGNORE:
ign_parts = ign.split(".")
if len(full_name_parts) == len(ign_parts):
match = True
for got, against in zip(full_name_parts, ign_parts):
if against != "*" and got != against:
match = False
break
if match:
return False
return True
TRANSLATIONS = {
"ida_hexrays.casm_t" : [
((
"uintvec_t",
"uint64vec_t"
), "eavec_t", True),
((
"unsigned int *",
"unsigned long long *"
), "unsigned-ea-like-numeric-type *", True),
((
"unsigned int &",
"unsigned long long &"
), "unsigned-ea-like-numeric-type &", True),
((
"unsigned int const &",
"unsigned long long const &"
), "unsigned-ea-like-numeric-type const &", True),
((
"qvector< unsigned int >::",
"qvector< unsigned long long >::"
), "qvector< unsigned-ea-like-numeric-type >::", True),
((
"qvector< unsigned int > &",
"qvector< unsigned long long > &"
), "qvector< unsigned-ea-like-numeric-type > &", True),
],
"ida_hexrays.ivl_t" : [
((
") -> 'unsigned int'",
") -> 'unsigned long long'", # py3
), ") -> 'unsigned-ea-like-numeric-type'", True),
((
") -> unsigned int",
") -> unsigned long long", # py3
), ") -> unsigned-ea-like-numeric-type", True),
],
"ida_hexrays.uval_ivl_t" : [
((
") -> 'unsigned int'",
") -> 'unsigned long long'", # py3
), ") -> 'unsigned-ea-like-numeric-type'", True),
((
") -> unsigned int",
") -> unsigned long long", # py3
), ") -> unsigned-ea-like-numeric-type", True),
((
"_off: unsigned int",
"_off: unsigned long long", # py3
), "_off: unsigned-ea-like-numeric-type", True),
((
"_size: unsigned int",
"_size: unsigned long long", # py3
), "_size: unsigned-ea-like-numeric-type", True),
],
"ida_hexrays.ivlset_t" : [
((
"ivlset_tpl< ivl_t,unsigned int >::",
"ivlset_tpl< ivl_t,unsigned long long >::", # py3
), "ivlset_tpl< ivl_t,unsigned-ea-like-numeric-type >::", True),
((
"v: unsigned int",
"v: unsigned long long"
), "v: unsigned-ea-like-numeric-type", True),
],
"ida_hexrays.uval_ivl_ivlset_t" : [
((
"ivlset_tpl< ivl_t,unsigned int >::",
"ivlset_tpl< ivl_t,unsigned long long >::",
), "ivlset_tpl< ivl_t,unsigned-ea-like-numeric-type >::", True),
((
"v: unsigned int",
"v: unsigned long long"
), "v: unsigned-ea-like-numeric-type", True),
],
"ida_segment.segment_defsr_array" : [
((
"unsigned int const &",
"unsigned long long const &",
), "unsigned-ea-like-numeric-type const &", True),
((
"data: unsigned int (&)",
"data: unsigned long long (&)",
), "data: unsigned-ea-like-numeric-type (&)", True),
],
"ida_nalt.strpath_ids_array" : [
# py3
((
"unsigned int const &",
"unsigned long long const &",
), "unsigned-ea-like-numeric-type const &", True),
# py3
((
"data: unsigned int (&)",
"data: unsigned long long (&)",
), "data: unsigned-ea-like-numeric-type (&)", True),
],
"idc.add_func" : [
(("add_func(start, end=4294967295)",
"add_func(start, end=4294967295L)",
"add_func(start, end=18446744073709551615)", # py3
"add_func(start, end=18446744073709551615L)",
), "add_func(start, end=BADADDR)", True),
],
"idc.next_head" : [
(("next_head(ea, maxea=4294967295)",
"next_head(ea, maxea=4294967295L)",
"next_head(ea, maxea=18446744073709551615)", # py3
"next_head(ea, maxea=18446744073709551615L)",
), "next_head(ea, maxea=BADADDR)", True),
],
"ida_xref.casevec_t" : [
((
"qvector< int >",
"qvector< long long >",
), "qvector< signed-ea-like-numeric-type >", True),
],
# all that follows is for py3
"ida_dbg.dbg_bin_search" : [
((
"'uint32 *, qstring *'",
"'uint64 *, qstring *'",
), "'unsigned-ea-like-numeric-type *, qstring *'", True),
],
"ida_dbg.get_ip_val" : [
((
"'uint32 *'",
"'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_dbg.get_sp_val" : [
((
"'uint32 *'",
"'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_funcs.dyn_ea_array" : [
((
"-> unsigned int const &",
"-> unsigned long long const &",
), "-> unsigned-ea-like-numeric-type const &", True),
((
"-> unsigned int *",
"-> unsigned long long *",
), "-> unsigned-ea-like-numeric-type *", True),
((
"_data: unsigned int *",
"_data: unsigned long long *",
), "_data: unsigned-ea-like-numeric-type *", True),
((
"v: unsigned int const &",
"v: unsigned long long const &",
), "v: unsigned-ea-like-numeric-type const &", True),
# Python3
((
"-> 'unsigned int const &'",
"-> 'unsigned long long const &'",
), "-> 'unsigned-ea-like-numeric-type const &'", True),
],
"ida_idp.ph_find_op_value" : [
((
"uint32",
"uint64",
), "unsigned-ea-like-numeric-type", True),
],
"ida_idp.ph_find_reg_value" : [
((
"uint32",
"uint64",
), "unsigned-ea-like-numeric-type", True),
],
"ida_regfinder.find_reg_value" : [
((
"'uint32 *'",
"'uint64 *'",
), "unsigned-ea-like-numeric-type", True),
],
"ida_regfinder.find_sp_value" : [
((
"'int32 *'",
"'int64 *'",
), "signed-ea-like-numeric-type", True),
],
"ida_hexrays.user_iflags_t" : [
((
"int([x]) -> integer",
), "int(x=0) -> integer", False),
],
"ida_hexrays.eamap_t" : [
((
"int([x]) -> integer",
), "int(x=0) -> integer", False),
((
"_Keyval: unsigned int const &",
"_Keyval: unsigned long long const &"
), "_Keyval: unsigned-ea-like-numeric-type const &", True),
],
"ida_hexrays.user_unions_t" : [
((
"_Keyval: unsigned int const &",
"_Keyval: unsigned long long const &"
), "_Keyval: unsigned-ea-like-numeric-type const &", True),
],
"ida_hexrays.DecompilationFailure" : [
((
"Helper for pickle.",
), "helper for pickle", False),
],
"idc.DeprecatedIDCError" : [
((
"Helper for pickle.",
), "helper for pickle", False),
],
"ida_idp._processor_t" : [
((
"'uint32 *'",
"'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_idp._processor_t_find_op_value" : [
((
"'uint32 *'",
"'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_idp._processor_t_find_reg_value" : [
((
"'uint32 *'",
"'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_kernwin.atoea" : [
((
"-> 'uint32 *'",
"-> 'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_kernwin.str2ea" : [
((
"-> 'uint32 *'",
"-> 'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_kernwin.str2ea_ex" : [
((
"-> 'uint32 *'",
"-> 'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_kernwin.PluginForm" : [
((
"module '__main__' from 'tools/dumpdoc.py'",
"module '__main__' (built-in)",
), "module 'main'", False),
],
}
def _cleandoc(self, docstring):
docstring = super(docfixing_collector_t, self)._cleandoc(docstring)
name = self.scope.get_full_name()
translations = None
while name:
translations = self.TRANSLATIONS.get(name, None)
if translations:
break
name_parts = name.split(".")
name = ".".join(name_parts[:-1])
if translations:
out = []
for l in docstring.split("\n"):
for all_frm, dst, _ in translations:
assert(isinstance(all_frm, tuple))
for frm in all_frm:
idx = l.find(frm)
if idx > -1:
# sys.stderr.write("SPOTTED '%s' in '%s', position %s\n" % (frm, l, idx))
l = l[0:idx] + dst + l[idx+len(frm):]
# sys.stderr.write("ADDING '%s'\n" % l)
out.append(l)
docstring = '\n'.join(out)
return docstring
toplevel_scopes = []
for path in args.paths.split(","):
with open(path, "r") as f:
tree = ast.parse(f.read())
_, fname = os.path.split(path)
module_name = fname[:fname.index(".")]
vc = docfixing_collector_t(module_name)
vc.visit(tree)
toplevel_scopes.append(vc.scope)
flags = (DF_DOC if args.dump_doc else 0) \
| (DF_KIND if args.dump_kind else 0)
for s in toplevel_scopes:
print(dump(s, flags=flags))