Discussion:
finding unused globals in the kernel
Arnd Bergmann
2004-02-28 21:13:34 UTC
Permalink
I've been looking for a way to find symbols in the kernel that
are not referenced anywhere and could be removed. This script is
what I came up with, it's rather slow and complicated, but I have
managed to find quite a bit of dead code with it.

It will also write a message for symbols that are both defined
static and global in some places, that information is available
for free here.

Going through the output might be a long-term task for the
janitors.

As an example, I'm including the output of the script for the
current i386 defconfig.

Arnd <><

===== Makefile 1.458 vs edited =====
--- 1.458/Makefile Wed Feb 18 04:52:33 2004
+++ edited/Makefile Sat Feb 28 20:24:43 2004
@@ -945,6 +945,9 @@
-name '*.[hcS]' -type f -print | sort \
| xargs $(PERL) -w scripts/checkversion.pl

+unusedcheck: $(vmlinux-objs)
+ bash $(srctree)/scripts/checkunused.sh $(ARCH) $(vmlinux-objs)
+
endif #ifeq ($(config-targets),1)
endif #ifeq ($(mixed-targets),1)

--- /dev/null 2003-09-20 22:40:53.000000000 +0200
+++ ./scripts/checkunused.sh 2004-02-28 20:36:09.000000000 +0100
@@ -0,0 +1,44 @@
+#!/bin/bash
+RELOC=R_`echo $1 | tr a-z A-Z | sed -e 's/I386/386/' -e 's/S390X\?/390/'`
+shift
+objdump -Dr "$@" |
+grep '\([0-9a-f].*>:$\|'"$RELOC"'[^.]*$\|^.*<[_a-zA-Z0-9+]*>$\)' |
+sed -e 's/.*: [A-Z_0-9]*.\([a-zA-Z0-9_]*\).*$/ref \1/g' \
+ -e 's/^.*<\(.*\)>:/def \1/g' \
+ -e 's/.*<\([^-+]*\>\).*$/ref \1/g' | (
+ while read a b ; do
+ if [ "$a" = def ] ; then
+ f=$b
+ else
+ if [ "$f" != "$b" ] ; then
+ echo $b $a
+ fi
+ fi
+ done
+ nm "$@" | grep '\<[UAWRTDBwrtdba]\>' |
+ sed -e 's/^.* [wrtdba] \(.*\)$/\1 local/g' \
+ -e 's/^.* . \(.*\)$/\1 def/g'
+) |
+sort | uniq | grep -v '\.' |
+while read a b ; do
+ if [ $b = ref ] ; then
+ if [ "$a" != "$sym" ] ; then
+ echo undefined reference $a
+ if [ "$sym" -a "$scope" = "def" ] ; then
+ echo unreferenced definition X $sym
+ fi
+ fi
+ sym=
+ else
+ if [ "$sym" -a "$scope" = "def" ] ; then
+ if [ "$sym" = "$a" ] ; then
+ echo defined static and global $sym
+ else
+ echo unreferenced definition $sym
+ fi
+ fi
+
+ sym=$a
+ scope=$b
+ fi
+done

