@@ -187,6 +187,8 @@ def help(self, *args):
187187 def construct_locals (self ) -> List [Tuple [List [str ], Any ]]:
188188 """Returns a listing of the functions to be added to the environment."""
189189 return [
190+ (["bc" , "breakpoint_clear" ], self .breakpoint_clear ),
191+ (["bl" , "breakpoint_list" ], self .breakpoint_list ),
190192 (["bp" , "breakpoint" ], self .breakpoint ),
191193 (["dt" , "display_type" ], self .display_type ),
192194 (["db" , "display_bytes" ], self .display_bytes ),
@@ -827,22 +829,60 @@ def wrapped_read(offset: int, length: int, pad: bool = False) -> bytes:
827829 original_read = getattr (wrapped_read , "original_read" )
828830 for breakpoint in getattr (wrapped_read , "breakpoints" ):
829831 if (offset <= breakpoint ) and (breakpoint < offset + length ):
832+ print (
833+ "Hit breakpoint, entering python debugger. To continue running without the debugger use the command continue"
834+ )
830835 import pdb
831836
832837 pdb .set_trace ()
833- print ( "Hit breakpoint" )
838+ _ = "First statement after the breakpoint, use u(p), d(own) and list to navigate through the execution frames"
834839 return original_read (offset , length , pad )
835840
836841 setattr (wrapped_read , "breakpoints" , set ())
837842 setattr (wrapped_read , "original_read" , layer .read )
838843 setattr (layer , "read" , wrapped_read )
839844
840845 # Add the new breakpoint
841- print (f"Setting breakpoint { address :x} on { layer .name } " )
846+ print (f"Setting breakpoint { address :# x} on { layer .name } " )
842847 breakpoints = getattr (layer .read , "breakpoints" )
843848 breakpoints .add (address )
844849 setattr (layer .read , "breakpoints" , breakpoints )
845850
851+ def breakpoint_list (self , layer_names : Optional [List [str ]] = None ):
852+ """List available breakpoints for a set of layers"""
853+ if not layer_names :
854+ layer_names = [layer_name for layer_name in self .context .layers ]
855+
856+ print ("Listing breakpoints:" )
857+ for layer_name in layer_names :
858+ print (f" { layer_name } " )
859+ layer = self .context .layers .get (layer_name , None )
860+ if layer and hasattr (layer .read , "breakpoints" ):
861+ for breakpoint in layer .read .breakpoints :
862+ print (f" { breakpoint :#x} " )
863+
864+ def breakpoint_clear (
865+ self , offset : Optional [int ] = None , layer_name : Optional [str ] = None
866+ ):
867+ """Clears a offset breakpoint on a layer (or all breakpoints if offset or layer not specified)
868+
869+ Args:
870+ offset: Address of the breakpoint to clear (or all if None)
871+ layer_name: Layer to clear breakpoints from (or all if None)
872+ """
873+ print ("Clearing breakpoints:" )
874+ for candidate_layer_name in self .context .layers :
875+ candidate_layer = self .context .layers [candidate_layer_name ]
876+ if layer_name is None or layer_name == candidate_layer_name :
877+ print (f" { candidate_layer_name } " )
878+ if hasattr (candidate_layer .read , "breakpoints" ):
879+ breakpoints_to_remove = set ()
880+ for breakpoint in candidate_layer .read .breakpoints :
881+ if offset is None or offset == breakpoint :
882+ print (f" clearing { breakpoint :#x} " )
883+ breakpoints_to_remove .add (breakpoint )
884+ candidate_layer .read .breakpoints -= breakpoints_to_remove
885+
846886
847887class NullFileHandler (io .BytesIO , interfaces .plugins .FileHandlerInterface ):
848888 """Null FileHandler that swallows files whole without consuming memory"""
0 commit comments