Skip to content

Commit 783a3cb

Browse files
committed
Support for local debug directories
1 parent 7dd6f31 commit 783a3cb

File tree

3 files changed

+102
-15
lines changed

3 files changed

+102
-15
lines changed

rust/examples/dwarf/dwarf_import/src/helpers.rs

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
use std::path::PathBuf;
1516
use std::{
1617
collections::HashMap,
1718
ops::Deref,
@@ -303,9 +304,7 @@ pub(crate) fn get_expr_value<R: Reader<Offset = usize>>(
303304
}
304305

305306

306-
pub(crate) fn download_debug_info(view: &BinaryView) -> Result<Ref<BinaryView>, String> {
307-
let settings = Settings::new("");
308-
307+
pub(crate) fn get_build_id(view: &BinaryView) -> Result<String, String> {
309308
let mut build_id: Option<String> = None;
310309

311310
if let Ok(raw_view) = view.raw_view() {
@@ -351,14 +350,24 @@ pub(crate) fn download_debug_info(view: &BinaryView) -> Result<Ref<BinaryView>,
351350
}
352351
}
353352

354-
if build_id.is_none() {
355-
return Err("Failed to get build id".to_string());
353+
if let Some(x) = build_id {
354+
Ok(x)
356355
}
356+
else {
357+
Err("Failed to get build id".to_string())
358+
}
359+
}
360+
361+
362+
pub(crate) fn download_debug_info(view: &BinaryView) -> Result<Ref<BinaryView>, String> {
363+
let settings = Settings::new("");
364+
365+
let build_id = get_build_id(view)?;
357366

358367
let debug_server_urls = settings.get_string_list("network.debuginfodServers", Some(view), None);
359368

360369
for debug_server_url in debug_server_urls.iter() {
361-
let artifact_url = format!("{}/buildid/{}/debuginfo", debug_server_url, build_id.as_ref().unwrap());
370+
let artifact_url = format!("{}/buildid/{}/debuginfo", debug_server_url, build_id);
362371

363372
// Download from remote
364373
let (tx, rx) = mpsc::channel();
@@ -421,3 +430,47 @@ pub(crate) fn download_debug_info(view: &BinaryView) -> Result<Ref<BinaryView>,
421430
}
422431
return Err("Could not find a server with debug info for this file".to_string());
423432
}
433+
434+
435+
pub(crate) fn load_debug_info_for_build_id(view: &BinaryView) -> Result<Option<Ref<BinaryView>>, String> {
436+
let settings = Settings::new("");
437+
let debug_info_paths = settings.get_string_list("analysis.debugInfo.debugDirectories", Some(view), None);
438+
if debug_info_paths.is_empty() {
439+
return Ok(None)
440+
}
441+
442+
for debug_info_path in debug_info_paths.into_iter() {
443+
if let Ok(path) = PathBuf::from_str(&debug_info_path.to_string())
444+
{
445+
let build_id = get_build_id(view)?;
446+
let elf_path = path
447+
.join(&build_id[..2])
448+
.join(&build_id[2..])
449+
.join("elf");
450+
451+
let debug_ext_path = path
452+
.join(&build_id[..2])
453+
.join(format!("{}.debug", &build_id[2..]));
454+
455+
let options = "{\"analysis.debugInfo.internal\": false}";
456+
let final_path = if debug_ext_path.exists() {
457+
debug_ext_path
458+
}
459+
else if elf_path.exists() {
460+
elf_path
461+
}
462+
else {
463+
// No paths exist
464+
return Ok(None)
465+
};
466+
return Ok(
467+
binaryninja::load_with_options(
468+
final_path.to_string_lossy().to_string(),
469+
false,
470+
Some(options)
471+
)
472+
);
473+
}
474+
}
475+
Ok(None)
476+
}

rust/examples/dwarf/dwarf_import/src/lib.rs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,9 @@ struct DWARFParser;
270270

271271
impl CustomDebugInfoParser for DWARFParser {
272272
fn is_valid(&self, view: &BinaryView) -> bool {
273-
dwarfreader::is_valid(view) || dwarfreader::can_use_debuginfod(view)
273+
dwarfreader::is_valid(view) ||
274+
dwarfreader::can_use_build_id(view) ||
275+
dwarfreader::can_use_debuginfod(view)
274276
}
275277

276278
fn parse_info(
@@ -280,13 +282,29 @@ impl CustomDebugInfoParser for DWARFParser {
280282
debug_file: &BinaryView,
281283
progress: Box<dyn Fn(usize, usize) -> Result<(), ()>>,
282284
) -> bool {
283-
let external_file = if !dwarfreader::is_valid(bv) && dwarfreader::can_use_debuginfod(bv) {
284-
if let Ok(debug_view) = helpers::download_debug_info(bv) {
285-
Some(debug_view)
286-
} else {
285+
let external_file = if !dwarfreader::is_valid(bv) {
286+
if dwarfreader::can_use_build_id(bv) {
287+
if let Ok(Some(debug_view)) = helpers::load_debug_info_for_build_id(bv) {
288+
Some(debug_view)
289+
}
290+
else {
291+
if dwarfreader::can_use_debuginfod(bv) {
292+
if let Ok(debug_view) = helpers::download_debug_info(bv) {
293+
Some(debug_view)
294+
} else {
295+
None
296+
}
297+
}
298+
else {
299+
None
300+
}
301+
}
302+
}
303+
else {
287304
None
288305
}
289-
} else {
306+
}
307+
else {
290308
None
291309
};
292310

@@ -333,6 +351,18 @@ pub extern "C" fn CorePluginInit() -> bool {
333351
}"#,
334352
);
335353

354+
settings.register_setting_json(
355+
"analysis.debugInfo.debugDirectories",
356+
r#"{
357+
"title" : "Debug File Directories",
358+
"type" : "array",
359+
"elementType" : "string",
360+
"default" : [],
361+
"description" : "Paths to folder containing debug info stored by build id.",
362+
"ignore" : []
363+
}"#,
364+
);
365+
336366
DebugInfoParser::register("DWARF", DWARFParser {});
337367
true
338368
}

rust/examples/dwarf/shared/src/lib.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,14 @@ pub fn is_raw_dwo_dwarf(view: &BinaryView) -> bool {
5454
}
5555

5656
pub fn can_use_debuginfod(view: &BinaryView) -> bool {
57+
can_use_build_id(view) &&
58+
Settings::new("")
59+
.get_bool("network.enableDebuginfod", Some(view), None)
60+
}
61+
62+
pub fn can_use_build_id(view: &BinaryView) -> bool {
5763
if let Ok(raw_view) = view.raw_view() {
58-
if raw_view.section_by_name(".note.gnu.build-id").is_ok() {
59-
return Settings::new("").get_bool("network.enableDebuginfod", Some(view), None);
60-
}
64+
return raw_view.section_by_name(".note.gnu.build-id").is_ok()
6165
}
6266
false
6367
}

0 commit comments

Comments
 (0)