-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
binutils: multi-GOT building/linking issues #40
Comments
Some background: binutils supports many different formats and architectures. Some of these require separate tables for addresses and procedures, aka GOT and PLT. On IRIX GOT and PLT are combined into one section. This section is normally accessed using indexed memory operations, limiting its size to 16k entries. An absolutely certain set of conditions that will create a library that can't be successfully relocated: make sure it has more than 16k GOT and PLT entries combined, and make sure it has both types. Then, use Learned from reading binutils code; the dynamic symbol table and the GOT are in sync - the first relocatable symbol in dynsym is the first GOT entry, and from then on they have identical entries in identical order. Noted in practice, may or may not be related; binutils-generated multi-GOT may have a lot of trailing "garbage" not recognized by IRIX
In this case it looks like the second GOT part also has the two fixed first-part entries (addresses 0x00000000 and 0x80000000). This does not happen always, but sometimes. Pondering:
How IRIX does this:
An example of this is easy to produce, just run the python thing and compile the result with MIPSpro toolchain. |
So, two possible avenues:
Both might mean fixing some internal bfd bugs too. Some part of the GOT combining-reassigning logic might be doing something inappropriate here. |
Of the options you list - my initial reaction is to "do what MIPSpro toolchain does" - as we might avoid other issues that strange (to IRIX) extended GOTs could cause. RE: the python script, some thoughts Do we know at what point the behaviour starts to diverge (using this script)? e.g. Certainly isolating that "N/N+1" case will allow us (with some instrumentation such as liberal logging) to:
I think my first step would to identify that N, and have a script that generates the N and N+1, N+2 scenarios and uses both toolchains on them. Like this we are part of the way to having a "test suite" for this kind of change, too. Having N, N+1 scenarios means an X linker built/running on linux can be directly stepped through in gdb or other visual debugger, too (I like to use Eclipse for this, yeah, I know). |
And another unhelpful comment, probably: During my travels to get a more recent binutils version working on IRIX, I noticed that apart from the linker, all the other tools in binutils 2.32 were happily passing their tests. I wonder if there is value that we focus this change + tweak on a "fixed" binutils 2.32 (but honestly, I've no idea how tricky it would be to properly resolve the non-multiGOT issues in that version). |
The hard N is "when there is a PLT, and GOT + PLT combined size reaches 16382 entries", possibly plus or minus a couple. The breakage is uniform from there on. The aforementioned weird case is with Firefox libxul.so and as said, may or may not be related. The stuff generated by the Python script is more predictable and given that we know all the function and variable names, it's easy to verify whether or not they ended up in the dynsym table. |
https://github.com/bminor/binutils-gdb/blob/binutils-2_23-branch/bfd/elfxx-mips.c#L8928 When we hit that condition, we're in the "may or may not work" territory. I am not sure where the GOT + PLT joining happens. |
http://mirror.rqsall.com/misc/multi-got-mips.txt Here's the GOT article from dmz-portal.mips.com. Thanks to @larb0b for getting this! |
I'd like someone to confirm me being wrong with this one; what if this is only limited to that one particular case - the stuff in |
So, right. Better to document this all while I'm at it, memory can't be trusted here. I used https://esp.iki.fi/generate2.py to generate a library with 20000 functions and variables, and an executable which calls all those functions and verifies the return values to correspond to the function names - a simple mechanism to ensure that correct functions are being called. I checked the library with
I checked the GOT of the executable with IRIX
Then I ran it with a couple of vars set to see what Summary: library got relocated, everything worked. Looks like UPDATE; this worked because |
https://gist.github.com/onre/c728cf2b22c206195bfa8afb4d93a71e Here's a sample of what the generate2.py script generates, here with only one function. Basically:
|
Alright, I'm not going to work on this anymore. Here's a tarball and a shell script which might be useful for the next brave soul. Works with gcc 4.7.4, does not work with gcc 9.2.0. Instructions:
|
A place to add notes and reproduce cases for our toolchain bug related to multi-GOT.
This python script (https://esp.iki.fi/generate3.py) was mentioned as generating things that exhibit the behaviour, I've personally not had the time to run this yet + compare against MIPSpro / older toolchains.
@onre if there's anything you feel like adding, please do!
The text was updated successfully, but these errors were encountered: