------- 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