44
55Run the application with the debugger, suspend the debugger, select a thread and finally run the script.
66
7- Copyright (c) 1990-2009 Hex-Rays
7+ Copyright (c) 1990-2017 Hex-Rays
88ALL RIGHTS RESERVED.
9-
10-
11- v1.0 - initial version
12- v1.0.1 - added stack segment bitness detection, thus works with 64bit processes too
139"""
14- import idaapi
15- import idc
10+ import ida_ua
11+ import ida_bytes
12+ import ida_kernwin
13+ import ida_funcs
14+ import ida_name
15+ import ida_ida
16+ import ida_idp
17+ import ida_segment
18+ import ida_dbg
1619import idautils
17- from ida_kernwin import Choose
1820
1921# -----------------------------------------------------------------------
2022# class to take a copy of a segment_t
@@ -24,6 +26,7 @@ def __init__(self, s):
2426 self .end_ea = s .end_ea
2527 self .perm = s .perm
2628 self .bitness = s .bitness
29+
2730 def __cmp__ (self , other ):
2831 return cmp (self .start_ea , other .start_ea )
2932
@@ -51,18 +54,18 @@ def IsPrevInsnCall(ea):
5154 is a CALL instruction
5255 """
5356 global CallPattern
54- if ea == idaapi .BADADDR or ea < 10 :
57+ if ea == ida_idaapi .BADADDR or ea < 10 :
5558 return None
5659
5760 for delta , opcodes in CallPattern :
5861 # assume caller's ea
5962 caller = ea + delta
6063 # get the bytes
61- bytes = [x for x in GetDataList (caller , len (opcodes ), 1 )]
64+ bytes = [x for x in idautils . GetDataList (caller , len (opcodes ), 1 )]
6265 # do we have a match? is it a call instruction?
6366 if bytes == opcodes :
64- tmp = idaapi .insn_t ()
65- if idaapi .decode_insn (tmp , caller ) and idaapi .is_call_insn (tmp ):
67+ insn = ida_ua .insn_t ()
68+ if ida_ua .decode_insn (insn , caller ) and ida_idp .is_call_insn (insn ):
6669 return caller
6770 return None
6871
@@ -79,32 +82,35 @@ class Result:
7982 def __init__ (self , caller , sp ):
8083 self .caller = caller
8184 self .sp = sp
82- f = idaapi .get_func (caller )
83- self .displ = ""
85+ f = ida_funcs .get_func (caller )
86+ self .displ = "%08x: " % caller
8487 if f :
85- self .displ += idc .get_func_name (caller )
88+ self .displ += ida_funcs .get_func_name (caller )
8689 t = caller - f .start_ea
8790 if t > 0 : self .displ += "+" + hex (t )
8891 else :
8992 self .displ += hex (caller )
9093 self .displ += " [" + hex (sp ) + "]"
9194
95+ def __str__ (self ):
96+ return self .displ
97+
9298 # get stack pointer
93- sp = cpu .Esp
94- seg = idaapi .getseg (sp )
99+ sp = idautils . cpu .Esp
100+ seg = ida_segment .getseg (sp )
95101 if not seg :
96102 return (False , "Could not locate stack segment!" )
97103
98104 stack_seg = Seg (seg )
99105 word_size = 2 ** (seg .bitness + 1 )
100106 callers = []
101- sp = cpu .Esp - word_size
107+ sp = idautils . cpu .Esp - word_size
102108 while sp < stack_seg .end_ea :
103109 sp += word_size
104110 ptr = idautils .GetDataList (sp , 1 , word_size ).next ()
105- seg = idaapi .getseg (ptr )
111+ seg = ida_segment .getseg (ptr )
106112 # only accept executable segments
107- if (not seg ) or ((seg .perm & idaapi .SEGPERM_EXEC ) == 0 ):
113+ if (not seg ) or ((seg .perm & ida_segment .SEGPERM_EXEC ) == 0 ):
108114 continue
109115 # try to find caller
110116 caller = IsPrevInsnCall (ptr )
@@ -118,69 +124,63 @@ def __init__(self, caller, sp):
118124 if ret :
119125 ea = ret [0 ]
120126 # function exists?
121- f = idaapi .get_func (ea )
127+ f = ida_funcs .get_func (ea )
122128 if not f :
123129 # create function
124- idc .add_func (ea , idaapi . BADADDR )
130+ ida_funcs .add_func (ea )
125131
126132 # get the flags
127- f = idc .get_flags (caller )
133+ f = ida_bytes .get_flags (caller )
128134 # no code there?
129- if not is_code (f ):
130- create_insn (caller )
135+ if not ida_bytes . is_code (f ):
136+ ida_ua . create_insn (caller )
131137
132138 callers .append (Result (caller , sp ))
133139 #
134140 return (True , callers )
135141
136142# -----------------------------------------------------------------------
137143# Chooser class
138- class CallStackWalkChoose (Choose ):
144+ class CallStackWalkChoose (ida_kernwin . Choose ):
139145 def __init__ (self , title , items ):
140- Choose .__init__ (self , title , [ ["Caller" , 16 ], ["Display" , 250 ] ])
146+ ida_kernwin .Choose .__init__ (
147+ self ,
148+ title ,
149+ [["Location" , 30 ]])
141150 self .items = items
142-
143- def OnGetLine (self , n ):
144- o = self .items [n ]
145- line = []
146- line .append ("%X" % o .caller )
147- line .append ("%s" % o .displ )
148- return line
151+ self .modal = True
149152
150153 def OnGetSize (self ):
151154 return len (self .items )
152155
156+ def OnGetLine (self , n ):
157+ return [str (self .items [n ])]
158+
153159 def OnSelectLine (self , n ):
154- o = self .items [n ]
155- jumpto (o .caller )
156- return (Choose .NOTHING_CHANGED , )
160+ ida_kernwin .jumpto (self .items [n ].caller )
157161
158162# -----------------------------------------------------------------------
159163def main ():
160- if not idaapi .is_debugger_on ():
161- idc .warning ("Please run the process first!" )
164+ if not ida_dbg .is_debugger_on ():
165+ ida_kernwin .warning ("Please run the process first!" )
162166 return
163- if idaapi .get_process_state () != - 1 :
164- idc .warning ("Please suspend the debugger first!" )
167+ if ida_dbg .get_process_state () != - 1 :
168+ ida_kernwin .warning ("Please suspend the debugger first!" )
165169 return
166170
167- # only avail from IdaPython r232
168- if hasattr (idaapi , "NearestName" ):
169- # get all debug names
170- dn = idaapi .get_debug_names (idaapi .cvar .inf .min_ea , idaapi .cvar .inf .max_ea )
171- # initiate a nearest name search (using debug names)
172- nn = idaapi .NearestName (dn )
173- else :
174- nn = None
171+ # get all debug namesp
172+ dn = ida_name .get_debug_names (ida_ida .cvar .inf .min_ea , ida_ida .cvar .inf .max_ea )
173+ # initiate a nearest name search (using debug names)
174+ nn = ida_name .NearestName (dn )
175175
176176 ret , callstack = CallStackWalk (nn )
177177 if ret :
178- title = "Call stack walker (thread %X)" % (get_current_thread ())
179- idaapi .close_chooser (title )
178+ title = "Call stack walker (thread %X)" % (ida_dbg . get_current_thread ())
179+ ida_kernwin .close_chooser (title )
180180 c = CallStackWalkChoose (title , callstack )
181- c .Show ()
181+ c .Show (True )
182182 else :
183- idc .warning ("Failed to walk the stack:" + callstack )
183+ ida_kernwin .warning ("Failed to walk the stack:" + callstack )
184184
185185# -----------------------------------------------------------------------
186186main ()
0 commit comments