Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unintuitive, costly side effects in ComplexBlock.get_mode() #518

Open
whyitfor opened this issue Nov 17, 2024 · 0 comments
Open

Unintuitive, costly side effects in ComplexBlock.get_mode() #518

whyitfor opened this issue Nov 17, 2024 · 0 comments

Comments

@whyitfor
Copy link
Contributor

whyitfor commented Nov 17, 2024

What is the problem? (Here is where you provide a complete Traceback.)
ComplexBlock.get_mode() has an unintuitive side-effect, namely, that it unpacks the complex block:

...
await self.resource.unpack()
bb_modes = {bb.mode for bb in await self.get_basic_blocks()}

This can have a cascading effect of things being unpacked (or attempted to be unpacked). For example, if you run resource.auto_run(all_analyzers=True) on a ComplexBlock, the ComplexBlockSymbolAnalyzer will run, which tries to get the mode, causing the ComplexBlock to be unpacked.

It is generally desirable to have workflows that do not rely on a ComplexBlock always being unpacked into basic blocks. For example, PatchFromSourceModifier only needs to know the mode and size of the complex block; forcing this modifier to unpack all complex blocks is prohibitively expensive.

Please provide some information about your environment.
Any OFRAK environment.

If you've discovered it, what is the root cause of the problem?
See above.

How often does the issue happen?

What are the steps to reproduce the issue?
With logging.INFO, run complex_block.resource.auto_run(all_analyzers=True) on any complex block to see this:

> /ofrak-u-boot/decomp.py(33)extract_decomp()
     32             import ipdb; ipdb.set_trace()
---> 33             await complex_block.resource.auto_run(all_analyzers=True)
     34

ipdb> c
[ job_service.py:  123] JOB ed33810f357447cd808c174b9a6f8240 - Running ComplexBlockSymbolAnalyzer on resource 02be68f728134741aa98d60058aa57eb
[ job_service.py:  123] JOB ed33810f357447cd808c174b9a6f8240 - Running DecompilationAnalyzer on resource 02be68f728134741aa98d60058aa57eb
[ job_service.py:  123] JOB ed33810f357447cd808c174b9a6f8240 - Running DecompilationAnalysisIdentifier on resource 02be68f728134741aa98d60058aa57eb
[ job_service.py:  528] JOB ed33810f357447cd808c174b9a6f8240 - Finished running DecompilationAnalysisIdentifier on 02be68f728134741aa98d60058aa57eb:
	Modified resources: 02be68f728134741aa98d60058aa57eb
[ job_service.py:  123] JOB ed33810f357447cd808c174b9a6f8240 - Running LinkableSymbolIdentifier on resource 02be68f728134741aa98d60058aa57eb
[ job_service.py:  528] JOB ed33810f357447cd808c174b9a6f8240 - Finished running LinkableSymbolIdentifier on 02be68f728134741aa98d60058aa57eb:
	Modified resources: 02be68f728134741aa98d60058aa57eb
[ job_service.py:  123] JOB ed33810f357447cd808c174b9a6f8240 - Running ComplexBlockUnpacker on resource 02be68f728134741aa98d60058aa57eb
[ job_service.py:  528] JOB ed33810f357447cd808c174b9a6f8240 - Finished running DecompilationAnalyzer on 02be68f728134741aa98d60058aa57eb:
	Modified resources: 97f4ea1fce1043de81d839bd36c9f9c9,02be68f728134741aa98d60058aa57eb
[ job_service.py:  528] JOB ed33810f357447cd808c174b9a6f8240 - Finished running ComplexBlockUnpacker on 02be68f728134741aa98d60058aa57eb:
	Modified resources: 97f4ea1fce1043de81d839bd36c9f9c9,f27dd734f9214753bda624555c034a6c,02be68f728134741aa98d60058aa57eb
	Created resources: f27dd734f9214753bda624555c034a6c
[ job_service.py:  528] JOB ed33810f357447cd808c174b9a6f8240 - Finished running ComplexBlockSymbolAnalyzer on 02be68f728134741aa98d60058aa57eb:
	Modified resources: f27dd734f9214753bda624555c034a6c,02be68f728134741aa98d60058aa57eb

We tell OFRAK to only run Analyzers -- because of ComplexBlock.get_mode side effects, we end up running 5 components, only 2 of which are analyzers:

  • ComplexBlockSymbolAnalyzer
  • DecompilationAnalyzer
  • DecompilationAnalysisIdentifier
  • LinkableSymbolIdentifier
  • ComplexBlockUnpacker

How would you implement this fix?

  1. ComplexBlock.get_mode() currently unpacks, then checks every BasicBlock for the mode (and raises an error if they do not match). It seems that a simpler implementation of ComplexBlock.get_mode() could simply be one where CodeRegionUnpacker populates the mode of the entrypoint as it gets the ComplexBlock's size. This would likely work for most use cases when the mode of the complex block is needed.

  2. More generally, it is worth reflecting on what, if any, side effects ResourceView methods can/should have.

Are there any (reasonable) alternative approaches?
Probably.

Are you interested in implementing it yourself?
Perhaps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant