"failed looking up symbol _Unwind_Resume"

118 views
Skip to first unread message

Tomasz Grabiec

unread,
Oct 22, 2013, 3:31:32 PM10/22/13
to Osv Dev
Hi,

I've been investigating a problem with exceptions thrown from boost libraries. When exception is thrown OSv aborts with the message as in the title.

It turns out that these symbols are defined in libgcc_eh.a which we link into loader.elf. The problem is that the family of _Unwind_* symbols is declared with hidden visibility (binding global, visibility hidden). This causes that upon linking an executable object (loader.elf) they change binding to local and cannot be looked up dynamically anymore by current elf.cc code.

More on the visibility feature: http://gcc.gnu.org/wiki/Visibility

I created a quick dirty solution and modified libgcc_eh.a so that hidden symbols have default visibility. I needed to use manually tweaked objcopy as it did not have support for visibility manipulation out of the box. The problem goes away then, though I am not sure this is the path we want to follow.

I wanted to discuss the approach we should take to solve this.


--
Tomek

Nadav Har'El

unread,
Oct 23, 2013, 1:33:23 AM10/23/13
to Tomasz Grabiec, Osv Dev
On Tue, Oct 22, 2013 at 10:31 PM, Tomasz Grabiec <tgra...@cloudius-systems.com> wrote:
Hi,

I've been investigating a problem with exceptions thrown from boost libraries. When exception is thrown OSv aborts with the message as in the title.

It turns out that these symbols are defined in libgcc_eh.a which we link into loader.elf. The problem is that the family of _Unwind_* symbols is declared with hidden visibility (binding global, visibility hidden). This causes that upon linking an executable object (loader.elf) they change binding to local and cannot be looked up dynamically anymore by current elf.cc code.

If that is the case, how come the exception in tst-excecpt.so does work? This is also a shared library that throws an exception, so what is different there? Can you expand tst-except.so to demonstrate a case of exception-throwing that doesn't work correctly today (without boost)?

 There's another ugly point to consider - we also link loader.elf with libunwind.a, and it appears it also has its own version of _Unwind_Resume and other functions. I don't remember why we actually do this... But I'm assuming the linker doesn't actually pick up this function from libunwind.a, as it is  already available from libgcc_eh.a.


More on the visibility feature: http://gcc.gnu.org/wiki/Visibility

I created a quick dirty solution and modified libgcc_eh.a so that hidden symbols have default visibility. I needed to use manually tweaked objcopy as it did not have support for visibility manipulation out of the box. The problem goes away then, though I am not sure this is the path we want to follow.

I wanted to discuss the approach we should take to solve this.


--
Tomek

--
You received this message because you are subscribed to the Google Groups "OSv Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to osv-dev+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--

Tomasz Grabiec

unread,
Oct 23, 2013, 4:41:44 AM10/23/13
to Nadav Har'El, Osv Dev
On Wed, Oct 23, 2013 at 7:33 AM, Nadav Har'El <n...@cloudius-systems.com> wrote:
On Tue, Oct 22, 2013 at 10:31 PM, Tomasz Grabiec <tgra...@cloudius-systems.com> wrote:
Hi,

I've been investigating a problem with exceptions thrown from boost libraries. When exception is thrown OSv aborts with the message as in the title.

It turns out that these symbols are defined in libgcc_eh.a which we link into loader.elf. The problem is that the family of _Unwind_* symbols is declared with hidden visibility (binding global, visibility hidden). This causes that upon linking an executable object (loader.elf) they change binding to local and cannot be looked up dynamically anymore by current elf.cc code.

If that is the case, how come the exception in tst-excecpt.so does work? This is also a shared library that throws an exception, so what is different there? Can you expand tst-except.so to demonstrate a case of exception-throwing that doesn't work correctly today (without boost)?

I'll try to put up something which fails in the same way, I only checked that when exceptions are thrown from tst-except, _Unwind_Resume symbol is not looked up. I need to figure out when this symbol is actually used.
 

 There's another ugly point to consider - we also link loader.elf with libunwind.a, and it appears it also has its own version of _Unwind_Resume and other functions. I don't remember why we actually do this... But I'm assuming the linker doesn't actually pick up this function from libunwind.a, as it is  already available from libgcc_eh.a.

The symbols from libgcc_eh.a have precedence over the ones from libunwind.a. I made an experiment and converted symbols in libgcc_eh.a to local and pulled libunwind inside --whole-archive so that protected symbols from libunwind.a became visible externally. Unfortunately it doesn't quite work, the program aborts with "Attempted to execute null pointer" or something like this, the backtrace was in _Unwind_Resume, I didn't bother to debug it.

