FDE with 0 PC range filtering for gold
Егор Кочетов
gluk47@gmail.com
Thu Feb 25 12:32:00 GMT 2016
Hello. I’ve recently come through an exception uncaught by a correct
corresponding catch block in a binary compiled with clang and gold for
Android. As a result, I suppose the FDE filtering to be added to
discard invalid FDE with 0 PC range to increase compatibility with
ld.bfd. The details are below.
If a function is of a non-void return type and its body is completely
empty, then clang optimizer marks this function as unreachable and
later removes it (if using at least -O1). The FDEs for such removed
functions are not deleted, though, but instead, pc_begin and pc_end
values for these FDEs are adjusted to be the same values, and PC range
of the resulting FDE is 0.
ld.bfd discards 0-range FDEs while reading object files (the code for
it is in the file 'elf-eh-frame.c', function
'_bfd_elf_parse_eh_frame'), while gold includes such entries as-is.
Since these FDEs actually belong to optimized-out functions, there
usually is another valid function starting with the address which is
listed as PC_begin of the 0-range FDE, with its own FDE, containing
valid unwinding information. However, the GCC's unwinder (from
libgcc_s.so) uses only one FDE for a given PC_begin value (since how
can there reasonably be two different FDEs with exactly the same
starting address?), which sometimes happens to be the 0-range FDE
depending on the assembler layout. This FDE cannot be applied to any
address because of its range; the valid FDE for the stack frame is
ignored; the exception is not caught by the corresponding catch clause
and eventually triggers std::terminate.
The root cause of the issue seems to be somewhere in clang; however,
it appears reasonable to add a rather simple fix to gold to improve
its compatibility with ld.bfd, and to improve its robustness.
The original Android test case fixed by the supposed patch is here:
https://android.googlesource.com/platform/ndk/+/master/tests/device/test-stlport_static-exception/jni/dyncast2_1.cpp
To see the issue reproduced, you can compile the attached 'main.cpp'
using ld.gold and ld.bfd and examine the result with 'readelf -wf'. In
the gold-produced binary there will be a potentially faulty entry with
'pc=00000a10..00000a10'.
gold/ChangeLog:
Egor Kochetov <egor.kochetov@intel.com>
* ehframe.h: updated function prototypes to enable discarding
FDEs with 0 PC range
* ehframe.cc: added filtering of FDEs to discard those with 0 PC range.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: main.cpp
Type: text/x-c++src
Size: 263 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/binutils/attachments/20160225/f414d9e0/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: fde-filter.patch
Type: application/octet-stream
Size: 4424 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/binutils/attachments/20160225/f414d9e0/attachment.obj>
More information about the Binutils
mailing list