[cfe-dev] Linker error and obfuscated name: Part II

Edward Diener eldlistmailingz at tropicsoft.com
Fri Aug 7 07:07:15 PDT 2015


On 8/6/2015 4:58 PM, David Majnemer wrote:
>
>
> On Thu, Aug 6, 2015 at 1:21 PM, Edward Diener
> <eldlistmailingz-5p0dqD/c5LGWd6l5hS35sQ at public.gmane.org
> <mailto:eldlistmailingz-5p0dqD/c5LGWd6l5hS35sQ at public.gmane.org>> wrote:
>
>     On 8/6/2015 12:44 PM, Reid Kleckner wrote:
>
>         Hm, GCC never tries to import RTTI, so maybe it makes sense that we
>         never export it. Anyway, there's a bug here. Maybe David knows
>         what's up.
>
>
>     I tried this simple example:
>
>     // ex_aclass.hpp
>
>     #ifndef EX_ACLASS_HPP
>     #define EX_ACLASS_HPP
>     #if defined(BLD_EX_EXAMPLE)
>              #define EX_DECL __attribute__((__dllexport__))
>     #else
>              #define EX_DECL __attribute__((__dllimport__))
>     #endif
>     class EX_DECL ex_aclass
>     {
>     public:
>          int a_function(long);
>     };
>     #endif // EX_ACLASS_HPP
>
>     // ex_aclass.cpp
>
>     #define BLD_EX_EXAMPLE
>     #include "ex_aclass.hpp"
>     int ex_aclass::a_function(long amt)
>              {
>              return(amt > 1000000 ? 10 : 20);
>              }
>
>     // Compile ex_aclass
>
>     clang++.exe -c -x c++ -D__MINGW_FORCE_SYS_INTRINS -O0 -g -fno-inline
>     -Wall -g -march=i686 -m32 -o "ex_aclass.obj" "ex_aclass.cpp"
>
>     // Link to ex_ac dll
>
>     clang++.exe -o "ex_ac.dll" -Wl,-soname -Wl,ex_ac.dll -shared
>     -Wl,--start-group "ex_aclass.obj" -Wl,-Bstatic -Wl,-Bdynamic
>     -Wl,--end-group -g -march=i686 -m32
>
>     // ex_use_aclass.cpp
>
>     #include "ex_aclass.hpp"
>     int main(int argc,char * argv[])
>              {
>              ex_aclass aclass;
>              int ret(aclass.a_function(10000));
>              return ret;
>              }
>
>     // Compile ex_use_aclass
>
>     clang++.exe -c -x c++ -D__MINGW_FORCE_SYS_INTRINS -O0 -g -fno-inline
>     -Wall -g -march=i686 -m32 -o "ex_use_aclass.obj" "ex_use_aclass.cpp"
>
>     // Link ex_use_ac executable
>
>     clang++.exe -Wl,-R -Wl,"." -Wl,-rpath-link -Wl,"." -o
>     "ex_use_ac.exe" -Wl,--start-group "ex_use_aclass.obj" "ex_ac.dll"
>     -Wl,-Bstatic -Wl,-Bdynamic -Wl,--end-group -g -march=i686 -m32
>
>     All of this worked with no problems.
>
>     So the basic ability to access functionality in a class in a DLL
>     from outside that DLL works fine using clang on Windows. It is
>     something specific in my original example below that is causing
>     linking problems, whether I export entire classes or whether I
>     export individual member functions. Just thought I would let you
>     know. Needless to say I need to solve my original problem because
>     that code mimics the design of a very small portion of the Boost
>     serialization library and is the cause why the Boost serialization
>     library will not build with clang on Windows targeting gcc.
>
>
> Should be fixed in r244266.

I got the latest llvm/clang and rebuilt clang. Now for my simple example 
above, which previously built without any errors, I get when just 
linking the shared library:

clang++.exe -o "ex_ac" -Wl,-soname -Wl,ex_ac.dll -shared 
-Wl,--start-group "ex_aclass.obj" -Wl,-Bstatic -Wl,-Bdynamic 
-Wl,--end-group -g -march=i686 -m32

