------- Comment #23 from mikpe at it dot uu dot se  2010-03-19 23:20 -------
While working on another debugging patch I noticed something that I think might
explain the libjava regressions, especially the stack trace ones.

The binutils change breaks _Unwind_GetRegionStart().

Example: We have three functions, f1() starts at address 100 and is 20 bytes,
f2() starts at address 120 and is 10 bytes, and f3() starts at address 130.
f1() and f2() got the same inlined unwind table data U1, while f3() got some
different unwind table data U3.

A pre-binutils-2.20 .ARM.exidx table for this program would be

[0] = { 100, U1 }, [1] = { 120, U1 }, [2] = { 130, U3 }, ...

binutils-2.20 and later merge entry [1] with entry [0] since they are adjacent
and have the same unwind table data, producing a final .ARM.exidx table:

[0] = { 100, U1 }, [1] = { 130, U3 }, ...

So an exception in or unwind through f2() will now return { 100, U1 } rather
than { 120, U1 }.

The first thing that happens with the found table entry is that the function
start address is stashed away (unwind-arm.c:get_eit_entry(), the assignment to
ucbp->pr_cache.fnstart). Then __gnu_unwind_pr_common() uses fnstart while
interpreting the unwind table data; I haven't studied that code but since
libstdc++ test cases don't regress I assume the incorrect fnstart doesn't
matter for inlined unwind table data.

However, pr-support.c:_Unwind_GetRegionStart() also uses fnstart, so users of
_Unwind_GetRegionStart() will see f1() not f2() for exceptions in or unwinds
through f2(). In particular, libjava/stacktrace.cc looks like it will construct
bogus stack traces (see its uses of 'start_ip').


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40860

Reply via email to