LLVM/Clang use opt to show linked ll file - clang

I had two c files and want show IR for its linked bit code
link1.c
#include "link2.h"
int main() {
int a;
int b;
foo(a,b);
return 0;
}
link2.h
#include<stdio.h>
link2.c
#include "link2.h"
void foo(int a, int b) {
printf("%d\n", a);
printf("%d\n", b);
}
I did the following command to get bc file.
clang -o0 -emit-llvm file1.c -c -o file1.bc
clang -o0 -emit-llvm file2.c -c -o file2.bc
llvm-link -o link.bc link1.bc link2.bc
When I tried lli link.bc and llvm-dis link.bc it run correctly and showed linked ll file, but when I use opt link.bc -S -o link.ll to get ll file it just reported segmentation error. Can anyone let me know what to do with opt?

It seems like it is because version compatible issue of opt. I should use a 3.5 version but turns out I was using 3.4.2.

Related

PANIC: unprotected error in call to Lua API (undefined symbol: lua_gettop)

My environment is Lua-5.4.2 Luasocket-3.0-rc1.
When I run lua script directly, it work success.
When i run it through c language, it tell me error.
Error Msg is :
PANIC: unprotected error in call to Lua API (error running script: error loading module 'socket.core' from file '/usr/local/lib/lua/5.4/socket/core.so': undefined symbol: lua_gettop)
Aborted(core dumped)
Does anyone know why?
lua script code is:(test.lua)
#!/usr/local/bin/lua
local socket = require("socket")
print(socket._VERSION)
c code is:(main.c)
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
int main(void)
{
lua_State *L;
L = luaL_newstate();
luaopen_base(L);
luaL_openlibs(L);
printf("lua enter\n");
if (luaL_dofile(L, "test.lua"))
{
luaL_error(L, "error running script: %s", lua_tostring(L, -1));
}
printf("lua exit\n");
while(1) pause();
lua_close(L);
return 0;
}
tl;dr: Pass -Wl,-E to GCC.
I was able to reproduce your problem with this Dockerfile:
FROM gcc:11.1.0
RUN wget https://www.lua.org/ftp/lua-5.4.2.tar.gz \
&& git clone https://github.com/diegonehab/luasocket.git
RUN tar zxf lua-5.4.2.tar.gz \
&& cd lua-5.4.2 \
&& make linux \
&& make install \
&& cd ../luasocket \
&& git checkout 5b18e475f38fcf28429b1cc4b17baee3b9793a62 \
&& make linux LUAV=5.4 \
&& make install LUAV=5.4
COPY test.lua main.c ./
When I run lua test.lua in the resulting Docker container, it works fine. When I run gcc -o test main.c /usr/local/lib/liblua.a -ldl -lm -Wl,-rpath='/usr/local/lib/lua/5.4/socket' && ./test, I get the same panic that you get.
The reason that the standalone Lua binary works and yours doesn't is that the former is linked with -E:
MYLDFLAGS= $(LOCAL) -Wl,-E
ld's documentation for -E says this about it:
If you use dlopen to load a dynamic object which needs to refer back to the symbols defined by the program, rather than some other dynamic object, then you will probably need to use this option when linking the program itself.
Lua uses dlopen to load C modules that you require, and said modules need to call Lua functions, which are linked into your binary, so it makes sense that you need this option. And indeed, when I add -Wl,-E to the GCC command line, then it works fine for me:
root#077bbb831441:/# gcc -o test main.c /usr/local/lib/liblua.a -ldl -lm -Wl,-rpath='/usr/local/lib/lua/5.4/socket' -Wl,-E && ./test
lua enter
LuaSocket 3.0-rc1
lua exit

How to tranform clang .ast file to ir or bitcode file?