bash /home/arnd/linux-2.6-ipc/scripts/checkunused.sh i386 arch/i386/kernel/head.o arch/i386/kernel/init_task.o init/built-in.o usr/built-in.o arch/i386/kernel/built-in.o arch/i386/mm/built-in.o arch/i386/mach-default/built-in.o kernel/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o lib/lib.a arch/i386/lib/lib.a lib/built-in.o arch/i386/lib/built-in.o drivers/built-in.o sound/built-in.o arch/i386/pci/built-in.o arch/i386/oprofile/built-in.o arch/i386/power/built-in.o net/built-in.o
unreferenced definition VSYSCALL_BASE
unreferenced definition Version_132611
unreferenced definition __journal_internal_check
unreferenced definition __pmd_alloc
unreferenced definition __send_IPI_shortcut
unreferenced definition _fh_update
unreferenced definition _fh_update_old
unreferenced definition acpi_clear_gpe
unreferenced definition acpi_detach_data
defined static and global acpi_disable
unreferenced definition acpi_ds_method_data_get_type
unreferenced definition acpi_ds_obj_stack_delete_all
unreferenced definition acpi_ds_obj_stack_get_value
unreferenced definition acpi_ds_result_insert
unreferenced definition acpi_ds_result_remove
unreferenced definition acpi_evaluate_object_typed
unreferenced definition acpi_gbl_abort_method
unreferenced definition acpi_gbl_breakpoint_walk
unreferenced definition acpi_gbl_method_executing
unreferenced definition acpi_gbl_nesting_level
unreferenced definition acpi_gbl_parsed_namespace_root
unreferenced definition acpi_gbl_pm1_enable_register_save
unreferenced definition acpi_gbl_step_to_next_call
unreferenced definition acpi_get_event_status
unreferenced definition acpi_get_firmware_waking_vector
unreferenced definition acpi_get_gpe_status
unreferenced definition acpi_get_table_header
unreferenced definition acpi_get_timer_resolution
unreferenced definition acpi_install_initialization_handler
unreferenced definition acpi_load_table
unreferenced definition acpi_ns_find_parent_name
unreferenced definition acpi_ns_unload_namespace
unreferenced definition acpi_os_get_line
unreferenced definition acpi_os_get_pci_id
unreferenced definition acpi_os_get_physical_address
unreferenced definition acpi_os_writable
unreferenced definition acpi_ps_get_child
unreferenced definition acpi_ps_get_depth_next
unreferenced definition acpi_ps_get_name
unreferenced definition acpi_ps_get_opcode_name
unreferenced definition acpi_save_state_disk
unreferenced definition acpi_subsystem_status
unreferenced definition acpi_tb_handle_to_object
unreferenced definition acpi_unload_table
unreferenced definition acpi_ut_create_pkg_state_and_push
unreferenced definition acpi_ut_dump_buffer
unreferenced definition acpi_ut_get_event_name
unreferenced definition acpi_ut_print_string
unreferenced definition acpi_ut_strupr
unreferenced definition alloc_null_binding
unreferenced definition bcopy
unreferenced definition blk_queue_resize_tags
defined static and global boot_cpu_logical_apicid
unreferenced definition boot_gdt
unreferenced definition bootmem_bootmap_pages
unreferenced definition cache_drop
unreferenced definition cache_find
defined static and global charset2uni
unreferenced definition compat_sys_futex
unreferenced definition con_protect_unimap
defined static and global debug
defined static and global dev_seq_next
defined static and global dev_seq_start
defined static and global dev_seq_stop
unreferenced definition dodgy_tsc
unreferenced definition early_serial_setup
unreferenced definition emergency_remount
unreferenced definition emergency_sync
unreferenced definition exp_pseudoroot
unreferenced definition ext2_count_free
unreferenced definition ext2_panic
unreferenced definition ext3_count_free
unreferenced definition ext3_panic
unreferenced definition free_cold_page
unreferenced definition get_fpu_twd
unreferenced definition hardpps_ptr
defined static and global helpers
unreferenced definition hid_find_field_in_report
unreferenced definition hid_find_report_by_usage
unreferenced definition highend_pfn
unreferenced definition highstart_pfn
unreferenced definition i830_alloc_pages
unreferenced definition i830_calloc
unreferenced definition i830_dma_service
unreferenced definition i830_do_cleanup_pageflip
unreferenced definition i830_driver_irq_postinstall
unreferenced definition i830_driver_irq_preinstall
unreferenced definition i830_driver_irq_uninstall
unreferenced definition i830_ioremap_nocache
unreferenced definition init_bootmem_node
unreferenced definition init_cpu_khz
unreferenced definition irq_entries_start
unreferenced definition ksize
unreferenced definition memcmp
unreferenced definition mp_bus_id_to_local
unreferenced definition mp_bus_id_to_node
unreferenced definition mtrr_centaur_report_mcr
unreferenced definition mtrr_if_name
defined static and global mtrr_state
unreferenced definition nfs_commit_release
unreferenced definition nfsd_dosync
unreferenced definition nlmsvc_decode_res
unreferenced definition node_online_map
unreferenced definition pci_assign_unassigned_resources
unreferenced definition pg1
unreferenced definition pmd_cache
unreferenced definition pmd_ctor
unreferenced definition print_all_local_APICs
unreferenced definition print_driverbyte
unreferenced definition print_hostbyte
unreferenced definition promise_rw_disk
unreferenced definition ptrace_readdata
unreferenced definition ptrace_writedata
unreferenced definition quad_local_to_mp_bus_id
unreferenced definition register_leds
unreferenced definition resize_screen
defined static and global resume_device
unreferenced definition rpc_pipe_iops
unreferenced definition rpciod_wake_up
unreferenced definition rtnetlink_send
unreferenced definition send_IPI_mask_bitmask
unreferenced definition send_IPI_mask_sequence
unreferenced definition set_fpu_cwd
unreferenced definition set_fpu_mxcsr
unreferenced definition set_fpu_swd
unreferenced definition set_fpu_twd
unreferenced definition set_pmd_pfn
unreferenced definition show_trace_task
unreferenced definition snd_ac97_suspend
unreferenced definition snd_pcm_format_cpu_endian
unreferenced definition snd_pcm_format_silence
unreferenced definition snd_pcm_format_silence_16
unreferenced definition snd_pcm_format_silence_32
unreferenced definition snd_pcm_hw_param_any
unreferenced definition snd_pcm_hw_param_setinteger
unreferenced definition snd_pcm_hw_params_any
unreferenced definition snd_pcm_plug_capture_channels_mask
unreferenced definition startup_32
unreferenced definition stext
unreferenced definition strcat
unreferenced definition strchr
unreferenced definition strcmp
unreferenced definition strncat
unreferenced definition strncmp
unreferenced definition strrchr
unreferenced definition svc_auth_register
unreferenced definition svc_auth_unregister
unreferenced definition sys_pciconfig_iobase
unreferenced definition sys_pciconfig_read
unreferenced definition sys_pciconfig_write
unreferenced definition sys_semop
unreferenced definition sysfs_mknod
unreferenced definition timer_bug_msg
unreferenced definition tr_table
unreferenced definition tty_paranoia_check
unreferenced definition tty_write_message
unreferenced definition uart_console_device
unreferenced definition udf64_high32
unreferenced definition udf64_low32
unreferenced definition udf_filead_read
unreferenced definition udf_get_fileextent
unreferenced definition unregister_cpu_notifier
unreferenced definition usb_stor_sense_notready
unreferenced definition xdr_decode_netobj_fixed
unreferenced definition xdr_kmap
unreferenced definition xdr_kunmap
unreferenced definition xdr_shift_iovec
unreferenced definition xquad_portio
Keith Owens
2004-03-01 06:11:12 UTC
Permalink
On Sat, 28 Feb 2004 22:13:34 +0100,
Post by Arnd Bergmann
I've been looking for a way to find symbols in the kernel that
are not referenced anywhere and could be removed. This script is
what I came up with, it's rather slow and complicated, but I have
managed to find quite a bit of dead code with it.
It is a bit harder than a simple compare. EXPORT_SYMBOL(foo) generates
a reference to foo even if nothing uses it, which hides unused
variables. Certain symbols appear as unused but are really used by the
2.4 version of insmod. Your script does not handle modules at all.

