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

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

Related

Pktgen failed to load Lua script - User State for CLI not set for Lua

Running Pktgen with Lua scripts generates a failure User State for CLI not set for Lua.
The command I'm running is:
sudo -E ./usr/local/bin/pktgen --no-telemetry -l 4,6,8,10 -n 4 -a 0000:03:02.0 -m 1024 -- -T -P -m [6:8].0 -f test/hello-world.lua
Which gives the following result:
I have set the environment variables RTE_SDK=/root/Program/dpdk and
RTE_TARGET=x86_64-native-linux-gcc.
The failure comes from cli.c (link to code):
/**
* Load and execute a command file or Lua script file.
*
*/
int
cli_execute_cmdfile(const char *filename)
{
if (filename == NULL)
return 0;
gb_reset_buf(this_cli->gb);
if (strstr(filename, ".lua") || strstr(filename, ".LUA") ) {
if (!this_cli->user_state) {
cli_printf(">>> User State for CLI not set for Lua\n");
return -1;
}
if (lua_dofile) {
/* Execute the Lua script file. */
if (lua_dofile(this_cli->user_state, filename) != 0)
return -1;
} else
cli_printf(">>> Lua is not enabled in configuration!\n");
} else {
FILE *fd;
char buff[256];
fd = fopen(filename, "r");
if (fd == NULL)
return -1;
/* Read and feed the lines to the cmdline parser. */
while (fgets(buff, sizeof(buff), fd))
cli_input(buff, strlen(buff));
fclose(fd);
}
return 0;
}
So it would seem this_cli->user_state is not set, but how do you set it?
I have looked through the documentation for CLI, but it doesn't mention setting any user state from what I can see.
Update:
After having installed Lua and cmake, I ran meson -Denable_lua=true build which worked fine. But when I run ninja -C build I receive this error:
user_state is set in pktgen-main.c, but within a #ifdef LUA_ENABLED section.
Looking at meson_options.txt, which is at the base directory of a pktgen extraction, it contains:
option('enable_lua', type: 'boolean', value: false, description: 'Enable Lua support')
That means that you must enable Lua support when building (after installing dependencies, as shown below):
meson -Denable_lua=true build
This is going to require a few more dependencies, so you may have to install them, e.g. in Ubuntu:
sudo apt-get install cmake
And then installing Lua - I had to install it from source as per the instructions, because installing it with Ubuntu's package manager apt didn't give me the library that was needed:
curl -R -O http://www.lua.org/ftp/lua-5.4.4.tar.gz
tar zxf lua-5.4.4.tar.gz
cd lua-5.4.4
make all test
sudo make install

Building and linking lua from source via makefile

