Add a breakpoint in the given module at the given PC in that module. If the requested PC does not fall exactly on an opcode boundary, the breakpoint is "slipped" forward to the next available opcode PC. No effect if the breakpoint is already set.
(&mut self, module: &Module, pc: ModulePC)
| 1085 | /// |
| 1086 | /// No effect if the breakpoint is already set. |
| 1087 | pub fn add_breakpoint(&mut self, module: &Module, pc: ModulePC) -> Result<()> { |
| 1088 | let frame_table = module |
| 1089 | .frame_table() |
| 1090 | .expect("Frame table must be present when guest-debug is enabled"); |
| 1091 | let actual_pc = frame_table.nearest_breakpoint(pc).unwrap_or(pc); |
| 1092 | let requested_key = BreakpointKey::from_raw(module, pc); |
| 1093 | let actual_key = BreakpointKey::from_raw(module, actual_pc); |
| 1094 | |
| 1095 | if actual_pc != pc { |
| 1096 | log::trace!("slipping breakpoint from {requested_key:?} to {actual_key:?}"); |
| 1097 | self.state |
| 1098 | .breakpoint_redirects |
| 1099 | .insert(requested_key, actual_key); |
| 1100 | } |
| 1101 | |
| 1102 | let refcount = self.state.breakpoints.entry(actual_key).or_insert(0); |
| 1103 | *refcount += 1; |
| 1104 | if *refcount == 1 { |
| 1105 | // First reference: actually patch the code. |
| 1106 | let mem = |
| 1107 | Self::get_code_memory(self.state, self.registry, &mut self.dirty_modules, module)?; |
| 1108 | let patches = frame_table.lookup_breakpoint_patches_by_pc(actual_pc); |
| 1109 | Self::patch(patches, mem, true); |
| 1110 | } |
| 1111 | Ok(()) |
| 1112 | } |
| 1113 | |
| 1114 | /// Remove a breakpoint in the given module at the given PC in |
| 1115 | /// that module. |
no test coverage detected