mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-07 03:40:15 +00:00
parent
011a521968
commit
d1a750c528
@ -45,7 +45,7 @@ GDB commands are useful:
|
|||||||
The <monitor> configuration can host optional <policy> nodes referring to
|
The <monitor> configuration can host optional <policy> nodes referring to
|
||||||
inferiors by their respective labels. For example:
|
inferiors by their respective labels. For example:
|
||||||
|
|
||||||
! <monitor>
|
! <monitor max_response="2K">
|
||||||
! <policy label="first-test-log" wait="no" stop="yes" wx="no"/>
|
! <policy label="first-test-log" wait="no" stop="yes" wx="no"/>
|
||||||
! </monitor>
|
! </monitor>
|
||||||
|
|
||||||
@ -67,6 +67,11 @@ The enabling of the 'wx' attribute prompts the monitor to map the executable
|
|||||||
code of the monitored component as writeable memory, allowing the patching of
|
code of the monitored component as writeable memory, allowing the patching of
|
||||||
text segment by GDB, which is needed for using breakpoints.
|
text segment by GDB, which is needed for using breakpoints.
|
||||||
|
|
||||||
|
The "max_response" attribute of the <monitor> node specifies the
|
||||||
|
maximum payload size of a GDB command response packet. The default value
|
||||||
|
is 2048 bytes. It can be increased for higher memory dump throughput, provided
|
||||||
|
that the terminal session component has the capacity to receive the configured
|
||||||
|
amount plus GDB protocol overhead and potential asynchronous notifications.
|
||||||
|
|
||||||
RAM wiping
|
RAM wiping
|
||||||
----------
|
----------
|
||||||
|
@ -153,6 +153,10 @@ struct Monitor::Gdb::State : Noncopyable
|
|||||||
|
|
||||||
bool gdb_connected { false };
|
bool gdb_connected { false };
|
||||||
|
|
||||||
|
struct Max_response { size_t num_bytes; };
|
||||||
|
|
||||||
|
Max_response max_response;
|
||||||
|
|
||||||
void flush(Inferior_pd &pd)
|
void flush(Inferior_pd &pd)
|
||||||
{
|
{
|
||||||
if (_current.constructed() && _current->pd.id() == pd.id())
|
if (_current.constructed() && _current->pd.id() == pd.id())
|
||||||
@ -266,9 +270,12 @@ struct Monitor::Gdb::State : Noncopyable
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
State(Inferiors &inferiors, Memory_accessor &memory_accessor)
|
State(Inferiors &inferiors, Memory_accessor &memory_accessor,
|
||||||
|
Xml_node const &config)
|
||||||
:
|
:
|
||||||
inferiors(inferiors), _memory_accessor(memory_accessor)
|
inferiors(inferiors), _memory_accessor(memory_accessor),
|
||||||
|
max_response(config.sub_node("monitor").attribute_value("max_response",
|
||||||
|
Number_of_bytes(2048)))
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -343,12 +350,12 @@ struct qXfer : Command_with_separator
|
|||||||
{
|
{
|
||||||
size_t offset, len;
|
size_t offset, len;
|
||||||
|
|
||||||
static Window from_args(Const_byte_range_ptr const &args)
|
static Window from_args(Const_byte_range_ptr const &args,
|
||||||
|
State::Max_response max_response)
|
||||||
{
|
{
|
||||||
return { .offset = comma_separated_hex_value(args, 0, 0UL),
|
return { .offset = comma_separated_hex_value(args, 0, 0UL),
|
||||||
/* terminal_crosslink currently buffers 4096 bytes */
|
|
||||||
.len = min(comma_separated_hex_value(args, 1, 0UL),
|
.len = min(comma_separated_hex_value(args, 1, 0UL),
|
||||||
2048UL) };
|
max_response.num_bytes) };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -368,14 +375,14 @@ struct qXfer : Command_with_separator
|
|||||||
|
|
||||||
with_skipped_prefix(args, "features:read:target.xml:", [&] (Const_byte_range_ptr const &args) {
|
with_skipped_prefix(args, "features:read:target.xml:", [&] (Const_byte_range_ptr const &args) {
|
||||||
Raw_data_ptr const total_bytes { _binary_gdb_target_xml_start, _binary_gdb_target_xml_end };
|
Raw_data_ptr const total_bytes { _binary_gdb_target_xml_start, _binary_gdb_target_xml_end };
|
||||||
_send_window(out, total_bytes, Window::from_args(args));
|
_send_window(out, total_bytes, Window::from_args(args, state.max_response));
|
||||||
handled = true;
|
handled = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
with_skipped_prefix(args, "threads:read::", [&] (Const_byte_range_ptr const &args) {
|
with_skipped_prefix(args, "threads:read::", [&] (Const_byte_range_ptr const &args) {
|
||||||
State::Thread_list const thread_list(state.inferiors);
|
State::Thread_list const thread_list(state.inferiors);
|
||||||
thread_list.with_bytes([&] (Const_byte_range_ptr const &bytes) {
|
thread_list.with_bytes([&] (Const_byte_range_ptr const &bytes) {
|
||||||
_send_window(out, bytes, Window::from_args(args)); });
|
_send_window(out, bytes, Window::from_args(args, state.max_response)); });
|
||||||
handled = true;
|
handled = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -383,7 +390,7 @@ struct qXfer : Command_with_separator
|
|||||||
if (state.current_defined()) {
|
if (state.current_defined()) {
|
||||||
State::Memory_map const memory_map(state._current->pd);
|
State::Memory_map const memory_map(state._current->pd);
|
||||||
memory_map.with_bytes([&] (Const_byte_range_ptr const &bytes) {
|
memory_map.with_bytes([&] (Const_byte_range_ptr const &bytes) {
|
||||||
_send_window(out, bytes, Window::from_args(args)); });
|
_send_window(out, bytes, Window::from_args(args, state.max_response)); });
|
||||||
} else
|
} else
|
||||||
gdb_response(out, [&] (Output &out) {
|
gdb_response(out, [&] (Output &out) {
|
||||||
print(out, "l"); });
|
print(out, "l"); });
|
||||||
@ -638,26 +645,32 @@ struct m : Command_without_separator
|
|||||||
void execute(State &state, Const_byte_range_ptr const &args, Output &out) const override
|
void execute(State &state, Const_byte_range_ptr const &args, Output &out) const override
|
||||||
{
|
{
|
||||||
addr_t const addr = comma_separated_hex_value(args, 0, addr_t(0));
|
addr_t const addr = comma_separated_hex_value(args, 0, addr_t(0));
|
||||||
size_t const len = comma_separated_hex_value(args, 1, 0UL);
|
|
||||||
|
/* GDB's 'm' command encodes memory as hex, two characters per byte. */
|
||||||
|
size_t const len = min(comma_separated_hex_value(args, 1, 0UL),
|
||||||
|
state.max_response.num_bytes / 2);
|
||||||
|
|
||||||
gdb_response(out, [&] (Output &out) {
|
gdb_response(out, [&] (Output &out) {
|
||||||
|
|
||||||
/*
|
for (size_t pos = 0; pos < len; ) {
|
||||||
* The terminal_crosslink component uses a buffer of 4 KiB and
|
|
||||||
* some space is needed for asynchronous notifications and
|
|
||||||
* protocol overhead. GDB's 'm' command encodes memory as hex,
|
|
||||||
* two characters per byte. Hence, a dump of max. 1 KiB is
|
|
||||||
* currently possible.
|
|
||||||
*/
|
|
||||||
char buf[1024] { };
|
|
||||||
|
|
||||||
Byte_range_ptr const dst { buf, min(sizeof(buf), len) };
|
char chunk[min(16*1024UL, len)] { };
|
||||||
|
|
||||||
size_t const read_len =
|
size_t const remain_len = len - pos;
|
||||||
state.read_memory(Memory_accessor::Virt_addr { addr }, dst);
|
size_t const num_bytes = min(sizeof(chunk), remain_len);
|
||||||
|
|
||||||
for (unsigned i = 0; i < read_len; i++)
|
size_t const read_len =
|
||||||
print(out, Gdb_hex(buf[i]));
|
state.read_memory(Memory_accessor::Virt_addr { addr + pos },
|
||||||
|
Byte_range_ptr(chunk, num_bytes));
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < read_len; i++)
|
||||||
|
print(out, Gdb_hex(chunk[i]));
|
||||||
|
|
||||||
|
pos += read_len;
|
||||||
|
|
||||||
|
if (read_len < num_bytes)
|
||||||
|
break;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -197,9 +197,9 @@ struct Monitor::Main : Sandbox::State_handler,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Gdb_stub(Env &env, Inferiors &inferiors)
|
Gdb_stub(Env &env, Inferiors &inferiors, Xml_node const &config)
|
||||||
:
|
:
|
||||||
_env(env), _state(inferiors, _memory_accessor)
|
_env(env), _state(inferiors, _memory_accessor, config)
|
||||||
{
|
{
|
||||||
_terminal.read_avail_sigh(_terminal_read_avail_handler);
|
_terminal.read_avail_sigh(_terminal_read_avail_handler);
|
||||||
_handle_terminal_read_avail();
|
_handle_terminal_read_avail();
|
||||||
@ -342,7 +342,8 @@ struct Monitor::Main : Sandbox::State_handler,
|
|||||||
if (_reporter.constructed())
|
if (_reporter.constructed())
|
||||||
_reporter->enabled(reporter_enabled);
|
_reporter->enabled(reporter_enabled);
|
||||||
|
|
||||||
_gdb_stub.conditional(config.has_sub_node("monitor"), _env, _inferiors);
|
_gdb_stub.conditional(config.has_sub_node("monitor"), _env, _inferiors,
|
||||||
|
config);
|
||||||
|
|
||||||
_apply_monitor_config_to_inferiors();
|
_apply_monitor_config_to_inferiors();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user