Interaction of fno-exceptions and POSITION INDEPENDENT CODE

Viewed 115

I ran into a rather bizarre issue while building a dynamic library. Here are details with a small example:

A simple file called static.h whose contents are:

#pragma once

#include <string>

std::string static_speak();

static.cpp looks like this:

#include "static.h"

std::string static_speak() {
  return "I am static";
}

one can build a static library with these two files (using cmake) as:

add_library(static
  static.cpp
)

Now, consider another file called shared.cpp whose contents are:

#include "static.h"

std::string dynamic_speak() {
  return static_speak() + " I am dynamic";
}

One can try to build a dynamic library (again using cmake) as:

add_library(shared SHARED
  shared.cpp
)
target_link_libraries(shared PRIVATE
  static
)

When one tries to build the above, one will run into the following error:

[4/4] Linking CXX shared library libshared.so
FAILED: libshared.so
: && /opt/vatic/bin/clang++ -fPIC -g   -shared -Wl,-soname,libshared.so -o libshared.so CMakeFiles/shared.dir/shared.cpp.o  libstatic.a && :                                 
/usr/bin/ld: libstatic.a(static.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC                    
/usr/bin/ld: final link failed: Nonrepresentable section on output
clang-10: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.

This makes sense. We didn't compile static with POSITION_INDEPENDENT_CODE. That is easily fixable via:

add_library(static
  static.cpp
)
set_target_properties(static
  PROPERTIES
  POSITION_INDEPENDENT_CODE ON
)

Everything works perfectly now when one compiles shared library.

Now here is the problem. Let's say I didn't enable POSITION_INDEPENDENT_CODE but instead disabled exceptions (!) in my code as:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")

Now when I try to compile shared, everything still works!! How are exceptions and fPIC related to each other?

Here is a repo to reproduce the issue: https://github.com/skgbanga/shared

1 Answers

How are exceptions and fPIC related to each other?

They aren't (mostly).

What happens is that compiling with -fno-exceptions changes the relocations (certain exception-related data is no longer referenced), and because of that, there is no relocation which causes the error at link time.

You can confirm this by building with and without -fno-exceptions, and comparing output from objdump -dr CMakeFiles/static.dir/static.cpp.o.

P.S. I could not reproduce your problem using g++ (Debian 9.3.0-8), because it defaults to building with -fPIE, and both links succeed.

And if I add -fno-pie, then both links fail the same way.

Related