LLVM-5.0 Makefile undefined reference fail - c++

Including the following statement in my code
main_module->dump(); // main_module is of type llvm::Module*
causes the following linker error:
undefined reference to 'llvm::Module::dump() const'
The dump method resides in /usr/lib/llvm-5.0/include/llvm/IR/Module.h
I checked stack overflow (Using llvm::Function::dump(), linker gives "undefined reference to `llvm::Value::dump() const'"), and it seems we get this error when the linker isn't fed the libraries in correct order. However, I clearly have the libraries in the end in my compilation command:
clang++-5.0 -g -O3 main.cpp -o main llvm-config-5.0 --cxxflags --ldflags --system-libs --libs core mcjit native
Any help is appreciated.
The weird thing is, the linker figured out that the type of the dump method. It clearly went in the include file. So why would it call it an undefined reference?
Code I am trying to run:
`
# include "llvm/IR/LLVMContext.h"
# include "llvm/IR/Module.h"
# include "llvm/IR/IRBuilder.h"
# include <iostream>
using namespace llvm;
static LLVMContext ctxt;
static IRBuilder<> builder(ctxt);
int main(int argc, char** argv) {
Module* main_module = new Module("main_module", ctxt);
std::cout << main_module->getModuleIdentifier() << "\n";
FunctionType* func_type = FunctionType::get(builder.getInt32Ty(), false);
Function* main_func = Function::Create(func_type,Function::ExternalLinkage, "main", main_module);
if (main_module->getFunction("main")) {
std::cout << "Found function!\n";
}
main_module->dump(); // need this for debugging and testing reasons with LLVM
return 0;
}

In addition to the solution that Subrat provided, you can adjust your code to avoid calling dump. You can achieve the same thing by calling:
main_module->print(llvm::outs(), nullptr);
Similarly, if you want to dump a LLVM function, you can write:
main_func->print(llvm::outs());
Actually, as of LLVM 5.0.0, this is how the dump() function is implemented.

Seems like the definition for dump is in ASMWriter.cpp, which seems to be depracated.
Also, ASMWrite.cpp's debug method refers to dbgs() which is in debug.cpp
I fixed the problem by copying over debug.cpp and the Module::dump() (from ASMWriter.cpp--since I don't need the whole code, only a specific subroutine from this file) routine and putting it in my cpp file.

Related

dlopen succeeds (or at least seems to) but then dlsym fails to retrieve a symbol from a shared library

In an attempt to undersand how lazily loaded dynamic libraries work, I've made up the following (unfortunately non-working) example.
dynamic.hpp - Header of the library
#pragma once
void foo();
dynamic.cpp - Implementation of the library
#include "dynamic.hpp"
#include <iostream>
void foo() {
std::cout << "Hello world, dynamic library speaking" << std::endl;
}
main.cpp - main function that wants to use the library (edited from the snippet in this question)
#include <iostream>
#include <dlfcn.h>
#include "dynamic.hpp"
int main() {
void * lib = dlopen("./libdynamic.so", RTLD_LAZY);
if (!lib) {
std::cerr << "Error (when loading the lib): " << dlerror() << std::endl;
}
dlerror();
auto foo = dlsym(lib, "foo");
auto error = dlerror();
if (error) {
std::cerr << "Error (when loading the symbol `foo`): " << error << std::endl;
}
dlerror();
using Foo = void (*)();
(Foo(foo)());
}
Compilation and linking¹
# compile main.cpp
g++ -g -O0 -c main.cpp
# compile dynamic.cpp into shared library
g++ -fPIC -Wall -g -O0 -pedantic -shared -std=c++20 dynamic.cpp -o libdynamic.so
# link
g++ -Wall -g -pedantic -L. -ldynamic main.o -o main
Run
LD_LIBRARY_PATH='.' ./main
Error
Error (when loading the symbol `foo`): ./libdynamic.so: undefined symbol: foo
Segmentation fault (core dumped)
As far as I can tell, the error above clearly shows that the library is correctly loaded, but it's the retrieval of the symbol which fails for some reason.
(¹) A few options are redundant or, at least, not necessary. I don't think this really affects what's happening, but if you think so, I can try again with the options you suggest.
auto foo = dlsym(lib, "foo");
Perform the following simple thought experiment: in C++ you can have overloaded functions:
void foo();
void foo(int bar);
So, if your shared library has these two functions, which one would you expect to get from a simple "dlsym(lib, "foo")" and why that one, exactly?
If you ponder and wrap your brain around this simple question you will reach the inescapable conclusion that you must be missing something fundamental. And you are: name mangling.
The actual symbol names used for functions in C++ code are "mangled". That is, if you use objdump and/or nm tools to dump the actual symbols in the shared libraries you will see a bunch of convoluted symbols, with "foo" hiding somewhere in the middle of them.
The mangling is used to encode the "signature" of a function: its name and the type of its parameters, so that different overloads of "foo" produce distinct and unique symbol names.
You need to feed the mangled name into dlsym in order to resolve the symbol.

Trivial Eigen3 Tensor program does not build without -On

I'm trying to build a write of software with the Tensor module provided as unsupported from eigen3. I've written a simple piece of code that will build with a simple application of VectorXd (just printing it to stdout), and will also build with an analogous application of Tensor in place of the VectorXd, but WILL NOT build when I do not throw an optimization flag (-On). Note that my build is from within a conda enviromnent that is using conda-forge compilers, so the g++ in what follows is the g++ obtained from conda forge for ubuntu. It says its name in the error messages following, if that is perceived to be the issue.
I have a feeling this is not about the program I'm trying to write, but just in case I've included an mwe.cpp that seems to produce the error. The code follows:
#include <eigen3/Eigen/Dense>
#include <eigen3/unsupported/Eigen/CXX11/Tensor>
#include <iostream>
using namespace Eigen;
using namespace std;
int main(int argc, char const *argv[])
{
VectorXd v(6);
v << 1, 2, 3, 4, 5, 6;
cout << v.cwiseSqrt() << "\n";
Tensor<double, 1> t(6);
for (auto i=0; i<v.size(); i++){
t(i) = v(i);
}
cout << "\n";
for (auto i=0; i<t.size(); i++){
cout << t(i) << " ";
}
cout << "\n";
return 0;
}
If the above code is compiled without any optimizations, like:
g++ -I ~/miniconda3/envs/myenv/include/ mwe.cpp -o mwe
I get the following compiler error:
/home/myname/miniconda3/envs/myenv/bin/../lib/gcc/x86_64-conda_cos6-linux-gnu/7.3.0/../../../../x86_64-conda_cos6-linux-gnu/bin/ld: /tmp/cc2q8gj4.o: in function `Eigen::internal::(anonymous namespace)::get_random_seed()':
mwe.cpp:(.text+0x15): undefined reference to `clock_gettime'
collect2: error: ld returned 1 exit status
If instead I ask for 'n' optimization level, like the following:
g++ -I ~/miniconda3/envs/loos/include/ -On mwe.cpp -o mwe
The program builds without complaint and I get expected output:
$ ./mwe
1
1.41421
1.73205
2
2.23607
2.44949
1 2 3 4 5 6
I have no clue why this little program, or the real program I'm trying to write, would be trying to get a random seed for anything. Any advice would be appreciated. The reason why I would like to build without optimization is so that debugging is easier. I actually thought all this was being caused by debug flags, but I realized that my build tool's debug setting didn't ask for optimization and narrowed that down to the apparent cause. If I throw -g -O1 I do not see the error.
Obviously, if one were to comment out all the code that has to do with the Tensor module, that is everthing in main above 'return' and below the cwiseSqrt() line, and also the include statement, the code builds and produces expected output.
Technically, this is a linker error (g++ calls the compiler as well as the linker, depending on the command line arguments). And you get linker-errors if an externally defined function is called from somewhere, even if the code is never reached.
When compiling with optimizations enabled, g++ will optimize away uncalled functions (outside the global namespace), thus you get no linker errors. You may want to try -Og instead of -O1 for better debugging experience.
The following code should produce similar behavior:
int foo(); // externally defined
namespace { // anonymous namespace
// defined inside this module, but never called
int bar() {
return foo();
}
}
int main() {
// if you un-comment this line, the
// optimized version will fail as well:
// ::bar();
}
According to man clock_gettime you need to link with -lrt if your glibc version is older than 2.17 -- maybe that is the case for your setup:
g++ -I ~/miniconda3/envs/myenv/include/ mwe.cpp -o mwe -lrt

shared library with Undefined Behavior Sanitizer (clang++)

I have a problem while running an executable file with dlopen function used to open shared and sanitized library with a one simple function.
I use precompiled Clang 3.9.0 for Ubuntu 14.04.
My question is: Is it possible to run it properly, so I can look for undefined behavior errors in the library while running an executable ? If the answers is yes, then how ?
I have two files:
//simpledll.cpp
#include <cstdio>
int hehe(int argc) {
int k = 0x7fffffff;
k += argc;
return 0;
}
//dlopen.cpp
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main() {
void* handle;
handle = dlopen("simpledll.so", RTLD_LAZY);
if(!handle) {
fprintf(stderr, "%s\n", dlerror());
}
int (*function)(int) = reinterpret_cast<int (*)(int)> (dlsym(handle, "_Z4hehei"));
if (function == nullptr)
fprintf(stderr, "Nope\n");
else
function(1000); // this yields signed integer overflow
return 0;
}
I have tried to get it to work in two steps (both have failed)
Step I
Compile the executable with:
clang++ dlopen.cpp -ldl --std=c++11 -o dlopen
Compile the library with:
clang++ -fsanitize=undefined -shared -o simpledll.so -fPIC simpledll.cpp
Result:
./dlopen: symbol lookup error: simpledll.so: undefined symbol: __ubsan_handle_add_overflow
Step II (idea from this forum)
Compile the executable as in Step I,
Compile the library with:
clang++ -fsanitize=undefined -shared -Wl,--whole-archive -L/usr/local/lib/clang/3.9.0/lib/linux/ -lclang_rt.ubsan_standalone_cxx-x86_64 -Wl,--no-whole-archive -lclang_rt.ubsan_standalone-x86_64 -Wl,--no-whole-archive -o simpledll.so -fPIC simpledll.cpp
Result:
==11478==Sanitizer CHECK failed: /home/development/llvm/3.9.0/final/llvm.src/projects/compiler-rt/lib/ubsan/ubsan_init.cc:61 ((UBSAN_MODE_UNKNOWN)) != ((ubsan_mode)) (0, 0)
Note that in Step II, if we substitute the function in the shared library with the one that has no undefined behavior code, the program runs without a CHECK failed error. This indicates that UBSAN has found an undefined behavior code, however it was unable to report it properly.
Regards,
Jaszczur

"Duplicate symbol" when attempting to compile two .cpp files (from XCode) in terminal (MacOSX)

I have two .cpp files, main.cpp and secondFile.cpp:
#include <iostream>
int main()
{
std::cout << "Hello, World!\n" << std::endl;
std::cout << "I was also able to add this line!" << std::endl;
return 0;
}
And
#include <iostream>
int main()
{
std::cout << "This was from the second file!" << std::endl;
return 0;
}
I have successfully run g++ -o main.cpp main and g++ -o secondFile.cpp secondFile, as well as run each of their corresponding executables. However when I attempt to compile them simultaneously into a single executable g++ -o main.cpp secondFile.cpp bothScripts or clang++ main.cpp secondFile.cpp -o bothScripts I receive the following error:
"duplicate symbol _main in:
/var/folders/49/38grlkzs44zcth3v_dw9m9dm0000gn/T/main-d43536.o
/var/folders/49/38grlkzs44zcth3v_dw9m9dm0000gn/T/secondfile-2bee63.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)"
Clearly something is being loaded twice, but I am unsure whether this is a library (iostream), that I've named both sections 'main', or something else entirely. There are certainly questions similar to this already, but many are convoluted and not as fundamental for new C++ members (hence my question here).
Context: My rationale is to practice building executables from multiple .cpp files. Is there a better way to go about this? (New to C++ but not to programming/code as a whole.)
The reason for your error is simple. You have 2 main() functions. As you should know, in a C++ program, the function main() generally defines the entry point of a program. When each of the files are compiled together, and have their own main() function, the compiler gets confused and throws an error. To solve this, simply change the name of the main() function in one file, and call it from the other file, if you are planning to run them together.

Linking/compiling a program that uses boost/filesystem.hpp

I'm trying to use the boost/filesystem library in some code that I am writing. I seem to be having a hard time getting it to compile. I'm running Debian Wheezy, and have boost version 1.49(which is what comes if you install using apt-get). I'm trying to compile an example that is available with the documentation
#include <iostream>
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
int main(int argc, char* argv[])
{
if (argc < 2)
{
std::cout << "Usage: tut1 path\n";
return 1;
}
std::cout << argv[1] << " " << file_size(argv[1]) << '\n';
return 0;
}
I use the following command:
g++ temp.cc -o temp /usr/lib/libboost_filesystem.a
I get a number of errors such as:
/usr/lib/libboost_filesystem.a(operations.o): In function `boost::filesystem3::detail::dir_itr_close(void*&, void*&)':
(.text+0x4d): undefined reference to `boost::system::system_category()'
/usr/lib/libboost_filesystem.a(operations.o): In function `boost::filesystem3::detail::directory_iterator_increment(boost::filesystem3::directory_iterator&, boost::system::error_code*)':
(.text+0xe3): undefined reference to `boost::system::system_category()'
This is probably some linking error right? Any ideas on how I could solve it?
UPDATE #1:
I tried running it with the -lboost_filesyste and -L /usr/lib. It gives me the following error:
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
You are not linking the library properly. Also, as others mentioned, boost_filesystem needs also boost_system library. Use:
g++ temp.cc -o temp -lboost_system -lboost_filesystem
Command line param -l foo links libfoo.a library. If the static library is not in default library location, use command -L /custom/library/dir. But I believe /usr/lib is automatically taken into consideration by GCC.
Edit
According to your comment below it looks like you are not compiling the file with main() function, or you have a typo in main() name. Make sure that temp.cc contains one and only one of these functions:
int main();
int main(int argc, char** argv);
Of course you do remember that upper/lower case matters. :)
Boost.Filesystem uses things in Boost.System. You have to link against that, too.
The error messages that you are seeing:
/usr/lib/libboost_filesystem.a(operations.o): In function
`boost::filesystem3::detail::dir_itr_close(void*&, void*&)':
(.text+0x4d): undefined reference to `boost::system::system_category()'
that's a reference to Boost.System
Add -lboost_system and you should be good to go (or, at least better off).
Compile with -lboost_filesystem