Apologize for my poor English.
[root#xxxx] ~
❯ clang -emit-ast aa.c
[root#xxxx] ~
❯ xxd aa.ast | head
00000000: 4350 4348 0108 0000 ce0a 0000 07c1 b3d0 CPCH............
00000010: 8cc2 2bb8 022d c8c2 2bb0 c22f 8802 2bbc ..+..-..+../..+.
00000020: c228 acc2 4312 b442 29d0 4228 9042 28d0 .(..C..B).B(.B(.
00000030: 4228 3c30 472b bc02 29d4 022b 94c2 2fb8 B(<0G+..)..+../.
I can get clang ast file with -emit-ast option
and I want to transform it to llvm ir.
But I cannot find any interface to solved it.
Anyone has suggests??
Clang AST files can be used in place of source files, so the following code works:
// main.cpp
#include <iostream>
int main() {
std::cout << "Hello, world!" << std::endl;
return 0;
}
> clang++ -emit-ast main.cpp -o a.ast
> clang++ a.ast -o a.out
> ./a.out
Hello, world!
Answering your question:
> clang -emit-llvm -c aa.ast

Linking to statically compiled z3 needs additional libraries on Linux

I used CMake to compile a static version of (a fairly recent of) z3 using:
cmake -DBUILD_LIBZ3_SHARED=false -DCMAKE_INSTALL_PREFIX=/opt/z3-devel -G "Unix Makefiles" ../
Now when I statically link the library against a C++ program, say this small variation of a z3 example:
#include"z3++.h"
using namespace z3;
int main(int argc, char** argv) {
config conf;
context c(conf);
expr x = c.int_const("x");
expr y = c.int_const("y");
expr z = c.int_const("z");
goal g(c);
g.add( ((2*x)+y)+z == 4);
g.add( (x+(2*y))+z == 4);
g.add( x+y == 4);
std::cout << g << "\n";
tactic t(c, "fm");
apply_result r = t(g);
std::cout << r << "\n";
return 0;
}
via
g++ -c -I /opt/z3-devel/include -static -o main.o main.cc
g++ -static -L /opt/z3-devel/lib64 -o main main.o -lz3
I receive a long list of undefined reference linking errors. What solves the issue is to add -lgomp -pthread -lrt -ldl as additional libraries. The linker outputs the following warning:
/usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/8/libgomp.a(target.o): in function `gomp_target_init':
(.text+0x32c): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
Nevertheless, the program runs fine on my own machine and on Starexec.
Is this combination of static and dynamic linking the best I can do? Shouldn't those libraries be already statically linked into libz3.a? I have static versions of gomp, pthread and rt available on the system.

llvm-link error when using memcpy in C code and compiling with wasm target

I am trying to compile two *.c files to LLVM bitcode via clang, link them together using llvm-link, and make a single *.wasm file out of it. I built LLVM on my machine via the Makefile provided by https://github.com/yurydelendik/wasmception
This works fine until I use memcpy in the C code. Then llvm-link stops with error:
Intrinsic has incorrect argument type!
void (i8*, i8*, i32, i1)* #llvm.memcpy.p0i8.p0i8.i32
The following is a minimal example to reproduce the issue:
one.c
#define EXPORT __attribute__((visibility("default")))
#include <string.h>
char* some_str();
EXPORT void do_something() {
char* cpy_src = some_str();
char other_str[15];
memcpy(other_str, cpy_src, strlen(cpy_src));
}
two.c
char* some_str() {
return "Hello World";
}
Execute the following commands:
$ clang --target=wasm32-unknown-unknown-wasm --sysroot=../wasmception/sysroot -S -emit-llvm -nostartfiles -fvisibility=hidden one.c -o one.bc
[...]
$ clang --target=wasm32-unknown-unknown-wasm --sysroot=../wasmception/sysroot -S -emit-llvm -nostartfiles -fvisibility=hidden two.c -o two.bc
[...]
Note that no optimization is done because that would eliminate the unnecessary memcpy call here. As I said, this is a minimal example out of context to show the error.
$ llvm-link one.bc two.bc -o res.bc -v
Loading 'one.bc'
Linking in 'one.bc'
Loading 'two.bc'
Linking in 'two.bc'
Intrinsic has incorrect argument type!
void (i8*, i8*, i32, i1)* #llvm.memcpy.p0i8.p0i8.i32
llvm-link: error: linked module is broken!
When I comment out the memcpy call in the example file, the error is gone. Of course this is not an option in the real project I am working at.
Am I doing something wrong? Is it a bad idea in general to use memcpy in a WebAssembly context? Can this be a bug in LLVM/Clang?
Reading through these github issues, it seems the memcpy intrinsic is not currently supported by the WASM backend:
https://github.com/WebAssembly/design/issues/236
https://github.com/WebAssembly/design/issues/1003
As a workaround, you could instruct clang to disable intrinsic expansion using -fno-builtin, so that the generated code will call the actual memcpy function.

Is it possible code coverage of a shared library using gcov?

I try to test an executable which uses OpenCV shared library. When using gcov to know what code lines were covered I only get info about my .cpp files and .hpp of the library. No info is shown about .cpp files of the library.
I compiled and linked with -pg --coverage flags.
Yes, gcov can give coverage information about a shared library. If I remember correctly from the problems I had getting this to work on my project, you're probably not including the --coverage flag on the linking of the dynamic library. Here's the smallest example I could create.
Makefile:
CXXFLAGS += --coverage
LDFLAGS += --coverage
myexec: myexec.cpp libmylib.so
libmylib.so: mylib.o
gcc --coverage -shared -Wl,-soname,libmylib.so -o libmylib.so mylib.o
mylib.o: CXXFLAGS += -fPIC
myexec.cpp:
#include "mylib.h"
int main(int argc, char** argv)
{
return is_even(argc);
}
mylib.h
#ifndef MYLIB_H
#define MYLIB_H
int is_even(int num);
#endif
mylib.cpp
#include "mylib.h"
int is_even(int num)
{
if (num % 2)
return false;
else
return true;
}
Output of make (so you can see exactly what the build was):
g++ --coverage -fPIC -c -o mylib.o mylib.cpp
gcc --coverage -shared -Wl,-soname,libmylib.so -o libmylib.so mylib.o
g++ --coverage --coverage myexec.cpp libmylib.so -o myexec
I ran the executable using LD_LIBRARY_PATH="." ./myexec a, and then ran gcov mylib.cpp. Here's the contents of mylib.cpp.gcov:
-: 0:Source:mylib.cpp
-: 0:Graph:mylib.gcno
-: 0:Data:mylib.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include "mylib.h"
-: 2:
1: 3:int is_even(int num)
-: 4:{
1: 5: if (num % 2)
#####: 6: return false;
-: 7: else
1: 8: return true;
-: 9:}

Resources