[Ltrace-devel] MIPS o32

Petr Machata pmachata at redhat.com
Mon Sep 24 23:28:52 UTC 2012


"Edgar E. Iglesias" <edgar.iglesias at gmail.com> writes:

> Yeah, MIPS o32 is a bit different than other archs. The issue with
> the PLT is that it is only used when the symbol hasn't been resolved
> yet. All code jumps indirectly via GOT entries. At build time, the GOT
> entires are built to point into the PLT/stubs but as soon as a symbol
> gets resolved, code will jump directly (via GOT entries) to the various
> functions without jumping via the PLT. So we need to put breakpoints
> to the functions themselves as symbols get resolved.

Interesting.  This is rather similar to the case of PPC64, which also
doesn't have proper PLT slots.  You can still achieve exact PLT tracing.
You distribute breakpoints as usual to PLT entries.  The first time
around, you let it pass through to the dynamic linker.  Somehow
(breakpoint in the right place, singlestepping, watchpoint, whatever
floats your boat) you catch that GOT was updated.  You remember the
resolved address, un-resolve it again, and when the breakpoint hits the
next time around, you set PC to the (now known) destination address.

This can all be arranged by currently existing ltrace mechanisms, but
it's fair amount of work.  If you don't feel like losing sleep over
this, I'm happy to accept any patches that just fix tracing on MIPS
whichever way.

Oh, and note that prelink will likely pre-resolve those GOT entries.

> For function pointers, GOT entries are created with correspoding
> relocations that get resolved before the program starts, those
> need special treatment too.

Cover these with test cases, please, I don't think this is propely
tested in ltrace.  My experience is that tests written for edge cases of
one architecture tend to uncover bugs on different architectures.

> I had not considered the multithreaded issues yet.

The special handling of first PLT call is something that is exercised by
reentrant calls as well.  E.g.:

--lib.c--
void foo (void (*cb) (void)) { cb (); }

--main.c--
void foo (void (*cb) (void));
void main (void) {
  static int i = 0;
  if (i++ < 2) foo (&main);
}

Like in a multi-threaded case, you need to catch the change in GOT
before the call to foo is made the second time around.  Old PPC code
would miss the second call to foo, because it would only re-seat the
breakpoint after foo returned for the first time.

> Anyway, I'll start by posting patches for to get the basic tracing
> going once I'm done with that and then we can discuss the various
> solutions to the multithreaded cases.

Great, looking forward.

Thank you,
PM



More information about the Ltrace-devel mailing list