binutils 2.18 generates this, which works because lr does not get frobbed
and is obviously more efficient anyway as both here and with CVS, the
destination is within the 22-bit thumb branch limit):
0x20058568 <___Unwind_RaiseException_from_thumb+0>: bx pc
0x2005856a <___Unwind_RaiseException_from_thumb+2>: nop
0x2005856c <___Unwind_RaiseException_change_to_arm>: b 0x20052918
<___Unwind_RaiseException>
The problem originates with this change, checked in on 2008-05-15 or so:
http://sourceware.org/ml/binutils/2008-04/msg00423.html
So the first issue is: why is this generating a long call stub in the first
place? I believe the answer is that in 2.18, elf32_thumb_to_arm_stub()
generated the stub, called from elf32_arm_final_link_relocate(). In CVS,
the choice of stub is decided in arm_type_of_stub(), called from
elf32_arm_size_stubs() which is called in ld's emultempl/armelf.em in
"gld${EMULATION_NAME}_finish". It does not try and deal with a simple stub
in that code, but then as a result identifies a long call stub instead -
perhaps it was thinking that other code would fix it up? To cut a long
story short, the overall effect is that arm_type_of_stub() is called from
lang_process(), whereas elf32_thumb_to_arm_stub() is called from ldwrite(),
which is called subsequently, and thus is too late. I believe.
The second issue is that the long call stub can never work with C++
exceptions in GCC, at least for ARM EABI, and possibly the standard dwarf
unwinder as well. So if a call _was_ too far away for a simple stub, then
it would go wrong.