namespace.pl below handles all the special cases on kernels from 2.0
through 2.4. It needs updating for 2.6 kernels, enjoy.

=========

#!/usr/bin/perl -w
#
# namespace.pl. Mon Jan 27 1997
#
# Perform a name space analysis on the linux kernel.
#
# Copyright Keith Owens <***@ocs.com.au>. GPL.
#
# Invoke by changing directory to the top of the kernel source
# tree then namespace.pl, no parameters.
#
# Tuned for 2.1.x kernels with the new module handling, it will
# work with 2.0 kernels as well. Last change 2.4.25 for ia64.
#
# The source must be compiled/assembled first, the object files
# are the primary input to this script. Incomplete or missing
# objects will result in a flawed analysis. Compile both vmlinux
# and modules.
#
# Even with complete objects, treat the result of the analysis
# with caution. Some external references are only used by
# certain architectures, others with certain combinations of
# configuration parameters. Ideally the source should include
# something like
#
# #ifndef CONFIG_...
# static
# #endif
# symbol_definition;
#
# so the symbols are defined as static unless a particular
# CONFIG_... requires it to be external.
#

require 5; # at least perl 5
use strict;
use File::Find;

my $nm = "/usr/bin/nm -p"; # in case somebody moves nm
$nm = "/sw/sdev/gcc+bin-ia64/as3-gcc323-bin2.14.90.0.4/bin/nm -p"; # in case somebody moves nm

