g77 block data initialization
Skip Egdorf
egdorf@zaphod.lanl.gov
Wed Oct 21 18:58:00 GMT 1998
----------
X-Sun-Data-Type: text
X-Sun-Data-Description: text
X-Sun-Data-Name: text
X-Sun-Charset: us-ascii
X-Sun-Content-Lines: 158
Dave,
Thanks for the reply. I'll try to give more info and examples without
cluttering up egcs-bugs. If you know of others I should send to, or
if I should send this to the whole egcs-bugs list, let me know.
> Uhm, why? What's the advantage over just linking the shared (or even
> static) libraries as normal? [Note, BTW, if this is x86, that shared
> objects consume a precious register, I believe -- can someone confirm
> that, as we should probably note it in the doc?]
Basically, we want to be able to play games calling things in odd orders
in different archives with dlsym. The project at the moment is to show that
the new dynamic linking method gives the same results as the old static
linking method before we branch out. Thus, we need to run essentially
the same code. This is probably the main thrust of this bug, and it means
that this may spill over to the implementors of libldl.so: A fortran program
should be able to be run either statically linked by ld, or dynamically
linked by dlopen() and have the same effect.
>
> Skip> The egcs problem seems to be that the initialization performed
> Skip> by the block-data programs ONLY happens in the FIRST archive
> Skip> loaded. Any block datas in the second, third, ... libraries do
> Skip> not seem to have their initializations performed.
>
> To address any bug we'd need a runnable example and `g77 -v' output,
> per manual. You are using EXTERNAL for the block data and making sure
> that's resolved, aren't you?
> ...
> If you can tell us what information is missing from the g77 manual,
> perhaps we can fill it in. The second index entry (Block Data and
> Libraries) seems to be the relevant one.
And naturally, that is the on piece of the FM that I had not RTFM'ed.
The section of the manual seems quite complete, but there is still
some sort of dynamic linking problem.
I was handling the static linking issue when needed with "-u blkdat_"
type things to the linker. Adding the appropriate "External"s doesn't
change things except to add one more level of error message (I'll describe
below in the annotated run.) All my examples here include the
"external".
Now, on to the examples: I will include two run logs. I will then
include a shar file of some test code. It's short; total of 121 lines in
six files. Here's hoping the mime attachements work. If the mail message
doesn't have two text run logs and one text shar file, let me know.
The first log, rh-run.log, is from a libc6-based system (Redhat-5.1)
out of the box.
The second log, sw-run.log, is from a libc5-based system (Slackware-3.5)
with egcs-1.1 added.
Slackware includes gcc-2.7.2.3 and g77-0.5.21 which won't work
due to bugs generating PIC. I prefer the newer egcs stuff anyway as
it seems a lot cleaner in general. The main difference between the
libc5 and libc6 based systems seems to be that libc5 includes an
error message when dlopen fails and libc6 doesn't include the
message.
The logs give the appropriate versions, a "make" of the three tests, and
runs of the three tests. run-bug1 and run-bug2 print two lines which are
the paths of the libraries being loaded in the order they are being loaded
so that I can remember which test is which as I run them.
The tests are a C main program that calls a subroutine "test" in fortran
source. Subroutine test uses data from a common block initialized in a
block data. It prints the 4 strings from the common block. The three
varients are a "classic" static-linked version to show a baseline
working code, and two dynamic links in different orders of library
loading.
files in the .shar:
Makefile builds everything - NOTE: the makefile contains absolute paths
for ${CC} and ${FC} - change these (or omit them) to get the proper
compilers on your system.
test1.F contains the subroutine
blkdat.F contains the block data
run-static.c is a simple C main that calls test normally. It is static linked
to give an example of the progrma running in a classic static-linked way.
run-bug1.c dynamically loads a .so with subroutine "test" followed by a dynamic
load of the block data, followed by a dlsym-style lookup and call of "test".
run-bug2.c does the same but loads the two .so's in the reverse order: the
block data followed by the subroutine.
run-bug1.c and run-bug2.c contain absolute paths of the .so files so CHANGE THESE
to match wherever you unload the tests on your system.
To run the tests, unpack the shar file somewhere. Edit the Makefile to
set CC and FC properly for your system. Edit run-bug1.c and run-bug2.c to
point to the proper dynamic libraries (where you just unpacked everything).
Make; run-static; run-bug1; run-bug2
Here's how I see the tests.
--
run-bug2 - load block data then subroutine:
Loading the block data first and the subroutine second WORKS. However, (not shown
by this simple test case) if there are additional block data's loaded in lator
libraries, they fail to link properly (their common blocks are uninitialized)
as in the bug1 case. This happens to be the same behaviour seen on Sun's Solaris
Fortran compiler, so at least egcs/libc6 and Sun are in agreement.
On the Slackware/libc5 system, even loading the block data first seems to cause
the link to fail! It seems that the initialized data in the block data is not loaded
even though a "nm testb.so" shows a "D str_" for the common block. perhaps since
nothing references it in that library, it isn't getting linked. Loading the
subroutine second uses the uninitialized version of the common block; "do a
nm test1.so" and see "B str_". It doesn't seem to know that an initialized version
has already been loaded.
--
run-bug1 - load subroutine first, then block data.
Before adding the "external blkdat" to test1.F, this would load and not initialize the
common block. Adding the "external blkdat" causes an undefined reference to blkdat_
upon the dynamic load. This is with RTLD_LAZY in the dlopen call that SHOULD let
undefined symbols alone until they are actually called at runtime. This implies
(since RTLD_LAZY works in other contexts) that something is trying to link to the
block data.
----
What I would LIKE to see is that I could do dlopen() loads of all the libraries,
common blocks would be initialized as if it had all been linked statically, and the
code would run identically to the statically linked version. It may be necessary to
call some sort of "finalization" routine to say "Link time is over, let's
run" in the same way that f_init is used to turn on IO.
It seems that the hard problems are:
1. How do we let a common block initialized in the third library loaded (e.g.)
properly initialize the common block first seen as uninitialized in the
second library loaded?
2. Why is the external symbol (blkdat_ in my test) being linked when the subroutine
is loaded? It probably is trying to get to the block data stuff, but that will not
be available until a lator library is loaded. How do we get this link to delay
until the block data is actually available?
----
I am not as worried about the Slackware/libc5 failure on run-bug2. If this
happens to be library related (libdl??) and we can only fix it for libc6,
I will be quite satisfied upgrading.
----
What else can I do to help the bug finding process???
Skip Egdorf
hwe@lanl.gov
----------
X-Sun-Data-Type: shell-script
X-Sun-Data-Description: shell-script
X-Sun-Data-Name: bug-blkdat.shar
X-Sun-Charset: us-ascii
X-Sun-Content-Lines: 238
#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.1).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 1998-10-21 09:49 MDT by <egdorf@dogbert>.
# Source directory was `/home/egdorf/mcnpx/bug-blkdat'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 739 -rw-r--r-- Makefile
# 157 -rw-r--r-- blkdat.F
# 642 -rw-r--r-- run-bug1.c
# 642 -rw-r--r-- run-bug2.c
# 104 -rw-r--r-- run_static.c
# 256 -rw-r--r-- test1.F
#
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
shar_touch=touch
else
shar_touch=:
echo
echo 'WARNING: not restoring timestamps. Consider getting and'
echo "installing GNU \`touch', distributed in GNU File Utilities..."
echo
fi
rm -f 1231235999 $$.touch
#
# ============= Makefile ==============
if test -f 'Makefile' && test X"$1" != X"-c"; then
echo 'x - skipping Makefile (file already exists)'
else
echo 'x - extracting Makefile (text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
CC = /usr/local/bin/gcc
FC = /usr/local/bin/g77
CFLAGS = -rdynamic
FFLAGS += -fpic
SOFLAGS = -shared
X
all: run-static run-bug1 run-bug2
X
clean:
X rm -f *.o *.so *.cpp run-static run-bug{1,2} *~
X
###
X
run-bug1: run-bug1.o test1.so testb.so
X ${CC} -o run-bug1 run-bug1.o -ldl -lf2c -lm -lc
X
run-bug2: run-bug2.o test1.so testb.so
X ${CC} -o run-bug2 run-bug2.o -ldl -lf2c -lm -lc
X
run-static: run_static.o test1.o blkdat.o
X ${FC} ${FFLAGS} -o run-static run_static.o test1.o blkdat.o
X
test1.so: test1.o
X ${FC} ${FFLAGS} ${SOFLAGS} -o test1.so test1.o -lf2c -lm -lc
X
test1.o: test1.F
X ${FC} -c ${FFLAGS} test1.F
X
testb.so: blkdat.o
X ${FC} ${FFLAGS} ${SOFLAGS} -o testb.so blkdat.o -lf2c -lm -lc
X
blkdat.o: blkdat.F
X ${FC} -c ${FFLAGS} blkdat.F
SHAR_EOF
$shar_touch -am 1021094398 'Makefile' &&
chmod 0644 'Makefile' ||
echo 'restore of Makefile failed'
shar_count="`wc -c < 'Makefile'`"
test 739 -eq "$shar_count" ||
echo "Makefile: original size 739, current size $shar_count"
fi
# ============= blkdat.F ==============
if test -f 'blkdat.F' && test X"$1" != X"-c"; then
echo 'x - skipping blkdat.F (file already exists)'
else
echo 'x - extracting blkdat.F (text)'
sed 's/^X//' << 'SHAR_EOF' > 'blkdat.F' &&
X block data blkdat
X character strings(4)*8
X common/str/strings
X data strings/'string01','string02','string03','string04'/
X end
SHAR_EOF
$shar_touch -am 1014143698 'blkdat.F' &&
chmod 0644 'blkdat.F' ||
echo 'restore of blkdat.F failed'
shar_count="`wc -c < 'blkdat.F'`"
test 157 -eq "$shar_count" ||
echo "blkdat.F: original size 157, current size $shar_count"
fi
# ============= run-bug1.c ==============
if test -f 'run-bug1.c' && test X"$1" != X"-c"; then
echo 'x - skipping run-bug1.c (file already exists)'
else
echo 'x - extracting run-bug1.c (text)'
sed 's/^X//' << 'SHAR_EOF' > 'run-bug1.c' &&
#include <stdio.h>
#include <dlfcn.h>
X
void MAIN__() {}
X
int main(int argc, char **argv)
X {
X void *handle1, *handleb;
X void (*f)();
X char *lib1 = "/home/egdorf/mcnpx/bug-blkdat/test1.so";
X char *libb = "/home/egdorf/mcnpx/bug-blkdat/testb.so";
X
X printf ("%s\n%s\n", lib1, libb);
X if ((handle1 = dlopen(lib1, RTLD_LAZY | RTLD_GLOBAL)) == NULL)
X {
X fprintf (stderr, "Can't load test1\n");
X exit (1);
X }
X
X if ((handleb = dlopen(libb, RTLD_LAZY | RTLD_GLOBAL)) == NULL)
X {
X fprintf (stderr, "Can't load testb\n");
X exit (1);
X }
X
X f_init ();
X if ((f = (void (*)())dlsym (handle1, "test_")) != NULL)
X (*f) ();
X
X f_exit ();
X exit (0);
X }
SHAR_EOF
$shar_touch -am 1021093398 'run-bug1.c' &&
chmod 0644 'run-bug1.c' ||
echo 'restore of run-bug1.c failed'
shar_count="`wc -c < 'run-bug1.c'`"
test 642 -eq "$shar_count" ||
echo "run-bug1.c: original size 642, current size $shar_count"
fi
# ============= run-bug2.c ==============
if test -f 'run-bug2.c' && test X"$1" != X"-c"; then
echo 'x - skipping run-bug2.c (file already exists)'
else
echo 'x - extracting run-bug2.c (text)'
sed 's/^X//' << 'SHAR_EOF' > 'run-bug2.c' &&
#include <stdio.h>
#include <dlfcn.h>
X
void MAIN__() {}
X
int main(int argc, char **argv)
X {
X void *handle1, *handleb;
X void (*f)();
X char *lib1 = "/home/egdorf/mcnpx/bug-blkdat/test1.so";
X char *libb = "/home/egdorf/mcnpx/bug-blkdat/testb.so";
X
X printf ("%s\n%s\n", libb, lib1);
X if ((handleb = dlopen(libb, RTLD_LAZY | RTLD_GLOBAL)) == NULL)
X {
X fprintf (stderr, "Can't load testb\n");
X exit (1);
X }
X
X if ((handle1 = dlopen(lib1, RTLD_LAZY | RTLD_GLOBAL)) == NULL)
X {
X fprintf (stderr, "Can't load test1\n");
X exit (1);
X }
X
X f_init ();
X if ((f = (void (*)())dlsym (handle1, "test_")) != NULL)
X (*f) ();
X
X f_exit ();
X exit (0);
X }
SHAR_EOF
$shar_touch -am 1021090898 'run-bug2.c' &&
chmod 0644 'run-bug2.c' ||
echo 'restore of run-bug2.c failed'
shar_count="`wc -c < 'run-bug2.c'`"
test 642 -eq "$shar_count" ||
echo "run-bug2.c: original size 642, current size $shar_count"
fi
# ============= run_static.c ==============
if test -f 'run_static.c' && test X"$1" != X"-c"; then
echo 'x - skipping run_static.c (file already exists)'
else
echo 'x - extracting run_static.c (text)'
sed 's/^X//' << 'SHAR_EOF' > 'run_static.c' &&
#include <stdio.h>
X
int main(int argc, char **argv)
X {
X f_init ();
X test_ ();
X f_exit ();
X exit (0);
X }
SHAR_EOF
$shar_touch -am 1014120498 'run_static.c' &&
chmod 0644 'run_static.c' ||
echo 'restore of run_static.c failed'
shar_count="`wc -c < 'run_static.c'`"
test 104 -eq "$shar_count" ||
echo "run_static.c: original size 104, current size $shar_count"
fi
# ============= test1.F ==============
if test -f 'test1.F' && test X"$1" != X"-c"; then
echo 'x - skipping test1.F (file already exists)'
else
echo 'x - extracting test1.F (text)'
sed 's/^X//' << 'SHAR_EOF' > 'test1.F' &&
X Subroutine test ()
X character strings(4)*8
X common /str/strings
X external blkdat
X write (6,*) "In test"
X do 100 i = 1, 4
X write (6,*)"String ", i, " is ", strings(i)
X 100 continue
X return
X end
SHAR_EOF
$shar_touch -am 1021080398 'test1.F' &&
chmod 0644 'test1.F' ||
echo 'restore of test1.F failed'
shar_count="`wc -c < 'test1.F'`"
test 256 -eq "$shar_count" ||
echo "test1.F: original size 256, current size $shar_count"
fi
exit 0
----------
X-Sun-Data-Type: default
X-Sun-Data-Description: default
X-Sun-Data-Name: rh-run.log
X-Sun-Charset: us-ascii
X-Sun-Content-Lines: 48
dilbert$ uname -a
Linux dilbert.lanl.gov 2.0.35 #1 Tue Oct 20 15:02:15 MDT 1998 i586 unknown
dilbert$ which gcc
/usr/bin/gcc
dilbert$ which g77
/usr/bin/g77
dilbert$ gcc --version
2.7.2.3
dilbert$ g77 --version
egcs-2.90.27 980315 (egcs-1.0.2 release)
dilbert$ ls -l
total 6
-rw-r--r-- 1 egdorf 124 691 Oct 21 10:49 Makefile
-rw-r--r-- 1 egdorf 124 157 Oct 14 14:36 blkdat.F
-rw-r--r-- 1 egdorf 124 630 Oct 21 10:52 run-bug1.c
-rw-r--r-- 1 egdorf 124 630 Oct 21 10:52 run-bug2.c
-rw-r--r-- 1 egdorf 124 104 Oct 14 12:04 run_static.c
-rw-r--r-- 1 egdorf 124 256 Oct 21 08:03 test1.F
dilbert$ make
cc -rdynamic -c run_static.c -o run_static.o
f77 -c -fpic test1.F
f77 -c -fpic blkdat.F
f77 -fpic -o run-static run_static.o test1.o blkdat.o
cc -rdynamic -c run-bug1.c -o run-bug1.o
f77 -fpic -shared -o test1.so test1.o -lf2c -lm -lc
f77 -fpic -shared -o testb.so blkdat.o -lf2c -lm -lc
cc -o run-bug1 run-bug1.o -ldl -lf2c -lm -lc
cc -rdynamic -c run-bug2.c -o run-bug2.o
cc -o run-bug2 run-bug2.o -ldl -lf2c -lm -lc
dilbert$ ./run-static
In test
String 1 is string01
String 2 is string02
String 3 is string03
String 4 is string04
dilbert$ ./run-bug1
/home/egdorf/bug-blkdat/test1.so
/home/egdorf/bug-blkdat/testb.so
Can't load test1
dilbert$ ./run-bug2
/home/egdorf/bug-blkdat/testb.so
/home/egdorf/bug-blkdat/test1.so
In test
String 1 is string01
String 2 is string02
String 3 is string03
String 4 is string04
dilbert$
----------
X-Sun-Data-Type: default
X-Sun-Data-Description: default
X-Sun-Data-Name: sw-run.log
X-Sun-Charset: us-ascii
X-Sun-Content-Lines: 59
dogbert$ uname -a
Linux dogbert 2.0.32 #1 Fri Nov 21 17:52:15 MST 1997 i586 unknown
dogbert$ which gcc
/usr/local/bin/gcc
dogbert$ which g77
/usr/local/bin/g77
dogbert$ gcc --version
egcs-2.91.57
dogbert$ g77 --version
GNU Fortran 0.5.24-19980804
Copyright (C) 1997 Free Software Foundation, Inc.
For more version information on components of the GNU Fortran
compilation system, especially useful when reporting bugs,
type the command `g77 --verbose'.
GNU Fortran comes with NO WARRANTY, to the extent permitted by law.
You may redistribute copies of GNU Fortran
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING
or type the command `info -f g77 Copying'.
dogbert$ ls -l
total 6
-rw-r--r-- 1 egdorf users 739 Oct 21 09:43 Makefile
-rw-r--r-- 1 egdorf users 157 Oct 14 14:36 blkdat.F
-rw-r--r-- 1 egdorf users 642 Oct 21 09:33 run-bug1.c
-rw-r--r-- 1 egdorf users 642 Oct 21 09:08 run-bug2.c
-rw-r--r-- 1 egdorf users 104 Oct 14 12:04 run_static.c
-rw-r--r-- 1 egdorf users 256 Oct 21 08:03 test1.F
dogbert$ make
/usr/local/bin/gcc -rdynamic -c run_static.c -o run_static.o
/usr/local/bin/g77 -c -fpic test1.F
/usr/local/bin/g77 -c -fpic blkdat.F
/usr/local/bin/g77 -fpic -o run-static run_static.o test1.o blkdat.o
/usr/local/bin/gcc -rdynamic -c run-bug1.c -o run-bug1.o
/usr/local/bin/g77 -fpic -shared -o test1.so test1.o -lf2c -lm -lc
/usr/local/bin/g77 -fpic -shared -o testb.so blkdat.o -lf2c -lm -lc
/usr/local/bin/gcc -o run-bug1 run-bug1.o -ldl -lf2c -lm -lc
/usr/local/bin/gcc -rdynamic -c run-bug2.c -o run-bug2.o
/usr/local/bin/gcc -o run-bug2 run-bug2.o -ldl -lf2c -lm -lc
dogbert$ run-static
In test
String 1 is string01
String 2 is string02
String 3 is string03
String 4 is string04
dogbert$ run-bug1
/home/egdorf/mcnpx/bug-blkdat/test1.so
/home/egdorf/mcnpx/bug-blkdat/testb.so
run-bug1: can't resolve symbol 'blkdat_'
Can't load test1
dogbert$ run-bug2
/home/egdorf/mcnpx/bug-blkdat/testb.so
/home/egdorf/mcnpx/bug-blkdat/test1.so
In test
String 1 is
String 2 is
String 3 is
String 4 is
dogbert$
More information about the Gcc-bugs
mailing list