4949#include <linux/fsnotify.h>
5050#include <linux/irq_work.h>
5151#include <linux/workqueue.h>
52+ #include <linux/sort.h>
5253
5354#include <asm/setup.h> /* COMMAND_LINE_SIZE and kaslr_offset() */
5455
@@ -6001,6 +6002,59 @@ struct trace_scratch {
60016002
60026003static DEFINE_MUTEX (scratch_mutex );
60036004
6005+ static int cmp_mod_entry (const void * key , const void * pivot )
6006+ {
6007+ unsigned long addr = (unsigned long )key ;
6008+ const struct trace_mod_entry * ent = pivot ;
6009+
6010+ if (addr >= ent [0 ].mod_addr && addr < ent [1 ].mod_addr )
6011+ return 0 ;
6012+ else
6013+ return addr - ent -> mod_addr ;
6014+ }
6015+
6016+ /**
6017+ * trace_adjust_address() - Adjust prev boot address to current address.
6018+ * @tr: Persistent ring buffer's trace_array.
6019+ * @addr: Address in @tr which is adjusted.
6020+ */
6021+ unsigned long trace_adjust_address (struct trace_array * tr , unsigned long addr )
6022+ {
6023+ struct trace_module_delta * module_delta ;
6024+ struct trace_scratch * tscratch ;
6025+ struct trace_mod_entry * entry ;
6026+ int idx = 0 , nr_entries ;
6027+
6028+ /* If we don't have last boot delta, return the address */
6029+ if (!(tr -> flags & TRACE_ARRAY_FL_LAST_BOOT ))
6030+ return addr ;
6031+
6032+ /* tr->module_delta must be protected by rcu. */
6033+ guard (rcu )();
6034+ tscratch = tr -> scratch ;
6035+ /* if there is no tscrach, module_delta must be NULL. */
6036+ module_delta = READ_ONCE (tr -> module_delta );
6037+ if (!module_delta || tscratch -> entries [0 ].mod_addr > addr )
6038+ return addr + tr -> text_delta ;
6039+
6040+ /* Note that entries must be sorted. */
6041+ nr_entries = tscratch -> nr_entries ;
6042+ if (nr_entries == 1 ||
6043+ tscratch -> entries [nr_entries - 1 ].mod_addr < addr )
6044+ idx = nr_entries - 1 ;
6045+ else {
6046+ entry = __inline_bsearch ((void * )addr ,
6047+ tscratch -> entries ,
6048+ nr_entries - 1 ,
6049+ sizeof (tscratch -> entries [0 ]),
6050+ cmp_mod_entry );
6051+ if (entry )
6052+ idx = entry - tscratch -> entries ;
6053+ }
6054+
6055+ return addr + module_delta -> delta [idx ];
6056+ }
6057+
60046058#ifdef CONFIG_MODULES
60056059static int save_mod (struct module * mod , void * data )
60066060{
@@ -6035,6 +6089,7 @@ static int save_mod(struct module *mod, void *data)
60356089
60366090static void update_last_data (struct trace_array * tr )
60376091{
6092+ struct trace_module_delta * module_delta ;
60386093 struct trace_scratch * tscratch ;
60396094
60406095 if (!(tr -> flags & TRACE_ARRAY_FL_BOOT ))
@@ -6073,6 +6128,9 @@ static void update_last_data(struct trace_array *tr)
60736128 return ;
60746129
60756130 tscratch = tr -> scratch ;
6131+ module_delta = READ_ONCE (tr -> module_delta );
6132+ WRITE_ONCE (tr -> module_delta , NULL );
6133+ kfree_rcu (module_delta , rcu );
60766134
60776135 /* Set the persistent ring buffer meta data to this address */
60786136#ifdef CONFIG_RANDOMIZE_BASE
@@ -9355,10 +9413,51 @@ static struct dentry *trace_instance_dir;
93559413static void
93569414init_tracer_tracefs (struct trace_array * tr , struct dentry * d_tracer );
93579415
9416+ #ifdef CONFIG_MODULES
9417+ static int make_mod_delta (struct module * mod , void * data )
9418+ {
9419+ struct trace_module_delta * module_delta ;
9420+ struct trace_scratch * tscratch ;
9421+ struct trace_mod_entry * entry ;
9422+ struct trace_array * tr = data ;
9423+ int i ;
9424+
9425+ tscratch = tr -> scratch ;
9426+ module_delta = READ_ONCE (tr -> module_delta );
9427+ for (i = 0 ; i < tscratch -> nr_entries ; i ++ ) {
9428+ entry = & tscratch -> entries [i ];
9429+ if (strcmp (mod -> name , entry -> mod_name ))
9430+ continue ;
9431+ if (mod -> state == MODULE_STATE_GOING )
9432+ module_delta -> delta [i ] = 0 ;
9433+ else
9434+ module_delta -> delta [i ] = (unsigned long )mod -> mem [MOD_TEXT ].base
9435+ - entry -> mod_addr ;
9436+ break ;
9437+ }
9438+ return 0 ;
9439+ }
9440+ #else
9441+ static int make_mod_delta (struct module * mod , void * data )
9442+ {
9443+ return 0 ;
9444+ }
9445+ #endif
9446+
9447+ static int mod_addr_comp (const void * a , const void * b , const void * data )
9448+ {
9449+ const struct trace_mod_entry * e1 = a ;
9450+ const struct trace_mod_entry * e2 = b ;
9451+
9452+ return e1 -> mod_addr > e2 -> mod_addr ? 1 : -1 ;
9453+ }
9454+
93589455static void setup_trace_scratch (struct trace_array * tr ,
93599456 struct trace_scratch * tscratch , unsigned int size )
93609457{
9458+ struct trace_module_delta * module_delta ;
93619459 struct trace_mod_entry * entry ;
9460+ int i , nr_entries ;
93629461
93639462 if (!tscratch )
93649463 return ;
@@ -9375,7 +9474,7 @@ static void setup_trace_scratch(struct trace_array *tr,
93759474 goto reset ;
93769475
93779476 /* Check if each module name is a valid string */
9378- for (int i = 0 ; i < tscratch -> nr_entries ; i ++ ) {
9477+ for (i = 0 ; i < tscratch -> nr_entries ; i ++ ) {
93799478 int n ;
93809479
93819480 entry = & tscratch -> entries [i ];
@@ -9389,6 +9488,25 @@ static void setup_trace_scratch(struct trace_array *tr,
93899488 if (n == MODULE_NAME_LEN )
93909489 goto reset ;
93919490 }
9491+
9492+ /* Sort the entries so that we can find appropriate module from address. */
9493+ nr_entries = tscratch -> nr_entries ;
9494+ sort_r (tscratch -> entries , nr_entries , sizeof (struct trace_mod_entry ),
9495+ mod_addr_comp , NULL , NULL );
9496+
9497+ if (IS_ENABLED (CONFIG_MODULES )) {
9498+ module_delta = kzalloc (struct_size (module_delta , delta , nr_entries ), GFP_KERNEL );
9499+ if (!module_delta ) {
9500+ pr_info ("module_delta allocation failed. Not able to decode module address." );
9501+ goto reset ;
9502+ }
9503+ init_rcu_head (& module_delta -> rcu );
9504+ } else
9505+ module_delta = NULL ;
9506+ WRITE_ONCE (tr -> module_delta , module_delta );
9507+
9508+ /* Scan modules to make text delta for modules. */
9509+ module_for_each_mod (make_mod_delta , tr );
93929510 return ;
93939511 reset :
93949512 /* Invalid trace modules */
@@ -10105,16 +10223,20 @@ static void trace_module_remove_evals(struct module *mod)
1010510223static inline void trace_module_remove_evals (struct module * mod ) { }
1010610224#endif /* CONFIG_TRACE_EVAL_MAP_FILE */
1010710225
10108- static void trace_module_record (struct module * mod )
10226+ static void trace_module_record (struct module * mod , bool add )
1010910227{
1011010228 struct trace_array * tr ;
10229+ unsigned long flags ;
1011110230
1011210231 list_for_each_entry (tr , & ftrace_trace_arrays , list ) {
10232+ flags = tr -> flags & (TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT );
1011310233 /* Update any persistent trace array that has already been started */
10114- if ((tr -> flags & (TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT )) ==
10115- TRACE_ARRAY_FL_BOOT ) {
10234+ if (flags == TRACE_ARRAY_FL_BOOT && add ) {
1011610235 guard (mutex )(& scratch_mutex );
1011710236 save_mod (mod , tr );
10237+ } else if (flags & TRACE_ARRAY_FL_LAST_BOOT ) {
10238+ /* Update delta if the module loaded in previous boot */
10239+ make_mod_delta (mod , tr );
1011810240 }
1011910241 }
1012010242}
@@ -10127,10 +10249,11 @@ static int trace_module_notify(struct notifier_block *self,
1012710249 switch (val ) {
1012810250 case MODULE_STATE_COMING :
1012910251 trace_module_add_evals (mod );
10130- trace_module_record (mod );
10252+ trace_module_record (mod , true );
1013110253 break ;
1013210254 case MODULE_STATE_GOING :
1013310255 trace_module_remove_evals (mod );
10256+ trace_module_record (mod , false);
1013410257 break ;
1013510258 }
1013610259
0 commit comments