bootstrap/core/debuggers/gdb.rs
1use std::borrow::Cow;
2use std::path::Path;
3
4use crate::core::android;
5use crate::core::builder::Builder;
6use crate::utils::exec::BootstrapCommand;
7
8pub(crate) struct Gdb<'a> {
9 pub(crate) gdb: Cow<'a, Path>,
10}
11
12pub(crate) fn discover_gdb<'a>(
13 builder: &'a Builder<'_>,
14 android: Option<&android::Android>,
15) -> Option<Gdb<'a>> {
16 // If there's an explicitly-configured gdb, use that.
17 if let Some(gdb) = builder.config.gdb.as_deref() {
18 // FIXME(Zalathar): Consider returning None if gdb is an empty string,
19 // as a way to explicitly disable ambient gdb discovery.
20 let gdb = Cow::Borrowed(gdb);
21 return Some(Gdb { gdb });
22 }
23
24 // Otherwise, fall back to whatever gdb is sitting around in PATH.
25 // (That's the historical behavior, but maybe we should require opt-in?)
26
27 let gdb: Cow<'_, Path> = match android {
28 Some(android::Android { android_cross_path, .. }) => {
29 android_cross_path.join("bin/gdb").into()
30 }
31 None => Path::new("gdb").into(),
32 };
33
34 // Check whether an ambient gdb exists, by running `gdb --version`.
35 let output = {
36 let mut gdb_command = BootstrapCommand::new(gdb.as_ref()).allow_failure();
37 gdb_command.arg("--version");
38 gdb_command.run_capture(builder)
39 };
40
41 if output.is_success() { Some(Gdb { gdb }) } else { None }
42}