Possibly wrong address passed to callq asm instruction within MPIR test binaries

Corinna Vinschen corinna-cygwin@cygwin.com
Mon Apr 7 08:43:00 GMT 2014


On Apr  6 20:20, Jean-Pierre Flori wrote:
> [...]
> The problem we recently encountered was the following:
> in gmp-impl.h, mpn_store (which can be either a macro or a function if 
> efficient assembly is available, and so is always a function on x86_64) 
> was not marked __declspec(dllexport/dllimport).
> (See https://github.com/wbhart/mpir/blob/master/gmp-impl.h#L2419 for the 
> current version with the __GMP_DECLSPEC, defined in mpir.h (from gmp-
> h.in) where this gets defined as __declspec(dllimport) for the user 
> visible header and use outside of MPIR itself)
> It seems that because of this lack, the call to mpn_store from a bunch of 
> test executables produced the wrong callq instruction.
> Once we added the __GMP_DECLSPEC the function got correctly called.
> 
> What I don't really get is that from what I've read e.g. here : https://
> access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/4/
> html/Using_ld_the_GNU_Linker/win32.html
> is that the dllimport/export should not be needed anymore.

And in fact it isn't.

> So I took a slightly deeper look and played with the definition of 
> __GMP_DECLSPEC in gmp-h.in/mpir.h to be empty or __declspec(dllexport/
> import).
> The library was built with:
> ./configure --disable-static --enable-shared
> make
> make check (-> potential segfaults when testing the mpn dir)
> 
> As far as dllexport is concerned, we pass --export-all-symbols to ld, and 
> as expected, we don't need the dllexport part when building the library 
> (we get __imp_ and __nm_ symbols for functions).
> 
> But it seems that the --enable-auto-import counterpart (which should be 
> ld default) is defeated.
> I've had a look at the assembly and objects produced by gcc before linking 
> and they indeed look different.
> With the dllimport magic, I get in t-neg.s:
>         movq    %rax, %rcx
>         movq    __imp___gmpn_store(%rip), %rax
>         call    *%rax
> Without it I get:
>         movq    %rax, %rcx
>         call    __gmpn_store
> Similar differences in the object file (t-neg.o).
> Looking at the exes produced (.libs/t-neg.exe) gives with the dllimport 
> magic:
>    100401115:   48 89 c1                mov    %rax,%rcx
>    100401118:   48 8b 05 f1 71 00 00    mov    0x71f1(%rip),%rax        # 
> 100408310 <__imp___gmpn_store>
>    10040111f:   ff d0                   callq  *%rax
> Without it:
>    100401111:   48 89 c1                mov    %rax,%rcx
>    100401114:   e8 f7 71 00 00          callq  100408310 
> <__imp___gmpn_store>

This is ok.  Look closely at the address after the callq.  It's the
start address of the executable (0x1:00400000) plus an offset.  If you
disassemble the executable you will find a jmp statement at this
address.  This is the trampoline code which is automatically generated
for external references if they are not marked with dllimport.

The problem at this point is that I can't reproduce your issue with a
simple example.  Here's the example:

==== SNIP ====
$ cat > lib.c <<EOF
#include <stdio.h>

int
foo (int a)
{
  printf ("a = %d\n", a);
  return a;
}
EOF
$ cat > app.c <<EOF
#include <stdio.h>

extern int foo (int);

int
main ()
{
  int x = foo (42);
  printf ("x = %d\n", x);
  return 0;
}
EOF
$ gcc -g -shared -o lib.dll lib.c
$ gcc -g -o app app.c lib.dll
$ ./app
a = 42
x = 42
==== SNAP ====

Let's have a look into the executable:

$ objdump -d app.exe
[...]
00000001004010d0 <main>:
   1004010d0:   55                      push   %rbp
   1004010d1:   48 89 e5                mov    %rsp,%rbp
   1004010d4:   48 83 ec 30             sub    $0x30,%rsp
   1004010d8:   e8 93 00 00 00          callq  100401170 <__main>
   1004010dd:   b9 2a 00 00 00          mov    $0x2a,%ecx
   1004010e2:   e8 59 06 00 00          callq  100401740 <foo>
   1004010e7:   89 45 fc                mov    %eax,-0x4(%rbp)
   [...]

So the call to foo is a call to address 1:00401740.  Let's have
a look what is at that address:

0000000100401740 <foo>:
   100401740:   ff 25 1a 5a 00 00       jmpq   *0x5a1a(%rip)        # 100407160 <__imp_foo>

Address 100407160 is somewhere within the IAT which gets relocated
at runtime.

This is exactly as it's supposed to be.

Now, here's the question:  Where is your problem different?  What
exactly makes your code fail?  Can you construct your problem from
my simple testcase, or can you construct an equally simple testcase
which fails?


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://cygwin.com/pipermail/cygwin/attachments/20140407/1ecd6eb4/attachment.sig>


More information about the Cygwin mailing list