Skip to content

Commit f0af463

Browse files
committed
testcase to check for bad symbol name prefixes
This checks the main libs that would be directly or indirectly linked against the users executable (libmpi.so, libmpi_mpifh.so, libmpi_usempi.so, libopen-rte, libopen-pal) using "nm" and looking for symbols without ompi_ opal_ mpi_ etc prefixes. Signed-off-by: Mark Allen <[email protected]>
1 parent ff2dd69 commit f0af463

File tree

5 files changed

+224
-2
lines changed

5 files changed

+224
-2
lines changed

configure.ac

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
# Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
2323
# Copyright (c) 2014-2017 Research Organization for Information Science
2424
# and Technology (RIST). All rights reserved.
25-
# Copyright (c) 2016 IBM Corporation. All rights reserved.
25+
# Copyright (c) 2016-2017 IBM Corporation. All rights reserved.
2626
# $COPYRIGHT$
2727
#
2828
# Additional copyrights may follow
@@ -1407,6 +1407,7 @@ AC_CONFIG_FILES([
14071407
test/support/Makefile
14081408
test/threads/Makefile
14091409
test/util/Makefile
1410+
test/symbol_name/Makefile
14101411
])
14111412
m4_ifdef([project_ompi], [AC_CONFIG_FILES([test/monitoring/Makefile])])
14121413
m4_ifdef([project_ompi], [

test/Makefile.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# Copyright (c) 2010 Cisco Systems, Inc. All rights reserved.
1414
# Copyright (c) 2015-2016 Research Organization for Information Science
1515
# and Technology (RIST). All rights reserved.
16+
# Copyright (c) 2017 IBM Corporation. All rights reserved.
1617
# $COPYRIGHT$
1718
#
1819
# Additional copyrights may follow
@@ -21,7 +22,7 @@
2122
#
2223

2324
# support needs to be first for dependencies
24-
SUBDIRS = support asm class threads datatype util dss
25+
SUBDIRS = support asm class threads datatype util dss symbol_name
2526
if PROJECT_OMPI
2627
SUBDIRS += monitoring
2728
endif

test/symbol_name/Makefile.am

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#
2+
# Copyright (c) 2017 IBM Corporation. All rights reserved.
3+
# $COPYRIGHT$
4+
#
5+
# Additional copyrights may follow
6+
#
7+
# $HEADER$
8+
#
9+
10+
# Note: the Jenkins tests on LANL-distcheck and travis-ci keep
11+
# failing when I write this Makefile.am in the "obvious" way.
12+
# The test ends up running in $PWD
13+
# /path/to/openmpi-gitclone/_build/test/symbol_name/
14+
# while files like nmcheck_prefix and nmcheck_prefix.pl are in
15+
# /path/to/openmpi-gitclone/test/symbol_name/
16+
# and can be located with the env var $srcdir
17+
#
18+
# I tried putting nmchec_prefix.pl in check_SCRIPTS and that does
19+
# cause a "make nmcheck_prefix.pl" step, but it then says there's
20+
# no rule to make that target.
21+
#
22+
# Since I don't know what is the "correct" way to access the extra file
23+
# nmcheck_prefix.pl, what I'm doing for now is using $srcdir to
24+
# find it.
25+
26+
TESTS = nmcheck_prefix
27+
28+
EXTRA_DIST = nmcheck_prefix nmcheck_prefix.pl
29+
30+
AM_TESTS_ENVIRONMENT = MYBASE='$(top_builddir)'; OMPI_LIBMPI_NAME=@OMPI_LIBMPI_NAME@; export MYBASE OMPI_LIBMPI_NAME;
31+
32+
export VERBOSE=yes

test/symbol_name/nmcheck_prefix

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/sh
2+
3+
# Copyright (c) 2017 IBM Corporation. All rights reserved.
4+
5+
6+
# if there's no perl, skip the test
7+
perl -v > /dev/null 2>&1
8+
if [ $? -ne 0 ] ; then exit 77 ; fi
9+
10+
# I wrote more in Makedefs.am about why I'm using ${srcdir} here. I suspect
11+
# there's a more correct way to set up automake so the file is available,
12+
# but nothing else has worked for me yet.
13+
14+
perl ${srcdir}/nmcheck_prefix.pl

test/symbol_name/nmcheck_prefix.pl

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
#!/usr/bin/env perl
2+
3+
# Copyright (c) 2017 IBM Corporation. All rights reserved.
4+
5+
sub main {
6+
if (!$ENV{MYBASE}) {
7+
print "Test expects env var MYBASE set to base dir\n";
8+
print "(where ompi/ opal/ orte/ test/ etc live)\n";
9+
print "And optionally OMPI_LIBMPI_NAME should be set\n";
10+
print "if MPI is configured with some name other than\n";
11+
print "\"mpi\" for that.\n";
12+
exit -1;
13+
}
14+
15+
# env var MYBASE should be the top dir where ompi/ opal/ orte/ test/ etc live.
16+
# env var OMPI_LIBMPI_NAME should be @OMPI_LIBMPI_NAME@ from automake
17+
#
18+
# Most likely the libs we want to check are
19+
# ompi/.libs/lib<mpi>.so
20+
# ompi/mpi/fortran/mpif-h/.libs/lib<mpi>_mpifh.so
21+
# ompi/mpi/fortran/use-mpi-tkr/.libs/lib<mpi>_usempi.so
22+
# orte/.libs/libopen-rte.so
23+
# opal/.libs/libopen-pal.so
24+
# but I hate to assume those are the locations, so I'll use 'find' and
25+
# test whatever ".so"s are found.
26+
27+
@libs = ();
28+
$mpi = "mpi";
29+
if ($ENV{OMPI_LIBMPI_NAME}) {
30+
$mpi = $ENV{OMPI_LIBMPI_NAME};
31+
}
32+
for $name (
33+
"lib${mpi}.so",
34+
"lib${mpi}_mpifh.so",
35+
"lib${mpi}_usempi.so",
36+
"libopen-rte.so",
37+
"libopen-pal.so" )
38+
{
39+
for $loc (split(/\n/, `find $ENV{MYBASE} -name $name`)) {
40+
if ($loc !~ /openmpi-gitclone/) {
41+
push @libs, $loc;
42+
}
43+
}
44+
}
45+
46+
@mca_symbols = lookup_mca_symbols();
47+
48+
print "Checking for bad symbol names in the main libs:\n";
49+
$isbad = 0;
50+
for $lib (@libs) {
51+
print "checking $lib\n";
52+
check_lib_for_bad_exports($lib);
53+
}
54+
if ($isbad) { exit(-1); }
55+
}
56+
57+
# Find libraries with names of the form libmca_coll_basic.a etc
58+
# and presume those to be MCAs that are being built into libmpi.so etc
59+
# rather than the usual case where it becomes mca_coll_basic.so.
60+
#
61+
# When name pollution occurs in an MCA .so we don't care about it.
62+
# When it's an MCA built into libmpi.so we care a little, but aren't
63+
# going to make this testcase fail over it.
64+
sub lookup_mca_symbols {
65+
my @list;
66+
my $lib;
67+
68+
@list = ();
69+
for $lib (split(/\n/, `find $ENV{MYBASE} -name libmca_[a-zA-Z0-9_-]*\\.a`))
70+
{
71+
if ($lib !~ /openmpi-gitclone/) {
72+
print "NOTE: found static $lib\n";
73+
push @list, get_nm($lib, 'all');
74+
}
75+
}
76+
77+
return @list;
78+
}
79+
80+
sub check_lib_for_bad_exports {
81+
my $lib = $_[0];
82+
my @symbols;
83+
my $s;
84+
85+
@symbols = get_nm($lib, 'all');
86+
87+
# grep to get rid of symbol prefixes that are considered acceptable,
88+
# leaving behind anything bad:
89+
@symbols = grep(!/^ompi_/i, @symbols);
90+
@symbols = grep(!/^opal_/i, @symbols);
91+
@symbols = grep(!/^orte_/i, @symbols);
92+
@symbols = grep(!/^orted_/i, @symbols);
93+
@symbols = grep(!/^oshmem_/i, @symbols);
94+
@symbols = grep(!/^mpi_/i, @symbols);
95+
@symbols = grep(!/^pmpi_/i, @symbols);
96+
@symbols = grep(!/^pmix_/i, @symbols);
97+
@symbols = grep(!/^pmix2x_/i, @symbols);
98+
@symbols = grep(!/^PMI_/i, @symbols);
99+
@symbols = grep(!/^PMI2_/i, @symbols);
100+
@symbols = grep(!/^MPIR_/, @symbols);
101+
@symbols = grep(!/^MPIX_/, @symbols);
102+
@symbols = grep(!/^mpidbg_dll_locations$/, @symbols);
103+
@symbols = grep(!/^mpimsgq_dll_locations$/, @symbols);
104+
@symbols = grep(!/^ompit_/i, @symbols);
105+
@symbols = grep(!/^ADIO_/i, @symbols);
106+
@symbols = grep(!/^ADIOI_/i, @symbols);
107+
@symbols = grep(!/^MPIO_/i, @symbols);
108+
@symbols = grep(!/^MPIOI_/i, @symbols);
109+
@symbols = grep(!/^MPIU_/i, @symbols);
110+
@symbols = grep(!/^NBC_/i, @symbols);
111+
@symbols = grep(!/^mca_/, @symbols);
112+
113+
@symbols = grep(!/^_fini$/, @symbols);
114+
@symbols = grep(!/^_init$/, @symbols);
115+
@symbols = grep(!/^_edata$/, @symbols);
116+
@symbols = grep(!/^_end$/, @symbols);
117+
@symbols = grep(!/^__bss_start$/, @symbols);
118+
@symbols = grep(!/^__malloc_initialize_hook$/, @symbols);
119+
120+
# The symbols can now be split into two groups: fatal and warning.
121+
# The warnings will be for symbols that appear to be from MCAs that
122+
# this build has placed into a main lib, but which would normally
123+
# be segregated into some mca_*.so
124+
# for the fatal ones.
125+
@warning_symbols = @fatal_symbols = ();
126+
if (scalar(@mca_symbols) > 0) {
127+
%whash = ();
128+
for $s (@mca_symbols) {
129+
$whash{$s} = 1;
130+
}
131+
for $s (@symbols) {
132+
if ($whash{$s}) {
133+
push @warning_symbols, $s;
134+
} else {
135+
push @fatal_symbols, $s;
136+
}
137+
}
138+
} else {
139+
@fatal_symbols = @symbols;
140+
}
141+
142+
for $s (@fatal_symbols) {
143+
print " [error] $s\n";
144+
$isbad = 1;
145+
}
146+
for $s (@warning_symbols) {
147+
print " [warning] $s \n";
148+
}
149+
}
150+
151+
# get_nm /path/to/some/libfoo.so <func|wfunc|all>
152+
153+
sub get_nm {
154+
my $lib = $_[0];
155+
my $mode = $_[1];
156+
my $pattern;
157+
my $cmd;
158+
my @tmp;
159+
160+
$pattern = " [TWBCDVR] ";
161+
if ($mode eq 'func') { $pattern = " [T] "; }
162+
if ($mode eq 'wfunc') { $pattern = " [W] "; }
163+
164+
$cmd = "nm $lib";
165+
$cmd = "$cmd | grep \"$pattern\"";
166+
$cmd = "$cmd | sed -e 's/ *\$//' -e 's/.* //'";
167+
168+
@tmp = split(/\n/, qx#$cmd#);
169+
@tmp = sort(@tmp);
170+
171+
return(@tmp);
172+
}
173+
174+
main();

0 commit comments

Comments
 (0)