tracing: Show module names and addresses of last boot
Add the last boot module's names and addresses to the last_boot_info file. This only shows the module information from a previous boot. If the buffer is started and is recording the current boot, this file still will only show "current". ~# cat instances/boot_mapped/last_boot_info 10c00000 [kernel] ffffffffc00ca000 usb_serial_simple ffffffffc00ae000 usbserial ffffffffc008b000 bfq ~# echo function > instances/boot_mapped/current_tracer ~# cat instances/boot_mapped/last_boot_info # Current Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Andrew Morton <akpm@linux-foundation.org> Link: https://lore.kernel.org/20250305164609.299186021@goodmis.org Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
This commit is contained in:
committed by
Steven Rostedt (Google)
parent
fd39e48fe8
commit
1bd25a6f71
+91
-15
@@ -5999,6 +5999,8 @@ struct trace_scratch {
|
||||
struct trace_mod_entry entries[];
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(scratch_mutex);
|
||||
|
||||
static int save_mod(struct module *mod, void *data)
|
||||
{
|
||||
struct trace_array *tr = data;
|
||||
@@ -6039,6 +6041,7 @@ static void update_last_data(struct trace_array *tr)
|
||||
flex_array_size(tscratch, entries, tscratch->nr_entries));
|
||||
tscratch->nr_entries = 0;
|
||||
|
||||
guard(mutex)(&scratch_mutex);
|
||||
module_for_each_mod(save_mod, tr);
|
||||
}
|
||||
|
||||
@@ -6876,15 +6879,47 @@ tracing_total_entries_read(struct file *filp, char __user *ubuf,
|
||||
return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
tracing_last_boot_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
|
||||
{
|
||||
struct trace_array *tr = filp->private_data;
|
||||
struct trace_scratch *tscratch = tr->scratch;
|
||||
struct seq_buf seq;
|
||||
char buf[64];
|
||||
#define LAST_BOOT_HEADER ((void *)1)
|
||||
|
||||
seq_buf_init(&seq, buf, 64);
|
||||
static void *l_next(struct seq_file *m, void *v, loff_t *pos)
|
||||
{
|
||||
struct trace_array *tr = m->private;
|
||||
struct trace_scratch *tscratch = tr->scratch;
|
||||
unsigned int index = *pos;
|
||||
|
||||
(*pos)++;
|
||||
|
||||
if (*pos == 1)
|
||||
return LAST_BOOT_HEADER;
|
||||
|
||||
/* Only show offsets of the last boot data */
|
||||
if (!tscratch || !(tr->flags & TRACE_ARRAY_FL_LAST_BOOT))
|
||||
return NULL;
|
||||
|
||||
/* *pos 0 is for the header, 1 is for the first module */
|
||||
index--;
|
||||
|
||||
if (index >= tscratch->nr_entries)
|
||||
return NULL;
|
||||
|
||||
return &tscratch->entries[index];
|
||||
}
|
||||
|
||||
static void *l_start(struct seq_file *m, loff_t *pos)
|
||||
{
|
||||
mutex_lock(&scratch_mutex);
|
||||
|
||||
return l_next(m, NULL, pos);
|
||||
}
|
||||
|
||||
static void l_stop(struct seq_file *m, void *p)
|
||||
{
|
||||
mutex_unlock(&scratch_mutex);
|
||||
}
|
||||
|
||||
static void show_last_boot_header(struct seq_file *m, struct trace_array *tr)
|
||||
{
|
||||
struct trace_scratch *tscratch = tr->scratch;
|
||||
|
||||
/*
|
||||
* Do not leak KASLR address. This only shows the KASLR address of
|
||||
@@ -6894,11 +6929,52 @@ tracing_last_boot_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t
|
||||
* should not be the same as the current boot.
|
||||
*/
|
||||
if (tscratch && (tr->flags & TRACE_ARRAY_FL_LAST_BOOT))
|
||||
seq_buf_printf(&seq, "%lx\t[kernel]\n", tscratch->kaslr_addr);
|
||||
seq_printf(m, "%lx\t[kernel]\n", tscratch->kaslr_addr);
|
||||
else
|
||||
seq_buf_puts(&seq, "# Current\n");
|
||||
seq_puts(m, "# Current\n");
|
||||
}
|
||||
|
||||
return simple_read_from_buffer(ubuf, cnt, ppos, buf, seq_buf_used(&seq));
|
||||
static int l_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct trace_array *tr = m->private;
|
||||
struct trace_mod_entry *entry = v;
|
||||
|
||||
if (v == LAST_BOOT_HEADER) {
|
||||
show_last_boot_header(m, tr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
seq_printf(m, "%lx\t%s\n", entry->mod_addr, entry->mod_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct seq_operations last_boot_seq_ops = {
|
||||
.start = l_start,
|
||||
.next = l_next,
|
||||
.stop = l_stop,
|
||||
.show = l_show,
|
||||
};
|
||||
|
||||
static int tracing_last_boot_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct trace_array *tr = inode->i_private;
|
||||
struct seq_file *m;
|
||||
int ret;
|
||||
|
||||
ret = tracing_check_open_get_tr(tr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = seq_open(file, &last_boot_seq_ops);
|
||||
if (ret) {
|
||||
trace_array_put(tr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
m = file->private_data;
|
||||
m->private = tr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tracing_buffer_meta_open(struct inode *inode, struct file *filp)
|
||||
@@ -7527,10 +7603,10 @@ static const struct file_operations trace_time_stamp_mode_fops = {
|
||||
};
|
||||
|
||||
static const struct file_operations last_boot_fops = {
|
||||
.open = tracing_open_generic_tr,
|
||||
.read = tracing_last_boot_read,
|
||||
.llseek = generic_file_llseek,
|
||||
.release = tracing_release_generic_tr,
|
||||
.open = tracing_last_boot_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = tracing_seq_release,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_TRACER_SNAPSHOT
|
||||
|
||||
Reference in New Issue
Block a user