Non-returning functions and calls to them are not being processed properly
by Dyninst on ppc/be. As a consequence, in the analysis results produced
by Dyninst for a binary for AMG 2013, two functions and a long branch
trampoline are fused into a single function, which leads to confusion in
HPCToolkit’s hpcstruct.

Advertising

The problem report below refers to two binaries: one called ungetc.ppc,
which is a dynamic ppc/be binary for a main program that contains a single
call to ungetc and a second binary amg2013.gnu.ppc, which is a statically
linked binary for bg/q (ppc/be).
The binaries can be found here:
https://rice.box.com/s/1c6i42lz7dlpxb3fy29rm39zvps5f8br
First a case that works:
The call at 0x1001cd0 in the ungetc.ppc binary at the end of ._IO_ungetc
is labeled as non-returning by the following line in Parser.C at line
1012 in my copy of Dyninst source:
is_nonret = obj().cs()->nonReturning(target);
The function nonReturning resolves the address to a ParseAPI::Function
and then determines that a mangled name of that function
(_Unwind_Resume) is in the table of names of non_returning_funcs
defined in CodeSource.C
1001cd0: 48 07 20 71 bl 1073d40 <._Unwind_Resume>
1001cd4: 60 00 00 00 nop
_IO_ungetc():
1001cd8: 00 00 00 00 .long 0x0
1001cdc: 00 00 00 01 .long 0x1
1001ce0: 80 03 00 00 lwz r0,0(r3)
__vmx__sigsetjmp_ent():
1001ce4: 60 00 00 00 nop
1001ce8: 60 00 00 00 nop
1001cec: 60 00 00 00 nop
Now a case that doesn’t work:
In the amg2013.gnu.ppc binary, the branch at 0x158d6b0, which
is at the same spot in ._IO_ungetc, goes to a ppc long_branch trampoline
that makes a tail call to _Unwind_Resume. This call is not classified as
non-returning. As a result, there is a fall through edge that joins it
to the branch trampoline for _IO_vfscanf that that follows ._IO_ungetc.
...
158d6b0: 4b ff fb 41 bl 158d1f0
<00008345.long_branch_r2off._Unwind_Resume+0>
158d6b4: e8 41 00 28 ld r2,40(r1)
_IO_ungetc():
158d6b8: 00 00 00 00 .long 0x0
158d6bc: 00 00 00 01 .long 0x1
158d6c0: 80 03 00 00 lwz r0,0(r3)
000000000158d6c4 <00008368.long_branch_r2off._IO_vfscanf+0>:
00008368.long_branch_r2off._IO_vfscanf+0():
158d6c4: f8 41 00 28 std r2,40(r1)
158d6c8: 3c 42 00 01 addis r2,r2,1
158d6cc: 38 42 ff f8 addi r2,r2,-8
158d6d0: 48 05 a1 00 b 15e77d0 <._IO_vfscanf>
158d6d4: 60 00 00 00 nop
158d6d8: 60 00 00 00 nop
158d6dc: 60 00 00 00 nop
In fact, the same issue at then end of ._IO_setvbuf, which precedes
._IO_ungetc causes a fall through edge between ._IO_setvbuf and
._IO_ungetc.
The long_branch trampoline that is the target of the call at 0x158d6b0
is included below:
000000000158d1f0 <00008345.long_branch_r2off._Unwind_Resume+0>:
00008345.long_branch_r2off._Unwind_Resume+0():
158d1f0: f8 41 00 28 std r2,40(r1)
158d1f4: 3c 42 ff ff addis r2,r2,-1
158d1f8: 38 42 00 08 addi r2,r2,8
158d1fc: 4b fd b0 f4 b 15682f0 <._Unwind_Resume>
It seems that non-returning status isn't properly being computed for
functions. When I dump dyninst parseAPI functions and print their
return status, I find that both _Unwind_Resume is listed as returning
and the long branch trampoline at 0x158d1f0 that goes to ._Unwind_Resume
is also listed as returning as well.
function targ158d1f0 RETURN
[158d1f0,158d200)
DIRECT --> 15682f0
function _Unwind_Resume RETURN
[15682f0,15683b4)
COND_TAKEN --> 15683b8
COND_NOT_TAKEN --> 15683b4
[15683b4,15683b8)
FALLTHROUGH --> 15683b8
[15683b8,15683d8)
CALL --> 1567970
CALL_FT --> 15683d8
...
It seems that the ParseAPI::Function for _Unwind_Resume should be marked
as non-returning since the name is identified as a non-returning function.
If I understand the logic and how this should propagate,
marking the parseAPI function for _Unwind_Resume as non-returning should
cause the long-branch trampoline that ends in a tail call to it to be seen as
non-returning,
which would then cause the call to the long-branch trampoline as having no
CALL_FT edge.
While the branch trampolines may contribute to bad propagation of
knowledge about non-returning functions on ppc, the fact that the
ParseAPI::Function for _Unwind_Resume is not marked as non-returning
seems like a problem that transcends architecture.
--
John Mellor-Crummey Professor
Dept of Computer Science Rice University
email: joh...@rice.edu phone: 713-348-5179