This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

function addresses and ld.so


Greetings!  I've made some progress on a long standing bug/annoyance
with GCL usage, namely that, especially on particular architectures
such as ia64, gcl systems can be unstable when compiled against one
version of a shared library, and run against a different but
compatible version.

GCL stores addresses of its functions in data structures allocated in
the normal way in its .data section.  It then runs an unexec routine
which saves the memory image including these addresses to a file.
When the file is then later run against ostensibly compatible but
different shared library versions, occasionally the stored function
addresses will no longer point to the correct function.

One mechanism I've identified leading to this behavior is that on
ia64, for example, passing a function address as an argument to
another function which stores it in a saved variable does not actually
pass the address, but rather an address to some region governed
directly by ld.so, at which location the desired function address is
to be found.

For example, on i386:

=============================================================================
Breakpoint 1, LISP_makefun (strg=0x824d3ad "FORMAT", fn=0x80afaf5 <fLformat>, argd=32322)
    at makefun.c:113
(gdb) p fLformat
$1 = {object (object, object)} 0x80afaf5 <fLformat>
(gdb) frame 1
#1  0x0805058f in NewInit () at new_init.c:493
(gdb) p fLformat
$2 = {object (object, object)} 0x80afaf5 <fLformat>
(gdb) 
=============================================================================

The call to LISP_makefun in frame 1 is:

LISP_makefun("FORMAT",(object (*)())fLformat,...);

But on ia64:

=============================================================================
(gdb)
LISP_makefun (strg=0x6000000000009988 "FORMAT", 
    fn=0x200000000003c358 <local+12616>, argd=32322) at makefun.c:113
113	{ object sym = make_ordinary(strg);

(gdb) p fLformat
p fLformat
$1 = {object (object, object)} 0x40000000001a9390 <fLformat>
(gdb) p/x *(long *)fn
p/x *(long *)fn
$4 = 0x40000000001a9390
=============================================================================

Somehow the compiler has instructed the code to look in this ld.so
space for the function address, and adopts the convention that when
one calls the function via (*fn)(...), one really calls the address
pointed to by fn as opposed to fn itself.  

So when for example I run the program against two different but
compatible versions of shared libraries, ldd reports a different
mapping on ia64 in the 0x20000... range, and while fLformat has the
same address 0x40000000001a9390 in both instances, and while the
stored address in the calling variable has the same value of
0x200000000003c358 in both instances, the address stored at the latter
location is not reliably the former unless ld.so makes the same
mapping for the libs, which presumably can only be guaranteed by
using identical versions.

Is there a gcc compiler option which can disable this behavior, and
pass the function addresses as they are?

Take care,

-- 
Camm Maguire			     			camm@enhanced.com
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]