if ($#ARGV != -1) {
print STDERR "usage: $0 takes no parameters\n";
die("giving up\n");
}

my %nmdata = (); # nm data for each object
my %def = (); # all definitions for each name
my %ksymtab = (); # names that appear in __ksymtab_
my %ref = (); # $ref{$name} exists if there is a true external reference to $name
my %export = (); # $export{$name} exists if there is an EXPORT_... of $name

&find(\&linux_objects, '.'); # find the objects and do_nm on them
list_multiply_defined();
resolve_external_references();
list_extra_externals();

exit(0);

sub linux_objects
{
# Select objects, ignoring objects which are only created by
# merging other objects. Also ignore all of modules, scripts
# and compressed.
my $basename = $_;
$_ = $File::Find::name;
s:^\./::;
if (/.*\.o$/ && ! (
m:/fs.o$: || m:/isofs.o$: || m:/nfs.o$:
|| m:/xiafs.o$: || m:/umsdos.o$: || m:/hpfs.o$:
|| m:/smbfs.o$: || m:/ncpfs.o$: || m:/ufs.o$:
|| m:/affs.o$: || m:/romfs.o$: || m:/kernel.o$:
|| m:/mm.o$: || m:/ipc.o$: || m:/ext.o$:
|| m:/msdos.o$: || m:proc/proc.o$: || m:/minix.o$:
|| m:/ext2.o$: || m:/sysv.o$: || m:/fat.o$:
|| m:/vfat.o$: || m:/unix.o$: || m:/802.o$:
|| m:/appletalk.o$: || m:/ax25.o$: || m:/core.o$:
|| m:/ethernet.o$: || m:/ipv4.o$: || m:/ipx.o$:
|| m:/netrom.o$: || m:/ipv6.o$: || m:/x25.o$:
|| m:/rose.o$: || m:/bridge.o$: || m:/lapb.o$:
|| m:/sock_n_syms.o$: || m:/teles.o$: || m:/pcbit.o$:
|| m:/isdn.o$: || m:/ftape.o$: || m:/scsi_mod.o$:
|| m:/sd_mod.o$: || m:/sr_mod.o$:
|| m:/sound.o$: || m:/piggy.o$: || m:/bootsect.o$:
|| m:/boot/setup.o$: || m:^modules/: || m:^scripts/:
|| m:/compressed/: || m:/vmlinux-obj.o$:
|| m:/autofs.o$: || m:lockd/lockd.o$: || m:/nfsd.o$:
|| m:/sunrpc.o$: || m:/scsi_n_syms.o$:
|| m:boot/bbootsect.o$: || m:boot/bsetup.o$:
|| m:misc/parport.o$: || m:nls/nls.o$:
|| m:debug/debug.o$: || m:netlink/netlink.o$:
|| m:sched/sched.o$: || m:sound/sb.o$:
|| m:sound/soundcore.o$: || m:pci/pci_syms.o$:
|| m:devpts/devpts.o$: || m:video/fbdev.o$:
|| m:arch/i386/kdb/kdba.o$: || m:crypto/crypto.o$:
|| m:drivers/block/block.o$: || m:drivers/cdrom/driver.o$:
|| m:drivers/char/char.o$:
|| m:drivers/ide/arm/idedriver-arm.o$:
|| m:drivers/ide/ide-core.o$: || m:drivers/ide/ide-detect.o$:
|| m:drivers/ide/idedriver.o$:
|| m:drivers/ide/legacy/idedriver-legacy.o$:
|| m:drivers/ide/pci/idedriver-pci.o$:
|| m:drivers/ide/ppc/idedriver-ppc.o$:
|| m:drivers/ide/raid/idedriver-raid.o$:
|| m:drivers/md/lvm-mod.o$: || m:drivers/md/mddev.o$:
|| m:drivers/media/media.o$: || m:drivers/media/radio/radio.o$:
|| m:drivers/media/video/video.o$: || m:drivers/misc/misc.o$:
|| m:drivers/net/e1000/e1000.o$: || m:drivers/net/net.o$:
|| m:lib/zlib_deflate/zlib_deflate.o$:
|| m:net/8021q/8021q.o$:
|| m:net/bluetooth/bluez.o$:
|| m:net/ipv4/netfilter/ipchains.o$:
|| m:net/ipv4/netfilter/iptable_nat.o$:
|| m:net/ipv4/netfilter/ip_conntrack.o$:
|| m:net/ipv4/netfilter/netfilter.o$:
|| m:net/ipv6/netfilter/netfilter.o$:
|| m:drivers/parport/driver.o$: || m:drivers/pci/driver.o$:
|| m:drivers/scsi/aic7xxx/aic7xxx_drv.o$:
|| m:drivers/scsi/aic7xxx/aic7xxx.o$:
|| m:drivers/scsi/scsidrv.o$:
|| m:drivers/sound/sounddrivers.o$: || m:drivers/video/video.o$:
|| m:fs/autofs4/autofs4.o$: || m:fs/ext3/ext3.o$:
|| m:fs/jbd/jbd.o$: || m:fs/partitions/partitions.o$:
|| m:fs/ramfs/ramfs.o$: || m:fs/xfs/linux/linux_xfs.o$:
|| m:fs/xfs/pagebuf/pagebuf.o$:
|| m:fs/xfs/support/support_xfs.o$: || m:fs/xfs/xfs.o$:
|| m:kdb/kdb.o$:
|| m:lib/zlib_inflate/zlib_inflate.o$: || m:net/network.o$:
|| m:net/packet/packet.o$:
|| m:fs/xfs/quota/xfs_quota.o$:
|| m:fs/udf/udf.o$:
|| m:fs/intermezzo/intermezzo.o$:
|| m:fs/hugetlbfs/hugetlbfs.o$:
|| m:fs/freevxfs/freevxfs.o$:
|| m:fs/devfs/devfs.o$:
|| m:fs/cramfs/cramfs.o$:
|| m:drivers/usb/hid.o$:
|| m:drivers/usb/usbcore.o$:
|| m:drivers/sound/emu10k1/emu10k1.o$:
|| m:drivers/sound/cs4281/cs4281.o$:
|| m:drivers/net/tulip/tulip.o$:
|| m:drivers/net/sk98lin/sk98lin.o$:
|| m:drivers/net/bonding/bonding.o$:
|| m:drivers/message/fusion/fusion.o$:
|| m:drivers/input/inputdrv.o$:
|| m:drivers/ieee1394/ieee1394.o$:
|| m:drivers/char/joystick/js.o$:
|| m:drivers/char/agp/agpgart.o$:
|| m:drivers/char/agp/agp.o$:
|| m:drivers/bluetooth/hci_uart.o$:
|| m:drivers/acpi/acpi.o$:
|| m:drivers/acpi/utilities/utilities.o$:
|| m:drivers/acpi/tables/tables.o$:
|| m:drivers/acpi/resources/resources.o$:
|| m:drivers/acpi/parser/parser.o$:
|| m:drivers/acpi/namespace/namespace.o$:
|| m:drivers/acpi/hardware/hardware.o$:
|| m:drivers/acpi/executer/executer.o$:
|| m:drivers/acpi/events/events.o$:
|| m:drivers/acpi/dispatcher/dispatcher.o$:
|| m:arch/ia64/lib/__divsi3.o$:
|| m:arch/ia64/lib/__udivsi3.o$:
|| m:arch/ia64/lib/__modsi3.o$:
|| m:arch/ia64/lib/__umodsi3.o$:
|| m:arch/ia64/lib/__divdi3.o$:
|| m:arch/ia64/lib/__udivdi3.o$:
|| m:arch/ia64/lib/__moddi3.o$:
|| m:arch/ia64/lib/__umoddi3.o$:
|| m:arch/ia64/ia32/ia32.o$:
)
) {
do_nm($basename, $_);
}
$_ = $basename; # File::Find expects $_ untouched (undocumented)
}

