<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - libunwind: [ARM] EHABI getInfoFromEHABISection can fail if last .ARM.exidx table entry contains unwind information"
   href="https://llvm.org/bugs/show_bug.cgi?id=31091">31091</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>libunwind: [ARM] EHABI getInfoFromEHABISection can fail if last .ARM.exidx table entry contains unwind information
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libc++abi
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>3.9
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>All Bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>peter.smith@linaro.org
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org, mclow.lists@gmail.com
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>If the last entry of the .ARM.exidx table contains unwinding information
libunwind will be unable to find it.

I have been testing out lld's ARM port against the libcxxabi tests and found a
few exceptions test failures. These failures would disappear if I reordered the
functions so that no function that threw and caught an exception was after
main.

I tracked the point of failure down to getInfoFromEHABISection: 

template <typename A, typename R>
bool UnwindCursor<A, R>::getInfoFromEHABISection(
    pint_t pc,
    const UnwindInfoSections &sects) {
  EHABISectionIterator<A> begin =
      EHABISectionIterator<A>::begin(_addressSpace, sects);
  EHABISectionIterator<A> end =
      EHABISectionIterator<A>::end(_addressSpace, sects);

  EHABISectionIterator<A> itNextPC = std::upper_bound(begin, end, pc);
  if (itNextPC == begin || itNextPC == end)
    return false;
  EHABISectionIterator<A> itThisPC = itNextPC - 1;

  pint_t thisPC = itThisPC.functionAddress();
  pint_t nextPC = itNextPC.functionAddress();
  pint_t indexDataAddr = itThisPC.dataAddress();

If the last entry in the table contains the pc then upper_bound will return end
and return false. When I reorder the table entries main is last and the tests
don't throw through main so all thrown exceptions are caught as expected.

It turns out that ld.bfd inserts a sentinel EXIDX_CANTUNWIND .ARM.exidx entry
as the last entry in the table (usually the address of rodata is used) which
means that this implementation will always work when ld.bfd is used. 

A sentinel entry is useful as without it the scope of the last table entry is
the start of the program to the end of the address space (unless some other
information from the runtime is used to find the highest acceptable PC).
However I cannot find anywhere within the EHABI specification
<a href="http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf">http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf</a>
that requires the presence of a sentinel entry. Unless I've missed something I
think that the libunwind implementation isn't compliant with the specification.

As ld.bfd always adds a terminating table entry this can't be reproduced with
it.

I used the lld ARM port using libcxx libcxxabi and libunwind running
catch_pointer_nullptr.pass.cpp (the templated tests are generated after main).

It may be possible, even beneficial to get lld to add a sentinel terminating
table entry in the same way, however I think it is still worth raising this as
there are other third party linkers that may use libunwind and won't
necessarily add a sentinel.</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>