Attempt to match new functions by searching for swallowed functions (islands) in a given range. Args: src_index_start (int): start (source) index of an unmatched (source) gap src_index_end (int): end (source) index of an unmatched (source) gap lower_bound
(self, src_index_start, src_index_end, lower_bound, upper_bound)
| 303 | return False |
| 304 | |
| 305 | def attemptMatchSwallow(self, src_index_start, src_index_end, lower_bound, upper_bound): |
| 306 | """Attempt to match new functions by searching for swallowed functions (islands) in a given range. |
| 307 | |
| 308 | Args: |
| 309 | src_index_start (int): start (source) index of an unmatched (source) gap |
| 310 | src_index_end (int): end (source) index of an unmatched (source) gap |
| 311 | lower_bound (int): ea of the lower bound of the gap in the binary address space |
| 312 | upper_bound (int): ea of the upper bound of the gap in the binary address space |
| 313 | |
| 314 | Return Value: |
| 315 | True iff matched at least one function |
| 316 | """ |
| 317 | gap_size = upper_bound - lower_bound |
| 318 | # sanity check - should not happen |
| 319 | if gap_size <= 0: |
| 320 | return False |
| 321 | # check all of the options in the source gap |
| 322 | for src_index in range(src_index_start, src_index_end + 1): |
| 323 | # check for a single xref source function |
| 324 | src_candidate_ctx = self._engine.src_functions_ctx[src_index] |
| 325 | if len(src_candidate_ctx.xrefs) != 1: |
| 326 | continue |
| 327 | # check if the xref was matched already (we can't advance otherwise) |
| 328 | src_parent = list(src_candidate_ctx.xrefs)[0] |
| 329 | if not src_parent.matched(): |
| 330 | continue |
| 331 | # now check if there is a floating chunk inside this gap |
| 332 | bin_parent = src_parent.match |
| 333 | # make sure (sanity check) that bin_parent is not inside our gap |
| 334 | if lower_bound <= bin_parent.ea <= upper_bound: |
| 335 | continue |
| 336 | island_blocks = self._engine.disas.searchIslands(bin_parent.ea, lower_bound, upper_bound) |
| 337 | # Failed to find a match |
| 338 | if island_blocks is None: |
| 339 | return False |
| 340 | # We have a list of linked external blocks, that are linked to the parent function, and were found in our gap => Jackpot |
| 341 | island_ctx = self._engine.disas.analyzeIslandFunction(island_blocks) |
| 342 | island_ctx.preprocess() |
| 343 | # Fix it's externals |
| 344 | bin_internal_calls = [] |
| 345 | bin_external_calls = [] |
| 346 | for call_ea in island_ctx.calls: |
| 347 | if call_ea in self._engine.bin_functions_ctx.keys(): |
| 348 | bin_internal_calls.append(self._engine.bin_functions_ctx[call_ea]) |
| 349 | else: |
| 350 | bin_external_calls.append(call_ea) |
| 351 | island_ctx.calls = bin_internal_calls |
| 352 | island_ctx.externals = bin_external_calls |
| 353 | # score it up and check for a match (no need to filter this option, it's a swallow) |
| 354 | score = island_ctx.compare(src_candidate_ctx, self._engine.logger) |
| 355 | if src_index == src_index_start or src_index == src_index_end: |
| 356 | score += getNeighbourScore() |
| 357 | if score >= MINIMAL_ISLAND_SCORE: |
| 358 | self._engine.bin_functions_ctx[island_ctx.ea] = island_ctx |
| 359 | self._engine.declareMatch(src_candidate_ctx.index, island_ctx.ea, REASON_SWALLOW) |
| 360 | return True |
| 361 | return False |
no test coverage detected