Skip to content

Commit 7c4402e

Browse files
committed
[DWARF] Fix loading Fat Mach-O debug files
1 parent 2c759a5 commit 7c4402e

File tree

1 file changed

+66
-12
lines changed
  • plugins/dwarf/dwarf_import/src

1 file changed

+66
-12
lines changed

plugins/dwarf/dwarf_import/src/lib.rs

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ use binaryninja::logger::Logger;
4747
use helpers::{get_build_id, load_debug_info_for_build_id};
4848
use iset::IntervalMap;
4949
use log::{debug, error, warn};
50+
use object::read::macho::FatArch;
5051
use object::{Object, ObjectSection};
5152

5253
trait ReaderType: Reader<Offset = usize> {}
@@ -650,6 +651,60 @@ fn parse_dwarf(
650651
Ok(debug_info_builder)
651652
}
652653

654+
fn parse_data_to_object<'a>(
655+
data: &'a [u8],
656+
target_bv: &BinaryView,
657+
) -> Result<object::File<'a>, String> {
658+
// Try to parse as normal file, fall back to parsing as fat macho and selecting the right arch from the target bv
659+
if let Ok(o) = object::File::parse(data) {
660+
return Ok(o);
661+
}
662+
663+
if let Some(bv_arch) = target_bv.default_arch() {
664+
let target_obj_arch = match bv_arch.name().as_str() {
665+
"x86" => object::Architecture::I386,
666+
"x86_64" => object::Architecture::X86_64,
667+
"aarch64" => object::Architecture::Aarch64,
668+
"armv7" | "thumb2" => object::Architecture::Arm,
669+
"mips32" => object::Architecture::Mips,
670+
"mips64" => object::Architecture::Mips64,
671+
"ppc" => object::Architecture::PowerPc,
672+
"ppc64" => object::Architecture::PowerPc64,
673+
_ => {
674+
return Err(format!(
675+
"Unable to determine architecture to load from \"{}\"",
676+
bv_arch.name()
677+
));
678+
}
679+
};
680+
if let Ok(o) = object::read::macho::MachOFatFile32::parse(data) {
681+
for arch in o.arches() {
682+
if arch.architecture() == target_obj_arch {
683+
let arch_data = arch
684+
.data(data)
685+
.map_err(|e| format!("Failed to read FatArch32: {}", e))?;
686+
return object::File::parse(arch_data)
687+
.map_err(|e| format!("Failed to parse object from FatArch32 data: {}", e));
688+
}
689+
}
690+
}
691+
692+
if let Ok(o) = object::read::macho::MachOFatFile64::parse(data) {
693+
for arch in o.arches() {
694+
if arch.architecture() == target_obj_arch {
695+
let arch_data = arch
696+
.data(data)
697+
.map_err(|e| format!("Failed to read FatArch64: {}", e))?;
698+
return object::File::parse(arch_data)
699+
.map_err(|e| format!("Failed to parse object from FatArch64 data: {}", e));
700+
}
701+
}
702+
}
703+
}
704+
705+
Err("Unable to load object from data".to_string())
706+
}
707+
653708
struct DWARFParser;
654709

655710
impl CustomDebugInfoParser for DWARFParser {
@@ -713,10 +768,10 @@ impl CustomDebugInfoParser for DWARFParser {
713768
return false;
714769
};
715770

716-
let debug_file = match object::File::parse(debug_data_vec.as_slice()) {
771+
let debug_file = match parse_data_to_object(debug_data_vec.as_slice(), bv) {
717772
Ok(x) => x,
718773
Err(e) => {
719-
log::error!("Failed to parse bv: {}", e);
774+
log::error!("Failed to parse debug data: {}", e);
720775
return false;
721776
}
722777
};
@@ -753,16 +808,15 @@ impl CustomDebugInfoParser for DWARFParser {
753808
},
754809
);
755810

756-
let sup_file =
757-
sup_view_data
758-
.as_ref()
759-
.and_then(|data| match object::File::parse(data.as_slice()) {
760-
Ok(x) => Some(x),
761-
Err(e) => {
762-
log::error!("Failed to parse supplementary bv: {}", e);
763-
None
764-
}
765-
});
811+
let sup_file = sup_view_data.as_ref().and_then(|data| {
812+
match parse_data_to_object(data.as_slice(), bv) {
813+
Ok(x) => Some(x),
814+
Err(e) => {
815+
log::error!("Failed to parse supplementary debug data: {}", e);
816+
None
817+
}
818+
}
819+
});
766820

767821
// If we have a sup file, verify its build id with the expected build id, else warn
768822
if let Some(sup_file) = &sup_file {

0 commit comments

Comments
 (0)