I have a large software project with a complex build process that works as follows:
- Compile individual source files.
- Partially link object files for each module with another .o using
ld -r . - Hide private characters in each module using
objcopy -G . - Partially bind the module objects together, again using
ld -r . - Link the modules together with a common object.
Step 3 is needed to allow global module variables that are not exported to the rest of the project.
All this works great with ARM and IA32. Unfortunately, now I have to do something on mips (in particular, mipsel-linux-gnu for Android). And the general MIPS ABI object is much more complicated than on other platforms, and it does not work.
What happens is that in step 5 this error fails:
CALL16 reloc at 0x1234 not against global symbol
This is because the compiler generates CALL16 transitions for calling functions in another compilation unit, but CALL16 allows you to only call global characters --- and because of step 3 some of the characters that we are trying to call are no longer global.
At this moment, I see several possible options:
- convince the linker to allow CALL16 transitions to regular PC-relative processing calls inside compilation in step 2.
- same, but in step 4 or 5.
- tell the compiler not to generate CALL16 moves for compilation function calls.
- others.
Turning off step 3, I'm afraid, is not an option due to external requirements.
What I really would like to do is generate an absolute code, which is fixed when loading to the desired addresses; it is smaller, much faster and much simpler, and we do not need to share the library between processes. Unfortunately, it seems that Android dlopen() does not seem to support this.
I'm currently not in my depths. Anyone have any suggestions?
This is gcc 4.4.5 (from Emdebian), binutils 2.20.1. The target BFD is elf32-tradlittlemips. The host system is Linux and I use cross-compilation for Android.
Adding
I also get warnings similar to this from step 4.
$MODULE.o: Can't find matching LO16 reloc against `$SYMBOLNAME' for R_MIPS_GOT16 at 0x18 in section `.text.$SYMBOLNAME'
Looking at the parsing of the input in step 4, I see that the compiler generated the code as follows:
50: 8f9e0000 lw s8,0(gp) 50: R_MIPS_GOT16 $SYMBOLNAME 54: 8fd9001c lw t9,28(s8) 58: 0320f809 jalr t9 5c: 00a02021 move a0,a1
Is GOT16 not fixing the top half of the address, and should LO16 follow for the bottom half? But the code looks like it is trying to touch the GOT. It puzzles me. I do not know if this is due to my earlier problem or is it another problem or is it not a problem at all ...
Update
Apparently, MIPS just doesn't support hidden global characters!
We went around it, distorting the names of the characters that should be hidden so that no one could say what it is. This pretty much pushes external requirements, but I sold them management, indicating that this is the only way to get a shippable product.
This is absolutely horrible (and includes some very disgusting makefile work), so I would prefer a better solution if anyone has ...