sub do_nm
{
my ($basename, $fullname) = @_;
my ($source, $type, $name);
if (! -e $basename) {
printf STDERR "$basename does not exist\n";
return;
}
if ($fullname !~ /\.o$/) {
printf STDERR "$fullname is not an object file\n";
return;
}
$source = $basename;
$source =~ s/\.o$//;
if (! -e "$source.c" && ! -e "$source.S") {
printf STDERR "No source file found for $fullname\n";
return;
}
if (! open(NMDATA, "$nm $basename|")) {
printf STDERR "$nm $fullname failed $!\n";
return;
}
my @nmdata;
while (<NMDATA>) {
chop;
($type, $name) = (split(/ +/, $_, 3))[1..2];
# Expected types
# B weak external reference to data that has been resolved
# C global variable, uninitialised
# D global variable, initialised
# G global variable, initialised, small data section
# R global array, initialised
# S global variable, uninitialised, small bss
# T global label/procedure
# U external reference
# W weak external reference to text that has been resolved
# a assembler equate
# b static variable, uninitialised
# d static variable, initialised
# g static variable, initialised, small data section
# r static array, initialised
# s static variable, uninitialised, small bss
# t static label/procedures
# w weak external reference to text that has not been resolved
# ? undefined type, used a lot by modules
if ($type !~ /^[BCDGRSTUWabdgrstw?]$/) {
printf STDERR "nm output for $fullname contains unknown type '$_'\n";
}
elsif ($name =~ /\./) {
# name with '.' is local static
}
else {
$type = 'R' if ($type eq '?'); # binutils replaced ? with R at one point
$name =~ s/_R[a-f0-9]{8}$//; # module versions adds this
if ($type =~ /[BCDGRSTW]/ &&
$name ne 'init_module' &&
$name ne 'cleanup_module' &&
$name ne 'Using_Versions' &&
$name !~ /^Version_[0-9]+$/ &&
$name !~ /^__module_parm_/ &&
$name !~ /^__kstrtab/ &&
$name !~ /^__ksymtab/ &&
$name ne '__module_description' &&
$name ne '__module_author' &&
$name ne '__module_device' &&
$name ne 'kernel_version') {
if (!exists($def{$name})) {
$def{$name} = [];
}
push(@{$def{$name}}, $fullname);
}
push(@nmdata, "$type $name");
if ($name =~ /^__ksymtab_/) {
$name = substr($name, 10);
if (!exists($ksymtab{$name})) {
$ksymtab{$name} = [];
}
push(@{$ksymtab{$name}}, $fullname);
}
}
}
close(NMDATA);
if ($#nmdata < 0) {
printf "No nm data for $fullname\n";
return;
}
$nmdata{$fullname} = \@nmdata;
}

