[Ffmpeg-devel] Re: Broken trunk on AMD64 with PIC enabled

Trent Piepho xyzzy
Wed Apr 4 05:48:16 CEST 2007


On Wed, 4 Apr 2007, Michael Niedermayer wrote:
> On Wed, Apr 04, 2007 at 01:03:29AM +0200, Diego 'Flameeyes' Petten? wrote:
> > For what it's worth, while I'm still trying to understand how inline
> > asm works (I said already, I have no clue about it and I don't pretend
> > to pass like I have some), I'll be working locally on xine with the
> > attached patch applied. As Trent Piepho said, there's no way the
> > references in that code would be PIC-compatible, and at least this much
> > I think I understand.
>
> you understand but Trent Piepho seems to be wrong, the references are
> PIC-compatible its a problem of relocations with the assembler/linker/loader
> on x86-64

No, in this case Michael Niedermayer seems to be wrong.  There is a
difference between PIC code and code that can be put in a DSO.  Code that
uses TEXTRELs is not pic, but can still (on ia32) be put in a DSO.

About your test:

asm volatile ("movzbl table(%1, %2, 2), %0"

This is not pic.  When you use the pic flag with gcc, you tell gcc to
compile your C code to pic asm.  What you stick in an asm block can be
anything, pic, non-pic, random gibberish, etc.  So just because it compiled
with -fpic doesn't mean it actually _is_ pic.  In this case, the object you
produced is not 100% pic.  The C code is pic, but your asm isn't.

Creating a dynamic shared object (DSO) is something different.  On ia-32,
that asm code can be used in a DSO.  An ia-32 DSO does not need to be pic,
as it can use TEXTRELs.

For example:
$ gcc -shared -fpic test.c -o test.so
$ objdump -d test.so
...
0000052c <test>:
 550:   0f b6 84 42 00 00 00    movzbl 0x0(%edx,%eax,2),%eax
 557:   00
...
$ objdump -R test.so
DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE
00000554 R_386_32          table
...
$ readelf -d test.so
 0x00000016 (TEXTREL)                    0x0
...

The dynamic relocation record means the dynamic linker must write the
32-bit address of 'table' to offset 554, which is the displacement field of
the movzbl instruction in the inline asm.  This is a text relocation and
means the page the code is in will not be shareable, creates more work for
the dynamic linker, and dirties the page so that to page it out, it must be
written to swap rather than dropped.  But on ia-32, it still works.

On x64-64, TEXTRELs are much more problematic and in general *can't be
used*.  This is not a limitation of the GNU toolchain, but a limitation of
the AMD64 instrunction set, and exists on non-GNU OSes too.

The displacement field in the movzbl instruction, where the address of
'table' should be written, is only 32-bits.  On x86-64 the address space is
64-bits!  How can a 64-bit address be loaded into a signed 32-bit
displacement field?  It can't!

64-bit TEXTRELs can only be used with the 64-bit absolute address form of
the mov instruction, an x86-64 extension.  But in this case, you could just
use a rip-relative mov and avoid the whole problem.  So what would be the
point?

In order to support 32-bit TEXTRELs on x86-64, it would be necessary to
give up much of the use of the 64-bit address space.  Since x86-64 no
longer uses segment start addresses like ia-32, this is quite hard to do.




More information about the ffmpeg-devel mailing list