We have an issue where a nonPIC binary that is
* calling a function in a shared object
* calling another function in a shared object, which references the address of
the first function, saving it as a function pointer.
* later, calling yet another function (in a shared object) which invokes the
Because the executable itself doesn't refer directly to the address of the
function, an abicalls stub is generated.
However, since the canonical address of the function is, as I understand it, the
address of the stub in the
executable's .MIPS.stubs section, when the function invocation is performed it
will mess up because the $gp
is pointing at the shared objects got, whereas the stub assumes that it points
at the executables got.
If a the address of the function is taken in the executable, then all is well
since this generates a PLT
entry with STO_MIPS_PLT.
Attached is an example application, which I've tried to comment as clearly as
This is with binutils 2.19, under QNX 6.4.1
For some reason attachments don't work for me, here are the example source files...
* Here we call function(), which initially selects a traditional
* abicalls stub
/* We show as this function to give us the address of function(),
* however the linker is not aware that the address of function() will
* be referenced within the shared object
/* when we now as this funtion to invoke our function pointer, it does
* so from the GOT context of b.so, and thus if it transfer into an
* abicalls stub it will load the incorrect got entry (ie that from
* b.so rather a) and havoc will ensue!
/* But if this code is enabled, the reference to the address of function()
* causes a PLT to be used, and the address of the PLT becomes
* the canonical address of function()
fp = function;
typedef void (fptr)(void);
extern void function(void);
extern void invoke_function(fptr *f);
extern void set_funtion_address(fptr **f);
void set_function_address(fptr **fp)
*fp = function;
void invoke_function(fptr *fp)
QCC=env QNX_TARGET=/home/cburgess/qssl/stage qcc -V4.3.3,gcc_ntomipsbe -I .
all: a b.so
rm -f a b.so *.o
$(QCC) -g -c a.c
$(QCC) -g -shared -c b.c
$(QCC) -S a.c
a: a.o b.so
$(QCC) -o a a.o b.so
$(QCC) -shared -o b.so -Wl,-soname=b.so b.o
Hmm, this target doesn't seem to be in the FSF sources. Are you using a
Unlike PLTs, .MIPS.stubs entries must never act as the canonical function
address. Their only use is to resolve implement lazily-bound calls from within
the same dynamic object.
The thing that stands out for me is that you don't compile your shared library
as -fPIC. Does it work with that fixed?
we do have some minor local changes. If it helps I'll check if it happens with
a standard linux target.
the -shared switch on our qcc is a synonym for -fpic, it will pass -fpic to the
compiler. we are using -mno-shared -mplt for executables.
our version is browseable at
looks like we just applied the 2.19.1 patch to our trunk.