1*4882a593Smuzhiyun#!/usr/bin/perl 2*4882a593Smuzhiyun# 3*4882a593Smuzhiyun# namespace.pl. Mon Aug 30 2004 4*4882a593Smuzhiyun# 5*4882a593Smuzhiyun# Perform a name space analysis on the linux kernel. 6*4882a593Smuzhiyun# 7*4882a593Smuzhiyun# Copyright Keith Owens <kaos@ocs.com.au>. GPL. 8*4882a593Smuzhiyun# 9*4882a593Smuzhiyun# Invoke by changing directory to the top of the kernel object 10*4882a593Smuzhiyun# tree then namespace.pl, no parameters. 11*4882a593Smuzhiyun# 12*4882a593Smuzhiyun# Tuned for 2.1.x kernels with the new module handling, it will 13*4882a593Smuzhiyun# work with 2.0 kernels as well. 14*4882a593Smuzhiyun# 15*4882a593Smuzhiyun# Last change 2.6.9-rc1, adding support for separate source and object 16*4882a593Smuzhiyun# trees. 17*4882a593Smuzhiyun# 18*4882a593Smuzhiyun# The source must be compiled/assembled first, the object files 19*4882a593Smuzhiyun# are the primary input to this script. Incomplete or missing 20*4882a593Smuzhiyun# objects will result in a flawed analysis. Compile both vmlinux 21*4882a593Smuzhiyun# and modules. 22*4882a593Smuzhiyun# 23*4882a593Smuzhiyun# Even with complete objects, treat the result of the analysis 24*4882a593Smuzhiyun# with caution. Some external references are only used by 25*4882a593Smuzhiyun# certain architectures, others with certain combinations of 26*4882a593Smuzhiyun# configuration parameters. Ideally the source should include 27*4882a593Smuzhiyun# something like 28*4882a593Smuzhiyun# 29*4882a593Smuzhiyun# #ifndef CONFIG_... 30*4882a593Smuzhiyun# static 31*4882a593Smuzhiyun# #endif 32*4882a593Smuzhiyun# symbol_definition; 33*4882a593Smuzhiyun# 34*4882a593Smuzhiyun# so the symbols are defined as static unless a particular 35*4882a593Smuzhiyun# CONFIG_... requires it to be external. 36*4882a593Smuzhiyun# 37*4882a593Smuzhiyun# A symbol that is suffixed with '(export only)' has these properties 38*4882a593Smuzhiyun# 39*4882a593Smuzhiyun# * It is global. 40*4882a593Smuzhiyun# * It is marked EXPORT_SYMBOL or EXPORT_SYMBOL_GPL, either in the same 41*4882a593Smuzhiyun# source file or a different source file. 42*4882a593Smuzhiyun# * Given the current .config, nothing uses the symbol. 43*4882a593Smuzhiyun# 44*4882a593Smuzhiyun# The symbol is a candidate for conversion to static, plus removal of the 45*4882a593Smuzhiyun# export. But be careful that a different .config might use the symbol. 46*4882a593Smuzhiyun# 47*4882a593Smuzhiyun# 48*4882a593Smuzhiyun# Name space analysis and cleanup is an iterative process. You cannot 49*4882a593Smuzhiyun# expect to find all the problems in a single pass. 50*4882a593Smuzhiyun# 51*4882a593Smuzhiyun# * Identify possibly unnecessary global declarations, verify that they 52*4882a593Smuzhiyun# really are unnecessary and change them to static. 53*4882a593Smuzhiyun# * Compile and fix up gcc warnings about static, removing dead symbols 54*4882a593Smuzhiyun# as necessary. 55*4882a593Smuzhiyun# * make clean and rebuild with different configs (especially 56*4882a593Smuzhiyun# CONFIG_MODULES=n) to see which symbols are being defined when the 57*4882a593Smuzhiyun# config does not require them. These symbols bloat the kernel object 58*4882a593Smuzhiyun# for no good reason, which is frustrating for embedded systems. 59*4882a593Smuzhiyun# * Wrap config sensitive symbols in #ifdef CONFIG_foo, as long as the 60*4882a593Smuzhiyun# code does not get too ugly. 61*4882a593Smuzhiyun# * Repeat the name space analysis until you can live with with the 62*4882a593Smuzhiyun# result. 63*4882a593Smuzhiyun# 64*4882a593Smuzhiyun 65*4882a593Smuzhiyunuse warnings; 66*4882a593Smuzhiyunuse strict; 67*4882a593Smuzhiyunuse File::Find; 68*4882a593Smuzhiyunuse File::Spec; 69*4882a593Smuzhiyun 70*4882a593Smuzhiyunmy $nm = ($ENV{'NM'} || "nm") . " -p"; 71*4882a593Smuzhiyunmy $objdump = ($ENV{'OBJDUMP'} || "objdump") . " -s -j .comment"; 72*4882a593Smuzhiyunmy $srctree = File::Spec->curdir(); 73*4882a593Smuzhiyunmy $objtree = File::Spec->curdir(); 74*4882a593Smuzhiyun$srctree = File::Spec->rel2abs($ENV{'srctree'}) if (exists($ENV{'srctree'})); 75*4882a593Smuzhiyun$objtree = File::Spec->rel2abs($ENV{'objtree'}) if (exists($ENV{'objtree'})); 76*4882a593Smuzhiyun 77*4882a593Smuzhiyunif ($#ARGV != -1) { 78*4882a593Smuzhiyun print STDERR "usage: $0 takes no parameters\n"; 79*4882a593Smuzhiyun die("giving up\n"); 80*4882a593Smuzhiyun} 81*4882a593Smuzhiyun 82*4882a593Smuzhiyunmy %nmdata = (); # nm data for each object 83*4882a593Smuzhiyunmy %def = (); # all definitions for each name 84*4882a593Smuzhiyunmy %ksymtab = (); # names that appear in __ksymtab_ 85*4882a593Smuzhiyunmy %ref = (); # $ref{$name} exists if there is a true external reference to $name 86*4882a593Smuzhiyunmy %export = (); # $export{$name} exists if there is an EXPORT_... of $name 87*4882a593Smuzhiyun 88*4882a593Smuzhiyunmy %nmexception = ( 89*4882a593Smuzhiyun 'fs/ext3/bitmap' => 1, 90*4882a593Smuzhiyun 'fs/ext4/bitmap' => 1, 91*4882a593Smuzhiyun 'arch/x86/lib/thunk_32' => 1, 92*4882a593Smuzhiyun 'arch/x86/lib/cmpxchg' => 1, 93*4882a593Smuzhiyun 'arch/x86/vdso/vdso32/note' => 1, 94*4882a593Smuzhiyun 'lib/irq_regs' => 1, 95*4882a593Smuzhiyun 'usr/initramfs_data' => 1, 96*4882a593Smuzhiyun 'drivers/scsi/aic94xx/aic94xx_dump' => 1, 97*4882a593Smuzhiyun 'drivers/scsi/libsas/sas_dump' => 1, 98*4882a593Smuzhiyun 'lib/dec_and_lock' => 1, 99*4882a593Smuzhiyun 'drivers/ide/ide-probe-mini' => 1, 100*4882a593Smuzhiyun 'usr/initramfs_data' => 1, 101*4882a593Smuzhiyun 'drivers/acpi/acpia/exdump' => 1, 102*4882a593Smuzhiyun 'drivers/acpi/acpia/rsdump' => 1, 103*4882a593Smuzhiyun 'drivers/acpi/acpia/nsdumpdv' => 1, 104*4882a593Smuzhiyun 'drivers/acpi/acpia/nsdump' => 1, 105*4882a593Smuzhiyun 'arch/ia64/sn/kernel/sn2/io' => 1, 106*4882a593Smuzhiyun 'arch/ia64/kernel/gate-data' => 1, 107*4882a593Smuzhiyun 'security/capability' => 1, 108*4882a593Smuzhiyun 'fs/ntfs/sysctl' => 1, 109*4882a593Smuzhiyun 'fs/jfs/jfs_debug' => 1, 110*4882a593Smuzhiyun); 111*4882a593Smuzhiyun 112*4882a593Smuzhiyunmy %nameexception = ( 113*4882a593Smuzhiyun 'mod_use_count_' => 1, 114*4882a593Smuzhiyun '__initramfs_end' => 1, 115*4882a593Smuzhiyun '__initramfs_start' => 1, 116*4882a593Smuzhiyun '_einittext' => 1, 117*4882a593Smuzhiyun '_sinittext' => 1, 118*4882a593Smuzhiyun 'kallsyms_names' => 1, 119*4882a593Smuzhiyun 'kallsyms_num_syms' => 1, 120*4882a593Smuzhiyun 'kallsyms_addresses'=> 1, 121*4882a593Smuzhiyun 'kallsyms_offsets' => 1, 122*4882a593Smuzhiyun 'kallsyms_relative_base'=> 1, 123*4882a593Smuzhiyun '__this_module' => 1, 124*4882a593Smuzhiyun '_etext' => 1, 125*4882a593Smuzhiyun '_edata' => 1, 126*4882a593Smuzhiyun '_end' => 1, 127*4882a593Smuzhiyun '__bss_start' => 1, 128*4882a593Smuzhiyun '_text' => 1, 129*4882a593Smuzhiyun '_stext' => 1, 130*4882a593Smuzhiyun '__gp' => 1, 131*4882a593Smuzhiyun 'ia64_unw_start' => 1, 132*4882a593Smuzhiyun 'ia64_unw_end' => 1, 133*4882a593Smuzhiyun '__init_begin' => 1, 134*4882a593Smuzhiyun '__init_end' => 1, 135*4882a593Smuzhiyun '__bss_stop' => 1, 136*4882a593Smuzhiyun '__nosave_begin' => 1, 137*4882a593Smuzhiyun '__nosave_end' => 1, 138*4882a593Smuzhiyun 'pg0' => 1, 139*4882a593Smuzhiyun 'vdso_enabled' => 1, 140*4882a593Smuzhiyun '__stack_chk_fail' => 1, 141*4882a593Smuzhiyun 'VDSO32_PRELINK' => 1, 142*4882a593Smuzhiyun 'VDSO32_vsyscall' => 1, 143*4882a593Smuzhiyun 'VDSO32_rt_sigreturn'=>1, 144*4882a593Smuzhiyun 'VDSO32_sigreturn' => 1, 145*4882a593Smuzhiyun); 146*4882a593Smuzhiyun 147*4882a593Smuzhiyun 148*4882a593Smuzhiyun&find(\&linux_objects, '.'); # find the objects and do_nm on them 149*4882a593Smuzhiyun&list_multiply_defined(); 150*4882a593Smuzhiyun&resolve_external_references(); 151*4882a593Smuzhiyun&list_extra_externals(); 152*4882a593Smuzhiyun 153*4882a593Smuzhiyunexit(0); 154*4882a593Smuzhiyun 155*4882a593Smuzhiyunsub linux_objects 156*4882a593Smuzhiyun{ 157*4882a593Smuzhiyun # Select objects, ignoring objects which are only created by 158*4882a593Smuzhiyun # merging other objects. Also ignore all of modules, scripts 159*4882a593Smuzhiyun # and compressed. Most conglomerate objects are handled by do_nm, 160*4882a593Smuzhiyun # this list only contains the special cases. These include objects 161*4882a593Smuzhiyun # that are linked from just one other object and objects for which 162*4882a593Smuzhiyun # there is really no permanent source file. 163*4882a593Smuzhiyun my $basename = $_; 164*4882a593Smuzhiyun $_ = $File::Find::name; 165*4882a593Smuzhiyun s:^\./::; 166*4882a593Smuzhiyun if (/.*\.o$/ && 167*4882a593Smuzhiyun ! ( 168*4882a593Smuzhiyun m:/built-in.a$: 169*4882a593Smuzhiyun || m:arch/x86/vdso/: 170*4882a593Smuzhiyun || m:arch/x86/boot/: 171*4882a593Smuzhiyun || m:arch/ia64/ia32/ia32.o$: 172*4882a593Smuzhiyun || m:arch/ia64/kernel/gate-syms.o$: 173*4882a593Smuzhiyun || m:arch/ia64/lib/__divdi3.o$: 174*4882a593Smuzhiyun || m:arch/ia64/lib/__divsi3.o$: 175*4882a593Smuzhiyun || m:arch/ia64/lib/__moddi3.o$: 176*4882a593Smuzhiyun || m:arch/ia64/lib/__modsi3.o$: 177*4882a593Smuzhiyun || m:arch/ia64/lib/__udivdi3.o$: 178*4882a593Smuzhiyun || m:arch/ia64/lib/__udivsi3.o$: 179*4882a593Smuzhiyun || m:arch/ia64/lib/__umoddi3.o$: 180*4882a593Smuzhiyun || m:arch/ia64/lib/__umodsi3.o$: 181*4882a593Smuzhiyun || m:arch/ia64/scripts/check_gas_for_hint.o$: 182*4882a593Smuzhiyun || m:arch/ia64/sn/kernel/xp.o$: 183*4882a593Smuzhiyun || m:boot/bbootsect.o$: 184*4882a593Smuzhiyun || m:boot/bsetup.o$: 185*4882a593Smuzhiyun || m:/bootsect.o$: 186*4882a593Smuzhiyun || m:/boot/setup.o$: 187*4882a593Smuzhiyun || m:/compressed/: 188*4882a593Smuzhiyun || m:drivers/cdrom/driver.o$: 189*4882a593Smuzhiyun || m:drivers/char/drm/tdfx_drv.o$: 190*4882a593Smuzhiyun || m:drivers/ide/ide-detect.o$: 191*4882a593Smuzhiyun || m:drivers/ide/pci/idedriver-pci.o$: 192*4882a593Smuzhiyun || m:drivers/media/media.o$: 193*4882a593Smuzhiyun || m:drivers/scsi/sd_mod.o$: 194*4882a593Smuzhiyun || m:drivers/video/video.o$: 195*4882a593Smuzhiyun || m:fs/devpts/devpts.o$: 196*4882a593Smuzhiyun || m:fs/exportfs/exportfs.o$: 197*4882a593Smuzhiyun || m:fs/hugetlbfs/hugetlbfs.o$: 198*4882a593Smuzhiyun || m:fs/msdos/msdos.o$: 199*4882a593Smuzhiyun || m:fs/nls/nls.o$: 200*4882a593Smuzhiyun || m:fs/ramfs/ramfs.o$: 201*4882a593Smuzhiyun || m:fs/romfs/romfs.o$: 202*4882a593Smuzhiyun || m:fs/vfat/vfat.o$: 203*4882a593Smuzhiyun || m:init/mounts.o$: 204*4882a593Smuzhiyun || m:^modules/: 205*4882a593Smuzhiyun || m:net/netlink/netlink.o$: 206*4882a593Smuzhiyun || m:net/sched/sched.o$: 207*4882a593Smuzhiyun || m:/piggy.o$: 208*4882a593Smuzhiyun || m:^scripts/: 209*4882a593Smuzhiyun || m:sound/.*/snd-: 210*4882a593Smuzhiyun || m:^.*/\.tmp_: 211*4882a593Smuzhiyun || m:^\.tmp_: 212*4882a593Smuzhiyun || m:/vmlinux-obj.o$: 213*4882a593Smuzhiyun || m:^tools/: 214*4882a593Smuzhiyun ) 215*4882a593Smuzhiyun ) { 216*4882a593Smuzhiyun do_nm($basename, $_); 217*4882a593Smuzhiyun } 218*4882a593Smuzhiyun $_ = $basename; # File::Find expects $_ untouched (undocumented) 219*4882a593Smuzhiyun} 220*4882a593Smuzhiyun 221*4882a593Smuzhiyunsub do_nm 222*4882a593Smuzhiyun{ 223*4882a593Smuzhiyun my ($basename, $fullname) = @_; 224*4882a593Smuzhiyun my ($source, $type, $name); 225*4882a593Smuzhiyun if (! -e $basename) { 226*4882a593Smuzhiyun printf STDERR "$basename does not exist\n"; 227*4882a593Smuzhiyun return; 228*4882a593Smuzhiyun } 229*4882a593Smuzhiyun if ($fullname !~ /\.o$/) { 230*4882a593Smuzhiyun printf STDERR "$fullname is not an object file\n"; 231*4882a593Smuzhiyun return; 232*4882a593Smuzhiyun } 233*4882a593Smuzhiyun ($source = $basename) =~ s/\.o$//; 234*4882a593Smuzhiyun if (-e "$source.c" || -e "$source.S") { 235*4882a593Smuzhiyun $source = File::Spec->catfile($objtree, $File::Find::dir, $source) 236*4882a593Smuzhiyun } else { 237*4882a593Smuzhiyun $source = File::Spec->catfile($srctree, $File::Find::dir, $source) 238*4882a593Smuzhiyun } 239*4882a593Smuzhiyun if (! -e "$source.c" && ! -e "$source.S") { 240*4882a593Smuzhiyun # No obvious source, exclude the object if it is conglomerate 241*4882a593Smuzhiyun open(my $objdumpdata, "$objdump $basename|") 242*4882a593Smuzhiyun or die "$objdump $fullname failed $!\n"; 243*4882a593Smuzhiyun 244*4882a593Smuzhiyun my $comment; 245*4882a593Smuzhiyun while (<$objdumpdata>) { 246*4882a593Smuzhiyun chomp(); 247*4882a593Smuzhiyun if (/^In archive/) { 248*4882a593Smuzhiyun # Archives are always conglomerate 249*4882a593Smuzhiyun $comment = "GCC:GCC:"; 250*4882a593Smuzhiyun last; 251*4882a593Smuzhiyun } 252*4882a593Smuzhiyun next if (! /^[ 0-9a-f]{5,} /); 253*4882a593Smuzhiyun $comment .= substr($_, 43); 254*4882a593Smuzhiyun } 255*4882a593Smuzhiyun close($objdumpdata); 256*4882a593Smuzhiyun 257*4882a593Smuzhiyun if (!defined($comment) || $comment !~ /GCC\:.*GCC\:/m) { 258*4882a593Smuzhiyun printf STDERR "No source file found for $fullname\n"; 259*4882a593Smuzhiyun } 260*4882a593Smuzhiyun return; 261*4882a593Smuzhiyun } 262*4882a593Smuzhiyun open (my $nmdata, "$nm $basename|") 263*4882a593Smuzhiyun or die "$nm $fullname failed $!\n"; 264*4882a593Smuzhiyun 265*4882a593Smuzhiyun my @nmdata; 266*4882a593Smuzhiyun while (<$nmdata>) { 267*4882a593Smuzhiyun chop; 268*4882a593Smuzhiyun ($type, $name) = (split(/ +/, $_, 3))[1..2]; 269*4882a593Smuzhiyun # Expected types 270*4882a593Smuzhiyun # A absolute symbol 271*4882a593Smuzhiyun # B weak external reference to data that has been resolved 272*4882a593Smuzhiyun # C global variable, uninitialised 273*4882a593Smuzhiyun # D global variable, initialised 274*4882a593Smuzhiyun # G global variable, initialised, small data section 275*4882a593Smuzhiyun # R global array, initialised 276*4882a593Smuzhiyun # S global variable, uninitialised, small bss 277*4882a593Smuzhiyun # T global label/procedure 278*4882a593Smuzhiyun # U external reference 279*4882a593Smuzhiyun # W weak external reference to text that has been resolved 280*4882a593Smuzhiyun # V similar to W, but the value of the weak symbol becomes zero with no error. 281*4882a593Smuzhiyun # a assembler equate 282*4882a593Smuzhiyun # b static variable, uninitialised 283*4882a593Smuzhiyun # d static variable, initialised 284*4882a593Smuzhiyun # g static variable, initialised, small data section 285*4882a593Smuzhiyun # r static array, initialised 286*4882a593Smuzhiyun # s static variable, uninitialised, small bss 287*4882a593Smuzhiyun # t static label/procedures 288*4882a593Smuzhiyun # w weak external reference to text that has not been resolved 289*4882a593Smuzhiyun # v similar to w 290*4882a593Smuzhiyun # ? undefined type, used a lot by modules 291*4882a593Smuzhiyun if ($type !~ /^[ABCDGRSTUWVabdgrstwv?]$/) { 292*4882a593Smuzhiyun printf STDERR "nm output for $fullname contains unknown type '$_'\n"; 293*4882a593Smuzhiyun } 294*4882a593Smuzhiyun elsif ($name =~ /\./) { 295*4882a593Smuzhiyun # name with '.' is local static 296*4882a593Smuzhiyun } 297*4882a593Smuzhiyun else { 298*4882a593Smuzhiyun $type = 'R' if ($type eq '?'); # binutils replaced ? with R at one point 299*4882a593Smuzhiyun # binutils keeps changing the type for exported symbols, force it to R 300*4882a593Smuzhiyun $type = 'R' if ($name =~ /^__ksymtab/ || $name =~ /^__kstrtab/); 301*4882a593Smuzhiyun $name =~ s/_R[a-f0-9]{8}$//; # module versions adds this 302*4882a593Smuzhiyun if ($type =~ /[ABCDGRSTWV]/ && 303*4882a593Smuzhiyun $name ne 'init_module' && 304*4882a593Smuzhiyun $name ne 'cleanup_module' && 305*4882a593Smuzhiyun $name ne 'Using_Versions' && 306*4882a593Smuzhiyun $name !~ /^Version_[0-9]+$/ && 307*4882a593Smuzhiyun $name !~ /^__parm_/ && 308*4882a593Smuzhiyun $name !~ /^__kstrtab/ && 309*4882a593Smuzhiyun $name !~ /^__ksymtab/ && 310*4882a593Smuzhiyun $name !~ /^__kcrctab_/ && 311*4882a593Smuzhiyun $name !~ /^__exitcall_/ && 312*4882a593Smuzhiyun $name !~ /^__initcall_/ && 313*4882a593Smuzhiyun $name !~ /^__kdb_initcall_/ && 314*4882a593Smuzhiyun $name !~ /^__kdb_exitcall_/ && 315*4882a593Smuzhiyun $name !~ /^__module_/ && 316*4882a593Smuzhiyun $name !~ /^__mod_/ && 317*4882a593Smuzhiyun $name !~ /^__crc_/ && 318*4882a593Smuzhiyun $name ne '__this_module' && 319*4882a593Smuzhiyun $name ne 'kernel_version') { 320*4882a593Smuzhiyun if (!exists($def{$name})) { 321*4882a593Smuzhiyun $def{$name} = []; 322*4882a593Smuzhiyun } 323*4882a593Smuzhiyun push(@{$def{$name}}, $fullname); 324*4882a593Smuzhiyun } 325*4882a593Smuzhiyun push(@nmdata, "$type $name"); 326*4882a593Smuzhiyun if ($name =~ /^__ksymtab_/) { 327*4882a593Smuzhiyun $name = substr($name, 10); 328*4882a593Smuzhiyun if (!exists($ksymtab{$name})) { 329*4882a593Smuzhiyun $ksymtab{$name} = []; 330*4882a593Smuzhiyun } 331*4882a593Smuzhiyun push(@{$ksymtab{$name}}, $fullname); 332*4882a593Smuzhiyun } 333*4882a593Smuzhiyun } 334*4882a593Smuzhiyun } 335*4882a593Smuzhiyun close($nmdata); 336*4882a593Smuzhiyun 337*4882a593Smuzhiyun if ($#nmdata < 0) { 338*4882a593Smuzhiyun printf "No nm data for $fullname\n" 339*4882a593Smuzhiyun unless $nmexception{$fullname}; 340*4882a593Smuzhiyun return; 341*4882a593Smuzhiyun } 342*4882a593Smuzhiyun $nmdata{$fullname} = \@nmdata; 343*4882a593Smuzhiyun} 344*4882a593Smuzhiyun 345*4882a593Smuzhiyunsub drop_def 346*4882a593Smuzhiyun{ 347*4882a593Smuzhiyun my ($object, $name) = @_; 348*4882a593Smuzhiyun my $nmdata = $nmdata{$object}; 349*4882a593Smuzhiyun my ($i, $j); 350*4882a593Smuzhiyun for ($i = 0; $i <= $#{$nmdata}; ++$i) { 351*4882a593Smuzhiyun if ($name eq (split(' ', $nmdata->[$i], 2))[1]) { 352*4882a593Smuzhiyun splice(@{$nmdata{$object}}, $i, 1); 353*4882a593Smuzhiyun my $def = $def{$name}; 354*4882a593Smuzhiyun for ($j = 0; $j < $#{$def{$name}}; ++$j) { 355*4882a593Smuzhiyun if ($def{$name}[$j] eq $object) { 356*4882a593Smuzhiyun splice(@{$def{$name}}, $j, 1); 357*4882a593Smuzhiyun } 358*4882a593Smuzhiyun } 359*4882a593Smuzhiyun last; 360*4882a593Smuzhiyun } 361*4882a593Smuzhiyun } 362*4882a593Smuzhiyun} 363*4882a593Smuzhiyun 364*4882a593Smuzhiyunsub list_multiply_defined 365*4882a593Smuzhiyun{ 366*4882a593Smuzhiyun foreach my $name (keys(%def)) { 367*4882a593Smuzhiyun if ($#{$def{$name}} > 0) { 368*4882a593Smuzhiyun # Special case for cond_syscall 369*4882a593Smuzhiyun if ($#{$def{$name}} == 1 && 370*4882a593Smuzhiyun ($name =~ /^sys_/ || $name =~ /^compat_sys_/ || 371*4882a593Smuzhiyun $name =~ /^sys32_/)) { 372*4882a593Smuzhiyun if($def{$name}[0] eq "kernel/sys_ni.o" || 373*4882a593Smuzhiyun $def{$name}[1] eq "kernel/sys_ni.o") { 374*4882a593Smuzhiyun &drop_def("kernel/sys_ni.o", $name); 375*4882a593Smuzhiyun next; 376*4882a593Smuzhiyun } 377*4882a593Smuzhiyun } 378*4882a593Smuzhiyun 379*4882a593Smuzhiyun printf "$name is multiply defined in :-\n"; 380*4882a593Smuzhiyun foreach my $module (@{$def{$name}}) { 381*4882a593Smuzhiyun printf "\t$module\n"; 382*4882a593Smuzhiyun } 383*4882a593Smuzhiyun } 384*4882a593Smuzhiyun } 385*4882a593Smuzhiyun} 386*4882a593Smuzhiyun 387*4882a593Smuzhiyunsub resolve_external_references 388*4882a593Smuzhiyun{ 389*4882a593Smuzhiyun my ($kstrtab, $ksymtab, $export); 390*4882a593Smuzhiyun 391*4882a593Smuzhiyun printf "\n"; 392*4882a593Smuzhiyun foreach my $object (keys(%nmdata)) { 393*4882a593Smuzhiyun my $nmdata = $nmdata{$object}; 394*4882a593Smuzhiyun for (my $i = 0; $i <= $#{$nmdata}; ++$i) { 395*4882a593Smuzhiyun my ($type, $name) = split(' ', $nmdata->[$i], 2); 396*4882a593Smuzhiyun if ($type eq "U" || $type eq "w") { 397*4882a593Smuzhiyun if (exists($def{$name}) || exists($ksymtab{$name})) { 398*4882a593Smuzhiyun # add the owning object to the nmdata 399*4882a593Smuzhiyun $nmdata->[$i] = "$type $name $object"; 400*4882a593Smuzhiyun # only count as a reference if it is not EXPORT_... 401*4882a593Smuzhiyun $kstrtab = "R __kstrtab_$name"; 402*4882a593Smuzhiyun $ksymtab = "R __ksymtab_$name"; 403*4882a593Smuzhiyun $export = 0; 404*4882a593Smuzhiyun for (my $j = 0; $j <= $#{$nmdata}; ++$j) { 405*4882a593Smuzhiyun if ($nmdata->[$j] eq $kstrtab || 406*4882a593Smuzhiyun $nmdata->[$j] eq $ksymtab) { 407*4882a593Smuzhiyun $export = 1; 408*4882a593Smuzhiyun last; 409*4882a593Smuzhiyun } 410*4882a593Smuzhiyun } 411*4882a593Smuzhiyun if ($export) { 412*4882a593Smuzhiyun $export{$name} = ""; 413*4882a593Smuzhiyun } 414*4882a593Smuzhiyun else { 415*4882a593Smuzhiyun $ref{$name} = "" 416*4882a593Smuzhiyun } 417*4882a593Smuzhiyun } 418*4882a593Smuzhiyun elsif ( ! $nameexception{$name} 419*4882a593Smuzhiyun && $name !~ /^__sched_text_/ 420*4882a593Smuzhiyun && $name !~ /^__start_/ 421*4882a593Smuzhiyun && $name !~ /^__end_/ 422*4882a593Smuzhiyun && $name !~ /^__stop_/ 423*4882a593Smuzhiyun && $name !~ /^__scheduling_functions_.*_here/ 424*4882a593Smuzhiyun && $name !~ /^__.*initcall_/ 425*4882a593Smuzhiyun && $name !~ /^__.*per_cpu_start/ 426*4882a593Smuzhiyun && $name !~ /^__.*per_cpu_end/ 427*4882a593Smuzhiyun && $name !~ /^__alt_instructions/ 428*4882a593Smuzhiyun && $name !~ /^__setup_/ 429*4882a593Smuzhiyun && $name !~ /^__mod_timer/ 430*4882a593Smuzhiyun && $name !~ /^__mod_page_state/ 431*4882a593Smuzhiyun && $name !~ /^init_module/ 432*4882a593Smuzhiyun && $name !~ /^cleanup_module/ 433*4882a593Smuzhiyun ) { 434*4882a593Smuzhiyun printf "Cannot resolve "; 435*4882a593Smuzhiyun printf "weak " if ($type eq "w"); 436*4882a593Smuzhiyun printf "reference to $name from $object\n"; 437*4882a593Smuzhiyun } 438*4882a593Smuzhiyun } 439*4882a593Smuzhiyun } 440*4882a593Smuzhiyun } 441*4882a593Smuzhiyun} 442*4882a593Smuzhiyun 443*4882a593Smuzhiyunsub list_extra_externals 444*4882a593Smuzhiyun{ 445*4882a593Smuzhiyun my %noref = (); 446*4882a593Smuzhiyun 447*4882a593Smuzhiyun foreach my $name (keys(%def)) { 448*4882a593Smuzhiyun if (! exists($ref{$name})) { 449*4882a593Smuzhiyun my @module = @{$def{$name}}; 450*4882a593Smuzhiyun foreach my $module (@module) { 451*4882a593Smuzhiyun if (! exists($noref{$module})) { 452*4882a593Smuzhiyun $noref{$module} = []; 453*4882a593Smuzhiyun } 454*4882a593Smuzhiyun push(@{$noref{$module}}, $name); 455*4882a593Smuzhiyun } 456*4882a593Smuzhiyun } 457*4882a593Smuzhiyun } 458*4882a593Smuzhiyun if (%noref) { 459*4882a593Smuzhiyun printf "\nExternally defined symbols with no external references\n"; 460*4882a593Smuzhiyun foreach my $module (sort(keys(%noref))) { 461*4882a593Smuzhiyun printf " $module\n"; 462*4882a593Smuzhiyun foreach (sort(@{$noref{$module}})) { 463*4882a593Smuzhiyun my $export; 464*4882a593Smuzhiyun if (exists($export{$_})) { 465*4882a593Smuzhiyun $export = " (export only)"; 466*4882a593Smuzhiyun } else { 467*4882a593Smuzhiyun $export = ""; 468*4882a593Smuzhiyun } 469*4882a593Smuzhiyun printf " $_$export\n"; 470*4882a593Smuzhiyun } 471*4882a593Smuzhiyun } 472*4882a593Smuzhiyun } 473*4882a593Smuzhiyun} 474