C:\Utilities\mingw-w64\i686-5.1.0-posix-dwarf-rt_v4-rev0\mingw32\i686-w64-mingw32\lib/libmingw32.a(lib32_libmingw32_a-pseudo-reloc.o):pseudo-reloc.c:(.text+0x1d6): 
undefined reference to `__chkstk_ms'
clang++.exe: error: linker command failed with exit code 1 (use -v to 
see invocation)

I do not know if r244266 is responsible for this but the latest clang on 
Windows targeting gcc has an even more serious problem now when trying 
to build a dll. In fac every attempt to link a shared library now gets 
this error regarding 'undefined reference to `__chkstk_ms'.

>
>
>
>         On Thu, Aug 6, 2015 at 9:36 AM, Reid Kleckner
>         <rnk-hpIqsD4AKlfQT0dZR+AlfA-XMD5yJDbdMReXY1tMh2IBg at public.gmane.org
>         <mailto:rnk-hpIqsD4AKlfQT0dZR%2BAlfA-XMD5yJDbdMReXY1tMh2IBg at public.gmane.org>
>
>         <mailto:rnk-hpIqsD4AKlfQT0dZR+AlfA-XMD5yJDbdMReXY1tMh2IBg at public.gmane.org
>         <mailto:rnk-hpIqsD4AKlfQT0dZR%2BAlfA-XMD5yJDbdMReXY1tMh2IBg at public.gmane.org>>>
>         wrote:
>
>              I reproduced your example, and it looks like we are
>         forgetting to
>              export RTTI with dllexport in Itanium. We only export the
>         vtable.
>              This is what each compiler exports for ex_xml_exception.obj:
>
>              $ dumpbin -directives ex_xml_exception.clang.obj | grep
>         -export:_ZT
>              | c++filt --no-strip-underscore
>                  -export:virtual thunk to
>         ex_xml_exception::~ex_xml_exception()
>                  -export:virtual thunk to
>         ex_xml_exception::~ex_xml_exception()
>                  -export:vtable for ex_xml_exception,data
>
>              $ dumpbin -directives ex_xml_exception.gcc.obj | grep
>         -export:_ZT |
>              c++filt --no-strip-underscore
>                  -export:typeinfo for ex_exception,data
>                  -export:typeinfo for ex_xml_exception,data
>                  -export:construction vtable for
>              ex_exception-in-ex_xml_exception,data
>                  -export:VTT for ex_xml_exception,data
>                  -export:vtable for ex_xml_exception,data
>                  -export:virtual thunk to
>         ex_xml_exception::~ex_xml_exception()
>                  -export:virtual thunk to
>         ex_xml_exception::~ex_xml_exception()
>
>              In your previous example where the whole class wasn't
>         exported, I
>              think we might be doing the wrong thing when the key
>         function is
>              dllimport / dllexport. We think that it will provide exported
>              symbols for vtables and RTTI but it doesn't. This is
>         something we
>              didn't run into because the MSVC ABI doesn't have key
>         functions.
>
>              On Thu, Aug 6, 2015 at 6:16 AM, Edward Diener
>              <eldlistmailingz-5p0dqD/c5LGWd6l5hS35sQ at public.gmane.org
>         <mailto:eldlistmailingz-5p0dqD/c5LGWd6l5hS35sQ at public.gmane.org>
>              <mailto:eldlistmailingz-5p0dqD
>         <mailto:eldlistmailingz-5p0dqD>/c5LGWd6l5hS35sQ-XMD5yJDbdMReXY1tMh2IBg at public.gmane.org
>         <mailto:c5LGWd6l5hS35sQ at public.gmane.org>>> wrote:
>
>                  Using clang on Windows targeting mingw(-64)/gcc since
>         it does
>                  not appear possible to export individual member
>         functions of a
>                  class, as well as export the RTTI of the class, without
>                  exporting the entire class, I have changed my example
>         in my post
>                  "Linker error and obfuscated name" to export the entire
>         class
>                  itself. But I am still seeing a linker error, Here is the
>                  changed code and command lines:
>
>                  // ex_decl.hpp
>
>                  #ifndef EX_DECL_HPP
>                  #define EX_DECL_HPP
>                  #if defined(BLD_EX_EXAMPLE)
>                       #define EX_DECL __attribute__((__dllexport__))
>                  #else
>                       #define EX_DECL __attribute__((__dllimport__))
>                  #endif
>                  #endif // EX_DECL_HPP
>
>                  // ex_exception.hpp
>
>                  #ifndef EX_EXCEPTION_HPP
>                  #define EX_EXCEPTION_HPP
>                  #include <exception>
>                  #include "ex_decl.hpp"
>                  class EX_DECL ex_exception :
>                       public virtual std::exception
>                  {
>                  private:
>                       char m_buffer[128];
>                  protected:
>                       unsigned int append(unsigned int l, const char * a);
>                       ex_exception() ;
>                  public:
>                       typedef enum {
>                         no_exception,
>                         other_exception
>                       } ex_exception_code;
>                       ex_exception_code code;
>                       ex_exception(ex_exception_code c,const char * e1 =
>         0,const
>                  char * e2 = 0) ;
>                       ex_exception(ex_exception const &) ;
>                       virtual ~ex_exception() throw() ;
>                       virtual const char * what() const throw() ;
>                  };
>                  #endif // EX_EXCEPTION_HPP
>
>                  // ex_exception.cpp
>
>                  #include <exception>
>                  #include <cstring>
>                  #define BLD_EX_EXAMPLE
>                  #include "ex_exception.hpp"
>                  unsigned int ex_exception::append(unsigned int l, const
>         char * a){
>                       while(l < (sizeof(m_buffer) - 1)){
>                           char c = *a++;
>                           if('\0' == c)
>                               break;
>                           m_buffer[l++] = c;
>                       }
>                       m_buffer[l] = '\0';
>                       return l;
>                  }
>                  ex_exception::ex_exception(ex_exception_code c,const char *
>                  e1,const char * e2) : code(c)
>                  {
>                     unsigned int length = 0;
>                       switch(code){
>                       case no_exception:
>                           length = append(length, "uninitialized
>         exception");
>                           break;
>                       case other_exception:
>                           length = append(length, "unknown derived
>         exception");
>                           break;
>                       default:
>                           length = append(length, "programming error");
>                           break;
>                       }
>                  }
>                  ex_exception::ex_exception(ex_exception const & oth) :
>                  std::exception(oth),code(oth.code)
>                  {
>                       std::memcpy(m_buffer,oth.m_buffer,sizeof m_buffer);
>                  }
>                  ex_exception::~ex_exception() throw() {}
>                  const char * ex_exception::what() const throw() { return
>                  m_buffer; }
>                  ex_exception::ex_exception() : code(no_exception) {}
>
>                  // Compile ex_exception.cpp
>
>                  clang++.exe -c -x c++ -D__MINGW_FORCE_SYS_INTRINS
>                  -Wno-unused-local-typedef
>         -Wno-dll-attribute-on-redeclaration
>                  -O0 -g -fno-inline -Wall -g -march=i686 -m32 -o
>                  "ex_exception.obj" "ex_exception.cpp"
>
>                  // ex_xml_exception.hpp
>
>                  #ifndef EX_XML_EXCEPTION_HPP
>                  #define EX_XML_EXCEPTION_HPP
>                  #include <exception>
>                  #include "ex_decl.hpp"
>                  #include "ex_exception.hpp"
>                  class EX_DECL ex_xml_exception :
>                       public virtual ex_exception
>                  {
>                  public:
>                       typedef enum {
>                           xml_archive_parsing_error,
>                           xml_archive_tag_mismatch,
>                           xml_archive_tag_name_error
>                       } ex_exception_code;
>                       ex_xml_exception(ex_exception_code c,const char * e1 =
>                  0,const char * e2 = 0);
>                       ex_xml_exception(ex_xml_exception const &) ;
>                       virtual ~ex_xml_exception() throw() ;
>                  };
>                  #endif // EX_XML_EXCEPTION_HPP
>
>                  // ex_xml_exception.cpp
>
>                  #include <exception>
>                  #define BLD_EX_EXAMPLE
>                  #include "ex_xml_exception.hpp"
>                  ex_xml_exception::ex_xml_exception(ex_exception_code
>         c,const
>                  char * e1,const char * e2) :
>                           ex_exception(other_exception, e1, e2)
>                       {
>                           switch(c){
>                           case xml_archive_parsing_error:
>                               ex_exception::append(0, "unrecognized XML
>         syntax");
>                               break;
>                           case xml_archive_tag_mismatch:
>                               ex_exception::append(0, "XML start/end tag
>         mismatch");
>                               if(0 != e1){
>                                   ex_exception::append(0, " - ");
>                                   ex_exception::append(0, e1);
>                               }
>                               break;
>                           case xml_archive_tag_name_error:
>                               ex_exception::append(0, "Invalid XML tag
>         name");
>                               break;
>                           default:
>                               ex_exception::append(0, "programming error");
>                               break;
>                           }
>                       }
>                  ex_xml_exception::ex_xml_exception(ex_xml_exception
>         const & oth)
>                  : std::exception(oth),ex_exception(oth){}
>                  ex_xml_exception::~ex_xml_exception() throw() {}
>
>                  // Compile ex_xml_exception.cpp
>
>                  clang++.exe -c -x c++ -D__MINGW_FORCE_SYS_INTRINS
>                  -Wno-unused-local-typedef
>         -Wno-dll-attribute-on-redeclaration
>                  -O0 -g -fno-inline -Wall -g -march=i686 -m32 -o
>                  "ex_xml_exception.obj" "ex_xml_exception.cpp"
>
>                  // Link exmp-clang37-d-1_59.dll
>
>                  clang++.exe -o "exmp-clang37-d-1_59.dll" -Wl,-soname
>                  -Wl,exmp-clang37-d-1_59.dll -shared -Wl,--start-group
>                  "ex_exception.obj" "ex_xml_exception.obj"  -Wl,-Bstatic
>                  -Wl,-Bdynamic  -Wl,--end-group -g -march=i686 -m32
>
>                  // throw_exception_ex.cpp
>
>                  #include "ex_xml_exception.hpp"
>                  template<class E> void throw_exception(E const & e) {
>         throw e; }
>                  int main(int argc,char * argv[])
>                  {
>                       if (argc > 1)
>                             {
>
>
>         throw_exception(ex_xml_exception(ex_xml_exception::xml_archive_parsing_error));
>
>                             }
>                       return 0;
>                  }
>
>                  // Compile throw_exception_ex.cpp
>
>                  clang++.exe -c -x c++ -D__MINGW_FORCE_SYS_INTRINS
>                  -Wno-unused-local-typedef
>         -Wno-dll-attribute-on-redeclaration
>                  -O0 -g -fno-inline -Wall -g -march=i686 -m32 -o
>                  "throw_exception_ex.obj" "throw_exception_ex.cpp"
>
>                  // Link thr_exmp.exe
>
>                  clang++.exe -Wl,-R -Wl,"." -Wl,-rpath-link -Wl,"." -o
>                  "thr_exmp.exe" -Wl,--start-group "throw_exception_ex.obj"
>                  "exmp-clang37-d-1_59.dll" -Wl,-Bstatic -Wl,-Bdynamic
>                  -Wl,--end-group -g -march=i686 -m32
>
>                  // Error message from this link
>
>                  throw_exception_ex.obj: In function
>                  `Z15throw_exceptionI16ex_xml_exceptionEvRKT_':
>                  throw_exception_ex.cpp:2: undefined reference to
>                  `_imp___ZTI16ex_xml_exception'
>                  clang++.exe: error: linker command failed with exit
>         code 1 (use
>                  -v to see invocation)
>
>                  So even when I export/import the entire class rather than
>                  individual member functions, I can not link my final module
>                  successfully as it is still looking for something in
>         the shared
>                  library that it says is not there.
>
>                  This same code succeeds without problem with
>         mingw(-64)/gcc on
>                  Windows.




More information about the cfe-dev mailing list