11import os
2- from typing import Optional , Union
2+ from typing import Callable , Optional , Union
33from pathlib import Path
44
55import openai
99from binaryninja .function import Function
1010from binaryninja .lowlevelil import LowLevelILFunction
1111from binaryninja .mediumlevelil import MediumLevelILFunction
12- from binaryninja .highlevelil import HighLevelILFunction , HighLevelILInstruction
12+ from binaryninja .highlevelil import HighLevelILFunction , HighLevelILInstruction , \
13+ HighLevelILVarInit
1314from binaryninja .settings import Settings
1415from binaryninja import log , BinaryView
1516
@@ -24,10 +25,10 @@ class Agent:
2425 It is in IL_FORM. What does this function do?
2526 '''
2627
27- rename_variable_question : str = '''
28- In one word, what should the variable name be for the variable that is
29- assigned to the result of the C expression:\n
30- '''
28+ rename_variable_question : str = "In one word, what should the variable " \
29+ "be for the variable that is assigned to the result of the C " \
30+ " expression:\n "
31+
3132
3233 # A mapping of IL forms to their names.
3334 il_name : dict [type , str ] = {
@@ -48,6 +49,8 @@ def __init__(self,
4849 # Set instance attributes.
4950 self .bv = bv
5051 self .model = self .get_model ()
52+ # Used for the callback function.
53+ self .instruction = None
5154
5255 def read_api_key (self , filename : Optional [Path ]= None ) -> str :
5356 '''Checks for the API key in three locations.
@@ -157,16 +160,46 @@ def generate_query(self, function: Union[Function,
157160 prompt += '\n ' .join (self .instruction_list (function ))
158161 return prompt
159162
160- def generate_rename_expression_query (
161- instruction : HighLevelILInstruction ) -> str :
163+ def generate_rename_variable_query ( self ,
164+ instruction : HighLevelILInstruction ) -> Optional [ str ] :
162165 '''Generates a query string given a BNIL instruction. Returns the query
163166 as a string.
164167 '''
165- pass
168+ if not isinstance (instruction , HighLevelILVarInit ):
169+ raise TypeError (f'Expected a BNIL instruction of type '
170+ f'HighLevelILVarInit got { type (instruction )} .' )
171+ # Assign the instruction to the Agent instance. This is used for the
172+ # callback function so we don't need to pass in the instruction to the
173+ # Query instance. This is kind of janky and should be examined in future
174+ # versions.
175+ self .instruction = instruction
176+
177+ prompt : str = self .rename_variable_question
178+ # Get the disassembly lines and add them to the prompt.
179+ for line in instruction .instruction_operands :
180+ prompt += str (line )
166181
167- def send_query (self , query : str ) -> None :
182+ return prompt
183+
184+ def rename_variable (self , response : str ) -> None :
185+ '''Renames the variable of the instruction saved in the Agent instance
186+ to the response passed in as an argument.
187+ '''
188+ if self .instruction is None :
189+ raise TypeError ('No instruction was saved in the Agent instance.' )
190+ if response is None or response == '' :
191+ raise TypeError (f'No response was returned from OpenAI; got type { type (response )} .' )
192+ # Get just one word from the response.
193+ response = response .split ()[0 ]
194+ # Assign the variable name to the response.
195+ log .log_debug (f'Renaming variable in expression { self .instruction } to { response } .' )
196+ self .instruction .dest .name = response
197+
198+
199+ def send_query (self , query : str , callback : Optional [Callable ]= None ) -> None :
168200 '''Sends a query to the engine and prints the response.'''
169201 query = Query (query_string = query ,
170202 model = self .model ,
171- max_token_count = self .get_token_count ())
203+ max_token_count = self .get_token_count (),
204+ callback_function = callback )
172205 query .start ()
0 commit comments