Replace extract_global_symbols script by a more expressive Perl version
authorLaurent Georget <laurent.georget@inria.fr>
Wed, 1 Jul 2015 15:17:03 +0000 (17:17 +0200)
committerLaurent Georget <laurent.georget@inria.fr>
Wed, 1 Jul 2015 15:17:48 +0000 (17:17 +0200)
extract_global_symbols.pl [new file with mode: 0755]
extract_global_symbols.sh [deleted file]

diff --git a/extract_global_symbols.pl b/extract_global_symbols.pl
new file mode 100755 (executable)
index 0000000..5911489
--- /dev/null
@@ -0,0 +1,81 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use File::Find ();
+use File::Basename;
+use Cwd;
+
+# Set the variable $File::Find::dont_use_nlink if you're using AFS,
+# since AFS cheats.
+
+# for the convenience of &wanted calls, including -eval statements:
+use vars qw/*name *dir *prune/;
+*name   = *File::Find::name;
+*dir    = *File::Find::dir;
+*prune  = *File::Find::prune;
+
+sub wanted;
+
+
+print <<'EOF';
+CREATE TABLE global_symbols   (        symbol TEXT,
+dir TEXT,
+file TEXT,
+line INTEGER);
+EOF
+
+# Traverse desired filesystems
+File::Find::find({wanted => \&wanted}, '.');
+
+sub wanted {
+    my ($dev,$ino,$mode,$nlink,$uid,$gid);
+
+    (
+       (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
+       $File::Find::name =~ /^\.\/lib\z/s
+       ||
+       $File::Find::name =~ /^\.\/arch\/x86\/lib\z/s
+       ||
+       $File::Find::name =~ /^\.\/drivers\z/s
+    ) &&
+    ($File::Find::prune = 1)
+    ||
+    (
+       /^.*\.dwo\z/s &&
+       ($nlink || (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_))) &&
+       ! /^.*built-in.*\z/s
+    ) &&
+    look_for_symbols_in_file($name);
+}
+
+
+sub look_for_symbols_in_file
+{
+       my $file = shift;
+       my ($base,$path,$suffix) = fileparse($file,('.dwo'));
+       if (! -e "$base.mod.c" && -e "$base.o")
+       {
+               #print STDERR "$base\n";
+               my $nm_output;
+               open ($nm_output, "-|", "nm -l -g --defined-only --no-sort $base.o");
+               while (<$nm_output>)
+               {
+                       if (/.*\s+T\s+(\w+).*:(\d+)/)
+                       {
+                               # print STDERR $_;
+                               my ($symbol,$line) = ($1,$2);
+                               # Special case for system calls
+                               next if $symbol =~ /^SyS_/;
+                               $symbol =~ s/^sys_/SYSC_/;
+
+                               print "INSERT INTO global_symbols (symbol,dir,file,line) VALUES ('$symbol', '$path', '$base.c', '$line');\n"
+                       }
+               }
+       }
+}
+
+1;
+
+__END__
diff --git a/extract_global_symbols.sh b/extract_global_symbols.sh
deleted file mode 100755 (executable)
index be25b41..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/zsh
-
-cat <<EOF
-CREATE TABLE global_symbols   (        symbol TEXT PRIMARY KEY,
-dir TEXT,
-file TEXT);
-EOF
-
-for i in $(find -name '*.dwo' -a ! -name '*built-in*' -a ! -wholename '*/drivers/*' -a ! -wholename '*/lib/*' ) ; do
-       if [[ ! -e ${i/%.dwo/.mod.c} ]]; then
-               for symbol in $(nm ${i/%.dwo/.o} | awk '$2 == "T" { print $3; }') ; do
-               echo "INSERT INTO global_symbols (symbol,dir,file) VALUES ('${symbol}', '${$(dirname $i)#\.\/}', '$(basename $i .dwo).c');"
-               done
-       fi
-done