This e-mail went out over a week ago.  I noticed just now that I forgot
to CC: the ltrace devel list, so I'm resending it.  I haven't had a
chance to work on the MIPS backend since I wrote this.

------

Hi there,

I had a chance to look into MIPS tracing on Sunday.  For the PLT-ful
case we can just reuse what core does, so that's not a problem.

In PLT-disabled binaries, the calls are done through addresses fetched
from GOT.

00400660 <main>:
  [...]
  400670:       3c1c0042        lui     gp,0x42
  400674:       279c8900        addiu   gp,gp,-30464 <-- gp = some global 
pointer?
  [...]
  40068c:       8f828034        lw      v0,-32716(gp) <-- address from GOT
  400690:       00200825        move    at,at
  400694:       0040c821        move    t9,v0
  400698:       0320f809        jalr    t9    <-- jump to it
  40069c:       00200825        move    at,at

GOT initially contains addresses that point to .MIPS.stubs section,
where the jump leads:

  400820:       8f998010        lw      t9,-32752(gp) <-- t9 = GOT[0]
  400824:       03e07821        move    t7,ra         <-- t7 = caller's return 
addr
  400828:       0320f809        jalr    t9
  40082c:       24180009        li      t8,9          <-- t8 = .dynsym index

After the first call, GOT entry is resolved and contains address of the
resolved symbol.  So .MIPS.stubs is avoided except on first call, and
possibly even then, if the binary has been prelinked (but I haven't had
a chance to check that, my qemu image isn't prelinked).

So we have to do the same relatively complicated thing that PPC backend
does: the first time a stub breakpoint is hit, we single-step through
dynamic linker, looking for when the corresponding GOT entry is updated.
When it is, we rewrite it back, but remember the resolved address.  When
this stub breakpoint is hit the second time, we just move PC over to
that resolved address that we remembered (and update $t9 as well).

This is now partly implemented on pmachata/mips.  It doesn't handle
prelinked binaries yet, and I didn't try to run the test suite yet
eihter.  But it's a good start, and already it could give reasonable
traces for ls, pwd, and a couple test binaries.

The original code placed the breakpoint at the resolved address, and
knew to update it after the function returns.  Unfortunately that
creates a window between when the call is resolved, and when it returns,
where any calls (like those from other threads, or recursive calls done
through PLT) would be missed.  That's why I ported the fairly
complicated PPC approach.

Originally I wanted to leave out an optimization that PPC backend does,
whereby you remember the address of the instruction which resolved a GOT
entry, and put a breakpoint there.  Next time, instead of
single-stepping through dynamic linker, you just let the traced process
hit this breakpoint.  Now MIPS doesn't allow PTRACE_SINGLESTEP, and we
must do it in software, so single-stepping is super expensive.  In my
qemu, the first instance of each library call took like half a second to
resolve, and I'm afraid that on the often low-power MIPS boxes, this
could be similarly bad.  So eventually I put the optimization in.

Thanks,
PM

_______________________________________________
Ltrace-devel mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/ltrace-devel

Reply via email to