Port-powerpc archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

COMPAT_LINUX: assembly level tricks (long)



Hi!

I have a problem with dynamic linking in Linux emulation. With Linux's
ld.so-1.7.0 everything is fine. With ld.so-2.1.3 (which is mandatory if
we want to run Netscape or the JDK), dynamically linkied executables do
not get their arguments anymore.

What hapens is that the programs expects argc, argv and envp 16 bytes
lower than were they actually are (which is on the top of the stack,
exactly where the stack pointer given to the program points)

Here is a stack dump illustrating the problem:

7fffe970  7fff e990 0180 0744 0000 0000 7fff e9d4 ................
7fffe980  7fff e980 0000 0006 0184 0000 0184 0000 ................
7fffe990  7fff e9a0 0180 05cc 4196 62ac 7fff e9ec ........A.b.....
7fffe9a0  7fff e9c0 4188 9550 0000 0000 0000 0000 ....A..P........
7fffe9b0  7fff e9c0 4186 65e0 0180 0518 4186 5d60 ....A.e.....A.]`
7fffe9c0  7fff e9d0 4188 9580 0180 0518 4186 5d60 ....A.......A.]`
7fffe9d0  0000 0000 0000 0000 0000 0000 0000 0000 ................
7fffe9e0  0000 0001 7fff eac8 0000 0000 7fff eacd ................

By displaying &argv, I know it is at 7fffe9fc. I therfore know that the
programm expected argv to be on 7fffe9d4 and argc on 7fffe9d0. In fact,
they are on 7fffe9e4 and 7fffe9e0, 16 bytes higher.

I tried to change the stack pointer given to the program (shift it to 16
bytes lower), but it breaks everything, ld.so is no more able to link
the executable (I think it does not get the ELF aux. table)

If I just shift argc, argv, envp 16 bytes lower, ld.so does not get its
arguments anymore, and it also breaks (I got the message "you invoked
ld.so without arguments...).

If I duplicate argc, argv, envp, that is: I leave them untouched, and I
copy them 16 bytes lower, the goal is to have this stack layout:
7fffe9d0  0000 0001 7fff eac8 0000 0000 7fff eacd ................
7fffe9e0  0000 0001 7fff eac8 0000 0000 7fff eacd ................
and to keep the stack pointer at 7fffe9e0. The result is even more
surprising: it seems that ld.so erases the copy 16 bytes lower, and when
the program run, I end up with the same stack as before: 
7fffe9d0  0000 0000 0000 0000 0000 0000 0000 0000 ................
7fffe9e0  0000 0001 7fff eac8 0000 0000 7fff eacd ................

I posted a question about this on the linux-gcc mailing list. I'm
waiting for an answer, and in the meantime, I worked on another idea.

It seems that ld.so erases 16 bytes where it expects argc, argv and envp
before actually running the program. So here is my idea: I would carry
on with duplicating these arguments, and I would set up a kind of
trampoline code on the stack, that would re-copy the 16 bytes where they
were erased and then run the real program. In the kernel, I would
replace the AT_ENTRY entry in the ELF aux. table by the adress of my
trompoline code, and I would setup the trampoline code so that on
termination it would jump to the program real entry (that was previously
the AT_ENTRY in the aux table).

This trampoline code would be executed after ld.so loads the libraries,
and before the program is run (control transfered to the program entry).
Any idea about this? It is reasonable?

I started writing a piece of assembly code to do this. I'm not (yet) a
PowerPC assembler expert, so please tell me if the following is ok:

tramp:  lwz     r11,(stack)     /* Is syntax ok? */
        subic   r12,r11,16
        li      r13,4
loop:   lwz     r14,(r12)
        stw     (r11),r14
        addi    r12,r12,4
        addi    r11,r11,4
        subic.  r14,r14,1
        bne     loop
        lwz     r11,(target)    /* syntax ? */
        jmp     r11             /* syntax ? */
target: dc.w    1       /* orginal prog entry point. setup by kernel */
stack:  dc.w    1       /* original stack top. setup by kernel. */

In the kernel, I would setup
- target as the AT_ENTRY value
- stack as the stack pointer before leaving the kernel (points to argc)
Then copy all this stuff on the stack, and replace AT_ENTRY address by
tramp: address.

About syntax problems: I'm not sure of the following:
by "lwz r11,(target)" I mean put in r11 the value contained at the
address of "target:". Is it right?
and by jmp r11, I mean jump inconditonnaly to address contained in r11.
I'm not sure of the mnemonic. 

I'm also looking for a PowerPC assembly language reference, I don't have
very good documentation.

-- 
Emmanuel Dreyfus.  
Vous avez deplacé la souris. 
Windows NT doit maintenant redemarrer pour valider les modifications.
p99dreyf%criens.u-psud.fr@localhost



Home | Main Index | Thread Index | Old Index