This is the mail archive of the binutils@sourceware.org mailing list for the binutils 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]

Re: [PATCH] Don't set TEXT_START_ADDR for MIPS n64


"Maciej W. Rozycki" <macro@linux-mips.org> writes:
> On Sat, 28 Jun 2008, Richard Sandiford wrote:
>> In:
>> 
>>     http://sourceware.org/ml/binutils/2003-05/msg00636.html
>> 
>> Maciej increased the n64 TEXT_START_ADDR beyond the 2GB limit:
>> 
>>     Setting text segment's start address above 4 GB for 64-bit
>>     executables aids in finding unportable software -- if a pointer
>>     is cropped to 32 bits, instead of a possible memory corruption a
>>     segmentation fault is sent as nothing is mapped below text normally.
>> 
>> That's certainly a useful thing to want to test.  However,
>> as linux has proved, you can get big size savings using -msym32
>> for n64 code.  The n64 definition prevents -msym32 working by default.
>> 
>> Of the two, I think allowing -msym32 is the better default choice.
>> Anyone wanting to smoke out invalid assumptions could still use
>> -Ttext to do so.
>> 
>> Tested on mips64-linux-gnu and mips64el-linux-gnu.  OK to install?
>
>  Richard, I have no doubt about the usefulness of -msym32, but unlike with
> the Linux kernel which uses non-PIC code and where merely shorter
> instruction sequences are used omitting references to the %higher() and
> %highest() parts of relocations, here this option is an externally visible
> change to the ABI.  So why don't you simply use a separate set of linker
> scripts for this new emulation?  For pure n64 binaries there is a clear
> benefit from locating text beyond the first 4GB and no negative impact
> whatsoever.

My point is that there _is_ a negative impact for pure n64 binaries.
As of 4.2, GCC tries to use absolute references in executables if we
know it's safe to do so.  For example:

    static int x;
    int get_x (void) { return x; }

can use %hi/%lo-style accesses to refer to "x".  It can also use
absolute accesses to set up $gp in functions that still need it.

This behaviour (selected by -mno-shared) changes the ABI of ET_REL
objects but it does _not_ change the ABI of the final executable.
The option simply changes internal details of the executable, such as
whether it calls via a JAL instead of via a local GOT entry, or whether
it loads a symbol value using %hi and %lo instead of relying on the GOT.
GCC 4.3 and above use this mode whenever you configure for sufficiently
recent binutils.

When it comes to n64, there is little benefit to using absolute
accesses for 64-bit symbols; it is often cheaper to load from the GOT.
Thus -mno-shared only does something useful if you compile with -msym32.

So when passed "-mabi=64 -O", GCC 4.3 generates:

        lui     $3,%hi(%neg(%gp_rel(get_x)))
        daddu   $3,$3,$25
        daddiu  $3,$3,%lo(%neg(%gp_rel(get_x)))
        ld      $2,%got_page(x)($3)
        j       $31
        lw      $2,%got_ofst(x)($2)

When passed "-mabi=64 -O -msym32", GCC 4.3 generates:

        lui     $2,%hi(x)
        j       $31
        lw      $2,%lo(x)($2)

As I said above, the second version can still produce a pure n64 binary,
so -msym32 is already useful for such binaries.  The problem is that
you cannot link such an object with the default scripts, because the
text address is set so high.  The question then is: should the onus be
on users of -msym32 to change the default, or should the onus be on
those who want a +4GB start address to change the default?  I think the
former is the more user-friendly option.  And I think it's the most
friendly option even without the non-PIC support mentioned yesterday,
although that does IMO tip the scales even more.

Yes, changing the start address has a user-visible effect, just as
changing the number of instructions in (say) printf() has a user-visible
effect.  I don't think either changes the ABI.  Nothing should rely on
printf() having a certain number of instructions, and nothing should
rely on the start address being exactly 120000000.  Code that wants to
know the size of printf() should look at the symbol info, and code that
wants to know the load addresses should read them from the program headers.
I think the ABI simply defines a range of valid load addresses, and the
new address is just as valid as the old one.

Richard


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