Bug 200171 - lang/gcc5: set rpath by default via the gcc, g++, gfortran,... drivers
Summary: lang/gcc5: set rpath by default via the gcc, g++, gfortran,... drivers
Status: New
Alias: None
Product: Ports & Packages
Classification: Unclassified
Component: Individual Port(s) (show other bugs)
Version: Latest
Hardware: Any Any
: --- Affects Some People
Assignee: Gerald Pfeifer
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-05-13 14:49 UTC by Roger Leigh
Modified: 2018-08-04 15:26 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Roger Leigh 2015-05-13 14:49:48 UTC
I've tried to make a minimal test case for this but haven't succeeded as yet, maybe I don't have the right pattern of shared libs and call stack, but I can hopefully explain exactly what's wrong.

I've built GCC from ports (lang/gcc5), and then updated make.conf and rebuilt all ports from scratch using gcc5, so everything under /usr/local is built by gcc5.

My program, using xerces-c3 and consisting of a number of shared libraries, dies when it encounters invalid input in a unit test.  The code is below, with the site that throws an exception marked with *****.  What happens is that the parser throws a xercesc::XMLErrs::Codes enum (which is expected).  However, the surprising part is that it's not caught by the "catch(...)" block, or an explicit catch for the type in question (not shown here).  Instead it immediately aborts via abort() and verbose_terminate_handler().  This is because the shared libraries, executables are all linked against libgcc_s.so and ldd shows it to be using the copy from /lib (GCC4.2).  If I use LD_LIBRARY_PATH to make it use the copy from /usr/local/lib/gcc5, then everything works correctly.

So the essence of this bug report is basically to ask whether the GCC ports could force the use of a newer libgcc_s.so e.g. with rpath or the like, so that exception handling can work properly for shared libraries and programs built with gcc from ports.  The default works for the simple case (one shared lib and/or a standalone binary), but not for more complex cases.

  void
  read_source(xercesc::XercesDOMParser& parser,
              xercesc::InputSource&     source)
  {
    // To clean up properly due to the lack of Xerces
    // exception-safety, track if we need to throw an exception after
    // cleanup.
    bool ok = false;
    std::string fail_message;

    ome::common::xml::ErrorReporter er;
    parser.setErrorHandler(&er);

    ome::common::xml::EntityResolver res;
    parser.setXMLEntityResolver(&res);

    try
      {
        parser.parse(source); **** Exception thrown here ****
        ok = true;
      }
    catch (const xercesc::XMLException& toCatch)
      {
        fail_message = "XMLException during DOM XML parsing: ";
        fail_message += ome::common::xml::String(toCatch.getMessage());
      }
    catch (const xercesc::DOMException& toCatch)
      {
        fail_message = "DOMException during DOM XML parsing: ";
        fail_message += ome::common::xml::String(toCatch.getMessage());
      }
    catch (...) **** Exception *not* handled here ****
      {
        fail_message = "Unexpected exception during DOM XML writing";
      }

    if (!ok)
      throw std::runtime_error(fail_message);
   if (er || !parser.getDocument())
      throw std::runtime_error("Parse error");
  }
Comment 1 Gerald Pfeifer freebsd_committer 2015-11-08 19:42:09 UTC
For ports employing USE_GCC this works fine due to the following
code in Mk/bsd.gcc.mk:

  _GCC_RUNTIME:=          ${LOCALBASE}/lib/gcc${V}
  CFLAGS+=                -Wl,-rpath=${_GCC_RUNTIME}
  CXXFLAGS+=              -Wl,-rpath=${_GCC_RUNTIME}
  LDFLAGS+=               -Wl,-rpath=${_GCC_RUNTIME} -L${_GCC_RUNTIME}

You can do the equivalent of this for your own builds.

I assume, though, that what you are really asking for is for the
lang/gcc* ports to add this fully automatically.
Comment 2 Roger Leigh 2015-11-08 20:13:17 UTC
Yes, exactly.

While Mk/bsd.gcc.mk can set this correctly and automatically when building ports, this fails to work when building anything which isn't a port, such as building my own software during development and for testing and debugging--any invocation of the compiler outside a port build can therefore result in subtly broken builds.  If there was an error at build time, then I could live with it, but the subtlety of how exception handling is broken is not--it took some time to figure out what was going on.  I think it would be reasonable for the compiler to always use a suitable libgcc so that such errors can not occur.


Kind regards,
Roger
Comment 3 Gerald Pfeifer freebsd_committer 2018-08-04 15:26:48 UTC
PR 223279 also would have benefited (been avoid) by this.