Bug 10009 - Conflict between MIPS PLTS and abicalls stubs
Summary: Conflict between MIPS PLTS and abicalls stubs
Status: WAITING
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.19
: P2 normal
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-03-26 13:32 UTC by Colin Burgess
Modified: 2009-04-01 17:38 UTC (History)
1 user (show)

See Also:
Host: i386-linux-gnu
Target: mips-unknown-qnx6.4.0
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Colin Burgess 2009-03-26 13:32:44 UTC
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
function pointer.

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
possible.

This is with binutils 2.19, under QNX 6.4.1

Regards,

Colin

-- 
cburgess@qnx.com
Comment 1 Colin Burgess 2009-03-26 13:40:26 UTC
For some reason attachments don't work for me, here are the example source files...

a.c:

#include <a.h>

int main(void)
{
    fptr *fp;

    /*  
     * Here we call function(), which initially selects a traditional
     * abicalls stub
     */
    function();

    /* 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
     */ 
    set_function_address(&fp);

    /* 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!
     */
    invoke_function(fp);

#if 0
    /* 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;
#endif

    return 0;
}

a.h:
typedef void (fptr)(void);

extern void function(void);
extern void invoke_function(fptr *f);
extern void set_funtion_address(fptr **f);

b.c:
#include <a.h>

void function(void)
{
}

void set_function_address(fptr **fp)
{
    *fp = function;
}

void invoke_function(fptr *fp)
{
    (fp)();
}

Makefile:
QCC=env QNX_TARGET=/home/cburgess/qssl/stage qcc -V4.3.3,gcc_ntomipsbe -I .

all: a b.so

clean:
    rm -f a b.so *.o

a.o: a.c
    $(QCC) -g -c a.c

b.o: b.c
    $(QCC) -g -shared -c b.c

a.s: 
    $(QCC) -S a.c

a: a.o b.so
    $(QCC) -o a a.o b.so

b.so: b.o
    $(QCC) -shared -o b.so -Wl,-soname=b.so b.o

Comment 2 rsandifo@nildram.co.uk 2009-04-01 17:29:54 UTC
Hmm, this target doesn't seem to be in the FSF sources.  Are you using a
locally-modified version?

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?
Comment 3 Colin Burgess 2009-04-01 17:38:33 UTC
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
http://community.qnx.com/svn/repos/core-dev-tools/tools/binutils/trunk.  It
looks like we just applied the 2.19.1 patch to our trunk.