I'm trying to read and call a function parsed from LLVM bitcode in LLVM 2.8. I have everything working apart from the actual call, which crashes the program.
First I have this C code:
void hello() {}
I've compiled this with:
llvm-gcc -c -emit-llvm hello.c -o hello.bc
Here's a trimmed down version of the code that's supposed to read it:
using namespace std;
using namespace llvm;
void callFunction(string file, string function) {
InitializeNativeTarget();
LLVMContext context;
string error;
MemoryBuffer* buff = MemoryBuffer::getFile(file);
Module* m = getLazyBitcodeModule(buff, context, &error);
// Check the module parsed here.
// ...
ExecutionEngine* engine = ExecutionEngine::create(m);
// Check the engine started up correctly here.
// ...
Function* func = m->getFunction(function);
// Check the function was found here.
// ..
vector<GenericValue> args(0);
// This is what crashes.
engine->runFunction(func, args);
}
I've included plenty of LLVM headers, including ExecutionEngine/JIT.h, and the code checks at each step to make sure values aren't NULL. It parses the bitcode, and I have examined the function it finds to confirm it was as expected.
I've also tried building a module and function myself, which works as expected, so the problem definitely arises from the fact that the function is produced by the bitcode.
I've managed to get this running as expected. I was curious if the problem lay in the above process, but this is obviously not the case. The system I was running this as a part of was causing the crash, and the code above does work on its own.
Related
I am no longer able to build my C++ project after coming back to it after a while (I've since updated macOS and Xcode), either from Xcode or by calling clang on the command line. I am getting an error on every use of std::shared_ptr::make_shared in my code. I want to emphasize this used to compile and run fine and I don't understand what has changed. Perhaps updating xcode broke my toolchain somehow.
I have reproduced the problem in some very trivial code that I believe should compile fine:
#include <string>
#include <memory>
class test_c {
private:
std::string str_;
public:
test_c(std::string str__) : str_(str__) { }
};
std::string test_s = "test";
auto test = std::shared_ptr<test_c>::make_shared(test_s);
The errors look like this:
$ clang -std=c++14 test.cpp
test.cpp:10:38: error: no member named 'make_shared' in 'std::__1::shared_ptr<test_c>'
auto test = std::shared_ptr<test_c>::make_shared(test_s);
~~~~~~~~~~~~~~~~~~~~~~~~~^
1 error generated.
I can't find any way to call make_shared as a static method at all. Also checked your code in other in older versions of Clang. Doesn't seem that it can work...
Maybe just:
auto test = std::make_shared<test_c>(test_s);
UPD
Wait. Indeed it worked in in clang of version 9. Looks it really was updated to disable this feature...
Not working in v10.
I'm trying to port the lhslib library (written in C++) to WebAssembly using emscripten (emcc v. 1.40.1, clang v. 12.0.0, macOS 10.15.5). Unfortunately I have a very limited understanding of C++, so please bear with me.
So far, I forked the repo, created a build folder, and from there started to try and convert the randomLHS.cpp file to WASM:
// a short overview of what the file looks like
#include "LHSCommonDefines.h"
#include "utilityLHS.h"
namespace lhslib
{
void randomLHS(int n, int k, bclib::matrix<int> & result, bclib::CRandom<double> & oRandom)
{
// further contents of the file
}
}
Running
emcc ../src/lhslib/randomLHS.cpp -I../src/bclib -o randomLHS.html
creates the expected files randomLHS.wasm ,randomLHS.js, and randomLHS.html.
However, when serving the html file and inspecting the Module object created by emscripten, it does not contain the desired randomLHS function.
I then read about the EXPORTED_FUNCTIONS option and proceeded to try the following
emcc ../src/lhslib/randomLHS.cpp -I../src/bclib -o randomLHS.html -s EXPORTED_FUNCTIONS='["_randomLHS"]' -s EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]'
This results in the following error:
emcc: error: undefined exported function: "_randomLHS" [-Wundefined] [-Werror]
Unfortunately I couldn't find any examples showcasing how to export a namespace (as in the randomLHS file), or how to specify a function from the namespace that should be exported.
Could you guide me on how I could achieve this?
Thanks for you help!
So according to the emscripten docs on using ccall and cwrap:
These methods can be used with compiled C functions — name-mangled C++ functions won’t work.
I believe there are other ways to do this; check out WebIDL Binder and Embind.
One of Objective C's primary features is simple introspection. A typical use of this functionality is the ability to check some method (function), to make sure it indeed exists, before calling it.
Whereas the following code will throw an error at runtime (although it compiles just fine (Apple LLVM version 7.0.2 (clang-700.1.81)))...
#import Foundation;
#interface Maybe : NSObject + (void) maybeNot; #end
#implementation Maybe #end
int main (){ [Maybe maybeNot]; }
By adding one simple condition before the call...
if ([Maybe respondsToSelector:#selector(maybeNot)])
We can wait till runtime to decide whether or not to call the method.
Is there any way to do this with "standard" C (c11) or C++ (std=c14)?
i.e....
extern void callMeIfYouDare();
int main() { /* if (...) */ callMeIfYouDare(); }
I guess I should also mention that I am testing/using this is in a Darwin runtime environment.
On GNU gcc / Mingw32 / Cygwin you can use Weak symbol:
#include <stdio.h>
extern void __attribute__((weak)) callMeIfYouDare();
void (*callMePtr)() = &callMeIfYouDare;
int main() {
if (callMePtr) {
printf("Calling...\n");
callMePtr();
} else {
printf("callMeIfYouDare() unresolved\n");
}
}
Compile and run:
$ g++ test_undef.cpp -o test_undef.exe
$ ./test_undef.exe
callMeIfYouDare() unresolved
If you link it with library that defines callMeIfYouDare though it will call it. Note that going via the pointer is necessary in Mingw32/Cygwin at least. Placing a direct call callMeIfYouDare() will result in a truncated relocation by default which unless you want to play with linker scripts is unavoidable.
Using Visual Studio, you might be able to get __declspec(selectany) to do the same trick: GCC style weak linking in Visual Studio?
Update #1: For XCode you can use __attribute__((weak_import)) instead according to: Frameworks and Weak Linking
Update #2: For XCode based on "Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)" I managed to resolve the issue by compiling with the following command:
g++ test_undef.cpp -undefined dynamic_lookup -o test_undef
and leaving __attribute__((weak)) as it is for the other platforms.
If you can see a function of an object (not pointer) is called in a source code and the code is compiled successfully - then the function does exist and no checking needed.
If a function being called via a pointer then you assume your pointer is of type of the class that has that function. To check whether it's so or not you use casting:
auto* p = dynamic_cast<YourClass*>(somepointer);
if (p != nullptr)
p->execute();
C++ or C don't have introspection. You could add some with your additional layer (look at Qt metaobject, or GTK GObject introspection for examples); you might consider customizing GCC with MELT to get some introspection... (but that would take weeks). You could have some additional script or tool which emits C or C++ code related to your introspection needs (SWIG could be inspirational).
In your particular case, you might want to use weak symbols (at least on Linux). Perhaps use the relevant function attribute so code.
extern void perhapshere(void) __attribute__((weak));
if (perhapshere)
perhapshere();
and you might even make that shorter with some macro.
Maybe you just want to load some plugin with dlopen(3) and use dlsym(3) to find symbols in it (or even in the whole program which you would link with -rdynamic, by giving the NULL path to dlopen and using dlsym on the obtained handle); be aware that C++ uses name mangling.
So you might try
void*mainhdl = dlopen(NULL, RTLD_NOW);
if (!mainhdl) { fprintf(stderr, "dlopen failed %s\n", dlerror());
exit(EXIT_FAILURE); };
then later:
typedef void voidvoidsig_t (void); // the signature of perhapshere
void* ad = dlsym(mainhdl, "perhapshere");
if (ad != NULL) {
voidvoidsig_t* funptr = (voidvoidsig_t*)ad;
(*funptr)();
}
I want to use Clang and LibTooling to create some C++ source analysis and transformation tools. I've built Clang and LibTooling following this tutorial, and I've been able to run and create some analysis tools and compile C++ programs using the Clang binary I built. However, if I include headers from the standard library (in either source files or my tools), I run into issues when compiling or running the source files/tools. For instance, if I run clang-check on the following C++ source file:
#include <iostream>
int main() {
std::cout << "Hello";
return 0;
}
I get "fatal error: 'iostream' file not found". (Note: I can compile C++ programs, e.g. ones with user-defined classes, just not C++ programs using the standard library.) In an attempt to resolve the issue, I built libc++ (following this guide, building it in the llvm/project directory where I built LLVM and Clang), but I'm still having trouble getting Clang and the tools to use libc++. Now, if I try to compile a test file using:
export CPLUS_INCLUDE_PATH="~/clang-llvm/llvm/projects/libcxx/include"
export LD_LIBRARY_PATH="~/clang-llvm/llvm/projects/libcxx/lib"
~/clang-llvm/llvm/build/bin/clang++ ~/Documents/main.cpp
Then I get "fatal error: 'unistd.h' file not found". So my question is this: how do I properly point Clang and my tools to use libc++?
I am running OS X Yosemite 10.10 and using Clang 3.6.0.
Clang comes with some custom includes. So usually you have clang in
/usr/bin/clang++
and the includes in
/usr/lib/clang/3.6.1/include
but clang looks for them as a relative path:
../lib/clang/3.6.1/include
so make sure this relative path is accessible from either the clang++ binary, or your libtooling application.
Include your tool into this:
#include "clang/Tooling/CommonOptionsParser.h" // For reading compiler switches from the command line
#include "clang/Tooling/Tooling.h"
static cl::OptionCategory MyToolCategory("SearchGlobalSymbols");
static cl::extrahelp MoreHelp("\nMore help text..."); // Text that will be appended to the help text. You can leave out this line.
/* Your code (definition of your custom RecursiveASTVisitor and ASTConsumer) */
/* Define class MyASTFrontendAction here, derived from ASTFrontendAction */
int main(int argc, const char **argv)
{
/* Your code */
CommonOptionsParser op(argc, argv, MyToolCategory); // Parse the command-line arguments
ClangTool Tool(op.getCompilations(), op.getSourcePathList()); // Create a new Clang Tool instance (a LibTooling environment)
return Tool.run(newFrontendActionFactory<MyASTFrontendAction>().get()); // Run custom Frontendaction
}
The CommonOptionsParser allows you to read commands from the command line that are passed to the compiler.
For example, you can now call your tool like this:
your-tool yoursourcefile.c -- -nostdinc -I"path/to/your/standardlibrary"
Everything after the double dash will be passed to the compiler. Possible flags are described here:
http://clang.llvm.org/docs/CommandGuide/clang.html
-nostdinc tells the Preprocessor not to look for standard include paths. You can specify you own paths instead after -I.
Hope it helped someone :) Ask me if I wasn't specific enough.
Did you move/rename any of the parent directories after building/installing? The compiler should have been configured to know where to look for its standard libraries without having to specify the environment variable paths.
Use homebrew and install llvm using the command
brew install llvm
Your problem should be solved.
Hey everyguys I've been taking a look at boost signals recently because I'd like to switch over to it from my own custom code for handling signal notification. I ran into a problem compiling the first example from here: http://www.boost.org/doc/libs/1_53_0/doc/html/signals2/tutorial.html, here is the example source code:
struct HelloWorld
{
void operator()() const
{
std::cout << "Hello, World!" << std::endl;
}
};
// Signal with no arguments and a void return value
boost::signals2::signal<void ()> sig;
// Connect a HelloWorld slot
HelloWorld hello;
sig.connect(hello);
// Call all of the slots
sig();
The problem that arose from attempting to compile this with: clang++ -std=c++11 signals2example.cpp is this error here:
error: no matching function for call to 'get'
func(std::get<indices>(args)...);
To narrow down the problem I commented out all the lines until I figured out which one caused it, it was the line that simply says "sig();" and the problem seems to be related to the std::get function which is for tuples or something. There are not many helpful posts online with regards to boost::signal2 and clang++ clashing. I should also note that g++ compiles this document with no complaints at all.
When you are compiling with Clang and you use the STL, the system STL (usually libstdc++) is used. It can be an old version (Do you use OSX?).
Clang has perfect support for C++11 with libc++, try adding -stdlib=libc++ to the command line.
You may also try to run both gcc and clang with -v and check the include paths to see which stdlib is used in each case.