sub list_multiply_defined
{
my ($name, $module);
foreach $name (keys(%def)) {
if ($#{$def{$name}} > 0) {
printf "$name is multiply defined in :-\n";
foreach $module (@{$def{$name}}) {
printf "\t$module\n";
}
}
}
}

sub resolve_external_references
{
my ($object, $type, $name, $i, $j, $kstrtab, $ksymtab, $export);
printf "\n";
foreach $object (keys(%nmdata)) {
my $nmdata = $nmdata{$object};
for ($i = 0; $i <= $#{$nmdata}; ++$i) {
($type, $name) = split(' ', $nmdata->[$i], 2);
if ($type eq "U" || $type eq "w") {
if (exists($def{$name}) || exists($ksymtab{$name})) {
# add the owning object to the nmdata
$nmdata->[$i] = "$type $name $object";
# only count as a reference if it is not EXPORT_...
$kstrtab = "R __kstrtab_$name";
$ksymtab = "R __ksymtab_$name";
$export = 0;
for ($j = 0; $j <= $#{$nmdata}; ++$j) {
if ($nmdata->[$j] eq $kstrtab ||
$nmdata->[$j] eq $ksymtab) {
$export = 1;
last;
}
}
if ($export) {
$export{$name} = "";
}
else {
$ref{$name} = ""
}
}
elsif ($name ne "mod_use_count_" &&
$name ne "__this_module" &&
$name ne "_etext" &&
$name ne "_edata" &&
$name ne "_end" &&
$name ne "__start___ksymtab" &&
$name ne "__start___ex_table" &&
$name ne "__stop___ksymtab" &&
$name ne "__stop___ex_table" &&
$name ne "__stop___ex_table" &&
$name ne "__bss_start" &&
$name ne "_text" &&
$name ne "_stext" &&
$name ne "__start_gate_section" &&
$name ne "__start___kallsyms" &&
$name ne "__stop___kallsyms" &&
$name ne "__gp" &&
$name ne "__start_gate_section" &&
$name ne "__stop_gate_section" &&
$name ne "ia64_unw_start" &&
$name ne "__setup_start" &&
$name ne "__setup_end" &&
$name ne "__initcall_start" &&
$name ne "__initcall_end" &&
$name ne "ia64_unw_end" &&
$name ne "__init_begin" &&
$name ne "__init_end") {
printf "Cannot resolve reference to $name from $object\n";
}
}
}
}
}