Note that when symbols from libgcc_eh are made visible boost libs throw exceptions just fine.

Avi Kivity

unread,
Oct 23, 2013, 5:16:29 AM10/23/13
to Nadav Har'El, Tomasz Grabiec, Osv Dev
On 10/23/2013 06:33 AM, Nadav Har'El wrote:
On Tue, Oct 22, 2013 at 10:31 PM, Tomasz Grabiec <tgra...@cloudius-systems.com> wrote:
Hi,

I've been investigating a problem with exceptions thrown from boost libraries. When exception is thrown OSv aborts with the message as in the title.

It turns out that these symbols are defined in libgcc_eh.a which we link into loader.elf. The problem is that the family of _Unwind_* symbols is declared with hidden visibility (binding global, visibility hidden). This causes that upon linking an executable object (loader.elf) they change binding to local and cannot be looked up dynamically anymore by current elf.cc code.

If that is the case, how come the exception in tst-excecpt.so does work? This is also a shared library that throws an exception, so what is different there? Can you expand tst-except.so to demonstrate a case of exception-throwing that doesn't work correctly today (without boost)?

 There's another ugly point to consider - we also link loader.elf with libunwind.a, and it appears it also has its own version of _Unwind_Resume and other functions. I don't remember why we actually do this... But I'm assuming the linker doesn't actually pick up this function from libunwind.a, as it is  already available from libgcc_eh.a.

libunwind.a was added at a very early point, it's possible that subsequent changes made it unnecessary.

Ordinary binaries don't link with it, I don't see why we should.

Tomasz Grabiec

unread,
Oct 23, 2013, 5:30:19 AM10/23/13
to Avi Kivity, Nadav Har'El, Osv Dev
I managed to create a test case for this:

Patch:
diff --git a/tests/tst-except.cc b/tests/tst-except.cc
index 91124a6..f108262 100644
--- a/tests/tst-except.cc
+++ b/tests/tst-except.cc
@@ -16,6 +16,19 @@ static void report(bool ok, const char* msg)
     debug("%s: %s\n", (ok ? "PASS" : "FAIL"), msg);
 }
 
+class Resource {
+public:
+    ~Resource() {
+        debug("bye!\n");
+    }
+};
+
+Resource throw_with_unwind_resume() {
+    Resource x;
+    throw 1;
+    return x;
+}
+
 int main(int ac, char** av)
 {
     try {
@@ -24,6 +37,15 @@ int main(int ac, char** av)
     } catch (int e) {
         report (e == 1, "catch 1");
     }
+
+    try {
+        throw_with_unwind_resume();
+        report (0, "don't continue after throw");
+    } catch(int e) {
+        report (e == 1, "catch 1");
+    }
+
+
     debug("SUMMARY: %d tests, %d failures\n", tests, fails);
 
 }


Console output:

  (...)
  PASS: catch 1
  bye!
  failed looking up symbol _Unwind_Resume
  Aborted

Nadav Har'El

unread,
Oct 23, 2013, 5:44:39 AM10/23/13
to Tomasz Grabiec, Avi Kivity, Osv Dev
On Wed, Oct 23, 2013 at 12:30 PM, Tomasz Grabiec <tgra...@cloudius-systems.com> wrote:
I managed to create a test case for this:

Thanks great.
Now it will be easier to look for (and test) the solution.

Nadav Har'El

unread,
Oct 23, 2013, 10:09:07 AM10/23/13
to Avi Kivity, Tomasz Grabiec, Osv Dev
On Wed, Oct 23, 2013 at 12:16 PM, Avi Kivity <a...@cloudius-systems.com> wrote:
libunwind.a was added at a very early point, it's possible that subsequent changes made it unnecessary.

Ordinary binaries don't link with it, I don't see why we should.

It would be really great if we can eliminate the separate use of libunwind.a - especially since we have to compile it ourselves.
I guess somebody will need to invest some time to understand why we need libunwind.a at all.

Note one place we currently use libunwind.a is in libc/misc/backtrace.cc. I have in backtrace.cc a second implementation using the gcc runtime instead of libunwind, so it's worth revisiting it too. But we need to figure out first why libunwind.a is needed besides backtrace() (backtrace() was added to OSv much later than libunwind).

Tomasz Grabiec

unread,
Oct 31, 2013, 2:34:32 PM10/31/13
to Nadav Har'El, Avi Kivity, Osv Dev
I created a github issue for this: https://github.com/cloudius-systems/osv/issues/76
Reply all
Reply to author
Forward
0 new messages