mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-18 12:06:43 +00:00
OSDK GDB server args with QEMU-style options
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
43e3f8cf6b
commit
ab8b6afee5
5
Makefile
5
Makefile
@ -199,8 +199,7 @@ endif
|
|||||||
|
|
||||||
.PHONY: gdb_server
|
.PHONY: gdb_server
|
||||||
gdb_server: initramfs $(CARGO_OSDK)
|
gdb_server: initramfs $(CARGO_OSDK)
|
||||||
@cargo osdk run $(CARGO_OSDK_ARGS) --gdb-server --gdb-wait-client --gdb-vsc \
|
@cargo osdk run $(CARGO_OSDK_ARGS) --gdb-server wait-client,vscode,addr=:$(GDB_TCP_PORT)
|
||||||
--gdb-server-addr :$(GDB_TCP_PORT)
|
|
||||||
|
|
||||||
.PHONY: gdb_client
|
.PHONY: gdb_client
|
||||||
gdb_client: $(CARGO_OSDK)
|
gdb_client: $(CARGO_OSDK)
|
||||||
@ -208,7 +207,7 @@ gdb_client: $(CARGO_OSDK)
|
|||||||
|
|
||||||
.PHONY: profile_server
|
.PHONY: profile_server
|
||||||
profile_server: initramfs $(CARGO_OSDK)
|
profile_server: initramfs $(CARGO_OSDK)
|
||||||
@cargo osdk run $(CARGO_OSDK_ARGS) --gdb-server --gdb-server-addr :$(GDB_TCP_PORT)
|
@cargo osdk run $(CARGO_OSDK_ARGS) --gdb-server addr=:$(GDB_TCP_PORT)
|
||||||
|
|
||||||
.PHONY: profile_client
|
.PHONY: profile_client
|
||||||
profile_client: $(CARGO_OSDK)
|
profile_client: $(CARGO_OSDK)
|
||||||
|
@ -15,16 +15,15 @@ Most options are the same as those of `cargo osdk build`.
|
|||||||
Refer to the [documentation](build.md) of `cargo osdk build`
|
Refer to the [documentation](build.md) of `cargo osdk build`
|
||||||
for more details.
|
for more details.
|
||||||
|
|
||||||
Options related with debugging:
|
Additionally, when running the kernel using QEMU, we can setup the QEMU as a
|
||||||
|
debug server using option `--gdb-server`. This option supports an additional
|
||||||
|
comma separated configuration list:
|
||||||
|
|
||||||
- `--gdb-server`: Enable QEMU GDB server for debugging.
|
- `addr=ADDR`: the network or unix socket address on which the GDB server listens
|
||||||
- `--gdb-wait-client`: Let the QEMU GDB server wait for the client connection before execution.
|
(default: `.osdk-gdb-socket`, a local UNIX socket);
|
||||||
- `--gdb-vsc`: Generate a '.vscode/launch.json' for debugging kernel with Visual Studio Code
|
- `wait-client`: let the GDB server wait for the GDB client before execution;
|
||||||
(only works when QEMU GDB server is enabled, i.e., `--gdb-server`).
|
- `vscode`: generate a '.vscode/launch.json' for debugging with Visual Studio Code
|
||||||
Requires [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb).
|
(Requires [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)).
|
||||||
- `--gdb-server-addr <ADDR>`: The network address on which the GDB server listens,
|
|
||||||
it can be either a path for the UNIX domain socket or a TCP port on an IP address.
|
|
||||||
[default: `.osdk-gdb-socket`(a local UNIX socket)]
|
|
||||||
|
|
||||||
See [Debug Command](debug.md) to interact with the GDB server in terminal.
|
See [Debug Command](debug.md) to interact with the GDB server in terminal.
|
||||||
|
|
||||||
@ -33,17 +32,17 @@ See [Debug Command](debug.md) to interact with the GDB server in terminal.
|
|||||||
Launch a debug server via QEMU with an unix socket stub, e.g. `.debug`:
|
Launch a debug server via QEMU with an unix socket stub, e.g. `.debug`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo osdk run --gdb-server --gdb-server-addr .debug
|
cargo osdk run --gdb-server addr=.debug
|
||||||
```
|
```
|
||||||
|
|
||||||
Launch a debug server via QEMU with a TCP stub, e.g., `localhost:1234`:
|
Launch a debug server via QEMU with a TCP stub, e.g., `localhost:1234`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo osdk run --gdb-server --gdb-server-addr :1234
|
cargo osdk run --gdb-server addr=:1234
|
||||||
```
|
```
|
||||||
|
|
||||||
Launch a debug server via QEMU and use VSCode to interact:
|
Launch a debug server via QEMU and use VSCode to interact with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo osdk run --gdb-server --gdb-vsc --gdb-server-addr :1234
|
cargo osdk run --gdb-server wait-client,vscode,addr=:1234
|
||||||
```
|
```
|
||||||
|
@ -37,7 +37,7 @@ pub fn main() {
|
|||||||
OsdkSubcommand::Run(run_args) => {
|
OsdkSubcommand::Run(run_args) => {
|
||||||
execute_run_command(
|
execute_run_command(
|
||||||
&load_config(&run_args.common_args),
|
&load_config(&run_args.common_args),
|
||||||
&run_args.gdb_server_args,
|
run_args.gdb_server.as_deref(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
OsdkSubcommand::Debug(debug_args) => {
|
OsdkSubcommand::Debug(debug_args) => {
|
||||||
@ -168,44 +168,20 @@ pub struct BuildArgs {
|
|||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct RunArgs {
|
pub struct RunArgs {
|
||||||
#[command(flatten)]
|
|
||||||
pub gdb_server_args: GdbServerArgs,
|
|
||||||
#[command(flatten)]
|
|
||||||
pub common_args: CommonArgs,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Args, Clone, Default)]
|
|
||||||
pub struct GdbServerArgs {
|
|
||||||
#[arg(
|
#[arg(
|
||||||
long = "gdb-server",
|
long = "gdb-server",
|
||||||
help = "Enable the QEMU GDB server for debugging",
|
help = "Enable the QEMU GDB server for debugging\n\
|
||||||
default_value_t
|
This option supports an additional comma separated configuration list:\n\t \
|
||||||
|
addr=ADDR: the network or unix socket address on which the GDB server listens, \
|
||||||
|
`.osdk-gdb-socket` by default;\n\t \
|
||||||
|
wait-client: let the GDB server wait for the GDB client before execution;\n\t \
|
||||||
|
vscode: generate a '.vscode/launch.json' for debugging with Visual Studio Code.",
|
||||||
|
value_name = "[addr=ADDR][,wait-client][,vscode]",
|
||||||
|
default_missing_value = ""
|
||||||
)]
|
)]
|
||||||
pub enabled: bool,
|
pub gdb_server: Option<String>,
|
||||||
#[arg(
|
#[command(flatten)]
|
||||||
long = "gdb-wait-client",
|
pub common_args: CommonArgs,
|
||||||
help = "Let the QEMU GDB server wait for the GDB client before execution",
|
|
||||||
default_value_t,
|
|
||||||
requires = "enabled"
|
|
||||||
)]
|
|
||||||
pub wait_client: bool,
|
|
||||||
#[arg(
|
|
||||||
long = "gdb-vsc",
|
|
||||||
help = "Generate a '.vscode/launch.json' for debugging with Visual Studio Code \
|
|
||||||
(only works when '--enable-gdb' is enabled)",
|
|
||||||
default_value_t,
|
|
||||||
requires = "enabled"
|
|
||||||
)]
|
|
||||||
pub vsc_launch_file: bool,
|
|
||||||
#[arg(
|
|
||||||
long = "gdb-server-addr",
|
|
||||||
help = "The network address on which the GDB server listens, \
|
|
||||||
it can be either a path for the UNIX domain socket or a TCP port on an IP address.",
|
|
||||||
value_name = "ADDR",
|
|
||||||
default_value = ".osdk-gdb-socket",
|
|
||||||
requires = "enabled"
|
|
||||||
)]
|
|
||||||
pub host_addr: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
|
@ -18,10 +18,9 @@ pub fn execute_debug_command(_profile: &str, args: &DebugArgs) {
|
|||||||
|
|
||||||
let mut gdb = Command::new("gdb");
|
let mut gdb = Command::new("gdb");
|
||||||
gdb.args([
|
gdb.args([
|
||||||
|
format!("{}", file_path.display()).as_str(),
|
||||||
"-ex",
|
"-ex",
|
||||||
format!("target remote {}", remote).as_str(),
|
format!("target remote {}", remote).as_str(),
|
||||||
"-ex",
|
|
||||||
format!("file {}", file_path.display()).as_str(),
|
|
||||||
]);
|
]);
|
||||||
gdb.status().unwrap();
|
gdb.status().unwrap();
|
||||||
}
|
}
|
||||||
|
@ -1,64 +1,29 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use std::process::exit;
|
||||||
|
|
||||||
|
use vsc::VscLaunchConfig;
|
||||||
|
|
||||||
use super::{build::create_base_and_cached_build, util::DEFAULT_TARGET_RELPATH};
|
use super::{build::create_base_and_cached_build, util::DEFAULT_TARGET_RELPATH};
|
||||||
use crate::{
|
use crate::{
|
||||||
cli::GdbServerArgs,
|
|
||||||
config::{scheme::ActionChoice, Config},
|
config::{scheme::ActionChoice, Config},
|
||||||
|
error::Errno,
|
||||||
|
error_msg,
|
||||||
util::{get_current_crate_info, get_target_directory},
|
util::{get_current_crate_info, get_target_directory},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn execute_run_command(config: &Config, gdb_server_args: &GdbServerArgs) {
|
pub fn execute_run_command(config: &Config, gdb_server_args: Option<&str>) {
|
||||||
if gdb_server_args.enabled {
|
|
||||||
use std::env;
|
|
||||||
env::set_var(
|
|
||||||
"RUSTFLAGS",
|
|
||||||
env::var("RUSTFLAGS").unwrap_or_default() + " -g",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let cargo_target_directory = get_target_directory();
|
let cargo_target_directory = get_target_directory();
|
||||||
let osdk_output_directory = cargo_target_directory.join(DEFAULT_TARGET_RELPATH);
|
let osdk_output_directory = cargo_target_directory.join(DEFAULT_TARGET_RELPATH);
|
||||||
let target_name = get_current_crate_info().name;
|
let target_name = get_current_crate_info().name;
|
||||||
|
|
||||||
let mut config = config.clone();
|
let mut config = config.clone();
|
||||||
if gdb_server_args.enabled {
|
|
||||||
let qemu_gdb_args = {
|
|
||||||
let gdb_stub_addr = gdb_server_args.host_addr.as_str();
|
|
||||||
match gdb::stub_type_of(gdb_stub_addr) {
|
|
||||||
gdb::StubAddrType::Unix => {
|
|
||||||
format!(
|
|
||||||
" -chardev socket,path={},server=on,wait=off,id=gdb0 -gdb chardev:gdb0",
|
|
||||||
gdb_stub_addr
|
|
||||||
)
|
|
||||||
}
|
|
||||||
gdb::StubAddrType::Tcp => {
|
|
||||||
format!(
|
|
||||||
" -gdb tcp:{}",
|
|
||||||
gdb::tcp_addr_util::format_tcp_addr(gdb_stub_addr)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
config.run.qemu.args += &qemu_gdb_args;
|
|
||||||
|
|
||||||
if gdb_server_args.wait_client {
|
let _vsc_launch_file = if let Some(gdb_server_str) = gdb_server_args {
|
||||||
config.run.qemu.args += " -S";
|
adapt_for_gdb_server(&mut config, gdb_server_str)
|
||||||
}
|
} else {
|
||||||
|
None
|
||||||
// Ensure debug info added when debugging in the release profile.
|
};
|
||||||
if config.run.build.profile.contains("release") {
|
|
||||||
config
|
|
||||||
.run
|
|
||||||
.build
|
|
||||||
.override_configs
|
|
||||||
.push(format!("profile.{}.debug=true", config.run.build.profile));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let _vsc_launch_file = gdb_server_args.vsc_launch_file.then(|| {
|
|
||||||
vsc::check_gdb_config(gdb_server_args);
|
|
||||||
let profile = super::util::profile_name_adapter(&config.run.build.profile);
|
|
||||||
vsc::VscLaunchConfig::new(profile, &gdb_server_args.host_addr)
|
|
||||||
});
|
|
||||||
|
|
||||||
let default_bundle_directory = osdk_output_directory.join(target_name);
|
let default_bundle_directory = osdk_output_directory.join(target_name);
|
||||||
let bundle = create_base_and_cached_build(
|
let bundle = create_base_and_cached_build(
|
||||||
@ -73,6 +38,82 @@ pub fn execute_run_command(config: &Config, gdb_server_args: &GdbServerArgs) {
|
|||||||
bundle.run(&config, ActionChoice::Run);
|
bundle.run(&config, ActionChoice::Run);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn adapt_for_gdb_server(config: &mut Config, gdb_server_str: &str) -> Option<VscLaunchConfig> {
|
||||||
|
let gdb_server_args = GdbServerArgs::from_str(gdb_server_str);
|
||||||
|
|
||||||
|
// Add GDB server arguments to QEMU.
|
||||||
|
let qemu_gdb_args = {
|
||||||
|
let gdb_stub_addr = gdb_server_args.host_addr.as_str();
|
||||||
|
match gdb::stub_type_of(gdb_stub_addr) {
|
||||||
|
gdb::StubAddrType::Unix => {
|
||||||
|
format!(
|
||||||
|
" -chardev socket,path={},server=on,wait=off,id=gdb0 -gdb chardev:gdb0",
|
||||||
|
gdb_stub_addr
|
||||||
|
)
|
||||||
|
}
|
||||||
|
gdb::StubAddrType::Tcp => {
|
||||||
|
format!(
|
||||||
|
" -gdb tcp:{}",
|
||||||
|
gdb::tcp_addr_util::format_tcp_addr(gdb_stub_addr)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
config.run.qemu.args += &qemu_gdb_args;
|
||||||
|
|
||||||
|
if gdb_server_args.wait_client {
|
||||||
|
config.run.qemu.args += " -S";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure debug info added when debugging in the release profile.
|
||||||
|
if config.run.build.profile.contains("release") {
|
||||||
|
config
|
||||||
|
.run
|
||||||
|
.build
|
||||||
|
.override_configs
|
||||||
|
.push(format!("profile.{}.debug=true", config.run.build.profile));
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_server_args.vsc_launch_file.then(|| {
|
||||||
|
vsc::check_gdb_config(&gdb_server_args);
|
||||||
|
let profile = super::util::profile_name_adapter(&config.run.build.profile);
|
||||||
|
vsc::VscLaunchConfig::new(profile, &gdb_server_args.host_addr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GdbServerArgs {
|
||||||
|
host_addr: String,
|
||||||
|
wait_client: bool,
|
||||||
|
vsc_launch_file: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GdbServerArgs {
|
||||||
|
fn from_str(args: &str) -> Self {
|
||||||
|
let mut host_addr = ".osdk-gdb-socket".to_string();
|
||||||
|
let mut wait_client = false;
|
||||||
|
let mut vsc_launch_file = false;
|
||||||
|
|
||||||
|
for arg in args.split(",") {
|
||||||
|
let kv = arg.split('=').collect::<Vec<_>>();
|
||||||
|
match kv.as_slice() {
|
||||||
|
["addr", addr] => host_addr = addr.to_string(),
|
||||||
|
["wait-client"] => wait_client = true,
|
||||||
|
["vscode"] => vsc_launch_file = true,
|
||||||
|
_ => {
|
||||||
|
error_msg!("Invalid GDB server argument: {}", arg);
|
||||||
|
exit(Errno::Cli as _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GdbServerArgs {
|
||||||
|
host_addr,
|
||||||
|
wait_client,
|
||||||
|
vsc_launch_file,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod gdb {
|
mod gdb {
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum StubAddrType {
|
pub enum StubAddrType {
|
||||||
@ -115,7 +156,6 @@ mod gdb {
|
|||||||
|
|
||||||
mod vsc {
|
mod vsc {
|
||||||
use crate::{
|
use crate::{
|
||||||
cli::GdbServerArgs,
|
|
||||||
commands::util::bin_file_name,
|
commands::util::bin_file_name,
|
||||||
util::{get_cargo_metadata, get_current_crate_info},
|
util::{get_cargo_metadata, get_current_crate_info},
|
||||||
};
|
};
|
||||||
@ -125,7 +165,7 @@ mod vsc {
|
|||||||
path::Path,
|
path::Path,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::gdb;
|
use super::{gdb, GdbServerArgs};
|
||||||
|
|
||||||
const VSC_DIR: &str = ".vscode";
|
const VSC_DIR: &str = ".vscode";
|
||||||
|
|
||||||
@ -174,6 +214,7 @@ mod vsc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for VscLaunchConfig {
|
impl Drop for VscLaunchConfig {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// remove generated files
|
// remove generated files
|
||||||
@ -209,14 +250,6 @@ mod vsc {
|
|||||||
use crate::{error::Errno, error_msg};
|
use crate::{error::Errno, error_msg};
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
if !args.enabled {
|
|
||||||
error_msg!(
|
|
||||||
"No need for a VSCode launch file without launching GDB server,\
|
|
||||||
pass '-h' for help"
|
|
||||||
);
|
|
||||||
exit(Errno::ParseMetadata as _);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check GDB server address
|
// check GDB server address
|
||||||
let gdb_stub_addr = args.host_addr.as_str();
|
let gdb_stub_addr = args.host_addr.as_str();
|
||||||
if gdb_stub_addr.is_empty() {
|
if gdb_stub_addr.is_empty() {
|
||||||
@ -224,7 +257,9 @@ mod vsc {
|
|||||||
exit(Errno::ParseMetadata as _);
|
exit(Errno::ParseMetadata as _);
|
||||||
}
|
}
|
||||||
if gdb::stub_type_of(gdb_stub_addr) != gdb::StubAddrType::Tcp {
|
if gdb::stub_type_of(gdb_stub_addr) != gdb::StubAddrType::Tcp {
|
||||||
error_msg!("Non-TCP GDB server address is not supported under '--gdb-vsc' currently");
|
error_msg!(
|
||||||
|
"Non-TCP GDB server address is not supported under '--gdb-server vscode' currently"
|
||||||
|
);
|
||||||
exit(Errno::ParseMetadata as _);
|
exit(Errno::ParseMetadata as _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,15 @@
|
|||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Errno {
|
pub enum Errno {
|
||||||
CreateCrate = 1,
|
Cli = 1,
|
||||||
GetMetadata = 2,
|
CreateCrate = 2,
|
||||||
AddRustToolchain = 3,
|
GetMetadata = 3,
|
||||||
ParseMetadata = 4,
|
AddRustToolchain = 4,
|
||||||
ExecuteCommand = 5,
|
ParseMetadata = 5,
|
||||||
BuildCrate = 6,
|
ExecuteCommand = 6,
|
||||||
RunBundle = 7,
|
BuildCrate = 7,
|
||||||
BadCrateName = 8,
|
RunBundle = 8,
|
||||||
|
BadCrateName = 9,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print error message to console
|
/// Print error message to console
|
||||||
|
@ -82,9 +82,7 @@ mod qemu_gdb_feature {
|
|||||||
let mut instance = cargo_osdk([
|
let mut instance = cargo_osdk([
|
||||||
"run",
|
"run",
|
||||||
"--gdb-server",
|
"--gdb-server",
|
||||||
"--gdb-wait-client",
|
format!("addr={},wait-client", unix_socket.as_str()).as_str(),
|
||||||
"--gdb-server-addr",
|
|
||||||
unix_socket.as_str(),
|
|
||||||
]);
|
]);
|
||||||
instance.current_dir(&workspace.os_dir());
|
instance.current_dir(&workspace.os_dir());
|
||||||
|
|
||||||
@ -112,8 +110,8 @@ mod qemu_gdb_feature {
|
|||||||
let mut gdb = Command::new("gdb");
|
let mut gdb = Command::new("gdb");
|
||||||
gdb.args(["-ex", format!("target remote {}", addr).as_str()]);
|
gdb.args(["-ex", format!("target remote {}", addr).as_str()]);
|
||||||
gdb.write_stdin("\n")
|
gdb.write_stdin("\n")
|
||||||
.write_stdin("c\n")
|
.write_stdin("quit\n")
|
||||||
.write_stdin("quit\n");
|
.write_stdin("y\n");
|
||||||
gdb.assert().success();
|
gdb.assert().success();
|
||||||
}
|
}
|
||||||
mod vsc {
|
mod vsc {
|
||||||
@ -132,18 +130,15 @@ mod qemu_gdb_feature {
|
|||||||
let mut instance = cargo_osdk([
|
let mut instance = cargo_osdk([
|
||||||
"run",
|
"run",
|
||||||
"--gdb-server",
|
"--gdb-server",
|
||||||
"--gdb-wait-client",
|
format!("wait-client,vscode,addr={}", addr).as_str(),
|
||||||
"--gdb-vsc",
|
|
||||||
"--gdb-server-addr",
|
|
||||||
addr,
|
|
||||||
]);
|
]);
|
||||||
instance.current_dir(&workspace.os_dir());
|
instance.current_dir(&workspace.os_dir());
|
||||||
|
|
||||||
let dir = workspace.os_dir();
|
let dir = workspace.os_dir();
|
||||||
let bin_file_path = Path::new(&workspace.os_dir())
|
let bin_file_path = Path::new(&workspace.os_dir())
|
||||||
.join("target")
|
.join("target")
|
||||||
.join("x86_64-unknown-none")
|
.join("osdk")
|
||||||
.join("debug")
|
.join(kernel_name)
|
||||||
.join(format!("{}-osdk-bin", kernel_name));
|
.join(format!("{}-osdk-bin", kernel_name));
|
||||||
let _gdb = std::thread::spawn(move || {
|
let _gdb = std::thread::spawn(move || {
|
||||||
while !bin_file_path.exists() {
|
while !bin_file_path.exists() {
|
||||||
|
Reference in New Issue
Block a user