Re: mips64 assembler
[ Andreas, please see bottom -- thanks! ]
David Daney <firstname.lastname@example.org> writes:
> On 09/22/2010 02:40 PM, Camm Maguire wrote:
>> David Daney<email@example.com> writes:
>>> On 09/20/2010 12:44 PM, Camm Maguire wrote:
>>>> David Daney<firstname.lastname@example.org> writes:
>>>>> PLT support works with the n32 ABI (with new toolchains). Can you use that?
>>>> -mabi=n32 -mplt still seems to generate a .MIPS.stubs section
>>>> requiring canonical gp register setting (gcc 4.4.5). Am I missing
>>> You may also have to specify -mno-shared. It looks like the GCC
>>> documentation is foobar for this option. At some point it started
>>> following -fPIC, but the documentation doesn't indicate this.
>> Still have a .MIPS.stub section and no .plt section. Am I looking for
>> the wrong thing?
> You have to have a compatible toolchain. That means gcc, Binutils and
> glibc all have to support it. MIPS PLT support was added recently, so
> old tools do not have the support.
OK, so I guess debian unstable is not up to speed yet?
>> Were you trying to finish a sentence here? (I'd love to know all your
>> thoughts on this matter!). I might get your gist (see below).
> ... I think the notion of a canonical gp does not exist for MIPS. The
> notion of gp can vary from instruction to instruction (but in practice
> only changes at function boundries).
(sid)camm@gabrielli:~/gcl-2.6.8pre/unixport$ readelf -a saved_gcl |grep -i -10 canonical
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
Notes at offset 0x000001bc with length 0x00000024:
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
Attribute Section: gnu
Tag_GNU_MIPS_ABI_FP: Hard float (-mdouble-float)
Canonical gp value: 008e2990
Address Access Initial Purpose
008da9a0 -32752(gp) 00000000 Lazy resolver
008da9a4 -32748(gp) 80000000 Module pointer (GNU extension)
Address Access Initial
008da9a8 -32744(gp) 00420000
008da9ac -32740(gp) 008a0000
>> This actually is a very useful piece of info -- thanks!
>> This obviously frees me from having to worry about the stub, but I'm
>> not sure if it allows me to escape from using the .got for the base
>> executable. This .got is guaranteed to be handled by ld.so on
>> startup, either immediately or lazily. Any .got I craft and append to
>> my loaded code will not, unless I can point the executable header to
>> this region somehow.
>> For example, say I load code that calls _setjmp. If I use the
>> existing .got, even if populated immediately, I know that if my code
>> is dumped, and the binary moved to another machine, and restarted, the
>> new _setjmp address will be handled properly.
> The jmp_buf has to contain the necessary state so that it can resume
> when you call longjmp. Some of the state (like the gp) may be
> regenerated by magic code emitted by GCC at the jump target. But this
> is no different than for other architectures. So you cannot relocate
> the GOT after an unexec it would probably have to remain in the same
> I would however note that their may be GCC bugs related to
> setjmp/longjmp and nested functions for the n32/n64 ABIs. I couldn't
> find any bugzilla entries for this though.
Well, this is not a _setjmp specific issue. Any symbol in an external
shared lib will suffice -- if loaded, relocated code (into a
previously fully linked executable) calls said symbol via the .plt
address, then it is guaranteed to work after unexec and possible image
tranfer to another machine. I.e. such a call sequence goes through
the .got entry tended to by ld.so on startup, whereas some newly
crafter .got at the end of the newly loaded code will not be managed
by ld.so without some major changes to the dumped binary at unexec
>> On other machines with a .plt (e.g. alpha), I don't leave the gp at
>> its 'canonical' value, but rather set it to a mini-table I craft at
>> the end of the code to be loaded. I then populate this .got
>> accordingly. The _setjmp address I use is the address of the .plt
>> entry. This will always call the .plt entry and never reset the new
>> .got slot, as the .plt is designed to set the .got slot of the base
>> executable. So the call is somewhat inefficient, but it works and is
>> stable. On mips, if I move the gp pointer to my mini-table, it will
>> no longer be correct in the stub where it is used to lookup the lazy
>> relocator of libdl in the .got of the base executable.
> The entry point of the lazy resolver is always at a fixed location in
> the GOT. So if you are creating a GOT, just make sure you reserve the
> slots that are used by ld.so.
> The stubs are a little unique in this manner. They rely on a valid gp
> at entry. All other functions calculate their own gp and don't care
> about the value of gp passed on entry.
This is the main point. And I'm assuming that the new plt support
will change this and not make this requirement. If this is truly
forthcoming, I think my best route is to wait for its arrival. The
other option remaining after our discussion is to
1) make my own meta-stub which pushes the stack, resets the gp, then
calls the stub, pops the stack and returns. This looks like about 20
instructions or so per call.
2) make my own .got containing the meta-stub address and relocate the
call to it.
This is doable, and I think I understand how to do it -- its just a
question of the tradeoff of simply waiting for the plt. Any
Thanks so much for this discussion. Do you think you also might be
able to share any insight on the following issue I posted to
debian-mips some time ago without response?
Camm Maguire email@example.com
"The earth is but one country, and mankind its citizens." -- Baha'u'llah