diff options
| author | Mason Reed <mason@vector35.com> | 2026-03-04 11:12:57 -0800 |
|---|---|---|
| committer | Mason Reed <35282038+emesare@users.noreply.github.com> | 2026-03-24 18:46:48 -0700 |
| commit | 61e4e7e772b9c427bf190f8557afc466d0488848 (patch) | |
| tree | 7a10f38191efc1189b0208fb8fdfe17fdbf1cf93 /plugins/warp | |
| parent | cc5f4dfc9d970ccd21bbd6f13b7235bc21990031 (diff) | |
[WARP] Fix relocatable region selection failing to fallback to section collection
Previously we only selected relocatable regions from the list of sections, now that we use the segment list we need a way to fallback to the
section list of the segment information is problematic (e.g. based at zero), that fallback has not been triggering as there is a segment for the synthetic sections.
Now when a user opens a firmware with only a single zero based segment it should fallback to the sections _and_ alert the user that they should fill out the section map (since that job is left to the user)
Diffstat (limited to 'plugins/warp')
| -rw-r--r-- | plugins/warp/src/lib.rs | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/plugins/warp/src/lib.rs b/plugins/warp/src/lib.rs index 1e622d58..6889c79d 100644 --- a/plugins/warp/src/lib.rs +++ b/plugins/warp/src/lib.rs @@ -25,6 +25,8 @@ use warp::signature::basic_block::BasicBlockGUID; use warp::signature::function::{Function, FunctionGUID}; use warp::signature::variable::FunctionVariable; +use binaryninja::section::Semantics; +use binaryninja::segment::Segment; /// Re-export the warp crate that is used, this is useful for consumers of this crate. pub use warp; @@ -418,6 +420,15 @@ pub fn is_address_relocatable(relocatable_regions: &[Range<u64>], address: u64) /// Currently, segments are used by default, however, if the only segment is based at 0, then we fall /// back to using sections. pub fn relocatable_regions(view: &BinaryView) -> Vec<Range<u64>> { + // We need to filter out the segment for the synthetic builtins, otherwise we can't get to + // the path where we look at sections for relocatable regions, this segment is always created + // for now we just filter, but in the future I would like to have something less jank. + let is_synthetic_segment = |segment: &Segment| { + view.sections_at(segment.address_range().start) + .iter() + .any(|sec| sec.auto_defined() && sec.semantics() == Semantics::External) + }; + // NOTE: We used to use sections because the image base for some object files would start // at zero, masking non-relocatable instructions, since then we have started adjusting the // image base to 0x10000 or higher so we can use segments directly, which improves the accuracy @@ -426,13 +437,14 @@ pub fn relocatable_regions(view: &BinaryView) -> Vec<Range<u64>> { .segments() .iter() .filter(|s| s.address_range().start != 0) + .filter(|s| !is_synthetic_segment(s)) .map(|s| s.address_range()) .collect::<Vec<_>>(); if ranges.is_empty() { // Realistically only happens if the only defined segment was based at 0, in which case - // we hope the user has set up correct sections. If not we are going to be masking off too many - // or too little instructions. + // we hope the user has set up correct sections. If not, we are going to be masking off too + // many or too little instructions. ranges = view .sections() .iter() |
