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
