52
52
my $suppress_dmesg = 0; # Don't show dmesg in output.
53
53
my $squash_by_path = 0; # Summary report grouped by absolute path.
54
54
my $squash_by_filename = 0; # Summary report grouped by filename.
55
+ my $kallsyms_file = " " ; # Kernel symbols file.
55
56
my $kernel_config_file = " " ; # Kernel configuration file.
56
57
my $opt_32bit = 0; # Scan 32-bit kernel.
57
58
my $page_offset_32bit = 0; # Page offset for 32-bit kernel.
58
59
60
+ my @kallsyms = ();
61
+
59
62
# Skip these absolute paths.
60
63
my @skip_abs = (
61
64
' /proc/kmsg' ,
@@ -96,6 +99,8 @@ sub help
96
99
--squash-by-path Show one result per unique path.
97
100
--squash-by-filename Show one result per unique filename.
98
101
--kernel-config-file=<file> Kernel configuration file (e.g /boot/config)
102
+ --kallsyms=<file> Read kernel symbol addresses from file (for
103
+ scanning binary files).
99
104
--32-bit Scan 32-bit kernel.
100
105
--page-offset-32-bit=o Page offset (for 32-bit kernel 0xABCD1234).
101
106
-d, --debug Display debugging output.
@@ -116,6 +121,7 @@ sub help
116
121
' squash-by-path' => \$squash_by_path ,
117
122
' squash-by-filename' => \$squash_by_filename ,
118
123
' raw' => \$raw ,
124
+ ' kallsyms=s' => \$kallsyms_file ,
119
125
' kernel-config-file=s' => \$kernel_config_file ,
120
126
' 32-bit' => \$opt_32bit ,
121
127
' page-offset-32-bit=o' => \$page_offset_32bit ,
@@ -156,6 +162,25 @@ sub help
156
162
select $fh ;
157
163
}
158
164
165
+ if ($kallsyms_file ) {
166
+ open my $fh , ' <' , $kallsyms_file or die " $0 : $kallsyms_file : $! \n " ;
167
+ while (<$fh >) {
168
+ chomp ;
169
+ my @entry = split / /, $_ ;
170
+ my $addr_text = $entry [0];
171
+ if ($addr_text !~ / ^0/ ) {
172
+ # TODO: Why is hex() so impossibly slow?
173
+ my $addr = hex ($addr_text );
174
+ my $symbol = $entry [2];
175
+ # Only keep kernel text addresses.
176
+ my $long = pack (" J" , $addr );
177
+ my $entry = [$long , $symbol ];
178
+ push @kallsyms , $entry ;
179
+ }
180
+ }
181
+ close $fh ;
182
+ }
183
+
159
184
parse_dmesg();
160
185
walk(@DIRS );
161
186
@@ -447,6 +472,25 @@ sub timed_parse_file
447
472
}
448
473
}
449
474
475
+ sub parse_binary
476
+ {
477
+ my ($file ) = @_ ;
478
+
479
+ open my $fh , " <:raw" , $file or return ;
480
+ local $/ = undef ;
481
+ my $bytes = <$fh >;
482
+ close $fh ;
483
+
484
+ foreach my $entry (@kallsyms ) {
485
+ my $addr = $entry -> [0];
486
+ my $symbol = $entry -> [1];
487
+ my $offset = index ($bytes , $addr );
488
+ if ($offset != -1) {
489
+ printf (" $file : $symbol @ $offset \n " );
490
+ }
491
+ }
492
+ }
493
+
450
494
sub parse_file
451
495
{
452
496
my ($file ) = @_ ;
@@ -456,6 +500,15 @@ sub parse_file
456
500
}
457
501
458
502
if (! -T $file ) {
503
+ if ($file =~ m | ^/sys/kernel/btf/| or
504
+ $file =~ m | ^/sys/devices/pci| or
505
+ $file =~ m | ^/sys/firmware/efi/efivars/| or
506
+ $file =~ m | ^/proc/bus/pci/| ) {
507
+ return ;
508
+ }
509
+ if (scalar @kallsyms > 0) {
510
+ parse_binary($file );
511
+ }
459
512
return ;
460
513
}
461
514
0 commit comments