Bug 753130

Summary: ltrace doesn't support re-entrant library calls on ppc64
Product: Red Hat Enterprise Linux 6 Reporter: Petr Machata <pmachata>
Component: ltraceAssignee: Petr Machata <pmachata>
Status: CLOSED WONTFIX QA Contact: qe-baseos-tools-bugs
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 6.6CC: law, mcermak, mnewsome, ohudlick
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2014-06-18 18:26:07 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:

Description Petr Machata 2011-11-11 12:13:37 UTC
This turned up during implementation of threading support, but the problem is more general.

https://bugzilla.redhat.com/show_bug.cgi?id=733216#c56
https://bugzilla.redhat.com/show_bug.cgi?id=733216#c57
https://bugzilla.redhat.com/show_bug.cgi?id=733216#c58

It's not obvious how to fix this.  We might single-step the process until the value in PLT changes, but that might be a fair amount of single-stepping.  We may end up having to put a breakpoint in the dynamic linker itself.

Comment 1 Petr Machata 2012-02-08 16:03:21 UTC
I'm pasting the relevant contents of the linked bug, as the bug itself is not publicly available:

#ifdef LIB
void call(void (*what) ()) {
  if (what)
    what();
}
#else
void call(void (*) ());
void ble() {
  call(0);
}
int main(int argc, char *argv[]) {
  call(&ble);
  return 0;
}
#endif

On ppc64:

# gcc -DLIB -m64 rec.c -fPIC -shared -o rec.so
# gcc -ULIB -m64 rec.c rec.so -Wl,-rpath,. -o rec
# ./ltrace ./rec
_start(1, 0xfffff9ff2c8, 0xfffff9ff2d8, <unfinished ...>
__libc_start_main(1, 0xfffff9ff2c8, 0xfffff9ff2d8, <unfinished ...>
call(0x10010be8, 0xfffff9ff2c8, 0xfffff9ff2d8) = 0
+++ exited (status 0) +++

On ppc32:

# gcc -DLIB rec.c -fPIC -shared -o rec.so
# gcc -ULIB rec.c rec.so -Wl,-rpath,. -o rec
# ./ltrace ./rec
_start(1, 0xffe5f3f4, 0xffe5f3fc, <unfinished ...>
__libc_start_main(1, 0xffe5f3f4, 0xffe5f3fc, <unfinished ...>
call(0x100015bc, 0xffe5f3f4, 0xffe5f3fc, <unfinished ...>
call(0, 0xffe5f3f4, 0xffe5f3fc) = 0
<... call resumed> ) = 0
+++ exited (status 0) +++

The deal is that on ppc, the PLT entry is changed after the first call.  So ltrace knows it has to re-insert the breakpoint.  But it cannot do so right away, when the PLT breakpoint is hit, it has to wait for the dynamic linker to actually change the entry first.  So it does the re-insertion on _return_ from the function.  Which is clever, except in case of re-entrant functions (or in multi-threaded app) this means that we miss all further calls to this one function until the first invocation returns.

The simple way out, viz. keeping everyone blocked until the first thread returns, is a no-go.  Apart from it being rather horrible, some functions don't actually return (__libc_start_main comes to mind).

Comment 2 Jeff Law 2013-11-13 15:03:21 UTC
This Bugzilla has been reviewed by Red Hat and is not planned on being
addressed in Red Hat Enterprise Linux 5, and therefore will be moved
to Red Hat Enterprise Linux 6.

If this bug is critical to production systems, please contact your Red
Hat support representative and provide sufficient business
justification.

Comment 6 RHEL Program Management 2014-06-18 18:26:07 UTC
Development Management has reviewed and declined this request.
You may appeal this decision by reopening this request.

Comment 7 Petr Machata 2015-04-16 10:23:13 UTC
*** Bug 1210725 has been marked as a duplicate of this bug. ***