summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-07-20 20:38:21 -0400
committerMason Reed <mason@vector35.com>2025-07-21 12:14:44 -0400
commit34216a4e6724c80c018b8cfa6f133a270728f095 (patch)
tree1d91869de73578e63049ed2bf2d1f18f83b864ce /plugins
parentde2020a70a7a972a38c2a9eae9e6d2b8f2770af9 (diff)
[WARP] Consult segments unconditionally when constructing relocatable regions
This removes more barriers for those working with firmware to use WARP, previously if you had defined any sections (such as a vector interrupt table) then backed segments would end up being marked non-relocatable. This, combined with the use of ELF intermediate object files created inconsistent GUID's, using the segments backing the real functions fixes this.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/warp/src/lib.rs33
1 files changed, 15 insertions, 18 deletions
diff --git a/plugins/warp/src/lib.rs b/plugins/warp/src/lib.rs
index bea85cdd..0a4a758c 100644
--- a/plugins/warp/src/lib.rs
+++ b/plugins/warp/src/lib.rs
@@ -400,30 +400,27 @@ pub fn is_address_relocatable(relocatable_regions: &[Range<u64>], address: u64)
// TODO: This might need to be configurable, in that case we better remove this function.
/// Get the relocatable regions of the view.
///
-/// Currently, this is all the sections, however, this might be refined later.
+/// 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>> {
- // NOTE: We cannot use segments here as there will be a zero-based segment.
- let mut ranges: Vec<_> = view
- .sections()
+ // 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
+ // of function GUIDs for binaries which have no or bad section definitions, common of firmware.
+ let mut ranges = view.segments()
.iter()
- .map(|s| Range {
- start: s.start(),
- end: s.end(),
- })
- .collect();
+ .filter(|s| s.address_range().start != 0)
+ .map(|s| s.address_range())
+ .collect::<Vec<_>>();
- // If the only section available is the synthetic one, fallback to using the segments.
- // NOTE: This should only happen for firmware, and it should be _fine_ considering that we
- // do not use segments for the case where we are based at some zero offset. The user should have
- // based the image somewhere reasonably.
- // TODO: Restrict this to only when image base is above some value?
- if ranges.len() <= 1 {
- let segment_ranges = view
- .segments()
+ 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.
+ ranges = view.sections()
.iter()
.map(|s| s.address_range())
.collect::<Vec<_>>();
- ranges.extend(segment_ranges);
}
ranges