bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug gold/19735] New: Incorrect handling of 0-PC-range FDEs


From: gluk47 at gmail dot com
Subject: [Bug gold/19735] New: Incorrect handling of 0-PC-range FDEs
Date: Fri, 26 Feb 2016 12:19:42 +0000

https://sourceware.org/bugzilla/show_bug.cgi?id=19735

            Bug ID: 19735
           Summary: Incorrect handling of 0-PC-range FDEs
           Product: binutils
           Version: 2.27 (HEAD)
            Status: NEW
          Severity: normal
          Priority: P2
         Component: gold
          Assignee: ccoutant at gmail dot com
          Reporter: gluk47 at gmail dot com
                CC: ian at airs dot com
  Target Milestone: ---

Created attachment 9044
  --> https://sourceware.org/bugzilla/attachment.cgi?id=9044&action=edit
Suggested solution

There is a case in which gold produces binaries with broken exception handling,
while ld.bfd produces correct binaries.

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 shrinks its
address range to zero (generates no assembly code, if using at least -O1). The
FDEs (stack frame unwinder information entries) for such shrunk 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 the shrunk 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 normally no
two different functions share 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.

It is not clear whether clang behavior is completely sane here; 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 code below 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 zero range like
'pc=00000a10..00000a10' and later an FDE with the same starting address.

int f() {}
int main () {
  try {
    throw 1;
    return 1;
  } catch (int) {
    return 0;
  }
  return 2;
}

-- 
You are receiving this mail because:
You are on the CC list for the bug.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]