This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

FDE with 0 PC range filtering for gold


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.
#include <cstdio>

int f() {}
int g() {
    try {
        throw "1";
    } catch (const char*) {
        throw 1;
    }
}

int main() {
  try {
    g();
    return 1;
  } catch (int) {
      printf ("caught int\n");
      return 0;
  }
  return 2;
}

Attachment: fde-filter.patch
Description: Binary data


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]