sub list_extra_externals
{
my %noref = ();
my ($name, @module, $module, $export);
foreach $name (keys(%def)) {
if (! exists($ref{$name})) {
@module = @{$def{$name}};
foreach $module (@module) {
if (! exists($noref{$module})) {
$noref{$module} = [];
}
push(@{$noref{$module}}, $name);
}
}
}
if (%noref) {
printf "\nExternally defined symbols with no external references\n";
foreach $module (sort(keys(%noref))) {
printf " $module\n";
foreach (sort(@{$noref{$module}})) {
if (exists($export{$_})) {
$export = " (export only)";
}
else {
$export = "";
}
printf " $_$export\n";
}
}
}
}

=========

Example output against a 2.4.25 ia64 kernel.

"Externally defined symbols with no external references" means that
these are global symbols with no references from outside the object
they are defined in, when built for this architecture and this config.
It does not mean that the symbol is not used, only that it is not used
by name outside the current source for one architecture and one config.

Be warned: this script gets false positives. Do not blindly change or
remove symbols.

For each suspect symbol, verify that there is no source that refers to
it, a config change might activate that source. If no other source
refers to the symbol then change it to static and rebuild. If gcc says
that the symbol is not used when it is marked static then remove it
completely.


No nm data for fs/filesystems.o
No nm data for fs/intermezzo/journal_obdfs.o
No nm data for fs/intermezzo/journal_reiserfs.o
No nm data for fs/intermezzo/journal_xfs.o
No nm data for drivers/ieee1394/oui.o
No nm data for drivers/ide/ide-probe-mini.o
uhci_device_operations is multiply defined in :-
drivers/usb/host/uhci.o
drivers/usb/host/usb-uhci.o
bust_spinlocks is multiply defined in :-
lib/bust_spinlocks.o
arch/ia64/kernel/traps.o

Cannot resolve reference to acpi_pci_link_exit from drivers/acpi/bus.o
Cannot resolve reference to __multi3 from drivers/usb/hid-core.o
Cannot resolve reference to __multi3 from drivers/ieee1394/ieee1394_core.o
Cannot resolve reference to __multi3 from fs/nfs/dir.o
Cannot resolve reference to __multi3 from fs/isofs/compress.o
Cannot resolve reference to msdos_partition from fs/partitions/check.o
Cannot resolve reference to __multi3 from net/ipv4/netfilter/ip_tables.o
Cannot resolve reference to __multi3 from drivers/message/fusion/mptbase.o
Cannot resolve reference to __multi3 from drivers/message/i2o/i2o_core.o
Cannot resolve reference to __multi3 from drivers/message/i2o/i2o_lan.o