I've tried to compile and link lua with my application. This is my makefile:
app.o: app.cpp
g++ -c app.cpp
PATH_LUA=../lua-5.4.3/src
LUA= \
$(PATH_LUA)/lapi.c \
$(PATH_LUA)/lauxlib.c \
$(PATH_LUA)/lbaselib.c \
$(PATH_LUA)/lcode.c \
$(PATH_LUA)/lcorolib.c \
$(PATH_LUA)/lctype.c \
$(PATH_LUA)/ldblib.c \
$(PATH_LUA)/ldebug.c \
$(PATH_LUA)/ldo.c \
$(PATH_LUA)/ldump.c \
$(PATH_LUA)/lfunc.c \
$(PATH_LUA)/lgc.c \
$(PATH_LUA)/linit.c \
$(PATH_LUA)/liolib.c \
$(PATH_LUA)/llex.c \
$(PATH_LUA)/lmathlib.c \
$(PATH_LUA)/lmem.c \
$(PATH_LUA)/loadlib.c \
$(PATH_LUA)/lobject.c \
$(PATH_LUA)/lopcodes.c \
$(PATH_LUA)/loslib.c \
$(PATH_LUA)/lparser.c \
$(PATH_LUA)/lstate.c \
$(PATH_LUA)/lstring.c \
$(PATH_LUA)/lstrlib.c \
$(PATH_LUA)/ltable.c \
$(PATH_LUA)/ltablib.c \
$(PATH_LUA)/ltm.c \
$(PATH_LUA)/lundump.c \
$(PATH_LUA)/lutf8lib.c \
$(PATH_LUA)/lvm.c \
$(PATH_LUA)/lzio.c
libLua.so:
g++ -shared $(LUA) -fPIC -o lua/libLua.so
all: libLua.so app.o
g++ -o app app.o -I$(PATH_LUA) -lLua -Llua -ldl
The compilation works fine, but something is wrong with the linkage, because I get tons of undefined references to "lua_XYZ-function". The undefined reference to lua_tointegerx for example makes no sense, since its implementation is located in lapi.c which is in the file-list above.
(INB4: "This is a duplicate question!" … I've tried my best to check them all.)
What am I missing?
You are putting the libLua.so (by the way, personally I think it's a really bad idea to name your library the same name as the standard library, just uppercase... there's no way that can't bite you or someone in the rear at some point) in the lua subdirectory but you don't tell the linker where to find it.
Then, you list liblua.a as the prerequisite, but you have no actual rule to build liblua.a, which means make will come up with one based on its internal rules... whatever rule it uses will certainly not include all your source files (how could it know?).
If you show us the actual output of running make (before all the error messages) it should be pretty clear this has gone wrong from the beginning.
Speaking from a strictly makefile perspective, it's virtually always wrong to have the name of the file your recipe builds be different than the name of the target in the makefile.
You have to compile lua as c++-code explicitly.
You do this by including
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
instead of
#include <lua.hpp> which includes that extern "C" {...} statement.

pcap "undefined reference to" error

I'm trying to read in data from pcap files using pcap_open_offline(). I've used #include <pcap/pcap.h> and compiled with no errors after some debugging. Now I've come across another problem I can't seem to figure out. I wrote the following function:
void openPcap(char* filename){
printf("Opening file %s\n", filename);
pcap_t *pcap;
const unsigned char *packet;
char errbuf[PCAP_ERRBUF_SIZE];
struct pcap_pkthdr header;
pcap = pcap_open_offline(filename, errbuf);
if (pcap == NULL){
fprintf(stderr, "%s Malformed packet records in file %s",ER,filename);
}
}
And my pcap_open_offline call gives me about 100 of these errors when I try to compile:
pcap-linux.c:(.text+0xcd4): undefined reference to 'nl_handle_alloc'
pcap-linux.c:(.text+0xce8): undefined reference to 'genl_connect'
pcap-linux.c:(.text+0xcf6): undefined reference to 'genl_ctrl_alloc_cache'
pcap-linux.c:(.text+0xd0e): undefined reference to 'genl_ctrl_search_by_name'
pcap-linux.c:(.text+0xd64): undefined reference to 'nl_handle_destroy'
pcap-linux.c:(.text+0xdd7): undefined reference to 'nl_cache_free'
This is what my makefile looks like:
# -------------------------------
C=/afs/nd.edu/user14/csesoft/new/bin/gcc
CFLAGS=-Wall -std=c11 -I/afs/nd.edu/coursesp.18/cse/cse30341.01/support/gcc-libpcap/include -D_BSD_SOURCE
LD=/afs/nd.edu/user14/csesoft/new/bin/g++
#LD=g++
LDFLAGS=-lpthread
# # ----------------------------
LDFLAGS += -L/afs/nd.edu/coursesp.18/cse/cse30341.01/support/gcc-libpcap/lib -lpcap # Add your own flags here, or leave blank
threadedRE: threadedRE.o
$(LD) $^ $(LDFLAGS) -o $#
threadedRE.o: threadedRE.c
$(C) $(CFLAGS) -c $<
# C compiler
%.o: %.c
$(C) $(CFLAGS) -c $<
.PHONY: clean
clean:
rm -f threadedRE *.o
And my headers are:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <sys/stat.h>
#include <pcap/pcap.h>
Any suggestions would be greatly appreciated.
It isn't a compiling error, but a linking one. At the end of build process you should see something like "ld exited with error".
pcap_open_offline() seems to use nl_handle_alloc() and other functions, but linker can't find object files containing their implementation. Pointing linker to proper library which contains required object files by adding -lnl to LDFLAGS should do the trick.

C/XCode: sh: ./child: No such file or directory. Command runs in terminal but not XCode

So I have a child.c file and I want to compile and run it in my main.c file using the system() function of stdlib.h.
child.c:
#include<stdio.h>
int main(){
printf("I am the child\n");
return 0;
}
main.c:
#include <stdio.h>
#include <stdlib.h>
int main() {
system("cd ~/Desktop/HW3/HW3");
system("gcc -o child child.c");
system("./child");
return 0;
}
everything worked fine when I compile and run main.c in terminal using the following command
abcs-mbp:HW3 abc$ cd
abcs-mbp:~ abc$ cd ~/Desktop/HW3/HW3
abcs-mbp:HW3 abc$ gcc -o main main.c
abcs-mbp:HW3 abc$ ./main
and it ran child.c and printed the following:
I am the child
but when I tried to run the exact same main.c in XCode, XCode gave me the following error:
clang: error: no such file or directory: 'child.c'
clang: error: no input files
sh: ./child: No such file or directory
anybody know why this is happening? I think it has something to do with path, but how can I tell XCode the path of child.c and then tell it to compile child.c?
I also tried
system("cd ~/Desktop/HW3/HW3");
system("gcc -o child child.c");
system("./child");
and
system("/Users/vqianxiao/Desktop/HW3/HW3/ gcc -o child child.c");
but nothing seems to work... any help is appreciated!
the reason that it does not work is a combination of things
1) each 'system' call is run in a separate shell instance,
so the second 'system' call
starts from the directory where the main program is running.
2) things do down from there
a suggested fix:
system("cd ~/Desktop/HW3/HW3; && gcc -o child child.c; && ./child;");
notice, all one system call, terminators at end of commands, and linked by && so one command must be successful to continue on to the next command

