This is the mail archive of the
mailing list for the binutils project.
Re: [PATCH] [MIPS] Ensure that local GOT entries accessed via a 16-bit index come first
- From: Richard Sandiford <rdsandiford at googlemail dot com>
- To: Kwok Cheung Yeung <kcy at codesourcery dot com>
- Cc: <binutils at sourceware dot org>, <jack dot carter at imgtec dot com>, <hjl dot tools at gmail dot com>, "Maciej W. Rozycki" <macro at codesourcery dot com>
- Date: Wed, 16 Apr 2014 20:29:07 +0100
- Subject: Re: [PATCH] [MIPS] Ensure that local GOT entries accessed via a 16-bit index come first
- Authentication-results: sourceware.org; auth=none
- References: <534E84C2 dot 9050505 at codesourcery dot com>
Kwok Cheung Yeung <firstname.lastname@example.org> writes:
>> We have a "canadian_cross" build of LLVM and have been getting off and
>> on link time errors from one of the input object files
>> RecursiveASTVisitorTest.o. :
>> relocation truncated to fit: R_MIPS_GOT16 against `no symbol'
>> Basically building LLVM with a MIPS GCC. I noticed that the section
>> count was way above 16 bits and seized on that as being the culprit.
> From the information you and H.J. have pointed me to, I need to dig
>> further. Why I never knew about this trap door for section overflow is
>> beyond me :-| Probably since I never hit the limit myself.
> I have been investigating this issue with the LLVM Canadian Cross build
> on MIPS. The problem arises mainly because of the way GCC constructs
> calls to member functions of C++ classes in PIC code - each member
> function of each class is placed in a different section (which, coupled
> with the use of class templates, explains the huge number of sections in
> the problematic object file). A call to a member function generates this
> type of code (with -mxgot):
> 2c: 3c020000 lui v0,0x0
> 2c: R_MIPS_GOT_HI16
> 30: 005c1021 addu v0,v0,gp
> 34: 8c420000 lw v0,0(v0)
> 34: R_MIPS_GOT_LO16
> 38: 0040c821 move t9,v0
> 3c: 0320f809 jalr t9
> 3c: R_MIPS_JALR
> 40: 00000000 nop
> meaning that each call to a member function may result in a new entry
> being placed in the local section of the GOT (if the symbol is local or
> mips_use_local_got_p() evaluates to true).
> The other main type of local GOT entry is created by page+offset
> references - e.g.:
> 50: 8f820000 lw v0,0(gp)
> 50: R_MIPS_GOT16 .rodata
> 54: 24450488 addiu a1,v0,1160
> 54: R_MIPS_LO16 .rodata
> 58: 3c020000 lui v0,0x0
> The GOT entry for the page is always accessed using a 16-bit lookup even
> with -mxgot - I believe the reasoning for this was because with each
> page covering 64KB, the addressable 16K GOT page entries would be enough
> to cover ~1GB of address space?
Yeah, I believe so.
> Unfortunately, since local GOT entries are allocated on-the-fly as they
> are encountered in the code, this means that the initial 16K entries are
> filled with a mixture of entries for member functions and pages (in this
> case, mainly the former). This means that there is the possibility that
> a page entry will be allocated outside of the addressable first 16K
> entries, resulting in a reloc overflow. However, with -mxgot, there is
> no problem calling member functions with entries after the first 16K
> entries (without -mxgot, these would also eventually result in overflows).
> I have created this patch to ensure that GOT page entries come before
> the member function entries. The idea is to fill the local GOT space
> from both ends at once, with entries accessed via 16-bit indexing being
> added on the lower end, and those with 32-bit indexing on the upper end.
> If the size of the local GOT is overestimated, this results in a gap in
> the middle of the local GOT area that must be accounted for when
> iterating over the local part of the GOT.
> This patch has only been lightly tested. I can confirm that the reloc
> overflow on building LLVM/Clang no longer occurs, and have tried running
> some of the generated LLVM and Clang binaries on QEMU and a real MIPS
> board. The ld testsuite has a couple of new failures due to the change
> in the GOT layout, so the expected outputs need to be updated (included
> in the patch).
This looks really good, thanks. Just for the record, in case anyone else
was thinking the same thing: I was a bit worried at first about using
unsigned int for assigned_high_gotno, since it's an "end - 1" value.
But of course it can never be negative because we always have at least
one reserved entry before the local area.
Please go ahead and install. If you don't have access yet, please
follow the instructions here:
listing me as sponsor.