Externally defined symbols with no external references
arch/ia64/dig/setup.o
drive_info
arch/ia64/ia32/binfmt_elf32.o
ia32_install_shared_page
ia32_setup_arg_pages
ia64_elf32_init
arch/ia64/ia32/ia32_entry.o
sys32_fork
sys32_vfork
arch/ia64/ia32/ia32_signal.o
copy_siginfo_from_user32
copy_siginfo_to_user32
arch/ia64/ia32/ia32_support.o
ia32_exec_domain
ia32_gdt
arch/ia64/ia32/sys_ia32.o
sys32_recvmsg
sys32_sendmsg
arch/ia64/kernel/acpi.o
acpi_find_vendor_resource
acpi_get_interrupt_model
acpi_get_sysname
acpi_hp_csr_space (export only)
acpi_madt
acpi_register_irq
acpi_vendor_resource_match
hp_ccsr_descriptor
platform_intr_list
arch/ia64/kernel/efi.o
efi_enter_virtual_mode
arch/ia64/kernel/entry.o
ia64_leave_syscall
ia64_ret_from_execve_syscall
sys_clone
sys_clone2
sys_rt_sigsuspend
arch/ia64/kernel/head.o
_start
ia64_spinlock_contention
arch/ia64/kernel/iosapic.o
iosapic_fixup_pci_interrupt
irq_type_iosapic_edge
arch/ia64/kernel/irq.o
handle_IRQ_event
irq_err_count
no_action
probe_irq_mask (export only)
arch/ia64/kernel/mca_asm.o
ia64_os_mca_dispatch_end
arch/ia64/kernel/pal.o
ia64_pal_default_handler
arch/ia64/kernel/pci.o
pci_root_ops
pci_sal_ops
pcibios_fixup_device_resources
pcibios_fixup_pbus_ranges
pcibios_update_irq
arch/ia64/kernel/perfmon.o
pfm_init
pfm_install_alternate_syswide_subsystem (export only)
pfm_remove_alternate_syswide_subsystem (export only)
arch/ia64/kernel/process.o
default_idle
do_copy_regs
do_dump_fpu
arch/ia64/kernel/sal.o
ia64_ptc_domain_info
ia64_sal_handler_init
arch/ia64/kernel/salinfo.o
salinfo_platform_oemdata
arch/ia64/kernel/setup.o
ia64_cycles_per_usec
identify_cpu
mmu_gathers
arch/ia64/kernel/smpboot.o
ia64_sync_itc
sync_master
arch/ia64/lib/csum_partial_copy.o
csum_partial_copy
arch/ia64/lib/memcpy.o
bcopy
arch/ia64/lib/strlen_user.o
__strlen_user (export only)
arch/ia64/mm/hugetlbpage.o
free_huge_page
set_hugetlb_mem_size
try_to_free_low
unmap_hugepage_range
update_and_free_page
arch/ia64/mm/init.o
cdata
ia64_set_rbs_bot
put_gate_page
arch/ia64/mm/tlb.o
ia64_global_tlb_purge
drivers/acpi/blacklist.o
acpi_blacklisted
drivers/acpi/bus.o
acpi_bus_scan (export only)
acpi_exit
acpi_root
acpi_setup
drivers/acpi/button.o
acpi_button_notify
acpi_button_notify_fixed
drivers/acpi/dispatcher/dsfield.o
acpi_ds_get_field_names
drivers/acpi/dispatcher/dsinit.o
acpi_ds_init_one_object
drivers/acpi/dispatcher/dsmthdat.o
acpi_ds_method_data_delete_value
acpi_ds_method_data_get_type
acpi_ds_method_data_set_value
drivers/acpi/dispatcher/dsobject.o
acpi_ds_build_internal_object
drivers/acpi/dispatcher/dsopcode.o
acpi_ds_execute_arguments
acpi_ds_init_buffer_field
drivers/acpi/dispatcher/dswload.o
acpi_ds_load1_begin_op
acpi_ds_load1_end_op
drivers/acpi/dispatcher/dswstate.o
acpi_ds_obj_stack_delete_all
acpi_ds_obj_stack_get_value
acpi_ds_result_insert
acpi_ds_result_remove
drivers/acpi/events/evevent.o
acpi_ev_fixed_event_dispatch
acpi_ev_fixed_event_initial