LLVM cannot find clang binary

I have just built and installed LLVM Clang 3.5.0 with compiler-rt. clang binary seems to work, but cannot build a simple test program:
$ cat hello.c
#include <stdio.h>
int main(int argc, char **argv) {
printf("Hello World\n");
return 0;
}
Building it borks with error: unable to execute command: Executable "" doesn't exist!
$ clang hello.c -o hello
error: unable to execute command: Executable "" doesn't exist!
Executable "" ? Interesting...
Debugging it further reveals that clang tries to call itself to build .o object file and then ld to link it, but does not know where itself exists apparently.
$ clang -### hello.c -o hello
clang version 3.5.0 (tags/RELEASE_350/final)
Target: x86_64-alpine-linux-musl
Thread model: posix
"" "-cc1" "-triple" "x86_64-alpine-linux-musl" "-emit-obj" "-mrelax-all" "-disable-free" "-main-file-name" "hello.c" "-mrelocation-model" "static" "-mdisable-fp-elim" "-fmath-errno" "-masm-verbose" "-mconstructor-aliases" "-munwind-tables" "-fuse-init-array" "-target-cpu" "x86-64" "-target-linker-version" "2.24" "-dwarf-column-info" "-resource-dir" "../lib/clang/3.5.0" "-internal-isystem" "/usr/local/include" "-internal-isystem" "../lib/clang/3.5.0/include" "-internal-externc-isystem" "/include" "-internal-externc-isystem" "/usr/include" "-fdebug-compilation-dir" "/" "-ferror-limit" "19" "-fmessage-length" "158" "-mstackrealign" "-fobjc-runtime=gcc" "-fdiagnostics-show-option" "-o" "/tmp/hello-37746e.o" "-x" "c" "hello.c"
"/usr/bin/ld" "-z" "relro" "--eh-frame-hdr" "-m" "elf_x86_64" "-dynamic-linker" "/lib/ld-musl-x86_64.so.1" "-o" "hello" "/usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.8.3/../../../crt1.o" "/usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.8.3/../../../crti.o" "/usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.8.3/crtbegin.o" "-L/usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.8.3" "-L/usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.8.3/../../../../x86_64-alpine-linux-musl/lib" "-L/usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.8.3/../../.." "-L/../lib" "-L/lib" "-L/usr/lib" "/tmp/hello-37746e.o" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "/usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.8.3/crtend.o" "/usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.8.3/../../../crtn.o"
When I run the first line putting /usr/bin/clang as the first item, it builds just fine:
$ /usr/bin/clang "-cc1" "-triple" "x86_64-alpine-linux-musl" "-emit-obj" "-mrelax-all" "-disable-free" "-main-file-name" "hello.c" "-mrelocation-model" "static" "-mdisable-fp-elim" "-fmath-errno" "-masm-verbose" "-mconstructor-aliases" "-munwind-tables" "-target-cpu" "x86-64" "-target-linker-version" "2.24" "-dwarf-column-info" "-resource-dir" "../lib/clang/3.5.0" "-internal-isystem" "/usr/local/include" "-internal-isystem" "../lib/clang/3.5.0/include" "-internal-externc-isystem" "/include" "-internal-externc-isystem" "/usr/include" "-fdebug-compilation-dir" "/" "-ferror-limit" "19" "-fmessage-length" "158" "-mstackrealign" "-fobjc-runtime=gcc" "-fdiagnostics-show-option" "-o" "/tmp/hello-4f64bb.o" "-x" "c" "hello.c"
$
And following /usr/bin/ld is able to link it just fine resulting in:
$ ./hello
Hello World
Anny suggestions what did I screw during configure/build?
clang source analysis shows that 'clang' program on Linux uses /proc/self/exe to find out real path of its binary. I am running in chroot without /proc mounted, thus it failed.
mount -t proc proc /proc
solves the issue

Resources